Skip to content

[DRAFT] Add SDK v2 telemetry and hardening#878

Closed
bmehta001 wants to merge 79 commits into
mainfrom
bhamehta/flcore/1ds-telemetry
Closed

[DRAFT] Add SDK v2 telemetry and hardening#878
bmehta001 wants to merge 79 commits into
mainfrom
bhamehta/flcore/1ds-telemetry

Conversation

@bmehta001

Copy link
Copy Markdown
Contributor

Summary

  • Adds SDK v2 telemetry plumbing and 1DS event emission across manager, catalog, downloads, EP registration, model/session usage, and web-service routes.
  • Hardens related packaging/runtime paths discovered during review: WinML/DirectML staging, ORT/GenAI runtime copies, download resume safety, streaming shutdown, and JS/Python native lifetime/loading.
  • Merged latest origin/main and preserved platform file I/O split with explicit close-error handling.

Validation

  • python sdk_v2/cpp/build.py --build --config RelWithDebInfo
  • Focused C++ tests: FileWriter, DownloadManager retry/legacy repair, AzureBlobDownloaderResume, SessionManager/WebService/SSE, EP/catalog focused tests.
  • npm run build in sdk_v2/js
  • JS manager/catalog disposal focused tests.

Notes

  • Draft because the branch is large; planning split follow-up PRs to separate telemetry from hardening/packaging fixes.

bmehta001 and others added 30 commits June 10, 2026 23:28
Port the C# Foundry Core telemetry event taxonomy to C++ in advance of the
1DS bridge.  The interface refactor is the source of truth — all backend
implementations and call sites are wired against it.

ITelemetry additions:
  - 4 new `Action` values (EpDownloadAttempt, EpDownloadAndRegister,
    ModelFileDownload, ModelInference).
  - 4 new payload structs (`EpDownloadAttemptInfo`,
    `EpDownloadAndRegisterInfo`, `ModelUsageInfo`, `DownloadInfo`).
  - 3 new virtual methods (`RecordEpDownloadAttempt`,
    `RecordEpDownloadAndRegister`, `RecordDownload`).
  - Replaced `RecordModelUsage(model_id, prompt_tokens, completion_tokens,
    duration_ms)` with `RecordModelUsage(const ModelUsageInfo&)` so callers
    can populate richer fields (TimeToFirstToken, EP, memory).
  - Extended `RecordModelId(action, model_id)` to take `status` and
    `user_agent`; added `RecordException(action, ex, user_agent)` overload.

New supporting code (all in `sdk_v2/cpp/src/telemetry/`):
  - `telemetry_environment.{h,cc}` — `IsCiEnvironment` /
    `IsTestingMode` / `IsTruthyValue` / `GetEnv`.  13 CI env-var
    names ported verbatim from neutron-server's `TelemetryEnvironment.cs`.
  - `telemetry_metadata.{h,cc}` — captures per-process metadata
    (`app_session_guid`, version, os_name / os_version / cpu_arch,
    test_mode flag) for stamping on every event.
  - `ep_download_tracker.{h,cc}` — RAII tracker that emits one
    `EPDownloadAndRegister` event per bootstrapper, recording stage
    transitions (initial -> download -> register).  Default failure
    semantics: dtor records remaining stages as `kFailure`; `Done()`
    records them as `kSkipped` for happy-path early exit.
  - `download_tracker.{h,cc}` — RAII tracker that emits one `Download`
    event per `DownloadManager::DownloadModel` call.

`TelemetryLogger` (the fallback / mirror) implements every new method,
formatting events as `[Telemetry] EventName Field=value ...` at Debug.
Test stubs (`NullTelemetry` and the `RecordingTelemetry` used by
`telemetry_test.cc`) were updated for the new interface.

Build verified RelWithDebInfo --no_telemetry.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
OneDsTelemetry is the production ITelemetry implementation.  It embeds a
TelemetryLogger mirror so every event is also logged locally to ILogger for
diagnostics, then conditionally uploads to 1DS through the Microsoft
cpp-client-telemetry SDK.

Suppression model (three-state):
  - CI environment detected -> skip `LogManager::Initialize`; local logging
    still happens, but no upload occurs.
  - Tenant token empty (build did not pass `-DFOUNDRY_LOCAL_TELEMETRY_TOKEN`)
    -> same as CI: no upload, only local logging.
  - Otherwise -> upload.  Every event is stamped with `test=true` when
    `FOUNDRY_TESTING_MODE` is truthy, `test=false` otherwise.

Common context, propagated to every event via `ILogger::SetContext`:
  - `app_name` (from `Configuration::app_name`).
  - `app_session_guid` (random v4 UUID; on Windows the special
    `UTCReplace_AppSessionGuid` field also gets the OS app session GUID).
  - `version` (from the generated `version.h`).
  - `os_name` / `os_version` / `cpu_arch` (Win: `GetVersionExA` +
    `GetNativeSystemInfo`; POSIX: `uname`).

The `MICROSOFT_KEYWORD_CRITICAL_DATA` (bit 47) policy flag is set on
every event via `SetPolicyBitFlags` so the data passes 1DS classifier.

Build / packaging:
  - `vcpkg.json`: `telemetry` feature pulls `cpp-client-telemetry`.
    The port is pending in microsoft/vcpkg#52316; until that merges,
    builds must pass `--no_telemetry`.
  - `CMakeLists.txt`: new `FOUNDRY_LOCAL_USE_TELEMETRY` option
    (default ON) and `FOUNDRY_LOCAL_TELEMETRY_TOKEN` advanced cache
    variable.  Calls `find_package(MSTelemetry CONFIG REQUIRED)`, includes
    `one_ds_telemetry.cc` and `configure_file`-generates
    `one_ds_tenant_token.h` containing the build-time token, then links
    `MSTelemetry::mat` and defines `FOUNDRY_LOCAL_HAS_1DS=1`.
  - `build.py`: new `--no_telemetry` and `--telemetry_token` flags;
    forwards through to CMake / VCPKG_MANIFEST_FEATURES.

Build verified RelWithDebInfo --no_telemetry; --use_telemetry will be
validated once the vcpkg port lands.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Plumb the typed telemetry interface through the orchestration layer so
that real workloads produce the new EPDownloadAttempt, EPDownloadAndRegister
and Download events.

Manager:
  - Construct `telemetry_` before `ep_detector_` so the detector can be
    handed a non-null sink at ctor time.  When `FOUNDRY_LOCAL_HAS_1DS` is
    defined, the implementation is `OneDsTelemetry` and reads the
    build-time token from the generated `one_ds_tenant_token.h`; otherwise
    it falls back to `TelemetryLogger`.
  - Member-declaration order in `manager.h` reorganised so consumers
    (`ep_detector_`, `download_manager_`) appear after the providers
    (`telemetry_`).  C++ destroys in reverse declaration order, so this
    keeps the raw `ITelemetry*` held by `EpDetector` and
    `DownloadManager` valid for their entire lifetime.
  - Explicit `~Manager()` Shutdown reset order updated to match: the
    telemetry sink is reset last (after ep_detector and download_manager).

EpDetector:
  - New optional `ITelemetry* telemetry` ctor arg (default nullptr) so
    unit tests that instantiate EpDetector directly continue to compile.
  - `DownloadAndRegisterEps` emits one `EPDownloadAndRegister` event
    per bootstrapper via `EpDownloadTracker` and a single aggregate
    `EPDownloadAttempt` event at the end with attempt / success / fail
    counts and an overall status.
  - Exceptions thrown from a bootstrapper invoke
    `EpDownloadTracker::RecordException` before re-throwing so the failure
    is recorded regardless of how it propagates.

DownloadManager:
  - New optional `ITelemetry* telemetry` ctor arg.  When non-null,
    `DownloadModel` wraps the call with a `DownloadTracker` that
    captures lock-wait, enumeration and download timings, total bytes,
    file count, max concurrency and final status (Success / Skipped /
    Failure).  `RecordException` is invoked on the exception path before
    re-throwing.
  - `DownloadModel` now takes an optional `user_agent` parameter so
    HTTP-driven downloads can attribute the event to the calling client.

DownloadBlobsToDirectory:
  - New optional `BlobDownloadStats*` out parameter populated with
    `total_size_bytes`, `file_count`, `enumeration_ms`,
    `download_ms`.  All existing 4-argument callers (including unit
    tests) keep working because the parameter defaults to nullptr.

Verified RelWithDebInfo --no_telemetry: 756 tests pass; 54 skipped
(environmental, missing local test data); 0 functional failures.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Now that microsoft/vcpkg#52316 has merged, bump the manifest baseline
from 256acc64 to 44819aa2 (current master) so the cpp-client-telemetry
3.10.161.1 port resolves.

Also rename the using-declaration in one_ds_telemetry.cc's anonymous
namespace from `using ::Microsoft::Applications::Events::ILogger;` to
`using MatILogger = ::Microsoft::Applications::Events::ILogger;` so it
no longer collides with the local `fl::ILogger` interface from
src/logger.h. Three callsites (SetCommonContext, SafeLog, GetMatLogger)
updated; the OneDsTelemetry ctor's `ILogger& logger` parameter
correctly resolves to fl::ILogger after the rename.

Verified with: python sdk_v2/cpp/build.py --use_telemetry
                       --config RelWithDebInfo --skip_examples
foundry_local.dll = 12.19 MB (telemetry on, empty token).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add /OPT:REF, /OPT:ICF, and /INCREMENTAL:NO to the foundry_local shared
library target for Release and RelWithDebInfo configs. MSVC's /DEBUG flag
(needed for PDB generation) silently disables these optimizations unless
they are explicitly re-enabled, leaving all unreferenced symbols from
statically-linked dependencies (notably cpp-client-telemetry/mat.lib)
in the final binary.

Also add -Wl,--gc-sections (Linux) and -Wl,-dead_strip (macOS) equivalents
for non-Windows builds.

Additionally, declare sqlite3 with default-features:false in vcpkg.json to
drop the unused json1 extension from the SQLite transitive dependency.

Measured impact (RelWithDebInfo, x64-windows, telemetry ON):
  foundry_local.dll: 12.19 MB -> 4.51 MB (-7.68 MB, -63%)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…t) foundation

Reworks the telemetry core ahead of broadening route/inference coverage:

- New InvocationContext {user_agent, correlation_id, indirect} threaded through
  the ITelemetry interface in place of the loose user_agent/indirect params.
  Direct() mints a fresh correlation id; AsIndirect() derives a caused-by child
  that reuses it. ActionTracker now carries the context and guarantees an id.
- Every event (Action/Error/Model/ModelId/Download/EP*) now carries a
  CorrelationId so all events from one operation can be grouped. The Model event
  also gains Stream and Direct.
- indirect now means "happened as a consequence of another action": the
  per-provider EPDownloadAndRegister is marked indirect and shares the overall
  EPDownloadAttempt's correlation id.
- Add ActionStatus::kClientError to separate 4xx client rejects from 5xx/internal
  failures (wired into handlers in a follow-up).
- Prune dead Action enum entries (kModelDownload/kModelDelete/kCoreAudioTranscribe)
  and add kServiceRequestUnmatched for the upcoming router catch-all.
- Share the v4 UUID generator (MakeGuidV4Hex) between metadata and correlation.

Builds clean (/W4 /WX); telemetry + ActionTracker unit tests pass.
…to-end

- Session::ProcessRequest now emits the previously-dead Model (kModelInference)
  event once per inference with model id, tokens, duration, stream flag and the
  caller's correlation id / indirect flag. Adds Session::SetRequestContext so an
  HTTP route can stage an indirect child context (shared correlation id), and a
  virtual ExecutionProvider() hook for the EP field.
- Chat completions handler: derive a Direct route context from the User-Agent
  header; map 4xx early-returns (empty body, invalid JSON, model not found/loaded)
  to kClientError instead of the default kFailure; emit kSessionCreate (indirect)
  on the HTTP path; stage the indirect session context.
- Streaming fix: the route action is no longer recorded (as a premature success
  with ~0ms) when the handler returns. The route ActionTracker is moved into the
  streaming thread and records on completion with the real duration and terminal
  status, so mid-stream failures surface as failures instead of vanishing.

Builds clean (/W4 /WX); telemetry/webservice/sse tests pass.
…, sampling)

Extends the chat-route pattern to every handler:

- Streaming completion fix also applied to the audio transcriptions route (its
  ActionTracker moved into the streaming thread).
- Embeddings, audio, responses (create + get/list/delete/input_items), and the
  model load/unload/list/retrieve routes now derive a Direct context from the
  User-Agent header, map 4xx early-returns to kClientError, and (for the
  inference routes) emit kSessionCreate and stage an indirect session context.
- Instrument GET /models/loaded (kModelList), previously untracked.
- Sample GET /status: emit a kServiceStatus action at most once per hour per
  process so the orchestrator heartbeat doesn't dominate volume.

Builds clean (/W4 /WX); telemetry/webservice/sse tests pass.
…ests

- UnmatchedRouteInterceptor: a request interceptor that, before routing, checks
  the router for a matching route. When none matches (unknown path or wrong
  method) it records a kServiceRequestUnmatched action (kClientError) and replies
  404, so requests that reach the service but no handler are no longer invisible.
- Tests (WebServiceTelemetryTest, using a capturing ITelemetry + empty catalog,
  no real model required):
    * unmatched route records kServiceRequestUnmatched with the right status,
      user agent, Direct flag and a correlation id;
    * an empty chat-completions body records kClientError (not kFailure) and
      emits no Model event;
    * three rapid GET /status calls record kServiceStatus exactly once (hourly
      sampling).

Builds clean (/W4 /WX); 72 telemetry/webservice/sse tests pass.
Every access to a model catalog source is now recorded, with success/failure:

- New CatalogFetch typed event carrying operation ("FetchAll" or the cached-id
  "FetchByIds" lookup), endpoint/region/format parsed from the catalog URL,
  status, duration, model count, error message, and a correlation id shared
  across the accesses of one refresh.
- FetchAllModelInfosWithCachedModels gains optional telemetry params (defaulted,
  so the snapshot tool and existing tests are unchanged) and emits an event for
  the primary fetch and, when it runs, the secondary cached-id lookup.
- AzureModelCatalog parses the catalog URL into endpoint/region/format
  (https://ai.azure.com/api/eastus/ux/v1.0 -> {ai.azure.com, eastus, ux/v1.0};
  "static" for the embedded snapshot) and threads an ITelemetry from Manager.
- Tests assert the primary and secondary accesses are each tracked with the
  right operation, status, endpoint, correlation id and model count.

Builds clean (/W4 /WX); catalog + telemetry + webservice tests pass.
…ions

- Drop the UTCReplace_ magic from the per-process correlation GUID: it only
  fires on the Windows UTC transmission path (not our direct upload, and never
  off-Windows), so it was dead weight. The field is now plainly "AppSessionGuid"
  — a stable per-process correlation id on every platform.
- Add ITelemetry::StartSession()/EndSession() (default no-op; OneDsTelemetry maps
  them to 1DS LogSession(Started/Ended), TelemetryLogger logs them). Manager
  opens a session when the web service starts and closes it on stop, so events
  carry the standard, cross-platform usage-session id (ext.app.sesId) and the
  backend gets session duration. This is additive — it complements the per-run
  AppSessionGuid and the per-operation CorrelationId.

Builds clean (/W4 /WX); telemetry/webservice/catalog tests pass.
Port the C# Foundry Core telemetry event taxonomy to C++ in advance of the
1DS bridge.  The interface refactor is the source of truth — all backend
implementations and call sites are wired against it.

ITelemetry additions:
  - 4 new `Action` values (EpDownloadAttempt, EpDownloadAndRegister,
    ModelFileDownload, ModelInference).
  - 4 new payload structs (`EpDownloadAttemptInfo`,
    `EpDownloadAndRegisterInfo`, `ModelUsageInfo`, `DownloadInfo`).
  - 3 new virtual methods (`RecordEpDownloadAttempt`,
    `RecordEpDownloadAndRegister`, `RecordDownload`).
  - Replaced `RecordModelUsage(model_id, prompt_tokens, completion_tokens,
    duration_ms)` with `RecordModelUsage(const ModelUsageInfo&)` so callers
    can populate richer fields (TimeToFirstToken, EP, memory).
  - Extended `RecordModelId(action, model_id)` to take `status` and
    `user_agent`; added `RecordException(action, ex, user_agent)` overload.

New supporting code (all in `sdk_v2/cpp/src/telemetry/`):
  - `telemetry_environment.{h,cc}` — `IsCiEnvironment` /
    `IsTestingMode` / `IsTruthyValue` / `GetEnv`.  13 CI env-var
    names ported verbatim from neutron-server's `TelemetryEnvironment.cs`.
  - `telemetry_metadata.{h,cc}` — captures per-process metadata
    (`app_session_guid`, version, os_name / os_version / cpu_arch,
    test_mode flag) for stamping on every event.
  - `ep_download_tracker.{h,cc}` — RAII tracker that emits one
    `EPDownloadAndRegister` event per bootstrapper, recording stage
    transitions (initial -> download -> register).  Default failure
    semantics: dtor records remaining stages as `kFailure`; `Done()`
    records them as `kSkipped` for happy-path early exit.
  - `download_tracker.{h,cc}` — RAII tracker that emits one `Download`
    event per `DownloadManager::DownloadModel` call.

`TelemetryLogger` (the fallback / mirror) implements every new method,
formatting events as `[Telemetry] EventName Field=value ...` at Debug.
Test stubs (`NullTelemetry` and the `RecordingTelemetry` used by
`telemetry_test.cc`) were updated for the new interface.

Build verified RelWithDebInfo --no_telemetry.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
OneDsTelemetry is the production ITelemetry implementation.  It embeds a
TelemetryLogger mirror so every event is also logged locally to ILogger for
diagnostics, then conditionally uploads to 1DS through the Microsoft
cpp-client-telemetry SDK.

Suppression model (three-state):
  - CI environment detected -> skip `LogManager::Initialize`; local logging
    still happens, but no upload occurs.
  - Tenant token empty (build did not pass `-DFOUNDRY_LOCAL_TELEMETRY_TOKEN`)
    -> same as CI: no upload, only local logging.
  - Otherwise -> upload.  Every event is stamped with `test=true` when
    `FOUNDRY_TESTING_MODE` is truthy, `test=false` otherwise.

Common context, propagated to every event via `ILogger::SetContext`:
  - `app_name` (from `Configuration::app_name`).
  - `app_session_guid` (random v4 UUID; on Windows the special
    `UTCReplace_AppSessionGuid` field also gets the OS app session GUID).
  - `version` (from the generated `version.h`).
  - `os_name` / `os_version` / `cpu_arch` (Win: `GetVersionExA` +
    `GetNativeSystemInfo`; POSIX: `uname`).

The `MICROSOFT_KEYWORD_CRITICAL_DATA` (bit 47) policy flag is set on
every event via `SetPolicyBitFlags` so the data passes 1DS classifier.

Build / packaging:
  - `vcpkg.json`: `telemetry` feature pulls `cpp-client-telemetry`.
    The port is pending in microsoft/vcpkg#52316; until that merges,
    builds must pass `--no_telemetry`.
  - `CMakeLists.txt`: new `FOUNDRY_LOCAL_USE_TELEMETRY` option
    (default ON) and `FOUNDRY_LOCAL_TELEMETRY_TOKEN` advanced cache
    variable.  Calls `find_package(MSTelemetry CONFIG REQUIRED)`, includes
    `one_ds_telemetry.cc` and `configure_file`-generates
    `one_ds_tenant_token.h` containing the build-time token, then links
    `MSTelemetry::mat` and defines `FOUNDRY_LOCAL_HAS_1DS=1`.
  - `build.py`: new `--no_telemetry` and `--telemetry_token` flags;
    forwards through to CMake / VCPKG_MANIFEST_FEATURES.

Build verified RelWithDebInfo --no_telemetry; --use_telemetry will be
validated once the vcpkg port lands.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Plumb the typed telemetry interface through the orchestration layer so
that real workloads produce the new EPDownloadAttempt, EPDownloadAndRegister
and Download events.

Manager:
  - Construct `telemetry_` before `ep_detector_` so the detector can be
    handed a non-null sink at ctor time.  When `FOUNDRY_LOCAL_HAS_1DS` is
    defined, the implementation is `OneDsTelemetry` and reads the
    build-time token from the generated `one_ds_tenant_token.h`; otherwise
    it falls back to `TelemetryLogger`.
  - Member-declaration order in `manager.h` reorganised so consumers
    (`ep_detector_`, `download_manager_`) appear after the providers
    (`telemetry_`).  C++ destroys in reverse declaration order, so this
    keeps the raw `ITelemetry*` held by `EpDetector` and
    `DownloadManager` valid for their entire lifetime.
  - Explicit `~Manager()` Shutdown reset order updated to match: the
    telemetry sink is reset last (after ep_detector and download_manager).

EpDetector:
  - New optional `ITelemetry* telemetry` ctor arg (default nullptr) so
    unit tests that instantiate EpDetector directly continue to compile.
  - `DownloadAndRegisterEps` emits one `EPDownloadAndRegister` event
    per bootstrapper via `EpDownloadTracker` and a single aggregate
    `EPDownloadAttempt` event at the end with attempt / success / fail
    counts and an overall status.
  - Exceptions thrown from a bootstrapper invoke
    `EpDownloadTracker::RecordException` before re-throwing so the failure
    is recorded regardless of how it propagates.

DownloadManager:
  - New optional `ITelemetry* telemetry` ctor arg.  When non-null,
    `DownloadModel` wraps the call with a `DownloadTracker` that
    captures lock-wait, enumeration and download timings, total bytes,
    file count, max concurrency and final status (Success / Skipped /
    Failure).  `RecordException` is invoked on the exception path before
    re-throwing.
  - `DownloadModel` now takes an optional `user_agent` parameter so
    HTTP-driven downloads can attribute the event to the calling client.

DownloadBlobsToDirectory:
  - New optional `BlobDownloadStats*` out parameter populated with
    `total_size_bytes`, `file_count`, `enumeration_ms`,
    `download_ms`.  All existing 4-argument callers (including unit
    tests) keep working because the parameter defaults to nullptr.

Verified RelWithDebInfo --no_telemetry: 756 tests pass; 54 skipped
(environmental, missing local test data); 0 functional failures.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Now that microsoft/vcpkg#52316 has merged, bump the manifest baseline
from 256acc64 to 44819aa2 (current master) so the cpp-client-telemetry
3.10.161.1 port resolves.

Also rename the using-declaration in one_ds_telemetry.cc's anonymous
namespace from `using ::Microsoft::Applications::Events::ILogger;` to
`using MatILogger = ::Microsoft::Applications::Events::ILogger;` so it
no longer collides with the local `fl::ILogger` interface from
src/logger.h. Three callsites (SetCommonContext, SafeLog, GetMatLogger)
updated; the OneDsTelemetry ctor's `ILogger& logger` parameter
correctly resolves to fl::ILogger after the rename.

Verified with: python sdk_v2/cpp/build.py --use_telemetry
                       --config RelWithDebInfo --skip_examples
foundry_local.dll = 12.19 MB (telemetry on, empty token).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add /OPT:REF, /OPT:ICF, and /INCREMENTAL:NO to the foundry_local shared
library target for Release and RelWithDebInfo configs. MSVC's /DEBUG flag
(needed for PDB generation) silently disables these optimizations unless
they are explicitly re-enabled, leaving all unreferenced symbols from
statically-linked dependencies (notably cpp-client-telemetry/mat.lib)
in the final binary.

Also add -Wl,--gc-sections (Linux) and -Wl,-dead_strip (macOS) equivalents
for non-Windows builds.

Additionally, declare sqlite3 with default-features:false in vcpkg.json to
drop the unused json1 extension from the SQLite transitive dependency.

Measured impact (RelWithDebInfo, x64-windows, telemetry ON):
  foundry_local.dll: 12.19 MB -> 4.51 MB (-7.68 MB, -63%)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…t) foundation

Reworks the telemetry core ahead of broadening route/inference coverage:

- New InvocationContext {user_agent, correlation_id, indirect} threaded through
  the ITelemetry interface in place of the loose user_agent/indirect params.
  Direct() mints a fresh correlation id; AsIndirect() derives a caused-by child
  that reuses it. ActionTracker now carries the context and guarantees an id.
- Every event (Action/Error/Model/ModelId/Download/EP*) now carries a
  CorrelationId so all events from one operation can be grouped. The Model event
  also gains Stream and Direct.
- indirect now means "happened as a consequence of another action": the
  per-provider EPDownloadAndRegister is marked indirect and shares the overall
  EPDownloadAttempt's correlation id.
- Add ActionStatus::kClientError to separate 4xx client rejects from 5xx/internal
  failures (wired into handlers in a follow-up).
- Prune dead Action enum entries (kModelDownload/kModelDelete/kCoreAudioTranscribe)
  and add kServiceRequestUnmatched for the upcoming router catch-all.
- Share the v4 UUID generator (MakeGuidV4Hex) between metadata and correlation.

Builds clean (/W4 /WX); telemetry + ActionTracker unit tests pass.
…to-end

- Session::ProcessRequest now emits the previously-dead Model (kModelInference)
  event once per inference with model id, tokens, duration, stream flag and the
  caller's correlation id / indirect flag. Adds Session::SetRequestContext so an
  HTTP route can stage an indirect child context (shared correlation id), and a
  virtual ExecutionProvider() hook for the EP field.
- Chat completions handler: derive a Direct route context from the User-Agent
  header; map 4xx early-returns (empty body, invalid JSON, model not found/loaded)
  to kClientError instead of the default kFailure; emit kSessionCreate (indirect)
  on the HTTP path; stage the indirect session context.
- Streaming fix: the route action is no longer recorded (as a premature success
  with ~0ms) when the handler returns. The route ActionTracker is moved into the
  streaming thread and records on completion with the real duration and terminal
  status, so mid-stream failures surface as failures instead of vanishing.

Builds clean (/W4 /WX); telemetry/webservice/sse tests pass.
…, sampling)

Extends the chat-route pattern to every handler:

- Streaming completion fix also applied to the audio transcriptions route (its
  ActionTracker moved into the streaming thread).
- Embeddings, audio, responses (create + get/list/delete/input_items), and the
  model load/unload/list/retrieve routes now derive a Direct context from the
  User-Agent header, map 4xx early-returns to kClientError, and (for the
  inference routes) emit kSessionCreate and stage an indirect session context.
- Instrument GET /models/loaded (kModelList), previously untracked.
- Sample GET /status: emit a kServiceStatus action at most once per hour per
  process so the orchestrator heartbeat doesn't dominate volume.

Builds clean (/W4 /WX); telemetry/webservice/sse tests pass.
…ests

- UnmatchedRouteInterceptor: a request interceptor that, before routing, checks
  the router for a matching route. When none matches (unknown path or wrong
  method) it records a kServiceRequestUnmatched action (kClientError) and replies
  404, so requests that reach the service but no handler are no longer invisible.
- Tests (WebServiceTelemetryTest, using a capturing ITelemetry + empty catalog,
  no real model required):
    * unmatched route records kServiceRequestUnmatched with the right status,
      user agent, Direct flag and a correlation id;
    * an empty chat-completions body records kClientError (not kFailure) and
      emits no Model event;
    * three rapid GET /status calls record kServiceStatus exactly once (hourly
      sampling).

Builds clean (/W4 /WX); 72 telemetry/webservice/sse tests pass.
Every access to a model catalog source is now recorded, with success/failure:

- New CatalogFetch typed event carrying operation ("FetchAll" or the cached-id
  "FetchByIds" lookup), endpoint/region/format parsed from the catalog URL,
  status, duration, model count, error message, and a correlation id shared
  across the accesses of one refresh.
- FetchAllModelInfosWithCachedModels gains optional telemetry params (defaulted,
  so the snapshot tool and existing tests are unchanged) and emits an event for
  the primary fetch and, when it runs, the secondary cached-id lookup.
- AzureModelCatalog parses the catalog URL into endpoint/region/format
  (https://ai.azure.com/api/eastus/ux/v1.0 -> {ai.azure.com, eastus, ux/v1.0};
  "static" for the embedded snapshot) and threads an ITelemetry from Manager.
- Tests assert the primary and secondary accesses are each tracked with the
  right operation, status, endpoint, correlation id and model count.

Builds clean (/W4 /WX); catalog + telemetry + webservice tests pass.
…ions

- Drop the UTCReplace_ magic from the per-process correlation GUID: it only
  fires on the Windows UTC transmission path (not our direct upload, and never
  off-Windows), so it was dead weight. The field is now plainly "AppSessionGuid"
  — a stable per-process correlation id on every platform.
- Add ITelemetry::StartSession()/EndSession() (default no-op; OneDsTelemetry maps
  them to 1DS LogSession(Started/Ended), TelemetryLogger logs them). Manager
  opens a session when the web service starts and closes it on stop, so events
  carry the standard, cross-platform usage-session id (ext.app.sesId) and the
  backend gets session duration. This is additive — it complements the per-run
  AppSessionGuid and the per-operation CorrelationId.

Builds clean (/W4 /WX); telemetry/webservice/catalog tests pass.
Bring the local telemetry branch up to the origin/main-backed merge state while preserving the SDK v2 catalog, download, WinML, pipeline, sample, and telemetry updates.

Key files changed:

- sdk_v2/cpp/CMakeLists.txt and sdk_v2/cpp/build.py

- sdk_v2/cpp/src/catalog, src/download, src/ep_detection, and src/telemetry

- sdk_v2/cpp/test telemetry, catalog, download, and SDK API coverage

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 297bc539-5f7f-4a70-9411-48e91a5bf532
Address post-merge review findings before opening the PR: keep telemetry tokens out of logged commands, make the WinML fetch-url path compatible with CMake 3.20, preserve newly discovered catalog variants on refresh, propagate file close failures before deleting download state, and mark cross-process cache hits as skipped downloads.

Files changed:

- sdk_v2/cpp/build.py and cmake/FindWinMLEpCatalog.cmake

- sdk_v2/cpp/src/catalog/base_model_catalog.*

- sdk_v2/cpp/src/download/download_manager.cc and file_writer.cc

- sdk_v2/cpp/test/internal_api/base_model_catalog_test.cc

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 297bc539-5f7f-4a70-9411-48e91a5bf532
Prevent supported CMake 3.20 builds from seeing newer FetchContent options and remove a catalog-refresh data race by making selected model variants atomic.

Files changed:

- sdk_v2/cpp/cmake/FindWinMLEpCatalog.cmake

- sdk_v2/cpp/src/model.cc

- sdk_v2/cpp/src/model.h

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 297bc539-5f7f-4a70-9411-48e91a5bf532
Redact typed telemetry-token CMake defines, serialize manual variant selection against catalog refresh, and bucket custom catalog URLs before uploading CatalogFetch telemetry.

Files changed:

- sdk_v2/cpp/build.py

- sdk_v2/cpp/src/catalog/azure_model_catalog.cc

- sdk_v2/cpp/src/model.cc

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 297bc539-5f7f-4a70-9411-48e91a5bf532
Request the new API table version after adding Catalog.GetModelVersions, keep C#/Python mirrors aligned, and prevent custom catalog failure telemetry from retaining URL query or fragment data.

Files changed:

- sdk_v2/cpp/include/foundry_local/foundry_local_c.h and src/c_api.cc

- sdk_v2/cs/src/Detail/NativeMethods.cs

- sdk_v2/python/src/foundry_local_sdk API-version mirrors

- sdk_v2/cpp/src/telemetry/telemetry_redaction.h and telemetry tests

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 297bc539-5f7f-4a70-9411-48e91a5bf532
Scrub catalog failure details in local logs, make C++ wrapper API-version mismatches fail clearly, and keep required C++ SDK archive dependencies including GSL headers and the WinML runtime DLL.

Files changed:

- .pipelines/v2/templates/steps-pack-cpp-sdk.yml

- sdk_v2/cpp/include/foundry_local/foundry_local_cpp.h

- sdk_v2/cpp/src/catalog/azure_model_catalog.cc

- sdk_v2/cpp/src/telemetry/telemetry_logger.cc and telemetry_redaction.h

- sdk_v2/cpp/test/internal_api/telemetry_test.cc

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 297bc539-5f7f-4a70-9411-48e91a5bf532
Avoid leaking telemetry tokens from failed build commands, acquire WinML through the flat-container FetchContent path by default, sanitize catalog failure logs consistently, and preserve explicit variant selections across catalog refresh.

Files changed:

- sdk_v2/cpp/build.py

- sdk_v2/cpp/cmake/FindWinMLEpCatalog.cmake

- sdk_v2/cpp/src/catalog/azure_model_catalog.cc

- sdk_v2/cpp/src/catalog/base_model_catalog.cc

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 297bc539-5f7f-4a70-9411-48e91a5bf532
Scrub remaining catalog failure logs, bucket nonstandard ai.azure.com catalog paths, and invalidate blob data/resume state when final close surfaces deferred write errors.

Files changed:

- sdk_v2/cpp/src/catalog/azure_model_catalog.cc

- sdk_v2/cpp/src/catalog/catalog_client.cc

- sdk_v2/cpp/src/download/blob_downloader.cc

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 297bc539-5f7f-4a70-9411-48e91a5bf532
bmehta001 added 27 commits July 11, 2026 05:04
Use sanitized catalog display names in refresh logs and avoid disposing the native manager from Node's synchronous exit event where native workers may still be unwinding.

Files changed:

- sdk_v2/cpp/src/catalog/azure_model_catalog.cc

- sdk_v2/cpp/src/catalog/base_model_catalog.cc

- sdk_v2/js/src/foundryLocalManager.ts

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 297bc539-5f7f-4a70-9411-48e91a5bf532
Fetch blob size and identity atomically so resume state and ranged reads agree on the same remote version, validate final model cache path segments, and make web-service shutdown stop safely around startup.

Files changed:

- sdk_v2/cpp/src/download/blob_downloader.cc

- sdk_v2/cpp/src/download/blob_downloader.h

- sdk_v2/cpp/src/download/download_manager.cc

- sdk_v2/cpp/src/manager.cc

- sdk_v2/cpp/src/manager.h

- sdk_v2/cpp/src/service/web_service.cc

- sdk_v2/cpp/test/internal_api/download_test.cc

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 297bc539-5f7f-4a70-9411-48e91a5bf532
Return web-service endpoint snapshots safely, keep JS native manager state alive across in-flight async workers and derived handles, and use ORT_LIB_PATH instead of mutating macOS Python dependency packages.

Files changed:

- sdk_v2/cpp/src/c_api.cc

- sdk_v2/cpp/src/manager.cc

- sdk_v2/cpp/src/manager.h

- sdk_v2/js/native/src/catalog.cc

- sdk_v2/js/native/src/catalog.h

- sdk_v2/js/native/src/manager.cc

- sdk_v2/js/native/src/manager.h

- sdk_v2/js/native/src/model.cc

- sdk_v2/js/native/src/model.h

- sdk_v2/js/native/src/session.cc

- sdk_v2/js/native/src/session.h

- sdk_v2/js/test/manager-dispose.test.ts

- sdk_v2/python/src/foundry_local_sdk/_native/lib_loader.py

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 297bc539-5f7f-4a70-9411-48e91a5bf532
Lease loaded models before session construction, keep JS session workers alive while async operations run, invalidate stale catalog/model handles after manager disposal, clear C API URL snapshots on stop, and report cancelled requests as cancelled telemetry.

Files changed:

- sdk_v2/cpp/src/c_api.cc

- sdk_v2/cpp/src/inferencing/generative/audio/audio_session.*

- sdk_v2/cpp/src/inferencing/generative/chat/chat_session.*

- sdk_v2/cpp/src/inferencing/generative/embeddings/embeddings_session.*

- sdk_v2/cpp/src/inferencing/model_load_manager.*

- sdk_v2/cpp/src/inferencing/session/session.cc

- sdk_v2/cpp/src/service/*handler.*

- sdk_v2/cpp/test/internal_api/model_load_manager_test.cc

- sdk_v2/js/native/src/{catalog,model,session}.*

- sdk_v2/js/src/catalog.ts

- sdk_v2/js/test/manager-dispose.test.ts

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 297bc539-5f7f-4a70-9411-48e91a5bf532
Drop the wrapper-level native manager keepalive when a JS session is disposed while preserving temporary strong keepalives inside in-flight async workers.

Files changed:

- sdk_v2/js/native/src/session.cc

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 297bc539-5f7f-4a70-9411-48e91a5bf532
Use an explicit lifecycle disposed flag for cached Catalog and Model handles, check manager disposal before creating download callbacks, and serialize C API URL snapshot publication with web-service stop.

Files changed:

- sdk_v2/cpp/src/c_api.cc

- sdk_v2/js/native/src/catalog.cc

- sdk_v2/js/native/src/catalog.h

- sdk_v2/js/native/src/manager.cc

- sdk_v2/js/native/src/manager.h

- sdk_v2/js/native/src/model.cc

- sdk_v2/js/native/src/model.h

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 297bc539-5f7f-4a70-9411-48e91a5bf532
Check the explicit manager lifecycle flag before creating sessions and clear streaming callbacks on all worker exit paths after cancellation changes.

Files changed:

- sdk_v2/js/native/src/model.cc

- sdk_v2/js/native/src/model.h

- sdk_v2/js/native/src/session.cc

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 297bc539-5f7f-4a70-9411-48e91a5bf532
Reject Catalog.getLatestVersion calls that pass a Model from a disposed manager before dereferencing the native model pointer.

Files changed:

- sdk_v2/js/native/src/catalog.cc

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 297bc539-5f7f-4a70-9411-48e91a5bf532
Track active JS session leases in the native manager lifecycle so manager disposal fails while sessions or in-flight session workers still hold native state.

Files changed:

- sdk_v2/js/native/src/manager.cc

- sdk_v2/js/native/src/manager.h

- sdk_v2/js/native/src/model.h

- sdk_v2/js/native/src/session.cc

- sdk_v2/js/native/src/session.h

- sdk_v2/js/src/foundryLocalManager.ts

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 297bc539-5f7f-4a70-9411-48e91a5bf532
Respect the retry delay after a forced refresh fails on an already-populated catalog, while preserving the existing catalog until the next retry window.

Files changed:

- sdk_v2/cpp/src/catalog/base_model_catalog.cc

- sdk_v2/cpp/test/internal_api/base_model_catalog_test.cc

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 297bc539-5f7f-4a70-9411-48e91a5bf532
Reset complete-but-unfinalized sidecars before seeding progress, so discarded resume state never emits a high initial progress value before a fresh download pass.

Files changed:

- sdk_v2/cpp/src/download/blob_downloader.cc

- sdk_v2/cpp/test/internal_api/download_test.cc

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 297bc539-5f7f-4a70-9411-48e91a5bf532
Reject web-service start during shutdown, avoid unmatched session-end telemetry, block manager disposal while native workers run, and sanitize/cap client User-Agent before telemetry.

Files changed:

- sdk_v2/cpp/src/manager.cc

- sdk_v2/cpp/src/manager.h

- sdk_v2/cpp/src/service/handler_utils.h

- sdk_v2/cpp/src/service/web_service.cc

- sdk_v2/js/native/src/manager.cc

- sdk_v2/js/native/src/manager.h

- sdk_v2/js/native/src/model.cc

- sdk_v2/js/test/manager-dispose.test.ts

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 297bc539-5f7f-4a70-9411-48e91a5bf532
Return latest versions by model name, fail unknown requested EP names, and keep suspect complete blob sidecars durable until reset state is saved.

Files changed:

- sdk_v2/cpp/src/catalog/base_model_catalog.cc

- sdk_v2/cpp/src/download/blob_downloader.cc

- sdk_v2/cpp/src/ep_detection/ep_detector.cc

- sdk_v2/cpp/test/internal_api/ep_detector_test.cc

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 297bc539-5f7f-4a70-9411-48e91a5bf532
Keep the manager-dispose worker test aligned with native behavior now that unmatched requested EP names fail instead of reporting success.

Files changed:

- sdk_v2/js/test/manager-dispose.test.ts

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 297bc539-5f7f-4a70-9411-48e91a5bf532
Skip finalized blobs during model retry downloads, avoid no-op EP snapshot growth, preserve live model instances for invalid late sessions during teardown, and treat failed terminal SSE pushes as cancellation before success/storage.

Files changed:

- sdk_v2/cpp/src/download/download_manager.cc

- sdk_v2/cpp/src/ep_detection/ep_detector.cc

- sdk_v2/cpp/src/inferencing/model_load_manager.cc

- sdk_v2/cpp/src/service/audio_transcriptions_handler.cc

- sdk_v2/cpp/src/service/chat_completions_handler.cc

- sdk_v2/cpp/src/service/responses_handler.cc

- sdk_v2/cpp/test/internal_api/base_model_catalog_test.cc

- sdk_v2/cpp/test/internal_api/download_test.cc

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 297bc539-5f7f-4a70-9411-48e91a5bf532
Store model IDs with cached Responses sessions and only reuse them when the continuation requests the same resolved model, avoiding silent cross-model inference reuse.

Files changed:

- sdk_v2/cpp/src/inferencing/session/session_manager.cc

- sdk_v2/cpp/src/inferencing/session/session_manager.h

- sdk_v2/cpp/src/service/responses_handler.cc

- sdk_v2/cpp/src/service/responses_handler.h

- sdk_v2/cpp/test/internal_api/session_manager_test.cc

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 297bc539-5f7f-4a70-9411-48e91a5bf532
Avoid raw model pointers during shutdown unload, cache web-service URL snapshots without per-poll growth, and reap completed streaming threads after producer completion.

Files changed:

- sdk_v2/cpp/src/c_api.cc

- sdk_v2/cpp/src/inferencing/model_load_manager.cc

- sdk_v2/cpp/src/service/audio_transcriptions_handler.cc

- sdk_v2/cpp/src/service/chat_completions_handler.cc

- sdk_v2/cpp/src/service/responses_handler.cc

- sdk_v2/cpp/src/service/web_service.h

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 297bc539-5f7f-4a70-9411-48e91a5bf532
Commit streaming Responses state before sending the terminal [DONE] marker so continuations cannot race ahead of response/session persistence.

Files changed:

- sdk_v2/cpp/src/service/responses_handler.cc

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 297bc539-5f7f-4a70-9411-48e91a5bf532
Ensure shutdown unload checks each model at least once after the deadline and fail Windows Python wheel staging when any required native runtime artifact is missing.

Files changed:

- .pipelines/v2/templates/steps-build-python.yml

- sdk_v2/cpp/src/inferencing/model_load_manager.cc

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 297bc539-5f7f-4a70-9411-48e91a5bf532
Re-check shutdown under the load-manager lock and require WinML/DirectML siblings when staging Windows JS prebuilds.

Files changed:

- sdk_v2/cpp/src/inferencing/model_load_manager.cc

- sdk_v2/js/script/pack-prebuilds.mjs

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 297bc539-5f7f-4a70-9411-48e91a5bf532
Only skip full-size blobs during model retry downloads when the existing download marker proves the directory was created by the sidecar-safe downloader; legacy incomplete directories redownload full-size blobs.

Files changed:

- sdk_v2/cpp/src/download/download_manager.cc

- sdk_v2/cpp/test/internal_api/download_test.cc

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 297bc539-5f7f-4a70-9411-48e91a5bf532
Leave unsafe legacy retry markers in place until a full repair completes so failed retries cannot promote corrupt full-size blobs to sidecar-safe skipping.

Files changed:

- sdk_v2/cpp/src/download/download_manager.cc

- sdk_v2/cpp/test/internal_api/download_test.cc

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 297bc539-5f7f-4a70-9411-48e91a5bf532
Use pre-creation directory state for sidecar-safe retry markers and keep Azure catalog public names as configured catalog URIs.

Files changed:

- sdk_v2/cpp/src/catalog/azure_model_catalog.cc

- sdk_v2/cpp/src/download/download_manager.cc

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 297bc539-5f7f-4a70-9411-48e91a5bf532
Merge latest main while preserving telemetry/download hardening and adopting main's platform file I/O split.

Files changed:

- sdk_v2/cpp/src/download/file_writer.cc

- sdk_v2/cpp/test/internal_api/download_test.cc

- merge updates from origin/main

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 297bc539-5f7f-4a70-9411-48e91a5bf532
Keep web-service URL snapshots valid until manager release and sanitize client User-Agent telemetry with a conservative allowlist and length cap.

Files changed:

- sdk_v2/cpp/src/c_api.cc

- sdk_v2/cpp/src/service/handler_utils.h

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 297bc539-5f7f-4a70-9411-48e91a5bf532
Reuse immutable web-service URL snapshots for unchanged URL generations and notify the streaming reaper when a thread completes before tracking observes it.

Files changed:

- sdk_v2/cpp/src/c_api.cc

- sdk_v2/cpp/src/service/web_service.h

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 297bc539-5f7f-4a70-9411-48e91a5bf532
Copy and stage Linux GenAI CUDA and ORT provider runtime libraries so standalone C++ SDK archives include the native dependencies needed by GPU execution providers.

Files changed:

- sdk_v2/cpp/CMakeLists.txt

- .pipelines/v2/templates/steps-build-linux.yml

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 297bc539-5f7f-4a70-9411-48e91a5bf532
@vercel

vercel Bot commented Jul 13, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
foundry-local Ready Ready Preview, Comment Jul 13, 2026 5:34pm

Request Review

@bmehta001

Copy link
Copy Markdown
Contributor Author

Closing this full-branch draft in favor of the split telemetry core PR #879 and hardening stack PR #880.

@bmehta001 bmehta001 closed this Jul 13, 2026
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.

1 participant