Compat: Add Multi-Azure Function Unique Named Pipe Configuration#20
Merged
Conversation
Changes: - Add CalculateTracePipeName() and CalculateDogStatsDPipeName() public methods - These methods generate unique pipe names with GUID suffixes - Methods are designed to be instrumented by the Datadog tracer - When tracer is present, instrumentation will override return values - When no tracer, methods work normally generating their own pipe names - Update ConfigureNamedPipes() to call these new methods - Add comprehensive tests for the new pipe name calculation methods This approach allows the tracer to control pipe naming while keeping the compat layer functional in standalone scenarios. Related: SVLS-8244
9065448 to
d9c813f
Compare
719ce66 to
f1afb0d
Compare
When DD_TRACE_PIPE_NAME or DD_TRACE_WINDOWS_PIPE_NAME (and their DogStatsD equivalents) are explicitly set, return the configured name directly. Only append a GUID suffix in auto-discovery mode (no env vars set). This prevents a mismatch where the tracer sends to the explicit pipe name but the compat binary listens on a GUID-suffixed variant. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
ConfigureNamedPipes now sets DD_TRACE_PIPE_NAME and DD_DOGSTATSD_PIPE_NAME in the current process environment, so that in-process consumers like the DogStatsD client can discover the pipe to connect to. This runs during the DOTNET_STARTUP_HOOKS phase, before user code calls DogStatsdService.Configure(), so the env vars are guaranteed to be visible. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Merged
5 tasks
Lewis-E
added a commit
to DataDog/dd-trace-dotnet
that referenced
this pull request
May 6, 2026
## Summary of changes * Allow use of unique windows named pipes for IPC, coordinated with the serverless compatibility layer's mini-agent. * See: DataDog/datadog-serverless-compat-dotnet#20 for compat-side changes. * See: DataDog/serverless-compat-self-monitoring#54 for integration testing in Azure. ## Reason for change * Improve support for running multiple Azure Functions in the same hosting plan. [[jira](https://datadoghq.atlassian.net/browse/SVLS-8244)] ## Implementation details For [Azure Functions](https://docs.datadoghq.com/serverless/azure_functions/?tab=dotnet#setup), the tracer loads first, then the compat layer, and then the compat layer launches a rust binary to act as the agent. Additionally, the client may or may not be using the DogstatsD client, and it is also possible to have the compat layer and DogstatsD in place without the tracer. We need to coordinate named pipes across all three/four of these codebases, noting that the tracer will use DogstatsD's pipe for runtime metrics if available. Given this order of operations, and that we want this to work with immutable configuration, the tracer should set pipe names for the compatibility layer via instrumentation if the tracer is present. 1. Tracer loads -- pipe name is generated 2. We check the presence of the compat layer + windows configs (using undocumented envvar `DD_SERVERLESS_COMPAT_BINARY_PATH` if necessary to adapt to Azure changes) to see if named pipes can be used or if we should rely on TCP 4. Compat layer loads 5. Tracer uses instrumentation to force the compat layer to generate the pipe names <pipe-a>, <pipe-b> 6. Compat layer passes the name to the mini-agent tracer <pipe-a> and dogstatsd <pipe-b>. | Scenario | Pipe generated? | Transport | Result | |---|---|---|---| | New tracer + no compat at all | No (binary not found) | TCP | Works | | New tracer + old compat (< 1.5) | No (version check fails) | TCP | Works | | New tracer + new compat (≥ 1.5) | Yes | Named pipe | Works (integration coordinates) | | New tracer + dev compat (0.0.0) | Yes | Named pipe | Works (integration coordinates) | | Old tracer + no compat | No | TCP | Works | | Old tracer + old compat (< 1.5) | No | TCP | Works (neither side knows about pipes) | | Old tracer + new compat (≥ 1.5) | No | TCP | **Broken** — tracer sends via TCP, but compat binary listens on pipe only. Requires [more serverless-components changes](DataDog/serverless-components#94). | | Old tracer + dev compat (0.0.0) | No | TCP | Not supported | ## Test coverage * Self Monitoring * New Unit Tests --------- Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com> Co-authored-by: Andrew Lock <andrewlock.net@gmail.com>
- Add frozen API contract comment to CalculateTracePipeName and
CalculateDogStatsDPipeName: assembly, type, method, version range,
and consequence of renaming (silent no-op in native profiler)
- Add reflection-based contract tests that catch renames at compile
time (nameof) and signature/accessibility changes at runtime
- Remove dead Environment.SetEnvironmentVariable("DD_TRACE_PIPE_NAME")
— nothing reads it; trace pipe flows tracer → DD_APM_WINDOWS_PIPE_NAME
→ mini-agent; only DD_DOGSTATSD_PIPE_NAME has an in-process consumer
- Drop unreachable null-check on Calculate* return values (both return string)
- Update existing ConfigureNamedPipes tests to assert DD_TRACE_PIPE_NAME
is NOT set, with explanatory comments
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Member
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 5e0d1719c0
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…tName param CalculatePipeName was only ever called after DeterminePipeBaseName already confirmed no env var is set, so its internal DeterminePipeBaseName call always returned the hardcoded default. Inline the GUID generation directly into CalculateTracePipeName and CalculateDogStatsDPipeName and delete the now-dead helper. With no remaining callers passing a non-null default, drop the defaultName parameter from DeterminePipeBaseName entirely. Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
lucaspimentel
approved these changes
May 6, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What does this PR do?
Motivation
Improve support for running multiple Azure Functions in the same hosting plan. [jira]
Describe how to test/QA your changes