autotel 2.24.0 → 2.25.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/auto.cjs +2 -2
- package/dist/auto.js +1 -1
- package/dist/{chunk-CSG2D3BZ.cjs → chunk-73SCHI7V.cjs} +7 -7
- package/dist/{chunk-CSG2D3BZ.cjs.map → chunk-73SCHI7V.cjs.map} +1 -1
- package/dist/{chunk-47KW5CV7.js → chunk-7RV6L24E.js} +4 -3
- package/dist/chunk-7RV6L24E.js.map +1 -0
- package/dist/{chunk-AXNPD6XW.cjs → chunk-7ZYUFMWU.cjs} +26 -26
- package/dist/{chunk-AXNPD6XW.cjs.map → chunk-7ZYUFMWU.cjs.map} +1 -1
- package/dist/{chunk-GSZJOYFF.js → chunk-BKIAH2YS.js} +3 -3
- package/dist/{chunk-GSZJOYFF.js.map → chunk-BKIAH2YS.js.map} +1 -1
- package/dist/{chunk-CLR5RQW4.cjs → chunk-DBUNRUDB.cjs} +5 -5
- package/dist/{chunk-CLR5RQW4.cjs.map → chunk-DBUNRUDB.cjs.map} +1 -1
- package/dist/{chunk-PDRIJURL.cjs → chunk-GIND746I.cjs} +4 -3
- package/dist/chunk-GIND746I.cjs.map +1 -0
- package/dist/{chunk-CZR7PJUZ.cjs → chunk-HCFBEOBM.cjs} +13 -13
- package/dist/{chunk-CZR7PJUZ.cjs.map → chunk-HCFBEOBM.cjs.map} +1 -1
- package/dist/{chunk-2D74YR4Z.js → chunk-JDV3LYOI.js} +3 -3
- package/dist/{chunk-2D74YR4Z.js.map → chunk-JDV3LYOI.js.map} +1 -1
- package/dist/{chunk-ZJTBAUXG.js → chunk-JZKMXKJX.js} +3 -3
- package/dist/{chunk-ZJTBAUXG.js.map → chunk-JZKMXKJX.js.map} +1 -1
- package/dist/{chunk-W6U2BUHU.cjs → chunk-LRFG6HRL.cjs} +5 -5
- package/dist/{chunk-W6U2BUHU.cjs.map → chunk-LRFG6HRL.cjs.map} +1 -1
- package/dist/{chunk-Z3BQYTZE.js → chunk-NYTCPK4J.js} +3 -3
- package/dist/{chunk-Z3BQYTZE.js.map → chunk-NYTCPK4J.js.map} +1 -1
- package/dist/{chunk-IJMW6CTV.js → chunk-P5YCN2Z3.js} +3 -3
- package/dist/{chunk-IJMW6CTV.js.map → chunk-P5YCN2Z3.js.map} +1 -1
- package/dist/decorators.cjs +2 -2
- package/dist/decorators.js +2 -2
- package/dist/event.cjs +5 -5
- package/dist/event.js +2 -2
- package/dist/functional.cjs +9 -9
- package/dist/functional.js +2 -2
- package/dist/index.cjs +41 -41
- package/dist/index.js +9 -9
- package/dist/instrumentation.cjs +8 -8
- package/dist/instrumentation.js +1 -1
- package/dist/messaging.cjs +6 -6
- package/dist/messaging.js +3 -3
- package/dist/semantic-helpers.cjs +7 -7
- package/dist/semantic-helpers.js +3 -3
- package/dist/test-span-collector.cjs +1 -0
- package/dist/test-span-collector.cjs.map +1 -1
- package/dist/test-span-collector.d.cts +2 -1
- package/dist/test-span-collector.d.ts +2 -1
- package/dist/test-span-collector.js +1 -1
- package/dist/test-span-collector.js.map +1 -1
- package/dist/webhook.cjs +3 -3
- package/dist/webhook.js +2 -2
- package/dist/workflow-distributed.cjs +4 -4
- package/dist/workflow-distributed.js +2 -2
- package/dist/workflow.cjs +7 -7
- package/dist/workflow.js +3 -3
- package/package.json +9 -7
- package/src/init.customization.test.ts +41 -31
- package/src/init.openllmetry.test.ts +98 -186
- package/src/init.ts +18 -1
- package/src/test-span-collector.ts +1 -1
- package/dist/chunk-47KW5CV7.js.map +0 -1
- package/dist/chunk-PDRIJURL.cjs.map +0 -1
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var chunkINJD3G4K_cjs = require('./chunk-INJD3G4K.cjs');
|
|
4
|
-
var
|
|
4
|
+
var chunk7ZYUFMWU_cjs = require('./chunk-7ZYUFMWU.cjs');
|
|
5
5
|
require('./chunk-W4EUTSB2.cjs');
|
|
6
6
|
require('./chunk-GML3FBOT.cjs');
|
|
7
7
|
require('./chunk-D5LMF53P.cjs');
|
|
8
8
|
require('./chunk-XRKAL7WJ.cjs');
|
|
9
|
-
require('./chunk-
|
|
9
|
+
require('./chunk-GIND746I.cjs');
|
|
10
10
|
require('./chunk-6YIDHH2S.cjs');
|
|
11
11
|
require('./chunk-GVLK7YUU.cjs');
|
|
12
12
|
require('./chunk-ZNMBW67B.cjs');
|
|
@@ -59,7 +59,7 @@ var WorkflowBaggage = chunkINJD3G4K_cjs.createSafeBaggageSchema(workflowBaggageF
|
|
|
59
59
|
function traceDistributedWorkflow(config) {
|
|
60
60
|
const spanName = `workflow.${config.name}`;
|
|
61
61
|
return (fnFactory) => {
|
|
62
|
-
return
|
|
62
|
+
return chunk7ZYUFMWU_cjs.trace(
|
|
63
63
|
{ name: spanName, spanKind: api.SpanKind.INTERNAL },
|
|
64
64
|
(baseCtx) => {
|
|
65
65
|
return async (...args) => {
|
|
@@ -158,7 +158,7 @@ function traceDistributedWorkflow(config) {
|
|
|
158
158
|
function traceDistributedStep(config) {
|
|
159
159
|
const spanName = `workflow.step.${config.name}`;
|
|
160
160
|
return (fnFactory) => {
|
|
161
|
-
return
|
|
161
|
+
return chunk7ZYUFMWU_cjs.trace(
|
|
162
162
|
{ name: spanName, spanKind: api.SpanKind.INTERNAL },
|
|
163
163
|
(baseCtx) => {
|
|
164
164
|
return async (...args) => {
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { createSafeBaggageSchema } from './chunk-4IFSYQVX.js';
|
|
2
|
-
import { trace } from './chunk-
|
|
2
|
+
import { trace } from './chunk-JDV3LYOI.js';
|
|
3
3
|
import './chunk-SR35DG5A.js';
|
|
4
4
|
import './chunk-B3ZHLLMP.js';
|
|
5
5
|
import './chunk-WD4RP6IV.js';
|
|
6
6
|
import './chunk-USSL3D6L.js';
|
|
7
|
-
import './chunk-
|
|
7
|
+
import './chunk-7RV6L24E.js';
|
|
8
8
|
import './chunk-YTGF4L2C.js';
|
|
9
9
|
import './chunk-X4RMFFMR.js';
|
|
10
10
|
import './chunk-WGWSHJ2N.js';
|
package/dist/workflow.cjs
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
4
|
-
require('./chunk-
|
|
3
|
+
var chunkDBUNRUDB_cjs = require('./chunk-DBUNRUDB.cjs');
|
|
4
|
+
require('./chunk-7ZYUFMWU.cjs');
|
|
5
5
|
require('./chunk-W4EUTSB2.cjs');
|
|
6
6
|
require('./chunk-GML3FBOT.cjs');
|
|
7
7
|
require('./chunk-D5LMF53P.cjs');
|
|
8
8
|
require('./chunk-XRKAL7WJ.cjs');
|
|
9
|
-
require('./chunk-
|
|
9
|
+
require('./chunk-GIND746I.cjs');
|
|
10
10
|
require('./chunk-6YIDHH2S.cjs');
|
|
11
11
|
require('./chunk-GVLK7YUU.cjs');
|
|
12
12
|
require('./chunk-ZNMBW67B.cjs');
|
|
@@ -25,19 +25,19 @@ require('./chunk-JEQ2X3Z6.cjs');
|
|
|
25
25
|
|
|
26
26
|
Object.defineProperty(exports, "getCurrentWorkflowContext", {
|
|
27
27
|
enumerable: true,
|
|
28
|
-
get: function () { return
|
|
28
|
+
get: function () { return chunkDBUNRUDB_cjs.getCurrentWorkflowContext; }
|
|
29
29
|
});
|
|
30
30
|
Object.defineProperty(exports, "isInWorkflow", {
|
|
31
31
|
enumerable: true,
|
|
32
|
-
get: function () { return
|
|
32
|
+
get: function () { return chunkDBUNRUDB_cjs.isInWorkflow; }
|
|
33
33
|
});
|
|
34
34
|
Object.defineProperty(exports, "traceStep", {
|
|
35
35
|
enumerable: true,
|
|
36
|
-
get: function () { return
|
|
36
|
+
get: function () { return chunkDBUNRUDB_cjs.traceStep; }
|
|
37
37
|
});
|
|
38
38
|
Object.defineProperty(exports, "traceWorkflow", {
|
|
39
39
|
enumerable: true,
|
|
40
|
-
get: function () { return
|
|
40
|
+
get: function () { return chunkDBUNRUDB_cjs.traceWorkflow; }
|
|
41
41
|
});
|
|
42
42
|
//# sourceMappingURL=workflow.cjs.map
|
|
43
43
|
//# sourceMappingURL=workflow.cjs.map
|
package/dist/workflow.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
export { getCurrentWorkflowContext, isInWorkflow, traceStep, traceWorkflow } from './chunk-
|
|
2
|
-
import './chunk-
|
|
1
|
+
export { getCurrentWorkflowContext, isInWorkflow, traceStep, traceWorkflow } from './chunk-P5YCN2Z3.js';
|
|
2
|
+
import './chunk-JDV3LYOI.js';
|
|
3
3
|
import './chunk-SR35DG5A.js';
|
|
4
4
|
import './chunk-B3ZHLLMP.js';
|
|
5
5
|
import './chunk-WD4RP6IV.js';
|
|
6
6
|
import './chunk-USSL3D6L.js';
|
|
7
|
-
import './chunk-
|
|
7
|
+
import './chunk-7RV6L24E.js';
|
|
8
8
|
import './chunk-YTGF4L2C.js';
|
|
9
9
|
import './chunk-X4RMFFMR.js';
|
|
10
10
|
import './chunk-WGWSHJ2N.js';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "autotel",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.25.0",
|
|
4
4
|
"description": "Write Once, Observe Anywhere",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -248,7 +248,6 @@
|
|
|
248
248
|
"license": "MIT",
|
|
249
249
|
"dependencies": {
|
|
250
250
|
"@opentelemetry/api": "^1.9.0",
|
|
251
|
-
"@tanstack/intent": "^0.0.13",
|
|
252
251
|
"@opentelemetry/api-logs": "^0.213.0",
|
|
253
252
|
"@opentelemetry/exporter-metrics-otlp-http": "^0.213.0",
|
|
254
253
|
"@opentelemetry/exporter-trace-otlp-http": "^0.213.0",
|
|
@@ -258,6 +257,7 @@
|
|
|
258
257
|
"@opentelemetry/sdk-node": "^0.213.0",
|
|
259
258
|
"@opentelemetry/sdk-trace-base": "^2.6.0",
|
|
260
259
|
"@opentelemetry/semantic-conventions": "^1.40.0",
|
|
260
|
+
"@tanstack/intent": "^0.0.23",
|
|
261
261
|
"import-in-the-middle": "^3.0.0"
|
|
262
262
|
},
|
|
263
263
|
"peerDependencies": {
|
|
@@ -334,12 +334,13 @@
|
|
|
334
334
|
"@opentelemetry/resource-detector-gcp": "^0.48.0",
|
|
335
335
|
"@opentelemetry/sdk-logs": "^0.213.0",
|
|
336
336
|
"@opentelemetry/sdk-trace-node": "^2.6.0",
|
|
337
|
+
"@swc/core": "^1.15.18",
|
|
337
338
|
"@total-typescript/ts-reset": "^0.6.1",
|
|
338
339
|
"@total-typescript/tsconfig": "^1.0.4",
|
|
339
340
|
"@types/eslint-config-prettier": "^6.11.3",
|
|
340
|
-
"@types/node": "^25.
|
|
341
|
-
"@typescript-eslint/eslint-plugin": "^8.
|
|
342
|
-
"@typescript-eslint/parser": "^8.
|
|
341
|
+
"@types/node": "^25.5.0",
|
|
342
|
+
"@typescript-eslint/eslint-plugin": "^8.57.1",
|
|
343
|
+
"@typescript-eslint/parser": "^8.57.1",
|
|
343
344
|
"eslint-config-prettier": "^10.1.8",
|
|
344
345
|
"eslint-plugin-unicorn": "^63.0.0",
|
|
345
346
|
"pino": "^10.3.1",
|
|
@@ -348,9 +349,10 @@
|
|
|
348
349
|
"tsup": "^8.5.1",
|
|
349
350
|
"tsx": "^4.21.0",
|
|
350
351
|
"typescript": "^5.9.3",
|
|
351
|
-
"typescript-eslint": "^8.
|
|
352
|
+
"typescript-eslint": "^8.57.1",
|
|
353
|
+
"unplugin-swc": "^1.5.9",
|
|
352
354
|
"vite-tsconfig-paths": "^6.1.1",
|
|
353
|
-
"vitest": "^4.0
|
|
355
|
+
"vitest": "^4.1.0",
|
|
354
356
|
"vitest-mock-extended": "^3.1.0",
|
|
355
357
|
"winston": "^3.19.0",
|
|
356
358
|
"yaml": "^2.8.2"
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { afterEach,
|
|
1
|
+
import { afterEach, describe, expect, it, vi } from 'vitest';
|
|
2
2
|
import type { MetricReader } from '@opentelemetry/sdk-metrics';
|
|
3
3
|
import type { NodeSDK } from '@opentelemetry/sdk-node';
|
|
4
4
|
import type { SpanProcessor } from '@opentelemetry/sdk-trace-base';
|
|
@@ -9,13 +9,6 @@ type SdkRecord = {
|
|
|
9
9
|
instance: DeepMockProxy<NodeSDK>;
|
|
10
10
|
};
|
|
11
11
|
|
|
12
|
-
const mockedModules = [
|
|
13
|
-
'@opentelemetry/sdk-node',
|
|
14
|
-
'@opentelemetry/exporter-trace-otlp-http',
|
|
15
|
-
'@opentelemetry/exporter-metrics-otlp-http',
|
|
16
|
-
'@opentelemetry/sdk-metrics',
|
|
17
|
-
];
|
|
18
|
-
|
|
19
12
|
async function loadInitWithMocks() {
|
|
20
13
|
const sdkInstances: SdkRecord[] = [];
|
|
21
14
|
const traceExporterOptions: Record<string, unknown>[] = [];
|
|
@@ -59,6 +52,9 @@ async function loadInitWithMocks() {
|
|
|
59
52
|
}
|
|
60
53
|
}
|
|
61
54
|
|
|
55
|
+
// Reset modules immediately before mocking to ensure clean state
|
|
56
|
+
vi.resetModules();
|
|
57
|
+
|
|
62
58
|
vi.doMock('@opentelemetry/sdk-node', () => ({
|
|
63
59
|
NodeSDK: MockNodeSDK,
|
|
64
60
|
}));
|
|
@@ -88,44 +84,56 @@ async function loadInitWithMocks() {
|
|
|
88
84
|
}
|
|
89
85
|
|
|
90
86
|
describe('init() customization', () => {
|
|
91
|
-
beforeEach(() => {
|
|
92
|
-
vi.resetModules();
|
|
93
|
-
});
|
|
94
|
-
|
|
95
87
|
afterEach(() => {
|
|
96
|
-
|
|
97
|
-
vi.doUnmock(mod);
|
|
98
|
-
}
|
|
99
|
-
vi.clearAllMocks();
|
|
88
|
+
vi.restoreAllMocks();
|
|
100
89
|
delete process.env.AUTOTEL_METRICS;
|
|
101
90
|
delete process.env.NODE_ENV;
|
|
102
91
|
});
|
|
103
92
|
|
|
104
|
-
it(
|
|
105
|
-
|
|
93
|
+
it(
|
|
94
|
+
'passes custom instrumentations to the NodeSDK',
|
|
95
|
+
{ timeout: 10_000 },
|
|
96
|
+
async () => {
|
|
97
|
+
const { init, sdkInstances } = await loadInitWithMocks();
|
|
106
98
|
|
|
107
|
-
|
|
99
|
+
const instrumentation = { name: 'http' } as any;
|
|
108
100
|
|
|
109
|
-
|
|
101
|
+
init({
|
|
102
|
+
service: 'instrumented-app',
|
|
103
|
+
instrumentations: [instrumentation],
|
|
104
|
+
});
|
|
110
105
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
106
|
+
const options = sdkInstances.at(-1)?.options as Record<string, unknown>;
|
|
107
|
+
expect(options.instrumentations).toBeDefined();
|
|
108
|
+
expect(options.instrumentations).toContain(instrumentation);
|
|
109
|
+
},
|
|
110
|
+
);
|
|
115
111
|
|
|
116
112
|
it('merges resource attributes with defaults', async () => {
|
|
117
|
-
const { init, sdkInstances } = await loadInitWithMocks();
|
|
113
|
+
const { init, getConfig, sdkInstances } = await loadInitWithMocks();
|
|
118
114
|
|
|
119
115
|
init({
|
|
120
116
|
service: 'resource-app',
|
|
121
117
|
resourceAttributes: { 'cloud.region': 'eu-central-1' },
|
|
122
118
|
});
|
|
123
119
|
|
|
124
|
-
const resource = sdkInstances.at(-1)?.options.resource as
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
120
|
+
const resource = sdkInstances.at(-1)?.options.resource as
|
|
121
|
+
| {
|
|
122
|
+
attributes?: Record<string, unknown>;
|
|
123
|
+
}
|
|
124
|
+
| undefined;
|
|
125
|
+
|
|
126
|
+
if (resource?.attributes) {
|
|
127
|
+
expect(resource.attributes['cloud.region']).toBe('eu-central-1');
|
|
128
|
+
expect(resource.attributes['service.name']).toBe('resource-app');
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const config = getConfig();
|
|
133
|
+
expect(config.service).toBe('resource-app');
|
|
134
|
+
expect(config.resourceAttributes).toMatchObject({
|
|
135
|
+
'cloud.region': 'eu-central-1',
|
|
136
|
+
});
|
|
129
137
|
});
|
|
130
138
|
|
|
131
139
|
it('creates a default OTLP metric reader when metrics enabled', async () => {
|
|
@@ -153,7 +161,8 @@ describe('init() customization', () => {
|
|
|
153
161
|
|
|
154
162
|
init({ service: 'custom-metrics', metricReaders: [customMetricReader] });
|
|
155
163
|
|
|
156
|
-
|
|
164
|
+
expect(sdkInstances).toHaveLength(1);
|
|
165
|
+
const options = sdkInstances.at(-1)!.options as Record<string, unknown>;
|
|
157
166
|
expect(options.metricReaders).toEqual([customMetricReader]);
|
|
158
167
|
expect(metricReaderOptions).toHaveLength(0);
|
|
159
168
|
});
|
|
@@ -186,6 +195,7 @@ describe('init() customization', () => {
|
|
|
186
195
|
init({
|
|
187
196
|
service: 'custom-sdk',
|
|
188
197
|
endpoint: 'http://localhost:4318',
|
|
198
|
+
metrics: false,
|
|
189
199
|
sdkFactory: (defaults) => {
|
|
190
200
|
expect(defaults.spanProcessors).toBeDefined();
|
|
191
201
|
return customSdk;
|
|
@@ -1,134 +1,36 @@
|
|
|
1
|
-
import { afterEach,
|
|
2
|
-
import type { NodeSDK } from '@opentelemetry/sdk-node';
|
|
3
|
-
import { mock, mockDeep, type DeepMockProxy } from 'vitest-mock-extended';
|
|
4
|
-
|
|
5
|
-
type SdkRecord = {
|
|
6
|
-
options: Record<string, unknown>;
|
|
7
|
-
instance: DeepMockProxy<NodeSDK>;
|
|
8
|
-
};
|
|
9
|
-
|
|
10
|
-
const mockedModules = [
|
|
11
|
-
'@opentelemetry/sdk-node',
|
|
12
|
-
'@opentelemetry/exporter-trace-otlp-http',
|
|
13
|
-
'@opentelemetry/exporter-metrics-otlp-http',
|
|
14
|
-
'@opentelemetry/sdk-metrics',
|
|
15
|
-
'./node-require',
|
|
16
|
-
];
|
|
17
|
-
|
|
18
|
-
// Track traceloop initialize calls globally
|
|
19
|
-
const traceloopInitializeCalls: Array<Record<string, unknown>> = [];
|
|
20
|
-
|
|
21
|
-
// Store mock initialize function globally
|
|
22
|
-
let globalMockInitialize: ReturnType<typeof vi.fn> | null = null;
|
|
23
|
-
|
|
24
|
-
async function loadInitWithMocks() {
|
|
25
|
-
const sdkInstances: SdkRecord[] = [];
|
|
26
|
-
|
|
27
|
-
class MockNodeSDK {
|
|
28
|
-
constructor(options: Record<string, unknown>) {
|
|
29
|
-
const instance = mockDeep<NodeSDK>();
|
|
30
|
-
instance.start.mockImplementation(() => {});
|
|
31
|
-
instance.shutdown.mockResolvedValue();
|
|
32
|
-
|
|
33
|
-
(instance as any).getTracerProvider = vi.fn().mockReturnValue(mock());
|
|
34
|
-
sdkInstances.push({ options, instance });
|
|
35
|
-
return instance;
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
class MockOTLPTraceExporter {
|
|
40
|
-
options: Record<string, unknown>;
|
|
41
|
-
|
|
42
|
-
constructor(options: Record<string, unknown>) {
|
|
43
|
-
this.options = options;
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
class MockOTLPMetricExporter {
|
|
48
|
-
options: Record<string, unknown>;
|
|
49
|
-
|
|
50
|
-
constructor(options: Record<string, unknown>) {
|
|
51
|
-
this.options = options;
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
class MockPeriodicExportingMetricReader {
|
|
56
|
-
options: Record<string, unknown>;
|
|
57
|
-
|
|
58
|
-
constructor(options: Record<string, unknown>) {
|
|
59
|
-
this.options = options;
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
// Clear module cache first
|
|
64
|
-
vi.resetModules();
|
|
1
|
+
import { afterEach, describe, expect, it, vi } from 'vitest';
|
|
65
2
|
|
|
66
|
-
|
|
67
|
-
globalMockInitialize = vi.fn((options?: Record<string, unknown>) => {
|
|
68
|
-
traceloopInitializeCalls.push(options || {});
|
|
69
|
-
});
|
|
3
|
+
type InitModule = typeof import('./init');
|
|
70
4
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
5
|
+
async function loadInitModule(): Promise<InitModule> {
|
|
6
|
+
vi.resetModules();
|
|
7
|
+
return import('./init');
|
|
8
|
+
}
|
|
75
9
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
vi.
|
|
80
|
-
|
|
81
|
-
if (id === '@traceloop/node-server-sdk') {
|
|
82
|
-
return mockTraceloop;
|
|
83
|
-
}
|
|
84
|
-
return undefined;
|
|
85
|
-
}),
|
|
86
|
-
requireModule: vi.fn((id: string) => {
|
|
87
|
-
const err = new Error(`Cannot find module '${id}'`);
|
|
88
|
-
(err as NodeJS.ErrnoException).code = 'MODULE_NOT_FOUND';
|
|
89
|
-
throw err;
|
|
90
|
-
}),
|
|
91
|
-
nodeRequire: vi.fn(),
|
|
92
|
-
}));
|
|
93
|
-
|
|
94
|
-
vi.doMock('@opentelemetry/sdk-node', () => ({
|
|
95
|
-
NodeSDK: MockNodeSDK,
|
|
96
|
-
}));
|
|
97
|
-
|
|
98
|
-
vi.doMock('@opentelemetry/exporter-trace-otlp-http', () => ({
|
|
99
|
-
OTLPTraceExporter: MockOTLPTraceExporter,
|
|
100
|
-
}));
|
|
101
|
-
|
|
102
|
-
vi.doMock('@opentelemetry/exporter-metrics-otlp-http', () => ({
|
|
103
|
-
OTLPMetricExporter: MockOTLPMetricExporter,
|
|
104
|
-
}));
|
|
105
|
-
|
|
106
|
-
vi.doMock('@opentelemetry/sdk-metrics', () => ({
|
|
107
|
-
PeriodicExportingMetricReader: MockPeriodicExportingMetricReader,
|
|
108
|
-
}));
|
|
109
|
-
|
|
110
|
-
const mod = await import('./init');
|
|
10
|
+
function createSdkFactory() {
|
|
11
|
+
const calls: Array<Record<string, unknown>> = [];
|
|
12
|
+
const getTracerProvider = vi.fn(() => ({ id: 'mock-tracer-provider' }));
|
|
13
|
+
const start = vi.fn();
|
|
14
|
+
const shutdown = vi.fn(async () => {});
|
|
111
15
|
|
|
112
16
|
return {
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
17
|
+
calls,
|
|
18
|
+
getTracerProvider,
|
|
19
|
+
start,
|
|
20
|
+
shutdown,
|
|
21
|
+
sdkFactory: (options: Record<string, unknown>) => {
|
|
22
|
+
calls.push(options);
|
|
23
|
+
return {
|
|
24
|
+
start,
|
|
25
|
+
shutdown,
|
|
26
|
+
getTracerProvider,
|
|
27
|
+
} as never;
|
|
28
|
+
},
|
|
118
29
|
};
|
|
119
30
|
}
|
|
120
31
|
|
|
121
32
|
describe('init() OpenLLMetry integration', () => {
|
|
122
|
-
beforeEach(() => {
|
|
123
|
-
vi.resetModules();
|
|
124
|
-
traceloopInitializeCalls.length = 0;
|
|
125
|
-
globalMockInitialize = null;
|
|
126
|
-
});
|
|
127
|
-
|
|
128
33
|
afterEach(() => {
|
|
129
|
-
for (const mod of mockedModules) {
|
|
130
|
-
vi.doUnmock(mod);
|
|
131
|
-
}
|
|
132
34
|
vi.clearAllMocks();
|
|
133
35
|
delete process.env.AUTOTEL_METRICS;
|
|
134
36
|
delete process.env.NODE_ENV;
|
|
@@ -136,29 +38,53 @@ describe('init() OpenLLMetry integration', () => {
|
|
|
136
38
|
});
|
|
137
39
|
|
|
138
40
|
it('should not initialize OpenLLMetry when disabled', async () => {
|
|
139
|
-
const
|
|
41
|
+
const mod = await loadInitModule();
|
|
42
|
+
const sdk = createSdkFactory();
|
|
43
|
+
const traceloopInitializeCalls: Array<Record<string, unknown>> = [];
|
|
44
|
+
|
|
45
|
+
mod._setOptionalRequireForTesting(() => ({
|
|
46
|
+
initialize: (options?: Record<string, unknown>) =>
|
|
47
|
+
traceloopInitializeCalls.push(options ?? {}),
|
|
48
|
+
}));
|
|
140
49
|
|
|
141
|
-
init({ service: 'test-app' });
|
|
50
|
+
mod.init({ service: 'test-app', sdkFactory: sdk.sdkFactory });
|
|
142
51
|
|
|
143
52
|
expect(traceloopInitializeCalls).toHaveLength(0);
|
|
53
|
+
mod._resetOptionalRequireForTesting();
|
|
144
54
|
});
|
|
145
55
|
|
|
146
56
|
it('should initialize OpenLLMetry when enabled', async () => {
|
|
147
|
-
const
|
|
57
|
+
const mod = await loadInitModule();
|
|
58
|
+
const sdk = createSdkFactory();
|
|
59
|
+
const traceloopInitializeCalls: Array<Record<string, unknown>> = [];
|
|
148
60
|
|
|
149
|
-
|
|
61
|
+
mod._setOptionalRequireForTesting(() => ({
|
|
62
|
+
initialize: (options?: Record<string, unknown>) =>
|
|
63
|
+
traceloopInitializeCalls.push(options ?? {}),
|
|
64
|
+
}));
|
|
65
|
+
|
|
66
|
+
mod.init({
|
|
150
67
|
service: 'test-app',
|
|
151
68
|
openllmetry: { enabled: true },
|
|
69
|
+
sdkFactory: sdk.sdkFactory,
|
|
152
70
|
});
|
|
153
71
|
|
|
154
72
|
expect(traceloopInitializeCalls).toHaveLength(1);
|
|
155
73
|
expect(traceloopInitializeCalls[0]).toBeDefined();
|
|
74
|
+
mod._resetOptionalRequireForTesting();
|
|
156
75
|
});
|
|
157
76
|
|
|
158
77
|
it('should pass OpenLLMetry options to initialize', async () => {
|
|
159
|
-
const
|
|
78
|
+
const mod = await loadInitModule();
|
|
79
|
+
const sdk = createSdkFactory();
|
|
80
|
+
const traceloopInitializeCalls: Array<Record<string, unknown>> = [];
|
|
81
|
+
|
|
82
|
+
mod._setOptionalRequireForTesting(() => ({
|
|
83
|
+
initialize: (options?: Record<string, unknown>) =>
|
|
84
|
+
traceloopInitializeCalls.push(options ?? {}),
|
|
85
|
+
}));
|
|
160
86
|
|
|
161
|
-
init({
|
|
87
|
+
mod.init({
|
|
162
88
|
service: 'test-app',
|
|
163
89
|
openllmetry: {
|
|
164
90
|
enabled: true,
|
|
@@ -167,6 +93,7 @@ describe('init() OpenLLMetry integration', () => {
|
|
|
167
93
|
apiKey: 'test-key',
|
|
168
94
|
},
|
|
169
95
|
},
|
|
96
|
+
sdkFactory: sdk.sdkFactory,
|
|
170
97
|
});
|
|
171
98
|
|
|
172
99
|
expect(traceloopInitializeCalls).toHaveLength(1);
|
|
@@ -174,109 +101,94 @@ describe('init() OpenLLMetry integration', () => {
|
|
|
174
101
|
disableBatch: true,
|
|
175
102
|
apiKey: 'test-key',
|
|
176
103
|
});
|
|
104
|
+
mod._resetOptionalRequireForTesting();
|
|
177
105
|
});
|
|
178
106
|
|
|
179
107
|
it('should reuse autotel tracer provider when OpenLLMetry is enabled', async () => {
|
|
180
|
-
const
|
|
181
|
-
|
|
108
|
+
const mod = await loadInitModule();
|
|
109
|
+
const sdk = createSdkFactory();
|
|
110
|
+
const traceloopInitializeCalls: Array<Record<string, unknown>> = [];
|
|
182
111
|
|
|
183
|
-
|
|
112
|
+
mod._setOptionalRequireForTesting(() => ({
|
|
113
|
+
initialize: (options?: Record<string, unknown>) =>
|
|
114
|
+
traceloopInitializeCalls.push(options ?? {}),
|
|
115
|
+
}));
|
|
116
|
+
|
|
117
|
+
mod.init({
|
|
184
118
|
service: 'test-app',
|
|
185
119
|
openllmetry: { enabled: true },
|
|
120
|
+
sdkFactory: sdk.sdkFactory,
|
|
186
121
|
});
|
|
187
122
|
|
|
188
|
-
expect(sdkInstances).toHaveLength(1);
|
|
189
|
-
const sdkInstance = sdkInstances[0].instance;
|
|
190
|
-
|
|
191
123
|
expect(traceloopInitializeCalls).toHaveLength(1);
|
|
192
124
|
const callOptions = traceloopInitializeCalls[0];
|
|
193
125
|
expect(callOptions).toBeDefined();
|
|
194
|
-
expect(
|
|
126
|
+
expect(sdk.getTracerProvider).toHaveBeenCalled();
|
|
127
|
+
mod._resetOptionalRequireForTesting();
|
|
195
128
|
});
|
|
196
129
|
|
|
197
130
|
it('should add OpenLLMetry instrumentations when selectiveInstrumentation is false', async () => {
|
|
198
|
-
const
|
|
131
|
+
const mod = await loadInitModule();
|
|
132
|
+
const sdk = createSdkFactory();
|
|
133
|
+
const mockTraceloop = {
|
|
134
|
+
initialize: vi.fn(),
|
|
135
|
+
instrumentations: [{ name: 'openai' }, { name: 'langchain' }],
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
mod._setOptionalRequireForTesting(() => mockTraceloop);
|
|
199
139
|
|
|
200
|
-
init({
|
|
140
|
+
mod.init({
|
|
201
141
|
service: 'test-app',
|
|
202
142
|
openllmetry: { enabled: true },
|
|
203
143
|
autoInstrumentations: false,
|
|
144
|
+
sdkFactory: sdk.sdkFactory,
|
|
204
145
|
});
|
|
205
146
|
|
|
206
|
-
const options =
|
|
147
|
+
const options = sdk.calls.at(-1) as Record<string, unknown>;
|
|
207
148
|
const instrumentations = options.instrumentations as unknown[];
|
|
208
149
|
|
|
209
150
|
expect(instrumentations).toBeDefined();
|
|
210
151
|
expect(mockTraceloop.instrumentations).toBeDefined();
|
|
152
|
+
mod._resetOptionalRequireForTesting();
|
|
211
153
|
});
|
|
212
154
|
|
|
213
155
|
it('should handle missing @traceloop/node-server-sdk gracefully', async () => {
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
vi.doMock('./node-require', () => ({
|
|
218
|
-
safeRequire: vi.fn(() => undefined),
|
|
219
|
-
requireModule: vi.fn((id: string) => {
|
|
220
|
-
const err = new Error(`Cannot find module '${id}'`);
|
|
221
|
-
(err as NodeJS.ErrnoException).code = 'MODULE_NOT_FOUND';
|
|
222
|
-
throw err;
|
|
223
|
-
}),
|
|
224
|
-
nodeRequire: vi.fn(),
|
|
225
|
-
}));
|
|
226
|
-
|
|
227
|
-
vi.doMock('@opentelemetry/sdk-node', () => ({
|
|
228
|
-
NodeSDK: class {
|
|
229
|
-
constructor() {
|
|
230
|
-
const instance = mockDeep<NodeSDK>();
|
|
231
|
-
instance.start.mockImplementation(() => {});
|
|
232
|
-
instance.shutdown.mockResolvedValue();
|
|
233
|
-
return instance;
|
|
234
|
-
}
|
|
235
|
-
},
|
|
236
|
-
}));
|
|
237
|
-
|
|
238
|
-
vi.doMock('@opentelemetry/exporter-trace-otlp-http', () => ({
|
|
239
|
-
OTLPTraceExporter: class {
|
|
240
|
-
constructor() {}
|
|
241
|
-
},
|
|
242
|
-
}));
|
|
243
|
-
|
|
244
|
-
vi.doMock('@opentelemetry/exporter-metrics-otlp-http', () => ({
|
|
245
|
-
OTLPMetricExporter: class {
|
|
246
|
-
constructor() {}
|
|
247
|
-
},
|
|
248
|
-
}));
|
|
249
|
-
|
|
250
|
-
vi.doMock('@opentelemetry/sdk-metrics', () => ({
|
|
251
|
-
PeriodicExportingMetricReader: class {
|
|
252
|
-
constructor() {}
|
|
253
|
-
},
|
|
254
|
-
}));
|
|
255
|
-
|
|
256
|
-
const { init } = await import('./init');
|
|
156
|
+
const mod = await loadInitModule();
|
|
157
|
+
const sdk = createSdkFactory();
|
|
158
|
+
mod._setOptionalRequireForTesting(() => undefined);
|
|
257
159
|
|
|
258
160
|
expect(() => {
|
|
259
|
-
init({
|
|
161
|
+
mod.init({
|
|
260
162
|
service: 'test-app',
|
|
261
163
|
openllmetry: { enabled: true },
|
|
164
|
+
sdkFactory: sdk.sdkFactory,
|
|
262
165
|
});
|
|
263
166
|
}).not.toThrow();
|
|
167
|
+
mod._resetOptionalRequireForTesting();
|
|
264
168
|
});
|
|
265
169
|
|
|
266
170
|
it('should initialize OpenLLMetry after SDK start', async () => {
|
|
267
|
-
const
|
|
268
|
-
|
|
171
|
+
const mod = await loadInitModule();
|
|
172
|
+
const sdk = createSdkFactory();
|
|
173
|
+
const traceloopInitializeCalls: Array<Record<string, unknown>> = [];
|
|
174
|
+
|
|
175
|
+
mod._setOptionalRequireForTesting(() => ({
|
|
176
|
+
initialize: (options?: Record<string, unknown>) =>
|
|
177
|
+
traceloopInitializeCalls.push(options ?? {}),
|
|
178
|
+
}));
|
|
269
179
|
|
|
270
|
-
init({
|
|
180
|
+
mod.init({
|
|
271
181
|
service: 'test-app',
|
|
272
182
|
openllmetry: { enabled: true },
|
|
183
|
+
sdkFactory: sdk.sdkFactory,
|
|
273
184
|
});
|
|
274
185
|
|
|
275
186
|
// Verify SDK started (synchronously in init)
|
|
276
|
-
expect(
|
|
277
|
-
expect(
|
|
187
|
+
expect(sdk.calls).toHaveLength(1);
|
|
188
|
+
expect(sdk.start).toHaveBeenCalled();
|
|
278
189
|
|
|
279
190
|
// Verify OpenLLMetry was initialized (synchronously via safeRequire)
|
|
280
191
|
expect(traceloopInitializeCalls).toHaveLength(1);
|
|
192
|
+
mod._resetOptionalRequireForTesting();
|
|
281
193
|
});
|
|
282
194
|
});
|