Description
Background and Motivation
ASP.NET Core hosting counters record the number of current requests and duration. There isn't a way for a framework, middleware or app to enrich these counters with tags per-request. For example, ASP.NET Core might want to add a tag to the HTTP server metrics that specifies whether there was an unhandled exception with that request.
This issue outlines an ASP.NET Core feature for adding tags to metrics. It's similar to the existing IHttpActivityFeature
. For an example of enriching the request activity with tags, see Activity Enrichment in ASP.NET Core 6.0.
Proposed API
namespace Microsoft.AspNetCore.Http.Features;
+ public interface IHttpMetricsTagsFeature
+ {
+ IList<KeyValuePair<string, object?> Tags { get; }
+ }
namespace Microsoft.AspNetCore.Connections.Features;
+ public interface IConnectionMetricsTagsFeature
+ {
+ IList<KeyValuePair<string, object?>> Tags { get; }
+ }
Implementations are internal. Features are automatically set on the HttpContext
or TransportConnection
if metrics is enabled (aka someone is listening).
Usage Examples
The feature is used by frameworks, middleware or apps when they want to enrich HTTP metrics counters (or connection counters) with extra tags. In the sample below, middleware catches unhandled exceptions, then uses the feature to add the exception type name to metrics.
app.Use(async (context, next) =>
{
try
{
await next.Invoke();
}
catch (Exception ex)
{
var tagsFeature = context.Features.Get<IHttpMetricsTagsFeature>();
if (tagsFeature != null)
{
tagsFeature.Tags.Add(new KeyValuePair<string, object?>("exception-type", ex.GetType().Name));
}
}
});
ASP.NET Core hosting uses the feature when recording counters.
public class HostingMetrics
{
public void RequestEnd(HttpContext context, long startTimestamp, long currentTimestamp)
{
var duration = new TimeSpan((long)(HostingApplicationDiagnostics.TimestampToTicks * (currentTimestamp - startTimestamp)));
var tags = new TagList();
// Known tag values.
tags.Add("scheme", context.Request.Scheme);
tags.Add("method", context.Request.Method);
// Framework, middleware or app define tags.
var tagsFeature = context.Features.Get<IHttpMetricsTagsFeature>();
if (tagsFeature != null)
{
foreach (var tag in tagsFeatures.Tags)
{
tags.Add(tag);
}
}
_requestDuration.Record(duration.TotalMilliseconds, tags);
}
}
Alternative Designs
One feature could be used for HTTP request and connection.
I believe that approach means it wouldn't be possible to get the connection metrics tags feature from a request, because the request feature of the same type would always be returned.