@ogcio/o11y-sdk-node 0.1.0-beta.1 → 0.1.0-beta.11

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.
Files changed (86) hide show
  1. package/CHANGELOG.md +81 -0
  2. package/README.md +222 -0
  3. package/dist/index.d.ts +3 -2
  4. package/dist/index.js +2 -0
  5. package/dist/lib/exporter/console.d.ts +3 -0
  6. package/dist/lib/exporter/console.js +20 -0
  7. package/dist/lib/exporter/grpc.d.ts +3 -0
  8. package/dist/lib/exporter/grpc.js +41 -0
  9. package/dist/lib/exporter/http.d.ts +3 -0
  10. package/dist/lib/{http.js → exporter/http.js} +15 -9
  11. package/dist/lib/exporter/index.d.ts +8 -0
  12. package/dist/lib/index.d.ts +36 -6
  13. package/dist/lib/instrumentation.node.d.ts +1 -1
  14. package/dist/lib/instrumentation.node.js +47 -23
  15. package/dist/lib/metrics.d.ts +18 -0
  16. package/dist/lib/metrics.js +24 -0
  17. package/dist/lib/processor/enrich-logger-processor.d.ts +10 -0
  18. package/dist/lib/processor/enrich-logger-processor.js +19 -0
  19. package/dist/lib/processor/enrich-span-processor.d.ts +11 -0
  20. package/dist/lib/processor/enrich-span-processor.js +22 -0
  21. package/dist/lib/resource.d.ts +7 -0
  22. package/dist/lib/resource.js +18 -0
  23. package/dist/lib/traces.d.ts +1 -0
  24. package/dist/lib/traces.js +4 -0
  25. package/dist/lib/url-sampler.d.ts +10 -0
  26. package/dist/lib/url-sampler.js +25 -0
  27. package/dist/lib/utils.d.ts +4 -2
  28. package/dist/lib/utils.js +8 -3
  29. package/dist/package.json +58 -0
  30. package/dist/vitest.config.js +15 -1
  31. package/index.ts +4 -2
  32. package/lib/exporter/console.ts +31 -0
  33. package/lib/exporter/grpc.ts +52 -0
  34. package/lib/{http.ts → exporter/http.ts} +19 -11
  35. package/lib/exporter/index.ts +9 -0
  36. package/lib/index.ts +46 -5
  37. package/lib/instrumentation.node.ts +61 -28
  38. package/lib/metrics.ts +75 -0
  39. package/lib/processor/enrich-logger-processor.ts +34 -0
  40. package/lib/processor/enrich-span-processor.ts +39 -0
  41. package/lib/resource.ts +30 -0
  42. package/lib/traces.ts +5 -0
  43. package/lib/url-sampler.ts +52 -0
  44. package/lib/utils.ts +16 -4
  45. package/package.json +33 -25
  46. package/test/index.test.ts +22 -12
  47. package/test/integration/README.md +26 -0
  48. package/test/integration/integration.test.ts +58 -0
  49. package/test/integration/run.sh +88 -0
  50. package/test/metrics.test.ts +142 -0
  51. package/test/node-config.test.ts +76 -44
  52. package/test/processor/enrich-logger-processor.test.ts +58 -0
  53. package/test/processor/enrich-span-processor.test.ts +104 -0
  54. package/test/resource.test.ts +33 -0
  55. package/test/url-sampler.test.ts +215 -0
  56. package/test/utils/alloy-log-parser.ts +46 -0
  57. package/test/validation.test.ts +48 -11
  58. package/tsconfig.json +2 -1
  59. package/vitest.config.ts +15 -1
  60. package/coverage/cobertura-coverage.xml +0 -199
  61. package/coverage/lcov-report/base.css +0 -224
  62. package/coverage/lcov-report/block-navigation.js +0 -87
  63. package/coverage/lcov-report/favicon.png +0 -0
  64. package/coverage/lcov-report/index.html +0 -131
  65. package/coverage/lcov-report/prettify.css +0 -1
  66. package/coverage/lcov-report/prettify.js +0 -2
  67. package/coverage/lcov-report/sdk-node/index.html +0 -116
  68. package/coverage/lcov-report/sdk-node/index.ts.html +0 -106
  69. package/coverage/lcov-report/sdk-node/lib/grpc.ts.html +0 -178
  70. package/coverage/lcov-report/sdk-node/lib/http.ts.html +0 -190
  71. package/coverage/lcov-report/sdk-node/lib/index.html +0 -191
  72. package/coverage/lcov-report/sdk-node/lib/index.ts.html +0 -265
  73. package/coverage/lcov-report/sdk-node/lib/instrumentation.node.ts.html +0 -310
  74. package/coverage/lcov-report/sdk-node/lib/options.ts.html +0 -109
  75. package/coverage/lcov-report/sdk-node/lib/utils.ts.html +0 -115
  76. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  77. package/coverage/lcov-report/sorter.js +0 -196
  78. package/coverage/lcov.info +0 -206
  79. package/dist/lib/grpc.d.ts +0 -3
  80. package/dist/lib/grpc.js +0 -26
  81. package/dist/lib/http.d.ts +0 -3
  82. package/dist/lib/options.d.ts +0 -7
  83. package/lib/grpc.ts +0 -31
  84. package/lib/options.ts +0 -8
  85. package/test-report.xml +0 -39
  86. /package/dist/lib/{options.js → exporter/index.js} +0 -0
@@ -0,0 +1,142 @@
1
+ import { describe, test, expect, vi, beforeEach, assert } from "vitest";
2
+ import { getMetric, MetricsParams } from "../lib/metrics";
3
+
4
+ const mockMeter = {
5
+ createGauge: vi.fn(),
6
+ createHistogram: vi.fn(),
7
+ createCounter: vi.fn(),
8
+ createUpDownCounter: vi.fn(),
9
+ createObservableCounter: vi.fn(),
10
+ createObservableUpDownCounter: vi.fn(),
11
+ createObservableGauge: vi.fn(),
12
+ };
13
+
14
+ vi.mock("@opentelemetry/api", async () => {
15
+ const { createNoopMeter } = await import("@opentelemetry/api");
16
+
17
+ return {
18
+ metrics: {
19
+ getMeter: vi.fn(() => mockMeter),
20
+ },
21
+ createNoopMeter: createNoopMeter,
22
+ };
23
+ });
24
+
25
+ describe("MetricsFactoryMap", () => {
26
+ beforeEach(() => {
27
+ vi.clearAllMocks();
28
+ });
29
+
30
+ const validMetricParams: MetricsParams = {
31
+ metricName: "test-metric",
32
+ meterName: "test-meter",
33
+ options: { description: "A test metric" },
34
+ };
35
+
36
+ test("should call createGauge when type is 'gauge'", () => {
37
+ mockMeter.createGauge.mockReturnValue("mocked-gauge");
38
+
39
+ const result = getMetric("gauge", validMetricParams);
40
+
41
+ expect(result).toBe("mocked-gauge");
42
+ expect(mockMeter.createGauge).toHaveBeenCalledWith(
43
+ validMetricParams.metricName,
44
+ validMetricParams.options,
45
+ );
46
+ });
47
+
48
+ test("should call createHistogram when type is 'histogram'", () => {
49
+ mockMeter.createHistogram.mockReturnValue("mocked-histogram");
50
+
51
+ const result = getMetric("histogram", validMetricParams);
52
+
53
+ expect(result).toBe("mocked-histogram");
54
+ expect(mockMeter.createHistogram).toHaveBeenCalledWith(
55
+ validMetricParams.metricName,
56
+ validMetricParams.options,
57
+ );
58
+ });
59
+
60
+ test("should call createCounter when type is 'counter'", () => {
61
+ mockMeter.createCounter.mockReturnValue("mocked-counter");
62
+
63
+ const result = getMetric("counter", validMetricParams);
64
+
65
+ expect(result).toBe("mocked-counter");
66
+ expect(mockMeter.createCounter).toHaveBeenCalledWith(
67
+ validMetricParams.metricName,
68
+ validMetricParams.options,
69
+ );
70
+ });
71
+
72
+ test("should call createUpDownCounter when type is 'updowncounter'", () => {
73
+ mockMeter.createUpDownCounter.mockReturnValue("mocked-updowncounter");
74
+
75
+ const result = getMetric("updowncounter", validMetricParams);
76
+
77
+ expect(result).toBe("mocked-updowncounter");
78
+ expect(mockMeter.createUpDownCounter).toHaveBeenCalledWith(
79
+ validMetricParams.metricName,
80
+ validMetricParams.options,
81
+ );
82
+ });
83
+
84
+ test("should call createObservableCounter when type is 'async-counter'", () => {
85
+ mockMeter.createObservableCounter.mockReturnValue("mocked-async-counter");
86
+
87
+ const result = getMetric("async-counter", validMetricParams);
88
+
89
+ expect(result).toBe("mocked-async-counter");
90
+ expect(mockMeter.createObservableCounter).toHaveBeenCalledWith(
91
+ validMetricParams.metricName,
92
+ validMetricParams.options,
93
+ );
94
+ });
95
+
96
+ test("should call createObservableUpDownCounter when type is 'async-updowncounter'", () => {
97
+ mockMeter.createObservableUpDownCounter.mockReturnValue(
98
+ "mocked-async-updowncounter",
99
+ );
100
+
101
+ const result = getMetric("async-updowncounter", validMetricParams);
102
+
103
+ expect(result).toBe("mocked-async-updowncounter");
104
+ expect(mockMeter.createObservableUpDownCounter).toHaveBeenCalledWith(
105
+ validMetricParams.metricName,
106
+ validMetricParams.options,
107
+ );
108
+ });
109
+
110
+ test("should call createObservableGauge when type is 'async-gauge'", () => {
111
+ mockMeter.createObservableGauge.mockReturnValue("mocked-async-gauge");
112
+
113
+ const result = getMetric("async-gauge", validMetricParams);
114
+
115
+ expect(result).toBe("mocked-async-gauge");
116
+ expect(mockMeter.createObservableGauge).toHaveBeenCalledWith(
117
+ validMetricParams.metricName,
118
+ validMetricParams.options,
119
+ );
120
+ });
121
+
122
+ test("should throw an error for unsupported metric types", () => {
123
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
124
+ const invalidMetricType = "invalid-type" as any;
125
+
126
+ expect(() => getMetric(invalidMetricType, validMetricParams)).toThrow(
127
+ `Unsupported metric type: ${invalidMetricType}`,
128
+ );
129
+ });
130
+
131
+ test("should return noop metric fallback for null config", async () => {
132
+ const nullMetricParams: MetricsParams = {
133
+ metricName: null!,
134
+ meterName: "",
135
+ };
136
+
137
+ const result = getMetric("async-gauge", nullMetricParams);
138
+
139
+ assert.isNotNull(result);
140
+ assert.equal(result.constructor.name, "NoopObservableGaugeMetric");
141
+ });
142
+ });
@@ -1,15 +1,18 @@
1
1
  import { test, describe, assert, expect } from "vitest";
2
2
  import buildNodeInstrumentation from "../lib/instrumentation.node.js";
3
- import { NodeSDK, logs } from "@opentelemetry/sdk-node";
4
- import { OTLPTraceExporter as GRPC_OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-grpc";
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
- import buildHttpExporters from "../lib/http.js";
6
+ import buildHttpExporters from "../lib/exporter/http.js";
7
+ import {
8
+ BatchSpanProcessor,
9
+ SimpleSpanProcessor,
10
+ } from "@opentelemetry/sdk-trace-base";
11
+ import {
12
+ BatchLogRecordProcessor,
13
+ SimpleLogRecordProcessor,
14
+ } from "@opentelemetry/sdk-logs";
15
+ import { EnrichSpanProcessor } from "../lib/processor/enrich-span-processor.js";
13
16
 
14
17
  describe("verify config settings", () => {
15
18
  const commonConfig = {
@@ -17,72 +20,101 @@ describe("verify config settings", () => {
17
20
  serviceName: "test",
18
21
  };
19
22
 
20
- test("grpc config", () => {
23
+ test("grpc config", async () => {
21
24
  const config: NodeSDKConfig = {
22
25
  ...commonConfig,
23
26
  protocol: "grpc",
27
+ collectorMode: "batch",
24
28
  diagLogLevel: "NONE",
25
29
  };
26
30
 
27
- const sdk: NodeSDK | undefined = buildNodeInstrumentation(config);
31
+ const sdk: NodeSDK | undefined = await buildNodeInstrumentation(config);
28
32
 
29
33
  assert.ok(sdk);
30
34
 
31
35
  const _configuration = sdk["_configuration"];
32
36
  assert.equal(_configuration.serviceName, commonConfig.serviceName);
33
37
 
34
- const traceExporter = _configuration.traceExporter;
35
- assert.equal(
36
- traceExporter["_transport"]["_parameters"]["compression"],
37
- "gzip",
38
- );
39
- assert.ok(traceExporter instanceof GRPC_OTLPTraceExporter);
38
+ const logs = _configuration.logRecordProcessors;
39
+
40
+ assert.equal(logs.length, 2);
41
+ assert.ok(logs[1] instanceof BatchLogRecordProcessor);
42
+
43
+ const spans = _configuration.spanProcessors;
44
+
45
+ assert.equal(spans.length, 2);
46
+ assert.ok(spans[0] instanceof BatchSpanProcessor);
47
+ assert.ok(spans[1] instanceof EnrichSpanProcessor);
40
48
 
41
- const logRecordProcessors = _configuration.logRecordProcessors;
42
- assert.equal(logRecordProcessors.length, 1);
43
- // assert default signals sending mode
44
- assert.ok(logRecordProcessors[0] instanceof logs.BatchLogRecordProcessor);
45
49
  assert.ok(
46
- logRecordProcessors[0]["_exporter"] instanceof GRPC_OTLPLogExporter,
50
+ _configuration.metricReader instanceof
51
+ metrics.PeriodicExportingMetricReader,
47
52
  );
48
-
49
- const metricReader = _configuration.metricReader;
50
- assert.ok(metricReader._exporter instanceof GRPC_OTLPMetricExporter);
51
53
  });
52
54
 
53
- test("http config", () => {
55
+ test("http config", async () => {
54
56
  const config: NodeSDKConfig = {
55
57
  ...commonConfig,
56
58
  protocol: "http",
57
59
  diagLogLevel: "NONE",
58
60
  };
59
61
 
60
- const sdk: NodeSDK | undefined = buildNodeInstrumentation(config);
62
+ const sdk: NodeSDK | undefined = await buildNodeInstrumentation(config);
61
63
  assert.ok(sdk);
62
64
 
63
65
  const _configuration = sdk["_configuration"];
64
66
  assert.equal(_configuration.serviceName, commonConfig.serviceName);
65
67
 
66
- const traceExporter = _configuration.traceExporter;
67
- assert.equal(
68
- traceExporter._transport._transport._parameters.compression,
69
- "gzip",
70
- );
71
- assert.ok(traceExporter instanceof HTTP_OTLPTraceExporter);
68
+ const logs = _configuration.logRecordProcessors;
69
+
70
+ assert.equal(logs.length, 2);
71
+ assert.ok(logs[1] instanceof BatchLogRecordProcessor);
72
+
73
+ const spans = _configuration.spanProcessors;
74
+
75
+ assert.equal(spans.length, 2);
76
+ assert.ok(spans[0] instanceof BatchSpanProcessor);
77
+ assert.ok(spans[1] instanceof EnrichSpanProcessor);
72
78
 
73
- const logRecordProcessors = _configuration.logRecordProcessors;
74
- assert.equal(logRecordProcessors.length, 1);
75
- // assert default signals sending mode
76
- assert.ok(logRecordProcessors[0] instanceof logs.BatchLogRecordProcessor);
77
79
  assert.ok(
78
- logRecordProcessors[0]["_exporter"] instanceof HTTP_OTLPLogExporter,
80
+ _configuration.metricReader instanceof
81
+ metrics.PeriodicExportingMetricReader,
79
82
  );
83
+ });
80
84
 
81
- const metricReader = _configuration.metricReader;
82
- assert.ok(metricReader._exporter instanceof HTTP_OTLPMetricExporter);
85
+ test("console - console config", async () => {
86
+ const config: NodeSDKConfig = {
87
+ ...commonConfig,
88
+ protocol: "console",
89
+ diagLogLevel: "NONE",
90
+ };
91
+
92
+ const sdk: NodeSDK = await buildNodeInstrumentation(config)!;
93
+ assert.ok(sdk);
94
+
95
+ const _configuration = sdk["_configuration"];
96
+ assert.equal(_configuration.serviceName, commonConfig.serviceName);
97
+
98
+ const logs = _configuration.logRecordProcessors;
99
+
100
+ // verify simple log processor for instant console logging
101
+ assert.equal(logs.length, 2);
102
+ assert.ok(logs[1] instanceof SimpleLogRecordProcessor);
103
+
104
+ const spans = _configuration.spanProcessors;
105
+
106
+ assert.equal(spans.length, 2);
107
+ // verify simple span for instant console logging
108
+ assert.ok(spans[0] instanceof SimpleSpanProcessor);
109
+ assert.ok(spans[1] instanceof EnrichSpanProcessor);
110
+
111
+ assert.ok(
112
+ _configuration.metricReader instanceof
113
+ metrics.PeriodicExportingMetricReader,
114
+ );
83
115
  });
84
116
 
85
- test("single log sending config", () => {
117
+ test("single log sending config", async () => {
86
118
  const config: NodeSDKConfig = {
87
119
  ...commonConfig,
88
120
  protocol: "grpc",
@@ -90,15 +122,15 @@ describe("verify config settings", () => {
90
122
  collectorMode: "single",
91
123
  };
92
124
 
93
- const sdk: NodeSDK | undefined = buildNodeInstrumentation(config);
125
+ const sdk: NodeSDK | undefined = await buildNodeInstrumentation(config);
94
126
 
95
127
  assert.ok(sdk);
96
128
 
97
129
  const _configuration = sdk["_configuration"];
98
130
 
99
131
  const logRecordProcessors = _configuration.logRecordProcessors;
100
- assert.equal(logRecordProcessors.length, 1);
101
- assert.ok(logRecordProcessors[0] instanceof logs.SimpleLogRecordProcessor);
132
+ assert.equal(logRecordProcessors.length, 2);
133
+ assert.ok(logRecordProcessors[1] instanceof SimpleLogRecordProcessor);
102
134
  });
103
135
 
104
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
+ });
@@ -0,0 +1,104 @@
1
+ import {
2
+ AttributeValue,
3
+ Context,
4
+ Exception,
5
+ Link,
6
+ Span,
7
+ SpanAttributes,
8
+ SpanContext,
9
+ SpanStatus,
10
+ TimeInput,
11
+ } from "@opentelemetry/api";
12
+ import { describe, expect, it } from "vitest";
13
+ import { EnrichSpanProcessor } from "../../lib/processor/enrich-span-processor.js";
14
+
15
+ class MockSpan implements Span {
16
+ public attributes: Record<string, AttributeValue> = {};
17
+
18
+ spanContext(): SpanContext {
19
+ throw new Error("Method not implemented.");
20
+ }
21
+ setAttribute(key: string, value: AttributeValue): this {
22
+ this.attributes[key] = value;
23
+ return this;
24
+ }
25
+ setAttributes(attributes: SpanAttributes): this {
26
+ throw new Error("Method not implemented.");
27
+ }
28
+ addEvent(
29
+ name: string,
30
+ attributesOrStartTime?: SpanAttributes | TimeInput,
31
+ startTime?: TimeInput,
32
+ ): this {
33
+ throw new Error("Method not implemented.");
34
+ }
35
+ addLink(link: Link): this {
36
+ throw new Error("Method not implemented.");
37
+ }
38
+ addLinks(links: Link[]): this {
39
+ throw new Error("Method not implemented.");
40
+ }
41
+ setStatus(status: SpanStatus): this {
42
+ throw new Error("Method not implemented.");
43
+ }
44
+ updateName(name: string): this {
45
+ throw new Error("Method not implemented.");
46
+ }
47
+ end(endTime?: TimeInput): void {
48
+ throw new Error("Method not implemented.");
49
+ }
50
+ isRecording(): boolean {
51
+ throw new Error("Method not implemented.");
52
+ }
53
+ recordException(exception: Exception, time?: TimeInput): void {
54
+ throw new Error("Method not implemented.");
55
+ }
56
+ }
57
+
58
+ describe("EnrichSpanProcessor", () => {
59
+ it("should set static attributes on span", () => {
60
+ const spanAttributes = {
61
+ key1: "value1",
62
+ key2: 123,
63
+ };
64
+ const processor = new EnrichSpanProcessor(spanAttributes);
65
+ const mockSpan = new MockSpan();
66
+ const mockContext = {} as Context;
67
+
68
+ processor.onStart(mockSpan, mockContext);
69
+
70
+ expect(mockSpan.attributes["key1"]).toBe("value1");
71
+ expect(mockSpan.attributes["key2"]).toBe(123);
72
+ });
73
+
74
+ it("should set dynamic attributes on span", () => {
75
+ const spanAttributes = {
76
+ dynamicKey: () => "dynamicValue",
77
+ };
78
+ const processor = new EnrichSpanProcessor(spanAttributes);
79
+ const mockSpan = new MockSpan();
80
+ const mockContext = {} as Context;
81
+
82
+ processor.onStart(mockSpan, mockContext);
83
+
84
+ expect(mockSpan.attributes["dynamicKey"]).toBe("dynamicValue");
85
+ });
86
+
87
+ it("should not set attributes if none are provided", () => {
88
+ const processor = new EnrichSpanProcessor();
89
+ const mockSpan = new MockSpan();
90
+ const mockContext = {} as Context;
91
+
92
+ processor.onStart(mockSpan, mockContext);
93
+
94
+ expect(mockSpan.attributes["key1"]).toBeUndefined();
95
+ });
96
+
97
+ it("default method, should maintain default behaviour", async () => {
98
+ const processor = new EnrichSpanProcessor();
99
+
100
+ expect(processor.onEnd(null!)).toBeUndefined();
101
+ expect(await processor.shutdown()).toBeUndefined();
102
+ expect(await processor.forceFlush()).toBeUndefined();
103
+ });
104
+ });
@@ -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
+ });