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

Logger Laravel Package

zhamao/logger

zhamao/logger is a lightweight logging library for PHP applications, offering configurable log levels, file and console output, and simple integration with Zhamao-based projects. Use it to write, format, and manage application logs with minimal setup.

View on GitHub
Deep Wiki
Context7

Getting Started

zhamao/logger is a standalone, PSR-3 console logger aimed at long-running CLI processes (the kind of thing you'd run under Swoole in the Zhamao robot framework), not an HTTP-side logging library. Treat it as a replacement for echo/dump()/Symfony Console styling in commands and workers, not as a replacement for Laravel's Log facade.

Minimal setup:

composer require zhamao/logger

There is no service provider and no extra.laravel auto-discovery — the package is framework-agnostic. So the first thing to do is open src/ and read the Logger class constructor. You're looking for:

  1. The constructor signature (does it take a minimum level, a resource, a format string?).
  2. Whether it implements Psr\Log\LoggerInterface (if it does, everything below gets easier).
  3. How it writes output — fwrite(STDOUT, ...), echo, or a stream you can inject.

First use case, and the one that justifies the dependency: an artisan command that currently spams $this->info() / $this->line() calls.

use Zhamao\Logger\Logger;

class SyncFeedCommand extends Command
{
    protected $signature = 'feed:sync {--v=0}';

    public function handle(): int
    {
        $logger = new Logger(/* min level from --v */);
        $logger->info('Starting feed sync', ['source' => 'crm']);

        try {
            // ...
            $logger->notice('Sync completed', ['rows' => $count]);
            return self::SUCCESS;
        } catch (\Throwable $e) {
            $logger->error('Sync failed: {message}', ['message' => $e->getMessage(), 'exception' => $e]);
            return self::FAILURE;
        }
    }
}

If it's not PSR-3 compliant, wrap it in a five-line adapter class before you use it anywhere else — you'll want that seam later.

Pin the dependency ("zhamao/logger": "1.1.9" or ^1.1.9) and read the changelog before bumping; see the risk notes below.

Implementation Patterns

Wrap it behind an interface, always. The whole value of this package is presentation (colour, level filtering, timestamps). Consumption sites should only ever type-hint Psr\Log\LoggerInterface. That way a future swap to Monolog costs you nothing.

$this->app->singleton(LoggerInterface::class, fn () => new Logger(...));

Register it as a custom Laravel log channel if you want Log::channel('cli')->info(...) for consistency with the rest of the app. You'll write a tiny driver that implements Illuminate\Log\Logger's expectations or simply extends Monolog's AbstractProcessingHandler and delegates to the zhamao logger. For most teams the cheaper route is: don't touch the channel config, inject the logger directly into CLI classes and leave Log alone for HTTP.

Map verbosity to levels. Console apps live and die by -v/-vv/-vvv. Resolve the option once in handle()/boot() and hand the resulting minimum level to the logger constructor. Don't sprinkle if ($this->option('verbose')) guards through the codebase.

Use structured context, not string concatenation. Pass arrays and use {placeholder} interpolation where supported. $logger->info('Job dispatched', ['id' => $id, 'queue' => $q]) survives a switch to JSON output; "Job $id dispatched to $q" does not.

Test against Psr\Log\NullLogger. Because you're injecting LoggerInterface, feature tests of commands need no special handling — bind NullLogger::class in the test container and assert on outcomes, not on printed text. If you do need to assert on output, back the logger with php://memory rather than capturing real STDOUT.

Long-running workers: instantiate one logger per process, not per job. Keep a monotonically increasing request/job ID in the context so interleaved lines remain traceable.

Since 1.1.9, writes are no longer @-suppressed. The library now lets PHP surface failures from echo/fwrite/fflush. That is the correct behaviour, but it means a closed or broken output stream (artisan ... | head -n 20, a rotated/short-lived log fifo, a supervisor that closed the pipe) can now produce fwrite(): Write of N bytes failed / broken-pipe warnings in your output or error handler instead of failing silently. If you run commands in pipes, either tolerate the warning at the end of the run or wrap your top-level handle() so a failed final flush doesn't turn a successful command into a non-zero exit. Test your command under | head -1 once after upgrading — it's a two-minute check that catches this.

Gotchas and Tips

  • Risk profile. One star, zero dependents, effectively a single-maintainer utility extracted from a larger framework. Pin the version in composer.json, and verify the release cadence against your PHP version before adopting. The PSR-3 wrapper discipline above is your insurance policy.
  • Error suppression was removed in 1.1.9. Anything that relied on the old silent-on-failure behaviour (piping to head, writing to a closed stream in a dying worker, disk-full on a redirected STDOUT) now emits PHP warnings from fwrite/fflush. If you have a custom set_error_handler, make sure it doesn't convert these E_WARNINGs into exceptions that kill a worker mid-job. Check the release diff (zhamao-robot/zhamao-logger PR #10) if you were on 1.1.8 or earlier.
  • Not for HTTP requests. Anything written to STDOUT during a web request ends up in the response body or the FPM log, not storage/logs. Keep it in artisan commands, queue workers, and standalone scripts.
  • ANSI escape codes leak. Coloured output is great in a TTY and disastrous in CI logs, | tee, or a supervisor-managed logfile. Check posix_isatty(STDOUT) (or stream_isatty) at boot and disable colour when it returns false. Many CLI loggers expose a setColor(false) or accept it in the constructor — find it early, because retrofitting it after your deployment pipeline is full of ^[[32m is unpleasant.
  • Swoole / coroutine interleaving. If you run this under Swoole with concurrent coroutines, writes to STDOUT can interleave mid-line. Either serialise writes through the logger's own lock or ensure each log call is a single fwrite of a fully-formed string. Note that with suppression removed, a partially-failed write is now visible — which is useful for diagnosing interleaving, but noisier.
  • Static state and singletons. The upstream framework uses a static logger accessor in places. If you hit a static Logger::getInstance(), be aware of it in tests — state persists across test methods and level changes bleed between them. Prefer constructor injection and reset any static handle in tearDown.
  • Don't double-log. If you wire it into Laravel's logging stack and also call it directly, the same message can land in both storage/logs/laravel.log and your console. Pick one path per environment: console logger in CLI, Monolog everywhere else.
  • Extension point to look for: Psr\Log\AbstractLogger inheritance or an overridable format()/write() method. That's where you add JSON lines for log shippers, or strip timestamps when your process supervisor already adds them. If you override write(), preserve the new un-suppressed error behaviour rather than reintroducing @.
  • Verify the level names. Some small loggers support non-standard levels (success, debug with custom weights). A quick grep through the source beats guessing, and a wrong level passed to a strict PSR-3 implementation throws InvalidArgumentException at runtime rather than silently downgrading.
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.
abbasudo/artisan-route
mirvan/ippanel
ignibyte/aic-framework
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
adachsoft/api-version-bundle
cgv/localized-resource
noith/settings
kda/laravel-package