diff --git a/pandora_console/extras/mr/37.sql b/pandora_console/extras/mr/37.sql
index 9f240d889d..c53f5e3c09 100644
--- a/pandora_console/extras/mr/37.sql
+++ b/pandora_console/extras/mr/37.sql
@@ -1,5 +1,9 @@
START TRANSACTION;
+ALTER TABLE `tagente_estado` ADD COLUMN `last_status_change` bigint(20) NOT NULL default '0';
+
+UPDATE `tconfig` SET `value`='policy,agent,data_type,module_name,server_type,interval,status,last_status_change,graph,warn,data,timestamp' WHERE `token` = 'status_monitor_fields';
+
ALTER TABLE `talert_templates` ADD COLUMN `disable_event` tinyint(1) DEFAULT 0;
ALTER TABLE `tevent_alert` ADD COLUMN `disable_event` tinyint(1) DEFAULT 0;
ALTER TABLE `talert_snmp` ADD COLUMN `disable_event` tinyint(1) DEFAULT 0;
diff --git a/pandora_console/extras/pandoradb_migrate_6.0_to_7.0.mysql.sql b/pandora_console/extras/pandoradb_migrate_6.0_to_7.0.mysql.sql
index 9236f7a5d8..093258fe43 100644
--- a/pandora_console/extras/pandoradb_migrate_6.0_to_7.0.mysql.sql
+++ b/pandora_console/extras/pandoradb_migrate_6.0_to_7.0.mysql.sql
@@ -1287,6 +1287,7 @@ ALTER TABLE `tagente_estado` MODIFY COLUMN `datos` mediumtext NOT NULL,
MODIFY COLUMN `last_known_status` tinyint(4) NULL DEFAULT '0',
MODIFY COLUMN `last_dynamic_update` bigint(20) NOT NULL DEFAULT '0',
MODIFY COLUMN `last_unknown_update` bigint(20) NOT NULL DEFAULT '0';
+ALTER TABLE `tagente_estado` ADD COLUMN `last_status_change` bigint(20) NOT NULL DEFAULT '0';
-- ---------------------------------------------------------------------
-- Table `talert_actions`
diff --git a/pandora_console/godmode/agentes/status_monitor_custom_fields.php b/pandora_console/godmode/agentes/status_monitor_custom_fields.php
index 7e9ae48bdd..ed52959a09 100644
--- a/pandora_console/godmode/agentes/status_monitor_custom_fields.php
+++ b/pandora_console/godmode/agentes/status_monitor_custom_fields.php
@@ -97,6 +97,10 @@ if ($fields_selected[0] != '') {
$result = __('Status');
break;
+ case 'last_status_change':
+ $result = __('Last status change');
+ break;
+
case 'graph':
$result = __('Graph');
break;
@@ -112,10 +116,6 @@ if ($fields_selected[0] != '') {
case 'timestamp':
$result = __('Timestamp');
break;
-
- case 'to_critical':
- $result = __('Last status change');
- break;
}
$result_selected[$field_selected] = $result;
@@ -146,11 +146,11 @@ $fields_available['module_name'] = __('Module name');
$fields_available['server_type'] = __('Server type');
$fields_available['interval'] = __('Interval');
$fields_available['status'] = __('Status');
+$fields_available['last_status_change'] = __('Last status change');
$fields_available['graph'] = __('Graph');
$fields_available['warn'] = __('Warn');
$fields_available['data'] = __('Data');
$fields_available['timestamp'] = __('Timestamp');
-$fields_available['to_critical'] = __('Last status change');
// remove fields already selected
foreach ($fields_available as $key => $available) {
diff --git a/pandora_console/include/ajax/module.php b/pandora_console/include/ajax/module.php
index 952ee9ee54..10587df2dc 100755
--- a/pandora_console/include/ajax/module.php
+++ b/pandora_console/include/ajax/module.php
@@ -1028,7 +1028,10 @@ if (check_login()) {
$title
);
- $data[5] = ui_print_status_image($status, htmlspecialchars($title), true);
+ $last_status_change_text = 'Time elapsed since last status change: ';
+ $last_status_change_text .= !empty($module['last_status_change']) ? human_time_comparation($module['last_status_change']) : __('N/A');
+
+ $data[5] = ui_print_status_image($status, htmlspecialchars($title), true, false, false, false, $last_status_change_text);
if (!$show_context_help_first_time) {
$show_context_help_first_time = true;
diff --git a/pandora_console/include/functions_agents.php b/pandora_console/include/functions_agents.php
index 7548843ce8..570e245bd7 100644
--- a/pandora_console/include/functions_agents.php
+++ b/pandora_console/include/functions_agents.php
@@ -3622,3 +3622,25 @@ function agents_get_sap_agents($id_agent)
return false;
}
+
+
+/**
+ * Return time at which last status change of a module occured.
+ *
+ * @param integer $id_agent.
+ * @return string timestamp.
+ */
+function agents_get_last_status_change($id_agent)
+{
+ $sql = sprintf(
+ 'SELECT *
+ FROM tagente_estado
+ WHERE id_agente = %d
+ ORDER BY last_status_change DESC',
+ $id_agent
+ );
+
+ $row = db_get_row_sql($sql);
+
+ return $row['last_status_change'];
+}
diff --git a/pandora_console/include/functions_treeview.php b/pandora_console/include/functions_treeview.php
index c7efb25f60..bb28926b33 100755
--- a/pandora_console/include/functions_treeview.php
+++ b/pandora_console/include/functions_treeview.php
@@ -325,6 +325,14 @@ function treeview_printModuleTable($id_module, $server_data=false, $no_head=fals
$row['data'] = $last_data_str;
$table->data['last_data'] = $row;
+ // Last status change.
+ $last_status_change = db_get_value('last_status_change', 'tagente_estado', 'id_agente_modulo', $module['id_agente_modulo']);
+ $row = [];
+ $row['title'] = __('Last status change');
+ $time_elapsed = ($last_status_change > 0) ? human_time_comparation($last_status_change) : __('N/A');
+ $row['data'] = $time_elapsed;
+ $table->data['tags'] = $row;
+
// End of table
html_print_table($table);
diff --git a/pandora_console/include/functions_ui.php b/pandora_console/include/functions_ui.php
index 013022b595..be050beb4a 100755
--- a/pandora_console/include/functions_ui.php
+++ b/pandora_console/include/functions_ui.php
@@ -2654,6 +2654,7 @@ function ui_get_status_images_path()
* @param array $options Options to set image attributes: I.E.: style.
* @param string $path Path of the image, if not provided use the status path.
* @param boolean $image_with_css Don't use an image. Draw an image with css styles.
+ * @param string $extra_text Text that is displayed after title (i.e. time elapsed since last status change of module).
*
* @return string HTML code if return parameter is true.
*/
@@ -2663,7 +2664,8 @@ function ui_print_status_image(
$return=false,
$options=false,
$path=false,
- $image_with_css=false
+ $image_with_css=false,
+ $extra_info=''
) {
if ($path === false) {
$imagepath_array = ui_get_status_images_path();
@@ -2680,7 +2682,7 @@ function ui_print_status_image(
if ($image_with_css === true) {
$shape_status = get_shape_status_set($type);
- return ui_print_status_sets($type, $title, $return, $shape_status);
+ return ui_print_status_sets($type, $title, $return, $shape_status, $extra_info);
} else {
if ($options === false) {
$options = [];
@@ -2768,10 +2770,11 @@ function get_shape_status_set($type)
/**
* Prints an image representing a status.
*
- * @param string $status Module status.
- * @param string $title Title.
- * @param boolean $return Whether to return an output string or echo now (optional, echo by default).
- * @param array $options Options to set image attributes: I.E.: style.
+ * @param string $status Module status.
+ * @param string $title Title.
+ * @param boolean $return Whether to return an output string or echo now (optional, echo by default).
+ * @param array $options Options to set image attributes: I.E.: style.
+ * @param string $extra_info Text that is displayed after title (i.e. time elapsed since last status change of module).
*
* @return string HTML.
*/
@@ -2779,7 +2782,8 @@ function ui_print_status_sets(
$status,
$title='',
$return=false,
- $options=false
+ $options=false,
+ $extra_info=''
) {
global $config;
@@ -2798,8 +2802,8 @@ function ui_print_status_sets(
}
if ($title != '') {
- $options['title'] = $title;
- $options['data-title'] = $title;
+ $options['title'] = empty($extra_info) ? $title : $title.'
'.$extra_info;
+ $options['data-title'] = empty($extra_info) ? $title : $title.'
'.$extra_info;
$options['data-use_title_for_force_title'] = 1;
if (isset($options['class'])) {
$options['class'] .= ' forced_title';
diff --git a/pandora_console/operation/agentes/estado_generalagente.php b/pandora_console/operation/agentes/estado_generalagente.php
index 4ecd610c43..b7ad228a44 100755
--- a/pandora_console/operation/agentes/estado_generalagente.php
+++ b/pandora_console/operation/agentes/estado_generalagente.php
@@ -368,6 +368,14 @@ if (enterprise_installed()) {
$table_contact->data[] = $data;
}
+$data = [];
+$data[0] = ''.__('Last status change').'';
+$last_status_change_agent = agents_get_last_status_change($agent['id_agente']);
+$time_elapsed = !empty($last_status_change_agent) ? human_time_comparation($last_status_change_agent) : ''.__('N/A').'';
+$data[1] = $time_elapsed;
+
+$table_contact->data[] = $data;
+
/*
* END: TABLE CONTACT BUILD
*/
diff --git a/pandora_console/operation/agentes/status_monitor.php b/pandora_console/operation/agentes/status_monitor.php
index 154f8194d9..e8e5c5896f 100644
--- a/pandora_console/operation/agentes/status_monitor.php
+++ b/pandora_console/operation/agentes/status_monitor.php
@@ -81,6 +81,7 @@ $offset = (int) get_parameter('offset', 0);
$status = (int) get_parameter('status', 4);
$modulegroup = (int) get_parameter('modulegroup', -1);
$tag_filter = (int) get_parameter('tag_filter', 0);
+$min_hours_status = (string) get_parameter('min_hours_status', '');
// Sort functionality
$sortField = get_parameter('sort_field');
$sort = get_parameter('sort', 'none');
@@ -95,6 +96,7 @@ if ($ag_freestring !== '' || $moduletype !== '' || $datatype !== ''
|| $ag_modulename !== '' || $refr !== 0 || $offset !== 0 || $status !== 4
|| $modulegroup !== -1 || $tag_filter !== 0 || $sortField !== ''
|| $sort !== 'none' || $id_module !== 0 || $module_option !== 1
+ || $min_hours_status !== ''
) {
$autosearch = true;
}
@@ -243,6 +245,13 @@ if ($status == AGENT_MODULE_STATUS_NORMAL) {
AND tagente_modulo.id_tipo_modulo NOT IN (21,22,23,100)';
}
+if (!empty($min_hours_status)) {
+ $date = new DateTime(null, new DateTimeZone($config['timezone']));
+ $current_timestamp = $date->getTimestamp();
+ $max_time = ($current_timestamp - ((int) $min_hours_status * 3600));
+ $sql_conditions .= sprintf(' AND tagente_estado.last_status_change < %d', $max_time);
+}
+
// Filter by agent custom fields
$sql_conditions_custom_fields = '';
if (!empty($ag_custom_fields)) {
@@ -531,16 +540,21 @@ $table->data[2][2] = ''.__('Show monitors...').'';
$table->data[2][3] = html_print_select($monitor_options, 'module_option', $module_option, '', '', '', true, false, true, '', false, 'width: 150px;');
-$table->data[2][4] = 'data[2][4] = ''.__('Min. hours in current status').'';
+$table->data[2][5] = html_print_input_text('min_hours_status', $min_hours_val, '', 12, 20, true);
+
+$table->data[3][0] = 'data[2][4] .= 'style="display:none"';
+ $table->data[3][0] .= 'style="display:none"';
}
-$table->data[2][4] .= '>'.__('Data type').'';
+$table->data[3][0] .= '>'.__('Data type').'';
-$table->data[2][5] .= '
';
+$table->data[3][1] .= '
';
switch ($moduletype) {
@@ -609,33 +623,33 @@ switch ($moduletype) {
}
$a = db_get_all_rows_sql($sql);
-$table->data[2][5] .= '';
- $table->data[2][5] .= '
';
+ $table->data[3][1] .= '
';
$table_custom_fields = new stdClass();
@@ -683,9 +697,9 @@ foreach ($custom_fields as $custom_field) {
$filters = '';
ui_toggle($filters, __('Show Options'), '', '', false);
} else {
- $table->colspan[3][0] = 7;
- $table->cellstyle[3][0] = 'padding-left: 10px;';
- $table->data[3][0] = ui_toggle(
+ $table->colspan[4][0] = 7;
+ $table->cellstyle[4][0] = 'padding-left: 10px;';
+ $table->data[4][0] = ui_toggle(
html_print_table(
$table_custom_fields,
true
@@ -864,6 +878,26 @@ switch ($sortField) {
}
break;
+ case 'last_status_change':
+ switch ($sort) {
+ case 'up':
+ $selectStatusUp = $selected;
+ $order = [
+ 'field' => 'tagente_estado.last_status_change',
+ 'order' => 'ASC',
+ ];
+ break;
+
+ case 'down':
+ $selectStatusDown = $selected;
+ $order = [
+ 'field' => 'tagente_estado.last_status_change',
+ 'order' => 'DESC',
+ ];
+ break;
+ }
+ break;
+
case 'timestamp':
switch ($sort) {
case 'up':
@@ -954,6 +988,7 @@ $sql = 'SELECT
tagente_modulo.snmp_oid,
tagente_estado.datos,
tagente_estado.estado,
+ tagente_estado.last_status_change,
tagente_modulo.min_warning,
tagente_modulo.max_warning,
tagente_modulo.str_warning,
@@ -1066,6 +1101,7 @@ $url_module_name = 'index.php?sec=view&sec2=operation/agentes/status_monitor
$url_server_type = 'index.php?sec=view&sec2=operation/agentes/status_monitor&datatype='.$datatype.'&moduletype='.$moduletype.'&refr='.$refr.'&modulegroup='.$modulegroup.'&offset='.$offset.'&ag_group='.$ag_group.'&ag_freestring='.$ag_freestring.'&ag_modulename='.$ag_modulename.'&status='.$status.$ag_custom_fields_params.'&sort_field=moduletype&sort=';
$url_interval = 'index.php?sec=view&sec2=operation/agentes/status_monitor&datatype='.$datatype.'&moduletype='.$moduletype.'&refr='.$refr.'&modulegroup='.$modulegroup.'&offset='.$offset.'&ag_group='.$ag_group.'&ag_freestring='.$ag_freestring.'&ag_modulename='.$ag_modulename.'&status='.$status.$ag_custom_fields_params.'&sort_field=interval&sort=';
$url_status = 'index.php?sec=view&sec2=operation/agentes/status_monitor&datatype='.$datatype.'&moduletype='.$moduletype.'&refr='.$refr.'&modulegroup='.$modulegroup.'&offset='.$offset.'&ag_group='.$ag_group.'&ag_freestring='.$ag_freestring.'&ag_modulename='.$ag_modulename.'&status='.$status.$ag_custom_fields_params.'&sort_field=status&sort=';
+$url_status = 'index.php?sec=view&sec2=operation/agentes/status_monitor&datatype='.$datatype.'&moduletype='.$moduletype.'&refr='.$refr.'&modulegroup='.$modulegroup.'&offset='.$offset.'&ag_group='.$ag_group.'&ag_freestring='.$ag_freestring.'&ag_modulename='.$ag_modulename.'&status='.$status.$ag_custom_fields_params.'&sort_field=last_status_change&sort=';
$url_data = 'index.php?sec=view&sec2=operation/agentes/status_monitor&datatype='.$datatype.'&moduletype='.$moduletype.'&refr='.$refr.'&modulegroup='.$modulegroup.'&offset='.$offset.'&ag_group='.$ag_group.'&ag_freestring='.$ag_freestring.'&ag_modulename='.$ag_modulename.'&status='.$status.$ag_custom_fields_params.'&sort_field=data&sort=';
$url_timestamp_up = 'index.php?sec=view&sec2=operation/agentes/status_monitor&datatype='.$datatype.'&moduletype='.$moduletype.'&refr='.$refr.'&offset='.$offset.'&ag_group='.$ag_group.'&ag_freestring='.$ag_freestring.'&ag_modulename='.$ag_modulename.'&status='.$status.$ag_custom_fields_params.'&sort_field=timestamp&sort=up';
$url_timestamp_down = 'index.php?sec=view&sec2=operation/agentes/status_monitor&datatype='.$datatype.'&moduletype='.$moduletype.'&refr='.$refr.'&modulegroup='.$modulegroup.'&offset='.$offset.'&ag_group='.$ag_group.'&ag_freestring='.$ag_freestring.'&ag_modulename='.$ag_modulename.'&status='.$status.$ag_custom_fields_params.'&sort_field=timestamp&sort=down';
@@ -1125,32 +1161,34 @@ if (!empty($result)) {
$table->align[6] = 'left';
}
- if (in_array('graph', $show_fields) || is_metaconsole()) {
- $table->head[7] = __('Graph');
+ if (in_array('last_status_change', $show_fields)) {
+ $table->head[7] = __('Last status change');
+ $table->head[7] .= ui_get_sorting_arrows($url_status.'up', $url_status.'down', $selectStatusUp, $selectStatusDown);
$table->align[7] = 'left';
}
- if (in_array('warn', $show_fields) || is_metaconsole()) {
- $table->head[8] = __('Warn');
+ if (in_array('graph', $show_fields) || is_metaconsole()) {
+ $table->head[8] = __('Graph');
$table->align[8] = 'left';
}
- if (in_array('data', $show_fields) || is_metaconsole()) {
- $table->head[9] = __('Data');
+ if (in_array('warn', $show_fields) || is_metaconsole()) {
+ $table->head[9] = __('Warn');
$table->align[9] = 'left';
+ }
+
+ if (in_array('data', $show_fields) || is_metaconsole()) {
+ $table->head[10] = __('Data');
+ $table->align[10] = 'left';
if (is_metaconsole()) {
- $table->head[9] .= ui_get_sorting_arrows($url_data.'up', $url_data.'down', $selectDataUp, $selectDataDown);
+ $table->head[10] .= ui_get_sorting_arrows($url_data.'up', $url_data.'down', $selectDataUp, $selectDataDown);
}
}
if (in_array('timestamp', $show_fields) || is_metaconsole()) {
- $table->head[10] = __('Timestamp');
- $table->head[10] .= ui_get_sorting_arrows($url_timestamp_up, $url_timestamp_down, $selectTimestampUp, $selectTimestampDown);
- $table->align[10] = 'left';
- }
-
- if (in_array('to_critical', $show_fields)) {
- $table->head[11] = __('Last status change');
+ $table->head[11] = __('Timestamp');
+ $table->head[11] .= ui_get_sorting_arrows($url_timestamp_up, $url_timestamp_down, $selectTimestampUp, $selectTimestampDown);
+ $table->align[11] = 'left';
}
$id_type_web_content_string = db_get_value(
@@ -1462,8 +1500,12 @@ if (!empty($result)) {
}
}
+ if (in_array('last_status_change', $show_fields) || is_metaconsole()) {
+ $data[7] = ($row['last_status_change'] > 0) ? human_time_comparation($row['last_status_change']) : __('N/A');
+ }
+
if (in_array('graph', $show_fields) || is_metaconsole()) {
- $data[7] = '';
+ $data[8] = '';
$acl_graphs = false;
@@ -1498,13 +1540,13 @@ if (!empty($result)) {
$link = 'winopeng(\''.$url.'?'.$graph_params_str.'\',\''.$win_handle.'\')';
- $data[7] = get_module_realtime_link_graph($row);
+ $data[8] = get_module_realtime_link_graph($row);
if (!is_snapshot_data($row['datos'])) {
- $data[7] .= ''.html_print_image('images/chart_curve.png', true, ['border' => '0', 'alt' => '']).'';
+ $data[8] .= ''.html_print_image('images/chart_curve.png', true, ['border' => '0', 'alt' => '']).'';
}
- $data[7] .= ''.html_print_image(
+ $data[8] .= ''.html_print_image(
'images/binary.png',
true,
[
@@ -1513,13 +1555,13 @@ if (!empty($result)) {
]
).'';
- $data[7] .= ''.$row['module_name'].'';
}
}
if (in_array('warn', $show_fields) || is_metaconsole()) {
- $data[8] = ui_print_module_warn_value(
+ $data[9] = ui_print_module_warn_value(
$row['max_warning'],
$row['min_warning'],
$row['str_warning'],
@@ -1661,7 +1703,7 @@ if (!empty($result)) {
}
if (in_array('data', $show_fields) || is_metaconsole()) {
- $data[9] = $salida;
+ $data[10] = $salida;
}
if (in_array('timestamp', $show_fields) || is_metaconsole()) {
@@ -1680,12 +1722,7 @@ if (!empty($result)) {
$option = ['style' => 'font-size:7pt;'];
}
- $data[10] = ui_print_timestamp($row['utimestamp'], true, $option);
- }
-
- if (in_array('to_critical', $show_fields)) {
- $change_status_timestamp = db_get_sql('SELECT utimestamp FROM tevento WHERE id_agentmodule='.$row['id_agente_modulo'].' ORDER BY utimestamp DESC');
- $data[11] = ui_print_timestamp($change_status_timestamp, true, $option);
+ $data[11] = ui_print_timestamp($row['utimestamp'], true, $option);
}
array_push($table->data, $data);
diff --git a/pandora_console/pandoradb.sql b/pandora_console/pandoradb.sql
index 2a5ce407be..0e14fb4b68 100644
--- a/pandora_console/pandoradb.sql
+++ b/pandora_console/pandoradb.sql
@@ -169,6 +169,7 @@ CREATE TABLE IF NOT EXISTS `tagente_estado` (
`ff_critical` int(4) unsigned default '0',
`last_dynamic_update` bigint(20) NOT NULL default '0',
`last_unknown_update` bigint(20) NOT NULL default '0',
+ `last_status_change` bigint(20) NOT NULL default '0',
PRIMARY KEY (`id_agente_estado`),
KEY `status_index_1` (`id_agente_modulo`),
KEY `idx_agente` (`id_agente`),
diff --git a/pandora_console/pandoradb_data.sql b/pandora_console/pandoradb_data.sql
index dc07c6fbe8..3fa6522a8d 100644
--- a/pandora_console/pandoradb_data.sql
+++ b/pandora_console/pandoradb_data.sql
@@ -84,7 +84,7 @@ INSERT INTO `tconfig` (`token`, `value`) VALUES
('netflow_nfdump', '/usr/bin/nfdump'),
('netflow_max_resolution', '50'),
('event_fields', 'mini_severity,evento,id_agente,estado,timestamp'),
-('status_monitor_fields', 'policy,agent,data_type,module_name,server_type,interval,status,graph,warn,data,timestamp'),
+('status_monitor_fields', 'policy,agent,data_type,module_name,server_type,interval,status,last_status_change,graph,warn,data,timestamp'),
('list_ACL_IPs_for_API', '127.0.0.1'),
('enable_pass_policy', 0),
('pass_size', 4),
diff --git a/pandora_server/lib/PandoraFMS/Core.pm b/pandora_server/lib/PandoraFMS/Core.pm
index f2ca2c162b..680276ab2c 100644
--- a/pandora_server/lib/PandoraFMS/Core.pm
+++ b/pandora_server/lib/PandoraFMS/Core.pm
@@ -1681,6 +1681,10 @@ sub pandora_process_module ($$$$$$$$$;$) {
# Get new status
my $new_status = get_module_status ($processed_data, $module, $module_type);
+ my $last_status_change = $agent_status->{'last_status_change'};
+
+ # Set the last status change macro. Even if its value changes later, whe want the original value.
+ $extra_macros->{'_modulelaststatuschange_'} = $last_status_change;
# Calculate the current interval
my $current_interval;
@@ -1748,6 +1752,9 @@ sub pandora_process_module ($$$$$$$$$;$) {
generate_status_event ($pa_config, $processed_data, $agent, $module, $new_status, $status, $known_status, $dbh);
$status = $new_status;
+ # Update the change of status timestamp.
+ $last_status_change = $utimestamp;
+
# Update module status count.
$mark_for_update = 1;
@@ -1784,6 +1791,9 @@ sub pandora_process_module ($$$$$$$$$;$) {
generate_status_event ($pa_config, $processed_data, $agent, $module, $new_status, $status, $known_status, $dbh);
$status = $new_status;
+ # Update the change of status timestamp.
+ $last_status_change = $utimestamp;
+
# Update module status count.
$mark_for_update = 1;
@@ -1810,6 +1820,9 @@ sub pandora_process_module ($$$$$$$$$;$) {
generate_status_event ($pa_config, $processed_data, $agent, $module, 0, $status, $known_status, $dbh);
$status = 0;
+ # Update the change of status timestamp.
+ $last_status_change = $utimestamp;
+
# Update module status count.
$mark_for_update = 1;
}
@@ -1818,6 +1831,9 @@ sub pandora_process_module ($$$$$$$$$;$) {
generate_status_event ($pa_config, $processed_data, $agent, $module, $known_status, $status, $known_status, $dbh);
$status = $known_status;
+ # Update the change of status timestamp.
+ $last_status_change = $utimestamp;
+
# reset counters because change status.
$ff_normal = 0;
$ff_critical = 0;
@@ -1835,11 +1851,12 @@ sub pandora_process_module ($$$$$$$$$;$) {
status_changes = ?, utimestamp = ?, timestamp = ?,
id_agente = ?, current_interval = ?, running_by = ?,
last_execution_try = ?, last_try = ?, last_error = ?,
- ff_start_utimestamp = ?, ff_normal = ?, ff_warning = ?, ff_critical = ?
+ ff_start_utimestamp = ?, ff_normal = ?, ff_warning = ?, ff_critical = ?,
+ last_status_change = ?
WHERE id_agente_modulo = ?', $processed_data, $status, $status, $new_status, $new_status, $status_changes,
$current_utimestamp, $timestamp, $module->{'id_agente'}, $current_interval, $server_id,
$utimestamp, ($save == 1) ? $timestamp : $agent_status->{'last_try'}, $last_error, $ff_start_utimestamp,
- $ff_normal, $ff_warning, $ff_critical, $module->{'id_agente_modulo'});
+ $ff_normal, $ff_warning, $ff_critical, $last_status_change, $module->{'id_agente_modulo'});
}
# Save module data. Async and log4x modules are not compressed.
@@ -5405,7 +5422,7 @@ sub pandora_module_unknown ($$) {
}
my @modules = get_db_rows ($dbh, 'SELECT tagente_modulo.*,
- tagente_estado.id_agente_estado, tagente_estado.estado
+ tagente_estado.id_agente_estado, tagente_estado.estado, tagente_estado.last_status_change
FROM tagente_modulo, tagente_estado, tagente
WHERE tagente.id_agente = tagente_estado.id_agente
AND tagente_modulo.id_agente_modulo = tagente_estado.id_agente_modulo
@@ -5432,7 +5449,7 @@ sub pandora_module_unknown ($$) {
# Set the module state to normal
logger ($pa_config, "Module " . $module->{'nombre'} . " is going to NORMAL", 10);
- db_do ($dbh, 'UPDATE tagente_estado SET last_status = 0, estado = 0, known_status = 0, last_known_status = 0 WHERE id_agente_estado = ?', $module->{'id_agente_estado'});
+ db_do ($dbh, 'UPDATE tagente_estado SET last_status = 0, estado = 0, known_status = 0, last_known_status = 0, last_status_change = ? WHERE id_agente_estado = ?', time(), $module->{'id_agente_estado'});
# Get agent information
my $agent = get_db_single_row ($dbh, 'SELECT *
@@ -5449,7 +5466,8 @@ sub pandora_module_unknown ($$) {
# Generate alerts
if (pandora_inhibit_alerts ($pa_config, $agent, $dbh, 0) == 0 && pandora_cps_enabled($agent, $module) == 0) {
- pandora_generate_alerts ($pa_config, 0, 3, $agent, $module, time (), $dbh, undef, undef, 0, 'unknown');
+ my $extra_macros = { _modulelaststatuschange_ => $module->{'last_status_change'}};
+ pandora_generate_alerts ($pa_config, 0, 3, $agent, $module, time (), $dbh, $extra_macros, undef, 0, 'unknown');
}
else {
logger($pa_config, "Alerts inhibited for agent '" . $agent->{'nombre'} . "'.", 10);
@@ -5462,6 +5480,7 @@ sub pandora_module_unknown ($$) {
# Replace macros
my %macros = (
_module_ => safe_output($module->{'nombre'}),
+ _modulelaststatuschange_ => $module->{'last_status_change'},
_data_ => 'N/A',
);
load_module_macros ($module->{'module_macros'}, \%macros);
@@ -5478,7 +5497,8 @@ sub pandora_module_unknown ($$) {
# Set the module status to unknown (the module can already be unknown if unknown_updates is enabled).
if ($module->{'estado'} != 3) {
logger ($pa_config, "Module " . $module->{'nombre'} . " is going to UNKNOWN", 10);
- db_do ($dbh, 'UPDATE tagente_estado SET last_status = 3, estado = 3, last_unknown_update = ? WHERE id_agente_estado = ?', time(), $module->{'id_agente_estado'});
+ my $utimestamp = time();
+ db_do ($dbh, 'UPDATE tagente_estado SET last_status = 3, estado = 3, last_unknown_update = ?, last_status_change = ? WHERE id_agente_estado = ?', $utimestamp, $utimestamp, , $module->{'id_agente_estado'});
}
# Get agent information
@@ -5493,7 +5513,8 @@ sub pandora_module_unknown ($$) {
# Generate alerts
if (pandora_inhibit_alerts ($pa_config, $agent, $dbh, 0) == 0 && pandora_cps_enabled($agent, $module) == 0) {
- pandora_generate_alerts ($pa_config, 0, 3, $agent, $module, time (), $dbh, undef, undef, 0, 'unknown');
+ my $extra_macros = { _modulelaststatuschange_ => $module->{'last_status_change'}};
+ pandora_generate_alerts ($pa_config, 0, 3, $agent, $module, time (), $dbh, $extra_macros, undef, 0, 'unknown');
}
else {
logger($pa_config, "Alerts inhibited for agent '" . $agent->{'nombre'} . "'.", 10);
@@ -5531,6 +5552,7 @@ sub pandora_module_unknown ($$) {
# Replace macros
my %macros = (
_module_ => safe_output($module->{'nombre'}),
+ _modulelaststatuschange_ => $module->{'last_status_change'},
);
load_module_macros ($module->{'module_macros'}, \%macros);
$description = subst_alert_macros ($description, \%macros, $pa_config, $dbh, $agent, $module);