2015-03-30 12:16:56 +01:00
< ? php
2017-12-24 21:55:24 +02:00
/*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version. Please see LICENSE.txt at the top level of
* the source code distribution for details.
*
* @package LibreNMS
* @subpackage graphs
2021-02-09 00:29:04 +01:00
* @link https://www.librenms.org
2018-03-25 22:50:09 +02:00
* @copyright 2018 LibreNMS
2017-12-24 21:55:24 +02:00
* @author LibreNMS Contributors
*/
2017-03-24 22:06:09 +00:00
$where = ' `devices`.`disabled` = 0' ;
2019-12-30 12:11:26 +01:00
$param = [];
2016-01-19 16:38:41 -07:00
$alert_states = [
// divined from librenms/alerts.php
'recovered' => 0 ,
'alerted' => 1 ,
'acknowledged' => 2 ,
'worse' => 3 ,
2017-10-15 12:50:55 -06:00
'better' => 4 ,
2016-01-19 16:38:41 -07:00
];
2016-08-18 20:28:22 -05:00
$show_recovered = false ;
2016-01-21 12:51:49 -07:00
2021-10-06 07:29:47 -05:00
if ( is_numeric ( $vars [ 'alert_id' ]) && $vars [ 'alert_id' ] > 0 ) {
$where .= ' AND `alerts`.`id` = ?' ;
$param [] = $vars [ 'alert_id' ];
}
2018-03-25 22:50:09 +02:00
if ( is_numeric ( $vars [ 'device_id' ]) && $vars [ 'device_id' ] > 0 ) {
$where .= ' AND `alerts`.`device_id`=' . $vars [ 'device_id' ];
2015-03-30 12:16:56 +01:00
}
2018-03-25 22:50:09 +02:00
if ( is_numeric ( $vars [ 'acknowledged' ])) {
2016-01-19 16:38:41 -07:00
// I assume that if we are searching for acknowleged/not, we aren't interested in recovered
2018-03-25 22:50:09 +02:00
$where .= ' AND `alerts`.`state`' . ( $vars [ 'acknowledged' ] ? '=' : '!=' ) . $alert_states [ 'acknowledged' ];
2016-01-19 16:38:41 -07:00
}
2018-05-16 05:54:02 +10:00
if ( is_numeric ( $vars [ 'fired' ])) {
$where .= ' AND `alerts`.`alerted`=' . $alert_states [ 'alerted' ];
}
2022-01-20 15:15:23 +01:00
if ( is_numeric ( $vars [ 'unreachable' ])) {
// Sub-select to flag if at least one parent is set, and all parents are offline
$where .= ' AND (SELECT IF(COUNT(`dr`.`parent_device_id`) > 0 AND COUNT(`dr`.`parent_device_id`)=count(`d`.`device_id`),1,0) FROM `device_relationships` `dr` LEFT JOIN `devices` `d` ON `dr`.`parent_device_id`=`d`.`device_id` AND `d`.`status`=0 WHERE `dr`.`child_device_id`=`devices`.`device_id`)=' . $vars [ 'unreachable' ];
}
2018-03-25 22:50:09 +02:00
if ( is_numeric ( $vars [ 'state' ])) {
$where .= ' AND `alerts`.`state`=' . $vars [ 'state' ];
if ( $vars [ 'state' ] == $alert_states [ 'recovered' ]) {
2016-08-18 20:28:22 -05:00
$show_recovered = true ;
2016-01-21 12:51:49 -07:00
}
2016-01-19 16:38:41 -07:00
}
2018-03-25 22:50:09 +02:00
if ( isset ( $vars [ 'min_severity' ])) {
2019-12-16 23:58:54 +01:00
$where .= get_sql_filter_min_severity ( $vars [ 'min_severity' ], 'alert_rules' );
2016-01-19 16:38:41 -07:00
}
2018-03-25 22:50:09 +02:00
if ( is_numeric ( $vars [ 'group' ])) {
2016-09-18 19:08:33 -05:00
$where .= ' AND devices.device_id IN (SELECT `device_id` FROM `device_group_device` WHERE `device_group_id` = ?)' ;
2018-03-25 22:50:09 +02:00
$param [] = $vars [ 'group' ];
2016-01-21 12:51:49 -07:00
}
if ( ! $show_recovered ) {
2017-12-24 21:55:24 +02:00
$where .= ' AND `alerts`.`state`!=' . $alert_states [ 'recovered' ];
2016-01-21 12:51:49 -07:00
}
2015-03-30 12:16:56 +01:00
if ( isset ( $searchPhrase ) && ! empty ( $searchPhrase )) {
2020-11-21 06:13:59 +02:00
$where .= ' AND (`alerts`.`timestamp` LIKE ? OR `rule` LIKE ? OR `name` LIKE ? OR `hostname` LIKE ? OR `sysName` LIKE ?)' ;
2020-07-10 16:17:09 +02:00
$param [] = " % $searchPhrase % " ;
$param [] = " % $searchPhrase % " ;
$param [] = " % $searchPhrase % " ;
$param [] = " % $searchPhrase % " ;
$param [] = " % $searchPhrase % " ;
2015-03-30 12:16:56 +01:00
}
2015-07-07 23:18:57 +01:00
$sql = ' FROM `alerts` LEFT JOIN `devices` ON `alerts`.`device_id`=`devices`.`device_id`' ;
2019-08-05 14:16:05 -05:00
if ( ! Auth :: user () -> hasGlobalRead ()) {
2019-12-30 12:11:26 +01:00
$device_ids = Permissions :: devicesForUser () -> toArray () ? : [ 0 ];
2020-01-15 16:59:24 +01:00
$where .= ' AND `devices`.`device_id` IN ' . dbGenPlaceholders ( count ( $device_ids ));
2019-12-30 12:11:26 +01:00
$param = array_merge ( $param , $device_ids );
2015-07-07 23:18:57 +01:00
}
2019-03-19 04:07:05 -06:00
$sql .= ' LEFT JOIN `locations` ON `devices`.`location_id` = `locations`.`id`' ;
2016-01-21 12:51:49 -07:00
$sql .= " RIGHT JOIN `alert_rules` ON `alerts`.`rule_id`=`alert_rules`.`id` WHERE $where " ;
2015-03-30 12:16:56 +01:00
$count_sql = " SELECT COUNT(`alerts`.`id`) $sql " ;
2017-12-24 21:55:24 +02:00
$total = dbFetchCell ( $count_sql , $param );
2015-04-12 11:47:21 +01:00
if ( empty ( $total )) {
$total = 0 ;
}
2015-03-30 12:16:56 +01:00
2018-07-12 22:48:18 +02:00
if ( ! isset ( $vars [ 'sort' ]) || empty ( $vars [ 'sort' ])) {
2015-03-30 12:16:56 +01:00
$sort = 'timestamp DESC' ;
2018-07-12 22:48:18 +02:00
} else {
2018-08-11 23:41:40 +02:00
$sort = '`alert_rules`.`severity` DESC, timestamp DESC' ;
2015-03-30 12:16:56 +01:00
}
$sql .= " ORDER BY $sort " ;
if ( isset ( $current )) {
2023-03-13 20:35:14 +00:00
$limit_low = (( $current * $rowCount ) - $rowCount );
2015-03-30 12:16:56 +01:00
$limit_high = $rowCount ;
}
if ( $rowCount != - 1 ) {
$sql .= " LIMIT $limit_low , $limit_high " ;
}
2021-11-18 15:46:22 -06:00
$sql = " SELECT `alerts`.*, `devices`.`hostname`, `devices`.`sysName`, `devices`.`display`, `devices`.`os`, `devices`.`hardware`, `locations`.`location`, `alert_rules`.`rule`, `alert_rules`.`name`, `alert_rules`.`severity` $sql " ;
2015-03-30 12:16:56 +01:00
2017-12-24 21:55:24 +02:00
$rulei = 0 ;
2018-03-25 22:50:09 +02:00
$format = $vars [ 'format' ];
2015-03-30 12:16:56 +01:00
foreach ( dbFetchRows ( $sql , $param ) as $alert ) {
2017-12-24 21:55:24 +02:00
$log = dbFetchCell ( 'SELECT details FROM alert_log WHERE rule_id = ? AND device_id = ? ORDER BY id DESC LIMIT 1' , [ $alert [ 'rule_id' ], $alert [ 'device_id' ]]);
2021-03-06 20:57:06 +00:00
$alert_log_id = dbFetchCell ( 'SELECT id FROM alert_log WHERE rule_id = ? AND device_id = ? ORDER BY id DESC LIMIT 1' , [ $alert [ 'rule_id' ], $alert [ 'device_id' ]]);
2021-10-03 01:12:18 +02:00
[ $fault_detail , $max_row_length ] = alert_details ( $log );
2018-09-19 23:38:01 +01:00
$info = json_decode ( $alert [ 'info' ], true );
2015-03-30 12:16:56 +01:00
2018-09-19 23:38:01 +01:00
$alert_to_ack = '<button type="button" class="btn btn-danger command-ack-alert fa fa-eye" aria-hidden="true" title="Mark as acknowledged" data-target="ack-alert" data-state="' . $alert [ 'state' ] . '" data-alert_id="' . $alert [ 'id' ] . '" data-alert_state="' . $alert [ 'state' ] . '" name="ack-alert"></button>' ;
$alert_to_nack = '<button type="button" class="btn btn-primary command-ack-alert fa fa-eye-slash" aria-hidden="true" title="Mark as not acknowledged" data-target="ack-alert" data-state="' . $alert [ 'state' ] . '" data-alert_id="' . $alert [ 'id' ] . '" data-alert_state="' . $alert [ 'state' ] . '" name="ack-alert"></button>' ;
$alert_to_unack = '<button type="button" class="btn btn-primary command-ack-alert fa fa-eye" aria-hidden="true" title="Mark as not acknowledged" data-target="ack-alert" data-state="' . $alert [ 'state' ] . '" data-alert_id="' . $alert [ 'id' ] . '" data-alert_state="' . $alert [ 'state' ] . '" name="ack-alert"></button>' ;
2017-12-27 05:29:28 +00:00
$ack_ico = $alert_to_ack ;
2017-12-24 21:55:24 +02:00
if (( int ) $alert [ 'state' ] === 0 ) {
$msg = '' ;
} elseif (( int ) $alert [ 'state' ] === 1 || ( int ) $alert [ 'state' ] === 3 || ( int ) $alert [ 'state' ] === 4 ) {
if (( int ) $alert [ 'state' ] === 3 ) {
$msg = '<i class="fa fa-angle-double-down" style="font-size:20px;" aria-hidden="true" title="Status got worse"></i>' ;
} elseif (( int ) $alert [ 'state' ] === 4 ) {
$msg = '<i class="fa fa-angle-double-up" style="font-size:20px;" aria-hidden="true" title="Status got better"></i>' ;
2015-03-31 18:47:10 +01:00
}
2017-12-24 21:55:24 +02:00
} elseif (( int ) $alert [ 'state' ] === 2 ) {
2018-09-19 23:38:01 +01:00
if ( $info [ 'until_clear' ] === false ) {
$ack_ico = $alert_to_unack ;
} else {
$ack_ico = $alert_to_nack ;
}
2017-12-24 21:55:24 +02:00
}
2015-03-30 12:16:56 +01:00
2023-03-13 20:35:14 +00:00
$hostname = '<div class="incident">' . generate_device_link ( $alert , shorthost ( format_hostname ( $alert ))) . '<div id="incident' . $alert [ 'id' ] . '"' ;
2021-10-03 01:12:18 +02:00
if ( is_numeric ( $vars [ 'uncollapse_key_count' ])) {
$hostname .= $max_row_length < ( int ) $vars [ 'uncollapse_key_count' ] ? '' : ' class="collapse"' ;
} else {
$hostname .= ' class="collapse"' ;
}
$hostname .= '>' . $fault_detail . '</div></div>' ;
2017-12-24 21:55:24 +02:00
2019-12-05 15:51:58 +01:00
$severity = $alert [ 'severity' ];
2020-03-01 15:50:45 +01:00
$severity_ico = '<span class="alert-status label-' . alert_layout ( $severity )[ 'background_color' ] . '"> </span>' ;
2015-03-30 12:16:56 +01:00
2019-12-05 15:51:58 +01:00
if ( $alert [ 'state' ] == 3 ) {
$severity .= ' <strong>+</strong>' ;
} elseif ( $alert [ 'state' ] == 4 ) {
$severity .= ' <strong>-</strong>' ;
}
2017-12-27 05:29:28 +00:00
if (( int ) $alert [ 'state' ] === 2 ) {
2018-04-26 06:00:56 +01:00
$severity_ico = '<span class="alert-status label-primary"> </span>' ;
2017-12-27 05:29:28 +00:00
}
2017-12-24 21:55:24 +02:00
$proc = dbFetchCell ( 'SELECT proc FROM alerts,alert_rules WHERE alert_rules.id = alerts.rule_id AND alerts.id = ?' , [ $alert [ 'id' ]]);
if (( $proc == '' ) || ( $proc == 'NULL' )) {
$has_proc = '' ;
} else {
if ( ! preg_match ( '/^http[s]*:\/\//' , $proc )) {
$has_proc = '' ;
} else {
$has_proc = '<a href="' . $proc . '" target="_blank"><button type="button" class="btn btn-info fa fa-external-link" aria-hidden="true"></button></a>' ;
}
}
2015-07-13 20:10:26 +02:00
2018-04-26 06:00:56 +01:00
if ( empty ( $alert [ 'note' ])) {
$note_class = 'default' ;
} else {
$note_class = 'warning' ;
}
2015-04-23 15:07:55 +00:00
$response [] = [
2017-12-24 21:55:24 +02:00
'id' => $rulei ++ ,
2021-03-28 17:25:30 -05:00
'rule' => '<i title="' . htmlentities ( $alert [ 'rule' ]) . '"><a href="' . \LibreNMS\Util\Url :: generate ([ 'page' => 'alert-rules' ]) . '">' . htmlentities ( $alert [ 'name' ]) . '</a></i>' ,
2023-03-13 20:35:14 +00:00
'details' => '<a class="fa-solid fa-plus incident-toggle" style="display:none" data-toggle="collapse" data-target="#incident' . $alert [ 'id' ] . '" data-parent="#alerts"></a>' ,
2022-11-04 23:13:36 -05:00
'verbose_details' => " <button type='button' class='btn btn-alert-details command-alert-details' aria-label='Details' id='alert-details' data-alert_log_id=' { $alert_log_id } '><i class='fa-solid fa-circle-info'></i></button> " ,
2017-12-24 21:55:24 +02:00
'hostname' => $hostname ,
2019-07-19 00:24:24 -04:00
'location' => generate_link ( $alert [ 'location' ], [ 'page' => 'devices' , 'location' => $alert [ 'location' ]]),
2015-03-30 12:16:56 +01:00
'timestamp' => ( $alert [ 'timestamp' ] ? $alert [ 'timestamp' ] : 'N/A' ),
2017-12-24 21:55:24 +02:00
'severity' => $severity_ico ,
'state' => $alert [ 'state' ],
'alert_id' => $alert [ 'id' ],
'ack_ico' => $ack_ico ,
'proc' => $has_proc ,
2018-04-26 06:00:56 +01:00
'notes' => " <button type='button' class='btn btn- $note_class fa fa-sticky-note-o command-alert-note' aria-label='Notes' id='alert-notes' data-alert_id=' { $alert [ 'id' ] } '></button> " ,
2015-03-31 18:47:10 +01:00
];
2017-12-24 21:55:24 +02:00
}
2015-07-13 20:10:26 +02:00
2015-03-30 12:16:56 +01:00
$output = [
2017-12-24 21:55:24 +02:00
'current' => $current ,
2015-03-30 12:16:56 +01:00
'rowCount' => $rowCount ,
2017-12-24 21:55:24 +02:00
'rows' => $response ,
'total' => $total ,
2015-03-30 12:16:56 +01:00
];
2021-03-04 07:55:41 -06:00
echo json_encode ( $output , JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE );