@heystack/otel 0.15.0 → 0.17.0
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 +36 -1
- package/dist/product.d.ts +41 -0
- package/dist/product.js +97 -0
- package/dist/traceparent.d.ts +8 -0
- package/dist/traceparent.js +5 -0
- package/dist/web.d.ts +4 -0
- package/dist/web.js +9 -1
- package/dist/workers-agents.d.ts +1 -1
- package/dist/workers-agents.js +1 -1
- package/dist/workers-bindings.d.ts +11 -1
- package/dist/workers-bindings.js +286 -6
- package/dist/workers.d.ts +91 -20
- package/dist/workers.js +962 -114
- package/package.json +5 -1
package/dist/workers.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type Span } from "@opentelemetry/api";
|
|
1
|
+
import { SpanKind, type Span } from "@opentelemetry/api";
|
|
2
2
|
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";
|
|
@@ -92,6 +92,8 @@ export declare class HeystackSpanExporter implements SpanExporter {
|
|
|
92
92
|
readonly ingestHost: string;
|
|
93
93
|
private readonly headers;
|
|
94
94
|
private shutdownState;
|
|
95
|
+
/** Exports rejected before network work because the in-flight cap was hit. */
|
|
96
|
+
droppedPending: number;
|
|
95
97
|
/**
|
|
96
98
|
* In-flight export fetches. Each `export()` adds its settled-when-the-POST-
|
|
97
99
|
* completes promise here and removes it on `finally`. `forceFlush()` awaits
|
|
@@ -112,10 +114,21 @@ export declare class HeystackSpanExporter implements SpanExporter {
|
|
|
112
114
|
waitUntil?: (p: Promise<unknown>) => void;
|
|
113
115
|
constructor(options: HeystackOptions);
|
|
114
116
|
export(spans: ReadableSpan[], resultCallback: (result: ExportResult) => void): void;
|
|
117
|
+
/**
|
|
118
|
+
* POST the batch with ONE bounded automatic retry for network errors / 429 /
|
|
119
|
+
* 5xx. Honours `Retry-After` (seconds form) on 429 within the total backoff
|
|
120
|
+
* cap; after retries are exhausted it preserves plain FAILED semantics via
|
|
121
|
+
* `resultCallback`. The returned promise never rejects.
|
|
122
|
+
*/
|
|
123
|
+
private postWithRetry;
|
|
124
|
+
/** Reserve a tracked slot synchronously before starting any network work. */
|
|
125
|
+
private reservePending;
|
|
115
126
|
/**
|
|
116
127
|
* Hand `p` to the OpenNext Cloudflare request context's `ctx.waitUntil`.
|
|
117
128
|
* Resolves the accessor first (awaiting its in-flight load if needed) so an
|
|
118
129
|
* export that fired before the dynamic import settled is still covered.
|
|
130
|
+
* Sets `outcome.borrowed` when (and only when) a real `waitUntil` received
|
|
131
|
+
* `p` — the signal the no-handoff advisory keys off.
|
|
119
132
|
*/
|
|
120
133
|
private handOffToCloudflareContext;
|
|
121
134
|
private warnedWaitUntilFailure;
|
|
@@ -235,13 +248,11 @@ export interface WorkersConfig {
|
|
|
235
248
|
/** Minimal public surface exposed by Cloudflare's Workers custom-spans API. */
|
|
236
249
|
export interface CloudflareNativeSpan {
|
|
237
250
|
readonly isTraced: boolean;
|
|
238
|
-
setAttribute(key: string, value
|
|
239
|
-
end(): void;
|
|
251
|
+
setAttribute(key: string, value?: string | number | boolean): void;
|
|
240
252
|
}
|
|
241
253
|
/** `ExecutionContext.tracing` without importing the `cloudflare:workers` module. */
|
|
242
254
|
export interface CloudflareNativeTracing {
|
|
243
|
-
enterSpan<T>(name: string, callback: (span: CloudflareNativeSpan) => T): T;
|
|
244
|
-
startActiveSpan<T>(name: string, callback: (span: CloudflareNativeSpan) => T): T;
|
|
255
|
+
enterSpan<T, A extends unknown[]>(name: string, callback: (span: CloudflareNativeSpan, ...args: A) => T, ...args: A): T;
|
|
245
256
|
}
|
|
246
257
|
/**
|
|
247
258
|
* A `BasicTracerProvider` with the underlying `HeystackSpanExporter` attached so
|
|
@@ -273,9 +284,9 @@ export declare function createTracerProvider(config: HeystackOptions & {
|
|
|
273
284
|
* context across `await` boundaries — child spans created after an `await`
|
|
274
285
|
* inside a handler are correctly parented to the request's root span.
|
|
275
286
|
*
|
|
276
|
-
* WinterCG-safe: it does NOT import
|
|
277
|
-
* ALS global that the runtime exposes. Falls back to
|
|
278
|
-
* when the global is absent (Deno, Bun without globals, etc.).
|
|
287
|
+
* WinterCG-safe: it does NOT import the Node-only async_hooks builtin; instead
|
|
288
|
+
* it uses the ALS global that the runtime exposes. Falls back to
|
|
289
|
+
* `SyncStackContextManager` when the global is absent (Deno, Bun without globals, etc.).
|
|
279
290
|
*/
|
|
280
291
|
export declare class AlsContextManager implements ContextManager {
|
|
281
292
|
private _als;
|
|
@@ -311,10 +322,12 @@ export declare function __resetContextManager(): void;
|
|
|
311
322
|
* FLUSH: on Next-on-OpenNext (where `@opennextjs/cloudflare` is present) the
|
|
312
323
|
* exporter automatically borrows the Cloudflare request context's
|
|
313
324
|
* `ctx.waitUntil` so the export POST completes before the isolate is torn down
|
|
314
|
-
* — no app hook needed. For other workerd setups without it,
|
|
315
|
-
*
|
|
316
|
-
*
|
|
317
|
-
* the
|
|
325
|
+
* — no app hook needed. For other workerd setups without it, wrap your
|
|
326
|
+
* handler's ExecutionContext with {@link wrapExecutionContext} (every
|
|
327
|
+
* `ctx.waitUntil` then also schedules the export drain), call `flushHeystack()`
|
|
328
|
+
* (which awaits the export fetch) from a response hook, hand it to
|
|
329
|
+
* `ctx.waitUntil(flushHeystack())`, or pass an explicit `waitUntil` in the
|
|
330
|
+
* config (highest priority). Returns the provider.
|
|
318
331
|
*/
|
|
319
332
|
export declare function initHeystackWorkers(config: WorkersConfig & {
|
|
320
333
|
apiKey: string;
|
|
@@ -328,21 +341,25 @@ export declare function initHeystackWorkers(config: WorkersConfig & {
|
|
|
328
341
|
* isolate is torn down. Best-effort no-op if no provider is registered.
|
|
329
342
|
*/
|
|
330
343
|
export declare function flushHeystack(): Promise<void>;
|
|
344
|
+
export declare function wrapExecutionContext<Props>(ctx: ExecutionContext<Props>): ExecutionContext<Props>;
|
|
331
345
|
/** Reset the singleton global provider. Internal/testing helper. */
|
|
332
346
|
export declare function __resetProvider(): void;
|
|
333
|
-
/** Reset the once-only
|
|
347
|
+
/** Reset the once-only warnings. Internal/testing helper. */
|
|
334
348
|
export declare function __resetWarnings(): void;
|
|
335
349
|
/**
|
|
336
350
|
* The shape of a Worker's default export. `fetch` is the common entrypoint, but
|
|
337
|
-
* a Worker may also export `queue` / `scheduled` / `tail` (and
|
|
338
|
-
* siblings). `instrument()`
|
|
339
|
-
*
|
|
340
|
-
*
|
|
351
|
+
* a Worker may also export `queue` / `scheduled` / `tail` / `email` (and
|
|
352
|
+
* arbitrary other siblings). `instrument()` traces `fetch`, `queue`,
|
|
353
|
+
* `scheduled`, `email` and `tail` when present — every other sibling is
|
|
354
|
+
* forwarded untouched, so wrapping never drops a handler Cloudflare requires
|
|
355
|
+
* for deploy.
|
|
341
356
|
*/
|
|
342
357
|
interface WorkerHandler<E> {
|
|
343
358
|
fetch?(req: Request, env: E, ctx: ExecutionContext): Promise<Response> | Response;
|
|
344
359
|
queue?(batch: MessageBatch<any>, env: E, ctx: ExecutionContext): Promise<void> | void;
|
|
345
360
|
scheduled?(controller: ScheduledController, env: E, ctx: ExecutionContext): Promise<void> | void;
|
|
361
|
+
email?(message: ForwardableEmailMessage, env: E, ctx: ExecutionContext): Promise<void> | void;
|
|
362
|
+
tail?(events: TraceItem[], env: E, ctx: ExecutionContext): Promise<void> | void;
|
|
346
363
|
[key: string]: unknown;
|
|
347
364
|
}
|
|
348
365
|
/**
|
|
@@ -370,8 +387,8 @@ interface WorkerHandler<E> {
|
|
|
370
387
|
* ALL HANDLERS FORWARDED: the returned object spreads `handler`, so sibling
|
|
371
388
|
* handlers a Worker exports (`tail`, `email`, etc.) are preserved — Cloudflare
|
|
372
389
|
* won't reject the deploy for a missing handler. `fetch` is always replaced with
|
|
373
|
-
* a traced wrapper; `queue` and `
|
|
374
|
-
* present; everything else is forwarded untouched.
|
|
390
|
+
* a traced wrapper; `queue`, `scheduled`, `email` and `tail` are wrapped (and
|
|
391
|
+
* traced) when present; everything else is forwarded untouched.
|
|
375
392
|
*
|
|
376
393
|
* If no API key is available (neither `config.apiKey` nor
|
|
377
394
|
* `env.HEYSTACK_API_KEY`), the handler runs untraced.
|
|
@@ -383,7 +400,7 @@ interface WorkerHandler<E> {
|
|
|
383
400
|
* traced key is present (and non-optional) exactly when it exists on the input
|
|
384
401
|
* handler, so a `{ fetch }` Worker yields a non-optional `fetch`.
|
|
385
402
|
*/
|
|
386
|
-
type Instrumented<E, H> = Omit<H, "fetch" | "queue" | "scheduled"> & (H extends {
|
|
403
|
+
type Instrumented<E, H> = Omit<H, "fetch" | "queue" | "scheduled" | "email" | "tail"> & (H extends {
|
|
387
404
|
fetch: unknown;
|
|
388
405
|
} ? {
|
|
389
406
|
fetch: (req: Request, env: E, ctx: ExecutionContext) => Promise<Response>;
|
|
@@ -395,6 +412,14 @@ type Instrumented<E, H> = Omit<H, "fetch" | "queue" | "scheduled"> & (H extends
|
|
|
395
412
|
scheduled: unknown;
|
|
396
413
|
} ? {
|
|
397
414
|
scheduled: (controller: ScheduledController, env: E, ctx: ExecutionContext) => Promise<void>;
|
|
415
|
+
} : unknown) & (H extends {
|
|
416
|
+
email: unknown;
|
|
417
|
+
} ? {
|
|
418
|
+
email: (message: ForwardableEmailMessage, env: E, ctx: ExecutionContext) => Promise<void>;
|
|
419
|
+
} : unknown) & (H extends {
|
|
420
|
+
tail: unknown;
|
|
421
|
+
} ? {
|
|
422
|
+
tail: (events: TraceItem[], env: E, ctx: ExecutionContext) => Promise<void>;
|
|
398
423
|
} : unknown);
|
|
399
424
|
/**
|
|
400
425
|
* Recover a handler's concrete env type from whichever traced entrypoint it
|
|
@@ -412,6 +437,52 @@ type EnvOf<H> = H extends {
|
|
|
412
437
|
scheduled: (controller: ScheduledController, env: infer E, ctx: ExecutionContext) => unknown;
|
|
413
438
|
} ? E : unknown;
|
|
414
439
|
export declare function instrument<H extends WorkerHandler<any>>(handler: H, config: WorkersConfig): Instrumented<EnvOf<H>, H>;
|
|
440
|
+
export interface InstrumentClassesOpts {
|
|
441
|
+
/**
|
|
442
|
+
* Factory that creates and starts a new span. Called at method-invocation
|
|
443
|
+
* time. For integration: omit it — the global `heystack` tracer is used with
|
|
444
|
+
* the active context (or the explicit `parentCtx`). For unit tests inject a
|
|
445
|
+
* fake so no global provider is required.
|
|
446
|
+
*/
|
|
447
|
+
startSpan?: (name: string, attrs: Record<string, unknown>, kind?: SpanKind, parentCtx?: Context) => Span;
|
|
448
|
+
}
|
|
449
|
+
/**
|
|
450
|
+
* Decorate a Durable Object class:
|
|
451
|
+
* - constructor: wraps the incoming `state` so `state.storage` operations emit
|
|
452
|
+
* INTERNAL child spans (`DO storage get|put|delete|list`) with key/count attrs.
|
|
453
|
+
* - `fetch()`: SERVER span named `<METHOD> <path>` (like instrument()'s fetch
|
|
454
|
+
* wrapper), continuing an inbound W3C traceparent, recording status/duration.
|
|
455
|
+
* - `alarm()`: INTERNAL span.
|
|
456
|
+
* - RPC prototype methods: SERVER span `DO rpc <method>` with rpc.method attrs.
|
|
457
|
+
*
|
|
458
|
+
* Every root span schedules flushHeystack() via `state.waitUntil` so exports
|
|
459
|
+
* complete before isolate teardown. Instance arrow-function methods assigned in
|
|
460
|
+
* the constructor are not enumerable on the prototype and stay unwrapped.
|
|
461
|
+
*
|
|
462
|
+
* export class Counter extends DurableObject {
|
|
463
|
+
* // ...
|
|
464
|
+
* }
|
|
465
|
+
* export const Counter = wrapDurableObjectClass(BaseCounter); // or decorate in place
|
|
466
|
+
*/
|
|
467
|
+
export declare function wrapDurableObjectClass<C extends {
|
|
468
|
+
readonly prototype: object;
|
|
469
|
+
}>(cls: C, opts?: InstrumentClassesOpts): C;
|
|
470
|
+
/**
|
|
471
|
+
* Decorate a Cloudflare Workflows entrypoint class so its `run(event, step)`
|
|
472
|
+
* emits a `workflow run` INTERNAL span with workflow identity/schedule metadata
|
|
473
|
+
* (never payload content), and the handed-out
|
|
474
|
+
* step object's methods become traced versions (see {@link wrapWorkflowStep}):
|
|
475
|
+
* `step.do(name, fn)` → INTERNAL span named `step <name>` with success/error
|
|
476
|
+
* status (step retries manifest as whole-run replays by the engine and are not
|
|
477
|
+
* observable at this layer, so no retry attribute is emitted), and
|
|
478
|
+
* sleep/sleepUntil/waitForEvent/waitForName → short marker spans.
|
|
479
|
+
*
|
|
480
|
+
* Every completed run schedules flushHeystack() via the entrypoint state's
|
|
481
|
+
* `waitUntil` so exports survive isolate teardown.
|
|
482
|
+
*/
|
|
483
|
+
export declare function wrapWorkflowEntrypointClass<C extends {
|
|
484
|
+
readonly prototype: object;
|
|
485
|
+
}>(cls: C, opts?: InstrumentClassesOpts): C;
|
|
415
486
|
/**
|
|
416
487
|
* Run `fn` inside a new child span named `name`. The span is automatically
|
|
417
488
|
* parented to the currently-active span (via `context.active()`), started
|