When Laravel runs as a long-lived process — such as with Laravel Octane, Laravel Horizon, or a standard queue worker — a single process handles many requests or jobs over its lifetime.
By default, telemetry exports are batched and flushed either periodically or when the process shuts down. Worker mode configuration lets you tune this behavior to match your runtime.
How it works
The package automatically detects whether it is running inside a worker process using a list of detectors. When a detector matches, the package hooks into the worker’s iteration lifecycle to flush telemetry at the right time.
Two detectors are built in:
| Detector | Detected when |
|---|
OctaneWorkerModeDetector | $_SERVER['LARAVEL_OCTANE'] is 1 or true |
QueueWorkerModeDetector | Running queue:work or horizon:work |
Detectors are checked in the order they appear in the detectors array. The first one that returns true activates worker mode.
Flush behavior
Periodic flushing (default)
By default, telemetry is batched and flushed on a timer (metrics_collect_interval) or when the process shuts down. This minimizes overhead per iteration.
Per-iteration flushing
Set flush_after_each_iteration to true to flush all pending telemetry at the end of every request or job. This guarantees data is exported promptly but adds a small amount of I/O per iteration.
OTEL_WORKER_MODE_FLUSH_AFTER_EACH_ITERATION=true
When flush_after_each_iteration is true, the metrics_collect_interval setting is ignored. Per-iteration flushing takes precedence over the periodic collection timer.
Environment variables
| Variable | Description | Default |
|---|
OTEL_WORKER_MODE_FLUSH_AFTER_EACH_ITERATION | Flush telemetry after each request or job | false |
OTEL_WORKER_MODE_COLLECT_INTERVAL | Metrics collection interval in seconds (ignored when per-iteration flushing is enabled) | 60 |
Configuration
The full worker_mode config block in config/opentelemetry.php:
'worker_mode' => [
/*
* Flush after each iteration (e.g. HTTP request, queue job).
* If false, flushes are batched and executed periodically and on shutdown.
*/
'flush_after_each_iteration' => env('OTEL_WORKER_MODE_FLUSH_AFTER_EACH_ITERATION', false),
/*
* Metrics collection interval in seconds.
* Ignored when flush_after_each_iteration is true.
*/
'metrics_collect_interval' => (int) env('OTEL_WORKER_MODE_COLLECT_INTERVAL', 60),
/*
* Detectors checked in order. The first match activates worker mode.
*/
'detectors' => [
WorkerMode\Detectors\OctaneWorkerModeDetector::class,
WorkerMode\Detectors\QueueWorkerModeDetector::class,
],
],
Custom detectors
If you run Laravel in a non-standard long-lived process, you can write a custom detector by implementing WorkerModeDetectorInterface:
use Closure;
use Keepsuit\LaravelOpenTelemetry\WorkerMode\WorkerModeDetectorInterface;
class MyWorkerModeDetector implements WorkerModeDetectorInterface
{
public function detect(): bool
{
// Return true when your worker runtime is active
return isset($_SERVER['MY_WORKER_RUNTIME']);
}
public function onIterationEnded(Closure $callback): void
{
// Register the callback to fire at the end of each iteration
app('events')->listen(MyIterationEndedEvent::class, $callback);
}
}
Then add your detector to the detectors array in config/opentelemetry.php:
'detectors' => [
MyWorkerModeDetector::class,
WorkerMode\Detectors\OctaneWorkerModeDetector::class,
WorkerMode\Detectors\QueueWorkerModeDetector::class,
],
Detectors are checked in order, so place more specific detectors before general ones.
Manual flush
You can also flush all pending telemetry manually at any point using the OpenTelemetry facade:
use Keepsuit\LaravelOpenTelemetry\Facades\OpenTelemetry;
OpenTelemetry::flush();
This forces all traces, metrics, and logs to be exported immediately, regardless of the configured flush strategy.