|
|
|
@ -2,8 +2,6 @@ |
|
|
|
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; |
|
|
|
@ -30,7 +28,7 @@ public class TelemetrySolutionInfoEnricher : ITelemetryActivityEventEnricher, IS |
|
|
|
if (await _telemetryActivityStorage.ShouldAddSolutionInformation(solutionId)) |
|
|
|
{ |
|
|
|
activity[ActivityPropertyNames.SolutionId] = solutionId; |
|
|
|
await FillSolutionInfoAsync(activity); |
|
|
|
AddSolutionInfo(activity); |
|
|
|
await _telemetryActivityStorage.MarkSolutionInfoAsAddedAsync(solutionId); |
|
|
|
activity[ActivityPropertyNames.HasSolutionInfo] = true; |
|
|
|
activity.Remove(ActivityPropertyNames.SolutionPath); |
|
|
|
@ -54,142 +52,105 @@ public class TelemetrySolutionInfoEnricher : ITelemetryActivityEventEnricher, IS |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
private Task FillSolutionInfoAsync(ActivityEvent activity) |
|
|
|
private void AddSolutionInfo(ActivityEvent activity) |
|
|
|
{ |
|
|
|
try |
|
|
|
{ |
|
|
|
if (!activity.TryGetValue(ActivityPropertyNames.SolutionPath, out var rawSolutionPath) |
|
|
|
|| string.IsNullOrWhiteSpace(rawSolutionPath?.ToString()) |
|
|
|
|| !File.Exists(rawSolutionPath?.ToString())) |
|
|
|
{ |
|
|
|
return Task.CompletedTask; |
|
|
|
} |
|
|
|
var solutionPath = activity[ActivityPropertyNames.SolutionPath]!.ToString()!; |
|
|
|
|
|
|
|
var solutionPath = rawSolutionPath!.ToString()!; |
|
|
|
var jsonContent = File.ReadAllText(solutionPath); |
|
|
|
using var doc = JsonDocument.Parse(jsonContent); |
|
|
|
var root = doc.RootElement; |
|
|
|
|
|
|
|
AddSolutionInformation(activity, root.GetProperty("creatingStudioConfiguration")); |
|
|
|
AddSolutionCreationConfiguration(activity, root.GetProperty("creatingStudioConfiguration")); |
|
|
|
|
|
|
|
if (root.TryGetProperty("modules", out var modulesElement) && modulesElement.ValueKind == JsonValueKind.Object) |
|
|
|
if (root.TryGetProperty("modules", out var modulesElement) && |
|
|
|
modulesElement.ValueKind == JsonValueKind.Object) |
|
|
|
{ |
|
|
|
var directoryPath = Path.GetDirectoryName(solutionPath)!; |
|
|
|
activity[ActivityPropertyNames.InstalledModules] = ExtractModules(directoryPath, modulesElement); |
|
|
|
activity[ActivityPropertyNames.InstalledModules] = ExtractModules(solutionPath, modulesElement); |
|
|
|
} |
|
|
|
} |
|
|
|
catch |
|
|
|
{ |
|
|
|
// ignored
|
|
|
|
} |
|
|
|
|
|
|
|
return Task.CompletedTask; |
|
|
|
} |
|
|
|
|
|
|
|
private bool TryGetSolutionIdFromActivity(ActivityEvent activity, out Guid solutionId) |
|
|
|
{ |
|
|
|
|
|
|
|
if (activity.TryGetValue(ActivityPropertyNames.SolutionId, out var value) && |
|
|
|
Guid.TryParse(value?.ToString(), out var parsedId)) |
|
|
|
{ |
|
|
|
solutionId = parsedId; |
|
|
|
return true; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
solutionId = Guid.Empty; |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
private bool TryGetSolutionIdFromFile(ActivityEvent activity, out Guid solutionId) |
|
|
|
{ |
|
|
|
solutionId = Guid.Empty; |
|
|
|
|
|
|
|
if (!activity.TryGetValue(ActivityPropertyNames.SolutionPath, out var value)) |
|
|
|
{ |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
var path = value?.ToString(); |
|
|
|
if (string.IsNullOrWhiteSpace(path) || !File.Exists(path)) |
|
|
|
{ |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
try |
|
|
|
if (activity.TryGetValue(ActivityPropertyNames.SolutionPath, out var pathValue) && |
|
|
|
pathValue is string && |
|
|
|
File.Exists(pathValue.ToString())) |
|
|
|
{ |
|
|
|
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)) |
|
|
|
try |
|
|
|
{ |
|
|
|
solutionId = parsedId; |
|
|
|
return true; |
|
|
|
var solutionPath = pathValue.ToString()!; |
|
|
|
var json = File.ReadAllText(solutionPath); |
|
|
|
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 |
|
|
|
{ |
|
|
|
// ignored
|
|
|
|
} |
|
|
|
} |
|
|
|
catch |
|
|
|
{ |
|
|
|
// ignored
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
solutionId = Guid.Empty; |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
private void AddSolutionInformation(Dictionary<string, object> activity, JsonElement config) |
|
|
|
private void AddSolutionCreationConfiguration(ActivityEvent activity, JsonElement config) |
|
|
|
{ |
|
|
|
var map = new (string Key, Action<JsonElement> Apply)[] |
|
|
|
{ |
|
|
|
("template", v => activity[ActivityPropertyNames.Template] = v.GetString() ?? string.Empty), |
|
|
|
("createdAbpStudioVersion", v => activity[ActivityPropertyNames.CreatedAbpStudioVersion] = v.GetString()!), |
|
|
|
("multiTenancy", v => activity[ActivityPropertyNames.MultiTenancy] = ParseBool(v)), |
|
|
|
("uiFramework", v => activity[ActivityPropertyNames.UiFramework] = v.GetString() ?? string.Empty), |
|
|
|
("databaseProvider", v => activity[ActivityPropertyNames.DatabaseProvider] = v.GetString() ?? string.Empty), |
|
|
|
("theme", v => activity[ActivityPropertyNames.Theme] = v.GetString() ?? string.Empty), |
|
|
|
("themeStyle", v => activity[ActivityPropertyNames.ThemeStyle] = v.GetString() ?? string.Empty), |
|
|
|
("publicWebsite", v => activity[ActivityPropertyNames.HasPublicWebsite] = ParseBool(v)), |
|
|
|
("tiered", v => activity[ActivityPropertyNames.IsTiered] = ParseBool(v)), |
|
|
|
("socialLogin", v => activity[ActivityPropertyNames.SocialLogins] = ParseBool(v)), |
|
|
|
("databaseManagementSystem", v => activity[ActivityPropertyNames.DatabaseManagementSystem] = v.GetString() ?? string.Empty), |
|
|
|
("separateTenantSchema", v => activity[ActivityPropertyNames.IsSeparateTenantSchema] = ParseBool(v)), |
|
|
|
("mobileFramework", v => activity[ActivityPropertyNames.MobileFramework] = v.GetString() ?? string.Empty), |
|
|
|
("includeTests", v => activity[ActivityPropertyNames.IncludeTests] = ParseBool(v)), |
|
|
|
("dynamicLocalization", v => activity[ActivityPropertyNames.DynamicLocalization] = ParseBool(v)), |
|
|
|
("kubernetesConfiguration", v => activity[ActivityPropertyNames.KubernetesConfiguration] = ParseBool(v)), |
|
|
|
("grafanaDashboard", v => activity[ActivityPropertyNames.GrafanaDashboard] = ParseBool(v)), |
|
|
|
}; |
|
|
|
|
|
|
|
foreach (var (key, apply) in map) |
|
|
|
{ |
|
|
|
if (config.TryGetProperty(key, out var prop)) |
|
|
|
{ |
|
|
|
apply(prop); |
|
|
|
} |
|
|
|
} |
|
|
|
activity[ActivityPropertyNames.Template] = config.GetProperty("template").GetString() ?? string.Empty; |
|
|
|
activity[ActivityPropertyNames.CreatedAbpStudioVersion] = config.GetProperty("createdAbpStudioVersion").GetString()!; |
|
|
|
activity[ActivityPropertyNames.MultiTenancy] = ParseBool(config.GetProperty("multiTenancy")); |
|
|
|
activity[ActivityPropertyNames.UiFramework] = config.GetProperty("uiFramework").GetString() ?? string.Empty; |
|
|
|
activity[ActivityPropertyNames.DatabaseProvider] = config.GetProperty("databaseProvider").GetString() ?? string.Empty; |
|
|
|
activity[ActivityPropertyNames.Theme] = config.GetProperty("theme").GetString() ?? string.Empty; |
|
|
|
activity[ActivityPropertyNames.ThemeStyle] = config.GetProperty("themeStyle").GetString() ?? string.Empty; |
|
|
|
activity[ActivityPropertyNames.HasPublicWebsite] = ParseBool(config.GetProperty("publicWebsite")); |
|
|
|
activity[ActivityPropertyNames.IsTiered] = ParseBool(config.GetProperty("tiered")); |
|
|
|
activity[ActivityPropertyNames.SocialLogins] = ParseBool(config.GetProperty("socialLogin")); |
|
|
|
activity[ActivityPropertyNames.DatabaseManagementSystem] = config.GetProperty("databaseManagementSystem").GetString() ?? string.Empty; |
|
|
|
activity[ActivityPropertyNames.IsSeparateTenantSchema] = ParseBool(config.GetProperty("separateTenantSchema")); |
|
|
|
activity[ActivityPropertyNames.MobileFramework] = config.GetProperty("mobileFramework").GetString() ?? string.Empty; |
|
|
|
activity[ActivityPropertyNames.IncludeTests] = ParseBool(config.GetProperty("includeTests")); |
|
|
|
activity[ActivityPropertyNames.DynamicLocalization] = ParseBool(config.GetProperty("dynamicLocalization")); |
|
|
|
activity[ActivityPropertyNames.KubernetesConfiguration] = ParseBool(config.GetProperty("kubernetesConfiguration")); |
|
|
|
activity[ActivityPropertyNames.GrafanaDashboard] = ParseBool(config.GetProperty("grafanaDashboard")); |
|
|
|
} |
|
|
|
|
|
|
|
private List<Dictionary<string, object>> ExtractModules(string directoryPath, JsonElement modulesElement) |
|
|
|
private List<Dictionary<string, object>> ExtractModules(string solutionPath, 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)) |
|
|
|
var modulePath = GetModuleFilePath(solutionPath, module); |
|
|
|
if (modulePath.IsNullOrEmpty()) |
|
|
|
{ |
|
|
|
continue; |
|
|
|
} |
|
|
|
|
|
|
|
var moduleJson = File.ReadAllText(fullPath); |
|
|
|
var moduleJson = File.ReadAllText(modulePath); |
|
|
|
using var moduleDoc = JsonDocument.Parse(moduleJson); |
|
|
|
|
|
|
|
if (!moduleDoc.RootElement.TryGetProperty("imports", out var imports) || |
|
|
|
@ -201,6 +162,7 @@ public class TelemetrySolutionInfoEnricher : ITelemetryActivityEventEnricher, IS |
|
|
|
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; |
|
|
|
@ -230,6 +192,23 @@ public class TelemetrySolutionInfoEnricher : ITelemetryActivityEventEnricher, IS |
|
|
|
return modules; |
|
|
|
} |
|
|
|
|
|
|
|
private string? GetModuleFilePath(string solutionPath, JsonProperty module) |
|
|
|
{ |
|
|
|
if (!module.Value.TryGetProperty("path", out var pathElement)) |
|
|
|
{ |
|
|
|
return null; |
|
|
|
} |
|
|
|
|
|
|
|
var path = pathElement.GetString(); |
|
|
|
if (path.IsNullOrEmpty()) |
|
|
|
{ |
|
|
|
return null; |
|
|
|
} |
|
|
|
|
|
|
|
var fullPath = Path.Combine(Path.GetDirectoryName(solutionPath)!, path); |
|
|
|
return File.Exists(fullPath) ? fullPath : null; |
|
|
|
} |
|
|
|
|
|
|
|
private bool ParseBool(JsonElement element) |
|
|
|
{ |
|
|
|
return element.ValueKind switch |
|
|
|
|