Configure SDK observability
Send SDK product events and sanitized failures through a host-owned PostHog client.
Initialize PostHog once in the host, then adapt that existing client:
import { createCapxulClient, postHogObservability } from "@capxul/sdk";
const observability = postHogObservability(posthog, {
enabled: () => analyticsConsentGranted,
engineeringEnabled: () => analyticsConsentGranted,
capxulEnv: "production",
context: () => ({
application: "operations-console",
release: appVersion,
sessionId,
organizationId,
correlationId,
}),
});
const created = await createCapxulClient({
publishableKey,
observability,
});The module carries SDK product events and captures one sanitized record when a public operation returns a failed result or unexpectedly throws. Delivery is best-effort and cannot change the domain result.
Failures from an observed public Effect include the completed operation's
trace_id and span_id. These IDs join the PostHog failure Event to its native
Log and APM span. They preserve the person and correlation captured at call
start. A host traceparent cannot supply the owning pair. Failures that have
no owning span omit the fields.
Do not put email addresses, wallet addresses, URLs, JSON, tokens, or arbitrary messages in observation context. Unsafe values are dropped. The backend derives actor identity from authentication and verifies Organization/application hints.
Backend linkage is deliberately bounded. A configured backend may emit linked engineering events. This behavior does not prove universal backend exception delivery.
Omit observability when the host has no consented analytics destination. The SDK
does not initialize PostHog, replay, page views, or global exception capture.
Engineering logs and traces do not add another application prop. The backend optionally supplies a validated PostHog ingest policy in the versioned bootstrap response; missing or invalid policy simply leaves engineering export disabled.
Use engineeringEnabled to apply the host's collection preference to these
bootstrap-configured exporters as well. It accepts a boolean or callback. False
or a thrown callback stops engineering collection for that client runtime and
drops its queued batches. Re-enable by creating a new client. Omit the option
to retain existing bootstrap behavior. The enabled option continues to
control product events and failure capture.
client.system.health(nonce, { signal }) uses the same production runtime. Its
SDK span continues the sanitized traceparent from host context and forwards
its native parent context to the operator.diagnostics.health backend action. The
action permits the existing bounded OTLP export. Local tests do not prove backend span arrival in PostHog.
For a CLI host that must exclude provider text and filesystem paths, also set
engineeringPrivacy: "minimal" on postHogObservability. This optional policy
projects every SDK engineering signal before export, including span exception
events and log causes. It keeps closed operations and error codes, timings,
environment, and validated invocation and native trace correlation. It removes
free-form text, bodies, URLs, and source paths. Omission retains the existing
credential-redacted diagnostics.
Browser failure capture
The optional failureCapture(event, properties, canonicalWords?) host callback
replaces capture only for SDK failures. It runs inside best-effort delivery.
Product and bootstrap events still use the existing client. Omit the callback
to keep the current behavior.
canonicalWords is a frozen in-process snapshot from the private original
CapxulError path. Direct adapter rows and decoded shape-only failures have no
snapshot. Only error_message, $exception_message, $issue_description and
the first exception value can carry canonical words. A distinct chain-revert
description keeps its existing text policy. Details, cause, stack and URLs
remain subject to the host privacy hook.
A browser host must supply the same synchronous capture closure to this
callback and its before_send wrapper. Bind one pending snapshot to the native
PostHog capture UUID, event and operation. Consume it before sanitization and
restore only original strings that equal the snapshot. Clear it when capture
returns or throws. Deferred, truncated and unmatched events use generic
masking. Never serialize the snapshot or infer authority from event fields.