{"id":30743180,"url":"https://github.com/ukho/eventhub-logging-provider","last_synced_at":"2025-09-04T02:03:54.318Z","repository":{"id":43843578,"uuid":"193504653","full_name":"UKHO/EventHub-Logging-Provider","owner":"UKHO","description":"Log provider for Microsoft.Extensions.Logging to log to Azure EventHub","archived":false,"fork":false,"pushed_at":"2025-07-31T16:02:21.000Z","size":665,"stargazers_count":2,"open_issues_count":12,"forks_count":1,"subscribers_count":10,"default_branch":"main","last_synced_at":"2025-07-31T19:44:05.496Z","etag":null,"topics":["azure","eventhub","logging","nuget"],"latest_commit_sha":null,"homepage":null,"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/UKHO.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":"CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2019-06-24T12:50:52.000Z","updated_at":"2024-06-11T13:06:03.000Z","dependencies_parsed_at":"2025-07-31T18:02:49.832Z","dependency_job_id":"57aa5774-257b-4020-8eb0-8501cfb96574","html_url":"https://github.com/UKHO/EventHub-Logging-Provider","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/UKHO/EventHub-Logging-Provider","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/UKHO%2FEventHub-Logging-Provider","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/UKHO%2FEventHub-Logging-Provider/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/UKHO%2FEventHub-Logging-Provider/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/UKHO%2FEventHub-Logging-Provider/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/UKHO","download_url":"https://codeload.github.com/UKHO/EventHub-Logging-Provider/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/UKHO%2FEventHub-Logging-Provider/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":273539317,"owners_count":25123499,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-04T02:00:08.968Z","response_time":61,"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":["azure","eventhub","logging","nuget"],"created_at":"2025-09-04T02:03:53.515Z","updated_at":"2025-09-04T02:03:54.309Z","avatar_url":"https://github.com/UKHO.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Event Hub Log Provider\n\nThe Event Hub Log Provider provides a logging sink for the Microsoft.Extensions.Logging.Abstractions. Logs are sent to Event Hub as a JSON message. The EventHubLogProvider provides a number of standard properties to enrich every log message, and provides a mechanism to add application specific custom properties to logs.\n\nThe Event Hub Log Provider supports these authentication methods\n\n- Managed Identity (Both Event Hub \u0026 Storage Account)\n- Connection string (for Event Hub) and SAS URI (for Azure Storage container access)\n\nAuthentication methods cannot be mixed between Event Hub and Storage Account, either both use Managed Identity or they use the other authentification method. \n\nInstructions to configure the services with either a managed identity or a connection string are below.\n\n## Getting Started\n\n### Installation Guide\n\nThis package is available from NuGet: UKHO.Logging.EventHubLogProvider\n\n```bash\n    nuget install UKHO.Logging.EventHubLogProvider\n```\n\nThere are two recommended setups depending on the version of .NET: a legacy setup for .NET Core, and a setup for .NET 5/6+.\n\n#### .NET 5/6+ Setup\n\nThe EventHubLogProvider is added to the ```IServiceCollection``` service collection via an ```ILoggingBuilder```.  \n\nNuGet packages can be installed for extensions to the builder, for example adding console logging in the below statement ```loggingBuilder.AddConsole();``` would require installing the package ```ConsoleLoggerExtensions```\n\n#### Configuration using connection string for Event hub\n\n```cs\n    services.AddLogging(loggingBuilder =\u003e\n    {\n        loggingBuilder.AddConfiguration(configuration.GetSection(\"Logging\"));\n        loggingBuilder.AddConsole();\n        loggingBuilder.AddDebug();\n        loggingBuilder.AddAzureWebAppDiagnostics();\n        var eventHubLoggingConfiguration = new EventHubLoggingConfiguration();\n        configuration.GetSection(EventHubLoggingConfiguration.ConfigSection).Bind(eventHubLoggingConfiguration);\n        if (!string.IsNullOrEmpty(eventHubLoggingConfiguration.ConnectionString))\n        {\n            loggingBuilder.AddEventHub(options =\u003e\n            {\n                options.Environment = eventHubLoggingConfiguration.Environment;\n                options.DefaultMinimumLogLevel = (LogLevel)Enum.Parse(typeof(LogLevel), eventHubLoggingConfiguration.MinimumLoggingLevel, true);\n                options.MinimumLogLevels[\"UKHO\"] = (LogLevel)Enum.Parse(typeof(LogLevel), eventHubLoggingConfiguration.UkhoMinimumLoggingLevel, true);\n                options.EventHubConnectionString = eventHubLoggingConfiguration.ConnectionString;\n                options.EventHubEntityPath = eventHubLoggingConfiguration.EntityPath;\n                options.System = eventHubLoggingConfiguration.System;\n                options.Service = eventHubLoggingConfiguration.Service;\n                options.NodeName = eventHubLoggingConfiguration.NodeName;\n                options.AdditionalValuesProvider = ConfigAdditionalValuesProvider;\n            });\n        }\n    });\n```\n\n#### Configuration using Managed identity to Event hub\n\n```cs\nvar eventHubLogProviderOptions = builder.Configuration.GetSection(\"EventHubLogProviderOptions\").Get\u003cEventHubLogProviderOptions\u003e();\nArgumentNullException.ThrowIfNull(eventHubLogProviderOptions);\n\nbuilder.Logging.AddEventHub(options =\u003e\n{         \n    options.EventHubFullyQualifiedNamespace = eventHubLogProviderOptions.EventHubFullyQualifiedNamespace,\n    options.TokenCredential = new DefaultAzureCredential(), \n    options.EventHubEntityPath = eventHubLogProviderOptions.EntityPath;\n    options.EnableConnectionValidation = eventHubLogProviderOptions.EnableConnectionValidation;\n    options.DefaultMinimumLogLevel = eventHubLogProviderOptions.MinimumLoggingLevel;\n    options.MinimumLogLevels[\"UKHO\"] = eventHubLogProviderOptions.UkhoMinimumLoggingLevel;\n\n    options.Environment = eventHubLogProviderOptions.Environment;\n    options.System = eventHubLogProviderOptions.System;\n    options.Service = eventHubLogProviderOptions.Service;\n    options.NodeName = eventHubLogProviderOptions.NodeName;\n    options.AdditionalValuesProvider = ConfigAdditionalValuesProvider;\n});\n```\n\nPlease note that following 2 options are added for authenticating with Managed Identity\n\n- EventHubFullyQualifiedNamespace - The fully qualified Event Hubs namespace to connect to. This is likely to be similar to {yournamespace}.servicebus.windows.net.\n- TokenCredential - The Azure managed identity credential to use for authorization.  \n\n[!NOTE] The application (or user if running in Visual Studio) will require `Azure Event Hubs Data Sender` role on the Event hub. \n\nIf you've upgraded from an earlier version of .NET Core and have not migrated to the new minimal hosting model, i.e., there is still a startup.cs, the above code should be added to the ```ConfigureServices```:\n\n```cs\npublic void ConfigureServices(IServiceCollection services)\n{\n    services.AddLogging(loggingBuilder =\u003e\n    {\n            ...\n}\n\n```\n\nAn ```HttpContextAccessor``` is unavailable in the ```ConfigureServices``` method, however, a reference to it can be acquired in the ```Configure``` method:\n\n```cs\npublic class Startup\n{\n    private readonly IConfiguration configuration;\n    private IHttpContextAccessor _httpContextAccessor;\n...\n\n\npublic void Configure(IApplicationBuilder app,\n                            IWebHostEnvironment env\n                            IHttpContextAccessor httpContextAccessor)\n    {\n        _httpContextAccessor = httpContextAccessor;\n    ...\n```\n\nThen, the additional values can be gathered as follows:\n\n```cs\nprivate void ConfigAdditionalValuesProvider(IDictionary\u003cstring, object\u003e additionalValues)\n{\n    if (_httpContextAccessor.HttpContext != null)\n    {\n        additionalValues[\"_RemoteIPAddress\"] =\n            _httpContextAccessor.HttpContext.Connection.RemoteIpAddress?.ToString();\n\n        additionalValues[\"_User-Agent\"] =\n            _httpContextAccessor.HttpContext.Request.Headers[\"User-Agent\"].FirstOrDefault() ?? string.Empty;\n\n        additionalValues[\"_AssemblyVersion\"] = Assembly\n            .GetExecutingAssembly()\n            .GetCustomAttributes\u003cAssemblyFileVersionAttribute\u003e().Single()\n            .Version;\n\n        additionalValues[\"_X-Correlation-ID\"] =\n            _httpContextAccessor.HttpContext.Request.Headers?[\"\"].FirstOrDefault() ?? string.Empty;\n    }\n}\n```\n\n#### Legacy .NET Core Setup\n\nThe EventHubLogProvider is added to a LoggerFactory as follows:\n\n```cs\nvar connectionString = \"\"; //Connection string to Event Hub with write permissions.\nvar entityPath = \"\"; //Event Hub entity path.\nloggerFactory.AddEventHub(\n    config =\u003e\n    {\n        /*\n        optional(AzureStorageLogProviderOptions)\n        Setting this property and setting (\"AzureStorageOptions:Enabled\") = true \n        enables the azure storage logging provider \n        (for messages with size \u003e= 1Mb)  \n    \n        Please check \"Azure Storage Logging Provider\" for more information.\n        */\n        config.AzureStorageLogProviderOptions = new AzureStorageLogProviderOptions(\n                                        Configuration.GetValue\u003cString\u003e(\"AzureStorageOptions:SasUrl\")\n                                        ,Configuration.GetValue\u003cBoolean\u003e(\"AzureStorageOptions:Enabled\")\n                                        ,Configuration.GetValue\u003cString\u003e (\"AzureStorageOptions:SuccessfulMessageTemplate\") \n                                        ,Configuration.GetValue\u003cString\u003e(\"AzureStorageOptions:FailedMessageTemplate\")\n                                        );\n         \n        \n        config.Environment = \"Production\";\n        config.DefaultMinimumLogLevel = LogLevel.Warning;\n        config.MinimumLogLevels[\"Microsoft.AspNetCore\"] = LogLevel.Trace;\n        config.MinimumLogLevels[\"Microsoft.AspNetCore.Server\"] = LogLevel.Error;\n        config.EventHubConnectionString = connectionString;\n        config.EventHubEntityPath = entityPath;\n        config.System = \"My System Name\";\n        config.Service = \"My Service Name\";\n        config.NodeName = \"Node 123\";\n        config.AdditionalValuesProvider = additionalValues =\u003e\n                                        {\n                                            additionalValues[\"_AssemblyVersion\"] = Assembly.GetExecutingAssembly()\n                                                .GetCustomAttributes\u003cAssemblyFileVersionAttribute\u003e().Single().Version;\n                                            additionalValues[\"_X-Correlation-ID\"] = correlationId;\n                                        };\n        config.ValidateConnectionString = true;\n    });\n```\n\nWithin a standard ASP .Net Core project, this provider is best added in the Start-up's `Configure` method as this will allow access to a `IHttpContextAccessor` for injecting request data to all logs.\n\n```cs\n public void Configure(IApplicationBuilder app,\n                              IHostingEnvironment env,\n                              ILoggerFactory loggerFactory,\n                              IHttpContextAccessor httpContextAccessor)\n    {\n        ...\n   \n        loggerFactory.AddConsole();\n        loggerFactory.AddEventHub(\n            config =\u003e\n            {\n                /*\n                optional(AzureStorageLogProviderOptions)\n                Setting this property and setting (\"AzureStorageOptions:Enabled\") = true \n                enables the azure storage logging provider \n                (for messages with size \u003e= 1Mb)  \n    \n                Please check \"Azure Storage Logging Provider\" for more information.\n                */\n                config.AzureStorageLogProviderOptions = new AzureStorageLogProviderOptions(\n                                        Configuration.GetValue\u003cString\u003e(\"AzureStorageOptions:SasUrl\")\n                                        ,Configuration.GetValue\u003cBoolean\u003e(\"AzureStorageOptions:Enabled\")\n                                        ,Configuration.GetValue\u003cString\u003e                                 (\"AzureStorageOptions:SuccessfulMessageTemplate\") \n                                        ,Configuration.GetValue\u003cString\u003e(\"AzureStorageOptions:FailedMessageTemplate\")\n                                        );\n                config.Environment = \"Production\";\n                config.DefaultMinimumLogLevel = LogLevel.Warning;\n                config.MinimumLogLevels[\"Microsoft.AspNetCore\"] = LogLevel.Trace;\n                config.MinimumLogLevels[\"Microsoft.AspNetCore.Server\"] = LogLevel.Error;\n                config.EventHubConnectionString = connectionString;\n                config.EventHubEntityPath = entityPath;\n                config.System = \"My System Name\";\n                config.Service = \"My Service Name\";\n                config.NodeName = \"Node 123\";\n                config.AdditionalValuesProvider = additionalValues =\u003e\n                                                {\n                                                    additionalValues[\"_AssemblyVersion\"] = Assembly.GetExecutingAssembly()\n                                                        .GetCustomAttributes\u003cAssemblyFileVersionAttribute\u003e().Single().Version;\n                                                    additionalValues[\"_X-Correlation-ID\"] = correlationId;\n                                                    additionalValues[\"_RemoteIPAddress\"] = httpContextAccessor.HttpContext.Connection.RemoteIpAddress.ToString();\n                                                    additionalValues[\"_User-Agent\"] = httpContextAccessor.HttpContext.Request.Headers[\"User-Agent\"].FirstOrDefault() ?? string.Empty;\n                                                };\n                config.ValidateConnectionString = true;\n            });\n    }\n```\n\n## Customisation of Log Parameter Serialization\n\nThe default log parameter serialization uses NewtonSoft.Net JsonConvert to serialize the log parameters to JSON. On occasion, it maybe desirable to customise the JSON produced to control how individual properties are serialized. This can be done by providing custom converters that extend the `Newtonsoft.Json.JsonConverter` class:\n\n```cs\nloggerFactory.AddEventHub(\n            config =\u003e\n            {\n                ...\n                config.CustomLogSerializerConverters = new List\u003cJsonConverter\u003e { new VersionJsonConverter() };\n                ...\n            });\n```\n\nThe JsonConverter must implement `WriteJson`, but the `ReadJson` method can be left unimplemented and the `CanRead` property can return false. The `CanConvert` method must only return true for the types that you wish to override the serialization of.  More details about custom converters can be found in the JsonConvert documentation \u003chttps://www.newtonsoft.com/json/help/html/CustomJsonConverter.htm\u003e.\n\n```cs\n    public class VersionJsonConverter : JsonConverter\n    {\n        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)\n        {\n            if (value is Version version)\n            {\n                writer.WriteValue($\"{version.MajorVersion}.{version.MinorVersion}.{version.Build}.{version.Revision}\");\n            }\n        }\n\n        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)\n        {\n            throw new NotImplementedException();\n        }\n\n        public override bool CanConvert(Type objectType)\n        {\n            return objectType == typeof(Version);\n        }\n\n        public override bool CanRead =\u003e false;\n    }\n```\n\n## Azure Storage Logging Provider\n\nThe Azure Storage Logging Provider is a storage logging provider that stores messages with size equal or greater than 1Mb into an Azure storage container. Finally, it updates the log entry with the azure storage blob details. Enabling the Azure storage provider is optional. It is enabled by providing the `AzureStorageLogProviderOptions` as shown below.\n\n\n\n### Configuration using Azure Storage conatiner SAS url\n\n The AzureStorageLogProviderOptions model consists of:\n\n```cs\n//The SAS url for the storage container, recommended rights set : racwl\nstring azureStorageContainerSasUrlString  \n//Enables (true) or disables(false) the Azure storage logging provider\nbool azureStorageLoggerEnabled,\n//A template for the messages that are successfully stored*\nstring successfulMessageTemplate,\n//A template for the messages that failed to be stored*\nstring failedMessageTemplate\n/*\nThe templates are configurable. \nThe parameters must be added with the following format: {{property_name}} \n\nAvailable properties:\n\n\u003cparam name=\"reasonPhrase\"\u003eThe result reason phrase\u003c/param\u003e\n\u003cparam name=\"statusCode\"\u003eThe http status code\u003c/param\u003e\n\u003cparam name=\"requestId\"\u003eThe client request Id\u003c/param\u003e\n\u003cparam name=\"fileSHA\"\u003eThe blob SHA 256\u003c/param\u003e\n\u003cparam name=\"isStored\"\u003eThe flag that determines if the result was successful/failed\u003c/param\u003e\n\u003cparam name=\"blobFullName\"\u003eThe blob full name\u003c/param\u003e\n\u003cparam name=\"fileSize\"\u003eThe file size (optional)\u003c/param\u003e\n\u003cparam name=\"modifiedDate\"\u003eThe modified date(optional)\u003c/param\u003e\n\npublic string ReasonPhrase { get; set; }\npublic int StatusCode { get; set; }\npublic string RequestId { get; set; }\npublic string FileSHA { get; set; }\npublic bool IsStored { get; set; }\npublic string BlobFullName { get; set; }\npublic long FileSize { get; set; }\npublic DateTime ModifiedDate { get; set; }\n\n*/\n```\n\n#### Example of a configuration section(json) \n\n```json\n    \"AzureStorageOptions\": {\n    \"SasUrl\": \"the_sas_url\", //removed for security reasons\n    \"Enabled\": true,\n    \"SuccessfulMessageTemplate\": \"Azure Storage Logging: A blob with the error details was created at {{BlobFullName}}. Reason: ErrorMessageEqualOrGreaterTo1MB ResponseMessage: {{ReasonPhrase}} ResponseCode: {{StatusCode}} RequestId: {{RequestId}} Sha256: {{FileSHA}} FileSize(Bs): {{FileSize}} FileModifiedDate: {{ModifiedDate}}\",\n    \"FailedMessageTemplate\": \"Azure Storage Logging: Storing blob failed. Reason: ErrorMessageEqualOrGreaterTo1MB ResponseMessage: {{ReasonPhrase}} ResponseCode: {{StatusCode}} RequestId: {{RequestId}}\"\n  }\n```\n\n### Configuration using Managed identity\n\n The AzureStorageLogProviderOptions model consists of:\n\n ```\noptions.AzureStorageLogProviderOptions = new AzureStorageLogProviderOptions(\n                        // Azure storage blob container uri\n                        new Uri(builder.Configuration.GetValue\u003cString\u003e(\"AzureStorageOptions:BlobContainerUri\"),\n                        // The Azure managed identity credential to use for authorization.\n                        new DefaultAzureCredential(),\n                        //Enables (true) or disables(false) the Azure storage logging provider\n                        builder.Configuration.GetValue\u003cString\u003e(\"AzureStorageOptions:AzureStorageLoggerEnabled\"),\n                        //A template for the messages that are successfully stored\n                        builder.Configuration.GetValue\u003cString\u003e(\"AzureStorageOptions:SuccessMessageTemaplate\"),\n                        //A template for the messages that failed to be stored*                      \n                        builder.Configuration.GetValue\u003cString\u003e(\"AzureStorageOptions:FailedMessageTemplate\")\n                        );\n\n\n```\n\n#### Example of a configuration section(json) \n\n```json\n    \"AzureStorageOptions\": {\n    \"BlobContainerUri\": \"blob container uri\", //This is likely to be similar to \"https://{account_name}.blob.core.windows.net/{container_name}\"\n    \"Enabled\": true,\n    \"SuccessfulMessageTemplate\": \"Azure Storage Logging: A blob with the error details was created at {{BlobFullName}}. Reason: ErrorMessageEqualOrGreaterTo1MB ResponseMessage: {{ReasonPhrase}} ResponseCode: {{StatusCode}} RequestId: {{RequestId}} Sha256: {{FileSHA}} FileSize(Bs): {{FileSize}} FileModifiedDate: {{ModifiedDate}}\",\n    \"FailedMessageTemplate\": \"Azure Storage Logging: Storing blob failed. Reason: ErrorMessageEqualOrGreaterTo1MB ResponseMessage: {{ReasonPhrase}} ResponseCode: {{StatusCode}} RequestId: {{RequestId}}\"\n  }\n```\n\n\u003e [!NOTE] \n\u003e The Managed Identity principal (or user if running on localhost) will require `Storage Blob Data Contributor` role on the Event hub. \n\n### Azure Storage Provider Functional Diagram\n\n[The diagram (Visio) can be downloaded using the following link](/docs/Technical%20Documentation/Logging%20Provider%20-%20Azure%20Storage%20Logging.vsdx)\n\n## EventHub Logging Provider Help File\n\n[Version 1.0.0](/docs/Technical%20Documentation/Help%20Files/1.0.0/Documentation.chm)\n\n## How to Engage, Contribute, and Give Feedback\n\nSome of the best ways to contribute are to try things out, file issues and make pull-requests.\n\n---\n\nThe UK Hydrographic Office (UKHO) supplies hydrographic information to protect lives at sea. Maintaining the confidentially, integrity and availability of our services is paramount. Found a security bug? Please report it to us at UKHO-ITSO@gov.co.uk\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fukho%2Feventhub-logging-provider","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fukho%2Feventhub-logging-provider","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fukho%2Feventhub-logging-provider/lists"}