Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HttpSemanticConventions - new metric in AspNetCore Instrumentation. #4802

Merged
merged 51 commits into from
Sep 14, 2023
Merged
Show file tree
Hide file tree
Changes from 40 commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
91f08c8
update AspNetCore for new metric 'http.server.request.duration'
TimothyMothra Aug 24, 2023
c111eea
cleanup
TimothyMothra Aug 24, 2023
32d8946
remove attributes
TimothyMothra Aug 24, 2023
3208431
comment
TimothyMothra Aug 24, 2023
d2f7ef4
readme
TimothyMothra Aug 24, 2023
1a49dab
comment
TimothyMothra Aug 24, 2023
7c11551
update readme
TimothyMothra Aug 24, 2023
93fe6ad
cleanup
TimothyMothra Aug 24, 2023
3842aa8
check flag in ctor
TimothyMothra Aug 25, 2023
ec2b825
Merge branch 'main' into 4484_newMetrics
TimothyMothra Aug 25, 2023
5f74488
update tags on metrics
TimothyMothra Aug 29, 2023
9fb75e5
refactor
TimothyMothra Aug 29, 2023
c335f65
Merge branch 'main' into 4484_newMetrics
TimothyMothra Aug 29, 2023
6c86a4a
fix name in log
TimothyMothra Aug 29, 2023
3bcefae
another fix
TimothyMothra Aug 29, 2023
e588453
more fixes
TimothyMothra Aug 29, 2023
88355cd
big refactor, split Old and New into two methods
TimothyMothra Aug 29, 2023
6a3f651
investigating test fix
TimothyMothra Aug 30, 2023
1a72356
final fix for test issue
TimothyMothra Aug 30, 2023
b9d194c
Merge branch 'main' into 4484_newMetrics
TimothyMothra Aug 30, 2023
ac76993
Merge branch 'main' into 4484_newMetrics
TimothyMothra Sep 5, 2023
b57320d
change unit to seconds
TimothyMothra Sep 5, 2023
7fdc29f
update Readme
TimothyMothra Sep 5, 2023
a782b51
cleanup if condition
TimothyMothra Sep 7, 2023
3788d15
fix indentation
TimothyMothra Sep 7, 2023
275de4e
update readme
TimothyMothra Sep 7, 2023
c6d5d76
change test to use IConfiguration
TimothyMothra Sep 7, 2023
3789fdd
markdown lint
TimothyMothra Sep 8, 2023
f110b29
split test methods
TimothyMothra Sep 9, 2023
6a52fcf
Merge branch 'main' into 4484_newMetrics
TimothyMothra Sep 11, 2023
7c11aac
Update src/OpenTelemetry.Instrumentation.AspNetCore/README.md
TimothyMothra Sep 11, 2023
9ab958c
cleanup Readme after suggestion conflict
TimothyMothra Sep 12, 2023
3646823
update changelog
TimothyMothra Sep 12, 2023
314c9d9
update changelog
TimothyMothra Sep 12, 2023
255b2da
refactor tests
TimothyMothra Sep 12, 2023
12d10cf
Update src/OpenTelemetry.Instrumentation.AspNetCore/README.md
TimothyMothra Sep 12, 2023
c38a93e
update changelog
TimothyMothra Sep 12, 2023
26ea138
Merge branch '4484_newMetrics' of https://github.com/TimothyMothra/op…
TimothyMothra Sep 12, 2023
1fd022b
Merge branch 'main' into 4484_newMetrics
TimothyMothra Sep 12, 2023
1f787be
markdownlint
TimothyMothra Sep 12, 2023
0b257af
rewrite changelog
TimothyMothra Sep 13, 2023
4987540
rewrite Readme
TimothyMothra Sep 13, 2023
0cfa424
markdownlint
TimothyMothra Sep 13, 2023
163d4d7
Merge branch 'main' into 4484_newMetrics
TimothyMothra Sep 13, 2023
80df848
rewrite changelog
TimothyMothra Sep 14, 2023
9f83898
Merge branch '4484_newMetrics' of https://github.com/TimothyMothra/op…
TimothyMothra Sep 14, 2023
744a980
edit changelog & readme
TimothyMothra Sep 14, 2023
1d694bc
update
TimothyMothra Sep 14, 2023
390d563
Merge branch 'main' into 4484_newMetrics
TimothyMothra Sep 14, 2023
6d4bb65
Merge branch '4484_newMetrics' of https://github.com/TimothyMothra/op…
TimothyMothra Sep 14, 2023
0015a20
feedback
TimothyMothra Sep 14, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions src/OpenTelemetry.Instrumentation.AspNetCore/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,18 @@

## Unreleased

* Introduced a new metric, `http.server.request.duration`, for users who opt
into the new semantic convention by configuring the `OTEL_SEMCONV_STABILITY_OPT_IN`
Copy link
Contributor

@utpilla utpilla Sep 13, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

https://www.merriam-webster.com/dictionary/opt%20in#examples

Suggested change
into the new semantic convention by configuring the `OTEL_SEMCONV_STABILITY_OPT_IN`
in to the new semantic convention by configuring the `OTEL_SEMCONV_STABILITY_OPT_IN`

environment variable. This metric measures time in seconds and offers unique
histogram buckets as per the
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This metric measures time in seconds and offers unique
histogram buckets

Not sure how to interpret "offers unique histogram buckets"? What does it mean?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"offers" is the wrong word here, "uses" would be more appropriate.
I'm trying to call attention to the fact that the buckets are different than the default.
4 lines below this I list the exact buckets.

I'm trying to find a succinct way to describe that this metric is different than what came before.
@cijothomas, do you think this would be better as a bulleted list?

ie:

- new metric: `http.server.request.duration`
- unit: seconds
- buckets: 0, 0.005, 0.01, 0.025, 0.05, 0.075, 0.1, 0.25, 0.5, 0.75, 1,
  2.5, 5, 7.5, 10

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the list is good. Hint that the buckets are so, because SDK specially handles this metric.

[spec](https://github.com/open-telemetry/semantic-conventions/blob/main/docs/http/http-metrics.md#metric-httpserverrequestduration)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

, replacing the previous `http.server.duration metric`, which measured time in
TimothyMothra marked this conversation as resolved.
Show resolved Hide resolved
milliseconds.
* Former buckets: `0, 5, 10, 25, 50, 75, 100, 250, 500, 750, 1000, 2500,
TimothyMothra marked this conversation as resolved.
Show resolved Hide resolved
5000, 7500, 10000`
* New buckets: `0, 0.005, 0.01, 0.025, 0.05, 0.075, 0.1, 0.25, 0.5, 0.75, 1,
2.5, 5, 7.5, 10`

## 1.5.1-beta.1

Released 2023-Jul-20
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,16 @@ namespace OpenTelemetry.Instrumentation.AspNetCore.Implementation;

internal sealed class HttpInMetricsListener : ListenerHandler
{
private const string HttpServerDurationMetricName = "http.server.duration";
internal const string HttpServerDurationMetricName = "http.server.duration";
internal const string HttpServerRequestDurationMetricName = "http.server.request.duration";

private const string OnStopEvent = "Microsoft.AspNetCore.Hosting.HttpRequestIn.Stop";
private const string EventName = "OnStopActivity";

private readonly Meter meter;
private readonly AspNetCoreMetricsInstrumentationOptions options;
private readonly Histogram<double> httpServerDuration;
private readonly Histogram<double> httpServerRequestDuration;
private readonly bool emitOldAttributes;
private readonly bool emitNewAttributes;

Expand All @@ -42,109 +45,172 @@ internal HttpInMetricsListener(string name, Meter meter, AspNetCoreMetricsInstru
{
this.meter = meter;
this.options = options;
this.httpServerDuration = meter.CreateHistogram<double>(HttpServerDurationMetricName, "ms", "Measures the duration of inbound HTTP requests.");

this.emitOldAttributes = this.options.HttpSemanticConvention.HasFlag(HttpSemanticConvention.Old);

this.emitNewAttributes = this.options.HttpSemanticConvention.HasFlag(HttpSemanticConvention.New);

if (this.emitOldAttributes)
{
this.httpServerDuration = meter.CreateHistogram<double>(HttpServerDurationMetricName, "ms", "Measures the duration of inbound HTTP requests.");
}

if (this.emitNewAttributes)
{
this.httpServerRequestDuration = meter.CreateHistogram<double>(HttpServerRequestDurationMetricName, "s", "Measures the duration of inbound HTTP requests.");
}
}

public override void OnEventWritten(string name, object payload)
{
if (name == OnStopEvent)
{
var context = payload as HttpContext;
if (context == null)
if (this.emitOldAttributes)
{
AspNetCoreInstrumentationEventSource.Log.NullPayload(nameof(HttpInMetricsListener), EventName, HttpServerDurationMetricName);
return;
this.OnEventWritten_Old(name, payload);
}

try
if (this.emitNewAttributes)
{
if (this.options.Filter?.Invoke(HttpServerDurationMetricName, context) == false)
{
AspNetCoreInstrumentationEventSource.Log.RequestIsFilteredOut(nameof(HttpInMetricsListener), EventName, HttpServerDurationMetricName);
return;
}
this.OnEventWritten_New(name, payload);
}
catch (Exception ex)
}
}

public void OnEventWritten_Old(string name, object payload)
{
var context = payload as HttpContext;
if (context == null)
{
AspNetCoreInstrumentationEventSource.Log.NullPayload(nameof(HttpInMetricsListener), EventName, HttpServerDurationMetricName);
return;
}

try
{
if (this.options.Filter?.Invoke(HttpServerDurationMetricName, context) == false)
{
AspNetCoreInstrumentationEventSource.Log.RequestFilterException(nameof(HttpInMetricsListener), EventName, HttpServerDurationMetricName, ex);
AspNetCoreInstrumentationEventSource.Log.RequestIsFilteredOut(nameof(HttpInMetricsListener), EventName, HttpServerDurationMetricName);
return;
}
}
catch (Exception ex)
{
AspNetCoreInstrumentationEventSource.Log.RequestFilterException(nameof(HttpInMetricsListener), EventName, HttpServerDurationMetricName, ex);
return;
}

// TODO: Prometheus pulls metrics by invoking the /metrics endpoint. Decide if it makes sense to suppress this.
// Below is just a temporary way of achieving this suppression for metrics (we should consider suppressing traces too).
// If we want to suppress activity from Prometheus then we should use SuppressInstrumentationScope.
if (context.Request.Path.HasValue && context.Request.Path.Value.Contains("metrics"))
{
return;
}

TagList tags = default;

// TODO: Prometheus pulls metrics by invoking the /metrics endpoint. Decide if it makes sense to suppress this.
// Below is just a temporary way of achieving this suppression for metrics (we should consider suppressing traces too).
// If we want to suppress activity from Prometheus then we should use SuppressInstrumentationScope.
if (context.Request.Path.HasValue && context.Request.Path.Value.Contains("metrics"))
tags.Add(new KeyValuePair<string, object>(SemanticConventions.AttributeHttpFlavor, HttpTagHelper.GetFlavorTagValueFromProtocol(context.Request.Protocol)));
tags.Add(new KeyValuePair<string, object>(SemanticConventions.AttributeHttpScheme, context.Request.Scheme));
tags.Add(new KeyValuePair<string, object>(SemanticConventions.AttributeHttpMethod, context.Request.Method));
tags.Add(new KeyValuePair<string, object>(SemanticConventions.AttributeHttpStatusCode, TelemetryHelper.GetBoxedStatusCode(context.Response.StatusCode)));

if (context.Request.Host.HasValue)
{
tags.Add(new KeyValuePair<string, object>(SemanticConventions.AttributeNetHostName, context.Request.Host.Host));

if (context.Request.Host.Port is not null && context.Request.Host.Port != 80 && context.Request.Host.Port != 443)
{
return;
tags.Add(new KeyValuePair<string, object>(SemanticConventions.AttributeNetHostPort, context.Request.Host.Port));
}
}

TagList tags = default;

// see the spec https://github.com/open-telemetry/opentelemetry-specification/blob/v1.20.0/specification/trace/semantic_conventions/http.md
if (this.emitOldAttributes)
#if NET6_0_OR_GREATER
var route = (context.GetEndpoint() as RouteEndpoint)?.RoutePattern.RawText;
if (!string.IsNullOrEmpty(route))
{
tags.Add(new KeyValuePair<string, object>(SemanticConventions.AttributeHttpRoute, route));
}
#endif
if (this.options.Enrich != null)
{
try
{
tags.Add(new KeyValuePair<string, object>(SemanticConventions.AttributeHttpFlavor, HttpTagHelper.GetFlavorTagValueFromProtocol(context.Request.Protocol)));
tags.Add(new KeyValuePair<string, object>(SemanticConventions.AttributeHttpScheme, context.Request.Scheme));
tags.Add(new KeyValuePair<string, object>(SemanticConventions.AttributeHttpMethod, context.Request.Method));
tags.Add(new KeyValuePair<string, object>(SemanticConventions.AttributeHttpStatusCode, TelemetryHelper.GetBoxedStatusCode(context.Response.StatusCode)));

if (context.Request.Host.HasValue)
{
tags.Add(new KeyValuePair<string, object>(SemanticConventions.AttributeNetHostName, context.Request.Host.Host));

if (context.Request.Host.Port is not null && context.Request.Host.Port != 80 && context.Request.Host.Port != 443)
{
tags.Add(new KeyValuePair<string, object>(SemanticConventions.AttributeNetHostPort, context.Request.Host.Port));
}
}
this.options.Enrich(HttpServerDurationMetricName, context, ref tags);
}
catch (Exception ex)
{
AspNetCoreInstrumentationEventSource.Log.EnrichmentException(nameof(HttpInMetricsListener), EventName, HttpServerDurationMetricName, ex);
}
}

// see the spec https://github.com/open-telemetry/semantic-conventions/blob/v1.21.0/docs/http/http-spans.md
if (this.emitNewAttributes)
// We are relying here on ASP.NET Core to set duration before writing the stop event.
// https://github.com/dotnet/aspnetcore/blob/d6fa351048617ae1c8b47493ba1abbe94c3a24cf/src/Hosting/Hosting/src/Internal/HostingApplicationDiagnostics.cs#L449
// TODO: Follow up with .NET team if we can continue to rely on this behavior.
this.httpServerDuration.Record(Activity.Current.Duration.TotalMilliseconds, tags);
}

public void OnEventWritten_New(string name, object payload)
{
var context = payload as HttpContext;
if (context == null)
{
AspNetCoreInstrumentationEventSource.Log.NullPayload(nameof(HttpInMetricsListener), EventName, HttpServerRequestDurationMetricName);
return;
}

try
{
if (this.options.Filter?.Invoke(HttpServerRequestDurationMetricName, context) == false)
{
tags.Add(new KeyValuePair<string, object>(SemanticConventions.AttributeNetworkProtocolVersion, HttpTagHelper.GetFlavorTagValueFromProtocol(context.Request.Protocol)));
tags.Add(new KeyValuePair<string, object>(SemanticConventions.AttributeUrlScheme, context.Request.Scheme));
tags.Add(new KeyValuePair<string, object>(SemanticConventions.AttributeHttpRequestMethod, context.Request.Method));
tags.Add(new KeyValuePair<string, object>(SemanticConventions.AttributeHttpResponseStatusCode, TelemetryHelper.GetBoxedStatusCode(context.Response.StatusCode)));

if (context.Request.Host.HasValue)
{
tags.Add(new KeyValuePair<string, object>(SemanticConventions.AttributeServerAddress, context.Request.Host.Host));

if (context.Request.Host.Port is not null && context.Request.Host.Port != 80 && context.Request.Host.Port != 443)
{
tags.Add(new KeyValuePair<string, object>(SemanticConventions.AttributeServerPort, context.Request.Host.Port));
}
}
AspNetCoreInstrumentationEventSource.Log.RequestIsFilteredOut(nameof(HttpInMetricsListener), EventName, HttpServerRequestDurationMetricName);
return;
}
}
catch (Exception ex)
{
AspNetCoreInstrumentationEventSource.Log.RequestFilterException(nameof(HttpInMetricsListener), EventName, HttpServerRequestDurationMetricName, ex);
return;
}

// TODO: Prometheus pulls metrics by invoking the /metrics endpoint. Decide if it makes sense to suppress this.
// Below is just a temporary way of achieving this suppression for metrics (we should consider suppressing traces too).
// If we want to suppress activity from Prometheus then we should use SuppressInstrumentationScope.
if (context.Request.Path.HasValue && context.Request.Path.Value.Contains("metrics"))
{
return;
}

TagList tags = default;

// see the spec https://github.com/open-telemetry/semantic-conventions/blob/v1.21.0/docs/http/http-spans.md
tags.Add(new KeyValuePair<string, object>(SemanticConventions.AttributeNetworkProtocolVersion, HttpTagHelper.GetFlavorTagValueFromProtocol(context.Request.Protocol)));
tags.Add(new KeyValuePair<string, object>(SemanticConventions.AttributeUrlScheme, context.Request.Scheme));
tags.Add(new KeyValuePair<string, object>(SemanticConventions.AttributeHttpRequestMethod, context.Request.Method));
tags.Add(new KeyValuePair<string, object>(SemanticConventions.AttributeHttpResponseStatusCode, TelemetryHelper.GetBoxedStatusCode(context.Response.StatusCode)));

#if NET6_0_OR_GREATER
var route = (context.GetEndpoint() as RouteEndpoint)?.RoutePattern.RawText;
if (!string.IsNullOrEmpty(route))
var route = (context.GetEndpoint() as RouteEndpoint)?.RoutePattern.RawText;
if (!string.IsNullOrEmpty(route))
{
tags.Add(new KeyValuePair<string, object>(SemanticConventions.AttributeHttpRoute, route));
}
#endif
if (this.options.Enrich != null)
{
try
{
tags.Add(new KeyValuePair<string, object>(SemanticConventions.AttributeHttpRoute, route));
this.options.Enrich(HttpServerRequestDurationMetricName, context, ref tags);
}
#endif
if (this.options.Enrich != null)
catch (Exception ex)
{
try
{
this.options.Enrich(HttpServerDurationMetricName, context, ref tags);
}
catch (Exception ex)
{
AspNetCoreInstrumentationEventSource.Log.EnrichmentException(nameof(HttpInMetricsListener), EventName, HttpServerDurationMetricName, ex);
}
AspNetCoreInstrumentationEventSource.Log.EnrichmentException(nameof(HttpInMetricsListener), EventName, HttpServerRequestDurationMetricName, ex);
}

// We are relying here on ASP.NET Core to set duration before writing the stop event.
// https://github.com/dotnet/aspnetcore/blob/d6fa351048617ae1c8b47493ba1abbe94c3a24cf/src/Hosting/Hosting/src/Internal/HostingApplicationDiagnostics.cs#L449
// TODO: Follow up with .NET team if we can continue to rely on this behavior.
this.httpServerDuration.Record(Activity.Current.Duration.TotalMilliseconds, tags);
}

// We are relying here on ASP.NET Core to set duration before writing the stop event.
// https://github.com/dotnet/aspnetcore/blob/d6fa351048617ae1c8b47493ba1abbe94c3a24cf/src/Hosting/Hosting/src/Internal/HostingApplicationDiagnostics.cs#L449
// TODO: Follow up with .NET team if we can continue to rely on this behavior.
this.httpServerRequestDuration.Record(Activity.Current.Duration.TotalSeconds, tags);
}
}
28 changes: 22 additions & 6 deletions src/OpenTelemetry.Instrumentation.AspNetCore/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,13 +90,29 @@ public void ConfigureServices(IServiceCollection services)

#### List of metrics produced

The instrumentation is implemented based on [metrics semantic
conventions](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/semantic_conventions/http-metrics.md#metric-httpserverduration).
Currently, the instrumentation supports the following metric.
The instrumentation is implemented based on
[metrics semantic conventions](https://github.com/open-telemetry/semantic-conventions/blob/4bbb8c907402caa90bc077214e8a2c78807c1ab9/docs/http/http-metrics.md).

| Name | Instrument Type | Unit | Description |
|-------|-----------------|------|-------------|
| `http.server.duration` | Histogram | `ms` | Measures the duration of inbound HTTP requests. |
Have you opt-ed into the new Http Semantic Conventions using `OTEL_SEMCONV_STABILITY_OPT_IN`?
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Have you opt-ed into the new Http Semantic Conventions using `OTEL_SEMCONV_STABILITY_OPT_IN`?
Have you opted in to the new Http Semantic Conventions using `OTEL_SEMCONV_STABILITY_OPT_IN`?


* If yes, the instrumentation supports the following metric.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is not clear. The env variable can take none,http,http/dup as values, This doc should also be structured in that way. i.e what if the env variable is set to "none", (also the default)
what is the env varaible is set to "http"
what is the env varaible is set to "http/dup" - both metric are emitted


| Name | Instrument Type | Unit | Description |
|-------|-----------------|------|-------------|
| `http.server.request.duration` | Histogram | `s` | Measures the duration of inbound HTTP requests. |
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it'd be good to callout here that SDK uses a special treatment for this metric by using a suitable buckets.
https://github.com/open-telemetry/opentelemetry-dotnet/pull/4820/files

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How much information are you looking for?
Is it sufficient to say "http.server.request.duration uses unique buckets suitable for seconds" ?

I could include a link to the spec which shows the buckets:
https://github.com/open-telemetry/semantic-conventions/blob/main/docs/http/http-metrics.md#metric-httpserverrequestduration

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

something along the lines of
"This metric is emitted in "s" as unit, as per the semantic convention guide. The convention also recommends to provide a custom buckets (link), but that capability is not yet available in OTel .NET. A workaround is already included in the OTel SDK (link), which specially treats this metric, and uses the recommended buckets"

^ feel free to edit/modify!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated. please re-review

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd highlight/make it clear that the workaround is "OpenTelemetry SDK specially treats this metric and uses a diff. default for histogram buckets, matching the recommended buckets" /similar wording. This will ensure most folks do not have any need to go and read the linked PR.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the linked PR is very light on details. That must be fixed separately. Specifically,

  1. it should list the exact name of the metrics for which SDK uses a diff. default.
  2. make it clear that the special treatment is only for the default case. If user overrides the buckets, then that'll always be respected.

(Not part of this PR, but this is essential to get the whole transition smoother for end users)


This metric is emitted in `seconds` as per the semantic convention. While
TimothyMothra marked this conversation as resolved.
Show resolved Hide resolved
the convention [recommends using custom histogram buckets](https://github.com/open-telemetry/semantic-conventions/blob/main/docs/http/http-metrics.md#metric-httpserverrequestduration)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use the commit tag?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm conflicted here.
I would rather link to an explicit tag. There changes we're implementing now are post v1.21.0, but this repo hasn't made a new release yet.

I can change links in both the Readme and Changelog to a commit as you've suggested.
When the next release happens (presumably v1.22.0) I think we should update these links.

, this feature is not yet available via .NET Metrics API.
A [workaround](https://github.com/open-telemetry/opentelemetry-dotnet/pull/4820)
has been included in OTel SDK starting version `1.6.0` which applies
recommended buckets by default for this metric.

* If no, the instrumentation supports the following metric.

| Name | Instrument Type | Unit | Description |
|-------|-----------------|------|-------------|
| `http.server.duration` | Histogram | `ms` | Measures the duration of inbound HTTP requests. |

## Advanced configuration

Expand Down
Loading