Skip to content

feat: telemetry - #826

Merged
eitjuh merged 13 commits into
betafrom
feat/telemetry
Oct 6, 2026
Merged

eitjuh merged 13 commits into
betafrom
feat/telemetry

Conversation

@eitjuh

@eitjuh eitjuh commented Oct 5, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds SDK usage telemetry. Every relayer request now carries four x-zama-sdk-* headers, which Kong already logs into Grafana:

Header Values
x-zama-sdk-version package version, e.g. 3.7.0
x-zama-sdk-layer core or react
x-zama-sdk-runtime browser (web()) or node (node())
x-zama-sdk-operation confidential-transfer, unshield, decrypt-balance, vault-*, encrypt, user-decrypt, delegated-user-decrypt, public-decrypt, offline-prepare. Omitted on the FHE key fetch.
  • Headers ride on @fhevm/sdk's per-request headers option and are stamped in one place, FhevmRelayer.
  • No end-user data is sent: no addresses, handles, amounts or identifiers.
  • On by default. createConfig({ telemetry: false }) turns it off. On Node, ZAMA_SDK_TELEMETRY=0 does the same.
  • Sent to every relayer URL, with no host check, so traffic through a backend proxy is measured too. Agreed with Ankur in #product-infra.
  • ZamaProvider tags its SDK as react.
  • The internal operation label is an @internal field on the new RelayerRequestOptions type, so it is stripped from the published types.
  • Public API change: telemetry?: boolean on the config. The per-call options of sdk.encrypt and sdk.decryption.* change from an inline Pick<FhevmRelayerOptions, "signal" | "timeout"> to the named RelayerRequestOptions, which has the same shape.
  • The example Next.js proxies and the proxy sample in the authentication guide now forward x-zama-sdk-* headers.
  • New guide: SDK usage telemetry. It lists exactly what is sent and how to opt out.

Scope

  • @zama-fhe/sdk
  • @zama-fhe/react-sdk
  • @zama-fhe/test-components
  • @zama-fhe/test-nextjs
  • @zama-fhe/test-vite
  • Examples (examples/)
  • CI/workflows
  • Docs

Validation

  • pnpm typecheck
  • pnpm lint
  • pnpm test:run (all unit tests pass)
  • pnpm build
  • pnpm api-report:check
  • pnpm llm:build + pnpm llm:check
  • pnpm docs:check-links
  • Checked the built bundle: x-zama-sdk-version inlines as the version string, and the internal operation field is not in the published .d.ts.

Related

Demo (if possible)

N/A, no UI change.

@cla-bot cla-bot Bot added the cla-signed label Oct 5, 2026
@github-actions

github-actions Bot commented Oct 5, 2026

Copy link
Copy Markdown

Public API Changes

sdk-ethers.api.md
--- a/sdk-ethers.api.md
+++ b/sdk-ethers.api.md
@@ -515,6 +515,7 @@
     relayers: { [K in TChains[number]["id"]]: RelayerConfig; };
     runtime?: FhevmRuntimeConfig;
     storage?: GenericStorage;
+    telemetry?: boolean;
     transportKeyPairScope?: string;
     transportKeyPairTTL?: number;
 }
sdk-query.api.md
--- a/sdk-query.api.md
+++ b/sdk-query.api.md
@@ -258,8 +258,8 @@
 
 // @public
 export class Decryption {
-    decryptPublicValues(encryptedValues: EncryptedValue[], options?: Pick<FhevmRelayerOptions, "signal" | "timeout">): Promise<DecryptPublicValuesResult>;
-    decryptValues(encryptedInput: DecryptInput[], options?: Pick<FhevmRelayerOptions, "signal" | "timeout">): Promise<Record<EncryptedValue, ClearValue>>;
+    decryptPublicValues(encryptedValues: EncryptedValue[], options?: RelayerRequestOptions): Promise<DecryptPublicValuesResult>;
+    decryptValues(encryptedInput: DecryptInput[], options?: RelayerRequestOptions): Promise<Record<EncryptedValue, ClearValue>>;
     delegatedBatchDecryptValues(input: {
         encryptedInputs: DecryptInput[];
         delegatorAddress: Address;
@@ -786,6 +786,9 @@
 export type RegisterPermitParams = SignedPreparedPermit;
 
 // @public
+export interface RelayerRequestOptions extends Pick<FhevmRelayerOptions, "signal" | "timeout"> {}
+
+// @public
 export interface RelayerSDK extends Pick<FhevmClient, "encryptValue" | "encryptValues" | "decryptPublicValue" | "decryptPublicValues" | "decryptPublicValuesWithSignatures" | "decryptValue" | "decryptValues" | "decryptValuesFromPairs" | "fetchFheEncryptionKeyBytes" | "generateTransportKeyPair" | "serializeTransportKeyPair" | "serializeSignedDecryptionPermit" | "signDecryptionPermit" | "parseTransportKeyPair" | "parseSignedDecryptionPermit"> {
     chain: FheChain;
     createUnsignedLegacyDecryptionPermitEip712(parameters: CreateUnsignedLegacyDecryptionPermitEip712Parameters): Promise<CreateUnsignedLegacyDecryptionPermitEip712ReturnType>;
@@ -1589,7 +1592,7 @@
     readonly decryption: Decryption;
     readonly delegations: Delegations;
     dispose(): void;
-    encrypt(params: EncryptParams, options?: Pick<FhevmRelayerOptions, "signal" | "timeout">): Promise<EncryptResult>;
+    encrypt(params: EncryptParams, options?: RelayerRequestOptions): Promise<EncryptResult>;
     readonly offline: Offline;
     readonly permits: Permits;
     readonly provider: GenericProvider;
sdk-viem.api.md
--- a/sdk-viem.api.md
+++ b/sdk-viem.api.md
@@ -481,6 +481,7 @@
     relayers: { [K in TChains[number]["id"]]: RelayerConfig; };
     runtime?: FhevmRuntimeConfig;
     storage?: GenericStorage;
+    telemetry?: boolean;
     transportKeyPairScope?: string;
     transportKeyPairTTL?: number;
 }
sdk.api.md
--- a/sdk.api.md
+++ b/sdk.api.md
@@ -5401,8 +5401,8 @@
 
 // @public
 export class Decryption {
-    decryptPublicValues(encryptedValues: EncryptedValue[], options?: Pick<FhevmRelayerOptions, "signal" | "timeout">): Promise<DecryptPublicValuesResult>;
-    decryptValues(encryptedInput: DecryptInput[], options?: Pick<FhevmRelayerOptions, "signal" | "timeout">): Promise<Record<EncryptedValue, ClearValue>>;
+    decryptPublicValues(encryptedValues: EncryptedValue[], options?: RelayerRequestOptions): Promise<DecryptPublicValuesResult>;
+    decryptValues(encryptedInput: DecryptInput[], options?: RelayerRequestOptions): Promise<Record<EncryptedValue, ClearValue>>;
     delegatedBatchDecryptValues(input: {
         encryptedInputs: DecryptInput[];
         delegatorAddress: Address;
@@ -12782,6 +12782,9 @@
 }
 
 // @public
+export interface RelayerRequestOptions extends Pick<FhevmRelayerOptions, "signal" | "timeout"> {}
+
+// @public
 export interface RelayerSDK extends Pick<FhevmClient, "encryptValue" | "encryptValues" | "decryptPublicValue" | "decryptPublicValues" | "decryptPublicValuesWithSignatures" | "decryptValue" | "decryptValues" | "decryptValuesFromPairs" | "fetchFheEncryptionKeyBytes" | "generateTransportKeyPair" | "serializeTransportKeyPair" | "serializeSignedDecryptionPermit" | "signDecryptionPermit" | "parseTransportKeyPair" | "parseSignedDecryptionPermit"> {
     chain: FheChain;
     createUnsignedLegacyDecryptionPermitEip712(parameters: CreateUnsignedLegacyDecryptionPermitEip712Parameters): Promise<CreateUnsignedLegacyDecryptionPermitEip712ReturnType>;
@@ -20816,6 +20819,7 @@
     relayers: { [K in TChains[number]["id"]]: RelayerConfig; };
     runtime?: FhevmRuntimeConfig;
     storage?: GenericStorage;
+    telemetry?: boolean;
     transportKeyPairScope?: string;
     transportKeyPairTTL?: number;
 }
@@ -20913,7 +20917,7 @@
     readonly decryption: Decryption;
     readonly delegations: Delegations;
     dispose(): void;
-    encrypt(params: EncryptParams, options?: Pick<FhevmRelayerOptions, "signal" | "timeout">): Promise<EncryptResult>;
+    encrypt(params: EncryptParams, options?: RelayerRequestOptions): Promise<EncryptResult>;
     readonly offline: Offline;
     readonly permits: Permits;
     readonly provider: GenericProvider;

@github-actions

github-actions Bot commented Oct 5, 2026 •

Copy link
Copy Markdown

Coverage Report

Status Category Percentage Covered / Total
🟢 Lines 93.64% (🎯 80%) 4025 / 4298
🔵 Statements 93.64% 4109 / 4388
🟢 Functions 92.12% (🎯 80%) 1311 / 1423
🟢 Branches 88.64% (🎯 80%) 1803 / 2034
File Coverage
File Stmts Branches Functions Lines Uncovered Lines
Changed Files
packages/react-sdk/src/provider.tsx 100% 83.33% 100% 100%
packages/sdk/src/telemetry.ts 100% 100% 100% 100%
packages/sdk/src/version.ts 100% 100% 100% 100%
packages/sdk/src/zama-sdk.ts 96.55% 100% 94.11% 96.55% 218, 290
packages/sdk/src/chains/router.ts 100% 100% 100% 100%
packages/sdk/src/config/build.ts 100% 100% 100% 100%
packages/sdk/src/config/types.ts 100% 100% 100% 100%
packages/sdk/src/config/web.ts 100% 100% 100% 100%
packages/sdk/src/namespaces/decryption.ts 100% 100% 100% 100%
packages/sdk/src/node/config.ts 100% 83.33% 100% 100%
packages/sdk/src/relayer/fhevm-relayer.ts 94.87% 94.33% 89.47% 94.82% 503-504, 138, 201, 206, 504, 653
packages/sdk/src/relayer/types.ts 100% 100% 100% 100%
packages/sdk/src/services/decryption-service.ts 96.68% 91.78% 97.14% 96.42% 210, 235, 360, 632-635, 645
packages/sdk/src/services/encryption-service.ts 100% 100% 100% 100%
packages/sdk/src/services/offline-service.ts 96% 96.87% 93.33% 96% 184-187, 284
packages/sdk/src/test-fixtures/vaults.ts 100% 100% 100% 100%
packages/sdk/src/token/token.ts 93.13% 79.34% 100% 92.96% 177, 248-250, 332, 399-401, 411, 436, 444-450, 518, 532, 538-543, 663, 814, 945-947
packages/sdk/src/token/wrapped-token.ts 95.08% 88.4% 100% 95.05% 77, 171, 247-253, 268-274, 460
packages/sdk/src/vaults/types.ts 100% 100% 100% 100%
packages/sdk/src/vaults/vault-batcher.ts 90.9% 91.66% 82.92% 90.81% 155, 178-186, 205-210, 239, 265, 404-405
packages/sdk/src/vaults/vault.ts 90.24% 100% 85.71% 90.24% 64-65, 81-82
Generated in workflow #866 for commit e67d78a by the Vitest Coverage Report Action

@eitjuh
eitjuh marked this pull request as ready for review October 5, 2026 19:07

@ankurdotb ankurdotb left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Claude comments:

  1. node() reads process.env without a guard (config.ts:43 (packages/sdk/src/node/config.ts)). This now runs inside createConfig, so it throws ReferenceError on runtimes without process (a Worker without nodejs_compat, or a browser bundle that pulls in /node). Using globalThis.process?.env would fix it. The agent put this at 60% confidence; I confirmed the bare read but not the failure.

  2. Some operation labels have no test. Nothing asserts vault-deposit, vault-redeem, vault-balance or delegated-user-decrypt, so swapping them would pass CI. The offload-encrypt worker path has no header assertion either. One agent says the live offload CI job passed against the real relayer, which covers it end to end but doesn't assert the headers.

  3. Version test is tautological

Comment thread docs/gitbook/src/guides/relayer-api-keys.md Outdated
Comment thread docs/gitbook/src/guides/telemetry.md
Comment thread docs/gitbook/src/guides/telemetry.md Outdated
Comment thread packages/sdk/src/namespaces/decryption.ts
Comment thread packages/sdk/src/relayer/fhevm-relayer.ts
Comment thread packages/sdk/src/telemetry.ts Outdated
Comment thread packages/sdk/src/version.ts
Comment thread docs/gitbook/src/guides/telemetry.md Outdated
Comment thread packages/sdk/src/namespaces/decryption.ts Outdated
Comment thread packages/sdk/src/relayer/types.ts
Comment thread packages/sdk/src/zama-sdk.ts Outdated
@eitjuh
eitjuh merged commit a65488b into beta Oct 6, 2026
33 checks passed
@eitjuh
eitjuh deleted the feat/telemetry branch October 6, 2026 13:15
@zama-bot

zama-bot commented Oct 6, 2026

Copy link
Copy Markdown
Collaborator

🎉 This PR is included in version 3.7.0-beta.6 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants