tracebeam-sdk 0.1.1 → 0.2.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/dist/index.d.mts +11 -3
- package/dist/index.d.ts +11 -3
- package/dist/index.js +735 -377
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +722 -376
- package/dist/index.mjs.map +1 -1
- package/dist/integrations/express.d.mts +26 -2
- package/dist/integrations/express.d.ts +26 -2
- package/dist/integrations/express.js +30 -0
- package/dist/integrations/express.js.map +1 -1
- package/dist/integrations/express.mjs +29 -0
- package/dist/integrations/express.mjs.map +1 -1
- package/dist/integrations/fastify.d.mts +1 -1
- package/dist/integrations/fastify.d.ts +1 -1
- package/dist/integrations/fastify.js.map +1 -1
- package/dist/integrations/fastify.mjs.map +1 -1
- package/dist/{client-CaHega3m.d.mts → sdk-bh44OWR9.d.mts} +11 -80
- package/dist/{client-CaHega3m.d.ts → sdk-bh44OWR9.d.ts} +11 -80
- package/package.json +12 -3
package/dist/index.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
2
3
|
var __defProp = Object.defineProperty;
|
|
3
4
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
5
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
5
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
8
|
var __export = (target, all) => {
|
|
7
9
|
for (var name in all)
|
|
@@ -15,6 +17,14 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
15
17
|
}
|
|
16
18
|
return to;
|
|
17
19
|
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
18
28
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
29
|
|
|
20
30
|
// src/index.ts
|
|
@@ -23,10 +33,622 @@ __export(src_exports, {
|
|
|
23
33
|
ConfigError: () => ConfigError,
|
|
24
34
|
DEFAULT_CONFIG: () => DEFAULT_CONFIG,
|
|
25
35
|
TraceBeamSDK: () => TraceBeamSDK,
|
|
26
|
-
loadConfigFromEnv: () => loadConfigFromEnv
|
|
36
|
+
loadConfigFromEnv: () => loadConfigFromEnv,
|
|
37
|
+
mergeConfig: () => mergeConfig,
|
|
38
|
+
validateConfig: () => validateConfig
|
|
27
39
|
});
|
|
28
40
|
module.exports = __toCommonJS(src_exports);
|
|
29
41
|
|
|
42
|
+
// src/sdk.ts
|
|
43
|
+
var api = __toESM(require("@opentelemetry/api"));
|
|
44
|
+
|
|
45
|
+
// node_modules/@opentelemetry/core/build/esm/trace/suppress-tracing.js
|
|
46
|
+
var import_api = require("@opentelemetry/api");
|
|
47
|
+
var SUPPRESS_TRACING_KEY = (0, import_api.createContextKey)("OpenTelemetry SDK Context Key SUPPRESS_TRACING");
|
|
48
|
+
function suppressTracing(context3) {
|
|
49
|
+
return context3.setValue(SUPPRESS_TRACING_KEY, true);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// node_modules/@opentelemetry/core/build/esm/common/logging-error-handler.js
|
|
53
|
+
var import_api2 = require("@opentelemetry/api");
|
|
54
|
+
function loggingErrorHandler() {
|
|
55
|
+
return (ex) => {
|
|
56
|
+
import_api2.diag.error(stringifyException(ex));
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
function stringifyException(ex) {
|
|
60
|
+
if (typeof ex === "string") {
|
|
61
|
+
return ex;
|
|
62
|
+
} else {
|
|
63
|
+
return JSON.stringify(flattenException(ex));
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
function flattenException(ex) {
|
|
67
|
+
const result = {};
|
|
68
|
+
let current = ex;
|
|
69
|
+
while (current !== null) {
|
|
70
|
+
Object.getOwnPropertyNames(current).forEach((propertyName) => {
|
|
71
|
+
if (result[propertyName])
|
|
72
|
+
return;
|
|
73
|
+
const value = current[propertyName];
|
|
74
|
+
if (value) {
|
|
75
|
+
result[propertyName] = String(value);
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
current = Object.getPrototypeOf(current);
|
|
79
|
+
}
|
|
80
|
+
return result;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// node_modules/@opentelemetry/core/build/esm/common/global-error-handler.js
|
|
84
|
+
var delegateHandler = loggingErrorHandler();
|
|
85
|
+
function globalErrorHandler(ex) {
|
|
86
|
+
try {
|
|
87
|
+
delegateHandler(ex);
|
|
88
|
+
} catch {
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// node_modules/@opentelemetry/core/build/esm/platform/node/environment.js
|
|
93
|
+
var import_api3 = require("@opentelemetry/api");
|
|
94
|
+
var import_util = require("util");
|
|
95
|
+
function getNumberFromEnv(key) {
|
|
96
|
+
const raw = process.env[key];
|
|
97
|
+
if (raw == null || raw.trim() === "") {
|
|
98
|
+
return void 0;
|
|
99
|
+
}
|
|
100
|
+
const value = Number(raw);
|
|
101
|
+
if (isNaN(value)) {
|
|
102
|
+
import_api3.diag.warn(`Unknown value ${(0, import_util.inspect)(raw)} for ${key}, expected a number, using defaults`);
|
|
103
|
+
return void 0;
|
|
104
|
+
}
|
|
105
|
+
return value;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// node_modules/@opentelemetry/core/build/esm/common/time.js
|
|
109
|
+
var NANOSECOND_DIGITS = 9;
|
|
110
|
+
var NANOSECOND_DIGITS_IN_MILLIS = 6;
|
|
111
|
+
var MILLISECONDS_TO_NANOSECONDS = Math.pow(10, NANOSECOND_DIGITS_IN_MILLIS);
|
|
112
|
+
var SECOND_TO_NANOSECONDS = Math.pow(10, NANOSECOND_DIGITS);
|
|
113
|
+
function hrTimeToMicroseconds(time) {
|
|
114
|
+
return time[0] * 1e6 + time[1] / 1e3;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// node_modules/@opentelemetry/core/build/esm/ExportResult.js
|
|
118
|
+
var ExportResultCode;
|
|
119
|
+
(function(ExportResultCode2) {
|
|
120
|
+
ExportResultCode2[ExportResultCode2["SUCCESS"] = 0] = "SUCCESS";
|
|
121
|
+
ExportResultCode2[ExportResultCode2["FAILED"] = 1] = "FAILED";
|
|
122
|
+
})(ExportResultCode || (ExportResultCode = {}));
|
|
123
|
+
|
|
124
|
+
// node_modules/@opentelemetry/core/build/esm/utils/promise.js
|
|
125
|
+
var Deferred = class {
|
|
126
|
+
_promise;
|
|
127
|
+
_resolve;
|
|
128
|
+
_reject;
|
|
129
|
+
constructor() {
|
|
130
|
+
this._promise = new Promise((resolve, reject) => {
|
|
131
|
+
this._resolve = resolve;
|
|
132
|
+
this._reject = reject;
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
get promise() {
|
|
136
|
+
return this._promise;
|
|
137
|
+
}
|
|
138
|
+
resolve(val) {
|
|
139
|
+
this._resolve(val);
|
|
140
|
+
}
|
|
141
|
+
reject(err) {
|
|
142
|
+
this._reject(err);
|
|
143
|
+
}
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
// node_modules/@opentelemetry/core/build/esm/utils/callback.js
|
|
147
|
+
var BindOnceFuture = class {
|
|
148
|
+
_isCalled = false;
|
|
149
|
+
_deferred = new Deferred();
|
|
150
|
+
_callback;
|
|
151
|
+
_that;
|
|
152
|
+
constructor(callback, that) {
|
|
153
|
+
this._callback = callback;
|
|
154
|
+
this._that = that;
|
|
155
|
+
}
|
|
156
|
+
get isCalled() {
|
|
157
|
+
return this._isCalled;
|
|
158
|
+
}
|
|
159
|
+
get promise() {
|
|
160
|
+
return this._deferred.promise;
|
|
161
|
+
}
|
|
162
|
+
call(...args) {
|
|
163
|
+
if (!this._isCalled) {
|
|
164
|
+
this._isCalled = true;
|
|
165
|
+
try {
|
|
166
|
+
Promise.resolve(this._callback.call(this._that, ...args)).then((val) => this._deferred.resolve(val), (err) => this._deferred.reject(err));
|
|
167
|
+
} catch (err) {
|
|
168
|
+
this._deferred.reject(err);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
return this._deferred.promise;
|
|
172
|
+
}
|
|
173
|
+
};
|
|
174
|
+
|
|
175
|
+
// node_modules/@opentelemetry/core/build/esm/internal/exporter.js
|
|
176
|
+
var import_api4 = require("@opentelemetry/api");
|
|
177
|
+
function _export(exporter, arg) {
|
|
178
|
+
return new Promise((resolve) => {
|
|
179
|
+
import_api4.context.with(suppressTracing(import_api4.context.active()), () => {
|
|
180
|
+
exporter.export(arg, (result) => {
|
|
181
|
+
resolve(result);
|
|
182
|
+
});
|
|
183
|
+
});
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// node_modules/@opentelemetry/core/build/esm/index.js
|
|
188
|
+
var internal = {
|
|
189
|
+
_export
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
// node_modules/@opentelemetry/sdk-trace-base/build/esm/export/BatchSpanProcessorBase.js
|
|
193
|
+
var import_api5 = require("@opentelemetry/api");
|
|
194
|
+
var BatchSpanProcessorBase = class {
|
|
195
|
+
_maxExportBatchSize;
|
|
196
|
+
_maxQueueSize;
|
|
197
|
+
_scheduledDelayMillis;
|
|
198
|
+
_exportTimeoutMillis;
|
|
199
|
+
_exporter;
|
|
200
|
+
_isExporting = false;
|
|
201
|
+
_finishedSpans = [];
|
|
202
|
+
_timer;
|
|
203
|
+
_shutdownOnce;
|
|
204
|
+
_droppedSpansCount = 0;
|
|
205
|
+
constructor(exporter, config) {
|
|
206
|
+
this._exporter = exporter;
|
|
207
|
+
this._maxExportBatchSize = typeof config?.maxExportBatchSize === "number" ? config.maxExportBatchSize : getNumberFromEnv("OTEL_BSP_MAX_EXPORT_BATCH_SIZE") ?? 512;
|
|
208
|
+
this._maxQueueSize = typeof config?.maxQueueSize === "number" ? config.maxQueueSize : getNumberFromEnv("OTEL_BSP_MAX_QUEUE_SIZE") ?? 2048;
|
|
209
|
+
this._scheduledDelayMillis = typeof config?.scheduledDelayMillis === "number" ? config.scheduledDelayMillis : getNumberFromEnv("OTEL_BSP_SCHEDULE_DELAY") ?? 5e3;
|
|
210
|
+
this._exportTimeoutMillis = typeof config?.exportTimeoutMillis === "number" ? config.exportTimeoutMillis : getNumberFromEnv("OTEL_BSP_EXPORT_TIMEOUT") ?? 3e4;
|
|
211
|
+
this._shutdownOnce = new BindOnceFuture(this._shutdown, this);
|
|
212
|
+
if (this._maxExportBatchSize > this._maxQueueSize) {
|
|
213
|
+
import_api5.diag.warn("BatchSpanProcessor: maxExportBatchSize must be smaller or equal to maxQueueSize, setting maxExportBatchSize to match maxQueueSize");
|
|
214
|
+
this._maxExportBatchSize = this._maxQueueSize;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
forceFlush() {
|
|
218
|
+
if (this._shutdownOnce.isCalled) {
|
|
219
|
+
return this._shutdownOnce.promise;
|
|
220
|
+
}
|
|
221
|
+
return this._flushAll();
|
|
222
|
+
}
|
|
223
|
+
// does nothing.
|
|
224
|
+
onStart(_span, _parentContext) {
|
|
225
|
+
}
|
|
226
|
+
onEnd(span) {
|
|
227
|
+
if (this._shutdownOnce.isCalled) {
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
if ((span.spanContext().traceFlags & import_api5.TraceFlags.SAMPLED) === 0) {
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
this._addToBuffer(span);
|
|
234
|
+
}
|
|
235
|
+
shutdown() {
|
|
236
|
+
return this._shutdownOnce.call();
|
|
237
|
+
}
|
|
238
|
+
_shutdown() {
|
|
239
|
+
return Promise.resolve().then(() => {
|
|
240
|
+
return this.onShutdown();
|
|
241
|
+
}).then(() => {
|
|
242
|
+
return this._flushAll();
|
|
243
|
+
}).then(() => {
|
|
244
|
+
return this._exporter.shutdown();
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
/** Add a span in the buffer. */
|
|
248
|
+
_addToBuffer(span) {
|
|
249
|
+
if (this._finishedSpans.length >= this._maxQueueSize) {
|
|
250
|
+
if (this._droppedSpansCount === 0) {
|
|
251
|
+
import_api5.diag.debug("maxQueueSize reached, dropping spans");
|
|
252
|
+
}
|
|
253
|
+
this._droppedSpansCount++;
|
|
254
|
+
return;
|
|
255
|
+
}
|
|
256
|
+
if (this._droppedSpansCount > 0) {
|
|
257
|
+
import_api5.diag.warn(`Dropped ${this._droppedSpansCount} spans because maxQueueSize reached`);
|
|
258
|
+
this._droppedSpansCount = 0;
|
|
259
|
+
}
|
|
260
|
+
this._finishedSpans.push(span);
|
|
261
|
+
this._maybeStartTimer();
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* Send all spans to the exporter respecting the batch size limit
|
|
265
|
+
* This function is used only on forceFlush or shutdown,
|
|
266
|
+
* for all other cases _flush should be used
|
|
267
|
+
* */
|
|
268
|
+
_flushAll() {
|
|
269
|
+
return new Promise((resolve, reject) => {
|
|
270
|
+
const promises = [];
|
|
271
|
+
const count = Math.ceil(this._finishedSpans.length / this._maxExportBatchSize);
|
|
272
|
+
for (let i = 0, j = count; i < j; i++) {
|
|
273
|
+
promises.push(this._flushOneBatch());
|
|
274
|
+
}
|
|
275
|
+
Promise.all(promises).then(() => {
|
|
276
|
+
resolve();
|
|
277
|
+
}).catch(reject);
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
_flushOneBatch() {
|
|
281
|
+
this._clearTimer();
|
|
282
|
+
if (this._finishedSpans.length === 0) {
|
|
283
|
+
return Promise.resolve();
|
|
284
|
+
}
|
|
285
|
+
return new Promise((resolve, reject) => {
|
|
286
|
+
const timer = setTimeout(() => {
|
|
287
|
+
reject(new Error("Timeout"));
|
|
288
|
+
}, this._exportTimeoutMillis);
|
|
289
|
+
import_api5.context.with(suppressTracing(import_api5.context.active()), () => {
|
|
290
|
+
let spans;
|
|
291
|
+
if (this._finishedSpans.length <= this._maxExportBatchSize) {
|
|
292
|
+
spans = this._finishedSpans;
|
|
293
|
+
this._finishedSpans = [];
|
|
294
|
+
} else {
|
|
295
|
+
spans = this._finishedSpans.splice(0, this._maxExportBatchSize);
|
|
296
|
+
}
|
|
297
|
+
const doExport = () => this._exporter.export(spans, (result) => {
|
|
298
|
+
clearTimeout(timer);
|
|
299
|
+
if (result.code === ExportResultCode.SUCCESS) {
|
|
300
|
+
resolve();
|
|
301
|
+
} else {
|
|
302
|
+
reject(result.error ?? new Error("BatchSpanProcessor: span export failed"));
|
|
303
|
+
}
|
|
304
|
+
});
|
|
305
|
+
let pendingResources = null;
|
|
306
|
+
for (let i = 0, len = spans.length; i < len; i++) {
|
|
307
|
+
const span = spans[i];
|
|
308
|
+
if (span.resource.asyncAttributesPending && span.resource.waitForAsyncAttributes) {
|
|
309
|
+
pendingResources ??= [];
|
|
310
|
+
pendingResources.push(span.resource.waitForAsyncAttributes());
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
if (pendingResources === null) {
|
|
314
|
+
doExport();
|
|
315
|
+
} else {
|
|
316
|
+
Promise.all(pendingResources).then(doExport, (err) => {
|
|
317
|
+
globalErrorHandler(err);
|
|
318
|
+
reject(err);
|
|
319
|
+
});
|
|
320
|
+
}
|
|
321
|
+
});
|
|
322
|
+
});
|
|
323
|
+
}
|
|
324
|
+
_maybeStartTimer() {
|
|
325
|
+
if (this._isExporting)
|
|
326
|
+
return;
|
|
327
|
+
const flush = () => {
|
|
328
|
+
this._isExporting = true;
|
|
329
|
+
this._flushOneBatch().finally(() => {
|
|
330
|
+
this._isExporting = false;
|
|
331
|
+
if (this._finishedSpans.length > 0) {
|
|
332
|
+
this._clearTimer();
|
|
333
|
+
this._maybeStartTimer();
|
|
334
|
+
}
|
|
335
|
+
}).catch((e) => {
|
|
336
|
+
this._isExporting = false;
|
|
337
|
+
globalErrorHandler(e);
|
|
338
|
+
});
|
|
339
|
+
};
|
|
340
|
+
if (this._finishedSpans.length >= this._maxExportBatchSize) {
|
|
341
|
+
return flush();
|
|
342
|
+
}
|
|
343
|
+
if (this._timer !== void 0)
|
|
344
|
+
return;
|
|
345
|
+
this._timer = setTimeout(() => flush(), this._scheduledDelayMillis);
|
|
346
|
+
if (typeof this._timer !== "number") {
|
|
347
|
+
this._timer.unref();
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
_clearTimer() {
|
|
351
|
+
if (this._timer !== void 0) {
|
|
352
|
+
clearTimeout(this._timer);
|
|
353
|
+
this._timer = void 0;
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
};
|
|
357
|
+
|
|
358
|
+
// node_modules/@opentelemetry/sdk-trace-base/build/esm/platform/node/export/BatchSpanProcessor.js
|
|
359
|
+
var BatchSpanProcessor = class extends BatchSpanProcessorBase {
|
|
360
|
+
onShutdown() {
|
|
361
|
+
}
|
|
362
|
+
};
|
|
363
|
+
|
|
364
|
+
// node_modules/@opentelemetry/sdk-trace-base/build/esm/export/ConsoleSpanExporter.js
|
|
365
|
+
var ConsoleSpanExporter = class {
|
|
366
|
+
/**
|
|
367
|
+
* Export spans.
|
|
368
|
+
* @param spans
|
|
369
|
+
* @param resultCallback
|
|
370
|
+
*/
|
|
371
|
+
export(spans, resultCallback) {
|
|
372
|
+
return this._sendSpans(spans, resultCallback);
|
|
373
|
+
}
|
|
374
|
+
/**
|
|
375
|
+
* Shutdown the exporter.
|
|
376
|
+
*/
|
|
377
|
+
shutdown() {
|
|
378
|
+
this._sendSpans([]);
|
|
379
|
+
return this.forceFlush();
|
|
380
|
+
}
|
|
381
|
+
/**
|
|
382
|
+
* Exports any pending spans in exporter
|
|
383
|
+
*/
|
|
384
|
+
forceFlush() {
|
|
385
|
+
return Promise.resolve();
|
|
386
|
+
}
|
|
387
|
+
/**
|
|
388
|
+
* converts span info into more readable format
|
|
389
|
+
* @param span
|
|
390
|
+
*/
|
|
391
|
+
_exportInfo(span) {
|
|
392
|
+
return {
|
|
393
|
+
resource: {
|
|
394
|
+
attributes: span.resource.attributes
|
|
395
|
+
},
|
|
396
|
+
instrumentationScope: span.instrumentationScope,
|
|
397
|
+
traceId: span.spanContext().traceId,
|
|
398
|
+
parentSpanContext: span.parentSpanContext,
|
|
399
|
+
traceState: span.spanContext().traceState?.serialize(),
|
|
400
|
+
name: span.name,
|
|
401
|
+
id: span.spanContext().spanId,
|
|
402
|
+
kind: span.kind,
|
|
403
|
+
timestamp: hrTimeToMicroseconds(span.startTime),
|
|
404
|
+
duration: hrTimeToMicroseconds(span.duration),
|
|
405
|
+
attributes: span.attributes,
|
|
406
|
+
status: span.status,
|
|
407
|
+
events: span.events,
|
|
408
|
+
links: span.links
|
|
409
|
+
};
|
|
410
|
+
}
|
|
411
|
+
/**
|
|
412
|
+
* Showing spans in console
|
|
413
|
+
* @param spans
|
|
414
|
+
* @param done
|
|
415
|
+
*/
|
|
416
|
+
_sendSpans(spans, done) {
|
|
417
|
+
for (const span of spans) {
|
|
418
|
+
console.dir(this._exportInfo(span), { depth: 3 });
|
|
419
|
+
}
|
|
420
|
+
if (done) {
|
|
421
|
+
return done({ code: ExportResultCode.SUCCESS });
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
};
|
|
425
|
+
|
|
426
|
+
// node_modules/@opentelemetry/sdk-trace-base/build/esm/export/SimpleSpanProcessor.js
|
|
427
|
+
var import_api6 = require("@opentelemetry/api");
|
|
428
|
+
var SimpleSpanProcessor = class {
|
|
429
|
+
_exporter;
|
|
430
|
+
_shutdownOnce;
|
|
431
|
+
_pendingExports;
|
|
432
|
+
constructor(exporter) {
|
|
433
|
+
this._exporter = exporter;
|
|
434
|
+
this._shutdownOnce = new BindOnceFuture(this._shutdown, this);
|
|
435
|
+
this._pendingExports = /* @__PURE__ */ new Set();
|
|
436
|
+
}
|
|
437
|
+
async forceFlush() {
|
|
438
|
+
await Promise.all(Array.from(this._pendingExports));
|
|
439
|
+
if (this._exporter.forceFlush) {
|
|
440
|
+
await this._exporter.forceFlush();
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
onStart(_span, _parentContext) {
|
|
444
|
+
}
|
|
445
|
+
onEnd(span) {
|
|
446
|
+
if (this._shutdownOnce.isCalled) {
|
|
447
|
+
return;
|
|
448
|
+
}
|
|
449
|
+
if ((span.spanContext().traceFlags & import_api6.TraceFlags.SAMPLED) === 0) {
|
|
450
|
+
return;
|
|
451
|
+
}
|
|
452
|
+
const pendingExport = this._doExport(span).catch((err) => globalErrorHandler(err));
|
|
453
|
+
this._pendingExports.add(pendingExport);
|
|
454
|
+
void pendingExport.finally(() => this._pendingExports.delete(pendingExport));
|
|
455
|
+
}
|
|
456
|
+
async _doExport(span) {
|
|
457
|
+
if (span.resource.asyncAttributesPending) {
|
|
458
|
+
await span.resource.waitForAsyncAttributes?.();
|
|
459
|
+
}
|
|
460
|
+
const result = await internal._export(this._exporter, [span]);
|
|
461
|
+
if (result.code !== ExportResultCode.SUCCESS) {
|
|
462
|
+
throw result.error ?? new Error(`SimpleSpanProcessor: span export failed (status ${result})`);
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
shutdown() {
|
|
466
|
+
return this._shutdownOnce.call();
|
|
467
|
+
}
|
|
468
|
+
_shutdown() {
|
|
469
|
+
return this._exporter.shutdown();
|
|
470
|
+
}
|
|
471
|
+
};
|
|
472
|
+
|
|
473
|
+
// src/sdk.ts
|
|
474
|
+
var import_sdk_trace_node = require("@opentelemetry/sdk-trace-node");
|
|
475
|
+
var import_exporter_trace_otlp_http = require("@opentelemetry/exporter-trace-otlp-http");
|
|
476
|
+
var import_resources = require("@opentelemetry/resources");
|
|
477
|
+
var import_semantic_conventions = require("@opentelemetry/semantic-conventions");
|
|
478
|
+
|
|
479
|
+
// node_modules/@opentelemetry/instrumentation/build/esm/autoLoader.js
|
|
480
|
+
var import_api7 = require("@opentelemetry/api");
|
|
481
|
+
|
|
482
|
+
// node_modules/@opentelemetry/api-logs/build/esm/NoopLogger.js
|
|
483
|
+
var NoopLogger = class {
|
|
484
|
+
emit(_logRecord) {
|
|
485
|
+
}
|
|
486
|
+
};
|
|
487
|
+
var NOOP_LOGGER = new NoopLogger();
|
|
488
|
+
|
|
489
|
+
// node_modules/@opentelemetry/api-logs/build/esm/NoopLoggerProvider.js
|
|
490
|
+
var NoopLoggerProvider = class {
|
|
491
|
+
getLogger(_name, _version, _options) {
|
|
492
|
+
return new NoopLogger();
|
|
493
|
+
}
|
|
494
|
+
};
|
|
495
|
+
var NOOP_LOGGER_PROVIDER = new NoopLoggerProvider();
|
|
496
|
+
|
|
497
|
+
// node_modules/@opentelemetry/api-logs/build/esm/ProxyLogger.js
|
|
498
|
+
var ProxyLogger = class {
|
|
499
|
+
constructor(provider, name, version, options) {
|
|
500
|
+
this._provider = provider;
|
|
501
|
+
this.name = name;
|
|
502
|
+
this.version = version;
|
|
503
|
+
this.options = options;
|
|
504
|
+
}
|
|
505
|
+
/**
|
|
506
|
+
* Emit a log record. This method should only be used by log appenders.
|
|
507
|
+
*
|
|
508
|
+
* @param logRecord
|
|
509
|
+
*/
|
|
510
|
+
emit(logRecord) {
|
|
511
|
+
this._getLogger().emit(logRecord);
|
|
512
|
+
}
|
|
513
|
+
/**
|
|
514
|
+
* Try to get a logger from the proxy logger provider.
|
|
515
|
+
* If the proxy logger provider has no delegate, return a noop logger.
|
|
516
|
+
*/
|
|
517
|
+
_getLogger() {
|
|
518
|
+
if (this._delegate) {
|
|
519
|
+
return this._delegate;
|
|
520
|
+
}
|
|
521
|
+
const logger = this._provider._getDelegateLogger(this.name, this.version, this.options);
|
|
522
|
+
if (!logger) {
|
|
523
|
+
return NOOP_LOGGER;
|
|
524
|
+
}
|
|
525
|
+
this._delegate = logger;
|
|
526
|
+
return this._delegate;
|
|
527
|
+
}
|
|
528
|
+
};
|
|
529
|
+
|
|
530
|
+
// node_modules/@opentelemetry/api-logs/build/esm/ProxyLoggerProvider.js
|
|
531
|
+
var ProxyLoggerProvider = class {
|
|
532
|
+
getLogger(name, version, options) {
|
|
533
|
+
var _a;
|
|
534
|
+
return (_a = this._getDelegateLogger(name, version, options)) !== null && _a !== void 0 ? _a : new ProxyLogger(this, name, version, options);
|
|
535
|
+
}
|
|
536
|
+
/**
|
|
537
|
+
* Get the delegate logger provider.
|
|
538
|
+
* Used by tests only.
|
|
539
|
+
* @internal
|
|
540
|
+
*/
|
|
541
|
+
_getDelegate() {
|
|
542
|
+
var _a;
|
|
543
|
+
return (_a = this._delegate) !== null && _a !== void 0 ? _a : NOOP_LOGGER_PROVIDER;
|
|
544
|
+
}
|
|
545
|
+
/**
|
|
546
|
+
* Set the delegate logger provider
|
|
547
|
+
* @internal
|
|
548
|
+
*/
|
|
549
|
+
_setDelegate(delegate) {
|
|
550
|
+
this._delegate = delegate;
|
|
551
|
+
}
|
|
552
|
+
/**
|
|
553
|
+
* @internal
|
|
554
|
+
*/
|
|
555
|
+
_getDelegateLogger(name, version, options) {
|
|
556
|
+
var _a;
|
|
557
|
+
return (_a = this._delegate) === null || _a === void 0 ? void 0 : _a.getLogger(name, version, options);
|
|
558
|
+
}
|
|
559
|
+
};
|
|
560
|
+
|
|
561
|
+
// node_modules/@opentelemetry/api-logs/build/esm/internal/global-utils.js
|
|
562
|
+
var GLOBAL_LOGS_API_KEY = /* @__PURE__ */ Symbol.for("io.opentelemetry.js.api.logs");
|
|
563
|
+
var _global = globalThis;
|
|
564
|
+
function makeGetter(requiredVersion, instance, fallback) {
|
|
565
|
+
return (version) => version === requiredVersion ? instance : fallback;
|
|
566
|
+
}
|
|
567
|
+
var API_BACKWARDS_COMPATIBILITY_VERSION = 1;
|
|
568
|
+
|
|
569
|
+
// node_modules/@opentelemetry/api-logs/build/esm/api/logs.js
|
|
570
|
+
var LogsAPI = class _LogsAPI {
|
|
571
|
+
constructor() {
|
|
572
|
+
this._proxyLoggerProvider = new ProxyLoggerProvider();
|
|
573
|
+
}
|
|
574
|
+
static getInstance() {
|
|
575
|
+
if (!this._instance) {
|
|
576
|
+
this._instance = new _LogsAPI();
|
|
577
|
+
}
|
|
578
|
+
return this._instance;
|
|
579
|
+
}
|
|
580
|
+
setGlobalLoggerProvider(provider) {
|
|
581
|
+
if (_global[GLOBAL_LOGS_API_KEY]) {
|
|
582
|
+
return this.getLoggerProvider();
|
|
583
|
+
}
|
|
584
|
+
_global[GLOBAL_LOGS_API_KEY] = makeGetter(API_BACKWARDS_COMPATIBILITY_VERSION, provider, NOOP_LOGGER_PROVIDER);
|
|
585
|
+
this._proxyLoggerProvider._setDelegate(provider);
|
|
586
|
+
return provider;
|
|
587
|
+
}
|
|
588
|
+
/**
|
|
589
|
+
* Returns the global logger provider.
|
|
590
|
+
*
|
|
591
|
+
* @returns LoggerProvider
|
|
592
|
+
*/
|
|
593
|
+
getLoggerProvider() {
|
|
594
|
+
var _a, _b;
|
|
595
|
+
return (_b = (_a = _global[GLOBAL_LOGS_API_KEY]) === null || _a === void 0 ? void 0 : _a.call(_global, API_BACKWARDS_COMPATIBILITY_VERSION)) !== null && _b !== void 0 ? _b : this._proxyLoggerProvider;
|
|
596
|
+
}
|
|
597
|
+
/**
|
|
598
|
+
* Returns a logger from the global logger provider.
|
|
599
|
+
*
|
|
600
|
+
* @returns Logger
|
|
601
|
+
*/
|
|
602
|
+
getLogger(name, version, options) {
|
|
603
|
+
return this.getLoggerProvider().getLogger(name, version, options);
|
|
604
|
+
}
|
|
605
|
+
/** Remove the global logger provider */
|
|
606
|
+
disable() {
|
|
607
|
+
delete _global[GLOBAL_LOGS_API_KEY];
|
|
608
|
+
this._proxyLoggerProvider = new ProxyLoggerProvider();
|
|
609
|
+
}
|
|
610
|
+
};
|
|
611
|
+
|
|
612
|
+
// node_modules/@opentelemetry/api-logs/build/esm/index.js
|
|
613
|
+
var logs = LogsAPI.getInstance();
|
|
614
|
+
|
|
615
|
+
// node_modules/@opentelemetry/instrumentation/build/esm/autoLoaderUtils.js
|
|
616
|
+
function enableInstrumentations(instrumentations, tracerProvider, meterProvider, loggerProvider) {
|
|
617
|
+
for (let i = 0, j = instrumentations.length; i < j; i++) {
|
|
618
|
+
const instrumentation = instrumentations[i];
|
|
619
|
+
if (tracerProvider) {
|
|
620
|
+
instrumentation.setTracerProvider(tracerProvider);
|
|
621
|
+
}
|
|
622
|
+
if (meterProvider) {
|
|
623
|
+
instrumentation.setMeterProvider(meterProvider);
|
|
624
|
+
}
|
|
625
|
+
if (loggerProvider && instrumentation.setLoggerProvider) {
|
|
626
|
+
instrumentation.setLoggerProvider(loggerProvider);
|
|
627
|
+
}
|
|
628
|
+
if (!instrumentation.getConfig().enabled) {
|
|
629
|
+
instrumentation.enable();
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
function disableInstrumentations(instrumentations) {
|
|
634
|
+
instrumentations.forEach((instrumentation) => instrumentation.disable());
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
// node_modules/@opentelemetry/instrumentation/build/esm/autoLoader.js
|
|
638
|
+
function registerInstrumentations(options) {
|
|
639
|
+
const tracerProvider = options.tracerProvider || import_api7.trace.getTracerProvider();
|
|
640
|
+
const meterProvider = options.meterProvider || import_api7.metrics.getMeterProvider();
|
|
641
|
+
const loggerProvider = options.loggerProvider || logs.getLoggerProvider();
|
|
642
|
+
const instrumentations = options.instrumentations?.flat() ?? [];
|
|
643
|
+
enableInstrumentations(instrumentations, tracerProvider, meterProvider, loggerProvider);
|
|
644
|
+
return () => {
|
|
645
|
+
disableInstrumentations(instrumentations);
|
|
646
|
+
};
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
// src/sdk.ts
|
|
650
|
+
var import_auto_instrumentations_node = require("@opentelemetry/auto-instrumentations-node");
|
|
651
|
+
|
|
30
652
|
// src/config.ts
|
|
31
653
|
var DEFAULT_CONFIG = {
|
|
32
654
|
environment: "development",
|
|
@@ -127,357 +749,143 @@ function parseBoolEnv(name, defaultValue) {
|
|
|
127
749
|
return value.toLowerCase() === "true" || value === "1";
|
|
128
750
|
}
|
|
129
751
|
|
|
130
|
-
// src/
|
|
131
|
-
var defaultLogger = {
|
|
132
|
-
debug: (msg, ...args) => console.debug(`[tracebeam] ${msg}`, ...args),
|
|
133
|
-
warn: (msg, ...args) => console.warn(`[tracebeam] ${msg}`, ...args),
|
|
134
|
-
error: (msg, ...args) => console.error(`[tracebeam] ${msg}`, ...args)
|
|
135
|
-
};
|
|
136
|
-
var Transport = class {
|
|
137
|
-
endpoint;
|
|
138
|
-
apiKey;
|
|
139
|
-
timeout;
|
|
140
|
-
logger;
|
|
141
|
-
debug;
|
|
142
|
-
state = "active";
|
|
143
|
-
constructor(options) {
|
|
144
|
-
this.endpoint = options.endpoint.replace(/\/$/, "");
|
|
145
|
-
this.apiKey = options.apiKey;
|
|
146
|
-
this.timeout = options.timeout;
|
|
147
|
-
this.debug = options.debug;
|
|
148
|
-
this.logger = options.logger ?? defaultLogger;
|
|
149
|
-
}
|
|
150
|
-
/**
|
|
151
|
-
* Get current transport state
|
|
152
|
-
*/
|
|
153
|
-
getState() {
|
|
154
|
-
return this.state;
|
|
155
|
-
}
|
|
156
|
-
/**
|
|
157
|
-
* Check if transport is active
|
|
158
|
-
*/
|
|
159
|
-
isActive() {
|
|
160
|
-
return this.state === "active";
|
|
161
|
-
}
|
|
162
|
-
/**
|
|
163
|
-
* Send a batch of events to the Ingest API
|
|
164
|
-
* Implements retry with exponential backoff
|
|
165
|
-
*/
|
|
166
|
-
async send(events) {
|
|
167
|
-
if (!this.isActive()) {
|
|
168
|
-
return {
|
|
169
|
-
success: false,
|
|
170
|
-
error: "Transport disabled",
|
|
171
|
-
message: `Transport is ${this.state}`,
|
|
172
|
-
code: 0
|
|
173
|
-
};
|
|
174
|
-
}
|
|
175
|
-
const batch = { events };
|
|
176
|
-
const url = `${this.endpoint}/api/v1/events`;
|
|
177
|
-
let lastError = null;
|
|
178
|
-
const maxRetries = 3;
|
|
179
|
-
const baseDelay = 1e3;
|
|
180
|
-
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
181
|
-
try {
|
|
182
|
-
const response = await this.executeRequest(url, batch);
|
|
183
|
-
if (response.success) {
|
|
184
|
-
if (this.debug) {
|
|
185
|
-
this.logger.debug(`Sent ${events.length} events successfully`);
|
|
186
|
-
}
|
|
187
|
-
return response;
|
|
188
|
-
}
|
|
189
|
-
const errorResponse = response;
|
|
190
|
-
lastError = errorResponse;
|
|
191
|
-
switch (errorResponse.code) {
|
|
192
|
-
case 401:
|
|
193
|
-
this.state = "disabled";
|
|
194
|
-
this.logger.error("Invalid API key. SDK disabled.");
|
|
195
|
-
return errorResponse;
|
|
196
|
-
case 402:
|
|
197
|
-
this.state = "quota_exceeded";
|
|
198
|
-
this.logger.warn("Event quota exceeded. SDK paused.");
|
|
199
|
-
return errorResponse;
|
|
200
|
-
case 429:
|
|
201
|
-
const retryAfter = errorResponse.retry_after ?? 1;
|
|
202
|
-
if (attempt < maxRetries) {
|
|
203
|
-
await this.sleep(retryAfter * 1e3);
|
|
204
|
-
continue;
|
|
205
|
-
}
|
|
206
|
-
return errorResponse;
|
|
207
|
-
case 400:
|
|
208
|
-
this.logger.warn("Bad request:", errorResponse.message);
|
|
209
|
-
return errorResponse;
|
|
210
|
-
default:
|
|
211
|
-
if (errorResponse.code >= 500 && attempt < maxRetries) {
|
|
212
|
-
const delay = this.calculateBackoff(attempt, baseDelay);
|
|
213
|
-
if (this.debug) {
|
|
214
|
-
this.logger.debug(`Retry ${attempt + 1}/${maxRetries} after ${delay}ms`);
|
|
215
|
-
}
|
|
216
|
-
await this.sleep(delay);
|
|
217
|
-
continue;
|
|
218
|
-
}
|
|
219
|
-
return errorResponse;
|
|
220
|
-
}
|
|
221
|
-
} catch (error) {
|
|
222
|
-
if (attempt < maxRetries) {
|
|
223
|
-
const delay = this.calculateBackoff(attempt, baseDelay);
|
|
224
|
-
if (this.debug) {
|
|
225
|
-
this.logger.debug(`Network error, retry ${attempt + 1}/${maxRetries} after ${delay}ms`);
|
|
226
|
-
}
|
|
227
|
-
await this.sleep(delay);
|
|
228
|
-
continue;
|
|
229
|
-
}
|
|
230
|
-
const networkError = {
|
|
231
|
-
success: false,
|
|
232
|
-
error: "Network Error",
|
|
233
|
-
message: error instanceof Error ? error.message : "Unknown error",
|
|
234
|
-
code: 0
|
|
235
|
-
};
|
|
236
|
-
return networkError;
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
return lastError ?? {
|
|
240
|
-
success: false,
|
|
241
|
-
error: "Max retries exceeded",
|
|
242
|
-
message: "Failed after maximum retry attempts",
|
|
243
|
-
code: 0
|
|
244
|
-
};
|
|
245
|
-
}
|
|
246
|
-
/**
|
|
247
|
-
* Execute HTTP request
|
|
248
|
-
*/
|
|
249
|
-
async executeRequest(url, batch) {
|
|
250
|
-
const controller = new AbortController();
|
|
251
|
-
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
|
|
252
|
-
try {
|
|
253
|
-
const response = await fetch(url, {
|
|
254
|
-
method: "POST",
|
|
255
|
-
headers: {
|
|
256
|
-
"Content-Type": "application/json",
|
|
257
|
-
"Authorization": `Bearer ${this.apiKey}`
|
|
258
|
-
},
|
|
259
|
-
body: JSON.stringify(batch),
|
|
260
|
-
signal: controller.signal
|
|
261
|
-
});
|
|
262
|
-
const data = await response.json();
|
|
263
|
-
return data;
|
|
264
|
-
} finally {
|
|
265
|
-
clearTimeout(timeoutId);
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
|
-
/**
|
|
269
|
-
* Calculate backoff delay with jitter
|
|
270
|
-
*/
|
|
271
|
-
calculateBackoff(attempt, baseDelay) {
|
|
272
|
-
const exponentialDelay = baseDelay * Math.pow(2, attempt);
|
|
273
|
-
const jitter = exponentialDelay * 0.1 * (Math.random() * 2 - 1);
|
|
274
|
-
return Math.round(exponentialDelay + jitter);
|
|
275
|
-
}
|
|
276
|
-
/**
|
|
277
|
-
* Sleep for specified milliseconds
|
|
278
|
-
*/
|
|
279
|
-
sleep(ms) {
|
|
280
|
-
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
281
|
-
}
|
|
282
|
-
};
|
|
283
|
-
|
|
284
|
-
// src/queue.ts
|
|
285
|
-
var EventQueue = class {
|
|
286
|
-
queue = [];
|
|
287
|
-
options;
|
|
288
|
-
onFlush;
|
|
289
|
-
flushTimer = null;
|
|
290
|
-
isFlushing = false;
|
|
291
|
-
constructor(options, onFlush) {
|
|
292
|
-
this.options = options;
|
|
293
|
-
this.onFlush = onFlush;
|
|
294
|
-
}
|
|
295
|
-
/**
|
|
296
|
-
* Start the background flush timer
|
|
297
|
-
*/
|
|
298
|
-
start() {
|
|
299
|
-
if (this.flushTimer) return;
|
|
300
|
-
this.flushTimer = setInterval(() => {
|
|
301
|
-
this.flush().catch(() => {
|
|
302
|
-
});
|
|
303
|
-
}, this.options.flushInterval);
|
|
304
|
-
if (this.flushTimer.unref) {
|
|
305
|
-
this.flushTimer.unref();
|
|
306
|
-
}
|
|
307
|
-
}
|
|
308
|
-
/**
|
|
309
|
-
* Stop the background flush timer
|
|
310
|
-
*/
|
|
311
|
-
stop() {
|
|
312
|
-
if (this.flushTimer) {
|
|
313
|
-
clearInterval(this.flushTimer);
|
|
314
|
-
this.flushTimer = null;
|
|
315
|
-
}
|
|
316
|
-
}
|
|
317
|
-
/**
|
|
318
|
-
* Add an event to the queue
|
|
319
|
-
* Returns immediately (non-blocking)
|
|
320
|
-
*/
|
|
321
|
-
add(event) {
|
|
322
|
-
if (this.queue.length >= this.options.maxQueueSize) {
|
|
323
|
-
this.queue.shift();
|
|
324
|
-
if (this.options.debug) {
|
|
325
|
-
console.warn("[tracebeam] Queue full, dropping oldest event");
|
|
326
|
-
}
|
|
327
|
-
}
|
|
328
|
-
this.queue.push(event);
|
|
329
|
-
if (this.queue.length >= this.options.batchSize) {
|
|
330
|
-
this.flush().catch(() => {
|
|
331
|
-
});
|
|
332
|
-
}
|
|
333
|
-
}
|
|
334
|
-
/**
|
|
335
|
-
* Flush all queued events
|
|
336
|
-
*/
|
|
337
|
-
async flush() {
|
|
338
|
-
if (this.isFlushing || this.queue.length === 0) {
|
|
339
|
-
return;
|
|
340
|
-
}
|
|
341
|
-
this.isFlushing = true;
|
|
342
|
-
try {
|
|
343
|
-
const events = this.queue.splice(0, this.queue.length);
|
|
344
|
-
await this.onFlush(events);
|
|
345
|
-
} finally {
|
|
346
|
-
this.isFlushing = false;
|
|
347
|
-
}
|
|
348
|
-
}
|
|
349
|
-
/**
|
|
350
|
-
* Get current queue size
|
|
351
|
-
*/
|
|
352
|
-
size() {
|
|
353
|
-
return this.queue.length;
|
|
354
|
-
}
|
|
355
|
-
/**
|
|
356
|
-
* Check if queue is empty
|
|
357
|
-
*/
|
|
358
|
-
isEmpty() {
|
|
359
|
-
return this.queue.length === 0;
|
|
360
|
-
}
|
|
361
|
-
};
|
|
362
|
-
function createEvent(projectId, environment, error, options = {}, globalTags = {}, globalExtra = {}) {
|
|
363
|
-
if (!projectId || projectId.trim() === "") {
|
|
364
|
-
throw new ConfigError('createEvent: "projectId" must be a non-empty string.');
|
|
365
|
-
}
|
|
366
|
-
if (!environment || environment.trim() === "") {
|
|
367
|
-
throw new ConfigError('createEvent: "environment" must be a non-empty string.');
|
|
368
|
-
}
|
|
369
|
-
const level = options.level ?? "error";
|
|
370
|
-
const timestamp = options.timestamp ?? (/* @__PURE__ */ new Date()).toISOString();
|
|
371
|
-
const tags = {
|
|
372
|
-
...globalTags,
|
|
373
|
-
...options.tags
|
|
374
|
-
};
|
|
375
|
-
const extra = {
|
|
376
|
-
...globalExtra,
|
|
377
|
-
...options.extra
|
|
378
|
-
};
|
|
379
|
-
const truncatedError = error.length > 1e4 ? error.slice(0, 1e4) : error;
|
|
380
|
-
return {
|
|
381
|
-
project_id: projectId,
|
|
382
|
-
error: truncatedError,
|
|
383
|
-
level,
|
|
384
|
-
environment,
|
|
385
|
-
timestamp,
|
|
386
|
-
tags,
|
|
387
|
-
extra
|
|
388
|
-
};
|
|
389
|
-
}
|
|
390
|
-
|
|
391
|
-
// src/client.ts
|
|
752
|
+
// src/sdk.ts
|
|
392
753
|
var TraceBeamSDK = class _TraceBeamSDK {
|
|
393
754
|
config;
|
|
394
|
-
|
|
395
|
-
|
|
755
|
+
provider;
|
|
756
|
+
tracer;
|
|
757
|
+
isInitialized = true;
|
|
396
758
|
globalTags = {};
|
|
397
759
|
globalExtra = {};
|
|
398
760
|
userId = null;
|
|
399
|
-
isInitialized = true;
|
|
400
761
|
/**
|
|
401
762
|
* Create SDK instance from configuration
|
|
402
763
|
*/
|
|
403
764
|
constructor(config) {
|
|
404
765
|
validateConfig(config);
|
|
405
766
|
this.config = mergeConfig(config);
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
767
|
+
const baseUrl = this.config.endpoint.replace(/\/$/, "");
|
|
768
|
+
const exporterUrl = `${baseUrl}/v1/traces`;
|
|
769
|
+
const exporter = new import_exporter_trace_otlp_http.OTLPTraceExporter({
|
|
770
|
+
url: exporterUrl,
|
|
771
|
+
headers: {
|
|
772
|
+
"Authorization": `Bearer ${this.config.apiKey}`
|
|
773
|
+
}
|
|
411
774
|
});
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
debug: this.config.debug
|
|
418
|
-
},
|
|
419
|
-
this.handleFlush.bind(this)
|
|
420
|
-
);
|
|
421
|
-
this.queue.start();
|
|
775
|
+
const spanProcessors = [];
|
|
776
|
+
spanProcessors.push(new BatchSpanProcessor(exporter, {
|
|
777
|
+
maxExportBatchSize: this.config.batchSize,
|
|
778
|
+
scheduledDelayMillis: this.config.flushInterval
|
|
779
|
+
}));
|
|
422
780
|
if (this.config.debug) {
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
781
|
+
spanProcessors.push(new SimpleSpanProcessor(new ConsoleSpanExporter()));
|
|
782
|
+
console.debug("[tracebeam] Initialized OTLP", {
|
|
783
|
+
url: exporterUrl,
|
|
784
|
+
projectId: this.config.projectId
|
|
427
785
|
});
|
|
428
786
|
}
|
|
787
|
+
this.provider = new import_sdk_trace_node.NodeTracerProvider({
|
|
788
|
+
resource: (0, import_resources.resourceFromAttributes)({
|
|
789
|
+
[import_semantic_conventions.SemanticResourceAttributes.SERVICE_NAME]: this.config.projectId,
|
|
790
|
+
[import_semantic_conventions.SemanticResourceAttributes.SERVICE_VERSION]: this.config.environment,
|
|
791
|
+
[import_semantic_conventions.SemanticResourceAttributes.DEPLOYMENT_ENVIRONMENT]: this.config.environment,
|
|
792
|
+
"telemetry.sdk.language": "nodejs",
|
|
793
|
+
"telemetry.sdk.name": "tracebeam-sdk",
|
|
794
|
+
"telemetry.sdk.version": "0.2.0"
|
|
795
|
+
}),
|
|
796
|
+
spanProcessors
|
|
797
|
+
});
|
|
798
|
+
this.provider.register();
|
|
799
|
+
registerInstrumentations({
|
|
800
|
+
tracerProvider: this.provider,
|
|
801
|
+
instrumentations: [
|
|
802
|
+
(0, import_auto_instrumentations_node.getNodeAutoInstrumentations)({
|
|
803
|
+
// Disable some noisy instrumentations
|
|
804
|
+
"@opentelemetry/instrumentation-fs": { enabled: false },
|
|
805
|
+
"@opentelemetry/instrumentation-dns": { enabled: false }
|
|
806
|
+
})
|
|
807
|
+
]
|
|
808
|
+
});
|
|
809
|
+
this.tracer = api.trace.getTracer("tracebeam-sdk");
|
|
429
810
|
}
|
|
430
|
-
/**
|
|
431
|
-
* Create SDK instance from environment variables
|
|
432
|
-
*
|
|
433
|
-
* Required env vars:
|
|
434
|
-
* - TRACEBEAM_API_KEY
|
|
435
|
-
* - TRACEBEAM_PROJECT_ID
|
|
436
|
-
*
|
|
437
|
-
* Optional env vars:
|
|
438
|
-
* - TRACEBEAM_ENVIRONMENT (default: 'development')
|
|
439
|
-
* - TRACEBEAM_ENDPOINT (default: 'https://ingest.tracebeam.io')
|
|
440
|
-
* - TRACEBEAM_BATCH_SIZE (default: 100)
|
|
441
|
-
* - TRACEBEAM_FLUSH_INTERVAL (default: 5000)
|
|
442
|
-
* - TRACEBEAM_HTTP_TIMEOUT (default: 10000)
|
|
443
|
-
* - TRACEBEAM_MAX_QUEUE_SIZE (default: 10000)
|
|
444
|
-
* - TRACEBEAM_SAMPLE_RATE (default: 1.0)
|
|
445
|
-
* - TRACEBEAM_DEBUG (default: false)
|
|
446
|
-
*/
|
|
447
811
|
static fromEnv() {
|
|
448
812
|
const config = loadConfigFromEnv();
|
|
449
813
|
return new _TraceBeamSDK(config);
|
|
450
814
|
}
|
|
451
815
|
/**
|
|
452
816
|
* Capture an exception/error
|
|
453
|
-
* Returns immediately (non-blocking)
|
|
454
817
|
*/
|
|
455
818
|
captureException(error, options = {}) {
|
|
456
819
|
if (!this.canCapture()) return;
|
|
457
|
-
const
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
820
|
+
const timestamp = options.timestamp ? new Date(options.timestamp).getTime() : Date.now();
|
|
821
|
+
let startTime = timestamp;
|
|
822
|
+
if (options.latency) {
|
|
823
|
+
startTime = timestamp - options.latency;
|
|
824
|
+
}
|
|
825
|
+
let spanName = "exception";
|
|
826
|
+
let spanStatus = api.SpanStatusCode.ERROR;
|
|
827
|
+
let errorMessage = "";
|
|
828
|
+
if (error instanceof Error) {
|
|
829
|
+
spanName = error.name || "Error";
|
|
830
|
+
errorMessage = error.message;
|
|
831
|
+
} else if (typeof error === "string") {
|
|
832
|
+
if (error === "") {
|
|
833
|
+
spanName = options.tags?.["endpoint"] || "request";
|
|
834
|
+
spanStatus = api.SpanStatusCode.OK;
|
|
835
|
+
} else {
|
|
836
|
+
spanName = "Error";
|
|
837
|
+
errorMessage = error;
|
|
838
|
+
}
|
|
839
|
+
} else {
|
|
840
|
+
spanName = "Error";
|
|
841
|
+
errorMessage = String(error);
|
|
842
|
+
}
|
|
843
|
+
const span = this.tracer.startSpan(spanName, {
|
|
844
|
+
startTime,
|
|
845
|
+
kind: api.SpanKind.CLIENT
|
|
462
846
|
});
|
|
463
|
-
|
|
847
|
+
const attributes = {};
|
|
848
|
+
Object.entries(this.globalTags).forEach(([k, v]) => attributes[k] = v);
|
|
849
|
+
if (options.tags) {
|
|
850
|
+
Object.entries(options.tags).forEach(([k, v]) => attributes[k] = v);
|
|
851
|
+
}
|
|
852
|
+
Object.entries(this.globalExtra).forEach(([k, v]) => {
|
|
853
|
+
if (typeof v === "string" || typeof v === "number" || typeof v === "boolean") {
|
|
854
|
+
attributes[k] = v;
|
|
855
|
+
} else {
|
|
856
|
+
attributes[k] = JSON.stringify(v);
|
|
857
|
+
}
|
|
858
|
+
});
|
|
859
|
+
if (options.extra) {
|
|
860
|
+
Object.entries(options.extra).forEach(([k, v]) => {
|
|
861
|
+
if (typeof v === "string" || typeof v === "number" || typeof v === "boolean") {
|
|
862
|
+
attributes[k] = v;
|
|
863
|
+
} else {
|
|
864
|
+
attributes[k] = JSON.stringify(v);
|
|
865
|
+
}
|
|
866
|
+
});
|
|
867
|
+
}
|
|
868
|
+
if (options.latency) {
|
|
869
|
+
attributes["latency_ms"] = options.latency;
|
|
870
|
+
attributes["latency"] = options.latency;
|
|
871
|
+
}
|
|
872
|
+
span.setAttributes(attributes);
|
|
873
|
+
span.setStatus({ code: spanStatus });
|
|
874
|
+
if (error && error !== "") {
|
|
875
|
+
if (error instanceof Error) {
|
|
876
|
+
span.recordException(error);
|
|
877
|
+
} else {
|
|
878
|
+
span.recordException(new Error(String(error)));
|
|
879
|
+
}
|
|
880
|
+
}
|
|
881
|
+
span.end(timestamp);
|
|
464
882
|
}
|
|
465
883
|
/**
|
|
466
|
-
* Capture a message
|
|
467
|
-
* Returns immediately (non-blocking)
|
|
884
|
+
* Capture a message
|
|
468
885
|
*/
|
|
469
886
|
captureMessage(message, options = {}) {
|
|
470
|
-
|
|
471
|
-
const event = this.createEventWithContext(message, {
|
|
472
|
-
level: "info",
|
|
473
|
-
...options
|
|
474
|
-
});
|
|
475
|
-
this.queue.add(event);
|
|
887
|
+
this.captureException(message, { ...options, level: options.level || "info" });
|
|
476
888
|
}
|
|
477
|
-
/**
|
|
478
|
-
* Set the current user ID
|
|
479
|
-
* Will be included in all subsequent events
|
|
480
|
-
*/
|
|
481
889
|
setUser(userId) {
|
|
482
890
|
this.userId = userId;
|
|
483
891
|
if (userId) {
|
|
@@ -486,62 +894,30 @@ ${error.stack ?? ""}` : String(error);
|
|
|
486
894
|
delete this.globalExtra["user_id"];
|
|
487
895
|
}
|
|
488
896
|
}
|
|
489
|
-
/**
|
|
490
|
-
* Set a global tag
|
|
491
|
-
* Will be included in all subsequent events
|
|
492
|
-
*/
|
|
493
897
|
setTag(key, value) {
|
|
494
898
|
this.globalTags[key] = value;
|
|
495
899
|
}
|
|
496
|
-
/**
|
|
497
|
-
* Set multiple global tags
|
|
498
|
-
* Will be included in all subsequent events
|
|
499
|
-
*/
|
|
500
900
|
setTags(tags) {
|
|
501
901
|
Object.assign(this.globalTags, tags);
|
|
502
902
|
}
|
|
503
|
-
/**
|
|
504
|
-
* Set global extra context
|
|
505
|
-
* Will be included in all subsequent events
|
|
506
|
-
*/
|
|
507
903
|
setExtra(key, value) {
|
|
508
904
|
this.globalExtra[key] = value;
|
|
509
905
|
}
|
|
510
|
-
/**
|
|
511
|
-
* Set multiple global extra context values
|
|
512
|
-
*/
|
|
513
906
|
setExtras(extras) {
|
|
514
907
|
Object.assign(this.globalExtra, extras);
|
|
515
908
|
}
|
|
516
|
-
/**
|
|
517
|
-
* Manually flush queued events
|
|
518
|
-
* Call this to ensure events are sent before process exit
|
|
519
|
-
*/
|
|
520
909
|
async flush() {
|
|
521
|
-
await this.
|
|
910
|
+
await this.provider.forceFlush();
|
|
522
911
|
}
|
|
523
|
-
/**
|
|
524
|
-
* Graceful shutdown
|
|
525
|
-
* Flushes remaining events and stops background workers
|
|
526
|
-
*/
|
|
527
912
|
async close() {
|
|
528
913
|
this.isInitialized = false;
|
|
529
|
-
this.
|
|
530
|
-
await this.flush();
|
|
531
|
-
if (this.config.debug) {
|
|
532
|
-
console.debug("[tracebeam] Closed");
|
|
533
|
-
}
|
|
914
|
+
await this.provider.shutdown();
|
|
534
915
|
}
|
|
535
|
-
/**
|
|
536
|
-
* Check if SDK is active and can capture events
|
|
537
|
-
*/
|
|
538
916
|
isActive() {
|
|
539
|
-
return this.isInitialized
|
|
917
|
+
return this.isInitialized;
|
|
540
918
|
}
|
|
541
|
-
// Private methods
|
|
542
919
|
canCapture() {
|
|
543
920
|
if (!this.isInitialized) return false;
|
|
544
|
-
if (!this.transport.isActive()) return false;
|
|
545
921
|
if (this.config.sampleRate < 1) {
|
|
546
922
|
if (Math.random() > this.config.sampleRate) {
|
|
547
923
|
return false;
|
|
@@ -549,32 +925,14 @@ ${error.stack ?? ""}` : String(error);
|
|
|
549
925
|
}
|
|
550
926
|
return true;
|
|
551
927
|
}
|
|
552
|
-
createEventWithContext(error, options) {
|
|
553
|
-
return createEvent(
|
|
554
|
-
this.config.projectId,
|
|
555
|
-
this.config.environment,
|
|
556
|
-
error,
|
|
557
|
-
options,
|
|
558
|
-
this.globalTags,
|
|
559
|
-
this.globalExtra
|
|
560
|
-
);
|
|
561
|
-
}
|
|
562
|
-
async handleFlush(events) {
|
|
563
|
-
if (events.length === 0) return;
|
|
564
|
-
try {
|
|
565
|
-
await this.transport.send(events);
|
|
566
|
-
} catch (error) {
|
|
567
|
-
if (this.config.debug) {
|
|
568
|
-
console.error("[tracebeam] Failed to flush events:", error);
|
|
569
|
-
}
|
|
570
|
-
}
|
|
571
|
-
}
|
|
572
928
|
};
|
|
573
929
|
// Annotate the CommonJS export names for ESM import in node:
|
|
574
930
|
0 && (module.exports = {
|
|
575
931
|
ConfigError,
|
|
576
932
|
DEFAULT_CONFIG,
|
|
577
933
|
TraceBeamSDK,
|
|
578
|
-
loadConfigFromEnv
|
|
934
|
+
loadConfigFromEnv,
|
|
935
|
+
mergeConfig,
|
|
936
|
+
validateConfig
|
|
579
937
|
});
|
|
580
938
|
//# sourceMappingURL=index.js.map
|