00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 
00035 
00036 
00037 #include "ink_platform.h"
00038 #include "ink_memory.h"
00039 #include "ink_defs.h"
00040 #include "ink_error.h"
00041 #include "ink_assert.h"
00042 #include "ink_time.h"
00043 #include "ink_hrtime.h"
00044 #include "Diags.h"
00045 #include "Compatability.h"
00046 
00047 
00048 int diags_on_for_plugins = 0;
00049 bool DiagsConfigState::enabled[2] = { false, false };
00050 
00051 
00052 inkcoreapi Diags *diags = NULL;
00053 
00054 
00055 
00056 
00057 
00058 
00059 
00060 
00061 
00062 
00063 
00064 
00065 
00066 
00067 char *
00068 SrcLoc::str(char *buf, int buflen) const
00069 {
00070   const char * shortname;
00071 
00072   if (!this->valid() || buflen < 1)
00073     return (NULL);
00074 
00075   shortname = strrchr(file, '/');
00076   shortname = shortname ? (shortname + 1) : file;
00077 
00078   if (func != NULL) {
00079     snprintf(buf, buflen, "%s:%d (%s)", shortname, line, func);
00080   } else {
00081     snprintf(buf, buflen, "%s:%d", shortname, line);
00082   }
00083   buf[buflen - 1] = NUL;
00084   return (buf);
00085 }
00086 
00087 
00088 
00089 
00090 
00091 
00092 
00093 
00094 
00095 
00096 
00097 
00098 
00099 
00100 
00101 
00102 
00103 
00104 
00105 
00106 
00107 
00108 Diags::Diags(const char *bdt, const char *bat, FILE * _diags_log_fp)
00109   : diags_log_fp(_diags_log_fp), magic(DIAGS_MAGIC), show_location(0),
00110     base_debug_tags(NULL), base_action_tags(NULL)
00111 {
00112   int i;
00113 
00114   cleanup_func = NULL;
00115   ink_mutex_init(&tag_table_lock, "Diags::tag_table_lock");
00116 
00117 
00118   
00119 
00120 
00121   if (bdt && *bdt) {
00122     base_debug_tags = ats_strdup(bdt);
00123   }
00124   if (bat && *bat) {
00125     base_action_tags = ats_strdup(bat);
00126   }
00127 
00128   config.enabled[DiagsTagType_Debug] = (base_debug_tags != NULL);
00129   config.enabled[DiagsTagType_Action] = (base_action_tags != NULL);
00130   diags_on_for_plugins = config.enabled[DiagsTagType_Debug];
00131 
00132   for (i = 0; i < DiagsLevel_Count; i++) {
00133     config.outputs[i].to_stdout = false;
00134     config.outputs[i].to_stderr = false;
00135     config.outputs[i].to_syslog = false;
00136     config.outputs[i].to_diagslog = true;
00137   }
00138 
00139 
00140   
00141 
00142 
00143   activated_tags[DiagsTagType_Debug] = NULL;
00144   activated_tags[DiagsTagType_Action] = NULL;
00145   prefix_str = "";
00146 
00147 }
00148 
00149 Diags::~Diags()
00150 {
00151   diags_log_fp = NULL;
00152 
00153   ats_free((void *)base_debug_tags);
00154   ats_free((void *)base_action_tags);
00155 
00156   deactivate_all(DiagsTagType_Debug);
00157   deactivate_all(DiagsTagType_Action);
00158 }
00159 
00160 
00161 
00162 
00163 
00164 
00165 
00166 
00167 
00168 
00169 
00170 
00171 
00172 
00173 
00174 
00175 
00176 
00177 
00178 
00179 
00180 
00181 
00182 
00183 
00184 
00185 
00186 
00187 
00188 void
00189 Diags::print_va(const char *debug_tag, DiagsLevel diags_level, const SrcLoc *loc,
00190                 const char *format_string, va_list ap) const
00191 {
00192   struct timeval tp;
00193   const char *s;
00194   char *buffer, *d, timestamp_buf[48];
00195   char format_buf[1024], format_buf_w_ts[1024], *end_of_format;
00196 
00197 
00198   
00199   
00200   
00201 
00202 
00203   format_buf[0] = NUL;
00204   format_buf_w_ts[0] = NUL;
00205 
00206 
00207   
00208   
00209 
00210 
00211   end_of_format = format_buf;
00212   *end_of_format = NUL;
00213 
00214   
00215   pthread_t id = pthread_self();
00216   end_of_format += snprintf(end_of_format, sizeof(format_buf), "{0x%" PRIx64 "} ", (uint64_t) id);
00217 
00218 
00219   
00220 
00221 
00222   for (s = level_name(diags_level); *s; *end_of_format++ = *s++);
00223   *end_of_format++ = ':';
00224   *end_of_format++ = ' ';
00225 
00226 
00227   
00228 
00229 
00230   if (loc && loc->valid()) {
00231     char *lp, buf[256];
00232     lp = loc->str(buf, sizeof(buf));
00233     if (lp) {
00234       *end_of_format++ = '<';
00235       for (s = lp; *s; *end_of_format++ = *s++);
00236       *end_of_format++ = '>';
00237       *end_of_format++ = ' ';
00238     }
00239   }
00240 
00241   
00242 
00243 
00244   if (debug_tag) {
00245     *end_of_format++ = '(';
00246     for (s = debug_tag; *s; *end_of_format++ = *s++);
00247     *end_of_format++ = ')';
00248     *end_of_format++ = ' ';
00249   }
00250 
00251   
00252 
00253 
00254   for (s = format_string; *s; *end_of_format++ = *s++);
00255   *end_of_format++ = NUL;
00256 
00257 
00258 
00259   
00260 
00261 
00262   ink_gethrtimeofday(&tp, NULL);
00263   time_t cur_clock = (time_t) tp.tv_sec;
00264   buffer = ink_ctime_r(&cur_clock, timestamp_buf);
00265   snprintf(&(timestamp_buf[19]), (sizeof(timestamp_buf) - 20), ".%03d", (int) (tp.tv_usec / 1000));
00266 
00267   d = format_buf_w_ts;
00268   *d++ = '[';
00269   for (int i = 4; buffer[i]; i++)
00270     *d++ = buffer[i];
00271   *d++ = ']';
00272   *d++ = ' ';
00273 
00274   for (int k = 0; prefix_str[k]; k++)
00275     *d++ = prefix_str[k];
00276   for (s = format_buf; *s; *d++ = *s++);
00277   *d++ = NUL;
00278 
00279 
00280   
00281 
00282 
00283   lock();
00284   if (config.outputs[diags_level].to_diagslog) {
00285     if (diags_log_fp) {
00286       va_list ap_scratch;
00287       va_copy(ap_scratch, ap);
00288       buffer = format_buf_w_ts;
00289       vfprintf(diags_log_fp, buffer, ap_scratch);
00290       {
00291         int len = strlen(buffer);
00292         if (len > 0 && buffer[len - 1] != '\n') {
00293           putc('\n', diags_log_fp);
00294         }
00295       }
00296     }
00297   }
00298 
00299   if (config.outputs[diags_level].to_stdout) {
00300     va_list ap_scratch;
00301     va_copy(ap_scratch, ap);
00302     buffer = format_buf_w_ts;
00303     vfprintf(stdout, buffer, ap_scratch);
00304     {
00305       int len = strlen(buffer);
00306       if (len > 0 && buffer[len - 1] != '\n') {
00307         putc('\n', stdout);
00308       }
00309     }
00310   }
00311 
00312   if (config.outputs[diags_level].to_stderr) {
00313     va_list ap_scratch;
00314     va_copy(ap_scratch, ap);
00315     buffer = format_buf_w_ts;
00316     vfprintf(stderr, buffer, ap_scratch);
00317     {
00318       int len = strlen(buffer);
00319       if (len > 0 && buffer[len - 1] != '\n') {
00320         putc('\n', stderr);
00321       }
00322     }
00323   }
00324 
00325 #if !defined(freebsd)
00326   unlock();
00327 #endif
00328 
00329   if (config.outputs[diags_level].to_syslog) {
00330     int priority;
00331     char syslog_buffer[2048];
00332 
00333     switch (diags_level) {
00334     case DL_Diag:
00335     case DL_Debug:
00336       priority = LOG_DEBUG;
00337 
00338       break;
00339     case DL_Status:
00340       priority = LOG_INFO;
00341       break;
00342     case DL_Note:
00343       priority = LOG_NOTICE;
00344       break;
00345     case DL_Warning:
00346       priority = LOG_WARNING;
00347       break;
00348     case DL_Error:
00349       priority = LOG_ERR;
00350       break;
00351     case DL_Fatal:
00352       priority = LOG_CRIT;
00353       break;
00354     case DL_Alert:
00355       priority = LOG_ALERT;
00356       break;
00357     case DL_Emergency:
00358       priority = LOG_EMERG;
00359       break;
00360     default:
00361       priority = LOG_NOTICE;
00362       break;
00363     }
00364     vsnprintf(syslog_buffer, sizeof(syslog_buffer) - 1, format_buf, ap);
00365     syslog(priority, "%s", syslog_buffer);
00366   }
00367 #if defined(freebsd)
00368   unlock();
00369 #endif
00370 }
00371 
00372 
00373 
00374 
00375 
00376 
00377 
00378 
00379 
00380 
00381 
00382 
00383 
00384 bool
00385 Diags::tag_activated(const char *tag, DiagsTagType mode) const
00386 {
00387   bool activated = false;
00388 
00389   if (tag == NULL)
00390     return (true);
00391 
00392   lock();
00393   if (activated_tags[mode])
00394     activated = (activated_tags[mode]->match(tag) != -1);
00395   unlock();
00396 
00397   return (activated);
00398 }
00399 
00400 
00401 
00402 
00403 
00404 
00405 
00406 
00407 
00408 
00409 
00410 
00411 
00412 void
00413 Diags::activate_taglist(const char *taglist, DiagsTagType mode)
00414 {
00415   if (taglist) {
00416     lock();
00417     if (activated_tags[mode]) {
00418       delete activated_tags[mode];
00419     }
00420     activated_tags[mode] = new DFA;
00421     activated_tags[mode]->compile(taglist);
00422     unlock();
00423   }
00424 }
00425 
00426 
00427 
00428 
00429 
00430 
00431 
00432 
00433 
00434 
00435 
00436 
00437 void
00438 Diags::deactivate_all(DiagsTagType mode)
00439 {
00440   lock();
00441   if (activated_tags[mode]) {
00442     delete activated_tags[mode];
00443     activated_tags[mode] = NULL;
00444   }
00445   unlock();
00446 }
00447 
00448 
00449 
00450 
00451 
00452 
00453 
00454 
00455 
00456 
00457 
00458 const char *
00459 Diags::level_name(DiagsLevel dl) const
00460 {
00461   switch (dl) {
00462   case DL_Diag:
00463     return ("DIAG");
00464   case DL_Debug:
00465     return ("DEBUG");
00466   case DL_Status:
00467     return ("STATUS");
00468   case DL_Note:
00469     return ("NOTE");
00470   case DL_Warning:
00471     return ("WARNING");
00472   case DL_Error:
00473     return ("ERROR");
00474   case DL_Fatal:
00475     return ("FATAL");
00476   case DL_Alert:
00477     return ("ALERT");
00478   case DL_Emergency:
00479     return ("EMERGENCY");
00480   default:
00481     return ("DIAG");
00482   }
00483 }
00484 
00485 
00486 
00487 
00488 
00489 
00490 
00491 
00492 void
00493 Diags::dump(FILE * fp) const
00494 {
00495   int i;
00496 
00497   fprintf(fp, "Diags:\n");
00498   fprintf(fp, "  debug.enabled: %d\n", config.enabled[DiagsTagType_Debug]);
00499   fprintf(fp, "  debug default tags: '%s'\n", (base_debug_tags ? base_debug_tags : "NULL"));
00500   fprintf(fp, "  action.enabled: %d\n", config.enabled[DiagsTagType_Action]);
00501   fprintf(fp, "  action default tags: '%s'\n", (base_action_tags ? base_action_tags : "NULL"));
00502   fprintf(fp, "  outputs:\n");
00503   for (i = 0; i < DiagsLevel_Count; i++) {
00504     fprintf(fp, "    %10s [stdout=%d, stderr=%d, syslog=%d, diagslog=%d]\n",
00505             level_name((DiagsLevel) i),
00506             config.outputs[i].to_stdout,
00507             config.outputs[i].to_stderr, config.outputs[i].to_syslog, config.outputs[i].to_diagslog);
00508   }
00509 }
00510 
00511 void
00512 Diags::log(const char *tag, DiagsLevel level,
00513            const char *file, const char *func, const int line,
00514            const char *format_string ...) const
00515 {
00516   if (! on(tag))
00517     return;
00518 
00519   va_list ap;
00520   va_start(ap, format_string);
00521   if (show_location) {
00522     SrcLoc lp(file, func, line);
00523     print_va(tag, level, &lp, format_string, ap);
00524   } else {
00525     print_va(tag, level, NULL, format_string, ap);
00526   }
00527   va_end(ap);
00528 }
00529 
00530 void
00531 Diags::error_va(DiagsLevel level,
00532              const char *file, const char *func, const int line,
00533              const char *format_string, va_list ap) const
00534 {
00535   va_list ap2;
00536 
00537   if (DiagsLevel_IsTerminal(level)) {
00538     va_copy(ap2, ap);
00539   }
00540 
00541   if (show_location) {
00542     SrcLoc lp(file, func, line);
00543     print_va(NULL, level, &lp, format_string, ap);
00544   } else {
00545     print_va(NULL, level, NULL, format_string, ap);
00546   }
00547 
00548   if (DiagsLevel_IsTerminal(level)) {
00549     if (cleanup_func)
00550       cleanup_func();
00551     ink_fatal_va(1, format_string, ap2);
00552   }
00553 }