Skip to content
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

Merged
merged 10 commits into from
Oct 28, 2020
Merged

EZP-31967: Added logging to ezplatform:cron:run command #14

merged 10 commits into from
Oct 28, 2020

Conversation

homarx
Copy link
Contributor

@homarx homarx commented Sep 29, 2020

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).

@lserwatka
Copy link
Member

@homarx could you create JIRA ticket and update PR title and commit message?

src/bundle/Command/CronRunCommand.php Outdated Show resolved Hide resolved
src/bundle/Command/CronRunCommand.php Outdated Show resolved Hide resolved
src/bundle/Command/CronRunCommand.php Outdated Show resolved Hide resolved
src/bundle/Command/CronRunCommand.php Outdated Show resolved Hide resolved
@Nattfarinn
Copy link
Contributor

Run composer fix-cs to apply our Coding Standards

@homarx
Copy link
Contributor Author

homarx commented Sep 29, 2020

Coding standards are applied by running fix-cs

@homarx homarx changed the title Adding logging feature to run command EZP-31967: Adding logging feature to run command Sep 29, 2020
@homarx
Copy link
Contributor Author

homarx commented Sep 29, 2020

@homarx could you create JIRA ticket and update PR title and commit message?

@lserwatka Ticket is created and PR title is edited
https://jira.ez.no/browse/EZP-31967

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 }
Copy link
Contributor

@Nattfarinn Nattfarinn Sep 29, 2020

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.

Copy link
Contributor Author

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

Copy link
Contributor

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.

Copy link
Contributor Author

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

Copy link
Contributor

@Nattfarinn Nattfarinn Sep 30, 2020

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"

Copy link
Contributor Author

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?

Copy link
Contributor Author

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?

src/bundle/Resources/config/monolog.yml Outdated Show resolved Hide resolved
src/bundle/Command/CronRunCommand.php Outdated Show resolved Hide resolved
Copy link
Member

@alongosz alongosz left a 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.

src/bundle/Resources/config/services.yml Outdated Show resolved Hide resolved
src/bundle/Resources/config/services.yml Outdated Show resolved Hide resolved
src/bundle/Resources/config/services.yml Outdated Show resolved Hide resolved
@alongosz alongosz changed the title EZP-31967: Adding logging feature to run command EZP-31967: Added logging to ezplatform:cron:run command Oct 26, 2020
@alongosz alongosz requested a review from Nattfarinn October 26, 2020 12:47
@mnocon mnocon self-assigned this Oct 27, 2020
Copy link
Member

@mnocon mnocon left a 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.

@alongosz alongosz merged commit d439530 into ezsystems:2.0 Oct 28, 2020
@alongosz
Copy link
Member

Thank you @homarx 🎉

@homarx
Copy link
Contributor Author

homarx commented Nov 2, 2020

@alongosz @Nattfarinn Thank you for your support and patience ; )

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

Successfully merging this pull request may close these issues.

5 participants