Browse Source

Refactor telemetry solution info handling.

pull/23059/head
Emre KARA 1 year ago
parent
commit
cfcda6c617
  1. 3
      abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json
  2. 9
      framework/src/Volo.Abp.Core/Volo/Abp/AbpApplicationWithExternalServiceProvider.cs
  3. 218
      framework/src/Volo.Abp.Core/Volo/Abp/Telemetry/Activity/ActivityDataProvider.cs
  4. 32
      framework/src/Volo.Abp.Core/Volo/Abp/Telemetry/Activity/ActivityPropertyName.cs
  5. 28
      framework/src/Volo.Abp.Core/Volo/Abp/Telemetry/Activity/ActivityStorage.cs
  6. 15
      framework/src/Volo.Abp.Core/Volo/Abp/Telemetry/Activity/IActivityStorage.cs
  7. 12
      framework/src/Volo.Abp.Core/Volo/Abp/Telemetry/Activity/ISolutionInfoProvider.cs
  8. 244
      framework/src/Volo.Abp.Core/Volo/Abp/Telemetry/Activity/SolutionInfoProvider.cs
  9. 1
      framework/src/Volo.Abp.Core/Volo/Abp/Telemetry/ITelemetryService.cs
  10. 12
      framework/src/Volo.Abp.Core/Volo/Abp/Telemetry/TelemetryService.cs

3
abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json

@ -717,6 +717,7 @@
"IncludePrereleaseInfo": "Gets or sets whether to include prerelease versions in the cache",
"CacheVersionCount": "Cache Version Count",
"CacheVersionCountInfo": "Gets or sets the number of versions to cache",
"CacheLatestVersionsInfo": "This caches the latest versions of the NuGet packages"
"CacheLatestVersionsInfo": "This caches the latest versions of the NuGet packages",
"Menu:TelemetryReports" : "Telemetry Reports"
}
}

9
framework/src/Volo.Abp.Core/Volo/Abp/AbpApplicationWithExternalServiceProvider.cs

@ -88,11 +88,10 @@ internal class AbpApplicationWithExternalServiceProvider : AbpApplicationBase, I
await using var _ = telemetryService.TrackActivity(ActivityNameConsts.ApplicationRun, activity =>
{
activity.Add(ActivityPropertyName.Assembly, assembly.Location);
activity.Add(ActivityPropertyName.ProjectId, packageMetadata.ProjectId!);
activity.Add(ActivityPropertyName.ProjectType, packageMetadata.Role!);
activity.Add(ActivityPropertyName.SolutionPath,
packageMetadata.AbpSlnPath ?? string.Empty);
activity[ActivityPropertyName.Assembly] = assembly.Location;
activity[ActivityPropertyName.ProjectId] = packageMetadata.ProjectId!;
activity[ActivityPropertyName.ProjectType] = packageMetadata.Role!;
activity[ActivityPropertyName.SolutionPath] = packageMetadata.AbpSlnPath!;
});
}

218
framework/src/Volo.Abp.Core/Volo/Abp/Telemetry/Activity/ActivityDataProvider.cs

@ -1,18 +1,10 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text.Json;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Telemetry.EnvironmentInspection;
using Volo.Abp.Telemetry.EnvironmentInspection.Contracts;
using Volo.Abp.Telemetry.Shared;
using Volo.Abp.Telemetry.Shared.Enums;
using DatabaseProvider = Volo.Abp.Telemetry.Shared.Enums.DatabaseProvider;
using MobileApp = Volo.Abp.Telemetry.Shared.Enums.MobileApp;
namespace Volo.Abp.Telemetry.Activity;
@ -22,20 +14,22 @@ public class ActivityDataProvider : IActivityDataProvider, IScopedDependency
private readonly ISoftwareInfoProvider _softwareInfoProvider;
private readonly IEnumerable<ITelemetryApplicationInfoContributor> _applicationInfoContributors;
private readonly IActivityStorage _activityStorage;
private readonly ISolutionInfoProvider _solutionInfoProvider;
public ActivityDataProvider(
IDeviceInfoProvider deviceInfoProvider,
ISoftwareInfoProvider softwareInfoProvider,
IEnumerable<ITelemetryApplicationInfoContributor> applicationInfoContributors,
IActivityStorage activityStorage)
IActivityStorage activityStorage, ISolutionInfoProvider solutionInfoProvider)
{
_deviceInfoProvider = deviceInfoProvider;
_softwareInfoProvider = softwareInfoProvider;
_applicationInfoContributors = applicationInfoContributors;
_activityStorage = activityStorage;
_solutionInfoProvider = solutionInfoProvider;
}
public virtual SessionType GetSessionType()
protected virtual SessionType GetSessionType()
{
return SessionType.ApplicationRuntime;
}
@ -51,7 +45,7 @@ public class ActivityDataProvider : IActivityDataProvider, IScopedDependency
activity[ActivityPropertyName.IsFirstSession] = isFirstSession;
activity[ActivityPropertyName.DeviceId] = _deviceInfoProvider.GetDeviceId();
if (await ShouldAddDeviceInfoAsync())
if (await _activityStorage.ShouldAddDeviceInfoAsync())
{
await AddDeviceInformationAsync(activity);
}
@ -63,28 +57,26 @@ public class ActivityDataProvider : IActivityDataProvider, IScopedDependency
if (await ShouldAddSolutionInformation(activity))
{
await AddSolutionInformationAsync(activity);
var solutionInfo = await _solutionInfoProvider.GetSolutionInfoAsync(activity[ActivityPropertyName.SolutionPath].ToString()!);
foreach (var entry in solutionInfo)
{
activity[entry.Key] = entry.Value;
}
}
}
protected virtual async Task<bool> ShouldAddDeviceInfoAsync()
{
var lastSend = await _activityStorage.GetLastDeviceInfoSendTimeAsync();
return lastSend is null || DateTimeOffset.UtcNow - lastSend > TimeSpan.FromDays(7);
}
protected virtual async Task<bool> ShouldAddSolutionInformation(ActivityData activity)
{
if (
!activity.TryGetValue(ActivityPropertyName.SolutionId, out var id) ||
!Guid.TryParse(id.ToString(), out var solutionId))
!Guid.TryParse(id.ToString(), out var solutionId) && activity.ContainsKey(ActivityPropertyName.SolutionPath))
{
return false;
}
var lastSend = await _activityStorage.GetLastSolutionInfoSendTimeAsync(solutionId);
return lastSend is null || DateTimeOffset.UtcNow - lastSend > TimeSpan.FromDays(7);
return await _activityStorage.ShouldAddSolutionInformation(solutionId);
}
protected virtual async Task AddDeviceInformationAsync(ActivityData activityData)
@ -96,6 +88,8 @@ public class ActivityDataProvider : IActivityDataProvider, IScopedDependency
var softwareList = await _softwareInfoProvider.GetSoftwareInfoAsync();
activityData[ActivityPropertyName.InstalledSoftwares] = softwareList;
await _activityStorage.MarkDeviceInfoAsSentAsync();
}
protected virtual async Task AddApplicationInformationAsync(ActivityData activityData)
@ -106,26 +100,6 @@ public class ActivityDataProvider : IActivityDataProvider, IScopedDependency
}
}
protected virtual async Task AddSolutionInformationAsync(ActivityData activityData)
{
var solutionJson = File.ReadAllText(activityData[ActivityPropertyName.SolutionPath].ToString()!);
using var solutionDoc = JsonDocument.Parse(solutionJson);
var root = solutionDoc.RootElement;
if (root.TryGetProperty("creatingStudioConfiguration", out var config))
{
AddCreatingStudioConfiguration(activityData, config);
}
activityData[ActivityPropertyName.LicenseType] = await GetLicenseTypeAsync();
if (root.TryGetProperty("modules", out var modulesElement) && modulesElement.ValueKind == JsonValueKind.Object)
{
var modules = ExtractModules(modulesElement);
activityData[ActivityPropertyName.InstalledModules] = modules;
}
}
protected virtual void AddSolutionId(ActivityData activityData)
{
@ -139,165 +113,11 @@ public class ActivityDataProvider : IActivityDataProvider, IScopedDependency
return;
}
var solutionJson = File.ReadAllText((string)path);
using var solutionDoc = JsonDocument.Parse(solutionJson);
var root = solutionDoc.RootElement;
var solutionId = ReadSolutionIdFromJson(root);
activityData[ActivityPropertyName.SolutionId] = solutionId;
}
protected virtual Guid ReadSolutionIdFromJson(JsonElement root)
{
return root.TryGetProperty("id", out var idElement) && Guid.TryParse(idElement.GetString(), out var id)
? id
: throw new Exception("Solution ID is not valid.");
}
protected virtual void AddCreatingStudioConfiguration(ActivityData activityData, JsonElement config)
{
activityData[ActivityPropertyName.Template] = MapSolutionTemplate(config.GetProperty("template").GetString());
activityData[ActivityPropertyName.CreatedAbpStudioVersion] = config.GetProperty("createdAbpStudioVersion").GetString()!;
activityData[ActivityPropertyName.IsTiered] = config.GetProperty("Tiered").GetBoolean();
activityData[ActivityPropertyName.UiFramework] = MapUiFramework(config.GetProperty("uiFramework").GetString());
activityData[ActivityPropertyName.DatabaseProvider] = MapDatabaseProvider(config.GetProperty("databaseProvider").GetString());
activityData[ActivityPropertyName.DatabaseManagementSystem] = MapDbms(config.GetProperty("databaseManagementSystem").GetString());
activityData[ActivityPropertyName.IsSeparateTenantSchema] = config.GetProperty("separateTenantSchema").GetBoolean();
activityData[ActivityPropertyName.Theme] = MapUiTheme(config.GetProperty("theme").GetString());
activityData[ActivityPropertyName.ThemeStyle] = MapUiThemeStyle(config.GetProperty("themeStyle").GetString());
activityData[ActivityPropertyName.MobileFramework] = MapMobileApp(config.GetProperty("mobileFramework").GetString());
activityData[ActivityPropertyName.HasPublicWebsite] = config.GetProperty("publicWebsite").GetBoolean();
activityData[ActivityPropertyName.IncludeTests] = config.GetProperty("includeTests").GetBoolean();
activityData[ActivityPropertyName.MultiTenancy] = config.GetProperty("multiTenancy").GetBoolean();
activityData[ActivityPropertyName.DynamicLocalization] = config.GetProperty("dynamicLocalization").GetBoolean();
activityData[ActivityPropertyName.KubernetesConfiguration] = config.GetProperty("kubernetesConfiguration").GetBoolean();
activityData[ActivityPropertyName.GrafanaDashboard] = config.GetProperty("grafanaDashboard").GetBoolean();
activityData[ActivityPropertyName.SocialLogins] = config.GetProperty("socialLogin").GetBoolean();
}
protected virtual List<SolutionModuleInstallationInfo> ExtractModules(JsonElement modulesElement)
{
var modules = new List<SolutionModuleInstallationInfo>();
foreach (var module in modulesElement.EnumerateObject())
var solutionId = _solutionInfoProvider.GetSolutionId((string)path);
if (solutionId.HasValue)
{
var name = module.Name;
if (!module.Value.TryGetProperty("path", out var pathElement))
{
continue;
}
var path = pathElement.GetString();
if (path.IsNullOrEmpty() || !File.Exists(path))
{
continue;
}
var moduleJson = File.ReadAllText(path);
using var moduleDoc = JsonDocument.Parse(moduleJson);
if (!moduleDoc.RootElement.TryGetProperty("imports", out var imports) || imports.ValueKind != JsonValueKind.Object)
{
continue;
}
foreach (var import in imports.EnumerateObject())
{
var version = import.Value.GetProperty("version").GetString();
var creationTime = import.Value.TryGetProperty("creationTime", out var ct) ? DateTimeOffset.Parse(ct.GetString()!) : (DateTimeOffset?)null;
if (modules.Any(x => x.ModuleName == name && x.Version == version))
{
continue;
}
modules.Add(new SolutionModuleInstallationInfo { ModuleName = name, Version = version, InstallationTime = creationTime });
}
}
return modules;
}
protected virtual async Task<int> GetLicenseTypeAsync()
{
if (!File.Exists(AbpTelemetryPaths.AccessToken))
{
return 0;
activityData[ActivityPropertyName.SolutionId] = solutionId.Value;
}
using var httpClient = new HttpClient();
var accessToken = File.ReadAllText(AbpTelemetryPaths.AccessToken);
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
var json = await httpClient.GetStringAsync($"{AbpPlatformUrls.AbpIoUrl}api/license/api-key");
using var doc = JsonDocument.Parse(json);
return doc.RootElement.GetProperty("licenseType").GetInt32();
}
protected virtual UiTheme MapUiTheme(string? theme) => theme switch
{
"none" => UiTheme.None,
"basic" => UiTheme.Basic,
"leptonx" => UiTheme.LeptonX,
"leptonx-lite" => UiTheme.LeptonXLite,
_ => UiTheme.Unknown
};
protected virtual UiThemeStyle MapUiThemeStyle(string? style) => style switch
{
"dim" => UiThemeStyle.Dim,
"style" => UiThemeStyle.System,
"dark" => UiThemeStyle.Dark,
"light" => UiThemeStyle.Light,
_ => UiThemeStyle.Unknown
};
protected virtual SolutionTemplate MapSolutionTemplate(string? template) => template switch
{
"microservice" => SolutionTemplate.Microservice,
"app-nolayers" => SolutionTemplate.AppNoLayers,
"app" => SolutionTemplate.AppLayered,
_ => SolutionTemplate.Unknown
};
protected virtual UiFramework MapUiFramework(string? framework) => framework switch
{
"mvc" => UiFramework.MvcRazorPages,
"blazor" => UiFramework.BlazorWasm,
"angular" => UiFramework.Angular,
"blazor-server" => UiFramework.BlazorServer,
"blazor-webapp" => UiFramework.BlazorWebApp,
"maui-blazor" => UiFramework.BlazorMaUI,
"none" => UiFramework.None,
_ => UiFramework.Unknown
};
protected virtual DatabaseProvider MapDatabaseProvider(string? provider) => provider switch
{
"ef" => DatabaseProvider.EfCore,
"mongodb" => DatabaseProvider.MongoDb,
"none" => DatabaseProvider.None,
_ => DatabaseProvider.Unknown
};
protected virtual Dbms MapDbms(string? dbms) => dbms switch
{
"mysql" => Dbms.MySql,
"oracle" => Dbms.Oracle,
"oracle-devart" => Dbms.OracleDevart,
"postgresql" => Dbms.PostgreSql,
"sqlserver" => Dbms.SqlServer,
"sqlite" => Dbms.Sqlite,
_ => Dbms.Unknown
};
protected virtual MobileApp MapMobileApp(string? mobile) => mobile switch
{
"maui" => MobileApp.Maui,
"react-native" => MobileApp.ReactNative,
"none" => MobileApp.None,
_ => MobileApp.Unknown
};
}

32
framework/src/Volo.Abp.Core/Volo/Abp/Telemetry/Activity/ActivityPropertyName.cs

@ -3,6 +3,10 @@
public static class ActivityPropertyName
{
public const string SessionId = nameof(SessionId);
public const string Id = nameof(Id);
public const string UserId = nameof(UserId);
public const string OrganizationId = nameof(OrganizationId);
public const string IpAddress = nameof(IpAddress);
public const string IsFirstSession = nameof(IsFirstSession);
public const string DeviceId = nameof(DeviceId);
public const string DeviceType = nameof(DeviceType);
@ -41,4 +45,32 @@ public static class ActivityPropertyName
public const string Assembly = nameof(Assembly);
public const string LicenseType = nameof(LicenseType);
public const string SessionType = nameof(SessionType);
public const string HasError = nameof(HasError);
public const string ActivityDuration = nameof(ActivityDuration);
public const string ActivityDetails = nameof(ActivityDetails);
public const string ApplicationId = nameof(ApplicationId);
public const string Time = nameof(Time);
public const string SoftwareName = nameof(SoftwareName);
public const string SoftwareVersion = nameof(SoftwareVersion);
public const string SoftwareUiTheme = nameof(SoftwareUiTheme);
public const string SoftwareType = nameof(SoftwareType);
public const string UserDeviceId = nameof(UserDeviceId);
public const string SolutionTemplate = nameof(SolutionTemplate);
public const string WebFramework = nameof(WebFramework);
public const string Dbms = nameof(Dbms);
public const string UiTheme = nameof(UiTheme);
public const string UiThemeStyle = nameof(UiThemeStyle);
public const string MobileApp = nameof(MobileApp);
public const string IsMultiTenant = nameof(IsMultiTenant);
public const string SampleCrudPage = nameof(SampleCrudPage);
public const string FirstAbpVersion = nameof(FirstAbpVersion);
public const string FirstDotnetVersion = nameof(FirstDotnetVersion);
public const string CreationTool = nameof(CreationTool);
public const string Applications = nameof(Applications);
public const string ModuleName = nameof(ModuleName);
public const string ModuleVersion = nameof(ModuleVersion);
public const string ModuleInstallationTime = nameof(ModuleInstallationTime);
public const string ApplicationType = nameof(ApplicationType);
public const string AbpModuleCount = nameof(AbpModuleCount);
}

28
framework/src/Volo.Abp.Core/Volo/Abp/Telemetry/Activity/ActivityStorage.cs

@ -128,7 +128,10 @@ public class ActivityStorage : IActivityStorage, ISingletonDependency
{
using var reader = new StreamReader(stream, Encoding.UTF8);
var json = await reader.ReadToEndAsync();
return JsonSerializer.Deserialize<ActivityStorageState?>(json) ?? new ActivityStorageState();
return JsonSerializer.Deserialize<ActivityStorageState?>(json, new JsonSerializerOptions
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase
}) ?? new ActivityStorageState();
});
return _cachedState;
}
@ -178,7 +181,7 @@ public class ActivityStorage : IActivityStorage, ISingletonDependency
}
private async Task EnsureFileExistsAsync()
private Task EnsureFileExistsAsync()
{
try
{
@ -192,7 +195,11 @@ public class ActivityStorage : IActivityStorage, ISingletonDependency
if (!File.Exists(AbpTelemetryPaths.ActivityStorage))
{
var json = JsonSerializer.Serialize(_cachedState ?? new ActivityStorageState(),
new JsonSerializerOptions { WriteIndented = true });
new JsonSerializerOptions
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
WriteIndented = true
});
File.WriteAllText(AbpTelemetryPaths.ActivityStorage, json, Encoding.UTF8);
}
}
@ -200,5 +207,20 @@ public class ActivityStorage : IActivityStorage, ISingletonDependency
{
//ignored
}
return Task.CompletedTask;
}
public virtual async Task<bool> ShouldAddDeviceInfoAsync()
{
var lastSend = await GetLastDeviceInfoSendTimeAsync();
return lastSend is null || DateTimeOffset.UtcNow - lastSend > TimeSpan.FromDays(7);
}
public virtual async Task<bool> ShouldAddSolutionInformation(Guid solutionId)
{
var lastSend = await GetLastSolutionInfoSendTimeAsync(solutionId);
return lastSend is null || DateTimeOffset.UtcNow - lastSend > TimeSpan.FromDays(7);
}
}

15
framework/src/Volo.Abp.Core/Volo/Abp/Telemetry/Activity/IActivityStorage.cs

@ -1,7 +1,16 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Telemetry.EnvironmentInspection.Contracts;
using Volo.Abp.Telemetry.Shared;
using Volo.Abp.Telemetry.Shared.Enums;
namespace Volo.Abp.Telemetry.Activity;
@ -10,10 +19,12 @@ public interface IActivityStorage
Task<DateTimeOffset?> GetLastActivitySendTimeAsync();
Task<(bool isFirstSession, Guid sessionId)> GetOrCreateSessionInfoAsync();
Task MarkActivitiesAsSentAsync();
Task MarkDeviceInfoAsSentAsync();
Task<DateTimeOffset?> GetLastSolutionInfoSendTimeAsync(Guid solutionId);
Task<DateTimeOffset?> GetLastDeviceInfoSendTimeAsync();
Task BufferActivityAsync(ActivityData activityData);
Task<List<ActivityData>> GetBufferedActivitiesAsync();
Task EndSessionAsync();
}
Task<bool> ShouldAddDeviceInfoAsync();
Task<bool> ShouldAddSolutionInformation(Guid solutionId);
}

12
framework/src/Volo.Abp.Core/Volo/Abp/Telemetry/Activity/ISolutionInfoProvider.cs

@ -0,0 +1,12 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace Volo.Abp.Telemetry.Activity;
public interface ISolutionInfoProvider
{
Task<IDictionary<string, object>> GetSolutionInfoAsync(string solutionPath);
Guid? GetSolutionId(string solutionPath);
}

244
framework/src/Volo.Abp.Core/Volo/Abp/Telemetry/Activity/SolutionInfoProvider.cs

@ -0,0 +1,244 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text.Json;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Telemetry.EnvironmentInspection.Contracts;
using Volo.Abp.Telemetry.Shared;
using Volo.Abp.Telemetry.Shared.Enums;
namespace Volo.Abp.Telemetry.Activity;
public class SolutionInfoProvider : ISolutionInfoProvider , ISingletonDependency
{
public async Task<IDictionary<string, object>> GetSolutionInfoAsync(string solutionPath)
{
var dictionary = new Dictionary<string, object>();
var solutionJson = File.ReadAllText(solutionPath);
using var solutionDoc = JsonDocument.Parse(solutionJson);
var root = solutionDoc.RootElement;
if (root.TryGetProperty("creatingStudioConfiguration", out var config))
{
AddCreatingStudioConfiguration(dictionary, config);
}
dictionary[ActivityPropertyName.LicenseType] = await GetLicenseTypeAsync();
if (root.TryGetProperty("modules", out var modulesElement) && modulesElement.ValueKind == JsonValueKind.Object)
{
var modules = ExtractModules(modulesElement);
dictionary[ActivityPropertyName.InstalledModules] = modules;
}
return dictionary;
}
public Guid? GetSolutionId(string solutionPath)
{
var solutionJson = File.ReadAllText((string)solutionPath);
using var solutionDoc = JsonDocument.Parse(solutionJson);
var root = solutionDoc.RootElement;
return ReadSolutionIdFromJson(root);
}
private Guid? ReadSolutionIdFromJson(JsonElement root)
{
return root.TryGetProperty("id", out var idElement) && Guid.TryParse(idElement.GetString(), out var id)
? id
: null;
}
protected virtual void AddCreatingStudioConfiguration(Dictionary<string,object> dict, JsonElement config)
{
try
{
var mappings = new Dictionary<string, Action<JsonElement>>
{
{ "template", value => dict[ActivityPropertyName.Template] = MapSolutionTemplate(value.GetString()) },
{ "createdAbpStudioVersion", value => dict[ActivityPropertyName.CreatedAbpStudioVersion] = value.GetString()! },
{ "tiered", value => dict[ActivityPropertyName.IsTiered] = ParseBool(value) },
{ "uiFramework", value => dict[ActivityPropertyName.UiFramework] = MapUiFramework(value.GetString()) },
{ "databaseProvider", value => dict[ActivityPropertyName.DatabaseProvider] = MapDatabaseProvider(value.GetString()) },
{ "databaseManagementSystem", value => dict[ActivityPropertyName.DatabaseManagementSystem] = MapDbms(value.GetString()) },
{ "separateTenantSchema", value => dict[ActivityPropertyName.IsSeparateTenantSchema] = ParseBool(value) },
{ "theme", value => dict[ActivityPropertyName.Theme] = MapUiTheme(value.GetString()) },
{ "themeStyle", value => dict[ActivityPropertyName.ThemeStyle] = MapUiThemeStyle(value.GetString()) },
{ "mobileFramework", value => dict[ActivityPropertyName.MobileFramework] = MapMobileApp(value.GetString()) },
{ "publicWebsite", value => dict[ActivityPropertyName.HasPublicWebsite] = ParseBool(value) },
{ "includeTests", value => dict[ActivityPropertyName.IncludeTests] = ParseBool(value) },
{ "multiTenancy", value => dict[ActivityPropertyName.MultiTenancy] = ParseBool(value) },
{ "dynamicLocalization", value => dict[ActivityPropertyName.DynamicLocalization] = ParseBool(value) },
{ "kubernetesConfiguration", value => dict[ActivityPropertyName.KubernetesConfiguration] = ParseBool(value) },
{ "grafanaDashboard", value => dict[ActivityPropertyName.GrafanaDashboard] = ParseBool(value) },
{ "socialLogin", value => dict[ActivityPropertyName.SocialLogins] = ParseBool(value) }
};
foreach (var mapping in mappings)
{
try
{
if (config.TryGetProperty(mapping.Key, out var propertyValue))
{
mapping.Value(propertyValue);
}
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
private static bool ParseBool(JsonElement element) =>
element.ValueKind switch
{
JsonValueKind.True => true,
JsonValueKind.False => false,
JsonValueKind.String when bool.TryParse(element.GetString(), out var b) => b,
_ => false
};
protected virtual List<SolutionModuleInstallationInfo> ExtractModules(JsonElement modulesElement)
{
var modules = new List<SolutionModuleInstallationInfo>();
foreach (var module in modulesElement.EnumerateObject())
{
var name = module.Name;
if (!module.Value.TryGetProperty("path", out var pathElement))
{
continue;
}
var path = pathElement.GetString();
if (path.IsNullOrEmpty() || !File.Exists(path))
{
continue;
}
var moduleJson = File.ReadAllText(path);
using var moduleDoc = JsonDocument.Parse(moduleJson);
if (!moduleDoc.RootElement.TryGetProperty("imports", out var imports) ||
imports.ValueKind != JsonValueKind.Object)
{
continue;
}
foreach (var import in imports.EnumerateObject())
{
var version = import.Value.GetProperty("version").GetString();
var creationTime = import.Value.TryGetProperty("creationTime", out var ct)
? DateTimeOffset.Parse(ct.GetString()!)
: (DateTimeOffset?)null;
if (modules.Any(x => x.ModuleName == name && x.Version == version))
{
continue;
}
modules.Add(new SolutionModuleInstallationInfo
{
ModuleName = name, Version = version, InstallationTime = creationTime
});
}
}
return modules;
}
protected virtual async Task<int> GetLicenseTypeAsync()
{
if (!File.Exists(AbpTelemetryPaths.AccessToken))
{
return 0;
}
using var httpClient = new HttpClient();
var accessToken = File.ReadAllText(AbpTelemetryPaths.AccessToken);
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
var json = await httpClient.GetStringAsync($"{AbpPlatformUrls.AbpIoUrl}api/license/api-key");
using var doc = JsonDocument.Parse(json);
return doc.RootElement.GetProperty("licenseType").GetInt32();
}
protected virtual UiTheme MapUiTheme(string? theme) => theme switch
{
"none" => UiTheme.None,
"basic" => UiTheme.Basic,
"leptonx" => UiTheme.LeptonX,
"leptonx-lite" => UiTheme.LeptonXLite,
_ => UiTheme.Unknown
};
protected virtual UiThemeStyle MapUiThemeStyle(string? style) => style switch
{
"dim" => UiThemeStyle.Dim,
"style" => UiThemeStyle.System,
"dark" => UiThemeStyle.Dark,
"light" => UiThemeStyle.Light,
_ => UiThemeStyle.Unknown
};
protected virtual SolutionTemplate MapSolutionTemplate(string? template) => template switch
{
"microservice" => SolutionTemplate.Microservice,
"app-nolayers" => SolutionTemplate.AppNoLayers,
"app" => SolutionTemplate.AppLayered,
_ => SolutionTemplate.Unknown
};
protected virtual UiFramework MapUiFramework(string? framework) => framework switch
{
"mvc" => UiFramework.MvcRazorPages,
"blazor" => UiFramework.BlazorWasm,
"angular" => UiFramework.Angular,
"blazor-server" => UiFramework.BlazorServer,
"blazor-webapp" => UiFramework.BlazorWebApp,
"maui-blazor" => UiFramework.BlazorMaUI,
"none" => UiFramework.None,
_ => UiFramework.Unknown
};
protected virtual DatabaseProvider MapDatabaseProvider(string? provider) => provider switch
{
"ef" => DatabaseProvider.EfCore,
"mongodb" => DatabaseProvider.MongoDb,
"none" => DatabaseProvider.None,
_ => DatabaseProvider.Unknown
};
protected virtual Dbms MapDbms(string? dbms) => dbms switch
{
"mysql" => Dbms.MySql,
"oracle" => Dbms.Oracle,
"oracle-devart" => Dbms.OracleDevart,
"postgresql" => Dbms.PostgreSql,
"sqlserver" => Dbms.SqlServer,
"sqlite" => Dbms.Sqlite,
_ => Dbms.Unknown
};
protected virtual MobileApp MapMobileApp(string? mobile) => mobile switch
{
"maui" => MobileApp.Maui,
"react-native" => MobileApp.ReactNative,
"none" => MobileApp.None,
_ => MobileApp.Unknown
};
}

1
framework/src/Volo.Abp.Core/Volo/Abp/Telemetry/ITelemetryService.cs

@ -11,4 +11,5 @@ public interface ITelemetryService
IAsyncDisposable TrackActivity(ActivityData activityData);
Task AddActivityAsync(ActivityData data);
Task AddActivityAsync(string activityName, string? details = null);
Task AddActivityAsync(string activityName, Action<ActivityData> configure);
}

12
framework/src/Volo.Abp.Core/Volo/Abp/Telemetry/TelemetryService.cs

@ -95,4 +95,16 @@ public class TelemetryService : ITelemetryService , IScopedDependency
{
await AddActivityAsync(new ActivityData(activityName, details));
}
public async Task AddActivityAsync(string activityName, Action<ActivityData> configure)
{
var activityData = new ActivityData(activityName)
{
Time = DateTimeOffset.UtcNow
};
configure?.Invoke(activityData);
await AddActivityAsync(activityData);
}
}
Loading…
Cancel
Save