mirror of
https://github.com/pandorafms/pandorafms.git
synced 2025-07-28 00:04:37 +02:00
Some fixed for the enterprise PDF reports.
This commit is contained in:
parent
98d9032034
commit
4387c36bbf
@ -462,6 +462,18 @@ function reporting_SLA($report, $content, $type = 'dinamic',
|
|||||||
$return["date"] = reporting_get_date_text($report, $content);
|
$return["date"] = reporting_get_date_text($report, $content);
|
||||||
|
|
||||||
|
|
||||||
|
// Get chart
|
||||||
|
reporting_set_conf_charts($width, $height, $only_image, $type,
|
||||||
|
$content, $ttl);
|
||||||
|
|
||||||
|
if (!empty($force_width_chart)) {
|
||||||
|
$width = $force_width_chart;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($force_height_chart)) {
|
||||||
|
$height = $force_height_chart;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
$edge_interval = 10;
|
$edge_interval = 10;
|
||||||
|
|
||||||
@ -777,8 +789,10 @@ function reporting_SLA($report, $content, $type = 'dinamic',
|
|||||||
|
|
||||||
if ($show_table) {
|
if ($show_table) {
|
||||||
$data = array ();
|
$data = array ();
|
||||||
$data['agent'] = modules_get_agentmodule_agent_name ($sla['id_agent_module']);
|
$data['agent'] = modules_get_agentmodule_agent_name(
|
||||||
$data['module'] = modules_get_agentmodule_name ($sla['id_agent_module']);
|
$sla['id_agent_module']);
|
||||||
|
$data['module'] = modules_get_agentmodule_name(
|
||||||
|
$sla['id_agent_module']);
|
||||||
$data['max'] = $sla['sla_max'];
|
$data['max'] = $sla['sla_max'];
|
||||||
$data['min'] = $sla['sla_min'];
|
$data['min'] = $sla['sla_min'];
|
||||||
$data['sla_limit'] = $sla['sla_limit'];
|
$data['sla_limit'] = $sla['sla_limit'];
|
||||||
@ -827,10 +841,20 @@ function reporting_SLA($report, $content, $type = 'dinamic',
|
|||||||
$dataslice['module'] = modules_get_agentmodule_name ($sla['id_agent_module']);
|
$dataslice['module'] = modules_get_agentmodule_name ($sla['id_agent_module']);
|
||||||
|
|
||||||
$dataslice['chart'] = graph_sla_slicebar(
|
$dataslice['chart'] = graph_sla_slicebar(
|
||||||
$sla['id_agent_module'], $content['period'],
|
$sla['id_agent_module'],
|
||||||
$sla['sla_min'], $sla['sla_max'],
|
$content['period'],
|
||||||
$report['datetime'], $content, $content['time_from'],
|
$sla['sla_min'],
|
||||||
$content['time_to'], 650, 25, $urlImage, 1, false, false);
|
$sla['sla_max'],
|
||||||
|
$report['datetime'],
|
||||||
|
$content,
|
||||||
|
$content['time_from'],
|
||||||
|
$content['time_to'],
|
||||||
|
650,
|
||||||
|
25,
|
||||||
|
$urlImage,
|
||||||
|
$ttl,
|
||||||
|
false,
|
||||||
|
false);
|
||||||
|
|
||||||
$return['charts'][] = $dataslice;
|
$return['charts'][] = $dataslice;
|
||||||
}
|
}
|
||||||
@ -6717,4 +6741,662 @@ function reporting_get_agentmodule_data_sum ($id_agent_module,
|
|||||||
|
|
||||||
return $total;
|
return $total;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the planned downtimes that affect the passed modules on an specific datetime range.
|
||||||
|
*
|
||||||
|
* @param int Start date in utimestamp.
|
||||||
|
* @param int End date in utimestamp.
|
||||||
|
* @param array The agent modules ids.
|
||||||
|
*
|
||||||
|
* @return Array with the planned downtimes that are executed in any moment of the range selected and affect the
|
||||||
|
* agent modules selected.
|
||||||
|
*/
|
||||||
|
function reporting_get_planned_downtimes ($start_date, $end_date, $id_agent_modules = false) {
|
||||||
|
$start_time = date("H:i:s", $start_date);
|
||||||
|
$end_time = date("H:i:s", $end_date);
|
||||||
|
|
||||||
|
$start_day = date("d", $start_date);
|
||||||
|
$end_day = date("d", $end_date);
|
||||||
|
|
||||||
|
$start_month = date("m", $start_date);
|
||||||
|
$end_month = date("m", $end_date);
|
||||||
|
|
||||||
|
if ($start_date > $end_date) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($end_date - $start_date >= SECONDS_1MONTH) {
|
||||||
|
// If the date range is larger than 1 month, every monthly planned downtime will be inside
|
||||||
|
$periodically_monthly_w = "type_periodicity = 'monthly'";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Check if the range is larger than the planned downtime execution, or if its start or end
|
||||||
|
// is inside the planned downtime execution.
|
||||||
|
// The start and end time is very important.
|
||||||
|
$periodically_monthly_w = "type_periodicity = 'monthly'
|
||||||
|
AND (((periodically_day_from > '$start_day'
|
||||||
|
OR (periodically_day_from = '$start_day'
|
||||||
|
AND periodically_time_from >= '$start_time'))
|
||||||
|
AND (periodically_day_to < '$end_day'
|
||||||
|
OR (periodically_day_to = '$end_day'
|
||||||
|
AND periodically_time_to <= '$end_time')))
|
||||||
|
OR ((periodically_day_from < '$start_day'
|
||||||
|
OR (periodically_day_from = '$start_day'
|
||||||
|
AND periodically_time_from <= '$start_time'))
|
||||||
|
AND (periodically_day_to > '$start_day'
|
||||||
|
OR (periodically_day_to = '$start_day'
|
||||||
|
AND periodically_time_to >= '$start_time')))
|
||||||
|
OR ((periodically_day_from < '$end_day'
|
||||||
|
OR (periodically_day_from = '$end_day'
|
||||||
|
AND periodically_time_from <= '$end_time'))
|
||||||
|
AND (periodically_day_to > '$end_day'
|
||||||
|
OR (periodically_day_to = '$end_day'
|
||||||
|
AND periodically_time_to >= '$end_time'))))";
|
||||||
|
}
|
||||||
|
|
||||||
|
$periodically_weekly_days = array();
|
||||||
|
$date_aux = $start_date;
|
||||||
|
$i = 0;
|
||||||
|
|
||||||
|
if (($end_date - $start_date) >= SECONDS_1WEEK) {
|
||||||
|
// If the date range is larger than 7 days, every weekly planned downtime will be inside.
|
||||||
|
for ($i = 0; $i < 7; $i++) {
|
||||||
|
$weekday_actual = strtolower(date('l', $date_aux));
|
||||||
|
$periodically_weekly_days[] = "($weekday_actual = 1)";
|
||||||
|
$date_aux += SECONDS_1DAY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (($end_date - $start_date) <= SECONDS_1DAY && $start_day == $end_day) {
|
||||||
|
// If the date range is smaller than 1 day, the start and end days can be equal or consecutive.
|
||||||
|
// If they are equal, the execution times have to be contained in the date range times or contain
|
||||||
|
// the start or end time of the date range.
|
||||||
|
$weekday_actual = strtolower(date('l', $start_date));
|
||||||
|
$periodically_weekly_days[] = "($weekday_actual = 1
|
||||||
|
AND ((periodically_time_from > '$start_time' AND periodically_time_to < '$end_time')
|
||||||
|
OR (periodically_time_from = '$start_time'
|
||||||
|
OR (periodically_time_from < '$start_time'
|
||||||
|
AND periodically_time_to >= '$start_time'))
|
||||||
|
OR (periodically_time_from = '$end_time'
|
||||||
|
OR (periodically_time_from < '$end_time'
|
||||||
|
AND periodically_time_to >= '$end_time'))))";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
while ($date_aux <= $end_date && $i < 7) {
|
||||||
|
|
||||||
|
$weekday_actual = strtolower(date('l', $date_aux));
|
||||||
|
$day_num_actual = date('d', $date_aux);
|
||||||
|
|
||||||
|
if ($date_aux == $start_date) {
|
||||||
|
$periodically_weekly_days[] = "($weekday_actual = 1 AND periodically_time_to >= '$start_time')";
|
||||||
|
}
|
||||||
|
else if ($day_num_actual == $end_day) {
|
||||||
|
$periodically_weekly_days[] = "($weekday_actual = 1 AND periodically_time_from <= '$end_time')";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$periodically_weekly_days[] = "($weekday_actual = 1)";
|
||||||
|
}
|
||||||
|
|
||||||
|
$date_aux += SECONDS_1DAY;
|
||||||
|
$i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($periodically_weekly_days)) {
|
||||||
|
$periodically_weekly_w = "type_periodicity = 'weekly' AND (".implode(" OR ", $periodically_weekly_days).")";
|
||||||
|
$periodically_condition = "(($periodically_monthly_w) OR ($periodically_weekly_w))";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$periodically_condition = "($periodically_monthly_w)";
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($id_agent_modules !== false) {
|
||||||
|
if (empty($id_agent_modules))
|
||||||
|
return array();
|
||||||
|
|
||||||
|
$id_agent_modules_str = implode(",", $id_agent_modules);
|
||||||
|
|
||||||
|
$sql_downtime = "SELECT DISTINCT(tpdr.id), tpdr.*
|
||||||
|
FROM (
|
||||||
|
SELECT tpd.*
|
||||||
|
FROM tplanned_downtime tpd, tplanned_downtime_agents tpda, tagente_modulo tam
|
||||||
|
WHERE (tpd.id = tpda.id_downtime
|
||||||
|
AND tpda.all_modules = 1
|
||||||
|
AND tpda.id_agent = tam.id_agente
|
||||||
|
AND tam.id_agente_modulo IN ($id_agent_modules_str))
|
||||||
|
AND ((type_execution = 'periodically'
|
||||||
|
AND $periodically_condition)
|
||||||
|
OR (type_execution = 'once'
|
||||||
|
AND ((date_from >= '$start_date' AND date_to <= '$end_date')
|
||||||
|
OR (date_from <= '$start_date' AND date_to >= '$end_date')
|
||||||
|
OR (date_from <= '$start_date' AND date_to >= '$start_date')
|
||||||
|
OR (date_from <= '$end_date' AND date_to >= '$end_date'))))
|
||||||
|
UNION ALL
|
||||||
|
SELECT tpd.*
|
||||||
|
FROM tplanned_downtime tpd, tplanned_downtime_modules tpdm
|
||||||
|
WHERE (tpd.id = tpdm.id_downtime
|
||||||
|
AND tpdm.id_agent_module IN ($id_agent_modules_str))
|
||||||
|
AND ((type_execution = 'periodically'
|
||||||
|
AND $periodically_condition)
|
||||||
|
OR (type_execution = 'once'
|
||||||
|
AND ((date_from >= '$start_date' AND date_to <= '$end_date')
|
||||||
|
OR (date_from <= '$start_date' AND date_to >= '$end_date')
|
||||||
|
OR (date_from <= '$start_date' AND date_to >= '$start_date')
|
||||||
|
OR (date_from <= '$end_date' AND date_to >= '$end_date'))))
|
||||||
|
) tpdr
|
||||||
|
ORDER BY tpdr.id";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$sql_downtime = "SELECT *
|
||||||
|
FROM tplanned_downtime tpd, tplanned_downtime_modules tpdm
|
||||||
|
WHERE (type_execution = 'periodically'
|
||||||
|
AND $periodically_condition)
|
||||||
|
OR (type_execution = 'once'
|
||||||
|
AND ((date_from >= '$start_date' AND date_to <= '$end_date')
|
||||||
|
OR (date_from <= '$start_date' AND date_to >= '$end_date')
|
||||||
|
OR (date_from <= '$start_date' AND date_to >= '$start_date')
|
||||||
|
OR (date_from <= '$end_date' AND date_to >= '$end_date')))";
|
||||||
|
}
|
||||||
|
|
||||||
|
$downtimes = db_get_all_rows_sql($sql_downtime);
|
||||||
|
if ($downtimes == false) {
|
||||||
|
$downtimes = array();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $downtimes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get SLA of a module.
|
||||||
|
*
|
||||||
|
* @param int Agent module to calculate SLA
|
||||||
|
* @param int Period to check the SLA compliance.
|
||||||
|
* @param int Minimum data value the module in the right interval
|
||||||
|
* @param int Maximum data value the module in the right interval. False will
|
||||||
|
* ignore max value
|
||||||
|
* @param int Beginning date of the report in UNIX time (current date by default).
|
||||||
|
* @param array $dayWeek Array of days week to extract as array('monday' => false, 'tuesday' => true....), and by default is null.
|
||||||
|
* @param string $timeFrom Time in the day to start to extract in mysql format, by default null.
|
||||||
|
* @param string $timeTo Time in the day to end to extract in mysql format, by default null.
|
||||||
|
*
|
||||||
|
* @return float SLA percentage of the requested module. False if no data were
|
||||||
|
* found
|
||||||
|
*/
|
||||||
|
function reporting_get_agentmodule_sla_day ($id_agent_module, $period = 0, $min_value = 1, $max_value = false, $date = 0, $daysWeek = null, $timeFrom = null, $timeTo = null) {
|
||||||
|
global $config;
|
||||||
|
|
||||||
|
if (empty($id_agent_module))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Initialize variables
|
||||||
|
if (empty ($date)) {
|
||||||
|
$date = get_system_time ();
|
||||||
|
}
|
||||||
|
if ($daysWeek === null) {
|
||||||
|
$daysWeek = array();
|
||||||
|
}
|
||||||
|
// Limit date to start searching data
|
||||||
|
$datelimit = $date - $period;
|
||||||
|
|
||||||
|
$search_in_history_db = db_search_in_history_db($datelimit);
|
||||||
|
|
||||||
|
// Get interval data
|
||||||
|
$sql = sprintf ('SELECT *
|
||||||
|
FROM tagente_datos
|
||||||
|
WHERE id_agente_modulo = %d
|
||||||
|
AND utimestamp > %d AND utimestamp <= %d',
|
||||||
|
$id_agent_module, $datelimit, $date);
|
||||||
|
|
||||||
|
//Add the working times (mon - tue - wed ...) and from time to time
|
||||||
|
$days = array();
|
||||||
|
//Translate to mysql week days
|
||||||
|
if ($daysWeek) {
|
||||||
|
foreach ($daysWeek as $key => $value) {
|
||||||
|
if (!$value) {
|
||||||
|
if ($key == 'monday') {
|
||||||
|
$days[] = 2;
|
||||||
|
}
|
||||||
|
if ($key == 'tuesday') {
|
||||||
|
$days[] = 3;
|
||||||
|
}
|
||||||
|
if ($key == 'wednesday') {
|
||||||
|
$days[] = 4;
|
||||||
|
}
|
||||||
|
if ($key == 'thursday') {
|
||||||
|
$days[] = 5;
|
||||||
|
}
|
||||||
|
if ($key == 'friday') {
|
||||||
|
$days[] = 6;
|
||||||
|
}
|
||||||
|
if ($key == 'saturday') {
|
||||||
|
$days[] = 7;
|
||||||
|
}
|
||||||
|
if ($key == 'sunday') {
|
||||||
|
$days[] = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count($days) > 0) {
|
||||||
|
$sql .= ' AND DAYOFWEEK(FROM_UNIXTIME(utimestamp)) NOT IN (' . implode(',', $days) . ')';
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($timeFrom < $timeTo) {
|
||||||
|
$sql .= ' AND (TIME(FROM_UNIXTIME(utimestamp)) >= "' . $timeFrom . '" AND TIME(FROM_UNIXTIME(utimestamp)) <= "'. $timeTo . '")';
|
||||||
|
}
|
||||||
|
elseif ($timeFrom > $timeTo) {
|
||||||
|
$sql .= ' AND (TIME(FROM_UNIXTIME(utimestamp)) >= "' . $timeFrom . '" OR TIME(FROM_UNIXTIME(utimestamp)) <= "'. $timeTo . '")';
|
||||||
|
}
|
||||||
|
$sql .= ' ORDER BY utimestamp ASC';
|
||||||
|
$interval_data = db_get_all_rows_sql ($sql, $search_in_history_db);
|
||||||
|
|
||||||
|
if ($interval_data === false) {
|
||||||
|
$interval_data = array ();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate planned downtime dates
|
||||||
|
$downtime_dates = reporting_get_planned_downtimes_intervals($id_agent_module, $datelimit, $date);
|
||||||
|
|
||||||
|
// Get previous data
|
||||||
|
$previous_data = modules_get_previous_data ($id_agent_module, $datelimit);
|
||||||
|
|
||||||
|
if ($previous_data !== false) {
|
||||||
|
$previous_data['utimestamp'] = $datelimit;
|
||||||
|
array_unshift ($interval_data, $previous_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get next data
|
||||||
|
$next_data = modules_get_next_data ($id_agent_module, $date);
|
||||||
|
|
||||||
|
if ($next_data !== false) {
|
||||||
|
$next_data['utimestamp'] = $date;
|
||||||
|
array_push ($interval_data, $next_data);
|
||||||
|
}
|
||||||
|
else if (count ($interval_data) > 0) {
|
||||||
|
// Propagate the last known data to the end of the interval
|
||||||
|
$next_data = array_pop ($interval_data);
|
||||||
|
array_push ($interval_data, $next_data);
|
||||||
|
$next_data['utimestamp'] = $date;
|
||||||
|
array_push ($interval_data, $next_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count ($interval_data) < 2) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set initial conditions
|
||||||
|
$bad_period = 0;
|
||||||
|
$first_data = array_shift ($interval_data);
|
||||||
|
|
||||||
|
// Do not count the empty start of an interval as 0
|
||||||
|
if ($first_data['utimestamp'] != $datelimit) {
|
||||||
|
$period = $date - $first_data['utimestamp'];
|
||||||
|
}
|
||||||
|
|
||||||
|
$previous_utimestamp = $first_data['utimestamp'];
|
||||||
|
if ((($max_value > $min_value AND ($first_data['datos'] > $max_value OR $first_data['datos'] < $min_value))) OR
|
||||||
|
($max_value <= $min_value AND $first_data['datos'] < $min_value)) {
|
||||||
|
|
||||||
|
$previous_status = 1;
|
||||||
|
foreach ($downtime_dates as $date_dt) {
|
||||||
|
if (($date_dt['date_from'] <= $previous_utimestamp) AND ($date_dt['date_to'] >= $previous_utimestamp)) {
|
||||||
|
$previous_status = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$previous_status = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
foreach ($interval_data as $data) {
|
||||||
|
// Previous status was critical
|
||||||
|
if ($previous_status == 1) {
|
||||||
|
$bad_period += $data['utimestamp'] - $previous_utimestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (array_key_exists('datos', $data)) {
|
||||||
|
// Re-calculate previous status for the next data
|
||||||
|
if ((($max_value > $min_value AND ($data['datos'] > $max_value OR $data['datos'] < $min_value))) OR
|
||||||
|
($max_value <= $min_value AND $data['datos'] < $min_value)) {
|
||||||
|
|
||||||
|
$previous_status = 1;
|
||||||
|
foreach ($downtime_dates as $date_dt) {
|
||||||
|
if (($date_dt['date_from'] <= $data['utimestamp']) AND ($date_dt['date_to'] >= $data['utimestamp'])) {
|
||||||
|
$previous_status = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$previous_status = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$previous_utimestamp = $data['utimestamp'];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the percentage of SLA compliance
|
||||||
|
return (float) (100 - ($bad_period / $period) * 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get several SLA data for an agentmodule within a period divided on subperiods
|
||||||
|
*
|
||||||
|
* @param int Agent module to calculate SLA
|
||||||
|
* @param int Period to check the SLA compliance.
|
||||||
|
* @param int Minimum data value the module in the right interval
|
||||||
|
* @param int Maximum data value the module in the right interval. False will
|
||||||
|
* ignore max value
|
||||||
|
* @param array $days Array of days week to extract as array('monday' => false, 'tuesday' => true....), and by default is null.
|
||||||
|
* @param string $timeFrom Time in the day to start to extract in mysql format, by default null.
|
||||||
|
* @param string $timeTo Time in the day to end to extract in mysql format, by default null.
|
||||||
|
*
|
||||||
|
* @return Array with values either 1, 2, 3 or 4 depending if the SLA percentage for this subperiod
|
||||||
|
* is within the sla limits, on the edge, outside or with an unknown value.
|
||||||
|
*/
|
||||||
|
function reporting_get_agentmodule_sla_array ($id_agent_module, $period = 0, $min_value = 1, $max_value = false, $date = 0, $daysWeek = null, $timeFrom = null, $timeTo = null) {
|
||||||
|
global $config;
|
||||||
|
|
||||||
|
if (empty($id_agent_module))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Initialize variables
|
||||||
|
if (empty ($date)) {
|
||||||
|
$date = get_system_time ();
|
||||||
|
}
|
||||||
|
if ($daysWeek === null) {
|
||||||
|
$daysWeek = array();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hotfix: The edge values are confuse to the users
|
||||||
|
$percent = 0;
|
||||||
|
|
||||||
|
// Limit date to start searching data
|
||||||
|
$datelimit = $date - $period;
|
||||||
|
|
||||||
|
$search_in_history_db = db_search_in_history_db($datelimit);
|
||||||
|
|
||||||
|
// Get interval data
|
||||||
|
$sql = sprintf ('SELECT * FROM tagente_datos
|
||||||
|
WHERE id_agente_modulo = %d
|
||||||
|
AND utimestamp > %d AND utimestamp <= %d',
|
||||||
|
$id_agent_module, $datelimit, $date);
|
||||||
|
|
||||||
|
//Add the working times (mon - tue - wed ...) and from time to time
|
||||||
|
$days = array();
|
||||||
|
//Translate to mysql week days
|
||||||
|
|
||||||
|
if ($daysWeek) {
|
||||||
|
foreach ($daysWeek as $key => $value) {
|
||||||
|
if (!$value) {
|
||||||
|
if ($key == 'monday') {
|
||||||
|
$days[] = 2;
|
||||||
|
}
|
||||||
|
if ($key == 'tuesday') {
|
||||||
|
$days[] = 3;
|
||||||
|
}
|
||||||
|
if ($key == 'wednesday') {
|
||||||
|
$days[] = 4;
|
||||||
|
}
|
||||||
|
if ($key == 'thursday') {
|
||||||
|
$days[] = 5;
|
||||||
|
}
|
||||||
|
if ($key == 'friday') {
|
||||||
|
$days[] = 6;
|
||||||
|
}
|
||||||
|
if ($key == 'saturday') {
|
||||||
|
$days[] = 7;
|
||||||
|
}
|
||||||
|
if ($key == 'sunday') {
|
||||||
|
$days[] = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count($days) > 0) {
|
||||||
|
$sql .= ' AND DAYOFWEEK(FROM_UNIXTIME(utimestamp)) NOT IN (' . implode(',', $days) . ')';
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($timeFrom != $timeTo) {
|
||||||
|
if ($timeFrom < $timeTo) {
|
||||||
|
$sql .= ' AND (TIME(FROM_UNIXTIME(utimestamp)) >= "' . $timeFrom . '" AND TIME(FROM_UNIXTIME(utimestamp)) <= "'. $timeTo . '")';
|
||||||
|
}
|
||||||
|
elseif ($timeFrom > $timeTo) {
|
||||||
|
$sql .= ' AND (TIME(FROM_UNIXTIME(utimestamp)) >= "' . $timeFrom . '" OR TIME(FROM_UNIXTIME(utimestamp)) <= "'. $timeTo . '")';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$sql .= ' ORDER BY utimestamp ASC';
|
||||||
|
$interval_data = db_get_all_rows_sql ($sql, $search_in_history_db);
|
||||||
|
|
||||||
|
if ($interval_data === false) {
|
||||||
|
$interval_data = array ();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Indexing data
|
||||||
|
$interval_data_indexed = array();
|
||||||
|
foreach($interval_data as $idata) {
|
||||||
|
$interval_data_indexed[$idata['utimestamp']]['data'] = $idata['datos'];
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------Calculate unknown status events------------------------
|
||||||
|
$events_unknown = db_get_all_rows_filter ('tevento',
|
||||||
|
array ('id_agentmodule' => $id_agent_module,
|
||||||
|
"utimestamp > $datelimit",
|
||||||
|
"utimestamp < $date",
|
||||||
|
'order' => 'utimestamp ASC'),
|
||||||
|
array ('id_evento', 'evento', 'timestamp', 'utimestamp', 'event_type'));
|
||||||
|
|
||||||
|
if ($events_unknown === false) {
|
||||||
|
$events_unknown = array ();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add unknown periods to data
|
||||||
|
for ($i = 0; isset($events_unknown[$i]); $i++) {
|
||||||
|
$eu = $events_unknown[$i];
|
||||||
|
|
||||||
|
if ($eu['event_type'] == 'going_unknown') {
|
||||||
|
$interval_data_indexed[$eu['utimestamp']]['data'] = 0;
|
||||||
|
$interval_data_indexed[$eu['utimestamp']]['status'] = 4;
|
||||||
|
|
||||||
|
// Search the corresponding recovery event.
|
||||||
|
for ($j = $i+1; isset($events_unknown[$j]); $j++) {
|
||||||
|
$eu = $events_unknown[$j];
|
||||||
|
|
||||||
|
if ($eu['event_type'] != 'going_unknown' && substr ($eu['event_type'], 0, 5) == 'going') {
|
||||||
|
$interval_data_indexed[$eu['utimestamp']]['data'] = 0;
|
||||||
|
$interval_data_indexed[$eu['utimestamp']]['status'] = 6;
|
||||||
|
|
||||||
|
// Do not process read events again.
|
||||||
|
$i = $j;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the last event before inverval to know if graph start on unknown
|
||||||
|
$prev_event = db_get_row_filter ('tevento',
|
||||||
|
array ('id_agentmodule' => $id_agent_module,
|
||||||
|
"utimestamp <= $datelimit",
|
||||||
|
'order' => 'utimestamp DESC'));
|
||||||
|
if (isset($prev_event['event_type']) && $prev_event['event_type'] == 'going_unknown') {
|
||||||
|
$start_unknown = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$start_unknown = false;
|
||||||
|
}
|
||||||
|
//------------------------------------------------------------------
|
||||||
|
|
||||||
|
//-----------------Set limits of the interval-----------------------
|
||||||
|
// Get previous data (This adds the first data if the begin of module data is after the begin time interval)
|
||||||
|
$previous_data = modules_get_previous_data ($id_agent_module, $datelimit);
|
||||||
|
if ($previous_data !== false ) {
|
||||||
|
$previous_value = $previous_data['datos'];
|
||||||
|
// if ((($previous_value > ($min_value - $percent)) && ($previous_value < ($min_value + $percent))) ||
|
||||||
|
// (($previous_value > ($max_value - $percent)) && ($previous_value < ($max_value + $percent)))) {//2 when value is within the edges
|
||||||
|
// $previous_known_status = 2;
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
if (($previous_value >= ($min_value + $percent)) && ($previous_value <= ($max_value - $percent))) { //1 when value is OK
|
||||||
|
$previous_known_status = 1;
|
||||||
|
}
|
||||||
|
elseif (($previous_value <= ($min_value - $percent)) || ($previous_value >= ($max_value + $percent))) { //3 when value is Wrong
|
||||||
|
$previous_known_status = 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the starting of the graph is unknown we set it
|
||||||
|
if ($start_unknown) {
|
||||||
|
$interval_data_indexed[$datelimit]['data'] = 0;
|
||||||
|
$interval_data_indexed[$datelimit]['status'] = 4;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if ($previous_data !== false ) {
|
||||||
|
$interval_data_indexed[$datelimit]['data'] = $previous_data['datos'];
|
||||||
|
}
|
||||||
|
else { // If there are not data befor interval set unknown
|
||||||
|
$interval_data_indexed[$datelimit]['data'] = 0;
|
||||||
|
$interval_data_indexed[$datelimit]['status'] = 4;
|
||||||
|
$previous_known_status = 1; // Assume the module was in normal status if there is no previous data.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get next data (This adds data before the interval of the report)
|
||||||
|
$next_data = modules_get_next_data ($id_agent_module, $date);
|
||||||
|
|
||||||
|
if ($next_data !== false) {
|
||||||
|
$interval_data_indexed[$date]['data'] = $previous_data['datos'];
|
||||||
|
}
|
||||||
|
else if (count ($interval_data_indexed) > 0) {
|
||||||
|
// Propagate the last known data to the end of the interval (if there is no module data at the end point)
|
||||||
|
ksort($interval_data_indexed);
|
||||||
|
$last_data = end($interval_data_indexed);
|
||||||
|
$interval_data_indexed[$date] = $last_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------
|
||||||
|
|
||||||
|
//--------Calculate planned downtime dates--------------------------
|
||||||
|
$downtime_dates = reporting_get_planned_downtimes_intervals($id_agent_module, $datelimit, $date);
|
||||||
|
|
||||||
|
foreach ($downtime_dates as $downtime_date) {
|
||||||
|
// Delete data of the planned downtime and put the last data on the upper limit
|
||||||
|
$interval_data_indexed[$downtime_date['date_from']]['data'] = 0;
|
||||||
|
$interval_data_indexed[$downtime_date['date_from']]['status'] = 5;
|
||||||
|
$interval_data_indexed[$downtime_date['date_to']]['data'] = 0;
|
||||||
|
$interval_data_indexed[$downtime_date['date_to']]['status'] = 4;
|
||||||
|
|
||||||
|
$last_downtime_data = false;
|
||||||
|
foreach ($interval_data_indexed as $idi_timestamp => $idi) {
|
||||||
|
if ($idi_timestamp != $downtime_date['date_from'] && $idi_timestamp != $downtime_date['date_to'] &&
|
||||||
|
$idi_timestamp >= $downtime_date['date_from'] && $idi_timestamp <= $downtime_date['date_to']) {
|
||||||
|
$last_downtime_data = $idi['data'];
|
||||||
|
unset($interval_data_indexed[$idi_timestamp]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the last data of the interval as limit
|
||||||
|
if ($last_downtime_data !== false) {
|
||||||
|
$interval_data_indexed[$downtime_date['date_to']]['data'] = $last_downtime_data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Sort the array
|
||||||
|
ksort($interval_data_indexed);
|
||||||
|
|
||||||
|
// We need more or equal two points
|
||||||
|
if (count ($interval_data_indexed) < 2) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Get the percentage for the limits
|
||||||
|
$diff = $max_value - $min_value;
|
||||||
|
|
||||||
|
// Get module type
|
||||||
|
$id_module_type = db_get_value('id_tipo_modulo', 'tagente_modulo', 'id_agente_modulo', $id_agent_module);
|
||||||
|
// If module is boolean don't create translation intervals (on the edge intervals)
|
||||||
|
// if ($id_module_type == 2 or $id_module_type == 6 or $id_module_type == 9 or $id_module_type == 18){
|
||||||
|
// $percent = 0;
|
||||||
|
// }
|
||||||
|
// else {
|
||||||
|
// // Getting 10% of $diff --> $percent = ($diff/100)*10, so...
|
||||||
|
// $percent = $diff / 10;
|
||||||
|
// }
|
||||||
|
|
||||||
|
//Set initial conditions
|
||||||
|
$first_data = array_shift ($interval_data);
|
||||||
|
$previous_utimestamp = $date - $period;
|
||||||
|
|
||||||
|
$previous_value = $first_data ['datos'];
|
||||||
|
$previous_status = 0;
|
||||||
|
|
||||||
|
if (isset($first_data['status'])) {
|
||||||
|
// 4 for the Unknown value and 5 for planned downtime
|
||||||
|
$previous_status = $first_data['status'];
|
||||||
|
}
|
||||||
|
// elseif ((($previous_value > ($min_value - $percent)) && ($previous_value < ($min_value + $percent))) ||
|
||||||
|
// (($previous_value > ($max_value - $percent)) && ($previous_value < ($max_value + $percent)))) {//2 when value is within the edges
|
||||||
|
// $previous_status = 2;
|
||||||
|
// }
|
||||||
|
elseif (($previous_value >= ($min_value + $percent)) && ($previous_value <= ($max_value - $percent))) { //1 when value is OK
|
||||||
|
$previous_status = 1;
|
||||||
|
}
|
||||||
|
elseif (($previous_value <= ($min_value - $percent)) || ($previous_value >= ($max_value + $percent))) { //3 when value is Wrong
|
||||||
|
$previous_status = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
$data_colors = array();
|
||||||
|
$i = 0;
|
||||||
|
|
||||||
|
foreach ($interval_data_indexed as $utimestamp => $data) {
|
||||||
|
$change = false;
|
||||||
|
$value = $data['data'];
|
||||||
|
if (isset($data['status'])) {
|
||||||
|
// Leaving unkown status.
|
||||||
|
if ($data['status'] == 6) {
|
||||||
|
$status = $previous_known_status;
|
||||||
|
}
|
||||||
|
// 4 unknown, 5 planned downtime.
|
||||||
|
else {
|
||||||
|
$status = $data['status'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// elseif ((($value > ($min_value - $percent)) && ($value < ($min_value + $percent))) ||
|
||||||
|
// (($value > ($max_value - $percent)) && ($value < ($max_value + $percent)))) { //2 when value is within the edges
|
||||||
|
// $status = 2;
|
||||||
|
// }
|
||||||
|
elseif (($value >= ($min_value + $percent)) && ($value <= ($max_value - $percent))) { //1 when value is OK
|
||||||
|
$status = 1;
|
||||||
|
}
|
||||||
|
elseif (($value <= ($min_value - $percent)) || ($value >= ($max_value + $percent))) { //3 when value is Wrong
|
||||||
|
$status = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($status != $previous_status) {
|
||||||
|
$change = true;
|
||||||
|
$data_colors[$i]['data'] = $previous_status;
|
||||||
|
$data_colors[$i]['utimestamp'] = $utimestamp - $previous_utimestamp;
|
||||||
|
$i++;
|
||||||
|
$previous_status = $status;
|
||||||
|
$previous_utimestamp = $utimestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save the last known status.
|
||||||
|
if ($status <= 3) {
|
||||||
|
$previous_known_status = $status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($change == false) {
|
||||||
|
$data_colors[$i]['data'] = $previous_status;
|
||||||
|
$data_colors[$i]['utimestamp'] = $date - $previous_utimestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $data_colors;
|
||||||
|
}
|
||||||
?>
|
?>
|
@ -1822,665 +1822,13 @@ function reporting_html_sql(&$table, $item) {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get SLA of a module.
|
|
||||||
*
|
|
||||||
* @param int Agent module to calculate SLA
|
|
||||||
* @param int Period to check the SLA compliance.
|
|
||||||
* @param int Minimum data value the module in the right interval
|
|
||||||
* @param int Maximum data value the module in the right interval. False will
|
|
||||||
* ignore max value
|
|
||||||
* @param int Beginning date of the report in UNIX time (current date by default).
|
|
||||||
* @param array $dayWeek Array of days week to extract as array('monday' => false, 'tuesday' => true....), and by default is null.
|
|
||||||
* @param string $timeFrom Time in the day to start to extract in mysql format, by default null.
|
|
||||||
* @param string $timeTo Time in the day to end to extract in mysql format, by default null.
|
|
||||||
*
|
|
||||||
* @return float SLA percentage of the requested module. False if no data were
|
|
||||||
* found
|
|
||||||
*/
|
|
||||||
function reporting_get_agentmodule_sla_day ($id_agent_module, $period = 0, $min_value = 1, $max_value = false, $date = 0, $daysWeek = null, $timeFrom = null, $timeTo = null) {
|
|
||||||
global $config;
|
|
||||||
|
|
||||||
if (empty($id_agent_module))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Initialize variables
|
|
||||||
if (empty ($date)) {
|
|
||||||
$date = get_system_time ();
|
|
||||||
}
|
|
||||||
if ($daysWeek === null) {
|
|
||||||
$daysWeek = array();
|
|
||||||
}
|
|
||||||
// Limit date to start searching data
|
|
||||||
$datelimit = $date - $period;
|
|
||||||
|
|
||||||
$search_in_history_db = db_search_in_history_db($datelimit);
|
|
||||||
|
|
||||||
// Get interval data
|
|
||||||
$sql = sprintf ('SELECT *
|
|
||||||
FROM tagente_datos
|
|
||||||
WHERE id_agente_modulo = %d
|
|
||||||
AND utimestamp > %d AND utimestamp <= %d',
|
|
||||||
$id_agent_module, $datelimit, $date);
|
|
||||||
|
|
||||||
//Add the working times (mon - tue - wed ...) and from time to time
|
|
||||||
$days = array();
|
|
||||||
//Translate to mysql week days
|
|
||||||
if ($daysWeek) {
|
|
||||||
foreach ($daysWeek as $key => $value) {
|
|
||||||
if (!$value) {
|
|
||||||
if ($key == 'monday') {
|
|
||||||
$days[] = 2;
|
|
||||||
}
|
|
||||||
if ($key == 'tuesday') {
|
|
||||||
$days[] = 3;
|
|
||||||
}
|
|
||||||
if ($key == 'wednesday') {
|
|
||||||
$days[] = 4;
|
|
||||||
}
|
|
||||||
if ($key == 'thursday') {
|
|
||||||
$days[] = 5;
|
|
||||||
}
|
|
||||||
if ($key == 'friday') {
|
|
||||||
$days[] = 6;
|
|
||||||
}
|
|
||||||
if ($key == 'saturday') {
|
|
||||||
$days[] = 7;
|
|
||||||
}
|
|
||||||
if ($key == 'sunday') {
|
|
||||||
$days[] = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (count($days) > 0) {
|
|
||||||
$sql .= ' AND DAYOFWEEK(FROM_UNIXTIME(utimestamp)) NOT IN (' . implode(',', $days) . ')';
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($timeFrom < $timeTo) {
|
|
||||||
$sql .= ' AND (TIME(FROM_UNIXTIME(utimestamp)) >= "' . $timeFrom . '" AND TIME(FROM_UNIXTIME(utimestamp)) <= "'. $timeTo . '")';
|
|
||||||
}
|
|
||||||
elseif ($timeFrom > $timeTo) {
|
|
||||||
$sql .= ' AND (TIME(FROM_UNIXTIME(utimestamp)) >= "' . $timeFrom . '" OR TIME(FROM_UNIXTIME(utimestamp)) <= "'. $timeTo . '")';
|
|
||||||
}
|
|
||||||
$sql .= ' ORDER BY utimestamp ASC';
|
|
||||||
$interval_data = db_get_all_rows_sql ($sql, $search_in_history_db);
|
|
||||||
|
|
||||||
if ($interval_data === false) {
|
|
||||||
$interval_data = array ();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calculate planned downtime dates
|
|
||||||
$downtime_dates = reporting_get_planned_downtimes_intervals($id_agent_module, $datelimit, $date);
|
|
||||||
|
|
||||||
// Get previous data
|
|
||||||
$previous_data = modules_get_previous_data ($id_agent_module, $datelimit);
|
|
||||||
|
|
||||||
if ($previous_data !== false) {
|
|
||||||
$previous_data['utimestamp'] = $datelimit;
|
|
||||||
array_unshift ($interval_data, $previous_data);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get next data
|
|
||||||
$next_data = modules_get_next_data ($id_agent_module, $date);
|
|
||||||
|
|
||||||
if ($next_data !== false) {
|
|
||||||
$next_data['utimestamp'] = $date;
|
|
||||||
array_push ($interval_data, $next_data);
|
|
||||||
}
|
|
||||||
else if (count ($interval_data) > 0) {
|
|
||||||
// Propagate the last known data to the end of the interval
|
|
||||||
$next_data = array_pop ($interval_data);
|
|
||||||
array_push ($interval_data, $next_data);
|
|
||||||
$next_data['utimestamp'] = $date;
|
|
||||||
array_push ($interval_data, $next_data);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (count ($interval_data) < 2) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set initial conditions
|
|
||||||
$bad_period = 0;
|
|
||||||
$first_data = array_shift ($interval_data);
|
|
||||||
|
|
||||||
// Do not count the empty start of an interval as 0
|
|
||||||
if ($first_data['utimestamp'] != $datelimit) {
|
|
||||||
$period = $date - $first_data['utimestamp'];
|
|
||||||
}
|
|
||||||
|
|
||||||
$previous_utimestamp = $first_data['utimestamp'];
|
|
||||||
if ((($max_value > $min_value AND ($first_data['datos'] > $max_value OR $first_data['datos'] < $min_value))) OR
|
|
||||||
($max_value <= $min_value AND $first_data['datos'] < $min_value)) {
|
|
||||||
|
|
||||||
$previous_status = 1;
|
|
||||||
foreach ($downtime_dates as $date_dt) {
|
|
||||||
if (($date_dt['date_from'] <= $previous_utimestamp) AND ($date_dt['date_to'] >= $previous_utimestamp)) {
|
|
||||||
$previous_status = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$previous_status = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
foreach ($interval_data as $data) {
|
|
||||||
// Previous status was critical
|
|
||||||
if ($previous_status == 1) {
|
|
||||||
$bad_period += $data['utimestamp'] - $previous_utimestamp;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (array_key_exists('datos', $data)) {
|
|
||||||
// Re-calculate previous status for the next data
|
|
||||||
if ((($max_value > $min_value AND ($data['datos'] > $max_value OR $data['datos'] < $min_value))) OR
|
|
||||||
($max_value <= $min_value AND $data['datos'] < $min_value)) {
|
|
||||||
|
|
||||||
$previous_status = 1;
|
|
||||||
foreach ($downtime_dates as $date_dt) {
|
|
||||||
if (($date_dt['date_from'] <= $data['utimestamp']) AND ($date_dt['date_to'] >= $data['utimestamp'])) {
|
|
||||||
$previous_status = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$previous_status = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$previous_utimestamp = $data['utimestamp'];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return the percentage of SLA compliance
|
|
||||||
return (float) (100 - ($bad_period / $period) * 100);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get several SLA data for an agentmodule within a period divided on subperiods
|
|
||||||
*
|
|
||||||
* @param int Agent module to calculate SLA
|
|
||||||
* @param int Period to check the SLA compliance.
|
|
||||||
* @param int Minimum data value the module in the right interval
|
|
||||||
* @param int Maximum data value the module in the right interval. False will
|
|
||||||
* ignore max value
|
|
||||||
* @param array $days Array of days week to extract as array('monday' => false, 'tuesday' => true....), and by default is null.
|
|
||||||
* @param string $timeFrom Time in the day to start to extract in mysql format, by default null.
|
|
||||||
* @param string $timeTo Time in the day to end to extract in mysql format, by default null.
|
|
||||||
*
|
|
||||||
* @return Array with values either 1, 2, 3 or 4 depending if the SLA percentage for this subperiod
|
|
||||||
* is within the sla limits, on the edge, outside or with an unknown value.
|
|
||||||
*/
|
|
||||||
function reporting_get_agentmodule_sla_array ($id_agent_module, $period = 0, $min_value = 1, $max_value = false, $date = 0, $daysWeek = null, $timeFrom = null, $timeTo = null) {
|
|
||||||
global $config;
|
|
||||||
|
|
||||||
if (empty($id_agent_module))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Initialize variables
|
|
||||||
if (empty ($date)) {
|
|
||||||
$date = get_system_time ();
|
|
||||||
}
|
|
||||||
if ($daysWeek === null) {
|
|
||||||
$daysWeek = array();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Hotfix: The edge values are confuse to the users
|
|
||||||
$percent = 0;
|
|
||||||
|
|
||||||
// Limit date to start searching data
|
|
||||||
$datelimit = $date - $period;
|
|
||||||
|
|
||||||
$search_in_history_db = db_search_in_history_db($datelimit);
|
|
||||||
|
|
||||||
// Get interval data
|
|
||||||
$sql = sprintf ('SELECT * FROM tagente_datos
|
|
||||||
WHERE id_agente_modulo = %d
|
|
||||||
AND utimestamp > %d AND utimestamp <= %d',
|
|
||||||
$id_agent_module, $datelimit, $date);
|
|
||||||
|
|
||||||
//Add the working times (mon - tue - wed ...) and from time to time
|
|
||||||
$days = array();
|
|
||||||
//Translate to mysql week days
|
|
||||||
|
|
||||||
if ($daysWeek) {
|
|
||||||
foreach ($daysWeek as $key => $value) {
|
|
||||||
if (!$value) {
|
|
||||||
if ($key == 'monday') {
|
|
||||||
$days[] = 2;
|
|
||||||
}
|
|
||||||
if ($key == 'tuesday') {
|
|
||||||
$days[] = 3;
|
|
||||||
}
|
|
||||||
if ($key == 'wednesday') {
|
|
||||||
$days[] = 4;
|
|
||||||
}
|
|
||||||
if ($key == 'thursday') {
|
|
||||||
$days[] = 5;
|
|
||||||
}
|
|
||||||
if ($key == 'friday') {
|
|
||||||
$days[] = 6;
|
|
||||||
}
|
|
||||||
if ($key == 'saturday') {
|
|
||||||
$days[] = 7;
|
|
||||||
}
|
|
||||||
if ($key == 'sunday') {
|
|
||||||
$days[] = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (count($days) > 0) {
|
|
||||||
$sql .= ' AND DAYOFWEEK(FROM_UNIXTIME(utimestamp)) NOT IN (' . implode(',', $days) . ')';
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($timeFrom != $timeTo) {
|
|
||||||
if ($timeFrom < $timeTo) {
|
|
||||||
$sql .= ' AND (TIME(FROM_UNIXTIME(utimestamp)) >= "' . $timeFrom . '" AND TIME(FROM_UNIXTIME(utimestamp)) <= "'. $timeTo . '")';
|
|
||||||
}
|
|
||||||
elseif ($timeFrom > $timeTo) {
|
|
||||||
$sql .= ' AND (TIME(FROM_UNIXTIME(utimestamp)) >= "' . $timeFrom . '" OR TIME(FROM_UNIXTIME(utimestamp)) <= "'. $timeTo . '")';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$sql .= ' ORDER BY utimestamp ASC';
|
|
||||||
$interval_data = db_get_all_rows_sql ($sql, $search_in_history_db);
|
|
||||||
|
|
||||||
if ($interval_data === false) {
|
|
||||||
$interval_data = array ();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Indexing data
|
|
||||||
$interval_data_indexed = array();
|
|
||||||
foreach($interval_data as $idata) {
|
|
||||||
$interval_data_indexed[$idata['utimestamp']]['data'] = $idata['datos'];
|
|
||||||
}
|
|
||||||
|
|
||||||
//-----------Calculate unknown status events------------------------
|
|
||||||
$events_unknown = db_get_all_rows_filter ('tevento',
|
|
||||||
array ('id_agentmodule' => $id_agent_module,
|
|
||||||
"utimestamp > $datelimit",
|
|
||||||
"utimestamp < $date",
|
|
||||||
'order' => 'utimestamp ASC'),
|
|
||||||
array ('id_evento', 'evento', 'timestamp', 'utimestamp', 'event_type'));
|
|
||||||
|
|
||||||
if ($events_unknown === false) {
|
|
||||||
$events_unknown = array ();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add unknown periods to data
|
|
||||||
for ($i = 0; isset($events_unknown[$i]); $i++) {
|
|
||||||
$eu = $events_unknown[$i];
|
|
||||||
|
|
||||||
if ($eu['event_type'] == 'going_unknown') {
|
|
||||||
$interval_data_indexed[$eu['utimestamp']]['data'] = 0;
|
|
||||||
$interval_data_indexed[$eu['utimestamp']]['status'] = 4;
|
|
||||||
|
|
||||||
// Search the corresponding recovery event.
|
|
||||||
for ($j = $i+1; isset($events_unknown[$j]); $j++) {
|
|
||||||
$eu = $events_unknown[$j];
|
|
||||||
|
|
||||||
if ($eu['event_type'] != 'going_unknown' && substr ($eu['event_type'], 0, 5) == 'going') {
|
|
||||||
$interval_data_indexed[$eu['utimestamp']]['data'] = 0;
|
|
||||||
$interval_data_indexed[$eu['utimestamp']]['status'] = 6;
|
|
||||||
|
|
||||||
// Do not process read events again.
|
|
||||||
$i = $j;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the last event before inverval to know if graph start on unknown
|
|
||||||
$prev_event = db_get_row_filter ('tevento',
|
|
||||||
array ('id_agentmodule' => $id_agent_module,
|
|
||||||
"utimestamp <= $datelimit",
|
|
||||||
'order' => 'utimestamp DESC'));
|
|
||||||
if (isset($prev_event['event_type']) && $prev_event['event_type'] == 'going_unknown') {
|
|
||||||
$start_unknown = true;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$start_unknown = false;
|
|
||||||
}
|
|
||||||
//------------------------------------------------------------------
|
|
||||||
|
|
||||||
//-----------------Set limits of the interval-----------------------
|
|
||||||
// Get previous data (This adds the first data if the begin of module data is after the begin time interval)
|
|
||||||
$previous_data = modules_get_previous_data ($id_agent_module, $datelimit);
|
|
||||||
if ($previous_data !== false ) {
|
|
||||||
$previous_value = $previous_data['datos'];
|
|
||||||
// if ((($previous_value > ($min_value - $percent)) && ($previous_value < ($min_value + $percent))) ||
|
|
||||||
// (($previous_value > ($max_value - $percent)) && ($previous_value < ($max_value + $percent)))) {//2 when value is within the edges
|
|
||||||
// $previous_known_status = 2;
|
|
||||||
// }
|
|
||||||
// else
|
|
||||||
if (($previous_value >= ($min_value + $percent)) && ($previous_value <= ($max_value - $percent))) { //1 when value is OK
|
|
||||||
$previous_known_status = 1;
|
|
||||||
}
|
|
||||||
elseif (($previous_value <= ($min_value - $percent)) || ($previous_value >= ($max_value + $percent))) { //3 when value is Wrong
|
|
||||||
$previous_known_status = 3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the starting of the graph is unknown we set it
|
|
||||||
if ($start_unknown) {
|
|
||||||
$interval_data_indexed[$datelimit]['data'] = 0;
|
|
||||||
$interval_data_indexed[$datelimit]['status'] = 4;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if ($previous_data !== false ) {
|
|
||||||
$interval_data_indexed[$datelimit]['data'] = $previous_data['datos'];
|
|
||||||
}
|
|
||||||
else { // If there are not data befor interval set unknown
|
|
||||||
$interval_data_indexed[$datelimit]['data'] = 0;
|
|
||||||
$interval_data_indexed[$datelimit]['status'] = 4;
|
|
||||||
$previous_known_status = 1; // Assume the module was in normal status if there is no previous data.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get next data (This adds data before the interval of the report)
|
|
||||||
$next_data = modules_get_next_data ($id_agent_module, $date);
|
|
||||||
|
|
||||||
if ($next_data !== false) {
|
|
||||||
$interval_data_indexed[$date]['data'] = $previous_data['datos'];
|
|
||||||
}
|
|
||||||
else if (count ($interval_data_indexed) > 0) {
|
|
||||||
// Propagate the last known data to the end of the interval (if there is no module data at the end point)
|
|
||||||
ksort($interval_data_indexed);
|
|
||||||
$last_data = end($interval_data_indexed);
|
|
||||||
$interval_data_indexed[$date] = $last_data;
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------
|
|
||||||
|
|
||||||
//--------Calculate planned downtime dates--------------------------
|
|
||||||
$downtime_dates = reporting_get_planned_downtimes_intervals($id_agent_module, $datelimit, $date);
|
|
||||||
|
|
||||||
foreach ($downtime_dates as $downtime_date) {
|
|
||||||
// Delete data of the planned downtime and put the last data on the upper limit
|
|
||||||
$interval_data_indexed[$downtime_date['date_from']]['data'] = 0;
|
|
||||||
$interval_data_indexed[$downtime_date['date_from']]['status'] = 5;
|
|
||||||
$interval_data_indexed[$downtime_date['date_to']]['data'] = 0;
|
|
||||||
$interval_data_indexed[$downtime_date['date_to']]['status'] = 4;
|
|
||||||
|
|
||||||
$last_downtime_data = false;
|
|
||||||
foreach ($interval_data_indexed as $idi_timestamp => $idi) {
|
|
||||||
if ($idi_timestamp != $downtime_date['date_from'] && $idi_timestamp != $downtime_date['date_to'] &&
|
|
||||||
$idi_timestamp >= $downtime_date['date_from'] && $idi_timestamp <= $downtime_date['date_to']) {
|
|
||||||
$last_downtime_data = $idi['data'];
|
|
||||||
unset($interval_data_indexed[$idi_timestamp]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set the last data of the interval as limit
|
|
||||||
if ($last_downtime_data !== false) {
|
|
||||||
$interval_data_indexed[$downtime_date['date_to']]['data'] = $last_downtime_data;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//------------------------------------------------------------------
|
|
||||||
|
|
||||||
// Sort the array
|
|
||||||
ksort($interval_data_indexed);
|
|
||||||
|
|
||||||
// We need more or equal two points
|
|
||||||
if (count ($interval_data_indexed) < 2) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Get the percentage for the limits
|
|
||||||
$diff = $max_value - $min_value;
|
|
||||||
|
|
||||||
// Get module type
|
|
||||||
$id_module_type = db_get_value('id_tipo_modulo', 'tagente_modulo', 'id_agente_modulo', $id_agent_module);
|
|
||||||
// If module is boolean don't create translation intervals (on the edge intervals)
|
|
||||||
// if ($id_module_type == 2 or $id_module_type == 6 or $id_module_type == 9 or $id_module_type == 18){
|
|
||||||
// $percent = 0;
|
|
||||||
// }
|
|
||||||
// else {
|
|
||||||
// // Getting 10% of $diff --> $percent = ($diff/100)*10, so...
|
|
||||||
// $percent = $diff / 10;
|
|
||||||
// }
|
|
||||||
|
|
||||||
//Set initial conditions
|
|
||||||
$first_data = array_shift ($interval_data);
|
|
||||||
$previous_utimestamp = $date - $period;
|
|
||||||
|
|
||||||
$previous_value = $first_data ['datos'];
|
|
||||||
$previous_status = 0;
|
|
||||||
|
|
||||||
if (isset($first_data['status'])) {
|
|
||||||
// 4 for the Unknown value and 5 for planned downtime
|
|
||||||
$previous_status = $first_data['status'];
|
|
||||||
}
|
|
||||||
// elseif ((($previous_value > ($min_value - $percent)) && ($previous_value < ($min_value + $percent))) ||
|
|
||||||
// (($previous_value > ($max_value - $percent)) && ($previous_value < ($max_value + $percent)))) {//2 when value is within the edges
|
|
||||||
// $previous_status = 2;
|
|
||||||
// }
|
|
||||||
elseif (($previous_value >= ($min_value + $percent)) && ($previous_value <= ($max_value - $percent))) { //1 when value is OK
|
|
||||||
$previous_status = 1;
|
|
||||||
}
|
|
||||||
elseif (($previous_value <= ($min_value - $percent)) || ($previous_value >= ($max_value + $percent))) { //3 when value is Wrong
|
|
||||||
$previous_status = 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
$data_colors = array();
|
|
||||||
$i = 0;
|
|
||||||
|
|
||||||
foreach ($interval_data_indexed as $utimestamp => $data) {
|
|
||||||
$change = false;
|
|
||||||
$value = $data['data'];
|
|
||||||
if (isset($data['status'])) {
|
|
||||||
// Leaving unkown status.
|
|
||||||
if ($data['status'] == 6) {
|
|
||||||
$status = $previous_known_status;
|
|
||||||
}
|
|
||||||
// 4 unknown, 5 planned downtime.
|
|
||||||
else {
|
|
||||||
$status = $data['status'];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// elseif ((($value > ($min_value - $percent)) && ($value < ($min_value + $percent))) ||
|
|
||||||
// (($value > ($max_value - $percent)) && ($value < ($max_value + $percent)))) { //2 when value is within the edges
|
|
||||||
// $status = 2;
|
|
||||||
// }
|
|
||||||
elseif (($value >= ($min_value + $percent)) && ($value <= ($max_value - $percent))) { //1 when value is OK
|
|
||||||
$status = 1;
|
|
||||||
}
|
|
||||||
elseif (($value <= ($min_value - $percent)) || ($value >= ($max_value + $percent))) { //3 when value is Wrong
|
|
||||||
$status = 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($status != $previous_status) {
|
|
||||||
$change = true;
|
|
||||||
$data_colors[$i]['data'] = $previous_status;
|
|
||||||
$data_colors[$i]['utimestamp'] = $utimestamp - $previous_utimestamp;
|
|
||||||
$i++;
|
|
||||||
$previous_status = $status;
|
|
||||||
$previous_utimestamp = $utimestamp;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Save the last known status.
|
|
||||||
if ($status <= 3) {
|
|
||||||
$previous_known_status = $status;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ($change == false) {
|
|
||||||
$data_colors[$i]['data'] = $previous_status;
|
|
||||||
$data_colors[$i]['utimestamp'] = $date - $previous_utimestamp;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $data_colors;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the planned downtimes that affect the passed modules on an specific datetime range.
|
|
||||||
*
|
|
||||||
* @param int Start date in utimestamp.
|
|
||||||
* @param int End date in utimestamp.
|
|
||||||
* @param array The agent modules ids.
|
|
||||||
*
|
|
||||||
* @return Array with the planned downtimes that are executed in any moment of the range selected and affect the
|
|
||||||
* agent modules selected.
|
|
||||||
*/
|
|
||||||
function reporting_get_planned_downtimes ($start_date, $end_date, $id_agent_modules = false) {
|
|
||||||
$start_time = date("H:i:s", $start_date);
|
|
||||||
$end_time = date("H:i:s", $end_date);
|
|
||||||
|
|
||||||
$start_day = date("d", $start_date);
|
|
||||||
$end_day = date("d", $end_date);
|
|
||||||
|
|
||||||
$start_month = date("m", $start_date);
|
|
||||||
$end_month = date("m", $end_date);
|
|
||||||
|
|
||||||
if ($start_date > $end_date) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($end_date - $start_date >= SECONDS_1MONTH) {
|
|
||||||
// If the date range is larger than 1 month, every monthly planned downtime will be inside
|
|
||||||
$periodically_monthly_w = "type_periodicity = 'monthly'";
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// Check if the range is larger than the planned downtime execution, or if its start or end
|
|
||||||
// is inside the planned downtime execution.
|
|
||||||
// The start and end time is very important.
|
|
||||||
$periodically_monthly_w = "type_periodicity = 'monthly'
|
|
||||||
AND (((periodically_day_from > '$start_day'
|
|
||||||
OR (periodically_day_from = '$start_day'
|
|
||||||
AND periodically_time_from >= '$start_time'))
|
|
||||||
AND (periodically_day_to < '$end_day'
|
|
||||||
OR (periodically_day_to = '$end_day'
|
|
||||||
AND periodically_time_to <= '$end_time')))
|
|
||||||
OR ((periodically_day_from < '$start_day'
|
|
||||||
OR (periodically_day_from = '$start_day'
|
|
||||||
AND periodically_time_from <= '$start_time'))
|
|
||||||
AND (periodically_day_to > '$start_day'
|
|
||||||
OR (periodically_day_to = '$start_day'
|
|
||||||
AND periodically_time_to >= '$start_time')))
|
|
||||||
OR ((periodically_day_from < '$end_day'
|
|
||||||
OR (periodically_day_from = '$end_day'
|
|
||||||
AND periodically_time_from <= '$end_time'))
|
|
||||||
AND (periodically_day_to > '$end_day'
|
|
||||||
OR (periodically_day_to = '$end_day'
|
|
||||||
AND periodically_time_to >= '$end_time'))))";
|
|
||||||
}
|
|
||||||
|
|
||||||
$periodically_weekly_days = array();
|
|
||||||
$date_aux = $start_date;
|
|
||||||
$i = 0;
|
|
||||||
|
|
||||||
if (($end_date - $start_date) >= SECONDS_1WEEK) {
|
|
||||||
// If the date range is larger than 7 days, every weekly planned downtime will be inside.
|
|
||||||
for ($i = 0; $i < 7; $i++) {
|
|
||||||
$weekday_actual = strtolower(date('l', $date_aux));
|
|
||||||
$periodically_weekly_days[] = "($weekday_actual = 1)";
|
|
||||||
$date_aux += SECONDS_1DAY;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (($end_date - $start_date) <= SECONDS_1DAY && $start_day == $end_day) {
|
|
||||||
// If the date range is smaller than 1 day, the start and end days can be equal or consecutive.
|
|
||||||
// If they are equal, the execution times have to be contained in the date range times or contain
|
|
||||||
// the start or end time of the date range.
|
|
||||||
$weekday_actual = strtolower(date('l', $start_date));
|
|
||||||
$periodically_weekly_days[] = "($weekday_actual = 1
|
|
||||||
AND ((periodically_time_from > '$start_time' AND periodically_time_to < '$end_time')
|
|
||||||
OR (periodically_time_from = '$start_time'
|
|
||||||
OR (periodically_time_from < '$start_time'
|
|
||||||
AND periodically_time_to >= '$start_time'))
|
|
||||||
OR (periodically_time_from = '$end_time'
|
|
||||||
OR (periodically_time_from < '$end_time'
|
|
||||||
AND periodically_time_to >= '$end_time'))))";
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
while ($date_aux <= $end_date && $i < 7) {
|
|
||||||
|
|
||||||
$weekday_actual = strtolower(date('l', $date_aux));
|
|
||||||
$day_num_actual = date('d', $date_aux);
|
|
||||||
|
|
||||||
if ($date_aux == $start_date) {
|
|
||||||
$periodically_weekly_days[] = "($weekday_actual = 1 AND periodically_time_to >= '$start_time')";
|
|
||||||
}
|
|
||||||
else if ($day_num_actual == $end_day) {
|
|
||||||
$periodically_weekly_days[] = "($weekday_actual = 1 AND periodically_time_from <= '$end_time')";
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$periodically_weekly_days[] = "($weekday_actual = 1)";
|
|
||||||
}
|
|
||||||
|
|
||||||
$date_aux += SECONDS_1DAY;
|
|
||||||
$i++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!empty($periodically_weekly_days)) {
|
|
||||||
$periodically_weekly_w = "type_periodicity = 'weekly' AND (".implode(" OR ", $periodically_weekly_days).")";
|
|
||||||
$periodically_condition = "(($periodically_monthly_w) OR ($periodically_weekly_w))";
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$periodically_condition = "($periodically_monthly_w)";
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($id_agent_modules !== false) {
|
|
||||||
if (empty($id_agent_modules))
|
|
||||||
return array();
|
|
||||||
|
|
||||||
$id_agent_modules_str = implode(",", $id_agent_modules);
|
|
||||||
|
|
||||||
$sql_downtime = "SELECT DISTINCT(tpdr.id), tpdr.*
|
|
||||||
FROM (
|
|
||||||
SELECT tpd.*
|
|
||||||
FROM tplanned_downtime tpd, tplanned_downtime_agents tpda, tagente_modulo tam
|
|
||||||
WHERE (tpd.id = tpda.id_downtime
|
|
||||||
AND tpda.all_modules = 1
|
|
||||||
AND tpda.id_agent = tam.id_agente
|
|
||||||
AND tam.id_agente_modulo IN ($id_agent_modules_str))
|
|
||||||
AND ((type_execution = 'periodically'
|
|
||||||
AND $periodically_condition)
|
|
||||||
OR (type_execution = 'once'
|
|
||||||
AND ((date_from >= '$start_date' AND date_to <= '$end_date')
|
|
||||||
OR (date_from <= '$start_date' AND date_to >= '$end_date')
|
|
||||||
OR (date_from <= '$start_date' AND date_to >= '$start_date')
|
|
||||||
OR (date_from <= '$end_date' AND date_to >= '$end_date'))))
|
|
||||||
UNION ALL
|
|
||||||
SELECT tpd.*
|
|
||||||
FROM tplanned_downtime tpd, tplanned_downtime_modules tpdm
|
|
||||||
WHERE (tpd.id = tpdm.id_downtime
|
|
||||||
AND tpdm.id_agent_module IN ($id_agent_modules_str))
|
|
||||||
AND ((type_execution = 'periodically'
|
|
||||||
AND $periodically_condition)
|
|
||||||
OR (type_execution = 'once'
|
|
||||||
AND ((date_from >= '$start_date' AND date_to <= '$end_date')
|
|
||||||
OR (date_from <= '$start_date' AND date_to >= '$end_date')
|
|
||||||
OR (date_from <= '$start_date' AND date_to >= '$start_date')
|
|
||||||
OR (date_from <= '$end_date' AND date_to >= '$end_date'))))
|
|
||||||
) tpdr
|
|
||||||
ORDER BY tpdr.id";
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$sql_downtime = "SELECT *
|
|
||||||
FROM tplanned_downtime tpd, tplanned_downtime_modules tpdm
|
|
||||||
WHERE (type_execution = 'periodically'
|
|
||||||
AND $periodically_condition)
|
|
||||||
OR (type_execution = 'once'
|
|
||||||
AND ((date_from >= '$start_date' AND date_to <= '$end_date')
|
|
||||||
OR (date_from <= '$start_date' AND date_to >= '$end_date')
|
|
||||||
OR (date_from <= '$start_date' AND date_to >= '$start_date')
|
|
||||||
OR (date_from <= '$end_date' AND date_to >= '$end_date')))";
|
|
||||||
}
|
|
||||||
|
|
||||||
$downtimes = db_get_all_rows_sql($sql_downtime);
|
|
||||||
if ($downtimes == false) {
|
|
||||||
$downtimes = array();
|
|
||||||
}
|
|
||||||
|
|
||||||
return $downtimes;
|
|
||||||
}
|
|
||||||
|
|
||||||
function reporting_get_stats_servers($tiny = true) {
|
function reporting_get_stats_servers($tiny = true) {
|
||||||
global $config;
|
global $config;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user