diff --git a/NBB.sln b/NBB.sln index c74651ba..9b0053b9 100644 --- a/NBB.sln +++ b/NBB.sln @@ -383,6 +383,21 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NBB.MultiTenancy.Abstractio EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NBB.EventStore.AdoNet.Tests", "test\UnitTests\EventStore\NBB.EventStore.AdoNet.Tests\NBB.EventStore.AdoNet.Tests.csproj", "{C3F79479-1011-4ECB-8876-81B81CA2457B}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NBB.Tools.Serilog.Enrichers.ServiceIdentifier", "src\Tools\Serilog\NBB.Tools.Serilog.Enrichers.ServiceIdentifier\NBB.Tools.Serilog.Enrichers.ServiceIdentifier.csproj", "{EE64CE9C-7A9C-4832-B9CD-00106CFA620C}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tools", "Tools", "{2177F9CE-CD18-4D61-8DAE-0E27D3C44AB3}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NBB.Tools.Serilog.Enrichers.ServiceIdentifier.Tests", "test\UnitTests\Tools\NBB.Tools.Serilog.Enrichers.ServiceIdentifier.Tests\NBB.Tools.Serilog.Enrichers.ServiceIdentifier.Tests.csproj", "{E2F3DA74-E8BB-492B-877C-24E781C4FB1F}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NBB.Tools.Serilog.Enrichers.TenantId", "src\Tools\Serilog\NBB.Tools.Serilog.Enrichers.TenantId\NBB.Tools.Serilog.Enrichers.TenantId.csproj", "{C964F164-C8BF-487A-9D24-5E169A7E950F}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NBB.Tools.Serilog.Enrichers.TenantId.Tests", "test\UnitTests\Tools\NBB.Tools.Serilog.Enrichers.TenantId.Tests\NBB.Tools.Serilog.Enrichers.TenantId.Tests.csproj", "{81E535EC-ACB5-4EE4-A173-06983B40F80F}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Serilog", "Serilog", "{33AEB049-EC66-4728-9B22-CC0F282D3E73}" + ProjectSection(SolutionItems) = preProject + src\Tools\Serilog\README.md = src\Tools\Serilog\README.md + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -861,6 +876,22 @@ Global {C3F79479-1011-4ECB-8876-81B81CA2457B}.Debug|Any CPU.Build.0 = Debug|Any CPU {C3F79479-1011-4ECB-8876-81B81CA2457B}.Release|Any CPU.ActiveCfg = Release|Any CPU {C3F79479-1011-4ECB-8876-81B81CA2457B}.Release|Any CPU.Build.0 = Release|Any CPU + {EE64CE9C-7A9C-4832-B9CD-00106CFA620C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EE64CE9C-7A9C-4832-B9CD-00106CFA620C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EE64CE9C-7A9C-4832-B9CD-00106CFA620C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EE64CE9C-7A9C-4832-B9CD-00106CFA620C}.Release|Any CPU.Build.0 = Release|Any CPU + {E2F3DA74-E8BB-492B-877C-24E781C4FB1F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E2F3DA74-E8BB-492B-877C-24E781C4FB1F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E2F3DA74-E8BB-492B-877C-24E781C4FB1F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E2F3DA74-E8BB-492B-877C-24E781C4FB1F}.Release|Any CPU.Build.0 = Release|Any CPU + {C964F164-C8BF-487A-9D24-5E169A7E950F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C964F164-C8BF-487A-9D24-5E169A7E950F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C964F164-C8BF-487A-9D24-5E169A7E950F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C964F164-C8BF-487A-9D24-5E169A7E950F}.Release|Any CPU.Build.0 = Release|Any CPU + {81E535EC-ACB5-4EE4-A173-06983B40F80F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {81E535EC-ACB5-4EE4-A173-06983B40F80F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {81E535EC-ACB5-4EE4-A173-06983B40F80F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {81E535EC-ACB5-4EE4-A173-06983B40F80F}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -991,7 +1022,7 @@ Global {74583BC7-B9BC-4D27-B9E9-5DB136A8E41C} = {D28298B7-63A2-4751-BEB9-C3C30F2E7107} {A2A174AF-8612-4796-B5FA-E2F9EB3AB68F} = {74583BC7-B9BC-4D27-B9E9-5DB136A8E41C} {EF374BA2-61FC-41FB-8229-5187DCBAA63A} = {7311E32F-C1B0-41C9-B5F1-DE9EBB6ABB55} - {A5826A9E-7E96-4A52-8A06-2B6DC9855954} = {EF374BA2-61FC-41FB-8229-5187DCBAA63A} + {A5826A9E-7E96-4A52-8A06-2B6DC9855954} = {33AEB049-EC66-4728-9B22-CC0F282D3E73} {2FEDB78D-E355-4449-A9D3-1C3079E38FD9} = {20C8482D-1525-47B0-B78B-09632892E8E4} {0B65210B-9A1D-4D07-98B4-69995FEF21BD} = {4DCC0E0D-52D8-4F97-9B26-C3F9CB76F16F} {04556BEE-32FE-47D5-8C22-7D336FA44D7C} = {584C62C0-2AE6-4DD6-9BCF-8FF28B7122CE} @@ -1020,6 +1051,12 @@ Global {A53CE5F4-841F-40E3-A079-22C583509D6E} = {584C62C0-2AE6-4DD6-9BCF-8FF28B7122CE} {CEE3FAE5-2E96-4318-9A4D-7FAAC529CB08} = {0ECF24A0-BFED-4F7A-8B06-CC40E628E852} {C3F79479-1011-4ECB-8876-81B81CA2457B} = {0407911F-89FC-4138-BD4D-D4CFCFBB5DC1} + {EE64CE9C-7A9C-4832-B9CD-00106CFA620C} = {33AEB049-EC66-4728-9B22-CC0F282D3E73} + {2177F9CE-CD18-4D61-8DAE-0E27D3C44AB3} = {90E022FB-CA1B-49DD-9BEA-CE7F8E74E8BB} + {E2F3DA74-E8BB-492B-877C-24E781C4FB1F} = {2177F9CE-CD18-4D61-8DAE-0E27D3C44AB3} + {C964F164-C8BF-487A-9D24-5E169A7E950F} = {33AEB049-EC66-4728-9B22-CC0F282D3E73} + {81E535EC-ACB5-4EE4-A173-06983B40F80F} = {2177F9CE-CD18-4D61-8DAE-0E27D3C44AB3} + {33AEB049-EC66-4728-9B22-CC0F282D3E73} = {EF374BA2-61FC-41FB-8229-5187DCBAA63A} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {23A42379-616A-43EF-99BC-803DF151F54E} diff --git a/src/Messaging/NBB.Messaging.Abstractions/MessageBusPublisher.cs b/src/Messaging/NBB.Messaging.Abstractions/MessageBusPublisher.cs index fd2aa25c..5f0d7fdb 100644 --- a/src/Messaging/NBB.Messaging.Abstractions/MessageBusPublisher.cs +++ b/src/Messaging/NBB.Messaging.Abstractions/MessageBusPublisher.cs @@ -80,8 +80,8 @@ private MessagingEnvelope PrepareMessageEnvelope(TMessage me private string GetSourceId() { - var topicPrefix = _configuration.GetSection("Messaging")?["Source"]; - return topicPrefix ?? ""; + var sourceId = _configuration.GetSection("Messaging")?["Source"]; + return sourceId ?? ""; } } } diff --git a/src/Messaging/NBB.Messaging.Abstractions/MessagingContextAccessor.cs b/src/Messaging/NBB.Messaging.Abstractions/MessagingContextAccessor.cs index 0a39dfea..d2f89d95 100644 --- a/src/Messaging/NBB.Messaging.Abstractions/MessagingContextAccessor.cs +++ b/src/Messaging/NBB.Messaging.Abstractions/MessagingContextAccessor.cs @@ -5,14 +5,14 @@ namespace NBB.Messaging.Abstractions { - public class MessagingContextAccessor - { - private static readonly AsyncLocal AsyncLocal = new(); - - public MessagingContext MessagingContext - { - get => AsyncLocal.Value; - set => AsyncLocal.Value = value; - } + public class MessagingContextAccessor + { + private static readonly AsyncLocal AsyncLocal = new(); + + public MessagingContext MessagingContext + { + get => AsyncLocal.Value; + set => AsyncLocal.Value = value; + } } } diff --git a/src/Tools/Serilog/NBB.Tools.Serilog.Enrichers.ServiceIdentifier/NBB.Tools.Serilog.Enrichers.ServiceIdentifier.csproj b/src/Tools/Serilog/NBB.Tools.Serilog.Enrichers.ServiceIdentifier/NBB.Tools.Serilog.Enrichers.ServiceIdentifier.csproj new file mode 100644 index 00000000..7e67d74d --- /dev/null +++ b/src/Tools/Serilog/NBB.Tools.Serilog.Enrichers.ServiceIdentifier/NBB.Tools.Serilog.Enrichers.ServiceIdentifier.csproj @@ -0,0 +1,14 @@ + + + + net6.0 + + + + + + + + + + diff --git a/src/Tools/Serilog/NBB.Tools.Serilog.Enrichers.ServiceIdentifier/README.md b/src/Tools/Serilog/NBB.Tools.Serilog.Enrichers.ServiceIdentifier/README.md new file mode 100644 index 00000000..f3f8e57d --- /dev/null +++ b/src/Tools/Serilog/NBB.Tools.Serilog.Enrichers.ServiceIdentifier/README.md @@ -0,0 +1,71 @@ +# NBB.Tools.Serilog.Enrichers.ServiceIdentifier + +This project provides a Serilog Enricher that adds a service identifier to the log context. +The identifier is taken either from messaging source or from the Assembly.GetEntryAssembly().Name. + + +## NuGet install +``` +dotnet add package NBB.Tools.Serilog.Enrichers.ServiceIdentifier +``` +# Registration +The enricher should be registered in `Startup.cs`: + +```csharp +public void ConfigureServices(IServiceCollection services) +{ + ... + services.AddSingleton(); + ... +} +``` +# Usage: example for Program.cs +```csharp +var hostBuilder = CreateHostBuilder(args); +var tempLogger = new LoggerConfiguration() + .ReadFrom.Configuration(Configuration) + .CreateLogger(); + +hostBuilder.UseSerilog((context, services, configuration) => +{ + configuration.ReadFrom.Configuration(Configuration); + configuration.Enrich.With(services.GetRequiredService()); + ... +}); +``` + +# Usage: example for an sql logger configured in appsettings.json + "Serilog": { + "MinimumLevel": "Debug", + "tableName": "TABLE_NAME", + "WriteTo": [ + { + "Name": "MSSqlServer", + "Args": { + "connectionString": "Server=SERVER,POST;Database=DB;User Id=USERID;Password=PASS;MultipleActiveResultSets=true", + "tableName": "TABLE_NAME", + "autoCreateSqlTable": false, + "columnOptionsSection": { + "addStandardColumns": [ "LogEvent" ], + "customColumns": [ + { + "ColumnName": "ServiceIdentifier", + "PropertyName": "ServiceIdentifier", + "DataType": "nvarchar", + "DataLength": "255", + "AllowNull": true + } + ] + } + } + }, + { + "Name": "Console", + "Args": { + "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] {Message} T: {TenantId} E: {EnvelopeGuid} N: {FirstName} {LastName} ID: {IdCardIdentifier} EID: {FingerprintId} {NewLine}{Exception}" + } + } + ], + "Enrich": [ "FromLogContext", "WithMachineName", "WithThreadId", "ServiceIdentifier" ] + }, + diff --git a/src/Tools/Serilog/NBB.Tools.Serilog.Enrichers.ServiceIdentifier/ServiceIdentifierEnricher.cs b/src/Tools/Serilog/NBB.Tools.Serilog.Enrichers.ServiceIdentifier/ServiceIdentifierEnricher.cs new file mode 100644 index 00000000..126ee6d0 --- /dev/null +++ b/src/Tools/Serilog/NBB.Tools.Serilog.Enrichers.ServiceIdentifier/ServiceIdentifierEnricher.cs @@ -0,0 +1,31 @@ +// Copyright (c) TotalSoft. +// This source code is licensed under the MIT license. + +using Microsoft.Extensions.Configuration; +using Serilog.Core; +using Serilog.Events; +using System.Reflection; + +namespace NBB.Tools.Serilog.Enrichers.ServiceIdentifier +{ + public class ServiceIdentifierEnricher : ILogEventEnricher + { + private readonly IConfiguration _configuration; + public static string PropertyName { get; } = "ServiceIdentifier"; + + public ServiceIdentifierEnricher(IConfiguration configuration) + { + _configuration = configuration; + } + + public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory) + { + var source = _configuration.GetSection("Messaging")?["Source"]; + if (string.IsNullOrEmpty(source)) + { + source = Assembly.GetEntryAssembly().GetName().Name; + } + logEvent.AddOrUpdateProperty(propertyFactory.CreateProperty(PropertyName, source)); + } + } +} diff --git a/src/Tools/Serilog/NBB.Tools.Serilog.Enrichers.TenantId/NBB.Tools.Serilog.Enrichers.TenantId.csproj b/src/Tools/Serilog/NBB.Tools.Serilog.Enrichers.TenantId/NBB.Tools.Serilog.Enrichers.TenantId.csproj new file mode 100644 index 00000000..e36eb715 --- /dev/null +++ b/src/Tools/Serilog/NBB.Tools.Serilog.Enrichers.TenantId/NBB.Tools.Serilog.Enrichers.TenantId.csproj @@ -0,0 +1,18 @@ + + + + net6.0 + + + + + + + + + + + + + + diff --git a/src/Tools/Serilog/NBB.Tools.Serilog.Enrichers.TenantId/README.md b/src/Tools/Serilog/NBB.Tools.Serilog.Enrichers.TenantId/README.md new file mode 100644 index 00000000..c6346718 --- /dev/null +++ b/src/Tools/Serilog/NBB.Tools.Serilog.Enrichers.TenantId/README.md @@ -0,0 +1,76 @@ +# NBB.Tools.Serilog.Enrichers.TenantId + +This project provides a Serilog Enricher that adds the tenant id to the log context. +It can be the case that logging is requested before tenant identification is requested or that tenant cannot be found. In this case, the empty guid will be set in the context. + + +## NuGet install +``` +dotnet add package NBB.MultiTenancy.Serilog +``` +# Registration +The enricher should be registered in `Startup.cs`: + +```csharp +public void ConfigureServices(IServiceCollection services) +{ + ... + services.AddSingleton(); + ... +} +``` +# Usage: example for Program.cs +```csharp +var hostBuilder = CreateHostBuilder(args); +var tempLogger = new LoggerConfiguration() + .ReadFrom.Configuration(Configuration) + .CreateLogger(); + +hostBuilder.UseSerilog((context, services, configuration) => +{ + configuration.ReadFrom.Configuration(Configuration); + configuration.Enrich.With(services.GetRequiredService()); + ... +}); +``` + +# Usage: example for an sql logger configured in appsettings.json + "Serilog": { + "MinimumLevel": "Debug", + "tableName": "TABLE_NAME", + "WriteTo": [ + { + "Name": "MSSqlServer", + "Args": { + "connectionString": "Server=SERVER,POST;Database=DB;User Id=USERID;Password=PASS;MultipleActiveResultSets=true", + "tableName": "TABLE_NAME", + "autoCreateSqlTable": false, + "columnOptionsSection": { + "addStandardColumns": [ "LogEvent" ], + "customColumns": [ + { + "ColumnName": "TenantId", + "PropertyName": "TenantId", + "DataType": "uniqueidentifier", + "AllowNull": false + }, + { + "ColumnName": "OtherId", + "PropertyName": "OtherId", + "DataType": "uniqueidentifier", + "AllowNull": true + } + ] + } + } + }, + { + "Name": "Console", + "Args": { + "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] {Message} T: {TenantId} E: {EnvelopeGuid} N: {FirstName} {LastName} ID: {IdCardIdentifier} EID: {FingerprintId} {NewLine}{Exception}" + } + } + ], + "Enrich": [ "FromLogContext", "WithMachineName", "WithThreadId", "Tenant" ] + }, + diff --git a/src/Tools/Serilog/NBB.Tools.Serilog.Enrichers.TenantId/TenantEnricher.cs b/src/Tools/Serilog/NBB.Tools.Serilog.Enrichers.TenantId/TenantEnricher.cs new file mode 100644 index 00000000..50abc959 --- /dev/null +++ b/src/Tools/Serilog/NBB.Tools.Serilog.Enrichers.TenantId/TenantEnricher.cs @@ -0,0 +1,32 @@ +// Copyright (c) TotalSoft. +// This source code is licensed under the MIT license. + +using NBB.MultiTenancy.Abstractions; +using NBB.MultiTenancy.Abstractions.Context; +using Serilog.Core; +using Serilog.Events; + +namespace NBB.Tools.Serilog.Enrichers.TenantId +{ + public class TenantEnricher : ILogEventEnricher + { + private readonly ITenantContextAccessor _tenantContextAccessor; + public static string PropertyName { get; } = nameof(Tenant.Default.TenantId); + + public TenantEnricher(ITenantContextAccessor tenantContextAccessor) + { + _tenantContextAccessor = tenantContextAccessor; + } + + public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory) + { + if (_tenantContextAccessor.TenantContext == null) + { + logEvent.AddOrUpdateProperty(propertyFactory.CreateProperty(PropertyName, Tenant.Default.TenantId)); + return; + } + var tenantId = _tenantContextAccessor.TenantContext.TryGetTenantId(); + logEvent.AddOrUpdateProperty(propertyFactory.CreateProperty(PropertyName, tenantId ?? Tenant.Default.TenantId)); + } + } +} diff --git a/src/Tools/Serilog/README.md b/src/Tools/Serilog/README.md new file mode 100644 index 00000000..52f1474a --- /dev/null +++ b/src/Tools/Serilog/README.md @@ -0,0 +1,9 @@ +# Serilog tools + +NBB serilog tools provide enrichers and sinks for NBB. + +The package [`NBB.Tools.Serilog.Enrichers.ServiceIdentifier`](NBB.Tools.Serilog.Enrichers.ServiceIdentifier) provides an enricher for service identifier. It is taken from nbb source / entry assembly name / process name. + +The package [`NBB.Tools.Serilog.Enrichers.TenantId`](NBB.Tools.Serilog.Enrichers.TenantId) provides an enricher for tenant id from nbb tenant context. + +The package [`NBB.Tools.Serilog.OpenTracingSink`](NBB.Tools.Serilog.OpenTracingSink) provides a sink for serilog and opentracing. diff --git a/test/UnitTests/Tools/NBB.Tools.Serilog.Enrichers.ServiceIdentifier.Tests/NBB.Tools.Serilog.Enrichers.ServiceIdentifier.Tests.csproj b/test/UnitTests/Tools/NBB.Tools.Serilog.Enrichers.ServiceIdentifier.Tests/NBB.Tools.Serilog.Enrichers.ServiceIdentifier.Tests.csproj new file mode 100644 index 00000000..43658348 --- /dev/null +++ b/test/UnitTests/Tools/NBB.Tools.Serilog.Enrichers.ServiceIdentifier.Tests/NBB.Tools.Serilog.Enrichers.ServiceIdentifier.Tests.csproj @@ -0,0 +1,27 @@ + + + + net6.0 + false + + + + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + diff --git a/test/UnitTests/Tools/NBB.Tools.Serilog.Enrichers.ServiceIdentifier.Tests/ServiceIdentifierEnricherTests.cs b/test/UnitTests/Tools/NBB.Tools.Serilog.Enrichers.ServiceIdentifier.Tests/ServiceIdentifierEnricherTests.cs new file mode 100644 index 00000000..9c29808d --- /dev/null +++ b/test/UnitTests/Tools/NBB.Tools.Serilog.Enrichers.ServiceIdentifier.Tests/ServiceIdentifierEnricherTests.cs @@ -0,0 +1,93 @@ +// Copyright (c) TotalSoft. +// This source code is licensed under the MIT license. + +using Microsoft.Extensions.Configuration; +using Moq; +using Serilog.Core; +using Serilog.Events; +using Serilog.Parsing; +using System; +using System.Collections.Generic; +using System.Reflection; +using Xunit; + +namespace NBB.Tools.Serilog.Enrichers.ServiceIdentifier.Tests +{ + public class ServiceIdentifierEnricherTests + { + private static ILogEventPropertyFactory GetPropertyFactory() + { + var propertyFactory = new Mock(); + propertyFactory.Setup(x => x.CreateProperty(It.IsAny(), It.IsAny(), It.IsAny())).Returns( + (name, value, destructureObjects) => + { + var property = new LogEventProperty(name, new ScalarValue(value)); + return property; + }); + return propertyFactory.Object; + } + + private static LogEvent GetLogEvent() + { + var logEvent = new LogEvent(DateTimeOffset.UtcNow, LogEventLevel.Verbose, null, + new MessageTemplate("atemplate", new List()), + new List + { + new LogEventProperty("aname1", new ScalarValue("avalue")), + new LogEventProperty("aname2", new ScalarValue(42)) + }); + return logEvent; + } + + + + [Fact] + public void Service_identifier_enricher_from_messaging_source() + { + var propertyFactory = GetPropertyFactory(); + var service = "WorkerService"; + + var logEvent = GetLogEvent(); + var myConfiguration = new Dictionary + { + {"Messaging:Source", service}, + }; + + var configuration = new ConfigurationBuilder() + .AddInMemoryCollection(myConfiguration) + .Build(); + + var enricher = new ServiceIdentifierEnricher(configuration); + + enricher.Enrich(logEvent, propertyFactory); + + Assert.Equal(3, logEvent.Properties.Count); + var value = logEvent.Properties[ServiceIdentifierEnricher.PropertyName] as ScalarValue; + Assert.NotNull(value); + Assert.Equal(service, value.Value); + } + + [Fact] + public void Service_identifier_enricher_from_default() + { + var propertyFactory = GetPropertyFactory(); + var expectedName = Assembly.GetEntryAssembly().GetName().Name; + + var logEvent = GetLogEvent(); + var myConfiguration = new Dictionary { }; + + var configuration = new ConfigurationBuilder() + .AddInMemoryCollection(myConfiguration) + .Build(); + + var enricher = new ServiceIdentifierEnricher(configuration); + + enricher.Enrich(logEvent, propertyFactory); + + Assert.Equal(3, logEvent.Properties.Count); + var value = logEvent.Properties[ServiceIdentifierEnricher.PropertyName] as ScalarValue; + Assert.NotNull(value); + Assert.Equal(expectedName, value.Value); + } + } +} diff --git a/test/UnitTests/Tools/NBB.Tools.Serilog.Enrichers.TenantId.Tests/NBB.Tools.Serilog.Enrichers.TenantId.Tests.csproj b/test/UnitTests/Tools/NBB.Tools.Serilog.Enrichers.TenantId.Tests/NBB.Tools.Serilog.Enrichers.TenantId.Tests.csproj new file mode 100644 index 00000000..56dc5804 --- /dev/null +++ b/test/UnitTests/Tools/NBB.Tools.Serilog.Enrichers.TenantId.Tests/NBB.Tools.Serilog.Enrichers.TenantId.Tests.csproj @@ -0,0 +1,27 @@ + + + + net6.0 + false + + + + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + diff --git a/test/UnitTests/Tools/NBB.Tools.Serilog.Enrichers.TenantId.Tests/TenantIdEnricherTests.cs b/test/UnitTests/Tools/NBB.Tools.Serilog.Enrichers.TenantId.Tests/TenantIdEnricherTests.cs new file mode 100644 index 00000000..4257c59e --- /dev/null +++ b/test/UnitTests/Tools/NBB.Tools.Serilog.Enrichers.TenantId.Tests/TenantIdEnricherTests.cs @@ -0,0 +1,95 @@ +// Copyright (c) TotalSoft. +// This source code is licensed under the MIT license. + +using Moq; +using NBB.MultiTenancy.Abstractions; +using NBB.MultiTenancy.Abstractions.Context; +using NBB.Tools.Serilog.Enrichers.TenantId; +using Serilog.Core; +using Serilog.Events; +using Serilog.Parsing; +using System; +using System.Collections.Generic; +using Xunit; + +namespace NBB.MultiTenancy.Serilog.Tests +{ + public class TenantIdEnricherTests + { + private static ILogEventPropertyFactory GetPropertyFactory() + { + var propertyFactory = new Mock(); + propertyFactory.Setup(x => x.CreateProperty(It.IsAny(), It.IsAny(), It.IsAny())).Returns( + (name, value, destructureObjects) => + { + var property = new LogEventProperty(name, new ScalarValue(value)); + return property; + }); + return propertyFactory.Object; + } + + private static LogEvent GetLogEvent() + { + var logEvent = new LogEvent(DateTimeOffset.UtcNow, LogEventLevel.Verbose, null, + new MessageTemplate("mesagetemplate", new List()), + new List + { + new LogEventProperty("prop1", new ScalarValue("val1")), + new LogEventProperty("prop2", new ScalarValue(22)) + }); + return logEvent; + } + + [Fact] + public void TenantId_enricher_correct_value_from_context() + { + var tid = Guid.Parse("68a448a2-e7d8-4875-8127-f18668217eb6"); + + var propertyFactory = GetPropertyFactory(); + + var logEvent = GetLogEvent(); + + var tenantContextAccessor = new TenantContextAccessor + { + TenantContext = new TenantContext(new Tenant(tid, tid.ToString())) + }; + + var enricher = new TenantEnricher(tenantContextAccessor); + + enricher.Enrich(logEvent, propertyFactory); + + Assert.Equal(3, logEvent.Properties.Count); + Assert.Equal(tid.ToString(), logEvent.Properties[TenantEnricher.PropertyName].ToString()); + } + + [Fact] + public void TenantId_enricher_correct_value_null_context() + { + var propertyFactory = GetPropertyFactory(); + + var logEvent = GetLogEvent(); + + var enricher = new TenantEnricher(new TenantContextAccessor()); + + enricher.Enrich(logEvent, propertyFactory); + + Assert.Equal(3, logEvent.Properties.Count); + Assert.Equal(Tenant.Default.TenantId.ToString(), logEvent.Properties[TenantEnricher.PropertyName].ToString()); + } + + [Fact] + public void TenantId_enricher_value_with_no_tenant_default_value() + { + var propertyFactory = GetPropertyFactory(); + + var logEvent = GetLogEvent(); + + var enricher = new TenantEnricher(new TenantContextAccessor { TenantContext = new TenantContext(null)}); + + enricher.Enrich(logEvent, propertyFactory); + + Assert.Equal(3, logEvent.Properties.Count); + Assert.Equal(Tenant.Default.TenantId.ToString(), logEvent.Properties[TenantEnricher.PropertyName].ToString()); + } + } +}