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 }