From 59570ae22d90f3ac15993009e4a4c7903bab31e7 Mon Sep 17 00:00:00 2001 From: James Newton-King Date: Mon, 31 Jul 2023 12:02:15 +0800 Subject: [PATCH 01/13] Rename hosting metrics to be consistent with OpenTelemetry --- .../Internal/HostingApplicationDiagnostics.cs | 6 +- .../Hosting/src/Internal/HostingMetrics.cs | 113 +++++++++++++----- .../HostingApplicationDiagnosticsTests.cs | 24 ++-- .../Hosting/test/HostingMetricsTests.cs | 58 +++++---- 4 files changed, 129 insertions(+), 72 deletions(-) diff --git a/src/Hosting/Hosting/src/Internal/HostingApplicationDiagnostics.cs b/src/Hosting/Hosting/src/Internal/HostingApplicationDiagnostics.cs index c5658692b0dd..0d045ee520d8 100644 --- a/src/Hosting/Hosting/src/Internal/HostingApplicationDiagnostics.cs +++ b/src/Hosting/Hosting/src/Internal/HostingApplicationDiagnostics.cs @@ -148,15 +148,11 @@ public void RequestEnd(HttpContext httpContext, Exception? exception, HostingApp httpContext.Request.Host, route, httpContext.Response.StatusCode, + reachedPipelineEnd, exception, customTags, startTimestamp, currentTimestamp); - - if (reachedPipelineEnd) - { - _metrics.UnhandledRequest(); - } } if (reachedPipelineEnd) diff --git a/src/Hosting/Hosting/src/Internal/HostingMetrics.cs b/src/Hosting/Hosting/src/Internal/HostingMetrics.cs index 3fd09d9bac3e..3cbfa300ccae 100644 --- a/src/Hosting/Hosting/src/Internal/HostingMetrics.cs +++ b/src/Hosting/Hosting/src/Internal/HostingMetrics.cs @@ -3,6 +3,7 @@ using System.Collections.Frozen; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Diagnostics.Metrics; using Microsoft.AspNetCore.Http; @@ -13,26 +14,21 @@ internal sealed class HostingMetrics : IDisposable public const string MeterName = "Microsoft.AspNetCore.Hosting"; private readonly Meter _meter; - private readonly UpDownCounter _currentRequestsCounter; + private readonly UpDownCounter _activeRequestsCounter; private readonly Histogram _requestDuration; - private readonly Counter _unhandledRequestsCounter; public HostingMetrics(IMeterFactory meterFactory) { _meter = meterFactory.Create(MeterName); - _currentRequestsCounter = _meter.CreateUpDownCounter( - "http-server-current-requests", + _activeRequestsCounter = _meter.CreateUpDownCounter( + "http.server.active_requests", description: "Number of HTTP requests that are currently active on the server."); _requestDuration = _meter.CreateHistogram( - "http-server-request-duration", + "http.server.duration", unit: "s", - description: "The duration of HTTP requests on the server."); - - _unhandledRequestsCounter = _meter.CreateCounter( - "http-server-unhandled-requests", - description: "Number of HTTP requests that reached the end of the middleware pipeline without being handled by application code."); + description: "Measures the duration of inbound HTTP requests."); } // Note: Calling code checks whether counter is enabled. @@ -41,35 +37,43 @@ public void RequestStart(bool isHttps, string scheme, string method, HostString // Tags must match request end. var tags = new TagList(); InitializeRequestTags(ref tags, isHttps, scheme, method, host); - _currentRequestsCounter.Add(1, tags); + _activeRequestsCounter.Add(1, tags); } - public void RequestEnd(string protocol, bool isHttps, string scheme, string method, HostString host, string? route, int statusCode, Exception? exception, List>? customTags, long startTimestamp, long currentTimestamp) + public void RequestEnd(string protocol, bool isHttps, string scheme, string method, HostString host, string? route, int statusCode, bool unhandledRequest, Exception? exception, List>? customTags, long startTimestamp, long currentTimestamp) { var tags = new TagList(); InitializeRequestTags(ref tags, isHttps, scheme, method, host); // Tags must match request start. - if (_currentRequestsCounter.Enabled) + if (_activeRequestsCounter.Enabled) { - _currentRequestsCounter.Add(-1, tags); + _activeRequestsCounter.Add(-1, tags); } if (_requestDuration.Enabled) { - tags.Add("protocol", protocol); + tags.Add("network.protocol.name", "http"); + if (TryGetHttpVersion(protocol, out var httpVersion)) + { + tags.Add("network.protocol.version", httpVersion); + } + if (unhandledRequest) + { + tags.Add("aspnet.request.is_unhandled", true); + } // Add information gathered during request. - tags.Add("status-code", GetBoxedStatusCode(statusCode)); + tags.Add("http.response.status_code", GetBoxedStatusCode(statusCode)); if (route != null) { - tags.Add("route", route); + tags.Add("http.route", route); } // This exception is only present if there is an unhandled exception. - // An exception caught by ExceptionHandlerMiddleware and DeveloperExceptionMiddleware isn't thrown to here. Instead, those middleware add exception-name to custom tags. + // An exception caught by ExceptionHandlerMiddleware and DeveloperExceptionMiddleware isn't thrown to here. Instead, those middleware add exception.type to custom tags. if (exception != null) { - tags.Add("exception-name", exception.GetType().FullName); + tags.Add("exception.type", exception.GetType().FullName); } if (customTags != null) { @@ -84,25 +88,20 @@ public void RequestEnd(string protocol, bool isHttps, string scheme, string meth } } - public void UnhandledRequest() - { - _unhandledRequestsCounter.Add(1); - } - public void Dispose() { _meter.Dispose(); } - public bool IsEnabled() => _currentRequestsCounter.Enabled || _requestDuration.Enabled || _unhandledRequestsCounter.Enabled; + public bool IsEnabled() => _activeRequestsCounter.Enabled || _requestDuration.Enabled; private static void InitializeRequestTags(ref TagList tags, bool isHttps, string scheme, string method, HostString host) { - tags.Add("scheme", scheme); - tags.Add("method", method); + tags.Add("url.scheme", scheme); + tags.Add("http.request.method", ResolveHttpMethod(method)); if (host.HasValue) { - tags.Add("host", host.Host); + tags.Add("server.address", host.Host); // Port is parsed each time it's accessed. Store part in local variable. if (host.Port is { } port) @@ -110,7 +109,7 @@ private static void InitializeRequestTags(ref TagList tags, bool isHttps, string // Add port tag when not the default value for the current scheme if ((isHttps && port != 443) || (!isHttps && port != 80)) { - tags.Add("port", port); + tags.Add("server.port", port); } } } @@ -197,4 +196,60 @@ private static object GetBoxedStatusCode(int statusCode) return statusCode; } + + private static readonly FrozenDictionary KnownMethods = FrozenDictionary.ToFrozenDictionary(new[] + { + KeyValuePair.Create(HttpMethods.Connect, HttpMethods.Connect), + KeyValuePair.Create(HttpMethods.Delete, HttpMethods.Delete), + KeyValuePair.Create(HttpMethods.Get, HttpMethods.Get), + KeyValuePair.Create(HttpMethods.Head, HttpMethods.Head), + KeyValuePair.Create(HttpMethods.Options, HttpMethods.Options), + KeyValuePair.Create(HttpMethods.Patch, HttpMethods.Patch), + KeyValuePair.Create(HttpMethods.Post, HttpMethods.Post), + KeyValuePair.Create(HttpMethods.Put, HttpMethods.Put), + KeyValuePair.Create(HttpMethods.Trace, HttpMethods.Trace) + }, StringComparer.OrdinalIgnoreCase); + + private static string ResolveHttpMethod(string method) + { + if (KnownMethods.TryGetValue(method, out var result)) + { + // KnownMethods ignores case. Use the value returned by the dictionary to have a consistent case. + return result; + } + return "_UNKNOWN"; + } + + private static bool TryGetHttpVersion(string protocol, [NotNullWhen(true)] out string? version) + { + if (HttpProtocol.IsHttp11(protocol)) + { + version = "1.1"; + return true; + } + if (HttpProtocol.IsHttp2(protocol)) + { + // HTTP/2 only has one version. + version = "2"; + return true; + } + if (HttpProtocol.IsHttp3(protocol)) + { + // HTTP/3 only has one version. + version = "3"; + return true; + } + if (HttpProtocol.IsHttp10(protocol)) + { + version = "1.0"; + return true; + } + if (HttpProtocol.IsHttp09(protocol)) + { + version = "0.9"; + return true; + } + version = null; + return false; + } } diff --git a/src/Hosting/Hosting/test/HostingApplicationDiagnosticsTests.cs b/src/Hosting/Hosting/test/HostingApplicationDiagnosticsTests.cs index 8a4db4e13b95..e37184c788b8 100644 --- a/src/Hosting/Hosting/test/HostingApplicationDiagnosticsTests.cs +++ b/src/Hosting/Hosting/test/HostingApplicationDiagnosticsTests.cs @@ -53,10 +53,10 @@ public async Task EventCountersAndMetricsValues() var hostingApplication1 = CreateApplication(out var features1, eventSource: hostingEventSource, meterFactory: testMeterFactory1); var hostingApplication2 = CreateApplication(out var features2, eventSource: hostingEventSource, meterFactory: testMeterFactory2); - using var currentRequestsRecorder1 = new MetricCollector(testMeterFactory1, HostingMetrics.MeterName, "http-server-current-requests"); - using var currentRequestsRecorder2 = new MetricCollector(testMeterFactory2, HostingMetrics.MeterName, "http-server-current-requests"); - using var requestDurationRecorder1 = new MetricCollector(testMeterFactory1, HostingMetrics.MeterName, "http-server-request-duration"); - using var requestDurationRecorder2 = new MetricCollector(testMeterFactory2, HostingMetrics.MeterName, "http-server-request-duration"); + using var activeRequestsCollector1 = new MetricCollector(testMeterFactory1, HostingMetrics.MeterName, "http.server.active_requests"); + using var activeRequestsCollector2 = new MetricCollector(testMeterFactory2, HostingMetrics.MeterName, "http.server.active_requests"); + using var requestDurationCollector1 = new MetricCollector(testMeterFactory1, HostingMetrics.MeterName, "http.server.duration"); + using var requestDurationCollector2 = new MetricCollector(testMeterFactory2, HostingMetrics.MeterName, "http.server.duration"); // Act/Assert 1 var context1 = hostingApplication1.CreateContext(features1); @@ -75,15 +75,15 @@ public async Task EventCountersAndMetricsValues() Assert.Equal(0, await currentRequestValues.FirstOrDefault(v => v == 0)); Assert.Equal(0, await failedRequestValues.FirstOrDefault(v => v == 0)); - Assert.Collection(currentRequestsRecorder1.GetMeasurementSnapshot(), + Assert.Collection(activeRequestsCollector1.GetMeasurementSnapshot(), m => Assert.Equal(1, m.Value), m => Assert.Equal(-1, m.Value)); - Assert.Collection(currentRequestsRecorder2.GetMeasurementSnapshot(), + Assert.Collection(activeRequestsCollector2.GetMeasurementSnapshot(), m => Assert.Equal(1, m.Value), m => Assert.Equal(-1, m.Value)); - Assert.Collection(requestDurationRecorder1.GetMeasurementSnapshot(), + Assert.Collection(requestDurationCollector1.GetMeasurementSnapshot(), m => Assert.True(m.Value > 0)); - Assert.Collection(requestDurationRecorder2.GetMeasurementSnapshot(), + Assert.Collection(requestDurationCollector2.GetMeasurementSnapshot(), m => Assert.True(m.Value > 0)); // Act/Assert 2 @@ -106,20 +106,20 @@ public async Task EventCountersAndMetricsValues() Assert.Equal(0, await currentRequestValues.FirstOrDefault(v => v == 0)); Assert.Equal(2, await failedRequestValues.FirstOrDefault(v => v == 2)); - Assert.Collection(currentRequestsRecorder1.GetMeasurementSnapshot(), + Assert.Collection(activeRequestsCollector1.GetMeasurementSnapshot(), m => Assert.Equal(1, m.Value), m => Assert.Equal(-1, m.Value), m => Assert.Equal(1, m.Value), m => Assert.Equal(-1, m.Value)); - Assert.Collection(currentRequestsRecorder2.GetMeasurementSnapshot(), + Assert.Collection(activeRequestsCollector2.GetMeasurementSnapshot(), m => Assert.Equal(1, m.Value), m => Assert.Equal(-1, m.Value), m => Assert.Equal(1, m.Value), m => Assert.Equal(-1, m.Value)); - Assert.Collection(requestDurationRecorder1.GetMeasurementSnapshot(), + Assert.Collection(requestDurationCollector1.GetMeasurementSnapshot(), m => Assert.True(m.Value > 0), m => Assert.True(m.Value > 0)); - Assert.Collection(requestDurationRecorder2.GetMeasurementSnapshot(), + Assert.Collection(requestDurationCollector2.GetMeasurementSnapshot(), m => Assert.True(m.Value > 0), m => Assert.True(m.Value > 0)); } diff --git a/src/Hosting/Hosting/test/HostingMetricsTests.cs b/src/Hosting/Hosting/test/HostingMetricsTests.cs index 33598ec8abce..59d325fc3e5a 100644 --- a/src/Hosting/Hosting/test/HostingMetricsTests.cs +++ b/src/Hosting/Hosting/test/HostingMetricsTests.cs @@ -26,9 +26,8 @@ public void MultipleRequests() var httpContext = new DefaultHttpContext(); var meter = meterFactory.Meters.Single(); - using var requestDurationCollector = new MetricCollector(meterFactory, HostingMetrics.MeterName, "http-server-request-duration"); - using var currentRequestsCollector = new MetricCollector(meterFactory, HostingMetrics.MeterName, "http-server-current-requests"); - using var unhandledRequestsCollector = new MetricCollector(meterFactory, HostingMetrics.MeterName, "http-server-unhandled-requests"); + using var requestDurationCollector = new MetricCollector(meterFactory, HostingMetrics.MeterName, "http.server.duration"); + using var activeRequestsCollector = new MetricCollector(meterFactory, HostingMetrics.MeterName, "http.server.active_requests"); // Act/Assert Assert.Equal(HostingMetrics.MeterName, meter.Name); @@ -40,11 +39,11 @@ public void MultipleRequests() context1.HttpContext.Response.StatusCode = StatusCodes.Status200OK; hostingApplication.DisposeContext(context1, null); - Assert.Collection(currentRequestsCollector.GetMeasurementSnapshot(), + Assert.Collection(activeRequestsCollector.GetMeasurementSnapshot(), m => Assert.Equal(1, m.Value), m => Assert.Equal(-1, m.Value)); Assert.Collection(requestDurationCollector.GetMeasurementSnapshot(), - m => AssertRequestDuration(m, HttpProtocol.Http11, StatusCodes.Status200OK)); + m => AssertRequestDuration(m, "1.1", StatusCodes.Status200OK)); // Request 2 (after failure) httpContext.Request.Protocol = HttpProtocol.Http2; @@ -52,14 +51,14 @@ public void MultipleRequests() context2.HttpContext.Response.StatusCode = StatusCodes.Status500InternalServerError; hostingApplication.DisposeContext(context2, new InvalidOperationException("Test error")); - Assert.Collection(currentRequestsCollector.GetMeasurementSnapshot(), + Assert.Collection(activeRequestsCollector.GetMeasurementSnapshot(), m => Assert.Equal(1, m.Value), m => Assert.Equal(-1, m.Value), m => Assert.Equal(1, m.Value), m => Assert.Equal(-1, m.Value)); Assert.Collection(requestDurationCollector.GetMeasurementSnapshot(), - m => AssertRequestDuration(m, HttpProtocol.Http11, StatusCodes.Status200OK), - m => AssertRequestDuration(m, HttpProtocol.Http2, StatusCodes.Status500InternalServerError, exceptionName: "System.InvalidOperationException")); + m => AssertRequestDuration(m, "1.1", StatusCodes.Status200OK), + m => AssertRequestDuration(m, "2", StatusCodes.Status500InternalServerError, exceptionName: "System.InvalidOperationException")); // Request 3 httpContext.Request.Protocol = HttpProtocol.Http3; @@ -67,19 +66,19 @@ public void MultipleRequests() context3.HttpContext.Items["__RequestUnhandled"] = true; context3.HttpContext.Response.StatusCode = StatusCodes.Status404NotFound; - Assert.Collection(currentRequestsCollector.GetMeasurementSnapshot(), + Assert.Collection(activeRequestsCollector.GetMeasurementSnapshot(), m => Assert.Equal(1, m.Value), m => Assert.Equal(-1, m.Value), m => Assert.Equal(1, m.Value), m => Assert.Equal(-1, m.Value), m => Assert.Equal(1, m.Value)); Assert.Collection(requestDurationCollector.GetMeasurementSnapshot(), - m => AssertRequestDuration(m, HttpProtocol.Http11, StatusCodes.Status200OK), - m => AssertRequestDuration(m, HttpProtocol.Http2, StatusCodes.Status500InternalServerError, exceptionName: "System.InvalidOperationException")); + m => AssertRequestDuration(m, "1.1", StatusCodes.Status200OK), + m => AssertRequestDuration(m, "2", StatusCodes.Status500InternalServerError, exceptionName: "System.InvalidOperationException")); hostingApplication.DisposeContext(context3, null); - Assert.Collection(currentRequestsCollector.GetMeasurementSnapshot(), + Assert.Collection(activeRequestsCollector.GetMeasurementSnapshot(), m => Assert.Equal(1, m.Value), m => Assert.Equal(-1, m.Value), m => Assert.Equal(1, m.Value), @@ -87,24 +86,31 @@ public void MultipleRequests() m => Assert.Equal(1, m.Value), m => Assert.Equal(-1, m.Value)); Assert.Collection(requestDurationCollector.GetMeasurementSnapshot(), - m => AssertRequestDuration(m, HttpProtocol.Http11, StatusCodes.Status200OK), - m => AssertRequestDuration(m, HttpProtocol.Http2, StatusCodes.Status500InternalServerError, exceptionName: "System.InvalidOperationException"), - m => AssertRequestDuration(m, HttpProtocol.Http3, StatusCodes.Status404NotFound)); - Assert.Collection(unhandledRequestsCollector.GetMeasurementSnapshot(), - m => Assert.Equal(1, m.Value)); + m => AssertRequestDuration(m, "1.1", StatusCodes.Status200OK), + m => AssertRequestDuration(m, "2", StatusCodes.Status500InternalServerError, exceptionName: "System.InvalidOperationException"), + m => AssertRequestDuration(m, "3", StatusCodes.Status404NotFound, unhandledRequest: true)); - static void AssertRequestDuration(CollectedMeasurement measurement, string protocol, int statusCode, string exceptionName = null) + static void AssertRequestDuration(CollectedMeasurement measurement, string httpVersion, int statusCode, string exceptionName = null, bool? unhandledRequest = null) { Assert.True(measurement.Value > 0); - Assert.Equal(protocol, (string)measurement.Tags["protocol"]); - Assert.Equal(statusCode, (int)measurement.Tags["status-code"]); + Assert.Equal("http", (string)measurement.Tags["network.protocol.name"]); + Assert.Equal(httpVersion, (string)measurement.Tags["network.protocol.version"]); + Assert.Equal(statusCode, (int)measurement.Tags["http.response.status_code"]); if (exceptionName == null) { - Assert.DoesNotContain(measurement.Tags.ToArray(), t => t.Key == "exception-name"); + Assert.DoesNotContain(measurement.Tags.ToArray(), t => t.Key == "exception.type"); + } + else + { + Assert.Equal(exceptionName, (string)measurement.Tags["exception.type"]); + } + if (unhandledRequest ?? false) + { + Assert.True((bool)measurement.Tags["aspnet.request.is_unhandled"]); } else { - Assert.Equal(exceptionName, (string)measurement.Tags.ToArray().Single(t => t.Key == "exception-name").Value); + Assert.DoesNotContain(measurement.Tags.ToArray(), t => t.Key == "aspnet.request.is_unhandled"); } } } @@ -133,8 +139,8 @@ public async Task StartListeningDuringRequest_NotMeasured() await syncPoint.WaitForSyncPoint().DefaultTimeout(); - using var requestDurationCollector = new MetricCollector(meterFactory, HostingMetrics.MeterName, "http-server-request-duration"); - using var currentRequestsCollector = new MetricCollector(meterFactory, HostingMetrics.MeterName, "http-server-current-requests"); + using var requestDurationCollector = new MetricCollector(meterFactory, HostingMetrics.MeterName, "http.server.duration"); + using var currentRequestsCollector = new MetricCollector(meterFactory, HostingMetrics.MeterName, "http.server.active_requests"); context1.HttpContext.Response.StatusCode = StatusCodes.Status200OK; syncPoint.Continue(); @@ -155,8 +161,8 @@ public void IHttpMetricsTagsFeatureNotUsedFromFeatureCollection() var httpContext = new DefaultHttpContext(); var meter = meterFactory.Meters.Single(); - using var requestDurationCollector = new MetricCollector(meterFactory, HostingMetrics.MeterName, "http-server-request-duration"); - using var currentRequestsCollector = new MetricCollector(meterFactory, HostingMetrics.MeterName, "http-server-current-requests"); + using var requestDurationCollector = new MetricCollector(meterFactory, HostingMetrics.MeterName, "http.server.duration"); + using var currentRequestsCollector = new MetricCollector(meterFactory, HostingMetrics.MeterName, "http.server.active_requests"); // Act/Assert Assert.Equal(HostingMetrics.MeterName, meter.Name); From 9bf404cccc2201013cc5c2023f6fa506b587c572 Mon Sep 17 00:00:00 2001 From: James Newton-King Date: Mon, 31 Jul 2023 14:58:39 +0800 Subject: [PATCH 02/13] Diagnostics exception handler --- .../Diagnostics/src/DiagnosticsMetrics.cs | 23 ++++++++++++++++--- .../Diagnostics/src/DiagnosticsTelemetry.cs | 2 +- .../DeveloperExceptionPageMiddlewareTest.cs | 12 +++++----- .../ExceptionHandlerMiddlewareTest.cs | 10 ++++---- .../test/UnitTests/ExceptionHandlerTest.cs | 6 ++--- src/Middleware/Middleware.slnf | 3 +++ 6 files changed, 38 insertions(+), 18 deletions(-) diff --git a/src/Middleware/Diagnostics/src/DiagnosticsMetrics.cs b/src/Middleware/Diagnostics/src/DiagnosticsMetrics.cs index f77ab2050e4f..e61fe95654a0 100644 --- a/src/Middleware/Diagnostics/src/DiagnosticsMetrics.cs +++ b/src/Middleware/Diagnostics/src/DiagnosticsMetrics.cs @@ -22,7 +22,7 @@ public DiagnosticsMetrics(IMeterFactory meterFactory) _meter = meterFactory.Create(MeterName); _handlerExceptionCounter = _meter.CreateCounter( - "diagnostics-handler-exception", + "aspnet.diagnostics_handler.exceptions", description: "Number of exceptions caught by exception handling middleware."); } @@ -38,14 +38,31 @@ public void RequestException(string exceptionName, ExceptionResult result, strin private void RequestExceptionCore(string exceptionName, ExceptionResult result, string? handler) { var tags = new TagList(); - tags.Add("exception-name", exceptionName); - tags.Add("result", result.ToString()); + tags.Add("exception.type", exceptionName); + tags.Add("result", GetExceptionResult(result)); if (handler != null) { tags.Add("handler", 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 diff --git a/src/Middleware/Diagnostics/src/DiagnosticsTelemetry.cs b/src/Middleware/Diagnostics/src/DiagnosticsTelemetry.cs index 28e0db455fd9..5a319af79c6e 100644 --- a/src/Middleware/Diagnostics/src/DiagnosticsTelemetry.cs +++ b/src/Middleware/Diagnostics/src/DiagnosticsTelemetry.cs @@ -15,7 +15,7 @@ public static void ReportUnhandledException(ILogger logger, HttpContext context, if (context.Features.Get() is { } tagsFeature) { - tagsFeature.Tags.Add(new KeyValuePair("exception-name", ex.GetType().FullName)); + tagsFeature.Tags.Add(new KeyValuePair("exception.type", ex.GetType().FullName)); } } } diff --git a/src/Middleware/Diagnostics/test/UnitTests/DeveloperExceptionPageMiddlewareTest.cs b/src/Middleware/Diagnostics/test/UnitTests/DeveloperExceptionPageMiddlewareTest.cs index dc80c53efb6a..74d216d1b16b 100644 --- a/src/Middleware/Diagnostics/test/UnitTests/DeveloperExceptionPageMiddlewareTest.cs +++ b/src/Middleware/Diagnostics/test/UnitTests/DeveloperExceptionPageMiddlewareTest.cs @@ -540,8 +540,8 @@ public async Task UnhandledError_ExceptionNameTagAdded() { // Arrange var meterFactory = new TestMeterFactory(); - using var requestDurationCollector = new MetricCollector(meterFactory, "Microsoft.AspNetCore.Hosting", "http-server-request-duration"); - using var requestExceptionCollector = new MetricCollector(meterFactory, DiagnosticsMetrics.MeterName, "diagnostics-handler-exception"); + using var requestDurationCollector = new MetricCollector(meterFactory, "Microsoft.AspNetCore.Hosting", "http.server.duration"); + using var requestExceptionCollector = new MetricCollector(meterFactory, DiagnosticsMetrics.MeterName, "aspnet.diagnostics_handler.exceptions"); using var host = new HostBuilder() .ConfigureServices(s => @@ -579,17 +579,17 @@ public async Task UnhandledError_ExceptionNameTagAdded() m => { Assert.True(m.Value > 0); - Assert.Equal(500, (int)m.Tags.ToArray().Single(t => t.Key == "status-code").Value); - Assert.Equal("System.Exception", (string)m.Tags.ToArray().Single(t => t.Key == "exception-name").Value); + Assert.Equal(500, (int)m.Tags["http.response.status_code"]); + Assert.Equal("System.Exception", (string)m.Tags["exception.type"]); }); Assert.Collection(requestExceptionCollector.GetMeasurementSnapshot(), - m => AssertRequestException(m, "System.Exception", "Unhandled")); + m => AssertRequestException(m, "System.Exception", "unhandled")); } private static void AssertRequestException(CollectedMeasurement measurement, string exceptionName, string result, string handler = null) { Assert.Equal(1, measurement.Value); - Assert.Equal(exceptionName, (string)measurement.Tags["exception-name"]); + Assert.Equal(exceptionName, (string)measurement.Tags["exception.type"]); Assert.Equal(result, measurement.Tags["result"].ToString()); if (handler == null) { diff --git a/src/Middleware/Diagnostics/test/UnitTests/ExceptionHandlerMiddlewareTest.cs b/src/Middleware/Diagnostics/test/UnitTests/ExceptionHandlerMiddlewareTest.cs index 0a0b0fcf9c29..627f6a111a13 100644 --- a/src/Middleware/Diagnostics/test/UnitTests/ExceptionHandlerMiddlewareTest.cs +++ b/src/Middleware/Diagnostics/test/UnitTests/ExceptionHandlerMiddlewareTest.cs @@ -211,7 +211,7 @@ public async Task Metrics_NoExceptionThrown() var middleware = CreateMiddleware(_ => Task.CompletedTask, optionsAccessor, exceptionHandlers, meterFactory); var meter = meterFactory.Meters.Single(); - using var diagnosticsRequestExceptionCollector = new MetricCollector(meterFactory, DiagnosticsMetrics.MeterName, "diagnostics-handler-exception"); + using var diagnosticsRequestExceptionCollector = new MetricCollector(meterFactory, DiagnosticsMetrics.MeterName, "aspnet.diagnostics_handler.exceptions"); // Act await middleware.Invoke(httpContext); @@ -234,7 +234,7 @@ public async Task Metrics_ExceptionThrown_Handled_Reported() var middleware = CreateMiddleware(_ => throw new InvalidOperationException(), optionsAccessor, exceptionHandlers, meterFactory); var meter = meterFactory.Meters.Single(); - using var diagnosticsRequestExceptionCollector = new MetricCollector(meterFactory, DiagnosticsMetrics.MeterName, "diagnostics-handler-exception"); + using var diagnosticsRequestExceptionCollector = new MetricCollector(meterFactory, DiagnosticsMetrics.MeterName, "aspnet.diagnostics_handler.exceptions"); // Act await middleware.Invoke(httpContext); @@ -256,7 +256,7 @@ public async Task Metrics_ExceptionThrown_ResponseStarted_Skipped() var middleware = CreateMiddleware(_ => throw new InvalidOperationException(), optionsAccessor, exceptionHandlers, meterFactory); var meter = meterFactory.Meters.Single(); - using var diagnosticsRequestExceptionCollector = new MetricCollector(meterFactory, DiagnosticsMetrics.MeterName, "diagnostics-handler-exception"); + using var diagnosticsRequestExceptionCollector = new MetricCollector(meterFactory, DiagnosticsMetrics.MeterName, "aspnet.diagnostics_handler.exceptions"); // Act await Assert.ThrowsAsync(() => middleware.Invoke(httpContext)); @@ -281,7 +281,7 @@ public async Task Metrics_ExceptionThrown_DefaultSettings_Handled_Reported() var middleware = CreateMiddleware(_ => throw new InvalidOperationException(), optionsAccessor, meterFactory: meterFactory); var meter = meterFactory.Meters.Single(); - using var diagnosticsRequestExceptionCollector = new MetricCollector(meterFactory, DiagnosticsMetrics.MeterName, "diagnostics-handler-exception"); + using var diagnosticsRequestExceptionCollector = new MetricCollector(meterFactory, DiagnosticsMetrics.MeterName, "aspnet.diagnostics_handler.exceptions"); // Act await middleware.Invoke(httpContext); @@ -305,7 +305,7 @@ public async Task Metrics_ExceptionThrown_Unhandled_Reported() var middleware = CreateMiddleware(_ => throw new InvalidOperationException(), optionsAccessor, meterFactory: meterFactory); var meter = meterFactory.Meters.Single(); - using var diagnosticsRequestExceptionCollector = new MetricCollector(meterFactory, DiagnosticsMetrics.MeterName, "diagnostics-handler-exception"); + using var diagnosticsRequestExceptionCollector = new MetricCollector(meterFactory, DiagnosticsMetrics.MeterName, "aspnet.diagnostics_handler.exceptions"); // Act await Assert.ThrowsAsync(() => middleware.Invoke(httpContext)); diff --git a/src/Middleware/Diagnostics/test/UnitTests/ExceptionHandlerTest.cs b/src/Middleware/Diagnostics/test/UnitTests/ExceptionHandlerTest.cs index ec2eea50d192..b55aca5326af 100644 --- a/src/Middleware/Diagnostics/test/UnitTests/ExceptionHandlerTest.cs +++ b/src/Middleware/Diagnostics/test/UnitTests/ExceptionHandlerTest.cs @@ -917,7 +917,7 @@ public async Task UnhandledError_ExceptionNameTagAdded() { // Arrange var meterFactory = new TestMeterFactory(); - using var instrumentCollector = new MetricCollector(meterFactory, "Microsoft.AspNetCore.Hosting", "http-server-request-duration"); + using var instrumentCollector = new MetricCollector(meterFactory, "Microsoft.AspNetCore.Hosting", "http.server.duration"); using var host = new HostBuilder() .ConfigureServices(s => @@ -961,8 +961,8 @@ public async Task UnhandledError_ExceptionNameTagAdded() m => { Assert.True(m.Value > 0); - Assert.Equal(404, (int)m.Tags.ToArray().Single(t => t.Key == "status-code").Value); - Assert.Equal("System.Exception", (string)m.Tags.ToArray().Single(t => t.Key == "exception-name").Value); + Assert.Equal(404, (int)m.Tags["http.response.status_code"]); + Assert.Equal("System.Exception", (string)m.Tags["exception.type"]); }); } } diff --git a/src/Middleware/Middleware.slnf b/src/Middleware/Middleware.slnf index fd9d1ba17db3..2c64128c9144 100644 --- a/src/Middleware/Middleware.slnf +++ b/src/Middleware/Middleware.slnf @@ -16,6 +16,8 @@ "src\\Extensions\\Features\\src\\Microsoft.Extensions.Features.csproj", "src\\FileProviders\\Embedded\\src\\Microsoft.Extensions.FileProviders.Embedded.csproj", "src\\FileProviders\\Manifest.MSBuildTask\\src\\Microsoft.Extensions.FileProviders.Embedded.Manifest.Task.csproj", + "src\\HealthChecks\\Abstractions\\src\\Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions.csproj", + "src\\HealthChecks\\HealthChecks\\src\\Microsoft.Extensions.Diagnostics.HealthChecks.csproj", "src\\Hosting\\Abstractions\\src\\Microsoft.AspNetCore.Hosting.Abstractions.csproj", "src\\Hosting\\Hosting\\src\\Microsoft.AspNetCore.Hosting.csproj", "src\\Hosting\\Server.Abstractions\\src\\Microsoft.AspNetCore.Hosting.Server.Abstractions.csproj", @@ -28,6 +30,7 @@ "src\\Http\\Http.Abstractions\\src\\Microsoft.AspNetCore.Http.Abstractions.csproj", "src\\Http\\Http.Extensions\\src\\Microsoft.AspNetCore.Http.Extensions.csproj", "src\\Http\\Http.Features\\src\\Microsoft.AspNetCore.Http.Features.csproj", + "src\\Http\\Http.Results\\src\\Microsoft.AspNetCore.Http.Results.csproj", "src\\Http\\Http\\src\\Microsoft.AspNetCore.Http.csproj", "src\\Http\\Metadata\\src\\Microsoft.AspNetCore.Metadata.csproj", "src\\Http\\Routing.Abstractions\\src\\Microsoft.AspNetCore.Routing.Abstractions.csproj", From 15e988cf2b77f439151f50d6857b40d29535dedb Mon Sep 17 00:00:00 2001 From: James Newton-King Date: Mon, 31 Jul 2023 15:03:21 +0800 Subject: [PATCH 03/13] Fix tests --- .../test/UnitTests/ExceptionHandlerMiddlewareTest.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Middleware/Diagnostics/test/UnitTests/ExceptionHandlerMiddlewareTest.cs b/src/Middleware/Diagnostics/test/UnitTests/ExceptionHandlerMiddlewareTest.cs index 627f6a111a13..08f097e9da9f 100644 --- a/src/Middleware/Diagnostics/test/UnitTests/ExceptionHandlerMiddlewareTest.cs +++ b/src/Middleware/Diagnostics/test/UnitTests/ExceptionHandlerMiddlewareTest.cs @@ -241,7 +241,7 @@ public async Task Metrics_ExceptionThrown_Handled_Reported() // Assert Assert.Collection(diagnosticsRequestExceptionCollector.GetMeasurementSnapshot(), - m => AssertRequestException(m, "System.InvalidOperationException", "Handled", typeof(TestExceptionHandler).FullName)); + m => AssertRequestException(m, "System.InvalidOperationException", "handled", typeof(TestExceptionHandler).FullName)); } [Fact] @@ -263,7 +263,7 @@ public async Task Metrics_ExceptionThrown_ResponseStarted_Skipped() // Assert Assert.Collection(diagnosticsRequestExceptionCollector.GetMeasurementSnapshot(), - m => AssertRequestException(m, "System.InvalidOperationException", "Skipped")); + m => AssertRequestException(m, "System.InvalidOperationException", "skipped")); } private sealed class TestResponseFeature : HttpResponseFeature @@ -288,7 +288,7 @@ public async Task Metrics_ExceptionThrown_DefaultSettings_Handled_Reported() // Assert Assert.Collection(diagnosticsRequestExceptionCollector.GetMeasurementSnapshot(), - m => AssertRequestException(m, "System.InvalidOperationException", "Handled", null)); + m => AssertRequestException(m, "System.InvalidOperationException", "handled", null)); } [Fact] @@ -312,13 +312,13 @@ public async Task Metrics_ExceptionThrown_Unhandled_Reported() // Assert Assert.Collection(diagnosticsRequestExceptionCollector.GetMeasurementSnapshot(), - m => AssertRequestException(m, "System.InvalidOperationException", "Unhandled")); + m => AssertRequestException(m, "System.InvalidOperationException", "unhandled")); } private static void AssertRequestException(CollectedMeasurement measurement, string exceptionName, string result, string handler = null) { Assert.Equal(1, measurement.Value); - Assert.Equal(exceptionName, (string)measurement.Tags["exception-name"]); + Assert.Equal(exceptionName, (string)measurement.Tags["exception.type"]); Assert.Equal(result, measurement.Tags["result"].ToString()); if (handler == null) { From bd95d3419f8af987f0ad1cf24069116074f336a8 Mon Sep 17 00:00:00 2001 From: James Newton-King Date: Mon, 31 Jul 2023 15:05:08 +0800 Subject: [PATCH 04/13] Fix other --- src/Hosting/Hosting/src/Internal/HostingMetrics.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Hosting/Hosting/src/Internal/HostingMetrics.cs b/src/Hosting/Hosting/src/Internal/HostingMetrics.cs index 3cbfa300ccae..ddc08677b54b 100644 --- a/src/Hosting/Hosting/src/Internal/HostingMetrics.cs +++ b/src/Hosting/Hosting/src/Internal/HostingMetrics.cs @@ -217,7 +217,7 @@ private static string ResolveHttpMethod(string method) // KnownMethods ignores case. Use the value returned by the dictionary to have a consistent case. return result; } - return "_UNKNOWN"; + return "_OTHER"; } private static bool TryGetHttpVersion(string protocol, [NotNullWhen(true)] out string? version) From 082a313098dccc5d666e727635b14a562e5ba790 Mon Sep 17 00:00:00 2001 From: James Newton-King Date: Mon, 31 Jul 2023 20:45:50 +0800 Subject: [PATCH 05/13] Routing --- src/Http/Routing/src/RoutingMetrics.cs | 25 ++++++------ .../test/UnitTests/RoutingMetricsTests.cs | 38 +++++++++---------- 2 files changed, 29 insertions(+), 34 deletions(-) diff --git a/src/Http/Routing/src/RoutingMetrics.cs b/src/Http/Routing/src/RoutingMetrics.cs index fd0f72a97aab..48bd2002303b 100644 --- a/src/Http/Routing/src/RoutingMetrics.cs +++ b/src/Http/Routing/src/RoutingMetrics.cs @@ -10,33 +10,30 @@ internal sealed class RoutingMetrics public const string MeterName = "Microsoft.AspNetCore.Routing"; private readonly Meter _meter; - private readonly Counter _matchSuccessCounter; - private readonly Counter _matchFailureCounter; + private readonly Counter _matchAttemptsCounter; public RoutingMetrics(IMeterFactory meterFactory) { _meter = meterFactory.Create(MeterName); - _matchSuccessCounter = _meter.CreateCounter( - "routing-match-success", - description: "Number of requests that successfully matched to an endpoint."); - - _matchFailureCounter = _meter.CreateCounter( - "routing-match-failure", - description: "Number of requests that failed to match to an endpoint. An unmatched request may be handled by later middleware, such as the static files or authentication middleware."); + _matchAttemptsCounter = _meter.CreateCounter( + "aspnet.routing.match_attempts", + description: "Number of requests that were attempted to be matched to an endpoint."); } - public bool MatchSuccessCounterEnabled => _matchSuccessCounter.Enabled; + public bool MatchSuccessCounterEnabled => _matchAttemptsCounter.Enabled; public void MatchSuccess(string route, bool isFallback) { - _matchSuccessCounter.Add(1, - new KeyValuePair("route", route), - new KeyValuePair("fallback", isFallback)); + _matchAttemptsCounter.Add(1, + new KeyValuePair("http.route", route), + new KeyValuePair("aspnet.routing.match_status", "success"), + new KeyValuePair("aspnet.routing.route.is_fallback", isFallback)); } public void MatchFailure() { - _matchFailureCounter.Add(1); + _matchAttemptsCounter.Add(1, + new KeyValuePair("aspnet.routing.match_status", "failure")); } } diff --git a/src/Http/Routing/test/UnitTests/RoutingMetricsTests.cs b/src/Http/Routing/test/UnitTests/RoutingMetricsTests.cs index e8338013317b..4b625a803a10 100644 --- a/src/Http/Routing/test/UnitTests/RoutingMetricsTests.cs +++ b/src/Http/Routing/test/UnitTests/RoutingMetricsTests.cs @@ -9,7 +9,6 @@ using Microsoft.AspNetCore.Routing.Patterns; using Microsoft.AspNetCore.Routing.TestObjects; using Microsoft.AspNetCore.Testing; -using Microsoft.Extensions.Diagnostics.Metrics; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Extensions.Options; @@ -35,8 +34,7 @@ public async Task Match_Success() var httpContext = new DefaultHttpContext(); var meter = meterFactory.Meters.Single(); - using var routingMatchSuccessCollector = new MetricCollector(meterFactory, RoutingMetrics.MeterName, "routing-match-success"); - using var routingMatchFailureCollector = new MetricCollector(meterFactory, RoutingMetrics.MeterName, "routing-match-failure"); + using var routingMatchAttemptsCollector = new MetricCollector(meterFactory, RoutingMetrics.MeterName, "aspnet.routing.match_attempts"); // Act await middleware.Invoke(httpContext); @@ -45,9 +43,8 @@ public async Task Match_Success() Assert.Equal(RoutingMetrics.MeterName, meter.Name); Assert.Null(meter.Version); - Assert.Collection(routingMatchSuccessCollector.GetMeasurementSnapshot(), + Assert.Collection(routingMatchAttemptsCollector.GetMeasurementSnapshot(), m => AssertSuccess(m, "/{hi}", fallback: false)); - Assert.Empty(routingMatchFailureCollector.GetMeasurementSnapshot()); } [Theory] @@ -71,8 +68,7 @@ public async Task Match_SuccessFallback_SetTagIfPresent(bool hasFallbackMetadata var httpContext = new DefaultHttpContext(); var meter = meterFactory.Meters.Single(); - using var routingMatchSuccessCollector = new MetricCollector(meterFactory, RoutingMetrics.MeterName, "routing-match-success"); - using var routingMatchFailureCollector = new MetricCollector(meterFactory, RoutingMetrics.MeterName, "routing-match-failure"); + using var routingMatchAttemptsCollector = new MetricCollector(meterFactory, RoutingMetrics.MeterName, "aspnet.routing.match_attempts"); // Act await middleware.Invoke(httpContext); @@ -81,9 +77,8 @@ public async Task Match_SuccessFallback_SetTagIfPresent(bool hasFallbackMetadata Assert.Equal(RoutingMetrics.MeterName, meter.Name); Assert.Null(meter.Version); - Assert.Collection(routingMatchSuccessCollector.GetMeasurementSnapshot(), + Assert.Collection(routingMatchAttemptsCollector.GetMeasurementSnapshot(), m => AssertSuccess(m, "/{hi}", fallback: hasFallbackMetadata)); - Assert.Empty(routingMatchFailureCollector.GetMeasurementSnapshot()); } [Fact] @@ -100,8 +95,7 @@ public async Task Match_Success_MissingRoute() var httpContext = new DefaultHttpContext(); var meter = meterFactory.Meters.Single(); - using var routingMatchSuccessCollector = new MetricCollector(meterFactory, RoutingMetrics.MeterName, "routing-match-success"); - using var routingMatchFailureCollector = new MetricCollector(meterFactory, RoutingMetrics.MeterName, "routing-match-failure"); + using var routingMatchAttemptsCollector = new MetricCollector(meterFactory, RoutingMetrics.MeterName, "aspnet.routing.match_attempts"); // Act await middleware.Invoke(httpContext); @@ -110,9 +104,8 @@ public async Task Match_Success_MissingRoute() Assert.Equal(RoutingMetrics.MeterName, meter.Name); Assert.Null(meter.Version); - Assert.Collection(routingMatchSuccessCollector.GetMeasurementSnapshot(), + Assert.Collection(routingMatchAttemptsCollector.GetMeasurementSnapshot(), m => AssertSuccess(m, "(missing)", fallback: false)); - Assert.Empty(routingMatchFailureCollector.GetMeasurementSnapshot()); } [Fact] @@ -126,8 +119,7 @@ public async Task Match_Failure() var httpContext = new DefaultHttpContext(); var meter = meterFactory.Meters.Single(); - using var routingMatchSuccessCollector = new MetricCollector(meterFactory, RoutingMetrics.MeterName, "routing-match-success"); - using var routingMatchFailureCollector = new MetricCollector(meterFactory, RoutingMetrics.MeterName, "routing-match-failure"); + using var routingMatchAttemptsCollector = new MetricCollector(meterFactory, RoutingMetrics.MeterName, "aspnet.routing.match_attempts"); // Act await middleware.Invoke(httpContext); @@ -136,16 +128,22 @@ public async Task Match_Failure() Assert.Equal(RoutingMetrics.MeterName, meter.Name); Assert.Null(meter.Version); - Assert.Empty(routingMatchSuccessCollector.GetMeasurementSnapshot()); - Assert.Collection(routingMatchFailureCollector.GetMeasurementSnapshot(), - m => Assert.Equal(1, m.Value)); + Assert.Collection(routingMatchAttemptsCollector.GetMeasurementSnapshot(), + m => AssertFailure(m)); + } + + private void AssertFailure(CollectedMeasurement measurement) + { + Assert.Equal(1, measurement.Value); + Assert.Equal("failure", (string)measurement.Tags["aspnet.routing.match_status"]); } private void AssertSuccess(CollectedMeasurement measurement, string route, bool fallback) { Assert.Equal(1, measurement.Value); - Assert.Equal(route, (string)measurement.Tags["route"]); - Assert.Equal(fallback, (bool)measurement.Tags["fallback"]); + Assert.Equal("success", (string)measurement.Tags["aspnet.routing.match_status"]); + Assert.Equal(route, (string)measurement.Tags["http.route"]); + Assert.Equal(fallback, (bool)measurement.Tags["aspnet.routing.route.is_fallback"]); } private EndpointRoutingMiddleware CreateMiddleware( From 626c3119f8668463b43e0c0374fec13c23c2baf4 Mon Sep 17 00:00:00 2001 From: James Newton-King Date: Tue, 1 Aug 2023 09:09:31 +0800 Subject: [PATCH 06/13] PR feedback --- src/Http/Routing/src/RoutingMetrics.cs | 2 +- .../test/UnitTests/RoutingMetricsTests.cs | 2 +- .../Diagnostics/src/DiagnosticsMetrics.cs | 6 +++--- .../DeveloperExceptionPageMiddlewareTest.cs | 8 ++++---- .../UnitTests/ExceptionHandlerMiddlewareTest.cs | 16 ++++++++-------- 5 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/Http/Routing/src/RoutingMetrics.cs b/src/Http/Routing/src/RoutingMetrics.cs index 48bd2002303b..de3a17316c27 100644 --- a/src/Http/Routing/src/RoutingMetrics.cs +++ b/src/Http/Routing/src/RoutingMetrics.cs @@ -28,7 +28,7 @@ public void MatchSuccess(string route, bool isFallback) _matchAttemptsCounter.Add(1, new KeyValuePair("http.route", route), new KeyValuePair("aspnet.routing.match_status", "success"), - new KeyValuePair("aspnet.routing.route.is_fallback", isFallback)); + new KeyValuePair("aspnet.routing.is_fallback", isFallback)); } public void MatchFailure() diff --git a/src/Http/Routing/test/UnitTests/RoutingMetricsTests.cs b/src/Http/Routing/test/UnitTests/RoutingMetricsTests.cs index 4b625a803a10..701d1c311423 100644 --- a/src/Http/Routing/test/UnitTests/RoutingMetricsTests.cs +++ b/src/Http/Routing/test/UnitTests/RoutingMetricsTests.cs @@ -143,7 +143,7 @@ private void AssertSuccess(CollectedMeasurement measurement, string route, Assert.Equal(1, measurement.Value); Assert.Equal("success", (string)measurement.Tags["aspnet.routing.match_status"]); Assert.Equal(route, (string)measurement.Tags["http.route"]); - Assert.Equal(fallback, (bool)measurement.Tags["aspnet.routing.route.is_fallback"]); + Assert.Equal(fallback, (bool)measurement.Tags["aspnet.routing.is_fallback"]); } private EndpointRoutingMiddleware CreateMiddleware( diff --git a/src/Middleware/Diagnostics/src/DiagnosticsMetrics.cs b/src/Middleware/Diagnostics/src/DiagnosticsMetrics.cs index e61fe95654a0..df7f7c78c3c7 100644 --- a/src/Middleware/Diagnostics/src/DiagnosticsMetrics.cs +++ b/src/Middleware/Diagnostics/src/DiagnosticsMetrics.cs @@ -22,7 +22,7 @@ public DiagnosticsMetrics(IMeterFactory meterFactory) _meter = meterFactory.Create(MeterName); _handlerExceptionCounter = _meter.CreateCounter( - "aspnet.diagnostics_handler.exceptions", + "aspnet.diagnostics.exceptions", description: "Number of exceptions caught by exception handling middleware."); } @@ -39,10 +39,10 @@ private void RequestExceptionCore(string exceptionName, ExceptionResult result, { var tags = new TagList(); tags.Add("exception.type", exceptionName); - tags.Add("result", GetExceptionResult(result)); + tags.Add("aspnet.diagnostics.exception.result", GetExceptionResult(result)); if (handler != null) { - tags.Add("handler", handler); + tags.Add("aspnet.diagnostics.handler.type", handler); } _handlerExceptionCounter.Add(1, tags); } diff --git a/src/Middleware/Diagnostics/test/UnitTests/DeveloperExceptionPageMiddlewareTest.cs b/src/Middleware/Diagnostics/test/UnitTests/DeveloperExceptionPageMiddlewareTest.cs index 74d216d1b16b..8b5dd0d8849d 100644 --- a/src/Middleware/Diagnostics/test/UnitTests/DeveloperExceptionPageMiddlewareTest.cs +++ b/src/Middleware/Diagnostics/test/UnitTests/DeveloperExceptionPageMiddlewareTest.cs @@ -541,7 +541,7 @@ public async Task UnhandledError_ExceptionNameTagAdded() // Arrange var meterFactory = new TestMeterFactory(); using var requestDurationCollector = new MetricCollector(meterFactory, "Microsoft.AspNetCore.Hosting", "http.server.duration"); - using var requestExceptionCollector = new MetricCollector(meterFactory, DiagnosticsMetrics.MeterName, "aspnet.diagnostics_handler.exceptions"); + using var requestExceptionCollector = new MetricCollector(meterFactory, DiagnosticsMetrics.MeterName, "aspnet.diagnostics.exceptions"); using var host = new HostBuilder() .ConfigureServices(s => @@ -590,14 +590,14 @@ private static void AssertRequestException(CollectedMeasurement measuremen { Assert.Equal(1, measurement.Value); Assert.Equal(exceptionName, (string)measurement.Tags["exception.type"]); - Assert.Equal(result, measurement.Tags["result"].ToString()); + Assert.Equal(result, measurement.Tags["aspnet.diagnostics.exception.result"].ToString()); if (handler == null) { - Assert.False(measurement.Tags.ContainsKey("handler")); + Assert.False(measurement.Tags.ContainsKey("aspnet.diagnostics.handler.type")); } else { - Assert.Equal(handler, (string)measurement.Tags["handler"]); + Assert.Equal(handler, (string)measurement.Tags["aspnet.diagnostics.handler.type"]); } } diff --git a/src/Middleware/Diagnostics/test/UnitTests/ExceptionHandlerMiddlewareTest.cs b/src/Middleware/Diagnostics/test/UnitTests/ExceptionHandlerMiddlewareTest.cs index 08f097e9da9f..f4e1d5ed1e3f 100644 --- a/src/Middleware/Diagnostics/test/UnitTests/ExceptionHandlerMiddlewareTest.cs +++ b/src/Middleware/Diagnostics/test/UnitTests/ExceptionHandlerMiddlewareTest.cs @@ -211,7 +211,7 @@ public async Task Metrics_NoExceptionThrown() var middleware = CreateMiddleware(_ => Task.CompletedTask, optionsAccessor, exceptionHandlers, meterFactory); var meter = meterFactory.Meters.Single(); - using var diagnosticsRequestExceptionCollector = new MetricCollector(meterFactory, DiagnosticsMetrics.MeterName, "aspnet.diagnostics_handler.exceptions"); + using var diagnosticsRequestExceptionCollector = new MetricCollector(meterFactory, DiagnosticsMetrics.MeterName, "aspnet.diagnostics.exceptions"); // Act await middleware.Invoke(httpContext); @@ -234,7 +234,7 @@ public async Task Metrics_ExceptionThrown_Handled_Reported() var middleware = CreateMiddleware(_ => throw new InvalidOperationException(), optionsAccessor, exceptionHandlers, meterFactory); var meter = meterFactory.Meters.Single(); - using var diagnosticsRequestExceptionCollector = new MetricCollector(meterFactory, DiagnosticsMetrics.MeterName, "aspnet.diagnostics_handler.exceptions"); + using var diagnosticsRequestExceptionCollector = new MetricCollector(meterFactory, DiagnosticsMetrics.MeterName, "aspnet.diagnostics.exceptions"); // Act await middleware.Invoke(httpContext); @@ -256,7 +256,7 @@ public async Task Metrics_ExceptionThrown_ResponseStarted_Skipped() var middleware = CreateMiddleware(_ => throw new InvalidOperationException(), optionsAccessor, exceptionHandlers, meterFactory); var meter = meterFactory.Meters.Single(); - using var diagnosticsRequestExceptionCollector = new MetricCollector(meterFactory, DiagnosticsMetrics.MeterName, "aspnet.diagnostics_handler.exceptions"); + using var diagnosticsRequestExceptionCollector = new MetricCollector(meterFactory, DiagnosticsMetrics.MeterName, "aspnet.diagnostics.exceptions"); // Act await Assert.ThrowsAsync(() => middleware.Invoke(httpContext)); @@ -281,7 +281,7 @@ public async Task Metrics_ExceptionThrown_DefaultSettings_Handled_Reported() var middleware = CreateMiddleware(_ => throw new InvalidOperationException(), optionsAccessor, meterFactory: meterFactory); var meter = meterFactory.Meters.Single(); - using var diagnosticsRequestExceptionCollector = new MetricCollector(meterFactory, DiagnosticsMetrics.MeterName, "aspnet.diagnostics_handler.exceptions"); + using var diagnosticsRequestExceptionCollector = new MetricCollector(meterFactory, DiagnosticsMetrics.MeterName, "aspnet.diagnostics.exceptions"); // Act await middleware.Invoke(httpContext); @@ -305,7 +305,7 @@ public async Task Metrics_ExceptionThrown_Unhandled_Reported() var middleware = CreateMiddleware(_ => throw new InvalidOperationException(), optionsAccessor, meterFactory: meterFactory); var meter = meterFactory.Meters.Single(); - using var diagnosticsRequestExceptionCollector = new MetricCollector(meterFactory, DiagnosticsMetrics.MeterName, "aspnet.diagnostics_handler.exceptions"); + using var diagnosticsRequestExceptionCollector = new MetricCollector(meterFactory, DiagnosticsMetrics.MeterName, "aspnet.diagnostics.exceptions"); // Act await Assert.ThrowsAsync(() => middleware.Invoke(httpContext)); @@ -319,14 +319,14 @@ private static void AssertRequestException(CollectedMeasurement measuremen { Assert.Equal(1, measurement.Value); Assert.Equal(exceptionName, (string)measurement.Tags["exception.type"]); - Assert.Equal(result, measurement.Tags["result"].ToString()); + Assert.Equal(result, measurement.Tags["aspnet.diagnostics.exception.result"].ToString()); if (handler == null) { - Assert.False(measurement.Tags.ContainsKey("handler")); + Assert.False(measurement.Tags.ContainsKey("aspnet.diagnostics.handler.type")); } else { - Assert.Equal(handler, (string)measurement.Tags["handler"]); + Assert.Equal(handler, (string)measurement.Tags["aspnet.diagnostics.handler.type"]); } } From 68b8b662f9026638b6afd413d78ad6cb110c5765 Mon Sep 17 00:00:00 2001 From: James Newton-King Date: Tue, 1 Aug 2023 09:32:48 +0800 Subject: [PATCH 07/13] PR feedback --- src/Hosting/Hosting/src/Internal/HostingMetrics.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Hosting/Hosting/src/Internal/HostingMetrics.cs b/src/Hosting/Hosting/src/Internal/HostingMetrics.cs index ddc08677b54b..8937d56f28c7 100644 --- a/src/Hosting/Hosting/src/Internal/HostingMetrics.cs +++ b/src/Hosting/Hosting/src/Internal/HostingMetrics.cs @@ -99,6 +99,9 @@ private static void InitializeRequestTags(ref TagList tags, bool isHttps, string { tags.Add("url.scheme", scheme); tags.Add("http.request.method", ResolveHttpMethod(method)); + + // TODO: Support configuration for enabling host header annotations + /* if (host.HasValue) { tags.Add("server.address", host.Host); @@ -113,6 +116,7 @@ private static void InitializeRequestTags(ref TagList tags, bool isHttps, string } } } + */ } // Status Codes listed at http://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml @@ -212,6 +216,7 @@ private static object GetBoxedStatusCode(int statusCode) private static string ResolveHttpMethod(string method) { + // TODO: Support configuration for configuring known methods if (KnownMethods.TryGetValue(method, out var result)) { // KnownMethods ignores case. Use the value returned by the dictionary to have a consistent case. From 9cfa262e1b6da30f632287c5f6123a34cbd0cde8 Mon Sep 17 00:00:00 2001 From: James Newton-King Date: Tue, 1 Aug 2023 09:53:45 +0800 Subject: [PATCH 08/13] Fix build --- src/Hosting/Hosting/src/Internal/HostingMetrics.cs | 2 ++ src/Hosting/Hosting/test/HostingMetricsTests.cs | 5 ++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Hosting/Hosting/src/Internal/HostingMetrics.cs b/src/Hosting/Hosting/src/Internal/HostingMetrics.cs index 8937d56f28c7..5da9c665f1cd 100644 --- a/src/Hosting/Hosting/src/Internal/HostingMetrics.cs +++ b/src/Hosting/Hosting/src/Internal/HostingMetrics.cs @@ -100,6 +100,8 @@ private static void InitializeRequestTags(ref TagList tags, bool isHttps, string tags.Add("url.scheme", scheme); tags.Add("http.request.method", ResolveHttpMethod(method)); + _ = isHttps; + _ = host; // TODO: Support configuration for enabling host header annotations /* if (host.HasValue) diff --git a/src/Hosting/Hosting/test/HostingMetricsTests.cs b/src/Hosting/Hosting/test/HostingMetricsTests.cs index 59d325fc3e5a..fca2caef8451 100644 --- a/src/Hosting/Hosting/test/HostingMetricsTests.cs +++ b/src/Hosting/Hosting/test/HostingMetricsTests.cs @@ -9,7 +9,6 @@ using Microsoft.AspNetCore.Internal; using Microsoft.AspNetCore.Testing; using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Diagnostics.Metrics; using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Extensions.Telemetry.Testing.Metering; @@ -98,7 +97,7 @@ static void AssertRequestDuration(CollectedMeasurement measurement, stri Assert.Equal(statusCode, (int)measurement.Tags["http.response.status_code"]); if (exceptionName == null) { - Assert.DoesNotContain(measurement.Tags.ToArray(), t => t.Key == "exception.type"); + Assert.False(measurement.Tags.ContainsKey("exception.type")); } else { @@ -110,7 +109,7 @@ static void AssertRequestDuration(CollectedMeasurement measurement, stri } else { - Assert.DoesNotContain(measurement.Tags.ToArray(), t => t.Key == "aspnet.request.is_unhandled"); + Assert.False(measurement.Tags.ContainsKey("aspnet.request.is_unhandled")); } } } From 5856e2503ce33c173d1fec3941ad6681c9925420 Mon Sep 17 00:00:00 2001 From: James Newton-King Date: Wed, 2 Aug 2023 11:59:44 +0800 Subject: [PATCH 09/13] Update name to http.server.request.duration --- src/Hosting/Hosting/src/Internal/HostingMetrics.cs | 2 +- .../Hosting/test/HostingApplicationDiagnosticsTests.cs | 4 ++-- src/Hosting/Hosting/test/HostingMetricsTests.cs | 6 +++--- .../test/UnitTests/DeveloperExceptionPageMiddlewareTest.cs | 2 +- .../Diagnostics/test/UnitTests/ExceptionHandlerTest.cs | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/Hosting/Hosting/src/Internal/HostingMetrics.cs b/src/Hosting/Hosting/src/Internal/HostingMetrics.cs index 5da9c665f1cd..788561b47e97 100644 --- a/src/Hosting/Hosting/src/Internal/HostingMetrics.cs +++ b/src/Hosting/Hosting/src/Internal/HostingMetrics.cs @@ -26,7 +26,7 @@ public HostingMetrics(IMeterFactory meterFactory) description: "Number of HTTP requests that are currently active on the server."); _requestDuration = _meter.CreateHistogram( - "http.server.duration", + "http.server.request.duration", unit: "s", description: "Measures the duration of inbound HTTP requests."); } diff --git a/src/Hosting/Hosting/test/HostingApplicationDiagnosticsTests.cs b/src/Hosting/Hosting/test/HostingApplicationDiagnosticsTests.cs index e37184c788b8..08465dd8547d 100644 --- a/src/Hosting/Hosting/test/HostingApplicationDiagnosticsTests.cs +++ b/src/Hosting/Hosting/test/HostingApplicationDiagnosticsTests.cs @@ -55,8 +55,8 @@ public async Task EventCountersAndMetricsValues() using var activeRequestsCollector1 = new MetricCollector(testMeterFactory1, HostingMetrics.MeterName, "http.server.active_requests"); using var activeRequestsCollector2 = new MetricCollector(testMeterFactory2, HostingMetrics.MeterName, "http.server.active_requests"); - using var requestDurationCollector1 = new MetricCollector(testMeterFactory1, HostingMetrics.MeterName, "http.server.duration"); - using var requestDurationCollector2 = new MetricCollector(testMeterFactory2, HostingMetrics.MeterName, "http.server.duration"); + using var requestDurationCollector1 = new MetricCollector(testMeterFactory1, HostingMetrics.MeterName, "http.server.request.duration"); + using var requestDurationCollector2 = new MetricCollector(testMeterFactory2, HostingMetrics.MeterName, "http.server.request.duration"); // Act/Assert 1 var context1 = hostingApplication1.CreateContext(features1); diff --git a/src/Hosting/Hosting/test/HostingMetricsTests.cs b/src/Hosting/Hosting/test/HostingMetricsTests.cs index fca2caef8451..7ae9edcecd3d 100644 --- a/src/Hosting/Hosting/test/HostingMetricsTests.cs +++ b/src/Hosting/Hosting/test/HostingMetricsTests.cs @@ -25,7 +25,7 @@ public void MultipleRequests() var httpContext = new DefaultHttpContext(); var meter = meterFactory.Meters.Single(); - using var requestDurationCollector = new MetricCollector(meterFactory, HostingMetrics.MeterName, "http.server.duration"); + using var requestDurationCollector = new MetricCollector(meterFactory, HostingMetrics.MeterName, "http.server.request.duration"); using var activeRequestsCollector = new MetricCollector(meterFactory, HostingMetrics.MeterName, "http.server.active_requests"); // Act/Assert @@ -138,7 +138,7 @@ public async Task StartListeningDuringRequest_NotMeasured() await syncPoint.WaitForSyncPoint().DefaultTimeout(); - using var requestDurationCollector = new MetricCollector(meterFactory, HostingMetrics.MeterName, "http.server.duration"); + using var requestDurationCollector = new MetricCollector(meterFactory, HostingMetrics.MeterName, "http.server.request.duration"); using var currentRequestsCollector = new MetricCollector(meterFactory, HostingMetrics.MeterName, "http.server.active_requests"); context1.HttpContext.Response.StatusCode = StatusCodes.Status200OK; @@ -160,7 +160,7 @@ public void IHttpMetricsTagsFeatureNotUsedFromFeatureCollection() var httpContext = new DefaultHttpContext(); var meter = meterFactory.Meters.Single(); - using var requestDurationCollector = new MetricCollector(meterFactory, HostingMetrics.MeterName, "http.server.duration"); + using var requestDurationCollector = new MetricCollector(meterFactory, HostingMetrics.MeterName, "http.server.request.duration"); using var currentRequestsCollector = new MetricCollector(meterFactory, HostingMetrics.MeterName, "http.server.active_requests"); // Act/Assert diff --git a/src/Middleware/Diagnostics/test/UnitTests/DeveloperExceptionPageMiddlewareTest.cs b/src/Middleware/Diagnostics/test/UnitTests/DeveloperExceptionPageMiddlewareTest.cs index 8b5dd0d8849d..6a2068ec34b6 100644 --- a/src/Middleware/Diagnostics/test/UnitTests/DeveloperExceptionPageMiddlewareTest.cs +++ b/src/Middleware/Diagnostics/test/UnitTests/DeveloperExceptionPageMiddlewareTest.cs @@ -540,7 +540,7 @@ public async Task UnhandledError_ExceptionNameTagAdded() { // Arrange var meterFactory = new TestMeterFactory(); - using var requestDurationCollector = new MetricCollector(meterFactory, "Microsoft.AspNetCore.Hosting", "http.server.duration"); + using var requestDurationCollector = new MetricCollector(meterFactory, "Microsoft.AspNetCore.Hosting", "http.server.request.duration"); using var requestExceptionCollector = new MetricCollector(meterFactory, DiagnosticsMetrics.MeterName, "aspnet.diagnostics.exceptions"); using var host = new HostBuilder() diff --git a/src/Middleware/Diagnostics/test/UnitTests/ExceptionHandlerTest.cs b/src/Middleware/Diagnostics/test/UnitTests/ExceptionHandlerTest.cs index b55aca5326af..93431bee80ef 100644 --- a/src/Middleware/Diagnostics/test/UnitTests/ExceptionHandlerTest.cs +++ b/src/Middleware/Diagnostics/test/UnitTests/ExceptionHandlerTest.cs @@ -917,7 +917,7 @@ public async Task UnhandledError_ExceptionNameTagAdded() { // Arrange var meterFactory = new TestMeterFactory(); - using var instrumentCollector = new MetricCollector(meterFactory, "Microsoft.AspNetCore.Hosting", "http.server.duration"); + using var instrumentCollector = new MetricCollector(meterFactory, "Microsoft.AspNetCore.Hosting", "http.server.request.duration"); using var host = new HostBuilder() .ConfigureServices(s => From 232b0a4de1d7fa44726debc126119734b7668116 Mon Sep 17 00:00:00 2001 From: James Newton-King Date: Fri, 4 Aug 2023 13:17:27 +0800 Subject: [PATCH 10/13] Name change --- .../Hosting/src/Internal/HostingMetrics.cs | 2 +- src/Http/Routing/src/RoutingMetrics.cs | 8 ++++---- .../Diagnostics/src/DiagnosticsMetrics.cs | 6 +++--- .../DeveloperExceptionPageMiddlewareTest.cs | 8 ++++---- .../UnitTests/ExceptionHandlerMiddlewareTest.cs | 16 ++++++++-------- 5 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/Hosting/Hosting/src/Internal/HostingMetrics.cs b/src/Hosting/Hosting/src/Internal/HostingMetrics.cs index 788561b47e97..21a8710bb362 100644 --- a/src/Hosting/Hosting/src/Internal/HostingMetrics.cs +++ b/src/Hosting/Hosting/src/Internal/HostingMetrics.cs @@ -60,7 +60,7 @@ public void RequestEnd(string protocol, bool isHttps, string scheme, string meth } if (unhandledRequest) { - tags.Add("aspnet.request.is_unhandled", true); + tags.Add("aspnetcore.request.is_unhandled", true); } // Add information gathered during request. diff --git a/src/Http/Routing/src/RoutingMetrics.cs b/src/Http/Routing/src/RoutingMetrics.cs index de3a17316c27..fc2cfe58b8a2 100644 --- a/src/Http/Routing/src/RoutingMetrics.cs +++ b/src/Http/Routing/src/RoutingMetrics.cs @@ -17,7 +17,7 @@ public RoutingMetrics(IMeterFactory meterFactory) _meter = meterFactory.Create(MeterName); _matchAttemptsCounter = _meter.CreateCounter( - "aspnet.routing.match_attempts", + "aspnetcore.routing.match_attempts", description: "Number of requests that were attempted to be matched to an endpoint."); } @@ -27,13 +27,13 @@ public void MatchSuccess(string route, bool isFallback) { _matchAttemptsCounter.Add(1, new KeyValuePair("http.route", route), - new KeyValuePair("aspnet.routing.match_status", "success"), - new KeyValuePair("aspnet.routing.is_fallback", isFallback)); + new KeyValuePair("aspnetcore.routing.match_status", "success"), + new KeyValuePair("aspnetcore.routing.is_fallback", isFallback)); } public void MatchFailure() { _matchAttemptsCounter.Add(1, - new KeyValuePair("aspnet.routing.match_status", "failure")); + new KeyValuePair("aspnetcore.routing.match_status", "failure")); } } diff --git a/src/Middleware/Diagnostics/src/DiagnosticsMetrics.cs b/src/Middleware/Diagnostics/src/DiagnosticsMetrics.cs index df7f7c78c3c7..a48505d4b837 100644 --- a/src/Middleware/Diagnostics/src/DiagnosticsMetrics.cs +++ b/src/Middleware/Diagnostics/src/DiagnosticsMetrics.cs @@ -22,7 +22,7 @@ public DiagnosticsMetrics(IMeterFactory meterFactory) _meter = meterFactory.Create(MeterName); _handlerExceptionCounter = _meter.CreateCounter( - "aspnet.diagnostics.exceptions", + "aspnetcore.diagnostics.exceptions", description: "Number of exceptions caught by exception handling middleware."); } @@ -39,10 +39,10 @@ private void RequestExceptionCore(string exceptionName, ExceptionResult result, { var tags = new TagList(); tags.Add("exception.type", exceptionName); - tags.Add("aspnet.diagnostics.exception.result", GetExceptionResult(result)); + tags.Add("aspnetcore.diagnostics.exception.result", GetExceptionResult(result)); if (handler != null) { - tags.Add("aspnet.diagnostics.handler.type", handler); + tags.Add("aspnetcore.diagnostics.handler.type", handler); } _handlerExceptionCounter.Add(1, tags); } diff --git a/src/Middleware/Diagnostics/test/UnitTests/DeveloperExceptionPageMiddlewareTest.cs b/src/Middleware/Diagnostics/test/UnitTests/DeveloperExceptionPageMiddlewareTest.cs index 6a2068ec34b6..92e456adcb38 100644 --- a/src/Middleware/Diagnostics/test/UnitTests/DeveloperExceptionPageMiddlewareTest.cs +++ b/src/Middleware/Diagnostics/test/UnitTests/DeveloperExceptionPageMiddlewareTest.cs @@ -541,7 +541,7 @@ public async Task UnhandledError_ExceptionNameTagAdded() // Arrange var meterFactory = new TestMeterFactory(); using var requestDurationCollector = new MetricCollector(meterFactory, "Microsoft.AspNetCore.Hosting", "http.server.request.duration"); - using var requestExceptionCollector = new MetricCollector(meterFactory, DiagnosticsMetrics.MeterName, "aspnet.diagnostics.exceptions"); + using var requestExceptionCollector = new MetricCollector(meterFactory, DiagnosticsMetrics.MeterName, "aspnetcore.diagnostics.exceptions"); using var host = new HostBuilder() .ConfigureServices(s => @@ -590,14 +590,14 @@ private static void AssertRequestException(CollectedMeasurement measuremen { Assert.Equal(1, measurement.Value); Assert.Equal(exceptionName, (string)measurement.Tags["exception.type"]); - Assert.Equal(result, measurement.Tags["aspnet.diagnostics.exception.result"].ToString()); + Assert.Equal(result, measurement.Tags["aspnetcore.diagnostics.exception.result"].ToString()); if (handler == null) { - Assert.False(measurement.Tags.ContainsKey("aspnet.diagnostics.handler.type")); + Assert.False(measurement.Tags.ContainsKey("aspnetcore.diagnostics.handler.type")); } else { - Assert.Equal(handler, (string)measurement.Tags["aspnet.diagnostics.handler.type"]); + Assert.Equal(handler, (string)measurement.Tags["aspnetcore.diagnostics.handler.type"]); } } diff --git a/src/Middleware/Diagnostics/test/UnitTests/ExceptionHandlerMiddlewareTest.cs b/src/Middleware/Diagnostics/test/UnitTests/ExceptionHandlerMiddlewareTest.cs index f4e1d5ed1e3f..fd0c791cd287 100644 --- a/src/Middleware/Diagnostics/test/UnitTests/ExceptionHandlerMiddlewareTest.cs +++ b/src/Middleware/Diagnostics/test/UnitTests/ExceptionHandlerMiddlewareTest.cs @@ -211,7 +211,7 @@ public async Task Metrics_NoExceptionThrown() var middleware = CreateMiddleware(_ => Task.CompletedTask, optionsAccessor, exceptionHandlers, meterFactory); var meter = meterFactory.Meters.Single(); - using var diagnosticsRequestExceptionCollector = new MetricCollector(meterFactory, DiagnosticsMetrics.MeterName, "aspnet.diagnostics.exceptions"); + using var diagnosticsRequestExceptionCollector = new MetricCollector(meterFactory, DiagnosticsMetrics.MeterName, "aspnetcore.diagnostics.exceptions"); // Act await middleware.Invoke(httpContext); @@ -234,7 +234,7 @@ public async Task Metrics_ExceptionThrown_Handled_Reported() var middleware = CreateMiddleware(_ => throw new InvalidOperationException(), optionsAccessor, exceptionHandlers, meterFactory); var meter = meterFactory.Meters.Single(); - using var diagnosticsRequestExceptionCollector = new MetricCollector(meterFactory, DiagnosticsMetrics.MeterName, "aspnet.diagnostics.exceptions"); + using var diagnosticsRequestExceptionCollector = new MetricCollector(meterFactory, DiagnosticsMetrics.MeterName, "aspnetcore.diagnostics.exceptions"); // Act await middleware.Invoke(httpContext); @@ -256,7 +256,7 @@ public async Task Metrics_ExceptionThrown_ResponseStarted_Skipped() var middleware = CreateMiddleware(_ => throw new InvalidOperationException(), optionsAccessor, exceptionHandlers, meterFactory); var meter = meterFactory.Meters.Single(); - using var diagnosticsRequestExceptionCollector = new MetricCollector(meterFactory, DiagnosticsMetrics.MeterName, "aspnet.diagnostics.exceptions"); + using var diagnosticsRequestExceptionCollector = new MetricCollector(meterFactory, DiagnosticsMetrics.MeterName, "aspnetcore.diagnostics.exceptions"); // Act await Assert.ThrowsAsync(() => middleware.Invoke(httpContext)); @@ -281,7 +281,7 @@ public async Task Metrics_ExceptionThrown_DefaultSettings_Handled_Reported() var middleware = CreateMiddleware(_ => throw new InvalidOperationException(), optionsAccessor, meterFactory: meterFactory); var meter = meterFactory.Meters.Single(); - using var diagnosticsRequestExceptionCollector = new MetricCollector(meterFactory, DiagnosticsMetrics.MeterName, "aspnet.diagnostics.exceptions"); + using var diagnosticsRequestExceptionCollector = new MetricCollector(meterFactory, DiagnosticsMetrics.MeterName, "aspnetcore.diagnostics.exceptions"); // Act await middleware.Invoke(httpContext); @@ -305,7 +305,7 @@ public async Task Metrics_ExceptionThrown_Unhandled_Reported() var middleware = CreateMiddleware(_ => throw new InvalidOperationException(), optionsAccessor, meterFactory: meterFactory); var meter = meterFactory.Meters.Single(); - using var diagnosticsRequestExceptionCollector = new MetricCollector(meterFactory, DiagnosticsMetrics.MeterName, "aspnet.diagnostics.exceptions"); + using var diagnosticsRequestExceptionCollector = new MetricCollector(meterFactory, DiagnosticsMetrics.MeterName, "aspnetcore.diagnostics.exceptions"); // Act await Assert.ThrowsAsync(() => middleware.Invoke(httpContext)); @@ -319,14 +319,14 @@ private static void AssertRequestException(CollectedMeasurement measuremen { Assert.Equal(1, measurement.Value); Assert.Equal(exceptionName, (string)measurement.Tags["exception.type"]); - Assert.Equal(result, measurement.Tags["aspnet.diagnostics.exception.result"].ToString()); + Assert.Equal(result, measurement.Tags["aspnetcore.diagnostics.exception.result"].ToString()); if (handler == null) { - Assert.False(measurement.Tags.ContainsKey("aspnet.diagnostics.handler.type")); + Assert.False(measurement.Tags.ContainsKey("aspnetcore.diagnostics.handler.type")); } else { - Assert.Equal(handler, (string)measurement.Tags["aspnet.diagnostics.handler.type"]); + Assert.Equal(handler, (string)measurement.Tags["aspnetcore.diagnostics.handler.type"]); } } From 75d6287398c97f6a46b16a0147dbfc56728dc14c Mon Sep 17 00:00:00 2001 From: James Newton-King Date: Fri, 4 Aug 2023 13:19:03 +0800 Subject: [PATCH 11/13] Name change --- .../Routing/test/UnitTests/RoutingMetricsTests.cs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Http/Routing/test/UnitTests/RoutingMetricsTests.cs b/src/Http/Routing/test/UnitTests/RoutingMetricsTests.cs index 701d1c311423..18ed872ce99a 100644 --- a/src/Http/Routing/test/UnitTests/RoutingMetricsTests.cs +++ b/src/Http/Routing/test/UnitTests/RoutingMetricsTests.cs @@ -34,7 +34,7 @@ public async Task Match_Success() var httpContext = new DefaultHttpContext(); var meter = meterFactory.Meters.Single(); - using var routingMatchAttemptsCollector = new MetricCollector(meterFactory, RoutingMetrics.MeterName, "aspnet.routing.match_attempts"); + using var routingMatchAttemptsCollector = new MetricCollector(meterFactory, RoutingMetrics.MeterName, "aspnetcore.routing.match_attempts"); // Act await middleware.Invoke(httpContext); @@ -68,7 +68,7 @@ public async Task Match_SuccessFallback_SetTagIfPresent(bool hasFallbackMetadata var httpContext = new DefaultHttpContext(); var meter = meterFactory.Meters.Single(); - using var routingMatchAttemptsCollector = new MetricCollector(meterFactory, RoutingMetrics.MeterName, "aspnet.routing.match_attempts"); + using var routingMatchAttemptsCollector = new MetricCollector(meterFactory, RoutingMetrics.MeterName, "aspnetcore.routing.match_attempts"); // Act await middleware.Invoke(httpContext); @@ -95,7 +95,7 @@ public async Task Match_Success_MissingRoute() var httpContext = new DefaultHttpContext(); var meter = meterFactory.Meters.Single(); - using var routingMatchAttemptsCollector = new MetricCollector(meterFactory, RoutingMetrics.MeterName, "aspnet.routing.match_attempts"); + using var routingMatchAttemptsCollector = new MetricCollector(meterFactory, RoutingMetrics.MeterName, "aspnetcore.routing.match_attempts"); // Act await middleware.Invoke(httpContext); @@ -119,7 +119,7 @@ public async Task Match_Failure() var httpContext = new DefaultHttpContext(); var meter = meterFactory.Meters.Single(); - using var routingMatchAttemptsCollector = new MetricCollector(meterFactory, RoutingMetrics.MeterName, "aspnet.routing.match_attempts"); + using var routingMatchAttemptsCollector = new MetricCollector(meterFactory, RoutingMetrics.MeterName, "aspnetcore.routing.match_attempts"); // Act await middleware.Invoke(httpContext); @@ -135,15 +135,15 @@ public async Task Match_Failure() private void AssertFailure(CollectedMeasurement measurement) { Assert.Equal(1, measurement.Value); - Assert.Equal("failure", (string)measurement.Tags["aspnet.routing.match_status"]); + Assert.Equal("failure", (string)measurement.Tags["aspnetcore.routing.match_status"]); } private void AssertSuccess(CollectedMeasurement measurement, string route, bool fallback) { Assert.Equal(1, measurement.Value); - Assert.Equal("success", (string)measurement.Tags["aspnet.routing.match_status"]); + Assert.Equal("success", (string)measurement.Tags["aspnetcore.routing.match_status"]); Assert.Equal(route, (string)measurement.Tags["http.route"]); - Assert.Equal(fallback, (bool)measurement.Tags["aspnet.routing.is_fallback"]); + Assert.Equal(fallback, (bool)measurement.Tags["aspnetcore.routing.is_fallback"]); } private EndpointRoutingMiddleware CreateMiddleware( From 82af403c6ddce32dff308deebea4f0f85821de7a Mon Sep 17 00:00:00 2001 From: James Newton-King Date: Fri, 4 Aug 2023 14:40:52 +0800 Subject: [PATCH 12/13] Fix build --- src/Hosting/Hosting/test/HostingMetricsTests.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Hosting/Hosting/test/HostingMetricsTests.cs b/src/Hosting/Hosting/test/HostingMetricsTests.cs index 7ae9edcecd3d..18cd4f54c54a 100644 --- a/src/Hosting/Hosting/test/HostingMetricsTests.cs +++ b/src/Hosting/Hosting/test/HostingMetricsTests.cs @@ -105,11 +105,11 @@ static void AssertRequestDuration(CollectedMeasurement measurement, stri } if (unhandledRequest ?? false) { - Assert.True((bool)measurement.Tags["aspnet.request.is_unhandled"]); + Assert.True((bool)measurement.Tags["aspnetcore.request.is_unhandled"]); } else { - Assert.False(measurement.Tags.ContainsKey("aspnet.request.is_unhandled")); + Assert.False(measurement.Tags.ContainsKey("aspnetcore.request.is_unhandled")); } } } From 7bcb72905882e924e01ba49de70f3b24d69fc663 Mon Sep 17 00:00:00 2001 From: James Newton-King Date: Sat, 5 Aug 2023 12:41:45 +0800 Subject: [PATCH 13/13] PR feedback --- src/Hosting/Hosting/src/Internal/HostingMetrics.cs | 1 + src/Http/Routing/src/RoutingMetrics.cs | 3 ++- src/Middleware/Diagnostics/src/DiagnosticsMetrics.cs | 3 ++- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Hosting/Hosting/src/Internal/HostingMetrics.cs b/src/Hosting/Hosting/src/Internal/HostingMetrics.cs index 21a8710bb362..3eca109f9e0f 100644 --- a/src/Hosting/Hosting/src/Internal/HostingMetrics.cs +++ b/src/Hosting/Hosting/src/Internal/HostingMetrics.cs @@ -23,6 +23,7 @@ public HostingMetrics(IMeterFactory meterFactory) _activeRequestsCounter = _meter.CreateUpDownCounter( "http.server.active_requests", + unit: "{request}", description: "Number of HTTP requests that are currently active on the server."); _requestDuration = _meter.CreateHistogram( diff --git a/src/Http/Routing/src/RoutingMetrics.cs b/src/Http/Routing/src/RoutingMetrics.cs index fc2cfe58b8a2..c8400d9f7f68 100644 --- a/src/Http/Routing/src/RoutingMetrics.cs +++ b/src/Http/Routing/src/RoutingMetrics.cs @@ -17,7 +17,8 @@ public RoutingMetrics(IMeterFactory meterFactory) _meter = meterFactory.Create(MeterName); _matchAttemptsCounter = _meter.CreateCounter( - "aspnetcore.routing.match_attempts", + "aspnetcore.routing.match_attempts", + unit: "{match_attempt}", description: "Number of requests that were attempted to be matched to an endpoint."); } diff --git a/src/Middleware/Diagnostics/src/DiagnosticsMetrics.cs b/src/Middleware/Diagnostics/src/DiagnosticsMetrics.cs index a48505d4b837..7280bd5190a3 100644 --- a/src/Middleware/Diagnostics/src/DiagnosticsMetrics.cs +++ b/src/Middleware/Diagnostics/src/DiagnosticsMetrics.cs @@ -22,7 +22,8 @@ public DiagnosticsMetrics(IMeterFactory meterFactory) _meter = meterFactory.Create(MeterName); _handlerExceptionCounter = _meter.CreateCounter( - "aspnetcore.diagnostics.exceptions", + "aspnetcore.diagnostics.exceptions", + unit: "{exception}", description: "Number of exceptions caught by exception handling middleware."); }