SLA algorythm 2.0
This commit is contained in:
parent
ed69265fb7
commit
b1f400ac0d
|
@ -466,6 +466,394 @@ function db_get_all_rows_sql($sql, $search_history_db = false, $cache = true, $d
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* Returns the time the module is in unknown status (by events)
|
||||
*
|
||||
* @param int $id_agente_modulo module to check
|
||||
* @param int $tstart begin of search
|
||||
* @param int $tend end of search
|
||||
*
|
||||
*/
|
||||
function db_get_module_ranges_unknown($id_agente_modulo, $tstart = false, $tend = false) {
|
||||
global $config;
|
||||
|
||||
if (!isset($id_agente_modulo)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((!isset($tstart)) || ($tstart === false)) {
|
||||
// Return data from the begining
|
||||
$tstart = 0;
|
||||
}
|
||||
|
||||
if ((!isset($tend)) || ($tend === false)) {
|
||||
// Return data until now
|
||||
$tend = time();
|
||||
}
|
||||
|
||||
if ($tstart > $tend) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// Retrieve going unknown events in range
|
||||
$query = "SELECT utimestamp,event_type FROM tevento WHERE id_agentmodule = " . $id_agente_modulo;
|
||||
$query .= " AND event_type like 'going_%' ";
|
||||
$query .= " AND utimestamp >= $tstart AND utimestamp <= $tend ";
|
||||
$query .= " ORDER BY utimestamp ASC";
|
||||
|
||||
$events = db_get_all_rows_sql($query);
|
||||
|
||||
if (! is_array($events)){
|
||||
return false;
|
||||
}
|
||||
|
||||
$last_status = 0; // normal
|
||||
$return = array();
|
||||
$i=0;
|
||||
foreach ($events as $event) {
|
||||
switch ($event["event_type"]) {
|
||||
case "going_up_critical":
|
||||
case "going_up_warning":
|
||||
case "going_up_normal": {
|
||||
if ($last_status == 1) {
|
||||
$return[$i]["time_to"] = $event["utimestamp"];
|
||||
$i++;
|
||||
$last_status = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "going_unknown":{
|
||||
if ($last_status == 0){
|
||||
$return[$i] = array();
|
||||
$return[$i]["time_from"] = $event["utimestamp"];
|
||||
$last_status = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Uncompresses and returns the data of a given id_agent_module
|
||||
*
|
||||
* @param int $id_agente_modulo id_agente_modulo
|
||||
* @param utimestamp $tstart Begin of the catch
|
||||
* @param utimestamp $tend End of the catch
|
||||
* @param int $interval Size of slice (default-> module_interval)
|
||||
*
|
||||
* @return hash with the data uncompressed in blocks of module_interval
|
||||
* false in case of empty result
|
||||
*
|
||||
* Note: All "unknown" data are marked as NULL
|
||||
* Warning: Be careful with the amount of data, check your RAM size available
|
||||
*
|
||||
*/
|
||||
function db_uncompress_module_data($id_agente_modulo, $tstart = false, $tend = false) {
|
||||
global $config;
|
||||
|
||||
if (!isset($id_agente_modulo)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((!isset($tstart)) || ($tstart === false)) {
|
||||
// Return data from the begining
|
||||
$tstart = 0;
|
||||
}
|
||||
|
||||
if ((!isset($tend)) || ($tend === false)) {
|
||||
// Return data until now
|
||||
$tend = time();
|
||||
}
|
||||
|
||||
if ($tstart > $tend) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
$search_historydb = false;
|
||||
$table = "tagente_datos";
|
||||
|
||||
$module = modules_get_agentmodule($id_agente_modulo);
|
||||
if ($module === false){
|
||||
// module not exists
|
||||
return false;
|
||||
}
|
||||
$module_type = $module['id_tipo_modulo'];
|
||||
$module_type_str = modules_get_type_name ($module_type);
|
||||
if (strstr ($module_type_str, 'string') !== false) {
|
||||
$table = "tagente_datos_string";
|
||||
}
|
||||
|
||||
|
||||
// Get first available utimestamp in active DB
|
||||
$query = " SELECT utimestamp, datos FROM $table ";
|
||||
$query .= " WHERE id_agente_modulo=$id_agente_modulo AND utimestamp < $tstart";
|
||||
$query .= " ORDER BY utimestamp DESC LIMIT 1";
|
||||
|
||||
|
||||
$ret = db_get_all_rows_sql( $query , $search_historydb);
|
||||
|
||||
if ( ( $ret === false ) || (( isset($ret[0]["utimestamp"]) && ($ret[0]["utimestamp"] > $tstart )))) {
|
||||
// Value older than first retrieved from active DB
|
||||
$search_historydb = true;
|
||||
|
||||
$ret = db_get_all_rows_sql( $query , $search_historydb);
|
||||
}
|
||||
else {
|
||||
$first_data["utimestamp"] = $ret[0]["utimestamp"];
|
||||
$first_data["datos"] = $ret[0]["datos"];
|
||||
}
|
||||
|
||||
if ( ( $ret === false ) || (( isset($ret[0]["utimestamp"]) && ($ret[0]["utimestamp"] > $tstart )))) {
|
||||
// No previous data. -> not init
|
||||
// Avoid false unknown status
|
||||
$first_data["utimestamp"] = time();
|
||||
$first_data["datos"] = false;
|
||||
}
|
||||
else {
|
||||
$first_data["utimestamp"] = $ret[0]["utimestamp"];
|
||||
$first_data["datos"] = $ret[0]["datos"];
|
||||
}
|
||||
|
||||
$query = " SELECT utimestamp, datos FROM $table ";
|
||||
$query .= " WHERE id_agente_modulo=$id_agente_modulo AND utimestamp >= $tstart AND utimestamp <= $tend";
|
||||
$query .= " ORDER BY utimestamp ASC";
|
||||
|
||||
// Retrieve all data from module in given range
|
||||
$raw_data = db_get_all_rows_sql($query, $search_historydb);
|
||||
|
||||
if (($raw_data === false) && ($ret === false)) {
|
||||
// No data
|
||||
return false;
|
||||
}
|
||||
|
||||
// Retrieve going unknown events in range
|
||||
$unknown_events = db_get_module_ranges_unknown($id_agente_modulo, $tstart, $tend);
|
||||
|
||||
// Retrieve module_interval to build the template
|
||||
$module_interval = modules_get_interval ($id_agente_modulo);
|
||||
$slice_size = $module_interval;
|
||||
|
||||
// We'll return a bidimensional array
|
||||
// Structure returned: schema:
|
||||
//
|
||||
// uncompressed_data =>
|
||||
// pool_id (int)
|
||||
// utimestamp (start of current slice)
|
||||
// data
|
||||
// array
|
||||
// utimestamp
|
||||
// datos
|
||||
|
||||
$return = array();
|
||||
|
||||
// Point current_timestamp to begin of the set and initialize flags
|
||||
$current_timestamp = $tstart;
|
||||
$last_inserted_value = $first_data["datos"];
|
||||
$last_timestamp = $first_data["utimestamp"];
|
||||
$data_found = 0;
|
||||
|
||||
// Build template
|
||||
$pool_id = 0;
|
||||
$now = time();
|
||||
|
||||
$in_unknown_status = 0;
|
||||
if (is_array($unknown_events)) {
|
||||
$current_unknown = array_shift($unknown_events);
|
||||
}
|
||||
while ( $current_timestamp < $tend ) {
|
||||
$expected_data_generated = 0;
|
||||
|
||||
$return[$pool_id]["data"] = array();
|
||||
$tmp_data = array();
|
||||
$data_found = 0;
|
||||
|
||||
if (is_array($unknown_events)) {
|
||||
$i = 0;
|
||||
while ($current_timestamp >= $unknown_events[$i]["time_to"] ) {
|
||||
// Skip unknown events in past
|
||||
array_splice($unknown_events, $i,1);
|
||||
$i++;
|
||||
if (!isset($unknown_events[$i])) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (isset($current_unknown)) {
|
||||
|
||||
// check if recovered from unknown status
|
||||
if(is_array($unknown_events) && isset($current_unknown)) {
|
||||
if ( (($current_timestamp+$slice_size) > $current_unknown["time_to"])
|
||||
&& ($current_timestamp < $current_unknown["time_to"])
|
||||
&& ($in_unknown_status == 1) ) {
|
||||
// Recovered from unknown
|
||||
|
||||
if ( ($current_unknown["time_to"] > $current_timestamp)
|
||||
&& ($expected_data_generated == 0) ) {
|
||||
// also add the "expected" data
|
||||
$tmp_data["utimestamp"] = $current_timestamp;
|
||||
if ($in_unknown_status == 1) {
|
||||
$tmp_data["datos"] = null;
|
||||
}
|
||||
else {
|
||||
$tmp_data["datos"] = $last_inserted_value;
|
||||
}
|
||||
$return[$pool_id]["utimestamp"] = $current_timestamp;
|
||||
array_push($return[$pool_id]["data"], $tmp_data);
|
||||
$expected_data_generated = 1;
|
||||
}
|
||||
|
||||
|
||||
$tmp_data["utimestamp"] = $current_unknown["time_to"];
|
||||
$tmp_data["datos"] = $last_inserted_value;
|
||||
// debug purpose
|
||||
//$tmp_data["obs"] = "event recovery data";
|
||||
|
||||
$return[$pool_id]["utimestamp"] = $current_timestamp;
|
||||
array_push($return[$pool_id]["data"], $tmp_data);
|
||||
$data_found = 1;
|
||||
$in_unknown_status = 0;
|
||||
}
|
||||
|
||||
if ( (($current_timestamp+$slice_size) > $current_unknown["time_from"])
|
||||
&& (($current_timestamp+$slice_size) < $current_unknown["time_to"])
|
||||
&& ($in_unknown_status == 0) ) {
|
||||
// Add unknown state detected
|
||||
|
||||
if ( $current_unknown["time_from"] < ($current_timestamp+$slice_size)) {
|
||||
if ( ($current_unknown["time_from"] > $current_timestamp)
|
||||
&& ($expected_data_generated == 0) ) {
|
||||
// also add the "expected" data
|
||||
$tmp_data["utimestamp"] = $current_timestamp;
|
||||
if ($in_unknown_status == 1) {
|
||||
$tmp_data["datos"] = null;
|
||||
}
|
||||
else {
|
||||
$tmp_data["datos"] = $last_inserted_value;
|
||||
}
|
||||
$return[$pool_id]["utimestamp"] = $current_timestamp;
|
||||
array_push($return[$pool_id]["data"], $tmp_data);
|
||||
$expected_data_generated = 1;
|
||||
}
|
||||
|
||||
$tmp_data["utimestamp"] = $current_unknown["time_from"];
|
||||
$tmp_data["datos"] = null;
|
||||
// debug purpose
|
||||
//$tmp_data["obs"] = "event data";
|
||||
$return[$pool_id]["utimestamp"] = $current_timestamp;
|
||||
array_push($return[$pool_id]["data"], $tmp_data);
|
||||
$data_found = 1;
|
||||
}
|
||||
$in_unknown_status = 1;
|
||||
}
|
||||
|
||||
if ( ($in_unknown_status == 0) && ($current_timestamp >= $current_unknown["time_to"]) ) {
|
||||
$current_unknown = array_shift($unknown_events);
|
||||
}
|
||||
}
|
||||
} // unknown events handle
|
||||
}
|
||||
|
||||
// Search for data
|
||||
$i=0;
|
||||
if (is_array($raw_data)) {
|
||||
foreach ($raw_data as $data) {
|
||||
if ( ($data["utimestamp"] >= $current_timestamp)
|
||||
&& ($data["utimestamp"] < ($current_timestamp+$slice_size)) ) {
|
||||
// Data in block, push in, and remove from $raw_data (processed)
|
||||
|
||||
if ( ($data["utimestamp"] > $current_timestamp)
|
||||
&& ($expected_data_generated == 0) ) {
|
||||
// also add the "expected" data
|
||||
$tmp_data["utimestamp"] = $current_timestamp;
|
||||
if ($in_unknown_status == 1) {
|
||||
$tmp_data["datos"] = null;
|
||||
}
|
||||
else {
|
||||
$tmp_data["datos"] = $last_inserted_value;
|
||||
}
|
||||
//$tmp_data["obs"] = "expected data";
|
||||
$return[$pool_id]["utimestamp"] = $current_timestamp;
|
||||
array_push($return[$pool_id]["data"], $tmp_data);
|
||||
$expected_data_generated = 1;
|
||||
}
|
||||
|
||||
$tmp_data["utimestamp"] = intval($data["utimestamp"]);
|
||||
$tmp_data["datos"] = $data["datos"];
|
||||
// debug purpose
|
||||
//$tmp_data["obs"] = "real data";
|
||||
|
||||
$return[$pool_id]["utimestamp"] = $current_timestamp;
|
||||
array_push($return[$pool_id]["data"], $tmp_data);
|
||||
|
||||
$last_inserted_value = $data["datos"];
|
||||
$last_timestamp = intval($data["utimestamp"]);
|
||||
|
||||
unset($raw_data[$i]);
|
||||
$data_found = 1;
|
||||
$in_unknown_status = 0;
|
||||
}
|
||||
elseif ($data["utimestamp"] > ($current_timestamp+$slice_size)) {
|
||||
// Data in future, stop searching new ones
|
||||
break;
|
||||
}
|
||||
}
|
||||
$i++;
|
||||
}
|
||||
|
||||
if ($data_found == 0) {
|
||||
// No data found, lug the last_value until SECONDS_1DAY + 2*modules_get_interval
|
||||
// UNKNOWN!
|
||||
|
||||
if (($current_timestamp > $now) || (($current_timestamp - $last_timestamp) > (SECONDS_1DAY + 2*$module_interval))) {
|
||||
if (isset($last_inserted_value)) {
|
||||
// unhandled unknown status control
|
||||
$unhandled_time_unknown = $current_timestamp - (SECONDS_1DAY + 2*$module_interval) - $last_timestamp;
|
||||
if ($unhandled_time_unknown > 0) {
|
||||
// unhandled unknown status detected. Add to previous pool
|
||||
$tmp_data["utimestamp"] = intval($last_timestamp) + (SECONDS_1DAY + 2*$module_interval);
|
||||
$tmp_data["datos"] = null;
|
||||
// debug purpose
|
||||
//$tmp_data["obs"] = "unknown extra";
|
||||
// add to previous pool if needed
|
||||
if (isset($return[$pool_id-1])) {
|
||||
array_push($return[$pool_id-1]["data"], $tmp_data);
|
||||
}
|
||||
}
|
||||
}
|
||||
$last_inserted_value = null;
|
||||
}
|
||||
|
||||
$tmp_data["utimestamp"] = $current_timestamp;
|
||||
|
||||
if ($in_unknown_status == 1) {
|
||||
$tmp_data["datos"] = null;
|
||||
}
|
||||
else {
|
||||
$tmp_data["datos"] = $last_inserted_value;
|
||||
}
|
||||
// debug purpose
|
||||
//$tmp_data["obs"] = "virtual data";
|
||||
|
||||
$return[$pool_id]["utimestamp"] = $current_timestamp;
|
||||
array_push($return[$pool_id]["data"], $tmp_data);
|
||||
}
|
||||
|
||||
$pool_id++;
|
||||
$current_timestamp += $slice_size;
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all the rows of a table in the database that matches a filter.
|
||||
*
|
||||
|
|
|
@ -3717,6 +3717,701 @@ function reporting_sql($report, $content) {
|
|||
return reporting_check_structure_content($return);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Truncates a value
|
||||
//
|
||||
// Returns the truncated value
|
||||
//
|
||||
function sla_truncate($num, $accurancy = 2){
|
||||
if (!isset($accurancy)){
|
||||
$accurancy = 2;
|
||||
}
|
||||
$mult = pow(10, $accurancy);
|
||||
return floor($num*$mult)/$mult;
|
||||
}
|
||||
|
||||
//
|
||||
// Aux: check value limits
|
||||
//
|
||||
// Returns if the data is in a valid range or not
|
||||
//
|
||||
function sla_check_value($value, $min, $max, $inverse_interval = 0) {
|
||||
if ($max == $min) { // equal 0
|
||||
if ($value == $max) {
|
||||
return ($inverse_interval==0)?true:false;
|
||||
}
|
||||
return ($inverse_interval==0)?false:true;
|
||||
}
|
||||
if (!isset ($max)) {
|
||||
if ($value >= $min) {
|
||||
return ($inverse_interval==0)?true:false;
|
||||
}
|
||||
return ($inverse_interval==0)?false:true;
|
||||
}
|
||||
if (!isset ($min)) {
|
||||
if ($value <= $max) {
|
||||
return ($inverse_interval==0)?true:false;
|
||||
}
|
||||
return ($inverse_interval==0)?false:true;
|
||||
}
|
||||
if (($max*1) == 0) { // ignore
|
||||
return sla_check_value($value,$min,null, $inverse_interval);
|
||||
}
|
||||
if (($min*1) == 0) { // ignore
|
||||
return sla_check_value($value,null,$max, $inverse_interval);
|
||||
}
|
||||
if (($value >= $min) && ($value <= $max)) {
|
||||
return ($inverse_interval==0)?true:false;
|
||||
}
|
||||
return ($inverse_interval==0)?false:true;
|
||||
}
|
||||
|
||||
/**
|
||||
* SLA fixed worktime
|
||||
*
|
||||
* Check (if needed) if the range specified by wt_start and wt_end is a valid
|
||||
* range or not.
|
||||
*
|
||||
* As worktime is order (older ... newer) the idx works as flag to identify
|
||||
* last range checked, in order to improve the algorythm performance.
|
||||
*
|
||||
* @param int $wt_start start of the range
|
||||
* @param int $wt_end end of the range
|
||||
* @param hash $worktime hash containing the valid intervals
|
||||
* @param int $idx last ranges checked
|
||||
*
|
||||
*/
|
||||
function sla_fixed_worktime($wt_start, $wt_end, $worktime = null, $idx = 0) {
|
||||
|
||||
$return = array();
|
||||
|
||||
// Accept all ranges by default
|
||||
$return["wt_valid"] = 1;
|
||||
$return["interval"] = $wt_end - $wt_start;
|
||||
|
||||
// No exclusions defined, entire worktime is valid
|
||||
if ((!isset($worktime) || (!is_array($worktime)))) {
|
||||
return $return;
|
||||
}
|
||||
|
||||
// Check exceptions
|
||||
$total = count($worktime);
|
||||
|
||||
$return["idx"] = $idx;
|
||||
|
||||
if (!(($idx <= $total) && ($idx >= 0))) {
|
||||
$idx = 0;
|
||||
}
|
||||
|
||||
$start_fixed = 0;
|
||||
for ($i=$idx; $i < $total; $i++) {
|
||||
$wt = $worktime[$i];
|
||||
|
||||
if ($start_fixed == 1) {
|
||||
// Intervals greater than 1 DAY
|
||||
if ($wt_end < $wt["date_from"]) {
|
||||
return $return;
|
||||
}
|
||||
|
||||
if ( ($wt_end >= $wt["date_from"])
|
||||
&& ($wt_end <= $wt["date_to"])) {
|
||||
// add last slice
|
||||
$return["interval"] += $wt_end - $wt["date_from"];
|
||||
return $return;
|
||||
}
|
||||
if ( ($wt_end >= $wt["date_from"])
|
||||
&& ($wt_end <= $wt["date_to"])) {
|
||||
// Add current slice and continue checking
|
||||
$return["interval"] += $wt["date_to"] - $wt["date_from"];
|
||||
// Also ignore this slice
|
||||
$return["idx"] = $i;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ( ($wt_start < $wt["date_from"])
|
||||
&& ($wt_end < $wt["date_from"])) {
|
||||
// Case A: ..start..end..[...]......
|
||||
$return["wt_valid"] = 0;
|
||||
return $return;
|
||||
}
|
||||
if ( ($wt_start <= $wt["date_from"])
|
||||
&& ($wt_end >= $wt["date_from"])
|
||||
&& ($wt_end <= $wt["date_to"])) {
|
||||
// Case B: ...start..[..end..]......
|
||||
$return["wt_valid"] = 1;
|
||||
$return["interval"] = $wt_end - $wt["date_from"];
|
||||
return $return;
|
||||
}
|
||||
if ( ($wt_start >= $wt["date_from"])
|
||||
&& ($wt_start <= $wt["date_to"])
|
||||
&& ($wt_end >= $wt["date_from"])
|
||||
&& ($wt_end <= $wt["date_to"])) {
|
||||
// Case C: ...[..start..end..]......
|
||||
$return["wt_valid"] = 1;
|
||||
return $return;
|
||||
}
|
||||
if ( ($wt_start >= $wt["date_from"])
|
||||
&& ($wt_start <= $wt["date_to"])
|
||||
&& ($wt_end > $wt["date_to"])) {
|
||||
// Case D: ...[..start..]...end.....
|
||||
$return["interval"] = $wt["date_to"] - $wt_start;
|
||||
|
||||
$return["wt_valid"] = 1;
|
||||
$start_fixed = 1;
|
||||
if (($i+1) == $total) {
|
||||
// if there's no more worktime ranges to check return the accumulated
|
||||
return $return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ( ($wt_start < $wt["date_from"])
|
||||
&& ($wt_end > $wt["date_to"])) {
|
||||
// Case E: ...start...[...]...end...
|
||||
$return["wt_valid"] = 1;
|
||||
$return["interval"] = $wt["date_to"] - $wt["date_from"];
|
||||
|
||||
if (($wt_end - $wt_start) < SECONDS_1DAY) {
|
||||
// Interval is less than 1 day
|
||||
return $return;
|
||||
}
|
||||
else {
|
||||
// Interval greater than 1 day, split valid worktimes
|
||||
$start_fixed = 1;
|
||||
}
|
||||
|
||||
}
|
||||
if ( ($wt_start > $wt["date_to"])
|
||||
&& ($wt_end > $wt["date_to"])) {
|
||||
// Case F: ...[....]..start...end...
|
||||
// Invalid, check next worktime hole
|
||||
$return["wt_valid"] = 0;
|
||||
// and remove current one
|
||||
$return["idx"] = $i+1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$return["wt_valid"] = 0;
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Advanced SLA result with summary
|
||||
*
|
||||
* @param int $id_agent_module id_agent_module
|
||||
* @param int $time_from Time start
|
||||
* @param int $time_to time end
|
||||
* @param int $min_value minimum value for OK status
|
||||
* @param int $max_value maximum value for OK status
|
||||
* @param int $inverse_interval inverse interval (range) for OK status
|
||||
* @param hash $daysWeek Days of active work times (M-T-W-T-V-S-S)
|
||||
* @param int $timeFrom Start of work time, in each day
|
||||
* @param int $timeTo End of work time, in each day
|
||||
* @param int $slices Number of reports (time division)
|
||||
*
|
||||
* @return array Returns a hash with the calculated data
|
||||
*
|
||||
*/
|
||||
function reporting_advanced_sla ($id_agent_module, $time_from = null, $time_to = null,
|
||||
$min_value = null, $max_value = null, $inverse_interval = null, $daysWeek = null,
|
||||
$timeFrom = null, $timeTo = null, $slices = 1) {
|
||||
|
||||
// In content:
|
||||
//
|
||||
// [time_from, time_to] => Worktime
|
||||
// week's days => flags to manage workdays
|
||||
|
||||
if (!isset($id_agent_module)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($slices < 1) {
|
||||
$slices = 1;
|
||||
}
|
||||
|
||||
if (!isset($min_value) && (!isset($max_value) && (!isset($inverse_interval)))) {
|
||||
// Infer availability range based on the critical thresholds
|
||||
$agentmodule_info = modules_get_agentmodule($id_agent_module);
|
||||
|
||||
// take in mind: the "inverse" critical threshold
|
||||
$min_value = $agentmodule_info["min_critical"];
|
||||
$max_value = $agentmodule_info["max_critical"];
|
||||
$inverse_interval = $agentmodule_info["critical_inverse"]==0?1:0;
|
||||
|
||||
if (!isset($min_value)){
|
||||
$min_value = 0;
|
||||
}
|
||||
if (!isset($max_value)){
|
||||
$max_value = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// By default show last day
|
||||
$datetime_to = time();
|
||||
$datetime_from = $datetime_to - SECONDS_1DAY;
|
||||
|
||||
// Or apply specified range
|
||||
if ((isset($time_to) && isset($time_from)) && ($time_to > $time_from)) {
|
||||
$datetime_to = $time_to;
|
||||
$datetime_from = $time_from;
|
||||
}
|
||||
if (!isset($time_to)) {
|
||||
$datetime_to = $time_to;
|
||||
}
|
||||
if (!isset($time_from)) {
|
||||
$datetime_from = $time_from;
|
||||
}
|
||||
|
||||
|
||||
$uncompressed_data = db_uncompress_module_data($id_agent_module, $datetime_from, $datetime_to);
|
||||
|
||||
if (is_array($uncompressed_data)){
|
||||
$n_pools = count($uncompressed_data);
|
||||
if ($n_pools == 0){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
$planned_downtimes = reporting_get_planned_downtimes_intervals($id_agent_module, $datetime_from, $datetime_to);
|
||||
|
||||
if ( (is_array($planned_downtimes)) && (count($planned_downtimes) > 0)){
|
||||
// Sort retrieved planned downtimes
|
||||
usort($planned_downtimes, function ($a, $b) {
|
||||
$a = intval($a["date_from"]);
|
||||
$b = intval($b["date_from"]);
|
||||
if ($a==$b) {
|
||||
return 0;
|
||||
}
|
||||
return ($a<$b)?-1:1;
|
||||
});
|
||||
|
||||
// Compress (overlapped) planned downtimes
|
||||
$npd = count($planned_downtimes);
|
||||
for ($i=0; $i<$npd; $i++) {
|
||||
if (isset($planned_downtimes[$i+1])) {
|
||||
if ($planned_downtimes[$i]["date_to"] >= $planned_downtimes[$i+1]["date_from"]) {
|
||||
// merge
|
||||
$planned_downtimes[$i]["date_to"] = $planned_downtimes[$i+1]["date_to"];
|
||||
array_splice ($planned_downtimes, $i+1, 1);
|
||||
$npd--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
$planned_downtimes = null;
|
||||
}
|
||||
|
||||
// Structure retrieved: schema:
|
||||
//
|
||||
// uncompressed_data =>
|
||||
// pool_id (int)
|
||||
// utimestamp (start of current slice)
|
||||
// data
|
||||
// array
|
||||
// utimestamp
|
||||
// datos
|
||||
//
|
||||
|
||||
|
||||
// Build exceptions
|
||||
$worktime = null;
|
||||
|
||||
if ( ((isset($daysWeek))
|
||||
&& (isset($timeFrom))
|
||||
&& (isset($timeTo)))
|
||||
|| (is_array($planned_downtimes)) ) {
|
||||
$n = 0;
|
||||
|
||||
if (!isset($daysWeek)) {
|
||||
// init
|
||||
$daysWeek = array (
|
||||
"1" => 1, // sunday"
|
||||
"2" => 1, // monday
|
||||
"3" => 1, // tuesday
|
||||
"4" => 1, // wednesday
|
||||
"5" => 1, // thursday
|
||||
"6" => 1, // friday
|
||||
"7" => 1, // saturday
|
||||
);
|
||||
}
|
||||
|
||||
foreach ($daysWeek as $day) {
|
||||
if ($day == 1){
|
||||
$n++;
|
||||
}
|
||||
}
|
||||
if ( ($n == count($daysWeek)) && ($timeFrom == $timeTo) && (!is_array($planned_downtimes)) ) {
|
||||
// Ignore custom ranges
|
||||
$worktime = null;
|
||||
}
|
||||
else {
|
||||
|
||||
// get only first day
|
||||
$date_start = strtotime(date("Y/m/d",$datetime_from));
|
||||
$date_end = strtotime(date("Y/m/d",$datetime_to));
|
||||
|
||||
$t_day = $date_start;
|
||||
$i = 0;
|
||||
$worktime = array();
|
||||
|
||||
if ($timeFrom == $timeTo) {
|
||||
$timeFrom = "00:00:00";
|
||||
$timeTo = "00:00:00";
|
||||
}
|
||||
|
||||
if (!isset($timeFrom)) {
|
||||
$timeFrom = "00:00:00";
|
||||
}
|
||||
if (!isset($timeTo)) {
|
||||
$timeTo = "00:00:00";
|
||||
}
|
||||
|
||||
// timeFrom (seconds)
|
||||
sscanf($timeFrom, "%d:%d:%d", $hours, $minutes, $seconds);
|
||||
$secondsFrom = $hours * 3600 + $minutes * 60 + $seconds;
|
||||
|
||||
// timeTo (seconds)
|
||||
sscanf($timeTo, "%d:%d:%d", $hours, $minutes, $seconds);
|
||||
$secondsTo = $hours * 3600 + $minutes * 60 + $seconds;
|
||||
|
||||
// Apply planned downtime exceptions (fix matrix)
|
||||
while ($t_day <= $date_end) {
|
||||
if ($daysWeek[date("w", $t_day)+1] == 1) {
|
||||
$wt_start = strtotime(date("Y/m/d H:i:s",$t_day + $secondsFrom));
|
||||
$wt_end = strtotime(date("Y/m/d H:i:s",$t_day + $secondsTo));
|
||||
if ($timeFrom == $timeTo) {
|
||||
$wt_end += SECONDS_1DAY;
|
||||
}
|
||||
|
||||
// Check if in planned downtime
|
||||
if (is_array($planned_downtimes)) {
|
||||
$start_fixed = 0;
|
||||
|
||||
$n_planned_downtimes = count($planned_downtimes);
|
||||
$i_planned_downtimes = 0;
|
||||
|
||||
|
||||
|
||||
$last_pd = end($planned_downtimes);
|
||||
|
||||
if ($wt_start > $last_pd["date_to"]) {
|
||||
// There's no more planned downtimes, accept remaining range
|
||||
$worktime[$i]= array();
|
||||
$worktime[$i]["date_from"] = $wt_start;
|
||||
$worktime[$i]["date_to"] = $wt_end;
|
||||
$i++;
|
||||
}
|
||||
else {
|
||||
for($i_planned_downtimes=0; $i_planned_downtimes < $n_planned_downtimes; $i_planned_downtimes++){
|
||||
$pd = $planned_downtimes[$i_planned_downtimes];
|
||||
|
||||
if($start_fixed == 1) {
|
||||
// Interval greater than found planned downtime
|
||||
if ( $wt_end < $pd["date_from"] ) {
|
||||
$worktime[$i]= array();
|
||||
// wt_start already fixed
|
||||
$worktime[$i]["date_from"] = $wt_start;
|
||||
$worktime[$i]["date_to"] = $wt_end;
|
||||
$i++;
|
||||
break;
|
||||
}
|
||||
if ( ( $wt_end >= $pd["date_from"] )
|
||||
&& ( $wt_end <= $pd["date_to"] )) {
|
||||
$worktime[$i]= array();
|
||||
// wt_start already fixed
|
||||
$worktime[$i]["date_from"] = $wt_start;
|
||||
$worktime[$i]["date_to"] = $pd["date_from"];
|
||||
$i++;
|
||||
break;
|
||||
}
|
||||
if ( $wt_end > $pd["date_to"] ) {
|
||||
$worktime[$i]= array();
|
||||
// wt_start already fixed
|
||||
$worktime[$i]["date_from"] = $wt_start;
|
||||
$worktime[$i]["date_to"] = $pd["date_from"];
|
||||
$i++;
|
||||
|
||||
$start_fixed = 0;
|
||||
// Search following planned downtimes, we're still on work time!
|
||||
$wt_start = $pd["date_from"];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ( ( $wt_start < $pd["date_from"])
|
||||
&& ( $wt_end < $pd["date_from"]) ) {
|
||||
// Out of planned downtime: Add worktime
|
||||
$worktime[$i]= array();
|
||||
$worktime[$i]["date_from"] = $wt_start;
|
||||
$worktime[$i]["date_to"] = $wt_end;
|
||||
$i++;
|
||||
break;
|
||||
}
|
||||
if ( ( $wt_start < $pd["date_from"])
|
||||
&& ( $wt_end <= $pd["date_to"]) ) {
|
||||
// Not all worktime in downtime.
|
||||
$worktime[$i]= array();
|
||||
$worktime[$i]["date_from"] = $wt_start;
|
||||
$worktime[$i]["date_to"] = $pd["date_from"];
|
||||
$i++;
|
||||
break;
|
||||
}
|
||||
if ( ( $wt_start >= $pd["date_from"])
|
||||
&& ( $wt_end <= $pd["date_to"]) ) {
|
||||
// All worktime in downtime, ignore
|
||||
break;
|
||||
}
|
||||
if ( ( $wt_start >= $pd["date_from"])
|
||||
&& ( $wt_start <= $pd["date_to"])
|
||||
&& ( $wt_end > $pd["date_to"]) ) {
|
||||
// Begin of the worktime in downtime, adjust.
|
||||
// Search for end of worktime.
|
||||
$wt_start = $pd["date_to"];
|
||||
$start_fixed = 1;
|
||||
}
|
||||
if ( ( $wt_start < $pd["date_from"])
|
||||
&& ( $wt_end > $pd["date_to"]) ) {
|
||||
// Begin of the worktime in downtime, adjust.
|
||||
// Search for end of worktime.
|
||||
$worktime[$i]= array();
|
||||
$worktime[$i]["date_from"] = $wt_start;
|
||||
$worktime[$i]["date_to"] = $pd["date_from"];
|
||||
$i++;
|
||||
$wt_start = $pd["date_to"];
|
||||
$start_fixed = 1;
|
||||
}
|
||||
|
||||
if ( ($start_fixed == 1) && (($i_planned_downtimes+1) == $n_planned_downtimes) ) {
|
||||
// There's no more planned downtimes, accept remaining range
|
||||
$worktime[$i]= array();
|
||||
$worktime[$i]["date_from"] = $wt_start;
|
||||
$worktime[$i]["date_to"] = $wt_end;
|
||||
$i++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// No planned downtimes scheduled
|
||||
$worktime[$i]= array();
|
||||
$worktime[$i]["date_from"] = $wt_start;
|
||||
$worktime[$i]["date_to"] = $wt_end;
|
||||
$i++;
|
||||
}
|
||||
}
|
||||
$t_day+=SECONDS_1DAY;
|
||||
} // End while -> build matrix
|
||||
} // End else (prepare fixed matrix)
|
||||
} // Finished: Build exceptions
|
||||
|
||||
// DEBUG
|
||||
// print "Umcompressed data debug:\n";
|
||||
// foreach ($uncompressed_data as $k => $caja) {
|
||||
// print "caja: $k\t" . $caja["utimestamp"] . "\n";
|
||||
// foreach ($caja["data"] as $dato) {
|
||||
// print "\t" . $dato["utimestamp"] . "\t" . $dato["datos"] . "\t" . date("Y/m/d H:i:s",$dato["utimestamp"]) . "\t" . $dato["obs"] . "\n";
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
// Initialization
|
||||
$global_return = array();
|
||||
|
||||
$wt_check["idx"] = 0;
|
||||
$last_pool_id = 0;
|
||||
$last_item_id = 0;
|
||||
|
||||
// Support to slices
|
||||
$global_datetime_from = $datetime_from;
|
||||
$global_datetime_to = $datetime_to;
|
||||
$range = ($datetime_to - $datetime_from) / $slices;
|
||||
|
||||
// Analysis begins
|
||||
for ($count=0; $count < $slices; $count++) {
|
||||
|
||||
$datetime_from = $global_datetime_from + ($count*$range);
|
||||
$datetime_to = $global_datetime_from + (($count+1)*$range);
|
||||
|
||||
$return = array();
|
||||
// timing
|
||||
$time_total = 0;
|
||||
$time_in_ok = 0;
|
||||
$time_in_error = 0;
|
||||
$time_in_unknown = 0;
|
||||
$time_in_not_init = 0;
|
||||
|
||||
// checks
|
||||
$bad_checks = 0;
|
||||
$ok_checks = 0;
|
||||
$not_init_checks = 0;
|
||||
$unknown_checks = 0;
|
||||
$total_checks = 0;
|
||||
|
||||
if (is_array($uncompressed_data)) {
|
||||
|
||||
$n_pools = count($uncompressed_data);
|
||||
for($pool_index = $last_pool_id; $pool_index < $n_pools; $pool_index++ ) {
|
||||
$pool = $uncompressed_data[$pool_index];
|
||||
|
||||
// check limits
|
||||
if (isset($uncompressed_data[$pool_index+1])) {
|
||||
$next_pool = $uncompressed_data[$pool_index+1];
|
||||
}
|
||||
else {
|
||||
$next_pool = null;
|
||||
}
|
||||
if (isset($next_pool)) {
|
||||
$pool["next_utimestamp"] = $next_pool["utimestamp"];
|
||||
}
|
||||
else {
|
||||
$pool["next_utimestamp"] = $global_datetime_to;
|
||||
}
|
||||
|
||||
// update last pool checked: avoid repetition
|
||||
$last_pool_id = $pool_index;
|
||||
|
||||
|
||||
if ($datetime_from > $pool["utimestamp"]) {
|
||||
# Skip pool
|
||||
continue;
|
||||
}
|
||||
|
||||
// Test if need to acquire current pool
|
||||
if ( (($datetime_from <= $pool["utimestamp"]) && ($datetime_to >= $pool["next_utimestamp"]))
|
||||
|| ($datetime_to > $pool["utimestamp"]) ) {
|
||||
|
||||
# Acquire pool to this slice
|
||||
|
||||
$nitems_in_pool = count($pool["data"]);
|
||||
for ($i=0; $i < $nitems_in_pool; $i++ ) {
|
||||
$current_data = $pool["data"][$i];
|
||||
|
||||
if (($i+1) >= $nitems_in_pool) {
|
||||
// if pool exceded, check next pool timestamp
|
||||
$next_data = $next_pool;
|
||||
}
|
||||
else {
|
||||
// pool not exceded, check next item
|
||||
$next_data = $pool["data"][$i+1];
|
||||
}
|
||||
|
||||
if (isset ($next_data["utimestamp"])) {
|
||||
// check next mark time in current pool
|
||||
$next_timestamp = $next_data["utimestamp"];
|
||||
|
||||
}
|
||||
else {
|
||||
// check last time -> datetime_to
|
||||
if (!isset($next_pool)) {
|
||||
$next_timestamp = $global_datetime_to;
|
||||
}
|
||||
else {
|
||||
$next_timestamp = $datetime_to;
|
||||
}
|
||||
}
|
||||
|
||||
// Effective time limits for current data
|
||||
$wt_start = $current_data["utimestamp"];
|
||||
$wt_end = $next_timestamp;
|
||||
|
||||
// Remove time spent in planned downtime and not in planning
|
||||
$wt_check = sla_fixed_worktime($wt_start, $wt_end, $worktime, $wt_check["idx"]);
|
||||
$time_interval = $wt_check["interval"];
|
||||
if ($time_interval == 0){
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($wt_check["wt_valid"] == 1) {
|
||||
$total_checks++;
|
||||
$time_total += $time_interval;
|
||||
if ((isset ($current_data["datos"])) && ($current_data["datos"] !== false)) {
|
||||
// not unknown nor not init values
|
||||
if (sla_check_value($current_data["datos"],$min_value, $max_value, $inverse_interval)) {
|
||||
$ok_checks++;
|
||||
$time_in_ok += $time_interval;
|
||||
|
||||
}
|
||||
else {
|
||||
$bad_checks++;
|
||||
$time_in_error += $time_interval;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if($current_data["datos"] === null) {
|
||||
$time_in_unknown += $time_interval;
|
||||
$unknown_checks++;
|
||||
}
|
||||
elseif ($current_data["datos"] === false) {
|
||||
$time_in_not_init += $time_interval;
|
||||
$not_init_checks++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// ignore worktime, is in an invalid period:
|
||||
// scheduled downtimes
|
||||
// not 24x7 sla's
|
||||
}
|
||||
} // End of pool items analysis (for)
|
||||
|
||||
} // End analysis of pool acquired
|
||||
else {
|
||||
break;
|
||||
}
|
||||
|
||||
} // End of pool analysis (for)
|
||||
}
|
||||
else {
|
||||
// If monitor in not-init status => no data to show
|
||||
$time_in_not_init = $datetime_to - $datetime_from;
|
||||
$not_init_checks++;
|
||||
}
|
||||
|
||||
|
||||
// Timing
|
||||
$return["time_total"] = $time_total;
|
||||
$return["time_ok"] = $time_in_ok;
|
||||
$return["time_error"] = $time_in_error;
|
||||
$return["time_unknown"] = $time_in_unknown;
|
||||
$return["time_not_init"] = $time_in_not_init;
|
||||
|
||||
// # Checks
|
||||
$return["checks_total"] = $total_checks;
|
||||
$return["checks_ok"] = $ok_checks;
|
||||
$return["checks_error"] = $bad_checks;
|
||||
$return["checks_unknown"] = $unknown_checks;
|
||||
$return["checks_not_init"] = $not_init_checks;
|
||||
|
||||
// SLA
|
||||
if (($time_in_error+$time_in_ok) == 0) {
|
||||
$return["SLA"] = 0;
|
||||
}
|
||||
else {
|
||||
$return["SLA"] = (($time_in_ok/($time_in_error+$time_in_ok))*100);
|
||||
}
|
||||
|
||||
// SLA
|
||||
$return["SLA_fixed"] = sla_truncate($return["SLA"], $config['graph_precision']);
|
||||
|
||||
if ($slices > 1) {
|
||||
array_push($global_return, $return);
|
||||
}
|
||||
|
||||
} // end of slice analysis (for)
|
||||
|
||||
if ($slices > 1) {
|
||||
return $global_return;
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
function reporting_availability($report, $content, $date=false, $time=false) {
|
||||
global $config;
|
||||
|
||||
|
|
Loading…
Reference in New Issue