diff --git a/src/ServiceControl.Infrastructure/LoggerUtil.cs b/src/ServiceControl.Infrastructure/LoggerUtil.cs index b00617fbe0..a562e6f934 100644 --- a/src/ServiceControl.Infrastructure/LoggerUtil.cs +++ b/src/ServiceControl.Infrastructure/LoggerUtil.cs @@ -2,10 +2,13 @@ { using System; using System.Collections.Concurrent; + using System.Diagnostics; + using System.Reflection; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using NLog.Extensions.Logging; using OpenTelemetry.Logs; + using OpenTelemetry.Resources; using ServiceControl.Infrastructure.TestLogger; [Flags] @@ -24,11 +27,32 @@ public static class LoggerUtil public static string SeqAddress { private get; set; } - public static bool IsLoggingTo(Loggers logger) + // Telemetry resource attached to exported OTLP logs (service.name/service.version/service.instance.id). + // Set once at process startup via Initialize() — before any logger is created — so both the host pipeline + // and the static bootstrap loggers (CreateStaticLogger) share a single instance identity. Defaults to + // CreateDefault() (which still honors OTEL_SERVICE_NAME/OTEL_RESOURCE_ATTRIBUTES) for the rare logger + // created before Initialize runs. + static ResourceBuilder serviceResourceBuilder = CreateResourcesBuilder(); + + static ResourceBuilder CreateResourcesBuilder() { - return (logger & ActiveLoggers) == logger; + var asm = Assembly.GetEntryAssembly() ?? throw new InvalidOperationException("Entry assembly not found"); + var serviceName = asm.GetName().Name ?? throw new InvalidOperationException("Entry assembly name not found"); + var serviceVersion = FileVersionInfo.GetVersionInfo(asm.Location).ProductVersion; + + // CreateDefault() also reads OTEL_SERVICE_NAME/OTEL_RESOURCE_ATTRIBUTES, so operators can still enrich + // the resource with deployment-specific attributes via those environment variables. + return ResourceBuilder + .CreateDefault() + .AddService( + serviceName, + serviceVersion: serviceVersion, + autoGenerateServiceInstanceId: true + ); } + public static bool IsLoggingTo(Loggers logger) => (logger & ActiveLoggers) == logger; + public static void ConfigureLogging(this ILoggingBuilder loggingBuilder, LogLevel level) { loggingBuilder.SetMinimumLevel(level); @@ -54,7 +78,11 @@ public static void ConfigureLogging(this ILoggingBuilder loggingBuilder, LogLeve } if (IsLoggingTo(Loggers.Otlp)) { - loggingBuilder.AddOpenTelemetry(configure => configure.AddOtlpExporter()); + loggingBuilder.AddOpenTelemetry(configure => + { + configure.SetResourceBuilder(serviceResourceBuilder); + configure.AddOtlpExporter(); + }); } }