Skip to content

Commit 6385c47

Browse files
khanayan123claude
andcommitted
Optimize TelemetryHttpHeaderNames per review feedback
- Use pre-sized arrays instead of List<T> + ToArray() - Lazy-initialize HttpSerializedDefaultAgentHeaders - Use StringBuilderCache instead of string concatenation - Consolidate duplicate RuntimeId.Get() calls Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent d7ec963 commit 6385c47

1 file changed

Lines changed: 51 additions & 41 deletions

File tree

tracer/src/Datadog.Trace/Telemetry/TelemetryHttpHeaderNames.cs

Lines changed: 51 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -3,90 +3,100 @@
33
// This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2017 Datadog, Inc.
44
// </copyright>
55

6+
using System;
67
using System.Collections.Generic;
8+
using System.Threading;
79
using Datadog.Trace.HttpOverStreams;
810
using Datadog.Trace.Util;
911

1012
namespace Datadog.Trace.Telemetry
1113
{
1214
internal static class TelemetryHttpHeaderNames
1315
{
16+
private static string _httpSerializedDefaultAgentHeaders;
17+
1418
/// <summary>
1519
/// Gets the default agent headers in the format <c>Key: Value\r\n</c>. For use in HTTP headers.
16-
/// Not a const because session headers depend on runtime values.
20+
/// Lazily initialized because session headers depend on runtime values.
1721
/// </summary>
18-
internal static string HttpSerializedDefaultAgentHeaders { get; } = BuildSerializedAgentHeaders();
22+
internal static string HttpSerializedDefaultAgentHeaders =>
23+
LazyInitializer.EnsureInitialized(ref _httpSerializedDefaultAgentHeaders, BuildSerializedAgentHeaders);
1924

2025
/// <summary>
2126
/// Gets the default constant headers that should be added to any request to the agent
2227
/// </summary>
2328
internal static KeyValuePair<string, string>[] GetDefaultAgentHeaders()
2429
{
25-
var headers = new List<KeyValuePair<string, string>>
26-
{
27-
new(TelemetryConstants.ClientLibraryLanguageHeader, TracerConstants.Language),
28-
new(TelemetryConstants.ClientLibraryVersionHeader, TracerConstants.AssemblyVersion),
29-
new(HttpHeaderNames.TracingEnabled, "false"), // don't add automatic instrumentation to requests directed to the agent
30-
new(TelemetryConstants.SessionIdHeader, RuntimeId.Get()),
31-
};
30+
var sessionId = RuntimeId.Get();
31+
var rootSessionId = RuntimeId.GetRootSessionId();
32+
var includeRoot = rootSessionId != sessionId;
33+
var headerCount = includeRoot ? 5 : 4;
3234

33-
AddRootSessionIdHeader(headers);
35+
var headers = new KeyValuePair<string, string>[headerCount];
36+
headers[0] = new(TelemetryConstants.ClientLibraryLanguageHeader, TracerConstants.Language);
37+
headers[1] = new(TelemetryConstants.ClientLibraryVersionHeader, TracerConstants.AssemblyVersion);
38+
headers[2] = new(HttpHeaderNames.TracingEnabled, "false"); // don't add automatic instrumentation to requests directed to the agent
39+
headers[3] = new(TelemetryConstants.SessionIdHeader, sessionId);
3440

35-
return headers.ToArray();
41+
if (includeRoot)
42+
{
43+
headers[4] = new(TelemetryConstants.RootSessionIdHeader, rootSessionId);
44+
}
45+
46+
return headers;
3647
}
3748

3849
/// <summary>
3950
/// Gets the default constant headers that should be added to any request to the direct telemetry intake
4051
/// </summary>
4152
internal static KeyValuePair<string, string>[] GetDefaultIntakeHeaders(TelemetrySettings.AgentlessSettings settings)
4253
{
43-
var headers = new List<KeyValuePair<string, string>>
44-
{
45-
new(TelemetryConstants.ClientLibraryLanguageHeader, TracerConstants.Language),
46-
new(TelemetryConstants.ClientLibraryVersionHeader, TracerConstants.AssemblyVersion),
47-
new(HttpHeaderNames.TracingEnabled, "false"),
48-
new(TelemetryConstants.ApiKeyHeader, settings.ApiKey),
49-
new(TelemetryConstants.SessionIdHeader, RuntimeId.Get()),
50-
};
54+
var sessionId = RuntimeId.Get();
55+
var rootSessionId = RuntimeId.GetRootSessionId();
56+
var includeRoot = rootSessionId != sessionId;
57+
var baseCount = settings.Cloud is null ? 5 : 8;
58+
var headerCount = includeRoot ? baseCount + 1 : baseCount;
59+
60+
var headers = new KeyValuePair<string, string>[headerCount];
61+
headers[0] = new(TelemetryConstants.ClientLibraryLanguageHeader, TracerConstants.Language);
62+
headers[1] = new(TelemetryConstants.ClientLibraryVersionHeader, TracerConstants.AssemblyVersion);
63+
headers[2] = new(HttpHeaderNames.TracingEnabled, "false");
64+
headers[3] = new(TelemetryConstants.ApiKeyHeader, settings.ApiKey);
65+
headers[4] = new(TelemetryConstants.SessionIdHeader, sessionId);
5166

67+
var index = 5;
5268
if (settings.Cloud is { } cloud)
5369
{
54-
headers.Add(new(TelemetryConstants.CloudProviderHeader, cloud.Provider));
55-
headers.Add(new(TelemetryConstants.CloudResourceTypeHeader, cloud.ResourceType));
56-
headers.Add(new(TelemetryConstants.CloudResourceIdentifierHeader, cloud.ResourceIdentifier));
70+
headers[index++] = new(TelemetryConstants.CloudProviderHeader, cloud.Provider);
71+
headers[index++] = new(TelemetryConstants.CloudResourceTypeHeader, cloud.ResourceType);
72+
headers[index++] = new(TelemetryConstants.CloudResourceIdentifierHeader, cloud.ResourceIdentifier);
5773
}
5874

59-
AddRootSessionIdHeader(headers);
60-
61-
return headers.ToArray();
62-
}
63-
64-
private static void AddRootSessionIdHeader(List<KeyValuePair<string, string>> headers)
65-
{
66-
var sessionId = RuntimeId.Get();
67-
var rootSessionId = RuntimeId.GetRootSessionId();
68-
if (rootSessionId != sessionId)
75+
if (includeRoot)
6976
{
70-
headers.Add(new(TelemetryConstants.RootSessionIdHeader, rootSessionId));
77+
headers[index] = new(TelemetryConstants.RootSessionIdHeader, rootSessionId);
7178
}
79+
80+
return headers;
7281
}
7382

7483
private static string BuildSerializedAgentHeaders()
7584
{
76-
var serialized =
77-
$"{TelemetryConstants.ClientLibraryLanguageHeader}: {TracerConstants.Language}" + DatadogHttpValues.CrLf +
78-
$"{TelemetryConstants.ClientLibraryVersionHeader}: {TracerConstants.AssemblyVersion}" + DatadogHttpValues.CrLf +
79-
$"{HttpHeaderNames.TracingEnabled}: false" + DatadogHttpValues.CrLf +
80-
$"{TelemetryConstants.SessionIdHeader}: {RuntimeId.Get()}" + DatadogHttpValues.CrLf;
81-
8285
var sessionId = RuntimeId.Get();
8386
var rootSessionId = RuntimeId.GetRootSessionId();
87+
88+
var sb = StringBuilderCache.Acquire();
89+
sb.Append(TelemetryConstants.ClientLibraryLanguageHeader).Append(": ").Append(TracerConstants.Language).Append(DatadogHttpValues.CrLf);
90+
sb.Append(TelemetryConstants.ClientLibraryVersionHeader).Append(": ").Append(TracerConstants.AssemblyVersion).Append(DatadogHttpValues.CrLf);
91+
sb.Append(HttpHeaderNames.TracingEnabled).Append(": false").Append(DatadogHttpValues.CrLf);
92+
sb.Append(TelemetryConstants.SessionIdHeader).Append(": ").Append(sessionId).Append(DatadogHttpValues.CrLf);
93+
8494
if (rootSessionId != sessionId)
8595
{
86-
serialized += $"{TelemetryConstants.RootSessionIdHeader}: {rootSessionId}" + DatadogHttpValues.CrLf;
96+
sb.Append(TelemetryConstants.RootSessionIdHeader).Append(": ").Append(rootSessionId).Append(DatadogHttpValues.CrLf);
8797
}
8898

89-
return serialized;
99+
return StringBuilderCache.GetStringAndRelease(sb);
90100
}
91101
}
92102
}

0 commit comments

Comments
 (0)