@snap-agent/analytics 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,625 @@
1
+ import { PerformanceTimings, TokenMetrics, RAGMetrics, AnalyticsPlugin, RequestTrackingData, ResponseTrackingData, ErrorTrackingData } from '@snap-agent/core';
2
+ export { ErrorTrackingData, PerformanceTimings, RAGMetrics, RequestTrackingData, ResponseTrackingData, TokenMetrics } from '@snap-agent/core';
3
+
4
+ interface StoredRequest {
5
+ id: string;
6
+ agentId: string;
7
+ threadId?: string;
8
+ userId?: string;
9
+ timestamp: Date;
10
+ messageLength: number;
11
+ model?: string;
12
+ provider?: string;
13
+ }
14
+ interface StoredResponse {
15
+ id: string;
16
+ requestId: string;
17
+ agentId: string;
18
+ threadId?: string;
19
+ userId?: string;
20
+ timestamp: Date;
21
+ responseLength: number;
22
+ timings: PerformanceTimings;
23
+ tokens: TokenMetrics;
24
+ rag?: RAGMetrics;
25
+ success: boolean;
26
+ errorType?: string;
27
+ model?: string;
28
+ provider?: string;
29
+ }
30
+ interface StoredError {
31
+ id: string;
32
+ agentId: string;
33
+ threadId?: string;
34
+ timestamp: Date;
35
+ errorType: string;
36
+ errorMessage: string;
37
+ component?: string;
38
+ }
39
+ interface AnalyticsQueryOptions {
40
+ agentId?: string;
41
+ threadId?: string;
42
+ userId?: string;
43
+ startDate?: Date;
44
+ endDate?: Date;
45
+ limit?: number;
46
+ offset?: number;
47
+ }
48
+ interface AggregationOptions extends AnalyticsQueryOptions {
49
+ groupBy?: 'hour' | 'day' | 'week' | 'month';
50
+ }
51
+ /**
52
+ * Storage adapter interface for analytics data persistence.
53
+ * Implementations handle storage and retrieval of analytics metrics.
54
+ */
55
+ interface AnalyticsStorage {
56
+ /**
57
+ * Save request records
58
+ */
59
+ saveRequests(requests: StoredRequest[]): Promise<void>;
60
+ /**
61
+ * Save response records
62
+ */
63
+ saveResponses(responses: StoredResponse[]): Promise<void>;
64
+ /**
65
+ * Save error records
66
+ */
67
+ saveErrors(errors: StoredError[]): Promise<void>;
68
+ /**
69
+ * Get requests with optional filtering
70
+ */
71
+ getRequests(options?: AnalyticsQueryOptions): Promise<StoredRequest[]>;
72
+ /**
73
+ * Get responses with optional filtering
74
+ */
75
+ getResponses(options?: AnalyticsQueryOptions): Promise<StoredResponse[]>;
76
+ /**
77
+ * Get errors with optional filtering
78
+ */
79
+ getErrors(options?: AnalyticsQueryOptions): Promise<StoredError[]>;
80
+ /**
81
+ * Get aggregated request count by time period
82
+ */
83
+ getRequestCount(options?: AggregationOptions): Promise<number>;
84
+ /**
85
+ * Get aggregated response count by time period
86
+ */
87
+ getResponseCount(options?: AggregationOptions): Promise<number>;
88
+ /**
89
+ * Get aggregated error count by time period
90
+ */
91
+ getErrorCount(options?: AggregationOptions): Promise<number>;
92
+ /**
93
+ * Delete records older than the specified date
94
+ */
95
+ deleteOlderThan(date: Date): Promise<{
96
+ requests: number;
97
+ responses: number;
98
+ errors: number;
99
+ }>;
100
+ /**
101
+ * Clear all analytics data
102
+ */
103
+ clear(): Promise<void>;
104
+ /**
105
+ * Check if storage is connected and ready
106
+ */
107
+ isReady(): Promise<boolean>;
108
+ /**
109
+ * Close the storage connection (if applicable)
110
+ */
111
+ close(): Promise<void>;
112
+ }
113
+
114
+ /**
115
+ * In-memory analytics storage implementation.
116
+ * Suitable for development, testing, or short-lived processes.
117
+ * Data is lost when the process terminates.
118
+ */
119
+ declare class MemoryAnalyticsStorage implements AnalyticsStorage {
120
+ private requests;
121
+ private responses;
122
+ private errors;
123
+ saveRequests(requests: StoredRequest[]): Promise<void>;
124
+ saveResponses(responses: StoredResponse[]): Promise<void>;
125
+ saveErrors(errors: StoredError[]): Promise<void>;
126
+ getRequests(options?: AnalyticsQueryOptions): Promise<StoredRequest[]>;
127
+ getResponses(options?: AnalyticsQueryOptions): Promise<StoredResponse[]>;
128
+ getErrors(options?: AnalyticsQueryOptions): Promise<StoredError[]>;
129
+ getRequestCount(options?: AggregationOptions): Promise<number>;
130
+ getResponseCount(options?: AggregationOptions): Promise<number>;
131
+ getErrorCount(options?: AggregationOptions): Promise<number>;
132
+ deleteOlderThan(date: Date): Promise<{
133
+ requests: number;
134
+ responses: number;
135
+ errors: number;
136
+ }>;
137
+ clear(): Promise<void>;
138
+ isReady(): Promise<boolean>;
139
+ close(): Promise<void>;
140
+ /**
141
+ * Filter records based on query options
142
+ */
143
+ private filterRecords;
144
+ /**
145
+ * Get current storage stats (for debugging)
146
+ */
147
+ getStats(): {
148
+ requests: number;
149
+ responses: number;
150
+ errors: number;
151
+ };
152
+ }
153
+
154
+ interface MongoAnalyticsStorageConfig {
155
+ /**
156
+ * MongoDB connection URI
157
+ */
158
+ uri: string;
159
+ /**
160
+ * Database name
161
+ * @default 'snap-agent-analytics'
162
+ */
163
+ database?: string;
164
+ /**
165
+ * Collection prefix
166
+ * @default 'analytics'
167
+ */
168
+ collectionPrefix?: string;
169
+ /**
170
+ * Create indexes on first connection
171
+ * @default true
172
+ */
173
+ createIndexes?: boolean;
174
+ }
175
+ /**
176
+ * MongoDB analytics storage implementation.
177
+ * Provides persistent storage with efficient querying and aggregation.
178
+ */
179
+ declare class MongoAnalyticsStorage implements AnalyticsStorage {
180
+ private client;
181
+ private db;
182
+ private requestsCollection;
183
+ private responsesCollection;
184
+ private errorsCollection;
185
+ private readonly config;
186
+ private connectionPromise;
187
+ constructor(config: MongoAnalyticsStorageConfig);
188
+ /**
189
+ * Ensure connection to MongoDB
190
+ */
191
+ private ensureConnection;
192
+ private connect;
193
+ private createIndexes;
194
+ saveRequests(requests: StoredRequest[]): Promise<void>;
195
+ saveResponses(responses: StoredResponse[]): Promise<void>;
196
+ saveErrors(errors: StoredError[]): Promise<void>;
197
+ getRequests(options?: AnalyticsQueryOptions): Promise<StoredRequest[]>;
198
+ getResponses(options?: AnalyticsQueryOptions): Promise<StoredResponse[]>;
199
+ getErrors(options?: AnalyticsQueryOptions): Promise<StoredError[]>;
200
+ getRequestCount(options?: AggregationOptions): Promise<number>;
201
+ getResponseCount(options?: AggregationOptions): Promise<number>;
202
+ getErrorCount(options?: AggregationOptions): Promise<number>;
203
+ deleteOlderThan(date: Date): Promise<{
204
+ requests: number;
205
+ responses: number;
206
+ errors: number;
207
+ }>;
208
+ clear(): Promise<void>;
209
+ isReady(): Promise<boolean>;
210
+ close(): Promise<void>;
211
+ /**
212
+ * Build MongoDB query from options
213
+ */
214
+ private buildQuery;
215
+ /**
216
+ * Get aggregated metrics with grouping by time period
217
+ */
218
+ getAggregatedMetrics(options?: AggregationOptions): Promise<{
219
+ totalRequests: number;
220
+ totalResponses: number;
221
+ totalErrors: number;
222
+ avgLatency: number;
223
+ totalTokens: number;
224
+ errorRate: number;
225
+ }>;
226
+ }
227
+
228
+ interface AnalyticsConfig {
229
+ /**
230
+ * Enable performance metrics
231
+ * @default true
232
+ */
233
+ enablePerformance?: boolean;
234
+ /**
235
+ * Enable RAG metrics
236
+ * @default true
237
+ */
238
+ enableRAG?: boolean;
239
+ /**
240
+ * Enable cost tracking
241
+ * @default true
242
+ */
243
+ enableCost?: boolean;
244
+ /**
245
+ * Enable conversation metrics
246
+ * @default true
247
+ */
248
+ enableConversation?: boolean;
249
+ /**
250
+ * Enable error tracking
251
+ * @default true
252
+ */
253
+ enableErrors?: boolean;
254
+ /**
255
+ * Cost per 1K tokens by model (for cost calculation)
256
+ * Format: { 'gpt-4o': { input: 0.005, output: 0.015 } }
257
+ */
258
+ modelCosts?: Record<string, {
259
+ input: number;
260
+ output: number;
261
+ }>;
262
+ /**
263
+ * Cost per 1K embedding tokens
264
+ * @default 0.0001
265
+ */
266
+ embeddingCost?: number;
267
+ /**
268
+ * Data retention in days (0 = forever)
269
+ * @default 30
270
+ */
271
+ retentionDays?: number;
272
+ /**
273
+ * Flush interval in ms (for batched writes)
274
+ * @default 5000
275
+ */
276
+ flushInterval?: number;
277
+ /**
278
+ * Custom event handler for real-time metrics
279
+ */
280
+ onMetric?: (metric: MetricEvent) => void;
281
+ /**
282
+ * Analytics storage adapter for persistent storage.
283
+ * If not provided, uses in-memory storage (data lost on restart).
284
+ *
285
+ * @example
286
+ * // Use MongoDB storage
287
+ * import { MongoAnalyticsStorage } from '@snap-agent/analytics/storage';
288
+ *
289
+ * const analytics = new SnapAgentAnalytics({
290
+ * storage: new MongoAnalyticsStorage({ uri: process.env.MONGODB_URI! }),
291
+ * });
292
+ */
293
+ storage?: AnalyticsStorage;
294
+ }
295
+ interface MetricEvent {
296
+ type: 'request' | 'response' | 'error';
297
+ timestamp: Date;
298
+ data: RequestTrackingData | ResponseTrackingData | ErrorTrackingData;
299
+ }
300
+ /**
301
+ * Data passed to onFlush callback
302
+ */
303
+ interface FlushData {
304
+ requests: StoredRequest[];
305
+ responses: StoredResponse[];
306
+ errors: StoredError[];
307
+ timestamp: Date;
308
+ }
309
+ /**
310
+ * Performance metrics aggregation
311
+ */
312
+ interface PerformanceMetrics {
313
+ totalRequests: number;
314
+ avgLatency: number;
315
+ p50Latency: number;
316
+ p95Latency: number;
317
+ p99Latency: number;
318
+ minLatency: number;
319
+ maxLatency: number;
320
+ avgLLMTime: number;
321
+ avgRAGTime: number;
322
+ avgPluginTime: number;
323
+ avgDbTime: number;
324
+ avgTimeToFirstToken: number;
325
+ avgTimeToLastToken: number;
326
+ latencyDistribution: {
327
+ under100ms: number;
328
+ under500ms: number;
329
+ under1s: number;
330
+ under5s: number;
331
+ over5s: number;
332
+ };
333
+ }
334
+ /**
335
+ * RAG metrics aggregation
336
+ */
337
+ interface RAGAnalyticsMetrics {
338
+ totalQueries: number;
339
+ avgDocumentsRetrieved: number;
340
+ avgVectorSearchTime: number;
341
+ avgEmbeddingTime: number;
342
+ cacheHitRate: number;
343
+ cacheMissRate: number;
344
+ avgSimilarityScore: number;
345
+ avgRerankTime: number;
346
+ avgContextLength: number;
347
+ avgContextTokens: number;
348
+ avgSourcesCount: number;
349
+ retrievalSuccessRate: number;
350
+ }
351
+ /**
352
+ * Cost metrics aggregation
353
+ */
354
+ interface CostMetrics {
355
+ totalCost: number;
356
+ totalTokens: number;
357
+ totalPromptTokens: number;
358
+ totalCompletionTokens: number;
359
+ avgTokensPerRequest: number;
360
+ avgCostPerRequest: number;
361
+ tokenEfficiency: number;
362
+ costByModel: Record<string, number>;
363
+ costByAgent: Record<string, number>;
364
+ tokensByModel: Record<string, number>;
365
+ totalEmbeddingTokens: number;
366
+ totalEmbeddingCost: number;
367
+ dailyCosts: Record<string, number>;
368
+ }
369
+ /**
370
+ * Conversation quality metrics
371
+ */
372
+ interface ConversationMetrics {
373
+ totalThreads: number;
374
+ totalMessages: number;
375
+ avgMessagesPerThread: number;
376
+ avgThreadDuration: number;
377
+ avgSessionLength: number;
378
+ userReturnRate: number;
379
+ threadAbandonmentRate: number;
380
+ avgInputLength: number;
381
+ avgOutputLength: number;
382
+ inputLengthDistribution: {
383
+ short: number;
384
+ medium: number;
385
+ long: number;
386
+ veryLong: number;
387
+ };
388
+ }
389
+ /**
390
+ * Error metrics aggregation
391
+ */
392
+ interface ErrorMetrics {
393
+ totalErrors: number;
394
+ errorRate: number;
395
+ errorsByType: Record<string, number>;
396
+ llmErrors: number;
397
+ ragErrors: number;
398
+ pluginErrors: number;
399
+ dbErrors: number;
400
+ networkErrors: number;
401
+ timeoutErrors: number;
402
+ rateLimitHits: number;
403
+ successRate: number;
404
+ retryCount: number;
405
+ fallbackUsage: number;
406
+ recentErrors: Array<{
407
+ timestamp: Date;
408
+ type: string;
409
+ message: string;
410
+ agentId: string;
411
+ }>;
412
+ }
413
+ /**
414
+ * All metrics aggregated
415
+ */
416
+ interface AggregatedMetrics {
417
+ period: {
418
+ start: Date;
419
+ end: Date;
420
+ };
421
+ performance: PerformanceMetrics;
422
+ rag: RAGAnalyticsMetrics;
423
+ cost: CostMetrics;
424
+ conversation: ConversationMetrics;
425
+ errors: ErrorMetrics;
426
+ }
427
+ /**
428
+ * Time series data point
429
+ */
430
+ interface TimeSeriesMetric {
431
+ timestamp: Date;
432
+ value: number;
433
+ metadata?: Record<string, any>;
434
+ }
435
+ /**
436
+ * Percentile metrics helper
437
+ */
438
+ interface PercentileMetrics {
439
+ p50: number;
440
+ p75: number;
441
+ p90: number;
442
+ p95: number;
443
+ p99: number;
444
+ }
445
+ /**
446
+ * SnapAgent Analytics Plugin
447
+ *
448
+ * Comprehensive analytics tracking for AI agents with 5 metric categories:
449
+ * 1. Performance Metrics - Latency, timing breakdown, percentiles
450
+ * 2. RAG Metrics - Retrieval stats, cache rates, similarity scores
451
+ * 3. Cost & Token Metrics - Usage tracking, cost calculation
452
+ * 4. Conversation Metrics - Engagement, session quality
453
+ * 5. Error Metrics - Error rates, reliability stats
454
+ */
455
+ declare class SnapAgentAnalytics implements AnalyticsPlugin {
456
+ name: string;
457
+ type: "analytics";
458
+ private config;
459
+ private storage;
460
+ private requests;
461
+ private responses;
462
+ private errors;
463
+ private threadStats;
464
+ private userSessions;
465
+ private idCounter;
466
+ private flushTimer?;
467
+ private pendingRequests;
468
+ private pendingResponses;
469
+ private pendingErrors;
470
+ private isFlushing;
471
+ constructor(config?: AnalyticsConfig);
472
+ /**
473
+ * Track incoming request (basic)
474
+ */
475
+ trackRequest(data: {
476
+ agentId: string;
477
+ threadId?: string;
478
+ message: string;
479
+ timestamp: Date;
480
+ }): Promise<void>;
481
+ /**
482
+ * Track response (basic)
483
+ */
484
+ trackResponse(data: {
485
+ agentId: string;
486
+ threadId?: string;
487
+ response: string;
488
+ latency: number;
489
+ tokensUsed?: number;
490
+ timestamp: Date;
491
+ }): Promise<void>;
492
+ /**
493
+ * Track request with full metadata
494
+ */
495
+ trackRequestExtended(data: RequestTrackingData): Promise<void>;
496
+ /**
497
+ * Track response with full metrics
498
+ */
499
+ trackResponseExtended(data: ResponseTrackingData): Promise<void>;
500
+ /**
501
+ * Track errors
502
+ */
503
+ trackError(data: ErrorTrackingData): Promise<void>;
504
+ /**
505
+ * Get aggregated metrics
506
+ */
507
+ getMetrics(options?: {
508
+ agentId?: string;
509
+ startDate?: Date;
510
+ endDate?: Date;
511
+ groupBy?: 'hour' | 'day' | 'week' | 'month';
512
+ }): Promise<AggregatedMetrics>;
513
+ /**
514
+ * Get performance metrics
515
+ */
516
+ getPerformanceMetrics(options?: {
517
+ agentId?: string;
518
+ startDate?: Date;
519
+ endDate?: Date;
520
+ }): PerformanceMetrics;
521
+ /**
522
+ * Get RAG metrics
523
+ */
524
+ getRAGMetrics(options?: {
525
+ agentId?: string;
526
+ startDate?: Date;
527
+ endDate?: Date;
528
+ }): RAGAnalyticsMetrics;
529
+ /**
530
+ * Get cost metrics
531
+ */
532
+ getCostMetrics(options?: {
533
+ agentId?: string;
534
+ startDate?: Date;
535
+ endDate?: Date;
536
+ }): CostMetrics;
537
+ /**
538
+ * Get conversation metrics
539
+ */
540
+ getConversationMetrics(options?: {
541
+ agentId?: string;
542
+ startDate?: Date;
543
+ endDate?: Date;
544
+ }): ConversationMetrics;
545
+ /**
546
+ * Get error metrics
547
+ */
548
+ getErrorMetrics(options?: {
549
+ agentId?: string;
550
+ startDate?: Date;
551
+ endDate?: Date;
552
+ }): ErrorMetrics;
553
+ /**
554
+ * Get time series data
555
+ */
556
+ getTimeSeries(metric: 'latency' | 'tokens' | 'cost' | 'errors' | 'requests', options?: {
557
+ agentId?: string;
558
+ startDate?: Date;
559
+ endDate?: Date;
560
+ groupBy?: 'hour' | 'day' | 'week';
561
+ }): TimeSeriesMetric[];
562
+ private calculatePerformanceMetrics;
563
+ private calculateRAGMetrics;
564
+ private calculateCostMetrics;
565
+ private calculateConversationMetrics;
566
+ private calculateErrorMetrics;
567
+ private calculateCost;
568
+ private updateThreadStats;
569
+ private trackUserSession;
570
+ private filterResponses;
571
+ private filterRequests;
572
+ private filterErrors;
573
+ private getTimeKey;
574
+ private avg;
575
+ private percentile;
576
+ private cleanup;
577
+ private emptyPerformanceMetrics;
578
+ private emptyRAGMetrics;
579
+ private emptyCostMetrics;
580
+ private emptyConversationMetrics;
581
+ /**
582
+ * Get raw data for export
583
+ */
584
+ exportData(): {
585
+ requests: StoredRequest[];
586
+ responses: StoredResponse[];
587
+ errors: StoredError[];
588
+ };
589
+ /**
590
+ * Clear all analytics data
591
+ */
592
+ clear(): void;
593
+ /**
594
+ * Get summary statistics
595
+ */
596
+ getSummary(): Record<string, any>;
597
+ /**
598
+ * Start the flush timer
599
+ */
600
+ private startFlushTimer;
601
+ /**
602
+ * Stop the flush timer
603
+ */
604
+ private stopFlushTimer;
605
+ /**
606
+ * Flush pending data to external storage via onFlush callback
607
+ * @returns Promise that resolves when flush is complete
608
+ */
609
+ flush(): Promise<void>;
610
+ /**
611
+ * Stop the analytics plugin and flush remaining data
612
+ * Call this before shutting down to ensure all data is persisted
613
+ */
614
+ stop(): Promise<void>;
615
+ /**
616
+ * Get count of pending (unflushed) items
617
+ */
618
+ getPendingCount(): {
619
+ requests: number;
620
+ responses: number;
621
+ errors: number;
622
+ };
623
+ }
624
+
625
+ export { type AggregatedMetrics, type AggregationOptions, type AnalyticsConfig, type AnalyticsQueryOptions, type AnalyticsStorage, type ConversationMetrics, type CostMetrics, type ErrorMetrics, type FlushData, MemoryAnalyticsStorage, type MetricEvent, MongoAnalyticsStorage, type MongoAnalyticsStorageConfig, type PercentileMetrics, type PerformanceMetrics, type RAGAnalyticsMetrics, SnapAgentAnalytics, type StoredError, type StoredRequest, type StoredResponse, type TimeSeriesMetric };