@heystack/otel 0.18.0 → 0.19.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +151 -27
- package/dist/core.d.ts +1 -0
- package/dist/core.js +4 -0
- package/dist/hash.d.ts +19 -0
- package/dist/hash.js +47 -0
- package/dist/next.d.ts +2 -1
- package/dist/next.js +5 -0
- package/dist/node.d.ts +14 -2
- package/dist/node.js +49 -4
- package/dist/redact.d.ts +57 -0
- package/dist/redact.js +190 -0
- package/dist/web.d.ts +42 -0
- package/dist/web.js +91 -24
- package/dist/workers-bindings.d.ts +39 -2
- package/dist/workers-bindings.js +388 -78
- package/dist/workers-coverage.d.ts +11 -0
- package/dist/workers-coverage.js +22 -0
- package/dist/workers-native.d.ts +66 -0
- package/dist/workers-native.js +147 -0
- package/dist/workers-propagation.d.ts +24 -0
- package/dist/workers-propagation.js +72 -0
- package/dist/workers-routes.d.ts +11 -0
- package/dist/workers-routes.js +45 -0
- package/dist/workers-sampler.d.ts +10 -1
- package/dist/workers-sampler.js +7 -3
- package/dist/workers.d.ts +108 -19
- package/dist/workers.js +639 -190
- package/package.json +9 -4
package/dist/workers.d.ts
CHANGED
|
@@ -3,6 +3,10 @@ import { type Context, type ContextManager } from "@opentelemetry/api";
|
|
|
3
3
|
import { BasicTracerProvider, type ReadableSpan, type SpanExporter } from "@opentelemetry/sdk-trace-base";
|
|
4
4
|
import { type HeystackOptions } from "./core.js";
|
|
5
5
|
import { type LLMGatewayConfig } from "./llm-enrich.js";
|
|
6
|
+
import { wrapSqlClient } from "./workers-bindings.js";
|
|
7
|
+
import { NATIVELY_COVERED, NATIVE_PROPAGATES_EXTERNAL, shouldEnrichNatively, type BindingKind } from "./workers-coverage.js";
|
|
8
|
+
import { type CloudflareSpan, type CloudflareTracing } from "./workers-native.js";
|
|
9
|
+
import { type SpanPrivacyOptions } from "./redact.js";
|
|
6
10
|
declare const ExportResultCode: {
|
|
7
11
|
readonly SUCCESS: 0;
|
|
8
12
|
readonly FAILED: 1;
|
|
@@ -54,13 +58,15 @@ interface OtlpTracesPayload {
|
|
|
54
58
|
}[];
|
|
55
59
|
}[];
|
|
56
60
|
}
|
|
61
|
+
/** Per-span attribute transform applied at serialization (privacy pass). */
|
|
62
|
+
type AttributeTransform = (attrs: Record<string, unknown>, span: ReadableSpan) => Record<string, unknown>;
|
|
57
63
|
/**
|
|
58
64
|
* Serialize a batch of ended spans into a single OTLP/JSON traces payload.
|
|
59
65
|
*
|
|
60
66
|
* All spans in a SimpleSpanProcessor batch share the same per-request provider,
|
|
61
67
|
* hence the same resource, so we emit a single resourceSpans entry.
|
|
62
68
|
*/
|
|
63
|
-
export declare function serializeSpans(spans: ReadableSpan[]): OtlpTracesPayload;
|
|
69
|
+
export declare function serializeSpans(spans: ReadableSpan[], transform?: AttributeTransform): OtlpTracesPayload;
|
|
64
70
|
/** Parse a W3C `traceparent`. Returns null for malformed or all-zero ids. */
|
|
65
71
|
export declare function parseTraceparent(header: string | null): {
|
|
66
72
|
traceId: string;
|
|
@@ -112,7 +118,13 @@ export declare class HeystackSpanExporter implements SpanExporter {
|
|
|
112
118
|
* the `pending` set + manual `flushHeystack()` when absent/unavailable.
|
|
113
119
|
*/
|
|
114
120
|
waitUntil?: (p: Promise<unknown>) => void;
|
|
115
|
-
|
|
121
|
+
/**
|
|
122
|
+
* Privacy pass on every exported span — redacts URL attributes (`url.full`,
|
|
123
|
+
* `http.url`, `http.target`, `url.query`, …) so spans from host frameworks
|
|
124
|
+
* (Next/OpenNext, manual spans) are covered too, not just Heystack's own.
|
|
125
|
+
*/
|
|
126
|
+
private readonly privacy;
|
|
127
|
+
constructor(options: HeystackOptions & SpanPrivacyOptions);
|
|
116
128
|
export(spans: ReadableSpan[], resultCallback: (result: ExportResult) => void): void;
|
|
117
129
|
/**
|
|
118
130
|
* POST the batch with ONE bounded automatic retry for network errors / 429 /
|
|
@@ -143,7 +155,7 @@ export declare class HeystackSpanExporter implements SpanExporter {
|
|
|
143
155
|
*/
|
|
144
156
|
forceFlush(): Promise<void>;
|
|
145
157
|
}
|
|
146
|
-
export interface WorkersConfig {
|
|
158
|
+
export interface WorkersConfig extends SpanPrivacyOptions {
|
|
147
159
|
service: string;
|
|
148
160
|
/** Defaults to env.HEYSTACK_API_KEY at request time if omitted. */
|
|
149
161
|
apiKey?: string;
|
|
@@ -185,17 +197,33 @@ export interface WorkersConfig {
|
|
|
185
197
|
* Defaults to `false` (no binding tracing). Consumed by a later task.
|
|
186
198
|
*/
|
|
187
199
|
instrumentBindings?: boolean | string[];
|
|
200
|
+
/**
|
|
201
|
+
* Native mode only: per-kind override of which bindings the SDK enriches on
|
|
202
|
+
* top of Cloudflare's own spans. Default: only kinds Cloudflare does not trace
|
|
203
|
+
* (`ai`, `vectorize`, `workflow`, `hyperdrive`, `analytics_engine`). Set
|
|
204
|
+
* `{ ai: false }` to opt out or `{ d1: true }` to force-enrich a covered kind.
|
|
205
|
+
* Ignored when `instrumentBindings` is set explicitly.
|
|
206
|
+
*/
|
|
207
|
+
nativeEnrichment?: Partial<Record<BindingKind, boolean>>;
|
|
188
208
|
/**
|
|
189
209
|
* Select the Workers tracing plane. `auto` (default) uses Cloudflare's native
|
|
190
210
|
* tracer when `ctx.tracing` is available and otherwise falls back to direct
|
|
191
211
|
* OTLP export. `native` prefers the platform tracer but still fails open when
|
|
192
212
|
* unavailable. `direct` always uses Heystack's fetch exporter.
|
|
193
213
|
*
|
|
194
|
-
* Native mode
|
|
195
|
-
*
|
|
196
|
-
*
|
|
214
|
+
* Native mode creates no OTel provider and does not re-instrument what
|
|
215
|
+
* Cloudflare already spans (fetch, D1, KV, R2, DO, Queues, rate limit,
|
|
216
|
+
* service bindings). It enriches only the uncovered binding kinds (Workers AI,
|
|
217
|
+
* Vectorize, Workflows, Analytics Engine; Hyperdrive via `wrapSqlClient`) as
|
|
218
|
+
* native child spans, gated by `nativeEnrichment` / an explicit
|
|
219
|
+
* `instrumentBindings`.
|
|
197
220
|
*/
|
|
198
221
|
nativeTracing?: "auto" | "native" | "direct";
|
|
222
|
+
/**
|
|
223
|
+
* Explicit Cloudflare tracer (`ctx.tracing`) for contexts that have none of
|
|
224
|
+
* their own, e.g. Durable Objects. Preferred over `ctx.tracing` when set.
|
|
225
|
+
*/
|
|
226
|
+
tracing?: CloudflareTracing;
|
|
199
227
|
/**
|
|
200
228
|
* Head-sampling configuration. When omitted (or `rate` >= 1), all traces are
|
|
201
229
|
* kept. When `rate` < 1, a deterministic FNV-1a hash of the trace ID decides
|
|
@@ -204,7 +232,9 @@ export interface WorkersConfig {
|
|
|
204
232
|
*
|
|
205
233
|
* Note: head sampling is parent-respecting, so an incoming request carrying a
|
|
206
234
|
* sampled `traceparent` is still recorded even at `rate: 0` (it is not an
|
|
207
|
-
* absolute kill-switch; it governs only fresh/root traces)
|
|
235
|
+
* absolute kill-switch; it governs only fresh/root traces) — unless
|
|
236
|
+
* `trustInboundSampling: false`, which makes the rate decide for inbound
|
|
237
|
+
* traces too.
|
|
208
238
|
*
|
|
209
239
|
* When `remote: true`, the sampling rate is fetched once per isolate from
|
|
210
240
|
* `{endpoint}/v1/sampling/config` on the first request. Cold-isolate spans
|
|
@@ -215,6 +245,25 @@ export interface WorkersConfig {
|
|
|
215
245
|
rate?: number;
|
|
216
246
|
remote?: boolean;
|
|
217
247
|
};
|
|
248
|
+
/**
|
|
249
|
+
* Whether an inbound W3C `traceparent` sampled flag (`-01` / `-00`) decides
|
|
250
|
+
* keep/drop for the request's trace. Default `true` (parent-based sampling,
|
|
251
|
+
* so a browser→Worker trace samples consistently). Set `false` on a Worker
|
|
252
|
+
* that receives traffic from callers you don't control: the trace id is
|
|
253
|
+
* still continued (correlation is kept) but the keep/drop decision is made
|
|
254
|
+
* by THIS Worker's `sampling` rate over the trace id, so a client can't force
|
|
255
|
+
* recording with `-01` (or hide its requests with `-00`). Only meaningful when
|
|
256
|
+
* `sampling` is set (with no rate every trace is kept anyway).
|
|
257
|
+
*/
|
|
258
|
+
trustInboundSampling?: boolean;
|
|
259
|
+
/**
|
|
260
|
+
* Cloudflare geo attributes recorded on the SERVER span from `req.cf`.
|
|
261
|
+
* `"country"` (default) records only `geo.country`; `"full"` also records
|
|
262
|
+
* `geo.region`, `geo.city` and `geo.asn`; `false` records none. The end-user
|
|
263
|
+
* IP (`client.address`) is separate and off by default — see
|
|
264
|
+
* {@link SpanPrivacyOptions.captureClientIp}.
|
|
265
|
+
*/
|
|
266
|
+
captureGeo?: "country" | "full" | false;
|
|
218
267
|
/**
|
|
219
268
|
* LLM/gen_ai capture for outbound calls to known providers (OpenAI, Anthropic,
|
|
220
269
|
* Mistral, Google, CF AI Gateway). Metadata (model, tokens, latency,
|
|
@@ -243,17 +292,36 @@ export interface WorkersConfig {
|
|
|
243
292
|
redact?: (text: string) => string;
|
|
244
293
|
maxContentChars?: number;
|
|
245
294
|
gateways?: LLMGatewayConfig[];
|
|
295
|
+
/**
|
|
296
|
+
* The Cloudflare AI Gateway exports its own OTel spans for these calls.
|
|
297
|
+
* When true the SDK's LLM span is marked `heystack.ai.delegated` so the
|
|
298
|
+
* call is counted once (by the gateway). Opt-in: without it the SDK span is
|
|
299
|
+
* the counted one, so an AI call isn't lost if the gateway's own export
|
|
300
|
+
* isn't configured. The `cf-aig-otel-*` headers are sent either way.
|
|
301
|
+
*/
|
|
302
|
+
gatewayExport?: boolean;
|
|
246
303
|
};
|
|
304
|
+
/**
|
|
305
|
+
* Path templates for `http.route`, e.g. `["/users/:id", "/files/*"]` (first
|
|
306
|
+
* match wins; a trailing `*` matches the rest). If neither this nor
|
|
307
|
+
* `routeTemplate` is set, `http.route` is omitted and Heystack templates the
|
|
308
|
+
* path server-side.
|
|
309
|
+
*/
|
|
310
|
+
routes?: string[];
|
|
311
|
+
/** Compute the `http.route` template per request; wins over `routes`. */
|
|
312
|
+
routeTemplate?: (req: Request) => string | undefined;
|
|
313
|
+
/**
|
|
314
|
+
* Hostnames (exact string or RegExp) that receive `traceparent` (and AI
|
|
315
|
+
* Gateway headers) on native-mode outbound fetches. Default: every host except
|
|
316
|
+
* the Heystack ingest endpoint. `[]` disables propagation.
|
|
317
|
+
*/
|
|
318
|
+
propagateTargets?: Array<string | RegExp>;
|
|
247
319
|
}
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
/** `ExecutionContext.tracing` without importing the `cloudflare:workers` module. */
|
|
254
|
-
export interface CloudflareNativeTracing {
|
|
255
|
-
enterSpan<T, A extends unknown[]>(name: string, callback: (span: CloudflareNativeSpan, ...args: A) => T, ...args: A): T;
|
|
256
|
-
}
|
|
320
|
+
export type { CloudflareSpan, CloudflareTracing };
|
|
321
|
+
/** @deprecated Use {@link CloudflareSpan}. */
|
|
322
|
+
export type CloudflareNativeSpan = CloudflareSpan;
|
|
323
|
+
/** @deprecated Use {@link CloudflareTracing}. */
|
|
324
|
+
export type CloudflareNativeTracing = CloudflareTracing;
|
|
257
325
|
/**
|
|
258
326
|
* A `BasicTracerProvider` with the underlying `HeystackSpanExporter` attached so
|
|
259
327
|
* flush paths can drain its in-flight fetches directly (the OTel processor's
|
|
@@ -272,10 +340,12 @@ export type HeystackTracerProvider = BasicTracerProvider & {
|
|
|
272
340
|
* must drain the exporter — `await provider.heystackExporter.forceFlush()` (or
|
|
273
341
|
* `flushHeystack()`), not just `provider.forceFlush()`.
|
|
274
342
|
*/
|
|
275
|
-
export declare function createTracerProvider(config: HeystackOptions & {
|
|
343
|
+
export declare function createTracerProvider(config: HeystackOptions & SpanPrivacyOptions & {
|
|
276
344
|
sampling?: {
|
|
277
345
|
rate?: number;
|
|
346
|
+
remote?: boolean;
|
|
278
347
|
};
|
|
348
|
+
trustInboundSampling?: boolean;
|
|
279
349
|
}): HeystackTracerProvider;
|
|
280
350
|
/**
|
|
281
351
|
* An AsyncLocalStorage-backed ContextManager for the /workers entry. When the
|
|
@@ -483,6 +553,22 @@ export declare function wrapDurableObjectClass<C extends {
|
|
|
483
553
|
export declare function wrapWorkflowEntrypointClass<C extends {
|
|
484
554
|
readonly prototype: object;
|
|
485
555
|
}>(cls: C, opts?: InstrumentClassesOpts): C;
|
|
556
|
+
/**
|
|
557
|
+
* Decorate a `WorkerEntrypoint` class (the target of a Service binding):
|
|
558
|
+
* - `fetch()` is traced exactly like an `instrument()`ed handler (SERVER span,
|
|
559
|
+
* inbound `traceparent` continued, export drained via `ctx.waitUntil`).
|
|
560
|
+
* - every public RPC method gets a SERVER span `rpc <method>` with
|
|
561
|
+
* `jsrpc.method` / `rpc.method`. Return values (including stubs, RpcTargets
|
|
562
|
+
* and custom thenables), `this` and errors pass through untouched.
|
|
563
|
+
*
|
|
564
|
+
* RPC spans exist in DIRECT mode only. When Cloudflare native tracing is active
|
|
565
|
+
* it already emits `jsrpc` spans, so RPC calls pass straight through and `fetch`
|
|
566
|
+
* takes `instrument()`'s native path. Constructor, `#private`, `_underscore` and
|
|
567
|
+
* Symbol-keyed members are never wrapped.
|
|
568
|
+
*
|
|
569
|
+
* export default wrapWorkerEntrypointClass(class Api extends WorkerEntrypoint { ... }, { service: "api" });
|
|
570
|
+
*/
|
|
571
|
+
export declare function wrapWorkerEntrypointClass<T extends new (...a: any[]) => object>(cls: T, cfg: WorkersConfig): T;
|
|
486
572
|
/**
|
|
487
573
|
* Run `fn` inside a new child span named `name`. The span is automatically
|
|
488
574
|
* parented to the currently-active span (via `context.active()`), started
|
|
@@ -502,8 +588,8 @@ export declare function withSpan<T>(name: string, attrs: Record<string, string |
|
|
|
502
588
|
* without `nodejs_compat`: the explicit context cannot be lost across async
|
|
503
589
|
* boundaries. It falls back to the regular OTel tracer outside Cloudflare.
|
|
504
590
|
*/
|
|
505
|
-
export declare function withCloudflareSpan<T>(ctx: ExecutionContext |
|
|
506
|
-
export declare function withCloudflareSpan<T>(ctx: ExecutionContext |
|
|
591
|
+
export declare function withCloudflareSpan<T>(ctx: ExecutionContext | CloudflareTracing, name: string, fn: (span: Span) => T | Promise<T>): Promise<T>;
|
|
592
|
+
export declare function withCloudflareSpan<T>(ctx: ExecutionContext | CloudflareTracing, name: string, attrs: Record<string, string | number | boolean>, fn: (span: Span) => T | Promise<T>): Promise<T>;
|
|
507
593
|
/**
|
|
508
594
|
* Add a named event (with optional attributes) to the currently-active span.
|
|
509
595
|
* No-op when no span is active.
|
|
@@ -523,3 +609,6 @@ export { llmRequestAttrs as genAiRequestAttrs } from "./llm-enrich.js";
|
|
|
523
609
|
*/
|
|
524
610
|
export { llmResponseAttrs as genAiResponseAttrs } from "./llm-enrich.js";
|
|
525
611
|
export type { LLMGatewayConfig, LLMProvider } from "./llm-enrich.js";
|
|
612
|
+
export { NATIVELY_COVERED, NATIVE_PROPAGATES_EXTERNAL, shouldEnrichNatively, wrapSqlClient };
|
|
613
|
+
export { matchRoute } from "./workers-routes.js";
|
|
614
|
+
export type { BindingKind };
|