[Examples.AspNetCore] enable analysis (#6193)

Co-authored-by: Rajkumar Rangaraj <rajrang@microsoft.com>
This commit is contained in:
Piotr Kiełkowicz 2025-03-25 18:34:21 +01:00 committed by GitHub
parent 6c69fb2b8c
commit c1472c76fd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 43 additions and 30 deletions

View File

@ -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<long> freezingDaysCounter;
public WeatherForecastController(ILogger<WeatherForecastController> logger, Instrumentation instrumentation)
public WeatherForecastController(ILogger<WeatherForecastController> 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<WeatherForecast> 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;
}

View File

@ -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<ILogger, string, IDisposable?> Scope = LoggerMessage.DefineScope<string>("{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);
}

View File

@ -2,6 +2,8 @@
<PropertyGroup>
<TargetFramework>$(DefaultTargetFrameworkForExampleApps)</TargetFramework>
<AnalysisLevel>latest-all</AnalysisLevel>
<NoWarn>$(NoWarn);CA1515</NoWarn>
</PropertyGroup>
<ItemGroup>

View File

@ -11,15 +11,15 @@ using System.Diagnostics.Metrics;
/// ActivitySource and Instruments. This avoids possible type collisions
/// with other components in the DI container.
/// </summary>
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<long>("weather.days.freezing", description: "The number of days where the temperature is below freezing");

View File

@ -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<Instrumentation>();
appBuilder.Services.AddSingleton<InstrumentationSource>();
// 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.