🎼 Laravel Integration Guide

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

  • • PHP 8.1 or higher
  • • Laravel 10.x, 11.x, or 12.x
  • • An active TraceKit account
  • • 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:

ComponentWhat's CapturedAuto-Traced?
HTTP RequestsRoute, method, status, duration✓ Yes
Database QueriesSQL, bindings, duration, connection✓ Yes
Queue JobsJob class, queue name, status, payload✓ Yes
ExceptionsType, message, stack trace, context✓ Yes
Custom SpansManual instrumentation (optional)Manual

📦 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.

🚀 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!

Configuration Options

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),
];

📸 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!

→ 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

Exception Handling

Exceptions are automatically captured with full stack traces for code discovery:

<?php

// Exceptions are AUTOMATICALLY captured with full stack traces!
// No additional code needed - just throw exceptions as normal

Route::get('/payment/{id}', function ($id) {
    $payment = Payment::find($id);

    if (!$payment) {
        // This exception will be captured with:
        // - Full stack trace
        // - File and line number
        // - Request context (route, headers, params)
        // - All for code discovery!
        throw new \Exception('Payment not found');
    }

    return $payment;
});

// You can also manually capture at exception points
Route::post('/process', function (Request $request) {
    try {
        $result = $this->riskyOperation($request->all());
    } catch (\Exception $e) {
        // Optionally add a snapshot before re-throwing
        tracekit_snapshot('operation-failed', [
            'error' => $e->getMessage(),
            'input' => $request->all(),
        ]);
        
        throw $e; // Auto-captured!
    }
});

Production Safe

Snapshots are sampled and have minimal performance impact. Capture rates and conditions can be controlled via the TraceKit dashboard.

🚀 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

2. Start the Local UI:

tracekit-local

3. Run your app (Laravel automatically uses APP_ENV=local):

php artisan serve

4. 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 - everything runs locally

Benefits

  • See your first trace in under 60 seconds
  • Debug locally without switching to the cloud dashboard
  • Stay in your flow - everything runs on your machine
  • Works completely offline
  • Perfect for development and demos
💡

Troubleshooting

If traces aren't appearing in Local UI, check:

  • Local UI is running (curl http://localhost:9999/api/health)
  • APP_ENV=local is set in .env file
  • SDK version is v1.1.1 or higher
  • Check logs for "🔍 Local UI detected" message

🌐 Service Discovery

TraceKit automatically instruments outgoing HTTP calls made with Laravel's HTTP client to create service dependency graphs. When your service makes an HTTP request to another service, TraceKit creates CLIENT spans and injects trace context headers.

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:

URLExtracted Service Name
http://payment-service:3000payment-service
http://payment.internalpayment
http://payment.svc.cluster.localpayment
https://api.example.comapi.example.com
💡

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;
        }
    }
}

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;
    }
}
🎉

You're all set!

Your Laravel application is now sending traces to TraceKit. Visit the Dashboard to see your traces.

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);

🔧 Troubleshooting

Traces Not Appearing?

  1. Verify your API key is correct in .env
  2. Check TRACEKIT_ENABLED=true in your .env
  3. Clear config cache: php artisan config:clear
  4. Check Laravel logs in storage/logs/laravel.log
  5. Verify TraceKit endpoint is accessible

Package Not Auto-Discovered?

Run package discovery manually:

php artisan package:discover php artisan config:clear

🚀 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!