autotel 4.1.0 → 4.2.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/dist/auto.cjs +5 -3
- package/dist/auto.cjs.map +1 -1
- package/dist/auto.js +3 -3
- package/dist/auto.js.map +1 -1
- package/dist/chunk-C_NdSu1c.cjs +34 -0
- package/dist/correlation-id.cjs +1 -1
- package/dist/correlation-id.d.cts.map +1 -1
- package/dist/correlation-id.d.ts.map +1 -1
- package/dist/correlation-id.js +1 -1
- package/dist/decorators.cjs +1 -1
- package/dist/decorators.js +1 -1
- package/dist/{event-ByBTV9M2.js → event-531asIM6.js} +4 -4
- package/dist/{event-ByBTV9M2.js.map → event-531asIM6.js.map} +1 -1
- package/dist/{event-BhHREDJk.cjs → event-CcZYwp50.cjs} +4 -4
- package/dist/{event-BhHREDJk.cjs.map → event-CcZYwp50.cjs.map} +1 -1
- package/dist/event.cjs +1 -1
- package/dist/event.js +1 -1
- package/dist/{functional-zpzNLhky.cjs → functional-C8B0Qa7o.cjs} +10 -7
- package/dist/functional-C8B0Qa7o.cjs.map +1 -0
- package/dist/{functional-DtI0u4vx.js → functional-r-AUIRy_.js} +9 -9
- package/dist/functional-r-AUIRy_.js.map +1 -0
- package/dist/functional.cjs +1 -1
- package/dist/functional.js +1 -1
- package/dist/http.cjs +1 -1
- package/dist/http.js +1 -1
- package/dist/index.cjs +15 -13
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +14 -14
- package/dist/index.js.map +1 -1
- package/dist/{init-D-jnNMix.js → init-BS2JVkrL.js} +2 -2
- package/dist/{init-D-jnNMix.js.map → init-BS2JVkrL.js.map} +1 -1
- package/dist/{init-BX7AmFRl.cjs → init-BXiuPK6j.cjs} +3 -3
- package/dist/{init-BX7AmFRl.cjs.map → init-BXiuPK6j.cjs.map} +1 -1
- package/dist/instrumentation.cjs +2 -2
- package/dist/instrumentation.js +2 -2
- package/dist/logger.cjs +236 -8
- package/dist/logger.cjs.map +1 -0
- package/dist/messaging.cjs +1 -1
- package/dist/messaging.js +1 -1
- package/dist/{node-require-DF5QBX6z.cjs → node-require-CZ_PU448.cjs} +6 -4
- package/dist/node-require-CZ_PU448.cjs.map +1 -0
- package/dist/{node-require-Db1oDpLj.js → node-require-vROmTeJ8.js} +5 -5
- package/dist/node-require-vROmTeJ8.js.map +1 -0
- package/dist/{operation-context-C-2hmmtP.js → operation-context-CKBoA4Qy.js} +3 -3
- package/dist/operation-context-CKBoA4Qy.js.map +1 -0
- package/dist/{operation-context-n4_obUwq.cjs → operation-context-D6LDf4W_.cjs} +3 -1
- package/dist/operation-context-D6LDf4W_.cjs.map +1 -0
- package/dist/register.cjs +3 -1
- package/dist/register.cjs.map +1 -1
- package/dist/register.js +2 -2
- package/dist/register.js.map +1 -1
- package/dist/semantic-helpers.cjs +1 -1
- package/dist/semantic-helpers.js +1 -1
- package/dist/{stable-hash-Cg5cT34Q.js → stable-hash-ChFBIhNt.js} +3 -3
- package/dist/stable-hash-ChFBIhNt.js.map +1 -0
- package/dist/{stable-hash-BNTMrmdB.cjs → stable-hash-brKISGf1.cjs} +4 -2
- package/dist/stable-hash-brKISGf1.cjs.map +1 -0
- package/dist/trace-context-Cijqoi6e.d.cts.map +1 -1
- package/dist/trace-context-Cijqoi6e.d.ts.map +1 -1
- package/dist/trace-helpers.cjs +1 -1
- package/dist/trace-helpers.js +1 -1
- package/dist/{track-wc0HafS_.js → track-COUuU48p.js} +5 -5
- package/dist/track-COUuU48p.js.map +1 -0
- package/dist/{track-D59FfpL0.cjs → track-Cb3Q4QmS.cjs} +4 -2
- package/dist/track-Cb3Q4QmS.cjs.map +1 -0
- package/dist/validate.cjs +1 -1
- package/dist/validate.js +1 -1
- package/dist/webhook.cjs +1 -1
- package/dist/webhook.js +1 -1
- package/dist/workflow-distributed.cjs +1 -1
- package/dist/workflow-distributed.js +1 -1
- package/dist/workflow.cjs +3 -1
- package/dist/workflow.cjs.map +1 -1
- package/dist/workflow.d.cts.map +1 -1
- package/dist/workflow.d.ts.map +1 -1
- package/dist/workflow.js +3 -3
- package/dist/workflow.js.map +1 -1
- package/dist/yaml-config.cjs +233 -4
- package/dist/yaml-config.cjs.map +1 -0
- package/dist/yaml-config.d.cts.map +1 -1
- package/dist/yaml-config.d.ts.map +1 -1
- package/dist/yaml-config.js +8 -7
- package/dist/yaml-config.js.map +1 -1
- package/package.json +1 -2
- package/dist/functional-DtI0u4vx.js.map +0 -1
- package/dist/functional-zpzNLhky.cjs.map +0 -1
- package/dist/logger-thMPLpOG.cjs +0 -487
- package/dist/logger-thMPLpOG.cjs.map +0 -1
- package/dist/node-require-DF5QBX6z.cjs.map +0 -1
- package/dist/node-require-Db1oDpLj.js.map +0 -1
- package/dist/operation-context-C-2hmmtP.js.map +0 -1
- package/dist/operation-context-n4_obUwq.cjs.map +0 -1
- package/dist/stable-hash-BNTMrmdB.cjs.map +0 -1
- package/dist/stable-hash-Cg5cT34Q.js.map +0 -1
- package/dist/track-D59FfpL0.cjs.map +0 -1
- package/dist/track-wc0HafS_.js.map +0 -1
- package/dist/yaml-config-Ck2uB0Dp.cjs +0 -273
- package/dist/yaml-config-Ck2uB0Dp.cjs.map +0 -1
- package/src/attribute-redacting-processor.test.ts +0 -763
- package/src/attribute-redacting-processor.ts +0 -621
- package/src/attributes/attachers.ts +0 -161
- package/src/attributes/builders.ts +0 -529
- package/src/attributes/domains.ts +0 -42
- package/src/attributes/index.ts +0 -81
- package/src/attributes/registry.ts +0 -323
- package/src/attributes/types.ts +0 -211
- package/src/attributes/utils.ts +0 -64
- package/src/attributes/validators.ts +0 -266
- package/src/attributes.test.ts +0 -292
- package/src/auto.ts +0 -67
- package/src/autotel-logger.test.ts +0 -548
- package/src/autotel-logger.ts +0 -364
- package/src/baggage-span-processor.test.ts +0 -202
- package/src/baggage-span-processor.ts +0 -100
- package/src/business-baggage.test.ts +0 -500
- package/src/business-baggage.ts +0 -669
- package/src/circuit-breaker.test.ts +0 -341
- package/src/circuit-breaker.ts +0 -184
- package/src/config.test.ts +0 -94
- package/src/config.ts +0 -172
- package/src/correlated-events.test.ts +0 -151
- package/src/correlated-events.ts +0 -47
- package/src/correlation-id.test.ts +0 -163
- package/src/correlation-id.ts +0 -206
- package/src/db.test.ts +0 -252
- package/src/db.ts +0 -447
- package/src/decorators.test.ts +0 -153
- package/src/decorators.ts +0 -188
- package/src/define-event.test.ts +0 -41
- package/src/define-event.ts +0 -58
- package/src/devtools.ts +0 -60
- package/src/drain-pipeline.test.ts +0 -68
- package/src/drain-pipeline.ts +0 -199
- package/src/drain-toolkit.test.ts +0 -113
- package/src/drain-toolkit.ts +0 -129
- package/src/enricher-toolkit.test.ts +0 -67
- package/src/enricher-toolkit.ts +0 -79
- package/src/enrichers.test.ts +0 -150
- package/src/enrichers.ts +0 -145
- package/src/env-config.test.ts +0 -323
- package/src/env-config.ts +0 -309
- package/src/error-catalog.test.ts +0 -133
- package/src/error-catalog.ts +0 -262
- package/src/event-queue.test.ts +0 -864
- package/src/event-queue.ts +0 -699
- package/src/event-subscriber.ts +0 -262
- package/src/event-testing.ts +0 -197
- package/src/event.test.ts +0 -1104
- package/src/event.ts +0 -988
- package/src/events-config.ts +0 -235
- package/src/exporters.ts +0 -165
- package/src/filtering-span-processor.test.ts +0 -281
- package/src/filtering-span-processor.ts +0 -111
- package/src/flatten-attributes.test.ts +0 -76
- package/src/flatten-attributes.ts +0 -80
- package/src/functional.strict-types.typecheck.ts +0 -53
- package/src/functional.test.ts +0 -1464
- package/src/functional.ts +0 -2539
- package/src/functional.types.test.ts +0 -135
- package/src/hook.mjs +0 -15
- package/src/http.test.ts +0 -485
- package/src/http.ts +0 -424
- package/src/index.ts +0 -433
- package/src/init-auto-redactor.test.ts +0 -53
- package/src/init-redactor.test.ts +0 -8
- package/src/init.customization.test.ts +0 -665
- package/src/init.integrations.test.ts +0 -399
- package/src/init.openllmetry.test.ts +0 -194
- package/src/init.protocol.test.ts +0 -215
- package/src/init.ts +0 -2439
- package/src/instrumentation.test.ts +0 -108
- package/src/instrumentation.ts +0 -319
- package/src/logger.test.ts +0 -125
- package/src/logger.ts +0 -341
- package/src/messaging-adapters.test.ts +0 -595
- package/src/messaging-adapters.ts +0 -583
- package/src/messaging-testing.test.ts +0 -573
- package/src/messaging-testing.ts +0 -935
- package/src/messaging.test.ts +0 -1646
- package/src/messaging.ts +0 -2245
- package/src/metric-helpers.ts +0 -47
- package/src/metric-testing.ts +0 -197
- package/src/metric.ts +0 -446
- package/src/metrics.test.ts +0 -241
- package/src/node-require.ts +0 -123
- package/src/operation-context.ts +0 -93
- package/src/parse-error.test.ts +0 -73
- package/src/parse-error.ts +0 -112
- package/src/posthog-logs.test.ts +0 -115
- package/src/posthog-logs.ts +0 -77
- package/src/pretty-console-exporter.test.ts +0 -545
- package/src/pretty-console-exporter.ts +0 -413
- package/src/pretty-log-formatter.test.ts +0 -123
- package/src/pretty-log-formatter.ts +0 -210
- package/src/processors/canonical-log-line-processor.test.ts +0 -523
- package/src/processors/canonical-log-line-processor.ts +0 -396
- package/src/processors.ts +0 -152
- package/src/rate-limiter.test.ts +0 -199
- package/src/rate-limiter.ts +0 -98
- package/src/redact-values.test.ts +0 -90
- package/src/redact-values.ts +0 -34
- package/src/register.ts +0 -37
- package/src/request-logger.test.ts +0 -545
- package/src/request-logger.ts +0 -342
- package/src/sampling.test.ts +0 -1060
- package/src/sampling.ts +0 -737
- package/src/security-schema.test.ts +0 -45
- package/src/security-schema.ts +0 -107
- package/src/semantic-conventions.ts +0 -15
- package/src/semantic-helpers.test.ts +0 -226
- package/src/semantic-helpers.ts +0 -438
- package/src/shutdown.test.ts +0 -364
- package/src/shutdown.ts +0 -246
- package/src/span-name-normalizer.test.ts +0 -377
- package/src/span-name-normalizer.ts +0 -213
- package/src/stable-hash.ts +0 -27
- package/src/structured-error.test.ts +0 -191
- package/src/structured-error.ts +0 -157
- package/src/stub.integration.test.ts +0 -361
- package/src/tail-sampling-processor.test.ts +0 -230
- package/src/tail-sampling-processor.ts +0 -55
- package/src/test-span-collector.test.ts +0 -234
- package/src/test-span-collector.ts +0 -150
- package/src/testing.ts +0 -705
- package/src/trace-context.test.ts +0 -73
- package/src/trace-context.ts +0 -567
- package/src/trace-helpers.new.test.ts +0 -278
- package/src/trace-helpers.test.ts +0 -290
- package/src/trace-helpers.ts +0 -710
- package/src/trace-hybrid.test.ts +0 -42
- package/src/trace-hybrid.ts +0 -37
- package/src/tracer-provider.test.ts +0 -183
- package/src/tracer-provider.ts +0 -266
- package/src/track.test.ts +0 -154
- package/src/track.ts +0 -216
- package/src/validate.test.ts +0 -287
- package/src/validate.ts +0 -307
- package/src/validation-attributes.ts +0 -43
- package/src/validation.test.ts +0 -330
- package/src/validation.ts +0 -246
- package/src/variable-name-inference.test.ts +0 -178
- package/src/variable-name-inference.ts +0 -242
- package/src/webhook.test.ts +0 -649
- package/src/webhook.ts +0 -637
- package/src/workflow-distributed.test.ts +0 -786
- package/src/workflow-distributed.ts +0 -916
- package/src/workflow.async-safety.integration.test.ts +0 -345
- package/src/workflow.test.ts +0 -647
- package/src/workflow.ts +0 -810
- package/src/yaml-config.test.ts +0 -373
- package/src/yaml-config.ts +0 -351
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest';
|
|
2
|
-
import { enterOrRun } from './trace-context';
|
|
3
|
-
|
|
4
|
-
type Box<T> = { value: T };
|
|
5
|
-
|
|
6
|
-
function createFakeStorage<T>(initialValue?: T) {
|
|
7
|
-
let currentStore =
|
|
8
|
-
initialValue === undefined ? undefined : { value: initialValue };
|
|
9
|
-
const runCalls: Array<Box<T>> = [];
|
|
10
|
-
const enterWithCalls: Array<Box<T>> = [];
|
|
11
|
-
|
|
12
|
-
const storage = {
|
|
13
|
-
getStore() {
|
|
14
|
-
return currentStore;
|
|
15
|
-
},
|
|
16
|
-
run(store: Box<T>, fn: () => void) {
|
|
17
|
-
runCalls.push(store);
|
|
18
|
-
const previousStore = currentStore;
|
|
19
|
-
currentStore = store;
|
|
20
|
-
try {
|
|
21
|
-
fn();
|
|
22
|
-
} finally {
|
|
23
|
-
currentStore = previousStore;
|
|
24
|
-
}
|
|
25
|
-
},
|
|
26
|
-
enterWith(store: Box<T>) {
|
|
27
|
-
enterWithCalls.push(store);
|
|
28
|
-
currentStore = store;
|
|
29
|
-
},
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
return {
|
|
33
|
-
enterWithCalls,
|
|
34
|
-
runCalls,
|
|
35
|
-
storage: storage as unknown as {
|
|
36
|
-
enterWith?: (store: Box<T>) => void;
|
|
37
|
-
getStore: () => Box<T> | undefined;
|
|
38
|
-
run: (store: Box<T>, fn: () => void) => void;
|
|
39
|
-
},
|
|
40
|
-
};
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
describe('enterOrRun', () => {
|
|
44
|
-
it('mutates the existing store when already inside a run scope', () => {
|
|
45
|
-
const { storage } = createFakeStorage('outer');
|
|
46
|
-
|
|
47
|
-
enterOrRun(storage as never, 'updated');
|
|
48
|
-
|
|
49
|
-
expect(storage.getStore()?.value).toBe('updated');
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
it('falls back to run() when enterWith throws', () => {
|
|
53
|
-
const { runCalls, storage } = createFakeStorage<string>();
|
|
54
|
-
storage.enterWith = () => {
|
|
55
|
-
throw new Error('enterWith not supported');
|
|
56
|
-
};
|
|
57
|
-
|
|
58
|
-
enterOrRun(storage as never, 'worker-value');
|
|
59
|
-
|
|
60
|
-
expect(runCalls).toHaveLength(1);
|
|
61
|
-
expect(runCalls[0]?.value).toBe('worker-value');
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
it('prefers enterWith() when no store exists and the runtime supports it', () => {
|
|
65
|
-
const { enterWithCalls, storage } = createFakeStorage<string>();
|
|
66
|
-
|
|
67
|
-
enterOrRun(storage as never, 'node-value');
|
|
68
|
-
|
|
69
|
-
expect(enterWithCalls).toHaveLength(1);
|
|
70
|
-
expect(enterWithCalls[0]?.value).toBe('node-value');
|
|
71
|
-
expect(storage.getStore()?.value).toBe('node-value');
|
|
72
|
-
});
|
|
73
|
-
});
|
package/src/trace-context.ts
DELETED
|
@@ -1,567 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Trace context types and utilities
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import type {
|
|
6
|
-
Span,
|
|
7
|
-
SpanStatusCode,
|
|
8
|
-
BaggageEntry,
|
|
9
|
-
Context,
|
|
10
|
-
Link,
|
|
11
|
-
} from '@opentelemetry/api';
|
|
12
|
-
import { context, propagation } from '@opentelemetry/api';
|
|
13
|
-
import { AsyncLocalStorage } from 'node:async_hooks';
|
|
14
|
-
import { recordStructuredError } from './structured-error';
|
|
15
|
-
import { track } from './track';
|
|
16
|
-
|
|
17
|
-
type AsyncLocalBox<T> = {
|
|
18
|
-
value: T;
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* AsyncLocalStorage for storing the active context with baggage
|
|
23
|
-
* This allows setters to update the context and have it persist
|
|
24
|
-
*/
|
|
25
|
-
const contextStorage = new AsyncLocalStorage<AsyncLocalBox<Context>>();
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Get the context storage instance (for initialization in functional.ts)
|
|
29
|
-
*/
|
|
30
|
-
export function getContextStorage(): AsyncLocalStorage<AsyncLocalBox<Context>> {
|
|
31
|
-
return contextStorage;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Get the active context, checking our stored context first
|
|
36
|
-
* This ensures baggage setters work with OpenTelemetry's propagation
|
|
37
|
-
*/
|
|
38
|
-
export function getActiveContextWithBaggage(): Context {
|
|
39
|
-
// Check stored context first (from setters), then fall back to active context
|
|
40
|
-
// This ensures ctx.setBaggage() changes are visible to OpenTelemetry operations
|
|
41
|
-
const stored = contextStorage.getStore()?.value;
|
|
42
|
-
return stored ?? context.active();
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* Set a value in AsyncLocalStorage, preferring enterWith() when available
|
|
47
|
-
* (Node.js) and falling back to run() for environments that only support
|
|
48
|
-
* run() (e.g. Cloudflare Workers).
|
|
49
|
-
*
|
|
50
|
-
* On runtimes without enterWith() we mutate the existing run() scope when one
|
|
51
|
-
* exists. This is what allows baggage/correlation updates to remain visible
|
|
52
|
-
* for the rest of the traced callback in Workers.
|
|
53
|
-
*/
|
|
54
|
-
export function enterOrRun<T>(
|
|
55
|
-
storage: AsyncLocalStorage<AsyncLocalBox<T>>,
|
|
56
|
-
value: T,
|
|
57
|
-
): void {
|
|
58
|
-
const existingStore = storage.getStore();
|
|
59
|
-
if (existingStore) {
|
|
60
|
-
existingStore.value = value;
|
|
61
|
-
return;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
const boxedValue = { value };
|
|
65
|
-
try {
|
|
66
|
-
storage.enterWith(boxedValue);
|
|
67
|
-
} catch {
|
|
68
|
-
// Cloudflare Workers define enterWith but throw at runtime
|
|
69
|
-
storage.run(boxedValue, () => {});
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* Try to keep OpenTelemetry's context manager in sync with baggage updates
|
|
75
|
-
*/
|
|
76
|
-
type ContextManagerLike = {
|
|
77
|
-
with?: (ctx: Context, fn: () => void) => void;
|
|
78
|
-
_asyncLocalStorage?: { enterWith?: (ctx: Context) => void };
|
|
79
|
-
};
|
|
80
|
-
|
|
81
|
-
function updateActiveContext(newContext: Context): void {
|
|
82
|
-
// Update our storage first so any helper reads see the new context
|
|
83
|
-
enterOrRun(contextStorage, newContext);
|
|
84
|
-
|
|
85
|
-
const contextWithManager = context as unknown as {
|
|
86
|
-
_getContextManager?: () => ContextManagerLike;
|
|
87
|
-
};
|
|
88
|
-
|
|
89
|
-
const manager = contextWithManager._getContextManager?.();
|
|
90
|
-
if (!manager) return;
|
|
91
|
-
|
|
92
|
-
const asyncLocal =
|
|
93
|
-
(manager as { _asyncLocalStorage?: { enterWith?: (ctx: Context) => void } })
|
|
94
|
-
._asyncLocalStorage ?? undefined;
|
|
95
|
-
if (asyncLocal?.enterWith) {
|
|
96
|
-
asyncLocal.enterWith(newContext);
|
|
97
|
-
return;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
if (typeof manager.with === 'function') {
|
|
101
|
-
manager.with(newContext, () => {});
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
/**
|
|
106
|
-
* Base trace context containing trace identifiers
|
|
107
|
-
*/
|
|
108
|
-
export interface TraceContextBase {
|
|
109
|
-
traceId: string;
|
|
110
|
-
spanId: string;
|
|
111
|
-
correlationId: string;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
/**
|
|
115
|
-
* Attribute value types following OpenTelemetry specification.
|
|
116
|
-
* Supports primitive values and arrays of homogeneous primitives.
|
|
117
|
-
*/
|
|
118
|
-
export type AttributeValue =
|
|
119
|
-
| string
|
|
120
|
-
| number
|
|
121
|
-
| boolean
|
|
122
|
-
| string[]
|
|
123
|
-
| number[]
|
|
124
|
-
| boolean[];
|
|
125
|
-
|
|
126
|
-
/**
|
|
127
|
-
* Span methods available on trace context
|
|
128
|
-
*/
|
|
129
|
-
export interface SpanMethods {
|
|
130
|
-
/** Set a single attribute on the span */
|
|
131
|
-
setAttribute(key: string, value: AttributeValue): void;
|
|
132
|
-
/** Set multiple attributes on the span */
|
|
133
|
-
setAttributes(attrs: Record<string, AttributeValue>): void;
|
|
134
|
-
/** Set the status of the span */
|
|
135
|
-
setStatus(status: { code: SpanStatusCode; message?: string }): void;
|
|
136
|
-
/** Add a link to another span */
|
|
137
|
-
addLink(link: Link): void;
|
|
138
|
-
/** Add multiple links to other spans */
|
|
139
|
-
addLinks(links: Link[]): void;
|
|
140
|
-
/** Update the span name dynamically */
|
|
141
|
-
updateName(name: string): void;
|
|
142
|
-
/** Check if the span is recording */
|
|
143
|
-
isRecording(): boolean;
|
|
144
|
-
/**
|
|
145
|
-
* Record an error on the span: sets ERROR status, structured `error.*`
|
|
146
|
-
* attributes (including `why`/`fix`/`link` from `createStructuredError`),
|
|
147
|
-
* and during the OTel Span Event API back-compat window also records the
|
|
148
|
-
* exception via the legacy span event API.
|
|
149
|
-
*
|
|
150
|
-
* Replaces the deprecated `recordException` (OTEP 4430). Accepts `unknown`
|
|
151
|
-
* so it can be called directly with the value caught from a `catch` block.
|
|
152
|
-
*/
|
|
153
|
-
recordError(error: unknown): void;
|
|
154
|
-
/**
|
|
155
|
-
* Emit a tracked event correlated to this span. Equivalent to the standalone
|
|
156
|
-
* `track(event, data)` but reads naturally on `ctx`. Replaces the deprecated
|
|
157
|
-
* `ctx.addEvent` (OTEP 4430) — events become correlated logs rather than
|
|
158
|
-
* span events.
|
|
159
|
-
*/
|
|
160
|
-
track<Events extends Record<string, unknown> = Record<string, unknown>>(
|
|
161
|
-
event: keyof Events & string,
|
|
162
|
-
data?: Events[keyof Events & string],
|
|
163
|
-
): void;
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
/**
|
|
167
|
-
* Baggage methods available on trace context
|
|
168
|
-
*
|
|
169
|
-
* @template TBaggage - Optional type for typed baggage (defaults to undefined for untyped)
|
|
170
|
-
*/
|
|
171
|
-
export interface BaggageMethods<
|
|
172
|
-
TBaggage extends Record<string, unknown> | undefined = undefined,
|
|
173
|
-
> {
|
|
174
|
-
/**
|
|
175
|
-
* Get a baggage entry by key
|
|
176
|
-
* @param key - Baggage key
|
|
177
|
-
* @returns Baggage entry value or undefined
|
|
178
|
-
*/
|
|
179
|
-
getBaggage(key: string): string | undefined;
|
|
180
|
-
|
|
181
|
-
/**
|
|
182
|
-
* Set a baggage entry
|
|
183
|
-
*
|
|
184
|
-
* Note: OpenTelemetry contexts are immutable. For proper scoping across async
|
|
185
|
-
* boundaries, use withBaggage() instead. This method updates baggage in the
|
|
186
|
-
* current context which may not propagate to all child operations.
|
|
187
|
-
*
|
|
188
|
-
* @param key - Baggage key
|
|
189
|
-
* @param value - Baggage value
|
|
190
|
-
* @returns The baggage value that was set (for chaining)
|
|
191
|
-
*
|
|
192
|
-
* @example Using withBaggage() (recommended)
|
|
193
|
-
* ```typescript
|
|
194
|
-
* await withBaggage({ baggage: { 'key': 'value' }, fn: async () => {
|
|
195
|
-
* // Baggage is available here and in child spans
|
|
196
|
-
* });
|
|
197
|
-
* ```
|
|
198
|
-
*/
|
|
199
|
-
setBaggage(key: string, value: string): string;
|
|
200
|
-
|
|
201
|
-
/**
|
|
202
|
-
* Delete a baggage entry
|
|
203
|
-
*
|
|
204
|
-
* Note: OpenTelemetry contexts are immutable. For proper scoping across async
|
|
205
|
-
* boundaries, use withBaggage() with only the entries you want instead.
|
|
206
|
-
*
|
|
207
|
-
* @param key - Baggage key
|
|
208
|
-
*/
|
|
209
|
-
deleteBaggage(key: string): void;
|
|
210
|
-
|
|
211
|
-
/**
|
|
212
|
-
* Get all baggage entries
|
|
213
|
-
* @returns Map of all baggage entries
|
|
214
|
-
*/
|
|
215
|
-
getAllBaggage(): Map<string, BaggageEntry>;
|
|
216
|
-
|
|
217
|
-
/**
|
|
218
|
-
* Get typed baggage (only available when TBaggage is defined)
|
|
219
|
-
* This is used internally by defineBaggageSchema()
|
|
220
|
-
*
|
|
221
|
-
* @internal
|
|
222
|
-
*/
|
|
223
|
-
getTypedBaggage?: TBaggage extends Record<string, unknown>
|
|
224
|
-
? <T extends TBaggage>(namespace?: string) => Partial<T> | undefined
|
|
225
|
-
: never;
|
|
226
|
-
|
|
227
|
-
/**
|
|
228
|
-
* Set typed baggage (only available when TBaggage is defined)
|
|
229
|
-
* This is used internally by defineBaggageSchema()
|
|
230
|
-
*
|
|
231
|
-
* @internal
|
|
232
|
-
*/
|
|
233
|
-
setTypedBaggage?: TBaggage extends Record<string, unknown>
|
|
234
|
-
? <T extends TBaggage>(
|
|
235
|
-
namespace: string | undefined,
|
|
236
|
-
value: Partial<T>,
|
|
237
|
-
) => void
|
|
238
|
-
: never;
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
/**
|
|
242
|
-
* Complete trace context that merges base context, span methods, and baggage methods
|
|
243
|
-
*
|
|
244
|
-
* This is the ctx parameter passed to factory functions in trace().
|
|
245
|
-
* It provides access to trace IDs, span manipulation methods, and baggage operations.
|
|
246
|
-
*
|
|
247
|
-
* @template TBaggage - Optional type for typed baggage support
|
|
248
|
-
*
|
|
249
|
-
* @example Untyped (default)
|
|
250
|
-
* ```typescript
|
|
251
|
-
* export const handler = trace((ctx) => async () => {
|
|
252
|
-
* ctx.getBaggage('key'); // returns string | undefined
|
|
253
|
-
* });
|
|
254
|
-
* ```
|
|
255
|
-
*
|
|
256
|
-
* @example Typed baggage
|
|
257
|
-
* ```typescript
|
|
258
|
-
* type TenantBaggage = { tenantId: string; region?: string };
|
|
259
|
-
*
|
|
260
|
-
* export const handler = trace<TenantBaggage>((ctx) => async () => {
|
|
261
|
-
* // Use typed schema helper for type-safe access
|
|
262
|
-
* const schema = defineBaggageSchema<TenantBaggage>('tenant');
|
|
263
|
-
* const tenant = schema.get(ctx); // Partial<TenantBaggage> | undefined
|
|
264
|
-
* });
|
|
265
|
-
* ```
|
|
266
|
-
*/
|
|
267
|
-
export type TraceContext<
|
|
268
|
-
TBaggage extends Record<string, unknown> | undefined = undefined,
|
|
269
|
-
> = TraceContextBase & SpanMethods & BaggageMethods<TBaggage>;
|
|
270
|
-
|
|
271
|
-
/**
|
|
272
|
-
* Create a TraceContext from an OpenTelemetry Span
|
|
273
|
-
*
|
|
274
|
-
* This utility extracts trace context information from a span
|
|
275
|
-
* and provides span manipulation methods and baggage operations in a consistent format.
|
|
276
|
-
*
|
|
277
|
-
* Note: Baggage methods always operate on the currently active context,
|
|
278
|
-
* which may differ from the context when createTraceContext was called.
|
|
279
|
-
*/
|
|
280
|
-
export function createTraceContext<
|
|
281
|
-
TBaggage extends Record<string, unknown> | undefined = undefined,
|
|
282
|
-
>(span: Span): TraceContext<TBaggage> {
|
|
283
|
-
const spanContext = span.spanContext();
|
|
284
|
-
|
|
285
|
-
// Store the current active context in AsyncLocalStorage so baggage setters can update it
|
|
286
|
-
// This ensures ctx.setBaggage() changes persist and are visible to OpenTelemetry operations
|
|
287
|
-
// IMPORTANT: Only initialize if not already set (preserve baggage updates from parent spans)
|
|
288
|
-
const existingStored = contextStorage.getStore()?.value;
|
|
289
|
-
if (!existingStored) {
|
|
290
|
-
const activeContext = context.active();
|
|
291
|
-
enterOrRun(contextStorage, activeContext);
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
// Baggage helpers that always use the current active context
|
|
295
|
-
// This ensures baggage operations work correctly even if context changes
|
|
296
|
-
const baggageHelpers: BaggageMethods<TBaggage> = {
|
|
297
|
-
getBaggage(key: string): string | undefined {
|
|
298
|
-
// Check active context first (from withBaggage, context.with, etc.)
|
|
299
|
-
// Then check stored context (from setters)
|
|
300
|
-
// This ensures both withBaggage() and ctx.setBaggage() work correctly
|
|
301
|
-
const activeCtx = context.active();
|
|
302
|
-
let baggage = propagation.getBaggage(activeCtx);
|
|
303
|
-
if (!baggage) {
|
|
304
|
-
const storedContext = contextStorage.getStore()?.value;
|
|
305
|
-
if (storedContext) {
|
|
306
|
-
baggage = propagation.getBaggage(storedContext);
|
|
307
|
-
}
|
|
308
|
-
}
|
|
309
|
-
return baggage?.getEntry(key)?.value;
|
|
310
|
-
},
|
|
311
|
-
|
|
312
|
-
setBaggage(key: string, value: string): string {
|
|
313
|
-
// OpenTelemetry contexts are immutable, so we create a new context with updated baggage
|
|
314
|
-
// Check active context first (may have baggage from withBaggage), then stored context
|
|
315
|
-
const activeCtx = context.active();
|
|
316
|
-
const storedContext = contextStorage.getStore()?.value;
|
|
317
|
-
const currentContext = storedContext ?? activeCtx;
|
|
318
|
-
const baggage =
|
|
319
|
-
propagation.getBaggage(currentContext) ?? propagation.createBaggage();
|
|
320
|
-
const updated = baggage.setEntry(key, { value });
|
|
321
|
-
const newContext = propagation.setBaggage(currentContext, updated);
|
|
322
|
-
|
|
323
|
-
updateActiveContext(newContext);
|
|
324
|
-
|
|
325
|
-
return value;
|
|
326
|
-
},
|
|
327
|
-
|
|
328
|
-
deleteBaggage(key: string): void {
|
|
329
|
-
// Check active context first, then stored context
|
|
330
|
-
const activeCtx = context.active();
|
|
331
|
-
const storedContext = contextStorage.getStore()?.value;
|
|
332
|
-
const currentContext = storedContext ?? activeCtx;
|
|
333
|
-
const baggage = propagation.getBaggage(currentContext);
|
|
334
|
-
if (baggage) {
|
|
335
|
-
const updated = baggage.removeEntry(key);
|
|
336
|
-
const newContext = propagation.setBaggage(currentContext, updated);
|
|
337
|
-
|
|
338
|
-
updateActiveContext(newContext);
|
|
339
|
-
}
|
|
340
|
-
},
|
|
341
|
-
|
|
342
|
-
getAllBaggage(): Map<string, BaggageEntry> {
|
|
343
|
-
// Check active context first, then stored context
|
|
344
|
-
const activeCtx = context.active();
|
|
345
|
-
let baggage = propagation.getBaggage(activeCtx);
|
|
346
|
-
if (!baggage) {
|
|
347
|
-
const storedContext = contextStorage.getStore()?.value;
|
|
348
|
-
if (storedContext) {
|
|
349
|
-
baggage = propagation.getBaggage(storedContext);
|
|
350
|
-
}
|
|
351
|
-
}
|
|
352
|
-
if (!baggage) {
|
|
353
|
-
return new Map();
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
// Convert baggage entries to a Map
|
|
357
|
-
const entries = new Map<string, BaggageEntry>();
|
|
358
|
-
for (const [key, entry] of baggage.getAllEntries()) {
|
|
359
|
-
entries.set(key, entry);
|
|
360
|
-
}
|
|
361
|
-
return entries;
|
|
362
|
-
},
|
|
363
|
-
|
|
364
|
-
// Typed baggage helpers (used by defineBaggageSchema)
|
|
365
|
-
getTypedBaggage: (<T extends Record<string, unknown>>(
|
|
366
|
-
namespace?: string,
|
|
367
|
-
) => {
|
|
368
|
-
// Check active context first, then stored context
|
|
369
|
-
const activeCtx = context.active();
|
|
370
|
-
let baggage = propagation.getBaggage(activeCtx);
|
|
371
|
-
if (!baggage) {
|
|
372
|
-
const storedContext = contextStorage.getStore()?.value;
|
|
373
|
-
if (storedContext) {
|
|
374
|
-
baggage = propagation.getBaggage(storedContext);
|
|
375
|
-
}
|
|
376
|
-
}
|
|
377
|
-
if (!baggage) return;
|
|
378
|
-
|
|
379
|
-
const prefix = namespace ? `${namespace}.` : '';
|
|
380
|
-
const result: Record<string, unknown> = {};
|
|
381
|
-
|
|
382
|
-
for (const [key, entry] of baggage.getAllEntries()) {
|
|
383
|
-
if (namespace && key.startsWith(prefix)) {
|
|
384
|
-
const fieldName = key.slice(prefix.length);
|
|
385
|
-
result[fieldName] = entry.value;
|
|
386
|
-
} else if (!namespace) {
|
|
387
|
-
result[key] = entry.value;
|
|
388
|
-
}
|
|
389
|
-
}
|
|
390
|
-
|
|
391
|
-
return Object.keys(result).length > 0
|
|
392
|
-
? (result as Partial<T>)
|
|
393
|
-
: undefined;
|
|
394
|
-
}) as TBaggage extends Record<string, unknown>
|
|
395
|
-
? <T extends TBaggage>(namespace?: string) => Partial<T> | undefined
|
|
396
|
-
: never,
|
|
397
|
-
|
|
398
|
-
setTypedBaggage: (<T extends Record<string, unknown>>(
|
|
399
|
-
namespace: string | undefined,
|
|
400
|
-
value: Partial<T>,
|
|
401
|
-
) => {
|
|
402
|
-
// Check active context first, then stored context
|
|
403
|
-
const activeCtx = context.active();
|
|
404
|
-
const storedContext = contextStorage.getStore()?.value;
|
|
405
|
-
const currentContext = storedContext ?? activeCtx;
|
|
406
|
-
let baggage =
|
|
407
|
-
propagation.getBaggage(currentContext) ?? propagation.createBaggage();
|
|
408
|
-
|
|
409
|
-
const prefix = namespace ? `${namespace}.` : '';
|
|
410
|
-
for (const [key, val] of Object.entries(value)) {
|
|
411
|
-
if (val !== undefined) {
|
|
412
|
-
const baggageKey = `${prefix}${key}`;
|
|
413
|
-
baggage = baggage.setEntry(baggageKey, { value: String(val) });
|
|
414
|
-
}
|
|
415
|
-
}
|
|
416
|
-
|
|
417
|
-
const newContext = propagation.setBaggage(currentContext, baggage);
|
|
418
|
-
updateActiveContext(newContext);
|
|
419
|
-
}) as TBaggage extends Record<string, unknown>
|
|
420
|
-
? <T extends TBaggage>(
|
|
421
|
-
namespace: string | undefined,
|
|
422
|
-
value: Partial<T>,
|
|
423
|
-
) => void
|
|
424
|
-
: never,
|
|
425
|
-
};
|
|
426
|
-
|
|
427
|
-
// `recordException` and `addEvent` are intentionally bound at runtime but
|
|
428
|
-
// omitted from the `SpanMethods` type. They exist solely so existing call
|
|
429
|
-
// sites keep working through the OTel Span Event API deprecation window
|
|
430
|
-
// (see MIGRATION.md). New code MUST go through `recordStructuredError`,
|
|
431
|
-
// `emitCorrelatedEvent`, or the request logger. The cast below is what hides
|
|
432
|
-
// these compatibility-only fields from the public type.
|
|
433
|
-
const traceCtx = {
|
|
434
|
-
traceId: spanContext.traceId,
|
|
435
|
-
spanId: spanContext.spanId,
|
|
436
|
-
correlationId: spanContext.traceId.slice(0, 16),
|
|
437
|
-
setAttribute: span.setAttribute.bind(span),
|
|
438
|
-
setAttributes: span.setAttributes.bind(span),
|
|
439
|
-
setStatus: span.setStatus.bind(span),
|
|
440
|
-
recordException: span.recordException.bind(span),
|
|
441
|
-
addEvent: span.addEvent.bind(span),
|
|
442
|
-
addLink: span.addLink.bind(span),
|
|
443
|
-
addLinks: span.addLinks.bind(span),
|
|
444
|
-
updateName: span.updateName.bind(span),
|
|
445
|
-
isRecording: span.isRecording.bind(span),
|
|
446
|
-
recordError: (error: unknown) => {
|
|
447
|
-
const err = error instanceof Error ? error : new Error(String(error));
|
|
448
|
-
recordStructuredError(traceCtx, err);
|
|
449
|
-
},
|
|
450
|
-
track: (event: string, data?: Record<string, unknown>) => {
|
|
451
|
-
track(event, data);
|
|
452
|
-
},
|
|
453
|
-
...baggageHelpers,
|
|
454
|
-
} as unknown as TraceContext<TBaggage>;
|
|
455
|
-
|
|
456
|
-
return traceCtx;
|
|
457
|
-
}
|
|
458
|
-
|
|
459
|
-
/**
|
|
460
|
-
* Define a typed baggage schema for type-safe baggage operations
|
|
461
|
-
*
|
|
462
|
-
* This helper provides a type-safe API for working with baggage entries.
|
|
463
|
-
* The namespace parameter is optional and prefixes all keys to avoid collisions.
|
|
464
|
-
*
|
|
465
|
-
* @template T - The baggage schema type (all fields are treated as optional)
|
|
466
|
-
* @param namespace - Optional namespace to prefix baggage keys
|
|
467
|
-
*
|
|
468
|
-
* @example Basic usage
|
|
469
|
-
* ```typescript
|
|
470
|
-
* type TenantBaggage = { tenantId: string; region?: string };
|
|
471
|
-
* const tenantBaggage = defineBaggageSchema<TenantBaggage>('tenant');
|
|
472
|
-
*
|
|
473
|
-
* export const handler = trace<TenantBaggage>((ctx) => async () => {
|
|
474
|
-
* // Get typed baggage
|
|
475
|
-
* const tenant = tenantBaggage.get(ctx);
|
|
476
|
-
* if (tenant?.tenantId) {
|
|
477
|
-
* console.log('Tenant:', tenant.tenantId);
|
|
478
|
-
* }
|
|
479
|
-
*
|
|
480
|
-
* // Set typed baggage
|
|
481
|
-
* tenantBaggage.set(ctx, { tenantId: 't1', region: 'us-east-1' });
|
|
482
|
-
* });
|
|
483
|
-
* ```
|
|
484
|
-
*
|
|
485
|
-
* @example With withBaggage helper
|
|
486
|
-
* ```typescript
|
|
487
|
-
* const tenantBaggage = defineBaggageSchema<TenantBaggage>('tenant');
|
|
488
|
-
*
|
|
489
|
-
* export const handler = trace<TenantBaggage>((ctx) => async () => {
|
|
490
|
-
* return await tenantBaggage.with(ctx, { tenantId: 't1' }, async () => {
|
|
491
|
-
* // Baggage is available here and in child spans
|
|
492
|
-
* const tenant = tenantBaggage.get(ctx);
|
|
493
|
-
* });
|
|
494
|
-
* });
|
|
495
|
-
* ```
|
|
496
|
-
*/
|
|
497
|
-
export function defineBaggageSchema<T extends Record<string, unknown>>(
|
|
498
|
-
namespace?: string,
|
|
499
|
-
) {
|
|
500
|
-
return {
|
|
501
|
-
/**
|
|
502
|
-
* Get typed baggage from context
|
|
503
|
-
* @param ctx - Trace context
|
|
504
|
-
* @returns Partial baggage object or undefined if no baggage is set
|
|
505
|
-
*/
|
|
506
|
-
get: (ctx: TraceContext<T>): Partial<T> | undefined => {
|
|
507
|
-
if (!ctx.getTypedBaggage) return undefined;
|
|
508
|
-
return ctx.getTypedBaggage<T>(namespace);
|
|
509
|
-
},
|
|
510
|
-
|
|
511
|
-
/**
|
|
512
|
-
* Set typed baggage in context
|
|
513
|
-
*
|
|
514
|
-
* Note: For proper scoping across async boundaries, use the `with` method instead
|
|
515
|
-
*
|
|
516
|
-
* @param ctx - Trace context
|
|
517
|
-
* @param value - Partial baggage object to set
|
|
518
|
-
*/
|
|
519
|
-
set: (ctx: TraceContext<T>, value: Partial<T>): void => {
|
|
520
|
-
if (!ctx.setTypedBaggage) return;
|
|
521
|
-
ctx.setTypedBaggage<T>(namespace, value);
|
|
522
|
-
},
|
|
523
|
-
|
|
524
|
-
/**
|
|
525
|
-
* Run a function with typed baggage properly scoped
|
|
526
|
-
*
|
|
527
|
-
* This is the recommended way to set baggage as it ensures proper
|
|
528
|
-
* scoping across async boundaries.
|
|
529
|
-
*
|
|
530
|
-
* @param ctx - Trace context (can be omitted, will use active context)
|
|
531
|
-
* @param value - Partial baggage object to set
|
|
532
|
-
* @param fn - Function to execute with the baggage
|
|
533
|
-
*/
|
|
534
|
-
with: <R>(
|
|
535
|
-
ctxOrValue: TraceContext<T> | Partial<T>,
|
|
536
|
-
valueOrFn: Partial<T> | (() => R | Promise<R>),
|
|
537
|
-
maybeFn?: () => R | Promise<R>,
|
|
538
|
-
): R | Promise<R> => {
|
|
539
|
-
// Support both with(ctx, value, fn) and with(value, fn)
|
|
540
|
-
const value = maybeFn
|
|
541
|
-
? (valueOrFn as Partial<T>)
|
|
542
|
-
: (ctxOrValue as Partial<T>);
|
|
543
|
-
const fn = maybeFn || (valueOrFn as () => R | Promise<R>);
|
|
544
|
-
|
|
545
|
-
// Serialize typed baggage to flat key-value pairs
|
|
546
|
-
const prefix = namespace ? `${namespace}.` : '';
|
|
547
|
-
const flatBaggage: Record<string, string> = {};
|
|
548
|
-
for (const [key, val] of Object.entries(value)) {
|
|
549
|
-
if (val !== undefined) {
|
|
550
|
-
flatBaggage[`${prefix}${key}`] = String(val);
|
|
551
|
-
}
|
|
552
|
-
}
|
|
553
|
-
|
|
554
|
-
// Use the existing withBaggage helper
|
|
555
|
-
const currentContext = context.active();
|
|
556
|
-
let baggage =
|
|
557
|
-
propagation.getBaggage(currentContext) ?? propagation.createBaggage();
|
|
558
|
-
|
|
559
|
-
for (const [key, val] of Object.entries(flatBaggage)) {
|
|
560
|
-
baggage = baggage.setEntry(key, { value: val });
|
|
561
|
-
}
|
|
562
|
-
|
|
563
|
-
const newContext = propagation.setBaggage(currentContext, baggage);
|
|
564
|
-
return context.with(newContext, fn);
|
|
565
|
-
},
|
|
566
|
-
};
|
|
567
|
-
}
|