Home

Awesome

Audit.NET

USAGE | OUTPUT | CUSTOMIZATION | DATA PROVIDERS | CREATION POLICY | CONFIGURATION | EXTENSIONS

issuesbuild statuschat / supportdonations
issues-openissues-closedbuild-statusGitter Gitterbackers paypal

An extensible framework to audit executing operations in .NET and .NET Core.

Generate audit logs with evidence for reconstruction and examination of activities that have affected specific operations or procedures.

With Audit.NET you can generate tracking information about operations being executed. It gathers environmental information such as the caller user ID, machine name, method name, and exceptions, including execution time and exposing an extensible mechanism to enrich the logs and handle the audit output.

NuGet

NuGet Status NuGet Count

To install the package run the following command on the Package Manager Console:

PM> Install-Package Audit.NET

Changelog

Check the CHANGELOG.md file.

Introduction

The Audit Scope and Audit Event are the central objects of this framework.

Audit Scope

The AuditScope serves as the central object in this framework, representing the scope of an audited operation or event. It acts as a context for auditing, capturing pertinent details like the start time, involved entities, and any additional custom information. Essentially, the AuditScope encapsulates an AuditEvent, controlling its life cycle.

The AuditScope is a disposable object, commonly utilized within a using statement to ensure proper finalization and recording of audit information upon exiting the scope.

See the audit scope statechart.

Audit Event

The AuditEvent functions as an extensible information container that captures the details of the audited operation, is the representation of the audited information within an Audit Scope. It includes details about the audited operation, such as the event type, timestamp, execution duration, and any custom fields or properties.

The AuditEvent is typically serialized into a format suitable for storage or transmission, such as JSON.

The audit events are stored using a Data Provider. You can use one of the available data providers or implement your own.

SUPPORT FOR OLDER .NET FRAMEWORKS

Beginning with version 23.0.0, this library and its extensions have discontinued support for older .NET Framework and Entity Framework (versions that lost Microsoft support before 2023).

For reference, please consult the following links:

This library and its extensions will maintain support for the following minimum .NET framework versions:

The following frameworks were deprecated and removed from the list of target frameworks:

This discontinuation led to the following modifications:

Usage

The Audit Scope is the central object of this framework. It encapsulates an audit event, controlling its life cycle. The Audit Event is an extensible information container of an audited operation.

There are several ways to create an Audit Scope:

AuditScope options

OptionTypeDescription
EventTypestringA string representing the type of the event
TargetGetterFunc<object>Target object getter (a func that returns the object to track)
ExtraFieldsobjectAnonymous object that contains additional fields to be merged into the audit event
DataProviderAuditDataProviderThe data provider to use. Defaults to the DataProvider configured on Audit.Core.Configuration.DataProvider
CreationPolicyEventCreationPolicyThe creation policy to use. Default is InsertOnEnd
IsCreateAndSaveboolValue indicating whether this scope should be immediately ended and saved after creation. Default is false
AuditEventAuditEventCustom initial audit event to use. By default it will create a new instance of basic AuditEvent
SkipExtraFramesintValue used to indicate how many frames in the stack should be skipped to determine the calling method. Default is 0
CallingMethodMethodBaseSpecific calling method to store on the event. Default is to use the calling stack to determine the calling method.

Suppose you have the following code to cancel an order that you want to audit:

Order order = Db.GetOrder(orderId);
order.Status = -1;
order.OrderItems = null;
order = Db.OrderUpdate(order);

To audit this operation, you can surround the code with a using block that creates an AuditScope, indicating a target object to track:

Order order = Db.GetOrder(orderId);
using (AuditScope.Create("Order:Update", () => order))
{
    order.Status = -1;
    order.OrderItems = null;
    order = Db.OrderUpdate(order);
}

Note

It is not mandatory to use a using block, but it simplifies the syntax when the code to audit is on a single block, allowing the detection of exceptions and calculating the duration by implicitly saving the event on disposal.

Note

When using the extensions that logs interactions with different systems, like Audit.EntityFramework, Audit.WebApi, etc. you don't need to explicitly create the AuditScope or AuditEvent, they are created internally by the extension.

Simple logging

If you are not tracking an object or the duration of an event, you can use the Log shortcut method that logs an event immediately. For example:

AuditScope.Log("Event Type", new { ExtraField = "extra value" });

Manual Saving

You can control the creation and saving logic, by creating a manual AuditScope. For example to log a pair of Start/End method calls as a single event:

public class SomethingThatStartsAndEnds
{
    private AuditScope auditScope;

    public int Status { get; set; }

    public void Start()
    {
        // Create a manual scope
        auditScope = AuditScope.Create(new AuditScopeOptions()
        {
            EventType = "MyEvent",
            TargetGetter = () => this.Status,
            CreationPolicy = EventCreationPolicy.Manual
        });
    }

    public void End()
    {
        // Save the event
        auditScope.Save();  
        // Discard to avoid further saving
        auditScope.Discard();
    }
}

For more information about the EventCreationPolicy please see Event Creation Policy section.

Output

The library will generate an output (AuditEvent) for each operation, including:

An example of the output in JSON:

{
    "EventType": "Order:Update",
    "Environment": {
        "UserName": "Federico",
        "MachineName": "HP",
        "DomainName": "HP",
        "CallingMethodName": "Audit.UnitTest.AuditTests.TestUpdate()",
        "Exception": null,
        "Culture": "en-GB"
    },
    "Activity": {
        "StartTimeUtc": "2023-12-01T17:36:52.2256288Z",
	"SpanId": "23a93b9e8cbc457f",
	"TraceId": "2d3e5e90f790c7d2274d9bb047531f66",
	"ParentId": "0000000000000000",
	"Operation": "Update"
    },
    "StartDate": "2016-08-23T11:33:14.653191Z",
    "EndDate": "2016-08-23T11:33:23.1820786Z",
    "Duration": 8529,
    "Target": {
        "Type": "Order",
        "Old": {
            "OrderId": "39dc0d86-d5fc-4d2e-b918-fb1a97710c99",
            "Status": 2,
            "OrderItems": [{
                "Sku": "1002",
                "Quantity": 3.0
            }]
        },
        "New": {
            "OrderId": "39dc0d86-d5fc-4d2e-b918-fb1a97710c99",
            "Status": -1,
            "OrderItems": null
        }
    }
}

Output details

The following tables describe the output fields:

Field NameTypeDescription
EventTypestringUser-defined string to group the events
EnvironmentEnvironmentContains information about the execution environment
StartDateDateTimeDate and time when the event has started
EndDateDateTimeDate and time when the event has ended
DurationintegerDuration of the event in milliseconds
TargetTargetUser-defined tracked object
CommentsArray of stringsUser-defined comments
CustomFieldsDictionaryUser-defined custom fields
Field NameTypeDescription
UserNamestringCurrent logged user name
MachineNamestringExecuting machine name
DomainNamestringCurrent user domain
CallingMethodNamestringCalling method signature information
StackTracestringThe full stack trace at the moment of the audit scope creation (NULL unless it's enabled by configuration)
ExceptionstringIndicates if an Exception has been detected (NULL if no exception has been thrown)
CulturestringCurrent culture identifier
Field NameTypeDescription
TypestringTracked object type name
OldObjectValue of the tracked object at the beginning of the event
NewObjectValue of the tracked object at the end of the event

Custom Fields and Comments

The AuditScope object provides two methods to extend the event output.

For example:

Order order = Db.GetOrder(orderId);
using (var audit = AuditScope.Create("Order:Update", () => order))
{
    audit.SetCustomField("ReferenceId", orderId);
    order.Status = -1;
    order = Db.OrderUpdate(order);
    audit.Comment("Status Updated to Cancelled");
}

You can also set Custom Fields when creating the AuditScope, by passing an anonymous object with the properties you want as extra fields. For example:

using (var audit = AuditScope.Create("Order:Update", () => order, new { ReferenceId = orderId }))
{
    order.Status = -1;
    order = Db.OrderUpdate(order);
    audit.Comment("Status Updated to Cancelled");
}

You can also access the Custom Fields directly from Event.CustomFields property of the scope. For example:

using (var audit = AuditScope.Create("Order:Update", () => order, new { ReferenceId = orderId }))
{
    audit.Event.CustomFields["ReferenceId"] = orderId;
}

Note

Custom fields are not limited to single properties, you can store any object as well, by default they will be JSON serialized.

Extending AuditEvent

Another way to enrich the event output is to create a class inheriting from the AuditEvent class, then you can pass an instance of your class to the AuditScope.Create method. For example:

public class YourAuditEvent : AuditEvent
{
    public Guid ReferenceId { get; set; } = Guid.NewGuid();
}

using (var scope = AuditScope.Create(new AuditScopeOptions { AuditEvent = new YourAuditEvent() }))
{
    //...
}

The output of the previous examples would be:

{
    "EventType": "Order:Update",
    "Environment": {
        "UserName": "Federico",
        "MachineName": "HP",
        "DomainName": "HP",
        "CallingMethodName": "Audit.UnitTest.AuditTests.TestUpdate()",
        "Exception": null,
        "Culture": "en-GB"
    },
    "Target": {
        "Type": "Order",
        "Old": {
            "OrderId": "39dc0d86-d5fc-4d2e-b918-fb1a97710c99",
            "Status": 2,
            
        },
        "New": {
            "OrderId": "39dc0d86-d5fc-4d2e-b918-fb1a97710c99",
            "Status": -1,
            
        }
    },
    "ReferenceId": "39dc0d86-d5fc-4d2e-b918-fb1a97710c99",           // <-- Custom Field
    "Comments": ["Status Updated to Cancelled"],                     // <-- Comments
    "StartDate": "2016-08-23T11:34:44.656101-05:00",
    "EndDate": "2016-08-23T11:34:55.1810821-05:00",
    "Duration": 8531
}

Discard option

The AuditScope object has a Discard() method to allow the user to discard an event. Discarding an event means it won't be saved.

For example, if you want to avoid saving the audit event under certain conditions:

using (var scope = AuditScope.Create(new AuditScopeOptions("SomeEvent", () => someTarget)))
{
    try
    {
        //some operation
        Critical.Operation();
    }
    catch (Exception ex)
    {
        //If an exception is thrown, discard the audit event
        scope.Discard();
    }
}

Data providers

A data provider (or storage sink) contains the logic to handle the audit event output, where you define what to do with the audit logs.

You can use one of the data providers included or inject your own mechanism by creating a class that inherits from AuditDataProvider and overrides its methods:

If your data provider will support asynchronous operations, you must also implement the following methods:

Also, if your data provider will support event retrieval, you should implement the following methods:

For example:

public class MyCustomDataProvider : AuditDataProvider
{
    public override object InsertEvent(AuditEvent auditEvent)
    {
        var fileName = $"Log{Guid.NewGuid()}.json";
        File.WriteAllText(fileName, auditEvent.ToJson());
        return fileName;
    }
    public override void ReplaceEvent(object eventId, AuditEvent auditEvent)
    {
        var fileName = eventId.ToString();
        File.WriteAllText(fileName, auditEvent.ToJson());
    }
    public override T GetEvent<T>(object eventId)
    {
        var fileName = eventId.ToString();
        return JsonConvert.DeserializeObject<T>(File.ReadAllText(fileName));
    }
    // async implementation:
    public override async Task<object> InsertEventAsync(AuditEvent auditEvent, CancellationToken cancellationToken = default)
    {
        var fileName = $"Log{Guid.NewGuid()}.json";
        await File.WriteAllTextAsync(fileName, auditEvent.ToJson(), cancellationToken);
        return fileName;
    }
    public override async Task ReplaceEventAsync(object eventId, AuditEvent auditEvent, CancellationToken cancellationToken = default)
    {
        var fileName = eventId.ToString();
        await File.WriteAllTextAsync(fileName, auditEvent.ToJson(), cancellationToken);
    }
    public override async Task<T> GetEventAsync<T>(object eventId, CancellationToken cancellationToken = default)
    {
        var fileName = eventId.ToString();
        return await GetFromFileAsync<T>(cancellationToken);
    }
}

Data provider selection

The data provider can be set globally for the entire application or per audit scope.

Note

If you don't specify a global data provider, it will default to a FileDataProvider that logs events as .json files into the current working directory.

To set the global data provider, assign the DataProvider property on the static Audit.Core.Configuration object, or call the fluent API Use(). For example:

Audit.Core.Configuration.DataProvider = new MyCustomDataProvider();

Or using the fluent API Use() method:

Audit.Core.Configuration.Setup()
  .Use(new MyCustomDataProvider());

To set the data provider per-scope, use the AuditScopeOptions when creating an AuditScope. For example:

var scope = AuditScope.Create(new AuditScopeOptions 
{ 
  DataProvider = new MyCustomDataProvider(), ... }
);

Every data provider is accompanied by a fluent API accessible during object construction or via its respective Use___() method. For instance, in the case of the SqlDataProvider:

var sqlDataProvider = new SqlDataProvider(_ => _
    .ConnectionString("your connection string")
    .TableName("your table name")
    .IdColumnName("your id column name")
    .JsonColumnName("your json column name"));
Audit.Core.Configuration.Setup()
  .UseSqlServer(_ => _
    .ConnectionString("your connection string")
    .TableName("your table name")
    .IdColumnName("your id column name")
    .JsonColumnName("your json column name"));

Data provider wrappers

A special type of Data Providers that allows wrapping other Data Provider with different purposes.

Dynamic data provider

As an alternative to creating a data provider class, you can define the mechanism at run time by using the DynamicDataProvider or DynamicAsyncDataProvider classes. For example:

Audit.Core.Configuration.Setup()
  .UseDynamicProvider(config => config
    .OnInsert(ev => Console.Write(ev.ToJson())));

For async operations, you should use the DynamicAsyncDataProvider, for example:

Audit.Core.Configuration.Setup()
  .UseDynamicAsyncProvider(config => config
    .OnInsert(async ev => await File.WriteAllTextAsync(filePath, ev.ToJson())));

Lazy Factory data provider

You can set the global data provider using a deferred instantiation technique, with a lazy factory method that will be called upon its initial utilization. For instance, in situations where dependency resolution is needed but not immediately accessible during initialization.

Allows to lazily instantiate the data provider to use. The data provider factory method will be called only once; the first time it's needed.

For example:

Audit.Core.Configuration.Setup()
    .UseLazyFactory(() => app.ApplicationServices.GetService<CustomDataProvider>());

Deferred Factory data provider

You can defer creating the data provider for each Audit Event until it is ready to be saved by using a deferred factory method. The factory method will be called for each audit event being saved.

For example:

var sqlDataProvider = new SqlDataProvider(config => config...);
var fileDataProvider = new FileDataProvider(config => config...);

Audit.Core.Configuration.Setup()
    .UseDeferredFactory(auditEvent => auditEvent is AuditEventWebApi ? sqlDataProvider : fileDataProvider);

Conditional data provider

Enables the configuration of different data providers based on conditions related to the audit event.

For example:

Configuration.DataProvider = new ConditionalDataProvider(config => config
  .When(auditEvent => auditEvent.EventType.Equals("A"), new MyCustomDataProvider())
  .When(auditEvent => auditEvent.EventType.Equals("B"), new SqlDataProvider())
  .Otherwise(new FileDataProvider()));

Polly data provider

Allows to define Polly resilience strategies to any Data Provider.

This is useful when you want to add resilience to your data provider, for example, to retry failed operations, or to add a circuit breaker.

For example:

Audit.Core.Configuration.Setup()
  .UsePolly(p => p
    .DataProvider(new SqlDataProvider(...))
    .WithResilience(resilience => resilience
      .AddRetry(new()
      {
        ShouldHandle = new PredicateBuilder().Handle<SqlException>(),
        MaxRetryAttempts = 2
      })));

For more information, please refer to the Audit.NET.Polly documentation.

Data providers included

The Data Providers included are summarized in the following table:

TypeTechnologyPackage / ClassDescriptionConfiguration API
SQLAmazon QLDBAudit.NET.AmazonQLDB / AmazonQldbDataProviderStore the audit events using Amazon QLDB..UseAmazonQldb()
SQLEntity FrameworkAudit.EntityFramework / EntityFrameworkDataProviderStore EntityFramework audit events in the same EF context. (This data provider can only be used for Entity Framework audits).UseEntityFramework()
SQLMySqlAudit.NET.MySql / MySqlDataProviderStore the events as rows in a MySQL database table, in JSON format..UseMySql()
SQLPostgre SQLAudit.NET.PostgreSql / PostgreSqlDataProviderStore the events as rows in a PostgreSQL database table, in JSON format..UsePostgreSql()
SQLSQL ServerAudit.NET.SqlServer / SqlDataProviderStore the events as rows in a MS SQL Table, in JSON format..UseSqlServer()
NoSQLAzure CosmosAudit.NET.AzureCosmos / AzureCosmosDataProviderStore the events in an Azure Cosmos DB container, in JSON format..UseAzureCosmos()
NoSQLAzure StorageAudit.NET.AzureStorageBlobs / AzureStorageBlobDataProviderStore the events in an Azure Blob Storage container, in JSON format..UseAzureStorageBlobs()
NoSQLAzure TablesAudit.NET.AzureStorageTables / AzureStorageTableDataProviderStore the events in an Azure Table Storage..UseAzureTableStorage()
NoSQLDynamo DBAudit.NET.DynamoDB / DynamoDataProviderStore audit events in Amazon DynamoDB™ tables..UseDynamoDB()
NoSQLElasticsearchAudit.NET.Elasticsearch / ElasticsearchDataProviderStore audit events in Elasticsearch indices..UseElasticsearch()
NoSQLKafkaAudit.NET.Kafka / KafkaDataProviderStream the audit events to Apache Kafka topics..UseKafka() / .UseKafka<TKey>()
NoSQLMongo DBAudit.NET.MongoDB / MongoDataProviderStore the events in a Mongo DB collection, in BSON format..UseMongoDB()
NoSQLRaven DBAudit.NET.RavenDB / RavenDbDataProviderStore the events as documents in a Raven DB database table, in JSON format..UseRavenDB()
NoSQLRedisAudit.NET.Redis / RedisDataProviderStore audit logs in Redis as Strings, Lists, SortedSets, Hashes, Streams or publish to a PubSub channel..UseRedis()
LocalWindows Event LogAudit.NET / Audit.NET.EventLog.Core 7 EventLogDataProviderWrite the audit logs to the Windows EventLog..UseEventLogProvider()
LocalFile SystemAudit.NET / FileDataProviderStore the audit logs as files. Dynamically configure the directory and path..UseFileLogProvider()
InMemoryIn-Memory ListAudit.NET / InMemoryDataProviderStore the audit logs in memory in a thread-safe list. Useful for testing purposes..UseInMemoryProvider()
InMemoryIn-Memory Blocking CollectionAudit.NET / BlockingCollectionDataProviderStore the audit events in a BlockingCollection that can be accessed by different threads to consume the events.UseInMemoryBlockingCollectionProvider()
InMemoryIn-Memory ChannelAudit.NET.Channels / ChannelDataProviderStore the audit events in a Channel (from System.Threading.Channels) that can be accessed to consume the events.UseInMemoryChannelProvider()
LoggingLog4netAudit.NET.log4net / Log4netDataProviderStore the audit events using Apache log4net™..UseLog4net()
LoggingNLogAudit.NET.NLog / NLogDataProviderStore the audit events using NLog..UseNLog()
LoggingSerilogAudit.NET.Serilog / SerilogDataProviderStore the audit events using Serilog™.UseSerilog()
NetworkUDPAudit.NET.Udp / UdpDataProviderSend Audit Logs as UDP datagrams to a network..UseUdp()
WrapperConditionalAudit.NET / ConditionalDataProviderAllows the configuration of different data providers based on conditions related to the audit event..UseConditional()
WrapperDeferredAudit.NET / DeferredDataProviderFacilitates delayed data provider instantiation via a factory method that is invoked for each Audit Event..UseDeferredFactory()
WrapperDynamicAudit.NET / DynamicDataProvider / DynamicAsyncDataProviderDynamically change the behavior at run-time. Define Insert and a Replace actions with lambda expressions..UseDynamicProvider() / .UseDynamicAsyncProvider()
WrapperLazyAudit.NET / LazyDataProviderFacilitates delayed data provider instantiation via a factory method that is invoked just once, upon the initial need..UseLazyFactory()
WrapperPollyAudit.NET.Polly / PollyDataProviderAllows to define Polly resilience strategies to any Data Provider.UsePolly()

Event Creation Policy

The audit scope can be configured to call its data provider in different ways:

You can set the Creation Policy per scope, for example, to explicitly set the Creation Policy to Manual:

using (var scope = AuditScope.Create(new AuditScopeOptions { CreationPolicy = EventCreationPolicy.Manual }))
{
    //...
    scope.Save();
}

Note

If you don't provide a Creation Policy, the default Creation Policy configured will be used (see the configuration section).

AuditScope statechart

The following is the internal state machine representation of the AuditScope object:

<img src="https://i.imgur.com/7WqGECe.png" alt="AuditScope statecart" />

Configuration

Data provider

To change the default data provider, set the static property DataProvider on Audit.Core.Configuration class. This should be done before the AuditScope creation, i.e. during application startup.

For example, to set your own provider as the default data provider:

Audit.Core.Configuration.DataProvider = new MyCustomDataProvider();

Note

If you don't specify a Data Provider, a default FileDataProvider will be used to write the events as .json files into the current working directory.

Creation Policy

To change the default creation policy, set the static property CreationPolicy on Audit.Core.Configuration class. This should be done before the AuditScope creation, i.e. during application startup.

For example, to set the default creation policy to Manual:

Audit.Core.Configuration.CreationPolicy = EventCreationPolicy.Manual;

Note

If you don't specify a Creation Policy, the default Insert on End will be used.

Custom Actions

You can configure Custom Actions that are executed for all the Audit Scopes in your application. This allows to globally change the behavior and data, intercepting the scopes after they are created or before they are saved.

Call the static AddCustomAction() method on Audit.Core.Configuration class to attach a custom action.

For example, to globally discard the events under a certain condition:

Audit.Core.Configuration.AddCustomAction(ActionType.OnScopeCreated, scope =>
{
    if (DateTime.Now.Hour == 17) // Tea time
    {
        scope.Discard();
    }
});

Or to add custom fields/comments globally to all scopes:

Audit.Core.Configuration.AddCustomAction(ActionType.OnEventSaving, scope =>
{
    if (scope.Event.Environment.Exception != null)
    {
        scope.SetCustomField("Oops", true);
    }
    scope.Comment("Saved at " + DateTime.Now);
});

Custom actions can also be asynchronous, for example:

Audit.Core.Configuration.AddCustomAction(ActionType.OnScopeCreated, async scope =>
{
    var result = await svcProvider.GetService<InfoService>().GetInfoAsync();
    scope.SetCustomField("Info", result);
});

The ActionType indicates when to perform the action. The allowed values are:

Stack Trace

To include the stack trace details into the event environment, ensure that the IncludeStackTrace configuration is set to true. Default is false.

Audit.Core.Configuration.IncludeStackTrace = true;

or

Audit.Core.Configuration.Setup()
    .IncludeStackTrace();

Activity Trace

To include the current activity trace details from System.Diagnostics.Activity API into the event, ensure that the IncludeActivityTrace configuration is set to true. The default is false.

It will include the current Activity operation name, ID, and StartTime, along with associated Tags and Events.

Audit.Core.Configuration.IncludeActivityTrace = true;

or

Audit.Core.Configuration.Setup()
    .IncludeActivityTrace();

To create and start a new distributed activity trace, you can use the StartActivityTrace configuration:

Audit.Core.Configuration.Setup()
    .StartActivityTrace();

Global switch off

You can disable audit logging by setting the static property Configuration.AuditDisabled to true. The audit events are globally ignored while this flag is set. For example to disable the audits on certain environments:

if (environment.IsDevelopment())
{
    Audit.Core.Configuration.AuditDisabled = true;
}

Global serialization settings

Most of the data providers serialize audit events in JSON format. Audit.NET uses System.Text.Json by default for the serialization and deserialization of audit events.

If you want to change the behavior, you can change the settings via the static property Configuration.JsonSettings.

For example:

Audit.Core.Configuration.JsonSettings = new JsonSerializerOptions
{
    DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingDefault,
    AllowTrailingCommas = true
};

Custom serialization mechanism

If you want to use a custom JSON serialization mechanism for the Audit Events, you can create a class implementing IJsonAdapter and assign it to the static property Configuration.JsonAdapter.

For example:

Audit.Core.Configuration.JsonAdapter = new MyCustomAdapter(); 

Or by using the fluent API:

Audit.Core.Configuration.Setup()
    .JsonAdapter<MyCustomAdapter>()
    ...

Note

Take into account that some of the AuditEvent properties rely on attribute decoration for serialization and deserialization. The recommendation is to use the default adapter and, when needed, use the Newtonsoft Json adapter provided (see next section).

Alternative serialization mechanism

This library offers the option to configure an alternative JSON serialization mechanism through the following adapter:

Configuration Fluent API

Alternatively to the properties/methods mentioned before, you can configure the library using a convenient Fluent API provided by the method Audit.Core.Configuration.Setup(), this is the most straightforward way to configure the library.

For example, to set the FileLog Provider with its default settings using a Manual creation policy:

Audit.Core.Configuration.Setup
    .IncludeStackTrace()
    .IncludeActivityTrace()
    .UseFileLogProvider()
    .WithCreationPolicy(EventCreationPolicy.Manual);

Configuration examples

File log provider with dynamic directory path and filename:
Audit.Core.Configuration.Setup()
    .UseFileLogProvider(config => config
        .DirectoryBuilder(_ => $@"C:\Logs\{DateTime.Now:yyyy-MM-dd}")
        .FilenameBuilder(auditEvent => $"{auditEvent.Environment.UserName}_{DateTime.Now.Ticks}.json"));
File log provider with an InsertOnStart-ReplaceOnEnd creation policy, and a global custom field set in a custom action:
Audit.Core.Configuration.Setup()
    .UseFileLogProvider(config => config
        .FilenamePrefix("Event_")
        .Directory(@"C:\AuditLogs\1"))
    .WithCreationPolicy(EventCreationPolicy.InsertOnStartReplaceOnEnd)
    .WithAction(x => x.OnScopeCreated(scope => scope.SetCustomField("ApplicationId", "MyApplication")));
Event log provider with an InsertOnEnd creation policy:
Audit.Core.Configuration.Setup()
    .UseEventLogProvider(config => config
        .SourcePath("My Audited Application")
        .LogName("Application"))
    .WithCreationPolicy(EventCreationPolicy.InsertOnEnd);
Dynamic provider to log to the console:
Audit.Core.Configuration.Setup()
    .UseDynamicProvider(config => config
        .OnInsert(ev => Console.WriteLine("{0}: {1}->{2}", ev.StartDate, ev.Environment.UserName, ev.EventType)));
Multiple providers with conditional logic:
var sqlDataProvider = new SqlDataProvider(sql => sql.ConnectionString(CnnString).TableName("Logs"));
var fileDataProvider = new FileDataProvider(file => file.Directory(@"C:\logs"));

Audit.Core.Configuration.Setup()
    .UseConditional(c => c
        .When(ev => ev.EventType == "API", sqlDataProvider)
        .Otherwise(fileDataProvider));

Extensions

The following packages are extensions to log interactions with different systems such as MVC, WebApi, WCF, and Entity Framework:

<a></a>PackageDescription
<img src="https://i.imgur.com/hVMM5WF.png" alt="icon" width="90"/>Audit.DynamicProxyGenerate detailed audit logs for any class without changing its code by using a proxy.
<img src="https://i.imgur.com/wdVHFoc.png" alt="icon" width="90"/>Audit.EntityFrameworkGenerate detailed audit logs for saving operations on Entity Framework, by inheriting from a provided DbContext or IdentityDbContext. Includes support for EF 6 and EF 7 (EF Core).
<img src="https://i.imgur.com/Fn4thn0.png" alt="icon" width="90"/>Audit.FileSystemGenerate audit logs by intercepting file system events via FileSystemWatcher.
<img src="https://i.imgur.com/8lV5DRk.png" alt="icon" width="90" />Audit.HttpClientGenerate detailed client-side audit logs for HttpClient REST calls, by configuring a provided message handler.
<img src="https://i.imgur.com/ap6CeoG.png" alt="icon" width="90"/>Audit.MVCGenerate detailed audit logs by decorating MVC Actions and Controllers with an action filter attribute. Includes support for ASP.NET Core MVC.
<img src="https://i.imgur.com/GB2e52X.jpg" alt="icon" width="90"/>Audit.SignalRGenerate audit logs for SignalR and SignalR Core invocations by intercepting the hub processing
<img src="https://i.imgur.com/p6knit4.png" alt="icon" width="90" />Audit.WCFGenerate detailed server-side audit logs for Windows Communication Foundation (WCF) service calls, by configuring a provided behavior.
<img src="https://i.imgur.com/p6knit4.png" alt="icon" width="90" />Audit.WCF.ClientGenerate detailed client-side audit logs for Windows Communication Foundation (WCF) service calls, by configuring a provided behavior.
<img src="https://i.imgur.com/9go2b0f.png" alt="icon" width="90"/>Audit.WebApiGenerate detailed audit logs by decorating Web API Methods and Controllers with an action filter attribute, or by using a middleware. Includes support for ASP.NET Core.
<img src="https://i.imgur.com/1nMVLQo.png" alt="icon" width="90"/>Audit.MongoClientGenerate detailed audit logs by adding a Command Event Subscriber into the configuration of the MongoDB Driver.

Storage providers

Apart from the FileLog, EventLog and Dynamic event storage providers, there are others included in different packages:

<a></a>PackageDescription
<img width="80" src="https://unpkg.com/simple-icons@v11/icons/amazondynamodb.svg" />Audit.NET.AmazonQLDBStore the audit events in Amazon QLDB (Quantum Ledger Database).
<img width="80" src="https://unpkg.com/simple-icons@v11/icons/microsoftazure.svg" />Audit.NET.AzureCosmosStore the events in an Azure Cosmos DB container, in JSON format.
<img width="80" src="https://unpkg.com/simple-icons@v11/icons/microsoftazure.svg" />Audit.NET.AzureStorageStore the events in an Azure Blob Storage container or an Azure Table using the legacy client WindowsAzure.Storage.
<img width="80" src="https://unpkg.com/simple-icons@v11/icons/microsoftazure.svg" />Audit.NET.AzureStorageBlobsStore the events in an Azure Blob Storage container using the latest client Azure.Storage.Blobs.
<img width="80" src="https://unpkg.com/simple-icons@v11/icons/microsoftazure.svg" />Audit.NET.AzureStorageTablesStore the events in an Azure Table Storage using the latest client Azure.Data.Tables.
<img width="80" src="https://unpkg.com/simple-icons@v11/icons/csharp.svg" />Audit.NET.ChannelsStore the audit events in a Channel (from System.Threading.Channels) that can be accessed to consume the events.
<img width="80" src="https://unpkg.com/simple-icons@v11/icons/amazondynamodb.svg" />Audit.NET.DynamoDBStore the audit events in Amazon DynamoDB tables.
<img width="80" src="https://unpkg.com/simple-icons@v11/icons/elasticsearch.svg" />Audit.NET.ElasticsearchStore the audit events in Elasticsearch indices.
<img width="80" src="https://unpkg.com/simple-icons@v11/icons/apachekafka.svg" />Audit.NET.KafkaStream the audit events to an Apache Kafka server.
<img width="80" src="https://unpkg.com/simple-icons@v11/icons/csharp.svg" />Audit.NET.log4netStore the audit events using Apache log4net™.
<img width="80" src="https://unpkg.com/simple-icons@v11/icons/mongodb.svg" />Audit.NET.MongoDBStore the events in a Mongo DB Collection, in BSON format.
<img width="80" src="https://unpkg.com/simple-icons@v11/icons/mysql.svg" />Audit.NET.MySqlStore the events as rows in MySQL database, in JSON format.
<img width="80" src="https://unpkg.com/simple-icons@v11/icons/csharp.svg" />Audit.NET.NLogStore the audit events using NLog™.
<img width="80" src="https://unpkg.com/simple-icons@v11/icons/csharp.svg" />Audit.NET.PollyDefine Polly resiliencie strategies to any data provider.
<img width="80" src="https://unpkg.com/simple-icons@v11/icons/postgresql.svg" />Audit.NET.PostgreSqlStore the events as rows in a PostgreSQL database, in JSON format.
<img width="80" src="https://unpkg.com/simple-icons@v11/icons/csharp.svg" />Audit.NET.RavenDBStore the events as documents in a Raven DB database, in JSON format.
<img width="80" src="https://unpkg.com/simple-icons@v11/icons/redis.svg" />Audit.NET.RedisStore Audit Logs in a Redis database as String, List, Hash, Sorted Set, Streams or publishing to a Redis PubSub channel.
<img width="80" src="https://unpkg.com/simple-icons@v11/icons/microsoftsqlserver.svg" />Audit.NET.SqlServerStore the events as rows in a SQL Table, in JSON format.
<img width="80" src="https://unpkg.com/simple-icons@v11/icons/csharp.svg" />Audit.NET.SerilogStore the audit events using Serilog™
<img width="80" src="https://unpkg.com/simple-icons@v11/icons/csharp.svg" />Audit.NET.UdpSend audit events as UDP datagrams to a network.

Change Log

For detailed information on changes in the new release refer to the change log.

Contribute

If you like this project please contribute in any of the following ways: