diff --git a/examples/AspNetCore/Controllers/WeatherForecastController.cs b/examples/AspNetCore/Controllers/WeatherForecastController.cs index 44b8b30cb..bbb257334 100644 --- a/examples/AspNetCore/Controllers/WeatherForecastController.cs +++ b/examples/AspNetCore/Controllers/WeatherForecastController.cs @@ -5,6 +5,7 @@ namespace Examples.AspNetCore.Controllers; using System.Diagnostics; using System.Diagnostics.Metrics; +using System.Security.Cryptography; using Examples.AspNetCore; using Microsoft.AspNetCore.Mvc; @@ -23,24 +24,24 @@ public class WeatherForecastController : ControllerBase private readonly ActivitySource activitySource; private readonly Counter freezingDaysCounter; - public WeatherForecastController(ILogger logger, Instrumentation instrumentation) + public WeatherForecastController(ILogger logger, InstrumentationSource instrumentationSource) { this.logger = logger ?? throw new ArgumentNullException(nameof(logger)); - ArgumentNullException.ThrowIfNull(instrumentation); - this.activitySource = instrumentation.ActivitySource; - this.freezingDaysCounter = instrumentation.FreezingDaysCounter; + ArgumentNullException.ThrowIfNull(instrumentationSource); + this.activitySource = instrumentationSource.ActivitySource; + this.freezingDaysCounter = instrumentationSource.FreezingDaysCounter; } [HttpGet] public IEnumerable Get() { - using var scope = this.logger.BeginScope("{Id}", Guid.NewGuid().ToString("N")); + using var scope = this.logger.BeginIdScope(Guid.NewGuid().ToString("N")); - // Making an http call here to serve as an example of + // Making a http call here to serve as an example of // how dependency calls will be captured and treated // automatically as child of incoming request. - var res = HttpClient.GetStringAsync("http://google.com").Result; + var res = HttpClient.GetStringAsync(new Uri("http://google.com")).Result; // Optional: Manually create an activity. This will become a child of // the activity created from the instrumentation library for AspNetCore. @@ -52,22 +53,18 @@ public class WeatherForecastController : ControllerBase // a manual activity using Activity.Current?.SetTag() using var activity = this.activitySource.StartActivity("calculate forecast"); - var rng = new Random(); var forecast = Enumerable.Range(1, 5).Select(index => new WeatherForecast { Date = DateTime.Now.AddDays(index), - TemperatureC = rng.Next(-20, 55), - Summary = Summaries[rng.Next(Summaries.Length)], + TemperatureC = RandomNumberGenerator.GetInt32(-20, 55), + Summary = Summaries[RandomNumberGenerator.GetInt32(Summaries.Length)], }) .ToArray(); // Optional: Count the freezing days this.freezingDaysCounter.Add(forecast.Count(f => f.TemperatureC < 0)); - this.logger.LogInformation( - "WeatherForecasts generated {count}: {forecasts}", - forecast.Length, - forecast); + this.logger.WeatherForecastGenerated(LogLevel.Information, forecast.Length, forecast); return forecast; } diff --git a/examples/AspNetCore/Controllers/WeatherForecastControllerLog.cs b/examples/AspNetCore/Controllers/WeatherForecastControllerLog.cs new file mode 100644 index 000000000..eb6bc2926 --- /dev/null +++ b/examples/AspNetCore/Controllers/WeatherForecastControllerLog.cs @@ -0,0 +1,14 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +namespace Examples.AspNetCore.Controllers; + +internal static partial class WeatherForecastControllerLog +{ + private static readonly Func Scope = LoggerMessage.DefineScope("{Id}"); + + public static IDisposable? BeginIdScope(this ILogger logger, string id) => Scope(logger, id); + + [LoggerMessage(EventId = 1, Message = "WeatherForecasts generated {Count}: {Forecasts}")] + public static partial void WeatherForecastGenerated(this ILogger logger, LogLevel logLevel, int count, WeatherForecast[] forecasts); +} diff --git a/examples/AspNetCore/Examples.AspNetCore.csproj b/examples/AspNetCore/Examples.AspNetCore.csproj index e476b1ed4..e7f998e04 100644 --- a/examples/AspNetCore/Examples.AspNetCore.csproj +++ b/examples/AspNetCore/Examples.AspNetCore.csproj @@ -2,6 +2,8 @@ $(DefaultTargetFrameworkForExampleApps) + latest-all + $(NoWarn);CA1515 diff --git a/examples/AspNetCore/Instrumentation.cs b/examples/AspNetCore/InstrumentationSource.cs similarity index 85% rename from examples/AspNetCore/Instrumentation.cs rename to examples/AspNetCore/InstrumentationSource.cs index 4b0ede115..be6d57640 100644 --- a/examples/AspNetCore/Instrumentation.cs +++ b/examples/AspNetCore/InstrumentationSource.cs @@ -11,15 +11,15 @@ using System.Diagnostics.Metrics; /// ActivitySource and Instruments. This avoids possible type collisions /// with other components in the DI container. /// -public class Instrumentation : IDisposable +public sealed class InstrumentationSource : IDisposable { internal const string ActivitySourceName = "Examples.AspNetCore"; internal const string MeterName = "Examples.AspNetCore"; private readonly Meter meter; - public Instrumentation() + public InstrumentationSource() { - string? version = typeof(Instrumentation).Assembly.GetName().Version?.ToString(); + string? version = typeof(InstrumentationSource).Assembly.GetName().Version?.ToString(); this.ActivitySource = new ActivitySource(ActivitySourceName, version); this.meter = new Meter(MeterName, version); this.FreezingDaysCounter = this.meter.CreateCounter("weather.days.freezing", description: "The number of days where the temperature is below freezing"); diff --git a/examples/AspNetCore/Program.cs b/examples/AspNetCore/Program.cs index 9b12dc681..afd59db31 100644 --- a/examples/AspNetCore/Program.cs +++ b/examples/AspNetCore/Program.cs @@ -13,20 +13,20 @@ using OpenTelemetry.Trace; var appBuilder = WebApplication.CreateBuilder(args); // Note: Switch between Zipkin/OTLP/Console by setting UseTracingExporter in appsettings.json. -var tracingExporter = appBuilder.Configuration.GetValue("UseTracingExporter", defaultValue: "console").ToLowerInvariant(); +var tracingExporter = appBuilder.Configuration.GetValue("UseTracingExporter", defaultValue: "CONSOLE").ToUpperInvariant(); // Note: Switch between Prometheus/OTLP/Console by setting UseMetricsExporter in appsettings.json. -var metricsExporter = appBuilder.Configuration.GetValue("UseMetricsExporter", defaultValue: "console").ToLowerInvariant(); +var metricsExporter = appBuilder.Configuration.GetValue("UseMetricsExporter", defaultValue: "CONSOLE").ToUpperInvariant(); // Note: Switch between Console/OTLP by setting UseLogExporter in appsettings.json. -var logExporter = appBuilder.Configuration.GetValue("UseLogExporter", defaultValue: "console").ToLowerInvariant(); +var logExporter = appBuilder.Configuration.GetValue("UseLogExporter", defaultValue: "CONSOLE").ToUpperInvariant(); // Note: Switch between Explicit/Exponential by setting HistogramAggregation in appsettings.json -var histogramAggregation = appBuilder.Configuration.GetValue("HistogramAggregation", defaultValue: "explicit").ToLowerInvariant(); +var histogramAggregation = appBuilder.Configuration.GetValue("HistogramAggregation", defaultValue: "EXPLICIT").ToUpperInvariant(); // Create a service to expose ActivitySource, and Metric Instruments // for manual instrumentation -appBuilder.Services.AddSingleton(); +appBuilder.Services.AddSingleton(); // Clear default logging providers used by WebApplication host. appBuilder.Logging.ClearProviders(); @@ -45,7 +45,7 @@ appBuilder.Services.AddOpenTelemetry() // Ensure the TracerProvider subscribes to any custom ActivitySources. builder - .AddSource(Instrumentation.ActivitySourceName) + .AddSource(InstrumentationSource.ActivitySourceName) .SetSampler(new AlwaysOnSampler()) .AddHttpClientInstrumentation() .AddAspNetCoreInstrumentation(); @@ -55,7 +55,7 @@ appBuilder.Services.AddOpenTelemetry() switch (tracingExporter) { - case "zipkin": + case "ZIPKIN": builder.AddZipkinExporter(); builder.ConfigureServices(services => @@ -65,7 +65,7 @@ appBuilder.Services.AddOpenTelemetry() }); break; - case "otlp": + case "OTLP": builder.AddOtlpExporter(otlpOptions => { // Use IConfiguration directly for Otlp exporter endpoint option. @@ -84,7 +84,7 @@ appBuilder.Services.AddOpenTelemetry() // Ensure the MeterProvider subscribes to any custom Meters. builder - .AddMeter(Instrumentation.MeterName) + .AddMeter(InstrumentationSource.MeterName) .SetExemplarFilter(ExemplarFilterType.TraceBased) .AddRuntimeInstrumentation() .AddHttpClientInstrumentation() @@ -92,7 +92,7 @@ appBuilder.Services.AddOpenTelemetry() switch (histogramAggregation) { - case "exponential": + case "EXPONENTIAL": builder.AddView(instrument => { return instrument.GetType().GetGenericTypeDefinition() == typeof(Histogram<>) @@ -108,10 +108,10 @@ appBuilder.Services.AddOpenTelemetry() switch (metricsExporter) { - case "prometheus": + case "PROMETHEUS": builder.AddPrometheusExporter(); break; - case "otlp": + case "OTLP": builder.AddOtlpExporter(otlpOptions => { // Use IConfiguration directly for Otlp exporter endpoint option. @@ -129,7 +129,7 @@ appBuilder.Services.AddOpenTelemetry() switch (logExporter) { - case "otlp": + case "OTLP": builder.AddOtlpExporter(otlpOptions => { // Use IConfiguration directly for Otlp exporter endpoint option.