-
Notifications
You must be signed in to change notification settings - Fork 4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
EZP-31967: Added logging to ezplatform:cron:run command #14
Conversation
@homarx could you create JIRA ticket and update PR title and commit message? |
Run |
Coding standards are applied by running fix-cs |
@lserwatka Ticket is created and PR title is edited What should happen with the commits? Prefix them with EZP-31967? |
class: '%ezplatform.console.command.run.class%' | ||
tags: | ||
- { name: console.command } | ||
- { name: monolog.logger, channel: cronjob } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AFAIK, you don't need it anymore.
LoggerInterface $cronjobLogger
,LoggerAwareInterface
+ this tag
are two ways of injecting the right channel. I wasn't aware of previous answer and it is "either/or" rather than do both.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Nattfarinn Autowiring (https://symfony.com/doc/current/logging/channels_handlers.html#how-to-autowire-logger-channels) doesn't work with Symfony 3.4. Consequently the first variant (LoggerInterface $cronjobLogger
) is out I think.
For the second variant I need some help. Are the following steps correct:
- Class CronRunCommand must implement LoggerAwareInterface
- setLogger function has to be implemented for class CronRunCommand
- the service is configured with monolog.logger tag
- the service calls setLogger with specific logger channel
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@homarx Exactly, and the last step is done automatically during container build by Symfony.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Nattfarinn It doesn't work without the setLogger call configured in service.
CronRunCommand.php:
<?php
/**
* @copyright Copyright (C) Ibexa AS. All rights reserved.
* @license For full copyright and license information view LICENSE file distributed with this source code.
*/
namespace EzSystems\EzPlatformCronBundle\Command;
use Cron\Cron;
use Cron\Executor\Executor;
use Cron\Resolver\ArrayResolver;
use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Psr\Log\LoggerAwareInterface;
use Psr\Log\LoggerInterface;
class CronRunCommand extends ContainerAwareCommand implements LoggerAwareInterface
{
/**
* @var \Psr\Log\LoggerInterface
*/
private $logger;
/**
* @param \Psr\Log\LoggerInterface $logger
*/
public function setLogger(LoggerInterface $logger)
{
$this->logger = $logger;
}
protected function configure()
{
$this
->setDefinition([
new InputOption('category', null, InputOption::VALUE_REQUIRED, 'Job category to run', 'default'),
])
->setName('ezplatform:cron:run')
->setDescription('Perform one-time cron tasks run.')
->setHelp(
<<<EOT
It's not meant to be run manually, yet it's OK to do so as it still might be useful for development purpose.
Check documentation how to setup it be called automatically.
EOT
);
}
protected function execute(InputInterface $input, OutputInterface $output)
{
$registry = $this->getContainer()->get('ezplatform.cron.registry.cronjobs');
$category = $input->getOption('category');
$cronJobs = $registry->getCategoryCronJobs($category);
$resolver = new ArrayResolver($cronJobs);
$cron = new Cron();
$cron->setExecutor(new Executor());
$cron->setResolver($resolver);
$reports = $cron->run();
while ($cron->isRunning()) {
usleep(10000);
}
if ($this->logger) {
foreach ($reports->getReports() as $report) {
$process = $report->getJob()->getProcess();
$extraInfo = [
'command' => $process->getCommandLine(),
'exitCode' => $process->getExitCode(),
];
foreach ($report->getOutput() as $reportOutput) {
$this->logger->info($reportOutput, $extraInfo);
}
if (!$report->isSuccessful()) {
foreach ($report->getError() as $reportError) {
$reportError = trim($reportError);
if (!empty($reportError)) {
$this->logger->error($reportError, $extraInfo);
}
}
}
}
}
}
}
service.yml:
parameters:
ezplatform.cron.registry.cronjobs.class: EzSystems\EzPlatformCronBundle\Registry\CronJobsRegistry
ezplatform.console.command.run.class: EzSystems\EzPlatformCronBundle\Command\CronRunCommand
services:
ezplatform.cron.registry.cronjobs:
class: '%ezplatform.cron.registry.cronjobs.class%'
arguments:
- '%kernel.environment%'
- '@ezpublish.siteaccess'
ezplatform.console.command.run:
class: '%ezplatform.console.command.run.class%'
# calls:
# - [setLogger, ["@monolog.logger.cronjob"]]
tags:
- { name: console.command }
- { name: monolog.logger, channel: cronjob }
When I comment in the setLogger call in service.yml, logfile is written as expected.
I'm implementing on Platform v2 with Symfony 3.4
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Huh, my bad. I was almost 100% sure it was already part of 3.4, but turns out it is not.
Ignore the LoggerAwareInterface
then and just go with plain old dependency injection (use LoggerInterface $logger
in constructor):
ezplatform.console.command.run:
class: '%ezplatform.console.command.run.class%'
arguments:
$logger: "@monolog.logger.cronjob"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Nattfarinn If monolog.logger.cronjob service is injected as argument it has to be configured. Otherwise an error would be thrown.
If the service is injected via tag it doesen't matter if cronjob channel is configured or not:
ezplatform.console.command.run:
class: '%ezplatform.console.command.run.class%'
tags:
- { name: console.command }
- { name: monolog.logger, channel: cronjob }
Which do you think is the better way?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Nattfarinn I choosed the injection via argument and added the missing config (monolog channel). Can you please take a look at my last commit?
…gger variable in constructor
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@homarx I spotted more CS issues in services.yml
. Must've missed that last time, I apologize for the inconvenience.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tested on ezplatform 2.5.14 with custom Commands registered as cron jobs, looks good to me!
Approved.
Thank you @homarx 🎉 |
@alongosz @Nattfarinn Thank you for your support and patience ; ) |
With this feature it will be possible to log all outputs and errors processed by run command.
To do so the channel
cronjob
has to be added to monolog configuration (example in README.md).