[DRAFT] Add SDK v2 telemetry and hardening#878
Closed
bmehta001 wants to merge 79 commits into
Closed
Conversation
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
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
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Contributor
Author
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.
Summary
Validation
python sdk_v2/cpp/build.py --build --config RelWithDebInfonpm run buildinsdk_v2/jsNotes