![]() |
Icinga-core 1.4.0
next gen monitoring
|
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(¤t_time); 00518 t=localtime(¤t_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(¤t_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(¤t_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