From ABP Sensei
Configures and manages ABP Framework audit logging: AbpAuditingOptions, entity history, IAuditingStore, and audit log filtering. Useful when setting up audit trails or tracking entity changes in ABP.
How this skill is triggered — by the user, by Claude, or both
Slash command
/abp-sensei:abp-audit-loggingThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
User asks about audit logging, audit trails, entity history, AbpAuditingOptions, IAuditingStore, audit log contributors, or tracking changes in ABP Framework.
User asks about audit logging, audit trails, entity history, AbpAuditingOptions, IAuditingStore, audit log contributors, or tracking changes in ABP Framework.
ABP's audit logging system:
IAuditingStoreConfigure<AbpAuditingOptions>(options =>
{
options.IsEnabled = true; // Root switch (default: true)
options.HideErrors = true; // Hide audit save errors (default: true)
options.IsEnabledForAnonymousUsers = true; // Log anonymous users (default: true)
options.AlwaysLogOnException = true; // Always log on exception (default: true)
options.IsEnabledForIntegrationService = false; // Enable for integration services
options.IsEnabledForGetRequests = false; // Log GET requests (default: false)
options.DisableLogActionInfo = false; // Don't log AuditLogActionInfo
options.ApplicationName = "MyApp"; // Distinguish multi-app logs
options.SaveEntityHistoryWhenNavigationChanges = true;
});
Key options:
IsEnabled — Master switch; if false, all other options ignoredHideErrors — If true, audit save errors logged silently; if false, throwsAlwaysLogOnException — Force audit log on exception regardless of other settingsIsEnabledForGetRequests — GET requests normally not logged (shouldn't change data)ApplicationName — Critical when multiple apps share audit log databaseImportant: Entity history is disabled by default for all entities. You must explicitly enable it.
Configure<AbpAuditingOptions>(options =>
{
options.EntityHistorySelectors.AddAllEntities();
});
Configure<AbpAuditingOptions>(options =>
{
options.EntityHistorySelectors.Add(
new NamedTypeSelector(
"MySelectorName",
type => typeof(IEntity).IsAssignableFrom(type)
)
);
});
[Audited]
public class MyEntity : Entity<Guid>
{
// ...
}
[DisableAuditing]
public class MyEntity : Entity<Guid>
{
// ...
}
[Audited]
public class MyUser : Entity<Guid>
{
public string Name { get; set; }
[DisableAuditing] // Don't log password changes
public string Password { get; set; }
}
[DisableAuditing]
public class MyUser : Entity<Guid>
{
[Audited] // Only log Name changes
public string Name { get; set; }
public string Email { get; set; }
public string Password { get; set; }
}
// Skip audit properties on update and skip publishing entity updated event
entity.IgnoreAuditPropertiesOnUpdate();
An entity is ignored in entity change audit logging if:
AbpAuditingOptions.IgnoredTypesIEntity[DisableAuditing]
public class MyController : AbpController
{
[DisableAuditing]
public IActionResult MyAction() { }
}
[DisableAuditing]
public class MyAppService : ApplicationService
{
[DisableAuditing]
public async Task DoSomethingAsync() { }
}
[Audited]
public class MyService : ITransientDependency
{
public virtual async Task DoWorkAsync() { }
}
Service must be DI-registered and method must be
virtualfor interception.
Default implementation saves to database. Custom implementation:
public class MyAuditingStore : IAuditingStore, ITransientDependency
{
public async Task SaveAsync(AuditLogInfo auditInfo)
{
// Save to custom location (file, external service, etc.)
}
}
public class AuditLogInfo
{
public string ApplicationName { get; set; }
public Guid? UserId { get; set; }
public string UserName { get; set; }
public Guid? TenantId { get; set; }
public string TenantName { get; set; }
public string ImpersonatorUserName { get; set; }
public Guid? ImpersonatorUserId { get; set; }
public DateTime ExecutionTime { get; set; }
public int ExecutionDuration { get; set; } // milliseconds
public string ClientIpAddress { get; set; }
public string ClientName { get; set; }
public string BrowserInfo { get; set; }
public string HttpMethod { get; set; }
public string Url { get; set; }
public int? HttpStatusCode { get; set; }
public string ExceptionMessage { get; set; }
public string Exception { get; set; }
public Dictionary<string, object> ExtraProperties { get; set; }
public List<AuditLogActionInfo> Actions { get; set; }
public List<EntityChangeInfo> EntityChanges { get; set; }
public List<EntityPropertyChangeInfo> EntityPropertyChanges { get; set; }
}
Extend audit log with custom data:
public class MyAuditLogContributor : AuditLogContributor
{
public override Task PreContributeAsync(AuditLogContributionContext context)
{
// Before action execution
context.AuditLog.ExtraProperties["CustomKey"] = "CustomValue";
return Task.CompletedTask;
}
public override Task PostContributeAsync(AuditLogContributionContext context)
{
// After action execution
return Task.CompletedTask;
}
}
// Register
Configure<AbpAuditingOptions>(options =>
{
options.Contributors.Add<MyAuditLogContributor>();
});
Force audit logging for specific services regardless of other settings:
Configure<AbpAuditingOptions>(options =>
{
options.AlwaysLogSelectors.Add(
new NamedTypeSelector(
"CriticalServices",
type => typeof(ICriticalService).IsAssignableFrom(type)
)
);
});
Audit logging module supports:
AbpAuditLoggingDbContextAbpAuditLoggingMongoDbContextBoth providers store audit logs in AbpAuditLogs collection/table.
Enable ASP.NET Core auditing middleware:
app.UseAuditing();
Usually called automatically by AbpAspNetCoreAuditingModule.
ASP.NET Core specific auditing options:
Configure<AbpAspNetCoreAuditingOptions>(options =>
{
// Configure URL filtering
options.UrlControllers.Add("HealthCheck"); // Exclude health check endpoints
});
Configure<AbpAspNetCoreAuditingUrlOptions>(options =>
{
// URL-based filtering
options.IgnoredUrls.Add("/health");
options.IgnoredUrls.Add("/api/health");
});
Entity history in Blazor Server: Not guaranteed to be complete for every UI interaction. Blazor Server uses SignalR-based event handling, and under some flows the audit scope/action tracking may not align with
DbContext.SaveChanges, causing missing or partial entity change records. See GitHub #11682.
AddAllEntities() only if you need full audit trail (storage intensive)[Audited] / [DisableAuditing] for fine-grained controlApplicationName when multiple apps share audit databaseAlwaysLogSelectors for critical services that must always be loggedThe Volo.Abp.SettingManagement module includes IAuditingStore implementation:
abp add-package Volo.Abp.AuditLogging.EntityFrameworkCore
Provides CDSS development patterns for drug interaction checking, dose validation, clinical scoring (NEWS2, qSOFA), and alert classification integrated into EMR workflows.
npx claudepluginhub burakdmir/abp-skills --plugin abp-sensei