Icinga-core 1.4.0
next gen monitoring
cgi/readlogs.c
Go to the documentation of this file.
00001 /***********************************************************************
00002  *
00003  * READLOGS.C - Functions for reading Log files in Icinga CGIs
00004  *
00005  * Copyright (c) 1999-2009 Ethan Galstad (egalstad@nagios.org)
00006  * Copyright (c) 2009-2011 Icinga Development Team (http://www.icinga.org)
00007  *
00008  * License:
00009  *
00010  * This program is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License version 2 as
00012  * published by the Free Software Foundation.
00013  *
00014  * This program is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017  * GNU General Public License for more details.
00018  *
00019  * You should have received a copy of the GNU General Public License
00020  * along with this program; if not, write to the Free Software
00021  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00022  ***********************************************************************/
00023 
00029 #include "../include/cgiutils.h"
00030 #include "../include/readlogs.h"
00031 
00032 
00035 logfilter       *filter_list=NULL;                      
00036 logentry        *entry_list=NULL;                       
00037 logentry        *last_entry=NULL;                       
00043 extern int      log_rotation_method;                    
00045 extern char     log_file[MAX_FILENAME_LENGTH];          
00046 extern char     log_archive_path[MAX_FILENAME_LENGTH];  
00051 time_t          this_scheduled_log_rotation=0L;         
00052 time_t          last_scheduled_log_rotation=0L;         
00053 time_t          next_scheduled_log_rotation=0L;         
00083 int add_log_filter(int requested_filter, int include_exclude) {
00084         logfilter *temp_filter=NULL;
00085 
00086         temp_filter=(logfilter *)malloc(sizeof(logfilter));
00087         if(temp_filter==NULL)
00088                 return READLOG_ERROR_MEMORY;
00089 
00090         /* initialize filter */
00091         temp_filter->next=NULL;
00092         temp_filter->include=0;
00093         temp_filter->exclude=0;
00094 
00095         if (include_exclude==LOGFILTER_INCLUDE)
00096                 temp_filter->include=requested_filter;
00097         else if (include_exclude==LOGFILTER_EXCLUDE)
00098                 temp_filter->exclude=requested_filter;
00099         else {
00100                 my_free(temp_filter);
00101                 return READLOG_ERROR;
00102         }
00103 
00104         if (filter_list==NULL)
00105                 filter_list=temp_filter;
00106         else{
00107                 temp_filter->next=filter_list;
00108                 filter_list=temp_filter;
00109         }
00110 
00111         return READLOG_OK;
00112 }
00113 
00114 
00142 int get_log_entries(char *log_file, char *search_string, int reverse,time_t ts_start, time_t ts_end) {
00143         char *input=NULL;
00144         char *temp_buffer=NULL;
00145         char *search_regex=NULL;
00146         int type=0;
00147         int regex_i=0, i=0, len=0;
00148         short keep_entry=TRUE;
00149         time_t timestamp;
00150         mmapfile *thefile=NULL;
00151         logentry *temp_entry=NULL;
00152         regex_t preg;
00153         logfilter *temp_filter;
00154 
00155         if((thefile=mmap_fopen(log_file))!=NULL){
00156 
00157                 if(search_string!=NULL){
00158                         /* allocate for 3 extra chars, ^, $ and \0 */
00159                         search_regex = malloc(sizeof(char) * (strlen(search_string) * 2 + 3));
00160                         len=strlen(search_string);
00161                         for (i=0;i<len;i++,regex_i++) {
00162                                 if(search_string[i]=='*') {
00163                                         search_regex[regex_i++]='.';
00164                                         search_regex[regex_i]='*';
00165                                 }else
00166                                         search_regex[regex_i]=search_string[i];
00167                         }
00168                         //search_regex[0]='^';
00169                         //search_regex[regex_i++]='$';
00170 
00171                         search_regex[regex_i]='\0';
00172 
00173                         /* check and compile regex */
00174                         if (regcomp(&preg,search_regex,REG_ICASE|REG_NOSUB) != 0 ) {
00175                                 regfree(&preg);
00176                                 mmap_fclose(thefile);
00177                                 return READLOG_ERROR_FILTER;
00178                         }
00179                 }
00180 
00181                 while(1){
00182 
00183                         /* free memory */
00184                         my_free(input);
00185 
00186                         if((input=mmap_fgets(thefile))==NULL)
00187                                 break;
00188 
00189                         strip(input);
00190 
00191                         if ((int)strlen(input)==0)
00192                                 continue;
00193 
00194                         /* get timestamp */
00195                         temp_buffer=strtok(input,"]");
00196                         timestamp=(temp_buffer==NULL)?0L:strtoul(temp_buffer+1,NULL,10);
00197 
00198                         /* skip line if out of time range */
00199                         if ((ts_start>=0 && timestamp<ts_start) || (ts_end>=0 && timestamp>ts_end))
00200                                 continue;
00201 
00202                         /* get log entry text */
00203                         temp_buffer=strtok(NULL,"\n");
00204 
00205                         if(search_string!=NULL){
00206                                 if (regexec(&preg,temp_buffer,0,NULL,0)==REG_NOMATCH)
00207                                         continue;
00208                         }
00209 
00210 
00211                         if(strstr(temp_buffer," starting..."))
00212                                 type=LOGENTRY_STARTUP;
00213                         else if(strstr(temp_buffer," shutting down..."))
00214                                 type=LOGENTRY_SHUTDOWN;
00215                         else if(strstr(temp_buffer,"Bailing out"))
00216                                 type=LOGENTRY_BAILOUT;
00217                         else if(strstr(temp_buffer," restarting..."))
00218                                 type=LOGENTRY_RESTART;
00219                         else if(strstr(temp_buffer,"HOST ALERT:") && strstr(temp_buffer,";DOWN;"))
00220                                 type=LOGENTRY_HOST_DOWN;
00221                         else if(strstr(temp_buffer,"HOST ALERT:") && strstr(temp_buffer,";UNREACHABLE;"))
00222                                 type=LOGENTRY_HOST_UNREACHABLE;
00223                         else if(strstr(temp_buffer,"HOST ALERT:") && strstr(temp_buffer,";RECOVERY;"))
00224                                 type=LOGENTRY_HOST_RECOVERY;
00225                         else if(strstr(temp_buffer,"HOST ALERT:") && strstr(temp_buffer,";UP;"))
00226                                 type=LOGENTRY_HOST_UP;
00227                         else if(strstr(temp_buffer,"HOST NOTIFICATION:"))
00228                                 type=LOGENTRY_HOST_NOTIFICATION;
00229                         else if(strstr(temp_buffer,"SERVICE ALERT:") && strstr(temp_buffer,";CRITICAL;"))
00230                                 type=LOGENTRY_SERVICE_CRITICAL;
00231                         else if(strstr(temp_buffer,"SERVICE ALERT:") && strstr(temp_buffer,";WARNING;"))
00232                                 type=LOGENTRY_SERVICE_WARNING;
00233                         else if(strstr(temp_buffer,"SERVICE ALERT:") && strstr(temp_buffer,";UNKNOWN;"))
00234                                 type=LOGENTRY_SERVICE_UNKNOWN;
00235                         else if(strstr(temp_buffer,"SERVICE ALERT:") && strstr(temp_buffer,";RECOVERY;"))
00236                                 type=LOGENTRY_SERVICE_RECOVERY;
00237                         else if(strstr(temp_buffer,"SERVICE ALERT:") && strstr(temp_buffer,";OK;"))
00238                                 type=LOGENTRY_SERVICE_OK;
00239                         else if(strstr(temp_buffer,"SERVICE NOTIFICATION:"))
00240                                 type=LOGENTRY_SERVICE_NOTIFICATION;
00241                         else if(strstr(temp_buffer,"SERVICE EVENT HANDLER:"))
00242                                 type=LOGENTRY_SERVICE_EVENT_HANDLER;
00243                         else if(strstr(temp_buffer,"HOST EVENT HANDLER:"))
00244                                 type=LOGENTRY_HOST_EVENT_HANDLER;
00245                         else if(strstr(temp_buffer,"EXTERNAL COMMAND:"))
00246                                 type=LOGENTRY_EXTERNAL_COMMAND;
00247                         else if(strstr(temp_buffer,"PASSIVE SERVICE CHECK:"))
00248                                 type=LOGENTRY_PASSIVE_SERVICE_CHECK;
00249                         else if(strstr(temp_buffer,"PASSIVE HOST CHECK:"))
00250                                 type=LOGENTRY_PASSIVE_HOST_CHECK;
00251                         else if(strstr(temp_buffer,"LOG ROTATION:"))
00252                                 type=LOGENTRY_LOG_ROTATION;
00253                         else if(strstr(temp_buffer,"active mode..."))
00254                                 type=LOGENTRY_ACTIVE_MODE;
00255                         else if(strstr(temp_buffer,"standby mode..."))
00256                                 type=LOGENTRY_STANDBY_MODE;
00257                         else if(strstr(temp_buffer,"SERVICE FLAPPING ALERT:") && strstr(temp_buffer,";STARTED;"))
00258                                 type=LOGENTRY_SERVICE_FLAPPING_STARTED;
00259                         else if(strstr(temp_buffer,"SERVICE FLAPPING ALERT:") && strstr(temp_buffer,";STOPPED;"))
00260                                 type=LOGENTRY_SERVICE_FLAPPING_STOPPED;
00261                         else if(strstr(temp_buffer,"SERVICE FLAPPING ALERT:") && strstr(temp_buffer,";DISABLED;"))
00262                                 type=LOGENTRY_SERVICE_FLAPPING_DISABLED;
00263                         else if(strstr(temp_buffer,"HOST FLAPPING ALERT:") && strstr(temp_buffer,";STARTED;"))
00264                                 type=LOGENTRY_HOST_FLAPPING_STARTED;
00265                         else if(strstr(temp_buffer,"HOST FLAPPING ALERT:") && strstr(temp_buffer,";STOPPED;"))
00266                                 type=LOGENTRY_HOST_FLAPPING_STOPPED;
00267                         else if(strstr(temp_buffer,"HOST FLAPPING ALERT:") && strstr(temp_buffer,";DISABLED;"))
00268                                 type=LOGENTRY_HOST_FLAPPING_DISABLED;
00269                         else if(strstr(temp_buffer,"SERVICE DOWNTIME ALERT:") && strstr(temp_buffer,";STARTED;"))
00270                                 type=LOGENTRY_SERVICE_DOWNTIME_STARTED;
00271                         else if(strstr(temp_buffer,"SERVICE DOWNTIME ALERT:") && strstr(temp_buffer,";STOPPED;"))
00272                                 type=LOGENTRY_SERVICE_DOWNTIME_STOPPED;
00273                         else if(strstr(temp_buffer,"SERVICE DOWNTIME ALERT:") && strstr(temp_buffer,";CANCELLED;"))
00274                                 type=LOGENTRY_SERVICE_DOWNTIME_CANCELLED;
00275                         else if(strstr(temp_buffer,"HOST DOWNTIME ALERT:") && strstr(temp_buffer,";STARTED;"))
00276                                 type=LOGENTRY_HOST_DOWNTIME_STARTED;
00277                         else if(strstr(temp_buffer,"HOST DOWNTIME ALERT:") && strstr(temp_buffer,";STOPPED;"))
00278                                 type=LOGENTRY_HOST_DOWNTIME_STOPPED;
00279                         else if(strstr(temp_buffer,"HOST DOWNTIME ALERT:") && strstr(temp_buffer,";CANCELLED;"))
00280                                 type=LOGENTRY_HOST_DOWNTIME_CANCELLED;
00281                         else if (strstr(temp_buffer,"INITIAL SERVICE STATE:"))
00282                                 type=LOGENTRY_SERVICE_INITIAL_STATE;
00283                         else if (strstr(temp_buffer,"INITIAL HOST STATE:"))
00284                                 type=LOGENTRY_HOST_INITIAL_STATE;
00285                         else if (strstr(temp_buffer,"CURRENT SERVICE STATE:"))
00286                                 type=LOGENTRY_SERVICE_CURRENT_STATE;
00287                         else if (strstr(temp_buffer,"CURRENT HOST STATE:"))
00288                                 type=LOGENTRY_HOST_CURRENT_STATE;
00289                         else if(strstr(temp_buffer,"error executing command"))
00290                                 type=LOGENTRY_ERROR_COMMAND_EXECUTION;
00291                         else if(strstr(temp_buffer,"idomod:"))
00292                                 type=LOGENTRY_IDOMOD;
00293                         else if(strstr(temp_buffer,"npcdmod:"))
00294                                 type=LOGENTRY_NPCDMOD;
00295                         else if(strstr(temp_buffer,"Auto-save of"))
00296                                 type=LOGENTRY_AUTOSAVE;
00297                         else if(strstr(temp_buffer,"Warning:"))
00298                                 type=LOGENTRY_SYSTEM_WARNING;
00299                         else
00300                                 type=LOGENTRY_UNDEFINED;
00301 
00302                         /* apply filters */
00303                         if(filter_list!=NULL) {
00304                                 keep_entry=FALSE;
00305                                 for(temp_filter=filter_list;temp_filter!=NULL;temp_filter=temp_filter->next) {
00306                                         if(temp_filter->include!=0) {
00307                                                 if(temp_filter->include==type) {
00308                                                         keep_entry=TRUE;
00309                                                         break;
00310                                                 }
00311                                         }
00312                                         else if(temp_filter->exclude!=0) {
00313                                                 if(temp_filter->exclude==type) {
00314                                                         keep_entry=FALSE;
00315                                                         break;
00316                                                 } else
00317                                                         keep_entry=TRUE;
00318                                         }
00319                                 }
00320                                 if (keep_entry==FALSE)
00321                                         continue;
00322                         }
00323 
00324                         /* initialzie */
00325                         /* allocate memory for a new log entry */
00326                         temp_entry=(logentry *)malloc(sizeof(logentry));
00327                         if(temp_entry==NULL) {
00328                                 mmap_fclose(thefile);
00329                                 return READLOG_ERROR_MEMORY;
00330                         }
00331 
00332                         temp_entry->timestamp=0L;
00333                         temp_entry->type=0;
00334                         temp_entry->entry_text=NULL;
00335                         temp_entry->next=NULL;
00336 
00337 
00338                         temp_entry->timestamp=timestamp;
00339                         temp_entry->type=type;
00340                         temp_entry->entry_text=strdup(temp_buffer);
00341                         
00342                         if (reverse==TRUE) {
00343                                 if (entry_list==NULL){
00344                                         entry_list=temp_entry;
00345                                         last_entry=entry_list;
00346                                 } else {
00347                                         last_entry->next=temp_entry;
00348                                         last_entry=temp_entry;
00349                                 }
00350                         } else {
00351                                 temp_entry->next=entry_list;
00352                                 entry_list=temp_entry;
00353                         }
00354                 }
00355 
00356                 mmap_fclose(thefile);
00357 
00358                 if(search_string!=NULL)
00359                         regfree(&preg);
00360         } else
00361                 return READLOG_ERROR_NOFILE;
00362 
00363         return READLOG_OK;
00364 }
00365 
00369 void free_log_filters(void){
00370         logfilter *temp_filter=NULL;
00371         logfilter *next_filter=NULL;
00372 
00373         for(temp_filter=filter_list;temp_filter!=NULL;) {
00374                 next_filter=temp_filter->next;
00375                 my_free(temp_filter);
00376                 temp_filter=next_filter;
00377         }
00378 
00379         filter_list=NULL;
00380 
00381         return;
00382 }
00383 
00387 void free_log_entries(void){
00388         logentry *temp_entry;
00389         logentry *next_entry;
00390 
00391         for(temp_entry=entry_list;temp_entry!=NULL;) {
00392                 next_entry=temp_entry->next;
00393                 if(temp_entry->entry_text!=NULL)
00394                     my_free(temp_entry->entry_text);
00395                 my_free(temp_entry);
00396                 temp_entry=next_entry;
00397         }
00398 
00399         entry_list=NULL;
00400 
00401         return;
00402 }
00403 
00417 void get_log_archive_to_use(int archive,char *file_name,int file_name_length){
00418         struct tm *t;
00419         FILE *fd;
00420 
00421         /* determine the time at which the log was rotated for this archive # */
00422         determine_log_rotation_times(archive);
00423 
00424         /* if we're not rotating the logs or if we want the current log, use the main one... */
00425         if(log_rotation_method==LOG_ROTATION_NONE || archive<=0){
00426                 strncpy(file_name,log_file,file_name_length);
00427                 file_name[file_name_length-1]='\x0';
00428                 return;
00429         }
00430 
00431         t=localtime(&this_scheduled_log_rotation);
00432 
00433         /* use the time that the log rotation occurred to figure out the name of the log file */
00434         snprintf(file_name,file_name_length,"%sicinga-%02d-%02d-%d-%02d.log",log_archive_path, t->tm_mon+1, t->tm_mday, t->tm_year+1900, t->tm_hour);
00435         file_name[file_name_length-1]='\x0';
00436 
00437         /* check if a icinga named archive logfile already exist. Otherwise change back to nagios syntax */
00438         if((fd = fopen(file_name, "r")) == NULL){
00439                 snprintf(file_name,file_name_length,"%snagios-%02d-%02d-%d-%02d.log",log_archive_path,t->tm_mon+1,t->tm_mday,t->tm_year+1900,t->tm_hour);
00440                 file_name[file_name_length-1]='\x0';
00441 
00442                 /* 06-02-2010 Michael Friedrich
00443                    Yeah, and if no log has been written, nagios- will fail with the wrong error message
00444                    leading the user to the assumption that the logfile is not even created - if the logfile
00445                    was not rotated by the core after this date */
00446                 if((fd = fopen(file_name, "r")) == NULL){
00447                         snprintf(file_name,file_name_length,"%sicinga-%02d-%02d-%d-%02d.log",log_archive_path, t->tm_mon+1, t->tm_mday, t->tm_year+1900, t->tm_hour);
00448                         file_name[file_name_length-1]='\x0';
00449                 } else
00450                         fclose(fd);
00451         } else
00452                 fclose(fd);
00453 
00454         return;
00455 }
00456 
00457 
00471 int determine_archive_to_use_from_time(time_t target_time){
00472         time_t current_time;
00473         int current_archive=0;
00474 
00475         /* if log rotation is disabled, we don't have archives */
00476         if(log_rotation_method==LOG_ROTATION_NONE)
00477                 return 0;
00478 
00479         /* make sure target time is rational */
00480         current_time=time(NULL);
00481         if(target_time>=current_time)
00482                 return 0;
00483 
00484         /* backtrack through archives to find the one we need for this time */
00485         /* start with archive of 1, subtract one when we find the right time period to compensate for current (non-rotated) log */
00486         for(current_archive=1;;current_archive++){
00487 
00488                 /* determine time at which the log rotation occurred for this archive number */
00489                 determine_log_rotation_times(current_archive);
00490 
00491                 /* if the target time falls within the times encompassed by this archive, we have the right archive! */
00492                 if(target_time>=this_scheduled_log_rotation)
00493                         return current_archive-1;
00494         }
00495 
00496         return 0;
00497 }
00498 
00499 
00506 void determine_log_rotation_times(int archive){
00507         struct tm *t;
00508         int current_month;
00509         int is_dst_now=FALSE;
00510         time_t current_time;
00511 
00512         /* negative archive numbers don't make sense */
00513         /* if archive=0 (current log), this_scheduled_log_rotation time is set to next rotation time */
00514         if(archive<0)
00515                 return;
00516 
00517         time(&current_time);
00518         t=localtime(&current_time);
00519         is_dst_now=(t->tm_isdst>0)?TRUE:FALSE;
00520         t->tm_min=0;
00521         t->tm_sec=0;
00522 
00523         switch(log_rotation_method){
00524 
00525                 case LOG_ROTATION_HOURLY:
00526                         this_scheduled_log_rotation=mktime(t);
00527                         this_scheduled_log_rotation=(time_t)(this_scheduled_log_rotation-((archive-1)*3600));
00528                         last_scheduled_log_rotation=(time_t)(this_scheduled_log_rotation-3600);
00529                         break;
00530 
00531                 case LOG_ROTATION_DAILY:
00532                         t->tm_hour=0;
00533                         this_scheduled_log_rotation=mktime(t);
00534                         this_scheduled_log_rotation=(time_t)(this_scheduled_log_rotation-((archive-1)*86400));
00535                         last_scheduled_log_rotation=(time_t)(this_scheduled_log_rotation-86400);
00536                         break;
00537 
00538                 case LOG_ROTATION_WEEKLY:
00539                         t->tm_hour=0;
00540                         this_scheduled_log_rotation=mktime(t);
00541                         this_scheduled_log_rotation=(time_t)(this_scheduled_log_rotation-(86400*t->tm_wday));
00542                         this_scheduled_log_rotation=(time_t)(this_scheduled_log_rotation-((archive-1)*604800));
00543                         last_scheduled_log_rotation=(time_t)(this_scheduled_log_rotation-604800);
00544                         break;
00545 
00546                 case LOG_ROTATION_MONTHLY:
00547 
00548                         t=localtime(&current_time);
00549                         t->tm_mon++;
00550                         t->tm_mday=1;
00551                         t->tm_hour=0;
00552                         t->tm_min=0;
00553                         t->tm_sec=0;
00554                         for(current_month=0;current_month<=archive;current_month++){
00555                                 if(t->tm_mon==0){
00556                                         t->tm_mon=11;
00557                                         t->tm_year--;
00558                                 } else
00559                                         t->tm_mon--;
00560                         }
00561                         last_scheduled_log_rotation=mktime(t);
00562 
00563                         t=localtime(&current_time);
00564                         t->tm_mon++;
00565                         t->tm_mday=1;
00566                         t->tm_hour=0;
00567                         t->tm_min=0;
00568                         t->tm_sec=0;
00569                         for(current_month=0;current_month<archive;current_month++){
00570                                 if(t->tm_mon==0){
00571                                         t->tm_mon=11;
00572                                         t->tm_year--;
00573                                 } else
00574                                         t->tm_mon--;
00575                         }
00576                         this_scheduled_log_rotation=mktime(t);
00577 
00578                         break;
00579                 default:
00580                         break;
00581         }
00582 
00583         /* adjust this rotation time for daylight savings time */
00584         t=localtime(&this_scheduled_log_rotation);
00585         if(t->tm_isdst>0 && is_dst_now==FALSE)
00586                 this_scheduled_log_rotation=(time_t)(this_scheduled_log_rotation-3600);
00587         else if(t->tm_isdst==0 && is_dst_now==TRUE)
00588                 this_scheduled_log_rotation=(time_t)(this_scheduled_log_rotation+3600);
00589 
00590         /* adjust last rotation time for daylight savings time */
00591         t=localtime(&last_scheduled_log_rotation);
00592         if(t->tm_isdst>0 && is_dst_now==FALSE)
00593                 last_scheduled_log_rotation=(time_t)(last_scheduled_log_rotation-3600);
00594         else if(t->tm_isdst==0 && is_dst_now==TRUE)
00595                 last_scheduled_log_rotation=(time_t)(last_scheduled_log_rotation+3600);
00596 
00597         return;
00598 }
00599 
 All Data Structures Files Functions Variables Typedefs Defines