| File: DiagnosticsMetrics.cs | Web Access |
| Project: src\aspnetcore\src\Middleware\Diagnostics\src\Microsoft.AspNetCore.Diagnostics.csproj (Microsoft.AspNetCore.Diagnostics) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics; using System.Diagnostics.Metrics; using System.Runtime.CompilerServices; namespace Microsoft.AspNetCore.Diagnostics; // There are multiple instances of this metrics type. Each middleware creates an instance because there isn't a central place to register it in DI. // Multiple instances is ok because the meter and counter names are consistent. // DefaultMeterFactory caches instances meters by name, and meter caches instances of counters by name. internal sealed class DiagnosticsMetrics { public const string MeterName = "Microsoft.AspNetCore.Diagnostics"; private readonly Meter _meter; private readonly Counter<long> _handlerExceptionCounter; public DiagnosticsMetrics(IMeterFactory meterFactory) { _meter = meterFactory.Create(MeterName); _handlerExceptionCounter = _meter.CreateCounter<long>( "aspnetcore.diagnostics.exceptions", unit: "{exception}", description: "Number of exceptions caught by exception handling middleware."); } public void RequestException(string exceptionName, ExceptionResult result, string? handler) { if (_handlerExceptionCounter.Enabled) { RequestExceptionCore(exceptionName, result, handler); } } [MethodImpl(MethodImplOptions.NoInlining)] private void RequestExceptionCore(string exceptionName, ExceptionResult result, string? handler) { var tags = new TagList(); tags.Add("error.type", exceptionName); tags.Add("aspnetcore.diagnostics.exception.result", GetExceptionResult(result)); if (handler != null) { tags.Add("aspnetcore.diagnostics.handler.type", handler); } _handlerExceptionCounter.Add(1, tags); } private static string GetExceptionResult(ExceptionResult result) { switch (result) { case ExceptionResult.Skipped: return "skipped"; case ExceptionResult.Handled: return "handled"; case ExceptionResult.Unhandled: return "unhandled"; case ExceptionResult.Aborted: return "aborted"; default: throw new InvalidOperationException("Unexpected value: " + result); } } } internal enum ExceptionResult { Skipped, Handled, Unhandled, Aborted }