2482 lines
82 KiB
C
2482 lines
82 KiB
C
/**************************************************************************
|
|
*
|
|
* HISTOGRAM.C - Nagios Alert Histogram CGI
|
|
*
|
|
* Copyright (c) 2001-2008 Ethan Galstad (egalstad@nagios.org)
|
|
* Last Modified: 10-15-2008
|
|
*
|
|
* License:
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License version 2 as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
*************************************************************************/
|
|
|
|
#include "../include/config.h"
|
|
#include "../include/common.h"
|
|
#include "../include/objects.h"
|
|
#include "../include/statusdata.h"
|
|
|
|
#include "../include/cgiutils.h"
|
|
#include "../include/getcgi.h"
|
|
#include "../include/cgiauth.h"
|
|
|
|
#include <gd.h> /* Boutell's GD library function */
|
|
#include <gdfonts.h> /* GD library small font definition */
|
|
|
|
|
|
/*#define DEBUG 1*/
|
|
|
|
|
|
#define HISTOGRAM_IMAGE "histogram.png"
|
|
|
|
/* archived state types */
|
|
#define AS_NO_DATA 0
|
|
#define AS_PROGRAM_START 1
|
|
#define AS_PROGRAM_END 2
|
|
#define AS_HOST_UP 3
|
|
#define AS_HOST_DOWN 4
|
|
#define AS_HOST_UNREACHABLE 5
|
|
#define AS_SVC_OK 6
|
|
#define AS_SVC_UNKNOWN 7
|
|
#define AS_SVC_WARNING 8
|
|
#define AS_SVC_CRITICAL 9
|
|
|
|
|
|
/* display types */
|
|
#define DISPLAY_HOST_HISTOGRAM 0
|
|
#define DISPLAY_SERVICE_HISTOGRAM 1
|
|
#define DISPLAY_NO_HISTOGRAM 2
|
|
|
|
/* input types */
|
|
#define GET_INPUT_NONE 0
|
|
#define GET_INPUT_TARGET_TYPE 1
|
|
#define GET_INPUT_HOST_TARGET 2
|
|
#define GET_INPUT_SERVICE_TARGET 3
|
|
#define GET_INPUT_OPTIONS 4
|
|
|
|
/* breakdown types */
|
|
#define BREAKDOWN_MONTHLY 0
|
|
#define BREAKDOWN_DAY_OF_MONTH 1
|
|
#define BREAKDOWN_DAY_OF_WEEK 2
|
|
#define BREAKDOWN_HOURLY 3
|
|
|
|
/* modes */
|
|
#define CREATE_HTML 0
|
|
#define CREATE_IMAGE 1
|
|
|
|
/* standard report times */
|
|
#define TIMEPERIOD_CUSTOM 0
|
|
#define TIMEPERIOD_TODAY 1
|
|
#define TIMEPERIOD_YESTERDAY 2
|
|
#define TIMEPERIOD_THISWEEK 3
|
|
#define TIMEPERIOD_LASTWEEK 4
|
|
#define TIMEPERIOD_THISMONTH 5
|
|
#define TIMEPERIOD_LASTMONTH 6
|
|
#define TIMEPERIOD_THISQUARTER 7
|
|
#define TIMEPERIOD_LASTQUARTER 8
|
|
#define TIMEPERIOD_THISYEAR 9
|
|
#define TIMEPERIOD_LASTYEAR 10
|
|
#define TIMEPERIOD_LAST24HOURS 11
|
|
#define TIMEPERIOD_LAST7DAYS 12
|
|
#define TIMEPERIOD_LAST31DAYS 13
|
|
|
|
|
|
#define MAX_ARCHIVE_SPREAD 65
|
|
#define MAX_ARCHIVE 65
|
|
#define MAX_ARCHIVE_BACKTRACKS 60
|
|
|
|
#define DRAWING_WIDTH 550
|
|
#define DRAWING_HEIGHT 195
|
|
#define DRAWING_X_OFFSET 60
|
|
#define DRAWING_Y_OFFSET 235
|
|
|
|
#define GRAPH_HOST_UP 1
|
|
#define GRAPH_HOST_DOWN 2
|
|
#define GRAPH_HOST_UNREACHABLE 4
|
|
#define GRAPH_SERVICE_OK 8
|
|
#define GRAPH_SERVICE_WARNING 16
|
|
#define GRAPH_SERVICE_UNKNOWN 32
|
|
#define GRAPH_SERVICE_CRITICAL 64
|
|
|
|
#define GRAPH_HOST_PROBLEMS 6
|
|
#define GRAPH_HOST_ALL 7
|
|
|
|
#define GRAPH_SERVICE_PROBLEMS 112
|
|
#define GRAPH_SERVICE_ALL 120
|
|
|
|
#define GRAPH_EVERYTHING 255
|
|
|
|
|
|
#define GRAPH_SOFT_STATETYPES 1
|
|
#define GRAPH_HARD_STATETYPES 2
|
|
#define GRAPH_ALL_STATETYPES 3
|
|
|
|
|
|
|
|
|
|
extern char main_config_file[MAX_FILENAME_LENGTH];
|
|
extern char url_html_path[MAX_FILENAME_LENGTH];
|
|
extern char url_images_path[MAX_FILENAME_LENGTH];
|
|
extern char url_stylesheets_path[MAX_FILENAME_LENGTH];
|
|
extern char physical_images_path[MAX_FILENAME_LENGTH];
|
|
|
|
extern int log_rotation_method;
|
|
|
|
extern host *host_list;
|
|
extern service *service_list;
|
|
|
|
|
|
|
|
authdata current_authdata;
|
|
|
|
|
|
typedef struct timeslice_data_struct {
|
|
unsigned long service_ok;
|
|
unsigned long host_up;
|
|
unsigned long service_critical;
|
|
unsigned long host_down;
|
|
unsigned long service_unknown;
|
|
unsigned long host_unreachable;
|
|
unsigned long service_warning;
|
|
} timeslice_data;
|
|
|
|
|
|
timeslice_data *tsdata;
|
|
|
|
|
|
void convert_timeperiod_to_times(int);
|
|
void compute_report_times(void);
|
|
void graph_all_histogram_data(void);
|
|
void add_archived_state(int, time_t);
|
|
void read_archived_state_data(void);
|
|
void scan_log_file_for_archived_state_data(char *);
|
|
void draw_line(int, int, int, int, int);
|
|
void draw_dashed_line(int, int, int, int, int);
|
|
|
|
void document_header(int);
|
|
void document_footer(void);
|
|
int process_cgivars(void);
|
|
|
|
|
|
time_t t1;
|
|
time_t t2;
|
|
|
|
int start_second = 0;
|
|
int start_minute = 0;
|
|
int start_hour = 0;
|
|
int start_day = 1;
|
|
int start_month = 1;
|
|
int start_year = 2000;
|
|
int end_second = 0;
|
|
int end_minute = 0;
|
|
int end_hour = 24;
|
|
int end_day = 1;
|
|
int end_month = 1;
|
|
int end_year = 2000;
|
|
|
|
int display_type = DISPLAY_NO_HISTOGRAM;
|
|
int mode = CREATE_HTML;
|
|
int input_type = GET_INPUT_NONE;
|
|
int timeperiod_type = TIMEPERIOD_LAST24HOURS;
|
|
int breakdown_type = BREAKDOWN_HOURLY;
|
|
int compute_time_from_parts = FALSE;
|
|
|
|
int initial_states_logged = FALSE;
|
|
int assume_state_retention = TRUE;
|
|
int new_states_only = FALSE;
|
|
|
|
int last_state = AS_NO_DATA;
|
|
int program_restart_has_occurred = FALSE;
|
|
|
|
int graph_events = GRAPH_EVERYTHING;
|
|
int graph_statetypes = GRAPH_HARD_STATETYPES;
|
|
|
|
int embedded = FALSE;
|
|
int display_header = TRUE;
|
|
|
|
char *host_name = "";
|
|
char *svc_description = "";
|
|
|
|
gdImagePtr histogram_image = 0;
|
|
int color_white = 0;
|
|
int color_black = 0;
|
|
int color_red = 0;
|
|
int color_darkred = 0;
|
|
int color_green = 0;
|
|
int color_yellow = 0;
|
|
int color_orange = 0;
|
|
int color_lightgray = 0;
|
|
FILE *image_file = NULL;
|
|
|
|
int backtrack_archives = 0;
|
|
int earliest_archive = 0;
|
|
time_t earliest_time;
|
|
time_t latest_time;
|
|
|
|
int image_width = 900;
|
|
int image_height = 320;
|
|
|
|
int total_buckets = 96;
|
|
|
|
|
|
|
|
int main(int argc, char **argv) {
|
|
int result = OK;
|
|
char temp_buffer[MAX_INPUT_BUFFER];
|
|
char image_template[MAX_INPUT_BUFFER];
|
|
char start_timestring[MAX_INPUT_BUFFER];
|
|
char end_timestring[MAX_INPUT_BUFFER];
|
|
host *temp_host;
|
|
service *temp_service;
|
|
int is_authorized = TRUE;
|
|
int found = FALSE;
|
|
int days, hours, minutes, seconds;
|
|
char *first_service = NULL;
|
|
int x;
|
|
time_t t3;
|
|
time_t current_time;
|
|
struct tm *t;
|
|
|
|
/* initialize time period to last 24 hours */
|
|
time(&t2);
|
|
t1 = (time_t)(t2 - (60 * 60 * 24));
|
|
|
|
/* get the arguments passed in the URL */
|
|
process_cgivars();
|
|
|
|
/* reset internal CGI variables */
|
|
reset_cgi_vars();
|
|
|
|
/* read the CGI configuration file */
|
|
result = read_cgi_config_file(get_cgi_config_location());
|
|
if(result == ERROR) {
|
|
if(mode == CREATE_HTML) {
|
|
document_header(FALSE);
|
|
cgi_config_file_error(get_cgi_config_location());
|
|
document_footer();
|
|
}
|
|
return ERROR;
|
|
}
|
|
|
|
/* read the main configuration file */
|
|
result = read_main_config_file(main_config_file);
|
|
if(result == ERROR) {
|
|
if(mode == CREATE_HTML) {
|
|
document_header(FALSE);
|
|
main_config_file_error(main_config_file);
|
|
document_footer();
|
|
}
|
|
return ERROR;
|
|
}
|
|
|
|
/* read all object configuration data */
|
|
result = read_all_object_configuration_data(main_config_file, READ_ALL_OBJECT_DATA);
|
|
if(result == ERROR) {
|
|
if(mode == CREATE_HTML) {
|
|
document_header(FALSE);
|
|
object_data_error();
|
|
document_footer();
|
|
}
|
|
return ERROR;
|
|
}
|
|
|
|
/* read all status data */
|
|
result = read_all_status_data(get_cgi_config_location(), READ_ALL_STATUS_DATA);
|
|
if(result == ERROR) {
|
|
if(mode == CREATE_HTML) {
|
|
document_header(FALSE);
|
|
status_data_error();
|
|
document_footer();
|
|
}
|
|
free_memory();
|
|
return ERROR;
|
|
}
|
|
|
|
document_header(TRUE);
|
|
|
|
/* get authentication information */
|
|
get_authentication_information(¤t_authdata);
|
|
|
|
if(compute_time_from_parts == TRUE)
|
|
compute_report_times();
|
|
|
|
/* make sure times are sane, otherwise swap them */
|
|
if(t2 < t1) {
|
|
t3 = t2;
|
|
t2 = t1;
|
|
t1 = t3;
|
|
}
|
|
|
|
|
|
if(mode == CREATE_HTML && display_header == TRUE) {
|
|
|
|
/* begin top table */
|
|
printf("<table border=0 width=100%% cellspacing=0 cellpadding=0>\n");
|
|
printf("<tr>\n");
|
|
|
|
/* left column of the first row */
|
|
printf("<td align=left valign=top width=33%%>\n");
|
|
|
|
if(display_type == DISPLAY_HOST_HISTOGRAM)
|
|
snprintf(temp_buffer, sizeof(temp_buffer) - 1, "Host Alert Histogram");
|
|
else if(display_type == DISPLAY_SERVICE_HISTOGRAM)
|
|
snprintf(temp_buffer, sizeof(temp_buffer) - 1, "Service Alert Histogram");
|
|
else
|
|
snprintf(temp_buffer, sizeof(temp_buffer) - 1, "Host and Service Alert Histogram");
|
|
temp_buffer[sizeof(temp_buffer) - 1] = '\x0';
|
|
display_info_table(temp_buffer, FALSE, ¤t_authdata);
|
|
|
|
if(display_type != DISPLAY_NO_HISTOGRAM && input_type == GET_INPUT_NONE) {
|
|
|
|
printf("<TABLE BORDER=1 CELLPADDING=0 CELLSPACING=0 CLASS='linkBox'>\n");
|
|
printf("<TR><TD CLASS='linkBox'>\n");
|
|
|
|
if(display_type == DISPLAY_HOST_HISTOGRAM) {
|
|
#ifdef USE_TRENDS
|
|
printf("<a href='%s?host=%s&t1=%lu&t2=%lu&assumestateretention=%s'>View Trends For This Host</a><BR>\n", TRENDS_CGI, url_encode(host_name), t1, t2, (assume_state_retention == TRUE) ? "yes" : "no");
|
|
#endif
|
|
printf("<a href='%s?host=%s&t1=%lu&t2=%lu&assumestateretention=%s&show_log_entries'>View Availability Report For This Host</a><BR>\n", AVAIL_CGI, url_encode(host_name), t1, t2, (assume_state_retention == TRUE) ? "yes" : "no");
|
|
printf("<a href='%s?host=%s'>View Status Detail For This Host</a><BR>\n", STATUS_CGI, url_encode(host_name));
|
|
printf("<a href='%s?host=%s'>View History For This Host</a><BR>\n", HISTORY_CGI, url_encode(host_name));
|
|
printf("<a href='%s?host=%s'>View Notifications For This Host</a><BR>\n", NOTIFICATIONS_CGI, url_encode(host_name));
|
|
}
|
|
else {
|
|
#ifdef USE_TRENDS
|
|
printf("<a href='%s?host=%s", TRENDS_CGI, url_encode(host_name));
|
|
#endif
|
|
printf("&service=%s&t1=%lu&t2=%lu&assumestateretention=%s'>View Trends For This Service</a><BR>\n", url_encode(svc_description), t1, t2, (assume_state_retention == TRUE) ? "yes" : "no");
|
|
printf("<a href='%s?host=%s", AVAIL_CGI, url_encode(host_name));
|
|
printf("&service=%s&t1=%lu&t2=%lu&assumestateretention=%s&show_log_entries'>View Availability Report For This Service</a><BR>\n", url_encode(svc_description), t1, t2, (assume_state_retention == TRUE) ? "yes" : "no");
|
|
printf("<A HREF='%s?host=%s&", HISTORY_CGI, url_encode(host_name));
|
|
printf("service=%s'>View History For This Service</A><BR>\n", url_encode(svc_description));
|
|
printf("<A HREF='%s?host=%s&", NOTIFICATIONS_CGI, url_encode(host_name));
|
|
printf("service=%s'>View Notifications For This Service</A><BR>\n", url_encode(svc_description));
|
|
}
|
|
|
|
printf("</TD></TR>\n");
|
|
printf("</TABLE>\n");
|
|
}
|
|
|
|
printf("</td>\n");
|
|
|
|
/* center column of top row */
|
|
printf("<td align=center valign=top width=33%%>\n");
|
|
|
|
if(display_type != DISPLAY_NO_HISTOGRAM && input_type == GET_INPUT_NONE) {
|
|
|
|
printf("<DIV ALIGN=CENTER CLASS='dataTitle'>\n");
|
|
if(display_type == DISPLAY_HOST_HISTOGRAM)
|
|
printf("Host '%s'", host_name);
|
|
else if(display_type == DISPLAY_SERVICE_HISTOGRAM)
|
|
printf("Service '%s' On Host '%s'", svc_description, host_name);
|
|
printf("</DIV>\n");
|
|
|
|
printf("<BR>\n");
|
|
|
|
printf("<IMG SRC='%s%s' BORDER=0 ALT='%s Event Histogram' TITLE='%s Event Histogram'>\n", url_images_path, TRENDS_ICON, (display_type == DISPLAY_HOST_HISTOGRAM) ? "Host" : "Service", (display_type == DISPLAY_HOST_HISTOGRAM) ? "Host" : "Service");
|
|
|
|
printf("<BR CLEAR=ALL>\n");
|
|
|
|
get_time_string(&t1, start_timestring, sizeof(start_timestring) - 1, SHORT_DATE_TIME);
|
|
get_time_string(&t2, end_timestring, sizeof(end_timestring) - 1, SHORT_DATE_TIME);
|
|
printf("<div align=center class='reportRange'>%s to %s</div>\n", start_timestring, end_timestring);
|
|
|
|
get_time_breakdown((time_t)(t2 - t1), &days, &hours, &minutes, &seconds);
|
|
printf("<div align=center class='reportDuration'>Duration: %dd %dh %dm %ds</div>\n", days, hours, minutes, seconds);
|
|
}
|
|
|
|
printf("</td>\n");
|
|
|
|
/* right hand column of top row */
|
|
printf("<td align=right valign=bottom width=33%%>\n");
|
|
|
|
printf("<form method=\"GET\" action=\"%s\">\n", HISTOGRAM_CGI);
|
|
printf("<table border=0 CLASS='optBox'>\n");
|
|
|
|
if(display_type != DISPLAY_NO_HISTOGRAM && input_type == GET_INPUT_NONE) {
|
|
|
|
printf("<tr><td CLASS='optBoxItem' valign=top align=left>Report period:</td><td CLASS='optBoxItem' valign=top align=left>Assume state retention:</td></tr>\n");
|
|
printf("<tr><td CLASS='optBoxItem' valign=top align=left>\n");
|
|
|
|
printf("<input type='hidden' name='t1' value='%lu'>\n", (unsigned long)t1);
|
|
printf("<input type='hidden' name='t2' value='%lu'>\n", (unsigned long)t2);
|
|
printf("<input type='hidden' name='host' value='%s'>\n", escape_string(host_name));
|
|
if(display_type == DISPLAY_SERVICE_HISTOGRAM)
|
|
printf("<input type='hidden' name='service' value='%s'>\n", escape_string(svc_description));
|
|
|
|
printf("<select name='timeperiod'>\n");
|
|
printf("<option value=custom>[ Current time range ]\n");
|
|
printf("<option value=today %s>Today\n", (timeperiod_type == TIMEPERIOD_TODAY) ? "SELECTED" : "");
|
|
printf("<option value=last24hours %s>Last 24 Hours\n", (timeperiod_type == TIMEPERIOD_LAST24HOURS) ? "SELECTED" : "");
|
|
printf("<option value=yesterday %s>Yesterday\n", (timeperiod_type == TIMEPERIOD_YESTERDAY) ? "SELECTED" : "");
|
|
printf("<option value=thisweek %s>This Week\n", (timeperiod_type == TIMEPERIOD_THISWEEK) ? "SELECTED" : "");
|
|
printf("<option value=last7days %s>Last 7 Days\n", (timeperiod_type == TIMEPERIOD_LAST7DAYS) ? "SELECTED" : "");
|
|
printf("<option value=lastweek %s>Last Week\n", (timeperiod_type == TIMEPERIOD_LASTWEEK) ? "SELECTED" : "");
|
|
printf("<option value=thismonth %s>This Month\n", (timeperiod_type == TIMEPERIOD_THISMONTH) ? "SELECTED" : "");
|
|
printf("<option value=last31days %s>Last 31 Days\n", (timeperiod_type == TIMEPERIOD_LAST31DAYS) ? "SELECTED" : "");
|
|
printf("<option value=lastmonth %s>Last Month\n", (timeperiod_type == TIMEPERIOD_LASTMONTH) ? "SELECTED" : "");
|
|
printf("<option value=thisyear %s>This Year\n", (timeperiod_type == TIMEPERIOD_THISYEAR) ? "SELECTED" : "");
|
|
printf("<option value=lastyear %s>Last Year\n", (timeperiod_type == TIMEPERIOD_LASTYEAR) ? "SELECTED" : "");
|
|
printf("</select>\n");
|
|
printf("</td><td CLASS='optBoxItem' valign=top align=left>\n");
|
|
printf("<select name='assumestateretention'>\n");
|
|
printf("<option value=yes %s>yes\n", (assume_state_retention == TRUE) ? "SELECTED" : "");
|
|
printf("<option value=no %s>no\n", (assume_state_retention == TRUE) ? "" : "SELECTED");
|
|
printf("</select>\n");
|
|
printf("</td></tr>\n");
|
|
|
|
printf("<tr><td CLASS='optBoxItem' valign=top align=left>Breakdown type:</td><td CLASS='optBoxItem' valign=top align=left>Initial states logged:</td></tr>\n");
|
|
printf("<tr><td CLASS='optBoxItem' valign=top align=left>\n");
|
|
printf("<select name='breakdown'>\n");
|
|
printf("<option value=monthly %s>Month\n", (breakdown_type == BREAKDOWN_MONTHLY) ? "SELECTED" : "");
|
|
printf("<option value=dayofmonth %s>Day of the Month\n", (breakdown_type == BREAKDOWN_DAY_OF_MONTH) ? "SELECTED" : "");
|
|
printf("<option value=dayofweek %s>Day of the Week\n", (breakdown_type == BREAKDOWN_DAY_OF_WEEK) ? "SELECTED" : "");
|
|
printf("<option value=hourly %s>Hour of the Day\n", (breakdown_type == BREAKDOWN_HOURLY) ? "SELECTED" : "");
|
|
printf("</select>\n");
|
|
printf("</td><td CLASS='optBoxItem' valign=top align=left>\n");
|
|
printf("<select name='initialstateslogged'>\n");
|
|
printf("<option value=yes %s>yes\n", (initial_states_logged == TRUE) ? "SELECTED" : "");
|
|
printf("<option value=no %s>no\n", (initial_states_logged == TRUE) ? "" : "SELECTED");
|
|
printf("</select>\n");
|
|
printf("</td></tr>\n");
|
|
|
|
printf("<tr><td CLASS='optBoxItem' valign=top align=left>Events to graph:</td><td CLASS='optBoxItem' valign=top align=left>Ignore repeated states:</td></tr>\n");
|
|
printf("<tr><td CLASS='optBoxItem' valign=top align=left>\n");
|
|
printf("<select name='graphevents'>\n");
|
|
if(display_type == DISPLAY_HOST_HISTOGRAM) {
|
|
printf("<option value=%d %s>All host events\n", GRAPH_HOST_ALL, (graph_events == GRAPH_HOST_ALL) ? "SELECTED" : "");
|
|
printf("<option value=%d %s>Host problem events\n", GRAPH_HOST_PROBLEMS, (graph_events == GRAPH_HOST_PROBLEMS) ? "SELECTED" : "");
|
|
printf("<option value=%d %s>Host up events\n", GRAPH_HOST_UP, (graph_events == GRAPH_HOST_UP) ? "SELECTED" : "");
|
|
printf("<option value=%d %s>Host down events\n", GRAPH_HOST_DOWN, (graph_events == GRAPH_HOST_DOWN) ? "SELECTED" : "");
|
|
printf("<option value=%d %s>Host unreachable events\n", GRAPH_HOST_UNREACHABLE, (graph_events == GRAPH_HOST_UNREACHABLE) ? "SELECTED" : "");
|
|
}
|
|
else {
|
|
printf("<option value=%d %s>All service events\n", GRAPH_SERVICE_ALL, (graph_events == GRAPH_SERVICE_ALL) ? "SELECTED" : "");
|
|
printf("<option value=%d %s>Service problem events\n", GRAPH_SERVICE_PROBLEMS, (graph_events == GRAPH_SERVICE_PROBLEMS) ? "SELECTED" : "");
|
|
printf("<option value=%d %s>Service ok events\n", GRAPH_SERVICE_OK, (graph_events == GRAPH_SERVICE_OK) ? "SELECTED" : "");
|
|
printf("<option value=%d %s>Service warning events\n", GRAPH_SERVICE_WARNING, (graph_events == GRAPH_SERVICE_WARNING) ? "SELECTED" : "");
|
|
printf("<option value=%d %s>Service unknown events\n", GRAPH_SERVICE_UNKNOWN, (graph_events == GRAPH_SERVICE_UNKNOWN) ? "SELECTED" : "");
|
|
printf("<option value=%d %s>Service critical events\n", GRAPH_SERVICE_CRITICAL, (graph_events == GRAPH_SERVICE_CRITICAL) ? "SELECTED" : "");
|
|
}
|
|
printf("</select>\n");
|
|
printf("</td><td CLASS='optBoxItem' valign=top align=left>\n");
|
|
printf("<select name='newstatesonly'>\n");
|
|
printf("<option value=yes %s>yes\n", (new_states_only == TRUE) ? "SELECTED" : "");
|
|
printf("<option value=no %s>no\n", (new_states_only == TRUE) ? "" : "SELECTED");
|
|
printf("</select>\n");
|
|
printf("</td></tr>\n");
|
|
|
|
printf("<tr><td CLASS='optBoxItem' valign=top align=left>State types to graph:</td><td CLASS='optBoxItem' valign=top align=left></td></tr>\n");
|
|
printf("<tr><td CLASS='optBoxItem' valign=top align=left>\n");
|
|
printf("<select name='graphstatetypes'>\n");
|
|
printf("<option value=%d %s>Hard states\n", GRAPH_HARD_STATETYPES, (graph_statetypes == GRAPH_HARD_STATETYPES) ? "SELECTED" : "");
|
|
printf("<option value=%d %s>Soft states\n", GRAPH_SOFT_STATETYPES, (graph_statetypes == GRAPH_SOFT_STATETYPES) ? "SELECTED" : "");
|
|
printf("<option value=%d %s>Hard and soft states\n", GRAPH_ALL_STATETYPES, (graph_statetypes == GRAPH_ALL_STATETYPES) ? "SELECTED" : "");
|
|
printf("</select>\n");
|
|
printf("</td><td CLASS='optBoxItem' valign=top align=left>\n");
|
|
printf("<input type='submit' value='Update'>\n");
|
|
printf("</td></tr>\n");
|
|
}
|
|
|
|
/* display context-sensitive help */
|
|
printf("<tr><td></td><td align=right valign=bottom>\n");
|
|
if(display_type != DISPLAY_NO_HISTOGRAM && input_type == GET_INPUT_NONE) {
|
|
if(display_type == DISPLAY_HOST_HISTOGRAM)
|
|
display_context_help(CONTEXTHELP_HISTOGRAM_HOST);
|
|
else
|
|
display_context_help(CONTEXTHELP_HISTOGRAM_SERVICE);
|
|
}
|
|
else if(display_type == DISPLAY_NO_HISTOGRAM || input_type != GET_INPUT_NONE) {
|
|
if(input_type == GET_INPUT_NONE)
|
|
display_context_help(CONTEXTHELP_HISTOGRAM_MENU1);
|
|
else if(input_type == GET_INPUT_TARGET_TYPE)
|
|
display_context_help(CONTEXTHELP_HISTOGRAM_MENU1);
|
|
else if(input_type == GET_INPUT_HOST_TARGET)
|
|
display_context_help(CONTEXTHELP_HISTOGRAM_MENU2);
|
|
else if(input_type == GET_INPUT_SERVICE_TARGET)
|
|
display_context_help(CONTEXTHELP_HISTOGRAM_MENU3);
|
|
else if(input_type == GET_INPUT_OPTIONS)
|
|
display_context_help(CONTEXTHELP_HISTOGRAM_MENU4);
|
|
}
|
|
printf("</td></tr>\n");
|
|
|
|
printf("</table>\n");
|
|
printf("</form>\n");
|
|
|
|
printf("</td>\n");
|
|
|
|
/* end of top table */
|
|
printf("</tr>\n");
|
|
printf("</table>\n");
|
|
}
|
|
|
|
/* check authorization... */
|
|
if(display_type == DISPLAY_HOST_HISTOGRAM) {
|
|
temp_host = find_host(host_name);
|
|
if(temp_host == NULL || is_authorized_for_host(temp_host, ¤t_authdata) == FALSE)
|
|
is_authorized = FALSE;
|
|
}
|
|
else if(display_type == DISPLAY_SERVICE_HISTOGRAM) {
|
|
temp_service = find_service(host_name, svc_description);
|
|
if(temp_service == NULL || is_authorized_for_service(temp_service, ¤t_authdata) == FALSE)
|
|
is_authorized = FALSE;
|
|
}
|
|
if(is_authorized == FALSE) {
|
|
|
|
if(mode == CREATE_HTML)
|
|
printf("<P><DIV ALIGN=CENTER CLASS='errorMessage'>It appears as though you are not authorized to view information for the specified %s...</DIV></P>\n", (display_type == DISPLAY_HOST_HISTOGRAM) ? "host" : "service");
|
|
|
|
document_footer();
|
|
free_memory();
|
|
return ERROR;
|
|
}
|
|
|
|
if(display_type != DISPLAY_NO_HISTOGRAM && input_type == GET_INPUT_NONE) {
|
|
|
|
/* print URL to image */
|
|
if(mode == CREATE_HTML) {
|
|
|
|
printf("<BR><BR>\n");
|
|
printf("<DIV ALIGN=CENTER>\n");
|
|
printf("<IMG SRC='%s?createimage&t1=%lu&t2=%lu", HISTOGRAM_CGI, (unsigned long)t1, (unsigned long)t2);
|
|
printf("&host=%s", url_encode(host_name));
|
|
if(display_type == DISPLAY_SERVICE_HISTOGRAM)
|
|
printf("&service=%s", url_encode(svc_description));
|
|
printf("&breakdown=");
|
|
if(breakdown_type == BREAKDOWN_MONTHLY)
|
|
printf("monthly");
|
|
else if(breakdown_type == BREAKDOWN_DAY_OF_MONTH)
|
|
printf("dayofmonth");
|
|
else if(breakdown_type == BREAKDOWN_DAY_OF_WEEK)
|
|
printf("dayofweek");
|
|
else
|
|
printf("hourly");
|
|
printf("&assumestateretention=%s", (assume_state_retention == TRUE) ? "yes" : "no");
|
|
printf("&initialstateslogged=%s", (initial_states_logged == TRUE) ? "yes" : "no");
|
|
printf("&newstatesonly=%s", (new_states_only == TRUE) ? "yes" : "no");
|
|
printf("&graphevents=%d", graph_events);
|
|
printf("&graphstatetypes=%d", graph_statetypes);
|
|
printf("' BORDER=0 name='histogramimage'>\n");
|
|
printf("</DIV>\n");
|
|
}
|
|
|
|
/* read and process state data */
|
|
else {
|
|
|
|
/* allocate memory */
|
|
tsdata = NULL;
|
|
if(breakdown_type == BREAKDOWN_MONTHLY)
|
|
total_buckets = 12;
|
|
else if(breakdown_type == BREAKDOWN_DAY_OF_MONTH)
|
|
total_buckets = 31;
|
|
else if(breakdown_type == BREAKDOWN_DAY_OF_WEEK)
|
|
total_buckets = 7;
|
|
else
|
|
total_buckets = 96;
|
|
|
|
tsdata = (timeslice_data *)malloc(sizeof(timeslice_data) * total_buckets);
|
|
if(tsdata == NULL)
|
|
return ERROR;
|
|
|
|
for(x = 0; x < total_buckets; x++) {
|
|
tsdata[x].service_ok = 0L;
|
|
tsdata[x].service_unknown = 0L;
|
|
tsdata[x].service_warning = 0L;
|
|
tsdata[x].service_critical = 0L;
|
|
tsdata[x].host_up = 0L;
|
|
tsdata[x].host_down = 0L;
|
|
tsdata[x].host_unreachable = 0L;
|
|
}
|
|
|
|
/* read in all necessary archived state data */
|
|
read_archived_state_data();
|
|
|
|
#ifdef DEBUG
|
|
printf("Done reading archived state data.\n");
|
|
#endif
|
|
|
|
/* location of image template */
|
|
snprintf(image_template, sizeof(image_template) - 1, "%s/%s", physical_images_path, HISTOGRAM_IMAGE);
|
|
image_template[sizeof(image_template) - 1] = '\x0';
|
|
|
|
/* allocate buffer for storing image */
|
|
image_file = fopen(image_template, "r");
|
|
if(image_file != NULL) {
|
|
histogram_image = gdImageCreateFromPng(image_file);
|
|
fclose(image_file);
|
|
}
|
|
if(histogram_image == NULL)
|
|
histogram_image = gdImageCreate(image_width, image_height);
|
|
if(histogram_image == NULL) {
|
|
#ifdef DEBUG
|
|
printf("Error: Could not allocate memory for image\n");
|
|
#endif
|
|
return ERROR;
|
|
}
|
|
|
|
/* allocate colors used for drawing */
|
|
color_white = gdImageColorAllocate(histogram_image, 255, 255, 255);
|
|
color_black = gdImageColorAllocate(histogram_image, 0, 0, 0);
|
|
color_red = gdImageColorAllocate(histogram_image, 255, 0, 0);
|
|
color_darkred = gdImageColorAllocate(histogram_image, 128, 0, 0);
|
|
color_green = gdImageColorAllocate(histogram_image, 0, 128, 0);
|
|
color_yellow = gdImageColorAllocate(histogram_image, 176, 178, 20);
|
|
color_orange = gdImageColorAllocate(histogram_image, 255, 100, 25);
|
|
color_lightgray = gdImageColorAllocate(histogram_image, 192, 192, 192);
|
|
|
|
/* set transparency index */
|
|
gdImageColorTransparent(histogram_image, color_white);
|
|
|
|
/* make sure the graphic is interlaced */
|
|
gdImageInterlace(histogram_image, 1);
|
|
|
|
#ifdef DEBUG
|
|
printf("Starting to graph data...\n");
|
|
#endif
|
|
|
|
/* graph archived state histogram data */
|
|
graph_all_histogram_data();
|
|
|
|
#ifdef DEBUG
|
|
printf("Done graphing data.\n");
|
|
#endif
|
|
|
|
/* use STDOUT for writing the image data... */
|
|
image_file = stdout;
|
|
|
|
#ifdef DEBUG
|
|
image_file = fopen("/tmp/histogram.png", "w");
|
|
#endif
|
|
|
|
/* write the image to to STDOUT */
|
|
gdImagePng(histogram_image, image_file);
|
|
|
|
#ifdef DEBUG
|
|
fclose(image_file);
|
|
#endif
|
|
|
|
/* free memory allocated to image */
|
|
gdImageDestroy(histogram_image);
|
|
|
|
/* free memory allocated for data */
|
|
free(tsdata);
|
|
}
|
|
}
|
|
|
|
|
|
/* show user a selection of hosts and services to choose from... */
|
|
if(display_type == DISPLAY_NO_HISTOGRAM || input_type != GET_INPUT_NONE) {
|
|
|
|
/* ask the user for what host they want a report for */
|
|
if(input_type == GET_INPUT_HOST_TARGET) {
|
|
|
|
printf("<P><DIV ALIGN=CENTER>\n");
|
|
printf("<DIV CLASS='reportSelectTitle'>Step 2: Select Host</DIV>\n");
|
|
printf("</DIV></P>\n");
|
|
|
|
printf("<P><DIV ALIGN=CENTER>\n");
|
|
|
|
printf("<form method=\"GET\" action=\"%s\">\n", HISTOGRAM_CGI);
|
|
printf("<input type='hidden' name='input' value='getoptions'>\n");
|
|
|
|
printf("<TABLE BORDER=0 cellspacing=0 cellpadding=10>\n");
|
|
printf("<tr><td class='reportSelectSubTitle' valign=center>Host:</td>\n");
|
|
printf("<td class='reportSelectItem' valign=center>\n");
|
|
printf("<select name='host'>\n");
|
|
|
|
for(temp_host = host_list; temp_host != NULL; temp_host = temp_host->next) {
|
|
if(is_authorized_for_host(temp_host, ¤t_authdata) == TRUE)
|
|
printf("<option value='%s'>%s\n", escape_string(temp_host->name), temp_host->name);
|
|
}
|
|
|
|
printf("</select>\n");
|
|
printf("</td></tr>\n");
|
|
|
|
printf("<tr><td></td><td class='reportSelectItem'>\n");
|
|
printf("<input type='submit' value='Continue to Step 3'>\n");
|
|
printf("</td></tr>\n");
|
|
|
|
printf("</TABLE>\n");
|
|
printf("</form>\n");
|
|
|
|
printf("</DIV></P>\n");
|
|
}
|
|
|
|
/* ask the user for what service they want a report for */
|
|
else if(input_type == GET_INPUT_SERVICE_TARGET) {
|
|
|
|
printf("<SCRIPT LANGUAGE='JavaScript'>\n");
|
|
printf("function gethostname(hostindex){\n");
|
|
printf("hostnames=[");
|
|
|
|
for(temp_service = service_list; temp_service != NULL; temp_service = temp_service->next) {
|
|
if(is_authorized_for_service(temp_service, ¤t_authdata) == TRUE) {
|
|
if(found == TRUE)
|
|
printf(",");
|
|
else
|
|
first_service = temp_service->host_name;
|
|
printf(" \"%s\"", temp_service->host_name);
|
|
found = TRUE;
|
|
}
|
|
}
|
|
|
|
printf(" ]\n");
|
|
printf("return hostnames[hostindex];\n");
|
|
printf("}\n");
|
|
printf("</SCRIPT>\n");
|
|
|
|
|
|
printf("<P><DIV ALIGN=CENTER>\n");
|
|
printf("<DIV CLASS='reportSelectTitle'>Step 2: Select Service</DIV>\n");
|
|
printf("</DIV></P>\n");
|
|
|
|
printf("<P><DIV ALIGN=CENTER>\n");
|
|
|
|
printf("<form method=\"GET\" action=\"%s\" name=\"serviceform\">\n", HISTOGRAM_CGI);
|
|
printf("<input type='hidden' name='input' value='getoptions'>\n");
|
|
printf("<input type='hidden' name='host' value='%s'>\n", (first_service == NULL) ? "unknown" : (char *)escape_string(first_service));
|
|
|
|
printf("<TABLE BORDER=0 cellpadding=5>\n");
|
|
printf("<tr><td class='reportSelectSubTitle'>Service:</td>\n");
|
|
printf("<td class='reportSelectItem'>\n");
|
|
printf("<select name='service' onFocus='document.serviceform.host.value=gethostname(this.selectedIndex);' onChange='document.serviceform.host.value=gethostname(this.selectedIndex);'>\n");
|
|
|
|
for(temp_service = service_list; temp_service != NULL; temp_service = temp_service->next) {
|
|
if(is_authorized_for_service(temp_service, ¤t_authdata) == TRUE)
|
|
printf("<option value='%s'>%s;%s\n", escape_string(temp_service->description), temp_service->host_name, temp_service->description);
|
|
}
|
|
|
|
printf("</select>\n");
|
|
printf("</td></tr>\n");
|
|
|
|
printf("<tr><td></td><td class='reportSelectItem'>\n");
|
|
printf("<input type='submit' value='Continue to Step 3'>\n");
|
|
printf("</td></tr>\n");
|
|
|
|
printf("</TABLE>\n");
|
|
printf("</form>\n");
|
|
|
|
printf("</DIV></P>\n");
|
|
}
|
|
|
|
/* ask the user for report range and options */
|
|
else if(input_type == GET_INPUT_OPTIONS) {
|
|
|
|
time(¤t_time);
|
|
t = localtime(¤t_time);
|
|
|
|
start_day = 1;
|
|
start_year = t->tm_year + 1900;
|
|
end_day = t->tm_mday;
|
|
end_year = t->tm_year + 1900;
|
|
|
|
printf("<P><DIV ALIGN=CENTER>\n");
|
|
printf("<DIV CLASS='reportSelectTitle'>Step 3: Select Report Options</DIV>\n");
|
|
printf("</DIV></P>\n");
|
|
|
|
printf("<P><DIV ALIGN=CENTER>\n");
|
|
|
|
printf("<form method=\"GET\" action=\"%s\">\n", HISTOGRAM_CGI);
|
|
printf("<input type='hidden' name='host' value='%s'>\n", escape_string(host_name));
|
|
if(display_type == DISPLAY_SERVICE_HISTOGRAM)
|
|
printf("<input type='hidden' name='service' value='%s'>\n", escape_string(svc_description));
|
|
|
|
printf("<TABLE BORDER=0 cellpadding=5>\n");
|
|
printf("<tr><td class='reportSelectSubTitle' align=right>Report Period:</td>\n");
|
|
printf("<td class='reportSelectItem'>\n");
|
|
printf("<select name='timeperiod'>\n");
|
|
printf("<option value=today>Today\n");
|
|
printf("<option value=last24hours>Last 24 Hours\n");
|
|
printf("<option value=yesterday>Yesterday\n");
|
|
printf("<option value=thisweek>This Week\n");
|
|
printf("<option value=last7days SELECTED>Last 7 Days\n");
|
|
printf("<option value=lastweek>Last Week\n");
|
|
printf("<option value=thismonth>This Month\n");
|
|
printf("<option value=last31days>Last 31 Days\n");
|
|
printf("<option value=lastmonth>Last Month\n");
|
|
printf("<option value=thisyear>This Year\n");
|
|
printf("<option value=lastyear>Last Year\n");
|
|
printf("<option value=custom>* CUSTOM REPORT PERIOD *\n");
|
|
printf("</select>\n");
|
|
printf("</td></tr>\n");
|
|
|
|
printf("<tr><td valign=top class='reportSelectSubTitle'>If Custom Report Period...</td></tr>\n");
|
|
|
|
printf("<tr>");
|
|
printf("<td valign=top class='reportSelectSubTitle'>Start Date (Inclusive):</td>\n");
|
|
printf("<td align=left valign=top class='reportSelectItem'>");
|
|
printf("<select name='smon'>\n");
|
|
printf("<option value='1' %s>January\n", (t->tm_mon == 0) ? "SELECTED" : "");
|
|
printf("<option value='2' %s>February\n", (t->tm_mon == 1) ? "SELECTED" : "");
|
|
printf("<option value='3' %s>March\n", (t->tm_mon == 2) ? "SELECTED" : "");
|
|
printf("<option value='4' %s>April\n", (t->tm_mon == 3) ? "SELECTED" : "");
|
|
printf("<option value='5' %s>May\n", (t->tm_mon == 4) ? "SELECTED" : "");
|
|
printf("<option value='6' %s>June\n", (t->tm_mon == 5) ? "SELECTED" : "");
|
|
printf("<option value='7' %s>July\n", (t->tm_mon == 6) ? "SELECTED" : "");
|
|
printf("<option value='8' %s>August\n", (t->tm_mon == 7) ? "SELECTED" : "");
|
|
printf("<option value='9' %s>September\n", (t->tm_mon == 8) ? "SELECTED" : "");
|
|
printf("<option value='10' %s>October\n", (t->tm_mon == 9) ? "SELECTED" : "");
|
|
printf("<option value='11' %s>November\n", (t->tm_mon == 10) ? "SELECTED" : "");
|
|
printf("<option value='12' %s>December\n", (t->tm_mon == 11) ? "SELECTED" : "");
|
|
printf("</select>\n ");
|
|
printf("<input type='text' size='2' maxlength='2' name='sday' value='%d'> ", start_day);
|
|
printf("<input type='text' size='4' maxlength='4' name='syear' value='%d'>", start_year);
|
|
printf("<input type='hidden' name='shour' value='0'>\n");
|
|
printf("<input type='hidden' name='smin' value='0'>\n");
|
|
printf("<input type='hidden' name='ssec' value='0'>\n");
|
|
printf("</td>\n");
|
|
printf("</tr>\n");
|
|
|
|
printf("<tr>");
|
|
printf("<td valign=top class='reportSelectSubTitle'>End Date (Inclusive):</td>\n");
|
|
printf("<td align=left valign=top class='reportSelectItem'>");
|
|
printf("<select name='emon'>\n");
|
|
printf("<option value='1' %s>January\n", (t->tm_mon == 0) ? "SELECTED" : "");
|
|
printf("<option value='2' %s>February\n", (t->tm_mon == 1) ? "SELECTED" : "");
|
|
printf("<option value='3' %s>March\n", (t->tm_mon == 2) ? "SELECTED" : "");
|
|
printf("<option value='4' %s>April\n", (t->tm_mon == 3) ? "SELECTED" : "");
|
|
printf("<option value='5' %s>May\n", (t->tm_mon == 4) ? "SELECTED" : "");
|
|
printf("<option value='6' %s>June\n", (t->tm_mon == 5) ? "SELECTED" : "");
|
|
printf("<option value='7' %s>July\n", (t->tm_mon == 6) ? "SELECTED" : "");
|
|
printf("<option value='8' %s>August\n", (t->tm_mon == 7) ? "SELECTED" : "");
|
|
printf("<option value='9' %s>September\n", (t->tm_mon == 8) ? "SELECTED" : "");
|
|
printf("<option value='10' %s>October\n", (t->tm_mon == 9) ? "SELECTED" : "");
|
|
printf("<option value='11' %s>November\n", (t->tm_mon == 10) ? "SELECTED" : "");
|
|
printf("<option value='12' %s>December\n", (t->tm_mon == 11) ? "SELECTED" : "");
|
|
printf("</select>\n ");
|
|
printf("<input type='text' size='2' maxlength='2' name='eday' value='%d'> ", end_day);
|
|
printf("<input type='text' size='4' maxlength='4' name='eyear' value='%d'>", end_year);
|
|
printf("<input type='hidden' name='ehour' value='24'>\n");
|
|
printf("<input type='hidden' name='emin' value='0'>\n");
|
|
printf("<input type='hidden' name='esec' value='0'>\n");
|
|
printf("</td>\n");
|
|
printf("</tr>\n");
|
|
|
|
printf("<tr><td colspan=2><br></td></tr>\n");
|
|
|
|
printf("<tr><td class='reportSelectSubTitle' align=right>Statistics Breakdown:</td>\n");
|
|
printf("<td class='reportSelectItem'>\n");
|
|
printf("<select name='breakdown'>\n");
|
|
printf("<option value=monthly>Month\n");
|
|
printf("<option value=dayofmonth SELECTED>Day of the Month\n");
|
|
printf("<option value=dayofweek>Day of the Week\n");
|
|
printf("<option value=hourly>Hour of the Day\n");
|
|
printf("</select>\n");
|
|
printf("</td></tr>\n");
|
|
|
|
printf("<tr><td class='reportSelectSubTitle' align=right>Events To Graph:</td>\n");
|
|
printf("<td class='reportSelectItem'>\n");
|
|
printf("<select name='graphevents'>\n");
|
|
if(display_type == DISPLAY_HOST_HISTOGRAM) {
|
|
printf("<option value=%d %s>All host events\n", GRAPH_HOST_ALL, (graph_events == GRAPH_HOST_ALL) ? "SELECTED" : "");
|
|
printf("<option value=%d %s>Host problem events\n", GRAPH_HOST_PROBLEMS, (graph_events == GRAPH_HOST_PROBLEMS) ? "SELECTED" : "");
|
|
printf("<option value=%d %s>Host up events\n", GRAPH_HOST_UP, (graph_events == GRAPH_HOST_UP) ? "SELECTED" : "");
|
|
printf("<option value=%d %s>Host down events\n", GRAPH_HOST_DOWN, (graph_events == GRAPH_HOST_DOWN) ? "SELECTED" : "");
|
|
printf("<option value=%d %s>Host unreachable events\n", GRAPH_HOST_UNREACHABLE, (graph_events == GRAPH_HOST_UNREACHABLE) ? "SELECTED" : "");
|
|
}
|
|
else {
|
|
printf("<option value=%d %s>All service events\n", GRAPH_SERVICE_ALL, (graph_events == GRAPH_SERVICE_ALL) ? "SELECTED" : "");
|
|
printf("<option value=%d %s>Service problem events\n", GRAPH_SERVICE_PROBLEMS, (graph_events == GRAPH_SERVICE_PROBLEMS) ? "SELECTED" : "");
|
|
printf("<option value=%d %s>Service ok events\n", GRAPH_SERVICE_OK, (graph_events == GRAPH_SERVICE_OK) ? "SELECTED" : "");
|
|
printf("<option value=%d %s>Service warning events\n", GRAPH_SERVICE_WARNING, (graph_events == GRAPH_SERVICE_WARNING) ? "SELECTED" : "");
|
|
printf("<option value=%d %s>Service unknown events\n", GRAPH_SERVICE_UNKNOWN, (graph_events == GRAPH_SERVICE_UNKNOWN) ? "SELECTED" : "");
|
|
printf("<option value=%d %s>Service critical events\n", GRAPH_SERVICE_CRITICAL, (graph_events == GRAPH_SERVICE_CRITICAL) ? "SELECTED" : "");
|
|
}
|
|
printf("</select>\n");
|
|
printf("</td></tr>\n");
|
|
|
|
printf("<tr><td class='reportSelectSubTitle' align=right>State Types To Graph:</td>\n");
|
|
printf("<td class='reportSelectItem'>\n");
|
|
printf("<select name='graphstatetypes'>\n");
|
|
printf("<option value=%d>Hard states\n", GRAPH_HARD_STATETYPES);
|
|
printf("<option value=%d>Soft states\n", GRAPH_SOFT_STATETYPES);
|
|
printf("<option value=%d SELECTED>Hard and soft states\n", GRAPH_ALL_STATETYPES);
|
|
printf("</select>\n");
|
|
printf("</td></tr>\n");
|
|
|
|
printf("<tr><td class='reportSelectSubTitle' align=right>Assume State Retention:</td>\n");
|
|
printf("<td class='reportSelectItem'>\n");
|
|
printf("<select name='assumestateretention'>\n");
|
|
printf("<option value='yes'>Yes\n");
|
|
printf("<option value='no'>No\n");
|
|
printf("</select>\n");
|
|
printf("</td></tr>\n");
|
|
|
|
printf("<tr><td class='reportSelectSubTitle' align=right>Initial States Logged:</td>\n");
|
|
printf("<td class='reportSelectItem'>\n");
|
|
printf("<select name='initialstateslogged'>\n");
|
|
printf("<option value='yes'>Yes\n");
|
|
printf("<option value='no' SELECTED>No\n");
|
|
printf("</select>\n");
|
|
printf("</td></tr>\n");
|
|
|
|
printf("<tr><td class='reportSelectSubTitle' align=right>Ignore Repeated States:</td>\n");
|
|
printf("<td class='reportSelectItem'>\n");
|
|
printf("<select name='newstatesonly'>\n");
|
|
printf("<option value='yes'>Yes\n");
|
|
printf("<option value='no' SELECTED>No\n");
|
|
printf("</select>\n");
|
|
printf("</td></tr>\n");
|
|
|
|
printf("<tr><td></td><td class='reportSelectItem'><input type='submit' value='Create Report'></td></tr>\n");
|
|
|
|
printf("</TABLE>\n");
|
|
printf("</form>\n");
|
|
|
|
printf("</DIV></P>\n");
|
|
}
|
|
|
|
/* as the user whether they want a graph for a host or service */
|
|
else {
|
|
printf("<P><DIV ALIGN=CENTER>\n");
|
|
printf("<DIV CLASS='reportSelectTitle'>Step 1: Select Report Type</DIV>\n");
|
|
printf("</DIV></P>\n");
|
|
|
|
printf("<P><DIV ALIGN=CENTER>\n");
|
|
|
|
printf("<form method=\"GET\" action=\"%s\">\n", HISTOGRAM_CGI);
|
|
printf("<TABLE BORDER=0 cellpadding=5>\n");
|
|
printf("<tr><td class='reportSelectSubTitle' align=right>Type:</td>\n");
|
|
printf("<td class='reportSelectItem'>\n");
|
|
printf("<select name='input'>\n");
|
|
printf("<option value=gethost>Host\n");
|
|
printf("<option value=getservice>Service\n");
|
|
printf("</select>\n");
|
|
printf("</td></tr>\n");
|
|
|
|
printf("<tr><td></td><td class='reportSelectItem'>\n");
|
|
printf("<input type='submit' value='Continue to Step 2'>\n");
|
|
printf("</td></tr>\n");
|
|
|
|
printf("</TABLE>\n");
|
|
printf("</form>\n");
|
|
|
|
printf("</DIV></P>\n");
|
|
}
|
|
|
|
}
|
|
|
|
document_footer();
|
|
|
|
/* free all other allocated memory */
|
|
free_memory();
|
|
|
|
return OK;
|
|
}
|
|
|
|
|
|
void document_header(int use_stylesheet) {
|
|
char date_time[MAX_DATETIME_LENGTH];
|
|
time_t current_time;
|
|
time_t expire_time;
|
|
|
|
if(mode == CREATE_HTML) {
|
|
printf("Cache-Control: no-store\r\n");
|
|
printf("Pragma: no-cache\r\n");
|
|
|
|
time(¤t_time);
|
|
get_time_string(¤t_time, date_time, sizeof(date_time), HTTP_DATE_TIME);
|
|
printf("Last-Modified: %s\r\n", date_time);
|
|
|
|
expire_time = (time_t)0;
|
|
get_time_string(&expire_time, date_time, sizeof(date_time), HTTP_DATE_TIME);
|
|
printf("Expires: %s\r\n", date_time);
|
|
|
|
printf("Content-type: text/html\r\n\r\n");
|
|
|
|
if(embedded == TRUE)
|
|
return;
|
|
|
|
printf("<html>\n");
|
|
printf("<head>\n");
|
|
printf("<link rel=\"shortcut icon\" href=\"%sfavicon.ico\" type=\"image/ico\">\n", url_images_path);
|
|
printf("<title>\n");
|
|
printf("Nagios Histogram\n");
|
|
printf("</title>\n");
|
|
|
|
if(use_stylesheet == TRUE) {
|
|
printf("<LINK REL='stylesheet' TYPE='text/css' HREF='%s%s'>\n", url_stylesheets_path, COMMON_CSS);
|
|
printf("<LINK REL='stylesheet' TYPE='text/css' HREF='%s%s'>\n", url_stylesheets_path, HISTOGRAM_CSS);
|
|
}
|
|
|
|
printf("</head>\n");
|
|
|
|
printf("<BODY CLASS='histogram'>\n");
|
|
|
|
/* include user SSI header */
|
|
include_ssi_files(HISTOGRAM_CGI, SSI_HEADER);
|
|
|
|
printf("<div id=\"popup\" style=\"position:absolute; z-index:1; visibility: hidden\"></div>\n");
|
|
}
|
|
|
|
else {
|
|
printf("Cache-Control: no-store\r\n");
|
|
printf("Pragma: no-cache\r\n");
|
|
|
|
time(¤t_time);
|
|
get_time_string(¤t_time, date_time, sizeof(date_time), HTTP_DATE_TIME);
|
|
printf("Last-Modified: %s\r\n", date_time);
|
|
|
|
expire_time = (time_t)0L;
|
|
get_time_string(&expire_time, date_time, sizeof(date_time), HTTP_DATE_TIME);
|
|
printf("Expires: %s\r\n", date_time);
|
|
|
|
printf("Content-Type: image/png\r\n\r\n");
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
void document_footer(void) {
|
|
|
|
if(embedded == TRUE)
|
|
return;
|
|
|
|
if(mode == CREATE_HTML) {
|
|
|
|
/* include user SSI footer */
|
|
include_ssi_files(HISTOGRAM_CGI, SSI_FOOTER);
|
|
|
|
printf("</body>\n");
|
|
printf("</html>\n");
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
int process_cgivars(void) {
|
|
char **variables;
|
|
int error = FALSE;
|
|
int x;
|
|
|
|
variables = getcgivars();
|
|
|
|
for(x = 0; variables[x] != NULL; x++) {
|
|
|
|
/* do some basic length checking on the variable identifier to prevent buffer overflows */
|
|
if(strlen(variables[x]) >= MAX_INPUT_BUFFER - 1) {
|
|
x++;
|
|
continue;
|
|
}
|
|
|
|
/* we found the host argument */
|
|
else if(!strcmp(variables[x], "host")) {
|
|
x++;
|
|
if(variables[x] == NULL) {
|
|
error = TRUE;
|
|
break;
|
|
}
|
|
|
|
if((host_name = (char *)strdup(variables[x])) == NULL)
|
|
host_name = "";
|
|
strip_html_brackets(host_name);
|
|
|
|
display_type = DISPLAY_HOST_HISTOGRAM;
|
|
}
|
|
|
|
/* we found the node width argument */
|
|
else if(!strcmp(variables[x], "service")) {
|
|
x++;
|
|
if(variables[x] == NULL) {
|
|
error = TRUE;
|
|
break;
|
|
}
|
|
|
|
if((svc_description = (char *)strdup(variables[x])) == NULL)
|
|
svc_description = "";
|
|
strip_html_brackets(svc_description);
|
|
|
|
display_type = DISPLAY_SERVICE_HISTOGRAM;
|
|
}
|
|
|
|
/* we found first time argument */
|
|
else if(!strcmp(variables[x], "t1")) {
|
|
x++;
|
|
if(variables[x] == NULL) {
|
|
error = TRUE;
|
|
break;
|
|
}
|
|
|
|
t1 = (time_t)strtoul(variables[x], NULL, 10);
|
|
timeperiod_type = TIMEPERIOD_CUSTOM;
|
|
}
|
|
|
|
/* we found first time argument */
|
|
else if(!strcmp(variables[x], "t2")) {
|
|
x++;
|
|
if(variables[x] == NULL) {
|
|
error = TRUE;
|
|
break;
|
|
}
|
|
|
|
t2 = (time_t)strtoul(variables[x], NULL, 10);
|
|
timeperiod_type = TIMEPERIOD_CUSTOM;
|
|
}
|
|
|
|
/* we found the image creation option */
|
|
else if(!strcmp(variables[x], "createimage")) {
|
|
mode = CREATE_IMAGE;
|
|
}
|
|
|
|
/* we found the backtrack archives argument */
|
|
else if(!strcmp(variables[x], "backtrack")) {
|
|
x++;
|
|
if(variables[x] == NULL) {
|
|
error = TRUE;
|
|
break;
|
|
}
|
|
|
|
backtrack_archives = atoi(variables[x]);
|
|
if(backtrack_archives < 0)
|
|
backtrack_archives = 0;
|
|
if(backtrack_archives > MAX_ARCHIVE_BACKTRACKS)
|
|
backtrack_archives = MAX_ARCHIVE_BACKTRACKS;
|
|
}
|
|
|
|
/* we found the standard timeperiod argument */
|
|
else if(!strcmp(variables[x], "timeperiod")) {
|
|
x++;
|
|
if(variables[x] == NULL) {
|
|
error = TRUE;
|
|
break;
|
|
}
|
|
|
|
if(!strcmp(variables[x], "today"))
|
|
timeperiod_type = TIMEPERIOD_TODAY;
|
|
else if(!strcmp(variables[x], "yesterday"))
|
|
timeperiod_type = TIMEPERIOD_YESTERDAY;
|
|
else if(!strcmp(variables[x], "thisweek"))
|
|
timeperiod_type = TIMEPERIOD_THISWEEK;
|
|
else if(!strcmp(variables[x], "lastweek"))
|
|
timeperiod_type = TIMEPERIOD_LASTWEEK;
|
|
else if(!strcmp(variables[x], "thismonth"))
|
|
timeperiod_type = TIMEPERIOD_THISMONTH;
|
|
else if(!strcmp(variables[x], "lastmonth"))
|
|
timeperiod_type = TIMEPERIOD_LASTMONTH;
|
|
else if(!strcmp(variables[x], "thisquarter"))
|
|
timeperiod_type = TIMEPERIOD_THISQUARTER;
|
|
else if(!strcmp(variables[x], "lastquarter"))
|
|
timeperiod_type = TIMEPERIOD_LASTQUARTER;
|
|
else if(!strcmp(variables[x], "thisyear"))
|
|
timeperiod_type = TIMEPERIOD_THISYEAR;
|
|
else if(!strcmp(variables[x], "lastyear"))
|
|
timeperiod_type = TIMEPERIOD_LASTYEAR;
|
|
else if(!strcmp(variables[x], "last24hours"))
|
|
timeperiod_type = TIMEPERIOD_LAST24HOURS;
|
|
else if(!strcmp(variables[x], "last7days"))
|
|
timeperiod_type = TIMEPERIOD_LAST7DAYS;
|
|
else if(!strcmp(variables[x], "last31days"))
|
|
timeperiod_type = TIMEPERIOD_LAST31DAYS;
|
|
else if(!strcmp(variables[x], "custom"))
|
|
timeperiod_type = TIMEPERIOD_CUSTOM;
|
|
else
|
|
timeperiod_type = TIMEPERIOD_TODAY;
|
|
|
|
|
|
if(timeperiod_type != TIMEPERIOD_CUSTOM)
|
|
convert_timeperiod_to_times(timeperiod_type);
|
|
}
|
|
|
|
/* we found time argument */
|
|
else if(!strcmp(variables[x], "smon")) {
|
|
x++;
|
|
if(variables[x] == NULL) {
|
|
error = TRUE;
|
|
break;
|
|
}
|
|
|
|
if(timeperiod_type != TIMEPERIOD_CUSTOM)
|
|
continue;
|
|
|
|
start_month = atoi(variables[x]);
|
|
timeperiod_type = TIMEPERIOD_CUSTOM;
|
|
compute_time_from_parts = TRUE;
|
|
}
|
|
|
|
/* we found time argument */
|
|
else if(!strcmp(variables[x], "sday")) {
|
|
x++;
|
|
if(variables[x] == NULL) {
|
|
error = TRUE;
|
|
break;
|
|
}
|
|
|
|
if(timeperiod_type != TIMEPERIOD_CUSTOM)
|
|
continue;
|
|
|
|
start_day = atoi(variables[x]);
|
|
timeperiod_type = TIMEPERIOD_CUSTOM;
|
|
compute_time_from_parts = TRUE;
|
|
}
|
|
|
|
/* we found time argument */
|
|
else if(!strcmp(variables[x], "syear")) {
|
|
x++;
|
|
if(variables[x] == NULL) {
|
|
error = TRUE;
|
|
break;
|
|
}
|
|
|
|
if(timeperiod_type != TIMEPERIOD_CUSTOM)
|
|
continue;
|
|
|
|
start_year = atoi(variables[x]);
|
|
timeperiod_type = TIMEPERIOD_CUSTOM;
|
|
compute_time_from_parts = TRUE;
|
|
}
|
|
|
|
/* we found time argument */
|
|
else if(!strcmp(variables[x], "smin")) {
|
|
x++;
|
|
if(variables[x] == NULL) {
|
|
error = TRUE;
|
|
break;
|
|
}
|
|
|
|
if(timeperiod_type != TIMEPERIOD_CUSTOM)
|
|
continue;
|
|
|
|
start_minute = atoi(variables[x]);
|
|
timeperiod_type = TIMEPERIOD_CUSTOM;
|
|
compute_time_from_parts = TRUE;
|
|
}
|
|
|
|
/* we found time argument */
|
|
else if(!strcmp(variables[x], "ssec")) {
|
|
x++;
|
|
if(variables[x] == NULL) {
|
|
error = TRUE;
|
|
break;
|
|
}
|
|
|
|
if(timeperiod_type != TIMEPERIOD_CUSTOM)
|
|
continue;
|
|
|
|
start_second = atoi(variables[x]);
|
|
timeperiod_type = TIMEPERIOD_CUSTOM;
|
|
compute_time_from_parts = TRUE;
|
|
}
|
|
|
|
/* we found time argument */
|
|
else if(!strcmp(variables[x], "shour")) {
|
|
x++;
|
|
if(variables[x] == NULL) {
|
|
error = TRUE;
|
|
break;
|
|
}
|
|
|
|
if(timeperiod_type != TIMEPERIOD_CUSTOM)
|
|
continue;
|
|
|
|
start_hour = atoi(variables[x]);
|
|
timeperiod_type = TIMEPERIOD_CUSTOM;
|
|
compute_time_from_parts = TRUE;
|
|
}
|
|
|
|
|
|
/* we found time argument */
|
|
else if(!strcmp(variables[x], "emon")) {
|
|
x++;
|
|
if(variables[x] == NULL) {
|
|
error = TRUE;
|
|
break;
|
|
}
|
|
|
|
if(timeperiod_type != TIMEPERIOD_CUSTOM)
|
|
continue;
|
|
|
|
end_month = atoi(variables[x]);
|
|
timeperiod_type = TIMEPERIOD_CUSTOM;
|
|
compute_time_from_parts = TRUE;
|
|
}
|
|
|
|
/* we found time argument */
|
|
else if(!strcmp(variables[x], "eday")) {
|
|
x++;
|
|
if(variables[x] == NULL) {
|
|
error = TRUE;
|
|
break;
|
|
}
|
|
|
|
if(timeperiod_type != TIMEPERIOD_CUSTOM)
|
|
continue;
|
|
|
|
end_day = atoi(variables[x]);
|
|
timeperiod_type = TIMEPERIOD_CUSTOM;
|
|
compute_time_from_parts = TRUE;
|
|
}
|
|
|
|
/* we found time argument */
|
|
else if(!strcmp(variables[x], "eyear")) {
|
|
x++;
|
|
if(variables[x] == NULL) {
|
|
error = TRUE;
|
|
break;
|
|
}
|
|
|
|
if(timeperiod_type != TIMEPERIOD_CUSTOM)
|
|
continue;
|
|
|
|
end_year = atoi(variables[x]);
|
|
timeperiod_type = TIMEPERIOD_CUSTOM;
|
|
compute_time_from_parts = TRUE;
|
|
}
|
|
|
|
/* we found time argument */
|
|
else if(!strcmp(variables[x], "emin")) {
|
|
x++;
|
|
if(variables[x] == NULL) {
|
|
error = TRUE;
|
|
break;
|
|
}
|
|
|
|
if(timeperiod_type != TIMEPERIOD_CUSTOM)
|
|
continue;
|
|
|
|
end_minute = atoi(variables[x]);
|
|
timeperiod_type = TIMEPERIOD_CUSTOM;
|
|
compute_time_from_parts = TRUE;
|
|
}
|
|
|
|
/* we found time argument */
|
|
else if(!strcmp(variables[x], "esec")) {
|
|
x++;
|
|
if(variables[x] == NULL) {
|
|
error = TRUE;
|
|
break;
|
|
}
|
|
|
|
if(timeperiod_type != TIMEPERIOD_CUSTOM)
|
|
continue;
|
|
|
|
end_second = atoi(variables[x]);
|
|
timeperiod_type = TIMEPERIOD_CUSTOM;
|
|
compute_time_from_parts = TRUE;
|
|
}
|
|
|
|
/* we found time argument */
|
|
else if(!strcmp(variables[x], "ehour")) {
|
|
x++;
|
|
if(variables[x] == NULL) {
|
|
error = TRUE;
|
|
break;
|
|
}
|
|
|
|
if(timeperiod_type != TIMEPERIOD_CUSTOM)
|
|
continue;
|
|
|
|
end_hour = atoi(variables[x]);
|
|
timeperiod_type = TIMEPERIOD_CUSTOM;
|
|
compute_time_from_parts = TRUE;
|
|
}
|
|
|
|
/* we found the embed option */
|
|
else if(!strcmp(variables[x], "embedded"))
|
|
embedded = TRUE;
|
|
|
|
/* we found the noheader option */
|
|
else if(!strcmp(variables[x], "noheader"))
|
|
display_header = FALSE;
|
|
|
|
/* we found the input option */
|
|
else if(!strcmp(variables[x], "input")) {
|
|
x++;
|
|
if(variables[x] == NULL) {
|
|
error = TRUE;
|
|
break;
|
|
}
|
|
|
|
if(!strcmp(variables[x], "gethost"))
|
|
input_type = GET_INPUT_HOST_TARGET;
|
|
else if(!strcmp(variables[x], "getservice"))
|
|
input_type = GET_INPUT_SERVICE_TARGET;
|
|
else if(!strcmp(variables[x], "getoptions"))
|
|
input_type = GET_INPUT_OPTIONS;
|
|
else
|
|
input_type = GET_INPUT_TARGET_TYPE;
|
|
}
|
|
|
|
/* we found the graph states option */
|
|
else if(!strcmp(variables[x], "graphevents")) {
|
|
x++;
|
|
if(variables[x] == NULL) {
|
|
error = TRUE;
|
|
break;
|
|
}
|
|
|
|
graph_events = atoi(variables[x]);
|
|
}
|
|
|
|
/* we found the graph state types option */
|
|
else if(!strcmp(variables[x], "graphstatetypes")) {
|
|
x++;
|
|
if(variables[x] == NULL) {
|
|
error = TRUE;
|
|
break;
|
|
}
|
|
|
|
graph_statetypes = atoi(variables[x]);
|
|
}
|
|
|
|
/* we found the breakdown option */
|
|
else if(!strcmp(variables[x], "breakdown")) {
|
|
x++;
|
|
if(variables[x] == NULL) {
|
|
error = TRUE;
|
|
break;
|
|
}
|
|
|
|
if(!strcmp(variables[x], "monthly"))
|
|
breakdown_type = BREAKDOWN_MONTHLY;
|
|
else if(!strcmp(variables[x], "dayofmonth"))
|
|
breakdown_type = BREAKDOWN_DAY_OF_MONTH;
|
|
else if(!strcmp(variables[x], "dayofweek"))
|
|
breakdown_type = BREAKDOWN_DAY_OF_WEEK;
|
|
else
|
|
breakdown_type = BREAKDOWN_HOURLY;
|
|
}
|
|
|
|
/* we found the assume state retention option */
|
|
else if(!strcmp(variables[x], "assumestateretention")) {
|
|
x++;
|
|
if(variables[x] == NULL) {
|
|
error = TRUE;
|
|
break;
|
|
}
|
|
|
|
if(!strcmp(variables[x], "yes"))
|
|
assume_state_retention = TRUE;
|
|
else
|
|
assume_state_retention = FALSE;
|
|
}
|
|
|
|
/* we found the initial states logged option */
|
|
else if(!strcmp(variables[x], "initialstateslogged")) {
|
|
x++;
|
|
if(variables[x] == NULL) {
|
|
error = TRUE;
|
|
break;
|
|
}
|
|
|
|
if(!strcmp(variables[x], "yes"))
|
|
initial_states_logged = TRUE;
|
|
else
|
|
initial_states_logged = FALSE;
|
|
|
|
}
|
|
|
|
/* we found the new states only option */
|
|
else if(!strcmp(variables[x], "newstatesonly")) {
|
|
x++;
|
|
if(variables[x] == NULL) {
|
|
error = TRUE;
|
|
break;
|
|
}
|
|
|
|
if(!strcmp(variables[x], "yes"))
|
|
new_states_only = TRUE;
|
|
else
|
|
new_states_only = FALSE;
|
|
|
|
}
|
|
}
|
|
|
|
/* free memory allocated to the CGI variables */
|
|
free_cgivars(variables);
|
|
|
|
return error;
|
|
}
|
|
|
|
|
|
|
|
/* graphs histogram data */
|
|
void graph_all_histogram_data(void) {
|
|
int pixel_x;
|
|
int pixel_y;
|
|
int last_pixel_y;
|
|
int current_bucket;
|
|
int actual_bucket;
|
|
unsigned long max_value;
|
|
double x_scaling_factor;
|
|
double y_scaling_factor;
|
|
double x_units;
|
|
double y_units;
|
|
int current_unit;
|
|
int actual_unit;
|
|
char temp_buffer[MAX_INPUT_BUFFER];
|
|
int string_width;
|
|
int string_height;
|
|
char *days[7] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
|
|
char *months[12] = {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"};
|
|
char start_time[MAX_INPUT_BUFFER];
|
|
char end_time[MAX_INPUT_BUFFER];
|
|
|
|
unsigned long state1_max = 0L;
|
|
unsigned long state1_min = 0L;
|
|
int have_state1_min = FALSE;
|
|
unsigned long state1_sum = 0L;
|
|
double state1_avg = 0.0;
|
|
unsigned long state2_max = 0L;
|
|
unsigned long state2_min = 0L;
|
|
int have_state2_min = FALSE;
|
|
unsigned long state2_sum = 0L;
|
|
double state2_avg = 0.0;
|
|
unsigned long state3_max = 0L;
|
|
unsigned long state3_min = 0L;
|
|
int have_state3_min = FALSE;
|
|
unsigned long state3_sum = 0L;
|
|
double state3_avg = 0.0;
|
|
unsigned long state4_max = 0L;
|
|
unsigned long state4_min = 0L;
|
|
int have_state4_min = FALSE;
|
|
unsigned long state4_sum = 0L;
|
|
double state4_avg = 0.0;
|
|
|
|
|
|
#ifdef DEBUG
|
|
printf("Total Buckets: %d\n", total_buckets);
|
|
#endif
|
|
|
|
/* determine max value in the buckets (for scaling) */
|
|
max_value = 0L;
|
|
for(current_bucket = 0; current_bucket < total_buckets; current_bucket++) {
|
|
if(tsdata[current_bucket].service_ok > max_value)
|
|
max_value = tsdata[current_bucket].service_ok;
|
|
if(tsdata[current_bucket].service_warning > max_value)
|
|
max_value = tsdata[current_bucket].service_warning;
|
|
if(tsdata[current_bucket].service_unknown > max_value)
|
|
max_value = tsdata[current_bucket].service_unknown;
|
|
if(tsdata[current_bucket].service_critical > max_value)
|
|
max_value = tsdata[current_bucket].service_critical;
|
|
if(tsdata[current_bucket].host_up > max_value)
|
|
max_value = tsdata[current_bucket].host_up;
|
|
if(tsdata[current_bucket].host_down > max_value)
|
|
max_value = tsdata[current_bucket].host_down;
|
|
if(tsdata[current_bucket].host_unreachable > max_value)
|
|
max_value = tsdata[current_bucket].host_unreachable;
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
printf("Done determining max bucket values\n");
|
|
printf("MAX_VALUE=%lu\n", max_value);
|
|
printf("DRAWING_HEIGHT=%lu\n", DRAWING_HEIGHT);
|
|
#endif
|
|
|
|
/* min number of values to graph */
|
|
if(max_value < 10)
|
|
max_value = 10;
|
|
#ifdef DEBUG
|
|
printf("ADJUSTED MAX_VALUE=%lu\n", max_value);
|
|
#endif
|
|
|
|
/* determine y scaling factor */
|
|
/*y_scaling_factor=floor((double)DRAWING_HEIGHT/(double)max_value);*/
|
|
y_scaling_factor = (double)((double)DRAWING_HEIGHT / (double)max_value);
|
|
|
|
/* determine x scaling factor */
|
|
x_scaling_factor = (double)((double)DRAWING_WIDTH / (double)total_buckets);
|
|
|
|
/* determine y units resolution - we want a max of about 10 y grid lines */
|
|
/*
|
|
y_units=(double)((double)DRAWING_HEIGHT/19.0);
|
|
y_units=ceil(y_units/y_scaling_factor)*y_scaling_factor;
|
|
*/
|
|
y_units = ceil(19.0 / y_scaling_factor);
|
|
|
|
/* determine x units resolution */
|
|
if(breakdown_type == BREAKDOWN_HOURLY)
|
|
x_units = (double)((double)DRAWING_WIDTH / (double)(total_buckets / 4.0));
|
|
else
|
|
x_units = x_scaling_factor;
|
|
|
|
#ifdef DEBUG
|
|
printf("DRAWING_WIDTH: %d\n", DRAWING_WIDTH);
|
|
printf("DRAWING_HEIGHT: %d\n", DRAWING_HEIGHT);
|
|
printf("max_value: %lu\n", max_value);
|
|
printf("x_scaling_factor: %.3f\n", x_scaling_factor);
|
|
printf("y_scaling_factor: %.3f\n", y_scaling_factor);
|
|
printf("x_units: %.3f\n", x_units);
|
|
printf("y_units: %.3f\n", y_units);
|
|
printf("y units to draw: %.3f\n", ((double)max_value / y_units));
|
|
#endif
|
|
|
|
string_height = gdFontSmall->h;
|
|
|
|
#ifdef DEBUG
|
|
printf("Starting to draw Y grid lines...\n");
|
|
#endif
|
|
|
|
/* draw y grid lines */
|
|
if(max_value > 0) {
|
|
for(current_unit = 1; (current_unit * y_units * y_scaling_factor) <= DRAWING_HEIGHT; current_unit++) {
|
|
draw_dashed_line(DRAWING_X_OFFSET, DRAWING_Y_OFFSET - (current_unit * y_units * y_scaling_factor), DRAWING_X_OFFSET + DRAWING_WIDTH, DRAWING_Y_OFFSET - (current_unit * y_units * y_scaling_factor), color_lightgray);
|
|
#ifdef DEBUG
|
|
printf(" Drawing Y unit #%d @ %d\n", current_unit, (int)(current_unit * y_units * y_scaling_factor));
|
|
#endif
|
|
}
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
printf("Starting to draw X grid lines...\n");
|
|
#endif
|
|
|
|
/* draw x grid lines */
|
|
for(current_unit = 1; (int)(current_unit * x_units) <= DRAWING_WIDTH; current_unit++)
|
|
draw_dashed_line(DRAWING_X_OFFSET + (int)(current_unit * x_units), DRAWING_Y_OFFSET, DRAWING_X_OFFSET + (int)(current_unit * x_units), DRAWING_Y_OFFSET - DRAWING_HEIGHT, color_lightgray);
|
|
|
|
#ifdef DEBUG
|
|
printf("Starting to draw grid units...\n");
|
|
#endif
|
|
|
|
/* draw y units */
|
|
if(max_value > 0) {
|
|
for(current_unit = 0; (current_unit * y_units * y_scaling_factor) <= DRAWING_HEIGHT; current_unit++) {
|
|
snprintf(temp_buffer, sizeof(temp_buffer) - 1, "%d", (int)(current_unit * y_units));
|
|
temp_buffer[sizeof(temp_buffer) - 1] = '\x0';
|
|
string_width = gdFontSmall->w * strlen(temp_buffer);
|
|
gdImageString(histogram_image, gdFontSmall, DRAWING_X_OFFSET - string_width - 5, DRAWING_Y_OFFSET - (current_unit * y_units * y_scaling_factor) - (string_height / 2), (unsigned char *)temp_buffer, color_black);
|
|
}
|
|
}
|
|
|
|
/* draw x units */
|
|
for(current_unit = 0, actual_unit = 0; (int)(current_unit * x_units) <= DRAWING_WIDTH; current_unit++, actual_unit++) {
|
|
|
|
if(actual_unit >= total_buckets)
|
|
actual_unit = 0;
|
|
|
|
if(breakdown_type == BREAKDOWN_MONTHLY)
|
|
snprintf(temp_buffer, sizeof(temp_buffer) - 1, "%s", months[actual_unit]);
|
|
else if(breakdown_type == BREAKDOWN_DAY_OF_MONTH)
|
|
snprintf(temp_buffer, sizeof(temp_buffer) - 1, "%d", actual_unit + 1);
|
|
else if(breakdown_type == BREAKDOWN_DAY_OF_WEEK)
|
|
snprintf(temp_buffer, sizeof(temp_buffer) - 1, "%s", days[actual_unit]);
|
|
else
|
|
snprintf(temp_buffer, sizeof(temp_buffer) - 1, "%02d:00", (actual_unit == 24) ? 0 : actual_unit);
|
|
|
|
temp_buffer[sizeof(temp_buffer) - 1] = '\x0';
|
|
string_width = gdFontSmall->w * strlen(temp_buffer);
|
|
|
|
gdImageStringUp(histogram_image, gdFontSmall, DRAWING_X_OFFSET + (current_unit * x_units) - (string_height / 2), DRAWING_Y_OFFSET + 5 + string_width, (unsigned char *)temp_buffer, color_black);
|
|
}
|
|
|
|
/* draw y unit measure */
|
|
snprintf(temp_buffer, sizeof(temp_buffer) - 1, "Number of Events");
|
|
temp_buffer[sizeof(temp_buffer) - 1] = '\x0';
|
|
string_width = gdFontSmall->w * strlen(temp_buffer);
|
|
gdImageStringUp(histogram_image, gdFontSmall, 0, DRAWING_Y_OFFSET - (DRAWING_HEIGHT / 2) + (string_width / 2), (unsigned char *)temp_buffer, color_black);
|
|
|
|
/* draw x unit measure */
|
|
if(breakdown_type == BREAKDOWN_MONTHLY)
|
|
snprintf(temp_buffer, sizeof(temp_buffer) - 1, "Month");
|
|
else if(breakdown_type == BREAKDOWN_DAY_OF_MONTH)
|
|
snprintf(temp_buffer, sizeof(temp_buffer) - 1, "Day of the Month");
|
|
else if(breakdown_type == BREAKDOWN_DAY_OF_WEEK)
|
|
snprintf(temp_buffer, sizeof(temp_buffer) - 1, "Day of the Week");
|
|
else
|
|
snprintf(temp_buffer, sizeof(temp_buffer) - 1, "Hour of the Day (15 minute increments)");
|
|
temp_buffer[sizeof(temp_buffer) - 1] = '\x0';
|
|
string_width = gdFontSmall->w * strlen(temp_buffer);
|
|
gdImageString(histogram_image, gdFontSmall, DRAWING_X_OFFSET + (DRAWING_WIDTH / 2) - (string_width / 2), DRAWING_Y_OFFSET + 70, (unsigned char *)temp_buffer, color_black);
|
|
|
|
/* draw title */
|
|
snprintf(start_time, sizeof(start_time) - 1, "%s", ctime(&t1));
|
|
start_time[sizeof(start_time) - 1] = '\x0';
|
|
start_time[strlen(start_time) - 1] = '\x0';
|
|
snprintf(end_time, sizeof(end_time) - 1, "%s", ctime(&t2));
|
|
end_time[sizeof(end_time) - 1] = '\x0';
|
|
end_time[strlen(end_time) - 1] = '\x0';
|
|
|
|
if(display_type == DISPLAY_HOST_HISTOGRAM)
|
|
snprintf(temp_buffer, sizeof(temp_buffer) - 1, "Event History For Host '%s'", host_name);
|
|
else
|
|
snprintf(temp_buffer, sizeof(temp_buffer) - 1, "Event History For Service '%s' On Host '%s'", svc_description, host_name);
|
|
temp_buffer[sizeof(temp_buffer) - 1] = '\x0';
|
|
string_width = gdFontSmall->w * strlen(temp_buffer);
|
|
gdImageString(histogram_image, gdFontSmall, DRAWING_X_OFFSET + (DRAWING_WIDTH / 2) - (string_width / 2), 0, (unsigned char *)temp_buffer, color_black);
|
|
|
|
snprintf(temp_buffer, sizeof(temp_buffer) - 1, "%s to %s", start_time, end_time);
|
|
temp_buffer[sizeof(temp_buffer) - 1] = '\x0';
|
|
string_width = gdFontSmall->w * strlen(temp_buffer);
|
|
gdImageString(histogram_image, gdFontSmall, DRAWING_X_OFFSET + (DRAWING_WIDTH / 2) - (string_width / 2), string_height + 5, (unsigned char *)temp_buffer, color_black);
|
|
|
|
|
|
#ifdef DEBUG
|
|
printf("About to starting graphing (total_buckets=%d)...\n", total_buckets);
|
|
#endif
|
|
|
|
|
|
/* graph service states */
|
|
if(display_type == DISPLAY_HOST_HISTOGRAM) {
|
|
|
|
/* graph host recoveries */
|
|
if(graph_events & GRAPH_HOST_UP) {
|
|
|
|
last_pixel_y = 0;
|
|
for(current_bucket = 0, actual_bucket = 0; current_bucket <= total_buckets; current_bucket++, actual_bucket++) {
|
|
|
|
if(actual_bucket >= total_buckets)
|
|
actual_bucket = 0;
|
|
|
|
pixel_x = (int)(current_bucket * x_scaling_factor);
|
|
|
|
pixel_y = (int)(tsdata[actual_bucket].host_up * y_scaling_factor);
|
|
|
|
if(current_bucket > 0 && !(last_pixel_y == 0 && pixel_y == 0))
|
|
draw_line(DRAWING_X_OFFSET + pixel_x - (int)x_scaling_factor, DRAWING_Y_OFFSET - last_pixel_y, DRAWING_X_OFFSET + pixel_x, DRAWING_Y_OFFSET - pixel_y, color_green);
|
|
|
|
last_pixel_y = pixel_y;
|
|
|
|
if(current_bucket < total_buckets) {
|
|
if(have_state1_min == FALSE || tsdata[actual_bucket].host_up < state1_min) {
|
|
state1_min = tsdata[actual_bucket].host_up;
|
|
have_state1_min = TRUE;
|
|
}
|
|
if(state1_max == 0 || tsdata[actual_bucket].host_up > state1_max)
|
|
state1_max = tsdata[actual_bucket].host_up;
|
|
state1_sum += tsdata[actual_bucket].host_up;
|
|
}
|
|
}
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
printf("Done graphing HOST UP states...\n");
|
|
#endif
|
|
|
|
/* graph host down states */
|
|
if(graph_events & GRAPH_HOST_DOWN) {
|
|
|
|
last_pixel_y = 0;
|
|
for(current_bucket = 0, actual_bucket = 0; current_bucket <= total_buckets; current_bucket++, actual_bucket++) {
|
|
|
|
if(actual_bucket >= total_buckets)
|
|
actual_bucket = 0;
|
|
|
|
pixel_x = (int)(current_bucket * x_scaling_factor);
|
|
|
|
pixel_y = (int)(tsdata[actual_bucket].host_down * y_scaling_factor);
|
|
|
|
if(current_bucket > 0 && !(last_pixel_y == 0 && pixel_y == 0))
|
|
draw_line(DRAWING_X_OFFSET + pixel_x - (int)x_scaling_factor, DRAWING_Y_OFFSET - last_pixel_y, DRAWING_X_OFFSET + pixel_x, DRAWING_Y_OFFSET - pixel_y, color_red);
|
|
|
|
last_pixel_y = pixel_y;
|
|
|
|
if(current_bucket < total_buckets) {
|
|
if(have_state2_min == FALSE || tsdata[actual_bucket].host_down < state2_min) {
|
|
state2_min = tsdata[actual_bucket].host_down;
|
|
have_state2_min = TRUE;
|
|
}
|
|
if(state2_max == 0 || tsdata[actual_bucket].host_down > state2_max)
|
|
state2_max = tsdata[actual_bucket].host_down;
|
|
state2_sum += tsdata[actual_bucket].host_down;
|
|
}
|
|
}
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
printf("Done graphing HOST DOWN states...\n");
|
|
#endif
|
|
|
|
/* graph host unreachable states */
|
|
if(graph_events & GRAPH_HOST_UNREACHABLE) {
|
|
|
|
last_pixel_y = 0;
|
|
for(current_bucket = 0, actual_bucket = 0; current_bucket <= total_buckets; current_bucket++, actual_bucket++) {
|
|
|
|
if(actual_bucket >= total_buckets)
|
|
actual_bucket = 0;
|
|
|
|
pixel_x = (int)(current_bucket * x_scaling_factor);
|
|
|
|
pixel_y = (int)(tsdata[actual_bucket].host_unreachable * y_scaling_factor);
|
|
|
|
if(current_bucket > 0 && !(last_pixel_y == 0 && pixel_y == 0))
|
|
draw_line(DRAWING_X_OFFSET + pixel_x - (int)x_scaling_factor, DRAWING_Y_OFFSET - last_pixel_y, DRAWING_X_OFFSET + pixel_x, DRAWING_Y_OFFSET - pixel_y, color_darkred);
|
|
|
|
last_pixel_y = pixel_y;
|
|
|
|
if(current_bucket < total_buckets) {
|
|
if(have_state3_min == FALSE || tsdata[actual_bucket].host_unreachable < state3_min) {
|
|
state3_min = tsdata[actual_bucket].host_unreachable;
|
|
have_state3_min = TRUE;
|
|
}
|
|
if(state3_max == 0 || tsdata[actual_bucket].host_unreachable > state3_max)
|
|
state3_max = tsdata[actual_bucket].host_unreachable;
|
|
state3_sum += tsdata[actual_bucket].host_unreachable;
|
|
}
|
|
}
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
printf("Done graphing HOST UNREACHABLE states...\n");
|
|
#endif
|
|
|
|
}
|
|
|
|
/* graph service states */
|
|
else {
|
|
|
|
/* graph service recoveries */
|
|
if(graph_events & GRAPH_SERVICE_OK) {
|
|
|
|
last_pixel_y = 0;
|
|
for(current_bucket = 0, actual_bucket = 0; current_bucket <= total_buckets; current_bucket++, actual_bucket++) {
|
|
|
|
if(actual_bucket >= total_buckets)
|
|
actual_bucket = 0;
|
|
|
|
pixel_x = (int)(current_bucket * x_scaling_factor);
|
|
|
|
pixel_y = (int)(tsdata[actual_bucket].service_ok * y_scaling_factor);
|
|
|
|
if(current_bucket > 0 && !(last_pixel_y == 0 && pixel_y == 0))
|
|
draw_line(DRAWING_X_OFFSET + pixel_x - (int)x_scaling_factor, DRAWING_Y_OFFSET - last_pixel_y, DRAWING_X_OFFSET + pixel_x, DRAWING_Y_OFFSET - pixel_y, color_green);
|
|
|
|
last_pixel_y = pixel_y;
|
|
|
|
if(current_bucket < total_buckets) {
|
|
if(have_state1_min == FALSE || tsdata[actual_bucket].service_ok < state1_min) {
|
|
state1_min = tsdata[actual_bucket].service_ok;
|
|
have_state1_min = TRUE;
|
|
}
|
|
if(state1_max == 0 || tsdata[actual_bucket].service_ok > state1_max)
|
|
state1_max = tsdata[actual_bucket].service_ok;
|
|
state1_sum += tsdata[actual_bucket].service_ok;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* graph service warning states */
|
|
if(graph_events & GRAPH_SERVICE_WARNING) {
|
|
|
|
last_pixel_y = 0;
|
|
for(current_bucket = 0, actual_bucket = 0; current_bucket <= total_buckets; current_bucket++, actual_bucket++) {
|
|
|
|
if(actual_bucket >= total_buckets)
|
|
actual_bucket = 0;
|
|
|
|
pixel_x = (int)(current_bucket * x_scaling_factor);
|
|
|
|
pixel_y = (int)(tsdata[actual_bucket].service_warning * y_scaling_factor);
|
|
|
|
if(current_bucket > 0 && !(last_pixel_y == 0 && pixel_y == 0))
|
|
draw_line(DRAWING_X_OFFSET + pixel_x - (int)x_scaling_factor, DRAWING_Y_OFFSET - last_pixel_y, DRAWING_X_OFFSET + pixel_x, DRAWING_Y_OFFSET - pixel_y, color_yellow);
|
|
|
|
last_pixel_y = pixel_y;
|
|
|
|
if(current_bucket < total_buckets) {
|
|
if(have_state2_min == FALSE || tsdata[actual_bucket].service_warning < state2_min) {
|
|
state2_min = tsdata[actual_bucket].service_warning;
|
|
have_state2_min = TRUE;
|
|
}
|
|
if(state2_max == 0 || tsdata[actual_bucket].service_warning > state2_max)
|
|
state2_max = tsdata[actual_bucket].service_warning;
|
|
state2_sum += tsdata[actual_bucket].service_warning;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* graph service unknown states */
|
|
if(graph_events & GRAPH_SERVICE_UNKNOWN) {
|
|
|
|
last_pixel_y = 0;
|
|
for(current_bucket = 0, actual_bucket = 0; current_bucket <= total_buckets; current_bucket++, actual_bucket++) {
|
|
|
|
if(actual_bucket >= total_buckets)
|
|
actual_bucket = 0;
|
|
|
|
pixel_x = (int)(current_bucket * x_scaling_factor);
|
|
|
|
pixel_y = (int)(tsdata[actual_bucket].service_unknown * y_scaling_factor);
|
|
|
|
if(current_bucket > 0 && !(last_pixel_y == 0 && pixel_y == 0))
|
|
draw_line(DRAWING_X_OFFSET + pixel_x - (int)x_scaling_factor, DRAWING_Y_OFFSET - last_pixel_y, DRAWING_X_OFFSET + pixel_x, DRAWING_Y_OFFSET - pixel_y, color_orange);
|
|
|
|
last_pixel_y = pixel_y;
|
|
|
|
if(current_bucket < total_buckets) {
|
|
if(have_state3_min == FALSE || tsdata[actual_bucket].service_unknown < state3_min) {
|
|
state3_min = tsdata[actual_bucket].service_unknown;
|
|
have_state3_min = TRUE;
|
|
}
|
|
if(state3_max == 0 || tsdata[actual_bucket].service_unknown > state3_max)
|
|
state3_max = tsdata[actual_bucket].service_unknown;
|
|
state3_sum += tsdata[actual_bucket].service_unknown;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* graph service critical states */
|
|
if(graph_events & GRAPH_SERVICE_CRITICAL) {
|
|
|
|
last_pixel_y = 0;
|
|
for(current_bucket = 0, actual_bucket = 0; current_bucket <= total_buckets; current_bucket++, actual_bucket++) {
|
|
|
|
if(actual_bucket >= total_buckets)
|
|
actual_bucket = 0;
|
|
|
|
pixel_x = (int)(current_bucket * x_scaling_factor);
|
|
|
|
pixel_y = (int)(tsdata[actual_bucket].service_critical * y_scaling_factor);
|
|
|
|
if(current_bucket > 0 && !(last_pixel_y == 0 && pixel_y == 0))
|
|
draw_line(DRAWING_X_OFFSET + pixel_x - (int)x_scaling_factor, DRAWING_Y_OFFSET - last_pixel_y, DRAWING_X_OFFSET + pixel_x, DRAWING_Y_OFFSET - pixel_y, color_red);
|
|
|
|
last_pixel_y = pixel_y;
|
|
|
|
if(current_bucket < total_buckets) {
|
|
if(have_state4_min == FALSE || tsdata[actual_bucket].service_critical < state4_min) {
|
|
state4_min = tsdata[actual_bucket].service_critical;
|
|
have_state4_min = TRUE;
|
|
}
|
|
if(state4_max == 0 || tsdata[actual_bucket].service_critical > state4_max)
|
|
state4_max = tsdata[actual_bucket].service_critical;
|
|
state4_sum += tsdata[actual_bucket].service_critical;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
printf("Done graphing states...\n");
|
|
#endif
|
|
|
|
/* draw graph boundaries */
|
|
draw_line(DRAWING_X_OFFSET, DRAWING_Y_OFFSET, DRAWING_X_OFFSET, DRAWING_Y_OFFSET - DRAWING_HEIGHT, color_black);
|
|
draw_line(DRAWING_X_OFFSET + DRAWING_WIDTH, DRAWING_Y_OFFSET, DRAWING_X_OFFSET + DRAWING_WIDTH, DRAWING_Y_OFFSET - DRAWING_HEIGHT, color_black);
|
|
draw_line(DRAWING_X_OFFSET, DRAWING_Y_OFFSET, DRAWING_X_OFFSET + DRAWING_WIDTH, DRAWING_Y_OFFSET, color_black);
|
|
|
|
|
|
/* graph stats */
|
|
snprintf(temp_buffer, sizeof(temp_buffer) - 1, "EVENT TYPE");
|
|
temp_buffer[sizeof(temp_buffer) - 1] = '\x0';
|
|
string_width = gdFontSmall->w * strlen(temp_buffer);
|
|
gdImageString(histogram_image, gdFontSmall, DRAWING_X_OFFSET + DRAWING_WIDTH + 15, DRAWING_Y_OFFSET - DRAWING_HEIGHT, (unsigned char *)temp_buffer, color_black);
|
|
|
|
snprintf(temp_buffer, sizeof(temp_buffer) - 1, " MIN MAX SUM AVG");
|
|
temp_buffer[sizeof(temp_buffer) - 1] = '\x0';
|
|
string_width = gdFontSmall->w * strlen(temp_buffer);
|
|
gdImageString(histogram_image, gdFontSmall, DRAWING_X_OFFSET + DRAWING_WIDTH + 115, DRAWING_Y_OFFSET - DRAWING_HEIGHT, (unsigned char *)temp_buffer, color_black);
|
|
|
|
draw_line(DRAWING_X_OFFSET + DRAWING_WIDTH + 15, DRAWING_Y_OFFSET - DRAWING_HEIGHT + string_height + 2, DRAWING_X_OFFSET + DRAWING_WIDTH + 275, DRAWING_Y_OFFSET - DRAWING_HEIGHT + string_height + 2, color_black);
|
|
|
|
snprintf(temp_buffer, sizeof(temp_buffer) - 1, "Recovery (%s):", (display_type == DISPLAY_SERVICE_HISTOGRAM) ? "Ok" : "Up");
|
|
temp_buffer[sizeof(temp_buffer) - 1] = '\x0';
|
|
string_width = gdFontSmall->w * strlen(temp_buffer);
|
|
gdImageString(histogram_image, gdFontSmall, DRAWING_X_OFFSET + DRAWING_WIDTH + 15, DRAWING_Y_OFFSET - DRAWING_HEIGHT + ((string_height + 5) * 1), (unsigned char *)temp_buffer, color_green);
|
|
|
|
state1_avg = (double)((double)state1_sum / (double)total_buckets);
|
|
snprintf(temp_buffer, sizeof(temp_buffer) - 1, "%5lu %5lu %5lu %.2f", state1_min, state1_max, state1_sum, state1_avg);
|
|
temp_buffer[sizeof(temp_buffer) - 1] = '\x0';
|
|
string_width = gdFontSmall->w * strlen(temp_buffer);
|
|
gdImageString(histogram_image, gdFontSmall, DRAWING_X_OFFSET + DRAWING_WIDTH + 115, DRAWING_Y_OFFSET - DRAWING_HEIGHT + ((string_height + 5) * 1), (unsigned char *)temp_buffer, color_black);
|
|
|
|
snprintf(temp_buffer, sizeof(temp_buffer) - 1, "%s:", (display_type == DISPLAY_SERVICE_HISTOGRAM) ? "Warning" : "Down");
|
|
temp_buffer[sizeof(temp_buffer) - 1] = '\x0';
|
|
string_width = gdFontSmall->w * strlen(temp_buffer);
|
|
gdImageString(histogram_image, gdFontSmall, DRAWING_X_OFFSET + DRAWING_WIDTH + 15, DRAWING_Y_OFFSET - DRAWING_HEIGHT + ((string_height + 5) * 2), (unsigned char *)temp_buffer, (display_type == DISPLAY_SERVICE_HISTOGRAM) ? color_yellow : color_red);
|
|
|
|
state2_avg = (double)((double)state2_sum / (double)total_buckets);
|
|
snprintf(temp_buffer, sizeof(temp_buffer) - 1, "%5lu %5lu %5lu %.2f", state2_min, state2_max, state2_sum, state2_avg);
|
|
temp_buffer[sizeof(temp_buffer) - 1] = '\x0';
|
|
string_width = gdFontSmall->w * strlen(temp_buffer);
|
|
gdImageString(histogram_image, gdFontSmall, DRAWING_X_OFFSET + DRAWING_WIDTH + 115, DRAWING_Y_OFFSET - DRAWING_HEIGHT + ((string_height + 5) * 2), (unsigned char *)temp_buffer, color_black);
|
|
|
|
snprintf(temp_buffer, sizeof(temp_buffer) - 1, "%s:", (display_type == DISPLAY_SERVICE_HISTOGRAM) ? "Unknown" : "Unreachable");
|
|
temp_buffer[sizeof(temp_buffer) - 1] = '\x0';
|
|
string_width = gdFontSmall->w * strlen(temp_buffer);
|
|
gdImageString(histogram_image, gdFontSmall, DRAWING_X_OFFSET + DRAWING_WIDTH + 15, DRAWING_Y_OFFSET - DRAWING_HEIGHT + ((string_height + 5) * 3), (unsigned char *)temp_buffer, (display_type == DISPLAY_SERVICE_HISTOGRAM) ? color_orange : color_darkred);
|
|
|
|
state3_avg = (double)((double)state3_sum / (double)total_buckets);
|
|
snprintf(temp_buffer, sizeof(temp_buffer) - 1, "%5lu %5lu %5lu %.2f", state3_min, state3_max, state3_sum, state3_avg);
|
|
temp_buffer[sizeof(temp_buffer) - 1] = '\x0';
|
|
string_width = gdFontSmall->w * strlen(temp_buffer);
|
|
gdImageString(histogram_image, gdFontSmall, DRAWING_X_OFFSET + DRAWING_WIDTH + 115, DRAWING_Y_OFFSET - DRAWING_HEIGHT + ((string_height + 5) * 3), (unsigned char *)temp_buffer, color_black);
|
|
|
|
if(display_type == DISPLAY_SERVICE_HISTOGRAM) {
|
|
|
|
snprintf(temp_buffer, sizeof(temp_buffer) - 1, "Critical:");
|
|
temp_buffer[sizeof(temp_buffer) - 1] = '\x0';
|
|
string_width = gdFontSmall->w * strlen(temp_buffer);
|
|
gdImageString(histogram_image, gdFontSmall, DRAWING_X_OFFSET + DRAWING_WIDTH + 15, DRAWING_Y_OFFSET - DRAWING_HEIGHT + ((string_height + 5) * 4), (unsigned char *)temp_buffer, color_red);
|
|
|
|
state4_avg = (double)((double)state4_sum / (double)total_buckets);
|
|
snprintf(temp_buffer, sizeof(temp_buffer) - 1, "%5lu %5lu %5lu %.2f", state4_min, state4_max, state4_sum, state4_avg);
|
|
temp_buffer[sizeof(temp_buffer) - 1] = '\x0';
|
|
string_width = gdFontSmall->w * strlen(temp_buffer);
|
|
gdImageString(histogram_image, gdFontSmall, DRAWING_X_OFFSET + DRAWING_WIDTH + 115, DRAWING_Y_OFFSET - DRAWING_HEIGHT + ((string_height + 5) * 4), (unsigned char *)temp_buffer, color_black);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
/* adds an archived state entry */
|
|
void add_archived_state(int state_type, time_t time_stamp) {
|
|
struct tm *our_time;
|
|
int bucket;
|
|
int skip_state = FALSE;
|
|
|
|
#ifdef DEBUG2
|
|
printf("NEW ENTRY: last=%d this=%d\n", last_state, state_type);
|
|
#endif
|
|
|
|
/* don't record program starts/stops, just make a note that one occurred */
|
|
if(state_type == AS_PROGRAM_START || state_type == AS_PROGRAM_END) {
|
|
#ifdef DEBUG2
|
|
printf("Recording a program start: %d\n", state_type);
|
|
#endif
|
|
program_restart_has_occurred = TRUE;
|
|
return;
|
|
}
|
|
|
|
/* see if we should even take into account this event */
|
|
if(program_restart_has_occurred == TRUE) {
|
|
|
|
#ifdef DEBUG2
|
|
printf("program_restart_has_occurred: last=%d this=%d\n", last_state, state_type);
|
|
#endif
|
|
|
|
if(initial_states_logged == TRUE) {
|
|
if(state_type == AS_SVC_OK && last_state == AS_SVC_OK)
|
|
skip_state = TRUE;
|
|
if(state_type == AS_HOST_UP && last_state == AS_HOST_UP)
|
|
skip_state = TRUE;
|
|
}
|
|
|
|
if(assume_state_retention == TRUE && initial_states_logged == TRUE) {
|
|
if(state_type == AS_SVC_WARNING && last_state == AS_SVC_WARNING)
|
|
skip_state = TRUE;
|
|
if(state_type == AS_SVC_UNKNOWN && last_state == AS_SVC_UNKNOWN)
|
|
skip_state = TRUE;
|
|
if(state_type == AS_SVC_CRITICAL && last_state == AS_SVC_CRITICAL)
|
|
skip_state = TRUE;
|
|
if(state_type == AS_HOST_DOWN && last_state == AS_HOST_DOWN)
|
|
skip_state = TRUE;
|
|
if(state_type == AS_HOST_UNREACHABLE && last_state == AS_HOST_UNREACHABLE)
|
|
skip_state = TRUE;
|
|
}
|
|
|
|
if(skip_state == TRUE) {
|
|
program_restart_has_occurred = FALSE;
|
|
#ifdef DEBUG2
|
|
printf("Skipping state...\n");
|
|
#endif
|
|
return;
|
|
}
|
|
}
|
|
|
|
/* reset program restart variable */
|
|
program_restart_has_occurred = FALSE;
|
|
|
|
/* are we only processing new states */
|
|
if(new_states_only == TRUE && state_type == last_state) {
|
|
#ifdef DEBUG2
|
|
printf("Skipping state (not a new state)...\n");
|
|
#endif
|
|
return;
|
|
}
|
|
|
|
#ifdef DEBUG2
|
|
printf("GOODSTATE: %d @ %lu\n", state_type, (unsigned long)time_stamp);
|
|
#endif
|
|
|
|
|
|
|
|
our_time = localtime(&time_stamp);
|
|
|
|
/* calculate the correct bucket to dump the data into */
|
|
if(breakdown_type == BREAKDOWN_MONTHLY)
|
|
bucket = our_time->tm_mon;
|
|
|
|
else if(breakdown_type == BREAKDOWN_DAY_OF_MONTH)
|
|
bucket = our_time->tm_mday - 1;
|
|
|
|
else if(breakdown_type == BREAKDOWN_DAY_OF_WEEK)
|
|
bucket = our_time->tm_wday;
|
|
|
|
else
|
|
bucket = (our_time->tm_hour * 4) + (our_time->tm_min / 15);
|
|
|
|
#ifdef DEBUG2
|
|
printf("\tBucket=%d\n", bucket);
|
|
#endif
|
|
|
|
/* save the data in the correct bucket */
|
|
if(state_type == AS_SVC_OK)
|
|
tsdata[bucket].service_ok++;
|
|
else if(state_type == AS_SVC_UNKNOWN)
|
|
tsdata[bucket].service_unknown++;
|
|
else if(state_type == AS_SVC_WARNING)
|
|
tsdata[bucket].service_warning++;
|
|
else if(state_type == AS_SVC_CRITICAL)
|
|
tsdata[bucket].service_critical++;
|
|
else if(state_type == AS_HOST_UP)
|
|
tsdata[bucket].host_up++;
|
|
else if(state_type == AS_HOST_DOWN)
|
|
tsdata[bucket].host_down++;
|
|
else if(state_type == AS_HOST_UNREACHABLE)
|
|
tsdata[bucket].host_unreachable++;
|
|
|
|
/* record last state type */
|
|
last_state = state_type;
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
/* reads log files for archived state data */
|
|
void read_archived_state_data(void) {
|
|
char filename[MAX_FILENAME_LENGTH];
|
|
int newest_archive = 0;
|
|
int oldest_archive = 0;
|
|
int current_archive;
|
|
|
|
#ifdef DEBUG2
|
|
printf("Determining archives to use...\n");
|
|
#endif
|
|
|
|
/* determine earliest archive to use */
|
|
oldest_archive = determine_archive_to_use_from_time(t1);
|
|
if(log_rotation_method != LOG_ROTATION_NONE)
|
|
oldest_archive += backtrack_archives;
|
|
|
|
/* determine most recent archive to use */
|
|
newest_archive = determine_archive_to_use_from_time(t2);
|
|
|
|
if(oldest_archive < newest_archive)
|
|
oldest_archive = newest_archive;
|
|
|
|
#ifdef DEBUG2
|
|
printf("Oldest archive: %d\n", oldest_archive);
|
|
printf("Newest archive: %d\n", newest_archive);
|
|
#endif
|
|
|
|
/* read in all the necessary archived logs */
|
|
for(current_archive = newest_archive; current_archive <= oldest_archive; current_archive++) {
|
|
|
|
/* get the name of the log file that contains this archive */
|
|
get_log_archive_to_use(current_archive, filename, sizeof(filename) - 1);
|
|
|
|
#ifdef DEBUG2
|
|
printf("\tCurrent archive: %d (%s)\n", current_archive, filename);
|
|
#endif
|
|
|
|
/* scan the log file for archived state data */
|
|
scan_log_file_for_archived_state_data(filename);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
/* grabs archives state data from a log file */
|
|
void scan_log_file_for_archived_state_data(char *filename) {
|
|
char *input = NULL;
|
|
char *input2 = NULL;
|
|
char entry_host_name[MAX_INPUT_BUFFER];
|
|
char entry_svc_description[MAX_INPUT_BUFFER];
|
|
char *temp_buffer;
|
|
time_t time_stamp;
|
|
mmapfile *thefile;
|
|
|
|
/* print something so browser doesn't time out */
|
|
if(mode == CREATE_HTML) {
|
|
printf(" ");
|
|
fflush(NULL);
|
|
}
|
|
|
|
if((thefile = mmap_fopen(filename)) == NULL) {
|
|
#ifdef DEBUG2
|
|
printf("Could not open file '%s' for reading.\n", filename);
|
|
#endif
|
|
return;
|
|
}
|
|
|
|
#ifdef DEBUG2
|
|
printf("Scanning log file '%s' for archived state data...\n", filename);
|
|
#endif
|
|
|
|
while(1) {
|
|
|
|
/* free memory */
|
|
free(input);
|
|
free(input2);
|
|
input = NULL;
|
|
input2 = NULL;
|
|
|
|
/* read the next line */
|
|
if((input = mmap_fgets(thefile)) == NULL)
|
|
break;
|
|
|
|
strip(input);
|
|
|
|
if((input2 = strdup(input)) == NULL)
|
|
continue;
|
|
|
|
temp_buffer = my_strtok(input2, "]");
|
|
time_stamp = (temp_buffer == NULL) ? (time_t)0 : (time_t)strtoul(temp_buffer + 1, NULL, 10);
|
|
|
|
/* program starts/restarts */
|
|
if(strstr(input, " starting..."))
|
|
add_archived_state(AS_PROGRAM_START, time_stamp);
|
|
if(strstr(input, " restarting..."))
|
|
add_archived_state(AS_PROGRAM_START, time_stamp);
|
|
|
|
/* program stops */
|
|
if(strstr(input, " shutting down..."))
|
|
add_archived_state(AS_PROGRAM_END, time_stamp);
|
|
if(strstr(input, "Bailing out"))
|
|
add_archived_state(AS_PROGRAM_END, time_stamp);
|
|
|
|
if(display_type == DISPLAY_HOST_HISTOGRAM) {
|
|
if(strstr(input, "HOST ALERT:")) {
|
|
|
|
/* get host name */
|
|
temp_buffer = my_strtok(NULL, ":");
|
|
temp_buffer = my_strtok(NULL, ";");
|
|
strncpy(entry_host_name, (temp_buffer == NULL) ? "" : temp_buffer + 1, sizeof(entry_host_name));
|
|
entry_host_name[sizeof(entry_host_name) - 1] = '\x0';
|
|
|
|
if(strcmp(host_name, entry_host_name))
|
|
continue;
|
|
|
|
/* skip soft states if necessary */
|
|
if(!(graph_statetypes & GRAPH_SOFT_STATETYPES) && strstr(input, ";SOFT;"))
|
|
continue;
|
|
|
|
/* skip hard states if necessary */
|
|
if(!(graph_statetypes & GRAPH_HARD_STATETYPES) && strstr(input, ";HARD;"))
|
|
continue;
|
|
|
|
if(strstr(input, ";DOWN;"))
|
|
add_archived_state(AS_HOST_DOWN, time_stamp);
|
|
else if(strstr(input, ";UNREACHABLE;"))
|
|
add_archived_state(AS_HOST_UNREACHABLE, time_stamp);
|
|
else if(strstr(input, ";RECOVERY") || strstr(input, ";UP;"))
|
|
add_archived_state(AS_HOST_UP, time_stamp);
|
|
}
|
|
}
|
|
if(display_type == DISPLAY_SERVICE_HISTOGRAM) {
|
|
if(strstr(input, "SERVICE ALERT:")) {
|
|
|
|
/* get host name */
|
|
temp_buffer = my_strtok(NULL, ":");
|
|
temp_buffer = my_strtok(NULL, ";");
|
|
strncpy(entry_host_name, (temp_buffer == NULL) ? "" : temp_buffer + 1, sizeof(entry_host_name));
|
|
entry_host_name[sizeof(entry_host_name) - 1] = '\x0';
|
|
|
|
if(strcmp(host_name, entry_host_name))
|
|
continue;
|
|
|
|
/* get service description */
|
|
temp_buffer = my_strtok(NULL, ";");
|
|
strncpy(entry_svc_description, (temp_buffer == NULL) ? "" : temp_buffer, sizeof(entry_svc_description));
|
|
entry_svc_description[sizeof(entry_svc_description) - 1] = '\x0';
|
|
|
|
if(strcmp(svc_description, entry_svc_description))
|
|
continue;
|
|
|
|
/* skip soft states if necessary */
|
|
if(!(graph_statetypes & GRAPH_SOFT_STATETYPES) && strstr(input, ";SOFT;"))
|
|
continue;
|
|
|
|
/* skip hard states if necessary */
|
|
if(!(graph_statetypes & GRAPH_HARD_STATETYPES) && strstr(input, ";HARD;"))
|
|
continue;
|
|
|
|
if(strstr(input, ";CRITICAL;"))
|
|
add_archived_state(AS_SVC_CRITICAL, time_stamp);
|
|
else if(strstr(input, ";WARNING;"))
|
|
add_archived_state(AS_SVC_WARNING, time_stamp);
|
|
else if(strstr(input, ";UNKNOWN;"))
|
|
add_archived_state(AS_SVC_UNKNOWN, time_stamp);
|
|
else if(strstr(input, ";RECOVERY;") || strstr(input, ";OK;"))
|
|
add_archived_state(AS_SVC_OK, time_stamp);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
/* free memory and close the file */
|
|
free(input);
|
|
free(input2);
|
|
mmap_fclose(thefile);
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
|
|
void convert_timeperiod_to_times(int type) {
|
|
time_t current_time;
|
|
struct tm *t;
|
|
|
|
/* get the current time */
|
|
time(¤t_time);
|
|
|
|
t = localtime(¤t_time);
|
|
|
|
t->tm_sec = 0;
|
|
t->tm_min = 0;
|
|
t->tm_hour = 0;
|
|
t->tm_isdst = -1;
|
|
|
|
switch(type) {
|
|
case TIMEPERIOD_LAST24HOURS:
|
|
t1 = current_time - (60 * 60 * 24);
|
|
t2 = current_time;
|
|
break;
|
|
case TIMEPERIOD_TODAY:
|
|
t1 = mktime(t);
|
|
t2 = current_time;
|
|
break;
|
|
case TIMEPERIOD_YESTERDAY:
|
|
t1 = (time_t)(mktime(t) - (60 * 60 * 24));
|
|
t2 = (time_t)mktime(t);
|
|
break;
|
|
case TIMEPERIOD_THISWEEK:
|
|
t1 = (time_t)(mktime(t) - (60 * 60 * 24 * t->tm_wday));
|
|
t2 = current_time;
|
|
break;
|
|
case TIMEPERIOD_LASTWEEK:
|
|
t1 = (time_t)(mktime(t) - (60 * 60 * 24 * t->tm_wday) - (60 * 60 * 24 * 7));
|
|
t2 = (time_t)(mktime(t) - (60 * 60 * 24 * t->tm_wday));
|
|
break;
|
|
case TIMEPERIOD_THISMONTH:
|
|
t->tm_mday = 1;
|
|
t1 = mktime(t);
|
|
t2 = current_time;
|
|
break;
|
|
case TIMEPERIOD_LASTMONTH:
|
|
t->tm_mday = 1;
|
|
t2 = mktime(t);
|
|
if(t->tm_mon == 0) {
|
|
t->tm_mon = 11;
|
|
t->tm_year--;
|
|
}
|
|
else
|
|
t->tm_mon--;
|
|
t1 = mktime(t);
|
|
break;
|
|
case TIMEPERIOD_THISQUARTER:
|
|
break;
|
|
case TIMEPERIOD_LASTQUARTER:
|
|
break;
|
|
case TIMEPERIOD_THISYEAR:
|
|
t->tm_mon = 0;
|
|
t->tm_mday = 1;
|
|
t1 = mktime(t);
|
|
t2 = current_time;
|
|
break;
|
|
case TIMEPERIOD_LASTYEAR:
|
|
t->tm_mon = 0;
|
|
t->tm_mday = 1;
|
|
t2 = mktime(t);
|
|
t->tm_year--;
|
|
t1 = mktime(t);
|
|
break;
|
|
case TIMEPERIOD_LAST7DAYS:
|
|
t2 = current_time;
|
|
t1 = current_time - (7 * 24 * 60 * 60);
|
|
break;
|
|
case TIMEPERIOD_LAST31DAYS:
|
|
t2 = current_time;
|
|
t1 = current_time - (31 * 24 * 60 * 60);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
void compute_report_times(void) {
|
|
time_t current_time;
|
|
struct tm *st;
|
|
struct tm *et;
|
|
|
|
/* get the current time */
|
|
time(¤t_time);
|
|
|
|
st = localtime(¤t_time);
|
|
|
|
st->tm_sec = start_second;
|
|
st->tm_min = start_minute;
|
|
st->tm_hour = start_hour;
|
|
st->tm_mday = start_day;
|
|
st->tm_mon = start_month - 1;
|
|
st->tm_year = start_year - 1900;
|
|
st->tm_isdst = -1;
|
|
|
|
t1 = mktime(st);
|
|
|
|
et = localtime(¤t_time);
|
|
|
|
et->tm_sec = end_second;
|
|
et->tm_min = end_minute;
|
|
et->tm_hour = end_hour;
|
|
et->tm_mday = end_day;
|
|
et->tm_mon = end_month - 1;
|
|
et->tm_year = end_year - 1900;
|
|
et->tm_isdst = -1;
|
|
|
|
t2 = mktime(et);
|
|
}
|
|
|
|
|
|
|
|
/* draws a solid line */
|
|
void draw_line(int x1, int y1, int x2, int y2, int color) {
|
|
int styleSolid[1];
|
|
|
|
styleSolid[0] = color;
|
|
|
|
/* sets current style to a solid line */
|
|
gdImageSetStyle(histogram_image, styleSolid, 1);
|
|
|
|
/* draws a line (dashed) */
|
|
gdImageLine(histogram_image, x1, y1, x2, y2, gdStyled);
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
/* draws a dashed line */
|
|
void draw_dashed_line(int x1, int y1, int x2, int y2, int color) {
|
|
int styleDashed[6];
|
|
|
|
styleDashed[0] = color;
|
|
styleDashed[1] = color;
|
|
styleDashed[2] = gdTransparent;
|
|
styleDashed[3] = gdTransparent;
|
|
styleDashed[4] = gdTransparent;
|
|
styleDashed[5] = gdTransparent;
|
|
|
|
/* sets current style to a solid line */
|
|
gdImageSetStyle(histogram_image, styleDashed, 6);
|
|
|
|
/* draws a line (dashed) */
|
|
gdImageLine(histogram_image, x1, y1, x2, y2, gdStyled);
|
|
|
|
return;
|
|
}
|