Skip to content

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:

bash
# Publish configuration
php artisan vendor:publish --tag=mindwave-config

# Publish and run migrations
php artisan vendor:publish --tag=mindwave-migrations
php artisan migrate

Enable Tracing ​

Configure tracing in your .env file:

dotenv
# 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=false

Make an LLM Call ​

That's it! Every LLM call is now automatically traced:

php
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 database

Query Your Traces ​

Query traces using Eloquent:

php
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: ok

Storage 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:

php
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:

php
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:

php
// 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:

php
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:

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:

dotenv
MINDWAVE_TRACING_ENABLED=true
MINDWAVE_TRACE_DATABASE=true
MINDWAVE_TRACE_CAPTURE_MESSAGES=true  # Debug with full context
MINDWAVE_TRACE_SAMPLER=always_on

Production:

dotenv
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:

dotenv
MINDWAVE_COST_ESTIMATION_ENABLED=true

Update pricing regularly as providers change rates.

2. Protect User Privacy ​

Never capture prompts/responses in production:

dotenv
MINDWAVE_TRACE_CAPTURE_MESSAGES=false

3. Use Sampling in High-Volume Apps ​

Sample traces to reduce overhead:

dotenv
MINDWAVE_TRACE_SAMPLER=traceidratio
MINDWAVE_TRACE_SAMPLE_RATIO=0.1  # 10% of traces

4. Set Up Data Retention ​

Automatically prune old traces:

php
// config/mindwave-tracing.php
'retention_days' => 30,

Schedule the prune command:

php
// app/Console/Kernel.php
$schedule->command('mindwave:prune-traces --days=30')
    ->daily();

5. Monitor Your Monitoring ​

Use events to alert on issues:

php
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:

dotenv
MINDWAVE_TRACE_DATABASE=false
MINDWAVE_TRACE_OTLP_ENABLED=true
OTEL_EXPORTER_OTLP_ENDPOINT=http://tempo:4318

Common Scenarios ​

Scenario 1: Startup (Local Development) ​

Goal: Debug locally, minimal setup

Configuration:

dotenv
MINDWAVE_TRACE_DATABASE=true
MINDWAVE_TRACE_OTLP_ENABLED=false
MINDWAVE_TRACE_CAPTURE_MESSAGES=true

Why: Database storage is simplest, no external dependencies.

Scenario 2: Growing Team (Staging + Production) ​

Goal: Visualize traces, track costs

Configuration:

dotenv
# 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.1

Why: Jaeger for staging visualization, Tempo for production scale.

Scenario 3: Enterprise (Multi-Region, High Volume) ​

Goal: Scale, compliance, cost optimization

Configuration:

dotenv
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=false

Why: OpenTelemetry Collector for advanced processing, low sampling for scale.

Troubleshooting ​

Traces Not Appearing ​

Check configuration:

php
php artisan tinker
>>> config('mindwave-tracing.enabled')
=> true

Check migrations:

bash
php artisan migrate:status | grep mindwave

Check logs:

bash
tail -f storage/logs/laravel.log | grep -i trace

High Memory Usage ​

Reduce sampling:

dotenv
MINDWAVE_TRACE_SAMPLE_RATIO=0.1

Disable message capture:

dotenv
MINDWAVE_TRACE_CAPTURE_MESSAGES=false

Slow Performance ​

Use OTLP instead of database:

dotenv
MINDWAVE_TRACE_DATABASE=false
MINDWAVE_TRACE_OTLP_ENABLED=true

Increase batch delay:

php
'batch' => [
    'scheduled_delay_ms' => 10000,  // 10 seconds
],

Next Steps ​

Getting Started:

Advanced:

Production: