Skip to content

Expose telemetry through Rust SDK, C ABI, and .NET binding - #821

Open
RamonArjona4 wants to merge 60 commits into
mainfrom
user/ramonarjona4/telemetry-04-rust-sdk-ffi
Open

Expose telemetry through Rust SDK, C ABI, and .NET binding#821
RamonArjona4 wants to merge 60 commits into
mainfrom
user/ramonarjona4/telemetry-04-rust-sdk-ffi

Conversation

@RamonArjona4

@RamonArjona4RamonArjona4 commented Aug 12, 2026

Copy link
Copy Markdown
Member

Summary

Exposes stable telemetry consent and policy through the public Rust SDK, panic-safe C ABI, and managed .NET binding. Adds typed presenter/status/withdrawal APIs, native binding entry points, streaming and state-aware propagation, and binding-codegen coverage.

This is PR 4 of 5 and depends on the stable runtime integration in PR 3.

Stack

OrderChangePR
1Normative privacy and telemetry documentation#818
2Consent and policy foundation#819
3Stable config and executor integration#820
4Rust SDK, C ABI, and .NET binding#821
5Node.js and .NET SDK refinements#822

Review only this PR's diff; prerequisite behavior is in the PR above.

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
There may be pipelines that require an authorized user to comment /azp run to run.

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
There may be pipelines that require an authorized user to comment /azp run to run.

Comment threadsrc/core/mxc-sdk/README.md Outdated
Comment threadsrc/core/mxc-sdk/README.md Outdated
Comment threadsrc/core/mxc-sdk/src/telemetry.rs Outdated
Comment threadsrc/core/mxc-sdk/src/telemetry.rs
Comment threadsrc/ffi/mxc_ffi/src/streaming.rs Outdated

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:shipit:

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Exposes telemetry consent, policy, and per-run enablement through the Rust SDK and C ABI.

Changes:

  • Adds typed Rust telemetry APIs.
  • Adds panic-safe C ABI consent and policy entry points.
  • Propagates telemetry settings and expands tests/codegen checks.

Reviewed changes

Copilot reviewed 7 out of 8 changed files in this pull request and generated 2 comments.

Show a summary per file
FileDescription
src/ffi/mxc_ffi/src/streaming.rsPropagates telemetry into streaming requests.
src/ffi/mxc_ffi/src/lib.rsAdds telemetry ABI and tests.
src/ffi/mxc_ffi/Cargo.tomlAdds telemetry test support.
src/core/mxc-sdk/src/telemetry.rsImplements the Rust telemetry facade.
src/core/mxc-sdk/src/lib.rsExports the telemetry module.
src/core/mxc-sdk/README.mdDocuments telemetry APIs and usage.
src/Cargo.lockRecords the test dependency.
scripts/check-dotnet-bindings-codegen.jsVerifies generated telemetry entry points.
Suppressed comments (1)

src/ffi/mxc_ffi/src/lib.rs:622

  • This new ABI entry point manually constructs a stable JSON contract, but no FFI-level test invokes it. Add a test that asserts every returned field (including reason: null where applicable), checks the platform-specific values, and frees the returned string; otherwise field omissions or ownership regressions can pass unnoticed.
pub unsafe extern "C" fn mxc_telemetry_get_consent_status(out_utf8: *mut *mut c_char) -> i32 {

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment threadsrc/ffi/mxc_ffi/src/lib.rs Outdated
Comment threadsrc/ffi/mxc_ffi/src/lib.rs
CopilotAI review requested due to automatic review settings August 13, 2026 05:43

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 7 out of 8 changed files in this pull request and generated no new comments.

Suppressed comments (3)

src/core/mxc-sdk/src/telemetry.rs:342

  • This accessor returns inner_consent::get_status().effective_state, not the recorded state. For example, a legacy stored grant is returned as Undetermined; calling it “recorded” obscures the stored/effective distinction and can mislead SDK consumers. Point callers needing the persisted value to get_consent_status.
/// Return the user's recorded consent decision.

src/ffi/mxc_ffi/src/lib.rs:439

  • The export marshals the effective state returned by get_consent(), not necessarily the persisted state. A version-invalid stored grant is reported as "undetermined", so describing this as persisted gives C callers the wrong contract; mxc_telemetry_get_consent_status is the API that exposes both values.
/// Read the persisted telemetry consent state.

src/ffi/mxc_ffi/src/lib.rs:627

  • This is the only new telemetry export with no FFI-level test, so the JSON field names/values, allocation ownership, and null-output status can regress without this crate detecting it. Add a test using the isolated telemetry environment that calls this export, parses and frees the JSON, asserts storedState, effectiveState, reason, and policy, and covers a null out pointer.
pub unsafe extern "C" fn mxc_telemetry_get_consent_status(out_utf8: *mut *mut c_char) -> i32 {

Comment threadsrc/core/mxc-sdk/src/telemetry.rs Outdated
Comment threadsrc/ffi/mxc_ffi/src/lib.rs
Comment threadsrc/ffi/mxc_ffi/src/lib.rs
Comment threadsrc/core/mxc-sdk/src/telemetry.rs
Comment threadsrc/ffi/mxc_ffi/src/lib.rs
@RamonArjona4
RamonArjona4 requested review from a team and CopilotAugust 18, 2026 18:50
@RamonArjona4
RamonArjona4force-pushed the user/ramonarjona4/telemetry-04-rust-sdk-ffi branch from 1f67a37 to 0ca5177CompareAugust 18, 2026 18:50

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 15 out of 16 changed files in this pull request and generated no new comments.

Suppressed comments (5)

sdk/dotnet/Microsoft.Mxc.Sdk/MxcTelemetry.cs:275

  • A non-success native status is silently collapsed to false, and the catch below does the same for load/marshaling failures. Because false is also a legitimate answer, a broken native install becomes invisible to hosts that poll this getter. Keep the fail-closed return value, but report each distinct swallowed failure once through a non-throwing diagnostic path.
 int needsPrompt = 0;
var status = NativeMethods.mxc_telemetry_needs_consent_prompt(&needsPrompt);
return status == (int)ErrorCode.Success && needsPrompt != 0;

sdk/dotnet/Microsoft.Mxc.Sdk/MxcTelemetry.cs:302

  • This non-success path (and the catch below) returns the legitimate Blocked state without reporting why, so native ABI/load failures are indistinguishable from an administrator actually blocking telemetry. Preserve the fail-closed result, but emit a non-throwing, once-per-distinct-failure diagnostic so polling does not spam logs.
 if (status != (int)ErrorCode.Success)
{
return TelemetryPolicyState.Blocked;
}

src/ffi/mxc_ffi/src/lib.rs:87

  • This safety note overstates what the surrounding catch_unwind can protect. A panic escaping a Rust extern "C" presenter cannot unwind back to this frame; it normally aborts at the non-unwinding ABI boundary. The callback must catch Rust panics too, just as the managed bridge below catches managed exceptions, or binding authors may believe a presenter panic is recoverable.
/// **The callback must not unwind across the FFI boundary.** Only Rust panics
/// are caught by [`std::panic::catch_unwind`] on the Rust side; a C++
/// exception, a .NET/CLR exception, an Objective-C exception, a Go panic, or
/// any other foreign unwind mechanism escaping this callback into Rust is

sdk/dotnet/Microsoft.Mxc.Sdk/MxcTelemetry.cs:102

  • The PR description and stack explicitly reserve the Node.js/.NET SDK surfaces for #822, but this file introduces the public .NET telemetry API in #821. That makes this PR contain the next stack layer and prevents the Rust SDK/C ABI change from being reviewed independently as described. Please move the .NET API, policy, error-code, and managed-test changes to #822 or update/split the stack consistently.
/// <summary>Telemetry consent helpers over the native <c>mxc_ffi</c> surface.</summary>
public static class MxcTelemetry

sdk/dotnet/Microsoft.Mxc.Sdk/MxcTelemetry.cs:149

  • This catch converts native-load, marshaling, and malformed-native-response failures into the legitimate Undetermined consent state. Callers then cannot distinguish “no decision” from a broken installation. Consent reads should surface failures as the SDK's documented MxcException type; reserve never-throw fail-closed behavior for the polling helpers (NeedsConsentPrompt and GetPolicy).

This issue also appears in the following locations of the same file:

  • line 273
  • line 299
 catch
{
return TelemetryConsentState.Undetermined;
}

Keep the .NET run-to-completion API on the canonical nested Telemetry settings and remove internal implementation language from the Rust SDK documentation.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 6e20d046-910e-4ee7-b8e8-acb0fe007208

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The callback unwind contract is inaccurate and the .NET README references a nonexistent state-aware telemetry property.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details
  • Files reviewed: 23/24 changed files
  • Comments generated: 2
  • Review effort level: Balanced

Comment threadsrc/ffi/mxc_ffi/src/lib.rs Outdated
Comment threadsdk/dotnet/README.md Outdated
Require all FFI presenter callbacks to contain failures internally and remove the unavailable state-aware telemetry option from the standalone .NET SDK documentation.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 6e20d046-910e-4ee7-b8e8-acb0fe007208

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

The privacy-sensitive public API spans Rust, native ABI, managed callbacks, and custom build integration, warranting final human validation.

Review details
  • Files reviewed: 23/24 changed files
  • Comments generated: 0 new
  • Review effort level: Balanced

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 6e20d046-910e-4ee7-b8e8-acb0fe007208
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 6e20d046-910e-4ee7-b8e8-acb0fe007208

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

The privacy-sensitive API spans Rust, native ABI, managed callbacks, and custom test-build infrastructure, warranting final human review.

Review details
  • Files reviewed: 23/24 changed files
  • Comments generated: 0 new
  • Review effort level: Balanced

Resolve the telemetry and diagnostic overlap with PR #791 while preserving top-level telemetry consent, internal state-aware correlation, requested sandbox attribution, and the scoped ETW audit events.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 6e20d046-910e-4ee7-b8e8-acb0fe007208
Carry the current PR #820 runtime and scoped ETW integration forward without rewriting the published Rust SDK and FFI history.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 6e20d046-910e-4ee7-b8e8-acb0fe007208

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Public API documentation incorrectly describes effective consent as the persisted user decision.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details
  • Files reviewed: 23/24 changed files
  • Comments generated: 3
  • Review effort level: Balanced

Comment threadsdk/dotnet/Microsoft.Mxc.Sdk/MxcTelemetry.cs
Comment threadsrc/core/mxc-sdk/src/telemetry.rs Outdated
Comment threadsrc/ffi/mxc_ffi/src/lib.rs Outdated
Resolve the squash-merge overlap by retaining the Rust SDK telemetry accessor and combined telemetry test support while adopting the finalized correlation-vector documentation.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 6e20d046-910e-4ee7-b8e8-acb0fe007208

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The asynchronous consent API can persist consent after its cancellation token has been canceled.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details
  • Files reviewed: 23/24 changed files
  • Comments generated: 1
  • Review effort level: Balanced

Comment threadsdk/dotnet/Microsoft.Mxc.Sdk/MxcTelemetry.cs
Centralize binding policy parsing in the native engine, clarify effective consent APIs, and make asynchronous consent cancellation state-consistent across stalled, faulted, and synchronous presenters.
Refs #1090, #1111, #1112, #1113, #1114
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 6e20d046-910e-4ee7-b8e8-acb0fe007208

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

Managed fail-closed query paths silently suppress failures instead of emitting required deduplicated diagnostics.

Review details

Suppressed comments (3)

Previously missed (1) — in code that hasn't changed since the last review.

sdk/dotnet/Microsoft.Mxc.Sdk/MxcTelemetry.cs:151

  • This fallback silently hides native-load and managed parsing failures. Telemetry's fail-closed convention requires swallowed failures to remain diagnosable once per distinct failure (see docs/telemetry/telemetry-administrative-policy.md:47-49 and the native report_diagnostic_once helper), otherwise a broken binding is indistinguishable from a genuine undetermined state. Report the exception through a non-throwing, deduplicated diagnostic helper before returning Undetermined.

This issue also appears in the following locations of the same file:

  • line 317
  • line 351

sdk/dotnet/Microsoft.Mxc.Sdk/MxcTelemetry.cs:319

  • This catch converts every resolver/native failure to false without any diagnostic. Because false is also the legitimate no-prompt result, a broken native installation becomes invisible; the telemetry failure-handling convention reports swallowed failures once per distinct failure (docs/telemetry/telemetry-administrative-policy.md:47-49). Use the same non-throwing, deduplicated managed diagnostic helper as the other fail-closed queries before returning.
 catch
{
return false;

sdk/dotnet/Microsoft.Mxc.Sdk/MxcTelemetry.cs:353

  • Returning Blocked is correctly fail-closed, but silently swallowing this exception violates the policy contract that unreadable failures are reported once so operators can distinguish a broken deployment from an intentional block (docs/telemetry/telemetry-administrative-policy.md:43-49). Emit a non-throwing, deduplicated diagnostic before returning the fallback.
 catch
{
return TelemetryPolicyState.Blocked;
  • Files reviewed: 26/27 changed files
  • Comments generated: 0 new
  • Review effort level: Balanced

Emit non-throwing, process-deduplicated diagnostics whenever managed consent and policy queries return fail-closed fallback values.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 6e20d046-910e-4ee7-b8e8-acb0fe007208
Use stable bounded diagnostic categories, redact exception details, and add deterministic deduplication coverage.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 6e20d046-910e-4ee7-b8e8-acb0fe007208
Route fail-closed reports through Trace, use typed allocation-free deduplication keys, remove the global sink override, and document the managed diagnostic channel.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 6e20d046-910e-4ee7-b8e8-acb0fe007208
Make deduplication and capacity independently testable, scope Trace assertions to unique operation tags, and cover concurrent reports.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 6e20d046-910e-4ee7-b8e8-acb0fe007208
Add an internal query seam for deterministic fail-closed integration tests, cover concurrent capacity and throwing Trace listeners, and document retained diagnostic fields.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 6e20d046-910e-4ee7-b8e8-acb0fe007208
Use atomic override restoration, cover concurrent disposal, and name the seam for the fail-closed reads it intentionally isolates.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 6e20d046-910e-4ee7-b8e8-acb0fe007208
Rollback diagnostic reservations when Trace listeners fail, isolate production tracker state in tests, strengthen override restoration coverage, and consolidate reporter control flow.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 6e20d046-910e-4ee7-b8e8-acb0fe007208
Reject overlapping process-global test overrides, cover each read failure branch, and clarify diagnostic documentation.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 6e20d046-910e-4ee7-b8e8-acb0fe007208
Use a fresh dedup tracker and assert the distinct exception and status diagnostic paths without consuming process-global state.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 6e20d046-910e-4ee7-b8e8-acb0fe007208
Dispose process-global test overrides during assertion unwinding and document why the telemetry collection is nonparallel.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 6e20d046-910e-4ee7-b8e8-acb0fe007208
Document that managed fail-closed reporting retains a bounded set of distinct process-lifetime failure signatures.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 6e20d046-910e-4ee7-b8e8-acb0fe007208

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

The broad privacy-sensitive, cross-language API and FFI changes warrant final human validation despite the extensive coverage.

Review details
  • Files reviewed: 26/27 changed files
  • Comments generated: 0 new
  • Review effort level: Balanced

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants

@RamonArjona4@jsidewhite@MGudgin@bbonaby