From d7362bfa2608fd458eaa1f1df66312c8bbd0183a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?SAL=C4=B0H=20=C3=96ZKARA?= Date: Mon, 8 Dec 2025 13:31:23 +0300 Subject: [PATCH 01/19] Add telemetry to CleanCommand execution Introduced ITelemetryService to CleanCommand and now log an activity when the clean command is executed. This enables tracking usage of the clean command for internal telemetry purposes. --- .../Volo/Abp/Cli/Commands/CleanCommand.cs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/CleanCommand.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/CleanCommand.cs index 092e996095..0f973b1ae9 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/CleanCommand.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/CleanCommand.cs @@ -8,6 +8,8 @@ using Microsoft.Extensions.Logging.Abstractions; using Volo.Abp.Cli.Args; using Volo.Abp.Cli.Utils; using Volo.Abp.DependencyInjection; +using Volo.Abp.Internal.Telemetry; +using Volo.Abp.Internal.Telemetry.Constants; namespace Volo.Abp.Cli.Commands; @@ -17,6 +19,8 @@ public class CleanCommand : IConsoleCommand, ITransientDependency public ILogger Logger { get; set; } + public ITelemetryService TelemetryService { get; set; } + protected ICmdHelper CmdHelper { get; } public CleanCommand(ICmdHelper cmdHelper) @@ -25,8 +29,10 @@ public class CleanCommand : IConsoleCommand, ITransientDependency Logger = NullLogger.Instance; } - public Task ExecuteAsync(CommandLineArgs commandLineArgs) + public async Task ExecuteAsync(CommandLineArgs commandLineArgs) { + await TelemetryService.AddActivityAsync(ActivityNameConsts.AbpCliCommandsClean); + var binEntries = Directory.EnumerateDirectories(Directory.GetCurrentDirectory(), "bin", SearchOption.AllDirectories); var objEntries = Directory.EnumerateDirectories(Directory.GetCurrentDirectory(), "obj", SearchOption.AllDirectories); @@ -49,7 +55,6 @@ public class CleanCommand : IConsoleCommand, ITransientDependency Logger.LogInformation($"'bin' and 'obj' folders removed successfully!"); Logger.LogInformation("Solution cleaned successfully!"); - return Task.CompletedTask; } public string GetUsageInfo() From 469fc986110ec1dac708ad3f393604794f1f16ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?SAL=C4=B0H=20=C3=96ZKARA?= Date: Tue, 9 Dec 2025 16:20:15 +0300 Subject: [PATCH 02/19] Integrate telemetry tracking into CLI commands Added telemetry activity tracking to AddModule, AddPackage, Clean, and ListModules commands using ITelemetryService. Introduced TelemetryCliSessionProvider to enrich telemetry session data and updated service registration to remove the default TelemetrySessionInfoEnricher. --- .../Volo/Abp/Cli/AbpCliCoreModule.cs | 4 +++ .../Volo/Abp/Cli/Commands/AddModuleCommand.cs | 13 +++++++- .../Abp/Cli/Commands/AddPackageCommand.cs | 22 ++++++++++--- .../Volo/Abp/Cli/Commands/CleanCommand.cs | 3 +- .../Abp/Cli/Commands/ListModulesCommand.cs | 5 +++ .../Telemetry/TelemetryCliSessionProvider.cs | 32 +++++++++++++++++++ 6 files changed, 72 insertions(+), 7 deletions(-) create mode 100644 framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Telemetry/TelemetryCliSessionProvider.cs diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/AbpCliCoreModule.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/AbpCliCoreModule.cs index 7b249f0517..5f4f6cfaf6 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/AbpCliCoreModule.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/AbpCliCoreModule.cs @@ -1,3 +1,4 @@ +using System.Collections.Generic; using System.Text; using Microsoft.Extensions.DependencyInjection; using Volo.Abp.Cli.Commands; @@ -10,6 +11,7 @@ using Volo.Abp.Cli.ServiceProxying.JavaScript; using Volo.Abp.Domain; using Volo.Abp.Http; using Volo.Abp.IdentityModel; +using Volo.Abp.Internal.Telemetry.Activity.Providers; using Volo.Abp.Json; using Volo.Abp.Localization; using Volo.Abp.Minify; @@ -36,6 +38,8 @@ public class AbpCliCoreModule : AbpModule { client.DefaultRequestHeaders.UserAgent.ParseAdd("MyAgent/1.0"); }); + + context.Services.RemoveAll(x => x.ImplementationType == typeof(TelemetrySessionInfoEnricher)); Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/AddModuleCommand.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/AddModuleCommand.cs index 4756c3f99b..d32498d970 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/AddModuleCommand.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/AddModuleCommand.cs @@ -11,6 +11,8 @@ using Volo.Abp.Cli.ProjectBuilding.Templates.MvcModule; using Volo.Abp.Cli.ProjectModification; using Volo.Abp.Cli.Utils; using Volo.Abp.DependencyInjection; +using Volo.Abp.Internal.Telemetry; +using Volo.Abp.Internal.Telemetry.Constants; namespace Volo.Abp.Cli.Commands; @@ -21,6 +23,7 @@ public class AddModuleCommand : IConsoleCommand, ITransientDependency private AddModuleInfoOutput _lastAddedModuleInfo; public ILogger Logger { get; set; } + public ITelemetryService TelemetryService { get; set; } protected SolutionModuleAdder SolutionModuleAdder { get; } public SolutionPackageVersionFinder SolutionPackageVersionFinder { get; } @@ -66,13 +69,21 @@ public class AddModuleCommand : IConsoleCommand, ITransientDependency } var newTemplate = commandLineArgs.Options.ContainsKey(Options.NewTemplate.Long); + var solutionFile = GetSolutionFile(commandLineArgs); + + await using var _ = TelemetryService.TrackActivityAsync(newTemplate + ? ActivityNameConsts.AbpCliCommandsInstallLocalModule + : ActivityNameConsts.AbpCliCommandsInstallModule, o => + { + o[ActivityPropertyNames.SolutionPath] = solutionFile; + }); + var template = commandLineArgs.Options.GetOrNull(Options.Template.Short, Options.Template.Long); var newProTemplate = !string.IsNullOrEmpty(template) && template == ModuleProTemplate.TemplateName; var withSourceCode = newTemplate || newProTemplate || commandLineArgs.Options.ContainsKey(Options.SourceCode.Long); var addSourceCodeToSolutionFile = withSourceCode && commandLineArgs.Options.ContainsKey("add-to-solution-file"); var skipOpeningDocumentation = commandLineArgs.Options.ContainsKey(Options.SkipOpeningDocumentation.Long); var skipDbMigrations = newTemplate || newProTemplate || commandLineArgs.Options.ContainsKey(Options.DbMigrations.Skip); - var solutionFile = GetSolutionFile(commandLineArgs); var version = commandLineArgs.Options.GetOrNull(Options.Version.Short, Options.Version.Long); if (version == null) diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/AddPackageCommand.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/AddPackageCommand.cs index e9acb7ae24..cbda50602a 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/AddPackageCommand.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/AddPackageCommand.cs @@ -9,6 +9,8 @@ using Volo.Abp.Cli.Args; using Volo.Abp.Cli.ProjectModification; using Volo.Abp.Cli.Utils; using Volo.Abp.DependencyInjection; +using Volo.Abp.Internal.Telemetry; +using Volo.Abp.Internal.Telemetry.Constants; namespace Volo.Abp.Cli.Commands; @@ -17,6 +19,8 @@ public class AddPackageCommand : IConsoleCommand, ITransientDependency public const string Name = "add-package"; public ILogger Logger { get; set; } + + public ITelemetryService TelemetryService { get; set; } protected ProjectNugetPackageAdder ProjectNugetPackageAdder { get; } @@ -51,14 +55,22 @@ public class AddPackageCommand : IConsoleCommand, ITransientDependency var version = commandLineArgs.Options.GetOrNull(Options.Version.Short, Options.Version.Long); var withSourceCode = commandLineArgs.Options.ContainsKey(Options.SourceCode.Long); - + if (isNugetPackage) { var addSourceCodeToSolutionFile = withSourceCode && commandLineArgs.Options.ContainsKey("add-to-solution-file"); - + + var slnFile = GetSolutionFile(commandLineArgs); + var projectFile = GetProjectFile(commandLineArgs); + + await using var _ = TelemetryService.TrackActivityAsync(ActivityNameConsts.AbpCliCommandsAddPackage, o => + { + o[ActivityPropertyNames.SolutionPath] = slnFile; + }); + await ProjectNugetPackageAdder.AddAsync( - GetSolutionFile(commandLineArgs), - GetProjectFile(commandLineArgs), + slnFile, + projectFile, commandLineArgs.Target, version, true, @@ -68,6 +80,8 @@ public class AddPackageCommand : IConsoleCommand, ITransientDependency } else if (isNpmPackage) { + await using var _ = TelemetryService.TrackActivityAsync(ActivityNameConsts.AbpCliCommandsAddPackage); + await ProjectNpmPackageAdder.AddNpmPackageAsync( GetAngularDirectory(commandLineArgs), commandLineArgs.Target, diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/CleanCommand.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/CleanCommand.cs index 0f973b1ae9..886e4faa2b 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/CleanCommand.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/CleanCommand.cs @@ -31,8 +31,7 @@ public class CleanCommand : IConsoleCommand, ITransientDependency public async Task ExecuteAsync(CommandLineArgs commandLineArgs) { - await TelemetryService.AddActivityAsync(ActivityNameConsts.AbpCliCommandsClean); - + await using var _ = TelemetryService.TrackActivityAsync(ActivityNameConsts.AbpCliCommandsClean); var binEntries = Directory.EnumerateDirectories(Directory.GetCurrentDirectory(), "bin", SearchOption.AllDirectories); var objEntries = Directory.EnumerateDirectories(Directory.GetCurrentDirectory(), "obj", SearchOption.AllDirectories); diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/ListModulesCommand.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/ListModulesCommand.cs index af685102d8..4496e62eeb 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/ListModulesCommand.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/ListModulesCommand.cs @@ -7,6 +7,8 @@ using System.Threading.Tasks; using Volo.Abp.Cli.Args; using Volo.Abp.Cli.ProjectBuilding; using Volo.Abp.DependencyInjection; +using Volo.Abp.Internal.Telemetry; +using Volo.Abp.Internal.Telemetry.Constants; namespace Volo.Abp.Cli.Commands; @@ -16,6 +18,7 @@ public class ListModulesCommand : IConsoleCommand, ITransientDependency public ModuleInfoProvider ModuleInfoProvider { get; } public ILogger Logger { get; set; } + public ITelemetryService TelemetryService { get; set; } public ListModulesCommand(ModuleInfoProvider moduleInfoProvider) @@ -26,6 +29,8 @@ public class ListModulesCommand : IConsoleCommand, ITransientDependency public async Task ExecuteAsync(CommandLineArgs commandLineArgs) { + await using var _ = TelemetryService.TrackActivityAsync(ActivityNameConsts.AbpCliCommandsListModules); + var modules = await ModuleInfoProvider.GetModuleListAsync(); var freeModules = modules.Where(m => !m.IsPro).ToList(); var proModules = modules.Where(m => m.IsPro).ToList(); diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Telemetry/TelemetryCliSessionProvider.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Telemetry/TelemetryCliSessionProvider.cs new file mode 100644 index 0000000000..1934f9fc3f --- /dev/null +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Telemetry/TelemetryCliSessionProvider.cs @@ -0,0 +1,32 @@ +using System; +using System.IO; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Internal.Telemetry.Activity; +using Volo.Abp.Internal.Telemetry.Activity.Contracts; +using Volo.Abp.Internal.Telemetry.Activity.Providers; +using Volo.Abp.Internal.Telemetry.Constants; +using Volo.Abp.Internal.Telemetry.Constants.Enums; + +namespace Volo.Abp.Cli.Telemetry; + +[ExposeServices(typeof(ITelemetryActivityEventEnricher))] +public class TelemetryCliSessionProvider : TelemetryActivityEventEnricher +{ + public TelemetryCliSessionProvider(IServiceProvider serviceProvider) : base(serviceProvider) + { + } + + public override int ExecutionOrder { get; set; } = 10; + protected override Type ReplaceParentType { get; set; } = typeof(TelemetrySessionInfoEnricher); + + protected override Task ExecuteAsync(ActivityContext context) + { + context.Current[ActivityPropertyNames.SessionType] = SessionType.AbpCli; + context.Current[ActivityPropertyNames.SessionId] = Guid.NewGuid(); + context.Current[ActivityPropertyNames.IsFirstSession] = !File.Exists(TelemetryPaths.ActivityStorage); + + return Task.CompletedTask; + } + +} \ No newline at end of file From b0a1c0ab0e1e21e4b9baceddbc4149db1d86faa7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?SAL=C4=B0H=20=C3=96ZKARA?= Date: Wed, 10 Dec 2025 09:54:17 +0300 Subject: [PATCH 03/19] Integrate telemetry tracking into CLI commands Added ITelemetryService usage to CliService, NewCommand, and UpdateCommand to track command execution and error activities. This enables better monitoring and diagnostics for CLI operations by reporting activity names and relevant metadata to the telemetry system. --- .../Volo/Abp/Cli/CliService.cs | 7 +++++++ .../Volo/Abp/Cli/Commands/NewCommand.cs | 20 +++++++++++++++++++ .../Volo/Abp/Cli/Commands/UpdateCommand.cs | 4 ++++ 3 files changed, 31 insertions(+) diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/CliService.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/CliService.cs index 0a0c46b6a4..d89b68989b 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/CliService.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/CliService.cs @@ -14,6 +14,8 @@ using Volo.Abp.Cli.Memory; using Volo.Abp.Cli.Version; using Volo.Abp.Cli.Utils; using Volo.Abp.DependencyInjection; +using Volo.Abp.Internal.Telemetry; +using Volo.Abp.Internal.Telemetry.Constants; namespace Volo.Abp.Cli; @@ -21,6 +23,7 @@ public class CliService : ITransientDependency { private readonly MemoryService _memoryService; public ILogger Logger { get; set; } + public ITelemetryService TelemetryService { get; set; } protected ICommandLineArgumentParser CommandLineArgumentParser { get; } protected ICommandSelector CommandSelector { get; } protected IServiceScopeFactory ServiceScopeFactory { get; } @@ -64,6 +67,7 @@ public class CliService : ITransientDependency try { + await using var _ = TelemetryService.TrackActivityAsync(ActivityNameConsts.AbpCliRun); if (commandLineArgs.IsCommand("prompt")) { await RunPromptAsync(); @@ -80,10 +84,13 @@ public class CliService : ITransientDependency catch (CliUsageException usageException) { Logger.LogWarning(usageException.Message); + await TelemetryService.AddActivityAsync(ActivityNameConsts.AbpCliExit); Environment.ExitCode = 1; } catch (Exception ex) { + await TelemetryService.AddErrorActivityAsync(ex.Message); + await TelemetryService.AddActivityAsync(ActivityNameConsts.AbpCliExit); Logger.LogException(ex); throw; } diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs index 796a8ff757..0c8367a7c5 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs @@ -11,11 +11,16 @@ using Volo.Abp.Cli.Commands.Services; using Volo.Abp.Cli.LIbs; using Volo.Abp.Cli.ProjectBuilding; using Volo.Abp.Cli.ProjectBuilding.Events; +using Volo.Abp.Cli.ProjectBuilding.Templates.Module; +using Volo.Abp.Cli.ProjectBuilding.Templates.MvcModule; using Volo.Abp.Cli.ProjectModification; using Volo.Abp.Cli.Utils; using Volo.Abp.Cli.Version; using Volo.Abp.DependencyInjection; using Volo.Abp.EventBus.Local; +using Volo.Abp.Internal.Telemetry; +using Volo.Abp.Internal.Telemetry.Constants; +using Volo.Abp.Internal.Telemetry.Constants.Enums; namespace Volo.Abp.Cli.Commands; @@ -25,6 +30,7 @@ public class NewCommand : ProjectCreationCommandBase, IConsoleCommand, ITransien protected TemplateProjectBuilder TemplateProjectBuilder { get; } public ITemplateInfoProvider TemplateInfoProvider { get; } + public ITelemetryService TelemetryService { get; set; } public NewCommand( ConnectionStringProvider connectionStringProvider, @@ -94,6 +100,20 @@ public class NewCommand : ProjectCreationCommandBase, IConsoleCommand, ITransien var result = await TemplateProjectBuilder.BuildAsync( projectArgs ); + + var activityName = ActivityNameConsts.AbpCliCommandsNewSolution; + + if (ModuleTemplateBase.IsModuleTemplate(template)) + { + activityName = ActivityNameConsts.AbpCliCommandsNewModule; + } + + await TelemetryService.AddActivityAsync(activityName, o => + { + o[ActivityPropertyNames.CreationTool] = AbpTool.OldCli; + o[ActivityPropertyNames.Template] = template; + o[ActivityPropertyNames.SolutionPath] = projectArgs.OutputFolder; + }); ExtractProjectZip(result, projectArgs.OutputFolder); diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/UpdateCommand.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/UpdateCommand.cs index ae3cda8723..f46dd79f5e 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/UpdateCommand.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/UpdateCommand.cs @@ -9,6 +9,8 @@ using Microsoft.Extensions.Logging.Abstractions; using Volo.Abp.Cli.Args; using Volo.Abp.Cli.ProjectModification; using Volo.Abp.DependencyInjection; +using Volo.Abp.Internal.Telemetry; +using Volo.Abp.Internal.Telemetry.Constants; namespace Volo.Abp.Cli.Commands; @@ -17,6 +19,7 @@ public class UpdateCommand : IConsoleCommand, ITransientDependency public const string Name = "update"; public ILogger Logger { get; set; } + public ITelemetryService TelemetryService { get; set; } private readonly VoloNugetPackagesVersionUpdater _nugetPackagesVersionUpdater; private readonly NpmPackagesUpdater _npmPackagesUpdater; @@ -32,6 +35,7 @@ public class UpdateCommand : IConsoleCommand, ITransientDependency public async Task ExecuteAsync(CommandLineArgs commandLineArgs) { + await using var _ = TelemetryService.TrackActivityAsync(ActivityNameConsts.AbpCliCommandsUpdate); var updateNpm = commandLineArgs.Options.ContainsKey(Options.Packages.Npm); var updateNuget = commandLineArgs.Options.ContainsKey(Options.Packages.NuGet); From 39ad3e6d3380f80ad771304d8cd3eecd68e7eb96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?SAL=C4=B0H=20=C3=96ZKARA?= Date: Wed, 10 Dec 2025 13:18:12 +0300 Subject: [PATCH 04/19] Improve telemetry solution path handling and enrichment Refactored telemetry logic to better handle and enrich solution path information, including moving TelemetryCliSessionProvider, updating activity tracking in commands, and enhancing TelemetrySolutionInfoEnricher to reliably find and set solution paths and IDs. Removed redundant service registrations and improved the order and conditions for telemetry activities. --- .../Volo/Abp/Cli/AbpCliCoreModule.cs | 2 - .../Volo/Abp/Cli/CliService.cs | 3 +- .../Abp/Cli/Commands/AddPackageCommand.cs | 10 +--- .../Volo/Abp/Cli/Commands/NewCommand.cs | 1 - .../Volo.Abp.Cli/Volo/Abp/Cli/AbpCliModule.cs | 9 ++- .../Telemetry/TelemetryCliSessionProvider.cs | 21 ++++++- .../TelemetrySolutionInfoEnricher.cs | 57 ++++++++++++++++++- .../Activity/TelemetryJsonExtensions.cs | 10 ++++ 8 files changed, 97 insertions(+), 16 deletions(-) rename framework/src/{Volo.Abp.Cli.Core => Volo.Abp.Cli}/Volo/Abp/Cli/Telemetry/TelemetryCliSessionProvider.cs (51%) diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/AbpCliCoreModule.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/AbpCliCoreModule.cs index 5f4f6cfaf6..cea7a38b8b 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/AbpCliCoreModule.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/AbpCliCoreModule.cs @@ -38,8 +38,6 @@ public class AbpCliCoreModule : AbpModule { client.DefaultRequestHeaders.UserAgent.ParseAdd("MyAgent/1.0"); }); - - context.Services.RemoveAll(x => x.ImplementationType == typeof(TelemetrySessionInfoEnricher)); Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/CliService.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/CliService.cs index d89b68989b..7f5f3224e6 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/CliService.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/CliService.cs @@ -84,7 +84,6 @@ public class CliService : ITransientDependency catch (CliUsageException usageException) { Logger.LogWarning(usageException.Message); - await TelemetryService.AddActivityAsync(ActivityNameConsts.AbpCliExit); Environment.ExitCode = 1; } catch (Exception ex) @@ -94,6 +93,8 @@ public class CliService : ITransientDependency Logger.LogException(ex); throw; } + + await TelemetryService.AddActivityAsync(ActivityNameConsts.AbpCliExit); } private async Task RunPromptAsync() diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/AddPackageCommand.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/AddPackageCommand.cs index cbda50602a..4cec1023b3 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/AddPackageCommand.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/AddPackageCommand.cs @@ -43,6 +43,9 @@ public class AddPackageCommand : IConsoleCommand, ITransientDependency GetUsageInfo() ); } + + await using var _ = TelemetryService.TrackActivityAsync(ActivityNameConsts.AbpCliCommandsNewPackage); + await using var __ = TelemetryService.TrackActivityAsync(ActivityNameConsts.AbpCliCommandsAddPackage); var isNpmPackage = false; var isNugetPackage = true; @@ -63,11 +66,6 @@ public class AddPackageCommand : IConsoleCommand, ITransientDependency var slnFile = GetSolutionFile(commandLineArgs); var projectFile = GetProjectFile(commandLineArgs); - await using var _ = TelemetryService.TrackActivityAsync(ActivityNameConsts.AbpCliCommandsAddPackage, o => - { - o[ActivityPropertyNames.SolutionPath] = slnFile; - }); - await ProjectNugetPackageAdder.AddAsync( slnFile, projectFile, @@ -80,8 +78,6 @@ public class AddPackageCommand : IConsoleCommand, ITransientDependency } else if (isNpmPackage) { - await using var _ = TelemetryService.TrackActivityAsync(ActivityNameConsts.AbpCliCommandsAddPackage); - await ProjectNpmPackageAdder.AddNpmPackageAsync( GetAngularDirectory(commandLineArgs), commandLineArgs.Target, diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs index 0c8367a7c5..ac932dae67 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs @@ -112,7 +112,6 @@ public class NewCommand : ProjectCreationCommandBase, IConsoleCommand, ITransien { o[ActivityPropertyNames.CreationTool] = AbpTool.OldCli; o[ActivityPropertyNames.Template] = template; - o[ActivityPropertyNames.SolutionPath] = projectArgs.OutputFolder; }); ExtractProjectZip(result, projectArgs.OutputFolder); diff --git a/framework/src/Volo.Abp.Cli/Volo/Abp/Cli/AbpCliModule.cs b/framework/src/Volo.Abp.Cli/Volo/Abp/Cli/AbpCliModule.cs index c782eadd52..d1b30d34b5 100644 --- a/framework/src/Volo.Abp.Cli/Volo/Abp/Cli/AbpCliModule.cs +++ b/framework/src/Volo.Abp.Cli/Volo/Abp/Cli/AbpCliModule.cs @@ -1,4 +1,6 @@ -using Volo.Abp.Autofac; +using System.Collections.Generic; +using Volo.Abp.Autofac; +using Volo.Abp.Internal.Telemetry.Activity.Providers; using Volo.Abp.Modularity; namespace Volo.Abp.Cli; @@ -9,5 +11,8 @@ namespace Volo.Abp.Cli; )] public class AbpCliModule : AbpModule { - + public override void ConfigureServices(ServiceConfigurationContext context) + { + context.Services.RemoveAll(x => x.ImplementationType == typeof(TelemetrySessionInfoEnricher)); + } } diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Telemetry/TelemetryCliSessionProvider.cs b/framework/src/Volo.Abp.Cli/Volo/Abp/Cli/Telemetry/TelemetryCliSessionProvider.cs similarity index 51% rename from framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Telemetry/TelemetryCliSessionProvider.cs rename to framework/src/Volo.Abp.Cli/Volo/Abp/Cli/Telemetry/TelemetryCliSessionProvider.cs index 1934f9fc3f..807b94f5e4 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Telemetry/TelemetryCliSessionProvider.cs +++ b/framework/src/Volo.Abp.Cli/Volo/Abp/Cli/Telemetry/TelemetryCliSessionProvider.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.IO; using System.Threading.Tasks; using Volo.Abp.DependencyInjection; @@ -18,13 +19,31 @@ public class TelemetryCliSessionProvider : TelemetryActivityEventEnricher } public override int ExecutionOrder { get; set; } = 10; - protected override Type ReplaceParentType { get; set; } = typeof(TelemetrySessionInfoEnricher); + protected override Type? ReplaceParentType { get; set; } = typeof(TelemetrySessionInfoEnricher); protected override Task ExecuteAsync(ActivityContext context) { context.Current[ActivityPropertyNames.SessionType] = SessionType.AbpCli; context.Current[ActivityPropertyNames.SessionId] = Guid.NewGuid(); context.Current[ActivityPropertyNames.IsFirstSession] = !File.Exists(TelemetryPaths.ActivityStorage); + + if (context.ExtraProperties.ContainsKey(ActivityPropertyNames.SolutionPath)) + { + return Task.CompletedTask; + } + + if(context.Current.TryGetValue(ActivityPropertyNames.SolutionPath, out var existingSolutionPath) && existingSolutionPath is string) + { + context.ExtraProperties[ActivityPropertyNames.SolutionPath] = existingSolutionPath; + return Task.CompletedTask; + } + + if (context.Current.TryGetValue(ActivityPropertyNames.AdditionalProperties, out var additionalProperties) && + additionalProperties is Dictionary additionalPropertiesDict && + additionalPropertiesDict.TryGetValue(ActivityPropertyNames.SolutionPath, out var solutionPath)) + { + context.ExtraProperties[ActivityPropertyNames.SolutionPath] = solutionPath; + } return Task.CompletedTask; } diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/Internal/Telemetry/Activity/Providers/TelemetrySolutionInfoEnricher.cs b/framework/src/Volo.Abp.Core/Volo/Abp/Internal/Telemetry/Activity/Providers/TelemetrySolutionInfoEnricher.cs index c57d51e6f2..f39b3babd8 100644 --- a/framework/src/Volo.Abp.Core/Volo/Abp/Internal/Telemetry/Activity/Providers/TelemetrySolutionInfoEnricher.cs +++ b/framework/src/Volo.Abp.Core/Volo/Abp/Internal/Telemetry/Activity/Providers/TelemetrySolutionInfoEnricher.cs @@ -21,12 +21,17 @@ internal sealed class TelemetrySolutionInfoEnricher : TelemetryActivityEventEnri protected override Task CanExecuteAsync(ActivityContext context) { - if (context.SolutionId.HasValue && !context.SolutionPath.IsNullOrEmpty()) + if (context.SolutionPath.IsNullOrEmpty()) + { + return Task.FromResult(false); + } + + if (context.SolutionId.HasValue) { return Task.FromResult(_telemetryActivityStorage.ShouldAddSolutionInformation(context.SolutionId.Value)); } - return Task.FromResult(false); + return Task.FromResult(true); } protected override Task ExecuteAsync(ActivityContext context) @@ -37,6 +42,14 @@ internal sealed class TelemetrySolutionInfoEnricher : TelemetryActivityEventEnri { return Task.CompletedTask; } + + var correctSolutionPath = FindCorrectSolutionPath(context.SolutionPath); + if (correctSolutionPath.IsNullOrEmpty()) + { + return Task.CompletedTask; + } + + context.ExtraProperties[ActivityPropertyNames.SolutionPath] = correctSolutionPath; var jsonContent = File.ReadAllText(context.SolutionPath!); using var doc = JsonDocument.Parse(jsonContent, new JsonDocumentOptions @@ -45,6 +58,15 @@ internal sealed class TelemetrySolutionInfoEnricher : TelemetryActivityEventEnri }); var root = doc.RootElement; + + var solutionId = TelemetryJsonExtensions.GetGuidOrNull(root, "id"); + + if (!solutionId.HasValue) + { + return Task.CompletedTask; + } + + context.Current[ActivityPropertyNames.SolutionId] = solutionId; if (root.TryGetProperty("versions", out var versions)) { @@ -149,4 +171,35 @@ internal sealed class TelemetrySolutionInfoEnricher : TelemetryActivityEventEnri var fullPath = Path.Combine(Path.GetDirectoryName(solutionPath)!, path); return File.Exists(fullPath) ? fullPath : null; } + + private static string? FindCorrectSolutionPath(string solutionPath) + { + if (solutionPath.EndsWith(".abpsln")) + { + return solutionPath; + } + + if (solutionPath.EndsWith(".sln")) + { + solutionPath = solutionPath[..^4] + ".abpsln"; + if (File.Exists(solutionPath)) + { + return solutionPath; + } + } + + var dir = Path.GetDirectoryName(solutionPath); + if (dir.IsNullOrEmpty()) + { + return null; + } + + var abpSolutionFiles = Directory.GetFiles(dir, "*.abpsln", SearchOption.TopDirectoryOnly); + + return abpSolutionFiles.Length switch + { + 1 => abpSolutionFiles[0], + _ => null + }; + } } \ No newline at end of file diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/Internal/Telemetry/Activity/TelemetryJsonExtensions.cs b/framework/src/Volo.Abp.Core/Volo/Abp/Internal/Telemetry/Activity/TelemetryJsonExtensions.cs index 6f8b5c2a10..f822f72f18 100644 --- a/framework/src/Volo.Abp.Core/Volo/Abp/Internal/Telemetry/Activity/TelemetryJsonExtensions.cs +++ b/framework/src/Volo.Abp.Core/Volo/Abp/Internal/Telemetry/Activity/TelemetryJsonExtensions.cs @@ -31,4 +31,14 @@ static internal class TelemetryJsonExtensions return null; } + + static internal Guid? GetGuidOrNull(JsonElement element, string propertyName) + { + if (element.TryGetProperty(propertyName, out var guidProperty) && Guid.TryParse(guidProperty.GetString(), out var guidValue)) + { + return guidValue; + } + + return null; + } } \ No newline at end of file From 144d3d3f885641d80f2746a13681aee1107929c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?SAL=C4=B0H=20=C3=96ZKARA?= Date: Wed, 10 Dec 2025 13:25:36 +0300 Subject: [PATCH 05/19] Improve solution file handling and cleanup unused usings Removed unused using directives in AbpCliCoreModule and NewCommand for better code clarity. Refactored AddPackageCommand to inline solution and project file retrieval. Enhanced TelemetrySolutionInfoEnricher to support '.slnx' files by mapping them to '.abpsln' if present. --- .../Volo.Abp.Cli.Core/Volo/Abp/Cli/AbpCliCoreModule.cs | 2 -- .../Volo/Abp/Cli/Commands/AddPackageCommand.cs | 7 ++----- .../Volo/Abp/Cli/Commands/NewCommand.cs | 1 - .../Activity/Providers/TelemetrySolutionInfoEnricher.cs | 9 +++++++++ 4 files changed, 11 insertions(+), 8 deletions(-) diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/AbpCliCoreModule.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/AbpCliCoreModule.cs index cea7a38b8b..7b249f0517 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/AbpCliCoreModule.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/AbpCliCoreModule.cs @@ -1,4 +1,3 @@ -using System.Collections.Generic; using System.Text; using Microsoft.Extensions.DependencyInjection; using Volo.Abp.Cli.Commands; @@ -11,7 +10,6 @@ using Volo.Abp.Cli.ServiceProxying.JavaScript; using Volo.Abp.Domain; using Volo.Abp.Http; using Volo.Abp.IdentityModel; -using Volo.Abp.Internal.Telemetry.Activity.Providers; using Volo.Abp.Json; using Volo.Abp.Localization; using Volo.Abp.Minify; diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/AddPackageCommand.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/AddPackageCommand.cs index 4cec1023b3..a8fbdb8840 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/AddPackageCommand.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/AddPackageCommand.cs @@ -63,12 +63,9 @@ public class AddPackageCommand : IConsoleCommand, ITransientDependency { var addSourceCodeToSolutionFile = withSourceCode && commandLineArgs.Options.ContainsKey("add-to-solution-file"); - var slnFile = GetSolutionFile(commandLineArgs); - var projectFile = GetProjectFile(commandLineArgs); - await ProjectNugetPackageAdder.AddAsync( - slnFile, - projectFile, + GetSolutionFile(commandLineArgs), + GetProjectFile(commandLineArgs), commandLineArgs.Target, version, true, diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs index ac932dae67..4d02472d27 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs @@ -12,7 +12,6 @@ using Volo.Abp.Cli.LIbs; using Volo.Abp.Cli.ProjectBuilding; using Volo.Abp.Cli.ProjectBuilding.Events; using Volo.Abp.Cli.ProjectBuilding.Templates.Module; -using Volo.Abp.Cli.ProjectBuilding.Templates.MvcModule; using Volo.Abp.Cli.ProjectModification; using Volo.Abp.Cli.Utils; using Volo.Abp.Cli.Version; diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/Internal/Telemetry/Activity/Providers/TelemetrySolutionInfoEnricher.cs b/framework/src/Volo.Abp.Core/Volo/Abp/Internal/Telemetry/Activity/Providers/TelemetrySolutionInfoEnricher.cs index f39b3babd8..38d68f3f71 100644 --- a/framework/src/Volo.Abp.Core/Volo/Abp/Internal/Telemetry/Activity/Providers/TelemetrySolutionInfoEnricher.cs +++ b/framework/src/Volo.Abp.Core/Volo/Abp/Internal/Telemetry/Activity/Providers/TelemetrySolutionInfoEnricher.cs @@ -188,6 +188,15 @@ internal sealed class TelemetrySolutionInfoEnricher : TelemetryActivityEventEnri } } + if (solutionPath.EndsWith(".slnx")) + { + solutionPath = solutionPath[..^5] + ".abpsln"; + if (File.Exists(solutionPath)) + { + return solutionPath; + } + } + var dir = Path.GetDirectoryName(solutionPath); if (dir.IsNullOrEmpty()) { From b60604789913ac197267f3fb0f283fa0584055d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?SAL=C4=B0H=20=C3=96ZKARA?= Date: Wed, 10 Dec 2025 13:27:58 +0300 Subject: [PATCH 06/19] Move AbpCliExit telemetry to finally block Ensures that the AbpCliExit activity is always logged by moving the telemetry call to a finally block, regardless of whether an exception occurs. --- framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/CliService.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/CliService.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/CliService.cs index 7f5f3224e6..c514236bd7 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/CliService.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/CliService.cs @@ -89,12 +89,13 @@ public class CliService : ITransientDependency catch (Exception ex) { await TelemetryService.AddErrorActivityAsync(ex.Message); - await TelemetryService.AddActivityAsync(ActivityNameConsts.AbpCliExit); Logger.LogException(ex); throw; } - - await TelemetryService.AddActivityAsync(ActivityNameConsts.AbpCliExit); + finally + { + await TelemetryService.AddActivityAsync(ActivityNameConsts.AbpCliExit); + } } private async Task RunPromptAsync() From d7def2007f445f0d1e7186446bce4aa5c1b708cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?SAL=C4=B0H=20=C3=96ZKARA?= Date: Wed, 10 Dec 2025 13:35:31 +0300 Subject: [PATCH 07/19] Refactor solution path retrieval in telemetry context Moved solution path lookup logic from TelemetryCliSessionProvider to ActivityContext via a new TryGetValue method, simplifying property access and reducing duplication. --- .../Telemetry/TelemetryCliSessionProvider.cs | 19 --------------- .../Telemetry/Activity/ActivityContext.cs | 24 ++++++++++++++++++- 2 files changed, 23 insertions(+), 20 deletions(-) diff --git a/framework/src/Volo.Abp.Cli/Volo/Abp/Cli/Telemetry/TelemetryCliSessionProvider.cs b/framework/src/Volo.Abp.Cli/Volo/Abp/Cli/Telemetry/TelemetryCliSessionProvider.cs index 807b94f5e4..0126f329ef 100644 --- a/framework/src/Volo.Abp.Cli/Volo/Abp/Cli/Telemetry/TelemetryCliSessionProvider.cs +++ b/framework/src/Volo.Abp.Cli/Volo/Abp/Cli/Telemetry/TelemetryCliSessionProvider.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using System.IO; using System.Threading.Tasks; using Volo.Abp.DependencyInjection; @@ -26,24 +25,6 @@ public class TelemetryCliSessionProvider : TelemetryActivityEventEnricher context.Current[ActivityPropertyNames.SessionType] = SessionType.AbpCli; context.Current[ActivityPropertyNames.SessionId] = Guid.NewGuid(); context.Current[ActivityPropertyNames.IsFirstSession] = !File.Exists(TelemetryPaths.ActivityStorage); - - if (context.ExtraProperties.ContainsKey(ActivityPropertyNames.SolutionPath)) - { - return Task.CompletedTask; - } - - if(context.Current.TryGetValue(ActivityPropertyNames.SolutionPath, out var existingSolutionPath) && existingSolutionPath is string) - { - context.ExtraProperties[ActivityPropertyNames.SolutionPath] = existingSolutionPath; - return Task.CompletedTask; - } - - if (context.Current.TryGetValue(ActivityPropertyNames.AdditionalProperties, out var additionalProperties) && - additionalProperties is Dictionary additionalPropertiesDict && - additionalPropertiesDict.TryGetValue(ActivityPropertyNames.SolutionPath, out var solutionPath)) - { - context.ExtraProperties[ActivityPropertyNames.SolutionPath] = solutionPath; - } return Task.CompletedTask; } diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/Internal/Telemetry/Activity/ActivityContext.cs b/framework/src/Volo.Abp.Core/Volo/Abp/Internal/Telemetry/Activity/ActivityContext.cs index 8a03a66e65..7c232671e7 100644 --- a/framework/src/Volo.Abp.Core/Volo/Abp/Internal/Telemetry/Activity/ActivityContext.cs +++ b/framework/src/Volo.Abp.Core/Volo/Abp/Internal/Telemetry/Activity/ActivityContext.cs @@ -19,7 +19,7 @@ public class ActivityContext public string? DeviceId => Current.Get(ActivityPropertyNames.DeviceId); - public string? SolutionPath => ExtraProperties.TryGetValue(ActivityPropertyNames.SolutionPath, out var solutionPath) + public string? SolutionPath => TryGetValue(ActivityPropertyNames.SolutionPath, out var solutionPath) ? solutionPath?.ToString() : null; @@ -42,6 +42,28 @@ public class ActivityContext return new ActivityContext(activity); } + + public bool TryGetValue(string key, out object? value) + { + if (Current.TryGetValue(key, out value)) + { + return true; + } + + if (ExtraProperties.TryGetValue(key, out value)) + { + return true; + } + + if (Current.TryGetValue(ActivityPropertyNames.AdditionalProperties, out var additionalProperties) && + additionalProperties is Dictionary additionalPropertiesDict && + additionalPropertiesDict.TryGetValue(key, out value)) + { + return true; + } + + return false; + } public void Terminate() { From ba71174d5e81b8b3379539a459b81edde42ff1d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?SAL=C4=B0H=20=C3=96ZKARA?= Date: Wed, 10 Dec 2025 14:45:30 +0300 Subject: [PATCH 08/19] Update TelemetrySolutionInfoEnricher.cs --- .../Activity/Providers/TelemetrySolutionInfoEnricher.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/Internal/Telemetry/Activity/Providers/TelemetrySolutionInfoEnricher.cs b/framework/src/Volo.Abp.Core/Volo/Abp/Internal/Telemetry/Activity/Providers/TelemetrySolutionInfoEnricher.cs index 38d68f3f71..97e487585a 100644 --- a/framework/src/Volo.Abp.Core/Volo/Abp/Internal/Telemetry/Activity/Providers/TelemetrySolutionInfoEnricher.cs +++ b/framework/src/Volo.Abp.Core/Volo/Abp/Internal/Telemetry/Activity/Providers/TelemetrySolutionInfoEnricher.cs @@ -181,7 +181,7 @@ internal sealed class TelemetrySolutionInfoEnricher : TelemetryActivityEventEnri if (solutionPath.EndsWith(".sln")) { - solutionPath = solutionPath[..^4] + ".abpsln"; + solutionPath = solutionPath.RemovePostFix(".sln") + ".abpsln"; if (File.Exists(solutionPath)) { return solutionPath; @@ -190,7 +190,7 @@ internal sealed class TelemetrySolutionInfoEnricher : TelemetryActivityEventEnri if (solutionPath.EndsWith(".slnx")) { - solutionPath = solutionPath[..^5] + ".abpsln"; + solutionPath = solutionPath.RemovePostFix(".slnx") + ".abpsln"; if (File.Exists(solutionPath)) { return solutionPath; From 3cab27772c940ef4384a1cb2012030f462b54127 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?SAL=C4=B0H=20=C3=96ZKARA?= Date: Wed, 10 Dec 2025 15:24:24 +0300 Subject: [PATCH 09/19] Add SetSolutionPath method and refactor solution path handling Introduced SetSolutionPath to ActivityContext for consistent solution path updates. Refactored TelemetrySolutionInfoEnricher to use the new method and improved logic for resolving .abpsln files based on possible extensions. --- .../Telemetry/Activity/ActivityContext.cs | 24 +++++++++++ .../TelemetrySolutionInfoEnricher.cs | 40 +++++++------------ 2 files changed, 39 insertions(+), 25 deletions(-) diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/Internal/Telemetry/Activity/ActivityContext.cs b/framework/src/Volo.Abp.Core/Volo/Abp/Internal/Telemetry/Activity/ActivityContext.cs index 7c232671e7..f6bb8e7e50 100644 --- a/framework/src/Volo.Abp.Core/Volo/Abp/Internal/Telemetry/Activity/ActivityContext.cs +++ b/framework/src/Volo.Abp.Core/Volo/Abp/Internal/Telemetry/Activity/ActivityContext.cs @@ -65,6 +65,30 @@ public class ActivityContext return false; } + public void SetSolutionPath(string solutionPath) + { + if (solutionPath == SolutionPath) + { + return; + } + + ExtraProperties[ActivityPropertyNames.SolutionPath] = solutionPath; + + if(Current.ContainsKey(ActivityPropertyNames.SolutionPath)) + { + Current[ActivityPropertyNames.SolutionPath] = solutionPath; + } + + if (Current.TryGetValue(ActivityPropertyNames.AdditionalProperties, out var additionalPropertiesObj) && + additionalPropertiesObj is Dictionary additionalPropertiesDict) + { + if (additionalPropertiesDict.ContainsKey(ActivityPropertyNames.SolutionPath)) + { + additionalPropertiesDict[ActivityPropertyNames.SolutionPath] = solutionPath; + } + } + } + public void Terminate() { IsTerminated = true; diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/Internal/Telemetry/Activity/Providers/TelemetrySolutionInfoEnricher.cs b/framework/src/Volo.Abp.Core/Volo/Abp/Internal/Telemetry/Activity/Providers/TelemetrySolutionInfoEnricher.cs index 97e487585a..97a2eba926 100644 --- a/framework/src/Volo.Abp.Core/Volo/Abp/Internal/Telemetry/Activity/Providers/TelemetrySolutionInfoEnricher.cs +++ b/framework/src/Volo.Abp.Core/Volo/Abp/Internal/Telemetry/Activity/Providers/TelemetrySolutionInfoEnricher.cs @@ -49,7 +49,7 @@ internal sealed class TelemetrySolutionInfoEnricher : TelemetryActivityEventEnri return Task.CompletedTask; } - context.ExtraProperties[ActivityPropertyNames.SolutionPath] = correctSolutionPath; + context.SetSolutionPath(correctSolutionPath); var jsonContent = File.ReadAllText(context.SolutionPath!); using var doc = JsonDocument.Parse(jsonContent, new JsonDocumentOptions @@ -178,37 +178,27 @@ internal sealed class TelemetrySolutionInfoEnricher : TelemetryActivityEventEnri { return solutionPath; } + + var possibleExtensions = new[] + { + ".sln", + ".slnx" + }; - if (solutionPath.EndsWith(".sln")) + foreach (var extension in possibleExtensions) { - solutionPath = solutionPath.RemovePostFix(".sln") + ".abpsln"; - if (File.Exists(solutionPath)) + if (!solutionPath.EndsWith(extension)) { - return solutionPath; + continue; } - } - - if (solutionPath.EndsWith(".slnx")) - { - solutionPath = solutionPath.RemovePostFix(".slnx") + ".abpsln"; - if (File.Exists(solutionPath)) + + var abpSlnPath = solutionPath.Substring(0, solutionPath.Length - extension.Length) + ".abpsln"; + if (File.Exists(abpSlnPath)) { - return solutionPath; + return abpSlnPath; } } - - var dir = Path.GetDirectoryName(solutionPath); - if (dir.IsNullOrEmpty()) - { - return null; - } - - var abpSolutionFiles = Directory.GetFiles(dir, "*.abpsln", SearchOption.TopDirectoryOnly); - return abpSolutionFiles.Length switch - { - 1 => abpSolutionFiles[0], - _ => null - }; + return null; } } \ No newline at end of file From b8abda680020cde94969200ab7f6a60bcc87f611 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?SAL=C4=B0H=20=C3=96ZKARA?= Date: Wed, 10 Dec 2025 15:25:28 +0300 Subject: [PATCH 10/19] Refactor telemetry activity initialization in AddModuleCommand Moved solutionFile assignment to after telemetry activity tracking and removed passing solutionFile as a telemetry property. This streamlines the activity initialization and improves code clarity. --- .../Volo/Abp/Cli/Commands/AddModuleCommand.cs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/AddModuleCommand.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/AddModuleCommand.cs index d32498d970..204882a597 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/AddModuleCommand.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/AddModuleCommand.cs @@ -69,14 +69,10 @@ public class AddModuleCommand : IConsoleCommand, ITransientDependency } var newTemplate = commandLineArgs.Options.ContainsKey(Options.NewTemplate.Long); - var solutionFile = GetSolutionFile(commandLineArgs); await using var _ = TelemetryService.TrackActivityAsync(newTemplate ? ActivityNameConsts.AbpCliCommandsInstallLocalModule - : ActivityNameConsts.AbpCliCommandsInstallModule, o => - { - o[ActivityPropertyNames.SolutionPath] = solutionFile; - }); + : ActivityNameConsts.AbpCliCommandsInstallModule); var template = commandLineArgs.Options.GetOrNull(Options.Template.Short, Options.Template.Long); var newProTemplate = !string.IsNullOrEmpty(template) && template == ModuleProTemplate.TemplateName; @@ -84,6 +80,7 @@ public class AddModuleCommand : IConsoleCommand, ITransientDependency var addSourceCodeToSolutionFile = withSourceCode && commandLineArgs.Options.ContainsKey("add-to-solution-file"); var skipOpeningDocumentation = commandLineArgs.Options.ContainsKey(Options.SkipOpeningDocumentation.Long); var skipDbMigrations = newTemplate || newProTemplate || commandLineArgs.Options.ContainsKey(Options.DbMigrations.Skip); + var solutionFile = GetSolutionFile(commandLineArgs); var version = commandLineArgs.Options.GetOrNull(Options.Version.Short, Options.Version.Long); if (version == null) From 7a9e5afff023ae092ebadac41e17b50bd538c661 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?SAL=C4=B0H=20=C3=96ZKARA?= Date: Wed, 10 Dec 2025 15:30:03 +0300 Subject: [PATCH 11/19] Remove unnecessary blank line at end of file Cleaned up TelemetryCliSessionProvider.cs by deleting an extraneous blank line at the end of the file. --- .../Volo/Abp/Cli/Telemetry/TelemetryCliSessionProvider.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/framework/src/Volo.Abp.Cli/Volo/Abp/Cli/Telemetry/TelemetryCliSessionProvider.cs b/framework/src/Volo.Abp.Cli/Volo/Abp/Cli/Telemetry/TelemetryCliSessionProvider.cs index 0126f329ef..030a9f83db 100644 --- a/framework/src/Volo.Abp.Cli/Volo/Abp/Cli/Telemetry/TelemetryCliSessionProvider.cs +++ b/framework/src/Volo.Abp.Cli/Volo/Abp/Cli/Telemetry/TelemetryCliSessionProvider.cs @@ -28,5 +28,4 @@ public class TelemetryCliSessionProvider : TelemetryActivityEventEnricher return Task.CompletedTask; } - } \ No newline at end of file From 55a511f10fa384cb55d3a30b56aed34c99414600 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?SAL=C4=B0H=20=C3=96ZKARA?= Date: Wed, 10 Dec 2025 15:37:40 +0300 Subject: [PATCH 12/19] revert changes --- .../Telemetry/Activity/ActivityContext.cs | 48 +--------------- .../TelemetrySolutionInfoEnricher.cs | 56 +------------------ .../Activity/TelemetryJsonExtensions.cs | 10 ---- 3 files changed, 3 insertions(+), 111 deletions(-) diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/Internal/Telemetry/Activity/ActivityContext.cs b/framework/src/Volo.Abp.Core/Volo/Abp/Internal/Telemetry/Activity/ActivityContext.cs index f6bb8e7e50..8a03a66e65 100644 --- a/framework/src/Volo.Abp.Core/Volo/Abp/Internal/Telemetry/Activity/ActivityContext.cs +++ b/framework/src/Volo.Abp.Core/Volo/Abp/Internal/Telemetry/Activity/ActivityContext.cs @@ -19,7 +19,7 @@ public class ActivityContext public string? DeviceId => Current.Get(ActivityPropertyNames.DeviceId); - public string? SolutionPath => TryGetValue(ActivityPropertyNames.SolutionPath, out var solutionPath) + public string? SolutionPath => ExtraProperties.TryGetValue(ActivityPropertyNames.SolutionPath, out var solutionPath) ? solutionPath?.ToString() : null; @@ -42,52 +42,6 @@ public class ActivityContext return new ActivityContext(activity); } - - public bool TryGetValue(string key, out object? value) - { - if (Current.TryGetValue(key, out value)) - { - return true; - } - - if (ExtraProperties.TryGetValue(key, out value)) - { - return true; - } - - if (Current.TryGetValue(ActivityPropertyNames.AdditionalProperties, out var additionalProperties) && - additionalProperties is Dictionary additionalPropertiesDict && - additionalPropertiesDict.TryGetValue(key, out value)) - { - return true; - } - - return false; - } - - public void SetSolutionPath(string solutionPath) - { - if (solutionPath == SolutionPath) - { - return; - } - - ExtraProperties[ActivityPropertyNames.SolutionPath] = solutionPath; - - if(Current.ContainsKey(ActivityPropertyNames.SolutionPath)) - { - Current[ActivityPropertyNames.SolutionPath] = solutionPath; - } - - if (Current.TryGetValue(ActivityPropertyNames.AdditionalProperties, out var additionalPropertiesObj) && - additionalPropertiesObj is Dictionary additionalPropertiesDict) - { - if (additionalPropertiesDict.ContainsKey(ActivityPropertyNames.SolutionPath)) - { - additionalPropertiesDict[ActivityPropertyNames.SolutionPath] = solutionPath; - } - } - } public void Terminate() { diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/Internal/Telemetry/Activity/Providers/TelemetrySolutionInfoEnricher.cs b/framework/src/Volo.Abp.Core/Volo/Abp/Internal/Telemetry/Activity/Providers/TelemetrySolutionInfoEnricher.cs index 97a2eba926..c57d51e6f2 100644 --- a/framework/src/Volo.Abp.Core/Volo/Abp/Internal/Telemetry/Activity/Providers/TelemetrySolutionInfoEnricher.cs +++ b/framework/src/Volo.Abp.Core/Volo/Abp/Internal/Telemetry/Activity/Providers/TelemetrySolutionInfoEnricher.cs @@ -21,17 +21,12 @@ internal sealed class TelemetrySolutionInfoEnricher : TelemetryActivityEventEnri protected override Task CanExecuteAsync(ActivityContext context) { - if (context.SolutionPath.IsNullOrEmpty()) - { - return Task.FromResult(false); - } - - if (context.SolutionId.HasValue) + if (context.SolutionId.HasValue && !context.SolutionPath.IsNullOrEmpty()) { return Task.FromResult(_telemetryActivityStorage.ShouldAddSolutionInformation(context.SolutionId.Value)); } - return Task.FromResult(true); + return Task.FromResult(false); } protected override Task ExecuteAsync(ActivityContext context) @@ -42,14 +37,6 @@ internal sealed class TelemetrySolutionInfoEnricher : TelemetryActivityEventEnri { return Task.CompletedTask; } - - var correctSolutionPath = FindCorrectSolutionPath(context.SolutionPath); - if (correctSolutionPath.IsNullOrEmpty()) - { - return Task.CompletedTask; - } - - context.SetSolutionPath(correctSolutionPath); var jsonContent = File.ReadAllText(context.SolutionPath!); using var doc = JsonDocument.Parse(jsonContent, new JsonDocumentOptions @@ -58,15 +45,6 @@ internal sealed class TelemetrySolutionInfoEnricher : TelemetryActivityEventEnri }); var root = doc.RootElement; - - var solutionId = TelemetryJsonExtensions.GetGuidOrNull(root, "id"); - - if (!solutionId.HasValue) - { - return Task.CompletedTask; - } - - context.Current[ActivityPropertyNames.SolutionId] = solutionId; if (root.TryGetProperty("versions", out var versions)) { @@ -171,34 +149,4 @@ internal sealed class TelemetrySolutionInfoEnricher : TelemetryActivityEventEnri var fullPath = Path.Combine(Path.GetDirectoryName(solutionPath)!, path); return File.Exists(fullPath) ? fullPath : null; } - - private static string? FindCorrectSolutionPath(string solutionPath) - { - if (solutionPath.EndsWith(".abpsln")) - { - return solutionPath; - } - - var possibleExtensions = new[] - { - ".sln", - ".slnx" - }; - - foreach (var extension in possibleExtensions) - { - if (!solutionPath.EndsWith(extension)) - { - continue; - } - - var abpSlnPath = solutionPath.Substring(0, solutionPath.Length - extension.Length) + ".abpsln"; - if (File.Exists(abpSlnPath)) - { - return abpSlnPath; - } - } - - return null; - } } \ No newline at end of file diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/Internal/Telemetry/Activity/TelemetryJsonExtensions.cs b/framework/src/Volo.Abp.Core/Volo/Abp/Internal/Telemetry/Activity/TelemetryJsonExtensions.cs index f822f72f18..6f8b5c2a10 100644 --- a/framework/src/Volo.Abp.Core/Volo/Abp/Internal/Telemetry/Activity/TelemetryJsonExtensions.cs +++ b/framework/src/Volo.Abp.Core/Volo/Abp/Internal/Telemetry/Activity/TelemetryJsonExtensions.cs @@ -31,14 +31,4 @@ static internal class TelemetryJsonExtensions return null; } - - static internal Guid? GetGuidOrNull(JsonElement element, string propertyName) - { - if (element.TryGetProperty(propertyName, out var guidProperty) && Guid.TryParse(guidProperty.GetString(), out var guidValue)) - { - return guidValue; - } - - return null; - } } \ No newline at end of file From 7be5a343063d1cabdaf033be42065a829d0dffb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?SAL=C4=B0H=20=C3=96ZKARA?= Date: Wed, 10 Dec 2025 15:37:43 +0300 Subject: [PATCH 13/19] Update TelemetryCliSessionProvider.cs --- .../Volo/Abp/Cli/Telemetry/TelemetryCliSessionProvider.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/framework/src/Volo.Abp.Cli/Volo/Abp/Cli/Telemetry/TelemetryCliSessionProvider.cs b/framework/src/Volo.Abp.Cli/Volo/Abp/Cli/Telemetry/TelemetryCliSessionProvider.cs index 030a9f83db..7088e387b3 100644 --- a/framework/src/Volo.Abp.Cli/Volo/Abp/Cli/Telemetry/TelemetryCliSessionProvider.cs +++ b/framework/src/Volo.Abp.Cli/Volo/Abp/Cli/Telemetry/TelemetryCliSessionProvider.cs @@ -18,7 +18,6 @@ public class TelemetryCliSessionProvider : TelemetryActivityEventEnricher } public override int ExecutionOrder { get; set; } = 10; - protected override Type? ReplaceParentType { get; set; } = typeof(TelemetrySessionInfoEnricher); protected override Task ExecuteAsync(ActivityContext context) { From d64d4574eebf4c15a3dc749c4a9901e60d031d36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?SAL=C4=B0H=20=C3=96ZKARA?= Date: Thu, 11 Dec 2025 12:32:48 +0300 Subject: [PATCH 14/19] Refactor TelemetryService usage to constructor injection Replaces property-based ITelemetryService injection with constructor injection and private readonly fields across CLI command and service classes. This change improves dependency management and aligns with best practices for service injection. --- .../src/Volo.Abp.Cli.Core/Volo/Abp/Cli/CliService.cs | 12 +++++++----- .../Volo/Abp/Cli/Commands/AddModuleCommand.cs | 9 ++++++--- .../Volo/Abp/Cli/Commands/AddPackageCommand.cs | 11 ++++++----- .../Volo/Abp/Cli/Commands/CleanCommand.cs | 9 +++++---- .../Volo/Abp/Cli/Commands/ListModulesCommand.cs | 7 ++++--- .../Volo/Abp/Cli/Commands/NewCommand.cs | 9 ++++++--- .../Volo/Abp/Cli/Commands/UpdateCommand.cs | 7 ++++--- 7 files changed, 38 insertions(+), 26 deletions(-) diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/CliService.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/CliService.cs index c514236bd7..063ceddebf 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/CliService.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/CliService.cs @@ -22,8 +22,8 @@ namespace Volo.Abp.Cli; public class CliService : ITransientDependency { private readonly MemoryService _memoryService; + private readonly ITelemetryService _telemetryService; public ILogger Logger { get; set; } - public ITelemetryService TelemetryService { get; set; } protected ICommandLineArgumentParser CommandLineArgumentParser { get; } protected ICommandSelector CommandSelector { get; } protected IServiceScopeFactory ServiceScopeFactory { get; } @@ -38,7 +38,8 @@ public class CliService : ITransientDependency PackageVersionCheckerService nugetService, ICmdHelper cmdHelper, MemoryService memoryService, - CliVersionService cliVersionService) + CliVersionService cliVersionService, + ITelemetryService telemetryService) { _memoryService = memoryService; CommandLineArgumentParser = commandLineArgumentParser; @@ -47,6 +48,7 @@ public class CliService : ITransientDependency PackageVersionCheckerService = nugetService; CmdHelper = cmdHelper; CliVersionService = cliVersionService; + _telemetryService = telemetryService; Logger = NullLogger.Instance; } @@ -67,7 +69,7 @@ public class CliService : ITransientDependency try { - await using var _ = TelemetryService.TrackActivityAsync(ActivityNameConsts.AbpCliRun); + await using var _ = _telemetryService.TrackActivityAsync(ActivityNameConsts.AbpCliRun); if (commandLineArgs.IsCommand("prompt")) { await RunPromptAsync(); @@ -88,13 +90,13 @@ public class CliService : ITransientDependency } catch (Exception ex) { - await TelemetryService.AddErrorActivityAsync(ex.Message); + await _telemetryService.AddErrorActivityAsync(ex.Message); Logger.LogException(ex); throw; } finally { - await TelemetryService.AddActivityAsync(ActivityNameConsts.AbpCliExit); + await _telemetryService.AddActivityAsync(ActivityNameConsts.AbpCliExit); } } diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/AddModuleCommand.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/AddModuleCommand.cs index 204882a597..38483517da 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/AddModuleCommand.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/AddModuleCommand.cs @@ -22,8 +22,9 @@ public class AddModuleCommand : IConsoleCommand, ITransientDependency public const string Name = "add-module"; private AddModuleInfoOutput _lastAddedModuleInfo; + private readonly ITelemetryService _telemetryService; + public ILogger Logger { get; set; } - public ITelemetryService TelemetryService { get; set; } protected SolutionModuleAdder SolutionModuleAdder { get; } public SolutionPackageVersionFinder SolutionPackageVersionFinder { get; } @@ -42,11 +43,13 @@ public class AddModuleCommand : IConsoleCommand, ITransientDependency public AddModuleCommand( SolutionModuleAdder solutionModuleAdder, SolutionPackageVersionFinder solutionPackageVersionFinder, - IOptions options) + IOptions options, + ITelemetryService telemetryService) { _options = options.Value; SolutionModuleAdder = solutionModuleAdder; SolutionPackageVersionFinder = solutionPackageVersionFinder; + _telemetryService = telemetryService; Logger = NullLogger.Instance; } @@ -70,7 +73,7 @@ public class AddModuleCommand : IConsoleCommand, ITransientDependency var newTemplate = commandLineArgs.Options.ContainsKey(Options.NewTemplate.Long); - await using var _ = TelemetryService.TrackActivityAsync(newTemplate + await using var _ = _telemetryService.TrackActivityAsync(newTemplate ? ActivityNameConsts.AbpCliCommandsInstallLocalModule : ActivityNameConsts.AbpCliCommandsInstallModule); diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/AddPackageCommand.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/AddPackageCommand.cs index a8fbdb8840..f397ef8d6e 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/AddPackageCommand.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/AddPackageCommand.cs @@ -18,18 +18,19 @@ public class AddPackageCommand : IConsoleCommand, ITransientDependency { public const string Name = "add-package"; - public ILogger Logger { get; set; } + private readonly ITelemetryService _telemetryService; - public ITelemetryService TelemetryService { get; set; } + public ILogger Logger { get; set; } protected ProjectNugetPackageAdder ProjectNugetPackageAdder { get; } public ProjectNpmPackageAdder ProjectNpmPackageAdder { get; } - public AddPackageCommand(ProjectNugetPackageAdder projectNugetPackageAdder, ProjectNpmPackageAdder projectNpmPackageAdder) + public AddPackageCommand(ProjectNugetPackageAdder projectNugetPackageAdder, ProjectNpmPackageAdder projectNpmPackageAdder, ITelemetryService telemetryService) { ProjectNugetPackageAdder = projectNugetPackageAdder; ProjectNpmPackageAdder = projectNpmPackageAdder; + _telemetryService = telemetryService; Logger = NullLogger.Instance; } @@ -44,8 +45,8 @@ public class AddPackageCommand : IConsoleCommand, ITransientDependency ); } - await using var _ = TelemetryService.TrackActivityAsync(ActivityNameConsts.AbpCliCommandsNewPackage); - await using var __ = TelemetryService.TrackActivityAsync(ActivityNameConsts.AbpCliCommandsAddPackage); + await using var _ = _telemetryService.TrackActivityAsync(ActivityNameConsts.AbpCliCommandsNewPackage); + await using var __ = _telemetryService.TrackActivityAsync(ActivityNameConsts.AbpCliCommandsAddPackage); var isNpmPackage = false; var isNugetPackage = true; diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/CleanCommand.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/CleanCommand.cs index 886e4faa2b..661cf7995b 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/CleanCommand.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/CleanCommand.cs @@ -18,20 +18,21 @@ public class CleanCommand : IConsoleCommand, ITransientDependency public const string Name = "clean"; public ILogger Logger { get; set; } - - public ITelemetryService TelemetryService { get; set; } protected ICmdHelper CmdHelper { get; } + + private readonly ITelemetryService _telemetryService; - public CleanCommand(ICmdHelper cmdHelper) + public CleanCommand(ICmdHelper cmdHelper, ITelemetryService telemetryService) { CmdHelper = cmdHelper; + _telemetryService = telemetryService; Logger = NullLogger.Instance; } public async Task ExecuteAsync(CommandLineArgs commandLineArgs) { - await using var _ = TelemetryService.TrackActivityAsync(ActivityNameConsts.AbpCliCommandsClean); + await using var _ = _telemetryService.TrackActivityAsync(ActivityNameConsts.AbpCliCommandsClean); var binEntries = Directory.EnumerateDirectories(Directory.GetCurrentDirectory(), "bin", SearchOption.AllDirectories); var objEntries = Directory.EnumerateDirectories(Directory.GetCurrentDirectory(), "obj", SearchOption.AllDirectories); diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/ListModulesCommand.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/ListModulesCommand.cs index 4496e62eeb..8a9d4fd6d1 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/ListModulesCommand.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/ListModulesCommand.cs @@ -18,18 +18,19 @@ public class ListModulesCommand : IConsoleCommand, ITransientDependency public ModuleInfoProvider ModuleInfoProvider { get; } public ILogger Logger { get; set; } - public ITelemetryService TelemetryService { get; set; } + private readonly ITelemetryService _telemetryService; - public ListModulesCommand(ModuleInfoProvider moduleInfoProvider) + public ListModulesCommand(ModuleInfoProvider moduleInfoProvider, ITelemetryService telemetryService) { ModuleInfoProvider = moduleInfoProvider; + _telemetryService = telemetryService; Logger = NullLogger.Instance; } public async Task ExecuteAsync(CommandLineArgs commandLineArgs) { - await using var _ = TelemetryService.TrackActivityAsync(ActivityNameConsts.AbpCliCommandsListModules); + await using var _ = _telemetryService.TrackActivityAsync(ActivityNameConsts.AbpCliCommandsListModules); var modules = await ModuleInfoProvider.GetModuleListAsync(); var freeModules = modules.Where(m => !m.IsPro).ToList(); diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs index 4d02472d27..149b477d5b 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs @@ -29,7 +29,8 @@ public class NewCommand : ProjectCreationCommandBase, IConsoleCommand, ITransien protected TemplateProjectBuilder TemplateProjectBuilder { get; } public ITemplateInfoProvider TemplateInfoProvider { get; } - public ITelemetryService TelemetryService { get; set; } + + private readonly ITelemetryService _telemetryService; public NewCommand( ConnectionStringProvider connectionStringProvider, @@ -45,7 +46,8 @@ public class NewCommand : ProjectCreationCommandBase, IConsoleCommand, ITransien ITemplateInfoProvider templateInfoProvider, TemplateProjectBuilder templateProjectBuilder, AngularThemeConfigurer angularThemeConfigurer, - CliVersionService cliVersionService) : + CliVersionService cliVersionService, + ITelemetryService telemetryService) : base(connectionStringProvider, solutionPackageVersionFinder, cmdHelper, @@ -61,6 +63,7 @@ public class NewCommand : ProjectCreationCommandBase, IConsoleCommand, ITransien { TemplateInfoProvider = templateInfoProvider; TemplateProjectBuilder = templateProjectBuilder; + _telemetryService = telemetryService; } public async Task ExecuteAsync(CommandLineArgs commandLineArgs) @@ -107,7 +110,7 @@ public class NewCommand : ProjectCreationCommandBase, IConsoleCommand, ITransien activityName = ActivityNameConsts.AbpCliCommandsNewModule; } - await TelemetryService.AddActivityAsync(activityName, o => + await _telemetryService.AddActivityAsync(activityName, o => { o[ActivityPropertyNames.CreationTool] = AbpTool.OldCli; o[ActivityPropertyNames.Template] = template; diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/UpdateCommand.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/UpdateCommand.cs index f46dd79f5e..68ab346064 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/UpdateCommand.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/UpdateCommand.cs @@ -19,23 +19,24 @@ public class UpdateCommand : IConsoleCommand, ITransientDependency public const string Name = "update"; public ILogger Logger { get; set; } - public ITelemetryService TelemetryService { get; set; } private readonly VoloNugetPackagesVersionUpdater _nugetPackagesVersionUpdater; private readonly NpmPackagesUpdater _npmPackagesUpdater; + private readonly ITelemetryService _telemetryService; public UpdateCommand(VoloNugetPackagesVersionUpdater nugetPackagesVersionUpdater, - NpmPackagesUpdater npmPackagesUpdater) + NpmPackagesUpdater npmPackagesUpdater, ITelemetryService telemetryService) { _nugetPackagesVersionUpdater = nugetPackagesVersionUpdater; _npmPackagesUpdater = npmPackagesUpdater; + _telemetryService = telemetryService; Logger = NullLogger.Instance; } public async Task ExecuteAsync(CommandLineArgs commandLineArgs) { - await using var _ = TelemetryService.TrackActivityAsync(ActivityNameConsts.AbpCliCommandsUpdate); + await using var _ = _telemetryService.TrackActivityAsync(ActivityNameConsts.AbpCliCommandsUpdate); var updateNpm = commandLineArgs.Options.ContainsKey(Options.Packages.Npm); var updateNuget = commandLineArgs.Options.ContainsKey(Options.Packages.NuGet); From ac29577569bd77c64a4fba943ec9afdd7d81aaa2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?SAL=C4=B0H=20=C3=96ZKARA?= Date: Thu, 11 Dec 2025 12:57:36 +0300 Subject: [PATCH 15/19] Add OldCli flag to telemetry session context Introduces a new 'OldCli' property set to true in the telemetry session context to help identify sessions initiated by the old CLI. --- .../Volo/Abp/Cli/Telemetry/TelemetryCliSessionProvider.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/framework/src/Volo.Abp.Cli/Volo/Abp/Cli/Telemetry/TelemetryCliSessionProvider.cs b/framework/src/Volo.Abp.Cli/Volo/Abp/Cli/Telemetry/TelemetryCliSessionProvider.cs index 7088e387b3..bc0fcc2028 100644 --- a/framework/src/Volo.Abp.Cli/Volo/Abp/Cli/Telemetry/TelemetryCliSessionProvider.cs +++ b/framework/src/Volo.Abp.Cli/Volo/Abp/Cli/Telemetry/TelemetryCliSessionProvider.cs @@ -24,6 +24,7 @@ public class TelemetryCliSessionProvider : TelemetryActivityEventEnricher context.Current[ActivityPropertyNames.SessionType] = SessionType.AbpCli; context.Current[ActivityPropertyNames.SessionId] = Guid.NewGuid(); context.Current[ActivityPropertyNames.IsFirstSession] = !File.Exists(TelemetryPaths.ActivityStorage); + context.Current["OldCli"] = true; return Task.CompletedTask; } From 354746ca739c78d7ac6f38ee86885ff2b62c371f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?SAL=C4=B0H=20=C3=96ZKARA?= Date: Thu, 11 Dec 2025 13:46:02 +0300 Subject: [PATCH 16/19] Add 'OldCli' flag to additional telemetry properties Ensures the 'OldCli' flag is set in the AdditionalProperties dictionary within the telemetry context, creating the dictionary if it does not exist. This provides consistent telemetry data for identifying CLI usage. --- .../Cli/Telemetry/TelemetryCliSessionProvider.cs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/framework/src/Volo.Abp.Cli/Volo/Abp/Cli/Telemetry/TelemetryCliSessionProvider.cs b/framework/src/Volo.Abp.Cli/Volo/Abp/Cli/Telemetry/TelemetryCliSessionProvider.cs index bc0fcc2028..17c340febd 100644 --- a/framework/src/Volo.Abp.Cli/Volo/Abp/Cli/Telemetry/TelemetryCliSessionProvider.cs +++ b/framework/src/Volo.Abp.Cli/Volo/Abp/Cli/Telemetry/TelemetryCliSessionProvider.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.IO; using System.Threading.Tasks; using Volo.Abp.DependencyInjection; @@ -26,6 +27,18 @@ public class TelemetryCliSessionProvider : TelemetryActivityEventEnricher context.Current[ActivityPropertyNames.IsFirstSession] = !File.Exists(TelemetryPaths.ActivityStorage); context.Current["OldCli"] = true; + if(context.Current.TryGetValue>(ActivityPropertyNames.AdditionalProperties, out var additionalProperties)) + { + additionalProperties["OldCli"] = true; + } + else + { + context.Current[ActivityPropertyNames.AdditionalProperties] = new Dictionary + { + { "OldCli", true } + }; + } + return Task.CompletedTask; } } \ No newline at end of file From ae4a5fbf88470f48a80d010f12342663a763f43f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?SAL=C4=B0H=20=C3=96ZKARA?= Date: Thu, 11 Dec 2025 14:41:45 +0300 Subject: [PATCH 17/19] Add NullTelemetryService and telemetry config logic Introduces NullTelemetryService to provide a no-op implementation of ITelemetryService. Updates AbpCliCoreModule to conditionally configure telemetry services based on the ABP_STUDIO_ENABLE_TELEMETRY environment variable. --- .../Volo/Abp/Cli/AbpCliCoreModule.cs | 26 +++++++++++++ .../Abp/Cli/Telemetry/NullTelemetryService.cs | 39 +++++++++++++++++++ 2 files changed, 65 insertions(+) create mode 100644 framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Telemetry/NullTelemetryService.cs diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/AbpCliCoreModule.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/AbpCliCoreModule.cs index 7b249f0517..8ff8ad3206 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/AbpCliCoreModule.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/AbpCliCoreModule.cs @@ -1,5 +1,8 @@ +using System; +using System.Linq; using System.Text; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; using Volo.Abp.Cli.Commands; using Volo.Abp.Cli.Commands.Internal; using Volo.Abp.Cli.Http; @@ -7,9 +10,12 @@ using Volo.Abp.Cli.ServiceProxying; using Volo.Abp.Cli.ServiceProxying.Angular; using Volo.Abp.Cli.ServiceProxying.CSharp; using Volo.Abp.Cli.ServiceProxying.JavaScript; +using Volo.Abp.Cli.Telemetry; using Volo.Abp.Domain; using Volo.Abp.Http; using Volo.Abp.IdentityModel; +using Volo.Abp.Internal.Telemetry; +using Volo.Abp.Internal.Telemetry.Activity.Providers; using Volo.Abp.Json; using Volo.Abp.Localization; using Volo.Abp.Minify; @@ -27,6 +33,8 @@ namespace Volo.Abp.Cli; )] public class AbpCliCoreModule : AbpModule { + private const string EnableTelemetryVariableName = "ABP_STUDIO_ENABLE_TELEMETRY"; + public override void ConfigureServices(ServiceConfigurationContext context) { context.Services.AddHttpClient(CliConsts.HttpClientName) @@ -82,5 +90,23 @@ public class AbpCliCoreModule : AbpModule options.Generators[AngularServiceProxyGenerator.Name] = typeof(AngularServiceProxyGenerator); options.Generators[CSharpServiceProxyGenerator.Name] = typeof(CSharpServiceProxyGenerator); }); + + ConfigureTelemetry(context.Services); + } + + private static void ConfigureTelemetry(IServiceCollection services) + { + var enableTelemetryEnvironmentVariable = Environment.GetEnvironmentVariable(EnableTelemetryVariableName , EnvironmentVariableTarget.Machine) + ?? Environment.GetEnvironmentVariable(EnableTelemetryVariableName , EnvironmentVariableTarget.User) + ?? Environment.GetEnvironmentVariable(EnableTelemetryVariableName , EnvironmentVariableTarget.Process); + + if (enableTelemetryEnvironmentVariable.IsNullOrEmpty() || !enableTelemetryEnvironmentVariable.Equals("false", StringComparison.InvariantCultureIgnoreCase)) + { + services.Remove(services.First(p => p.ImplementationType == typeof(TelemetrySessionInfoEnricher))); + } + else + { + services.Replace(ServiceDescriptor.Singleton()); + } } } diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Telemetry/NullTelemetryService.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Telemetry/NullTelemetryService.cs new file mode 100644 index 0000000000..4f3c695f7d --- /dev/null +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Telemetry/NullTelemetryService.cs @@ -0,0 +1,39 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Volo.Abp.Internal.Telemetry; +using Volo.Abp.Internal.Telemetry.Activity; + +namespace Volo.Abp.Cli.Telemetry; + +public class NullTelemetryService : ITelemetryService +{ + public IAsyncDisposable TrackActivity(ActivityEvent activityData) + { + return NullAsyncDisposable.Instance; + } + public IAsyncDisposable TrackActivityAsync(string activityName, Action>? additionalProperties = null) + { + return NullAsyncDisposable.Instance; + } + + public Task AddActivityAsync(string activityName, Action>? additionalProperties = null) + { + return Task.CompletedTask; + } + + public Task AddErrorActivityAsync(Action> additionalProperties) + { + return Task.CompletedTask; + } + + public Task AddErrorActivityAsync(string errorMessage) + { + return Task.CompletedTask; + } + + public Task AddErrorForActivityAsync(string failingActivity, string errorMessage) + { + return Task.CompletedTask; + } +} \ No newline at end of file From f9fe9b92cc74d4ed25953ba7b8b796059746c1d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?SAL=C4=B0H=20=C3=96ZKARA?= Date: Thu, 11 Dec 2025 14:44:36 +0300 Subject: [PATCH 18/19] Update AbpCliModule.cs --- framework/src/Volo.Abp.Cli/Volo/Abp/Cli/AbpCliModule.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/framework/src/Volo.Abp.Cli/Volo/Abp/Cli/AbpCliModule.cs b/framework/src/Volo.Abp.Cli/Volo/Abp/Cli/AbpCliModule.cs index d1b30d34b5..179d4e8e38 100644 --- a/framework/src/Volo.Abp.Cli/Volo/Abp/Cli/AbpCliModule.cs +++ b/framework/src/Volo.Abp.Cli/Volo/Abp/Cli/AbpCliModule.cs @@ -11,8 +11,5 @@ namespace Volo.Abp.Cli; )] public class AbpCliModule : AbpModule { - public override void ConfigureServices(ServiceConfigurationContext context) - { - context.Services.RemoveAll(x => x.ImplementationType == typeof(TelemetrySessionInfoEnricher)); - } + } From 51c5e1be2604ed7c237019fc4cdd91fda1ed25c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?SAL=C4=B0H=20=C3=96ZKARA?= Date: Thu, 11 Dec 2025 14:47:59 +0300 Subject: [PATCH 19/19] Update AbpCliModule.cs --- framework/src/Volo.Abp.Cli/Volo/Abp/Cli/AbpCliModule.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/framework/src/Volo.Abp.Cli/Volo/Abp/Cli/AbpCliModule.cs b/framework/src/Volo.Abp.Cli/Volo/Abp/Cli/AbpCliModule.cs index 179d4e8e38..c782eadd52 100644 --- a/framework/src/Volo.Abp.Cli/Volo/Abp/Cli/AbpCliModule.cs +++ b/framework/src/Volo.Abp.Cli/Volo/Abp/Cli/AbpCliModule.cs @@ -1,6 +1,4 @@ -using System.Collections.Generic; -using Volo.Abp.Autofac; -using Volo.Abp.Internal.Telemetry.Activity.Providers; +using Volo.Abp.Autofac; using Volo.Abp.Modularity; namespace Volo.Abp.Cli;