@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 +542 -0
- package/dist/index.d.mts +12 -10
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +32 -11
- package/dist/index.mjs.map +1 -1
- package/package.json +39 -34
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 [
|
|
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,
|
|
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
|
package/dist/index.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/enrichments/outgoing-http/consts.ts","../src/enrichments/outgoing-http/types.ts","../src/instrumentations.ts","../src/logger.ts","../src/metrics.ts","../src/otel.ts","../src/tracer.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"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(" "),
|
|
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
|
|
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: [
|
|
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
|
-
|
|
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])
|
|
808
|
-
|
|
809
|
-
|
|
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
|
|
830
|
-
metricReader
|
|
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
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":["SpanStatusCode","SpanStatusCode","SpanStatusCode","context","context","SpanStatusCode"],"sources":["../src/enrichments/outgoing-http/consts.ts","../src/enrichments/outgoing-http/apply-attributes.ts","../src/enrichments/outgoing-http/helpers.ts","../src/enrichments/outgoing-http/normalize-http.ts","../src/enrichments/outgoing-http/build-http-config.ts","../src/enrichments/outgoing-http/normalize-undici.ts","../src/enrichments/outgoing-http/build-undici-config.ts","../src/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.
|
|
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.
|
|
28
|
-
"@opentelemetry/core": "2.
|
|
29
|
-
"@opentelemetry/exporter-logs-otlp-http": "0.
|
|
30
|
-
"@opentelemetry/exporter-metrics-otlp-http": "0.
|
|
31
|
-
"@opentelemetry/exporter-trace-otlp-http": "0.
|
|
32
|
-
"@opentelemetry/instrumentation": "0.
|
|
33
|
-
"@opentelemetry/instrumentation-dns": "0.
|
|
34
|
-
"@opentelemetry/instrumentation-express": "0.
|
|
35
|
-
"@opentelemetry/instrumentation-fs": "0.
|
|
36
|
-
"@opentelemetry/instrumentation-grpc": "0.
|
|
37
|
-
"@opentelemetry/instrumentation-http": "0.
|
|
38
|
-
"@opentelemetry/instrumentation-net": "0.
|
|
39
|
-
"@opentelemetry/instrumentation-redis": "0.
|
|
40
|
-
"@opentelemetry/instrumentation-socket.io": "0.
|
|
41
|
-
"@opentelemetry/instrumentation-undici": "0.
|
|
42
|
-
"@opentelemetry/resource-detector-container": "0.8.
|
|
43
|
-
"@opentelemetry/resource-detector-gcp": "0.
|
|
44
|
-
"@opentelemetry/resources": "2.
|
|
45
|
-
"@opentelemetry/sdk-logs": "0.
|
|
46
|
-
"@opentelemetry/sdk-metrics": "2.
|
|
47
|
-
"@opentelemetry/sdk-node": "0.
|
|
48
|
-
"@opentelemetry/sdk-trace-node": "2.
|
|
49
|
-
"@opentelemetry/semantic-conventions": "1.
|
|
50
|
-
"@sebspark/opentelemetry-instrumentation-opensearch": "0.3.
|
|
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.
|
|
58
|
-
"@
|
|
59
|
-
"@testcontainers/
|
|
60
|
-
"
|
|
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
|
|
64
|
-
"
|
|
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.
|
|
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
|
+
}
|