Files
librenms-librenms/includes/polling/applications/sneck.inc.php
Zane C. Bowers-Hadley 5da8e70bf4 add Sneck support, making it very trivial to use Nagios style checks in a NRPE like manner (#13954)
* code stuff done for Sneck

* whoops, correct the abs value post adding it post rrd update

* return a array for getting the sneck data and nicely print the raw return value

* add test stuff and freeze time at 1650911765 for tests

* move the freezeTime

* add use Illuminate\Support\Carbon;

* more test changes

* rework freezeTime a bit more

* more test stuff

* another test

* rework it a bit again

* correct variable spelling for $time_diff

* remove freezeTime as we are using a old version of Laravel

* finalize graphs

* misc

* finalize sneck page

* mve the sneck tests as it needs a newer version of laravel than we are using

* add documents for sneck

* finalize the poller

* formatting cleanup

* correct comment type

* correct the spelling of description

* more documentation

* save the check returns as metrics

* add some more examples

* fix some of the sneck alerts and add a few more examples

* turn off time to polling by default

* suggest using ntp if enabled

* since we are zeroing time_to_polling by default, this now works

* backout some suggested changes for once we change to larval 9

* remove del_sneck_data as it is no longer used

* add more docs on the metrics

* php-cs-fixer to fix a few things

* update and fix sneck tests

* remote a metric from the test

* another minor tweak to the test

* one more minor change

* ahh! derp! think I found it finally... hopefully hanging this for the last time...

* now use app data

* now logs check changes

* add a missing )

* add a missing )

* some style fixes

* update the sneck page use to the app data stuff

* update the poller to use the new app data

* misc

* update sneck to log check status changes

* correct alert log messages

* correct a comment

* fix metrics

* derp, another fix

* test fix

* re-order to avoid warning

* poller update

* update sneck graphs

* update sneck graphs

* remove a unneeded line

* test update for discovery

* minor tweaks to the test and fix update the polling a bit

* style fix

* fix return data printing

* fix the test data to include app data

* attempted test fix

* add config def to apps.sneck.polling_time_diff

* cleanup docs a bit

* minor config tweaks

* minor doc cleanup
2023-06-15 09:06:28 -05:00

160 lines
5.3 KiB
PHP

<?php
use Carbon\Carbon;
use LibreNMS\Config;
use LibreNMS\Exceptions\JsonAppException;
use LibreNMS\RRD\RrdDefinition;
$name = 'sneck';
$old_checks = [];
$old_checks_data = [];
if (isset($app->data['data']) && isset($app->data['data']['checks'])) {
$old_checks = array_keys($app->data['data']['checks']);
$old_checks_data = $app->data['data']['checks'];
}
if (Config::has('apps.sneck.polling_time_diff')) {
$compute_time_diff = Config::get('apps.sneck.polling_time_diff');
} else {
$compute_time_diff = false;
}
try {
$json_return = json_app_get($device, $name, 1);
} catch (JsonAppException $e) {
echo PHP_EOL . $name . ':' . $e->getCode() . ':' . $e->getMessage() . PHP_EOL;
// Set empty metrics and error message
update_application($app, $e->getCode() . ':' . $e->getMessage(), []);
return;
}
$app->data = $json_return;
$new_checks = [];
if (isset($json_return['data']) and isset($json_return['data']['checks'])) {
$new_checks = array_keys($json_return['data']['checks']);
}
$rrd_name = ['app', $name, $app->app_id];
$rrd_def = RrdDefinition::make()
->addDataset('time', 'DERIVE', 0)
->addDataset('time_to_polling', 'GAUGE', 0)
->addDataset('ok', 'GAUGE', 0)
->addDataset('warning', 'GAUGE', 0)
->addDataset('critical', 'GAUGE', 0)
->addDataset('unknown', 'GAUGE', 0)
->addDataset('errored', 'GAUGE', 0);
// epoch off set between poller and when the when the JSON was generated
// only compueted if
if ($compute_time_diff) {
$time_to_polling = Carbon::now()->timestamp - $json_return['data']['time'];
} else {
$time_to_polling = 0;
}
$fields = [
'time' => $json_return['data']['time'],
'time_to_polling' => $time_to_polling,
'ok' => $json_return['data']['ok'],
'warning' => $json_return['data']['warning'],
'critical' => $json_return['data']['critical'],
'unknown' => $json_return['data']['unknown'],
'errored' => $json_return['data']['errored'],
];
$tags = ['name' => $name, 'app_id' => $app->app_id, 'rrd_def' => $rrd_def, 'rrd_name' => $rrd_name];
data_update($device, 'app', $tags, $fields);
// save the return status for each alerting possibilities
foreach ($json_return['data']['checks'] as $key => $value) {
$fields['check_' . $key] = $value['exit'];
}
$fields['time_to_polling_abs'] = abs($time_to_polling);
if (abs($time_to_polling) > 540) {
$json_return['data']['alertString'] = $json_return['data']['alertString'] . "\nGreater than 540 seconds since the polled data was generated";
$json_return['data']['alert'] = 1;
}
//check for added checks
$added_checks = array_values(array_diff($new_checks, $old_checks));
//check for removed checks
$removed_checks = array_values(array_diff($old_checks, $new_checks));
// if we have any check changes, log it
if (sizeof($added_checks) > 0 || sizeof($removed_checks) > 0) {
$log_message = 'Sneck Check Change:';
$log_message .= count($added_checks) > 0 ? ' Added ' . json_encode($added_checks) : '';
$log_message .= count($removed_checks) > 0 ? ' Removed ' . json_encode($added_checks) : '';
log_event($log_message, $device, 'application');
}
// go through and looking for status changes
$cleared = [];
$warned = [];
$alerted = [];
$unknowned = [];
foreach ($new_checks as $check) {
if (isset($old_checks_data[$check]) && isset($old_checks_data[$check]['exit']) && isset($old_checks_data[$check]['output'])) {
if ($json_return['data']['checks'][$check]['exit'] != $app->data['data']['checks'][$check]['exit']) {
$check_output = $json_return['data']['checks'][$check]['output'];
$exit_code = $json_return['data']['checks'][$check]['exit'];
if ($exit_code == 1) {
$warned[$check] = $check_output;
} elseif ($exit_code == 2) {
$alerted[$check] = $check_output;
} elseif ($exit_code >= 3) {
$unknowned[$check] = $check_output;
} elseif ($exit_code == 0) {
$cleared[$check] = $check_output;
}
}
} else {
if (isset($json_return['data']['checks'][$check]['exit']) && isset($json_return['data']['checks'][$check]['output'])) {
$check_output = $json_return['data']['checks'][$check]['output'];
$exit_code = $json_return['data']['checks'][$check]['exit'];
if ($exit_code == 1) {
$warned[$check] = $check_output;
} elseif ($exit_code == 2) {
$alerted[$check] = $check_output;
} elseif ($exit_code >= 3) {
$unknowned[$check] = $check_output;
}
}
}
}
// log any clears
if (sizeof($cleared) > 0) {
$log_message = 'Sneck Check Clears: ' . json_encode($cleared);
log_event($log_message, $device, 'application', 1);
}
// log any warnings
if (sizeof($warned) > 0) {
$log_message = 'Sneck Check Warns: ' . json_encode($warned);
log_event($log_message, $device, 'application', 4);
}
// log any alerts
if (sizeof($alerted) > 0) {
$log_message = 'Sneck Check Alerts: ' . json_encode($alerted);
log_event($log_message, $device, 'application', 5);
}
// log any unknowns
if (sizeof($unknowned) > 0) {
$log_message = 'Sneck Check Unknowns: ' . json_encode($unknownwed);
log_event($log_message, $device, 'application', 6);
}
// update it here as we are done with this mostly
update_application($app, 'OK', $fields);