@illuma-ai/observability-node 0.1.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.
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Integration tests for the Node.js Observability client.
3
+ *
4
+ * Validates environment variable resolution (ILLUMA_* and LANGFUSE_* fallback),
5
+ * class inheritance from ObservabilityCoreClient, fetchWithRetry implementation,
6
+ * and process exit handler registration.
7
+ */
8
+ export {};
9
+ //# sourceMappingURL=client.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/client.test.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG"}
@@ -0,0 +1,235 @@
1
+ /**
2
+ * Integration tests for the Node.js Observability client.
3
+ *
4
+ * Validates environment variable resolution (ILLUMA_* and LANGFUSE_* fallback),
5
+ * class inheritance from ObservabilityCoreClient, fetchWithRetry implementation,
6
+ * and process exit handler registration.
7
+ */
8
+ import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
9
+ import { Observability } from '../client.js';
10
+ import { ObservabilityCoreClient } from '@illuma-ai/observability-core';
11
+ // ---------------------------------------------------------------------------
12
+ // Environment variable helpers
13
+ // ---------------------------------------------------------------------------
14
+ const ENV_KEYS = [
15
+ 'ILLUMA_PUBLIC_KEY',
16
+ 'ILLUMA_SECRET_KEY',
17
+ 'ILLUMA_BASE_URL',
18
+ 'LANGFUSE_PUBLIC_KEY',
19
+ 'LANGFUSE_SECRET_KEY',
20
+ 'LANGFUSE_BASE_URL',
21
+ ];
22
+ /** Save and clear all relevant env vars before each test. */
23
+ function clearEnvVars() {
24
+ const saved = {};
25
+ for (const key of ENV_KEYS) {
26
+ saved[key] = process.env[key];
27
+ delete process.env[key];
28
+ }
29
+ return saved;
30
+ }
31
+ /** Restore previously saved env vars. */
32
+ function restoreEnvVars(saved) {
33
+ for (const [key, value] of Object.entries(saved)) {
34
+ if (value === undefined) {
35
+ delete process.env[key];
36
+ }
37
+ else {
38
+ process.env[key] = value;
39
+ }
40
+ }
41
+ }
42
+ // ---------------------------------------------------------------------------
43
+ // Tests
44
+ // ---------------------------------------------------------------------------
45
+ describe('Observability (Node.js client)', () => {
46
+ let savedEnv;
47
+ let processOnSpy;
48
+ beforeEach(() => {
49
+ savedEnv = clearEnvVars();
50
+ // Spy on process.on to verify exit handler registration without side effects
51
+ processOnSpy = vi.spyOn(process, 'on');
52
+ });
53
+ afterEach(() => {
54
+ restoreEnvVars(savedEnv);
55
+ processOnSpy.mockRestore();
56
+ });
57
+ // -------------------------------------------------------------------------
58
+ // Env var reading
59
+ // -------------------------------------------------------------------------
60
+ describe('environment variable reading', () => {
61
+ it('should read ILLUMA_PUBLIC_KEY, ILLUMA_SECRET_KEY, ILLUMA_BASE_URL', () => {
62
+ process.env.ILLUMA_PUBLIC_KEY = 'pk-illuma';
63
+ process.env.ILLUMA_SECRET_KEY = 'sk-illuma';
64
+ process.env.ILLUMA_BASE_URL = 'https://observe.illuma.ai';
65
+ const client = new Observability({ flushInterval: 0 });
66
+ // Client should have been created without errors
67
+ expect(client).toBeInstanceOf(Observability);
68
+ // Verify it produces traces (which proves it read the keys)
69
+ const trace = client.trace({ name: 'env-test' });
70
+ expect(trace).toBeDefined();
71
+ });
72
+ it('should fall back to LANGFUSE_PUBLIC_KEY when ILLUMA_PUBLIC_KEY is not set', () => {
73
+ process.env.LANGFUSE_PUBLIC_KEY = 'pk-langfuse';
74
+ process.env.LANGFUSE_SECRET_KEY = 'sk-langfuse';
75
+ process.env.LANGFUSE_BASE_URL = 'https://cloud.langfuse.com';
76
+ const client = new Observability({ flushInterval: 0 });
77
+ expect(client).toBeInstanceOf(Observability);
78
+ });
79
+ it('should prefer ILLUMA_* over LANGFUSE_* when both are set', () => {
80
+ process.env.ILLUMA_PUBLIC_KEY = 'pk-illuma';
81
+ process.env.ILLUMA_SECRET_KEY = 'sk-illuma';
82
+ process.env.ILLUMA_BASE_URL = 'https://observe.illuma.ai';
83
+ process.env.LANGFUSE_PUBLIC_KEY = 'pk-langfuse';
84
+ process.env.LANGFUSE_SECRET_KEY = 'sk-langfuse';
85
+ process.env.LANGFUSE_BASE_URL = 'https://cloud.langfuse.com';
86
+ // We can't directly inspect which key was used, but the constructor
87
+ // should succeed and prefer ILLUMA_* (verified by the code path)
88
+ const client = new Observability({ flushInterval: 0 });
89
+ expect(client).toBeInstanceOf(Observability);
90
+ });
91
+ it('should prefer explicit constructor args over env vars', () => {
92
+ process.env.ILLUMA_PUBLIC_KEY = 'pk-env';
93
+ process.env.ILLUMA_SECRET_KEY = 'sk-env';
94
+ process.env.ILLUMA_BASE_URL = 'https://env.example.com';
95
+ const client = new Observability({
96
+ publicKey: 'pk-explicit',
97
+ secretKey: 'sk-explicit',
98
+ baseUrl: 'https://explicit.example.com',
99
+ flushInterval: 0,
100
+ });
101
+ expect(client).toBeInstanceOf(Observability);
102
+ });
103
+ it('should throw when publicKey is not available from any source', () => {
104
+ process.env.ILLUMA_SECRET_KEY = 'sk-test';
105
+ process.env.ILLUMA_BASE_URL = 'https://observe.test';
106
+ expect(() => new Observability()).toThrow('publicKey is required');
107
+ });
108
+ it('should throw when secretKey is not available from any source', () => {
109
+ process.env.ILLUMA_PUBLIC_KEY = 'pk-test';
110
+ process.env.ILLUMA_BASE_URL = 'https://observe.test';
111
+ expect(() => new Observability()).toThrow('secretKey is required');
112
+ });
113
+ it('should throw when baseUrl is not available from any source', () => {
114
+ process.env.ILLUMA_PUBLIC_KEY = 'pk-test';
115
+ process.env.ILLUMA_SECRET_KEY = 'sk-test';
116
+ expect(() => new Observability()).toThrow('baseUrl is required');
117
+ });
118
+ });
119
+ // -------------------------------------------------------------------------
120
+ // Extends core correctly
121
+ // -------------------------------------------------------------------------
122
+ describe('class inheritance', () => {
123
+ it('should extend ObservabilityCoreClient', () => {
124
+ process.env.ILLUMA_PUBLIC_KEY = 'pk-test';
125
+ process.env.ILLUMA_SECRET_KEY = 'sk-test';
126
+ process.env.ILLUMA_BASE_URL = 'https://observe.test';
127
+ const client = new Observability({ flushInterval: 0 });
128
+ expect(client).toBeInstanceOf(ObservabilityCoreClient);
129
+ });
130
+ it('should expose trace() method from the core client', () => {
131
+ process.env.ILLUMA_PUBLIC_KEY = 'pk-test';
132
+ process.env.ILLUMA_SECRET_KEY = 'sk-test';
133
+ process.env.ILLUMA_BASE_URL = 'https://observe.test';
134
+ const client = new Observability({ flushInterval: 0 });
135
+ expect(typeof client.trace).toBe('function');
136
+ expect(typeof client.flush).toBe('function');
137
+ expect(typeof client.shutdown).toBe('function');
138
+ expect(typeof client.score).toBe('function');
139
+ });
140
+ it('should support the full trace -> span -> generation chain', () => {
141
+ process.env.ILLUMA_PUBLIC_KEY = 'pk-test';
142
+ process.env.ILLUMA_SECRET_KEY = 'sk-test';
143
+ process.env.ILLUMA_BASE_URL = 'https://observe.test';
144
+ const client = new Observability({ flushInterval: 0 });
145
+ const trace = client.trace({ name: 'test-trace' });
146
+ const span = trace.span({ name: 'test-span' });
147
+ const gen = span.generation({ name: 'test-gen', model: 'gpt-4o' });
148
+ gen.end({ output: 'done' });
149
+ span.end();
150
+ // All operations should have enqueued events
151
+ expect(client.getQueue().length).toBeGreaterThan(0);
152
+ });
153
+ });
154
+ // -------------------------------------------------------------------------
155
+ // fetchWithRetry with mocked fetch
156
+ // -------------------------------------------------------------------------
157
+ describe('fetchWithRetry', () => {
158
+ it('should send events to the server via native fetch', async () => {
159
+ process.env.ILLUMA_PUBLIC_KEY = 'pk-test';
160
+ process.env.ILLUMA_SECRET_KEY = 'sk-test';
161
+ process.env.ILLUMA_BASE_URL = 'https://observe.test';
162
+ const mockFetch = vi.fn().mockResolvedValue({
163
+ status: 200,
164
+ statusText: 'OK',
165
+ ok: true,
166
+ json: async () => ({ successes: [], errors: [] }),
167
+ text: async () => '',
168
+ });
169
+ // Replace global fetch for this test
170
+ const originalFetch = globalThis.fetch;
171
+ globalThis.fetch = mockFetch;
172
+ try {
173
+ const client = new Observability({ flushInterval: 0 });
174
+ client.trace({ name: 'fetch-test' });
175
+ await client.flush();
176
+ expect(mockFetch).toHaveBeenCalledTimes(1);
177
+ const [url, options] = mockFetch.mock.calls[0];
178
+ expect(url).toBe('https://observe.test/api/public/ingestion');
179
+ expect(options.method).toBe('POST');
180
+ expect(options.headers['Content-Type']).toBe('application/json');
181
+ expect(options.headers['Authorization']).toMatch(/^Basic /);
182
+ }
183
+ finally {
184
+ globalThis.fetch = originalFetch;
185
+ }
186
+ });
187
+ it('should handle fetch errors gracefully', async () => {
188
+ process.env.ILLUMA_PUBLIC_KEY = 'pk-test';
189
+ process.env.ILLUMA_SECRET_KEY = 'sk-test';
190
+ process.env.ILLUMA_BASE_URL = 'https://observe.test';
191
+ const mockFetch = vi.fn().mockRejectedValue(new Error('Network error'));
192
+ const originalFetch = globalThis.fetch;
193
+ globalThis.fetch = mockFetch;
194
+ // Suppress error output during test
195
+ const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => { });
196
+ try {
197
+ const client = new Observability({
198
+ flushInterval: 0,
199
+ maxRetries: 0,
200
+ });
201
+ client.trace({ name: 'error-test' });
202
+ await client.flush();
203
+ // Events should be re-queued after failure
204
+ expect(client.getQueue().length).toBeGreaterThan(0);
205
+ }
206
+ finally {
207
+ globalThis.fetch = originalFetch;
208
+ consoleSpy.mockRestore();
209
+ }
210
+ });
211
+ });
212
+ // -------------------------------------------------------------------------
213
+ // Process exit handler registration
214
+ // -------------------------------------------------------------------------
215
+ describe('process exit handler', () => {
216
+ it('should register a beforeExit handler on construction', () => {
217
+ process.env.ILLUMA_PUBLIC_KEY = 'pk-test';
218
+ process.env.ILLUMA_SECRET_KEY = 'sk-test';
219
+ process.env.ILLUMA_BASE_URL = 'https://observe.test';
220
+ new Observability({ flushInterval: 0 });
221
+ expect(processOnSpy).toHaveBeenCalledWith('beforeExit', expect.any(Function));
222
+ });
223
+ it('should only register one exit handler even if multiple instances are created', () => {
224
+ process.env.ILLUMA_PUBLIC_KEY = 'pk-test';
225
+ process.env.ILLUMA_SECRET_KEY = 'sk-test';
226
+ process.env.ILLUMA_BASE_URL = 'https://observe.test';
227
+ // Each instance registers its own handler (per-instance guard)
228
+ const client1 = new Observability({ flushInterval: 0 });
229
+ // Creating the same instance again would still register (separate instance)
230
+ // But the guard prevents re-registration on the same instance
231
+ expect(processOnSpy).toHaveBeenCalledWith('beforeExit', expect.any(Function));
232
+ });
233
+ });
234
+ });
235
+ //# sourceMappingURL=client.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.test.js","sourceRoot":"","sources":["../../src/__tests__/client.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Integration tests for the observeOpenAI wrapper.
3
+ *
4
+ * Validates that the OpenAI client Proxy intercepts chat.completions.create,
5
+ * records generation events with correct model/usage data, and handles
6
+ * errors by creating ERROR-level generation events.
7
+ */
8
+ export {};
9
+ //# sourceMappingURL=openai.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/openai.test.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG"}
@@ -0,0 +1,370 @@
1
+ /**
2
+ * Integration tests for the observeOpenAI wrapper.
3
+ *
4
+ * Validates that the OpenAI client Proxy intercepts chat.completions.create,
5
+ * records generation events with correct model/usage data, and handles
6
+ * errors by creating ERROR-level generation events.
7
+ */
8
+ import { describe, it, expect, vi, beforeEach } from 'vitest';
9
+ import { observeOpenAI } from '../openai.js';
10
+ import { Observability } from '../client.js';
11
+ import { ObservationLevel } from '@illuma-ai/observability-core';
12
+ // ---------------------------------------------------------------------------
13
+ // Mock OpenAI client
14
+ // ---------------------------------------------------------------------------
15
+ function createMockOpenAI(overrides = {}) {
16
+ const defaultChatResponse = {
17
+ id: 'chatcmpl-abc123',
18
+ model: 'gpt-4o-2024-08-06',
19
+ choices: [
20
+ {
21
+ message: { role: 'assistant', content: 'Hello! How can I help you?' },
22
+ finish_reason: 'stop',
23
+ },
24
+ ],
25
+ usage: {
26
+ prompt_tokens: 10,
27
+ completion_tokens: 8,
28
+ total_tokens: 18,
29
+ },
30
+ };
31
+ const defaultCompletionResponse = {
32
+ id: 'cmpl-xyz789',
33
+ model: 'gpt-3.5-turbo-instruct',
34
+ choices: [
35
+ {
36
+ text: 'The answer is 42.',
37
+ finish_reason: 'stop',
38
+ },
39
+ ],
40
+ usage: {
41
+ prompt_tokens: 5,
42
+ completion_tokens: 6,
43
+ total_tokens: 11,
44
+ },
45
+ };
46
+ return {
47
+ chat: {
48
+ completions: {
49
+ create: vi.fn().mockImplementation(async () => {
50
+ if (overrides.chatError)
51
+ throw overrides.chatError;
52
+ return overrides.chatResponse ?? defaultChatResponse;
53
+ }),
54
+ },
55
+ },
56
+ completions: {
57
+ create: vi.fn().mockImplementation(async () => {
58
+ if (overrides.completionError)
59
+ throw overrides.completionError;
60
+ return overrides.completionResponse ?? defaultCompletionResponse;
61
+ }),
62
+ },
63
+ };
64
+ }
65
+ // ---------------------------------------------------------------------------
66
+ // Mock Observability client (avoid real network + env var requirements)
67
+ // ---------------------------------------------------------------------------
68
+ function createMockObservability() {
69
+ // Mock global fetch so the Observability constructor's fetchWithRetry works
70
+ const originalFetch = globalThis.fetch;
71
+ globalThis.fetch = vi.fn().mockResolvedValue({
72
+ status: 200,
73
+ statusText: 'OK',
74
+ ok: true,
75
+ json: async () => ({ successes: [], errors: [] }),
76
+ text: async () => '',
77
+ });
78
+ const client = new Observability({
79
+ publicKey: 'pk-test',
80
+ secretKey: 'sk-test',
81
+ baseUrl: 'https://observe.test',
82
+ flushInterval: 0,
83
+ flushAt: 1000, // High threshold to prevent auto-flush during tests
84
+ });
85
+ // Restore fetch after construction
86
+ globalThis.fetch = originalFetch;
87
+ // Expose getQueue with a different name to avoid confusion
88
+ return Object.assign(client, {
89
+ _getQueueDirect: () => client.getQueue(),
90
+ });
91
+ }
92
+ // ---------------------------------------------------------------------------
93
+ // Tests
94
+ // ---------------------------------------------------------------------------
95
+ describe('observeOpenAI', () => {
96
+ let observability;
97
+ beforeEach(() => {
98
+ observability = createMockObservability();
99
+ });
100
+ // -------------------------------------------------------------------------
101
+ // Wrapping
102
+ // -------------------------------------------------------------------------
103
+ describe('wrapping', () => {
104
+ it('should return a proxied client with the same interface', () => {
105
+ const openai = createMockOpenAI();
106
+ const wrapped = observeOpenAI(openai, observability);
107
+ // Should have the same top-level properties
108
+ expect(wrapped.chat).toBeDefined();
109
+ expect(wrapped.chat.completions).toBeDefined();
110
+ expect(typeof wrapped.chat.completions.create).toBe('function');
111
+ expect(wrapped.completions).toBeDefined();
112
+ expect(typeof wrapped.completions.create).toBe('function');
113
+ });
114
+ it('should preserve non-intercepted properties via proxy pass-through', () => {
115
+ const openai = createMockOpenAI();
116
+ openai.models = { list: vi.fn().mockResolvedValue([]) };
117
+ const wrapped = observeOpenAI(openai, observability);
118
+ // Non-intercepted properties should pass through
119
+ expect(wrapped.models).toBeDefined();
120
+ expect(wrapped.models.list).toBe(openai.models.list);
121
+ });
122
+ });
123
+ // -------------------------------------------------------------------------
124
+ // chat.completions.create interception
125
+ // -------------------------------------------------------------------------
126
+ describe('chat.completions.create interception', () => {
127
+ it('should call the original create method and return its result', async () => {
128
+ const openai = createMockOpenAI();
129
+ const wrapped = observeOpenAI(openai, observability);
130
+ const result = await wrapped.chat.completions.create({
131
+ model: 'gpt-4o',
132
+ messages: [{ role: 'user', content: 'Hello' }],
133
+ });
134
+ // Should return the original response
135
+ expect(result).toMatchObject({
136
+ id: 'chatcmpl-abc123',
137
+ choices: expect.any(Array),
138
+ });
139
+ // Should have called the original function
140
+ expect(openai.chat.completions.create).toHaveBeenCalledTimes(1);
141
+ });
142
+ it('should create trace and generation events', async () => {
143
+ const openai = createMockOpenAI();
144
+ const wrapped = observeOpenAI(openai, observability);
145
+ await wrapped.chat.completions.create({
146
+ model: 'gpt-4o',
147
+ messages: [{ role: 'user', content: 'Hello' }],
148
+ });
149
+ const queue = observability._getQueueDirect();
150
+ // Should have at least a trace-create and generation-create
151
+ const types = queue.map((e) => e.type);
152
+ expect(types).toContain('trace-create');
153
+ expect(types).toContain('generation-create');
154
+ });
155
+ it('should record correct model in generation event', async () => {
156
+ const openai = createMockOpenAI();
157
+ const wrapped = observeOpenAI(openai, observability);
158
+ await wrapped.chat.completions.create({
159
+ model: 'gpt-4o',
160
+ messages: [{ role: 'user', content: 'Test' }],
161
+ });
162
+ const queue = observability._getQueueDirect();
163
+ const genEvent = queue.find((e) => e.type === 'generation-create');
164
+ expect(genEvent.body.model).toBe('gpt-4o');
165
+ expect(genEvent.body.name).toBe('chat.completions.create');
166
+ });
167
+ it('should record correct usage in generation event', async () => {
168
+ const openai = createMockOpenAI();
169
+ const wrapped = observeOpenAI(openai, observability);
170
+ await wrapped.chat.completions.create({
171
+ model: 'gpt-4o',
172
+ messages: [{ role: 'user', content: 'Test' }],
173
+ });
174
+ const queue = observability._getQueueDirect();
175
+ const genEvent = queue.find((e) => e.type === 'generation-create');
176
+ expect(genEvent.body.usage).toMatchObject({
177
+ input: 10,
178
+ output: 8,
179
+ total: 18,
180
+ });
181
+ });
182
+ it('should record input messages and output message', async () => {
183
+ const openai = createMockOpenAI();
184
+ const wrapped = observeOpenAI(openai, observability);
185
+ const messages = [{ role: 'user', content: 'What is 2+2?' }];
186
+ await wrapped.chat.completions.create({
187
+ model: 'gpt-4o',
188
+ messages,
189
+ });
190
+ const queue = observability._getQueueDirect();
191
+ const genEvent = queue.find((e) => e.type === 'generation-create');
192
+ expect(genEvent.body.input).toEqual(messages);
193
+ expect(genEvent.body.output).toMatchObject({
194
+ role: 'assistant',
195
+ content: 'Hello! How can I help you?',
196
+ });
197
+ });
198
+ it('should extract model parameters (temperature, max_tokens)', async () => {
199
+ const openai = createMockOpenAI();
200
+ const wrapped = observeOpenAI(openai, observability);
201
+ await wrapped.chat.completions.create({
202
+ model: 'gpt-4o',
203
+ messages: [{ role: 'user', content: 'Test' }],
204
+ temperature: 0.5,
205
+ max_tokens: 200,
206
+ top_p: 0.9,
207
+ });
208
+ const queue = observability._getQueueDirect();
209
+ const genEvent = queue.find((e) => e.type === 'generation-create');
210
+ expect(genEvent.body.modelParameters).toMatchObject({
211
+ temperature: 0.5,
212
+ max_tokens: 200,
213
+ top_p: 0.9,
214
+ });
215
+ });
216
+ it('should record OpenAI response ID and finish_reason in metadata', async () => {
217
+ const openai = createMockOpenAI();
218
+ const wrapped = observeOpenAI(openai, observability);
219
+ await wrapped.chat.completions.create({
220
+ model: 'gpt-4o',
221
+ messages: [{ role: 'user', content: 'Test' }],
222
+ });
223
+ const queue = observability._getQueueDirect();
224
+ const genEvent = queue.find((e) => e.type === 'generation-create');
225
+ expect(genEvent.body.metadata).toMatchObject({
226
+ openai_id: 'chatcmpl-abc123',
227
+ finish_reason: 'stop',
228
+ });
229
+ });
230
+ it('should set startTime and endTime on the generation', async () => {
231
+ const openai = createMockOpenAI();
232
+ const wrapped = observeOpenAI(openai, observability);
233
+ await wrapped.chat.completions.create({
234
+ model: 'gpt-4o',
235
+ messages: [{ role: 'user', content: 'Test' }],
236
+ });
237
+ const queue = observability._getQueueDirect();
238
+ const genEvent = queue.find((e) => e.type === 'generation-create');
239
+ expect(genEvent.body.startTime).toBeDefined();
240
+ expect(genEvent.body.endTime).toBeDefined();
241
+ });
242
+ });
243
+ // -------------------------------------------------------------------------
244
+ // Options: traceName, userId, sessionId
245
+ // -------------------------------------------------------------------------
246
+ describe('options', () => {
247
+ it('should use custom traceName', async () => {
248
+ const openai = createMockOpenAI();
249
+ const wrapped = observeOpenAI(openai, observability, {
250
+ traceName: 'my-custom-trace',
251
+ });
252
+ await wrapped.chat.completions.create({
253
+ model: 'gpt-4o',
254
+ messages: [{ role: 'user', content: 'Test' }],
255
+ });
256
+ const queue = observability._getQueueDirect();
257
+ const traceEvent = queue.find((e) => e.type === 'trace-create');
258
+ expect(traceEvent.body.name).toBe('my-custom-trace');
259
+ });
260
+ it('should attach userId and sessionId to the trace', async () => {
261
+ const openai = createMockOpenAI();
262
+ const wrapped = observeOpenAI(openai, observability, {
263
+ userId: 'user-42',
264
+ sessionId: 'session-abc',
265
+ });
266
+ await wrapped.chat.completions.create({
267
+ model: 'gpt-4o',
268
+ messages: [{ role: 'user', content: 'Test' }],
269
+ });
270
+ const queue = observability._getQueueDirect();
271
+ const traceEvent = queue.find((e) => e.type === 'trace-create');
272
+ expect(traceEvent.body.userId).toBe('user-42');
273
+ expect(traceEvent.body.sessionId).toBe('session-abc');
274
+ });
275
+ it('should merge generationMetadata into generation metadata', async () => {
276
+ const openai = createMockOpenAI();
277
+ const wrapped = observeOpenAI(openai, observability, {
278
+ generationMetadata: { env: 'test', feature: 'chat' },
279
+ });
280
+ await wrapped.chat.completions.create({
281
+ model: 'gpt-4o',
282
+ messages: [{ role: 'user', content: 'Test' }],
283
+ });
284
+ const queue = observability._getQueueDirect();
285
+ const genEvent = queue.find((e) => e.type === 'generation-create');
286
+ const metadata = genEvent.body.metadata;
287
+ expect(metadata.env).toBe('test');
288
+ expect(metadata.feature).toBe('chat');
289
+ });
290
+ });
291
+ // -------------------------------------------------------------------------
292
+ // Error handling
293
+ // -------------------------------------------------------------------------
294
+ describe('error handling', () => {
295
+ it('should create an ERROR-level generation when OpenAI throws', async () => {
296
+ const apiError = new Error('Rate limit exceeded');
297
+ const openai = createMockOpenAI({ chatError: apiError });
298
+ const wrapped = observeOpenAI(openai, observability);
299
+ await expect(wrapped.chat.completions.create({
300
+ model: 'gpt-4o',
301
+ messages: [{ role: 'user', content: 'Test' }],
302
+ })).rejects.toThrow('Rate limit exceeded');
303
+ const queue = observability._getQueueDirect();
304
+ const genEvent = queue.find((e) => e.type === 'generation-create');
305
+ expect(genEvent.body.level).toBe(ObservationLevel.ERROR);
306
+ expect(genEvent.body.statusMessage).toBe('Rate limit exceeded');
307
+ expect(genEvent.body.model).toBe('gpt-4o');
308
+ });
309
+ it('should still re-throw the original error', async () => {
310
+ const apiError = new Error('API key invalid');
311
+ const openai = createMockOpenAI({ chatError: apiError });
312
+ const wrapped = observeOpenAI(openai, observability);
313
+ await expect(wrapped.chat.completions.create({
314
+ model: 'gpt-4o',
315
+ messages: [{ role: 'user', content: 'Test' }],
316
+ })).rejects.toThrow('API key invalid');
317
+ });
318
+ it('should record the error generation with startTime and endTime', async () => {
319
+ const apiError = new Error('Timeout');
320
+ const openai = createMockOpenAI({ chatError: apiError });
321
+ const wrapped = observeOpenAI(openai, observability);
322
+ await expect(wrapped.chat.completions.create({
323
+ model: 'gpt-4o',
324
+ messages: [{ role: 'user', content: 'Test' }],
325
+ })).rejects.toThrow();
326
+ const queue = observability._getQueueDirect();
327
+ const genEvent = queue.find((e) => e.type === 'generation-create');
328
+ expect(genEvent.body.startTime).toBeDefined();
329
+ expect(genEvent.body.endTime).toBeDefined();
330
+ });
331
+ it('should handle non-Error thrown values', async () => {
332
+ const openai = createMockOpenAI();
333
+ // Override to throw a string
334
+ openai.chat.completions.create = vi.fn().mockRejectedValue('string error');
335
+ const wrapped = observeOpenAI(openai, observability);
336
+ await expect(wrapped.chat.completions.create({
337
+ model: 'gpt-4o',
338
+ messages: [{ role: 'user', content: 'Test' }],
339
+ })).rejects.toBe('string error');
340
+ const queue = observability._getQueueDirect();
341
+ const genEvent = queue.find((e) => e.type === 'generation-create');
342
+ expect(genEvent.body.level).toBe(ObservationLevel.ERROR);
343
+ expect(genEvent.body.statusMessage).toBe('string error');
344
+ });
345
+ });
346
+ // -------------------------------------------------------------------------
347
+ // completions.create (legacy)
348
+ // -------------------------------------------------------------------------
349
+ describe('completions.create (legacy)', () => {
350
+ it('should intercept legacy completions.create calls', async () => {
351
+ const openai = createMockOpenAI();
352
+ const wrapped = observeOpenAI(openai, observability);
353
+ const result = await wrapped.completions.create({
354
+ model: 'gpt-3.5-turbo-instruct',
355
+ prompt: 'Say hello',
356
+ });
357
+ expect(result).toMatchObject({ id: 'cmpl-xyz789' });
358
+ const queue = observability._getQueueDirect();
359
+ const genEvent = queue.find((e) => e.type === 'generation-create');
360
+ expect(genEvent.body.name).toBe('completions.create');
361
+ expect(genEvent.body.model).toBe('gpt-3.5-turbo-instruct');
362
+ expect(genEvent.body.usage).toMatchObject({
363
+ input: 5,
364
+ output: 6,
365
+ total: 11,
366
+ });
367
+ });
368
+ });
369
+ });
370
+ //# sourceMappingURL=openai.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai.test.js","sourceRoot":"","sources":["../../src/__tests__/openai.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,74 @@
1
+ import { ObservabilityCoreClient, type FetchOptions, type FetchResponse } from '@illuma-ai/observability-core';
2
+ /**
3
+ * Options for the Node.js Observability client.
4
+ * All fields are optional — values are read from environment variables when omitted.
5
+ *
6
+ * Env var resolution order (first match wins):
7
+ * - `ILLUMA_PUBLIC_KEY` / `LANGFUSE_PUBLIC_KEY`
8
+ * - `ILLUMA_SECRET_KEY` / `LANGFUSE_SECRET_KEY`
9
+ * - `ILLUMA_BASE_URL` / `LANGFUSE_BASE_URL`
10
+ */
11
+ export interface ObservabilityOptions {
12
+ /** Public API key. Falls back to ILLUMA_PUBLIC_KEY or LANGFUSE_PUBLIC_KEY env var. */
13
+ publicKey?: string;
14
+ /** Secret API key. Falls back to ILLUMA_SECRET_KEY or LANGFUSE_SECRET_KEY env var. */
15
+ secretKey?: string;
16
+ /** Base URL of the Illuma Observe instance. Falls back to ILLUMA_BASE_URL or LANGFUSE_BASE_URL env var. */
17
+ baseUrl?: string;
18
+ /** Number of events to batch before auto-flushing (default: 15) */
19
+ flushAt?: number;
20
+ /** Interval in ms between auto-flushes (default: 5000) */
21
+ flushInterval?: number;
22
+ /** Max retries for failed ingestion requests (default: 3) */
23
+ maxRetries?: number;
24
+ }
25
+ /**
26
+ * Node.js SDK client for Illuma Observability.
27
+ *
28
+ * Extends the core client with:
29
+ * - **Environment variable auto-detection** for credentials and base URL
30
+ * (compatible with both `ILLUMA_*` and `LANGFUSE_*` env vars for drop-in migration)
31
+ * - **Native Node.js `fetch`** (Node 18+)
32
+ * - **Process exit handler** that auto-flushes pending events before shutdown
33
+ *
34
+ * @example
35
+ * ```ts
36
+ * // Reads ILLUMA_PUBLIC_KEY, ILLUMA_SECRET_KEY, ILLUMA_BASE_URL from env
37
+ * const observability = new Observability();
38
+ *
39
+ * const trace = observability.trace({ name: 'my-chain' });
40
+ * trace.generation({ model: 'gpt-4o', input: 'Hello', output: 'Hi!' });
41
+ *
42
+ * await observability.shutdown();
43
+ * ```
44
+ *
45
+ * @example
46
+ * ```ts
47
+ * // Explicit configuration (overrides env vars)
48
+ * const observability = new Observability({
49
+ * publicKey: 'pk-...',
50
+ * secretKey: 'sk-...',
51
+ * baseUrl: 'https://observe.illuma.ai',
52
+ * });
53
+ * ```
54
+ */
55
+ export declare class Observability extends ObservabilityCoreClient {
56
+ private exitHandlerRegistered;
57
+ constructor(options?: ObservabilityOptions);
58
+ /**
59
+ * Send an HTTP request using native Node.js fetch.
60
+ * Implements the abstract method from ObservabilityCoreClient.
61
+ * Retry logic is handled by the core client.
62
+ *
63
+ * @param url - The full endpoint URL
64
+ * @param options - Fetch options (method, headers, body, signal)
65
+ * @returns Simplified response object
66
+ */
67
+ protected fetchWithRetry(url: string, options: FetchOptions): Promise<FetchResponse>;
68
+ /**
69
+ * Register a handler that flushes pending events when the Node.js process exits.
70
+ * Uses `beforeExit` so the event loop can wait for the async flush to complete.
71
+ */
72
+ private registerExitHandler;
73
+ }
74
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,uBAAuB,EAEvB,KAAK,YAAY,EACjB,KAAK,aAAa,EACnB,MAAM,+BAA+B,CAAC;AAKvC;;;;;;;;GAQG;AACH,MAAM,WAAW,oBAAoB;IACnC,sFAAsF;IACtF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,sFAAsF;IACtF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,2GAA2G;IAC3G,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,mEAAmE;IACnE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,0DAA0D;IAC1D,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,6DAA6D;IAC7D,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,qBAAa,aAAc,SAAQ,uBAAuB;IACxD,OAAO,CAAC,qBAAqB,CAAS;gBAE1B,OAAO,GAAE,oBAAyB;IAkD9C;;;;;;;;OAQG;cACa,cAAc,CAC5B,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,YAAY,GACpB,OAAO,CAAC,aAAa,CAAC;IAiBzB;;;OAGG;IACH,OAAO,CAAC,mBAAmB;CAW5B"}
package/dist/client.js ADDED
@@ -0,0 +1,108 @@
1
+ import { ObservabilityCoreClient, } from '@illuma-ai/observability-core';
2
+ const SDK_NAME = '@illuma-ai/observability-node';
3
+ const SDK_VERSION = '0.1.0';
4
+ /**
5
+ * Node.js SDK client for Illuma Observability.
6
+ *
7
+ * Extends the core client with:
8
+ * - **Environment variable auto-detection** for credentials and base URL
9
+ * (compatible with both `ILLUMA_*` and `LANGFUSE_*` env vars for drop-in migration)
10
+ * - **Native Node.js `fetch`** (Node 18+)
11
+ * - **Process exit handler** that auto-flushes pending events before shutdown
12
+ *
13
+ * @example
14
+ * ```ts
15
+ * // Reads ILLUMA_PUBLIC_KEY, ILLUMA_SECRET_KEY, ILLUMA_BASE_URL from env
16
+ * const observability = new Observability();
17
+ *
18
+ * const trace = observability.trace({ name: 'my-chain' });
19
+ * trace.generation({ model: 'gpt-4o', input: 'Hello', output: 'Hi!' });
20
+ *
21
+ * await observability.shutdown();
22
+ * ```
23
+ *
24
+ * @example
25
+ * ```ts
26
+ * // Explicit configuration (overrides env vars)
27
+ * const observability = new Observability({
28
+ * publicKey: 'pk-...',
29
+ * secretKey: 'sk-...',
30
+ * baseUrl: 'https://observe.illuma.ai',
31
+ * });
32
+ * ```
33
+ */
34
+ export class Observability extends ObservabilityCoreClient {
35
+ exitHandlerRegistered = false;
36
+ constructor(options = {}) {
37
+ const publicKey = options.publicKey ??
38
+ process.env.ILLUMA_PUBLIC_KEY ??
39
+ process.env.LANGFUSE_PUBLIC_KEY;
40
+ const secretKey = options.secretKey ??
41
+ process.env.ILLUMA_SECRET_KEY ??
42
+ process.env.LANGFUSE_SECRET_KEY;
43
+ const baseUrl = options.baseUrl ??
44
+ process.env.ILLUMA_BASE_URL ??
45
+ process.env.LANGFUSE_BASE_URL;
46
+ if (!publicKey) {
47
+ throw new Error('[observability-node] publicKey is required. ' +
48
+ 'Pass it in the constructor or set ILLUMA_PUBLIC_KEY / LANGFUSE_PUBLIC_KEY env var.');
49
+ }
50
+ if (!secretKey) {
51
+ throw new Error('[observability-node] secretKey is required. ' +
52
+ 'Pass it in the constructor or set ILLUMA_SECRET_KEY / LANGFUSE_SECRET_KEY env var.');
53
+ }
54
+ if (!baseUrl) {
55
+ throw new Error('[observability-node] baseUrl is required. ' +
56
+ 'Pass it in the constructor or set ILLUMA_BASE_URL / LANGFUSE_BASE_URL env var.');
57
+ }
58
+ const coreConfig = {
59
+ publicKey,
60
+ secretKey,
61
+ baseUrl,
62
+ flushAt: options.flushAt,
63
+ flushInterval: options.flushInterval,
64
+ maxRetries: options.maxRetries,
65
+ };
66
+ super(coreConfig);
67
+ // Register process exit handler to auto-flush pending events
68
+ this.registerExitHandler();
69
+ }
70
+ /**
71
+ * Send an HTTP request using native Node.js fetch.
72
+ * Implements the abstract method from ObservabilityCoreClient.
73
+ * Retry logic is handled by the core client.
74
+ *
75
+ * @param url - The full endpoint URL
76
+ * @param options - Fetch options (method, headers, body, signal)
77
+ * @returns Simplified response object
78
+ */
79
+ async fetchWithRetry(url, options) {
80
+ const response = await fetch(url, {
81
+ method: options.method,
82
+ headers: options.headers,
83
+ body: options.body,
84
+ signal: options.signal,
85
+ });
86
+ return {
87
+ status: response.status,
88
+ statusText: response.statusText,
89
+ ok: response.ok,
90
+ json: () => response.json(),
91
+ text: () => response.text(),
92
+ };
93
+ }
94
+ /**
95
+ * Register a handler that flushes pending events when the Node.js process exits.
96
+ * Uses `beforeExit` so the event loop can wait for the async flush to complete.
97
+ */
98
+ registerExitHandler() {
99
+ if (this.exitHandlerRegistered) {
100
+ return;
101
+ }
102
+ this.exitHandlerRegistered = true;
103
+ process.on('beforeExit', () => {
104
+ void this.flush();
105
+ });
106
+ }
107
+ }
108
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,uBAAuB,GAIxB,MAAM,+BAA+B,CAAC;AAEvC,MAAM,QAAQ,GAAG,+BAA+B,CAAC;AACjD,MAAM,WAAW,GAAG,OAAO,CAAC;AA0B5B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,MAAM,OAAO,aAAc,SAAQ,uBAAuB;IAChD,qBAAqB,GAAG,KAAK,CAAC;IAEtC,YAAY,UAAgC,EAAE;QAC5C,MAAM,SAAS,GACb,OAAO,CAAC,SAAS;YACjB,OAAO,CAAC,GAAG,CAAC,iBAAiB;YAC7B,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC;QAElC,MAAM,SAAS,GACb,OAAO,CAAC,SAAS;YACjB,OAAO,CAAC,GAAG,CAAC,iBAAiB;YAC7B,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC;QAElC,MAAM,OAAO,GACX,OAAO,CAAC,OAAO;YACf,OAAO,CAAC,GAAG,CAAC,eAAe;YAC3B,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC;QAEhC,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,MAAM,IAAI,KAAK,CACb,8CAA8C;gBAC5C,oFAAoF,CACvF,CAAC;QACJ,CAAC;QACD,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,MAAM,IAAI,KAAK,CACb,8CAA8C;gBAC5C,oFAAoF,CACvF,CAAC;QACJ,CAAC;QACD,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CACb,4CAA4C;gBAC1C,gFAAgF,CACnF,CAAC;QACJ,CAAC;QAED,MAAM,UAAU,GAA8B;YAC5C,SAAS;YACT,SAAS;YACT,OAAO;YACP,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,aAAa,EAAE,OAAO,CAAC,aAAa;YACpC,UAAU,EAAE,OAAO,CAAC,UAAU;SAC/B,CAAC;QAEF,KAAK,CAAC,UAAU,CAAC,CAAC;QAElB,6DAA6D;QAC7D,IAAI,CAAC,mBAAmB,EAAE,CAAC;IAC7B,CAAC;IAED;;;;;;;;OAQG;IACO,KAAK,CAAC,cAAc,CAC5B,GAAW,EACX,OAAqB;QAErB,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;YAChC,MAAM,EAAE,OAAO,CAAC,MAAM;YACtB,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,MAAM,EAAE,OAAO,CAAC,MAAM;SACvB,CAAC,CAAC;QAEH,OAAO;YACL,MAAM,EAAE,QAAQ,CAAC,MAAM;YACvB,UAAU,EAAE,QAAQ,CAAC,UAAU;YAC/B,EAAE,EAAE,QAAQ,CAAC,EAAE;YACf,IAAI,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,IAAI,EAAE;YAC3B,IAAI,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,IAAI,EAAE;SAC5B,CAAC;IACJ,CAAC;IAED;;;OAGG;IACK,mBAAmB;QACzB,IAAI,IAAI,CAAC,qBAAqB,EAAE,CAAC;YAC/B,OAAO;QACT,CAAC;QAED,IAAI,CAAC,qBAAqB,GAAG,IAAI,CAAC;QAElC,OAAO,CAAC,EAAE,CAAC,YAAY,EAAE,GAAG,EAAE;YAC5B,KAAK,IAAI,CAAC,KAAK,EAAE,CAAC;QACpB,CAAC,CAAC,CAAC;IACL,CAAC;CACF"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * @illuma-ai/observability-node
3
+ *
4
+ * Node.js SDK for Illuma Observability — LLM tracing and analytics.
5
+ * Drop-in replacement for the `langfuse` npm package.
6
+ *
7
+ * @example
8
+ * ```ts
9
+ * import { Observability, observeOpenAI } from '@illuma-ai/observability-node';
10
+ *
11
+ * // Reads ILLUMA_PUBLIC_KEY, ILLUMA_SECRET_KEY, ILLUMA_BASE_URL from env
12
+ * // (also supports LANGFUSE_* env vars for easy migration)
13
+ * const observability = new Observability();
14
+ *
15
+ * const trace = observability.trace({ name: 'my-workflow' });
16
+ * trace.generation({ model: 'gpt-4o', input: 'Hello', output: 'Hi!' });
17
+ *
18
+ * await observability.shutdown();
19
+ * ```
20
+ *
21
+ * @packageDocumentation
22
+ */
23
+ export { Observability, type ObservabilityOptions } from './client.js';
24
+ export { observeOpenAI, type ObserveOpenAIOptions } from './openai.js';
25
+ export type { ObservabilityClientConfig, TraceParams, GenerationParams, SpanParams, EventParams, ScoreParams, IngestionEvent, IngestionEventType, IngestionBatchRequest, } from '@illuma-ai/observability-core';
26
+ export { ObservabilityCoreClient, TraceClient } from '@illuma-ai/observability-core';
27
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EAAE,aAAa,EAAE,KAAK,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACvE,OAAO,EAAE,aAAa,EAAE,KAAK,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAGvE,YAAY,EACV,yBAAyB,EACzB,WAAW,EACX,gBAAgB,EAChB,UAAU,EACV,WAAW,EACX,WAAW,EACX,cAAc,EACd,kBAAkB,EAClB,qBAAqB,GACtB,MAAM,+BAA+B,CAAC;AAEvC,OAAO,EAAE,uBAAuB,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,26 @@
1
+ /**
2
+ * @illuma-ai/observability-node
3
+ *
4
+ * Node.js SDK for Illuma Observability — LLM tracing and analytics.
5
+ * Drop-in replacement for the `langfuse` npm package.
6
+ *
7
+ * @example
8
+ * ```ts
9
+ * import { Observability, observeOpenAI } from '@illuma-ai/observability-node';
10
+ *
11
+ * // Reads ILLUMA_PUBLIC_KEY, ILLUMA_SECRET_KEY, ILLUMA_BASE_URL from env
12
+ * // (also supports LANGFUSE_* env vars for easy migration)
13
+ * const observability = new Observability();
14
+ *
15
+ * const trace = observability.trace({ name: 'my-workflow' });
16
+ * trace.generation({ model: 'gpt-4o', input: 'Hello', output: 'Hi!' });
17
+ *
18
+ * await observability.shutdown();
19
+ * ```
20
+ *
21
+ * @packageDocumentation
22
+ */
23
+ export { Observability } from './client.js';
24
+ export { observeOpenAI } from './openai.js';
25
+ export { ObservabilityCoreClient, TraceClient } from '@illuma-ai/observability-core';
26
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EAAE,aAAa,EAA6B,MAAM,aAAa,CAAC;AACvE,OAAO,EAAE,aAAa,EAA6B,MAAM,aAAa,CAAC;AAevE,OAAO,EAAE,uBAAuB,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAC"}
@@ -0,0 +1,63 @@
1
+ import type { Observability } from './client.js';
2
+ /**
3
+ * Represents the minimal shape of an OpenAI client we need to instrument.
4
+ * We avoid importing the `openai` package directly to keep it as an optional peer dependency.
5
+ */
6
+ interface OpenAILike {
7
+ chat: {
8
+ completions: {
9
+ create: (...args: unknown[]) => Promise<unknown>;
10
+ };
11
+ };
12
+ completions: {
13
+ create: (...args: unknown[]) => Promise<unknown>;
14
+ };
15
+ }
16
+ /**
17
+ * Options for configuring the OpenAI observation wrapper.
18
+ */
19
+ export interface ObserveOpenAIOptions {
20
+ /** Parent trace name. Defaults to "openai-call". */
21
+ traceName?: string;
22
+ /** Additional metadata to attach to each generation event */
23
+ generationMetadata?: Record<string, unknown>;
24
+ /** User ID to associate with traces */
25
+ userId?: string;
26
+ /** Session ID to group related traces */
27
+ sessionId?: string;
28
+ }
29
+ /**
30
+ * Wraps an OpenAI client instance with automatic observability instrumentation.
31
+ *
32
+ * Uses ES Proxy to intercept calls to `chat.completions.create()` and
33
+ * `completions.create()`, automatically creating trace and generation events
34
+ * with model, usage, and timing information.
35
+ *
36
+ * The returned client has the same interface as the original — existing code
37
+ * works unchanged.
38
+ *
39
+ * @param openai - An OpenAI client instance (from the `openai` npm package)
40
+ * @param observability - An initialized Observability client
41
+ * @param options - Optional configuration for trace naming and metadata
42
+ * @returns A proxied OpenAI client with the same interface
43
+ *
44
+ * @example
45
+ * ```ts
46
+ * import OpenAI from 'openai';
47
+ * import { Observability, observeOpenAI } from '@illuma-ai/observability-node';
48
+ *
49
+ * const client = new OpenAI();
50
+ * const observability = new Observability(); // reads env vars
51
+ *
52
+ * const traced = observeOpenAI(client, observability);
53
+ *
54
+ * // Works exactly like the original client, but now all calls are traced
55
+ * const response = await traced.chat.completions.create({
56
+ * model: 'gpt-4o',
57
+ * messages: [{ role: 'user', content: 'Hello!' }],
58
+ * });
59
+ * ```
60
+ */
61
+ export declare function observeOpenAI<T extends OpenAILike>(openai: T, observability: Observability, options?: ObserveOpenAIOptions): T;
62
+ export {};
63
+ //# sourceMappingURL=openai.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai.d.ts","sourceRoot":"","sources":["../src/openai.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEjD;;;GAGG;AACH,UAAU,UAAU;IAClB,IAAI,EAAE;QACJ,WAAW,EAAE;YACX,MAAM,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;SAClD,CAAC;KACH,CAAC;IACF,WAAW,EAAE;QACX,MAAM,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;KAClD,CAAC;CACH;AAwCD;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,oDAAoD;IACpD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,6DAA6D;IAC7D,kBAAkB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC7C,uCAAuC;IACvC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,yCAAyC;IACzC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,wBAAgB,aAAa,CAAC,CAAC,SAAS,UAAU,EAChD,MAAM,EAAE,CAAC,EACT,aAAa,EAAE,aAAa,EAC5B,OAAO,GAAE,oBAAyB,GACjC,CAAC,CAwLH"}
package/dist/openai.js ADDED
@@ -0,0 +1,190 @@
1
+ import { ObservationLevel } from '@illuma-ai/observability-core';
2
+ /**
3
+ * Wraps an OpenAI client instance with automatic observability instrumentation.
4
+ *
5
+ * Uses ES Proxy to intercept calls to `chat.completions.create()` and
6
+ * `completions.create()`, automatically creating trace and generation events
7
+ * with model, usage, and timing information.
8
+ *
9
+ * The returned client has the same interface as the original — existing code
10
+ * works unchanged.
11
+ *
12
+ * @param openai - An OpenAI client instance (from the `openai` npm package)
13
+ * @param observability - An initialized Observability client
14
+ * @param options - Optional configuration for trace naming and metadata
15
+ * @returns A proxied OpenAI client with the same interface
16
+ *
17
+ * @example
18
+ * ```ts
19
+ * import OpenAI from 'openai';
20
+ * import { Observability, observeOpenAI } from '@illuma-ai/observability-node';
21
+ *
22
+ * const client = new OpenAI();
23
+ * const observability = new Observability(); // reads env vars
24
+ *
25
+ * const traced = observeOpenAI(client, observability);
26
+ *
27
+ * // Works exactly like the original client, but now all calls are traced
28
+ * const response = await traced.chat.completions.create({
29
+ * model: 'gpt-4o',
30
+ * messages: [{ role: 'user', content: 'Hello!' }],
31
+ * });
32
+ * ```
33
+ */
34
+ export function observeOpenAI(openai, observability, options = {}) {
35
+ const { traceName = 'openai-call', generationMetadata, userId, sessionId, } = options;
36
+ /**
37
+ * Wrap a create function to auto-instrument it with tracing.
38
+ * Handles both chat.completions.create and completions.create.
39
+ */
40
+ function wrapCreate(originalFn, kind) {
41
+ return async function wrappedCreate(...args) {
42
+ const params = (args[0] ?? {});
43
+ const startTime = new Date().toISOString();
44
+ // Create a trace for this call
45
+ const trace = observability.trace({
46
+ name: traceName,
47
+ input: params,
48
+ userId,
49
+ sessionId,
50
+ });
51
+ try {
52
+ // Call the original OpenAI method
53
+ const result = await originalFn.apply(openai, args);
54
+ const endTime = new Date().toISOString();
55
+ if (kind === 'chat') {
56
+ const response = result;
57
+ trace.generation({
58
+ name: `chat.completions.create`,
59
+ model: params.model ?? response.model,
60
+ input: params.messages,
61
+ output: response.choices?.[0]?.message,
62
+ startTime,
63
+ endTime,
64
+ modelParameters: extractModelParams(params),
65
+ usage: response.usage
66
+ ? {
67
+ input: response.usage.prompt_tokens,
68
+ output: response.usage.completion_tokens,
69
+ total: response.usage.total_tokens,
70
+ }
71
+ : undefined,
72
+ metadata: {
73
+ ...generationMetadata,
74
+ openai_id: response.id,
75
+ finish_reason: response.choices?.[0]?.finish_reason,
76
+ },
77
+ });
78
+ }
79
+ else {
80
+ const response = result;
81
+ trace.generation({
82
+ name: `completions.create`,
83
+ model: params.model ?? response.model,
84
+ input: params.prompt,
85
+ output: response.choices?.[0]?.text,
86
+ startTime,
87
+ endTime,
88
+ modelParameters: extractModelParams(params),
89
+ usage: response.usage
90
+ ? {
91
+ input: response.usage.prompt_tokens,
92
+ output: response.usage.completion_tokens,
93
+ total: response.usage.total_tokens,
94
+ }
95
+ : undefined,
96
+ metadata: {
97
+ ...generationMetadata,
98
+ openai_id: response.id,
99
+ finish_reason: response.choices?.[0]?.finish_reason,
100
+ },
101
+ });
102
+ }
103
+ return result;
104
+ }
105
+ catch (err) {
106
+ const endTime = new Date().toISOString();
107
+ // Record the failed generation
108
+ trace.generation({
109
+ name: kind === 'chat' ? 'chat.completions.create' : 'completions.create',
110
+ model: params.model,
111
+ input: kind === 'chat' ? params.messages : params.prompt,
112
+ startTime,
113
+ endTime,
114
+ modelParameters: extractModelParams(params),
115
+ level: ObservationLevel.ERROR,
116
+ statusMessage: err instanceof Error ? err.message : String(err),
117
+ metadata: generationMetadata,
118
+ });
119
+ throw err;
120
+ }
121
+ };
122
+ }
123
+ /**
124
+ * Extract common model parameters from OpenAI request params.
125
+ */
126
+ function extractModelParams(params) {
127
+ const modelParams = {};
128
+ const keys = [
129
+ 'temperature',
130
+ 'top_p',
131
+ 'max_tokens',
132
+ 'max_completion_tokens',
133
+ 'frequency_penalty',
134
+ 'presence_penalty',
135
+ 'stop',
136
+ 'seed',
137
+ 'response_format',
138
+ 'tools',
139
+ 'tool_choice',
140
+ ];
141
+ for (const key of keys) {
142
+ if (params[key] !== undefined) {
143
+ modelParams[key] = params[key];
144
+ }
145
+ }
146
+ return modelParams;
147
+ }
148
+ // Create proxied chat.completions object with instrumented create method
149
+ const wrappedChatCreate = wrapCreate(openai.chat.completions.create.bind(openai.chat.completions), 'chat');
150
+ const proxiedChatCompletions = new Proxy(openai.chat.completions, {
151
+ get(target, prop, receiver) {
152
+ if (prop === 'create') {
153
+ return wrappedChatCreate;
154
+ }
155
+ return Reflect.get(target, prop, receiver);
156
+ },
157
+ });
158
+ // Create proxied chat object
159
+ const proxiedChat = new Proxy(openai.chat, {
160
+ get(target, prop, receiver) {
161
+ if (prop === 'completions') {
162
+ return proxiedChatCompletions;
163
+ }
164
+ return Reflect.get(target, prop, receiver);
165
+ },
166
+ });
167
+ // Create proxied completions object with instrumented create method
168
+ const wrappedCompletionsCreate = wrapCreate(openai.completions.create.bind(openai.completions), 'completion');
169
+ const proxiedCompletions = new Proxy(openai.completions, {
170
+ get(target, prop, receiver) {
171
+ if (prop === 'create') {
172
+ return wrappedCompletionsCreate;
173
+ }
174
+ return Reflect.get(target, prop, receiver);
175
+ },
176
+ });
177
+ // Create the top-level proxy
178
+ return new Proxy(openai, {
179
+ get(target, prop, receiver) {
180
+ if (prop === 'chat') {
181
+ return proxiedChat;
182
+ }
183
+ if (prop === 'completions') {
184
+ return proxiedCompletions;
185
+ }
186
+ return Reflect.get(target, prop, receiver);
187
+ },
188
+ });
189
+ }
190
+ //# sourceMappingURL=openai.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai.js","sourceRoot":"","sources":["../src/openai.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,39 @@
1
+ {
2
+ "name": "@illuma-ai/observability-node",
3
+ "version": "0.1.0",
4
+ "description": "Node.js SDK for Illuma Observability - LLM tracing and analytics",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "import": "./dist/index.js",
11
+ "types": "./dist/index.d.ts"
12
+ }
13
+ },
14
+ "files": ["dist"],
15
+ "scripts": {
16
+ "build": "tsc",
17
+ "test": "vitest run",
18
+ "test:watch": "vitest",
19
+ "prepublishOnly": "npm run build"
20
+ },
21
+ "dependencies": {
22
+ "@illuma-ai/observability-core": "^0.1.0"
23
+ },
24
+ "devDependencies": {
25
+ "typescript": "^5.4.5",
26
+ "@types/node": "^20.14.2",
27
+ "vitest": "^1.6.0"
28
+ },
29
+ "publishConfig": {
30
+ "access": "public"
31
+ },
32
+ "repository": {
33
+ "type": "git",
34
+ "url": "https://github.com/illuma-ai/observability.git",
35
+ "directory": "packages/observability-node"
36
+ },
37
+ "license": "MIT",
38
+ "keywords": ["llm", "observability", "tracing", "illuma", "node"]
39
+ }