league/tactician or Laravel’s native Artisan/Bus systems). It extends Tactician’s middleware pipeline, making it ideal for CQRS, event sourcing, or workflow-heavy applications where command logging is critical for debugging, auditing, or observability.monolog/monolog, react/promise-stream).AppServiceProvider or bind() methods, aligning with Laravel’s DI principles.Log::channel() system, enabling route-specific logging (e.g., stack, single, daily).CommandBus (if used) or Laravel’s Bus facade.CommandMetadata interface.| Risk Area | Mitigation Strategy |
|---|---|
| Performance Overhead | Logs only at INFO/DEBUG levels; configurable via PSR-3 logger. Use async logging (e.g., monolog/handler-async) for high-throughput systems. |
| Log Bloat | Filter sensitive data (e.g., passwords) using Tactician’s CommandNormalizer or Laravel’s Log::shouldLog() guards. |
| Middleware Order | Ensure logger middleware is first in the pipeline to capture raw command input. Tactician’s Middleware::first() can enforce this. |
| Laravel Version | Tested with Laravel 10+ (PHP 8.1+). Backward compatibility with older versions may require shims (e.g., for Bus facade). |
| Custom Command Buses | If using non-Tactician buses (e.g., Laravel\Bus\QueueingDispatcher), wrap the bus in Tactician’s CommandBus for compatibility. |
UserCreatedCommand with payload but exclude PasswordResetCommand for security.single channel, or route to external systems (e.g., ELK, Datadog) via Log::build()?CommandMetadata or Laravel’s Log::withContext().Bus + Log::info() or Spatie’s Laravel Activity Log for simpler cases.MonologBundle), but loses Laravel-specific conveniences (e.g., channels, stack traces).Log::debug('Command executed') in handlers). Identify gaps (e.g., missing payloads, no timing).composer require league/tactician-logger
Register the logger middleware in AppServiceProvider:
use League\Tactician\Logger\CommandLoggerMiddleware;
use League\Tactician\Logger\Handler\CommandLoggerHandler;
use Psr\Log\LoggerInterface;
public function register()
{
$this->app->bind(CommandLoggerMiddleware::class, function ($app) {
return new CommandLoggerMiddleware(
new CommandLoggerHandler($app->make(LoggerInterface::class))
);
});
}
$bus = new CommandBus([
new CommandLoggerMiddleware($logger),
// ... other middleware
]);
CommandBus or use a custom middleware to log before/after execution.CommandLoggerHandler to filter sensitive data or add context:
$handler = new CommandLoggerHandler($logger, [
'exclude_commands' => ['PasswordResetCommand'],
'include_context' => ['user_id', 'request_id']
]);
| Component | Compatibility Notes |
|---|---|
| Laravel 10+ | Full support (PHP 8.1+). Use Bus facade or Tactician’s CommandBus. |
| Laravel <10 | May require shims for Bus facade or Tactician v2.x. |
| Monolog 3.x | Required for PSR-3 compliance. Laravel includes this by default. |
| Custom Command Buses | Requires wrapping in Tactician’s bus or implementing Tactician\CommandBusInterface. |
| Queue Workers | Logs appear in Laravel’s queue worker logs (e.g., php artisan queue:work --once). |
SendEmailCommand) to validate format and performance.ERROR, CRITICAL) for failed commands and integrate with Laravel’s error reporting.league/tactician-logger and PSR-3 logger (already in Laravel).config/logging.php or environment variables (e.g., LOG_LEVEL=debug).Log::extend() to dynamically switch log handlers.dd()/Log::debug() in handlers. Logs include command payloads, timestamps, and middleware context.INFO for production, DEBUG for local).{
"level": "info",
"command": "App\\Commands\\CreateUserCommand",
"payload": {"name": "John", "email": "john@example.com"},
"handler": "App\\Handlers\\CreateUserHandler",
"duration_ms": 42,
"context": {"user_id": 123, "request_id": "abc123"}
}
monolog/handler-async to avoid blocking command execution.CommandLoggerHandler.How can I help you explore Laravel packages today?