autotel 6.3.0 → 6.4.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.
Files changed (55) hide show
  1. package/dist/auto.cjs +1 -1
  2. package/dist/auto.js +1 -1
  3. package/dist/{canonical-log-line-processor-mKABvGP0.js → canonical-log-line-processor-B0vq_QR6.js} +3 -1
  4. package/dist/{canonical-log-line-processor-DOjb6Kxy.cjs → canonical-log-line-processor-DxtBGZIi.cjs} +3 -1
  5. package/dist/correlation-id.cjs +1 -1
  6. package/dist/correlation-id.js +1 -1
  7. package/dist/decorators.cjs +1 -1
  8. package/dist/decorators.d.cts +1 -1
  9. package/dist/decorators.d.ts +1 -1
  10. package/dist/decorators.js +1 -1
  11. package/dist/event.cjs +1 -1
  12. package/dist/event.js +1 -1
  13. package/dist/{functional-DCBhFool.js → functional-0o9xSedq.js} +221 -283
  14. package/dist/functional-AT22vCw6.d.ts +389 -0
  15. package/dist/functional-e6jw5zQj.d.cts +389 -0
  16. package/dist/{functional-TbnG2lu7.cjs → functional-qZxRcIBp.cjs} +221 -283
  17. package/dist/functional.cjs +1 -1
  18. package/dist/functional.d.cts +2 -432
  19. package/dist/functional.d.ts +2 -432
  20. package/dist/functional.js +1 -1
  21. package/dist/http.cjs +1 -1
  22. package/dist/http.js +1 -1
  23. package/dist/index.cjs +3 -3
  24. package/dist/index.d.cts +2 -2
  25. package/dist/index.d.ts +2 -2
  26. package/dist/index.js +3 -3
  27. package/dist/{init-BneZ7WJ8.cjs → init-BnxHAi2M.cjs} +19 -10
  28. package/dist/{init-Qn4gIW1i.js → init-BxfZ3Vbw.js} +19 -10
  29. package/dist/{init-CfVWN4ND.d.cts → init-Cc7-vvzj.d.cts} +18 -0
  30. package/dist/{init-C1i2_2zl.d.ts → init-CsODvlau.d.ts} +18 -0
  31. package/dist/instrumentation.cjs +1 -1
  32. package/dist/instrumentation.js +1 -1
  33. package/dist/messaging.cjs +1 -1
  34. package/dist/messaging.js +1 -1
  35. package/dist/policy-CbpP4tFH.d.cts +147 -0
  36. package/dist/policy-CbpP4tFH.d.ts +147 -0
  37. package/dist/policy.cjs +0 -0
  38. package/dist/policy.d.cts +2 -0
  39. package/dist/policy.d.ts +2 -0
  40. package/dist/policy.js +0 -0
  41. package/dist/processors.cjs +1 -1
  42. package/dist/processors.js +1 -1
  43. package/dist/semantic-helpers.cjs +1 -1
  44. package/dist/semantic-helpers.js +1 -1
  45. package/dist/webhook.cjs +1 -1
  46. package/dist/webhook.js +1 -1
  47. package/dist/workflow-distributed.cjs +1 -1
  48. package/dist/workflow-distributed.js +1 -1
  49. package/dist/workflow.cjs +1 -1
  50. package/dist/workflow.js +1 -1
  51. package/dist/yaml-config.cjs +1 -0
  52. package/dist/yaml-config.d.cts +3 -1
  53. package/dist/yaml-config.d.ts +3 -1
  54. package/dist/yaml-config.js +1 -0
  55. package/package.json +6 -1
@@ -1,7 +1,7 @@
1
1
  import { getForceFlushableProvider } from "./tracer-provider.js";
2
2
  import { getConfig } from "./config.js";
3
3
  import { AUTOTEL_SAMPLING_RATE, AUTOTEL_SAMPLING_TAIL_EVALUATED, AUTOTEL_SAMPLING_TAIL_KEEP, AlwaysSampler } from "./sampling.js";
4
- import { D as getActiveContextWithBaggage, O as getContextStorage, T as createTraceContext, h as getEventQueue, m as runInOperationContext, r as getSdk, t as getConfig$1 } from "./init-Qn4gIW1i.js";
4
+ import { D as getActiveContextWithBaggage, O as getContextStorage, T as createTraceContext, h as getEventQueue, m as runInOperationContext, r as getSdk, t as getConfig$1 } from "./init-BxfZ3Vbw.js";
5
5
  import { setSpanName } from "./trace-helpers.js";
6
6
  import { SpanStatusCode, context, propagation, trace } from "@opentelemetry/api";
7
7
  import * as nodeFs from "node:fs";
@@ -34,6 +34,11 @@ function captureStackTrace() {
34
34
  Error.stackTraceLimit = originalStackTraceLimit;
35
35
  return stack;
36
36
  }
37
+ const INTERNAL_FRAME = new RegExp(String.raw`(?:${[
38
+ "variable-name-inference",
39
+ "functional",
40
+ "functional-wrapper"
41
+ ].join("|")})\.(?:ts|js)`);
37
42
  /**
38
43
  * Parses the stack trace to find where trace() was called
39
44
  *
@@ -41,7 +46,7 @@ function captureStackTrace() {
41
46
  * at functionName (file:line:column)
42
47
  * at file:line:column
43
48
  *
44
- * We skip frames until we find one that's NOT in functional.ts or this file.
49
+ * We skip frames until we find one that's not in the functional API internals.
45
50
  * We also need to skip one additional frame (the trace/span/instrument function itself)
46
51
  * to get to the actual user code.
47
52
  */
@@ -49,7 +54,7 @@ function parseCallLocation(stack) {
49
54
  const lines = stack.split("\n");
50
55
  let skippedExternalFrame = false;
51
56
  for (const line of lines) {
52
- if (line.includes("variable-name-inference.ts") || line.includes("variable-name-inference.js") || line.includes("functional.ts") || line.includes("functional.js")) continue;
57
+ if (INTERNAL_FRAME.test(line)) continue;
53
58
  const match = line.match(/at\s+(?:.*\s+)?\(?([^:]+):(\d+):(\d+)\)?/) || line.match(/^.*?([^:]+):(\d+):(\d+)/);
54
59
  if (match) {
55
60
  let filePath = match[1].trim();
@@ -147,68 +152,35 @@ function inferVariableNameFromCallStack() {
147
152
  }
148
153
 
149
154
  //#endregion
150
- //#region src/functional.ts
151
- /**
152
- * Functional API for non-class code
153
- *
154
- * Three approaches for different use cases:
155
- * 1. trace() - Zero-ceremony HOF for single functions
156
- * 2. withTracing() - Middleware-style composable wrapper
157
- * 3. instrument() - Batch auto-instrumentation for modules
158
- *
159
- * @example trace() - Single function
160
- * ```typescript
161
- * export const createUser = trace(async (data) => {
162
- * getActiveTraceContext()?.setAttribute('user.id', data.id)
163
- * return await db.users.create(data)
164
- * })
165
- * ```
166
- *
167
- * @example withTracing() - Composable middleware
168
- * ```typescript
169
- * export const createUser = withTracing({
170
- * name: 'user.create'
171
- * })(ctx => async (data) => {
172
- * ctx.setAttribute('user.id', data.id)
173
- * return await db.users.create(data)
174
- * })
175
- * ```
176
- *
177
- * @example instrument() - Batch instrumentation
178
- * ```typescript
179
- * export default instrument({
180
- * createUser: async (data) => { },
181
- * updateUser: async (id, data) => { }
182
- * }, { serviceName: 'user' })
183
- * ```
184
- */
155
+ //#region src/functional-wrapper.ts
156
+ const FUNCTIONAL_ERROR_MESSAGE_LIMIT = 500;
157
+ const AUTOTEL_INPUT_ATTR = "autotel.input";
158
+ const AUTOTEL_OUTPUT_ATTR = "autotel.output";
159
+ const CAPTURE_MAX_CHARS = 4096;
185
160
  let unknownSpanNameWarningEmitted = false;
161
+ function inferFunctionName(fn) {
162
+ if (fn.displayName) return fn.displayName;
163
+ if (fn.name && fn.name !== "anonymous") return fn.name;
164
+ const match = Function.prototype.toString.call(fn).match(/function\s+([^(\s]+)/);
165
+ return match?.[1] && match[1] !== "anonymous" ? match[1] : void 0;
166
+ }
186
167
  function resolveVariableName(named, variableName) {
187
168
  const suppliedFunctionName = inferFunctionName(named);
188
169
  const callStackVariableName = suppliedFunctionName ? void 0 : inferVariableNameFromCallStack();
189
170
  return variableName || suppliedFunctionName || callStackVariableName;
190
171
  }
191
- /**
192
- * Wrap an explicit context factory `(ctx) => (...args) => result`.
193
- * Used by {@link withTracing}; the input is a factory by contract, so there is
194
- * no plain-vs-factory detection. The factory is never invoked at construction
195
- * time — only when the wrapper is called.
196
- */
197
- function wrapFactoryWithTracing(factory, options, variableName) {
198
- return wrapWithTracingSync(factory, options, resolveVariableName(factory, variableName));
199
- }
200
- /**
201
- * Wrap a plain function `(...args) => result`. Used by {@link trace} and
202
- * {@link instrument}: the function receives its real arguments and no context
203
- * is injected. Reach the active span via {@link getActiveTraceContext} inside
204
- * the body (or any helper it calls).
205
- */
206
- function wrapPlainWithTracing(fn, options, variableName) {
207
- const effectiveVariableName = resolveVariableName(fn, variableName);
208
- const factory = (_ctx) => fn;
209
- return wrapWithTracingSync(factory, options, effectiveVariableName);
172
+ function getSpanName(options, fn, variableName) {
173
+ if (options.name) return options.name;
174
+ const fnName = variableName || inferFunctionName(fn) || "anonymous";
175
+ if (options.serviceName) return `${options.serviceName}.${fnName}`;
176
+ if (fnName !== "anonymous") return fnName;
177
+ const initConfig = getConfig$1();
178
+ if (typeof process !== "undefined" && process.env.NODE_ENV !== "production" && !unknownSpanNameWarningEmitted && initConfig?.logger?.warn) {
179
+ unknownSpanNameWarningEmitted = true;
180
+ initConfig.logger.warn({}, "[autotel] Span name resolved to \"unknown\". Pass an explicit name, for example trace(\"operation.name\", fn).");
181
+ }
182
+ return "unknown";
210
183
  }
211
- const MAX_ERROR_MESSAGE_LENGTH = 500;
212
184
  function createDummyCtx() {
213
185
  return {
214
186
  traceId: "",
@@ -229,11 +201,6 @@ function createDummyCtx() {
229
201
  getAllBaggage: () => /* @__PURE__ */ new Map()
230
202
  };
231
203
  }
232
- /** Attribute keys for opt-in function I/O capture (see TracingOptions). */
233
- const AUTOTEL_INPUT_ATTR = "autotel.input";
234
- const AUTOTEL_OUTPUT_ATTR = "autotel.output";
235
- const CAPTURE_MAX_CHARS = 4096;
236
- /** JSON-serialize a captured value, defensively (truncate, swallow cycles). */
237
204
  function serializeCapture(value) {
238
205
  if (value === void 0) return void 0;
239
206
  try {
@@ -244,41 +211,21 @@ function serializeCapture(value) {
244
211
  return;
245
212
  }
246
213
  }
247
- /** `autotel.input` from args (single arg captured directly, else the array). */
248
214
  function captureInputAttrs(args, enabled) {
249
215
  if (!enabled) return {};
250
- const s = serializeCapture(args.length === 1 ? args[0] : args);
251
- return s === void 0 ? {} : { [AUTOTEL_INPUT_ATTR]: s };
216
+ const serialized = serializeCapture(args.length === 1 ? args[0] : args);
217
+ return serialized === void 0 ? {} : { [AUTOTEL_INPUT_ATTR]: serialized };
252
218
  }
253
- /** `autotel.output` from the return value. */
254
219
  function captureOutputAttrs(result, enabled) {
255
220
  if (!enabled) return {};
256
- const s = serializeCapture(result);
257
- return s === void 0 ? {} : { [AUTOTEL_OUTPUT_ATTR]: s };
258
- }
259
- const INSTRUMENTED_SYMBOL = Symbol.for("autotel.functional.instrumented");
260
- function hasInstrumentationFlag(value) {
261
- return (typeof value === "function" || typeof value === "object") && value !== null && Boolean(value[INSTRUMENTED_SYMBOL]);
221
+ const serialized = serializeCapture(result);
222
+ return serialized === void 0 ? {} : { [AUTOTEL_OUTPUT_ATTR]: serialized };
262
223
  }
263
- /**
264
- * Truncate error message to prevent span bloat
265
- */
266
224
  function truncateErrorMessage(message) {
267
- if (message.length <= MAX_ERROR_MESSAGE_LENGTH) return message;
268
- return `${message.slice(0, MAX_ERROR_MESSAGE_LENGTH)}... (truncated)`;
225
+ return message.length <= 500 ? message : `${message.slice(0, 500)}... (truncated)`;
269
226
  }
270
- /**
271
- * Terminal handling for a value thrown by a traced function. Shared by all four
272
- * `trace()` execution paths (immediate + wrapper, sync + async) so the outcome
273
- * rules live in exactly one place. Ends the span; the caller flushes (await/void)
274
- * and rethrows.
275
- *
276
- * If `isError` classifies the throw as expected control flow — e.g. a framework
277
- * `redirect()` / `notFound()` signal — it is recorded as a success outcome with
278
- * an OK status and no exception. Otherwise it is recorded as an error.
279
- */
280
- function finalizeThrownSpan(error, isError, ctx) {
281
- const { span, spanName, duration, callCounter, durationHistogram, handleTailSampling, extraAttributes } = ctx;
227
+ function finalizeThrownSpan(error, isError, finalizeContext) {
228
+ const { span, spanName, duration, callCounter, durationHistogram, handleTailSampling, extraAttributes } = finalizeContext;
282
229
  const baseAttributes = {
283
230
  ...extraAttributes,
284
231
  "operation.name": spanName,
@@ -323,45 +270,197 @@ function finalizeThrownSpan(error, isError, ctx) {
323
270
  "exception.type": error instanceof Error ? error.constructor.name : "Error",
324
271
  "exception.message": truncatedMessage
325
272
  });
326
- if (error instanceof Error && error.stack) span.setAttribute("exception.stack", error.stack.slice(0, MAX_ERROR_MESSAGE_LENGTH));
273
+ if (error instanceof Error && error.stack) span.setAttribute("exception.stack", error.stack.slice(0, 500));
327
274
  const thrown = error instanceof Error ? error : new Error(String(error));
328
275
  span.recordException(thrown);
329
276
  handleTailSampling(false, duration, thrown);
330
277
  span.end();
331
278
  }
332
- /**
333
- * Try to infer function name from function properties
334
- * Checks for displayName, name, or other metadata that might be set
335
- */
336
- function inferFunctionName(fn) {
337
- const displayName = fn.displayName;
338
- if (displayName) return displayName;
339
- if (fn.name && fn.name !== "anonymous" && fn.name !== "") return fn.name;
340
- const match = Function.prototype.toString.call(fn).match(/function\s+([^(\s]+)/);
341
- if (match && match[1] && match[1] !== "anonymous") return match[1];
342
- }
343
- /**
344
- * Determine span name using priority:
345
- * 1. Explicit name option
346
- * 2. serviceName + functionName
347
- * 3. Inferred from function/variable name (including stack trace fallback)
348
- * 4. Fallback to 'unknown'
349
- */
350
- function getSpanName(options, fn, variableName) {
351
- if (options.name) return options.name;
352
- let fnName = variableName || inferFunctionName(fn);
353
- fnName = fnName || "anonymous";
354
- if (options.serviceName) return `${options.serviceName}.${fnName}`;
355
- if (fnName && fnName !== "anonymous") return fnName;
279
+ function createRootTelemetryFlusher(options, isRootSpan) {
356
280
  const initConfig = getConfig$1();
357
- if (typeof process !== "undefined" && process.env.NODE_ENV !== "production" && !unknownSpanNameWarningEmitted && initConfig?.logger?.warn) {
358
- unknownSpanNameWarningEmitted = true;
359
- initConfig.logger.warn({}, "[autotel] Span name resolved to \"unknown\". Pass an explicit name, for example trace(\"operation.name\", fn).");
281
+ const shouldFlush = options.flushOnRootSpanEnd ?? initConfig?.flushOnRootSpanEnd ?? true;
282
+ const shouldFlushSpans = initConfig?.forceFlushOnShutdown ?? false;
283
+ return async () => {
284
+ if (!shouldFlush || !isRootSpan) return;
285
+ try {
286
+ const queue = getEventQueue();
287
+ if (queue && queue.size() > 0) await queue.flush();
288
+ if (shouldFlushSpans) await getForceFlushableProvider(getSdk())?.forceFlush();
289
+ } catch (error) {
290
+ getConfig$1()?.logger?.error?.({ err: error instanceof Error ? error : void 0 }, `[autotel] Auto-flush failed${error instanceof Error ? "" : `: ${String(error)}`}`);
291
+ }
292
+ };
293
+ }
294
+ function runWithTraceContextStorage(fn) {
295
+ const storage = getContextStorage();
296
+ if (storage.getStore()) return fn();
297
+ return storage.run({ value: context.active() }, fn);
298
+ }
299
+ function wrapWithTracingSync(fnFactory, options, variableName) {
300
+ const { tracer, meter } = getConfig();
301
+ const sampler = options.sampler || new AlwaysSampler();
302
+ const spanName = getSpanName(options, fnFactory, variableName);
303
+ const callCounter = options.withMetrics ? meter.createCounter(`${spanName}.calls`, {
304
+ description: `Call count for ${spanName}`,
305
+ unit: "1"
306
+ }) : void 0;
307
+ const durationHistogram = options.withMetrics ? meter.createHistogram(`${spanName}.duration`, {
308
+ description: `Duration for ${spanName}`,
309
+ unit: "ms"
310
+ }) : void 0;
311
+ function wrappedFunction(...args) {
312
+ const samplingContext = {
313
+ operationName: spanName,
314
+ args,
315
+ metadata: {}
316
+ };
317
+ const shouldSample = sampler.shouldSample(samplingContext);
318
+ const sampleRate = sampler.sampleRate?.(samplingContext);
319
+ const needsTailSampling = sampler.needsTailSampling?.() ?? false;
320
+ if (!shouldSample && !needsTailSampling) return fnFactory(createDummyCtx()).call(this, ...args);
321
+ const startTime = performance.now();
322
+ const flushRootTelemetry = createRootTelemetryFlusher(options, options.startNewRoot || trace.getActiveSpan() === void 0);
323
+ const spanOptions = {};
324
+ if (options.startNewRoot) spanOptions.root = true;
325
+ if (options.spanKind !== void 0) spanOptions.kind = options.spanKind;
326
+ return tracer.startActiveSpan(spanName, spanOptions, getActiveContextWithBaggage(), (span) => runInOperationContext(spanName, () => runWithTraceContextStorage(() => {
327
+ let shouldKeepSpan = true;
328
+ setSpanName(span, spanName);
329
+ if (sampleRate !== void 0 && sampleRate > 1) span.setAttribute(AUTOTEL_SAMPLING_RATE, sampleRate);
330
+ const fn = fnFactory(createTraceContext(span));
331
+ const argsAttributes = {
332
+ ...captureInputAttrs(args, options.captureInput),
333
+ ...options.attributesFromArgs ? options.attributesFromArgs(args) : {}
334
+ };
335
+ const handleTailSampling = (success, duration, error) => {
336
+ if (needsTailSampling && sampler.shouldKeepTrace) {
337
+ shouldKeepSpan = sampler.shouldKeepTrace(samplingContext, {
338
+ success,
339
+ duration,
340
+ error
341
+ });
342
+ span.setAttribute(AUTOTEL_SAMPLING_TAIL_KEEP, shouldKeepSpan);
343
+ span.setAttribute(AUTOTEL_SAMPLING_TAIL_EVALUATED, true);
344
+ }
345
+ };
346
+ const onSuccess = (result) => {
347
+ const duration = performance.now() - startTime;
348
+ callCounter?.add(1, {
349
+ operation: spanName,
350
+ status: "success"
351
+ });
352
+ durationHistogram?.record(duration, {
353
+ operation: spanName,
354
+ status: "success"
355
+ });
356
+ const resultAttributes = {
357
+ ...captureOutputAttrs(result, options.captureOutput),
358
+ ...options.attributesFromResult ? options.attributesFromResult(result) : {}
359
+ };
360
+ span.setStatus({ code: SpanStatusCode.OK });
361
+ span.setAttributes({
362
+ ...argsAttributes,
363
+ ...resultAttributes,
364
+ "operation.name": spanName,
365
+ "code.function": spanName,
366
+ "operation.duration": duration,
367
+ "operation.success": true
368
+ });
369
+ handleTailSampling(true, duration);
370
+ span.end();
371
+ return result;
372
+ };
373
+ const onError = (error) => {
374
+ finalizeThrownSpan(error, options.isError, {
375
+ span,
376
+ spanName,
377
+ duration: performance.now() - startTime,
378
+ callCounter,
379
+ durationHistogram,
380
+ handleTailSampling,
381
+ extraAttributes: argsAttributes
382
+ });
383
+ throw error;
384
+ };
385
+ try {
386
+ callCounter?.add(1, {
387
+ operation: spanName,
388
+ status: "started"
389
+ });
390
+ const result = context.with(trace.setSpan(getActiveContextWithBaggage(), span), () => fn.call(this, ...args));
391
+ if (result instanceof Promise) return result.then(async (value) => {
392
+ const completed = onSuccess(value);
393
+ await flushRootTelemetry();
394
+ return completed;
395
+ }, async (error) => {
396
+ try {
397
+ return onError(error);
398
+ } finally {
399
+ await flushRootTelemetry();
400
+ }
401
+ });
402
+ const completed = onSuccess(result);
403
+ flushRootTelemetry();
404
+ return completed;
405
+ } catch (error) {
406
+ try {
407
+ return onError(error);
408
+ } finally {
409
+ flushRootTelemetry();
410
+ }
411
+ }
412
+ })));
360
413
  }
361
- return "unknown";
414
+ Object.defineProperty(wrappedFunction, "name", {
415
+ value: variableName || "trace",
416
+ configurable: true
417
+ });
418
+ return wrappedFunction;
362
419
  }
420
+ /** Wrap an explicit `(ctx) => (...args) => result` context factory. */
421
+ function wrapFactoryWithTracing(factory, options, variableName) {
422
+ return wrapWithTracingSync(factory, options, resolveVariableName(factory, variableName));
423
+ }
424
+ /** Wrap a plain function without injecting a context argument. */
425
+ function wrapPlainWithTracing(fn, options, variableName) {
426
+ return wrapWithTracingSync((_ctx) => fn, options, resolveVariableName(fn, variableName));
427
+ }
428
+
429
+ //#endregion
430
+ //#region src/functional.ts
363
431
  /**
364
- * Check if function should be skipped
432
+ * Functional API for non-class code
433
+ *
434
+ * Three approaches for different use cases:
435
+ * 1. trace() - Zero-ceremony HOF for single functions
436
+ * 2. withTracing() - Middleware-style composable wrapper
437
+ * 3. instrument() - Batch auto-instrumentation for modules
438
+ *
439
+ * @example trace() - Single function
440
+ * ```typescript
441
+ * export const createUser = trace(async (data) => {
442
+ * getActiveTraceContext()?.setAttribute('user.id', data.id)
443
+ * return await db.users.create(data)
444
+ * })
445
+ * ```
446
+ *
447
+ * @example withTracing() - Composable middleware
448
+ * ```typescript
449
+ * export const createUser = withTracing({
450
+ * name: 'user.create'
451
+ * })(ctx => async (data) => {
452
+ * ctx.setAttribute('user.id', data.id)
453
+ * return await db.users.create(data)
454
+ * })
455
+ * ```
456
+ *
457
+ * @example instrument() - Batch instrumentation
458
+ * ```typescript
459
+ * export default instrument({
460
+ * createUser: async (data) => { },
461
+ * updateUser: async (id, data) => { }
462
+ * }, { serviceName: 'user' })
463
+ * ```
365
464
  */
366
465
  function shouldSkip(key, fn, skip) {
367
466
  if (key.startsWith("_")) return true;
@@ -443,167 +542,6 @@ const ctx = new Proxy({}, {
443
542
  return Object.getOwnPropertyDescriptor(ctxValue, prop);
444
543
  }
445
544
  });
446
- /**
447
- * Build the root-operation flush policy once and reuse it for wrapped and
448
- * immediate execution. Async operations await this function; sync operations
449
- * trigger it without blocking.
450
- */
451
- function createRootTelemetryFlusher(options, isRootSpan) {
452
- const initConfig = getConfig$1();
453
- const shouldFlush = options.flushOnRootSpanEnd ?? initConfig?.flushOnRootSpanEnd ?? true;
454
- const shouldFlushSpans = initConfig?.forceFlushOnShutdown ?? false;
455
- return async () => {
456
- if (!shouldFlush || !isRootSpan) return;
457
- try {
458
- const queue = getEventQueue();
459
- if (queue && queue.size() > 0) await queue.flush();
460
- if (shouldFlushSpans) await getForceFlushableProvider(getSdk())?.forceFlush();
461
- } catch (error) {
462
- (getConfig$1()?.logger)?.error?.({ err: error instanceof Error ? error : void 0 }, `[autotel] Auto-flush failed${error instanceof Error ? "" : `: ${String(error)}`}`);
463
- }
464
- };
465
- }
466
- /**
467
- * Give every root operation its own baggage context without replacing a
468
- * caller's existing scope. AsyncLocalStorage keeps the scope alive until an
469
- * async result settles and restores the previous store afterwards.
470
- */
471
- function runWithTraceContextStorage(fn) {
472
- const storage = getContextStorage();
473
- if (storage.getStore()) return fn();
474
- return storage.run({ value: context.active() }, fn);
475
- }
476
- /**
477
- * Core tracing wrapper for sync functions (internal implementation)
478
- */
479
- function wrapWithTracingSync(fnFactory, options, variableName) {
480
- if (hasInstrumentationFlag(fnFactory)) {}
481
- const config = getConfig();
482
- const tracer = config.tracer;
483
- const meter = config.meter;
484
- const sampler = options.sampler || new AlwaysSampler();
485
- const spanName = getSpanName(options, fnFactory, variableName);
486
- const callCounter = options.withMetrics ? meter.createCounter(`${spanName}.calls`, {
487
- description: `Call count for ${spanName}`,
488
- unit: "1"
489
- }) : void 0;
490
- const durationHistogram = options.withMetrics ? meter.createHistogram(`${spanName}.duration`, {
491
- description: `Duration for ${spanName}`,
492
- unit: "ms"
493
- }) : void 0;
494
- function wrappedFunction(...args) {
495
- const samplingContext = {
496
- operationName: spanName,
497
- args,
498
- metadata: {}
499
- };
500
- const shouldSample = sampler.shouldSample(samplingContext);
501
- const sampleRate = sampler.sampleRate?.(samplingContext);
502
- const needsTailSampling = sampler.needsTailSampling?.() ?? false;
503
- if (!shouldSample && !needsTailSampling) return fnFactory(createDummyCtx()).call(this, ...args);
504
- const startTime = performance.now();
505
- const flushRootTelemetry = createRootTelemetryFlusher(options, options.startNewRoot || trace.getActiveSpan() === void 0);
506
- const spanOptions = {};
507
- if (options.startNewRoot) spanOptions.root = true;
508
- if (options.spanKind !== void 0) spanOptions.kind = options.spanKind;
509
- const parentContext = getActiveContextWithBaggage();
510
- return tracer.startActiveSpan(spanName, spanOptions, parentContext, (span) => {
511
- return runInOperationContext(spanName, () => runWithTraceContextStorage(() => {
512
- let shouldKeepSpan = true;
513
- setSpanName(span, spanName);
514
- if (sampleRate !== void 0 && sampleRate > 1) span.setAttribute(AUTOTEL_SAMPLING_RATE, sampleRate);
515
- const fn = fnFactory(createTraceContext(span));
516
- const argsAttributes = {
517
- ...captureInputAttrs(args, options.captureInput),
518
- ...options.attributesFromArgs ? options.attributesFromArgs(args) : {}
519
- };
520
- const handleTailSampling = (success, duration, error) => {
521
- if (needsTailSampling && sampler.shouldKeepTrace) {
522
- shouldKeepSpan = sampler.shouldKeepTrace(samplingContext, {
523
- success,
524
- duration,
525
- error
526
- });
527
- span.setAttribute(AUTOTEL_SAMPLING_TAIL_KEEP, shouldKeepSpan);
528
- span.setAttribute(AUTOTEL_SAMPLING_TAIL_EVALUATED, true);
529
- }
530
- };
531
- const onSuccess = (result) => {
532
- const duration = performance.now() - startTime;
533
- callCounter?.add(1, {
534
- operation: spanName,
535
- status: "success"
536
- });
537
- durationHistogram?.record(duration, {
538
- operation: spanName,
539
- status: "success"
540
- });
541
- const resultAttributes = {
542
- ...captureOutputAttrs(result, options.captureOutput),
543
- ...options.attributesFromResult ? options.attributesFromResult(result) : {}
544
- };
545
- span.setStatus({ code: SpanStatusCode.OK });
546
- span.setAttributes({
547
- ...argsAttributes,
548
- ...resultAttributes,
549
- "operation.name": spanName,
550
- "code.function": spanName,
551
- "operation.duration": duration,
552
- "operation.success": true
553
- });
554
- handleTailSampling(true, duration);
555
- span.end();
556
- return result;
557
- };
558
- const onError = (error) => {
559
- finalizeThrownSpan(error, options.isError, {
560
- span,
561
- spanName,
562
- duration: performance.now() - startTime,
563
- callCounter,
564
- durationHistogram,
565
- handleTailSampling,
566
- extraAttributes: argsAttributes
567
- });
568
- throw error;
569
- };
570
- try {
571
- callCounter?.add(1, {
572
- operation: spanName,
573
- status: "started"
574
- });
575
- const result = context.with(getActiveContextWithBaggage(), () => fn.call(this, ...args));
576
- if (result instanceof Promise) return result.then(async (value) => {
577
- const completed = onSuccess(value);
578
- await flushRootTelemetry();
579
- return completed;
580
- }, async (error) => {
581
- try {
582
- return onError(error);
583
- } finally {
584
- await flushRootTelemetry();
585
- }
586
- });
587
- const completed = onSuccess(result);
588
- flushRootTelemetry();
589
- return completed;
590
- } catch (error) {
591
- try {
592
- return onError(error);
593
- } finally {
594
- flushRootTelemetry();
595
- }
596
- }
597
- }));
598
- });
599
- }
600
- wrappedFunction[INSTRUMENTED_SYMBOL] = true;
601
- Object.defineProperty(wrappedFunction, "name", {
602
- value: variableName || "trace",
603
- configurable: true
604
- });
605
- return wrappedFunction;
606
- }
607
545
  function trace$1(fnOrNameOrOptions, maybeFn) {
608
546
  if (typeof fnOrNameOrOptions === "function") return wrapPlainWithTracing(fnOrNameOrOptions, {});
609
547
  if (!maybeFn) throw new Error("trace(name|options, fn): fn is required");
@@ -694,7 +632,7 @@ function span(nameOrOptions, fn) {
694
632
  span.end();
695
633
  return resolved;
696
634
  }).catch((error) => {
697
- const errorMessage = error instanceof Error ? error.message.slice(0, MAX_ERROR_MESSAGE_LENGTH) : String(error).slice(0, MAX_ERROR_MESSAGE_LENGTH);
635
+ const errorMessage = error instanceof Error ? error.message.slice(0, 500) : String(error).slice(0, 500);
698
636
  span.setAttribute("error.message", errorMessage);
699
637
  span.setStatus({
700
638
  code: SpanStatusCode.ERROR,
@@ -710,7 +648,7 @@ function span(nameOrOptions, fn) {
710
648
  return result;
711
649
  }
712
650
  } catch (error) {
713
- const errorMessage = error instanceof Error ? error.message.slice(0, MAX_ERROR_MESSAGE_LENGTH) : String(error).slice(0, MAX_ERROR_MESSAGE_LENGTH);
651
+ const errorMessage = error instanceof Error ? error.message.slice(0, 500) : String(error).slice(0, 500);
714
652
  span.setAttribute("error.message", errorMessage);
715
653
  span.setStatus({
716
654
  code: SpanStatusCode.ERROR,