TraceKitTraceKit Docs
Frameworks

Laravel Integration Guide

Integrate TraceKit with Laravel for automatic request tracing, live breakpoints, and production debugging. See database queries, API calls, and exceptions in real-time.

Learn how to instrument your Laravel applications with TraceKit APM for zero-config distributed tracing and performance monitoring.

Zero-Config Automatic Tracing

TraceKit Laravel package automatically traces HTTP requests, database queries, queue jobs, cache operations, and more with minimal setup. Just install and configure your API key!

Prerequisites

Before you begin, you need:

  • PHP 8.1 or higher
  • Laravel 10.x, 11.x, or 12.x
  • A TraceKit account (create one free)
  • A generated API key from the API Keys page

What Gets Traced Automatically

With TraceKit Laravel package installed, these operations are traced automatically with zero configuration:

ComponentSpan TypeCaptured AttributesAuto-Traced?
HTTP RequestsSERVERRoute, method, status, durationYes
Database QueriesDBSQL, bindings, duration, connectionYes
Outgoing HTTP CallsCLIENTmethod, url, status_code, duration, peer.serviceYes (via Http facade)
Queue JobsCustomjob.class, queue, attempts, durationYes
ExceptionsN/Aexception.type, exception.message, stack_traceYes
Custom SpansCustomuser-defined attributesManual

Installation

Install the TraceKit Laravel package via Composer:

composer require tracekit/laravel-apm

Package Autodiscovery -- The service provider is automatically registered via Laravel's package discovery. No need to manually register it!

Configuration

1. Publish Configuration (Optional)

If you want to customize settings, publish the configuration file:

php artisan vendor:publish --provider="TraceKit\Laravel\TracekitServiceProvider"

This creates config/tracekit.php where you can customize settings.

2. Add API Key to .env

Add your TraceKit API key to your .env file:

# TraceKit APM Configuration
TRACEKIT_API_KEY=ctxio_your_generated_api_key_here
TRACEKIT_ENDPOINT=https://app.tracekit.dev/v1/traces
TRACEKIT_SERVICE_NAME=my-laravel-app
TRACEKIT_ENABLED=true

Important Security Note -- Never commit your API key to version control. Keep it in your .env file and use environment-specific values.

Verify It Works

Start your application and make a few requests. Then open the Traces page in your TraceKit dashboard. You should see:

  • SERVER spans for each incoming HTTP request (auto-traced by middleware)
  • DB spans for Eloquent and query builder queries (auto-traced by QueryListener)
  • CLIENT spans for outgoing HTTP calls via the Http facade

Traces typically appear within 30 seconds. If you don't see them, check the Troubleshooting section.

Laravel 12+ Middleware Setup

For Laravel 12+, middleware registration has changed. The package attempts automatic registration, but if needed, manually add the middleware to bootstrap/app.php:

<?php

use Illuminate\Foundation\Application;
use Illuminate\Foundation\Configuration\Middleware;
use TraceKit\Laravel\Middleware\TracekitMiddleware;

return Application::configure(basePath: dirname(__DIR__))
    ->withMiddleware(function (Middleware $middleware) {
        $middleware->web(append: [
            TracekitMiddleware::class,
        ]);
        $middleware->api(append: [
            TracekitMiddleware::class,
        ]);
    })
    // ... rest of your configuration
    ->create();

Laravel 10 & 11 -- For Laravel 10 and 11, the middleware is registered automatically via the service provider. No manual configuration needed!

Environment Variables

Available configuration options in config/tracekit.php:

<?php

return [
    // Enable/disable tracing
    'enabled' => env('TRACEKIT_ENABLED', env('APP_ENV') !== 'local'),

    // Your TraceKit API key
    'api_key' => env('TRACEKIT_API_KEY', ''),

    // OTLP endpoint for sending traces
    'endpoint' => env('TRACEKIT_ENDPOINT', 'https://app.tracekit.dev/v1/traces'),

    // Service name as it appears in TraceKit
    'service_name' => env('TRACEKIT_SERVICE_NAME', env('APP_NAME', 'laravel-app')),

    // Sample rate (0.0 to 1.0)
    'sample_rate' => env('TRACEKIT_SAMPLE_RATE', 1.0),

    // Enable/disable specific features
    'features' => [
        'http' => env('TRACEKIT_HTTP_ENABLED', true),
        'database' => env('TRACEKIT_DATABASE_ENABLED', true),
        'cache' => env('TRACEKIT_CACHE_ENABLED', true),
        'queue' => env('TRACEKIT_QUEUE_ENABLED', true),
        'redis' => env('TRACEKIT_REDIS_ENABLED', true),
    ],

    // Routes to ignore
    'ignored_routes' => [
        '/health',
        '/up',
        '/_healthz',
    ],

    // Slow query threshold (ms)
    'slow_query_threshold' => env('TRACEKIT_SLOW_QUERY_MS', 100),

    // Include query bindings in traces
    'include_query_bindings' => env('TRACEKIT_INCLUDE_BINDINGS', true),
];

Configuration Reference

OptionTypeDefaultEnv VariableDescription
api_keystring""TRACEKIT_API_KEYYour TraceKit API key for authentication
endpointstring"app.tracekit.dev"TRACEKIT_ENDPOINTTraceKit collector endpoint URL
traces_pathstring"/v1/traces"TRACEKIT_TRACES_PATHHTTP path for trace data export
metrics_pathstring"/v1/metrics"TRACEKIT_METRICS_PATHHTTP path for metrics data export
service_namestringAPP_NAME or "laravel-app"TRACEKIT_SERVICE_NAMEName of your service in the trace dashboard
enabledbooltrue (non-local)TRACEKIT_ENABLEDEnable or disable tracing globally
sample_ratefloat1.0TRACEKIT_SAMPLE_RATETrace sampling rate (0.0 to 1.0, where 1.0 = 100%)
features.httpbooltrueTRACEKIT_HTTP_ENABLEDAuto-trace incoming HTTP requests
features.databasebooltrueTRACEKIT_DATABASE_ENABLEDAuto-trace Eloquent and DB queries
features.cachebooltrueTRACEKIT_CACHE_ENABLEDAuto-trace cache operations (Redis, Memcached, file)
features.queuebooltrueTRACEKIT_QUEUE_ENABLEDAuto-trace queued jobs and events
features.redisbooltrueTRACEKIT_REDIS_ENABLEDAuto-trace Redis commands
slow_query_thresholdint100TRACEKIT_SLOW_QUERY_MSThreshold in ms to flag slow queries
include_query_bindingsbooltrueTRACEKIT_INCLUDE_BINDINGSInclude query parameter bindings in trace data
code_monitoring.enabledboolfalseTRACEKIT_CODE_MONITORING_ENABLEDEnable live code debugging / snapshot capture
code_monitoring.poll_intervalint30TRACEKIT_CODE_MONITORING_POLL_INTERVALHow often to poll for active breakpoints (seconds)
code_monitoring.max_variable_depthint3TRACEKIT_CODE_MONITORING_MAX_DEPTHMax variable inspection depth for snapshots
code_monitoring.max_string_lengthint1000TRACEKIT_CODE_MONITORING_MAX_STRINGMax string length captured in snapshots
suppress_errorsbooltrueTRACEKIT_SUPPRESS_ERRORSSuppress SDK errors to prevent app crashes
service_name_mappingsarray[]code onlyMap host:port to service names for service discovery
ignored_routesarray['/health', '/up', '/_healthz']code onlyRoutes excluded from tracing (health checks, etc.)

Laravel auto-reads all TRACEKIT_* environment variables via the env() helper. Add them to your .env file and they take effect immediately (run php artisan config:clear if config is cached).

Code Monitoring (Live Debugging)

Production-Safe Live Debugging -- Capture variable state, stack traces, and request context at any point in your code without redeployment. Perfect for debugging production issues! See the full Code Monitoring Documentation.

Setup

To enable code monitoring for live debugging, add these settings to your .env:

# Enable code monitoring
TRACEKIT_CODE_MONITORING_ENABLED=true

# Polling interval (seconds)
# - 1-5: Development (fast updates, higher load)
# - 10-30: Production (recommended)
# - 60+: Low traffic/minimal overhead
TRACEKIT_CODE_MONITORING_POLL_INTERVAL=30

# Variable inspection depth (1-10)
TRACEKIT_CODE_MONITORING_MAX_DEPTH=3

# String truncation length
TRACEKIT_CODE_MONITORING_MAX_STRING=1000

Usage: Add Debug Points

Use the tracekit_snapshot() helper to capture variable state:

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class OrderController extends Controller
{
    public function processOrder(Request $request)
    {
        $userId = $request->user()->id;
        $cartTotal = $request->input('cart_total');

        // Capture variable state at checkout start
        tracekit_snapshot('checkout-start', [
            'user_id' => $userId,
            'cart_total' => $cartTotal,
            'items_count' => $request->input('items', [])->count(),
        ]);

        try {
            $order = $this->createOrder($request->all());
            $payment = $this->processPayment($order);

            // Capture successful payment state
            tracekit_snapshot('payment-success', [
                'order_id' => $order->id,
                'payment_id' => $payment->id,
                'amount' => $payment->amount,
            ]);

            return response()->json(['order' => $order], 201);
        } catch (\Exception $e) {
            // Exception automatically captured with stack trace!
            throw $e;
        }
    }
}

Features

  • Auto-Registration -- Breakpoints automatically created on first call
  • Variable Capture -- Deep inspection of arrays, objects, and primitives
  • Stack Traces -- Full call stack with file and line numbers
  • Request Context -- HTTP method, route, headers, and query params

Production Safety

The Laravel SDK includes multiple layers of protection:

  • PII Scrubbing -- 13 built-in sensitive data patterns enabled by default. Detected values are replaced with typed [REDACTED:type] markers before leaving your server.
  • Crash Isolation -- All entry points wrap operations in catch(\Throwable) blocks. SDK errors are silently logged and never propagate to your application.
  • Circuit Breaker -- 3 consecutive failures within 60 seconds triggers a 5-minute cooldown. Uses Laravel's Cache facade for cross-request persistence.
  • Remote Kill Switch -- Toggle code monitoring on/off from the dashboard. Propagates instantly via SSE for Artisan commands and queue workers, or via polling for web requests.

Real-Time Updates -- The Laravel SDK uses app()->runningInConsole() to detect the execution context. Long-lived Artisan commands and queue workers receive kill switch and breakpoint updates via SSE (Server-Sent Events) for instant propagation. Web requests use lightweight polling on each snapshot call since PHP processes are short-lived.

LLM Instrumentation

TraceKit automatically instruments OpenAI and Anthropic API calls when detected. LLM calls appear as spans with OTel GenAI semantic convention attributes.

Zero-config auto-instrumentation -- The Laravel SDK auto-registers LLM instrumentation via the service provider. If your app makes OpenAI or Anthropic API calls via HTTP, TraceKit captures them automatically through event listeners.

Captured Attributes

AttributeDescription
gen_ai.systemProvider name (openai, anthropic)
gen_ai.request.modelModel name (gpt-4o, claude-sonnet-4-20250514, etc.)
gen_ai.usage.input_tokensPrompt token count
gen_ai.usage.output_tokensCompletion token count
gen_ai.response.finish_reasonsFinish reason (stop, end_turn, tool_calls)

Configuration

config/tracekit.php
// config/tracekit.php
return [
    'api_key' => env('TRACEKIT_API_KEY'),
    'service_name' => env('APP_NAME', 'my-laravel-app'),
    'llm' => [
        'enabled' => true,
        'openai' => true,
        'anthropic' => true,
        'capture_content' => false,
    ],
];

Use TRACEKIT_LLM_CAPTURE_CONTENT=true to enable prompt/completion capture without code changes. Useful for enabling in staging but not production.

Streaming Support -- Streaming responses produce a single span that covers the entire stream. Token counts are accumulated from the final chunk. No special configuration needed.

LLM Dashboard -- View LLM cost, token usage, and latency metrics on the dedicated LLM Observability dashboard at /ai/llm in your TraceKit instance.

Local UI (Development Mode)

Debug your Laravel application locally without creating an account. TraceKit Local UI runs on your machine at http://localhost:9999 and automatically receives traces when you run your app in local environment.

Automatic Detection -- The Laravel SDK automatically detects when Local UI is running on port 9999 and sends traces to both Local UI and cloud (if you have an API key configured).

Quick Start

  1. Install the Local UI:
npm install -g @tracekit/local-ui
  1. Start the Local UI:
tracekit-local
  1. Run your app (Laravel automatically uses APP_ENV=local):
php artisan serve
  1. Open your browser:
http://localhost:9999

Features

  • Auto-Detection -- SDK checks for Local UI at localhost:9999 on startup
  • Real-Time Updates -- See traces instantly with WebSocket live updates
  • Development Only -- Only activates when APP_ENV=local
  • Works Offline -- No internet connection required

Service Discovery

TraceKit automatically instruments outgoing HTTP calls made with Laravel's HTTP client to create service dependency graphs.

Usage with Laravel HTTP Client

Just use Laravel's HTTP client as normal -- everything is traced automatically:

<?php

use Illuminate\Support\Facades\Http;

// All HTTP calls are automatically traced!
Route::post('/checkout', function (Request $request) {
    // This creates a CLIENT span for the payment-service call
    $paymentResponse = Http::post('http://payment-service/charge', [
        'amount' => $request->input('amount'),
        'user_id' => auth()->id(),
    ]);

    // This creates another CLIENT span for the inventory-service call
    $inventoryResponse = Http::post('http://inventory-service/reserve', [
        'item_id' => $request->input('item_id'),
    ]);

    return response()->json([
        'status' => 'success',
        'payment_id' => $paymentResponse['payment_id'],
    ]);
});

Custom Service Name Mappings

For local development or when service names can't be inferred from hostnames, configure service name mappings in config/tracekit.php:

// config/tracekit.php
return [
    // ... other config

    // Map localhost URLs to actual service names
    'service_name_mappings' => [
        'localhost:8082' => 'payment-service',
        'localhost:8083' => 'user-service',
        'localhost:8084' => 'inventory-service',
    ],
];

// Now requests to localhost:8082 will show as "payment-service" in your service graph
// Http::get('http://localhost:8082/charge');
// -> Creates CLIENT span with peer.service = "payment-service"

Service Name Detection

TraceKit intelligently extracts service names from URLs:

Viewing Service Dependencies -- Visit your TraceKit dashboard to see the Service Map -- a visual graph showing which services call which, with health metrics and latency data.

Manual Instrumentation (Optional)

For custom business logic or specific operations you want to measure, you can manually create spans:

<?php

use TraceKit\Laravel\TracekitClient;

class OrderController extends Controller
{
    public function processOrder(Request $request, TracekitClient $tracekit)
    {
        // Create a custom span
        $span = $tracekit->startSpan('process-order', null, [
            'order.id' => $request->input('order_id'),
            'user.id' => auth()->id(),
        ]);

        try {
            $order = $this->createOrder($request->all());
            $this->processPayment($order);
            $this->sendConfirmation($order);

            $tracekit->endSpan($span, [
                'order.total' => $order->total,
                'order.items_count' => $order->items()->count(),
            ]);

            return response()->json($order, 201);
        } catch (\Exception $e) {
            $tracekit->recordException($span, $e);
            $tracekit->endSpan($span, [], 'ERROR');
            throw $e;
        }
    }
}

Tracekit Facade API

Facade MethodParametersReturnsDescription
Tracekit::startSpan($op, $attrs)string $operationName, array $attributes = []arrayStart a new span via the Facade. Returns span data array.
Tracekit::endSpan($data, $attrs, $status)array $spanData, array $attributes = [], ?string $status = nullvoidEnd a span and optionally set additional attributes and status.
Tracekit::captureSnapshot($label, $vars)string $label, array $variables = []voidCapture a code monitoring snapshot with variable state at this point.
Tracekit::counter($name, $tags)string $name, array $tags = []CounterCreate or retrieve a counter metric via the Facade.
Tracekit::gauge($name, $tags)string $name, array $tags = []GaugeCreate or retrieve a gauge metric via the Facade.
Tracekit::histogram($name, $tags)string $name, array $tags = []HistogramCreate or retrieve a histogram metric via the Facade.

The Tracekit Facade proxies all TracekitClient methods. Use it anywhere in your Laravel application without injecting the client directly.

Complete Example

Here's a complete example showing automatic and manual tracing:

<?php

namespace App\Http\Controllers;

use App\Models\User;
use Illuminate\Http\Request;
use TraceKit\Laravel\TracekitClient;

class UserController extends Controller
{
    // HTTP requests are automatically traced!
    public function index()
    {
        // Database queries are automatically traced!
        $users = User::where('active', true)->get();

        return response()->json($users);
    }

    // You can add custom spans for specific operations
    public function processUserData(Request $request, TracekitClient $tracekit)
    {
        // Start custom span
        $span = $tracekit->startSpan('process-user-data', null, [
            'user.count' => $request->input('user_ids')->count(),
        ]);

        try {
            // Your business logic here
            $results = [];
            foreach ($request->input('user_ids') as $userId) {
                $user = User::find($userId);
                $results[] = $this->processUser($user);
            }

            $tracekit->endSpan($span, [
                'results.count' => count($results),
            ]);

            return response()->json($results);
        } catch (\Exception $e) {
            $tracekit->recordException($span, $e);
            $tracekit->endSpan($span, [], 'ERROR');
            throw $e;
        }
    }

    private function processUser($user)
    {
        // Database queries here are also automatically traced!
        $user->last_processed_at = now();
        $user->save();

        return $user;
    }
}

Custom Metrics

Track custom metrics like request counts, queue sizes, and response times using the TraceKit metrics API.

Counter

Track monotonically increasing values (requests, events):

use TraceKit\Laravel\Facades\Tracekit;

// Create a counter with optional tags
$counter = Tracekit::counter('http.requests.total', [
    'service' => 'api',
    'method' => 'GET',
]);

// Increment by 1
$counter->inc();

// Add a specific value
$counter->add(5);

Gauge

Track values that can go up or down (queue size, connections):

// Create a gauge
$gauge = Tracekit::gauge('http.connections.active');

// Set to specific value
$gauge->set(42);

// Increment/decrement
$gauge->inc();
$gauge->dec();

Histogram

Track value distributions (latencies, sizes):

// Create a histogram with tags
$histogram = Tracekit::histogram('http.request.duration', [
    'unit' => 'ms',
]);

// Record values
$histogram->record(45.2);
$histogram->record(123.5);

View Custom Metrics Guide

Troubleshooting

Traces not appearing?

Cause: Laravel config caching can hide .env changes, or the TraceKit service provider is not loaded.

Fix:

  • Clear config cache: php artisan config:clear
  • Verify TRACEKIT_ENABLED=true in .env
  • Check that TRACEKIT_API_KEY is set
  • Review storage/logs/laravel.log for export errors
  • Ensure the TraceKit service provider is in your providers list (should be auto-discovered)

Package not auto-discovered?

Cause: Laravel's package auto-discovery cache is stale or the package was installed with --no-scripts.

Fix:

  • Run php artisan package:discover followed by php artisan config:clear
  • Verify the provider appears in bootstrap/cache/packages.php
  • If still missing, manually add TraceKit\Laravel\TracekitServiceProvider::class to config/app.php providers array

Code monitoring not working?

Cause: Code monitoring is disabled by default in Laravel.

Fix:

  • Set TRACEKIT_CODE_MONITORING_ENABLED=true in .env
  • Run php artisan config:clear
  • Add captureSnapshot() calls via the Tracekit facade: Tracekit::captureSnapshot('label')
  • Wait for the poll interval (default 30s) before expecting results

Authentication errors (401/403)?

Cause: API key in .env is wrong, has quotes wrapping it, or config cache is stale.

Fix:

  • In .env, use TRACEKIT_API_KEY=ctxio_xxx (no quotes around value)
  • Run php artisan config:clear
  • Verify with php artisan tinker then config('tracekit.api_key')
  • Regenerate key in dashboard if needed

Database or queue traces missing?

Cause: Specific feature flags in the TraceKit config are disabled.

Fix:

  • Verify feature flags in .env: TRACEKIT_DATABASE_ENABLED=true, TRACEKIT_QUEUE_ENABLED=true, TRACEKIT_CACHE_ENABLED=true
  • Check that the slow_query_threshold (default 100ms) is not filtering out fast queries you expect to see
  • Review ignored_routes in config/tracekit.php to ensure your routes are not excluded

Next Steps

  • Explore your traces on the Traces page to identify slow queries and performance bottlenecks
  • Configure alert rules to get notified when issues occur
  • Add custom spans for specific business logic you want to measure
  • Adjust sampling rates for high-traffic applications

Pro Tip -- Enable query bindings to see actual SQL values in traces. Just set TRACEKIT_INCLUDE_BINDINGS=true in your .env file. Perfect for debugging!

On this page