MonitoringCommands.php in Monitoring 8
Namespace
Drupal\monitoring\CommandsFile
src/Commands/MonitoringCommands.phpView source
<?php
namespace Drupal\monitoring\Commands;
use Consolidation\AnnotatedCommand\CommandResult;
use Consolidation\OutputFormatters\StructuredData\PropertyList;
use Consolidation\OutputFormatters\StructuredData\RowsOfFields;
use Drupal\Component\Render\FormattableMarkup;
use Drupal\Component\Serialization\Json;
use Drupal\Component\Utility\Unicode;
use Drupal\Core\Datetime\DateFormatterInterface;
use Drupal\monitoring\Result\SensorResultInterface;
use Drupal\monitoring\Sensor\SensorManager;
use Drush\Commands\DrushCommands;
/**
* A Drush commandfile for the Monitoring module.
*/
class MonitoringCommands extends DrushCommands {
/**
* Exit code for an unknown sensor status.
*/
public const SENSOR_STATUS_UNKNOWN = 3;
/**
* Exit code for a critical sensor status.
*/
public const SENSOR_STATUS_CRITICAL = 2;
/**
* Exit code for a warning sensor status.
*/
public const SENSOR_STATUS_WARNING = 1;
/**
* Exit code for a proper run with OK status.
*/
public const SENSOR_STATUS_OK = 0;
/**
* The Sensor Manager service.
*
* @var \Drupal\monitoring\Sensor\SensorManager
*/
protected $sensorManager;
/**
* The Date formatter service.
*
* @var \Drupal\Core\Datetime\DateFormatterInterface
*/
protected $dateFormatter;
/**
* MonitoringCommands constructor.
*
* @param \Drupal\monitoring\Sensor\SensorManager $sensor_manager
* The Sensor Manager service.
* @param \Drupal\Core\Datetime\DateFormatterInterface $date_formatter
* The Date formatter service.
*/
public function __construct(SensorManager $sensor_manager, DateFormatterInterface $date_formatter) {
parent::__construct();
$this->sensorManager = $sensor_manager;
$this->dateFormatter = $date_formatter;
}
/**
* List all sensors.
*
* @validate-module-enabled monitoring
*
* @command monitoring:list-sensors
* @aliases monitoring-list-sensors
* @field-labels
* label: Label
* name: Name
* category: Category
* enabled: Enabled
* description: Description
* value_info: Value info
* caching_time: Caching time
* has_thresholds: Has thresholds
* @default-fields label,name,category,enabled
*
* @return \Consolidation\OutputFormatters\StructuredData\RowsOfFields
* A list with sensors.
*/
public function sensorConfigAll() {
$sensor_config_list = $this->sensorManager
->getAllSensorConfig();
$rows = [];
foreach ($sensor_config_list as $name => $sensor_config) {
$rows[] = [
'label' => $sensor_config
->label(),
'name' => $name,
'category' => $sensor_config
->getCategory(),
'description' => $sensor_config
->getDescription(),
'value_info' => new FormattableMarkup('type: @type, label: @label, numeric: @numeric', [
'@type' => $sensor_config
->getValueType() ?: dt('N/A'),
'@label' => $sensor_config
->getValueLabel() ?: dt('N/A'),
'@numeric' => $sensor_config
->isNumeric() ? dt('Yes') : dt('No'),
]),
'caching_time' => $this->dateFormatter
->formatInterval($sensor_config
->getCachingTime()),
'enabled' => $sensor_config
->isEnabled() ? dt('Yes') : dt('No'),
'has_thresholds' => $sensor_config
->isDefiningThresholds() ? dt('Yes') : dt('No'),
];
}
return new RowsOfFields($rows);
}
/**
* Displays detailed information about the sensor config.
*
* @param string $sensor_name
* Specific sensor name for which we want to display info.
*
* @usage drush monitoring-sensor-config node_new
* Prints info of the node_new sensor.
* @validate-module-enabled monitoring
*
* @command monitoring:sensor-config
* @aliases monitoring-sensor-config
* @field-labels
* label: Label
* category: Category
* description: Description
* value_info: Value info
* caching_time: Caching time
* enabled: Enabled
* has_thresholds: Has thresholds
*
* @return \Consolidation\OutputFormatters\StructuredData\PropertyList
* A list with sensor config properties.
*/
public function sensorConfig($sensor_name = NULL) {
$sensor_config = $this->sensorManager
->getSensorConfigByName($sensor_name);
$data = [
'label' => $sensor_config
->label(),
'category' => $sensor_config
->getCategory(),
'description' => $sensor_config
->getDescription(),
'value_info' => new FormattableMarkup('type: @type, label: @label, numeric: @numeric', [
'@type' => $sensor_config
->getValueType() ?: dt('N/A'),
'@label' => $sensor_config
->getValueLabel() ?: dt('N/A'),
'@numeric' => $sensor_config
->isNumeric() ? dt('Yes') : dt('No'),
]),
'caching_time' => $this->dateFormatter
->formatInterval($sensor_config
->getCachingTime()),
'enabled' => $sensor_config
->isEnabled() ? dt('Yes') : dt('No'),
'has_thresholds' => $sensor_config
->isDefiningThresholds() ? dt('Yes') : dt('No'),
];
return new PropertyList($data);
}
/**
* Runs all sensors or a specific sensor and provides verbose data.
*
* @param string $sensor_name
* Sensor name to invoke or keep empty to invoke all sensors.
* @param array $options
* An associative array of options whose values come from cli, aliases,
* config, etc.
*
* @option force
* If the sensor execution should be forced in case cached result is
* available.
* @option output
* (deprecated) Use --format for standard outputs and --sensu-output for
* a format suitable for sensu.
* @option expand
* Relevant only for the json output. Currently "sensor" value supported.
* @option sensu-source
* Relevant only for sensu output. The sensu source. Defaults to the
* host name.
* @option sensu-ttl
* Relevant only for sensu output. Sensu TTL (Time to live)
* @option sensu-handlers
* Relevant only for sensu output. A comma separated list of Sensu handlers
* (names).
* @option sensu-metric-handlers
* Relevant only for sensu output. Defaults to the Sensu handlers.
* @option sensu-metrics
* Relevant only for sensu output. Expose numeric sensors additionally as
* metrics. Enabled by default.
* @option sensu-output
* Use this option to format the output for sensu. To get other formats use
* the drush option --format.
*
* @usage drush monitoring-run monitoring_git_dirty_tree
* Runs sensor to monitor the git status.
* @usage drush monitoring-run --verbose monitoring_git_dirty_tree
* Runs sensor to monitor the git status and displays verbose information.
* @usage drush monitoring-run --output=json --watchdog=disable
* Will output the sensor results in json format. The option
* --watchdog=disable will suppress watchdog output to console.
* @usage drush monitoring-run --output=sensu --sensu-source=example.org --sensu-ttl=600 --sensu-handlers=email,pagerduty
* Will output the sensor results in sensu format. The option
* --sensu-source=example.org will provide the sensu source. The option
* --sensu-ttl=600 will provide the sensor 600 seconds time to live.
* @validate-module-enabled monitoring
*
* @command monitoring:run
* @aliases monitoring-run
* @field-labels
* sensor_name: ID
* label: Label
* status: Status
* message: Message
* exec_time: Execution time
* result_age: Result age
* value: Value
* verbose: Verbose
* sensor: Sensor data
*
* @return \Consolidation\AnnotatedCommand\CommandResult
* The result list with exit code.
*/
public function run($sensor_name = NULL, array $options = [
'force' => NULL,
'output' => NULL,
'expand' => NULL,
'show-exec-time' => NULL,
'sensu-source' => NULL,
'sensu-ttl' => NULL,
'sensu-handlers' => NULL,
'sensu-metric-handlers' => NULL,
'sensu-metrics' => true,
]) {
$sensor_names = [];
if (!empty($sensor_name)) {
$sensor_names[] = $sensor_name;
}
$results = monitoring_sensor_run_multiple($sensor_names, $options['force'], $options['verbose']);
$rows = [];
foreach ($results as $key => $result) {
$rows[$key] = [
'sensor_name' => $result
->getSensorId(),
'label' => $result
->getSensorConfig()
->getLabel(),
'status' => $result
->getStatusLabel(),
'message' => $result
->getMessage(),
'exec_time' => $result
->getExecutionTime(),
'result_age' => $this->dateFormatter
->formatInterval(time() - $result
->getTimestamp()),
];
if ($options['format'] != 'table') {
$rows[$key]['value'] = $result
->getValue();
if ($options['expand'] == 'sensor') {
$rows[$key]['sensor'] = $result
->getSensorConfig()
->toArray();
}
}
// Add the verbose output if requested.
if ($verbose_output = $result
->getVerboseOutput()) {
// @todo Improve plaintext rendering for tables(view sensor).
$rows[$key]['verbose'] = strip_tags(\Drupal::service('renderer')
->renderRoot($verbose_output));
}
}
$status = self::SENSOR_STATUS_OK;
foreach ($results as $result) {
if ($status < self::SENSOR_STATUS_CRITICAL && $result
->isCritical()) {
$status = self::SENSOR_STATUS_CRITICAL;
// We already have the highest status so we can stop looping now.
break;
}
if ($status < self::SENSOR_STATUS_UNKNOWN && $result
->isUnknown()) {
$status = self::SENSOR_STATUS_UNKNOWN;
}
elseif ($status < self::SENSOR_STATUS_WARNING && $result
->isWarning()) {
$status = self::SENSOR_STATUS_WARNING;
}
}
if ($options['output'] == 'sensu' || $options['sensu-output']) {
$source = $options['sensu-source'] ?: \Drupal::request()
->getHost();
$ttl = (int) $options['sensu-ttl'];
$handlers = explode(',', $options['sensu-handlers']);
$metric_handlers = explode(',', $options['sensu-metric-handlers']);
$this
->outputSensuFormat($results, $source, $ttl, $handlers, $metric_handlers, $options['sensu-metrics']);
return CommandResult::exitCode($status);
}
elseif ($options['output'] && $options['output'] !== 'sensu') {
$this
->logger()
->error(dt('Unsupported output option @output. Use the --format option to specify formatting options.', [
'@output' => $options['output'],
]));
return CommandResult::exitCode(MONITORING_DRUSH_SENSOR_STATUS_UNKNOWN);
}
return CommandResult::dataWithExitCode(new RowsOfFields($rows), $status);
}
/**
* Enable specified monitoring sensor.
*
* @param string $sensor_name
* Sensor name to enable.
*
* @usage drush monitoring-enable monitoring_git_dirty_tree
* Enables monitoring_git_dirty_tree sensor.
* @validate-module-enabled monitoring
*
* @command monitoring:enable
* @aliases monitoring-enable
*/
public function enable($sensor_name) {
$sensor_config = $this->sensorManager
->getSensorConfigByName($sensor_name);
if ($sensor_config
->isEnabled()) {
$message = dt('The sensor @name is already enabled.', [
'@name' => $sensor_config
->label(),
]);
$this
->logger()
->notice($message);
return;
}
$this->sensorManager
->enableSensor($sensor_name);
$message = dt('The sensor @name was enabled.', [
'@name' => $sensor_config
->label(),
]);
/* @noinspection PhpUndefinedMethodInspection */
$this
->logger()
->success($message);
}
/**
* Disable specified monitoring sensor.
*
* @param string $sensor_name
* Sensor name to disable.
*
* @usage drush monitoring-disable monitoring_git_dirty_tree
* Disables monitoring_git_dirty_tree sensor.
* @validate-module-enabled monitoring
*
* @command monitoring:disable
* @aliases monitoring-disable
*/
public function disable($sensor_name) {
$sensor_config = $this->sensorManager
->getSensorConfigByName($sensor_name);
if (!$sensor_config
->isEnabled()) {
$message = dt('The sensor @name is already disabled.', [
'@name' => $sensor_config
->label(),
]);
$this
->logger()
->notice($message);
return;
}
$this->sensorManager
->disableSensor($sensor_name);
$message = dt('The sensor @name was disabled.', [
'@name' => $sensor_config
->label(),
]);
/* @noinspection PhpUndefinedMethodInspection */
$this
->logger()
->success($message);
}
/**
* Rebuild the list of sensors.
*
* @validate-module-enabled monitoring
*
* @command monitoring:rebuild
* @aliases monitoring-rebuild
*/
public function rebuild() {
$this->sensorManager
->rebuildSensors();
/* @noinspection PhpUndefinedMethodInspection */
$this
->logger()
->success(dt('Sensors rebuilt.'));
}
/**
* Results output in sensu format.
*
* @param \Drupal\monitoring\Result\SensorResultInterface[] $results
* List of sensor result objects.
* @param string $source
* Sensu source.
* @param int $ttl
* Sensor time to live.
* @param array $handlers
* Sensu handlers.
* @param array $metric_handlers
* Sensu metric handlers.
* @param bool $metrics
* Sensu metrics.
*/
protected function outputSensuFormat(array $results, $source, $ttl, array $handlers, array $metric_handlers, $metrics) {
$status_codes = [
SensorResultInterface::STATUS_OK => 0,
SensorResultInterface::STATUS_WARNING => 1,
SensorResultInterface::STATUS_CRITICAL => 2,
SensorResultInterface::STATUS_UNKNOWN => 3,
SensorResultInterface::STATUS_INFO => 0,
];
foreach ($results as $name => $result) {
// Build sensu check result.
$sensu_output = [];
$sensu_output['name'] = $name;
$sensu_output['status'] = $status_codes[$result
->getStatus()];
if ($ttl) {
$sensu_output['ttl'] = $ttl;
}
if ($handlers) {
$sensu_output['handlers'] = $handlers;
}
$sensu_output['output'] = $result
->getMessage();
$sensu_output['interval'] = $result
->getSensorConfig()
->getCachingTime();
$sensu_output['duration'] = $result
->getExecutionTime() / 1000;
$sensu_output['source'] = $source;
$this
->output()
->writeln(Json::encode($sensu_output));
// Also print numeric sensors as metrics, if enabled.
if ($result
->getSensorConfig()
->isNumeric() && $metrics) {
$sensu_metric_output = $sensu_output;
$sensu_metric_output['name'] = $name . '_metric';
$sensu_metric_output['type'] = 'metric';
if ($metric_handlers) {
$sensu_metric_output['handlers'] = $metric_handlers;
}
// Build the metrics data.
$reversed_source = implode('.', array_reverse(explode('.', $sensu_output['source'])));
$value = $result
->getValue();
$executed = $result
->getTimestamp();
$sensu_metric_output['output'] = $reversed_source . '.' . $name . ' ' . $value . ' ' . $executed;
$this
->output()
->writeln(Json::encode($sensu_metric_output));
}
}
}
}
Classes
Name | Description |
---|---|
MonitoringCommands | A Drush commandfile for the Monitoring module. |