namespace FiscalOS.ServiceDefaults; public static class ServiceDefaultsExtensions { private const string HealthEndpointPath = "/health"; private const string AlivenessEndpointPath = "/alive"; public static TBuilder AddServiceDefaults(this TBuilder builder) where TBuilder : IHostApplicationBuilder { builder.ConfigureOpenTelemetry(); builder.AddDefaultHealthChecks(); builder.Services.AddServiceDiscovery(); builder.Services.ConfigureHttpClientDefaults(static http => { http.AddStandardResilienceHandler(); http.AddServiceDiscovery(); }); return builder; } public static TBuilder ConfigureOpenTelemetry(this TBuilder builder) where TBuilder : IHostApplicationBuilder { builder.Logging.AddOpenTelemetry(logging => { logging.IncludeFormattedMessage = true; logging.IncludeScopes = true; }); builder.Services.AddOpenTelemetry() .WithMetrics(metrics => metrics.AddAspNetCoreInstrumentation() .AddHttpClientInstrumentation() .AddRuntimeInstrumentation() ) .WithTracing(tracing => tracing.AddSource(builder.Environment.ApplicationName) .AddAspNetCoreInstrumentation(tracing => tracing.Filter = context => context.Request.Path.StartsWithSegments(HealthEndpointPath, StringComparison.InvariantCultureIgnoreCase) is false && context.Request.Path.StartsWithSegments(AlivenessEndpointPath, StringComparison.InvariantCultureIgnoreCase) is false ) .AddHttpClientInstrumentation() ); builder.AddOpenTelemetryExporters(); return builder; } public static TBuilder AddDefaultHealthChecks(this TBuilder builder) where TBuilder : IHostApplicationBuilder { builder.Services.AddHealthChecks() .AddCheck("self", static () => HealthCheckResult.Healthy(), ["live"]); return builder; } public static WebApplication MapDefaultEndpoints(this WebApplication app) { ArgumentNullException.ThrowIfNull(app, nameof(app)); if (app.Environment.IsDevelopment()) { app.MapHealthChecks(HealthEndpointPath); app.MapHealthChecks(AlivenessEndpointPath, new HealthCheckOptions { Predicate = static r => r.Tags.Contains("live") }); } return app; } private static TBuilder AddOpenTelemetryExporters(this TBuilder builder) where TBuilder : IHostApplicationBuilder { var useOtlpExporter = !string.IsNullOrWhiteSpace(builder.Configuration["OTEL_EXPORTER_OTLP_ENDPOINT"]); if (useOtlpExporter) { builder.Services.AddOpenTelemetry().UseOtlpExporter(); } return builder; } }