Skip to content

Commit d1d6d4b

Browse files
[HttpClient & HttpWebRequest] Set http.request.method as per spec (#5003)
1 parent 5cb7a3f commit d1d6d4b

File tree

11 files changed

+224
-43
lines changed

11 files changed

+224
-43
lines changed

src/OpenTelemetry.Instrumentation.AspNetCore/Implementation/HttpInListener.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -252,13 +252,15 @@ public void OnStartActivity(Activity activity, object payload)
252252
activity.SetTag(SemanticConventions.AttributeUrlQuery, request.QueryString.Value);
253253
}
254254

255-
if (RequestMethodHelper.TryResolveHttpMethod(request.Method, out var httpMethod))
255+
if (RequestMethodHelper.KnownMethods.TryGetValue(request.Method, out var httpMethod))
256256
{
257257
activity.SetTag(SemanticConventions.AttributeHttpRequestMethod, httpMethod);
258258
}
259259
else
260260
{
261-
activity.SetTag(SemanticConventions.AttributeHttpRequestMethod, httpMethod);
261+
// Set to default "_OTHER" as per spec.
262+
// https://github.com/open-telemetry/semantic-conventions/blob/v1.22.0/docs/http/http-spans.md#common-attributes
263+
activity.SetTag(SemanticConventions.AttributeHttpRequestMethod, "_OTHER");
262264
activity.SetTag(SemanticConventions.AttributeHttpRequestMethodOriginal, request.Method);
263265
}
264266

src/OpenTelemetry.Instrumentation.AspNetCore/Implementation/HttpInMetricsListener.cs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
// limitations under the License.
1515
// </copyright>
1616

17-
#if !NET8_0_OR_GREATER
1817
using System.Diagnostics;
1918
using System.Diagnostics.Metrics;
2019
using Microsoft.AspNetCore.Http;
@@ -153,8 +152,16 @@ public void OnEventWritten_New(string name, object payload)
153152
tags.Add(new KeyValuePair<string, object>(SemanticConventions.AttributeNetworkProtocolVersion, HttpTagHelper.GetFlavorTagValueFromProtocol(context.Request.Protocol)));
154153
tags.Add(new KeyValuePair<string, object>(SemanticConventions.AttributeUrlScheme, context.Request.Scheme));
155154
tags.Add(new KeyValuePair<string, object>(SemanticConventions.AttributeHttpResponseStatusCode, TelemetryHelper.GetBoxedStatusCode(context.Response.StatusCode)));
156-
RequestMethodHelper.TryResolveHttpMethod(context.Request.Method, out var httpMethod);
157-
tags.Add(new KeyValuePair<string, object>(SemanticConventions.AttributeHttpRequestMethod, httpMethod));
155+
if (RequestMethodHelper.KnownMethods.TryGetValue(context.Request.Method, out var httpMethod))
156+
{
157+
tags.Add(new KeyValuePair<string, object>(SemanticConventions.AttributeHttpRequestMethod, httpMethod));
158+
}
159+
else
160+
{
161+
// Set to default "_OTHER" as per spec.
162+
// https://github.com/open-telemetry/semantic-conventions/blob/v1.22.0/docs/http/http-spans.md#common-attributes
163+
tags.Add(new KeyValuePair<string, object>(SemanticConventions.AttributeHttpRequestMethod, "_OTHER"));
164+
}
158165

159166
#if NET6_0_OR_GREATER
160167
var route = (context.GetEndpoint() as RouteEndpoint)?.RoutePattern.RawText;
@@ -170,4 +177,3 @@ public void OnEventWritten_New(string name, object payload)
170177
this.httpServerRequestDuration.Record(Activity.Current.Duration.TotalSeconds, tags);
171178
}
172179
}
173-
#endif

src/OpenTelemetry.Instrumentation.Http/CHANGELOG.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,22 @@
22

33
## Unreleased
44

5+
* Updated `http.request.method` to match specification guidelines.
6+
* For activity, if the method does not belong to one of the [known
7+
values](https://github.com/open-telemetry/semantic-conventions/blob/v1.22.0/docs/http/http-spans.md#:~:text=http.request.method%20has%20the%20following%20list%20of%20well%2Dknown%20values)
8+
then the request method will be set on an additional tag
9+
`http.request.method.original` and `http.request.method` will be set to
10+
`_OTHER`.
11+
* For metrics, if the original method does not belong to one of the [known
12+
values](https://github.com/open-telemetry/semantic-conventions/blob/v1.22.0/docs/http/http-spans.md#:~:text=http.request.method%20has%20the%20following%20list%20of%20well%2Dknown%20values)
13+
then `http.request.method` on `http.client.request.duration` metric will be
14+
set to `_OTHER`
15+
16+
`http.request.method` is set on `http.client.request.duration` metric or
17+
activity when `OTEL_SEMCONV_STABILITY_OPT_IN` environment variable is set to
18+
`http` or `http/dup`.
19+
([#5003](https://github.com/open-telemetry/opentelemetry-dotnet/pull/5003))
20+
521
## 1.6.0-beta.2
622

723
Released 2023-Oct-26

src/OpenTelemetry.Instrumentation.Http/Implementation/HttpHandlerDiagnosticListener.cs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#endif
2424
using System.Reflection;
2525
using OpenTelemetry.Context.Propagation;
26+
using OpenTelemetry.Internal;
2627
using OpenTelemetry.Trace;
2728
using static OpenTelemetry.Internal.HttpSemanticConventionHelper;
2829

@@ -185,7 +186,18 @@ public void OnStartActivity(Activity activity, object payload)
185186
// see the spec https://github.com/open-telemetry/semantic-conventions/blob/v1.21.0/docs/http/http-spans.md
186187
if (this.emitNewAttributes)
187188
{
188-
activity.SetTag(SemanticConventions.AttributeHttpRequestMethod, HttpTagHelper.GetNameForHttpMethod(request.Method));
189+
if (RequestMethodHelper.KnownMethods.TryGetValue(request.Method.Method, out var httpMethod))
190+
{
191+
activity.SetTag(SemanticConventions.AttributeHttpRequestMethod, httpMethod);
192+
}
193+
else
194+
{
195+
// Set to default "_OTHER" as per spec.
196+
// https://github.com/open-telemetry/semantic-conventions/blob/v1.22.0/docs/http/http-spans.md#common-attributes
197+
activity.SetTag(SemanticConventions.AttributeHttpRequestMethod, "_OTHER");
198+
activity.SetTag(SemanticConventions.AttributeHttpRequestMethodOriginal, request.Method.Method);
199+
}
200+
189201
activity.SetTag(SemanticConventions.AttributeServerAddress, request.RequestUri.Host);
190202
if (!request.RequestUri.IsDefaultPort)
191203
{

src/OpenTelemetry.Instrumentation.Http/Implementation/HttpHandlerMetricsDiagnosticListener.cs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
using System.Net.Http;
2424
#endif
2525
using System.Reflection;
26+
using OpenTelemetry.Internal;
2627
using OpenTelemetry.Trace;
2728
using static OpenTelemetry.Internal.HttpSemanticConventionHelper;
2829

@@ -97,7 +98,17 @@ public override void OnEventWritten(string name, object payload)
9798
{
9899
TagList tags = default;
99100

100-
tags.Add(new KeyValuePair<string, object>(SemanticConventions.AttributeHttpRequestMethod, HttpTagHelper.GetNameForHttpMethod(request.Method)));
101+
if (RequestMethodHelper.KnownMethods.TryGetValue(request.Method.Method, out var httpMethod))
102+
{
103+
tags.Add(new KeyValuePair<string, object>(SemanticConventions.AttributeHttpRequestMethod, httpMethod));
104+
}
105+
else
106+
{
107+
// Set to default "_OTHER" as per spec.
108+
// https://github.com/open-telemetry/semantic-conventions/blob/v1.22.0/docs/http/http-spans.md#common-attributes
109+
tags.Add(new KeyValuePair<string, object>(SemanticConventions.AttributeHttpRequestMethod, "_OTHER"));
110+
}
111+
101112
tags.Add(new KeyValuePair<string, object>(SemanticConventions.AttributeNetworkProtocolVersion, HttpTagHelper.GetFlavorTagValueFromProtocolVersion(request.Version)));
102113
tags.Add(new KeyValuePair<string, object>(SemanticConventions.AttributeServerAddress, request.RequestUri.Host));
103114
tags.Add(new KeyValuePair<string, object>(SemanticConventions.AttributeUrlScheme, request.RequestUri.Scheme));

src/OpenTelemetry.Instrumentation.Http/Implementation/HttpWebRequestActivitySource.netfx.cs

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
using System.Reflection.Emit;
2424
using System.Runtime.CompilerServices;
2525
using OpenTelemetry.Context.Propagation;
26+
using OpenTelemetry.Internal;
2627
using OpenTelemetry.Trace;
2728
using static OpenTelemetry.Internal.HttpSemanticConventionHelper;
2829

@@ -153,7 +154,18 @@ private static void AddRequestTagsAndInstrumentRequest(HttpWebRequest request, A
153154
// see the spec https://github.com/open-telemetry/semantic-conventions/blob/v1.21.0/docs/http/http-spans.md
154155
if (tracingEmitNewAttributes)
155156
{
156-
activity.SetTag(SemanticConventions.AttributeHttpRequestMethod, request.Method);
157+
if (RequestMethodHelper.KnownMethods.TryGetValue(request.Method, out var httpMethod))
158+
{
159+
activity.SetTag(SemanticConventions.AttributeHttpRequestMethod, httpMethod);
160+
}
161+
else
162+
{
163+
// Set to default "_OTHER" as per spec.
164+
// https://github.com/open-telemetry/semantic-conventions/blob/v1.22.0/docs/http/http-spans.md#common-attributes
165+
activity.SetTag(SemanticConventions.AttributeHttpRequestMethod, "_OTHER");
166+
activity.SetTag(SemanticConventions.AttributeHttpRequestMethodOriginal, request.Method);
167+
}
168+
157169
activity.SetTag(SemanticConventions.AttributeServerAddress, request.RequestUri.Host);
158170
if (!request.RequestUri.IsDefaultPort)
159171
{
@@ -495,7 +507,17 @@ private static void ProcessResult(IAsyncResult asyncResult, AsyncCallback asyncC
495507
{
496508
TagList tags = default;
497509

498-
tags.Add(SemanticConventions.AttributeHttpRequestMethod, request.Method);
510+
if (RequestMethodHelper.KnownMethods.TryGetValue(request.Method, out var httpMethod))
511+
{
512+
tags.Add(new KeyValuePair<string, object>(SemanticConventions.AttributeHttpRequestMethod, httpMethod));
513+
}
514+
else
515+
{
516+
// Set to default "_OTHER" as per spec.
517+
// https://github.com/open-telemetry/semantic-conventions/blob/v1.22.0/docs/http/http-spans.md#common-attributes
518+
tags.Add(new KeyValuePair<string, object>(SemanticConventions.AttributeHttpRequestMethod, "_OTHER"));
519+
}
520+
499521
tags.Add(SemanticConventions.AttributeServerAddress, request.RequestUri.Host);
500522
tags.Add(SemanticConventions.AttributeUrlScheme, request.RequestUri.Scheme);
501523
tags.Add(SemanticConventions.AttributeNetworkProtocolVersion, HttpTagHelper.GetFlavorTagValueFromProtocolVersion(request.ProtocolVersion));

src/OpenTelemetry.Instrumentation.Http/MeterProviderBuilderExtensions.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,9 @@ public static MeterProviderBuilder AddHttpClientInstrumentation(
4545
.AddMeter("System.Net.Http")
4646
.AddMeter("System.Net.NameResolution");
4747
#else
48-
// Note: Warm-up the status code mapping.
48+
// Note: Warm-up the status code and method mapping.
4949
_ = TelemetryHelper.BoxedStatusCodes;
50+
_ = RequestMethodHelper.KnownMethods;
5051

5152
builder.ConfigureServices(services =>
5253
{

src/OpenTelemetry.Instrumentation.Http/OpenTelemetry.Instrumentation.Http.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
<Compile Include="$(RepoRoot)\src\Shared\HttpSemanticConventionHelper.cs" Link="Includes\HttpSemanticConventionHelper.cs" />
1717
<Compile Include="$(RepoRoot)\src\Shared\Options\*.cs" Link="Includes\Options\%(Filename).cs" />
1818
<Compile Include="$(RepoRoot)\src\Shared\Shims\NullableAttributes.cs" Link="Includes\Shims\NullableAttributes.cs" />
19+
<Compile Include="$(RepoRoot)\src\Shared\RequestMethodHelper.cs" Link="Includes\RequestMethodHelper.cs" />
1920
</ItemGroup>
2021

2122
<ItemGroup Condition="'$(RunningDotNetPack)' != 'true'">

src/OpenTelemetry.Instrumentation.Http/TracerProviderBuilderExtensions.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,9 @@ public static TracerProviderBuilder AddHttpClientInstrumentation(
6060
{
6161
Guard.ThrowIfNull(builder);
6262

63-
// Note: Warm-up the status code mapping.
63+
// Note: Warm-up the status code and method mapping.
6464
_ = TelemetryHelper.BoxedStatusCodes;
65+
_ = RequestMethodHelper.KnownMethods;
6566

6667
name ??= Options.DefaultName;
6768

src/Shared/RequestMethodHelper.cs

Lines changed: 7 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -30,23 +30,7 @@ internal static class RequestMethodHelper
3030

3131
static RequestMethodHelper()
3232
{
33-
#if NET8_0_OR_GREATER
34-
KnownMethods = FrozenDictionary.ToFrozenDictionary(
35-
new[]
36-
{
37-
KeyValuePair.Create("GET", "GET"),
38-
KeyValuePair.Create("PUT", "PUT"),
39-
KeyValuePair.Create("POST", "POST"),
40-
KeyValuePair.Create("DELETE", "DELETE"),
41-
KeyValuePair.Create("HEAD", "HEAD"),
42-
KeyValuePair.Create("OPTIONS", "OPTIONS"),
43-
KeyValuePair.Create("TRACE", "TRACE"),
44-
KeyValuePair.Create("PATCH", "PATCH"),
45-
KeyValuePair.Create("CONNECT", "CONNECT"),
46-
},
47-
StringComparer.OrdinalIgnoreCase);
48-
#else
49-
KnownMethods = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
33+
var knownMethodSet = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
5034
{
5135
{ "GET", "GET" },
5236
{ "PUT", "PUT" },
@@ -58,20 +42,12 @@ static RequestMethodHelper()
5842
{ "PATCH", "PATCH" },
5943
{ "CONNECT", "CONNECT" },
6044
};
61-
#endif
62-
}
63-
64-
public static bool TryResolveHttpMethod(string method, out string resolvedMethod)
65-
{
66-
if (KnownMethods.TryGetValue(method, out resolvedMethod))
67-
{
68-
// KnownMethods ignores case. Use the value returned by the dictionary to have a consistent case.
69-
return true;
70-
}
7145

72-
// Set to default "_OTHER" as per spec.
73-
// https://github.com/open-telemetry/semantic-conventions/blob/v1.22.0/docs/http/http-spans.md#common-attributes
74-
resolvedMethod = "_OTHER";
75-
return false;
46+
// KnownMethods ignores case. Use the value returned by the dictionary to have a consistent case.
47+
#if NET8_0_OR_GREATER
48+
KnownMethods = FrozenDictionary.ToFrozenDictionary(knownMethodSet, StringComparer.OrdinalIgnoreCase);
49+
#else
50+
KnownMethods = knownMethodSet;
51+
#endif
7652
}
7753
}

0 commit comments

Comments
 (0)