diff --git a/core/lib/Drupal/Core/Cron.php b/core/lib/Drupal/Core/Cron.php index 74d2866402a..a544ca8db05 100644 --- a/core/lib/Drupal/Core/Cron.php +++ b/core/lib/Drupal/Core/Cron.php @@ -13,6 +13,7 @@ use Drupal\Core\Session\AnonymousUserSession; use Drupal\Core\Session\AccountSwitcherInterface; use Drupal\Core\Queue\SuspendQueueException; use Psr\Log\LoggerInterface; +use Psr\Log\NullLogger; /** * The Drupal core Cron service. @@ -196,16 +197,20 @@ class Cron implements CronInterface { protected function invokeCronHandlers() { $module_previous = ''; + // If detailed logging isn't enabled, don't log individual execution times. + $time_logging_enabled = \Drupal::config('system.cron')->get('logging'); + $logger = $time_logging_enabled ? $this->logger : new NullLogger(); + // Iterate through the modules calling their cron handlers (if any): foreach ($this->moduleHandler->getImplementations('cron') as $module) { if (!$module_previous) { - $this->logger->notice('Starting execution of @module_cron().', [ + $logger->notice('Starting execution of @module_cron().', [ '@module' => $module, ]); } else { - $this->logger->notice('Starting execution of @module_cron(), execution of @module_previous_cron() took @time.', [ + $logger->notice('Starting execution of @module_cron(), execution of @module_previous_cron() took @time.', [ '@module' => $module, '@module_previous' => $module_previous, '@time' => Timer::read('cron_' . $module_previous) . 'ms', @@ -225,7 +230,7 @@ class Cron implements CronInterface { $module_previous = $module; } if ($module_previous) { - $this->logger->notice('Execution of @module_previous_cron() took @time.', [ + $logger->notice('Execution of @module_previous_cron() took @time.', [ '@module_previous' => $module_previous, '@time' => Timer::read('cron_' . $module_previous) . 'ms', ]); diff --git a/core/modules/automated_cron/automated_cron.module b/core/modules/automated_cron/automated_cron.module index 858236f974d..6b8c4d24393 100644 --- a/core/modules/automated_cron/automated_cron.module +++ b/core/modules/automated_cron/automated_cron.module @@ -34,14 +34,8 @@ function automated_cron_help($route_name, RouteMatchInterface $route_match) { function automated_cron_form_system_cron_settings_alter(&$form, &$form_state) { $automated_cron_settings = \Drupal::config('automated_cron.settings'); - // Add automated cron settings. - $form['automated_cron'] = [ - '#title' => t('Cron settings'), - '#type' => 'details', - '#open' => TRUE, - ]; $options = [3600, 10800, 21600, 43200, 86400, 604800]; - $form['automated_cron']['interval'] = [ + $form['cron']['interval'] = [ '#type' => 'select', '#title' => t('Run cron every'), '#description' => t('More information about setting up scheduled tasks can be found by reading the cron tutorial on drupal.org.', ['@url' => 'https://www.drupal.org/cron']), @@ -49,13 +43,6 @@ function automated_cron_form_system_cron_settings_alter(&$form, &$form_state) { '#options' => [0 => t('Never')] + array_map([\Drupal::service('date.formatter'), 'formatInterval'], array_combine($options, $options)), ]; - $form['actions']['#type'] = 'actions'; - $form['actions']['submit'] = [ - '#type' => 'submit', - '#value' => t('Save configuration'), - '#button_type' => 'primary', - ]; - // Add submit callback. $form['#submit'][] = 'automated_cron_settings_submit'; @@ -70,5 +57,4 @@ function automated_cron_settings_submit(array $form, FormStateInterface $form_st \Drupal::configFactory()->getEditable('automated_cron.settings') ->set('interval', $form_state->getValue('interval')) ->save(); - drupal_set_message(t('The configuration options have been saved.')); } diff --git a/core/modules/config/src/Tests/ConfigInstallProfileOverrideTest.php b/core/modules/config/src/Tests/ConfigInstallProfileOverrideTest.php index c2cea6d4366..ec508df7dbe 100644 --- a/core/modules/config/src/Tests/ConfigInstallProfileOverrideTest.php +++ b/core/modules/config/src/Tests/ConfigInstallProfileOverrideTest.php @@ -36,6 +36,7 @@ class ConfigInstallProfileOverrideTest extends WebTestBase { 'requirements_warning' => 172800, 'requirements_error' => 1209600, ), + 'logging' => 1, ); // The expected active configuration altered by the install profile. $expected_profile_data = array( @@ -43,6 +44,7 @@ class ConfigInstallProfileOverrideTest extends WebTestBase { 'requirements_warning' => 259200, 'requirements_error' => 1209600, ), + 'logging' => 1, ); $expected_profile_data['_core']['default_config_hash'] = Crypt::hashBase64(serialize($expected_profile_data)); diff --git a/core/modules/config/tests/config_override_test/config/install/system.cron.yml b/core/modules/config/tests/config_override_test/config/install/system.cron.yml index e4a27dcc2c7..c27b41dbba8 100644 --- a/core/modules/config/tests/config_override_test/config/install/system.cron.yml +++ b/core/modules/config/tests/config_override_test/config/install/system.cron.yml @@ -1,4 +1,4 @@ threshold: requirements_warning: 172800 requirements_error: 1209600 - +logging: 1 diff --git a/core/modules/dblog/src/Tests/DbLogTest.php b/core/modules/dblog/src/Tests/DbLogTest.php index 886f7681e97..daa9421b731 100644 --- a/core/modules/dblog/src/Tests/DbLogTest.php +++ b/core/modules/dblog/src/Tests/DbLogTest.php @@ -147,6 +147,25 @@ class DbLogTest extends WebTestBase { $count = db_query('SELECT COUNT(wid) FROM {watchdog}')->fetchField(); $this->assertTrue($count > $row_limit, format_string('Dblog row count of @count exceeds row limit of @limit', array('@count' => $count, '@limit' => $row_limit))); + // Get the number of enabled modules. Cron adds a log entry for each module. + $list = \Drupal::moduleHandler()->getImplementations('cron'); + $module_count = count($list); + $cron_detailed_count = $this->runCron(); + $this->assertTrue($cron_detailed_count == $module_count + 2, format_string('Cron added @count of @expected new log entries', array('@count' => $cron_detailed_count, '@expected' => $module_count + 2))); + + // Test disabling of detailed cron logging. + $this->config('system.cron')->set('logging', 0)->save(); + $cron_count = $this->runCron(); + $this->assertTrue($cron_count = 1, format_string('Cron added @count of @expected new log entries', array('@count' => $cron_count, '@expected' => 1))); + } + + /** + * Runs cron and returns number of new log entries. + * + * @return int + * Number of new watchdog entries. + */ + private function runCron() { // Get last ID to compare against; log entries get deleted, so we can't // reliably add the number of newly created log entries to the current count // to measure number of log entries created by cron. @@ -158,12 +177,7 @@ class DbLogTest extends WebTestBase { // Get last ID after cron was run. $current_id = db_query('SELECT MAX(wid) FROM {watchdog}')->fetchField(); - // Get the number of enabled modules. Cron adds a log entry for each module. - $list = \Drupal::moduleHandler()->getImplementations('cron'); - $module_count = count($list); - - $count = $current_id - $last_id; - $this->assertTrue(($current_id - $last_id) == $module_count + 2, format_string('Cron added @count of @expected new log entries', array('@count' => $count, '@expected' => $module_count + 2))); + return $current_id - $last_id; } /** diff --git a/core/modules/system/config/install/system.cron.yml b/core/modules/system/config/install/system.cron.yml index e6f30d3d2d8..c27b41dbba8 100644 --- a/core/modules/system/config/install/system.cron.yml +++ b/core/modules/system/config/install/system.cron.yml @@ -1,3 +1,4 @@ threshold: requirements_warning: 172800 requirements_error: 1209600 +logging: 1 diff --git a/core/modules/system/config/schema/system.schema.yml b/core/modules/system/config/schema/system.schema.yml index e34d375cf18..c23ed7e0aee 100644 --- a/core/modules/system/config/schema/system.schema.yml +++ b/core/modules/system/config/schema/system.schema.yml @@ -72,6 +72,9 @@ system.cron: requirements_error: type: integer label: 'Requirements error period' + logging: + type: integer + label: 'Detailed cron logging' system.date: type: config_object diff --git a/core/modules/system/src/Form/CronForm.php b/core/modules/system/src/Form/CronForm.php index af1623e9649..d19915dced2 100644 --- a/core/modules/system/src/Form/CronForm.php +++ b/core/modules/system/src/Form/CronForm.php @@ -10,11 +10,13 @@ use Drupal\Core\Form\FormBase; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\State\StateInterface; use Symfony\Component\DependencyInjection\ContainerInterface; +use Drupal\Core\Form\ConfigFormBaseTrait; /** * Configure cron settings for this site. */ class CronForm extends FormBase { + use ConfigFormBaseTrait; /** * Stores the state storage service. @@ -65,6 +67,13 @@ class CronForm extends FormBase { $this->moduleHandler = $module_handler; } + /** + * {@inheritdoc} + */ + protected function getEditableConfigNames() { + return ['system.cron']; + } + /** * {@inheritdoc} */ @@ -107,11 +116,31 @@ class CronForm extends FormBase { ); if (!$this->moduleHandler->moduleExists('automated_cron')) { - $form['cron'] = array( + $form['automated_cron'] = array( '#markup' => $this->t('Enable the Automated Cron module to allow cron execution at the end of a server response.'), ); } + $form['cron'] = [ + '#title' => t('Cron settings'), + '#type' => 'details', + '#open' => TRUE, + ]; + + $form['cron']['logging'] = array( + '#type' => 'checkbox', + '#title' => t('Detailed cron logging'), + '#default_value' => $this->config('system.cron')->get('logging'), + '#description' => 'Run times of individual cron jobs will be written to watchdog', + ); + + $form['actions']['#type'] = 'actions'; + $form['actions']['submit'] = [ + '#type' => 'submit', + '#value' => t('Save configuration'), + '#button_type' => 'primary', + ]; + return $form; } @@ -119,6 +148,11 @@ class CronForm extends FormBase { * Runs cron and reloads the page. */ public function submitForm(array &$form, FormStateInterface $form_state) { + $this->config('system.cron') + ->set('logging', $form_state->getValue('logging')) + ->save(); + drupal_set_message(t('The configuration options have been saved.')); + // Run cron manually from Cron form. if ($this->cron->run()) { drupal_set_message(t('Cron ran successfully.')); diff --git a/core/modules/system/system.install b/core/modules/system/system.install index d6d6b44491d..6dc2663d1b4 100644 --- a/core/modules/system/system.install +++ b/core/modules/system/system.install @@ -1784,3 +1784,13 @@ function system_update_8202() { /** * @} End of "addtogroup updates-8.2.3". */ + +/** + * Add detailed cron logging configuration. + */ +function system_update_8203() { + $config_factory = \Drupal::configFactory(); + $system_cron_config = $config_factory->getEditable('system.cron') + ->set('logging', 1) + ->save(TRUE); +} diff --git a/core/modules/system/tests/src/Kernel/Migrate/d7/MigrateSystemConfigurationTest.php b/core/modules/system/tests/src/Kernel/Migrate/d7/MigrateSystemConfigurationTest.php index 59d7b01b8a8..22e9ba75933 100644 --- a/core/modules/system/tests/src/Kernel/Migrate/d7/MigrateSystemConfigurationTest.php +++ b/core/modules/system/tests/src/Kernel/Migrate/d7/MigrateSystemConfigurationTest.php @@ -24,6 +24,7 @@ class MigrateSystemConfigurationTest extends MigrateDrupal7TestBase { 'requirements_warning' => 172800, 'requirements_error' => 1209600, ], + 'logging' => 1, ], 'system.date' => [ 'country' => [ diff --git a/core/profiles/standard/config/install/system.cron.yml b/core/profiles/standard/config/install/system.cron.yml index e6f30d3d2d8..c27b41dbba8 100644 --- a/core/profiles/standard/config/install/system.cron.yml +++ b/core/profiles/standard/config/install/system.cron.yml @@ -1,3 +1,4 @@ threshold: requirements_warning: 172800 requirements_error: 1209600 +logging: 1 diff --git a/core/profiles/testing_config_overrides/config/install/system.cron.yml b/core/profiles/testing_config_overrides/config/install/system.cron.yml index e9c97bc4ad5..f3cdb47cbc5 100644 --- a/core/profiles/testing_config_overrides/config/install/system.cron.yml +++ b/core/profiles/testing_config_overrides/config/install/system.cron.yml @@ -1,3 +1,4 @@ threshold: requirements_warning: 259200 requirements_error: 1209600 +logging: 1