diff --git a/.github/workflows/codeql-analysis-cron.yml b/.github/workflows/codeql-analysis-cron.yml index dbb80dfc69..4c55ad17a1 100644 --- a/.github/workflows/codeql-analysis-cron.yml +++ b/.github/workflows/codeql-analysis-cron.yml @@ -16,6 +16,8 @@ jobs: uses: actions/setup-dotnet@a98b56852c35b8e3190ac28c8c2271da59106c68 # v6.0.0 with: dotnet-version: 10.0.x + cache: true + cache-dependency-path: "**/packages.lock.json" - name: Checkout repository uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 65579bb11a..429d344967 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -16,6 +16,8 @@ jobs: uses: actions/setup-dotnet@a98b56852c35b8e3190ac28c8c2271da59106c68 # v6.0.0 with: dotnet-version: 10.0.x + cache: true + cache-dependency-path: "**/packages.lock.json" - name: Checkout repository uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index c786fa30b8..0bc8a687cd 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -46,6 +46,8 @@ jobs: uses: actions/setup-dotnet@a98b56852c35b8e3190ac28c8c2271da59106c68 # v6.0.0 with: dotnet-version: 10.0.x + cache: true + cache-dependency-path: "**/packages.lock.json" - name: Cache NuGet packages uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 with: @@ -76,6 +78,8 @@ jobs: uses: actions/setup-dotnet@a98b56852c35b8e3190ac28c8c2271da59106c68 # v6.0.0 with: dotnet-version: 10.0.x + cache: true + cache-dependency-path: "**/packages.lock.json" - name: Cache NuGet packages uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 with: @@ -129,22 +133,11 @@ jobs: username: ${{ secrets.DHI_DOCKERHUB_USERNAME }} password: ${{ secrets.DHI_DOCKERHUB_TOKEN }} - - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 - with: - node-version: 24.19.0 - cache: "npm" - cache-dependency-path: "**/package-lock.json" - - name: Setup Docker uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0 with: driver: docker-container - - name: Setup NuGet - uses: actions/setup-dotnet@a98b56852c35b8e3190ac28c8c2271da59106c68 # v6.0.0 - with: - dotnet-version: 10.0.x - - name: Cache Image uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 with: @@ -208,6 +201,8 @@ jobs: uses: actions/setup-dotnet@a98b56852c35b8e3190ac28c8c2271da59106c68 # v6.0.0 with: dotnet-version: 10.0.x + cache: true + cache-dependency-path: "**/packages.lock.json" - name: Cache NuGet packages uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 @@ -360,6 +355,8 @@ jobs: uses: actions/setup-dotnet@a98b56852c35b8e3190ac28c8c2271da59106c68 # v6.0.0 with: dotnet-version: 10.0.x + cache: true + cache-dependency-path: "**/packages.lock.json" - name: Install nuget-licenses tool run: dotnet tool install --global nuget-license - name: Show Allowed Licenses diff --git a/.run/docker-compose (with Postgres).run.xml b/.run/docker-compose (with Postgres).run.xml index e04d4f9e87..2fe260c769 100644 --- a/.run/docker-compose (with Postgres).run.xml +++ b/.run/docker-compose (with Postgres).run.xml @@ -1,20 +1,29 @@  - - - - - - - - - + + + + + + + + + + diff --git a/Applications/AdminApi/src/AdminApi.Infrastructure.Database.Postgres/packages.lock.json b/Applications/AdminApi/src/AdminApi.Infrastructure.Database.Postgres/packages.lock.json index f3ec13f2cc..c0af973b92 100644 --- a/Applications/AdminApi/src/AdminApi.Infrastructure.Database.Postgres/packages.lock.json +++ b/Applications/AdminApi/src/AdminApi.Infrastructure.Database.Postgres/packages.lock.json @@ -584,6 +584,7 @@ "Microsoft.Extensions.Identity.Core": "[10.0.10, 10.0.10]", "Microsoft.Extensions.Logging": "[10.0.10, 10.0.10]", "Npgsql.EntityFrameworkCore.PostgreSQL": "[10.0.3, 10.0.3]", + "OpenTelemetry.Api": "[1.17.0, )", "Polly": "[8.7.0, 8.7.0]", "RabbitMQ.Client": "[7.2.1, 7.2.1]", "Serilog": "[4.4.0, 4.4.0]" @@ -888,6 +889,12 @@ "Npgsql": "10.0.3" } }, + "OpenTelemetry.Api": { + "type": "CentralTransitive", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" + }, "Polly": { "type": "CentralTransitive", "requested": "[8.7.0, 8.7.0]", diff --git a/Applications/AdminApi/src/AdminApi.Infrastructure.Database.SqlServer/packages.lock.json b/Applications/AdminApi/src/AdminApi.Infrastructure.Database.SqlServer/packages.lock.json index f3ec13f2cc..c0af973b92 100644 --- a/Applications/AdminApi/src/AdminApi.Infrastructure.Database.SqlServer/packages.lock.json +++ b/Applications/AdminApi/src/AdminApi.Infrastructure.Database.SqlServer/packages.lock.json @@ -584,6 +584,7 @@ "Microsoft.Extensions.Identity.Core": "[10.0.10, 10.0.10]", "Microsoft.Extensions.Logging": "[10.0.10, 10.0.10]", "Npgsql.EntityFrameworkCore.PostgreSQL": "[10.0.3, 10.0.3]", + "OpenTelemetry.Api": "[1.17.0, )", "Polly": "[8.7.0, 8.7.0]", "RabbitMQ.Client": "[7.2.1, 7.2.1]", "Serilog": "[4.4.0, 4.4.0]" @@ -888,6 +889,12 @@ "Npgsql": "10.0.3" } }, + "OpenTelemetry.Api": { + "type": "CentralTransitive", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" + }, "Polly": { "type": "CentralTransitive", "requested": "[8.7.0, 8.7.0]", diff --git a/Applications/AdminApi/src/AdminApi.Infrastructure/Persistence/Database/Converters/PnsHandleEntityFrameworkValueConverter.cs b/Applications/AdminApi/src/AdminApi.Infrastructure/Persistence/Database/Converters/PnsHandleEntityFrameworkValueConverter.cs index 613ffc375c..66309feadc 100644 --- a/Applications/AdminApi/src/AdminApi.Infrastructure/Persistence/Database/Converters/PnsHandleEntityFrameworkValueConverter.cs +++ b/Applications/AdminApi/src/AdminApi.Infrastructure/Persistence/Database/Converters/PnsHandleEntityFrameworkValueConverter.cs @@ -46,6 +46,5 @@ private static PnsHandle DeserializeHandle(string pnsHandle) var value = tokens[1]; return new PnsHandle(platform, value); - ; } } diff --git a/Applications/AdminApi/src/AdminApi.Infrastructure/packages.lock.json b/Applications/AdminApi/src/AdminApi.Infrastructure/packages.lock.json index 506dbc3cb0..ba81372c45 100644 --- a/Applications/AdminApi/src/AdminApi.Infrastructure/packages.lock.json +++ b/Applications/AdminApi/src/AdminApi.Infrastructure/packages.lock.json @@ -578,6 +578,7 @@ "Microsoft.Extensions.Identity.Core": "[10.0.10, 10.0.10]", "Microsoft.Extensions.Logging": "[10.0.10, 10.0.10]", "Npgsql.EntityFrameworkCore.PostgreSQL": "[10.0.3, 10.0.3]", + "OpenTelemetry.Api": "[1.17.0, )", "Polly": "[8.7.0, 8.7.0]", "RabbitMQ.Client": "[7.2.1, 7.2.1]", "Serilog": "[4.4.0, 4.4.0]" @@ -882,6 +883,12 @@ "Npgsql": "10.0.3" } }, + "OpenTelemetry.Api": { + "type": "CentralTransitive", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" + }, "Polly": { "type": "CentralTransitive", "requested": "[8.7.0, 8.7.0]", diff --git a/Applications/AdminApi/src/AdminApi/Authentication/AnonymousUserContext.cs b/Applications/AdminApi/src/AdminApi/Authentication/AnonymousUserContext.cs index 8be6495734..54527b96bd 100644 --- a/Applications/AdminApi/src/AdminApi/Authentication/AnonymousUserContext.cs +++ b/Applications/AdminApi/src/AdminApi/Authentication/AnonymousUserContext.cs @@ -1,4 +1,5 @@ -using Backbone.BuildingBlocks.Application.Abstractions.Infrastructure.UserContext; +using Backbone.BuildingBlocks.Application.Abstractions.Exceptions; +using Backbone.BuildingBlocks.Application.Abstractions.Infrastructure.UserContext; using Backbone.DevelopmentKit.Identity.ValueObjects; namespace Backbone.AdminApi.Authentication; @@ -7,7 +8,7 @@ public class AnonymousUserContext : IUserContext { public IdentityAddress GetAddress() { - throw new NotSupportedException(); + throw new NotFoundException(); } public IdentityAddress? GetAddressOrNull() @@ -17,7 +18,7 @@ public IdentityAddress GetAddress() public DeviceId GetDeviceId() { - throw new NotSupportedException(); + throw new NotFoundException(); } public DeviceId? GetDeviceIdOrNull() @@ -27,27 +28,27 @@ public DeviceId GetDeviceId() public string GetUserId() { - throw new NotSupportedException(); + throw new NotFoundException(); } public string? GetUserIdOrNull() { - throw new NotSupportedException(); + return null; } public string GetUsername() { - throw new NotSupportedException(); + throw new NotFoundException(); } public string? GetUsernameOrNull() { - throw new NotSupportedException(); + return null; } public string GetClientId() { - throw new NotSupportedException(); + throw new NotFoundException(); } public string? GetClientIdOrNull() diff --git a/Applications/AdminApi/src/AdminApi/Configuration/AdminApiConfiguration.cs b/Applications/AdminApi/src/AdminApi/Configuration/AdminApiConfiguration.cs index 408c2ecd05..faa63d79a8 100644 --- a/Applications/AdminApi/src/AdminApi/Configuration/AdminApiConfiguration.cs +++ b/Applications/AdminApi/src/AdminApi/Configuration/AdminApiConfiguration.cs @@ -7,6 +7,9 @@ namespace Backbone.AdminApi.Configuration; public class AdminApiConfiguration { + [Required] + public required TelemetryConfiguration Telemetry { get; init; } + [Required] public required AuthenticationConfiguration Authentication { get; init; } @@ -18,6 +21,11 @@ public class AdminApiConfiguration [Required] public required InfrastructureConfiguration Infrastructure { get; init; } + public class TelemetryConfiguration + { + public required OpenTelemetryCollectorConfiguration OpenTelemetryCollector { get; set; } = new(); + } + public class AuthenticationConfiguration { [Required] diff --git a/Applications/AdminApi/src/AdminApi/Program.cs b/Applications/AdminApi/src/AdminApi/Program.cs index c7fb1d3752..eb2b76b642 100644 --- a/Applications/AdminApi/src/AdminApi/Program.cs +++ b/Applications/AdminApi/src/AdminApi/Program.cs @@ -1,3 +1,4 @@ +using System.Reflection; using Autofac.Extensions.DependencyInjection; using Backbone.AdminApi.Authentication; using Backbone.AdminApi.Configuration; @@ -73,14 +74,14 @@ static WebApplication CreateApp(string[] args) builder.Host .UseSerilog((context, configuration) => configuration - .ReadFrom.Configuration(context.Configuration, new ConfigurationReaderOptions { SectionName = "Logging" }) - .Enrich.WithCorrelationId("X-Correlation-Id", addValueIfHeaderAbsence: true) - .Enrich.FromLogContext() - .Enrich.WithProperty("service", "adminui") - .Enrich.WithExceptionDetails(new DestructuringOptionsBuilder() - .WithDefaultDestructurers() - .WithDestructurers([new DbUpdateExceptionDestructurer()])) - .Enrich.WithSensitiveDataMasking(options => options.AddSensitiveDataMasks()), preserveStaticLogger: true) + .ReadFrom.Configuration(context.Configuration, new ConfigurationReaderOptions { SectionName = "Telemetry:Logging" }) + .Enrich.WithCorrelationId("X-Correlation-Id", addValueIfHeaderAbsence: true) + .Enrich.FromLogContext() + .Enrich.WithExceptionDetails(new DestructuringOptionsBuilder() + .WithDefaultDestructurers() + .WithDestructurers([new DbUpdateExceptionDestructurer()])) + .Enrich.WithSensitiveDataMasking(options => options.AddSensitiveDataMasks()), + writeToProviders: true) .UseServiceProviderFactory(new AutofacServiceProviderFactory()); ConfigureServices(builder.Services, builder.Configuration, builder.Environment); @@ -133,7 +134,7 @@ static void ConfigureServices(IServiceCollection services, IConfiguration config options.ReplaceApplicationStore(); }); - services.AddOpenTelemetryWithPrometheusExporter(METER_NAME); + services.AddOpenTelemetry(METER_NAME, Assembly.GetExecutingAssembly().GetName().Version?.ToString() ?? "unknown", parsedConfiguration.Telemetry.OpenTelemetryCollector); services.AddTransient(); @@ -158,8 +159,6 @@ static void Configure(WebApplication app, AdminApiConfiguration configuration) if (configuration.SwaggerUi.Enabled) app.UseCustomSwaggerUi(); - app.MapPrometheusScrapingEndpoint(); - // the following headers are necessary to run the application in webassembly mode app.Use(async (context, next) => { diff --git a/Applications/AdminApi/src/AdminApi/appsettings.json b/Applications/AdminApi/src/AdminApi/appsettings.json index 4ba48a4ddd..1d59d85bf3 100644 --- a/Applications/AdminApi/src/AdminApi/appsettings.json +++ b/Applications/AdminApi/src/AdminApi/appsettings.json @@ -29,19 +29,21 @@ } } }, - "Logging": { - "MinimumLevel": { - "Default": "Warning", - "Override": { - "Backbone": "Information", - "Azure.Messaging.ServiceBus": "Error" - } - }, - "WriteTo": { - "Console": { - "Name": "Console", - "Args": { - "formatter": "Serilog.Formatting.Compact.CompactJsonFormatter, Serilog.Formatting.Compact" + "Telemetry": { + "Logging": { + "MinimumLevel": { + "Default": "Warning", + "Override": { + "Backbone": "Information", + "Azure.Messaging.ServiceBus": "Error" + } + }, + "WriteTo": { + "Console": { + "Name": "Console", + "Args": { + "formatter": "Serilog.Formatting.Compact.CompactJsonFormatter, Serilog.Formatting.Compact" + } } } } diff --git a/Applications/AdminApi/src/AdminApi/packages.lock.json b/Applications/AdminApi/src/AdminApi/packages.lock.json index 4ac52b7ba4..3c4031b016 100644 --- a/Applications/AdminApi/src/AdminApi/packages.lock.json +++ b/Applications/AdminApi/src/AdminApi/packages.lock.json @@ -782,11 +782,6 @@ "OpenTelemetry.Api.ProviderBuilderExtensions": "1.17.0" } }, - "OpenTelemetry.Api": { - "type": "Transitive", - "resolved": "1.17.0", - "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" - }, "OpenTelemetry.Api.ProviderBuilderExtensions": { "type": "Transitive", "resolved": "1.17.0", @@ -994,9 +989,10 @@ "DotNetDiag.HealthChecks.SqlServer": "[10.0.10, 10.0.10]", "Microsoft.EntityFrameworkCore": "[10.0.10, 10.0.10]", "Microsoft.EntityFrameworkCore.Relational": "[10.0.10, 10.0.10]", - "OpenTelemetry.Exporter.Prometheus.AspNetCore": "[1.11.2-beta.1, 1.11.2-beta.1]", + "OpenTelemetry.Exporter.OpenTelemetryProtocol": "[1.17.0, )", "OpenTelemetry.Extensions.Hosting": "[1.17.0, 1.17.0]", "OpenTelemetry.Instrumentation.AspNetCore": "[1.17.0, 1.17.0]", + "OpenTelemetry.Instrumentation.EntityFrameworkCore": "[1.17.0-beta.1, )", "OpenTelemetry.Instrumentation.Http": "[1.17.0, 1.17.0]", "OpenTelemetry.Instrumentation.Runtime": "[1.17.0, 1.17.0]", "Polly": "[8.7.0, 8.7.0]", @@ -1057,6 +1053,7 @@ "Microsoft.Extensions.Identity.Core": "[10.0.10, 10.0.10]", "Microsoft.Extensions.Logging": "[10.0.10, 10.0.10]", "Npgsql.EntityFrameworkCore.PostgreSQL": "[10.0.3, 10.0.3]", + "OpenTelemetry.Api": "[1.17.0, )", "Polly": "[8.7.0, 8.7.0]", "RabbitMQ.Client": "[7.2.1, 7.2.1]", "Serilog": "[4.4.0, 4.4.0]" @@ -1725,13 +1722,19 @@ "OpenIddict.Abstractions": "7.6.0" } }, - "OpenTelemetry.Exporter.Prometheus.AspNetCore": { + "OpenTelemetry.Api": { "type": "CentralTransitive", - "requested": "[1.11.2-beta.1, 1.11.2-beta.1]", - "resolved": "1.11.2-beta.1", - "contentHash": "jouLU4VHpzyXuzF2yi/bpt9DoseZGyUudSdTFvylgIwIx6ST1bdI/AXNoJ4/n6HwMiso677ILLm/RM8DY+EYwA==", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" + }, + "OpenTelemetry.Exporter.OpenTelemetryProtocol": { + "type": "CentralTransitive", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "R1omQOrQpGlS0Cp5UIr/TAiuEA48JrPlgr1NPV5gESiTU7HhWU+ILe2EBSYb1fKdsSavZ7nZkHcUxAzofPqr2A==", "dependencies": { - "OpenTelemetry": "[1.11.2, 2.0.0)" + "OpenTelemetry": "1.17.0" } }, "OpenTelemetry.Extensions.Hosting": { @@ -1752,6 +1755,15 @@ "OpenTelemetry.Api.ProviderBuilderExtensions": "[1.17.0, 2.0.0)" } }, + "OpenTelemetry.Instrumentation.EntityFrameworkCore": { + "type": "CentralTransitive", + "requested": "[1.17.0-beta.1, )", + "resolved": "1.17.0-beta.1", + "contentHash": "BPSv1rk6qEkGZUGTNBfk7XmYqBAWdF3FBdjXEjVClp0bKUl6VCumlaosT84qvlK7YnHLCv5FFqJHx2N62TbKEw==", + "dependencies": { + "OpenTelemetry.Api.ProviderBuilderExtensions": "[1.17.0, 2.0.0)" + } + }, "OpenTelemetry.Instrumentation.Http": { "type": "CentralTransitive", "requested": "[1.17.0, 1.17.0]", diff --git a/Applications/AdminApi/test/AdminApi.Tests.Integration/packages.lock.json b/Applications/AdminApi/test/AdminApi.Tests.Integration/packages.lock.json index 6440293241..bd48ad7d60 100644 --- a/Applications/AdminApi/test/AdminApi.Tests.Integration/packages.lock.json +++ b/Applications/AdminApi/test/AdminApi.Tests.Integration/packages.lock.json @@ -1246,11 +1246,6 @@ "OpenTelemetry.Api.ProviderBuilderExtensions": "1.17.0" } }, - "OpenTelemetry.Api": { - "type": "Transitive", - "resolved": "1.17.0", - "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" - }, "OpenTelemetry.Api.ProviderBuilderExtensions": { "type": "Transitive", "resolved": "1.17.0", @@ -1630,9 +1625,10 @@ "DotNetDiag.HealthChecks.SqlServer": "[10.0.10, 10.0.10]", "Microsoft.EntityFrameworkCore": "[10.0.10, 10.0.10]", "Microsoft.EntityFrameworkCore.Relational": "[10.0.10, 10.0.10]", - "OpenTelemetry.Exporter.Prometheus.AspNetCore": "[1.11.2-beta.1, 1.11.2-beta.1]", + "OpenTelemetry.Exporter.OpenTelemetryProtocol": "[1.17.0, )", "OpenTelemetry.Extensions.Hosting": "[1.17.0, 1.17.0]", "OpenTelemetry.Instrumentation.AspNetCore": "[1.17.0, 1.17.0]", + "OpenTelemetry.Instrumentation.EntityFrameworkCore": "[1.17.0-beta.1, )", "OpenTelemetry.Instrumentation.Http": "[1.17.0, 1.17.0]", "OpenTelemetry.Instrumentation.Runtime": "[1.17.0, 1.17.0]", "Polly": "[8.7.0, 8.7.0]", @@ -1693,6 +1689,7 @@ "Microsoft.Extensions.Identity.Core": "[10.0.10, 10.0.10]", "Microsoft.Extensions.Logging": "[10.0.10, 10.0.10]", "Npgsql.EntityFrameworkCore.PostgreSQL": "[10.0.3, 10.0.3]", + "OpenTelemetry.Api": "[1.17.0, )", "Polly": "[8.7.0, 8.7.0]", "RabbitMQ.Client": "[7.2.1, 7.2.1]", "Serilog": "[4.4.0, 4.4.0]" @@ -2559,13 +2556,19 @@ "OpenIddict.EntityFrameworkCore.Models": "7.6.0" } }, - "OpenTelemetry.Exporter.Prometheus.AspNetCore": { + "OpenTelemetry.Api": { + "type": "CentralTransitive", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" + }, + "OpenTelemetry.Exporter.OpenTelemetryProtocol": { "type": "CentralTransitive", - "requested": "[1.11.2-beta.1, 1.11.2-beta.1]", - "resolved": "1.11.2-beta.1", - "contentHash": "jouLU4VHpzyXuzF2yi/bpt9DoseZGyUudSdTFvylgIwIx6ST1bdI/AXNoJ4/n6HwMiso677ILLm/RM8DY+EYwA==", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "R1omQOrQpGlS0Cp5UIr/TAiuEA48JrPlgr1NPV5gESiTU7HhWU+ILe2EBSYb1fKdsSavZ7nZkHcUxAzofPqr2A==", "dependencies": { - "OpenTelemetry": "[1.11.2, 2.0.0)" + "OpenTelemetry": "1.17.0" } }, "OpenTelemetry.Extensions.Hosting": { @@ -2587,6 +2590,17 @@ "OpenTelemetry.Api.ProviderBuilderExtensions": "[1.17.0, 2.0.0)" } }, + "OpenTelemetry.Instrumentation.EntityFrameworkCore": { + "type": "CentralTransitive", + "requested": "[1.17.0-beta.1, )", + "resolved": "1.17.0-beta.1", + "contentHash": "BPSv1rk6qEkGZUGTNBfk7XmYqBAWdF3FBdjXEjVClp0bKUl6VCumlaosT84qvlK7YnHLCv5FFqJHx2N62TbKEw==", + "dependencies": { + "Microsoft.Extensions.Configuration": "10.0.0", + "Microsoft.Extensions.Options": "10.0.0", + "OpenTelemetry.Api.ProviderBuilderExtensions": "[1.17.0, 2.0.0)" + } + }, "OpenTelemetry.Instrumentation.Http": { "type": "CentralTransitive", "requested": "[1.17.0, 1.17.0]", diff --git a/Applications/AdminCli/src/AdminCli/Configuration/AdminCliConfiguration.cs b/Applications/AdminCli/src/AdminCli/Configuration/AdminCliConfiguration.cs index fa21ed451c..28d240dd59 100644 --- a/Applications/AdminCli/src/AdminCli/Configuration/AdminCliConfiguration.cs +++ b/Applications/AdminCli/src/AdminCli/Configuration/AdminCliConfiguration.cs @@ -1,4 +1,5 @@ using System.ComponentModel.DataAnnotations; +using Backbone.BuildingBlocks.API.Extensions; using Backbone.BuildingBlocks.Infrastructure.EventBus; using Backbone.BuildingBlocks.Infrastructure.Persistence.Database; @@ -6,9 +7,17 @@ namespace Backbone.AdminCli.Configuration; public class AdminCliConfiguration { + [Required] + public required TelemetryConfiguration Telemetry { get; init; } + [Required] public required AdminInfrastructureConfiguration Infrastructure { get; init; } + public class TelemetryConfiguration + { + public required OpenTelemetryCollectorConfiguration OpenTelemetryCollector { get; set; } = new(); + } + public class AdminInfrastructureConfiguration { [Required] diff --git a/Applications/AdminCli/src/AdminCli/Program.cs b/Applications/AdminCli/src/AdminCli/Program.cs index 5b9b953f79..831bf49061 100644 --- a/Applications/AdminCli/src/AdminCli/Program.cs +++ b/Applications/AdminCli/src/AdminCli/Program.cs @@ -1,3 +1,4 @@ +using System.Reflection; using Autofac; using Autofac.Extensions.DependencyInjection; using Backbone.AdminApi.Infrastructure.Persistence; @@ -77,6 +78,7 @@ private static IServiceProvider BuildServiceProvider(IConfiguration configuratio #pragma warning restore ASP0000 services.AddDatabase(parsedConfiguration.Infrastructure.SqlDatabase); + services.AddOpenTelemetry(METER_NAME, Assembly.GetExecutingAssembly().GetName().Version?.ToString() ?? "unknown", parsedConfiguration.Telemetry.OpenTelemetryCollector); var containerBuilder = new ContainerBuilder(); containerBuilder.Populate(services); diff --git a/Applications/AdminCli/src/AdminCli/appsettings.json b/Applications/AdminCli/src/AdminCli/appsettings.json index 4ba48a4ddd..1d59d85bf3 100644 --- a/Applications/AdminCli/src/AdminCli/appsettings.json +++ b/Applications/AdminCli/src/AdminCli/appsettings.json @@ -29,19 +29,21 @@ } } }, - "Logging": { - "MinimumLevel": { - "Default": "Warning", - "Override": { - "Backbone": "Information", - "Azure.Messaging.ServiceBus": "Error" - } - }, - "WriteTo": { - "Console": { - "Name": "Console", - "Args": { - "formatter": "Serilog.Formatting.Compact.CompactJsonFormatter, Serilog.Formatting.Compact" + "Telemetry": { + "Logging": { + "MinimumLevel": { + "Default": "Warning", + "Override": { + "Backbone": "Information", + "Azure.Messaging.ServiceBus": "Error" + } + }, + "WriteTo": { + "Console": { + "Name": "Console", + "Args": { + "formatter": "Serilog.Formatting.Compact.CompactJsonFormatter, Serilog.Formatting.Compact" + } } } } diff --git a/Applications/AdminCli/src/AdminCli/packages.lock.json b/Applications/AdminCli/src/AdminCli/packages.lock.json index 28fe1fa37a..08dfd1a72a 100644 --- a/Applications/AdminCli/src/AdminCli/packages.lock.json +++ b/Applications/AdminCli/src/AdminCli/packages.lock.json @@ -932,11 +932,6 @@ "OpenTelemetry.Api.ProviderBuilderExtensions": "1.17.0" } }, - "OpenTelemetry.Api": { - "type": "Transitive", - "resolved": "1.17.0", - "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" - }, "OpenTelemetry.Api.ProviderBuilderExtensions": { "type": "Transitive", "resolved": "1.17.0", @@ -1138,9 +1133,10 @@ "DotNetDiag.HealthChecks.SqlServer": "[10.0.10, 10.0.10]", "Microsoft.EntityFrameworkCore": "[10.0.10, 10.0.10]", "Microsoft.EntityFrameworkCore.Relational": "[10.0.10, 10.0.10]", - "OpenTelemetry.Exporter.Prometheus.AspNetCore": "[1.11.2-beta.1, 1.11.2-beta.1]", + "OpenTelemetry.Exporter.OpenTelemetryProtocol": "[1.17.0, )", "OpenTelemetry.Extensions.Hosting": "[1.17.0, 1.17.0]", "OpenTelemetry.Instrumentation.AspNetCore": "[1.17.0, 1.17.0]", + "OpenTelemetry.Instrumentation.EntityFrameworkCore": "[1.17.0-beta.1, )", "OpenTelemetry.Instrumentation.Http": "[1.17.0, 1.17.0]", "OpenTelemetry.Instrumentation.Runtime": "[1.17.0, 1.17.0]", "Polly": "[8.7.0, 8.7.0]", @@ -1201,6 +1197,7 @@ "Microsoft.Extensions.Identity.Core": "[10.0.10, 10.0.10]", "Microsoft.Extensions.Logging": "[10.0.10, 10.0.10]", "Npgsql.EntityFrameworkCore.PostgreSQL": "[10.0.3, 10.0.3]", + "OpenTelemetry.Api": "[1.17.0, )", "Polly": "[8.7.0, 8.7.0]", "RabbitMQ.Client": "[7.2.1, 7.2.1]", "Serilog": "[4.4.0, 4.4.0]" @@ -1920,13 +1917,19 @@ "OpenIddict.EntityFrameworkCore.Models": "7.6.0" } }, - "OpenTelemetry.Exporter.Prometheus.AspNetCore": { + "OpenTelemetry.Api": { + "type": "CentralTransitive", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" + }, + "OpenTelemetry.Exporter.OpenTelemetryProtocol": { "type": "CentralTransitive", - "requested": "[1.11.2-beta.1, 1.11.2-beta.1]", - "resolved": "1.11.2-beta.1", - "contentHash": "jouLU4VHpzyXuzF2yi/bpt9DoseZGyUudSdTFvylgIwIx6ST1bdI/AXNoJ4/n6HwMiso677ILLm/RM8DY+EYwA==", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "R1omQOrQpGlS0Cp5UIr/TAiuEA48JrPlgr1NPV5gESiTU7HhWU+ILe2EBSYb1fKdsSavZ7nZkHcUxAzofPqr2A==", "dependencies": { - "OpenTelemetry": "[1.11.2, 2.0.0)" + "OpenTelemetry": "1.17.0" } }, "OpenTelemetry.Extensions.Hosting": { @@ -1948,6 +1951,17 @@ "OpenTelemetry.Api.ProviderBuilderExtensions": "[1.17.0, 2.0.0)" } }, + "OpenTelemetry.Instrumentation.EntityFrameworkCore": { + "type": "CentralTransitive", + "requested": "[1.17.0-beta.1, )", + "resolved": "1.17.0-beta.1", + "contentHash": "BPSv1rk6qEkGZUGTNBfk7XmYqBAWdF3FBdjXEjVClp0bKUl6VCumlaosT84qvlK7YnHLCv5FFqJHx2N62TbKEw==", + "dependencies": { + "Microsoft.Extensions.Configuration": "10.0.0", + "Microsoft.Extensions.Options": "10.0.0", + "OpenTelemetry.Api.ProviderBuilderExtensions": "[1.17.0, 2.0.0)" + } + }, "OpenTelemetry.Instrumentation.Http": { "type": "CentralTransitive", "requested": "[1.17.0, 1.17.0]", diff --git a/Applications/ConsumerApi/src/Configuration/ConsumerApiConfiguration.cs b/Applications/ConsumerApi/src/Configuration/ConsumerApiConfiguration.cs index fad4efc0cd..ed63b9305c 100644 --- a/Applications/ConsumerApi/src/Configuration/ConsumerApiConfiguration.cs +++ b/Applications/ConsumerApi/src/Configuration/ConsumerApiConfiguration.cs @@ -6,6 +6,9 @@ namespace Backbone.ConsumerApi.Configuration; public class ConsumerApiConfiguration { + [Required] + public required TelemetryConfiguration Telemetry { get; init; } + [Required] public required AuthenticationConfiguration Authentication { get; init; } @@ -21,6 +24,12 @@ public class ConsumerApiConfiguration public WellKnownEndpointsConfiguration? WellKnownEndpoints { get; init; } + public class TelemetryConfiguration + { + [Required] + public required OpenTelemetryCollectorConfiguration OpenTelemetryCollector { get; set; } = new(); + } + public class WellKnownEndpointsConfiguration { [Required] diff --git a/Applications/ConsumerApi/src/Program.cs b/Applications/ConsumerApi/src/Program.cs index 63b54eed27..c46c33d993 100644 --- a/Applications/ConsumerApi/src/Program.cs +++ b/Applications/ConsumerApi/src/Program.cs @@ -1,3 +1,4 @@ +using System.Reflection; using Autofac.Extensions.DependencyInjection; using Backbone.BuildingBlocks.API.Extensions; using Backbone.BuildingBlocks.API.Mvc.Middleware; @@ -86,14 +87,14 @@ static WebApplication CreateApp(string[] args) builder.Host .UseSerilog((context, configuration) => configuration - .ReadFrom.Configuration(context.Configuration, new ConfigurationReaderOptions { SectionName = "Logging" }) - .Enrich.WithCorrelationId("X-Correlation-Id", addValueIfHeaderAbsence: true) - .Enrich.FromLogContext() - .Enrich.WithProperty("service", "consumerapi") - .Enrich.WithExceptionDetails(new DestructuringOptionsBuilder() - .WithDefaultDestructurers() - .WithDestructurers([new DbUpdateExceptionDestructurer()])) - .Enrich.WithSensitiveDataMasking(options => options.AddSensitiveDataMasks()), preserveStaticLogger: true) + .ReadFrom.Configuration(context.Configuration, new ConfigurationReaderOptions { SectionName = "Telemetry:Logging" }) + .Enrich.WithCorrelationId("X-Correlation-Id", addValueIfHeaderAbsence: true) + .Enrich.FromLogContext() + .Enrich.WithExceptionDetails(new DestructuringOptionsBuilder() + .WithDefaultDestructurers() + .WithDestructurers([new DbUpdateExceptionDestructurer()])) + .Enrich.WithSensitiveDataMasking(options => options.AddSensitiveDataMasks()), + writeToProviders: true) .UseServiceProviderFactory(new AutofacServiceProviderFactory()); ConfigureServices(builder.Services, builder.Configuration, builder.Environment); @@ -173,7 +174,7 @@ static void ConfigureServices(IServiceCollection services, IConfiguration config options.KnownProxies.Clear(); }); - services.AddOpenTelemetryWithPrometheusExporter(METER_NAME); + services.AddOpenTelemetry(METER_NAME, Assembly.GetExecutingAssembly().GetName().Version?.ToString() ?? "unknown", parsedBackboneConfiguration.Telemetry.OpenTelemetryCollector); services.AddEventBus(parsedBackboneConfiguration.Infrastructure.EventBus, METER_NAME); services.AddHttpUserAgentParser(); @@ -184,8 +185,6 @@ static void Configure(WebApplication app, ConsumerApiConfiguration configuration if (configuration.SwaggerUi.Enabled) app.UseCustomSwaggerUi(); - app.MapPrometheusScrapingEndpoint(); - app.UseSerilogRequestLogging(opts => { opts.EnrichDiagnosticContext = LogHelper.EnrichFromRequest; @@ -214,6 +213,8 @@ static void Configure(WebApplication app, ConsumerApiConfiguration configuration app.UseCors(); app.UseAuthentication().UseAuthorization(); + app.UseMiddleware(); + app.MapControllers(); app.MapHealthChecks("/health", new HealthCheckOptions { diff --git a/Applications/ConsumerApi/src/appsettings.json b/Applications/ConsumerApi/src/appsettings.json index 182a9aa1d4..1d59d85bf3 100644 --- a/Applications/ConsumerApi/src/appsettings.json +++ b/Applications/ConsumerApi/src/appsettings.json @@ -29,22 +29,23 @@ } } }, - "Logging": { - "MinimumLevel": { - "Default": "Warning", - "Override": { - "Backbone": "Information", - "Azure.Messaging.ServiceBus": "Error" - } - }, - "WriteTo": { - "Console": { - "Name": "Console", - "Args": { - "formatter": "Serilog.Formatting.Compact.CompactJsonFormatter, Serilog.Formatting.Compact" + "Telemetry": { + "Logging": { + "MinimumLevel": { + "Default": "Warning", + "Override": { + "Backbone": "Information", + "Azure.Messaging.ServiceBus": "Error" + } + }, + "WriteTo": { + "Console": { + "Name": "Console", + "Args": { + "formatter": "Serilog.Formatting.Compact.CompactJsonFormatter, Serilog.Formatting.Compact" + } } } } } } - diff --git a/Applications/ConsumerApi/src/packages.lock.json b/Applications/ConsumerApi/src/packages.lock.json index f79b0fb5be..5e10aa829e 100644 --- a/Applications/ConsumerApi/src/packages.lock.json +++ b/Applications/ConsumerApi/src/packages.lock.json @@ -753,11 +753,6 @@ "OpenTelemetry.Api.ProviderBuilderExtensions": "1.17.0" } }, - "OpenTelemetry.Api": { - "type": "Transitive", - "resolved": "1.17.0", - "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" - }, "OpenTelemetry.Api.ProviderBuilderExtensions": { "type": "Transitive", "resolved": "1.17.0", @@ -947,9 +942,10 @@ "DotNetDiag.HealthChecks.SqlServer": "[10.0.10, 10.0.10]", "Microsoft.EntityFrameworkCore": "[10.0.10, 10.0.10]", "Microsoft.EntityFrameworkCore.Relational": "[10.0.10, 10.0.10]", - "OpenTelemetry.Exporter.Prometheus.AspNetCore": "[1.11.2-beta.1, 1.11.2-beta.1]", + "OpenTelemetry.Exporter.OpenTelemetryProtocol": "[1.17.0, )", "OpenTelemetry.Extensions.Hosting": "[1.17.0, 1.17.0]", "OpenTelemetry.Instrumentation.AspNetCore": "[1.17.0, 1.17.0]", + "OpenTelemetry.Instrumentation.EntityFrameworkCore": "[1.17.0-beta.1, )", "OpenTelemetry.Instrumentation.Http": "[1.17.0, 1.17.0]", "OpenTelemetry.Instrumentation.Runtime": "[1.17.0, 1.17.0]", "Polly": "[8.7.0, 8.7.0]", @@ -1010,6 +1006,7 @@ "Microsoft.Extensions.Identity.Core": "[10.0.10, 10.0.10]", "Microsoft.Extensions.Logging": "[10.0.10, 10.0.10]", "Npgsql.EntityFrameworkCore.PostgreSQL": "[10.0.3, 10.0.3]", + "OpenTelemetry.Api": "[1.17.0, )", "Polly": "[8.7.0, 8.7.0]", "RabbitMQ.Client": "[7.2.1, 7.2.1]", "Serilog": "[4.4.0, 4.4.0]" @@ -1949,13 +1946,19 @@ "OpenIddict.EntityFrameworkCore.Models": "7.6.0" } }, - "OpenTelemetry.Exporter.Prometheus.AspNetCore": { + "OpenTelemetry.Api": { "type": "CentralTransitive", - "requested": "[1.11.2-beta.1, 1.11.2-beta.1]", - "resolved": "1.11.2-beta.1", - "contentHash": "jouLU4VHpzyXuzF2yi/bpt9DoseZGyUudSdTFvylgIwIx6ST1bdI/AXNoJ4/n6HwMiso677ILLm/RM8DY+EYwA==", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" + }, + "OpenTelemetry.Exporter.OpenTelemetryProtocol": { + "type": "CentralTransitive", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "R1omQOrQpGlS0Cp5UIr/TAiuEA48JrPlgr1NPV5gESiTU7HhWU+ILe2EBSYb1fKdsSavZ7nZkHcUxAzofPqr2A==", "dependencies": { - "OpenTelemetry": "[1.11.2, 2.0.0)" + "OpenTelemetry": "1.17.0" } }, "OpenTelemetry.Extensions.Hosting": { @@ -1976,6 +1979,15 @@ "OpenTelemetry.Api.ProviderBuilderExtensions": "[1.17.0, 2.0.0)" } }, + "OpenTelemetry.Instrumentation.EntityFrameworkCore": { + "type": "CentralTransitive", + "requested": "[1.17.0-beta.1, )", + "resolved": "1.17.0-beta.1", + "contentHash": "BPSv1rk6qEkGZUGTNBfk7XmYqBAWdF3FBdjXEjVClp0bKUl6VCumlaosT84qvlK7YnHLCv5FFqJHx2N62TbKEw==", + "dependencies": { + "OpenTelemetry.Api.ProviderBuilderExtensions": "[1.17.0, 2.0.0)" + } + }, "OpenTelemetry.Instrumentation.Http": { "type": "CentralTransitive", "requested": "[1.17.0, 1.17.0]", diff --git a/Applications/ConsumerApi/test/ConsumerApi.Tests.Integration/packages.lock.json b/Applications/ConsumerApi/test/ConsumerApi.Tests.Integration/packages.lock.json index 638a3e4aaa..6a350cd847 100644 --- a/Applications/ConsumerApi/test/ConsumerApi.Tests.Integration/packages.lock.json +++ b/Applications/ConsumerApi/test/ConsumerApi.Tests.Integration/packages.lock.json @@ -1215,11 +1215,6 @@ "OpenTelemetry.Api.ProviderBuilderExtensions": "1.17.0" } }, - "OpenTelemetry.Api": { - "type": "Transitive", - "resolved": "1.17.0", - "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" - }, "OpenTelemetry.Api.ProviderBuilderExtensions": { "type": "Transitive", "resolved": "1.17.0", @@ -1528,9 +1523,10 @@ "DotNetDiag.HealthChecks.SqlServer": "[10.0.10, 10.0.10]", "Microsoft.EntityFrameworkCore": "[10.0.10, 10.0.10]", "Microsoft.EntityFrameworkCore.Relational": "[10.0.10, 10.0.10]", - "OpenTelemetry.Exporter.Prometheus.AspNetCore": "[1.11.2-beta.1, 1.11.2-beta.1]", + "OpenTelemetry.Exporter.OpenTelemetryProtocol": "[1.17.0, )", "OpenTelemetry.Extensions.Hosting": "[1.17.0, 1.17.0]", "OpenTelemetry.Instrumentation.AspNetCore": "[1.17.0, 1.17.0]", + "OpenTelemetry.Instrumentation.EntityFrameworkCore": "[1.17.0-beta.1, )", "OpenTelemetry.Instrumentation.Http": "[1.17.0, 1.17.0]", "OpenTelemetry.Instrumentation.Runtime": "[1.17.0, 1.17.0]", "Polly": "[8.7.0, 8.7.0]", @@ -1591,6 +1587,7 @@ "Microsoft.Extensions.Identity.Core": "[10.0.10, 10.0.10]", "Microsoft.Extensions.Logging": "[10.0.10, 10.0.10]", "Npgsql.EntityFrameworkCore.PostgreSQL": "[10.0.3, 10.0.3]", + "OpenTelemetry.Api": "[1.17.0, )", "Polly": "[8.7.0, 8.7.0]", "RabbitMQ.Client": "[7.2.1, 7.2.1]", "Serilog": "[4.4.0, 4.4.0]" @@ -2764,13 +2761,19 @@ "OpenIddict.EntityFrameworkCore.Models": "7.6.0" } }, - "OpenTelemetry.Exporter.Prometheus.AspNetCore": { + "OpenTelemetry.Api": { + "type": "CentralTransitive", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" + }, + "OpenTelemetry.Exporter.OpenTelemetryProtocol": { "type": "CentralTransitive", - "requested": "[1.11.2-beta.1, 1.11.2-beta.1]", - "resolved": "1.11.2-beta.1", - "contentHash": "jouLU4VHpzyXuzF2yi/bpt9DoseZGyUudSdTFvylgIwIx6ST1bdI/AXNoJ4/n6HwMiso677ILLm/RM8DY+EYwA==", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "R1omQOrQpGlS0Cp5UIr/TAiuEA48JrPlgr1NPV5gESiTU7HhWU+ILe2EBSYb1fKdsSavZ7nZkHcUxAzofPqr2A==", "dependencies": { - "OpenTelemetry": "[1.11.2, 2.0.0)" + "OpenTelemetry": "1.17.0" } }, "OpenTelemetry.Extensions.Hosting": { @@ -2792,6 +2795,17 @@ "OpenTelemetry.Api.ProviderBuilderExtensions": "[1.17.0, 2.0.0)" } }, + "OpenTelemetry.Instrumentation.EntityFrameworkCore": { + "type": "CentralTransitive", + "requested": "[1.17.0-beta.1, )", + "resolved": "1.17.0-beta.1", + "contentHash": "BPSv1rk6qEkGZUGTNBfk7XmYqBAWdF3FBdjXEjVClp0bKUl6VCumlaosT84qvlK7YnHLCv5FFqJHx2N62TbKEw==", + "dependencies": { + "Microsoft.Extensions.Configuration": "10.0.0", + "Microsoft.Extensions.Options": "10.0.0", + "OpenTelemetry.Api.ProviderBuilderExtensions": "[1.17.0, 2.0.0)" + } + }, "OpenTelemetry.Instrumentation.Http": { "type": "CentralTransitive", "requested": "[1.17.0, 1.17.0]", diff --git a/Applications/DatabaseMigrator/src/DatabaseMigrator/Configuration.cs b/Applications/DatabaseMigrator/src/DatabaseMigrator/Configuration.cs index 6f1bafc49b..9703ab0d7d 100644 --- a/Applications/DatabaseMigrator/src/DatabaseMigrator/Configuration.cs +++ b/Applications/DatabaseMigrator/src/DatabaseMigrator/Configuration.cs @@ -1,14 +1,23 @@ using System.ComponentModel.DataAnnotations; +using Backbone.BuildingBlocks.API.Extensions; using Backbone.BuildingBlocks.Infrastructure.Persistence.Database; namespace Backbone.DatabaseMigrator; public class Configuration { + [Required] + public required TelemetryConfiguration Telemetry { get; init; } + [Required] public required InfrastructureConfiguration Infrastructure { get; init; } } +public class TelemetryConfiguration +{ + public required OpenTelemetryCollectorConfiguration OpenTelemetryCollector { get; set; } = new(); +} + public class InfrastructureConfiguration { [Required] diff --git a/Applications/DatabaseMigrator/src/DatabaseMigrator/DatabaseMigrator.csproj b/Applications/DatabaseMigrator/src/DatabaseMigrator/DatabaseMigrator.csproj index 9e2ae7008a..b1839f82e9 100644 --- a/Applications/DatabaseMigrator/src/DatabaseMigrator/DatabaseMigrator.csproj +++ b/Applications/DatabaseMigrator/src/DatabaseMigrator/DatabaseMigrator.csproj @@ -29,6 +29,7 @@ + diff --git a/Applications/DatabaseMigrator/src/DatabaseMigrator/Dockerfile b/Applications/DatabaseMigrator/src/DatabaseMigrator/Dockerfile index a44c949d74..b0b2c198a8 100644 --- a/Applications/DatabaseMigrator/src/DatabaseMigrator/Dockerfile +++ b/Applications/DatabaseMigrator/src/DatabaseMigrator/Dockerfile @@ -17,6 +17,8 @@ COPY ["Applications/AdminApi/src/AdminApi.Infrastructure.Database.SqlServer/Admi COPY ["Applications/AdminApi/src/AdminApi.Infrastructure.Database.SqlServer/AdminApi.Infrastructure.Database.SqlServer.csproj", "Applications/AdminApi/src/AdminApi.Infrastructure.Database.SqlServer/packages.lock.json*", "Applications/AdminApi/src/AdminApi.Infrastructure.Database.SqlServer/"] COPY ["Applications/AdminApi/src/AdminApi.Infrastructure.Database.Postgres/AdminApi.Infrastructure.Database.Postgres.csproj", "Applications/AdminApi/src/AdminApi.Infrastructure.Database.Postgres/packages.lock.json*", "Applications/AdminApi/src/AdminApi.Infrastructure.Database.Postgres/"] +COPY ["BuildingBlocks/src/BuildingBlocks.API/BuildingBlocks.API.csproj", "BuildingBlocks/src/BuildingBlocks.API/packages.lock.json*", "BuildingBlocks/src/BuildingBlocks.API/"] +COPY ["BuildingBlocks/src/BuildingBlocks.Module/BuildingBlocks.Module.csproj", "BuildingBlocks/src/BuildingBlocks.Module/packages.lock.json*", "BuildingBlocks/src/BuildingBlocks.Module/"] COPY ["BuildingBlocks/src/BuildingBlocks.Infrastructure/BuildingBlocks.Infrastructure.csproj", "BuildingBlocks/src/BuildingBlocks.Infrastructure/packages.lock.json*", "BuildingBlocks/src/BuildingBlocks.Infrastructure/"] COPY ["BuildingBlocks/src/BuildingBlocks.Application.Abstractions/BuildingBlocks.Application.Abstractions.csproj", "BuildingBlocks/src/BuildingBlocks.Application.Abstractions/packages.lock.json*", "BuildingBlocks/src/BuildingBlocks.Application.Abstractions/"] COPY ["BuildingBlocks/src/DevelopmentKit.Identity/DevelopmentKit.Identity.csproj", "BuildingBlocks/src/DevelopmentKit.Identity/packages.lock.json*", "BuildingBlocks/src/DevelopmentKit.Identity/"] @@ -82,7 +84,7 @@ COPY ["Modules/Tokens/src/Tokens.Application/Tokens.Application.csproj", "Module COPY ["Modules/Tokens/src/Tokens.Domain/Tokens.Domain.csproj", "Modules/Tokens/src/Tokens.Domain/packages.lock.json*", "Modules/Tokens/src/Tokens.Domain/"] COPY ["Modules/Tokens/src/Tokens.Infrastructure.Database.Postgres/Tokens.Infrastructure.Database.Postgres.csproj", "Modules/Tokens/src/Tokens.Infrastructure.Database.Postgres/packages.lock.json*", "Modules/Tokens/src/Tokens.Infrastructure.Database.Postgres/"] -RUN dotnet restore /p:ContinuousIntegrationBuild=true "Applications/DatabaseMigrator/src/DatabaseMigrator/DatabaseMigrator.csproj" +RUN dotnet restore /p:ContinuousIntegrationBuild=true /p:Configuration=Release "Applications/DatabaseMigrator/src/DatabaseMigrator/DatabaseMigrator.csproj" COPY . . diff --git a/Applications/DatabaseMigrator/src/DatabaseMigrator/Program.cs b/Applications/DatabaseMigrator/src/DatabaseMigrator/Program.cs index be677d8218..9104cd375b 100644 --- a/Applications/DatabaseMigrator/src/DatabaseMigrator/Program.cs +++ b/Applications/DatabaseMigrator/src/DatabaseMigrator/Program.cs @@ -1,4 +1,6 @@ -using Autofac.Extensions.DependencyInjection; +using System.Reflection; +using Autofac.Extensions.DependencyInjection; +using Backbone.BuildingBlocks.API.Extensions; using Backbone.BuildingBlocks.Application.Abstractions.Infrastructure.EventBus; using Backbone.DatabaseMigrator; using Microsoft.Extensions.Options; @@ -62,15 +64,21 @@ static IHostBuilder CreateHostBuilder(string[] args) services.AddSingleton(); services.AddAllDbContexts(parsedConfiguration.Infrastructure.SqlDatabase); + + services.AddOpenTelemetry(METER_NAME, Assembly.GetExecutingAssembly().GetName().Version?.ToString() ?? "unknown", parsedConfiguration.Telemetry.OpenTelemetryCollector); }) .UseServiceProviderFactory(new AutofacServiceProviderFactory()) .UseSerilog((context, configuration) => configuration - .ReadFrom.Configuration(context.Configuration, new ConfigurationReaderOptions { SectionName = "Logging" }) + .ReadFrom.Configuration(context.Configuration, new ConfigurationReaderOptions { SectionName = "Telemetry:Logging" }) .Enrich.FromLogContext() - .Enrich.WithProperty("service", "databasemigrator") .Enrich.WithExceptionDetails(new DestructuringOptionsBuilder() .WithDefaultDestructurers() .WithDestructurers([new DbUpdateExceptionDestructurer()]) ), preserveStaticLogger: true ); } + +public partial class Program +{ + private const string METER_NAME = "enmeshed.backbone.databasemigrator"; +} diff --git a/Applications/DatabaseMigrator/src/DatabaseMigrator/appsettings.json b/Applications/DatabaseMigrator/src/DatabaseMigrator/appsettings.json index 4ba48a4ddd..1d59d85bf3 100644 --- a/Applications/DatabaseMigrator/src/DatabaseMigrator/appsettings.json +++ b/Applications/DatabaseMigrator/src/DatabaseMigrator/appsettings.json @@ -29,19 +29,21 @@ } } }, - "Logging": { - "MinimumLevel": { - "Default": "Warning", - "Override": { - "Backbone": "Information", - "Azure.Messaging.ServiceBus": "Error" - } - }, - "WriteTo": { - "Console": { - "Name": "Console", - "Args": { - "formatter": "Serilog.Formatting.Compact.CompactJsonFormatter, Serilog.Formatting.Compact" + "Telemetry": { + "Logging": { + "MinimumLevel": { + "Default": "Warning", + "Override": { + "Backbone": "Information", + "Azure.Messaging.ServiceBus": "Error" + } + }, + "WriteTo": { + "Console": { + "Name": "Console", + "Args": { + "formatter": "Serilog.Formatting.Compact.CompactJsonFormatter, Serilog.Formatting.Compact" + } } } } diff --git a/Applications/DatabaseMigrator/src/DatabaseMigrator/packages.lock.json b/Applications/DatabaseMigrator/src/DatabaseMigrator/packages.lock.json index 1fbbc019fb..4a48f227e4 100644 --- a/Applications/DatabaseMigrator/src/DatabaseMigrator/packages.lock.json +++ b/Applications/DatabaseMigrator/src/DatabaseMigrator/packages.lock.json @@ -182,6 +182,22 @@ "runtime.native.System.Data.SqlClient.sni": "4.4.0" } }, + "Asp.Versioning.Abstractions": { + "type": "Transitive", + "resolved": "10.1.0", + "contentHash": "RwdgC5O0baZ4pt30pAKKPQHq2CV4unBKA4HWoTeu7NY9ZwXM0dWYGf1Ipc5GK0eFBe9cMeqz4pGpPncMz4/ZNQ==", + "dependencies": { + "Microsoft.Extensions.Primitives": "10.0.0" + } + }, + "Asp.Versioning.Http": { + "type": "Transitive", + "resolved": "10.0.1", + "contentHash": "g0ayV/9ho3tGgooC6eF5p1063I1WzlxFJDYQrigcGnW+mLvui6eXrcW5hzTHhQREroUR3ZwXQrIN2SAIoi+KDw==", + "dependencies": { + "Asp.Versioning.Abstractions": "10.1.0" + } + }, "AWSSDK.Core": { "type": "Transitive", "resolved": "4.0.100.9", @@ -210,16 +226,6 @@ "System.Memory.Data": "1.0.2" } }, - "Azure.Identity": { - "type": "Transitive", - "resolved": "1.17.1", - "contentHash": "MSZkBrctcpiGxs9Cvr2VKKoN6qFLZlP3I6xuCWJ9iTgitI5Rgxtk5gfOSpXPZE3+CJmZ/mnqpQyGyjawFn5Vvg==", - "dependencies": { - "Azure.Core": "1.50.0", - "Microsoft.Identity.Client": "4.78.0", - "Microsoft.Identity.Client.Extensions.Msal": "4.78.0" - } - }, "Azure.Storage.Common": { "type": "Transitive", "resolved": "12.28.0", @@ -491,22 +497,34 @@ }, "Microsoft.Data.SqlClient": { "type": "Transitive", - "resolved": "6.1.4", - "contentHash": "lQcSog5LLImg4yNEuuG6ccvdzXnCvER8Rms9Ngk9zB4Q8na4f+S7/abSoC7gnEltBg4e5xTnLAWmMLIOtLg4pg==", + "resolved": "7.0.2", + "contentHash": "zwv76lANFQQI6Gmp6ntkzMWIWVqm8Wf4Mz00AeGCk1n8HCi5afi6bNynSe18uI0xeL0n6J+Myjk9AiIsL5oSqw==", + "dependencies": { + "Microsoft.Bcl.Cryptography": "9.0.13", + "Microsoft.Data.SqlClient.Extensions.Abstractions": "[7.0.2, 8.0.0)", + "Microsoft.Data.SqlClient.Internal.Logging": "[7.0.2, 8.0.0)", + "Microsoft.Data.SqlClient.SNI.runtime": "[6.0.2, 7.0.0)", + "Microsoft.Extensions.Caching.Memory": "9.0.13", + "Microsoft.IdentityModel.JsonWebTokens": "8.16.0", + "Microsoft.IdentityModel.Protocols.OpenIdConnect": "8.16.0", + "Microsoft.SqlServer.Server": "[1.0.0, 2.0.0)", + "System.Configuration.ConfigurationManager": "9.0.13", + "System.Security.Cryptography.Pkcs": "9.0.13" + } + }, + "Microsoft.Data.SqlClient.Extensions.Abstractions": { + "type": "Transitive", + "resolved": "7.0.2", + "contentHash": "Zx7z61fG2Nc6LdDn4jA7b5Aj1ABrljkOPRE31RvVUdjF6IgbG60leDUhMCafsnWFgaheiK3iqpLe+kbf5Z5L8Q==", "dependencies": { - "Azure.Core": "1.50.0", - "Azure.Identity": "1.17.1", - "Microsoft.Data.SqlClient.SNI.runtime": "6.0.2", - "Microsoft.Extensions.Caching.Memory": "9.0.11", - "Microsoft.Identity.Client": "4.80.0", - "Microsoft.IdentityModel.JsonWebTokens": "7.7.1", - "Microsoft.IdentityModel.Protocols.OpenIdConnect": "7.7.1", - "Microsoft.SqlServer.Server": "1.0.0", - "System.Configuration.ConfigurationManager": "9.0.11", - "System.IdentityModel.Tokens.Jwt": "7.7.1", - "System.Security.Cryptography.Pkcs": "9.0.11" + "Microsoft.Data.SqlClient.Internal.Logging": "[7.0.2, 8.0.0)" } }, + "Microsoft.Data.SqlClient.Internal.Logging": { + "type": "Transitive", + "resolved": "7.0.2", + "contentHash": "iqgYBbGSVy/DIYWjzmQOa964Kn4rs4wW5vg2IamqVK0fQqfTiILVR5hMK27XWqoyONtAZs+VxH354cPJBtSnbg==" + }, "Microsoft.Data.SqlClient.SNI.runtime": { "type": "Transitive", "resolved": "6.0.2", @@ -549,6 +567,11 @@ "Microsoft.Extensions.Options.ConfigurationExtensions": "10.0.10" } }, + "Microsoft.Extensions.ApiDescription.Server": { + "type": "Transitive", + "resolved": "10.0.0", + "contentHash": "NCWCGiwRwje8773yzPQhvucYnnfeR+ZoB1VRIrIMp4uaeUNw7jvEPHij3HIbwCDuNCrNcphA00KSAR9yD9qmbg==" + }, "Microsoft.Extensions.Caching.Abstractions": { "type": "Transitive", "resolved": "10.0.10", @@ -907,11 +930,11 @@ }, "Microsoft.IdentityModel.Protocols.OpenIdConnect": { "type": "Transitive", - "resolved": "7.7.1", - "contentHash": "yT2Hdj8LpPbcT9C9KlLVxXl09C8zjFaVSaApdOwuecMuoV4s6Sof/mnTDz/+F/lILPIBvrWugR9CC7iRVZgbfQ==", + "resolved": "8.16.0", + "contentHash": "h4yVXyJsEBBX5lg2G5ftMsi5JzcNEGAzrNphA6DQ6eOd8P0s+cDCOyPwVTYLePZvJL5unbPvYIvzrbTXzFjXnQ==", "dependencies": { - "Microsoft.IdentityModel.Protocols": "7.7.1", - "System.IdentityModel.Tokens.Jwt": "7.7.1" + "Microsoft.IdentityModel.Protocols": "8.16.0", + "System.IdentityModel.Tokens.Jwt": "8.16.0" } }, "Microsoft.IdentityModel.Tokens": { @@ -924,6 +947,11 @@ "Microsoft.IdentityModel.Logging": "8.19.2" } }, + "Microsoft.OpenApi": { + "type": "Transitive", + "resolved": "2.7.5", + "contentHash": "0FA67RSnRM4tcBKqiqVu/HPdZ9+QOKbmeRjxRUGTCjPU4C0bmUhd97Dso7Yild5P7nOV6GxJ2xrK0Kv/O9xp0w==" + }, "Microsoft.SqlServer.Server": { "type": "Transitive", "resolved": "1.0.0", @@ -1141,6 +1169,26 @@ "OpenIddict.Validation": "7.6.0" } }, + "OpenTelemetry": { + "type": "Transitive", + "resolved": "1.17.0", + "contentHash": "rMLOTftlMlTm7+MSrvXDHnJRjVkROFNKXHZrYjOsX+LankaFG7QSflx7qRRGjoqZoirohnxmJQ7GEb9occO4Gg==", + "dependencies": { + "Microsoft.Extensions.Configuration.EnvironmentVariables": "10.0.0", + "Microsoft.Extensions.Diagnostics.Abstractions": "10.0.0", + "Microsoft.Extensions.Logging.Configuration": "10.0.0", + "OpenTelemetry.Api.ProviderBuilderExtensions": "1.17.0" + } + }, + "OpenTelemetry.Api.ProviderBuilderExtensions": { + "type": "Transitive", + "resolved": "1.17.0", + "contentHash": "Xgc3Qf9B9TFMFpx6exTdGqMWuYIT2miNzkdMPutVvT9YuMFaEovXWke1Gb6z8NxYaQbbGF38vYLuSg1JCeui5Q==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0", + "OpenTelemetry.Api": "1.17.0" + } + }, "Polly.Core": { "type": "Transitive", "resolved": "8.7.0", @@ -1220,6 +1268,27 @@ "resolved": "2.1.11", "contentHash": "PK0GLFkfhZzLQeR3PJf71FmhtHox+U3vcY6ZtswoMjrefkB9k6ErNJEnwXqc5KgXDSjige2XXrezqS39gkpQKA==" }, + "Swashbuckle.AspNetCore.Swagger": { + "type": "Transitive", + "resolved": "10.2.3", + "contentHash": "1jUUs3WQnrS0FUtaZPLSy1yYMEwS1zlvDmvQ2/eldPHUANX0LJSLVZecCMgSMdeGiRqeaRrIXLtSz++TCiTMww==", + "dependencies": { + "Microsoft.OpenApi": "2.7.5" + } + }, + "Swashbuckle.AspNetCore.SwaggerGen": { + "type": "Transitive", + "resolved": "10.2.3", + "contentHash": "y7t4coDRAeFYChmvlMRiH2OjbiRrm9AVIDgt17fQfs3x9PVAI5PiwWYOhg+4F13R4Q36WDc9lqfoOnNa3tNbGg==", + "dependencies": { + "Swashbuckle.AspNetCore.Swagger": "10.2.3" + } + }, + "Swashbuckle.AspNetCore.SwaggerUI": { + "type": "Transitive", + "resolved": "10.2.3", + "contentHash": "nthWONRs/FJ4yyG206g1cC52WEG8EqrjuMWjGdR+5XG7lbjFto6NqcI9EMICgVFom/UivIjUVwI76ZHbHwTPfQ==" + }, "System.ClientModel": { "type": "Transitive", "resolved": "1.14.0", @@ -1286,11 +1355,11 @@ }, "System.Configuration.ConfigurationManager": { "type": "Transitive", - "resolved": "9.0.11", - "contentHash": "vPinosRgEk1CGjohbv0pDuz6gPprkWo5xvBTjOJjks5JOgOEWvPndq5NngGxiTcBcy1+k9GwzZ1c3Bp2fU5ezw==", + "resolved": "9.0.13", + "contentHash": "GbBrJq9S/gYpHzm7Pxx6Y5tDyfSfyxW6tlP5oiKJV38uf19Wp+GIIAnWfyL1zmNiz1+EjwVapw2WkBFvvqKQzg==", "dependencies": { - "System.Diagnostics.EventLog": "9.0.11", - "System.Security.Cryptography.ProtectedData": "9.0.11" + "System.Diagnostics.EventLog": "9.0.13", + "System.Security.Cryptography.ProtectedData": "9.0.13" } }, "System.Diagnostics.EventLog": { @@ -1300,11 +1369,11 @@ }, "System.IdentityModel.Tokens.Jwt": { "type": "Transitive", - "resolved": "7.7.1", - "contentHash": "rQkO1YbAjLwnDJSMpRhRtrc6XwIcEOcUvoEcge+evurpzSZM3UNK+MZfD3sKyTlYsvknZ6eJjSBfnmXqwOsT9Q==", + "resolved": "8.16.0", + "contentHash": "rrs2u7DRMXQG2yh0oVyF/vLwosfRv20Ld2iEpYcKwQWXHjfV+gFXNQsQ9p008kR9Ou4pxBs68Q6/9zC8Gi1wjg==", "dependencies": { - "Microsoft.IdentityModel.JsonWebTokens": "7.7.1", - "Microsoft.IdentityModel.Tokens": "7.7.1" + "Microsoft.IdentityModel.JsonWebTokens": "8.16.0", + "Microsoft.IdentityModel.Tokens": "8.16.0" } }, "System.IO.Hashing": { @@ -1337,8 +1406,8 @@ }, "System.Security.Cryptography.ProtectedData": { "type": "Transitive", - "resolved": "9.0.11", - "contentHash": "s8yUYuYYu+PAwvBdhLG1KyrGrk9gkYeuPxfAsXsTqqWyepwSyEw8hAaflW4nO98NG52YpYI1am2+9o+79h2RtQ==" + "resolved": "9.0.13", + "contentHash": "t8S9IDpjJKsLpLkeBdW8cWtcPyYqrGu93Dej1RO6WwuL/lkFSqWlan3rMJfortqz1mRIh+sys2AFsSA6jWJ3Jg==" }, "System.Security.Cryptography.Xml": { "type": "Transitive", @@ -1371,6 +1440,33 @@ "Backbone.AdminApi.Infrastructure": "[1.0.0, )" } }, + "Backbone.BuildingBlocks.API": { + "type": "Project", + "dependencies": { + "Asp.Versioning.Mvc": "[10.0.1, 10.0.1]", + "Asp.Versioning.Mvc.ApiExplorer": "[10.0.1, 10.0.1]", + "Backbone.BuildingBlocks.Application": "[1.0.0, )", + "Backbone.BuildingBlocks.Module": "[1.0.0, )", + "Backbone.Modules.Devices.Domain": "[1.0.0, )", + "Backbone.Modules.Devices.Infrastructure": "[1.0.0, )", + "Backbone.Tooling": "[1.0.0, )", + "DotNetDiag.HealthChecks.NpgSql": "[10.0.10, 10.0.10]", + "DotNetDiag.HealthChecks.SqlServer": "[10.0.10, 10.0.10]", + "Microsoft.EntityFrameworkCore": "[10.0.10, 10.0.10]", + "Microsoft.EntityFrameworkCore.Relational": "[10.0.10, 10.0.10]", + "OpenTelemetry.Exporter.OpenTelemetryProtocol": "[1.17.0, )", + "OpenTelemetry.Extensions.Hosting": "[1.17.0, 1.17.0]", + "OpenTelemetry.Instrumentation.AspNetCore": "[1.17.0, 1.17.0]", + "OpenTelemetry.Instrumentation.EntityFrameworkCore": "[1.17.0-beta.1, )", + "OpenTelemetry.Instrumentation.Http": "[1.17.0, 1.17.0]", + "OpenTelemetry.Instrumentation.Runtime": "[1.17.0, 1.17.0]", + "Polly": "[8.7.0, 8.7.0]", + "Serilog.Enrichers.Sensitive": "[2.1.0, 2.1.0]", + "Serilog.Extensions.Hosting": "[10.0.0, 10.0.0]", + "Swashbuckle.AspNetCore": "[10.2.3, 10.2.3]", + "System.Data.SqlClient": "[4.9.1, 4.9.1]" + } + }, "Backbone.BuildingBlocks.Application": { "type": "Project", "dependencies": { @@ -1422,11 +1518,21 @@ "Microsoft.Extensions.Identity.Core": "[10.0.10, 10.0.10]", "Microsoft.Extensions.Logging": "[10.0.10, 10.0.10]", "Npgsql.EntityFrameworkCore.PostgreSQL": "[10.0.3, 10.0.3]", + "OpenTelemetry.Api": "[1.17.0, )", "Polly": "[8.7.0, 8.7.0]", "RabbitMQ.Client": "[7.2.1, 7.2.1]", "Serilog": "[4.4.0, 4.4.0]" } }, + "Backbone.BuildingBlocks.Module": { + "type": "Project", + "dependencies": { + "Backbone.BuildingBlocks.Application.Abstractions": "[1.0.0, )", + "Microsoft.Extensions.Configuration.Abstractions": "[10.0.10, 10.0.10]", + "Microsoft.Extensions.DependencyInjection.Abstractions": "[10.0.10, 10.0.10]", + "ReHackt.Extensions.Options.Validation": "[10.0.1, 10.0.1]" + } + }, "Backbone.Common.Infrastructure": { "type": "Project", "dependencies": { @@ -1852,6 +1958,24 @@ "Microsoft.Extensions.Options": "[10.0.10, 10.0.10]" } }, + "Asp.Versioning.Mvc": { + "type": "CentralTransitive", + "requested": "[10.0.1, 10.0.1]", + "resolved": "10.0.1", + "contentHash": "OqoFPKKxXkNmw62H3CgXkPrf1L4PPwwyYr9QMP6itt/khKTIayqaHhK6F2e3jt6KHc4s23cWAUbu+Z5GPEeMaw==", + "dependencies": { + "Asp.Versioning.Http": "10.0.1" + } + }, + "Asp.Versioning.Mvc.ApiExplorer": { + "type": "CentralTransitive", + "requested": "[10.0.1, 10.0.1]", + "resolved": "10.0.1", + "contentHash": "ylPZe+LheFp0pt2tSMq2pPeGAkMLqWVOn5+1/xOB/eUj889n9b35Sny08bSQ0ziAGIFjp3BBTXaYsWJjRoFV4A==", + "dependencies": { + "Asp.Versioning.Mvc": "10.0.1" + } + }, "Autofac": { "type": "CentralTransitive", "requested": "[9.3.2, 9.3.2]", @@ -1906,6 +2030,26 @@ "resolved": "2.1.79", "contentHash": "8YijbzgTfmqmQOnVNorYM6K++pxqnW3nJ4aC1sRHzxUA2CcuoJ9gsTem3kgBnPRMc38zZHl4Esb6hAezXIEEuw==" }, + "DotNetDiag.HealthChecks.NpgSql": { + "type": "CentralTransitive", + "requested": "[10.0.10, 10.0.10]", + "resolved": "10.0.10", + "contentHash": "lxb6wQ1YC/TpvZMVgbyeLP5dYOg/RJWLg1xlR+I0FeyfyMmukppKdwzBOrKRtZ8FHG3nV9xrVTaPdwRw0yL4Vw==", + "dependencies": { + "Microsoft.Extensions.Diagnostics.HealthChecks": "10.0.9", + "Npgsql": "10.0.3" + } + }, + "DotNetDiag.HealthChecks.SqlServer": { + "type": "CentralTransitive", + "requested": "[10.0.10, 10.0.10]", + "resolved": "10.0.10", + "contentHash": "6t2HP5VQR0GZDJiw8iZvzOTRC+84irUeaUuWvcqcnc4K5Mzrn/A9V0ucoyjySXOF1vGkdTHjlJMknJVYC9c2Hg==", + "dependencies": { + "Microsoft.Data.SqlClient": "7.0.2", + "Microsoft.Extensions.Diagnostics.HealthChecks": "10.0.9" + } + }, "EFCore.BulkExtensions.Core": { "type": "CentralTransitive", "requested": "[10.0.1, 10.0.1]", @@ -2276,6 +2420,71 @@ "OpenIddict.EntityFrameworkCore.Models": "7.6.0" } }, + "OpenTelemetry.Api": { + "type": "CentralTransitive", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" + }, + "OpenTelemetry.Exporter.OpenTelemetryProtocol": { + "type": "CentralTransitive", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "R1omQOrQpGlS0Cp5UIr/TAiuEA48JrPlgr1NPV5gESiTU7HhWU+ILe2EBSYb1fKdsSavZ7nZkHcUxAzofPqr2A==", + "dependencies": { + "OpenTelemetry": "1.17.0" + } + }, + "OpenTelemetry.Extensions.Hosting": { + "type": "CentralTransitive", + "requested": "[1.17.0, 1.17.0]", + "resolved": "1.17.0", + "contentHash": "t1OwL/4qgboGMobYVT+UV5zgWnFqCp4Pw8lcsmzh8m2K8PQsTKkyxrC32tqYTMYny3GOW4q5cltE3dTVzLmRew==", + "dependencies": { + "Microsoft.Extensions.Hosting.Abstractions": "10.0.0", + "OpenTelemetry": "1.17.0" + } + }, + "OpenTelemetry.Instrumentation.AspNetCore": { + "type": "CentralTransitive", + "requested": "[1.17.0, 1.17.0]", + "resolved": "1.17.0", + "contentHash": "rGbmk1vuy1kvgZmE0ps7Vb99YZvDap6AalrrF60FwnNit1uW/PbeFZj1cpb0T8MPkYmjhBrRJ1/JB6QqXkRjHA==", + "dependencies": { + "OpenTelemetry.Api.ProviderBuilderExtensions": "[1.17.0, 2.0.0)" + } + }, + "OpenTelemetry.Instrumentation.EntityFrameworkCore": { + "type": "CentralTransitive", + "requested": "[1.17.0-beta.1, )", + "resolved": "1.17.0-beta.1", + "contentHash": "BPSv1rk6qEkGZUGTNBfk7XmYqBAWdF3FBdjXEjVClp0bKUl6VCumlaosT84qvlK7YnHLCv5FFqJHx2N62TbKEw==", + "dependencies": { + "Microsoft.Extensions.Configuration": "10.0.0", + "Microsoft.Extensions.Options": "10.0.0", + "OpenTelemetry.Api.ProviderBuilderExtensions": "[1.17.0, 2.0.0)" + } + }, + "OpenTelemetry.Instrumentation.Http": { + "type": "CentralTransitive", + "requested": "[1.17.0, 1.17.0]", + "resolved": "1.17.0", + "contentHash": "uTwVtxIJ/xB96wGYTaDsbkJVeCFdUxTwvrlDUn2YJixy0UuKc8DvQMzwKNJMTzNFiiyYO9c40id6tUHTmWs33A==", + "dependencies": { + "Microsoft.Extensions.Configuration": "10.0.0", + "Microsoft.Extensions.Options": "10.0.0", + "OpenTelemetry.Api.ProviderBuilderExtensions": "[1.17.0, 2.0.0)" + } + }, + "OpenTelemetry.Instrumentation.Runtime": { + "type": "CentralTransitive", + "requested": "[1.17.0, 1.17.0]", + "resolved": "1.17.0", + "contentHash": "HyYenisDn/xdtyVXdjImsCl+RNC2gq01N0rvSR7tsYAylXR2sxX/YgMsyTajMXA27+r1vB7lNU8cWRhV0fwL+Q==", + "dependencies": { + "OpenTelemetry.Api": "[1.17.0, 2.0.0)" + } + }, "Polly": { "type": "CentralTransitive", "requested": "[8.7.0, 8.7.0]", @@ -2294,11 +2503,29 @@ "System.Threading.RateLimiting": "8.0.0" } }, + "Serilog.Enrichers.Sensitive": { + "type": "CentralTransitive", + "requested": "[2.1.0, 2.1.0]", + "resolved": "2.1.0", + "contentHash": "nlaEYMoHjJqncjQgc0Nv4LOIkAwUt4Nvmx3EMNjY4MKC7QqZs9zB0v/NwFnaWzLF7qztc7mna1bjn20Auohu0g==" + }, "SimpleBase": { "type": "CentralTransitive", "requested": "[5.6.3, 5.6.3]", "resolved": "5.6.3", "contentHash": "ayL730f1gdQVYmFFLKSX83QcoltyKSMBsV94qfCBpZHMaJz/e3ALuXKZDD8SkseWbNHxBe0HxLRBe5OOpQ9HpA==" + }, + "Swashbuckle.AspNetCore": { + "type": "CentralTransitive", + "requested": "[10.2.3, 10.2.3]", + "resolved": "10.2.3", + "contentHash": "8KNh1RWvofdU6DVLyBs4Z/OpUMnmf8oNvJQc0QxpwySRbi42bwLfdVMMrXZWANg5U5KQGQq1xW6r/hlcqw99tQ==", + "dependencies": { + "Microsoft.Extensions.ApiDescription.Server": "10.0.0", + "Swashbuckle.AspNetCore.Swagger": "10.2.3", + "Swashbuckle.AspNetCore.SwaggerGen": "10.2.3", + "Swashbuckle.AspNetCore.SwaggerUI": "10.2.3" + } } }, "net10.0/linux-arm64": { @@ -2318,20 +2545,19 @@ }, "Microsoft.Data.SqlClient": { "type": "Transitive", - "resolved": "6.1.4", - "contentHash": "lQcSog5LLImg4yNEuuG6ccvdzXnCvER8Rms9Ngk9zB4Q8na4f+S7/abSoC7gnEltBg4e5xTnLAWmMLIOtLg4pg==", + "resolved": "7.0.2", + "contentHash": "zwv76lANFQQI6Gmp6ntkzMWIWVqm8Wf4Mz00AeGCk1n8HCi5afi6bNynSe18uI0xeL0n6J+Myjk9AiIsL5oSqw==", "dependencies": { - "Azure.Core": "1.50.0", - "Azure.Identity": "1.17.1", - "Microsoft.Data.SqlClient.SNI.runtime": "6.0.2", - "Microsoft.Extensions.Caching.Memory": "9.0.11", - "Microsoft.Identity.Client": "4.80.0", - "Microsoft.IdentityModel.JsonWebTokens": "7.7.1", - "Microsoft.IdentityModel.Protocols.OpenIdConnect": "7.7.1", - "Microsoft.SqlServer.Server": "1.0.0", - "System.Configuration.ConfigurationManager": "9.0.11", - "System.IdentityModel.Tokens.Jwt": "7.7.1", - "System.Security.Cryptography.Pkcs": "9.0.11" + "Microsoft.Bcl.Cryptography": "9.0.13", + "Microsoft.Data.SqlClient.Extensions.Abstractions": "[7.0.2, 8.0.0)", + "Microsoft.Data.SqlClient.Internal.Logging": "[7.0.2, 8.0.0)", + "Microsoft.Data.SqlClient.SNI.runtime": "[6.0.2, 7.0.0)", + "Microsoft.Extensions.Caching.Memory": "9.0.13", + "Microsoft.IdentityModel.JsonWebTokens": "8.16.0", + "Microsoft.IdentityModel.Protocols.OpenIdConnect": "8.16.0", + "Microsoft.SqlServer.Server": "[1.0.0, 2.0.0)", + "System.Configuration.ConfigurationManager": "9.0.13", + "System.Security.Cryptography.Pkcs": "9.0.13" } }, "Microsoft.Data.SqlClient.SNI.runtime": { @@ -2398,20 +2624,19 @@ }, "Microsoft.Data.SqlClient": { "type": "Transitive", - "resolved": "6.1.4", - "contentHash": "lQcSog5LLImg4yNEuuG6ccvdzXnCvER8Rms9Ngk9zB4Q8na4f+S7/abSoC7gnEltBg4e5xTnLAWmMLIOtLg4pg==", + "resolved": "7.0.2", + "contentHash": "zwv76lANFQQI6Gmp6ntkzMWIWVqm8Wf4Mz00AeGCk1n8HCi5afi6bNynSe18uI0xeL0n6J+Myjk9AiIsL5oSqw==", "dependencies": { - "Azure.Core": "1.50.0", - "Azure.Identity": "1.17.1", - "Microsoft.Data.SqlClient.SNI.runtime": "6.0.2", - "Microsoft.Extensions.Caching.Memory": "9.0.11", - "Microsoft.Identity.Client": "4.80.0", - "Microsoft.IdentityModel.JsonWebTokens": "7.7.1", - "Microsoft.IdentityModel.Protocols.OpenIdConnect": "7.7.1", - "Microsoft.SqlServer.Server": "1.0.0", - "System.Configuration.ConfigurationManager": "9.0.11", - "System.IdentityModel.Tokens.Jwt": "7.7.1", - "System.Security.Cryptography.Pkcs": "9.0.11" + "Microsoft.Bcl.Cryptography": "9.0.13", + "Microsoft.Data.SqlClient.Extensions.Abstractions": "[7.0.2, 8.0.0)", + "Microsoft.Data.SqlClient.Internal.Logging": "[7.0.2, 8.0.0)", + "Microsoft.Data.SqlClient.SNI.runtime": "[6.0.2, 7.0.0)", + "Microsoft.Extensions.Caching.Memory": "9.0.13", + "Microsoft.IdentityModel.JsonWebTokens": "8.16.0", + "Microsoft.IdentityModel.Protocols.OpenIdConnect": "8.16.0", + "Microsoft.SqlServer.Server": "[1.0.0, 2.0.0)", + "System.Configuration.ConfigurationManager": "9.0.13", + "System.Security.Cryptography.Pkcs": "9.0.13" } }, "Microsoft.Data.SqlClient.SNI.runtime": { @@ -2478,20 +2703,19 @@ }, "Microsoft.Data.SqlClient": { "type": "Transitive", - "resolved": "6.1.4", - "contentHash": "lQcSog5LLImg4yNEuuG6ccvdzXnCvER8Rms9Ngk9zB4Q8na4f+S7/abSoC7gnEltBg4e5xTnLAWmMLIOtLg4pg==", + "resolved": "7.0.2", + "contentHash": "zwv76lANFQQI6Gmp6ntkzMWIWVqm8Wf4Mz00AeGCk1n8HCi5afi6bNynSe18uI0xeL0n6J+Myjk9AiIsL5oSqw==", "dependencies": { - "Azure.Core": "1.50.0", - "Azure.Identity": "1.17.1", - "Microsoft.Data.SqlClient.SNI.runtime": "6.0.2", - "Microsoft.Extensions.Caching.Memory": "9.0.11", - "Microsoft.Identity.Client": "4.80.0", - "Microsoft.IdentityModel.JsonWebTokens": "7.7.1", - "Microsoft.IdentityModel.Protocols.OpenIdConnect": "7.7.1", - "Microsoft.SqlServer.Server": "1.0.0", - "System.Configuration.ConfigurationManager": "9.0.11", - "System.IdentityModel.Tokens.Jwt": "7.7.1", - "System.Security.Cryptography.Pkcs": "9.0.11" + "Microsoft.Bcl.Cryptography": "9.0.13", + "Microsoft.Data.SqlClient.Extensions.Abstractions": "[7.0.2, 8.0.0)", + "Microsoft.Data.SqlClient.Internal.Logging": "[7.0.2, 8.0.0)", + "Microsoft.Data.SqlClient.SNI.runtime": "[6.0.2, 7.0.0)", + "Microsoft.Extensions.Caching.Memory": "9.0.13", + "Microsoft.IdentityModel.JsonWebTokens": "8.16.0", + "Microsoft.IdentityModel.Protocols.OpenIdConnect": "8.16.0", + "Microsoft.SqlServer.Server": "[1.0.0, 2.0.0)", + "System.Configuration.ConfigurationManager": "9.0.13", + "System.Security.Cryptography.Pkcs": "9.0.13" } }, "Microsoft.Data.SqlClient.SNI.runtime": { @@ -2558,20 +2782,19 @@ }, "Microsoft.Data.SqlClient": { "type": "Transitive", - "resolved": "6.1.4", - "contentHash": "lQcSog5LLImg4yNEuuG6ccvdzXnCvER8Rms9Ngk9zB4Q8na4f+S7/abSoC7gnEltBg4e5xTnLAWmMLIOtLg4pg==", - "dependencies": { - "Azure.Core": "1.50.0", - "Azure.Identity": "1.17.1", - "Microsoft.Data.SqlClient.SNI.runtime": "6.0.2", - "Microsoft.Extensions.Caching.Memory": "9.0.11", - "Microsoft.Identity.Client": "4.80.0", - "Microsoft.IdentityModel.JsonWebTokens": "7.7.1", - "Microsoft.IdentityModel.Protocols.OpenIdConnect": "7.7.1", - "Microsoft.SqlServer.Server": "1.0.0", - "System.Configuration.ConfigurationManager": "9.0.11", - "System.IdentityModel.Tokens.Jwt": "7.7.1", - "System.Security.Cryptography.Pkcs": "9.0.11" + "resolved": "7.0.2", + "contentHash": "zwv76lANFQQI6Gmp6ntkzMWIWVqm8Wf4Mz00AeGCk1n8HCi5afi6bNynSe18uI0xeL0n6J+Myjk9AiIsL5oSqw==", + "dependencies": { + "Microsoft.Bcl.Cryptography": "9.0.13", + "Microsoft.Data.SqlClient.Extensions.Abstractions": "[7.0.2, 8.0.0)", + "Microsoft.Data.SqlClient.Internal.Logging": "[7.0.2, 8.0.0)", + "Microsoft.Data.SqlClient.SNI.runtime": "[6.0.2, 7.0.0)", + "Microsoft.Extensions.Caching.Memory": "9.0.13", + "Microsoft.IdentityModel.JsonWebTokens": "8.16.0", + "Microsoft.IdentityModel.Protocols.OpenIdConnect": "8.16.0", + "Microsoft.SqlServer.Server": "[1.0.0, 2.0.0)", + "System.Configuration.ConfigurationManager": "9.0.13", + "System.Security.Cryptography.Pkcs": "9.0.13" } }, "Microsoft.Data.SqlClient.SNI.runtime": { diff --git a/Applications/DatabaseMigrator/test/DatabaseMigrator.Tests/packages.lock.json b/Applications/DatabaseMigrator/test/DatabaseMigrator.Tests/packages.lock.json index e79e7d6cd6..efc571fe2c 100644 --- a/Applications/DatabaseMigrator/test/DatabaseMigrator.Tests/packages.lock.json +++ b/Applications/DatabaseMigrator/test/DatabaseMigrator.Tests/packages.lock.json @@ -38,6 +38,22 @@ "xunit.v3.core.mtp-v2": "[3.2.2]" } }, + "Asp.Versioning.Abstractions": { + "type": "Transitive", + "resolved": "10.1.0", + "contentHash": "RwdgC5O0baZ4pt30pAKKPQHq2CV4unBKA4HWoTeu7NY9ZwXM0dWYGf1Ipc5GK0eFBe9cMeqz4pGpPncMz4/ZNQ==", + "dependencies": { + "Microsoft.Extensions.Primitives": "10.0.0" + } + }, + "Asp.Versioning.Http": { + "type": "Transitive", + "resolved": "10.0.1", + "contentHash": "g0ayV/9ho3tGgooC6eF5p1063I1WzlxFJDYQrigcGnW+mLvui6eXrcW5hzTHhQREroUR3ZwXQrIN2SAIoi+KDw==", + "dependencies": { + "Asp.Versioning.Abstractions": "10.1.0" + } + }, "AWSSDK.Core": { "type": "Transitive", "resolved": "4.0.100.9", @@ -66,16 +82,6 @@ "System.Memory.Data": "1.0.2" } }, - "Azure.Identity": { - "type": "Transitive", - "resolved": "1.17.1", - "contentHash": "MSZkBrctcpiGxs9Cvr2VKKoN6qFLZlP3I6xuCWJ9iTgitI5Rgxtk5gfOSpXPZE3+CJmZ/mnqpQyGyjawFn5Vvg==", - "dependencies": { - "Azure.Core": "1.50.0", - "Microsoft.Identity.Client": "4.78.0", - "Microsoft.Identity.Client.Extensions.Msal": "4.78.0" - } - }, "Azure.Storage.Common": { "type": "Transitive", "resolved": "12.28.0", @@ -357,22 +363,34 @@ }, "Microsoft.Data.SqlClient": { "type": "Transitive", - "resolved": "6.1.4", - "contentHash": "lQcSog5LLImg4yNEuuG6ccvdzXnCvER8Rms9Ngk9zB4Q8na4f+S7/abSoC7gnEltBg4e5xTnLAWmMLIOtLg4pg==", + "resolved": "7.0.2", + "contentHash": "zwv76lANFQQI6Gmp6ntkzMWIWVqm8Wf4Mz00AeGCk1n8HCi5afi6bNynSe18uI0xeL0n6J+Myjk9AiIsL5oSqw==", "dependencies": { - "Azure.Core": "1.50.0", - "Azure.Identity": "1.17.1", - "Microsoft.Data.SqlClient.SNI.runtime": "6.0.2", - "Microsoft.Extensions.Caching.Memory": "9.0.11", - "Microsoft.Identity.Client": "4.80.0", - "Microsoft.IdentityModel.JsonWebTokens": "7.7.1", - "Microsoft.IdentityModel.Protocols.OpenIdConnect": "7.7.1", - "Microsoft.SqlServer.Server": "1.0.0", - "System.Configuration.ConfigurationManager": "9.0.11", - "System.IdentityModel.Tokens.Jwt": "7.7.1", - "System.Security.Cryptography.Pkcs": "9.0.11" + "Microsoft.Bcl.Cryptography": "9.0.13", + "Microsoft.Data.SqlClient.Extensions.Abstractions": "[7.0.2, 8.0.0)", + "Microsoft.Data.SqlClient.Internal.Logging": "[7.0.2, 8.0.0)", + "Microsoft.Data.SqlClient.SNI.runtime": "[6.0.2, 7.0.0)", + "Microsoft.Extensions.Caching.Memory": "9.0.13", + "Microsoft.IdentityModel.JsonWebTokens": "8.16.0", + "Microsoft.IdentityModel.Protocols.OpenIdConnect": "8.16.0", + "Microsoft.SqlServer.Server": "[1.0.0, 2.0.0)", + "System.Configuration.ConfigurationManager": "9.0.13", + "System.Security.Cryptography.Pkcs": "9.0.13" } }, + "Microsoft.Data.SqlClient.Extensions.Abstractions": { + "type": "Transitive", + "resolved": "7.0.2", + "contentHash": "Zx7z61fG2Nc6LdDn4jA7b5Aj1ABrljkOPRE31RvVUdjF6IgbG60leDUhMCafsnWFgaheiK3iqpLe+kbf5Z5L8Q==", + "dependencies": { + "Microsoft.Data.SqlClient.Internal.Logging": "[7.0.2, 8.0.0)" + } + }, + "Microsoft.Data.SqlClient.Internal.Logging": { + "type": "Transitive", + "resolved": "7.0.2", + "contentHash": "iqgYBbGSVy/DIYWjzmQOa964Kn4rs4wW5vg2IamqVK0fQqfTiILVR5hMK27XWqoyONtAZs+VxH354cPJBtSnbg==" + }, "Microsoft.Data.SqlClient.SNI.runtime": { "type": "Transitive", "resolved": "6.0.2", @@ -429,6 +447,11 @@ "Microsoft.Extensions.Options.ConfigurationExtensions": "10.0.10" } }, + "Microsoft.Extensions.ApiDescription.Server": { + "type": "Transitive", + "resolved": "10.0.0", + "contentHash": "NCWCGiwRwje8773yzPQhvucYnnfeR+ZoB1VRIrIMp4uaeUNw7jvEPHij3HIbwCDuNCrNcphA00KSAR9yD9qmbg==" + }, "Microsoft.Extensions.Caching.Abstractions": { "type": "Transitive", "resolved": "10.0.10", @@ -787,11 +810,11 @@ }, "Microsoft.IdentityModel.Protocols.OpenIdConnect": { "type": "Transitive", - "resolved": "7.7.1", - "contentHash": "yT2Hdj8LpPbcT9C9KlLVxXl09C8zjFaVSaApdOwuecMuoV4s6Sof/mnTDz/+F/lILPIBvrWugR9CC7iRVZgbfQ==", + "resolved": "8.16.0", + "contentHash": "h4yVXyJsEBBX5lg2G5ftMsi5JzcNEGAzrNphA6DQ6eOd8P0s+cDCOyPwVTYLePZvJL5unbPvYIvzrbTXzFjXnQ==", "dependencies": { - "Microsoft.IdentityModel.Protocols": "7.7.1", - "System.IdentityModel.Tokens.Jwt": "7.7.1" + "Microsoft.IdentityModel.Protocols": "8.16.0", + "System.IdentityModel.Tokens.Jwt": "8.16.0" } }, "Microsoft.IdentityModel.Tokens": { @@ -804,6 +827,11 @@ "Microsoft.IdentityModel.Logging": "8.19.2" } }, + "Microsoft.OpenApi": { + "type": "Transitive", + "resolved": "2.7.5", + "contentHash": "0FA67RSnRM4tcBKqiqVu/HPdZ9+QOKbmeRjxRUGTCjPU4C0bmUhd97Dso7Yild5P7nOV6GxJ2xrK0Kv/O9xp0w==" + }, "Microsoft.SqlServer.Server": { "type": "Transitive", "resolved": "1.0.0", @@ -1056,6 +1084,26 @@ "OpenIddict.Validation": "7.6.0" } }, + "OpenTelemetry": { + "type": "Transitive", + "resolved": "1.17.0", + "contentHash": "rMLOTftlMlTm7+MSrvXDHnJRjVkROFNKXHZrYjOsX+LankaFG7QSflx7qRRGjoqZoirohnxmJQ7GEb9occO4Gg==", + "dependencies": { + "Microsoft.Extensions.Configuration.EnvironmentVariables": "10.0.0", + "Microsoft.Extensions.Diagnostics.Abstractions": "10.0.0", + "Microsoft.Extensions.Logging.Configuration": "10.0.0", + "OpenTelemetry.Api.ProviderBuilderExtensions": "1.17.0" + } + }, + "OpenTelemetry.Api.ProviderBuilderExtensions": { + "type": "Transitive", + "resolved": "1.17.0", + "contentHash": "Xgc3Qf9B9TFMFpx6exTdGqMWuYIT2miNzkdMPutVvT9YuMFaEovXWke1Gb6z8NxYaQbbGF38vYLuSg1JCeui5Q==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0", + "OpenTelemetry.Api": "1.17.0" + } + }, "Polly.Core": { "type": "Transitive", "resolved": "8.7.0", @@ -1157,6 +1205,27 @@ "SQLitePCLRaw.core": "2.1.11" } }, + "Swashbuckle.AspNetCore.Swagger": { + "type": "Transitive", + "resolved": "10.2.3", + "contentHash": "1jUUs3WQnrS0FUtaZPLSy1yYMEwS1zlvDmvQ2/eldPHUANX0LJSLVZecCMgSMdeGiRqeaRrIXLtSz++TCiTMww==", + "dependencies": { + "Microsoft.OpenApi": "2.7.5" + } + }, + "Swashbuckle.AspNetCore.SwaggerGen": { + "type": "Transitive", + "resolved": "10.2.3", + "contentHash": "y7t4coDRAeFYChmvlMRiH2OjbiRrm9AVIDgt17fQfs3x9PVAI5PiwWYOhg+4F13R4Q36WDc9lqfoOnNa3tNbGg==", + "dependencies": { + "Swashbuckle.AspNetCore.Swagger": "10.2.3" + } + }, + "Swashbuckle.AspNetCore.SwaggerUI": { + "type": "Transitive", + "resolved": "10.2.3", + "contentHash": "nthWONRs/FJ4yyG206g1cC52WEG8EqrjuMWjGdR+5XG7lbjFto6NqcI9EMICgVFom/UivIjUVwI76ZHbHwTPfQ==" + }, "System.ClientModel": { "type": "Transitive", "resolved": "1.14.0", @@ -1175,11 +1244,11 @@ }, "System.Configuration.ConfigurationManager": { "type": "Transitive", - "resolved": "9.0.11", - "contentHash": "vPinosRgEk1CGjohbv0pDuz6gPprkWo5xvBTjOJjks5JOgOEWvPndq5NngGxiTcBcy1+k9GwzZ1c3Bp2fU5ezw==", + "resolved": "9.0.13", + "contentHash": "GbBrJq9S/gYpHzm7Pxx6Y5tDyfSfyxW6tlP5oiKJV38uf19Wp+GIIAnWfyL1zmNiz1+EjwVapw2WkBFvvqKQzg==", "dependencies": { - "System.Diagnostics.EventLog": "9.0.11", - "System.Security.Cryptography.ProtectedData": "9.0.11" + "System.Diagnostics.EventLog": "9.0.13", + "System.Security.Cryptography.ProtectedData": "9.0.13" } }, "System.Diagnostics.EventLog": { @@ -1189,11 +1258,11 @@ }, "System.IdentityModel.Tokens.Jwt": { "type": "Transitive", - "resolved": "7.7.1", - "contentHash": "rQkO1YbAjLwnDJSMpRhRtrc6XwIcEOcUvoEcge+evurpzSZM3UNK+MZfD3sKyTlYsvknZ6eJjSBfnmXqwOsT9Q==", + "resolved": "8.16.0", + "contentHash": "rrs2u7DRMXQG2yh0oVyF/vLwosfRv20Ld2iEpYcKwQWXHjfV+gFXNQsQ9p008kR9Ou4pxBs68Q6/9zC8Gi1wjg==", "dependencies": { - "Microsoft.IdentityModel.JsonWebTokens": "7.7.1", - "Microsoft.IdentityModel.Tokens": "7.7.1" + "Microsoft.IdentityModel.JsonWebTokens": "8.16.0", + "Microsoft.IdentityModel.Tokens": "8.16.0" } }, "System.IO.Hashing": { @@ -1226,8 +1295,8 @@ }, "System.Security.Cryptography.ProtectedData": { "type": "Transitive", - "resolved": "9.0.11", - "contentHash": "s8yUYuYYu+PAwvBdhLG1KyrGrk9gkYeuPxfAsXsTqqWyepwSyEw8hAaflW4nO98NG52YpYI1am2+9o+79h2RtQ==" + "resolved": "9.0.13", + "contentHash": "t8S9IDpjJKsLpLkeBdW8cWtcPyYqrGu93Dej1RO6WwuL/lkFSqWlan3rMJfortqz1mRIh+sys2AFsSA6jWJ3Jg==" }, "System.Security.Cryptography.Xml": { "type": "Transitive", @@ -1329,6 +1398,33 @@ "Backbone.AdminApi.Infrastructure": "[1.0.0, )" } }, + "Backbone.BuildingBlocks.API": { + "type": "Project", + "dependencies": { + "Asp.Versioning.Mvc": "[10.0.1, 10.0.1]", + "Asp.Versioning.Mvc.ApiExplorer": "[10.0.1, 10.0.1]", + "Backbone.BuildingBlocks.Application": "[1.0.0, )", + "Backbone.BuildingBlocks.Module": "[1.0.0, )", + "Backbone.Modules.Devices.Domain": "[1.0.0, )", + "Backbone.Modules.Devices.Infrastructure": "[1.0.0, )", + "Backbone.Tooling": "[1.0.0, )", + "DotNetDiag.HealthChecks.NpgSql": "[10.0.10, 10.0.10]", + "DotNetDiag.HealthChecks.SqlServer": "[10.0.10, 10.0.10]", + "Microsoft.EntityFrameworkCore": "[10.0.10, 10.0.10]", + "Microsoft.EntityFrameworkCore.Relational": "[10.0.10, 10.0.10]", + "OpenTelemetry.Exporter.OpenTelemetryProtocol": "[1.17.0, )", + "OpenTelemetry.Extensions.Hosting": "[1.17.0, 1.17.0]", + "OpenTelemetry.Instrumentation.AspNetCore": "[1.17.0, 1.17.0]", + "OpenTelemetry.Instrumentation.EntityFrameworkCore": "[1.17.0-beta.1, )", + "OpenTelemetry.Instrumentation.Http": "[1.17.0, 1.17.0]", + "OpenTelemetry.Instrumentation.Runtime": "[1.17.0, 1.17.0]", + "Polly": "[8.7.0, 8.7.0]", + "Serilog.Enrichers.Sensitive": "[2.1.0, 2.1.0]", + "Serilog.Extensions.Hosting": "[10.0.0, 10.0.0]", + "Swashbuckle.AspNetCore": "[10.2.3, 10.2.3]", + "System.Data.SqlClient": "[4.9.1, 4.9.1]" + } + }, "Backbone.BuildingBlocks.Application": { "type": "Project", "dependencies": { @@ -1380,11 +1476,21 @@ "Microsoft.Extensions.Identity.Core": "[10.0.10, 10.0.10]", "Microsoft.Extensions.Logging": "[10.0.10, 10.0.10]", "Npgsql.EntityFrameworkCore.PostgreSQL": "[10.0.3, 10.0.3]", + "OpenTelemetry.Api": "[1.17.0, )", "Polly": "[8.7.0, 8.7.0]", "RabbitMQ.Client": "[7.2.1, 7.2.1]", "Serilog": "[4.4.0, 4.4.0]" } }, + "Backbone.BuildingBlocks.Module": { + "type": "Project", + "dependencies": { + "Backbone.BuildingBlocks.Application.Abstractions": "[1.0.0, )", + "Microsoft.Extensions.Configuration.Abstractions": "[10.0.10, 10.0.10]", + "Microsoft.Extensions.DependencyInjection.Abstractions": "[10.0.10, 10.0.10]", + "ReHackt.Extensions.Options.Validation": "[10.0.1, 10.0.1]" + } + }, "Backbone.Common.Infrastructure": { "type": "Project", "dependencies": { @@ -1408,6 +1514,7 @@ "Autofac.Extensions.DependencyInjection": "[11.0.2, 11.0.2]", "Backbone.AdminApi.Infrastructure.Database.Postgres": "[1.0.0, )", "Backbone.AdminApi.Infrastructure.Database.SqlServer": "[1.0.0, )", + "Backbone.BuildingBlocks.API": "[1.0.0, )", "Backbone.Modules.Announcements.Infrastructure": "[1.0.0, )", "Backbone.Modules.Announcements.Infrastructure.Database.Postgres": "[1.0.0, )", "Backbone.Modules.Announcements.Infrastructure.Database.SqlServer": "[1.0.0, )", @@ -1872,6 +1979,24 @@ "Shouldly": "[4.3.0, 4.3.0]" } }, + "Asp.Versioning.Mvc": { + "type": "CentralTransitive", + "requested": "[10.0.1, 10.0.1]", + "resolved": "10.0.1", + "contentHash": "OqoFPKKxXkNmw62H3CgXkPrf1L4PPwwyYr9QMP6itt/khKTIayqaHhK6F2e3jt6KHc4s23cWAUbu+Z5GPEeMaw==", + "dependencies": { + "Asp.Versioning.Http": "10.0.1" + } + }, + "Asp.Versioning.Mvc.ApiExplorer": { + "type": "CentralTransitive", + "requested": "[10.0.1, 10.0.1]", + "resolved": "10.0.1", + "contentHash": "ylPZe+LheFp0pt2tSMq2pPeGAkMLqWVOn5+1/xOB/eUj889n9b35Sny08bSQ0ziAGIFjp3BBTXaYsWJjRoFV4A==", + "dependencies": { + "Asp.Versioning.Mvc": "10.0.1" + } + }, "Autofac": { "type": "CentralTransitive", "requested": "[9.3.2, 9.3.2]", @@ -1936,6 +2061,26 @@ "resolved": "2.1.79", "contentHash": "8YijbzgTfmqmQOnVNorYM6K++pxqnW3nJ4aC1sRHzxUA2CcuoJ9gsTem3kgBnPRMc38zZHl4Esb6hAezXIEEuw==" }, + "DotNetDiag.HealthChecks.NpgSql": { + "type": "CentralTransitive", + "requested": "[10.0.10, 10.0.10]", + "resolved": "10.0.10", + "contentHash": "lxb6wQ1YC/TpvZMVgbyeLP5dYOg/RJWLg1xlR+I0FeyfyMmukppKdwzBOrKRtZ8FHG3nV9xrVTaPdwRw0yL4Vw==", + "dependencies": { + "Microsoft.Extensions.Diagnostics.HealthChecks": "10.0.9", + "Npgsql": "10.0.3" + } + }, + "DotNetDiag.HealthChecks.SqlServer": { + "type": "CentralTransitive", + "requested": "[10.0.10, 10.0.10]", + "resolved": "10.0.10", + "contentHash": "6t2HP5VQR0GZDJiw8iZvzOTRC+84irUeaUuWvcqcnc4K5Mzrn/A9V0ucoyjySXOF1vGkdTHjlJMknJVYC9c2Hg==", + "dependencies": { + "Microsoft.Data.SqlClient": "7.0.2", + "Microsoft.Extensions.Diagnostics.HealthChecks": "10.0.9" + } + }, "EFCore.BulkExtensions.Core": { "type": "CentralTransitive", "requested": "[10.0.1, 10.0.1]", @@ -2373,6 +2518,71 @@ "OpenIddict.EntityFrameworkCore.Models": "7.6.0" } }, + "OpenTelemetry.Api": { + "type": "CentralTransitive", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" + }, + "OpenTelemetry.Exporter.OpenTelemetryProtocol": { + "type": "CentralTransitive", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "R1omQOrQpGlS0Cp5UIr/TAiuEA48JrPlgr1NPV5gESiTU7HhWU+ILe2EBSYb1fKdsSavZ7nZkHcUxAzofPqr2A==", + "dependencies": { + "OpenTelemetry": "1.17.0" + } + }, + "OpenTelemetry.Extensions.Hosting": { + "type": "CentralTransitive", + "requested": "[1.17.0, 1.17.0]", + "resolved": "1.17.0", + "contentHash": "t1OwL/4qgboGMobYVT+UV5zgWnFqCp4Pw8lcsmzh8m2K8PQsTKkyxrC32tqYTMYny3GOW4q5cltE3dTVzLmRew==", + "dependencies": { + "Microsoft.Extensions.Hosting.Abstractions": "10.0.0", + "OpenTelemetry": "1.17.0" + } + }, + "OpenTelemetry.Instrumentation.AspNetCore": { + "type": "CentralTransitive", + "requested": "[1.17.0, 1.17.0]", + "resolved": "1.17.0", + "contentHash": "rGbmk1vuy1kvgZmE0ps7Vb99YZvDap6AalrrF60FwnNit1uW/PbeFZj1cpb0T8MPkYmjhBrRJ1/JB6QqXkRjHA==", + "dependencies": { + "OpenTelemetry.Api.ProviderBuilderExtensions": "[1.17.0, 2.0.0)" + } + }, + "OpenTelemetry.Instrumentation.EntityFrameworkCore": { + "type": "CentralTransitive", + "requested": "[1.17.0-beta.1, )", + "resolved": "1.17.0-beta.1", + "contentHash": "BPSv1rk6qEkGZUGTNBfk7XmYqBAWdF3FBdjXEjVClp0bKUl6VCumlaosT84qvlK7YnHLCv5FFqJHx2N62TbKEw==", + "dependencies": { + "Microsoft.Extensions.Configuration": "10.0.0", + "Microsoft.Extensions.Options": "10.0.0", + "OpenTelemetry.Api.ProviderBuilderExtensions": "[1.17.0, 2.0.0)" + } + }, + "OpenTelemetry.Instrumentation.Http": { + "type": "CentralTransitive", + "requested": "[1.17.0, 1.17.0]", + "resolved": "1.17.0", + "contentHash": "uTwVtxIJ/xB96wGYTaDsbkJVeCFdUxTwvrlDUn2YJixy0UuKc8DvQMzwKNJMTzNFiiyYO9c40id6tUHTmWs33A==", + "dependencies": { + "Microsoft.Extensions.Configuration": "10.0.0", + "Microsoft.Extensions.Options": "10.0.0", + "OpenTelemetry.Api.ProviderBuilderExtensions": "[1.17.0, 2.0.0)" + } + }, + "OpenTelemetry.Instrumentation.Runtime": { + "type": "CentralTransitive", + "requested": "[1.17.0, 1.17.0]", + "resolved": "1.17.0", + "contentHash": "HyYenisDn/xdtyVXdjImsCl+RNC2gq01N0rvSR7tsYAylXR2sxX/YgMsyTajMXA27+r1vB7lNU8cWRhV0fwL+Q==", + "dependencies": { + "OpenTelemetry.Api": "[1.17.0, 2.0.0)" + } + }, "Polly": { "type": "CentralTransitive", "requested": "[8.7.0, 8.7.0]", @@ -2407,6 +2617,12 @@ "resolved": "4.4.0", "contentHash": "ZC6Le3rr4TVJJjS4KsQAesxeF1EhW9qcZmmG7eP5Y2G3+gTGkJEUXkq4+tZNPtyp05I0wWOxnIjwtxFweJsObw==" }, + "Serilog.Enrichers.Sensitive": { + "type": "CentralTransitive", + "requested": "[2.1.0, 2.1.0]", + "resolved": "2.1.0", + "contentHash": "nlaEYMoHjJqncjQgc0Nv4LOIkAwUt4Nvmx3EMNjY4MKC7QqZs9zB0v/NwFnaWzLF7qztc7mna1bjn20Auohu0g==" + }, "Serilog.Exceptions": { "type": "CentralTransitive", "requested": "[8.4.0, 8.4.0]", @@ -2521,6 +2737,18 @@ "Microsoft.Extensions.Logging.Abstractions": "8.0.3" } }, + "Swashbuckle.AspNetCore": { + "type": "CentralTransitive", + "requested": "[10.2.3, 10.2.3]", + "resolved": "10.2.3", + "contentHash": "8KNh1RWvofdU6DVLyBs4Z/OpUMnmf8oNvJQc0QxpwySRbi42bwLfdVMMrXZWANg5U5KQGQq1xW6r/hlcqw99tQ==", + "dependencies": { + "Microsoft.Extensions.ApiDescription.Server": "10.0.0", + "Swashbuckle.AspNetCore.Swagger": "10.2.3", + "Swashbuckle.AspNetCore.SwaggerGen": "10.2.3", + "Swashbuckle.AspNetCore.SwaggerUI": "10.2.3" + } + }, "System.Data.SqlClient": { "type": "CentralTransitive", "requested": "[4.9.1, 4.9.1]", @@ -2539,20 +2767,19 @@ }, "Microsoft.Data.SqlClient": { "type": "Transitive", - "resolved": "6.1.4", - "contentHash": "lQcSog5LLImg4yNEuuG6ccvdzXnCvER8Rms9Ngk9zB4Q8na4f+S7/abSoC7gnEltBg4e5xTnLAWmMLIOtLg4pg==", + "resolved": "7.0.2", + "contentHash": "zwv76lANFQQI6Gmp6ntkzMWIWVqm8Wf4Mz00AeGCk1n8HCi5afi6bNynSe18uI0xeL0n6J+Myjk9AiIsL5oSqw==", "dependencies": { - "Azure.Core": "1.50.0", - "Azure.Identity": "1.17.1", - "Microsoft.Data.SqlClient.SNI.runtime": "6.0.2", - "Microsoft.Extensions.Caching.Memory": "9.0.11", - "Microsoft.Identity.Client": "4.80.0", - "Microsoft.IdentityModel.JsonWebTokens": "7.7.1", - "Microsoft.IdentityModel.Protocols.OpenIdConnect": "7.7.1", - "Microsoft.SqlServer.Server": "1.0.0", - "System.Configuration.ConfigurationManager": "9.0.11", - "System.IdentityModel.Tokens.Jwt": "7.7.1", - "System.Security.Cryptography.Pkcs": "9.0.11" + "Microsoft.Bcl.Cryptography": "9.0.13", + "Microsoft.Data.SqlClient.Extensions.Abstractions": "[7.0.2, 8.0.0)", + "Microsoft.Data.SqlClient.Internal.Logging": "[7.0.2, 8.0.0)", + "Microsoft.Data.SqlClient.SNI.runtime": "[6.0.2, 7.0.0)", + "Microsoft.Extensions.Caching.Memory": "9.0.13", + "Microsoft.IdentityModel.JsonWebTokens": "8.16.0", + "Microsoft.IdentityModel.Protocols.OpenIdConnect": "8.16.0", + "Microsoft.SqlServer.Server": "[1.0.0, 2.0.0)", + "System.Configuration.ConfigurationManager": "9.0.13", + "System.Security.Cryptography.Pkcs": "9.0.13" } }, "Microsoft.Data.SqlClient.SNI.runtime": { @@ -2630,20 +2857,19 @@ }, "Microsoft.Data.SqlClient": { "type": "Transitive", - "resolved": "6.1.4", - "contentHash": "lQcSog5LLImg4yNEuuG6ccvdzXnCvER8Rms9Ngk9zB4Q8na4f+S7/abSoC7gnEltBg4e5xTnLAWmMLIOtLg4pg==", + "resolved": "7.0.2", + "contentHash": "zwv76lANFQQI6Gmp6ntkzMWIWVqm8Wf4Mz00AeGCk1n8HCi5afi6bNynSe18uI0xeL0n6J+Myjk9AiIsL5oSqw==", "dependencies": { - "Azure.Core": "1.50.0", - "Azure.Identity": "1.17.1", - "Microsoft.Data.SqlClient.SNI.runtime": "6.0.2", - "Microsoft.Extensions.Caching.Memory": "9.0.11", - "Microsoft.Identity.Client": "4.80.0", - "Microsoft.IdentityModel.JsonWebTokens": "7.7.1", - "Microsoft.IdentityModel.Protocols.OpenIdConnect": "7.7.1", - "Microsoft.SqlServer.Server": "1.0.0", - "System.Configuration.ConfigurationManager": "9.0.11", - "System.IdentityModel.Tokens.Jwt": "7.7.1", - "System.Security.Cryptography.Pkcs": "9.0.11" + "Microsoft.Bcl.Cryptography": "9.0.13", + "Microsoft.Data.SqlClient.Extensions.Abstractions": "[7.0.2, 8.0.0)", + "Microsoft.Data.SqlClient.Internal.Logging": "[7.0.2, 8.0.0)", + "Microsoft.Data.SqlClient.SNI.runtime": "[6.0.2, 7.0.0)", + "Microsoft.Extensions.Caching.Memory": "9.0.13", + "Microsoft.IdentityModel.JsonWebTokens": "8.16.0", + "Microsoft.IdentityModel.Protocols.OpenIdConnect": "8.16.0", + "Microsoft.SqlServer.Server": "[1.0.0, 2.0.0)", + "System.Configuration.ConfigurationManager": "9.0.13", + "System.Security.Cryptography.Pkcs": "9.0.13" } }, "Microsoft.Data.SqlClient.SNI.runtime": { @@ -2721,20 +2947,19 @@ }, "Microsoft.Data.SqlClient": { "type": "Transitive", - "resolved": "6.1.4", - "contentHash": "lQcSog5LLImg4yNEuuG6ccvdzXnCvER8Rms9Ngk9zB4Q8na4f+S7/abSoC7gnEltBg4e5xTnLAWmMLIOtLg4pg==", + "resolved": "7.0.2", + "contentHash": "zwv76lANFQQI6Gmp6ntkzMWIWVqm8Wf4Mz00AeGCk1n8HCi5afi6bNynSe18uI0xeL0n6J+Myjk9AiIsL5oSqw==", "dependencies": { - "Azure.Core": "1.50.0", - "Azure.Identity": "1.17.1", - "Microsoft.Data.SqlClient.SNI.runtime": "6.0.2", - "Microsoft.Extensions.Caching.Memory": "9.0.11", - "Microsoft.Identity.Client": "4.80.0", - "Microsoft.IdentityModel.JsonWebTokens": "7.7.1", - "Microsoft.IdentityModel.Protocols.OpenIdConnect": "7.7.1", - "Microsoft.SqlServer.Server": "1.0.0", - "System.Configuration.ConfigurationManager": "9.0.11", - "System.IdentityModel.Tokens.Jwt": "7.7.1", - "System.Security.Cryptography.Pkcs": "9.0.11" + "Microsoft.Bcl.Cryptography": "9.0.13", + "Microsoft.Data.SqlClient.Extensions.Abstractions": "[7.0.2, 8.0.0)", + "Microsoft.Data.SqlClient.Internal.Logging": "[7.0.2, 8.0.0)", + "Microsoft.Data.SqlClient.SNI.runtime": "[6.0.2, 7.0.0)", + "Microsoft.Extensions.Caching.Memory": "9.0.13", + "Microsoft.IdentityModel.JsonWebTokens": "8.16.0", + "Microsoft.IdentityModel.Protocols.OpenIdConnect": "8.16.0", + "Microsoft.SqlServer.Server": "[1.0.0, 2.0.0)", + "System.Configuration.ConfigurationManager": "9.0.13", + "System.Security.Cryptography.Pkcs": "9.0.13" } }, "Microsoft.Data.SqlClient.SNI.runtime": { @@ -2812,20 +3037,19 @@ }, "Microsoft.Data.SqlClient": { "type": "Transitive", - "resolved": "6.1.4", - "contentHash": "lQcSog5LLImg4yNEuuG6ccvdzXnCvER8Rms9Ngk9zB4Q8na4f+S7/abSoC7gnEltBg4e5xTnLAWmMLIOtLg4pg==", - "dependencies": { - "Azure.Core": "1.50.0", - "Azure.Identity": "1.17.1", - "Microsoft.Data.SqlClient.SNI.runtime": "6.0.2", - "Microsoft.Extensions.Caching.Memory": "9.0.11", - "Microsoft.Identity.Client": "4.80.0", - "Microsoft.IdentityModel.JsonWebTokens": "7.7.1", - "Microsoft.IdentityModel.Protocols.OpenIdConnect": "7.7.1", - "Microsoft.SqlServer.Server": "1.0.0", - "System.Configuration.ConfigurationManager": "9.0.11", - "System.IdentityModel.Tokens.Jwt": "7.7.1", - "System.Security.Cryptography.Pkcs": "9.0.11" + "resolved": "7.0.2", + "contentHash": "zwv76lANFQQI6Gmp6ntkzMWIWVqm8Wf4Mz00AeGCk1n8HCi5afi6bNynSe18uI0xeL0n6J+Myjk9AiIsL5oSqw==", + "dependencies": { + "Microsoft.Bcl.Cryptography": "9.0.13", + "Microsoft.Data.SqlClient.Extensions.Abstractions": "[7.0.2, 8.0.0)", + "Microsoft.Data.SqlClient.Internal.Logging": "[7.0.2, 8.0.0)", + "Microsoft.Data.SqlClient.SNI.runtime": "[6.0.2, 7.0.0)", + "Microsoft.Extensions.Caching.Memory": "9.0.13", + "Microsoft.IdentityModel.JsonWebTokens": "8.16.0", + "Microsoft.IdentityModel.Protocols.OpenIdConnect": "8.16.0", + "Microsoft.SqlServer.Server": "[1.0.0, 2.0.0)", + "System.Configuration.ConfigurationManager": "9.0.13", + "System.Security.Cryptography.Pkcs": "9.0.13" } }, "Microsoft.Data.SqlClient.SNI.runtime": { diff --git a/Applications/EventHandlerService/src/EventHandlerService/EventHandlerService.csproj b/Applications/EventHandlerService/src/EventHandlerService/EventHandlerService.csproj index acffc08337..a145b29401 100644 --- a/Applications/EventHandlerService/src/EventHandlerService/EventHandlerService.csproj +++ b/Applications/EventHandlerService/src/EventHandlerService/EventHandlerService.csproj @@ -8,7 +8,6 @@ - diff --git a/Applications/EventHandlerService/src/EventHandlerService/EventHandlerServiceConfiguration.cs b/Applications/EventHandlerService/src/EventHandlerService/EventHandlerServiceConfiguration.cs index 7b90a16287..359e861192 100644 --- a/Applications/EventHandlerService/src/EventHandlerService/EventHandlerServiceConfiguration.cs +++ b/Applications/EventHandlerService/src/EventHandlerService/EventHandlerServiceConfiguration.cs @@ -1,14 +1,23 @@ using System.ComponentModel.DataAnnotations; +using Backbone.BuildingBlocks.API.Extensions; using Backbone.BuildingBlocks.Infrastructure.EventBus; namespace Backbone.EventHandlerService; public class EventHandlerServiceConfiguration { + [Required] + public required TelemetryConfiguration Telemetry { get; init; } + [Required] public required InfrastructureConfiguration Infrastructure { get; init; } } +public class TelemetryConfiguration +{ + public required OpenTelemetryCollectorConfiguration OpenTelemetryCollector { get; set; } = new(); +} + public class InfrastructureConfiguration { [Required] diff --git a/Applications/EventHandlerService/src/EventHandlerService/Program.cs b/Applications/EventHandlerService/src/EventHandlerService/Program.cs index 41ec4b93e7..e7a46128bf 100644 --- a/Applications/EventHandlerService/src/EventHandlerService/Program.cs +++ b/Applications/EventHandlerService/src/EventHandlerService/Program.cs @@ -1,4 +1,5 @@ -using Autofac.Extensions.DependencyInjection; +using System.Reflection; +using Autofac.Extensions.DependencyInjection; using Backbone.BuildingBlocks.API.Extensions; using Backbone.BuildingBlocks.API.Serilog; using Backbone.BuildingBlocks.Infrastructure.EventBus; @@ -13,7 +14,6 @@ using Backbone.Modules.Tokens.Application; using Backbone.Modules.Tokens.Module; using Microsoft.Extensions.Options; -using OpenTelemetry.Metrics; using Serilog; using Serilog.Enrichers.Sensitive; using Serilog.Exceptions; @@ -21,7 +21,6 @@ using Serilog.Exceptions.EntityFrameworkCore.Destructurers; using Serilog.Settings.Configuration; using InfrastructureConfiguration = Backbone.Modules.Quotas.Infrastructure.InfrastructureConfiguration; -using OpenTelemetrySdk = OpenTelemetry.Sdk; Log.Logger = new LoggerConfiguration() .WriteTo.Console() @@ -36,20 +35,8 @@ Log.Information("App created."); Log.Information("Starting app..."); - var meterProvider = OpenTelemetrySdk.CreateMeterProviderBuilder() - .AddMeter(METER_NAME) - .AddMeter("Microsoft.EntityFrameworkCore") - .AddPrometheusHttpListener(options => - { - var host = Environment.GetEnvironmentVariable("METRICS_HOST") ?? "localhost"; - options.UriPrefixes = [$"http://{host}:9444/"]; - }) - .Build(); - await app.Build().RunAsync(); - meterProvider.Dispose(); - return 0; } catch (Exception ex) @@ -69,7 +56,6 @@ static IHostBuilder CreateHostBuilder(string[] args) .ConfigureAppConfiguration((hostContext, configuration) => { configuration.Sources.Clear(); - var env = hostContext.HostingEnvironment; configuration .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) @@ -88,6 +74,8 @@ static IHostBuilder CreateHostBuilder(string[] args) services.BuildServiceProvider().GetRequiredService>().Value; #pragma warning restore ASP0000 + services.AddOpenTelemetry(METER_NAME, Assembly.GetExecutingAssembly().GetName().Version?.ToString() ?? "unknown", parsedConfiguration.Telemetry.OpenTelemetryCollector); + services.AddTransient(); services @@ -108,13 +96,13 @@ static IHostBuilder CreateHostBuilder(string[] args) }) .UseServiceProviderFactory(new AutofacServiceProviderFactory()) .UseSerilog((context, configuration) => configuration - .ReadFrom.Configuration(context.Configuration, new ConfigurationReaderOptions { SectionName = "Logging" }) + .ReadFrom.Configuration(context.Configuration, new ConfigurationReaderOptions { SectionName = "Telemetry:Logging" }) .Enrich.FromLogContext() - .Enrich.WithProperty("service", "eventHandlerService") .Enrich.WithExceptionDetails(new DestructuringOptionsBuilder() .WithDefaultDestructurers() .WithDestructurers([new DbUpdateExceptionDestructurer()])) - .Enrich.WithSensitiveDataMasking(options => options.AddSensitiveDataMasks()), preserveStaticLogger: true + .Enrich.WithSensitiveDataMasking(options => options.AddSensitiveDataMasks()), + writeToProviders: true ); } diff --git a/Applications/EventHandlerService/src/EventHandlerService/appsettings.json b/Applications/EventHandlerService/src/EventHandlerService/appsettings.json index 4ba48a4ddd..1d59d85bf3 100644 --- a/Applications/EventHandlerService/src/EventHandlerService/appsettings.json +++ b/Applications/EventHandlerService/src/EventHandlerService/appsettings.json @@ -29,19 +29,21 @@ } } }, - "Logging": { - "MinimumLevel": { - "Default": "Warning", - "Override": { - "Backbone": "Information", - "Azure.Messaging.ServiceBus": "Error" - } - }, - "WriteTo": { - "Console": { - "Name": "Console", - "Args": { - "formatter": "Serilog.Formatting.Compact.CompactJsonFormatter, Serilog.Formatting.Compact" + "Telemetry": { + "Logging": { + "MinimumLevel": { + "Default": "Warning", + "Override": { + "Backbone": "Information", + "Azure.Messaging.ServiceBus": "Error" + } + }, + "WriteTo": { + "Console": { + "Name": "Console", + "Args": { + "formatter": "Serilog.Formatting.Compact.CompactJsonFormatter, Serilog.Formatting.Compact" + } } } } diff --git a/Applications/EventHandlerService/src/EventHandlerService/packages.lock.json b/Applications/EventHandlerService/src/EventHandlerService/packages.lock.json index 2e7fa7fc59..be6f317816 100644 --- a/Applications/EventHandlerService/src/EventHandlerService/packages.lock.json +++ b/Applications/EventHandlerService/src/EventHandlerService/packages.lock.json @@ -12,15 +12,6 @@ "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.9" } }, - "OpenTelemetry.Exporter.Prometheus.HttpListener": { - "type": "Direct", - "requested": "[1.11.2-beta.1, 1.11.2-beta.1]", - "resolved": "1.11.2-beta.1", - "contentHash": "Ppwr0l7X4AbZ2+b1XaZzl+I1196MtA+kelsdHF7QutoOtgdY7Mx0RAFMV7dKYCIRsOumfYaOb8U/Hkkft5HLrQ==", - "dependencies": { - "OpenTelemetry": "[1.11.2, 2.0.0)" - } - }, "Serilog.Enrichers.Sensitive": { "type": "Direct", "requested": "[2.1.0, 2.1.0]", @@ -996,11 +987,6 @@ "OpenTelemetry.Api.ProviderBuilderExtensions": "1.17.0" } }, - "OpenTelemetry.Api": { - "type": "Transitive", - "resolved": "1.17.0", - "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" - }, "OpenTelemetry.Api.ProviderBuilderExtensions": { "type": "Transitive", "resolved": "1.17.0", @@ -1209,9 +1195,10 @@ "DotNetDiag.HealthChecks.SqlServer": "[10.0.10, 10.0.10]", "Microsoft.EntityFrameworkCore": "[10.0.10, 10.0.10]", "Microsoft.EntityFrameworkCore.Relational": "[10.0.10, 10.0.10]", - "OpenTelemetry.Exporter.Prometheus.AspNetCore": "[1.11.2-beta.1, 1.11.2-beta.1]", + "OpenTelemetry.Exporter.OpenTelemetryProtocol": "[1.17.0, )", "OpenTelemetry.Extensions.Hosting": "[1.17.0, 1.17.0]", "OpenTelemetry.Instrumentation.AspNetCore": "[1.17.0, 1.17.0]", + "OpenTelemetry.Instrumentation.EntityFrameworkCore": "[1.17.0-beta.1, )", "OpenTelemetry.Instrumentation.Http": "[1.17.0, 1.17.0]", "OpenTelemetry.Instrumentation.Runtime": "[1.17.0, 1.17.0]", "Polly": "[8.7.0, 8.7.0]", @@ -1272,6 +1259,7 @@ "Microsoft.Extensions.Identity.Core": "[10.0.10, 10.0.10]", "Microsoft.Extensions.Logging": "[10.0.10, 10.0.10]", "Npgsql.EntityFrameworkCore.PostgreSQL": "[10.0.3, 10.0.3]", + "OpenTelemetry.Api": "[1.17.0, )", "Polly": "[8.7.0, 8.7.0]", "RabbitMQ.Client": "[7.2.1, 7.2.1]", "Serilog": "[4.4.0, 4.4.0]" @@ -2280,13 +2268,19 @@ "OpenIddict.EntityFrameworkCore.Models": "7.6.0" } }, - "OpenTelemetry.Exporter.Prometheus.AspNetCore": { + "OpenTelemetry.Api": { "type": "CentralTransitive", - "requested": "[1.11.2-beta.1, 1.11.2-beta.1]", - "resolved": "1.11.2-beta.1", - "contentHash": "jouLU4VHpzyXuzF2yi/bpt9DoseZGyUudSdTFvylgIwIx6ST1bdI/AXNoJ4/n6HwMiso677ILLm/RM8DY+EYwA==", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" + }, + "OpenTelemetry.Exporter.OpenTelemetryProtocol": { + "type": "CentralTransitive", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "R1omQOrQpGlS0Cp5UIr/TAiuEA48JrPlgr1NPV5gESiTU7HhWU+ILe2EBSYb1fKdsSavZ7nZkHcUxAzofPqr2A==", "dependencies": { - "OpenTelemetry": "[1.11.2, 2.0.0)" + "OpenTelemetry": "1.17.0" } }, "OpenTelemetry.Extensions.Hosting": { @@ -2308,6 +2302,17 @@ "OpenTelemetry.Api.ProviderBuilderExtensions": "[1.17.0, 2.0.0)" } }, + "OpenTelemetry.Instrumentation.EntityFrameworkCore": { + "type": "CentralTransitive", + "requested": "[1.17.0-beta.1, )", + "resolved": "1.17.0-beta.1", + "contentHash": "BPSv1rk6qEkGZUGTNBfk7XmYqBAWdF3FBdjXEjVClp0bKUl6VCumlaosT84qvlK7YnHLCv5FFqJHx2N62TbKEw==", + "dependencies": { + "Microsoft.Extensions.Configuration": "10.0.0", + "Microsoft.Extensions.Options": "10.0.0", + "OpenTelemetry.Api.ProviderBuilderExtensions": "[1.17.0, 2.0.0)" + } + }, "OpenTelemetry.Instrumentation.Http": { "type": "CentralTransitive", "requested": "[1.17.0, 1.17.0]", diff --git a/Applications/EventHandlerService/test/EventHandlerService.Tests/packages.lock.json b/Applications/EventHandlerService/test/EventHandlerService.Tests/packages.lock.json index 053004b83e..ca0649b169 100644 --- a/Applications/EventHandlerService/test/EventHandlerService.Tests/packages.lock.json +++ b/Applications/EventHandlerService/test/EventHandlerService.Tests/packages.lock.json @@ -1034,11 +1034,6 @@ "OpenTelemetry.Api.ProviderBuilderExtensions": "1.17.0" } }, - "OpenTelemetry.Api": { - "type": "Transitive", - "resolved": "1.17.0", - "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" - }, "OpenTelemetry.Api.ProviderBuilderExtensions": { "type": "Transitive", "resolved": "1.17.0", @@ -1321,9 +1316,10 @@ "DotNetDiag.HealthChecks.SqlServer": "[10.0.10, 10.0.10]", "Microsoft.EntityFrameworkCore": "[10.0.10, 10.0.10]", "Microsoft.EntityFrameworkCore.Relational": "[10.0.10, 10.0.10]", - "OpenTelemetry.Exporter.Prometheus.AspNetCore": "[1.11.2-beta.1, 1.11.2-beta.1]", + "OpenTelemetry.Exporter.OpenTelemetryProtocol": "[1.17.0, )", "OpenTelemetry.Extensions.Hosting": "[1.17.0, 1.17.0]", "OpenTelemetry.Instrumentation.AspNetCore": "[1.17.0, 1.17.0]", + "OpenTelemetry.Instrumentation.EntityFrameworkCore": "[1.17.0-beta.1, )", "OpenTelemetry.Instrumentation.Http": "[1.17.0, 1.17.0]", "OpenTelemetry.Instrumentation.Runtime": "[1.17.0, 1.17.0]", "Polly": "[8.7.0, 8.7.0]", @@ -1384,6 +1380,7 @@ "Microsoft.Extensions.Identity.Core": "[10.0.10, 10.0.10]", "Microsoft.Extensions.Logging": "[10.0.10, 10.0.10]", "Npgsql.EntityFrameworkCore.PostgreSQL": "[10.0.3, 10.0.3]", + "OpenTelemetry.Api": "[1.17.0, )", "Polly": "[8.7.0, 8.7.0]", "RabbitMQ.Client": "[7.2.1, 7.2.1]", "Serilog": "[4.4.0, 4.4.0]" @@ -1435,7 +1432,6 @@ "Backbone.Modules.Relationships.Module": "[1.0.0, )", "Backbone.Modules.Synchronization.Module": "[1.0.0, )", "Backbone.Modules.Tokens.Module": "[1.0.0, )", - "OpenTelemetry.Exporter.Prometheus.HttpListener": "[1.11.2-beta.1, 1.11.2-beta.1]", "Serilog.Enrichers.Sensitive": "[2.1.0, 2.1.0]", "Serilog.Exceptions": "[8.4.0, 8.4.0]", "Serilog.Exceptions.EntityFrameworkCore": "[8.4.0, 8.4.0]", @@ -2454,22 +2450,19 @@ "OpenIddict.EntityFrameworkCore.Models": "7.6.0" } }, - "OpenTelemetry.Exporter.Prometheus.AspNetCore": { + "OpenTelemetry.Api": { "type": "CentralTransitive", - "requested": "[1.11.2-beta.1, 1.11.2-beta.1]", - "resolved": "1.11.2-beta.1", - "contentHash": "jouLU4VHpzyXuzF2yi/bpt9DoseZGyUudSdTFvylgIwIx6ST1bdI/AXNoJ4/n6HwMiso677ILLm/RM8DY+EYwA==", - "dependencies": { - "OpenTelemetry": "[1.11.2, 2.0.0)" - } + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" }, - "OpenTelemetry.Exporter.Prometheus.HttpListener": { + "OpenTelemetry.Exporter.OpenTelemetryProtocol": { "type": "CentralTransitive", - "requested": "[1.11.2-beta.1, 1.11.2-beta.1]", - "resolved": "1.11.2-beta.1", - "contentHash": "Ppwr0l7X4AbZ2+b1XaZzl+I1196MtA+kelsdHF7QutoOtgdY7Mx0RAFMV7dKYCIRsOumfYaOb8U/Hkkft5HLrQ==", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "R1omQOrQpGlS0Cp5UIr/TAiuEA48JrPlgr1NPV5gESiTU7HhWU+ILe2EBSYb1fKdsSavZ7nZkHcUxAzofPqr2A==", "dependencies": { - "OpenTelemetry": "[1.11.2, 2.0.0)" + "OpenTelemetry": "1.17.0" } }, "OpenTelemetry.Extensions.Hosting": { @@ -2491,6 +2484,17 @@ "OpenTelemetry.Api.ProviderBuilderExtensions": "[1.17.0, 2.0.0)" } }, + "OpenTelemetry.Instrumentation.EntityFrameworkCore": { + "type": "CentralTransitive", + "requested": "[1.17.0-beta.1, )", + "resolved": "1.17.0-beta.1", + "contentHash": "BPSv1rk6qEkGZUGTNBfk7XmYqBAWdF3FBdjXEjVClp0bKUl6VCumlaosT84qvlK7YnHLCv5FFqJHx2N62TbKEw==", + "dependencies": { + "Microsoft.Extensions.Configuration": "10.0.0", + "Microsoft.Extensions.Options": "10.0.0", + "OpenTelemetry.Api.ProviderBuilderExtensions": "[1.17.0, 2.0.0)" + } + }, "OpenTelemetry.Instrumentation.Http": { "type": "CentralTransitive", "requested": "[1.17.0, 1.17.0]", diff --git a/Applications/Housekeeper/src/Housekeeper/Configuration.cs b/Applications/Housekeeper/src/Housekeeper/Configuration.cs index de8e2704f6..4d6ddc9167 100644 --- a/Applications/Housekeeper/src/Housekeeper/Configuration.cs +++ b/Applications/Housekeeper/src/Housekeeper/Configuration.cs @@ -1,13 +1,22 @@ using System.ComponentModel.DataAnnotations; +using Backbone.BuildingBlocks.API.Extensions; using Backbone.BuildingBlocks.Infrastructure.EventBus; namespace Backbone.Housekeeper; public class Configuration { + [Required] + public required TelemetryConfiguration Telemetry { get; init; } + [Required] public required InfrastructureConfiguration Infrastructure { get; init; } + public class TelemetryConfiguration + { + public required OpenTelemetryCollectorConfiguration OpenTelemetryCollector { get; set; } = new(); + } + public class InfrastructureConfiguration { [Required] diff --git a/Applications/Housekeeper/src/Housekeeper/Executor.cs b/Applications/Housekeeper/src/Housekeeper/Executor.cs index a1e2b3d4d1..0fdfd7d6b2 100644 --- a/Applications/Housekeeper/src/Housekeeper/Executor.cs +++ b/Applications/Housekeeper/src/Housekeeper/Executor.cs @@ -1,4 +1,5 @@ using System.Diagnostics; +using Backbone.BuildingBlocks.Application.Housekeeping; using MediatR; using ExecuteAnnouncementsModuleHousekeepingCommand = Backbone.Modules.Announcements.Application.Announcements.Commands.ExecuteHousekeeping.ExecuteHousekeepingCommand; using ExecuteChallengesModuleHousekeepingCommand = Backbone.Modules.Challenges.Application.Challenges.Commands.ExecuteHousekeeping.ExecuteHousekeepingCommand; @@ -13,46 +14,45 @@ namespace Backbone.Housekeeper; public class Executor { private readonly IMediator _mediator; - private readonly ILogger _logger; - public Executor(IMediator mediator, ILogger logger) + public Executor(IMediator mediator) { _mediator = mediator; - _logger = logger; } public async Task Execute(CancellationToken cancellationToken) { - _logger.StartingDeletion(); - var stopwatch = Stopwatch.StartNew(); + using var activity = StartHousekeeperActivity(); + + try + { + await HousekeepingTelemetry.TrackModuleDeletion("Announcements", ct => _mediator.Send(new ExecuteAnnouncementsModuleHousekeepingCommand(), ct), cancellationToken); + await HousekeepingTelemetry.TrackModuleDeletion("Challenges", ct => _mediator.Send(new ExecuteChallengesModuleHousekeepingCommand(), ct), cancellationToken); + await HousekeepingTelemetry.TrackModuleDeletion("Devices", ct => _mediator.Send(new ExecuteDevicesModuleHousekeepingCommand(), ct), cancellationToken); + await HousekeepingTelemetry.TrackModuleDeletion("Files", ct => _mediator.Send(new ExecuteFilesModuleHousekeepingCommand(), ct), cancellationToken); + await HousekeepingTelemetry.TrackModuleDeletion("Relationships", ct => _mediator.Send(new ExecuteRelationshipsModuleHousekeepingCommand(), ct), cancellationToken); + await HousekeepingTelemetry.TrackModuleDeletion("Synchronization", ct => _mediator.Send(new ExecuteSynchronizationModuleHousekeepingCommand(), ct), cancellationToken); + await HousekeepingTelemetry.TrackModuleDeletion("Tokens", ct => _mediator.Send(new ExecuteTokensModuleHousekeepingCommand(), ct), cancellationToken); + } + catch (Exception ex) + { + activity?.AddException(ex); + activity?.SetStatus(ActivityStatusCode.Error, ex.Message); + throw; + } + } - await _mediator.Send(new ExecuteAnnouncementsModuleHousekeepingCommand(), cancellationToken); - await _mediator.Send(new ExecuteChallengesModuleHousekeepingCommand(), cancellationToken); - await _mediator.Send(new ExecuteDevicesModuleHousekeepingCommand(), cancellationToken); - await _mediator.Send(new ExecuteFilesModuleHousekeepingCommand(), cancellationToken); - await _mediator.Send(new ExecuteRelationshipsModuleHousekeepingCommand(), cancellationToken); - await _mediator.Send(new ExecuteSynchronizationModuleHousekeepingCommand(), cancellationToken); - await _mediator.Send(new ExecuteTokensModuleHousekeepingCommand(), cancellationToken); + private static Activity? StartHousekeeperActivity() + { + // ReSharper disable once ExplicitCallerInfoArgument + var activity = HousekeepingTelemetry.ACTIVITY_SOURCE.StartActivity("housekeeper_run"); - stopwatch.Stop(); + if (activity == null) + return null; - _logger.DeletionCompleted(stopwatch.ElapsedMilliseconds); - } -} + activity.SetTag("housekeeping.trace_id", activity.TraceId.ToString()); + activity.SetTag("housekeeper.operation", "job_run"); -internal static partial class ExecutorLogs -{ - [LoggerMessage( - EventId = 468524, - EventName = "Housekeeper.Executor.StartingDeletion", - Level = LogLevel.Information, - Message = "Starting deletion...")] - public static partial void StartingDeletion(this ILogger logger); - - [LoggerMessage( - EventId = 945132, - EventName = "Housekeeper.Executor.DeletionCompleted", - Level = LogLevel.Information, - Message = "Deletion completed after {elapsedMilliseconds}ms.")] - public static partial void DeletionCompleted(this ILogger logger, long elapsedMilliseconds); + return activity; + } } diff --git a/Applications/Housekeeper/src/Housekeeper/Program.cs b/Applications/Housekeeper/src/Housekeeper/Program.cs index d2e0bd7777..ee994afbdd 100644 --- a/Applications/Housekeeper/src/Housekeeper/Program.cs +++ b/Applications/Housekeeper/src/Housekeeper/Program.cs @@ -1,5 +1,7 @@ -using Autofac.Extensions.DependencyInjection; +using System.Reflection; +using Autofac.Extensions.DependencyInjection; using Backbone.BuildingBlocks.API.Extensions; +using Backbone.BuildingBlocks.Application.Housekeeping; using Backbone.BuildingBlocks.Application.QuotaCheck; using Backbone.BuildingBlocks.Infrastructure.EventBus; using Backbone.Housekeeper; @@ -23,68 +25,86 @@ .WriteTo.Console() .CreateBootstrapLogger(); -var app = CreateHostBuilder(args).Build(); +using var host = CreateHostBuilder(args).Build(); -await app.Services.GetRequiredService().Execute(CancellationToken.None); -return; +try +{ + await host.StartAsync(); + + await host.Services.GetRequiredService().Execute(CancellationToken.None); + + return 0; +} +catch (Exception ex) +{ + Log.Fatal(ex, "There was an error while executing the housekeeper."); + return 1; +} +finally +{ + await host.StopAsync(); +} -static IHostBuilder CreateHostBuilder(string[] args) +static HostApplicationBuilder CreateHostBuilder(string[] args) { - return Host.CreateDefaultBuilder(args) - .ConfigureAppConfiguration((hostContext, configuration) => - { - configuration.Sources.Clear(); - var env = hostContext.HostingEnvironment; - - configuration - .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) - .AddJsonFile("appsettings.override.json", optional: true, reloadOnChange: false); - - configuration.AddEnvironmentVariables(); - configuration.AddCommandLine(args); - }) - .ConfigureServices((hostContext, services) => - { - var configuration = hostContext.Configuration; - - services.ConfigureAndValidate(configuration.Bind); - - services.AddLogging(); - - services - .AddModule(configuration) - .AddModule(configuration) - .AddModule(configuration) - .AddModule(configuration) - .AddModule(configuration) - .AddModule(configuration) - .AddModule(configuration); - - var parsedConfiguration = services.BuildServiceProvider().GetRequiredService>().Value; - - services.AddCustomOpenIddict(); - - services.AddCustomIdentity(hostContext.HostingEnvironment); - - services.AddSingleton(); - - services.AddTransient(); - - services.AddEventBus(parsedConfiguration.Infrastructure.EventBus, METER_NAME); - }) - .UseServiceProviderFactory(new AutofacServiceProviderFactory()) - .UseSerilog((context, configuration) => configuration - .ReadFrom.Configuration(context.Configuration, new ConfigurationReaderOptions { SectionName = "Logging" }) - .Enrich.FromLogContext() - .Enrich.WithProperty("service", "housekeeper") - .Enrich.WithExceptionDetails(new DestructuringOptionsBuilder() - .WithDefaultDestructurers() - .WithDestructurers([new DbUpdateExceptionDestructurer()]) - ), preserveStaticLogger: true - ); + var builder = Host.CreateApplicationBuilder(args); + builder.ConfigureContainer(new AutofacServiceProviderFactory()); + + var configuration = builder.Configuration; + var services = builder.Services; + + // Configure Configuration + builder.Configuration.Sources.Clear(); + builder.Configuration + .AddJsonFile("appsettings.json", optional: true) + .AddJsonFile("appsettings.override.json", optional: true); + builder.Configuration.AddEnvironmentVariables(); + builder.Configuration.AddCommandLine(args); + + // Configure Services + services.Configure(options => { options.SuppressStatusMessages = true; }); + + services.ConfigureAndValidate(configuration.Bind); + + services.AddLogging(); + + services + .AddModule(configuration) + .AddModule(configuration) + .AddModule(configuration) + .AddModule(configuration) + .AddModule(configuration) + .AddModule(configuration) + .AddModule(configuration); + + var parsedConfiguration = services.BuildServiceProvider().GetRequiredService>().Value; + + services.AddCustomOpenIddict(); + + services.AddCustomIdentity(builder.Environment); + + services.AddSingleton(); + + services.AddTransient(); + + services.AddOpenTelemetry(METER_NAME, Assembly.GetExecutingAssembly().GetName().Version?.ToString() ?? "unknown", parsedConfiguration.Telemetry.OpenTelemetryCollector, + HousekeepingTelemetry.ACTIVITY_SOURCE_NAME); + + services.AddEventBus(parsedConfiguration.Infrastructure.EventBus, METER_NAME); + + services.AddSerilog(configuration => configuration + .ReadFrom.Configuration(builder.Configuration, new ConfigurationReaderOptions { SectionName = "Telemetry:Logging" }) + .Enrich.FromLogContext() + .Enrich.WithExceptionDetails(new DestructuringOptionsBuilder() + .WithDefaultDestructurers() + .WithDestructurers([new DbUpdateExceptionDestructurer()]) + ), preserveStaticLogger: true + ); + + return builder; } public partial class Program diff --git a/Applications/Housekeeper/src/Housekeeper/appsettings.json b/Applications/Housekeeper/src/Housekeeper/appsettings.json index ea3baf0d94..063d1d17d5 100644 --- a/Applications/Housekeeper/src/Housekeeper/appsettings.json +++ b/Applications/Housekeeper/src/Housekeeper/appsettings.json @@ -25,22 +25,23 @@ } } }, - "Logging": { - "MinimumLevel": { - "Default": "Warning", - "Override": { - "Backbone": "Information", - "Azure.Messaging.ServiceBus": "Error" - } - }, - "WriteTo": { - "Console": { - "Name": "Console", - "Args": { - "formatter": "Serilog.Formatting.Compact.CompactJsonFormatter, Serilog.Formatting.Compact" + "Telemetry": { + "Logging": { + "MinimumLevel": { + "Default": "Warning", + "Override": { + "Backbone": "Information", + "Azure.Messaging.ServiceBus": "Error" + } + }, + "WriteTo": { + "Console": { + "Name": "Console", + "Args": { + "formatter": "Serilog.Formatting.Compact.CompactJsonFormatter, Serilog.Formatting.Compact" + } } } } } } - diff --git a/Applications/Housekeeper/src/Housekeeper/packages.lock.json b/Applications/Housekeeper/src/Housekeeper/packages.lock.json index f9d89de4b5..64b4ce3e3a 100644 --- a/Applications/Housekeeper/src/Housekeeper/packages.lock.json +++ b/Applications/Housekeeper/src/Housekeeper/packages.lock.json @@ -1180,11 +1180,6 @@ "OpenTelemetry.Api.ProviderBuilderExtensions": "1.17.0" } }, - "OpenTelemetry.Api": { - "type": "Transitive", - "resolved": "1.17.0", - "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" - }, "OpenTelemetry.Api.ProviderBuilderExtensions": { "type": "Transitive", "resolved": "1.17.0", @@ -1459,9 +1454,10 @@ "DotNetDiag.HealthChecks.SqlServer": "[10.0.10, 10.0.10]", "Microsoft.EntityFrameworkCore": "[10.0.10, 10.0.10]", "Microsoft.EntityFrameworkCore.Relational": "[10.0.10, 10.0.10]", - "OpenTelemetry.Exporter.Prometheus.AspNetCore": "[1.11.2-beta.1, 1.11.2-beta.1]", + "OpenTelemetry.Exporter.OpenTelemetryProtocol": "[1.17.0, )", "OpenTelemetry.Extensions.Hosting": "[1.17.0, 1.17.0]", "OpenTelemetry.Instrumentation.AspNetCore": "[1.17.0, 1.17.0]", + "OpenTelemetry.Instrumentation.EntityFrameworkCore": "[1.17.0-beta.1, )", "OpenTelemetry.Instrumentation.Http": "[1.17.0, 1.17.0]", "OpenTelemetry.Instrumentation.Runtime": "[1.17.0, 1.17.0]", "Polly": "[8.7.0, 8.7.0]", @@ -1522,6 +1518,7 @@ "Microsoft.Extensions.Identity.Core": "[10.0.10, 10.0.10]", "Microsoft.Extensions.Logging": "[10.0.10, 10.0.10]", "Npgsql.EntityFrameworkCore.PostgreSQL": "[10.0.3, 10.0.3]", + "OpenTelemetry.Api": "[1.17.0, )", "Polly": "[8.7.0, 8.7.0]", "RabbitMQ.Client": "[7.2.1, 7.2.1]", "Serilog": "[4.4.0, 4.4.0]" @@ -2513,13 +2510,19 @@ "OpenIddict.EntityFrameworkCore.Models": "7.6.0" } }, - "OpenTelemetry.Exporter.Prometheus.AspNetCore": { + "OpenTelemetry.Api": { + "type": "CentralTransitive", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" + }, + "OpenTelemetry.Exporter.OpenTelemetryProtocol": { "type": "CentralTransitive", - "requested": "[1.11.2-beta.1, 1.11.2-beta.1]", - "resolved": "1.11.2-beta.1", - "contentHash": "jouLU4VHpzyXuzF2yi/bpt9DoseZGyUudSdTFvylgIwIx6ST1bdI/AXNoJ4/n6HwMiso677ILLm/RM8DY+EYwA==", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "R1omQOrQpGlS0Cp5UIr/TAiuEA48JrPlgr1NPV5gESiTU7HhWU+ILe2EBSYb1fKdsSavZ7nZkHcUxAzofPqr2A==", "dependencies": { - "OpenTelemetry": "[1.11.2, 2.0.0)" + "OpenTelemetry": "1.17.0" } }, "OpenTelemetry.Extensions.Hosting": { @@ -2541,6 +2544,17 @@ "OpenTelemetry.Api.ProviderBuilderExtensions": "[1.17.0, 2.0.0)" } }, + "OpenTelemetry.Instrumentation.EntityFrameworkCore": { + "type": "CentralTransitive", + "requested": "[1.17.0-beta.1, )", + "resolved": "1.17.0-beta.1", + "contentHash": "BPSv1rk6qEkGZUGTNBfk7XmYqBAWdF3FBdjXEjVClp0bKUl6VCumlaosT84qvlK7YnHLCv5FFqJHx2N62TbKEw==", + "dependencies": { + "Microsoft.Extensions.Configuration": "10.0.0", + "Microsoft.Extensions.Options": "10.0.0", + "OpenTelemetry.Api.ProviderBuilderExtensions": "[1.17.0, 2.0.0)" + } + }, "OpenTelemetry.Instrumentation.Http": { "type": "CentralTransitive", "requested": "[1.17.0, 1.17.0]", diff --git a/Applications/IdentityDeletionJobs/src/Job.IdentityDeletion/IdentityDeletionJobConfiguration.cs b/Applications/IdentityDeletionJobs/src/Job.IdentityDeletion/IdentityDeletionJobConfiguration.cs index 382bb26b4b..ed6f358a11 100644 --- a/Applications/IdentityDeletionJobs/src/Job.IdentityDeletion/IdentityDeletionJobConfiguration.cs +++ b/Applications/IdentityDeletionJobs/src/Job.IdentityDeletion/IdentityDeletionJobConfiguration.cs @@ -1,10 +1,14 @@ using System.ComponentModel.DataAnnotations; +using Backbone.BuildingBlocks.API.Extensions; using Backbone.BuildingBlocks.Infrastructure.EventBus; namespace Backbone.Job.IdentityDeletion; public class IdentityDeletionJobConfiguration { + [Required] + public required TelemetryConfiguration Telemetry { get; init; } + [Required] public required InfrastructureConfiguration Infrastructure { get; init; } @@ -17,3 +21,8 @@ public class InfrastructureConfiguration [Required] public required EventBusConfiguration EventBus { get; init; } } + +public class TelemetryConfiguration +{ + public required OpenTelemetryCollectorConfiguration OpenTelemetryCollector { get; set; } = new(); +} diff --git a/Applications/IdentityDeletionJobs/src/Job.IdentityDeletion/Program.cs b/Applications/IdentityDeletionJobs/src/Job.IdentityDeletion/Program.cs index 42de790e16..3a6b9714f4 100644 --- a/Applications/IdentityDeletionJobs/src/Job.IdentityDeletion/Program.cs +++ b/Applications/IdentityDeletionJobs/src/Job.IdentityDeletion/Program.cs @@ -107,11 +107,13 @@ public static IHostBuilder CreateHostBuilder(string[] args) services.RegisterIdentityDeleters(); + services.AddOpenTelemetry(METER_NAME, Assembly.GetExecutingAssembly().GetName().Version?.ToString() ?? "unknown", parsedConfiguration.Telemetry.OpenTelemetryCollector); + services.AddEventBus(parsedConfiguration.Infrastructure.EventBus, METER_NAME); }) .UseServiceProviderFactory(new AutofacServiceProviderFactory()) .UseSerilog((context, configuration) => configuration - .ReadFrom.Configuration(context.Configuration, new ConfigurationReaderOptions { SectionName = "Logging" }) + .ReadFrom.Configuration(context.Configuration, new ConfigurationReaderOptions { SectionName = "Telemetry:Logging" }) .Enrich.FromLogContext() .Enrich.WithProperty("service", "jobs.identitydeletion") .Enrich.WithExceptionDetails(new DestructuringOptionsBuilder() diff --git a/Applications/IdentityDeletionJobs/src/Job.IdentityDeletion/appsettings.json b/Applications/IdentityDeletionJobs/src/Job.IdentityDeletion/appsettings.json index 4ba48a4ddd..1d59d85bf3 100644 --- a/Applications/IdentityDeletionJobs/src/Job.IdentityDeletion/appsettings.json +++ b/Applications/IdentityDeletionJobs/src/Job.IdentityDeletion/appsettings.json @@ -29,19 +29,21 @@ } } }, - "Logging": { - "MinimumLevel": { - "Default": "Warning", - "Override": { - "Backbone": "Information", - "Azure.Messaging.ServiceBus": "Error" - } - }, - "WriteTo": { - "Console": { - "Name": "Console", - "Args": { - "formatter": "Serilog.Formatting.Compact.CompactJsonFormatter, Serilog.Formatting.Compact" + "Telemetry": { + "Logging": { + "MinimumLevel": { + "Default": "Warning", + "Override": { + "Backbone": "Information", + "Azure.Messaging.ServiceBus": "Error" + } + }, + "WriteTo": { + "Console": { + "Name": "Console", + "Args": { + "formatter": "Serilog.Formatting.Compact.CompactJsonFormatter, Serilog.Formatting.Compact" + } } } } diff --git a/Applications/IdentityDeletionJobs/src/Job.IdentityDeletion/packages.lock.json b/Applications/IdentityDeletionJobs/src/Job.IdentityDeletion/packages.lock.json index 08664ee13e..a3252482ac 100644 --- a/Applications/IdentityDeletionJobs/src/Job.IdentityDeletion/packages.lock.json +++ b/Applications/IdentityDeletionJobs/src/Job.IdentityDeletion/packages.lock.json @@ -981,11 +981,6 @@ "OpenTelemetry.Api.ProviderBuilderExtensions": "1.17.0" } }, - "OpenTelemetry.Api": { - "type": "Transitive", - "resolved": "1.17.0", - "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" - }, "OpenTelemetry.Api.ProviderBuilderExtensions": { "type": "Transitive", "resolved": "1.17.0", @@ -1186,9 +1181,10 @@ "DotNetDiag.HealthChecks.SqlServer": "[10.0.10, 10.0.10]", "Microsoft.EntityFrameworkCore": "[10.0.10, 10.0.10]", "Microsoft.EntityFrameworkCore.Relational": "[10.0.10, 10.0.10]", - "OpenTelemetry.Exporter.Prometheus.AspNetCore": "[1.11.2-beta.1, 1.11.2-beta.1]", + "OpenTelemetry.Exporter.OpenTelemetryProtocol": "[1.17.0, )", "OpenTelemetry.Extensions.Hosting": "[1.17.0, 1.17.0]", "OpenTelemetry.Instrumentation.AspNetCore": "[1.17.0, 1.17.0]", + "OpenTelemetry.Instrumentation.EntityFrameworkCore": "[1.17.0-beta.1, )", "OpenTelemetry.Instrumentation.Http": "[1.17.0, 1.17.0]", "OpenTelemetry.Instrumentation.Runtime": "[1.17.0, 1.17.0]", "Polly": "[8.7.0, 8.7.0]", @@ -1249,6 +1245,7 @@ "Microsoft.Extensions.Identity.Core": "[10.0.10, 10.0.10]", "Microsoft.Extensions.Logging": "[10.0.10, 10.0.10]", "Npgsql.EntityFrameworkCore.PostgreSQL": "[10.0.3, 10.0.3]", + "OpenTelemetry.Api": "[1.17.0, )", "Polly": "[8.7.0, 8.7.0]", "RabbitMQ.Client": "[7.2.1, 7.2.1]", "Serilog": "[4.4.0, 4.4.0]" @@ -2308,13 +2305,19 @@ "OpenIddict.EntityFrameworkCore.Models": "7.6.0" } }, - "OpenTelemetry.Exporter.Prometheus.AspNetCore": { + "OpenTelemetry.Api": { + "type": "CentralTransitive", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" + }, + "OpenTelemetry.Exporter.OpenTelemetryProtocol": { "type": "CentralTransitive", - "requested": "[1.11.2-beta.1, 1.11.2-beta.1]", - "resolved": "1.11.2-beta.1", - "contentHash": "jouLU4VHpzyXuzF2yi/bpt9DoseZGyUudSdTFvylgIwIx6ST1bdI/AXNoJ4/n6HwMiso677ILLm/RM8DY+EYwA==", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "R1omQOrQpGlS0Cp5UIr/TAiuEA48JrPlgr1NPV5gESiTU7HhWU+ILe2EBSYb1fKdsSavZ7nZkHcUxAzofPqr2A==", "dependencies": { - "OpenTelemetry": "[1.11.2, 2.0.0)" + "OpenTelemetry": "1.17.0" } }, "OpenTelemetry.Extensions.Hosting": { @@ -2336,6 +2339,17 @@ "OpenTelemetry.Api.ProviderBuilderExtensions": "[1.17.0, 2.0.0)" } }, + "OpenTelemetry.Instrumentation.EntityFrameworkCore": { + "type": "CentralTransitive", + "requested": "[1.17.0-beta.1, )", + "resolved": "1.17.0-beta.1", + "contentHash": "BPSv1rk6qEkGZUGTNBfk7XmYqBAWdF3FBdjXEjVClp0bKUl6VCumlaosT84qvlK7YnHLCv5FFqJHx2N62TbKEw==", + "dependencies": { + "Microsoft.Extensions.Configuration": "10.0.0", + "Microsoft.Extensions.Options": "10.0.0", + "OpenTelemetry.Api.ProviderBuilderExtensions": "[1.17.0, 2.0.0)" + } + }, "OpenTelemetry.Instrumentation.Http": { "type": "CentralTransitive", "requested": "[1.17.0, 1.17.0]", diff --git a/Applications/IdentityDeletionJobs/test/Job.IdentityDeletion.Tests.Integration/packages.lock.json b/Applications/IdentityDeletionJobs/test/Job.IdentityDeletion.Tests.Integration/packages.lock.json index f02870c612..161d8b8dae 100644 --- a/Applications/IdentityDeletionJobs/test/Job.IdentityDeletion.Tests.Integration/packages.lock.json +++ b/Applications/IdentityDeletionJobs/test/Job.IdentityDeletion.Tests.Integration/packages.lock.json @@ -1034,11 +1034,6 @@ "OpenTelemetry.Api.ProviderBuilderExtensions": "1.17.0" } }, - "OpenTelemetry.Api": { - "type": "Transitive", - "resolved": "1.17.0", - "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" - }, "OpenTelemetry.Api.ProviderBuilderExtensions": { "type": "Transitive", "resolved": "1.17.0", @@ -1313,9 +1308,10 @@ "DotNetDiag.HealthChecks.SqlServer": "[10.0.10, 10.0.10]", "Microsoft.EntityFrameworkCore": "[10.0.10, 10.0.10]", "Microsoft.EntityFrameworkCore.Relational": "[10.0.10, 10.0.10]", - "OpenTelemetry.Exporter.Prometheus.AspNetCore": "[1.11.2-beta.1, 1.11.2-beta.1]", + "OpenTelemetry.Exporter.OpenTelemetryProtocol": "[1.17.0, )", "OpenTelemetry.Extensions.Hosting": "[1.17.0, 1.17.0]", "OpenTelemetry.Instrumentation.AspNetCore": "[1.17.0, 1.17.0]", + "OpenTelemetry.Instrumentation.EntityFrameworkCore": "[1.17.0-beta.1, )", "OpenTelemetry.Instrumentation.Http": "[1.17.0, 1.17.0]", "OpenTelemetry.Instrumentation.Runtime": "[1.17.0, 1.17.0]", "Polly": "[8.7.0, 8.7.0]", @@ -1376,6 +1372,7 @@ "Microsoft.Extensions.Identity.Core": "[10.0.10, 10.0.10]", "Microsoft.Extensions.Logging": "[10.0.10, 10.0.10]", "Npgsql.EntityFrameworkCore.PostgreSQL": "[10.0.3, 10.0.3]", + "OpenTelemetry.Api": "[1.17.0, )", "Polly": "[8.7.0, 8.7.0]", "RabbitMQ.Client": "[7.2.1, 7.2.1]", "Serilog": "[4.4.0, 4.4.0]" @@ -2509,13 +2506,19 @@ "OpenIddict.EntityFrameworkCore.Models": "7.6.0" } }, - "OpenTelemetry.Exporter.Prometheus.AspNetCore": { + "OpenTelemetry.Api": { + "type": "CentralTransitive", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" + }, + "OpenTelemetry.Exporter.OpenTelemetryProtocol": { "type": "CentralTransitive", - "requested": "[1.11.2-beta.1, 1.11.2-beta.1]", - "resolved": "1.11.2-beta.1", - "contentHash": "jouLU4VHpzyXuzF2yi/bpt9DoseZGyUudSdTFvylgIwIx6ST1bdI/AXNoJ4/n6HwMiso677ILLm/RM8DY+EYwA==", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "R1omQOrQpGlS0Cp5UIr/TAiuEA48JrPlgr1NPV5gESiTU7HhWU+ILe2EBSYb1fKdsSavZ7nZkHcUxAzofPqr2A==", "dependencies": { - "OpenTelemetry": "[1.11.2, 2.0.0)" + "OpenTelemetry": "1.17.0" } }, "OpenTelemetry.Extensions.Hosting": { @@ -2537,6 +2540,17 @@ "OpenTelemetry.Api.ProviderBuilderExtensions": "[1.17.0, 2.0.0)" } }, + "OpenTelemetry.Instrumentation.EntityFrameworkCore": { + "type": "CentralTransitive", + "requested": "[1.17.0-beta.1, )", + "resolved": "1.17.0-beta.1", + "contentHash": "BPSv1rk6qEkGZUGTNBfk7XmYqBAWdF3FBdjXEjVClp0bKUl6VCumlaosT84qvlK7YnHLCv5FFqJHx2N62TbKEw==", + "dependencies": { + "Microsoft.Extensions.Configuration": "10.0.0", + "Microsoft.Extensions.Options": "10.0.0", + "OpenTelemetry.Api.ProviderBuilderExtensions": "[1.17.0, 2.0.0)" + } + }, "OpenTelemetry.Instrumentation.Http": { "type": "CentralTransitive", "requested": "[1.17.0, 1.17.0]", diff --git a/Applications/IdentityDeletionJobs/test/Job.IdentityDeletion.Tests/packages.lock.json b/Applications/IdentityDeletionJobs/test/Job.IdentityDeletion.Tests/packages.lock.json index f02870c612..161d8b8dae 100644 --- a/Applications/IdentityDeletionJobs/test/Job.IdentityDeletion.Tests/packages.lock.json +++ b/Applications/IdentityDeletionJobs/test/Job.IdentityDeletion.Tests/packages.lock.json @@ -1034,11 +1034,6 @@ "OpenTelemetry.Api.ProviderBuilderExtensions": "1.17.0" } }, - "OpenTelemetry.Api": { - "type": "Transitive", - "resolved": "1.17.0", - "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" - }, "OpenTelemetry.Api.ProviderBuilderExtensions": { "type": "Transitive", "resolved": "1.17.0", @@ -1313,9 +1308,10 @@ "DotNetDiag.HealthChecks.SqlServer": "[10.0.10, 10.0.10]", "Microsoft.EntityFrameworkCore": "[10.0.10, 10.0.10]", "Microsoft.EntityFrameworkCore.Relational": "[10.0.10, 10.0.10]", - "OpenTelemetry.Exporter.Prometheus.AspNetCore": "[1.11.2-beta.1, 1.11.2-beta.1]", + "OpenTelemetry.Exporter.OpenTelemetryProtocol": "[1.17.0, )", "OpenTelemetry.Extensions.Hosting": "[1.17.0, 1.17.0]", "OpenTelemetry.Instrumentation.AspNetCore": "[1.17.0, 1.17.0]", + "OpenTelemetry.Instrumentation.EntityFrameworkCore": "[1.17.0-beta.1, )", "OpenTelemetry.Instrumentation.Http": "[1.17.0, 1.17.0]", "OpenTelemetry.Instrumentation.Runtime": "[1.17.0, 1.17.0]", "Polly": "[8.7.0, 8.7.0]", @@ -1376,6 +1372,7 @@ "Microsoft.Extensions.Identity.Core": "[10.0.10, 10.0.10]", "Microsoft.Extensions.Logging": "[10.0.10, 10.0.10]", "Npgsql.EntityFrameworkCore.PostgreSQL": "[10.0.3, 10.0.3]", + "OpenTelemetry.Api": "[1.17.0, )", "Polly": "[8.7.0, 8.7.0]", "RabbitMQ.Client": "[7.2.1, 7.2.1]", "Serilog": "[4.4.0, 4.4.0]" @@ -2509,13 +2506,19 @@ "OpenIddict.EntityFrameworkCore.Models": "7.6.0" } }, - "OpenTelemetry.Exporter.Prometheus.AspNetCore": { + "OpenTelemetry.Api": { + "type": "CentralTransitive", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" + }, + "OpenTelemetry.Exporter.OpenTelemetryProtocol": { "type": "CentralTransitive", - "requested": "[1.11.2-beta.1, 1.11.2-beta.1]", - "resolved": "1.11.2-beta.1", - "contentHash": "jouLU4VHpzyXuzF2yi/bpt9DoseZGyUudSdTFvylgIwIx6ST1bdI/AXNoJ4/n6HwMiso677ILLm/RM8DY+EYwA==", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "R1omQOrQpGlS0Cp5UIr/TAiuEA48JrPlgr1NPV5gESiTU7HhWU+ILe2EBSYb1fKdsSavZ7nZkHcUxAzofPqr2A==", "dependencies": { - "OpenTelemetry": "[1.11.2, 2.0.0)" + "OpenTelemetry": "1.17.0" } }, "OpenTelemetry.Extensions.Hosting": { @@ -2537,6 +2540,17 @@ "OpenTelemetry.Api.ProviderBuilderExtensions": "[1.17.0, 2.0.0)" } }, + "OpenTelemetry.Instrumentation.EntityFrameworkCore": { + "type": "CentralTransitive", + "requested": "[1.17.0-beta.1, )", + "resolved": "1.17.0-beta.1", + "contentHash": "BPSv1rk6qEkGZUGTNBfk7XmYqBAWdF3FBdjXEjVClp0bKUl6VCumlaosT84qvlK7YnHLCv5FFqJHx2N62TbKEw==", + "dependencies": { + "Microsoft.Extensions.Configuration": "10.0.0", + "Microsoft.Extensions.Options": "10.0.0", + "OpenTelemetry.Api.ProviderBuilderExtensions": "[1.17.0, 2.0.0)" + } + }, "OpenTelemetry.Instrumentation.Http": { "type": "CentralTransitive", "requested": "[1.17.0, 1.17.0]", diff --git a/Applications/SseServer/src/SseServer/Configuration.cs b/Applications/SseServer/src/SseServer/Configuration.cs index c5e22fadba..143473d93a 100644 --- a/Applications/SseServer/src/SseServer/Configuration.cs +++ b/Applications/SseServer/src/SseServer/Configuration.cs @@ -6,6 +6,9 @@ namespace Backbone.SseServer; public class Configuration { + [Required] + public required TelemetryConfiguration Telemetry { get; init; } + [Required] public required AuthenticationConfiguration Authentication { get; init; } @@ -20,6 +23,11 @@ public class Configuration [Required] public required SseServerConfiguration SseServer { get; init; } + public class TelemetryConfiguration + { + public required OpenTelemetryCollectorConfiguration OpenTelemetryCollector { get; set; } = new(); + } + public class AuthenticationConfiguration { [Required] diff --git a/Applications/SseServer/src/SseServer/Program.cs b/Applications/SseServer/src/SseServer/Program.cs index 0fb79bc1a9..a892138d50 100644 --- a/Applications/SseServer/src/SseServer/Program.cs +++ b/Applications/SseServer/src/SseServer/Program.cs @@ -1,3 +1,4 @@ +using System.Reflection; using Autofac.Extensions.DependencyInjection; using Backbone.BuildingBlocks.API.Extensions; using Backbone.BuildingBlocks.API.Mvc.Middleware; @@ -63,13 +64,13 @@ static WebApplication CreateApp(string[] args) builder.Host .UseSerilog((context, configuration) => configuration - .ReadFrom.Configuration(context.Configuration, new ConfigurationReaderOptions { SectionName = "Logging" }) + .ReadFrom.Configuration(context.Configuration, new ConfigurationReaderOptions { SectionName = "Telemetry:Logging" }) .Enrich.WithCorrelationId("X-Correlation-Id", addValueIfHeaderAbsence: true) .Enrich.FromLogContext() - .Enrich.WithProperty("service", "sseserver") .Enrich.WithExceptionDetails(new DestructuringOptionsBuilder() .WithDefaultDestructurers() - .WithDestructurers([new DbUpdateExceptionDestructurer()])), preserveStaticLogger: true + .WithDestructurers([new DbUpdateExceptionDestructurer()])), + writeToProviders: true ) .UseServiceProviderFactory(new AutofacServiceProviderFactory()); @@ -111,7 +112,7 @@ static void ConfigureServices(IServiceCollection services, IConfiguration config options.KnownProxies.Clear(); }); - services.AddOpenTelemetryWithPrometheusExporter(METER_NAME); + services.AddOpenTelemetry(METER_NAME, Assembly.GetExecutingAssembly().GetName().Version?.ToString() ?? "unknown", parsedConfiguration.Telemetry.OpenTelemetryCollector); services.AddCustomIdentity(environment); @@ -123,8 +124,6 @@ static void Configure(WebApplication app, Configuration configuration) if (configuration.SwaggerUi.Enabled) app.UseCustomSwaggerUi(); - app.MapPrometheusScrapingEndpoint(); - app.UseSerilogRequestLogging(opts => { opts.EnrichDiagnosticContext = LogHelper.EnrichFromRequest; diff --git a/Applications/SseServer/src/SseServer/appsettings.json b/Applications/SseServer/src/SseServer/appsettings.json index 691c9b3cbc..30be7fb2c5 100644 --- a/Applications/SseServer/src/SseServer/appsettings.json +++ b/Applications/SseServer/src/SseServer/appsettings.json @@ -32,19 +32,21 @@ } } }, - "Logging": { - "MinimumLevel": { - "Default": "Warning", - "Override": { - "Backbone": "Information", - "Azure.Messaging.ServiceBus": "Error" - } - }, - "WriteTo": { - "Console": { - "Name": "Console", - "Args": { - "formatter": "Serilog.Formatting.Compact.CompactJsonFormatter, Serilog.Formatting.Compact" + "Telemetry": { + "Logging": { + "MinimumLevel": { + "Default": "Warning", + "Override": { + "Backbone": "Information", + "Azure.Messaging.ServiceBus": "Error" + } + }, + "WriteTo": { + "Console": { + "Name": "Console", + "Args": { + "formatter": "Serilog.Formatting.Compact.CompactJsonFormatter, Serilog.Formatting.Compact" + } } } } diff --git a/Applications/SseServer/src/SseServer/packages.lock.json b/Applications/SseServer/src/SseServer/packages.lock.json index 08e019ec59..02a5e1e85f 100644 --- a/Applications/SseServer/src/SseServer/packages.lock.json +++ b/Applications/SseServer/src/SseServer/packages.lock.json @@ -723,11 +723,6 @@ "OpenTelemetry.Api.ProviderBuilderExtensions": "1.17.0" } }, - "OpenTelemetry.Api": { - "type": "Transitive", - "resolved": "1.17.0", - "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" - }, "OpenTelemetry.Api.ProviderBuilderExtensions": { "type": "Transitive", "resolved": "1.17.0", @@ -912,9 +907,10 @@ "DotNetDiag.HealthChecks.SqlServer": "[10.0.10, 10.0.10]", "Microsoft.EntityFrameworkCore": "[10.0.10, 10.0.10]", "Microsoft.EntityFrameworkCore.Relational": "[10.0.10, 10.0.10]", - "OpenTelemetry.Exporter.Prometheus.AspNetCore": "[1.11.2-beta.1, 1.11.2-beta.1]", + "OpenTelemetry.Exporter.OpenTelemetryProtocol": "[1.17.0, )", "OpenTelemetry.Extensions.Hosting": "[1.17.0, 1.17.0]", "OpenTelemetry.Instrumentation.AspNetCore": "[1.17.0, 1.17.0]", + "OpenTelemetry.Instrumentation.EntityFrameworkCore": "[1.17.0-beta.1, )", "OpenTelemetry.Instrumentation.Http": "[1.17.0, 1.17.0]", "OpenTelemetry.Instrumentation.Runtime": "[1.17.0, 1.17.0]", "Polly": "[8.7.0, 8.7.0]", @@ -975,6 +971,7 @@ "Microsoft.Extensions.Identity.Core": "[10.0.10, 10.0.10]", "Microsoft.Extensions.Logging": "[10.0.10, 10.0.10]", "Npgsql.EntityFrameworkCore.PostgreSQL": "[10.0.3, 10.0.3]", + "OpenTelemetry.Api": "[1.17.0, )", "Polly": "[8.7.0, 8.7.0]", "RabbitMQ.Client": "[7.2.1, 7.2.1]", "Serilog": "[4.4.0, 4.4.0]" @@ -1448,13 +1445,19 @@ "OpenIddict.EntityFrameworkCore.Models": "7.6.0" } }, - "OpenTelemetry.Exporter.Prometheus.AspNetCore": { + "OpenTelemetry.Api": { "type": "CentralTransitive", - "requested": "[1.11.2-beta.1, 1.11.2-beta.1]", - "resolved": "1.11.2-beta.1", - "contentHash": "jouLU4VHpzyXuzF2yi/bpt9DoseZGyUudSdTFvylgIwIx6ST1bdI/AXNoJ4/n6HwMiso677ILLm/RM8DY+EYwA==", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" + }, + "OpenTelemetry.Exporter.OpenTelemetryProtocol": { + "type": "CentralTransitive", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "R1omQOrQpGlS0Cp5UIr/TAiuEA48JrPlgr1NPV5gESiTU7HhWU+ILe2EBSYb1fKdsSavZ7nZkHcUxAzofPqr2A==", "dependencies": { - "OpenTelemetry": "[1.11.2, 2.0.0)" + "OpenTelemetry": "1.17.0" } }, "OpenTelemetry.Extensions.Hosting": { @@ -1475,6 +1478,15 @@ "OpenTelemetry.Api.ProviderBuilderExtensions": "[1.17.0, 2.0.0)" } }, + "OpenTelemetry.Instrumentation.EntityFrameworkCore": { + "type": "CentralTransitive", + "requested": "[1.17.0-beta.1, )", + "resolved": "1.17.0-beta.1", + "contentHash": "BPSv1rk6qEkGZUGTNBfk7XmYqBAWdF3FBdjXEjVClp0bKUl6VCumlaosT84qvlK7YnHLCv5FFqJHx2N62TbKEw==", + "dependencies": { + "OpenTelemetry.Api.ProviderBuilderExtensions": "[1.17.0, 2.0.0)" + } + }, "OpenTelemetry.Instrumentation.Http": { "type": "CentralTransitive", "requested": "[1.17.0, 1.17.0]", diff --git a/Applications/SseServer/test/SseServerTests/packages.lock.json b/Applications/SseServer/test/SseServerTests/packages.lock.json index a7d038ebe1..10399c7091 100644 --- a/Applications/SseServer/test/SseServerTests/packages.lock.json +++ b/Applications/SseServer/test/SseServerTests/packages.lock.json @@ -1069,11 +1069,6 @@ "OpenTelemetry.Api.ProviderBuilderExtensions": "1.17.0" } }, - "OpenTelemetry.Api": { - "type": "Transitive", - "resolved": "1.17.0", - "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" - }, "OpenTelemetry.Api.ProviderBuilderExtensions": { "type": "Transitive", "resolved": "1.17.0", @@ -1364,9 +1359,10 @@ "DotNetDiag.HealthChecks.SqlServer": "[10.0.10, 10.0.10]", "Microsoft.EntityFrameworkCore": "[10.0.10, 10.0.10]", "Microsoft.EntityFrameworkCore.Relational": "[10.0.10, 10.0.10]", - "OpenTelemetry.Exporter.Prometheus.AspNetCore": "[1.11.2-beta.1, 1.11.2-beta.1]", + "OpenTelemetry.Exporter.OpenTelemetryProtocol": "[1.17.0, )", "OpenTelemetry.Extensions.Hosting": "[1.17.0, 1.17.0]", "OpenTelemetry.Instrumentation.AspNetCore": "[1.17.0, 1.17.0]", + "OpenTelemetry.Instrumentation.EntityFrameworkCore": "[1.17.0-beta.1, )", "OpenTelemetry.Instrumentation.Http": "[1.17.0, 1.17.0]", "OpenTelemetry.Instrumentation.Runtime": "[1.17.0, 1.17.0]", "Polly": "[8.7.0, 8.7.0]", @@ -1427,6 +1423,7 @@ "Microsoft.Extensions.Identity.Core": "[10.0.10, 10.0.10]", "Microsoft.Extensions.Logging": "[10.0.10, 10.0.10]", "Npgsql.EntityFrameworkCore.PostgreSQL": "[10.0.3, 10.0.3]", + "OpenTelemetry.Api": "[1.17.0, )", "Polly": "[8.7.0, 8.7.0]", "RabbitMQ.Client": "[7.2.1, 7.2.1]", "Serilog": "[4.4.0, 4.4.0]" @@ -2130,13 +2127,19 @@ "OpenIddict.EntityFrameworkCore.Models": "7.6.0" } }, - "OpenTelemetry.Exporter.Prometheus.AspNetCore": { + "OpenTelemetry.Api": { + "type": "CentralTransitive", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" + }, + "OpenTelemetry.Exporter.OpenTelemetryProtocol": { "type": "CentralTransitive", - "requested": "[1.11.2-beta.1, 1.11.2-beta.1]", - "resolved": "1.11.2-beta.1", - "contentHash": "jouLU4VHpzyXuzF2yi/bpt9DoseZGyUudSdTFvylgIwIx6ST1bdI/AXNoJ4/n6HwMiso677ILLm/RM8DY+EYwA==", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "R1omQOrQpGlS0Cp5UIr/TAiuEA48JrPlgr1NPV5gESiTU7HhWU+ILe2EBSYb1fKdsSavZ7nZkHcUxAzofPqr2A==", "dependencies": { - "OpenTelemetry": "[1.11.2, 2.0.0)" + "OpenTelemetry": "1.17.0" } }, "OpenTelemetry.Extensions.Hosting": { @@ -2158,6 +2161,17 @@ "OpenTelemetry.Api.ProviderBuilderExtensions": "[1.17.0, 2.0.0)" } }, + "OpenTelemetry.Instrumentation.EntityFrameworkCore": { + "type": "CentralTransitive", + "requested": "[1.17.0-beta.1, )", + "resolved": "1.17.0-beta.1", + "contentHash": "BPSv1rk6qEkGZUGTNBfk7XmYqBAWdF3FBdjXEjVClp0bKUl6VCumlaosT84qvlK7YnHLCv5FFqJHx2N62TbKEw==", + "dependencies": { + "Microsoft.Extensions.Configuration": "10.0.0", + "Microsoft.Extensions.Options": "10.0.0", + "OpenTelemetry.Api.ProviderBuilderExtensions": "[1.17.0, 2.0.0)" + } + }, "OpenTelemetry.Instrumentation.Http": { "type": "CentralTransitive", "requested": "[1.17.0, 1.17.0]", diff --git a/Backbone.Tests.ArchUnit/packages.lock.json b/Backbone.Tests.ArchUnit/packages.lock.json index bc01a81735..ccd440d94c 100644 --- a/Backbone.Tests.ArchUnit/packages.lock.json +++ b/Backbone.Tests.ArchUnit/packages.lock.json @@ -1129,11 +1129,6 @@ "OpenTelemetry.Api.ProviderBuilderExtensions": "1.17.0" } }, - "OpenTelemetry.Api": { - "type": "Transitive", - "resolved": "1.17.0", - "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" - }, "OpenTelemetry.Api.ProviderBuilderExtensions": { "type": "Transitive", "resolved": "1.17.0", @@ -1450,9 +1445,10 @@ "DotNetDiag.HealthChecks.SqlServer": "[10.0.10, 10.0.10]", "Microsoft.EntityFrameworkCore": "[10.0.10, 10.0.10]", "Microsoft.EntityFrameworkCore.Relational": "[10.0.10, 10.0.10]", - "OpenTelemetry.Exporter.Prometheus.AspNetCore": "[1.11.2-beta.1, 1.11.2-beta.1]", + "OpenTelemetry.Exporter.OpenTelemetryProtocol": "[1.17.0, )", "OpenTelemetry.Extensions.Hosting": "[1.17.0, 1.17.0]", "OpenTelemetry.Instrumentation.AspNetCore": "[1.17.0, 1.17.0]", + "OpenTelemetry.Instrumentation.EntityFrameworkCore": "[1.17.0-beta.1, )", "OpenTelemetry.Instrumentation.Http": "[1.17.0, 1.17.0]", "OpenTelemetry.Instrumentation.Runtime": "[1.17.0, 1.17.0]", "Polly": "[8.7.0, 8.7.0]", @@ -1522,6 +1518,7 @@ "Microsoft.Extensions.Identity.Core": "[10.0.10, 10.0.10]", "Microsoft.Extensions.Logging": "[10.0.10, 10.0.10]", "Npgsql.EntityFrameworkCore.PostgreSQL": "[10.0.3, 10.0.3]", + "OpenTelemetry.Api": "[1.17.0, )", "Polly": "[8.7.0, 8.7.0]", "RabbitMQ.Client": "[7.2.1, 7.2.1]", "Serilog": "[4.4.0, 4.4.0]" @@ -1610,7 +1607,6 @@ "Backbone.Modules.Relationships.Module": "[1.0.0, )", "Backbone.Modules.Synchronization.Module": "[1.0.0, )", "Backbone.Modules.Tokens.Module": "[1.0.0, )", - "OpenTelemetry.Exporter.Prometheus.HttpListener": "[1.11.2-beta.1, 1.11.2-beta.1]", "Serilog.Enrichers.Sensitive": "[2.1.0, 2.1.0]", "Serilog.Exceptions": "[8.4.0, 8.4.0]", "Serilog.Exceptions.EntityFrameworkCore": "[8.4.0, 8.4.0]", @@ -2976,22 +2972,19 @@ "OpenIddict.EntityFrameworkCore.Models": "7.6.0" } }, - "OpenTelemetry.Exporter.Prometheus.AspNetCore": { + "OpenTelemetry.Api": { "type": "CentralTransitive", - "requested": "[1.11.2-beta.1, 1.11.2-beta.1]", - "resolved": "1.11.2-beta.1", - "contentHash": "jouLU4VHpzyXuzF2yi/bpt9DoseZGyUudSdTFvylgIwIx6ST1bdI/AXNoJ4/n6HwMiso677ILLm/RM8DY+EYwA==", - "dependencies": { - "OpenTelemetry": "[1.11.2, 2.0.0)" - } + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" }, - "OpenTelemetry.Exporter.Prometheus.HttpListener": { + "OpenTelemetry.Exporter.OpenTelemetryProtocol": { "type": "CentralTransitive", - "requested": "[1.11.2-beta.1, 1.11.2-beta.1]", - "resolved": "1.11.2-beta.1", - "contentHash": "Ppwr0l7X4AbZ2+b1XaZzl+I1196MtA+kelsdHF7QutoOtgdY7Mx0RAFMV7dKYCIRsOumfYaOb8U/Hkkft5HLrQ==", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "R1omQOrQpGlS0Cp5UIr/TAiuEA48JrPlgr1NPV5gESiTU7HhWU+ILe2EBSYb1fKdsSavZ7nZkHcUxAzofPqr2A==", "dependencies": { - "OpenTelemetry": "[1.11.2, 2.0.0)" + "OpenTelemetry": "1.17.0" } }, "OpenTelemetry.Extensions.Hosting": { @@ -3013,6 +3006,17 @@ "OpenTelemetry.Api.ProviderBuilderExtensions": "[1.17.0, 2.0.0)" } }, + "OpenTelemetry.Instrumentation.EntityFrameworkCore": { + "type": "CentralTransitive", + "requested": "[1.17.0-beta.1, )", + "resolved": "1.17.0-beta.1", + "contentHash": "BPSv1rk6qEkGZUGTNBfk7XmYqBAWdF3FBdjXEjVClp0bKUl6VCumlaosT84qvlK7YnHLCv5FFqJHx2N62TbKEw==", + "dependencies": { + "Microsoft.Extensions.Configuration": "10.0.0", + "Microsoft.Extensions.Options": "10.0.0", + "OpenTelemetry.Api.ProviderBuilderExtensions": "[1.17.0, 2.0.0)" + } + }, "OpenTelemetry.Instrumentation.Http": { "type": "CentralTransitive", "requested": "[1.17.0, 1.17.0]", diff --git a/BuildingBlocks/src/BuildingBlocks.API/BuildingBlocks.API.csproj b/BuildingBlocks/src/BuildingBlocks.API/BuildingBlocks.API.csproj index d4900f0fc9..5cdf49cc5e 100644 --- a/BuildingBlocks/src/BuildingBlocks.API/BuildingBlocks.API.csproj +++ b/BuildingBlocks/src/BuildingBlocks.API/BuildingBlocks.API.csproj @@ -7,9 +7,10 @@ - + + diff --git a/BuildingBlocks/src/BuildingBlocks.API/Diagnostics/DatabaseNameProcessor.cs b/BuildingBlocks/src/BuildingBlocks.API/Diagnostics/DatabaseNameProcessor.cs new file mode 100644 index 0000000000..bad16c330b --- /dev/null +++ b/BuildingBlocks/src/BuildingBlocks.API/Diagnostics/DatabaseNameProcessor.cs @@ -0,0 +1,13 @@ +using System.Diagnostics; +using OpenTelemetry; + +namespace Backbone.BuildingBlocks.API.Diagnostics; + +public sealed class DatabaseNameProcessor : BaseProcessor +{ + public override void OnStart(Activity activity) + { + if (activity.Source.Name.Contains("EntityFrameworkCore")) + activity.SetTag("peer.service", "database"); + } +} diff --git a/BuildingBlocks/src/BuildingBlocks.API/Diagnostics/UserContextProcessor.cs b/BuildingBlocks/src/BuildingBlocks.API/Diagnostics/UserContextProcessor.cs new file mode 100644 index 0000000000..fe2b356da7 --- /dev/null +++ b/BuildingBlocks/src/BuildingBlocks.API/Diagnostics/UserContextProcessor.cs @@ -0,0 +1,26 @@ +using System.Diagnostics; +using Backbone.BuildingBlocks.Application.Abstractions.Infrastructure.UserContext; +using Microsoft.Extensions.DependencyInjection; +using OpenTelemetry; + +namespace Backbone.BuildingBlocks.API.Diagnostics; + +public sealed class UserContextProcessor : BaseProcessor +{ + private readonly IServiceProvider _serviceProvider; + + public UserContextProcessor(IServiceProvider serviceProvider) + { + _serviceProvider = serviceProvider; + } + + public override void OnEnd(Activity data) + { + var userContext = _serviceProvider.GetService(); + + data.SetTag("enmeshed.backbone.client_id", userContext?.GetClientIdOrNull() ?? Baggage.Current.GetBaggage("enmeshed.backbone.client_id")); + data.SetTag("enmeshed.backbone.device_id", userContext?.GetDeviceIdOrNull() ?? Baggage.Current.GetBaggage("enmeshed.backbone.device_id")); + data.SetTag("enmeshed.backbone.identity_address", userContext?.GetAddressOrNull()?.Value ?? Baggage.Current.GetBaggage("enmeshed.backbone.identity_address")); + data.SetTag("enmeshed.backbone.username", userContext?.GetUsernameOrNull() ?? Baggage.Current.GetBaggage("enmeshed.backbone.username")); + } +} diff --git a/BuildingBlocks/src/BuildingBlocks.API/Extensions/ServiceCollectionExtensions.cs b/BuildingBlocks/src/BuildingBlocks.API/Extensions/ServiceCollectionExtensions.cs index ddea668262..418969281b 100644 --- a/BuildingBlocks/src/BuildingBlocks.API/Extensions/ServiceCollectionExtensions.cs +++ b/BuildingBlocks/src/BuildingBlocks.API/Extensions/ServiceCollectionExtensions.cs @@ -1,5 +1,7 @@ using Asp.Versioning.ApiExplorer; using Backbone.BuildingBlocks.API.AspNetCoreIdentityCustomizations; +using Backbone.BuildingBlocks.API.Diagnostics; +using Backbone.BuildingBlocks.Infrastructure.EventBus; using Backbone.BuildingBlocks.Infrastructure.Persistence.Database; using Backbone.BuildingBlocks.Module; using Backbone.Modules.Devices.Domain.Entities.Identities; @@ -10,7 +12,10 @@ using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Options; using Microsoft.OpenApi; +using OpenTelemetry.Logs; using OpenTelemetry.Metrics; +using OpenTelemetry.Resources; +using OpenTelemetry.Trace; using Swashbuckle.AspNetCore.SwaggerGen; namespace Backbone.BuildingBlocks.API.Extensions; @@ -103,19 +108,58 @@ public IServiceCollection AddCustomIdentity(IHostEnvironment environment) return services; } - public IServiceCollection AddOpenTelemetryWithPrometheusExporter(string name) + public IServiceCollection AddOpenTelemetry(string resourceName, string resourceVersion, OpenTelemetryCollectorConfiguration openTelemetryCollectorConfiguration, + params string[] additionalActivitySourceNames) { services.AddOpenTelemetry() + .ConfigureResource(resource => resource.AddService(resourceName, serviceVersion: resourceVersion)) .WithMetrics(metrics => { metrics - .AddPrometheusExporter() - .AddMeter(name) + .AddAspNetCoreInstrumentation() + .AddMeter(resourceName) .AddMeter("Microsoft.EntityFrameworkCore") .AddMeter("Microsoft.AspNetCore.Hosting") .AddMeter("Microsoft.AspNetCore.Diagnostics") - .AddMeter("Microsoft.AspNetCore.Server.Kestrel"); - }); + .AddMeter("Microsoft.AspNetCore.Server.Kestrel") + .AddMeter("Microsoft.AspNetCore.Authorization") + .AddMeter("Microsoft.AspNetCore.Authentication") + .AddMeter("Microsoft.AspNetCore.Identity"); + + if (openTelemetryCollectorConfiguration.Endpoint != null) + metrics.AddOtlpExporter(options => { options.Endpoint = new Uri(openTelemetryCollectorConfiguration.Endpoint); }); + }) + .WithTracing(tracing => + { + tracing + .AddAspNetCoreInstrumentation() + .AddEntityFrameworkCoreInstrumentation() + .AddHttpClientInstrumentation() + .AddSource(EventBusDiagnostics.ACTIVITY_SOURCE_NAME) + .AddProcessor() + .AddProcessor(); + + foreach (var activitySourceName in additionalActivitySourceNames) + { + tracing.AddSource(activitySourceName); + } + + if (openTelemetryCollectorConfiguration.Endpoint != null) + tracing.AddOtlpExporter(options => { options.Endpoint = new Uri(openTelemetryCollectorConfiguration.Endpoint); }); + }) + .WithLogging( + logging => + { + if (openTelemetryCollectorConfiguration.Endpoint != null) + logging.AddOtlpExporter(options => { options.Endpoint = new Uri(openTelemetryCollectorConfiguration.Endpoint); }); + }, + logging => + { + logging.IncludeFormattedMessage = true; + logging.IncludeScopes = true; + logging.ParseStateValues = true; + } + ); return services; } @@ -194,6 +238,11 @@ [new OpenApiSecuritySchemeReference(securityDefinitionName, document)] = [] } } +public class OpenTelemetryCollectorConfiguration +{ + public string? Endpoint { get; set; } +} + public class SwaggerUiConfiguration { public bool Enabled { get; init; } diff --git a/BuildingBlocks/src/BuildingBlocks.API/Mvc/Middleware/TraceIdMiddleware.cs b/BuildingBlocks/src/BuildingBlocks.API/Mvc/Middleware/TraceIdMiddleware.cs index b057ff9e1c..107e9f270f 100644 --- a/BuildingBlocks/src/BuildingBlocks.API/Mvc/Middleware/TraceIdMiddleware.cs +++ b/BuildingBlocks/src/BuildingBlocks.API/Mvc/Middleware/TraceIdMiddleware.cs @@ -1,3 +1,4 @@ +using System.Diagnostics; using Microsoft.AspNetCore.Http; namespace Backbone.BuildingBlocks.API.Mvc.Middleware; @@ -17,7 +18,7 @@ public Task InvokeAsync(HttpContext context) { context.Response.OnStarting(() => { - var traceId = context.TraceIdentifier; + var traceId = Activity.Current?.TraceId.ToString() ?? context.TraceIdentifier; context.Response.Headers[RESPONSE_HEADER_TRACE_ID] = traceId; return Task.CompletedTask; }); diff --git a/BuildingBlocks/src/BuildingBlocks.API/Mvc/Middleware/UserContextBaggageMiddleware.cs b/BuildingBlocks/src/BuildingBlocks.API/Mvc/Middleware/UserContextBaggageMiddleware.cs new file mode 100644 index 0000000000..e914025b36 --- /dev/null +++ b/BuildingBlocks/src/BuildingBlocks.API/Mvc/Middleware/UserContextBaggageMiddleware.cs @@ -0,0 +1,43 @@ +using Backbone.BuildingBlocks.Application.Abstractions.Infrastructure.UserContext; +using Microsoft.AspNetCore.Http; +using OpenTelemetry; + +namespace Backbone.BuildingBlocks.API.Mvc.Middleware; + +public class UserContextBaggageMiddleware +{ + private const string DEVICE_ID = "enmeshed.backbone.device_id"; + private const string IDENTITY_ADDRESS = "enmeshed.backbone.identity_address"; + private const string CLIENT_ID = "enmeshed.backbone.client_id"; + private const string USERNAME = "enmeshed.backbone.username"; + + private readonly RequestDelegate _next; + + public UserContextBaggageMiddleware(RequestDelegate next) + { + _next = next; + } + + public async Task InvokeAsync(HttpContext context, IUserContext userContext) + { + var baggageItems = new List>(); + + AddIfNotNull(baggageItems, DEVICE_ID, userContext.GetDeviceIdOrNull()?.Value); + AddIfNotNull(baggageItems, IDENTITY_ADDRESS, userContext.GetAddressOrNull()?.Value); + AddIfNotNull(baggageItems, CLIENT_ID, userContext.GetClientIdOrNull()); + AddIfNotNull(baggageItems, USERNAME, userContext.GetUsernameOrNull()); + + if (baggageItems.Count > 0) + Baggage.SetBaggage(baggageItems); + + await _next(context); + } + + private static void AddIfNotNull(List> baggageItems, string key, string? value) + { + if (value == null) + return; + + baggageItems.Add(new KeyValuePair(key, value)); + } +} diff --git a/BuildingBlocks/src/BuildingBlocks.API/packages.lock.json b/BuildingBlocks/src/BuildingBlocks.API/packages.lock.json index 40232d4cf1..0a6d7e7565 100644 --- a/BuildingBlocks/src/BuildingBlocks.API/packages.lock.json +++ b/BuildingBlocks/src/BuildingBlocks.API/packages.lock.json @@ -64,13 +64,13 @@ "Microsoft.Extensions.Logging": "10.0.10" } }, - "OpenTelemetry.Exporter.Prometheus.AspNetCore": { + "OpenTelemetry.Exporter.OpenTelemetryProtocol": { "type": "Direct", - "requested": "[1.11.2-beta.1, 1.11.2-beta.1]", - "resolved": "1.11.2-beta.1", - "contentHash": "jouLU4VHpzyXuzF2yi/bpt9DoseZGyUudSdTFvylgIwIx6ST1bdI/AXNoJ4/n6HwMiso677ILLm/RM8DY+EYwA==", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "R1omQOrQpGlS0Cp5UIr/TAiuEA48JrPlgr1NPV5gESiTU7HhWU+ILe2EBSYb1fKdsSavZ7nZkHcUxAzofPqr2A==", "dependencies": { - "OpenTelemetry": "[1.11.2, 2.0.0)" + "OpenTelemetry": "1.17.0" } }, "OpenTelemetry.Extensions.Hosting": { @@ -92,6 +92,17 @@ "OpenTelemetry.Api.ProviderBuilderExtensions": "[1.17.0, 2.0.0)" } }, + "OpenTelemetry.Instrumentation.EntityFrameworkCore": { + "type": "Direct", + "requested": "[1.17.0-beta.1, )", + "resolved": "1.17.0-beta.1", + "contentHash": "BPSv1rk6qEkGZUGTNBfk7XmYqBAWdF3FBdjXEjVClp0bKUl6VCumlaosT84qvlK7YnHLCv5FFqJHx2N62TbKEw==", + "dependencies": { + "Microsoft.Extensions.Configuration": "10.0.0", + "Microsoft.Extensions.Options": "10.0.0", + "OpenTelemetry.Api.ProviderBuilderExtensions": "[1.17.0, 2.0.0)" + } + }, "OpenTelemetry.Instrumentation.Http": { "type": "Direct", "requested": "[1.17.0, 1.17.0]", @@ -1066,11 +1077,6 @@ "OpenTelemetry.Api.ProviderBuilderExtensions": "1.17.0" } }, - "OpenTelemetry.Api": { - "type": "Transitive", - "resolved": "1.17.0", - "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" - }, "OpenTelemetry.Api.ProviderBuilderExtensions": { "type": "Transitive", "resolved": "1.17.0", @@ -1298,6 +1304,7 @@ "Microsoft.Extensions.Identity.Core": "[10.0.10, 10.0.10]", "Microsoft.Extensions.Logging": "[10.0.10, 10.0.10]", "Npgsql.EntityFrameworkCore.PostgreSQL": "[10.0.3, 10.0.3]", + "OpenTelemetry.Api": "[1.17.0, )", "Polly": "[8.7.0, 8.7.0]", "RabbitMQ.Client": "[7.2.1, 7.2.1]", "Serilog": "[4.4.0, 4.4.0]" @@ -1823,6 +1830,12 @@ "OpenIddict.EntityFrameworkCore.Models": "7.6.0" } }, + "OpenTelemetry.Api": { + "type": "CentralTransitive", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" + }, "RabbitMQ.Client": { "type": "CentralTransitive", "requested": "[7.2.1, 7.2.1]", diff --git a/BuildingBlocks/src/BuildingBlocks.Application/Housekeeping/HousekeepingTelemetry.cs b/BuildingBlocks/src/BuildingBlocks.Application/Housekeeping/HousekeepingTelemetry.cs new file mode 100644 index 0000000000..7c2646d5d3 --- /dev/null +++ b/BuildingBlocks/src/BuildingBlocks.Application/Housekeeping/HousekeepingTelemetry.cs @@ -0,0 +1,73 @@ +using System.Diagnostics; + +namespace Backbone.BuildingBlocks.Application.Housekeeping; + +public static class HousekeepingTelemetry +{ + public const string ACTIVITY_SOURCE_NAME = "Backbone.Housekeeping"; + + public static readonly ActivitySource ACTIVITY_SOURCE = new(ACTIVITY_SOURCE_NAME); + + public static async Task TrackModuleDeletion(string moduleName, Func execute, CancellationToken cancellationToken) + { + using var activity = StartModuleDeletionActivity(moduleName); + + try + { + await execute(cancellationToken); + } + catch (Exception ex) + { + TrackException(activity, ex); + throw; + } + } + + private static Activity? StartModuleDeletionActivity(string moduleName) + { + var activity = ACTIVITY_SOURCE.StartActivity($"delete {moduleName} module"); + + if (activity == null) + return null; + + activity.SetTag("housekeeping.operation", "module_deletion"); + activity.SetTag("housekeeping.module", moduleName); + + return activity; + } + + public static async Task TrackItemDeletion(string itemType, Func> delete, CancellationToken cancellationToken) + { + using var activity = StartItemDeletionActivity(itemType); + + try + { + var numberOfDeletedItems = await delete(cancellationToken); + activity?.SetTag("housekeeping.deleted_item_count", numberOfDeletedItems); + } + catch (Exception ex) + { + TrackException(activity, ex); + throw; + } + } + + private static Activity? StartItemDeletionActivity(string itemType) + { + var activity = ACTIVITY_SOURCE.StartActivity($"delete {itemType}"); + + if (activity == null) + return null; + + activity.SetTag("housekeeping.operation", "delete"); + activity.SetTag("housekeeping.item_type", itemType); + + return activity; + } + + private static void TrackException(Activity? activity, Exception exception) + { + activity?.AddException(exception); + activity?.SetStatus(ActivityStatusCode.Error, exception.Message); + } +} diff --git a/BuildingBlocks/src/BuildingBlocks.Application/Housekeeping/LoggerExtensions.cs b/BuildingBlocks/src/BuildingBlocks.Application/Housekeeping/LoggerExtensions.cs deleted file mode 100644 index 3f1ec46564..0000000000 --- a/BuildingBlocks/src/BuildingBlocks.Application/Housekeeping/LoggerExtensions.cs +++ /dev/null @@ -1,13 +0,0 @@ -using Microsoft.Extensions.Logging; - -namespace Backbone.BuildingBlocks.Application.Housekeeping; - -public static partial class LoggerExtensions -{ - [LoggerMessage( - EventId = 769524, - EventName = "ExecuteHousekeeping.DataDeleted", - Level = LogLevel.Information, - Message = "Deleted {numberOfDeletedItems} {descriptionOfDeletedObjects} in {elapsedMilliseconds}ms.")] - public static partial void DataDeleted(this ILogger logger, int numberOfDeletedItems, string descriptionOfDeletedObjects, long elapsedMilliseconds); -} diff --git a/BuildingBlocks/src/BuildingBlocks.Application/packages.lock.json b/BuildingBlocks/src/BuildingBlocks.Application/packages.lock.json index f99f6e2ee8..8b0e819af8 100644 --- a/BuildingBlocks/src/BuildingBlocks.Application/packages.lock.json +++ b/BuildingBlocks/src/BuildingBlocks.Application/packages.lock.json @@ -742,6 +742,7 @@ "Microsoft.Extensions.Identity.Core": "[10.0.10, 10.0.10]", "Microsoft.Extensions.Logging": "[10.0.10, 10.0.10]", "Npgsql.EntityFrameworkCore.PostgreSQL": "[10.0.3, 10.0.3]", + "OpenTelemetry.Api": "[1.17.0, )", "Polly": "[8.7.0, 8.7.0]", "RabbitMQ.Client": "[7.2.1, 7.2.1]", "Serilog": "[4.4.0, 4.4.0]" @@ -1092,6 +1093,12 @@ "Npgsql": "10.0.3" } }, + "OpenTelemetry.Api": { + "type": "CentralTransitive", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" + }, "RabbitMQ.Client": { "type": "CentralTransitive", "requested": "[7.2.1, 7.2.1]", diff --git a/BuildingBlocks/src/BuildingBlocks.Infrastructure/BuildingBlocks.Infrastructure.csproj b/BuildingBlocks/src/BuildingBlocks.Infrastructure/BuildingBlocks.Infrastructure.csproj index 06bde4e9e3..05a38d5e2c 100644 --- a/BuildingBlocks/src/BuildingBlocks.Infrastructure/BuildingBlocks.Infrastructure.csproj +++ b/BuildingBlocks/src/BuildingBlocks.Infrastructure/BuildingBlocks.Infrastructure.csproj @@ -21,6 +21,7 @@ + diff --git a/BuildingBlocks/src/BuildingBlocks.Infrastructure/EventBus/AzureServiceBus/EventBusAzureServiceBus.Consumer.cs b/BuildingBlocks/src/BuildingBlocks.Infrastructure/EventBus/AzureServiceBus/EventBusAzureServiceBus.Consumer.cs index a6fe12fcd3..380f5d64f5 100644 --- a/BuildingBlocks/src/BuildingBlocks.Infrastructure/EventBus/AzureServiceBus/EventBusAzureServiceBus.Consumer.cs +++ b/BuildingBlocks/src/BuildingBlocks.Infrastructure/EventBus/AzureServiceBus/EventBusAzureServiceBus.Consumer.cs @@ -1,4 +1,5 @@ using System.Diagnostics; +using System.Text; using System.Text.Json; using Azure.Messaging.ServiceBus; using Azure.Messaging.ServiceBus.Administration; @@ -8,11 +9,16 @@ using Backbone.Tooling.Extensions; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; +using OpenTelemetry; namespace Backbone.BuildingBlocks.Infrastructure.EventBus.AzureServiceBus; public partial class EventBusAzureServiceBus { + private const string CALL_OPERATION_NAME = "call"; + private const string PROCESS_OPERATION_NAME = "consume"; + private const string PROCESS_OPERATION_TYPE = "process"; + public async Task Subscribe() where T : DomainEvent where TH : IDomainEventHandler @@ -29,7 +35,12 @@ public async Task Subscribe() processor.ProcessMessageAsync += async args => { + using var activity = StartProcessActivity(args.Message, subscriptionName, args.Message.Body.ToMemory().Length); + var messageData = args.Message.Body.ToString(); + + activity?.AddEvent(new ActivityEvent("enmeshed.backbone.event_bus.consumer.message_decoded")); + var correlationId = args.Message.CorrelationId; correlationId = correlationId.IsNullOrEmpty() ? CustomLogContext.GenerateCorrelationId() : correlationId; @@ -107,16 +118,15 @@ private async Task RegisterSubscriptionClientMessageHandler(CancellationToken ca private Task ErrorHandler(ProcessErrorEventArgs args) { - var ex = args.Exception; - var context = args.ErrorSource; - - _logger.ErrorHandlingMessage(context, ex); + Activity.Current?.AddException(args.Exception); return Task.CompletedTask; } private async Task ProcessEvent(string message) where TEvent : DomainEvent where THandler : IDomainEventHandler { + Activity.Current?.AddEvent(new ActivityEvent("enmeshed.backbone.event_bus.consumer.start_processing")); + var eventType = typeof(TEvent); var domainEvent = JsonSerializer.Deserialize(message)!; @@ -129,21 +139,93 @@ private async Task ProcessEvent(string message) where TE if (scope.ServiceProvider.GetService(typeof(THandler)) is not IDomainEventHandler handler) throw new Exception($"Domain event handler '{typeof(THandler).FullName}' could not be resolved from dependency container or it does not implement {nameof(IDomainEventHandler)}."); + Activity.Current?.AddEvent(new ActivityEvent("enmeshed.backbone.event_bus.consumer.handler_resolved")); + var startedAt = Stopwatch.GetTimestamp(); - await (Task)concreteType.GetMethod("Handle")!.Invoke(handler, [domainEvent])!; + using (var handlerActivity = StartHandlerActivity()) + { + try + { + await (Task)concreteType.GetMethod("Handle")!.Invoke(handler, [domainEvent])!; + } + catch (Exception ex) + { + handlerActivity?.AddException(ex); + throw; + } + } + _metrics.TrackEventProcessingDuration(startedAt, GetSubscriptionName()); _metrics.IncrementNumberOfHandledEvents(GetSubscriptionName()); } catch (Exception ex) { - _logger.ErrorWhileProcessingDomainEvent(domainEvent.DomainEventId, ex); + Activity.Current?.AddException(ex); return false; } return true; } + private Activity? StartHandlerActivity() where TEvent : DomainEvent where THandler : IDomainEventHandler + { + var handlerType = typeof(THandler); + var eventType = typeof(TEvent); + var activity = EventBusDiagnostics.ACTIVITY_SOURCE.StartActivity($"{CALL_OPERATION_NAME} {handlerType.FullName}", ActivityKind.Internal); + + if (activity == null) + return null; + + activity.SetTag("event_bus.event.name", eventType.GetEventName()); + activity.SetTag("event_bus.event.type", eventType.FullName); + activity.SetTag("event_bus.handler.type", handlerType.FullName); + + return activity; + } + + private Activity? StartProcessActivity(ServiceBusReceivedMessage message, string subscriptionName, int bodySize) + { + var parentContext = EventBusDiagnostics.PROPAGATOR.Extract(default, + message.ApplicationProperties, + ExtractTraceContextFromApplicationProperties); + Baggage.Current = parentContext.Baggage; + + var destinationName = $"{TOPIC_NAME}.{subscriptionName}"; + var activity = EventBusDiagnostics.ACTIVITY_SOURCE.StartActivity($"{PROCESS_OPERATION_NAME} {destinationName}", ActivityKind.Consumer, parentContext.ActivityContext); + + if (activity == null) + return null; + + activity.SetTag("messaging.system", MESSAGING_SYSTEM); + activity.SetTag("messaging.operation.name", PROCESS_OPERATION_NAME); + activity.SetTag("messaging.operation.type", PROCESS_OPERATION_TYPE); + activity.SetTag("messaging.destination.name", destinationName); + activity.SetTag("messaging.destination.subscription.name", subscriptionName); + activity.SetTag("messaging.destination.template", $"{TOPIC_NAME}:{{subscriptionName}}"); + activity.SetTag("messaging.message.body.size", bodySize); + activity.SetTag("messaging.servicebus.message.delivery_count", message.DeliveryCount); + activity.SetTag("messaging.servicebus.message.enqueued_time", message.EnqueuedTime.ToUnixTimeSeconds()); + + if (!message.MessageId.IsNullOrEmpty()) + activity.SetTag("messaging.message.id", message.MessageId); + + if (!message.CorrelationId.IsNullOrEmpty()) + activity.SetTag("messaging.message.conversation_id", message.CorrelationId); + + return activity; + } + + private IEnumerable ExtractTraceContextFromApplicationProperties(IReadOnlyDictionary applicationProperties, string key) + { + if (!applicationProperties.TryGetValue(key, out var value)) return []; + + if (value is string stringValue) return [stringValue]; + if (value is byte[] bytes) return [Encoding.UTF8.GetString(bytes)]; + + return []; + } + public async Task StopConsuming(CancellationToken cancellationToken) { foreach (var processor in _processors) diff --git a/BuildingBlocks/src/BuildingBlocks.Infrastructure/EventBus/AzureServiceBus/EventBusAzureServiceBus.Publisher.cs b/BuildingBlocks/src/BuildingBlocks.Infrastructure/EventBus/AzureServiceBus/EventBusAzureServiceBus.Publisher.cs index 7ae0330314..f60f2691fa 100644 --- a/BuildingBlocks/src/BuildingBlocks.Infrastructure/EventBus/AzureServiceBus/EventBusAzureServiceBus.Publisher.cs +++ b/BuildingBlocks/src/BuildingBlocks.Infrastructure/EventBus/AzureServiceBus/EventBusAzureServiceBus.Publisher.cs @@ -4,12 +4,18 @@ using Azure.Messaging.ServiceBus; using Backbone.BuildingBlocks.Domain.Events; using Backbone.BuildingBlocks.Infrastructure.CorrelationIds; +using Backbone.Tooling.Extensions; using Microsoft.Extensions.Logging; +using OpenTelemetry; +using OpenTelemetry.Context.Propagation; namespace Backbone.BuildingBlocks.Infrastructure.EventBus.AzureServiceBus; public partial class EventBusAzureServiceBus { + private const string PUBLISH_OPERATION_NAME = "publish"; + private const string SEND_OPERATION_TYPE = "send"; + public async Task Publish(DomainEvent @event) { var eventName = @event.GetEventName(); @@ -26,6 +32,8 @@ public async Task Publish(DomainEvent @event) CorrelationId = CustomLogContext.GetCorrelationId() }; + using var activity = StartPublishActivity(message, @event.DomainEventId, eventName, body.Length); + _logger.SendingDomainEvent(message.MessageId); try @@ -38,10 +46,48 @@ public async Task Publish(DomainEvent @event) _logger.LogDebug("Successfully sent domain event with id '{MessageId}'.", message.MessageId); } - catch (Exception) + catch (Exception ex) { _metrics.IncrementNumberOfPublishingErrors(eventName); + activity?.AddException(ex); throw; } } + + private Activity? StartPublishActivity(ServiceBusMessage message, string messageId, string eventName, int bodySize) + { + var destinationName = $"{TOPIC_NAME}:{eventName}"; + + var activity = EventBusDiagnostics.ACTIVITY_SOURCE.StartActivity($"{PUBLISH_OPERATION_NAME} {destinationName}", ActivityKind.Producer, Activity.Current?.Context ?? default); + + ActivityContext contextToInject = default; + + if (activity != null) + contextToInject = activity.Context; + else if (Activity.Current != null) + contextToInject = Activity.Current.Context; + + EventBusDiagnostics.PROPAGATOR.Inject(new PropagationContext(contextToInject, Baggage.Current), message.ApplicationProperties, InjectTraceContextIntoApplicationProperties); + + if (activity == null) + return null; + + activity.SetTag("messaging.system", MESSAGING_SYSTEM); + activity.SetTag("messaging.operation.name", PUBLISH_OPERATION_NAME); + activity.SetTag("messaging.operation.type", SEND_OPERATION_TYPE); + activity.SetTag("messaging.destination.name", destinationName); + activity.SetTag("messaging.message.id", messageId); + activity.SetTag("messaging.message.body.size", bodySize); + activity.SetTag("messaging.destination.template", $"{TOPIC_NAME}:{{eventName}}"); + + if (!message.CorrelationId.IsNullOrEmpty()) + activity.SetTag("messaging.message.conversation_id", message.CorrelationId); + + return activity; + } + + private void InjectTraceContextIntoApplicationProperties(IDictionary applicationProperties, string key, string value) + { + applicationProperties[key] = value; + } } diff --git a/BuildingBlocks/src/BuildingBlocks.Infrastructure/EventBus/AzureServiceBus/EventBusAzureServiceBus.cs b/BuildingBlocks/src/BuildingBlocks.Infrastructure/EventBus/AzureServiceBus/EventBusAzureServiceBus.cs index 17806d957a..296c2484ba 100644 --- a/BuildingBlocks/src/BuildingBlocks.Infrastructure/EventBus/AzureServiceBus/EventBusAzureServiceBus.cs +++ b/BuildingBlocks/src/BuildingBlocks.Infrastructure/EventBus/AzureServiceBus/EventBusAzureServiceBus.cs @@ -10,6 +10,7 @@ namespace Backbone.BuildingBlocks.Infrastructure.EventBus.AzureServiceBus; public partial class EventBusAzureServiceBus : IEventBus, IDisposable, IAsyncDisposable { private const string TOPIC_NAME = "default"; + private const string MESSAGING_SYSTEM = "servicebus"; private const int MAX_DELIVERY_COUNT = 5; private readonly ServiceBusProcessorOptions _options = new() @@ -86,11 +87,4 @@ internal static partial class EventBusAzureServiceBusLogs Level = LogLevel.Error, Message = "Error handling message with context {exceptionContext}.")] public static partial void ErrorHandlingMessage(this ILogger logger, ServiceBusErrorSource exceptionContext, Exception exception); - - [LoggerMessage( - EventId = 146670, - EventName = "EventBusAzureServiceBus.ErrorWhileProcessingDomainEvent", - Level = LogLevel.Error, - Message = "An error occurred while processing the event with id '{domainEventId}'.")] - public static partial void ErrorWhileProcessingDomainEvent(this ILogger logger, string domainEventId, Exception ex); } diff --git a/BuildingBlocks/src/BuildingBlocks.Infrastructure/EventBus/EventBusDiagnostics.cs b/BuildingBlocks/src/BuildingBlocks.Infrastructure/EventBus/EventBusDiagnostics.cs new file mode 100644 index 0000000000..edd0b9508f --- /dev/null +++ b/BuildingBlocks/src/BuildingBlocks.Infrastructure/EventBus/EventBusDiagnostics.cs @@ -0,0 +1,12 @@ +using System.Diagnostics; +using OpenTelemetry.Context.Propagation; + +namespace Backbone.BuildingBlocks.Infrastructure.EventBus; + +public class EventBusDiagnostics +{ + public const string ACTIVITY_SOURCE_NAME = "Backbone.EventBus"; + + public static readonly ActivitySource ACTIVITY_SOURCE = new(ACTIVITY_SOURCE_NAME); + public static readonly TextMapPropagator PROPAGATOR = Propagators.DefaultTextMapPropagator; +} diff --git a/BuildingBlocks/src/BuildingBlocks.Infrastructure/EventBus/GoogleCloudPubSub/EventBusGoogleCloudPubSub.Consumer.cs b/BuildingBlocks/src/BuildingBlocks.Infrastructure/EventBus/GoogleCloudPubSub/EventBusGoogleCloudPubSub.Consumer.cs index 078136fdfb..08c5f31aa2 100644 --- a/BuildingBlocks/src/BuildingBlocks.Infrastructure/EventBus/GoogleCloudPubSub/EventBusGoogleCloudPubSub.Consumer.cs +++ b/BuildingBlocks/src/BuildingBlocks.Infrastructure/EventBus/GoogleCloudPubSub/EventBusGoogleCloudPubSub.Consumer.cs @@ -10,12 +10,17 @@ using Grpc.Core; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; +using OpenTelemetry; using Type = System.Type; namespace Backbone.BuildingBlocks.Infrastructure.EventBus.GoogleCloudPubSub; public partial class EventBusGoogleCloudPubSub { + private const string CALL_OPERATION_NAME = "call"; + private const string PROCESS_OPERATION_NAME = "consume"; + private const string PROCESS_OPERATION_TYPE = "process"; + public async Task Subscribe() where T : DomainEvent where TH : IDomainEventHandler @@ -79,8 +84,14 @@ public async Task StartConsuming(CancellationToken cancellationToken) private async Task OnIncomingEvent(PubsubMessage @event, Type eventType, Type handlerType) { + var subscriptionName = GetSubscriptionName(_projectId, handlerType, eventType).SubscriptionId; + + using var activity = StartProcessActivity(@event, subscriptionName, @event.Data.Length); + var eventData = @event.Data.ToStringUtf8(); + activity?.AddEvent(new ActivityEvent("enmeshed.backbone.event_bus.consumer.message_decoded")); + try { @event.Attributes.TryGetValue(PubSubMessageAttributes.CORRELATION_ID, out var correlationId); @@ -94,8 +105,10 @@ public async Task StartConsuming(CancellationToken cancellationToken) } catch (Exception ex) { - _metrics.IncrementNumberOfProcessingErrors(GetSubscriptionName(_projectId, handlerType, eventType).SubscriptionId); - _logger.ErrorHandlingMessage(ex.StackTrace!, ex); + activity?.AddException(ex); + + _metrics.IncrementNumberOfProcessingErrors(subscriptionName); + activity?.AddException(ex); return SubscriberClient.Reply.Nack; } @@ -104,6 +117,8 @@ public async Task StartConsuming(CancellationToken cancellationToken) private async Task ProcessEvent(string message, Type eventType, Type handlerType) { + Activity.Current?.AddEvent(new ActivityEvent("enmeshed.backbone.event_bus.consumer.start_processing")); + var subscriptionName = GetSubscriptionName(_projectId, handlerType, eventType).SubscriptionId; var domainEvent = JsonSerializer.Deserialize(message, eventType)!; @@ -112,15 +127,83 @@ private async Task ProcessEvent(string message, Type eventType, Type handlerType if (scope.ServiceProvider.GetService(handlerType) is not IDomainEventHandler handler) throw new Exception("Domain event handler could not be resolved from dependency container or it does not implement IDomainEventHandler."); + Activity.Current?.AddEvent(new ActivityEvent("enmeshed.backbone.event_bus.consumer.handler_resolved")); + var handleMethod = handler.GetType().GetMethod("Handle"); var startedAt = Stopwatch.GetTimestamp(); - await (Task)handleMethod!.Invoke(handler, [domainEvent])!; + using (var handlerActivity = StartHandlerActivity(eventType, handlerType)) + { + try + { + await (Task)handleMethod!.Invoke(handler, [domainEvent])!; + } + catch (Exception ex) + { + handlerActivity?.AddException(ex); + throw; + } + } + _metrics.TrackEventProcessingDuration(startedAt, subscriptionName); _metrics.IncrementNumberOfHandledEvents(subscriptionName); } + private Activity? StartHandlerActivity(Type eventType, Type handlerType) + { + var activity = EventBusDiagnostics.ACTIVITY_SOURCE.StartActivity($"{CALL_OPERATION_NAME} {handlerType.FullName}", ActivityKind.Internal); + + if (activity == null) + return null; + + activity.SetTag("event_bus.event.name", eventType.GetEventName()); + activity.SetTag("event_bus.event.type", eventType.FullName); + activity.SetTag("event_bus.handler.type", handlerType.FullName); + + return activity; + } + + private Activity? StartProcessActivity(PubsubMessage message, string subscriptionName, int bodySize) + { + var parentContext = EventBusDiagnostics.PROPAGATOR.Extract(default, + message.Attributes, + ExtractTraceContextFromAttributes); + Baggage.Current = parentContext.Baggage; + + var destinationName = $"{_topicName.TopicId}.{subscriptionName}"; + var activity = EventBusDiagnostics.ACTIVITY_SOURCE.StartActivity($"{PROCESS_OPERATION_NAME} {destinationName}", ActivityKind.Consumer, parentContext.ActivityContext); + + if (activity == null) + return null; + + activity.SetTag("messaging.system", MESSAGING_SYSTEM); + activity.SetTag("messaging.operation.name", PROCESS_OPERATION_NAME); + activity.SetTag("messaging.operation.type", PROCESS_OPERATION_TYPE); + activity.SetTag("messaging.destination.name", destinationName); + activity.SetTag("messaging.destination.subscription.name", subscriptionName); + activity.SetTag("messaging.destination.template", $"{_topicName.TopicId}:{{subscriptionName}}"); + activity.SetTag("messaging.message.body.size", bodySize); + + if (!message.MessageId.IsNullOrEmpty()) + activity.SetTag("messaging.message.id", message.MessageId); + + if (!message.OrderingKey.IsNullOrEmpty()) + activity.SetTag("messaging.gcp_pubsub.message.ordering_key", message.OrderingKey); + + if (message.Attributes.TryGetValue(PubSubMessageAttributes.CORRELATION_ID, out var correlationId) && !correlationId.IsNullOrEmpty()) + activity.SetTag("messaging.message.conversation_id", correlationId); + + return activity; + } + + private IEnumerable ExtractTraceContextFromAttributes(IDictionary attributes, string key) + { + if (!attributes.TryGetValue(key, out var value)) return []; + + return [value]; + } + public async Task StopConsuming(CancellationToken cancellationToken) { var stopTasks = _subscriptions.Select(subscription => subscription.SubscriberClient.StopAsync(new SubscriberClient.ShutdownOptions(), CancellationToken.None)); diff --git a/BuildingBlocks/src/BuildingBlocks.Infrastructure/EventBus/GoogleCloudPubSub/EventBusGoogleCloudPubSub.Publisher.cs b/BuildingBlocks/src/BuildingBlocks.Infrastructure/EventBus/GoogleCloudPubSub/EventBusGoogleCloudPubSub.Publisher.cs index 647efdccb5..11cd223e75 100644 --- a/BuildingBlocks/src/BuildingBlocks.Infrastructure/EventBus/GoogleCloudPubSub/EventBusGoogleCloudPubSub.Publisher.cs +++ b/BuildingBlocks/src/BuildingBlocks.Infrastructure/EventBus/GoogleCloudPubSub/EventBusGoogleCloudPubSub.Publisher.cs @@ -2,13 +2,19 @@ using System.Text.Json; using Backbone.BuildingBlocks.Domain.Events; using Backbone.BuildingBlocks.Infrastructure.CorrelationIds; +using Backbone.Tooling.Extensions; using Google.Cloud.PubSub.V1; using Google.Protobuf; +using OpenTelemetry; +using OpenTelemetry.Context.Propagation; namespace Backbone.BuildingBlocks.Infrastructure.EventBus.GoogleCloudPubSub; public partial class EventBusGoogleCloudPubSub { + private const string PUBLISH_OPERATION_NAME = "publish"; + private const string SEND_OPERATION_TYPE = "send"; + public async Task Publish(DomainEvent @event) { var eventName = @event.GetEventName(); @@ -27,19 +33,58 @@ public async Task Publish(DomainEvent @event) } }; + using var activity = StartPublishActivity(message, eventName, messageBytes.Length); + try { var startedAt = Stopwatch.GetTimestamp(); var messageId = await _publisherClient.PublishAsync(message); - _logger.SuccessfullySentDomainEvent(messageId); + activity?.SetTag("messaging.message.id", messageId); _metrics.TrackEventPublishingDuration(startedAt); _metrics.IncrementNumberOfPublishedEvents(eventName); } - catch (Exception) + catch (Exception ex) { _metrics.IncrementNumberOfPublishingErrors(eventName); + activity?.AddException(ex); throw; } } + + private Activity? StartPublishActivity(PubsubMessage message, string eventName, int bodySize) + { + var destinationName = $"{_topicName.TopicId}:{eventName}"; + + var activity = EventBusDiagnostics.ACTIVITY_SOURCE.StartActivity($"{PUBLISH_OPERATION_NAME} {destinationName}", ActivityKind.Producer, Activity.Current?.Context ?? default); + + ActivityContext contextToInject = default; + + if (activity != null) + contextToInject = activity.Context; + else if (Activity.Current != null) + contextToInject = Activity.Current.Context; + + EventBusDiagnostics.PROPAGATOR.Inject(new PropagationContext(contextToInject, Baggage.Current), message.Attributes, InjectTraceContextIntoAttributes); + + if (activity == null) + return null; + + activity.SetTag("messaging.system", MESSAGING_SYSTEM); + activity.SetTag("messaging.operation.name", PUBLISH_OPERATION_NAME); + activity.SetTag("messaging.operation.type", SEND_OPERATION_TYPE); + activity.SetTag("messaging.destination.name", destinationName); + activity.SetTag("messaging.message.body.size", bodySize); + activity.SetTag("messaging.destination.template", $"{_topicName.TopicId}:{{eventName}}"); + + if (message.Attributes.TryGetValue(PubSubMessageAttributes.CORRELATION_ID, out var correlationId) && !correlationId.IsNullOrEmpty()) + activity.SetTag("messaging.message.conversation_id", correlationId); + + return activity; + } + + private void InjectTraceContextIntoAttributes(IDictionary attributes, string key, string value) + { + attributes[key] = value; + } } diff --git a/BuildingBlocks/src/BuildingBlocks.Infrastructure/EventBus/GoogleCloudPubSub/EventBusGoogleCloudPubSub.cs b/BuildingBlocks/src/BuildingBlocks.Infrastructure/EventBus/GoogleCloudPubSub/EventBusGoogleCloudPubSub.cs index 79e657b108..d9cb4e5bc7 100644 --- a/BuildingBlocks/src/BuildingBlocks.Infrastructure/EventBus/GoogleCloudPubSub/EventBusGoogleCloudPubSub.cs +++ b/BuildingBlocks/src/BuildingBlocks.Infrastructure/EventBus/GoogleCloudPubSub/EventBusGoogleCloudPubSub.cs @@ -13,6 +13,7 @@ public partial class EventBusGoogleCloudPubSub : IEventBus, IDisposable, IAsyncD { private const int SUBSCRIPTION_MINIMUM_BACKOFF = 2; private const int SUBSCRIPTION_MAXIMUM_BACKOFF = 120; + private const string MESSAGING_SYSTEM = "gcp_pubsub"; private static readonly TimeSpan MESSAGE_ACK_DEADLINE = 60.Seconds(); @@ -130,20 +131,3 @@ public Subscription(SubscriberClient subscriberClient, Type eventType, Type hand public Type HandlerType { get; } } } - -internal static partial class EventBusGoogleCloudPubSubLogs -{ - [LoggerMessage( - EventId = 830408, - EventName = "EventBusGoogleCloudPubSub.SuccessfullySentDomainEvent", - Level = LogLevel.Debug, - Message = "Successfully sent domain event with id '{messageId}'.")] - public static partial void SuccessfullySentDomainEvent(this ILogger logger, string messageId); - - [LoggerMessage( - EventId = 712382, - EventName = "EventBusGoogleCloudPubSub.ErrorHandlingMessage", - Level = LogLevel.Error, - Message = "Error handling message with context {exceptionSource}.")] - public static partial void ErrorHandlingMessage(this ILogger logger, string exceptionSource, Exception exception); -} diff --git a/BuildingBlocks/src/BuildingBlocks.Infrastructure/EventBus/RabbitMQ/EventBusRabbitMq.Consumer.cs b/BuildingBlocks/src/BuildingBlocks.Infrastructure/EventBus/RabbitMQ/EventBusRabbitMq.Consumer.cs index caef784981..c0ef9cb38e 100644 --- a/BuildingBlocks/src/BuildingBlocks.Infrastructure/EventBus/RabbitMQ/EventBusRabbitMq.Consumer.cs +++ b/BuildingBlocks/src/BuildingBlocks.Infrastructure/EventBus/RabbitMQ/EventBusRabbitMq.Consumer.cs @@ -7,6 +7,7 @@ using Backbone.Tooling.Extensions; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; +using OpenTelemetry; using RabbitMQ.Client; using RabbitMQ.Client.Events; @@ -14,6 +15,15 @@ namespace Backbone.BuildingBlocks.Infrastructure.EventBus.RabbitMQ; public partial class EventBusRabbitMq { + private const int HANDLER_RETRY_COUNT = 5; + private const string CALL_OPERATION_NAME = "call"; + private const string PROCESS_OPERATION_NAME = "consume"; + private const string PROCESS_OPERATION_TYPE = "process"; + + private readonly string _deadLetterExchangeName; + private readonly string _deadLetterQueueName; + private readonly SubscriptionManager _subscriptionManager = new(); + public async Task Subscribe() where TEvent : DomainEvent where THandler : IDomainEventHandler { var queueName = GetQueueName(); @@ -25,30 +35,67 @@ public async Task Subscribe() where TEvent : DomainEvent where _subscriptionManager.AddSubscription(consumer, queueName); } + private async Task EnsureDeadLetterQueueExists() + { + IChannel? channel = null; + + try + { + channel = await _channelPool.Get(); + + await channel.QueueDeclareAsync(_deadLetterQueueName, + durable: true, + exclusive: false, + autoDelete: false, + arguments: new Dictionary + { + { "x-queue-type", "quorum" }, + } + ); + + await channel.QueueBindAsync(_deadLetterQueueName, _deadLetterExchangeName, "#"); + + _logger.LogTrace("Successfully bound dead letter queue."); + } + finally + { + if (channel != null) + _channelPool.Return(channel); + } + } + private async Task CreateQueue(string queueName) where TEvent : DomainEvent { var eventName = typeof(TEvent).GetEventName(); - var channel = await _channelPool.Get(); + IChannel? channel = null; - await channel.QueueDeclareAsync(queueName, - durable: true, - exclusive: false, - autoDelete: false, - arguments: new Dictionary - { - { "x-queue-type", "quorum" }, - { "x-delivery-limit", HANDLER_RETRY_COUNT }, - { "x-dead-letter-exchange", _deadLetterExchangeName }, - { "x-dead-letter-routing-key", $"dead.routing.{eventName}" } - } - ); + try + { + channel = await _channelPool.Get(); - await channel.QueueBindAsync(queueName, _exchangeName, eventName); + await channel.QueueDeclareAsync(queueName, + durable: true, + exclusive: false, + autoDelete: false, + arguments: new Dictionary + { + { "x-queue-type", "quorum" }, + { "x-delivery-limit", HANDLER_RETRY_COUNT }, + { "x-dead-letter-exchange", _deadLetterExchangeName }, + { "x-dead-letter-routing-key", $"dead.routing.{eventName}" } + } + ); - _logger.LogTrace("Successfully bound queue '{QueueName}' to event '{EventName}'.", queueName, eventName); + await channel.QueueBindAsync(queueName, _exchangeName, eventName); - _channelPool.Return(channel); + _logger.LogTrace("Successfully bound queue '{QueueName}' to event '{EventName}'.", queueName, eventName); + } + finally + { + if (channel != null) + _channelPool.Return(channel); + } } private async Task CreateConsumer() where TEvent : DomainEvent where THandler : IDomainEventHandler @@ -58,10 +105,14 @@ private async Task CreateConsumer( consumer.ReceivedAsync += async (_, eventArgs) => { - var eventName = eventArgs.RoutingKey; + var queueName = GetQueueName(); + + using var activity = StartProcessActivity(eventArgs, queueName, eventArgs.BasicProperties, eventArgs.Body.Length); var message = Encoding.UTF8.GetString(eventArgs.Body.ToArray()); + activity?.AddEvent(new ActivityEvent("enmeshed.backbone.event_bus.consumer.message_decoded")); + try { var correlationId = eventArgs.BasicProperties.CorrelationId; @@ -76,10 +127,10 @@ private async Task CreateConsumer( } catch (Exception ex) { + activity?.AddException(ex); + await channel.BasicRejectAsync(eventArgs.DeliveryTag, true); _metrics.IncrementNumberOfProcessingErrors(GetQueueName()); - - _logger.ErrorWhileProcessingDomainEvent(eventName, ex); } }; @@ -88,10 +139,7 @@ private async Task CreateConsumer( private async Task ProcessEvent(string message) where TEvent : DomainEvent where THandler : IDomainEventHandler { - var eventType = typeof(TEvent); - var eventName = eventType.GetEventName(); - - _logger.LogDebug("Processing RabbitMQ event: '{EventName}'", eventName); + Activity.Current?.AddEvent(new ActivityEvent("enmeshed.backbone.event_bus.consumer.start_processing")); var domainEvent = JsonSerializer.Deserialize(message); @@ -102,15 +150,43 @@ private async Task ProcessEvent(string message) where TEvent : if (scope.ServiceProvider.GetService(handlerType) is not IDomainEventHandler handler) throw new Exception("Domain event handler could not be resolved from dependency container or it does not implement IDomainEventHandler."); - var concreteType = typeof(IDomainEventHandler<>).MakeGenericType(eventType); + Activity.Current?.AddEvent(new ActivityEvent("enmeshed.backbone.event_bus.consumer.handler_resolved")); var startedAt = Stopwatch.GetTimestamp(); - await (Task)concreteType.GetMethod("Handle")!.Invoke(handler, [domainEvent])!; + using (var handlerActivity = StartHandlerActivity()) + { + try + { + await (Task)handlerType.GetMethod("Handle")!.Invoke(handler, [domainEvent])!; + } + catch (Exception ex) + { + handlerActivity?.AddException(ex); + throw; + } + } + _metrics.TrackEventProcessingDuration(startedAt, GetQueueName()); _metrics.IncrementNumberOfHandledEvents(GetQueueName()); } + private Activity? StartHandlerActivity() where TEvent : DomainEvent where THandler : IDomainEventHandler + { + var handlerType = typeof(THandler); + var eventType = typeof(TEvent); + var activity = EventBusDiagnostics.ACTIVITY_SOURCE.StartActivity($"{CALL_OPERATION_NAME} {handlerType.FullName}", ActivityKind.Internal); + + if (activity == null) + return null; + + activity.SetTag("event_bus.event.name", eventType.GetEventName()); + activity.SetTag("event_bus.event.type", eventType.FullName); + activity.SetTag("event_bus.handler.type", handlerType.FullName); + + return activity; + } + public async Task StartConsuming(CancellationToken cancellationToken) { foreach (var subscription in _subscriptionManager) @@ -130,4 +206,53 @@ public async Task StopConsuming(CancellationToken cancellationToken) } } } + + private Activity? StartProcessActivity(BasicDeliverEventArgs eventArgs, string queueName, IReadOnlyBasicProperties properties, int bodySize) + { + var parentContext = EventBusDiagnostics.PROPAGATOR.Extract(default, + eventArgs.BasicProperties, + ExtractTraceContextFromBasicProperties); + Baggage.Current = parentContext.Baggage; + + var destinationName = $"{_exchangeName}.{queueName}"; + var activity = EventBusDiagnostics.ACTIVITY_SOURCE.StartActivity($"{PROCESS_OPERATION_NAME} {destinationName}", ActivityKind.Consumer, parentContext.ActivityContext); + + if (activity == null) + return null; + + activity.SetTag("messaging.system", MESSAGING_SYSTEM); + activity.SetTag("messaging.operation.name", PROCESS_OPERATION_NAME); + activity.SetTag("messaging.operation.type", PROCESS_OPERATION_TYPE); + activity.SetTag("messaging.destination.name", destinationName); + activity.SetTag("messaging.destination.template", $"{_exchangeName}:{{queueName}}"); + activity.SetTag("messaging.rabbitmq.destination.routing_key", eventArgs.RoutingKey); + activity.SetTag("messaging.rabbitmq.message.delivery_tag", eventArgs.DeliveryTag); + activity.SetTag("messaging.message.body.size", bodySize); + + if (!properties.MessageId.IsNullOrEmpty()) + activity.SetTag("messaging.message.id", properties.MessageId); + + if (!properties.CorrelationId.IsNullOrEmpty()) + activity.SetTag("messaging.message.conversation_id", properties.CorrelationId); + + return activity; + } + + private IEnumerable ExtractTraceContextFromBasicProperties(IReadOnlyBasicProperties props, string key) + { + if (props.Headers == null || !props.Headers.TryGetValue(key, out var value)) return []; + + if (value is byte[] bytes) return [Encoding.UTF8.GetString(bytes)]; + + return []; + } + + public static string GetQueueName() where TEvent : DomainEvent where THandler : IDomainEventHandler + { + var eventHandlerFullName = typeof(THandler).FullName!; + + var moduleName = eventHandlerFullName.Split('.').ElementAt(2); + + return $"{moduleName}.{typeof(TEvent).GetEventName()}"; + } } diff --git a/BuildingBlocks/src/BuildingBlocks.Infrastructure/EventBus/RabbitMQ/EventBusRabbitMq.Publisher.cs b/BuildingBlocks/src/BuildingBlocks.Infrastructure/EventBus/RabbitMQ/EventBusRabbitMq.Publisher.cs index 4a89b25b16..e3f4bbb153 100644 --- a/BuildingBlocks/src/BuildingBlocks.Infrastructure/EventBus/RabbitMQ/EventBusRabbitMq.Publisher.cs +++ b/BuildingBlocks/src/BuildingBlocks.Infrastructure/EventBus/RabbitMQ/EventBusRabbitMq.Publisher.cs @@ -3,53 +3,102 @@ using System.Text.Json; using Backbone.BuildingBlocks.Domain.Events; using Backbone.BuildingBlocks.Infrastructure.CorrelationIds; -using Microsoft.Extensions.Logging; +using OpenTelemetry; +using OpenTelemetry.Context.Propagation; +using Polly.Retry; using RabbitMQ.Client; namespace Backbone.BuildingBlocks.Infrastructure.EventBus.RabbitMQ; public partial class EventBusRabbitMq { + private const int PUBLISH_RETRY_COUNT = 6; + private const string PUBLISH_OPERATION_NAME = "publish"; + private const string SEND_OPERATION_TYPE = "send"; + + private readonly AsyncRetryPolicy _publishRetryPolicy; + public async Task Publish(DomainEvent @event) { var eventName = @event.GetEventName(); - - _logger.LogInformation("Creating RabbitMQ channel to publish a '{EventName}'.", eventName); - var message = JsonSerializer.Serialize(@event, @event.GetType()); - var body = Encoding.UTF8.GetBytes(message); _metrics.TrackHandledMessageSize(body.Length); - await _publishRetryPolicy.ExecuteAsync(async () => + var properties = new BasicProperties { - _logger.LogDebug("Publishing a '{EventName}' event to RabbitMQ.", eventName); + DeliveryMode = DeliveryModes.Persistent, + MessageId = @event.DomainEventId, + CorrelationId = CustomLogContext.GetCorrelationId() + }; + using var activity = StartPublishActivity(properties, @event.DomainEventId, eventName, body.Length); - var channel = await _channelPool.Get(); - var properties = new BasicProperties - { - DeliveryMode = DeliveryModes.Persistent, - MessageId = @event.DomainEventId, - CorrelationId = CustomLogContext.GetCorrelationId() - }; + IChannel? channel = null; + await _publishRetryPolicy.ExecuteAsync(async () => + { try { + channel = await _channelPool.Get(); + + activity?.AddEvent(new ActivityEvent("enmeshed.backbone.event_bus.publisher.acquired_channel_for_publish")); + var startedAt = Stopwatch.GetTimestamp(); await channel.BasicPublishAsync(_exchangeName, eventName, mandatory: false, properties, body); - _logger.PublishedDomainEvent(); _metrics.TrackEventPublishingDuration(startedAt); _metrics.IncrementNumberOfPublishedEvents(eventName); } - catch (Exception) + catch (Exception ex) { _metrics.IncrementNumberOfPublishingErrors(eventName); + Activity.Current?.AddException(ex); throw; } + finally + { + if (channel != null) + _channelPool.Return(channel); - _channelPool.Return(channel); + activity?.AddEvent(new ActivityEvent("enmeshed.backbone.event_bus.publisher.returned_channel")); + } }); } + + private Activity? StartPublishActivity(BasicProperties properties, string messageId, string eventName, int bodySize) + { + var destinationName = $"{_exchangeName}:{eventName}"; + + var activity = EventBusDiagnostics.ACTIVITY_SOURCE.StartActivity($"{PUBLISH_OPERATION_NAME} {destinationName}", ActivityKind.Producer, Activity.Current?.Context ?? default); + + ActivityContext contextToInject = default; + + if (activity != null) + contextToInject = activity.Context; + else if (Activity.Current != null) + contextToInject = Activity.Current.Context; + + EventBusDiagnostics.PROPAGATOR.Inject(new PropagationContext(contextToInject, Baggage.Current), properties, InjectTraceContextIntoProperties); + + if (activity == null) + return null; + + activity.SetTag("messaging.system", MESSAGING_SYSTEM); + activity.SetTag("messaging.operation.name", PUBLISH_OPERATION_NAME); + activity.SetTag("messaging.operation.type", SEND_OPERATION_TYPE); + activity.SetTag("messaging.destination.name", destinationName); + activity.SetTag("messaging.message.id", messageId); + activity.SetTag("messaging.message.body.size", bodySize); + activity.SetTag("messaging.destination.template", $"{_exchangeName}:{{eventName}}"); + activity.SetTag("messaging.rabbitmq.destination.routing_key", eventName); + + return activity; + } + + private void InjectTraceContextIntoProperties(IBasicProperties properties, string key, string value) + { + properties.Headers ??= new Dictionary(); + properties.Headers[key] = value; + } } diff --git a/BuildingBlocks/src/BuildingBlocks.Infrastructure/EventBus/RabbitMQ/EventBusRabbitMq.cs b/BuildingBlocks/src/BuildingBlocks.Infrastructure/EventBus/RabbitMQ/EventBusRabbitMq.cs index aca59ab97d..4eaed01469 100644 --- a/BuildingBlocks/src/BuildingBlocks.Infrastructure/EventBus/RabbitMQ/EventBusRabbitMq.cs +++ b/BuildingBlocks/src/BuildingBlocks.Infrastructure/EventBus/RabbitMQ/EventBusRabbitMq.cs @@ -1,10 +1,8 @@ using System.Net.Sockets; using Backbone.BuildingBlocks.Application.Abstractions.Infrastructure.EventBus; -using Backbone.BuildingBlocks.Domain.Events; using Backbone.Tooling.Extensions; using Microsoft.Extensions.Logging; using Polly; -using Polly.Retry; using RabbitMQ.Client; using RabbitMQ.Client.Exceptions; @@ -12,9 +10,9 @@ namespace Backbone.BuildingBlocks.Infrastructure.EventBus.RabbitMQ; public partial class EventBusRabbitMq : IEventBus, IDisposable { - private const int PUBLISH_RETRY_COUNT = 6; private const int CONNECTION_RETRY_COUNT = 6; - private const int HANDLER_RETRY_COUNT = 5; + + private const string MESSAGING_SYSTEM = "rabbitmq"; private readonly ILogger _logger; private readonly IServiceProvider _serviceProvider; @@ -24,10 +22,6 @@ public partial class EventBusRabbitMq : IEventBus, IDisposable private readonly string _exchangeName; private readonly EventBusMetrics _metrics; - private readonly string _deadLetterExchangeName; - private readonly string _deadLetterQueueName; - private readonly SubscriptionManager _subscriptionManager = new(); - private readonly AsyncRetryPolicy _publishRetryPolicy; private EventBusRabbitMq(IConnection connection, ILogger logger, IServiceProvider serviceProvider, string exchangeName, EventBusMetrics metrics) { @@ -44,8 +38,7 @@ private EventBusRabbitMq(IConnection connection, ILogger logge .Or() .Or() .WaitAndRetryAsync(PUBLISH_RETRY_COUNT, - _ => 2.Seconds(), - (ex, _) => _logger.ErrorOnPublish(ex)); + _ => 2.Seconds()); _connection.ConnectionShutdownAsync += (_, args) => { @@ -94,50 +87,24 @@ private async Task Init() private async Task EnsureExchangeExists(string exchangeName, string exchangeType = "direct") { + IChannel? channel = null; + try { - var channel = await _channelPool.Get(); - await channel.ExchangeDeclarePassiveAsync(exchangeName); - _channelPool.Return(channel); + channel = await _channelPool.Get(); + + await channel.ExchangeDeclareAsync(exchangeName, exchangeType, durable: true); } - catch (OperationInterruptedException ex) + catch (Exception ex) { - if (ex.ShutdownReason?.ReplyCode == 404) - { - try - { - var channel = await _channelPool.Get(); - await channel.ExchangeDeclareAsync(exchangeName, exchangeType, durable: true); - _channelPool.Return(channel); - } - catch (Exception) - { - _logger.LogCritical("The exchange '{ExchangeName}' does not exist and could not be created.", exchangeName); - throw new Exception($"The exchange '{exchangeName}' does not exist and could not be created."); - } - } + _logger.LogCritical(ex, "The exchange '{ExchangeName}' does not exist and could not be created.", exchangeName); + throw new Exception($"The exchange '{exchangeName}' does not exist and could not be created.", ex); + } + finally + { + if (channel != null) + _channelPool.Return(channel); } - } - - private async Task EnsureDeadLetterQueueExists() - { - var channel = await _channelPool.Get(); - - await channel.QueueDeclareAsync(_deadLetterQueueName, - durable: true, - exclusive: false, - autoDelete: false, - arguments: new Dictionary - { - { "x-queue-type", "quorum" }, - } - ); - - await channel.QueueBindAsync(_deadLetterQueueName, _deadLetterExchangeName, "#"); - - _logger.LogTrace("Successfully bound dead letter queue."); - - _channelPool.Return(channel); } public void Dispose() @@ -145,15 +112,6 @@ public void Dispose() _channelPool.Dispose(); } - public static string GetQueueName() where TEvent : DomainEvent where THandler : IDomainEventHandler - { - var eventHandlerFullName = typeof(THandler).FullName!; - - var moduleName = eventHandlerFullName.Split('.').ElementAt(2); - - return $"{moduleName}.{typeof(TEvent).GetEventName()}"; - } - public bool IsConnected => _connection.IsOpen; } @@ -169,7 +127,7 @@ internal static partial class EventBusRabbitMqLogs [LoggerMessage( EventId = 900001, EventName = "EventBusRabbitMQ.ConnectionShutdown", - Level = LogLevel.Error, + Level = LogLevel.Warning, Message = "A shutdown of the connection was initiated. Initiator: {shutdownInitiator}, ReplyCode: {replyCode}, ReplyText: {replyText}")] public static partial void ConnectionShutdown(this ILogger logger, ShutdownInitiator shutdownInitiator, ushort replyCode, string replyText); @@ -186,25 +144,4 @@ internal static partial class EventBusRabbitMqLogs Level = LogLevel.Information, Message = "The connection was successfully recovered.")] public static partial void RecoverySucceeded(this ILogger logger); - - [LoggerMessage( - EventId = 411326, - EventName = "EventBusRabbitMQ.ErrorOnPublish", - Level = LogLevel.Warning, - Message = "There was an error while trying to publish an event.")] - public static partial void ErrorOnPublish(this ILogger logger, Exception exception); - - [LoggerMessage( - EventId = 585231, - EventName = "EventBusRabbitMQ.PublishedDomainEvent", - Level = LogLevel.Debug, - Message = "Successfully published the event.")] - public static partial void PublishedDomainEvent(this ILogger logger); - - [LoggerMessage( - EventId = 702822, - EventName = "EventBusRabbitMQ.ErrorWhileProcessingDomainEvent", - Level = LogLevel.Error, - Message = "An error occurred while processing the domain event of type '{eventName}'.")] - public static partial void ErrorWhileProcessingDomainEvent(this ILogger logger, string eventName, Exception exception); } diff --git a/BuildingBlocks/src/BuildingBlocks.Infrastructure/Persistence/BlobStorage/AzureStorageAccount/AzureStorageAccountContainerClientFactory.cs b/BuildingBlocks/src/BuildingBlocks.Infrastructure/Persistence/BlobStorage/AzureStorageAccount/AzureStorageAccountContainerClientFactory.cs index a650447f63..b832333223 100644 --- a/BuildingBlocks/src/BuildingBlocks.Infrastructure/Persistence/BlobStorage/AzureStorageAccount/AzureStorageAccountContainerClientFactory.cs +++ b/BuildingBlocks/src/BuildingBlocks.Infrastructure/Persistence/BlobStorage/AzureStorageAccount/AzureStorageAccountContainerClientFactory.cs @@ -1,4 +1,3 @@ -using Azure; using Azure.Storage.Blobs; using Azure.Storage.Blobs.Models; using Microsoft.Extensions.Logging; @@ -39,17 +38,9 @@ public BlobContainerClient GetContainerClient(string containerName) private BlobContainerClient CreateContainerClient(string containerName) { var newContainer = new BlobContainerClient(_configuration.ConnectionString, containerName); - newContainer.CreateIfNotExists(); - try - { - newContainer.SetAccessPolicy(PublicAccessType.Blob); - } - catch (RequestFailedException ex) - { - _logger.LogInformation(ex, - "An error was thrown while trying to set the access policy on the BlobContainerClient. This error is ignored."); - } + if (!newContainer.Exists()) + newContainer.Create(PublicAccessType.Blob); return newContainer; } diff --git a/BuildingBlocks/src/BuildingBlocks.Infrastructure/Persistence/BlobStorage/S3/S3BlobStorage.cs b/BuildingBlocks/src/BuildingBlocks.Infrastructure/Persistence/BlobStorage/S3/S3BlobStorage.cs index 8262b9e68e..4a78e65b73 100644 --- a/BuildingBlocks/src/BuildingBlocks.Infrastructure/Persistence/BlobStorage/S3/S3BlobStorage.cs +++ b/BuildingBlocks/src/BuildingBlocks.Infrastructure/Persistence/BlobStorage/S3/S3BlobStorage.cs @@ -122,8 +122,6 @@ private async Task UploadChangedBlobs() foreach (var blob in changedBlobs) { - await EnsureKeyDoesNotExist(blob.Folder, blob.Name); - using var memoryStream = new MemoryStream(blob.Content); try @@ -134,7 +132,8 @@ private async Task UploadChangedBlobs() { InputStream = memoryStream, Key = blob.Name, - BucketName = blob.Folder + BucketName = blob.Folder, + IfNoneMatch = "*" }; var transferUtility = new TransferUtility(_s3Client); @@ -154,26 +153,6 @@ private async Task UploadChangedBlobs() } } - private async Task EnsureKeyDoesNotExist(string folder, string key) - { - try - { - var request = new GetObjectRequest - { - BucketName = folder, - Key = key - }; - - await _s3Client.GetObjectAsync(request); - - _logger.LogError("A blob with key '{blobName}' already exists.", key); - throw new BlobAlreadyExistsException(key); - } - catch (AmazonS3Exception ex) when (ex.StatusCode == HttpStatusCode.NotFound) - { - } - } - private async Task DeleteRemovedBlobs() { _logger.LogTrace("Deleting '{removedBlobsCount}' blobs...", _removedBlobs.Count); diff --git a/BuildingBlocks/src/BuildingBlocks.Infrastructure/packages.lock.json b/BuildingBlocks/src/BuildingBlocks.Infrastructure/packages.lock.json index 2a24f5193a..d303f57b00 100644 --- a/BuildingBlocks/src/BuildingBlocks.Infrastructure/packages.lock.json +++ b/BuildingBlocks/src/BuildingBlocks.Infrastructure/packages.lock.json @@ -214,6 +214,12 @@ "Npgsql": "10.0.3" } }, + "OpenTelemetry.Api": { + "type": "Direct", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" + }, "Polly": { "type": "Direct", "requested": "[8.7.0, 8.7.0]", diff --git a/BuildingBlocks/src/UnitTestTools/packages.lock.json b/BuildingBlocks/src/UnitTestTools/packages.lock.json index a22c236624..54a1a66468 100644 --- a/BuildingBlocks/src/UnitTestTools/packages.lock.json +++ b/BuildingBlocks/src/UnitTestTools/packages.lock.json @@ -692,6 +692,7 @@ "Microsoft.Extensions.Identity.Core": "[10.0.10, 10.0.10]", "Microsoft.Extensions.Logging": "[10.0.10, 10.0.10]", "Npgsql.EntityFrameworkCore.PostgreSQL": "[10.0.3, 10.0.3]", + "OpenTelemetry.Api": "[1.17.0, )", "Polly": "[8.7.0, 8.7.0]", "RabbitMQ.Client": "[7.2.1, 7.2.1]", "Serilog": "[4.4.0, 4.4.0]" @@ -1005,6 +1006,12 @@ "Npgsql": "10.0.3" } }, + "OpenTelemetry.Api": { + "type": "CentralTransitive", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" + }, "RabbitMQ.Client": { "type": "CentralTransitive", "requested": "[7.2.1, 7.2.1]", diff --git a/BuildingBlocks/test/BuildingBlocks.API.Tests/BuildingBlocks.API.Tests.csproj b/BuildingBlocks/test/BuildingBlocks.API.Tests/BuildingBlocks.API.Tests.csproj index 55436455cd..e1c5dcf8ee 100644 --- a/BuildingBlocks/test/BuildingBlocks.API.Tests/BuildingBlocks.API.Tests.csproj +++ b/BuildingBlocks/test/BuildingBlocks.API.Tests/BuildingBlocks.API.Tests.csproj @@ -11,6 +11,7 @@ + diff --git a/BuildingBlocks/test/BuildingBlocks.API.Tests/Mvc/Middleware/UserContextBaggageMiddlewareTests.cs b/BuildingBlocks/test/BuildingBlocks.API.Tests/Mvc/Middleware/UserContextBaggageMiddlewareTests.cs new file mode 100644 index 0000000000..3b357bee89 --- /dev/null +++ b/BuildingBlocks/test/BuildingBlocks.API.Tests/Mvc/Middleware/UserContextBaggageMiddlewareTests.cs @@ -0,0 +1,107 @@ +using Backbone.BuildingBlocks.API.Mvc.Middleware; +using Backbone.BuildingBlocks.Application.Abstractions.Exceptions; +using Backbone.BuildingBlocks.Application.Abstractions.Infrastructure.UserContext; +using Backbone.DevelopmentKit.Identity.ValueObjects; +using Microsoft.AspNetCore.Http; +using OpenTelemetry; + +namespace Backbone.BuildingBlocks.API.Tests.Mvc.Middleware; + +public class UserContextBaggageMiddlewareTests +{ + [Fact] + public async Task InvokeAsync_SetsUserContextValuesAsBaggage() + { + var identityAddress = CreateRandomIdentityAddress(); + var deviceId = CreateRandomDeviceId(); + var userContext = new TestUserContext(identityAddress, deviceId, "client-id", "username"); + var previousBaggage = Baggage.Current; + + try + { + Baggage.ClearBaggage(); + + var middleware = new UserContextBaggageMiddleware(_ => + { + Baggage.GetBaggage("deviceId").ShouldBe(deviceId.Value); + Baggage.GetBaggage("identityAddress").ShouldBe(identityAddress.Value); + Baggage.GetBaggage("clientId").ShouldBe("client-id"); + Baggage.GetBaggage("username").ShouldBe("username"); + + return Task.CompletedTask; + }); + + await middleware.InvokeAsync(new DefaultHttpContext(), userContext); + } + finally + { + Baggage.Current = previousBaggage; + } + } + + private class TestUserContext : IUserContext + { + private readonly IdentityAddress? _address; + private readonly DeviceId? _deviceId; + private readonly string? _clientId; + private readonly string? _username; + + public TestUserContext(IdentityAddress? address, DeviceId? deviceId, string? clientId, string? username) + { + _address = address; + _deviceId = deviceId; + _clientId = clientId; + _username = username; + } + + public IdentityAddress GetAddress() + { + return GetAddressOrNull() ?? throw new NotFoundException(); + } + + public IdentityAddress? GetAddressOrNull() + { + return _address; + } + + public DeviceId GetDeviceId() + { + return GetDeviceIdOrNull() ?? throw new NotFoundException(); + } + + public DeviceId? GetDeviceIdOrNull() + { + return _deviceId; + } + + public string GetUserId() + { + return GetUserIdOrNull() ?? throw new NotFoundException(); + } + + public string? GetUserIdOrNull() + { + return null; + } + + public string GetUsername() + { + return GetUsernameOrNull() ?? throw new NotFoundException(); + } + + public string? GetUsernameOrNull() + { + return _username; + } + + public string GetClientId() + { + return GetClientIdOrNull() ?? throw new NotFoundException(); + } + + public string? GetClientIdOrNull() + { + return _clientId; + } + } +} diff --git a/BuildingBlocks/test/BuildingBlocks.API.Tests/UnitTest1.cs b/BuildingBlocks/test/BuildingBlocks.API.Tests/UnitTest1.cs deleted file mode 100644 index 792c7d0599..0000000000 --- a/BuildingBlocks/test/BuildingBlocks.API.Tests/UnitTest1.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Xunit; - -namespace Backbone.BuildingBlocks.API.Tests; - -public class UnitTest1 -{ - [Fact] - public void Test1() - { - } -} diff --git a/BuildingBlocks/test/BuildingBlocks.API.Tests/packages.lock.json b/BuildingBlocks/test/BuildingBlocks.API.Tests/packages.lock.json index 9edb155c25..adf5bb76e0 100644 --- a/BuildingBlocks/test/BuildingBlocks.API.Tests/packages.lock.json +++ b/BuildingBlocks/test/BuildingBlocks.API.Tests/packages.lock.json @@ -18,6 +18,16 @@ "Microsoft.TestPlatform.TestHost": "18.8.1" } }, + "Shouldly": { + "type": "Direct", + "requested": "[4.3.0, 4.3.0]", + "resolved": "4.3.0", + "contentHash": "sDetrWXrl6YXZ4HeLsdBoNk3uIa7K+V4uvIJ+cqdRa5DrFxeTED7VkjoxCuU1kJWpUuBDZz2QXFzSxBtVXLwRQ==", + "dependencies": { + "DiffEngine": "11.3.0", + "EmptyFiles": "4.4.0" + } + }, "xunit.v3.mtp-v2": { "type": "Direct", "requested": "[3.2.2, 3.2.2]", @@ -90,6 +100,20 @@ "System.Diagnostics.EventLog": "6.0.0" } }, + "DiffEngine": { + "type": "Transitive", + "resolved": "11.3.0", + "contentHash": "k0ZgZqd09jLZQjR8FyQbSQE86Q7QZnjEzq1LPHtj1R2AoWO8sjV5x+jlSisL7NZAbUOI4y+7Bog8gkr9WIRBGw==", + "dependencies": { + "EmptyFiles": "4.4.0", + "System.Management": "6.0.1" + } + }, + "EmptyFiles": { + "type": "Transitive", + "resolved": "4.4.0", + "contentHash": "gwJEfIGS7FhykvtZoscwXj/XwW+mJY6UbAZk+qtLKFUGWC95kfKXnj8VkxsZQnWBxJemM/q664rGLN5nf+OHZw==" + }, "Google.Api.CommonProtos": { "type": "Transitive", "resolved": "2.17.0", @@ -317,6 +341,20 @@ "resolved": "10.0.10", "contentHash": "2gLDordUCGf3aNOOuqtTbP5mxhiP9nk6TnvGiE3RnqT891O+Zf/qKu1PIREubs1M16A0SImr4vULBfU5BTDs1Q==" }, + "Microsoft.EntityFrameworkCore.Sqlite.Core": { + "type": "Transitive", + "resolved": "10.0.10", + "contentHash": "YbVWMIouzwTKBiLms8boa7xeRT88wI14R1msv3XExFk9n0/sa8nU7MwDa1CKtfLGMJs7O7QWuS9/xhcQ72AD2A==", + "dependencies": { + "Microsoft.Data.Sqlite.Core": "10.0.10", + "Microsoft.EntityFrameworkCore.Relational": "10.0.10", + "Microsoft.Extensions.Caching.Memory": "10.0.10", + "Microsoft.Extensions.Configuration.Abstractions": "10.0.10", + "Microsoft.Extensions.DependencyModel": "10.0.10", + "Microsoft.Extensions.Logging": "10.0.10", + "SQLitePCLRaw.core": "2.1.11" + } + }, "Microsoft.EntityFrameworkCore.SqlServer.Abstractions": { "type": "Transitive", "resolved": "10.0.3", @@ -432,6 +470,11 @@ "Microsoft.Extensions.Hosting.Abstractions": "10.0.10" } }, + "Microsoft.Extensions.DependencyModel": { + "type": "Transitive", + "resolved": "10.0.10", + "contentHash": "rfZA1RjR021RPqSmIPovfz2aOd79TGqJ9BengbjnzIISOVwjLmuSDnhCMmiY/1c6iYvGolQ1iNGzkav0u11XEA==" + }, "Microsoft.Extensions.Diagnostics": { "type": "Transitive", "resolved": "10.0.10", @@ -992,11 +1035,6 @@ "OpenTelemetry.Api.ProviderBuilderExtensions": "1.17.0" } }, - "OpenTelemetry.Api": { - "type": "Transitive", - "resolved": "1.17.0", - "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" - }, "OpenTelemetry.Api.ProviderBuilderExtensions": { "type": "Transitive", "resolved": "1.17.0", @@ -1072,6 +1110,28 @@ "Serilog": "4.2.0" } }, + "SQLitePCLRaw.bundle_e_sqlite3": { + "type": "Transitive", + "resolved": "2.1.11", + "contentHash": "DC4nA7yWnf4UZdgJDF+9Mus4/cb0Y3Sfgi3gDnAoKNAIBwzkskNAbNbyu+u4atT0ruVlZNJfwZmwiEwE5oz9LQ==", + "dependencies": { + "SQLitePCLRaw.lib.e_sqlite3": "2.1.11", + "SQLitePCLRaw.provider.e_sqlite3": "2.1.11" + } + }, + "SQLitePCLRaw.core": { + "type": "Transitive", + "resolved": "2.1.11", + "contentHash": "PK0GLFkfhZzLQeR3PJf71FmhtHox+U3vcY6ZtswoMjrefkB9k6ErNJEnwXqc5KgXDSjige2XXrezqS39gkpQKA==" + }, + "SQLitePCLRaw.provider.e_sqlite3": { + "type": "Transitive", + "resolved": "2.1.11", + "contentHash": "Y/0ZkR+r0Cg3DQFuCl1RBnv/tmxpIZRU3HUvelPw6MVaKHwYYR8YNvgs0vuNuXCMvlyJ+Fh88U1D4tah1tt6qw==", + "dependencies": { + "SQLitePCLRaw.core": "2.1.11" + } + }, "Swashbuckle.AspNetCore.Swagger": { "type": "Transitive", "resolved": "10.2.3", @@ -1244,9 +1304,11 @@ "DotNetDiag.HealthChecks.SqlServer": "[10.0.10, 10.0.10]", "Microsoft.EntityFrameworkCore": "[10.0.10, 10.0.10]", "Microsoft.EntityFrameworkCore.Relational": "[10.0.10, 10.0.10]", - "OpenTelemetry.Exporter.Prometheus.AspNetCore": "[1.11.2-beta.1, 1.11.2-beta.1]", + "OpenTelemetry.Exporter.Console": "[1.17.0, )", + "OpenTelemetry.Exporter.OpenTelemetryProtocol": "[1.17.0, )", "OpenTelemetry.Extensions.Hosting": "[1.17.0, 1.17.0]", "OpenTelemetry.Instrumentation.AspNetCore": "[1.17.0, 1.17.0]", + "OpenTelemetry.Instrumentation.EntityFrameworkCore": "[1.17.0-beta.1, )", "OpenTelemetry.Instrumentation.Http": "[1.17.0, 1.17.0]", "OpenTelemetry.Instrumentation.Runtime": "[1.17.0, 1.17.0]", "Polly": "[8.7.0, 8.7.0]", @@ -1307,6 +1369,7 @@ "Microsoft.Extensions.Identity.Core": "[10.0.10, 10.0.10]", "Microsoft.Extensions.Logging": "[10.0.10, 10.0.10]", "Npgsql.EntityFrameworkCore.PostgreSQL": "[10.0.3, 10.0.3]", + "OpenTelemetry.Api": "[1.17.0, )", "Polly": "[8.7.0, 8.7.0]", "RabbitMQ.Client": "[7.2.1, 7.2.1]", "Serilog": "[4.4.0, 4.4.0]" @@ -1398,6 +1461,20 @@ "Microsoft.Extensions.Options": "[10.0.10, 10.0.10]" } }, + "Backbone.UnitTestTools": { + "type": "Project", + "dependencies": { + "Backbone.BuildingBlocks.Infrastructure": "[1.0.0, )", + "Backbone.DevelopmentKit.Identity": "[1.0.0, )", + "Backbone.Tooling": "[1.0.0, )", + "FakeItEasy": "[9.0.1, 9.0.1]", + "FluentValidation": "[12.1.1, 12.1.1]", + "MediatR": "[12.5.0, 12.5.0]", + "Microsoft.EntityFrameworkCore.Sqlite": "[10.0.10, 10.0.10]", + "Polly": "[8.7.0, 8.7.0]", + "Shouldly": "[4.3.0, 4.3.0]" + } + }, "Asp.Versioning.Mvc": { "type": "CentralTransitive", "requested": "[10.0.1, 10.0.1]", @@ -1523,6 +1600,15 @@ "NetTopologySuite.IO.SqlServerBytes": "2.1.0" } }, + "FakeItEasy": { + "type": "CentralTransitive", + "requested": "[9.0.1, 9.0.1]", + "resolved": "9.0.1", + "contentHash": "cqM6hKjoAmjuh+GzKLX7gcqCDownqffmQ3KSBMdFowCZgwQMXpu1jlsJE649FsrMF5Ea5kYpuokGTuOaUrz/2w==", + "dependencies": { + "Castle.Core": "5.2.1" + } + }, "FirebaseAdmin": { "type": "CentralTransitive", "requested": "[3.6.0, 3.6.0]", @@ -1604,6 +1690,15 @@ "Microsoft.Extensions.Identity.Stores": "10.0.10" } }, + "Microsoft.Data.Sqlite.Core": { + "type": "CentralTransitive", + "requested": "[10.0.10, 10.0.10]", + "resolved": "10.0.10", + "contentHash": "TPCs0ldm7AWqcKmp6f/Xr+14sat7hx4rHfRlS4RgCURBH2thEWbAKEyX7cCWr63zVJVOJIJZTg2cBiUXa8ys6g==", + "dependencies": { + "SQLitePCLRaw.core": "2.1.11" + } + }, "Microsoft.EntityFrameworkCore": { "type": "CentralTransitive", "requested": "[10.0.10, 10.0.10]", @@ -1646,6 +1741,21 @@ "Microsoft.Extensions.Logging": "10.0.10" } }, + "Microsoft.EntityFrameworkCore.Sqlite": { + "type": "CentralTransitive", + "requested": "[10.0.10, 10.0.10]", + "resolved": "10.0.10", + "contentHash": "kzg9MuQNJvZQxAU+piSkEzc7/1tpW6n1nVSGGMObu2GgxLK8Nf+6fvZundaznTZ+O2KhfPZ8HFNCzMH3PWDUmA==", + "dependencies": { + "Microsoft.EntityFrameworkCore.Sqlite.Core": "10.0.10", + "Microsoft.Extensions.Caching.Memory": "10.0.10", + "Microsoft.Extensions.Configuration.Abstractions": "10.0.10", + "Microsoft.Extensions.DependencyModel": "10.0.10", + "Microsoft.Extensions.Logging": "10.0.10", + "SQLitePCLRaw.bundle_e_sqlite3": "2.1.11", + "SQLitePCLRaw.core": "2.1.11" + } + }, "Microsoft.EntityFrameworkCore.SqlServer": { "type": "CentralTransitive", "requested": "[10.0.10, 10.0.10]", @@ -1894,13 +2004,28 @@ "OpenIddict.EntityFrameworkCore.Models": "7.6.0" } }, - "OpenTelemetry.Exporter.Prometheus.AspNetCore": { + "OpenTelemetry.Api": { + "type": "CentralTransitive", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" + }, + "OpenTelemetry.Exporter.Console": { + "type": "CentralTransitive", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "sSoCa2DMCkw7tQabiVduwKWVyg9ungCiwh+0JuDPODF6CuYvR+OCuJwqcbzJsTMecWQrbgL8OYWAt3GC5tJGhw==", + "dependencies": { + "OpenTelemetry": "1.17.0" + } + }, + "OpenTelemetry.Exporter.OpenTelemetryProtocol": { "type": "CentralTransitive", - "requested": "[1.11.2-beta.1, 1.11.2-beta.1]", - "resolved": "1.11.2-beta.1", - "contentHash": "jouLU4VHpzyXuzF2yi/bpt9DoseZGyUudSdTFvylgIwIx6ST1bdI/AXNoJ4/n6HwMiso677ILLm/RM8DY+EYwA==", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "R1omQOrQpGlS0Cp5UIr/TAiuEA48JrPlgr1NPV5gESiTU7HhWU+ILe2EBSYb1fKdsSavZ7nZkHcUxAzofPqr2A==", "dependencies": { - "OpenTelemetry": "[1.11.2, 2.0.0)" + "OpenTelemetry": "1.17.0" } }, "OpenTelemetry.Extensions.Hosting": { @@ -1922,6 +2047,17 @@ "OpenTelemetry.Api.ProviderBuilderExtensions": "[1.17.0, 2.0.0)" } }, + "OpenTelemetry.Instrumentation.EntityFrameworkCore": { + "type": "CentralTransitive", + "requested": "[1.17.0-beta.1, )", + "resolved": "1.17.0-beta.1", + "contentHash": "BPSv1rk6qEkGZUGTNBfk7XmYqBAWdF3FBdjXEjVClp0bKUl6VCumlaosT84qvlK7YnHLCv5FFqJHx2N62TbKEw==", + "dependencies": { + "Microsoft.Extensions.Configuration": "10.0.0", + "Microsoft.Extensions.Options": "10.0.0", + "OpenTelemetry.Api.ProviderBuilderExtensions": "[1.17.0, 2.0.0)" + } + }, "OpenTelemetry.Instrumentation.Http": { "type": "CentralTransitive", "requested": "[1.17.0, 1.17.0]", @@ -2001,6 +2137,12 @@ "resolved": "5.6.3", "contentHash": "ayL730f1gdQVYmFFLKSX83QcoltyKSMBsV94qfCBpZHMaJz/e3ALuXKZDD8SkseWbNHxBe0HxLRBe5OOpQ9HpA==" }, + "SQLitePCLRaw.lib.e_sqlite3": { + "type": "CentralTransitive", + "requested": "[2.1.12, 2.1.12]", + "resolved": "2.1.12", + "contentHash": "fWi8Dbknuhgg72fWinIdjXVaqO1hHL4YBBwVLnr7e1c9TAZwJ0QE38j9syW1hwx6HaqEVTwI+O07WPdZn8Rp0w==" + }, "Swashbuckle.AspNetCore": { "type": "CentralTransitive", "requested": "[10.2.3, 10.2.3]", @@ -2097,6 +2239,12 @@ "resolved": "10.0.10", "contentHash": "KG8t5RHczdgB3IWvRndpI0nE1DSo7ikDYSDbITxfgRFyIvnYiKzuPjaZOsPnwFQ1aOGUl9sEulJul9wlHLEUoA==" }, + "SQLitePCLRaw.lib.e_sqlite3": { + "type": "CentralTransitive", + "requested": "[2.1.12, 2.1.12]", + "resolved": "2.1.12", + "contentHash": "fWi8Dbknuhgg72fWinIdjXVaqO1hHL4YBBwVLnr7e1c9TAZwJ0QE38j9syW1hwx6HaqEVTwI+O07WPdZn8Rp0w==" + }, "System.Data.SqlClient": { "type": "CentralTransitive", "requested": "[4.9.1, 4.9.1]", @@ -2181,6 +2329,12 @@ "resolved": "10.0.10", "contentHash": "KG8t5RHczdgB3IWvRndpI0nE1DSo7ikDYSDbITxfgRFyIvnYiKzuPjaZOsPnwFQ1aOGUl9sEulJul9wlHLEUoA==" }, + "SQLitePCLRaw.lib.e_sqlite3": { + "type": "CentralTransitive", + "requested": "[2.1.12, 2.1.12]", + "resolved": "2.1.12", + "contentHash": "fWi8Dbknuhgg72fWinIdjXVaqO1hHL4YBBwVLnr7e1c9TAZwJ0QE38j9syW1hwx6HaqEVTwI+O07WPdZn8Rp0w==" + }, "System.Data.SqlClient": { "type": "CentralTransitive", "requested": "[4.9.1, 4.9.1]", @@ -2265,6 +2419,12 @@ "resolved": "10.0.10", "contentHash": "KG8t5RHczdgB3IWvRndpI0nE1DSo7ikDYSDbITxfgRFyIvnYiKzuPjaZOsPnwFQ1aOGUl9sEulJul9wlHLEUoA==" }, + "SQLitePCLRaw.lib.e_sqlite3": { + "type": "CentralTransitive", + "requested": "[2.1.12, 2.1.12]", + "resolved": "2.1.12", + "contentHash": "fWi8Dbknuhgg72fWinIdjXVaqO1hHL4YBBwVLnr7e1c9TAZwJ0QE38j9syW1hwx6HaqEVTwI+O07WPdZn8Rp0w==" + }, "System.Data.SqlClient": { "type": "CentralTransitive", "requested": "[4.9.1, 4.9.1]", @@ -2349,6 +2509,12 @@ "resolved": "10.0.10", "contentHash": "KG8t5RHczdgB3IWvRndpI0nE1DSo7ikDYSDbITxfgRFyIvnYiKzuPjaZOsPnwFQ1aOGUl9sEulJul9wlHLEUoA==" }, + "SQLitePCLRaw.lib.e_sqlite3": { + "type": "CentralTransitive", + "requested": "[2.1.12, 2.1.12]", + "resolved": "2.1.12", + "contentHash": "fWi8Dbknuhgg72fWinIdjXVaqO1hHL4YBBwVLnr7e1c9TAZwJ0QE38j9syW1hwx6HaqEVTwI+O07WPdZn8Rp0w==" + }, "System.Data.SqlClient": { "type": "CentralTransitive", "requested": "[4.9.1, 4.9.1]", diff --git a/BuildingBlocks/test/BuildingBlocks.Application.Tests/packages.lock.json b/BuildingBlocks/test/BuildingBlocks.Application.Tests/packages.lock.json index a62fbd456c..a1127661b4 100644 --- a/BuildingBlocks/test/BuildingBlocks.Application.Tests/packages.lock.json +++ b/BuildingBlocks/test/BuildingBlocks.Application.Tests/packages.lock.json @@ -904,6 +904,7 @@ "Microsoft.Extensions.Identity.Core": "[10.0.10, 10.0.10]", "Microsoft.Extensions.Logging": "[10.0.10, 10.0.10]", "Npgsql.EntityFrameworkCore.PostgreSQL": "[10.0.3, 10.0.3]", + "OpenTelemetry.Api": "[1.17.0, )", "Polly": "[8.7.0, 8.7.0]", "RabbitMQ.Client": "[7.2.1, 7.2.1]", "Serilog": "[4.4.0, 4.4.0]" @@ -1329,6 +1330,12 @@ "Npgsql": "10.0.3" } }, + "OpenTelemetry.Api": { + "type": "CentralTransitive", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" + }, "Polly": { "type": "CentralTransitive", "requested": "[8.7.0, 8.7.0]", diff --git a/BuildingBlocks/test/BuildingBlocks.Infrastructure.Tests/packages.lock.json b/BuildingBlocks/test/BuildingBlocks.Infrastructure.Tests/packages.lock.json index 6d19f723e4..5d02e3f788 100644 --- a/BuildingBlocks/test/BuildingBlocks.Infrastructure.Tests/packages.lock.json +++ b/BuildingBlocks/test/BuildingBlocks.Infrastructure.Tests/packages.lock.json @@ -744,6 +744,7 @@ "Microsoft.Extensions.Identity.Core": "[10.0.10, 10.0.10]", "Microsoft.Extensions.Logging": "[10.0.10, 10.0.10]", "Npgsql.EntityFrameworkCore.PostgreSQL": "[10.0.3, 10.0.3]", + "OpenTelemetry.Api": "[1.17.0, )", "Polly": "[8.7.0, 8.7.0]", "RabbitMQ.Client": "[7.2.1, 7.2.1]", "Serilog": "[4.4.0, 4.4.0]" @@ -1012,6 +1013,12 @@ "Npgsql": "10.0.3" } }, + "OpenTelemetry.Api": { + "type": "CentralTransitive", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" + }, "Polly": { "type": "CentralTransitive", "requested": "[8.7.0, 8.7.0]", diff --git a/BuildingBlocks/test/Crypto.Tests/packages.lock.json b/BuildingBlocks/test/Crypto.Tests/packages.lock.json index b81b61a08b..be17c6caba 100644 --- a/BuildingBlocks/test/Crypto.Tests/packages.lock.json +++ b/BuildingBlocks/test/Crypto.Tests/packages.lock.json @@ -780,6 +780,7 @@ "Microsoft.Extensions.Identity.Core": "[10.0.10, 10.0.10]", "Microsoft.Extensions.Logging": "[10.0.10, 10.0.10]", "Npgsql.EntityFrameworkCore.PostgreSQL": "[10.0.3, 10.0.3]", + "OpenTelemetry.Api": "[1.17.0, )", "Polly": "[8.7.0, 8.7.0]", "RabbitMQ.Client": "[7.2.1, 7.2.1]", "Serilog": "[4.4.0, 4.4.0]" @@ -1169,6 +1170,12 @@ "libsodium": "[1.0.22, 1.0.23)" } }, + "OpenTelemetry.Api": { + "type": "CentralTransitive", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" + }, "Polly": { "type": "CentralTransitive", "requested": "[8.7.0, 8.7.0]", diff --git a/BuildingBlocks/test/DevelopmentKit.Identity.Tests/packages.lock.json b/BuildingBlocks/test/DevelopmentKit.Identity.Tests/packages.lock.json index 5e8d5734df..49a49b165e 100644 --- a/BuildingBlocks/test/DevelopmentKit.Identity.Tests/packages.lock.json +++ b/BuildingBlocks/test/DevelopmentKit.Identity.Tests/packages.lock.json @@ -775,6 +775,7 @@ "Microsoft.Extensions.Identity.Core": "[10.0.10, 10.0.10]", "Microsoft.Extensions.Logging": "[10.0.10, 10.0.10]", "Npgsql.EntityFrameworkCore.PostgreSQL": "[10.0.3, 10.0.3]", + "OpenTelemetry.Api": "[1.17.0, )", "Polly": "[8.7.0, 8.7.0]", "RabbitMQ.Client": "[7.2.1, 7.2.1]", "Serilog": "[4.4.0, 4.4.0]" @@ -1142,6 +1143,12 @@ "Npgsql": "10.0.3" } }, + "OpenTelemetry.Api": { + "type": "CentralTransitive", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" + }, "Polly": { "type": "CentralTransitive", "requested": "[8.7.0, 8.7.0]", diff --git a/BuildingBlocks/test/Tooling.Tests/packages.lock.json b/BuildingBlocks/test/Tooling.Tests/packages.lock.json index 5e8d5734df..49a49b165e 100644 --- a/BuildingBlocks/test/Tooling.Tests/packages.lock.json +++ b/BuildingBlocks/test/Tooling.Tests/packages.lock.json @@ -775,6 +775,7 @@ "Microsoft.Extensions.Identity.Core": "[10.0.10, 10.0.10]", "Microsoft.Extensions.Logging": "[10.0.10, 10.0.10]", "Npgsql.EntityFrameworkCore.PostgreSQL": "[10.0.3, 10.0.3]", + "OpenTelemetry.Api": "[1.17.0, )", "Polly": "[8.7.0, 8.7.0]", "RabbitMQ.Client": "[7.2.1, 7.2.1]", "Serilog": "[4.4.0, 4.4.0]" @@ -1142,6 +1143,12 @@ "Npgsql": "10.0.3" } }, + "OpenTelemetry.Api": { + "type": "CentralTransitive", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" + }, "Polly": { "type": "CentralTransitive", "requested": "[8.7.0, 8.7.0]", diff --git a/Common/src/Common.Infrastructure/packages.lock.json b/Common/src/Common.Infrastructure/packages.lock.json index 4043a27961..8d45412b7d 100644 --- a/Common/src/Common.Infrastructure/packages.lock.json +++ b/Common/src/Common.Infrastructure/packages.lock.json @@ -605,6 +605,7 @@ "Microsoft.Extensions.Identity.Core": "[10.0.10, 10.0.10]", "Microsoft.Extensions.Logging": "[10.0.10, 10.0.10]", "Npgsql.EntityFrameworkCore.PostgreSQL": "[10.0.3, 10.0.3]", + "OpenTelemetry.Api": "[1.17.0, )", "Polly": "[8.7.0, 8.7.0]", "RabbitMQ.Client": "[7.2.1, 7.2.1]", "Serilog": "[4.4.0, 4.4.0]" @@ -897,6 +898,12 @@ "Npgsql": "10.0.3" } }, + "OpenTelemetry.Api": { + "type": "CentralTransitive", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" + }, "RabbitMQ.Client": { "type": "CentralTransitive", "requested": "[7.2.1, 7.2.1]", diff --git a/Directory.Packages.props b/Directory.Packages.props index 847e4a5795..cafdd86dfc 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -69,10 +69,11 @@ - - + + + diff --git a/Modules/Announcements/src/Announcements.Application/Announcements/Commands/ExecuteHousekeeping/Handler.cs b/Modules/Announcements/src/Announcements.Application/Announcements/Commands/ExecuteHousekeeping/Handler.cs index e77c894acb..6bfc93c7bd 100644 --- a/Modules/Announcements/src/Announcements.Application/Announcements/Commands/ExecuteHousekeeping/Handler.cs +++ b/Modules/Announcements/src/Announcements.Application/Announcements/Commands/ExecuteHousekeeping/Handler.cs @@ -1,21 +1,17 @@ -using System.Diagnostics; -using Backbone.BuildingBlocks.Application.Housekeeping; +using Backbone.BuildingBlocks.Application.Housekeeping; using Backbone.Modules.Announcements.Application.Infrastructure.Persistence.Repository; using Backbone.Modules.Announcements.Domain.Entities; using MediatR; -using Microsoft.Extensions.Logging; namespace Backbone.Modules.Announcements.Application.Announcements.Commands.ExecuteHousekeeping; public class Handler : IRequestHandler { private readonly IAnnouncementsRepository _announcementsRepository; - private readonly ILogger _logger; - public Handler(IAnnouncementsRepository announcementsRepository, ILogger logger) + public Handler(IAnnouncementsRepository announcementsRepository) { _announcementsRepository = announcementsRepository; - _logger = logger; } public async Task Handle(ExecuteHousekeepingCommand request, CancellationToken cancellationToken) @@ -25,10 +21,6 @@ public async Task Handle(ExecuteHousekeepingCommand request, CancellationToken c private async Task DeleteAnnouncements(CancellationToken cancellationToken) { - var stopwatch = Stopwatch.StartNew(); - var numberOfDeletedItems = await _announcementsRepository.Delete(Announcement.CanBeCleanedUp, cancellationToken); - stopwatch.Stop(); - - _logger.DataDeleted(numberOfDeletedItems, "announcements", stopwatch.ElapsedMilliseconds); + await HousekeepingTelemetry.TrackItemDeletion("announcements", ct => _announcementsRepository.Delete(Announcement.CanBeCleanedUp, ct), cancellationToken); } } diff --git a/Modules/Announcements/src/Announcements.Application/packages.lock.json b/Modules/Announcements/src/Announcements.Application/packages.lock.json index a1549fdf1b..aab6490e33 100644 --- a/Modules/Announcements/src/Announcements.Application/packages.lock.json +++ b/Modules/Announcements/src/Announcements.Application/packages.lock.json @@ -717,6 +717,7 @@ "Microsoft.Extensions.Identity.Core": "[10.0.10, 10.0.10]", "Microsoft.Extensions.Logging": "[10.0.10, 10.0.10]", "Npgsql.EntityFrameworkCore.PostgreSQL": "[10.0.3, 10.0.3]", + "OpenTelemetry.Api": "[1.17.0, )", "Polly": "[8.7.0, 8.7.0]", "RabbitMQ.Client": "[7.2.1, 7.2.1]", "Serilog": "[4.4.0, 4.4.0]" @@ -1109,6 +1110,12 @@ "Npgsql": "10.0.3" } }, + "OpenTelemetry.Api": { + "type": "CentralTransitive", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" + }, "Polly": { "type": "CentralTransitive", "requested": "[8.7.0, 8.7.0]", diff --git a/Modules/Announcements/src/Announcements.Infrastructure.Database.Postgres/packages.lock.json b/Modules/Announcements/src/Announcements.Infrastructure.Database.Postgres/packages.lock.json index 95c663af8c..2fba97ac90 100644 --- a/Modules/Announcements/src/Announcements.Infrastructure.Database.Postgres/packages.lock.json +++ b/Modules/Announcements/src/Announcements.Infrastructure.Database.Postgres/packages.lock.json @@ -707,6 +707,7 @@ "Microsoft.Extensions.Identity.Core": "[10.0.10, 10.0.10]", "Microsoft.Extensions.Logging": "[10.0.10, 10.0.10]", "Npgsql.EntityFrameworkCore.PostgreSQL": "[10.0.3, 10.0.3]", + "OpenTelemetry.Api": "[1.17.0, )", "Polly": "[8.7.0, 8.7.0]", "RabbitMQ.Client": "[7.2.1, 7.2.1]", "Serilog": "[4.4.0, 4.4.0]" @@ -1129,6 +1130,12 @@ "Npgsql": "10.0.3" } }, + "OpenTelemetry.Api": { + "type": "CentralTransitive", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" + }, "Polly": { "type": "CentralTransitive", "requested": "[8.7.0, 8.7.0]", diff --git a/Modules/Announcements/src/Announcements.Infrastructure.Database.SqlServer/packages.lock.json b/Modules/Announcements/src/Announcements.Infrastructure.Database.SqlServer/packages.lock.json index 95c663af8c..2fba97ac90 100644 --- a/Modules/Announcements/src/Announcements.Infrastructure.Database.SqlServer/packages.lock.json +++ b/Modules/Announcements/src/Announcements.Infrastructure.Database.SqlServer/packages.lock.json @@ -707,6 +707,7 @@ "Microsoft.Extensions.Identity.Core": "[10.0.10, 10.0.10]", "Microsoft.Extensions.Logging": "[10.0.10, 10.0.10]", "Npgsql.EntityFrameworkCore.PostgreSQL": "[10.0.3, 10.0.3]", + "OpenTelemetry.Api": "[1.17.0, )", "Polly": "[8.7.0, 8.7.0]", "RabbitMQ.Client": "[7.2.1, 7.2.1]", "Serilog": "[4.4.0, 4.4.0]" @@ -1129,6 +1130,12 @@ "Npgsql": "10.0.3" } }, + "OpenTelemetry.Api": { + "type": "CentralTransitive", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" + }, "Polly": { "type": "CentralTransitive", "requested": "[8.7.0, 8.7.0]", diff --git a/Modules/Announcements/src/Announcements.Infrastructure/packages.lock.json b/Modules/Announcements/src/Announcements.Infrastructure/packages.lock.json index 63c6b88e90..229e1cf241 100644 --- a/Modules/Announcements/src/Announcements.Infrastructure/packages.lock.json +++ b/Modules/Announcements/src/Announcements.Infrastructure/packages.lock.json @@ -749,6 +749,7 @@ "Microsoft.Extensions.Identity.Core": "[10.0.10, 10.0.10]", "Microsoft.Extensions.Logging": "[10.0.10, 10.0.10]", "Npgsql.EntityFrameworkCore.PostgreSQL": "[10.0.3, 10.0.3]", + "OpenTelemetry.Api": "[1.17.0, )", "Polly": "[8.7.0, 8.7.0]", "RabbitMQ.Client": "[7.2.1, 7.2.1]", "Serilog": "[4.4.0, 4.4.0]" @@ -1117,6 +1118,12 @@ "Microsoft.Extensions.Primitives": "10.0.10" } }, + "OpenTelemetry.Api": { + "type": "CentralTransitive", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" + }, "Polly": { "type": "CentralTransitive", "requested": "[8.7.0, 8.7.0]", diff --git a/Modules/Announcements/src/Announcements.Module/packages.lock.json b/Modules/Announcements/src/Announcements.Module/packages.lock.json index f04a654c62..f383c2d44d 100644 --- a/Modules/Announcements/src/Announcements.Module/packages.lock.json +++ b/Modules/Announcements/src/Announcements.Module/packages.lock.json @@ -917,11 +917,6 @@ "OpenTelemetry.Api.ProviderBuilderExtensions": "1.17.0" } }, - "OpenTelemetry.Api": { - "type": "Transitive", - "resolved": "1.17.0", - "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" - }, "OpenTelemetry.Api.ProviderBuilderExtensions": { "type": "Transitive", "resolved": "1.17.0", @@ -1112,9 +1107,10 @@ "DotNetDiag.HealthChecks.SqlServer": "[10.0.10, 10.0.10]", "Microsoft.EntityFrameworkCore": "[10.0.10, 10.0.10]", "Microsoft.EntityFrameworkCore.Relational": "[10.0.10, 10.0.10]", - "OpenTelemetry.Exporter.Prometheus.AspNetCore": "[1.11.2-beta.1, 1.11.2-beta.1]", + "OpenTelemetry.Exporter.OpenTelemetryProtocol": "[1.17.0, )", "OpenTelemetry.Extensions.Hosting": "[1.17.0, 1.17.0]", "OpenTelemetry.Instrumentation.AspNetCore": "[1.17.0, 1.17.0]", + "OpenTelemetry.Instrumentation.EntityFrameworkCore": "[1.17.0-beta.1, )", "OpenTelemetry.Instrumentation.Http": "[1.17.0, 1.17.0]", "OpenTelemetry.Instrumentation.Runtime": "[1.17.0, 1.17.0]", "Polly": "[8.7.0, 8.7.0]", @@ -1175,6 +1171,7 @@ "Microsoft.Extensions.Identity.Core": "[10.0.10, 10.0.10]", "Microsoft.Extensions.Logging": "[10.0.10, 10.0.10]", "Npgsql.EntityFrameworkCore.PostgreSQL": "[10.0.3, 10.0.3]", + "OpenTelemetry.Api": "[1.17.0, )", "Polly": "[8.7.0, 8.7.0]", "RabbitMQ.Client": "[7.2.1, 7.2.1]", "Serilog": "[4.4.0, 4.4.0]" @@ -1802,13 +1799,19 @@ "OpenIddict.EntityFrameworkCore.Models": "7.6.0" } }, - "OpenTelemetry.Exporter.Prometheus.AspNetCore": { + "OpenTelemetry.Api": { + "type": "CentralTransitive", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" + }, + "OpenTelemetry.Exporter.OpenTelemetryProtocol": { "type": "CentralTransitive", - "requested": "[1.11.2-beta.1, 1.11.2-beta.1]", - "resolved": "1.11.2-beta.1", - "contentHash": "jouLU4VHpzyXuzF2yi/bpt9DoseZGyUudSdTFvylgIwIx6ST1bdI/AXNoJ4/n6HwMiso677ILLm/RM8DY+EYwA==", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "R1omQOrQpGlS0Cp5UIr/TAiuEA48JrPlgr1NPV5gESiTU7HhWU+ILe2EBSYb1fKdsSavZ7nZkHcUxAzofPqr2A==", "dependencies": { - "OpenTelemetry": "[1.11.2, 2.0.0)" + "OpenTelemetry": "1.17.0" } }, "OpenTelemetry.Extensions.Hosting": { @@ -1830,6 +1833,17 @@ "OpenTelemetry.Api.ProviderBuilderExtensions": "[1.17.0, 2.0.0)" } }, + "OpenTelemetry.Instrumentation.EntityFrameworkCore": { + "type": "CentralTransitive", + "requested": "[1.17.0-beta.1, )", + "resolved": "1.17.0-beta.1", + "contentHash": "BPSv1rk6qEkGZUGTNBfk7XmYqBAWdF3FBdjXEjVClp0bKUl6VCumlaosT84qvlK7YnHLCv5FFqJHx2N62TbKEw==", + "dependencies": { + "Microsoft.Extensions.Configuration": "10.0.0", + "Microsoft.Extensions.Options": "10.0.0", + "OpenTelemetry.Api.ProviderBuilderExtensions": "[1.17.0, 2.0.0)" + } + }, "OpenTelemetry.Instrumentation.Http": { "type": "CentralTransitive", "requested": "[1.17.0, 1.17.0]", diff --git a/Modules/Announcements/test/Announcements.Application.Tests/packages.lock.json b/Modules/Announcements/test/Announcements.Application.Tests/packages.lock.json index a9f455d2fc..1e85922241 100644 --- a/Modules/Announcements/test/Announcements.Application.Tests/packages.lock.json +++ b/Modules/Announcements/test/Announcements.Application.Tests/packages.lock.json @@ -928,6 +928,7 @@ "Microsoft.Extensions.Identity.Core": "[10.0.10, 10.0.10]", "Microsoft.Extensions.Logging": "[10.0.10, 10.0.10]", "Npgsql.EntityFrameworkCore.PostgreSQL": "[10.0.3, 10.0.3]", + "OpenTelemetry.Api": "[1.17.0, )", "Polly": "[8.7.0, 8.7.0]", "RabbitMQ.Client": "[7.2.1, 7.2.1]", "Serilog": "[4.4.0, 4.4.0]" @@ -1385,6 +1386,12 @@ "Npgsql": "10.0.3" } }, + "OpenTelemetry.Api": { + "type": "CentralTransitive", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" + }, "Polly": { "type": "CentralTransitive", "requested": "[8.7.0, 8.7.0]", diff --git a/Modules/Announcements/test/Announcements.Domain.Tests/packages.lock.json b/Modules/Announcements/test/Announcements.Domain.Tests/packages.lock.json index c255df051d..08cc489eef 100644 --- a/Modules/Announcements/test/Announcements.Domain.Tests/packages.lock.json +++ b/Modules/Announcements/test/Announcements.Domain.Tests/packages.lock.json @@ -775,6 +775,7 @@ "Microsoft.Extensions.Identity.Core": "[10.0.10, 10.0.10]", "Microsoft.Extensions.Logging": "[10.0.10, 10.0.10]", "Npgsql.EntityFrameworkCore.PostgreSQL": "[10.0.3, 10.0.3]", + "OpenTelemetry.Api": "[1.17.0, )", "Polly": "[8.7.0, 8.7.0]", "RabbitMQ.Client": "[7.2.1, 7.2.1]", "Serilog": "[4.4.0, 4.4.0]" @@ -1156,6 +1157,12 @@ "Npgsql": "10.0.3" } }, + "OpenTelemetry.Api": { + "type": "CentralTransitive", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" + }, "Polly": { "type": "CentralTransitive", "requested": "[8.7.0, 8.7.0]", diff --git a/Modules/Challenges/src/Challenges.Application/Challenges/Commands/ExecuteHousekeeping/Handler.cs b/Modules/Challenges/src/Challenges.Application/Challenges/Commands/ExecuteHousekeeping/Handler.cs index b535c821e3..8b722ecb5c 100644 --- a/Modules/Challenges/src/Challenges.Application/Challenges/Commands/ExecuteHousekeeping/Handler.cs +++ b/Modules/Challenges/src/Challenges.Application/Challenges/Commands/ExecuteHousekeeping/Handler.cs @@ -1,21 +1,17 @@ -using System.Diagnostics; -using Backbone.BuildingBlocks.Application.Housekeeping; +using Backbone.BuildingBlocks.Application.Housekeeping; using Backbone.Modules.Challenges.Application.Infrastructure.Persistence.Repository; using Backbone.Modules.Challenges.Domain.Entities; using MediatR; -using Microsoft.Extensions.Logging; namespace Backbone.Modules.Challenges.Application.Challenges.Commands.ExecuteHousekeeping; public class Handler : IRequestHandler { private readonly IChallengesRepository _challengesRepository; - private readonly ILogger _logger; - public Handler(IChallengesRepository challengesRepository, ILogger logger) + public Handler(IChallengesRepository challengesRepository) { _challengesRepository = challengesRepository; - _logger = logger; } public async Task Handle(ExecuteHousekeepingCommand request, CancellationToken cancellationToken) @@ -25,10 +21,6 @@ public async Task Handle(ExecuteHousekeepingCommand request, CancellationToken c private async Task DeleteChallenges(CancellationToken cancellationToken) { - var stopwatch = Stopwatch.StartNew(); - var numberOfDeletedItems = await _challengesRepository.Delete(Challenge.CanBeCleanedUp, cancellationToken); - stopwatch.Stop(); - - _logger.DataDeleted(numberOfDeletedItems, "challenges", stopwatch.ElapsedMilliseconds); + await HousekeepingTelemetry.TrackItemDeletion("challenges", ct => _challengesRepository.Delete(Challenge.CanBeCleanedUp, ct), cancellationToken); } } diff --git a/Modules/Challenges/src/Challenges.Application/packages.lock.json b/Modules/Challenges/src/Challenges.Application/packages.lock.json index 94bb56581b..07deb20eaf 100644 --- a/Modules/Challenges/src/Challenges.Application/packages.lock.json +++ b/Modules/Challenges/src/Challenges.Application/packages.lock.json @@ -723,6 +723,7 @@ "Microsoft.Extensions.Identity.Core": "[10.0.10, 10.0.10]", "Microsoft.Extensions.Logging": "[10.0.10, 10.0.10]", "Npgsql.EntityFrameworkCore.PostgreSQL": "[10.0.3, 10.0.3]", + "OpenTelemetry.Api": "[1.17.0, )", "Polly": "[8.7.0, 8.7.0]", "RabbitMQ.Client": "[7.2.1, 7.2.1]", "Serilog": "[4.4.0, 4.4.0]" @@ -1102,6 +1103,12 @@ "Npgsql": "10.0.3" } }, + "OpenTelemetry.Api": { + "type": "CentralTransitive", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" + }, "Polly": { "type": "CentralTransitive", "requested": "[8.7.0, 8.7.0]", diff --git a/Modules/Challenges/src/Challenges.Infrastructure.Database.Postgres/packages.lock.json b/Modules/Challenges/src/Challenges.Infrastructure.Database.Postgres/packages.lock.json index 0e431093ac..c7305d7bcb 100644 --- a/Modules/Challenges/src/Challenges.Infrastructure.Database.Postgres/packages.lock.json +++ b/Modules/Challenges/src/Challenges.Infrastructure.Database.Postgres/packages.lock.json @@ -707,6 +707,7 @@ "Microsoft.Extensions.Identity.Core": "[10.0.10, 10.0.10]", "Microsoft.Extensions.Logging": "[10.0.10, 10.0.10]", "Npgsql.EntityFrameworkCore.PostgreSQL": "[10.0.3, 10.0.3]", + "OpenTelemetry.Api": "[1.17.0, )", "Polly": "[8.7.0, 8.7.0]", "RabbitMQ.Client": "[7.2.1, 7.2.1]", "Serilog": "[4.4.0, 4.4.0]" @@ -1123,6 +1124,12 @@ "Npgsql": "10.0.3" } }, + "OpenTelemetry.Api": { + "type": "CentralTransitive", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" + }, "Polly": { "type": "CentralTransitive", "requested": "[8.7.0, 8.7.0]", diff --git a/Modules/Challenges/src/Challenges.Infrastructure.Database.SqlServer/packages.lock.json b/Modules/Challenges/src/Challenges.Infrastructure.Database.SqlServer/packages.lock.json index 0e431093ac..c7305d7bcb 100644 --- a/Modules/Challenges/src/Challenges.Infrastructure.Database.SqlServer/packages.lock.json +++ b/Modules/Challenges/src/Challenges.Infrastructure.Database.SqlServer/packages.lock.json @@ -707,6 +707,7 @@ "Microsoft.Extensions.Identity.Core": "[10.0.10, 10.0.10]", "Microsoft.Extensions.Logging": "[10.0.10, 10.0.10]", "Npgsql.EntityFrameworkCore.PostgreSQL": "[10.0.3, 10.0.3]", + "OpenTelemetry.Api": "[1.17.0, )", "Polly": "[8.7.0, 8.7.0]", "RabbitMQ.Client": "[7.2.1, 7.2.1]", "Serilog": "[4.4.0, 4.4.0]" @@ -1123,6 +1124,12 @@ "Npgsql": "10.0.3" } }, + "OpenTelemetry.Api": { + "type": "CentralTransitive", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" + }, "Polly": { "type": "CentralTransitive", "requested": "[8.7.0, 8.7.0]", diff --git a/Modules/Challenges/src/Challenges.Infrastructure/packages.lock.json b/Modules/Challenges/src/Challenges.Infrastructure/packages.lock.json index e1481e1406..e9da05fd7e 100644 --- a/Modules/Challenges/src/Challenges.Infrastructure/packages.lock.json +++ b/Modules/Challenges/src/Challenges.Infrastructure/packages.lock.json @@ -743,6 +743,7 @@ "Microsoft.Extensions.Identity.Core": "[10.0.10, 10.0.10]", "Microsoft.Extensions.Logging": "[10.0.10, 10.0.10]", "Npgsql.EntityFrameworkCore.PostgreSQL": "[10.0.3, 10.0.3]", + "OpenTelemetry.Api": "[1.17.0, )", "Polly": "[8.7.0, 8.7.0]", "RabbitMQ.Client": "[7.2.1, 7.2.1]", "Serilog": "[4.4.0, 4.4.0]" @@ -1111,6 +1112,12 @@ "Microsoft.Extensions.Primitives": "10.0.10" } }, + "OpenTelemetry.Api": { + "type": "CentralTransitive", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" + }, "Polly": { "type": "CentralTransitive", "requested": "[8.7.0, 8.7.0]", diff --git a/Modules/Challenges/src/Challenges.Module/packages.lock.json b/Modules/Challenges/src/Challenges.Module/packages.lock.json index 2d0c70ffb7..40eb8a9d32 100644 --- a/Modules/Challenges/src/Challenges.Module/packages.lock.json +++ b/Modules/Challenges/src/Challenges.Module/packages.lock.json @@ -917,11 +917,6 @@ "OpenTelemetry.Api.ProviderBuilderExtensions": "1.17.0" } }, - "OpenTelemetry.Api": { - "type": "Transitive", - "resolved": "1.17.0", - "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" - }, "OpenTelemetry.Api.ProviderBuilderExtensions": { "type": "Transitive", "resolved": "1.17.0", @@ -1112,9 +1107,10 @@ "DotNetDiag.HealthChecks.SqlServer": "[10.0.10, 10.0.10]", "Microsoft.EntityFrameworkCore": "[10.0.10, 10.0.10]", "Microsoft.EntityFrameworkCore.Relational": "[10.0.10, 10.0.10]", - "OpenTelemetry.Exporter.Prometheus.AspNetCore": "[1.11.2-beta.1, 1.11.2-beta.1]", + "OpenTelemetry.Exporter.OpenTelemetryProtocol": "[1.17.0, )", "OpenTelemetry.Extensions.Hosting": "[1.17.0, 1.17.0]", "OpenTelemetry.Instrumentation.AspNetCore": "[1.17.0, 1.17.0]", + "OpenTelemetry.Instrumentation.EntityFrameworkCore": "[1.17.0-beta.1, )", "OpenTelemetry.Instrumentation.Http": "[1.17.0, 1.17.0]", "OpenTelemetry.Instrumentation.Runtime": "[1.17.0, 1.17.0]", "Polly": "[8.7.0, 8.7.0]", @@ -1175,6 +1171,7 @@ "Microsoft.Extensions.Identity.Core": "[10.0.10, 10.0.10]", "Microsoft.Extensions.Logging": "[10.0.10, 10.0.10]", "Npgsql.EntityFrameworkCore.PostgreSQL": "[10.0.3, 10.0.3]", + "OpenTelemetry.Api": "[1.17.0, )", "Polly": "[8.7.0, 8.7.0]", "RabbitMQ.Client": "[7.2.1, 7.2.1]", "Serilog": "[4.4.0, 4.4.0]" @@ -1802,13 +1799,19 @@ "OpenIddict.EntityFrameworkCore.Models": "7.6.0" } }, - "OpenTelemetry.Exporter.Prometheus.AspNetCore": { + "OpenTelemetry.Api": { + "type": "CentralTransitive", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" + }, + "OpenTelemetry.Exporter.OpenTelemetryProtocol": { "type": "CentralTransitive", - "requested": "[1.11.2-beta.1, 1.11.2-beta.1]", - "resolved": "1.11.2-beta.1", - "contentHash": "jouLU4VHpzyXuzF2yi/bpt9DoseZGyUudSdTFvylgIwIx6ST1bdI/AXNoJ4/n6HwMiso677ILLm/RM8DY+EYwA==", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "R1omQOrQpGlS0Cp5UIr/TAiuEA48JrPlgr1NPV5gESiTU7HhWU+ILe2EBSYb1fKdsSavZ7nZkHcUxAzofPqr2A==", "dependencies": { - "OpenTelemetry": "[1.11.2, 2.0.0)" + "OpenTelemetry": "1.17.0" } }, "OpenTelemetry.Extensions.Hosting": { @@ -1830,6 +1833,17 @@ "OpenTelemetry.Api.ProviderBuilderExtensions": "[1.17.0, 2.0.0)" } }, + "OpenTelemetry.Instrumentation.EntityFrameworkCore": { + "type": "CentralTransitive", + "requested": "[1.17.0-beta.1, )", + "resolved": "1.17.0-beta.1", + "contentHash": "BPSv1rk6qEkGZUGTNBfk7XmYqBAWdF3FBdjXEjVClp0bKUl6VCumlaosT84qvlK7YnHLCv5FFqJHx2N62TbKEw==", + "dependencies": { + "Microsoft.Extensions.Configuration": "10.0.0", + "Microsoft.Extensions.Options": "10.0.0", + "OpenTelemetry.Api.ProviderBuilderExtensions": "[1.17.0, 2.0.0)" + } + }, "OpenTelemetry.Instrumentation.Http": { "type": "CentralTransitive", "requested": "[1.17.0, 1.17.0]", diff --git a/Modules/Challenges/test/Challenges.Application.Tests/packages.lock.json b/Modules/Challenges/test/Challenges.Application.Tests/packages.lock.json index becd21b3a4..cfe37ec63f 100644 --- a/Modules/Challenges/test/Challenges.Application.Tests/packages.lock.json +++ b/Modules/Challenges/test/Challenges.Application.Tests/packages.lock.json @@ -913,6 +913,7 @@ "Microsoft.Extensions.Identity.Core": "[10.0.10, 10.0.10]", "Microsoft.Extensions.Logging": "[10.0.10, 10.0.10]", "Npgsql.EntityFrameworkCore.PostgreSQL": "[10.0.3, 10.0.3]", + "OpenTelemetry.Api": "[1.17.0, )", "Polly": "[8.7.0, 8.7.0]", "RabbitMQ.Client": "[7.2.1, 7.2.1]", "Serilog": "[4.4.0, 4.4.0]" @@ -1367,6 +1368,12 @@ "Npgsql": "10.0.3" } }, + "OpenTelemetry.Api": { + "type": "CentralTransitive", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" + }, "Polly": { "type": "CentralTransitive", "requested": "[8.7.0, 8.7.0]", diff --git a/Modules/Devices/src/Devices.Application/Devices/Commands/ExecuteHousekeeping/Handler.cs b/Modules/Devices/src/Devices.Application/Devices/Commands/ExecuteHousekeeping/Handler.cs index 6aa8a93cc3..17c6931456 100644 --- a/Modules/Devices/src/Devices.Application/Devices/Commands/ExecuteHousekeeping/Handler.cs +++ b/Modules/Devices/src/Devices.Application/Devices/Commands/ExecuteHousekeeping/Handler.cs @@ -1,21 +1,17 @@ -using System.Diagnostics; -using Backbone.BuildingBlocks.Application.Housekeeping; +using Backbone.BuildingBlocks.Application.Housekeeping; using Backbone.Modules.Devices.Application.Infrastructure.Persistence.Repository; using Backbone.Modules.Devices.Domain.Entities.Identities; using MediatR; -using Microsoft.Extensions.Logging; namespace Backbone.Modules.Devices.Application.Devices.Commands.ExecuteHousekeeping; public class Handler : IRequestHandler { private readonly IIdentitiesRepository _identitiesRepository; - private readonly ILogger _logger; - public Handler(IIdentitiesRepository identitiesRepository, ILogger logger) + public Handler(IIdentitiesRepository identitiesRepository) { _identitiesRepository = identitiesRepository; - _logger = logger; } public async Task Handle(ExecuteHousekeepingCommand request, CancellationToken cancellationToken) @@ -26,19 +22,13 @@ public async Task Handle(ExecuteHousekeepingCommand request, CancellationToken c private async Task DeleteDeletionProcesses(CancellationToken cancellationToken) { - var stopwatch = Stopwatch.StartNew(); - var numberOfDeletedItems = await _identitiesRepository.DeleteDeletionProcesses(IdentityDeletionProcess.CanBeCleanedUp, cancellationToken); - stopwatch.Stop(); - - _logger.DataDeleted(numberOfDeletedItems, "identity deletion processes", stopwatch.ElapsedMilliseconds); + await HousekeepingTelemetry.TrackItemDeletion("identity deletion processes", ct => _identitiesRepository.DeleteDeletionProcesses(IdentityDeletionProcess.CanBeCleanedUp, ct), + cancellationToken); } private async Task DeleteDeletionProcessAuditLogEntries(CancellationToken cancellationToken) { - var stopwatch = Stopwatch.StartNew(); - var numberOfDeletedItems = await _identitiesRepository.DeleteDeletionProcessAuditLogEntries(IdentityDeletionProcessAuditLogEntry.CanBeCleanedUp, cancellationToken); - stopwatch.Stop(); - - _logger.DataDeleted(numberOfDeletedItems, "identity deletion process audit log entries", stopwatch.ElapsedMilliseconds); + await HousekeepingTelemetry.TrackItemDeletion("identity deletion process audit log entries", + ct => _identitiesRepository.DeleteDeletionProcessAuditLogEntries(IdentityDeletionProcessAuditLogEntry.CanBeCleanedUp, ct), cancellationToken); } } diff --git a/Modules/Devices/src/Devices.Application/packages.lock.json b/Modules/Devices/src/Devices.Application/packages.lock.json index 4942cbfedf..60726347be 100644 --- a/Modules/Devices/src/Devices.Application/packages.lock.json +++ b/Modules/Devices/src/Devices.Application/packages.lock.json @@ -782,6 +782,7 @@ "Microsoft.Extensions.Identity.Core": "[10.0.10, 10.0.10]", "Microsoft.Extensions.Logging": "[10.0.10, 10.0.10]", "Npgsql.EntityFrameworkCore.PostgreSQL": "[10.0.3, 10.0.3]", + "OpenTelemetry.Api": "[1.17.0, )", "Polly": "[8.7.0, 8.7.0]", "RabbitMQ.Client": "[7.2.1, 7.2.1]", "Serilog": "[4.4.0, 4.4.0]" @@ -1213,6 +1214,12 @@ "libsodium": "[1.0.22, 1.0.23)" } }, + "OpenTelemetry.Api": { + "type": "CentralTransitive", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" + }, "RabbitMQ.Client": { "type": "CentralTransitive", "requested": "[7.2.1, 7.2.1]", diff --git a/Modules/Devices/src/Devices.Infrastructure.Database.Postgres/packages.lock.json b/Modules/Devices/src/Devices.Infrastructure.Database.Postgres/packages.lock.json index fb94ff05fb..bed319bd4d 100644 --- a/Modules/Devices/src/Devices.Infrastructure.Database.Postgres/packages.lock.json +++ b/Modules/Devices/src/Devices.Infrastructure.Database.Postgres/packages.lock.json @@ -1031,6 +1031,7 @@ "Microsoft.Extensions.Identity.Core": "[10.0.10, 10.0.10]", "Microsoft.Extensions.Logging": "[10.0.10, 10.0.10]", "Npgsql.EntityFrameworkCore.PostgreSQL": "[10.0.3, 10.0.3]", + "OpenTelemetry.Api": "[1.17.0, )", "Polly": "[8.7.0, 8.7.0]", "RabbitMQ.Client": "[7.2.1, 7.2.1]", "Serilog": "[4.4.0, 4.4.0]" @@ -1571,6 +1572,12 @@ "OpenIddict.EntityFrameworkCore.Models": "7.6.0" } }, + "OpenTelemetry.Api": { + "type": "CentralTransitive", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" + }, "Polly": { "type": "CentralTransitive", "requested": "[8.7.0, 8.7.0]", diff --git a/Modules/Devices/src/Devices.Infrastructure.Database.SqlServer/packages.lock.json b/Modules/Devices/src/Devices.Infrastructure.Database.SqlServer/packages.lock.json index fb94ff05fb..bed319bd4d 100644 --- a/Modules/Devices/src/Devices.Infrastructure.Database.SqlServer/packages.lock.json +++ b/Modules/Devices/src/Devices.Infrastructure.Database.SqlServer/packages.lock.json @@ -1031,6 +1031,7 @@ "Microsoft.Extensions.Identity.Core": "[10.0.10, 10.0.10]", "Microsoft.Extensions.Logging": "[10.0.10, 10.0.10]", "Npgsql.EntityFrameworkCore.PostgreSQL": "[10.0.3, 10.0.3]", + "OpenTelemetry.Api": "[1.17.0, )", "Polly": "[8.7.0, 8.7.0]", "RabbitMQ.Client": "[7.2.1, 7.2.1]", "Serilog": "[4.4.0, 4.4.0]" @@ -1571,6 +1572,12 @@ "OpenIddict.EntityFrameworkCore.Models": "7.6.0" } }, + "OpenTelemetry.Api": { + "type": "CentralTransitive", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" + }, "Polly": { "type": "CentralTransitive", "requested": "[8.7.0, 8.7.0]", diff --git a/Modules/Devices/src/Devices.Infrastructure/packages.lock.json b/Modules/Devices/src/Devices.Infrastructure/packages.lock.json index d260fcc3e3..b1ae00ad4d 100644 --- a/Modules/Devices/src/Devices.Infrastructure/packages.lock.json +++ b/Modules/Devices/src/Devices.Infrastructure/packages.lock.json @@ -1186,6 +1186,7 @@ "Microsoft.Extensions.Identity.Core": "[10.0.10, 10.0.10]", "Microsoft.Extensions.Logging": "[10.0.10, 10.0.10]", "Npgsql.EntityFrameworkCore.PostgreSQL": "[10.0.3, 10.0.3]", + "OpenTelemetry.Api": "[1.17.0, )", "Polly": "[8.7.0, 8.7.0]", "RabbitMQ.Client": "[7.2.1, 7.2.1]", "Serilog": "[4.4.0, 4.4.0]" @@ -1558,6 +1559,12 @@ "OpenIddict.Abstractions": "7.6.0" } }, + "OpenTelemetry.Api": { + "type": "CentralTransitive", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" + }, "RabbitMQ.Client": { "type": "CentralTransitive", "requested": "[7.2.1, 7.2.1]", diff --git a/Modules/Devices/src/Devices.Module/packages.lock.json b/Modules/Devices/src/Devices.Module/packages.lock.json index 79a1bbcc2c..127ca1a74e 100644 --- a/Modules/Devices/src/Devices.Module/packages.lock.json +++ b/Modules/Devices/src/Devices.Module/packages.lock.json @@ -917,11 +917,6 @@ "OpenTelemetry.Api.ProviderBuilderExtensions": "1.17.0" } }, - "OpenTelemetry.Api": { - "type": "Transitive", - "resolved": "1.17.0", - "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" - }, "OpenTelemetry.Api.ProviderBuilderExtensions": { "type": "Transitive", "resolved": "1.17.0", @@ -1112,9 +1107,10 @@ "DotNetDiag.HealthChecks.SqlServer": "[10.0.10, 10.0.10]", "Microsoft.EntityFrameworkCore": "[10.0.10, 10.0.10]", "Microsoft.EntityFrameworkCore.Relational": "[10.0.10, 10.0.10]", - "OpenTelemetry.Exporter.Prometheus.AspNetCore": "[1.11.2-beta.1, 1.11.2-beta.1]", + "OpenTelemetry.Exporter.OpenTelemetryProtocol": "[1.17.0, )", "OpenTelemetry.Extensions.Hosting": "[1.17.0, 1.17.0]", "OpenTelemetry.Instrumentation.AspNetCore": "[1.17.0, 1.17.0]", + "OpenTelemetry.Instrumentation.EntityFrameworkCore": "[1.17.0-beta.1, )", "OpenTelemetry.Instrumentation.Http": "[1.17.0, 1.17.0]", "OpenTelemetry.Instrumentation.Runtime": "[1.17.0, 1.17.0]", "Polly": "[8.7.0, 8.7.0]", @@ -1175,6 +1171,7 @@ "Microsoft.Extensions.Identity.Core": "[10.0.10, 10.0.10]", "Microsoft.Extensions.Logging": "[10.0.10, 10.0.10]", "Npgsql.EntityFrameworkCore.PostgreSQL": "[10.0.3, 10.0.3]", + "OpenTelemetry.Api": "[1.17.0, )", "Polly": "[8.7.0, 8.7.0]", "RabbitMQ.Client": "[7.2.1, 7.2.1]", "Serilog": "[4.4.0, 4.4.0]" @@ -1774,13 +1771,19 @@ "OpenIddict.EntityFrameworkCore.Models": "7.6.0" } }, - "OpenTelemetry.Exporter.Prometheus.AspNetCore": { + "OpenTelemetry.Api": { + "type": "CentralTransitive", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" + }, + "OpenTelemetry.Exporter.OpenTelemetryProtocol": { "type": "CentralTransitive", - "requested": "[1.11.2-beta.1, 1.11.2-beta.1]", - "resolved": "1.11.2-beta.1", - "contentHash": "jouLU4VHpzyXuzF2yi/bpt9DoseZGyUudSdTFvylgIwIx6ST1bdI/AXNoJ4/n6HwMiso677ILLm/RM8DY+EYwA==", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "R1omQOrQpGlS0Cp5UIr/TAiuEA48JrPlgr1NPV5gESiTU7HhWU+ILe2EBSYb1fKdsSavZ7nZkHcUxAzofPqr2A==", "dependencies": { - "OpenTelemetry": "[1.11.2, 2.0.0)" + "OpenTelemetry": "1.17.0" } }, "OpenTelemetry.Extensions.Hosting": { @@ -1802,6 +1805,17 @@ "OpenTelemetry.Api.ProviderBuilderExtensions": "[1.17.0, 2.0.0)" } }, + "OpenTelemetry.Instrumentation.EntityFrameworkCore": { + "type": "CentralTransitive", + "requested": "[1.17.0-beta.1, )", + "resolved": "1.17.0-beta.1", + "contentHash": "BPSv1rk6qEkGZUGTNBfk7XmYqBAWdF3FBdjXEjVClp0bKUl6VCumlaosT84qvlK7YnHLCv5FFqJHx2N62TbKEw==", + "dependencies": { + "Microsoft.Extensions.Configuration": "10.0.0", + "Microsoft.Extensions.Options": "10.0.0", + "OpenTelemetry.Api.ProviderBuilderExtensions": "[1.17.0, 2.0.0)" + } + }, "OpenTelemetry.Instrumentation.Http": { "type": "CentralTransitive", "requested": "[1.17.0, 1.17.0]", diff --git a/Modules/Devices/test/Devices.Application.Tests/packages.lock.json b/Modules/Devices/test/Devices.Application.Tests/packages.lock.json index b4ba96f8a7..875d51adfd 100644 --- a/Modules/Devices/test/Devices.Application.Tests/packages.lock.json +++ b/Modules/Devices/test/Devices.Application.Tests/packages.lock.json @@ -1237,6 +1237,7 @@ "Microsoft.Extensions.Identity.Core": "[10.0.10, 10.0.10]", "Microsoft.Extensions.Logging": "[10.0.10, 10.0.10]", "Npgsql.EntityFrameworkCore.PostgreSQL": "[10.0.3, 10.0.3]", + "OpenTelemetry.Api": "[1.17.0, )", "Polly": "[8.7.0, 8.7.0]", "RabbitMQ.Client": "[7.2.1, 7.2.1]", "Serilog": "[4.4.0, 4.4.0]" @@ -1815,6 +1816,12 @@ "OpenIddict.EntityFrameworkCore.Models": "7.6.0" } }, + "OpenTelemetry.Api": { + "type": "CentralTransitive", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" + }, "Polly": { "type": "CentralTransitive", "requested": "[8.7.0, 8.7.0]", diff --git a/Modules/Devices/test/Devices.Domain.Tests/packages.lock.json b/Modules/Devices/test/Devices.Domain.Tests/packages.lock.json index 0aec2365d9..7c706dfc3f 100644 --- a/Modules/Devices/test/Devices.Domain.Tests/packages.lock.json +++ b/Modules/Devices/test/Devices.Domain.Tests/packages.lock.json @@ -784,6 +784,7 @@ "Microsoft.Extensions.Identity.Core": "[10.0.10, 10.0.10]", "Microsoft.Extensions.Logging": "[10.0.10, 10.0.10]", "Npgsql.EntityFrameworkCore.PostgreSQL": "[10.0.3, 10.0.3]", + "OpenTelemetry.Api": "[1.17.0, )", "Polly": "[8.7.0, 8.7.0]", "RabbitMQ.Client": "[7.2.1, 7.2.1]", "Serilog": "[4.4.0, 4.4.0]" @@ -1179,6 +1180,12 @@ "Npgsql": "10.0.3" } }, + "OpenTelemetry.Api": { + "type": "CentralTransitive", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" + }, "Polly": { "type": "CentralTransitive", "requested": "[8.7.0, 8.7.0]", diff --git a/Modules/Devices/test/Devices.Infrastructure.Tests/packages.lock.json b/Modules/Devices/test/Devices.Infrastructure.Tests/packages.lock.json index b4ba96f8a7..875d51adfd 100644 --- a/Modules/Devices/test/Devices.Infrastructure.Tests/packages.lock.json +++ b/Modules/Devices/test/Devices.Infrastructure.Tests/packages.lock.json @@ -1237,6 +1237,7 @@ "Microsoft.Extensions.Identity.Core": "[10.0.10, 10.0.10]", "Microsoft.Extensions.Logging": "[10.0.10, 10.0.10]", "Npgsql.EntityFrameworkCore.PostgreSQL": "[10.0.3, 10.0.3]", + "OpenTelemetry.Api": "[1.17.0, )", "Polly": "[8.7.0, 8.7.0]", "RabbitMQ.Client": "[7.2.1, 7.2.1]", "Serilog": "[4.4.0, 4.4.0]" @@ -1815,6 +1816,12 @@ "OpenIddict.EntityFrameworkCore.Models": "7.6.0" } }, + "OpenTelemetry.Api": { + "type": "CentralTransitive", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" + }, "Polly": { "type": "CentralTransitive", "requested": "[8.7.0, 8.7.0]", diff --git a/Modules/Files/src/Files.Application/Files/Commands/ExecuteHousekeeping/Handler.cs b/Modules/Files/src/Files.Application/Files/Commands/ExecuteHousekeeping/Handler.cs index 348500a9d2..b01c1f2573 100644 --- a/Modules/Files/src/Files.Application/Files/Commands/ExecuteHousekeeping/Handler.cs +++ b/Modules/Files/src/Files.Application/Files/Commands/ExecuteHousekeeping/Handler.cs @@ -1,8 +1,6 @@ -using System.Diagnostics; -using Backbone.BuildingBlocks.Application.Housekeeping; +using Backbone.BuildingBlocks.Application.Housekeeping; using Backbone.Modules.Files.Application.Infrastructure.Persistence.Repository; using MediatR; -using Microsoft.Extensions.Logging; using File = Backbone.Modules.Files.Domain.Entities.File; namespace Backbone.Modules.Files.Application.Files.Commands.ExecuteHousekeeping; @@ -10,12 +8,10 @@ namespace Backbone.Modules.Files.Application.Files.Commands.ExecuteHousekeeping; public class Handler : IRequestHandler { private readonly IFilesRepository _filesRepository; - private readonly ILogger _logger; - public Handler(IFilesRepository filesRepository, ILogger logger) + public Handler(IFilesRepository filesRepository) { _filesRepository = filesRepository; - _logger = logger; } public async Task Handle(ExecuteHousekeepingCommand request, CancellationToken cancellationToken) @@ -26,19 +22,11 @@ public async Task Handle(ExecuteHousekeepingCommand request, CancellationToken c private async Task DeleteFiles(CancellationToken cancellationToken) { - var stopwatch = Stopwatch.StartNew(); - var numberOfDeletedItems = await _filesRepository.Delete(File.CanBeCleanedUp, cancellationToken); - stopwatch.Stop(); - - _logger.DataDeleted(numberOfDeletedItems, "files", stopwatch.ElapsedMilliseconds); + await HousekeepingTelemetry.TrackItemDeletion("files", ct => _filesRepository.Delete(File.CanBeCleanedUp, ct), cancellationToken); } private async Task DeleteOrphanedBlobs(CancellationToken cancellationToken) { - var stopwatch = Stopwatch.StartNew(); - var numberOfDeletedItems = await _filesRepository.DeleteOrphanedBlobs(cancellationToken); - stopwatch.Stop(); - - _logger.DataDeleted(numberOfDeletedItems, "orphaned file contents", stopwatch.ElapsedMilliseconds); + await HousekeepingTelemetry.TrackItemDeletion("orphaned file contents", _filesRepository.DeleteOrphanedBlobs, cancellationToken); } } diff --git a/Modules/Files/src/Files.Application/packages.lock.json b/Modules/Files/src/Files.Application/packages.lock.json index fe7423ba22..178bf3b215 100644 --- a/Modules/Files/src/Files.Application/packages.lock.json +++ b/Modules/Files/src/Files.Application/packages.lock.json @@ -717,6 +717,7 @@ "Microsoft.Extensions.Identity.Core": "[10.0.10, 10.0.10]", "Microsoft.Extensions.Logging": "[10.0.10, 10.0.10]", "Npgsql.EntityFrameworkCore.PostgreSQL": "[10.0.3, 10.0.3]", + "OpenTelemetry.Api": "[1.17.0, )", "Polly": "[8.7.0, 8.7.0]", "RabbitMQ.Client": "[7.2.1, 7.2.1]", "Serilog": "[4.4.0, 4.4.0]" @@ -1102,6 +1103,12 @@ "Npgsql": "10.0.3" } }, + "OpenTelemetry.Api": { + "type": "CentralTransitive", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" + }, "Polly": { "type": "CentralTransitive", "requested": "[8.7.0, 8.7.0]", diff --git a/Modules/Files/src/Files.Infrastructure.Database.Postgres/packages.lock.json b/Modules/Files/src/Files.Infrastructure.Database.Postgres/packages.lock.json index 326a7a3955..4dd7d17cd3 100644 --- a/Modules/Files/src/Files.Infrastructure.Database.Postgres/packages.lock.json +++ b/Modules/Files/src/Files.Infrastructure.Database.Postgres/packages.lock.json @@ -707,6 +707,7 @@ "Microsoft.Extensions.Identity.Core": "[10.0.10, 10.0.10]", "Microsoft.Extensions.Logging": "[10.0.10, 10.0.10]", "Npgsql.EntityFrameworkCore.PostgreSQL": "[10.0.3, 10.0.3]", + "OpenTelemetry.Api": "[1.17.0, )", "Polly": "[8.7.0, 8.7.0]", "RabbitMQ.Client": "[7.2.1, 7.2.1]", "Serilog": "[4.4.0, 4.4.0]" @@ -1123,6 +1124,12 @@ "Npgsql": "10.0.3" } }, + "OpenTelemetry.Api": { + "type": "CentralTransitive", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" + }, "Polly": { "type": "CentralTransitive", "requested": "[8.7.0, 8.7.0]", diff --git a/Modules/Files/src/Files.Infrastructure.Database.SqlServer/packages.lock.json b/Modules/Files/src/Files.Infrastructure.Database.SqlServer/packages.lock.json index 326a7a3955..4dd7d17cd3 100644 --- a/Modules/Files/src/Files.Infrastructure.Database.SqlServer/packages.lock.json +++ b/Modules/Files/src/Files.Infrastructure.Database.SqlServer/packages.lock.json @@ -707,6 +707,7 @@ "Microsoft.Extensions.Identity.Core": "[10.0.10, 10.0.10]", "Microsoft.Extensions.Logging": "[10.0.10, 10.0.10]", "Npgsql.EntityFrameworkCore.PostgreSQL": "[10.0.3, 10.0.3]", + "OpenTelemetry.Api": "[1.17.0, )", "Polly": "[8.7.0, 8.7.0]", "RabbitMQ.Client": "[7.2.1, 7.2.1]", "Serilog": "[4.4.0, 4.4.0]" @@ -1123,6 +1124,12 @@ "Npgsql": "10.0.3" } }, + "OpenTelemetry.Api": { + "type": "CentralTransitive", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" + }, "Polly": { "type": "CentralTransitive", "requested": "[8.7.0, 8.7.0]", diff --git a/Modules/Files/src/Files.Infrastructure/packages.lock.json b/Modules/Files/src/Files.Infrastructure/packages.lock.json index 8a5a5d8bb5..e4714cd198 100644 --- a/Modules/Files/src/Files.Infrastructure/packages.lock.json +++ b/Modules/Files/src/Files.Infrastructure/packages.lock.json @@ -743,6 +743,7 @@ "Microsoft.Extensions.Identity.Core": "[10.0.10, 10.0.10]", "Microsoft.Extensions.Logging": "[10.0.10, 10.0.10]", "Npgsql.EntityFrameworkCore.PostgreSQL": "[10.0.3, 10.0.3]", + "OpenTelemetry.Api": "[1.17.0, )", "Polly": "[8.7.0, 8.7.0]", "RabbitMQ.Client": "[7.2.1, 7.2.1]", "Serilog": "[4.4.0, 4.4.0]" @@ -1111,6 +1112,12 @@ "Microsoft.Extensions.Primitives": "10.0.10" } }, + "OpenTelemetry.Api": { + "type": "CentralTransitive", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" + }, "Polly": { "type": "CentralTransitive", "requested": "[8.7.0, 8.7.0]", diff --git a/Modules/Files/src/Files.Module/packages.lock.json b/Modules/Files/src/Files.Module/packages.lock.json index d8e528dcb6..ec79607250 100644 --- a/Modules/Files/src/Files.Module/packages.lock.json +++ b/Modules/Files/src/Files.Module/packages.lock.json @@ -917,11 +917,6 @@ "OpenTelemetry.Api.ProviderBuilderExtensions": "1.17.0" } }, - "OpenTelemetry.Api": { - "type": "Transitive", - "resolved": "1.17.0", - "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" - }, "OpenTelemetry.Api.ProviderBuilderExtensions": { "type": "Transitive", "resolved": "1.17.0", @@ -1112,9 +1107,10 @@ "DotNetDiag.HealthChecks.SqlServer": "[10.0.10, 10.0.10]", "Microsoft.EntityFrameworkCore": "[10.0.10, 10.0.10]", "Microsoft.EntityFrameworkCore.Relational": "[10.0.10, 10.0.10]", - "OpenTelemetry.Exporter.Prometheus.AspNetCore": "[1.11.2-beta.1, 1.11.2-beta.1]", + "OpenTelemetry.Exporter.OpenTelemetryProtocol": "[1.17.0, )", "OpenTelemetry.Extensions.Hosting": "[1.17.0, 1.17.0]", "OpenTelemetry.Instrumentation.AspNetCore": "[1.17.0, 1.17.0]", + "OpenTelemetry.Instrumentation.EntityFrameworkCore": "[1.17.0-beta.1, )", "OpenTelemetry.Instrumentation.Http": "[1.17.0, 1.17.0]", "OpenTelemetry.Instrumentation.Runtime": "[1.17.0, 1.17.0]", "Polly": "[8.7.0, 8.7.0]", @@ -1175,6 +1171,7 @@ "Microsoft.Extensions.Identity.Core": "[10.0.10, 10.0.10]", "Microsoft.Extensions.Logging": "[10.0.10, 10.0.10]", "Npgsql.EntityFrameworkCore.PostgreSQL": "[10.0.3, 10.0.3]", + "OpenTelemetry.Api": "[1.17.0, )", "Polly": "[8.7.0, 8.7.0]", "RabbitMQ.Client": "[7.2.1, 7.2.1]", "Serilog": "[4.4.0, 4.4.0]" @@ -1802,13 +1799,19 @@ "OpenIddict.EntityFrameworkCore.Models": "7.6.0" } }, - "OpenTelemetry.Exporter.Prometheus.AspNetCore": { + "OpenTelemetry.Api": { + "type": "CentralTransitive", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" + }, + "OpenTelemetry.Exporter.OpenTelemetryProtocol": { "type": "CentralTransitive", - "requested": "[1.11.2-beta.1, 1.11.2-beta.1]", - "resolved": "1.11.2-beta.1", - "contentHash": "jouLU4VHpzyXuzF2yi/bpt9DoseZGyUudSdTFvylgIwIx6ST1bdI/AXNoJ4/n6HwMiso677ILLm/RM8DY+EYwA==", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "R1omQOrQpGlS0Cp5UIr/TAiuEA48JrPlgr1NPV5gESiTU7HhWU+ILe2EBSYb1fKdsSavZ7nZkHcUxAzofPqr2A==", "dependencies": { - "OpenTelemetry": "[1.11.2, 2.0.0)" + "OpenTelemetry": "1.17.0" } }, "OpenTelemetry.Extensions.Hosting": { @@ -1830,6 +1833,17 @@ "OpenTelemetry.Api.ProviderBuilderExtensions": "[1.17.0, 2.0.0)" } }, + "OpenTelemetry.Instrumentation.EntityFrameworkCore": { + "type": "CentralTransitive", + "requested": "[1.17.0-beta.1, )", + "resolved": "1.17.0-beta.1", + "contentHash": "BPSv1rk6qEkGZUGTNBfk7XmYqBAWdF3FBdjXEjVClp0bKUl6VCumlaosT84qvlK7YnHLCv5FFqJHx2N62TbKEw==", + "dependencies": { + "Microsoft.Extensions.Configuration": "10.0.0", + "Microsoft.Extensions.Options": "10.0.0", + "OpenTelemetry.Api.ProviderBuilderExtensions": "[1.17.0, 2.0.0)" + } + }, "OpenTelemetry.Instrumentation.Http": { "type": "CentralTransitive", "requested": "[1.17.0, 1.17.0]", diff --git a/Modules/Files/test/Files.Application.Tests/packages.lock.json b/Modules/Files/test/Files.Application.Tests/packages.lock.json index 993dad1ffd..e0195c9822 100644 --- a/Modules/Files/test/Files.Application.Tests/packages.lock.json +++ b/Modules/Files/test/Files.Application.Tests/packages.lock.json @@ -913,6 +913,7 @@ "Microsoft.Extensions.Identity.Core": "[10.0.10, 10.0.10]", "Microsoft.Extensions.Logging": "[10.0.10, 10.0.10]", "Npgsql.EntityFrameworkCore.PostgreSQL": "[10.0.3, 10.0.3]", + "OpenTelemetry.Api": "[1.17.0, )", "Polly": "[8.7.0, 8.7.0]", "RabbitMQ.Client": "[7.2.1, 7.2.1]", "Serilog": "[4.4.0, 4.4.0]" @@ -1355,6 +1356,12 @@ "Npgsql": "10.0.3" } }, + "OpenTelemetry.Api": { + "type": "CentralTransitive", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" + }, "Polly": { "type": "CentralTransitive", "requested": "[8.7.0, 8.7.0]", diff --git a/Modules/Files/test/Files.Domain.Tests/packages.lock.json b/Modules/Files/test/Files.Domain.Tests/packages.lock.json index b46eb9bcab..d9d00a121e 100644 --- a/Modules/Files/test/Files.Domain.Tests/packages.lock.json +++ b/Modules/Files/test/Files.Domain.Tests/packages.lock.json @@ -775,6 +775,7 @@ "Microsoft.Extensions.Identity.Core": "[10.0.10, 10.0.10]", "Microsoft.Extensions.Logging": "[10.0.10, 10.0.10]", "Npgsql.EntityFrameworkCore.PostgreSQL": "[10.0.3, 10.0.3]", + "OpenTelemetry.Api": "[1.17.0, )", "Polly": "[8.7.0, 8.7.0]", "RabbitMQ.Client": "[7.2.1, 7.2.1]", "Serilog": "[4.4.0, 4.4.0]" @@ -1149,6 +1150,12 @@ "Npgsql": "10.0.3" } }, + "OpenTelemetry.Api": { + "type": "CentralTransitive", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" + }, "Polly": { "type": "CentralTransitive", "requested": "[8.7.0, 8.7.0]", diff --git a/Modules/Files/test/Files.Infrastructure.Tests/packages.lock.json b/Modules/Files/test/Files.Infrastructure.Tests/packages.lock.json index ee08428377..a7c9d26bc5 100644 --- a/Modules/Files/test/Files.Infrastructure.Tests/packages.lock.json +++ b/Modules/Files/test/Files.Infrastructure.Tests/packages.lock.json @@ -913,6 +913,7 @@ "Microsoft.Extensions.Identity.Core": "[10.0.10, 10.0.10]", "Microsoft.Extensions.Logging": "[10.0.10, 10.0.10]", "Npgsql.EntityFrameworkCore.PostgreSQL": "[10.0.3, 10.0.3]", + "OpenTelemetry.Api": "[1.17.0, )", "Polly": "[8.7.0, 8.7.0]", "RabbitMQ.Client": "[7.2.1, 7.2.1]", "Serilog": "[4.4.0, 4.4.0]" @@ -1367,6 +1368,12 @@ "Npgsql": "10.0.3" } }, + "OpenTelemetry.Api": { + "type": "CentralTransitive", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" + }, "Polly": { "type": "CentralTransitive", "requested": "[8.7.0, 8.7.0]", diff --git a/Modules/Messages/src/Messages.Application/packages.lock.json b/Modules/Messages/src/Messages.Application/packages.lock.json index e604cb5ef3..b5f3bac59f 100644 --- a/Modules/Messages/src/Messages.Application/packages.lock.json +++ b/Modules/Messages/src/Messages.Application/packages.lock.json @@ -717,6 +717,7 @@ "Microsoft.Extensions.Identity.Core": "[10.0.10, 10.0.10]", "Microsoft.Extensions.Logging": "[10.0.10, 10.0.10]", "Npgsql.EntityFrameworkCore.PostgreSQL": "[10.0.3, 10.0.3]", + "OpenTelemetry.Api": "[1.17.0, )", "Polly": "[8.7.0, 8.7.0]", "RabbitMQ.Client": "[7.2.1, 7.2.1]", "Serilog": "[4.4.0, 4.4.0]" @@ -1102,6 +1103,12 @@ "Npgsql": "10.0.3" } }, + "OpenTelemetry.Api": { + "type": "CentralTransitive", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" + }, "Polly": { "type": "CentralTransitive", "requested": "[8.7.0, 8.7.0]", diff --git a/Modules/Messages/src/Messages.Infrastructure.Database.Postgres/packages.lock.json b/Modules/Messages/src/Messages.Infrastructure.Database.Postgres/packages.lock.json index 57c8867134..422efc74f4 100644 --- a/Modules/Messages/src/Messages.Infrastructure.Database.Postgres/packages.lock.json +++ b/Modules/Messages/src/Messages.Infrastructure.Database.Postgres/packages.lock.json @@ -707,6 +707,7 @@ "Microsoft.Extensions.Identity.Core": "[10.0.10, 10.0.10]", "Microsoft.Extensions.Logging": "[10.0.10, 10.0.10]", "Npgsql.EntityFrameworkCore.PostgreSQL": "[10.0.3, 10.0.3]", + "OpenTelemetry.Api": "[1.17.0, )", "Polly": "[8.7.0, 8.7.0]", "RabbitMQ.Client": "[7.2.1, 7.2.1]", "Serilog": "[4.4.0, 4.4.0]" @@ -1123,6 +1124,12 @@ "Npgsql": "10.0.3" } }, + "OpenTelemetry.Api": { + "type": "CentralTransitive", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" + }, "Polly": { "type": "CentralTransitive", "requested": "[8.7.0, 8.7.0]", diff --git a/Modules/Messages/src/Messages.Infrastructure.Database.SqlServer/packages.lock.json b/Modules/Messages/src/Messages.Infrastructure.Database.SqlServer/packages.lock.json index 57c8867134..422efc74f4 100644 --- a/Modules/Messages/src/Messages.Infrastructure.Database.SqlServer/packages.lock.json +++ b/Modules/Messages/src/Messages.Infrastructure.Database.SqlServer/packages.lock.json @@ -707,6 +707,7 @@ "Microsoft.Extensions.Identity.Core": "[10.0.10, 10.0.10]", "Microsoft.Extensions.Logging": "[10.0.10, 10.0.10]", "Npgsql.EntityFrameworkCore.PostgreSQL": "[10.0.3, 10.0.3]", + "OpenTelemetry.Api": "[1.17.0, )", "Polly": "[8.7.0, 8.7.0]", "RabbitMQ.Client": "[7.2.1, 7.2.1]", "Serilog": "[4.4.0, 4.4.0]" @@ -1123,6 +1124,12 @@ "Npgsql": "10.0.3" } }, + "OpenTelemetry.Api": { + "type": "CentralTransitive", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" + }, "Polly": { "type": "CentralTransitive", "requested": "[8.7.0, 8.7.0]", diff --git a/Modules/Messages/src/Messages.Infrastructure/packages.lock.json b/Modules/Messages/src/Messages.Infrastructure/packages.lock.json index 849090b0c2..d9f0c58c51 100644 --- a/Modules/Messages/src/Messages.Infrastructure/packages.lock.json +++ b/Modules/Messages/src/Messages.Infrastructure/packages.lock.json @@ -743,6 +743,7 @@ "Microsoft.Extensions.Identity.Core": "[10.0.10, 10.0.10]", "Microsoft.Extensions.Logging": "[10.0.10, 10.0.10]", "Npgsql.EntityFrameworkCore.PostgreSQL": "[10.0.3, 10.0.3]", + "OpenTelemetry.Api": "[1.17.0, )", "Polly": "[8.7.0, 8.7.0]", "RabbitMQ.Client": "[7.2.1, 7.2.1]", "Serilog": "[4.4.0, 4.4.0]" @@ -1111,6 +1112,12 @@ "Microsoft.Extensions.Primitives": "10.0.10" } }, + "OpenTelemetry.Api": { + "type": "CentralTransitive", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" + }, "Polly": { "type": "CentralTransitive", "requested": "[8.7.0, 8.7.0]", diff --git a/Modules/Messages/src/Messages.Module/packages.lock.json b/Modules/Messages/src/Messages.Module/packages.lock.json index 66d5f7d07d..25f7300cce 100644 --- a/Modules/Messages/src/Messages.Module/packages.lock.json +++ b/Modules/Messages/src/Messages.Module/packages.lock.json @@ -917,11 +917,6 @@ "OpenTelemetry.Api.ProviderBuilderExtensions": "1.17.0" } }, - "OpenTelemetry.Api": { - "type": "Transitive", - "resolved": "1.17.0", - "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" - }, "OpenTelemetry.Api.ProviderBuilderExtensions": { "type": "Transitive", "resolved": "1.17.0", @@ -1112,9 +1107,10 @@ "DotNetDiag.HealthChecks.SqlServer": "[10.0.10, 10.0.10]", "Microsoft.EntityFrameworkCore": "[10.0.10, 10.0.10]", "Microsoft.EntityFrameworkCore.Relational": "[10.0.10, 10.0.10]", - "OpenTelemetry.Exporter.Prometheus.AspNetCore": "[1.11.2-beta.1, 1.11.2-beta.1]", + "OpenTelemetry.Exporter.OpenTelemetryProtocol": "[1.17.0, )", "OpenTelemetry.Extensions.Hosting": "[1.17.0, 1.17.0]", "OpenTelemetry.Instrumentation.AspNetCore": "[1.17.0, 1.17.0]", + "OpenTelemetry.Instrumentation.EntityFrameworkCore": "[1.17.0-beta.1, )", "OpenTelemetry.Instrumentation.Http": "[1.17.0, 1.17.0]", "OpenTelemetry.Instrumentation.Runtime": "[1.17.0, 1.17.0]", "Polly": "[8.7.0, 8.7.0]", @@ -1175,6 +1171,7 @@ "Microsoft.Extensions.Identity.Core": "[10.0.10, 10.0.10]", "Microsoft.Extensions.Logging": "[10.0.10, 10.0.10]", "Npgsql.EntityFrameworkCore.PostgreSQL": "[10.0.3, 10.0.3]", + "OpenTelemetry.Api": "[1.17.0, )", "Polly": "[8.7.0, 8.7.0]", "RabbitMQ.Client": "[7.2.1, 7.2.1]", "Serilog": "[4.4.0, 4.4.0]" @@ -1802,13 +1799,19 @@ "OpenIddict.EntityFrameworkCore.Models": "7.6.0" } }, - "OpenTelemetry.Exporter.Prometheus.AspNetCore": { + "OpenTelemetry.Api": { + "type": "CentralTransitive", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" + }, + "OpenTelemetry.Exporter.OpenTelemetryProtocol": { "type": "CentralTransitive", - "requested": "[1.11.2-beta.1, 1.11.2-beta.1]", - "resolved": "1.11.2-beta.1", - "contentHash": "jouLU4VHpzyXuzF2yi/bpt9DoseZGyUudSdTFvylgIwIx6ST1bdI/AXNoJ4/n6HwMiso677ILLm/RM8DY+EYwA==", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "R1omQOrQpGlS0Cp5UIr/TAiuEA48JrPlgr1NPV5gESiTU7HhWU+ILe2EBSYb1fKdsSavZ7nZkHcUxAzofPqr2A==", "dependencies": { - "OpenTelemetry": "[1.11.2, 2.0.0)" + "OpenTelemetry": "1.17.0" } }, "OpenTelemetry.Extensions.Hosting": { @@ -1830,6 +1833,17 @@ "OpenTelemetry.Api.ProviderBuilderExtensions": "[1.17.0, 2.0.0)" } }, + "OpenTelemetry.Instrumentation.EntityFrameworkCore": { + "type": "CentralTransitive", + "requested": "[1.17.0-beta.1, )", + "resolved": "1.17.0-beta.1", + "contentHash": "BPSv1rk6qEkGZUGTNBfk7XmYqBAWdF3FBdjXEjVClp0bKUl6VCumlaosT84qvlK7YnHLCv5FFqJHx2N62TbKEw==", + "dependencies": { + "Microsoft.Extensions.Configuration": "10.0.0", + "Microsoft.Extensions.Options": "10.0.0", + "OpenTelemetry.Api.ProviderBuilderExtensions": "[1.17.0, 2.0.0)" + } + }, "OpenTelemetry.Instrumentation.Http": { "type": "CentralTransitive", "requested": "[1.17.0, 1.17.0]", diff --git a/Modules/Messages/test/Messages.Application.Tests/packages.lock.json b/Modules/Messages/test/Messages.Application.Tests/packages.lock.json index e1df3a35f7..ffa3a80c90 100644 --- a/Modules/Messages/test/Messages.Application.Tests/packages.lock.json +++ b/Modules/Messages/test/Messages.Application.Tests/packages.lock.json @@ -913,6 +913,7 @@ "Microsoft.Extensions.Identity.Core": "[10.0.10, 10.0.10]", "Microsoft.Extensions.Logging": "[10.0.10, 10.0.10]", "Npgsql.EntityFrameworkCore.PostgreSQL": "[10.0.3, 10.0.3]", + "OpenTelemetry.Api": "[1.17.0, )", "Polly": "[8.7.0, 8.7.0]", "RabbitMQ.Client": "[7.2.1, 7.2.1]", "Serilog": "[4.4.0, 4.4.0]" @@ -1367,6 +1368,12 @@ "Npgsql": "10.0.3" } }, + "OpenTelemetry.Api": { + "type": "CentralTransitive", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" + }, "Polly": { "type": "CentralTransitive", "requested": "[8.7.0, 8.7.0]", diff --git a/Modules/Messages/test/Messages.Domain.Tests/packages.lock.json b/Modules/Messages/test/Messages.Domain.Tests/packages.lock.json index 2387fe80cd..3f17afea03 100644 --- a/Modules/Messages/test/Messages.Domain.Tests/packages.lock.json +++ b/Modules/Messages/test/Messages.Domain.Tests/packages.lock.json @@ -784,6 +784,7 @@ "Microsoft.Extensions.Identity.Core": "[10.0.10, 10.0.10]", "Microsoft.Extensions.Logging": "[10.0.10, 10.0.10]", "Npgsql.EntityFrameworkCore.PostgreSQL": "[10.0.3, 10.0.3]", + "OpenTelemetry.Api": "[1.17.0, )", "Polly": "[8.7.0, 8.7.0]", "RabbitMQ.Client": "[7.2.1, 7.2.1]", "Serilog": "[4.4.0, 4.4.0]" @@ -1149,6 +1150,12 @@ "Npgsql": "10.0.3" } }, + "OpenTelemetry.Api": { + "type": "CentralTransitive", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" + }, "Polly": { "type": "CentralTransitive", "requested": "[8.7.0, 8.7.0]", diff --git a/Modules/Quotas/src/Quotas.Application/Metrics/MetricStatusesService.cs b/Modules/Quotas/src/Quotas.Application/Metrics/MetricStatusesService.cs index fe1dddecbc..661488dea2 100644 --- a/Modules/Quotas/src/Quotas.Application/Metrics/MetricStatusesService.cs +++ b/Modules/Quotas/src/Quotas.Application/Metrics/MetricStatusesService.cs @@ -1,3 +1,4 @@ +using System.Diagnostics; using Backbone.Modules.Quotas.Application.Infrastructure.Persistence.Repository; using Backbone.Modules.Quotas.Domain.Aggregates.Identities; using Backbone.Modules.Quotas.Domain.Metrics; @@ -18,7 +19,8 @@ public MetricStatusesService(MetricCalculatorFactory metricCalculatorFactory, II public async Task RecalculateMetricStatuses(List identityAddresses, List metrics, MetricUpdateType updateType, CancellationToken cancellationToken) { - var identities = await _identitiesRepository.ListByAddresses(identityAddresses, cancellationToken, track: true); + var identities = (await _identitiesRepository.ListByAddresses(identityAddresses, cancellationToken, track: true)).ToList(); + foreach (var identity in identities) { await identity.UpdateMetricStatuses(metrics, _metricCalculatorFactory, updateType, cancellationToken); diff --git a/Modules/Quotas/src/Quotas.Application/packages.lock.json b/Modules/Quotas/src/Quotas.Application/packages.lock.json index c9474369ec..9c3d60281d 100644 --- a/Modules/Quotas/src/Quotas.Application/packages.lock.json +++ b/Modules/Quotas/src/Quotas.Application/packages.lock.json @@ -707,6 +707,7 @@ "Microsoft.Extensions.Identity.Core": "[10.0.10, 10.0.10]", "Microsoft.Extensions.Logging": "[10.0.10, 10.0.10]", "Npgsql.EntityFrameworkCore.PostgreSQL": "[10.0.3, 10.0.3]", + "OpenTelemetry.Api": "[1.17.0, )", "Polly": "[8.7.0, 8.7.0]", "RabbitMQ.Client": "[7.2.1, 7.2.1]", "Serilog": "[4.4.0, 4.4.0]" @@ -1100,6 +1101,12 @@ "Npgsql": "10.0.3" } }, + "OpenTelemetry.Api": { + "type": "CentralTransitive", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" + }, "Polly": { "type": "CentralTransitive", "requested": "[8.7.0, 8.7.0]", diff --git a/Modules/Quotas/src/Quotas.Infrastructure.Database.Postgres/packages.lock.json b/Modules/Quotas/src/Quotas.Infrastructure.Database.Postgres/packages.lock.json index 6affd7afdc..60b6bc57a8 100644 --- a/Modules/Quotas/src/Quotas.Infrastructure.Database.Postgres/packages.lock.json +++ b/Modules/Quotas/src/Quotas.Infrastructure.Database.Postgres/packages.lock.json @@ -707,6 +707,7 @@ "Microsoft.Extensions.Identity.Core": "[10.0.10, 10.0.10]", "Microsoft.Extensions.Logging": "[10.0.10, 10.0.10]", "Npgsql.EntityFrameworkCore.PostgreSQL": "[10.0.3, 10.0.3]", + "OpenTelemetry.Api": "[1.17.0, )", "Polly": "[8.7.0, 8.7.0]", "RabbitMQ.Client": "[7.2.1, 7.2.1]", "Serilog": "[4.4.0, 4.4.0]" @@ -1142,6 +1143,12 @@ "Npgsql": "10.0.3" } }, + "OpenTelemetry.Api": { + "type": "CentralTransitive", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" + }, "Polly": { "type": "CentralTransitive", "requested": "[8.7.0, 8.7.0]", diff --git a/Modules/Quotas/src/Quotas.Infrastructure.Database.SqlServer/packages.lock.json b/Modules/Quotas/src/Quotas.Infrastructure.Database.SqlServer/packages.lock.json index 6affd7afdc..60b6bc57a8 100644 --- a/Modules/Quotas/src/Quotas.Infrastructure.Database.SqlServer/packages.lock.json +++ b/Modules/Quotas/src/Quotas.Infrastructure.Database.SqlServer/packages.lock.json @@ -707,6 +707,7 @@ "Microsoft.Extensions.Identity.Core": "[10.0.10, 10.0.10]", "Microsoft.Extensions.Logging": "[10.0.10, 10.0.10]", "Npgsql.EntityFrameworkCore.PostgreSQL": "[10.0.3, 10.0.3]", + "OpenTelemetry.Api": "[1.17.0, )", "Polly": "[8.7.0, 8.7.0]", "RabbitMQ.Client": "[7.2.1, 7.2.1]", "Serilog": "[4.4.0, 4.4.0]" @@ -1142,6 +1143,12 @@ "Npgsql": "10.0.3" } }, + "OpenTelemetry.Api": { + "type": "CentralTransitive", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" + }, "Polly": { "type": "CentralTransitive", "requested": "[8.7.0, 8.7.0]", diff --git a/Modules/Quotas/src/Quotas.Infrastructure/packages.lock.json b/Modules/Quotas/src/Quotas.Infrastructure/packages.lock.json index 4e9a5e8ac5..0fc839a16b 100644 --- a/Modules/Quotas/src/Quotas.Infrastructure/packages.lock.json +++ b/Modules/Quotas/src/Quotas.Infrastructure/packages.lock.json @@ -753,6 +753,7 @@ "Microsoft.Extensions.Identity.Core": "[10.0.10, 10.0.10]", "Microsoft.Extensions.Logging": "[10.0.10, 10.0.10]", "Npgsql.EntityFrameworkCore.PostgreSQL": "[10.0.3, 10.0.3]", + "OpenTelemetry.Api": "[1.17.0, )", "Polly": "[8.7.0, 8.7.0]", "RabbitMQ.Client": "[7.2.1, 7.2.1]", "Serilog": "[4.4.0, 4.4.0]" @@ -1129,6 +1130,12 @@ "Microsoft.Extensions.Primitives": "10.0.10" } }, + "OpenTelemetry.Api": { + "type": "CentralTransitive", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" + }, "Polly": { "type": "CentralTransitive", "requested": "[8.7.0, 8.7.0]", diff --git a/Modules/Quotas/src/Quotas.Module/packages.lock.json b/Modules/Quotas/src/Quotas.Module/packages.lock.json index 547e48c851..c48eb7b25c 100644 --- a/Modules/Quotas/src/Quotas.Module/packages.lock.json +++ b/Modules/Quotas/src/Quotas.Module/packages.lock.json @@ -917,11 +917,6 @@ "OpenTelemetry.Api.ProviderBuilderExtensions": "1.17.0" } }, - "OpenTelemetry.Api": { - "type": "Transitive", - "resolved": "1.17.0", - "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" - }, "OpenTelemetry.Api.ProviderBuilderExtensions": { "type": "Transitive", "resolved": "1.17.0", @@ -1112,9 +1107,10 @@ "DotNetDiag.HealthChecks.SqlServer": "[10.0.10, 10.0.10]", "Microsoft.EntityFrameworkCore": "[10.0.10, 10.0.10]", "Microsoft.EntityFrameworkCore.Relational": "[10.0.10, 10.0.10]", - "OpenTelemetry.Exporter.Prometheus.AspNetCore": "[1.11.2-beta.1, 1.11.2-beta.1]", + "OpenTelemetry.Exporter.OpenTelemetryProtocol": "[1.17.0, )", "OpenTelemetry.Extensions.Hosting": "[1.17.0, 1.17.0]", "OpenTelemetry.Instrumentation.AspNetCore": "[1.17.0, 1.17.0]", + "OpenTelemetry.Instrumentation.EntityFrameworkCore": "[1.17.0-beta.1, )", "OpenTelemetry.Instrumentation.Http": "[1.17.0, 1.17.0]", "OpenTelemetry.Instrumentation.Runtime": "[1.17.0, 1.17.0]", "Polly": "[8.7.0, 8.7.0]", @@ -1175,6 +1171,7 @@ "Microsoft.Extensions.Identity.Core": "[10.0.10, 10.0.10]", "Microsoft.Extensions.Logging": "[10.0.10, 10.0.10]", "Npgsql.EntityFrameworkCore.PostgreSQL": "[10.0.3, 10.0.3]", + "OpenTelemetry.Api": "[1.17.0, )", "Polly": "[8.7.0, 8.7.0]", "RabbitMQ.Client": "[7.2.1, 7.2.1]", "Serilog": "[4.4.0, 4.4.0]" @@ -1804,13 +1801,19 @@ "OpenIddict.EntityFrameworkCore.Models": "7.6.0" } }, - "OpenTelemetry.Exporter.Prometheus.AspNetCore": { + "OpenTelemetry.Api": { + "type": "CentralTransitive", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" + }, + "OpenTelemetry.Exporter.OpenTelemetryProtocol": { "type": "CentralTransitive", - "requested": "[1.11.2-beta.1, 1.11.2-beta.1]", - "resolved": "1.11.2-beta.1", - "contentHash": "jouLU4VHpzyXuzF2yi/bpt9DoseZGyUudSdTFvylgIwIx6ST1bdI/AXNoJ4/n6HwMiso677ILLm/RM8DY+EYwA==", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "R1omQOrQpGlS0Cp5UIr/TAiuEA48JrPlgr1NPV5gESiTU7HhWU+ILe2EBSYb1fKdsSavZ7nZkHcUxAzofPqr2A==", "dependencies": { - "OpenTelemetry": "[1.11.2, 2.0.0)" + "OpenTelemetry": "1.17.0" } }, "OpenTelemetry.Extensions.Hosting": { @@ -1832,6 +1835,17 @@ "OpenTelemetry.Api.ProviderBuilderExtensions": "[1.17.0, 2.0.0)" } }, + "OpenTelemetry.Instrumentation.EntityFrameworkCore": { + "type": "CentralTransitive", + "requested": "[1.17.0-beta.1, )", + "resolved": "1.17.0-beta.1", + "contentHash": "BPSv1rk6qEkGZUGTNBfk7XmYqBAWdF3FBdjXEjVClp0bKUl6VCumlaosT84qvlK7YnHLCv5FFqJHx2N62TbKEw==", + "dependencies": { + "Microsoft.Extensions.Configuration": "10.0.0", + "Microsoft.Extensions.Options": "10.0.0", + "OpenTelemetry.Api.ProviderBuilderExtensions": "[1.17.0, 2.0.0)" + } + }, "OpenTelemetry.Instrumentation.Http": { "type": "CentralTransitive", "requested": "[1.17.0, 1.17.0]", diff --git a/Modules/Quotas/test/Quotas.Application.Tests/packages.lock.json b/Modules/Quotas/test/Quotas.Application.Tests/packages.lock.json index 41465b5071..8a3c1baaba 100644 --- a/Modules/Quotas/test/Quotas.Application.Tests/packages.lock.json +++ b/Modules/Quotas/test/Quotas.Application.Tests/packages.lock.json @@ -913,6 +913,7 @@ "Microsoft.Extensions.Identity.Core": "[10.0.10, 10.0.10]", "Microsoft.Extensions.Logging": "[10.0.10, 10.0.10]", "Npgsql.EntityFrameworkCore.PostgreSQL": "[10.0.3, 10.0.3]", + "OpenTelemetry.Api": "[1.17.0, )", "Polly": "[8.7.0, 8.7.0]", "RabbitMQ.Client": "[7.2.1, 7.2.1]", "Serilog": "[4.4.0, 4.4.0]" @@ -1352,6 +1353,12 @@ "Npgsql": "10.0.3" } }, + "OpenTelemetry.Api": { + "type": "CentralTransitive", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" + }, "Polly": { "type": "CentralTransitive", "requested": "[8.7.0, 8.7.0]", diff --git a/Modules/Quotas/test/Quotas.Domain.Tests/packages.lock.json b/Modules/Quotas/test/Quotas.Domain.Tests/packages.lock.json index 0f582abca4..581530866a 100644 --- a/Modules/Quotas/test/Quotas.Domain.Tests/packages.lock.json +++ b/Modules/Quotas/test/Quotas.Domain.Tests/packages.lock.json @@ -781,6 +781,7 @@ "Microsoft.Extensions.Identity.Core": "[10.0.10, 10.0.10]", "Microsoft.Extensions.Logging": "[10.0.10, 10.0.10]", "Npgsql.EntityFrameworkCore.PostgreSQL": "[10.0.3, 10.0.3]", + "OpenTelemetry.Api": "[1.17.0, )", "Polly": "[8.7.0, 8.7.0]", "RabbitMQ.Client": "[7.2.1, 7.2.1]", "Serilog": "[4.4.0, 4.4.0]" @@ -1163,6 +1164,12 @@ "Npgsql": "10.0.3" } }, + "OpenTelemetry.Api": { + "type": "CentralTransitive", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" + }, "Polly": { "type": "CentralTransitive", "requested": "[8.7.0, 8.7.0]", diff --git a/Modules/Quotas/test/Quotas.Infrastructure.Tests/packages.lock.json b/Modules/Quotas/test/Quotas.Infrastructure.Tests/packages.lock.json index dc841262fb..578c87fb06 100644 --- a/Modules/Quotas/test/Quotas.Infrastructure.Tests/packages.lock.json +++ b/Modules/Quotas/test/Quotas.Infrastructure.Tests/packages.lock.json @@ -913,6 +913,7 @@ "Microsoft.Extensions.Identity.Core": "[10.0.10, 10.0.10]", "Microsoft.Extensions.Logging": "[10.0.10, 10.0.10]", "Npgsql.EntityFrameworkCore.PostgreSQL": "[10.0.3, 10.0.3]", + "OpenTelemetry.Api": "[1.17.0, )", "Polly": "[8.7.0, 8.7.0]", "RabbitMQ.Client": "[7.2.1, 7.2.1]", "Serilog": "[4.4.0, 4.4.0]" @@ -1001,20 +1002,29 @@ "Backbone.BuildingBlocks.Domain": "[1.0.0, )", "Backbone.Modules.Relationships.Common": "[1.0.0, )", "Backbone.Modules.Relationships.Domain": "[1.0.0, )", - "FluentValidation.DependencyInjectionExtensions": "[12.1.1, 12.1.1]" + "Backbone.UnitTestTools": "[1.0.0, )", + "FluentValidation.DependencyInjectionExtensions": "[12.1.1, 12.1.1]", + "GitHubActionsTestLogger": "[3.0.5, 3.0.5]", + "Microsoft.NET.Test.Sdk": "[18.8.1, 18.8.1]" } }, "Backbone.Modules.Relationships.Common": { "type": "Project", "dependencies": { - "FluentValidation": "[12.1.1, 12.1.1]" + "Backbone.UnitTestTools": "[1.0.0, )", + "FluentValidation": "[12.1.1, 12.1.1]", + "GitHubActionsTestLogger": "[3.0.5, 3.0.5]", + "Microsoft.NET.Test.Sdk": "[18.8.1, 18.8.1]" } }, "Backbone.Modules.Relationships.Domain": { "type": "Project", "dependencies": { "Backbone.DevelopmentKit.Identity": "[1.0.0, )", - "Backbone.Tooling": "[1.0.0, )" + "Backbone.Tooling": "[1.0.0, )", + "Backbone.UnitTestTools": "[1.0.0, )", + "GitHubActionsTestLogger": "[3.0.5, 3.0.5]", + "Microsoft.NET.Test.Sdk": "[18.8.1, 18.8.1]" } }, "Backbone.Modules.Relationships.Infrastructure": { @@ -1024,8 +1034,11 @@ "Backbone.BuildingBlocks.Infrastructure": "[1.0.0, )", "Backbone.Modules.Relationships.Application": "[1.0.0, )", "Backbone.Modules.Relationships.Domain": "[1.0.0, )", + "Backbone.UnitTestTools": "[1.0.0, )", + "GitHubActionsTestLogger": "[3.0.5, 3.0.5]", "Microsoft.EntityFrameworkCore": "[10.0.10, 10.0.10]", "Microsoft.EntityFrameworkCore.SqlServer": "[10.0.10, 10.0.10]", + "Microsoft.NET.Test.Sdk": "[18.8.1, 18.8.1]", "Npgsql.EntityFrameworkCore.PostgreSQL": "[10.0.3, 10.0.3]" } }, @@ -1460,6 +1473,12 @@ "Npgsql": "10.0.3" } }, + "OpenTelemetry.Api": { + "type": "CentralTransitive", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" + }, "Polly": { "type": "CentralTransitive", "requested": "[8.7.0, 8.7.0]", diff --git a/Modules/Relationships/src/Relationships.Application/Relationships/Commands/ExecuteHousekeeping/Handler.cs b/Modules/Relationships/src/Relationships.Application/Relationships/Commands/ExecuteHousekeeping/Handler.cs index 513ee29203..34f6cdff29 100644 --- a/Modules/Relationships/src/Relationships.Application/Relationships/Commands/ExecuteHousekeeping/Handler.cs +++ b/Modules/Relationships/src/Relationships.Application/Relationships/Commands/ExecuteHousekeeping/Handler.cs @@ -1,24 +1,20 @@ -using System.Diagnostics; -using Backbone.BuildingBlocks.Application.Housekeeping; +using Backbone.BuildingBlocks.Application.Housekeeping; using Backbone.Modules.Relationships.Application.Infrastructure.Persistence.Repository; using Backbone.Modules.Relationships.Domain.Aggregates.Relationships; using Backbone.Modules.Relationships.Domain.Aggregates.RelationshipTemplates; using MediatR; -using Microsoft.Extensions.Logging; namespace Backbone.Modules.Relationships.Application.Relationships.Commands.ExecuteHousekeeping; public class Handler : IRequestHandler { private readonly IRelationshipTemplatesRepository _relationshipTemplatesRepository; - private readonly ILogger _logger; private readonly IRelationshipsRepository _relationshipsRepository; - public Handler(IRelationshipTemplatesRepository relationshipTemplatesRepository, IRelationshipsRepository relationshipsRepository, ILogger logger) + public Handler(IRelationshipTemplatesRepository relationshipTemplatesRepository, IRelationshipsRepository relationshipsRepository) { _relationshipTemplatesRepository = relationshipTemplatesRepository; _relationshipsRepository = relationshipsRepository; - _logger = logger; } public async Task Handle(ExecuteHousekeepingCommand request, CancellationToken cancellationToken) @@ -29,20 +25,11 @@ public async Task Handle(ExecuteHousekeepingCommand request, CancellationToken c private async Task DeleteRelationshipTemplates(CancellationToken cancellationToken) { - var stopwatch = Stopwatch.StartNew(); - var numberOfDeletedItems = await _relationshipTemplatesRepository.Delete(RelationshipTemplate.CanBeCleanedUp, cancellationToken); - stopwatch.Stop(); - - _logger.DataDeleted(numberOfDeletedItems, "relationship templates", stopwatch.ElapsedMilliseconds); - + await HousekeepingTelemetry.TrackItemDeletion("relationship templates", ct => _relationshipTemplatesRepository.Delete(RelationshipTemplate.CanBeCleanedUp, ct), cancellationToken); } private async Task DeleteRelationships(CancellationToken cancellationToken) { - var stopwatch = Stopwatch.StartNew(); - var numberOfDeletedItems = await _relationshipsRepository.Delete(Relationship.CanBeCleanedUp, cancellationToken); - stopwatch.Stop(); - - _logger.DataDeleted(numberOfDeletedItems, "relationships", stopwatch.ElapsedMilliseconds); + await HousekeepingTelemetry.TrackItemDeletion("relationships", ct => _relationshipsRepository.Delete(Relationship.CanBeCleanedUp, ct), cancellationToken); } } diff --git a/Modules/Relationships/src/Relationships.Application/packages.lock.json b/Modules/Relationships/src/Relationships.Application/packages.lock.json index 4858842384..f6cb83af71 100644 --- a/Modules/Relationships/src/Relationships.Application/packages.lock.json +++ b/Modules/Relationships/src/Relationships.Application/packages.lock.json @@ -717,6 +717,7 @@ "Microsoft.Extensions.Identity.Core": "[10.0.10, 10.0.10]", "Microsoft.Extensions.Logging": "[10.0.10, 10.0.10]", "Npgsql.EntityFrameworkCore.PostgreSQL": "[10.0.3, 10.0.3]", + "OpenTelemetry.Api": "[1.17.0, )", "Polly": "[8.7.0, 8.7.0]", "RabbitMQ.Client": "[7.2.1, 7.2.1]", "Serilog": "[4.4.0, 4.4.0]" @@ -1108,6 +1109,12 @@ "Npgsql": "10.0.3" } }, + "OpenTelemetry.Api": { + "type": "CentralTransitive", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" + }, "Polly": { "type": "CentralTransitive", "requested": "[8.7.0, 8.7.0]", diff --git a/Modules/Relationships/src/Relationships.Infrastructure.Database.Postgres/packages.lock.json b/Modules/Relationships/src/Relationships.Infrastructure.Database.Postgres/packages.lock.json index cb779750b2..47c24c4966 100644 --- a/Modules/Relationships/src/Relationships.Infrastructure.Database.Postgres/packages.lock.json +++ b/Modules/Relationships/src/Relationships.Infrastructure.Database.Postgres/packages.lock.json @@ -707,6 +707,7 @@ "Microsoft.Extensions.Identity.Core": "[10.0.10, 10.0.10]", "Microsoft.Extensions.Logging": "[10.0.10, 10.0.10]", "Npgsql.EntityFrameworkCore.PostgreSQL": "[10.0.3, 10.0.3]", + "OpenTelemetry.Api": "[1.17.0, )", "Polly": "[8.7.0, 8.7.0]", "RabbitMQ.Client": "[7.2.1, 7.2.1]", "Serilog": "[4.4.0, 4.4.0]" @@ -1131,6 +1132,12 @@ "Npgsql": "10.0.3" } }, + "OpenTelemetry.Api": { + "type": "CentralTransitive", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" + }, "Polly": { "type": "CentralTransitive", "requested": "[8.7.0, 8.7.0]", diff --git a/Modules/Relationships/src/Relationships.Infrastructure.Database.SqlServer/packages.lock.json b/Modules/Relationships/src/Relationships.Infrastructure.Database.SqlServer/packages.lock.json index cb779750b2..47c24c4966 100644 --- a/Modules/Relationships/src/Relationships.Infrastructure.Database.SqlServer/packages.lock.json +++ b/Modules/Relationships/src/Relationships.Infrastructure.Database.SqlServer/packages.lock.json @@ -707,6 +707,7 @@ "Microsoft.Extensions.Identity.Core": "[10.0.10, 10.0.10]", "Microsoft.Extensions.Logging": "[10.0.10, 10.0.10]", "Npgsql.EntityFrameworkCore.PostgreSQL": "[10.0.3, 10.0.3]", + "OpenTelemetry.Api": "[1.17.0, )", "Polly": "[8.7.0, 8.7.0]", "RabbitMQ.Client": "[7.2.1, 7.2.1]", "Serilog": "[4.4.0, 4.4.0]" @@ -1131,6 +1132,12 @@ "Npgsql": "10.0.3" } }, + "OpenTelemetry.Api": { + "type": "CentralTransitive", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" + }, "Polly": { "type": "CentralTransitive", "requested": "[8.7.0, 8.7.0]", diff --git a/Modules/Relationships/src/Relationships.Infrastructure/packages.lock.json b/Modules/Relationships/src/Relationships.Infrastructure/packages.lock.json index 427e080fbe..d4bbd19692 100644 --- a/Modules/Relationships/src/Relationships.Infrastructure/packages.lock.json +++ b/Modules/Relationships/src/Relationships.Infrastructure/packages.lock.json @@ -743,6 +743,7 @@ "Microsoft.Extensions.Identity.Core": "[10.0.10, 10.0.10]", "Microsoft.Extensions.Logging": "[10.0.10, 10.0.10]", "Npgsql.EntityFrameworkCore.PostgreSQL": "[10.0.3, 10.0.3]", + "OpenTelemetry.Api": "[1.17.0, )", "Polly": "[8.7.0, 8.7.0]", "RabbitMQ.Client": "[7.2.1, 7.2.1]", "Serilog": "[4.4.0, 4.4.0]" @@ -1119,6 +1120,12 @@ "Microsoft.Extensions.Primitives": "10.0.10" } }, + "OpenTelemetry.Api": { + "type": "CentralTransitive", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" + }, "Polly": { "type": "CentralTransitive", "requested": "[8.7.0, 8.7.0]", diff --git a/Modules/Relationships/src/Relationships.Module/packages.lock.json b/Modules/Relationships/src/Relationships.Module/packages.lock.json index 02c70b327f..0a4f1b6d6f 100644 --- a/Modules/Relationships/src/Relationships.Module/packages.lock.json +++ b/Modules/Relationships/src/Relationships.Module/packages.lock.json @@ -917,11 +917,6 @@ "OpenTelemetry.Api.ProviderBuilderExtensions": "1.17.0" } }, - "OpenTelemetry.Api": { - "type": "Transitive", - "resolved": "1.17.0", - "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" - }, "OpenTelemetry.Api.ProviderBuilderExtensions": { "type": "Transitive", "resolved": "1.17.0", @@ -1112,9 +1107,10 @@ "DotNetDiag.HealthChecks.SqlServer": "[10.0.10, 10.0.10]", "Microsoft.EntityFrameworkCore": "[10.0.10, 10.0.10]", "Microsoft.EntityFrameworkCore.Relational": "[10.0.10, 10.0.10]", - "OpenTelemetry.Exporter.Prometheus.AspNetCore": "[1.11.2-beta.1, 1.11.2-beta.1]", + "OpenTelemetry.Exporter.OpenTelemetryProtocol": "[1.17.0, )", "OpenTelemetry.Extensions.Hosting": "[1.17.0, 1.17.0]", "OpenTelemetry.Instrumentation.AspNetCore": "[1.17.0, 1.17.0]", + "OpenTelemetry.Instrumentation.EntityFrameworkCore": "[1.17.0-beta.1, )", "OpenTelemetry.Instrumentation.Http": "[1.17.0, 1.17.0]", "OpenTelemetry.Instrumentation.Runtime": "[1.17.0, 1.17.0]", "Polly": "[8.7.0, 8.7.0]", @@ -1175,6 +1171,7 @@ "Microsoft.Extensions.Identity.Core": "[10.0.10, 10.0.10]", "Microsoft.Extensions.Logging": "[10.0.10, 10.0.10]", "Npgsql.EntityFrameworkCore.PostgreSQL": "[10.0.3, 10.0.3]", + "OpenTelemetry.Api": "[1.17.0, )", "Polly": "[8.7.0, 8.7.0]", "RabbitMQ.Client": "[7.2.1, 7.2.1]", "Serilog": "[4.4.0, 4.4.0]" @@ -1810,13 +1807,19 @@ "OpenIddict.EntityFrameworkCore.Models": "7.6.0" } }, - "OpenTelemetry.Exporter.Prometheus.AspNetCore": { + "OpenTelemetry.Api": { + "type": "CentralTransitive", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" + }, + "OpenTelemetry.Exporter.OpenTelemetryProtocol": { "type": "CentralTransitive", - "requested": "[1.11.2-beta.1, 1.11.2-beta.1]", - "resolved": "1.11.2-beta.1", - "contentHash": "jouLU4VHpzyXuzF2yi/bpt9DoseZGyUudSdTFvylgIwIx6ST1bdI/AXNoJ4/n6HwMiso677ILLm/RM8DY+EYwA==", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "R1omQOrQpGlS0Cp5UIr/TAiuEA48JrPlgr1NPV5gESiTU7HhWU+ILe2EBSYb1fKdsSavZ7nZkHcUxAzofPqr2A==", "dependencies": { - "OpenTelemetry": "[1.11.2, 2.0.0)" + "OpenTelemetry": "1.17.0" } }, "OpenTelemetry.Extensions.Hosting": { @@ -1838,6 +1841,17 @@ "OpenTelemetry.Api.ProviderBuilderExtensions": "[1.17.0, 2.0.0)" } }, + "OpenTelemetry.Instrumentation.EntityFrameworkCore": { + "type": "CentralTransitive", + "requested": "[1.17.0-beta.1, )", + "resolved": "1.17.0-beta.1", + "contentHash": "BPSv1rk6qEkGZUGTNBfk7XmYqBAWdF3FBdjXEjVClp0bKUl6VCumlaosT84qvlK7YnHLCv5FFqJHx2N62TbKEw==", + "dependencies": { + "Microsoft.Extensions.Configuration": "10.0.0", + "Microsoft.Extensions.Options": "10.0.0", + "OpenTelemetry.Api.ProviderBuilderExtensions": "[1.17.0, 2.0.0)" + } + }, "OpenTelemetry.Instrumentation.Http": { "type": "CentralTransitive", "requested": "[1.17.0, 1.17.0]", diff --git a/Modules/Relationships/test/Relationships.Application.Tests/packages.lock.json b/Modules/Relationships/test/Relationships.Application.Tests/packages.lock.json index dcd7649be9..77fd6a0e4c 100644 --- a/Modules/Relationships/test/Relationships.Application.Tests/packages.lock.json +++ b/Modules/Relationships/test/Relationships.Application.Tests/packages.lock.json @@ -913,6 +913,7 @@ "Microsoft.Extensions.Identity.Core": "[10.0.10, 10.0.10]", "Microsoft.Extensions.Logging": "[10.0.10, 10.0.10]", "Npgsql.EntityFrameworkCore.PostgreSQL": "[10.0.3, 10.0.3]", + "OpenTelemetry.Api": "[1.17.0, )", "Polly": "[8.7.0, 8.7.0]", "RabbitMQ.Client": "[7.2.1, 7.2.1]", "Serilog": "[4.4.0, 4.4.0]" @@ -1363,6 +1364,12 @@ "Npgsql": "10.0.3" } }, + "OpenTelemetry.Api": { + "type": "CentralTransitive", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" + }, "Polly": { "type": "CentralTransitive", "requested": "[8.7.0, 8.7.0]", diff --git a/Modules/Relationships/test/Relationships.Domain.Tests/packages.lock.json b/Modules/Relationships/test/Relationships.Domain.Tests/packages.lock.json index 09524736bb..5ff7847095 100644 --- a/Modules/Relationships/test/Relationships.Domain.Tests/packages.lock.json +++ b/Modules/Relationships/test/Relationships.Domain.Tests/packages.lock.json @@ -775,6 +775,7 @@ "Microsoft.Extensions.Identity.Core": "[10.0.10, 10.0.10]", "Microsoft.Extensions.Logging": "[10.0.10, 10.0.10]", "Npgsql.EntityFrameworkCore.PostgreSQL": "[10.0.3, 10.0.3]", + "OpenTelemetry.Api": "[1.17.0, )", "Polly": "[8.7.0, 8.7.0]", "RabbitMQ.Client": "[7.2.1, 7.2.1]", "Serilog": "[4.4.0, 4.4.0]" @@ -1149,6 +1150,12 @@ "Npgsql": "10.0.3" } }, + "OpenTelemetry.Api": { + "type": "CentralTransitive", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" + }, "Polly": { "type": "CentralTransitive", "requested": "[8.7.0, 8.7.0]", diff --git a/Modules/Relationships/test/Relationships.Infrastructure.Tests/packages.lock.json b/Modules/Relationships/test/Relationships.Infrastructure.Tests/packages.lock.json index 4379a50862..c28cb4a828 100644 --- a/Modules/Relationships/test/Relationships.Infrastructure.Tests/packages.lock.json +++ b/Modules/Relationships/test/Relationships.Infrastructure.Tests/packages.lock.json @@ -904,6 +904,7 @@ "Microsoft.Extensions.Identity.Core": "[10.0.10, 10.0.10]", "Microsoft.Extensions.Logging": "[10.0.10, 10.0.10]", "Npgsql.EntityFrameworkCore.PostgreSQL": "[10.0.3, 10.0.3]", + "OpenTelemetry.Api": "[1.17.0, )", "Polly": "[8.7.0, 8.7.0]", "RabbitMQ.Client": "[7.2.1, 7.2.1]", "Serilog": "[4.4.0, 4.4.0]" @@ -1375,6 +1376,12 @@ "Npgsql": "10.0.3" } }, + "OpenTelemetry.Api": { + "type": "CentralTransitive", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" + }, "Polly": { "type": "CentralTransitive", "requested": "[8.7.0, 8.7.0]", diff --git a/Modules/Synchronization/src/Synchronization.Application/SyncRuns/Commands/ExecuteHousekeeping/Handler.cs b/Modules/Synchronization/src/Synchronization.Application/SyncRuns/Commands/ExecuteHousekeeping/Handler.cs index 00647fc1a8..436c0347da 100644 --- a/Modules/Synchronization/src/Synchronization.Application/SyncRuns/Commands/ExecuteHousekeeping/Handler.cs +++ b/Modules/Synchronization/src/Synchronization.Application/SyncRuns/Commands/ExecuteHousekeeping/Handler.cs @@ -1,23 +1,19 @@ -using System.Diagnostics; -using Backbone.BuildingBlocks.Application.Housekeeping; +using Backbone.BuildingBlocks.Application.Housekeeping; using Backbone.Modules.Synchronization.Application.Infrastructure; using Backbone.Modules.Synchronization.Domain.Entities; using Backbone.Modules.Synchronization.Domain.Entities.Sync; using MediatR; using Microsoft.EntityFrameworkCore; -using Microsoft.Extensions.Logging; namespace Backbone.Modules.Synchronization.Application.SyncRuns.Commands.ExecuteHousekeeping; public class Handler : IRequestHandler { private readonly ISynchronizationDbContext _dbContext; - private readonly ILogger _logger; - public Handler(ISynchronizationDbContext dbContext, ILogger logger) + public Handler(ISynchronizationDbContext dbContext) { _dbContext = dbContext; - _logger = logger; } public async Task Handle(ExecuteHousekeepingCommand request, CancellationToken cancellationToken) @@ -28,19 +24,12 @@ public async Task Handle(ExecuteHousekeepingCommand request, CancellationToken c private async Task DeleteSyncRuns(CancellationToken cancellationToken) { - var stopwatch = Stopwatch.StartNew(); - var numberOfDeletedItems = await _dbContext.Set().Where(SyncRun.CanBeCleanedUp).ExecuteDeleteAsync(cancellationToken); - stopwatch.Stop(); - - _logger.DataDeleted(numberOfDeletedItems, "sync runs", stopwatch.ElapsedMilliseconds); + await HousekeepingTelemetry.TrackItemDeletion("sync runs", ct => _dbContext.Set().Where(SyncRun.CanBeCleanedUp).ExecuteDeleteAsync(ct), cancellationToken); } private async Task DeleteDatawalletModifications(CancellationToken cancellationToken) { - var stopwatch = Stopwatch.StartNew(); - var numberOfDeletedItems = await _dbContext.Set().Where(DatawalletModification.CanBeCleanedUp).ExecuteDeleteAsync(cancellationToken); - stopwatch.Stop(); - - _logger.DataDeleted(numberOfDeletedItems, "datawallet modifications", stopwatch.ElapsedMilliseconds); + await HousekeepingTelemetry.TrackItemDeletion("datawallet modifications", + ct => _dbContext.Set().Where(DatawalletModification.CanBeCleanedUp).ExecuteDeleteAsync(ct), cancellationToken); } } diff --git a/Modules/Synchronization/src/Synchronization.Application/packages.lock.json b/Modules/Synchronization/src/Synchronization.Application/packages.lock.json index a684b9c074..aaeaa40082 100644 --- a/Modules/Synchronization/src/Synchronization.Application/packages.lock.json +++ b/Modules/Synchronization/src/Synchronization.Application/packages.lock.json @@ -723,6 +723,7 @@ "Microsoft.Extensions.Identity.Core": "[10.0.10, 10.0.10]", "Microsoft.Extensions.Logging": "[10.0.10, 10.0.10]", "Npgsql.EntityFrameworkCore.PostgreSQL": "[10.0.3, 10.0.3]", + "OpenTelemetry.Api": "[1.17.0, )", "Polly": "[8.7.0, 8.7.0]", "RabbitMQ.Client": "[7.2.1, 7.2.1]", "Serilog": "[4.4.0, 4.4.0]" @@ -1102,6 +1103,12 @@ "Npgsql": "10.0.3" } }, + "OpenTelemetry.Api": { + "type": "CentralTransitive", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" + }, "Polly": { "type": "CentralTransitive", "requested": "[8.7.0, 8.7.0]", diff --git a/Modules/Synchronization/src/Synchronization.Infrastructure.Database.Postgres/packages.lock.json b/Modules/Synchronization/src/Synchronization.Infrastructure.Database.Postgres/packages.lock.json index b05b1b5faf..8300d5b400 100644 --- a/Modules/Synchronization/src/Synchronization.Infrastructure.Database.Postgres/packages.lock.json +++ b/Modules/Synchronization/src/Synchronization.Infrastructure.Database.Postgres/packages.lock.json @@ -712,6 +712,7 @@ "Microsoft.Extensions.Identity.Core": "[10.0.10, 10.0.10]", "Microsoft.Extensions.Logging": "[10.0.10, 10.0.10]", "Npgsql.EntityFrameworkCore.PostgreSQL": "[10.0.3, 10.0.3]", + "OpenTelemetry.Api": "[1.17.0, )", "Polly": "[8.7.0, 8.7.0]", "RabbitMQ.Client": "[7.2.1, 7.2.1]", "Serilog": "[4.4.0, 4.4.0]" @@ -1139,6 +1140,12 @@ "Npgsql": "10.0.3" } }, + "OpenTelemetry.Api": { + "type": "CentralTransitive", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" + }, "Polly": { "type": "CentralTransitive", "requested": "[8.7.0, 8.7.0]", diff --git a/Modules/Synchronization/src/Synchronization.Infrastructure.Database.SqlServer/packages.lock.json b/Modules/Synchronization/src/Synchronization.Infrastructure.Database.SqlServer/packages.lock.json index b05b1b5faf..8300d5b400 100644 --- a/Modules/Synchronization/src/Synchronization.Infrastructure.Database.SqlServer/packages.lock.json +++ b/Modules/Synchronization/src/Synchronization.Infrastructure.Database.SqlServer/packages.lock.json @@ -712,6 +712,7 @@ "Microsoft.Extensions.Identity.Core": "[10.0.10, 10.0.10]", "Microsoft.Extensions.Logging": "[10.0.10, 10.0.10]", "Npgsql.EntityFrameworkCore.PostgreSQL": "[10.0.3, 10.0.3]", + "OpenTelemetry.Api": "[1.17.0, )", "Polly": "[8.7.0, 8.7.0]", "RabbitMQ.Client": "[7.2.1, 7.2.1]", "Serilog": "[4.4.0, 4.4.0]" @@ -1139,6 +1140,12 @@ "Npgsql": "10.0.3" } }, + "OpenTelemetry.Api": { + "type": "CentralTransitive", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" + }, "Polly": { "type": "CentralTransitive", "requested": "[8.7.0, 8.7.0]", diff --git a/Modules/Synchronization/src/Synchronization.Infrastructure/packages.lock.json b/Modules/Synchronization/src/Synchronization.Infrastructure/packages.lock.json index 627a13a348..b1686af405 100644 --- a/Modules/Synchronization/src/Synchronization.Infrastructure/packages.lock.json +++ b/Modules/Synchronization/src/Synchronization.Infrastructure/packages.lock.json @@ -757,6 +757,7 @@ "Microsoft.Extensions.Identity.Core": "[10.0.10, 10.0.10]", "Microsoft.Extensions.Logging": "[10.0.10, 10.0.10]", "Npgsql.EntityFrameworkCore.PostgreSQL": "[10.0.3, 10.0.3]", + "OpenTelemetry.Api": "[1.17.0, )", "Polly": "[8.7.0, 8.7.0]", "RabbitMQ.Client": "[7.2.1, 7.2.1]", "Serilog": "[4.4.0, 4.4.0]" @@ -1126,6 +1127,12 @@ "Microsoft.Extensions.Primitives": "10.0.10" } }, + "OpenTelemetry.Api": { + "type": "CentralTransitive", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" + }, "Polly": { "type": "CentralTransitive", "requested": "[8.7.0, 8.7.0]", diff --git a/Modules/Synchronization/src/Synchronization.Module/packages.lock.json b/Modules/Synchronization/src/Synchronization.Module/packages.lock.json index bc46eaba24..8ac332c7d6 100644 --- a/Modules/Synchronization/src/Synchronization.Module/packages.lock.json +++ b/Modules/Synchronization/src/Synchronization.Module/packages.lock.json @@ -917,11 +917,6 @@ "OpenTelemetry.Api.ProviderBuilderExtensions": "1.17.0" } }, - "OpenTelemetry.Api": { - "type": "Transitive", - "resolved": "1.17.0", - "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" - }, "OpenTelemetry.Api.ProviderBuilderExtensions": { "type": "Transitive", "resolved": "1.17.0", @@ -1117,9 +1112,10 @@ "DotNetDiag.HealthChecks.SqlServer": "[10.0.10, 10.0.10]", "Microsoft.EntityFrameworkCore": "[10.0.10, 10.0.10]", "Microsoft.EntityFrameworkCore.Relational": "[10.0.10, 10.0.10]", - "OpenTelemetry.Exporter.Prometheus.AspNetCore": "[1.11.2-beta.1, 1.11.2-beta.1]", + "OpenTelemetry.Exporter.OpenTelemetryProtocol": "[1.17.0, )", "OpenTelemetry.Extensions.Hosting": "[1.17.0, 1.17.0]", "OpenTelemetry.Instrumentation.AspNetCore": "[1.17.0, 1.17.0]", + "OpenTelemetry.Instrumentation.EntityFrameworkCore": "[1.17.0-beta.1, )", "OpenTelemetry.Instrumentation.Http": "[1.17.0, 1.17.0]", "OpenTelemetry.Instrumentation.Runtime": "[1.17.0, 1.17.0]", "Polly": "[8.7.0, 8.7.0]", @@ -1180,6 +1176,7 @@ "Microsoft.Extensions.Identity.Core": "[10.0.10, 10.0.10]", "Microsoft.Extensions.Logging": "[10.0.10, 10.0.10]", "Npgsql.EntityFrameworkCore.PostgreSQL": "[10.0.3, 10.0.3]", + "OpenTelemetry.Api": "[1.17.0, )", "Polly": "[8.7.0, 8.7.0]", "RabbitMQ.Client": "[7.2.1, 7.2.1]", "Serilog": "[4.4.0, 4.4.0]" @@ -1818,13 +1815,19 @@ "OpenIddict.EntityFrameworkCore.Models": "7.6.0" } }, - "OpenTelemetry.Exporter.Prometheus.AspNetCore": { + "OpenTelemetry.Api": { + "type": "CentralTransitive", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" + }, + "OpenTelemetry.Exporter.OpenTelemetryProtocol": { "type": "CentralTransitive", - "requested": "[1.11.2-beta.1, 1.11.2-beta.1]", - "resolved": "1.11.2-beta.1", - "contentHash": "jouLU4VHpzyXuzF2yi/bpt9DoseZGyUudSdTFvylgIwIx6ST1bdI/AXNoJ4/n6HwMiso677ILLm/RM8DY+EYwA==", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "R1omQOrQpGlS0Cp5UIr/TAiuEA48JrPlgr1NPV5gESiTU7HhWU+ILe2EBSYb1fKdsSavZ7nZkHcUxAzofPqr2A==", "dependencies": { - "OpenTelemetry": "[1.11.2, 2.0.0)" + "OpenTelemetry": "1.17.0" } }, "OpenTelemetry.Extensions.Hosting": { @@ -1846,6 +1849,17 @@ "OpenTelemetry.Api.ProviderBuilderExtensions": "[1.17.0, 2.0.0)" } }, + "OpenTelemetry.Instrumentation.EntityFrameworkCore": { + "type": "CentralTransitive", + "requested": "[1.17.0-beta.1, )", + "resolved": "1.17.0-beta.1", + "contentHash": "BPSv1rk6qEkGZUGTNBfk7XmYqBAWdF3FBdjXEjVClp0bKUl6VCumlaosT84qvlK7YnHLCv5FFqJHx2N62TbKEw==", + "dependencies": { + "Microsoft.Extensions.Configuration": "10.0.0", + "Microsoft.Extensions.Options": "10.0.0", + "OpenTelemetry.Api.ProviderBuilderExtensions": "[1.17.0, 2.0.0)" + } + }, "OpenTelemetry.Instrumentation.Http": { "type": "CentralTransitive", "requested": "[1.17.0, 1.17.0]", diff --git a/Modules/Synchronization/test/Synchronization.Application.Tests/packages.lock.json b/Modules/Synchronization/test/Synchronization.Application.Tests/packages.lock.json index 06226946fe..1ce8bf6397 100644 --- a/Modules/Synchronization/test/Synchronization.Application.Tests/packages.lock.json +++ b/Modules/Synchronization/test/Synchronization.Application.Tests/packages.lock.json @@ -913,6 +913,7 @@ "Microsoft.Extensions.Identity.Core": "[10.0.10, 10.0.10]", "Microsoft.Extensions.Logging": "[10.0.10, 10.0.10]", "Npgsql.EntityFrameworkCore.PostgreSQL": "[10.0.3, 10.0.3]", + "OpenTelemetry.Api": "[1.17.0, )", "Polly": "[8.7.0, 8.7.0]", "RabbitMQ.Client": "[7.2.1, 7.2.1]", "Serilog": "[4.4.0, 4.4.0]" @@ -1369,6 +1370,12 @@ "Npgsql": "10.0.3" } }, + "OpenTelemetry.Api": { + "type": "CentralTransitive", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" + }, "Polly": { "type": "CentralTransitive", "requested": "[8.7.0, 8.7.0]", diff --git a/Modules/Synchronization/test/Synchronization.Domain.Tests/packages.lock.json b/Modules/Synchronization/test/Synchronization.Domain.Tests/packages.lock.json index 4397de7f45..23ebebd80c 100644 --- a/Modules/Synchronization/test/Synchronization.Domain.Tests/packages.lock.json +++ b/Modules/Synchronization/test/Synchronization.Domain.Tests/packages.lock.json @@ -775,6 +775,7 @@ "Microsoft.Extensions.Identity.Core": "[10.0.10, 10.0.10]", "Microsoft.Extensions.Logging": "[10.0.10, 10.0.10]", "Npgsql.EntityFrameworkCore.PostgreSQL": "[10.0.3, 10.0.3]", + "OpenTelemetry.Api": "[1.17.0, )", "Polly": "[8.7.0, 8.7.0]", "RabbitMQ.Client": "[7.2.1, 7.2.1]", "Serilog": "[4.4.0, 4.4.0]" @@ -1149,6 +1150,12 @@ "Npgsql": "10.0.3" } }, + "OpenTelemetry.Api": { + "type": "CentralTransitive", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" + }, "Polly": { "type": "CentralTransitive", "requested": "[8.7.0, 8.7.0]", diff --git a/Modules/Tags/src/Tags.Application/packages.lock.json b/Modules/Tags/src/Tags.Application/packages.lock.json index 053ade0a25..2391cb87af 100644 --- a/Modules/Tags/src/Tags.Application/packages.lock.json +++ b/Modules/Tags/src/Tags.Application/packages.lock.json @@ -707,6 +707,7 @@ "Microsoft.Extensions.Identity.Core": "[10.0.10, 10.0.10]", "Microsoft.Extensions.Logging": "[10.0.10, 10.0.10]", "Npgsql.EntityFrameworkCore.PostgreSQL": "[10.0.3, 10.0.3]", + "OpenTelemetry.Api": "[1.17.0, )", "Polly": "[8.7.0, 8.7.0]", "RabbitMQ.Client": "[7.2.1, 7.2.1]", "Serilog": "[4.4.0, 4.4.0]" @@ -1088,6 +1089,12 @@ "Npgsql": "10.0.3" } }, + "OpenTelemetry.Api": { + "type": "CentralTransitive", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" + }, "Polly": { "type": "CentralTransitive", "requested": "[8.7.0, 8.7.0]", diff --git a/Modules/Tags/src/Tags.Infrastructure/packages.lock.json b/Modules/Tags/src/Tags.Infrastructure/packages.lock.json index d1d4b1bc0a..2b2d7607be 100644 --- a/Modules/Tags/src/Tags.Infrastructure/packages.lock.json +++ b/Modules/Tags/src/Tags.Infrastructure/packages.lock.json @@ -707,6 +707,7 @@ "Microsoft.Extensions.Identity.Core": "[10.0.10, 10.0.10]", "Microsoft.Extensions.Logging": "[10.0.10, 10.0.10]", "Npgsql.EntityFrameworkCore.PostgreSQL": "[10.0.3, 10.0.3]", + "OpenTelemetry.Api": "[1.17.0, )", "Polly": "[8.7.0, 8.7.0]", "RabbitMQ.Client": "[7.2.1, 7.2.1]", "Serilog": "[4.4.0, 4.4.0]" @@ -1096,6 +1097,12 @@ "Npgsql": "10.0.3" } }, + "OpenTelemetry.Api": { + "type": "CentralTransitive", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" + }, "Polly": { "type": "CentralTransitive", "requested": "[8.7.0, 8.7.0]", diff --git a/Modules/Tags/src/Tags.Module/packages.lock.json b/Modules/Tags/src/Tags.Module/packages.lock.json index c35e89f2d5..522040fa37 100644 --- a/Modules/Tags/src/Tags.Module/packages.lock.json +++ b/Modules/Tags/src/Tags.Module/packages.lock.json @@ -717,6 +717,7 @@ "Microsoft.Extensions.Identity.Core": "[10.0.10, 10.0.10]", "Microsoft.Extensions.Logging": "[10.0.10, 10.0.10]", "Npgsql.EntityFrameworkCore.PostgreSQL": "[10.0.3, 10.0.3]", + "OpenTelemetry.Api": "[1.17.0, )", "Polly": "[8.7.0, 8.7.0]", "RabbitMQ.Client": "[7.2.1, 7.2.1]", "Serilog": "[4.4.0, 4.4.0]" @@ -1122,6 +1123,12 @@ "Npgsql": "10.0.3" } }, + "OpenTelemetry.Api": { + "type": "CentralTransitive", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" + }, "Polly": { "type": "CentralTransitive", "requested": "[8.7.0, 8.7.0]", diff --git a/Modules/Tokens/src/Tokens.Application/Tokens/Commands/ExecuteHousekeeping/Handler.cs b/Modules/Tokens/src/Tokens.Application/Tokens/Commands/ExecuteHousekeeping/Handler.cs index a300885cad..823d6ad127 100644 --- a/Modules/Tokens/src/Tokens.Application/Tokens/Commands/ExecuteHousekeeping/Handler.cs +++ b/Modules/Tokens/src/Tokens.Application/Tokens/Commands/ExecuteHousekeeping/Handler.cs @@ -1,21 +1,17 @@ -using System.Diagnostics; -using Backbone.BuildingBlocks.Application.Housekeeping; +using Backbone.BuildingBlocks.Application.Housekeeping; using Backbone.Modules.Tokens.Application.Infrastructure.Persistence.Repository; using Backbone.Modules.Tokens.Domain.Entities; using MediatR; -using Microsoft.Extensions.Logging; namespace Backbone.Modules.Tokens.Application.Tokens.Commands.ExecuteHousekeeping; public class Handler : IRequestHandler { private readonly ITokensRepository _tokensRepository; - private readonly ILogger _logger; - public Handler(ITokensRepository tokensRepository, ILogger logger) + public Handler(ITokensRepository tokensRepository) { _tokensRepository = tokensRepository; - _logger = logger; } public async Task Handle(ExecuteHousekeepingCommand request, CancellationToken cancellationToken) @@ -25,10 +21,6 @@ public async Task Handle(ExecuteHousekeepingCommand request, CancellationToken c private async Task DeleteTokens(CancellationToken cancellationToken) { - var stopwatch = Stopwatch.StartNew(); - var numberOfDeletedItems = await _tokensRepository.Delete(Token.CanBeCleanedUp, cancellationToken); - stopwatch.Stop(); - - _logger.DataDeleted(numberOfDeletedItems, "tokens", stopwatch.ElapsedMilliseconds); + await HousekeepingTelemetry.TrackItemDeletion("tokens", ct => _tokensRepository.Delete(Token.CanBeCleanedUp, ct), cancellationToken); } } diff --git a/Modules/Tokens/src/Tokens.Application/packages.lock.json b/Modules/Tokens/src/Tokens.Application/packages.lock.json index e6794b17ef..b0f37d0061 100644 --- a/Modules/Tokens/src/Tokens.Application/packages.lock.json +++ b/Modules/Tokens/src/Tokens.Application/packages.lock.json @@ -726,6 +726,7 @@ "Microsoft.Extensions.Identity.Core": "[10.0.10, 10.0.10]", "Microsoft.Extensions.Logging": "[10.0.10, 10.0.10]", "Npgsql.EntityFrameworkCore.PostgreSQL": "[10.0.3, 10.0.3]", + "OpenTelemetry.Api": "[1.17.0, )", "Polly": "[8.7.0, 8.7.0]", "RabbitMQ.Client": "[7.2.1, 7.2.1]", "Serilog": "[4.4.0, 4.4.0]" @@ -1111,6 +1112,12 @@ "Npgsql": "10.0.3" } }, + "OpenTelemetry.Api": { + "type": "CentralTransitive", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" + }, "RabbitMQ.Client": { "type": "CentralTransitive", "requested": "[7.2.1, 7.2.1]", diff --git a/Modules/Tokens/src/Tokens.Infrastructure.Database.Postgres/packages.lock.json b/Modules/Tokens/src/Tokens.Infrastructure.Database.Postgres/packages.lock.json index bc0a937c77..694195933b 100644 --- a/Modules/Tokens/src/Tokens.Infrastructure.Database.Postgres/packages.lock.json +++ b/Modules/Tokens/src/Tokens.Infrastructure.Database.Postgres/packages.lock.json @@ -716,6 +716,7 @@ "Microsoft.Extensions.Identity.Core": "[10.0.10, 10.0.10]", "Microsoft.Extensions.Logging": "[10.0.10, 10.0.10]", "Npgsql.EntityFrameworkCore.PostgreSQL": "[10.0.3, 10.0.3]", + "OpenTelemetry.Api": "[1.17.0, )", "Polly": "[8.7.0, 8.7.0]", "RabbitMQ.Client": "[7.2.1, 7.2.1]", "Serilog": "[4.4.0, 4.4.0]" @@ -1134,6 +1135,12 @@ "Npgsql": "10.0.3" } }, + "OpenTelemetry.Api": { + "type": "CentralTransitive", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" + }, "RabbitMQ.Client": { "type": "CentralTransitive", "requested": "[7.2.1, 7.2.1]", diff --git a/Modules/Tokens/src/Tokens.Infrastructure.Database.SqlServer/packages.lock.json b/Modules/Tokens/src/Tokens.Infrastructure.Database.SqlServer/packages.lock.json index bc0a937c77..694195933b 100644 --- a/Modules/Tokens/src/Tokens.Infrastructure.Database.SqlServer/packages.lock.json +++ b/Modules/Tokens/src/Tokens.Infrastructure.Database.SqlServer/packages.lock.json @@ -716,6 +716,7 @@ "Microsoft.Extensions.Identity.Core": "[10.0.10, 10.0.10]", "Microsoft.Extensions.Logging": "[10.0.10, 10.0.10]", "Npgsql.EntityFrameworkCore.PostgreSQL": "[10.0.3, 10.0.3]", + "OpenTelemetry.Api": "[1.17.0, )", "Polly": "[8.7.0, 8.7.0]", "RabbitMQ.Client": "[7.2.1, 7.2.1]", "Serilog": "[4.4.0, 4.4.0]" @@ -1134,6 +1135,12 @@ "Npgsql": "10.0.3" } }, + "OpenTelemetry.Api": { + "type": "CentralTransitive", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" + }, "RabbitMQ.Client": { "type": "CentralTransitive", "requested": "[7.2.1, 7.2.1]", diff --git a/Modules/Tokens/src/Tokens.Infrastructure/packages.lock.json b/Modules/Tokens/src/Tokens.Infrastructure/packages.lock.json index 2a653ae72b..b793a355ce 100644 --- a/Modules/Tokens/src/Tokens.Infrastructure/packages.lock.json +++ b/Modules/Tokens/src/Tokens.Infrastructure/packages.lock.json @@ -752,6 +752,7 @@ "Microsoft.Extensions.Identity.Core": "[10.0.10, 10.0.10]", "Microsoft.Extensions.Logging": "[10.0.10, 10.0.10]", "Npgsql.EntityFrameworkCore.PostgreSQL": "[10.0.3, 10.0.3]", + "OpenTelemetry.Api": "[1.17.0, )", "Polly": "[8.7.0, 8.7.0]", "RabbitMQ.Client": "[7.2.1, 7.2.1]", "Serilog": "[4.4.0, 4.4.0]" @@ -1121,6 +1122,12 @@ "Microsoft.Extensions.Primitives": "10.0.10" } }, + "OpenTelemetry.Api": { + "type": "CentralTransitive", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" + }, "RabbitMQ.Client": { "type": "CentralTransitive", "requested": "[7.2.1, 7.2.1]", diff --git a/Modules/Tokens/src/Tokens.Module/packages.lock.json b/Modules/Tokens/src/Tokens.Module/packages.lock.json index fb9da6ef28..3cc976ed05 100644 --- a/Modules/Tokens/src/Tokens.Module/packages.lock.json +++ b/Modules/Tokens/src/Tokens.Module/packages.lock.json @@ -917,11 +917,6 @@ "OpenTelemetry.Api.ProviderBuilderExtensions": "1.17.0" } }, - "OpenTelemetry.Api": { - "type": "Transitive", - "resolved": "1.17.0", - "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" - }, "OpenTelemetry.Api.ProviderBuilderExtensions": { "type": "Transitive", "resolved": "1.17.0", @@ -1112,9 +1107,10 @@ "DotNetDiag.HealthChecks.SqlServer": "[10.0.10, 10.0.10]", "Microsoft.EntityFrameworkCore": "[10.0.10, 10.0.10]", "Microsoft.EntityFrameworkCore.Relational": "[10.0.10, 10.0.10]", - "OpenTelemetry.Exporter.Prometheus.AspNetCore": "[1.11.2-beta.1, 1.11.2-beta.1]", + "OpenTelemetry.Exporter.OpenTelemetryProtocol": "[1.17.0, )", "OpenTelemetry.Extensions.Hosting": "[1.17.0, 1.17.0]", "OpenTelemetry.Instrumentation.AspNetCore": "[1.17.0, 1.17.0]", + "OpenTelemetry.Instrumentation.EntityFrameworkCore": "[1.17.0-beta.1, )", "OpenTelemetry.Instrumentation.Http": "[1.17.0, 1.17.0]", "OpenTelemetry.Instrumentation.Runtime": "[1.17.0, 1.17.0]", "Polly": "[8.7.0, 8.7.0]", @@ -1175,6 +1171,7 @@ "Microsoft.Extensions.Identity.Core": "[10.0.10, 10.0.10]", "Microsoft.Extensions.Logging": "[10.0.10, 10.0.10]", "Npgsql.EntityFrameworkCore.PostgreSQL": "[10.0.3, 10.0.3]", + "OpenTelemetry.Api": "[1.17.0, )", "Polly": "[8.7.0, 8.7.0]", "RabbitMQ.Client": "[7.2.1, 7.2.1]", "Serilog": "[4.4.0, 4.4.0]" @@ -1806,13 +1803,19 @@ "OpenIddict.EntityFrameworkCore.Models": "7.6.0" } }, - "OpenTelemetry.Exporter.Prometheus.AspNetCore": { + "OpenTelemetry.Api": { + "type": "CentralTransitive", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" + }, + "OpenTelemetry.Exporter.OpenTelemetryProtocol": { "type": "CentralTransitive", - "requested": "[1.11.2-beta.1, 1.11.2-beta.1]", - "resolved": "1.11.2-beta.1", - "contentHash": "jouLU4VHpzyXuzF2yi/bpt9DoseZGyUudSdTFvylgIwIx6ST1bdI/AXNoJ4/n6HwMiso677ILLm/RM8DY+EYwA==", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "R1omQOrQpGlS0Cp5UIr/TAiuEA48JrPlgr1NPV5gESiTU7HhWU+ILe2EBSYb1fKdsSavZ7nZkHcUxAzofPqr2A==", "dependencies": { - "OpenTelemetry": "[1.11.2, 2.0.0)" + "OpenTelemetry": "1.17.0" } }, "OpenTelemetry.Extensions.Hosting": { @@ -1834,6 +1837,17 @@ "OpenTelemetry.Api.ProviderBuilderExtensions": "[1.17.0, 2.0.0)" } }, + "OpenTelemetry.Instrumentation.EntityFrameworkCore": { + "type": "CentralTransitive", + "requested": "[1.17.0-beta.1, )", + "resolved": "1.17.0-beta.1", + "contentHash": "BPSv1rk6qEkGZUGTNBfk7XmYqBAWdF3FBdjXEjVClp0bKUl6VCumlaosT84qvlK7YnHLCv5FFqJHx2N62TbKEw==", + "dependencies": { + "Microsoft.Extensions.Configuration": "10.0.0", + "Microsoft.Extensions.Options": "10.0.0", + "OpenTelemetry.Api.ProviderBuilderExtensions": "[1.17.0, 2.0.0)" + } + }, "OpenTelemetry.Instrumentation.Http": { "type": "CentralTransitive", "requested": "[1.17.0, 1.17.0]", diff --git a/Modules/Tokens/test/Tokens.Application.Tests/packages.lock.json b/Modules/Tokens/test/Tokens.Application.Tests/packages.lock.json index 86383cc6f4..eb094aaecb 100644 --- a/Modules/Tokens/test/Tokens.Application.Tests/packages.lock.json +++ b/Modules/Tokens/test/Tokens.Application.Tests/packages.lock.json @@ -922,6 +922,7 @@ "Microsoft.Extensions.Identity.Core": "[10.0.10, 10.0.10]", "Microsoft.Extensions.Logging": "[10.0.10, 10.0.10]", "Npgsql.EntityFrameworkCore.PostgreSQL": "[10.0.3, 10.0.3]", + "OpenTelemetry.Api": "[1.17.0, )", "Polly": "[8.7.0, 8.7.0]", "RabbitMQ.Client": "[7.2.1, 7.2.1]", "Serilog": "[4.4.0, 4.4.0]" @@ -1378,6 +1379,12 @@ "Npgsql": "10.0.3" } }, + "OpenTelemetry.Api": { + "type": "CentralTransitive", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" + }, "RabbitMQ.Client": { "type": "CentralTransitive", "requested": "[7.2.1, 7.2.1]", diff --git a/Modules/Tokens/test/Tokens.Domain.Tests/packages.lock.json b/Modules/Tokens/test/Tokens.Domain.Tests/packages.lock.json index ec41395032..533d364c63 100644 --- a/Modules/Tokens/test/Tokens.Domain.Tests/packages.lock.json +++ b/Modules/Tokens/test/Tokens.Domain.Tests/packages.lock.json @@ -784,6 +784,7 @@ "Microsoft.Extensions.Identity.Core": "[10.0.10, 10.0.10]", "Microsoft.Extensions.Logging": "[10.0.10, 10.0.10]", "Npgsql.EntityFrameworkCore.PostgreSQL": "[10.0.3, 10.0.3]", + "OpenTelemetry.Api": "[1.17.0, )", "Polly": "[8.7.0, 8.7.0]", "RabbitMQ.Client": "[7.2.1, 7.2.1]", "Serilog": "[4.4.0, 4.4.0]" @@ -1158,6 +1159,12 @@ "Npgsql": "10.0.3" } }, + "OpenTelemetry.Api": { + "type": "CentralTransitive", + "requested": "[1.17.0, )", + "resolved": "1.17.0", + "contentHash": "mSBxzomZgHIJu9CyVNqyDu/n2JHEtqVgfcCD1Br0cV5iLYogjZOMqhlVLt99PEp+0KGBNUR3GXgeOdN2GR3F9g==" + }, "RabbitMQ.Client": { "type": "CentralTransitive", "requested": "[7.2.1, 7.2.1]", diff --git a/appsettings.override.json b/appsettings.override.json index f732a6719c..2262b87dd7 100644 --- a/appsettings.override.json +++ b/appsettings.override.json @@ -1,292 +1,288 @@ { - "RunMigrations": true, - "Authentication": { - "JwtSigningCertificate": "MIIJ7wIBAzCCCaUGCSqGSIb3DQEHAaCCCZYEggmSMIIJjjCCBAIGCSqGSIb3DQEHBqCCA/MwggPvAgEAMIID6AYJKoZIhvcNAQcBMFcGCSqGSIb3DQEFDTBKMCkGCSqGSIb3DQEFDDAcBAiIVEGIEnzbyAICCAAwDAYIKoZIhvcNAgkFADAdBglghkgBZQMEASoEEC1tOaulJJjkAl2W7xeF3G6AggOAm1VdXzAQ6MhHabp6+rzEuaAyBpuMi8zD8OEl8/xMv47UsFUor38aZjQd14qTTLz5MnksI/qgjQHLuMEmN1eWARsUBkeYvLuz0icl2q9A5Rn9CaKHIemQWq9mIobq3XnXhwDFEd+G/WgjNoK65Ndu20pnuc9LDlfq6fx2eXDbHAWLeUTnlQsEY4M/owNKIjlO/VsYJCshvEPlbtCnyzXwkrtQ5i2XufIJsfX0qoK/dXfoMVUjPxa/L8uR40bAWc1LVkvO0Ox4rY9VCtC1eHe3fcS48AaYCGRMpkZ7N+nDOb7lPs7BcxVoIrj/PkqiNI4rMOZVEgz21OWhueIjBv4gxfV+vW7IZ7xWvC1uUYIKEKEl6mk8KJ5zruO3tObX70+4saBiTNd/76+CVR4qCSwYcD7bZjpMOiaVFyxy0ay3dCwoivLK1jWNFJ25tngYpXKGCtOP0/Zi1fyseo4C54Ef5Yoo+BG3bkKR9VHChWzbB+b1p2lOwfBWIWlGjoZ+expyBjnk+FWrFDZeMknpW3PANCtcT/zqzqPKG3g4DAnSx9xDqvR7GBEgUlaUBAsCM3NvbahzevFFNE21aVajmTpSdejqvgNgvHPHA+BHfhMYx3mcMEkZ+phEHrWRSg925Iy64afL9/XvxoB/uFOYta/ir4ZqCbOy+yrc4+ppQlvLEIUnL4BGWcZ7d2NNRHWOHg0UqzxakezWhoGh1DDWfNdEj+eoa8DTvQr9hX0DQljym1I51qYdrv18rSf+MQj9jhBgQ77WBCX4sDkj4W9d7kKah8Fa0v+4bB1CqrETAsCESvBzSNyYEXKpyjdR/m8w/dti13Kz9ptvi8zd70tcqsqjaB3Qaz3gZRzRlPJORrg2cjWm+xLTOIQ+thk+O3U7l5R47h7QT44eSroKmX8Ptt/wkn9HRcI9bjylzrjTFw45/Re61RpHm3+NXUfvTPLaaXYSolldAgYN1gq+yYZJvBViWQB7gE05fpph6t6DYhEr2VtkLljxDclRPF14AKZaQCIndTiUX69eQfIpD4edHyBvFWSkf+fC1whOE/tqKY0vDflhBDrWFsvDwnEo0iYy671nu19RnBnZws0vseJeikQdCWBY6m0Wq7oViCyFCWyJPDukz3E9uCRrckki2i5+V2MM2IMtgImVFvRqaRbi7vF+Qjccs9Ri0+evcsc9dWjsnHkwggWEBgkqhkiG9w0BBwGgggV1BIIFcTCCBW0wggVpBgsqhkiG9w0BDAoBAqCCBTEwggUtMFcGCSqGSIb3DQEFDTBKMCkGCSqGSIb3DQEFDDAcBAj06Hc+Gh2z5wICCAAwDAYIKoZIhvcNAgkFADAdBglghkgBZQMEASoEEOwPSnf4F479I2AKr8i0TLYEggTQFtwGZHL6BF2++nDi2EAjc7XXIxp0u4qM17eZjafdltFpketf6pQCD/hDry+mVeIapTY9hOPE5XdjdFoJtOZPZHfvrrb0Jn+rgGAPYGBzqGK4NPVWHiDZ3uA4R4Tiwhgqd/ZQIdRshUEPVfu4EzTIAEhmHl+1g8JiD8EcYAXO1IRCLm17IsIYXT6d8cYe3Zy3AgULsF0/OwQIPVqaJCIwPR3qw68GXNA4iWWHuXJhdtrqHrGrkfBRuZZ5+7R838RM9Bk+ljWphidPmIFZmhjACt/c1qorGPhQTil0WT9VU9rN/gJ1rKcu3RQ1TRJDTjZYaPSMu9ycvFLpsP8XBJUpfHnczPS25bclKaJRUvou6aiwtyQsqWCDLGRuwN06Oins28R5/QQNYbcOr77WBlgh28K1TLcnQopE9xp12XBj8iOeUlVMiMVlph02TrGMXOqU0rlRpsYECMSfHw4xdH87GBUxmE4ndE7JI7wu73MsHQ+3kDTTvGG6xzY6rbNg+V6CfOZc102645sJskdCD6ygzUfgDwDcxjyky2u86qBFR/9d3M7Vh+PQpijYxQ/w4FzwgHUPII+JqqY8secPSA64L8qXj4daG74Wc3y+veajJzkFBUiaJnCER1WEJf0b4eBAEG1gaJ/B2hrp+lEd30qbE//iJWna5gYboIzMENfJ4RsqxlW4hZs6aqBuDr8QXL1chc11g0nMY9sI0kZVwF8+13eFh4ypt4H34usOiWHft2eeA/Z2h8agrT8UFkRfy3/1dGoNwqicXgqY3MgoxqlfDQ6hjPkO5JAbRc0cuZQMPu38dO66+qoI/Db4zdo+8G6sXOgZkzduQlARhx6VORq2QFoufsyqXvsUWFWSXEOjWLbLwKK5og8sV4OmWXGRPbTo+Hc3pmmuYcpEwtH6wFCb0vXVeOhSd7GX8Yv2V0yVt19IjgUGtukVWt9DUe6uImzsPm9ZdivWUB3RlKYRGpS16yhG0ZdRwBJweDoitK091ooN6Um74eO17dH0jAQw3XPBxgJ64qEdSzfJ/xybM45BSUPAft2wXXlckLOId9Us56oV7WeszTOkOPDKz9GnKT05xPXNDgAqstVZc0nXEq0eFzTORREBP0w2ijwPu9mfPvRACY8p7YMnNbZzMGBvpa3ILezRIgThMbnzf+YiBP2Ddt9bWoxDsIj7jaqDzxjG2WtI1qGEqFyLCeUkSx2UpkbGViCkx8CsMwXJwLrYdoxqjyOg2Oz09EFF5eI1wkLqEtez8dOTLEn7oFjTyFbRkNoynuwvNqHEG2qzbw02Rb82qyrurKmOnNHog7FXLDe0kGFgKuNXbCw+to2lAhWY0CmEe8qfQLeAiV3TsGHSrGSkoegmfPHsuboCdez/ETJZWoodryUPdY3PFNa0xZOJvbtkiG2Vo55Rjq9wbd+MWAGcxhaCVEmEJ0UWWsn3Oe+h4mn3wT9+P+hkAR9duXT6tq+5DmKB2RD3fR3vIc4H5eLaIzOOmjSdfGFvIaj+06jS7SGicuKqF5ND4HPtXJrQgQUdO/gIHCkE9nn4hXCoz/bGkU4FN2WPz5TTMVsYuxMVp1I2UayoQppltkp3oaDb/S36FeO644d5zb7ARayF68NL5MrM/MRK24jhtx2WV4ZN9HIxJTAjBgkqhkiG9w0BCRUxFgQU/S6zDu6S3P4i1WdDz+j3esGxT4UwQTAxMA0GCWCGSAFlAwQCAQUABCCiOwVWGDHil8dA7XvoQNTLTJDm7EwdfGC4KJUV9smgUgQI4ZRrDNXXl8cCAggA", - "JwtLifetimeInSeconds": 300, - "ApiKey": "test" - }, - "Cors": { - "AllowedOrigins": "http://localhost:8080;https://localhost:8080", - "AccessControlAllowCredentials": true - }, - "Infrastructure": { - "EventBus": { - "ProductName": "RabbitMQ", - // possible values: InMemory, RabbitMQ, GoogleCloudPubSub, AzureServiceBus - - "RabbitMQ": { - "EnableSsl": false, - "HostName": "localhost", - "Username": "guest", - "Password": "guest" - } + "RunMigrations": true, + "Authentication": { + "JwtSigningCertificate": "MIIJ7wIBAzCCCaUGCSqGSIb3DQEHAaCCCZYEggmSMIIJjjCCBAIGCSqGSIb3DQEHBqCCA/MwggPvAgEAMIID6AYJKoZIhvcNAQcBMFcGCSqGSIb3DQEFDTBKMCkGCSqGSIb3DQEFDDAcBAiIVEGIEnzbyAICCAAwDAYIKoZIhvcNAgkFADAdBglghkgBZQMEASoEEC1tOaulJJjkAl2W7xeF3G6AggOAm1VdXzAQ6MhHabp6+rzEuaAyBpuMi8zD8OEl8/xMv47UsFUor38aZjQd14qTTLz5MnksI/qgjQHLuMEmN1eWARsUBkeYvLuz0icl2q9A5Rn9CaKHIemQWq9mIobq3XnXhwDFEd+G/WgjNoK65Ndu20pnuc9LDlfq6fx2eXDbHAWLeUTnlQsEY4M/owNKIjlO/VsYJCshvEPlbtCnyzXwkrtQ5i2XufIJsfX0qoK/dXfoMVUjPxa/L8uR40bAWc1LVkvO0Ox4rY9VCtC1eHe3fcS48AaYCGRMpkZ7N+nDOb7lPs7BcxVoIrj/PkqiNI4rMOZVEgz21OWhueIjBv4gxfV+vW7IZ7xWvC1uUYIKEKEl6mk8KJ5zruO3tObX70+4saBiTNd/76+CVR4qCSwYcD7bZjpMOiaVFyxy0ay3dCwoivLK1jWNFJ25tngYpXKGCtOP0/Zi1fyseo4C54Ef5Yoo+BG3bkKR9VHChWzbB+b1p2lOwfBWIWlGjoZ+expyBjnk+FWrFDZeMknpW3PANCtcT/zqzqPKG3g4DAnSx9xDqvR7GBEgUlaUBAsCM3NvbahzevFFNE21aVajmTpSdejqvgNgvHPHA+BHfhMYx3mcMEkZ+phEHrWRSg925Iy64afL9/XvxoB/uFOYta/ir4ZqCbOy+yrc4+ppQlvLEIUnL4BGWcZ7d2NNRHWOHg0UqzxakezWhoGh1DDWfNdEj+eoa8DTvQr9hX0DQljym1I51qYdrv18rSf+MQj9jhBgQ77WBCX4sDkj4W9d7kKah8Fa0v+4bB1CqrETAsCESvBzSNyYEXKpyjdR/m8w/dti13Kz9ptvi8zd70tcqsqjaB3Qaz3gZRzRlPJORrg2cjWm+xLTOIQ+thk+O3U7l5R47h7QT44eSroKmX8Ptt/wkn9HRcI9bjylzrjTFw45/Re61RpHm3+NXUfvTPLaaXYSolldAgYN1gq+yYZJvBViWQB7gE05fpph6t6DYhEr2VtkLljxDclRPF14AKZaQCIndTiUX69eQfIpD4edHyBvFWSkf+fC1whOE/tqKY0vDflhBDrWFsvDwnEo0iYy671nu19RnBnZws0vseJeikQdCWBY6m0Wq7oViCyFCWyJPDukz3E9uCRrckki2i5+V2MM2IMtgImVFvRqaRbi7vF+Qjccs9Ri0+evcsc9dWjsnHkwggWEBgkqhkiG9w0BBwGgggV1BIIFcTCCBW0wggVpBgsqhkiG9w0BDAoBAqCCBTEwggUtMFcGCSqGSIb3DQEFDTBKMCkGCSqGSIb3DQEFDDAcBAj06Hc+Gh2z5wICCAAwDAYIKoZIhvcNAgkFADAdBglghkgBZQMEASoEEOwPSnf4F479I2AKr8i0TLYEggTQFtwGZHL6BF2++nDi2EAjc7XXIxp0u4qM17eZjafdltFpketf6pQCD/hDry+mVeIapTY9hOPE5XdjdFoJtOZPZHfvrrb0Jn+rgGAPYGBzqGK4NPVWHiDZ3uA4R4Tiwhgqd/ZQIdRshUEPVfu4EzTIAEhmHl+1g8JiD8EcYAXO1IRCLm17IsIYXT6d8cYe3Zy3AgULsF0/OwQIPVqaJCIwPR3qw68GXNA4iWWHuXJhdtrqHrGrkfBRuZZ5+7R838RM9Bk+ljWphidPmIFZmhjACt/c1qorGPhQTil0WT9VU9rN/gJ1rKcu3RQ1TRJDTjZYaPSMu9ycvFLpsP8XBJUpfHnczPS25bclKaJRUvou6aiwtyQsqWCDLGRuwN06Oins28R5/QQNYbcOr77WBlgh28K1TLcnQopE9xp12XBj8iOeUlVMiMVlph02TrGMXOqU0rlRpsYECMSfHw4xdH87GBUxmE4ndE7JI7wu73MsHQ+3kDTTvGG6xzY6rbNg+V6CfOZc102645sJskdCD6ygzUfgDwDcxjyky2u86qBFR/9d3M7Vh+PQpijYxQ/w4FzwgHUPII+JqqY8secPSA64L8qXj4daG74Wc3y+veajJzkFBUiaJnCER1WEJf0b4eBAEG1gaJ/B2hrp+lEd30qbE//iJWna5gYboIzMENfJ4RsqxlW4hZs6aqBuDr8QXL1chc11g0nMY9sI0kZVwF8+13eFh4ypt4H34usOiWHft2eeA/Z2h8agrT8UFkRfy3/1dGoNwqicXgqY3MgoxqlfDQ6hjPkO5JAbRc0cuZQMPu38dO66+qoI/Db4zdo+8G6sXOgZkzduQlARhx6VORq2QFoufsyqXvsUWFWSXEOjWLbLwKK5og8sV4OmWXGRPbTo+Hc3pmmuYcpEwtH6wFCb0vXVeOhSd7GX8Yv2V0yVt19IjgUGtukVWt9DUe6uImzsPm9ZdivWUB3RlKYRGpS16yhG0ZdRwBJweDoitK091ooN6Um74eO17dH0jAQw3XPBxgJ64qEdSzfJ/xybM45BSUPAft2wXXlckLOId9Us56oV7WeszTOkOPDKz9GnKT05xPXNDgAqstVZc0nXEq0eFzTORREBP0w2ijwPu9mfPvRACY8p7YMnNbZzMGBvpa3ILezRIgThMbnzf+YiBP2Ddt9bWoxDsIj7jaqDzxjG2WtI1qGEqFyLCeUkSx2UpkbGViCkx8CsMwXJwLrYdoxqjyOg2Oz09EFF5eI1wkLqEtez8dOTLEn7oFjTyFbRkNoynuwvNqHEG2qzbw02Rb82qyrurKmOnNHog7FXLDe0kGFgKuNXbCw+to2lAhWY0CmEe8qfQLeAiV3TsGHSrGSkoegmfPHsuboCdez/ETJZWoodryUPdY3PFNa0xZOJvbtkiG2Vo55Rjq9wbd+MWAGcxhaCVEmEJ0UWWsn3Oe+h4mn3wT9+P+hkAR9duXT6tq+5DmKB2RD3fR3vIc4H5eLaIzOOmjSdfGFvIaj+06jS7SGicuKqF5ND4HPtXJrQgQUdO/gIHCkE9nn4hXCoz/bGkU4FN2WPz5TTMVsYuxMVp1I2UayoQppltkp3oaDb/S36FeO644d5zb7ARayF68NL5MrM/MRK24jhtx2WV4ZN9HIxJTAjBgkqhkiG9w0BCRUxFgQU/S6zDu6S3P4i1WdDz+j3esGxT4UwQTAxMA0GCWCGSAFlAwQCAQUABCCiOwVWGDHil8dA7XvoQNTLTJDm7EwdfGC4KJUV9smgUgQI4ZRrDNXXl8cCAggA", + "JwtLifetimeInSeconds": 300, + "ApiKey": "test" }, - "SqlDatabase": { - "Provider": "Postgres", - "ConnectionString": "User ID=postgres;Password=admin;Server=localhost;Port=5432;Database=enmeshed;" - // postgres, - // "ConnectionString": "Server=localhost;Database=enmeshed;User Id=sa;Password=Passw0rd;TrustServerCertificate=True" // sqlserver - } - }, - "SwaggerUi": { - "Enabled": true - }, - "ModuleDefaults": { - "Application": { - "DidDomainName": "localhost" + "Cors": { + "AllowedOrigins": "http://localhost:8080;https://localhost:8080", + "AccessControlAllowCredentials": true }, "Infrastructure": { - "SqlDatabase": { - "Provider": "Postgres", - "ConnectionString": "User ID=postgres;Password=admin;Server=localhost;Port=5432;Database=enmeshed;" - // postgres - // "ConnectionString": "Server=localhost;Database=enmeshed;User Id=sa;Password=Passw0rd;TrustServerCertificate=True" // sqlserver - } - } - }, - "Modules": { - "Announcements": {}, - "Challenges": {}, - "Quotas": {}, - "Devices": { - "Application": { - "IdentityDeletion": { - "AuditLogRetentionPeriodInDays": 1 - }, - "Notifications": { - "Texts": [ - { - "Code": "TestCode", - "Translations": { - "en": { - "Title": "Test Title", - "Body": "Test Body" - }, - "de": { - "Title": "Test Titel", - "Body": "Test Inhalt" - } - } - } - ] - } - }, - "Infrastructure": { - "PushNotifications": { - "Providers": { - "dummy": { - "enabled": true - }, - "sse": { - "enabled": true, - "SseServerBaseAddress": "http://localhost:8083" + "EventBus": { + "ProductName": "RabbitMQ", + // possible values: InMemory, RabbitMQ, GoogleCloudPubSub, AzureServiceBus + + "RabbitMQ": { + "EnableSsl": false, + "HostName": "localhost", + "Username": "guest", + "Password": "guest" } - } - } - } - }, - "Files": { - "Infrastructure": { - "BlobStorage": { - "ProductName": "AzureStorageAccount", - "AzureStorageAccount": { - "ConnectionString": "DefaultEndpointsProtocol=http;AccountName=devstoreaccount1;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;BlobEndpoint=http://localhost:10000/devstoreaccount1;", - "ContainerName": "files" - } + }, + "SqlDatabase": { + "Provider": "Postgres", + "ConnectionString": "User ID=postgres;Password=admin;Server=localhost;Port=5432;Database=enmeshed;" + // postgres, + // "ConnectionString": "Server=localhost;Database=enmeshed;User Id=sa;Password=Passw0rd;TrustServerCertificate=True" // sqlserver } - } }, - "Messages": { - "Application": { - "MaxNumberOfMessageRecipients": 20 - } + "SwaggerUi": { + "Enabled": true }, - "Relationships": { - "PublicRelationshipTemplateReferences": { - "test": [ - { - "title": "a", - "description": "Description", - "truncatedReference": "Reference" - }, - { - "title": "b", - "description": "Description", - "truncatedReference": "Reference" - }, - { - "title": "c", - "description": "Description", - "truncatedReference": "Reference" - } - ], - "client2": [ - { - "title": "d", - "description": "Description", - "truncatedReference": "Reference" - }, - { - "title": "e", - "description": "Description", - "truncatedReference": "Reference" - } - ] - } + "ModuleDefaults": { + "Application": { + "DidDomainName": "localhost" + }, + "Infrastructure": { + "SqlDatabase": { + "Provider": "Postgres", + "ConnectionString": "User ID=postgres;Password=admin;Server=localhost;Port=5432;Database=enmeshed;" + // postgres + // "ConnectionString": "Server=localhost;Database=enmeshed;User Id=sa;Password=Passw0rd;TrustServerCertificate=True" // sqlserver + } + } }, - "Synchronization": {}, - "Tags": { - "Application": { - "SupportedLanguages": [ - "de", - "en" - ], - "TagsForAttributeValueTypes": { - "IdentityFileReference": { - "schulabschluss": { - "displayNames": { - "de": "Abschluss", - "en": "Degree" - }, - "children": { - "realschule": { - "displayNames": { - "de": "Realschule", - "en": "Secondary School" - }, - "children": { - "zeugnis": { - "displayNames": { - "de": "Zeugnis", - "en": "Diploma" - } - } - } + "Modules": { + "Announcements": {}, + "Challenges": {}, + "Quotas": {}, + "Devices": { + "Application": { + "IdentityDeletion": { + "AuditLogRetentionPeriodInDays": 1 }, - "gymnasium": { - "displayNames": { - "de": "Gymnasium", - "en": "High School" - }, - "children": { - "zeugnis": { - "displayNames": { - "de": "Zeugnis", - "en": "Diploma" - } + "Notifications": { + "Texts": [ + { + "Code": "TestCode", + "Translations": { + "en": { + "Title": "Test Title", + "Body": "Test Body" + }, + "de": { + "Title": "Test Titel", + "Body": "Test Inhalt" + } + } + } + ] + } + }, + "Infrastructure": { + "PushNotifications": { + "Providers": { + "dummy": { + "enabled": true + }, + "sse": { + "enabled": true, + "SseServerBaseAddress": "http://localhost:8083" + } } - } } - } } - }, - "PhoneNumber": { - "notfall": { - "displayNames": { - "de": "Notfallkontakt", - "en": "Emergency Contact" - } + }, + "Files": { + "Infrastructure": { + "BlobStorage": { + "ProductName": "AzureStorageAccount", + "AzureStorageAccount": { + "ConnectionString": "DefaultEndpointsProtocol=http;AccountName=devstoreaccount1;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;BlobEndpoint=http://localhost:10000/devstoreaccount1;", + "ContainerName": "files" + } + } } - }, - "StreetAddress": { - "lieferung": { - "displayNames": { - "de": "Lieferadresse", - "en": "Deliver Address" - } - }, - "heimat": { - "displayNames": { - "de": "Heimatadresse", - "en": "Home Address" - } + }, + "Messages": { + "Application": { + "MaxNumberOfMessageRecipients": 20 } - } - } - } - }, - "Tokens": {} - }, - "Logging": { - "MinimumLevel": { - "Default": "Information", - "Override": { - "Backbone": "Debug" - } - }, - "WriteTo": { - "Seq": { - "Name": "Seq", - "Args": { - "ServerUrl": "http://localhost:5341" - } - }, - "Console": { - "Args": { - "Theme": "Serilog.Sinks.SystemConsole.Themes.AnsiConsoleTheme::Sixteen, Serilog.Sinks.Console", - "OutputTemplate": "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj} (Correlation ID: {CorrelationId}){NewLine}{Exception}" - } - } - } - }, - "AppOnboarding": { - "DefaultAppId": "frosch", - "Apps": [ - { - "Id": "frosch", - "DisplayName": "Frosch", - "Description": "Sie haben einen QR-Code der Frosch Wallet gescannt. Um fortfahren zu können, laden Sie die Frosch Wallet-App auf Ihr Gerät.", - "IconUrl": "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNjAiIGhlaWdodD0iNjAiIHZpZXdCb3g9IjAgMCA2MCA2MCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPGcgY2xpcC1wYXRoPSJ1cmwoI2NsaXAwXzc0MDgzXzEzODcyMSkiPgo8bWFzayBpZD0ibWFzazBfNzQwODNfMTM4NzIxIiBzdHlsZT0ibWFzay10eXBlOmFscGhhIiBtYXNrVW5pdHM9InVzZXJTcGFjZU9uVXNlIiB4PSIwIiB5PSIwIiB3aWR0aD0iNjAiIGhlaWdodD0iNjAiPgo8cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTM4LjE0NDUgNi41MDQzNGUtMDZDMzguOTc4OSA2LjUwNDM0ZS0wNiAzOS44MTM1IDAuMDAwMjAxODE3IDQwLjY0ODQgMC4wMDQ4ODkzMkM0MS4zNTE1IDAuMDA4OTkxMjMgNDIuMDU0NCAwLjAxNzM5MDkgNDIuNzU2OCAwLjAzNjEzOTNDNDQuMjg3OCAwLjA3Nzc0NTMgNDUuODMyMiAwLjE2NzYxMSA0Ny4zNDY3IDAuNDM5NDZDNDguODgyOSAwLjcxNTQxOSA1MC4zMTI0IDEuMTY2MjkgNTEuNzA4IDEuODc2OTZDNTMuMDc5NyAyLjU3NTM5IDU0LjMzNTggMy40ODc1MiA1NS40MjM4IDQuNTc2MThDNTYuNTExOSA1LjY2NDg1IDU3LjQyNDYgNi45MjAzMiA1OC4xMjMxIDguMjkyQzU4LjgzMzEgOS42ODc2MyA1OS4yODQ2IDExLjExNzEgNTkuNTYwNiAxMi42NTMzQzU5LjgzMyAxNC4xNjcyIDU5LjkyMjMgMTUuNzExNyA1OS45NjM5IDE3LjI0MzJDNTkuOTgzMiAxNy45NDU2IDU5Ljk5MSAxOC42NDkxIDU5Ljk5NTEgMTkuMzUxNkM2MC4wMDA0IDIwLjE4NTkgNjAgMjEuMDIwNSA2MCAyMS44NTU1VjM4LjE0NDVDNjAgMzguOTc4OSA1OS45OTk4IDM5LjgxMzUgNTkuOTk1MSA0MC42NDg0QzU5Ljk5MSA0MS4zNTE1IDU5Ljk4MjYgNDIuMDU0NCA1OS45NjM5IDQyLjc1NjhDNTkuOTIyMyA0NC4yODc4IDU5LjgzMjQgNDUuODMyMiA1OS41NjA2IDQ3LjM0NjdDNTkuMjg0NiA0OC44ODI5IDU4LjgzMzcgNTAuMzEyNCA1OC4xMjMxIDUxLjcwOEM1Ny40MjQ2IDUzLjA3OTcgNTYuNTEyNSA1NC4zMzU4IDU1LjQyMzggNTUuNDIzOEM1NC4zMzUyIDU2LjUxMTkgNTMuMDc5NyA1Ny40MjQ2IDUxLjcwOCA1OC4xMjMxQzUwLjMxMjQgNTguODMzMSA0OC44ODI5IDU5LjI4NDYgNDcuMzQ2NyA1OS41NjA2QzQ1LjgzMjggNTkuODMzIDQ0LjI4ODQgNTkuOTIyMyA0Mi43NTY4IDU5Ljk2MzlDNDIuMDU0NCA1OS45ODMyIDQxLjM1MDkgNTkuOTkxIDQwLjY0ODQgNTkuOTk1MUMzOS44MTQxIDYwLjAwMDQgMzguOTc5NSA2MCAzOC4xNDQ1IDYwSDIxLjg1NTVDMjEuMDIxMSA2MCAyMC4xODY1IDU5Ljk5OTggMTkuMzUxNiA1OS45OTUxQzE4LjY0ODUgNTkuOTkxIDE3Ljk0NTYgNTkuOTgyNiAxNy4yNDMyIDU5Ljk2MzlDMTUuNzEyMyA1OS45MjIzIDE0LjE2NzggNTkuODMyNCAxMi42NTMzIDU5LjU2MDZDMTEuMTE3MSA1OS4yODQ2IDkuNjg3NjMgNTguODMzNyA4LjI5MiA1OC4xMjMxQzYuOTIwMzIgNTcuNDI0NiA1LjY2NDI2IDU2LjUxMjUgNC41NzYxOCA1NS40MjM4QzMuNDg4MSA1NC4zMzUyIDIuNTc1MzkgNTMuMDc5NyAxLjg3Njk2IDUxLjcwOEMxLjE2Njg4IDUwLjMxMjQgMC43MTU0MTggNDguODgyOSAwLjQzOTQ2IDQ3LjM0NjdDMC4xNjcwMjYgNDUuODMyOCAwLjA3Nzc0NDggNDQuMjg4NCAwLjAzNjEzOTMgNDIuNzU2OEMwLjAxNjgwNDggNDIuMDU0NCAwLjAwODk5MTEgNDEuMzUwOSAwLjAwNDg4OTMyIDQwLjY0ODRDLTAuMDAwMzg0MTIyIDM5LjgxNDEgNi41MDM2NWUtMDYgMzguOTc5NSA2LjUwMzY1ZS0wNiAzOC4xNDQ1VjIxLjg1NTVDNi41MDM2NWUtMDYgMjEuMDIxMSAwLjAwMDIwMTg4OSAyMC4xODY1IDAuMDA0ODg5MzIgMTkuMzUxNkMwLjAwODk5MTMzIDE4LjY0ODUgMC4wMTczOTE0IDE3Ljk0NTYgMC4wMzYxMzkzIDE3LjI0MzJDMC4wNzc3NDYyIDE1LjcxMjMgMC4xNjc2MTEgMTQuMTY3OCAwLjQzOTQ2IDEyLjY1MzNDMC43MTU0MjMgMTEuMTE3MSAxLjE2NjI4IDkuNjg3NjMgMS44NzY5NiA4LjI5MkMyLjU3NTQgNi45MjAzMiAzLjQ4NzUxIDUuNjY0MjYgNC41NzYxOCA0LjU3NjE4QzUuNjY0ODUgMy40ODgxIDYuOTIwMzIgMi41NzUzOSA4LjI5MiAxLjg3Njk2QzkuNjg3NjIgMS4xNjY4NyAxMS4xMTcxIDAuNzE1NDIxIDEyLjY1MzMgMC40Mzk0NkMxNC4xNjczIDAuMTY3MDIzIDE1LjcxMTcgMC4wNzc3NDU4IDE3LjI0MzIgMC4wMzYxMzkzQzE3Ljk0NTYgMC4wMTY4MDUzIDE4LjY0OTEgMC4wMDg5OTExNyAxOS4zNTE2IDAuMDA0ODg5MzJDMjAuMTg1OSAtMC4wMDAzODQwODkgMjEuMDIwNSA2LjQ5NzMxZS0wNiAyMS44NTU1IDYuNTA0MzRlLTA2SDM4LjE0NDVaIiBmaWxsPSIjRDlEOUQ5Ii8+CjwvbWFzaz4KPGcgbWFzaz0idXJsKCNtYXNrMF83NDA4M18xMzg3MjEpIj4KPHJlY3Qgd2lkdGg9IjYwIiBoZWlnaHQ9IjYwIiBmaWxsPSIjRkZDQkE1Ii8+CjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMV83NDA4M18xMzg3MjEpIj4KPHBhdGggZD0iTTI4Ljk3NzIgMTYuMjIxNUMzMC44NTk5IDE2LjIyMTUgMzIuMzg2MSAxNC42OTU0IDMyLjM4NjEgMTIuODEyOUMzMi4zODYxIDEwLjkzMDQgMzAuODU5OSA5LjQwNDMgMjguOTc3MiA5LjQwNDNDMjcuMDk0NiA5LjQwNDMgMjUuNTY4MyAxMC45MzA0IDI1LjU2ODMgMTIuODEyOUMyNS41NjgzIDE0LjY5NTQgMjcuMDk0NiAxNi4yMjE1IDI4Ljk3NzIgMTYuMjIxNVoiIGZpbGw9IiMxOTI5NTIiLz4KPHBhdGggZD0iTTYzLjU2OTUgNTEuODU1NkM2My4zMTI0IDUxLjE0OTggNjMuMTMxOCA1MC40MDU3IDYzLjAzMzMgNDkuNjM0M0M2Mi42Nzc2IDQ2LjgwNTcgNjMuNTI1OCA0NC4xMDI5IDY1LjE3MjggNDIuMDM0OEM2NC4wODM5IDQxLjE1MzkgNjIuOTg0MSA0MC4zMDA0IDYxLjg2MjQgMzkuNDY4N0M2MS44MDc2IDM5LjQzMDQgNjEuNzU4NCAzOS4zOTIxIDYxLjcwMzcgMzkuMzUzOEM2MS4yMDAzIDM4Ljk4MTggNjAuNjkxNCAzOC42MTUyIDYwLjE4MjUgMzguMjU0MUM1OS41ODA2IDM3LjgyNzQgNTguOTczMyAzNy40MDYxIDU4LjM2MDQgMzYuOTk1N0M1OC4zNDk1IDM2Ljk5MDMgNTguMzM4NiAzNi45NzkzIDU4LjMyNzYgMzYuOTczOUM1Ni40NTYzIDQyLjA1NjYgNTMuOTY2NiA0Ni4zMTg3IDUxLjk0MjEgNDkuMzE3QzU1LjMyOTEgNTEuMzMwNCA1OS4zNjcyIDUyLjI5ODggNjMuNTY5NSA1MS44NTU2WiIgZmlsbD0iIzE5Mjk1MiIvPgo8cGF0aCBkPSJNMzYuODQwMSA0NS43Mjc4QzM3LjE3MzkgNDYuNTE1NyAzOC4wMjIgNDYuOTkxNyAzOC44OTc1IDQ2LjgyMjFDMzkuOTA0MyA0Ni42MjUxIDQwLjU2MDkgNDUuNjU2NyA0MC4zNjM5IDQ0LjY1QzQwLjE2NjkgNDMuNjQzMyAzOS4xOTMgNDIuOTg2OCAzOC4xOTE2IDQzLjE4MzdDMzcuODY4OCA0My4yNDM5IDM3LjU4OTcgNDMuMzkxNiAzNy4zNTk5IDQzLjU4ODZDMzUuODM4OCA0Mi45OTIyIDM0LjIzNTYgNDIuNTg3MyAzMi41NzIyIDQyLjM5NTlDMzMuNjY2NSAzOS45MzM4IDM0LjU0NzUgMzcuMTM4IDM0LjgwNDYgMzQuMjA1NEMzOS4xMzgyIDM3LjE5MjcgNDMuMTE2MiA0MC42ODg4IDQ2LjYyMzYgNDQuNjM5MUM0Ny40NzcyIDM5LjUzNDQgNDcuNjE5NCAzNC44MTI3IDQ3LjM5NTEgMzAuNjkyOUM0Ni43MTY2IDMwLjM1OTEgNDYuMDM4MSAzMC4wMzYzIDQ1LjM1NDEgMjkuNzE5QzQ0LjYzMTkgMjkuMzg1MyA0My45MDQxIDI5LjA1NyA0My4xNzA5IDI4LjczOTZDMzIuNjU5NyAyNC4yMzEzIDIxLjIzNDcgMjEuNjA1MiA5LjM1NTU5IDIxLjIzMzFDMTAuOTUzMyAyMy45NDY4IDE0LjI1ODMgMjQuNzgzOSAxNC4yNTgzIDI0Ljc4MzlDMTguMTU0MSAyNS43OTYxIDIxLjkxODcgMjcuMTYzOSAyNS41MTkxIDI4Ljg1NDVDMjYuMTE1NSAzMC44MzUxIDI3LjQxNzggMzYuMDYwMiAyNi45OTY1IDQyLjU2NTVDMjQuMDggNDMuMDg1MiAyMS40MjYyIDQ0LjIzOTcgMTkuMTYwOSA0NS44ODFDMTguODEwNyA0NS43MDYgMTguNDAwNCA0NS42MzQ4IDE3Ljk4NDUgNDUuNzE2OUMxNi45Nzc3IDQ1LjkxMzkgMTYuMzIxMSA0Ni44ODc3IDE2LjUxODEgNDcuODg5QzE2LjcxNTEgNDguODkwMiAxNy42ODM2IDQ5LjU1MjIgMTguNjkwNCA0OS4zNTUzQzE5LjQ4MzggNDkuMjAyMSAyMC4wNTI4IDQ4LjU2MTkgMjAuMTYyMyA0Ny44MDE0QzIyLjIyNTEgNDcuMDkwMiAyNC4zNyA0Ni41Mzc2IDI2LjU4NjEgNDYuMTYwMUMyNi4zODM2IDQ3LjQwMiAyNi4xMTU1IDQ4LjY3NjggMjUuNzU0NCA0OS45NjhDMjUuNzQ4OSA0OS45NjggMjUuNzM4IDQ5Ljk2OCAyNS43MzI1IDQ5Ljk2OEMyNC43MjU3IDUwLjE2NSAyNC4wNjkxIDUxLjEzODkgMjQuMjY2MSA1Mi4xNDAxQzI0LjQ2MyA1My4xNDE0IDI1LjQzMTUgNTMuODAzNCAyNi40MzgzIDUzLjYwNjRDMjcuNDQ1MSA1My40MDk1IDI4LjEwMTggNTIuNDM1NiAyNy45MDQ4IDUxLjQzNDNDMjcuODQ0NiA1MS4xMzM0IDI3LjcxMzMgNTAuODcwOCAyNy41MzI3IDUwLjY0NjVDMjguMzIwNiA0OS42NTYyIDI5LjYxMiA0Ny45MTA5IDMwLjg5NzggNDUuNjYyMkMzMi45MDA1IDQ1LjUzNjMgMzQuODgxMiA0NS41NTgyIDM2LjgyOTIgNDUuNzIyNEwzNi44NDAxIDQ1LjcyNzhaIiBmaWxsPSIjMTkyOTUyIi8+CjxwYXRoIGQ9Ik05OS4yNTA3IDM5LjExMzVDOTguNjM3OSAzNC4yMTY3IDk0LjE2NzUgMzAuNzQyNSA4OS4yNzAzIDMxLjM1NTNDODkuMDk1MiAzMS4zNzcyIDg4LjkyNTYgMzEuNDEgODguNzU1OSAzMS40NDI4QzgxLjkxNjMgMjQuMTY2MSA3NS40MzIzIDE2LjkyMjEgNjYuMTUyMiAxNC42NjI1QzY1Ljk0NDMgMTQuNjEzMyA2NS43MzY0IDE0LjU2NCA2NS41Mjg0IDE0LjUyMDNDNTUuODkyNyAxMi40MzU3IDQ1Ljk1MDYgMTEuMjkyMiAzNS44MTY5IDExLjE2MDlDMzQuOTk2MSA5LjA4NzMzIDMyLjg2MjIgNy43NDY4OCAzMC41NDc2IDguMDM2ODZDMzAuMzg4OSA4LjA1ODc0IDMwLjIzMDMgOC4wODYxIDMwLjA3NzEgOC4xMTg5M0MyOS4wMjEgNi45MzE2NyAyNy40MTc4IDYuMjY5NjUgMjUuNzIxNiA2LjQ4MzAzQzIzLjExNyA2LjgxMTMgMjEuMjM0NyA5LjA4MTg2IDIxLjM0OTYgMTEuNjU4OEMxMy4xMDM3IDEyLjg3MzQgNy43ODUyMSAxNi42NjUgOS4zNTU2IDIxLjIzMzVDMjEuMjI5MyAyMS42MDU1IDMyLjY1OTcgMjQuMjMxNyA0My4xNiAyOC43MzQ1QzQ0LjU4ODEgMjkuMzQ3MyA0NS45OTQzIDMwLjAwMzkgNDcuMzg5NiAzMC42ODc4QzQ3LjcxNzkgMzYuNzI4IDQ3LjI2MzggNDQuMDU5NSA0NC45MjczIDUyLjAwOTJDMzkuODkzMyA1Mi40NTc4IDM2LjAxOTQgNTQuMDY2NCAzNC4xMDk3IDU1LjAyMzhDMzMuNjk5MyA1NC42OTAxIDMzLjE1MjIgNTQuNTMxNCAzMi41OTQxIDU0LjYzNTRDMzEuNTg3MyA1NC44MzI0IDMwLjkzMDYgNTUuODA2MiAzMS4xMjc2IDU2LjgwNzVDMzEuMzI0NiA1Ny44MDg3IDMyLjI5ODYgNTguNDcwNyAzMy4yOTk5IDU4LjI3MzhDMzQuMTg2MyA1OC4xMDQxIDM0Ljc5OTIgNTcuMzI3MiAzNC43OTkyIDU2LjQ1NzNDMzguNzU1MiA1NS40MDY4IDQxLjU3ODYgNTUuNTMyNyA0MS41Nzg2IDU1LjUzMjdDMzkuNjkwOSA1Ni41Mjg0IDM3LjcxMDEgNTguODIwOSAzNi42Mzc3IDYwLjE4MzJDMzYuNDU3MSA2MC4xNjY4IDM2LjI3NjUgNjAuMTYxMyAzNi4wOTA1IDYwLjE5OTZDMzUuMDgzNyA2MC4zOTY2IDM0LjQyNzEgNjEuMzY1IDM0LjYyNDEgNjIuMzcxN0MzNC44MjEgNjMuMzc4NCAzNS43OTUgNjQuMDM1IDM2Ljc5NjMgNjMuODM4QzM3Ljc5NzcgNjMuNjQxIDM4LjQ1OTcgNjIuNjcyNiAzOC4yNjI4IDYxLjY2NTlDMzguMjQwOSA2MS41NjIgMzguMjA4IDYxLjQ2MzUgMzguMTc1MiA2MS4zNjVDNDIuMTY0MSA1OC4yMTM2IDQ1LjQ4NTUgNTYuOTA2IDQ1LjQ4NTUgNTYuOTA2QzQ1LjUyMzggNTguMTY0MyA0NS40MjUzIDYwLjA3MzggNDUuMzM3NyA2MS40MjUyQzQ0LjQ2MjIgNjEuNzA5NyA0My45MTUxIDYyLjYwMTUgNDQuMDkwMiA2My41MzE2QzQ0LjI4NzEgNjQuNTM4MyA0NS4yNjExIDY1LjE5NDkgNDYuMjYyNCA2NC45OTc5QzQ3LjI2MzggNjQuODAwOSA0Ny45MjU4IDYzLjgzMjUgNDcuNzI4OSA2Mi44MjU4QzQ3LjY1MjMgNjIuNDIxIDQ3LjQzODkgNjIuMDc2MyA0Ny4xNTQzIDYxLjgxMzZDNDguODk5OCA1Ny44OTA4IDQ5LjAwMzggNTQuMzY3MyA0OC45ODc0IDUzLjI4OTVDNTAuNjYxNyA1MS4yNTQyIDU1LjI5NjMgNDUuMTc1NiA1OC4zMjIxIDM2Ljk2ODhDNjAuNjgwNSAzOC41NDQ1IDYyLjk1NjcgNDAuMjQwNiA2NS4xNjczIDQyLjAyOTdDNjMuNTIwMyA0NC4wOTc4IDYyLjY3NzcgNDYuODAwNiA2My4wMjc4IDQ5LjYyOTJDNjMuNTQ3NyA1My43NiA2Ni40NzUgNTYuOTk5IDcwLjIyODYgNTguMTE1MUM2Ni45NTExIDU4LjgwNDUgNjQuNDQ1IDU5Ljg4MjMgNjMuMDIyNCA2MC41OTM2QzYyLjYxMiA2MC4yNTk4IDYyLjA2NDggNjAuMTAxMiA2MS41MDY3IDYwLjIwNTFDNjAuNDk5OSA2MC40MDIxIDU5Ljg0MzMgNjEuMzcwNSA2MC4wNDAzIDYyLjM3NzJDNjAuMjM3MyA2My4zODM5IDYxLjIxMTIgNjQuMDQwNCA2Mi4yMTI1IDYzLjg0MzVDNjMuMDk5IDYzLjY3MzkgNjMuNzExOCA2Mi44OTY5IDYzLjcxMTggNjIuMDI3QzY3LjY2NzkgNjAuOTc2NSA3MC40OTEzIDYxLjEwMjQgNzAuNDkxMyA2MS4xMDI0QzY4LjYwMzUgNjIuMDk4MiA2Ni42MjI4IDY0LjM5MDYgNjUuNTUwMyA2NS43NTI5QzY1LjM2OTcgNjUuNzM2NSA2NS4xODkyIDY1LjczMTEgNjUuMDAzMSA2NS43Njk0QzYzLjk5NjMgNjUuOTY2MyA2My4zMzk3IDY2Ljk0MDIgNjMuNTM2NyA2Ny45NDE0QzYzLjczMzcgNjguOTQ4MSA2NC43MDc3IDY5LjYwNDcgNjUuNzA5IDY5LjQwNzdDNjYuNzEwMyA2OS4yMTA4IDY3LjM3MjQgNjguMjM2OSA2Ny4xNzU0IDY3LjIzNTZDNjcuMTUzNSA2Ny4xMzE3IDY3LjEyMDcgNjcuMDMzMiA2Ny4wODc5IDY2LjkzNDdDNzEuMDc2OCA2My43ODMzIDc0LjM5ODEgNjIuNDc1NyA3NC4zOTgxIDYyLjQ3NTdDNzQuNDM2NCA2My43MzQxIDc0LjMzNzkgNjUuNjQzNSA3NC4yNTA0IDY2Ljk5NDlDNzMuMzc0OSA2Ny4yNzk0IDcyLjgyNzcgNjguMTcxMiA3My4wMDI4IDY5LjEwMTNDNzMuMTk5OCA3MC4xMDggNzQuMTczOCA3MC43NjQ2IDc1LjE3NTEgNzAuNTY3NkM3Ni4xODE5IDcwLjM3MDcgNzYuODM4NSA2OS40MDIzIDc2LjY0MTUgNjguMzk1NUM3Ni41NjQ5IDY3Ljk5MDcgNzYuMzUxNSA2Ny42NDYgNzYuMDY3IDY3LjM4MzRDNzcuNDI0IDY0LjMzMDQgNzcuNzkwNiA2MS41MTI3IDc3Ljg3ODEgNTkuOTA0MkM3OC42Mjc4IDU5LjY3NDQgODkuNTk4NiA1Ni4xOTQ3IDk3LjMxMzcgNDUuODM3NkM5Ny41MzI2IDQ1LjU2NDEgOTcuNzQwNSA0NS4yODUgOTcuOTMyIDQ0Ljk4OTZDOTcuOTQzIDQ0Ljk3MzIgOTcuOTUzOSA0NC45NTY4IDk3Ljk3MDMgNDQuOTQwNEg5Ny45NjQ5Qzk5LjAxIDQzLjI1NTIgOTkuNTA3OSA0MS4yMjU0IDk5LjI0NTIgMzkuMTA4TDk5LjI1MDcgMzkuMTEzNVpNMjkuMzk4NiAxNi4xOTQ1QzI3LjUzMjcgMTYuNDI5NyAyNS44MzEgMTUuMTA1NyAyNS41OTU3IDEzLjI0QzI1LjM2MDQgMTEuMzc0MyAyNi42ODQ2IDkuNjcyNzYgMjguNTUwNCA5LjQzNzQ5QzMwLjQxNjMgOS4yMDIyMyAzMi4xMTggMTAuNTI2MyAzMi4zNTMzIDEyLjM5MkMzMi41ODg2IDE0LjI1NzcgMzEuMjY0NCAxNS45NTkyIDI5LjM5ODYgMTYuMTk0NVoiIGZpbGw9IndoaXRlIi8+CjwvZz4KPC9nPgo8L2c+CjxkZWZzPgo8Y2xpcFBhdGggaWQ9ImNsaXAwXzc0MDgzXzEzODcyMSI+CjxyZWN0IHdpZHRoPSI2MCIgaGVpZ2h0PSI2MCIgZmlsbD0id2hpdGUiLz4KPC9jbGlwUGF0aD4KPGNsaXBQYXRoIGlkPSJjbGlwMV83NDA4M18xMzg3MjEiPgo8cmVjdCB3aWR0aD0iOTAuMjM0NCIgaGVpZ2h0PSI2NC4xNjY3IiBmaWxsPSJ3aGl0ZSIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoOS4wODIwMyA2LjQ0NTMxKSIvPgo8L2NsaXBQYXRoPgo8L2RlZnM+Cjwvc3ZnPgo=", - "BannerUrl": "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjc5IiBoZWlnaHQ9IjgxIiB2aWV3Qm94PSIwIDAgMjc5IDgxIiBmaWxsPSJub25lIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPgo8ZyBjbGlwLXBhdGg9InVybCgjY2xpcDBfNzQwODNfMTM4Mzk3KSI+CjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMV83NDA4M18xMzgzOTcpIj4KPGcgY2xpcC1wYXRoPSJ1cmwoI2NsaXAyXzc0MDgzXzEzODM5NykiPgo8cGF0aCBkPSJNNDYuMDAyNSAxNC4xNjU3QzQ4LjUyOTkgMTQuMTY1NyA1MC41Nzg5IDEyLjExNyA1MC41Nzg5IDkuNTg5NjlDNTAuNTc4OSA3LjA2MjQzIDQ4LjUyOTkgNS4wMTM2NyA0Ni4wMDI1IDUuMDEzNjdDNDMuNDc1IDUuMDEzNjcgNDEuNDI2IDcuMDYyNDMgNDEuNDI2IDkuNTg5NjlDNDEuNDI2IDEyLjExNyA0My40NzUgMTQuMTY1NyA0Ni4wMDI1IDE0LjE2NTdaIiBmaWxsPSIjMTkyOTUyIi8+CjxwYXRoIGQ9Ik05Mi40NDI2IDYyLjAwNDZDOTIuMDk3NCA2MS4wNTcxIDkxLjg1NSA2MC4wNTgxIDkxLjcyMjcgNTkuMDIyNEM5MS4yNDUzIDU1LjIyNSA5Mi4zODM5IDUxLjU5NjUgOTQuNTk0OSA0OC44MjAxQzkzLjEzMzEgNDcuNjM3NSA5MS42NTY2IDQ2LjQ5MTYgOTAuMTUwNyA0NS4zNzUyQzkwLjA3NzMgNDUuMzIzOCA5MC4wMTEyIDQ1LjI3MjQgODkuOTM3NyA0NS4yMjA5Qzg5LjI2MTkgNDQuNzIxNSA4OC41Nzg3IDQ0LjIyOTMgODcuODk1NiA0My43NDQ2Qzg3LjA4NzUgNDMuMTcxNiA4Ni4yNzIxIDQyLjYwNjEgODUuNDQ5NCA0Mi4wNTUyQzg1LjQzNDcgNDIuMDQ3OCA4NS40MiA0Mi4wMzMyIDg1LjQwNTMgNDIuMDI1OEM4Mi44OTMxIDQ4Ljg0OTQgNzkuNTUwNyA1NC41NzEzIDc2LjgzMjggNTguNTk2NEM4MS4zNzk4IDYxLjI5OTQgODYuODAxIDYyLjU5OTUgOTIuNDQyNiA2Mi4wMDQ2WiIgZmlsbD0iIzE5Mjk1MiIvPgo8cGF0aCBkPSJNNTYuNTU4NCA1My43NzhDNTcuMDA2NSA1NC44MzU3IDU4LjE0NTEgNTUuNDc0OCA1OS4zMjA0IDU1LjI0NzFDNjAuNjcyIDU0Ljk4MjYgNjEuNTUzNSA1My42ODI1IDYxLjI4OTEgNTIuMzMxQzYxLjAyNDYgNTAuOTc5NSA1OS43MTcxIDUwLjA5ODEgNTguMzcyOCA1MC4zNjI1QzU3LjkzOTQgNTAuNDQzMyA1Ny41NjQ3IDUwLjY0MTcgNTcuMjU2MiA1MC45MDYxQzU1LjIxNDEgNTAuMTA1NSA1My4wNjE4IDQ5LjU2MTkgNTAuODI4NiA0OS4zMDQ4QzUyLjI5NzggNDUuOTk5NSA1My40ODA1IDQyLjI0NjIgNTMuODI1NyAzOC4zMDkyQzU5LjY0MzYgNDIuMzE5NiA2NC45ODQgNDcuMDEzMiA2OS42OTI3IDUyLjMxNjNDNzAuODM4NiA0NS40NjMzIDcxLjAyOTYgMzkuMTI0NSA3MC43Mjg0IDMzLjU5MzZDNjkuODE3NSAzMy4xNDU1IDY4LjkwNjcgMzIuNzEyMiA2Ny45ODg0IDMyLjI4NjJDNjcuMDE4OCAzMS44MzgxIDY2LjA0MTggMzEuMzk3NCA2NS4wNTc1IDMwLjk3MTRDNTAuOTQ2MiAyNC45MTkgMzUuNjA4MSAyMS4zOTMzIDE5LjY2MDQgMjAuODkzOUMyMS44MDU0IDI0LjUzNyAyNi4yNDIyIDI1LjY2MDggMjYuMjQyMiAyNS42NjA4QzMxLjQ3MjUgMjcuMDE5NyAzNi41MjY0IDI4Ljg1NiA0MS4zNTk5IDMxLjEyNTZDNDIuMTYwNiAzMy43ODQ2IDQzLjkwODkgNDAuNzk5MiA0My4zNDMzIDQ5LjUzMjVDMzkuNDI4IDUwLjIzMDMgMzUuODY1MiA1MS43ODAyIDMyLjgyNDEgNTMuOTgzN0MzMi4zNTM5IDUzLjc0ODYgMzEuODAzIDUzLjY1MzIgMzEuMjQ0NyA1My43NjMzQzI5Ljg5MzEgNTQuMDI3OCAyOS4wMTE2IDU1LjMzNTIgMjkuMjc2MSA1Ni42Nzk0QzI5LjU0MDUgNTguMDIzNSAzMC44NDA3IDU4LjkxMjMgMzIuMTkyMyA1OC42NDc5QzMzLjI1NzUgNTguNDQyMiAzNC4wMjE0IDU3LjU4MjggMzQuMTY4NCA1Ni41NjE4QzM2LjkzNzcgNTUuNjA3IDM5LjgxNzMgNTQuODY1MSA0Mi43OTIzIDU0LjM1ODNDNDIuNTIwNSA1Ni4wMjU2IDQyLjE2MDYgNTcuNzM3MSA0MS42NzU4IDU5LjQ3MDVDNDEuNjY4NCA1OS40NzA1IDQxLjY1MzcgNTkuNDcwNSA0MS42NDY0IDU5LjQ3MDVDNDAuMjk0OCA1OS43MzQ5IDM5LjQxMzMgNjEuMDQyNCAzOS42Nzc3IDYyLjM4NjVDMzkuOTQyMiA2My43MzA3IDQxLjI0MjQgNjQuNjE5NCA0Mi41OTQgNjQuMzU1QzQzLjk0NTYgNjQuMDkwNiA0NC44MjcxIDYyLjc4MzIgNDQuNTYyNyA2MS40MzlDNDQuNDgxOSA2MS4wMzUgNDQuMzA1NiA2MC42ODI1IDQ0LjA2MzIgNjAuMzgxM0M0NS4xMjEgNTkuMDUxOCA0Ni44NTQ2IDU2LjcwODcgNDguNTgwOCA1My42ODk5QzUxLjI2OTQgNTMuNTIwOSA1My45Mjg2IDUzLjU1MDMgNTYuNTQzNyA1My43NzA3TDU2LjU1ODQgNTMuNzc4WiIgZmlsbD0iIzE5Mjk1MiIvPgo8cGF0aCBkPSJNMTQwLjM0NSA0NC44OTY3QzEzOS41MjIgMzguMzIyOCAxMzMuNTIgMzMuNjU4NyAxMjYuOTQ2IDM0LjQ4MTNDMTI2LjcxMSAzNC41MTA3IDEyNi40ODMgMzQuNTU0OCAxMjYuMjU1IDM0LjU5ODlDMTE3LjA3MyAyNC44Mjk4IDEwOC4zNjggMTUuMTA0OSA5NS45MDk4IDEyLjA3MTNDOTUuNjMwNyAxMi4wMDUyIDk1LjM1MTUgMTEuOTM5MSA5NS4wNzI0IDExLjg4MDRDODIuMTM2NCA5LjA4MTg3IDY4Ljc4OTEgNy41NDY3NCA1NS4xODQ3IDcuMzcwNDVDNTQuMDgyOCA0LjU4NjY1IDUxLjIxNzkgMi43ODcwOSA0OC4xMTA3IDMuMTc2MzhDNDcuODk3NiAzLjIwNTc2IDQ3LjY4NDYgMy4yNDI0OSA0Ny40Nzg5IDMuMjg2NTZDNDYuMDYxMiAxLjY5MjY2IDQzLjkwODkgMC44MDM5MDEgNDEuNjMxNyAxLjA5MDM2QzM4LjEzNTEgMS41MzEwNyAzNS42MDgxIDQuNTc5MyAzNS43NjI0IDguMDM4ODZDMjQuNjkyMiA5LjY2OTQ4IDE3LjU1MjEgMTQuNzU5NyAxOS42NjA0IDIwLjg5MjhDMzUuNjAwOCAyMS4zOTIzIDUwLjk0NjEgMjQuOTE4IDY1LjA0MjcgMzAuOTYzQzY2Ljk2IDMxLjc4NTcgNjguODQ3OSAzMi42NjcxIDcwLjcyMSAzMy41ODUyQzcxLjE2MTggNDEuNjk0MyA3MC41NTIxIDUxLjUzNjggNjcuNDE1NCA2Mi4yMDkyQzYwLjY1NzMgNjIuODExNSA1NS40NTY1IDY0Ljk3MSA1Mi44OTI4IDY2LjI1NjRDNTIuMzQxOCA2NS44MDgzIDUxLjYwNzMgNjUuNTk1MyA1MC44NTggNjUuNzM0OUM0OS41MDY0IDY1Ljk5OTMgNDguNjI0OSA2Ny4zMDY4IDQ4Ljg4OTMgNjguNjUwOUM0OS4xNTM4IDY5Ljk5NTEgNTAuNDYxMyA3MC44ODM4IDUxLjgwNTYgNzAuNjE5NEM1Mi45OTU2IDcwLjM5MTcgNTMuODE4MyA2OS4zNDg3IDUzLjgxODMgNjguMTgwOEM1OS4xMjk0IDY2Ljc3MDYgNjIuOTE5OCA2Ni45Mzk1IDYyLjkxOTggNjYuOTM5NUM2MC4zODU1IDY4LjI3NjMgNTcuNzI2MyA3MS4zNTM5IDU2LjI4NjUgNzMuMTgyOUM1Ni4wNDQxIDczLjE2MDggNTUuODAxNyA3My4xNTM1IDU1LjU1MiA3My4yMDQ5QzU0LjIwMDMgNzMuNDY5MyA1My4zMTg4IDc0Ljc2OTQgNTMuNTgzMyA3Ni4xMjA5QzUzLjg0NzcgNzcuNDcyNCA1NS4xNTUzIDc4LjM1MzggNTYuNDk5NiA3OC4wODk0QzU3Ljg0MzggNzcuODI1IDU4LjczMjcgNzYuNTI0OSA1OC40NjgyIDc1LjE3MzRDNTguNDM4OSA3NS4wMzM4IDU4LjM5NDggNzQuOTAxNiA1OC4zNTA3IDc0Ljc2OTRDNjMuNzA1OCA3MC41Mzg2IDY4LjE2NDcgNjguNzgzMSA2OC4xNjQ3IDY4Ljc4MzFDNjguMjE2MSA3MC40NzI1IDY4LjA4MzkgNzMuMDM2IDY3Ljk2NjQgNzQuODUwMkM2Ni43OTEgNzUuMjMyMiA2Ni4wNTY1IDc2LjQyOTQgNjYuMjkxNSA3Ny42NzgxQzY2LjU1NiA3OS4wMjk2IDY3Ljg2MzUgNzkuOTExIDY5LjIwNzggNzkuNjQ2NkM3MC41NTIxIDc5LjM4MjIgNzEuNDQwOSA3OC4wODIxIDcxLjE3NjUgNzYuNzMwNkM3MS4wNzM2IDc2LjE4NyA3MC43ODcyIDc1LjcyNDMgNzAuNDA1MiA3NS4zNzE3QzcyLjc0ODUgNzAuMTA1MiA3Mi44ODgxIDY1LjM3NSA3Mi44NjYgNjMuOTI4Qzc1LjExMzggNjEuMTk1NiA4MS4zMzU3IDUzLjAzNTIgODUuMzk4IDQyLjAxNzVDODguNTY0IDQ0LjEzMjkgOTEuNjE5OSA0Ni40MDk4IDk0LjU4NzYgNDguODExN0M5Mi4zNzY1IDUxLjU4ODIgOTEuMjQ1MiA1NS4yMTY3IDkxLjcxNTMgNTkuMDE0MUM5Mi40MTMyIDY0LjU1OTcgOTYuMzQzMiA2OC45MDggMTAxLjM4MiA3MC40MDY0Qzk2Ljk4MjMgNzEuMzMxOSA5My42MTc5IDcyLjc3ODkgOTEuNzA4IDczLjczMzdDOTEuMTU3MSA3My4yODU3IDkwLjQyMjUgNzMuMDcyNyA4OS42NzMyIDczLjIxMjJDODguMzIxNiA3My40NzY3IDg3LjQ0MDEgNzQuNzc2OCA4Ny43MDQ1IDc2LjEyODNDODcuOTY5IDc3LjQ3OTggODkuMjc2NSA3OC4zNjEyIDkwLjYyMDggNzguMDk2OEM5MS44MTA4IDc3Ljg2OTEgOTIuNjMzNiA3Ni44MjYgOTIuNjMzNiA3NS42NTgyQzk3Ljk0NDYgNzQuMjQ3OSAxMDEuNzM1IDc0LjQxNjggMTAxLjczNSA3NC40MTY4Qzk5LjIwMDcgNzUuNzUzNyA5Ni41NDE1IDc4LjgzMTMgOTUuMTAxOCA4MC42NjAyQzk0Ljg1OTMgODAuNjM4MiA5NC42MTY5IDgwLjYzMDggOTQuMzY3MiA4MC42ODIzQzkzLjAxNTYgODAuOTQ2NyA5Mi4xMzQxIDgyLjI1NDEgOTIuMzk4NSA4My41OTgzQzkyLjY2MyA4NC45NDk4IDkzLjk3MDUgODUuODMxMiA5NS4zMTQ4IDg1LjU2NjhDOTYuNjU5MSA4NS4zMDIzIDk3LjU0NzkgODMuOTk0OSA5Ny4yODM1IDgyLjY1MDdDOTcuMjU0MSA4Mi41MTEyIDk3LjIxIDgyLjM3OSA5Ny4xNjU5IDgyLjI0NjhDMTAyLjUyMSA3OC4wMTYgMTA2Ljk4IDc2LjI2MDUgMTA2Ljk4IDc2LjI2MDVDMTA3LjAzMSA3Ny45NDk5IDEwNi44OTkgODAuNTEzMyAxMDYuNzgyIDgyLjMyNzZDMTA1LjYwNiA4Mi43MDk1IDEwNC44NzIgODMuOTA2OCAxMDUuMTA3IDg1LjE1NTRDMTA1LjM3MSA4Ni41MDY5IDEwNi42NzkgODcuMzg4NCAxMDguMDIzIDg3LjEyMzlDMTA5LjM3NSA4Ni44NTk1IDExMC4yNTYgODUuNTU5NCAxMDkuOTkyIDg0LjIwNzlDMTA5Ljg4OSA4My42NjQ0IDEwOS42MDIgODMuMjAxNiAxMDkuMjIgODIuODQ5MUMxMTEuMDQyIDc4Ljc1MDUgMTExLjUzNCA3NC45Njc3IDExMS42NTIgNzIuODA4M0MxMTIuNjU4IDcyLjQ5OTggMTI3LjM4NyA2Ny44MjgzIDEzNy43NDQgNTMuOTIzOUMxMzguMDM4IDUzLjU1NjcgMTM4LjMxNyA1My4xODIxIDEzOC41NzQgNTIuNzg1NEMxMzguNTg5IDUyLjc2MzQgMTM4LjYwNCA1Mi43NDE0IDEzOC42MjYgNTIuNzE5M0gxMzguNjE4QzE0MC4wMjEgNTAuNDU3IDE0MC42OSA0Ny43MzIgMTQwLjMzNyA0NC44ODk0TDE0MC4zNDUgNDQuODk2N1pNNDYuNTY4IDE0LjEyOEM0NC4wNjMxIDE0LjQ0MzggNDEuNzc4NiAxMi42NjYzIDQxLjQ2MjcgMTAuMTYxNkM0MS4xNDY4IDcuNjU2OTEgNDIuOTI0NSA1LjM3MjU4IDQ1LjQyOTQgNS4wNTY3M0M0Ny45MzQ0IDQuNzQwODkgNTAuMjE4OSA2LjUxODQyIDUwLjUzNDggOS4wMjMxMUM1MC44NTA2IDExLjUyNzggNDkuMDczIDEzLjgxMjEgNDYuNTY4IDE0LjEyOFoiIGZpbGw9IiNGRkNCQTUiLz4KPC9nPgo8cmVjdCB4PSI4Ny40Njc0IiB5PSItMC4zMDQ2ODgiIHdpZHRoPSIyLjAxMzc1IiBoZWlnaHQ9IjgwLjU1IiBmaWxsPSIjMTkyOTUyIi8+CjwvZz4KPHBhdGggZD0iTTExMy4zOTYgNTUuMTcxNUwxMDUuMjE1IDI4LjEwMTNDMTA1LjA5MyAyNy42ODg2IDEwNS4zOTkgMjcuMjY4MiAxMDUuODM1IDI3LjI2ODJIMTEwLjU0MkMxMTAuODMyIDI3LjI2ODIgMTExLjA5MyAyNy40NTkzIDExMS4xNjkgMjcuNzQyMUwxMTcuMDU0IDQ4Ljg1MUgxMTcuNDQ1TDEyMy42MDUgMjcuNzM0NEMxMjMuNjg5IDI3LjQ1OTMgMTIzLjk0MiAyNy4yNjgyIDEyNC4yMzMgMjcuMjY4MkgxMjguNzcxQzEyOS4wNjIgMjcuMjY4MiAxMjkuMzE0IDI3LjQ1OTMgMTI5LjM5OCAyNy43MzQ0TDEzNS40OTggNDguODUxSDEzNS45NDFMMTQxLjc3MyAyNy43NDIxQzE0MS44NDkgMjcuNDU5MyAxNDIuMTEgMjcuMjY4MiAxNDIuNCAyNy4yNjgySDE0Ni45OTJDMTQ3LjQyOCAyNy4yNjgyIDE0Ny43NDIgMjcuNjg4NiAxNDcuNjEyIDI4LjEwODlMMTM5LjM3IDU1LjE3OTJDMTM5LjI4NiA1NS40NTQzIDEzOS4wMzMgNTUuNjM3NyAxMzguNzUgNTUuNjM3N0gxMzIuNjk3QzEzMi40MTMgNTUuNjM3NyAxMzIuMTUzIDU1LjQ0NjcgMTMyLjA3NyA1NS4xNzkyTDEyNi41OSAzNi45NTE1SDEyNi4xNDZMMTIwLjc2NiA1NS4xNzkyQzEyMC42ODIgNTUuNDU0MyAxMjAuNDI5IDU1LjY0NTQgMTIwLjE0NiA1NS42NDU0SDExNC4wMzlDMTEzLjc1NiA1NS42NDU0IDExMy41MDMgNTUuNDU0MyAxMTMuNDE5IDU1LjE4NjhMMTEzLjM5NiA1NS4xNzE1WiIgZmlsbD0iIzE5Mjk1MiIvPgo8cGF0aCBkPSJNMTU4LjQ4NyA1Ni4wNzMzQzE1Ni41NTggNTYuMDczMyAxNTQuOTI4IDU1LjgxMzUgMTUzLjYxMiA1NS4yOTM4QzE1Mi4yOTYgNTQuNzc0MSAxNTEuMzAxIDUzLjkxMDUgMTUwLjYzNSA1Mi43MTA2QzE0OS45NjkgNTEuNTAzIDE0OS42MzIgNDkuODY3NSAxNDkuNjMyIDQ3Ljc4ODdDMTQ5LjYzMiA0NS42MDI5IDE0OS44OTMgNDMuODY4MSAxNTAuNDEzIDQyLjU5MTdDMTUwLjkzMyA0MS4zMTU0IDE1MS44MjEgNDAuMzkwNiAxNTMuMDg0IDM5Ljg0MDRDMTU0LjM0NiAzOS4yODI1IDE1Ni4xMyAzOS4wMDczIDE1OC40MzMgMzkuMDA3M0MxNTguOCAzOS4wMDczIDE1OS4zNTEgMzkuMDE1IDE2MC4wNzggMzkuMDM3OUMxNjAuODA1IDM5LjA1MzIgMTYxLjY0IDM5LjA3NjEgMTYyLjU4OSAzOS4wOTE0QzE2My41MzggMzkuMTE0MyAxNjQuNDc5IDM5LjEyOTYgMTY1LjQyOCAzOS4xNDQ5QzE2Ni4xMDkgMzkuMTYwMiAxNjYuNzQ0IDM5LjE3NTUgMTY3LjM0MSAzOS4xOTg0QzE2Ny43MTYgMzkuMjEzNyAxNjguMDIyIDM4LjkxNTYgMTY4LjAyMiAzOC41NDExVjM3Ljg5MTVDMTY4LjAyMiAzNi40NDcgMTY3LjkzIDM1LjMxNTkgMTY3Ljc0NyAzNC40OTgyQzE2Ny41NjMgMzMuNjgwNCAxNjcuMTggMzMuMDc2NiAxNjYuNjA2IDMyLjY5NDVDMTY2LjAzMiAzMi4zMDQ3IDE2NS4yMDYgMzIuMDUyNSAxNjQuMTI3IDMxLjk0NTVDMTYzLjA0OCAzMS44MzA5IDE2MS42NTUgMzEuNzc3NCAxNTkuOTQ4IDMxLjc3NzRDMTU5LjEyOSAzMS43Nzc0IDE1OC4xNzMgMzEuODA4IDE1Ny4wNzkgMzEuODYxNUMxNTUuOTg0IDMxLjkxNSAxNTQuOTEzIDMxLjk4MzcgMTUzLjg4IDMyLjA1MjVDMTUzLjIzNyAzMi4wOTg0IDE1Mi42ODYgMzIuMTUxOSAxNTIuMjI3IDMyLjIxM0MxNTEuODI5IDMyLjI2NjUgMTUxLjQ4NCAzMS45NjA4IDE1MS40ODQgMzEuNTYzNFYyOC4yMDgzQzE1MS40ODQgMjcuODk0OSAxNTEuNzA2IDI3LjYxOTggMTUyLjAyIDI3LjU1ODdDMTUzLjM5OCAyNy4zMTQxIDE1NC44OSAyNy4xMzA3IDE1Ni40OTcgMjcuMDE2QzE1OC4zMTggMjYuODg2MSAxNjAuMTMyIDI2LjgxNzMgMTYxLjk1MyAyNi44MTczQzE2NC4wNzMgMjYuODE3MyAxNjUuODQxIDI2Ljk0NzIgMTY3LjI3MiAyNy4yMDcxQzE2OC43MDMgMjcuNDY2OSAxNjkuODU5IDI3Ljg3MiAxNzAuNzU0IDI4LjQyOTlDMTcxLjY0MiAyOC45ODc4IDE3Mi4zMTUgMjkuNzA2MiAxNzIuNzU5IDMwLjYwMDRDMTczLjIwMyAzMS40OTQ2IDE3My41MTcgMzIuNTU2OSAxNzMuNzA4IDMzLjc5NTFDMTczLjg5MiAzNS4wNDA4IDE3My45ODQgMzYuNDU0NyAxNzMuOTg0IDM4LjA1MlY1NC45ODA0QzE3My45ODQgNTUuMzM5NyAxNzMuNjkzIDU1LjYzMDEgMTczLjMzMyA1NS42MzAxSDE2OS4xMzlDMTY4Ljc5NSA1NS42MzAxIDE2OC41MTIgNTUuMzYyNiAxNjguNDg5IDU1LjAxODdMMTY4LjMwNSA1MS45NjE2SDE2Ny45NjlDMTY3LjMzMyA1My4xNDYyIDE2Ni40OTIgNTQuMDQ4IDE2NS40MzUgNTQuNjU5NUMxNjQuMzc5IDU1LjI3MDkgMTYzLjIzMSA1NS42NjA2IDE2Mi4wMDcgNTUuODI4OEMxNjAuNzgzIDU1Ljk5NjkgMTU5LjYxMiA1Ni4wODEgMTU4LjQ5NCA1Ni4wODFMMTU4LjQ4NyA1Ni4wNzMzWk0xNjEuMTA0IDUxLjI4OTFDMTYyLjAzIDUxLjI4OTEgMTYyLjg3OSA1MS4yMjc5IDE2My42MzcgNTEuMDk4QzE2NC4zOTUgNTAuOTY4MSAxNjUuMDY4IDUwLjc0NjQgMTY1LjY0MiA1MC40MzMxQzE2Ni4yMTYgNTAuMTE5NyAxNjYuNjc1IDQ5LjY4NDEgMTY3LjAwNCA0OS4xMjYyQzE2Ny4zNDEgNDguNDk5NSAxNjcuNTg2IDQ3Ljc3MzQgMTY3Ljc1NCA0Ni45NTU3QzE2Ny45MjMgNDYuMTM3OSAxNjguMDA3IDQ1LjE3NDkgMTY4LjAwNyA0NC4wNjY4VjQzLjA2NTZIMTU5Ljg3MkMxNTguNjQ3IDQzLjA2NTYgMTU3LjcwNiA0My4xNTczIDE1Ny4wNTYgNDMuMzQwN0MxNTYuNDA1IDQzLjUyNDEgMTU1Ljk2OSA0My45MTM5IDE1NS43NDcgNDQuNTFDMTU1LjUyNSA0NS4xMDYyIDE1NS40MSA0Ni4wMDggMTU1LjQxIDQ3LjIzODVDMTU1LjQxIDQ4LjM5MjUgMTU1LjU0IDQ5LjI0ODUgMTU1LjgwMSA0OS44MjE3QzE1Ni4wNjEgNTAuMzk0OSAxNTYuNjEyIDUwLjc4NDYgMTU3LjQ0NiA1MC45OTFDMTU4LjI4IDUxLjE5NzMgMTU5LjQ5NyA1MS4yOTY3IDE2MS4wOTYgNTEuMjk2N0wxNjEuMTA0IDUxLjI4OTFaIiBmaWxsPSIjMTkyOTUyIi8+CjxwYXRoIGQ9Ik0xNzkuNTU1IDU1LjA1NjlWMTkuNjEwM0MxNzkuNTU1IDE5LjI5NyAxNzkuODQ2IDE5LjAzNzEgMTgwLjE5OCAxOS4wMzcxSDE4NC44MDVDMTg1LjE2NCAxOS4wMzcxIDE4NS40NTUgMTkuMjk3IDE4NS40NTUgMTkuNjEwM1Y1NS4wNTY5QzE4NS40NTUgNTUuMzcwMiAxODUuMTY0IDU1LjYzMDEgMTg0LjgxMiA1NS42MzAxSDE4MC4xOThDMTc5LjgzOCA1NS42MzAxIDE3OS41NTUgNTUuMzc3OSAxNzkuNTU1IDU1LjA1NjlaIiBmaWxsPSIjMTkyOTUyIi8+CjxwYXRoIGQ9Ik0xOTIuMzA1IDU1LjA0OTJWMTkuNjE4QzE5Mi4zMDUgMTkuMjk3IDE5Mi41OTUgMTkuMDM3MSAxOTIuOTYzIDE5LjAzNzFIMTk3LjU1NEMxOTcuOTE0IDE5LjAzNzEgMTk4LjIxMyAxOS4yOTcgMTk4LjIxMyAxOS42MThWNTUuMDQ5MkMxOTguMjEzIDU1LjM3MDIgMTk3LjkyMiA1NS42MzAxIDE5Ny41NTQgNTUuNjMwMUgxOTIuOTYzQzE5Mi42MDMgNTUuNjMwMSAxOTIuMzA1IDU1LjM3MDIgMTkyLjMwNSA1NS4wNDkyWiIgZmlsbD0iIzE5Mjk1MiIvPgo8cGF0aCBkPSJNMjE2LjcwOSA1Ni4wNzMzQzIxNC4yOTkgNTYuMDczMyAyMTIuMjg2IDU1LjkxMjkgMjEwLjY5NCA1NS41OTk1QzIwOS4wOTUgNTUuMjg2MiAyMDcuODE3IDU0Ljc2NjUgMjA2Ljg1MyA1NC4wNDA0QzIwNS44ODggNTMuMzE0NCAyMDUuMTYxIDUyLjM4OTYgMjA0LjY3OSA1MS4yNTg1QzIwNC4xOTcgNTAuMTI3NCAyMDMuODgzIDQ4Ljc1MTcgMjAzLjczIDQ3LjEzOTFDMjAzLjU4NSA0NS41MjY1IDIwMy41MDggNDMuNjQ2NCAyMDMuNTA4IDQxLjQ5MTJDMjAzLjUwOCAzOC45MzA5IDIwMy42MzggMzYuNzI5OCAyMDMuODk5IDM0Ljg3MjdDMjA0LjE1OSAzMy4wMTU1IDIwNC42OTQgMzEuNDg3IDIwNS41MTMgMzAuMjc5NEMyMDYuMzMyIDI5LjA3MTkgMjA3LjYwMyAyOC4xOTMgMjA5LjMzMiAyNy42MzUxQzIxMS4wNjIgMjcuMDc3MiAyMTMuMzczIDI2LjgwMiAyMTYuMjY2IDI2LjgwMkMyMTguNTMxIDI2LjgwMiAyMjAuMzkgMjYuOTc3OCAyMjEuODM3IDI3LjMyOTRDMjIzLjI4MyAyNy42ODA5IDIyNC40MjMgMjguMjMxMiAyMjUuMjY1IDI4Ljk3MjVDMjI2LjEwNyAyOS43MTM5IDIyNi43MTIgMzAuNjY5MiAyMjcuMTAyIDMxLjgzODVDMjI3LjQ5MiAzMy4wMDc5IDIyNy43NDUgMzQuMzk4OCAyMjcuODUyIDM2LjAxMTRDMjI3Ljk2NyAzNy42MjQgMjI4LjAyIDM5LjQ1MDYgMjI4LjAyIDQxLjQ5MTJWNDIuNzIxN0MyMjguMDIgNDMuMDg4NSAyMjcuNzIyIDQzLjM3ODkgMjI3LjM2MiA0My4zNzg5SDIwOS40NzdDMjA5LjQ3NyA0NS4wNDUgMjA5LjU1NCA0Ni4zOTAxIDIwOS42OTkgNDcuNDE0MkMyMDkuODQ1IDQ4LjQzMDcgMjEwLjE4OSA0OS4yMTAzIDIxMC43MzMgNDkuNzUyOUMyMTEuMjY4IDUwLjI4NzkgMjEyLjEyNSA1MC42NjI0IDIxMy4yOTYgNTAuODY4N0MyMTQuNDY3IDUxLjA3NTEgMjE2LjA1MSA1MS4xNzQ0IDIxOC4wNTYgNTEuMTc0NEMyMTguOTA2IDUxLjE3NDQgMjE5Ljg0NyA1MS4xNTkxIDIyMC44NzMgNTEuMTIwOUMyMjEuODkgNTEuMDgyNyAyMjIuOTM5IDUxLjAwNjMgMjI0LjAxOCA1MC44OTkzQzIyNC43OTggNTAuODE1MiAyMjUuNTI1IDUwLjc0NjQgMjI2LjE5MSA1MC42ODUzQzIyNi41ODIgNTAuNjQ3MSAyMjYuOTExIDUwLjk1MjggMjI2LjkxMSA1MS4zNDI2VjU0LjY4MjRDMjI2LjkxMSA1NS4wMTEgMjI2LjY3MyA1NS4yODYyIDIyNi4zNTIgNTUuMzMyQzIyNS42NTYgNTUuNDQ2NyAyMjQuODYgNTUuNTUzNiAyMjMuOTU3IDU1LjY1M0MyMjIuODA5IDU1Ljc4MjkgMjIxLjYgNTUuODgyMyAyMjAuMzM3IDU1Ljk1ODdDMjE5LjA3NCA1Ni4wMzUxIDIxNy44NjUgNTYuMDczMyAyMTYuNzE3IDU2LjA3MzNIMjE2LjcwOVpNMjIyLjMzNCAzOS4zMzZWMzkuMTY3OEMyMjIuMzM0IDM3LjUwMTcgMjIyLjIzNSAzNi4xNzE5IDIyMi4wMjggMzUuMTkzN0MyMjEuODIxIDM0LjIwNzggMjIxLjQ5MiAzMy40NjY0IDIyMS4wMjYgMzIuOTY5NkMyMjAuNTU5IDMyLjQ2NTIgMjE5LjkzMSAzMi4xMzY2IDIxOS4xMzUgMzEuOTY4NUMyMTguMzM5IDMxLjgwMDMgMjE3LjM0NSAzMS43MTYzIDIxNi4xNTggMzEuNzE2M0MyMTQuNjc0IDMxLjcxNjMgMjEzLjQ5NSAzMS44MTU2IDIxMi42MjMgMzIuMDIyQzIxMS43NSAzMi4yMjgzIDIxMS4wOTIgMzIuNjAyOCAyMTAuNjQ4IDMzLjE2MDdDMjEwLjIwNCAzMy43MTg2IDIwOS44OTggMzQuNDkwNSAyMDkuNzMgMzUuNDY4OEMyMDkuNTYyIDM2LjQ1NDcgMjA5LjQ3NyAzNy43Mzg3IDIwOS40NzcgMzkuMzM2SDIyMi4zNDJIMjIyLjMzNFoiIGZpbGw9IiMxOTI5NTIiLz4KPHBhdGggZD0iTTI0Mi45NDMgMjYuNjk1VjE5LjYwMjdDMjQyLjk0MyAxOS4yODkzIDI0Mi42OTEgMTkuMDM3MSAyNDIuMzc3IDE5LjAzNzFIMjM3LjUzM0MyMzcuMjE5IDE5LjAzNzEgMjM2Ljk2NiAxOS4yODkzIDIzNi45NjYgMTkuNjAyN1YyNi42OTVDMjM2Ljk2NiAyNy4wMDg0IDIzNi43MTQgMjcuMjYwNiAyMzYuNCAyNy4yNjA2SDIzMS43ODVDMjMxLjQ3MiAyNy4yNjA2IDIzMS4yMTkgMjcuNTEyOCAyMzEuMjE5IDI3LjgyNjFWMzEuNjM5OEMyMzEuMjE5IDMxLjk1MzIgMjMxLjQ3MiAzMi4yMDU0IDIzMS43ODUgMzIuMjA1NEgyMzYuNEMyMzYuNzE0IDMyLjIwNTQgMjM2Ljk2NiAzMi40NTc2IDIzNi45NjYgMzIuNzcwOVY1NS4wNTY5QzIzNi45NjYgNTUuMzcwMiAyMzcuMjE5IDU1LjYyMjQgMjM3LjUzMyA1NS42MjI0SDI0Mi4zNzdDMjQyLjY5MSA1NS42MjI0IDI0Mi45NDMgNTUuMzcwMiAyNDIuOTQzIDU1LjA1NjlWMzIuNzcwOUMyNDIuOTQzIDMyLjQ1NzYgMjQzLjE5NiAzMi4yMDU0IDI0My41MSAzMi4yMDU0SDI1Ny4xNDdDMjU5LjEwNiAzMi4yMDU0IDI2MC42OTggMzAuNjIzNCAyNjAuNjk4IDI4LjY1OTJWMjcuODI2MUMyNjAuNjk4IDI3LjUxMjggMjYwLjQ0NSAyNy4yNjA2IDI2MC4xMzIgMjcuMjYwNkgyNDMuNTFDMjQzLjE5NiAyNy4yNjA2IDI0Mi45NDMgMjcuMDA4NCAyNDIuOTQzIDI2LjY4NzRWMjYuNjk1WiIgZmlsbD0iIzE5Mjk1MiIvPgo8L2c+CjxkZWZzPgo8Y2xpcFBhdGggaWQ9ImNsaXAwXzc0MDgzXzEzODM5NyI+CjxyZWN0IHdpZHRoPSIyNzkiIGhlaWdodD0iODAuNTUxMiIgZmlsbD0id2hpdGUiLz4KPC9jbGlwUGF0aD4KPGNsaXBQYXRoIGlkPSJjbGlwMV83NDA4M18xMzgzOTciPgo8cmVjdCB3aWR0aD0iNzAuNDgxMiIgaGVpZ2h0PSI4MC41NSIgZmlsbD0id2hpdGUiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDE5IC0wLjMwNDY4OCkiLz4KPC9jbGlwUGF0aD4KPGNsaXBQYXRoIGlkPSJjbGlwMl83NDA4M18xMzgzOTciPgo8cmVjdCB3aWR0aD0iMTIxLjE0IiBoZWlnaHQ9Ijg2LjE0MzciIGZpbGw9IndoaXRlIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxOS4yOTMxIDEuMDM5MDYpIi8+CjwvY2xpcFBhdGg+CjwvZGVmcz4KPC9zdmc+Cg==", - "ColorScheme": - { - "Primary": "#192952", - "Secondary": "#EFE0D5", - "Background": "#FFF8F5", - "OnPrimary": "#FFF8F5", - "OnSecondary": "#221A14" }, - "AppleAppStore": { - "AppLink": "https://apps.apple.com/de/app/frosch/id6756783868" + "Relationships": { + "PublicRelationshipTemplateReferences": { + "test": [ + { + "title": "a", + "description": "Description", + "truncatedReference": "Reference" + }, + { + "title": "b", + "description": "Description", + "truncatedReference": "Reference" + }, + { + "title": "c", + "description": "Description", + "truncatedReference": "Reference" + } + ], + "client2": [ + { + "title": "d", + "description": "Description", + "truncatedReference": "Reference" + }, + { + "title": "e", + "description": "Description", + "truncatedReference": "Reference" + } + ] + } }, - "GooglePlayStore": { - "AppLink": "https://play.google.com/store/apps/details?id=app.frosch.prod" - } - }, - { - "Id": "enmeshed", - "DisplayName": "enmeshed", - "Description": "Sie haben einen QR-Code der enmeshed-Plattform gescannt. Um fortfahren zu können, laden Sie die enmeshed-App auf Ihr Gerät.", - "ColorScheme": - { - "Primary": "#192952", - "Secondary": "#EFE0D5", - "Background": "#FFF8F5", - "OnPrimary": "#FFF8F5", - "OnSecondary": "#221A14" + "Synchronization": {}, + "Tags": { + "Application": { + "SupportedLanguages": ["de", "en"], + "TagsForAttributeValueTypes": { + "IdentityFileReference": { + "schulabschluss": { + "displayNames": { + "de": "Abschluss", + "en": "Degree" + }, + "children": { + "realschule": { + "displayNames": { + "de": "Realschule", + "en": "Secondary School" + }, + "children": { + "zeugnis": { + "displayNames": { + "de": "Zeugnis", + "en": "Diploma" + } + } + } + }, + "gymnasium": { + "displayNames": { + "de": "Gymnasium", + "en": "High School" + }, + "children": { + "zeugnis": { + "displayNames": { + "de": "Zeugnis", + "en": "Diploma" + } + } + } + } + } + } + }, + "PhoneNumber": { + "notfall": { + "displayNames": { + "de": "Notfallkontakt", + "en": "Emergency Contact" + } + } + }, + "StreetAddress": { + "lieferung": { + "displayNames": { + "de": "Lieferadresse", + "en": "Deliver Address" + } + }, + "heimat": { + "displayNames": { + "de": "Heimatadresse", + "en": "Home Address" + } + } + } + } + } }, - "IconUrl": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAPAAAADwCAMAAAAJixmgAAAAA3NCSVQICAjb4U/gAAAATlBMVEX///8BNor49vUBAAAgICD+bQCVlZX/dgCampoXQo17fH0AH4Xm6OzS1d2/wceqrrj/x6n+18Jsf6s7XZz/nl+Jl7r/6dr6hiz/t4w6RV1ba3fKAAAFhklEQVR4nO2d65LaMAxGE283JJsbCQTY93/R2klgIYUQS526n6zzYzvT6XR8RrIsG5tNEkVRFEVRFEVRFEVRFEVRFOUppnKY0MP4J1R10+bZTN42srWrZnTNLeMP+4eVrqU61202az6S5Y1E5eqF7oQ4ZdOu2I5RrkMP8a9S5+u+TrkVFOQ34b1ShR7nX+JdOv8EWUZam/fpfBUWYbzdV0aMvXwlxHjr/L0pg1euxtPXAr06Vf6+eRt60Bz8dbELFyGhHbBJbWi+eRN64FSIAYYNMTXAsLO4pgrneeih0yDrgnYflDX4KgxZtsgly51/hB48hZbsi5nThuELWacZU9gdcIUevj+MRQlTmFGzHKGH7w9POMPrLqMT5qxKmMLRRZhVpQGFo5vDzGUJT5jVeCCuw6zWEvGsltdLI26IOQFG3B6yqhZgkWZVLcTNUsI6xAPc/yecnIbMaEadBs1oek5D1mgHMcSwAabuiWEDTAwxZJd1hVSoMUv0hPFPatA1+Ip3UkMntOXr29MXt0KPfH18fPkZhx4xj6+PX798jDPogjX5+hij3xGffK3x97bKlYE/fLj62hBXW67UwtfnH99kQweStbgN5cij7/iKZ00X/lHL0jdZe7gk4KXWE9/ETC/xlrJZJuAt3jPfEWOdb08tp+eWNfjcdbz0dRhT1U3TtK39Uct4W7rqKxBpvubUdfvLZd91p6f5KMrXdMfz7vPG7nzpltKSfLujk3zA/sWxu/83cnzNfre0vTrv9rcwy/G1us9sZ+fdfvpXYnxPxxXdUfl4Sh58sdfX/fNkXgTZSImveRfeWfksxfe8yddVLxm+a9VqqSzC14dPeN9kaz5fjdF9t9WrO87o65Gn7+5zH3rMHE6+us74FHrUDLwT2gkfQ4+aTkfwRU5qvxXpjtADp+JfscBDfKZGGDTEtBk8hrh7/7//h1BK9AxkoSaXLAdiu0XPaNCcvnCEL6FHT4CuazmHHj0BljDgJD4xMtqCt4PgCQNWLU6RhhSmNtKzMF47rcIqLEw4uqIV3bLEFMZrPKJrLePbPES3PYzuACC6Ix7GIR7opy3RHdNGdxAf30ct0X2YFt3HpfF9IB7flYfoLrX4J/Un+LWl+C6meV21FHH1MDl5xFjC5VKP68M7GdeH47sgnkT3BCCJ75FHEt0znmTlodZO5kMtR1xP8UYie2w5EdVz2k1EbQy/Om1j1dhUdTsMfd8Pg5xfqP36ay2a4ZCWZTpTpkWP/pU0Iy+6zLq3imnxgLU+gH+r1MgT4+ZQLmSvzmU64Id5aVy/0p2dwb8LL1kYm2FN11Ee0L9v6d7YhnddV0aQb8Z/VKoXQe7Ri9ds/L3FdgzyAb12jcabfYUYe/ha4wI+q99Xq0WMQ4+YSb2pXN0bD6GHzMIcfIWLEvrrLQdvXzuNgQtX7TmDJ2PgpPZPaEcJ22SSAmxD3IceOBVagHFDTAwwboh7YoBtiCELtSH7Fpg7RXJGozaY9IwGzWlqjR6FAet0xfCF7LYYUxhzErecCBdp6OH7Q9go3QvjnXxwijRkmVZhP2G8dUmF/YTxUppZpaMTxluWmtg6LV5rCXjmwdo8QJ4AsPbDeKsSb/dQhh48Bc4RD+B22MIIMGJG25wmn0sDLkoOcp2GrNEOarMF2GZNEEMMG2AbYtosRg1wkpiCEGPoOw+EtRixjb7DO6nh76b5dtSgPccPld9HTNATeKLadpV29sVdkX7wMBbha403Lk6pgHyeMP2WWp0W6PXqjuZtWqdlD74ePVL16688ykJKOt9Ye8dTpgNu//yapn/62sM9TROVzXfU7aF8kHbPD3v8XyG+RtUMVnqm6AX8wvQtVFVd15WUt7SKoiiKoiiKoiiKoiiKoijb+A3hKz2nnuI0BgAAAABJRU5ErkJggg==", - "BannerUrl": "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjU1IiBoZWlnaHQ9Ijc0IiB2aWV3Qm94PSIwIDAgMjU1IDc0IiBmaWxsPSJub25lIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPgo8cGF0aCBkPSJNNzIuNDIyNyAzOS4yNjY4SDU3LjM0MzFDNTcuNzQzNyA0Mi4zNDg4IDU5LjM3NyA0My41OTg0IDYxLjk4ODIgNDMuNTk4NEM2NC4xOTg5IDQzLjU5ODQgNjUuNDgzNyA0Mi42NTg2IDY2LjE0NDMgNDEuMDUyTDcyLjE1NzUgNDMuMDYyOUM3MC44NzI2IDQ2LjkwMSA2Ni42MjgxIDQ4Ljk1MzkgNjEuOTg4MiA0OC45NTM5QzU0LjY0ODcgNDguOTUzOSA1MC4wNTA0IDQ0LjcxMTUgNTAuMDUwNCAzNy4zNTA0QzUwLjA1MDQgMjkuOTg5MiA1NC43ODM5IDI1Ljc0NjkgNjEuNjM0NSAyNS43NDY5QzY4LjQ4NTEgMjUuNzQ2OSA3Mi41OTk2IDMwLjE2NzggNzIuNTk5NiAzNi4zMjY1QzcyLjU5OTYgMzcuNDQ0OSA3Mi41MTEyIDM4LjU1OCA3Mi40MjI3IDM5LjI3MjFWMzkuMjY2OFpNNTcuMzkgMzUuMjAyOUg2NS40MzY5QzY1LjE3MTYgMzIuNTI1MiA2My45MzM2IDMxLjA0OTggNjEuNjM0NSAzMS4wNDk4QzU5LjMzNTQgMzEuMDQ5OCA1Ny44MzIxIDMyLjM0NjcgNTcuMzkgMzUuMjAyOVoiIGZpbGw9IiMyMTIxMjEiLz4KPHBhdGggZD0iTTk2Ljc0MDUgMzMuNjQzNlY0OC41MDc2SDg5LjIyNDFWMzUuNjU0NUM4OS4yMjQxIDMyLjU3MjUgODcuOTM5MyAzMS41NDg2IDg2LjA4MjMgMzEuNTQ4NkM4My45MTMyIDMxLjU0ODYgODIuMTAzIDMyLjk3NjcgODIuMTAzIDM2LjY4MzZWNDguNTEyOUg3NC41ODY2VjI2LjE5ODRIODEuMzA3Mkw4MS41MjU2IDMwLjcwODVDODIuODUyMSAyNy40NDggODUuNTUxNyAyNS43NTIxIDg5LjA4ODggMjUuNzUyMUM5My42NDU1IDI1Ljc1MjEgOTYuNzQwNSAyOC40NzcxIDk2Ljc0MDUgMzMuNjU0MVYzMy42NDM2WiIgZmlsbD0iIzIxMjEyMSIvPgo8cGF0aCBkPSJNOTkuNzkzOSAyNi4xODc5SDEwNi41MTRMMTA2LjczMyAzMC41MTk1QzEwOC4xNDggMjcuMzk1NSAxMTAuODAxIDI1Ljc0MTYgMTE0LjE2MSAyNS43NDE2QzExNy41MjEgMjUuNzQxNiAxMTkuOTk3IDI3LjI1OSAxMjEuMTQ3IDMwLjE2MjVDMTIyLjUyIDI3LjI1OSAxMjUuMzkxIDI1Ljc0MTYgMTI4LjU3NSAyNS43NDE2QzEzMi45MDggMjUuNzQxNiAxMzYuMTc5IDI4LjQxOTMgMTM2LjEzOCAzMy42NDM2TDEzNi4wNDkgNDguNTA3NkgxMjguNjIxVjM1LjM4NjdDMTI4LjYyMSAzMi41Nzc3IDEyNy40MjUgMzEuNTQ4NiAxMjUuNjE1IDMxLjU0ODZDMTIzLjM2MyAzMS41NDg2IDEyMS43MjQgMzMuMjQ0NSAxMjEuNzI0IDM2LjU5NDNWNDguNTEyOUgxMTQuMjA4VjM1LjM5MkMxMTQuMjA4IDMyLjU4MyAxMTIuOTcgMzEuNTUzOSAxMTEuMjAxIDMxLjU1MzlDMTA5LjEyIDMxLjU1MzkgMTA3LjMxIDMzLjA3MTMgMTA3LjMxIDM2LjczMDhWNDguNTEyOUg5OS43OTM5VjI2LjE4NzlaIiBmaWxsPSIjMjEyMTIxIi8+CjxwYXRoIGQ9Ik0xNjAuNDA5IDM5LjI2NjhIMTQ1LjMyOUMxNDUuNzI0IDQyLjM0ODggMTQ3LjM2MyA0My41OTg0IDE0OS45NzQgNDMuNTk4NEMxNTIuMTg1IDQzLjU5ODQgMTUzLjQ2NSA0Mi42NTg2IDE1NC4xMyA0MS4wNTJMMTYwLjE0MyA0My4wNjI5QzE1OC44NjQgNDYuOTAxIDE1NC42MTQgNDguOTUzOSAxNDkuOTc0IDQ4Ljk1MzlDMTQyLjYzNSA0OC45NTM5IDEzOC4wMzYgNDQuNzExNSAxMzguMDM2IDM3LjM1MDRDMTM4LjAzNiAyOS45ODkyIDE0Mi43NyAyNS43NDY5IDE0OS42MjEgMjUuNzQ2OUMxNTYuNDcxIDI1Ljc0NjkgMTYwLjU4NiAzMC4xNjc4IDE2MC41ODYgMzYuMzI2NUMxNjAuNTg2IDM3LjQ0NDkgMTYwLjQ5NyAzOC41NTggMTYwLjQwOSAzOS4yNzIxVjM5LjI2NjhaTTE0NS4zNzYgMzUuMjAyOUgxNTMuNDIzQzE1My4xNTggMzIuNTI1MiAxNTEuOTIgMzEuMDQ5OCAxNDkuNjIxIDMxLjA0OThDMTQ3LjMyMSAzMS4wNDk4IDE0NS44MTggMzIuMzQ2NyAxNDUuMzc2IDM1LjIwMjlaIiBmaWxsPSIjMjEyMTIxIi8+CjxwYXRoIGQ9Ik0xNjAuOTgxIDQ0LjcxMTVMMTY0LjUxOCA0MC41MTY0QzE2NS45NzUgNDIuNDM4MSAxNjguNTQ0IDQzLjg2NjIgMTcxLjU1MSA0My44NjYyQzE3My4zNjYgNDMuODY2MiAxNzQuNjkyIDQzLjMzMDcgMTc0LjY5MiA0Mi4yMTIzQzE3NC42OTIgNDEuNDA5IDE3NC4yNSA0MC45MTU1IDE3Mi40ODIgNDAuNTU4NEwxNjkuMzg3IDM5LjkzMzZDMTYzLjgxNiAzOC43NzMzIDE2MS43MzUgMzYuNjMxMSAxNjEuNzM1IDMzLjAxMzVDMTYxLjczNSAyOS4zOTU5IDE2NS4wMDcgMjUuNzM2NCAxNzIuMTI4IDI1LjczNjRDMTc2LjYzOCAyNS43MzY0IDE4MC4wODcgMjcuMTIyNSAxODIuMTIgMjkuNTc0NEwxNzguNTM3IDMzLjY4MDNDMTc3LjEyMiAzMS44OTUyIDE3NC42NDYgMzAuODI0MSAxNzIuNDM1IDMwLjgyNDFDMTcwLjIyNCAzMC44MjQxIDE2OS4yMDUgMzEuNDQ4OSAxNjkuMjA1IDMyLjQ3OEMxNjkuMjA1IDMzLjI4MTMgMTY5LjgyNCAzMy44MTY4IDE3MS44MTYgMzQuMjIxMUwxNzUuODQyIDM1LjAyNDRDMTgwLjM5OSAzNS44Njk4IDE4Mi4yNTYgMzguMTQ4NSAxODIuMjU2IDQxLjI3MjVDMTgyLjI1NiA0NS42MDQxIDE3OC44MDcgNDguOTQ4NyAxNzEuODYzIDQ4Ljk0ODdDMTY3LjQ0MSA0OC45NDg3IDE2My41MDQgNDcuNDczMyAxNjAuOTg2IDQ0LjcwNjNMMTYwLjk4MSA0NC43MTE1WiIgZmlsbD0iIzIxMjEyMSIvPgo8cGF0aCBkPSJNMTgzLjkzMSAxNi43MjY2SDE5MS40NDdWMzAuMjUxOEMxOTIuNzczIDI3LjI1OSAxOTUuMjQ5IDI1Ljc0MTYgMTk4LjQzMyAyNS43NDE2QzIwMi45OSAyNS43NDE2IDIwNi4wODQgMjguNDY2NiAyMDYuMDg0IDMzLjY0MzZWNDguNTA3NkgxOTguNTY4VjM1Ljc0MzdDMTk4LjU2OCAzMi41NzI1IDE5Ny4yODggMzEuNTAxNCAxOTUuNDI2IDMxLjUwMTRDMTkzLjI1NyAzMS41MDE0IDE5MS40NDcgMzMuMDE4OCAxOTEuNDQ3IDM2Ljc2NzZWNDguNTA3NkgxODMuOTMxVjE2LjcyNjZaIiBmaWxsPSIjMjEyMTIxIi8+CjxwYXRoIGQ9Ik0yMzAuMzU1IDM5LjI2NjhIMjE1LjI3NkMyMTUuNjc2IDQyLjM0ODggMjE3LjMxIDQzLjU5ODQgMjE5LjkyMSA0My41OTg0QzIyMi4xMzIgNDMuNTk4NCAyMjMuNDE2IDQyLjY1ODYgMjI0LjA3NyA0MS4wNTJMMjMwLjA5IDQzLjA2MjlDMjI4LjgxMSA0Ni45MDEgMjI0LjU2MSA0OC45NTM5IDIxOS45MjEgNDguOTUzOUMyMTIuNTgxIDQ4Ljk1MzkgMjA3Ljk4MyA0NC43MTE1IDIwNy45ODMgMzcuMzUwNEMyMDcuOTgzIDI5Ljk4OTIgMjEyLjcxNyAyNS43NDY5IDIxOS41NjcgMjUuNzQ2OUMyMjYuNDE4IDI1Ljc0NjkgMjMwLjUzMiAzMC4xNjc4IDIzMC41MzIgMzYuMzI2NUMyMzAuNTMyIDM3LjQ0NDkgMjMwLjQ0NCAzOC41NTggMjMwLjM1NSAzOS4yNzIxVjM5LjI2NjhaTTIxNS4zMjMgMzUuMjAyOUgyMjMuMzdDMjIzLjEwNCAzMi41MjUyIDIyMS44NjYgMzEuMDQ5OCAyMTkuNTY3IDMxLjA0OThDMjE3LjI2OCAzMS4wNDk4IDIxNS43NjUgMzIuMzQ2NyAyMTUuMzIzIDM1LjIwMjlaIiBmaWxsPSIjMjEyMTIxIi8+CjxwYXRoIGQ9Ik0yNTQuODUgMTYuNzI2NlY0OC41MDI0SDI0OC4xMjlMMjQ3Ljg2NCA0NC4xMjg3QzI0Ni42MjYgNDcuMTIxNSAyNDQuMDE1IDQ4Ljk0ODcgMjQwLjY1NSA0OC45NDg3QzIzNS4xNzIgNDguOTQ4NyAyMzEuNTQ3IDQ0LjcwNjMgMjMxLjU0NyAzNy40MzQ0QzIzMS41NDcgMzAuMTYyNSAyMzUuMzQ5IDI1Ljc0MTYgMjQwLjgzMiAyNS43NDE2QzI0My45NzMgMjUuNzQxNiAyNDYuMTg0IDI3LjQzNzUgMjQ3LjMzNCAyOS45ODRWMTYuNzI2NkgyNTQuODVaTTI0Ny4zMzQgMzcuMjEzOUMyNDcuMzM0IDMzLjQ2NSAyNDUuODMgMzEuMzIyOSAyNDMuMzA4IDMxLjMyMjlDMjQwLjc4NSAzMS4zMjI5IDIzOS4xMDUgMzMuMTk3MyAyMzkuMTA1IDM3LjM1MDRDMjM5LjEwNSA0MS41MDM1IDI0MC42NSA0My4zNzc5IDI0My4yNjEgNDMuMzc3OUMyNDUuODcyIDQzLjM3NzkgMjQ3LjMyOCA0MS4yMzU3IDI0Ny4zMjggMzcuMjE5MUwyNDcuMzM0IDM3LjIxMzlaIiBmaWxsPSIjMjEyMTIxIi8+CjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNMzcuOTc0NCAxMS4xMzA2QzM4LjQ4MTkgMTEuNjM4MSAzOC40ODE5IDEyLjQ2MDkgMzcuOTc0NCAxMi45Njg0TDEzLjk0MzEgMzYuOTk5N0wzNy45NzQ0IDYxLjAzMUMzOC40ODE5IDYxLjUzODUgMzguNDgxOSA2Mi4zNjEzIDM3Ljk3NDQgNjIuODY4OEMzNy40NjY5IDYzLjM3NjMgMzYuNjQ0MSA2My4zNzYzIDM2LjEzNjcgNjIuODY4OEwxMC4yNjc2IDM2Ljk5OTdMMzYuMTM2NyAxMS4xMzA2QzM2LjY0NDEgMTAuNjIzMSAzNy40NjY5IDEwLjYyMzEgMzcuOTc0NCAxMS4xMzA2WiIgZmlsbD0iIzIxMjEyMSIvPgo8Y2lyY2xlIGN4PSIzNy4wNTU1IiBjeT0iMTIuMDQ5MSIgcj0iMTEuOTU1MyIgZmlsbD0iIzlBOUE5QSIvPgo8Y2lyY2xlIGN4PSIzNy4wNTU1IiBjeT0iNjEuOTQ5NCIgcj0iMTEuOTU1MyIgZmlsbD0iIzE3NDI4RCIvPgo8Y2lyY2xlIGN4PSIxMi4xMDUzIiBjeT0iMzYuOTk4MyIgcj0iMTEuOTU1MyIgZmlsbD0iI0ZGNzYwMCIvPgo8L3N2Zz4K", - "AppleAppStore": { - "AppLink": "https://apps.apple.com/us/app/enmeshed/id1576693742" + "Tokens": {} + }, + "Telemetry": { + "OpenTelemetryCollector": { + "Endpoint": "http://localhost:4317" }, - "GooglePlayStore": { - "AppLink": "https://play.google.com/store/apps/details?id=eu.enmeshed.app" + "Logging": { + "MinimumLevel": { + "Default": "Information", + "Override": { + "Backbone": "Debug" + } + }, + "WriteTo": { + "Seq": { + "Name": "Seq", + "Args": { + "ServerUrl": "http://localhost:5341" + } + }, + "Console": { + "Args": { + "Theme": "Serilog.Sinks.SystemConsole.Themes.AnsiConsoleTheme::Sixteen, Serilog.Sinks.Console", + "OutputTemplate": "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj} (Correlation ID: {CorrelationId}){NewLine}{Exception}" + } + } + } } - } - ] - }, - "WellKnownEndpoints": { - "AppleAppSiteAssociations": [ - "R7Y6NESEQW.eu.enmeshed.app" - ], - "AndroidAssetLinks": [ - { - "PackageName": "eu.enmeshed.app", - "Sha256CertFingerprints": [ - "0F:6F:48:FF:59:E7:B4:EC:52:4A:BB:E7:45:41:E7:38:5B:13:D1:0B:14:37:CF:C3:59:08:DF:22:F3:CA:70:38" + }, + "AppOnboarding": { + "DefaultAppId": "frosch", + "Apps": [ + { + "Id": "frosch", + "DisplayName": "Frosch", + "Description": "Sie haben einen QR-Code der Frosch Wallet gescannt. Um fortfahren zu können, laden Sie die Frosch Wallet-App auf Ihr Gerät.", + "IconUrl": "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNjAiIGhlaWdodD0iNjAiIHZpZXdCb3g9IjAgMCA2MCA2MCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPGcgY2xpcC1wYXRoPSJ1cmwoI2NsaXAwXzc0MDgzXzEzODcyMSkiPgo8bWFzayBpZD0ibWFzazBfNzQwODNfMTM4NzIxIiBzdHlsZT0ibWFzay10eXBlOmFscGhhIiBtYXNrVW5pdHM9InVzZXJTcGFjZU9uVXNlIiB4PSIwIiB5PSIwIiB3aWR0aD0iNjAiIGhlaWdodD0iNjAiPgo8cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTM4LjE0NDUgNi41MDQzNGUtMDZDMzguOTc4OSA2LjUwNDM0ZS0wNiAzOS44MTM1IDAuMDAwMjAxODE3IDQwLjY0ODQgMC4wMDQ4ODkzMkM0MS4zNTE1IDAuMDA4OTkxMjMgNDIuMDU0NCAwLjAxNzM5MDkgNDIuNzU2OCAwLjAzNjEzOTNDNDQuMjg3OCAwLjA3Nzc0NTMgNDUuODMyMiAwLjE2NzYxMSA0Ny4zNDY3IDAuNDM5NDZDNDguODgyOSAwLjcxNTQxOSA1MC4zMTI0IDEuMTY2MjkgNTEuNzA4IDEuODc2OTZDNTMuMDc5NyAyLjU3NTM5IDU0LjMzNTggMy40ODc1MiA1NS40MjM4IDQuNTc2MThDNTYuNTExOSA1LjY2NDg1IDU3LjQyNDYgNi45MjAzMiA1OC4xMjMxIDguMjkyQzU4LjgzMzEgOS42ODc2MyA1OS4yODQ2IDExLjExNzEgNTkuNTYwNiAxMi42NTMzQzU5LjgzMyAxNC4xNjcyIDU5LjkyMjMgMTUuNzExNyA1OS45NjM5IDE3LjI0MzJDNTkuOTgzMiAxNy45NDU2IDU5Ljk5MSAxOC42NDkxIDU5Ljk5NTEgMTkuMzUxNkM2MC4wMDA0IDIwLjE4NTkgNjAgMjEuMDIwNSA2MCAyMS44NTU1VjM4LjE0NDVDNjAgMzguOTc4OSA1OS45OTk4IDM5LjgxMzUgNTkuOTk1MSA0MC42NDg0QzU5Ljk5MSA0MS4zNTE1IDU5Ljk4MjYgNDIuMDU0NCA1OS45NjM5IDQyLjc1NjhDNTkuOTIyMyA0NC4yODc4IDU5LjgzMjQgNDUuODMyMiA1OS41NjA2IDQ3LjM0NjdDNTkuMjg0NiA0OC44ODI5IDU4LjgzMzcgNTAuMzEyNCA1OC4xMjMxIDUxLjcwOEM1Ny40MjQ2IDUzLjA3OTcgNTYuNTEyNSA1NC4zMzU4IDU1LjQyMzggNTUuNDIzOEM1NC4zMzUyIDU2LjUxMTkgNTMuMDc5NyA1Ny40MjQ2IDUxLjcwOCA1OC4xMjMxQzUwLjMxMjQgNTguODMzMSA0OC44ODI5IDU5LjI4NDYgNDcuMzQ2NyA1OS41NjA2QzQ1LjgzMjggNTkuODMzIDQ0LjI4ODQgNTkuOTIyMyA0Mi43NTY4IDU5Ljk2MzlDNDIuMDU0NCA1OS45ODMyIDQxLjM1MDkgNTkuOTkxIDQwLjY0ODQgNTkuOTk1MUMzOS44MTQxIDYwLjAwMDQgMzguOTc5NSA2MCAzOC4xNDQ1IDYwSDIxLjg1NTVDMjEuMDIxMSA2MCAyMC4xODY1IDU5Ljk5OTggMTkuMzUxNiA1OS45OTUxQzE4LjY0ODUgNTkuOTkxIDE3Ljk0NTYgNTkuOTgyNiAxNy4yNDMyIDU5Ljk2MzlDMTUuNzEyMyA1OS45MjIzIDE0LjE2NzggNTkuODMyNCAxMi42NTMzIDU5LjU2MDZDMTEuMTE3MSA1OS4yODQ2IDkuNjg3NjMgNTguODMzNyA4LjI5MiA1OC4xMjMxQzYuOTIwMzIgNTcuNDI0NiA1LjY2NDI2IDU2LjUxMjUgNC41NzYxOCA1NS40MjM4QzMuNDg4MSA1NC4zMzUyIDIuNTc1MzkgNTMuMDc5NyAxLjg3Njk2IDUxLjcwOEMxLjE2Njg4IDUwLjMxMjQgMC43MTU0MTggNDguODgyOSAwLjQzOTQ2IDQ3LjM0NjdDMC4xNjcwMjYgNDUuODMyOCAwLjA3Nzc0NDggNDQuMjg4NCAwLjAzNjEzOTMgNDIuNzU2OEMwLjAxNjgwNDggNDIuMDU0NCAwLjAwODk5MTEgNDEuMzUwOSAwLjAwNDg4OTMyIDQwLjY0ODRDLTAuMDAwMzg0MTIyIDM5LjgxNDEgNi41MDM2NWUtMDYgMzguOTc5NSA2LjUwMzY1ZS0wNiAzOC4xNDQ1VjIxLjg1NTVDNi41MDM2NWUtMDYgMjEuMDIxMSAwLjAwMDIwMTg4OSAyMC4xODY1IDAuMDA0ODg5MzIgMTkuMzUxNkMwLjAwODk5MTMzIDE4LjY0ODUgMC4wMTczOTE0IDE3Ljk0NTYgMC4wMzYxMzkzIDE3LjI0MzJDMC4wNzc3NDYyIDE1LjcxMjMgMC4xNjc2MTEgMTQuMTY3OCAwLjQzOTQ2IDEyLjY1MzNDMC43MTU0MjMgMTEuMTE3MSAxLjE2NjI4IDkuNjg3NjMgMS44NzY5NiA4LjI5MkMyLjU3NTQgNi45MjAzMiAzLjQ4NzUxIDUuNjY0MjYgNC41NzYxOCA0LjU3NjE4QzUuNjY0ODUgMy40ODgxIDYuOTIwMzIgMi41NzUzOSA4LjI5MiAxLjg3Njk2QzkuNjg3NjIgMS4xNjY4NyAxMS4xMTcxIDAuNzE1NDIxIDEyLjY1MzMgMC40Mzk0NkMxNC4xNjczIDAuMTY3MDIzIDE1LjcxMTcgMC4wNzc3NDU4IDE3LjI0MzIgMC4wMzYxMzkzQzE3Ljk0NTYgMC4wMTY4MDUzIDE4LjY0OTEgMC4wMDg5OTExNyAxOS4zNTE2IDAuMDA0ODg5MzJDMjAuMTg1OSAtMC4wMDAzODQwODkgMjEuMDIwNSA2LjQ5NzMxZS0wNiAyMS44NTU1IDYuNTA0MzRlLTA2SDM4LjE0NDVaIiBmaWxsPSIjRDlEOUQ5Ii8+CjwvbWFzaz4KPGcgbWFzaz0idXJsKCNtYXNrMF83NDA4M18xMzg3MjEpIj4KPHJlY3Qgd2lkdGg9IjYwIiBoZWlnaHQ9IjYwIiBmaWxsPSIjRkZDQkE1Ii8+CjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMV83NDA4M18xMzg3MjEpIj4KPHBhdGggZD0iTTI4Ljk3NzIgMTYuMjIxNUMzMC44NTk5IDE2LjIyMTUgMzIuMzg2MSAxNC42OTU0IDMyLjM4NjEgMTIuODEyOUMzMi4zODYxIDEwLjkzMDQgMzAuODU5OSA5LjQwNDMgMjguOTc3MiA5LjQwNDNDMjcuMDk0NiA5LjQwNDMgMjUuNTY4MyAxMC45MzA0IDI1LjU2ODMgMTIuODEyOUMyNS41NjgzIDE0LjY5NTQgMjcuMDk0NiAxNi4yMjE1IDI4Ljk3NzIgMTYuMjIxNVoiIGZpbGw9IiMxOTI5NTIiLz4KPHBhdGggZD0iTTYzLjU2OTUgNTEuODU1NkM2My4zMTI0IDUxLjE0OTggNjMuMTMxOCA1MC40MDU3IDYzLjAzMzMgNDkuNjM0M0M2Mi42Nzc2IDQ2LjgwNTcgNjMuNTI1OCA0NC4xMDI5IDY1LjE3MjggNDIuMDM0OEM2NC4wODM5IDQxLjE1MzkgNjIuOTg0MSA0MC4zMDA0IDYxLjg2MjQgMzkuNDY4N0M2MS44MDc2IDM5LjQzMDQgNjEuNzU4NCAzOS4zOTIxIDYxLjcwMzcgMzkuMzUzOEM2MS4yMDAzIDM4Ljk4MTggNjAuNjkxNCAzOC42MTUyIDYwLjE4MjUgMzguMjU0MUM1OS41ODA2IDM3LjgyNzQgNTguOTczMyAzNy40MDYxIDU4LjM2MDQgMzYuOTk1N0M1OC4zNDk1IDM2Ljk5MDMgNTguMzM4NiAzNi45NzkzIDU4LjMyNzYgMzYuOTczOUM1Ni40NTYzIDQyLjA1NjYgNTMuOTY2NiA0Ni4zMTg3IDUxLjk0MjEgNDkuMzE3QzU1LjMyOTEgNTEuMzMwNCA1OS4zNjcyIDUyLjI5ODggNjMuNTY5NSA1MS44NTU2WiIgZmlsbD0iIzE5Mjk1MiIvPgo8cGF0aCBkPSJNMzYuODQwMSA0NS43Mjc4QzM3LjE3MzkgNDYuNTE1NyAzOC4wMjIgNDYuOTkxNyAzOC44OTc1IDQ2LjgyMjFDMzkuOTA0MyA0Ni42MjUxIDQwLjU2MDkgNDUuNjU2NyA0MC4zNjM5IDQ0LjY1QzQwLjE2NjkgNDMuNjQzMyAzOS4xOTMgNDIuOTg2OCAzOC4xOTE2IDQzLjE4MzdDMzcuODY4OCA0My4yNDM5IDM3LjU4OTcgNDMuMzkxNiAzNy4zNTk5IDQzLjU4ODZDMzUuODM4OCA0Mi45OTIyIDM0LjIzNTYgNDIuNTg3MyAzMi41NzIyIDQyLjM5NTlDMzMuNjY2NSAzOS45MzM4IDM0LjU0NzUgMzcuMTM4IDM0LjgwNDYgMzQuMjA1NEMzOS4xMzgyIDM3LjE5MjcgNDMuMTE2MiA0MC42ODg4IDQ2LjYyMzYgNDQuNjM5MUM0Ny40NzcyIDM5LjUzNDQgNDcuNjE5NCAzNC44MTI3IDQ3LjM5NTEgMzAuNjkyOUM0Ni43MTY2IDMwLjM1OTEgNDYuMDM4MSAzMC4wMzYzIDQ1LjM1NDEgMjkuNzE5QzQ0LjYzMTkgMjkuMzg1MyA0My45MDQxIDI5LjA1NyA0My4xNzA5IDI4LjczOTZDMzIuNjU5NyAyNC4yMzEzIDIxLjIzNDcgMjEuNjA1MiA5LjM1NTU5IDIxLjIzMzFDMTAuOTUzMyAyMy45NDY4IDE0LjI1ODMgMjQuNzgzOSAxNC4yNTgzIDI0Ljc4MzlDMTguMTU0MSAyNS43OTYxIDIxLjkxODcgMjcuMTYzOSAyNS41MTkxIDI4Ljg1NDVDMjYuMTE1NSAzMC44MzUxIDI3LjQxNzggMzYuMDYwMiAyNi45OTY1IDQyLjU2NTVDMjQuMDggNDMuMDg1MiAyMS40MjYyIDQ0LjIzOTcgMTkuMTYwOSA0NS44ODFDMTguODEwNyA0NS43MDYgMTguNDAwNCA0NS42MzQ4IDE3Ljk4NDUgNDUuNzE2OUMxNi45Nzc3IDQ1LjkxMzkgMTYuMzIxMSA0Ni44ODc3IDE2LjUxODEgNDcuODg5QzE2LjcxNTEgNDguODkwMiAxNy42ODM2IDQ5LjU1MjIgMTguNjkwNCA0OS4zNTUzQzE5LjQ4MzggNDkuMjAyMSAyMC4wNTI4IDQ4LjU2MTkgMjAuMTYyMyA0Ny44MDE0QzIyLjIyNTEgNDcuMDkwMiAyNC4zNyA0Ni41Mzc2IDI2LjU4NjEgNDYuMTYwMUMyNi4zODM2IDQ3LjQwMiAyNi4xMTU1IDQ4LjY3NjggMjUuNzU0NCA0OS45NjhDMjUuNzQ4OSA0OS45NjggMjUuNzM4IDQ5Ljk2OCAyNS43MzI1IDQ5Ljk2OEMyNC43MjU3IDUwLjE2NSAyNC4wNjkxIDUxLjEzODkgMjQuMjY2MSA1Mi4xNDAxQzI0LjQ2MyA1My4xNDE0IDI1LjQzMTUgNTMuODAzNCAyNi40MzgzIDUzLjYwNjRDMjcuNDQ1MSA1My40MDk1IDI4LjEwMTggNTIuNDM1NiAyNy45MDQ4IDUxLjQzNDNDMjcuODQ0NiA1MS4xMzM0IDI3LjcxMzMgNTAuODcwOCAyNy41MzI3IDUwLjY0NjVDMjguMzIwNiA0OS42NTYyIDI5LjYxMiA0Ny45MTA5IDMwLjg5NzggNDUuNjYyMkMzMi45MDA1IDQ1LjUzNjMgMzQuODgxMiA0NS41NTgyIDM2LjgyOTIgNDUuNzIyNEwzNi44NDAxIDQ1LjcyNzhaIiBmaWxsPSIjMTkyOTUyIi8+CjxwYXRoIGQ9Ik05OS4yNTA3IDM5LjExMzVDOTguNjM3OSAzNC4yMTY3IDk0LjE2NzUgMzAuNzQyNSA4OS4yNzAzIDMxLjM1NTNDODkuMDk1MiAzMS4zNzcyIDg4LjkyNTYgMzEuNDEgODguNzU1OSAzMS40NDI4QzgxLjkxNjMgMjQuMTY2MSA3NS40MzIzIDE2LjkyMjEgNjYuMTUyMiAxNC42NjI1QzY1Ljk0NDMgMTQuNjEzMyA2NS43MzY0IDE0LjU2NCA2NS41Mjg0IDE0LjUyMDNDNTUuODkyNyAxMi40MzU3IDQ1Ljk1MDYgMTEuMjkyMiAzNS44MTY5IDExLjE2MDlDMzQuOTk2MSA5LjA4NzMzIDMyLjg2MjIgNy43NDY4OCAzMC41NDc2IDguMDM2ODZDMzAuMzg4OSA4LjA1ODc0IDMwLjIzMDMgOC4wODYxIDMwLjA3NzEgOC4xMTg5M0MyOS4wMjEgNi45MzE2NyAyNy40MTc4IDYuMjY5NjUgMjUuNzIxNiA2LjQ4MzAzQzIzLjExNyA2LjgxMTMgMjEuMjM0NyA5LjA4MTg2IDIxLjM0OTYgMTEuNjU4OEMxMy4xMDM3IDEyLjg3MzQgNy43ODUyMSAxNi42NjUgOS4zNTU2IDIxLjIzMzVDMjEuMjI5MyAyMS42MDU1IDMyLjY1OTcgMjQuMjMxNyA0My4xNiAyOC43MzQ1QzQ0LjU4ODEgMjkuMzQ3MyA0NS45OTQzIDMwLjAwMzkgNDcuMzg5NiAzMC42ODc4QzQ3LjcxNzkgMzYuNzI4IDQ3LjI2MzggNDQuMDU5NSA0NC45MjczIDUyLjAwOTJDMzkuODkzMyA1Mi40NTc4IDM2LjAxOTQgNTQuMDY2NCAzNC4xMDk3IDU1LjAyMzhDMzMuNjk5MyA1NC42OTAxIDMzLjE1MjIgNTQuNTMxNCAzMi41OTQxIDU0LjYzNTRDMzEuNTg3MyA1NC44MzI0IDMwLjkzMDYgNTUuODA2MiAzMS4xMjc2IDU2LjgwNzVDMzEuMzI0NiA1Ny44MDg3IDMyLjI5ODYgNTguNDcwNyAzMy4yOTk5IDU4LjI3MzhDMzQuMTg2MyA1OC4xMDQxIDM0Ljc5OTIgNTcuMzI3MiAzNC43OTkyIDU2LjQ1NzNDMzguNzU1MiA1NS40MDY4IDQxLjU3ODYgNTUuNTMyNyA0MS41Nzg2IDU1LjUzMjdDMzkuNjkwOSA1Ni41Mjg0IDM3LjcxMDEgNTguODIwOSAzNi42Mzc3IDYwLjE4MzJDMzYuNDU3MSA2MC4xNjY4IDM2LjI3NjUgNjAuMTYxMyAzNi4wOTA1IDYwLjE5OTZDMzUuMDgzNyA2MC4zOTY2IDM0LjQyNzEgNjEuMzY1IDM0LjYyNDEgNjIuMzcxN0MzNC44MjEgNjMuMzc4NCAzNS43OTUgNjQuMDM1IDM2Ljc5NjMgNjMuODM4QzM3Ljc5NzcgNjMuNjQxIDM4LjQ1OTcgNjIuNjcyNiAzOC4yNjI4IDYxLjY2NTlDMzguMjQwOSA2MS41NjIgMzguMjA4IDYxLjQ2MzUgMzguMTc1MiA2MS4zNjVDNDIuMTY0MSA1OC4yMTM2IDQ1LjQ4NTUgNTYuOTA2IDQ1LjQ4NTUgNTYuOTA2QzQ1LjUyMzggNTguMTY0MyA0NS40MjUzIDYwLjA3MzggNDUuMzM3NyA2MS40MjUyQzQ0LjQ2MjIgNjEuNzA5NyA0My45MTUxIDYyLjYwMTUgNDQuMDkwMiA2My41MzE2QzQ0LjI4NzEgNjQuNTM4MyA0NS4yNjExIDY1LjE5NDkgNDYuMjYyNCA2NC45OTc5QzQ3LjI2MzggNjQuODAwOSA0Ny45MjU4IDYzLjgzMjUgNDcuNzI4OSA2Mi44MjU4QzQ3LjY1MjMgNjIuNDIxIDQ3LjQzODkgNjIuMDc2MyA0Ny4xNTQzIDYxLjgxMzZDNDguODk5OCA1Ny44OTA4IDQ5LjAwMzggNTQuMzY3MyA0OC45ODc0IDUzLjI4OTVDNTAuNjYxNyA1MS4yNTQyIDU1LjI5NjMgNDUuMTc1NiA1OC4zMjIxIDM2Ljk2ODhDNjAuNjgwNSAzOC41NDQ1IDYyLjk1NjcgNDAuMjQwNiA2NS4xNjczIDQyLjAyOTdDNjMuNTIwMyA0NC4wOTc4IDYyLjY3NzcgNDYuODAwNiA2My4wMjc4IDQ5LjYyOTJDNjMuNTQ3NyA1My43NiA2Ni40NzUgNTYuOTk5IDcwLjIyODYgNTguMTE1MUM2Ni45NTExIDU4LjgwNDUgNjQuNDQ1IDU5Ljg4MjMgNjMuMDIyNCA2MC41OTM2QzYyLjYxMiA2MC4yNTk4IDYyLjA2NDggNjAuMTAxMiA2MS41MDY3IDYwLjIwNTFDNjAuNDk5OSA2MC40MDIxIDU5Ljg0MzMgNjEuMzcwNSA2MC4wNDAzIDYyLjM3NzJDNjAuMjM3MyA2My4zODM5IDYxLjIxMTIgNjQuMDQwNCA2Mi4yMTI1IDYzLjg0MzVDNjMuMDk5IDYzLjY3MzkgNjMuNzExOCA2Mi44OTY5IDYzLjcxMTggNjIuMDI3QzY3LjY2NzkgNjAuOTc2NSA3MC40OTEzIDYxLjEwMjQgNzAuNDkxMyA2MS4xMDI0QzY4LjYwMzUgNjIuMDk4MiA2Ni42MjI4IDY0LjM5MDYgNjUuNTUwMyA2NS43NTI5QzY1LjM2OTcgNjUuNzM2NSA2NS4xODkyIDY1LjczMTEgNjUuMDAzMSA2NS43Njk0QzYzLjk5NjMgNjUuOTY2MyA2My4zMzk3IDY2Ljk0MDIgNjMuNTM2NyA2Ny45NDE0QzYzLjczMzcgNjguOTQ4MSA2NC43MDc3IDY5LjYwNDcgNjUuNzA5IDY5LjQwNzdDNjYuNzEwMyA2OS4yMTA4IDY3LjM3MjQgNjguMjM2OSA2Ny4xNzU0IDY3LjIzNTZDNjcuMTUzNSA2Ny4xMzE3IDY3LjEyMDcgNjcuMDMzMiA2Ny4wODc5IDY2LjkzNDdDNzEuMDc2OCA2My43ODMzIDc0LjM5ODEgNjIuNDc1NyA3NC4zOTgxIDYyLjQ3NTdDNzQuNDM2NCA2My43MzQxIDc0LjMzNzkgNjUuNjQzNSA3NC4yNTA0IDY2Ljk5NDlDNzMuMzc0OSA2Ny4yNzk0IDcyLjgyNzcgNjguMTcxMiA3My4wMDI4IDY5LjEwMTNDNzMuMTk5OCA3MC4xMDggNzQuMTczOCA3MC43NjQ2IDc1LjE3NTEgNzAuNTY3NkM3Ni4xODE5IDcwLjM3MDcgNzYuODM4NSA2OS40MDIzIDc2LjY0MTUgNjguMzk1NUM3Ni41NjQ5IDY3Ljk5MDcgNzYuMzUxNSA2Ny42NDYgNzYuMDY3IDY3LjM4MzRDNzcuNDI0IDY0LjMzMDQgNzcuNzkwNiA2MS41MTI3IDc3Ljg3ODEgNTkuOTA0MkM3OC42Mjc4IDU5LjY3NDQgODkuNTk4NiA1Ni4xOTQ3IDk3LjMxMzcgNDUuODM3NkM5Ny41MzI2IDQ1LjU2NDEgOTcuNzQwNSA0NS4yODUgOTcuOTMyIDQ0Ljk4OTZDOTcuOTQzIDQ0Ljk3MzIgOTcuOTUzOSA0NC45NTY4IDk3Ljk3MDMgNDQuOTQwNEg5Ny45NjQ5Qzk5LjAxIDQzLjI1NTIgOTkuNTA3OSA0MS4yMjU0IDk5LjI0NTIgMzkuMTA4TDk5LjI1MDcgMzkuMTEzNVpNMjkuMzk4NiAxNi4xOTQ1QzI3LjUzMjcgMTYuNDI5NyAyNS44MzEgMTUuMTA1NyAyNS41OTU3IDEzLjI0QzI1LjM2MDQgMTEuMzc0MyAyNi42ODQ2IDkuNjcyNzYgMjguNTUwNCA5LjQzNzQ5QzMwLjQxNjMgOS4yMDIyMyAzMi4xMTggMTAuNTI2MyAzMi4zNTMzIDEyLjM5MkMzMi41ODg2IDE0LjI1NzcgMzEuMjY0NCAxNS45NTkyIDI5LjM5ODYgMTYuMTk0NVoiIGZpbGw9IndoaXRlIi8+CjwvZz4KPC9nPgo8L2c+CjxkZWZzPgo8Y2xpcFBhdGggaWQ9ImNsaXAwXzc0MDgzXzEzODcyMSI+CjxyZWN0IHdpZHRoPSI2MCIgaGVpZ2h0PSI2MCIgZmlsbD0id2hpdGUiLz4KPC9jbGlwUGF0aD4KPGNsaXBQYXRoIGlkPSJjbGlwMV83NDA4M18xMzg3MjEiPgo8cmVjdCB3aWR0aD0iOTAuMjM0NCIgaGVpZ2h0PSI2NC4xNjY3IiBmaWxsPSJ3aGl0ZSIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoOS4wODIwMyA2LjQ0NTMxKSIvPgo8L2NsaXBQYXRoPgo8L2RlZnM+Cjwvc3ZnPgo=", + "BannerUrl": "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjc5IiBoZWlnaHQ9IjgxIiB2aWV3Qm94PSIwIDAgMjc5IDgxIiBmaWxsPSJub25lIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPgo8ZyBjbGlwLXBhdGg9InVybCgjY2xpcDBfNzQwODNfMTM4Mzk3KSI+CjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMV83NDA4M18xMzgzOTcpIj4KPGcgY2xpcC1wYXRoPSJ1cmwoI2NsaXAyXzc0MDgzXzEzODM5NykiPgo8cGF0aCBkPSJNNDYuMDAyNSAxNC4xNjU3QzQ4LjUyOTkgMTQuMTY1NyA1MC41Nzg5IDEyLjExNyA1MC41Nzg5IDkuNTg5NjlDNTAuNTc4OSA3LjA2MjQzIDQ4LjUyOTkgNS4wMTM2NyA0Ni4wMDI1IDUuMDEzNjdDNDMuNDc1IDUuMDEzNjcgNDEuNDI2IDcuMDYyNDMgNDEuNDI2IDkuNTg5NjlDNDEuNDI2IDEyLjExNyA0My40NzUgMTQuMTY1NyA0Ni4wMDI1IDE0LjE2NTdaIiBmaWxsPSIjMTkyOTUyIi8+CjxwYXRoIGQ9Ik05Mi40NDI2IDYyLjAwNDZDOTIuMDk3NCA2MS4wNTcxIDkxLjg1NSA2MC4wNTgxIDkxLjcyMjcgNTkuMDIyNEM5MS4yNDUzIDU1LjIyNSA5Mi4zODM5IDUxLjU5NjUgOTQuNTk0OSA0OC44MjAxQzkzLjEzMzEgNDcuNjM3NSA5MS42NTY2IDQ2LjQ5MTYgOTAuMTUwNyA0NS4zNzUyQzkwLjA3NzMgNDUuMzIzOCA5MC4wMTEyIDQ1LjI3MjQgODkuOTM3NyA0NS4yMjA5Qzg5LjI2MTkgNDQuNzIxNSA4OC41Nzg3IDQ0LjIyOTMgODcuODk1NiA0My43NDQ2Qzg3LjA4NzUgNDMuMTcxNiA4Ni4yNzIxIDQyLjYwNjEgODUuNDQ5NCA0Mi4wNTUyQzg1LjQzNDcgNDIuMDQ3OCA4NS40MiA0Mi4wMzMyIDg1LjQwNTMgNDIuMDI1OEM4Mi44OTMxIDQ4Ljg0OTQgNzkuNTUwNyA1NC41NzEzIDc2LjgzMjggNTguNTk2NEM4MS4zNzk4IDYxLjI5OTQgODYuODAxIDYyLjU5OTUgOTIuNDQyNiA2Mi4wMDQ2WiIgZmlsbD0iIzE5Mjk1MiIvPgo8cGF0aCBkPSJNNTYuNTU4NCA1My43NzhDNTcuMDA2NSA1NC44MzU3IDU4LjE0NTEgNTUuNDc0OCA1OS4zMjA0IDU1LjI0NzFDNjAuNjcyIDU0Ljk4MjYgNjEuNTUzNSA1My42ODI1IDYxLjI4OTEgNTIuMzMxQzYxLjAyNDYgNTAuOTc5NSA1OS43MTcxIDUwLjA5ODEgNTguMzcyOCA1MC4zNjI1QzU3LjkzOTQgNTAuNDQzMyA1Ny41NjQ3IDUwLjY0MTcgNTcuMjU2MiA1MC45MDYxQzU1LjIxNDEgNTAuMTA1NSA1My4wNjE4IDQ5LjU2MTkgNTAuODI4NiA0OS4zMDQ4QzUyLjI5NzggNDUuOTk5NSA1My40ODA1IDQyLjI0NjIgNTMuODI1NyAzOC4zMDkyQzU5LjY0MzYgNDIuMzE5NiA2NC45ODQgNDcuMDEzMiA2OS42OTI3IDUyLjMxNjNDNzAuODM4NiA0NS40NjMzIDcxLjAyOTYgMzkuMTI0NSA3MC43Mjg0IDMzLjU5MzZDNjkuODE3NSAzMy4xNDU1IDY4LjkwNjcgMzIuNzEyMiA2Ny45ODg0IDMyLjI4NjJDNjcuMDE4OCAzMS44MzgxIDY2LjA0MTggMzEuMzk3NCA2NS4wNTc1IDMwLjk3MTRDNTAuOTQ2MiAyNC45MTkgMzUuNjA4MSAyMS4zOTMzIDE5LjY2MDQgMjAuODkzOUMyMS44MDU0IDI0LjUzNyAyNi4yNDIyIDI1LjY2MDggMjYuMjQyMiAyNS42NjA4QzMxLjQ3MjUgMjcuMDE5NyAzNi41MjY0IDI4Ljg1NiA0MS4zNTk5IDMxLjEyNTZDNDIuMTYwNiAzMy43ODQ2IDQzLjkwODkgNDAuNzk5MiA0My4zNDMzIDQ5LjUzMjVDMzkuNDI4IDUwLjIzMDMgMzUuODY1MiA1MS43ODAyIDMyLjgyNDEgNTMuOTgzN0MzMi4zNTM5IDUzLjc0ODYgMzEuODAzIDUzLjY1MzIgMzEuMjQ0NyA1My43NjMzQzI5Ljg5MzEgNTQuMDI3OCAyOS4wMTE2IDU1LjMzNTIgMjkuMjc2MSA1Ni42Nzk0QzI5LjU0MDUgNTguMDIzNSAzMC44NDA3IDU4LjkxMjMgMzIuMTkyMyA1OC42NDc5QzMzLjI1NzUgNTguNDQyMiAzNC4wMjE0IDU3LjU4MjggMzQuMTY4NCA1Ni41NjE4QzM2LjkzNzcgNTUuNjA3IDM5LjgxNzMgNTQuODY1MSA0Mi43OTIzIDU0LjM1ODNDNDIuNTIwNSA1Ni4wMjU2IDQyLjE2MDYgNTcuNzM3MSA0MS42NzU4IDU5LjQ3MDVDNDEuNjY4NCA1OS40NzA1IDQxLjY1MzcgNTkuNDcwNSA0MS42NDY0IDU5LjQ3MDVDNDAuMjk0OCA1OS43MzQ5IDM5LjQxMzMgNjEuMDQyNCAzOS42Nzc3IDYyLjM4NjVDMzkuOTQyMiA2My43MzA3IDQxLjI0MjQgNjQuNjE5NCA0Mi41OTQgNjQuMzU1QzQzLjk0NTYgNjQuMDkwNiA0NC44MjcxIDYyLjc4MzIgNDQuNTYyNyA2MS40MzlDNDQuNDgxOSA2MS4wMzUgNDQuMzA1NiA2MC42ODI1IDQ0LjA2MzIgNjAuMzgxM0M0NS4xMjEgNTkuMDUxOCA0Ni44NTQ2IDU2LjcwODcgNDguNTgwOCA1My42ODk5QzUxLjI2OTQgNTMuNTIwOSA1My45Mjg2IDUzLjU1MDMgNTYuNTQzNyA1My43NzA3TDU2LjU1ODQgNTMuNzc4WiIgZmlsbD0iIzE5Mjk1MiIvPgo8cGF0aCBkPSJNMTQwLjM0NSA0NC44OTY3QzEzOS41MjIgMzguMzIyOCAxMzMuNTIgMzMuNjU4NyAxMjYuOTQ2IDM0LjQ4MTNDMTI2LjcxMSAzNC41MTA3IDEyNi40ODMgMzQuNTU0OCAxMjYuMjU1IDM0LjU5ODlDMTE3LjA3MyAyNC44Mjk4IDEwOC4zNjggMTUuMTA0OSA5NS45MDk4IDEyLjA3MTNDOTUuNjMwNyAxMi4wMDUyIDk1LjM1MTUgMTEuOTM5MSA5NS4wNzI0IDExLjg4MDRDODIuMTM2NCA5LjA4MTg3IDY4Ljc4OTEgNy41NDY3NCA1NS4xODQ3IDcuMzcwNDVDNTQuMDgyOCA0LjU4NjY1IDUxLjIxNzkgMi43ODcwOSA0OC4xMTA3IDMuMTc2MzhDNDcuODk3NiAzLjIwNTc2IDQ3LjY4NDYgMy4yNDI0OSA0Ny40Nzg5IDMuMjg2NTZDNDYuMDYxMiAxLjY5MjY2IDQzLjkwODkgMC44MDM5MDEgNDEuNjMxNyAxLjA5MDM2QzM4LjEzNTEgMS41MzEwNyAzNS42MDgxIDQuNTc5MyAzNS43NjI0IDguMDM4ODZDMjQuNjkyMiA5LjY2OTQ4IDE3LjU1MjEgMTQuNzU5NyAxOS42NjA0IDIwLjg5MjhDMzUuNjAwOCAyMS4zOTIzIDUwLjk0NjEgMjQuOTE4IDY1LjA0MjcgMzAuOTYzQzY2Ljk2IDMxLjc4NTcgNjguODQ3OSAzMi42NjcxIDcwLjcyMSAzMy41ODUyQzcxLjE2MTggNDEuNjk0MyA3MC41NTIxIDUxLjUzNjggNjcuNDE1NCA2Mi4yMDkyQzYwLjY1NzMgNjIuODExNSA1NS40NTY1IDY0Ljk3MSA1Mi44OTI4IDY2LjI1NjRDNTIuMzQxOCA2NS44MDgzIDUxLjYwNzMgNjUuNTk1MyA1MC44NTggNjUuNzM0OUM0OS41MDY0IDY1Ljk5OTMgNDguNjI0OSA2Ny4zMDY4IDQ4Ljg4OTMgNjguNjUwOUM0OS4xNTM4IDY5Ljk5NTEgNTAuNDYxMyA3MC44ODM4IDUxLjgwNTYgNzAuNjE5NEM1Mi45OTU2IDcwLjM5MTcgNTMuODE4MyA2OS4zNDg3IDUzLjgxODMgNjguMTgwOEM1OS4xMjk0IDY2Ljc3MDYgNjIuOTE5OCA2Ni45Mzk1IDYyLjkxOTggNjYuOTM5NUM2MC4zODU1IDY4LjI3NjMgNTcuNzI2MyA3MS4zNTM5IDU2LjI4NjUgNzMuMTgyOUM1Ni4wNDQxIDczLjE2MDggNTUuODAxNyA3My4xNTM1IDU1LjU1MiA3My4yMDQ5QzU0LjIwMDMgNzMuNDY5MyA1My4zMTg4IDc0Ljc2OTQgNTMuNTgzMyA3Ni4xMjA5QzUzLjg0NzcgNzcuNDcyNCA1NS4xNTUzIDc4LjM1MzggNTYuNDk5NiA3OC4wODk0QzU3Ljg0MzggNzcuODI1IDU4LjczMjcgNzYuNTI0OSA1OC40NjgyIDc1LjE3MzRDNTguNDM4OSA3NS4wMzM4IDU4LjM5NDggNzQuOTAxNiA1OC4zNTA3IDc0Ljc2OTRDNjMuNzA1OCA3MC41Mzg2IDY4LjE2NDcgNjguNzgzMSA2OC4xNjQ3IDY4Ljc4MzFDNjguMjE2MSA3MC40NzI1IDY4LjA4MzkgNzMuMDM2IDY3Ljk2NjQgNzQuODUwMkM2Ni43OTEgNzUuMjMyMiA2Ni4wNTY1IDc2LjQyOTQgNjYuMjkxNSA3Ny42NzgxQzY2LjU1NiA3OS4wMjk2IDY3Ljg2MzUgNzkuOTExIDY5LjIwNzggNzkuNjQ2NkM3MC41NTIxIDc5LjM4MjIgNzEuNDQwOSA3OC4wODIxIDcxLjE3NjUgNzYuNzMwNkM3MS4wNzM2IDc2LjE4NyA3MC43ODcyIDc1LjcyNDMgNzAuNDA1MiA3NS4zNzE3QzcyLjc0ODUgNzAuMTA1MiA3Mi44ODgxIDY1LjM3NSA3Mi44NjYgNjMuOTI4Qzc1LjExMzggNjEuMTk1NiA4MS4zMzU3IDUzLjAzNTIgODUuMzk4IDQyLjAxNzVDODguNTY0IDQ0LjEzMjkgOTEuNjE5OSA0Ni40MDk4IDk0LjU4NzYgNDguODExN0M5Mi4zNzY1IDUxLjU4ODIgOTEuMjQ1MiA1NS4yMTY3IDkxLjcxNTMgNTkuMDE0MUM5Mi40MTMyIDY0LjU1OTcgOTYuMzQzMiA2OC45MDggMTAxLjM4MiA3MC40MDY0Qzk2Ljk4MjMgNzEuMzMxOSA5My42MTc5IDcyLjc3ODkgOTEuNzA4IDczLjczMzdDOTEuMTU3MSA3My4yODU3IDkwLjQyMjUgNzMuMDcyNyA4OS42NzMyIDczLjIxMjJDODguMzIxNiA3My40NzY3IDg3LjQ0MDEgNzQuNzc2OCA4Ny43MDQ1IDc2LjEyODNDODcuOTY5IDc3LjQ3OTggODkuMjc2NSA3OC4zNjEyIDkwLjYyMDggNzguMDk2OEM5MS44MTA4IDc3Ljg2OTEgOTIuNjMzNiA3Ni44MjYgOTIuNjMzNiA3NS42NTgyQzk3Ljk0NDYgNzQuMjQ3OSAxMDEuNzM1IDc0LjQxNjggMTAxLjczNSA3NC40MTY4Qzk5LjIwMDcgNzUuNzUzNyA5Ni41NDE1IDc4LjgzMTMgOTUuMTAxOCA4MC42NjAyQzk0Ljg1OTMgODAuNjM4MiA5NC42MTY5IDgwLjYzMDggOTQuMzY3MiA4MC42ODIzQzkzLjAxNTYgODAuOTQ2NyA5Mi4xMzQxIDgyLjI1NDEgOTIuMzk4NSA4My41OTgzQzkyLjY2MyA4NC45NDk4IDkzLjk3MDUgODUuODMxMiA5NS4zMTQ4IDg1LjU2NjhDOTYuNjU5MSA4NS4zMDIzIDk3LjU0NzkgODMuOTk0OSA5Ny4yODM1IDgyLjY1MDdDOTcuMjU0MSA4Mi41MTEyIDk3LjIxIDgyLjM3OSA5Ny4xNjU5IDgyLjI0NjhDMTAyLjUyMSA3OC4wMTYgMTA2Ljk4IDc2LjI2MDUgMTA2Ljk4IDc2LjI2MDVDMTA3LjAzMSA3Ny45NDk5IDEwNi44OTkgODAuNTEzMyAxMDYuNzgyIDgyLjMyNzZDMTA1LjYwNiA4Mi43MDk1IDEwNC44NzIgODMuOTA2OCAxMDUuMTA3IDg1LjE1NTRDMTA1LjM3MSA4Ni41MDY5IDEwNi42NzkgODcuMzg4NCAxMDguMDIzIDg3LjEyMzlDMTA5LjM3NSA4Ni44NTk1IDExMC4yNTYgODUuNTU5NCAxMDkuOTkyIDg0LjIwNzlDMTA5Ljg4OSA4My42NjQ0IDEwOS42MDIgODMuMjAxNiAxMDkuMjIgODIuODQ5MUMxMTEuMDQyIDc4Ljc1MDUgMTExLjUzNCA3NC45Njc3IDExMS42NTIgNzIuODA4M0MxMTIuNjU4IDcyLjQ5OTggMTI3LjM4NyA2Ny44MjgzIDEzNy43NDQgNTMuOTIzOUMxMzguMDM4IDUzLjU1NjcgMTM4LjMxNyA1My4xODIxIDEzOC41NzQgNTIuNzg1NEMxMzguNTg5IDUyLjc2MzQgMTM4LjYwNCA1Mi43NDE0IDEzOC42MjYgNTIuNzE5M0gxMzguNjE4QzE0MC4wMjEgNTAuNDU3IDE0MC42OSA0Ny43MzIgMTQwLjMzNyA0NC44ODk0TDE0MC4zNDUgNDQuODk2N1pNNDYuNTY4IDE0LjEyOEM0NC4wNjMxIDE0LjQ0MzggNDEuNzc4NiAxMi42NjYzIDQxLjQ2MjcgMTAuMTYxNkM0MS4xNDY4IDcuNjU2OTEgNDIuOTI0NSA1LjM3MjU4IDQ1LjQyOTQgNS4wNTY3M0M0Ny45MzQ0IDQuNzQwODkgNTAuMjE4OSA2LjUxODQyIDUwLjUzNDggOS4wMjMxMUM1MC44NTA2IDExLjUyNzggNDkuMDczIDEzLjgxMjEgNDYuNTY4IDE0LjEyOFoiIGZpbGw9IiNGRkNCQTUiLz4KPC9nPgo8cmVjdCB4PSI4Ny40Njc0IiB5PSItMC4zMDQ2ODgiIHdpZHRoPSIyLjAxMzc1IiBoZWlnaHQ9IjgwLjU1IiBmaWxsPSIjMTkyOTUyIi8+CjwvZz4KPHBhdGggZD0iTTExMy4zOTYgNTUuMTcxNUwxMDUuMjE1IDI4LjEwMTNDMTA1LjA5MyAyNy42ODg2IDEwNS4zOTkgMjcuMjY4MiAxMDUuODM1IDI3LjI2ODJIMTEwLjU0MkMxMTAuODMyIDI3LjI2ODIgMTExLjA5MyAyNy40NTkzIDExMS4xNjkgMjcuNzQyMUwxMTcuMDU0IDQ4Ljg1MUgxMTcuNDQ1TDEyMy42MDUgMjcuNzM0NEMxMjMuNjg5IDI3LjQ1OTMgMTIzLjk0MiAyNy4yNjgyIDEyNC4yMzMgMjcuMjY4MkgxMjguNzcxQzEyOS4wNjIgMjcuMjY4MiAxMjkuMzE0IDI3LjQ1OTMgMTI5LjM5OCAyNy43MzQ0TDEzNS40OTggNDguODUxSDEzNS45NDFMMTQxLjc3MyAyNy43NDIxQzE0MS44NDkgMjcuNDU5MyAxNDIuMTEgMjcuMjY4MiAxNDIuNCAyNy4yNjgySDE0Ni45OTJDMTQ3LjQyOCAyNy4yNjgyIDE0Ny43NDIgMjcuNjg4NiAxNDcuNjEyIDI4LjEwODlMMTM5LjM3IDU1LjE3OTJDMTM5LjI4NiA1NS40NTQzIDEzOS4wMzMgNTUuNjM3NyAxMzguNzUgNTUuNjM3N0gxMzIuNjk3QzEzMi40MTMgNTUuNjM3NyAxMzIuMTUzIDU1LjQ0NjcgMTMyLjA3NyA1NS4xNzkyTDEyNi41OSAzNi45NTE1SDEyNi4xNDZMMTIwLjc2NiA1NS4xNzkyQzEyMC42ODIgNTUuNDU0MyAxMjAuNDI5IDU1LjY0NTQgMTIwLjE0NiA1NS42NDU0SDExNC4wMzlDMTEzLjc1NiA1NS42NDU0IDExMy41MDMgNTUuNDU0MyAxMTMuNDE5IDU1LjE4NjhMMTEzLjM5NiA1NS4xNzE1WiIgZmlsbD0iIzE5Mjk1MiIvPgo8cGF0aCBkPSJNMTU4LjQ4NyA1Ni4wNzMzQzE1Ni41NTggNTYuMDczMyAxNTQuOTI4IDU1LjgxMzUgMTUzLjYxMiA1NS4yOTM4QzE1Mi4yOTYgNTQuNzc0MSAxNTEuMzAxIDUzLjkxMDUgMTUwLjYzNSA1Mi43MTA2QzE0OS45NjkgNTEuNTAzIDE0OS42MzIgNDkuODY3NSAxNDkuNjMyIDQ3Ljc4ODdDMTQ5LjYzMiA0NS42MDI5IDE0OS44OTMgNDMuODY4MSAxNTAuNDEzIDQyLjU5MTdDMTUwLjkzMyA0MS4zMTU0IDE1MS44MjEgNDAuMzkwNiAxNTMuMDg0IDM5Ljg0MDRDMTU0LjM0NiAzOS4yODI1IDE1Ni4xMyAzOS4wMDczIDE1OC40MzMgMzkuMDA3M0MxNTguOCAzOS4wMDczIDE1OS4zNTEgMzkuMDE1IDE2MC4wNzggMzkuMDM3OUMxNjAuODA1IDM5LjA1MzIgMTYxLjY0IDM5LjA3NjEgMTYyLjU4OSAzOS4wOTE0QzE2My41MzggMzkuMTE0MyAxNjQuNDc5IDM5LjEyOTYgMTY1LjQyOCAzOS4xNDQ5QzE2Ni4xMDkgMzkuMTYwMiAxNjYuNzQ0IDM5LjE3NTUgMTY3LjM0MSAzOS4xOTg0QzE2Ny43MTYgMzkuMjEzNyAxNjguMDIyIDM4LjkxNTYgMTY4LjAyMiAzOC41NDExVjM3Ljg5MTVDMTY4LjAyMiAzNi40NDcgMTY3LjkzIDM1LjMxNTkgMTY3Ljc0NyAzNC40OTgyQzE2Ny41NjMgMzMuNjgwNCAxNjcuMTggMzMuMDc2NiAxNjYuNjA2IDMyLjY5NDVDMTY2LjAzMiAzMi4zMDQ3IDE2NS4yMDYgMzIuMDUyNSAxNjQuMTI3IDMxLjk0NTVDMTYzLjA0OCAzMS44MzA5IDE2MS42NTUgMzEuNzc3NCAxNTkuOTQ4IDMxLjc3NzRDMTU5LjEyOSAzMS43Nzc0IDE1OC4xNzMgMzEuODA4IDE1Ny4wNzkgMzEuODYxNUMxNTUuOTg0IDMxLjkxNSAxNTQuOTEzIDMxLjk4MzcgMTUzLjg4IDMyLjA1MjVDMTUzLjIzNyAzMi4wOTg0IDE1Mi42ODYgMzIuMTUxOSAxNTIuMjI3IDMyLjIxM0MxNTEuODI5IDMyLjI2NjUgMTUxLjQ4NCAzMS45NjA4IDE1MS40ODQgMzEuNTYzNFYyOC4yMDgzQzE1MS40ODQgMjcuODk0OSAxNTEuNzA2IDI3LjYxOTggMTUyLjAyIDI3LjU1ODdDMTUzLjM5OCAyNy4zMTQxIDE1NC44OSAyNy4xMzA3IDE1Ni40OTcgMjcuMDE2QzE1OC4zMTggMjYuODg2MSAxNjAuMTMyIDI2LjgxNzMgMTYxLjk1MyAyNi44MTczQzE2NC4wNzMgMjYuODE3MyAxNjUuODQxIDI2Ljk0NzIgMTY3LjI3MiAyNy4yMDcxQzE2OC43MDMgMjcuNDY2OSAxNjkuODU5IDI3Ljg3MiAxNzAuNzU0IDI4LjQyOTlDMTcxLjY0MiAyOC45ODc4IDE3Mi4zMTUgMjkuNzA2MiAxNzIuNzU5IDMwLjYwMDRDMTczLjIwMyAzMS40OTQ2IDE3My41MTcgMzIuNTU2OSAxNzMuNzA4IDMzLjc5NTFDMTczLjg5MiAzNS4wNDA4IDE3My45ODQgMzYuNDU0NyAxNzMuOTg0IDM4LjA1MlY1NC45ODA0QzE3My45ODQgNTUuMzM5NyAxNzMuNjkzIDU1LjYzMDEgMTczLjMzMyA1NS42MzAxSDE2OS4xMzlDMTY4Ljc5NSA1NS42MzAxIDE2OC41MTIgNTUuMzYyNiAxNjguNDg5IDU1LjAxODdMMTY4LjMwNSA1MS45NjE2SDE2Ny45NjlDMTY3LjMzMyA1My4xNDYyIDE2Ni40OTIgNTQuMDQ4IDE2NS40MzUgNTQuNjU5NUMxNjQuMzc5IDU1LjI3MDkgMTYzLjIzMSA1NS42NjA2IDE2Mi4wMDcgNTUuODI4OEMxNjAuNzgzIDU1Ljk5NjkgMTU5LjYxMiA1Ni4wODEgMTU4LjQ5NCA1Ni4wODFMMTU4LjQ4NyA1Ni4wNzMzWk0xNjEuMTA0IDUxLjI4OTFDMTYyLjAzIDUxLjI4OTEgMTYyLjg3OSA1MS4yMjc5IDE2My42MzcgNTEuMDk4QzE2NC4zOTUgNTAuOTY4MSAxNjUuMDY4IDUwLjc0NjQgMTY1LjY0MiA1MC40MzMxQzE2Ni4yMTYgNTAuMTE5NyAxNjYuNjc1IDQ5LjY4NDEgMTY3LjAwNCA0OS4xMjYyQzE2Ny4zNDEgNDguNDk5NSAxNjcuNTg2IDQ3Ljc3MzQgMTY3Ljc1NCA0Ni45NTU3QzE2Ny45MjMgNDYuMTM3OSAxNjguMDA3IDQ1LjE3NDkgMTY4LjAwNyA0NC4wNjY4VjQzLjA2NTZIMTU5Ljg3MkMxNTguNjQ3IDQzLjA2NTYgMTU3LjcwNiA0My4xNTczIDE1Ny4wNTYgNDMuMzQwN0MxNTYuNDA1IDQzLjUyNDEgMTU1Ljk2OSA0My45MTM5IDE1NS43NDcgNDQuNTFDMTU1LjUyNSA0NS4xMDYyIDE1NS40MSA0Ni4wMDggMTU1LjQxIDQ3LjIzODVDMTU1LjQxIDQ4LjM5MjUgMTU1LjU0IDQ5LjI0ODUgMTU1LjgwMSA0OS44MjE3QzE1Ni4wNjEgNTAuMzk0OSAxNTYuNjEyIDUwLjc4NDYgMTU3LjQ0NiA1MC45OTFDMTU4LjI4IDUxLjE5NzMgMTU5LjQ5NyA1MS4yOTY3IDE2MS4wOTYgNTEuMjk2N0wxNjEuMTA0IDUxLjI4OTFaIiBmaWxsPSIjMTkyOTUyIi8+CjxwYXRoIGQ9Ik0xNzkuNTU1IDU1LjA1NjlWMTkuNjEwM0MxNzkuNTU1IDE5LjI5NyAxNzkuODQ2IDE5LjAzNzEgMTgwLjE5OCAxOS4wMzcxSDE4NC44MDVDMTg1LjE2NCAxOS4wMzcxIDE4NS40NTUgMTkuMjk3IDE4NS40NTUgMTkuNjEwM1Y1NS4wNTY5QzE4NS40NTUgNTUuMzcwMiAxODUuMTY0IDU1LjYzMDEgMTg0LjgxMiA1NS42MzAxSDE4MC4xOThDMTc5LjgzOCA1NS42MzAxIDE3OS41NTUgNTUuMzc3OSAxNzkuNTU1IDU1LjA1NjlaIiBmaWxsPSIjMTkyOTUyIi8+CjxwYXRoIGQ9Ik0xOTIuMzA1IDU1LjA0OTJWMTkuNjE4QzE5Mi4zMDUgMTkuMjk3IDE5Mi41OTUgMTkuMDM3MSAxOTIuOTYzIDE5LjAzNzFIMTk3LjU1NEMxOTcuOTE0IDE5LjAzNzEgMTk4LjIxMyAxOS4yOTcgMTk4LjIxMyAxOS42MThWNTUuMDQ5MkMxOTguMjEzIDU1LjM3MDIgMTk3LjkyMiA1NS42MzAxIDE5Ny41NTQgNTUuNjMwMUgxOTIuOTYzQzE5Mi42MDMgNTUuNjMwMSAxOTIuMzA1IDU1LjM3MDIgMTkyLjMwNSA1NS4wNDkyWiIgZmlsbD0iIzE5Mjk1MiIvPgo8cGF0aCBkPSJNMjE2LjcwOSA1Ni4wNzMzQzIxNC4yOTkgNTYuMDczMyAyMTIuMjg2IDU1LjkxMjkgMjEwLjY5NCA1NS41OTk1QzIwOS4wOTUgNTUuMjg2MiAyMDcuODE3IDU0Ljc2NjUgMjA2Ljg1MyA1NC4wNDA0QzIwNS44ODggNTMuMzE0NCAyMDUuMTYxIDUyLjM4OTYgMjA0LjY3OSA1MS4yNTg1QzIwNC4xOTcgNTAuMTI3NCAyMDMuODgzIDQ4Ljc1MTcgMjAzLjczIDQ3LjEzOTFDMjAzLjU4NSA0NS41MjY1IDIwMy41MDggNDMuNjQ2NCAyMDMuNTA4IDQxLjQ5MTJDMjAzLjUwOCAzOC45MzA5IDIwMy42MzggMzYuNzI5OCAyMDMuODk5IDM0Ljg3MjdDMjA0LjE1OSAzMy4wMTU1IDIwNC42OTQgMzEuNDg3IDIwNS41MTMgMzAuMjc5NEMyMDYuMzMyIDI5LjA3MTkgMjA3LjYwMyAyOC4xOTMgMjA5LjMzMiAyNy42MzUxQzIxMS4wNjIgMjcuMDc3MiAyMTMuMzczIDI2LjgwMiAyMTYuMjY2IDI2LjgwMkMyMTguNTMxIDI2LjgwMiAyMjAuMzkgMjYuOTc3OCAyMjEuODM3IDI3LjMyOTRDMjIzLjI4MyAyNy42ODA5IDIyNC40MjMgMjguMjMxMiAyMjUuMjY1IDI4Ljk3MjVDMjI2LjEwNyAyOS43MTM5IDIyNi43MTIgMzAuNjY5MiAyMjcuMTAyIDMxLjgzODVDMjI3LjQ5MiAzMy4wMDc5IDIyNy43NDUgMzQuMzk4OCAyMjcuODUyIDM2LjAxMTRDMjI3Ljk2NyAzNy42MjQgMjI4LjAyIDM5LjQ1MDYgMjI4LjAyIDQxLjQ5MTJWNDIuNzIxN0MyMjguMDIgNDMuMDg4NSAyMjcuNzIyIDQzLjM3ODkgMjI3LjM2MiA0My4zNzg5SDIwOS40NzdDMjA5LjQ3NyA0NS4wNDUgMjA5LjU1NCA0Ni4zOTAxIDIwOS42OTkgNDcuNDE0MkMyMDkuODQ1IDQ4LjQzMDcgMjEwLjE4OSA0OS4yMTAzIDIxMC43MzMgNDkuNzUyOUMyMTEuMjY4IDUwLjI4NzkgMjEyLjEyNSA1MC42NjI0IDIxMy4yOTYgNTAuODY4N0MyMTQuNDY3IDUxLjA3NTEgMjE2LjA1MSA1MS4xNzQ0IDIxOC4wNTYgNTEuMTc0NEMyMTguOTA2IDUxLjE3NDQgMjE5Ljg0NyA1MS4xNTkxIDIyMC44NzMgNTEuMTIwOUMyMjEuODkgNTEuMDgyNyAyMjIuOTM5IDUxLjAwNjMgMjI0LjAxOCA1MC44OTkzQzIyNC43OTggNTAuODE1MiAyMjUuNTI1IDUwLjc0NjQgMjI2LjE5MSA1MC42ODUzQzIyNi41ODIgNTAuNjQ3MSAyMjYuOTExIDUwLjk1MjggMjI2LjkxMSA1MS4zNDI2VjU0LjY4MjRDMjI2LjkxMSA1NS4wMTEgMjI2LjY3MyA1NS4yODYyIDIyNi4zNTIgNTUuMzMyQzIyNS42NTYgNTUuNDQ2NyAyMjQuODYgNTUuNTUzNiAyMjMuOTU3IDU1LjY1M0MyMjIuODA5IDU1Ljc4MjkgMjIxLjYgNTUuODgyMyAyMjAuMzM3IDU1Ljk1ODdDMjE5LjA3NCA1Ni4wMzUxIDIxNy44NjUgNTYuMDczMyAyMTYuNzE3IDU2LjA3MzNIMjE2LjcwOVpNMjIyLjMzNCAzOS4zMzZWMzkuMTY3OEMyMjIuMzM0IDM3LjUwMTcgMjIyLjIzNSAzNi4xNzE5IDIyMi4wMjggMzUuMTkzN0MyMjEuODIxIDM0LjIwNzggMjIxLjQ5MiAzMy40NjY0IDIyMS4wMjYgMzIuOTY5NkMyMjAuNTU5IDMyLjQ2NTIgMjE5LjkzMSAzMi4xMzY2IDIxOS4xMzUgMzEuOTY4NUMyMTguMzM5IDMxLjgwMDMgMjE3LjM0NSAzMS43MTYzIDIxNi4xNTggMzEuNzE2M0MyMTQuNjc0IDMxLjcxNjMgMjEzLjQ5NSAzMS44MTU2IDIxMi42MjMgMzIuMDIyQzIxMS43NSAzMi4yMjgzIDIxMS4wOTIgMzIuNjAyOCAyMTAuNjQ4IDMzLjE2MDdDMjEwLjIwNCAzMy43MTg2IDIwOS44OTggMzQuNDkwNSAyMDkuNzMgMzUuNDY4OEMyMDkuNTYyIDM2LjQ1NDcgMjA5LjQ3NyAzNy43Mzg3IDIwOS40NzcgMzkuMzM2SDIyMi4zNDJIMjIyLjMzNFoiIGZpbGw9IiMxOTI5NTIiLz4KPHBhdGggZD0iTTI0Mi45NDMgMjYuNjk1VjE5LjYwMjdDMjQyLjk0MyAxOS4yODkzIDI0Mi42OTEgMTkuMDM3MSAyNDIuMzc3IDE5LjAzNzFIMjM3LjUzM0MyMzcuMjE5IDE5LjAzNzEgMjM2Ljk2NiAxOS4yODkzIDIzNi45NjYgMTkuNjAyN1YyNi42OTVDMjM2Ljk2NiAyNy4wMDg0IDIzNi43MTQgMjcuMjYwNiAyMzYuNCAyNy4yNjA2SDIzMS43ODVDMjMxLjQ3MiAyNy4yNjA2IDIzMS4yMTkgMjcuNTEyOCAyMzEuMjE5IDI3LjgyNjFWMzEuNjM5OEMyMzEuMjE5IDMxLjk1MzIgMjMxLjQ3MiAzMi4yMDU0IDIzMS43ODUgMzIuMjA1NEgyMzYuNEMyMzYuNzE0IDMyLjIwNTQgMjM2Ljk2NiAzMi40NTc2IDIzNi45NjYgMzIuNzcwOVY1NS4wNTY5QzIzNi45NjYgNTUuMzcwMiAyMzcuMjE5IDU1LjYyMjQgMjM3LjUzMyA1NS42MjI0SDI0Mi4zNzdDMjQyLjY5MSA1NS42MjI0IDI0Mi45NDMgNTUuMzcwMiAyNDIuOTQzIDU1LjA1NjlWMzIuNzcwOUMyNDIuOTQzIDMyLjQ1NzYgMjQzLjE5NiAzMi4yMDU0IDI0My41MSAzMi4yMDU0SDI1Ny4xNDdDMjU5LjEwNiAzMi4yMDU0IDI2MC42OTggMzAuNjIzNCAyNjAuNjk4IDI4LjY1OTJWMjcuODI2MUMyNjAuNjk4IDI3LjUxMjggMjYwLjQ0NSAyNy4yNjA2IDI2MC4xMzIgMjcuMjYwNkgyNDMuNTFDMjQzLjE5NiAyNy4yNjA2IDI0Mi45NDMgMjcuMDA4NCAyNDIuOTQzIDI2LjY4NzRWMjYuNjk1WiIgZmlsbD0iIzE5Mjk1MiIvPgo8L2c+CjxkZWZzPgo8Y2xpcFBhdGggaWQ9ImNsaXAwXzc0MDgzXzEzODM5NyI+CjxyZWN0IHdpZHRoPSIyNzkiIGhlaWdodD0iODAuNTUxMiIgZmlsbD0id2hpdGUiLz4KPC9jbGlwUGF0aD4KPGNsaXBQYXRoIGlkPSJjbGlwMV83NDA4M18xMzgzOTciPgo8cmVjdCB3aWR0aD0iNzAuNDgxMiIgaGVpZ2h0PSI4MC41NSIgZmlsbD0id2hpdGUiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDE5IC0wLjMwNDY4OCkiLz4KPC9jbGlwUGF0aD4KPGNsaXBQYXRoIGlkPSJjbGlwMl83NDA4M18xMzgzOTciPgo8cmVjdCB3aWR0aD0iMTIxLjE0IiBoZWlnaHQ9Ijg2LjE0MzciIGZpbGw9IndoaXRlIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxOS4yOTMxIDEuMDM5MDYpIi8+CjwvY2xpcFBhdGg+CjwvZGVmcz4KPC9zdmc+Cg==", + "ColorScheme": { + "Primary": "#192952", + "Secondary": "#EFE0D5", + "Background": "#FFF8F5", + "OnPrimary": "#FFF8F5", + "OnSecondary": "#221A14" + }, + "AppleAppStore": { + "AppLink": "https://apps.apple.com/de/app/frosch/id6756783868" + }, + "GooglePlayStore": { + "AppLink": "https://play.google.com/store/apps/details?id=app.frosch.prod" + } + }, + { + "Id": "enmeshed", + "DisplayName": "enmeshed", + "Description": "Sie haben einen QR-Code der enmeshed-Plattform gescannt. Um fortfahren zu können, laden Sie die enmeshed-App auf Ihr Gerät.", + "ColorScheme": { + "Primary": "#192952", + "Secondary": "#EFE0D5", + "Background": "#FFF8F5", + "OnPrimary": "#FFF8F5", + "OnSecondary": "#221A14" + }, + "IconUrl": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAPAAAADwCAMAAAAJixmgAAAAA3NCSVQICAjb4U/gAAAATlBMVEX///8BNor49vUBAAAgICD+bQCVlZX/dgCampoXQo17fH0AH4Xm6OzS1d2/wceqrrj/x6n+18Jsf6s7XZz/nl+Jl7r/6dr6hiz/t4w6RV1ba3fKAAAFhklEQVR4nO2d65LaMAxGE283JJsbCQTY93/R2klgIYUQS526n6zzYzvT6XR8RrIsG5tNEkVRFEVRFEVRFEVRFEVRFOUppnKY0MP4J1R10+bZTN42srWrZnTNLeMP+4eVrqU61202az6S5Y1E5eqF7oQ4ZdOu2I5RrkMP8a9S5+u+TrkVFOQ34b1ShR7nX+JdOv8EWUZam/fpfBUWYbzdV0aMvXwlxHjr/L0pg1euxtPXAr06Vf6+eRt60Bz8dbELFyGhHbBJbWi+eRN64FSIAYYNMTXAsLO4pgrneeih0yDrgnYflDX4KgxZtsgly51/hB48hZbsi5nThuELWacZU9gdcIUevj+MRQlTmFGzHKGH7w9POMPrLqMT5qxKmMLRRZhVpQGFo5vDzGUJT5jVeCCuw6zWEvGsltdLI26IOQFG3B6yqhZgkWZVLcTNUsI6xAPc/yecnIbMaEadBs1oek5D1mgHMcSwAabuiWEDTAwxZJd1hVSoMUv0hPFPatA1+Ip3UkMntOXr29MXt0KPfH18fPkZhx4xj6+PX798jDPogjX5+hij3xGffK3x97bKlYE/fLj62hBXW67UwtfnH99kQweStbgN5cij7/iKZ00X/lHL0jdZe7gk4KXWE9/ETC/xlrJZJuAt3jPfEWOdb08tp+eWNfjcdbz0dRhT1U3TtK39Uct4W7rqKxBpvubUdfvLZd91p6f5KMrXdMfz7vPG7nzpltKSfLujk3zA/sWxu/83cnzNfre0vTrv9rcwy/G1us9sZ+fdfvpXYnxPxxXdUfl4Sh58sdfX/fNkXgTZSImveRfeWfksxfe8yddVLxm+a9VqqSzC14dPeN9kaz5fjdF9t9WrO87o65Gn7+5zH3rMHE6+us74FHrUDLwT2gkfQ4+aTkfwRU5qvxXpjtADp+JfscBDfKZGGDTEtBk8hrh7/7//h1BK9AxkoSaXLAdiu0XPaNCcvnCEL6FHT4CuazmHHj0BljDgJD4xMtqCt4PgCQNWLU6RhhSmNtKzMF47rcIqLEw4uqIV3bLEFMZrPKJrLePbPES3PYzuACC6Ix7GIR7opy3RHdNGdxAf30ct0X2YFt3HpfF9IB7flYfoLrX4J/Un+LWl+C6meV21FHH1MDl5xFjC5VKP68M7GdeH47sgnkT3BCCJ75FHEt0znmTlodZO5kMtR1xP8UYie2w5EdVz2k1EbQy/Om1j1dhUdTsMfd8Pg5xfqP36ay2a4ZCWZTpTpkWP/pU0Iy+6zLq3imnxgLU+gH+r1MgT4+ZQLmSvzmU64Id5aVy/0p2dwb8LL1kYm2FN11Ee0L9v6d7YhnddV0aQb8Z/VKoXQe7Ri9ds/L3FdgzyAb12jcabfYUYe/ha4wI+q99Xq0WMQ4+YSb2pXN0bD6GHzMIcfIWLEvrrLQdvXzuNgQtX7TmDJ2PgpPZPaEcJ22SSAmxD3IceOBVagHFDTAwwboh7YoBtiCELtSH7Fpg7RXJGozaY9IwGzWlqjR6FAet0xfCF7LYYUxhzErecCBdp6OH7Q9go3QvjnXxwijRkmVZhP2G8dUmF/YTxUppZpaMTxluWmtg6LV5rCXjmwdo8QJ4AsPbDeKsSb/dQhh48Bc4RD+B22MIIMGJG25wmn0sDLkoOcp2GrNEOarMF2GZNEEMMG2AbYtosRg1wkpiCEGPoOw+EtRixjb7DO6nh76b5dtSgPccPld9HTNATeKLadpV29sVdkX7wMBbha403Lk6pgHyeMP2WWp0W6PXqjuZtWqdlD74ePVL16688ykJKOt9Ye8dTpgNu//yapn/62sM9TROVzXfU7aF8kHbPD3v8XyG+RtUMVnqm6AX8wvQtVFVd15WUt7SKoiiKoiiKoiiKoiiKoijb+A3hKz2nnuI0BgAAAABJRU5ErkJggg==", + "BannerUrl": "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjU1IiBoZWlnaHQ9Ijc0IiB2aWV3Qm94PSIwIDAgMjU1IDc0IiBmaWxsPSJub25lIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPgo8cGF0aCBkPSJNNzIuNDIyNyAzOS4yNjY4SDU3LjM0MzFDNTcuNzQzNyA0Mi4zNDg4IDU5LjM3NyA0My41OTg0IDYxLjk4ODIgNDMuNTk4NEM2NC4xOTg5IDQzLjU5ODQgNjUuNDgzNyA0Mi42NTg2IDY2LjE0NDMgNDEuMDUyTDcyLjE1NzUgNDMuMDYyOUM3MC44NzI2IDQ2LjkwMSA2Ni42MjgxIDQ4Ljk1MzkgNjEuOTg4MiA0OC45NTM5QzU0LjY0ODcgNDguOTUzOSA1MC4wNTA0IDQ0LjcxMTUgNTAuMDUwNCAzNy4zNTA0QzUwLjA1MDQgMjkuOTg5MiA1NC43ODM5IDI1Ljc0NjkgNjEuNjM0NSAyNS43NDY5QzY4LjQ4NTEgMjUuNzQ2OSA3Mi41OTk2IDMwLjE2NzggNzIuNTk5NiAzNi4zMjY1QzcyLjU5OTYgMzcuNDQ0OSA3Mi41MTEyIDM4LjU1OCA3Mi40MjI3IDM5LjI3MjFWMzkuMjY2OFpNNTcuMzkgMzUuMjAyOUg2NS40MzY5QzY1LjE3MTYgMzIuNTI1MiA2My45MzM2IDMxLjA0OTggNjEuNjM0NSAzMS4wNDk4QzU5LjMzNTQgMzEuMDQ5OCA1Ny44MzIxIDMyLjM0NjcgNTcuMzkgMzUuMjAyOVoiIGZpbGw9IiMyMTIxMjEiLz4KPHBhdGggZD0iTTk2Ljc0MDUgMzMuNjQzNlY0OC41MDc2SDg5LjIyNDFWMzUuNjU0NUM4OS4yMjQxIDMyLjU3MjUgODcuOTM5MyAzMS41NDg2IDg2LjA4MjMgMzEuNTQ4NkM4My45MTMyIDMxLjU0ODYgODIuMTAzIDMyLjk3NjcgODIuMTAzIDM2LjY4MzZWNDguNTEyOUg3NC41ODY2VjI2LjE5ODRIODEuMzA3Mkw4MS41MjU2IDMwLjcwODVDODIuODUyMSAyNy40NDggODUuNTUxNyAyNS43NTIxIDg5LjA4ODggMjUuNzUyMUM5My42NDU1IDI1Ljc1MjEgOTYuNzQwNSAyOC40NzcxIDk2Ljc0MDUgMzMuNjU0MVYzMy42NDM2WiIgZmlsbD0iIzIxMjEyMSIvPgo8cGF0aCBkPSJNOTkuNzkzOSAyNi4xODc5SDEwNi41MTRMMTA2LjczMyAzMC41MTk1QzEwOC4xNDggMjcuMzk1NSAxMTAuODAxIDI1Ljc0MTYgMTE0LjE2MSAyNS43NDE2QzExNy41MjEgMjUuNzQxNiAxMTkuOTk3IDI3LjI1OSAxMjEuMTQ3IDMwLjE2MjVDMTIyLjUyIDI3LjI1OSAxMjUuMzkxIDI1Ljc0MTYgMTI4LjU3NSAyNS43NDE2QzEzMi45MDggMjUuNzQxNiAxMzYuMTc5IDI4LjQxOTMgMTM2LjEzOCAzMy42NDM2TDEzNi4wNDkgNDguNTA3NkgxMjguNjIxVjM1LjM4NjdDMTI4LjYyMSAzMi41Nzc3IDEyNy40MjUgMzEuNTQ4NiAxMjUuNjE1IDMxLjU0ODZDMTIzLjM2MyAzMS41NDg2IDEyMS43MjQgMzMuMjQ0NSAxMjEuNzI0IDM2LjU5NDNWNDguNTEyOUgxMTQuMjA4VjM1LjM5MkMxMTQuMjA4IDMyLjU4MyAxMTIuOTcgMzEuNTUzOSAxMTEuMjAxIDMxLjU1MzlDMTA5LjEyIDMxLjU1MzkgMTA3LjMxIDMzLjA3MTMgMTA3LjMxIDM2LjczMDhWNDguNTEyOUg5OS43OTM5VjI2LjE4NzlaIiBmaWxsPSIjMjEyMTIxIi8+CjxwYXRoIGQ9Ik0xNjAuNDA5IDM5LjI2NjhIMTQ1LjMyOUMxNDUuNzI0IDQyLjM0ODggMTQ3LjM2MyA0My41OTg0IDE0OS45NzQgNDMuNTk4NEMxNTIuMTg1IDQzLjU5ODQgMTUzLjQ2NSA0Mi42NTg2IDE1NC4xMyA0MS4wNTJMMTYwLjE0MyA0My4wNjI5QzE1OC44NjQgNDYuOTAxIDE1NC42MTQgNDguOTUzOSAxNDkuOTc0IDQ4Ljk1MzlDMTQyLjYzNSA0OC45NTM5IDEzOC4wMzYgNDQuNzExNSAxMzguMDM2IDM3LjM1MDRDMTM4LjAzNiAyOS45ODkyIDE0Mi43NyAyNS43NDY5IDE0OS42MjEgMjUuNzQ2OUMxNTYuNDcxIDI1Ljc0NjkgMTYwLjU4NiAzMC4xNjc4IDE2MC41ODYgMzYuMzI2NUMxNjAuNTg2IDM3LjQ0NDkgMTYwLjQ5NyAzOC41NTggMTYwLjQwOSAzOS4yNzIxVjM5LjI2NjhaTTE0NS4zNzYgMzUuMjAyOUgxNTMuNDIzQzE1My4xNTggMzIuNTI1MiAxNTEuOTIgMzEuMDQ5OCAxNDkuNjIxIDMxLjA0OThDMTQ3LjMyMSAzMS4wNDk4IDE0NS44MTggMzIuMzQ2NyAxNDUuMzc2IDM1LjIwMjlaIiBmaWxsPSIjMjEyMTIxIi8+CjxwYXRoIGQ9Ik0xNjAuOTgxIDQ0LjcxMTVMMTY0LjUxOCA0MC41MTY0QzE2NS45NzUgNDIuNDM4MSAxNjguNTQ0IDQzLjg2NjIgMTcxLjU1MSA0My44NjYyQzE3My4zNjYgNDMuODY2MiAxNzQuNjkyIDQzLjMzMDcgMTc0LjY5MiA0Mi4yMTIzQzE3NC42OTIgNDEuNDA5IDE3NC4yNSA0MC45MTU1IDE3Mi40ODIgNDAuNTU4NEwxNjkuMzg3IDM5LjkzMzZDMTYzLjgxNiAzOC43NzMzIDE2MS43MzUgMzYuNjMxMSAxNjEuNzM1IDMzLjAxMzVDMTYxLjczNSAyOS4zOTU5IDE2NS4wMDcgMjUuNzM2NCAxNzIuMTI4IDI1LjczNjRDMTc2LjYzOCAyNS43MzY0IDE4MC4wODcgMjcuMTIyNSAxODIuMTIgMjkuNTc0NEwxNzguNTM3IDMzLjY4MDNDMTc3LjEyMiAzMS44OTUyIDE3NC42NDYgMzAuODI0MSAxNzIuNDM1IDMwLjgyNDFDMTcwLjIyNCAzMC44MjQxIDE2OS4yMDUgMzEuNDQ4OSAxNjkuMjA1IDMyLjQ3OEMxNjkuMjA1IDMzLjI4MTMgMTY5LjgyNCAzMy44MTY4IDE3MS44MTYgMzQuMjIxMUwxNzUuODQyIDM1LjAyNDRDMTgwLjM5OSAzNS44Njk4IDE4Mi4yNTYgMzguMTQ4NSAxODIuMjU2IDQxLjI3MjVDMTgyLjI1NiA0NS42MDQxIDE3OC44MDcgNDguOTQ4NyAxNzEuODYzIDQ4Ljk0ODdDMTY3LjQ0MSA0OC45NDg3IDE2My41MDQgNDcuNDczMyAxNjAuOTg2IDQ0LjcwNjNMMTYwLjk4MSA0NC43MTE1WiIgZmlsbD0iIzIxMjEyMSIvPgo8cGF0aCBkPSJNMTgzLjkzMSAxNi43MjY2SDE5MS40NDdWMzAuMjUxOEMxOTIuNzczIDI3LjI1OSAxOTUuMjQ5IDI1Ljc0MTYgMTk4LjQzMyAyNS43NDE2QzIwMi45OSAyNS43NDE2IDIwNi4wODQgMjguNDY2NiAyMDYuMDg0IDMzLjY0MzZWNDguNTA3NkgxOTguNTY4VjM1Ljc0MzdDMTk4LjU2OCAzMi41NzI1IDE5Ny4yODggMzEuNTAxNCAxOTUuNDI2IDMxLjUwMTRDMTkzLjI1NyAzMS41MDE0IDE5MS40NDcgMzMuMDE4OCAxOTEuNDQ3IDM2Ljc2NzZWNDguNTA3NkgxODMuOTMxVjE2LjcyNjZaIiBmaWxsPSIjMjEyMTIxIi8+CjxwYXRoIGQ9Ik0yMzAuMzU1IDM5LjI2NjhIMjE1LjI3NkMyMTUuNjc2IDQyLjM0ODggMjE3LjMxIDQzLjU5ODQgMjE5LjkyMSA0My41OTg0QzIyMi4xMzIgNDMuNTk4NCAyMjMuNDE2IDQyLjY1ODYgMjI0LjA3NyA0MS4wNTJMMjMwLjA5IDQzLjA2MjlDMjI4LjgxMSA0Ni45MDEgMjI0LjU2MSA0OC45NTM5IDIxOS45MjEgNDguOTUzOUMyMTIuNTgxIDQ4Ljk1MzkgMjA3Ljk4MyA0NC43MTE1IDIwNy45ODMgMzcuMzUwNEMyMDcuOTgzIDI5Ljk4OTIgMjEyLjcxNyAyNS43NDY5IDIxOS41NjcgMjUuNzQ2OUMyMjYuNDE4IDI1Ljc0NjkgMjMwLjUzMiAzMC4xNjc4IDIzMC41MzIgMzYuMzI2NUMyMzAuNTMyIDM3LjQ0NDkgMjMwLjQ0NCAzOC41NTggMjMwLjM1NSAzOS4yNzIxVjM5LjI2NjhaTTIxNS4zMjMgMzUuMjAyOUgyMjMuMzdDMjIzLjEwNCAzMi41MjUyIDIyMS44NjYgMzEuMDQ5OCAyMTkuNTY3IDMxLjA0OThDMjE3LjI2OCAzMS4wNDk4IDIxNS43NjUgMzIuMzQ2NyAyMTUuMzIzIDM1LjIwMjlaIiBmaWxsPSIjMjEyMTIxIi8+CjxwYXRoIGQ9Ik0yNTQuODUgMTYuNzI2NlY0OC41MDI0SDI0OC4xMjlMMjQ3Ljg2NCA0NC4xMjg3QzI0Ni42MjYgNDcuMTIxNSAyNDQuMDE1IDQ4Ljk0ODcgMjQwLjY1NSA0OC45NDg3QzIzNS4xNzIgNDguOTQ4NyAyMzEuNTQ3IDQ0LjcwNjMgMjMxLjU0NyAzNy40MzQ0QzIzMS41NDcgMzAuMTYyNSAyMzUuMzQ5IDI1Ljc0MTYgMjQwLjgzMiAyNS43NDE2QzI0My45NzMgMjUuNzQxNiAyNDYuMTg0IDI3LjQzNzUgMjQ3LjMzNCAyOS45ODRWMTYuNzI2NkgyNTQuODVaTTI0Ny4zMzQgMzcuMjEzOUMyNDcuMzM0IDMzLjQ2NSAyNDUuODMgMzEuMzIyOSAyNDMuMzA4IDMxLjMyMjlDMjQwLjc4NSAzMS4zMjI5IDIzOS4xMDUgMzMuMTk3MyAyMzkuMTA1IDM3LjM1MDRDMjM5LjEwNSA0MS41MDM1IDI0MC42NSA0My4zNzc5IDI0My4yNjEgNDMuMzc3OUMyNDUuODcyIDQzLjM3NzkgMjQ3LjMyOCA0MS4yMzU3IDI0Ny4zMjggMzcuMjE5MUwyNDcuMzM0IDM3LjIxMzlaIiBmaWxsPSIjMjEyMTIxIi8+CjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNMzcuOTc0NCAxMS4xMzA2QzM4LjQ4MTkgMTEuNjM4MSAzOC40ODE5IDEyLjQ2MDkgMzcuOTc0NCAxMi45Njg0TDEzLjk0MzEgMzYuOTk5N0wzNy45NzQ0IDYxLjAzMUMzOC40ODE5IDYxLjUzODUgMzguNDgxOSA2Mi4zNjEzIDM3Ljk3NDQgNjIuODY4OEMzNy40NjY5IDYzLjM3NjMgMzYuNjQ0MSA2My4zNzYzIDM2LjEzNjcgNjIuODY4OEwxMC4yNjc2IDM2Ljk5OTdMMzYuMTM2NyAxMS4xMzA2QzM2LjY0NDEgMTAuNjIzMSAzNy40NjY5IDEwLjYyMzEgMzcuOTc0NCAxMS4xMzA2WiIgZmlsbD0iIzIxMjEyMSIvPgo8Y2lyY2xlIGN4PSIzNy4wNTU1IiBjeT0iMTIuMDQ5MSIgcj0iMTEuOTU1MyIgZmlsbD0iIzlBOUE5QSIvPgo8Y2lyY2xlIGN4PSIzNy4wNTU1IiBjeT0iNjEuOTQ5NCIgcj0iMTEuOTU1MyIgZmlsbD0iIzE3NDI4RCIvPgo8Y2lyY2xlIGN4PSIxMi4xMDUzIiBjeT0iMzYuOTk4MyIgcj0iMTEuOTU1MyIgZmlsbD0iI0ZGNzYwMCIvPgo8L3N2Zz4K", + "AppleAppStore": { + "AppLink": "https://apps.apple.com/us/app/enmeshed/id1576693742" + }, + "GooglePlayStore": { + "AppLink": "https://play.google.com/store/apps/details?id=eu.enmeshed.app" + } + } ] - } - ] - } + }, + "WellKnownEndpoints": { + "AppleAppSiteAssociations": ["R7Y6NESEQW.eu.enmeshed.app"], + "AndroidAssetLinks": [ + { + "PackageName": "eu.enmeshed.app", + "Sha256CertFingerprints": ["0F:6F:48:FF:59:E7:B4:EC:52:4A:BB:E7:45:41:E7:38:5B:13:D1:0B:14:37:CF:C3:59:08:DF:22:F3:CA:70:38"] + } + ] + } } diff --git a/docker-compose/docker-compose.yml b/docker-compose/docker-compose.yml index 68ce63dc24..745a774c55 100644 --- a/docker-compose/docker-compose.yml +++ b/docker-compose/docker-compose.yml @@ -58,6 +58,78 @@ services: - SEQ_FIRSTRUN_NOAUTHENTICATION=True restart: unless-stopped + prometheus: + image: prom/prometheus:v3.14.0 + container_name: prometheus + command: + - --config.file=/etc/prometheus/prometheus.yml + - --storage.tsdb.path=/prometheus + - --web.enable-remote-write-receiver + ports: + - "9090:9090" + volumes: + - ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml:ro + - prometheus-data:/prometheus + restart: unless-stopped + + tempo: + image: grafana/tempo:3.0.3 + container_name: tempo + user: "0:0" + command: + - -config.file=/etc/tempo/tempo.yml + volumes: + - ./tempo/tempo.yml:/etc/tempo/tempo.yml:ro + - tempo-data:/tmp/tempo + restart: unless-stopped + + loki: + image: grafana/loki:3.7.6 + container_name: loki + command: + - -config.file=/etc/loki/loki.yml + ports: + - "3100:3100" + volumes: + - ./loki/loki.yml:/etc/loki/loki.yml:ro + - loki-data:/loki + restart: unless-stopped + + grafana: + image: grafana/grafana:13.2.1 + container_name: grafana + environment: + - GF_SECURITY_ADMIN_USER=admin + - GF_SECURITY_ADMIN_PASSWORD=admin + ports: + - "3000:3000" + depends_on: + - prometheus + - tempo + - loki + volumes: + - ./grafana/provisioning:/etc/grafana/provisioning:ro + - grafana-data:/var/lib/grafana + restart: unless-stopped + + otel-collector: + image: otel/opentelemetry-collector:0.159.0 + volumes: + - ./otel-collector/otel-collector-config.yml:/etc/otel/config.yaml + # - ./log:/log/otel + command: --config /etc/otel/config.yaml + environment: + TEMPO_ENDPOINT: "tempo:4317" + ports: + - "8889:8889" # Prometheus metrics exporter (scrape endpoint) + - "55679:55679" # ZPages extension + - "4317:4317" # OTLP Receiver + - "4318:4318" # OTLP HTTP Receiver + depends_on: + - tempo + - prometheus + - loki + networks: default: name: backbone @@ -68,3 +140,7 @@ volumes: postgres-volume: azure-storage-emulator-volume: seq-data: + prometheus-data: + tempo-data: + loki-data: + grafana-data: diff --git a/docker-compose/grafana/provisioning/datasources/datasources.yml b/docker-compose/grafana/provisioning/datasources/datasources.yml new file mode 100644 index 0000000000..3e32a7453f --- /dev/null +++ b/docker-compose/grafana/provisioning/datasources/datasources.yml @@ -0,0 +1,32 @@ +apiVersion: 1 + +datasources: + - name: Prometheus + uid: prometheus + type: prometheus + access: proxy + url: http://prometheus:9090 + isDefault: true + editable: false + + - name: Tempo + uid: tempo + type: tempo + access: proxy + url: http://tempo:3200 + editable: false + jsonData: + httpMethod: GET + serviceMap: + datasourceUid: prometheus + nodeGraph: + enabled: true + tracesToMetrics: + datasourceUid: prometheus + + - name: Loki + uid: loki + type: loki + access: proxy + url: http://loki:3100 + editable: false diff --git a/docker-compose/loki/loki.yml b/docker-compose/loki/loki.yml new file mode 100644 index 0000000000..2ab43f81bc --- /dev/null +++ b/docker-compose/loki/loki.yml @@ -0,0 +1,41 @@ +auth_enabled: false + +server: + http_listen_port: 3100 + +common: + path_prefix: /loki + replication_factor: 1 + ring: + kvstore: + store: inmemory + storage: + filesystem: + chunks_directory: /loki/chunks + rules_directory: /loki/rules + +schema_config: + configs: + - from: 2024-04-01 + store: tsdb + object_store: filesystem + schema: v13 + index: + prefix: index_ + period: 24h + +limits_config: + allow_structured_metadata: true + volume_enabled: true + otlp_config: + resource_attributes: + ignore_defaults: true + attributes_config: + - action: index_label + attributes: + - service.name + - deployment.environment.name + +compactor: + working_directory: /loki/compactor + delete_request_store: filesystem diff --git a/docker-compose/otel-collector/otel-collector-config.yml b/docker-compose/otel-collector/otel-collector-config.yml new file mode 100644 index 0000000000..0b06ba2b48 --- /dev/null +++ b/docker-compose/otel-collector/otel-collector-config.yml @@ -0,0 +1,65 @@ +extensions: + health_check: + zpages: + endpoint: :55679 + +receivers: + otlp: + protocols: + grpc: + endpoint: 0.0.0.0:4317 + http: + endpoint: 0.0.0.0:4318 + +processors: + memory_limiter: + check_interval: 1s + limit_percentage: 50 + spike_limit_percentage: 30 + + batch: + +exporters: + debug: + otlp/tempo: + endpoint: "${TEMPO_ENDPOINT}" + tls: + insecure: true + prometheus: + endpoint: "0.0.0.0:8889" + otlp_http/loki: + endpoint: "http://loki:3100/otlp" + +service: + pipelines: + traces: + receivers: + - otlp + processors: + - memory_limiter + - batch + exporters: + - debug + - otlp/tempo + metrics: + receivers: + - otlp + processors: + - memory_limiter + - batch + exporters: + - debug + - prometheus + logs: + receivers: + - otlp + processors: + - memory_limiter + - batch + exporters: + - debug + - otlp_http/loki + + extensions: + - health_check + - zpages diff --git a/docker-compose/prometheus/prometheus.yml b/docker-compose/prometheus/prometheus.yml new file mode 100644 index 0000000000..0d1851622b --- /dev/null +++ b/docker-compose/prometheus/prometheus.yml @@ -0,0 +1,9 @@ +global: + scrape_interval: 15s + evaluation_interval: 15s + +scrape_configs: + - job_name: otel-collector + static_configs: + - targets: + - otel-collector:8889 diff --git a/docker-compose/tempo/tempo.yml b/docker-compose/tempo/tempo.yml new file mode 100644 index 0000000000..1dcffc3f38 --- /dev/null +++ b/docker-compose/tempo/tempo.yml @@ -0,0 +1,40 @@ +auth_enabled: false + +server: + http_listen_port: 3200 + +distributor: + receivers: + otlp: + protocols: + grpc: + endpoint: 0.0.0.0:4317 + http: + endpoint: 0.0.0.0:4318 + +metrics_generator: + registry: + collection_interval: 15s + storage: + path: /tmp/tempo/generator/wal + remote_write: + - url: http://prometheus:9090/api/v1/write + +storage: + trace: + backend: local + wal: + path: /tmp/tempo/wal + local: + path: /tmp/tempo/blocks + +overrides: + defaults: + metrics_generator: + processors: + - service-graphs + - span-metrics + +query_frontend: + metrics: + max_duration: 720h diff --git a/helm/templates/eventhandler/deployment.yaml b/helm/templates/eventhandler/deployment.yaml index d96128b9c6..2ded933456 100644 --- a/helm/templates/eventhandler/deployment.yaml +++ b/helm/templates/eventhandler/deployment.yaml @@ -50,10 +50,6 @@ spec: {{- toYaml .Values.eventhandler.resources | nindent 12 }} image: "{{ .Values.eventhandler.image.repository }}:{{- default .Chart.AppVersion .Values.eventhandler.image.tagOverride }}" imagePullPolicy: {{ .Values.eventhandler.image.pullPolicy }} - ports: - - name: metrics - containerPort: 9444 - protocol: TCP volumeMounts: - name: settings-override mountPath: /app/appsettings.override.json diff --git a/helm/templates/eventhandler/service.yaml b/helm/templates/eventhandler/service.yaml deleted file mode 100644 index 40ab66e16d..0000000000 --- a/helm/templates/eventhandler/service.yaml +++ /dev/null @@ -1,15 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: {{ .Values.eventhandler.name }} - labels: - {{- include "global.labels" . | nindent 4 }} - app: {{ .Values.eventhandler.name }} -spec: - type: ClusterIP - ports: - - name: metrics - port: 9444 - targetPort: 9444 - selector: - app: {{ .Values.eventhandler.name }}