observa-sdk 0.0.8 → 0.0.10
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/README.md +300 -11
- package/dist/index.cjs +658 -7
- package/dist/index.d.cts +181 -3
- package/dist/index.d.ts +181 -3
- package/dist/index.js +663 -7
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -41,18 +41,58 @@ const observa = init({
|
|
|
41
41
|
|
|
42
42
|
## Quick Start
|
|
43
43
|
|
|
44
|
-
###
|
|
44
|
+
### Auto-Capture with OpenAI (Recommended)
|
|
45
45
|
|
|
46
|
-
|
|
46
|
+
The easiest way to track LLM calls is using the `observeOpenAI()` wrapper - it automatically captures 90%+ of your LLM interactions:
|
|
47
47
|
|
|
48
48
|
```typescript
|
|
49
49
|
import { init } from "observa-sdk";
|
|
50
|
+
import OpenAI from "openai";
|
|
50
51
|
|
|
51
|
-
// Initialize
|
|
52
|
+
// Initialize Observa
|
|
52
53
|
const observa = init({
|
|
53
54
|
apiKey: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", // Your API key from signup
|
|
54
55
|
});
|
|
55
56
|
|
|
57
|
+
// Initialize OpenAI client
|
|
58
|
+
const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });
|
|
59
|
+
|
|
60
|
+
// Wrap with Observa (automatic tracing)
|
|
61
|
+
const wrappedOpenAI = observa.observeOpenAI(openai, {
|
|
62
|
+
name: 'my-app',
|
|
63
|
+
userId: 'user_123',
|
|
64
|
+
redact: (data) => {
|
|
65
|
+
// Optional: Scrub sensitive data before sending to Observa
|
|
66
|
+
if (data?.messages) {
|
|
67
|
+
return { ...data, messages: '[REDACTED]' };
|
|
68
|
+
}
|
|
69
|
+
return data;
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
// Use wrapped client - automatically tracked!
|
|
74
|
+
const response = await wrappedOpenAI.chat.completions.create({
|
|
75
|
+
model: 'gpt-4',
|
|
76
|
+
messages: [{ role: 'user', content: 'Hello!' }],
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
// Streaming also works automatically
|
|
80
|
+
const stream = await wrappedOpenAI.chat.completions.create({
|
|
81
|
+
model: 'gpt-4',
|
|
82
|
+
messages: [{ role: 'user', content: 'Hello!' }],
|
|
83
|
+
stream: true,
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
for await (const chunk of stream) {
|
|
87
|
+
process.stdout.write(chunk.choices[0]?.delta?.content || '');
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### Legacy Manual Tracking
|
|
92
|
+
|
|
93
|
+
For more control, you can still use the manual `track()` method:
|
|
94
|
+
|
|
95
|
+
```typescript
|
|
56
96
|
// Track AI interactions with simple wrapping
|
|
57
97
|
const response = await observa.track({ query: "What is the weather?" }, () =>
|
|
58
98
|
fetch("https://api.openai.com/v1/chat/completions", {
|
|
@@ -67,18 +107,26 @@ const response = await observa.track({ query: "What is the weather?" }, () =>
|
|
|
67
107
|
);
|
|
68
108
|
```
|
|
69
109
|
|
|
70
|
-
###
|
|
110
|
+
### Manual Tracking (Advanced)
|
|
111
|
+
|
|
112
|
+
For more control over what gets tracked, use the manual tracking methods:
|
|
71
113
|
|
|
72
114
|
```typescript
|
|
73
|
-
//
|
|
74
|
-
const
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
115
|
+
// Use trackLLMCall for fine-grained control
|
|
116
|
+
const spanId = observa.trackLLMCall({
|
|
117
|
+
model: 'gpt-4',
|
|
118
|
+
input: 'Hello!',
|
|
119
|
+
output: 'Hi there!',
|
|
120
|
+
inputTokens: 10,
|
|
121
|
+
outputTokens: 5,
|
|
122
|
+
latencyMs: 1200,
|
|
123
|
+
operationName: 'chat',
|
|
124
|
+
providerName: 'openai',
|
|
79
125
|
});
|
|
80
126
|
```
|
|
81
127
|
|
|
128
|
+
See the [API Reference](#api-reference) section for all available methods.
|
|
129
|
+
|
|
82
130
|
## Multi-Tenant Architecture
|
|
83
131
|
|
|
84
132
|
Observa SDK uses a **multi-tenant shared runtime architecture** for optimal cost, scalability, and operational simplicity.
|
|
@@ -141,6 +189,9 @@ interface ObservaInitConfig {
|
|
|
141
189
|
projectId?: string;
|
|
142
190
|
environment?: "dev" | "prod";
|
|
143
191
|
|
|
192
|
+
// Observa backend URL (optional, defaults to https://api.observa.ai)
|
|
193
|
+
apiUrl?: string;
|
|
194
|
+
|
|
144
195
|
// SDK behavior
|
|
145
196
|
mode?: "development" | "production";
|
|
146
197
|
sampleRate?: number; // 0..1, default: 1.0
|
|
@@ -153,6 +204,7 @@ interface ObservaInitConfig {
|
|
|
153
204
|
- **apiKey**: Your Observa API key (JWT format recommended)
|
|
154
205
|
- **tenantId** / **projectId**: Required only for legacy API keys
|
|
155
206
|
- **environment**: `"dev"` or `"prod"` (defaults to `"dev"`)
|
|
207
|
+
- **apiUrl**: Observa backend URL (optional, defaults to `https://api.observa.ai`)
|
|
156
208
|
- **mode**: SDK mode - `"development"` logs traces to console, `"production"` sends to Observa
|
|
157
209
|
- **sampleRate**: Fraction of traces to record (0.0 to 1.0)
|
|
158
210
|
- **maxResponseChars**: Maximum response size to capture (prevents huge payloads)
|
|
@@ -163,9 +215,246 @@ interface ObservaInitConfig {
|
|
|
163
215
|
|
|
164
216
|
Initialize the Observa SDK instance.
|
|
165
217
|
|
|
218
|
+
**Example:**
|
|
219
|
+
```typescript
|
|
220
|
+
import { init } from "observa-sdk";
|
|
221
|
+
|
|
222
|
+
const observa = init({
|
|
223
|
+
apiKey: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", // Your JWT API key
|
|
224
|
+
apiUrl: "https://api.observa.ai", // Optional, defaults to https://api.observa.ai
|
|
225
|
+
environment: "prod", // Optional, defaults to "dev"
|
|
226
|
+
mode: "production", // Optional, "development" or "production"
|
|
227
|
+
sampleRate: 1.0, // Optional, 0.0 to 1.0, default: 1.0
|
|
228
|
+
maxResponseChars: 50000, // Optional, default: 50000
|
|
229
|
+
});
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
### `observa.observeOpenAI(client, options?)`
|
|
233
|
+
|
|
234
|
+
Wrap an OpenAI client with automatic tracing. This is the **recommended** way to track LLM calls.
|
|
235
|
+
|
|
236
|
+
**Parameters:**
|
|
237
|
+
- `client` (required): OpenAI client instance
|
|
238
|
+
- `options` (optional):
|
|
239
|
+
- `name` (optional): Application/service name
|
|
240
|
+
- `tags` (optional): Array of tags
|
|
241
|
+
- `userId` (optional): User identifier
|
|
242
|
+
- `sessionId` (optional): Session identifier
|
|
243
|
+
- `redact` (optional): Function to sanitize data before sending to Observa
|
|
244
|
+
|
|
245
|
+
**Returns**: Wrapped OpenAI client (use it exactly like the original client)
|
|
246
|
+
|
|
247
|
+
**Example:**
|
|
248
|
+
```typescript
|
|
249
|
+
import OpenAI from 'openai';
|
|
250
|
+
|
|
251
|
+
const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });
|
|
252
|
+
const wrapped = observa.observeOpenAI(openai, {
|
|
253
|
+
name: 'my-app',
|
|
254
|
+
userId: 'user_123',
|
|
255
|
+
redact: (data) => {
|
|
256
|
+
// Sanitize sensitive data
|
|
257
|
+
if (data?.messages) {
|
|
258
|
+
return { ...data, messages: '[REDACTED]' };
|
|
259
|
+
}
|
|
260
|
+
return data;
|
|
261
|
+
}
|
|
262
|
+
});
|
|
263
|
+
|
|
264
|
+
// Use wrapped client - automatically tracked!
|
|
265
|
+
const response = await wrapped.chat.completions.create({
|
|
266
|
+
model: 'gpt-4',
|
|
267
|
+
messages: [{ role: 'user', content: 'Hello!' }],
|
|
268
|
+
});
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
### `observa.observeAnthropic(client, options?)`
|
|
272
|
+
|
|
273
|
+
Wrap an Anthropic client with automatic tracing. Same API as `observeOpenAI()`.
|
|
274
|
+
|
|
275
|
+
**Example:**
|
|
276
|
+
```typescript
|
|
277
|
+
import Anthropic from '@anthropic-ai/sdk';
|
|
278
|
+
|
|
279
|
+
const anthropic = new Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY });
|
|
280
|
+
const wrapped = observa.observeAnthropic(anthropic, {
|
|
281
|
+
name: 'my-app',
|
|
282
|
+
redact: (data) => ({ ...data, messages: '[REDACTED]' })
|
|
283
|
+
});
|
|
284
|
+
|
|
285
|
+
// Use wrapped client - automatically tracked!
|
|
286
|
+
const response = await wrapped.messages.create({
|
|
287
|
+
model: 'claude-3-opus-20240229',
|
|
288
|
+
max_tokens: 1024,
|
|
289
|
+
messages: [{ role: 'user', content: 'Hello!' }],
|
|
290
|
+
});
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
### `observa.startTrace(options)`
|
|
294
|
+
|
|
295
|
+
Start a new trace for manual trace management. Returns the trace ID.
|
|
296
|
+
|
|
297
|
+
**Parameters:**
|
|
298
|
+
- `options.name` (optional): Trace name
|
|
299
|
+
- `options.metadata` (optional): Custom metadata object
|
|
300
|
+
- `options.conversationId` (optional): Conversation identifier
|
|
301
|
+
- `options.sessionId` (optional): Session identifier
|
|
302
|
+
- `options.userId` (optional): User identifier
|
|
303
|
+
|
|
304
|
+
**Returns**: `string` - The trace ID
|
|
305
|
+
|
|
306
|
+
**Example:**
|
|
307
|
+
```typescript
|
|
308
|
+
const traceId = observa.startTrace({
|
|
309
|
+
name: "RAG Query",
|
|
310
|
+
conversationId: "conv-123",
|
|
311
|
+
userId: "user-456",
|
|
312
|
+
metadata: { feature: "chat", version: "2.0" }
|
|
313
|
+
});
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
### `observa.endTrace(options)`
|
|
317
|
+
|
|
318
|
+
End the current trace and send all buffered events. Must be called after `startTrace()`.
|
|
319
|
+
|
|
320
|
+
**Parameters:**
|
|
321
|
+
- `options.outcome` (optional): `"success"` | `"error"` | `"timeout"` (default: `"success"`)
|
|
322
|
+
|
|
323
|
+
**Returns**: `Promise<string>` - The trace ID
|
|
324
|
+
|
|
325
|
+
**Example:**
|
|
326
|
+
```typescript
|
|
327
|
+
await observa.endTrace({ outcome: "success" });
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
### `observa.trackLLMCall(options)` ⭐ NEW - Full OTEL Support
|
|
331
|
+
|
|
332
|
+
Track an LLM call with complete OTEL compliance. **This is the recommended method** for tracking LLM calls.
|
|
333
|
+
|
|
334
|
+
**Parameters:**
|
|
335
|
+
- `model` (required): Model name
|
|
336
|
+
- `input`, `output`: Input/output text
|
|
337
|
+
- `inputTokens`, `outputTokens`, `totalTokens`: Token counts
|
|
338
|
+
- `latencyMs` (required): Latency in milliseconds
|
|
339
|
+
- `operationName`: OTEL operation name ("chat", "text_completion", "generate_content")
|
|
340
|
+
- `providerName`: Provider name ("openai", "anthropic", etc.) - auto-inferred from model if not provided
|
|
341
|
+
- `responseModel`: Actual model used (vs requested)
|
|
342
|
+
- `topK`, `topP`, `frequencyPenalty`, `presencePenalty`, `stopSequences`, `seed`: Sampling parameters
|
|
343
|
+
- `inputCost`, `outputCost`: Structured cost tracking
|
|
344
|
+
- `inputMessages`, `outputMessages`, `systemInstructions`: Structured message objects
|
|
345
|
+
- `serverAddress`, `serverPort`: Server metadata
|
|
346
|
+
- `conversationIdOtel`: OTEL conversation ID
|
|
347
|
+
- And more... (see SDK_SOTA_IMPLEMENTATION.md for complete list)
|
|
348
|
+
|
|
349
|
+
**Example:**
|
|
350
|
+
```typescript
|
|
351
|
+
const spanId = observa.trackLLMCall({
|
|
352
|
+
model: "gpt-4-turbo",
|
|
353
|
+
input: "What is AI?",
|
|
354
|
+
output: "AI is...",
|
|
355
|
+
inputTokens: 10,
|
|
356
|
+
outputTokens: 50,
|
|
357
|
+
latencyMs: 1200,
|
|
358
|
+
operationName: "chat",
|
|
359
|
+
providerName: "openai", // Auto-inferred if not provided
|
|
360
|
+
temperature: 0.7,
|
|
361
|
+
topP: 0.9,
|
|
362
|
+
inputCost: 0.00245,
|
|
363
|
+
outputCost: 0.01024
|
|
364
|
+
});
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
### `observa.trackEmbedding(options)` ⭐ NEW
|
|
368
|
+
|
|
369
|
+
Track an embedding operation with full OTEL support.
|
|
370
|
+
|
|
371
|
+
**Example:**
|
|
372
|
+
```typescript
|
|
373
|
+
const spanId = observa.trackEmbedding({
|
|
374
|
+
model: "text-embedding-ada-002",
|
|
375
|
+
dimensionCount: 1536,
|
|
376
|
+
inputTokens: 10,
|
|
377
|
+
outputTokens: 1536,
|
|
378
|
+
latencyMs: 45,
|
|
379
|
+
cost: 0.0001
|
|
380
|
+
});
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
### `observa.trackVectorDbOperation(options)` ⭐ NEW
|
|
384
|
+
|
|
385
|
+
Track vector database operations (Pinecone, Weaviate, Qdrant, etc.).
|
|
386
|
+
|
|
387
|
+
**Example:**
|
|
388
|
+
```typescript
|
|
389
|
+
const spanId = observa.trackVectorDbOperation({
|
|
390
|
+
operationType: "vector_search",
|
|
391
|
+
indexName: "documents",
|
|
392
|
+
vectorDimensions: 1536,
|
|
393
|
+
resultsCount: 10,
|
|
394
|
+
latencyMs: 30,
|
|
395
|
+
cost: 0.0005,
|
|
396
|
+
providerName: "pinecone"
|
|
397
|
+
});
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
### `observa.trackCacheOperation(options)` ⭐ NEW
|
|
401
|
+
|
|
402
|
+
Track cache hit/miss operations.
|
|
403
|
+
|
|
404
|
+
**Example:**
|
|
405
|
+
```typescript
|
|
406
|
+
const spanId = observa.trackCacheOperation({
|
|
407
|
+
cacheBackend: "redis",
|
|
408
|
+
hitStatus: "hit",
|
|
409
|
+
latencyMs: 2,
|
|
410
|
+
savedCost: 0.01269
|
|
411
|
+
});
|
|
412
|
+
```
|
|
413
|
+
|
|
414
|
+
### `observa.trackAgentCreate(options)` ⭐ NEW
|
|
415
|
+
|
|
416
|
+
Track agent creation.
|
|
417
|
+
|
|
418
|
+
**Example:**
|
|
419
|
+
```typescript
|
|
420
|
+
const spanId = observa.trackAgentCreate({
|
|
421
|
+
agentName: "Customer Support Agent",
|
|
422
|
+
toolsBound: ["web_search", "database_query"],
|
|
423
|
+
modelConfig: { model: "gpt-4-turbo", temperature: 0.7 }
|
|
424
|
+
});
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
### `observa.trackToolCall(options)` - Enhanced
|
|
428
|
+
|
|
429
|
+
Track a tool call with OTEL standardization.
|
|
430
|
+
|
|
431
|
+
**New Parameters:**
|
|
432
|
+
- `toolType`: "function" | "extension" | "datastore"
|
|
433
|
+
- `toolDescription`: Tool description
|
|
434
|
+
- `toolCallId`: Unique tool invocation ID
|
|
435
|
+
- `errorType`, `errorCategory`: Structured error classification
|
|
436
|
+
|
|
437
|
+
### `observa.trackRetrieval(options)` - Enhanced
|
|
438
|
+
|
|
439
|
+
Track retrieval operations with vector metadata.
|
|
440
|
+
|
|
441
|
+
**New Parameters:**
|
|
442
|
+
- `embeddingModel`: Model used for embeddings
|
|
443
|
+
- `embeddingDimensions`: Vector dimensions
|
|
444
|
+
- `vectorMetric`: Similarity metric
|
|
445
|
+
- `rerankScore`, `fusionMethod`, `qualityScore`: Quality metrics
|
|
446
|
+
|
|
447
|
+
### `observa.trackError(options)` - Enhanced
|
|
448
|
+
|
|
449
|
+
Track errors with structured classification.
|
|
450
|
+
|
|
451
|
+
**New Parameters:**
|
|
452
|
+
- `errorCategory`: Error category
|
|
453
|
+
- `errorCode`: Error code
|
|
454
|
+
|
|
166
455
|
### `observa.track(event, action)`
|
|
167
456
|
|
|
168
|
-
Track an AI interaction.
|
|
457
|
+
Track an AI interaction (legacy method, still supported).
|
|
169
458
|
|
|
170
459
|
**Parameters**:
|
|
171
460
|
|