/** * OpenTelemetry SDK stand-up: HyperDX's OTel distribution (`@hyperdx/node-opentelemetry`) * — auto-instrumentation + uncaught-exception capture — against a self-hosted OTLP collector, * with a process-stable resource-attribute set. * * Init runs from plugin `register()` (process scope): the agent hooks register there, before * any runtime, and emit through this SDK's tracer. Only process-stable values ride the resource * (`service.*`, `deployment.environment`, `user.id`), so init need not wait for a runtime. * * Gated by OTLP-config presence: inits iff an OTLP endpoint env is set (no enable flag, no * localhost default). No endpoint ⇒ no SDK and the global tracer/logger no-op. If a non-noop * global `TracerProvider` already exists (the gateway's `diagnostics-otel` owns it), we stand * down and emit through the global API — one SDK per process, first writer wins. * * The package is imported dynamically: it reads `OTEL_EXPORTER_OTLP_*` at module-load and * exposes no init() option for them, so the env must be set first. Under openclaw the operator * sets all of these (the SDK derives none): * OTEL_EXPORTER_OTLP_ENDPOINT / _TRACES_ENDPOINT / _LOGS_ENDPOINT / _METRICS_ENDPOINT / _HEADERS * See docs/runtime-docs/runtime-api.md (Tracing). */ /** True when any OTLP endpoint env is set — the gate for standing up the plugin's SDK. */ export declare function isOtlpEndpointConfigured(): boolean; /** * Whether {@link initOtelSdk} has completed. Code that loads `@hyperdx/node-opentelemetry` * lazily (e.g. per-trace attribute stamping) gates on this so the package — which captures * its OTLP transport env at module-load — never loads when telemetry is disabled or under test. */ export declare function isOtelInitialized(): boolean; /** * Decode the `senpi_user_id` claim from a JWT without verifying its signature. * Returns `undefined` for any non-JWT / malformed / missing-claim input; never throws. * * The claim name is assumed, not confirmed against a real token — if the id lives * under a different claim (e.g. `sub`), this must change before `user.id` is trusted. */ export declare function decodeSenpiUserId(token: string | undefined): string | undefined; /** Attribute sources not carried by the {@link IdentityEnvelope}. */ export interface OtelResourceExtras { /** Process-level instance id → `service.instance.id` ({@link PROCESS_INSTANCE_ID}). */ readonly serviceInstanceId?: string; /** → `service.version`. */ readonly serviceVersion?: string; /** → `deployment.environment`. */ readonly deploymentEnvironment?: string; /** Decoded `senpi_user_id` → `user.id`. */ readonly userId?: string; } /** * Build the `OTEL_RESOURCE_ATTRIBUTES` value as a `key=value,key=value` string. * Values are percent-encoded so spaces/commas stay valid; empty keys are omitted. * * SCOPING (multi-runtime): resource attributes are process-global and immutable * after the first init(), but N runtimes (one per wallet) share one process — so * only PROCESS-STABLE values belong here. We carry: * - service.name, service.version, deployment.environment — process-stable. * - service.instance.id — a PROCESS-level id ({@link PROCESS_INSTANCE_ID}), not * the per-runtime `IdentityEnvelope.bootId`. * - user.id — process-stable: single-tenant, one SENPI_API_KEY = one user for * the whole process, so it is the same across every runtime here. * * The per-runtime keys (senpi.strategy.address, senpi.recipe, senpi.recipe.version, * senpi.runtime, senpi.group, senpi.config.hash) are deliberately OMITTED — on a process-global * resource they would stamp the first runtime's value onto every other runtime's * telemetry. They ride per-trace via `setTraceAttributes` and per-log via the logger's * emit-time identity stamp (both reading the same per-runtime identity context). */ export declare function buildOtelResourceAttributes(serviceName: string, extras: OtelResourceExtras): string; export interface InitOtelSdkParams { /** SENPI_API_KEY JWT (the MCP bearer) — decoded locally for `user.id`. */ readonly userToken?: string; /** Plugin version → `service.version`. */ readonly serviceVersion: string; } /** * Initialise the OTel SDK. Idempotent, side-effecting, and never crashes boot: * no-ops when no OTLP endpoint is configured, when a real global TracerProvider * already exists (the gateway owns it — we emit through the global API instead), * when already initialised, or under test. */ export declare function initOtelSdk(params: InitOtelSdkParams): Promise; /** * Flush and stop the OTel SDK. Best-effort, idempotent, never throws. * * Required because {@link initOtelSdk} disables HyperDX's own SIGTERM handler * (`stopOnTerminationSignals: false`) — that handler was the SDK's only on-exit * flush, so without an explicit shutdown the span/log batch processors' buffers * are dropped at process exit. The SDK is process-global (one per process, * shared across all hosted runtimes), so this must be called ONCE at process / * plugin teardown, after every span has been emitted — never per-runtime, which * would cut off telemetry for sibling runtimes still running. */ export declare function shutdownOtelSdk(): Promise; //# sourceMappingURL=otel-sdk.d.ts.map