PHPackages                             erfanmomeniii/laravel-jaeger-client - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Logging &amp; Monitoring](/categories/logging)
4. /
5. erfanmomeniii/laravel-jaeger-client

ActiveLibrary[Logging &amp; Monitoring](/categories/logging)

erfanmomeniii/laravel-jaeger-client
===================================

A production-grade Jaeger distributed tracing client for Laravel with deep framework integration

v1.0.0(3mo ago)00MITPHPPHP ^8.1

Since Apr 26Pushed 3mo agoCompare

[ Source](https://github.com/ErfanMomeniii/laravel-jaeger-client)[ Packagist](https://packagist.org/packages/erfanmomeniii/laravel-jaeger-client)[ RSS](/packages/erfanmomeniii-laravel-jaeger-client/feed)WikiDiscussions master Synced 1w ago

READMEChangelog (1)Dependencies (11)Versions (2)Used By (0)

Laravel Jaeger Client
=====================

[](#laravel-jaeger-client)

A production-grade [Jaeger](https://www.jaegertracing.io/) distributed tracing client for Laravel.

Zero-config automatic tracing for HTTP requests, database queries, queue jobs, cache, Redis, and more — plus a clean API for manual instrumentation.

[![License: MIT](https://camo.githubusercontent.com/784362b26e4b3546254f1893e778ba64616e362bd6ac791991d2c9e880a3a64e/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c6963656e73652d4d49542d677265656e2e737667)](LICENSE)

---

Why This Package?
-----------------

[](#why-this-package)

FeatureThis packageRaw PHP Jaeger clientsOpenTelemetry SDKAutomatic HTTP tracing✅❌✅DB / Queue / Cache watchers✅❌Partial`Jaeger::fake()` for testing✅❌❌Trace context in logs✅❌PartialZero external PHP deps✅❌❌Lightweight (no gRPC/protobuf)✅✅❌Laravel auto-discovery✅❌❌---

Requirements
------------

[](#requirements)

- PHP 8.1+
- Laravel 10, 11, or 12
- `ext-sockets` (for UDP transport, enabled by default in most PHP installations)

Installation
------------

[](#installation)

```
composer require erfanmomeniii/laravel-jaeger-client
```

Publish the config file:

```
php artisan vendor:publish --tag=jaeger-config
```

That's it. The package auto-discovers and starts tracing immediately.

---

Quick Start
-----------

[](#quick-start)

### 1. Start Jaeger

[](#1-start-jaeger)

```
docker run -d --name jaeger \
  -p 6831:6831/udp \
  -p 16686:16686 \
  jaegertracing/all-in-one:latest
```

### 2. Add to your `.env`

[](#2-add-to-your-env)

```
JAEGER_ENABLED=true
JAEGER_SERVICE_NAME=my-api
```

### 3. Make a request to your app, then open

[](#3-make-a-request-to-your-app-then-open-httplocalhost16686)

You'll see traces for every HTTP request, including child spans for each database query, outbound HTTP call, and more — without writing a single line of tracing code.

---

What Gets Traced Automatically
------------------------------

[](#what-gets-traced-automatically)

ComponentSpan nameEnabled by defaultHTTP requests`HTTP GET /api/users`✅Database queries`db.query`✅Queue jobs`queue.process ProcessPayment`✅Outbound HTTP`HTTP POST api.stripe.com`✅Log context*(injects trace\_id/span\_id)*✅Cache operations`cache.hit`, `cache.put`❌Redis commands`redis.GET`, `redis.SET`❌Events`event.OrderCreated`❌Artisan commands`artisan:migrate`❌View rendering`view.render welcome`❌Enable any disabled watcher in `config/jaeger.php`:

```
'cache' => ['enabled' => true],
'redis' => ['enabled' => true],
```

---

Manual Instrumentation
----------------------

[](#manual-instrumentation)

### `measure()` — Trace a block of code (recommended)

[](#measure--trace-a-block-of-code-recommended)

The simplest way. The span auto-finishes when the callback returns, and errors are auto-tagged:

```
use LaravelJaeger\Laravel\Facades\Jaeger;

$result = Jaeger::build('payment.charge')
    ->withTag('payment.id', $payment->id)
    ->withTag('payment.amount', $payment->amount)
    ->measure(function () use ($payment) {
        return $this->gateway->charge($payment);
    });
```

### `jaeger_span()` — Quick scope for manual control

[](#jaeger_span--quick-scope-for-manual-control)

When you need to add tags or logs during execution:

```
$scope = jaeger_span('order.process', ['order.id' => $order->id]);

try {
    $this->processOrder($order);
    $scope->getSpan()->setTag('order.status', 'completed');
} catch (\Throwable $e) {
    $scope->getSpan()->setTag('error', true);
    $scope->getSpan()->log([
        'event' => 'error',
        'error.kind' => get_class($e),
        'error.message' => $e->getMessage(),
    ]);
    throw $e;
} finally {
    $scope->close();
}
```

### Other Helpers

[](#other-helpers)

```
// Tag the current active span (from middleware or a parent)
jaeger_active_span()?->setTag('user.id', auth()->id());

// Access the tracer directly
$tracer = jaeger();
```

---

Configuration
-------------

[](#configuration)

All settings are in `config/jaeger.php`, driven by environment variables:

### Core Settings

[](#core-settings)

```
JAEGER_ENABLED=true                  # Master switch (false = zero overhead)
JAEGER_SERVICE_NAME=my-api           # Service name shown in Jaeger UI
JAEGER_SERVICE_VERSION=1.2.0         # Shown as process tag
JAEGER_ENVIRONMENT=production        # Shown as process tag
```

### Transport

[](#transport)

```
# UDP to Jaeger agent (default — recommended for production)
JAEGER_TRANSPORT=udp
JAEGER_AGENT_HOST=127.0.0.1
JAEGER_AGENT_PORT=6831

# HTTP direct to collector (useful for serverless / no sidecar)
JAEGER_TRANSPORT=http
JAEGER_COLLECTOR_ENDPOINT=http://jaeger-collector:14268/api/traces
JAEGER_AUTH_TOKEN=your-secret-token

# Debug: write spans to Laravel log
JAEGER_TRANSPORT=log

# Disable sending entirely
JAEGER_TRANSPORT=null
```

### Sampling

[](#sampling)

```
# Sample everything (development)
JAEGER_SAMPLER_TYPE=const
JAEGER_SAMPLER_PARAM=1

# Sample 10% of traces (production)
JAEGER_SAMPLER_TYPE=probabilistic
JAEGER_SAMPLER_PARAM=0.1

# Max 2 traces per second (high-traffic production)
JAEGER_SAMPLER_TYPE=rate_limiting
JAEGER_SAMPLER_PARAM=2.0
```

### Propagation Format

[](#propagation-format)

```
# Jaeger native (default) — uber-trace-id header
JAEGER_PROPAGATION=jaeger

# Zipkin B3 — X-B3-TraceId / X-B3-SpanId headers
JAEGER_PROPAGATION=b3

# W3C TraceContext — traceparent header
JAEGER_PROPAGATION=w3c

# Try all formats when extracting (for polyglot environments)
JAEGER_PROPAGATION=composite
```

### Feature Toggles

[](#feature-toggles)

```
JAEGER_MIDDLEWARE_ENABLED=true       # HTTP request tracing
JAEGER_DB_ENABLED=true               # Database query tracing
JAEGER_QUEUE_ENABLED=true            # Queue job tracing
JAEGER_HTTP_CLIENT_ENABLED=true      # Outbound HTTP tracing
JAEGER_LOG_CONTEXT_ENABLED=true      # Inject trace_id in logs
JAEGER_CACHE_ENABLED=false           # Cache operation tracing
JAEGER_REDIS_ENABLED=false           # Redis command tracing
JAEGER_EVENTS_ENABLED=false          # Event dispatch tracing
JAEGER_ARTISAN_ENABLED=false         # Artisan command tracing
JAEGER_VIEWS_ENABLED=false           # View rendering tracing
```

---

Queue Tracing
-------------

[](#queue-tracing)

Trace context propagates automatically from the dispatching request to the job worker. Add the `TracedJob` trait to your jobs:

```
use Illuminate\Contracts\Queue\ShouldQueue;
use LaravelJaeger\Laravel\Traits\TracedJob;

class ProcessPayment implements ShouldQueue
{
    use TracedJob;

    public function handle(): void
    {
        // The parent trace from the HTTP request is linked here.
        jaeger_active_span()?->setTag('payment.status', 'completed');
    }
}
```

---

Log Correlation
---------------

[](#log-correlation)

When `JAEGER_LOG_CONTEXT_ENABLED=true` (default), every log line includes trace context:

```
{
  "message": "Payment processed successfully",
  "extra": {
    "trace_id": "a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4",
    "span_id": "1a2b3c4d5e6f7a8b"
  }
}
```

Search your logs by `trace_id` to find all log entries for a single request, then click through to the Jaeger UI to see the full trace.

---

Testing
-------

[](#testing)

### `Jaeger::fake()`

[](#jaegerfake)

Works just like Laravel's `Queue::fake()` and `Event::fake()`:

```
use LaravelJaeger\Laravel\Facades\Jaeger;

public function test_checkout_creates_payment_trace(): void
{
    $fake = Jaeger::fake();

    $this->postJson('/api/checkout', ['item_id' => 1]);

    // Assert spans were created
    $fake->assertSpanCreated('HTTP POST /api/checkout');
    $fake->assertSpanCreated('db.query');
    $fake->assertSpanCreated('payment.charge');

    // Assert specific tags
    $fake->assertSpanHasTag('payment.charge', 'payment.amount', 99.99);

    // Assert errors were recorded
    $fake->assertSpanHasLog('payment.charge', ['event' => 'error']);

    // Assert span count
    $fake->assertSpanCount(5);
}
```

### `WithTracing` Trait

[](#withtracing-trait)

For test classes that always need tracing:

```
use LaravelJaeger\Testing\WithTracing;

class PaymentTest extends TestCase
{
    use WithTracing;

    public function test_charge(): void
    {
        // $this->fakeTracer is automatically available
        $this->processPayment();

        $this->fakeTracer->assertSpanCreated('payment.charge');
    }
}
```

### All Assertion Methods

[](#all-assertion-methods)

MethodDescription`assertSpanCreated($name)`A span with this operation name exists`assertSpanNotCreated($name)`No span with this name exists`assertSpanCreatedWithTags($name, $tags)`Span exists with these tag values`assertSpanCount($n)`Exactly *n* spans were created`assertNoSpansCreated()`Zero spans created`assertSpanHasTag($name, $key, $value)`Specific tag value on a span`assertSpanHasLog($name, $fields)`Span has a log entry with these fields`collectedSpans()`Get raw span array for custom assertions`reset()`Clear all collected spans---

Extending
---------

[](#extending)

Every component is coded to an interface. Swap any part by rebinding in the container.

### Custom Sampler

[](#custom-sampler)

```
use LaravelJaeger\Contracts\SamplerInterface;

class UserBasedSampler implements SamplerInterface
{
    public function isSampled(string $traceId, string $operationName): array
    {
        $isAdmin = auth()->user()?->is_admin ?? false;

        return [$isAdmin, ['sampler.type' => 'user-based', 'sampler.param' => $isAdmin]];
    }

    public function close(): void {}
}

// Register in AppServiceProvider:
$this->app->bind(SamplerInterface::class, UserBasedSampler::class);
```

### Custom Transport

[](#custom-transport)

```
use LaravelJaeger\Contracts\TransportInterface;

class KafkaTransport implements TransportInterface
{
    public function append(array $spans): void { /* buffer spans */ }
    public function flush(): void { /* publish to Kafka topic */ }
    public function close(): void { /* disconnect */ }
}
```

---

Resilience
----------

[](#resilience)

This package is designed to **never break your application**:

- All watchers and middleware wrap their logic in `try/catch` — tracing errors are silently swallowed
- UDP transport has a **circuit breaker** — stops trying after 5 consecutive failures, retries after 30s
- When `JAEGER_ENABLED=false`, a `NullTracer` is used with **zero allocations** (no performance impact)
- Spans have **hard limits** on tags (256), logs (128), and tag value length (4KB) to prevent memory issues
- Flush happens in `app()->terminating()` — after the response is sent to the client

---

License
-------

[](#license)

MIT — see [LICENSE](LICENSE).

###  Health Score

34

—

LowBetter than 75% of packages

Maintenance82

Actively maintained with recent releases

Popularity0

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity42

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

90d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/87831029?v=4)[Erfan Momeni](/maintainers/ErfanMomeniii)[@ErfanMomeniii](https://github.com/ErfanMomeniii)

---

Top Contributors

[![ErfanMomeniii](https://avatars.githubusercontent.com/u/87831029?v=4)](https://github.com/ErfanMomeniii "ErfanMomeniii (2 commits)")

---

Tags

distributed-tracingjaegerlaravelobservabilityopentracingphptracinglaravelapmtracingobservabilityjaegeropentracingdistributed-tracing

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StyleLaravel Pint

### Embed Badge

![Health badge](/badges/erfanmomeniii-laravel-jaeger-client/health.svg)

```
[![Health](https://phpackages.com/badges/erfanmomeniii-laravel-jaeger-client/health.svg)](https://phpackages.com/packages/erfanmomeniii-laravel-jaeger-client)
```

###  Alternatives

[psalm/plugin-laravel

Psalm plugin for Laravel

3345.3M347](/packages/psalm-plugin-laravel)[roots/acorn

Framework for Roots WordPress projects built with Laravel components.

9762.4M133](/packages/roots-acorn)[laravel/cashier

Laravel Cashier provides an expressive, fluent interface to Stripe's subscription billing services.

2.5k30.2M151](/packages/laravel-cashier)[laravel/scout

Laravel Scout provides a driver based solution to searching your Eloquent models.

1.7k55.0M632](/packages/laravel-scout)[laravel/pulse

Laravel Pulse is a real-time application performance monitoring tool and dashboard for your Laravel application.

1.7k15.1M136](/packages/laravel-pulse)[api-platform/laravel

API Platform support for Laravel

58174.6k17](/packages/api-platform-laravel)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
