@sebspark/otel 4.1.17 → 4.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +39 -0
- package/dist/index.d.mts +0 -14
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +36 -66
- package/dist/index.mjs.map +1 -1
- package/package.json +39 -43
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,44 @@
|
|
|
1
1
|
# @sebspark/otel
|
|
2
2
|
|
|
3
|
+
## 4.2.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 7db408f: feat(opensearch): type `aggs`/`aggregations` in `SearchRequestBody<T>` against the index mapping. Restores `field` and `script` on `max`, `min`, `sum`, `avg`, `value_count`, `cardinality` and `terms`, which `@opensearch-project/opensearch` 3.9.0 dropped (opensearch-project/opensearch-js#1154). `field` on these and on `date_histogram`, `date_range` and `range` autocompletes paths from the mapping and accepts any other field name. `filter` takes an index-aware query, `top_hits` gets index-aware `sort`/`_source`, and sub-aggregations are typed recursively. Other aggregations keep their upstream types. `AggregationContainer<T>` is exported for typing individual aggregations.
|
|
8
|
+
|
|
9
|
+
feat(opensearch): the typing never blocks a request OpenSearch accepts. Fields that are not in the mapping (e.g. added by dynamic mapping) are accepted in `query`, `sort`, `_source`, `collapse`, `highlight`, aggregation `field`/`filter` and `top_hits` `sort`/`_source`; mapped fields still autocomplete. `DocumentFor<T>` accepts fields that are not in the mapping as `unknown`, so `index`, `bulk` and the bulk helpers take documents with extra fields. A generic `SearchRequest<T>` can be passed to the upstream `Client`.
|
|
10
|
+
|
|
11
|
+
fix(opensearch): sort accepts the direction shorthand (`{ age: 'desc' }`), `knn_vector` fields map to `number[]` in `DocumentFor`, `knn.filter` is a single query instead of an array, and `script_score.query` is required. OpenSearch rejects both an array `knn.filter` and a `script_score` without `query`, so only requests that already failed at runtime stop compiling. To migrate, combine several knn filters in one `bool` query (`filter: { bool: { filter: [...] } }`), and add `query: { match_all: {} }` to a `script_score` that had none.
|
|
12
|
+
|
|
13
|
+
chore(deps): update dependencies
|
|
14
|
+
- `@google-cloud/pubsub` 6.3.1 → 6.3.2
|
|
15
|
+
- `@inquirer/figures` 2.0.9 → 2.0.10
|
|
16
|
+
- `@inquirer/prompts` 8.7.4 → 8.7.5
|
|
17
|
+
- `@opentelemetry/semantic-conventions` 1.43.0 → 1.44.0
|
|
18
|
+
- `redis` 6.3.0 → 6.3.1
|
|
19
|
+
- `tsdown` 0.23.1 → 0.23.4
|
|
20
|
+
|
|
21
|
+
fix: dependency issues found by knip
|
|
22
|
+
- `@sebspark/promise-cache`: drop the unused `@sebspark/otel`
|
|
23
|
+
- `@sebspark/socket.io-gcp-pubsub-emitter`: drop the unused `uuid`
|
|
24
|
+
- `@sebspark/memredis`: derive `GetExOptions` from `redis` instead of importing the unlisted `@redis/client` internals
|
|
25
|
+
|
|
26
|
+
fix(test-iap): the default base image of `TestIapContainer` is now `node:26.13.0-alpine`, pinned by digest, instead of the floating `node:22-alpine`. Use `withBaseImage()` to choose another image.
|
|
27
|
+
|
|
28
|
+
- Updated dependencies [7db408f]
|
|
29
|
+
- @sebspark/opentelemetry-instrumentation-opensearch@0.4.1
|
|
30
|
+
|
|
31
|
+
## 4.2.0
|
|
32
|
+
|
|
33
|
+
### Minor Changes
|
|
34
|
+
|
|
35
|
+
- ad1e80f: Upgraded to OpenTelemetry 3.0 (`@opentelemetry/api` 1.10).
|
|
36
|
+
|
|
37
|
+
### Patch Changes
|
|
38
|
+
|
|
39
|
+
- Updated dependencies [ad1e80f]
|
|
40
|
+
- @sebspark/opentelemetry-instrumentation-opensearch@0.4.0
|
|
41
|
+
|
|
3
42
|
## 4.1.17
|
|
4
43
|
|
|
5
44
|
### Patch Changes
|
package/dist/index.d.mts
CHANGED
|
@@ -9,10 +9,7 @@ import { SocketIoInstrumentationConfig } from "@opentelemetry/instrumentation-so
|
|
|
9
9
|
import { OpenSearchInstrumentationConfig } from "@sebspark/opentelemetry-instrumentation-opensearch";
|
|
10
10
|
import "@opentelemetry/instrumentation-http";
|
|
11
11
|
import "@opentelemetry/instrumentation-undici";
|
|
12
|
-
//#region src/enrichments/outgoing-http/consts.d.ts
|
|
13
12
|
declare const PROTOCOLS: readonly ['https', 'http'];
|
|
14
|
-
//#endregion
|
|
15
|
-
//#region src/enrichments/outgoing-http/types.d.ts
|
|
16
13
|
type Protocol = (typeof PROTOCOLS)[number];
|
|
17
14
|
interface NormalisedRequest {
|
|
18
15
|
method: string;
|
|
@@ -49,8 +46,6 @@ interface OutgoingHttpEnrichmentConfig extends InstrumentationConfig {
|
|
|
49
46
|
*/
|
|
50
47
|
ignoreOutgoingPaths?: string[];
|
|
51
48
|
}
|
|
52
|
-
//#endregion
|
|
53
|
-
//#region src/instrumentations.d.ts
|
|
54
49
|
export declare const instrumentations: {
|
|
55
50
|
readonly http: (config?: OutgoingHttpEnrichmentConfig) => Promise<Instrumentation<InstrumentationConfig>>;
|
|
56
51
|
readonly express: (config?: ExpressInstrumentationConfig) => Promise<Instrumentation<InstrumentationConfig>>;
|
|
@@ -63,8 +58,6 @@ export declare const instrumentations: {
|
|
|
63
58
|
readonly socketIo: (config?: SocketIoInstrumentationConfig) => Promise<Instrumentation<InstrumentationConfig>>;
|
|
64
59
|
readonly opensearch: (config?: OpenSearchInstrumentationConfig) => Promise<Instrumentation<InstrumentationConfig>>;
|
|
65
60
|
};
|
|
66
|
-
//#endregion
|
|
67
|
-
//#region src/logger.d.ts
|
|
68
61
|
type Attrs = Record<string, any>;
|
|
69
62
|
export type Logger = ReturnType<typeof getLogger>;
|
|
70
63
|
export declare function getLogger(serviceOverride?: string, extraAttrs?: Attrs): {
|
|
@@ -109,16 +102,10 @@ export declare function getLogger(serviceOverride?: string, extraAttrs?: Attrs):
|
|
|
109
102
|
(error: Error, attrs?: Attrs): void;
|
|
110
103
|
};
|
|
111
104
|
};
|
|
112
|
-
//#endregion
|
|
113
|
-
//#region src/metrics.d.ts
|
|
114
105
|
export declare function getMeter(componentNameOverride?: string): import("@opentelemetry/api").Meter;
|
|
115
|
-
//#endregion
|
|
116
|
-
//#region src/otel.d.ts
|
|
117
106
|
export declare function initialize(...instrumentations: Promise<Instrumentation>[]): Promise<void>;
|
|
118
107
|
export declare function isInitialized(): boolean;
|
|
119
108
|
export declare const dispose: () => Promise<void>;
|
|
120
|
-
//#endregion
|
|
121
|
-
//#region src/tracer.d.ts
|
|
122
109
|
type OtelTracer = ReturnType<typeof trace.getTracer>;
|
|
123
110
|
type Span$2 = ReturnType<OtelTracer['startSpan']>;
|
|
124
111
|
type Func<T> = (span: Span$2) => Promise<T> | T;
|
|
@@ -150,6 +137,5 @@ interface Tracer extends OtelTracer {
|
|
|
150
137
|
* @returns Tracer with helpers
|
|
151
138
|
*/
|
|
152
139
|
export declare function getTracer(componentNameOverride?: string): Tracer;
|
|
153
|
-
//#endregion
|
|
154
140
|
export { type Context, type Counter, type Gauge, type Histogram, type Meter, type ObservableCounter, type ObservableGauge, type ObservableUpDownCounter, type Span, type SpanStatus, SpanStatusCode, type UpDownCounter, context };
|
|
155
141
|
//# sourceMappingURL=index.d.mts.map
|
package/dist/index.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/enrichments/outgoing-http/consts.ts","../src/enrichments/outgoing-http/types.ts","../src/instrumentations.ts","../src/logger.ts","../src/metrics.ts","../src/otel.ts","../src/tracer.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":["Span","Span"],"sources":["../src/enrichments/outgoing-http/consts.ts","../src/enrichments/outgoing-http/types.ts","../src/instrumentations.ts","../src/logger.ts","../src/metrics.ts","../src/otel.ts","../src/tracer.ts"],"mappings":";;;;;;;;;;;cA0Ba;KCtBD,mBAAmB;UASd;EACf;EACA;EACA;;EAEA;EACA,UAAU;;EAEV,UAAU;;UAeK,qCAAqC;;;;;EAKpD;;EAGA;;;;;;EAOA,cAAc,MAAMA,QAAM,SAAS;;;;;EAMnC;;;;;EAMA;;qBCpCW;WACX,OAAI,SAAU,iCAA4B,QAAA,gBAAA;WAe1C,UAAO,SAAU,iCAA4B,QAAA,gBAAA;WAc7C,OAAI,SAAU,8BAAyB,QAAA,gBAAA;WAcvC,QAAK,SAAU,+BAA0B,QAAA,gBAAA;WAczC,MAAG,SAAU,6BAAwB,QAAA,gBAAA;WAcrC,MAAG,SAAU,0BAAqB,QAAA,gBAAA;WAclC,KAAE,SAAU,4BAAuB,QAAA,gBAAA;WAcnC,SAAM,SAAU,iCAA4B,QAAA,gBAAA;WAe5C,WAAQ,SAAU,kCAA6B,QAAA,gBAAA;WAc/C,aAAU,SAAU,oCAA+B,QAAA,gBAAA;;KCtJhD,QAAQ;YAED,SAAS,kBAAkB;wBACvB,UAAU,0BAA0B,aAAY;EAkF5D;KAjBM,aAAM,QAAU;KAChB,aAAM,OAAS,OAAK,QAAU;KAC5B,OAAA,OAAK,QAAU;;EAgBvB;;;;;EACA;;;;;EACA;;;;;EACA;;;;;EACA;;;;;EACA;;;;;EACA;;;;;;wBC9FY,SAAS,8DAA8B;wBC0BjC,cACjB,kBAAkB,QAAQ,qBAAkB;wBAejC;qBAsCH,eAAO;KC3Ef,aAAa,kBAAkB,MAAM;KACrCC,SAAO,WAAW;KAElB,KAAK,MAAM,MAAMA,WAAS,QAAQ,KAAK;KACvC,SAAS,MAAM,MAAMA,WAAS;KAE9B;GACF,GAAG,cAAc,IAAI,KAAK,KAAK,QAAQ;GACvC,GAAG,cAAc,SAAS,aAAa,IAAI,KAAK,KAAK,QAAQ;GAC7D,GAAG,cAAc,QAAQA,QAAM,IAAI,KAAK,KAAK,QAAQ;GACrD,GAAG,cAAc,SAAS,aAAa,QAAQA,QAAM,IAAI,KAAK,KAAK,QAAQ;;KAEzE;GACF,GAAG,cAAc,IAAI,SAAS,KAAK;GACnC,GAAG,cAAc,SAAS,aAAa,IAAI,SAAS,KAAK;GACzD,GAAG,cAAc,QAAQA,QAAM,IAAI,SAAS,KAAK;GACjD,GAAG,cAAc,SAAS,aAAa,QAAQA,QAAM,IAAI,SAAS,KAAK;;;;;UAMhE,eAAe;EACvB,WAAW;EACX,eAAe;;;;;;;;;wBAUD,UAAU,iCAAiC"}
|
package/dist/index.mjs
CHANGED
|
@@ -1,20 +1,19 @@
|
|
|
1
|
-
import { DiagConsoleLogger, DiagLogLevel, SpanStatusCode, SpanStatusCode as SpanStatusCode$1, context, context as context$1, diag, metrics, trace } from "@opentelemetry/api";
|
|
1
|
+
import { DiagConsoleLogger, DiagLogLevel, SeverityNumber, SpanStatusCode, SpanStatusCode as SpanStatusCode$1, context, context as context$1, diag, logs, metrics, trace } from "@opentelemetry/api";
|
|
2
2
|
import { ATTR_ERROR_TYPE, ATTR_HTTP_REQUEST_METHOD, ATTR_HTTP_RESPONSE_STATUS_CODE, ATTR_NETWORK_PEER_ADDRESS, ATTR_NETWORK_PEER_PORT, ATTR_NETWORK_PROTOCOL_VERSION, ATTR_SERVER_ADDRESS, ATTR_SERVER_PORT, ATTR_SERVICE_NAME, ATTR_SERVICE_VERSION, ATTR_URL_FULL, ATTR_URL_PATH, ATTR_URL_QUERY, ATTR_URL_SCHEME } from "@opentelemetry/semantic-conventions";
|
|
3
|
-
import { SeverityNumber, logs } from "@opentelemetry/api-logs";
|
|
4
3
|
import { NodeSDK } from "@opentelemetry/sdk-node";
|
|
5
4
|
import { OTLPLogExporter } from "@opentelemetry/exporter-logs-otlp-http";
|
|
6
5
|
import { OTLPMetricExporter } from "@opentelemetry/exporter-metrics-otlp-http";
|
|
7
6
|
import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http";
|
|
8
7
|
import { BatchLogRecordProcessor, LoggerProvider, SimpleLogRecordProcessor } from "@opentelemetry/sdk-logs";
|
|
9
8
|
import { PeriodicExportingMetricReader } from "@opentelemetry/sdk-metrics";
|
|
10
|
-
import { BatchSpanProcessor, SimpleSpanProcessor } from "@opentelemetry/sdk-trace
|
|
9
|
+
import { BatchSpanProcessor, SimpleSpanProcessor } from "@opentelemetry/sdk-trace";
|
|
11
10
|
import { ExportResultCode } from "@opentelemetry/core";
|
|
12
11
|
import fss from "fast-safe-stringify";
|
|
13
12
|
import kleur from "kleur";
|
|
14
13
|
import { containerDetector } from "@opentelemetry/resource-detector-container";
|
|
15
14
|
import { gcpDetector } from "@opentelemetry/resource-detector-gcp";
|
|
16
15
|
import { detectResources, envDetector, osDetector, processDetector, resourceFromAttributes, serviceInstanceIdDetector } from "@opentelemetry/resources";
|
|
17
|
-
|
|
16
|
+
// src/enrichments/outgoing-http/consts.ts
|
|
18
17
|
const ATTR_HTTP_REQUEST_BODY_SIZE = "http.request.body.size";
|
|
19
18
|
const ATTR_HTTP_RESPONSE_BODY_SIZE = "http.response.body.size";
|
|
20
19
|
const DEFAULT_REQUEST_HEADERS = [
|
|
@@ -34,8 +33,7 @@ const DEFAULT_RESPONSE_HEADERS = [
|
|
|
34
33
|
"x-ratelimit-reset",
|
|
35
34
|
"retry-after"
|
|
36
35
|
];
|
|
37
|
-
|
|
38
|
-
//#region src/enrichments/outgoing-http/apply-attributes.ts
|
|
36
|
+
// src/enrichments/outgoing-http/apply-attributes.ts
|
|
39
37
|
const requestHeaderAttr = (h) => `http.request.header.${h.toLowerCase().replace(/-/g, "_")}`;
|
|
40
38
|
const responseHeaderAttr = (h) => `http.response.header.${h.toLowerCase().replace(/-/g, "_")}`;
|
|
41
39
|
const applyRequestAttributes = (span, req, cfg) => {
|
|
@@ -82,8 +80,7 @@ const applyResponseAttributes = (span, res, cfg) => {
|
|
|
82
80
|
if (res.remoteAddress) span.setAttribute(ATTR_NETWORK_PEER_ADDRESS, res.remoteAddress);
|
|
83
81
|
if (res.remotePort) span.setAttribute(ATTR_NETWORK_PEER_PORT, res.remotePort);
|
|
84
82
|
};
|
|
85
|
-
|
|
86
|
-
//#region src/enrichments/outgoing-http/helpers.ts
|
|
83
|
+
// src/enrichments/outgoing-http/helpers.ts
|
|
87
84
|
const resolve = (opts) => ({
|
|
88
85
|
captureRequestHeaders: opts.captureRequestHeaders ?? DEFAULT_REQUEST_HEADERS,
|
|
89
86
|
captureResponseHeaders: opts.captureResponseHeaders ?? DEFAULT_RESPONSE_HEADERS,
|
|
@@ -93,8 +90,7 @@ const resolve = (opts) => ({
|
|
|
93
90
|
});
|
|
94
91
|
const isClientRequest = (req) => typeof req.getHeader === "function";
|
|
95
92
|
const isIncomingMessage = (res) => res != null && typeof res === "object" && "statusCode" in res && "headers" in res;
|
|
96
|
-
|
|
97
|
-
//#region src/enrichments/outgoing-http/normalize-http.ts
|
|
93
|
+
// src/enrichments/outgoing-http/normalize-http.ts
|
|
98
94
|
const normHttpRequest = (req) => {
|
|
99
95
|
const hostname = String(req.hostname ?? req.host ?? "").split(":")[0];
|
|
100
96
|
const port = Number(req.port ?? req.defaultPort ?? 80);
|
|
@@ -137,13 +133,12 @@ const getHeaderFromObject = (headers, name) => {
|
|
|
137
133
|
return;
|
|
138
134
|
}
|
|
139
135
|
};
|
|
140
|
-
|
|
141
|
-
//#region src/enrichments/outgoing-http/build-http-config.ts
|
|
136
|
+
// src/enrichments/outgoing-http/build-http-config.ts
|
|
142
137
|
/**
|
|
143
138
|
* Build an HttpInstrumentationConfig that applies shared enrichment logic.
|
|
144
139
|
*
|
|
145
140
|
* The returned config can be spread with your own additional options:
|
|
146
|
-
* new HttpInstrumentation({ ...buildHttpConfig(opts),
|
|
141
|
+
* new HttpInstrumentation({ ...buildHttpConfig(opts), requireParentforOutgoingSpans: true })
|
|
147
142
|
*/
|
|
148
143
|
const buildHttpConfig = (opts = {}) => {
|
|
149
144
|
const cfg = resolve(opts);
|
|
@@ -195,8 +190,7 @@ const buildHttpConfig = (opts = {}) => {
|
|
|
195
190
|
}
|
|
196
191
|
};
|
|
197
192
|
};
|
|
198
|
-
|
|
199
|
-
//#region src/enrichments/outgoing-http/normalize-undici.ts
|
|
193
|
+
// src/enrichments/outgoing-http/normalize-undici.ts
|
|
200
194
|
const normUndiciRequest = (req) => {
|
|
201
195
|
const origin = new URL(req.origin);
|
|
202
196
|
const protocol = origin.protocol.replace(":", "");
|
|
@@ -249,8 +243,7 @@ const parseUndiciRequestHeaders = (headers) => {
|
|
|
249
243
|
}
|
|
250
244
|
return result;
|
|
251
245
|
};
|
|
252
|
-
|
|
253
|
-
//#region src/enrichments/outgoing-http/build-undici-config.ts
|
|
246
|
+
// src/enrichments/outgoing-http/build-undici-config.ts
|
|
254
247
|
/**
|
|
255
248
|
* Build an UndiciInstrumentationConfig that applies shared enrichment logic.
|
|
256
249
|
*
|
|
@@ -273,11 +266,9 @@ function buildUndiciConfig(opts = {}) {
|
|
|
273
266
|
}
|
|
274
267
|
};
|
|
275
268
|
}
|
|
276
|
-
|
|
277
|
-
//#region src/enrichments/outgoing-http/index.ts
|
|
269
|
+
// src/enrichments/outgoing-http/index.ts
|
|
278
270
|
/* istanbul ignore file */
|
|
279
|
-
|
|
280
|
-
//#region src/instrumentations.ts
|
|
271
|
+
// src/instrumentations.ts
|
|
281
272
|
const cache = /* @__PURE__ */ new Map();
|
|
282
273
|
const cacheKey = (instrumentationName, config) => {
|
|
283
274
|
return config ? `${instrumentationName}:${JSON.stringify(config)}` : instrumentationName;
|
|
@@ -337,8 +328,7 @@ const instrumentations = {
|
|
|
337
328
|
return cache.get(key);
|
|
338
329
|
}
|
|
339
330
|
};
|
|
340
|
-
|
|
341
|
-
//#region src/consts.ts
|
|
331
|
+
// src/consts.ts
|
|
342
332
|
const LOG_SEVERITY_MAP = {
|
|
343
333
|
TRACE: 1,
|
|
344
334
|
DEBUG: 5,
|
|
@@ -352,8 +342,7 @@ const LOG_SEVERITY_MAP = {
|
|
|
352
342
|
ALERT: 22,
|
|
353
343
|
EMERGENCY: 23
|
|
354
344
|
};
|
|
355
|
-
|
|
356
|
-
//#region src/loggers/formatters/style.ts
|
|
345
|
+
// src/loggers/formatters/style.ts
|
|
357
346
|
const colors = {
|
|
358
347
|
gray: kleur.gray,
|
|
359
348
|
dim: kleur.dim,
|
|
@@ -389,8 +378,7 @@ const statusColorMap = {
|
|
|
389
378
|
2: colors.red
|
|
390
379
|
};
|
|
391
380
|
colors.white, colors.cyan, colors.yellow, colors.magenta, colors.green;
|
|
392
|
-
|
|
393
|
-
//#region src/loggers/formatters/shared.ts
|
|
381
|
+
// src/loggers/formatters/shared.ts
|
|
394
382
|
const stringify = fss.default.stableStringify;
|
|
395
383
|
function formatTimestamp(time) {
|
|
396
384
|
const date = new Date(hrTimeToMillis(time));
|
|
@@ -433,14 +421,12 @@ function calculateDuration(span) {
|
|
|
433
421
|
const end = hrTimeToMillis(span.endTime);
|
|
434
422
|
return Math.max(0, Math.round(end - start));
|
|
435
423
|
}
|
|
436
|
-
|
|
437
|
-
//#region src/loggers/formatters/log-record.ts
|
|
424
|
+
// src/loggers/formatters/log-record.ts
|
|
438
425
|
function formatLogRecord(record) {
|
|
439
426
|
const timestamp = formatTimestamp(record.hrTime);
|
|
440
427
|
return `${formatService(record.resource)} ${timestamp} ${formatLevel(record)} ${formatScope(record.resource, record.instrumentationScope)}${formatMessage(record)}${formatAttributes(record.attributes)}`;
|
|
441
428
|
}
|
|
442
|
-
|
|
443
|
-
//#region src/loggers/formatters/metrics.ts
|
|
429
|
+
// src/loggers/formatters/metrics.ts
|
|
444
430
|
function formatMetrics(resourceMetrics) {
|
|
445
431
|
const { resource, scopeMetrics } = resourceMetrics;
|
|
446
432
|
return scopeMetrics.map((scopeMetric) => formatScopeMetric(scopeMetric, resource)).join("\n");
|
|
@@ -469,8 +455,7 @@ function extractMetricValue(dp) {
|
|
|
469
455
|
function isHistogramLike(val) {
|
|
470
456
|
return typeof val === "object" && val !== null && "sum" in val && typeof val.sum === "number";
|
|
471
457
|
}
|
|
472
|
-
|
|
473
|
-
//#region src/loggers/formatters/span.ts
|
|
458
|
+
// src/loggers/formatters/span.ts
|
|
474
459
|
const LABEL_WIDTH = 20;
|
|
475
460
|
const DESCRIPTION_MAX_WIDTH = 16;
|
|
476
461
|
const BAR_MIN_WIDTH = 1;
|
|
@@ -571,11 +556,9 @@ function computeDepth(span, allSpans) {
|
|
|
571
556
|
}
|
|
572
557
|
return depth;
|
|
573
558
|
}
|
|
574
|
-
|
|
575
|
-
//#region src/loggers/formatters/index.ts
|
|
559
|
+
// src/loggers/formatters/index.ts
|
|
576
560
|
/* istanbul ignore file */
|
|
577
|
-
|
|
578
|
-
//#region src/loggers/console-metric-pretty-exporter.ts
|
|
561
|
+
// src/loggers/console-metric-pretty-exporter.ts
|
|
579
562
|
var ConsoleMetricPrettyExporter = class {
|
|
580
563
|
patterns;
|
|
581
564
|
constructor() {
|
|
@@ -614,8 +597,7 @@ function globToRegex(glob) {
|
|
|
614
597
|
const regex = `^${glob.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*")}$`;
|
|
615
598
|
return new RegExp(regex);
|
|
616
599
|
}
|
|
617
|
-
|
|
618
|
-
//#region src/loggers/console-log-pretty-exporter.ts
|
|
600
|
+
// src/loggers/console-log-pretty-exporter.ts
|
|
619
601
|
var ConsoleLogPrettyExporter = class {
|
|
620
602
|
logThreshold;
|
|
621
603
|
constructor() {
|
|
@@ -646,8 +628,7 @@ var ConsoleLogPrettyExporter = class {
|
|
|
646
628
|
done?.({ code: ExportResultCode.SUCCESS });
|
|
647
629
|
}
|
|
648
630
|
};
|
|
649
|
-
|
|
650
|
-
//#region src/loggers/console-span-pretty-exporter.ts
|
|
631
|
+
// src/loggers/console-span-pretty-exporter.ts
|
|
651
632
|
var ConsoleSpanPrettyExporter = class {
|
|
652
633
|
allowedStatuses;
|
|
653
634
|
constructor() {
|
|
@@ -678,11 +659,9 @@ var ConsoleSpanPrettyExporter = class {
|
|
|
678
659
|
return Promise.resolve();
|
|
679
660
|
}
|
|
680
661
|
};
|
|
681
|
-
|
|
682
|
-
//#region src/loggers/index.ts
|
|
662
|
+
// src/loggers/index.ts
|
|
683
663
|
/* istanbul ignore file */
|
|
684
|
-
|
|
685
|
-
//#region src/loggers/tree-span-processor.ts
|
|
664
|
+
// src/loggers/tree-span-processor.ts
|
|
686
665
|
var TreeSpanProcessor = class {
|
|
687
666
|
exporter;
|
|
688
667
|
orphans = /* @__PURE__ */ new Map();
|
|
@@ -720,8 +699,7 @@ var TreeSpanProcessor = class {
|
|
|
720
699
|
await this.exporter.forceFlush?.();
|
|
721
700
|
}
|
|
722
701
|
};
|
|
723
|
-
|
|
724
|
-
//#region src/providers.ts
|
|
702
|
+
// src/providers.ts
|
|
725
703
|
const getLogProvider = (resource, otlpEndpoint) => {
|
|
726
704
|
if (otlpEndpoint) {
|
|
727
705
|
const otlpExporter = new OTLPLogExporter({ url: `${otlpEndpoint}/v1/logs` });
|
|
@@ -747,16 +725,15 @@ const getSpanProcessor = (otlpEndpoint) => {
|
|
|
747
725
|
if (!otlpEndpoint) return new TreeSpanProcessor(exporter);
|
|
748
726
|
if (process.env.OTEL_SIMPLE_SPAN_PROCESSOR === "true") {
|
|
749
727
|
console.log("[otel] Using SimpleSpanProcessor (OTEL_SIMPLE_SPAN_PROCESSOR=true)");
|
|
750
|
-
return new SimpleSpanProcessor(exporter);
|
|
728
|
+
return new SimpleSpanProcessor({ exporter });
|
|
751
729
|
}
|
|
752
|
-
return new BatchSpanProcessor(exporter);
|
|
730
|
+
return new BatchSpanProcessor({ exporter });
|
|
753
731
|
};
|
|
754
732
|
const getMetricReader = (otlpEndpoint) => {
|
|
755
733
|
const metricExporter = otlpEndpoint ? new OTLPMetricExporter({ url: `${otlpEndpoint}/v1/metrics` }) : new ConsoleMetricPrettyExporter();
|
|
756
734
|
return new PeriodicExportingMetricReader({ exporter: metricExporter });
|
|
757
735
|
};
|
|
758
|
-
|
|
759
|
-
//#region src/otel-context.ts
|
|
736
|
+
// src/otel-context.ts
|
|
760
737
|
/**
|
|
761
738
|
* Extracts telemetry context from environment (cloud/k8s aware),
|
|
762
739
|
* with support for subservice/component override.
|
|
@@ -787,8 +764,7 @@ function detectTelemetryContext(componentNameOverride) {
|
|
|
787
764
|
}
|
|
788
765
|
};
|
|
789
766
|
}
|
|
790
|
-
|
|
791
|
-
//#region src/resource.ts
|
|
767
|
+
// src/resource.ts
|
|
792
768
|
const isOnGcp = () => !!(process.env.K_SERVICE || process.env.GAE_APPLICATION || process.env.KUBERNETES_SERVICE_HOST);
|
|
793
769
|
const getResource = async () => {
|
|
794
770
|
const baseRes = detectResources({ detectors: [
|
|
@@ -806,8 +782,7 @@ const getResource = async () => {
|
|
|
806
782
|
if (resource.waitForAsyncAttributes) await resource.waitForAsyncAttributes();
|
|
807
783
|
return resource;
|
|
808
784
|
};
|
|
809
|
-
|
|
810
|
-
//#region src/otel.ts
|
|
785
|
+
// src/otel.ts
|
|
811
786
|
diag.disable();
|
|
812
787
|
diag.setLogger(new DiagConsoleLogger(), DiagLogLevel.ERROR);
|
|
813
788
|
const OTEL_INIT_KEY = Symbol.for("@sebspark/otel:initialized");
|
|
@@ -844,8 +819,8 @@ async function _initialize(instrumentations) {
|
|
|
844
819
|
const spanProcessor = getSpanProcessor(otlpEndpoint);
|
|
845
820
|
const metricReader = getMetricReader(otlpEndpoint);
|
|
846
821
|
sdk = new NodeSDK({
|
|
847
|
-
spanProcessor,
|
|
848
|
-
metricReader,
|
|
822
|
+
spanProcessors: [spanProcessor],
|
|
823
|
+
metricReaders: [metricReader],
|
|
849
824
|
instrumentations,
|
|
850
825
|
resource
|
|
851
826
|
});
|
|
@@ -865,8 +840,7 @@ const dispose = async () => {
|
|
|
865
840
|
console.log("[otel] Shutdown complete.");
|
|
866
841
|
}
|
|
867
842
|
};
|
|
868
|
-
|
|
869
|
-
//#region src/logger.ts
|
|
843
|
+
// src/logger.ts
|
|
870
844
|
function getLogger(serviceOverride, extraAttrs = {}) {
|
|
871
845
|
const { systemName, systemVersion, resourceAttributes } = detectTelemetryContext(serviceOverride);
|
|
872
846
|
const defaultAttrs = {
|
|
@@ -927,15 +901,13 @@ function getLogger(serviceOverride, extraAttrs = {}) {
|
|
|
927
901
|
emergency: createLogFn("EMERGENCY")
|
|
928
902
|
};
|
|
929
903
|
}
|
|
930
|
-
|
|
931
|
-
//#region src/metrics.ts
|
|
904
|
+
// src/metrics.ts
|
|
932
905
|
function getMeter(componentNameOverride) {
|
|
933
906
|
if (!isInitialized() && process.env.NODE_ENV !== "test") console.warn("OTEL must be initialized before using getMeter()");
|
|
934
907
|
const { componentName, systemName, systemVersion } = detectTelemetryContext(componentNameOverride);
|
|
935
908
|
return metrics.getMeter(componentName ?? systemName, systemVersion);
|
|
936
909
|
}
|
|
937
|
-
|
|
938
|
-
//#region src/tracer.ts
|
|
910
|
+
// src/tracer.ts
|
|
939
911
|
/**
|
|
940
912
|
* Returns an OpenTelemetry tracer bound to the current service.
|
|
941
913
|
* Includes `withTrace()` and `withTraceSync()` helpers for span-wrapped execution.
|
|
@@ -1046,10 +1018,8 @@ const isFunction = (value) => typeof value === "function";
|
|
|
1046
1018
|
const isSpan = (value) => value !== null && value !== void 0 && isFunction(value.spanContext) && isFunction(value.end);
|
|
1047
1019
|
/* istanbul ignore next */
|
|
1048
1020
|
const isSpanOptions = (value) => value !== null && value !== void 0 && (!!value.startTime || !!value.attributes || !!value.kind) && !isSpan(value);
|
|
1049
|
-
|
|
1050
|
-
//#region src/index.ts
|
|
1021
|
+
// src/index.ts
|
|
1051
1022
|
/* istanbul ignore file */
|
|
1052
|
-
//#endregion
|
|
1053
1023
|
export { SpanStatusCode, context, dispose, getLogger, getMeter, getTracer, initialize, instrumentations, isInitialized };
|
|
1054
1024
|
|
|
1055
1025
|
//# sourceMappingURL=index.mjs.map
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":["SpanStatusCode","SpanStatusCode","SpanStatusCode","context","context","SpanStatusCode"],"sources":["../src/enrichments/outgoing-http/consts.ts","../src/enrichments/outgoing-http/apply-attributes.ts","../src/enrichments/outgoing-http/helpers.ts","../src/enrichments/outgoing-http/normalize-http.ts","../src/enrichments/outgoing-http/build-http-config.ts","../src/enrichments/outgoing-http/normalize-undici.ts","../src/enrichments/outgoing-http/build-undici-config.ts","../src/enrichments/outgoing-http/index.ts","../src/instrumentations.ts","../src/consts.ts","../src/loggers/formatters/style.ts","../src/loggers/formatters/shared.ts","../src/loggers/formatters/log-record.ts","../src/loggers/formatters/metrics.ts","../src/loggers/formatters/span.ts","../src/loggers/formatters/index.ts","../src/loggers/console-metric-pretty-exporter.ts","../src/loggers/console-log-pretty-exporter.ts","../src/loggers/console-span-pretty-exporter.ts","../src/loggers/index.ts","../src/loggers/tree-span-processor.ts","../src/providers.ts","../src/otel-context.ts","../src/resource.ts","../src/otel.ts","../src/logger.ts","../src/metrics.ts","../src/tracer.ts","../src/index.ts"],"sourcesContent":["// Incubating attrs — copied as string literals per OTel JS team recommendation:\n// importing from /incubating at runtime is explicitly discouraged because that\n// entry-point is NOT subject to semver and may break in minor releases.\n// https://github.com/open-telemetry/opentelemetry-js/tree/main/packages/opentelemetry-semantic-conventions#unstable-semconv\nexport const ATTR_HTTP_REQUEST_BODY_SIZE = 'http.request.body.size'\nexport const ATTR_HTTP_RESPONSE_BODY_SIZE = 'http.response.body.size'\n\nexport const DEFAULT_REQUEST_HEADERS: string[] = [\n 'content-type',\n 'accept',\n 'x-request-id',\n 'x-correlation-id',\n 'traceparent',\n 'tracestate',\n] as const\n\nexport const DEFAULT_RESPONSE_HEADERS: string[] = [\n 'content-type',\n 'x-request-id',\n 'x-correlation-id',\n 'x-ratelimit-limit',\n 'x-ratelimit-remaining',\n 'x-ratelimit-reset',\n 'retry-after',\n] as const\n\nexport const PROTOCOLS = ['https', 'http'] as const\n","import { type Span, SpanStatusCode } from '@opentelemetry/api'\nimport {\n ATTR_ERROR_TYPE,\n ATTR_HTTP_REQUEST_METHOD,\n ATTR_HTTP_RESPONSE_STATUS_CODE,\n ATTR_NETWORK_PEER_ADDRESS,\n ATTR_NETWORK_PEER_PORT,\n ATTR_SERVER_ADDRESS,\n ATTR_SERVER_PORT,\n ATTR_URL_FULL,\n ATTR_URL_PATH,\n ATTR_URL_QUERY,\n ATTR_URL_SCHEME,\n} from '@opentelemetry/semantic-conventions'\nimport {\n ATTR_HTTP_REQUEST_BODY_SIZE,\n ATTR_HTTP_RESPONSE_BODY_SIZE,\n} from './consts'\nimport type {\n NormalisedRequest,\n NormalisedResponse,\n ResolvedConfig,\n} from './types'\n\nconst requestHeaderAttr = (h: string) =>\n `http.request.header.${h.toLowerCase().replace(/-/g, '_')}`\nconst responseHeaderAttr = (h: string) =>\n `http.response.header.${h.toLowerCase().replace(/-/g, '_')}`\n\nexport const applyRequestAttributes = (\n span: Span,\n req: NormalisedRequest,\n cfg: ResolvedConfig\n): void => {\n const { method, hostname, port, path, protocol } = req\n const [urlPath, urlQuery] = path.split('?')\n /* istanbul ignore next */\n const defaultPort = protocol === 'https' ? 443 : 80\n /* istanbul ignore next */\n const portSuffix = port !== defaultPort ? `:${port}` : ''\n /* istanbul ignore next */\n const resolvedUrlPath = urlPath ?? '/'\n\n // Stable semconv v1.23+ attributes\n span.setAttributes({\n [ATTR_HTTP_REQUEST_METHOD]: method.toUpperCase(),\n [ATTR_SERVER_ADDRESS]: hostname,\n [ATTR_SERVER_PORT]: port,\n [ATTR_URL_SCHEME]: protocol,\n [ATTR_URL_PATH]: resolvedUrlPath,\n [ATTR_URL_FULL]: `${protocol}://${hostname}${portSuffix}${path}`,\n })\n\n if (urlQuery) {\n span.setAttribute(ATTR_URL_QUERY, urlQuery)\n }\n\n if (cfg.useDescriptiveSpanNames) {\n span.updateName(`${method.toUpperCase()} ${hostname}${resolvedUrlPath}`)\n }\n\n for (const header of cfg.captureRequestHeaders) {\n const value = req.getHeader(header)\n if (value !== undefined) {\n span.setAttribute(requestHeaderAttr(header), value)\n }\n }\n\n const contentLength = req.getHeader('content-length')\n if (contentLength !== undefined) {\n span.setAttribute(ATTR_HTTP_REQUEST_BODY_SIZE, Number(contentLength))\n }\n\n cfg.enrichSpan(span, req)\n}\n\nexport const applyResponseAttributes = (\n span: Span,\n res: NormalisedResponse,\n cfg: ResolvedConfig\n): void => {\n const { statusCode } = res\n\n span.setAttribute(ATTR_HTTP_RESPONSE_STATUS_CODE, statusCode)\n\n // OTel spec for CLIENT spans: 5xx = SDK error; 4xx is not (it's the\n // server's fault). We still record error.type for both so they're filterable.\n if (statusCode >= 500) {\n span.setStatus({\n code: SpanStatusCode.ERROR,\n message: `HTTP ${statusCode}`,\n })\n span.setAttribute(ATTR_ERROR_TYPE, String(statusCode))\n } else if (statusCode >= 400) {\n span.setAttribute(ATTR_ERROR_TYPE, String(statusCode))\n }\n\n for (const header of cfg.captureResponseHeaders) {\n const value = res.getHeader(header)\n if (value !== undefined) {\n span.setAttribute(responseHeaderAttr(header), value)\n }\n }\n\n const contentLength = res.getHeader('content-length')\n if (contentLength !== undefined) {\n span.setAttribute(ATTR_HTTP_RESPONSE_BODY_SIZE, Number(contentLength))\n }\n\n // Resolved wire address (post-proxy) — separate from the original hostname\n // so you can see both in the span and spot mesh rewrites.\n if (res.remoteAddress) {\n span.setAttribute(ATTR_NETWORK_PEER_ADDRESS, res.remoteAddress)\n }\n if (res.remotePort) {\n span.setAttribute(ATTR_NETWORK_PEER_PORT, res.remotePort)\n }\n}\n","import type { ClientRequest, IncomingMessage } from 'node:http'\nimport { DEFAULT_REQUEST_HEADERS, DEFAULT_RESPONSE_HEADERS } from './consts'\nimport type { OutgoingHttpEnrichmentConfig, ResolvedConfig } from './types'\n\nexport const resolve = (\n opts: OutgoingHttpEnrichmentConfig\n): ResolvedConfig => ({\n captureRequestHeaders: opts.captureRequestHeaders ?? DEFAULT_REQUEST_HEADERS,\n captureResponseHeaders:\n opts.captureResponseHeaders ?? DEFAULT_RESPONSE_HEADERS,\n enrichSpan: opts.enrichSpan ?? (() => {}),\n useDescriptiveSpanNames: opts.useDescriptiveSpanNames ?? true,\n ignoreOutgoingPaths: opts.ignoreOutgoingPaths ?? [],\n})\n\nexport const isClientRequest = (\n req: ClientRequest | IncomingMessage\n): req is ClientRequest =>\n typeof (req as ClientRequest).getHeader === 'function'\n\nexport const isIncomingMessage = (res: unknown): res is IncomingMessage =>\n res != null &&\n typeof res === 'object' &&\n 'statusCode' in res &&\n 'headers' in res\n","import type { IncomingMessage, RequestOptions } from 'node:http'\nimport type { NormalisedRequest, NormalisedResponse, Protocol } from './types'\n\nexport const normHttpRequest = (req: RequestOptions): NormalisedRequest => {\n const hostname = String(req.hostname ?? req.host ?? '').split(':')[0]\n const port = Number(req.port ?? req.defaultPort ?? 80)\n const path = String(req.path ?? '/')\n const protocol: Protocol = port === 443 ? 'https' : 'http'\n\n return {\n method: req.method ?? 'GET',\n hostname,\n port,\n path,\n protocol,\n getHeader(name) {\n const headers = req.headers\n if (!headers || Array.isArray(headers)) return undefined\n return getHeaderFromObject(headers as Record<string, unknown>, name)\n },\n }\n}\n\nexport const normHttpResponse = (res: IncomingMessage): NormalisedResponse => {\n const socket = res.socket\n return {\n statusCode: res.statusCode ?? 0,\n statusMessage: res.statusMessage ?? '',\n getHeader(name) {\n return getHeaderFromObject(res.headers, name)\n },\n remoteAddress: socket?.remoteAddress,\n remotePort: socket?.remotePort,\n }\n}\n\nexport const getHeaderFromObject = (\n headers: Record<string, unknown> | undefined,\n name: string\n): string[] | undefined => {\n if (!headers) return undefined\n\n const target = name.toLowerCase()\n\n // Iterate over all keys to find case-insensitive match\n for (const key of Object.keys(headers)) {\n if (key.toLowerCase() === target) {\n const value = headers[key]\n if (Array.isArray(value)) return value\n /* istanbul ignore next */\n if (typeof value === 'string') return [value]\n /* istanbul ignore next */\n return undefined\n }\n }\n\n return undefined\n}\n","import type { Attributes } from '@opentelemetry/api'\nimport type { HttpInstrumentationConfig } from '@opentelemetry/instrumentation-http'\nimport {\n ATTR_HTTP_REQUEST_METHOD,\n ATTR_NETWORK_PEER_ADDRESS,\n ATTR_NETWORK_PEER_PORT,\n ATTR_NETWORK_PROTOCOL_VERSION,\n ATTR_SERVER_ADDRESS,\n ATTR_SERVER_PORT,\n ATTR_URL_FULL,\n ATTR_URL_PATH,\n ATTR_URL_SCHEME,\n} from '@opentelemetry/semantic-conventions'\nimport {\n applyRequestAttributes,\n applyResponseAttributes,\n} from './apply-attributes'\nimport { isClientRequest, isIncomingMessage, resolve } from './helpers'\nimport { normHttpRequest, normHttpResponse } from './normalize-http'\nimport type { OutgoingHttpEnrichmentConfig } from './types'\n\n/**\n * Build an HttpInstrumentationConfig that applies shared enrichment logic.\n *\n * The returned config can be spread with your own additional options:\n * new HttpInstrumentation({ ...buildHttpConfig(opts), serverName: 'gateway' })\n */\nexport const buildHttpConfig = (\n opts: OutgoingHttpEnrichmentConfig = {}\n): HttpInstrumentationConfig => {\n const cfg = resolve(opts)\n\n const config: HttpInstrumentationConfig = {\n enabled: opts.enabled,\n ignoreOutgoingRequestHook(req) {\n if (!cfg.ignoreOutgoingPaths.length) return false\n const path = req.path ?? ''\n return cfg.ignoreOutgoingPaths.some((p) =>\n path.toLowerCase().startsWith(p.toLowerCase())\n )\n },\n\n // startOutgoingSpanHook fires at span creation time — before any proxy or\n // service-mesh sidecar can rewrite the destination socket. The returned\n // attributes are the \"ground truth\" hostname we captured off the wire.\n startOutgoingSpanHook(req) {\n const { method, hostname, port, path, protocol } = normHttpRequest(req)\n const [urlPath] = path.split('?')\n const defaultPort = protocol === 'https' ? 443 : 80\n const portSuffix = port !== defaultPort ? `:${port}` : ''\n /* istanbul ignore next */\n const resolvedUrlPath = urlPath ?? '/'\n\n const attrs: Attributes = {\n [ATTR_HTTP_REQUEST_METHOD]: method.toUpperCase(),\n [ATTR_SERVER_ADDRESS]: hostname,\n [ATTR_SERVER_PORT]: port,\n [ATTR_URL_SCHEME]: protocol,\n [ATTR_URL_PATH]: resolvedUrlPath,\n [ATTR_URL_FULL]: `${protocol}://${hostname}${portSuffix}${path}`,\n [ATTR_NETWORK_PEER_ADDRESS]: hostname,\n [ATTR_NETWORK_PEER_PORT]: port,\n }\n /* istanbul ignore next */\n for (const [key, val] of Object.entries(req.headers || {})) {\n if (!val) continue\n\n const name = key.toLowerCase().replace(/-/g, '_')\n const value = Array.isArray(val) ? val.join(',') : val\n attrs[`http.request.header.${name}`] = value\n }\n return attrs\n },\n\n requestHook(span, request) {\n // requestHook fires for both incoming (IncomingMessage) and outgoing\n // (ClientRequest) spans — skip the incoming side.\n if (!isClientRequest(request)) return\n\n // HTTP version isn't always accessible here, but try to read it.\n const proto = request.protocol\n if (proto) {\n span.setAttribute(\n ATTR_NETWORK_PROTOCOL_VERSION,\n /* istanbul ignore next */\n proto === 'https:' ? '1.1' : '1.1'\n )\n }\n\n applyRequestAttributes(span, normHttpRequest(request), cfg)\n },\n\n responseHook(span, response) {\n if (!isIncomingMessage(response)) return\n applyResponseAttributes(span, normHttpResponse(response), cfg)\n },\n }\n\n return config\n}\n","import type {\n UndiciRequest,\n UndiciResponse,\n} from '@opentelemetry/instrumentation-undici'\nimport type { NormalisedRequest, NormalisedResponse } from './types'\n\nexport const normUndiciRequest = (req: UndiciRequest): NormalisedRequest => {\n const origin = new URL(req.origin)\n const protocol = origin.protocol.replace(':', '') as 'http' | 'https'\n const port = Number(origin.port) || (protocol === 'https' ? 443 : 80)\n\n // Parse \"Key: Value\\r\\nKey2: Value2\\r\\n\" → Map\n const headers = parseUndiciRequestHeaders(req.headers)\n\n return {\n method: req.method,\n hostname: origin.hostname,\n port,\n path: req.path,\n protocol,\n getHeader: (name) => headers[name.toLowerCase()],\n }\n}\n\nexport const normUndiciResponse = (res: UndiciResponse): NormalisedResponse => {\n const headers = parseUndiciResponseHeaders(res.headers)\n\n return {\n statusCode: res.statusCode,\n statusMessage: res.statusText,\n getHeader: (name) => headers[name.toLowerCase()],\n }\n}\n\nexport const parseUndiciResponseHeaders = (\n headers: Buffer<ArrayBufferLike>[]\n): Record<string, string[]> => {\n const result: Record<string, string[]> = {}\n\n for (let i = 0; i < headers.length; i += 2) {\n const keyBuf = headers[i]\n const valBuf = headers[i + 1]\n\n if (!keyBuf || !valBuf) continue\n\n /* istanbul ignore next */\n const key = (\n Buffer.isBuffer(keyBuf)\n ? keyBuf.toString('utf8').trim()\n : Buffer.from(keyBuf as ArrayBuffer)\n .toString('utf8')\n .trim()\n ).toLowerCase()\n\n /* istanbul ignore next */\n const val = Buffer.isBuffer(valBuf)\n ? valBuf.toString('utf8').trim()\n : Buffer.from(valBuf as ArrayBuffer)\n .toString('utf8')\n .trim()\n\n if (!key || !val) continue\n\n if (!result[key]) result[key] = []\n result[key].push(val)\n }\n\n return result\n}\n\nexport const parseUndiciRequestHeaders = (\n headers: string | (string | string[])[]\n) => {\n const result: Record<string, string[]> = {}\n\n if (typeof headers === 'string') {\n // Single string format: \"key: value\"\n const [key, ...rest] = headers.split(':')\n if (key && rest.length > 0) {\n result[key.trim().toLowerCase()] = [rest.join(':').trim()]\n }\n } else {\n // The type union guarantees headers is string | array[]; the else-if is always true\n /* istanbul ignore else */\n if (Array.isArray(headers)) {\n // Array format: [key, value] or [key, [value1, value2]]\n for (let i = 0; i < headers.length; i += 2) {\n const key = headers[i]\n const val = headers[i + 1]\n if (typeof key !== 'string' || val == null) continue\n\n if (Array.isArray(val)) {\n result[key.toLowerCase()] = val.map((v) => String(v))\n } else {\n result[key.toLowerCase()] = [String(val)]\n }\n }\n }\n }\n\n return result\n}\n","import type { UndiciInstrumentationConfig } from '@opentelemetry/instrumentation-undici'\nimport {\n applyRequestAttributes,\n applyResponseAttributes,\n} from './apply-attributes'\nimport { resolve } from './helpers'\nimport { normUndiciRequest, normUndiciResponse } from './normalize-undici'\nimport type { OutgoingHttpEnrichmentConfig } from './types'\n\n/**\n * Build an UndiciInstrumentationConfig that applies shared enrichment logic.\n *\n * new UndiciInstrumentation(buildUndiciConfig(opts))\n */\nexport function buildUndiciConfig(\n opts: OutgoingHttpEnrichmentConfig = {}\n): UndiciInstrumentationConfig {\n const cfg = resolve(opts)\n\n const config: UndiciInstrumentationConfig = {\n enabled: opts.enabled,\n ignoreRequestHook(req) {\n if (!cfg.ignoreOutgoingPaths.length) return false\n const path = req.path ?? ''\n return cfg.ignoreOutgoingPaths.some((p) =>\n path.toLowerCase().startsWith(p.toLowerCase())\n )\n },\n\n // undici collapses startSpanHook + requestHook into a single requestHook\n // because diagnostics_channel gives us everything at once.\n requestHook(span, request) {\n applyRequestAttributes(span, normUndiciRequest(request), cfg)\n },\n\n responseHook(span, { response }) {\n applyResponseAttributes(span, normUndiciResponse(response), cfg)\n },\n }\n\n return config\n}\n","/* istanbul ignore file */\n/**\n * Shared enrichment logic for outgoing HTTP spans, normalised across\n * @opentelemetry/instrumentation-http (node:http / node:https)\n * @opentelemetry/instrumentation-undici (undici / global fetch)\n *\n * Usage:\n *\n * import { HttpInstrumentation } from '@opentelemetry/instrumentation-http'\n * import { UndiciInstrumentation } from '@opentelemetry/instrumentation-undici'\n * import { buildHttpConfig, buildUndiciConfig } from './instrumentation/outgoing-http'\n * import type { OutgoingHttpEnrichmentConfig } from './instrumentation/outgoing-http'\n *\n * const opts: OutgoingHttpEnrichmentConfig = {\n * captureRequestHeaders: ['x-tenant-id', 'x-request-id'],\n * captureResponseHeaders: ['x-ratelimit-remaining'],\n * enrichSpan: (span, req) =>\n * span.setAttribute('app.tenant.id', req.getHeader('x-tenant-id') ?? ''),\n * ignoreOutgoingPaths: ['/health', '/ready'],\n * }\n *\n * new HttpInstrumentation(buildHttpConfig(opts))\n * new UndiciInstrumentation(buildUndiciConfig(opts))\n */\n\nexport { buildHttpConfig } from './build-http-config'\nexport { buildUndiciConfig } from './build-undici-config'\nexport type { OutgoingHttpEnrichmentConfig } from './types'\n","import type {\n Instrumentation,\n InstrumentationConfig,\n} from '@opentelemetry/instrumentation'\nimport type { DnsInstrumentationConfig } from '@opentelemetry/instrumentation-dns'\nimport type { ExpressInstrumentationConfig } from '@opentelemetry/instrumentation-express'\nimport type { FsInstrumentationConfig } from '@opentelemetry/instrumentation-fs'\nimport type { GrpcInstrumentationConfig } from '@opentelemetry/instrumentation-grpc'\nimport type { RedisInstrumentationConfig } from '@opentelemetry/instrumentation-redis'\nimport type { SocketIoInstrumentationConfig } from '@opentelemetry/instrumentation-socket.io'\nimport type { OpenSearchInstrumentationConfig } from '@sebspark/opentelemetry-instrumentation-opensearch'\nimport {\n buildHttpConfig,\n buildUndiciConfig,\n type OutgoingHttpEnrichmentConfig,\n} from './enrichments/outgoing-http'\n\nconst cache = new Map<string, Promise<Instrumentation>>()\nconst cacheKey = (\n instrumentationName: string,\n config?: InstrumentationConfig\n) => {\n return config\n ? `${instrumentationName}:${JSON.stringify(config)}`\n : instrumentationName\n}\n\nexport const instrumentations = {\n http(config?: OutgoingHttpEnrichmentConfig) {\n const key = cacheKey('http', config)\n if (!cache.has(key)) {\n cache.set(\n key,\n import('@opentelemetry/instrumentation-http').then(\n ({ HttpInstrumentation }) =>\n new HttpInstrumentation(buildHttpConfig(config))\n )\n )\n }\n // biome-ignore lint/style/noNonNullAssertion: it will always exist\n return cache.get(key)!\n },\n\n express(config?: ExpressInstrumentationConfig) {\n const key = cacheKey('express', config)\n if (!cache.has(key)) {\n cache.set(\n key,\n import('@opentelemetry/instrumentation-express').then(\n ({ ExpressInstrumentation }) => new ExpressInstrumentation(config)\n )\n )\n }\n // biome-ignore lint/style/noNonNullAssertion: it will always exist\n return cache.get(key)!\n },\n\n grpc(config?: GrpcInstrumentationConfig) {\n const key = cacheKey('grpc', config)\n if (!cache.has(key)) {\n cache.set(\n key,\n import('@opentelemetry/instrumentation-grpc').then(\n ({ GrpcInstrumentation }) => new GrpcInstrumentation(config)\n )\n )\n }\n // biome-ignore lint/style/noNonNullAssertion: it will always exist\n return cache.get(key)!\n },\n\n redis(config?: RedisInstrumentationConfig) {\n const key = cacheKey('redis', config)\n if (!cache.has(key)) {\n cache.set(\n key,\n import('@opentelemetry/instrumentation-redis').then(\n ({ RedisInstrumentation }) => new RedisInstrumentation(config)\n )\n )\n }\n // biome-ignore lint/style/noNonNullAssertion: it will always exist\n return cache.get(key)!\n },\n\n dns(config?: DnsInstrumentationConfig) {\n const key = cacheKey('dns', config)\n if (!cache.has(key)) {\n cache.set(\n key,\n import('@opentelemetry/instrumentation-dns').then(\n ({ DnsInstrumentation }) => new DnsInstrumentation(config)\n )\n )\n }\n // biome-ignore lint/style/noNonNullAssertion: it will always exist\n return cache.get(key)!\n },\n\n net(config?: InstrumentationConfig) {\n const key = cacheKey('dns', config)\n if (!cache.has(key)) {\n cache.set(\n key,\n import('@opentelemetry/instrumentation-net').then(\n ({ NetInstrumentation }) => new NetInstrumentation(config)\n )\n )\n }\n // biome-ignore lint/style/noNonNullAssertion: it will always exist\n return cache.get(key)!\n },\n\n fs(config?: FsInstrumentationConfig) {\n const key = cacheKey('fs', config)\n if (!cache.has(key)) {\n cache.set(\n key,\n import('@opentelemetry/instrumentation-fs').then(\n ({ FsInstrumentation }) => new FsInstrumentation(config)\n )\n )\n }\n // biome-ignore lint/style/noNonNullAssertion: it will always exist\n return cache.get(key)!\n },\n\n undici(config?: OutgoingHttpEnrichmentConfig) {\n const key = cacheKey('undici', config)\n if (!cache.has(key)) {\n cache.set(\n key,\n import('@opentelemetry/instrumentation-undici').then(\n ({ UndiciInstrumentation }) =>\n new UndiciInstrumentation(buildUndiciConfig(config))\n )\n )\n }\n // biome-ignore lint/style/noNonNullAssertion: it will always exist\n return cache.get(key)!\n },\n\n socketIo(config?: SocketIoInstrumentationConfig) {\n const key = cacheKey('socket-io', config)\n if (!cache.has(key)) {\n cache.set(\n key,\n import('@opentelemetry/instrumentation-socket.io').then(\n ({ SocketIoInstrumentation }) => new SocketIoInstrumentation(config)\n )\n )\n }\n // biome-ignore lint/style/noNonNullAssertion: it will always exist\n return cache.get(key)!\n },\n\n opensearch(config?: OpenSearchInstrumentationConfig) {\n const key = cacheKey('opensearch', config)\n if (!cache.has(key)) {\n cache.set(\n key,\n import('@sebspark/opentelemetry-instrumentation-opensearch').then(\n ({ OpenSearchInstrumentation }) =>\n new OpenSearchInstrumentation({\n suppressInternalInstrumentation: true,\n ...(config || {}),\n })\n )\n )\n }\n // biome-ignore lint/style/noNonNullAssertion: it will always exist\n return cache.get(key)!\n },\n} as const\n","export const LOG_SEVERITY_MAP = {\n TRACE: 1,\n DEBUG: 5,\n INFO: 9,\n NOTICE: 10,\n WARNING: 13,\n WARN: 13,\n ERROR: 17,\n FATAL: 21,\n CRITICAL: 21,\n ALERT: 22,\n EMERGENCY: 23,\n} as const\n\nexport type LOG_SEVERITY_NAME = keyof typeof LOG_SEVERITY_MAP\n","import kleur from 'kleur'\n\nexport const colors = {\n gray: kleur.gray,\n dim: kleur.dim,\n cyan: kleur.cyan,\n white: kleur.white,\n green: kleur.green,\n yellow: kleur.yellow,\n red: kleur.red,\n magenta: kleur.magenta,\n}\n\nexport const levelColorMap: Record<string, (s: string) => string> = {\n DEBUG: kleur.magenta,\n INFO: kleur.green,\n WARN: kleur.yellow,\n ERROR: kleur.red,\n FATAL: kleur.red,\n}\n\nexport const levelIconMap: Record<string, string> = {\n DEBUG: '🐛',\n INFO: 'ℹ️ ',\n WARN: '⚠️ ',\n ERROR: '❌',\n FATAL: '💀',\n}\n\n// --- Span status codes (per OpenTelemetry spec) ---\nexport const statusLabelMap: Record<number, string> = {\n 0: 'UNSET',\n 1: 'OK',\n 2: 'ERROR',\n}\n\nexport const statusColorMap: Record<number, (s: string) => string> = {\n 0: colors.gray, // UNSET\n 1: colors.green, // OK\n 2: colors.red, // ERROR\n}\n\n// --- Span kinds (for visual context: client/server etc.) ---\nexport const kindLabelMap: Record<number, string> = {\n 0: 'INTERNAL',\n 1: 'SERVER',\n 2: 'CLIENT',\n 3: 'PRODUCER',\n 4: 'CONSUMER',\n}\n\nexport const kindColorMap: Record<number, (s: string) => string> = {\n 0: colors.white, // INTERNAL\n 1: colors.cyan, // SERVER\n 2: colors.yellow, // CLIENT\n 3: colors.magenta, // PRODUCER\n 4: colors.green, // CONSUMER\n}\n","import type { HrTime } from '@opentelemetry/api'\nimport type { LogAttributes } from '@opentelemetry/api-logs'\nimport type { Resource } from '@opentelemetry/resources'\nimport type { ReadableLogRecord } from '@opentelemetry/sdk-logs'\nimport type { ReadableSpan } from '@opentelemetry/sdk-trace-node'\nimport {\n ATTR_SERVICE_NAME,\n ATTR_SERVICE_VERSION,\n} from '@opentelemetry/semantic-conventions'\nimport fss from 'fast-safe-stringify'\nimport { colors, levelColorMap, levelIconMap } from './style'\n\nconst stringify = fss.default.stableStringify\n\ntype IResource = Pick<Resource, 'attributes'>\ntype IInstrumentation = ReadableLogRecord['instrumentationScope']\n\nexport function formatTimestamp(time: HrTime): string {\n const date = new Date(hrTimeToMillis(time))\n return colors.dim(date.toISOString().slice(11, 23)) // HH:mm:ss.sss\n}\n\nexport function formatService(resource: IResource): string {\n const name = resource.attributes[ATTR_SERVICE_NAME] ?? 'unknown-service'\n const version = resource.attributes[ATTR_SERVICE_VERSION] ?? '1.0.0'\n return colors.gray(`[${name}@${version}]`)\n}\n\nexport function formatLevel(record: ReadableLogRecord): string {\n const text = (record.severityText ?? 'INFO').toUpperCase()\n const colorFn = levelColorMap[text] ?? colors.white\n const icon = levelIconMap[text] ?? '•'\n return `${icon} ${colorFn(text.padEnd(5))}`\n}\n\nexport function formatScope(\n resource: IResource,\n instrumentationScope: IInstrumentation\n): string {\n const component = resource.attributes['component.name']\n const { name } = instrumentationScope\n const scopeLabel =\n component || (name && name !== 'unknown' ? name : undefined)\n\n if (!scopeLabel) return ''\n\n return colors.cyan(`${scopeLabel} `)\n}\n\nexport function formatMessage(record: ReadableLogRecord): string {\n return typeof record.body === 'string' ? record.body : stringify(record.body)\n}\n\nexport function formatAttributes(attrs: LogAttributes): string {\n const keys = Object.keys(attrs).filter(\n (k) =>\n !k.startsWith('service.') &&\n !k.startsWith('serviceContext.') &&\n k !== 'cloud.orchestrator' &&\n k !== 'component.name'\n )\n if (keys.length === 0) return ''\n const formatted = keys.map((k) => {\n const val = attrs[k]\n return `${k}=${typeof val === 'object' ? stringify(val) : val}`\n })\n return ` ${colors.gray(formatted.join(' '))}`\n}\n\nexport function hrTimeToMillis(hrTime: [number, number]): number {\n return hrTime[0] * 1000 + Math.floor(hrTime[1] / 1_000_000)\n}\n\nexport function calculateDuration(span: ReadableSpan): number {\n const start = hrTimeToMillis(span.startTime)\n const end = hrTimeToMillis(span.endTime)\n return Math.max(0, Math.round(end - start))\n}\n","import type { ReadableLogRecord } from '@opentelemetry/sdk-logs'\nimport {\n formatAttributes,\n formatLevel,\n formatMessage,\n formatScope,\n formatService,\n formatTimestamp,\n} from './shared'\n\nexport function formatLogRecord(record: ReadableLogRecord): string {\n const timestamp = formatTimestamp(record.hrTime)\n const service = formatService(record.resource)\n const level = formatLevel(record)\n const scope = formatScope(record.resource, record.instrumentationScope)\n const message = formatMessage(record)\n const attrs = formatAttributes(record.attributes)\n\n return `${service} ${timestamp} ${level} ${scope}${message}${attrs}`\n}\n","import type { Resource } from '@opentelemetry/resources'\nimport type {\n DataPoint,\n MetricData,\n ResourceMetrics,\n ScopeMetrics,\n} from '@opentelemetry/sdk-metrics'\nimport {\n formatAttributes,\n formatScope,\n formatService,\n formatTimestamp,\n} from './shared'\nimport { colors } from './style'\n\nexport function formatMetrics(resourceMetrics: ResourceMetrics): string {\n const { resource, scopeMetrics } = resourceMetrics\n\n return scopeMetrics\n .map((scopeMetric) => formatScopeMetric(scopeMetric, resource))\n .join('\\n')\n}\n\nfunction formatScopeMetric(\n scopeMetric: ScopeMetrics,\n resource: Resource\n): string {\n return scopeMetric.metrics\n .map((metric: MetricData) =>\n formatMetricData(metric, resource, scopeMetric.scope)\n )\n .join('\\n')\n}\n\nfunction formatMetricData(\n metric: MetricData,\n resource: Resource,\n scope: ScopeMetrics['scope']\n): string {\n const scopeStr = formatScope(resource, scope)\n const serviceStr = formatService(resource)\n\n const lines: string[] = []\n\n for (const dp of metric.dataPoints) {\n const ts = formatTimestamp(dp.startTime)\n const value = extractMetricValue(dp)\n const attrs = formatAttributes(dp.attributes ?? {})\n\n lines.push(\n `${serviceStr} ${ts} 📊 ${scopeStr}${colors.white(metric.descriptor.name)} ${colors.dim(value)}${attrs}`\n )\n }\n\n return lines.join('\\n')\n}\n\nfunction extractMetricValue(dp: DataPoint<unknown>): string {\n const value = dp.value\n\n if (typeof value === 'number') {\n return value.toString()\n }\n\n if (isHistogramLike(value)) {\n return value.sum.toString()\n }\n\n return '[complex]'\n}\n\nfunction isHistogramLike(val: unknown): val is { sum: number } {\n return (\n typeof val === 'object' &&\n val !== null &&\n 'sum' in val &&\n typeof (val as { sum: number }).sum === 'number'\n )\n}\n","import { SpanStatusCode } from '@opentelemetry/api'\nimport type { ReadableSpan } from '@opentelemetry/sdk-trace-node'\nimport {\n calculateDuration,\n formatService,\n formatTimestamp,\n hrTimeToMillis,\n} from './shared'\nimport { colors, statusColorMap, statusLabelMap } from './style'\n\nconst LABEL_WIDTH = 20\nconst DESCRIPTION_MAX_WIDTH = 16\nconst BAR_MIN_WIDTH = 1\nconst BAR_MAX_WIDTH = 20\n\nexport function formatSpans(spans: ReadableSpan[]) {\n const rootSpan = spans[0]\n const rootStart = hrTimeToMillis(rootSpan.startTime)\n const rootEnd = hrTimeToMillis(rootSpan.endTime)\n const totalDuration = rootEnd - rootStart\n\n const service = formatService(rootSpan.resource)\n const timestamp = formatTimestamp(rootSpan.startTime)\n const traceId = colors.gray(`[${rootSpan.spanContext().traceId}]`)\n\n const lines = [`${service} ${timestamp} ${traceId}`]\n\n for (const span of spans) {\n const offset = hrTimeToMillis(span.startTime) - rootStart\n const depth = computeDepth(span, spans) // optional\n lines.push(\n formatSpan(span, {\n offsetMs: offset,\n totalDurationMs: totalDuration,\n depth,\n })\n )\n }\n\n return lines.join('\\n')\n}\n\nexport function formatSpan(\n span: ReadableSpan,\n opts: {\n offsetMs: number // relative start time in ms (0 for root)\n totalDurationMs: number // total duration in ms (root span duration)\n depth: number // nesting level for indent\n }\n): string {\n const label = formatLabel(span, opts.depth)\n const bar = buildBar(span, opts?.offsetMs, opts?.totalDurationMs)\n const barColor =\n span.status.code === SpanStatusCode.OK\n ? colors.green\n : span.status.code === SpanStatusCode.ERROR\n ? colors.red\n : colors.gray\n const desc = formatDescription(span)\n const status = formatStatus(span)\n const duration = formatDuration(span, opts?.offsetMs)\n const spanId = colors.gray(`[${span.spanContext().spanId}]`)\n\n return `${label} ${barColor(bar)} ${desc} ${status} ${duration} ${spanId}`\n}\n\nfunction formatLabel(span: ReadableSpan, depth: number) {\n const indent = ' '.repeat(depth) // 2 spaces per depth level\n const label = `${indent}└─ ${span.name}`\n return label.padEnd(LABEL_WIDTH)\n}\n\nfunction buildBar(\n span: ReadableSpan,\n offsetMs: number | undefined,\n totalDurationMs: number | undefined\n) {\n const duration = calculateDuration(span)\n\n if (\n typeof offsetMs !== 'number' ||\n typeof totalDurationMs !== 'number' ||\n totalDurationMs === 0\n ) {\n // fallback: show duration-only bar\n const capped = Math.min(duration, 1000)\n const barLength = Math.max(\n BAR_MIN_WIDTH,\n Math.round((capped / 1000) * BAR_MAX_WIDTH)\n )\n return '█'.repeat(barLength).padEnd(BAR_MAX_WIDTH + 2)\n }\n\n // Relative position and size\n const offsetRatio = Math.max(0, Math.min(offsetMs / totalDurationMs, 1))\n const durationRatio = Math.max(0, Math.min(duration / totalDurationMs, 1))\n\n const offsetChars = Math.floor(offsetRatio * BAR_MAX_WIDTH)\n const barChars = Math.max(\n BAR_MIN_WIDTH,\n Math.round(durationRatio * BAR_MAX_WIDTH)\n )\n\n const empty = ' '.repeat(offsetChars)\n const bar = '█'.repeat(barChars)\n\n return (empty + bar).padEnd(BAR_MAX_WIDTH + 2)\n}\n\nfunction formatDescription(span: ReadableSpan): string {\n const keyPriority = [\n // HTTP\n ['http.method', 'http.target'], // → GET /users/123\n ['http.route'], // → /users/:id\n ['http.url'], // → https://...\n\n // GraphQL\n ['graphql.operation.name'], // → getUsers\n ['graphql.operation.type'], // → query\n ['graphql.document'], // → full query text (maybe too long)\n\n // WebSocket\n ['ws.event'], // → connection, message, disconnect\n ['ws.message_type'], // → ping/pong/text/binary\n ['ws.url'], // → wss://...\n\n // Redis\n ['db.system', 'db.statement'], // → redis, \"SET foo bar\"\n ['db.operation'], // → GET, SET\n\n // Spanner\n ['db.statement'], // → SELECT * FROM...\n ['db.operation'], // → SELECT, INSERT\n ['db.name'], // → projects/.../instances/.../databases/...\n\n // OpenSearch\n ['db.operation'], // → search, index, bulk\n ['db.statement'], // → { query DSL... }\n\n // Pub/Sub (GCP)\n ['messaging.operation'], // → publish, receive\n ['messaging.destination'], // → topic-a\n ['messaging.gcp_pubsub.topic'], // → projects/x/topics/y\n\n // General FaaS\n ['faas.invoked_name'], // → myFunction\n ['faas.trigger'], // → http, pubsub, etc.\n\n // Custom or fallback\n ['otel.description'],\n ]\n\n for (const keys of keyPriority) {\n const parts = keys\n .map((k) => span.attributes[k])\n .filter((v) => v !== undefined && v !== null)\n .map((v) => String(v)) // 👈 FIX — guarantees string\n if (parts.length > 0) {\n return truncate(parts.join(' '), DESCRIPTION_MAX_WIDTH - 1).padEnd(\n DESCRIPTION_MAX_WIDTH\n )\n }\n }\n\n return ''.padEnd(DESCRIPTION_MAX_WIDTH)\n}\n\nfunction formatStatus(span: ReadableSpan): string {\n const code = span.status.code\n const label = statusLabelMap[code] ?? 'UNSET'\n const colorFn = statusColorMap[code] ?? colors.gray\n return colorFn(label).padEnd(6)\n}\n\nfunction formatDuration(\n span: ReadableSpan,\n offsetMs: number | undefined\n): string {\n const duration = calculateDuration(span)\n\n const format = (ms: number): string =>\n ms >= 1000 ? `${(ms / 1000).toFixed(2)} s` : `${ms} ms`\n\n return `(${format(offsetMs || 0)}–${format(duration)})`.padEnd(16)\n}\n\nfunction truncate(input: unknown, maxLength: number): string {\n // In practice, input is always a string — the String() cast is a defensive fallback.\n const str = String(input)\n return str.length > maxLength ? `${str.slice(0, maxLength - 1)}…` : str\n}\n\nfunction computeDepth(span: ReadableSpan, allSpans: ReadableSpan[]): number {\n let depth = 0\n let currentParentId = span.parentSpanContext?.spanId\n\n while (currentParentId) {\n const parentSpan = allSpans.find(\n (s) => s.spanContext().spanId === currentParentId\n )\n if (!parentSpan) break\n\n depth += 1\n currentParentId = parentSpan.parentSpanContext?.spanId\n }\n\n return depth\n}\n","/* istanbul ignore file */\nexport * from './log-record'\nexport * from './metrics'\nexport * from './span'\n","import { type ExportResult, ExportResultCode } from '@opentelemetry/core'\nimport type {\n PushMetricExporter,\n ResourceMetrics,\n} from '@opentelemetry/sdk-metrics'\nimport { formatMetrics } from './formatters/index'\n\nexport class ConsoleMetricPrettyExporter implements PushMetricExporter {\n private readonly patterns: RegExp[]\n\n constructor() {\n const raw = process.env.METRIC_FILTER ?? ''\n const entries = raw\n .split(',')\n .map((e) => e.trim())\n .filter(Boolean)\n\n this.patterns = entries.map(globToRegex)\n }\n\n private filterMetrics(\n resourceMetrics: ResourceMetrics\n ): ResourceMetrics | undefined {\n // No filter = block all metrics\n if (this.patterns.length === 0) return undefined\n\n const filteredScopes = resourceMetrics.scopeMetrics\n .map((scopeMetric) => {\n const filteredMetrics = scopeMetric.metrics.filter((metric) =>\n this.patterns.some((pattern) => pattern.test(metric.descriptor.name))\n )\n\n if (filteredMetrics.length === 0) return undefined\n\n return {\n ...scopeMetric,\n metrics: filteredMetrics,\n }\n })\n .filter((s): s is NonNullable<typeof s> => s !== undefined)\n\n if (filteredScopes.length === 0) return undefined\n\n return {\n ...resourceMetrics,\n scopeMetrics: filteredScopes,\n }\n }\n\n export(\n metrics: ResourceMetrics,\n resultCallback: (result: ExportResult) => void\n ): void {\n const filtered = this.filterMetrics(metrics)\n if (filtered) {\n console.log(formatMetrics(filtered))\n }\n resultCallback({ code: ExportResultCode.SUCCESS })\n }\n\n shutdown(): Promise<void> {\n return Promise.resolve()\n }\n\n forceFlush(): Promise<void> {\n return Promise.resolve()\n }\n}\n\nfunction globToRegex(glob: string): RegExp {\n const escaped = glob.replace(/[.+^${}()|[\\]\\\\]/g, '\\\\$&')\n const regex = `^${escaped.replace(/\\*/g, '.*')}$`\n return new RegExp(regex)\n}\n","import { SeverityNumber } from '@opentelemetry/api-logs'\nimport { type ExportResult, ExportResultCode } from '@opentelemetry/core'\nimport type {\n LogRecordExporter,\n ReadableLogRecord,\n} from '@opentelemetry/sdk-logs'\nimport { LOG_SEVERITY_MAP, type LOG_SEVERITY_NAME } from '../consts'\nimport { formatLogRecord } from './formatters/index'\n\nexport class ConsoleLogPrettyExporter implements LogRecordExporter {\n private readonly logThreshold: number\n constructor() {\n const defaultLogLevel = 'INFO'\n const env = (process.env.LOG_LEVEL?.toUpperCase() ??\n defaultLogLevel) as LOG_SEVERITY_NAME\n this.logThreshold =\n LOG_SEVERITY_MAP[env] ?? LOG_SEVERITY_MAP[defaultLogLevel]\n }\n export(\n logs: ReadableLogRecord[],\n resultCallback: (result: ExportResult) => void\n ): void {\n this._sendLogRecords(logs, resultCallback)\n }\n\n shutdown(): Promise<void> {\n return Promise.resolve()\n }\n\n forceFlush(): Promise<void> {\n return Promise.resolve()\n }\n\n private _sendLogRecords(\n logRecords: ReadableLogRecord[],\n done: (result: ExportResult) => void\n ): void {\n for (const record of logRecords) {\n if ((record.severityNumber ?? 0) >= this.logThreshold) {\n const formatted = formatLogRecord(record)\n /* istanbul ignore next */\n const severity = record.severityNumber || SeverityNumber.UNSPECIFIED\n\n if (severity >= SeverityNumber.ERROR) {\n console.error(formatted)\n } else if (severity >= SeverityNumber.WARN) {\n console.log(formatted)\n } else if (severity >= SeverityNumber.INFO) {\n console.info(formatted)\n } else if (severity >= SeverityNumber.DEBUG) {\n console.debug(formatted)\n } else {\n console.trace(formatted)\n }\n }\n }\n\n done?.({ code: ExportResultCode.SUCCESS })\n }\n}\n","import { SpanStatusCode } from '@opentelemetry/api'\nimport { type ExportResult, ExportResultCode } from '@opentelemetry/core'\nimport type { ReadableSpan, SpanExporter } from '@opentelemetry/sdk-trace-node'\nimport { formatSpans } from './formatters/index'\n\nexport class ConsoleSpanPrettyExporter implements SpanExporter {\n private readonly allowedStatuses: Set<number>\n\n constructor() {\n const env = process.env.SPAN_LEVEL?.toUpperCase()\n if (!env) {\n this.allowedStatuses = new Set([\n SpanStatusCode.UNSET,\n SpanStatusCode.OK,\n SpanStatusCode.ERROR,\n ])\n } else {\n const map: Record<string, number> = {\n UNSET: SpanStatusCode.UNSET,\n OK: SpanStatusCode.OK,\n ERROR: SpanStatusCode.ERROR,\n }\n\n this.allowedStatuses = new Set(\n env\n .split(',')\n .map((s) => s.trim())\n .map((s) => map[s])\n .filter((v): v is number => typeof v === 'number')\n )\n }\n }\n\n private shouldExport(spans: ReadableSpan[]) {\n // print all spans\n if (this.allowedStatuses.size === 3) {\n return true\n }\n // print only certain levels\n return spans.some((span) => this.allowedStatuses.has(span.status.code))\n }\n\n export(\n spans: ReadableSpan[],\n resultCallback: (result: ExportResult) => void\n ): void {\n if (this.shouldExport(spans)) {\n console.log(formatSpans(spans))\n }\n\n resultCallback({ code: ExportResultCode.SUCCESS })\n }\n\n shutdown(): Promise<void> {\n return Promise.resolve()\n }\n}\n","/* istanbul ignore file */\nexport * from './console-log-pretty-exporter'\nexport * from './console-span-pretty-exporter'\nexport * from './gcp-json-log-exporter'\n","import type {\n ReadableSpan,\n SpanExporter,\n SpanProcessor,\n} from '@opentelemetry/sdk-trace-node'\n\nexport class TreeSpanProcessor implements SpanProcessor {\n private exporter: SpanExporter\n private orphans: Map<string, ReadableSpan[]> = new Map()\n\n constructor(exporter: SpanExporter) {\n this.exporter = exporter\n }\n\n onStart(): void {\n // no-op\n }\n\n onEnd(span: ReadableSpan): void {\n const parentId = span.parentSpanContext?.spanId\n\n if (parentId) {\n const siblings = this.orphans.get(parentId) || []\n this.orphans.set(parentId, [...siblings, span])\n\n return\n }\n\n const children = this.getChildrenRecursively(span)\n const sorted = [span, ...children].sort((s1, s2) => {\n const [sec1, nano1] = s1.startTime\n const [sec2, nano2] = s2.startTime\n\n if (sec1 !== sec2) return sec1 - sec2\n return nano1 - nano2\n })\n this.exporter.export(sorted, () => {})\n }\n\n private getChildrenRecursively(span: ReadableSpan) {\n const spanId = span.spanContext().spanId\n const children = this.orphans.get(spanId) || []\n this.orphans.delete(spanId)\n\n const result = [...children]\n for (const child of children) {\n result.push(...this.getChildrenRecursively(child))\n }\n\n return result\n }\n\n shutdown(): Promise<void> {\n return this.exporter.shutdown()\n }\n\n async forceFlush(): Promise<void> {\n await this.exporter.forceFlush?.()\n }\n}\n","import { OTLPLogExporter } from '@opentelemetry/exporter-logs-otlp-http'\nimport { OTLPMetricExporter } from '@opentelemetry/exporter-metrics-otlp-http'\nimport { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http'\nimport type { Resource } from '@opentelemetry/resources'\nimport {\n BatchLogRecordProcessor,\n LoggerProvider,\n type LogRecordProcessor,\n SimpleLogRecordProcessor,\n} from '@opentelemetry/sdk-logs'\nimport { PeriodicExportingMetricReader } from '@opentelemetry/sdk-metrics'\nimport {\n BatchSpanProcessor,\n SimpleSpanProcessor,\n type SpanProcessor,\n} from '@opentelemetry/sdk-trace-node'\nimport { ConsoleMetricPrettyExporter } from './loggers/console-metric-pretty-exporter'\nimport {\n ConsoleLogPrettyExporter,\n ConsoleSpanPrettyExporter,\n} from './loggers/index'\nimport { TreeSpanProcessor } from './loggers/tree-span-processor'\n\nexport const getLogProvider = (\n resource: Resource,\n otlpEndpoint: string | undefined\n) => {\n // With collector\n if (otlpEndpoint) {\n const otlpExporter = new OTLPLogExporter({ url: `${otlpEndpoint}/v1/logs` })\n const processors: LogRecordProcessor[] = [\n new BatchLogRecordProcessor({ exporter: otlpExporter }),\n ]\n\n // Console logging for cluster\n if (process.env.LOG_LEVEL) {\n const consoleExporter = new ConsoleLogPrettyExporter()\n processors.push(\n new SimpleLogRecordProcessor({ exporter: consoleExporter })\n )\n }\n\n return new LoggerProvider({\n resource,\n processors,\n })\n }\n\n // Local dev\n const consoleExporter = new ConsoleLogPrettyExporter()\n const processor = new SimpleLogRecordProcessor({ exporter: consoleExporter })\n return new LoggerProvider({\n resource,\n processors: [processor],\n })\n}\n\nexport const getSpanProcessor = (\n otlpEndpoint: string | undefined\n): SpanProcessor => {\n const exporter = otlpEndpoint\n ? new OTLPTraceExporter({\n url: `${otlpEndpoint}/v1/traces`,\n })\n : new ConsoleSpanPrettyExporter()\n\n if (!otlpEndpoint) {\n return new TreeSpanProcessor(exporter)\n }\n\n if (process.env.OTEL_SIMPLE_SPAN_PROCESSOR === 'true') {\n console.log(\n '[otel] Using SimpleSpanProcessor (OTEL_SIMPLE_SPAN_PROCESSOR=true)'\n )\n return new SimpleSpanProcessor(exporter)\n }\n\n return new BatchSpanProcessor(exporter)\n}\n\nexport const getMetricReader = (otlpEndpoint: string | undefined) => {\n const metricExporter = otlpEndpoint\n ? new OTLPMetricExporter({\n url: `${otlpEndpoint}/v1/metrics`,\n })\n : new ConsoleMetricPrettyExporter()\n const metricReader = new PeriodicExportingMetricReader({\n exporter: metricExporter,\n })\n\n return metricReader\n}\n","import {\n ATTR_SERVICE_NAME,\n ATTR_SERVICE_VERSION,\n} from '@opentelemetry/semantic-conventions'\n\n/**\n * Extracts telemetry context from environment (cloud/k8s aware),\n * with support for subservice/component override.\n */\nexport function detectTelemetryContext(componentNameOverride?: string) {\n const {\n OTEL_SERVICE_NAME, // e.g. \"UserSystem\"\n OTEL_SERVICE_VERSION, // e.g. \"1.2.3\"\n K_SERVICE,\n K_REVISION,\n K_CONFIGURATION,\n KUBERNETES_SERVICE_HOST,\n POD_NAME,\n POD_NAMESPACE,\n GCP_PROJECT,\n CLOUD_PROVIDER,\n } = process.env\n\n const systemName = OTEL_SERVICE_NAME || 'unknown-service'\n const systemVersion = OTEL_SERVICE_VERSION || '1.0.0'\n\n // Only use component if explicitly provided\n const componentName = componentNameOverride || undefined\n\n const resourceAttributes = {\n [ATTR_SERVICE_NAME]: systemName,\n [ATTR_SERVICE_VERSION]: systemVersion,\n 'serviceContext.service': systemName,\n 'serviceContext.version': systemVersion,\n ...(K_SERVICE && { 'cloud.run.service': K_SERVICE }),\n ...(K_REVISION && { 'cloud.run.revision': K_REVISION }),\n ...(K_CONFIGURATION && { 'cloud.run.configuration': K_CONFIGURATION }),\n ...(POD_NAME && { 'k8s.pod_name': POD_NAME }),\n ...(POD_NAMESPACE && { 'k8s.namespace_name': POD_NAMESPACE }),\n ...(KUBERNETES_SERVICE_HOST && { 'cloud.orchestrator': 'kubernetes' }),\n ...(GCP_PROJECT && { 'cloud.account.id': GCP_PROJECT }),\n ...(CLOUD_PROVIDER && { 'cloud.provider': CLOUD_PROVIDER }),\n ...(componentName && { 'component.name': componentName }),\n }\n\n return {\n systemName,\n systemVersion,\n componentName,\n resourceAttributes,\n }\n}\n","import { containerDetector } from '@opentelemetry/resource-detector-container'\nimport { gcpDetector } from '@opentelemetry/resource-detector-gcp'\nimport {\n detectResources,\n envDetector,\n osDetector,\n processDetector,\n resourceFromAttributes,\n serviceInstanceIdDetector,\n} from '@opentelemetry/resources'\nimport { detectTelemetryContext } from './otel-context'\n\nconst isOnGcp = () =>\n !!(\n process.env.K_SERVICE ||\n process.env.GAE_APPLICATION ||\n process.env.KUBERNETES_SERVICE_HOST\n )\n\nexport const getResource = async () => {\n const baseRes = detectResources({\n detectors: [\n containerDetector,\n envDetector,\n ...(isOnGcp() ? [gcpDetector] : []),\n osDetector,\n processDetector,\n serviceInstanceIdDetector,\n ],\n })\n\n if (baseRes.waitForAsyncAttributes) {\n await baseRes.waitForAsyncAttributes()\n }\n\n const { resourceAttributes } = detectTelemetryContext()\n const customRes = resourceFromAttributes(resourceAttributes)\n const resource = baseRes.merge(customRes)\n\n if (resource.waitForAsyncAttributes) {\n await resource.waitForAsyncAttributes()\n }\n\n return resource\n}\n","import {\n context,\n DiagConsoleLogger,\n DiagLogLevel,\n diag,\n metrics,\n trace,\n} from '@opentelemetry/api'\nimport { logs } from '@opentelemetry/api-logs'\nimport type { Instrumentation } from '@opentelemetry/instrumentation'\nimport type { LoggerProvider } from '@opentelemetry/sdk-logs'\nimport { NodeSDK } from '@opentelemetry/sdk-node'\nimport { getLogProvider, getMetricReader, getSpanProcessor } from './providers'\nimport { getResource } from './resource'\n\ndiag.disable()\ndiag.setLogger(new DiagConsoleLogger(), DiagLogLevel.ERROR)\n\n// Use globalThis with a Symbol key so the flag is shared even when the module\n// is instantiated more than once (e.g. --import preload vs main app graph when\n// using tsx or other loaders that don't share the ESM module cache).\nconst OTEL_INIT_KEY = Symbol.for('@sebspark/otel:initialized')\nconst OTEL_INIT_PROMISE_KEY = Symbol.for('@sebspark/otel:initPromise')\n\nfunction getGlobal(): {\n [key: symbol]: unknown\n} {\n return globalThis as Record<symbol, unknown>\n}\n\nexport async function initialize(\n ...instrumentations: Promise<Instrumentation>[]\n) {\n const g = getGlobal()\n if (!g[OTEL_INIT_PROMISE_KEY]) {\n const resolvedInstrumentations = await Promise.all(instrumentations)\n const promise = _initialize(resolvedInstrumentations).catch((err) => {\n // Allow re-initialization if the first attempt fails\n g[OTEL_INIT_PROMISE_KEY] = undefined\n throw err\n })\n g[OTEL_INIT_PROMISE_KEY] = promise\n }\n return g[OTEL_INIT_PROMISE_KEY] as Promise<void>\n}\n\nexport function isInitialized() {\n return getGlobal()[OTEL_INIT_KEY] === true\n}\n\nlet sdk: NodeSDK | undefined\nlet logProvider: LoggerProvider | undefined\n\nasync function _initialize(instrumentations: Instrumentation[]) {\n const serviceName = process.env.OTEL_SERVICE_NAME ?? 'unknown-service'\n const otlpEndpoint = process.env.OTEL_EXPORTER_OTLP_ENDPOINT\n\n const resource = await getResource()\n\n // Reset any previous instrumentation\n context.disable()\n logs.disable()\n trace.disable()\n metrics.disable()\n\n // Manual setup for logs\n logProvider = getLogProvider(resource, otlpEndpoint)\n logs.setGlobalLoggerProvider(logProvider)\n\n // NodeSDK setup\n const spanProcessor = getSpanProcessor(otlpEndpoint)\n const metricReader = getMetricReader(otlpEndpoint)\n sdk = new NodeSDK({\n spanProcessor,\n metricReader,\n instrumentations,\n resource,\n })\n\n sdk.start()\n getGlobal()[OTEL_INIT_KEY] = true\n console.log(`[otel] Telemetry initialized for \"${serviceName}\"`)\n}\n\nexport const dispose = async () => {\n const processes: Promise<void>[] = []\n if (sdk) processes.push(sdk.shutdown())\n if (logProvider) processes.push(logProvider.shutdown())\n\n // Only initiate shotdown once\n sdk = undefined\n logProvider = undefined\n\n if (processes.length) {\n console.log('[otel] Shutting down...')\n await Promise.all(processes)\n console.log('[otel] Shutdown complete.')\n }\n}\n","import { context, trace } from '@opentelemetry/api'\nimport { logs } from '@opentelemetry/api-logs'\nimport { LOG_SEVERITY_MAP, type LOG_SEVERITY_NAME } from './consts'\nimport { isInitialized } from './otel'\nimport { detectTelemetryContext } from './otel-context'\n\n// biome-ignore lint/suspicious/noExplicitAny: library\ntype Attrs = Record<string, any>\n\nexport type Logger = ReturnType<typeof getLogger>\nexport function getLogger(serviceOverride?: string, extraAttrs: Attrs = {}) {\n const { systemName, systemVersion, resourceAttributes } =\n detectTelemetryContext(serviceOverride)\n\n const defaultAttrs = {\n ...resourceAttributes,\n ...extraAttrs,\n }\n\n let hasWarnedAboutInit = false\n\n function emit(\n severityText: LOG_SEVERITY_NAME,\n body: string,\n attrs: Attrs = {}\n ) {\n // Get the logger at the last second\n if (!isInitialized() && process.env.NODE_ENV !== 'test') {\n if (!hasWarnedAboutInit) {\n console.warn('OTEL must be initialized before using logger')\n hasWarnedAboutInit = true\n }\n console.log(`[${severityText}] ${body}`)\n return\n }\n const logger = logs.getLogger(systemName, systemVersion)\n\n const span = trace.getSpan(context.active())\n const spanContext = span?.spanContext()\n\n logger.emit({\n severityText,\n severityNumber: LOG_SEVERITY_MAP[severityText],\n body,\n attributes: {\n 'gcp.log_name': systemName.replace(/^@/, '').replace(/\\//g, '-'),\n ...defaultAttrs,\n ...(spanContext && {\n trace_id: spanContext.traceId,\n span_id: spanContext.spanId,\n }),\n ...attrs,\n },\n })\n }\n\n function resolveArgs(\n msg: string | Error,\n errOrAttrs?: Error | Attrs,\n maybeAttrs: Attrs = {}\n ): { body: string; attrs: Attrs } {\n if (errOrAttrs instanceof Error) {\n /* istanbul ignore next */\n const body = `${msg}: ${errOrAttrs.stack || errOrAttrs.message}`\n return { body, attrs: maybeAttrs }\n }\n\n /* istanbul ignore next */\n const body = msg instanceof Error ? msg.stack || msg.message : msg\n /* istanbul ignore next */\n const attrs = errOrAttrs || {}\n return { body, attrs }\n }\n\n type LogFn = {\n (msg: string, attrs?: Attrs): void\n (msg: string, error: Error, attrs?: Attrs): void\n (error: Error, attrs?: Attrs): void\n }\n\n function createLogFn(severity: LOG_SEVERITY_NAME): LogFn {\n return (\n msg: string | Error,\n errOrAttrs?: Error | Attrs,\n maybeAttrs: Attrs = {}\n ) => {\n const { body, attrs } = resolveArgs(msg, errOrAttrs, maybeAttrs)\n emit(severity, body, attrs)\n }\n }\n\n return {\n debug: createLogFn('DEBUG'),\n info: createLogFn('INFO'),\n notice: createLogFn('NOTICE'),\n warn: createLogFn('WARN'),\n error: createLogFn('ERROR'),\n critical: createLogFn('CRITICAL'),\n alert: createLogFn('ALERT'),\n emergency: createLogFn('EMERGENCY'),\n }\n}\n","import { metrics } from '@opentelemetry/api'\nimport { isInitialized } from './otel'\nimport { detectTelemetryContext } from './otel-context'\n\nexport function getMeter(componentNameOverride?: string) {\n if (!isInitialized() && process.env.NODE_ENV !== 'test') {\n console.warn('OTEL must be initialized before using getMeter()')\n }\n\n const { componentName, systemName, systemVersion } = detectTelemetryContext(\n componentNameOverride\n )\n return metrics.getMeter(componentName ?? systemName, systemVersion)\n}\n","import {\n context,\n type SpanOptions,\n SpanStatusCode,\n trace,\n} from '@opentelemetry/api'\nimport { isInitialized } from './otel'\nimport { detectTelemetryContext } from './otel-context'\n\ntype OtelTracer = ReturnType<typeof trace.getTracer>\ntype Span = ReturnType<OtelTracer['startSpan']>\n\ntype Func<T> = (span: Span) => Promise<T> | T\ntype SyncFunc<T> = (span: Span) => T\n\ntype WithTrace = {\n <T>(name: string, fn: Func<T>): Promise<T>\n <T>(name: string, options: SpanOptions, fn: Func<T>): Promise<T>\n <T>(name: string, parent: Span, fn: Func<T>): Promise<T>\n <T>(name: string, options: SpanOptions, parent: Span, fn: Func<T>): Promise<T>\n}\ntype WithTraceSync = {\n <T>(name: string, fn: SyncFunc<T>): T\n <T>(name: string, options: SpanOptions, fn: SyncFunc<T>): T\n <T>(name: string, parent: Span, fn: SyncFunc<T>): T\n <T>(name: string, options: SpanOptions, parent: Span, fn: SyncFunc<T>): T\n}\n\n/**\n * Extended tracer with helper methods for span-wrapped execution\n */\ninterface Tracer extends OtelTracer {\n withTrace: WithTrace\n withTraceSync: WithTraceSync\n}\n\n/**\n * Returns an OpenTelemetry tracer bound to the current service.\n * Includes `withTrace()` and `withTraceSync()` helpers for span-wrapped execution.\n *\n * @param serviceOverride - Optional override for service name\n * @returns Tracer with helpers\n */\nexport function getTracer(componentNameOverride?: string): Tracer {\n if (!isInitialized() && process.env.NODE_ENV !== 'test') {\n console.warn('OTEL must be initialized before calling getTracer()')\n }\n\n const { componentName, systemName, systemVersion } = detectTelemetryContext(\n componentNameOverride\n )\n const tracer = trace.getTracer(\n componentName ?? systemName,\n systemVersion\n ) as Tracer\n\n /**\n * Runs a function inside a new span (async variant).\n * Automatically handles span status and nesting.\n */\n const withTrace: WithTrace = async <T>(\n name: string,\n spanOptionsSpanOrFunc?: SpanOptions | Span | Func<T>,\n spanOrFunc?: Span | Func<T>,\n func?: Func<T>\n ): Promise<T> => {\n const { options, parent, fn } = extractArgs(\n spanOptionsSpanOrFunc,\n spanOrFunc,\n func\n )\n\n const parentContext = parent\n ? trace.setSpan(context.active(), parent)\n : context.active()\n\n const span = tracer.startSpan(name, options, parentContext)\n let ended = false\n const originalEnd = span.end.bind(span)\n const endOnce = () => {\n if (!ended) {\n ended = true\n originalEnd()\n }\n }\n span.end = endOnce\n\n return await context.with(trace.setSpan(parentContext, span), async () => {\n try {\n const result = await fn(span)\n span.setStatus({ code: SpanStatusCode.OK })\n return result\n } catch (err) {\n const error = err as Error\n span.setStatus({ code: SpanStatusCode.ERROR, message: error.message })\n span.recordException?.(error)\n throw err\n } finally {\n endOnce()\n }\n })\n }\n\n /**\n * Runs a synchronous function inside a new span.\n * Automatically handles span status and nesting.\n */\n const withTraceSync: WithTraceSync = <T>(\n name: string,\n spanOptionsSpanOrFunc?: SpanOptions | Span | SyncFunc<T>,\n spanOrFunc?: Span | SyncFunc<T>,\n func?: SyncFunc<T>\n ): T => {\n const { options, parent, fn } = extractArgs(\n spanOptionsSpanOrFunc,\n spanOrFunc,\n func\n )\n\n const parentContext = parent\n ? trace.setSpan(context.active(), parent)\n : context.active()\n\n const span = tracer.startSpan(name, options, parentContext)\n let ended = false\n const originalEnd = span.end.bind(span)\n const endOnce = () => {\n if (!ended) {\n ended = true\n originalEnd()\n }\n }\n span.end = endOnce\n\n return context.with(trace.setSpan(parentContext, span), () => {\n try {\n const result = fn(span)\n span.setStatus({ code: SpanStatusCode.OK })\n return result\n } catch (err) {\n const error = err as Error\n span.setStatus({ code: SpanStatusCode.ERROR, message: error.message })\n span.recordException?.(error)\n throw err\n } finally {\n endOnce()\n }\n })\n }\n\n tracer.withTrace = withTrace\n tracer.withTraceSync = withTraceSync\n\n return tracer\n}\n\ntype TraceArgs<T> = {\n options: SpanOptions\n parent?: Span\n fn: (span: Span) => T\n}\n\nfunction extractArgs<T>(\n spanOptionsSpanOrFunc?: SpanOptions | Span | ((span: Span) => T),\n spanOrFunc?: Span | ((span: Span) => T),\n func?: (span: Span) => T\n): TraceArgs<T> {\n let options: SpanOptions = {}\n let parent: Span | undefined\n let fn: (span: Span) => T\n\n if (isFunction(spanOptionsSpanOrFunc)) {\n fn = spanOptionsSpanOrFunc\n } else if (isFunction(spanOrFunc)) {\n const spanOrSpanOptions = spanOptionsSpanOrFunc as Span | SpanOptions\n if (isSpanOptions(spanOrSpanOptions)) {\n options = spanOrSpanOptions as SpanOptions\n } else {\n parent = spanOrSpanOptions as Span\n }\n fn = spanOrFunc\n } else {\n options = spanOptionsSpanOrFunc as SpanOptions\n parent = spanOrFunc as Span\n // biome-ignore lint/style/noNonNullAssertion: it IS defined here\n fn = func!\n }\n\n return { options, parent, fn }\n}\n\nconst isFunction = (value: unknown): value is (span: Span) => unknown =>\n typeof value === 'function'\nconst isSpan = (value: unknown): value is Span =>\n value !== null &&\n value !== undefined &&\n isFunction((value as Span).spanContext) &&\n isFunction((value as Span).end)\n/* istanbul ignore next */\nconst isSpanOptions = (value: unknown): value is SpanOptions =>\n value !== null &&\n value !== undefined &&\n (!!(value as SpanOptions).startTime ||\n !!(value as SpanOptions).attributes ||\n !!(value as SpanOptions).kind) &&\n !isSpan(value)\n","/* istanbul ignore file */\nexport {\n type Context,\n type Counter,\n context,\n type Gauge,\n type Histogram,\n type Meter,\n type ObservableCounter,\n type ObservableGauge,\n type ObservableUpDownCounter,\n type Span,\n type SpanStatus,\n SpanStatusCode,\n type UpDownCounter,\n} from '@opentelemetry/api'\nexport * from './instrumentations'\nexport * from './logger'\nexport * from './metrics'\nexport * from './otel'\nexport * from './tracer'\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["SpanStatusCode","SpanStatusCode","SpanStatusCode","context","context","SpanStatusCode"],"sources":["../src/enrichments/outgoing-http/consts.ts","../src/enrichments/outgoing-http/apply-attributes.ts","../src/enrichments/outgoing-http/helpers.ts","../src/enrichments/outgoing-http/normalize-http.ts","../src/enrichments/outgoing-http/build-http-config.ts","../src/enrichments/outgoing-http/normalize-undici.ts","../src/enrichments/outgoing-http/build-undici-config.ts","../src/enrichments/outgoing-http/index.ts","../src/instrumentations.ts","../src/consts.ts","../src/loggers/formatters/style.ts","../src/loggers/formatters/shared.ts","../src/loggers/formatters/log-record.ts","../src/loggers/formatters/metrics.ts","../src/loggers/formatters/span.ts","../src/loggers/formatters/index.ts","../src/loggers/console-metric-pretty-exporter.ts","../src/loggers/console-log-pretty-exporter.ts","../src/loggers/console-span-pretty-exporter.ts","../src/loggers/index.ts","../src/loggers/tree-span-processor.ts","../src/providers.ts","../src/otel-context.ts","../src/resource.ts","../src/otel.ts","../src/logger.ts","../src/metrics.ts","../src/tracer.ts","../src/index.ts"],"sourcesContent":["// Incubating attrs — copied as string literals per OTel JS team recommendation:\n// importing from /incubating at runtime is explicitly discouraged because that\n// entry-point is NOT subject to semver and may break in minor releases.\n// https://github.com/open-telemetry/opentelemetry-js/tree/main/packages/opentelemetry-semantic-conventions#unstable-semconv\nexport const ATTR_HTTP_REQUEST_BODY_SIZE = 'http.request.body.size'\nexport const ATTR_HTTP_RESPONSE_BODY_SIZE = 'http.response.body.size'\n\nexport const DEFAULT_REQUEST_HEADERS: string[] = [\n 'content-type',\n 'accept',\n 'x-request-id',\n 'x-correlation-id',\n 'traceparent',\n 'tracestate',\n] as const\n\nexport const DEFAULT_RESPONSE_HEADERS: string[] = [\n 'content-type',\n 'x-request-id',\n 'x-correlation-id',\n 'x-ratelimit-limit',\n 'x-ratelimit-remaining',\n 'x-ratelimit-reset',\n 'retry-after',\n] as const\n\nexport const PROTOCOLS = ['https', 'http'] as const\n","import { type Span, SpanStatusCode } from '@opentelemetry/api'\nimport {\n ATTR_ERROR_TYPE,\n ATTR_HTTP_REQUEST_METHOD,\n ATTR_HTTP_RESPONSE_STATUS_CODE,\n ATTR_NETWORK_PEER_ADDRESS,\n ATTR_NETWORK_PEER_PORT,\n ATTR_SERVER_ADDRESS,\n ATTR_SERVER_PORT,\n ATTR_URL_FULL,\n ATTR_URL_PATH,\n ATTR_URL_QUERY,\n ATTR_URL_SCHEME,\n} from '@opentelemetry/semantic-conventions'\nimport {\n ATTR_HTTP_REQUEST_BODY_SIZE,\n ATTR_HTTP_RESPONSE_BODY_SIZE,\n} from './consts'\nimport type {\n NormalisedRequest,\n NormalisedResponse,\n ResolvedConfig,\n} from './types'\n\nconst requestHeaderAttr = (h: string) =>\n `http.request.header.${h.toLowerCase().replace(/-/g, '_')}`\nconst responseHeaderAttr = (h: string) =>\n `http.response.header.${h.toLowerCase().replace(/-/g, '_')}`\n\nexport const applyRequestAttributes = (\n span: Span,\n req: NormalisedRequest,\n cfg: ResolvedConfig\n): void => {\n const { method, hostname, port, path, protocol } = req\n const [urlPath, urlQuery] = path.split('?')\n /* istanbul ignore next */\n const defaultPort = protocol === 'https' ? 443 : 80\n /* istanbul ignore next */\n const portSuffix = port !== defaultPort ? `:${port}` : ''\n /* istanbul ignore next */\n const resolvedUrlPath = urlPath ?? '/'\n\n // Stable semconv v1.23+ attributes\n span.setAttributes({\n [ATTR_HTTP_REQUEST_METHOD]: method.toUpperCase(),\n [ATTR_SERVER_ADDRESS]: hostname,\n [ATTR_SERVER_PORT]: port,\n [ATTR_URL_SCHEME]: protocol,\n [ATTR_URL_PATH]: resolvedUrlPath,\n [ATTR_URL_FULL]: `${protocol}://${hostname}${portSuffix}${path}`,\n })\n\n if (urlQuery) {\n span.setAttribute(ATTR_URL_QUERY, urlQuery)\n }\n\n if (cfg.useDescriptiveSpanNames) {\n span.updateName(`${method.toUpperCase()} ${hostname}${resolvedUrlPath}`)\n }\n\n for (const header of cfg.captureRequestHeaders) {\n const value = req.getHeader(header)\n if (value !== undefined) {\n span.setAttribute(requestHeaderAttr(header), value)\n }\n }\n\n const contentLength = req.getHeader('content-length')\n if (contentLength !== undefined) {\n span.setAttribute(ATTR_HTTP_REQUEST_BODY_SIZE, Number(contentLength))\n }\n\n cfg.enrichSpan(span, req)\n}\n\nexport const applyResponseAttributes = (\n span: Span,\n res: NormalisedResponse,\n cfg: ResolvedConfig\n): void => {\n const { statusCode } = res\n\n span.setAttribute(ATTR_HTTP_RESPONSE_STATUS_CODE, statusCode)\n\n // OTel spec for CLIENT spans: 5xx = SDK error; 4xx is not (it's the\n // server's fault). We still record error.type for both so they're filterable.\n if (statusCode >= 500) {\n span.setStatus({\n code: SpanStatusCode.ERROR,\n message: `HTTP ${statusCode}`,\n })\n span.setAttribute(ATTR_ERROR_TYPE, String(statusCode))\n } else if (statusCode >= 400) {\n span.setAttribute(ATTR_ERROR_TYPE, String(statusCode))\n }\n\n for (const header of cfg.captureResponseHeaders) {\n const value = res.getHeader(header)\n if (value !== undefined) {\n span.setAttribute(responseHeaderAttr(header), value)\n }\n }\n\n const contentLength = res.getHeader('content-length')\n if (contentLength !== undefined) {\n span.setAttribute(ATTR_HTTP_RESPONSE_BODY_SIZE, Number(contentLength))\n }\n\n // Resolved wire address (post-proxy) — separate from the original hostname\n // so you can see both in the span and spot mesh rewrites.\n if (res.remoteAddress) {\n span.setAttribute(ATTR_NETWORK_PEER_ADDRESS, res.remoteAddress)\n }\n if (res.remotePort) {\n span.setAttribute(ATTR_NETWORK_PEER_PORT, res.remotePort)\n }\n}\n","import type { ClientRequest, IncomingMessage } from 'node:http'\nimport { DEFAULT_REQUEST_HEADERS, DEFAULT_RESPONSE_HEADERS } from './consts'\nimport type { OutgoingHttpEnrichmentConfig, ResolvedConfig } from './types'\n\nexport const resolve = (\n opts: OutgoingHttpEnrichmentConfig\n): ResolvedConfig => ({\n captureRequestHeaders: opts.captureRequestHeaders ?? DEFAULT_REQUEST_HEADERS,\n captureResponseHeaders:\n opts.captureResponseHeaders ?? DEFAULT_RESPONSE_HEADERS,\n enrichSpan: opts.enrichSpan ?? (() => {}),\n useDescriptiveSpanNames: opts.useDescriptiveSpanNames ?? true,\n ignoreOutgoingPaths: opts.ignoreOutgoingPaths ?? [],\n})\n\nexport const isClientRequest = (\n req: ClientRequest | IncomingMessage\n): req is ClientRequest =>\n typeof (req as ClientRequest).getHeader === 'function'\n\nexport const isIncomingMessage = (res: unknown): res is IncomingMessage =>\n res != null &&\n typeof res === 'object' &&\n 'statusCode' in res &&\n 'headers' in res\n","import type { IncomingMessage, RequestOptions } from 'node:http'\nimport type { NormalisedRequest, NormalisedResponse, Protocol } from './types'\n\nexport const normHttpRequest = (req: RequestOptions): NormalisedRequest => {\n const hostname = String(req.hostname ?? req.host ?? '').split(':')[0]\n const port = Number(req.port ?? req.defaultPort ?? 80)\n const path = String(req.path ?? '/')\n const protocol: Protocol = port === 443 ? 'https' : 'http'\n\n return {\n method: req.method ?? 'GET',\n hostname,\n port,\n path,\n protocol,\n getHeader(name) {\n const headers = req.headers\n if (!headers || Array.isArray(headers)) return undefined\n return getHeaderFromObject(headers as Record<string, unknown>, name)\n },\n }\n}\n\nexport const normHttpResponse = (res: IncomingMessage): NormalisedResponse => {\n const socket = res.socket\n return {\n statusCode: res.statusCode ?? 0,\n statusMessage: res.statusMessage ?? '',\n getHeader(name) {\n return getHeaderFromObject(res.headers, name)\n },\n remoteAddress: socket?.remoteAddress,\n remotePort: socket?.remotePort,\n }\n}\n\nexport const getHeaderFromObject = (\n headers: Record<string, unknown> | undefined,\n name: string\n): string[] | undefined => {\n if (!headers) return undefined\n\n const target = name.toLowerCase()\n\n // Iterate over all keys to find case-insensitive match\n for (const key of Object.keys(headers)) {\n if (key.toLowerCase() === target) {\n const value = headers[key]\n if (Array.isArray(value)) return value\n /* istanbul ignore next */\n if (typeof value === 'string') return [value]\n /* istanbul ignore next */\n return undefined\n }\n }\n\n return undefined\n}\n","import type { Attributes } from '@opentelemetry/api'\nimport type { HttpInstrumentationConfig } from '@opentelemetry/instrumentation-http'\nimport {\n ATTR_HTTP_REQUEST_METHOD,\n ATTR_NETWORK_PEER_ADDRESS,\n ATTR_NETWORK_PEER_PORT,\n ATTR_NETWORK_PROTOCOL_VERSION,\n ATTR_SERVER_ADDRESS,\n ATTR_SERVER_PORT,\n ATTR_URL_FULL,\n ATTR_URL_PATH,\n ATTR_URL_SCHEME,\n} from '@opentelemetry/semantic-conventions'\nimport {\n applyRequestAttributes,\n applyResponseAttributes,\n} from './apply-attributes'\nimport { isClientRequest, isIncomingMessage, resolve } from './helpers'\nimport { normHttpRequest, normHttpResponse } from './normalize-http'\nimport type { OutgoingHttpEnrichmentConfig } from './types'\n\n/**\n * Build an HttpInstrumentationConfig that applies shared enrichment logic.\n *\n * The returned config can be spread with your own additional options:\n * new HttpInstrumentation({ ...buildHttpConfig(opts), requireParentforOutgoingSpans: true })\n */\nexport const buildHttpConfig = (\n opts: OutgoingHttpEnrichmentConfig = {}\n): HttpInstrumentationConfig => {\n const cfg = resolve(opts)\n\n const config: HttpInstrumentationConfig = {\n enabled: opts.enabled,\n ignoreOutgoingRequestHook(req) {\n if (!cfg.ignoreOutgoingPaths.length) return false\n const path = req.path ?? ''\n return cfg.ignoreOutgoingPaths.some((p) =>\n path.toLowerCase().startsWith(p.toLowerCase())\n )\n },\n\n // startOutgoingSpanHook fires at span creation time — before any proxy or\n // service-mesh sidecar can rewrite the destination socket. The returned\n // attributes are the \"ground truth\" hostname we captured off the wire.\n startOutgoingSpanHook(req) {\n const { method, hostname, port, path, protocol } = normHttpRequest(req)\n const [urlPath] = path.split('?')\n const defaultPort = protocol === 'https' ? 443 : 80\n const portSuffix = port !== defaultPort ? `:${port}` : ''\n /* istanbul ignore next */\n const resolvedUrlPath = urlPath ?? '/'\n\n const attrs: Attributes = {\n [ATTR_HTTP_REQUEST_METHOD]: method.toUpperCase(),\n [ATTR_SERVER_ADDRESS]: hostname,\n [ATTR_SERVER_PORT]: port,\n [ATTR_URL_SCHEME]: protocol,\n [ATTR_URL_PATH]: resolvedUrlPath,\n [ATTR_URL_FULL]: `${protocol}://${hostname}${portSuffix}${path}`,\n [ATTR_NETWORK_PEER_ADDRESS]: hostname,\n [ATTR_NETWORK_PEER_PORT]: port,\n }\n /* istanbul ignore next */\n for (const [key, val] of Object.entries(req.headers || {})) {\n if (!val) continue\n\n const name = key.toLowerCase().replace(/-/g, '_')\n const value = Array.isArray(val) ? val.join(',') : val\n attrs[`http.request.header.${name}`] = value\n }\n return attrs\n },\n\n requestHook(span, request) {\n // requestHook fires for both incoming (IncomingMessage) and outgoing\n // (ClientRequest) spans — skip the incoming side.\n if (!isClientRequest(request)) return\n\n // HTTP version isn't always accessible here, but try to read it.\n const proto = request.protocol\n if (proto) {\n span.setAttribute(\n ATTR_NETWORK_PROTOCOL_VERSION,\n /* istanbul ignore next */\n proto === 'https:' ? '1.1' : '1.1'\n )\n }\n\n applyRequestAttributes(span, normHttpRequest(request), cfg)\n },\n\n responseHook(span, response) {\n if (!isIncomingMessage(response)) return\n applyResponseAttributes(span, normHttpResponse(response), cfg)\n },\n }\n\n return config\n}\n","import type {\n UndiciRequest,\n UndiciResponse,\n} from '@opentelemetry/instrumentation-undici'\nimport type { NormalisedRequest, NormalisedResponse } from './types'\n\nexport const normUndiciRequest = (req: UndiciRequest): NormalisedRequest => {\n const origin = new URL(req.origin)\n const protocol = origin.protocol.replace(':', '') as 'http' | 'https'\n const port = Number(origin.port) || (protocol === 'https' ? 443 : 80)\n\n // Parse \"Key: Value\\r\\nKey2: Value2\\r\\n\" → Map\n const headers = parseUndiciRequestHeaders(req.headers)\n\n return {\n method: req.method,\n hostname: origin.hostname,\n port,\n path: req.path,\n protocol,\n getHeader: (name) => headers[name.toLowerCase()],\n }\n}\n\nexport const normUndiciResponse = (res: UndiciResponse): NormalisedResponse => {\n const headers = parseUndiciResponseHeaders(res.headers)\n\n return {\n statusCode: res.statusCode,\n statusMessage: res.statusText,\n getHeader: (name) => headers[name.toLowerCase()],\n }\n}\n\nexport const parseUndiciResponseHeaders = (\n headers: Buffer<ArrayBufferLike>[]\n): Record<string, string[]> => {\n const result: Record<string, string[]> = {}\n\n for (let i = 0; i < headers.length; i += 2) {\n const keyBuf = headers[i]\n const valBuf = headers[i + 1]\n\n if (!keyBuf || !valBuf) continue\n\n /* istanbul ignore next */\n const key = (\n Buffer.isBuffer(keyBuf)\n ? keyBuf.toString('utf8').trim()\n : Buffer.from(keyBuf as ArrayBuffer)\n .toString('utf8')\n .trim()\n ).toLowerCase()\n\n /* istanbul ignore next */\n const val = Buffer.isBuffer(valBuf)\n ? valBuf.toString('utf8').trim()\n : Buffer.from(valBuf as ArrayBuffer)\n .toString('utf8')\n .trim()\n\n if (!key || !val) continue\n\n if (!result[key]) result[key] = []\n result[key].push(val)\n }\n\n return result\n}\n\nexport const parseUndiciRequestHeaders = (\n headers: string | (string | string[])[]\n) => {\n const result: Record<string, string[]> = {}\n\n if (typeof headers === 'string') {\n // Single string format: \"key: value\"\n const [key, ...rest] = headers.split(':')\n if (key && rest.length > 0) {\n result[key.trim().toLowerCase()] = [rest.join(':').trim()]\n }\n } else {\n // The type union guarantees headers is string | array[]; the else-if is always true\n /* istanbul ignore else */\n if (Array.isArray(headers)) {\n // Array format: [key, value] or [key, [value1, value2]]\n for (let i = 0; i < headers.length; i += 2) {\n const key = headers[i]\n const val = headers[i + 1]\n if (typeof key !== 'string' || val == null) continue\n\n if (Array.isArray(val)) {\n result[key.toLowerCase()] = val.map((v) => String(v))\n } else {\n result[key.toLowerCase()] = [String(val)]\n }\n }\n }\n }\n\n return result\n}\n","import type { UndiciInstrumentationConfig } from '@opentelemetry/instrumentation-undici'\nimport {\n applyRequestAttributes,\n applyResponseAttributes,\n} from './apply-attributes'\nimport { resolve } from './helpers'\nimport { normUndiciRequest, normUndiciResponse } from './normalize-undici'\nimport type { OutgoingHttpEnrichmentConfig } from './types'\n\n/**\n * Build an UndiciInstrumentationConfig that applies shared enrichment logic.\n *\n * new UndiciInstrumentation(buildUndiciConfig(opts))\n */\nexport function buildUndiciConfig(\n opts: OutgoingHttpEnrichmentConfig = {}\n): UndiciInstrumentationConfig {\n const cfg = resolve(opts)\n\n const config: UndiciInstrumentationConfig = {\n enabled: opts.enabled,\n ignoreRequestHook(req) {\n if (!cfg.ignoreOutgoingPaths.length) return false\n const path = req.path ?? ''\n return cfg.ignoreOutgoingPaths.some((p) =>\n path.toLowerCase().startsWith(p.toLowerCase())\n )\n },\n\n // undici collapses startSpanHook + requestHook into a single requestHook\n // because diagnostics_channel gives us everything at once.\n requestHook(span, request) {\n applyRequestAttributes(span, normUndiciRequest(request), cfg)\n },\n\n responseHook(span, { response }) {\n applyResponseAttributes(span, normUndiciResponse(response), cfg)\n },\n }\n\n return config\n}\n","/* istanbul ignore file */\n/**\n * Shared enrichment logic for outgoing HTTP spans, normalised across\n * @opentelemetry/instrumentation-http (node:http / node:https)\n * @opentelemetry/instrumentation-undici (undici / global fetch)\n *\n * Usage:\n *\n * import { HttpInstrumentation } from '@opentelemetry/instrumentation-http'\n * import { UndiciInstrumentation } from '@opentelemetry/instrumentation-undici'\n * import { buildHttpConfig, buildUndiciConfig } from './instrumentation/outgoing-http'\n * import type { OutgoingHttpEnrichmentConfig } from './instrumentation/outgoing-http'\n *\n * const opts: OutgoingHttpEnrichmentConfig = {\n * captureRequestHeaders: ['x-tenant-id', 'x-request-id'],\n * captureResponseHeaders: ['x-ratelimit-remaining'],\n * enrichSpan: (span, req) =>\n * span.setAttribute('app.tenant.id', req.getHeader('x-tenant-id') ?? ''),\n * ignoreOutgoingPaths: ['/health', '/ready'],\n * }\n *\n * new HttpInstrumentation(buildHttpConfig(opts))\n * new UndiciInstrumentation(buildUndiciConfig(opts))\n */\n\nexport { buildHttpConfig } from './build-http-config'\nexport { buildUndiciConfig } from './build-undici-config'\nexport type { OutgoingHttpEnrichmentConfig } from './types'\n","import type {\n Instrumentation,\n InstrumentationConfig,\n} from '@opentelemetry/instrumentation'\nimport type { DnsInstrumentationConfig } from '@opentelemetry/instrumentation-dns'\nimport type { ExpressInstrumentationConfig } from '@opentelemetry/instrumentation-express'\nimport type { FsInstrumentationConfig } from '@opentelemetry/instrumentation-fs'\nimport type { GrpcInstrumentationConfig } from '@opentelemetry/instrumentation-grpc'\nimport type { RedisInstrumentationConfig } from '@opentelemetry/instrumentation-redis'\nimport type { SocketIoInstrumentationConfig } from '@opentelemetry/instrumentation-socket.io'\nimport type { OpenSearchInstrumentationConfig } from '@sebspark/opentelemetry-instrumentation-opensearch'\nimport {\n buildHttpConfig,\n buildUndiciConfig,\n type OutgoingHttpEnrichmentConfig,\n} from './enrichments/outgoing-http'\n\nconst cache = new Map<string, Promise<Instrumentation>>()\nconst cacheKey = (\n instrumentationName: string,\n config?: InstrumentationConfig\n) => {\n return config\n ? `${instrumentationName}:${JSON.stringify(config)}`\n : instrumentationName\n}\n\nexport const instrumentations = {\n http(config?: OutgoingHttpEnrichmentConfig) {\n const key = cacheKey('http', config)\n if (!cache.has(key)) {\n cache.set(\n key,\n import('@opentelemetry/instrumentation-http').then(\n ({ HttpInstrumentation }) =>\n new HttpInstrumentation(buildHttpConfig(config))\n )\n )\n }\n // biome-ignore lint/style/noNonNullAssertion: it will always exist\n return cache.get(key)!\n },\n\n express(config?: ExpressInstrumentationConfig) {\n const key = cacheKey('express', config)\n if (!cache.has(key)) {\n cache.set(\n key,\n import('@opentelemetry/instrumentation-express').then(\n ({ ExpressInstrumentation }) => new ExpressInstrumentation(config)\n )\n )\n }\n // biome-ignore lint/style/noNonNullAssertion: it will always exist\n return cache.get(key)!\n },\n\n grpc(config?: GrpcInstrumentationConfig) {\n const key = cacheKey('grpc', config)\n if (!cache.has(key)) {\n cache.set(\n key,\n import('@opentelemetry/instrumentation-grpc').then(\n ({ GrpcInstrumentation }) => new GrpcInstrumentation(config)\n )\n )\n }\n // biome-ignore lint/style/noNonNullAssertion: it will always exist\n return cache.get(key)!\n },\n\n redis(config?: RedisInstrumentationConfig) {\n const key = cacheKey('redis', config)\n if (!cache.has(key)) {\n cache.set(\n key,\n import('@opentelemetry/instrumentation-redis').then(\n ({ RedisInstrumentation }) => new RedisInstrumentation(config)\n )\n )\n }\n // biome-ignore lint/style/noNonNullAssertion: it will always exist\n return cache.get(key)!\n },\n\n dns(config?: DnsInstrumentationConfig) {\n const key = cacheKey('dns', config)\n if (!cache.has(key)) {\n cache.set(\n key,\n import('@opentelemetry/instrumentation-dns').then(\n ({ DnsInstrumentation }) => new DnsInstrumentation(config)\n )\n )\n }\n // biome-ignore lint/style/noNonNullAssertion: it will always exist\n return cache.get(key)!\n },\n\n net(config?: InstrumentationConfig) {\n const key = cacheKey('dns', config)\n if (!cache.has(key)) {\n cache.set(\n key,\n import('@opentelemetry/instrumentation-net').then(\n ({ NetInstrumentation }) => new NetInstrumentation(config)\n )\n )\n }\n // biome-ignore lint/style/noNonNullAssertion: it will always exist\n return cache.get(key)!\n },\n\n fs(config?: FsInstrumentationConfig) {\n const key = cacheKey('fs', config)\n if (!cache.has(key)) {\n cache.set(\n key,\n import('@opentelemetry/instrumentation-fs').then(\n ({ FsInstrumentation }) => new FsInstrumentation(config)\n )\n )\n }\n // biome-ignore lint/style/noNonNullAssertion: it will always exist\n return cache.get(key)!\n },\n\n undici(config?: OutgoingHttpEnrichmentConfig) {\n const key = cacheKey('undici', config)\n if (!cache.has(key)) {\n cache.set(\n key,\n import('@opentelemetry/instrumentation-undici').then(\n ({ UndiciInstrumentation }) =>\n new UndiciInstrumentation(buildUndiciConfig(config))\n )\n )\n }\n // biome-ignore lint/style/noNonNullAssertion: it will always exist\n return cache.get(key)!\n },\n\n socketIo(config?: SocketIoInstrumentationConfig) {\n const key = cacheKey('socket-io', config)\n if (!cache.has(key)) {\n cache.set(\n key,\n import('@opentelemetry/instrumentation-socket.io').then(\n ({ SocketIoInstrumentation }) => new SocketIoInstrumentation(config)\n )\n )\n }\n // biome-ignore lint/style/noNonNullAssertion: it will always exist\n return cache.get(key)!\n },\n\n opensearch(config?: OpenSearchInstrumentationConfig) {\n const key = cacheKey('opensearch', config)\n if (!cache.has(key)) {\n cache.set(\n key,\n import('@sebspark/opentelemetry-instrumentation-opensearch').then(\n ({ OpenSearchInstrumentation }) =>\n new OpenSearchInstrumentation({\n suppressInternalInstrumentation: true,\n ...(config || {}),\n })\n )\n )\n }\n // biome-ignore lint/style/noNonNullAssertion: it will always exist\n return cache.get(key)!\n },\n} as const\n","export const LOG_SEVERITY_MAP = {\n TRACE: 1,\n DEBUG: 5,\n INFO: 9,\n NOTICE: 10,\n WARNING: 13,\n WARN: 13,\n ERROR: 17,\n FATAL: 21,\n CRITICAL: 21,\n ALERT: 22,\n EMERGENCY: 23,\n} as const\n\nexport type LOG_SEVERITY_NAME = keyof typeof LOG_SEVERITY_MAP\n","import kleur from 'kleur'\n\nexport const colors = {\n gray: kleur.gray,\n dim: kleur.dim,\n cyan: kleur.cyan,\n white: kleur.white,\n green: kleur.green,\n yellow: kleur.yellow,\n red: kleur.red,\n magenta: kleur.magenta,\n}\n\nexport const levelColorMap: Record<string, (s: string) => string> = {\n DEBUG: kleur.magenta,\n INFO: kleur.green,\n WARN: kleur.yellow,\n ERROR: kleur.red,\n FATAL: kleur.red,\n}\n\nexport const levelIconMap: Record<string, string> = {\n DEBUG: '🐛',\n INFO: 'ℹ️ ',\n WARN: '⚠️ ',\n ERROR: '❌',\n FATAL: '💀',\n}\n\n// --- Span status codes (per OpenTelemetry spec) ---\nexport const statusLabelMap: Record<number, string> = {\n 0: 'UNSET',\n 1: 'OK',\n 2: 'ERROR',\n}\n\nexport const statusColorMap: Record<number, (s: string) => string> = {\n 0: colors.gray, // UNSET\n 1: colors.green, // OK\n 2: colors.red, // ERROR\n}\n\n// --- Span kinds (for visual context: client/server etc.) ---\nexport const kindLabelMap: Record<number, string> = {\n 0: 'INTERNAL',\n 1: 'SERVER',\n 2: 'CLIENT',\n 3: 'PRODUCER',\n 4: 'CONSUMER',\n}\n\nexport const kindColorMap: Record<number, (s: string) => string> = {\n 0: colors.white, // INTERNAL\n 1: colors.cyan, // SERVER\n 2: colors.yellow, // CLIENT\n 3: colors.magenta, // PRODUCER\n 4: colors.green, // CONSUMER\n}\n","import type { Attributes, HrTime } from '@opentelemetry/api'\nimport type { Resource } from '@opentelemetry/resources'\nimport type { ReadableLogRecord } from '@opentelemetry/sdk-logs'\nimport type { ReadableSpan } from '@opentelemetry/sdk-trace'\nimport {\n ATTR_SERVICE_NAME,\n ATTR_SERVICE_VERSION,\n} from '@opentelemetry/semantic-conventions'\nimport fss from 'fast-safe-stringify'\nimport { colors, levelColorMap, levelIconMap } from './style'\n\nconst stringify = fss.default.stableStringify\n\ntype IResource = Pick<Resource, 'attributes'>\ntype IInstrumentation = ReadableLogRecord['instrumentationScope']\n\nexport function formatTimestamp(time: HrTime): string {\n const date = new Date(hrTimeToMillis(time))\n return colors.dim(date.toISOString().slice(11, 23)) // HH:mm:ss.sss\n}\n\nexport function formatService(resource: IResource): string {\n const name = resource.attributes[ATTR_SERVICE_NAME] ?? 'unknown-service'\n const version = resource.attributes[ATTR_SERVICE_VERSION] ?? '1.0.0'\n return colors.gray(`[${name}@${version}]`)\n}\n\nexport function formatLevel(record: ReadableLogRecord): string {\n const text = (record.severityText ?? 'INFO').toUpperCase()\n const colorFn = levelColorMap[text] ?? colors.white\n const icon = levelIconMap[text] ?? '•'\n return `${icon} ${colorFn(text.padEnd(5))}`\n}\n\nexport function formatScope(\n resource: IResource,\n instrumentationScope: IInstrumentation\n): string {\n const component = resource.attributes['component.name']\n const { name } = instrumentationScope\n const scopeLabel =\n component || (name && name !== 'unknown' ? name : undefined)\n\n if (!scopeLabel) return ''\n\n return colors.cyan(`${scopeLabel} `)\n}\n\nexport function formatMessage(record: ReadableLogRecord): string {\n return typeof record.body === 'string' ? record.body : stringify(record.body)\n}\n\nexport function formatAttributes(attrs: Attributes): string {\n const keys = Object.keys(attrs).filter(\n (k) =>\n !k.startsWith('service.') &&\n !k.startsWith('serviceContext.') &&\n k !== 'cloud.orchestrator' &&\n k !== 'component.name'\n )\n if (keys.length === 0) return ''\n const formatted = keys.map((k) => {\n const val = attrs[k]\n return `${k}=${typeof val === 'object' ? stringify(val) : val}`\n })\n return ` ${colors.gray(formatted.join(' '))}`\n}\n\nexport function hrTimeToMillis(hrTime: [number, number]): number {\n return hrTime[0] * 1000 + Math.floor(hrTime[1] / 1_000_000)\n}\n\nexport function calculateDuration(span: ReadableSpan): number {\n const start = hrTimeToMillis(span.startTime)\n const end = hrTimeToMillis(span.endTime)\n return Math.max(0, Math.round(end - start))\n}\n","import type { ReadableLogRecord } from '@opentelemetry/sdk-logs'\nimport {\n formatAttributes,\n formatLevel,\n formatMessage,\n formatScope,\n formatService,\n formatTimestamp,\n} from './shared'\n\nexport function formatLogRecord(record: ReadableLogRecord): string {\n const timestamp = formatTimestamp(record.hrTime)\n const service = formatService(record.resource)\n const level = formatLevel(record)\n const scope = formatScope(record.resource, record.instrumentationScope)\n const message = formatMessage(record)\n const attrs = formatAttributes(record.attributes)\n\n return `${service} ${timestamp} ${level} ${scope}${message}${attrs}`\n}\n","import type { Resource } from '@opentelemetry/resources'\nimport type {\n DataPoint,\n MetricData,\n ResourceMetrics,\n ScopeMetrics,\n} from '@opentelemetry/sdk-metrics'\nimport {\n formatAttributes,\n formatScope,\n formatService,\n formatTimestamp,\n} from './shared'\nimport { colors } from './style'\n\nexport function formatMetrics(resourceMetrics: ResourceMetrics): string {\n const { resource, scopeMetrics } = resourceMetrics\n\n return scopeMetrics\n .map((scopeMetric) => formatScopeMetric(scopeMetric, resource))\n .join('\\n')\n}\n\nfunction formatScopeMetric(\n scopeMetric: ScopeMetrics,\n resource: Resource\n): string {\n return scopeMetric.metrics\n .map((metric: MetricData) =>\n formatMetricData(metric, resource, scopeMetric.scope)\n )\n .join('\\n')\n}\n\nfunction formatMetricData(\n metric: MetricData,\n resource: Resource,\n scope: ScopeMetrics['scope']\n): string {\n const scopeStr = formatScope(resource, scope)\n const serviceStr = formatService(resource)\n\n const lines: string[] = []\n\n for (const dp of metric.dataPoints) {\n const ts = formatTimestamp(dp.startTime)\n const value = extractMetricValue(dp)\n const attrs = formatAttributes(dp.attributes ?? {})\n\n lines.push(\n `${serviceStr} ${ts} 📊 ${scopeStr}${colors.white(metric.descriptor.name)} ${colors.dim(value)}${attrs}`\n )\n }\n\n return lines.join('\\n')\n}\n\nfunction extractMetricValue(dp: DataPoint<unknown>): string {\n const value = dp.value\n\n if (typeof value === 'number') {\n return value.toString()\n }\n\n if (isHistogramLike(value)) {\n return value.sum.toString()\n }\n\n return '[complex]'\n}\n\nfunction isHistogramLike(val: unknown): val is { sum: number } {\n return (\n typeof val === 'object' &&\n val !== null &&\n 'sum' in val &&\n typeof (val as { sum: number }).sum === 'number'\n )\n}\n","import { SpanStatusCode } from '@opentelemetry/api'\nimport type { ReadableSpan } from '@opentelemetry/sdk-trace'\nimport {\n calculateDuration,\n formatService,\n formatTimestamp,\n hrTimeToMillis,\n} from './shared'\nimport { colors, statusColorMap, statusLabelMap } from './style'\n\nconst LABEL_WIDTH = 20\nconst DESCRIPTION_MAX_WIDTH = 16\nconst BAR_MIN_WIDTH = 1\nconst BAR_MAX_WIDTH = 20\n\nexport function formatSpans(spans: ReadableSpan[]) {\n const rootSpan = spans[0]\n const rootStart = hrTimeToMillis(rootSpan.startTime)\n const rootEnd = hrTimeToMillis(rootSpan.endTime)\n const totalDuration = rootEnd - rootStart\n\n const service = formatService(rootSpan.resource)\n const timestamp = formatTimestamp(rootSpan.startTime)\n const traceId = colors.gray(`[${rootSpan.spanContext().traceId}]`)\n\n const lines = [`${service} ${timestamp} ${traceId}`]\n\n for (const span of spans) {\n const offset = hrTimeToMillis(span.startTime) - rootStart\n const depth = computeDepth(span, spans) // optional\n lines.push(\n formatSpan(span, {\n offsetMs: offset,\n totalDurationMs: totalDuration,\n depth,\n })\n )\n }\n\n return lines.join('\\n')\n}\n\nexport function formatSpan(\n span: ReadableSpan,\n opts: {\n offsetMs: number // relative start time in ms (0 for root)\n totalDurationMs: number // total duration in ms (root span duration)\n depth: number // nesting level for indent\n }\n): string {\n const label = formatLabel(span, opts.depth)\n const bar = buildBar(span, opts?.offsetMs, opts?.totalDurationMs)\n const barColor =\n span.status.code === SpanStatusCode.OK\n ? colors.green\n : span.status.code === SpanStatusCode.ERROR\n ? colors.red\n : colors.gray\n const desc = formatDescription(span)\n const status = formatStatus(span)\n const duration = formatDuration(span, opts?.offsetMs)\n const spanId = colors.gray(`[${span.spanContext().spanId}]`)\n\n return `${label} ${barColor(bar)} ${desc} ${status} ${duration} ${spanId}`\n}\n\nfunction formatLabel(span: ReadableSpan, depth: number) {\n const indent = ' '.repeat(depth) // 2 spaces per depth level\n const label = `${indent}└─ ${span.name}`\n return label.padEnd(LABEL_WIDTH)\n}\n\nfunction buildBar(\n span: ReadableSpan,\n offsetMs: number | undefined,\n totalDurationMs: number | undefined\n) {\n const duration = calculateDuration(span)\n\n if (\n typeof offsetMs !== 'number' ||\n typeof totalDurationMs !== 'number' ||\n totalDurationMs === 0\n ) {\n // fallback: show duration-only bar\n const capped = Math.min(duration, 1000)\n const barLength = Math.max(\n BAR_MIN_WIDTH,\n Math.round((capped / 1000) * BAR_MAX_WIDTH)\n )\n return '█'.repeat(barLength).padEnd(BAR_MAX_WIDTH + 2)\n }\n\n // Relative position and size\n const offsetRatio = Math.max(0, Math.min(offsetMs / totalDurationMs, 1))\n const durationRatio = Math.max(0, Math.min(duration / totalDurationMs, 1))\n\n const offsetChars = Math.floor(offsetRatio * BAR_MAX_WIDTH)\n const barChars = Math.max(\n BAR_MIN_WIDTH,\n Math.round(durationRatio * BAR_MAX_WIDTH)\n )\n\n const empty = ' '.repeat(offsetChars)\n const bar = '█'.repeat(barChars)\n\n return (empty + bar).padEnd(BAR_MAX_WIDTH + 2)\n}\n\nfunction formatDescription(span: ReadableSpan): string {\n const keyPriority = [\n // HTTP\n ['http.method', 'http.target'], // → GET /users/123\n ['http.route'], // → /users/:id\n ['http.url'], // → https://...\n\n // GraphQL\n ['graphql.operation.name'], // → getUsers\n ['graphql.operation.type'], // → query\n ['graphql.document'], // → full query text (maybe too long)\n\n // WebSocket\n ['ws.event'], // → connection, message, disconnect\n ['ws.message_type'], // → ping/pong/text/binary\n ['ws.url'], // → wss://...\n\n // Redis\n ['db.system', 'db.statement'], // → redis, \"SET foo bar\"\n ['db.operation'], // → GET, SET\n\n // Spanner\n ['db.statement'], // → SELECT * FROM...\n ['db.operation'], // → SELECT, INSERT\n ['db.name'], // → projects/.../instances/.../databases/...\n\n // OpenSearch\n ['db.operation'], // → search, index, bulk\n ['db.statement'], // → { query DSL... }\n\n // Pub/Sub (GCP)\n ['messaging.operation'], // → publish, receive\n ['messaging.destination'], // → topic-a\n ['messaging.gcp_pubsub.topic'], // → projects/x/topics/y\n\n // General FaaS\n ['faas.invoked_name'], // → myFunction\n ['faas.trigger'], // → http, pubsub, etc.\n\n // Custom or fallback\n ['otel.description'],\n ]\n\n for (const keys of keyPriority) {\n const parts = keys\n .map((k) => span.attributes[k])\n .filter((v) => v !== undefined && v !== null)\n .map((v) => String(v)) // 👈 FIX — guarantees string\n if (parts.length > 0) {\n return truncate(parts.join(' '), DESCRIPTION_MAX_WIDTH - 1).padEnd(\n DESCRIPTION_MAX_WIDTH\n )\n }\n }\n\n return ''.padEnd(DESCRIPTION_MAX_WIDTH)\n}\n\nfunction formatStatus(span: ReadableSpan): string {\n const code = span.status.code\n const label = statusLabelMap[code] ?? 'UNSET'\n const colorFn = statusColorMap[code] ?? colors.gray\n return colorFn(label).padEnd(6)\n}\n\nfunction formatDuration(\n span: ReadableSpan,\n offsetMs: number | undefined\n): string {\n const duration = calculateDuration(span)\n\n const format = (ms: number): string =>\n ms >= 1000 ? `${(ms / 1000).toFixed(2)} s` : `${ms} ms`\n\n return `(${format(offsetMs || 0)}–${format(duration)})`.padEnd(16)\n}\n\nfunction truncate(input: unknown, maxLength: number): string {\n // In practice, input is always a string — the String() cast is a defensive fallback.\n const str = String(input)\n return str.length > maxLength ? `${str.slice(0, maxLength - 1)}…` : str\n}\n\nfunction computeDepth(span: ReadableSpan, allSpans: ReadableSpan[]): number {\n let depth = 0\n let currentParentId = span.parentSpanContext?.spanId\n\n while (currentParentId) {\n const parentSpan = allSpans.find(\n (s) => s.spanContext().spanId === currentParentId\n )\n if (!parentSpan) break\n\n depth += 1\n currentParentId = parentSpan.parentSpanContext?.spanId\n }\n\n return depth\n}\n","/* istanbul ignore file */\nexport * from './log-record'\nexport * from './metrics'\nexport * from './span'\n","import { type ExportResult, ExportResultCode } from '@opentelemetry/core'\nimport type {\n PushMetricExporter,\n ResourceMetrics,\n} from '@opentelemetry/sdk-metrics'\nimport { formatMetrics } from './formatters/index'\n\nexport class ConsoleMetricPrettyExporter implements PushMetricExporter {\n private readonly patterns: RegExp[]\n\n constructor() {\n const raw = process.env.METRIC_FILTER ?? ''\n const entries = raw\n .split(',')\n .map((e) => e.trim())\n .filter(Boolean)\n\n this.patterns = entries.map(globToRegex)\n }\n\n private filterMetrics(\n resourceMetrics: ResourceMetrics\n ): ResourceMetrics | undefined {\n // No filter = block all metrics\n if (this.patterns.length === 0) return undefined\n\n const filteredScopes = resourceMetrics.scopeMetrics\n .map((scopeMetric) => {\n const filteredMetrics = scopeMetric.metrics.filter((metric) =>\n this.patterns.some((pattern) => pattern.test(metric.descriptor.name))\n )\n\n if (filteredMetrics.length === 0) return undefined\n\n return {\n ...scopeMetric,\n metrics: filteredMetrics,\n }\n })\n .filter((s): s is NonNullable<typeof s> => s !== undefined)\n\n if (filteredScopes.length === 0) return undefined\n\n return {\n ...resourceMetrics,\n scopeMetrics: filteredScopes,\n }\n }\n\n export(\n metrics: ResourceMetrics,\n resultCallback: (result: ExportResult) => void\n ): void {\n const filtered = this.filterMetrics(metrics)\n if (filtered) {\n console.log(formatMetrics(filtered))\n }\n resultCallback({ code: ExportResultCode.SUCCESS })\n }\n\n shutdown(): Promise<void> {\n return Promise.resolve()\n }\n\n forceFlush(): Promise<void> {\n return Promise.resolve()\n }\n}\n\nfunction globToRegex(glob: string): RegExp {\n const escaped = glob.replace(/[.+^${}()|[\\]\\\\]/g, '\\\\$&')\n const regex = `^${escaped.replace(/\\*/g, '.*')}$`\n return new RegExp(regex)\n}\n","import { SeverityNumber } from '@opentelemetry/api'\nimport { type ExportResult, ExportResultCode } from '@opentelemetry/core'\nimport type {\n LogRecordExporter,\n ReadableLogRecord,\n} from '@opentelemetry/sdk-logs'\nimport { LOG_SEVERITY_MAP, type LOG_SEVERITY_NAME } from '../consts'\nimport { formatLogRecord } from './formatters/index'\n\nexport class ConsoleLogPrettyExporter implements LogRecordExporter {\n private readonly logThreshold: number\n constructor() {\n const defaultLogLevel = 'INFO'\n const env = (process.env.LOG_LEVEL?.toUpperCase() ??\n defaultLogLevel) as LOG_SEVERITY_NAME\n this.logThreshold =\n LOG_SEVERITY_MAP[env] ?? LOG_SEVERITY_MAP[defaultLogLevel]\n }\n export(\n logs: ReadableLogRecord[],\n resultCallback: (result: ExportResult) => void\n ): void {\n this._sendLogRecords(logs, resultCallback)\n }\n\n shutdown(): Promise<void> {\n return Promise.resolve()\n }\n\n forceFlush(): Promise<void> {\n return Promise.resolve()\n }\n\n private _sendLogRecords(\n logRecords: ReadableLogRecord[],\n done: (result: ExportResult) => void\n ): void {\n for (const record of logRecords) {\n if ((record.severityNumber ?? 0) >= this.logThreshold) {\n const formatted = formatLogRecord(record)\n /* istanbul ignore next */\n const severity = record.severityNumber || SeverityNumber.UNSPECIFIED\n\n if (severity >= SeverityNumber.ERROR) {\n console.error(formatted)\n } else if (severity >= SeverityNumber.WARN) {\n console.log(formatted)\n } else if (severity >= SeverityNumber.INFO) {\n console.info(formatted)\n } else if (severity >= SeverityNumber.DEBUG) {\n console.debug(formatted)\n } else {\n console.trace(formatted)\n }\n }\n }\n\n done?.({ code: ExportResultCode.SUCCESS })\n }\n}\n","import { SpanStatusCode } from '@opentelemetry/api'\nimport { type ExportResult, ExportResultCode } from '@opentelemetry/core'\nimport type { ReadableSpan, SpanExporter } from '@opentelemetry/sdk-trace'\nimport { formatSpans } from './formatters/index'\n\nexport class ConsoleSpanPrettyExporter implements SpanExporter {\n private readonly allowedStatuses: Set<number>\n\n constructor() {\n const env = process.env.SPAN_LEVEL?.toUpperCase()\n if (!env) {\n this.allowedStatuses = new Set([\n SpanStatusCode.UNSET,\n SpanStatusCode.OK,\n SpanStatusCode.ERROR,\n ])\n } else {\n const map: Record<string, number> = {\n UNSET: SpanStatusCode.UNSET,\n OK: SpanStatusCode.OK,\n ERROR: SpanStatusCode.ERROR,\n }\n\n this.allowedStatuses = new Set(\n env\n .split(',')\n .map((s) => s.trim())\n .map((s) => map[s])\n .filter((v): v is number => typeof v === 'number')\n )\n }\n }\n\n private shouldExport(spans: ReadableSpan[]) {\n // print all spans\n if (this.allowedStatuses.size === 3) {\n return true\n }\n // print only certain levels\n return spans.some((span) => this.allowedStatuses.has(span.status.code))\n }\n\n export(\n spans: ReadableSpan[],\n resultCallback: (result: ExportResult) => void\n ): void {\n if (this.shouldExport(spans)) {\n console.log(formatSpans(spans))\n }\n\n resultCallback({ code: ExportResultCode.SUCCESS })\n }\n\n shutdown(): Promise<void> {\n return Promise.resolve()\n }\n}\n","/* istanbul ignore file */\nexport * from './console-log-pretty-exporter'\nexport * from './console-span-pretty-exporter'\nexport * from './gcp-json-log-exporter'\n","import type {\n ReadableSpan,\n SpanExporter,\n SpanProcessor,\n} from '@opentelemetry/sdk-trace'\n\nexport class TreeSpanProcessor implements SpanProcessor {\n private exporter: SpanExporter\n private orphans: Map<string, ReadableSpan[]> = new Map()\n\n constructor(exporter: SpanExporter) {\n this.exporter = exporter\n }\n\n onStart(): void {\n // no-op\n }\n\n onEnd(span: ReadableSpan): void {\n const parentId = span.parentSpanContext?.spanId\n\n if (parentId) {\n const siblings = this.orphans.get(parentId) || []\n this.orphans.set(parentId, [...siblings, span])\n\n return\n }\n\n const children = this.getChildrenRecursively(span)\n const sorted = [span, ...children].sort((s1, s2) => {\n const [sec1, nano1] = s1.startTime\n const [sec2, nano2] = s2.startTime\n\n if (sec1 !== sec2) return sec1 - sec2\n return nano1 - nano2\n })\n this.exporter.export(sorted, () => {})\n }\n\n private getChildrenRecursively(span: ReadableSpan) {\n const spanId = span.spanContext().spanId\n const children = this.orphans.get(spanId) || []\n this.orphans.delete(spanId)\n\n const result = [...children]\n for (const child of children) {\n result.push(...this.getChildrenRecursively(child))\n }\n\n return result\n }\n\n shutdown(): Promise<void> {\n return this.exporter.shutdown()\n }\n\n async forceFlush(): Promise<void> {\n await this.exporter.forceFlush?.()\n }\n}\n","import { OTLPLogExporter } from '@opentelemetry/exporter-logs-otlp-http'\nimport { OTLPMetricExporter } from '@opentelemetry/exporter-metrics-otlp-http'\nimport { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http'\nimport type { Resource } from '@opentelemetry/resources'\nimport {\n BatchLogRecordProcessor,\n LoggerProvider,\n type LogRecordProcessor,\n SimpleLogRecordProcessor,\n} from '@opentelemetry/sdk-logs'\nimport { PeriodicExportingMetricReader } from '@opentelemetry/sdk-metrics'\nimport {\n BatchSpanProcessor,\n SimpleSpanProcessor,\n type SpanProcessor,\n} from '@opentelemetry/sdk-trace'\nimport { ConsoleMetricPrettyExporter } from './loggers/console-metric-pretty-exporter'\nimport {\n ConsoleLogPrettyExporter,\n ConsoleSpanPrettyExporter,\n} from './loggers/index'\nimport { TreeSpanProcessor } from './loggers/tree-span-processor'\n\nexport const getLogProvider = (\n resource: Resource,\n otlpEndpoint: string | undefined\n) => {\n // With collector\n if (otlpEndpoint) {\n const otlpExporter = new OTLPLogExporter({ url: `${otlpEndpoint}/v1/logs` })\n const processors: LogRecordProcessor[] = [\n new BatchLogRecordProcessor({ exporter: otlpExporter }),\n ]\n\n // Console logging for cluster\n if (process.env.LOG_LEVEL) {\n const consoleExporter = new ConsoleLogPrettyExporter()\n processors.push(\n new SimpleLogRecordProcessor({ exporter: consoleExporter })\n )\n }\n\n return new LoggerProvider({\n resource,\n processors,\n })\n }\n\n // Local dev\n const consoleExporter = new ConsoleLogPrettyExporter()\n const processor = new SimpleLogRecordProcessor({ exporter: consoleExporter })\n return new LoggerProvider({\n resource,\n processors: [processor],\n })\n}\n\nexport const getSpanProcessor = (\n otlpEndpoint: string | undefined\n): SpanProcessor => {\n const exporter = otlpEndpoint\n ? new OTLPTraceExporter({\n url: `${otlpEndpoint}/v1/traces`,\n })\n : new ConsoleSpanPrettyExporter()\n\n if (!otlpEndpoint) {\n return new TreeSpanProcessor(exporter)\n }\n\n if (process.env.OTEL_SIMPLE_SPAN_PROCESSOR === 'true') {\n console.log(\n '[otel] Using SimpleSpanProcessor (OTEL_SIMPLE_SPAN_PROCESSOR=true)'\n )\n return new SimpleSpanProcessor({ exporter })\n }\n\n return new BatchSpanProcessor({ exporter })\n}\n\nexport const getMetricReader = (otlpEndpoint: string | undefined) => {\n const metricExporter = otlpEndpoint\n ? new OTLPMetricExporter({\n url: `${otlpEndpoint}/v1/metrics`,\n })\n : new ConsoleMetricPrettyExporter()\n const metricReader = new PeriodicExportingMetricReader({\n exporter: metricExporter,\n })\n\n return metricReader\n}\n","import {\n ATTR_SERVICE_NAME,\n ATTR_SERVICE_VERSION,\n} from '@opentelemetry/semantic-conventions'\n\n/**\n * Extracts telemetry context from environment (cloud/k8s aware),\n * with support for subservice/component override.\n */\nexport function detectTelemetryContext(componentNameOverride?: string) {\n const {\n OTEL_SERVICE_NAME, // e.g. \"UserSystem\"\n OTEL_SERVICE_VERSION, // e.g. \"1.2.3\"\n K_SERVICE,\n K_REVISION,\n K_CONFIGURATION,\n KUBERNETES_SERVICE_HOST,\n POD_NAME,\n POD_NAMESPACE,\n GCP_PROJECT,\n CLOUD_PROVIDER,\n } = process.env\n\n const systemName = OTEL_SERVICE_NAME || 'unknown-service'\n const systemVersion = OTEL_SERVICE_VERSION || '1.0.0'\n\n // Only use component if explicitly provided\n const componentName = componentNameOverride || undefined\n\n const resourceAttributes = {\n [ATTR_SERVICE_NAME]: systemName,\n [ATTR_SERVICE_VERSION]: systemVersion,\n 'serviceContext.service': systemName,\n 'serviceContext.version': systemVersion,\n ...(K_SERVICE && { 'cloud.run.service': K_SERVICE }),\n ...(K_REVISION && { 'cloud.run.revision': K_REVISION }),\n ...(K_CONFIGURATION && { 'cloud.run.configuration': K_CONFIGURATION }),\n ...(POD_NAME && { 'k8s.pod_name': POD_NAME }),\n ...(POD_NAMESPACE && { 'k8s.namespace_name': POD_NAMESPACE }),\n ...(KUBERNETES_SERVICE_HOST && { 'cloud.orchestrator': 'kubernetes' }),\n ...(GCP_PROJECT && { 'cloud.account.id': GCP_PROJECT }),\n ...(CLOUD_PROVIDER && { 'cloud.provider': CLOUD_PROVIDER }),\n ...(componentName && { 'component.name': componentName }),\n }\n\n return {\n systemName,\n systemVersion,\n componentName,\n resourceAttributes,\n }\n}\n","import { containerDetector } from '@opentelemetry/resource-detector-container'\nimport { gcpDetector } from '@opentelemetry/resource-detector-gcp'\nimport {\n detectResources,\n envDetector,\n osDetector,\n processDetector,\n resourceFromAttributes,\n serviceInstanceIdDetector,\n} from '@opentelemetry/resources'\nimport { detectTelemetryContext } from './otel-context'\n\nconst isOnGcp = () =>\n !!(\n process.env.K_SERVICE ||\n process.env.GAE_APPLICATION ||\n process.env.KUBERNETES_SERVICE_HOST\n )\n\nexport const getResource = async () => {\n const baseRes = detectResources({\n detectors: [\n containerDetector,\n envDetector,\n ...(isOnGcp() ? [gcpDetector] : []),\n osDetector,\n processDetector,\n serviceInstanceIdDetector,\n ],\n })\n\n if (baseRes.waitForAsyncAttributes) {\n await baseRes.waitForAsyncAttributes()\n }\n\n const { resourceAttributes } = detectTelemetryContext()\n const customRes = resourceFromAttributes(resourceAttributes)\n const resource = baseRes.merge(customRes)\n\n if (resource.waitForAsyncAttributes) {\n await resource.waitForAsyncAttributes()\n }\n\n return resource\n}\n","import {\n context,\n DiagConsoleLogger,\n DiagLogLevel,\n diag,\n logs,\n metrics,\n trace,\n} from '@opentelemetry/api'\nimport type { Instrumentation } from '@opentelemetry/instrumentation'\nimport type { LoggerProvider } from '@opentelemetry/sdk-logs'\nimport { NodeSDK } from '@opentelemetry/sdk-node'\nimport { getLogProvider, getMetricReader, getSpanProcessor } from './providers'\nimport { getResource } from './resource'\n\ndiag.disable()\ndiag.setLogger(new DiagConsoleLogger(), DiagLogLevel.ERROR)\n\n// Use globalThis with a Symbol key so the flag is shared even when the module\n// is instantiated more than once (e.g. --import preload vs main app graph when\n// using tsx or other loaders that don't share the ESM module cache).\nconst OTEL_INIT_KEY = Symbol.for('@sebspark/otel:initialized')\nconst OTEL_INIT_PROMISE_KEY = Symbol.for('@sebspark/otel:initPromise')\n\nfunction getGlobal(): {\n [key: symbol]: unknown\n} {\n return globalThis as Record<symbol, unknown>\n}\n\nexport async function initialize(\n ...instrumentations: Promise<Instrumentation>[]\n) {\n const g = getGlobal()\n if (!g[OTEL_INIT_PROMISE_KEY]) {\n const resolvedInstrumentations = await Promise.all(instrumentations)\n const promise = _initialize(resolvedInstrumentations).catch((err) => {\n // Allow re-initialization if the first attempt fails\n g[OTEL_INIT_PROMISE_KEY] = undefined\n throw err\n })\n g[OTEL_INIT_PROMISE_KEY] = promise\n }\n return g[OTEL_INIT_PROMISE_KEY] as Promise<void>\n}\n\nexport function isInitialized() {\n return getGlobal()[OTEL_INIT_KEY] === true\n}\n\nlet sdk: NodeSDK | undefined\nlet logProvider: LoggerProvider | undefined\n\nasync function _initialize(instrumentations: Instrumentation[]) {\n const serviceName = process.env.OTEL_SERVICE_NAME ?? 'unknown-service'\n const otlpEndpoint = process.env.OTEL_EXPORTER_OTLP_ENDPOINT\n\n const resource = await getResource()\n\n // Reset any previous instrumentation\n context.disable()\n logs.disable()\n trace.disable()\n metrics.disable()\n\n // Manual setup for logs\n logProvider = getLogProvider(resource, otlpEndpoint)\n logs.setGlobalLoggerProvider(logProvider)\n\n // NodeSDK setup\n const spanProcessor = getSpanProcessor(otlpEndpoint)\n const metricReader = getMetricReader(otlpEndpoint)\n sdk = new NodeSDK({\n spanProcessors: [spanProcessor],\n metricReaders: [metricReader],\n instrumentations,\n resource,\n })\n\n sdk.start()\n getGlobal()[OTEL_INIT_KEY] = true\n console.log(`[otel] Telemetry initialized for \"${serviceName}\"`)\n}\n\nexport const dispose = async () => {\n const processes: Promise<void>[] = []\n if (sdk) processes.push(sdk.shutdown())\n if (logProvider) processes.push(logProvider.shutdown())\n\n // Only initiate shotdown once\n sdk = undefined\n logProvider = undefined\n\n if (processes.length) {\n console.log('[otel] Shutting down...')\n await Promise.all(processes)\n console.log('[otel] Shutdown complete.')\n }\n}\n","import { context, logs, trace } from '@opentelemetry/api'\nimport { LOG_SEVERITY_MAP, type LOG_SEVERITY_NAME } from './consts'\nimport { isInitialized } from './otel'\nimport { detectTelemetryContext } from './otel-context'\n\n// biome-ignore lint/suspicious/noExplicitAny: library\ntype Attrs = Record<string, any>\n\nexport type Logger = ReturnType<typeof getLogger>\nexport function getLogger(serviceOverride?: string, extraAttrs: Attrs = {}) {\n const { systemName, systemVersion, resourceAttributes } =\n detectTelemetryContext(serviceOverride)\n\n const defaultAttrs = {\n ...resourceAttributes,\n ...extraAttrs,\n }\n\n let hasWarnedAboutInit = false\n\n function emit(\n severityText: LOG_SEVERITY_NAME,\n body: string,\n attrs: Attrs = {}\n ) {\n // Get the logger at the last second\n if (!isInitialized() && process.env.NODE_ENV !== 'test') {\n if (!hasWarnedAboutInit) {\n console.warn('OTEL must be initialized before using logger')\n hasWarnedAboutInit = true\n }\n console.log(`[${severityText}] ${body}`)\n return\n }\n const logger = logs.getLogger(systemName, systemVersion)\n\n const span = trace.getSpan(context.active())\n const spanContext = span?.spanContext()\n\n logger.emit({\n severityText,\n severityNumber: LOG_SEVERITY_MAP[severityText],\n body,\n attributes: {\n 'gcp.log_name': systemName.replace(/^@/, '').replace(/\\//g, '-'),\n ...defaultAttrs,\n ...(spanContext && {\n trace_id: spanContext.traceId,\n span_id: spanContext.spanId,\n }),\n ...attrs,\n },\n })\n }\n\n function resolveArgs(\n msg: string | Error,\n errOrAttrs?: Error | Attrs,\n maybeAttrs: Attrs = {}\n ): { body: string; attrs: Attrs } {\n if (errOrAttrs instanceof Error) {\n /* istanbul ignore next */\n const body = `${msg}: ${errOrAttrs.stack || errOrAttrs.message}`\n return { body, attrs: maybeAttrs }\n }\n\n /* istanbul ignore next */\n const body = msg instanceof Error ? msg.stack || msg.message : msg\n /* istanbul ignore next */\n const attrs = errOrAttrs || {}\n return { body, attrs }\n }\n\n type LogFn = {\n (msg: string, attrs?: Attrs): void\n (msg: string, error: Error, attrs?: Attrs): void\n (error: Error, attrs?: Attrs): void\n }\n\n function createLogFn(severity: LOG_SEVERITY_NAME): LogFn {\n return (\n msg: string | Error,\n errOrAttrs?: Error | Attrs,\n maybeAttrs: Attrs = {}\n ) => {\n const { body, attrs } = resolveArgs(msg, errOrAttrs, maybeAttrs)\n emit(severity, body, attrs)\n }\n }\n\n return {\n debug: createLogFn('DEBUG'),\n info: createLogFn('INFO'),\n notice: createLogFn('NOTICE'),\n warn: createLogFn('WARN'),\n error: createLogFn('ERROR'),\n critical: createLogFn('CRITICAL'),\n alert: createLogFn('ALERT'),\n emergency: createLogFn('EMERGENCY'),\n }\n}\n","import { metrics } from '@opentelemetry/api'\nimport { isInitialized } from './otel'\nimport { detectTelemetryContext } from './otel-context'\n\nexport function getMeter(componentNameOverride?: string) {\n if (!isInitialized() && process.env.NODE_ENV !== 'test') {\n console.warn('OTEL must be initialized before using getMeter()')\n }\n\n const { componentName, systemName, systemVersion } = detectTelemetryContext(\n componentNameOverride\n )\n return metrics.getMeter(componentName ?? systemName, systemVersion)\n}\n","import {\n context,\n type SpanOptions,\n SpanStatusCode,\n trace,\n} from '@opentelemetry/api'\nimport { isInitialized } from './otel'\nimport { detectTelemetryContext } from './otel-context'\n\ntype OtelTracer = ReturnType<typeof trace.getTracer>\ntype Span = ReturnType<OtelTracer['startSpan']>\n\ntype Func<T> = (span: Span) => Promise<T> | T\ntype SyncFunc<T> = (span: Span) => T\n\ntype WithTrace = {\n <T>(name: string, fn: Func<T>): Promise<T>\n <T>(name: string, options: SpanOptions, fn: Func<T>): Promise<T>\n <T>(name: string, parent: Span, fn: Func<T>): Promise<T>\n <T>(name: string, options: SpanOptions, parent: Span, fn: Func<T>): Promise<T>\n}\ntype WithTraceSync = {\n <T>(name: string, fn: SyncFunc<T>): T\n <T>(name: string, options: SpanOptions, fn: SyncFunc<T>): T\n <T>(name: string, parent: Span, fn: SyncFunc<T>): T\n <T>(name: string, options: SpanOptions, parent: Span, fn: SyncFunc<T>): T\n}\n\n/**\n * Extended tracer with helper methods for span-wrapped execution\n */\ninterface Tracer extends OtelTracer {\n withTrace: WithTrace\n withTraceSync: WithTraceSync\n}\n\n/**\n * Returns an OpenTelemetry tracer bound to the current service.\n * Includes `withTrace()` and `withTraceSync()` helpers for span-wrapped execution.\n *\n * @param serviceOverride - Optional override for service name\n * @returns Tracer with helpers\n */\nexport function getTracer(componentNameOverride?: string): Tracer {\n if (!isInitialized() && process.env.NODE_ENV !== 'test') {\n console.warn('OTEL must be initialized before calling getTracer()')\n }\n\n const { componentName, systemName, systemVersion } = detectTelemetryContext(\n componentNameOverride\n )\n const tracer = trace.getTracer(\n componentName ?? systemName,\n systemVersion\n ) as Tracer\n\n /**\n * Runs a function inside a new span (async variant).\n * Automatically handles span status and nesting.\n */\n const withTrace: WithTrace = async <T>(\n name: string,\n spanOptionsSpanOrFunc?: SpanOptions | Span | Func<T>,\n spanOrFunc?: Span | Func<T>,\n func?: Func<T>\n ): Promise<T> => {\n const { options, parent, fn } = extractArgs(\n spanOptionsSpanOrFunc,\n spanOrFunc,\n func\n )\n\n const parentContext = parent\n ? trace.setSpan(context.active(), parent)\n : context.active()\n\n const span = tracer.startSpan(name, options, parentContext)\n let ended = false\n const originalEnd = span.end.bind(span)\n const endOnce = () => {\n if (!ended) {\n ended = true\n originalEnd()\n }\n }\n span.end = endOnce\n\n return await context.with(trace.setSpan(parentContext, span), async () => {\n try {\n const result = await fn(span)\n span.setStatus({ code: SpanStatusCode.OK })\n return result\n } catch (err) {\n const error = err as Error\n span.setStatus({ code: SpanStatusCode.ERROR, message: error.message })\n span.recordException?.(error)\n throw err\n } finally {\n endOnce()\n }\n })\n }\n\n /**\n * Runs a synchronous function inside a new span.\n * Automatically handles span status and nesting.\n */\n const withTraceSync: WithTraceSync = <T>(\n name: string,\n spanOptionsSpanOrFunc?: SpanOptions | Span | SyncFunc<T>,\n spanOrFunc?: Span | SyncFunc<T>,\n func?: SyncFunc<T>\n ): T => {\n const { options, parent, fn } = extractArgs(\n spanOptionsSpanOrFunc,\n spanOrFunc,\n func\n )\n\n const parentContext = parent\n ? trace.setSpan(context.active(), parent)\n : context.active()\n\n const span = tracer.startSpan(name, options, parentContext)\n let ended = false\n const originalEnd = span.end.bind(span)\n const endOnce = () => {\n if (!ended) {\n ended = true\n originalEnd()\n }\n }\n span.end = endOnce\n\n return context.with(trace.setSpan(parentContext, span), () => {\n try {\n const result = fn(span)\n span.setStatus({ code: SpanStatusCode.OK })\n return result\n } catch (err) {\n const error = err as Error\n span.setStatus({ code: SpanStatusCode.ERROR, message: error.message })\n span.recordException?.(error)\n throw err\n } finally {\n endOnce()\n }\n })\n }\n\n tracer.withTrace = withTrace\n tracer.withTraceSync = withTraceSync\n\n return tracer\n}\n\ntype TraceArgs<T> = {\n options: SpanOptions\n parent?: Span\n fn: (span: Span) => T\n}\n\nfunction extractArgs<T>(\n spanOptionsSpanOrFunc?: SpanOptions | Span | ((span: Span) => T),\n spanOrFunc?: Span | ((span: Span) => T),\n func?: (span: Span) => T\n): TraceArgs<T> {\n let options: SpanOptions = {}\n let parent: Span | undefined\n let fn: (span: Span) => T\n\n if (isFunction(spanOptionsSpanOrFunc)) {\n fn = spanOptionsSpanOrFunc\n } else if (isFunction(spanOrFunc)) {\n const spanOrSpanOptions = spanOptionsSpanOrFunc as Span | SpanOptions\n if (isSpanOptions(spanOrSpanOptions)) {\n options = spanOrSpanOptions as SpanOptions\n } else {\n parent = spanOrSpanOptions as Span\n }\n fn = spanOrFunc\n } else {\n options = spanOptionsSpanOrFunc as SpanOptions\n parent = spanOrFunc as Span\n // biome-ignore lint/style/noNonNullAssertion: it IS defined here\n fn = func!\n }\n\n return { options, parent, fn }\n}\n\nconst isFunction = (value: unknown): value is (span: Span) => unknown =>\n typeof value === 'function'\nconst isSpan = (value: unknown): value is Span =>\n value !== null &&\n value !== undefined &&\n isFunction((value as Span).spanContext) &&\n isFunction((value as Span).end)\n/* istanbul ignore next */\nconst isSpanOptions = (value: unknown): value is SpanOptions =>\n value !== null &&\n value !== undefined &&\n (!!(value as SpanOptions).startTime ||\n !!(value as SpanOptions).attributes ||\n !!(value as SpanOptions).kind) &&\n !isSpan(value)\n","/* istanbul ignore file */\nexport {\n type Context,\n type Counter,\n context,\n type Gauge,\n type Histogram,\n type Meter,\n type ObservableCounter,\n type ObservableGauge,\n type ObservableUpDownCounter,\n type Span,\n type SpanStatus,\n SpanStatusCode,\n type UpDownCounter,\n} from '@opentelemetry/api'\nexport * from './instrumentations'\nexport * from './logger'\nexport * from './metrics'\nexport * from './otel'\nexport * from './tracer'\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sebspark/otel",
|
|
3
|
-
"version": "4.1
|
|
3
|
+
"version": "4.2.1",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.mjs",
|
|
@@ -18,58 +18,54 @@
|
|
|
18
18
|
"build": "spark-build src/index.ts",
|
|
19
19
|
"dev": "tsc --watch --noEmit",
|
|
20
20
|
"lint": "biome check .",
|
|
21
|
-
"test": "vitest run --passWithNoTests --coverage",
|
|
22
|
-
"test:e2e": "vitest --config vitest.config.e2e.ts --run",
|
|
21
|
+
"test": "vitest run --passWithNoTests --coverage --fsModuleCachePath node_modules/.vitest-cache",
|
|
22
|
+
"test:e2e": "vitest --config vitest.config.e2e.ts --run --fsModuleCachePath node_modules/.vitest-cache",
|
|
23
23
|
"typecheck": "vitest --typecheck.only --passWithNoTests --run"
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
|
-
"@opentelemetry/api": "1.
|
|
27
|
-
"@opentelemetry/
|
|
28
|
-
"@opentelemetry/
|
|
29
|
-
"@opentelemetry/exporter-
|
|
30
|
-
"@opentelemetry/exporter-
|
|
31
|
-
"@opentelemetry/
|
|
32
|
-
"@opentelemetry/instrumentation": "0.
|
|
33
|
-
"@opentelemetry/instrumentation-
|
|
34
|
-
"@opentelemetry/instrumentation-
|
|
35
|
-
"@opentelemetry/instrumentation-
|
|
36
|
-
"@opentelemetry/instrumentation-
|
|
37
|
-
"@opentelemetry/instrumentation-
|
|
38
|
-
"@opentelemetry/instrumentation-
|
|
39
|
-
"@opentelemetry/instrumentation-
|
|
40
|
-
"@opentelemetry/instrumentation-
|
|
41
|
-
"@opentelemetry/
|
|
42
|
-
"@opentelemetry/resource-detector-
|
|
43
|
-
"@opentelemetry/
|
|
44
|
-
"@opentelemetry/
|
|
45
|
-
"@opentelemetry/sdk-
|
|
46
|
-
"@opentelemetry/sdk-
|
|
47
|
-
"@opentelemetry/sdk-
|
|
48
|
-
"@opentelemetry/
|
|
49
|
-
"@opentelemetry
|
|
50
|
-
"@sebspark/opentelemetry-instrumentation-opensearch": "0.3.15",
|
|
26
|
+
"@opentelemetry/api": "1.10.0",
|
|
27
|
+
"@opentelemetry/core": "3.0.0",
|
|
28
|
+
"@opentelemetry/exporter-logs-otlp-http": "0.300.0",
|
|
29
|
+
"@opentelemetry/exporter-metrics-otlp-http": "0.300.0",
|
|
30
|
+
"@opentelemetry/exporter-trace-otlp-http": "0.300.0",
|
|
31
|
+
"@opentelemetry/instrumentation": "0.300.0",
|
|
32
|
+
"@opentelemetry/instrumentation-dns": "0.67.0",
|
|
33
|
+
"@opentelemetry/instrumentation-express": "0.72.0",
|
|
34
|
+
"@opentelemetry/instrumentation-fs": "0.43.0",
|
|
35
|
+
"@opentelemetry/instrumentation-grpc": "0.300.0",
|
|
36
|
+
"@opentelemetry/instrumentation-http": "0.300.0",
|
|
37
|
+
"@opentelemetry/instrumentation-net": "0.68.0",
|
|
38
|
+
"@opentelemetry/instrumentation-redis": "0.72.0",
|
|
39
|
+
"@opentelemetry/instrumentation-socket.io": "0.71.0",
|
|
40
|
+
"@opentelemetry/instrumentation-undici": "0.34.0",
|
|
41
|
+
"@opentelemetry/resource-detector-container": "0.9.0",
|
|
42
|
+
"@opentelemetry/resource-detector-gcp": "0.59.0",
|
|
43
|
+
"@opentelemetry/resources": "3.0.0",
|
|
44
|
+
"@opentelemetry/sdk-logs": "3.0.0",
|
|
45
|
+
"@opentelemetry/sdk-metrics": "3.0.0",
|
|
46
|
+
"@opentelemetry/sdk-node": "0.300.0",
|
|
47
|
+
"@opentelemetry/sdk-trace": "3.0.0",
|
|
48
|
+
"@opentelemetry/semantic-conventions": "1.44.0",
|
|
49
|
+
"@sebspark/opentelemetry-instrumentation-opensearch": "0.4.1",
|
|
51
50
|
"fast-safe-stringify": "2.1.1",
|
|
52
51
|
"kleur": "4.1.5",
|
|
53
52
|
"yaml": "2.9.1"
|
|
54
53
|
},
|
|
55
54
|
"devDependencies": {
|
|
56
|
-
"@biomejs/biome": "2.
|
|
57
|
-
"@opensearch-project/opensearch": "3.
|
|
58
|
-
"@opentelemetry/context-async-hooks": "
|
|
59
|
-
"@sebspark/tsconfig": "
|
|
60
|
-
"@testcontainers/opensearch": "12.1
|
|
61
|
-
"@testcontainers/redis": "12.1
|
|
62
|
-
"axios": "1.
|
|
63
|
-
"express": "5.
|
|
55
|
+
"@biomejs/biome": "2.6.4",
|
|
56
|
+
"@opensearch-project/opensearch": "3.9.0",
|
|
57
|
+
"@opentelemetry/context-async-hooks": "3.0.0",
|
|
58
|
+
"@sebspark/tsconfig": "3.0.28",
|
|
59
|
+
"@testcontainers/opensearch": "12.2.1",
|
|
60
|
+
"@testcontainers/redis": "12.2.1",
|
|
61
|
+
"axios": "1.21.0",
|
|
62
|
+
"express": "5.3.0",
|
|
64
63
|
"find-free-ports": "3.1.1",
|
|
65
|
-
"redis": "6.
|
|
64
|
+
"redis": "6.3.1",
|
|
66
65
|
"typescript": "7.0.2",
|
|
67
|
-
"undici": "8.
|
|
68
|
-
"vite": "8.3.
|
|
69
|
-
"vitest": "5.0.
|
|
70
|
-
},
|
|
71
|
-
"resolutions": {
|
|
72
|
-
"protobufjs": "8.8.0"
|
|
66
|
+
"undici": "8.12.3",
|
|
67
|
+
"vite": "8.3.5",
|
|
68
|
+
"vitest": "5.0.5"
|
|
73
69
|
},
|
|
74
70
|
"repository": {
|
|
75
71
|
"type": "git",
|