@illuma-ai/observability-core 0.1.0 → 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/dist/__tests__/core-client.test.d.ts +8 -0
- package/dist/__tests__/core-client.test.d.ts.map +1 -0
- package/dist/__tests__/core-client.test.js +844 -0
- package/dist/__tests__/core-client.test.js.map +1 -0
- package/dist/__tests__/generation-client.test.d.ts +8 -0
- package/dist/__tests__/generation-client.test.d.ts.map +1 -0
- package/dist/__tests__/generation-client.test.js +117 -0
- package/dist/__tests__/generation-client.test.js.map +1 -0
- package/dist/__tests__/span-client.test.d.ts +9 -0
- package/dist/__tests__/span-client.test.d.ts.map +1 -0
- package/dist/__tests__/span-client.test.js +272 -0
- package/dist/__tests__/span-client.test.js.map +1 -0
- package/dist/__tests__/trace-client.test.d.ts +9 -0
- package/dist/__tests__/trace-client.test.d.ts.map +1 -0
- package/dist/__tests__/trace-client.test.js +260 -0
- package/dist/__tests__/trace-client.test.js.map +1 -0
- package/dist/__tests__/types.test.d.ts +9 -0
- package/dist/__tests__/types.test.d.ts.map +1 -0
- package/dist/__tests__/types.test.js +453 -0
- package/dist/__tests__/types.test.js.map +1 -0
- package/dist/__tests__/utils.test.d.ts +7 -0
- package/dist/__tests__/utils.test.d.ts.map +1 -0
- package/dist/__tests__/utils.test.js +164 -0
- package/dist/__tests__/utils.test.js.map +1 -0
- package/dist/core-client.d.ts +1 -0
- package/dist/core-client.d.ts.map +1 -1
- package/dist/core-client.js +4 -0
- package/dist/core-client.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/span-client.d.ts +28 -0
- package/dist/span-client.d.ts.map +1 -1
- package/dist/span-client.js +92 -0
- package/dist/span-client.js.map +1 -1
- package/dist/trace-client.d.ts +35 -0
- package/dist/trace-client.d.ts.map +1 -1
- package/dist/trace-client.js +110 -0
- package/dist/trace-client.js.map +1 -1
- package/dist/types.d.ts +109 -7
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +40 -2
- package/dist/types.js.map +1 -1
- package/package.json +5 -2
|
@@ -0,0 +1,453 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unit tests for the observability type system.
|
|
3
|
+
*
|
|
4
|
+
* Validates enum values, ingestion event type constants, and structural
|
|
5
|
+
* compatibility of all parameter interfaces (TraceParams, GenerationParams,
|
|
6
|
+
* SpanParams, ScoreParams, ErrorInfo, etc.).
|
|
7
|
+
*/
|
|
8
|
+
import { describe, it, expect } from 'vitest';
|
|
9
|
+
import { ObservationType, ObservationLevel, IngestionEventType, } from '../index.js';
|
|
10
|
+
// ---------------------------------------------------------------------------
|
|
11
|
+
// ObservationType enum
|
|
12
|
+
// ---------------------------------------------------------------------------
|
|
13
|
+
describe('ObservationType', () => {
|
|
14
|
+
it('should have exactly 10 values', () => {
|
|
15
|
+
const values = Object.values(ObservationType);
|
|
16
|
+
expect(values).toHaveLength(10);
|
|
17
|
+
});
|
|
18
|
+
it.each([
|
|
19
|
+
['SPAN', 'SPAN'],
|
|
20
|
+
['GENERATION', 'GENERATION'],
|
|
21
|
+
['EVENT', 'EVENT'],
|
|
22
|
+
['AGENT', 'AGENT'],
|
|
23
|
+
['TOOL', 'TOOL'],
|
|
24
|
+
['CHAIN', 'CHAIN'],
|
|
25
|
+
['RETRIEVER', 'RETRIEVER'],
|
|
26
|
+
['EVALUATOR', 'EVALUATOR'],
|
|
27
|
+
['EMBEDDING', 'EMBEDDING'],
|
|
28
|
+
['GUARDRAIL', 'GUARDRAIL'],
|
|
29
|
+
])('should have %s = "%s"', (key, expected) => {
|
|
30
|
+
expect(ObservationType[key]).toBe(expected);
|
|
31
|
+
});
|
|
32
|
+
it('should use string values matching the key names', () => {
|
|
33
|
+
// All values should equal their keys (uppercase pattern)
|
|
34
|
+
for (const [key, value] of Object.entries(ObservationType)) {
|
|
35
|
+
expect(value).toBe(key);
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
// ---------------------------------------------------------------------------
|
|
40
|
+
// ObservationLevel enum
|
|
41
|
+
// ---------------------------------------------------------------------------
|
|
42
|
+
describe('ObservationLevel', () => {
|
|
43
|
+
it('should have exactly 4 values', () => {
|
|
44
|
+
const values = Object.values(ObservationLevel);
|
|
45
|
+
expect(values).toHaveLength(4);
|
|
46
|
+
});
|
|
47
|
+
it.each([
|
|
48
|
+
['DEBUG', 'DEBUG'],
|
|
49
|
+
['DEFAULT', 'DEFAULT'],
|
|
50
|
+
['WARNING', 'WARNING'],
|
|
51
|
+
['ERROR', 'ERROR'],
|
|
52
|
+
])('should have %s = "%s"', (key, expected) => {
|
|
53
|
+
expect(ObservationLevel[key]).toBe(expected);
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
// ---------------------------------------------------------------------------
|
|
57
|
+
// IngestionEventType constants
|
|
58
|
+
// ---------------------------------------------------------------------------
|
|
59
|
+
describe('IngestionEventType', () => {
|
|
60
|
+
it('should have all core event types', () => {
|
|
61
|
+
expect(IngestionEventType.TRACE_CREATE).toBe('trace-create');
|
|
62
|
+
expect(IngestionEventType.SPAN_CREATE).toBe('span-create');
|
|
63
|
+
expect(IngestionEventType.SPAN_UPDATE).toBe('span-update');
|
|
64
|
+
expect(IngestionEventType.GENERATION_CREATE).toBe('generation-create');
|
|
65
|
+
expect(IngestionEventType.GENERATION_UPDATE).toBe('generation-update');
|
|
66
|
+
expect(IngestionEventType.EVENT_CREATE).toBe('event-create');
|
|
67
|
+
expect(IngestionEventType.SCORE_CREATE).toBe('score-create');
|
|
68
|
+
expect(IngestionEventType.SDK_LOG).toBe('sdk-log');
|
|
69
|
+
});
|
|
70
|
+
it('should have all new typed observation event types', () => {
|
|
71
|
+
expect(IngestionEventType.AGENT_CREATE).toBe('agent-create');
|
|
72
|
+
expect(IngestionEventType.TOOL_CREATE).toBe('tool-create');
|
|
73
|
+
expect(IngestionEventType.CHAIN_CREATE).toBe('chain-create');
|
|
74
|
+
expect(IngestionEventType.RETRIEVER_CREATE).toBe('retriever-create');
|
|
75
|
+
expect(IngestionEventType.EVALUATOR_CREATE).toBe('evaluator-create');
|
|
76
|
+
expect(IngestionEventType.EMBEDDING_CREATE).toBe('embedding-create');
|
|
77
|
+
expect(IngestionEventType.GUARDRAIL_CREATE).toBe('guardrail-create');
|
|
78
|
+
});
|
|
79
|
+
it('should have the dataset-run-item-create event type', () => {
|
|
80
|
+
expect(IngestionEventType.DATASET_RUN_ITEM_CREATE).toBe('dataset-run-item-create');
|
|
81
|
+
});
|
|
82
|
+
it('should have exactly 16 event type constants', () => {
|
|
83
|
+
const keys = Object.keys(IngestionEventType);
|
|
84
|
+
expect(keys).toHaveLength(16);
|
|
85
|
+
});
|
|
86
|
+
it('should use kebab-case string values', () => {
|
|
87
|
+
for (const value of Object.values(IngestionEventType)) {
|
|
88
|
+
expect(value).toMatch(/^[a-z]+-[a-z]+(-[a-z]+)*$/);
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
// ---------------------------------------------------------------------------
|
|
93
|
+
// ErrorInfo interface
|
|
94
|
+
// ---------------------------------------------------------------------------
|
|
95
|
+
describe('ErrorInfo', () => {
|
|
96
|
+
it('should accept required fields (exceptionType, traceback)', () => {
|
|
97
|
+
const error = {
|
|
98
|
+
exceptionType: 'ValueError',
|
|
99
|
+
traceback: 'Traceback (most recent call last):\n File "main.py", line 42',
|
|
100
|
+
};
|
|
101
|
+
expect(error.exceptionType).toBe('ValueError');
|
|
102
|
+
expect(error.traceback).toContain('Traceback');
|
|
103
|
+
});
|
|
104
|
+
it('should accept the optional message field', () => {
|
|
105
|
+
const error = {
|
|
106
|
+
exceptionType: 'TypeError',
|
|
107
|
+
message: 'cannot read property of undefined',
|
|
108
|
+
traceback: 'at Object.<anonymous> (index.js:1:1)',
|
|
109
|
+
};
|
|
110
|
+
expect(error.message).toBe('cannot read property of undefined');
|
|
111
|
+
});
|
|
112
|
+
it('should not require message', () => {
|
|
113
|
+
const error = {
|
|
114
|
+
exceptionType: 'RuntimeError',
|
|
115
|
+
traceback: 'stack trace here',
|
|
116
|
+
};
|
|
117
|
+
expect(error.message).toBeUndefined();
|
|
118
|
+
});
|
|
119
|
+
});
|
|
120
|
+
// ---------------------------------------------------------------------------
|
|
121
|
+
// TraceParams type compatibility
|
|
122
|
+
// ---------------------------------------------------------------------------
|
|
123
|
+
describe('TraceParams', () => {
|
|
124
|
+
it('should accept all base fields', () => {
|
|
125
|
+
const params = {
|
|
126
|
+
id: 'trace-1',
|
|
127
|
+
name: 'my-trace',
|
|
128
|
+
userId: 'user-1',
|
|
129
|
+
sessionId: 'session-1',
|
|
130
|
+
input: { prompt: 'hello' },
|
|
131
|
+
output: { response: 'world' },
|
|
132
|
+
metadata: { key: 'value' },
|
|
133
|
+
tags: ['tag1', 'tag2'],
|
|
134
|
+
public: true,
|
|
135
|
+
version: '1.0.0',
|
|
136
|
+
timestamp: '2024-01-01T00:00:00.000Z',
|
|
137
|
+
};
|
|
138
|
+
expect(params.name).toBe('my-trace');
|
|
139
|
+
expect(params.tags).toHaveLength(2);
|
|
140
|
+
});
|
|
141
|
+
it('should accept the new release field', () => {
|
|
142
|
+
const params = { release: 'v2.3.1' };
|
|
143
|
+
expect(params.release).toBe('v2.3.1');
|
|
144
|
+
});
|
|
145
|
+
it('should accept the new environment field', () => {
|
|
146
|
+
const params = { environment: 'production' };
|
|
147
|
+
expect(params.environment).toBe('production');
|
|
148
|
+
});
|
|
149
|
+
it('should accept the new externalId field', () => {
|
|
150
|
+
const params = { externalId: 'ext-abc-123' };
|
|
151
|
+
expect(params.externalId).toBe('ext-abc-123');
|
|
152
|
+
});
|
|
153
|
+
it('should accept the new threadId field', () => {
|
|
154
|
+
const params = { threadId: 'thread-conv-456' };
|
|
155
|
+
expect(params.threadId).toBe('thread-conv-456');
|
|
156
|
+
});
|
|
157
|
+
it('should accept the new errorInfo field', () => {
|
|
158
|
+
const params = {
|
|
159
|
+
errorInfo: {
|
|
160
|
+
exceptionType: 'TimeoutError',
|
|
161
|
+
message: 'Request timed out',
|
|
162
|
+
traceback: 'at Timer.setTimeout (node:internal/timers:1:1)',
|
|
163
|
+
},
|
|
164
|
+
};
|
|
165
|
+
expect(params.errorInfo).toBeDefined();
|
|
166
|
+
expect(params.errorInfo.exceptionType).toBe('TimeoutError');
|
|
167
|
+
expect(params.errorInfo.message).toBe('Request timed out');
|
|
168
|
+
expect(params.errorInfo.traceback).toContain('Timer');
|
|
169
|
+
});
|
|
170
|
+
it('should accept all new fields together', () => {
|
|
171
|
+
const params = {
|
|
172
|
+
name: 'full-trace',
|
|
173
|
+
release: 'abc123',
|
|
174
|
+
environment: 'staging',
|
|
175
|
+
externalId: 'jira-PROJ-999',
|
|
176
|
+
threadId: 'thread-multi-turn',
|
|
177
|
+
errorInfo: {
|
|
178
|
+
exceptionType: 'Error',
|
|
179
|
+
traceback: 'stack',
|
|
180
|
+
},
|
|
181
|
+
};
|
|
182
|
+
expect(params.release).toBe('abc123');
|
|
183
|
+
expect(params.environment).toBe('staging');
|
|
184
|
+
expect(params.externalId).toBe('jira-PROJ-999');
|
|
185
|
+
expect(params.threadId).toBe('thread-multi-turn');
|
|
186
|
+
expect(params.errorInfo).toBeDefined();
|
|
187
|
+
});
|
|
188
|
+
});
|
|
189
|
+
// ---------------------------------------------------------------------------
|
|
190
|
+
// GenerationParams type compatibility
|
|
191
|
+
// ---------------------------------------------------------------------------
|
|
192
|
+
describe('GenerationParams', () => {
|
|
193
|
+
it('should accept the provider field', () => {
|
|
194
|
+
const params = {
|
|
195
|
+
model: 'gpt-4o',
|
|
196
|
+
provider: 'openai',
|
|
197
|
+
};
|
|
198
|
+
expect(params.provider).toBe('openai');
|
|
199
|
+
});
|
|
200
|
+
it('should accept the costDetails field', () => {
|
|
201
|
+
const params = {
|
|
202
|
+
costDetails: { input: 0.015, output: 0.06, cached: 0.0075 },
|
|
203
|
+
};
|
|
204
|
+
expect(params.costDetails.input).toBe(0.015);
|
|
205
|
+
expect(params.costDetails.cached).toBe(0.0075);
|
|
206
|
+
});
|
|
207
|
+
it('should accept the usageDetails field', () => {
|
|
208
|
+
const params = {
|
|
209
|
+
usageDetails: { cachedTokens: 200, audioTokens: 50, reasoningTokens: 1024 },
|
|
210
|
+
};
|
|
211
|
+
expect(params.usageDetails.cachedTokens).toBe(200);
|
|
212
|
+
expect(params.usageDetails.reasoningTokens).toBe(1024);
|
|
213
|
+
});
|
|
214
|
+
it('should accept the errorInfo field', () => {
|
|
215
|
+
const params = {
|
|
216
|
+
errorInfo: {
|
|
217
|
+
exceptionType: 'RateLimitError',
|
|
218
|
+
message: '429 Too Many Requests',
|
|
219
|
+
traceback: 'at OpenAI.request (openai.js:100:1)',
|
|
220
|
+
},
|
|
221
|
+
};
|
|
222
|
+
expect(params.errorInfo.exceptionType).toBe('RateLimitError');
|
|
223
|
+
});
|
|
224
|
+
it('should accept the environment field', () => {
|
|
225
|
+
const params = { environment: 'development' };
|
|
226
|
+
expect(params.environment).toBe('development');
|
|
227
|
+
});
|
|
228
|
+
it('should accept all generation-specific fields together', () => {
|
|
229
|
+
const params = {
|
|
230
|
+
id: 'gen-1',
|
|
231
|
+
name: 'completion',
|
|
232
|
+
model: 'claude-sonnet-4-20250514',
|
|
233
|
+
provider: 'anthropic',
|
|
234
|
+
input: [{ role: 'user', content: 'Hi' }],
|
|
235
|
+
output: { role: 'assistant', content: 'Hello!' },
|
|
236
|
+
usage: { input: 10, output: 5, total: 15, unit: 'TOKENS' },
|
|
237
|
+
usageDetails: { cachedTokens: 3 },
|
|
238
|
+
costDetails: { input: 0.01, output: 0.02 },
|
|
239
|
+
environment: 'production',
|
|
240
|
+
errorInfo: {
|
|
241
|
+
exceptionType: 'None',
|
|
242
|
+
traceback: '',
|
|
243
|
+
},
|
|
244
|
+
level: ObservationLevel.DEFAULT,
|
|
245
|
+
promptName: 'chat-prompt',
|
|
246
|
+
promptVersion: 2,
|
|
247
|
+
modelParameters: { temperature: 0.7 },
|
|
248
|
+
};
|
|
249
|
+
expect(params.provider).toBe('anthropic');
|
|
250
|
+
expect(params.usageDetails.cachedTokens).toBe(3);
|
|
251
|
+
expect(params.costDetails.input).toBe(0.01);
|
|
252
|
+
});
|
|
253
|
+
});
|
|
254
|
+
// ---------------------------------------------------------------------------
|
|
255
|
+
// SpanParams type compatibility
|
|
256
|
+
// ---------------------------------------------------------------------------
|
|
257
|
+
describe('SpanParams', () => {
|
|
258
|
+
it('should accept the type field with ObservationType values', () => {
|
|
259
|
+
const agentSpan = {
|
|
260
|
+
name: 'agent-run',
|
|
261
|
+
type: ObservationType.AGENT,
|
|
262
|
+
};
|
|
263
|
+
expect(agentSpan.type).toBe('AGENT');
|
|
264
|
+
const toolSpan = {
|
|
265
|
+
name: 'tool-call',
|
|
266
|
+
type: ObservationType.TOOL,
|
|
267
|
+
};
|
|
268
|
+
expect(toolSpan.type).toBe('TOOL');
|
|
269
|
+
});
|
|
270
|
+
it('should accept all ObservationType values for the type field', () => {
|
|
271
|
+
const allTypes = Object.values(ObservationType);
|
|
272
|
+
for (const obsType of allTypes) {
|
|
273
|
+
const params = { type: obsType };
|
|
274
|
+
expect(params.type).toBe(obsType);
|
|
275
|
+
}
|
|
276
|
+
});
|
|
277
|
+
it('should accept the model field', () => {
|
|
278
|
+
const params = { model: 'gpt-4o-mini' };
|
|
279
|
+
expect(params.model).toBe('gpt-4o-mini');
|
|
280
|
+
});
|
|
281
|
+
it('should accept the provider field', () => {
|
|
282
|
+
const params = { provider: 'aws_bedrock' };
|
|
283
|
+
expect(params.provider).toBe('aws_bedrock');
|
|
284
|
+
});
|
|
285
|
+
it('should accept the usage field', () => {
|
|
286
|
+
const params = {
|
|
287
|
+
usage: { input: 100, output: 50, total: 150, unit: 'TOKENS' },
|
|
288
|
+
};
|
|
289
|
+
expect(params.usage.total).toBe(150);
|
|
290
|
+
});
|
|
291
|
+
it('should accept the environment field', () => {
|
|
292
|
+
const params = { environment: 'staging' };
|
|
293
|
+
expect(params.environment).toBe('staging');
|
|
294
|
+
});
|
|
295
|
+
it('should accept the errorInfo field', () => {
|
|
296
|
+
const params = {
|
|
297
|
+
errorInfo: {
|
|
298
|
+
exceptionType: 'ConnectionError',
|
|
299
|
+
message: 'Vector DB unreachable',
|
|
300
|
+
traceback: 'at Retriever.search (retriever.ts:55:3)',
|
|
301
|
+
},
|
|
302
|
+
};
|
|
303
|
+
expect(params.errorInfo.exceptionType).toBe('ConnectionError');
|
|
304
|
+
});
|
|
305
|
+
it('should accept all new fields together for a retriever span', () => {
|
|
306
|
+
const params = {
|
|
307
|
+
name: 'vector-search',
|
|
308
|
+
type: ObservationType.RETRIEVER,
|
|
309
|
+
model: 'text-embedding-3-small',
|
|
310
|
+
provider: 'openai',
|
|
311
|
+
usage: { input: 50, total: 50 },
|
|
312
|
+
environment: 'production',
|
|
313
|
+
errorInfo: {
|
|
314
|
+
exceptionType: 'None',
|
|
315
|
+
traceback: '',
|
|
316
|
+
},
|
|
317
|
+
};
|
|
318
|
+
expect(params.type).toBe('RETRIEVER');
|
|
319
|
+
expect(params.model).toBe('text-embedding-3-small');
|
|
320
|
+
expect(params.provider).toBe('openai');
|
|
321
|
+
});
|
|
322
|
+
});
|
|
323
|
+
// ---------------------------------------------------------------------------
|
|
324
|
+
// ScoreParams type compatibility
|
|
325
|
+
// ---------------------------------------------------------------------------
|
|
326
|
+
describe('ScoreParams', () => {
|
|
327
|
+
it('should require traceId, name, and value', () => {
|
|
328
|
+
const params = {
|
|
329
|
+
traceId: 'trace-1',
|
|
330
|
+
name: 'accuracy',
|
|
331
|
+
value: 0.95,
|
|
332
|
+
};
|
|
333
|
+
expect(params.traceId).toBe('trace-1');
|
|
334
|
+
expect(params.name).toBe('accuracy');
|
|
335
|
+
expect(params.value).toBe(0.95);
|
|
336
|
+
});
|
|
337
|
+
describe('dataType', () => {
|
|
338
|
+
it.each(['NUMERIC', 'BOOLEAN', 'CATEGORICAL', 'CORRECTION'])('should accept dataType = "%s"', (dataType) => {
|
|
339
|
+
const params = {
|
|
340
|
+
traceId: 'trace-1',
|
|
341
|
+
name: 'metric',
|
|
342
|
+
value: 1,
|
|
343
|
+
dataType,
|
|
344
|
+
};
|
|
345
|
+
expect(params.dataType).toBe(dataType);
|
|
346
|
+
});
|
|
347
|
+
});
|
|
348
|
+
describe('source', () => {
|
|
349
|
+
it.each(['API', 'EVAL', 'ANNOTATION'])('should accept source = "%s"', (source) => {
|
|
350
|
+
const params = {
|
|
351
|
+
traceId: 'trace-1',
|
|
352
|
+
name: 'metric',
|
|
353
|
+
value: 1,
|
|
354
|
+
source,
|
|
355
|
+
};
|
|
356
|
+
expect(params.source).toBe(source);
|
|
357
|
+
});
|
|
358
|
+
});
|
|
359
|
+
it('should accept the metadata field', () => {
|
|
360
|
+
const params = {
|
|
361
|
+
traceId: 'trace-1',
|
|
362
|
+
name: 'quality',
|
|
363
|
+
value: 0.8,
|
|
364
|
+
metadata: { evaluatorVersion: '2.0', runId: 'eval-run-42' },
|
|
365
|
+
};
|
|
366
|
+
expect(params.metadata.evaluatorVersion).toBe('2.0');
|
|
367
|
+
});
|
|
368
|
+
it('should accept the sessionId field', () => {
|
|
369
|
+
const params = {
|
|
370
|
+
traceId: 'trace-1',
|
|
371
|
+
name: 'session-quality',
|
|
372
|
+
value: 4,
|
|
373
|
+
sessionId: 'session-abc',
|
|
374
|
+
};
|
|
375
|
+
expect(params.sessionId).toBe('session-abc');
|
|
376
|
+
});
|
|
377
|
+
it('should accept the stringValue field', () => {
|
|
378
|
+
const params = {
|
|
379
|
+
traceId: 'trace-1',
|
|
380
|
+
name: 'sentiment',
|
|
381
|
+
value: 1,
|
|
382
|
+
dataType: 'CATEGORICAL',
|
|
383
|
+
stringValue: 'positive',
|
|
384
|
+
};
|
|
385
|
+
expect(params.stringValue).toBe('positive');
|
|
386
|
+
});
|
|
387
|
+
it('should accept the environment field', () => {
|
|
388
|
+
const params = {
|
|
389
|
+
traceId: 'trace-1',
|
|
390
|
+
name: 'metric',
|
|
391
|
+
value: 1,
|
|
392
|
+
environment: 'production',
|
|
393
|
+
};
|
|
394
|
+
expect(params.environment).toBe('production');
|
|
395
|
+
});
|
|
396
|
+
it('should accept all optional fields together', () => {
|
|
397
|
+
const params = {
|
|
398
|
+
id: 'score-1',
|
|
399
|
+
traceId: 'trace-1',
|
|
400
|
+
observationId: 'gen-1',
|
|
401
|
+
sessionId: 'session-1',
|
|
402
|
+
name: 'comprehensive-score',
|
|
403
|
+
value: 0.75,
|
|
404
|
+
stringValue: 'good',
|
|
405
|
+
comment: 'Mostly correct but missed edge case',
|
|
406
|
+
dataType: 'CATEGORICAL',
|
|
407
|
+
source: 'ANNOTATION',
|
|
408
|
+
metadata: { annotatorId: 'user-5', round: 2 },
|
|
409
|
+
configId: 'config-abc',
|
|
410
|
+
environment: 'staging',
|
|
411
|
+
};
|
|
412
|
+
expect(params.dataType).toBe('CATEGORICAL');
|
|
413
|
+
expect(params.source).toBe('ANNOTATION');
|
|
414
|
+
expect(params.stringValue).toBe('good');
|
|
415
|
+
expect(params.metadata.round).toBe(2);
|
|
416
|
+
});
|
|
417
|
+
});
|
|
418
|
+
// ---------------------------------------------------------------------------
|
|
419
|
+
// UsageParams and UsageDetailsParams
|
|
420
|
+
// ---------------------------------------------------------------------------
|
|
421
|
+
describe('UsageParams', () => {
|
|
422
|
+
it('should accept all standard usage fields', () => {
|
|
423
|
+
const usage = {
|
|
424
|
+
input: 100,
|
|
425
|
+
output: 50,
|
|
426
|
+
total: 150,
|
|
427
|
+
unit: 'TOKENS',
|
|
428
|
+
inputCost: 0.01,
|
|
429
|
+
outputCost: 0.02,
|
|
430
|
+
totalCost: 0.03,
|
|
431
|
+
};
|
|
432
|
+
expect(usage.total).toBe(150);
|
|
433
|
+
expect(usage.totalCost).toBe(0.03);
|
|
434
|
+
});
|
|
435
|
+
it('should allow partial usage (all fields optional)', () => {
|
|
436
|
+
const usage = { total: 42 };
|
|
437
|
+
expect(usage.total).toBe(42);
|
|
438
|
+
expect(usage.input).toBeUndefined();
|
|
439
|
+
});
|
|
440
|
+
});
|
|
441
|
+
describe('UsageDetailsParams', () => {
|
|
442
|
+
it('should accept arbitrary string keys with numeric values', () => {
|
|
443
|
+
const details = {
|
|
444
|
+
cachedTokens: 200,
|
|
445
|
+
audioTokens: 50,
|
|
446
|
+
reasoningTokens: 1024,
|
|
447
|
+
imageTokens: 0,
|
|
448
|
+
};
|
|
449
|
+
expect(details.cachedTokens).toBe(200);
|
|
450
|
+
expect(Object.keys(details)).toHaveLength(4);
|
|
451
|
+
});
|
|
452
|
+
});
|
|
453
|
+
//# sourceMappingURL=types.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.test.js","sourceRoot":"","sources":["../../src/__tests__/types.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/utils.test.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unit tests for observability SDK utility functions.
|
|
3
|
+
*
|
|
4
|
+
* Covers: generateId, currentISOTimestamp, safeStringify, encodeBasicAuth, backoffDelay.
|
|
5
|
+
*/
|
|
6
|
+
import { describe, it, expect } from 'vitest';
|
|
7
|
+
import { generateId, currentISOTimestamp, safeStringify, encodeBasicAuth, backoffDelay, } from '../utils.js';
|
|
8
|
+
// ---------------------------------------------------------------------------
|
|
9
|
+
// generateId
|
|
10
|
+
// ---------------------------------------------------------------------------
|
|
11
|
+
describe('generateId', () => {
|
|
12
|
+
it('should return a string', () => {
|
|
13
|
+
expect(typeof generateId()).toBe('string');
|
|
14
|
+
});
|
|
15
|
+
it('should return unique values on consecutive calls', () => {
|
|
16
|
+
const ids = new Set(Array.from({ length: 100 }, () => generateId()));
|
|
17
|
+
expect(ids.size).toBe(100);
|
|
18
|
+
});
|
|
19
|
+
it('should return a valid UUID format', () => {
|
|
20
|
+
const id = generateId();
|
|
21
|
+
// Standard UUID v4 pattern: 8-4-4-4-12 hex chars
|
|
22
|
+
expect(id).toMatch(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/);
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
// ---------------------------------------------------------------------------
|
|
26
|
+
// currentISOTimestamp
|
|
27
|
+
// ---------------------------------------------------------------------------
|
|
28
|
+
describe('currentISOTimestamp', () => {
|
|
29
|
+
it('should return a valid ISO-8601 string', () => {
|
|
30
|
+
const ts = currentISOTimestamp();
|
|
31
|
+
// ISO format: YYYY-MM-DDTHH:MM:SS.sssZ
|
|
32
|
+
expect(ts).toMatch(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/);
|
|
33
|
+
});
|
|
34
|
+
it('should return the current time', () => {
|
|
35
|
+
const before = Date.now();
|
|
36
|
+
const ts = currentISOTimestamp();
|
|
37
|
+
const after = Date.now();
|
|
38
|
+
const parsed = new Date(ts).getTime();
|
|
39
|
+
expect(parsed).toBeGreaterThanOrEqual(before);
|
|
40
|
+
expect(parsed).toBeLessThanOrEqual(after);
|
|
41
|
+
});
|
|
42
|
+
it('should return a parseable Date string', () => {
|
|
43
|
+
const ts = currentISOTimestamp();
|
|
44
|
+
const date = new Date(ts);
|
|
45
|
+
expect(date.toISOString()).toBe(ts);
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
// ---------------------------------------------------------------------------
|
|
49
|
+
// safeStringify
|
|
50
|
+
// ---------------------------------------------------------------------------
|
|
51
|
+
describe('safeStringify', () => {
|
|
52
|
+
it('should stringify plain objects', () => {
|
|
53
|
+
const result = safeStringify({ a: 1, b: 'two' });
|
|
54
|
+
expect(JSON.parse(result)).toEqual({ a: 1, b: 'two' });
|
|
55
|
+
});
|
|
56
|
+
it('should handle circular references without throwing', () => {
|
|
57
|
+
const obj = { name: 'root' };
|
|
58
|
+
obj.self = obj;
|
|
59
|
+
const result = safeStringify(obj);
|
|
60
|
+
expect(result).toContain('"name":"root"');
|
|
61
|
+
expect(result).toContain('[Circular]');
|
|
62
|
+
});
|
|
63
|
+
it('should handle nested circular references', () => {
|
|
64
|
+
const a = { label: 'a' };
|
|
65
|
+
const b = { label: 'b', parent: a };
|
|
66
|
+
a.child = b;
|
|
67
|
+
b.grandchild = a; // circular back to a
|
|
68
|
+
const result = safeStringify(a);
|
|
69
|
+
expect(result).toContain('[Circular]');
|
|
70
|
+
expect(result).toContain('"label":"a"');
|
|
71
|
+
});
|
|
72
|
+
it('should handle BigInt values by converting to string', () => {
|
|
73
|
+
const result = safeStringify({ big: BigInt(9007199254740991) });
|
|
74
|
+
const parsed = JSON.parse(result);
|
|
75
|
+
expect(parsed.big).toBe('9007199254740991');
|
|
76
|
+
});
|
|
77
|
+
it('should handle null and undefined', () => {
|
|
78
|
+
expect(safeStringify(null)).toBe('null');
|
|
79
|
+
// undefined at top level is converted via String()
|
|
80
|
+
expect(safeStringify(undefined)).toBe(undefined);
|
|
81
|
+
});
|
|
82
|
+
it('should support indent parameter', () => {
|
|
83
|
+
const result = safeStringify({ a: 1 }, 2);
|
|
84
|
+
expect(result).toContain('\n');
|
|
85
|
+
expect(result).toContain(' ');
|
|
86
|
+
});
|
|
87
|
+
it('should stringify arrays', () => {
|
|
88
|
+
const result = safeStringify([1, 2, 3]);
|
|
89
|
+
expect(JSON.parse(result)).toEqual([1, 2, 3]);
|
|
90
|
+
});
|
|
91
|
+
it('should stringify nested objects', () => {
|
|
92
|
+
const result = safeStringify({ a: { b: { c: 42 } } });
|
|
93
|
+
expect(JSON.parse(result)).toEqual({ a: { b: { c: 42 } } });
|
|
94
|
+
});
|
|
95
|
+
});
|
|
96
|
+
// ---------------------------------------------------------------------------
|
|
97
|
+
// encodeBasicAuth
|
|
98
|
+
// ---------------------------------------------------------------------------
|
|
99
|
+
describe('encodeBasicAuth', () => {
|
|
100
|
+
it('should produce a Basic auth header string', () => {
|
|
101
|
+
const result = encodeBasicAuth('public', 'secret');
|
|
102
|
+
expect(result).toMatch(/^Basic .+$/);
|
|
103
|
+
});
|
|
104
|
+
it('should encode credentials as base64', () => {
|
|
105
|
+
const result = encodeBasicAuth('pk-abc', 'sk-xyz');
|
|
106
|
+
const expected = `Basic ${Buffer.from('pk-abc:sk-xyz').toString('base64')}`;
|
|
107
|
+
expect(result).toBe(expected);
|
|
108
|
+
});
|
|
109
|
+
it('should handle special characters in keys', () => {
|
|
110
|
+
const result = encodeBasicAuth('pk+special/key=', 'sk:pass@word!');
|
|
111
|
+
const expected = `Basic ${Buffer.from('pk+special/key=:sk:pass@word!').toString('base64')}`;
|
|
112
|
+
expect(result).toBe(expected);
|
|
113
|
+
});
|
|
114
|
+
it('should handle empty strings', () => {
|
|
115
|
+
const result = encodeBasicAuth('', '');
|
|
116
|
+
const expected = `Basic ${Buffer.from(':').toString('base64')}`;
|
|
117
|
+
expect(result).toBe(expected);
|
|
118
|
+
});
|
|
119
|
+
});
|
|
120
|
+
// ---------------------------------------------------------------------------
|
|
121
|
+
// backoffDelay
|
|
122
|
+
// ---------------------------------------------------------------------------
|
|
123
|
+
describe('backoffDelay', () => {
|
|
124
|
+
it('should return a number', () => {
|
|
125
|
+
expect(typeof backoffDelay(0)).toBe('number');
|
|
126
|
+
});
|
|
127
|
+
it('should increase with attempt number on average', () => {
|
|
128
|
+
// Run many samples to account for jitter
|
|
129
|
+
const samples = 50;
|
|
130
|
+
const avgAttempt0 = Array.from({ length: samples }, () => backoffDelay(0)).reduce((a, b) => a + b, 0) / samples;
|
|
131
|
+
const avgAttempt3 = Array.from({ length: samples }, () => backoffDelay(3)).reduce((a, b) => a + b, 0) / samples;
|
|
132
|
+
expect(avgAttempt3).toBeGreaterThan(avgAttempt0);
|
|
133
|
+
});
|
|
134
|
+
it('should respect the 30 second cap', () => {
|
|
135
|
+
// Very high attempt number should still be capped
|
|
136
|
+
for (let i = 0; i < 20; i++) {
|
|
137
|
+
const delay = backoffDelay(20);
|
|
138
|
+
expect(delay).toBeLessThanOrEqual(30_000);
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
it('should use exponential growth (base * 2^attempt)', () => {
|
|
142
|
+
// With jitter of up to 25%, the delay should be between base*2^n and base*2^n*1.25
|
|
143
|
+
const baseMs = 1000;
|
|
144
|
+
for (let attempt = 0; attempt < 4; attempt++) {
|
|
145
|
+
const exponential = baseMs * Math.pow(2, attempt);
|
|
146
|
+
const delay = backoffDelay(attempt, baseMs);
|
|
147
|
+
expect(delay).toBeGreaterThanOrEqual(exponential);
|
|
148
|
+
expect(delay).toBeLessThanOrEqual(exponential * 1.25);
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
it('should accept a custom base delay', () => {
|
|
152
|
+
const delay = backoffDelay(0, 500);
|
|
153
|
+
// Attempt 0 with base 500: 500 + jitter (up to 125)
|
|
154
|
+
expect(delay).toBeGreaterThanOrEqual(500);
|
|
155
|
+
expect(delay).toBeLessThanOrEqual(625);
|
|
156
|
+
});
|
|
157
|
+
it('should add jitter (non-deterministic within range)', () => {
|
|
158
|
+
// Two calls with the same attempt should very likely produce different values
|
|
159
|
+
// (only fails with probability ~1/2^52)
|
|
160
|
+
const delays = new Set(Array.from({ length: 10 }, () => backoffDelay(2)));
|
|
161
|
+
expect(delays.size).toBeGreaterThan(1);
|
|
162
|
+
});
|
|
163
|
+
});
|
|
164
|
+
//# sourceMappingURL=utils.test.js.map
|