I'm facing some problems with configuring Monolog to handle "nested loggers".
What I want to do:
Log from services to dedicated files (one per service) AND from all services to one file. Each logger should be also handled by monolog.handlers.console
.
Why I want to do
Each service has logic, but can use other services from DI. I want to know what exactly one service logs, so I want dedicated logger (with custom channel and custom log file) for each service. But when services relies on other services, I want to read logs in chronological order in one file.
What I have
app/config.yml
:
monolog:
handlers:
my_handler:
type: stream
path: %kernel.logs_dir%/%kernel.environment%.my.log
level: info
handler: my_bundle_handler
src/My/Bundle/Resources/config/config.yml
services:
# LOGGERS
my_logger:
class: Symfony\Bridge\Monolog\Logger
arguments: [my_logger]
calls:
- [pushHandler, [@monolog.handler.console]]
- [pushHandler, [@my_bundle_handler]]
tags:
- { name: monolog.logger, channel: my_channel}
# HANDLERS
my_bundle_handler:
abstract: true # Without it it will throw exception
type: group
members: [my_service_handler]
channels: ["my_channel"]
tags:
- { name: log_handler }
my_service_handler:
class: Monolog\Handler\StreamHandler
arguments: [%kernel.logs_dir%/%kernel.environment%.my_service.log, 100]
channels: ["my_channel"]
tags:
- { name: log_handler }
It does not work as expected. It logs to my_service.log
, but not to my.log
.
Is there possibility to achieve what I want?
Channels in monolog works exactly like you want. Sample monolog configuration
app/config.yml
monolog:
channels: ['deletion']
handlers:
main:
type: fingers_crossed
action_level: error
handler: grouped_main
formatter: "monolog.formatter.request"
buffer_size: 30
# if you will set stop_buffering: true - you will get ALL events after first error. It could produce huge logs for console
stop_buffering: false
# this is for getsentry.com error catching
sentry:
type: raven
dsn: '%sentry_url%'
level: notice
# Groups
grouped_main:
type: group
members: [sentry, streamed_main, streamed_main_brief]
# Streams
streamed_main:
type: stream
path: "%kernel.logs_dir%/%kernel.environment%.log"
streamed_main_brief:
type: stream
path: "%kernel.logs_dir%/%kernel.environment%_brief.log"
formatter: monolog.brief_formatter
console:
type: console
formatter: monolog.console_formatter
deletion:
# log deletion related messages
level: debug
type: stream
path: '%kernel.logs_dir%/deletion.log'
channels: ['deletion']
formatter: monolog.brief_formatter
services:
my_service:
class: Monolog\Processor\IntrospectionProcessor
tags:
- { name: monolog.processor }
monolog.console_formatter:
class: Symfony\Bridge\Monolog\Formatter\ConsoleFormatter
arguments:
- "<fg=black;bg=green>[%%datetime%%]</fg=black;bg=green> %%start_tag%%%%message%%%%end_tag%%\n"
monolog.brief_formatter:
class: Monolog\Formatter\LineFormatter
arguments:
- "[%%datetime%%] %%message%%\n"
# default format is
# - "[%datetime%] %channel%.%level_name%: %message% %context% %extra%\n"
If you will add code like
$this->getContainer()->get("logger")->info("Sample info");
$this->getContainer()->get("monolog.logger.deletion")->info("Deletion channel info");
$this->getContainer()->get("monolog.logger.deletion")->error("Deletion channel error");
$this->getContainer()->get("monolog.logger.deletion")->info("Deletion channel info #2");
You will get 3 log files with such a content
Channel log file
deletion.log
[2016-11-11 12:43:18] Deletion channel info
[2016-11-11 12:43:18] Deletion channel error
[2016-11-11 12:43:19] Deletion channel info #2
Default env log file
dev.log
[2016-11-11 12:43:18] event.DEBUG: Notified event "console.command" to listener "Symfony\Component\HttpKernel\EventListener\DebugHandlersListener::configure". [] {"file":"...."}
[2016-11-11 12:43:18] event.DEBUG: Notified event "console.command" to listener "Symfony\Bridge\Monolog\Handler\ConsoleHandler::onCommand". [] {"file":"...."}
[2016-11-11 12:43:18] app.INFO: Sample info [] {"file":"..."}
[2016-11-11 12:43:18] deletion.INFO: Deletion channel info [] {"file":"...."}
[2016-11-11 12:43:18] deletion.ERROR: Deletion channel error [] {"...."}
Brief env.log
[2016-11-11 12:43:18] Notified event "console.command" to listener "Symfony\Component\HttpKernel\EventListener\DebugHandlersListener::configure".
[2016-11-11 12:43:18] Notified event "console.command" to listener "Symfony\Bridge\Monolog\Handler\ConsoleHandler::onCommand".
[2016-11-11 12:43:18] Sample info
[2016-11-11 12:43:18] Deletion channel info
[2016-11-11 12:43:18] Deletion channel error
Also notice, that because of stop_buffering: false notice after error will not appear at dev.log, dev_brief.log, but will appear at deletion.log
And you should try sentry - its great product and his owners are cool guys :)