Skip to content

Compat: Add Multi-Azure Function Unique Named Pipe Configuration#20

Merged
Lewis-E merged 11 commits into
mainfrom
lewis/SVLS-8244/add-multifunction-named-pipes
May 7, 2026
Merged

Compat: Add Multi-Azure Function Unique Named Pipe Configuration#20
Lewis-E merged 11 commits into
mainfrom
lewis/SVLS-8244/add-multifunction-named-pipes

Conversation

@Lewis-E

@Lewis-E Lewis-E commented Feb 3, 2026

Copy link
Copy Markdown
Contributor

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

Comment thread Datadog.Serverless.Compat.Tests/CompatibilityLayerTests.cs Outdated
Comment thread Datadog.Serverless/CompatibilityLayer.cs Outdated
Lewis-E added 6 commits March 2, 2026 15:34
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
@Lewis-E Lewis-E force-pushed the lewis/SVLS-8244/add-multifunction-named-pipes branch from 9065448 to d9c813f Compare March 4, 2026 15:13
@Lewis-E Lewis-E force-pushed the lewis/SVLS-8244/add-multifunction-named-pipes branch from 719ce66 to f1afb0d Compare March 4, 2026 21:11
@Lewis-E Lewis-E marked this pull request as ready for review March 5, 2026 16:54
@Lewis-E Lewis-E requested review from a team as code owners March 5, 2026 16:54
@Lewis-E Lewis-E requested a review from kathiehuang March 5, 2026 16:54
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>
@Lewis-E Lewis-E requested a review from lucaspimentel March 6, 2026 19:00
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>
@Lewis-E Lewis-E changed the title Add Multi-Azure Function Unique Named Pipe Configuration Compat: Add Multi-Azure Function Unique Named Pipe Configuration Apr 30, 2026
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>
@lucaspimentel

Copy link
Copy Markdown
Member

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 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".

Comment thread Datadog.Serverless/CompatibilityLayer.cs
Comment thread Datadog.Serverless/CompatibilityLayer.cs Outdated
Comment thread Datadog.Serverless/CompatibilityLayer.cs Outdated
Comment thread Datadog.Serverless/CompatibilityLayer.cs Outdated
…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>

@kathiehuang kathiehuang left a comment

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.

LGTM!

@Lewis-E Lewis-E merged commit d8ffc58 into main May 7, 2026
5 checks passed
@Lewis-E Lewis-E deleted the lewis/SVLS-8244/add-multifunction-named-pipes branch May 7, 2026 20:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants