devtime-ltd/laravel-axiom-log

Batched Monolog handler for Axiom in Laravel.

Maintainers

Package info

github.com/devtime-ltd/laravel-axiom-log

pkg:composer/devtime-ltd/laravel-axiom-log

Transparency log

Statistics

Installs: 3 443

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 2

v0.9.0 2026-07-22 17:11 UTC

This package is auto-updated.

Last update: 2026-07-22 17:11:44 UTC


README

Batched log handler for Axiom in Laravel. Buffers log records in memory and flushes them as a single POST to Axiom's ingest API at end of request (or when batch size threshold is reached).

Looking for request logging? The request-logging middleware (now RequestSensor) moved to devtime-ltd/laravel-observability-log as of v0.4.0. It is provider-agnostic and works alongside this handler, Better Stack, stderr, or any other Laravel log channel.

Installation

composer require devtime-ltd/laravel-axiom-log

Configuration

Add a log channel to your config/logging.php:

'axiom' => [
    'driver' => 'monolog',
    'level' => env('LOG_LEVEL', 'debug'),
    'handler' => \DevtimeLtd\LaravelAxiomLog\AxiomHandler::class,
    'handler_with' => [
        'apiToken' => env('AXIOM_LOG_TOKEN'),
        'dataset'  => env('AXIOM_LOG_DATASET'),
    ],
    'processors' => [PsrLogMessageProcessor::class],
],

host (default: https://api.axiom.co), batchSize (default: 50), timeout (default: 5 seconds, applied to ingest cURL calls) and shutdownTimeout (default: 2 seconds, applied when flushing during PHP shutdown so an Axiom outage cannot stall the request) can be added to handler_with if you need non-default values.

Then add axiom to your LOG_STACK, or use it directly:

Log::channel('axiom')->info('something happened', ['key' => 'value']);

Need multiple Axiom channels with different datasets? Just define more entries:

'axiom-requests' => [
    'driver' => 'monolog',
    'level' => env('LOG_LEVEL', 'debug'),
    'handler' => \DevtimeLtd\LaravelAxiomLog\AxiomHandler::class,
    'handler_with' => [
        'apiToken' => env('AXIOM_LOG_TOKEN'),
        'dataset'  => 'acme_requests_log',
    ],
    'processors' => [PsrLogMessageProcessor::class],
],
'axiom-activity' => [
    'driver' => 'monolog',
    'level' => env('LOG_LEVEL', 'debug'),
    'handler' => \DevtimeLtd\LaravelAxiomLog\AxiomHandler::class,
    'handler_with' => [
        'apiToken' => env('AXIOM_LOG_TOKEN'),
        'dataset'  => 'acme_activity_log',
    ],
    'processors' => [PsrLogMessageProcessor::class],
],

Spool transport

By default each request POSTs its log batch to Axiom synchronously, holding the PHP worker for the round-trip. The spool transport appends batches to a local NDJSON file and ships them out-of-band:

'handler_with' => [
    // ...
    'transport' => 'spool',
    'spoolPath' => storage_path('logs/axiom-spool'),
],

Run php artisan axiom-log:daemon --interval=5 alongside your web server (one daemon per container, one spoolPath per channel), or schedule one-shot axiom-log:ship passes on single-host setups (->everyFifteenSeconds()->withoutOverlapping()).

Failed sends are retried next pass, corrupt lines are skipped, and past spoolMaxBytes (default 64 MB) the oldest spool files are evicted and new batches dropped with a warning. Unshipped records are lost on container replacement (a few seconds' worth with a healthy shipper). A socket transport for Octane runtimes is tracked in #18.

When records are sent

Records are buffered and flushed in any of the following situations:

  • The buffer reaches batchSize (default 50).
  • The handler is destructed at end of a synchronous request (PHP shutdown).
  • A queue worker finishes a job (JobProcessed, JobExceptionOccurred) or stops (WorkerStopping).
  • An Octane request, task, or tick terminates (auto-detected if laravel/octane is installed).

The queue and Octane hooks are registered automatically by LaravelAxiomLogServiceProvider (auto-discovered — no manual setup needed). If you have another long-lived process boundary (custom long-running command, scheduled job, etc.) where you want to flush eagerly, call $handler->flush() directly or hook into your own event.

Testing

composer test

License

MIT