From 753c10c492b0f51c6391c71e865a4d1131f40944 Mon Sep 17 00:00:00 2001 From: MSuMshk <2039814060@qq.com> Date: Tue, 2 Dec 2025 13:27:43 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E9=9B=86=E6=88=90OpenTelemetry?= =?UTF-8?q?=E5=9F=8B=E7=82=B9=E4=B8=8E=E6=97=A5=E5=BF=97=E8=BE=93=E5=87=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Api/TakeoutSaaS.AdminApi/Program.cs | 63 +++++++++++++++++- .../TakeoutSaaS.AdminApi.csproj | 7 ++ .../appsettings.Development.json | 33 ++++++++-- .../appsettings.Production.json | 33 ++++++++-- src/Api/TakeoutSaaS.MiniApi/Program.cs | 66 ++++++++++++++++++- .../TakeoutSaaS.MiniApi.csproj | 7 ++ .../appsettings.Development.json | 33 ++++++++-- .../appsettings.Production.json | 33 ++++++++-- src/Api/TakeoutSaaS.UserApi/Program.cs | 66 ++++++++++++++++++- .../TakeoutSaaS.UserApi.csproj | 7 ++ .../appsettings.Development.json | 11 +++- .../appsettings.Production.json | 11 +++- 12 files changed, 343 insertions(+), 27 deletions(-) diff --git a/src/Api/TakeoutSaaS.AdminApi/Program.cs b/src/Api/TakeoutSaaS.AdminApi/Program.cs index 1cdf937..e9619a0 100644 --- a/src/Api/TakeoutSaaS.AdminApi/Program.cs +++ b/src/Api/TakeoutSaaS.AdminApi/Program.cs @@ -5,6 +5,9 @@ using Microsoft.AspNetCore.Cors.Infrastructure; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; +using OpenTelemetry.Metrics; +using OpenTelemetry.Resources; +using OpenTelemetry.Trace; using Serilog; using TakeoutSaaS.Application.App.Extensions; using TakeoutSaaS.Application.Identity.Extensions; @@ -34,7 +37,12 @@ builder.Host.UseSerilog((context, _, configuration) => configuration .Enrich.FromLogContext() .Enrich.WithProperty("Service", "AdminApi") - .WriteTo.Console(); + .WriteTo.Console() + .WriteTo.File( + "logs/admin-api-.log", + rollingInterval: RollingInterval.Day, + retainedFileCountLimit: 7, + shared: true); }); builder.Services.AddSharedWebCore(); @@ -60,6 +68,59 @@ builder.Services.AddSmsApplication(builder.Configuration); builder.Services.AddMessagingModule(builder.Configuration); builder.Services.AddMessagingApplication(); builder.Services.AddSchedulerModule(builder.Configuration); +var otelSection = builder.Configuration.GetSection("Otel"); +var otelEndpoint = otelSection.GetValue("Endpoint"); +var useConsoleExporter = otelSection.GetValue("UseConsoleExporter") ?? builder.Environment.IsDevelopment(); +builder.Services.AddOpenTelemetry() + .ConfigureResource(resource => resource.AddService( + serviceName: "TakeoutSaaS.AdminApi", + serviceVersion: "1.0.0", + serviceInstanceId: Environment.MachineName)) + .WithTracing(tracing => + { + tracing + .SetSampler(new ParentBasedSampler(new AlwaysOnSampler())) + .AddAspNetCoreInstrumentation() + .AddHttpClientInstrumentation() + .AddEntityFrameworkCoreInstrumentation(options => + { + options.SetDbStatementForText = false; + options.SetDbStatementForStoredProcedure = false; + }); + + if (!string.IsNullOrWhiteSpace(otelEndpoint)) + { + tracing.AddOtlpExporter(exporter => + { + exporter.Endpoint = new Uri(otelEndpoint); + }); + } + + if (useConsoleExporter) + { + tracing.AddConsoleExporter(); + } + }) + .WithMetrics(metrics => + { + metrics + .AddAspNetCoreInstrumentation() + .AddHttpClientInstrumentation() + .AddRuntimeInstrumentation(); + + if (!string.IsNullOrWhiteSpace(otelEndpoint)) + { + metrics.AddOtlpExporter(exporter => + { + exporter.Endpoint = new Uri(otelEndpoint); + }); + } + + if (useConsoleExporter) + { + metrics.AddConsoleExporter(); + } + }); var adminOrigins = ResolveCorsOrigins(builder.Configuration, "Cors:Admin"); builder.Services.AddCors(options => diff --git a/src/Api/TakeoutSaaS.AdminApi/TakeoutSaaS.AdminApi.csproj b/src/Api/TakeoutSaaS.AdminApi/TakeoutSaaS.AdminApi.csproj index c8258af..810c4b7 100644 --- a/src/Api/TakeoutSaaS.AdminApi/TakeoutSaaS.AdminApi.csproj +++ b/src/Api/TakeoutSaaS.AdminApi/TakeoutSaaS.AdminApi.csproj @@ -8,6 +8,13 @@ + + + + + + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Api/TakeoutSaaS.AdminApi/appsettings.Development.json b/src/Api/TakeoutSaaS.AdminApi/appsettings.Development.json index 4eb2c0e..1bc5044 100644 --- a/src/Api/TakeoutSaaS.AdminApi/appsettings.Development.json +++ b/src/Api/TakeoutSaaS.AdminApi/appsettings.Development.json @@ -60,7 +60,9 @@ "Tenancy": { "TenantIdHeaderName": "X-Tenant-Id", "TenantCodeHeaderName": "X-Tenant-Code", - "IgnoredPaths": [ "/health" ], + "IgnoredPaths": [ + "/health" + ], "RootDomain": "" }, "Storage": { @@ -95,11 +97,27 @@ }, "Security": { "MaxFileSizeBytes": 10485760, - "AllowedImageExtensions": [ ".jpg", ".jpeg", ".png", ".webp", ".gif" ], - "AllowedFileExtensions": [ ".jpg", ".jpeg", ".png", ".webp", ".gif", ".pdf" ], + "AllowedImageExtensions": [ + ".jpg", + ".jpeg", + ".png", + ".webp", + ".gif" + ], + "AllowedFileExtensions": [ + ".jpg", + ".jpeg", + ".png", + ".webp", + ".gif", + ".pdf" + ], "DefaultUrlExpirationMinutes": 30, "EnableRefererValidation": true, - "AllowedReferers": [ "https://admin.example.com", "https://miniapp.example.com" ], + "AllowedReferers": [ + "https://admin.example.com", + "https://miniapp.example.com" + ], "AntiLeechTokenSecret": "ReplaceWithARandomToken" } }, @@ -149,5 +167,10 @@ "WorkerCount": 5, "DashboardEnabled": false, "DashboardPath": "/hangfire" + }, + "Otel": { + "Endpoint": "", + "Sampling": "ParentBasedAlwaysOn", + "UseConsoleExporter": true } -} +} \ No newline at end of file diff --git a/src/Api/TakeoutSaaS.AdminApi/appsettings.Production.json b/src/Api/TakeoutSaaS.AdminApi/appsettings.Production.json index 4eb2c0e..1bc5044 100644 --- a/src/Api/TakeoutSaaS.AdminApi/appsettings.Production.json +++ b/src/Api/TakeoutSaaS.AdminApi/appsettings.Production.json @@ -60,7 +60,9 @@ "Tenancy": { "TenantIdHeaderName": "X-Tenant-Id", "TenantCodeHeaderName": "X-Tenant-Code", - "IgnoredPaths": [ "/health" ], + "IgnoredPaths": [ + "/health" + ], "RootDomain": "" }, "Storage": { @@ -95,11 +97,27 @@ }, "Security": { "MaxFileSizeBytes": 10485760, - "AllowedImageExtensions": [ ".jpg", ".jpeg", ".png", ".webp", ".gif" ], - "AllowedFileExtensions": [ ".jpg", ".jpeg", ".png", ".webp", ".gif", ".pdf" ], + "AllowedImageExtensions": [ + ".jpg", + ".jpeg", + ".png", + ".webp", + ".gif" + ], + "AllowedFileExtensions": [ + ".jpg", + ".jpeg", + ".png", + ".webp", + ".gif", + ".pdf" + ], "DefaultUrlExpirationMinutes": 30, "EnableRefererValidation": true, - "AllowedReferers": [ "https://admin.example.com", "https://miniapp.example.com" ], + "AllowedReferers": [ + "https://admin.example.com", + "https://miniapp.example.com" + ], "AntiLeechTokenSecret": "ReplaceWithARandomToken" } }, @@ -149,5 +167,10 @@ "WorkerCount": 5, "DashboardEnabled": false, "DashboardPath": "/hangfire" + }, + "Otel": { + "Endpoint": "", + "Sampling": "ParentBasedAlwaysOn", + "UseConsoleExporter": true } -} +} \ No newline at end of file diff --git a/src/Api/TakeoutSaaS.MiniApi/Program.cs b/src/Api/TakeoutSaaS.MiniApi/Program.cs index 5dd9962..2c44874 100644 --- a/src/Api/TakeoutSaaS.MiniApi/Program.cs +++ b/src/Api/TakeoutSaaS.MiniApi/Program.cs @@ -1,4 +1,10 @@ +using System; +using System.Linq; using Microsoft.AspNetCore.Cors.Infrastructure; +using Microsoft.Extensions.Configuration; +using OpenTelemetry.Metrics; +using OpenTelemetry.Resources; +using OpenTelemetry.Trace; using Serilog; using TakeoutSaaS.Application.Messaging.Extensions; using TakeoutSaaS.Application.Sms.Extensions; @@ -17,7 +23,12 @@ builder.Host.UseSerilog((_, _, configuration) => configuration .Enrich.FromLogContext() .Enrich.WithProperty("Service", "MiniApi") - .WriteTo.Console(); + .WriteTo.Console() + .WriteTo.File( + "logs/mini-api-.log", + rollingInterval: RollingInterval.Day, + retainedFileCountLimit: 7, + shared: true); }); builder.Services.AddSharedWebCore(); @@ -34,6 +45,59 @@ builder.Services.AddSmsModule(builder.Configuration); builder.Services.AddSmsApplication(builder.Configuration); builder.Services.AddMessagingModule(builder.Configuration); builder.Services.AddMessagingApplication(); +var otelSection = builder.Configuration.GetSection("Otel"); +var otelEndpoint = otelSection.GetValue("Endpoint"); +var useConsoleExporter = otelSection.GetValue("UseConsoleExporter") ?? builder.Environment.IsDevelopment(); +builder.Services.AddOpenTelemetry() + .ConfigureResource(resource => resource.AddService( + serviceName: "TakeoutSaaS.MiniApi", + serviceVersion: "1.0.0", + serviceInstanceId: Environment.MachineName)) + .WithTracing(tracing => + { + tracing + .SetSampler(new ParentBasedSampler(new AlwaysOnSampler())) + .AddAspNetCoreInstrumentation() + .AddHttpClientInstrumentation() + .AddEntityFrameworkCoreInstrumentation(options => + { + options.SetDbStatementForText = false; + options.SetDbStatementForStoredProcedure = false; + }); + + if (!string.IsNullOrWhiteSpace(otelEndpoint)) + { + tracing.AddOtlpExporter(exporter => + { + exporter.Endpoint = new Uri(otelEndpoint); + }); + } + + if (useConsoleExporter) + { + tracing.AddConsoleExporter(); + } + }) + .WithMetrics(metrics => + { + metrics + .AddAspNetCoreInstrumentation() + .AddHttpClientInstrumentation() + .AddRuntimeInstrumentation(); + + if (!string.IsNullOrWhiteSpace(otelEndpoint)) + { + metrics.AddOtlpExporter(exporter => + { + exporter.Endpoint = new Uri(otelEndpoint); + }); + } + + if (useConsoleExporter) + { + metrics.AddConsoleExporter(); + } + }); var miniOrigins = ResolveCorsOrigins(builder.Configuration, "Cors:Mini"); builder.Services.AddCors(options => diff --git a/src/Api/TakeoutSaaS.MiniApi/TakeoutSaaS.MiniApi.csproj b/src/Api/TakeoutSaaS.MiniApi/TakeoutSaaS.MiniApi.csproj index 2269e2e..a5ca222 100644 --- a/src/Api/TakeoutSaaS.MiniApi/TakeoutSaaS.MiniApi.csproj +++ b/src/Api/TakeoutSaaS.MiniApi/TakeoutSaaS.MiniApi.csproj @@ -9,6 +9,13 @@ + + + + + + + diff --git a/src/Api/TakeoutSaaS.MiniApi/appsettings.Development.json b/src/Api/TakeoutSaaS.MiniApi/appsettings.Development.json index 3b288cf..8eb84b7 100644 --- a/src/Api/TakeoutSaaS.MiniApi/appsettings.Development.json +++ b/src/Api/TakeoutSaaS.MiniApi/appsettings.Development.json @@ -55,7 +55,9 @@ "Tenancy": { "TenantIdHeaderName": "X-Tenant-Id", "TenantCodeHeaderName": "X-Tenant-Code", - "IgnoredPaths": [ "/health" ], + "IgnoredPaths": [ + "/health" + ], "RootDomain": "" }, "Storage": { @@ -90,11 +92,27 @@ }, "Security": { "MaxFileSizeBytes": 10485760, - "AllowedImageExtensions": [ ".jpg", ".jpeg", ".png", ".webp", ".gif" ], - "AllowedFileExtensions": [ ".jpg", ".jpeg", ".png", ".webp", ".gif", ".pdf" ], + "AllowedImageExtensions": [ + ".jpg", + ".jpeg", + ".png", + ".webp", + ".gif" + ], + "AllowedFileExtensions": [ + ".jpg", + ".jpeg", + ".png", + ".webp", + ".gif", + ".pdf" + ], "DefaultUrlExpirationMinutes": 30, "EnableRefererValidation": true, - "AllowedReferers": [ "https://admin.example.com", "https://miniapp.example.com" ], + "AllowedReferers": [ + "https://admin.example.com", + "https://miniapp.example.com" + ], "AntiLeechTokenSecret": "ReplaceWithARandomToken" } }, @@ -138,5 +156,10 @@ "Exchange": "takeout.events", "ExchangeType": "topic", "PrefetchCount": 20 + }, + "Otel": { + "Endpoint": "", + "Sampling": "ParentBasedAlwaysOn", + "UseConsoleExporter": true } -} +} \ No newline at end of file diff --git a/src/Api/TakeoutSaaS.MiniApi/appsettings.Production.json b/src/Api/TakeoutSaaS.MiniApi/appsettings.Production.json index 3b288cf..8eb84b7 100644 --- a/src/Api/TakeoutSaaS.MiniApi/appsettings.Production.json +++ b/src/Api/TakeoutSaaS.MiniApi/appsettings.Production.json @@ -55,7 +55,9 @@ "Tenancy": { "TenantIdHeaderName": "X-Tenant-Id", "TenantCodeHeaderName": "X-Tenant-Code", - "IgnoredPaths": [ "/health" ], + "IgnoredPaths": [ + "/health" + ], "RootDomain": "" }, "Storage": { @@ -90,11 +92,27 @@ }, "Security": { "MaxFileSizeBytes": 10485760, - "AllowedImageExtensions": [ ".jpg", ".jpeg", ".png", ".webp", ".gif" ], - "AllowedFileExtensions": [ ".jpg", ".jpeg", ".png", ".webp", ".gif", ".pdf" ], + "AllowedImageExtensions": [ + ".jpg", + ".jpeg", + ".png", + ".webp", + ".gif" + ], + "AllowedFileExtensions": [ + ".jpg", + ".jpeg", + ".png", + ".webp", + ".gif", + ".pdf" + ], "DefaultUrlExpirationMinutes": 30, "EnableRefererValidation": true, - "AllowedReferers": [ "https://admin.example.com", "https://miniapp.example.com" ], + "AllowedReferers": [ + "https://admin.example.com", + "https://miniapp.example.com" + ], "AntiLeechTokenSecret": "ReplaceWithARandomToken" } }, @@ -138,5 +156,10 @@ "Exchange": "takeout.events", "ExchangeType": "topic", "PrefetchCount": 20 + }, + "Otel": { + "Endpoint": "", + "Sampling": "ParentBasedAlwaysOn", + "UseConsoleExporter": true } -} +} \ No newline at end of file diff --git a/src/Api/TakeoutSaaS.UserApi/Program.cs b/src/Api/TakeoutSaaS.UserApi/Program.cs index ddfa3af..e8d458b 100644 --- a/src/Api/TakeoutSaaS.UserApi/Program.cs +++ b/src/Api/TakeoutSaaS.UserApi/Program.cs @@ -1,4 +1,10 @@ +using System; +using System.Linq; using Microsoft.AspNetCore.Cors.Infrastructure; +using Microsoft.Extensions.Configuration; +using OpenTelemetry.Metrics; +using OpenTelemetry.Resources; +using OpenTelemetry.Trace; using Serilog; using TakeoutSaaS.Module.Tenancy.Extensions; using TakeoutSaaS.Shared.Web.Extensions; @@ -11,7 +17,12 @@ builder.Host.UseSerilog((_, _, configuration) => configuration .Enrich.FromLogContext() .Enrich.WithProperty("Service", "UserApi") - .WriteTo.Console(); + .WriteTo.Console() + .WriteTo.File( + "logs/user-api-.log", + rollingInterval: RollingInterval.Day, + retainedFileCountLimit: 7, + shared: true); }); builder.Services.AddSharedWebCore(); @@ -22,6 +33,59 @@ builder.Services.AddSharedSwagger(options => options.EnableAuthorization = true; }); builder.Services.AddTenantResolution(builder.Configuration); +var otelSection = builder.Configuration.GetSection("Otel"); +var otelEndpoint = otelSection.GetValue("Endpoint"); +var useConsoleExporter = otelSection.GetValue("UseConsoleExporter") ?? builder.Environment.IsDevelopment(); +builder.Services.AddOpenTelemetry() + .ConfigureResource(resource => resource.AddService( + serviceName: "TakeoutSaaS.UserApi", + serviceVersion: "1.0.0", + serviceInstanceId: Environment.MachineName)) + .WithTracing(tracing => + { + tracing + .SetSampler(new ParentBasedSampler(new AlwaysOnSampler())) + .AddAspNetCoreInstrumentation() + .AddHttpClientInstrumentation() + .AddEntityFrameworkCoreInstrumentation(options => + { + options.SetDbStatementForText = false; + options.SetDbStatementForStoredProcedure = false; + }); + + if (!string.IsNullOrWhiteSpace(otelEndpoint)) + { + tracing.AddOtlpExporter(exporter => + { + exporter.Endpoint = new Uri(otelEndpoint); + }); + } + + if (useConsoleExporter) + { + tracing.AddConsoleExporter(); + } + }) + .WithMetrics(metrics => + { + metrics + .AddAspNetCoreInstrumentation() + .AddHttpClientInstrumentation() + .AddRuntimeInstrumentation(); + + if (!string.IsNullOrWhiteSpace(otelEndpoint)) + { + metrics.AddOtlpExporter(exporter => + { + exporter.Endpoint = new Uri(otelEndpoint); + }); + } + + if (useConsoleExporter) + { + metrics.AddConsoleExporter(); + } + }); var userOrigins = ResolveCorsOrigins(builder.Configuration, "Cors:User"); builder.Services.AddCors(options => diff --git a/src/Api/TakeoutSaaS.UserApi/TakeoutSaaS.UserApi.csproj b/src/Api/TakeoutSaaS.UserApi/TakeoutSaaS.UserApi.csproj index ca338f6..247af3e 100644 --- a/src/Api/TakeoutSaaS.UserApi/TakeoutSaaS.UserApi.csproj +++ b/src/Api/TakeoutSaaS.UserApi/TakeoutSaaS.UserApi.csproj @@ -8,6 +8,13 @@ + + + + + + + diff --git a/src/Api/TakeoutSaaS.UserApi/appsettings.Development.json b/src/Api/TakeoutSaaS.UserApi/appsettings.Development.json index 7a3af9b..585bef6 100644 --- a/src/Api/TakeoutSaaS.UserApi/appsettings.Development.json +++ b/src/Api/TakeoutSaaS.UserApi/appsettings.Development.json @@ -55,7 +55,14 @@ "Tenancy": { "TenantIdHeaderName": "X-Tenant-Id", "TenantCodeHeaderName": "X-Tenant-Code", - "IgnoredPaths": [ "/health" ], + "IgnoredPaths": [ + "/health" + ], "RootDomain": "" + }, + "Otel": { + "Endpoint": "", + "Sampling": "ParentBasedAlwaysOn", + "UseConsoleExporter": true } -} +} \ No newline at end of file diff --git a/src/Api/TakeoutSaaS.UserApi/appsettings.Production.json b/src/Api/TakeoutSaaS.UserApi/appsettings.Production.json index 7a3af9b..585bef6 100644 --- a/src/Api/TakeoutSaaS.UserApi/appsettings.Production.json +++ b/src/Api/TakeoutSaaS.UserApi/appsettings.Production.json @@ -55,7 +55,14 @@ "Tenancy": { "TenantIdHeaderName": "X-Tenant-Id", "TenantCodeHeaderName": "X-Tenant-Code", - "IgnoredPaths": [ "/health" ], + "IgnoredPaths": [ + "/health" + ], "RootDomain": "" + }, + "Otel": { + "Endpoint": "", + "Sampling": "ParentBasedAlwaysOn", + "UseConsoleExporter": true } -} +} \ No newline at end of file