autotel 2.1.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/LICENSE +21 -0
- package/README.md +1946 -0
- package/dist/chunk-2LNRY4QK.js +273 -0
- package/dist/chunk-2LNRY4QK.js.map +1 -0
- package/dist/chunk-3HENGDW2.js +587 -0
- package/dist/chunk-3HENGDW2.js.map +1 -0
- package/dist/chunk-4OAT42CA.cjs +73 -0
- package/dist/chunk-4OAT42CA.cjs.map +1 -0
- package/dist/chunk-5GWX5LFW.js +70 -0
- package/dist/chunk-5GWX5LFW.js.map +1 -0
- package/dist/chunk-5R2M36QB.js +195 -0
- package/dist/chunk-5R2M36QB.js.map +1 -0
- package/dist/chunk-5ZN622AO.js +73 -0
- package/dist/chunk-5ZN622AO.js.map +1 -0
- package/dist/chunk-77MSMAUQ.cjs +498 -0
- package/dist/chunk-77MSMAUQ.cjs.map +1 -0
- package/dist/chunk-ABPEQ6RK.cjs +596 -0
- package/dist/chunk-ABPEQ6RK.cjs.map +1 -0
- package/dist/chunk-BWYGJKRB.js +95 -0
- package/dist/chunk-BWYGJKRB.js.map +1 -0
- package/dist/chunk-BZHG5IZ4.js +73 -0
- package/dist/chunk-BZHG5IZ4.js.map +1 -0
- package/dist/chunk-G7VZBCD6.cjs +35 -0
- package/dist/chunk-G7VZBCD6.cjs.map +1 -0
- package/dist/chunk-GVLK7YUU.cjs +30 -0
- package/dist/chunk-GVLK7YUU.cjs.map +1 -0
- package/dist/chunk-HCCXC7XG.js +205 -0
- package/dist/chunk-HCCXC7XG.js.map +1 -0
- package/dist/chunk-HE6T6FIX.cjs +203 -0
- package/dist/chunk-HE6T6FIX.cjs.map +1 -0
- package/dist/chunk-KIXWPOCO.cjs +100 -0
- package/dist/chunk-KIXWPOCO.cjs.map +1 -0
- package/dist/chunk-KVGNW3FC.js +87 -0
- package/dist/chunk-KVGNW3FC.js.map +1 -0
- package/dist/chunk-LITNXTTT.js +3 -0
- package/dist/chunk-LITNXTTT.js.map +1 -0
- package/dist/chunk-M4ANN7RL.js +114 -0
- package/dist/chunk-M4ANN7RL.js.map +1 -0
- package/dist/chunk-NC52UBR2.cjs +32 -0
- package/dist/chunk-NC52UBR2.cjs.map +1 -0
- package/dist/chunk-NHCNRQD3.cjs +212 -0
- package/dist/chunk-NHCNRQD3.cjs.map +1 -0
- package/dist/chunk-NZ72VDNY.cjs +4 -0
- package/dist/chunk-NZ72VDNY.cjs.map +1 -0
- package/dist/chunk-P6JUDYNO.js +57 -0
- package/dist/chunk-P6JUDYNO.js.map +1 -0
- package/dist/chunk-RJYY7BWX.js +1349 -0
- package/dist/chunk-RJYY7BWX.js.map +1 -0
- package/dist/chunk-TRI4V5BF.cjs +126 -0
- package/dist/chunk-TRI4V5BF.cjs.map +1 -0
- package/dist/chunk-UL33I6IS.js +139 -0
- package/dist/chunk-UL33I6IS.js.map +1 -0
- package/dist/chunk-URRW6M2C.cjs +61 -0
- package/dist/chunk-URRW6M2C.cjs.map +1 -0
- package/dist/chunk-UY3UYPBZ.cjs +77 -0
- package/dist/chunk-UY3UYPBZ.cjs.map +1 -0
- package/dist/chunk-W3253FGB.cjs +277 -0
- package/dist/chunk-W3253FGB.cjs.map +1 -0
- package/dist/chunk-W7LHZVQF.js +26 -0
- package/dist/chunk-W7LHZVQF.js.map +1 -0
- package/dist/chunk-WBWNM6LB.cjs +1360 -0
- package/dist/chunk-WBWNM6LB.cjs.map +1 -0
- package/dist/chunk-WFJ7L2RV.js +494 -0
- package/dist/chunk-WFJ7L2RV.js.map +1 -0
- package/dist/chunk-X4RMFFMR.js +28 -0
- package/dist/chunk-X4RMFFMR.js.map +1 -0
- package/dist/chunk-Y4Y2S7BM.cjs +92 -0
- package/dist/chunk-Y4Y2S7BM.cjs.map +1 -0
- package/dist/chunk-YLPNXZFI.cjs +143 -0
- package/dist/chunk-YLPNXZFI.cjs.map +1 -0
- package/dist/chunk-YTXEZ4SD.cjs +77 -0
- package/dist/chunk-YTXEZ4SD.cjs.map +1 -0
- package/dist/chunk-Z6ZWNWWR.js +30 -0
- package/dist/chunk-Z6ZWNWWR.js.map +1 -0
- package/dist/config.cjs +26 -0
- package/dist/config.cjs.map +1 -0
- package/dist/config.d.cts +75 -0
- package/dist/config.d.ts +75 -0
- package/dist/config.js +5 -0
- package/dist/config.js.map +1 -0
- package/dist/db.cjs +233 -0
- package/dist/db.cjs.map +1 -0
- package/dist/db.d.cts +123 -0
- package/dist/db.d.ts +123 -0
- package/dist/db.js +228 -0
- package/dist/db.js.map +1 -0
- package/dist/decorators.cjs +67 -0
- package/dist/decorators.cjs.map +1 -0
- package/dist/decorators.d.cts +91 -0
- package/dist/decorators.d.ts +91 -0
- package/dist/decorators.js +65 -0
- package/dist/decorators.js.map +1 -0
- package/dist/event-subscriber.cjs +6 -0
- package/dist/event-subscriber.cjs.map +1 -0
- package/dist/event-subscriber.d.cts +116 -0
- package/dist/event-subscriber.d.ts +116 -0
- package/dist/event-subscriber.js +3 -0
- package/dist/event-subscriber.js.map +1 -0
- package/dist/event-testing.cjs +21 -0
- package/dist/event-testing.cjs.map +1 -0
- package/dist/event-testing.d.cts +110 -0
- package/dist/event-testing.d.ts +110 -0
- package/dist/event-testing.js +4 -0
- package/dist/event-testing.js.map +1 -0
- package/dist/event.cjs +30 -0
- package/dist/event.cjs.map +1 -0
- package/dist/event.d.cts +282 -0
- package/dist/event.d.ts +282 -0
- package/dist/event.js +13 -0
- package/dist/event.js.map +1 -0
- package/dist/exporters.cjs +17 -0
- package/dist/exporters.cjs.map +1 -0
- package/dist/exporters.d.cts +1 -0
- package/dist/exporters.d.ts +1 -0
- package/dist/exporters.js +4 -0
- package/dist/exporters.js.map +1 -0
- package/dist/functional.cjs +46 -0
- package/dist/functional.cjs.map +1 -0
- package/dist/functional.d.cts +478 -0
- package/dist/functional.d.ts +478 -0
- package/dist/functional.js +13 -0
- package/dist/functional.js.map +1 -0
- package/dist/http.cjs +189 -0
- package/dist/http.cjs.map +1 -0
- package/dist/http.d.cts +169 -0
- package/dist/http.d.ts +169 -0
- package/dist/http.js +184 -0
- package/dist/http.js.map +1 -0
- package/dist/index.cjs +333 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +758 -0
- package/dist/index.d.ts +758 -0
- package/dist/index.js +143 -0
- package/dist/index.js.map +1 -0
- package/dist/instrumentation.cjs +182 -0
- package/dist/instrumentation.cjs.map +1 -0
- package/dist/instrumentation.d.cts +49 -0
- package/dist/instrumentation.d.ts +49 -0
- package/dist/instrumentation.js +179 -0
- package/dist/instrumentation.js.map +1 -0
- package/dist/logger.cjs +19 -0
- package/dist/logger.cjs.map +1 -0
- package/dist/logger.d.cts +146 -0
- package/dist/logger.d.ts +146 -0
- package/dist/logger.js +6 -0
- package/dist/logger.js.map +1 -0
- package/dist/metric-helpers.cjs +31 -0
- package/dist/metric-helpers.cjs.map +1 -0
- package/dist/metric-helpers.d.cts +13 -0
- package/dist/metric-helpers.d.ts +13 -0
- package/dist/metric-helpers.js +6 -0
- package/dist/metric-helpers.js.map +1 -0
- package/dist/metric-testing.cjs +21 -0
- package/dist/metric-testing.cjs.map +1 -0
- package/dist/metric-testing.d.cts +110 -0
- package/dist/metric-testing.d.ts +110 -0
- package/dist/metric-testing.js +4 -0
- package/dist/metric-testing.js.map +1 -0
- package/dist/metric.cjs +26 -0
- package/dist/metric.cjs.map +1 -0
- package/dist/metric.d.cts +240 -0
- package/dist/metric.d.ts +240 -0
- package/dist/metric.js +9 -0
- package/dist/metric.js.map +1 -0
- package/dist/processors.cjs +17 -0
- package/dist/processors.cjs.map +1 -0
- package/dist/processors.d.cts +1 -0
- package/dist/processors.d.ts +1 -0
- package/dist/processors.js +4 -0
- package/dist/processors.js.map +1 -0
- package/dist/sampling.cjs +40 -0
- package/dist/sampling.cjs.map +1 -0
- package/dist/sampling.d.cts +260 -0
- package/dist/sampling.d.ts +260 -0
- package/dist/sampling.js +7 -0
- package/dist/sampling.js.map +1 -0
- package/dist/semantic-helpers.cjs +35 -0
- package/dist/semantic-helpers.cjs.map +1 -0
- package/dist/semantic-helpers.d.cts +442 -0
- package/dist/semantic-helpers.d.ts +442 -0
- package/dist/semantic-helpers.js +14 -0
- package/dist/semantic-helpers.js.map +1 -0
- package/dist/tail-sampling-processor.cjs +13 -0
- package/dist/tail-sampling-processor.cjs.map +1 -0
- package/dist/tail-sampling-processor.d.cts +27 -0
- package/dist/tail-sampling-processor.d.ts +27 -0
- package/dist/tail-sampling-processor.js +4 -0
- package/dist/tail-sampling-processor.js.map +1 -0
- package/dist/testing.cjs +286 -0
- package/dist/testing.cjs.map +1 -0
- package/dist/testing.d.cts +291 -0
- package/dist/testing.d.ts +291 -0
- package/dist/testing.js +263 -0
- package/dist/testing.js.map +1 -0
- package/dist/trace-context-DRZdUvVY.d.cts +181 -0
- package/dist/trace-context-DRZdUvVY.d.ts +181 -0
- package/dist/trace-helpers.cjs +54 -0
- package/dist/trace-helpers.cjs.map +1 -0
- package/dist/trace-helpers.d.cts +524 -0
- package/dist/trace-helpers.d.ts +524 -0
- package/dist/trace-helpers.js +5 -0
- package/dist/trace-helpers.js.map +1 -0
- package/dist/tracer-provider.cjs +21 -0
- package/dist/tracer-provider.cjs.map +1 -0
- package/dist/tracer-provider.d.cts +169 -0
- package/dist/tracer-provider.d.ts +169 -0
- package/dist/tracer-provider.js +4 -0
- package/dist/tracer-provider.js.map +1 -0
- package/package.json +280 -0
- package/src/baggage-span-processor.test.ts +202 -0
- package/src/baggage-span-processor.ts +98 -0
- package/src/circuit-breaker.test.ts +341 -0
- package/src/circuit-breaker.ts +184 -0
- package/src/config.test.ts +94 -0
- package/src/config.ts +169 -0
- package/src/db.test.ts +252 -0
- package/src/db.ts +447 -0
- package/src/decorators.test.ts +203 -0
- package/src/decorators.ts +188 -0
- package/src/env-config.test.ts +246 -0
- package/src/env-config.ts +158 -0
- package/src/event-queue.test.ts +222 -0
- package/src/event-queue.ts +203 -0
- package/src/event-subscriber.ts +136 -0
- package/src/event-testing.ts +197 -0
- package/src/event.test.ts +718 -0
- package/src/event.ts +556 -0
- package/src/exporters.ts +96 -0
- package/src/functional.test.ts +1059 -0
- package/src/functional.ts +2295 -0
- package/src/http.test.ts +487 -0
- package/src/http.ts +424 -0
- package/src/index.ts +158 -0
- package/src/init.customization.test.ts +210 -0
- package/src/init.integrations.test.ts +366 -0
- package/src/init.openllmetry.test.ts +282 -0
- package/src/init.protocol.test.ts +215 -0
- package/src/init.ts +1426 -0
- package/src/instrumentation.test.ts +108 -0
- package/src/instrumentation.ts +308 -0
- package/src/logger.test.ts +117 -0
- package/src/logger.ts +246 -0
- package/src/metric-helpers.ts +47 -0
- package/src/metric-testing.ts +197 -0
- package/src/metric.ts +434 -0
- package/src/metrics.test.ts +205 -0
- package/src/operation-context.ts +93 -0
- package/src/processors.ts +106 -0
- package/src/rate-limiter.test.ts +199 -0
- package/src/rate-limiter.ts +98 -0
- package/src/sampling.test.ts +513 -0
- package/src/sampling.ts +428 -0
- package/src/semantic-helpers.test.ts +311 -0
- package/src/semantic-helpers.ts +584 -0
- package/src/shutdown.test.ts +311 -0
- package/src/shutdown.ts +222 -0
- package/src/stub.integration.test.ts +361 -0
- package/src/tail-sampling-processor.test.ts +226 -0
- package/src/tail-sampling-processor.ts +51 -0
- package/src/testing.ts +670 -0
- package/src/trace-context.ts +470 -0
- package/src/trace-helpers.new.test.ts +278 -0
- package/src/trace-helpers.test.ts +242 -0
- package/src/trace-helpers.ts +690 -0
- package/src/tracer-provider.test.ts +183 -0
- package/src/tracer-provider.ts +266 -0
- package/src/track.test.ts +153 -0
- package/src/track.ts +120 -0
- package/src/validation.test.ts +306 -0
- package/src/validation.ts +239 -0
- package/src/variable-name-inference.test.ts +178 -0
- package/src/variable-name-inference.ts +242 -0
|
@@ -0,0 +1,1349 @@
|
|
|
1
|
+
import { setSpanName } from './chunk-M4ANN7RL.js';
|
|
2
|
+
import { init_trace_context, createTraceContext, getContextStorage, getActiveContextWithBaggage } from './chunk-HCCXC7XG.js';
|
|
3
|
+
import { validateEvent, runInOperationContext } from './chunk-UL33I6IS.js';
|
|
4
|
+
import { getValidationConfig, isInitialized, warnIfNotInitialized, getConfig as getConfig$1, getLogger, getSdk } from './chunk-3HENGDW2.js';
|
|
5
|
+
import { AlwaysSampler } from './chunk-5R2M36QB.js';
|
|
6
|
+
import { getConfig } from './chunk-KVGNW3FC.js';
|
|
7
|
+
import { trace, SpanStatusCode, context, propagation } from '@opentelemetry/api';
|
|
8
|
+
import { readFileSync } from 'fs';
|
|
9
|
+
import { fileURLToPath } from 'url';
|
|
10
|
+
|
|
11
|
+
// src/rate-limiter.ts
|
|
12
|
+
var TokenBucketRateLimiter = class {
|
|
13
|
+
tokens;
|
|
14
|
+
maxTokens;
|
|
15
|
+
refillRate;
|
|
16
|
+
// tokens per millisecond
|
|
17
|
+
lastRefill;
|
|
18
|
+
constructor(config) {
|
|
19
|
+
this.maxTokens = config.burstCapacity || config.maxEventsPerSecond * 2;
|
|
20
|
+
this.tokens = this.maxTokens;
|
|
21
|
+
this.refillRate = config.maxEventsPerSecond / 1e3;
|
|
22
|
+
this.lastRefill = Date.now();
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Try to consume a token (allow an event)
|
|
26
|
+
* Returns true if allowed, false if rate limit exceeded
|
|
27
|
+
*/
|
|
28
|
+
tryConsume(count = 1) {
|
|
29
|
+
this.refill();
|
|
30
|
+
if (this.tokens >= count) {
|
|
31
|
+
this.tokens -= count;
|
|
32
|
+
return true;
|
|
33
|
+
}
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Wait until a token is available (async rate limiting)
|
|
38
|
+
* Returns a promise that resolves when the event can be processed
|
|
39
|
+
*/
|
|
40
|
+
async waitForToken(count = 1) {
|
|
41
|
+
this.refill();
|
|
42
|
+
if (this.tokens >= count) {
|
|
43
|
+
this.tokens -= count;
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
const tokensNeeded = count - this.tokens;
|
|
47
|
+
const waitMs = Math.ceil(tokensNeeded / this.refillRate);
|
|
48
|
+
await new Promise((resolve) => setTimeout(resolve, waitMs));
|
|
49
|
+
return this.waitForToken(count);
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Refill tokens based on elapsed time
|
|
53
|
+
*/
|
|
54
|
+
refill() {
|
|
55
|
+
const now = Date.now();
|
|
56
|
+
const elapsed = now - this.lastRefill;
|
|
57
|
+
const tokensToAdd = elapsed * this.refillRate;
|
|
58
|
+
this.tokens = Math.min(this.maxTokens, this.tokens + tokensToAdd);
|
|
59
|
+
this.lastRefill = now;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Get current available tokens (for testing/debugging)
|
|
63
|
+
*/
|
|
64
|
+
getAvailableTokens() {
|
|
65
|
+
this.refill();
|
|
66
|
+
return Math.floor(this.tokens);
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Reset the rate limiter (for testing)
|
|
70
|
+
*/
|
|
71
|
+
reset() {
|
|
72
|
+
this.tokens = this.maxTokens;
|
|
73
|
+
this.lastRefill = Date.now();
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
// src/event-queue.ts
|
|
78
|
+
var DEFAULT_CONFIG = {
|
|
79
|
+
maxSize: 5e4,
|
|
80
|
+
batchSize: 100,
|
|
81
|
+
flushInterval: 1e4,
|
|
82
|
+
maxRetries: 3,
|
|
83
|
+
rateLimit: {
|
|
84
|
+
maxEventsPerSecond: 100,
|
|
85
|
+
burstCapacity: 200
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
var EventQueue = class {
|
|
89
|
+
queue = [];
|
|
90
|
+
flushTimer = null;
|
|
91
|
+
config;
|
|
92
|
+
subscribers;
|
|
93
|
+
rateLimiter;
|
|
94
|
+
flushing = false;
|
|
95
|
+
constructor(subscribers, config) {
|
|
96
|
+
this.subscribers = subscribers;
|
|
97
|
+
this.config = { ...DEFAULT_CONFIG, ...config };
|
|
98
|
+
this.rateLimiter = this.config.rateLimit ? new TokenBucketRateLimiter(this.config.rateLimit) : null;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Enqueue an event for sending
|
|
102
|
+
*
|
|
103
|
+
* Backpressure policy:
|
|
104
|
+
* - Drops oldest event and logs warning if queue is full (same behavior in all environments)
|
|
105
|
+
*/
|
|
106
|
+
enqueue(event) {
|
|
107
|
+
if (this.queue.length >= this.config.maxSize) {
|
|
108
|
+
const droppedEvent = this.queue.shift();
|
|
109
|
+
getLogger().warn(
|
|
110
|
+
`[autotel] Events queue full (${this.config.maxSize} events). Dropping oldest event. Events are being produced faster than they can be sent. Check your subscribers or reduce tracking frequency.`,
|
|
111
|
+
{ droppedEvent: droppedEvent?.name }
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
this.queue.push(event);
|
|
115
|
+
this.scheduleBatchFlush();
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Schedule a batch flush if not already scheduled
|
|
119
|
+
*/
|
|
120
|
+
scheduleBatchFlush() {
|
|
121
|
+
if (this.flushTimer || this.flushing) return;
|
|
122
|
+
this.flushTimer = setTimeout(() => {
|
|
123
|
+
this.flushTimer = null;
|
|
124
|
+
void this.flushBatch();
|
|
125
|
+
}, this.config.flushInterval);
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Flush a batch of events
|
|
129
|
+
*/
|
|
130
|
+
async flushBatch() {
|
|
131
|
+
if (this.queue.length === 0 || this.flushing) return;
|
|
132
|
+
this.flushing = true;
|
|
133
|
+
try {
|
|
134
|
+
const batch = this.queue.splice(0, this.config.batchSize);
|
|
135
|
+
await this.sendWithRetry(batch, this.config.maxRetries);
|
|
136
|
+
} finally {
|
|
137
|
+
this.flushing = false;
|
|
138
|
+
if (this.queue.length > 0) {
|
|
139
|
+
this.scheduleBatchFlush();
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Send events with exponential backoff retry
|
|
145
|
+
*/
|
|
146
|
+
async sendWithRetry(events, retriesLeft) {
|
|
147
|
+
try {
|
|
148
|
+
await this.sendToSubscribers(events);
|
|
149
|
+
} catch (error) {
|
|
150
|
+
if (retriesLeft > 0) {
|
|
151
|
+
const delay = Math.pow(2, this.config.maxRetries - retriesLeft) * 1e3;
|
|
152
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
153
|
+
return this.sendWithRetry(events, retriesLeft - 1);
|
|
154
|
+
} else {
|
|
155
|
+
getLogger().error(
|
|
156
|
+
"[autotel] Failed to send events after retries",
|
|
157
|
+
error instanceof Error ? error : void 0,
|
|
158
|
+
{ retriesAttempted: this.config.maxRetries }
|
|
159
|
+
);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Send events to all configured subscribers with rate limiting
|
|
165
|
+
*/
|
|
166
|
+
async sendToSubscribers(events) {
|
|
167
|
+
if (!this.rateLimiter) {
|
|
168
|
+
const promises = events.map(
|
|
169
|
+
(event) => Promise.all(
|
|
170
|
+
this.subscribers.map(
|
|
171
|
+
(subscriber) => subscriber.trackEvent(event.name, event.attributes)
|
|
172
|
+
)
|
|
173
|
+
)
|
|
174
|
+
);
|
|
175
|
+
await Promise.all(promises);
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
for (const event of events) {
|
|
179
|
+
await this.rateLimiter.waitForToken();
|
|
180
|
+
await Promise.all(
|
|
181
|
+
this.subscribers.map(
|
|
182
|
+
(subscriber) => subscriber.trackEvent(event.name, event.attributes)
|
|
183
|
+
)
|
|
184
|
+
);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Flush all remaining events (for shutdown)
|
|
189
|
+
*/
|
|
190
|
+
async flush() {
|
|
191
|
+
if (this.flushTimer) {
|
|
192
|
+
clearTimeout(this.flushTimer);
|
|
193
|
+
this.flushTimer = null;
|
|
194
|
+
}
|
|
195
|
+
while (this.flushing) {
|
|
196
|
+
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
197
|
+
}
|
|
198
|
+
while (this.queue.length > 0) {
|
|
199
|
+
await this.flushBatch();
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Get queue size (for testing/debugging)
|
|
204
|
+
*/
|
|
205
|
+
size() {
|
|
206
|
+
return this.queue.length;
|
|
207
|
+
}
|
|
208
|
+
};
|
|
209
|
+
|
|
210
|
+
// src/track.ts
|
|
211
|
+
var eventsQueue = null;
|
|
212
|
+
function getOrCreateQueue() {
|
|
213
|
+
if (!isInitialized()) {
|
|
214
|
+
warnIfNotInitialized("track()");
|
|
215
|
+
return null;
|
|
216
|
+
}
|
|
217
|
+
if (!eventsQueue) {
|
|
218
|
+
const config = getConfig$1();
|
|
219
|
+
if (!config?.subscribers || config.subscribers.length === 0) {
|
|
220
|
+
return null;
|
|
221
|
+
}
|
|
222
|
+
eventsQueue = new EventQueue(config.subscribers);
|
|
223
|
+
}
|
|
224
|
+
return eventsQueue;
|
|
225
|
+
}
|
|
226
|
+
function track(event, data) {
|
|
227
|
+
const queue = getOrCreateQueue();
|
|
228
|
+
if (!queue) return;
|
|
229
|
+
const validationConfig = getValidationConfig();
|
|
230
|
+
const validated = validateEvent(event, data, validationConfig || void 0);
|
|
231
|
+
const span2 = trace.getActiveSpan();
|
|
232
|
+
const enrichedData = span2 ? {
|
|
233
|
+
...validated.attributes,
|
|
234
|
+
traceId: span2.spanContext().traceId,
|
|
235
|
+
spanId: span2.spanContext().spanId
|
|
236
|
+
} : validated.attributes;
|
|
237
|
+
queue.enqueue({
|
|
238
|
+
name: validated.eventName,
|
|
239
|
+
attributes: enrichedData,
|
|
240
|
+
timestamp: Date.now()
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
function getEventQueue() {
|
|
244
|
+
return eventsQueue;
|
|
245
|
+
}
|
|
246
|
+
function resetEventQueue() {
|
|
247
|
+
eventsQueue = null;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// src/functional.ts
|
|
251
|
+
init_trace_context();
|
|
252
|
+
var inferenceCache = /* @__PURE__ */ new Map();
|
|
253
|
+
var MAX_CACHE_SIZE = 50;
|
|
254
|
+
function captureStackTrace() {
|
|
255
|
+
const originalStackTraceLimit = Error.stackTraceLimit;
|
|
256
|
+
Error.stackTraceLimit = 10;
|
|
257
|
+
const err = new Error("Stack trace capture");
|
|
258
|
+
const stack = err.stack || "";
|
|
259
|
+
Error.stackTraceLimit = originalStackTraceLimit;
|
|
260
|
+
return stack;
|
|
261
|
+
}
|
|
262
|
+
function parseCallLocation(stack) {
|
|
263
|
+
const lines = stack.split("\n");
|
|
264
|
+
let skippedExternalFrame = false;
|
|
265
|
+
for (const line of lines) {
|
|
266
|
+
if (line.includes("variable-name-inference.ts") || line.includes("variable-name-inference.js") || line.includes("functional.ts") || line.includes("functional.js")) {
|
|
267
|
+
continue;
|
|
268
|
+
}
|
|
269
|
+
const match = line.match(/at\s+(?:.*\s+)?\(?([^:]+):(\d+):(\d+)\)?/) || line.match(/^.*?([^:]+):(\d+):(\d+)/);
|
|
270
|
+
if (match) {
|
|
271
|
+
let filePath = match[1].trim();
|
|
272
|
+
if (filePath.startsWith("file://")) {
|
|
273
|
+
try {
|
|
274
|
+
filePath = fileURLToPath(filePath);
|
|
275
|
+
} catch {
|
|
276
|
+
continue;
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
if (!skippedExternalFrame) {
|
|
280
|
+
skippedExternalFrame = true;
|
|
281
|
+
continue;
|
|
282
|
+
}
|
|
283
|
+
return {
|
|
284
|
+
file: filePath,
|
|
285
|
+
line: Number.parseInt(match[2], 10),
|
|
286
|
+
column: Number.parseInt(match[3], 10)
|
|
287
|
+
};
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
return void 0;
|
|
291
|
+
}
|
|
292
|
+
function readSourceLine(filePath, lineNumber) {
|
|
293
|
+
try {
|
|
294
|
+
if (typeof readFileSync !== "function") {
|
|
295
|
+
return void 0;
|
|
296
|
+
}
|
|
297
|
+
const content = readFileSync(filePath, "utf8");
|
|
298
|
+
const lines = content.split("\n");
|
|
299
|
+
return lines[lineNumber - 1];
|
|
300
|
+
} catch {
|
|
301
|
+
return void 0;
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
function extractVariableName(sourceLine) {
|
|
305
|
+
const trimmed = sourceLine.trim();
|
|
306
|
+
const patterns = [
|
|
307
|
+
// export const varName = anyFunction(
|
|
308
|
+
/export\s+const\s+([a-zA-Z_$][a-zA-Z0-9_$]*)\s*=\s*[a-zA-Z_$][a-zA-Z0-9_$]*\s*\(/,
|
|
309
|
+
// const varName = anyFunction(
|
|
310
|
+
/const\s+([a-zA-Z_$][a-zA-Z0-9_$]*)\s*=\s*[a-zA-Z_$][a-zA-Z0-9_$]*\s*\(/,
|
|
311
|
+
// export let varName = anyFunction(
|
|
312
|
+
/export\s+let\s+([a-zA-Z_$][a-zA-Z0-9_$]*)\s*=\s*[a-zA-Z_$][a-zA-Z0-9_$]*\s*\(/,
|
|
313
|
+
// let varName = anyFunction(
|
|
314
|
+
/let\s+([a-zA-Z_$][a-zA-Z0-9_$]*)\s*=\s*[a-zA-Z_$][a-zA-Z0-9_$]*\s*\(/,
|
|
315
|
+
// export var varName = anyFunction(
|
|
316
|
+
/export\s+var\s+([a-zA-Z_$][a-zA-Z0-9_$]*)\s*=\s*[a-zA-Z_$][a-zA-Z0-9_$]*\s*\(/,
|
|
317
|
+
// var varName = anyFunction(
|
|
318
|
+
/var\s+([a-zA-Z_$][a-zA-Z0-9_$]*)\s*=\s*[a-zA-Z_$][a-zA-Z0-9_$]*\s*\(/
|
|
319
|
+
];
|
|
320
|
+
for (const pattern of patterns) {
|
|
321
|
+
const match = trimmed.match(pattern);
|
|
322
|
+
if (match && match[1]) {
|
|
323
|
+
return match[1];
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
return void 0;
|
|
327
|
+
}
|
|
328
|
+
function cacheInference(key, value) {
|
|
329
|
+
if (inferenceCache.size >= MAX_CACHE_SIZE) {
|
|
330
|
+
const firstKey = inferenceCache.keys().next().value;
|
|
331
|
+
if (firstKey) {
|
|
332
|
+
inferenceCache.delete(firstKey);
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
inferenceCache.set(key, value);
|
|
336
|
+
}
|
|
337
|
+
function inferVariableNameFromCallStack() {
|
|
338
|
+
try {
|
|
339
|
+
const stack = captureStackTrace();
|
|
340
|
+
const callLocation = parseCallLocation(stack);
|
|
341
|
+
if (!callLocation) {
|
|
342
|
+
return void 0;
|
|
343
|
+
}
|
|
344
|
+
const cacheKey = `${callLocation.file}:${callLocation.line}`;
|
|
345
|
+
if (inferenceCache.has(cacheKey)) {
|
|
346
|
+
return inferenceCache.get(cacheKey);
|
|
347
|
+
}
|
|
348
|
+
const sourceLine = readSourceLine(callLocation.file, callLocation.line);
|
|
349
|
+
if (!sourceLine) {
|
|
350
|
+
return void 0;
|
|
351
|
+
}
|
|
352
|
+
const variableName = extractVariableName(sourceLine);
|
|
353
|
+
cacheInference(cacheKey, variableName);
|
|
354
|
+
return variableName;
|
|
355
|
+
} catch {
|
|
356
|
+
return void 0;
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
// src/functional.ts
|
|
361
|
+
var FACTORY_NAME_HINTS = /* @__PURE__ */ new Set([
|
|
362
|
+
"ctx",
|
|
363
|
+
"_ctx",
|
|
364
|
+
"context",
|
|
365
|
+
"tracecontext",
|
|
366
|
+
"tracectx"
|
|
367
|
+
]);
|
|
368
|
+
var TRACE_FACTORY_SET = /* @__PURE__ */ new WeakSet();
|
|
369
|
+
var SINGLE_LINE_COMMENT_REGEX = /\/\/.*$/gm;
|
|
370
|
+
var MULTI_LINE_COMMENT_REGEX = /\/\*[\s\S]*?\*\//gm;
|
|
371
|
+
var PARAM_TOKEN_SANITIZE_REGEX = new RegExp(String.raw`[{}\[\]\s]`, "g");
|
|
372
|
+
function markAsTraceFactory(fn) {
|
|
373
|
+
TRACE_FACTORY_SET.add(fn);
|
|
374
|
+
}
|
|
375
|
+
function hasFactoryMark(fn) {
|
|
376
|
+
return TRACE_FACTORY_SET.has(fn);
|
|
377
|
+
}
|
|
378
|
+
function sanitizeParameterToken(token) {
|
|
379
|
+
const [firstToken] = token.split("=");
|
|
380
|
+
return (firstToken ?? "").replaceAll(PARAM_TOKEN_SANITIZE_REGEX, "").trim();
|
|
381
|
+
}
|
|
382
|
+
function getFirstParameterToken(fn) {
|
|
383
|
+
let source = Function.prototype.toString.call(fn);
|
|
384
|
+
source = source.replaceAll(MULTI_LINE_COMMENT_REGEX, "").replaceAll(SINGLE_LINE_COMMENT_REGEX, "").trim();
|
|
385
|
+
const arrowMatch = source.match(
|
|
386
|
+
/^(?:async\s*)?(?:\(([^)]*)\)|([^=()]+))\s*=>/
|
|
387
|
+
);
|
|
388
|
+
if (arrowMatch) {
|
|
389
|
+
const params = (arrowMatch[1] ?? arrowMatch[2] ?? "").split(",");
|
|
390
|
+
const first = params[0]?.trim();
|
|
391
|
+
if (first) {
|
|
392
|
+
return sanitizeParameterToken(first);
|
|
393
|
+
}
|
|
394
|
+
return null;
|
|
395
|
+
}
|
|
396
|
+
const functionMatch = source.match(/^[^(]*\(([^)]*)\)/);
|
|
397
|
+
if (functionMatch) {
|
|
398
|
+
const params = functionMatch[1]?.split(",");
|
|
399
|
+
const first = params?.[0]?.trim();
|
|
400
|
+
if (first) {
|
|
401
|
+
return sanitizeParameterToken(first);
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
return null;
|
|
405
|
+
}
|
|
406
|
+
function looksLikeTraceFactory(fn) {
|
|
407
|
+
if (hasFactoryMark(fn)) {
|
|
408
|
+
return true;
|
|
409
|
+
}
|
|
410
|
+
if (fn.length === 0) {
|
|
411
|
+
return false;
|
|
412
|
+
}
|
|
413
|
+
const firstParam = getFirstParameterToken(fn);
|
|
414
|
+
if (!firstParam) {
|
|
415
|
+
return false;
|
|
416
|
+
}
|
|
417
|
+
const normalized = firstParam.toLowerCase();
|
|
418
|
+
if (FACTORY_NAME_HINTS.has(normalized) || normalized.startsWith("ctx") || normalized.startsWith("_ctx") || normalized.startsWith("trace")) {
|
|
419
|
+
return true;
|
|
420
|
+
}
|
|
421
|
+
return false;
|
|
422
|
+
}
|
|
423
|
+
function isFactoryReturningFunction(fnWithCtx) {
|
|
424
|
+
try {
|
|
425
|
+
const result = fnWithCtx(createDummyCtx());
|
|
426
|
+
return typeof result === "function";
|
|
427
|
+
} catch {
|
|
428
|
+
return false;
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
function isTraceFactoryFunction(fn) {
|
|
432
|
+
if (typeof fn !== "function") {
|
|
433
|
+
return false;
|
|
434
|
+
}
|
|
435
|
+
if (hasFactoryMark(fn)) {
|
|
436
|
+
return true;
|
|
437
|
+
}
|
|
438
|
+
if (looksLikeTraceFactory(fn)) {
|
|
439
|
+
markAsTraceFactory(fn);
|
|
440
|
+
return true;
|
|
441
|
+
}
|
|
442
|
+
return false;
|
|
443
|
+
}
|
|
444
|
+
function ensureTraceFactory(fnOrFactory) {
|
|
445
|
+
if (isTraceFactoryFunction(fnOrFactory)) {
|
|
446
|
+
return fnOrFactory;
|
|
447
|
+
}
|
|
448
|
+
const plainFn = fnOrFactory;
|
|
449
|
+
const factory = (ctx2) => {
|
|
450
|
+
return plainFn;
|
|
451
|
+
};
|
|
452
|
+
markAsTraceFactory(factory);
|
|
453
|
+
return factory;
|
|
454
|
+
}
|
|
455
|
+
function wrapFactoryWithTracing(fnOrFactory, options, variableName) {
|
|
456
|
+
const factory = ensureTraceFactory(fnOrFactory);
|
|
457
|
+
const sampleFn = factory(createDummyCtx());
|
|
458
|
+
const innerFunctionName = inferFunctionName(
|
|
459
|
+
sampleFn
|
|
460
|
+
);
|
|
461
|
+
const callStackVariableName = innerFunctionName ? void 0 : inferVariableNameFromCallStack();
|
|
462
|
+
const factoryName = inferFunctionName(factory);
|
|
463
|
+
const effectiveVariableName = variableName || innerFunctionName || callStackVariableName || factoryName;
|
|
464
|
+
const useAsyncWrapper = isAsyncFunction(sampleFn);
|
|
465
|
+
if (useAsyncWrapper) {
|
|
466
|
+
return wrapWithTracing(
|
|
467
|
+
factory,
|
|
468
|
+
options,
|
|
469
|
+
effectiveVariableName
|
|
470
|
+
);
|
|
471
|
+
}
|
|
472
|
+
return wrapWithTracingSync(
|
|
473
|
+
factory,
|
|
474
|
+
options,
|
|
475
|
+
effectiveVariableName
|
|
476
|
+
);
|
|
477
|
+
}
|
|
478
|
+
var MAX_ERROR_MESSAGE_LENGTH = 500;
|
|
479
|
+
function createDummyCtx() {
|
|
480
|
+
return {
|
|
481
|
+
traceId: "",
|
|
482
|
+
spanId: "",
|
|
483
|
+
correlationId: "",
|
|
484
|
+
setAttribute: () => {
|
|
485
|
+
},
|
|
486
|
+
setAttributes: () => {
|
|
487
|
+
},
|
|
488
|
+
setStatus: () => {
|
|
489
|
+
},
|
|
490
|
+
recordException: () => {
|
|
491
|
+
},
|
|
492
|
+
getBaggage: () => {
|
|
493
|
+
},
|
|
494
|
+
setBaggage: () => "",
|
|
495
|
+
deleteBaggage: () => {
|
|
496
|
+
},
|
|
497
|
+
getAllBaggage: () => /* @__PURE__ */ new Map()
|
|
498
|
+
};
|
|
499
|
+
}
|
|
500
|
+
function isAsyncFunction(fn) {
|
|
501
|
+
return typeof fn === "function" && fn.constructor?.name === "AsyncFunction";
|
|
502
|
+
}
|
|
503
|
+
var INSTRUMENTED_SYMBOL = Symbol.for("autotel.functional.instrumented");
|
|
504
|
+
function hasInstrumentationFlag(value) {
|
|
505
|
+
return (typeof value === "function" || typeof value === "object") && value !== null && Boolean(value[INSTRUMENTED_SYMBOL]);
|
|
506
|
+
}
|
|
507
|
+
function truncateErrorMessage(message) {
|
|
508
|
+
if (message.length <= MAX_ERROR_MESSAGE_LENGTH) {
|
|
509
|
+
return message;
|
|
510
|
+
}
|
|
511
|
+
return `${message.slice(0, MAX_ERROR_MESSAGE_LENGTH)}... (truncated)`;
|
|
512
|
+
}
|
|
513
|
+
function inferFunctionName(fn) {
|
|
514
|
+
const displayName = fn.displayName;
|
|
515
|
+
if (displayName) {
|
|
516
|
+
return displayName;
|
|
517
|
+
}
|
|
518
|
+
if (fn.name && fn.name !== "anonymous" && fn.name !== "") {
|
|
519
|
+
return fn.name;
|
|
520
|
+
}
|
|
521
|
+
const source = Function.prototype.toString.call(fn);
|
|
522
|
+
const match = source.match(/function\s+([^(\s]+)/);
|
|
523
|
+
if (match && match[1] && match[1] !== "anonymous") {
|
|
524
|
+
return match[1];
|
|
525
|
+
}
|
|
526
|
+
return void 0;
|
|
527
|
+
}
|
|
528
|
+
function getSpanName(options, fn, variableName) {
|
|
529
|
+
if (options.name) {
|
|
530
|
+
return options.name;
|
|
531
|
+
}
|
|
532
|
+
let fnName = variableName || inferFunctionName(fn);
|
|
533
|
+
fnName = fnName || "anonymous";
|
|
534
|
+
if (options.serviceName) {
|
|
535
|
+
return `${options.serviceName}.${fnName}`;
|
|
536
|
+
}
|
|
537
|
+
if (fnName && fnName !== "anonymous") {
|
|
538
|
+
return fnName;
|
|
539
|
+
}
|
|
540
|
+
return "unknown";
|
|
541
|
+
}
|
|
542
|
+
function shouldSkip(key, fn, skip) {
|
|
543
|
+
if (key.startsWith("_")) {
|
|
544
|
+
return true;
|
|
545
|
+
}
|
|
546
|
+
if (!skip || skip.length === 0) {
|
|
547
|
+
return false;
|
|
548
|
+
}
|
|
549
|
+
for (const rule of skip) {
|
|
550
|
+
if (typeof rule === "string" && key === rule) {
|
|
551
|
+
return true;
|
|
552
|
+
} else if (rule instanceof RegExp && rule.test(key)) {
|
|
553
|
+
return true;
|
|
554
|
+
} else if (typeof rule === "function" && rule(key, fn)) {
|
|
555
|
+
return true;
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
return false;
|
|
559
|
+
}
|
|
560
|
+
function getCtxValue() {
|
|
561
|
+
const activeSpan = trace.getActiveSpan();
|
|
562
|
+
if (!activeSpan) return null;
|
|
563
|
+
return createTraceContext(activeSpan);
|
|
564
|
+
}
|
|
565
|
+
var ctx = new Proxy({}, {
|
|
566
|
+
get(_target, prop) {
|
|
567
|
+
const ctxValue = getCtxValue();
|
|
568
|
+
if (!ctxValue) {
|
|
569
|
+
return;
|
|
570
|
+
}
|
|
571
|
+
return ctxValue[prop];
|
|
572
|
+
},
|
|
573
|
+
has(_target, prop) {
|
|
574
|
+
const ctxValue = getCtxValue();
|
|
575
|
+
if (!ctxValue) {
|
|
576
|
+
return false;
|
|
577
|
+
}
|
|
578
|
+
return prop in ctxValue;
|
|
579
|
+
},
|
|
580
|
+
ownKeys() {
|
|
581
|
+
const ctxValue = getCtxValue();
|
|
582
|
+
if (!ctxValue) {
|
|
583
|
+
return [];
|
|
584
|
+
}
|
|
585
|
+
return Object.keys(ctxValue);
|
|
586
|
+
},
|
|
587
|
+
getOwnPropertyDescriptor(_target, prop) {
|
|
588
|
+
const ctxValue = getCtxValue();
|
|
589
|
+
if (!ctxValue) {
|
|
590
|
+
return;
|
|
591
|
+
}
|
|
592
|
+
return Object.getOwnPropertyDescriptor(ctxValue, prop);
|
|
593
|
+
}
|
|
594
|
+
});
|
|
595
|
+
function wrapWithTracing(fnFactory, options, variableName) {
|
|
596
|
+
if (hasInstrumentationFlag(fnFactory)) ;
|
|
597
|
+
const config = getConfig();
|
|
598
|
+
const tracer = config.tracer;
|
|
599
|
+
const meter = config.meter;
|
|
600
|
+
const sampler = options.sampler || new AlwaysSampler();
|
|
601
|
+
const tempFn = fnFactory(createDummyCtx());
|
|
602
|
+
const spanName = getSpanName(options, tempFn, variableName);
|
|
603
|
+
const callCounter = options.withMetrics ? meter.createCounter(`${spanName}.calls`, {
|
|
604
|
+
description: `Call count for ${spanName}`,
|
|
605
|
+
unit: "1"
|
|
606
|
+
}) : void 0;
|
|
607
|
+
const durationHistogram = options.withMetrics ? meter.createHistogram(`${spanName}.duration`, {
|
|
608
|
+
description: `Duration for ${spanName}`,
|
|
609
|
+
unit: "ms"
|
|
610
|
+
}) : void 0;
|
|
611
|
+
const wrappedFunction = async function wrappedFunction2(...args) {
|
|
612
|
+
const samplingContext = {
|
|
613
|
+
operationName: spanName,
|
|
614
|
+
args,
|
|
615
|
+
metadata: {}
|
|
616
|
+
};
|
|
617
|
+
const shouldSample = sampler.shouldSample(samplingContext);
|
|
618
|
+
const needsTailSampling = "needsTailSampling" in sampler && typeof sampler.needsTailSampling === "function" ? sampler.needsTailSampling() : false;
|
|
619
|
+
if (!shouldSample && !needsTailSampling) {
|
|
620
|
+
const fn = fnFactory(createDummyCtx());
|
|
621
|
+
return await fn.call(this, ...args);
|
|
622
|
+
}
|
|
623
|
+
const startTime = performance.now();
|
|
624
|
+
const isRootSpan = options.startNewRoot || trace.getActiveSpan() === void 0;
|
|
625
|
+
const shouldAutoFlush = options.autoFlushEvents ?? getConfig$1()?.autoFlushEvents ?? true;
|
|
626
|
+
const shouldAutoFlushSpans = getConfig$1()?.autoFlush ?? false;
|
|
627
|
+
const flushIfNeeded = async () => {
|
|
628
|
+
if (!shouldAutoFlush || !isRootSpan) return;
|
|
629
|
+
try {
|
|
630
|
+
const queue = getEventQueue();
|
|
631
|
+
if (queue && queue.size() > 0) {
|
|
632
|
+
await queue.flush();
|
|
633
|
+
}
|
|
634
|
+
if (shouldAutoFlushSpans) {
|
|
635
|
+
const sdk = getSdk();
|
|
636
|
+
if (sdk) {
|
|
637
|
+
try {
|
|
638
|
+
const sdkAny = sdk;
|
|
639
|
+
if (typeof sdkAny.getTracerProvider === "function") {
|
|
640
|
+
const tracerProvider = sdkAny.getTracerProvider();
|
|
641
|
+
if (tracerProvider && typeof tracerProvider.forceFlush === "function") {
|
|
642
|
+
await tracerProvider.forceFlush();
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
} catch {
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
} catch (error) {
|
|
650
|
+
const initConfig = getConfig$1();
|
|
651
|
+
const logger = initConfig?.logger;
|
|
652
|
+
if (logger?.error) {
|
|
653
|
+
if (error instanceof Error) {
|
|
654
|
+
logger.error("[autotel] Auto-flush failed", error);
|
|
655
|
+
} else {
|
|
656
|
+
logger.error(`[autotel] Auto-flush failed: ${String(error)}`);
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
};
|
|
661
|
+
return tracer.startActiveSpan(
|
|
662
|
+
spanName,
|
|
663
|
+
options.startNewRoot ? { root: true } : {},
|
|
664
|
+
async (span2) => {
|
|
665
|
+
return runInOperationContext(spanName, async () => {
|
|
666
|
+
let shouldKeepSpan = true;
|
|
667
|
+
setSpanName(span2, spanName);
|
|
668
|
+
const initialContext = context.active();
|
|
669
|
+
const contextStorage = getContextStorage();
|
|
670
|
+
if (!contextStorage.getStore()) {
|
|
671
|
+
contextStorage.enterWith(initialContext);
|
|
672
|
+
}
|
|
673
|
+
const ctxValue = createTraceContext(span2);
|
|
674
|
+
const fn = fnFactory(ctxValue);
|
|
675
|
+
const argsAttributes = options.attributesFromArgs ? options.attributesFromArgs(args) : {};
|
|
676
|
+
const handleTailSampling = (success, duration, error) => {
|
|
677
|
+
if (needsTailSampling && "shouldKeepTrace" in sampler && typeof sampler.shouldKeepTrace === "function") {
|
|
678
|
+
shouldKeepSpan = sampler.shouldKeepTrace(samplingContext, {
|
|
679
|
+
success,
|
|
680
|
+
duration,
|
|
681
|
+
error
|
|
682
|
+
});
|
|
683
|
+
span2.setAttribute("sampling.tail.keep", shouldKeepSpan);
|
|
684
|
+
span2.setAttribute("sampling.tail.evaluated", true);
|
|
685
|
+
}
|
|
686
|
+
};
|
|
687
|
+
const onSuccess = async (result) => {
|
|
688
|
+
const duration = performance.now() - startTime;
|
|
689
|
+
callCounter?.add(1, {
|
|
690
|
+
operation: spanName,
|
|
691
|
+
status: "success"
|
|
692
|
+
});
|
|
693
|
+
durationHistogram?.record(duration, {
|
|
694
|
+
operation: spanName,
|
|
695
|
+
status: "success"
|
|
696
|
+
});
|
|
697
|
+
const resultAttributes = options.attributesFromResult ? options.attributesFromResult(result) : {};
|
|
698
|
+
span2.setStatus({ code: SpanStatusCode.OK });
|
|
699
|
+
span2.setAttributes({
|
|
700
|
+
...argsAttributes,
|
|
701
|
+
...resultAttributes,
|
|
702
|
+
"operation.name": spanName,
|
|
703
|
+
"code.function": spanName,
|
|
704
|
+
"operation.duration": duration,
|
|
705
|
+
"operation.success": true
|
|
706
|
+
});
|
|
707
|
+
handleTailSampling(true, duration);
|
|
708
|
+
span2.end();
|
|
709
|
+
await flushIfNeeded();
|
|
710
|
+
return result;
|
|
711
|
+
};
|
|
712
|
+
const onError = async (error) => {
|
|
713
|
+
const duration = performance.now() - startTime;
|
|
714
|
+
callCounter?.add(1, {
|
|
715
|
+
operation: spanName,
|
|
716
|
+
status: "error"
|
|
717
|
+
});
|
|
718
|
+
durationHistogram?.record(duration, {
|
|
719
|
+
operation: spanName,
|
|
720
|
+
status: "error"
|
|
721
|
+
});
|
|
722
|
+
const errorMessage = error instanceof Error ? error.message : "Unknown error";
|
|
723
|
+
const truncatedMessage = truncateErrorMessage(errorMessage);
|
|
724
|
+
span2.setStatus({
|
|
725
|
+
code: SpanStatusCode.ERROR,
|
|
726
|
+
message: truncatedMessage
|
|
727
|
+
});
|
|
728
|
+
span2.setAttributes({
|
|
729
|
+
...argsAttributes,
|
|
730
|
+
"operation.name": spanName,
|
|
731
|
+
"code.function": spanName,
|
|
732
|
+
"operation.duration": duration,
|
|
733
|
+
"operation.success": false,
|
|
734
|
+
error: true,
|
|
735
|
+
"exception.type": error instanceof Error ? error.constructor.name : "Error",
|
|
736
|
+
"exception.message": truncatedMessage
|
|
737
|
+
});
|
|
738
|
+
if (error instanceof Error && error.stack) {
|
|
739
|
+
span2.setAttribute(
|
|
740
|
+
"exception.stack",
|
|
741
|
+
error.stack.slice(0, MAX_ERROR_MESSAGE_LENGTH)
|
|
742
|
+
);
|
|
743
|
+
}
|
|
744
|
+
span2.recordException(
|
|
745
|
+
error instanceof Error ? error : new Error(String(error))
|
|
746
|
+
);
|
|
747
|
+
handleTailSampling(false, duration, error);
|
|
748
|
+
span2.end();
|
|
749
|
+
await flushIfNeeded();
|
|
750
|
+
throw error;
|
|
751
|
+
};
|
|
752
|
+
try {
|
|
753
|
+
callCounter?.add(1, {
|
|
754
|
+
operation: spanName,
|
|
755
|
+
status: "started"
|
|
756
|
+
});
|
|
757
|
+
const executeWithContext = async () => {
|
|
758
|
+
const currentContext = getActiveContextWithBaggage();
|
|
759
|
+
return context.with(currentContext, async () => {
|
|
760
|
+
return fn.call(this, ...args);
|
|
761
|
+
});
|
|
762
|
+
};
|
|
763
|
+
const result = await executeWithContext();
|
|
764
|
+
return await onSuccess(result);
|
|
765
|
+
} catch (error) {
|
|
766
|
+
await onError(error);
|
|
767
|
+
throw error;
|
|
768
|
+
}
|
|
769
|
+
});
|
|
770
|
+
}
|
|
771
|
+
);
|
|
772
|
+
};
|
|
773
|
+
wrappedFunction[INSTRUMENTED_SYMBOL] = true;
|
|
774
|
+
Object.defineProperty(wrappedFunction, "name", {
|
|
775
|
+
value: tempFn.name || "trace",
|
|
776
|
+
configurable: true
|
|
777
|
+
});
|
|
778
|
+
return wrappedFunction;
|
|
779
|
+
}
|
|
780
|
+
function wrapWithTracingSync(fnFactory, options, variableName) {
|
|
781
|
+
if (hasInstrumentationFlag(fnFactory)) ;
|
|
782
|
+
const config = getConfig();
|
|
783
|
+
const tracer = config.tracer;
|
|
784
|
+
const meter = config.meter;
|
|
785
|
+
const sampler = options.sampler || new AlwaysSampler();
|
|
786
|
+
const tempFn = fnFactory(createDummyCtx());
|
|
787
|
+
const spanName = getSpanName(options, tempFn, variableName);
|
|
788
|
+
const callCounter = options.withMetrics ? meter.createCounter(`${spanName}.calls`, {
|
|
789
|
+
description: `Call count for ${spanName}`,
|
|
790
|
+
unit: "1"
|
|
791
|
+
}) : void 0;
|
|
792
|
+
const durationHistogram = options.withMetrics ? meter.createHistogram(`${spanName}.duration`, {
|
|
793
|
+
description: `Duration for ${spanName}`,
|
|
794
|
+
unit: "ms"
|
|
795
|
+
}) : void 0;
|
|
796
|
+
function wrappedFunction(...args) {
|
|
797
|
+
const samplingContext = {
|
|
798
|
+
operationName: spanName,
|
|
799
|
+
args,
|
|
800
|
+
metadata: {}
|
|
801
|
+
};
|
|
802
|
+
const shouldSample = sampler.shouldSample(samplingContext);
|
|
803
|
+
const needsTailSampling = "needsTailSampling" in sampler && typeof sampler.needsTailSampling === "function" ? sampler.needsTailSampling() : false;
|
|
804
|
+
if (!shouldSample && !needsTailSampling) {
|
|
805
|
+
const fn = fnFactory(createDummyCtx());
|
|
806
|
+
return fn.call(this, ...args);
|
|
807
|
+
}
|
|
808
|
+
const startTime = performance.now();
|
|
809
|
+
const isRootSpan = options.startNewRoot || trace.getActiveSpan() === void 0;
|
|
810
|
+
const shouldAutoFlush = options.autoFlushEvents ?? getConfig$1()?.autoFlushEvents ?? true;
|
|
811
|
+
const shouldAutoFlushSpans = getConfig$1()?.autoFlush ?? false;
|
|
812
|
+
const flushIfNeeded = () => {
|
|
813
|
+
if (!shouldAutoFlush || !isRootSpan) return;
|
|
814
|
+
const queue = getEventQueue();
|
|
815
|
+
if (queue && queue.size() > 0) {
|
|
816
|
+
void queue.flush().catch((error) => {
|
|
817
|
+
const initConfig = getConfig$1();
|
|
818
|
+
const logger = initConfig?.logger;
|
|
819
|
+
if (logger?.error) {
|
|
820
|
+
if (error instanceof Error) {
|
|
821
|
+
logger.error("[autotel] Auto-flush failed", error);
|
|
822
|
+
} else {
|
|
823
|
+
logger.error(`[autotel] Auto-flush failed: ${String(error)}`);
|
|
824
|
+
}
|
|
825
|
+
}
|
|
826
|
+
});
|
|
827
|
+
}
|
|
828
|
+
if (shouldAutoFlushSpans) {
|
|
829
|
+
const sdk = getSdk();
|
|
830
|
+
if (sdk) {
|
|
831
|
+
try {
|
|
832
|
+
const sdkAny = sdk;
|
|
833
|
+
if (typeof sdkAny.getTracerProvider === "function") {
|
|
834
|
+
const tracerProvider = sdkAny.getTracerProvider();
|
|
835
|
+
if (tracerProvider && typeof tracerProvider.forceFlush === "function") {
|
|
836
|
+
void tracerProvider.forceFlush().catch((error) => {
|
|
837
|
+
const initConfig = getConfig$1();
|
|
838
|
+
const logger = initConfig?.logger;
|
|
839
|
+
if (logger?.error) {
|
|
840
|
+
if (error instanceof Error) {
|
|
841
|
+
logger.error("[autotel] Span flush failed", error);
|
|
842
|
+
} else {
|
|
843
|
+
logger.error(
|
|
844
|
+
`[autotel] Span flush failed: ${String(error)}`
|
|
845
|
+
);
|
|
846
|
+
}
|
|
847
|
+
}
|
|
848
|
+
});
|
|
849
|
+
}
|
|
850
|
+
}
|
|
851
|
+
} catch {
|
|
852
|
+
}
|
|
853
|
+
}
|
|
854
|
+
}
|
|
855
|
+
};
|
|
856
|
+
return tracer.startActiveSpan(
|
|
857
|
+
spanName,
|
|
858
|
+
options.startNewRoot ? { root: true } : {},
|
|
859
|
+
(span2) => {
|
|
860
|
+
return runInOperationContext(spanName, () => {
|
|
861
|
+
let shouldKeepSpan = true;
|
|
862
|
+
setSpanName(span2, spanName);
|
|
863
|
+
const ctxValue = createTraceContext(span2);
|
|
864
|
+
const fn = fnFactory(ctxValue);
|
|
865
|
+
const argsAttributes = options.attributesFromArgs ? options.attributesFromArgs(args) : {};
|
|
866
|
+
const handleTailSampling = (success, duration, error) => {
|
|
867
|
+
if (needsTailSampling && "shouldKeepTrace" in sampler && typeof sampler.shouldKeepTrace === "function") {
|
|
868
|
+
shouldKeepSpan = sampler.shouldKeepTrace(samplingContext, {
|
|
869
|
+
success,
|
|
870
|
+
duration,
|
|
871
|
+
error
|
|
872
|
+
});
|
|
873
|
+
span2.setAttribute("sampling.tail.keep", shouldKeepSpan);
|
|
874
|
+
span2.setAttribute("sampling.tail.evaluated", true);
|
|
875
|
+
}
|
|
876
|
+
};
|
|
877
|
+
const onSuccess = (result) => {
|
|
878
|
+
const duration = performance.now() - startTime;
|
|
879
|
+
callCounter?.add(1, {
|
|
880
|
+
operation: spanName,
|
|
881
|
+
status: "success"
|
|
882
|
+
});
|
|
883
|
+
durationHistogram?.record(duration, {
|
|
884
|
+
operation: spanName,
|
|
885
|
+
status: "success"
|
|
886
|
+
});
|
|
887
|
+
const resultAttributes = options.attributesFromResult ? options.attributesFromResult(result) : {};
|
|
888
|
+
span2.setStatus({ code: SpanStatusCode.OK });
|
|
889
|
+
span2.setAttributes({
|
|
890
|
+
...argsAttributes,
|
|
891
|
+
...resultAttributes,
|
|
892
|
+
"operation.name": spanName,
|
|
893
|
+
"code.function": spanName,
|
|
894
|
+
"operation.duration": duration,
|
|
895
|
+
"operation.success": true
|
|
896
|
+
});
|
|
897
|
+
handleTailSampling(true, duration);
|
|
898
|
+
span2.end();
|
|
899
|
+
void flushIfNeeded();
|
|
900
|
+
return result;
|
|
901
|
+
};
|
|
902
|
+
const onError = (error) => {
|
|
903
|
+
const duration = performance.now() - startTime;
|
|
904
|
+
callCounter?.add(1, {
|
|
905
|
+
operation: spanName,
|
|
906
|
+
status: "error"
|
|
907
|
+
});
|
|
908
|
+
durationHistogram?.record(duration, {
|
|
909
|
+
operation: spanName,
|
|
910
|
+
status: "error"
|
|
911
|
+
});
|
|
912
|
+
const errorMessage = error instanceof Error ? error.message : "Unknown error";
|
|
913
|
+
const truncatedMessage = truncateErrorMessage(errorMessage);
|
|
914
|
+
span2.setStatus({
|
|
915
|
+
code: SpanStatusCode.ERROR,
|
|
916
|
+
message: truncatedMessage
|
|
917
|
+
});
|
|
918
|
+
span2.setAttributes({
|
|
919
|
+
...argsAttributes,
|
|
920
|
+
"operation.name": spanName,
|
|
921
|
+
"code.function": spanName,
|
|
922
|
+
"operation.duration": duration,
|
|
923
|
+
"operation.success": false,
|
|
924
|
+
error: true,
|
|
925
|
+
"exception.type": error instanceof Error ? error.constructor.name : "Error",
|
|
926
|
+
"exception.message": truncatedMessage
|
|
927
|
+
});
|
|
928
|
+
span2.recordException(
|
|
929
|
+
error instanceof Error ? error : new Error(String(error))
|
|
930
|
+
);
|
|
931
|
+
handleTailSampling(false, duration, error);
|
|
932
|
+
span2.end();
|
|
933
|
+
void flushIfNeeded();
|
|
934
|
+
throw error;
|
|
935
|
+
};
|
|
936
|
+
try {
|
|
937
|
+
callCounter?.add(1, {
|
|
938
|
+
operation: spanName,
|
|
939
|
+
status: "started"
|
|
940
|
+
});
|
|
941
|
+
const result = fn.call(this, ...args);
|
|
942
|
+
if (result instanceof Promise) {
|
|
943
|
+
return result.then(onSuccess, onError);
|
|
944
|
+
}
|
|
945
|
+
return onSuccess(result);
|
|
946
|
+
} catch (error) {
|
|
947
|
+
return onError(error);
|
|
948
|
+
}
|
|
949
|
+
});
|
|
950
|
+
}
|
|
951
|
+
);
|
|
952
|
+
}
|
|
953
|
+
wrappedFunction[INSTRUMENTED_SYMBOL] = true;
|
|
954
|
+
Object.defineProperty(wrappedFunction, "name", {
|
|
955
|
+
value: tempFn.name || "trace",
|
|
956
|
+
configurable: true
|
|
957
|
+
});
|
|
958
|
+
return wrappedFunction;
|
|
959
|
+
}
|
|
960
|
+
function executeImmediately(fn, options) {
|
|
961
|
+
const config = getConfig();
|
|
962
|
+
const tracer = config.tracer;
|
|
963
|
+
const meter = config.meter;
|
|
964
|
+
const sampler = options.sampler || new AlwaysSampler();
|
|
965
|
+
const spanName = options.name || "anonymous";
|
|
966
|
+
const samplingContext = {
|
|
967
|
+
operationName: spanName,
|
|
968
|
+
args: [],
|
|
969
|
+
metadata: {}
|
|
970
|
+
};
|
|
971
|
+
const shouldSample = sampler.shouldSample(samplingContext);
|
|
972
|
+
const needsTailSampling = "needsTailSampling" in sampler && typeof sampler.needsTailSampling === "function" ? sampler.needsTailSampling() : false;
|
|
973
|
+
if (!shouldSample && !needsTailSampling) {
|
|
974
|
+
return fn(createDummyCtx());
|
|
975
|
+
}
|
|
976
|
+
const startTime = performance.now();
|
|
977
|
+
const isRootSpan = options.startNewRoot || trace.getActiveSpan() === void 0;
|
|
978
|
+
const shouldAutoFlush = options.autoFlushEvents ?? getConfig$1()?.autoFlushEvents ?? true;
|
|
979
|
+
const shouldAutoFlushSpans = getConfig$1()?.autoFlush ?? false;
|
|
980
|
+
const callCounter = options.withMetrics ? meter.createCounter(`${spanName}.calls`, {
|
|
981
|
+
description: `Call count for ${spanName}`,
|
|
982
|
+
unit: "1"
|
|
983
|
+
}) : void 0;
|
|
984
|
+
const durationHistogram = options.withMetrics ? meter.createHistogram(`${spanName}.duration`, {
|
|
985
|
+
description: `Duration for ${spanName}`,
|
|
986
|
+
unit: "ms"
|
|
987
|
+
}) : void 0;
|
|
988
|
+
const flushIfNeeded = async () => {
|
|
989
|
+
if (!shouldAutoFlush || !isRootSpan) return;
|
|
990
|
+
try {
|
|
991
|
+
const queue = getEventQueue();
|
|
992
|
+
if (queue && queue.size() > 0) {
|
|
993
|
+
await queue.flush();
|
|
994
|
+
}
|
|
995
|
+
if (shouldAutoFlushSpans) {
|
|
996
|
+
const sdk = getSdk();
|
|
997
|
+
if (sdk) {
|
|
998
|
+
try {
|
|
999
|
+
const sdkAny = sdk;
|
|
1000
|
+
if (typeof sdkAny.getTracerProvider === "function") {
|
|
1001
|
+
const tracerProvider = sdkAny.getTracerProvider();
|
|
1002
|
+
if (tracerProvider && typeof tracerProvider.forceFlush === "function") {
|
|
1003
|
+
await tracerProvider.forceFlush();
|
|
1004
|
+
}
|
|
1005
|
+
}
|
|
1006
|
+
} catch {
|
|
1007
|
+
}
|
|
1008
|
+
}
|
|
1009
|
+
}
|
|
1010
|
+
} catch (error) {
|
|
1011
|
+
const initConfig = getConfig$1();
|
|
1012
|
+
const logger = initConfig?.logger;
|
|
1013
|
+
if (logger?.error) {
|
|
1014
|
+
if (error instanceof Error) {
|
|
1015
|
+
logger.error("[autotel] Auto-flush failed", error);
|
|
1016
|
+
} else {
|
|
1017
|
+
logger.error(`[autotel] Auto-flush failed: ${String(error)}`);
|
|
1018
|
+
}
|
|
1019
|
+
}
|
|
1020
|
+
}
|
|
1021
|
+
};
|
|
1022
|
+
return tracer.startActiveSpan(
|
|
1023
|
+
spanName,
|
|
1024
|
+
options.startNewRoot ? { root: true } : {},
|
|
1025
|
+
(span2) => {
|
|
1026
|
+
return runInOperationContext(spanName, () => {
|
|
1027
|
+
let shouldKeepSpan = true;
|
|
1028
|
+
setSpanName(span2, spanName);
|
|
1029
|
+
const ctxValue = createTraceContext(span2);
|
|
1030
|
+
const handleTailSampling = (success, duration, error) => {
|
|
1031
|
+
if (needsTailSampling && "shouldKeepTrace" in sampler && typeof sampler.shouldKeepTrace === "function") {
|
|
1032
|
+
shouldKeepSpan = sampler.shouldKeepTrace(samplingContext, {
|
|
1033
|
+
success,
|
|
1034
|
+
duration,
|
|
1035
|
+
error
|
|
1036
|
+
});
|
|
1037
|
+
span2.setAttribute("sampling.tail.keep", shouldKeepSpan);
|
|
1038
|
+
span2.setAttribute("sampling.tail.evaluated", true);
|
|
1039
|
+
}
|
|
1040
|
+
};
|
|
1041
|
+
const onSuccessSync = (result) => {
|
|
1042
|
+
const duration = performance.now() - startTime;
|
|
1043
|
+
callCounter?.add(1, {
|
|
1044
|
+
operation: spanName,
|
|
1045
|
+
status: "success"
|
|
1046
|
+
});
|
|
1047
|
+
durationHistogram?.record(duration, {
|
|
1048
|
+
operation: spanName,
|
|
1049
|
+
status: "success"
|
|
1050
|
+
});
|
|
1051
|
+
span2.setStatus({ code: SpanStatusCode.OK });
|
|
1052
|
+
span2.setAttributes({
|
|
1053
|
+
"operation.name": spanName,
|
|
1054
|
+
"code.function": spanName,
|
|
1055
|
+
"operation.duration": duration,
|
|
1056
|
+
"operation.success": true
|
|
1057
|
+
});
|
|
1058
|
+
handleTailSampling(true, duration);
|
|
1059
|
+
span2.end();
|
|
1060
|
+
void flushIfNeeded();
|
|
1061
|
+
return result;
|
|
1062
|
+
};
|
|
1063
|
+
const onErrorSync = (error) => {
|
|
1064
|
+
const duration = performance.now() - startTime;
|
|
1065
|
+
callCounter?.add(1, {
|
|
1066
|
+
operation: spanName,
|
|
1067
|
+
status: "error"
|
|
1068
|
+
});
|
|
1069
|
+
durationHistogram?.record(duration, {
|
|
1070
|
+
operation: spanName,
|
|
1071
|
+
status: "error"
|
|
1072
|
+
});
|
|
1073
|
+
const errorMessage = error instanceof Error ? error.message : "Unknown error";
|
|
1074
|
+
const truncatedMessage = truncateErrorMessage(errorMessage);
|
|
1075
|
+
span2.setStatus({
|
|
1076
|
+
code: SpanStatusCode.ERROR,
|
|
1077
|
+
message: truncatedMessage
|
|
1078
|
+
});
|
|
1079
|
+
span2.setAttributes({
|
|
1080
|
+
"operation.name": spanName,
|
|
1081
|
+
"code.function": spanName,
|
|
1082
|
+
"operation.duration": duration,
|
|
1083
|
+
"operation.success": false,
|
|
1084
|
+
error: true,
|
|
1085
|
+
"exception.type": error instanceof Error ? error.constructor.name : "Error",
|
|
1086
|
+
"exception.message": truncatedMessage
|
|
1087
|
+
});
|
|
1088
|
+
if (error instanceof Error && error.stack) {
|
|
1089
|
+
span2.setAttribute(
|
|
1090
|
+
"exception.stack",
|
|
1091
|
+
error.stack.slice(0, MAX_ERROR_MESSAGE_LENGTH)
|
|
1092
|
+
);
|
|
1093
|
+
}
|
|
1094
|
+
span2.recordException(
|
|
1095
|
+
error instanceof Error ? error : new Error(String(error))
|
|
1096
|
+
);
|
|
1097
|
+
handleTailSampling(false, duration, error);
|
|
1098
|
+
span2.end();
|
|
1099
|
+
void flushIfNeeded();
|
|
1100
|
+
throw error;
|
|
1101
|
+
};
|
|
1102
|
+
const onSuccessAsync = async (result) => {
|
|
1103
|
+
const duration = performance.now() - startTime;
|
|
1104
|
+
callCounter?.add(1, {
|
|
1105
|
+
operation: spanName,
|
|
1106
|
+
status: "success"
|
|
1107
|
+
});
|
|
1108
|
+
durationHistogram?.record(duration, {
|
|
1109
|
+
operation: spanName,
|
|
1110
|
+
status: "success"
|
|
1111
|
+
});
|
|
1112
|
+
span2.setStatus({ code: SpanStatusCode.OK });
|
|
1113
|
+
span2.setAttributes({
|
|
1114
|
+
"operation.name": spanName,
|
|
1115
|
+
"code.function": spanName,
|
|
1116
|
+
"operation.duration": duration,
|
|
1117
|
+
"operation.success": true
|
|
1118
|
+
});
|
|
1119
|
+
handleTailSampling(true, duration);
|
|
1120
|
+
span2.end();
|
|
1121
|
+
await flushIfNeeded();
|
|
1122
|
+
return result;
|
|
1123
|
+
};
|
|
1124
|
+
const onErrorAsync = async (error) => {
|
|
1125
|
+
const duration = performance.now() - startTime;
|
|
1126
|
+
callCounter?.add(1, {
|
|
1127
|
+
operation: spanName,
|
|
1128
|
+
status: "error"
|
|
1129
|
+
});
|
|
1130
|
+
durationHistogram?.record(duration, {
|
|
1131
|
+
operation: spanName,
|
|
1132
|
+
status: "error"
|
|
1133
|
+
});
|
|
1134
|
+
const errorMessage = error instanceof Error ? error.message : "Unknown error";
|
|
1135
|
+
const truncatedMessage = truncateErrorMessage(errorMessage);
|
|
1136
|
+
span2.setStatus({
|
|
1137
|
+
code: SpanStatusCode.ERROR,
|
|
1138
|
+
message: truncatedMessage
|
|
1139
|
+
});
|
|
1140
|
+
span2.setAttributes({
|
|
1141
|
+
"operation.name": spanName,
|
|
1142
|
+
"code.function": spanName,
|
|
1143
|
+
"operation.duration": duration,
|
|
1144
|
+
"operation.success": false,
|
|
1145
|
+
error: true,
|
|
1146
|
+
"exception.type": error instanceof Error ? error.constructor.name : "Error",
|
|
1147
|
+
"exception.message": truncatedMessage
|
|
1148
|
+
});
|
|
1149
|
+
if (error instanceof Error && error.stack) {
|
|
1150
|
+
span2.setAttribute(
|
|
1151
|
+
"exception.stack",
|
|
1152
|
+
error.stack.slice(0, MAX_ERROR_MESSAGE_LENGTH)
|
|
1153
|
+
);
|
|
1154
|
+
}
|
|
1155
|
+
span2.recordException(
|
|
1156
|
+
error instanceof Error ? error : new Error(String(error))
|
|
1157
|
+
);
|
|
1158
|
+
handleTailSampling(false, duration, error);
|
|
1159
|
+
span2.end();
|
|
1160
|
+
await flushIfNeeded();
|
|
1161
|
+
throw error;
|
|
1162
|
+
};
|
|
1163
|
+
try {
|
|
1164
|
+
callCounter?.add(1, {
|
|
1165
|
+
operation: spanName,
|
|
1166
|
+
status: "started"
|
|
1167
|
+
});
|
|
1168
|
+
const result = fn(ctxValue);
|
|
1169
|
+
if (result instanceof Promise) {
|
|
1170
|
+
return result.then(onSuccessAsync, onErrorAsync);
|
|
1171
|
+
}
|
|
1172
|
+
return onSuccessSync(result);
|
|
1173
|
+
} catch (error) {
|
|
1174
|
+
return onErrorSync(error);
|
|
1175
|
+
}
|
|
1176
|
+
});
|
|
1177
|
+
}
|
|
1178
|
+
);
|
|
1179
|
+
}
|
|
1180
|
+
function trace2(fnOrNameOrOptions, maybeFn) {
|
|
1181
|
+
if (typeof fnOrNameOrOptions === "function") {
|
|
1182
|
+
if (looksLikeTraceFactory(fnOrNameOrOptions) && !isFactoryReturningFunction(
|
|
1183
|
+
fnOrNameOrOptions
|
|
1184
|
+
)) {
|
|
1185
|
+
return executeImmediately(
|
|
1186
|
+
fnOrNameOrOptions,
|
|
1187
|
+
{}
|
|
1188
|
+
);
|
|
1189
|
+
}
|
|
1190
|
+
return wrapFactoryWithTracing(
|
|
1191
|
+
fnOrNameOrOptions,
|
|
1192
|
+
{}
|
|
1193
|
+
);
|
|
1194
|
+
}
|
|
1195
|
+
if (typeof fnOrNameOrOptions === "string") {
|
|
1196
|
+
if (!maybeFn) {
|
|
1197
|
+
throw new Error("trace(name, fn): fn is required");
|
|
1198
|
+
}
|
|
1199
|
+
if (looksLikeTraceFactory(maybeFn) && !isFactoryReturningFunction(maybeFn)) {
|
|
1200
|
+
return executeImmediately(
|
|
1201
|
+
maybeFn,
|
|
1202
|
+
{ name: fnOrNameOrOptions }
|
|
1203
|
+
);
|
|
1204
|
+
}
|
|
1205
|
+
return wrapFactoryWithTracing(
|
|
1206
|
+
maybeFn,
|
|
1207
|
+
{ name: fnOrNameOrOptions }
|
|
1208
|
+
);
|
|
1209
|
+
}
|
|
1210
|
+
if (!maybeFn) {
|
|
1211
|
+
throw new Error("trace(options, fn): fn is required");
|
|
1212
|
+
}
|
|
1213
|
+
if (looksLikeTraceFactory(maybeFn) && !isFactoryReturningFunction(maybeFn)) {
|
|
1214
|
+
return executeImmediately(
|
|
1215
|
+
maybeFn,
|
|
1216
|
+
fnOrNameOrOptions
|
|
1217
|
+
);
|
|
1218
|
+
}
|
|
1219
|
+
return wrapFactoryWithTracing(
|
|
1220
|
+
maybeFn,
|
|
1221
|
+
fnOrNameOrOptions
|
|
1222
|
+
);
|
|
1223
|
+
}
|
|
1224
|
+
function withTracing(options = {}) {
|
|
1225
|
+
return (fnFactory) => wrapFactoryWithTracing(fnFactory, options);
|
|
1226
|
+
}
|
|
1227
|
+
function instrument(options) {
|
|
1228
|
+
const { functions, ...tracingOptions } = options;
|
|
1229
|
+
const instrumented = {};
|
|
1230
|
+
for (const key of Object.keys(functions)) {
|
|
1231
|
+
const typedKey = key;
|
|
1232
|
+
const fn = functions[typedKey];
|
|
1233
|
+
if (!fn || typeof fn !== "function") {
|
|
1234
|
+
instrumented[typedKey] = fn;
|
|
1235
|
+
continue;
|
|
1236
|
+
}
|
|
1237
|
+
if (shouldSkip(key, fn, tracingOptions.skip)) {
|
|
1238
|
+
instrumented[typedKey] = fn;
|
|
1239
|
+
continue;
|
|
1240
|
+
}
|
|
1241
|
+
const fnOptions = {
|
|
1242
|
+
...tracingOptions,
|
|
1243
|
+
...tracingOptions.overrides?.[key],
|
|
1244
|
+
// If no explicit name, use key as function name
|
|
1245
|
+
name: tracingOptions.overrides?.[key]?.name
|
|
1246
|
+
};
|
|
1247
|
+
const boundFn = fn.bind(functions);
|
|
1248
|
+
const fnFactory = (ctx2) => {
|
|
1249
|
+
return boundFn;
|
|
1250
|
+
};
|
|
1251
|
+
instrumented[typedKey] = wrapFactoryWithTracing(
|
|
1252
|
+
fnFactory,
|
|
1253
|
+
fnOptions,
|
|
1254
|
+
key
|
|
1255
|
+
);
|
|
1256
|
+
}
|
|
1257
|
+
return instrumented;
|
|
1258
|
+
}
|
|
1259
|
+
function span(options, fn) {
|
|
1260
|
+
const config = getConfig();
|
|
1261
|
+
const tracer = config.tracer;
|
|
1262
|
+
const { name, attributes } = options;
|
|
1263
|
+
const executeSpan = (span2) => {
|
|
1264
|
+
return runInOperationContext(name, () => {
|
|
1265
|
+
try {
|
|
1266
|
+
if (attributes) {
|
|
1267
|
+
for (const [key, value] of Object.entries(attributes)) {
|
|
1268
|
+
span2.setAttribute(key, value);
|
|
1269
|
+
}
|
|
1270
|
+
}
|
|
1271
|
+
const result2 = fn(span2);
|
|
1272
|
+
if (result2 instanceof Promise) {
|
|
1273
|
+
return result2.then((resolved) => {
|
|
1274
|
+
span2.setStatus({ code: SpanStatusCode.OK });
|
|
1275
|
+
span2.end();
|
|
1276
|
+
return resolved;
|
|
1277
|
+
}).catch((error) => {
|
|
1278
|
+
const errorMessage = error instanceof Error ? error.message.slice(0, MAX_ERROR_MESSAGE_LENGTH) : String(error).slice(0, MAX_ERROR_MESSAGE_LENGTH);
|
|
1279
|
+
span2.setAttribute("error.message", errorMessage);
|
|
1280
|
+
span2.setStatus({
|
|
1281
|
+
code: SpanStatusCode.ERROR,
|
|
1282
|
+
message: errorMessage
|
|
1283
|
+
});
|
|
1284
|
+
span2.recordException(
|
|
1285
|
+
error instanceof Error ? error : new Error(String(error))
|
|
1286
|
+
);
|
|
1287
|
+
span2.end();
|
|
1288
|
+
throw error;
|
|
1289
|
+
});
|
|
1290
|
+
} else {
|
|
1291
|
+
span2.setStatus({ code: SpanStatusCode.OK });
|
|
1292
|
+
span2.end();
|
|
1293
|
+
return result2;
|
|
1294
|
+
}
|
|
1295
|
+
} catch (error) {
|
|
1296
|
+
const errorMessage = error instanceof Error ? error.message.slice(0, MAX_ERROR_MESSAGE_LENGTH) : String(error).slice(0, MAX_ERROR_MESSAGE_LENGTH);
|
|
1297
|
+
span2.setAttribute("error.message", errorMessage);
|
|
1298
|
+
span2.setStatus({
|
|
1299
|
+
code: SpanStatusCode.ERROR,
|
|
1300
|
+
message: errorMessage
|
|
1301
|
+
});
|
|
1302
|
+
span2.recordException(
|
|
1303
|
+
error instanceof Error ? error : new Error(String(error))
|
|
1304
|
+
);
|
|
1305
|
+
span2.end();
|
|
1306
|
+
throw error;
|
|
1307
|
+
}
|
|
1308
|
+
});
|
|
1309
|
+
};
|
|
1310
|
+
const result = tracer.startActiveSpan(name, executeSpan);
|
|
1311
|
+
if (result instanceof Promise) {
|
|
1312
|
+
return result;
|
|
1313
|
+
}
|
|
1314
|
+
return result;
|
|
1315
|
+
}
|
|
1316
|
+
async function withNewContext(options) {
|
|
1317
|
+
const { fn } = options;
|
|
1318
|
+
const config = getConfig();
|
|
1319
|
+
const tracer = config.tracer;
|
|
1320
|
+
return tracer.startActiveSpan("root", { root: true }, async (span2) => {
|
|
1321
|
+
try {
|
|
1322
|
+
const result = await fn();
|
|
1323
|
+
span2.setStatus({ code: SpanStatusCode.OK });
|
|
1324
|
+
return result;
|
|
1325
|
+
} catch (error) {
|
|
1326
|
+
span2.recordException(
|
|
1327
|
+
error instanceof Error ? error : new Error(String(error))
|
|
1328
|
+
);
|
|
1329
|
+
span2.setStatus({ code: SpanStatusCode.ERROR });
|
|
1330
|
+
throw error;
|
|
1331
|
+
} finally {
|
|
1332
|
+
span2.end();
|
|
1333
|
+
}
|
|
1334
|
+
});
|
|
1335
|
+
}
|
|
1336
|
+
function withBaggage(options) {
|
|
1337
|
+
const { baggage: baggageEntries, fn } = options;
|
|
1338
|
+
const currentContext = context.active();
|
|
1339
|
+
let updatedBaggage = propagation.getBaggage(currentContext) ?? propagation.createBaggage();
|
|
1340
|
+
for (const [key, value] of Object.entries(baggageEntries)) {
|
|
1341
|
+
updatedBaggage = updatedBaggage.setEntry(key, { value });
|
|
1342
|
+
}
|
|
1343
|
+
const newContext = propagation.setBaggage(currentContext, updatedBaggage);
|
|
1344
|
+
return context.with(newContext, fn);
|
|
1345
|
+
}
|
|
1346
|
+
|
|
1347
|
+
export { ctx, getEventQueue, instrument, resetEventQueue, span, trace2 as trace, track, withBaggage, withNewContext, withTracing };
|
|
1348
|
+
//# sourceMappingURL=chunk-RJYY7BWX.js.map
|
|
1349
|
+
//# sourceMappingURL=chunk-RJYY7BWX.js.map
|