Observability Overview
Comprehensive monitoring, tracing, and debugging capabilities for production LLM applications. Mindwave provides production-grade observability with automatic instrumentation, cost tracking, and performance monitoring.
What is Observability?
Observability gives you deep insights into what's happening inside your AI application by combining:
- Traces - Detailed records of every LLM operation and its lifecycle
- Events - Real-time notifications about requests, completions, and errors
- Metrics - Token usage, costs, performance, and error rates
- Context - Full distributed tracing across services and components
For LLM applications, observability is critical for understanding costs, debugging production issues, optimizing performance, and ensuring quality.
Why Observability Matters for LLM Apps
Production Challenges
LLM applications have unique challenges that traditional monitoring doesn't address:
- Unpredictable Costs - Token usage varies wildly, making budgeting difficult
- Variable Performance - Response times range from milliseconds to minutes
- Black Box Behavior - Hard to understand why an LLM produced a specific response
- Distributed Operations - LLM calls span multiple services and providers
- Quality Issues - Difficult to detect degraded output quality
How Mindwave Helps
Mindwave's observability features solve these challenges:
- Automatic Cost Tracking - Real-time cost estimates for every LLM call
- Performance Monitoring - Track latency, identify slow operations
- Full Traceability - See exactly what happened during each request
- Provider Flexibility - Works with OpenAI, Anthropic, Ollama, and more
- Production-Ready - OpenTelemetry standard, battle-tested architecture
Key Features
OpenTelemetry Tracing
Mindwave uses OpenTelemetry, the industry-standard observability framework:
- Automatic Instrumentation - Zero-code tracing for all LLM operations
- Distributed Tracing - Track requests across services
- Vendor-Neutral - Works with any OTLP-compatible backend
- GenAI Conventions - Follows OpenTelemetry GenAI semantic conventions
Learn more: OpenTelemetry Tracing
Cost Tracking
Track and analyze LLM spending in real-time:
- Automatic Calculation - Costs computed for every request
- Per-User Attribution - Track spending by user, tenant, or feature
- Budget Alerts - Get notified when costs exceed thresholds
- Cost Optimization - Identify expensive operations to optimize
Learn more: Cost Tracking
Event System
React to LLM operations with Laravel events:
- LlmRequestStarted - Before calling the LLM provider
- LlmResponseCompleted - When a request finishes successfully
- LlmErrorOccurred - When an error happens
- LlmTokenStreamed - For each token in streaming responses
Learn more: Events
Database Storage
Query traces directly from your database:
- Eloquent Models - Query traces with Laravel's ORM
- Powerful Queries - Find expensive calls, slow operations, errors
- Local Analysis - No external dependencies required
- Data Retention - Configurable retention policies
Learn more: Querying Traces
OTLP Exporters
Send traces to production observability platforms:
- Jaeger - Open-source distributed tracing
- Grafana Tempo - High-scale tracing backend
- Honeycomb - Modern observability platform
- Datadog - Full-stack monitoring
- Any OTLP-compatible backend
Learn more: OTLP & Exporters
Quick Start
Installation
Mindwave's observability is included in the package. Publish configuration and migrations:
# Publish configuration
php artisan vendor:publish --tag=mindwave-config
# Publish and run migrations
php artisan vendor:publish --tag=mindwave-migrations
php artisan migrateEnable Tracing
Configure tracing in your .env file:
# Enable tracing
MINDWAVE_TRACING_ENABLED=true
# Service name (appears in tracing UI)
MINDWAVE_SERVICE_NAME=my-ai-app
# Database storage
MINDWAVE_TRACE_DATABASE=true
# Optional: OTLP export to Jaeger, Tempo, etc.
MINDWAVE_TRACE_OTLP_ENABLED=falseMake an LLM Call
That's it! Every LLM call is now automatically traced:
use Mindwave\Mindwave\Facades\Mindwave;
// This is automatically traced
$response = Mindwave::llm()
->generateText('What is Laravel?');
// Behind the scenes, Mindwave:
// 1. Creates a trace with unique trace_id
// 2. Creates a span for the LLM call
// 3. Records request parameters
// 4. Tracks token usage
// 5. Estimates cost
// 6. Stores in databaseQuery Your Traces
Query traces using Eloquent:
use Mindwave\Mindwave\Observability\Models\Trace;
// Get recent traces
$traces = Trace::with('spans')
->orderBy('created_at', 'desc')
->limit(10)
->get();
foreach ($traces as $trace) {
echo "Cost: \${$trace->estimated_cost}\n";
echo "Duration: {$trace->getDurationInMilliseconds()}ms\n";
echo "Tokens: {$trace->getTotalTokens()}\n";
}Architecture
Trace Structure
A trace represents a complete operation (like handling an API request) and contains multiple spans:
Trace: 3c8f4b9a2e1d6c7b8a9e0f1d2c3b4a5e
├── Span: chat gpt-4 [client] (750ms, $0.0045)
│ ├── operation: chat
│ ├── provider: openai
│ ├── model: gpt-4
│ ├── input_tokens: 150
│ ├── output_tokens: 300
│ └── status: ok
│
└── Span: execute_tool web_search [internal] (450ms)
├── operation: execute_tool
├── tool_name: web_search
└── status: okStorage Options
Mindwave supports multiple storage backends:
Database (Eloquent)
- Store traces in your application database
- Query with Laravel's ORM
- Fast local analysis
- No external dependencies
OTLP Export
- Send to Jaeger, Tempo, Honeycomb, Datadog
- Distributed tracing across services
- Production observability platforms
- Advanced querying and visualization
Both
- Use database for local queries
- Export to OTLP for distributed tracing
- Best of both worlds
Use Cases
Cost Monitoring
Track LLM spending in real-time:
use Mindwave\Mindwave\Observability\Models\Trace;
// Today's total cost
$cost = Trace::whereDate('created_at', today())
->sum('estimated_cost');
echo "Today's spend: \$" . number_format($cost, 2);Performance Analysis
Find slow operations:
use Mindwave\Mindwave\Observability\Models\Span;
// Find operations slower than 5 seconds
$slow = Span::slow(5000)
->orderBy('duration', 'desc')
->get();
foreach ($slow as $span) {
echo "{$span->name}: {$span->getDurationInMilliseconds()}ms\n";
}Error Debugging
Track down production issues:
// Find recent errors
$errors = Trace::where('status', 'error')
->with('spans')
->orderBy('created_at', 'desc')
->get();
foreach ($errors as $trace) {
$errorSpan = $trace->spans
->firstWhere('status_code', 'error');
echo "Error: {$errorSpan->status_description}\n";
echo "Trace: {$trace->trace_id}\n";
}Real-Time Monitoring
React to LLM operations with events:
use Mindwave\Mindwave\Observability\Events\LlmResponseCompleted;
use Illuminate\Support\Facades\Event;
Event::listen(LlmResponseCompleted::class, function ($event) {
// Alert on expensive calls
if ($event->costEstimate > 0.50) {
Slack::send("Expensive LLM call: \${$event->costEstimate}");
}
});Configuration
Basic Setup
Configure observability in config/mindwave-tracing.php:
return [
// Enable/disable tracing
'enabled' => env('MINDWAVE_TRACING_ENABLED', true),
// Service name
'service_name' => env('MINDWAVE_SERVICE_NAME', 'laravel-app'),
// Database storage
'database' => [
'enabled' => env('MINDWAVE_TRACE_DATABASE', true),
],
// OTLP export
'otlp' => [
'enabled' => env('MINDWAVE_TRACE_OTLP_ENABLED', false),
'endpoint' => env('OTEL_EXPORTER_OTLP_ENDPOINT'),
],
// Privacy
'capture_messages' => env('MINDWAVE_TRACE_CAPTURE_MESSAGES', false),
// Cost estimation
'cost_estimation' => [
'enabled' => true,
],
];Learn more: Configuration
Environment-Specific Settings
Development:
MINDWAVE_TRACING_ENABLED=true
MINDWAVE_TRACE_DATABASE=true
MINDWAVE_TRACE_CAPTURE_MESSAGES=true # Debug with full context
MINDWAVE_TRACE_SAMPLER=always_onProduction:
MINDWAVE_TRACING_ENABLED=true
MINDWAVE_TRACE_DATABASE=false # Use OTLP only
MINDWAVE_TRACE_OTLP_ENABLED=true
MINDWAVE_TRACE_CAPTURE_MESSAGES=false # Privacy
MINDWAVE_TRACE_SAMPLER=traceidratio
MINDWAVE_TRACE_SAMPLE_RATIO=0.1 # Sample 10%Best Practices
1. Always Track Costs in Production
Enable cost tracking to avoid billing surprises:
MINDWAVE_COST_ESTIMATION_ENABLED=trueUpdate pricing regularly as providers change rates.
2. Protect User Privacy
Never capture prompts/responses in production:
MINDWAVE_TRACE_CAPTURE_MESSAGES=false3. Use Sampling in High-Volume Apps
Sample traces to reduce overhead:
MINDWAVE_TRACE_SAMPLER=traceidratio
MINDWAVE_TRACE_SAMPLE_RATIO=0.1 # 10% of traces4. Set Up Data Retention
Automatically prune old traces:
// config/mindwave-tracing.php
'retention_days' => 30,Schedule the prune command:
// app/Console/Kernel.php
$schedule->command('mindwave:prune-traces --days=30')
->daily();5. Monitor Your Monitoring
Use events to alert on issues:
Event::listen(LlmErrorOccurred::class, function ($event) {
Log::error('LLM error', [
'model' => $event->model,
'error' => $event->getMessage(),
]);
});6. Use OTLP for Production
For production deployments, export to a dedicated observability platform:
MINDWAVE_TRACE_DATABASE=false
MINDWAVE_TRACE_OTLP_ENABLED=true
OTEL_EXPORTER_OTLP_ENDPOINT=http://tempo:4318Common Scenarios
Scenario 1: Startup (Local Development)
Goal: Debug locally, minimal setup
Configuration:
MINDWAVE_TRACE_DATABASE=true
MINDWAVE_TRACE_OTLP_ENABLED=false
MINDWAVE_TRACE_CAPTURE_MESSAGES=trueWhy: Database storage is simplest, no external dependencies.
Scenario 2: Growing Team (Staging + Production)
Goal: Visualize traces, track costs
Configuration:
# Staging
MINDWAVE_TRACE_DATABASE=true
MINDWAVE_TRACE_OTLP_ENABLED=true
OTEL_EXPORTER_OTLP_ENDPOINT=http://jaeger:4318
# Production
MINDWAVE_TRACE_DATABASE=false
MINDWAVE_TRACE_OTLP_ENABLED=true
OTEL_EXPORTER_OTLP_ENDPOINT=http://tempo:4318
MINDWAVE_TRACE_SAMPLE_RATIO=0.1Why: Jaeger for staging visualization, Tempo for production scale.
Scenario 3: Enterprise (Multi-Region, High Volume)
Goal: Scale, compliance, cost optimization
Configuration:
MINDWAVE_TRACE_DATABASE=false
MINDWAVE_TRACE_OTLP_ENABLED=true
OTEL_EXPORTER_OTLP_ENDPOINT=http://otel-collector:4318
MINDWAVE_TRACE_SAMPLE_RATIO=0.01 # 1% sampling
MINDWAVE_TRACE_CAPTURE_MESSAGES=falseWhy: OpenTelemetry Collector for advanced processing, low sampling for scale.
Troubleshooting
Traces Not Appearing
Check configuration:
php artisan tinker
>>> config('mindwave-tracing.enabled')
=> trueCheck migrations:
php artisan migrate:status | grep mindwaveCheck logs:
tail -f storage/logs/laravel.log | grep -i traceHigh Memory Usage
Reduce sampling:
MINDWAVE_TRACE_SAMPLE_RATIO=0.1Disable message capture:
MINDWAVE_TRACE_CAPTURE_MESSAGES=falseSlow Performance
Use OTLP instead of database:
MINDWAVE_TRACE_DATABASE=false
MINDWAVE_TRACE_OTLP_ENABLED=trueIncrease batch delay:
'batch' => [
'scheduled_delay_ms' => 10000, // 10 seconds
],Next Steps
Getting Started:
- Tracing - Complete tracing guide
- Configuration - All configuration options
- Cost Tracking - Monitor LLM costs
Advanced:
- Backends - Set up Jaeger, Tempo, Honeycomb
- Querying - Query traces effectively
- Events - React to LLM operations
Production:
- OTLP & Exporters - Production deployments
- Production Guide - Best practices for production