Installation
composer require openzipkin/zipkin
Basic Configuration
Add to config/app.php under providers:
OpenZipkin\Laravel\ZipkinServiceProvider::class,
Publish config (if needed):
php artisan vendor:publish --provider="OpenZipkin\Laravel\ZipkinServiceProvider" --tag="config"
First Use Case: Tracing a Controller
use OpenZipkin\Laravel\Zipkin;
class ExampleController extends Controller
{
public function index()
{
$span = Zipkin::startSpan('example-controller');
try {
// Your logic here
return response()->json(['success' => true]);
} finally {
$span->finish();
}
}
}
Verify in Zipkin UI
docker run -d -p 9411:9411 openzipkin/zipkin)http://localhost:9411 to see traces.Automatic Tracing Use middleware to auto-instrument HTTP requests:
// app/Http/Middleware/TraceRequests.php
public function handle($request, Closure $next)
{
$span = Zipkin::startSpan('http-request', ['http.method' => $request->method()]);
$response = $next($request);
$span->finish();
return $response;
}
Register in app/Http/Kernel.php:
protected $middleware = [
\App\Http\Middleware\TraceRequests::class,
];
Database Query Tracing Wrap Eloquent queries:
$span = Zipkin::startSpan('user-fetch');
$user = User::where('id', 1)->first();
$span->addAnnotation('SQL', ['query' => $user->toSql()]);
$span->finish();
Service Calls (HTTP/Queue) Trace external API calls:
$span = Zipkin::startSpan('external-api-call');
$response = Http::withOptions(['trace' => true])->get('https://api.example.com');
$span->finish();
Queue Job Tracing
Use Zipkin::startSpan() in job handles:
public function handle()
{
$span = Zipkin::startSpan('process-payment');
// Job logic
$span->finish();
}
Illuminate\Queue\Jobs\Job to auto-trace jobs.Zipkin::startSpan() in route closures.HorizonServiceProvider.$span = Zipkin::startSpan('serialize-user');
$resource = new UserResource($user);
$span->finish();
Span Context Propagation
Zipkin::getContext() is passed across threads (e.g., queues, HTTP clients).Zipkin::setContext() when forking spans (e.g., in async jobs).Sampling Rate
config/zipkin.php:
'sampler' => [
'type' => 'probabilistic',
'rate' => 1.0, // 100% sampling
],
Performance Overhead
if conditions). Focus on:
Clock Skew
Baggage Propagation
$span->setBaggageItem('user.id', $user->id);
Missing Traces:
config/zipkin.php).http://zipkin:9411/api/v2/spans).'logging' => [
'enabled' => true,
'channel' => 'single',
],
Corrupted Traces:
Zipkin::generateId() if needed).traceId and spanId are propagated correctly in headers:
$headers = [
'X-B3-TraceId' => $span->getTraceId(),
'X-B3-SpanId' => $span->getSpanId(),
];
Custom Reporters
Extend OpenZipkin\Reporter\BaseReporter to send spans to custom backends (e.g., Jaeger, Datadog).
Span Annotations Add custom annotations for debugging:
$span->addAnnotation('User loaded', ['user_id' => $user->id]);
Baggage Filters Use baggage to route requests dynamically:
if ($span->getBaggageItem('tenant.id')) {
// Tenant-specific logic
}
Context Managers
For complex workflows, use Zipkin::withContext():
Zipkin::withContext(function () {
$span = Zipkin::startSpan('nested-workflow');
// Nested logic
$span->finish();
});
Laravel Events Trace events globally:
Event::listen(function ($event) {
$span = Zipkin::startSpan('event-' . class_basename($event));
// Event logic
$span->finish();
});
How can I help you explore Laravel packages today?