[examples] Add manual activities and custom metrics to ASP.NET Core example (#4133)
This commit is contained in:
parent
da938d797e
commit
1273e83d55
|
|
@ -16,6 +16,9 @@
|
|||
|
||||
namespace Examples.AspNetCore.Controllers;
|
||||
|
||||
using System.Diagnostics;
|
||||
using System.Diagnostics.Metrics;
|
||||
using Examples.AspNetCore;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
[ApiController]
|
||||
|
|
@ -24,16 +27,22 @@ public class WeatherForecastController : ControllerBase
|
|||
{
|
||||
private static readonly string[] Summaries = new[]
|
||||
{
|
||||
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching",
|
||||
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching",
|
||||
};
|
||||
|
||||
private static readonly HttpClient HttpClient = new();
|
||||
|
||||
private readonly ILogger<WeatherForecastController> logger;
|
||||
private readonly ActivitySource activitySource;
|
||||
private readonly Counter<long> freezingDaysCounter;
|
||||
|
||||
public WeatherForecastController(ILogger<WeatherForecastController> logger)
|
||||
public WeatherForecastController(ILogger<WeatherForecastController> logger, Instrumentation instrumentation)
|
||||
{
|
||||
this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||
|
||||
ArgumentNullException.ThrowIfNull(instrumentation);
|
||||
this.activitySource = instrumentation.ActivitySource;
|
||||
this.freezingDaysCounter = instrumentation.FreezingDaysCounter;
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
|
|
@ -45,6 +54,17 @@ public class WeatherForecastController : ControllerBase
|
|||
// how dependency calls will be captured and treated
|
||||
// automatically as child of incoming request.
|
||||
var res = HttpClient.GetStringAsync("http://google.com").Result;
|
||||
|
||||
// Optional: Manually create an activity. This will become a child of
|
||||
// the activity created from the instrumentation library for AspNetCore.
|
||||
// Manually created activities are useful when there is a desire to track
|
||||
// a specific subset of the request. In this example one could imagine
|
||||
// that calculating the forecast is an expensive operation and therefore
|
||||
// something to be distinguished from the overall request.
|
||||
// Note: Tags can be added to the current activity without the need for
|
||||
// a manual activity using Acitivty.Current?.SetTag()
|
||||
using var activity = this.activitySource.StartActivity("calculate forecast");
|
||||
|
||||
var rng = new Random();
|
||||
var forecast = Enumerable.Range(1, 5).Select(index => new WeatherForecast
|
||||
{
|
||||
|
|
@ -54,6 +74,9 @@ public class WeatherForecastController : ControllerBase
|
|||
})
|
||||
.ToArray();
|
||||
|
||||
// Optional: Count the freezing days
|
||||
this.freezingDaysCounter.Add(forecast.Count(f => f.TemperatureC < 0));
|
||||
|
||||
this.logger.LogInformation(
|
||||
"WeatherForecasts generated {count}: {forecasts}",
|
||||
forecast.Length,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,50 @@
|
|||
// <copyright file="Instrumentation.cs" company="OpenTelemetry Authors">
|
||||
// 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.
|
||||
// </copyright>
|
||||
|
||||
namespace Examples.AspNetCore;
|
||||
|
||||
using System.Diagnostics;
|
||||
using System.Diagnostics.Metrics;
|
||||
|
||||
/// <summary>
|
||||
/// It is recommended to use a custom type to hold references for
|
||||
/// ActivitySource and Instruments. This avoids possible type collisions
|
||||
/// with other components in the DI container.
|
||||
/// </summary>
|
||||
public class Instrumentation : IDisposable
|
||||
{
|
||||
internal const string ActivitySourceName = "Examples.AspNetCore";
|
||||
internal const string MeterName = "Examples.AspNetCore";
|
||||
private readonly Meter meter;
|
||||
|
||||
public Instrumentation()
|
||||
{
|
||||
string? version = typeof(Instrumentation).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", "The number of days where the temperature is below freezing");
|
||||
}
|
||||
|
||||
public ActivitySource ActivitySource { get; }
|
||||
|
||||
public Counter<long> FreezingDaysCounter { get; }
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
this.ActivitySource.Dispose();
|
||||
this.meter.Dispose();
|
||||
}
|
||||
}
|
||||
|
|
@ -14,7 +14,7 @@
|
|||
// limitations under the License.
|
||||
// </copyright>
|
||||
|
||||
using System.Reflection;
|
||||
using Examples.AspNetCore;
|
||||
using OpenTelemetry;
|
||||
using OpenTelemetry.Exporter;
|
||||
using OpenTelemetry.Instrumentation.AspNetCore;
|
||||
|
|
@ -37,9 +37,13 @@ var logExporter = appBuilder.Configuration.GetValue<string>("UseLogExporter").To
|
|||
// Build a resource configuration action to set service information.
|
||||
Action<ResourceBuilder> configureResource = r => r.AddService(
|
||||
serviceName: appBuilder.Configuration.GetValue<string>("ServiceName"),
|
||||
serviceVersion: Assembly.GetExecutingAssembly().GetName().Version?.ToString() ?? "unknown",
|
||||
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<Instrumentation>();
|
||||
|
||||
// Configure OpenTelemetry tracing & metrics with auto-start using the
|
||||
// StartWithHost extension from OpenTelemetry.Extensions.Hosting.
|
||||
appBuilder.Services.AddOpenTelemetry()
|
||||
|
|
@ -48,7 +52,9 @@ appBuilder.Services.AddOpenTelemetry()
|
|||
{
|
||||
// Tracing
|
||||
|
||||
// Ensure the TracerProvider subscribes to any custom ActivitySources.
|
||||
builder
|
||||
.AddSource(Instrumentation.ActivitySourceName)
|
||||
.SetSampler(new AlwaysOnSampler())
|
||||
.AddHttpClientInstrumentation()
|
||||
.AddAspNetCoreInstrumentation();
|
||||
|
|
@ -98,7 +104,9 @@ appBuilder.Services.AddOpenTelemetry()
|
|||
{
|
||||
// Metrics
|
||||
|
||||
// Ensure the MeterProvider subscribes to any custom Meters.
|
||||
builder
|
||||
.AddMeter(Instrumentation.MeterName)
|
||||
.AddRuntimeInstrumentation()
|
||||
.AddHttpClientInstrumentation()
|
||||
.AddAspNetCoreInstrumentation();
|
||||
|
|
|
|||
Loading…
Reference in New Issue