Operations 8 min read

How to Set Up Zipkin Distributed Tracing in PHP Webman Projects

This guide explains Zipkin's architecture, data collection methods, and step‑by‑step installation and configuration for PHP applications, including creating tracers, recording spans, and integrating a middleware for full‑stack monitoring in Webman microservice environments.

Open Source Tech Hub
Open Source Tech Hub
Open Source Tech Hub
How to Set Up Zipkin Distributed Tracing in PHP Webman Projects

Overview

Zipkin is an open‑source distributed tracing system that reconstructs call chains, aggregates request counts, visualizes topology, and analyzes service dependencies, helping developers locate performance bottlenecks in microservice architectures.

Official repository: https://github.com/openzipkin/zipkin

Architecture

Primary tracing workflow

Client applications embed language‑specific SDKs (supporting OpenTracing) to report service call data.

The reported data is aggregated and persisted by Zipkin, producing detailed traces, performance overviews, and real‑time topologies for troubleshooting.

Trace data can be forwarded to downstream analysis services for offline processing and alerting.

Data reporting methods

Direct reporting (traditional frameworks)

Direct data reporting without an agent (e.g., PHP‑FPM + Nginx).

ThinkPHP 6.0

Laravel

Yii 2.0

Agent‑based reporting (modern frameworks)

Data reporting via an agent (command‑line mode).

webman

Swoole

Installation

Install via Composer:

composer require openzipkin/zipkin

Usage

Create a Tracer

A Tracer creates Span objects to record distributed operation timings. It also configures the reporting endpoint, local IP, and sampling rate.

function create_tracing($endpointName, $ipv4) {
    $endpoint = Endpoint::create($endpointName, $ipv4, null, 2555);
    $logger = new \Monolog\Logger('log');
    $logger->pushHandler(new \Monolog\Handler\ErrorLogHandler());
    $reporter = new Zipkin\Reporters\Http(Zipkin\Reporters\Http\CurlFactory::create());
    $sampler = BinarySampler::createAsAlwaysSample();
    $tracing = TracingBuilder::create()
        ->havingLocalEndpoint($endpoint)
        ->havingSampler($sampler)
        ->havingReporter($reporter)
        ->build();
    return $tracing;
}

Record request data

$rootSpan = $tracer->newTrace();
$rootSpan->setName('encode');
$rootSpan->start();
try {
    doSomethingExpensive();
} finally {
    $rootSpan->finish();
}
To record child or subsequent operations, pass the parent context to newChild() as shown.
$span = $tracer->newChild($parentSpan->getContext());
$span->setName('encode');
$span->start();
try {
    doSomethingExpensive();
} finally {
    $span->finish();
}

Overall flow

Client Span                                 Server Span
┌──────────────────┐                       ┌──────────────────┐
│                  │                       │                  │
│   TraceContext   │   Http Request Headers │   TraceContext   │
│ ┌──────────────┐ │   X‑B3‑TraceId        │ ┌──────────────┐ │
│ │ TraceId      │ │   X‑B3‑ParentSpanId   │ │ TraceId      │ │
│ │ ParentSpanId │ │   X‑B3‑SpanId         │ │ ParentSpanId │ │
│ │ SpanId       │ │   X‑B3‑Sampled        │ │ SpanId       │ │
│ │ Sampled      │ │                       │ │ Sampled      │ │
│ └──────────────┘ │                       │ └──────────────┘ │
└──────────────────┘                       └──────────────────┘

Webman integration example

Middleware implementation

<?php
declare(strict_types=1);

namespace app\middleware;

use Monolog\Handler\ErrorLogHandler;
use Monolog\Logger;
use think\facade\Db;
use Webman\MiddlewareInterface;
use Webman\Http\Response;
use Webman\Http\Request;
use Zipkin\Reporters\Http as ZipkinHttp;
use Zipkin\TracingBuilder;
use Zipkin\Samplers\BinarySampler;
use Zipkin\Endpoint;
use Workerman\Timer;
use const Zipkin\Tags\SQL_QUERY;

class ArmsMiddleware implements MiddlewareInterface
{
    public function process(Request $request, callable $next): Response
    {
        static $tracing = null, $tracer = null;
        if (!$tracing) {
            $endpoint = Endpoint::create('OpenTechStack', $request->getRealIp(), null, 2555);
            $logger = new Logger('log');
            $logger->pushHandler(new ErrorLogHandler());
            // Replace the URL with your Zipkin collector endpoint
            $reporter = new ZipkinHttp(['endpoint_url' => config('security')['endpoint_url']]);
            $sampler = BinarySampler::createAsAlwaysSample();
            $tracing = TracingBuilder::create()
                ->havingLocalEndpoint($endpoint)
                ->havingSampler($sampler)
                ->havingReporter($reporter)
                ->build();
            $tracer = $tracing->getTracer();
            Timer::add(55, function () use ($tracer) { $tracer->flush(); });
            register_shutdown_function(function () use ($tracer) { $tracer->flush(); });
        }

        $rootSpan = $tracer->newTrace();
        $rootSpan->setName($request->controller . '::' . $request->action);
        $rootSpan->start();
        $request->rootSpan = $rootSpan;
        $request->tracer = $tracer;
        $result = $next($request);

        if (class_exists(Db::class)) {
            $logs = Db::getDbLog(true);
            if (!empty($logs['sql'])) {
                foreach ($logs['sql'] as $sql) {
                    $sqlSpan = $tracer->newChild($rootSpan->getContext());
                    $sqlSpan->setName(SQL_QUERY);
                    $sqlSpan->start();
                    $sqlSpan->tag('db.statement', $sql);
                    $sqlSpan->finish();
                }
            }
        }

        $rootSpan->finish();
        return $result;
    }
}

Register the middleware

return [
    '' => [
        \app\middleware\ArmsMiddleware::class,
    ],
    // other middleware ...
];
Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

monitoringMicroservicesDistributed TracingPHPzipkinWebman
Open Source Tech Hub
Written by

Open Source Tech Hub

Sharing cutting-edge internet technologies and practical AI resources.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.