void do_eventlog(FILE *output, int maxcount, int maxminutes, char *fromtime, char *totime, char *pageregex, char *expageregex, char *hostregex, char *exhostregex, char *testregex, char *extestregex, char *colrregex, int ignoredialups, f_hostcheck hostcheck, event_t **eventlist, countlist_t **hostcounts, countlist_t **servicecounts, countsummary_t counttype, eventsummary_t sumtype, char *periodstring) { FILE *eventlog; char eventlogfilename[PATH_MAX]; time_t firstevent = 0; time_t lastevent = getcurrenttime(NULL); event_t *eventhead = NULL; struct stat st; char l[MAX_LINE_LEN]; char title[200]; /* For the PCRE matching */ const char *errmsg = NULL; int errofs = 0; pcre *pageregexp = NULL; pcre *expageregexp = NULL; pcre *hostregexp = NULL; pcre *exhostregexp = NULL; pcre *testregexp = NULL; pcre *extestregexp = NULL; pcre *colrregexp = NULL; countlist_t *hostcounthead = NULL, *svccounthead = NULL; if (eventlist) *eventlist = NULL; if (hostcounts) *hostcounts = NULL; if (servicecounts) *servicecounts = NULL; havedoneeventlog = 1; if ((maxminutes > 0) && (fromtime || totime)) { fprintf(output, "<B>Only one time interval type is allowed!</B>"); return; } if (fromtime) { firstevent = eventreport_time(fromtime); if(firstevent < 0) { if (output) fprintf(output,"<B>Invalid 'from' time: %s</B>", htmlquoted(fromtime)); return; } } else if (maxminutes == -1) { /* Unlimited number of minutes */ firstevent = 0; } else if (maxminutes > 0) { firstevent = getcurrenttime(NULL) - maxminutes*60; } else { firstevent = getcurrenttime(NULL) - 86400; } if (totime) { lastevent = eventreport_time(totime); if (lastevent < 0) { if (output) fprintf(output,"<B>Invalid 'to' time: %s</B>", htmlquoted(totime)); return; } if (lastevent < firstevent) { if (output) fprintf(output,"<B>'to' time must be after 'from' time.</B>"); return; } } if (!maxcount) maxcount = 100; if (pageregex && *pageregex) pageregexp = pcre_compile(pageregex, PCRE_CASELESS, &errmsg, &errofs, NULL); if (expageregex && *expageregex) expageregexp = pcre_compile(expageregex, PCRE_CASELESS, &errmsg, &errofs, NULL); if (hostregex && *hostregex) hostregexp = pcre_compile(hostregex, PCRE_CASELESS, &errmsg, &errofs, NULL); if (exhostregex && *exhostregex) exhostregexp = pcre_compile(exhostregex, PCRE_CASELESS, &errmsg, &errofs, NULL); if (testregex && *testregex) testregexp = pcre_compile(testregex, PCRE_CASELESS, &errmsg, &errofs, NULL); if (extestregex && *extestregex) extestregexp = pcre_compile(extestregex, PCRE_CASELESS, &errmsg, &errofs, NULL); if (colrregex && *colrregex) colrregexp = pcre_compile(colrregex, PCRE_CASELESS, &errmsg, &errofs, NULL); sprintf(eventlogfilename, "%s/allevents", xgetenv("XYMONHISTDIR")); eventlog = fopen(eventlogfilename, "r"); if (eventlog && (stat(eventlogfilename, &st) == 0)) { time_t curtime; int done = 0; int unlimited = (maxcount == -1); if (unlimited) maxcount = 1000; do { /* Find a spot in the eventlog file close to where the firstevent time is */ fseeko(eventlog, 0, SEEK_END); do { /* Go back maxcount*80 bytes - one entry is ~80 bytes */ if (ftello(eventlog) > maxcount*80) { unsigned int uicurtime; fseeko(eventlog, -maxcount*80, SEEK_CUR); if (fgets(l, sizeof(l), eventlog) && /* Skip to start of line */ fgets(l, sizeof(l), eventlog)) { sscanf(l, "%*s %*s %u %*u %*u %*s %*s %*d", &uicurtime); curtime = uicurtime; done = (curtime < firstevent); if (unlimited && !done) maxcount += 1000; } else { if (output) fprintf(output,"Error reading eventlog file %s: %s\n", eventlogfilename, strerror(errno)); return; } } else { rewind(eventlog); curtime = 0; done = 1; } } while (!done); if (unlimited) unlimited = ((curtime > firstevent) && (ftello(eventlog) > 0)); } while (unlimited); } eventhead = NULL; while (eventlog && (fgets(l, sizeof(l), eventlog))) { time_t eventtime, changetime, duration; unsigned int uievt, uicht, uidur; char hostname[MAX_LINE_LEN], svcname[MAX_LINE_LEN], newcol[MAX_LINE_LEN], oldcol[MAX_LINE_LEN]; char *newcolname, *oldcolname; int state, itemsfound, colrmatch; event_t *newevent; void *eventhost; struct htnames_t *eventcolumn; int ovector[30]; eventcount_t *countrec; itemsfound = sscanf(l, "%s %s %u %u %u %s %s %d", hostname, svcname, &uievt, &uicht, &uidur, newcol, oldcol, &state); eventtime = uievt; changetime = uicht; duration = uidur; oldcolname = colorname(eventcolor(oldcol)); newcolname = colorname(eventcolor(newcol)); /* For DURATION counts, we must parse all events until now */ if ((counttype != XYMON_COUNT_DURATION) && (eventtime > lastevent)) break; eventhost = hostinfo(hostname); eventcolumn = getname(svcname, 1); if ( (itemsfound == 8) && (eventtime >= firstevent) && (eventhost && !xmh_item(eventhost, XMH_FLAG_NONONGREEN)) && (wanted_eventcolumn(svcname)) ) { if (eventfilter(eventhost, svcname, pageregexp, expageregexp, hostregexp, exhostregexp, testregexp, extestregexp, ignoredialups, hostcheck) == 0) continue; /* For duration counts, record all events. We'll filter out the colors later. */ if (colrregexp && (counttype != XYMON_COUNT_DURATION)) { colrmatch = ( (pcre_exec(colrregexp, NULL, newcolname, strlen(newcolname), 0, 0, ovector, (sizeof(ovector)/sizeof(int))) >= 0) || (pcre_exec(colrregexp, NULL, oldcolname, strlen(oldcolname), 0, 0, ovector, (sizeof(ovector)/sizeof(int))) >= 0) ); } else colrmatch = 1; if (!colrmatch) continue; newevent = (event_t *) malloc(sizeof(event_t)); newevent->host = eventhost; newevent->service = eventcolumn; newevent->eventtime = eventtime; newevent->changetime = changetime; newevent->duration = duration; newevent->newcolor = eventcolor(newcol); newevent->oldcolor = eventcolor(oldcol); newevent->next = eventhead; eventhead = newevent; if (counttype != XYMON_COUNT_DURATION) { countrec = (eventcount_t *)xmh_item(eventhost, XMH_DATA); while (countrec && (countrec->service != eventcolumn)) countrec = countrec->next; if (countrec == NULL) { countrec = (eventcount_t *)calloc(1, sizeof(eventcount_t)); countrec->service = eventcolumn; countrec->next = (eventcount_t *)xmh_item(eventhost, XMH_DATA); xmh_set_item(eventhost, XMH_DATA, (void *)countrec); } countrec->count++; } } } /* Count the state changes per host */ svccounthead = hostcounthead = NULL; switch (counttype) { case XYMON_COUNT_EVENTS: count_events(&hostcounthead, &svccounthead); break; case XYMON_COUNT_DURATION: count_duration(firstevent, lastevent, pageregexp, expageregexp, hostregexp, exhostregexp, testregexp, extestregexp, ignoredialups, hostcheck, eventhead, &hostcounthead, &svccounthead); break; default: break; } if (hostcounthead) hostcounthead = msort(hostcounthead, record_compare, record_getnext, record_setnext); if (svccounthead) svccounthead = msort(svccounthead, record_compare, record_getnext, record_setnext); if (eventhead && (output != NULL)) { char *bgcolors[2] = { "#000000", "#000033" }; int bgcolor = 0; struct event_t *ewalk, *lasttoshow = eventhead; countlist_t *cwalk; unsigned long totalcount = 0; if (periodstring) fprintf(output, "<p><font size=+1>%s</font></p>\n", htmlquoted(periodstring)); switch (sumtype) { case XYMON_S_HOST_BREAKDOWN: /* Request for a specific service, show breakdown by host */ for (cwalk = hostcounthead; (cwalk); cwalk = cwalk->next) totalcount += cwalk->total; fprintf(output, "<table summary=\"Breakdown by host\" border=0>\n"); fprintf(output, "<tr><th align=left>Host</th><th colspan=2>%s</th></tr>\n", (counttype == XYMON_COUNT_EVENTS) ? "State changes" : "Seconds red/yellow"); fprintf(output, "<tr><td colspan=3><hr width=\"100%%\"></td></tr>\n"); for (cwalk = hostcounthead; (cwalk && (cwalk->total > 0)); cwalk = cwalk->next) { fprintf(output, "<tr><td align=left>%s</td><td align=right>%lu</td><td align=right>(%6.2f %%)</tr>\n", xmh_item(cwalk->src, XMH_HOSTNAME), cwalk->total, ((100.0 * cwalk->total) / totalcount)); } fprintf(output, "</table>\n"); break; case XYMON_S_SERVICE_BREAKDOWN: /* Request for a specific host, show breakdown by service */ for (cwalk = svccounthead; (cwalk); cwalk = cwalk->next) totalcount += cwalk->total; fprintf(output, "<table summary=\"Breakdown by service\" border=0>\n"); fprintf(output, "<tr><th align=left>Service</th><th colspan=2>%s</th></tr>\n", (counttype == XYMON_COUNT_EVENTS) ? "State changes" : "Seconds red/yellow"); fprintf(output, "<tr><td colspan=3><hr width=\"100%%\"></td></tr>\n"); for (cwalk = svccounthead; (cwalk && (cwalk->total > 0)); cwalk = cwalk->next) { fprintf(output, "<tr><td align=left>%s</td><td align=right>%lu</td><td align=right>(%6.2f %%)</tr>\n", ((htnames_t *)cwalk->src)->name, cwalk->total, ((100.0 * cwalk->total) / totalcount)); } fprintf(output, "</table>\n"); break; case XYMON_S_NONE: break; } if (sumtype == XYMON_S_NONE) { int count; count=0; ewalk=eventhead; do { count++; lasttoshow = ewalk; ewalk = ewalk->next; } while (ewalk && (count<maxcount)); if (ewalk) ewalk->next = NULL; /* Terminate list if any items left */ if (maxminutes > 0) { sprintf(title, "%d events received in the past %u minutes", count, (unsigned int)((getcurrenttime(NULL) - lasttoshow->eventtime) / 60)); } else { sprintf(title, "%d events received.", count); } } else { strcpy(title, "Events in summary"); } fprintf(output, "<BR><BR>\n"); fprintf(output, "<TABLE SUMMARY=\"$EVENTSTITLE\" BORDER=0>\n"); fprintf(output, "<TR BGCOLOR=\"#333333\">\n"); fprintf(output, "<TD ALIGN=CENTER COLSPAN=6><FONT SIZE=-1 COLOR=\"#33ebf4\">%s</FONT></TD></TR>\n", htmlquoted(title)); for (ewalk=eventhead; (ewalk); ewalk=ewalk->next) { char *hostname = xmh_item(ewalk->host, XMH_HOSTNAME); if ( (counttype == XYMON_COUNT_DURATION) && (ewalk->oldcolor < COL_YELLOW) && (ewalk->newcolor < COL_YELLOW) ) continue; if ( (counttype == XYMON_COUNT_DURATION) && (ewalk->eventtime >= lastevent) ) continue; fprintf(output, "<TR BGCOLOR=%s>\n", bgcolors[bgcolor]); bgcolor = ((bgcolor + 1) % 2); fprintf(output, "<TD ALIGN=CENTER>%s</TD>\n", ctime(&ewalk->eventtime)); if (ewalk->newcolor == COL_CLEAR) { fprintf(output, "<TD ALIGN=CENTER BGCOLOR=black><FONT COLOR=white>%s</FONT></TD>\n", hostname); } else { fprintf(output, "<TD ALIGN=CENTER BGCOLOR=%s><FONT COLOR=black>%s</FONT></TD>\n", colorname(ewalk->newcolor), hostname); } fprintf(output, "<TD ALIGN=LEFT>%s</TD>\n", ewalk->service->name); fprintf(output, "<TD><A HREF=\"%s\">\n", histlogurl(hostname, ewalk->service->name, ewalk->changetime, NULL)); fprintf(output, "<IMG SRC=\"%s/%s\" HEIGHT=\"%s\" WIDTH=\"%s\" BORDER=0 ALT=\"%s\" TITLE=\"%s\"></A>\n", xgetenv("XYMONSKIN"), dotgiffilename(ewalk->oldcolor, 0, 0), xgetenv("DOTHEIGHT"), xgetenv("DOTWIDTH"), colorname(ewalk->oldcolor), colorname(ewalk->oldcolor)); fprintf(output, "<IMG SRC=\"%s/arrow.gif\" BORDER=0 ALT=\"From -> To\">\n", xgetenv("XYMONSKIN")); fprintf(output, "<TD><A HREF=\"%s\">\n", histlogurl(hostname, ewalk->service->name, ewalk->eventtime, NULL)); fprintf(output, "<IMG SRC=\"%s/%s\" HEIGHT=\"%s\" WIDTH=\"%s\" BORDER=0 ALT=\"%s\" TITLE=\"%s\"></A></TD>\n", xgetenv("XYMONSKIN"), dotgiffilename(ewalk->newcolor, 0, 0), xgetenv("DOTHEIGHT"), xgetenv("DOTWIDTH"), colorname(ewalk->newcolor), colorname(ewalk->newcolor)); fprintf(output, "</TR>\n"); } fprintf(output, "</TABLE>\n"); } else if (output != NULL) { /* No events during the past maxminutes */ if (eventlog) sprintf(title, "No events received in the last %d minutes", maxminutes); else strcpy(title, "No events logged"); fprintf(output, "<CENTER><BR>\n"); fprintf(output, "<TABLE SUMMARY=\"%s\" BORDER=0>\n", title); fprintf(output, "<TR BGCOLOR=\"#333333\">\n"); fprintf(output, "<TD ALIGN=CENTER COLSPAN=6><FONT SIZE=-1 COLOR=\"#33ebf4\">%s</FONT></TD>\n", htmlquoted(title)); fprintf(output, "</TR>\n"); fprintf(output, "</TABLE>\n"); fprintf(output, "</CENTER>\n"); } if (eventlog) fclose(eventlog); if (pageregexp) pcre_free(pageregexp); if (hostregexp) pcre_free(hostregexp); if (testregexp) pcre_free(testregexp); if (colrregexp) pcre_free(colrregexp); /* Return the event- and count-lists, if wanted - or clean them up */ if (eventlist) { *eventlist = eventhead; } else { event_t *zombie, *ewalk = eventhead; while (ewalk) { zombie = ewalk; ewalk = ewalk->next; xfree(zombie); } } if (hostcounts) { *hostcounts = hostcounthead; } else { countlist_t *zombie, *hwalk = hostcounthead; while (hwalk) { zombie = hwalk; hwalk = hwalk->next; xfree(zombie); } } if (servicecounts) { *servicecounts = svccounthead; } else { countlist_t *zombie, *swalk = svccounthead; while (swalk) { zombie = swalk; swalk = swalk->next; xfree(zombie); } } }
int main(int argc, char *argv[]) { int argi; char *envarea = NULL; for (argi=1; (argi < argc); argi++) { if (argnmatch(argv[argi], "--env=")) { char *p = strchr(argv[argi], '='); loadenv(p+1, envarea); } else if (argnmatch(argv[argi], "--area=")) { char *p = strchr(argv[argi], '='); envarea = strdup(p+1); } else if (argnmatch(argv[argi], "--top")) { topcount = 10; webfile_hf = "topchanges"; webfile_form = "topchanges_form"; maxminutes = -1; maxcount = -1; } else if (strcmp(argv[argi], "--debug=")) { debug = 1; } } redirect_cgilog("eventlog"); load_hostnames(xgetenv("HOSTSCFG"), NULL, get_fqdn()); fprintf(stdout, "Content-type: %s\n\n", xgetenv("HTMLCONTENTTYPE")); cgidata = cgi_request(); if (cgidata == NULL) { /* Present the query form */ sethostenv("", "", "", colorname(COL_BLUE), NULL); showform(stdout, webfile_hf, webfile_form, COL_BLUE, getcurrenttime(NULL), NULL, NULL); return 0; } *periodstring = '\0'; parse_query(); if ((*periodstring == '\0') && (fromtime || totime)) { if (fromtime && totime) sprintf(periodstring, "Events between %s - %s", fromtime, totime); else if (fromtime) sprintf(periodstring, "Events since %s", fromtime); else if (totime) sprintf(periodstring, "Events until %s", totime); } /* Now generate the webpage */ headfoot(stdout, webfile_hf, "", "header", COL_GREEN); fprintf(stdout, "<center>\n"); if (topcount == 0) { do_eventlog(stdout, maxcount, maxminutes, fromtime, totime, pageregex, expageregex, hostregex, exhostregex, testregex, extestregex, colorregex, ignoredialups, NULL, NULL, NULL, NULL, counttype, summarybar, periodstring); } else { countlist_t *hcounts, *scounts; event_t *events; time_t firstevent, lastevent; do_eventlog(NULL, -1, -1, fromtime, totime, pageregex, expageregex, hostregex, exhostregex, testregex, extestregex, colorregex, ignoredialups, NULL, &events, &hcounts, &scounts, counttype, XYMON_S_NONE, NULL); lastevent = (totime ? eventreport_time(totime) : getcurrenttime(NULL)); if (fromtime) { firstevent = eventreport_time(fromtime); } else if (events) { event_t *ewalk; ewalk = events; while (ewalk->next) ewalk = ewalk->next; firstevent = ewalk->eventtime; } else firstevent = 0; show_topchanges(stdout, hcounts, scounts, events, topcount, firstevent, lastevent); } fprintf(stdout, "</center>\n"); headfoot(stdout, webfile_hf, "", "footer", COL_GREEN); return 0; }