@sebspark/otel 0.4.4 → 0.5.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 +2 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +138 -117
- package/dist/index.mjs +131 -110
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
import { LoggerProvider } from '@opentelemetry/api-logs';
|
|
1
2
|
import * as _opentelemetry_api from '@opentelemetry/api';
|
|
2
3
|
import { trace, SpanOptions } from '@opentelemetry/api';
|
|
3
4
|
|
|
4
5
|
type Attrs = Record<string, any>;
|
|
5
|
-
declare function getLogger(serviceOverride?: string, extraAttrs?: Attrs): {
|
|
6
|
+
declare function getLogger(serviceOverride?: string, extraAttrs?: Attrs, testProvider?: LoggerProvider): {
|
|
6
7
|
debug: (msg: string, attrs?: Attrs) => void;
|
|
7
8
|
info: (msg: string, attrs?: Attrs) => void;
|
|
8
9
|
notice: (msg: string, attrs?: Attrs) => void;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
import { LoggerProvider } from '@opentelemetry/api-logs';
|
|
1
2
|
import * as _opentelemetry_api from '@opentelemetry/api';
|
|
2
3
|
import { trace, SpanOptions } from '@opentelemetry/api';
|
|
3
4
|
|
|
4
5
|
type Attrs = Record<string, any>;
|
|
5
|
-
declare function getLogger(serviceOverride?: string, extraAttrs?: Attrs): {
|
|
6
|
+
declare function getLogger(serviceOverride?: string, extraAttrs?: Attrs, testProvider?: LoggerProvider): {
|
|
6
7
|
debug: (msg: string, attrs?: Attrs) => void;
|
|
7
8
|
info: (msg: string, attrs?: Attrs) => void;
|
|
8
9
|
notice: (msg: string, attrs?: Attrs) => void;
|
package/dist/index.js
CHANGED
|
@@ -38,8 +38,8 @@ __export(index_exports, {
|
|
|
38
38
|
module.exports = __toCommonJS(index_exports);
|
|
39
39
|
|
|
40
40
|
// src/logger.ts
|
|
41
|
-
var
|
|
42
|
-
var
|
|
41
|
+
var import_api4 = require("@opentelemetry/api");
|
|
42
|
+
var import_api_logs2 = require("@opentelemetry/api-logs");
|
|
43
43
|
|
|
44
44
|
// src/consts.ts
|
|
45
45
|
var LOG_SEVERITY_MAP = {
|
|
@@ -56,103 +56,9 @@ var LOG_SEVERITY_MAP = {
|
|
|
56
56
|
EMERGENCY: 23
|
|
57
57
|
};
|
|
58
58
|
|
|
59
|
-
// src/otel-context.ts
|
|
60
|
-
var import_semantic_conventions = require("@opentelemetry/semantic-conventions");
|
|
61
|
-
function detectTelemetryContext(componentNameOverride) {
|
|
62
|
-
const {
|
|
63
|
-
OTEL_SERVICE_NAME,
|
|
64
|
-
// e.g. "UserSystem"
|
|
65
|
-
OTEL_SERVICE_VERSION,
|
|
66
|
-
// e.g. "1.2.3"
|
|
67
|
-
K_SERVICE,
|
|
68
|
-
K_REVISION,
|
|
69
|
-
K_CONFIGURATION,
|
|
70
|
-
KUBERNETES_SERVICE_HOST,
|
|
71
|
-
POD_NAME,
|
|
72
|
-
POD_NAMESPACE,
|
|
73
|
-
GCP_PROJECT,
|
|
74
|
-
CLOUD_PROVIDER
|
|
75
|
-
} = process.env;
|
|
76
|
-
const systemName = OTEL_SERVICE_NAME || "unknown-service";
|
|
77
|
-
const systemVersion = OTEL_SERVICE_VERSION || "1.0.0";
|
|
78
|
-
const componentName = componentNameOverride || void 0;
|
|
79
|
-
const resourceAttributes = {
|
|
80
|
-
[import_semantic_conventions.ATTR_SERVICE_NAME]: systemName,
|
|
81
|
-
[import_semantic_conventions.ATTR_SERVICE_VERSION]: systemVersion,
|
|
82
|
-
"serviceContext.service": systemName,
|
|
83
|
-
"serviceContext.version": systemVersion,
|
|
84
|
-
...K_SERVICE && { "cloud.run.service": K_SERVICE },
|
|
85
|
-
...K_REVISION && { "cloud.run.revision": K_REVISION },
|
|
86
|
-
...K_CONFIGURATION && { "cloud.run.configuration": K_CONFIGURATION },
|
|
87
|
-
...POD_NAME && { "k8s.pod_name": POD_NAME },
|
|
88
|
-
...POD_NAMESPACE && { "k8s.namespace_name": POD_NAMESPACE },
|
|
89
|
-
...KUBERNETES_SERVICE_HOST && { "cloud.orchestrator": "kubernetes" },
|
|
90
|
-
...GCP_PROJECT && { "cloud.account.id": GCP_PROJECT },
|
|
91
|
-
...CLOUD_PROVIDER && { "cloud.provider": CLOUD_PROVIDER },
|
|
92
|
-
...componentName && { "component.name": componentName }
|
|
93
|
-
};
|
|
94
|
-
return {
|
|
95
|
-
systemName,
|
|
96
|
-
systemVersion,
|
|
97
|
-
componentName,
|
|
98
|
-
resourceAttributes
|
|
99
|
-
};
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
// src/logger.ts
|
|
103
|
-
function getLogger(serviceOverride, extraAttrs = {}) {
|
|
104
|
-
const { systemName, systemVersion, resourceAttributes } = detectTelemetryContext(serviceOverride);
|
|
105
|
-
const defaultAttrs = {
|
|
106
|
-
...resourceAttributes,
|
|
107
|
-
...extraAttrs
|
|
108
|
-
};
|
|
109
|
-
function emit(severityText, body, attrs = {}) {
|
|
110
|
-
const logger = import_api_logs.logs.getLogger(systemName, systemVersion);
|
|
111
|
-
const span = import_api.trace.getSpan(import_api.context.active());
|
|
112
|
-
const spanContext = span?.spanContext();
|
|
113
|
-
logger.emit({
|
|
114
|
-
severityText,
|
|
115
|
-
severityNumber: LOG_SEVERITY_MAP[severityText],
|
|
116
|
-
body,
|
|
117
|
-
attributes: {
|
|
118
|
-
...defaultAttrs,
|
|
119
|
-
...spanContext && {
|
|
120
|
-
trace_id: spanContext.traceId,
|
|
121
|
-
span_id: spanContext.spanId
|
|
122
|
-
},
|
|
123
|
-
...attrs
|
|
124
|
-
}
|
|
125
|
-
});
|
|
126
|
-
}
|
|
127
|
-
return {
|
|
128
|
-
debug: (msg, attrs) => emit("DEBUG", msg, attrs),
|
|
129
|
-
info: (msg, attrs) => emit("INFO", msg, attrs),
|
|
130
|
-
notice: (msg, attrs) => emit("NOTICE", msg, attrs),
|
|
131
|
-
warn: (msg, attrs) => emit("WARNING", msg, attrs),
|
|
132
|
-
error: (msg, errOrAttrs, maybeAttrs = {}) => {
|
|
133
|
-
let body;
|
|
134
|
-
let attrs;
|
|
135
|
-
if (errOrAttrs instanceof Error) {
|
|
136
|
-
body = `${msg}: ${errOrAttrs.stack || errOrAttrs.message}`;
|
|
137
|
-
attrs = maybeAttrs;
|
|
138
|
-
} else {
|
|
139
|
-
body = msg instanceof Error ? msg.stack || msg.message : msg;
|
|
140
|
-
attrs = errOrAttrs || {};
|
|
141
|
-
}
|
|
142
|
-
emit("ERROR", body, attrs);
|
|
143
|
-
},
|
|
144
|
-
critical: (msg, attrs) => emit("CRITICAL", msg, attrs),
|
|
145
|
-
alert: (msg, attrs) => emit("ALERT", msg, attrs),
|
|
146
|
-
emergency: (msg, attrs) => emit("EMERGENCY", msg, attrs)
|
|
147
|
-
};
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
// src/metrics.ts
|
|
151
|
-
var import_api5 = require("@opentelemetry/api");
|
|
152
|
-
|
|
153
59
|
// src/otel.ts
|
|
154
|
-
var
|
|
155
|
-
var
|
|
60
|
+
var import_api3 = require("@opentelemetry/api");
|
|
61
|
+
var import_api_logs = require("@opentelemetry/api-logs");
|
|
156
62
|
var import_auto_instrumentations_node = require("@opentelemetry/auto-instrumentations-node");
|
|
157
63
|
var import_sdk_node = require("@opentelemetry/sdk-node");
|
|
158
64
|
|
|
@@ -168,7 +74,7 @@ var import_sdk_trace_node = require("@opentelemetry/sdk-trace-node");
|
|
|
168
74
|
var import_core = require("@opentelemetry/core");
|
|
169
75
|
|
|
170
76
|
// src/loggers/formatters/shared.ts
|
|
171
|
-
var
|
|
77
|
+
var import_semantic_conventions = require("@opentelemetry/semantic-conventions");
|
|
172
78
|
var import_fast_safe_stringify = __toESM(require("fast-safe-stringify"));
|
|
173
79
|
|
|
174
80
|
// src/loggers/formatters/style.ts
|
|
@@ -229,8 +135,8 @@ function formatTimestamp(time) {
|
|
|
229
135
|
return colors.dim(date.toISOString().slice(11, 23));
|
|
230
136
|
}
|
|
231
137
|
function formatService(resource) {
|
|
232
|
-
const name = resource.attributes[
|
|
233
|
-
const version = resource.attributes[
|
|
138
|
+
const name = resource.attributes[import_semantic_conventions.ATTR_SERVICE_NAME] ?? "unknown-service";
|
|
139
|
+
const version = resource.attributes[import_semantic_conventions.ATTR_SERVICE_VERSION] ?? "1.0.0";
|
|
234
140
|
return colors.gray(`[${name}@${version}]`);
|
|
235
141
|
}
|
|
236
142
|
function formatLevel(record) {
|
|
@@ -320,7 +226,7 @@ function isHistogramLike(val) {
|
|
|
320
226
|
}
|
|
321
227
|
|
|
322
228
|
// src/loggers/formatters/span.ts
|
|
323
|
-
var
|
|
229
|
+
var import_api = require("@opentelemetry/api");
|
|
324
230
|
var LABEL_WIDTH = 20;
|
|
325
231
|
var DESCRIPTION_MAX_WIDTH = 16;
|
|
326
232
|
var BAR_MIN_WIDTH = 1;
|
|
@@ -350,7 +256,7 @@ function formatSpans(spans) {
|
|
|
350
256
|
function formatSpan(span, opts) {
|
|
351
257
|
const label = formatLabel(span, opts.depth);
|
|
352
258
|
const bar = buildBar(span, opts?.offsetMs, opts?.totalDurationMs);
|
|
353
|
-
const barColor = span.status.code ===
|
|
259
|
+
const barColor = span.status.code === import_api.SpanStatusCode.OK ? colors.green : span.status.code === import_api.SpanStatusCode.ERROR ? colors.red : colors.gray;
|
|
354
260
|
const desc = formatDescription(span);
|
|
355
261
|
const status = formatStatus(span);
|
|
356
262
|
const duration = formatDuration(span, opts?.offsetMs);
|
|
@@ -505,7 +411,7 @@ var ConsoleLogPrettyExporter = class {
|
|
|
505
411
|
};
|
|
506
412
|
|
|
507
413
|
// src/loggers/console-span-pretty-exporter.ts
|
|
508
|
-
var
|
|
414
|
+
var import_api2 = require("@opentelemetry/api");
|
|
509
415
|
var import_core2 = require("@opentelemetry/core");
|
|
510
416
|
var ConsoleSpanPrettyExporter = class {
|
|
511
417
|
allowedStatuses;
|
|
@@ -513,15 +419,15 @@ var ConsoleSpanPrettyExporter = class {
|
|
|
513
419
|
const env = process.env.SPAN_LEVEL?.toUpperCase();
|
|
514
420
|
if (!env) {
|
|
515
421
|
this.allowedStatuses = /* @__PURE__ */ new Set([
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
422
|
+
import_api2.SpanStatusCode.UNSET,
|
|
423
|
+
import_api2.SpanStatusCode.OK,
|
|
424
|
+
import_api2.SpanStatusCode.ERROR
|
|
519
425
|
]);
|
|
520
426
|
} else {
|
|
521
427
|
const map = {
|
|
522
|
-
UNSET:
|
|
523
|
-
OK:
|
|
524
|
-
ERROR:
|
|
428
|
+
UNSET: import_api2.SpanStatusCode.UNSET,
|
|
429
|
+
OK: import_api2.SpanStatusCode.OK,
|
|
430
|
+
ERROR: import_api2.SpanStatusCode.ERROR
|
|
525
431
|
};
|
|
526
432
|
this.allowedStatuses = new Set(
|
|
527
433
|
env.split(",").map((s) => s.trim()).map((s) => map[s]).filter((v) => typeof v === "number")
|
|
@@ -679,6 +585,51 @@ var getMetricReader = (otlpEndpoint) => {
|
|
|
679
585
|
|
|
680
586
|
// src/resource.ts
|
|
681
587
|
var import_resources = require("@opentelemetry/resources");
|
|
588
|
+
|
|
589
|
+
// src/otel-context.ts
|
|
590
|
+
var import_semantic_conventions2 = require("@opentelemetry/semantic-conventions");
|
|
591
|
+
function detectTelemetryContext(componentNameOverride) {
|
|
592
|
+
const {
|
|
593
|
+
OTEL_SERVICE_NAME,
|
|
594
|
+
// e.g. "UserSystem"
|
|
595
|
+
OTEL_SERVICE_VERSION,
|
|
596
|
+
// e.g. "1.2.3"
|
|
597
|
+
K_SERVICE,
|
|
598
|
+
K_REVISION,
|
|
599
|
+
K_CONFIGURATION,
|
|
600
|
+
KUBERNETES_SERVICE_HOST,
|
|
601
|
+
POD_NAME,
|
|
602
|
+
POD_NAMESPACE,
|
|
603
|
+
GCP_PROJECT,
|
|
604
|
+
CLOUD_PROVIDER
|
|
605
|
+
} = process.env;
|
|
606
|
+
const systemName = OTEL_SERVICE_NAME || "unknown-service";
|
|
607
|
+
const systemVersion = OTEL_SERVICE_VERSION || "1.0.0";
|
|
608
|
+
const componentName = componentNameOverride || void 0;
|
|
609
|
+
const resourceAttributes = {
|
|
610
|
+
[import_semantic_conventions2.ATTR_SERVICE_NAME]: systemName,
|
|
611
|
+
[import_semantic_conventions2.ATTR_SERVICE_VERSION]: systemVersion,
|
|
612
|
+
"serviceContext.service": systemName,
|
|
613
|
+
"serviceContext.version": systemVersion,
|
|
614
|
+
...K_SERVICE && { "cloud.run.service": K_SERVICE },
|
|
615
|
+
...K_REVISION && { "cloud.run.revision": K_REVISION },
|
|
616
|
+
...K_CONFIGURATION && { "cloud.run.configuration": K_CONFIGURATION },
|
|
617
|
+
...POD_NAME && { "k8s.pod_name": POD_NAME },
|
|
618
|
+
...POD_NAMESPACE && { "k8s.namespace_name": POD_NAMESPACE },
|
|
619
|
+
...KUBERNETES_SERVICE_HOST && { "cloud.orchestrator": "kubernetes" },
|
|
620
|
+
...GCP_PROJECT && { "cloud.account.id": GCP_PROJECT },
|
|
621
|
+
...CLOUD_PROVIDER && { "cloud.provider": CLOUD_PROVIDER },
|
|
622
|
+
...componentName && { "component.name": componentName }
|
|
623
|
+
};
|
|
624
|
+
return {
|
|
625
|
+
systemName,
|
|
626
|
+
systemVersion,
|
|
627
|
+
componentName,
|
|
628
|
+
resourceAttributes
|
|
629
|
+
};
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
// src/resource.ts
|
|
682
633
|
var getResource = async () => {
|
|
683
634
|
const baseRes = await (0, import_resources.detectResources)();
|
|
684
635
|
const { resourceAttributes } = detectTelemetryContext();
|
|
@@ -691,21 +642,29 @@ var getResource = async () => {
|
|
|
691
642
|
};
|
|
692
643
|
|
|
693
644
|
// src/otel.ts
|
|
694
|
-
import_api4.diag.setLogger(new import_api4.DiagConsoleLogger(), import_api4.DiagLogLevel.ERROR);
|
|
695
645
|
var initialization;
|
|
696
646
|
async function initialize() {
|
|
697
647
|
if (!initialization) {
|
|
698
|
-
|
|
648
|
+
import_api3.diag.setLogger(new import_api3.DiagConsoleLogger(), import_api3.DiagLogLevel.ERROR);
|
|
649
|
+
initialization = initializeOtel();
|
|
699
650
|
}
|
|
700
651
|
return initialization;
|
|
701
652
|
}
|
|
702
|
-
|
|
653
|
+
function isInitialized() {
|
|
654
|
+
return initialization !== void 0;
|
|
655
|
+
}
|
|
656
|
+
async function initializeOtel() {
|
|
703
657
|
try {
|
|
704
658
|
const serviceName = process.env.OTEL_SERVICE_NAME ?? "unknown-service";
|
|
705
659
|
const otlpEndpoint = process.env.OTEL_EXPORTER_OTLP_ENDPOINT;
|
|
660
|
+
const isTestMode = process.env.NODE_ENV === "test" || process.env.VITEST === "true";
|
|
706
661
|
const resource = await getResource();
|
|
707
|
-
|
|
708
|
-
|
|
662
|
+
let logProvider;
|
|
663
|
+
const shouldSetupLogProvider = !isTestMode || !!process.env.LOG_LEVEL;
|
|
664
|
+
if (shouldSetupLogProvider) {
|
|
665
|
+
logProvider = getLogProvider(resource, otlpEndpoint);
|
|
666
|
+
import_api_logs.logs.setGlobalLoggerProvider(logProvider);
|
|
667
|
+
}
|
|
709
668
|
const spanProcessor = getSpanProcessor(otlpEndpoint);
|
|
710
669
|
const metricReader = getMetricReader(otlpEndpoint);
|
|
711
670
|
const sdk = new import_sdk_node.NodeSDK({
|
|
@@ -718,16 +677,78 @@ async function _initialize() {
|
|
|
718
677
|
console.log(`[otel] Telemetry initialized for "${serviceName}"`);
|
|
719
678
|
process.on("SIGTERM", async () => {
|
|
720
679
|
console.log("[otel] Shutting down...");
|
|
721
|
-
|
|
680
|
+
const shutdownPromises = [sdk.shutdown()];
|
|
681
|
+
if (logProvider) {
|
|
682
|
+
shutdownPromises.push(logProvider.shutdown());
|
|
683
|
+
}
|
|
684
|
+
await Promise.all(shutdownPromises);
|
|
722
685
|
console.log("[otel] Shutdown complete.");
|
|
723
686
|
process.exit(0);
|
|
724
687
|
});
|
|
725
688
|
} catch (err) {
|
|
726
|
-
|
|
689
|
+
if (err instanceof Error && err.message.includes("duplicate registration")) {
|
|
690
|
+
console.warn("[otel] Warning - API already registered, continuing...");
|
|
691
|
+
} else {
|
|
692
|
+
console.error("[otel] Startup error:", err);
|
|
693
|
+
}
|
|
727
694
|
}
|
|
728
695
|
}
|
|
729
696
|
|
|
697
|
+
// src/logger.ts
|
|
698
|
+
function getLogger(serviceOverride, extraAttrs = {}, testProvider) {
|
|
699
|
+
if (!isInitialized()) {
|
|
700
|
+
throw new Error(
|
|
701
|
+
"OpenTelemetry is not initialized. Please call initialize() before getting a logger."
|
|
702
|
+
);
|
|
703
|
+
}
|
|
704
|
+
const { systemName, systemVersion, resourceAttributes } = detectTelemetryContext(serviceOverride);
|
|
705
|
+
const defaultAttrs = {
|
|
706
|
+
...resourceAttributes,
|
|
707
|
+
...extraAttrs
|
|
708
|
+
};
|
|
709
|
+
function emit(severityText, body, attrs = {}) {
|
|
710
|
+
const logger = testProvider ? testProvider.getLogger(systemName, systemVersion) : import_api_logs2.logs.getLogger(systemName, systemVersion);
|
|
711
|
+
const span = import_api4.trace.getSpan(import_api4.context.active());
|
|
712
|
+
const spanContext = span?.spanContext();
|
|
713
|
+
logger.emit({
|
|
714
|
+
severityText,
|
|
715
|
+
severityNumber: LOG_SEVERITY_MAP[severityText],
|
|
716
|
+
body,
|
|
717
|
+
attributes: {
|
|
718
|
+
...defaultAttrs,
|
|
719
|
+
...spanContext && {
|
|
720
|
+
trace_id: spanContext.traceId,
|
|
721
|
+
span_id: spanContext.spanId
|
|
722
|
+
},
|
|
723
|
+
...attrs
|
|
724
|
+
}
|
|
725
|
+
});
|
|
726
|
+
}
|
|
727
|
+
return {
|
|
728
|
+
debug: (msg, attrs) => emit("DEBUG", msg, attrs),
|
|
729
|
+
info: (msg, attrs) => emit("INFO", msg, attrs),
|
|
730
|
+
notice: (msg, attrs) => emit("NOTICE", msg, attrs),
|
|
731
|
+
warn: (msg, attrs) => emit("WARNING", msg, attrs),
|
|
732
|
+
error: (msg, errOrAttrs, maybeAttrs = {}) => {
|
|
733
|
+
let body;
|
|
734
|
+
let attrs;
|
|
735
|
+
if (errOrAttrs instanceof Error) {
|
|
736
|
+
body = `${msg}: ${errOrAttrs.stack || errOrAttrs.message}`;
|
|
737
|
+
attrs = maybeAttrs;
|
|
738
|
+
} else {
|
|
739
|
+
body = msg instanceof Error ? msg.stack || msg.message : msg;
|
|
740
|
+
attrs = errOrAttrs || {};
|
|
741
|
+
}
|
|
742
|
+
emit("ERROR", body, attrs);
|
|
743
|
+
},
|
|
744
|
+
critical: (msg, attrs) => emit("CRITICAL", msg, attrs),
|
|
745
|
+
alert: (msg, attrs) => emit("ALERT", msg, attrs),
|
|
746
|
+
emergency: (msg, attrs) => emit("EMERGENCY", msg, attrs)
|
|
747
|
+
};
|
|
748
|
+
}
|
|
749
|
+
|
|
730
750
|
// src/metrics.ts
|
|
751
|
+
var import_api5 = require("@opentelemetry/api");
|
|
731
752
|
async function getMeter(componentNameOverride) {
|
|
732
753
|
await initialize();
|
|
733
754
|
const { componentName, systemName, systemVersion } = detectTelemetryContext(
|
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// src/logger.ts
|
|
2
2
|
import { context, trace } from "@opentelemetry/api";
|
|
3
|
-
import { logs } from "@opentelemetry/api-logs";
|
|
3
|
+
import { logs as logs2 } from "@opentelemetry/api-logs";
|
|
4
4
|
|
|
5
5
|
// src/consts.ts
|
|
6
6
|
var LOG_SEVERITY_MAP = {
|
|
@@ -17,106 +17,9 @@ var LOG_SEVERITY_MAP = {
|
|
|
17
17
|
EMERGENCY: 23
|
|
18
18
|
};
|
|
19
19
|
|
|
20
|
-
// src/otel-context.ts
|
|
21
|
-
import {
|
|
22
|
-
ATTR_SERVICE_NAME,
|
|
23
|
-
ATTR_SERVICE_VERSION
|
|
24
|
-
} from "@opentelemetry/semantic-conventions";
|
|
25
|
-
function detectTelemetryContext(componentNameOverride) {
|
|
26
|
-
const {
|
|
27
|
-
OTEL_SERVICE_NAME,
|
|
28
|
-
// e.g. "UserSystem"
|
|
29
|
-
OTEL_SERVICE_VERSION,
|
|
30
|
-
// e.g. "1.2.3"
|
|
31
|
-
K_SERVICE,
|
|
32
|
-
K_REVISION,
|
|
33
|
-
K_CONFIGURATION,
|
|
34
|
-
KUBERNETES_SERVICE_HOST,
|
|
35
|
-
POD_NAME,
|
|
36
|
-
POD_NAMESPACE,
|
|
37
|
-
GCP_PROJECT,
|
|
38
|
-
CLOUD_PROVIDER
|
|
39
|
-
} = process.env;
|
|
40
|
-
const systemName = OTEL_SERVICE_NAME || "unknown-service";
|
|
41
|
-
const systemVersion = OTEL_SERVICE_VERSION || "1.0.0";
|
|
42
|
-
const componentName = componentNameOverride || void 0;
|
|
43
|
-
const resourceAttributes = {
|
|
44
|
-
[ATTR_SERVICE_NAME]: systemName,
|
|
45
|
-
[ATTR_SERVICE_VERSION]: systemVersion,
|
|
46
|
-
"serviceContext.service": systemName,
|
|
47
|
-
"serviceContext.version": systemVersion,
|
|
48
|
-
...K_SERVICE && { "cloud.run.service": K_SERVICE },
|
|
49
|
-
...K_REVISION && { "cloud.run.revision": K_REVISION },
|
|
50
|
-
...K_CONFIGURATION && { "cloud.run.configuration": K_CONFIGURATION },
|
|
51
|
-
...POD_NAME && { "k8s.pod_name": POD_NAME },
|
|
52
|
-
...POD_NAMESPACE && { "k8s.namespace_name": POD_NAMESPACE },
|
|
53
|
-
...KUBERNETES_SERVICE_HOST && { "cloud.orchestrator": "kubernetes" },
|
|
54
|
-
...GCP_PROJECT && { "cloud.account.id": GCP_PROJECT },
|
|
55
|
-
...CLOUD_PROVIDER && { "cloud.provider": CLOUD_PROVIDER },
|
|
56
|
-
...componentName && { "component.name": componentName }
|
|
57
|
-
};
|
|
58
|
-
return {
|
|
59
|
-
systemName,
|
|
60
|
-
systemVersion,
|
|
61
|
-
componentName,
|
|
62
|
-
resourceAttributes
|
|
63
|
-
};
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
// src/logger.ts
|
|
67
|
-
function getLogger(serviceOverride, extraAttrs = {}) {
|
|
68
|
-
const { systemName, systemVersion, resourceAttributes } = detectTelemetryContext(serviceOverride);
|
|
69
|
-
const defaultAttrs = {
|
|
70
|
-
...resourceAttributes,
|
|
71
|
-
...extraAttrs
|
|
72
|
-
};
|
|
73
|
-
function emit(severityText, body, attrs = {}) {
|
|
74
|
-
const logger = logs.getLogger(systemName, systemVersion);
|
|
75
|
-
const span = trace.getSpan(context.active());
|
|
76
|
-
const spanContext = span?.spanContext();
|
|
77
|
-
logger.emit({
|
|
78
|
-
severityText,
|
|
79
|
-
severityNumber: LOG_SEVERITY_MAP[severityText],
|
|
80
|
-
body,
|
|
81
|
-
attributes: {
|
|
82
|
-
...defaultAttrs,
|
|
83
|
-
...spanContext && {
|
|
84
|
-
trace_id: spanContext.traceId,
|
|
85
|
-
span_id: spanContext.spanId
|
|
86
|
-
},
|
|
87
|
-
...attrs
|
|
88
|
-
}
|
|
89
|
-
});
|
|
90
|
-
}
|
|
91
|
-
return {
|
|
92
|
-
debug: (msg, attrs) => emit("DEBUG", msg, attrs),
|
|
93
|
-
info: (msg, attrs) => emit("INFO", msg, attrs),
|
|
94
|
-
notice: (msg, attrs) => emit("NOTICE", msg, attrs),
|
|
95
|
-
warn: (msg, attrs) => emit("WARNING", msg, attrs),
|
|
96
|
-
error: (msg, errOrAttrs, maybeAttrs = {}) => {
|
|
97
|
-
let body;
|
|
98
|
-
let attrs;
|
|
99
|
-
if (errOrAttrs instanceof Error) {
|
|
100
|
-
body = `${msg}: ${errOrAttrs.stack || errOrAttrs.message}`;
|
|
101
|
-
attrs = maybeAttrs;
|
|
102
|
-
} else {
|
|
103
|
-
body = msg instanceof Error ? msg.stack || msg.message : msg;
|
|
104
|
-
attrs = errOrAttrs || {};
|
|
105
|
-
}
|
|
106
|
-
emit("ERROR", body, attrs);
|
|
107
|
-
},
|
|
108
|
-
critical: (msg, attrs) => emit("CRITICAL", msg, attrs),
|
|
109
|
-
alert: (msg, attrs) => emit("ALERT", msg, attrs),
|
|
110
|
-
emergency: (msg, attrs) => emit("EMERGENCY", msg, attrs)
|
|
111
|
-
};
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
// src/metrics.ts
|
|
115
|
-
import { metrics } from "@opentelemetry/api";
|
|
116
|
-
|
|
117
20
|
// src/otel.ts
|
|
118
21
|
import { DiagConsoleLogger, DiagLogLevel, diag } from "@opentelemetry/api";
|
|
119
|
-
import { logs
|
|
22
|
+
import { logs } from "@opentelemetry/api-logs";
|
|
120
23
|
import { getNodeAutoInstrumentations } from "@opentelemetry/auto-instrumentations-node";
|
|
121
24
|
import { NodeSDK } from "@opentelemetry/sdk-node";
|
|
122
25
|
|
|
@@ -139,8 +42,8 @@ import { ExportResultCode } from "@opentelemetry/core";
|
|
|
139
42
|
|
|
140
43
|
// src/loggers/formatters/shared.ts
|
|
141
44
|
import {
|
|
142
|
-
ATTR_SERVICE_NAME
|
|
143
|
-
ATTR_SERVICE_VERSION
|
|
45
|
+
ATTR_SERVICE_NAME,
|
|
46
|
+
ATTR_SERVICE_VERSION
|
|
144
47
|
} from "@opentelemetry/semantic-conventions";
|
|
145
48
|
import stringify from "fast-safe-stringify";
|
|
146
49
|
|
|
@@ -202,8 +105,8 @@ function formatTimestamp(time) {
|
|
|
202
105
|
return colors.dim(date.toISOString().slice(11, 23));
|
|
203
106
|
}
|
|
204
107
|
function formatService(resource) {
|
|
205
|
-
const name = resource.attributes[
|
|
206
|
-
const version = resource.attributes[
|
|
108
|
+
const name = resource.attributes[ATTR_SERVICE_NAME] ?? "unknown-service";
|
|
109
|
+
const version = resource.attributes[ATTR_SERVICE_VERSION] ?? "1.0.0";
|
|
207
110
|
return colors.gray(`[${name}@${version}]`);
|
|
208
111
|
}
|
|
209
112
|
function formatLevel(record) {
|
|
@@ -655,6 +558,54 @@ import {
|
|
|
655
558
|
detectResources,
|
|
656
559
|
resourceFromAttributes
|
|
657
560
|
} from "@opentelemetry/resources";
|
|
561
|
+
|
|
562
|
+
// src/otel-context.ts
|
|
563
|
+
import {
|
|
564
|
+
ATTR_SERVICE_NAME as ATTR_SERVICE_NAME2,
|
|
565
|
+
ATTR_SERVICE_VERSION as ATTR_SERVICE_VERSION2
|
|
566
|
+
} from "@opentelemetry/semantic-conventions";
|
|
567
|
+
function detectTelemetryContext(componentNameOverride) {
|
|
568
|
+
const {
|
|
569
|
+
OTEL_SERVICE_NAME,
|
|
570
|
+
// e.g. "UserSystem"
|
|
571
|
+
OTEL_SERVICE_VERSION,
|
|
572
|
+
// e.g. "1.2.3"
|
|
573
|
+
K_SERVICE,
|
|
574
|
+
K_REVISION,
|
|
575
|
+
K_CONFIGURATION,
|
|
576
|
+
KUBERNETES_SERVICE_HOST,
|
|
577
|
+
POD_NAME,
|
|
578
|
+
POD_NAMESPACE,
|
|
579
|
+
GCP_PROJECT,
|
|
580
|
+
CLOUD_PROVIDER
|
|
581
|
+
} = process.env;
|
|
582
|
+
const systemName = OTEL_SERVICE_NAME || "unknown-service";
|
|
583
|
+
const systemVersion = OTEL_SERVICE_VERSION || "1.0.0";
|
|
584
|
+
const componentName = componentNameOverride || void 0;
|
|
585
|
+
const resourceAttributes = {
|
|
586
|
+
[ATTR_SERVICE_NAME2]: systemName,
|
|
587
|
+
[ATTR_SERVICE_VERSION2]: systemVersion,
|
|
588
|
+
"serviceContext.service": systemName,
|
|
589
|
+
"serviceContext.version": systemVersion,
|
|
590
|
+
...K_SERVICE && { "cloud.run.service": K_SERVICE },
|
|
591
|
+
...K_REVISION && { "cloud.run.revision": K_REVISION },
|
|
592
|
+
...K_CONFIGURATION && { "cloud.run.configuration": K_CONFIGURATION },
|
|
593
|
+
...POD_NAME && { "k8s.pod_name": POD_NAME },
|
|
594
|
+
...POD_NAMESPACE && { "k8s.namespace_name": POD_NAMESPACE },
|
|
595
|
+
...KUBERNETES_SERVICE_HOST && { "cloud.orchestrator": "kubernetes" },
|
|
596
|
+
...GCP_PROJECT && { "cloud.account.id": GCP_PROJECT },
|
|
597
|
+
...CLOUD_PROVIDER && { "cloud.provider": CLOUD_PROVIDER },
|
|
598
|
+
...componentName && { "component.name": componentName }
|
|
599
|
+
};
|
|
600
|
+
return {
|
|
601
|
+
systemName,
|
|
602
|
+
systemVersion,
|
|
603
|
+
componentName,
|
|
604
|
+
resourceAttributes
|
|
605
|
+
};
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
// src/resource.ts
|
|
658
609
|
var getResource = async () => {
|
|
659
610
|
const baseRes = await detectResources();
|
|
660
611
|
const { resourceAttributes } = detectTelemetryContext();
|
|
@@ -667,21 +618,29 @@ var getResource = async () => {
|
|
|
667
618
|
};
|
|
668
619
|
|
|
669
620
|
// src/otel.ts
|
|
670
|
-
diag.setLogger(new DiagConsoleLogger(), DiagLogLevel.ERROR);
|
|
671
621
|
var initialization;
|
|
672
622
|
async function initialize() {
|
|
673
623
|
if (!initialization) {
|
|
674
|
-
|
|
624
|
+
diag.setLogger(new DiagConsoleLogger(), DiagLogLevel.ERROR);
|
|
625
|
+
initialization = initializeOtel();
|
|
675
626
|
}
|
|
676
627
|
return initialization;
|
|
677
628
|
}
|
|
678
|
-
|
|
629
|
+
function isInitialized() {
|
|
630
|
+
return initialization !== void 0;
|
|
631
|
+
}
|
|
632
|
+
async function initializeOtel() {
|
|
679
633
|
try {
|
|
680
634
|
const serviceName = process.env.OTEL_SERVICE_NAME ?? "unknown-service";
|
|
681
635
|
const otlpEndpoint = process.env.OTEL_EXPORTER_OTLP_ENDPOINT;
|
|
636
|
+
const isTestMode = process.env.NODE_ENV === "test" || process.env.VITEST === "true";
|
|
682
637
|
const resource = await getResource();
|
|
683
|
-
|
|
684
|
-
|
|
638
|
+
let logProvider;
|
|
639
|
+
const shouldSetupLogProvider = !isTestMode || !!process.env.LOG_LEVEL;
|
|
640
|
+
if (shouldSetupLogProvider) {
|
|
641
|
+
logProvider = getLogProvider(resource, otlpEndpoint);
|
|
642
|
+
logs.setGlobalLoggerProvider(logProvider);
|
|
643
|
+
}
|
|
685
644
|
const spanProcessor = getSpanProcessor(otlpEndpoint);
|
|
686
645
|
const metricReader = getMetricReader(otlpEndpoint);
|
|
687
646
|
const sdk = new NodeSDK({
|
|
@@ -694,16 +653,78 @@ async function _initialize() {
|
|
|
694
653
|
console.log(`[otel] Telemetry initialized for "${serviceName}"`);
|
|
695
654
|
process.on("SIGTERM", async () => {
|
|
696
655
|
console.log("[otel] Shutting down...");
|
|
697
|
-
|
|
656
|
+
const shutdownPromises = [sdk.shutdown()];
|
|
657
|
+
if (logProvider) {
|
|
658
|
+
shutdownPromises.push(logProvider.shutdown());
|
|
659
|
+
}
|
|
660
|
+
await Promise.all(shutdownPromises);
|
|
698
661
|
console.log("[otel] Shutdown complete.");
|
|
699
662
|
process.exit(0);
|
|
700
663
|
});
|
|
701
664
|
} catch (err) {
|
|
702
|
-
|
|
665
|
+
if (err instanceof Error && err.message.includes("duplicate registration")) {
|
|
666
|
+
console.warn("[otel] Warning - API already registered, continuing...");
|
|
667
|
+
} else {
|
|
668
|
+
console.error("[otel] Startup error:", err);
|
|
669
|
+
}
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
// src/logger.ts
|
|
674
|
+
function getLogger(serviceOverride, extraAttrs = {}, testProvider) {
|
|
675
|
+
if (!isInitialized()) {
|
|
676
|
+
throw new Error(
|
|
677
|
+
"OpenTelemetry is not initialized. Please call initialize() before getting a logger."
|
|
678
|
+
);
|
|
679
|
+
}
|
|
680
|
+
const { systemName, systemVersion, resourceAttributes } = detectTelemetryContext(serviceOverride);
|
|
681
|
+
const defaultAttrs = {
|
|
682
|
+
...resourceAttributes,
|
|
683
|
+
...extraAttrs
|
|
684
|
+
};
|
|
685
|
+
function emit(severityText, body, attrs = {}) {
|
|
686
|
+
const logger = testProvider ? testProvider.getLogger(systemName, systemVersion) : logs2.getLogger(systemName, systemVersion);
|
|
687
|
+
const span = trace.getSpan(context.active());
|
|
688
|
+
const spanContext = span?.spanContext();
|
|
689
|
+
logger.emit({
|
|
690
|
+
severityText,
|
|
691
|
+
severityNumber: LOG_SEVERITY_MAP[severityText],
|
|
692
|
+
body,
|
|
693
|
+
attributes: {
|
|
694
|
+
...defaultAttrs,
|
|
695
|
+
...spanContext && {
|
|
696
|
+
trace_id: spanContext.traceId,
|
|
697
|
+
span_id: spanContext.spanId
|
|
698
|
+
},
|
|
699
|
+
...attrs
|
|
700
|
+
}
|
|
701
|
+
});
|
|
703
702
|
}
|
|
703
|
+
return {
|
|
704
|
+
debug: (msg, attrs) => emit("DEBUG", msg, attrs),
|
|
705
|
+
info: (msg, attrs) => emit("INFO", msg, attrs),
|
|
706
|
+
notice: (msg, attrs) => emit("NOTICE", msg, attrs),
|
|
707
|
+
warn: (msg, attrs) => emit("WARNING", msg, attrs),
|
|
708
|
+
error: (msg, errOrAttrs, maybeAttrs = {}) => {
|
|
709
|
+
let body;
|
|
710
|
+
let attrs;
|
|
711
|
+
if (errOrAttrs instanceof Error) {
|
|
712
|
+
body = `${msg}: ${errOrAttrs.stack || errOrAttrs.message}`;
|
|
713
|
+
attrs = maybeAttrs;
|
|
714
|
+
} else {
|
|
715
|
+
body = msg instanceof Error ? msg.stack || msg.message : msg;
|
|
716
|
+
attrs = errOrAttrs || {};
|
|
717
|
+
}
|
|
718
|
+
emit("ERROR", body, attrs);
|
|
719
|
+
},
|
|
720
|
+
critical: (msg, attrs) => emit("CRITICAL", msg, attrs),
|
|
721
|
+
alert: (msg, attrs) => emit("ALERT", msg, attrs),
|
|
722
|
+
emergency: (msg, attrs) => emit("EMERGENCY", msg, attrs)
|
|
723
|
+
};
|
|
704
724
|
}
|
|
705
725
|
|
|
706
726
|
// src/metrics.ts
|
|
727
|
+
import { metrics } from "@opentelemetry/api";
|
|
707
728
|
async function getMeter(componentNameOverride) {
|
|
708
729
|
await initialize();
|
|
709
730
|
const { componentName, systemName, systemVersion } = detectTelemetryContext(
|