Documentation
¶
Overview ¶
Package otellix provides OpenTelemetry-native LLM observability for Go.
Package otellix provides OpenTelemetry-native LLM observability for Go.
Otellix wraps LLM API calls with automatic tracing, token counting, cost attribution, and budget enforcement. Built for production Go backends with cost-constrained environments as a first-class concern.
Quick start:
result, err := otellix.Trace(ctx, provider, params,
otellix.WithModel("claude-sonnet-4-6"),
otellix.WithFeatureID("chat-completion"),
otellix.WithUserID("usr_123"),
otellix.WithProjectID("proj_456"),
)
Index ¶
- func CalculateCost(provider, model string, result providers.CallResult) float64
- func EstimateCost(provider, model string, estimatedOutputTokens int64) float64
- func EstimateTokens(text string) int64
- func EstimateTokensFromMessages(messages []string) int64
- func RegisterDevPrinter()
- func RegisterModel(provider, model string, entry PricingEntry)
- func SetupDev() func()
- func Trace(ctx context.Context, provider providers.Provider, params providers.CallParams, ...) (providers.CallResult, error)
- type BudgetConfig
- type BudgetEnforcer
- func (e *BudgetEnforcer) BudgetError(userID, projectID string) *BudgetExceededError
- func (e *BudgetEnforcer) Check(ctx context.Context, userID, projectID string, estimatedCost float64) (bool, FallbackAction)
- func (e *BudgetEnforcer) Record(ctx context.Context, userID, projectID string, actualCost float64)
- func (e *BudgetEnforcer) Remaining(userID, projectID string) float64
- func (e *BudgetEnforcer) Status(ctx context.Context, userID, projectID string) BudgetStatus
- type BudgetExceededError
- type BudgetStatus
- type BudgetStore
- type Config
- type FallbackAction
- type InMemoryBudgetStore
- type Option
- func WithAttributes(attrs map[string]string) Option
- func WithBudgetConfig(bc *BudgetConfig) Option
- func WithFallbackModel(model string) Option
- func WithFeatureID(featureID string) Option
- func WithModel(model string) Option
- func WithProjectID(projectID string) Option
- func WithPromptDecorator(pd PromptDecorator) Option
- func WithPromptFingerprint(promptText string) Option
- func WithProvider(provider string) Option
- func WithSpanName(name string) Option
- func WithUserID(userID string) Option
- type PricingEntry
- type PromptDecorator
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func CalculateCost ¶
func CalculateCost(provider, model string, result providers.CallResult) float64
CalculateCost computes the USD cost for an LLM call based on the provider, model, and token counts in the result.
Returns 0 for unknown provider/model combinations (does not panic).
func EstimateCost ¶
EstimateCost estimates the cost assuming the given number of output tokens. Used for pre-call budget checks where actual token counts are unknown.
func EstimateTokens ¶
EstimateTokens provides a rough token count estimate from text length. This uses the common heuristic of ~4 characters per token for English text. It's intended for pre-call budget estimation, not exact accounting.
func EstimateTokensFromMessages ¶
EstimateTokensFromMessages estimates total input tokens across multiple messages.
func RegisterDevPrinter ¶
func RegisterDevPrinter()
RegisterDevPrinter enables the human-readable stdout printer without setting up an OTel trace exporter. Useful when you already have your own TracerProvider configured.
func RegisterModel ¶
func RegisterModel(provider, model string, entry PricingEntry)
RegisterModel adds or updates pricing for a provider/model combination. This allows callers to add custom models or override built-in pricing.
Example:
otellix.RegisterModel("anthropic", "claude-4-opus", otellix.PricingEntry{
InputPricePerMToken: 20.0,
OutputPricePerMToken: 100.0,
})
func SetupDev ¶
func SetupDev() func()
SetupDev initialises Otellix for local development with a stdout span exporter and the human-readable dev printer. Call this in main() for local development.
Usage:
shutdown := otellix.SetupDev() defer shutdown()
func Trace ¶
func Trace(ctx context.Context, provider providers.Provider, params providers.CallParams, opts ...Option) (providers.CallResult, error)
Trace executes an LLM call through the given provider, wrapping it with full OpenTelemetry tracing, cost attribution, and optional budget enforcement.
Usage:
result, err := otellix.Trace(ctx, provider, params,
otellix.WithModel("claude-sonnet-4-6"),
otellix.WithFeatureID("chat"),
otellix.WithUserID("usr_123"),
)
Types ¶
type BudgetConfig ¶
type BudgetConfig struct {
// PerUserDailyLimit is the maximum USD spend per user in the rolling window.
PerUserDailyLimit float64
// PerProjectDailyLimit is the maximum USD spend per project in the rolling window.
PerProjectDailyLimit float64
// FallbackAction determines what to do when the budget is exceeded.
FallbackAction FallbackAction
// FallbackModel is the cheaper model to use when FallbackDowngrade is triggered.
FallbackModel string
// ResetInterval is the rolling window duration. Default: 24 hours.
ResetInterval time.Duration
// Store is the backing store for budget data. Default: in-memory.
Store BudgetStore
}
BudgetConfig holds budget enforcement settings.
type BudgetEnforcer ¶
type BudgetEnforcer struct {
// contains filtered or unexported fields
}
BudgetEnforcer checks and records budget usage.
func NewBudgetEnforcer ¶
func NewBudgetEnforcer(config *BudgetConfig) *BudgetEnforcer
NewBudgetEnforcer creates a new enforcer. Uses InMemoryBudgetStore if config.Store is nil.
func (*BudgetEnforcer) BudgetError ¶
func (e *BudgetEnforcer) BudgetError(userID, projectID string) *BudgetExceededError
BudgetError creates a BudgetExceededError with current state.
func (*BudgetEnforcer) Check ¶
func (e *BudgetEnforcer) Check(ctx context.Context, userID, projectID string, estimatedCost float64) (bool, FallbackAction)
Check determines whether a call is allowed given current budget usage. Returns (allowed, fallbackAction).
func (*BudgetEnforcer) Record ¶
func (e *BudgetEnforcer) Record(ctx context.Context, userID, projectID string, actualCost float64)
Record adds actual cost to the budget store after a successful call.
func (*BudgetEnforcer) Remaining ¶
func (e *BudgetEnforcer) Remaining(userID, projectID string) float64
Remaining returns the remaining budget for a user/project (whichever is lower).
func (*BudgetEnforcer) Status ¶ added in v1.1.0
func (e *BudgetEnforcer) Status(ctx context.Context, userID, projectID string) BudgetStatus
Status returns the current detailed budget status for a user/project.
type BudgetExceededError ¶
type BudgetExceededError struct {
UserID string
ProjectID string
CurrentSpend float64
Limit float64
ResetAt time.Time
}
BudgetExceededError is returned when a call is blocked by budget enforcement.
func (*BudgetExceededError) Error ¶
func (e *BudgetExceededError) Error() string
type BudgetStatus ¶ added in v1.1.0
type BudgetStatus struct {
// Remaining is the USD amount left in the budget.
Remaining float64
// Usage is the USD amount spent so far in the current interval.
Usage float64
// IsExceeded is true if the budget limit has been reached.
IsExceeded bool
// Mode is the active fallback action (Block, Notify, Downgrade).
Mode FallbackAction
}
BudgetStatus represents the current state of a user's budget.
type BudgetStore ¶
type BudgetStore interface {
// GetSpend returns the current spend for a key within the rolling window.
GetSpend(ctx context.Context, key string) float64
// AddSpend records additional spend for a key.
AddSpend(ctx context.Context, key string, amount float64)
// GetResetTime returns when the current budget window resets for a key.
GetResetTime(ctx context.Context, key string) time.Time
}
BudgetStore is the interface for pluggable budget storage backends.
type Config ¶
type Config struct {
// Provider identifies the LLM provider (e.g. "anthropic", "openai", "gemini", "ollama").
Provider string
// Model is the specific model identifier (e.g. "claude-sonnet-4-6", "gpt-4o").
Model string
// FeatureID identifies which product feature triggered this call (for cost attribution).
FeatureID string
// UserID identifies who triggered the call (for per-user cost attribution and budget enforcement).
UserID string
// ProjectID identifies which tenant or project this call belongs to (for multi-tenant billing).
ProjectID string
// SpanName overrides the default OTel span name ("llm.call").
SpanName string
// Attributes holds arbitrary key-value metadata attached to the OTel span.
Attributes map[string]string
// EnablePromptFingerprint enables SHA256 fingerprinting of the prompt for drift detection.
EnablePromptFingerprint bool
// PromptText is the raw prompt text used for fingerprinting (system prompt + first user message).
PromptText string
// FallbackModel is the cheaper model to switch to when FallbackDowngrade is triggered.
FallbackModel string
// BudgetConfig holds budget enforcement settings. Nil means no budget enforcement.
BudgetConfig *BudgetConfig
// PromptDecorator is a function that can modify prompt params based on budget context.
PromptDecorator PromptDecorator
}
Config holds the configuration for a single traced LLM call.
type FallbackAction ¶
type FallbackAction int
FallbackAction determines what happens when a budget ceiling is exceeded.
const ( // FallbackBlock returns a BudgetExceededError immediately — the LLM is never called. FallbackBlock FallbackAction = iota // FallbackNotify calls the LLM but emits a budget.exceeded event on the span. FallbackNotify // FallbackDowngrade swaps to a cheaper model (Config.FallbackModel) and proceeds. FallbackDowngrade )
type InMemoryBudgetStore ¶
type InMemoryBudgetStore struct {
// contains filtered or unexported fields
}
InMemoryBudgetStore is a thread-safe, in-memory budget store using rolling time-bucketed counters. Suitable for single-process deployments.
func NewInMemoryBudgetStore ¶
func NewInMemoryBudgetStore(interval time.Duration) *InMemoryBudgetStore
NewInMemoryBudgetStore creates a new in-memory store with the given window.
func (*InMemoryBudgetStore) AddSpend ¶
func (s *InMemoryBudgetStore) AddSpend(ctx context.Context, key string, amount float64)
func (*InMemoryBudgetStore) GetResetTime ¶
type Option ¶
type Option func(*Config)
Option is a functional option for configuring a traced LLM call.
func WithAttributes ¶
WithAttributes sets arbitrary key-value metadata on the span.
func WithBudgetConfig ¶
func WithBudgetConfig(bc *BudgetConfig) Option
WithBudgetConfig sets budget enforcement configuration.
func WithFallbackModel ¶
WithFallbackModel sets the cheaper model for budget downgrade fallback.
func WithFeatureID ¶
WithFeatureID sets the product feature identifier for cost attribution.
func WithProjectID ¶
WithProjectID sets the project/tenant identifier.
func WithPromptDecorator ¶ added in v1.1.0
func WithPromptDecorator(pd PromptDecorator) Option
WithPromptDecorator sets a function to dynamically decorate prompts based on budget.
func WithPromptFingerprint ¶
WithPromptFingerprint enables prompt fingerprinting with the given prompt text.
func WithProvider ¶
WithProvider sets the LLM provider name.
func WithSpanName ¶
WithSpanName overrides the default span name.
func WithUserID ¶
WithUserID sets the user identifier for per-user cost tracking.
type PricingEntry ¶
type PricingEntry struct {
InputPricePerMToken float64 // USD per 1 million input tokens
OutputPricePerMToken float64 // USD per 1 million output tokens
CachePricePerMToken float64 // USD per 1 million cached tokens (0 if N/A)
}
PricingEntry holds the per-million-token pricing for a specific model.
func GetPricing ¶
func GetPricing(provider, model string) (PricingEntry, bool)
GetPricing returns the pricing entry for a specific provider/model combination. Returns (entry, false) if not found.
type PromptDecorator ¶ added in v1.1.0
type PromptDecorator func(ctx context.Context, status BudgetStatus, params *providers.CallParams)
PromptDecorator is a function that can modify LLM call parameters based on the current budget status before the provider is called.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
examples
|
|
|
basic
command
examples/basic/main.go — Minimal working example of Otellix.
|
examples/basic/main.go — Minimal working example of Otellix. |
|
budget-guardrail
command
examples/budget-guardrail/main.go — Budget enforcement demonstration.
|
examples/budget-guardrail/main.go — Budget enforcement demonstration. |
|
docker-compose/app
command
Docker Compose demo app — makes mock LLM calls to demonstrate Otellix metrics.
|
Docker Compose demo app — makes mock LLM calls to demonstrate Otellix metrics. |
|
gin-middleware
command
examples/gin-middleware/main.go — Gin integration with automatic attribution.
|
examples/gin-middleware/main.go — Gin integration with automatic attribution. |
|
prompt-optimization
command
|
|
|
Package exporters provides OTel exporters for Otellix telemetry data.
|
Package exporters provides OTel exporters for Otellix telemetry data. |
|
Package middleware provides HTTP middleware for automatic LLM call attribution.
|
Package middleware provides HTTP middleware for automatic LLM call attribution. |
|
Package providers defines the interface that all LLM provider wrappers implement.
|
Package providers defines the interface that all LLM provider wrappers implement. |
|
anthropic
Package anthropic provides an Otellix provider wrapper for the Anthropic API.
|
Package anthropic provides an Otellix provider wrapper for the Anthropic API. |
|
gemini
Package gemini provides an Otellix provider wrapper for Google's Gemini API.
|
Package gemini provides an Otellix provider wrapper for Google's Gemini API. |
|
ollama
Package ollama provides an Otellix provider wrapper for Ollama (local LLM inference).
|
Package ollama provides an Otellix provider wrapper for Ollama (local LLM inference). |
|
openai
Package openai provides an Otellix provider wrapper for the OpenAI API.
|
Package openai provides an Otellix provider wrapper for the OpenAI API. |