autotel-edge 3.16.13 → 3.16.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/config-0FktBGyj.js +290 -0
- package/dist/config-0FktBGyj.js.map +1 -0
- package/dist/events.d.ts +42 -43
- package/dist/events.d.ts.map +1 -0
- package/dist/events.js +144 -137
- package/dist/events.js.map +1 -1
- package/dist/execution-logger-BWlya70r.d.ts +137 -0
- package/dist/execution-logger-BWlya70r.d.ts.map +1 -0
- package/dist/execution-logger-CoxSsBmU.js +247 -0
- package/dist/execution-logger-CoxSsBmU.js.map +1 -0
- package/dist/index.d.ts +192 -276
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +930 -1060
- package/dist/index.js.map +1 -1
- package/dist/logger.d.ts +122 -136
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +783 -774
- package/dist/logger.js.map +1 -1
- package/dist/parse-error.d.ts +12 -10
- package/dist/parse-error.d.ts.map +1 -0
- package/dist/parse-error.js +55 -2
- package/dist/parse-error.js.map +1 -1
- package/dist/sampling.d.ts +51 -76
- package/dist/sampling.d.ts.map +1 -0
- package/dist/sampling.js +155 -90
- package/dist/sampling.js.map +1 -1
- package/dist/testing.d.ts +1 -2
- package/dist/testing.js +1 -3
- package/dist/types-HCbsjZzp.d.ts +214 -0
- package/dist/types-HCbsjZzp.d.ts.map +1 -0
- package/package.json +6 -6
- package/src/core/buffer.ts +4 -3
- package/src/core/provider.context.test.ts +55 -0
- package/src/core/provider.ts +18 -1
- package/binding.gyp +0 -9
- package/dist/chunk-AL7ZD64M.js +0 -291
- package/dist/chunk-AL7ZD64M.js.map +0 -1
- package/dist/chunk-INQQQVXN.js +0 -310
- package/dist/chunk-INQQQVXN.js.map +0 -1
- package/dist/chunk-M7Z4P5MC.js +0 -64
- package/dist/chunk-M7Z4P5MC.js.map +0 -1
- package/dist/execution-logger-77TRRoWn.d.ts +0 -84
- package/dist/testing.js.map +0 -1
- package/dist/types-uulICZo7.d.ts +0 -216
- package/index.js +0 -1
package/dist/index.js
CHANGED
|
@@ -1,1152 +1,1022 @@
|
|
|
1
|
-
|
|
2
|
-
import { setSpanName,
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import { EventEmitter } from 'events';
|
|
12
|
-
import { Buffer } from 'buffer';
|
|
13
|
-
export { Buffer } from 'buffer';
|
|
1
|
+
import { a as OTLPExporter, i as setConfig, n as getActiveConfig, r as parseConfig, t as createInitialiser } from "./config-0FktBGyj.js";
|
|
2
|
+
import { n as createTraceContext, r as setSpanName, t as getExecutionLogger } from "./execution-logger-CoxSsBmU.js";
|
|
3
|
+
import { parseError } from "./parse-error.js";
|
|
4
|
+
import { hrTimeDuration, isAttributeValue, isTimeInput, sanitizeAttributes } from "@opentelemetry/core";
|
|
5
|
+
import { SEMATTRS_EXCEPTION_MESSAGE, SEMATTRS_EXCEPTION_STACKTRACE, SEMATTRS_EXCEPTION_TYPE } from "@opentelemetry/semantic-conventions";
|
|
6
|
+
import { ROOT_CONTEXT, SpanStatusCode, context, context as context$1, propagation, trace as trace$1 } from "@opentelemetry/api";
|
|
7
|
+
import { RandomIdGenerator, SamplingDecision } from "@opentelemetry/sdk-trace-base";
|
|
8
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
9
|
+
import { EventEmitter } from "node:events";
|
|
10
|
+
import { Buffer } from "node:buffer";
|
|
14
11
|
|
|
12
|
+
//#region src/core/span.ts
|
|
15
13
|
function transformExceptionAttributes(exception) {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
if (exception.message) {
|
|
26
|
-
attributes[SEMATTRS_EXCEPTION_MESSAGE] = exception.message;
|
|
27
|
-
}
|
|
28
|
-
if (exception.stack) {
|
|
29
|
-
attributes[SEMATTRS_EXCEPTION_STACKTRACE] = exception.stack;
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
return attributes;
|
|
14
|
+
const attributes = {};
|
|
15
|
+
if (typeof exception === "string") attributes[SEMATTRS_EXCEPTION_MESSAGE] = exception;
|
|
16
|
+
else {
|
|
17
|
+
if (exception.code) attributes[SEMATTRS_EXCEPTION_TYPE] = exception.code.toString();
|
|
18
|
+
else if (exception.name) attributes[SEMATTRS_EXCEPTION_TYPE] = exception.name;
|
|
19
|
+
if (exception.message) attributes[SEMATTRS_EXCEPTION_MESSAGE] = exception.message;
|
|
20
|
+
if (exception.stack) attributes[SEMATTRS_EXCEPTION_STACKTRACE] = exception.stack;
|
|
21
|
+
}
|
|
22
|
+
return attributes;
|
|
33
23
|
}
|
|
34
24
|
function millisToHr(millis) {
|
|
35
|
-
|
|
25
|
+
return [Math.trunc(millis / 1e3), millis % 1e3 * 1e6];
|
|
36
26
|
}
|
|
37
27
|
function getHrTime(input) {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
return millisToHr(input);
|
|
45
|
-
} else if (Array.isArray(input)) {
|
|
46
|
-
return input;
|
|
47
|
-
}
|
|
48
|
-
const v = input;
|
|
49
|
-
throw new Error(`unreachable value: ${JSON.stringify(v)}`);
|
|
28
|
+
const now = Date.now();
|
|
29
|
+
if (!input) return millisToHr(now);
|
|
30
|
+
else if (input instanceof Date) return millisToHr(input.getTime());
|
|
31
|
+
else if (typeof input === "number") return millisToHr(input);
|
|
32
|
+
else if (Array.isArray(input)) return input;
|
|
33
|
+
throw new Error(`unreachable value: ${JSON.stringify(input)}`);
|
|
50
34
|
}
|
|
51
35
|
function isAttributeKey(key) {
|
|
52
|
-
|
|
36
|
+
return typeof key === "string" && key.length > 0;
|
|
53
37
|
}
|
|
38
|
+
/**
|
|
39
|
+
* Lightweight Span implementation for edge runtimes
|
|
40
|
+
*/
|
|
54
41
|
var SpanImpl = class {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
}
|
|
157
|
-
get droppedEventsCount() {
|
|
158
|
-
return this._droppedEventsCount;
|
|
159
|
-
}
|
|
160
|
-
get droppedLinksCount() {
|
|
161
|
-
return this._droppedLinksCount;
|
|
162
|
-
}
|
|
42
|
+
name;
|
|
43
|
+
_spanContext;
|
|
44
|
+
onEnd;
|
|
45
|
+
parentSpanId;
|
|
46
|
+
parentSpanContext;
|
|
47
|
+
kind;
|
|
48
|
+
attributes;
|
|
49
|
+
status = { code: 0 };
|
|
50
|
+
endTime = [0, 0];
|
|
51
|
+
_duration = [0, 0];
|
|
52
|
+
startTime;
|
|
53
|
+
events = [];
|
|
54
|
+
links;
|
|
55
|
+
resource;
|
|
56
|
+
instrumentationScope = { name: "autotel-edge" };
|
|
57
|
+
_ended = false;
|
|
58
|
+
_droppedAttributesCount = 0;
|
|
59
|
+
_droppedEventsCount = 0;
|
|
60
|
+
_droppedLinksCount = 0;
|
|
61
|
+
constructor(init) {
|
|
62
|
+
this.name = init.name;
|
|
63
|
+
this._spanContext = init.spanContext;
|
|
64
|
+
this.parentSpanId = init.parentSpanId;
|
|
65
|
+
this.parentSpanContext = init.parentSpanContext;
|
|
66
|
+
this.kind = init.spanKind || 0;
|
|
67
|
+
this.attributes = sanitizeAttributes(init.attributes);
|
|
68
|
+
this.startTime = getHrTime(init.startTime);
|
|
69
|
+
this.links = init.links || [];
|
|
70
|
+
this.resource = init.resource;
|
|
71
|
+
this.onEnd = init.onEnd;
|
|
72
|
+
}
|
|
73
|
+
addLink(link) {
|
|
74
|
+
this.links.push(link);
|
|
75
|
+
return this;
|
|
76
|
+
}
|
|
77
|
+
addLinks(links) {
|
|
78
|
+
this.links.push(...links);
|
|
79
|
+
return this;
|
|
80
|
+
}
|
|
81
|
+
spanContext() {
|
|
82
|
+
return this._spanContext;
|
|
83
|
+
}
|
|
84
|
+
setAttribute(key, value) {
|
|
85
|
+
if (isAttributeKey(key) && isAttributeValue(value)) this.attributes[key] = value;
|
|
86
|
+
return this;
|
|
87
|
+
}
|
|
88
|
+
setAttributes(attributes) {
|
|
89
|
+
for (const [key, value] of Object.entries(attributes)) this.setAttribute(key, value);
|
|
90
|
+
return this;
|
|
91
|
+
}
|
|
92
|
+
addEvent(name, attributesOrStartTime, startTime) {
|
|
93
|
+
if (isTimeInput(attributesOrStartTime)) {
|
|
94
|
+
startTime = attributesOrStartTime;
|
|
95
|
+
attributesOrStartTime = void 0;
|
|
96
|
+
}
|
|
97
|
+
const attributes = sanitizeAttributes(attributesOrStartTime);
|
|
98
|
+
const time = getHrTime(startTime);
|
|
99
|
+
this.events.push({
|
|
100
|
+
name,
|
|
101
|
+
attributes,
|
|
102
|
+
time
|
|
103
|
+
});
|
|
104
|
+
return this;
|
|
105
|
+
}
|
|
106
|
+
setStatus(status) {
|
|
107
|
+
this.status = status;
|
|
108
|
+
return this;
|
|
109
|
+
}
|
|
110
|
+
updateName(name) {
|
|
111
|
+
this.name = name;
|
|
112
|
+
return this;
|
|
113
|
+
}
|
|
114
|
+
end(endTime) {
|
|
115
|
+
if (this._ended) return;
|
|
116
|
+
this._ended = true;
|
|
117
|
+
this.endTime = getHrTime(endTime);
|
|
118
|
+
this._duration = hrTimeDuration(this.startTime, this.endTime);
|
|
119
|
+
this.onEnd(this);
|
|
120
|
+
}
|
|
121
|
+
isRecording() {
|
|
122
|
+
return !this._ended;
|
|
123
|
+
}
|
|
124
|
+
recordException(exception, time) {
|
|
125
|
+
const attributes = transformExceptionAttributes(exception);
|
|
126
|
+
this.addEvent("exception", attributes, time);
|
|
127
|
+
}
|
|
128
|
+
get duration() {
|
|
129
|
+
return this._duration;
|
|
130
|
+
}
|
|
131
|
+
get ended() {
|
|
132
|
+
return this._ended;
|
|
133
|
+
}
|
|
134
|
+
get droppedAttributesCount() {
|
|
135
|
+
return this._droppedAttributesCount;
|
|
136
|
+
}
|
|
137
|
+
get droppedEventsCount() {
|
|
138
|
+
return this._droppedEventsCount;
|
|
139
|
+
}
|
|
140
|
+
get droppedLinksCount() {
|
|
141
|
+
return this._droppedLinksCount;
|
|
142
|
+
}
|
|
163
143
|
};
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
144
|
+
|
|
145
|
+
//#endregion
|
|
146
|
+
//#region src/core/tracer.ts
|
|
147
|
+
const NewTraceFlags = {
|
|
148
|
+
RANDOM_TRACE_ID_SET: 2,
|
|
149
|
+
RANDOM_TRACE_ID_UNSET: 0
|
|
150
|
+
};
|
|
151
|
+
const idGenerator = new RandomIdGenerator();
|
|
152
|
+
let withNextSpanAttributes;
|
|
168
153
|
function getFlagAt(flagSequence, position) {
|
|
169
|
-
|
|
154
|
+
return (flagSequence >> position - 1 & 1) * position;
|
|
170
155
|
}
|
|
156
|
+
/**
|
|
157
|
+
* WorkerTracer - Lightweight tracer for edge environments
|
|
158
|
+
*/
|
|
171
159
|
var WorkerTracer = class {
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
sp.onEnd(span3);
|
|
246
|
-
}
|
|
247
|
-
},
|
|
248
|
-
resource: this.resource,
|
|
249
|
-
spanContext,
|
|
250
|
-
parentSpanContext,
|
|
251
|
-
parentSpanId,
|
|
252
|
-
spanKind,
|
|
253
|
-
startTime: options.startTime
|
|
254
|
-
});
|
|
255
|
-
for (const sp of this.spanProcessors) {
|
|
256
|
-
sp.onStart(span2, context2);
|
|
257
|
-
}
|
|
258
|
-
return span2;
|
|
259
|
-
}
|
|
260
|
-
startActiveSpan(name, ...args) {
|
|
261
|
-
const options = args.length > 1 ? args[0] : void 0;
|
|
262
|
-
const parentContext = args.length > 2 ? args[1] : context.active();
|
|
263
|
-
const fn = args.at(-1);
|
|
264
|
-
const span2 = this.startSpan(name, options, parentContext);
|
|
265
|
-
const contextWithSpanSet = trace.setSpan(parentContext, span2);
|
|
266
|
-
return context.with(contextWithSpanSet, fn, void 0, span2);
|
|
267
|
-
}
|
|
160
|
+
spanProcessors;
|
|
161
|
+
resource;
|
|
162
|
+
headSampler;
|
|
163
|
+
constructor(spanProcessors, resource) {
|
|
164
|
+
this.spanProcessors = spanProcessors;
|
|
165
|
+
this.resource = resource;
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Set the head sampler (called from config)
|
|
169
|
+
*/
|
|
170
|
+
setHeadSampler(sampler) {
|
|
171
|
+
this.headSampler = sampler;
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Force flush spans for a specific trace
|
|
175
|
+
*/
|
|
176
|
+
async forceFlush(traceId) {
|
|
177
|
+
const promises = this.spanProcessors.map(async (spanProcessor) => {
|
|
178
|
+
await spanProcessor.forceFlush(traceId);
|
|
179
|
+
});
|
|
180
|
+
await Promise.allSettled(promises);
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Add extra resource attributes
|
|
184
|
+
*/
|
|
185
|
+
addToResource(extra) {
|
|
186
|
+
this.resource.merge(extra);
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Start a new span
|
|
190
|
+
*/
|
|
191
|
+
startSpan(name, options = {}, context = context$1.active()) {
|
|
192
|
+
if (options.root) context = trace$1.deleteSpan(context);
|
|
193
|
+
if (!this.headSampler) throw new Error("Head sampler not configured. This is a bug in the instrumentation logic");
|
|
194
|
+
const parentSpanContext = trace$1.getSpan(context)?.spanContext();
|
|
195
|
+
const { traceId, randomTraceFlag } = getTraceInfo(parentSpanContext);
|
|
196
|
+
const spanKind = options.kind || 0;
|
|
197
|
+
const sanitisedAttrs = sanitizeAttributes(options.attributes);
|
|
198
|
+
const { decision, traceState, attributes: attrs } = (options.sampler || this.headSampler).shouldSample(context, traceId, name, spanKind, sanitisedAttrs, []);
|
|
199
|
+
const attributes = Object.assign({}, options.attributes, attrs, withNextSpanAttributes);
|
|
200
|
+
withNextSpanAttributes = {};
|
|
201
|
+
const spanId = idGenerator.generateSpanId();
|
|
202
|
+
const parentSpanId = parentSpanContext?.spanId;
|
|
203
|
+
const spanContext = {
|
|
204
|
+
traceId,
|
|
205
|
+
spanId,
|
|
206
|
+
traceFlags: (decision === SamplingDecision.RECORD_AND_SAMPLED ? 1 : 0) + randomTraceFlag,
|
|
207
|
+
traceState
|
|
208
|
+
};
|
|
209
|
+
const span = new SpanImpl({
|
|
210
|
+
attributes: sanitizeAttributes(attributes),
|
|
211
|
+
name,
|
|
212
|
+
onEnd: (span) => {
|
|
213
|
+
for (const sp of this.spanProcessors) sp.onEnd(span);
|
|
214
|
+
},
|
|
215
|
+
resource: this.resource,
|
|
216
|
+
spanContext,
|
|
217
|
+
parentSpanContext,
|
|
218
|
+
parentSpanId,
|
|
219
|
+
spanKind,
|
|
220
|
+
startTime: options.startTime
|
|
221
|
+
});
|
|
222
|
+
for (const sp of this.spanProcessors) sp.onStart(span, context);
|
|
223
|
+
return span;
|
|
224
|
+
}
|
|
225
|
+
startActiveSpan(name, ...args) {
|
|
226
|
+
const options = args.length > 1 ? args[0] : void 0;
|
|
227
|
+
const parentContext = args.length > 2 ? args[1] : context$1.active();
|
|
228
|
+
const fn = args.at(-1);
|
|
229
|
+
const span = this.startSpan(name, options, parentContext);
|
|
230
|
+
const contextWithSpanSet = trace$1.setSpan(parentContext, span);
|
|
231
|
+
return context$1.with(contextWithSpanSet, fn, void 0, span);
|
|
232
|
+
}
|
|
268
233
|
};
|
|
234
|
+
/**
|
|
235
|
+
* Set attributes for the next span created
|
|
236
|
+
*/
|
|
269
237
|
function withNextSpan(attrs) {
|
|
270
|
-
|
|
238
|
+
withNextSpanAttributes = Object.assign({}, withNextSpanAttributes, attrs);
|
|
271
239
|
}
|
|
272
240
|
function getTraceInfo(parentSpanContext) {
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
241
|
+
if (parentSpanContext && trace$1.isSpanContextValid(parentSpanContext)) {
|
|
242
|
+
const { traceId, traceFlags } = parentSpanContext;
|
|
243
|
+
return {
|
|
244
|
+
traceId,
|
|
245
|
+
randomTraceFlag: getFlagAt(traceFlags, 2)
|
|
246
|
+
};
|
|
247
|
+
} else return {
|
|
248
|
+
traceId: idGenerator.generateTraceId(),
|
|
249
|
+
randomTraceFlag: NewTraceFlags.RANDOM_TRACE_ID_SET
|
|
250
|
+
};
|
|
282
251
|
}
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
252
|
+
|
|
253
|
+
//#endregion
|
|
254
|
+
//#region src/core/context.ts
|
|
255
|
+
const ADD_LISTENER_METHODS = [
|
|
256
|
+
"addListener",
|
|
257
|
+
"on",
|
|
258
|
+
"once",
|
|
259
|
+
"prependListener",
|
|
260
|
+
"prependOnceListener"
|
|
289
261
|
];
|
|
290
262
|
var AbstractAsyncHooksContextManager = class {
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
contextManager._wrapped = true;
|
|
385
|
-
try {
|
|
386
|
-
return original.call(this, event, patchedListener);
|
|
387
|
-
} finally {
|
|
388
|
-
contextManager._wrapped = false;
|
|
389
|
-
}
|
|
390
|
-
};
|
|
391
|
-
}
|
|
392
|
-
_createPatchMap(ee) {
|
|
393
|
-
const map = /* @__PURE__ */ Object.create(null);
|
|
394
|
-
ee[this._kOtListeners] = map;
|
|
395
|
-
return map;
|
|
396
|
-
}
|
|
397
|
-
_getPatchMap(ee) {
|
|
398
|
-
return ee[this._kOtListeners];
|
|
399
|
-
}
|
|
400
|
-
_kOtListeners = /* @__PURE__ */ Symbol("OtListeners");
|
|
401
|
-
_wrapped = false;
|
|
263
|
+
/**
|
|
264
|
+
* Binds a context to the target function or event emitter
|
|
265
|
+
*/
|
|
266
|
+
bind(context, target) {
|
|
267
|
+
if (target instanceof EventEmitter) return this._bindEventEmitter(context, target);
|
|
268
|
+
if (typeof target === "function") return this._bindFunction(context, target);
|
|
269
|
+
return target;
|
|
270
|
+
}
|
|
271
|
+
_bindFunction(context, target) {
|
|
272
|
+
const manager = this;
|
|
273
|
+
const contextWrapper = function(...args) {
|
|
274
|
+
return manager.with(context, () => target.apply(this, args));
|
|
275
|
+
};
|
|
276
|
+
Object.defineProperty(contextWrapper, "length", {
|
|
277
|
+
enumerable: false,
|
|
278
|
+
configurable: true,
|
|
279
|
+
writable: false,
|
|
280
|
+
value: target.length
|
|
281
|
+
});
|
|
282
|
+
return contextWrapper;
|
|
283
|
+
}
|
|
284
|
+
/**
|
|
285
|
+
* By default, EventEmitter calls callbacks with their context, which we do
|
|
286
|
+
* not want. Instead we bind a specific context to all callbacks.
|
|
287
|
+
*/
|
|
288
|
+
_bindEventEmitter(context, ee) {
|
|
289
|
+
if (this._getPatchMap(ee) !== void 0) return ee;
|
|
290
|
+
this._createPatchMap(ee);
|
|
291
|
+
for (const methodName of ADD_LISTENER_METHODS) {
|
|
292
|
+
if (ee[methodName] === void 0) continue;
|
|
293
|
+
ee[methodName] = this._patchAddListener(ee, ee[methodName], context);
|
|
294
|
+
}
|
|
295
|
+
if (typeof ee.removeListener === "function") ee.removeListener = this._patchRemoveListener(ee, ee.removeListener);
|
|
296
|
+
if (typeof ee.off === "function") ee.off = this._patchRemoveListener(ee, ee.off);
|
|
297
|
+
if (typeof ee.removeAllListeners === "function") ee.removeAllListeners = this._patchRemoveAllListeners(ee, ee.removeAllListeners);
|
|
298
|
+
return ee;
|
|
299
|
+
}
|
|
300
|
+
_patchRemoveListener(ee, original) {
|
|
301
|
+
const contextManager = this;
|
|
302
|
+
return function(event, listener) {
|
|
303
|
+
const events = contextManager._getPatchMap(ee)?.[event];
|
|
304
|
+
if (events === void 0) return original.call(this, event, listener);
|
|
305
|
+
const patchedListener = events.get(listener);
|
|
306
|
+
return original.call(this, event, patchedListener || listener);
|
|
307
|
+
};
|
|
308
|
+
}
|
|
309
|
+
_patchRemoveAllListeners(ee, original) {
|
|
310
|
+
const contextManager = this;
|
|
311
|
+
return function(event) {
|
|
312
|
+
const map = contextManager._getPatchMap(ee);
|
|
313
|
+
if (map !== void 0) {
|
|
314
|
+
if (arguments.length === 0) contextManager._createPatchMap(ee);
|
|
315
|
+
else if (map[event] !== void 0) delete map[event];
|
|
316
|
+
}
|
|
317
|
+
return Reflect.apply(original, this, arguments);
|
|
318
|
+
};
|
|
319
|
+
}
|
|
320
|
+
_patchAddListener(ee, original, context) {
|
|
321
|
+
const contextManager = this;
|
|
322
|
+
return function(event, listener) {
|
|
323
|
+
/**
|
|
324
|
+
* This check prevents double-wrapping the listener.
|
|
325
|
+
* The implementation for ee.once wraps the listener and calls ee.on.
|
|
326
|
+
* Without this check, we would wrap that wrapped listener.
|
|
327
|
+
*/
|
|
328
|
+
if (contextManager._wrapped) return original.call(this, event, listener);
|
|
329
|
+
let map = contextManager._getPatchMap(ee);
|
|
330
|
+
if (map === void 0) map = contextManager._createPatchMap(ee);
|
|
331
|
+
let listeners = map[event];
|
|
332
|
+
if (listeners === void 0) {
|
|
333
|
+
listeners = /* @__PURE__ */ new WeakMap();
|
|
334
|
+
map[event] = listeners;
|
|
335
|
+
}
|
|
336
|
+
const patchedListener = contextManager.bind(context, listener);
|
|
337
|
+
listeners.set(listener, patchedListener);
|
|
338
|
+
contextManager._wrapped = true;
|
|
339
|
+
try {
|
|
340
|
+
return original.call(this, event, patchedListener);
|
|
341
|
+
} finally {
|
|
342
|
+
contextManager._wrapped = false;
|
|
343
|
+
}
|
|
344
|
+
};
|
|
345
|
+
}
|
|
346
|
+
_createPatchMap(ee) {
|
|
347
|
+
const map = Object.create(null);
|
|
348
|
+
ee[this._kOtListeners] = map;
|
|
349
|
+
return map;
|
|
350
|
+
}
|
|
351
|
+
_getPatchMap(ee) {
|
|
352
|
+
return ee[this._kOtListeners];
|
|
353
|
+
}
|
|
354
|
+
_kOtListeners = Symbol("OtListeners");
|
|
355
|
+
_wrapped = false;
|
|
402
356
|
};
|
|
357
|
+
/**
|
|
358
|
+
* AsyncLocalStorage-based context manager for edge runtimes
|
|
359
|
+
*/
|
|
403
360
|
var AsyncLocalStorageContextManager = class extends AbstractAsyncHooksContextManager {
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
361
|
+
_asyncLocalStorage;
|
|
362
|
+
constructor() {
|
|
363
|
+
super();
|
|
364
|
+
this._asyncLocalStorage = new AsyncLocalStorage();
|
|
365
|
+
}
|
|
366
|
+
active() {
|
|
367
|
+
return this._asyncLocalStorage.getStore() ?? ROOT_CONTEXT;
|
|
368
|
+
}
|
|
369
|
+
with(context, fn, thisArg, ...args) {
|
|
370
|
+
const cb = thisArg == null ? fn : fn.bind(thisArg);
|
|
371
|
+
return this._asyncLocalStorage.run(context, cb, ...args);
|
|
372
|
+
}
|
|
373
|
+
enable() {
|
|
374
|
+
return this;
|
|
375
|
+
}
|
|
376
|
+
disable() {
|
|
377
|
+
this._asyncLocalStorage.disable();
|
|
378
|
+
return this;
|
|
379
|
+
}
|
|
423
380
|
};
|
|
381
|
+
|
|
382
|
+
//#endregion
|
|
383
|
+
//#region src/core/provider.ts
|
|
384
|
+
/**
|
|
385
|
+
* Tracer provider for edge environments
|
|
386
|
+
*/
|
|
387
|
+
let globalContextManagerRegistered = false;
|
|
388
|
+
/**
|
|
389
|
+
* WorkerTracerProvider - Registers tracer globally
|
|
390
|
+
*/
|
|
424
391
|
var WorkerTracerProvider = class {
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
trace.setGlobalTracerProvider(provider);
|
|
446
|
-
}
|
|
392
|
+
tracer;
|
|
393
|
+
contextManager;
|
|
394
|
+
constructor(spanProcessors, resource) {
|
|
395
|
+
this.tracer = new WorkerTracer(spanProcessors, resource);
|
|
396
|
+
this.contextManager = new AsyncLocalStorageContextManager();
|
|
397
|
+
}
|
|
398
|
+
/**
|
|
399
|
+
* Get the tracer instance
|
|
400
|
+
*/
|
|
401
|
+
getTracer(_name, _version, _config) {
|
|
402
|
+
return this.tracer;
|
|
403
|
+
}
|
|
404
|
+
/**
|
|
405
|
+
* Register this provider as the global tracer
|
|
406
|
+
*/
|
|
407
|
+
register() {
|
|
408
|
+
this.contextManager.enable();
|
|
409
|
+
if (!globalContextManagerRegistered) globalContextManagerRegistered = context$1.setGlobalContextManager(this.contextManager);
|
|
410
|
+
trace$1.setGlobalTracerProvider({ getTracer: (_name, _version) => this.tracer });
|
|
411
|
+
}
|
|
447
412
|
};
|
|
413
|
+
|
|
414
|
+
//#endregion
|
|
415
|
+
//#region src/core/buffer.ts
|
|
416
|
+
/**
|
|
417
|
+
* Buffer polyfill for edge environments
|
|
418
|
+
*
|
|
419
|
+
* Cloudflare Workers and other edge runtimes need the Buffer global
|
|
420
|
+
* for OpenTelemetry OTLP serialization.
|
|
421
|
+
*/
|
|
448
422
|
globalThis.Buffer = Buffer;
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
423
|
+
|
|
424
|
+
//#endregion
|
|
425
|
+
//#region src/functional.ts
|
|
426
|
+
/**
|
|
427
|
+
* Functional API for autotel-edge
|
|
428
|
+
*
|
|
429
|
+
* Provides zero-boilerplate tracing helpers that mirror the Node.js runtime
|
|
430
|
+
* implementation while staying optimized for edge environments.
|
|
431
|
+
*/
|
|
432
|
+
const TRACE_FACTORY_MARK = "__autotelEdgeTraceFactory";
|
|
433
|
+
const INSTRUMENTED_MARK = "__autotelEdgeInstrumented";
|
|
434
|
+
const FACTORY_NAME_HINTS = {
|
|
435
|
+
ctx: true,
|
|
436
|
+
_ctx: true,
|
|
437
|
+
context: true,
|
|
438
|
+
tracecontext: true,
|
|
439
|
+
tracectx: true
|
|
457
440
|
};
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
441
|
+
const SINGLE_LINE_COMMENT_REGEX = /\/\/.*$/gm;
|
|
442
|
+
const MULTI_LINE_COMMENT_REGEX = /\/\*[\s\S]*?\*\//gm;
|
|
443
|
+
const PARAM_TOKEN_SANITIZE_REGEX = new RegExp(String.raw`[{}\[\]\s]`, "g");
|
|
461
444
|
function markAsTraceFactory(fn) {
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
445
|
+
try {
|
|
446
|
+
Object.defineProperty(fn, TRACE_FACTORY_MARK, {
|
|
447
|
+
value: true,
|
|
448
|
+
configurable: true
|
|
449
|
+
});
|
|
450
|
+
} catch {
|
|
451
|
+
fn[TRACE_FACTORY_MARK] = true;
|
|
452
|
+
}
|
|
470
453
|
}
|
|
471
454
|
function hasFactoryMark(fn) {
|
|
472
|
-
|
|
455
|
+
return Boolean(fn[TRACE_FACTORY_MARK]);
|
|
473
456
|
}
|
|
474
457
|
function sanitizeParameterToken(token) {
|
|
475
|
-
|
|
476
|
-
|
|
458
|
+
const [firstToken] = token.split("=");
|
|
459
|
+
return (firstToken ?? "").replaceAll(PARAM_TOKEN_SANITIZE_REGEX, "").trim();
|
|
477
460
|
}
|
|
478
461
|
function getFirstParameterToken(fn) {
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
const first = params?.[0]?.trim();
|
|
494
|
-
if (first) {
|
|
495
|
-
return sanitizeParameterToken(first);
|
|
496
|
-
}
|
|
497
|
-
}
|
|
498
|
-
return null;
|
|
462
|
+
let source = Function.prototype.toString.call(fn);
|
|
463
|
+
source = source.replaceAll(MULTI_LINE_COMMENT_REGEX, "").replaceAll(SINGLE_LINE_COMMENT_REGEX, "").trim();
|
|
464
|
+
const arrowMatch = source.match(/^(?:async\s*)?(?:\(([^)]*)\)|([^=()]+))\s*=>/);
|
|
465
|
+
if (arrowMatch) {
|
|
466
|
+
const first = (arrowMatch[1] ?? arrowMatch[2] ?? "").split(",")[0]?.trim();
|
|
467
|
+
if (first) return sanitizeParameterToken(first);
|
|
468
|
+
return null;
|
|
469
|
+
}
|
|
470
|
+
const functionMatch = source.match(/^[^(]*\(([^)]*)\)/);
|
|
471
|
+
if (functionMatch) {
|
|
472
|
+
const first = (functionMatch[1]?.split(","))?.[0]?.trim();
|
|
473
|
+
if (first) return sanitizeParameterToken(first);
|
|
474
|
+
}
|
|
475
|
+
return null;
|
|
499
476
|
}
|
|
500
477
|
function looksLikeTraceFactory(fn) {
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
return true;
|
|
514
|
-
}
|
|
515
|
-
return false;
|
|
516
|
-
}
|
|
478
|
+
if (hasFactoryMark(fn)) return true;
|
|
479
|
+
if (fn.length === 0) return false;
|
|
480
|
+
const firstParam = getFirstParameterToken(fn);
|
|
481
|
+
if (!firstParam) return false;
|
|
482
|
+
const normalized = firstParam.toLowerCase();
|
|
483
|
+
if (Object.hasOwn(FACTORY_NAME_HINTS, normalized) || normalized.startsWith("ctx") || normalized.startsWith("_ctx") || normalized.startsWith("trace")) return true;
|
|
484
|
+
return false;
|
|
485
|
+
}
|
|
486
|
+
/**
|
|
487
|
+
* Check if a function that takes ctx returns another function (factory pattern)
|
|
488
|
+
* vs returning a value directly (immediate execution pattern)
|
|
489
|
+
*/
|
|
517
490
|
function isFactoryReturningFunction(fnWithCtx) {
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
}
|
|
491
|
+
try {
|
|
492
|
+
return typeof fnWithCtx(createDummyCtx()) === "function";
|
|
493
|
+
} catch {
|
|
494
|
+
return false;
|
|
495
|
+
}
|
|
524
496
|
}
|
|
525
497
|
function isTraceFactoryFunction(fn) {
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
markAsTraceFactory(fn);
|
|
534
|
-
return true;
|
|
535
|
-
}
|
|
536
|
-
return false;
|
|
498
|
+
if (typeof fn !== "function") return false;
|
|
499
|
+
if (hasFactoryMark(fn)) return true;
|
|
500
|
+
if (looksLikeTraceFactory(fn)) {
|
|
501
|
+
markAsTraceFactory(fn);
|
|
502
|
+
return true;
|
|
503
|
+
}
|
|
504
|
+
return false;
|
|
537
505
|
}
|
|
538
506
|
function ensureTraceFactory(fnOrFactory) {
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
}
|
|
549
|
-
var MAX_ERROR_MESSAGE_LENGTH = 500;
|
|
507
|
+
if (isTraceFactoryFunction(fnOrFactory)) return fnOrFactory;
|
|
508
|
+
const plainFn = fnOrFactory;
|
|
509
|
+
const factory = (ctx) => {
|
|
510
|
+
return plainFn;
|
|
511
|
+
};
|
|
512
|
+
markAsTraceFactory(factory);
|
|
513
|
+
return factory;
|
|
514
|
+
}
|
|
515
|
+
const MAX_ERROR_MESSAGE_LENGTH = 500;
|
|
550
516
|
function createDummyCtx() {
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
addLink: () => {
|
|
566
|
-
},
|
|
567
|
-
addLinks: () => {
|
|
568
|
-
},
|
|
569
|
-
updateName: () => {
|
|
570
|
-
},
|
|
571
|
-
isRecording: () => false
|
|
572
|
-
};
|
|
517
|
+
return {
|
|
518
|
+
traceId: "",
|
|
519
|
+
spanId: "",
|
|
520
|
+
correlationId: "",
|
|
521
|
+
setAttribute: () => {},
|
|
522
|
+
setAttributes: () => {},
|
|
523
|
+
setStatus: () => {},
|
|
524
|
+
recordException: () => {},
|
|
525
|
+
addEvent: () => {},
|
|
526
|
+
addLink: () => {},
|
|
527
|
+
addLinks: () => {},
|
|
528
|
+
updateName: () => {},
|
|
529
|
+
isRecording: () => false
|
|
530
|
+
};
|
|
573
531
|
}
|
|
574
532
|
function truncateErrorMessage(message) {
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
}
|
|
578
|
-
return `${message.slice(0, MAX_ERROR_MESSAGE_LENGTH)}... (truncated)`;
|
|
533
|
+
if (message.length <= MAX_ERROR_MESSAGE_LENGTH) return message;
|
|
534
|
+
return `${message.slice(0, MAX_ERROR_MESSAGE_LENGTH)}... (truncated)`;
|
|
579
535
|
}
|
|
580
536
|
function inferFunctionName(fn) {
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
return fn.name;
|
|
587
|
-
}
|
|
588
|
-
const source = Function.prototype.toString.call(fn);
|
|
589
|
-
const match = source.match(/function\s+([^(\s]+)/);
|
|
590
|
-
if (match && match[1] && match[1] !== "anonymous") {
|
|
591
|
-
return match[1];
|
|
592
|
-
}
|
|
593
|
-
return void 0;
|
|
537
|
+
const displayName = fn.displayName;
|
|
538
|
+
if (displayName) return displayName;
|
|
539
|
+
if (fn.name && fn.name !== "anonymous") return fn.name;
|
|
540
|
+
const match = Function.prototype.toString.call(fn).match(/function\s+([^(\s]+)/);
|
|
541
|
+
if (match && match[1] && match[1] !== "anonymous") return match[1];
|
|
594
542
|
}
|
|
595
543
|
function getSpanName(options, fn, variableName) {
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
return `${options.serviceName}.${fnName}`;
|
|
603
|
-
}
|
|
604
|
-
if (fnName && fnName !== "anonymous") {
|
|
605
|
-
return fnName;
|
|
606
|
-
}
|
|
607
|
-
return "unknown";
|
|
544
|
+
if (options.name) return options.name;
|
|
545
|
+
let fnName = variableName ?? inferFunctionName(fn);
|
|
546
|
+
fnName = fnName || "anonymous";
|
|
547
|
+
if (options.serviceName) return `${options.serviceName}.${fnName}`;
|
|
548
|
+
if (fnName && fnName !== "anonymous") return fnName;
|
|
549
|
+
return "unknown";
|
|
608
550
|
}
|
|
609
551
|
function isAsyncFunction(fn) {
|
|
610
|
-
|
|
552
|
+
return typeof fn === "function" && fn.constructor?.name === "AsyncFunction";
|
|
611
553
|
}
|
|
612
554
|
function wrapWithTracingAsync(fnFactory, options, variableName) {
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
return wrappedFunction;
|
|
555
|
+
const tempFn = fnFactory(createDummyCtx());
|
|
556
|
+
const spanName = getSpanName(options, tempFn, variableName);
|
|
557
|
+
const wrappedFunction = async function wrappedFunction(...args) {
|
|
558
|
+
const tracer = trace$1.getTracer("autotel-edge");
|
|
559
|
+
const spanOptions = options.sampler ? { sampler: options.sampler } : {};
|
|
560
|
+
return tracer.startActiveSpan(spanName, spanOptions, async (span) => {
|
|
561
|
+
setSpanName(span, spanName);
|
|
562
|
+
try {
|
|
563
|
+
const actualFn = fnFactory(createTraceContext(span));
|
|
564
|
+
if (options.attributes) span.setAttributes(options.attributes);
|
|
565
|
+
if (options.attributesFromArgs) {
|
|
566
|
+
const argsAttrs = options.attributesFromArgs(args);
|
|
567
|
+
span.setAttributes(argsAttrs);
|
|
568
|
+
}
|
|
569
|
+
const result = await actualFn(...args);
|
|
570
|
+
if (options.attributesFromResult) {
|
|
571
|
+
const resultAttrs = options.attributesFromResult(result);
|
|
572
|
+
span.setAttributes(resultAttrs);
|
|
573
|
+
}
|
|
574
|
+
span.setAttribute("code.function", spanName);
|
|
575
|
+
span.setStatus({ code: SpanStatusCode.OK });
|
|
576
|
+
span.end();
|
|
577
|
+
return result;
|
|
578
|
+
} catch (error) {
|
|
579
|
+
const message = truncateErrorMessage(error instanceof Error ? error.message : String(error ?? "Unknown error"));
|
|
580
|
+
span.setAttribute("code.function", spanName);
|
|
581
|
+
span.setStatus({
|
|
582
|
+
code: SpanStatusCode.ERROR,
|
|
583
|
+
message
|
|
584
|
+
});
|
|
585
|
+
span.recordException(error instanceof Error ? error : new Error(String(error)));
|
|
586
|
+
span.end();
|
|
587
|
+
throw error;
|
|
588
|
+
}
|
|
589
|
+
});
|
|
590
|
+
};
|
|
591
|
+
Object.defineProperty(wrappedFunction, "name", {
|
|
592
|
+
value: tempFn.name || "trace",
|
|
593
|
+
configurable: true
|
|
594
|
+
});
|
|
595
|
+
wrappedFunction[INSTRUMENTED_MARK] = true;
|
|
596
|
+
return wrappedFunction;
|
|
656
597
|
}
|
|
657
598
|
function wrapWithTracingSync(fnFactory, options, variableName) {
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
return wrappedFunction;
|
|
599
|
+
const tempFn = fnFactory(createDummyCtx());
|
|
600
|
+
const spanName = getSpanName(options, tempFn, variableName);
|
|
601
|
+
const wrappedFunction = function wrappedFunction(...args) {
|
|
602
|
+
const tracer = trace$1.getTracer("autotel-edge");
|
|
603
|
+
const spanOptions = options.sampler ? { sampler: options.sampler } : {};
|
|
604
|
+
return tracer.startActiveSpan(spanName, spanOptions, (span) => {
|
|
605
|
+
setSpanName(span, spanName);
|
|
606
|
+
try {
|
|
607
|
+
const actualFn = fnFactory(createTraceContext(span));
|
|
608
|
+
if (options.attributes) span.setAttributes(options.attributes);
|
|
609
|
+
if (options.attributesFromArgs) {
|
|
610
|
+
const argsAttrs = options.attributesFromArgs(args);
|
|
611
|
+
span.setAttributes(argsAttrs);
|
|
612
|
+
}
|
|
613
|
+
const result = actualFn(...args);
|
|
614
|
+
if (options.attributesFromResult) {
|
|
615
|
+
const resultAttrs = options.attributesFromResult(result);
|
|
616
|
+
span.setAttributes(resultAttrs);
|
|
617
|
+
}
|
|
618
|
+
span.setAttribute("code.function", spanName);
|
|
619
|
+
span.setStatus({ code: SpanStatusCode.OK });
|
|
620
|
+
span.end();
|
|
621
|
+
return result;
|
|
622
|
+
} catch (error) {
|
|
623
|
+
const message = truncateErrorMessage(error instanceof Error ? error.message : String(error ?? "Unknown error"));
|
|
624
|
+
span.setAttribute("code.function", spanName);
|
|
625
|
+
span.setStatus({
|
|
626
|
+
code: SpanStatusCode.ERROR,
|
|
627
|
+
message
|
|
628
|
+
});
|
|
629
|
+
span.recordException(error instanceof Error ? error : new Error(String(error)));
|
|
630
|
+
span.end();
|
|
631
|
+
throw error;
|
|
632
|
+
}
|
|
633
|
+
});
|
|
634
|
+
};
|
|
635
|
+
Object.defineProperty(wrappedFunction, "name", {
|
|
636
|
+
value: tempFn.name || "trace",
|
|
637
|
+
configurable: true
|
|
638
|
+
});
|
|
639
|
+
wrappedFunction[INSTRUMENTED_MARK] = true;
|
|
640
|
+
return wrappedFunction;
|
|
701
641
|
}
|
|
702
642
|
function wrapFactoryWithTracing(fnOrFactory, options, variableName) {
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
);
|
|
712
|
-
}
|
|
713
|
-
return wrapWithTracingSync(
|
|
714
|
-
factory,
|
|
715
|
-
options,
|
|
716
|
-
variableName
|
|
717
|
-
);
|
|
718
|
-
}
|
|
643
|
+
const factory = ensureTraceFactory(fnOrFactory);
|
|
644
|
+
if (isAsyncFunction(factory(createDummyCtx()))) return wrapWithTracingAsync(factory, options, variableName);
|
|
645
|
+
return wrapWithTracingSync(factory, options, variableName);
|
|
646
|
+
}
|
|
647
|
+
/**
|
|
648
|
+
* Execute a function immediately within a trace span
|
|
649
|
+
* Used for the immediate execution pattern: trace((ctx) => result)
|
|
650
|
+
*/
|
|
719
651
|
function executeImmediately(fn, options) {
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
});
|
|
776
|
-
}
|
|
777
|
-
function trace3(fnOrNameOrOptions, maybeFn) {
|
|
778
|
-
if (typeof fnOrNameOrOptions === "function") {
|
|
779
|
-
if (looksLikeTraceFactory(fnOrNameOrOptions) && !isFactoryReturningFunction(fnOrNameOrOptions)) {
|
|
780
|
-
return executeImmediately(
|
|
781
|
-
fnOrNameOrOptions,
|
|
782
|
-
{}
|
|
783
|
-
);
|
|
784
|
-
}
|
|
785
|
-
return wrapFactoryWithTracing(
|
|
786
|
-
fnOrNameOrOptions,
|
|
787
|
-
{}
|
|
788
|
-
);
|
|
789
|
-
}
|
|
790
|
-
if (typeof fnOrNameOrOptions === "string") {
|
|
791
|
-
if (!maybeFn) {
|
|
792
|
-
throw new Error("trace(name, fn): fn is required");
|
|
793
|
-
}
|
|
794
|
-
if (looksLikeTraceFactory(maybeFn) && !isFactoryReturningFunction(maybeFn)) {
|
|
795
|
-
return executeImmediately(
|
|
796
|
-
maybeFn,
|
|
797
|
-
{ name: fnOrNameOrOptions }
|
|
798
|
-
);
|
|
799
|
-
}
|
|
800
|
-
return wrapFactoryWithTracing(
|
|
801
|
-
maybeFn,
|
|
802
|
-
{ name: fnOrNameOrOptions }
|
|
803
|
-
);
|
|
804
|
-
}
|
|
805
|
-
if (!maybeFn) {
|
|
806
|
-
throw new Error("trace(options, fn): fn is required");
|
|
807
|
-
}
|
|
808
|
-
if (looksLikeTraceFactory(maybeFn) && !isFactoryReturningFunction(maybeFn)) {
|
|
809
|
-
return executeImmediately(
|
|
810
|
-
maybeFn,
|
|
811
|
-
fnOrNameOrOptions
|
|
812
|
-
);
|
|
813
|
-
}
|
|
814
|
-
return wrapFactoryWithTracing(
|
|
815
|
-
maybeFn,
|
|
816
|
-
fnOrNameOrOptions
|
|
817
|
-
);
|
|
652
|
+
const tracer = trace$1.getTracer("@autotel/edge");
|
|
653
|
+
const spanName = options.name || "anonymous";
|
|
654
|
+
return tracer.startActiveSpan(spanName, (span) => {
|
|
655
|
+
try {
|
|
656
|
+
setSpanName(span, spanName);
|
|
657
|
+
const ctxValue = createTraceContext(span);
|
|
658
|
+
const onSuccess = (result) => {
|
|
659
|
+
span.setStatus({ code: SpanStatusCode.OK });
|
|
660
|
+
if (options.attributes) for (const [key, value] of Object.entries(options.attributes)) span.setAttribute(key, value);
|
|
661
|
+
span.end();
|
|
662
|
+
return result;
|
|
663
|
+
};
|
|
664
|
+
const onError = (error) => {
|
|
665
|
+
const truncatedMessage = truncateErrorMessage(error instanceof Error ? error.message : "Unknown error");
|
|
666
|
+
span.setStatus({
|
|
667
|
+
code: SpanStatusCode.ERROR,
|
|
668
|
+
message: truncatedMessage
|
|
669
|
+
});
|
|
670
|
+
span.setAttribute("error", true);
|
|
671
|
+
span.setAttribute("exception.type", error instanceof Error ? error.constructor.name : "Error");
|
|
672
|
+
span.setAttribute("exception.message", truncatedMessage);
|
|
673
|
+
span.recordException(error instanceof Error ? error : new Error(String(error)));
|
|
674
|
+
span.end();
|
|
675
|
+
throw error;
|
|
676
|
+
};
|
|
677
|
+
const result = fn(ctxValue);
|
|
678
|
+
if (result instanceof Promise) return result.then(onSuccess, onError);
|
|
679
|
+
return onSuccess(result);
|
|
680
|
+
} catch (error) {
|
|
681
|
+
const truncatedMessage = truncateErrorMessage(error instanceof Error ? error.message : "Unknown error");
|
|
682
|
+
span.setStatus({
|
|
683
|
+
code: SpanStatusCode.ERROR,
|
|
684
|
+
message: truncatedMessage
|
|
685
|
+
});
|
|
686
|
+
span.setAttribute("error", true);
|
|
687
|
+
span.setAttribute("exception.message", truncatedMessage);
|
|
688
|
+
span.recordException(error instanceof Error ? error : new Error(String(error)));
|
|
689
|
+
span.end();
|
|
690
|
+
throw error;
|
|
691
|
+
}
|
|
692
|
+
});
|
|
693
|
+
}
|
|
694
|
+
function trace(fnOrNameOrOptions, maybeFn) {
|
|
695
|
+
if (typeof fnOrNameOrOptions === "function") {
|
|
696
|
+
if (looksLikeTraceFactory(fnOrNameOrOptions) && !isFactoryReturningFunction(fnOrNameOrOptions)) return executeImmediately(fnOrNameOrOptions, {});
|
|
697
|
+
return wrapFactoryWithTracing(fnOrNameOrOptions, {});
|
|
698
|
+
}
|
|
699
|
+
if (typeof fnOrNameOrOptions === "string") {
|
|
700
|
+
if (!maybeFn) throw new Error("trace(name, fn): fn is required");
|
|
701
|
+
if (looksLikeTraceFactory(maybeFn) && !isFactoryReturningFunction(maybeFn)) return executeImmediately(maybeFn, { name: fnOrNameOrOptions });
|
|
702
|
+
return wrapFactoryWithTracing(maybeFn, { name: fnOrNameOrOptions });
|
|
703
|
+
}
|
|
704
|
+
if (!maybeFn) throw new Error("trace(options, fn): fn is required");
|
|
705
|
+
if (looksLikeTraceFactory(maybeFn) && !isFactoryReturningFunction(maybeFn)) return executeImmediately(maybeFn, fnOrNameOrOptions);
|
|
706
|
+
return wrapFactoryWithTracing(maybeFn, fnOrNameOrOptions);
|
|
818
707
|
}
|
|
819
708
|
function withTracing(options) {
|
|
820
|
-
|
|
709
|
+
return (fnOrFactory) => wrapFactoryWithTracing(fnOrFactory, options);
|
|
821
710
|
}
|
|
822
711
|
function shouldSkip(key, fn, skip) {
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
return true;
|
|
832
|
-
}
|
|
833
|
-
if (pattern instanceof RegExp && pattern.test(key)) {
|
|
834
|
-
return true;
|
|
835
|
-
}
|
|
836
|
-
if (typeof pattern === "function" && pattern(key, fn)) {
|
|
837
|
-
return true;
|
|
838
|
-
}
|
|
839
|
-
}
|
|
840
|
-
return false;
|
|
712
|
+
if (key.startsWith("_")) return true;
|
|
713
|
+
if (!skip || skip.length === 0) return false;
|
|
714
|
+
for (const pattern of skip) {
|
|
715
|
+
if (typeof pattern === "string" && key === pattern) return true;
|
|
716
|
+
if (pattern instanceof RegExp && pattern.test(key)) return true;
|
|
717
|
+
if (typeof pattern === "function" && pattern(key, fn)) return true;
|
|
718
|
+
}
|
|
719
|
+
return false;
|
|
841
720
|
}
|
|
842
721
|
function instrument(options) {
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
722
|
+
const { functions, ...tracingOptions } = options;
|
|
723
|
+
const instrumented = {};
|
|
724
|
+
for (const key of Object.keys(functions)) {
|
|
725
|
+
const fn = functions[key];
|
|
726
|
+
if (typeof fn !== "function") {
|
|
727
|
+
instrumented[key] = fn;
|
|
728
|
+
continue;
|
|
729
|
+
}
|
|
730
|
+
if (shouldSkip(key, fn, tracingOptions.skip)) {
|
|
731
|
+
instrumented[key] = fn;
|
|
732
|
+
continue;
|
|
733
|
+
}
|
|
734
|
+
const fnOptions = {
|
|
735
|
+
...tracingOptions,
|
|
736
|
+
...tracingOptions.overrides?.[key],
|
|
737
|
+
name: tracingOptions.overrides?.[key]?.name ?? tracingOptions.name
|
|
738
|
+
};
|
|
739
|
+
const boundFn = fn.bind(functions);
|
|
740
|
+
const fnFactory = (_ctx) => boundFn;
|
|
741
|
+
instrumented[key] = wrapFactoryWithTracing(fnFactory, fnOptions, key);
|
|
742
|
+
}
|
|
743
|
+
return instrumented;
|
|
865
744
|
}
|
|
866
745
|
function span(nameOrOptions, fn) {
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
};
|
|
910
|
-
const result = tracer.startActiveSpan(options.name, execute);
|
|
911
|
-
if (result instanceof Promise) {
|
|
912
|
-
return result;
|
|
913
|
-
}
|
|
914
|
-
return result;
|
|
746
|
+
const options = typeof nameOrOptions === "string" ? { name: nameOrOptions } : nameOrOptions;
|
|
747
|
+
const tracer = trace$1.getTracer("autotel-edge");
|
|
748
|
+
const execute = (span) => {
|
|
749
|
+
setSpanName(span, options.name);
|
|
750
|
+
try {
|
|
751
|
+
if (options.attributes) for (const [key, value] of Object.entries(options.attributes)) span.setAttribute(key, value);
|
|
752
|
+
const result = fn(span);
|
|
753
|
+
if (result instanceof Promise) return result.then((value) => {
|
|
754
|
+
span.setAttribute("code.function", options.name);
|
|
755
|
+
span.setStatus({ code: SpanStatusCode.OK });
|
|
756
|
+
span.end();
|
|
757
|
+
return value;
|
|
758
|
+
}).catch((error) => {
|
|
759
|
+
const message = truncateErrorMessage(error instanceof Error ? error.message : String(error ?? "Unknown error"));
|
|
760
|
+
span.setAttribute("code.function", options.name);
|
|
761
|
+
span.setStatus({
|
|
762
|
+
code: SpanStatusCode.ERROR,
|
|
763
|
+
message
|
|
764
|
+
});
|
|
765
|
+
span.recordException(error instanceof Error ? error : new Error(String(error)));
|
|
766
|
+
span.end();
|
|
767
|
+
throw error;
|
|
768
|
+
});
|
|
769
|
+
span.setAttribute("code.function", options.name);
|
|
770
|
+
span.setStatus({ code: SpanStatusCode.OK });
|
|
771
|
+
span.end();
|
|
772
|
+
return result;
|
|
773
|
+
} catch (error) {
|
|
774
|
+
const message = truncateErrorMessage(error instanceof Error ? error.message : String(error ?? "Unknown error"));
|
|
775
|
+
span.setAttribute("code.function", options.name);
|
|
776
|
+
span.setStatus({
|
|
777
|
+
code: SpanStatusCode.ERROR,
|
|
778
|
+
message
|
|
779
|
+
});
|
|
780
|
+
span.recordException(error instanceof Error ? error : new Error(String(error)));
|
|
781
|
+
span.end();
|
|
782
|
+
throw error;
|
|
783
|
+
}
|
|
784
|
+
};
|
|
785
|
+
const result = tracer.startActiveSpan(options.name, execute);
|
|
786
|
+
if (result instanceof Promise) return result;
|
|
787
|
+
return result;
|
|
915
788
|
}
|
|
916
789
|
|
|
917
|
-
|
|
790
|
+
//#endregion
|
|
791
|
+
//#region src/composition.ts
|
|
792
|
+
/**
|
|
793
|
+
* Identity helper for authoring an autotel configuration once with full
|
|
794
|
+
* type-checking. Mirrors `defineConfig` patterns in tools like Vite / Vitest.
|
|
795
|
+
*
|
|
796
|
+
* @example
|
|
797
|
+
* ```ts
|
|
798
|
+
* import { defineConfig } from 'autotel-edge'
|
|
799
|
+
*
|
|
800
|
+
* export const otelConfig = defineConfig({
|
|
801
|
+
* service: { name: 'checkout' },
|
|
802
|
+
* exporter: { url: process.env.OTLP_URL! },
|
|
803
|
+
* })
|
|
804
|
+
* ```
|
|
805
|
+
*/
|
|
918
806
|
function defineConfig(config) {
|
|
919
|
-
|
|
920
|
-
}
|
|
807
|
+
return config;
|
|
808
|
+
}
|
|
809
|
+
/**
|
|
810
|
+
* Run a list of subscribers in registration order. Errors thrown by an
|
|
811
|
+
* individual subscriber are caught and logged so a buggy subscriber never
|
|
812
|
+
* blocks the others — important because `subscribers` is the primary
|
|
813
|
+
* extensibility point for in-process side effects.
|
|
814
|
+
*/
|
|
921
815
|
function composeSubscribers(subscribers, options = {}) {
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
816
|
+
const label = options.name ?? "compose-subscribers";
|
|
817
|
+
return async (event) => {
|
|
818
|
+
for (const subscriber of subscribers) try {
|
|
819
|
+
await subscriber(event);
|
|
820
|
+
} catch (err) {
|
|
821
|
+
console.error(`[autotel-edge/${label}] subscriber failed:`, err);
|
|
822
|
+
}
|
|
823
|
+
};
|
|
824
|
+
}
|
|
825
|
+
/**
|
|
826
|
+
* Chain post-processors so each one sees the output of the previous one.
|
|
827
|
+
* This matches the standard OTel post-processor contract: take spans, return
|
|
828
|
+
* spans (possibly filtered, redacted, or annotated).
|
|
829
|
+
*/
|
|
933
830
|
function composePostProcessors(processors) {
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
831
|
+
return (spans) => {
|
|
832
|
+
let current = spans;
|
|
833
|
+
for (const processor of processors) try {
|
|
834
|
+
current = processor(current);
|
|
835
|
+
} catch (err) {
|
|
836
|
+
console.error("[autotel-edge/compose-post-processors] failed:", err);
|
|
837
|
+
}
|
|
838
|
+
return current;
|
|
839
|
+
};
|
|
840
|
+
}
|
|
841
|
+
/**
|
|
842
|
+
* Fan out span lifecycle events to multiple span processors. Any single
|
|
843
|
+
* processor's failure is isolated so it cannot break the others.
|
|
844
|
+
*
|
|
845
|
+
* Useful when you want to attach, say, a sampling processor + a custom
|
|
846
|
+
* attribute redactor + the default batch processor without having to author a
|
|
847
|
+
* single processor that knows about all three.
|
|
848
|
+
*/
|
|
946
849
|
function composeSpanProcessors(processors) {
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
);
|
|
973
|
-
},
|
|
974
|
-
async shutdown() {
|
|
975
|
-
await Promise.allSettled(
|
|
976
|
-
processors.map((p) => safe("shutdown", () => p.shutdown()))
|
|
977
|
-
);
|
|
978
|
-
}
|
|
979
|
-
};
|
|
850
|
+
const safe = (label, fn) => Promise.resolve().then(fn).catch((err) => {
|
|
851
|
+
console.error(`[autotel-edge/compose-span-processors:${label}]`, err);
|
|
852
|
+
});
|
|
853
|
+
return {
|
|
854
|
+
onStart(span, parentContext) {
|
|
855
|
+
for (const processor of processors) try {
|
|
856
|
+
processor.onStart(span, parentContext);
|
|
857
|
+
} catch (err) {
|
|
858
|
+
console.error("[autotel-edge/compose-span-processors:onStart]", err);
|
|
859
|
+
}
|
|
860
|
+
},
|
|
861
|
+
onEnd(span) {
|
|
862
|
+
for (const processor of processors) try {
|
|
863
|
+
processor.onEnd(span);
|
|
864
|
+
} catch (err) {
|
|
865
|
+
console.error("[autotel-edge/compose-span-processors:onEnd]", err);
|
|
866
|
+
}
|
|
867
|
+
},
|
|
868
|
+
async forceFlush() {
|
|
869
|
+
await Promise.allSettled(processors.map((p) => safe("forceFlush", () => p.forceFlush())));
|
|
870
|
+
},
|
|
871
|
+
async shutdown() {
|
|
872
|
+
await Promise.allSettled(processors.map((p) => safe("shutdown", () => p.shutdown())));
|
|
873
|
+
}
|
|
874
|
+
};
|
|
980
875
|
}
|
|
981
876
|
|
|
982
|
-
|
|
877
|
+
//#endregion
|
|
878
|
+
//#region src/plugin-runner.ts
|
|
983
879
|
function logPluginError(logger, name, hook, error) {
|
|
984
|
-
|
|
880
|
+
logger.error(`[autotel-edge/${name}] ${hook} failed:`, error);
|
|
985
881
|
}
|
|
986
882
|
function definePlugin(plugin) {
|
|
987
|
-
|
|
883
|
+
return plugin;
|
|
988
884
|
}
|
|
989
885
|
function createPluginRunner(plugins = [], options = {}) {
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
},
|
|
1087
|
-
async runKeep(ctx) {
|
|
1088
|
-
for (const plugin of list) {
|
|
1089
|
-
if (!plugin.keep) continue;
|
|
1090
|
-
try {
|
|
1091
|
-
await plugin.keep(ctx);
|
|
1092
|
-
} catch (err) {
|
|
1093
|
-
logPluginError(errorLogger, plugin.name, "keep", err);
|
|
1094
|
-
}
|
|
1095
|
-
}
|
|
1096
|
-
}
|
|
1097
|
-
};
|
|
1098
|
-
}
|
|
1099
|
-
var emptyRunner = createPluginRunner([]);
|
|
886
|
+
const errorLogger = options.logger ?? console;
|
|
887
|
+
const byName = /* @__PURE__ */ new Map();
|
|
888
|
+
for (const plugin of plugins) byName.set(plugin.name, plugin);
|
|
889
|
+
const list = Array.from(byName.values());
|
|
890
|
+
return {
|
|
891
|
+
plugins: list,
|
|
892
|
+
hasEnrich: list.some((p) => typeof p.enrich === "function"),
|
|
893
|
+
hasDrain: list.some((p) => typeof p.drain === "function"),
|
|
894
|
+
hasKeep: list.some((p) => typeof p.keep === "function"),
|
|
895
|
+
hasRequestLifecycle: list.some((p) => typeof p.onRequestStart === "function" || typeof p.onRequestFinish === "function"),
|
|
896
|
+
hasClientLog: list.some((p) => typeof p.onClientLog === "function"),
|
|
897
|
+
hasExtendLogger: list.some((p) => typeof p.extendLogger === "function"),
|
|
898
|
+
applyExtendLogger(logger) {
|
|
899
|
+
for (const plugin of list) {
|
|
900
|
+
if (!plugin.extendLogger) continue;
|
|
901
|
+
try {
|
|
902
|
+
plugin.extendLogger(logger);
|
|
903
|
+
} catch (err) {
|
|
904
|
+
logPluginError(errorLogger, plugin.name, "extendLogger", err);
|
|
905
|
+
}
|
|
906
|
+
}
|
|
907
|
+
},
|
|
908
|
+
runOnRequestStart(ctx) {
|
|
909
|
+
for (const plugin of list) {
|
|
910
|
+
if (!plugin.onRequestStart) continue;
|
|
911
|
+
try {
|
|
912
|
+
plugin.onRequestStart(ctx);
|
|
913
|
+
} catch (err) {
|
|
914
|
+
logPluginError(errorLogger, plugin.name, "onRequestStart", err);
|
|
915
|
+
}
|
|
916
|
+
}
|
|
917
|
+
},
|
|
918
|
+
runOnRequestFinish(ctx) {
|
|
919
|
+
for (const plugin of list) {
|
|
920
|
+
if (!plugin.onRequestFinish) continue;
|
|
921
|
+
try {
|
|
922
|
+
plugin.onRequestFinish(ctx);
|
|
923
|
+
} catch (err) {
|
|
924
|
+
logPluginError(errorLogger, plugin.name, "onRequestFinish", err);
|
|
925
|
+
}
|
|
926
|
+
}
|
|
927
|
+
},
|
|
928
|
+
runOnClientLog(ctx) {
|
|
929
|
+
for (const plugin of list) {
|
|
930
|
+
if (!plugin.onClientLog) continue;
|
|
931
|
+
try {
|
|
932
|
+
plugin.onClientLog(ctx);
|
|
933
|
+
} catch (err) {
|
|
934
|
+
logPluginError(errorLogger, plugin.name, "onClientLog", err);
|
|
935
|
+
}
|
|
936
|
+
}
|
|
937
|
+
},
|
|
938
|
+
async runSetup(ctx) {
|
|
939
|
+
for (const plugin of list) {
|
|
940
|
+
if (!plugin.setup) continue;
|
|
941
|
+
try {
|
|
942
|
+
await plugin.setup(ctx);
|
|
943
|
+
} catch (err) {
|
|
944
|
+
logPluginError(errorLogger, plugin.name, "setup", err);
|
|
945
|
+
}
|
|
946
|
+
}
|
|
947
|
+
},
|
|
948
|
+
async runEnrich(ctx) {
|
|
949
|
+
for (const plugin of list) {
|
|
950
|
+
if (!plugin.enrich) continue;
|
|
951
|
+
try {
|
|
952
|
+
await plugin.enrich(ctx);
|
|
953
|
+
} catch (err) {
|
|
954
|
+
logPluginError(errorLogger, plugin.name, "enrich", err);
|
|
955
|
+
}
|
|
956
|
+
}
|
|
957
|
+
},
|
|
958
|
+
async runDrain(ctx) {
|
|
959
|
+
const drains = list.filter((p) => typeof p.drain === "function");
|
|
960
|
+
if (drains.length === 0) return;
|
|
961
|
+
await Promise.allSettled(drains.map(async (plugin) => {
|
|
962
|
+
try {
|
|
963
|
+
await plugin.drain(ctx);
|
|
964
|
+
} catch (err) {
|
|
965
|
+
logPluginError(errorLogger, plugin.name, "drain", err);
|
|
966
|
+
}
|
|
967
|
+
}));
|
|
968
|
+
},
|
|
969
|
+
async runKeep(ctx) {
|
|
970
|
+
for (const plugin of list) {
|
|
971
|
+
if (!plugin.keep) continue;
|
|
972
|
+
try {
|
|
973
|
+
await plugin.keep(ctx);
|
|
974
|
+
} catch (err) {
|
|
975
|
+
logPluginError(errorLogger, plugin.name, "keep", err);
|
|
976
|
+
}
|
|
977
|
+
}
|
|
978
|
+
}
|
|
979
|
+
};
|
|
980
|
+
}
|
|
981
|
+
const emptyRunner = createPluginRunner([]);
|
|
1100
982
|
function getEmptyPluginRunner() {
|
|
1101
|
-
|
|
983
|
+
return emptyRunner;
|
|
1102
984
|
}
|
|
1103
985
|
|
|
1104
|
-
|
|
986
|
+
//#endregion
|
|
987
|
+
//#region src/middleware-toolkit.ts
|
|
1105
988
|
function matchesRoutePattern(path, pattern) {
|
|
1106
|
-
|
|
1107
|
-
|
|
989
|
+
const regexPattern = pattern.replaceAll(/[.+^${}()|[\]\\]/g, String.raw`\$&`).replaceAll("**", "{{GLOBSTAR}}").replaceAll("*", "[^/]*").replaceAll("{{GLOBSTAR}}", ".*").replaceAll("?", "[^/]");
|
|
990
|
+
return new RegExp(`^${regexPattern}$`).test(path);
|
|
1108
991
|
}
|
|
1109
992
|
function shouldInstrumentPath(path, options = {}) {
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
if (!include || include.length === 0) {
|
|
1115
|
-
return true;
|
|
1116
|
-
}
|
|
1117
|
-
return include.some((pattern) => matchesRoutePattern(path, pattern));
|
|
993
|
+
const { include, exclude } = options;
|
|
994
|
+
if (exclude && exclude.some((pattern) => matchesRoutePattern(path, pattern))) return false;
|
|
995
|
+
if (!include || include.length === 0) return true;
|
|
996
|
+
return include.some((pattern) => matchesRoutePattern(path, pattern));
|
|
1118
997
|
}
|
|
1119
998
|
function getServiceForPath(path, routes) {
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
if (matchesRoutePattern(path, pattern)) {
|
|
1123
|
-
return config.service;
|
|
1124
|
-
}
|
|
1125
|
-
}
|
|
1126
|
-
return void 0;
|
|
999
|
+
if (!routes) return void 0;
|
|
1000
|
+
for (const [pattern, config] of Object.entries(routes)) if (matchesRoutePattern(path, pattern)) return config.service;
|
|
1127
1001
|
}
|
|
1128
1002
|
async function runMiddlewareFinishPipeline(ctx, options = {}) {
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
logger.error("[autotel-edge/middleware] drain failed:", err);
|
|
1145
|
-
}
|
|
1146
|
-
})
|
|
1147
|
-
);
|
|
1003
|
+
const logger = options.logger ?? console;
|
|
1004
|
+
for (const enrich of options.enrichers ?? []) try {
|
|
1005
|
+
await enrich(ctx);
|
|
1006
|
+
} catch (err) {
|
|
1007
|
+
logger.error("[autotel-edge/middleware] enricher failed:", err);
|
|
1008
|
+
}
|
|
1009
|
+
const drains = options.drains ?? [];
|
|
1010
|
+
if (drains.length === 0) return;
|
|
1011
|
+
await Promise.allSettled(drains.map(async (drain) => {
|
|
1012
|
+
try {
|
|
1013
|
+
await drain(ctx);
|
|
1014
|
+
} catch (err) {
|
|
1015
|
+
logger.error("[autotel-edge/middleware] drain failed:", err);
|
|
1016
|
+
}
|
|
1017
|
+
}));
|
|
1148
1018
|
}
|
|
1149
1019
|
|
|
1150
|
-
|
|
1151
|
-
|
|
1020
|
+
//#endregion
|
|
1021
|
+
export { AsyncLocalStorageContextManager, Buffer, OTLPExporter, SpanImpl, WorkerTracer, WorkerTracerProvider, composePostProcessors, composeSpanProcessors, composeSubscribers, context, createInitialiser, createPluginRunner, defineConfig, definePlugin, getActiveConfig, getEmptyPluginRunner, getExecutionLogger, getServiceForPath, instrument as instrumentFunctions, matchesRoutePattern, parseConfig, parseError, propagation, runMiddlewareFinishPipeline, setConfig, shouldInstrumentPath, span, trace, withNextSpan, withTracing };
|
|
1152
1022
|
//# sourceMappingURL=index.js.map
|