|
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 |
| - <container xmlns="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 |
| - <service id="app.listener.command_exception" class="AppBundle\EventListener\ConsoleExceptionListener"> |
100 |
| - <argument type="service" id="logger"/> |
101 |
| - <tag name="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 |
| - <container xmlns="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 |
| - <service id="app.listener.command_error" class="AppBundle\EventListener\ErrorLoggerListener"> |
201 |
| - <argument type="service" id="logger"/> |
202 |
| - <tag name="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. |
0 commit comments