// // Copyright The OpenTelemetry Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // using System.Diagnostics.Metrics; using Examples.AspNetCore; using OpenTelemetry.Exporter; using OpenTelemetry.Instrumentation.AspNetCore; using OpenTelemetry.Logs; using OpenTelemetry.Metrics; using OpenTelemetry.Resources; using OpenTelemetry.Trace; var appBuilder = WebApplication.CreateBuilder(args); // Note: Switch between Zipkin/Jaeger/OTLP/Console by setting UseTracingExporter in appsettings.json. var tracingExporter = appBuilder.Configuration.GetValue("UseTracingExporter").ToLowerInvariant(); // Note: Switch between Prometheus/OTLP/Console by setting UseMetricsExporter in appsettings.json. var metricsExporter = appBuilder.Configuration.GetValue("UseMetricsExporter").ToLowerInvariant(); // Note: Switch between Console/OTLP by setting UseLogExporter in appsettings.json. var logExporter = appBuilder.Configuration.GetValue("UseLogExporter").ToLowerInvariant(); // Note: Switch between Explicit/Exponential by setting HistogramAggregation in appsettings.json var histogramAggregation = appBuilder.Configuration.GetValue("HistogramAggregation").ToLowerInvariant(); // Build a resource configuration action to set service information. Action configureResource = r => r.AddService( serviceName: appBuilder.Configuration.GetValue("ServiceName"), serviceVersion: typeof(Program).Assembly.GetName().Version?.ToString() ?? "unknown", serviceInstanceId: Environment.MachineName); // Create a service to expose ActivitySource, and Metric Instruments // for manual instrumentation appBuilder.Services.AddSingleton(); // Configure OpenTelemetry tracing & metrics with auto-start using the // AddOpenTelemetry extension from OpenTelemetry.Extensions.Hosting. appBuilder.Services.AddOpenTelemetry() .ConfigureResource(configureResource) .WithTracing(builder => { // Tracing // Ensure the TracerProvider subscribes to any custom ActivitySources. builder .AddSource(Instrumentation.ActivitySourceName) .SetSampler(new AlwaysOnSampler()) .AddHttpClientInstrumentation() .AddAspNetCoreInstrumentation(); // Use IConfiguration binding for AspNetCore instrumentation options. appBuilder.Services.Configure(appBuilder.Configuration.GetSection("AspNetCoreInstrumentation")); switch (tracingExporter) { case "jaeger": builder.AddJaegerExporter(); builder.ConfigureServices(services => { // Use IConfiguration binding for Jaeger exporter options. services.Configure(appBuilder.Configuration.GetSection("Jaeger")); // Customize the HttpClient that will be used when JaegerExporter is configured for HTTP transport. services.AddHttpClient("JaegerExporter", configureClient: (client) => client.DefaultRequestHeaders.Add("X-MyCustomHeader", "value")); }); break; case "zipkin": builder.AddZipkinExporter(); builder.ConfigureServices(services => { // Use IConfiguration binding for Zipkin exporter options. services.Configure(appBuilder.Configuration.GetSection("Zipkin")); }); break; case "otlp": builder.AddOtlpExporter(otlpOptions => { // Use IConfiguration directly for Otlp exporter endpoint option. otlpOptions.Endpoint = new Uri(appBuilder.Configuration.GetValue("Otlp:Endpoint")); }); break; default: builder.AddConsoleExporter(); break; } }) .WithMetrics(builder => { // Metrics // Ensure the MeterProvider subscribes to any custom Meters. builder .AddMeter(Instrumentation.MeterName) // .SetExemplarFilter(new TraceBasedExemplarFilter()) .AddRuntimeInstrumentation() .AddHttpClientInstrumentation() .AddAspNetCoreInstrumentation(); switch (histogramAggregation) { case "exponential": builder.AddView(instrument => { return instrument.GetType().GetGenericTypeDefinition() == typeof(Histogram<>) ? new Base2ExponentialBucketHistogramConfiguration() : null; }); break; default: // Explicit bounds histogram is the default. // No additional configuration necessary. break; } switch (metricsExporter) { case "prometheus": builder.AddPrometheusExporter(); break; case "otlp": builder.AddOtlpExporter(otlpOptions => { // Use IConfiguration directly for Otlp exporter endpoint option. otlpOptions.Endpoint = new Uri(appBuilder.Configuration.GetValue("Otlp:Endpoint")); }); break; default: builder.AddConsoleExporter(); break; } }); // Clear default logging providers used by WebApplication host. appBuilder.Logging.ClearProviders(); // Configure OpenTelemetry Logging. appBuilder.Logging.AddOpenTelemetry(options => { // Note: See appsettings.json Logging:OpenTelemetry section for configuration. var resourceBuilder = ResourceBuilder.CreateDefault(); configureResource(resourceBuilder); options.SetResourceBuilder(resourceBuilder); switch (logExporter) { case "otlp": options.AddOtlpExporter(otlpOptions => { // Use IConfiguration directly for Otlp exporter endpoint option. otlpOptions.Endpoint = new Uri(appBuilder.Configuration.GetValue("Otlp:Endpoint")); }); break; default: options.AddConsoleExporter(); break; } }); appBuilder.Services.AddControllers(); appBuilder.Services.AddEndpointsApiExplorer(); appBuilder.Services.AddSwaggerGen(); var app = appBuilder.Build(); if (app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(); } app.UseHttpsRedirection(); app.UseAuthorization(); app.MapControllers(); // Configure OpenTelemetry Prometheus AspNetCore middleware scrape endpoint if enabled. if (metricsExporter.Equals("prometheus", StringComparison.OrdinalIgnoreCase)) { app.UseOpenTelemetryPrometheusScrapingEndpoint(); } app.Run();