Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Slim Monolog Laravel Package

flynsarmy/slim-monolog

Monolog integration for the Slim PHP framework. Add PSR-3 logging to your Slim app with minimal setup, route messages through Monolog handlers, and get configurable, structured logging for requests, errors, and custom events.

Deep Wiki
Context7

Getting Started

This package is a single adapter class, Flynsarmy\SlimMonolog\LogWriter, that implements Slim 2's \Slim\LogWriter interface and forwards write($message, $level) to a Monolog logger. That's the whole surface area — read src/Flynsarmy/SlimMonolog/LogWriter.php first (it's ~50 lines) and you'll know everything the package does.

Install and check the constraints immediately, because they pin you to the Slim 2 / Monolog 1.x era:

composer require flynsarmy/slim-monolog
composer show monolog/monolog slim/slim   # confirm you're on 1.x / 2.x

Minimal wiring — register the writer as Slim's log writer before run():

require 'vendor/autoload.php';

$app = new \Slim\Slim([
    'log.enabled' => true,
    'log.level'   => \Slim\Log::DEBUG,
    'log.writer'  => new \Flynsarmy\SlimMonolog\LogWriter(
        __DIR__ . '/logs/app.log',
        \Monolog\Logger::DEBUG
    ),
]);

$app->get('/orders/{id}', function ($id) use ($app) {
    $app->log->info("Fetching order $id");   // -> lands in logs/app.log via Monolog
    // ...
});

$app->run();

First real use case: replace Slim's default file writer with Monolog so you get handlers (rotation, stderr, Slack, FirePHP) and so framework-generated messages (errors, 404s) go through the same pipeline as your own.

Implementation Patterns

Bootstrap-time single writer. The log.writer config key is the cleanest hook — one instance, one stream, applied globally. Alternatively, after construction:

$app->log->setWriter(new \Flynsarmy\SlimMonolog\LogWriter(__DIR__.'/logs/app.log'));

Use whichever happens first in your bootstrap; a later setWriter() silently replaces the previous one.

Rich handlers instead of the package's simple constructor. The constructor only gives you a filename and a level threshold. For anything else, build the Monolog instance yourself and hand Slim a writer:

$monolog = new \Monolog\Logger('app');
$monolog->pushHandler(new \Monolog\Handler\RotatingFileHandler(__DIR__.'/logs/app.log', 14));
$monolog->pushHandler(new \Monolog\Handler\StreamHandler('php://stderr', \Monolog\Logger::ERROR));

$app->log->setWriter(new class($monolog) implements \Slim\LogWriter {
    public function __construct(private $logger) {}
    public function write($message, $level = \Slim\Log::DEBUG) {
        $this->logger->log($this->map($level), $message);
    }
    // map \Slim\Log constants -> \Monolog\Logger constants
});

Writing that anonymous class once is usually less work than fighting the package's limitations.

Request/response logging via middleware. Slim 2 middleware wraps the route, so instrument at the edges:

class RequestLog
{
    public function call()
    {
        $app = \Slim\Slim::getInstance();
        $start = microtime(true);
        $this->next->call();
        $app->log->info(sprintf(
            '%s %s -> %d in %.1fms',
            $app->request->getMethod(),
            $app->request->getResourceUri(),
            $app->response->getStatus(),
            (microtime(true) - $start) * 1000
        ));
    }
}
$app->add(new RequestLog());

Hooks for lifecycle breadcrumbs. slim.before, slim.before.router, slim.before.dispatch, slim.after.router are cheap places to emit debug lines without touching route code.

Error handling. Wire Slim's error handler so exceptions get logged with context:

$app->error(function (\Exception $e) use ($app) {
    $app->log->error(get_class($e).': '.$e->getMessage()."\n".$e->getTraceAsString());
    $app->response->setStatus(500);
    echo 'Internal error';
});

Testing. Swap in Monolog\Handler\TestHandler and assert on records — this is the best argument for constructing Monolog yourself rather than trusting the constructor's defaults:

$this->assertTrue($handler->hasErrorThatContains('SQLSTATE'));

Gotchas and Tips

  • Slim 2 only. \Slim\LogWriter no longer exists in Slim 3/4; those use a PSR-3 logger in the container. Do not attempt to install this into a modern Slim app — you'll get a class-not-found at runtime, not at install time.
  • Unmaintained since 2015. The package's monolog/monolog constraint will block a Monolog 2/3 upgrade. Treat it as a 20-line dependency you may need to inline and own; that's the realistic long-term move.
  • Two different level scales. \Slim\Log::DEBUG and \Monolog\Logger::DEBUG are numerically different; the adapter translates. Always use the fluent methods ($app->log->info($msg)) rather than passing raw integers, and use \Monolog\Logger::* constants only when constructing the writer.
  • No context array. Coming from Laravel's Log::info($msg, $context), this hurts: write() takes a message string only. Interpolate, or bypass Slim and call the Monolog instance directly when you need structured context.
  • Path is a file, not a directory. Monolog's StreamHandler throws UnexpectedValueException if the parent directory is missing or unwritable. Pre-create logs/ and set permissions in your deploy script; a silent-looking logger is often just a discarded write to an unwritable stream.
  • log.enabled defaults off in some setups. If nothing appears, check log.enabled, then log.level (anything above your threshold is dropped), then whether an exception handler is swallowing before the log line.
  • No rotation, no channel name, no buffering. The constructor gives you neither RotatingFileHandler nor a custom channel — long-running or high-traffic apps will produce one unbounded file.
  • Ordering matters. Set the writer after new \Slim\Slim() but before $app->run(); writers set inside a route or late hook may miss earlier framework messages.
  • Avoid dev handlers in production. FirePHPHandler / ChromePHPHandler add per-request overhead and leak internal detail; gate them on $app->config('debug').
  • Escape hatch. LogWriter is small and unprotected — extending it and overriding write() is a legitimate way to add context, channeling, or redaction without forking the package.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle
glavweb/extra-bundle
glavweb/api-bundle
glavweb/admin-bundle
adachsoft/api-version-bundle
elsayed85/laravel-api-exceptions
ouhssini/laravel-demo-mode
daworks/ncloud-outbound-mailer-driver
gp247/cms
ignibyte/aic-gates
nexa-merchant/blog
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
cgv/localized-resource