Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Zipkin Opentracing Laravel Package

jcchavezs/zipkin-opentracing

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Install the package:
    composer require jcchavezs/zipkin-opentracing
    
  2. Configure Zipkin collector endpoint (e.g., in .env):
    ZIPKIN_ENDPOINT=http://localhost:9411/api/v2/spans
    
  3. Initialize the tracer in bootstrap/app.php or a service provider:
    use OpenTracing\Tracer;
    use Jcchavezs\Zipkin\ZipkinTracer;
    
    $tracer = new ZipkinTracer('my-service', [
        'collector_endpoint' => env('ZIPKIN_ENDPOINT'),
    ]);
    Tracer::setGlobalTracer($tracer);
    
  4. Wrap a span in your first use case (e.g., a controller method):
    use OpenTracing\Span;
    use OpenTracing\Tracer;
    
    public function index()
    {
        $tracer = Tracer::get();
        $span = $tracer->startSpan('controller.index');
        $span->setTag('http.method', 'GET');
        $span->setTag('http.url', '/');
    
        try {
            // Business logic here
            $span->log(['event' => 'business_logic']);
        } finally {
            $span->finish();
        }
    }
    

First Use Case: HTTP Request Tracing

Instrument an HTTP request (e.g., using illuminate/http middleware):

use OpenTracing\Tracer;
use OpenTracing\SpanContext;

public function handle($request, Closure $next)
{
    $tracer = Tracer::get();
    $span = $tracer->startSpan('http.request', [
        'childOf' => SpanContext::fromContext($request->get('tracing_context'))
    ]);
    $span->setTag('http.method', $request->method());
    $span->setTag('http.url', $request->fullUrl());

    try {
        $response = $next($request);
        $span->setTag('http.status_code', $response->getStatusCode());
        return $response;
    } finally {
        $span->finish();
    }
}

Implementation Patterns

1. Service-Level Tracing

Wrap service method calls with spans to visualize dependencies:

public function fetchUserData(UserService $userService)
{
    $tracer = Tracer::get();
    $span = $tracer->startSpan('service.fetch_user_data');

    try {
        $user = $userService->getUser(1);
        $span->setTag('user.id', $user->id);
        return $user;
    } finally {
        $span->finish();
    }
}

2. Database Query Tracing

Instrument Eloquent queries or raw DB calls:

use OpenTracing\Tracer;

public function getUserWithOrders($userId)
{
    $tracer = Tracer::get();
    $span = $tracer->startSpan('db.query.user_with_orders');
    $span->setTag('db.type', 'mysql');
    $span->setTag('db.statement', 'SELECT * FROM users WHERE id = ?');

    try {
        $user = User::with('orders')->find($userId);
        $span->log(['event' => 'query_executed', 'rows' => $user->orders->count()]);
        return $user;
    } finally {
        $span->finish();
    }
}

3. Asynchronous Task Tracing

Correlate queue jobs with their parent spans:

use OpenTracing\Tracer;
use Illuminate\Bus\QueueingDispatcher;

public function dispatchJob($job, array $options = [])
{
    $tracer = Tracer::get();
    $parentSpan = Tracer::getActiveSpan();

    $span = $tracer->startSpan('job.dispatch', [
        'childOf' => $parentSpan ? $parentSpan->getContext() : null,
    ]);
    $span->setTag('job.class', get_class($job));

    try {
        return $this->dispatchToQueue($job, $options, $span->getContext());
    } finally {
        $span->finish();
    }
}

4. HTTP Client Tracing

Instrument Guzzle or Symfony HTTP clients:

use OpenTracing\Tracer;
use GuzzleHttp\Client;

$client = new Client([
    'handler' => HandlerStack::create([
        new Middleware\TracingMiddleware(Tracer::get()),
    ]),
]);

$response = $client->get('https://api.example.com/data');

5. Context Propagation

Pass spans across service boundaries (e.g., gRPC, message queues):

// Extract context from incoming request
$carrier = new HttpHeaders();
$extractor = new ZipkinExtractor();
$context = $extractor->extract($carrier, $headers);

// Inject context into outgoing request
$injector = new ZipkinInjector();
$injector->inject($context, $carrier);

Gotchas and Tips

Pitfalls

  1. Span Leaks:

    • Unfinished spans consume memory. Always wrap logic in try-finally to call $span->finish().
    • Use Tracer::getActiveSpan() to check for active spans before starting new ones.
  2. Sampling Overhead:

    • Zipkin defaults to 100% sampling. Configure sampling in the tracer:
      $tracer = new ZipkinTracer('my-service', [
          'collector_endpoint' => env('ZIPKIN_ENDPOINT'),
          'sampler' => new CountingSampler(10), // Sample 1 in 10 traces
      ]);
      
  3. Context Propagation Failures:

    • Ensure headers are correctly passed between services. Use ZipkinExtractor/ZipkinInjector for HTTP.
    • For queues, serialize the span context and attach it to the job payload.
  4. Tag Limits:

    • Zipkin has a limit of 32 tags per span. Avoid excessive tagging in hot paths.
  5. PHP 8+ Compatibility:

    • The package supports PHP 7.4+. For PHP 8+, ensure your opentracing and zipkin dependencies are updated:
      composer require opentracing/opentracing:^2.0 openzipkin/zipkin:^3.0
      

Debugging Tips

  1. Verify Spans in Zipkin UI:

    • Check http://localhost:9411 for traces. Use the "Find Traces" feature to search by operation name or tags.
  2. Log Span Contexts:

    • Temporarily log span contexts to debug propagation:
      $spanContext = $span->getContext();
      \Log::debug('Span Context', [
          'trace_id' => $spanContext->getTraceId(),
          'span_id' => $spanContext->getSpanId(),
      ]);
      
  3. Check for Malformed Data:

    • Zipkin rejects spans with invalid timestamps or malformed annotations. Validate data before sending:
      if ($span->getStartTimestamp() > time()) {
          throw new \RuntimeException('Invalid span timestamp');
      }
      
  4. Throttling Errors:

    • If Zipkin returns 429 Too Many Requests, reduce sampling rate or batch spans:
      $tracer->send([$span1, $span2]); // Batch sends
      

Extension Points

  1. Custom Samplers:

    • Implement OpenTracing\Sampler to control trace sampling:
      class ProbabilitySampler implements Sampler {
          public function isSampled(array $context = null): bool {
              return mt_rand() / mt_getrandmax() < 0.1; // 10% sampling
          }
      }
      
  2. Custom Baggage:

    • Attach custom metadata to spans for filtering:
      $span->setBaggageItem('user.role', 'admin');
      
  3. Span Filters:

    • Filter spans before sending to Zipkin (e.g., exclude internal spans):
      $tracer->setSpanProcessor(new FilteringSpanProcessor(
          new ZipkinSpanProcessor(),
          function (Span $span) {
              return !str_starts_with($span->getOperationName(), 'internal.');
          }
      ));
      
  4. Custom Reporters:

    • Extend ZipkinReporter to add pre-send logic (e.g., logging):
      class LoggingZipkinReporter extends ZipkinReporter {
          public function report(Span $span) {
              \Log::debug('Sending span to Zipkin', [
                  'operation' => $span->getOperationName(),
              ]);
              parent::report($span);
          }
      }
      
  5. Async Reporting:

    • Use AsyncZipkinReporter to avoid blocking:
      $reporter = new AsyncZipkinReporter(
          new ZipkinReporter($collectorEndpoint),
          new React\EventLoop\Loop()
      );
      $tracer = new Zipkin
      
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle
atriumphp/atrium
sandermuller/package-boost-laravel
sandermuller/boost-skills
redaxo/core
yusufgenc/filament-api-forge
l3aro/rating-star-for-filament
leek/filament-subtenant-scope