@sebspark/otel 2.0.13 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -20,14 +20,46 @@ declare const instrumentations: {
20
20
  type Attrs = Record<string, any>;
21
21
  type Logger = ReturnType<typeof getLogger>;
22
22
  declare function getLogger(serviceOverride?: string, extraAttrs?: Attrs): {
23
- debug: (msg: string, attrs?: Attrs) => void;
24
- info: (msg: string, attrs?: Attrs) => void;
25
- notice: (msg: string, attrs?: Attrs) => void;
26
- warn: (msg: string, attrs?: Attrs) => void;
27
- error: (msg: string | Error, errOrAttrs?: Error | Attrs, maybeAttrs?: Attrs) => void;
28
- critical: (msg: string, attrs?: Attrs) => void;
29
- alert: (msg: string, attrs?: Attrs) => void;
30
- emergency: (msg: string, attrs?: Attrs) => void;
23
+ debug: {
24
+ (msg: string, attrs?: Attrs): void;
25
+ (msg: string, error: Error, attrs?: Attrs): void;
26
+ (error: Error, attrs?: Attrs): void;
27
+ };
28
+ info: {
29
+ (msg: string, attrs?: Attrs): void;
30
+ (msg: string, error: Error, attrs?: Attrs): void;
31
+ (error: Error, attrs?: Attrs): void;
32
+ };
33
+ notice: {
34
+ (msg: string, attrs?: Attrs): void;
35
+ (msg: string, error: Error, attrs?: Attrs): void;
36
+ (error: Error, attrs?: Attrs): void;
37
+ };
38
+ warn: {
39
+ (msg: string, attrs?: Attrs): void;
40
+ (msg: string, error: Error, attrs?: Attrs): void;
41
+ (error: Error, attrs?: Attrs): void;
42
+ };
43
+ error: {
44
+ (msg: string, attrs?: Attrs): void;
45
+ (msg: string, error: Error, attrs?: Attrs): void;
46
+ (error: Error, attrs?: Attrs): void;
47
+ };
48
+ critical: {
49
+ (msg: string, attrs?: Attrs): void;
50
+ (msg: string, error: Error, attrs?: Attrs): void;
51
+ (error: Error, attrs?: Attrs): void;
52
+ };
53
+ alert: {
54
+ (msg: string, attrs?: Attrs): void;
55
+ (msg: string, error: Error, attrs?: Attrs): void;
56
+ (error: Error, attrs?: Attrs): void;
57
+ };
58
+ emergency: {
59
+ (msg: string, attrs?: Attrs): void;
60
+ (msg: string, error: Error, attrs?: Attrs): void;
61
+ (error: Error, attrs?: Attrs): void;
62
+ };
31
63
  };
32
64
  //#endregion
33
65
  //#region src/metrics.d.ts
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../src/instrumentations.ts","../src/logger.ts","../src/metrics.ts","../src/otel.ts","../src/tracer.ts"],"mappings":";;;;;;cAYa,gBAAA;EAAA,uCAiFH,+BAAA,CAAA,qBAAA;EAAA;;;;;;;;;;;KCtFL,KAAA,GAAQ,MAAA;AAAA,KAED,MAAA,GAAS,UAAA,QAAkB,SAAA;AAAA,iBACvB,SAAA,CAAU,eAAA,WAA0B,UAAA,GAAY,KAAA;uBAyCzC,KAAA,GAAU,KAAA;sBACX,KAAA,GAAU,KAAA;wBACR,KAAA,GAAU,KAAA;sBACZ,KAAA,GAAU,KAAA;wBAEZ,KAAA,EAAK,UAAA,GACN,KAAA,GAAQ,KAAA,EAAK,UAAA,GACd,KAAA;0BAeQ,KAAA,GAAU,KAAA;uBACb,KAAA,GAAU,KAAA;2BACN,KAAA,GAAU,KAAA;AAAA;;;iBCvErB,QAAA,CAAS,qBAAA,YAAD,mBAAA,CAA+B,KAAA;;;iBCejC,UAAA,CAAA,GACjB,gBAAA,EAAkB,OAAA,CAAQ,eAAA,MAAkB,OAAA;AAAA,iBAYjC,aAAA,CAAA;;;KCvBX,UAAA,GAAa,UAAA,QAAkB,KAAA,CAAM,SAAA;AAAA,KACrC,MAAA,GAAO,UAAA,CAAW,UAAA;AAAA,KAElB,IAAA,OAAW,IAAA,EAAM,MAAA,KAAS,OAAA,CAAQ,CAAA,IAAK,CAAA;AAAA,KACvC,QAAA,OAAe,IAAA,EAAM,MAAA,KAAS,CAAA;AAAA,KAE9B,SAAA;EAAA,IACC,IAAA,UAAc,EAAA,EAAI,IAAA,CAAK,CAAA,IAAK,OAAA,CAAQ,CAAA;EAAA,IACpC,IAAA,UAAc,OAAA,EAAS,WAAA,EAAa,EAAA,EAAI,IAAA,CAAK,CAAA,IAAK,OAAA,CAAQ,CAAA;EAAA,IAC1D,IAAA,UAAc,MAAA,EAAQ,MAAA,EAAM,EAAA,EAAI,IAAA,CAAK,CAAA,IAAK,OAAA,CAAQ,CAAA;EAAA,IAClD,IAAA,UAAc,OAAA,EAAS,WAAA,EAAa,MAAA,EAAQ,MAAA,EAAM,EAAA,EAAI,IAAA,CAAK,CAAA,IAAK,OAAA,CAAQ,CAAA;AAAA;AAAA,KAEzE,aAAA;EAAA,IACC,IAAA,UAAc,EAAA,EAAI,QAAA,CAAS,CAAA,IAAK,CAAA;EAAA,IAChC,IAAA,UAAc,OAAA,EAAS,WAAA,EAAa,EAAA,EAAI,QAAA,CAAS,CAAA,IAAK,CAAA;EAAA,IACtD,IAAA,UAAc,MAAA,EAAQ,MAAA,EAAM,EAAA,EAAI,QAAA,CAAS,CAAA,IAAK,CAAA;EAAA,IAC9C,IAAA,UAAc,OAAA,EAAS,WAAA,EAAa,MAAA,EAAQ,MAAA,EAAM,EAAA,EAAI,QAAA,CAAS,CAAA,IAAK,CAAA;AAAA;;;;UAMhE,MAAA,SAAe,UAAA;EACvB,SAAA,EAAW,SAAA;EACX,aAAA,EAAe,aAAA;AAAA;;;;;;;;iBAUD,SAAA,CAAU,qBAAA,YAAiC,MAAA"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../src/instrumentations.ts","../src/logger.ts","../src/metrics.ts","../src/otel.ts","../src/tracer.ts"],"mappings":"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"}
package/dist/index.mjs CHANGED
@@ -14,7 +14,6 @@ import kleur from "kleur";
14
14
  import { containerDetector } from "@opentelemetry/resource-detector-container";
15
15
  import { gcpDetector } from "@opentelemetry/resource-detector-gcp";
16
16
  import { detectResources, envDetector, osDetector, processDetector, resourceFromAttributes, serviceInstanceIdDetector } from "@opentelemetry/resources";
17
-
18
17
  //#region src/instrumentations.ts
19
18
  let _http;
20
19
  let _express;
@@ -63,7 +62,6 @@ const instrumentations = {
63
62
  return _socketIo;
64
63
  }
65
64
  };
66
-
67
65
  //#endregion
68
66
  //#region src/consts.ts
69
67
  const LOG_SEVERITY_MAP = {
@@ -79,7 +77,6 @@ const LOG_SEVERITY_MAP = {
79
77
  ALERT: 22,
80
78
  EMERGENCY: 23
81
79
  };
82
-
83
80
  //#endregion
84
81
  //#region src/loggers/formatters/style.ts
85
82
  const colors = {
@@ -116,14 +113,7 @@ const statusColorMap = {
116
113
  1: colors.green,
117
114
  2: colors.red
118
115
  };
119
- const kindColorMap = {
120
- 0: colors.white,
121
- 1: colors.cyan,
122
- 2: colors.yellow,
123
- 3: colors.magenta,
124
- 4: colors.green
125
- };
126
-
116
+ colors.white, colors.cyan, colors.yellow, colors.magenta, colors.green;
127
117
  //#endregion
128
118
  //#region src/loggers/formatters/shared.ts
129
119
  const stringify = fss.default.stableStringify;
@@ -146,14 +136,13 @@ function formatScope(resource, instrumentationScope) {
146
136
  const { name, version } = instrumentationScope;
147
137
  const scopeLabel = component || (name && name !== "unknown" ? name : void 0);
148
138
  if (!scopeLabel) return "";
149
- const versionLabel = version ? `@${version}` : "";
150
- return colors.cyan(`${scopeLabel}${versionLabel} `);
139
+ return colors.cyan(`${scopeLabel} `);
151
140
  }
152
141
  function formatMessage(record) {
153
142
  return typeof record.body === "string" ? record.body : stringify(record.body);
154
143
  }
155
144
  function formatAttributes(attrs) {
156
- const keys = Object.keys(attrs).filter((k) => !k.startsWith("service.") && !k.startsWith("serviceContext."));
145
+ const keys = Object.keys(attrs).filter((k) => !k.startsWith("service.") && !k.startsWith("serviceContext.") && k !== "cloud.orchestrator" && k !== "component.name");
157
146
  if (keys.length === 0) return "";
158
147
  const formatted = keys.map((k) => {
159
148
  const val = attrs[k];
@@ -169,14 +158,12 @@ function calculateDuration(span) {
169
158
  const end = hrTimeToMillis(span.endTime);
170
159
  return Math.max(0, Math.round(end - start));
171
160
  }
172
-
173
161
  //#endregion
174
162
  //#region src/loggers/formatters/log-record.ts
175
163
  function formatLogRecord(record) {
176
164
  const timestamp = formatTimestamp(record.hrTime);
177
165
  return `${formatService(record.resource)} ${timestamp} ${formatLevel(record)} ${formatScope(record.resource, record.instrumentationScope)}${formatMessage(record)}${formatAttributes(record.attributes)}`;
178
166
  }
179
-
180
167
  //#endregion
181
168
  //#region src/loggers/formatters/metrics.ts
182
169
  function formatMetrics(resourceMetrics) {
@@ -207,7 +194,6 @@ function extractMetricValue(dp) {
207
194
  function isHistogramLike(val) {
208
195
  return typeof val === "object" && val !== null && "sum" in val && typeof val.sum === "number";
209
196
  }
210
-
211
197
  //#endregion
212
198
  //#region src/loggers/formatters/span.ts
213
199
  const LABEL_WIDTH = 20;
@@ -311,7 +297,6 @@ function computeDepth(span, allSpans) {
311
297
  }
312
298
  return depth;
313
299
  }
314
-
315
300
  //#endregion
316
301
  //#region src/loggers/console-metric-pretty-exporter.ts
317
302
  var ConsoleMetricPrettyExporter = class {
@@ -351,7 +336,96 @@ function globToRegex(glob) {
351
336
  const regex = `^${glob.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*")}$`;
352
337
  return new RegExp(regex);
353
338
  }
354
-
339
+ //#endregion
340
+ //#region src/loggers/gcp-json-log-exporter.ts
341
+ /**
342
+ * GCP Cloud Logging severity levels.
343
+ * Maps OTEL severity numbers to GCP-recognized severity strings.
344
+ * @see https://cloud.google.com/logging/docs/reference/v2/rest/v2/LogEntry#LogSeverity
345
+ */
346
+ const OTEL_TO_GCP_SEVERITY = {
347
+ TRACE: "DEBUG",
348
+ DEBUG: "DEBUG",
349
+ INFO: "INFO",
350
+ NOTICE: "NOTICE",
351
+ WARNING: "WARNING",
352
+ WARN: "WARNING",
353
+ ERROR: "ERROR",
354
+ FATAL: "CRITICAL",
355
+ CRITICAL: "CRITICAL",
356
+ ALERT: "ALERT",
357
+ EMERGENCY: "EMERGENCY"
358
+ };
359
+ /** Attribute keys that are excluded from labels (already represented elsewhere in the JSON) */
360
+ const EXCLUDED_LABEL_KEYS = new Set([
361
+ "service.name",
362
+ "service.version",
363
+ "serviceContext.service",
364
+ "serviceContext.version",
365
+ "component.name",
366
+ "cloud.orchestrator",
367
+ "trace_id",
368
+ "span_id"
369
+ ]);
370
+ /**
371
+ * A LogRecordExporter that outputs structured JSON to stdout,
372
+ * compatible with GCP Cloud Logging's expected format.
373
+ *
374
+ * When running on GKE, Cloud Logging automatically picks up
375
+ * JSON lines from stdout and parses recognized fields like
376
+ * `severity`, `message`, `logging.googleapis.com/trace`, etc.
377
+ *
378
+ * @see https://cloud.google.com/logging/docs/structured-logging
379
+ */
380
+ var GcpJsonLogExporter = class {
381
+ logThreshold;
382
+ gcpProject;
383
+ constructor() {
384
+ const defaultLogLevel = "INFO";
385
+ this.logThreshold = LOG_SEVERITY_MAP[process.env.LOG_LEVEL?.toUpperCase() ?? defaultLogLevel] ?? LOG_SEVERITY_MAP[defaultLogLevel];
386
+ this.gcpProject = process.env.GCP_PROJECT || process.env.GOOGLE_CLOUD_PROJECT;
387
+ }
388
+ export(logs, resultCallback) {
389
+ for (const record of logs) if ((record.severityNumber ?? 0) >= this.logThreshold) {
390
+ const json = this.formatRecord(record);
391
+ process.stdout.write(`${json}\n`);
392
+ }
393
+ resultCallback({ code: ExportResultCode.SUCCESS });
394
+ }
395
+ shutdown() {
396
+ return Promise.resolve();
397
+ }
398
+ forceFlush() {
399
+ return Promise.resolve();
400
+ }
401
+ formatRecord(record) {
402
+ const severity = OTEL_TO_GCP_SEVERITY[(record.severityText ?? "INFO").toUpperCase()] ?? "DEFAULT";
403
+ const timestamp = new Date(hrTimeToMillis(record.hrTime)).toISOString();
404
+ const message = typeof record.body === "string" ? record.body : JSON.stringify(record.body);
405
+ const serviceName = record.resource.attributes[ATTR_SERVICE_NAME] ?? "unknown-service";
406
+ const serviceVersion = record.resource.attributes[ATTR_SERVICE_VERSION] ?? "1.0.0";
407
+ const traceId = record.attributes.trace_id;
408
+ const spanId = record.attributes.span_id;
409
+ const entry = {
410
+ severity,
411
+ message,
412
+ time: timestamp,
413
+ serviceContext: {
414
+ service: serviceName,
415
+ version: serviceVersion
416
+ }
417
+ };
418
+ if (traceId) entry["logging.googleapis.com/trace"] = this.gcpProject ? `projects/${this.gcpProject}/traces/${traceId}` : traceId;
419
+ if (spanId) entry["logging.googleapis.com/spanId"] = spanId;
420
+ const labels = {};
421
+ for (const [key, value] of Object.entries(record.attributes)) {
422
+ if (EXCLUDED_LABEL_KEYS.has(key)) continue;
423
+ labels[key] = typeof value === "object" ? JSON.stringify(value) : String(value);
424
+ }
425
+ if (Object.keys(labels).length > 0) entry["logging.googleapis.com/labels"] = labels;
426
+ return JSON.stringify(entry);
427
+ }
428
+ };
355
429
  //#endregion
356
430
  //#region src/loggers/console-log-pretty-exporter.ts
357
431
  var ConsoleLogPrettyExporter = class {
@@ -382,7 +456,6 @@ var ConsoleLogPrettyExporter = class {
382
456
  done?.({ code: ExportResultCode.SUCCESS });
383
457
  }
384
458
  };
385
-
386
459
  //#endregion
387
460
  //#region src/loggers/console-span-pretty-exporter.ts
388
461
  var ConsoleSpanPrettyExporter = class {
@@ -415,7 +488,6 @@ var ConsoleSpanPrettyExporter = class {
415
488
  return Promise.resolve();
416
489
  }
417
490
  };
418
-
419
491
  //#endregion
420
492
  //#region src/loggers/tree-span-processor.ts
421
493
  var TreeSpanProcessor = class {
@@ -455,13 +527,15 @@ var TreeSpanProcessor = class {
455
527
  await this.exporter.forceFlush?.();
456
528
  }
457
529
  };
458
-
459
530
  //#endregion
460
531
  //#region src/providers.ts
461
532
  const getLogProvider = (resource, otlpEndpoint) => {
462
533
  if (otlpEndpoint) {
463
534
  const processors = [new BatchLogRecordProcessor(new OTLPLogExporter({ url: `${otlpEndpoint}/v1/logs` }))];
464
- if (process.env.LOG_LEVEL) processors.push(new SimpleLogRecordProcessor(new ConsoleLogPrettyExporter()));
535
+ if (process.env.LOG_LEVEL) {
536
+ const consoleExporter = !!(process.env.KUBERNETES_SERVICE_HOST || process.env.GCP_PROJECT) ? new GcpJsonLogExporter() : new ConsoleLogPrettyExporter();
537
+ processors.push(new SimpleLogRecordProcessor(consoleExporter));
538
+ }
465
539
  return new LoggerProvider({
466
540
  resource,
467
541
  processors
@@ -479,7 +553,6 @@ const getSpanProcessor = (otlpEndpoint) => {
479
553
  const getMetricReader = (otlpEndpoint) => {
480
554
  return new PeriodicExportingMetricReader({ exporter: otlpEndpoint ? new OTLPMetricExporter({ url: `${otlpEndpoint}/v1/metrics` }) : new ConsoleMetricPrettyExporter() });
481
555
  };
482
-
483
556
  //#endregion
484
557
  //#region src/otel-context.ts
485
558
  /**
@@ -512,7 +585,6 @@ function detectTelemetryContext(componentNameOverride) {
512
585
  }
513
586
  };
514
587
  }
515
-
516
588
  //#endregion
517
589
  //#region src/resource.ts
518
590
  const getResource = async () => {
@@ -531,7 +603,6 @@ const getResource = async () => {
531
603
  if (resource.waitForAsyncAttributes) await resource.waitForAsyncAttributes();
532
604
  return resource;
533
605
  };
534
-
535
606
  //#endregion
536
607
  //#region src/otel.ts
537
608
  diag.disable();
@@ -579,7 +650,6 @@ async function _initialize(instrumentations) {
579
650
  console.error("[otel] Startup error:", err);
580
651
  }
581
652
  }
582
-
583
653
  //#endregion
584
654
  //#region src/logger.ts
585
655
  function getLogger(serviceOverride, extraAttrs = {}) {
@@ -610,29 +680,33 @@ function getLogger(serviceOverride, extraAttrs = {}) {
610
680
  }
611
681
  });
612
682
  }
683
+ function resolveArgs(msg, errOrAttrs, maybeAttrs = {}) {
684
+ if (errOrAttrs instanceof Error) return {
685
+ body: `${msg}: ${errOrAttrs.stack || errOrAttrs.message}`,
686
+ attrs: maybeAttrs
687
+ };
688
+ return {
689
+ body: msg instanceof Error ? msg.stack || msg.message : msg,
690
+ attrs: errOrAttrs || {}
691
+ };
692
+ }
693
+ function createLogFn(severity) {
694
+ return (msg, errOrAttrs, maybeAttrs = {}) => {
695
+ const { body, attrs } = resolveArgs(msg, errOrAttrs, maybeAttrs);
696
+ emit(severity, body, attrs);
697
+ };
698
+ }
613
699
  return {
614
- debug: (msg, attrs) => emit("DEBUG", msg, attrs),
615
- info: (msg, attrs) => emit("INFO", msg, attrs),
616
- notice: (msg, attrs) => emit("NOTICE", msg, attrs),
617
- warn: (msg, attrs) => emit("WARNING", msg, attrs),
618
- error: (msg, errOrAttrs, maybeAttrs = {}) => {
619
- let body;
620
- let attrs;
621
- if (errOrAttrs instanceof Error) {
622
- body = `${msg}: ${errOrAttrs.stack || errOrAttrs.message}`;
623
- attrs = maybeAttrs;
624
- } else {
625
- body = msg instanceof Error ? msg.stack || msg.message : msg;
626
- attrs = errOrAttrs || {};
627
- }
628
- emit("ERROR", body, attrs);
629
- },
630
- critical: (msg, attrs) => emit("CRITICAL", msg, attrs),
631
- alert: (msg, attrs) => emit("ALERT", msg, attrs),
632
- emergency: (msg, attrs) => emit("EMERGENCY", msg, attrs)
700
+ debug: createLogFn("DEBUG"),
701
+ info: createLogFn("INFO"),
702
+ notice: createLogFn("NOTICE"),
703
+ warn: createLogFn("WARNING"),
704
+ error: createLogFn("ERROR"),
705
+ critical: createLogFn("CRITICAL"),
706
+ alert: createLogFn("ALERT"),
707
+ emergency: createLogFn("EMERGENCY")
633
708
  };
634
709
  }
635
-
636
710
  //#endregion
637
711
  //#region src/metrics.ts
638
712
  function getMeter(componentNameOverride) {
@@ -640,7 +714,6 @@ function getMeter(componentNameOverride) {
640
714
  const { componentName, systemName, systemVersion } = detectTelemetryContext(componentNameOverride);
641
715
  return metrics.getMeter(componentName ?? systemName, systemVersion);
642
716
  }
643
-
644
717
  //#endregion
645
718
  //#region src/tracer.ts
646
719
  /**
@@ -734,7 +807,7 @@ function extractArgs(spanOptionsSpanOrFunc, spanOrFunc, func) {
734
807
  const isFunction = (value) => typeof value === "function";
735
808
  const isSpan = (value) => value !== null && value !== void 0 && isFunction(value.spanContext) && isFunction(value.end);
736
809
  const isSpanOptions = (value) => value !== null && value !== void 0 && (!!value.startTime || !!value.attributes || !!value.kind) && !isSpan(value);
737
-
738
810
  //#endregion
739
811
  export { SpanStatusCode, context, getLogger, getMeter, getTracer, initialize, instrumentations, isInitialized };
812
+
740
813
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["SpanStatusCode","SpanStatusCode","context","context","SpanStatusCode"],"sources":["../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":["import type { Instrumentation } from '@opentelemetry/instrumentation'\n\nlet _http: Promise<Instrumentation> | undefined\nlet _express: Promise<Instrumentation> | undefined\nlet _grpc: Promise<Instrumentation> | undefined\nlet _redis: Promise<Instrumentation> | undefined\nlet _dns: Promise<Instrumentation> | undefined\nlet _net: Promise<Instrumentation> | undefined\nlet _fs: Promise<Instrumentation> | undefined\nlet _undici: Promise<Instrumentation> | undefined\nlet _socketIo: Promise<Instrumentation> | undefined\n\nexport const instrumentations = {\n get http() {\n if (!_http) {\n _http = import('@opentelemetry/instrumentation-http').then(\n ({ HttpInstrumentation }) => new HttpInstrumentation()\n )\n }\n return _http\n },\n\n get express() {\n if (!_express) {\n _express = import('@opentelemetry/instrumentation-express').then(\n ({ ExpressInstrumentation }) => new ExpressInstrumentation()\n )\n }\n return _express\n },\n\n get grpc() {\n if (!_grpc) {\n _grpc = import('@opentelemetry/instrumentation-grpc').then(\n ({ GrpcInstrumentation }) => new GrpcInstrumentation()\n )\n }\n return _grpc\n },\n\n get redis() {\n if (!_redis) {\n _redis = import('@opentelemetry/instrumentation-redis').then(\n ({ RedisInstrumentation }) => new RedisInstrumentation()\n )\n }\n return _redis\n },\n\n get dns() {\n if (!_dns) {\n _dns = import('@opentelemetry/instrumentation-dns').then(\n ({ DnsInstrumentation }) => new DnsInstrumentation()\n )\n }\n return _dns\n },\n\n get net() {\n if (!_net) {\n _net = import('@opentelemetry/instrumentation-net').then(\n ({ NetInstrumentation }) => new NetInstrumentation()\n )\n }\n return _net\n },\n\n get fs() {\n if (!_fs) {\n _fs = import('@opentelemetry/instrumentation-fs').then(\n ({ FsInstrumentation }) => new FsInstrumentation()\n )\n }\n return _fs\n },\n\n get undici() {\n if (!_undici) {\n _undici = import('@opentelemetry/instrumentation-undici').then(\n ({ UndiciInstrumentation }) => new UndiciInstrumentation()\n )\n }\n return _undici\n },\n\n get socketIo() {\n if (!_socketIo) {\n _socketIo = import('@opentelemetry/instrumentation-socket.io').then(\n ({ SocketIoInstrumentation }) => new SocketIoInstrumentation()\n )\n }\n return _socketIo\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, version } = instrumentationScope\n const scopeLabel =\n component || (name && name !== 'unknown' ? name : undefined)\n if (!scopeLabel) return ''\n\n const versionLabel = version ? `@${version}` : ''\n return colors.cyan(`${scopeLabel}${versionLabel} `)\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) => !k.startsWith('service.') && !k.startsWith('serviceContext.')\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 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 const severity = record.severityNumber || SeverityNumber.UNSPECIFIED\n\n if (severity >= SeverityNumber.ERROR) {\n console.error(formatted)\n } else if (severity >= SeverityNumber.WARN) {\n console.warn(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 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 processors.push(\n new SimpleLogRecordProcessor(new ConsoleLogPrettyExporter())\n )\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 const processor = otlpEndpoint\n ? new BatchSpanProcessor(exporter)\n : new TreeSpanProcessor(exporter)\n\n return processor\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\nexport const getResource = async () => {\n const baseRes = await detectResources({\n detectors: [\n containerDetector,\n envDetector,\n 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 { 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\nlet initialization: Promise<void> | undefined\nlet _isInitialized = false\nexport async function initialize(\n ...instrumentations: Promise<Instrumentation>[]\n) {\n if (!initialization) {\n const resolvedInstrumentations = await Promise.all(instrumentations)\n initialization = _initialize(resolvedInstrumentations)\n initialization.then(() => {\n _isInitialized = true\n })\n }\n return initialization\n}\n\nexport function isInitialized() {\n return _isInitialized\n}\n\nasync function _initialize(instrumentations: Instrumentation[]) {\n try {\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 const logProvider = getLogProvider(resource, otlpEndpoint)\n logs.setGlobalLoggerProvider(logProvider)\n\n // NodeSDK setup\n const spanProcessor = getSpanProcessor(otlpEndpoint)\n const metricReader = getMetricReader(otlpEndpoint)\n const sdk = new NodeSDK({\n spanProcessor,\n metricReader,\n instrumentations,\n resource,\n })\n\n await sdk.start()\n console.log(`[otel] Telemetry initialized for \"${serviceName}\"`)\n\n process.on('SIGTERM', async () => {\n console.log('[otel] Shutting down...')\n await Promise.all([sdk.shutdown(), logProvider.shutdown()])\n console.log('[otel] Shutdown complete.')\n process.exit(0)\n })\n } catch (err) {\n console.error('[otel] Startup error:', err)\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 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 console.warn('OTEL must be initialized before using logger')\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 ...defaultAttrs,\n ...(spanContext && {\n trace_id: spanContext.traceId,\n span_id: spanContext.spanId,\n }),\n ...attrs,\n },\n })\n }\n\n return {\n debug: (msg: string, attrs?: Attrs) => emit('DEBUG', msg, attrs),\n info: (msg: string, attrs?: Attrs) => emit('INFO', msg, attrs),\n notice: (msg: string, attrs?: Attrs) => emit('NOTICE', msg, attrs),\n warn: (msg: string, attrs?: Attrs) => emit('WARNING', msg, attrs),\n error: (\n msg: string | Error,\n errOrAttrs?: Error | Attrs,\n maybeAttrs: Attrs = {}\n ) => {\n let body: string\n let attrs: Attrs\n\n if (errOrAttrs instanceof Error) {\n body = `${msg}: ${errOrAttrs.stack || errOrAttrs.message}`\n attrs = maybeAttrs\n } else {\n body = msg instanceof Error ? msg.stack || msg.message : msg\n attrs = errOrAttrs || {}\n }\n\n emit('ERROR', body, attrs)\n },\n critical: (msg: string, attrs?: Attrs) => emit('CRITICAL', msg, attrs),\n alert: (msg: string, attrs?: Attrs) => emit('ALERT', msg, attrs),\n emergency: (msg: string, attrs?: Attrs) => emit('EMERGENCY', msg, attrs),\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\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 span.end()\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\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 span.end()\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)\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","context","context","SpanStatusCode"],"sources":["../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/gcp-json-log-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":["import type { Instrumentation } from '@opentelemetry/instrumentation'\n\nlet _http: Promise<Instrumentation> | undefined\nlet _express: Promise<Instrumentation> | undefined\nlet _grpc: Promise<Instrumentation> | undefined\nlet _redis: Promise<Instrumentation> | undefined\nlet _dns: Promise<Instrumentation> | undefined\nlet _net: Promise<Instrumentation> | undefined\nlet _fs: Promise<Instrumentation> | undefined\nlet _undici: Promise<Instrumentation> | undefined\nlet _socketIo: Promise<Instrumentation> | undefined\n\nexport const instrumentations = {\n get http() {\n if (!_http) {\n _http = import('@opentelemetry/instrumentation-http').then(\n ({ HttpInstrumentation }) => new HttpInstrumentation()\n )\n }\n return _http\n },\n\n get express() {\n if (!_express) {\n _express = import('@opentelemetry/instrumentation-express').then(\n ({ ExpressInstrumentation }) => new ExpressInstrumentation()\n )\n }\n return _express\n },\n\n get grpc() {\n if (!_grpc) {\n _grpc = import('@opentelemetry/instrumentation-grpc').then(\n ({ GrpcInstrumentation }) => new GrpcInstrumentation()\n )\n }\n return _grpc\n },\n\n get redis() {\n if (!_redis) {\n _redis = import('@opentelemetry/instrumentation-redis').then(\n ({ RedisInstrumentation }) => new RedisInstrumentation()\n )\n }\n return _redis\n },\n\n get dns() {\n if (!_dns) {\n _dns = import('@opentelemetry/instrumentation-dns').then(\n ({ DnsInstrumentation }) => new DnsInstrumentation()\n )\n }\n return _dns\n },\n\n get net() {\n if (!_net) {\n _net = import('@opentelemetry/instrumentation-net').then(\n ({ NetInstrumentation }) => new NetInstrumentation()\n )\n }\n return _net\n },\n\n get fs() {\n if (!_fs) {\n _fs = import('@opentelemetry/instrumentation-fs').then(\n ({ FsInstrumentation }) => new FsInstrumentation()\n )\n }\n return _fs\n },\n\n get undici() {\n if (!_undici) {\n _undici = import('@opentelemetry/instrumentation-undici').then(\n ({ UndiciInstrumentation }) => new UndiciInstrumentation()\n )\n }\n return _undici\n },\n\n get socketIo() {\n if (!_socketIo) {\n _socketIo = import('@opentelemetry/instrumentation-socket.io').then(\n ({ SocketIoInstrumentation }) => new SocketIoInstrumentation()\n )\n }\n return _socketIo\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, version } = 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 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 { type ExportResult, ExportResultCode } from '@opentelemetry/core'\nimport type {\n LogRecordExporter,\n ReadableLogRecord,\n} from '@opentelemetry/sdk-logs'\nimport {\n ATTR_SERVICE_NAME,\n ATTR_SERVICE_VERSION,\n} from '@opentelemetry/semantic-conventions'\nimport { LOG_SEVERITY_MAP, type LOG_SEVERITY_NAME } from '../consts'\nimport { hrTimeToMillis } from './formatters/shared'\n\n/**\n * GCP Cloud Logging severity levels.\n * Maps OTEL severity numbers to GCP-recognized severity strings.\n * @see https://cloud.google.com/logging/docs/reference/v2/rest/v2/LogEntry#LogSeverity\n */\nconst OTEL_TO_GCP_SEVERITY: Record<string, string> = {\n TRACE: 'DEBUG',\n DEBUG: 'DEBUG',\n INFO: 'INFO',\n NOTICE: 'NOTICE',\n WARNING: 'WARNING',\n WARN: 'WARNING',\n ERROR: 'ERROR',\n FATAL: 'CRITICAL',\n CRITICAL: 'CRITICAL',\n ALERT: 'ALERT',\n EMERGENCY: 'EMERGENCY',\n}\n\n/** Attribute keys that are excluded from labels (already represented elsewhere in the JSON) */\nconst EXCLUDED_LABEL_KEYS = new Set([\n 'service.name',\n 'service.version',\n 'serviceContext.service',\n 'serviceContext.version',\n 'component.name',\n 'cloud.orchestrator',\n 'trace_id',\n 'span_id',\n])\n\n/**\n * A LogRecordExporter that outputs structured JSON to stdout,\n * compatible with GCP Cloud Logging's expected format.\n *\n * When running on GKE, Cloud Logging automatically picks up\n * JSON lines from stdout and parses recognized fields like\n * `severity`, `message`, `logging.googleapis.com/trace`, etc.\n *\n * @see https://cloud.google.com/logging/docs/structured-logging\n */\nexport class GcpJsonLogExporter implements LogRecordExporter {\n private readonly logThreshold: number\n private readonly gcpProject: string | undefined\n\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 this.gcpProject =\n process.env.GCP_PROJECT || process.env.GOOGLE_CLOUD_PROJECT\n }\n\n export(\n logs: ReadableLogRecord[],\n resultCallback: (result: ExportResult) => void\n ): void {\n for (const record of logs) {\n if ((record.severityNumber ?? 0) >= this.logThreshold) {\n const json = this.formatRecord(record)\n process.stdout.write(`${json}\\n`)\n }\n }\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 private formatRecord(record: ReadableLogRecord): string {\n const severityText = (record.severityText ?? 'INFO').toUpperCase()\n const severity = OTEL_TO_GCP_SEVERITY[severityText] ?? 'DEFAULT'\n const timestamp = new Date(hrTimeToMillis(record.hrTime)).toISOString()\n const message =\n typeof record.body === 'string'\n ? record.body\n : JSON.stringify(record.body)\n\n const serviceName =\n record.resource.attributes[ATTR_SERVICE_NAME] ?? 'unknown-service'\n const serviceVersion =\n record.resource.attributes[ATTR_SERVICE_VERSION] ?? '1.0.0'\n\n const traceId = record.attributes.trace_id as string | undefined\n const spanId = record.attributes.span_id as string | undefined\n\n // Build the structured log entry\n const entry: Record<string, unknown> = {\n severity,\n message,\n time: timestamp,\n serviceContext: {\n service: serviceName,\n version: serviceVersion,\n },\n }\n\n // GCP trace correlation\n if (traceId) {\n entry['logging.googleapis.com/trace'] = this.gcpProject\n ? `projects/${this.gcpProject}/traces/${traceId}`\n : traceId\n }\n\n if (spanId) {\n entry['logging.googleapis.com/spanId'] = spanId\n }\n\n // Collect remaining attributes as labels\n const labels: Record<string, string> = {}\n for (const [key, value] of Object.entries(record.attributes)) {\n if (EXCLUDED_LABEL_KEYS.has(key)) continue\n labels[key] =\n typeof value === 'object' ? JSON.stringify(value) : String(value)\n }\n if (Object.keys(labels).length > 0) {\n entry['logging.googleapis.com/labels'] = labels\n }\n\n return JSON.stringify(entry)\n }\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 const severity = record.severityNumber || SeverityNumber.UNSPECIFIED\n\n if (severity >= SeverityNumber.ERROR) {\n console.error(formatted)\n } else if (severity >= SeverityNumber.WARN) {\n console.warn(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 type SpanProcessor,\n} from '@opentelemetry/sdk-trace-node'\nimport { ConsoleMetricPrettyExporter } from './loggers/console-metric-pretty-exporter'\nimport { GcpJsonLogExporter } from './loggers/gcp-json-log-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 isGcp = !!(\n process.env.KUBERNETES_SERVICE_HOST || process.env.GCP_PROJECT\n )\n const consoleExporter = isGcp\n ? new GcpJsonLogExporter()\n : 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 const processor = otlpEndpoint\n ? new BatchSpanProcessor(exporter)\n : new TreeSpanProcessor(exporter)\n\n return processor\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\nexport const getResource = async () => {\n const baseRes = await detectResources({\n detectors: [\n containerDetector,\n envDetector,\n 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 { 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\nlet initialization: Promise<void> | undefined\nlet _isInitialized = false\nexport async function initialize(\n ...instrumentations: Promise<Instrumentation>[]\n) {\n if (!initialization) {\n const resolvedInstrumentations = await Promise.all(instrumentations)\n initialization = _initialize(resolvedInstrumentations)\n initialization.then(() => {\n _isInitialized = true\n })\n }\n return initialization\n}\n\nexport function isInitialized() {\n return _isInitialized\n}\n\nasync function _initialize(instrumentations: Instrumentation[]) {\n try {\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 const logProvider = getLogProvider(resource, otlpEndpoint)\n logs.setGlobalLoggerProvider(logProvider)\n\n // NodeSDK setup\n const spanProcessor = getSpanProcessor(otlpEndpoint)\n const metricReader = getMetricReader(otlpEndpoint)\n const sdk = new NodeSDK({\n spanProcessor,\n metricReader,\n instrumentations,\n resource,\n })\n\n await sdk.start()\n console.log(`[otel] Telemetry initialized for \"${serviceName}\"`)\n\n process.on('SIGTERM', async () => {\n console.log('[otel] Shutting down...')\n await Promise.all([sdk.shutdown(), logProvider.shutdown()])\n console.log('[otel] Shutdown complete.')\n process.exit(0)\n })\n } catch (err) {\n console.error('[otel] Startup error:', err)\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 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 console.warn('OTEL must be initialized before using logger')\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 ...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 const body = `${msg}: ${errOrAttrs.stack || errOrAttrs.message}`\n return { body, attrs: maybeAttrs }\n }\n\n const body = msg instanceof Error ? msg.stack || msg.message : msg\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('WARNING'),\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\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 span.end()\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\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 span.end()\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)\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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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sebspark/otel",
3
- "version": "2.0.13",
3
+ "version": "2.1.0",
4
4
  "license": "Apache-2.0",
5
5
  "type": "module",
6
6
  "main": "dist/index.mjs",
@@ -23,34 +23,34 @@
23
23
  },
24
24
  "dependencies": {
25
25
  "@opentelemetry/api": "1.9.0",
26
- "@opentelemetry/api-logs": "0.212.0",
27
- "@opentelemetry/core": "2.5.1",
28
- "@opentelemetry/exporter-logs-otlp-http": "0.212.0",
29
- "@opentelemetry/exporter-metrics-otlp-http": "0.212.0",
30
- "@opentelemetry/exporter-trace-otlp-http": "0.212.0",
31
- "@opentelemetry/instrumentation": "0.212.0",
32
- "@opentelemetry/instrumentation-dns": "0.55.0",
33
- "@opentelemetry/instrumentation-express": "0.60.0",
34
- "@opentelemetry/instrumentation-fs": "0.31.0",
35
- "@opentelemetry/instrumentation-grpc": "0.212.0",
36
- "@opentelemetry/instrumentation-http": "0.212.0",
37
- "@opentelemetry/instrumentation-net": "0.56.0",
38
- "@opentelemetry/instrumentation-redis": "0.60.0",
39
- "@opentelemetry/instrumentation-socket.io": "0.59.0",
40
- "@opentelemetry/instrumentation-undici": "0.22.0",
41
- "@opentelemetry/resource-detector-container": "0.8.3",
42
- "@opentelemetry/resource-detector-gcp": "0.47.0",
43
- "@opentelemetry/resources": "2.5.1",
44
- "@opentelemetry/sdk-logs": "0.212.0",
45
- "@opentelemetry/sdk-metrics": "2.5.1",
46
- "@opentelemetry/sdk-node": "0.212.0",
47
- "@opentelemetry/sdk-trace-node": "2.5.1",
26
+ "@opentelemetry/api-logs": "0.213.0",
27
+ "@opentelemetry/core": "2.6.0",
28
+ "@opentelemetry/exporter-logs-otlp-http": "0.213.0",
29
+ "@opentelemetry/exporter-metrics-otlp-http": "0.213.0",
30
+ "@opentelemetry/exporter-trace-otlp-http": "0.213.0",
31
+ "@opentelemetry/instrumentation": "0.213.0",
32
+ "@opentelemetry/instrumentation-dns": "0.56.0",
33
+ "@opentelemetry/instrumentation-express": "0.61.0",
34
+ "@opentelemetry/instrumentation-fs": "0.32.0",
35
+ "@opentelemetry/instrumentation-grpc": "0.213.0",
36
+ "@opentelemetry/instrumentation-http": "0.213.0",
37
+ "@opentelemetry/instrumentation-net": "0.57.0",
38
+ "@opentelemetry/instrumentation-redis": "0.61.0",
39
+ "@opentelemetry/instrumentation-socket.io": "0.60.0",
40
+ "@opentelemetry/instrumentation-undici": "0.23.0",
41
+ "@opentelemetry/resource-detector-container": "0.8.4",
42
+ "@opentelemetry/resource-detector-gcp": "0.48.0",
43
+ "@opentelemetry/resources": "2.6.0",
44
+ "@opentelemetry/sdk-logs": "0.213.0",
45
+ "@opentelemetry/sdk-metrics": "2.6.0",
46
+ "@opentelemetry/sdk-node": "0.213.0",
47
+ "@opentelemetry/sdk-trace-node": "2.6.0",
48
48
  "@opentelemetry/semantic-conventions": "1.40.0",
49
49
  "fast-safe-stringify": "2.1.1",
50
50
  "kleur": "4.1.5"
51
51
  },
52
52
  "devDependencies": {
53
- "@opentelemetry/context-async-hooks": "2.5.1"
53
+ "@opentelemetry/context-async-hooks": "2.6.0"
54
54
  },
55
55
  "repository": {
56
56
  "type": "git",