From ee19d704927b8c94917762114003bc021590e93a Mon Sep 17 00:00:00 2001 From: Vishwesh Bankwar Date: Fri, 6 May 2022 14:44:54 -0700 Subject: [PATCH] Add additional tags to ASP.NET Core metrics (#3247) --- .../CHANGELOG.md | 3 + .../Implementation/HttpInMetricsListener.cs | 55 +++++++++++++++++-- .../MetricTests.cs | 8 ++- 3 files changed, 60 insertions(+), 6 deletions(-) diff --git a/src/OpenTelemetry.Instrumentation.AspNetCore/CHANGELOG.md b/src/OpenTelemetry.Instrumentation.AspNetCore/CHANGELOG.md index 9738193c92a..a9bb5ced3fa 100644 --- a/src/OpenTelemetry.Instrumentation.AspNetCore/CHANGELOG.md +++ b/src/OpenTelemetry.Instrumentation.AspNetCore/CHANGELOG.md @@ -2,6 +2,9 @@ ## Unreleased +* Added additional metric dimensions. + ([3247](https://github.com/open-telemetry/opentelemetry-dotnet/pull/3247)) + * Removes net5.0 target as .NET 5.0 is going out of support. The package keeps netstandard2.1 target, so it can still be used with .NET5.0 apps. diff --git a/src/OpenTelemetry.Instrumentation.AspNetCore/Implementation/HttpInMetricsListener.cs b/src/OpenTelemetry.Instrumentation.AspNetCore/Implementation/HttpInMetricsListener.cs index ae87595bf05..2becf9cf128 100644 --- a/src/OpenTelemetry.Instrumentation.AspNetCore/Implementation/HttpInMetricsListener.cs +++ b/src/OpenTelemetry.Instrumentation.AspNetCore/Implementation/HttpInMetricsListener.cs @@ -17,6 +17,9 @@ using System.Diagnostics; using System.Diagnostics.Metrics; using Microsoft.AspNetCore.Http; +#if NETCOREAPP +using Microsoft.AspNetCore.Routing; +#endif using OpenTelemetry.Trace; namespace OpenTelemetry.Instrumentation.AspNetCore.Implementation @@ -51,16 +54,60 @@ public override void OnStopActivity(Activity activity, object payload) return; } + string host; + + if (context.Request.Host.Port is null or 80 or 443) + { + host = context.Request.Host.Host; + } + else + { + host = context.Request.Host.Host + ":" + context.Request.Host.Port; + } + + TagList tags; + + // We need following directive as + // RouteEndpoint is not available in netstandard2.0 and netstandard2.1 +#if NETCOREAPP + var target = (context.GetEndpoint() as RouteEndpoint)?.RoutePattern.RawText; + // TODO: This is just a minimal set of attributes. See the spec for additional attributes: // https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/semantic_conventions/http-metrics.md#http-server - var tags = new TagList + if (!string.IsNullOrEmpty(target)) + { + tags = new TagList + { + { SemanticConventions.AttributeHttpFlavor, context.Request.Protocol }, + { SemanticConventions.AttributeHttpScheme, context.Request.Scheme }, + { SemanticConventions.AttributeHttpMethod, context.Request.Method }, + { SemanticConventions.AttributeHttpHost, host }, + { SemanticConventions.AttributeHttpTarget, target }, + { SemanticConventions.AttributeHttpStatusCode, context.Response.StatusCode.ToString() }, + }; + } + else + { + tags = new TagList + { + { SemanticConventions.AttributeHttpFlavor, context.Request.Protocol }, + { SemanticConventions.AttributeHttpScheme, context.Request.Scheme }, + { SemanticConventions.AttributeHttpMethod, context.Request.Method }, + { SemanticConventions.AttributeHttpHost, host }, + { SemanticConventions.AttributeHttpStatusCode, context.Response.StatusCode.ToString() }, + }; + } +#else + tags = new TagList { - { SemanticConventions.AttributeHttpMethod, context.Request.Method }, - { SemanticConventions.AttributeHttpScheme, context.Request.Scheme }, - { SemanticConventions.AttributeHttpStatusCode, context.Response.StatusCode }, { SemanticConventions.AttributeHttpFlavor, context.Request.Protocol }, + { SemanticConventions.AttributeHttpScheme, context.Request.Scheme }, + { SemanticConventions.AttributeHttpMethod, context.Request.Method }, + { SemanticConventions.AttributeHttpHost, host }, + { SemanticConventions.AttributeHttpStatusCode, context.Response.StatusCode.ToString() }, }; +#endif this.httpServerDuration.Record(activity.Duration.TotalMilliseconds, tags); } } diff --git a/test/OpenTelemetry.Instrumentation.AspNetCore.Tests/MetricTests.cs b/test/OpenTelemetry.Instrumentation.AspNetCore.Tests/MetricTests.cs index 87cc856156c..92512230663 100644 --- a/test/OpenTelemetry.Instrumentation.AspNetCore.Tests/MetricTests.cs +++ b/test/OpenTelemetry.Instrumentation.AspNetCore.Tests/MetricTests.cs @@ -116,13 +116,17 @@ public async Task RequestMetricIsCaptured() var method = new KeyValuePair(SemanticConventions.AttributeHttpMethod, "GET"); var scheme = new KeyValuePair(SemanticConventions.AttributeHttpScheme, "http"); - var statusCode = new KeyValuePair(SemanticConventions.AttributeHttpStatusCode, 200); + var statusCode = new KeyValuePair(SemanticConventions.AttributeHttpStatusCode, "200"); var flavor = new KeyValuePair(SemanticConventions.AttributeHttpFlavor, "HTTP/1.1"); + var host = new KeyValuePair(SemanticConventions.AttributeHttpHost, "localhost"); + var target = new KeyValuePair(SemanticConventions.AttributeHttpTarget, "api/Values"); Assert.Contains(method, attributes); Assert.Contains(scheme, attributes); Assert.Contains(statusCode, attributes); Assert.Contains(flavor, attributes); - Assert.Equal(4, attributes.Length); + Assert.Contains(host, attributes); + Assert.Contains(target, attributes); + Assert.Equal(6, attributes.Length); } public void Dispose()