Skip to content

Commit 3697fd6

Browse files
vandonrandrewlock
andauthored
Add process tags to remote config (#7840)
## Summary of changes adding process tags next to the service name in remote config requests equivalent Java PR: DataDog/dd-trace-java#8705 related change on the agent side: DataDog/datadog-agent#36049 ## Reason for change AIDM-195 ## Implementation details ## Test coverage I didn't see any existing tests on the content of the requests, didn't really feel like adding some. ## Other details <!-- Fixes #{issue} --> <!-- ⚠️ Note: Where possible, please obtain 2 approvals prior to merging. Unless CODEOWNERS specifies otherwise, for external teams it is typically best to have one review from a team member, and one review from apm-dotnet. Trivial changes do not require 2 reviews. MergeQueue is NOT enabled in this repository. If you have write access to the repo, the PR has 1-2 approvals (see above), and all of the required checks have passed, you can use the Squash and Merge button to merge the PR. If you don't have write access, or you need help, reach out in the #apm-dotnet channel in Slack. --> --------- Co-authored-by: Andrew Lock <[email protected]>
1 parent 499289a commit 3697fd6

File tree

4 files changed

+45
-36
lines changed

4 files changed

+45
-36
lines changed

tracer/src/Datadog.Trace/ProcessTags.cs

Lines changed: 37 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -20,52 +20,56 @@ internal static class ProcessTags
2020
public const string EntrypointBasedir = "entrypoint.basedir";
2121
public const string EntrypointWorkdir = "entrypoint.workdir";
2222

23-
public static readonly string SerializedTags = GetSerializedTags();
23+
// two views on the same data
24+
public static readonly List<string> TagsList = GetTagsList();
25+
public static readonly string SerializedTags = GetSerializedTagsFromList(TagsList);
2426

25-
/// <summary>
26-
/// From the full path of a directory, get the name of the leaf directory.
27-
/// </summary>
28-
private static string GetLastPathSegment(string directoryPath)
27+
private static List<string> GetTagsList()
2928
{
30-
// Path.GetFileName returns an empty string if the path ends with a '/'.
31-
// We could use Path.TrimEndingDirectorySeparator instead of the trim here, but it's not available on .NET Framework
32-
return Path.GetFileName(directoryPath.TrimEnd('\\').TrimEnd('/'));
29+
// ⚠️ make sure entries are added in alphabetical order of keys
30+
var tags = new List<string>(3); // Update if you add more entries below
31+
tags.AddNormalizedTag(EntrypointBasedir, GetLastPathSegment(AppContext.BaseDirectory));
32+
tags.AddNormalizedTag(EntrypointName, GetEntryPointName());
33+
// workdir can be changed by the code, but we consider that capturing the value when this is called is good enough
34+
tags.AddNormalizedTag(EntrypointWorkdir, GetLastPathSegment(Environment.CurrentDirectory));
35+
36+
return tags;
3337
}
3438

35-
private static string GetSerializedTags()
39+
/// <summary>
40+
/// normalizes the tag value (keys are hardcoded so they don't need that)
41+
/// and adds it to the list iff not null or empty
42+
/// </summary>
43+
private static void AddNormalizedTag(this List<string> tags, string key, string? value)
3644
{
37-
// ⚠️ make sure entries are added in alphabetical order of keys
38-
List<KeyValuePair<string, string?>> tags =
39-
[
40-
new(EntrypointBasedir, GetLastPathSegment(AppContext.BaseDirectory)),
41-
new(EntrypointName, GetEntryPointName()),
42-
// workdir can be changed by the code, but we consider that capturing the value when this is called is good enough
43-
new(EntrypointWorkdir, GetLastPathSegment(Environment.CurrentDirectory))
44-
];
45-
46-
// then normalize values and put all tags in a string
47-
var serializedTags = StringBuilderCache.Acquire();
48-
foreach (var kvp in tags)
45+
if (string.IsNullOrEmpty(value))
4946
{
50-
if (!string.IsNullOrEmpty(kvp.Value))
51-
{
52-
serializedTags.Append($"{kvp.Key}:{NormalizeTagValue(kvp.Value!)},");
53-
}
47+
return;
5448
}
5549

56-
serializedTags.Remove(serializedTags.Length - 1, length: 1); // remove last comma
57-
return StringBuilderCache.GetStringAndRelease(serializedTags);
50+
// TraceUtil.NormalizeTag does almost exactly what we want, except it allows ':',
51+
// which we don't want because we use it as a key/value separator.
52+
var normalizedValue = TraceUtil.NormalizeTag(value).Replace(oldChar: ':', newChar: '_');
53+
tags.Add($"{key}:{normalizedValue}");
5854
}
5955

60-
private static string? GetEntryPointName()
56+
private static string GetSerializedTagsFromList(List<string> tags)
6157
{
62-
return EntryAssemblyLocator.GetEntryAssembly()?.EntryPoint?.DeclaringType?.FullName;
58+
return string.Join(",", tags);
6359
}
6460

65-
private static string NormalizeTagValue(string tagValue)
61+
/// <summary>
62+
/// From the full path of a directory, get the name of the leaf directory.
63+
/// </summary>
64+
private static string GetLastPathSegment(string directoryPath)
6665
{
67-
// TraceUtil.NormalizeTag does almost exactly what we want, except it allows ':',
68-
// which we don't want because we use it as a key/value separator.
69-
return TraceUtil.NormalizeTag(tagValue).Replace(oldChar: ':', newChar: '_');
66+
// Path.GetFileName returns an empty string if the path ends with a '/'.
67+
// We could use Path.TrimEndingDirectorySeparator instead of the trim here, but it's not available on .NET Framework
68+
return Path.GetFileName(directoryPath.TrimEnd('\\').TrimEnd('/'));
69+
}
70+
71+
private static string? GetEntryPointName()
72+
{
73+
return EntryAssemblyLocator.GetEntryAssembly()?.EntryPoint?.DeclaringType?.FullName;
7074
}
7175
}

tracer/src/Datadog.Trace/RemoteConfigurationManagement/Protocol/RcmClientTracer.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,13 @@ namespace Datadog.Trace.RemoteConfigurationManagement.Protocol
1212
{
1313
internal class RcmClientTracer
1414
{
15-
public RcmClientTracer(string runtimeId, string tracerVersion, string service, string env, string? appVersion, List<string> tags)
15+
public RcmClientTracer(string runtimeId, string tracerVersion, string service, string env, string? appVersion, List<string> tags, List<string>? processTags)
1616
{
1717
RuntimeId = runtimeId;
1818
Language = TracerConstants.Language;
1919
TracerVersion = tracerVersion;
2020
Service = service;
21+
ProcessTags = processTags;
2122
Env = env;
2223
AppVersion = appVersion;
2324
Tags = tags;
@@ -35,6 +36,9 @@ public RcmClientTracer(string runtimeId, string tracerVersion, string service, s
3536
[JsonProperty("service")]
3637
public string Service { get; }
3738

39+
[JsonProperty("process_tags")]
40+
public List<string>? ProcessTags { get; }
41+
3842
[JsonProperty("extra_services")]
3943
public string[]? ExtraServices { get; set; }
4044

tracer/src/Datadog.Trace/RemoteConfigurationManagement/RemoteConfigurationManager.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ public static RemoteConfigurationManager Create(
6969
return new RemoteConfigurationManager(
7070
discoveryService,
7171
remoteConfigurationApi,
72-
rcmTracer: new RcmClientTracer(settings.RuntimeId, settings.TracerVersion, serviceName, TraceUtil.NormalizeTag(tracerSettings.Environment), tracerSettings.ServiceVersion, tags),
72+
new RcmClientTracer(settings.RuntimeId, settings.TracerVersion, serviceName, TraceUtil.NormalizeTag(tracerSettings.Environment), tracerSettings.ServiceVersion, tags, tracerSettings.PropagateProcessTags ? ProcessTags.TagsList : null),
7373
pollInterval: settings.PollInterval,
7474
gitMetadataTagsProvider,
7575
subscriptionManager);

tracer/test/Datadog.Trace.Tests/RemoteConfigurationManagement/RemoteConfigurationApiTests.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,8 @@ private static GetRcmRequest GetRequest(string backendClientStage = null)
243243
service: nameof(RemoteConfigurationApiTests),
244244
env: "RCM Test",
245245
appVersion: "1.0.0",
246-
tags: []);
246+
tags: [],
247+
processTags: ["a.b:c", "x.y:z"]);
247248

248249
var state = new RcmClientState(
249250
rootVersion: 1,

0 commit comments

Comments
 (0)