I am working on a Symfony 2 web app and I would like to inject a Monolog logger using a specific channel to a service:
The Config:
monolog:
handlers:
main:
type: stream
path: %kernel.root_dir%/%kernel.environment%.log
level: error
#channels: [!alert]
alert:
type: stream
path: %kernel.root_dir%/%kernel.environment%.alert.log
level: info
channels: [alert]
Service Config:
services:
some_service:
class: Some\Service
arguments: [#logger]
tags:
- { name: monolog.logger, channel: alert }
The Service:
class SomeService {
protected $logger;
public function __construct($logger) {
$this->logger = $logger;
$this->logger->info('Log this!');
}
The prod.log file:
[2016-03-28 11:25:47] alert.INFO: Log this!
The Problem: Although I specifically inject the logger using the alert channel, the message is handled by the main handler. Thus the messages are logged into the prod.log file instead of the prod.alert.log file.
When I leave the line channels: [!alert] as comment, the message is logged to prod.log. When I activate this line by removing the comment, the message is not logged at all (main handler ignores the channel correctly).
What have I to to, in order to use a specific handler to target a specific log file, mailer, etc? Messages to alert channel should be handled by the alert handler while all other handlers are ignored.
Use special service created for Monolog handler:
services:
some_service:
class: Namespace\Some\Service
arguments: ["#monolog.logger.alert"]
Related
I have a Symfony command which is executed under a cron entry and I need some log in production environment.
As I read here in production, for console commands, verbosity level is related to log level shown, so I tried to configure monolog to show "notice" level.
My problem is, log is never written in prod environment.
This is my command:
use Psr\Log\LoggerInterface;
class MyCommand extends Command
{
private $logger;
public function __construct(LoggerInterface $logger)
{
parent::__construct();
$this->logger = $logger;
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
$this->logger->notice('### HELLO ###');
}
}
And this is config/packages/prod/monolog.yml, see that action_level is set to notice:
monolog:
handlers:
main:
type: fingers_crossed
path: '%kernel.logs_dir%/%kernel.environment%.log'
action_level: notice
handler: nested
excluded_http_codes: [404, 405]
buffer_size: 50 # How many messages should be saved? Prevent memory leaks
nested:
type: stream
path: php://stderr
level: debug
formatter: monolog.formatter.json
console:
type: console
process_psr_3_messages: false
channels: ["!event", "!doctrine"]
A file var/log/prod.log never appears.
Note: according to this SO answer, commands are always run in dev environment, but the log entries don't appear in dev.log either.
I try to write logs to a specific file using a specific channel in Monolog (called encuestas_cloud) inside a Command in Symfony 3.4 but I'm not able to do it.
I've read Symfony docs and searched in the web and I think it's well configured but i get an error.
The code is:
In config_dev.yml:
monolog:
handlers:
main:
type: stream
path: '%kernel.logs_dir%/%kernel.environment%.log'
level: debug
channels: ['!event']
...
encuestas_cloud_logger:
#type: rotating_file
type: stream
path: 'D:/web/xampp/htdocs/temp/logs/encuestas_cloud.log'
level: info
channels: ['encuestas_cloud']
max_files: 10
In services.yml
services:
_defaults:
autowire: true
autoconfigure: true
public: false
AppBundle\Command\EncuestasCloudCommand\:
resource: '../../src/AppBundle/Command/EncuestasCloudCommand.php'
arguments: ['#logger']
public: true
tags:
- { name: monolog.logger, channel: encuestas_cloud }
The command:
// src/AppBundle/Command/EncuestasCloudCommand.php
namespace AppBundle\Command;
use Psr\Log\LoggerInterface;
use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
...
class EncuestasCloudCommand extends ContainerAwareCommand
{
private $logger;
public function __construct(LoggerInterface $logger)
{
$this->logger = $logger;
parent::__construct();
}
...
protected function execute(InputInterface $input, OutputInterface $output)
{
$logger = $this->logger;
$logger->addInfo('My logger is now ready');
When I execute it I get:
In LoggerChannelPass.php line 98:
Monolog configuration error: The logging channel "encuestas_cloud" assigned to the
"encuestas_cloud_logger" handler does not exist.
In ContainerBuilder.php line 1063:
You have requested a non-existent service "monolog.logger.encuestas_cloud".
If I add channels: ['encuestas_cloud'] in config_dev.yml
monolog:
channels: ['encuestas_cloud']
handlers:
main:
type: stream
...
The error dissappear but the log still goes to the general log file: dev.log
Please, could somebody help me to find out what is wrong with the configuration?
Thanks a lot!!!
Does changing the argument for your Command from #logger to #monolog.logger.encuestas_cloud work? That should inject the specific configured logger and therefor your logging would appear in the correct logger.
monolog:
channels: ['encuestas_cloud']
Should be defined AFAIK, and explicitly excluding the channel for your main logger, to not appear there:
monolog:
handlers:
main:
...
channels: [ '!encuestas_cloud' ]
Thanks a lot evertjes for your answer, it didn't solve the problem but helped me to investigate other paths...
The problem was that the command wasn't defined as a service in the right way, so Symfony was unable to match the channel to the service (and to the command).
I executed :
php bin/console debug:container
and the service of the command didn't appear.
So after investigating how to define a command as a service the configuration worked fine... uffff.
Here I post the final code that works.
In config_dev.yml:
monolog:
channels: ['encuestas_cloud']
handlers:
main:
type: stream
path: '%kernel.logs_dir%/%kernel.environment%.log'
level: debug
channels: ['!event','!encuestas_cloud']
...
encuestas_cloud_logger:
type: rotating_file
path: 'D:/web/xampp/htdocs/temp/logs/encuestas_cloud.log'
level: info
channels: ['encuestas_cloud']
max_files: 10
In services.yml
services:
_defaults:
autowire: true
autoconfigure: true
public: false
console.command.encuestas_cloud_command:
class: 'AppBundle\Command\EncuestasCloudCommand'
arguments: ['#logger']
public: true
tags:
- { name: monolog.logger, channel: encuestas_cloud }
The command:
// src/AppBundle/Command/EncuestasCloudCommand.php
namespace AppBundle\Command;
use Psr\Log\LoggerInterface;
use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
...
class EncuestasCloudCommand extends ContainerAwareCommand
{
private $logger;
public function __construct(LoggerInterface $logger)
{
$this->logger = $logger;
parent::__construct();
}
...
protected function execute(InputInterface $input, OutputInterface $output)
{
$logger = $this->logger;
$logger->addInfo('My logger is now ready');
Now the file is created and the log appears with the configured channel.
Thanks a lot to everybody!!!
Config.yml
gos_web_socket:
topics:
- #app.real_time.subscribe
- #app.real_time.push
server:
port: 8000 #The port the socket server will listen on
host: localhost #The host ip to bind to
router:
resources:
- #AppBundle/Resources/config/pubsub/routing.yml
client:
firewall: main #can be an array of firewalls
session_handler: #session.handler.pdo
pushers:
zmq:
default: true
host: 127.0.0.1
port: 8888
persistent: true
protocol: tcp
pubsub/routing.yml
real_time_push:
channel: all/user
handler:
callback: 'app.real_time.push' #related to the getName() of your topic
services.yml
app.real_time.subscribe:
class: AppBundle\RealTime\Subscribe
arguments: [ #gos_web_socket.websocket.client_manipulator ]
app.real_time.push:
class: AppBundle\RealTime\Push
arguments: [ #gos_web_socket.websocket.client_manipulator ]
The following function is getting hit when client subscribes on this topic. I can see the text in the console.
Subscribe Class onSubscribe() : Subscribe.php
public function onSubscribe(ConnectionInterface $connection, Topic $topic, WampRequest $request)
{
var_dump("This user is subscribed");
}
But when pushed via zmq from controller the onPush() function never got hit. I have already implemented TopicInterdace and PushableTopicInterface in Push.php.
Push Class onPush() : Push.php
public function onPush(Topic $topic, WampRequest $request, $data, $provider)
{
var_dump("Helloooooooooooooooooo0000000000");
}
Please can any one tell me where did I do wrong. Thanks in advance. Here is the controller
$pusher = $this->container->get('gos_web_socket.zmq.pusher');
//push(data, route_name, route_arguments)
$pusher->push(['my_data' => 'data'], 'real_time_push', ['username' => 'sujit']);
I made a command that automatically writes in routing.yml.
My problem is that when I try to browse one of the routes
api:
resource: "."
type: "api"
prefix: /api
I get this exception
Cannot load resource "."
I tried to add a cache:clear to my command but I get the same exception.
I added a cache warmup that runs after the command termination that way Symfony dumps routes into generated code .
class TerminateListener {
public function onConsoleTerminate(ConsoleTerminateEvent $event) {
if ($event->getCommand()->getName() == ('my:command')) {
$app = new Application();
$cache_clear_command = $event->getCommand()->getApplication()->find('cache:warmup');
$cache_clear_command->setApplication($app);
$event->getOutput()->setVerbosity('VERBOSITY_QUIET');
$cache_clear_command->run($event->getInput(), $event->getOutput());
}
}
}
services:
warmup.listener:
class:TerminateListener
tags:
- { name: kernel.event_listener, event: console.terminate , method: onConsoleTerminate }
I want to get User (FOSuserBundle) in Listener With Symfony (2.7).
My Listener service :
utilisateur_cabinet_listener:
class: UtilisateurBundle\Listener\Cabinet
arguments: [#router, #utilisateur_cabinet_repository]
tags:
- { name: kernel.event_listener, event: kernel.request, method: onKernelRequest }
In Stackoverflow, you recommend to import container service, but the subjects date. Do you have another solution ?