autotel 7.2.0 → 7.4.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 +16 -14
- package/dist/auto.cjs +1 -1
- package/dist/auto.js +1 -1
- package/dist/correlation-id.cjs +1 -1
- package/dist/correlation-id.js +1 -1
- package/dist/decorators.cjs +1 -1
- package/dist/decorators.js +1 -1
- package/dist/event.cjs +1 -1
- package/dist/event.js +1 -1
- package/dist/feature-flags.cjs +204 -0
- package/dist/feature-flags.d.cts +175 -0
- package/dist/feature-flags.d.ts +175 -0
- package/dist/feature-flags.js +198 -0
- package/dist/{functional-Doi0hFm3.js → functional-C4js2vTM.js} +5 -2
- package/dist/{functional-C925G95W.cjs → functional-DHlD7V0x.cjs} +5 -2
- 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 +2 -2
- package/dist/index.js +2 -2
- package/dist/{init-DzAdgcFM.js → init-CsKK9vZO.js} +22 -2
- package/dist/{init-aTZKsAwy.cjs → init-DmM7dprX.cjs} +27 -1
- package/dist/instrumentation.cjs +1 -1
- package/dist/instrumentation.js +1 -1
- package/dist/messaging.cjs +2 -2
- package/dist/messaging.js +2 -2
- package/dist/sampling.cjs +1 -1
- package/dist/sampling.js +1 -1
- package/dist/semantic-helpers.cjs +1 -1
- package/dist/semantic-helpers.js +1 -1
- package/dist/tail-sampling-processor.cjs +1 -1
- package/dist/tail-sampling-processor.js +1 -1
- package/dist/testing.cjs +32 -0
- package/dist/testing.d.cts +26 -1
- package/dist/testing.d.ts +26 -1
- package/dist/testing.js +32 -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 +1 -1
- package/dist/workflow.js +1 -1
- package/dist/yaml-config.cjs +1 -1
- package/dist/yaml-config.js +1 -1
- package/package.json +6 -1
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
import { trace } from "@opentelemetry/api";
|
|
2
|
+
import { logs } from "@opentelemetry/api-logs";
|
|
3
|
+
|
|
4
|
+
//#region src/feature-flags.ts
|
|
5
|
+
/**
|
|
6
|
+
* Feature flag evaluations, in the vocabulary OpenTelemetry already defined.
|
|
7
|
+
*
|
|
8
|
+
* A flagged rollout splits your traffic into two populations that share a
|
|
9
|
+
* service name, a route and a version. Without the flag on the span there is no
|
|
10
|
+
* way to ask the only question that matters during a rollout — is the new
|
|
11
|
+
* branch slower, or failing more, than the old one — and the usual workaround
|
|
12
|
+
* is to read it in the flag vendor's own dashboard, where the latency and the
|
|
13
|
+
* errors are not.
|
|
14
|
+
*
|
|
15
|
+
* The specification covers this: `feature_flag.key`, `.result.value`,
|
|
16
|
+
* `.result.variant`, `.result.reason`, `.provider.name`, `.context.id`, plus a
|
|
17
|
+
* `feature_flag.evaluation` event. Emitting those means any backend can split
|
|
18
|
+
* any metric by variant, with no vendor in the path.
|
|
19
|
+
*
|
|
20
|
+
* ## Attributes and events both
|
|
21
|
+
*
|
|
22
|
+
* Span attributes hold one flag: a second call overwrites the first. A request
|
|
23
|
+
* that branched on three flags needs one event each, which is what the
|
|
24
|
+
* `feature_flag.evaluation` event is for. Both are recorded — attributes so a
|
|
25
|
+
* single-flag span is filterable without unpacking events, events so a
|
|
26
|
+
* many-flag span keeps them all.
|
|
27
|
+
*
|
|
28
|
+
* ## Record what you branched on
|
|
29
|
+
*
|
|
30
|
+
* Record a flag where the code *reads* it, not where it is fetched. A flag
|
|
31
|
+
* evaluated and ignored explains nothing; the value the request actually took a
|
|
32
|
+
* branch on is the one that explains its behaviour.
|
|
33
|
+
*/
|
|
34
|
+
/** Canonical `feature_flag.*` attribute keys. */
|
|
35
|
+
const FEATURE_FLAG = {
|
|
36
|
+
KEY: "feature_flag.key",
|
|
37
|
+
RESULT_VALUE: "feature_flag.result.value",
|
|
38
|
+
RESULT_VARIANT: "feature_flag.result.variant",
|
|
39
|
+
RESULT_REASON: "feature_flag.result.reason",
|
|
40
|
+
PROVIDER_NAME: "feature_flag.provider.name",
|
|
41
|
+
CONTEXT_ID: "feature_flag.context.id",
|
|
42
|
+
SET_ID: "feature_flag.set.id",
|
|
43
|
+
VERSION: "feature_flag.version",
|
|
44
|
+
/**
|
|
45
|
+
* Why an evaluation failed. `feature_flag.evaluation.error.message` is the
|
|
46
|
+
* deprecated spelling of this and is deliberately not emitted — writing both
|
|
47
|
+
* would double the cardinality to no benefit.
|
|
48
|
+
*/
|
|
49
|
+
ERROR_MESSAGE: "feature_flag.error.message"
|
|
50
|
+
};
|
|
51
|
+
/** Canonical event name for one evaluation. */
|
|
52
|
+
const FEATURE_FLAG_EVALUATION_EVENT = "feature_flag.evaluation";
|
|
53
|
+
/**
|
|
54
|
+
* Canonical `feature_flag.result.reason` values. The registry defines them in
|
|
55
|
+
* lower snake case; OpenFeature and most SDKs report them upper-cased, and
|
|
56
|
+
* forwarding that splits every group-by into two buckets meaning the same
|
|
57
|
+
* thing.
|
|
58
|
+
*/
|
|
59
|
+
const FEATURE_FLAG_REASON = [
|
|
60
|
+
"static",
|
|
61
|
+
"default",
|
|
62
|
+
"targeting_match",
|
|
63
|
+
"split",
|
|
64
|
+
"cached",
|
|
65
|
+
"disabled",
|
|
66
|
+
"unknown",
|
|
67
|
+
"stale",
|
|
68
|
+
"error"
|
|
69
|
+
];
|
|
70
|
+
/**
|
|
71
|
+
* A flag value as an attribute.
|
|
72
|
+
*
|
|
73
|
+
* Booleans and numbers are kept as they are: `feature_flag.result.value`
|
|
74
|
+
* permits typed values, and stringifying `true` makes a boolean flag
|
|
75
|
+
* uncomparable with the numeric one next to it. Only a structured value — which
|
|
76
|
+
* no attribute type can hold — is serialised.
|
|
77
|
+
*/
|
|
78
|
+
function asAttributeValue(value) {
|
|
79
|
+
if (typeof value === "string" || typeof value === "boolean" || typeof value === "number" && Number.isFinite(value)) return value;
|
|
80
|
+
try {
|
|
81
|
+
return JSON.stringify(value) ?? String(value);
|
|
82
|
+
} catch {
|
|
83
|
+
return String(value);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
/** Canonical attributes for one evaluation. Absent fields are omitted. */
|
|
87
|
+
function featureFlagAttributes(evaluation) {
|
|
88
|
+
const attributes = {
|
|
89
|
+
[FEATURE_FLAG.KEY]: evaluation.key,
|
|
90
|
+
[FEATURE_FLAG.RESULT_VALUE]: asAttributeValue(evaluation.value)
|
|
91
|
+
};
|
|
92
|
+
const optional = [
|
|
93
|
+
[FEATURE_FLAG.RESULT_VARIANT, evaluation.variant],
|
|
94
|
+
[FEATURE_FLAG.RESULT_REASON, evaluation.reason === void 0 ? void 0 : evaluation.reason.toLowerCase()],
|
|
95
|
+
[FEATURE_FLAG.PROVIDER_NAME, evaluation.provider],
|
|
96
|
+
[FEATURE_FLAG.CONTEXT_ID, evaluation.contextId],
|
|
97
|
+
[FEATURE_FLAG.SET_ID, evaluation.setId],
|
|
98
|
+
[FEATURE_FLAG.VERSION, evaluation.version],
|
|
99
|
+
[FEATURE_FLAG.ERROR_MESSAGE, evaluation.errorMessage]
|
|
100
|
+
];
|
|
101
|
+
for (const [key, value] of optional) if (value !== void 0) attributes[key] = value;
|
|
102
|
+
return attributes;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Record a flag evaluation on `sink` — as attributes and as a
|
|
106
|
+
* `feature_flag.evaluation` event.
|
|
107
|
+
*
|
|
108
|
+
* A missing sink is a no-op: instrumentation must never be the reason a branch
|
|
109
|
+
* throws, and a flag read outside any span is a legitimate thing to do.
|
|
110
|
+
*/
|
|
111
|
+
function recordFeatureFlag(sink, evaluation) {
|
|
112
|
+
if (!sink) return;
|
|
113
|
+
const attributes = featureFlagAttributes(evaluation);
|
|
114
|
+
sink.setAttributes(attributes);
|
|
115
|
+
sink.track?.(FEATURE_FLAG_EVALUATION_EVENT, attributes);
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Emit the evaluation as an OpenTelemetry **log record**.
|
|
119
|
+
*
|
|
120
|
+
* This is the Logs API model the repository emits events through. The obvious
|
|
121
|
+
* shortcut — `Span.addEvent` on the active span — puts the evaluation somewhere
|
|
122
|
+
* no log or event pipeline will ever look, which is exactly the failure the
|
|
123
|
+
* invariant exists to prevent. `correlated-events` is not a way around it
|
|
124
|
+
* either: that helper prefers `addEvent` when the target has one, so routing
|
|
125
|
+
* through it lands in the same place with more indirection.
|
|
126
|
+
*
|
|
127
|
+
* `logs.getLogger` returns a no-op logger when no `LoggerProvider` is
|
|
128
|
+
* registered, so this costs nothing in an application that exports no logs.
|
|
129
|
+
*/
|
|
130
|
+
function emitEvaluationRecord(attributes) {
|
|
131
|
+
logs.getLogger("autotel").emit({
|
|
132
|
+
eventName: FEATURE_FLAG_EVALUATION_EVENT,
|
|
133
|
+
attributes
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
function evaluationFrom(hookContext, value, extra) {
|
|
137
|
+
return {
|
|
138
|
+
key: hookContext.flagKey,
|
|
139
|
+
value,
|
|
140
|
+
provider: hookContext.providerMetadata?.name,
|
|
141
|
+
contextId: hookContext.context?.targetingKey,
|
|
142
|
+
setId: hookContext.clientMetadata?.name,
|
|
143
|
+
...extra
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* An OpenFeature hook that records every evaluation under the canonical
|
|
148
|
+
* `feature_flag.*` convention.
|
|
149
|
+
*
|
|
150
|
+
* This is the zero-config path: OpenFeature already sits between the
|
|
151
|
+
* application and whichever flag vendor it uses, and it already fires on every
|
|
152
|
+
* evaluation — which is exactly the moment worth recording, because it is the
|
|
153
|
+
* moment the code branched.
|
|
154
|
+
*
|
|
155
|
+
* ```ts
|
|
156
|
+
* import { OpenFeature } from '@openfeature/server-sdk';
|
|
157
|
+
* import { autotelOpenFeatureHook } from 'autotel/feature-flags';
|
|
158
|
+
*
|
|
159
|
+
* OpenFeature.addHooks(autotelOpenFeatureHook());
|
|
160
|
+
* ```
|
|
161
|
+
*
|
|
162
|
+
* A failed evaluation is still recorded, with the default value the code
|
|
163
|
+
* actually used and `reason: 'ERROR'`. The default is what the request behaved
|
|
164
|
+
* as; the failure is why.
|
|
165
|
+
*/
|
|
166
|
+
function autotelOpenFeatureHook(options = {}) {
|
|
167
|
+
const getSpan = options.getSpan ?? (() => trace.getActiveSpan());
|
|
168
|
+
const emitLogRecord = options.emitLogRecord ?? emitEvaluationRecord;
|
|
169
|
+
/**
|
|
170
|
+
* Attributes onto the span that branched, and the event wherever the sink
|
|
171
|
+
* says. A sink with no `track` of its own gets a log record — including when
|
|
172
|
+
* there is no span at all, because the evaluation still happened.
|
|
173
|
+
*/
|
|
174
|
+
const record = (evaluation) => {
|
|
175
|
+
const sink = getSpan();
|
|
176
|
+
const attributes = featureFlagAttributes(evaluation);
|
|
177
|
+
sink?.setAttributes(attributes);
|
|
178
|
+
if (sink?.track) sink.track(FEATURE_FLAG_EVALUATION_EVENT, attributes);
|
|
179
|
+
else emitLogRecord(attributes);
|
|
180
|
+
};
|
|
181
|
+
return {
|
|
182
|
+
after(hookContext, details) {
|
|
183
|
+
record(evaluationFrom(hookContext, details.value, {
|
|
184
|
+
variant: details.variant,
|
|
185
|
+
reason: details.reason
|
|
186
|
+
}));
|
|
187
|
+
},
|
|
188
|
+
error(hookContext, error) {
|
|
189
|
+
record(evaluationFrom(hookContext, hookContext.defaultValue, {
|
|
190
|
+
reason: "error",
|
|
191
|
+
errorMessage: error instanceof Error ? error.message : String(error)
|
|
192
|
+
}));
|
|
193
|
+
}
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
//#endregion
|
|
198
|
+
export { FEATURE_FLAG, FEATURE_FLAG_EVALUATION_EVENT, FEATURE_FLAG_REASON, autotelOpenFeatureHook, featureFlagAttributes, recordFeatureFlag };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { l as asString, m as isDevelopment } from "./values-BenyvWKz.js";
|
|
2
2
|
import { getForceFlushableProvider } from "./tracer-provider.js";
|
|
3
3
|
import { getConfig } from "./config.js";
|
|
4
|
-
import { C as
|
|
4
|
+
import { C as AUTOTEL_SAMPLING_RATE, D as AlwaysSampler, G as getActiveContextWithBaggage, I as debugCaptureRequested, J as getEventQueue, K as getContextStorage, T as AUTOTEL_SAMPLING_TAIL_KEEP, U as createTraceContext, h as runInOperationContext, i as getSdk, n as getConfiguredSampler, q as hasExplicitSpanStatus, t as getConfig$1, w as AUTOTEL_SAMPLING_TAIL_EVALUATED, z as isForceKept } from "./init-CsKK9vZO.js";
|
|
5
5
|
import { evidenceAttribute } from "./evidence.js";
|
|
6
6
|
import { setSpanName } from "./trace-helpers.js";
|
|
7
7
|
import { SpanStatusCode, context, propagation, trace } from "@opentelemetry/api";
|
|
@@ -343,9 +343,11 @@ function runWithTraceContextStorage(fn) {
|
|
|
343
343
|
if (storage.getStore()) return fn();
|
|
344
344
|
return storage.run({ value: context.active() }, fn);
|
|
345
345
|
}
|
|
346
|
+
/** Used when neither the wrapper nor `init()` chose a sampler. */
|
|
347
|
+
const FALLBACK_SAMPLER = new AlwaysSampler();
|
|
346
348
|
function wrapWithTracingSync(fnFactory, options, variableName) {
|
|
347
349
|
const { tracer, meter } = getConfig();
|
|
348
|
-
const
|
|
350
|
+
const resolveSampler = () => options.sampler ?? getConfiguredSampler() ?? FALLBACK_SAMPLER;
|
|
349
351
|
const spanName = getSpanName(options, fnFactory, variableName);
|
|
350
352
|
const callCounter = options.withMetrics ? meter.createCounter(`${spanName}.calls`, {
|
|
351
353
|
description: `Call count for ${spanName}`,
|
|
@@ -361,6 +363,7 @@ function wrapWithTracingSync(fnFactory, options, variableName) {
|
|
|
361
363
|
args,
|
|
362
364
|
metadata: {}
|
|
363
365
|
};
|
|
366
|
+
const sampler = resolveSampler();
|
|
364
367
|
const shouldSample = sampler.shouldSample(samplingContext);
|
|
365
368
|
const sampleRate = sampler.sampleRate?.(samplingContext);
|
|
366
369
|
const needsTailSampling = sampler.needsTailSampling?.() ?? false;
|
|
@@ -2,7 +2,7 @@ const require_rolldown_runtime = require('./rolldown-runtime-C_NdSu1c.cjs');
|
|
|
2
2
|
const require_values = require('./values-DApyq53y.cjs');
|
|
3
3
|
const require_tracer_provider = require('./tracer-provider.cjs');
|
|
4
4
|
const require_config = require('./config.cjs');
|
|
5
|
-
const require_init = require('./init-
|
|
5
|
+
const require_init = require('./init-DmM7dprX.cjs');
|
|
6
6
|
const require_evidence = require('./evidence.cjs');
|
|
7
7
|
const require_trace_helpers = require('./trace-helpers.cjs');
|
|
8
8
|
let _opentelemetry_api = require("@opentelemetry/api");
|
|
@@ -346,9 +346,11 @@ function runWithTraceContextStorage(fn) {
|
|
|
346
346
|
if (storage.getStore()) return fn();
|
|
347
347
|
return storage.run({ value: _opentelemetry_api.context.active() }, fn);
|
|
348
348
|
}
|
|
349
|
+
/** Used when neither the wrapper nor `init()` chose a sampler. */
|
|
350
|
+
const FALLBACK_SAMPLER = new require_init.AlwaysSampler();
|
|
349
351
|
function wrapWithTracingSync(fnFactory, options, variableName) {
|
|
350
352
|
const { tracer, meter } = require_config.getConfig();
|
|
351
|
-
const
|
|
353
|
+
const resolveSampler = () => options.sampler ?? require_init.getConfiguredSampler() ?? FALLBACK_SAMPLER;
|
|
352
354
|
const spanName = getSpanName(options, fnFactory, variableName);
|
|
353
355
|
const callCounter = options.withMetrics ? meter.createCounter(`${spanName}.calls`, {
|
|
354
356
|
description: `Call count for ${spanName}`,
|
|
@@ -364,6 +366,7 @@ function wrapWithTracingSync(fnFactory, options, variableName) {
|
|
|
364
366
|
args,
|
|
365
367
|
metadata: {}
|
|
366
368
|
};
|
|
369
|
+
const sampler = resolveSampler();
|
|
367
370
|
const shouldSample = sampler.shouldSample(samplingContext);
|
|
368
371
|
const sampleRate = sampler.sampleRate?.(samplingContext);
|
|
369
372
|
const needsTailSampling = sampler.needsTailSampling?.() ?? false;
|
package/dist/functional.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
-
const require_functional = require('./functional-
|
|
2
|
+
const require_functional = require('./functional-DHlD7V0x.cjs');
|
|
3
3
|
|
|
4
4
|
exports.ctx = require_functional.ctx;
|
|
5
5
|
exports.getActiveTraceContext = require_functional.getActiveTraceContext;
|
package/dist/functional.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { a as trace, c as withTracing, i as span, n as getActiveTraceContext, o as withBaggage, r as instrument, s as withNewContext, t as ctx } from "./functional-
|
|
1
|
+
import { a as trace, c as withTracing, i as span, n as getActiveTraceContext, o as withBaggage, r as instrument, s as withNewContext, t as ctx } from "./functional-C4js2vTM.js";
|
|
2
2
|
|
|
3
3
|
export { ctx, getActiveTraceContext, instrument, span, trace, withBaggage, withNewContext, withTracing };
|
package/dist/http.cjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
2
|
const require_values = require('./values-DApyq53y.cjs');
|
|
3
3
|
const require_config = require('./config.cjs');
|
|
4
|
-
const require_init = require('./init-
|
|
4
|
+
const require_init = require('./init-DmM7dprX.cjs');
|
|
5
5
|
let _opentelemetry_api = require("@opentelemetry/api");
|
|
6
6
|
|
|
7
7
|
//#region src/http.ts
|
package/dist/http.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { _ as readProperty, h as isFunction, i as asNumber, l as asString } from "./values-BenyvWKz.js";
|
|
2
2
|
import { getConfig } from "./config.js";
|
|
3
|
-
import {
|
|
3
|
+
import { G as getActiveContextWithBaggage } from "./init-CsKK9vZO.js";
|
|
4
4
|
import { SpanStatusCode, context, propagation } from "@opentelemetry/api";
|
|
5
5
|
|
|
6
6
|
//#region src/http.ts
|
package/dist/index.cjs
CHANGED
|
@@ -3,13 +3,13 @@ const require_rolldown_runtime = require('./rolldown-runtime-C_NdSu1c.cjs');
|
|
|
3
3
|
const require_values = require('./values-DApyq53y.cjs');
|
|
4
4
|
const require_tracer_provider = require('./tracer-provider.cjs');
|
|
5
5
|
const require_structured_error = require('./structured-error--_wXpd_C.cjs');
|
|
6
|
-
const require_init = require('./init-
|
|
6
|
+
const require_init = require('./init-DmM7dprX.cjs');
|
|
7
7
|
const require_filtering_span_processor = require('./filtering-span-processor.cjs');
|
|
8
8
|
const require_span_name_normalizer = require('./span-name-normalizer.cjs');
|
|
9
9
|
const require_attribute_redacting_processor = require('./attribute-redacting-processor.cjs');
|
|
10
10
|
const require_canonical_log_line_processor = require('./canonical-log-line-processor-DolzdawH.cjs');
|
|
11
11
|
const require_metric = require('./metric.cjs');
|
|
12
|
-
const require_functional = require('./functional-
|
|
12
|
+
const require_functional = require('./functional-DHlD7V0x.cjs');
|
|
13
13
|
const require_trace_helpers = require('./trace-helpers.cjs');
|
|
14
14
|
const require_stable_hash = require('./stable-hash-C0pOegH_.cjs');
|
|
15
15
|
const require_correlated_events = require('./correlated-events-CcuknWnU.cjs');
|
package/dist/index.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { g as nonEmptyString, i as asNumber, l as asString, r as asFunction, s as asRecord, x as toError } from "./values-BenyvWKz.js";
|
|
2
2
|
import { getAutotelTracer, getAutotelTracerProvider, setAutotelTracerProvider } from "./tracer-provider.js";
|
|
3
3
|
import { a as flattenToAttributes, i as structuredErrorToJSON, n as getStructuredErrorAttributes, o as toAttributeValue, r as recordStructuredError, t as createStructuredError } from "./structured-error-YIuka-FE.js";
|
|
4
|
-
import {
|
|
4
|
+
import { B as markForceKept, D as AlwaysSampler, E as AdaptiveSampler, F as createLinkFromHeaders, H as samplingPresets, J as getEventQueue, L as extractLinksFromBatch, M as NeverSampler, N as RandomSampler, P as UserIdSampler, Q as getCorrelationId, S as AUTOTEL_DEBUG_BAGGAGE_KEY, T as AUTOTEL_SAMPLING_TAIL_KEEP, U as createTraceContext, V as resolveSamplingPreset, W as defineBaggageSchema, X as CORRELATION_ID_BAGGAGE_KEY, Y as track, Z as generateCorrelationId, a as init, b as BaggageSpanProcessor, c as lockLogger, d as Event, et as getOrCreateCorrelationId, f as getEvents, h as runInOperationContext, l as flush, m as getOperationContext, nt as setCorrelationId, o as isInitialized, p as resetEvents, rt as setCorrelationIdInBaggage, s as isLoggerLocked, tt as runWithCorrelationId, u as shutdown, w as AUTOTEL_SAMPLING_TAIL_EVALUATED, y as createStringRedactor } from "./init-CsKK9vZO.js";
|
|
5
5
|
import { FilteringSpanProcessor } from "./filtering-span-processor.js";
|
|
6
6
|
import { NORMALIZER_PATTERNS, NORMALIZER_PRESETS, SpanNameNormalizingProcessor } from "./span-name-normalizer.js";
|
|
7
7
|
import { AttributeRedactingProcessor, REDACTOR_PATTERNS, REDACTOR_PRESETS, builtinPatterns, createAttributeRedactor, createRedactedSpan, normalizeAttributeRedactorConfig } from "./attribute-redacting-processor.js";
|
|
8
8
|
import { n as formatDuration } from "./canonical-log-line-processor-hFUmS__K.js";
|
|
9
9
|
import { Metric, getMetrics, resetMetrics } from "./metric.js";
|
|
10
|
-
import { a as trace$2, c as withTracing, i as span, n as getActiveTraceContext, o as withBaggage, r as instrument, s as withNewContext, t as ctx } from "./functional-
|
|
10
|
+
import { a as trace$2, c as withTracing, i as span, n as getActiveTraceContext, o as withBaggage, r as instrument, s as withNewContext, t as ctx } from "./functional-C4js2vTM.js";
|
|
11
11
|
import { createDeterministicTraceId, enrichWithTraceContext, finalizeSpan, flattenMetadata, getActiveContext, getActiveSpan, getTraceContext, getTracer, isTracing, resolveTraceUrl, runWithSpan } from "./trace-helpers.js";
|
|
12
12
|
import { t as hashJson } from "./stable-hash-BkoAYVks.js";
|
|
13
13
|
import { t as emitCorrelatedEvent } from "./correlated-events-DwMMbItg.js";
|
|
@@ -782,6 +782,7 @@ function validateEvent(eventName, attributes, config) {
|
|
|
782
782
|
* Simple, no instantiation needed, auto-attaches trace context
|
|
783
783
|
*/
|
|
784
784
|
let eventsQueue = null;
|
|
785
|
+
let warnedNoSubscribers = false;
|
|
785
786
|
/**
|
|
786
787
|
* Build autotel event context for trace correlation
|
|
787
788
|
*
|
|
@@ -838,7 +839,13 @@ function getOrCreateQueue() {
|
|
|
838
839
|
}
|
|
839
840
|
if (!eventsQueue) {
|
|
840
841
|
const config = getConfig();
|
|
841
|
-
if (!config?.subscribers || config.subscribers.length === 0)
|
|
842
|
+
if (!config?.subscribers || config.subscribers.length === 0) {
|
|
843
|
+
if (!warnedNoSubscribers) {
|
|
844
|
+
warnedNoSubscribers = true;
|
|
845
|
+
getLogger().warn({}, "[autotel] track() dropped an event: init() configured no subscribers. Events (including gen_ai.evaluation.result and audit events) reach a backend through init({ subscribers: [...] }).");
|
|
846
|
+
}
|
|
847
|
+
return null;
|
|
848
|
+
}
|
|
842
849
|
eventsQueue = new EventQueue(config.subscribers);
|
|
843
850
|
}
|
|
844
851
|
return eventsQueue;
|
|
@@ -910,6 +917,7 @@ function getEventQueue() {
|
|
|
910
917
|
*/
|
|
911
918
|
function resetEventQueue() {
|
|
912
919
|
eventsQueue = null;
|
|
920
|
+
warnedNoSubscribers = false;
|
|
913
921
|
}
|
|
914
922
|
|
|
915
923
|
//#endregion
|
|
@@ -4212,6 +4220,18 @@ function warnIfNotInitialized(context) {
|
|
|
4212
4220
|
}
|
|
4213
4221
|
}
|
|
4214
4222
|
/**
|
|
4223
|
+
* The sampler `init()` was configured with, or undefined when it was not.
|
|
4224
|
+
*
|
|
4225
|
+
* Separate from {@link getDefaultSampler} on purpose: the tracing wrapper needs
|
|
4226
|
+
* to know whether a sampler was *chosen*. Falling back to the production preset
|
|
4227
|
+
* there would start dropping spans for every app that never asked to sample.
|
|
4228
|
+
*
|
|
4229
|
+
* @internal
|
|
4230
|
+
*/
|
|
4231
|
+
function getConfiguredSampler() {
|
|
4232
|
+
return config?.sampler;
|
|
4233
|
+
}
|
|
4234
|
+
/**
|
|
4215
4235
|
* @internal Close embedded devtools if running.
|
|
4216
4236
|
*/
|
|
4217
4237
|
async function _closeEmbeddedDevtools() {
|
|
@@ -4228,4 +4248,4 @@ function getSdk() {
|
|
|
4228
4248
|
}
|
|
4229
4249
|
|
|
4230
4250
|
//#endregion
|
|
4231
|
-
export {
|
|
4251
|
+
export { getCorrelationStorage as $, FeatureFlagSampler as A, markForceKept as B, AUTOTEL_SAMPLING_RATE as C, AlwaysSampler as D, AdaptiveSampler as E, createLinkFromHeaders as F, getActiveContextWithBaggage as G, samplingPresets as H, debugCaptureRequested as I, getEventQueue as J, getContextStorage as K, extractLinksFromBatch as L, NeverSampler as M, RandomSampler as N, CompositeSampler as O, UserIdSampler as P, getCorrelationId as Q, hashUnitInterval as R, AUTOTEL_DEBUG_BAGGAGE_KEY as S, AUTOTEL_SAMPLING_TAIL_KEEP as T, createTraceContext as U, resolveSamplingPreset as V, defineBaggageSchema as W, CORRELATION_ID_BAGGAGE_KEY as X, track as Y, generateCorrelationId as Z, loadYamlConfig as _, init as a, BaggageSpanProcessor as b, lockLogger as c, Event as d, getOrCreateCorrelationId as et, getEvents as f, hasYamlConfig as g, runInOperationContext as h, getSdk as i, KeyTargetRateSampler as j, DeterministicSampler as k, flush as l, getOperationContext as m, getConfiguredSampler as n, setCorrelationId as nt, isInitialized as o, resetEvents as p, hasExplicitSpanStatus as q, getLogger as r, setCorrelationIdInBaggage as rt, isLoggerLocked as s, getConfig as t, runWithCorrelationId as tt, shutdown as u, loadYamlConfigFromFile as v, AUTOTEL_SAMPLING_TAIL_EVALUATED as w, TailSamplingSpanProcessor as x, createStringRedactor as y, isForceKept as z };
|
|
@@ -786,6 +786,7 @@ function validateEvent(eventName, attributes, config) {
|
|
|
786
786
|
* Simple, no instantiation needed, auto-attaches trace context
|
|
787
787
|
*/
|
|
788
788
|
let eventsQueue = null;
|
|
789
|
+
let warnedNoSubscribers = false;
|
|
789
790
|
/**
|
|
790
791
|
* Build autotel event context for trace correlation
|
|
791
792
|
*
|
|
@@ -842,7 +843,13 @@ function getOrCreateQueue() {
|
|
|
842
843
|
}
|
|
843
844
|
if (!eventsQueue) {
|
|
844
845
|
const config = getConfig();
|
|
845
|
-
if (!config?.subscribers || config.subscribers.length === 0)
|
|
846
|
+
if (!config?.subscribers || config.subscribers.length === 0) {
|
|
847
|
+
if (!warnedNoSubscribers) {
|
|
848
|
+
warnedNoSubscribers = true;
|
|
849
|
+
getLogger().warn({}, "[autotel] track() dropped an event: init() configured no subscribers. Events (including gen_ai.evaluation.result and audit events) reach a backend through init({ subscribers: [...] }).");
|
|
850
|
+
}
|
|
851
|
+
return null;
|
|
852
|
+
}
|
|
846
853
|
eventsQueue = new EventQueue(config.subscribers);
|
|
847
854
|
}
|
|
848
855
|
return eventsQueue;
|
|
@@ -914,6 +921,7 @@ function getEventQueue() {
|
|
|
914
921
|
*/
|
|
915
922
|
function resetEventQueue() {
|
|
916
923
|
eventsQueue = null;
|
|
924
|
+
warnedNoSubscribers = false;
|
|
917
925
|
}
|
|
918
926
|
|
|
919
927
|
//#endregion
|
|
@@ -4216,6 +4224,18 @@ function warnIfNotInitialized(context) {
|
|
|
4216
4224
|
}
|
|
4217
4225
|
}
|
|
4218
4226
|
/**
|
|
4227
|
+
* The sampler `init()` was configured with, or undefined when it was not.
|
|
4228
|
+
*
|
|
4229
|
+
* Separate from {@link getDefaultSampler} on purpose: the tracing wrapper needs
|
|
4230
|
+
* to know whether a sampler was *chosen*. Falling back to the production preset
|
|
4231
|
+
* there would start dropping spans for every app that never asked to sample.
|
|
4232
|
+
*
|
|
4233
|
+
* @internal
|
|
4234
|
+
*/
|
|
4235
|
+
function getConfiguredSampler() {
|
|
4236
|
+
return config?.sampler;
|
|
4237
|
+
}
|
|
4238
|
+
/**
|
|
4219
4239
|
* @internal Close embedded devtools if running.
|
|
4220
4240
|
*/
|
|
4221
4241
|
async function _closeEmbeddedDevtools() {
|
|
@@ -4394,6 +4414,12 @@ Object.defineProperty(exports, 'getConfig', {
|
|
|
4394
4414
|
return getConfig;
|
|
4395
4415
|
}
|
|
4396
4416
|
});
|
|
4417
|
+
Object.defineProperty(exports, 'getConfiguredSampler', {
|
|
4418
|
+
enumerable: true,
|
|
4419
|
+
get: function () {
|
|
4420
|
+
return getConfiguredSampler;
|
|
4421
|
+
}
|
|
4422
|
+
});
|
|
4397
4423
|
Object.defineProperty(exports, 'getContextStorage', {
|
|
4398
4424
|
enumerable: true,
|
|
4399
4425
|
get: function () {
|
package/dist/instrumentation.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
-
const require_init = require('./init-
|
|
2
|
+
const require_init = require('./init-DmM7dprX.cjs');
|
|
3
3
|
const require_node_require = require('./node-require-EifOMikz.cjs');
|
|
4
4
|
let _opentelemetry_sdk_node = require("@opentelemetry/sdk-node");
|
|
5
5
|
let _opentelemetry_sdk_trace_base = require("@opentelemetry/sdk-trace-base");
|
package/dist/instrumentation.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { r as getLogger, x as TailSamplingSpanProcessor } from "./init-CsKK9vZO.js";
|
|
2
2
|
import { n as safeRequire, t as requireModule } from "./node-require-DSPjaw_l.js";
|
|
3
3
|
import { NodeSDK } from "@opentelemetry/sdk-node";
|
|
4
4
|
import { BatchSpanProcessor } from "@opentelemetry/sdk-trace-base";
|
package/dist/messaging.cjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
2
|
const require_values = require('./values-DApyq53y.cjs');
|
|
3
|
-
const require_init = require('./init-
|
|
4
|
-
const require_functional = require('./functional-
|
|
3
|
+
const require_init = require('./init-DmM7dprX.cjs');
|
|
4
|
+
const require_functional = require('./functional-DHlD7V0x.cjs');
|
|
5
5
|
const require_correlated_events = require('./correlated-events-CcuknWnU.cjs');
|
|
6
6
|
const require_trace_factory_validation = require('./trace-factory-validation-Dc8epn87.cjs');
|
|
7
7
|
let _opentelemetry_api = require("@opentelemetry/api");
|
package/dist/messaging.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { _ as readProperty, b as toAttributeValue, c as asScalar, g as nonEmptyString, h as isFunction, s as asRecord, v as resolveValue, y as splitNameOrOptions } from "./values-BenyvWKz.js";
|
|
2
|
-
import {
|
|
3
|
-
import { c as withTracing } from "./functional-
|
|
2
|
+
import { F as createLinkFromHeaders, L as extractLinksFromBatch } from "./init-CsKK9vZO.js";
|
|
3
|
+
import { c as withTracing } from "./functional-C4js2vTM.js";
|
|
4
4
|
import { t as emitCorrelatedEvent } from "./correlated-events-DwMMbItg.js";
|
|
5
5
|
import { t as assertTraceFactory } from "./trace-factory-validation-BjVAinz6.js";
|
|
6
6
|
import { SpanKind, context, propagation } from "@opentelemetry/api";
|
package/dist/sampling.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
-
const require_init = require('./init-
|
|
2
|
+
const require_init = require('./init-DmM7dprX.cjs');
|
|
3
3
|
|
|
4
4
|
exports.AUTOTEL_DEBUG_BAGGAGE_KEY = require_init.AUTOTEL_DEBUG_BAGGAGE_KEY;
|
|
5
5
|
exports.AUTOTEL_SAMPLING_RATE = require_init.AUTOTEL_SAMPLING_RATE;
|
package/dist/sampling.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { A as
|
|
1
|
+
import { A as FeatureFlagSampler, B as markForceKept, C as AUTOTEL_SAMPLING_RATE, D as AlwaysSampler, E as AdaptiveSampler, F as createLinkFromHeaders, H as samplingPresets, I as debugCaptureRequested, L as extractLinksFromBatch, M as NeverSampler, N as RandomSampler, O as CompositeSampler, P as UserIdSampler, R as hashUnitInterval, S as AUTOTEL_DEBUG_BAGGAGE_KEY, T as AUTOTEL_SAMPLING_TAIL_KEEP, V as resolveSamplingPreset, j as KeyTargetRateSampler, k as DeterministicSampler, w as AUTOTEL_SAMPLING_TAIL_EVALUATED, z as isForceKept } from "./init-CsKK9vZO.js";
|
|
2
2
|
|
|
3
3
|
export { AUTOTEL_DEBUG_BAGGAGE_KEY, AUTOTEL_SAMPLING_RATE, AUTOTEL_SAMPLING_TAIL_EVALUATED, AUTOTEL_SAMPLING_TAIL_KEEP, AdaptiveSampler, AlwaysSampler, CompositeSampler, DeterministicSampler, FeatureFlagSampler, KeyTargetRateSampler, NeverSampler, RandomSampler, UserIdSampler, createLinkFromHeaders, debugCaptureRequested, extractLinksFromBatch, hashUnitInterval, isForceKept, markForceKept, resolveSamplingPreset, samplingPresets };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
2
|
const require_values = require('./values-DApyq53y.cjs');
|
|
3
|
-
const require_functional = require('./functional-
|
|
3
|
+
const require_functional = require('./functional-DHlD7V0x.cjs');
|
|
4
4
|
const require_trace_factory_validation = require('./trace-factory-validation-Dc8epn87.cjs');
|
|
5
5
|
let _opentelemetry_api = require("@opentelemetry/api");
|
|
6
6
|
|
package/dist/semantic-helpers.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { b as toAttributeValue, g as nonEmptyString, s as asRecord } from "./values-BenyvWKz.js";
|
|
2
|
-
import { c as withTracing } from "./functional-
|
|
2
|
+
import { c as withTracing } from "./functional-C4js2vTM.js";
|
|
3
3
|
import { t as assertTraceFactory } from "./trace-factory-validation-BjVAinz6.js";
|
|
4
4
|
import { SpanKind } from "@opentelemetry/api";
|
|
5
5
|
|
package/dist/testing.cjs
CHANGED
|
@@ -8,6 +8,37 @@ let _opentelemetry_api = require("@opentelemetry/api");
|
|
|
8
8
|
let node_async_hooks = require("node:async_hooks");
|
|
9
9
|
node_async_hooks = require_rolldown_runtime.__toESM(node_async_hooks, 1);
|
|
10
10
|
|
|
11
|
+
//#region src/memory-exporter.ts
|
|
12
|
+
function toRecordedSpan(span) {
|
|
13
|
+
return {
|
|
14
|
+
name: span.name,
|
|
15
|
+
traceId: span.spanContext().traceId,
|
|
16
|
+
spanId: span.spanContext().spanId,
|
|
17
|
+
parentSpanId: span.parentSpanContext?.spanId,
|
|
18
|
+
durationMs: span.duration[0] * 1e3 + span.duration[1] / 1e6,
|
|
19
|
+
attributes: { ...span.attributes },
|
|
20
|
+
status: span.status
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
function createMemoryExporter() {
|
|
24
|
+
const collected = [];
|
|
25
|
+
return {
|
|
26
|
+
export(spans, resultCallback) {
|
|
27
|
+
for (const span of spans) collected.push(toRecordedSpan(span));
|
|
28
|
+
resultCallback({ code: 0 });
|
|
29
|
+
},
|
|
30
|
+
async shutdown() {},
|
|
31
|
+
async forceFlush() {},
|
|
32
|
+
spans: () => [...collected],
|
|
33
|
+
findSpan: (name) => collected.find((span) => span.name === name),
|
|
34
|
+
findSpans: (name) => collected.filter((span) => span.name === name),
|
|
35
|
+
reset: () => {
|
|
36
|
+
collected.length = 0;
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
//#endregion
|
|
11
42
|
//#region src/testing.ts
|
|
12
43
|
/**
|
|
13
44
|
* Testing Utilities
|
|
@@ -479,6 +510,7 @@ exports.assertTraceDuration = assertTraceDuration;
|
|
|
479
510
|
exports.assertTraceFailed = assertTraceFailed;
|
|
480
511
|
exports.assertTraceSucceeded = assertTraceSucceeded;
|
|
481
512
|
exports.createEventCollector = require_event_testing.createEventCollector;
|
|
513
|
+
exports.createMemoryExporter = createMemoryExporter;
|
|
482
514
|
exports.createMockLogger = createMockLogger;
|
|
483
515
|
exports.createTraceCollector = createTraceCollector;
|
|
484
516
|
exports.getTraceDuration = getTraceDuration;
|
package/dist/testing.d.cts
CHANGED
|
@@ -2,7 +2,32 @@ import { t as UnknownRecord } from "./values-CeMH-mYG.cjs";
|
|
|
2
2
|
import { s as Logger } from "./logger-S1Fgl0g3.cjs";
|
|
3
3
|
import { a as EventsValue, c as createEventCollector, i as EventsOutcome, n as EventData, o as assertEventTracked, r as EventsFunnelStep, s as assertOutcomeTracked, t as EventCollector } from "./event-testing-CBtnJXE5.cjs";
|
|
4
4
|
import { SerializedSpan, TestSpanCollector, serializeSpan } from "./test-span-collector.cjs";
|
|
5
|
+
import { SpanExporter } from "@opentelemetry/sdk-trace-base";
|
|
5
6
|
import { Attributes, Link, SpanKind, SpanStatus, SpanStatusCode } from "@opentelemetry/api";
|
|
7
|
+
//#region src/memory-exporter.d.ts
|
|
8
|
+
/** One finished span, flattened to the fields an assertion usually wants. */
|
|
9
|
+
interface RecordedSpan {
|
|
10
|
+
name: string;
|
|
11
|
+
traceId: string;
|
|
12
|
+
spanId: string;
|
|
13
|
+
parentSpanId: string | undefined;
|
|
14
|
+
/** Wall-clock duration of the span, in milliseconds. */
|
|
15
|
+
durationMs: number;
|
|
16
|
+
attributes: Attributes;
|
|
17
|
+
status: SpanStatus;
|
|
18
|
+
}
|
|
19
|
+
interface MemoryExporter extends SpanExporter {
|
|
20
|
+
/** Every span exported so far, in the order it finished. */
|
|
21
|
+
spans(): RecordedSpan[];
|
|
22
|
+
/** The first span with this name, or undefined. */
|
|
23
|
+
findSpan(name: string): RecordedSpan | undefined;
|
|
24
|
+
/** Every span with this name. */
|
|
25
|
+
findSpans(name: string): RecordedSpan[];
|
|
26
|
+
/** Discard what has been collected. */
|
|
27
|
+
reset(): void;
|
|
28
|
+
}
|
|
29
|
+
declare function createMemoryExporter(): MemoryExporter;
|
|
30
|
+
//#endregion
|
|
6
31
|
//#region src/testing.d.ts
|
|
7
32
|
/**
|
|
8
33
|
* Note: OpenTelemetry exporters and processors have moved to dedicated modules
|
|
@@ -290,4 +315,4 @@ declare function getTraceDuration(collector: TraceCollector, operationName: stri
|
|
|
290
315
|
*/
|
|
291
316
|
declare function assertTraceDuration(collector: TraceCollector, operationName: string, maxDurationMs: number): void;
|
|
292
317
|
//#endregion
|
|
293
|
-
export { type EventCollector, type EventData, type EventsFunnelStep, type EventsOutcome, type EventsValue, LogCollector, LogEntry, type SerializedSpan, SpanMatch, TestSpan, TestSpanCollector, TraceCollector, assertEventTracked, assertNoErrors, assertNoErrorsLogged, assertOutcomeTracked, assertTraceCreated, assertTraceDuration, assertTraceFailed, assertTraceSucceeded, createEventCollector, createMockLogger, createTraceCollector, getTraceDuration, serializeSpan, waitForTrace };
|
|
318
|
+
export { type EventCollector, type EventData, type EventsFunnelStep, type EventsOutcome, type EventsValue, LogCollector, LogEntry, type MemoryExporter, type RecordedSpan, type SerializedSpan, SpanMatch, TestSpan, TestSpanCollector, TraceCollector, assertEventTracked, assertNoErrors, assertNoErrorsLogged, assertOutcomeTracked, assertTraceCreated, assertTraceDuration, assertTraceFailed, assertTraceSucceeded, createEventCollector, createMemoryExporter, createMockLogger, createTraceCollector, getTraceDuration, serializeSpan, waitForTrace };
|