Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -184,5 +184,6 @@
<PackageVersion Include="coverlet.collector" Version="6.0.4" />
<PackageVersion Include="ConfigureAwait.Fody" Version="3.3.2" />
<PackageVersion Include="Fody" Version="6.9.2" />
<PackageVersion Include="System.Management" Version="9.0.1"/>
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
using System;
using System.Threading.Tasks;
using Volo.Abp.Application.Services;
using Volo.Abp.DependencyInjection;
using System.Linq;
using Microsoft.AspNetCore.Mvc;
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;
using Volo.Abp.Reflection;

namespace Volo.Abp.AspNetCore.Mvc;

[ExposeServices(typeof(ITelemetryActivityEventEnricher), typeof(IHasParentTelemetryActivityEventEnricher<TelemetryApplicationInfoEnricher>))]
public sealed class TelemetryApplicationMetricsEnricher : TelemetryActivityEventEnricher, IHasParentTelemetryActivityEventEnricher<TelemetryApplicationInfoEnricher>
{
private readonly ITypeFinder _typeFinder;
public TelemetryApplicationMetricsEnricher(ITypeFinder typeFinder, IServiceProvider serviceProvider) : base(serviceProvider)
{
_typeFinder = typeFinder;
}

protected override Task<bool> CanExecuteAsync(ActivityContext context)
{
return Task.FromResult(context.SessionType == SessionType.ApplicationRuntime);
}

protected override Task ExecuteAsync(ActivityContext context)
{
var appServiceCount = _typeFinder.Types.Count(t =>
typeof(IApplicationService).IsAssignableFrom(t) &&
t is { IsAbstract: false, IsInterface: false } &&
!t.AssemblyQualifiedName!.StartsWith(TelemetryConsts.VoloNameSpaceFilter));

var controllerCount = _typeFinder.Types.Count(t =>
typeof(ControllerBase).IsAssignableFrom(t) &&
!t.IsAbstract &&
!t.AssemblyQualifiedName!.StartsWith(TelemetryConsts.VoloNameSpaceFilter));


context.Current[ActivityPropertyNames.AppServiceCount] = appServiceCount;
context.Current[ActivityPropertyNames.ControllerCount] = controllerCount;
return Task.CompletedTask;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Volo.Abp.Authorization.Abstractions")]
[assembly: AssemblyTrademark("")]
[assembly: InternalsVisibleTo("Volo.Abp.Authorization")]

// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]

// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("83632bec-2f60-4c2b-b964-30e8b37fa9d8")]
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,8 @@ public virtual PermissionDefinition AddChild(
Parent = this
};

child[PermissionDefinitionContext.KnownPropertyNames.CurrentProviderName] = this[PermissionDefinitionContext.KnownPropertyNames.CurrentProviderName];

_children.Add(child);

return child;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,13 @@ public class PermissionDefinitionContext : IPermissionDefinitionContext

public Dictionary<string, PermissionGroupDefinition> Groups { get; }

internal IPermissionDefinitionProvider? CurrentProvider { get; set; }

public static class KnownPropertyNames
{
public const string CurrentProviderName = "_CurrentProviderName";
}

public PermissionDefinitionContext(IServiceProvider serviceProvider)
{
ServiceProvider = serviceProvider;
Expand All @@ -28,7 +35,16 @@ public virtual PermissionGroupDefinition AddGroup(
throw new AbpException($"There is already an existing permission group with name: {name}");
}

return Groups[name] = new PermissionGroupDefinition(name, displayName);
var group = new PermissionGroupDefinition(name, displayName);

if (CurrentProvider != null)
{
group[KnownPropertyNames.CurrentProviderName] = CurrentProvider.GetType().FullName;
}

Groups[name] = group;

return group;
}

[NotNull]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ public virtual PermissionDefinition AddPermission(
isEnabled
);

permission[PermissionDefinitionContext.KnownPropertyNames.CurrentProviderName] = this[PermissionDefinitionContext.KnownPropertyNames.CurrentProviderName];

_permissions.Add(permission);

return permission;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,18 +84,23 @@ protected virtual Dictionary<string, PermissionGroupDefinition> CreatePermission

foreach (var provider in providers)
{
context.CurrentProvider = provider;
provider.PreDefine(context);
}

foreach (var provider in providers)
{
context.CurrentProvider = provider;
provider.Define(context);
}

foreach (var provider in providers)
{
context.CurrentProvider = provider;
provider.PostDefine(context);
}

context.CurrentProvider = null;

return context.Groups;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
using System;
using System.Linq;
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;

namespace Volo.Abp.Authorization.Permissions;

[ExposeServices(typeof(ITelemetryActivityEventEnricher), typeof(IHasParentTelemetryActivityEventEnricher<TelemetryApplicationInfoEnricher>))]
public sealed class TelemetryPermissionInfoEnricher : TelemetryActivityEventEnricher, IHasParentTelemetryActivityEventEnricher<TelemetryApplicationInfoEnricher>
{
private readonly IPermissionDefinitionManager _permissionDefinitionManager;

public TelemetryPermissionInfoEnricher(IPermissionDefinitionManager permissionDefinitionManager,
IServiceProvider serviceProvider) : base(serviceProvider)
{
_permissionDefinitionManager = permissionDefinitionManager;
}

protected override Task<bool> CanExecuteAsync(ActivityContext context)
{
return Task.FromResult(context.ProjectId.HasValue);
}

protected async override Task ExecuteAsync(ActivityContext context)
{
var permissions = await _permissionDefinitionManager.GetPermissionsAsync();

var userDefinedPermissionsCount = permissions.Count(IsUserDefinedPermission);

context.Current[ActivityPropertyNames.PermissionCount] = userDefinedPermissionsCount;
}

private static bool IsUserDefinedPermission(PermissionDefinition permission)
{
return permission.Properties.TryGetValue(PermissionDefinitionContext.KnownPropertyNames.CurrentProviderName, out var providerName) &&
providerName is string &&
!providerName.ToString()!.StartsWith(TelemetryConsts.VoloNameSpaceFilter);
}


}
1 change: 1 addition & 0 deletions framework/src/Volo.Abp.Core/Volo.Abp.Core.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" />
<PackageReference Include="Microsoft.Extensions.Configuration.CommandLine" />
<PackageReference Include="Microsoft.Extensions.Options" />
<PackageReference Include="System.Management" />
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" />
<PackageReference Include="Microsoft.Extensions.Logging" />
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" />
Expand Down
54 changes: 54 additions & 0 deletions framework/src/Volo.Abp.Core/Volo/Abp/AbpApplicationBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,17 @@
using System.Reflection;
using System.Threading.Tasks;
using JetBrains.Annotations;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Internal;
using Volo.Abp.Internal.Telemetry;
using Volo.Abp.Internal.Telemetry.Constants;
using Volo.Abp.Logging;
using Volo.Abp.Modularity;
using Volo.Abp.Threading;

namespace Volo.Abp;

Expand Down Expand Up @@ -149,6 +153,56 @@ protected virtual IReadOnlyList<IAbpModuleDescriptor> LoadModules(IServiceCollec
options.PlugInSources
);
}
protected void SetupTelemetryTracking()
{
if (!ShouldSendTelemetryData())
{
return;
}

AsyncHelper.RunSync(InitializeTelemetryTracking);
}

protected async Task SetupTelemetryTrackingAsync()
{
if (!ShouldSendTelemetryData())
{
return;
}

await InitializeTelemetryTracking();
}

private async Task InitializeTelemetryTracking()
{
try
{
using var scope = ServiceProvider.CreateScope();
var telemetryService = scope.ServiceProvider.GetRequiredService<ITelemetryService>();
await telemetryService.AddActivityAsync(ActivityNameConsts.ApplicationRun);
}
catch (Exception ex)
{
try
{
using var scope = ServiceProvider.CreateScope();
var logger = scope.ServiceProvider.GetRequiredService<ILogger<AbpApplicationBase>>();
logger.LogException(ex, LogLevel.Trace);
}
catch
{
/* ignored */
}
}
}

private bool ShouldSendTelemetryData()
{
using var scope = ServiceProvider.CreateScope();
var abpHostEnvironment = scope.ServiceProvider.GetRequiredService<IAbpHostEnvironment>();
var configuration = scope.ServiceProvider.GetRequiredService<IConfiguration>();
return abpHostEnvironment.IsDevelopment() && configuration.GetValue<bool?>("Abp:Telemetry:IsEnabled") == true;
}

//TODO: We can extract a new class for this
public virtual async Task ConfigureServicesAsync()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ public async Task InitializeAsync(IServiceProvider serviceProvider)
SetServiceProvider(serviceProvider);

await InitializeModulesAsync();

await SetupTelemetryTrackingAsync();
}

public void Initialize([NotNull] IServiceProvider serviceProvider)
Expand All @@ -53,6 +55,8 @@ public void Initialize([NotNull] IServiceProvider serviceProvider)
SetServiceProvider(serviceProvider);

InitializeModules();

SetupTelemetryTracking();
}

public override void Dispose()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,15 @@ public async Task InitializeAsync()
{
CreateServiceProvider();
await InitializeModulesAsync();
await SetupTelemetryTrackingAsync();

}

public void Initialize()
{
CreateServiceProvider();
InitializeModules();
SetupTelemetryTracking();
}

public override void Dispose()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
using System;
using System.Collections.Generic;
using Volo.Abp.Internal.Telemetry.Constants;
using Volo.Abp.Internal.Telemetry.Constants.Enums;

namespace Volo.Abp.Internal.Telemetry.Activity;

public class ActivityContext
{
public ActivityEvent Current { get; }
public Dictionary<string, object> ExtraProperties { get; } = new();
public bool IsTerminated { get; private set; }

public Guid? ProjectId => Current.Get<Guid?>(ActivityPropertyNames.ProjectId);

public Guid? SolutionId => Current.Get<Guid?>(ActivityPropertyNames.SolutionId);

public SessionType? SessionType => Current.Get<SessionType?>(ActivityPropertyNames.SessionType);

public string? DeviceId => Current.Get<string?>(ActivityPropertyNames.DeviceId);

public string? SolutionPath => ExtraProperties.TryGetValue(ActivityPropertyNames.SolutionPath, out var solutionPath)
? solutionPath?.ToString()
: null;

private ActivityContext(ActivityEvent current)
{
Current = current;
}

public static ActivityContext Create(string activityName, string? details = null,
Action<Dictionary<string, object>>? additionalProperties = null)
{
var activity = new ActivityEvent(activityName, details);

if (additionalProperties is not null)
{
var additionalPropertiesDict = new Dictionary<string, object>();
activity[ActivityPropertyNames.AdditionalProperties] = additionalPropertiesDict;
additionalProperties.Invoke(additionalPropertiesDict);
}

return new ActivityContext(activity);
}

public void Terminate()
{
IsTerminated = true;
}
}
Loading