@ogcio/o11y-sdk-node 0.1.0-beta.8 → 0.2.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/CHANGELOG.md +74 -0
- package/dist/lib/exporter/console.d.ts +1 -1
- package/dist/lib/exporter/console.js +5 -1
- package/dist/lib/exporter/grpc.d.ts +2 -2
- package/dist/lib/exporter/grpc.js +12 -1
- package/dist/lib/exporter/http.d.ts +1 -1
- package/dist/lib/exporter/http.js +2 -0
- package/dist/lib/index.d.ts +7 -0
- package/dist/lib/instrumentation.node.d.ts +1 -1
- package/dist/lib/instrumentation.node.js +35 -38
- package/dist/lib/processor/enrich-logger-processor.d.ts +10 -0
- package/dist/lib/processor/enrich-logger-processor.js +19 -0
- package/dist/lib/resource.d.ts +7 -0
- package/dist/lib/resource.js +18 -0
- package/dist/package.json +25 -20
- package/dist/vitest.config.js +2 -2
- package/lib/exporter/console.ts +6 -2
- package/lib/exporter/grpc.ts +17 -2
- package/lib/exporter/http.ts +3 -1
- package/lib/index.ts +9 -0
- package/lib/instrumentation.node.ts +47 -54
- package/lib/processor/enrich-logger-processor.ts +34 -0
- package/lib/resource.ts +30 -0
- package/package.json +25 -20
- package/test/index.test.ts +44 -12
- package/test/integration/README.md +1 -1
- package/test/node-config.test.ts +18 -25
- package/test/processor/enrich-logger-processor.test.ts +58 -0
- package/test/{enrich-span-processor.test.ts → processor/enrich-span-processor.test.ts} +1 -2
- package/test/resource.test.ts +33 -0
- package/test/validation.test.ts +22 -16
- package/vitest.config.ts +2 -2
- /package/dist/lib/{options.d.ts → exporter/index.d.ts} +0 -0
- /package/dist/lib/{options.js → exporter/index.js} +0 -0
- /package/lib/{options.ts → exporter/index.ts} +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,79 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.2.0](https://github.com/ogcio/o11y/compare/@ogcio/o11y-sdk-node@v0.1.0-beta.13...@ogcio/o11y-sdk-node@v0.2.0) (2025-06-24)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* late june deps update ([#154](https://github.com/ogcio/o11y/issues/154)) ([a772622](https://github.com/ogcio/o11y/commit/a7726225a59b2dbcd4326919323d935843b2f93f))
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Miscellaneous Chores
|
|
12
|
+
|
|
13
|
+
* **deps-dev:** bump @types/node to `24` AB[#29294](https://github.com/ogcio/o11y/issues/29294) ([3c74c28](https://github.com/ogcio/o11y/commit/3c74c28af41af8403220368ac72a90e40c3e15ae))
|
|
14
|
+
|
|
15
|
+
## [0.1.0-beta.13](https://github.com/ogcio/o11y/compare/@ogcio/o11y-sdk-node@v0.1.0-beta.12...@ogcio/o11y-sdk-node@v0.1.0-beta.13) (2025-06-16)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
### Bug Fixes
|
|
19
|
+
|
|
20
|
+
* **sdk-node:** allow graceful shutdown of instrumentation on SIGTERM AB[#28329](https://github.com/ogcio/o11y/issues/28329) ([#151](https://github.com/ogcio/o11y/issues/151)) ([991ee15](https://github.com/ogcio/o11y/commit/991ee1559898b721823cb9d1e0490e2ad82e6d0a))
|
|
21
|
+
|
|
22
|
+
## [0.1.0-beta.12](https://github.com/ogcio/o11y/compare/@ogcio/o11y-sdk-node@v0.1.0-beta.11...@ogcio/o11y-sdk-node@v0.1.0-beta.12) (2025-06-04)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
### Features
|
|
26
|
+
|
|
27
|
+
* add custom log processor for span enrich ([#102](https://github.com/ogcio/o11y/issues/102)) ([bbf8334](https://github.com/ogcio/o11y/commit/bbf83340940ed651dff63bbe7aaa52881d1e8c8c))
|
|
28
|
+
* add opentelemetry sampler ([#66](https://github.com/ogcio/o11y/issues/66)) ([48a1761](https://github.com/ogcio/o11y/commit/48a1761d68fbccf7b63e4232a62376caecf01fbc))
|
|
29
|
+
* april depedency upgrade AB[#27200](https://github.com/ogcio/o11y/issues/27200) ([#116](https://github.com/ogcio/o11y/issues/116)) ([d792fe5](https://github.com/ogcio/o11y/commit/d792fe5a783b0b495912b5bef2babfe11ef5e01d))
|
|
30
|
+
* june deps update ([#147](https://github.com/ogcio/o11y/issues/147)) ([b365a40](https://github.com/ogcio/o11y/commit/b365a4099cdfd8533ffa4948620d29f0044bbd70))
|
|
31
|
+
* may deps update ([#136](https://github.com/ogcio/o11y/issues/136)) ([3edd8b1](https://github.com/ogcio/o11y/commit/3edd8b1d823740d555fc4d93be427e9dc1438a95))
|
|
32
|
+
* o11y sdk repo setup ([#15](https://github.com/ogcio/o11y/issues/15)) ([c5816ba](https://github.com/ogcio/o11y/commit/c5816baff1454353f12539949959e84964ed6401))
|
|
33
|
+
* o11y showcase AB[#25895](https://github.com/ogcio/o11y/issues/25895) ([#84](https://github.com/ogcio/o11y/issues/84)) ([f8f10af](https://github.com/ogcio/o11y/commit/f8f10af97d9f5c188e3e65f7d62d5c673edce25a))
|
|
34
|
+
* remove pnpm test on prepublishOnly script ([#68](https://github.com/ogcio/o11y/issues/68)) ([41f6f57](https://github.com/ogcio/o11y/commit/41f6f57fa415c4f7adc29f49f983539274ef7320))
|
|
35
|
+
* **sdk-node:** add span customization AB[#25358](https://github.com/ogcio/o11y/issues/25358) ([46ba97b](https://github.com/ogcio/o11y/commit/46ba97bac4004ff326a954592f45213ce0e4d683))
|
|
36
|
+
* **sdk-node:** custom metrics ([#53](https://github.com/ogcio/o11y/issues/53)) ([3cb40b1](https://github.com/ogcio/o11y/commit/3cb40b1add3d80615c8d123d233724094559c7ff))
|
|
37
|
+
* **sdk-node:** renaming MetricsParams interface properties AB[#26188](https://github.com/ogcio/o11y/issues/26188) ([#96](https://github.com/ogcio/o11y/issues/96)) ([244aee0](https://github.com/ogcio/o11y/commit/244aee01ae6e7f319ae7f9fdeff27eb40ee3c863))
|
|
38
|
+
* upgrade to opentelemetry 2 AB[#25863](https://github.com/ogcio/o11y/issues/25863) ([#106](https://github.com/ogcio/o11y/issues/106)) ([3ff0314](https://github.com/ogcio/o11y/commit/3ff0314fef9f4d7b5db76da3b94e9035801384c7))
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
### Bug Fixes
|
|
42
|
+
|
|
43
|
+
* add readme file inside submodule ([#27](https://github.com/ogcio/o11y/issues/27)) ([dc518d5](https://github.com/ogcio/o11y/commit/dc518d5dde573368443bc0f8619e80e331880c78))
|
|
44
|
+
* default attributes in resource ([#112](https://github.com/ogcio/o11y/issues/112)) ([f0f0b9d](https://github.com/ogcio/o11y/commit/f0f0b9d555ef321d31f7171e25dc4b8a5b044522))
|
|
45
|
+
* improve getMetric attributes types ([#76](https://github.com/ogcio/o11y/issues/76)) ([243649c](https://github.com/ogcio/o11y/commit/243649c4bfe750687a729fbd836772cce16e0cb1))
|
|
46
|
+
* prepublishOnly hook ([#60](https://github.com/ogcio/o11y/issues/60)) ([9fbd3ad](https://github.com/ogcio/o11y/commit/9fbd3ad0b45a1604cf2eccc26b2f8855640417a1))
|
|
47
|
+
* **sdk-node:** add waitForReady for grpc-client to handle transient init connection errors AB[#28329](https://github.com/ogcio/o11y/issues/28329) ([#144](https://github.com/ogcio/o11y/issues/144)) ([6f260da](https://github.com/ogcio/o11y/commit/6f260da15fcbcd2c629ec6d4bb9fb3592803f399))
|
|
48
|
+
* **sdk-node:** update sdk init examples AB[#28329](https://github.com/ogcio/o11y/issues/28329) ([#146](https://github.com/ogcio/o11y/issues/146)) ([81de295](https://github.com/ogcio/o11y/commit/81de2957a7bef7430a46c6677f3c876255ef7c88))
|
|
49
|
+
|
|
50
|
+
## [0.1.0-beta.11](https://github.com/ogcio/o11y/compare/@ogcio/o11y-sdk-node@v0.1.0-beta.10...@ogcio/o11y-sdk-node@v0.1.0-beta.11) (2025-05-21)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
### Features
|
|
54
|
+
|
|
55
|
+
* may deps update ([#136](https://github.com/ogcio/o11y/issues/136)) ([3edd8b1](https://github.com/ogcio/o11y/commit/3edd8b1d823740d555fc4d93be427e9dc1438a95))
|
|
56
|
+
|
|
57
|
+
## [0.1.0-beta.10](https://github.com/ogcio/o11y/compare/@ogcio/o11y-sdk-node@v0.1.0-beta.9...@ogcio/o11y-sdk-node@v0.1.0-beta.10) (2025-04-09)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
### Features
|
|
61
|
+
|
|
62
|
+
* april depedency upgrade AB[#27200](https://github.com/ogcio/o11y/issues/27200) ([#116](https://github.com/ogcio/o11y/issues/116)) ([d792fe5](https://github.com/ogcio/o11y/commit/d792fe5a783b0b495912b5bef2babfe11ef5e01d))
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
### Bug Fixes
|
|
66
|
+
|
|
67
|
+
* default attributes in resource ([#112](https://github.com/ogcio/o11y/issues/112)) ([f0f0b9d](https://github.com/ogcio/o11y/commit/f0f0b9d555ef321d31f7171e25dc4b8a5b044522))
|
|
68
|
+
|
|
69
|
+
## [0.1.0-beta.9](https://github.com/ogcio/o11y/compare/@ogcio/o11y-sdk-node@v0.1.0-beta.8...@ogcio/o11y-sdk-node@v0.1.0-beta.9) (2025-03-24)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
### Features
|
|
73
|
+
|
|
74
|
+
* add custom log processor for span enrich ([#102](https://github.com/ogcio/o11y/issues/102)) ([bbf8334](https://github.com/ogcio/o11y/commit/bbf83340940ed651dff63bbe7aaa52881d1e8c8c))
|
|
75
|
+
* upgrade to opentelemetry 2 AB[#25863](https://github.com/ogcio/o11y/issues/25863) ([#106](https://github.com/ogcio/o11y/issues/106)) ([3ff0314](https://github.com/ogcio/o11y/commit/3ff0314fef9f4d7b5db76da3b94e9035801384c7))
|
|
76
|
+
|
|
3
77
|
## [0.1.0-beta.8](https://github.com/ogcio/o11y/compare/@ogcio/o11y-sdk-node@v0.1.0-beta.7...@ogcio/o11y-sdk-node@v0.1.0-beta.8) (2025-03-07)
|
|
4
78
|
|
|
5
79
|
|
|
@@ -2,6 +2,7 @@ import { ConsoleLogRecordExporter, SimpleLogRecordProcessor, } from "@openteleme
|
|
|
2
2
|
import { metrics } from "@opentelemetry/sdk-node";
|
|
3
3
|
import { ConsoleSpanExporter, SimpleSpanProcessor, } from "@opentelemetry/sdk-trace-base";
|
|
4
4
|
import { EnrichSpanProcessor } from "../processor/enrich-span-processor.js";
|
|
5
|
+
import { EnrichLogProcessor } from "../processor/enrich-logger-processor.js";
|
|
5
6
|
export default function buildConsoleExporters(config) {
|
|
6
7
|
return {
|
|
7
8
|
spans: [
|
|
@@ -11,6 +12,9 @@ export default function buildConsoleExporters(config) {
|
|
|
11
12
|
metrics: new metrics.PeriodicExportingMetricReader({
|
|
12
13
|
exporter: new metrics.ConsoleMetricExporter(),
|
|
13
14
|
}),
|
|
14
|
-
logs: [
|
|
15
|
+
logs: [
|
|
16
|
+
new EnrichLogProcessor(config.spanAttributes),
|
|
17
|
+
new SimpleLogRecordProcessor(new ConsoleLogRecordExporter()),
|
|
18
|
+
],
|
|
15
19
|
};
|
|
16
20
|
}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { NodeSDKConfig } from "../index.js";
|
|
2
|
-
import { Exporters } from "
|
|
3
|
-
export default function buildGrpcExporters(config: NodeSDKConfig): Exporters
|
|
2
|
+
import { Exporters } from "./index.js";
|
|
3
|
+
export default function buildGrpcExporters(config: NodeSDKConfig): Promise<Exporters>;
|
|
@@ -5,12 +5,20 @@ import { OTLPLogExporter } from "@opentelemetry/exporter-logs-otlp-grpc";
|
|
|
5
5
|
import { OTLPMetricExporter } from "@opentelemetry/exporter-metrics-otlp-grpc";
|
|
6
6
|
import { LogRecordProcessorMap, SpanProcessorMap } from "../utils.js";
|
|
7
7
|
import { EnrichSpanProcessor } from "../processor/enrich-span-processor.js";
|
|
8
|
-
|
|
8
|
+
import { EnrichLogProcessor } from "../processor/enrich-logger-processor.js";
|
|
9
|
+
async function defaultMetadata() {
|
|
10
|
+
const { Metadata } = await import("@grpc/grpc-js");
|
|
11
|
+
return new Metadata({
|
|
12
|
+
waitForReady: true,
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
export default async function buildGrpcExporters(config) {
|
|
9
16
|
return {
|
|
10
17
|
spans: [
|
|
11
18
|
new SpanProcessorMap[config.collectorMode ?? "batch"](new OTLPTraceExporter({
|
|
12
19
|
url: `${config.collectorUrl}`,
|
|
13
20
|
compression: CompressionAlgorithm.GZIP,
|
|
21
|
+
metadata: config.grpcMetadata ?? (await defaultMetadata()),
|
|
14
22
|
})),
|
|
15
23
|
new EnrichSpanProcessor(config.spanAttributes),
|
|
16
24
|
],
|
|
@@ -18,12 +26,15 @@ export default function buildGrpcExporters(config) {
|
|
|
18
26
|
exporter: new OTLPMetricExporter({
|
|
19
27
|
url: `${config.collectorUrl}`,
|
|
20
28
|
compression: CompressionAlgorithm.GZIP,
|
|
29
|
+
metadata: config.grpcMetadata ?? (await defaultMetadata()),
|
|
21
30
|
}),
|
|
22
31
|
}),
|
|
23
32
|
logs: [
|
|
33
|
+
new EnrichLogProcessor(config.spanAttributes),
|
|
24
34
|
new LogRecordProcessorMap[config.collectorMode ?? "batch"](new OTLPLogExporter({
|
|
25
35
|
url: `${config.collectorUrl}`,
|
|
26
36
|
compression: CompressionAlgorithm.GZIP,
|
|
37
|
+
metadata: config.grpcMetadata ?? (await defaultMetadata()),
|
|
27
38
|
})),
|
|
28
39
|
],
|
|
29
40
|
};
|
|
@@ -5,6 +5,7 @@ import { OTLPLogExporter } from "@opentelemetry/exporter-logs-otlp-http";
|
|
|
5
5
|
import { OTLPMetricExporter } from "@opentelemetry/exporter-metrics-otlp-http";
|
|
6
6
|
import { LogRecordProcessorMap, SpanProcessorMap } from "../utils.js";
|
|
7
7
|
import { EnrichSpanProcessor } from "../processor/enrich-span-processor.js";
|
|
8
|
+
import { EnrichLogProcessor } from "../processor/enrich-logger-processor.js";
|
|
8
9
|
export default function buildHttpExporters(config) {
|
|
9
10
|
if (config.collectorUrl.endsWith("/")) {
|
|
10
11
|
config.collectorUrl = config.collectorUrl.slice(0, -1);
|
|
@@ -24,6 +25,7 @@ export default function buildHttpExporters(config) {
|
|
|
24
25
|
}),
|
|
25
26
|
}),
|
|
26
27
|
logs: [
|
|
28
|
+
new EnrichLogProcessor(config.spanAttributes),
|
|
27
29
|
new LogRecordProcessorMap[config.collectorMode ?? "batch"](new OTLPLogExporter({
|
|
28
30
|
url: `${config.collectorUrl}/v1/logs`,
|
|
29
31
|
compression: CompressionAlgorithm.GZIP,
|
package/dist/lib/index.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { Metadata } from "@grpc/grpc-js";
|
|
1
2
|
export interface NodeSDKConfig {
|
|
2
3
|
/**
|
|
3
4
|
* The opentelemetry collector entrypoint GRPC url.
|
|
@@ -58,6 +59,12 @@ export interface NodeSDKConfig {
|
|
|
58
59
|
* @default grpc
|
|
59
60
|
*/
|
|
60
61
|
protocol?: SDKProtocol;
|
|
62
|
+
/**
|
|
63
|
+
* Grpc Metadata for the grpc-js client.
|
|
64
|
+
*
|
|
65
|
+
* @default { waitForReady: true }
|
|
66
|
+
*/
|
|
67
|
+
grpcMetadata?: Metadata;
|
|
61
68
|
}
|
|
62
69
|
export interface SamplerCondition {
|
|
63
70
|
type: "endsWith" | "includes" | "equals";
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { NodeSDK } from "@opentelemetry/sdk-node";
|
|
2
2
|
import type { NodeSDKConfig } from "./index.js";
|
|
3
|
-
export default function buildNodeInstrumentation(config?: NodeSDKConfig): NodeSDK | undefined
|
|
3
|
+
export default function buildNodeInstrumentation(config?: NodeSDKConfig): Promise<NodeSDK | undefined>;
|
|
@@ -1,14 +1,15 @@
|
|
|
1
|
-
import
|
|
1
|
+
import process from "process";
|
|
2
|
+
import { diag, DiagConsoleLogger, DiagLogLevel } from "@opentelemetry/api";
|
|
2
3
|
import { getNodeAutoInstrumentations } from "@opentelemetry/auto-instrumentations-node";
|
|
3
4
|
import { W3CTraceContextPropagator } from "@opentelemetry/core";
|
|
4
|
-
import { NodeSDK
|
|
5
|
+
import { NodeSDK } from "@opentelemetry/sdk-node";
|
|
5
6
|
import { AlwaysOffSampler, ParentBasedSampler, TraceIdRatioBasedSampler, } from "@opentelemetry/sdk-trace-base";
|
|
6
|
-
import packageJson from "../package.json" with { type: "json" };
|
|
7
7
|
import buildConsoleExporters from "./exporter/console.js";
|
|
8
8
|
import buildGrpcExporters from "./exporter/grpc.js";
|
|
9
9
|
import buildHttpExporters from "./exporter/http.js";
|
|
10
|
+
import { ObservabilityResourceDetector } from "./resource.js";
|
|
10
11
|
import { UrlSampler } from "./url-sampler.js";
|
|
11
|
-
export default function buildNodeInstrumentation(config) {
|
|
12
|
+
export default async function buildNodeInstrumentation(config) {
|
|
12
13
|
if (!config) {
|
|
13
14
|
console.warn("observability config not set. Skipping NodeJS OpenTelemetry instrumentation.");
|
|
14
15
|
return;
|
|
@@ -21,16 +22,6 @@ export default function buildNodeInstrumentation(config) {
|
|
|
21
22
|
console.error("collectorUrl does not use a valid format. Skipping NodeJS OpenTelemetry instrumentation.");
|
|
22
23
|
return;
|
|
23
24
|
}
|
|
24
|
-
let exporter;
|
|
25
|
-
if (config.protocol === "http") {
|
|
26
|
-
exporter = buildHttpExporters(config);
|
|
27
|
-
}
|
|
28
|
-
else if (config.protocol === "console") {
|
|
29
|
-
exporter = buildConsoleExporters(config);
|
|
30
|
-
}
|
|
31
|
-
else {
|
|
32
|
-
exporter = buildGrpcExporters(config);
|
|
33
|
-
}
|
|
34
25
|
const urlSampler = new UrlSampler(config.ignoreUrls, new TraceIdRatioBasedSampler(config.traceRatio ?? 1));
|
|
35
26
|
const mainSampler = new ParentBasedSampler({
|
|
36
27
|
root: urlSampler,
|
|
@@ -39,41 +30,47 @@ export default function buildNodeInstrumentation(config) {
|
|
|
39
30
|
localParentSampled: urlSampler,
|
|
40
31
|
localParentNotSampled: new AlwaysOffSampler(),
|
|
41
32
|
});
|
|
33
|
+
diag.setLogger(new DiagConsoleLogger(), config.diagLogLevel ? DiagLogLevel[config.diagLogLevel] : DiagLogLevel.INFO);
|
|
42
34
|
try {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
35
|
+
const nodeSdkInstrumentation = getNodeAutoInstrumentations({
|
|
36
|
+
"@opentelemetry/instrumentation-fs": {
|
|
37
|
+
enabled: config.enableFS ?? false,
|
|
38
|
+
},
|
|
39
|
+
});
|
|
40
|
+
let exporter;
|
|
41
|
+
if (config.protocol === "http") {
|
|
42
|
+
exporter = buildHttpExporters(config);
|
|
43
|
+
}
|
|
44
|
+
else if (config.protocol === "console") {
|
|
45
|
+
exporter = buildConsoleExporters(config);
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
exporter = await buildGrpcExporters(config);
|
|
49
|
+
}
|
|
46
50
|
const sdk = new NodeSDK({
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
...config.resourceAttributes,
|
|
51
|
-
}),
|
|
51
|
+
resourceDetectors: [
|
|
52
|
+
new ObservabilityResourceDetector(config.resourceAttributes),
|
|
53
|
+
],
|
|
52
54
|
spanProcessors: exporter.spans,
|
|
53
55
|
serviceName: config.serviceName,
|
|
54
56
|
metricReader: exporter.metrics,
|
|
55
57
|
logRecordProcessors: exporter.logs,
|
|
56
58
|
sampler: mainSampler,
|
|
57
59
|
textMapPropagator: new W3CTraceContextPropagator(),
|
|
58
|
-
instrumentations: [
|
|
59
|
-
getNodeAutoInstrumentations({
|
|
60
|
-
"@opentelemetry/instrumentation-fs": {
|
|
61
|
-
enabled: config.enableFS ?? false,
|
|
62
|
-
},
|
|
63
|
-
"@opentelemetry/instrumentation-pino": {
|
|
64
|
-
logHook: (_span, record, _level) => {
|
|
65
|
-
if (config.spanAttributes != undefined) {
|
|
66
|
-
for (const [key, value] of Object.entries(config.spanAttributes)) {
|
|
67
|
-
record[key] = typeof value === "function" ? value() : value;
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
},
|
|
71
|
-
},
|
|
72
|
-
}),
|
|
73
|
-
],
|
|
60
|
+
instrumentations: [nodeSdkInstrumentation],
|
|
74
61
|
});
|
|
75
62
|
sdk.start();
|
|
76
63
|
console.log("NodeJS OpenTelemetry instrumentation started successfully.");
|
|
64
|
+
process.on("SIGTERM", async () => {
|
|
65
|
+
try {
|
|
66
|
+
// Flushing before shutdown is implemented on a per-exporter basis.
|
|
67
|
+
await sdk.shutdown();
|
|
68
|
+
console.log("NodeJS OpenTelemetry instrumentation shutdown successfully");
|
|
69
|
+
}
|
|
70
|
+
catch (error) {
|
|
71
|
+
console.error("Error shutting down NodeJS OpenTelemetry instrumentation:", error);
|
|
72
|
+
}
|
|
73
|
+
});
|
|
77
74
|
return sdk;
|
|
78
75
|
}
|
|
79
76
|
catch (error) {
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { LogRecord, LogRecordProcessor } from "@opentelemetry/sdk-logs";
|
|
2
|
+
import { Context } from "@opentelemetry/api";
|
|
3
|
+
import { SignalAttributeValue } from "../index.js";
|
|
4
|
+
export declare class EnrichLogProcessor implements LogRecordProcessor {
|
|
5
|
+
private _spanAttributes?;
|
|
6
|
+
constructor(spanAttributes?: Record<string, SignalAttributeValue | (() => SignalAttributeValue)>);
|
|
7
|
+
forceFlush(): Promise<void>;
|
|
8
|
+
onEmit(logRecord: LogRecord, _context?: Context): void;
|
|
9
|
+
shutdown(): Promise<void>;
|
|
10
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export class EnrichLogProcessor {
|
|
2
|
+
_spanAttributes = undefined;
|
|
3
|
+
constructor(spanAttributes) {
|
|
4
|
+
this._spanAttributes = spanAttributes;
|
|
5
|
+
}
|
|
6
|
+
forceFlush() {
|
|
7
|
+
return Promise.resolve();
|
|
8
|
+
}
|
|
9
|
+
onEmit(logRecord, _context) {
|
|
10
|
+
if (this._spanAttributes) {
|
|
11
|
+
for (const [key, value] of Object.entries(this._spanAttributes)) {
|
|
12
|
+
logRecord.setAttribute(key, typeof value === "function" ? value() : value);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
shutdown() {
|
|
17
|
+
return Promise.resolve();
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { ResourceDetector, DetectedResource } from "@opentelemetry/resources";
|
|
2
|
+
import { SignalAttributeValue } from "./index.js";
|
|
3
|
+
export declare class ObservabilityResourceDetector implements ResourceDetector {
|
|
4
|
+
private _resourceAttributes;
|
|
5
|
+
constructor(resourceAttributes?: Record<string, SignalAttributeValue>);
|
|
6
|
+
detect(): DetectedResource;
|
|
7
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import packageJson from "../package.json" with { type: "json" };
|
|
2
|
+
export class ObservabilityResourceDetector {
|
|
3
|
+
_resourceAttributes;
|
|
4
|
+
constructor(resourceAttributes) {
|
|
5
|
+
this._resourceAttributes = resourceAttributes;
|
|
6
|
+
}
|
|
7
|
+
detect() {
|
|
8
|
+
let attributes = {};
|
|
9
|
+
if (this._resourceAttributes) {
|
|
10
|
+
attributes = {
|
|
11
|
+
...this._resourceAttributes,
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
attributes["o11y.sdk.name"] = packageJson.name;
|
|
15
|
+
attributes["o11y.sdk.version"] = packageJson.version;
|
|
16
|
+
return { attributes };
|
|
17
|
+
}
|
|
18
|
+
}
|
package/dist/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ogcio/o11y-sdk-node",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Opentelemetry standard instrumentation SDK for NodeJS based project",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -27,27 +27,32 @@
|
|
|
27
27
|
"author": "team:ogcio/observability",
|
|
28
28
|
"license": "ISC",
|
|
29
29
|
"dependencies": {
|
|
30
|
+
"@grpc/grpc-js": "^1.13.4",
|
|
30
31
|
"@opentelemetry/api": "^1.9.0",
|
|
31
|
-
"@opentelemetry/auto-instrumentations-node": "^0.
|
|
32
|
-
"@opentelemetry/core": "
|
|
33
|
-
"@opentelemetry/exporter-logs-otlp-grpc": "^0.
|
|
34
|
-
"@opentelemetry/exporter-logs-otlp-http": "^0.
|
|
35
|
-
"@opentelemetry/exporter-metrics-otlp-grpc": "^0.
|
|
36
|
-
"@opentelemetry/exporter-metrics-otlp-http": "^0.
|
|
37
|
-
"@opentelemetry/exporter-trace-otlp-grpc": "^0.
|
|
38
|
-
"@opentelemetry/exporter-trace-otlp-http": "^0.
|
|
39
|
-
"@opentelemetry/instrumentation": "^0.
|
|
40
|
-
"@opentelemetry/otlp-exporter-base": "^0.
|
|
41
|
-
"@opentelemetry/
|
|
42
|
-
"@opentelemetry/sdk-
|
|
43
|
-
"@opentelemetry/sdk-
|
|
44
|
-
"@opentelemetry/sdk-
|
|
32
|
+
"@opentelemetry/auto-instrumentations-node": "^0.60.1",
|
|
33
|
+
"@opentelemetry/core": "^2.0.1",
|
|
34
|
+
"@opentelemetry/exporter-logs-otlp-grpc": "^0.202.0",
|
|
35
|
+
"@opentelemetry/exporter-logs-otlp-http": "^0.202.0",
|
|
36
|
+
"@opentelemetry/exporter-metrics-otlp-grpc": "^0.202.0",
|
|
37
|
+
"@opentelemetry/exporter-metrics-otlp-http": "^0.202.0",
|
|
38
|
+
"@opentelemetry/exporter-trace-otlp-grpc": "^0.202.0",
|
|
39
|
+
"@opentelemetry/exporter-trace-otlp-http": "^0.202.0",
|
|
40
|
+
"@opentelemetry/instrumentation": "^0.202.0",
|
|
41
|
+
"@opentelemetry/otlp-exporter-base": "^0.202.0",
|
|
42
|
+
"@opentelemetry/resources": "^2.0.1",
|
|
43
|
+
"@opentelemetry/sdk-logs": "^0.202.0",
|
|
44
|
+
"@opentelemetry/sdk-metrics": "^2.0.1",
|
|
45
|
+
"@opentelemetry/sdk-node": "^0.202.0",
|
|
46
|
+
"@opentelemetry/sdk-trace-base": "^2.0.1"
|
|
45
47
|
},
|
|
46
48
|
"devDependencies": {
|
|
47
|
-
"@types/node": "^
|
|
48
|
-
"@vitest/coverage-v8": "^3.
|
|
49
|
-
"tsx": "^4.
|
|
50
|
-
"typescript": "^5.8.
|
|
51
|
-
"vitest": "^3.
|
|
49
|
+
"@types/node": "^24.0.3",
|
|
50
|
+
"@vitest/coverage-v8": "^3.2.4",
|
|
51
|
+
"tsx": "^4.20.3",
|
|
52
|
+
"typescript": "^5.8.3",
|
|
53
|
+
"vitest": "^3.2.4"
|
|
54
|
+
},
|
|
55
|
+
"engines": {
|
|
56
|
+
"node": ">=20.6.0"
|
|
52
57
|
}
|
|
53
58
|
}
|
package/dist/vitest.config.js
CHANGED
|
@@ -21,10 +21,10 @@ export default defineConfig({
|
|
|
21
21
|
reporters: ["default", ["junit", { outputFile: "test-report.xml" }]],
|
|
22
22
|
environment: "node",
|
|
23
23
|
pool: "threads",
|
|
24
|
-
|
|
24
|
+
projects: [
|
|
25
25
|
{
|
|
26
26
|
test: {
|
|
27
|
-
include: ["**/test/*.test.ts"],
|
|
27
|
+
include: ["**/test/*.test.ts", "**/test/processor/*.test.ts"],
|
|
28
28
|
name: "unit",
|
|
29
29
|
},
|
|
30
30
|
},
|
package/lib/exporter/console.ts
CHANGED
|
@@ -8,8 +8,9 @@ import {
|
|
|
8
8
|
SimpleSpanProcessor,
|
|
9
9
|
} from "@opentelemetry/sdk-trace-base";
|
|
10
10
|
import { NodeSDKConfig } from "../index.js";
|
|
11
|
-
import { Exporters } from "
|
|
11
|
+
import { Exporters } from "./index.js";
|
|
12
12
|
import { EnrichSpanProcessor } from "../processor/enrich-span-processor.js";
|
|
13
|
+
import { EnrichLogProcessor } from "../processor/enrich-logger-processor.js";
|
|
13
14
|
|
|
14
15
|
export default function buildConsoleExporters(
|
|
15
16
|
config: NodeSDKConfig,
|
|
@@ -22,6 +23,9 @@ export default function buildConsoleExporters(
|
|
|
22
23
|
metrics: new metrics.PeriodicExportingMetricReader({
|
|
23
24
|
exporter: new metrics.ConsoleMetricExporter(),
|
|
24
25
|
}),
|
|
25
|
-
logs: [
|
|
26
|
+
logs: [
|
|
27
|
+
new EnrichLogProcessor(config.spanAttributes),
|
|
28
|
+
new SimpleLogRecordProcessor(new ConsoleLogRecordExporter()),
|
|
29
|
+
],
|
|
26
30
|
};
|
|
27
31
|
}
|
package/lib/exporter/grpc.ts
CHANGED
|
@@ -4,17 +4,29 @@ import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-grpc";
|
|
|
4
4
|
import { OTLPLogExporter } from "@opentelemetry/exporter-logs-otlp-grpc";
|
|
5
5
|
import { OTLPMetricExporter } from "@opentelemetry/exporter-metrics-otlp-grpc";
|
|
6
6
|
import { NodeSDKConfig } from "../index.js";
|
|
7
|
-
import { Exporters } from "
|
|
7
|
+
import { Exporters } from "./index.js";
|
|
8
8
|
import { LogRecordProcessorMap, SpanProcessorMap } from "../utils.js";
|
|
9
9
|
import { EnrichSpanProcessor } from "../processor/enrich-span-processor.js";
|
|
10
|
+
import { EnrichLogProcessor } from "../processor/enrich-logger-processor.js";
|
|
10
11
|
|
|
11
|
-
|
|
12
|
+
async function defaultMetadata() {
|
|
13
|
+
const { Metadata } = await import("@grpc/grpc-js");
|
|
14
|
+
|
|
15
|
+
return new Metadata({
|
|
16
|
+
waitForReady: true,
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export default async function buildGrpcExporters(
|
|
21
|
+
config: NodeSDKConfig,
|
|
22
|
+
): Promise<Exporters> {
|
|
12
23
|
return {
|
|
13
24
|
spans: [
|
|
14
25
|
new SpanProcessorMap[config.collectorMode ?? "batch"](
|
|
15
26
|
new OTLPTraceExporter({
|
|
16
27
|
url: `${config.collectorUrl}`,
|
|
17
28
|
compression: CompressionAlgorithm.GZIP,
|
|
29
|
+
metadata: config.grpcMetadata ?? (await defaultMetadata()),
|
|
18
30
|
}),
|
|
19
31
|
),
|
|
20
32
|
new EnrichSpanProcessor(config.spanAttributes),
|
|
@@ -23,13 +35,16 @@ export default function buildGrpcExporters(config: NodeSDKConfig): Exporters {
|
|
|
23
35
|
exporter: new OTLPMetricExporter({
|
|
24
36
|
url: `${config.collectorUrl}`,
|
|
25
37
|
compression: CompressionAlgorithm.GZIP,
|
|
38
|
+
metadata: config.grpcMetadata ?? (await defaultMetadata()),
|
|
26
39
|
}),
|
|
27
40
|
}),
|
|
28
41
|
logs: [
|
|
42
|
+
new EnrichLogProcessor(config.spanAttributes),
|
|
29
43
|
new LogRecordProcessorMap[config.collectorMode ?? "batch"](
|
|
30
44
|
new OTLPLogExporter({
|
|
31
45
|
url: `${config.collectorUrl}`,
|
|
32
46
|
compression: CompressionAlgorithm.GZIP,
|
|
47
|
+
metadata: config.grpcMetadata ?? (await defaultMetadata()),
|
|
33
48
|
}),
|
|
34
49
|
),
|
|
35
50
|
],
|
package/lib/exporter/http.ts
CHANGED
|
@@ -5,8 +5,9 @@ import { OTLPLogExporter } from "@opentelemetry/exporter-logs-otlp-http";
|
|
|
5
5
|
import { OTLPMetricExporter } from "@opentelemetry/exporter-metrics-otlp-http";
|
|
6
6
|
import { LogRecordProcessorMap, SpanProcessorMap } from "../utils.js";
|
|
7
7
|
import { EnrichSpanProcessor } from "../processor/enrich-span-processor.js";
|
|
8
|
-
import { Exporters } from "
|
|
8
|
+
import { Exporters } from "./index.js";
|
|
9
9
|
import { NodeSDKConfig } from "../index.js";
|
|
10
|
+
import { EnrichLogProcessor } from "../processor/enrich-logger-processor.js";
|
|
10
11
|
|
|
11
12
|
export default function buildHttpExporters(config: NodeSDKConfig): Exporters {
|
|
12
13
|
if (config.collectorUrl.endsWith("/")) {
|
|
@@ -30,6 +31,7 @@ export default function buildHttpExporters(config: NodeSDKConfig): Exporters {
|
|
|
30
31
|
}),
|
|
31
32
|
}),
|
|
32
33
|
logs: [
|
|
34
|
+
new EnrichLogProcessor(config.spanAttributes),
|
|
33
35
|
new LogRecordProcessorMap[config.collectorMode ?? "batch"](
|
|
34
36
|
new OTLPLogExporter({
|
|
35
37
|
url: `${config.collectorUrl}/v1/logs`,
|
package/lib/index.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import type { Metadata } from "@grpc/grpc-js";
|
|
2
|
+
|
|
1
3
|
export interface NodeSDKConfig {
|
|
2
4
|
/**
|
|
3
5
|
* The opentelemetry collector entrypoint GRPC url.
|
|
@@ -66,6 +68,13 @@ export interface NodeSDKConfig {
|
|
|
66
68
|
* @default grpc
|
|
67
69
|
*/
|
|
68
70
|
protocol?: SDKProtocol;
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Grpc Metadata for the grpc-js client.
|
|
74
|
+
*
|
|
75
|
+
* @default { waitForReady: true }
|
|
76
|
+
*/
|
|
77
|
+
grpcMetadata?: Metadata;
|
|
69
78
|
}
|
|
70
79
|
|
|
71
80
|
export interface SamplerCondition {
|
|
@@ -1,28 +1,24 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
DiagConsoleLogger,
|
|
4
|
-
DiagLogLevel,
|
|
5
|
-
Span,
|
|
6
|
-
} from "@opentelemetry/api";
|
|
1
|
+
import process from "process";
|
|
2
|
+
import { diag, DiagConsoleLogger, DiagLogLevel } from "@opentelemetry/api";
|
|
7
3
|
import { getNodeAutoInstrumentations } from "@opentelemetry/auto-instrumentations-node";
|
|
8
4
|
import { W3CTraceContextPropagator } from "@opentelemetry/core";
|
|
9
|
-
import { NodeSDK
|
|
5
|
+
import { NodeSDK } from "@opentelemetry/sdk-node";
|
|
10
6
|
import {
|
|
11
7
|
AlwaysOffSampler,
|
|
12
8
|
ParentBasedSampler,
|
|
13
9
|
TraceIdRatioBasedSampler,
|
|
14
10
|
} from "@opentelemetry/sdk-trace-base";
|
|
15
|
-
import packageJson from "../package.json" with { type: "json" };
|
|
16
11
|
import buildConsoleExporters from "./exporter/console.js";
|
|
17
12
|
import buildGrpcExporters from "./exporter/grpc.js";
|
|
18
13
|
import buildHttpExporters from "./exporter/http.js";
|
|
14
|
+
import type { Exporters } from "./exporter/index.js";
|
|
19
15
|
import type { NodeSDKConfig } from "./index.js";
|
|
20
|
-
import
|
|
16
|
+
import { ObservabilityResourceDetector } from "./resource.js";
|
|
21
17
|
import { UrlSampler } from "./url-sampler.js";
|
|
22
18
|
|
|
23
|
-
export default function buildNodeInstrumentation(
|
|
19
|
+
export default async function buildNodeInstrumentation(
|
|
24
20
|
config?: NodeSDKConfig,
|
|
25
|
-
): NodeSDK | undefined {
|
|
21
|
+
): Promise<NodeSDK | undefined> {
|
|
26
22
|
if (!config) {
|
|
27
23
|
console.warn(
|
|
28
24
|
"observability config not set. Skipping NodeJS OpenTelemetry instrumentation.",
|
|
@@ -44,16 +40,6 @@ export default function buildNodeInstrumentation(
|
|
|
44
40
|
return;
|
|
45
41
|
}
|
|
46
42
|
|
|
47
|
-
let exporter: Exporters;
|
|
48
|
-
|
|
49
|
-
if (config.protocol === "http") {
|
|
50
|
-
exporter = buildHttpExporters(config);
|
|
51
|
-
} else if (config.protocol === "console") {
|
|
52
|
-
exporter = buildConsoleExporters(config);
|
|
53
|
-
} else {
|
|
54
|
-
exporter = buildGrpcExporters(config);
|
|
55
|
-
}
|
|
56
|
-
|
|
57
43
|
const urlSampler = new UrlSampler(
|
|
58
44
|
config.ignoreUrls,
|
|
59
45
|
new TraceIdRatioBasedSampler(config.traceRatio ?? 1),
|
|
@@ -67,52 +53,59 @@ export default function buildNodeInstrumentation(
|
|
|
67
53
|
localParentNotSampled: new AlwaysOffSampler(),
|
|
68
54
|
});
|
|
69
55
|
|
|
56
|
+
diag.setLogger(
|
|
57
|
+
new DiagConsoleLogger(),
|
|
58
|
+
config.diagLogLevel ? DiagLogLevel[config.diagLogLevel] : DiagLogLevel.INFO,
|
|
59
|
+
);
|
|
60
|
+
|
|
70
61
|
try {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
62
|
+
const nodeSdkInstrumentation = getNodeAutoInstrumentations({
|
|
63
|
+
"@opentelemetry/instrumentation-fs": {
|
|
64
|
+
enabled: config.enableFS ?? false,
|
|
65
|
+
},
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
let exporter: Exporters;
|
|
69
|
+
|
|
70
|
+
if (config.protocol === "http") {
|
|
71
|
+
exporter = buildHttpExporters(config);
|
|
72
|
+
} else if (config.protocol === "console") {
|
|
73
|
+
exporter = buildConsoleExporters(config);
|
|
74
|
+
} else {
|
|
75
|
+
exporter = await buildGrpcExporters(config);
|
|
76
|
+
}
|
|
77
77
|
|
|
78
78
|
const sdk = new NodeSDK({
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
...config.resourceAttributes,
|
|
83
|
-
}),
|
|
79
|
+
resourceDetectors: [
|
|
80
|
+
new ObservabilityResourceDetector(config.resourceAttributes),
|
|
81
|
+
],
|
|
84
82
|
spanProcessors: exporter.spans,
|
|
85
83
|
serviceName: config.serviceName,
|
|
86
84
|
metricReader: exporter.metrics,
|
|
87
85
|
logRecordProcessors: exporter.logs,
|
|
88
86
|
sampler: mainSampler,
|
|
89
87
|
textMapPropagator: new W3CTraceContextPropagator(),
|
|
90
|
-
instrumentations: [
|
|
91
|
-
getNodeAutoInstrumentations({
|
|
92
|
-
"@opentelemetry/instrumentation-fs": {
|
|
93
|
-
enabled: config.enableFS ?? false,
|
|
94
|
-
},
|
|
95
|
-
"@opentelemetry/instrumentation-pino": {
|
|
96
|
-
logHook: (
|
|
97
|
-
_span: Span,
|
|
98
|
-
record: Record<string, unknown>,
|
|
99
|
-
_level?: number,
|
|
100
|
-
) => {
|
|
101
|
-
if (config.spanAttributes != undefined) {
|
|
102
|
-
for (const [key, value] of Object.entries(
|
|
103
|
-
config.spanAttributes,
|
|
104
|
-
)) {
|
|
105
|
-
record[key] = typeof value === "function" ? value() : value;
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
},
|
|
109
|
-
},
|
|
110
|
-
}),
|
|
111
|
-
],
|
|
88
|
+
instrumentations: [nodeSdkInstrumentation],
|
|
112
89
|
});
|
|
113
90
|
|
|
114
91
|
sdk.start();
|
|
115
92
|
console.log("NodeJS OpenTelemetry instrumentation started successfully.");
|
|
93
|
+
|
|
94
|
+
process.on("SIGTERM", async () => {
|
|
95
|
+
try {
|
|
96
|
+
// Flushing before shutdown is implemented on a per-exporter basis.
|
|
97
|
+
await sdk.shutdown();
|
|
98
|
+
console.log(
|
|
99
|
+
"NodeJS OpenTelemetry instrumentation shutdown successfully",
|
|
100
|
+
);
|
|
101
|
+
} catch (error) {
|
|
102
|
+
console.error(
|
|
103
|
+
"Error shutting down NodeJS OpenTelemetry instrumentation:",
|
|
104
|
+
error,
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
|
|
116
109
|
return sdk;
|
|
117
110
|
} catch (error) {
|
|
118
111
|
console.error(
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { LogRecord, LogRecordProcessor } from "@opentelemetry/sdk-logs";
|
|
2
|
+
import { Context } from "@opentelemetry/api";
|
|
3
|
+
import { SignalAttributeValue } from "../index.js";
|
|
4
|
+
|
|
5
|
+
export class EnrichLogProcessor implements LogRecordProcessor {
|
|
6
|
+
private _spanAttributes?:
|
|
7
|
+
| Record<string, SignalAttributeValue | (() => SignalAttributeValue)>
|
|
8
|
+
| undefined = undefined;
|
|
9
|
+
|
|
10
|
+
constructor(
|
|
11
|
+
spanAttributes?: Record<
|
|
12
|
+
string,
|
|
13
|
+
SignalAttributeValue | (() => SignalAttributeValue)
|
|
14
|
+
>,
|
|
15
|
+
) {
|
|
16
|
+
this._spanAttributes = spanAttributes;
|
|
17
|
+
}
|
|
18
|
+
forceFlush(): Promise<void> {
|
|
19
|
+
return Promise.resolve();
|
|
20
|
+
}
|
|
21
|
+
onEmit(logRecord: LogRecord, _context?: Context): void {
|
|
22
|
+
if (this._spanAttributes) {
|
|
23
|
+
for (const [key, value] of Object.entries(this._spanAttributes)) {
|
|
24
|
+
logRecord.setAttribute(
|
|
25
|
+
key,
|
|
26
|
+
typeof value === "function" ? value() : value,
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
shutdown(): Promise<void> {
|
|
32
|
+
return Promise.resolve();
|
|
33
|
+
}
|
|
34
|
+
}
|
package/lib/resource.ts
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ResourceDetector,
|
|
3
|
+
DetectedResource,
|
|
4
|
+
DetectedResourceAttributes,
|
|
5
|
+
} from "@opentelemetry/resources";
|
|
6
|
+
import { SignalAttributeValue } from "./index.js";
|
|
7
|
+
import packageJson from "../package.json" with { type: "json" };
|
|
8
|
+
|
|
9
|
+
export class ObservabilityResourceDetector implements ResourceDetector {
|
|
10
|
+
private _resourceAttributes: Record<string, SignalAttributeValue> | undefined;
|
|
11
|
+
|
|
12
|
+
constructor(resourceAttributes?: Record<string, SignalAttributeValue>) {
|
|
13
|
+
this._resourceAttributes = resourceAttributes;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
detect(): DetectedResource {
|
|
17
|
+
let attributes: DetectedResourceAttributes = {};
|
|
18
|
+
|
|
19
|
+
if (this._resourceAttributes) {
|
|
20
|
+
attributes = {
|
|
21
|
+
...this._resourceAttributes,
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
attributes["o11y.sdk.name"] = packageJson.name;
|
|
26
|
+
attributes["o11y.sdk.version"] = packageJson.version;
|
|
27
|
+
|
|
28
|
+
return { attributes };
|
|
29
|
+
}
|
|
30
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ogcio/o11y-sdk-node",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Opentelemetry standard instrumentation SDK for NodeJS based project",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -19,28 +19,33 @@
|
|
|
19
19
|
"author": "team:ogcio/observability",
|
|
20
20
|
"license": "ISC",
|
|
21
21
|
"dependencies": {
|
|
22
|
+
"@grpc/grpc-js": "^1.13.4",
|
|
22
23
|
"@opentelemetry/api": "^1.9.0",
|
|
23
|
-
"@opentelemetry/auto-instrumentations-node": "^0.
|
|
24
|
-
"@opentelemetry/core": "
|
|
25
|
-
"@opentelemetry/exporter-logs-otlp-grpc": "^0.
|
|
26
|
-
"@opentelemetry/exporter-logs-otlp-http": "^0.
|
|
27
|
-
"@opentelemetry/exporter-metrics-otlp-grpc": "^0.
|
|
28
|
-
"@opentelemetry/exporter-metrics-otlp-http": "^0.
|
|
29
|
-
"@opentelemetry/exporter-trace-otlp-grpc": "^0.
|
|
30
|
-
"@opentelemetry/exporter-trace-otlp-http": "^0.
|
|
31
|
-
"@opentelemetry/instrumentation": "^0.
|
|
32
|
-
"@opentelemetry/otlp-exporter-base": "^0.
|
|
33
|
-
"@opentelemetry/
|
|
34
|
-
"@opentelemetry/sdk-
|
|
35
|
-
"@opentelemetry/sdk-
|
|
36
|
-
"@opentelemetry/sdk-
|
|
24
|
+
"@opentelemetry/auto-instrumentations-node": "^0.60.1",
|
|
25
|
+
"@opentelemetry/core": "^2.0.1",
|
|
26
|
+
"@opentelemetry/exporter-logs-otlp-grpc": "^0.202.0",
|
|
27
|
+
"@opentelemetry/exporter-logs-otlp-http": "^0.202.0",
|
|
28
|
+
"@opentelemetry/exporter-metrics-otlp-grpc": "^0.202.0",
|
|
29
|
+
"@opentelemetry/exporter-metrics-otlp-http": "^0.202.0",
|
|
30
|
+
"@opentelemetry/exporter-trace-otlp-grpc": "^0.202.0",
|
|
31
|
+
"@opentelemetry/exporter-trace-otlp-http": "^0.202.0",
|
|
32
|
+
"@opentelemetry/instrumentation": "^0.202.0",
|
|
33
|
+
"@opentelemetry/otlp-exporter-base": "^0.202.0",
|
|
34
|
+
"@opentelemetry/resources": "^2.0.1",
|
|
35
|
+
"@opentelemetry/sdk-logs": "^0.202.0",
|
|
36
|
+
"@opentelemetry/sdk-metrics": "^2.0.1",
|
|
37
|
+
"@opentelemetry/sdk-node": "^0.202.0",
|
|
38
|
+
"@opentelemetry/sdk-trace-base": "^2.0.1"
|
|
37
39
|
},
|
|
38
40
|
"devDependencies": {
|
|
39
|
-
"@types/node": "^
|
|
40
|
-
"@vitest/coverage-v8": "^3.
|
|
41
|
-
"tsx": "^4.
|
|
42
|
-
"typescript": "^5.8.
|
|
43
|
-
"vitest": "^3.
|
|
41
|
+
"@types/node": "^24.0.3",
|
|
42
|
+
"@vitest/coverage-v8": "^3.2.4",
|
|
43
|
+
"tsx": "^4.20.3",
|
|
44
|
+
"typescript": "^5.8.3",
|
|
45
|
+
"vitest": "^3.2.4"
|
|
46
|
+
},
|
|
47
|
+
"engines": {
|
|
48
|
+
"node": ">=20.6.0"
|
|
44
49
|
},
|
|
45
50
|
"scripts": {
|
|
46
51
|
"build": "rm -rf dist && tsc -p tsconfig.json",
|
package/test/index.test.ts
CHANGED
|
@@ -1,13 +1,27 @@
|
|
|
1
|
-
import { describe, test, expect, vi } from "vitest";
|
|
1
|
+
import { describe, test, expect, vi, beforeEach, afterEach } from "vitest";
|
|
2
2
|
import { NodeSDKConfig } from "../index";
|
|
3
3
|
import { instrumentNode } from "../index";
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
default: vi.fn(),
|
|
7
|
-
}));
|
|
4
|
+
import * as buildNodeInstrumentationModule from "../lib/instrumentation.node";
|
|
5
|
+
import { metrics } from "@opentelemetry/sdk-node";
|
|
8
6
|
|
|
9
7
|
describe("instrumentNode", () => {
|
|
8
|
+
beforeEach(() => {
|
|
9
|
+
// @ts-ignore Avoid actually running exporters at any time in tests (overriding private method)
|
|
10
|
+
vi.spyOn(
|
|
11
|
+
metrics.PeriodicExportingMetricReader.prototype,
|
|
12
|
+
"_doRun",
|
|
13
|
+
).mockImplementation(vi.fn());
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
afterEach(() => {
|
|
17
|
+
vi.restoreAllMocks();
|
|
18
|
+
});
|
|
19
|
+
|
|
10
20
|
test("should call buildNodeInstrumentation with the provided config", async () => {
|
|
21
|
+
const instrumentationMock = vi
|
|
22
|
+
.spyOn(buildNodeInstrumentationModule, "default")
|
|
23
|
+
.mockImplementation(vi.fn());
|
|
24
|
+
|
|
11
25
|
const config: NodeSDKConfig = {
|
|
12
26
|
serviceName: "custom-service",
|
|
13
27
|
collectorUrl: "http://custom-collector.com",
|
|
@@ -23,16 +37,34 @@ describe("instrumentNode", () => {
|
|
|
23
37
|
},
|
|
24
38
|
};
|
|
25
39
|
|
|
26
|
-
|
|
27
|
-
"../lib/instrumentation.node"
|
|
28
|
-
);
|
|
40
|
+
await instrumentNode(config);
|
|
29
41
|
|
|
30
|
-
|
|
42
|
+
expect(instrumentationMock).toHaveBeenCalledWith(config);
|
|
43
|
+
});
|
|
31
44
|
|
|
32
|
-
|
|
45
|
+
test("should not throw when called without arguments", async () => {
|
|
46
|
+
await expect(instrumentNode()).resolves.not.toThrow();
|
|
33
47
|
});
|
|
34
48
|
|
|
35
|
-
test("should
|
|
36
|
-
|
|
49
|
+
test("should invoke instrumentation shutdown on SIGTERM", async () => {
|
|
50
|
+
const config: NodeSDKConfig = {
|
|
51
|
+
serviceName: "custom-service",
|
|
52
|
+
collectorUrl: "http://custom-collector.com",
|
|
53
|
+
protocol: "grpc",
|
|
54
|
+
resourceAttributes: {
|
|
55
|
+
"team.infra.cluster": "dev-01",
|
|
56
|
+
"team.infra.pod": "01",
|
|
57
|
+
"team.service.type": "fastify",
|
|
58
|
+
},
|
|
59
|
+
spanAttributes: {
|
|
60
|
+
"signal.namespace": "example",
|
|
61
|
+
"signal.number": () => "callback",
|
|
62
|
+
},
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
const sdk = await instrumentNode(config);
|
|
66
|
+
const shutdownMock = vi.spyOn(sdk, "shutdown");
|
|
67
|
+
process.emit("SIGTERM");
|
|
68
|
+
expect(shutdownMock).toHaveBeenCalled();
|
|
37
69
|
});
|
|
38
70
|
});
|
|
@@ -22,5 +22,5 @@ The `run.sh` script performs the following steps:
|
|
|
22
22
|
- run fastify app in a docker container
|
|
23
23
|
- ensure is running otherwise exit process
|
|
24
24
|
- execute some curl to the fastify microservice
|
|
25
|
-
-
|
|
25
|
+
- persist alloy log to a file and save to following path `/packages/sdk-node/test/integration/`
|
|
26
26
|
- docker turn down process (containers/network/image)
|
package/test/node-config.test.ts
CHANGED
|
@@ -1,18 +1,11 @@
|
|
|
1
1
|
import { test, describe, assert, expect } from "vitest";
|
|
2
2
|
import buildNodeInstrumentation from "../lib/instrumentation.node.js";
|
|
3
|
-
import { NodeSDK,
|
|
4
|
-
|
|
5
|
-
import { OTLPMetricExporter as GRPC_OTLPMetricExporter } from "@opentelemetry/exporter-metrics-otlp-grpc";
|
|
6
|
-
import { OTLPLogExporter as GRPC_OTLPLogExporter } from "@opentelemetry/exporter-logs-otlp-grpc";
|
|
7
|
-
|
|
8
|
-
import { OTLPTraceExporter as HTTP_OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http";
|
|
9
|
-
import { OTLPMetricExporter as HTTP_OTLPMetricExporter } from "@opentelemetry/exporter-metrics-otlp-http";
|
|
10
|
-
import { OTLPLogExporter as HTTP_OTLPLogExporter } from "@opentelemetry/exporter-logs-otlp-http";
|
|
3
|
+
import { NodeSDK, metrics } from "@opentelemetry/sdk-node";
|
|
4
|
+
|
|
11
5
|
import { NodeSDKConfig } from "../lib/index.js";
|
|
12
6
|
import buildHttpExporters from "../lib/exporter/http.js";
|
|
13
7
|
import {
|
|
14
8
|
BatchSpanProcessor,
|
|
15
|
-
ConsoleSpanExporter,
|
|
16
9
|
SimpleSpanProcessor,
|
|
17
10
|
} from "@opentelemetry/sdk-trace-base";
|
|
18
11
|
import {
|
|
@@ -27,7 +20,7 @@ describe("verify config settings", () => {
|
|
|
27
20
|
serviceName: "test",
|
|
28
21
|
};
|
|
29
22
|
|
|
30
|
-
test("grpc config", () => {
|
|
23
|
+
test("grpc config", async () => {
|
|
31
24
|
const config: NodeSDKConfig = {
|
|
32
25
|
...commonConfig,
|
|
33
26
|
protocol: "grpc",
|
|
@@ -35,7 +28,7 @@ describe("verify config settings", () => {
|
|
|
35
28
|
diagLogLevel: "NONE",
|
|
36
29
|
};
|
|
37
30
|
|
|
38
|
-
const sdk: NodeSDK | undefined = buildNodeInstrumentation(config);
|
|
31
|
+
const sdk: NodeSDK | undefined = await buildNodeInstrumentation(config);
|
|
39
32
|
|
|
40
33
|
assert.ok(sdk);
|
|
41
34
|
|
|
@@ -44,8 +37,8 @@ describe("verify config settings", () => {
|
|
|
44
37
|
|
|
45
38
|
const logs = _configuration.logRecordProcessors;
|
|
46
39
|
|
|
47
|
-
assert.equal(logs.length,
|
|
48
|
-
assert.ok(logs[
|
|
40
|
+
assert.equal(logs.length, 2);
|
|
41
|
+
assert.ok(logs[1] instanceof BatchLogRecordProcessor);
|
|
49
42
|
|
|
50
43
|
const spans = _configuration.spanProcessors;
|
|
51
44
|
|
|
@@ -59,14 +52,14 @@ describe("verify config settings", () => {
|
|
|
59
52
|
);
|
|
60
53
|
});
|
|
61
54
|
|
|
62
|
-
test("http config", () => {
|
|
55
|
+
test("http config", async () => {
|
|
63
56
|
const config: NodeSDKConfig = {
|
|
64
57
|
...commonConfig,
|
|
65
58
|
protocol: "http",
|
|
66
59
|
diagLogLevel: "NONE",
|
|
67
60
|
};
|
|
68
61
|
|
|
69
|
-
const sdk: NodeSDK | undefined = buildNodeInstrumentation(config);
|
|
62
|
+
const sdk: NodeSDK | undefined = await buildNodeInstrumentation(config);
|
|
70
63
|
assert.ok(sdk);
|
|
71
64
|
|
|
72
65
|
const _configuration = sdk["_configuration"];
|
|
@@ -74,8 +67,8 @@ describe("verify config settings", () => {
|
|
|
74
67
|
|
|
75
68
|
const logs = _configuration.logRecordProcessors;
|
|
76
69
|
|
|
77
|
-
assert.equal(logs.length,
|
|
78
|
-
assert.ok(logs[
|
|
70
|
+
assert.equal(logs.length, 2);
|
|
71
|
+
assert.ok(logs[1] instanceof BatchLogRecordProcessor);
|
|
79
72
|
|
|
80
73
|
const spans = _configuration.spanProcessors;
|
|
81
74
|
|
|
@@ -89,14 +82,14 @@ describe("verify config settings", () => {
|
|
|
89
82
|
);
|
|
90
83
|
});
|
|
91
84
|
|
|
92
|
-
test("console - console config", () => {
|
|
85
|
+
test("console - console config", async () => {
|
|
93
86
|
const config: NodeSDKConfig = {
|
|
94
87
|
...commonConfig,
|
|
95
88
|
protocol: "console",
|
|
96
89
|
diagLogLevel: "NONE",
|
|
97
90
|
};
|
|
98
91
|
|
|
99
|
-
const sdk: NodeSDK = buildNodeInstrumentation(config)!;
|
|
92
|
+
const sdk: NodeSDK = await buildNodeInstrumentation(config)!;
|
|
100
93
|
assert.ok(sdk);
|
|
101
94
|
|
|
102
95
|
const _configuration = sdk["_configuration"];
|
|
@@ -105,8 +98,8 @@ describe("verify config settings", () => {
|
|
|
105
98
|
const logs = _configuration.logRecordProcessors;
|
|
106
99
|
|
|
107
100
|
// verify simple log processor for instant console logging
|
|
108
|
-
assert.equal(logs.length,
|
|
109
|
-
assert.ok(logs[
|
|
101
|
+
assert.equal(logs.length, 2);
|
|
102
|
+
assert.ok(logs[1] instanceof SimpleLogRecordProcessor);
|
|
110
103
|
|
|
111
104
|
const spans = _configuration.spanProcessors;
|
|
112
105
|
|
|
@@ -121,7 +114,7 @@ describe("verify config settings", () => {
|
|
|
121
114
|
);
|
|
122
115
|
});
|
|
123
116
|
|
|
124
|
-
test("single log sending config", () => {
|
|
117
|
+
test("single log sending config", async () => {
|
|
125
118
|
const config: NodeSDKConfig = {
|
|
126
119
|
...commonConfig,
|
|
127
120
|
protocol: "grpc",
|
|
@@ -129,15 +122,15 @@ describe("verify config settings", () => {
|
|
|
129
122
|
collectorMode: "single",
|
|
130
123
|
};
|
|
131
124
|
|
|
132
|
-
const sdk: NodeSDK | undefined = buildNodeInstrumentation(config);
|
|
125
|
+
const sdk: NodeSDK | undefined = await buildNodeInstrumentation(config);
|
|
133
126
|
|
|
134
127
|
assert.ok(sdk);
|
|
135
128
|
|
|
136
129
|
const _configuration = sdk["_configuration"];
|
|
137
130
|
|
|
138
131
|
const logRecordProcessors = _configuration.logRecordProcessors;
|
|
139
|
-
assert.equal(logRecordProcessors.length,
|
|
140
|
-
assert.ok(logRecordProcessors[
|
|
132
|
+
assert.equal(logRecordProcessors.length, 2);
|
|
133
|
+
assert.ok(logRecordProcessors[1] instanceof SimpleLogRecordProcessor);
|
|
141
134
|
});
|
|
142
135
|
|
|
143
136
|
test("check if clear base endpoint final slash", () => {
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { describe, it, expect, vi } from "vitest";
|
|
2
|
+
import { LogRecord } from "@opentelemetry/sdk-logs";
|
|
3
|
+
import { EnrichLogProcessor } from "../../lib/processor/enrich-logger-processor.js";
|
|
4
|
+
|
|
5
|
+
const createMockLogRecord = () => {
|
|
6
|
+
return {
|
|
7
|
+
setAttribute: vi.fn(),
|
|
8
|
+
} as unknown as LogRecord;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
describe("EnrichLogProcessor", () => {
|
|
12
|
+
it("should enrich log record with static attributes", () => {
|
|
13
|
+
const attributes = { key1: "value1", key2: 42 };
|
|
14
|
+
const processor = new EnrichLogProcessor(attributes);
|
|
15
|
+
const mockLogRecord = createMockLogRecord();
|
|
16
|
+
|
|
17
|
+
processor.onEmit(mockLogRecord);
|
|
18
|
+
|
|
19
|
+
expect(mockLogRecord.setAttribute).toHaveBeenCalledWith("key1", "value1");
|
|
20
|
+
expect(mockLogRecord.setAttribute).toHaveBeenCalledWith("key2", 42);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it("should enrich log record with dynamic attributes", () => {
|
|
24
|
+
const attributes = {
|
|
25
|
+
key1: () => "dynamicValue",
|
|
26
|
+
key2: () => 100,
|
|
27
|
+
};
|
|
28
|
+
const processor = new EnrichLogProcessor(attributes);
|
|
29
|
+
const mockLogRecord = createMockLogRecord();
|
|
30
|
+
|
|
31
|
+
processor.onEmit(mockLogRecord);
|
|
32
|
+
|
|
33
|
+
expect(mockLogRecord.setAttribute).toHaveBeenCalledWith(
|
|
34
|
+
"key1",
|
|
35
|
+
"dynamicValue",
|
|
36
|
+
);
|
|
37
|
+
expect(mockLogRecord.setAttribute).toHaveBeenCalledWith("key2", 100);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it("should not set attributes if no span attributes are provided", () => {
|
|
41
|
+
const processor = new EnrichLogProcessor();
|
|
42
|
+
const mockLogRecord = createMockLogRecord();
|
|
43
|
+
|
|
44
|
+
processor.onEmit(mockLogRecord);
|
|
45
|
+
|
|
46
|
+
expect(mockLogRecord.setAttribute).not.toHaveBeenCalled();
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it("should reject forceFlush", async () => {
|
|
50
|
+
await expect(
|
|
51
|
+
new EnrichLogProcessor().forceFlush(),
|
|
52
|
+
).resolves.toBeUndefined();
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it("should resolve shutdown", async () => {
|
|
56
|
+
await expect(new EnrichLogProcessor().shutdown()).resolves.toBeUndefined();
|
|
57
|
+
});
|
|
58
|
+
});
|
|
@@ -5,13 +5,12 @@ import {
|
|
|
5
5
|
Link,
|
|
6
6
|
Span,
|
|
7
7
|
SpanAttributes,
|
|
8
|
-
SpanAttributeValue,
|
|
9
8
|
SpanContext,
|
|
10
9
|
SpanStatus,
|
|
11
10
|
TimeInput,
|
|
12
11
|
} from "@opentelemetry/api";
|
|
13
12
|
import { describe, expect, it } from "vitest";
|
|
14
|
-
import { EnrichSpanProcessor } from "
|
|
13
|
+
import { EnrichSpanProcessor } from "../../lib/processor/enrich-span-processor.js";
|
|
15
14
|
|
|
16
15
|
class MockSpan implements Span {
|
|
17
16
|
public attributes: Record<string, AttributeValue> = {};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { describe, test, expect } from "vitest";
|
|
2
|
+
import { ObservabilityResourceDetector } from "../lib/resource";
|
|
3
|
+
|
|
4
|
+
describe("ObservabilityResourceDetector", () => {
|
|
5
|
+
test("should return custom resource attribute", () => {
|
|
6
|
+
const detector = new ObservabilityResourceDetector({
|
|
7
|
+
first: "first_value",
|
|
8
|
+
second: "second_value",
|
|
9
|
+
});
|
|
10
|
+
const result = detector.detect();
|
|
11
|
+
|
|
12
|
+
expect(result.attributes).not.toBeNull();
|
|
13
|
+
expect(result.attributes).toHaveProperty("first");
|
|
14
|
+
expect(result.attributes!["first"]).eq("first_value");
|
|
15
|
+
expect(result.attributes).toHaveProperty("second");
|
|
16
|
+
expect(result.attributes!["second"]).eq("second_value");
|
|
17
|
+
// default
|
|
18
|
+
expect(result.attributes).toHaveProperty("o11y.sdk.name");
|
|
19
|
+
expect(result.attributes!["o11y.sdk.name"]).eq("@ogcio/o11y-sdk-node");
|
|
20
|
+
expect(result.attributes).toHaveProperty("o11y.sdk.version");
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
test("should return default resource attribute", () => {
|
|
24
|
+
const detector = new ObservabilityResourceDetector();
|
|
25
|
+
const result = detector.detect();
|
|
26
|
+
|
|
27
|
+
expect(result.attributes).not.toBeNull();
|
|
28
|
+
// default
|
|
29
|
+
expect(result.attributes).toHaveProperty("o11y.sdk.name");
|
|
30
|
+
expect(result.attributes!["o11y.sdk.name"]).eq("@ogcio/o11y-sdk-node");
|
|
31
|
+
expect(result.attributes).toHaveProperty("o11y.sdk.version");
|
|
32
|
+
});
|
|
33
|
+
});
|
package/test/validation.test.ts
CHANGED
|
@@ -10,7 +10,7 @@ describe("validation config: should return without breaking the execution", () =
|
|
|
10
10
|
.spyOn(console, "warn")
|
|
11
11
|
.mockImplementation(vi.fn());
|
|
12
12
|
|
|
13
|
-
instrumentNode();
|
|
13
|
+
await instrumentNode();
|
|
14
14
|
|
|
15
15
|
expect(consoleWarnSpy).toHaveBeenCalled();
|
|
16
16
|
expect(consoleWarnSpy).toHaveBeenCalledWith(
|
|
@@ -26,11 +26,13 @@ describe("validation config: should return without breaking the execution", () =
|
|
|
26
26
|
.mockImplementation(vi.fn());
|
|
27
27
|
const consoleLogSpy = vi.spyOn(console, "log").mockImplementation(vi.fn());
|
|
28
28
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
collectorUrl: undefined
|
|
32
|
-
})
|
|
33
|
-
|
|
29
|
+
await expect(
|
|
30
|
+
buildNodeInstrumentation({
|
|
31
|
+
collectorUrl: undefined,
|
|
32
|
+
}).then((result) => {
|
|
33
|
+
sdk = result;
|
|
34
|
+
}),
|
|
35
|
+
).resolves.not.toThrowError();
|
|
34
36
|
|
|
35
37
|
assert.equal(sdk, undefined);
|
|
36
38
|
|
|
@@ -41,7 +43,7 @@ describe("validation config: should return without breaking the execution", () =
|
|
|
41
43
|
expect(consoleLogSpy).not.toHaveBeenCalled();
|
|
42
44
|
});
|
|
43
45
|
|
|
44
|
-
test("node instrumentation: invalid url", () => {
|
|
46
|
+
test("node instrumentation: invalid url", async () => {
|
|
45
47
|
let sdk: NodeSDK | undefined = undefined;
|
|
46
48
|
|
|
47
49
|
const consoleErrorSpy = vi
|
|
@@ -49,11 +51,13 @@ describe("validation config: should return without breaking the execution", () =
|
|
|
49
51
|
.mockImplementation(vi.fn());
|
|
50
52
|
const consoleLogSpy = vi.spyOn(console, "log").mockImplementation(vi.fn());
|
|
51
53
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
+
await expect(
|
|
55
|
+
buildNodeInstrumentation({
|
|
54
56
|
collectorUrl: "notavalidURL",
|
|
55
|
-
})
|
|
56
|
-
|
|
57
|
+
}).then((result) => {
|
|
58
|
+
sdk = result;
|
|
59
|
+
}),
|
|
60
|
+
).resolves.not.toThrowError();
|
|
57
61
|
|
|
58
62
|
assert.equal(sdk, undefined);
|
|
59
63
|
|
|
@@ -64,7 +68,7 @@ describe("validation config: should return without breaking the execution", () =
|
|
|
64
68
|
expect(consoleLogSpy).not.toHaveBeenCalled();
|
|
65
69
|
});
|
|
66
70
|
|
|
67
|
-
test("node instrumentation: verify no instrumentation if exception occurs", () => {
|
|
71
|
+
test("node instrumentation: verify no instrumentation if exception occurs", async () => {
|
|
68
72
|
let sdk: NodeSDK | undefined = undefined;
|
|
69
73
|
|
|
70
74
|
const consoleErrorSpy = vi
|
|
@@ -78,12 +82,14 @@ describe("validation config: should return without breaking the execution", () =
|
|
|
78
82
|
}),
|
|
79
83
|
}));
|
|
80
84
|
|
|
81
|
-
|
|
82
|
-
|
|
85
|
+
await expect(
|
|
86
|
+
buildNodeInstrumentation({
|
|
83
87
|
collectorUrl: "https://testurl.com",
|
|
84
88
|
serviceName: "test",
|
|
85
|
-
})
|
|
86
|
-
|
|
89
|
+
}).then((result) => {
|
|
90
|
+
sdk = result;
|
|
91
|
+
}),
|
|
92
|
+
).resolves.not.toThrowError();
|
|
87
93
|
|
|
88
94
|
assert.equal(sdk, undefined);
|
|
89
95
|
|
package/vitest.config.ts
CHANGED
|
@@ -22,10 +22,10 @@ export default defineConfig({
|
|
|
22
22
|
reporters: ["default", ["junit", { outputFile: "test-report.xml" }]],
|
|
23
23
|
environment: "node",
|
|
24
24
|
pool: "threads",
|
|
25
|
-
|
|
25
|
+
projects: [
|
|
26
26
|
{
|
|
27
27
|
test: {
|
|
28
|
-
include: ["**/test/*.test.ts"],
|
|
28
|
+
include: ["**/test/*.test.ts", "**/test/processor/*.test.ts"],
|
|
29
29
|
name: "unit",
|
|
30
30
|
},
|
|
31
31
|
},
|
|
File without changes
|
|
File without changes
|
|
File without changes
|