Integration of Monolog for Nette Framework.
Install package using composer.
composer require contributte/monologRegister prepared compiler extension in your config.neon file.
extensions:
monolog: Contributte\Monolog\DI\MonologExtensionNote
This is just a Nette integration, see also Monolog documentation for more information about handlers, processors and formatters.
You can configure multiple logging channels. The default channel is required and is the only one that is autowired.
monolog:
channel:
default:
handlers:
- Monolog\Handler\StreamHandler(%appDir%/../log/app.log)
api:
handlers:
- Monolog\Handler\StreamHandler(%appDir%/../log/api.log)Handlers are responsible for writing log records to various destinations. You can use any Monolog handler.
monolog:
channel:
default:
handlers:
# Inline handler definition
- Monolog\Handler\StreamHandler(%appDir%/../log/app.log, Monolog\Logger::WARNING)
- Monolog\Handler\RotatingFileHandler(%appDir%/../log/app.log, 30, Monolog\Logger::DEBUG)
# Reference to existing service
- @myCustomHandlerProcessors allow you to add extra data to log records.
monolog:
channel:
default:
handlers:
- Monolog\Handler\StreamHandler(%appDir%/../log/app.log)
processors:
- Monolog\Processor\MemoryPeakUsageProcessor()
- Monolog\Processor\WebProcessor()
- Monolog\Processor\IntrospectionProcessor()Monolog integrates with Tracy debugger. By default, logs are bridged in both directions.
monolog:
hook:
fromTracy: true # enabled by default, log Tracy messages to Monolog
toTracy: true # enabled by default, log Monolog messages to TracyTip
For remote storage of Tracy bluescreens, consider using mangoweb-backend/monolog-tracy-handler.
Inject the logger using constructor injection or inject* method. Only the default channel is autowired.
use Psr\Log\LoggerInterface;
class OrderService
{
public function __construct(
private LoggerInterface $logger,
)
{
}
public function process(): void
{
$this->logger->info('Processing order');
$this->logger->error('Order failed', ['orderId' => 123]);
}
}Use LoggerManager when you need to access multiple channels.
monolog:
manager:
enabled: true # disabled by defaultuse Contributte\Monolog\LoggerManager;
class ReportService
{
public function __construct(
private LoggerManager $loggerManager,
)
{
}
public function generate(): void
{
$this->loggerManager->get('default')->info('Generating report');
$this->loggerManager->get('api')->info('Fetching data from API');
}
}LoggerHolder provides static access to the default logger when DI container is not available.
monolog:
holder:
enabled: true # disabled by defaultuse Contributte\Monolog\LoggerHolder;
class LegacyCode
{
public function process(): void
{
LoggerHolder::getInstance()->getLogger()->info('Processing');
}
}Warning
LoggerHolder should only be used in legacy code or situations where dependency injection is not possible.
monolog:
channel:
default:
handlers:
- Monolog\Handler\RotatingFileHandler(%appDir%/../log/app.log, 14, Monolog\Logger::DEBUG)
- Monolog\Handler\StreamHandler(php://stderr, Monolog\Logger::ERROR)
processors:
- Monolog\Processor\MemoryPeakUsageProcessor()
- Monolog\Processor\WebProcessor()
email:
handlers:
- Monolog\Handler\StreamHandler(%appDir%/../log/email.log)
hook:
fromTracy: true
toTracy: true
manager:
enabled: true
holder:
enabled: falseservices:
slackHandler:
factory: Monolog\Handler\SlackWebhookHandler(
%slack.webhookUrl%,
%slack.channel%,
%slack.username%
)
monolog:
channel:
default:
handlers:
- Monolog\Handler\StreamHandler(%appDir%/../log/app.log)
- @slackHandlerTip
Take a look at real Contributte Monolog configuration example at contributte/webapp-skeleton.