PHP

Send logs from PHP apps using cURL or Guzzle, with a PSR-3 compatible logger.

Quick start — cURL

No Composer packages needed:

php
<?php

define('LOGFLOW_API_KEY', getenv('LOGFLOW_API_KEY'));

function logflow(string $level, string $message, string $service = 'app', array $attributes = []): void
{
    $ch = curl_init('https://api.getlogflow.com/v1/logs');
    curl_setopt_array($ch, [
        CURLOPT_POST           => true,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_TIMEOUT        => 3,
        CURLOPT_HTTPHEADER     => [
            'Authorization: Bearer ' . LOGFLOW_API_KEY,
            'Content-Type: application/json',
        ],
        CURLOPT_POSTFIELDS => json_encode([
            'level'      => $level,
            'message'    => $message,
            'service'    => $service,
            'attributes' => $attributes,
        ]),
    ]);
    curl_exec($ch);
    curl_close($ch);
}

logflow('info', 'Server started', 'api', ['php_version' => PHP_VERSION]);
logflow('error', 'DB connection failed', 'api', ['host' => 'db-1']);

PSR-3 compatible logger

Implement Psr\Log\LoggerInterface for drop-in compatibility with Laravel, Symfony, and any PSR-3 aware package:

php
<?php

use PsrLogAbstractLogger;
use PsrLogLogLevel;
use Stringable;

class LogFlowLogger extends AbstractLogger
{
    private const LEVEL_MAP = [
        LogLevel::DEBUG     => 'debug',
        LogLevel::INFO      => 'info',
        LogLevel::NOTICE    => 'info',
        LogLevel::WARNING   => 'warn',
        LogLevel::ERROR     => 'error',
        LogLevel::CRITICAL  => 'error',
        LogLevel::ALERT     => 'fatal',
        LogLevel::EMERGENCY => 'fatal',
    ];

    public function __construct(
        private string $apiKey,
        private string $service = 'app',
    ) {}

    public function log($level, string|Stringable $message, array $context = []): void
    {
        $ch = curl_init('https://api.getlogflow.com/v1/logs');
        curl_setopt_array($ch, [
            CURLOPT_POST           => true,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_TIMEOUT        => 3,
            CURLOPT_HTTPHEADER     => [
                'Authorization: Bearer ' . $this->apiKey,
                'Content-Type: application/json',
            ],
            CURLOPT_POSTFIELDS => json_encode([
                'level'      => self::LEVEL_MAP[$level] ?? 'info',
                'message'    => (string) $message,
                'service'    => $this->service,
                'attributes' => $context,
            ]),
        ]);
        curl_exec($ch);
        curl_close($ch);
    }
}

// Usage
$logger = new LogFlowLogger(apiKey: getenv('LOGFLOW_API_KEY'), service: 'api');
$logger->info('User signed up', ['user_id' => 'u_123', 'plan' => 'growth']);
$logger->error('Payment failed', ['order_id' => 'ord_456', 'gateway' => 'stripe']);

Laravel integration

Register LogFlow as a custom logging channel in config/logging.php:

php
// config/logging.php
'channels' => [
    'logflow' => [
        'driver' => 'custom',
        'via'    => AppLoggingLogFlowLogger::class,
    ],
    'stack' => [
        'driver'   => 'stack',
        'channels' => ['single', 'logflow'], // log to both file and LogFlow
    ],
],

// app/Logging/LogFlowLogger.php
namespace AppLogging;

class LogFlowLogger
{
    public function __invoke(array $config): PsrLogLoggerInterface
    {
        return new LogFlowLogger(
            apiKey: env('LOGFLOW_API_KEY'),
            service: config('app.name'),
        );
    }
}
💡
Set LOG_CHANNEL=logflow in your .env to route all Laravel logs to LogFlow.

Batch sending

php
<?php

function logflow_batch(array $logs): void
{
    $ch = curl_init('https://api.getlogflow.com/v1/logs/batch');
    curl_setopt_array($ch, [
        CURLOPT_POST           => true,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_TIMEOUT        => 5,
        CURLOPT_HTTPHEADER     => [
            'Authorization: Bearer ' . LOGFLOW_API_KEY,
            'Content-Type: application/json',
        ],
        CURLOPT_POSTFIELDS => json_encode(['logs' => $logs]),
    ]);
    curl_exec($ch);
    curl_close($ch);
}

// Buffer logs during a request, flush at the end
$buffer = [];
$buffer[] = ['level' => 'info', 'message' => 'Request started', 'service' => 'api'];
$buffer[] = ['level' => 'info', 'message' => 'DB query ok', 'service' => 'api'];
logflow_batch($buffer);