@aws/durable-execution-sdk-js-otel 0.1.0 → 1.0.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 +494 -176
- package/dist/execution-plugin.mjs +539 -0
- package/dist/execution-plugin.mjs.map +1 -0
- package/dist/global-id-generator.mjs +622 -0
- package/dist/global-id-generator.mjs.map +1 -0
- package/dist/index.mjs +8 -516
- package/dist/index.mjs.map +1 -1
- package/dist/invocation-plugin.mjs +661 -0
- package/dist/invocation-plugin.mjs.map +1 -0
- package/dist/otel-execution.mjs +15 -0
- package/dist/otel-execution.mjs.map +1 -0
- package/dist/otel-invocation.mjs +16 -0
- package/dist/otel-invocation.mjs.map +1 -0
- package/dist-cjs/execution-plugin.js +541 -0
- package/dist-cjs/execution-plugin.js.map +1 -0
- package/dist-cjs/global-id-generator.js +637 -0
- package/dist-cjs/global-id-generator.js.map +1 -0
- package/dist-cjs/index.js +18 -519
- package/dist-cjs/index.js.map +1 -1
- package/dist-cjs/invocation-plugin.js +663 -0
- package/dist-cjs/invocation-plugin.js.map +1 -0
- package/dist-cjs/otel-execution.js +17 -0
- package/dist-cjs/otel-execution.js.map +1 -0
- package/dist-cjs/otel-invocation.js +18 -0
- package/dist-cjs/otel-invocation.js.map +1 -0
- package/package.json +26 -15
- package/dist-types/context-extractors.d.ts +0 -43
- package/dist-types/context-extractors.d.ts.map +0 -1
- package/dist-types/deterministic-id-generator.d.ts +0 -64
- package/dist-types/deterministic-id-generator.d.ts.map +0 -1
- package/dist-types/index.d.ts +0 -6
- package/dist-types/index.d.ts.map +0 -1
- package/dist-types/plugin.d.ts +0 -46
- package/dist-types/plugin.d.ts.map +0 -1
- package/dist-types/tsconfig.build.tsbuildinfo +0 -1
|
@@ -0,0 +1,637 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var api = require('@opentelemetry/api');
|
|
4
|
+
var sdkTraceNode = require('@opentelemetry/sdk-trace-node');
|
|
5
|
+
var node_async_hooks = require('node:async_hooks');
|
|
6
|
+
var node_crypto = require('node:crypto');
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* An OpenTelemetry IdGenerator with execution-scoped deterministic overrides.
|
|
10
|
+
*
|
|
11
|
+
* Overrides are active only while {@link withIds} runs. All other ID generation
|
|
12
|
+
* is delegated to the fallback generator. AsyncLocalStorage makes the override
|
|
13
|
+
* visible to the provider-owned generator without leaking it to unrelated spans
|
|
14
|
+
* or concurrent durable executions.
|
|
15
|
+
*/
|
|
16
|
+
class DeterministicIdGenerator {
|
|
17
|
+
fallbackIdGenerator;
|
|
18
|
+
static idOverrides = new node_async_hooks.AsyncLocalStorage();
|
|
19
|
+
constructor(fallbackIdGenerator = new sdkTraceNode.RandomIdGenerator()) {
|
|
20
|
+
this.fallbackIdGenerator = fallbackIdGenerator;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Runs a synchronous span-creation callback with deterministic IDs.
|
|
24
|
+
*
|
|
25
|
+
* The span ID is consumed on its first use so re-entrant ID generation cannot
|
|
26
|
+
* accidentally assign the same ID to more than one span.
|
|
27
|
+
*/
|
|
28
|
+
withIds(ids, fn) {
|
|
29
|
+
return DeterministicIdGenerator.idOverrides.run({ ...ids }, fn);
|
|
30
|
+
}
|
|
31
|
+
/** Generate a 32-char lowercase hex trace ID. */
|
|
32
|
+
generateTraceId() {
|
|
33
|
+
const traceId = DeterministicIdGenerator.idOverrides.getStore()?.traceId;
|
|
34
|
+
if (traceId) {
|
|
35
|
+
return traceId;
|
|
36
|
+
}
|
|
37
|
+
return this.fallbackIdGenerator.generateTraceId();
|
|
38
|
+
}
|
|
39
|
+
/** Generate a 16-char lowercase hex span ID. */
|
|
40
|
+
generateSpanId() {
|
|
41
|
+
const override = DeterministicIdGenerator.idOverrides.getStore();
|
|
42
|
+
if (override?.spanId) {
|
|
43
|
+
const spanId = override.spanId;
|
|
44
|
+
override.spanId = undefined;
|
|
45
|
+
return spanId;
|
|
46
|
+
}
|
|
47
|
+
return this.fallbackIdGenerator.generateSpanId();
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Derive a deterministic trace ID from an X-Ray Root field.
|
|
52
|
+
* Strips the `Root=1-` prefix and all `-` separators to produce
|
|
53
|
+
* a valid 32-character lowercase hex OpenTelemetry trace ID.
|
|
54
|
+
*
|
|
55
|
+
* @param xRayRoot - The Root field value, e.g. "1-5759e988-bd862e3fe1be46a994272793"
|
|
56
|
+
* @returns A 32-char lowercase hex string, or undefined if the input is invalid
|
|
57
|
+
*/
|
|
58
|
+
function deriveTraceIdFromXRayRoot(xRayRoot) {
|
|
59
|
+
// Strip "Root=" prefix if present
|
|
60
|
+
let root = xRayRoot;
|
|
61
|
+
if (root.startsWith("Root=")) {
|
|
62
|
+
root = root.slice(5);
|
|
63
|
+
}
|
|
64
|
+
// Strip the version prefix "1-"
|
|
65
|
+
if (root.startsWith("1-")) {
|
|
66
|
+
root = root.slice(2);
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
return undefined;
|
|
70
|
+
}
|
|
71
|
+
// Remove all dashes
|
|
72
|
+
const hex = root.replace(/-/g, "");
|
|
73
|
+
// Validate: must be exactly 32 lowercase hex characters
|
|
74
|
+
if (hex.length !== 32 || !/^[0-9a-f]{32}$/.test(hex)) {
|
|
75
|
+
return undefined;
|
|
76
|
+
}
|
|
77
|
+
return hex;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Derive a deterministic trace ID from an execution ARN and its durable start
|
|
81
|
+
* timestamp by hashing them with SHA-256 and truncating to the first 32
|
|
82
|
+
* lowercase hex characters.
|
|
83
|
+
*
|
|
84
|
+
* The timestamp is optional for callers that do not have it. When omitted, the
|
|
85
|
+
* ARN-only derivation is retained as a deterministic fallback.
|
|
86
|
+
*
|
|
87
|
+
* @param executionArn - The execution ARN string
|
|
88
|
+
* @param executionStartTimestamp - Stable start time of the durable execution
|
|
89
|
+
* @returns A 32-char lowercase hex string
|
|
90
|
+
*/
|
|
91
|
+
function deriveTraceIdFromArn(executionArn, executionStartTimestamp) {
|
|
92
|
+
const executionIdentity = executionStartTimestamp
|
|
93
|
+
? `${executionArn}:${executionStartTimestamp.toISOString()}`
|
|
94
|
+
: executionArn;
|
|
95
|
+
return node_crypto.createHash("sha256")
|
|
96
|
+
.update(executionIdentity)
|
|
97
|
+
.digest("hex")
|
|
98
|
+
.slice(0, 32);
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Derive a deterministic span ID from an operation ID scoped to a specific execution.
|
|
102
|
+
* Hashes `executionArn + ":" + operationId` with SHA-256 and truncates to the first
|
|
103
|
+
* 16 lowercase hex characters.
|
|
104
|
+
*
|
|
105
|
+
* The executionArn is included in the hash input to avoid span ID collisions when
|
|
106
|
+
* different executions (e.g., a parent and child workflow) share the same trace and
|
|
107
|
+
* have operations at the same positional ID.
|
|
108
|
+
*
|
|
109
|
+
* @param operationId - The operation ID string (positional identifier within an execution)
|
|
110
|
+
* @param executionArn - The execution ARN, used to scope span IDs per execution
|
|
111
|
+
* @returns A 16-char lowercase hex string
|
|
112
|
+
*/
|
|
113
|
+
function deriveSpanIdFromOperationId(operationId, executionArn) {
|
|
114
|
+
return node_crypto.createHash("sha256")
|
|
115
|
+
.update(executionArn + ":" + operationId)
|
|
116
|
+
.digest("hex")
|
|
117
|
+
.slice(0, 16);
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Derive a deterministic span ID for a Workflow_Span from an execution ARN.
|
|
121
|
+
* Hashes `"workflow:" + executionArn` with SHA-256 and truncates to the first
|
|
122
|
+
* 16 lowercase hex characters.
|
|
123
|
+
*
|
|
124
|
+
* The "workflow:" prefix acts as a salt to ensure the resulting span ID is
|
|
125
|
+
* distinct from IDs produced by `deriveSpanIdFromOperationId` for the same ARN.
|
|
126
|
+
*
|
|
127
|
+
* @param executionArn - The execution ARN string (must be non-empty)
|
|
128
|
+
* @returns A 16-char lowercase hex string, never equal to "0000000000000000"
|
|
129
|
+
* @throws Error if the execution ARN is an empty string
|
|
130
|
+
*/
|
|
131
|
+
function deriveWorkflowSpanId(executionArn) {
|
|
132
|
+
if (executionArn === "") {
|
|
133
|
+
throw new Error("Execution ARN must be non-empty");
|
|
134
|
+
}
|
|
135
|
+
const spanId = node_crypto.createHash("sha256")
|
|
136
|
+
.update("workflow:" + executionArn)
|
|
137
|
+
.digest("hex")
|
|
138
|
+
.slice(0, 16);
|
|
139
|
+
// Ensure the result is never all-zeros (astronomically unlikely with SHA-256,
|
|
140
|
+
// but guaranteed by contract)
|
|
141
|
+
if (spanId === "0000000000000000") {
|
|
142
|
+
return "0000000000000001";
|
|
143
|
+
}
|
|
144
|
+
return spanId;
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Derive a deterministic span ID for the synthetic execution root from an
|
|
148
|
+
* execution ARN. Hashes `"execution-root:" + executionArn` with SHA-256 and
|
|
149
|
+
* truncates to the first 16 lowercase hex characters.
|
|
150
|
+
*
|
|
151
|
+
* The `"execution-root:"` prefix is a distinct namespace from
|
|
152
|
+
* `deriveWorkflowSpanId` (`"workflow:"`) and `deriveSpanIdFromOperationId`
|
|
153
|
+
* (`"<arn>:<opId>"`), so the synthetic root never collides with the Workflow or
|
|
154
|
+
* operation spans that share the execution trace. Stable across reinvocations
|
|
155
|
+
* so the same synthetic root is the common ancestor every invocation.
|
|
156
|
+
*
|
|
157
|
+
* @param executionArn - The execution ARN string (must be non-empty)
|
|
158
|
+
* @returns A 16-char lowercase hex string, never equal to "0000000000000000"
|
|
159
|
+
* @throws Error if the execution ARN is an empty string
|
|
160
|
+
*/
|
|
161
|
+
function deriveExecutionRootSpanId(executionArn) {
|
|
162
|
+
if (executionArn === "") {
|
|
163
|
+
throw new Error("Execution ARN must be non-empty");
|
|
164
|
+
}
|
|
165
|
+
const spanId = node_crypto.createHash("sha256")
|
|
166
|
+
.update("execution-root:" + executionArn)
|
|
167
|
+
.digest("hex")
|
|
168
|
+
.slice(0, 16);
|
|
169
|
+
if (spanId === "0000000000000000") {
|
|
170
|
+
return "0000000000000001";
|
|
171
|
+
}
|
|
172
|
+
return spanId;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
const OTEL_TRACE_ID_PATTERN = /^[0-9a-f]{32}$/;
|
|
176
|
+
const OTEL_SPAN_ID_PATTERN = /^[0-9a-f]{16}$/;
|
|
177
|
+
const ALL_ZERO_TRACE_ID = "0".repeat(32);
|
|
178
|
+
const ALL_ZERO_SPAN_ID = "0".repeat(16);
|
|
179
|
+
/**
|
|
180
|
+
* True when `traceId` is a well-formed, non-zero 32-char hex OTel trace ID.
|
|
181
|
+
*
|
|
182
|
+
* Validity is stricter than a format match: an all-zero ID is well-formed hex
|
|
183
|
+
* but invalid, and anchoring an execution on it would split the trace.
|
|
184
|
+
*/
|
|
185
|
+
function isValidTraceId(traceId) {
|
|
186
|
+
return (traceId != null &&
|
|
187
|
+
OTEL_TRACE_ID_PATTERN.test(traceId) &&
|
|
188
|
+
traceId !== ALL_ZERO_TRACE_ID);
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* True when `spanId` is a well-formed, non-zero 16-char hex OTel span ID.
|
|
192
|
+
*/
|
|
193
|
+
function isValidSpanId(spanId) {
|
|
194
|
+
return (spanId != null &&
|
|
195
|
+
OTEL_SPAN_ID_PATTERN.test(spanId) &&
|
|
196
|
+
spanId !== ALL_ZERO_SPAN_ID);
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Resolves the tri-state sampling decision for an extracted context.
|
|
200
|
+
*
|
|
201
|
+
* Prefers an explicit `sampling` value; otherwise derives from `traceFlags`
|
|
202
|
+
* when present; otherwise `UNDECIDED`.
|
|
203
|
+
*/
|
|
204
|
+
function resolveSampling(extracted) {
|
|
205
|
+
if (extracted.sampling) {
|
|
206
|
+
return extracted.sampling;
|
|
207
|
+
}
|
|
208
|
+
if (extracted.traceFlags != null) {
|
|
209
|
+
return (extracted.traceFlags & 1) !== 0 ? "SAMPLED" : "NOT_SAMPLED";
|
|
210
|
+
}
|
|
211
|
+
return "UNDECIDED";
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* True when the extracted context carries a complete remote parent: a valid
|
|
215
|
+
* trace ID and a valid parent span ID, so it can serve as a remote parent.
|
|
216
|
+
*/
|
|
217
|
+
function hasCompleteRemoteParent(extracted) {
|
|
218
|
+
return (extracted != null &&
|
|
219
|
+
isValidTraceId(extracted.traceId) &&
|
|
220
|
+
isValidSpanId(extracted.parentSpanId));
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* True when the extracted context carries a valid (well-formed, non-zero) trace
|
|
224
|
+
* ID that the resolver can anchor the durable execution trace on.
|
|
225
|
+
*/
|
|
226
|
+
function hasValidTraceId(extracted) {
|
|
227
|
+
return extracted != null && isValidTraceId(extracted.traceId);
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* Reads the X-Ray trace header from the `_X_AMZN_TRACE_ID` environment variable.
|
|
231
|
+
*
|
|
232
|
+
* The durable execution backend propagates the same Root trace ID to every
|
|
233
|
+
* invocation, so all invocations of the same execution share one traceId.
|
|
234
|
+
*
|
|
235
|
+
* X-Ray Header format:
|
|
236
|
+
* Root=1-5759e988-bd862e3fe1be46a994272793;Parent=53995c3f42cd8ad8;Sampled=1
|
|
237
|
+
*
|
|
238
|
+
* - Extract Root value, strip "1-" prefix and all "-" to get 32-char hex traceId
|
|
239
|
+
* - Extract Parent value for parentSpanId (16-char hex)
|
|
240
|
+
* - Extract Sampled: `1` -> SAMPLED, `0` -> NOT_SAMPLED, anything else undecided
|
|
241
|
+
*
|
|
242
|
+
* `Root`, `Parent`, and `Sampled` are parsed independently: only `Sampled=1`
|
|
243
|
+
* and `Sampled=0` are authoritative, and an all-zero Root or Parent is rejected
|
|
244
|
+
* as invalid (it is well-formed hex but not a usable ID). A valid Root with no
|
|
245
|
+
* usable Parent is still returned (the trace ID is usable on its own).
|
|
246
|
+
*
|
|
247
|
+
* Returns undefined when _X_AMZN_TRACE_ID is missing or has no valid Root.
|
|
248
|
+
*/
|
|
249
|
+
function xRayContextExtractor(_info) {
|
|
250
|
+
const header = process.env._X_AMZN_TRACE_ID;
|
|
251
|
+
if (!header) {
|
|
252
|
+
return undefined;
|
|
253
|
+
}
|
|
254
|
+
// Parse the header into key-value pairs separated by semicolons
|
|
255
|
+
const fields = new Map();
|
|
256
|
+
for (const part of header.split(";")) {
|
|
257
|
+
const eqIdx = part.indexOf("=");
|
|
258
|
+
if (eqIdx > 0) {
|
|
259
|
+
const key = part.slice(0, eqIdx).trim();
|
|
260
|
+
const value = part.slice(eqIdx + 1).trim();
|
|
261
|
+
fields.set(key, value);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
const root = fields.get("Root");
|
|
265
|
+
if (!root) {
|
|
266
|
+
return undefined;
|
|
267
|
+
}
|
|
268
|
+
// Root format: 1-5759e988-bd862e3fe1be46a994272793
|
|
269
|
+
// Strip the "1-" prefix and remove all dashes to get 32-char hex
|
|
270
|
+
const rootValue = root.startsWith("1-") ? root.slice(2) : root;
|
|
271
|
+
const traceId = rootValue.replace(/-/g, "").toLowerCase();
|
|
272
|
+
// Reject a missing, malformed, or all-zero Root: it is not a usable trace ID.
|
|
273
|
+
if (!isValidTraceId(traceId)) {
|
|
274
|
+
return undefined;
|
|
275
|
+
}
|
|
276
|
+
// Parent is a 16-char hex span ID; reject an all-zero Parent the same way,
|
|
277
|
+
// and treat an unusable Parent as absent while keeping the valid Root.
|
|
278
|
+
const parent = fields.get("Parent");
|
|
279
|
+
let parentSpanId;
|
|
280
|
+
if (parent && isValidSpanId(parent.toLowerCase())) {
|
|
281
|
+
parentSpanId = parent.toLowerCase();
|
|
282
|
+
}
|
|
283
|
+
// Only Sampled=1 and Sampled=0 are authoritative; anything else is undecided.
|
|
284
|
+
const sampledField = fields.get("Sampled");
|
|
285
|
+
const sampling = sampledField === "1"
|
|
286
|
+
? "SAMPLED"
|
|
287
|
+
: sampledField === "0"
|
|
288
|
+
? "NOT_SAMPLED"
|
|
289
|
+
: "UNDECIDED";
|
|
290
|
+
return { traceId, parentSpanId, sampling };
|
|
291
|
+
}
|
|
292
|
+
/**
|
|
293
|
+
* Reads W3C traceparent from `context.clientContext.custom.traceparent`.
|
|
294
|
+
*
|
|
295
|
+
* W3C traceparent format:
|
|
296
|
+
* 00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01
|
|
297
|
+
* Format: version-traceId-parentId-traceFlags
|
|
298
|
+
*
|
|
299
|
+
* - traceId is 32 hex chars
|
|
300
|
+
* - parentId is 16 hex chars
|
|
301
|
+
* - flags is 2 hex chars (parsed to number)
|
|
302
|
+
*
|
|
303
|
+
* Returns undefined when clientContext or traceparent is missing or malformed.
|
|
304
|
+
*/
|
|
305
|
+
function w3cClientContextExtractor(info) {
|
|
306
|
+
const extendedInfo = info;
|
|
307
|
+
const traceparent = extendedInfo.context?.clientContext?.custom?.traceparent;
|
|
308
|
+
if (!traceparent) {
|
|
309
|
+
return undefined;
|
|
310
|
+
}
|
|
311
|
+
return parseW3CTraceparent(traceparent);
|
|
312
|
+
}
|
|
313
|
+
/**
|
|
314
|
+
* Parses a W3C traceparent header value.
|
|
315
|
+
*
|
|
316
|
+
* Format: version-traceId-parentId-flags
|
|
317
|
+
* Example: 00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01
|
|
318
|
+
*/
|
|
319
|
+
function parseW3CTraceparent(traceparent) {
|
|
320
|
+
const parts = traceparent.split("-");
|
|
321
|
+
// Must have exactly 4 parts: version, traceId, parentId, flags
|
|
322
|
+
if (parts.length !== 4) {
|
|
323
|
+
return undefined;
|
|
324
|
+
}
|
|
325
|
+
const [version, traceId, parentId, flags] = parts;
|
|
326
|
+
// Version must be 2 hex chars
|
|
327
|
+
if (!/^[0-9a-f]{2}$/.test(version)) {
|
|
328
|
+
return undefined;
|
|
329
|
+
}
|
|
330
|
+
// TraceId and ParentId must be well-formed AND non-zero. An all-zero trace or
|
|
331
|
+
// parent ID is syntactically 32/16 hex chars but invalid per the W3C spec;
|
|
332
|
+
// accepting it would let a malformed traceparent's sampled bit force or
|
|
333
|
+
// suppress sampling even though the resolver rejects the trace ID and falls
|
|
334
|
+
// back to the ARN-derived trace.
|
|
335
|
+
if (!isValidTraceId(traceId) || !isValidSpanId(parentId)) {
|
|
336
|
+
return undefined;
|
|
337
|
+
}
|
|
338
|
+
// Flags must be 2 hex chars
|
|
339
|
+
if (!/^[0-9a-f]{2}$/.test(flags)) {
|
|
340
|
+
return undefined;
|
|
341
|
+
}
|
|
342
|
+
const traceFlags = parseInt(flags, 16);
|
|
343
|
+
// W3C traceparent carries an explicit sampled bit, so the decision is never
|
|
344
|
+
// UNDECIDED.
|
|
345
|
+
const sampling = (traceFlags & 1) !== 0 ? "SAMPLED" : "NOT_SAMPLED";
|
|
346
|
+
return {
|
|
347
|
+
traceId,
|
|
348
|
+
parentSpanId: parentId,
|
|
349
|
+
traceFlags,
|
|
350
|
+
sampling,
|
|
351
|
+
};
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
const SAMPLER_FIELD = "_sampler";
|
|
355
|
+
function isSampler(value) {
|
|
356
|
+
return (typeof value === "object" &&
|
|
357
|
+
value !== null &&
|
|
358
|
+
"shouldSample" in value &&
|
|
359
|
+
typeof value.shouldSample === "function");
|
|
360
|
+
}
|
|
361
|
+
/**
|
|
362
|
+
* Sampler wrapper that preserves the application's sampler except while the
|
|
363
|
+
* durable plugin is creating its own spans with a resolved execution decision.
|
|
364
|
+
*/
|
|
365
|
+
class DurableSampler {
|
|
366
|
+
delegate;
|
|
367
|
+
static decisions = new node_async_hooks.AsyncLocalStorage();
|
|
368
|
+
constructor(delegate) {
|
|
369
|
+
this.delegate = delegate;
|
|
370
|
+
}
|
|
371
|
+
withDecision(decision, fn) {
|
|
372
|
+
return DurableSampler.decisions.run(decision, fn);
|
|
373
|
+
}
|
|
374
|
+
shouldSample(context, traceId, spanName, spanKind, attributes, links) {
|
|
375
|
+
const decision = DurableSampler.decisions.getStore();
|
|
376
|
+
if (decision !== undefined) {
|
|
377
|
+
return { decision };
|
|
378
|
+
}
|
|
379
|
+
return this.delegate.shouldSample(context, traceId, spanName, spanKind, attributes, links);
|
|
380
|
+
}
|
|
381
|
+
toString() {
|
|
382
|
+
return `DurableSampler{${this.delegate.toString()}}`;
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
/**
|
|
386
|
+
* Installs a durable-aware sampler on an OpenTelemetry SDK tracer.
|
|
387
|
+
*
|
|
388
|
+
* OpenTelemetry JavaScript does not expose the sampler through its public API.
|
|
389
|
+
* SDK tracers have historically stored it in the TypeScript-private `_sampler`
|
|
390
|
+
* field, which remains writable at runtime.
|
|
391
|
+
*/
|
|
392
|
+
function tryInstallDurableSampler(tracer) {
|
|
393
|
+
try {
|
|
394
|
+
const existingSampler = Reflect.get(tracer, SAMPLER_FIELD);
|
|
395
|
+
if (!isSampler(existingSampler)) {
|
|
396
|
+
return undefined;
|
|
397
|
+
}
|
|
398
|
+
if (existingSampler instanceof DurableSampler) {
|
|
399
|
+
return existingSampler;
|
|
400
|
+
}
|
|
401
|
+
const durableSampler = new DurableSampler(existingSampler);
|
|
402
|
+
if (!Reflect.set(tracer, SAMPLER_FIELD, durableSampler) ||
|
|
403
|
+
Reflect.get(tracer, SAMPLER_FIELD) !== durableSampler) {
|
|
404
|
+
return undefined;
|
|
405
|
+
}
|
|
406
|
+
return durableSampler;
|
|
407
|
+
}
|
|
408
|
+
catch {
|
|
409
|
+
return undefined;
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
function getConfiguredSampler(tracer) {
|
|
413
|
+
try {
|
|
414
|
+
const sampler = Reflect.get(tracer, SAMPLER_FIELD);
|
|
415
|
+
if (sampler instanceof DurableSampler) {
|
|
416
|
+
return Reflect.get(sampler, "delegate");
|
|
417
|
+
}
|
|
418
|
+
return isSampler(sampler) ? sampler : undefined;
|
|
419
|
+
}
|
|
420
|
+
catch {
|
|
421
|
+
return undefined;
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
/**
|
|
426
|
+
* The canonical trace ID: the propagated remote trace ID when valid, else one
|
|
427
|
+
* derived from the ARN and start time.
|
|
428
|
+
*
|
|
429
|
+
* Only these two anchors are used, and both are stable across Lambda
|
|
430
|
+
* reinvocations: the propagated `Root` is kept identical for every invocation by
|
|
431
|
+
* the durable backend, and the ARN-derived ID is a pure hash of the ARN. A live
|
|
432
|
+
* ambient span's trace ID is deliberately NOT used — it is not guaranteed stable
|
|
433
|
+
* across invocations, so anchoring on one could change the execution trace on
|
|
434
|
+
* replay and break the continuation/replay links (which target
|
|
435
|
+
* `deriveSpanIdFromOperationId` on the canonical trace).
|
|
436
|
+
*
|
|
437
|
+
* An all-zero or malformed remote trace ID is not usable, so it falls through to
|
|
438
|
+
* the ARN-derived ID rather than anchoring the execution on an unstable trace.
|
|
439
|
+
*/
|
|
440
|
+
function canonicalTraceId(extracted, executionArn, executionStartTimestamp) {
|
|
441
|
+
if (hasValidTraceId(extracted)) {
|
|
442
|
+
return extracted.traceId;
|
|
443
|
+
}
|
|
444
|
+
return deriveTraceIdFromArn(executionArn, executionStartTimestamp);
|
|
445
|
+
}
|
|
446
|
+
/**
|
|
447
|
+
* Flags for an explicit upstream decision, or the sampler's decision
|
|
448
|
+
* (`whenUndecided`) when the upstream did not decide. The supplier is consulted
|
|
449
|
+
* lazily, only for the `UNDECIDED` case, so an explicit decision never triggers
|
|
450
|
+
* a (discarded) sampler query.
|
|
451
|
+
*/
|
|
452
|
+
function explicitDecision(extracted, whenUndecided) {
|
|
453
|
+
const sampling = extracted ? resolveSampling(extracted) : "UNDECIDED";
|
|
454
|
+
switch (sampling) {
|
|
455
|
+
case "SAMPLED":
|
|
456
|
+
return sdkTraceNode.SamplingDecision.RECORD_AND_SAMPLED;
|
|
457
|
+
case "NOT_SAMPLED":
|
|
458
|
+
return sdkTraceNode.SamplingDecision.NOT_RECORD;
|
|
459
|
+
case "UNDECIDED":
|
|
460
|
+
default:
|
|
461
|
+
return whenUndecided();
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
function traceFlagsFromDecision(decision) {
|
|
465
|
+
return decision === sdkTraceNode.SamplingDecision.RECORD_AND_SAMPLED
|
|
466
|
+
? api.TraceFlags.SAMPLED
|
|
467
|
+
: api.TraceFlags.NONE;
|
|
468
|
+
}
|
|
469
|
+
/**
|
|
470
|
+
* Resolves the execution ancestor: a complete propagated remote parent when
|
|
471
|
+
* present, otherwise a synthetic execution root on the canonical trace.
|
|
472
|
+
*
|
|
473
|
+
* A live ambient span is never used as the ancestor. Its trace ID is not
|
|
474
|
+
* guaranteed stable across Lambda reinvocations, so anchoring the multi-
|
|
475
|
+
* invocation execution on it could change the execution trace on replay and
|
|
476
|
+
* break cross-invocation links. The two anchors used here are both stable: a
|
|
477
|
+
* propagated remote parent (the backend keeps `Root` identical every invocation)
|
|
478
|
+
* and the ARN-derived synthetic root (a pure hash of the ARN).
|
|
479
|
+
*
|
|
480
|
+
* @param extracted the context parsed from the backend header, or undefined
|
|
481
|
+
* @param canonical the trace ID the ancestor is anchored on
|
|
482
|
+
* @param executionArn the durable execution ARN
|
|
483
|
+
* @param rootSamplingDecision the configured root decision for this trace, applied
|
|
484
|
+
* to a remote parent or synthetic root when the header carries no explicit
|
|
485
|
+
* Sampled value
|
|
486
|
+
*/
|
|
487
|
+
function resolveExecutionTraceContext(extracted, canonical, executionArn, rootSamplingDecision) {
|
|
488
|
+
// A valid remote backend parent is the authoritative ancestor, regardless of
|
|
489
|
+
// whether Sampled is present.
|
|
490
|
+
if (hasCompleteRemoteParent(extracted)) {
|
|
491
|
+
const decision = explicitDecision(extracted, rootSamplingDecision);
|
|
492
|
+
const flags = traceFlagsFromDecision(decision);
|
|
493
|
+
const remoteParent = {
|
|
494
|
+
traceId: extracted.traceId,
|
|
495
|
+
spanId: extracted.parentSpanId,
|
|
496
|
+
traceFlags: flags,
|
|
497
|
+
isRemote: true,
|
|
498
|
+
};
|
|
499
|
+
return {
|
|
500
|
+
executionAncestor: remoteParent,
|
|
501
|
+
traceId: remoteParent.traceId,
|
|
502
|
+
traceFlags: flags,
|
|
503
|
+
samplingDecision: decision,
|
|
504
|
+
};
|
|
505
|
+
}
|
|
506
|
+
// No complete remote parent: synthesize an execution root on the canonical
|
|
507
|
+
// trace (the stable remote Root if one was provided, else the ARN-derived ID).
|
|
508
|
+
const samplingContext = hasValidTraceId(extracted) ? extracted : undefined;
|
|
509
|
+
const decision = explicitDecision(samplingContext, rootSamplingDecision);
|
|
510
|
+
const flags = traceFlagsFromDecision(decision);
|
|
511
|
+
const syntheticRoot = {
|
|
512
|
+
traceId: canonical,
|
|
513
|
+
spanId: deriveExecutionRootSpanId(executionArn),
|
|
514
|
+
traceFlags: flags,
|
|
515
|
+
isRemote: false,
|
|
516
|
+
};
|
|
517
|
+
return {
|
|
518
|
+
executionAncestor: syntheticRoot,
|
|
519
|
+
traceId: canonical,
|
|
520
|
+
traceFlags: flags,
|
|
521
|
+
samplingDecision: decision,
|
|
522
|
+
};
|
|
523
|
+
}
|
|
524
|
+
/**
|
|
525
|
+
* Decides how a root span on the given trace should be sampled, used only
|
|
526
|
+
* when the propagated context carries no explicit decision.
|
|
527
|
+
*
|
|
528
|
+
* Sampling precedence, highest first:
|
|
529
|
+
*
|
|
530
|
+
* 1. the backend's explicit `Sampled` on the propagated header — handled by the
|
|
531
|
+
* caller before reaching here;
|
|
532
|
+
* 2. the configured sampler is evaluated at its root policy (`ROOT_CONTEXT`, no
|
|
533
|
+
* parent) with the real trace ID. This honors custom samplers and avoids
|
|
534
|
+
* inheriting an unrelated ambient span's decision.
|
|
535
|
+
*
|
|
536
|
+
* The resolved decision is then enforced through DurableSampler for every
|
|
537
|
+
* SDK-created span, so direct samplers that ignore parent flags cannot override
|
|
538
|
+
* an explicit backend decision or the configured root decision.
|
|
539
|
+
*
|
|
540
|
+
* @param tracer the resolved SDK tracer
|
|
541
|
+
* @param traceId the canonical trace ID to evaluate
|
|
542
|
+
* @param spanName the span name passed to the sampler
|
|
543
|
+
* @param attributes the attributes the span is started with
|
|
544
|
+
*/
|
|
545
|
+
function rootSamplingDecision(tracer, traceId, spanName, attributes) {
|
|
546
|
+
const sampler = getConfiguredSampler(tracer);
|
|
547
|
+
if (!sampler) {
|
|
548
|
+
return sdkTraceNode.SamplingDecision.RECORD_AND_SAMPLED;
|
|
549
|
+
}
|
|
550
|
+
try {
|
|
551
|
+
// Evaluate with ROOT_CONTEXT (no parent), not the active context: a
|
|
552
|
+
// ParentBasedSampler must decide the execution root on its own root policy,
|
|
553
|
+
// not inherit the sampled bit of an unrelated ambient span that the resolver
|
|
554
|
+
// already rejected. Otherwise an unrelated unsampled ambient span could drop
|
|
555
|
+
// an execution whose root policy would sample it.
|
|
556
|
+
const result = sampler.shouldSample(api.ROOT_CONTEXT, traceId, spanName, api.SpanKind.INTERNAL, attributes, []);
|
|
557
|
+
return result.decision;
|
|
558
|
+
}
|
|
559
|
+
catch {
|
|
560
|
+
return sdkTraceNode.SamplingDecision.RECORD_AND_SAMPLED;
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
/**
|
|
565
|
+
* Resolves an application-owned provider factory or the globally registered
|
|
566
|
+
* provider. Exporters, sampling, resources, propagators, instrumentation, and
|
|
567
|
+
* provider shutdown remain application or ADOT responsibilities.
|
|
568
|
+
*/
|
|
569
|
+
function createTracerProvider(config, idGenerator) {
|
|
570
|
+
if (config?.tracerProviderFactory) {
|
|
571
|
+
const createIdGenerator = (fallbackIdGenerator) => fallbackIdGenerator
|
|
572
|
+
? new DeterministicIdGenerator(fallbackIdGenerator)
|
|
573
|
+
: idGenerator;
|
|
574
|
+
return {
|
|
575
|
+
tracerProvider: config.tracerProviderFactory(createIdGenerator),
|
|
576
|
+
usesGlobalProvider: false,
|
|
577
|
+
};
|
|
578
|
+
}
|
|
579
|
+
return {
|
|
580
|
+
tracerProvider: api.trace.getTracerProvider(),
|
|
581
|
+
usesGlobalProvider: true,
|
|
582
|
+
};
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
const ID_GENERATOR_FIELD = "_idGenerator";
|
|
586
|
+
function isIdGenerator(value) {
|
|
587
|
+
return (typeof value === "object" &&
|
|
588
|
+
value !== null &&
|
|
589
|
+
"generateTraceId" in value &&
|
|
590
|
+
typeof value.generateTraceId === "function" &&
|
|
591
|
+
"generateSpanId" in value &&
|
|
592
|
+
typeof value.generateSpanId === "function");
|
|
593
|
+
}
|
|
594
|
+
/**
|
|
595
|
+
* Installs deterministic durable IDs on an OpenTelemetry SDK tracer while
|
|
596
|
+
* preserving its configured generator for all unscoped ID generation.
|
|
597
|
+
*
|
|
598
|
+
* OpenTelemetry JavaScript does not expose this generator through its public
|
|
599
|
+
* API. SDK tracers have historically stored it in the TypeScript-private
|
|
600
|
+
* `_idGenerator` field, which remains writable at runtime.
|
|
601
|
+
*/
|
|
602
|
+
function tryInstallGlobalIdGenerator(tracer) {
|
|
603
|
+
try {
|
|
604
|
+
const existingIdGenerator = Reflect.get(tracer, ID_GENERATOR_FIELD);
|
|
605
|
+
if (!isIdGenerator(existingIdGenerator)) {
|
|
606
|
+
return undefined;
|
|
607
|
+
}
|
|
608
|
+
if (existingIdGenerator instanceof DeterministicIdGenerator) {
|
|
609
|
+
return existingIdGenerator;
|
|
610
|
+
}
|
|
611
|
+
const deterministicIdGenerator = new DeterministicIdGenerator(existingIdGenerator);
|
|
612
|
+
if (!Reflect.set(tracer, ID_GENERATOR_FIELD, deterministicIdGenerator) ||
|
|
613
|
+
Reflect.get(tracer, ID_GENERATOR_FIELD) !== deterministicIdGenerator) {
|
|
614
|
+
return undefined;
|
|
615
|
+
}
|
|
616
|
+
return deterministicIdGenerator;
|
|
617
|
+
}
|
|
618
|
+
catch {
|
|
619
|
+
return undefined;
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
exports.DeterministicIdGenerator = DeterministicIdGenerator;
|
|
624
|
+
exports.canonicalTraceId = canonicalTraceId;
|
|
625
|
+
exports.createTracerProvider = createTracerProvider;
|
|
626
|
+
exports.deriveExecutionRootSpanId = deriveExecutionRootSpanId;
|
|
627
|
+
exports.deriveSpanIdFromOperationId = deriveSpanIdFromOperationId;
|
|
628
|
+
exports.deriveTraceIdFromArn = deriveTraceIdFromArn;
|
|
629
|
+
exports.deriveTraceIdFromXRayRoot = deriveTraceIdFromXRayRoot;
|
|
630
|
+
exports.deriveWorkflowSpanId = deriveWorkflowSpanId;
|
|
631
|
+
exports.resolveExecutionTraceContext = resolveExecutionTraceContext;
|
|
632
|
+
exports.rootSamplingDecision = rootSamplingDecision;
|
|
633
|
+
exports.tryInstallDurableSampler = tryInstallDurableSampler;
|
|
634
|
+
exports.tryInstallGlobalIdGenerator = tryInstallGlobalIdGenerator;
|
|
635
|
+
exports.w3cClientContextExtractor = w3cClientContextExtractor;
|
|
636
|
+
exports.xRayContextExtractor = xRayContextExtractor;
|
|
637
|
+
//# sourceMappingURL=global-id-generator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"global-id-generator.js","sources":["../src/deterministic-id-generator.ts","../src/context-extractors.ts","../src/global-sampler.ts","../src/execution-trace-context.ts","../src/otel-plugin-provider.ts","../src/global-id-generator.ts"],"names":["AsyncLocalStorage","RandomIdGenerator","createHash","SamplingDecision","TraceFlags","ROOT_CONTEXT","SpanKind","trace"],"mappings":"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"}
|