--- title: "Log Store" description: "A robust and queryable system for persisting API request and response logs, with support for multiple database backends." icon: "clipboard-list" --- The LogStore is a core component of the Bifrost framework responsible for capturing, storing, and retrieving detailed logs of API requests and responses. It provides a persistent, queryable audit trail of all activity passing through the gateway, which is essential for debugging, monitoring, analytics, and compliance. ## Core Features - **Persistent Logging**: Automatically saves detailed information about each API request, including input, output, status, latency, and cost. - **Multiple Backend Support**: Comes with built-in support for SQLite and PostgreSQL, allowing you to choose the best storage solution for your deployment needs. - **Rich Querying and Filtering**: A powerful search API allows you to filter and sort logs based on a wide range of criteria such as provider, model, status, latency, cost, and content. - **Performance Analytics**: The search functionality also provides aggregated statistics, including total requests, success rate, average latency, total tokens, and total cost for the queried data. - **Structured Data Model**: Logs are stored in a structured format, with complex objects like message history and tool calls serialized as JSON for efficient storage and retrieval. - **Automatic Data Management**: Includes GORM hooks to automatically handle JSON serialization/deserialization and to build a searchable content summary. ## Architecture The LogStore is built around the `LogStore` interface, which defines the standard methods for interacting with the log database. The primary implementation, `RDBLogStore`, uses GORM to provide an abstraction over relational databases. ### Supported Backends - **SQLite**: The default, file-based database, ideal for local development and smaller, single-node deployments. - **PostgreSQL**: A production-ready database for scalable and high-availability deployments. The backend is configured in Bifrost's main configuration file. ### Initialization The LogStore is initialized at startup based on the provided configuration. ```go import ( "github.com/maximhq/bifrost/framework/logstore" "github.com/maximhq/bifrost/core/schemas" ) // Example: Initialize a SQLite-based LogStore config := &logstore.Config{ Enabled: true, Type: logstore.LogStoreTypeSQLite, Config: &logstore.SQLiteConfig{ File: "/path/to/logs.db", }, } var logger schemas.Logger // Assume logger is initialized store, err := logstore.NewLogStore(context.Background(), config, logger) if err != nil { // Handle error } ``` Here is an example for initializing a PostgreSQL-based `LogStore`: ```go // Example: Initialize a PostgreSQL-based LogStore pgConfig := &logstore.Config{ Enabled: true, Type: logstore.LogStoreTypePostgres, Config: &logstore.PostgresConfig{ Host: "localhost", Port: "5432", User: "postgres", Password: "secret", DBName: "bifrost_logs", SSLMode: "disable", MaxIdleConns: 5, // Optional: Maximum idle connections (default: 5) MaxOpenConns: 50, // Optional: Maximum open connections (default: 50) }, } store, err = logstore.NewLogStore(context.Background(), pgConfig, logger) if err != nil { // Handle error } ``` PostgreSQL databases used by Bifrost stores must be UTF8 encoded. See [PostgreSQL UTF8 Requirement](../../quickstart/gateway/setting-up#postgresql-utf8-requirement). ### Connection Pool Configuration For PostgreSQL backends, you can configure the database connection pool to optimize performance based on your workload: - **MaxIdleConns**: Maximum number of idle connections in the pool (default: 5) - **MaxOpenConns**: Maximum number of open connections to the database (default: 50) These parameters help manage database connection resources effectively. Increase them for high-traffic deployments or decrease them for resource-constrained environments. ## Data Model The core of the LogStore is the `Log` struct, which represents a single log entry in the `logs` table. ```go // Log represents a complete log entry for a request/response cycle type Log struct { ID string `gorm:"primaryKey;type:varchar(255)"` Timestamp time.Time `gorm:"index;not null"` Object string `gorm:"type:varchar(255);index;not null;column:object_type"` Provider string `gorm:"type:varchar(255);index;not null"` Model string `gorm:"type:varchar(255);index;not null"` Latency *float64 Cost *float64 `gorm:"index"` Status string `gorm:"type:varchar(50);index;not null"` // "processing", "success", or "error" Stream bool `gorm:"default:false"` // Denormalized token fields for easier querying PromptTokens int `gorm:"default:0"` CompletionTokens int `gorm:"default:0"` TotalTokens int `gorm:"default:0"` // JSON serialized fields InputHistory string `gorm:"type:text"` OutputMessage string `gorm:"type:text"` TokenUsage string `gorm:"type:text"` ErrorDetails string `gorm:"type:text"` // ... and many more for different data types } ``` Complex data like message arrays and tool calls are serialized into JSON strings for storage and are automatically deserialized back into their struct forms when retrieved. ## Usage ### Creating Log Entries A log entry is created by populating a `Log` struct and passing it to the `Create` method. This is typically handled internally by Bifrost's logging plugins. ```go logEntry := &logstore.Log{ ID: "req-xyz123", Timestamp: time.Now(), Provider: "openai", Model: "gpt-4", Status: "success", // ... other fields } err := store.Create(ctx, logEntry) ``` ### Searching and Filtering Logs The `SearchLogs` method provides a powerful way to query logs with fine-grained filters and pagination. ```go // Define search criteria filters := logstore.SearchFilters{ Providers: []string{"openai", "anthropic"}, Status: []string{"error"}, StartTime: &startTime, // time.Time pointer } pagination := logstore.PaginationOptions{ Limit: 50, Offset: 0, SortBy: "timestamp", Order: "desc", } // Execute the search results, err := store.SearchLogs(ctx, filters, pagination) if err != nil { // Handle error } // Process the results for _, log := range results.Logs { fmt.Printf("Found log: %s\n", log.ID) } // Access aggregated stats fmt.Printf("Total errors: %d\n", results.Stats.TotalRequests) ``` The LogStore is an indispensable tool for observability in Bifrost, providing the detailed audit trail needed to monitor, debug, and analyze AI application performance and behavior effectively.