@ogcio/o11y-sdk-node 0.4.2 → 0.6.1
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/sdk-core/index.d.ts +1 -0
- package/dist/sdk-core/index.js +1 -0
- package/dist/sdk-core/lib/index.d.ts +2 -0
- package/dist/sdk-core/lib/index.js +2 -0
- package/dist/sdk-core/lib/redaction/basic-redactor.d.ts +7 -0
- package/dist/sdk-core/lib/redaction/basic-redactor.js +18 -0
- package/dist/sdk-core/lib/redaction/email-redactor.d.ts +8 -0
- package/dist/sdk-core/lib/redaction/email-redactor.js +17 -0
- package/dist/sdk-core/lib/redaction/index.d.ts +9 -0
- package/dist/sdk-core/lib/redaction/index.js +4 -0
- package/dist/sdk-core/lib/redaction/ip-redactor.d.ts +9 -0
- package/dist/sdk-core/lib/redaction/ip-redactor.js +23 -0
- package/dist/sdk-core/lib/redaction/ppsn-redactor.d.ts +8 -0
- package/dist/sdk-core/lib/redaction/ppsn-redactor.js +17 -0
- package/dist/sdk-core/lib/utils/data-structures.d.ts +15 -0
- package/dist/{lib/internals/redaction/pii-detection.js → sdk-core/lib/utils/data-structures.js} +4 -27
- package/dist/sdk-core/lib/utils/index.d.ts +2 -0
- package/dist/sdk-core/lib/utils/index.js +2 -0
- package/dist/sdk-core/lib/utils/string-decoding.d.ts +7 -0
- package/dist/sdk-core/lib/utils/string-decoding.js +22 -0
- package/dist/{index.d.ts → sdk-node/index.d.ts} +1 -0
- package/dist/{index.js → sdk-node/index.js} +1 -0
- package/dist/{lib → sdk-node/lib}/config-manager.d.ts +1 -1
- package/dist/sdk-node/lib/exporter/console.d.ts +3 -0
- package/dist/sdk-node/lib/exporter/grpc.d.ts +3 -0
- package/dist/sdk-node/lib/exporter/http.d.ts +3 -0
- package/dist/{lib → sdk-node/lib}/exporter/index.d.ts +2 -2
- package/dist/{lib → sdk-node/lib}/exporter/pii-exporter-decorator.d.ts +5 -5
- package/dist/{lib → sdk-node/lib}/exporter/pii-exporter-decorator.js +6 -2
- package/dist/sdk-node/lib/exporter/processor-config.d.ts +7 -0
- package/dist/{lib → sdk-node/lib}/exporter/processor-config.js +4 -0
- package/dist/{lib → sdk-node/lib}/index.d.ts +11 -0
- package/dist/{lib → sdk-node/lib}/instrumentation.node.js +1 -1
- package/dist/sdk-node/lib/internals/redaction/redactors/email.d.ts +8 -0
- package/dist/sdk-node/lib/internals/redaction/redactors/email.js +19 -0
- package/dist/sdk-node/lib/internals/redaction/redactors/index.d.ts +16 -0
- package/dist/sdk-node/lib/internals/redaction/redactors/index.js +13 -0
- package/dist/sdk-node/lib/internals/redaction/redactors/ip.d.ts +8 -0
- package/dist/sdk-node/lib/internals/redaction/redactors/ip.js +20 -0
- package/dist/sdk-node/lib/internals/redaction/redactors/ppsn.d.ts +8 -0
- package/dist/sdk-node/lib/internals/redaction/redactors/ppsn.js +18 -0
- package/dist/{lib → sdk-node/lib}/metrics.d.ts +1 -1
- package/dist/{lib → sdk-node/lib}/processor/enrich-logger-processor.d.ts +3 -3
- package/dist/{lib → sdk-node/lib}/processor/enrich-span-processor.d.ts +3 -3
- package/dist/sdk-node/lib/processor/nextjs-logger-processor.d.ts +7 -0
- package/dist/sdk-node/lib/processor/nextjs-logger-processor.js +30 -0
- package/dist/sdk-node/lib/processor/nextjs-span-processor.d.ts +8 -0
- package/dist/sdk-node/lib/processor/nextjs-span-processor.js +25 -0
- package/dist/{lib → sdk-node/lib}/resource.d.ts +2 -2
- package/dist/{lib → sdk-node/lib}/traces.d.ts +1 -1
- package/dist/{lib → sdk-node/lib}/traces.js +1 -1
- package/dist/{lib → sdk-node/lib}/url-sampler.d.ts +3 -3
- package/dist/{lib → sdk-node/lib}/utils.d.ts +1 -1
- package/dist/sdk-node/package.json +62 -0
- package/package.json +28 -25
- package/CHANGELOG.md +0 -233
- package/dist/lib/exporter/console.d.ts +0 -3
- package/dist/lib/exporter/grpc.d.ts +0 -3
- package/dist/lib/exporter/http.d.ts +0 -3
- package/dist/lib/exporter/processor-config.d.ts +0 -5
- package/dist/lib/internals/redaction/pii-detection.d.ts +0 -25
- package/dist/lib/internals/redaction/redactors/email.d.ts +0 -8
- package/dist/lib/internals/redaction/redactors/email.js +0 -48
- package/dist/lib/internals/redaction/redactors/index.d.ts +0 -4
- package/dist/lib/internals/redaction/redactors/index.js +0 -6
- package/dist/lib/internals/redaction/redactors/ip.d.ts +0 -10
- package/dist/lib/internals/redaction/redactors/ip.js +0 -54
- package/dist/lib/internals/shared-metrics.d.ts +0 -7
- package/dist/lib/internals/shared-metrics.js +0 -18
- package/dist/package.json +0 -59
- package/dist/vitest.config.d.ts +0 -2
- package/dist/vitest.config.js +0 -45
- package/index.ts +0 -9
- package/lib/config-manager.ts +0 -12
- package/lib/exporter/console.ts +0 -33
- package/lib/exporter/grpc.ts +0 -65
- package/lib/exporter/http.ts +0 -56
- package/lib/exporter/index.ts +0 -9
- package/lib/exporter/pii-exporter-decorator.ts +0 -187
- package/lib/exporter/processor-config.ts +0 -23
- package/lib/index.ts +0 -118
- package/lib/instrumentation.node.ts +0 -115
- package/lib/internals/hooks.ts +0 -14
- package/lib/internals/redaction/pii-detection.ts +0 -113
- package/lib/internals/redaction/redactors/email.ts +0 -58
- package/lib/internals/redaction/redactors/index.ts +0 -12
- package/lib/internals/redaction/redactors/ip.ts +0 -68
- package/lib/internals/shared-metrics.ts +0 -34
- package/lib/metrics.ts +0 -75
- package/lib/processor/enrich-logger-processor.ts +0 -34
- package/lib/processor/enrich-span-processor.ts +0 -39
- package/lib/resource.ts +0 -30
- package/lib/traces.ts +0 -78
- package/lib/url-sampler.ts +0 -52
- package/lib/utils.ts +0 -22
- package/test/config-manager.test.ts +0 -34
- package/test/exporter/pii-exporter-decorator.test.ts +0 -88
- package/test/index.test.ts +0 -70
- package/test/integration/README.md +0 -74
- package/test/integration/docker-utils.sh +0 -214
- package/test/integration/main.sh +0 -52
- package/test/integration/teardown.sh +0 -7
- package/test/integration/test_fastify-o11y-pii-enabled/http-tracing.integration.test.ts +0 -56
- package/test/integration/test_fastify-o11y-pii-enabled/pii.integration.test.ts +0 -68
- package/test/integration/test_fastify-o11y-pii-enabled/run.sh +0 -42
- package/test/integration/test_without-o11y/run.sh +0 -30
- package/test/integration/test_without-o11y/verify-status.integration.test.ts +0 -32
- package/test/internals/hooks.test.ts +0 -45
- package/test/internals/pii-detection.test.ts +0 -265
- package/test/internals/redactors/email.test.ts +0 -81
- package/test/internals/redactors/ip.test.ts +0 -93
- package/test/internals/shared-metrics.test.ts +0 -34
- package/test/metrics.test.ts +0 -142
- package/test/node-config.test.ts +0 -190
- package/test/processor/enrich-logger-processor.test.ts +0 -58
- package/test/processor/enrich-span-processor.test.ts +0 -52
- package/test/resource.test.ts +0 -33
- package/test/traces/active-span.test.ts +0 -26
- package/test/traces/with-span.test.ts +0 -356
- package/test/url-sampler.test.ts +0 -215
- package/test/utils/alloy-log-parser.ts +0 -53
- package/test/utils/mock-signals.ts +0 -144
- package/test/validation.test.ts +0 -103
- package/tsconfig.json +0 -15
- package/vitest.config.ts +0 -46
- /package/dist/{lib → sdk-node/lib}/config-manager.js +0 -0
- /package/dist/{lib → sdk-node/lib}/exporter/console.js +0 -0
- /package/dist/{lib → sdk-node/lib}/exporter/grpc.js +0 -0
- /package/dist/{lib → sdk-node/lib}/exporter/http.js +0 -0
- /package/dist/{lib → sdk-node/lib}/exporter/index.js +0 -0
- /package/dist/{lib → sdk-node/lib}/index.js +0 -0
- /package/dist/{lib → sdk-node/lib}/instrumentation.node.d.ts +0 -0
- /package/dist/{lib → sdk-node/lib}/internals/hooks.d.ts +0 -0
- /package/dist/{lib → sdk-node/lib}/internals/hooks.js +0 -0
- /package/dist/{lib → sdk-node/lib}/metrics.js +0 -0
- /package/dist/{lib → sdk-node/lib}/processor/enrich-logger-processor.js +0 -0
- /package/dist/{lib → sdk-node/lib}/processor/enrich-span-processor.js +0 -0
- /package/dist/{lib → sdk-node/lib}/resource.js +0 -0
- /package/dist/{lib → sdk-node/lib}/url-sampler.js +0 -0
- /package/dist/{lib → sdk-node/lib}/utils.js +0 -0
|
@@ -1,356 +0,0 @@
|
|
|
1
|
-
import { Span, SpanOptions, SpanStatusCode, trace } from "@opentelemetry/api";
|
|
2
|
-
import { TraceState } from "@opentelemetry/core";
|
|
3
|
-
import { NodeSDK } from "@opentelemetry/sdk-node";
|
|
4
|
-
import {
|
|
5
|
-
InMemorySpanExporter,
|
|
6
|
-
SimpleSpanProcessor,
|
|
7
|
-
SpanProcessor,
|
|
8
|
-
} from "@opentelemetry/sdk-trace-base";
|
|
9
|
-
import { afterAll, afterEach, beforeAll, describe, expect, it } from "vitest";
|
|
10
|
-
import { setNodeSdkConfig } from "../../lib/config-manager.js";
|
|
11
|
-
import { getActiveSpan, withSpan } from "../../lib/traces.js";
|
|
12
|
-
|
|
13
|
-
describe("withSpan with opentelemetry not initialized", () => {
|
|
14
|
-
it("should handle noop span", async ({}) => {
|
|
15
|
-
let capturedSpan: Span;
|
|
16
|
-
|
|
17
|
-
await withSpan({
|
|
18
|
-
spanName: "test-sync-span",
|
|
19
|
-
fn: (span: Span) => {
|
|
20
|
-
capturedSpan = span;
|
|
21
|
-
},
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
expect(capturedSpan).not.toBeNull();
|
|
25
|
-
expect(capturedSpan.constructor.name).toBe("NonRecordingSpan");
|
|
26
|
-
});
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
describe("withSpan", () => {
|
|
30
|
-
let memoryExporter: InMemorySpanExporter;
|
|
31
|
-
let spanProcessor: SpanProcessor;
|
|
32
|
-
let sdk: NodeSDK;
|
|
33
|
-
|
|
34
|
-
beforeAll(() => {
|
|
35
|
-
memoryExporter = new InMemorySpanExporter();
|
|
36
|
-
spanProcessor = new SimpleSpanProcessor(memoryExporter);
|
|
37
|
-
sdk = new NodeSDK({
|
|
38
|
-
spanProcessors: [spanProcessor],
|
|
39
|
-
instrumentations: [],
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
setNodeSdkConfig({
|
|
43
|
-
collectorUrl: "http://localhost:4317",
|
|
44
|
-
});
|
|
45
|
-
sdk.start();
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
afterEach(async () => {
|
|
49
|
-
// Flush any remaining spans
|
|
50
|
-
await spanProcessor.forceFlush();
|
|
51
|
-
// Clean up
|
|
52
|
-
memoryExporter.reset();
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
afterAll(async () => {
|
|
56
|
-
await sdk.shutdown();
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
it("should handle simple synchronous usage", async ({}) => {
|
|
60
|
-
let capturedSpan: Span;
|
|
61
|
-
|
|
62
|
-
await withSpan({
|
|
63
|
-
spanName: "test-sync-span",
|
|
64
|
-
fn: (span: Span) => {
|
|
65
|
-
capturedSpan = span;
|
|
66
|
-
},
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
await spanProcessor.forceFlush();
|
|
70
|
-
const spans = memoryExporter.getFinishedSpans();
|
|
71
|
-
expect(spans).toHaveLength(1);
|
|
72
|
-
expect(spans[0].name).toBe("test-sync-span");
|
|
73
|
-
expect(spans[0].status.code).toBe(SpanStatusCode.OK);
|
|
74
|
-
expect(capturedSpan).toBeTruthy();
|
|
75
|
-
expect(capturedSpan.spanContext().traceId).toBe(
|
|
76
|
-
spans[0].spanContext().traceId,
|
|
77
|
-
);
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
it("should handle synchronous functions that throw errors", async ({}) => {
|
|
81
|
-
const error = new Error("Sync error");
|
|
82
|
-
|
|
83
|
-
await expect(
|
|
84
|
-
withSpan({
|
|
85
|
-
spanName: "test-sync-error-span",
|
|
86
|
-
fn: () => {
|
|
87
|
-
throw error;
|
|
88
|
-
},
|
|
89
|
-
}),
|
|
90
|
-
).rejects.toThrow(error.message);
|
|
91
|
-
|
|
92
|
-
await spanProcessor.forceFlush();
|
|
93
|
-
const spans = memoryExporter.getFinishedSpans();
|
|
94
|
-
expect(spans).toHaveLength(1);
|
|
95
|
-
expect(spans[0].name).toBe("test-sync-error-span");
|
|
96
|
-
expect(spans[0].status.code).toBe(SpanStatusCode.ERROR);
|
|
97
|
-
expect(spans[0].status.message).toBe(error.message);
|
|
98
|
-
expect(spans[0].events).toHaveLength(1);
|
|
99
|
-
expect(spans[0].events[0].name).toBe("exception");
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
it("should handle asynchronous functions correctly", async ({}) => {
|
|
103
|
-
let capturedSpan: Span;
|
|
104
|
-
|
|
105
|
-
await withSpan({
|
|
106
|
-
spanName: "test-async-span",
|
|
107
|
-
fn: async (span: Span) => {
|
|
108
|
-
capturedSpan = span;
|
|
109
|
-
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
110
|
-
return "async-result";
|
|
111
|
-
},
|
|
112
|
-
});
|
|
113
|
-
|
|
114
|
-
await spanProcessor.forceFlush();
|
|
115
|
-
const spans = memoryExporter.getFinishedSpans();
|
|
116
|
-
expect(spans).toHaveLength(1);
|
|
117
|
-
expect(spans[0].name).toBe("test-async-span");
|
|
118
|
-
expect(spans[0].status.code).toBe(SpanStatusCode.OK);
|
|
119
|
-
expect(capturedSpan).toBeTruthy();
|
|
120
|
-
expect(capturedSpan.spanContext().traceId).toBe(
|
|
121
|
-
spans[0].spanContext().traceId,
|
|
122
|
-
);
|
|
123
|
-
});
|
|
124
|
-
|
|
125
|
-
it("should handle asynchronous functions that reject", async () => {
|
|
126
|
-
const error = new Error("Async error");
|
|
127
|
-
|
|
128
|
-
await expect(
|
|
129
|
-
withSpan({
|
|
130
|
-
spanName: "test-async-error-span",
|
|
131
|
-
fn: async () => {
|
|
132
|
-
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
133
|
-
throw error;
|
|
134
|
-
},
|
|
135
|
-
}),
|
|
136
|
-
).rejects.toThrow(error.message);
|
|
137
|
-
|
|
138
|
-
await spanProcessor.forceFlush();
|
|
139
|
-
const spans = memoryExporter.getFinishedSpans();
|
|
140
|
-
expect(spans).toHaveLength(1);
|
|
141
|
-
expect(spans[0].name).toBe("test-async-error-span");
|
|
142
|
-
expect(spans[0].status.code).toBe(SpanStatusCode.ERROR);
|
|
143
|
-
expect(spans[0].status.message).toBe(error.message);
|
|
144
|
-
expect(spans[0].events).toHaveLength(1);
|
|
145
|
-
expect(spans[0].events[0].name).toBe("exception");
|
|
146
|
-
});
|
|
147
|
-
|
|
148
|
-
it("should handle non-Error exceptions", async () => {
|
|
149
|
-
const nonErrorException = { message: "Not an error object", code: 500 };
|
|
150
|
-
|
|
151
|
-
await expect(
|
|
152
|
-
withSpan({
|
|
153
|
-
spanName: "test-non-error-span",
|
|
154
|
-
fn: () => {
|
|
155
|
-
throw nonErrorException;
|
|
156
|
-
},
|
|
157
|
-
}),
|
|
158
|
-
).rejects.toEqual(nonErrorException);
|
|
159
|
-
|
|
160
|
-
const spans = memoryExporter.getFinishedSpans();
|
|
161
|
-
expect(spans).toHaveLength(1);
|
|
162
|
-
expect(spans[0].status.code).toBe(SpanStatusCode.ERROR);
|
|
163
|
-
expect(spans[0].status.message).toBe(JSON.stringify(nonErrorException));
|
|
164
|
-
expect(spans[0].events).toHaveLength(1);
|
|
165
|
-
expect(spans[0].events[0].name).toBe("exception");
|
|
166
|
-
});
|
|
167
|
-
|
|
168
|
-
it("should ensure span is ended even when errors occur", async () => {
|
|
169
|
-
const error = new Error("Test error");
|
|
170
|
-
|
|
171
|
-
await expect(
|
|
172
|
-
withSpan({
|
|
173
|
-
spanName: "test-finally-span",
|
|
174
|
-
fn: () => {
|
|
175
|
-
throw error;
|
|
176
|
-
},
|
|
177
|
-
}),
|
|
178
|
-
).rejects.toThrow("Test error");
|
|
179
|
-
|
|
180
|
-
const spans = memoryExporter.getFinishedSpans();
|
|
181
|
-
expect(spans).toHaveLength(1);
|
|
182
|
-
expect(spans[0].ended).toBe(true);
|
|
183
|
-
});
|
|
184
|
-
|
|
185
|
-
it("should pass span options to tracer", async () => {
|
|
186
|
-
const spanOptions: SpanOptions = {
|
|
187
|
-
attributes: { "custom.attribute": "custom-value" },
|
|
188
|
-
kind: 1,
|
|
189
|
-
};
|
|
190
|
-
|
|
191
|
-
await withSpan({
|
|
192
|
-
spanName: "test-options-span",
|
|
193
|
-
spanOptions,
|
|
194
|
-
fn: () => "result",
|
|
195
|
-
});
|
|
196
|
-
|
|
197
|
-
await spanProcessor.forceFlush();
|
|
198
|
-
const spans = memoryExporter.getFinishedSpans();
|
|
199
|
-
expect(spans).toHaveLength(1);
|
|
200
|
-
expect(spans[0].attributes["custom.attribute"]).toBe("custom-value");
|
|
201
|
-
expect(spans[0].kind).toBe(1);
|
|
202
|
-
});
|
|
203
|
-
|
|
204
|
-
it("should use custom tracer name", async () => {
|
|
205
|
-
const customTracerName = "custom-tracer";
|
|
206
|
-
|
|
207
|
-
await withSpan({
|
|
208
|
-
traceName: customTracerName,
|
|
209
|
-
spanName: "test-custom-tracer-span",
|
|
210
|
-
fn: () => "result",
|
|
211
|
-
});
|
|
212
|
-
|
|
213
|
-
await spanProcessor.forceFlush();
|
|
214
|
-
const spans = memoryExporter.getFinishedSpans();
|
|
215
|
-
expect(spans).toHaveLength(1);
|
|
216
|
-
expect(spans[0].name).toBe("test-custom-tracer-span");
|
|
217
|
-
expect(spans[0].instrumentationScope.name).toBe(customTracerName);
|
|
218
|
-
});
|
|
219
|
-
|
|
220
|
-
it("should use default tracer name when not specified", async () => {
|
|
221
|
-
await withSpan({
|
|
222
|
-
spanName: "test-default-tracer-span",
|
|
223
|
-
fn: () => "result",
|
|
224
|
-
});
|
|
225
|
-
|
|
226
|
-
await spanProcessor.forceFlush();
|
|
227
|
-
const defaultSpans = memoryExporter.getFinishedSpans();
|
|
228
|
-
expect(defaultSpans).toHaveLength(1);
|
|
229
|
-
expect(defaultSpans[0].name).toBe("test-default-tracer-span");
|
|
230
|
-
expect(defaultSpans[0].instrumentationScope.name).toBe("o11y-sdk");
|
|
231
|
-
|
|
232
|
-
memoryExporter.reset();
|
|
233
|
-
|
|
234
|
-
setNodeSdkConfig({
|
|
235
|
-
collectorUrl: "",
|
|
236
|
-
serviceName: "test-service",
|
|
237
|
-
serviceVersion: "v1.0.0",
|
|
238
|
-
});
|
|
239
|
-
|
|
240
|
-
await withSpan({
|
|
241
|
-
spanName: "test-default-tracer-span",
|
|
242
|
-
fn: () => "result",
|
|
243
|
-
});
|
|
244
|
-
await spanProcessor.forceFlush();
|
|
245
|
-
const spans = memoryExporter.getFinishedSpans();
|
|
246
|
-
expect(spans).toHaveLength(1);
|
|
247
|
-
expect(spans[0].name).toBe("test-default-tracer-span");
|
|
248
|
-
expect(spans[0].instrumentationScope.name).toBe("test-service");
|
|
249
|
-
expect(spans[0].instrumentationScope.version).toBe("v1.0.0");
|
|
250
|
-
});
|
|
251
|
-
|
|
252
|
-
it("should allow function to interact with span context", async () => {
|
|
253
|
-
let receivedSpan: Span;
|
|
254
|
-
|
|
255
|
-
await withSpan({
|
|
256
|
-
spanName: "test-span-context",
|
|
257
|
-
fn: (span: Span) => {
|
|
258
|
-
receivedSpan = span;
|
|
259
|
-
span.spanContext().traceState = new TraceState(
|
|
260
|
-
"alpha=aaaaaaaaaaaa,bravo=bbbbbbbbbbbb",
|
|
261
|
-
);
|
|
262
|
-
},
|
|
263
|
-
});
|
|
264
|
-
|
|
265
|
-
await spanProcessor.forceFlush();
|
|
266
|
-
const spans = memoryExporter.getFinishedSpans();
|
|
267
|
-
expect(spans).toHaveLength(1);
|
|
268
|
-
expect(receivedSpan).toBeTruthy();
|
|
269
|
-
expect(receivedSpan.spanContext().traceId).toBe(
|
|
270
|
-
spans[0].spanContext().traceId,
|
|
271
|
-
);
|
|
272
|
-
expect(receivedSpan.spanContext().spanId).toBe(
|
|
273
|
-
spans[0].spanContext().spanId,
|
|
274
|
-
);
|
|
275
|
-
expect(spans[0].spanContext().traceState.serialize()).toStrictEqual(
|
|
276
|
-
"alpha=aaaaaaaaaaaa,bravo=bbbbbbbbbbbb",
|
|
277
|
-
);
|
|
278
|
-
});
|
|
279
|
-
|
|
280
|
-
it("should preserve context across setTimeout", async () => {
|
|
281
|
-
await withSpan({
|
|
282
|
-
spanName: "test-timeout-context",
|
|
283
|
-
fn: async (span: Span) => {
|
|
284
|
-
return new Promise((resolve) => {
|
|
285
|
-
setTimeout(() => {
|
|
286
|
-
getActiveSpan().addEvent("promise-resolved", {
|
|
287
|
-
result: "timeout-result",
|
|
288
|
-
});
|
|
289
|
-
resolve("timeout-result");
|
|
290
|
-
}, 10);
|
|
291
|
-
});
|
|
292
|
-
},
|
|
293
|
-
});
|
|
294
|
-
|
|
295
|
-
let newSpan: Span;
|
|
296
|
-
await trace
|
|
297
|
-
.getTracer("some-tracer")
|
|
298
|
-
.startActiveSpan("other-context", async (span) => {
|
|
299
|
-
newSpan = span;
|
|
300
|
-
span.addEvent("other-context-event", {
|
|
301
|
-
result: "other-context-result",
|
|
302
|
-
});
|
|
303
|
-
});
|
|
304
|
-
|
|
305
|
-
newSpan.addEvent("another-context-event", {
|
|
306
|
-
result: "another-context-result",
|
|
307
|
-
});
|
|
308
|
-
newSpan.setStatus({ code: SpanStatusCode.OK });
|
|
309
|
-
newSpan.end();
|
|
310
|
-
await spanProcessor.forceFlush();
|
|
311
|
-
const spans = memoryExporter.getFinishedSpans();
|
|
312
|
-
expect(spans).toHaveLength(2);
|
|
313
|
-
|
|
314
|
-
const timeoutSpan = spans.find((s) => s.name === "test-timeout-context");
|
|
315
|
-
expect(timeoutSpan.status.code).toBe(SpanStatusCode.OK);
|
|
316
|
-
expect(timeoutSpan.events).toHaveLength(1);
|
|
317
|
-
expect(timeoutSpan.events[0].name).toStrictEqual("promise-resolved");
|
|
318
|
-
|
|
319
|
-
const otherTrackedSpan = spans.find((s) => s.name === "other-context");
|
|
320
|
-
expect(otherTrackedSpan.status.code).toBe(SpanStatusCode.OK);
|
|
321
|
-
expect(otherTrackedSpan.events).toHaveLength(2);
|
|
322
|
-
expect(otherTrackedSpan.events[0].name).toStrictEqual(
|
|
323
|
-
"other-context-event",
|
|
324
|
-
);
|
|
325
|
-
expect(otherTrackedSpan.events[1].name).toStrictEqual(
|
|
326
|
-
"another-context-event",
|
|
327
|
-
);
|
|
328
|
-
});
|
|
329
|
-
|
|
330
|
-
it("should handle nested spans correctly", async () => {
|
|
331
|
-
await withSpan({
|
|
332
|
-
spanName: "outer-span",
|
|
333
|
-
fn: async () => {
|
|
334
|
-
await withSpan({
|
|
335
|
-
spanName: "inner-span",
|
|
336
|
-
fn: async () => {
|
|
337
|
-
await new Promise((resolve) => setTimeout(resolve, 1));
|
|
338
|
-
},
|
|
339
|
-
});
|
|
340
|
-
},
|
|
341
|
-
});
|
|
342
|
-
|
|
343
|
-
await spanProcessor.forceFlush();
|
|
344
|
-
const spans = memoryExporter.getFinishedSpans();
|
|
345
|
-
expect(spans).toHaveLength(2);
|
|
346
|
-
|
|
347
|
-
const innerSpan = spans.find((s) => s.name === "inner-span");
|
|
348
|
-
const outerSpan = spans.find((s) => s.name === "outer-span");
|
|
349
|
-
|
|
350
|
-
expect(innerSpan).toBeTruthy();
|
|
351
|
-
expect(outerSpan).toBeTruthy();
|
|
352
|
-
expect(innerSpan!.parentSpanContext.spanId).toBe(
|
|
353
|
-
outerSpan!.spanContext().spanId,
|
|
354
|
-
);
|
|
355
|
-
});
|
|
356
|
-
});
|
package/test/url-sampler.test.ts
DELETED
|
@@ -1,215 +0,0 @@
|
|
|
1
|
-
import { Context } from "@opentelemetry/api";
|
|
2
|
-
import {
|
|
3
|
-
SamplingDecision,
|
|
4
|
-
SamplingResult,
|
|
5
|
-
} from "@opentelemetry/sdk-trace-base";
|
|
6
|
-
import { describe, expect, test, vi } from "vitest";
|
|
7
|
-
import { UrlSampler } from "../lib/url-sampler";
|
|
8
|
-
|
|
9
|
-
describe("url sampler", () => {
|
|
10
|
-
// mock sampler to be sure every trace after UrlSamper has RECORD status
|
|
11
|
-
const mockSampler = {
|
|
12
|
-
shouldSample: vi
|
|
13
|
-
.fn()
|
|
14
|
-
.mockImplementation(
|
|
15
|
-
(_context, _traceId, _spanName, _spanKind, attributes, _links) => {
|
|
16
|
-
return {
|
|
17
|
-
decision: SamplingDecision.RECORD,
|
|
18
|
-
attributes: attributes,
|
|
19
|
-
} as SamplingResult;
|
|
20
|
-
},
|
|
21
|
-
),
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
test("should add custom span attributes to trace", async () => {
|
|
25
|
-
const sampler: UrlSampler = new UrlSampler(
|
|
26
|
-
[
|
|
27
|
-
{
|
|
28
|
-
type: "endsWith",
|
|
29
|
-
url: "/health",
|
|
30
|
-
},
|
|
31
|
-
],
|
|
32
|
-
mockSampler,
|
|
33
|
-
{
|
|
34
|
-
"signal.namespace": "unittest",
|
|
35
|
-
"signal.callback.result": () => "test",
|
|
36
|
-
},
|
|
37
|
-
);
|
|
38
|
-
|
|
39
|
-
expect(sampler).not.toBeNull();
|
|
40
|
-
|
|
41
|
-
const result = sampler.shouldSample(
|
|
42
|
-
{} as Context,
|
|
43
|
-
"traceId",
|
|
44
|
-
"span",
|
|
45
|
-
0,
|
|
46
|
-
{ "http.target": "/track" },
|
|
47
|
-
[],
|
|
48
|
-
);
|
|
49
|
-
|
|
50
|
-
expect(sampler.toString()).toBe("UrlSampler");
|
|
51
|
-
expect(result.decision).toBe(SamplingDecision.RECORD);
|
|
52
|
-
expect(result.attributes).not.toBeNull();
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
test("should not record trace about /health api", async () => {
|
|
56
|
-
const sampler: UrlSampler = new UrlSampler(
|
|
57
|
-
[
|
|
58
|
-
{
|
|
59
|
-
type: "endsWith",
|
|
60
|
-
url: "/health",
|
|
61
|
-
},
|
|
62
|
-
],
|
|
63
|
-
mockSampler,
|
|
64
|
-
);
|
|
65
|
-
|
|
66
|
-
const result = sampler.shouldSample(
|
|
67
|
-
{} as Context,
|
|
68
|
-
"traceId",
|
|
69
|
-
"span",
|
|
70
|
-
0,
|
|
71
|
-
{ "http.target": "/health" },
|
|
72
|
-
[],
|
|
73
|
-
);
|
|
74
|
-
|
|
75
|
-
expect(sampler.toString()).toBe("UrlSampler");
|
|
76
|
-
expect(result.decision).toBe(SamplingDecision.NOT_RECORD);
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
test("should record every other trace which is not /health api", async () => {
|
|
80
|
-
const sampler: UrlSampler = new UrlSampler(
|
|
81
|
-
[
|
|
82
|
-
{
|
|
83
|
-
type: "endsWith",
|
|
84
|
-
url: "/health",
|
|
85
|
-
},
|
|
86
|
-
],
|
|
87
|
-
mockSampler,
|
|
88
|
-
);
|
|
89
|
-
|
|
90
|
-
let result = sampler.shouldSample(
|
|
91
|
-
{} as Context,
|
|
92
|
-
"traceId",
|
|
93
|
-
"span",
|
|
94
|
-
0,
|
|
95
|
-
{ "http.target": "/test" },
|
|
96
|
-
[],
|
|
97
|
-
);
|
|
98
|
-
|
|
99
|
-
expect(result.decision).toBe(SamplingDecision.RECORD);
|
|
100
|
-
|
|
101
|
-
result = sampler.shouldSample(
|
|
102
|
-
{} as Context,
|
|
103
|
-
"traceId",
|
|
104
|
-
"span",
|
|
105
|
-
0,
|
|
106
|
-
{ "http.target": "/another/url" },
|
|
107
|
-
[],
|
|
108
|
-
);
|
|
109
|
-
|
|
110
|
-
expect(result.decision).toBe(SamplingDecision.RECORD);
|
|
111
|
-
});
|
|
112
|
-
|
|
113
|
-
test("operator 'includes', should not record every trace which include /block in url", async () => {
|
|
114
|
-
const sampler: UrlSampler = new UrlSampler(
|
|
115
|
-
[
|
|
116
|
-
{
|
|
117
|
-
type: "includes",
|
|
118
|
-
url: "/block",
|
|
119
|
-
},
|
|
120
|
-
],
|
|
121
|
-
mockSampler,
|
|
122
|
-
);
|
|
123
|
-
|
|
124
|
-
expect(sampler).not.toBeNull();
|
|
125
|
-
|
|
126
|
-
const result = sampler.shouldSample(
|
|
127
|
-
{} as Context,
|
|
128
|
-
"traceId",
|
|
129
|
-
"span",
|
|
130
|
-
0,
|
|
131
|
-
{ "http.target": "/namespace/block/example/12" },
|
|
132
|
-
[],
|
|
133
|
-
);
|
|
134
|
-
|
|
135
|
-
expect(sampler.toString()).toBe("UrlSampler");
|
|
136
|
-
expect(result.decision).toBe(SamplingDecision.NOT_RECORD);
|
|
137
|
-
});
|
|
138
|
-
|
|
139
|
-
test("operator 'endsWith', should not record only trace which ends with /block in url", async () => {
|
|
140
|
-
const sampler: UrlSampler = new UrlSampler(
|
|
141
|
-
[
|
|
142
|
-
{
|
|
143
|
-
type: "endsWith",
|
|
144
|
-
url: "/block",
|
|
145
|
-
},
|
|
146
|
-
],
|
|
147
|
-
mockSampler,
|
|
148
|
-
);
|
|
149
|
-
|
|
150
|
-
expect(sampler).not.toBeNull();
|
|
151
|
-
|
|
152
|
-
// expect traced with block in the URL middle
|
|
153
|
-
let result = sampler.shouldSample(
|
|
154
|
-
{} as Context,
|
|
155
|
-
"traceId",
|
|
156
|
-
"span",
|
|
157
|
-
0,
|
|
158
|
-
{ "http.target": "/namespace/block/example/12" },
|
|
159
|
-
[],
|
|
160
|
-
);
|
|
161
|
-
|
|
162
|
-
expect(sampler.toString()).toBe("UrlSampler");
|
|
163
|
-
expect(result.decision).toBe(SamplingDecision.RECORD);
|
|
164
|
-
|
|
165
|
-
// should stop trace with block at the end
|
|
166
|
-
result = sampler.shouldSample(
|
|
167
|
-
{} as Context,
|
|
168
|
-
"traceId",
|
|
169
|
-
"span",
|
|
170
|
-
0,
|
|
171
|
-
{ "http.target": "/namespace/example/block" },
|
|
172
|
-
[],
|
|
173
|
-
);
|
|
174
|
-
|
|
175
|
-
expect(sampler.toString()).toBe("UrlSampler");
|
|
176
|
-
expect(result.decision).toBe(SamplingDecision.NOT_RECORD);
|
|
177
|
-
});
|
|
178
|
-
|
|
179
|
-
test("operator 'equals', should not record trace which is equal to /block in url", async () => {
|
|
180
|
-
const sampler: UrlSampler = new UrlSampler(
|
|
181
|
-
[
|
|
182
|
-
{
|
|
183
|
-
type: "equals",
|
|
184
|
-
url: "/block",
|
|
185
|
-
},
|
|
186
|
-
],
|
|
187
|
-
mockSampler,
|
|
188
|
-
);
|
|
189
|
-
|
|
190
|
-
expect(sampler).not.toBeNull();
|
|
191
|
-
|
|
192
|
-
let result = sampler.shouldSample(
|
|
193
|
-
{} as Context,
|
|
194
|
-
"traceId",
|
|
195
|
-
"span",
|
|
196
|
-
0,
|
|
197
|
-
{ "http.target": "/namespace/block/example/12" },
|
|
198
|
-
[],
|
|
199
|
-
);
|
|
200
|
-
|
|
201
|
-
expect(sampler.toString()).toBe("UrlSampler");
|
|
202
|
-
expect(result.decision).toBe(SamplingDecision.RECORD);
|
|
203
|
-
|
|
204
|
-
result = sampler.shouldSample(
|
|
205
|
-
{} as Context,
|
|
206
|
-
"traceId",
|
|
207
|
-
"span",
|
|
208
|
-
0,
|
|
209
|
-
{ "http.target": "/block" },
|
|
210
|
-
[],
|
|
211
|
-
);
|
|
212
|
-
|
|
213
|
-
expect(result.decision).toBe(SamplingDecision.NOT_RECORD);
|
|
214
|
-
});
|
|
215
|
-
});
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
export function parseLog(
|
|
2
|
-
log: string,
|
|
3
|
-
): Record<string, object | string | number> {
|
|
4
|
-
const logArray = log
|
|
5
|
-
.split("\\n")
|
|
6
|
-
.map((line) => line.trim())
|
|
7
|
-
.filter((line) => line);
|
|
8
|
-
|
|
9
|
-
const jsonObject: Record<string, object | string | number> = {};
|
|
10
|
-
let currentSection: Record<string, object | string | number> = jsonObject;
|
|
11
|
-
const sectionStack: Record<string, object | string | number>[] = [];
|
|
12
|
-
|
|
13
|
-
logArray.forEach((line) => {
|
|
14
|
-
line = line.trim();
|
|
15
|
-
|
|
16
|
-
if (line.startsWith("->")) {
|
|
17
|
-
const match = line.match(/->\s+([^:]+):\s+(Str|Int)\((.+)\)/);
|
|
18
|
-
if (match) {
|
|
19
|
-
const [, key, type, value] = match;
|
|
20
|
-
const parsedValue = type === "Int" ? parseInt(value, 10) : value;
|
|
21
|
-
|
|
22
|
-
if (typeof currentSection === "object") {
|
|
23
|
-
currentSection[key] = parsedValue;
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
} else if (line.endsWith(":")) {
|
|
27
|
-
// new section
|
|
28
|
-
const sectionName = line
|
|
29
|
-
.slice(0, -1)
|
|
30
|
-
.trim()
|
|
31
|
-
.toLowerCase()
|
|
32
|
-
.replace(" ", "_");
|
|
33
|
-
jsonObject[sectionName] = {};
|
|
34
|
-
currentSection = jsonObject[sectionName] as Record<
|
|
35
|
-
string,
|
|
36
|
-
object | string | number
|
|
37
|
-
>;
|
|
38
|
-
sectionStack.push(currentSection);
|
|
39
|
-
} else if (line.startsWith('"')) {
|
|
40
|
-
// Additional metadata at the end, store it separately
|
|
41
|
-
jsonObject["metadata"] = line;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
if (line.includes("Body:")) {
|
|
45
|
-
const match = line.match(/Body:\s+(\w+)\((.+)\)/);
|
|
46
|
-
if (match) {
|
|
47
|
-
jsonObject["log_body"] = match[2];
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
return jsonObject;
|
|
53
|
-
}
|