Skip to content

[DRAFT] Harden SDK v2 telemetry integration paths#880

Draft
bmehta001 wants to merge 88 commits into
bhamehta/flcore/1ds-telemetry-corefrom
bhamehta/flcore/1ds-telemetry-hardening-stack
Draft

[DRAFT] Harden SDK v2 telemetry integration paths#880
bmehta001 wants to merge 88 commits into
bhamehta/flcore/1ds-telemetry-corefrom
bhamehta/flcore/1ds-telemetry-hardening-stack

Conversation

@bmehta001

Copy link
Copy Markdown
Contributor

Summary

  • Stacked on telemetry core.
  • Contains review-driven hardening around download resume safety, runtime packaging, JS/Python native loading/lifetimes, web-service shutdown/streaming, and platform file I/O merge updates.

Notes

  • Draft split from the larger telemetry branch.
  • Base branch is bhamehta/flcore/1ds-telemetry-core.

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.
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
Pass telemetry tokens through the environment instead of argv/cache, publish immutable C API EP snapshots, track skipped download bytes/files, and force a safe redownload when final close reports deferred write failures.

Files changed:

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

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

- sdk_v2/cpp/src/download/blob_downloader.* and download_manager.cc

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

Copilot-Session: 297bc539-5f7f-4a70-9411-48e91a5bf532
Remove the telemetry-token CLI path, require environment-based token injection, raise the CMake floor for WinML package config, make catalog failure telemetry generic, and force safe redownload after unfinalized sidecars or close failures.

Files changed:

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

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

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

- sdk_v2/cpp/src/telemetry/one_ds_tenant_token.h.in

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

Copilot-Session: 297bc539-5f7f-4a70-9411-48e91a5bf532
Reject telemetry tokens supplied through the CMake cache, broaden build-command secret redaction, and reselect default variants after refresh only when the caller has not explicitly selected a variant.

Files changed:

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

- sdk_v2/cpp/src/model.* and 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
Keep CMake 3.21-compatible FetchContent calls, redact URL-valued build defines, report unmeasured TTFT as unset, and let WebService join streaming threads after service-dependent cleanup.

Files changed:

- sdk_v2/cpp/build.py

- sdk_v2/cpp/cmake/FindOnnxRuntime*.cmake

- sdk_v2/cpp/src/service streaming handlers and web_service.h

- sdk_v2/cpp/src/telemetry/telemetry.h

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

Copilot-Session: 297bc539-5f7f-4a70-9411-48e91a5bf532
Include ORT/GenAI runtime dependencies in C++ SDK bundles, keep no-telemetry builds from materializing tenant tokens, and join streaming threads after connection shutdown prevents new producers.

Files changed:

- .pipelines/v2/templates/steps-build-{windows,linux,macos}.yml

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

- sdk_v2/cpp/CMakeLists.txt

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

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

Copilot-Session: 297bc539-5f7f-4a70-9411-48e91a5bf532
Include provider companion patterns in Windows C++ artifacts, ensure Linux outputs include the ORT soname symlink, and avoid trusting size-only blob cache hits while resuming incomplete model downloads.

Files changed:

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

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

- sdk_v2/cpp/CMakeLists.txt

- sdk_v2/cpp/src/download/blob_downloader.* and download_manager.cc

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

Copilot-Session: 297bc539-5f7f-4a70-9411-48e91a5bf532
Reap completed streaming producer threads during normal operation, stage optional provider companion libraries, and make optional provider patterns non-fatal in C++ SDK archive packaging.

Files changed:

- .pipelines/v2/templates/steps-build-{linux,macos}.yml

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

- sdk_v2/cpp/src/service streaming handlers and web_service.h

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

Copilot-Session: 297bc539-5f7f-4a70-9411-48e91a5bf532
Forward DirectML with WinML, keep Python wheels limited to intended native payloads, and add SSE abort/reap handling so shutdown can wake streams and cancel producers.

Files changed:

- .pipelines/v2/templates/steps-build-{windows,python}.yml and steps-pack-cpp-sdk.yml

- sdk_v2/cpp/CMakeLists.txt and nuget/pack.py

- sdk_v2/cpp/src/service streaming helpers/handlers

- sdk_v2/js/script/copy-native.mjs

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

Copilot-Session: 297bc539-5f7f-4a70-9411-48e91a5bf532
Forward DirectML into JS/Python Windows payloads, verify the CUDA EP archive before extraction, and keep size-only blob skips disabled only for true incomplete-download resumes.

Files changed:

- .pipelines/v2/templates/steps-build-{js,python}.yml

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

- sdk_v2/cpp/src/ep_detection/cuda_ep_bootstrapper.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
Keep Windows Python DLL-directory handles alive, run /shutdown asynchronously, abort late-tracked streams during shutdown, and expose the CDN CUDA bootstrapper only on Windows.

Files changed:

- sdk_v2/python/src/foundry_local_sdk/_native/{api.py,lib_loader.py}

- sdk_v2/cpp/src/service/web_service.{cc,h}

- sdk_v2/cpp/src/manager.cc

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

Copilot-Session: 297bc539-5f7f-4a70-9411-48e91a5bf532
Auto-enable telemetry vcpkg feature for direct CMake, fix Windows ARM64 Python native probing, fully validate cached CUDA DLL payloads, gate unsupported WebGPU/CUDA bootstrapper platforms, clean up ORT/GenAI callbacks on constructor failure, and clean up partial web-service startup.

Files changed:

- sdk_v2/cpp/CMakeLists.txt

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

- sdk_v2/cpp/src/ep_detection/{cuda_ep_bootstrapper,webgpu_ep_bootstrapper,ep_utils}.*

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

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

Copilot-Session: 297bc539-5f7f-4a70-9411-48e91a5bf532
Bring the latest telemetry core review fixes into the stacked hardening branch while preserving the stronger web-service lifecycle protections already present in the stack.

Files changed:

- sdk_v2/cpp/src/manager.cc

- sdk_v2/cpp/src/telemetry/telemetry_environment.cc

- 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
Bring PR #879 round-5 Copilot fixes into the stacked hardening branch while preserving stack-only packaging hardening.

Keep #880's stricter unknown-EP behavior and include unmatched requested EPs in aggregate telemetry failure counts.

Files changed:

- sdk_v2/cpp/vcpkg.json

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

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

- sdk_v2/cpp/src/inferencing/generative/{chat,audio,embeddings}/*session*

- sdk_v2/cpp/src/service/{chat_completions,audio_transcriptions}_handler.cc

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

- sdk_v2/cpp/src/telemetry/{invocation_context,one_ds_telemetry,telemetry}.cc

- sdk_v2/cpp/test/internal_api/{ep_detector,telemetry}_test.cc

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

Copilot-Session: 297bc539-5f7f-4a70-9411-48e91a5bf532
Bring PR #879 round-6 Copilot fixes into the hardening stack while preserving #880's stricter unknown-EP behavior.

EP telemetry: cancellation records skipped provider phases and unmatched requested EPs remain aggregate failures in the stack.

Status telemetry: add/reset sampler state for deterministic status heartbeat tests.

Files changed:

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

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

- sdk_v2/cpp/src/service/web_service.{h,cc}

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

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

Copilot-Session: 297bc539-5f7f-4a70-9411-48e91a5bf532
…re' into bhamehta/flcore/1ds-telemetry-hardening-stack
…re' into bhamehta/flcore/1ds-telemetry-hardening-stack
Bring the ONNX Runtime-inspired ProcessInfo event into #880 while preserving the hardening stack's existing telemetry redaction tests.

Files changed:

- sdk_v2/cpp/src/manager.cc

- sdk_v2/cpp/src/telemetry/{telemetry,telemetry_logger,one_ds_telemetry,telemetry_metadata}.{h,cc}

- 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
Bring the persistent hashed device-id support from #879 into #880 while preserving the hardening stack's telemetry redaction behavior.

Files changed:

- sdk_v2/cpp/CMakeLists.txt

- sdk_v2/cpp/src/telemetry/device_id.{h,cc}

- sdk_v2/cpp/src/telemetry/one_ds_telemetry.cc

- sdk_v2/cpp/src/telemetry/{telemetry,telemetry_logger,telemetry_metadata}.cc

- sdk_v2/cpp/src/util/sha256.{h,cc}

- 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
…re' into bhamehta/flcore/1ds-telemetry-hardening-stack
Bring the final telemetry core docs/guards into #880: Privacy.md, UWP 1DS exclusion, and OneDsTelemetry initialized_ publish ordering.

Files changed:

- sdk_v2/cpp/docs/Privacy.md

- sdk_v2/cpp/CMakeLists.txt

- sdk_v2/cpp/vcpkg.json

- sdk_v2/cpp/src/telemetry/one_ds_telemetry.cc

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

Copilot-Session: 297bc539-5f7f-4a70-9411-48e91a5bf532
…re' into bhamehta/flcore/1ds-telemetry-hardening-stack
Bring all remaining #879 telemetry updates into #880, including FOUNDRY_TESTING_MODE removal, privacy-doc updates, and the OneDsTelemetry merge resolution.

Files changed:

- sdk_v2/cpp/docs/Privacy.md

- sdk_v2/cpp/src/telemetry/one_ds_telemetry.cc

- sdk_v2/cpp/src/telemetry/telemetry_environment.{h,cc}

- sdk_v2/cpp/src/telemetry/telemetry_logger.h

- sdk_v2/cpp/src/telemetry/telemetry_metadata.{h,cc}

- 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
Pass ITelemetry by reference through catalog, download, and EP detector paths so Manager always wires the real telemetry sink and direct tests explicitly use NullTelemetry. This removes nullable production telemetry plumbing while preserving test fakes.

Disable 1DS upload from C++ test binaries before GoogleTest initializes by setting FOUNDRY_LOCAL_TELEMETRY_DISABLED=1 in a shared test main. OneDsTelemetry now treats that switch like CI for upload suppression, so tests still exercise ITelemetry/local logging without sending events.

Files changed:

- sdk_v2/cpp/src/{catalog,download,ep_detection,telemetry}/ telemetry interfaces and gates

- sdk_v2/cpp/src/manager.{h,cc}

- sdk_v2/cpp/test/CMakeLists.txt and sdk_v2/cpp/test/test_main.cc

- sdk_v2/cpp/test/internal_api/* telemetry/download/catalog/EP tests

- sdk_v2/cpp/docs/Privacy.md

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

Copilot-Session: 297bc539-5f7f-4a70-9411-48e91a5bf532
Replace the no-op telemetry fake with TelemetryLogger wired to NullLog so tests exercise the same telemetry implementation without producing output. This removes the extra test-only ITelemetry implementation and keeps nullable production telemetry removed.

Drop the custom FOUNDRY_LOCAL_TELEMETRY_DISABLED switch introduced in 05edfba. Test binaries now set the existing CI gate before GoogleTest initializes, so OneDsTelemetry skips 1DS initialization via the same path used in CI.

Files changed:

- sdk_v2/cpp/test/internal_api/{audio,chat,session_manager,web_service,download,ep_detector,azure_catalog,telemetry,test_helpers}*

- sdk_v2/cpp/test/test_main.cc

- sdk_v2/cpp/src/telemetry/{one_ds_telemetry,telemetry_environment}.{h,cc}

- sdk_v2/cpp/docs/Privacy.md

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

Copilot-Session: 297bc539-5f7f-4a70-9411-48e91a5bf532
Mirror ONNX Runtime's bhamehta/suppress-test-telemetry pattern by setting ORT_RUNNING_UNIT_TESTS=1 in the C++ test entry point and adding IsRunningUnitTests()/ShouldSuppressTelemetry() helpers.

This keeps local test runs from initializing the 1DS uploader or emitting ProcessInfo without pretending the process is CI and without introducing a Foundry-specific disable switch.

Files changed:

- sdk_v2/cpp/src/telemetry/{telemetry_environment,one_ds_telemetry}.{h,cc}

- sdk_v2/cpp/src/manager.cc

- sdk_v2/cpp/test/test_main.cc

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

- sdk_v2/cpp/docs/Privacy.md

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

Copilot-Session: 297bc539-5f7f-4a70-9411-48e91a5bf532
Bring Foundry Local's startup telemetry metadata in line with the ORT/ORT GenAI telemetry branches: add cpuModel and deviceClass, use processorCount/deviceIdStatus field naming, and stop collecting locale.

Honor ORT_TELEMETRY_DISABLED for non-essential 1DS uploads while still allowing ProcessInfo outside CI/unit-test suppression, matching ORT GenAI semantics. CI and ORT_RUNNING_UNIT_TESTS remain hard-suppression paths that skip uploader initialization and ProcessInfo.

Files changed:

- sdk_v2/cpp/src/telemetry/{telemetry,telemetry_environment,telemetry_metadata,telemetry_logger,one_ds_telemetry}.{h,cc}

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

- sdk_v2/cpp/docs/Privacy.md

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

Copilot-Session: 297bc539-5f7f-4a70-9411-48e91a5bf532
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.

2 participants