mirror of https://github.com/abpframework/abp.git
21 changed files with 541 additions and 427 deletions
@ -0,0 +1,8 @@ |
|||
using System.Threading.Tasks; |
|||
|
|||
namespace Volo.Abp.Telemetry.Activity.Contracts; |
|||
|
|||
public interface ITelemetryActivityDataBuilder |
|||
{ |
|||
Task BuildAsync(ActivityData activity); |
|||
} |
|||
@ -0,0 +1,8 @@ |
|||
using System.Threading.Tasks; |
|||
|
|||
namespace Volo.Abp.Telemetry.Activity.Contracts; |
|||
|
|||
public interface ITelemetryActivityDataEnricher |
|||
{ |
|||
Task EnrichAsync(ActivityData activity); |
|||
} |
|||
@ -1,8 +0,0 @@ |
|||
using System.Threading.Tasks; |
|||
|
|||
namespace Volo.Abp.Telemetry.Activity.Contracts; |
|||
|
|||
public interface ITelemetryActivityDataProvider |
|||
{ |
|||
Task AddExtraInformationAsync(ActivityData activity); |
|||
} |
|||
@ -0,0 +1,37 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.IO; |
|||
using System.Threading.Tasks; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Volo.Abp.DependencyInjection; |
|||
using Volo.Abp.Telemetry.Activity.Contracts; |
|||
using Volo.Abp.Telemetry.Constants; |
|||
|
|||
namespace Volo.Abp.Telemetry.Activity.Providers; |
|||
|
|||
public class TelemetryActivityDataBuilder : ITelemetryActivityDataBuilder, ISingletonDependency |
|||
{ |
|||
private readonly IServiceProvider _serviceProvider; |
|||
|
|||
public TelemetryActivityDataBuilder(IServiceProvider serviceProvider) |
|||
{ |
|||
_serviceProvider = serviceProvider; |
|||
} |
|||
|
|||
public virtual async Task BuildAsync(ActivityData activity) |
|||
{ |
|||
var telemetrySessionTypeProvider = _serviceProvider.GetRequiredService<ITelemetrySessionTypeProvider>(); |
|||
var telemetryActivityStorage = _serviceProvider.GetRequiredService<ITelemetryActivityStorage>(); |
|||
|
|||
activity[ActivityPropertyName.SessionType] = telemetrySessionTypeProvider.SessionType; |
|||
activity[ActivityPropertyName.SessionId] = await telemetryActivityStorage.GetOrCreateSessionInfoAsync(); |
|||
activity[ActivityPropertyName.IsFirstSession] = !File.Exists(TelemetryPaths.ActivityStorage); |
|||
|
|||
var activityDataEnrichers = _serviceProvider.GetRequiredService<IEnumerable<ITelemetryActivityDataEnricher>>(); |
|||
|
|||
foreach (var activityDataEnricher in activityDataEnrichers) |
|||
{ |
|||
await activityDataEnricher.EnrichAsync(activity); |
|||
} |
|||
} |
|||
} |
|||
@ -1,76 +0,0 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Threading.Tasks; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Volo.Abp.DependencyInjection; |
|||
using Volo.Abp.Telemetry.Activity.Contracts; |
|||
using Volo.Abp.Telemetry.Constants; |
|||
using Volo.Abp.Telemetry.Constants.Enums; |
|||
using Volo.Abp.Telemetry.EnvironmentInspection.Contracts; |
|||
|
|||
namespace Volo.Abp.Telemetry.Activity.Providers; |
|||
|
|||
public class TelemetryActivityDataProvider : ITelemetryActivityDataProvider, ISingletonDependency |
|||
{ |
|||
private readonly IServiceProvider _serviceProvider; |
|||
|
|||
public TelemetryActivityDataProvider(IServiceProvider serviceProvider) |
|||
{ |
|||
_serviceProvider = serviceProvider; |
|||
} |
|||
|
|||
public virtual async Task AddExtraInformationAsync(ActivityData activity) |
|||
{ |
|||
var activityStorage = _serviceProvider.GetRequiredService<ITelemetryActivityStorage>(); |
|||
var sessionContext = _serviceProvider.GetRequiredService<ITelemetrySessionContextProvider>(); |
|||
var deviceInfoProvider = _serviceProvider.GetRequiredService<IDeviceInfoProvider>(); |
|||
|
|||
var (isFirstSession, sessionId) = await activityStorage.GetOrCreateSessionInfoAsync(); |
|||
|
|||
sessionContext.SetSolutionContext(activity); |
|||
activity[ActivityPropertyName.SessionType] = sessionContext.SessionType; |
|||
activity[ActivityPropertyName.SessionId] = sessionId; |
|||
activity[ActivityPropertyName.IsFirstSession] = isFirstSession; |
|||
activity[ActivityPropertyName.DeviceId] = deviceInfoProvider.GetDeviceId(); |
|||
|
|||
if (await activityStorage.ShouldAddDeviceInfoAsync()) |
|||
{ |
|||
activity[ActivityPropertyName.DeviceType] = deviceInfoProvider.GetDeviceType(); |
|||
activity[ActivityPropertyName.DeviceLanguage] = deviceInfoProvider.GetLanguage(); |
|||
activity[ActivityPropertyName.OperatingSystem] = deviceInfoProvider.GetOperatingSystem(); |
|||
activity[ActivityPropertyName.CountryIsoCode] = deviceInfoProvider.GetCountry(); |
|||
|
|||
var softwareInfo = _serviceProvider.GetRequiredService<ISoftwareInfoProvider>(); |
|||
var softwareList = await softwareInfo.GetSoftwareInfoAsync(); |
|||
activity[ActivityPropertyName.InstalledSoftwares] = softwareList; |
|||
|
|||
await activityStorage.MarkDeviceInfoAsSentAsync(); |
|||
} |
|||
|
|||
if (activity.ContainsKey(ActivityPropertyName.Assembly) && sessionContext.SessionType == SessionType.ApplicationRuntime) |
|||
{ |
|||
var contributors = _serviceProvider.GetRequiredService<IEnumerable<ITelemetryApplicationInfoContributor>>(); |
|||
foreach (var contributor in contributors) |
|||
{ |
|||
await contributor.ContributeAsync(activity); |
|||
} |
|||
activity.Remove(ActivityPropertyName.Assembly); |
|||
} |
|||
|
|||
if (activity.TryGetValue(ActivityPropertyName.SolutionId, out var rawSolutionId) && Guid.TryParse(rawSolutionId?.ToString(), out var solutionId)) |
|||
{ |
|||
|
|||
if (await activityStorage.ShouldAddSolutionInformation(solutionId)) |
|||
{ |
|||
var solutionProvider = _serviceProvider.GetRequiredService<ITelemetrySolutionInfoProvider>(); |
|||
var solutionInfo = await solutionProvider.GetSolutionInfoAsync(activity[ActivityPropertyName.SolutionPath].ToString()!); |
|||
|
|||
foreach (var entry in solutionInfo) |
|||
{ |
|||
activity[entry.Key] = entry.Value; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,35 @@ |
|||
using System.Collections.Generic; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.DependencyInjection; |
|||
using Volo.Abp.Telemetry.Activity.Contracts; |
|||
using Volo.Abp.Telemetry.Constants; |
|||
using Volo.Abp.Telemetry.Constants.Enums; |
|||
|
|||
namespace Volo.Abp.Telemetry.Activity.Providers; |
|||
|
|||
[ExposeServices(typeof(ITelemetryActivityDataEnricher))] |
|||
public class TelemetryApplicationInfoEnricher : ITelemetryActivityDataEnricher, ISingletonDependency |
|||
{ |
|||
private readonly ITelemetrySessionTypeProvider _telemetrySessionTypeProvider; |
|||
private readonly IEnumerable<ITelemetryApplicationInfoContributor> _telemetryApplicationInfoContributors; |
|||
|
|||
public TelemetryApplicationInfoEnricher(ITelemetrySessionTypeProvider telemetrySessionTypeProvider, |
|||
IEnumerable<ITelemetryApplicationInfoContributor> telemetryApplicationInfoContributors) |
|||
{ |
|||
_telemetrySessionTypeProvider = telemetrySessionTypeProvider; |
|||
_telemetryApplicationInfoContributors = telemetryApplicationInfoContributors; |
|||
} |
|||
|
|||
public async Task EnrichAsync(ActivityData activity) |
|||
{ |
|||
if (activity.ContainsKey(ActivityPropertyName.Assembly) && _telemetrySessionTypeProvider.SessionType == SessionType.ApplicationRuntime) |
|||
{ |
|||
foreach (var contributor in _telemetryApplicationInfoContributors) |
|||
{ |
|||
await contributor.ContributeAsync(activity); |
|||
} |
|||
|
|||
activity.Remove(ActivityPropertyName.Assembly); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,279 @@ |
|||
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.Activity.Contracts; |
|||
using Volo.Abp.Telemetry.Constants; |
|||
|
|||
namespace Volo.Abp.Telemetry.Activity.Providers; |
|||
|
|||
[ExposeServices(typeof(ITelemetryActivityDataEnricher))] |
|||
public class TelemetrySolutionInfoEnricher : ITelemetryActivityDataEnricher, ISingletonDependency |
|||
{ |
|||
private readonly ITelemetryActivityStorage _telemetryActivityStorage; |
|||
|
|||
public TelemetrySolutionInfoEnricher(ITelemetryActivityStorage telemetryActivityStorage) |
|||
{ |
|||
_telemetryActivityStorage = telemetryActivityStorage; |
|||
} |
|||
|
|||
|
|||
|
|||
public async Task EnrichAsync(ActivityData activity) |
|||
{ |
|||
var solutionId = GetSolutionId(activity); |
|||
if (solutionId.HasValue) |
|||
{ |
|||
if (await _telemetryActivityStorage.ShouldAddSolutionInformation(solutionId.Value)) |
|||
{ |
|||
await FillSolutionInfoAsync(activity); |
|||
await _telemetryActivityStorage.MarkSolutionInfoAsAddedAsync(solutionId.Value); |
|||
} |
|||
|
|||
activity.Remove(ActivityPropertyName.SolutionPath); |
|||
} |
|||
} |
|||
|
|||
private Guid? GetSolutionId(ActivityData activity) |
|||
{ |
|||
if (TryGetSolutionIdFromActivity(activity, out var solutionId)) |
|||
{ |
|||
return solutionId; |
|||
} |
|||
|
|||
if (TryGetSolutionIdFromFile(activity, out var idFromFile)) |
|||
{ |
|||
activity[ActivityPropertyName.SolutionId] = idFromFile; |
|||
return idFromFile; |
|||
} |
|||
|
|||
return null; |
|||
} |
|||
private async Task FillSolutionInfoAsync(ActivityData activityData) |
|||
{ |
|||
try |
|||
{ |
|||
if (!activityData.TryGetValue(ActivityPropertyName.SolutionPath, out var rawSolutionPath) |
|||
|| string.IsNullOrWhiteSpace(rawSolutionPath?.ToString()) |
|||
|| !File.Exists(rawSolutionPath?.ToString())) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
var solutionPath = rawSolutionPath!.ToString(); |
|||
|
|||
if (!File.Exists(solutionPath)) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
var jsonContent = File.ReadAllText(solutionPath); |
|||
using var doc = JsonDocument.Parse(jsonContent); |
|||
var root = doc.RootElement; |
|||
|
|||
AddSolutionInformation(activityData, root.GetProperty("creatingStudioConfiguration")); |
|||
|
|||
activityData[ActivityPropertyName.LicenseType] = await GetLicenseTypeAsync(); |
|||
|
|||
if (root.TryGetProperty("modules", out var modulesElement) && |
|||
modulesElement.ValueKind == JsonValueKind.Object) |
|||
{ |
|||
var directoryPath = Path.GetDirectoryName(solutionPath)!; |
|||
activityData[ActivityPropertyName.InstalledModules] = ExtractModules(directoryPath, modulesElement); |
|||
} |
|||
} |
|||
catch |
|||
{ |
|||
// ignored
|
|||
} |
|||
} |
|||
|
|||
private bool TryGetSolutionIdFromActivity(ActivityData activity, out Guid solutionId) |
|||
{ |
|||
solutionId = Guid.Empty; |
|||
|
|||
if (activity.TryGetValue(ActivityPropertyName.SolutionId, out var value) && |
|||
Guid.TryParse(value?.ToString(), out var parsedId)) |
|||
{ |
|||
solutionId = parsedId; |
|||
return true; |
|||
} |
|||
|
|||
return false; |
|||
} |
|||
|
|||
private bool TryGetSolutionIdFromFile(ActivityData activity, out Guid solutionId) |
|||
{ |
|||
solutionId = Guid.Empty; |
|||
|
|||
if (!activity.TryGetValue(ActivityPropertyName.SolutionPath, out var value)) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
var path = value?.ToString(); |
|||
if (string.IsNullOrWhiteSpace(path) || !File.Exists(path)) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
try |
|||
{ |
|||
var json = File.ReadAllText(path); |
|||
using var doc = JsonDocument.Parse(json); |
|||
if (doc.RootElement.TryGetProperty("id", out var idProp) && |
|||
Guid.TryParse(idProp.GetString(), out var parsedId)) |
|||
{ |
|||
solutionId = parsedId; |
|||
return true; |
|||
} |
|||
} |
|||
catch |
|||
{ |
|||
// ignore malformed json etc.
|
|||
} |
|||
|
|||
return false; |
|||
} |
|||
|
|||
private void AddSolutionInformation(Dictionary<string, object> activity, JsonElement config) |
|||
{ |
|||
var map = new (string Key, Action<JsonElement> Apply)[] |
|||
{ |
|||
("template", v => activity[ActivityPropertyName.Template] = v.GetString() ?? string.Empty), |
|||
("createdAbpStudioVersion", v => activity[ActivityPropertyName.CreatedAbpStudioVersion] = v.GetString()!), |
|||
("multiTenancy", v => activity[ActivityPropertyName.MultiTenancy] = ParseBool(v)), |
|||
("uiFramework", v => activity[ActivityPropertyName.UiFramework] = v.GetString() ?? string.Empty), |
|||
("databaseProvider", v => activity[ActivityPropertyName.DatabaseProvider] = v.GetString() ?? string.Empty), |
|||
("theme", v => activity[ActivityPropertyName.Theme] = v.GetString() ?? string.Empty), |
|||
("themeStyle", v => activity[ActivityPropertyName.ThemeStyle] = v.GetString() ?? string.Empty), |
|||
("publicWebsite", v => activity[ActivityPropertyName.HasPublicWebsite] = ParseBool(v)), |
|||
("tiered", v => activity[ActivityPropertyName.IsTiered] = ParseBool(v)), |
|||
("socialLogin", v => activity[ActivityPropertyName.SocialLogins] = ParseBool(v)), |
|||
("databaseManagementSystem", v => activity[ActivityPropertyName.DatabaseManagementSystem] = v.GetString() ?? string.Empty), |
|||
("separateTenantSchema", v => activity[ActivityPropertyName.IsSeparateTenantSchema] = ParseBool(v)), |
|||
("mobileFramework", v => activity[ActivityPropertyName.MobileFramework] = v.GetString() ?? string.Empty), |
|||
("includeTests", v => activity[ActivityPropertyName.IncludeTests] = ParseBool(v)), |
|||
("dynamicLocalization", v => activity[ActivityPropertyName.DynamicLocalization] = ParseBool(v)), |
|||
("kubernetesConfiguration", v => activity[ActivityPropertyName.KubernetesConfiguration] = ParseBool(v)), |
|||
("grafanaDashboard", v => activity[ActivityPropertyName.GrafanaDashboard] = ParseBool(v)), |
|||
}; |
|||
|
|||
foreach (var (key, apply) in map) |
|||
{ |
|||
if (config.TryGetProperty(key, out var prop)) |
|||
{ |
|||
apply(prop); |
|||
} |
|||
} |
|||
} |
|||
|
|||
private List<Dictionary<string, object>> ExtractModules(string directoryPath, JsonElement modulesElement) |
|||
{ |
|||
var modules = new List<Dictionary<string, object>>(); |
|||
|
|||
foreach (var module in modulesElement.EnumerateObject()) |
|||
{ |
|||
if (!module.Value.TryGetProperty("path", out var pathElement)) |
|||
{ |
|||
continue; |
|||
} |
|||
|
|||
var path = pathElement.GetString(); |
|||
if (string.IsNullOrWhiteSpace(path)) |
|||
{ |
|||
continue; |
|||
} |
|||
|
|||
var fullPath = Path.Combine(directoryPath, path); |
|||
if (!File.Exists(fullPath)) |
|||
{ |
|||
continue; |
|||
} |
|||
|
|||
var moduleJson = File.ReadAllText(fullPath); |
|||
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.TryGetValue(ActivityPropertyName.ModuleName, out var n) && n as string == import.Name && |
|||
x.TryGetValue(ActivityPropertyName.ModuleVersion, out var v) && v as string == version)) |
|||
{ |
|||
continue; |
|||
} |
|||
|
|||
var moduleEntry = new Dictionary<string, object> { { ActivityPropertyName.ModuleName, import.Name } }; |
|||
if (!version.IsNullOrEmpty()) |
|||
{ |
|||
moduleEntry[ActivityPropertyName.ModuleVersion] = version; |
|||
} |
|||
|
|||
if (creationTime.HasValue) |
|||
{ |
|||
moduleEntry[ActivityPropertyName.ModuleInstallationTime] = creationTime.Value; |
|||
} |
|||
|
|||
modules.Add(moduleEntry); |
|||
} |
|||
} |
|||
|
|||
return modules; |
|||
} |
|||
|
|||
private bool ParseBool(JsonElement element) |
|||
{ |
|||
return element.ValueKind switch |
|||
{ |
|||
JsonValueKind.True => true, |
|||
JsonValueKind.False => false, |
|||
JsonValueKind.String when bool.TryParse(element.GetString(), out var b) => b, |
|||
_ => false |
|||
}; |
|||
} |
|||
|
|||
private async Task<int> GetLicenseTypeAsync() |
|||
{ |
|||
if (!File.Exists(TelemetryPaths.AccessToken)) |
|||
{ |
|||
return 0; |
|||
} |
|||
|
|||
try |
|||
{ |
|||
using var httpClient = new HttpClient(); |
|||
var accessToken = File.ReadAllText(TelemetryPaths.AccessToken); |
|||
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken); |
|||
|
|||
var response = await httpClient.GetAsync($"{AbpPlatformUrls.AbpIoUrl}api/license/api-key"); |
|||
if (!response.IsSuccessStatusCode) |
|||
{ |
|||
return 0; |
|||
} |
|||
|
|||
var content = await response.Content.ReadAsStringAsync(); |
|||
using var doc = JsonDocument.Parse(content); |
|||
return doc.RootElement.GetProperty("licenseType").GetInt32(); |
|||
} |
|||
catch |
|||
{ |
|||
return 0; |
|||
} |
|||
} |
|||
} |
|||
@ -1,188 +0,0 @@ |
|||
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.Activity.Contracts; |
|||
using Volo.Abp.Telemetry.Constants; |
|||
|
|||
namespace Volo.Abp.Telemetry.Activity.Providers; |
|||
|
|||
public class TelemetrySolutionInfoProvider : ITelemetrySolutionInfoProvider, ISingletonDependency |
|||
{ |
|||
public async Task<IDictionary<string, object>> GetSolutionInfoAsync(string solutionPath) |
|||
{ |
|||
try |
|||
{ |
|||
var result = new Dictionary<string, object>(); |
|||
var jsonContent = File.ReadAllText(solutionPath); |
|||
using var doc = JsonDocument.Parse(jsonContent); |
|||
var root = doc.RootElement; |
|||
|
|||
AddSolutionInformation(result, root.GetProperty("creatingStudioConfiguration")); |
|||
|
|||
result[ActivityPropertyName.LicenseType] = await GetLicenseTypeAsync(); |
|||
|
|||
if (root.TryGetProperty("modules", out var modulesElement) && modulesElement.ValueKind == JsonValueKind.Object) |
|||
{ |
|||
var directoryPath = Path.GetDirectoryName(solutionPath)!; |
|||
result[ActivityPropertyName.InstalledModules] = ExtractModules(directoryPath, modulesElement); |
|||
} |
|||
|
|||
return result; |
|||
} |
|||
catch |
|||
{ |
|||
return new Dictionary<string, object>(); |
|||
} |
|||
} |
|||
|
|||
public Guid? GetSolutionId(string solutionPath) |
|||
{ |
|||
var jsonContent = File.ReadAllText(solutionPath); |
|||
using var doc = JsonDocument.Parse(jsonContent); |
|||
return TryGetGuid(doc.RootElement, "id"); |
|||
} |
|||
|
|||
private Guid? TryGetGuid(JsonElement root, string propertyName) |
|||
{ |
|||
return root.TryGetProperty(propertyName, out var prop) && Guid.TryParse(prop.GetString(), out var id) ? id : null; |
|||
} |
|||
|
|||
private void AddSolutionInformation(Dictionary<string, object> dict, JsonElement config) |
|||
{ |
|||
var map = new (string Key, Action<JsonElement> Apply)[] |
|||
{ |
|||
("template", v => dict[ActivityPropertyName.Template] = v.GetString() ?? string.Empty), |
|||
("createdAbpStudioVersion", v => dict[ActivityPropertyName.CreatedAbpStudioVersion] = v.GetString()!), |
|||
("multiTenancy", v => dict[ActivityPropertyName.MultiTenancy] = ParseBool(v)), |
|||
("uiFramework", v => dict[ActivityPropertyName.UiFramework] = v.GetString() ?? string.Empty), |
|||
("databaseProvider", v => dict[ActivityPropertyName.DatabaseProvider] = v.GetString() ?? string.Empty), |
|||
("theme", v => dict[ActivityPropertyName.Theme] = v.GetString() ?? string.Empty), |
|||
("themeStyle", v => dict[ActivityPropertyName.ThemeStyle] = v.GetString() ?? string.Empty), |
|||
("publicWebsite", v => dict[ActivityPropertyName.HasPublicWebsite] = ParseBool(v)), |
|||
("tiered", v => dict[ActivityPropertyName.IsTiered] = ParseBool(v)), |
|||
("socialLogin", v => dict[ActivityPropertyName.SocialLogins] = ParseBool(v)), |
|||
("databaseManagementSystem", v => dict[ActivityPropertyName.DatabaseManagementSystem] = v.GetString() ?? string.Empty), |
|||
("separateTenantSchema", v => dict[ActivityPropertyName.IsSeparateTenantSchema] = ParseBool(v)), |
|||
("mobileFramework", v => dict[ActivityPropertyName.MobileFramework] = v.GetString() ?? string.Empty), |
|||
("includeTests", v => dict[ActivityPropertyName.IncludeTests] = ParseBool(v)), |
|||
("dynamicLocalization", v => dict[ActivityPropertyName.DynamicLocalization] = ParseBool(v)), |
|||
("kubernetesConfiguration", v => dict[ActivityPropertyName.KubernetesConfiguration] = ParseBool(v)), |
|||
("grafanaDashboard", v => dict[ActivityPropertyName.GrafanaDashboard] = ParseBool(v)), |
|||
}; |
|||
|
|||
foreach (var (key, apply) in map) |
|||
{ |
|||
if (config.TryGetProperty(key, out var prop)) |
|||
{ |
|||
apply(prop); |
|||
} |
|||
} |
|||
} |
|||
|
|||
private List<Dictionary<string, object>> ExtractModules(string directoryPath, JsonElement modulesElement) |
|||
{ |
|||
var modules = new List<Dictionary<string, object>>(); |
|||
|
|||
foreach (var module in modulesElement.EnumerateObject()) |
|||
{ |
|||
if (!module.Value.TryGetProperty("path", out var pathElement)) |
|||
{ |
|||
continue; |
|||
} |
|||
|
|||
var path = pathElement.GetString(); |
|||
if (string.IsNullOrWhiteSpace(path)) |
|||
{ |
|||
continue; |
|||
} |
|||
|
|||
var fullPath = Path.Combine(directoryPath, path); |
|||
if (!File.Exists(fullPath)) |
|||
{ |
|||
continue; |
|||
} |
|||
|
|||
var moduleJson = File.ReadAllText(fullPath); |
|||
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.TryGetValue(ActivityPropertyName.ModuleName, out var n) && n as string == module.Name && |
|||
x.TryGetValue(ActivityPropertyName.ModuleVersion, out var v) && v as string == version)) |
|||
{ |
|||
continue; |
|||
} |
|||
|
|||
var moduleEntry = new Dictionary<string, object> { { ActivityPropertyName.ModuleName, module.Name } }; |
|||
if (!version.IsNullOrEmpty()) |
|||
{ |
|||
moduleEntry[ActivityPropertyName.ModuleVersion] = version; |
|||
} |
|||
|
|||
if (creationTime.HasValue) |
|||
{ |
|||
moduleEntry[ActivityPropertyName.ModuleInstallationTime] = creationTime.Value; |
|||
} |
|||
|
|||
modules.Add(moduleEntry); |
|||
} |
|||
} |
|||
|
|||
return modules; |
|||
} |
|||
|
|||
private static bool ParseBool(JsonElement element) |
|||
{ |
|||
return element.ValueKind switch |
|||
{ |
|||
JsonValueKind.True => true, |
|||
JsonValueKind.False => false, |
|||
JsonValueKind.String when bool.TryParse(element.GetString(), out var b) => b, |
|||
_ => false |
|||
}; |
|||
} |
|||
|
|||
protected virtual async Task<int> GetLicenseTypeAsync() |
|||
{ |
|||
if (!File.Exists(TelemetryPaths.AccessToken)) |
|||
{ |
|||
return 0; |
|||
} |
|||
|
|||
try |
|||
{ |
|||
using var httpClient = new HttpClient(); |
|||
var accessToken = File.ReadAllText(TelemetryPaths.AccessToken); |
|||
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken); |
|||
|
|||
var response = await httpClient.GetAsync($"{AbpPlatformUrls.AbpIoUrl}api/license/api-key"); |
|||
if (!response.IsSuccessStatusCode) |
|||
{ |
|||
return 0; |
|||
} |
|||
|
|||
var content = await response.Content.ReadAsStringAsync(); |
|||
using var doc = JsonDocument.Parse(content); |
|||
return doc.RootElement.GetProperty("licenseType").GetInt32(); |
|||
} |
|||
catch |
|||
{ |
|||
return 0; |
|||
} |
|||
} |
|||
} |
|||
@ -1,10 +0,0 @@ |
|||
using Volo.Abp.Telemetry.Activity; |
|||
using Volo.Abp.Telemetry.Constants.Enums; |
|||
|
|||
namespace Volo.Abp.Telemetry; |
|||
|
|||
public interface ITelemetrySessionContextProvider |
|||
{ |
|||
public SessionType SessionType { get; } |
|||
void SetSolutionContext(ActivityData activity); |
|||
} |
|||
@ -0,0 +1,8 @@ |
|||
using Volo.Abp.Telemetry.Constants.Enums; |
|||
|
|||
namespace Volo.Abp.Telemetry; |
|||
|
|||
public interface ITelemetrySessionTypeProvider |
|||
{ |
|||
SessionType SessionType { get; } |
|||
} |
|||
@ -1,39 +0,0 @@ |
|||
using System.IO; |
|||
using Volo.Abp.DependencyInjection; |
|||
using Volo.Abp.Telemetry.Activity; |
|||
using Volo.Abp.Telemetry.Activity.Contracts; |
|||
using Volo.Abp.Telemetry.Constants; |
|||
using Volo.Abp.Telemetry.Constants.Enums; |
|||
|
|||
namespace Volo.Abp.Telemetry; |
|||
|
|||
public class TelemetryApplicationRuntimeSessionTypeProvider : ITelemetrySessionContextProvider , ISingletonDependency |
|||
{ |
|||
private readonly ITelemetrySolutionInfoProvider _telemetrySolutionInfoProvider; |
|||
|
|||
public TelemetryApplicationRuntimeSessionTypeProvider(ITelemetrySolutionInfoProvider telemetrySolutionInfoProvider) |
|||
{ |
|||
_telemetrySolutionInfoProvider = telemetrySolutionInfoProvider; |
|||
} |
|||
|
|||
public virtual SessionType SessionType => SessionType.ApplicationRuntime; |
|||
public virtual void SetSolutionContext(ActivityData activity) |
|||
{ |
|||
if (activity.ContainsKey(ActivityPropertyName.SolutionId)) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
if (!activity.TryGetValue(ActivityPropertyName.SolutionPath, out var path) || !File.Exists((string)path)) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
var solutionId = _telemetrySolutionInfoProvider.GetSolutionId((string)path); |
|||
|
|||
if (solutionId.HasValue) |
|||
{ |
|||
activity[ActivityPropertyName.SolutionId] = solutionId.Value; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,10 @@ |
|||
using Volo.Abp.DependencyInjection; |
|||
using Volo.Abp.Telemetry.Constants.Enums; |
|||
|
|||
namespace Volo.Abp.Telemetry; |
|||
|
|||
[ExposeServices(typeof(ITelemetrySessionTypeProvider))] |
|||
public class TelemetrySessionTypeProvider : ITelemetrySessionTypeProvider, ISingletonDependency |
|||
{ |
|||
public SessionType SessionType => SessionType.ApplicationRuntime; |
|||
} |
|||
Loading…
Reference in new issue