Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
dc79c61
feat: add DD-Session-ID and DD-Root-Session-ID telemetry headers
khanayan123 Mar 25, 2026
d47e797
fix: sort using directives alphabetically (SA1210)
khanayan123 Mar 25, 2026
2804636
fix: correct using directive order (SA1210) - TestHelpers before Util
khanayan123 Mar 25, 2026
4351aa0
Merge branch 'master' into ayan.khan/stable-session-id-headers
khanayan123 Mar 26, 2026
642b76b
Initialize root session ID at tracer startup
khanayan123 Mar 26, 2026
d7ec963
Address PR review comments
khanayan123 Mar 27, 2026
6385c47
Optimize TelemetryHttpHeaderNames per review feedback
khanayan123 Mar 30, 2026
3406b39
Add test for inherited root session ID
khanayan123 Mar 31, 2026
9eff4f3
Merge branch 'master' into ayan.khan/stable-session-id-headers
khanayan123 Mar 31, 2026
8f98088
Update tracer/src/Datadog.Trace/Telemetry/TelemetryHttpHeaderNames.cs
khanayan123 Mar 31, 2026
7782691
Update tracer/src/Datadog.Trace/Util/RuntimeId.cs
khanayan123 Mar 31, 2026
38678c1
Update tracer/test/Datadog.Trace.Tests/Util/RuntimeIdTests.cs
khanayan123 Mar 31, 2026
56e6aea
Revert stray blank line in TracerManager.cs
khanayan123 Mar 31, 2026
98cca06
Use EnvironmentConfigurationSource to read root session ID
khanayan123 Mar 31, 2026
604f9ba
fix: use TestingAndPrivateOnly attribute instead of InternalForTesting
khanayan123 Mar 31, 2026
64d70b5
Merge branch 'master' into ayan.khan/stable-session-id-headers
khanayan123 Mar 31, 2026
4f3274a
fix: add missing using for TestingAndPrivateOnlyAttribute
khanayan123 Mar 31, 2026
fbb50f6
fix: add missing using for EnvironmentRestorerAttribute
khanayan123 Mar 31, 2026
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
Original file line number Diff line number Diff line change
Expand Up @@ -1580,6 +1580,15 @@ supportedConfigurations:
documentation: |-
Configuration key for whether telemetry metrics should be sent.
<see cref="Datadog.Trace.Telemetry.TelemetrySettings.MetricsEnabled"/>
_DD_ROOT_DOTNET_SESSION_ID:
Copy link
Copy Markdown
Member

@lucaspimentel lucaspimentel Mar 26, 2026

Choose a reason for hiding this comment

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

Why the leading underscore? _DD... instead of DD..? Is that something we're doing now for internal env vars? The RFC says DD_ROOT_<LIB>_SESSION_ID.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Agreed, this seems non standard

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Prefixing environment variables with _DD is convention we use in dd-trace-py to mark a configuration as internal/private. All implementations currently follow this spec, the implementation plan was out of date but I just pushed a fix.

Ideally we'd use _DD to be consistent across SDKs but this isn't a big deal for us. We would like to do what's best for the .NET library and ideally this PR would introduce minimal changes to library internals. From a backend perspective as long as the expected headers sent by the telemetry client we should be good.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

If that's the standard and it follows the spec and the other implementations, then yeah, go for it. I only asked because I had not seen it before and I didn't see in the RFC. Thanks!

(I wonder though it we have places where we look for DD_* env vars that would need to be updated. Probably not production code, but maybe tests or scripts that list all DD env vars for troubleshooting.)

Copy link
Copy Markdown
Contributor Author

@khanayan123 khanayan123 Mar 27, 2026

Choose a reason for hiding this comment

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

The _DD prefix was established by the Python implementation (dd-trace-py#16839).

The implementation proposal/parent RFC only mandates the HTTP header names (DD-Session-ID, DD-Root-Session-ID) the env var naming (DD_ROOT_LIB_SESSION_ID) is mentioned only in the "Process Spawning: Fork & Exec Support" appendix as an implementation detail.

The underscore prefix signals this is internal: we don't want to expose it as a public API, and keeping it private gives us flexibility to replace the propagation mechanism in a minor version without a breaking change.

That said, this is purely an internal convention if the DD_ prefix is preferred for the DOTNET implementation, I can update it. It's not customer-facing either way.

Copy link
Copy Markdown
Contributor Author

@khanayan123 khanayan123 Mar 31, 2026

Choose a reason for hiding this comment

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

As per discussion on slack and after updating the implementation proposal we will keep _DD_ROOT_LIB_SESSION_ID as the naming convention across SDKs for this env var

- implementation: A
type: string
default: null
product: Telemetry
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think this needs to be marked as a "platform key" so that it can be read directly from the environment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Unfortunately, anything starting with _DD_ has to be controlled by ConfigRegistry, hence the constraint in the analyzer

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Any resolution on this @anna-git @andrewlock? Since this is purely an internal implementation detail (the RFC only mandates the HTTP header names, not the env var), I'm happy to rename it to whatever works best with DOTNET standards whether that's dropping the _DD prefix to allow it to be a platform key, or keeping the current approach

Copy link
Copy Markdown
Contributor Author

@khanayan123 khanayan123 Mar 30, 2026

Choose a reason for hiding this comment

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

Resolved per discussion with @anna-git , this should stay as a config key in ConfigRegistry (not a platform key). Platform keys are for non-Datadog config keys. Since this is ours (_DD_ prefix), ConfigRegistry is the right place, which is how it's currently implemented.

const_name: RootSessionId
documentation: |-
Internal env var for propagating the root session ID to child processes.
Set automatically by the tracer at init time; not user-configurable.
DD_TEST_MANAGEMENT_ATTEMPT_TO_FIX_RETRIES:
- implementation: A
type: int
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@ internal static partial class ConfigurationKeys
{
internal static class Telemetry
{
/// <summary>
/// Internal env var for propagating the root session ID to child processes.
/// Set automatically by the tracer at init time; not user-configurable.
/// </summary>
public const string RootSessionId = "_DD_ROOT_DOTNET_SESSION_ID";

/// <summary>
/// SSI variable that provides a unique identifier for the instrumentation installation.
/// Used for tracking and correlation purposes in telemetry.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@ internal static partial class ConfigurationKeys
{
internal static class Telemetry
{
/// <summary>
/// Internal env var for propagating the root session ID to child processes.
/// Set automatically by the tracer at init time; not user-configurable.
/// </summary>
public const string RootSessionId = "_DD_ROOT_DOTNET_SESSION_ID";

/// <summary>
/// SSI variable that provides a unique identifier for the instrumentation installation.
/// Used for tracking and correlation purposes in telemetry.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@ internal static partial class ConfigurationKeys
{
internal static class Telemetry
{
/// <summary>
/// Internal env var for propagating the root session ID to child processes.
/// Set automatically by the tracer at init time; not user-configurable.
/// </summary>
public const string RootSessionId = "_DD_ROOT_DOTNET_SESSION_ID";

/// <summary>
/// SSI variable that provides a unique identifier for the instrumentation installation.
/// Used for tracking and correlation purposes in telemetry.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@ internal static partial class ConfigurationKeys
{
internal static class Telemetry
{
/// <summary>
/// Internal env var for propagating the root session ID to child processes.
/// Set automatically by the tracer at init time; not user-configurable.
/// </summary>
public const string RootSessionId = "_DD_ROOT_DOTNET_SESSION_ID";

/// <summary>
/// SSI variable that provides a unique identifier for the instrumentation installation.
/// Used for tracking and correlation purposes in telemetry.
Expand Down
3 changes: 3 additions & 0 deletions tracer/src/Datadog.Trace/Telemetry/TelemetryConstants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ internal static class TelemetryConstants
public const string ClientLibraryLanguageHeader = "DD-Client-Library-Language";
public const string ClientLibraryVersionHeader = "DD-Client-Library-Version";

public const string SessionIdHeader = "DD-Session-ID";
public const string RootSessionIdHeader = "DD-Root-Session-ID";

public const string CloudProviderHeader = "DD-Cloud-Provider";
public const string CloudResourceTypeHeader = "DD-Cloud-Resource-Type";
public const string CloudResourceIdentifierHeader = "DD-Cloud-Resource-Identifier";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
using Datadog.Trace.Logging;
using Datadog.Trace.PlatformHelpers;
using Datadog.Trace.Telemetry.Metrics;
using Datadog.Trace.Util;
using Datadog.Trace.Util.Http;
using Datadog.Trace.Vendors.Newtonsoft.Json;
using Datadog.Trace.Vendors.Newtonsoft.Json.Serialization;
Expand Down Expand Up @@ -56,6 +57,14 @@ public async Task<TelemetryPushResult> PushTelemetry(TelemetryData data)
request.AddHeader(TelemetryConstants.DebugHeader, "true");
}

var sessionId = RuntimeId.Get();
request.AddHeader(TelemetryConstants.SessionIdHeader, sessionId);
var rootSessionId = RuntimeId.GetRootSessionId();
if (rootSessionId != sessionId)
{
request.AddHeader(TelemetryConstants.RootSessionIdHeader, rootSessionId);
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Given that these headers are constants for the lifetime of the process, it would be preferable to add them to the TelemetryAgentHttpHeaderHelper and TelemetryAgentHttpHeaderHelper types. The other headers are added here because they depend on the payload. (Arguably container Metadata should be added elsewhere too, but that's a pre-existing issue 😅 )

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Moved session headers to TelemetryHttpHeaderNames


request.AddContainerMetadataHeaders(_containerMetadata);

TelemetryFactory.Metrics.RecordCountTelemetryApiRequests(endpointMetricTag);
Expand Down
5 changes: 5 additions & 0 deletions tracer/src/Datadog.Trace/TracerManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,11 @@ public TracerManager(
ServiceRemappingHash = serviceRemappingHash;

SpanContextPropagator = SpanContextPropagatorFactory.GetSpanContextPropagator(settings.PropagationStyleInject, settings.PropagationStyleExtract, settings.PropagationExtractFirstOnly, settings.PropagationBehaviorExtract);

// Eagerly initialize the root session ID so child processes inherit it
// even if spawned before the first telemetry flush.
_ = RuntimeId.GetRootSessionId();

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Rather than putting this here, I wonder if you actually need to call this in Instrumentation.Initialize, and make sure this flows through to the native profiler too. The reason being that they might send telemetry independently (I believe libdatadog does for example), and in that case you need to make sure they also apply the RootSessionId 🤔.

If you do modify that interface and pass it through to the profiler side, then you can remove that here too.

Copy link
Copy Markdown
Contributor Author

@khanayan123 khanayan123 Mar 27, 2026

Choose a reason for hiding this comment

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

@andrewlock Yes I believe that libdatadog does send telemetry independently, and those requests currently won't include the session headers.

@mabdinur is working on adding session ID support to libdatadog's FFI and once that lands we'll have a follow-up PR to pass it through from the managed side

I've also moved the GetRootSessionId() call earlier to Instrumentation.InitializeNoNativeParts()

UpdatePerTraceSettings(settings.Manager.InitialMutableSettings);
_settingSubscription = settings.Manager.SubscribeToChanges(changes =>
{
Expand Down
22 changes: 20 additions & 2 deletions tracer/src/Datadog.Trace/Util/RuntimeId.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

using System;
using System.Threading;
using Datadog.Trace.Configuration;
using Datadog.Trace.Logging;

namespace Datadog.Trace.Util
Expand All @@ -13,10 +14,13 @@ internal static class RuntimeId
{
private static readonly IDatadogLogger Log = DatadogLogging.GetLoggerFor(typeof(RuntimeId));
private static string _runtimeId;
private static string _rootSessionId;

public static string Get() => LazyInitializer.EnsureInitialized(ref _runtimeId, () => GetImpl());
public static string Get() => LazyInitializer.EnsureInitialized(ref _runtimeId, () => GetRuntimeIdImpl());
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The naming of public Get() and private GetImpl() was intentional (one method is the private implementation of the other).

To keep that naming convention, we can either rename the private GetRuntimeIdImpl() back to GetImpl(), or rename the public method to GetRuntimeId()`, which I think is better overall to distinguish the two:

GetRuntimeId()     -> GetRuntimeIdImpl()
GetRootSessionId() -> GetRootSessionIdImpl()

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

RuntimeId.GetRuntimeId() 😅 arguably we need a different name for RuntimeId now but whatever 😅

Copy link
Copy Markdown
Member

@lucaspimentel lucaspimentel Mar 27, 2026

Choose a reason for hiding this comment

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

RuntimeId.GetRuntimeId()

Whoa. I was looking only at the method names and didn't notice this. We could also go with:

Get()              -> GetImpl()
GetRootSessionId() -> GetRootSessionIdImpl()

No strong feelings either way, as long as we keep the internal consistency: Method()->MethodImpl().

Copy link
Copy Markdown
Contributor Author

@khanayan123 khanayan123 Mar 31, 2026

Choose a reason for hiding this comment

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

Went with approach 2 to minimize lines changes:

Get() -> GetImpl()
GetRootSessionId() -> GetRootSessionIdImpl()


private static string GetImpl()
public static string GetRootSessionId() => LazyInitializer.EnsureInitialized(ref _rootSessionId, () => GetRootSessionIdImpl());

private static string GetRuntimeIdImpl()
{
if (NativeLoader.TryGetRuntimeIdFromNative(out var runtimeId))
{
Expand All @@ -29,5 +33,19 @@ private static string GetImpl()

return guid;
}

private static string GetRootSessionIdImpl()
{
var inherited = EnvironmentHelpers.GetEnvironmentVariable(ConfigurationKeys.Telemetry.RootSessionId);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Grabbing this value directly from the environment means it won't be reported in telemetry configuration. Is that correct? If you need it reported you should use the EnvironmentConfigurationSource instead.

@anna-git why is this allowed actually? 🤔 Shouldn't we be forcing all configuration key values to go via the correct reporting mechanisms? I thought we were only allowed to use "platform keys" here?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Although not necessary to report it via telemetry since this is intended to be for internal usage, i've updated it to read from EnvironmentConfigurationSource since that's the existing mechanism for all config registry env vars

Copy link
Copy Markdown
Contributor Author

@khanayan123 khanayan123 Mar 31, 2026

Choose a reason for hiding this comment

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

Also in general we're currently still attempting to report all configs to telemetry, but in the future we might update the model to only report configs configured by the customer to telemetry and instead rely on config registry for default or internal configs

if (!string.IsNullOrEmpty(inherited))
{
Log.Debug("Inherited root session ID from parent: {RootSessionId}", inherited);
return inherited;
}

var rootId = Get();
EnvironmentHelpers.SetEnvironmentVariable(ConfigurationKeys.Telemetry.RootSessionId, rootId);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

For clarity, this simply won't work in many cases, such that this whole approach is potentially flawed...

  • On Unix, environment changes are not seen by native processes. There's no way to remediate this.
  • Users may well call Process.Start() with a custom env var block, in which case this won't be inherited.
  • If UseShellExecute=true is set when starting a new process, this won't work.

The "good" news is that starting new dotnet processes is not a standard pattern in general, so hopefully it just doesn't really matter...

Copy link
Copy Markdown
Contributor

@anna-git anna-git Mar 27, 2026

Choose a reason for hiding this comment

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

as we already instrument ProcessStart , maybe the RootSessionId could be passed down via the instrumentation setting some additional args or something 🤔

Copy link
Copy Markdown
Member

@lucaspimentel lucaspimentel Mar 27, 2026

Choose a reason for hiding this comment

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

starting new dotnet processes is not a standard pattern

Yet we have a whole instrumentation for it. 😉

tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Process

(edit: I had not refreshed to see Anna's comment before I posted mine 😅 )

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@lucaspimentel @anna-git @andrewlock Good point about the Process instrumentation.

Would you prefer we inject _DD_ROOT_DOTNET_SESSION_ID directly into the child process's ProcessStartInfo.Environment via the existing ClrProfiler/AutoInstrumentation/Process hooks, rather than relying on Environment.SetEnvironmentVariable()? And would that address the Unix limitations Andrew mentioned and handle cases where the user provides a custom env block or sets UseShellExecute=true?

Copy link
Copy Markdown
Contributor Author

@khanayan123 khanayan123 Mar 27, 2026

Choose a reason for hiding this comment

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

I think since dotnet already instruments process start it might make sense to utilize that instead of env vars, we implemented it in a similar way for Node

Copy link
Copy Markdown
Contributor Author

@khanayan123 khanayan123 Mar 30, 2026

Choose a reason for hiding this comment

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

Resolved per @andrewlock's recommendation, we'll keep SetEnvironmentVariable() and accept it won't give 100% coverage. Process instrumentation is too risky for this. Spawning child .NET processes is rare enough that this is acceptable.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

as we already instrument ProcessStart , maybe the RootSessionId could be passed down via the instrumentation setting some additional args or something 🤔

FWIW, I consider this to be very risky for breaking customers. I just don't see the value here as being worth the trade-off tbh

return rootId;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
using Datadog.Trace.Telemetry;
using Datadog.Trace.Telemetry.Transports;
using Datadog.Trace.TestHelpers;
using Datadog.Trace.Util;
using FluentAssertions;
using FluentAssertions.Execution;
using Xunit;
Expand Down Expand Up @@ -116,6 +117,12 @@ public async Task SetsRequiredHeaders(bool agentless, bool useCloudAgentless)
{ "DD-Client-Library-Version", TracerConstants.AssemblyVersion },
};

// DD-Session-ID is always present and equals the runtime ID
allExpected.Add(TelemetryConstants.SessionIdHeader, RuntimeId.Get());

// DD-Root-Session-ID is absent when rootSessionId == runtimeId (normal process)
// We can't assert absence in the loop below, so we check it separately after

if (ContainerMetadata.Instance.ContainerId is { } containerId)
{
allExpected.Add(AgentHttpHeaderNames.ContainerId, containerId);
Expand Down Expand Up @@ -149,6 +156,12 @@ public async Task SetsRequiredHeaders(bool agentless, bool useCloudAgentless)
}
}

// DD-Root-Session-ID should be absent in a normal (non-child) process
if (RuntimeId.GetRootSessionId() == RuntimeId.Get())
{
headers.AllKeys.Should().NotContain(TelemetryConstants.RootSessionIdHeader);
}

// should have either content-length or chunked encoding
headers.AllKeys.Should()
.Contain(s => s.Equals("Content-Type", StringComparison.OrdinalIgnoreCase)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ public class ConfigurationTests
"DD_CIVISIBILITY_CODE_COVERAGE_MODE",
"DD_CIVISIBILITY_AUTO_INSTRUMENTATION_PROVIDER",
// Internal env vars that we only ever read from environment
"_DD_ROOT_DOTNET_SESSION_ID",
"DD_INTERNAL_TRACE_NATIVE_ENGINE_PATH",
"DD_INTERNAL_PROFILING_NATIVE_ENGINE_PATH",
"DD_DOTNET_TRACER_HOME",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
using Datadog.Trace.Telemetry.Transports;
using Datadog.Trace.TestHelpers.FluentAssertionsExtensions.Json;
using Datadog.Trace.TestHelpers.TransportHelpers;
using Datadog.Trace.Util;
using Datadog.Trace.Vendors.Newtonsoft.Json;
using Datadog.Trace.Vendors.Newtonsoft.Json.Linq;
using FluentAssertions;
Expand Down Expand Up @@ -74,7 +75,8 @@ public async Task ShouldContainRequiredHeaders(bool debugEnabled, [Combinatorial
{ "DD-Telemetry-API-Version", TelemetryConstants.ApiVersionV2 },
{ "DD-Telemetry-Request-Type", "my-request-type" },
{ "Datadog-Container-ID", "my-container-id" },
{ "Datadog-Entity-ID", "my-entity-id" }
{ "Datadog-Entity-ID", "my-entity-id" },
{ TelemetryConstants.SessionIdHeader, RuntimeId.Get() },
};
if (debugEnabled)
{
Expand Down
15 changes: 15 additions & 0 deletions tracer/test/Datadog.Trace.Tests/TracerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -561,6 +561,21 @@ public void RuntimeId()
Guid.TryParse(runtimeId, out _).Should().BeTrue();
}

[Fact]
public void RootSessionId_DefaultsToRuntimeId()
{
var rootSessionId = Datadog.Trace.Util.RuntimeId.GetRootSessionId();
rootSessionId.Should().Be(Datadog.Trace.Util.RuntimeId.Get());
}

[Fact]
public void RootSessionId_SetsEnvVar()
{
var rootSessionId = Datadog.Trace.Util.RuntimeId.GetRootSessionId();
Environment.GetEnvironmentVariable(ConfigurationKeys.Telemetry.RootSessionId)
.Should().Be(rootSessionId);
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Do we need a test that sets env var _DD_ROOT_DOTNET_SESSION_ID and asserts that RuntimeId.GetRootSessionId()returns the inherited value (not the current runtime_id)?

I'm not sure how we would handle resetting the private static fields in RuntimeId, though. Might need some refactoring to make it more testable.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Added RuntimeId.ResetForTests() (follows SmallCacheOrNoCache.ResetForTests() pattern) and a single test that covers both paths: first asserts GetRootSessionId() defaults to runtime_id when no env var is set, then resets, pre-sets the env var, and asserts the inherited value is returned instead of the current runtime_id


Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This file contains tests for the Tracer class. Since these two tests are for the RuntimeId class, can you move this into a tracer/test/Datadog.Trace.Tests/Util/RuntimeIdTests.cs file? In Datadog.Trace.Tests we generally try to match the file/namespace layout of Datadog.Trace.

tracer/src/Datadog.Trace/Util/RuntimeId.cs

tracer/test/Datadog.Trace.Tests/Util/RuntimeIdTests.cs

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Moved to tracer/test/Datadog.Trace.Tests/Util/RuntimeIdTests.cs

[Fact]
public async Task ForceFlush()
{
Expand Down
Loading