- internal/aiapm/types.go: AICallRecord, filter, summary, and stats types - internal/aiapm/pricing.go: vendor pricing tables (Anthropic, OpenAI, Google, Mistral, DeepSeek, Groq) - internal/aiapm/store.go: PostgreSQL storage with batch insert, filtered queries, aggregations, timeseries - internal/aiapm/collector.go: async collector with buffered channel and background batch writer - internal/api/aiapm_handlers.go: Fiber route handlers for ingest, summary, models, vendors, costs, calls, pricing - cmd/server/main.go: register AI APM routes and create ai_calls table at startup
103 lines
3.7 KiB
Go
103 lines
3.7 KiB
Go
package aiapm
|
|
|
|
import "time"
|
|
|
|
// AICallRecord represents a single AI/LLM API call
|
|
type AICallRecord struct {
|
|
ID string `json:"id"`
|
|
Timestamp time.Time `json:"timestamp"`
|
|
ServiceName string `json:"service_name"`
|
|
ProjectID string `json:"project_id"`
|
|
Vendor string `json:"vendor"`
|
|
Model string `json:"model"`
|
|
TokensIn int `json:"tokens_in"`
|
|
TokensOut int `json:"tokens_out"`
|
|
TokensCacheRead int `json:"tokens_cache_read"`
|
|
TokensCacheWrite int `json:"tokens_cache_write"`
|
|
EstimatedCost float64 `json:"estimated_cost"`
|
|
LatencyMs int `json:"latency_ms"`
|
|
TTFBMs int `json:"ttfb_ms"`
|
|
Status string `json:"status"`
|
|
ErrorMessage string `json:"error_message,omitempty"`
|
|
Stream bool `json:"stream"`
|
|
Cached bool `json:"cached"`
|
|
Tags map[string]string `json:"tags,omitempty"`
|
|
}
|
|
|
|
// AICallFilter defines query filters for AI call records
|
|
type AICallFilter struct {
|
|
ServiceName string `json:"service_name"`
|
|
ProjectID string `json:"project_id"`
|
|
Vendor string `json:"vendor"`
|
|
Model string `json:"model"`
|
|
Status string `json:"status"`
|
|
From time.Time `json:"from"`
|
|
To time.Time `json:"to"`
|
|
Limit int `json:"limit"`
|
|
Offset int `json:"offset"`
|
|
}
|
|
|
|
// AIUsageSummary aggregated usage statistics
|
|
type AIUsageSummary struct {
|
|
TotalCalls int `json:"total_calls"`
|
|
TotalTokensIn int64 `json:"total_tokens_in"`
|
|
TotalTokensOut int64 `json:"total_tokens_out"`
|
|
TotalCacheRead int64 `json:"total_cache_read"`
|
|
TotalCacheWrite int64 `json:"total_cache_write"`
|
|
TotalCost float64 `json:"total_cost"`
|
|
AvgLatencyMs float64 `json:"avg_latency_ms"`
|
|
AvgTTFBMs float64 `json:"avg_ttfb_ms"`
|
|
ErrorCount int `json:"error_count"`
|
|
ErrorRate float64 `json:"error_rate"`
|
|
CacheHitRate float64 `json:"cache_hit_rate"`
|
|
UniqueModels int `json:"unique_models"`
|
|
UniqueVendors int `json:"unique_vendors"`
|
|
UniqueServices int `json:"unique_services"`
|
|
}
|
|
|
|
// AIModelStats per-model breakdown
|
|
type AIModelStats struct {
|
|
Vendor string `json:"vendor"`
|
|
Model string `json:"model"`
|
|
TotalCalls int `json:"total_calls"`
|
|
TotalTokens int64 `json:"total_tokens"`
|
|
TotalCost float64 `json:"total_cost"`
|
|
AvgLatencyMs float64 `json:"avg_latency_ms"`
|
|
ErrorCount int `json:"error_count"`
|
|
ErrorRate float64 `json:"error_rate"`
|
|
}
|
|
|
|
// AIVendorStats per-vendor breakdown
|
|
type AIVendorStats struct {
|
|
Vendor string `json:"vendor"`
|
|
TotalCalls int `json:"total_calls"`
|
|
TotalTokens int64 `json:"total_tokens"`
|
|
TotalCost float64 `json:"total_cost"`
|
|
AvgLatencyMs float64 `json:"avg_latency_ms"`
|
|
ModelCount int `json:"model_count"`
|
|
ErrorCount int `json:"error_count"`
|
|
ErrorRate float64 `json:"error_rate"`
|
|
}
|
|
|
|
// AICostBreakdown cost breakdown by dimension
|
|
type AICostBreakdown struct {
|
|
Dimension string `json:"dimension"` // vendor, model, service, project
|
|
Key string `json:"key"`
|
|
Cost float64 `json:"cost"`
|
|
Calls int `json:"calls"`
|
|
Tokens int64 `json:"tokens"`
|
|
}
|
|
|
|
// TimeseriesPoint a single point in a time series
|
|
type TimeseriesPoint struct {
|
|
Timestamp time.Time `json:"timestamp"`
|
|
Value float64 `json:"value"`
|
|
Count int `json:"count"`
|
|
}
|
|
|
|
// IngestRequest payload for the ingest endpoint
|
|
type IngestRequest struct {
|
|
Call *AICallRecord `json:"call,omitempty"`
|
|
Calls []AICallRecord `json:"calls,omitempty"`
|
|
}
|