{"id":17306861,"url":"https://github.com/skoruba/auditlogging","last_synced_at":"2026-03-11T05:31:34.371Z","repository":{"id":38053559,"uuid":"191358373","full_name":"skoruba/AuditLogging","owner":"skoruba","description":"🕊️ Simple audit logging for .NET Core with EntityFramework Core","archived":false,"fork":false,"pushed_at":"2026-02-23T17:37:46.000Z","size":88,"stargazers_count":120,"open_issues_count":8,"forks_count":45,"subscribers_count":5,"default_branch":"master","last_synced_at":"2026-02-24T00:53:39.951Z","etag":null,"topics":["aspnetcore","audit","audit-log","audit-trail","entityframeworkcore","identityserver4","logger","logging","netcore"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/skoruba.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2019-06-11T11:31:37.000Z","updated_at":"2026-02-23T17:36:55.000Z","dependencies_parsed_at":"2024-12-22T10:11:31.679Z","dependency_job_id":"50b2703c-9379-435c-b0a4-9e95dc02f6b9","html_url":"https://github.com/skoruba/AuditLogging","commit_stats":null,"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"purl":"pkg:github/skoruba/AuditLogging","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skoruba%2FAuditLogging","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skoruba%2FAuditLogging/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skoruba%2FAuditLogging/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skoruba%2FAuditLogging/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/skoruba","download_url":"https://codeload.github.com/skoruba/AuditLogging/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skoruba%2FAuditLogging/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30372170,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-10T21:41:54.280Z","status":"online","status_checked_at":"2026-03-11T02:00:07.027Z","response_time":84,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["aspnetcore","audit","audit-log","audit-trail","entityframeworkcore","identityserver4","logger","logging","netcore"],"created_at":"2024-10-15T11:59:43.705Z","updated_at":"2026-03-11T05:31:34.351Z","avatar_url":"https://github.com/skoruba.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"![Logo](docs/Images/Skoruba-ReadMe.png) \n\n# 🕊️ Skoruba.AuditLogging\n\u003e Simple audit logging for .NET Core with EntityFramework Core support\n\n**This project is ported to .NET 8.** 🚀\n\n# How to install\n\n```ps\ndotnet add package Skoruba.AuditLogging.EntityFramework --version 2.0.0\n```\n\n# How to use it\n\n## Setup for web application and auditing of users:\n\n```csharp\nservices.AddAuditLogging(options =\u003e\n                {\n                    options.Enabled = true;\n                    options.UseDefaultSubject = true;\n                    options.UseDefaultAction = true;\n                })\n                .AddDefaultHttpEventData(subjectOptions =\u003e\n                    {\n                        subjectOptions.SubjectIdentifierClaim = ClaimsConsts.Sub;\n                        subjectOptions.SubjectNameClaim = ClaimsConsts.Name;\n                    },\n                    actionOptions =\u003e\n                    {\n                        actionOptions.IncludeFormVariables = true;\n                    })\n                .AddDefaultStore(options =\u003e options.UseSqlServer(Configuration.GetConnectionString(\"ApplicationDbContext\"),\n                    optionsSql =\u003e optionsSql.MigrationsAssembly(migrationsAssembly)))\n                .AddDefaultAuditSink();\n```\n\n## Setup for machine application (e.g. background jobs):\n```csharp\nservices.AddAuditLogging(options =\u003e\n                {\n                    options.UseDefaultAction = false;\n                    options.Source = \"Web\"\n                })\n                .AddStaticEventSubject(subject =\u003e\n                {\n                    subject.SubjectType = AuditSubjectTypes.Machine;\n                    subject.SubjectIdentifier = EmailServiceConsts.Name;\n                    subject.SubjectName = Environment.MachineName;\n                })\n                .AddDefaultEventAction()\n                .AddStore\u003cApplicationDbContext, AuditLog, AuditLoggingRepository\u003cApplicationDbContext, AuditLog\u003e\u003e(options =\u003e\n                    options.UseSqlServer(configuration.GetConnectionString(\"ApplicationDbConnection\"),\n                        optionsSql =\u003e optionsSql.MigrationsAssembly(migrationsAssembly)))\n                .AddDefaultAuditSink();\n```\n\n\n## Usage in code\n\n```csharp\n            // Create fake product\n            var productDto = new ProductDto\n            {\n                Id = Guid.NewGuid().ToString(),\n                Name = Guid.NewGuid().ToString(),\n                Category = Guid.NewGuid().ToString()\n            };\n\n            // Log this action\n            var productGetUserEvent = new ProductGetEvent\n            {\n                Product = productDto\n            };           \n```\n\n### Logging for user action\n```csharp\n await _auditEventLogger.LogEventAsync(productGetUserEvent);\n```\n\n### Logging for machine action\n```csharp\nvar productGetMachineEvent = new ProductGetEvent\n            {\n                Product = productDto,\n                SubjectType = AuditSubjectTypes.Machine,\n                SubjectName = Environment.MachineName,\n                SubjectIdentifier = Environment.MachineName,\n                Action = new { Method = nameof(Get), Class = nameof(AuditController) }\n            };\n\n            await _auditEventLogger.LogEventAsync(productGetMachineEvent, options =\u003e\n                {\n                    options.UseDefaultSubject = false;\n                    options.UseDefaultAction = false;\n                });\n```\n\n**ProductAddedEvent.cs**\n```csharp\npublic class ProductAddedEvent : AuditEvent\n    {\n        public ProductDto ProductDto { get; set; }  \n    }\n```\n\n## AuditEvent - base event for logger\n\n| Property              | Description                                             |\n|-----------------------|---------------------------------------------------------|\n| Event                 | Name of event                                           |\n| Source                | Source of logging events                                |\n| Category              | Event category                                          |\n| SubjectIdentifier     | Identifier of caller which is responsible for the event |\n| SubjectName           | Name of caller which is responsible for the event       |\n| SubjectType           | Subject Type (eg. User/Machine)                         |\n| SubjectAdditionalData | Additional information for subject                      |\n| Action                | Information about request/action                        |\n\n## AuditLog - database table\n\n| Property              | Description                                             |\n|-----------------------|---------------------------------------------------------|\n| Id                    | Database unique identifier for event                    |\n| Event                 | Name of event                                           |\n| Source                | Source of logging events                                |\n| Category              | Event category                                          |\n| SubjectIdentifier     | Identifier of caller which is responsible for the event |\n| SubjectName           | Name of caller which is responsible for the event       |\n| SubjectType           | Subject Type (eg. User/Machine)                         |\n| SubjectAdditionalData | Additional information for subject                      |\n| Action                | Information about request/action                        |\n| Data                  | Data which are serialized into JSON format              |\n| Created               | Date and time for creating of the event                 |\n\n## Setup default IAuditSubject and IAuditAction\n\n## `IAuditSubject`\n**Default subject implementation for HTTP calls:**\n\n```csharp\npublic class AuditHttpSubject : IAuditSubject\n    {\n        public AuditHttpSubject(IHttpContextAccessor accessor, AuditHttpSubjectOptions options)\n        {\n            SubjectIdentifier = accessor.HttpContext.User.FindFirst(options.SubjectIdentifierClaim)?.Value;\n            SubjectName = accessor.HttpContext.User.FindFirst(options.SubjectNameClaim)?.Value;\n            SubjectAdditionalData = new\n            {\n                RemoteIpAddress = accessor.HttpContext.Connection?.RemoteIpAddress?.ToString(),\n                LocalIpAddress = accessor.HttpContext.Connection?.LocalIpAddress?.ToString(),\n                Claims = accessor.HttpContext.User.Claims?.Select(x=\u003e new { x.Type, x.Value })\n            };\n        }\n\n        public string SubjectName { get; set; }\n\n        public string SubjectType { get; set; } = AuditSubjectTypes.User;\n\n        public object SubjectAdditionalData { get; set; }\n\n        public string SubjectIdentifier { get; set; }\n    }\n```\n\n## `IAuditAction`\n**Default action implementation for HTTP calls:**\n```csharp\npublic class AuditHttpAction : IAuditAction\n    {\n        public AuditHttpAction(IHttpContextAccessor accessor, AuditHttpActionOptions options)\n        {\n            Action = new\n            {\n                TraceIdentifier = accessor.HttpContext.TraceIdentifier,\n                RequestUrl = accessor.HttpContext.Request.GetDisplayUrl(),\n                HttpMethod = accessor.HttpContext.Request.Method,\n                FormVariables = options.IncludeFormVariables ? HttpContextHelpers.GetFormVariables(accessor.HttpContext) : null\n            };\n        }\n\n        public object Action { get; set; }\n    }\n```\n\n## Sinks\n\n### Database migrations\n\n```ps\ndotnet ef migrations add DbInit -c DefaultAuditLoggingDbContext -o Data/Migrations\ndotnet ef database update -c DefaultAuditLoggingDbContext\n```\n\n### Database sink via EntityFramework Core - `DatabaseAuditEventLoggerSink`\n\n- By default it is used database sink via EntityFramework Core, for registration this default sink - it is required to register this method:\n\n```csharp\n.AddDefaultStore(options =\u003e options.UseSqlServer(Configuration.GetConnectionString(\"ApplicationDbContext\"),\n                    optionsSql =\u003e optionsSql.MigrationsAssembly(migrationsAssembly)))\n                .AddDefaultAuditSink()\n```\n\n### AddDefaultStore:\n\n- This method register default implementation of:\n\n- `DefaultAuditLoggingDbContext` - Default DbContext for access to database\n- `AuditLog` - Entity for logging all audit stuff\n- `AuditLoggingRepository` - Repository for access to database, which contains GRUD method for access to `AuditLog` table.\n\n- In the background it is used method called: `AddStore` - which is possible to use instead of AddDefaultStore and specify individual implementation of these objects above\n```csharp\nbuilder.AddStore\u003cDefaultAuditLoggingDbContext, AuditLog, AuditLoggingRepository\u003cDefaultAuditLoggingDbContext, AuditLog\u003e\u003e(dbContextOptions);\n```\n\n### AddDefaultAuditSink:\n\n- This method is for registration of default Sink:\n\n```csharp\nbuilder.AddAuditSinks\u003cDatabaseAuditEventLoggerSink\u003cAuditLog\u003e\u003e();\n```\n\n# How to use own Sink\n\n- It is necessary to implement interface `IAuditEventLoggerSink` and one single method called:\n\n```csharp\nTask PersistAsync(AuditEvent auditEvent);\n```\n\n- Then you can register your new sink via method - `.AddAuditSinks\u003c\u003e` - which has overload for maximum 8 sinks.\n\n# Example\n\n## Source code\n- Please, check out the project `Skoruba.AuditLogging.Host` - which contains example with Asp.Net Core API - with fake authentication for testing purpose only. 😊\n\n## Output in JSON format\n\n```json\n{\n      \"Id\":1,\n      \"Event\":\"ProductGetEvent\",\n      \"Category\":\"Web\",\n      \"SubjectIdentifier\":\"30256997-4096-428d-bfc7-8593d263b8eb\",\n      \"SubjectName\":\"bob\",\n      \"SubjectType\":\"User\",\n      \"SubjectAdditionalData\":{\n         \"RemoteIpAddress\":\"::1\",\n         \"LocalIpAddress\":\"::1\",\n         \"Claims\":[\n            {\n               \"Type\":\"name\",\n               \"Value\":\"bob\"\n            },\n            {\n               \"Type\":\"sub\",\n               \"Value\":\"30256997-4096-428d-bfc7-8593d263b8eb\"\n            },\n            {\n               \"Type\":\"role\",\n               \"Value\":\"31fad6ad-9df3-4e7f-b73f-68dc7d2636c6\"\n            }\n         ]\n      },\n      \"Action\":{\n         \"TraceIdentifier\":\"80000025-0000-ff00-b63f-84710c7967bb\",\n         \"RequestUrl\":\"https://localhost:44319/api/audit\",\n         \"HttpMethod\":\"GET\"\n      },\n      \"Data\":{\n         \"Product\":{\n            \"Id\":\"7d7138b6-e5c3-4548-814c-9119ddb1f785\",\n            \"Name\":\"c9bc91fe-79f2-439b-8bfa-be3f71947b63\",\n            \"Category\":\"b3f2f9d2-67d5-4b52-8156-04232adf0c4b\"\n         }\n      },\n      \"Created\":\"2019-09-09T12:03:12.7729634\"\n   }\n```\n\n# Licence\nThis repository is licensed under the terms of the MIT license.\n\n**NOTE:** This repository uses the source code from https://github.com/IdentityServer/IdentityServer4 which is under the terms of the **[Apache License 2.0](https://github.com/IdentityServer/IdentityServer4/blob/master/LICENSE)**.\n\n# Acknowledgements\n\n- This library is inspired by [EventService from IdentityServer4](https://github.com/IdentityServer/IdentityServer4).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fskoruba%2Fauditlogging","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fskoruba%2Fauditlogging","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fskoruba%2Fauditlogging/lists"}