Skip to content
Open
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Messaging;
using Datadog.Trace.ClrProfiler.CallTarget;
using Datadog.Trace.OpenTelemetry;
using Datadog.Trace.Tagging;
using Datadog.Trace.Util;
using Datadog.Trace.Util.Http;
Expand Down Expand Up @@ -72,6 +73,13 @@ internal static CallTargetReturn<TReturn> OnMethodEnd<TTarget, TReturn>(TTarget
if (state.Scope?.Span is Span span && span.Tags is HttpTags httpTags && returnValue is HttpWebRequest request)
{
var requestUri = request.RequestUri;

if (span.OpenTelemetrySemanticsEnabled)
{
HttpSemanticConventions.SetHttpClientRequestValues(span, httpTags, request.Method, requestUri, Tracer.Instance.TracerManager.QueryStringManager);
return new CallTargetReturn<TReturn>(returnValue);
}

var requestMethod = request.Method.ToUpperInvariant();

if (requestUri != null)
Expand Down
22 changes: 15 additions & 7 deletions tracer/src/Datadog.Trace/ClrProfiler/ScopeFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using Datadog.Trace.Configuration;
using Datadog.Trace.Configuration.Schema;
using Datadog.Trace.Logging;
using Datadog.Trace.OpenTelemetry;
using Datadog.Trace.Tagging;
using Datadog.Trace.Util;
using Datadog.Trace.Util.Http;
Expand Down Expand Up @@ -109,22 +110,29 @@ internal static Span CreateInactiveOutboundHttpSpan(
return null;
}

string resourceUrl = requestUri != null ? UriHelpers.CleanUri(requestUri, removeScheme: true, tryRemoveIds: true) : null;

var operationName = tracer.CurrentTraceSettings.Schema.Client.GetOperationNameForProtocol(ClientSchema.Protocol.Http);
var (serviceName, serviceNameSource) = tracer.CurrentTraceSettings.Schema.Client.GetServiceNameMetadata(ClientSchema.Component.Http);
tags = tracer.CurrentTraceSettings.Schema.Client.CreateHttpTags();

span = tracer.StartSpan(operationName, tags, serviceName: serviceName, serviceNameSource: serviceNameSource, traceId: traceId, spanId: spanId, startTime: startTime, addToTraceContext: addToTraceContext);

span.Type = SpanTypes.Http;
span.ResourceName = $"{httpMethod} {resourceUrl}";

tags.HttpMethod = httpMethod?.ToUpperInvariant();
if (requestUri is not null)
if (span.OpenTelemetrySemanticsEnabled)
{
HttpSemanticConventions.SetHttpClientRequestValues(span, tags, httpMethod, requestUri, tracer.TracerManager.QueryStringManager);
}
else
{
tags.HttpUrl = HttpRequestUtils.GetUrl(requestUri, tracer.TracerManager.QueryStringManager);
tags.Host = HttpRequestUtils.GetNormalizedHost(requestUri.Host);
string resourceUrl = requestUri != null ? UriHelpers.CleanUri(requestUri, removeScheme: true, tryRemoveIds: true) : null;
span.ResourceName = $"{httpMethod} {resourceUrl}";

tags.HttpMethod = httpMethod?.ToUpperInvariant();
if (requestUri is not null)
{
tags.HttpUrl = HttpRequestUtils.GetUrl(requestUri, tracer.TracerManager.QueryStringManager);
tags.Host = HttpRequestUtils.GetNormalizedHost(requestUri.Host);
}
}

tags.InstrumentationName = IntegrationRegistry.GetName(integrationId);
Expand Down
10 changes: 10 additions & 0 deletions tracer/src/Datadog.Trace/Configuration/TracerSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -818,6 +818,16 @@ not null when string.Equals(value, "otlp", StringComparison.OrdinalIgnoreCase) =
.WithKeys(ConfigurationKeys.OpenTelemetry.OtelSemanticsEnabled)
.AsBool(defaultValue: false);

if (OtelSemanticsEnabled && MetadataSchemaVersion != SchemaVersion.V0)
{
// OpenTelemetry semantics mode already fully replaces Datadog attribute naming and values,
// so the V1 schema's Datadog-only attributes (e.g. peer.service) must not be layered on top.
Log.Warning(
$"{ConfigurationKeys.MetadataSchemaVersion} is set to a version other than v0, but {ConfigurationKeys.OpenTelemetry.OtelSemanticsEnabled} is enabled. Using v0 instead.");
MetadataSchemaVersion = SchemaVersion.V0;
telemetry.Record(ConfigurationKeys.MetadataSchemaVersion, "v0", recordValue: true, ConfigurationOrigins.Calculated);
}

var disabledActivitySources = config.WithKeys(ConfigurationKeys.DisabledActivitySources).AsString();

DisabledActivitySources = !string.IsNullOrEmpty(disabledActivitySources) ? TrimSplitString(disabledActivitySources, commaSeparator) : [];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,18 @@ partial class HttpTags
// HttpMethodBytes = MessagePack.Serialize("http.method");
private static ReadOnlySpan<byte> HttpMethodBytes => [171, 104, 116, 116, 112, 46, 109, 101, 116, 104, 111, 100];

// HttpMethodOtelBytes = MessagePack.Serialize("http.request.method");
private static ReadOnlySpan<byte> HttpMethodOtelBytes => [179, 104, 116, 116, 112, 46, 114, 101, 113, 117, 101, 115, 116, 46, 109, 101, 116, 104, 111, 100];

// HttpRequestMethodOriginalBytes = MessagePack.Serialize("http.request.method_original");
private static ReadOnlySpan<byte> HttpRequestMethodOriginalBytes => [188, 104, 116, 116, 112, 46, 114, 101, 113, 117, 101, 115, 116, 46, 109, 101, 116, 104, 111, 100, 95, 111, 114, 105, 103, 105, 110, 97, 108];

// HttpUrlBytes = MessagePack.Serialize("http.url");
private static ReadOnlySpan<byte> HttpUrlBytes => [168, 104, 116, 116, 112, 46, 117, 114, 108];

// HttpUrlOtelBytes = MessagePack.Serialize("url.full");
private static ReadOnlySpan<byte> HttpUrlOtelBytes => [168, 117, 114, 108, 46, 102, 117, 108, 108];

// HttpClientHandlerTypeBytes = MessagePack.Serialize("http-client-handler-type");
private static ReadOnlySpan<byte> HttpClientHandlerTypeBytes => [184, 104, 116, 116, 112, 45, 99, 108, 105, 101, 110, 116, 45, 104, 97, 110, 100, 108, 101, 114, 45, 116, 121, 112, 101];

Expand All @@ -38,18 +47,29 @@ partial class HttpTags
// HostBytes = MessagePack.Serialize("out.host");
private static ReadOnlySpan<byte> HostBytes => [168, 111, 117, 116, 46, 104, 111, 115, 116];

// HostOtelBytes = MessagePack.Serialize("server.address");
private static ReadOnlySpan<byte> HostOtelBytes => [174, 115, 101, 114, 118, 101, 114, 46, 97, 100, 100, 114, 101, 115, 115];

// ServerPortBytes = MessagePack.Serialize("server.port");
private static ReadOnlySpan<byte> ServerPortBytes => [171, 115, 101, 114, 118, 101, 114, 46, 112, 111, 114, 116];

public override string? GetTag(string key)
{
return key switch
{
"span.kind" => SpanKind,
"component" => InstrumentationName,
"http.method" => HttpMethod,
"http.request.method" => HttpMethod,
"http.request.method_original" => HttpRequestMethodOriginal,
"http.url" => HttpUrl,
"url.full" => HttpUrl,
"http-client-handler-type" => HttpClientHandlerType,
"http.status_code" => HttpStatusCode is null ? null : Datadog.Trace.Util.IntStringCache.ToInvariantString(HttpStatusCode.Value),
"http.response.status_code" => HttpStatusCode is null ? null : Datadog.Trace.Util.IntStringCache.ToInvariantString(HttpStatusCode.Value),
"out.host" => Host,
"server.address" => Host,
"server.port" => ServerPort is null ? null : Datadog.Trace.Util.IntStringCache.ToInvariantString(ServerPort.Value),
_ => base.GetTag(key),
};
}
Expand All @@ -61,10 +81,15 @@ public override void SetTag(string key, string? value)
case "component":
InstrumentationName = value;
break;
case "http.method":
case "http.method":
case "http.request.method":
HttpMethod = value;
break;
case "http.url":
case "http.request.method_original":
HttpRequestMethodOriginal = value;
break;
case "http.url":
case "url.full":
HttpUrl = value;
break;
case "http-client-handler-type":
Expand All @@ -82,8 +107,20 @@ public override void SetTag(string key, string? value)
}

break;
case "out.host":
case "out.host":
case "server.address":
Host = value;
break;
case "server.port":
if (int.TryParse(value, System.Globalization.NumberStyles.Integer, System.Globalization.CultureInfo.InvariantCulture, out var parsedServerPort))
{
ServerPort = parsedServerPort;
}
else
{
ServerPort = null;
}

break;
case "span.kind":
Logger.Value.Warning("Attempted to set readonly tag {TagName} on {TagType}. Ignoring.", key, nameof(HttpTags));
Expand All @@ -108,12 +145,31 @@ public override void EnumerateTags<TProcessor>(ref TProcessor processor, bool op

if (HttpMethod is not null)
{
processor.Process(new TagItem<string>("http.method", HttpMethod, HttpMethodBytes));
if (openTelemetrySemanticsEnabled)
{
processor.Process(new TagItem<string>("http.request.method", HttpMethod, HttpMethodOtelBytes));
}
else
{
processor.Process(new TagItem<string>("http.method", HttpMethod, HttpMethodBytes));
}
}

if (HttpRequestMethodOriginal is not null)
{
processor.Process(new TagItem<string>("http.request.method_original", HttpRequestMethodOriginal, HttpRequestMethodOriginalBytes));
}

if (HttpUrl is not null)
{
processor.Process(new TagItem<string>("http.url", HttpUrl, HttpUrlBytes));
if (openTelemetrySemanticsEnabled)
{
processor.Process(new TagItem<string>("url.full", HttpUrl, HttpUrlOtelBytes));
}
else
{
processor.Process(new TagItem<string>("http.url", HttpUrl, HttpUrlBytes));
}
}

if (HttpClientHandlerType is not null)
Expand All @@ -135,7 +191,19 @@ public override void EnumerateTags<TProcessor>(ref TProcessor processor, bool op

if (Host is not null)
{
processor.Process(new TagItem<string>("out.host", Host, HostBytes));
if (openTelemetrySemanticsEnabled)
{
processor.Process(new TagItem<string>("server.address", Host, HostOtelBytes));
}
else
{
processor.Process(new TagItem<string>("out.host", Host, HostBytes));
}
}

if (ServerPort is not null)
{
processor.Process(new TagItem<int>("server.port", ServerPort.Value, ServerPortBytes));
}

base.EnumerateTags(ref processor, openTelemetrySemanticsEnabled);
Expand Down Expand Up @@ -164,6 +232,13 @@ protected override void WriteAdditionalTags(System.Text.StringBuilder sb)
.Append(',');
}

if (HttpRequestMethodOriginal is not null)
{
sb.Append("http.request.method_original (tag):")
.Append(HttpRequestMethodOriginal)
.Append(',');
}

if (HttpUrl is not null)
{
sb.Append("http.url (tag):")
Expand Down Expand Up @@ -192,6 +267,13 @@ protected override void WriteAdditionalTags(System.Text.StringBuilder sb)
.Append(',');
}

if (ServerPort is not null)
{
sb.Append("server.port (tag):")
.Append(ServerPort.Value.ToString(System.Globalization.CultureInfo.InvariantCulture))
.Append(',');
}

base.WriteAdditionalTags(sb);
}
}
Expand Down
Loading
Loading