observa-sdk 0.0.8 → 0.0.9

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 CHANGED
@@ -41,18 +41,58 @@ const observa = init({
41
41
 
42
42
  ## Quick Start
43
43
 
44
- ### JWT-based API Key (Recommended)
44
+ ### Auto-Capture with OpenAI (Recommended)
45
45
 
46
- After signing up, you'll receive a JWT-formatted API key that automatically encodes your tenant and project context:
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 with JWT API key from signup (automatically extracts tenant/project context)
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
- ### Legacy API Key Format
110
+ ### Manual Tracking (Advanced)
111
+
112
+ For more control over what gets tracked, use the manual tracking methods:
71
113
 
72
114
  ```typescript
73
- // For backward compatibility, you can still provide tenantId/projectId explicitly
74
- const observa = init({
75
- apiKey: "your-api-key",
76
- tenantId: "acme_corp",
77
- projectId: "prod_app",
78
- environment: "prod", // optional, defaults to "dev"
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