brackets/advanced-logger
Advanced Logger for Laravel adds flexible, configurable logging channels with richer context and customizable formatters, making it easier to capture, structure, and inspect application events and errors across environments while integrating cleanly with Laravel’s logging stack.
1. Install and inspect before you integrate.
composer require brackets/advanced-logger
Because this package has one star and zero dependents, do not assume the README is accurate for your Laravel version. The fastest path to understanding it:
# 1. What service provider does it register?
cat vendor/brackets/advanced-logger/composer.json
# 2. Does it auto-discover, and what does it bind?
cat vendor/brackets/advanced-logger/src/*ServiceProvider.php
# 3. Is there a config to publish?
php artisan vendor:publish --provider="Brackets\\AdvancedLogger\\AdvancedLoggerServiceProvider"
2. Look at the config file first, not the docs. For a package named "advanced logger," the config will tell you what it actually adds — almost certainly one or more of: a custom Monolog channel, automatic request/user context injection, a database log driver, or a facade wrapping Log with extra context arguments. The config keys map directly to which of those features are enabled.
3. Verify the channel is wired. Confirm your config/logging.php has (or you add) a channel pointing at the package's driver, and that your default stack includes it:
'channels' => [
'stack' => [
'driver' => 'stack',
'channels' => ['single', 'advanced'],
],
'advanced' => [
'driver' => 'advanced', // verify exact driver name in the package's ServiceProvider
// ...options from config/advanced-logger.php
],
],
4. First use case: enrich an existing log line. Before adopting anything wholesale, take one existing Log::info('Order placed') call and route it through the package so you can see what extra context it attaches (request ID, user ID, trace, caller). If the output is not visibly better than your current Log::info($msg, $context), stop here — Laravel's native context feature already covers most of this.
5. Sanity-check with a throwaway route that logs at every level and dumps to storage/logs/laravel.log. Confirm the formatter output is what you expect (JSON vs line, extra fields present, timestamps correct) before rolling it out.
Treat it as a context-enrichment layer, not a logging replacement. The value is in automatic context, so the pattern is:
Log::* calls.Log::info('Payment captured', [
'order_id' => $order->id,
'gateway' => 'stripe',
'amount' => $order->total,
]);
Request-scoped context via middleware. If the package ships middleware, register it in the web (and api) group so every request gets correlation data. If it does not ship one, add your own and push into Laravel's shared context — don't fight the package:
// app/Http/Middleware/LogContext.php
public function handle($request, Closure $next)
{
Log::withContext([
'request_id' => (string) Str::uuid(),
'user_id' => optional($request->user())->id,
'route' => $request->route()?->getName(),
]);
return $next($request);
}
Exception handler integration. In bootstrap/app.php (Laravel 11+) or app/Exceptions/Handler.php, log through the package's configured channel so uncaught exceptions get the same context as normal logs. Don't let two different log formats coexist — it defeats the purpose of structured logs.
Queue jobs need explicit propagation. Context set during an HTTP request does not survive into a queued job. The reliable pattern is to capture the request ID at dispatch time and re-establish it in handle():
class ProcessOrder implements ShouldQueue
{
public function __construct(public int $orderId, public string $requestId) {}
public function handle(): void
{
Log::withContext(['request_id' => $this->requestId, 'job' => self::class]);
// ...
}
}
Testing. Use Log::spy() and assert the message; only assert on context keys you control, since package-injected keys may change between versions. If the package writes to the database, use RefreshDatabase and assert on the table rather than parsing formatted strings.
Channel segregation. Configure a separate channel for this package and route only high-value events (payments, auth, integrations) to a persistent/queryable sink, while keeping debug noise on the default single/daily channel. Advanced logging is only worth it if the volume stays queryable.
Bus-factor risk is the headline concern. One star, zero dependents, last release October 2023. That predates Laravel 11's application skeleton rewrite and the bootstrap/app.php exception-handling changes. Test against your actual Laravel version before committing; expect to either pin an older framework or patch the service provider yourself. Fork it into your VCS and require it via a path/vcs repository rather than depending on Packagist availability.
"Advanced" often means "opinionated." Packages like this frequently swap the Monolog formatter or add a custom Handler. If log output suddenly changes shape (line → JSON, or extra prefixes), check config/logging.php and the package's channel definition first, not your application code. Any log-parsing pipeline (Datadog, Papertrail, Splunk) downstream will need its parser updated.
Context leaks under Octane / long-running workers. Static context registries are the classic bug. If the package stores context in a singleton or static property, context from request A will appear in request B's logs. Verify by logging from two consecutive requests with different users; if user IDs cross over, wrap the package's reset in a terminating middleware or Octane::tick().
Serialization failures. Context arrays get JSON-encoded. Objects with circular references, closures, or Eloquent models with lazy-loaded relations will either throw or silently log {}. Always pass scalars or arrays — $model->toArray() or just ->id, never $model.
Log volume and cost. Automatic context makes each line larger and encourages verbose logging. If it writes to a database table, add an index on created_at and level immediately, and set up a retention/prune command. A naive DB log driver will happily fill a disk.
Debugging checklist when logs don't appear:
php artisan config:clear — published config is cached in production.php artisan about / dump config('logging.default') and config('logging.channels').bootstrap/providers.php (Laravel 11+) or config/app.php if discovery is disabled.storage/logs permissions if the custom handler writes files.single to isolate whether the problem is the package or your app.Extension points to look for (in rough order of usefulness): a context-provider/pipeline interface you can implement to inject tenant or trace IDs; a custom formatter class you can swap in config; a Handler you can decorate. If none of these are cleanly exposed, prefer wrapping the package behind your own thin App\Support\Logger service — that way replacing it later is a one-file change instead of a codebase-wide find-and-replace.
Escape hatch. If you spend more than an afternoon fighting version compatibility, the native equivalents cover most of it: Log::withContext(), ContextProcessor in Monolog, a custom formatter, and a LogstashFormatter for JSON output. Given the package's maturity signals, document the decision either way so the next developer knows why it's there.
How can I help you explore Laravel packages today?