[DRAFT] Add SDK v2 telemetry core#879
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.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
There was a problem hiding this comment.
Pull request overview
Adds SDK v2 telemetry infrastructure, 1DS transport, correlation contexts, and instrumentation across inference, downloads, catalogs, EP registration, and HTTP services.
Changes:
- Introduces typed telemetry payloads, trackers, metadata, and optional 1DS upload support.
- Instruments SDK operations and streaming HTTP routes with correlated telemetry.
- Adds telemetry dependencies, build options, tests, and linker-size optimizations.
Reviewed changes
Copilot reviewed 49 out of 49 changed files in this pull request and generated 20 comments.
Show a summary per file
| File | Description |
|---|---|
sdk_v2/cpp/vcpkg.json |
Adds telemetry dependencies and feature. |
sdk_v2/cpp/test/internal_api/web_service_test.cc |
Tests HTTP telemetry behavior. |
sdk_v2/cpp/test/internal_api/telemetry_test.cc |
Updates telemetry unit tests. |
sdk_v2/cpp/test/internal_api/null_telemetry.h |
Updates no-op test sink. |
sdk_v2/cpp/src/telemetry/telemetry.h |
Defines telemetry API and payloads. |
sdk_v2/cpp/src/telemetry/telemetry.cc |
Maps actions and statuses. |
sdk_v2/cpp/src/telemetry/telemetry_metadata.h |
Declares process metadata. |
sdk_v2/cpp/src/telemetry/telemetry_metadata.cc |
Collects platform metadata. |
sdk_v2/cpp/src/telemetry/telemetry_logger.h |
Expands local telemetry logger. |
sdk_v2/cpp/src/telemetry/telemetry_logger.cc |
Formats typed telemetry events. |
sdk_v2/cpp/src/telemetry/telemetry_environment.h |
Declares runtime telemetry gating. |
sdk_v2/cpp/src/telemetry/telemetry_environment.cc |
Implements CI/test detection. |
sdk_v2/cpp/src/telemetry/telemetry_action_tracker.h |
Adds invocation-context tracking. |
sdk_v2/cpp/src/telemetry/telemetry_action_tracker.cc |
Emits correlated action events. |
sdk_v2/cpp/src/telemetry/one_ds_tenant_token.h.in |
Generates the tenant-token header. |
sdk_v2/cpp/src/telemetry/one_ds_telemetry.h |
Declares the 1DS sink. |
sdk_v2/cpp/src/telemetry/one_ds_telemetry.cc |
Implements 1DS event uploads. |
sdk_v2/cpp/src/telemetry/invocation_context.h |
Defines correlation context. |
sdk_v2/cpp/src/telemetry/invocation_context.cc |
Generates correlation UUIDs. |
sdk_v2/cpp/src/telemetry/ep_download_tracker.h |
Declares EP telemetry tracker. |
sdk_v2/cpp/src/telemetry/ep_download_tracker.cc |
Emits EP attempt details. |
sdk_v2/cpp/src/telemetry/download_tracker.h |
Declares model-download tracker. |
sdk_v2/cpp/src/telemetry/download_tracker.cc |
Emits model-download telemetry. |
sdk_v2/cpp/src/service/web_service.cc |
Instruments status and unmatched routes. |
sdk_v2/cpp/src/service/responses_handler.h |
Passes streaming route trackers. |
sdk_v2/cpp/src/service/responses_handler.cc |
Instruments Responses API operations. |
sdk_v2/cpp/src/service/models_handlers.cc |
Instruments model endpoints. |
sdk_v2/cpp/src/service/handler_utils.h |
Extracts request user agents. |
sdk_v2/cpp/src/service/embeddings_handler.cc |
Instruments embedding inference. |
sdk_v2/cpp/src/service/chat_completions_handler.h |
Extends streaming tracker ownership. |
sdk_v2/cpp/src/service/chat_completions_handler.cc |
Instruments chat streaming. |
sdk_v2/cpp/src/service/audio_transcriptions_handler.h |
Extends audio tracker ownership. |
sdk_v2/cpp/src/service/audio_transcriptions_handler.cc |
Instruments audio streaming. |
sdk_v2/cpp/src/manager.h |
Adjusts telemetry lifetime ordering. |
sdk_v2/cpp/src/manager.cc |
Constructs sinks and manages sessions. |
sdk_v2/cpp/src/inferencing/session/session.h |
Adds per-request telemetry context. |
sdk_v2/cpp/src/inferencing/session/session.cc |
Emits inference usage metrics. |
sdk_v2/cpp/src/ep_detection/ep_detector.h |
Accepts an optional telemetry sink. |
sdk_v2/cpp/src/ep_detection/ep_detector.cc |
Instruments EP registration. |
sdk_v2/cpp/src/download/download_manager.h |
Extends download telemetry API. |
sdk_v2/cpp/src/download/download_manager.cc |
Instruments model downloads. |
sdk_v2/cpp/src/download/blob_downloader.h |
Defines download statistics. |
sdk_v2/cpp/src/download/blob_downloader.cc |
Collects transfer statistics. |
sdk_v2/cpp/src/catalog/catalog_client.h |
Extends catalog telemetry API. |
sdk_v2/cpp/src/catalog/catalog_client.cc |
Emits catalog-fetch events. |
sdk_v2/cpp/src/catalog/azure_model_catalog.h |
Stores the telemetry sink. |
sdk_v2/cpp/src/catalog/azure_model_catalog.cc |
Adds catalog URL dimensions. |
sdk_v2/cpp/CMakeLists.txt |
Configures 1DS and linker stripping. |
sdk_v2/cpp/build.py |
Adds telemetry build options. |
Comments suppressed due to low confidence (1)
sdk_v2/cpp/src/service/responses_handler.cc:605
- Calling
Remove()makes shutdown stop waiting for this worker, but the capturedroute_trackeris destroyed only after the lambda returns. Manager teardown can consequently destroy telemetry in that gap and the tracker destructor will dereference freed telemetry. Emit/destroy the tracker before untracking the thread.
// Terminal event per spec
body_ptr->Push("data: [DONE]\n\n");
body_ptr->Finish();
tracker.Remove(std::this_thread::get_id());
| if args.telemetry_token is not None: | ||
| command += [f"-DFOUNDRY_LOCAL_TELEMETRY_TOKEN={args.telemetry_token}"] |
| // GetVersionExA is deprecated and lies for unmanifested apps. The reliable | ||
| // approach is to read the build number directly from kernel32 via | ||
| // RtlGetVersion, or fall back to the OS version registry. For now, use | ||
| // GetVersionEx — the deprecation only affects apps without a manifest, and | ||
| // Foundry Local has a manifest declaring Win10 / Win11 compat. |
| // Re-throw to preserve existing semantics — the wrapper RAII guard above | ||
| // resets download_in_progress_; the tracker dtor records the EP event. | ||
| throw; |
| if (tracker) { | ||
| tracker->RecordDownloadComplete(ActionStatus::kSuccess, "Installed"); | ||
| tracker->RecordRegisterComplete(ActionStatus::kSuccess, "Registered"); |
| std::unique_ptr<DownloadTracker> tracker; | ||
| if (telemetry_ != nullptr) { | ||
| tracker = std::make_unique<DownloadTracker>(info.model_id, user_agent, *telemetry_); | ||
| tracker->SetLockWaitMs(lock_wait_ms); | ||
| tracker->SetMaxConcurrency(static_cast<int32_t>(max_concurrency_)); | ||
| } |
| body_ptr->Finish(); | ||
| tracker.Remove(std::this_thread::get_id()); | ||
| thread_tracker.Remove(std::this_thread::get_id()); |
| telemetry_.RecordAction(action_, status_, context_, duration_ms); | ||
|
|
||
| if (!model_id_.empty()) { | ||
| telemetry_.RecordModelId(action_, model_id_); | ||
| telemetry_.RecordModelId(action_, model_id_, status_, context_); |
| DownloadTracker::~DownloadTracker() { | ||
| // Emit the Download event regardless of outcome. The default status is | ||
| // kFailure so abrupt exits (exceptions) are recorded as failures. | ||
| telemetry_.RecordDownload(info_); | ||
| } |
| EpDownloadTracker::~EpDownloadTracker() { | ||
| // Mirror neutron-server: if the caller didn't reach Done() or | ||
| // RecordRegisterComplete, assume the abrupt exit was an exception path and | ||
| // record any unfinished stage as kFailure. | ||
| RecordEvent(ActionStatus::kFailure); | ||
| } |
| parser.add_argument( | ||
| "--no_telemetry", action="store_true", | ||
| help="Skip building the 1DS (cpp-client-telemetry) bridge. Useful while the vcpkg " | ||
| "port (microsoft/vcpkg#52316) is unmerged or when building forks that should " | ||
| "not link any telemetry transport. Local diagnostic logging via TelemetryLogger " | ||
| "still works.", | ||
| ) |
Remove CLI tenant-token plumbing, use manifest-independent Windows OS metadata, make telemetry trackers best-effort, improve EP/download/session telemetry accuracy, and guard moved stream route trackers. Files changed: - sdk_v2/cpp/build.py - sdk_v2/cpp/CMakeLists.txt - sdk_v2/cpp/src/telemetry/* - sdk_v2/cpp/src/ep_detection/ep_detector.cc - sdk_v2/cpp/src/download/* - sdk_v2/cpp/src/inferencing/session/session.cc - sdk_v2/cpp/src/service/*handler.cc Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 297bc539-5f7f-4a70-9411-48e91a5bf532
Bring PR #879's Copilot round-1 telemetry fixes into the stacked hardening PR while preserving the hardening branch's broader implementations for conflicting files. Files changed: - sdk_v2/cpp/src/download/download_manager.cc - sdk_v2/cpp/src/ep_detection/ep_detector.cc - sdk_v2/cpp/src/inferencing/session/session.cc - sdk_v2/cpp/src/telemetry/download_tracker.h - sdk_v2/cpp/src/telemetry/telemetry_metadata.cc Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 297bc539-5f7f-4a70-9411-48e91a5bf532
| .count(); | ||
| usage.total_tokens = static_cast<int32_t>(response.usage.total_tokens); | ||
| usage.input_token_count = static_cast<int32_t>(response.usage.prompt_tokens); | ||
| telemetry_.RecordModelUsage(usage); |
| info.duration_ms = duration_ms; | ||
| info.model_count = model_count; | ||
| info.error_message = error; | ||
| telemetry->RecordCatalogFetch(info); |
| attempt_info.duration_ms = std::chrono::duration_cast<std::chrono::milliseconds>( | ||
| std::chrono::steady_clock::now() - attempt_start) | ||
| .count(); | ||
| telemetry_->RecordEpDownloadAttempt(attempt_info); |
| web_service_running_ = true; | ||
| // Open an app-usage session for the lifetime of the running service so events | ||
| // carry ext.app.sesId and the backend gets session duration. | ||
| telemetry_->StartSession(); |
| web_service_.reset(); | ||
| web_service_running_ = false; | ||
| bound_urls_.clear(); | ||
| telemetry_->EndSession(); |
| std::string correlation_id; | ||
| bool stream = false; // True if the inference was streamed (SSE) vs a single response | ||
| bool indirect = false; // True if the inference was driven by another action (e.g. an HTTP route) | ||
| int64_t time_to_first_token_ms = 0; |
| int64_t lock_wait_ms = std::chrono::duration_cast<std::chrono::milliseconds>( | ||
| clock::now() - lock_wait_start) | ||
| .count(); |
| if (auto slash = rest.find('/'); slash == std::string::npos) { | ||
| out.endpoint = rest; | ||
| } else { | ||
| out.endpoint = rest.substr(0, slash); | ||
| path = rest.substr(slash + 1); |
Make telemetry sink calls best-effort across model/catalog/session paths, sanitize 1DS error text, mirror session events locally, use an unknown TTFT sentinel, improve catalog URL dimensions and status sampling, and measure download lock waits accurately. Files changed: - sdk_v2/cpp/src/catalog/* - sdk_v2/cpp/src/download/download_manager.cc - sdk_v2/cpp/src/ep_detection/ep_detector.cc - sdk_v2/cpp/src/inferencing/session/session.cc - sdk_v2/cpp/src/manager.cc - sdk_v2/cpp/src/service/web_service.cc - sdk_v2/cpp/src/telemetry/* Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 297bc539-5f7f-4a70-9411-48e91a5bf532
| ActionTracker create_tracker(Action::kSessionCreate, ctx_.telemetry, session_ctx); | ||
| create_tracker.SetModelId(model_name); | ||
| ChatSession session(*model, *loaded, ctx_.logger, ctx_.telemetry); | ||
| create_tracker.SetStatus(ActionStatus::kSuccess); |
| ActionTracker create_tracker(Action::kSessionCreate, ctx_.telemetry, session_ctx); | ||
| create_tracker.SetModelId(model_name); | ||
| session = std::make_unique<ChatSession>(*model, *loaded, ctx_.logger, ctx_.telemetry); | ||
| create_tracker.SetStatus(ActionStatus::kSuccess); |
| ActionTracker create_tracker(Action::kSessionCreate, ctx_.telemetry, session_ctx); | ||
| create_tracker.SetModelId(model_name); | ||
| EmbeddingsSession session(*model, *loaded, ctx_.logger, ctx_.telemetry); | ||
| create_tracker.SetStatus(ActionStatus::kSuccess); |
| ActionTracker create_tracker(Action::kSessionCreate, ctx_.telemetry, session_ctx); | ||
| create_tracker.SetModelId(model_name); | ||
| AudioSession session(*model, *loaded, ctx_.logger, ctx_.telemetry); | ||
| create_tracker.SetStatus(ActionStatus::kSuccess); |
| // Use the context the caller staged (an HTTP route stages an indirect child | ||
| // with the route's correlation id); otherwise mint a direct context per call | ||
| // for direct SDK use. | ||
| InvocationContext context = request_context_ ? *request_context_ : InvocationContext::Direct(); | ||
| context.EnsureCorrelationId(); |
| /// Payload for the CatalogFetch event — emitted once per access to a model | ||
| /// catalog source (the live Azure catalog or the embedded static snapshot). | ||
| struct CatalogFetchInfo { |
| // RAII telemetry tracker — emits a "Download" event on destruction with whatever | ||
| // fields have been populated. Default status is kFailure so abrupt exits (exceptions) | ||
| // are recorded as failures; the happy path explicitly sets kSuccess / kSkipped. | ||
| std::unique_ptr<DownloadTracker> tracker; | ||
| if (telemetry_ != nullptr) { |
| bool TelemetryEnvironment::IsTruthyValue(std::string_view value) { | ||
| auto trimmed = Trim(value); | ||
| if (trimmed.empty()) { | ||
| return false; | ||
| } |
| // Use the W variant so we don't depend on the legacy CRT _CRT_SECURE_NO_WARNINGS. | ||
| // Env-var values are ASCII for the CI flags we care about; if a value is unicode | ||
| // we still get the bytes round-tripped correctly because we only do truthiness checks. |
Bring PR #879's second Copilot telemetry fixes into the hardening stack while retaining stronger redaction and lifecycle behavior already present here. Files changed: - sdk_v2/cpp/src/catalog/* - sdk_v2/cpp/src/download/download_manager.cc - sdk_v2/cpp/src/ep_detection/ep_detector.cc - sdk_v2/cpp/src/inferencing/session/session.cc - sdk_v2/cpp/src/service/web_service.cc - 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
Scope session-create timing to construction, consume staged request telemetry context once, and clean up remaining telemetry contract/duplicate-download-wait details. Files changed: - sdk_v2/cpp/src/inferencing/session/* - sdk_v2/cpp/src/service/*handler.cc - sdk_v2/cpp/src/download/download_manager.cc - sdk_v2/cpp/src/telemetry/telemetry.h Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 297bc539-5f7f-4a70-9411-48e91a5bf532
Keep telemetry enabled by default while making build-time opt-out explicit, block token overrides from CMake cache so pipelines do not depend on injected secrets, and add the native Android readiness bridge used before 1DS initialization. Also removes stale internal website wording that described telemetry as absent, keeping privacy language focused on on-device model processing. Files changed: sdk_v2/cpp/CMakeLists.txt, sdk_v2/cpp/build.py, sdk_v2/cpp/src/telemetry/android_telemetry_bridge.cc, sdk_v2/cpp/src/telemetry/one_ds_telemetry.cc, www/.internal-docs/CLEANUP_SUMMARY.md Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 297bc539-5f7f-4a70-9411-48e91a5bf532
Emit a dedicated AudioModel event after successful audio inference so audio models have modality-specific stats in addition to the generic Model event. The payload avoids file names and paths while capturing safe source kind, token counts, timing, stream/direct context, language hint, and PCM format/duration when available. Files changed: sdk_v2/cpp/src/inferencing/generative/audio/audio_session.cc, sdk_v2/cpp/src/inferencing/generative/audio/audio_session.h, sdk_v2/cpp/src/inferencing/session/session.cc, sdk_v2/cpp/src/inferencing/session/session.h, sdk_v2/cpp/src/telemetry/one_ds_telemetry.cc, sdk_v2/cpp/src/telemetry/one_ds_telemetry.h, sdk_v2/cpp/src/telemetry/telemetry.h, sdk_v2/cpp/src/telemetry/telemetry_logger.cc, sdk_v2/cpp/src/telemetry/telemetry_logger.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
Port the ORT/OGA client-side sampling helper and stamp popSample on 1DS events while keeping the current sampling rate at 100%. This gives Foundry the same event-level sampling control point for future volume reduction without changing current collection behavior. Files changed: sdk_v2/cpp/src/telemetry/one_ds_telemetry.cc, sdk_v2/cpp/src/telemetry/telemetry_sampling.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
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 83 out of 83 changed files in this pull request and generated 1 comment.
Comments suppressed due to low confidence (1)
sdk_v2/cpp/src/telemetry/one_ds_telemetry.cc:180
- A zero teardown timeout makes cpp-client-telemetry skip the upload-wait path and abort queued/pending requests during
FlushAndTeardown(). Since the destructor relies on that call to deliver the final session and recently queued events, normal process shutdown can lose telemetry. Use a positive timeout (the upstream runtime default is 1 second; its functional tests commonly use 2 seconds).
| #if FOUNDRY_LOCAL_HAS_1DS | ||
| // OneDsTelemetry keeps an always-on local diagnostic mirror and uploads to 1DS only when telemetry is | ||
| // not disabled by configuration and not in a CI environment. | ||
| telemetry_ = std::make_unique<OneDsTelemetry>(config_.app_name, *logger_, config_.disable_telemetry); | ||
| #else | ||
| telemetry_ = std::make_unique<TelemetryLogger>(config_.app_name, *logger_); |
Configure a positive 1DS teardown upload budget so FlushAndTeardown can upload queued events instead of aborting pending requests when maxTeardownUploadTimeInSec is zero. Files changed: 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
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 83 out of 83 changed files in this pull request and generated 1 comment.
Comments suppressed due to low confidence (1)
sdk_v2/cpp/src/manager.cc:354
disable_telemetry=truestill installs a telemetry sink:OneDsTelemetrymirrors every event toTelemetryLogger, and the no-1DS branch always usesTelemetryLoggerdirectly. Consequently model IDs, user agents, timings, and errors continue to be collected in local logs even though every public configuration contract says the SDK “collects and uploads nothing.” Select a no-opITelemetryimplementation when the option is set (before passing it to the detector, catalog, downloads, and sessions); keep local mirroring only for CI/transport-unavailable cases where telemetry was not explicitly disabled.
#if FOUNDRY_LOCAL_HAS_1DS
// OneDsTelemetry keeps an always-on local diagnostic mirror and uploads to 1DS only when telemetry is
// not disabled by configuration and not in a CI environment.
telemetry_ = std::make_unique<OneDsTelemetry>(config_.app_name, *logger_, config_.disable_telemetry);
#else
telemetry_ = std::make_unique<TelemetryLogger>(config_.app_name, *logger_);
#endif
| std::string out(static_cast<size_t>(needed - 1), '\0'); | ||
| const int written = ::WideCharToMultiByte(CP_UTF8, 0, wide_value, -1, out.data(), needed, nullptr, nullptr); | ||
| return written > 0 ? TrimVersionString(std::move(out)) : std::string{}; |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 83 out of 83 changed files in this pull request and generated 5 comments.
Comments suppressed due to low confidence (1)
sdk_v2/cpp/src/manager.cc:353
disable_telemetrydoes not implement the documented “collects and uploads nothing” contract.OneDsTelemetrystill sends every event to itsTelemetryLoggermirror when disabled, while telemetry-off builds unconditionally selectTelemetryLoggerand ignore the flag entirely. Select a true no-op sink before wiring telemetry into the subsystems, and verify that disabling telemetry emits neither event payloads nor telemetry log records.
#if FOUNDRY_LOCAL_HAS_1DS
// OneDsTelemetry keeps an always-on local diagnostic mirror and uploads to 1DS only when telemetry is
// not disabled by configuration and not in a CI environment.
telemetry_ = std::make_unique<OneDsTelemetry>(config_.app_name, *logger_, config_.disable_telemetry);
#else
telemetry_ = std::make_unique<TelemetryLogger>(config_.app_name, *logger_);
| /// Optional. Disable all telemetry. When true, the SDK collects and uploads no telemetry (no 1DS | ||
| /// uploader is created and no device identifier is written). Defaults to false (telemetry enabled). | ||
| FL_API_STATUS(SetDisableTelemetry, _In_ flConfiguration* config, bool disable); |
| void EpDownloadTracker::Done() { | ||
| RecordEvent(ActionStatus::kSkipped); | ||
| } |
| - **Environment / device:** Foundry Local version, operating system, architecture, CPU details, and total memory, plus a device identifier. On Windows, Linux, and macOS the device identifier is a locally generated random UUID (**not** a hardware identifier such as a machine GUID); only a hashed form is transmitted, and it can be reset. On Android, Foundry Local uses the device identifier provided by the 1DS SDK instead of creating a separate Foundry-generated device id. | ||
| - **Usage:** model and execution-provider activity, model and execution-provider download activity, and request outcomes. | ||
| - **Errors:** error information for reliability analysis. Error text is scrubbed of filesystem paths, URLs, and other free-form content before transmission. |
| return; | ||
| } | ||
|
|
||
| const bool regenerated_from_corruption = saw_corruption_before_mutex || status_ == TelemetryDeviceIdStatus::kCorrupted; |
| if(WIN32) | ||
| target_link_libraries(${TARGET} ${LINK_SCOPE} dbghelp bcrypt) | ||
| target_link_libraries(${TARGET} ${LINK_SCOPE} dbghelp bcrypt version) | ||
| # UWP builds have CMAKE_SYSTEM_NAME = "WindowsStore"; desktop = "Windows". | ||
| # WinHTTP is not available in UWP, so only define this on desktop Windows. | ||
| if(NOT CMAKE_SYSTEM_NAME STREQUAL "WindowsStore") |
Honor disable_telemetry by installing a no-op ITelemetry sink, so events are neither uploaded nor mirrored to local telemetry logs when the public contract says telemetry is disabled. Files changed: sdk_v2/cpp/src/manager.cc Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 297bc539-5f7f-4a70-9411-48e91a5bf532
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 83 out of 83 changed files in this pull request and generated 1 comment.
Comments suppressed due to low confidence (2)
sdk_v2/cpp/CMakeLists.txt:241
- These telemetry sources are compiled for every
WIN32target even though only the 1DS dependency is disabled forWindowsStore.device_id.ccandtelemetry_metadata.ccstill compile desktop-only APIs such asRegCreateKeyExA,GetFileVersionInfoA, andGlobalMemoryStatusEx, so UWP builds can fail or fail app certification. Gate/provide UWP implementations for the core telemetry sources as well as disabling 1DS.
src/service/audio_transcriptions_handler.cc
src/service/embeddings_handler.cc
src/service/chat_completions_handler.cc
src/service/models_handlers.cc
src/service/responses_handler.cc
src/service/web_service.cc
src/telemetry/telemetry.cc
src/telemetry/telemetry_action_tracker.cc
src/telemetry/device_id.cc
sdk_v2/cpp/src/ep_detection/ep_detector.cc:269
- On every successful combined
DownloadAndRegistercall this reports the download phase asSkipped, even when the bootstrapper actually downloaded a package. That makesDownloadStatus/DownloadTimeMsinaccurate for the main success path. The bootstrapper result needs to expose whether download occurred (and its timing/status), or this event should report only an aggregate phase that can be measured correctly.
tracker->RecordDownloadComplete(ActionStatus::kSkipped,
was_registered_before ? "Registered" : "Unknown");
tracker->RecordRegisterComplete(ActionStatus::kSuccess, "Registered");
| CatalogFetchInfo base_info; | ||
| base_info.endpoint = parsed.endpoint; | ||
| base_info.region = parsed.region; | ||
| base_info.format = parsed.format; |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 83 out of 83 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (1)
sdk_v2/cpp/src/telemetry/telemetry_metadata.cc:85
neededincludes the terminating NUL because the input length is-1, butoutreserves onlyneeded - 1bytes while the conversion is allowed to writeneeded. On Windows this writes one byte past the string buffer whenever a host version is found. Allocate space for the terminator, then remove it after conversion.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 83 out of 83 changed files in this pull request and generated 1 comment.
Comments suppressed due to low confidence (4)
sdk_v2/cpp/src/telemetry/telemetry_metadata.cc:84
neededincludes the terminating NUL, butoutreserves onlyneeded - 1bytes whileWideCharToMultiByteis told it can writeneeded. On Windows this writes one byte past the string's size whenever an EXE version string is found. Allocateneededbytes;TrimVersionStringwill remove the trailing NUL.
sdk_v2/cpp/docs/Privacy.md:17- The “What is collected” disclosure is incomplete relative to the upload implementation:
ProcessInfosends the process name and locale, common context sends the configured app name, action events send the HTTP User-Agent, and audio events can send the request language. Please disclose these fields (or stop uploading them) so this privacy document accurately describes the telemetry payload.
- **Environment / device:** Foundry Local version, operating system, architecture, CPU details, and total memory, plus a device identifier. On Windows, Linux, and macOS the device identifier is a locally generated random UUID (**not** a hardware identifier such as a machine GUID); only a hashed form is transmitted, and it can be reset. On Android, Foundry Local uses the device identifier provided by the 1DS SDK instead of creating a separate Foundry-generated device id.
sdk_v2/cpp/CMakeLists.txt:311
- The newly compiled Windows device-ID implementation directly calls
OpenProcessToken,GetTokenInformation,RegGetValueA, andRegCreateKeyExA, all of which requireAdvapi32.lib. It is compiled even whenFOUNDRY_LOCAL_USE_TELEMETRY=OFF, so a no-telemetry Windows build cannot rely on the 1DS target to supply that library and will fail with unresolved externals.
target_link_libraries(${TARGET} ${LINK_SCOPE} dbghelp bcrypt version)
sdk_v2/cpp/CMakeLists.txt:52
- Turning off the 1DS transport is not sufficient to keep UWP buildable:
device_id.ccandtelemetry_metadata.ccare still compiled unconditionally and their_WIN32branches use desktop-only registry/token/version APIs (RegGetValueA,OpenProcessToken,GetFileVersionInfoA). Add a WindowsStore-safe implementation or exclude those helpers and their Manager startup calls for UWP; otherwise the explicitly supported UWP configuration fails before the transport setting matters.
if(CMAKE_SYSTEM_NAME STREQUAL "WindowsStore")
set(FOUNDRY_LOCAL_USE_TELEMETRY OFF CACHE BOOL "1DS telemetry is not available for UWP" FORCE)
endif()
| return HexEncode(digest, sizeof(digest)); | ||
| } | ||
|
|
||
| std::string Sha256String(std::string_view value) { |
| // Copyright (c) Microsoft Corporation. All rights reserved. | ||
| // Licensed under the MIT License. | ||
|
|
||
| #include "http/HttpClient_Android.hpp" |
|
|
||
| ## Disabling Telemetry | ||
|
|
||
| Telemetry is opt-out through the SDK configuration: set the `disable_telemetry` option to `true` before creating the manager, and the SDK collects and uploads nothing. In the C++ SDK, this is `Configuration::SetDisableTelemetry(true)`. |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 83 out of 83 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (3)
sdk_v2/cpp/src/telemetry/telemetry_metadata.cc:84
neededincludes the terminating NUL, butouthas onlyneeded - 1writable characters while the conversion is told it may writeneeded. This writes past the string's size on every successful Windows version lookup. Allocateneeded, then remove the terminator after conversion.
sdk_v2/cpp/include/foundry_local/foundry_local_c.h:934- Appending this function to the version-1 table without incrementing
FOUNDRY_LOCAL_API_VERSIONdefeats the ABI version check. The updated C#/Python bindings still request v1, so when they load an older v1 native library they marshal/read this new slot past the old table and may call an arbitrary pointer instead of getting a clean version-mismatch failure. Introduce API v2 (and update each binding's requested version), while retaining the v1 table for older consumers.
/// Optional. Disable all telemetry. When true, the SDK collects and uploads no telemetry (no 1DS
/// uploader is created and no device identifier is written). Defaults to false (telemetry enabled).
FL_API_STATUS(SetDisableTelemetry, _In_ flConfiguration* config, bool disable);
sdk_v2/cpp/src/util/sha256.cc:87
- The only new assertion for this path checks the
c:prefix and output length, so both platform implementations could return an incorrect 64-character digest undetected. AddSha256Stringknown-vector tests (including"abc"and the empty string), matching the existingSha256Filevectors insha256_test.cc.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 83 out of 83 changed files in this pull request and generated 3 comments.
Comments suppressed due to low confidence (4)
sdk_v2/cpp/CMakeLists.txt:311
- The new Windows device-ID implementation calls
OpenProcessToken,RegGetValueA, andRegCreateKeyExA, all of which require Advapi32.lib. This target does not link it, so Windows builds—especially the newly supported--no_telemetryconfiguration where MSTelemetry cannot supply a transitive dependency—fail with unresolved externals.
target_link_libraries(${TARGET} ${LINK_SCOPE} dbghelp bcrypt version)
sdk_v2/cpp/CMakeLists.txt:52
- Turning off 1DS is not sufficient to keep the WindowsStore build valid.
device_id.ccandtelemetry_metadata.ccare still compiled unconditionally and their_WIN32branches call desktop-only registry and file-version APIs (RegGetValueA/RegCreateKeyExAandGetFileVersionInfoA). The UWP configuration therefore still compiles/links unsupported APIs; add WindowsStore-safe implementations or exclude these startup metadata paths for UWP.
if(CMAKE_SYSTEM_NAME STREQUAL "WindowsStore")
set(FOUNDRY_LOCAL_USE_TELEMETRY OFF CACHE BOOL "1DS telemetry is not available for UWP" FORCE)
endif()
sdk_v2/cpp/src/ep_detection/ep_detector.cc:269
RecordDownloadCompleteis called only after the combinedDownloadAndRegisteroperation has finished. Because that method measures elapsed time sinceRecordInitialState, the full operation is reported as a skipped download, while the immediately following successful register phase is reported as approximately 0 ms. Move the skipped download transition before invoking the combined bootstrapper so its elapsed time is attributed to registration.
tracker->RecordDownloadComplete(ActionStatus::kSkipped,
was_registered_before ? "Registered" : "Unknown");
tracker->RecordRegisterComplete(ActionStatus::kSuccess, "Registered");
sdk_v2/cpp/src/ep_detection/ep_detector.cc:281
- This failure path has the same phase-timing inversion: despite the comment saying the combined operation is recorded as registration, calling
RecordDownloadCompleteafter it returns puts all elapsed time indownload_duration_mswith statusSkipped, then records a near-zero failed registration. Advance to the register stage before calling the bootstrapper.
// Record the combined operation as the register phase rather than fabricating a download/register split.
tracker->RecordDownloadComplete(ActionStatus::kSkipped,
was_registered_before ? "Registered" : "Unknown");
tracker->RecordRegisterComplete(ActionStatus::kFailure,
was_registered_before ? "Registered" : "Unknown");
| flStatusPtr (*AddWebServiceEndpoint)(flConfiguration* config, const char* url); | ||
| flStatusPtr (*SetExternalServiceUrl)(flConfiguration* config, const char* url); | ||
| flStatusPtr (*SetAdditionalOptions)(flConfiguration* config, const flKeyValuePairs* options); | ||
| flStatusPtr (*SetDisableTelemetry)(flConfiguration* config, bool disable); |
|
|
||
| Telemetry is limited to a small set of trace events emitted over the SDK's lifecycle: | ||
|
|
||
| - **Environment / device:** Foundry Local version, operating system, architecture, CPU details, and total memory, plus a device identifier. On Windows, Linux, and macOS the device identifier is a locally generated random UUID (**not** a hardware identifier such as a machine GUID); only a hashed form is transmitted, and it can be reset. On Android, Foundry Local uses the device identifier provided by the 1DS SDK instead of creating a separate Foundry-generated device id. |
| usage.correlation_id = context.correlation_id; | ||
| usage.indirect = context.indirect; | ||
| usage.stream = streaming; | ||
| usage.num_messages = CountRequestMessages(request); |
Allocate space for the WideCharToMultiByte terminator when converting Windows version-resource strings, matching the ONNX Runtime fix and avoiding writing past the std::string size. Files changed: sdk_v2/cpp/src/telemetry/telemetry_metadata.cc Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 297bc539-5f7f-4a70-9411-48e91a5bf532
Port the ONNX Runtime GenAI telemetry lifetime decision from the global LOGMANAGER_INSTANCE singleton to a dedicated LogManagerProvider-owned instance. The 1DS configuration now outlives the provider, teardown releases the provider explicitly, and a shared lifecycle lock prevents concurrent event emission from racing destruction. Files changed: sdk_v2/cpp/src/telemetry/one_ds_telemetry.cc, sdk_v2/cpp/src/telemetry/one_ds_telemetry.h Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 297bc539-5f7f-4a70-9411-48e91a5bf532
Set ORT_TELEMETRY_DISABLED=1 at Azure and GitHub CI entry points so every CI job uses the same runtime telemetry opt-out variable across Foundry, ORT, and GenAI components. Files changed: .pipelines/foundry-local-packaging.yml, .github/workflows/samples-integration-test.yml Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 297bc539-5f7f-4a70-9411-48e91a5bf532
When Configuration.disable_telemetry is true, call OrtApi::DisableTelemetryEvents on the shared OrtEnv so ORT telemetry is suppressed without mutating process-wide environment variables. Leave the exact future GenAI hook, OgaSetTelemetryEnabled(false), as a TODO because the currently pinned GenAI headers do not expose it yet. Files changed: sdk_v2/cpp/src/manager.cc Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 297bc539-5f7f-4a70-9411-48e91a5bf532
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 85 out of 85 changed files in this pull request and generated 1 comment.
Comments suppressed due to low confidence (2)
sdk_v2/python/src/foundry_local_sdk/_native/build_cffi.py:477
- cffi’s
cdefparser does not accept the Cboolspelling (the file’s preprocessing contract at line 46 explicitly requires_Bool). This new vtable member therefore prevents_cffi_bindingsfrom being generated; use_Boolto match the other boolean ABI declarations.
sdk_v2/cpp/src/telemetry/one_ds_telemetry.cc:218 - This flag is set too late: if
GetLoggerreturns null or throws, the successfully created provider is never torn down/released (the null path drops anImplcontaining only a raw manager pointer, and the catch sees this flag as false). Mark initialization immediately afterCreateLogManagersucceeds and release the provider on the null-logger path.
| // RAII telemetry tracker — emits a "Download" event on destruction with whatever | ||
| // fields have been populated. Default status is kFailure so abrupt exits (exceptions) | ||
| // are recorded as failures; the happy path explicitly sets kSuccess / kSkipped. | ||
| std::unique_ptr<DownloadTracker> tracker; |
Summary
Notes