Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 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
f31867a
Remove Grafana dashboard from telemetry core
bmehta001 Aug 3, 2026
e51e25d
Harden telemetry and OGA process teardown
bmehta001 Aug 3, 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
5 changes: 4 additions & 1 deletion .pipelines/foundry-local-packaging.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,15 @@ 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
value: '1.26.0'
- name: cppGenaiVersion
value: '0.14.1'
value: '0.15.1'
- name: cppWinmlVersion
value: '2.1.70'
- name: cppBuildConfig
Expand Down
2 changes: 1 addition & 1 deletion .pipelines/v2/sdk_v2-pipeline-plan.md
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,7 @@ purposes:
Versions are pipeline-level variables, currently:

* `ortVersion` `1.26.0` (`Microsoft.ML.OnnxRuntime.Foundry`)
* `genaiVersion` `0.14.1` (`Microsoft.ML.OnnxRuntimeGenAI.Foundry`)
* `genaiVersion` `0.15.1` (`Microsoft.ML.OnnxRuntimeGenAI.Foundry`)
* `winmlVersion` `2.1.70` (`Microsoft.Windows.AI.MachineLearning`, WinML 2.x reg-free)

These must be kept in sync with the cmake defaults and with
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`
16 changes: 6 additions & 10 deletions sdk_v2/cpp/include/foundry_local/foundry_local_c.h
Original file line number Diff line number Diff line change
Expand Up @@ -362,13 +362,11 @@ typedef struct flUsage {
} flUsage;

/// Information about a discoverable execution provider.
/// Returned by Manager_GetDiscoverableEps. Storage is owned by the Manager; the
/// returned pointers and `name` strings are stable for the Manager's lifetime.
/// `is_registered` may be updated by a concurrent Manager_DownloadAndRegisterEps;
/// readers see a recent snapshot.
/// Returned by Manager_GetDiscoverableEps as a snapshot. Storage is owned by the implementation
/// and remains valid until Manager_GetDiscoverableEps is next called on the same thread.
typedef struct flEpInfo {
uint32_t version; ///< Set by impl to FOUNDRY_LOCAL_API_VERSION.
const char* name; ///< UTF-8 EP name. Stable for Manager lifetime.
const char* name; ///< UTF-8 EP name. Stable for the snapshot lifetime.
bool is_registered; ///< Whether the EP is currently registered with ORT.
/* V2 fields go here. */
} flEpInfo;
Expand Down Expand Up @@ -671,11 +669,9 @@ typedef struct flApi {

/* EP detection */

/// Get discoverable execution providers. Returns a pointer to an internal
/// array of versioned flEpInfo structs. The array, the structs, and the
/// `name` strings are owned by the Manager and remain valid for its lifetime.
/// `is_registered` values reflect a recent snapshot; concurrent calls to
/// Manager_DownloadAndRegisterEps may update them in place.
/// Get discoverable execution providers. Returns a pointer to a snapshot array
/// of versioned flEpInfo structs. The array, structs, and `name` strings remain
/// valid until Manager_GetDiscoverableEps is next called on the same thread.
FL_API_STATUS(Manager_GetDiscoverableEps, _In_ const flManager* manager,
_Outptr_result_buffer_(*out_count) const flEpInfo** out_eps,
_Out_ size_t* out_count);
Expand Down
4 changes: 4 additions & 0 deletions sdk_v2/cpp/include/foundry_local/foundry_local_cpp.h
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,10 @@ class Configuration {
/// Defaults to "centralus" when not set.
Configuration& SetCatalogRegion(const std::string& region);

/// Optional. Disable non-essential telemetry. Foundry Local may still send a minimal ProcessInfo event.
/// Defaults to false (telemetry enabled).
Configuration& SetDisableNonessentialTelemetry(bool disable);

const flConfiguration* native_handle() const noexcept { return handle_.get(); }

private:
Expand Down
6 changes: 6 additions & 0 deletions sdk_v2/cpp/include/foundry_local/foundry_local_cpp.inline.h
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,12 @@ inline Configuration& Configuration::SetCatalogRegion(const std::string& region)
return *this;
}

inline Configuration& Configuration::SetDisableNonessentialTelemetry(bool disable) {
KeyValuePairs options;
options.Set("DisableNonessentialTelemetry", disable ? "true" : "false");
return SetAdditionalOptions(options);
}

inline flConfiguration* detail::CreateConfiguration(const std::string& app_name) {
flConfiguration* config = nullptr;
Check(detail::config_api()->Create(app_name.c_str(), &config));
Expand Down
39 changes: 39 additions & 0 deletions sdk_v2/cpp/ports/cpp-client-telemetry/android-java-http.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 0f984a2..57f8eb0 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -381,7 +381,7 @@
set(MATSDK_NEEDS_CURL OFF)
if(PAL_IMPLEMENTATION STREQUAL "CPP11"
AND NOT BUILD_IOS
- AND (NOT CMAKE_SYSTEM_NAME STREQUAL "Android" OR MATSDK_USE_VCPKG_DEPS)
+ AND NOT CMAKE_SYSTEM_NAME STREQUAL "Android"
AND NOT BUILD_APPLE_HTTP)
set(MATSDK_NEEDS_CURL ON)
add_definitions(-DHAVE_MAT_CURL_HTTP_CLIENT)
diff --git a/cmake/MSTelemetryConfig.cmake.in b/cmake/MSTelemetryConfig.cmake.in
index e54cac2..84820bf 100644
--- a/cmake/MSTelemetryConfig.cmake.in
+++ b/cmake/MSTelemetryConfig.cmake.in
@@ -14,7 +14,7 @@
find_dependency(nlohmann_json CONFIG)

# Curl is re-found only when the SDK was built with the curl HTTP client
-# (Linux, Android via vcpkg, and macOS built without Apple HTTP).
+# (Linux and macOS built without Apple HTTP).
# Windows (WinInet), iOS, and macOS-with-Apple-HTTP do not link curl.
# We bake the build-time decision into a boolean rather than re-deriving it,
# because the macOS BUILD_APPLE_HTTP choice can't be inferred from
diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt
index 6d1b32d..95566d5 100644
--- a/lib/CMakeLists.txt
+++ b/lib/CMakeLists.txt
@@ -197,7 +197,7 @@
list(APPEND SRCS
pal/posix/NetworkInformationImpl_Android.cpp
)
- if(MATSDK_USE_VCPKG_DEPS)
+ if(MATSDK_NEEDS_CURL)
list(APPEND SRCS
http/HttpClient_Curl.cpp
http/HttpClient_Curl.hpp
Loading