Audit.NET: an extensible audit framework for .NET operations
An extensible framework to audit executing operations in .NET
At a glance
- What is it?
- Audit.NET is a C# library that records who ran an operation, on which machine, how long it took and what it changed, then hands the record to a data provider you choose. Its value is in the extension model; its cost is in the wiring.
- Who is it for?
- Adopt Audit.NET if you need operation-level audit records inside a .NET service and you are willing to pick a data provider and a creation policy deliberately. Do not adopt it if a framework-level interceptor already covers your case, or if you expect the base package alone to audit Entity Framework or MVC calls.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 15 days ago.
- What is it written in?
- Mainly C#, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 24, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The gap Audit.NET fills in a .NET service
Application logs answer "what happened in the process". Audit records answer a different question: which operation ran, who triggered it, from which machine, how long it took, and whether it threw. In a .NET service those answers are usually scattered. A controller logs a line, an EF interceptor logs another, exception middleware logs a third, and nothing ties them to a single operation identity.
Audit.NET takes the position that the operation itself is the unit of record. The README describes it as a framework to "audit executing operations in .NET and .NET Core" that captures "the caller's user ID, machine name, method name, exceptions, and execution time". That list is the actual scope. It is not a general-purpose logging facade and it is not a tracing system, although it can emit OpenTelemetry spans through the ActivityDataProvider.
The audience is narrower than the topic list suggests. If you maintain an ASP.NET Core or MVC service, a WCF service, a WebAPI service, an Azure Functions app, or a console job where someone will eventually ask "who deleted this row", the framework is aimed at you. If you only need request timing or structured diagnostics, a logging library already does that with less configuration.
How an audit event is built and where it goes
The design separates two concerns that most logging stacks merge. One side decides what an event contains; the other decides where the event ends up.
On the capture side, interaction extensions hook into a host system and produce an AuditEvent. The README lists Entity Framework, MVC, WebAPI, WCF, WCF Client, File System, SignalR, MongoClient, gRPC Client, gRPC Server, MediatR, Hangfire, Azure Functions and HttpClient. Each of these lives in its own package under src/, which is why Audit.NET.sln contains many projects rather than one. The base package knows nothing about EF or MVC.
On the output side, data providers serialize and write the event: JSON Files, Event Log, OpenTelemetry spans, SQL Server, MySQL, PostgreSQL, RavenDB, MongoDB, Azure Blob, Azure Tables, Azure Cosmos, Azure Event Hubs, Redis, Elasticsearch, OpenSearch, DynamoDB, ImmuDB, UDP datagrams and Channels. The list is long, and the practical consequence is that you must choose one before the first event is written.
Between the two sits a set of wrappers the README calls output wrappers: Polly for resilience, Lazy and Deferred factories for lazy instantiation, and a Conditional provider. These wrap another provider rather than replacing it. If your audit store is a remote database, the Polly wrapper is the documented place to put retry behaviour instead of writing it yourself.
Two further knobs shape the output. A creation policy decides whether an event is produced at all, which matters when an operation is called in a tight loop. Custom fields and comments let you attach application-specific data to the event before it is serialized. Both are first-class concepts in the README's navigation, not afterthoughts.
Installing Audit.NET and writing a first audit event
The README gives one installation path: the Package Manager Console command for the base package. That package provides the core event model and the built-in providers, but no host integration. If you are auditing Entity Framework calls, you also need the Entity Framework package; the README links to a separate README under src/Audit.EntityFramework for it.
PM> Install-Package Audit.NETRunning that in the Package Manager Console installs the core package into the selected project. The README does not show a dotnet add package equivalent, so if you work outside Visual Studio, take the package ID from the NuGet link in the README and use your usual package workflow.
The README's navigation lists Usage, Output, Customization, Data Providers, Creation Policy, Configuration and Extensions as the documented topics. Those are the sections to read in that order. Output is where you pick a data provider, and Creation Policy is where you decide when events are produced. The README does not walk through a complete code sample in the excerpt available here, so the honest instruction is to follow the Usage and Output sections of the repository README for the current API rather than copying a snippet from a third-party post.
One thing to settle before writing code: which provider you will use. Writing to JSON files is the lowest-friction option for a first run because the FileDataProvider is part of the base package. Moving to SQL Server, PostgreSQL or MongoDB later means swapping the provider, and the provider-specific READMEs under src/ are where the connection details live.
Where Audit.NET stops being the right tool
The framework records operations that pass through an extension it supports. Anything outside that surface is invisible to it. A raw ADO.NET command, a background thread that mutates state without going through EF or MediatR, a database change made by a DBA: none of these produce an audit event, because nothing in the pipeline raises one.
That boundary has a second edge. Because events are produced by interceptors inside the application process, an attacker with code execution in that process can suppress them. The README does not claim tamper resistance for the file or SQL providers. ImmuDB appears in the provider list, and an immutable store is the documented answer to that concern, but the choice is yours to make and the base package does not enforce it.
Volume is the other failure mode. Capturing an event per operation is expensive when operations are small and frequent. The README documents a creation policy precisely because unconditional capture is not always acceptable. Teams that skip that section and audit every EF query in a hot path will notice it in their storage bill before they notice it in their latency graphs.
Finally, Audit.NET is not a substitute for distributed tracing. It can emit OpenTelemetry spans through the ActivityDataProvider, but the event model is operation-centric, not span-centric. If your question is "why was this request slow across six services", a tracing system answers it more directly.
Audit.NET compared with EF Core's own interceptors
The closest alternative for the Entity Framework case is EF Core's built-in interception and change-tracking APIs. You write a SaveChangesInterceptor or use the ChangeTracker directly, inspect the entries, and write your own record. No extra package, no event model to learn, and full control over the shape of what you store.
The difference is in what you get for free. Audit.NET supplies the environmental fields the README lists (user ID, machine name, method name, exceptions, execution time) and a provider abstraction so the same event can go to SQL Server today and Elasticsearch later without rewriting the capture code. With raw interceptors you write that plumbing yourself, and you write it again for MVC, WCF or MediatR, each in its own idiom.
The trade-off runs the other way too. Raw interceptors add nothing to your dependency graph and cannot fall out of step with the EF version you are on. Audit.NET's integration packages track the host frameworks they wrap, so an EF Core major upgrade means checking whether the corresponding Audit.EntityFramework package has caught up. The CHANGELOG.md at the repository root is the file that answers that question, and it is worth reading before you pin a version.
Maintenance, licence and what an upgrade costs
Audit.NET is MIT licensed. The practical reading of that for a commercial service is that you can use it, modify it and ship it inside a closed product, provided the copyright notice and permission text travel with it. This is not legal advice; if your organisation treats third-party licence review as a formal step, run the LICENSE file at the repository root through that process rather than taking this paragraph as clearance.
The repository is not archived, and the last push was on 2026-09-16. That is recent enough that the project is not abandoned, and the CHANGELOG.md file is the documented place to see what changed between releases. The README also points at a CI workflow under .github/ and a SonarCloud quality gate, so build and static analysis are wired into the repository rather than run by hand.
The upgrade cost is mostly a function of how many extension packages you use. A service that audits EF Core only has one integration package to track. A service that audits EF Core, MVC, WebAPI and HttpClient has four, and each one follows its host framework's release cadence. The base package and the provider packages are a separate axis: switching from SQL Server to PostgreSQL is a provider swap, but it is still a code change and a redeployment, not a configuration toggle. Budget for it the first time you need to move a store.
Editorial conclusion
Adopt Audit.NET if you need operation-level audit records inside a .NET service and you are willing to pick a data provider and a creation policy deliberately. Do not adopt it if a framework-level interceptor already covers your case, or if you expect the base package alone to audit Entity Framework or MVC calls. Before writing code, confirm the exact NuGet package for your integration, check the CHANGELOG for the version you pin, and read the provider README for the store you intend to use.
Frequently asked questions
How do you use Audit.NET?
Install the base package from NuGet, then add the interaction extension for the system you want to audit, such as Entity Framework, MVC or WebAPI. Choose a data provider for output and a creation policy for when events are produced, both of which the README documents as separate topics.
What is Audit.NET?
It is an extensible framework for auditing executing operations in .NET and .NET Core, written in C# and licensed under MIT. It captures environmental data such as the caller's user ID, machine name, method name, exceptions and execution time, and writes audit logs through a configurable data provider.
What are the alternatives to Audit.NET?
For Entity Framework specifically, EF Core's own SaveChangesInterceptor and ChangeTracker APIs let you build the record yourself with no extra package. Audit.NET adds a shared event model and a provider abstraction across multiple host frameworks, which is the part you would otherwise write repeatedly.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/thepirat000-audit-net)