SLA algorythm 2.0

This commit is contained in:
fbsanchez 2016-11-17 17:31:09 +01:00
parent ed69265fb7
commit b1f400ac0d
2 changed files with 1083 additions and 0 deletions

View File

@ -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.
*

View File

@ -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;