Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
b4b65b8
Add SDK v2 telemetry integration
bmehta001 Jul 24, 2026
afe84ca
Simplify session manager cache shutdown
bmehta001 Jul 24, 2026
4779a20
Coarsen catalog failure telemetry text
bmehta001 Jul 24, 2026
daee874
Stop allowlisting audio telemetry language
bmehta001 Jul 24, 2026
6da21ee
Restore detailed catalog local diagnostics
bmehta001 Jul 24, 2026
b6aa776
Restore catalog refresh local error detail
bmehta001 Jul 24, 2026
12ea691
Minimize 1DS telemetry context fields
bmehta001 Jul 25, 2026
85afc61
Keep explicit ProcessInfo identity fields
bmehta001 Jul 25, 2026
150d0d4
Keep 1DS network context for telemetry events
bmehta001 Jul 25, 2026
c4d02d5
Own web service URL snapshots in the C API
bmehta001 Jul 26, 2026
323ffac
Avoid external SQLite in telemetry builds
bmehta001 Jul 26, 2026
773abcf
Initialize C API URL storage
bmehta001 Jul 26, 2026
7fdb01f
Initialize streaming audio telemetry language
bmehta001 Jul 26, 2026
0f56939
Harden JS settings validation and CI model setup
bmehta001 Jul 26, 2026
8fc84d9
Scope CI model-selection skips to embeddings
bmehta001 Jul 26, 2026
3fee74a
Add Foundry Local Grafana telemetry dashboard
bmehta001 Jul 28, 2026
948c25f
Match dashboard to supported Grafana version
bmehta001 Jul 28, 2026
7fc8461
Honor the upstream telemetry opt-out variable
bmehta001 Jul 28, 2026
926feb7
Keep telemetry suppression config-only
bmehta001 Jul 28, 2026
c98b327
Use the Android-native 1DS HTTP transport
bmehta001 Jul 30, 2026
672bbb1
Close remaining OGA telemetry parity gaps
bmehta001 Jul 30, 2026
3e9900e
Preserve the shared telemetry device ID
bmehta001 Jul 30, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/samples-integration-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ on:
permissions:
contents: read

env:
ORT_TELEMETRY_DISABLED: '1'

jobs:
# ── Python Samples ──────────────────────────────────────────────────
python-samples:
Expand Down
3 changes: 3 additions & 0 deletions .pipelines/foundry-local-packaging.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ parameters:

variables:
- group: FoundryLocal-ESRP-Signing
# Keep all CI jobs telemetry-free through the shared ORT/1DS runtime opt-out.
- name: ORT_TELEMETRY_DISABLED
value: '1'
# C++ SDK (sdk_v2/cpp) native dependency versions. Must match cmake defaults
# in sdk_v2/deps_versions.json.
- name: cppOrtVersion
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ Foundry Local is an **end-to-end local AI solution** for building applications t

User data never leaves the device, responses start immediately with zero network latency, and your app works offline. No per-token costs, no API keys, no backend infrastructure to maintain, and no Azure subscription required.

Foundry Local may collect usage data and send it to Microsoft to help improve our products and services. See the [privacy statement](sdk_v2/cpp/docs/Privacy.md) for more details.

### Key Features

- **Lightweight runtime** — The runtime handles model acquisition, hardware acceleration, model management, and inference (via [ONNX Runtime](https://onnxruntime.ai/)).
Expand Down
67 changes: 66 additions & 1 deletion sdk_v2/cpp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ endif()
if(NOT DEFINED FOUNDRY_LOCAL_BUILD_SERVICE OR FOUNDRY_LOCAL_BUILD_SERVICE)
list(APPEND VCPKG_MANIFEST_FEATURES "service")
endif()
# Telemetry must be selected before project() so vcpkg resolves the feature. Foundry Local Core always builds with
# telemetry; platforms that cannot link the 1DS transport are unsupported for this target.
if(CMAKE_SYSTEM_NAME STREQUAL "WindowsStore" OR VCPKG_TARGET_TRIPLET MATCHES "uwp")
message(FATAL_ERROR "Foundry Local Core always builds with telemetry; UWP/WindowsStore is not supported.")
endif()
list(APPEND VCPKG_MANIFEST_FEATURES "telemetry")

project(foundry_local VERSION 0.1.0 LANGUAGES CXX C)

Expand Down Expand Up @@ -45,6 +51,30 @@ option(FOUNDRY_LOCAL_BUILD_EXAMPLES "Build example programs" ON)
option(FOUNDRY_LOCAL_BUILD_SERVICE "Build web service support (requires oat++)" ON)
option(FOUNDRY_LOCAL_ENABLE_ASAN "Enable AddressSanitizer + UndefinedBehaviorSanitizer (Linux only)" OFF)

# Optional 1DS ingestion token override. Override only via environment so it does
# not appear in CMake cache files.
if(DEFINED CACHE{FOUNDRY_LOCAL_TELEMETRY_TOKEN}
AND NOT "$CACHE{FOUNDRY_LOCAL_TELEMETRY_TOKEN}" STREQUAL "")
message(FATAL_ERROR
"Do not pass FOUNDRY_LOCAL_TELEMETRY_TOKEN via -D or CMake cache. "
"Use the FOUNDRY_LOCAL_TELEMETRY_TOKEN environment variable for temporary test-tenant overrides.")
endif()
unset(FOUNDRY_LOCAL_TELEMETRY_TOKEN CACHE)

set(FOUNDRY_LOCAL_TELEMETRY_TOKEN "")
if(DEFINED ENV{FOUNDRY_LOCAL_TELEMETRY_TOKEN})
set(FOUNDRY_LOCAL_TELEMETRY_TOKEN "$ENV{FOUNDRY_LOCAL_TELEMETRY_TOKEN}")
endif()
if(FOUNDRY_LOCAL_TELEMETRY_TOKEN MATCHES "^\\$\\(")
set(FOUNDRY_LOCAL_TELEMETRY_TOKEN "")
endif()
if(FOUNDRY_LOCAL_TELEMETRY_TOKEN)
set(FOUNDRY_LOCAL_TELEMETRY_TOKEN_DEFINE
"#define FOUNDRY_LOCAL_TELEMETRY_TOKEN \"${FOUNDRY_LOCAL_TELEMETRY_TOKEN}\"")
else()
set(FOUNDRY_LOCAL_TELEMETRY_TOKEN_DEFINE "")
endif()

# Android: interactive examples and host tools don't run on device
if(ANDROID)
set(FOUNDRY_LOCAL_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)
Expand Down Expand Up @@ -87,6 +117,13 @@ if(WIN32)
find_package(WinMLEpCatalog)
endif()

# 1DS C++ client telemetry — provided by the cpp-client-telemetry vcpkg port.
find_package(MSTelemetry CONFIG REQUIRED)
if(NOT WIN32)
find_package(OpenSSL REQUIRED)
endif()
message(STATUS "1DS telemetry: enabled (cpp-client-telemetry found)")

# --------------------------------------------------------------------------
# Library target
# --------------------------------------------------------------------------
Expand Down Expand Up @@ -196,7 +233,13 @@ set(FOUNDRY_LOCAL_SOURCES
src/service/web_service.cc
src/telemetry/telemetry.cc
src/telemetry/telemetry_action_tracker.cc
src/telemetry/device_id.cc
src/telemetry/invocation_context.cc
src/telemetry/telemetry_environment.cc
src/telemetry/telemetry_logger.cc
src/telemetry/telemetry_metadata.cc
src/telemetry/ep_download_tracker.cc
src/telemetry/download_tracker.cc
src/utils.cc
src/util/file_lock.cc
src/http/http_download.cc
Expand All @@ -208,6 +251,12 @@ set(FOUNDRY_LOCAL_SOURCES
${FOUNDRY_LOCAL_INTERNAL_HEADERS}
)

# 1DS bridge — always compiled for Foundry Local Core.
list(APPEND FOUNDRY_LOCAL_SOURCES src/telemetry/one_ds_telemetry.cc)
if(ANDROID)
list(APPEND FOUNDRY_LOCAL_SOURCES src/telemetry/android_telemetry_bridge.cc)
endif()

# Organize headers into filters matching the directory structure in Visual Studio
source_group(TREE "${CMAKE_CURRENT_SOURCE_DIR}" PREFIX "Source" FILES ${FOUNDRY_LOCAL_SOURCES})
source_group(TREE "${CMAKE_CURRENT_SOURCE_DIR}/include" PREFIX "Public Headers" FILES ${FOUNDRY_LOCAL_PUBLIC_HEADERS})
Expand Down Expand Up @@ -250,12 +299,18 @@ function(foundry_local_configure_target TARGET LINK_SCOPE)
endif()

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")
Comment on lines 301 to 305
target_compile_definitions(${TARGET} PRIVATE FOUNDRY_LOCAL_USE_WINHTTP_TRANSPORT=1)
endif()
else()
target_link_libraries(${TARGET} ${LINK_SCOPE} OpenSSL::Crypto)
endif()

if(APPLE)
target_link_libraries(${TARGET} ${LINK_SCOPE} "-framework CoreFoundation")
endif()

if(ANDROID)
Expand All @@ -273,6 +328,9 @@ function(foundry_local_configure_target TARGET LINK_SCOPE)
else()
target_compile_definitions(${TARGET} ${LINK_SCOPE} FOUNDRY_LOCAL_HAS_EP_CATALOG=0)
endif()

target_link_libraries(${TARGET} ${LINK_SCOPE} MSTelemetry::mat)

endfunction()

# --------------------------------------------------------------------------
Expand All @@ -291,6 +349,13 @@ configure_file(
@ONLY
)

# Generate the 1DS tenant-token header.
configure_file(
"${CMAKE_CURRENT_SOURCE_DIR}/src/telemetry/one_ds_tenant_token.h.in"
"${CMAKE_CURRENT_BINARY_DIR}/generated/one_ds_tenant_token.h"
@ONLY
)

# --------------------------------------------------------------------------
# Object library — compiles all sources once. Both the shared (DLL) and
# static library targets re-use these object files, avoiding a double build.
Expand Down
13 changes: 10 additions & 3 deletions sdk_v2/cpp/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,6 @@ class HelpFormatter(argparse.ArgumentDefaultsHelpFormatter, argparse.RawDescript
help="Override the Microsoft.Windows.AI.MachineLearning NuGet version for the WinML EP "
"catalog (Windows only). Defaults to the version pinned in deps_versions.json.",
)

# Cross-compilation (mutually exclusive targets)
cross_group = parser.add_mutually_exclusive_group()
cross_group.add_argument(
Expand Down Expand Up @@ -439,6 +438,10 @@ def configure(args: argparse.Namespace) -> None:
if triplets_dir.is_dir():
command += [f"-DVCPKG_OVERLAY_TRIPLETS={triplets_dir}"]

ports_dir = SCRIPT_DIR / "ports"
if ports_dir.is_dir():
command += [f"-DVCPKG_OVERLAY_PORTS={ports_dir}"]

# Project options
build_tests = "ON"

Expand All @@ -451,9 +454,13 @@ def configure(args: argparse.Namespace) -> None:
f"-DFOUNDRY_LOCAL_BUILD_SERVICE={build_service}",
]

# Enable vcpkg manifest features for tests
# Enable vcpkg manifest features as needed. Multiple features are passed as a
# semicolon-separated list in a single -D flag.
manifest_features = []
if build_tests == "ON":
command += ["-DVCPKG_MANIFEST_FEATURES=tests"]
manifest_features.append("tests")
if manifest_features:
command += [f"-DVCPKG_MANIFEST_FEATURES={';'.join(manifest_features)}"]

# WinML EP catalog is enabled automatically on Windows by CMake. Allow an
# optional version override for the Microsoft.Windows.AI.MachineLearning NuGet.
Expand Down
23 changes: 16 additions & 7 deletions sdk_v2/cpp/docs/AndroidBuildPlan.md
Original file line number Diff line number Diff line change
Expand Up @@ -190,9 +190,16 @@ When `--android_run_emulator --test` is specified, `build.py`:

## SSL/Certificate Handling

### Transport split

- **Azure Core/Storage** uses native libcurl with OpenSSL and needs a PEM CA bundle through `SSL_CERT_FILE`.
- **1DS telemetry** uses `HttpClient_Android` through JNI and Java `HttpURLConnection`, which uses Android's Java trust
store directly. It does not use `SSL_CERT_FILE`.

### Problem

Statically-linked OpenSSL (built by vcpkg) **ignores the `SSL_CERT_DIR` environment variable** at
For the native Azure Core/Storage transport, statically-linked OpenSSL (built by vcpkg) **ignores the
`SSL_CERT_DIR` environment variable** at
runtime. The `--openssldir` path is baked at build time to a non-existent location on Android.
`SSL_CERT_FILE` with a single concatenated PEM bundle *is* honored.

Expand All @@ -214,15 +221,17 @@ all root CAs that the device trusts (including DigiCert Global Root G2 needed fo

### Production (with Java Bindings — Future)

The Java/Android host app will export system certificates (including user-installed CAs and
enterprise roots) to a PEM file and set `SSL_CERT_FILE` before loading the native library. This is
the same pattern FL Core used.
The Java/Android host app will export system certificates (including user-installed CAs and enterprise roots) to a
PEM file and set `SSL_CERT_FILE` before loading the native library for Azure Core/Storage. It must also initialize the
1DS Java `HttpClient` before creating a Foundry Local manager, but that telemetry transport uses the Java trust store
rather than the exported PEM file.

### Key Insight

`SSL_CERT_DIR` does **not** work with statically-linked OpenSSL on Android. Always use `SSL_CERT_FILE`
with a concatenated PEM bundle. The error message when this fails is misleading: "self-signed
certificate in certificate chain" — it actually means OpenSSL cannot find **any** CA store.
`SSL_CERT_DIR` does **not** work with statically-linked OpenSSL on Android. Native libcurl/OpenSSL consumers must use
`SSL_CERT_FILE` with a concatenated PEM bundle. The error message when this fails is misleading: "self-signed
certificate in certificate chain" — it actually means OpenSSL cannot find **any** CA store. This does not apply to the
1DS Java HTTP transport.

---

Expand Down
24 changes: 24 additions & 0 deletions sdk_v2/cpp/docs/Privacy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Privacy

## Data Collection

The software may collect information about you and your use of the software and send it to Microsoft. Microsoft may use this information to provide services and improve our products and services. You may disable non-essential telemetry as described below. There are also some features in the software that may enable you and Microsoft to collect data from users of your applications. If you use these features, you must comply with applicable law, including providing appropriate notices to users of your applications together with a copy of Microsoft's privacy statement. Our privacy statement is located at https://go.microsoft.com/fwlink/?LinkID=824704. You can learn more about data collection and use in the help documentation and our privacy statement. Your use of the software operates as your consent to these practices.

***

Foundry Local collects a small number of trace events with the goal of improving product quality. Official packages on supported platforms include the cross-platform 1DS telemetry SDK. Collection is subject to user consent and handled following Microsoft's privacy practices.

Telemetry is turned **ON** by default.

#### Technical Details

Foundry Local uses the cross-platform 1DS SDK (cpp_client_telemetry) to send trace events to Microsoft's telemetry backend over HTTPS. Based on user consent, this data is handled following GDPR and privacy regulations for anonymity and data access controls.

Non-essential telemetry can be disabled as follows. Foundry Local may still send a minimal ProcessInfo event.

- **Disable via manager config.** Set the disable-nonessential-telemetry option before creating the manager:
- C++: `Configuration::SetDisableNonessentialTelemetry(true)`
- C#: `Configuration.DisableNonessentialTelemetry = true`
- JavaScript/TypeScript: `disableNonessentialTelemetry: true`
- Python: `disable_nonessential_telemetry=True`
- Native additional option: `DisableNonessentialTelemetry=true`
53 changes: 53 additions & 0 deletions sdk_v2/cpp/docs/telemetry/grafana/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# Foundry Local Grafana dashboard

`foundry-local-telemetry-dashboard.json` is an importable Grafana dashboard for Foundry Local SDK v2 client
telemetry in Aria.

## Import

1. Install the Grafana Azure Data Explorer datasource plugin
(`grafana-azure-data-explorer-datasource`) version `7.2.8`. The dashboard targets Grafana `11.6.11`; newer
Grafana versions must also satisfy the plugin's compatibility requirements.
2. Configure a datasource that can query:
- Cluster: `https://kusto.aria.microsoft.com`
- Database: `9d5ddaec61e24567b788a20aea324631`
3. In Grafana, select **Dashboards > New > Import**, upload
`foundry-local-telemetry-dashboard.json`, and map **Aria Azure Data Explorer** to that datasource.

The dashboard defaults to UTC, the last seven days, and a five-minute refresh. Aria retention is approximately
12–14 days. Every query requires a populated `FoundryLocalVersion`, excluding legacy/unversioned telemetry from this
SDK v2 dashboard.

## Filters

All dashboard filters are time-aware and multi-select:

- App
- OS
- Foundry Local version
- User agent
- Action
- Status
- Model
- Execution provider

The filters use the ADX plugin's `$__contains` macro. Their **All** value must remain exactly `all`.

## Privacy

The dashboard does not project device identifiers, client IP addresses, or user identity fields. Device IDs are used
only inside an aggregate `count_distinct` calculation. Recent-error panels show the telemetry error text already
subject to Foundry Local's upload redaction rules.

## Regenerate

The JSON is generated from `generate-dashboard.py`:

```powershell
python sdk_v2\cpp\docs\telemetry\grafana\generate-dashboard.py
```

The queries were authored against the live Aria schemas for:

`action`, `audiomodel`, `catalogfetch`, `download`, `epdownloadandregister`, `epdownloadattempt`, `error`,
`hardwareinfo`, `model`, `modelid`, `processinfo`, and `session`.
Loading
Loading