@sebspark/otel 4.1.14 → 4.1.16

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 ADDED
@@ -0,0 +1,542 @@
1
+ # @sebspark/otel
2
+
3
+ ## 4.1.16
4
+
5
+ ### Patch Changes
6
+
7
+ - 66ac832: * Upgraded to TypeScript 7
8
+ - Replaced tsup with tsdown for package builds
9
+ - Fixed cli-tester stdout parsing, resolving flaky e2e tests across the repo
10
+ - Patched vulnerable transitive dependencies (uuid, socket.io-parser, and others)
11
+ - Updated dependencies [66ac832]
12
+ - @sebspark/opentelemetry-instrumentation-opensearch@0.3.14
13
+
14
+ ## 4.1.15
15
+
16
+ ### Patch Changes
17
+
18
+ - eefb531: Updated dependencies
19
+ - Updated dependencies [eefb531]
20
+ - @sebspark/opentelemetry-instrumentation-opensearch@0.3.13
21
+
22
+ ## 4.1.14
23
+
24
+ ### Patch Changes
25
+
26
+ - 5e9fc45: Bump dependencies. Security fixes:
27
+
28
+ - **form-data** 2.5.6 / 4.0.6 — CRLF injection via unescaped multipart field names and filenames (High)
29
+ - **vite** 8.1.2 — `server.fs.deny` bypass on Windows alternate paths; NTLMv2 hash disclosure via launch-editor (High/Moderate)
30
+ - **ws** 8.21.0 — Memory exhaustion DoS from tiny fragments; uninitialized memory disclosure (High/Moderate)
31
+ - **undici** 8.5.0 — Multiple DoS and information disclosure CVEs (High/Moderate/Low)
32
+ - **tar** 7.5.19 — PAX size override causes tar parser differential / file smuggling (Moderate)
33
+ - **qs** 6.15.3 — DoS via `qs.stringify` crash on null/undefined entries (Moderate)
34
+ - **@opentelemetry/core** 2.8.0 — Unbounded memory allocation in W3C Baggage propagation (Moderate)
35
+ - **@babel/core** 7.29.7 — Arbitrary file read via sourceMappingURL comment (Low)
36
+ - **protobufjs** 8.6.5
37
+
38
+ Other dependency updates:
39
+
40
+ - `@google-cloud/spanner` 8.8.0
41
+ - `@testcontainers/*` 12.0.4
42
+ - `google-auth-library` 10.9.0
43
+ - `mockserver-client` 7.3.0
44
+ - `nock` 14.0.16
45
+ - `prettier` 3.9.4
46
+ - `redis` 6.1.0
47
+ - `webpack` 5.108.3 / `webpack-cli` 7.1.0
48
+
49
+ - Updated dependencies [5e9fc45]
50
+ - @sebspark/opentelemetry-instrumentation-opensearch@0.3.12
51
+
52
+ ## 4.1.13
53
+
54
+ ### Patch Changes
55
+
56
+ - e0eda57: Updated dependencies
57
+ - Updated dependencies [e0eda57]
58
+ - @sebspark/opentelemetry-instrumentation-opensearch@0.3.11
59
+
60
+ ## 4.1.12
61
+
62
+ ### Patch Changes
63
+
64
+ - 26d55f0: Fix `@sebspark/memredis` so Redis clients are assignable to `IPersistor` by widening the pub/sub subscription return types to accept both MemRedis and node-redis implementations.
65
+
66
+ Also update supporting dependencies across the affected packages.
67
+
68
+ - Updated dependencies [26d55f0]
69
+ - @sebspark/opentelemetry-instrumentation-opensearch@0.3.10
70
+
71
+ ## 4.1.11
72
+
73
+ ### Patch Changes
74
+
75
+ - a6c27f3: Updated dependencies
76
+ - Updated dependencies [a6c27f3]
77
+ - @sebspark/opentelemetry-instrumentation-opensearch@0.3.9
78
+
79
+ ## 4.1.10
80
+
81
+ ### Patch Changes
82
+
83
+ - 97fe7da: Updated dependencies
84
+
85
+ ## 4.1.9
86
+
87
+ ### Patch Changes
88
+
89
+ - 264e665: Upgrade `redis` to v6 in `@sebspark/promise-cache` and bump minor dependencies across the workspace.
90
+
91
+ **Breaking change (`@sebspark/promise-cache`):**
92
+ `redis` upgraded from `5.12.1` → `6.0.0`. Redis v6 contains breaking changes in its API — see the [redis v6 migration guide](https://github.com/redis/node-redis/blob/master/docs/v4-to-v6.md) if your code uses the client directly.
93
+
94
+ **Dependency updates across packages:**
95
+ - `testcontainers` / `@testcontainers/*`: `12.0.0` → `12.0.1` (health-check, opensearch, opentelemetry-instrumentation-opensearch, otel, promise-cache, socket.io-gcp-pubsub-emitter, spanner-migrate, test-iap)
96
+ - `redis`: `5.12.1` → `6.0.0` (otel, promise-cache)
97
+ - `tsdown`: `0.22.0` → `0.22.1` (tsconfig)
98
+ - `turbo` / `@turbo/gen`: `2.9.15` → `2.9.16`
99
+ - `webpack-cli`: `7.0.2` → `7.0.3` (avsc-isometric)
100
+
101
+ **Test fix (`@sebspark/promise-cache`):**
102
+ Pinned Redis container image tag to `redis:8.8-alpine` (was `redis:8-alpine`) to prevent floating-tag drift in e2e tests.
103
+
104
+ - Updated dependencies [264e665]
105
+ - @sebspark/opentelemetry-instrumentation-opensearch@0.3.8
106
+
107
+ ## 4.1.8
108
+
109
+ ### Patch Changes
110
+
111
+ - 242eb33: This release primarily updates dependencies across the listed packages, including:
112
+ - Testcontainers v12 upgrades in packages that run integration/e2e tests.
113
+ - Vitest/Biome/Turbo and related tooling updates.
114
+ - Runtime dependency updates such as `date-fns`, `@inquirer/*`, `socket.io-adapter`, and `ws`.
115
+
116
+ It also includes two targeted fixes:
117
+ - `@sebspark/opensearch`: fixed TypeScript compatibility so strict `SearchRequest<T>` / `SearchRequestBody<T>` can be assigned to OpenSearch API request types, and added a compile-time compatibility test.
118
+ - `@sebspark/health-check`: updated the e2e readiness payload assertions and type-only import usage to match current runtime output and TypeScript expectations.
119
+
120
+ - Updated dependencies [242eb33]
121
+ - @sebspark/opentelemetry-instrumentation-opensearch@0.3.7
122
+
123
+ ## 4.1.7
124
+
125
+ ### Patch Changes
126
+
127
+ - c5e9c99: Resolve protobufjs CVE by pinning to `8.3.0` across all affected packages via root resolutions. Upgraded OpenTelemetry packages to `0.218.0` (which also eliminates the previous hardpin on `protobufjs@8.0.1`), `axios` to `1.16.1`, `ws` to `8.20.1`, `qs` to `6.15.2`, and `@opentelemetry/semantic-conventions` to `1.41.1`.
128
+ - Updated dependencies [c5e9c99]
129
+ - @sebspark/opentelemetry-instrumentation-opensearch@0.3.6
130
+
131
+ ## 4.1.6
132
+
133
+ ### Patch Changes
134
+
135
+ - 41bb8f2: ### `@sebspark/openapi-core`
136
+
137
+ `fromAxiosError` no longer references the `AxiosError` type in its signature. It now accepts `unknown` and uses a local duck-typed interface to extract the relevant fields. This removes the `axios` import from the published `dist/index.d.mts`, preventing downstream bundlers (rolldown/tsdown) from treating `AxiosError` as a missing value export.
138
+
139
+ ### `@sebspark/tsconfig`
140
+
141
+ Added `verbatimModuleSyntax: true` to `base.json`. All packages in the monorepo now emit `import type` modifiers correctly and TypeScript enforces type-only imports at typecheck time.
142
+
143
+ ### `@sebspark/openapi-client`
144
+
145
+ Updated `fromAxiosError` call site to pass `error` directly as `unknown` instead of casting to `AxiosError`.
146
+
147
+ ### Other packages
148
+
149
+ Dependency updates.
150
+
151
+ ## 4.1.5
152
+
153
+ ### Patch Changes
154
+
155
+ - a62ddaa: Updated vulnerable dependencies
156
+
157
+ ## 4.1.4
158
+
159
+ ### Patch Changes
160
+
161
+ - cf4ca8e: Export `Filter`, `MethodCall`, `MethodCallBuilder`, and `ResponseCb` from `@sebspark/emulator` so that packages wrapping `createEmulator<T>()` can name the return types in their generated declaration files (fixes TS4023).
162
+
163
+ Dependency updates:
164
+ - `@opentelemetry/*` instrumentation packages: `0.216.0` → `0.217.0`; `instrumentation-undici`: `0.26.0` → `0.27.0`; resource detectors, individual instrumentations bumped to latest patch/minor releases
165
+ - `@google-cloud/spanner`: `8.7.0` → `8.7.1`
166
+ - `fast-xml-parser`: `5.7.2` → `5.7.3`
167
+ - Dev: `turbo` `2.9.8` → `2.9.9`, `knip` `6.11.0` → `6.12.0`, `syncpack` `14.3.1` → `15.0.0`
168
+
169
+ - Updated dependencies [cf4ca8e]
170
+ - @sebspark/opentelemetry-instrumentation-opensearch@0.3.5
171
+
172
+ ## 4.1.3
173
+
174
+ ### Patch Changes
175
+
176
+ - 7d8cc98: Dependabot dependency updates
177
+ - Updated dependencies [7d8cc98]
178
+ - @sebspark/opentelemetry-instrumentation-opensearch@0.3.4
179
+
180
+ ## 4.1.2
181
+
182
+ ### Patch Changes
183
+
184
+ - 8a120f6: Updated dependencies for all and docs for emulator
185
+ - Updated dependencies [8a120f6]
186
+ - @sebspark/opentelemetry-instrumentation-opensearch@0.3.3
187
+
188
+ ## 4.1.1
189
+
190
+ ### Patch Changes
191
+
192
+ - e9a7a28: Updated dependencies
193
+ - Updated dependencies [e9a7a28]
194
+ - @sebspark/opentelemetry-instrumentation-opensearch@0.3.2
195
+
196
+ ## 4.1.0
197
+
198
+ ### Minor Changes
199
+
200
+ - 7494311: Allow consumers to use the SimpleSpanProcessor when needed.
201
+
202
+ ## 4.0.1
203
+
204
+ ### Patch Changes
205
+
206
+ - 4124516: Updated dependencies
207
+ - 4e12590: Updated dependencies
208
+ - Updated dependencies [4e12590]
209
+ - @sebspark/opentelemetry-instrumentation-opensearch@0.3.1
210
+
211
+ ## 4.0.0
212
+
213
+ ### Major Changes
214
+
215
+ - f07a679: Instrumentations are now methods and accept config
216
+
217
+ ## 3.0.4
218
+
219
+ ### Patch Changes
220
+
221
+ - aff5f58: Updated dependencies
222
+
223
+ ## 3.0.3
224
+
225
+ ### Patch Changes
226
+
227
+ - ae4b9bf: OTEL only tries to shut down once
228
+
229
+ ## 3.0.2
230
+
231
+ ### Patch Changes
232
+
233
+ - Updated dependencies [f202dc3]
234
+ - @sebspark/opentelemetry-instrumentation-opensearch@0.3.0
235
+
236
+ ## 3.0.1
237
+
238
+ ### Patch Changes
239
+
240
+ - 22bde73: Opensearch instrumentation does not call through to http instrumentation
241
+
242
+ ## 3.0.0
243
+
244
+ ### Major Changes
245
+
246
+ - 91aed80: Added instrumentation for outgoing http requests and removed SIGTERM listener
247
+
248
+ ### Patch Changes
249
+
250
+ - Updated dependencies [91aed80]
251
+ - @sebspark/opentelemetry-instrumentation-opensearch@0.2.2
252
+
253
+ ## 2.2.3
254
+
255
+ ### Patch Changes
256
+
257
+ - Updated dependencies [cd9e760]
258
+ - @sebspark/opentelemetry-instrumentation-opensearch@0.2.1
259
+
260
+ ## 2.2.2
261
+
262
+ ### Patch Changes
263
+
264
+ - Updated dependencies [b92b79a]
265
+ - @sebspark/opentelemetry-instrumentation-opensearch@0.2.0
266
+
267
+ ## 2.2.1
268
+
269
+ ### Patch Changes
270
+
271
+ - Updated dependencies [67d6129]
272
+ - @sebspark/opentelemetry-instrumentation-opensearch@0.1.1
273
+
274
+ ## 2.2.0
275
+
276
+ ### Minor Changes
277
+
278
+ - 3d2415a: Added instrumentation for opensearch
279
+
280
+ ## 2.1.8
281
+
282
+ ### Patch Changes
283
+
284
+ - 67871de: Otel now warns on stdout. Also dependency updates.
285
+
286
+ ## 2.1.7
287
+
288
+ ### Patch Changes
289
+
290
+ - 736a0b3: No bundling of packages in packages
291
+
292
+ ## 2.1.6
293
+
294
+ ### Patch Changes
295
+
296
+ - 5e9294e: chore: use global variables to store otel initialization
297
+
298
+ ## 2.1.5
299
+
300
+ ### Patch Changes
301
+
302
+ - 23be838: chore: change k8s logs format
303
+
304
+ ## 2.1.4
305
+
306
+ ### Patch Changes
307
+
308
+ - 6cf0475: chore: format service name, remove wrong characters
309
+
310
+ ## 2.1.3
311
+
312
+ ### Patch Changes
313
+
314
+ - 8cd0201: Fix for OTEL not initialized spam and double span.end()
315
+
316
+ ## 2.1.2
317
+
318
+ ### Patch Changes
319
+
320
+ - 1c13543: add missing attribute gcp.log_name
321
+
322
+ ## 2.1.1
323
+
324
+ ### Patch Changes
325
+
326
+ - 1485c2d: Changed warning level text from WARNING to WARN
327
+
328
+ ## 2.1.0
329
+
330
+ ### Minor Changes
331
+
332
+ - c60b7a4: chore: change logs formatting
333
+
334
+ ## 2.0.14
335
+
336
+ ### Patch Changes
337
+
338
+ - 2241dc7: Updated dependencies
339
+
340
+ ## 2.0.13
341
+
342
+ ### Patch Changes
343
+
344
+ - 80e6230: Updated dependencies
345
+
346
+ ## 2.0.12
347
+
348
+ ### Patch Changes
349
+
350
+ - c8dcadb: Updated dependencies
351
+
352
+ ## 2.0.11
353
+
354
+ ### Patch Changes
355
+
356
+ - 11a11ce: Updated dependencies
357
+
358
+ ## 2.0.9
359
+
360
+ ### Patch Changes
361
+
362
+ - 48ab717: Updated dependencies
363
+
364
+ ## 2.0.8
365
+
366
+ ### Patch Changes
367
+
368
+ - e0cb5ee: Updated build from tsup to tsdown
369
+
370
+ ## 2.0.7
371
+
372
+ ### Patch Changes
373
+
374
+ - 8626deb: Updated vulnerable, transitive jws dependency
375
+
376
+ ## 2.0.6
377
+
378
+ ### Patch Changes
379
+
380
+ - 7df8217: Updated dependencies
381
+
382
+ ## 2.0.5
383
+
384
+ ### Patch Changes
385
+
386
+ - 4b210c2: Standardized on a common build script
387
+
388
+ ## 2.0.4
389
+
390
+ ### Patch Changes
391
+
392
+ - 618a019: Dynamically imported instrumentations
393
+
394
+ ## 2.0.3
395
+
396
+ ### Patch Changes
397
+
398
+ - eb99a27: Marked opentelemetry dependencies as external
399
+
400
+ ## 2.0.2
401
+
402
+ ### Patch Changes
403
+
404
+ - 7e5c2e9: Switched to new tsconfig with moduleResolution=bundler
405
+
406
+ ## 2.0.1
407
+
408
+ ### Patch Changes
409
+
410
+ - d801e1e: Updated dependencies and fixed some exports
411
+
412
+ ## 2.0.0
413
+
414
+ ### Major Changes
415
+
416
+ - 0864ec2: ESM only. Minimum node version 22
417
+
418
+ ## 1.1.4
419
+
420
+ ### Patch Changes
421
+
422
+ - 3a40e49: Cleaned up dependencies
423
+
424
+ ## 1.1.3
425
+
426
+ ### Patch Changes
427
+
428
+ - 604c94a: Updated dependencies
429
+
430
+ ## 1.1.2
431
+
432
+ ### Patch Changes
433
+
434
+ - b8fe201: SpanStatusCode is exported as a value, not a type
435
+
436
+ ## 1.1.1
437
+
438
+ ### Patch Changes
439
+
440
+ - b86cf2d: Instrumentation warnings are now supressed during testing
441
+
442
+ ## 1.1.0
443
+
444
+ ### Minor Changes
445
+
446
+ - a8ba986: OTEL exports usable types
447
+
448
+ ## 1.0.5
449
+
450
+ ### Patch Changes
451
+
452
+ - 90fa604: Changed initialization handling in logger to solve OTEL fail spam
453
+
454
+ ## 1.0.4
455
+
456
+ ### Patch Changes
457
+
458
+ - 63fc64a: tracer and meter no longer throw before initialization
459
+
460
+ ## 1.0.3
461
+
462
+ ### Patch Changes
463
+
464
+ - 0e4d66b: Logger swallows messages before initialization
465
+
466
+ ## 1.0.2
467
+
468
+ ### Patch Changes
469
+
470
+ - 4b1337a: Disabling context before initialize
471
+
472
+ ## 1.0.1
473
+
474
+ ### Patch Changes
475
+
476
+ - c360c99: Init check is moved to first log call instead of at getLogger()
477
+
478
+ ## 1.0.0
479
+
480
+ ### Major Changes
481
+
482
+ - d361253: OTEL instrumentation now requires initialize and specific instrumentations
483
+
484
+ ## 0.4.2
485
+
486
+ ### Patch Changes
487
+
488
+ - d323365: Change error function to be able to receive an error object as parameter
489
+
490
+ ## 0.4.0
491
+
492
+ ### Minor Changes
493
+
494
+ - 0dc99f6: Console logger is added if LOG_LEVEL is set, even if collector exists
495
+
496
+ ## 0.3.1
497
+
498
+ ### Patch Changes
499
+
500
+ - fc781e2: Switched places for spanId/traceId
501
+
502
+ ## 0.3.0
503
+
504
+ ### Minor Changes
505
+
506
+ - 2a7b207: Added span and trace id to span logs
507
+
508
+ ## 0.2.4
509
+
510
+ ### Patch Changes
511
+
512
+ - 2c32898: Fixed wrongful options copy for span with parent
513
+
514
+ ## 0.2.3
515
+
516
+ ### Patch Changes
517
+
518
+ - 0288531: Tracer and Meter are asynch and Logger awaits init
519
+
520
+ ## 0.2.2
521
+
522
+ ### Patch Changes
523
+
524
+ - 005c598: Removed manual context registration
525
+
526
+ ## 0.2.1
527
+
528
+ ### Patch Changes
529
+
530
+ - ac28d06: No duplicate contextManager
531
+
532
+ ## 0.2.0
533
+
534
+ ### Minor Changes
535
+
536
+ - cc889fb: Added custom loggers for dev use
537
+
538
+ ## 0.1.0
539
+
540
+ ### Minor Changes
541
+
542
+ - 3007f53: First, simple implementation of OTEL instrumentation
package/dist/index.d.mts CHANGED
@@ -7,8 +7,10 @@ import { GrpcInstrumentationConfig } from "@opentelemetry/instrumentation-grpc";
7
7
  import { RedisInstrumentationConfig } from "@opentelemetry/instrumentation-redis";
8
8
  import { SocketIoInstrumentationConfig } from "@opentelemetry/instrumentation-socket.io";
9
9
  import { OpenSearchInstrumentationConfig } from "@sebspark/opentelemetry-instrumentation-opensearch";
10
+ import "@opentelemetry/instrumentation-http";
11
+ import "@opentelemetry/instrumentation-undici";
10
12
  //#region src/enrichments/outgoing-http/consts.d.ts
11
- declare const PROTOCOLS: readonly ["https", "http"];
13
+ declare const PROTOCOLS: readonly ['https', 'http'];
12
14
  //#endregion
13
15
  //#region src/enrichments/outgoing-http/types.d.ts
14
16
  type Protocol = (typeof PROTOCOLS)[number];
@@ -49,7 +51,7 @@ interface OutgoingHttpEnrichmentConfig extends InstrumentationConfig {
49
51
  }
50
52
  //#endregion
51
53
  //#region src/instrumentations.d.ts
52
- declare const instrumentations: {
54
+ export declare const instrumentations: {
53
55
  readonly http: (config?: OutgoingHttpEnrichmentConfig) => Promise<Instrumentation<InstrumentationConfig>>;
54
56
  readonly express: (config?: ExpressInstrumentationConfig) => Promise<Instrumentation<InstrumentationConfig>>;
55
57
  readonly grpc: (config?: GrpcInstrumentationConfig) => Promise<Instrumentation<InstrumentationConfig>>;
@@ -64,8 +66,8 @@ declare const instrumentations: {
64
66
  //#endregion
65
67
  //#region src/logger.d.ts
66
68
  type Attrs = Record<string, any>;
67
- type Logger = ReturnType<typeof getLogger>;
68
- declare function getLogger(serviceOverride?: string, extraAttrs?: Attrs): {
69
+ export type Logger = ReturnType<typeof getLogger>;
70
+ export declare function getLogger(serviceOverride?: string, extraAttrs?: Attrs): {
69
71
  debug: {
70
72
  (msg: string, attrs?: Attrs): void;
71
73
  (msg: string, error: Error, attrs?: Attrs): void;
@@ -109,12 +111,12 @@ declare function getLogger(serviceOverride?: string, extraAttrs?: Attrs): {
109
111
  };
110
112
  //#endregion
111
113
  //#region src/metrics.d.ts
112
- declare function getMeter(componentNameOverride?: string): import("@opentelemetry/api").Meter;
114
+ export declare function getMeter(componentNameOverride?: string): import("@opentelemetry/api").Meter;
113
115
  //#endregion
114
116
  //#region src/otel.d.ts
115
- declare function initialize(...instrumentations: Promise<Instrumentation>[]): Promise<void>;
116
- declare function isInitialized(): boolean;
117
- declare const dispose: () => Promise<void>;
117
+ export declare function initialize(...instrumentations: Promise<Instrumentation>[]): Promise<void>;
118
+ export declare function isInitialized(): boolean;
119
+ export declare const dispose: () => Promise<void>;
118
120
  //#endregion
119
121
  //#region src/tracer.d.ts
120
122
  type OtelTracer = ReturnType<typeof trace.getTracer>;
@@ -147,7 +149,7 @@ interface Tracer extends OtelTracer {
147
149
  * @param serviceOverride - Optional override for service name
148
150
  * @returns Tracer with helpers
149
151
  */
150
- declare function getTracer(componentNameOverride?: string): Tracer;
152
+ export declare function getTracer(componentNameOverride?: string): Tracer;
151
153
  //#endregion
152
- export { type Context, type Counter, type Gauge, type Histogram, Logger, type Meter, type ObservableCounter, type ObservableGauge, type ObservableUpDownCounter, type Span, type SpanStatus, SpanStatusCode, type UpDownCounter, context, dispose, getLogger, getMeter, getTracer, initialize, instrumentations, isInitialized };
154
+ 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 };
153
155
  //# sourceMappingURL=index.d.mts.map
@@ -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":"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"}
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":";;;;;;;;;;;;cA0Ba;;;KCtBD,mBAAmB;UASd;EACf;EACA;EACA;;EAEA;EACA,UAAU;;EAEV,UAAU;;UAeK,qCAAqC;;;;;EAKpD;;EAGA;;;;;;EAOA,cAAc,MAAM,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;;;;KCrJhD,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;;;;;;;;wBC/FY,SAAS,8DAA8B;;;wBC0BjC,cACjB,kBAAkB,QAAQ,qBAAkB;wBAejC;qBAsCH,eAAO;;;KC3Ef,aAAa,kBAAkB,MAAM;KACrC,SAAO,WAAW;KAElB,KAAK,MAAM,MAAM,WAAS,QAAQ,KAAK;KACvC,SAAS,MAAM,MAAM,WAAS;KAE9B;GACF,GAAG,cAAc,IAAI,KAAK,KAAK,QAAQ;GACvC,GAAG,cAAc,SAAS,aAAa,IAAI,KAAK,KAAK,QAAQ;GAC7D,GAAG,cAAc,QAAQ,QAAM,IAAI,KAAK,KAAK,QAAQ;GACrD,GAAG,cAAc,SAAS,aAAa,QAAQ,QAAM,IAAI,KAAK,KAAK,QAAQ;;KAEzE;GACF,GAAG,cAAc,IAAI,SAAS,KAAK;GACnC,GAAG,cAAc,SAAS,aAAa,IAAI,SAAS,KAAK;GACzD,GAAG,cAAc,QAAQ,QAAM,IAAI,SAAS,KAAK;GACjD,GAAG,cAAc,SAAS,aAAa,QAAQ,QAAM,IAAI,SAAS,KAAK;;;;;UAMhE,eAAe;EACvB,WAAW;EACX,eAAe;;;;;;;;;wBAUD,UAAU,iCAAiC"}
package/dist/index.mjs CHANGED
@@ -274,6 +274,9 @@ function buildUndiciConfig(opts = {}) {
274
274
  };
275
275
  }
276
276
  //#endregion
277
+ //#region src/enrichments/outgoing-http/index.ts
278
+ /* istanbul ignore file */
279
+ //#endregion
277
280
  //#region src/instrumentations.ts
278
281
  const cache = /* @__PURE__ */ new Map();
279
282
  const cacheKey = (instrumentationName, config) => {
@@ -539,7 +542,7 @@ function formatDescription(span) {
539
542
  ["otel.description"]
540
543
  ]) {
541
544
  const parts = keys.map((k) => span.attributes[k]).filter((v) => v !== void 0 && v !== null).map((v) => String(v));
542
- if (parts.length > 0) return truncate(parts.join(" "), DESCRIPTION_MAX_WIDTH - 1).padEnd(DESCRIPTION_MAX_WIDTH);
545
+ if (parts.length > 0) return truncate(parts.join(" "), 15).padEnd(DESCRIPTION_MAX_WIDTH);
543
546
  }
544
547
  return "".padEnd(DESCRIPTION_MAX_WIDTH);
545
548
  }
@@ -569,6 +572,9 @@ function computeDepth(span, allSpans) {
569
572
  return depth;
570
573
  }
571
574
  //#endregion
575
+ //#region src/loggers/formatters/index.ts
576
+ /* istanbul ignore file */
577
+ //#endregion
572
578
  //#region src/loggers/console-metric-pretty-exporter.ts
573
579
  var ConsoleMetricPrettyExporter = class {
574
580
  patterns;
@@ -673,6 +679,9 @@ var ConsoleSpanPrettyExporter = class {
673
679
  }
674
680
  };
675
681
  //#endregion
682
+ //#region src/loggers/index.ts
683
+ /* istanbul ignore file */
684
+ //#endregion
676
685
  //#region src/loggers/tree-span-processor.ts
677
686
  var TreeSpanProcessor = class {
678
687
  exporter;
@@ -715,19 +724,22 @@ var TreeSpanProcessor = class {
715
724
  //#region src/providers.ts
716
725
  const getLogProvider = (resource, otlpEndpoint) => {
717
726
  if (otlpEndpoint) {
718
- const processors = [new BatchLogRecordProcessor(new OTLPLogExporter({ url: `${otlpEndpoint}/v1/logs` }))];
727
+ const otlpExporter = new OTLPLogExporter({ url: `${otlpEndpoint}/v1/logs` });
728
+ const processors = [new BatchLogRecordProcessor({ exporter: otlpExporter })];
719
729
  if (process.env.LOG_LEVEL) {
720
730
  const consoleExporter = new ConsoleLogPrettyExporter();
721
- processors.push(new SimpleLogRecordProcessor(consoleExporter));
731
+ processors.push(new SimpleLogRecordProcessor({ exporter: consoleExporter }));
722
732
  }
723
733
  return new LoggerProvider({
724
734
  resource,
725
735
  processors
726
736
  });
727
737
  }
738
+ const consoleExporter = new ConsoleLogPrettyExporter();
739
+ const processor = new SimpleLogRecordProcessor({ exporter: consoleExporter });
728
740
  return new LoggerProvider({
729
741
  resource,
730
- processors: [new SimpleLogRecordProcessor(new ConsoleLogPrettyExporter())]
742
+ processors: [processor]
731
743
  });
732
744
  };
733
745
  const getSpanProcessor = (otlpEndpoint) => {
@@ -740,7 +752,8 @@ const getSpanProcessor = (otlpEndpoint) => {
740
752
  return new BatchSpanProcessor(exporter);
741
753
  };
742
754
  const getMetricReader = (otlpEndpoint) => {
743
- return new PeriodicExportingMetricReader({ exporter: otlpEndpoint ? new OTLPMetricExporter({ url: `${otlpEndpoint}/v1/metrics` }) : new ConsoleMetricPrettyExporter() });
755
+ const metricExporter = otlpEndpoint ? new OTLPMetricExporter({ url: `${otlpEndpoint}/v1/metrics` }) : new ConsoleMetricPrettyExporter();
756
+ return new PeriodicExportingMetricReader({ exporter: metricExporter });
744
757
  };
745
758
  //#endregion
746
759
  //#region src/otel-context.ts
@@ -804,10 +817,13 @@ function getGlobal() {
804
817
  }
805
818
  async function initialize(...instrumentations) {
806
819
  const g = getGlobal();
807
- if (!g[OTEL_INIT_PROMISE_KEY]) g[OTEL_INIT_PROMISE_KEY] = _initialize(await Promise.all(instrumentations)).catch((err) => {
808
- g[OTEL_INIT_PROMISE_KEY] = void 0;
809
- throw err;
810
- });
820
+ if (!g[OTEL_INIT_PROMISE_KEY]) {
821
+ const promise = _initialize(await Promise.all(instrumentations)).catch((err) => {
822
+ g[OTEL_INIT_PROMISE_KEY] = void 0;
823
+ throw err;
824
+ });
825
+ g[OTEL_INIT_PROMISE_KEY] = promise;
826
+ }
811
827
  return g[OTEL_INIT_PROMISE_KEY];
812
828
  }
813
829
  function isInitialized() {
@@ -825,9 +841,11 @@ async function _initialize(instrumentations) {
825
841
  metrics.disable();
826
842
  logProvider = getLogProvider(resource, otlpEndpoint);
827
843
  logs.setGlobalLoggerProvider(logProvider);
844
+ const spanProcessor = getSpanProcessor(otlpEndpoint);
845
+ const metricReader = getMetricReader(otlpEndpoint);
828
846
  sdk = new NodeSDK({
829
- spanProcessor: getSpanProcessor(otlpEndpoint),
830
- metricReader: getMetricReader(otlpEndpoint),
847
+ spanProcessor,
848
+ metricReader,
831
849
  instrumentations,
832
850
  resource
833
851
  });
@@ -1029,6 +1047,9 @@ const isSpan = (value) => value !== null && value !== void 0 && isFunction(value
1029
1047
  /* istanbul ignore next */
1030
1048
  const isSpanOptions = (value) => value !== null && value !== void 0 && (!!value.startTime || !!value.attributes || !!value.kind) && !isSpan(value);
1031
1049
  //#endregion
1050
+ //#region src/index.ts
1051
+ /* istanbul ignore file */
1052
+ //#endregion
1032
1053
  export { SpanStatusCode, context, dispose, getLogger, getMeter, getTracer, initialize, instrumentations, isInitialized };
1033
1054
 
1034
1055
  //# sourceMappingURL=index.mjs.map
@@ -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/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/console-metric-pretty-exporter.ts","../src/loggers/console-log-pretty-exporter.ts","../src/loggers/console-span-pretty-exporter.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"],"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","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","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","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 exporter = new OTLPLogExporter({ url: `${otlpEndpoint}/v1/logs` })\n const processors: LogRecordProcessor[] = [\n new BatchLogRecordProcessor(exporter),\n ]\n\n // Console logging for cluster\n if (process.env.LOG_LEVEL) {\n const consoleExporter = new ConsoleLogPrettyExporter()\n processors.push(new SimpleLogRecordProcessor(consoleExporter))\n }\n\n return new LoggerProvider({\n resource,\n processors,\n })\n }\n\n // Local dev\n const exporter = new ConsoleLogPrettyExporter()\n const processor = new SimpleLogRecordProcessor(exporter)\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"],"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), 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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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sebspark/otel",
3
- "version": "4.1.14",
3
+ "version": "4.1.16",
4
4
  "license": "Apache-2.0",
5
5
  "type": "module",
6
6
  "main": "dist/index.mjs",
@@ -20,54 +20,59 @@
20
20
  "lint": "biome check .",
21
21
  "test": "vitest run --passWithNoTests --coverage",
22
22
  "test:e2e": "vitest --config vitest.config.e2e.ts --run",
23
- "typecheck": "vitest --typecheck.only --passWithNoTests"
23
+ "typecheck": "vitest --typecheck.only --passWithNoTests --run"
24
24
  },
25
25
  "dependencies": {
26
26
  "@opentelemetry/api": "1.9.1",
27
- "@opentelemetry/api-logs": "0.219.0",
28
- "@opentelemetry/core": "2.8.0",
29
- "@opentelemetry/exporter-logs-otlp-http": "0.219.0",
30
- "@opentelemetry/exporter-metrics-otlp-http": "0.219.0",
31
- "@opentelemetry/exporter-trace-otlp-http": "0.219.0",
32
- "@opentelemetry/instrumentation": "0.219.0",
33
- "@opentelemetry/instrumentation-dns": "0.62.0",
34
- "@opentelemetry/instrumentation-express": "0.67.0",
35
- "@opentelemetry/instrumentation-fs": "0.38.0",
36
- "@opentelemetry/instrumentation-grpc": "0.219.0",
37
- "@opentelemetry/instrumentation-http": "0.219.0",
38
- "@opentelemetry/instrumentation-net": "0.63.0",
39
- "@opentelemetry/instrumentation-redis": "0.67.0",
40
- "@opentelemetry/instrumentation-socket.io": "0.66.0",
41
- "@opentelemetry/instrumentation-undici": "0.29.0",
42
- "@opentelemetry/resource-detector-container": "0.8.10",
43
- "@opentelemetry/resource-detector-gcp": "0.54.0",
44
- "@opentelemetry/resources": "2.8.0",
45
- "@opentelemetry/sdk-logs": "0.219.0",
46
- "@opentelemetry/sdk-metrics": "2.8.0",
47
- "@opentelemetry/sdk-node": "0.219.0",
48
- "@opentelemetry/sdk-trace-node": "2.8.0",
49
- "@opentelemetry/semantic-conventions": "1.41.1",
50
- "@sebspark/opentelemetry-instrumentation-opensearch": "0.3.12",
27
+ "@opentelemetry/api-logs": "0.222.0",
28
+ "@opentelemetry/core": "2.11.0",
29
+ "@opentelemetry/exporter-logs-otlp-http": "0.222.0",
30
+ "@opentelemetry/exporter-metrics-otlp-http": "0.222.0",
31
+ "@opentelemetry/exporter-trace-otlp-http": "0.222.0",
32
+ "@opentelemetry/instrumentation": "0.222.0",
33
+ "@opentelemetry/instrumentation-dns": "0.65.0",
34
+ "@opentelemetry/instrumentation-express": "0.70.0",
35
+ "@opentelemetry/instrumentation-fs": "0.41.0",
36
+ "@opentelemetry/instrumentation-grpc": "0.222.0",
37
+ "@opentelemetry/instrumentation-http": "0.222.0",
38
+ "@opentelemetry/instrumentation-net": "0.66.0",
39
+ "@opentelemetry/instrumentation-redis": "0.70.0",
40
+ "@opentelemetry/instrumentation-socket.io": "0.69.0",
41
+ "@opentelemetry/instrumentation-undici": "0.32.0",
42
+ "@opentelemetry/resource-detector-container": "0.8.13",
43
+ "@opentelemetry/resource-detector-gcp": "0.57.0",
44
+ "@opentelemetry/resources": "2.11.0",
45
+ "@opentelemetry/sdk-logs": "0.222.0",
46
+ "@opentelemetry/sdk-metrics": "2.11.0",
47
+ "@opentelemetry/sdk-node": "0.222.0",
48
+ "@opentelemetry/sdk-trace-node": "2.11.0",
49
+ "@opentelemetry/semantic-conventions": "1.43.0",
50
+ "@sebspark/opentelemetry-instrumentation-opensearch": "0.3.14",
51
51
  "fast-safe-stringify": "2.1.1",
52
52
  "kleur": "4.1.5",
53
53
  "yaml": "2.9.0"
54
54
  },
55
55
  "devDependencies": {
56
+ "@biomejs/biome": "2.5.12",
56
57
  "@opensearch-project/opensearch": "3.6.0",
57
- "@opentelemetry/context-async-hooks": "2.8.0",
58
- "@testcontainers/opensearch": "12.0.4",
59
- "@testcontainers/redis": "12.0.4",
60
- "axios": "1.18.1",
58
+ "@opentelemetry/context-async-hooks": "2.11.0",
59
+ "@sebspark/tsconfig": "*",
60
+ "@testcontainers/opensearch": "12.1.0",
61
+ "@testcontainers/redis": "12.1.0",
62
+ "axios": "1.20.0",
61
63
  "express": "5.2.1",
62
64
  "find-free-ports": "3.1.1",
63
- "redis": "6.1.0",
64
- "undici": "8.5.0"
65
+ "redis": "6.2.1",
66
+ "typescript": "7.0.2",
67
+ "undici": "8.10.2",
68
+ "vite": "8.2.2",
69
+ "vitest": "5.0.0"
65
70
  },
66
71
  "resolutions": {
67
- "protobufjs": "8.6.5"
72
+ "protobufjs": "8.8.0"
68
73
  },
69
74
  "repository": {
70
75
  "type": "git",
71
76
  "url": "https://github.com/seb-oss/Spark-packages.git"
72
77
  }
73
- }
78
+ }