Skip to content

Commit 40dabd3

Browse files
committed
Add flag on metrics feature to disable metrics per request
1 parent 8a6e8d7 commit 40dabd3

8 files changed

+76
-5
lines changed

src/Hosting/Hosting/src/Internal/HostingApplicationDiagnostics.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -154,12 +154,12 @@ public void RequestEnd(HttpContext httpContext, Exception? exception, HostingApp
154154

155155
if (context.MetricsEnabled)
156156
{
157+
Debug.Assert(context.MetricsTagsFeature != null, "MetricsTagsFeature should be set if MetricsEnabled is true.");
158+
157159
var endpoint = HttpExtensions.GetOriginalEndpoint(httpContext);
158-
var disableHttpRequestDurationMetric = endpoint?.Metadata.GetMetadata<IDisableHttpMetricsMetadata>() != null;
160+
var disableHttpRequestDurationMetric = endpoint?.Metadata.GetMetadata<IDisableHttpMetricsMetadata>() != null || context.MetricsTagsFeature.MetricsDisabled;
159161
var route = endpoint?.Metadata.GetMetadata<IRouteDiagnosticsMetadata>()?.Route;
160162

161-
Debug.Assert(context.MetricsTagsFeature != null, "MetricsTagsFeature should be set if MetricsEnabled is true.");
162-
163163
_metrics.RequestEnd(
164164
context.MetricsTagsFeature.Protocol!,
165165
context.MetricsTagsFeature.Scheme!,

src/Hosting/Hosting/src/Internal/HttpMetricsTagsFeature.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ namespace Microsoft.AspNetCore.Hosting;
88
internal sealed class HttpMetricsTagsFeature : IHttpMetricsTagsFeature
99
{
1010
ICollection<KeyValuePair<string, object?>> IHttpMetricsTagsFeature.Tags => TagsList;
11+
public bool MetricsDisabled { get; set; }
1112

1213
public List<KeyValuePair<string, object?>> TagsList { get; } = new List<KeyValuePair<string, object?>>();
1314

@@ -20,6 +21,7 @@ internal sealed class HttpMetricsTagsFeature : IHttpMetricsTagsFeature
2021
public void Reset()
2122
{
2223
TagsList.Clear();
24+
MetricsDisabled = false;
2325

2426
Method = null;
2527
Scheme = null;

src/Hosting/Hosting/test/HostingApplicationDiagnosticsTests.cs

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,7 @@ public void Metrics_Route_RouteTagReported()
295295
}
296296

297297
[Fact]
298-
public void Metrics_DisableHttpMetrics_NoMetrics()
298+
public void Metrics_DisableHttpMetricsWithMetadata_NoMetrics()
299299
{
300300
// Arrange
301301
var hostingEventSource = new HostingEventSource(Guid.NewGuid().ToString());
@@ -349,6 +349,62 @@ public void Metrics_DisableHttpMetrics_NoMetrics()
349349
Assert.Empty(requestDurationCollector.GetMeasurementSnapshot());
350350
}
351351

352+
[Fact]
353+
public void Metrics_DisableHttpMetricsWithFeature_NoMetrics()
354+
{
355+
// Arrange
356+
var hostingEventSource = new HostingEventSource(Guid.NewGuid().ToString());
357+
358+
var testMeterFactory = new TestMeterFactory();
359+
using var activeRequestsCollector = new MetricCollector<long>(testMeterFactory, HostingMetrics.MeterName, "http.server.active_requests");
360+
using var requestDurationCollector = new MetricCollector<double>(testMeterFactory, HostingMetrics.MeterName, "http.server.request.duration");
361+
362+
// Act
363+
var hostingApplication = CreateApplication(out var features, eventSource: hostingEventSource, meterFactory: testMeterFactory, configure: c =>
364+
{
365+
c.Request.Protocol = "1.1";
366+
c.Request.Scheme = "http";
367+
c.Request.Method = "POST";
368+
c.Request.Host = new HostString("localhost");
369+
c.Request.Path = "/hello";
370+
c.Request.ContentType = "text/plain";
371+
c.Request.ContentLength = 1024;
372+
});
373+
var context = hostingApplication.CreateContext(features);
374+
375+
Assert.Collection(activeRequestsCollector.GetMeasurementSnapshot(),
376+
m =>
377+
{
378+
Assert.Equal(1, m.Value);
379+
Assert.Equal("http", m.Tags["url.scheme"]);
380+
Assert.Equal("POST", m.Tags["http.request.method"]);
381+
});
382+
383+
context.HttpContext.Features.Get<IHttpMetricsTagsFeature>().MetricsDisabled = true;
384+
385+
// Assert 1
386+
Assert.True(context.MetricsTagsFeature.MetricsDisabled);
387+
388+
hostingApplication.DisposeContext(context, null);
389+
390+
// Assert 2
391+
Assert.Collection(activeRequestsCollector.GetMeasurementSnapshot(),
392+
m =>
393+
{
394+
Assert.Equal(1, m.Value);
395+
Assert.Equal("http", m.Tags["url.scheme"]);
396+
Assert.Equal("POST", m.Tags["http.request.method"]);
397+
},
398+
m =>
399+
{
400+
Assert.Equal(-1, m.Value);
401+
Assert.Equal("http", m.Tags["url.scheme"]);
402+
Assert.Equal("POST", m.Tags["http.request.method"]);
403+
});
404+
Assert.Empty(requestDurationCollector.GetMeasurementSnapshot());
405+
Assert.False(context.MetricsTagsFeature.MetricsDisabled);
406+
}
407+
352408
private sealed class TestRouteDiagnosticsMetadata : IRouteDiagnosticsMetadata
353409
{
354410
public string Route { get; } = "hello/{name}";

src/Hosting/Hosting/test/HostingMetricsTests.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,7 @@ public void IHttpMetricsTagsFeatureNotUsedFromFeatureCollection()
180180
private sealed class TestHttpMetricsTagsFeature : IHttpMetricsTagsFeature
181181
{
182182
public ICollection<KeyValuePair<string, object>> Tags { get; } = new Collection<KeyValuePair<string, object>>();
183+
public bool MetricsDisabled { get; set; }
183184
}
184185

185186
private static HostingApplication CreateApplication(IHttpContextFactory httpContextFactory = null, bool useHttpContextAccessor = false,

src/Http/Http.Abstractions/src/Metadata/IDisableHttpMetricsMetadata.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33

44
namespace Microsoft.AspNetCore.Http.Metadata;
55

6+
/// <summary>
7+
/// A marker interface which can be used to identify metadata that disables HTTP request duration metrics.
8+
/// </summary>
69
public interface IDisableHttpMetricsMetadata
710
{
811
}

src/Http/Http.Abstractions/src/PublicAPI.Unshipped.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@
33
Microsoft.AspNetCore.Http.HostString.HostString(string? value) -> void
44
*REMOVED*Microsoft.AspNetCore.Http.HostString.Value.get -> string!
55
Microsoft.AspNetCore.Http.HostString.Value.get -> string?
6+
Microsoft.AspNetCore.Http.Metadata.IDisableHttpMetricsMetadata

src/Http/Http.Features/src/IHttpMetricsTagsFeature.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,18 @@
44
namespace Microsoft.AspNetCore.Http.Features;
55

66
/// <summary>
7-
/// Provides access to tags added to the metrics HTTP request counter. This feature isn't set if the counter isn't enabled.
7+
/// Provides access to tags added to the metrics HTTP request duration counter. This feature isn't set if the counter isn't enabled.
88
/// </summary>
99
public interface IHttpMetricsTagsFeature
1010
{
1111
/// <summary>
1212
/// Gets the tag collection.
1313
/// </summary>
1414
ICollection<KeyValuePair<string, object?>> Tags { get; }
15+
16+
// MetricsDisabled was added after the initial release of this interface and is intentionally a DIM property.
17+
/// <summary>
18+
/// Gets or sets a flag that disables recording HTTP request duration counter for the current HTTP request.
19+
/// </summary>
20+
public bool MetricsDisabled { get; set; }
1521
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
11
#nullable enable
2+
Microsoft.AspNetCore.Http.Features.IHttpMetricsTagsFeature.MetricsDisabled.get -> bool
3+
Microsoft.AspNetCore.Http.Features.IHttpMetricsTagsFeature.MetricsDisabled.set -> void

0 commit comments

Comments
 (0)