Ingesting Logs from PHP

Send log entries to BunnyLogs from any PHP application using a custom log handler — no dependencies required beyond a standard PHP install.

How it works

BunnyLogs accepts log entries as an HTTP POST to your logspace endpoint. PHP's built-in stream_context_create + file_get_contents is all you need, or you can use Monolog — the de-facto standard logging library for PHP — to drop in a handler with almost no code.

Option 1 — Standalone (no dependencies)

Copy this helper into your project. It uses only PHP core functions and works on any host that allows outbound HTTPS.

<?php

function bunnylog(string $message, string $level = 'INFO', string $program = 'php'): void
{
    $uuid    = '<uuid>';   // replace with your logspace UUID
    $url     = "https://bunnylogs.com/live/{$uuid}";
    $payload = http_build_query([
        'message' => $message,
        'level'   => $level,
        'program' => $program,
    ]);

    $ctx = stream_context_create([
        'http' => [
            'method'        => 'POST',
            'header'        => "Content-Type: application/x-www-form-urlencoded\r\n",
            'content'       => $payload,
            'timeout'       => 3,
            'ignore_errors' => true,
        ],
    ]);

    @file_get_contents($url, false, $ctx);   // fire-and-forget; suppress errors
}

// Usage:
bunnylog('User signed up', 'INFO', 'auth');
bunnylog('Stripe webhook failed', 'ERROR', 'payments');
Option 2 — Monolog handler

If your project already uses Monolog (e.g. Laravel, Symfony, or a standalone install), add this handler class and wire it up in a few lines.

Install Monolog (skip if already present):

composer require monolog/monolog

BunnyLogsHandler.php

<?php

use Monolog\Handler\AbstractProcessingHandler;
use Monolog\Level;
use Monolog\LogRecord;

class BunnyLogsHandler extends AbstractProcessingHandler
{
    private string $url;

    public function __construct(string $uuid, int|string|Level $level = Level::Debug, bool $bubble = true)
    {
        parent::__construct($level, $bubble);
        $this->url = "https://bunnylogs.com/live/{$uuid}";
    }

    protected function write(LogRecord $record): void
    {
        $levelMap = [
            'DEBUG'     => 'DEBUG',
            'INFO'      => 'INFO',
            'NOTICE'    => 'INFO',
            'WARNING'   => 'WARNING',
            'ERROR'     => 'ERROR',
            'CRITICAL'  => 'ERROR',
            'ALERT'     => 'ERROR',
            'EMERGENCY' => 'ERROR',
        ];

        $payload = http_build_query([
            'message' => $record->message,
            'level'   => $levelMap[$record->level->getName()] ?? 'INFO',
            'program' => $record->channel,
        ]);

        $ctx = stream_context_create([
            'http' => [
                'method'        => 'POST',
                'header'        => "Content-Type: application/x-www-form-urlencoded\r\n",
                'content'       => $payload,
                'timeout'       => 3,
                'ignore_errors' => true,
            ],
        ]);

        @file_get_contents($this->url, false, $ctx);
    }
}

Wire it up:

<?php

require 'vendor/autoload.php';
require 'BunnyLogsHandler.php';

use Monolog\Logger;

$log = new Logger('myapp');
$log->pushHandler(new BunnyLogsHandler('<uuid>'));

$log->info('Application started');
$log->warning('Disk space low', ['free_gb' => 1.2]);
$log->error('Database connection failed');
Laravel

In Laravel, place BunnyLogsHandler.php in app/Logging/ and add a custom channel to config/logging.php:

'bunnylogs' => [
    'driver' => 'monolog',
    'handler' => App\Logging\BunnyLogsHandler::class,
    'with' => [
        'uuid' => env('BUNNYLOGS_UUID'),
    ],
    'level' => env('LOG_LEVEL', 'warning'),
],

Then set LOG_CHANNEL=bunnylogs (or add it to a stack channel) in .env.

Symfony

Register the handler as a service in config/services.yaml:

App\Logging\BunnyLogsHandler:
    arguments:
        $uuid: '%env(BUNNYLOGS_UUID)%'

Then reference it in config/packages/monolog.yaml:

monolog:
    handlers:
        bunnylogs:
            type: service
            id: App\Logging\BunnyLogsHandler
            level: warning
WordPress

Add the standalone helper to your theme's functions.php or a must-use plugin, then log anywhere in WordPress:

add_action('wp_login_failed', function (string $username) {
    bunnylog("Failed login for {$username}", 'WARNING', 'wordpress');
});

add_action('upgrader_process_complete', function () {
    bunnylog('Plugin/theme update completed', 'INFO', 'wordpress');
});
Tips
  • Store the UUID in an environment variable (BUNNYLOGS_UUID) rather than hard-coding it.
  • The timeout of 3 seconds prevents a slow BunnyLogs network call from blocking your users. For high-traffic sites, consider dispatching the HTTP call in a background job or queue.
  • Use the program field to distinguish between subsystems — e.g. auth, payments, cron — so you can filter by service in the BunnyLogs dashboard.
  • Monolog's channel name is used automatically as the program field by the handler above, so each new Logger('name') shows up as a distinct source.