|
4 | 4 | How to Enable Logging in Console Commands |
5 | 5 | ========================================= |
6 | 6 |
|
7 | | -The Console component doesn't provide any logging capabilities out of the box. |
8 | | -Normally, you run console commands manually and observe the output, which is |
9 | | -why logging is not provided. However, there are cases when you might need |
10 | | -logging. For example, if you are running console commands unattended, such |
11 | | -as from cron jobs or deployment scripts, it may be easier to use Symfony's |
12 | | -logging capabilities instead of configuring other tools to gather console |
13 | | -output and process it. This can be especially handful if you already have |
14 | | -some existing setup for aggregating and analyzing Symfony logs. |
| 7 | +In Symfony versions prior to 3.3, the Console component didn't provide any |
| 8 | +logging capabilities out of the box and you had to implement your own exception |
| 9 | +lister for the console. |
15 | 10 |
|
16 | | -There are basically two logging cases you would need: |
17 | | - |
18 | | -* Manually logging some information from your command; |
19 | | -* Logging uncaught exceptions. |
20 | | - |
21 | | -Manually Logging from a Console Command |
22 | | ---------------------------------------- |
23 | | - |
24 | | -This one is really simple. When you create a console command within the full-stack |
25 | | -framework as described in ":doc:`/console`", your command extends |
26 | | -:class:`Symfony\\Bundle\\FrameworkBundle\\Command\\ContainerAwareCommand`. |
27 | | -This means that you can simply access the standard logger service through the |
28 | | -container and use it to do the logging:: |
29 | | - |
30 | | - // src/AppBundle/Command/GreetCommand.php |
31 | | - namespace AppBundle\Command; |
32 | | - |
33 | | - use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand; |
34 | | - use Symfony\Component\Console\Input\InputArgument; |
35 | | - use Symfony\Component\Console\Input\InputInterface; |
36 | | - use Symfony\Component\Console\Input\InputOption; |
37 | | - use Symfony\Component\Console\Output\OutputInterface; |
38 | | - use Psr\Log\LoggerInterface; |
39 | | - |
40 | | - class GreetCommand extends ContainerAwareCommand |
41 | | - { |
42 | | - // ... |
43 | | - |
44 | | - protected function execute(InputInterface $input, OutputInterface $output) |
45 | | - { |
46 | | - /** @var $logger LoggerInterface */ |
47 | | - $logger = $this->getContainer()->get('logger'); |
48 | | - |
49 | | - $name = $input->getArgument('name'); |
50 | | - if ($name) { |
51 | | - $text = 'Hello '.$name; |
52 | | - } else { |
53 | | - $text = 'Hello'; |
54 | | - } |
55 | | - |
56 | | - if ($input->getOption('yell')) { |
57 | | - $text = strtoupper($text); |
58 | | - $logger->warning('Yelled: '.$text); |
59 | | - } else { |
60 | | - $logger->info('Greeted: '.$text); |
61 | | - } |
62 | | - |
63 | | - $output->writeln($text); |
64 | | - } |
65 | | - } |
66 | | - |
67 | | -Depending on the environment in which you run your command (and your logging |
68 | | -setup), you should see the logged entries in ``var/logs/dev.log`` or ``var/logs/prod.log``. |
69 | | - |
70 | | -Enabling automatic Exceptions Logging |
71 | | -------------------------------------- |
72 | | - |
73 | | -To get your console application to automatically log uncaught exceptions for |
74 | | -all of your commands, you can use:doc:`console events</components/console/events>`. |
75 | | - |
76 | | -First configure a listener for console exception events in the service container: |
77 | | - |
78 | | -..configuration-block:: |
79 | | - |
80 | | - ..code-block::yaml |
81 | | -
|
82 | | -# app/config/services.yml |
83 | | -services: |
84 | | -app.listener.command_exception: |
85 | | -class:AppBundle\EventListener\ConsoleExceptionListener |
86 | | -arguments:['@logger'] |
87 | | -tags: |
88 | | - -{ name: kernel.event_listener, event: console.exception } |
89 | | -
|
90 | | - ..code-block::xml |
91 | | -
|
92 | | -<!-- app/config/services.xml--> |
93 | | - <?xml version="1.0" encoding="UTF-8" ?> |
94 | | - <containerxmlns="http://symfony.com/schema/dic/services" |
95 | | -xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
96 | | -xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd"> |
97 | | -
|
98 | | - <services> |
99 | | - <serviceid="app.listener.command_exception"class="AppBundle\EventListener\ConsoleExceptionListener"> |
100 | | - <argumenttype="service"id="logger"/> |
101 | | - <tagname="kernel.event_listener"event="console.exception" /> |
102 | | - </service> |
103 | | - </services> |
104 | | - </container> |
105 | | -
|
106 | | - ..code-block::php |
107 | | -
|
108 | | - // app/config/services.php |
109 | | - use AppBundle\EventListener\ConsoleExceptionListener; |
110 | | - use Symfony\Component\DependencyInjection\Definition; |
111 | | - use Symfony\Component\DependencyInjection\Reference; |
112 | | -
|
113 | | - $definitionConsoleExceptionListener = new Definition( |
114 | | - ConsoleExceptionListener::class, |
115 | | - array(new Reference('logger')) |
116 | | - ); |
117 | | - $definitionConsoleExceptionListener->addTag( |
118 | | - 'kernel.event_listener', |
119 | | - array('event' => 'console.exception') |
120 | | - ); |
121 | | - $container->setDefinition( |
122 | | - 'app.listener.command_exception', |
123 | | - $definitionConsoleExceptionListener |
124 | | - ); |
125 | | -
|
126 | | -Then implement the actual listener:: |
127 | | - |
128 | | - // src/AppBundle/EventListener/ConsoleExceptionListener.php |
129 | | - namespace AppBundle\EventListener; |
130 | | - |
131 | | - use Symfony\Component\Console\Event\ConsoleExceptionEvent; |
132 | | - use Psr\Log\LoggerInterface; |
133 | | - |
134 | | - class ConsoleExceptionListener |
135 | | - { |
136 | | - private $logger; |
137 | | - |
138 | | - public function __construct(LoggerInterface $logger) |
139 | | - { |
140 | | - $this->logger = $logger; |
141 | | - } |
142 | | - |
143 | | - public function onConsoleException(ConsoleExceptionEvent $event) |
144 | | - { |
145 | | - $command = $event->getCommand(); |
146 | | - $exception = $event->getException(); |
147 | | - |
148 | | - $message = sprintf( |
149 | | - '%s: %s (uncaught exception) at %s line %s while running console command `%s`', |
150 | | - get_class($exception), |
151 | | - $exception->getMessage(), |
152 | | - $exception->getFile(), |
153 | | - $exception->getLine(), |
154 | | - $command->getName() |
155 | | - ); |
156 | | - |
157 | | - $this->logger->error($message, array('exception' => $exception)); |
158 | | - } |
159 | | - } |
160 | | - |
161 | | -In the code above, when any command throws an exception, the listener will |
162 | | -receive an event. You can simply log it by passing the logger service via the |
163 | | -service configuration. Your method receives a |
164 | | -:class:`Symfony\\Component\\Console\\Event\\ConsoleExceptionEvent` object, |
165 | | -which has methods to get information about the event and the exception. |
166 | | - |
167 | | -.. _logging-non-0-exit-statuses: |
168 | | - |
169 | | -Logging Error Exit Statuses |
170 | | ---------------------------- |
171 | | - |
172 | | -The logging capabilities of the console can be further extended by logging |
173 | | -commands that return error exit statuses, which are any number different than |
174 | | -zero. This way you will know if a command had any errors, even if no exceptions |
175 | | -were thrown. |
176 | | - |
177 | | -First configure a listener for console terminate events in the service container: |
178 | | - |
179 | | -..configuration-block:: |
180 | | - |
181 | | - ..code-block::yaml |
182 | | -
|
183 | | -# app/config/services.yml |
184 | | -services: |
185 | | -app.listener.command_error: |
186 | | -class:AppBundle\EventListener\ErrorLoggerListener |
187 | | -arguments:['@logger'] |
188 | | -tags: |
189 | | - -{ name: kernel.event_listener, event: console.terminate } |
190 | | -
|
191 | | - ..code-block::xml |
192 | | -
|
193 | | -<!-- app/config/services.xml--> |
194 | | - <?xml version="1.0" encoding="UTF-8" ?> |
195 | | - <containerxmlns="http://symfony.com/schema/dic/services" |
196 | | -xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
197 | | -xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd"> |
198 | | -
|
199 | | - <services> |
200 | | - <serviceid="app.listener.command_error"class="AppBundle\EventListener\ErrorLoggerListener"> |
201 | | - <argumenttype="service"id="logger"/> |
202 | | - <tagname="kernel.event_listener"event="console.terminate" /> |
203 | | - </service> |
204 | | - </services> |
205 | | - </container> |
206 | | -
|
207 | | - ..code-block::php |
208 | | -
|
209 | | - // app/config/services.php |
210 | | - use AppBundle\EventListener\ErrorLoggerListener; |
211 | | - use Symfony\Component\DependencyInjection\Definition; |
212 | | - use Symfony\Component\DependencyInjection\Reference; |
213 | | -
|
214 | | - $definitionErrorLoggerListener = new Definition( |
215 | | - ErrorLoggerListener::class, |
216 | | - array(new Reference('logger')) |
217 | | - ); |
218 | | - $definitionErrorLoggerListener->addTag( |
219 | | - 'kernel.event_listener', |
220 | | - array('event' => 'console.terminate') |
221 | | - ); |
222 | | - $container->setDefinition( |
223 | | - 'app.listener.command_error', |
224 | | - $definitionErrorLoggerListener |
225 | | - ); |
226 | | -
|
227 | | -Then implement the actual listener:: |
228 | | - |
229 | | - // src/AppBundle/EventListener/ErrorLoggerListener.php |
230 | | - namespace AppBundle\EventListener; |
231 | | - |
232 | | - use Symfony\Component\Console\Event\ConsoleTerminateEvent; |
233 | | - use Psr\Log\LoggerInterface; |
234 | | - |
235 | | - class ErrorLoggerListener |
236 | | - { |
237 | | - private $logger; |
238 | | - |
239 | | - public function __construct(LoggerInterface $logger) |
240 | | - { |
241 | | - $this->logger = $logger; |
242 | | - } |
243 | | - |
244 | | - public function onConsoleTerminate(ConsoleTerminateEvent $event) |
245 | | - { |
246 | | - $statusCode = $event->getExitCode(); |
247 | | - $command = $event->getCommand(); |
248 | | - |
249 | | - if ($statusCode === 0) { |
250 | | - return; |
251 | | - } |
252 | | - |
253 | | - if ($statusCode > 255) { |
254 | | - $statusCode = 255; |
255 | | - $event->setExitCode($statusCode); |
256 | | - } |
257 | | - |
258 | | - $this->logger->warning(sprintf( |
259 | | - 'Command `%s` exited with status code %d', |
260 | | - $command->getName(), |
261 | | - $statusCode |
262 | | - )); |
263 | | - } |
264 | | - } |
| 11 | +Starting from Symfony 3.3, the Console component provides automatic error and |
| 12 | +exception logging. |