00001
00002
00003
00004
00005
00006
00007
00008
00009 static const char rcsid[] __attribute__((used)) = "$Id: Log.cpp 1230 2014-11-16 02:32:01Z sella $";
00010
00011 #include "Log.h"
00012 #include "LogException.h"
00013 #include "LogFormat.h"
00014 #include "Process.h"
00015 #include "../Exception.h"
00016
00017 #include <stdio.h>
00018 #include <fcntl.h>
00019 #include <unistd.h>
00020 #include <syslog.h>
00021 #include <stdarg.h>
00022 #include <assert.h>
00023 #include <string.h>
00024
00025 #include <string>
00026
00027 #define BUFFER_SIZE (64 * 1024)
00028
00029 using namespace sella::util;
00030
00031 const char* Log::LABEL_EMERGENCY = "EMRG";
00032 const char* Log::LABEL_ALERT = "ALRT";
00033 const char* Log::LABEL_CRITICAL = "CRIT";
00034 const char* Log::LABEL_ERROR = "ERRO";
00035 const char* Log::LABEL_WARNING = "WARN";
00036 const char* Log::LABEL_NOTICE = "NOTE";
00037 const char* Log::LABEL_INFO = "INFO";
00038 const char* Log::LABEL_DEBUG = "DEBG";
00039
00040 Log::shared libutilxx__log __attribute__((init_priority(250)));
00041
00042 Log::Log(const std::string &identifier, int facility, int option, int mask, const LogFormat &format, size_t size) throw (LogException) :
00043 references(*(new uint64_t(1))),
00044 everyN(*(new uint64_t(1))),
00045
00046 identifier(identifier),
00047 facility(facility),
00048 option(option),
00049
00050 syslog(true),
00051 syslogMask(mask),
00052
00053 allTraceOptions(false)
00054 {
00055 pthread_mutex_init(&mutex, NULL);
00056 this->format = format.clone();
00057 setLogSize(size);
00058
00059 if (identifier.empty()) {
00060 this->identifier = Process::getBaseName();
00061 }
00062
00063 ::openlog(this->identifier.c_str(), option, facility);
00064 }
00065
00066 Log::Log(const std::string &file, const LogFormat &format, size_t size) throw (LogException) :
00067 references(*(new uint64_t(1))),
00068 everyN(*(new uint64_t(1))),
00069 identifier(file),
00070 facility(::open(file.c_str(), O_APPEND|O_CREAT|O_NONBLOCK, S_IRWXU)),
00071 option(0),
00072
00073 syslog(false),
00074 syslogMask(0),
00075
00076 allTraceOptions(false)
00077 {
00078 pthread_mutex_init(&mutex, NULL);
00079 this->format = format.clone();
00080 setLogSize(size);
00081
00082 if (this->facility < 0) {
00083 THROW(LogException, "failed to open file '%s' for logging", file.c_str());
00084 }
00085 }
00086
00087 Log::Log(const Log &other) throw () :
00088 references(other.references),
00089 everyN(other.everyN),
00090
00091 identifier(other.identifier),
00092 facility(other.facility),
00093 option(other.option),
00094
00095 format(NULL),
00096 syslog(other.syslog),
00097 syslogMask(other.syslogMask),
00098 size(other.size),
00099
00100 traceOptions(other.traceOptions),
00101 allTraceOptions(other.allTraceOptions)
00102 {
00103 pthread_mutex_init(&mutex, NULL);
00104 this->references += 1;
00105 this->format = other.format->clone();
00106 }
00107
00108 Log::~Log() throw () {
00109 if ((--(this->references)) == 0) {
00110 delete &(this->references);
00111 delete &(this->everyN);
00112 delete format;
00113
00114 if (this->syslog) {
00115 closelog();
00116 } else {
00117 close(this->facility);
00118 }
00119 }
00120
00121 pthread_mutex_destroy(&mutex);
00122 }
00123
00124 Log& Log::operator=(const Log &other) throw () {
00125 if (this != &other) {
00126 pthread_mutex_lock(&mutex);
00127
00128 this->references = other.references;
00129 this->references += 1;
00130 this->everyN = other.everyN;
00131
00132 this->identifier = other.identifier;
00133 this->facility = other.facility;
00134 this->option = other.option;
00135
00136 if (this->format) {
00137 delete format;
00138 }
00139
00140 this->format = other.format->clone();
00141 this->syslog = other.syslog;
00142 this->syslogMask = other.syslogMask;
00143 this->size = other.size;
00144
00145 this->traceOptions = other.traceOptions;
00146 this->allTraceOptions = other.allTraceOptions;
00147
00148 pthread_mutex_unlock(&mutex);
00149 }
00150 return *this;
00151 }
00152
00153 const Log::shared Log::shared_ptr(const std::string &identifier, int facility, int option, int mask, const LogFormat &format, size_t size) throw (LogException) {
00154 return std::make_shared<Log>(identifier, facility, option, mask, format, size);
00155 }
00156
00157 const Log::shared Log::shared_ptr(const std::string &file, const LogFormat &format, size_t size) throw (LogException) {
00158 return std::make_shared<Log>(file, format, size);
00159 }
00160
00161 const char* Log::priority(int level) throw () {
00162 switch (LOG_PRI(level)) {
00163 case Log::LEVEL_EMERGENCY:
00164 return Log::LABEL_EMERGENCY;
00165 case Log::LEVEL_ALERT:
00166 return Log::LABEL_ALERT;
00167 case Log::LEVEL_CRITICAL:
00168 return Log::LABEL_CRITICAL;
00169 case Log::LEVEL_ERROR:
00170 return Log::LABEL_ERROR;
00171 case Log::LEVEL_WARNING:
00172 return Log::LABEL_WARNING;
00173 case Log::LEVEL_NOTICE:
00174 return Log::LABEL_NOTICE;
00175 case Log::LEVEL_INFO:
00176 return Log::LABEL_INFO;
00177 case Log::LEVEL_DEBUG:
00178 return Log::LABEL_DEBUG;
00179 }
00180
00181 return "UNKN";
00182 }
00183
00184 void Log::setIdentifier(const std::string &identifier) throw () {
00185 this->identifier = identifier;
00186
00187 ::openlog(identifier.c_str(), option, facility);
00188 }
00189
00190 void Log::setFacility(int facility) throw () {
00191 this->facility = facility;
00192
00193 ::openlog(identifier.c_str(), option, facility);
00194 }
00195
00196 void Log::setOption(int option) throw () {
00197 this->option = option;
00198
00199 ::openlog(identifier.c_str(), option, facility);
00200 }
00201
00202 void Log::setFormat(const LogFormat &format) throw () {
00203 pthread_mutex_lock(&mutex);
00204
00205 if (this->format) {
00206 delete this->format;
00207 }
00208
00209 this->format = format.clone();
00210
00211 pthread_mutex_unlock(&mutex);
00212 }
00213
00214 void Log::setLogLevel(int level, bool on) throw () {
00215 pthread_mutex_lock(&mutex);
00216
00217 if (on) {
00218 this->syslogMask |= LOG_MASK(level);
00219 } else {
00220 this->syslogMask &= ~LOG_MASK(level);
00221 }
00222
00223 pthread_mutex_unlock(&mutex);
00224 }
00225
00226 int Log::setLogMask(int mask) throw () {
00227 pthread_mutex_lock(&mutex);
00228
00229 int prevMask = this->syslogMask;
00230 this->syslogMask = mask;
00231
00232 pthread_mutex_unlock(&mutex);
00233
00234 return prevMask;
00235 }
00236
00237 void Log::setLogSize(size_t size) throw () {
00238 this->size = (size < BUFFER_SIZE) ? size : BUFFER_SIZE;
00239 }
00240
00241 int Log::getLogMask(void) throw () {
00242 return this->syslogMask;
00243 }
00244
00245 bool Log::isLogMask(int level) throw () {
00246 return (this->syslogMask & LOG_MASK(level));
00247 }
00248
00249 size_t Log::getLogSize(void) throw () {
00250 return this->size;
00251 }
00252
00253 void Log::setTraceOption(const std::string &option, bool on) throw () {
00254
00255 if (option.compare("all") == 0) {
00256 allTraceOptions = on;
00257
00258 return;
00259 }
00260
00261 pthread_mutex_lock(&mutex);
00262
00263 if (on) {
00264 traceOptions.insert(option);
00265 } else {
00266 traceOptions.erase(option);
00267 }
00268
00269 pthread_mutex_unlock(&mutex);
00270 }
00271
00272 void Log::setTraceOption(const std::vector<std::string> &options, bool on) throw () {
00273 setTraceOptions(options, on);
00274 }
00275
00276 void Log::setTraceOption(const std::list<std::string> &options, bool on) throw () {
00277 setTraceOptions(options, on);
00278 }
00279
00280 void Log::setTraceOptions(const std::vector<std::string> &options, bool on) throw () {
00281 for (auto it = options.cbegin(); it != options.cend(); ++it) {
00282 setTraceOption(*it, on);
00283 }
00284 }
00285
00286 void Log::setTraceOptions(const std::list<std::string> &options, bool on) throw () {
00287 for (auto it = options.cbegin(); it != options.cend(); ++it) {
00288 setTraceOption(*it, on);
00289 }
00290 }
00291
00292 bool Log::isTraceOption(const char* option) throw () {
00293 assert(option);
00294
00295
00296 if (allTraceOptions) {
00297 return true;
00298 } else if (traceOptions.empty()) {
00299 return false;
00300 }
00301
00302 pthread_mutex_lock(&mutex);
00303
00304 if (traceOptions.find(option) == traceOptions.end()) {
00305 pthread_mutex_unlock(&mutex);
00306
00307 return false;
00308 }
00309
00310 pthread_mutex_unlock(&mutex);
00311
00312 return true;
00313 }
00314
00315 bool Log::isTraceOption(const std::string &option) throw () {
00316
00317 if (allTraceOptions) {
00318 return true;
00319 } else if (traceOptions.empty()) {
00320 return false;
00321 }
00322
00323 pthread_mutex_lock(&mutex);
00324
00325 if (traceOptions.find(option) == traceOptions.end()) {
00326 pthread_mutex_unlock(&mutex);
00327
00328 return false;
00329 }
00330
00331 pthread_mutex_unlock(&mutex);
00332
00333 return true;
00334 }
00335
00336 bool Log::hasTraceOptions(void) throw () {
00337 return (allTraceOptions || traceOptions.empty());
00338 }
00339
00340 void Log::clearTraceOptions(void) throw () {
00341 pthread_mutex_lock(&mutex);
00342
00343 allTraceOptions = false;
00344 traceOptions.clear();
00345
00346 pthread_mutex_unlock(&mutex);
00347 }
00348
00349 bool Log::incEveryN(uint64_t n) throw () {
00350 pthread_mutex_lock(&mutex);
00351
00352 bool result = (everyN++ % n == 0);
00353
00354 pthread_mutex_unlock(&mutex);
00355
00356 return result;
00357 }
00358
00359 bool Log::incFirstN(uint64_t n) throw () {
00360 pthread_mutex_lock(&mutex);
00361
00362 bool result = (everyN++ <= n);
00363
00364 pthread_mutex_unlock(&mutex);
00365
00366 return result;
00367 }
00368
00369 void Log::resetEveryN(void) throw () {
00370 pthread_mutex_lock(&mutex);
00371
00372 this->everyN = 0;
00373
00374 pthread_mutex_unlock(&mutex);
00375 }
00376
00377 bool Log::trace(const char *option, const char *func, const char *file, int line, const char *format, ...) throw () {
00378 int level = Log::LEVEL_INFO;
00379 va_list arguments;
00380 char buffer[BUFFER_SIZE];
00381 ssize_t c;
00382 struct timeval stamp;
00383
00384 if (!isTraceOption(option)) {
00385 return false;
00386 }
00387
00388 gettimeofday(&stamp, NULL);
00389
00390 if (format == NULL) {
00391 buffer[0] = NULL;
00392 } else {
00393 va_start(arguments, format);
00394 vsnprintf(buffer, sizeof(buffer), format, arguments);
00395 va_end(arguments);
00396 }
00397
00398 pthread_mutex_lock(&mutex);
00399
00400 std::string text = this->format->format(level, this->format->format(stamp).c_str(), func, file, line, option, buffer);
00401
00402 if (this->syslog) {
00403 resize(text);
00404 ::syslog(facility|level, text.c_str());
00405 } else {
00406 c = ::write(this->facility, text.c_str(), text.size());
00407 c = ::write(this->facility, "\n", 1);
00408 }
00409
00410 pthread_mutex_unlock(&mutex);
00411
00412 return true;
00413 }
00414
00415 bool Log::trace(std::string &option, const char *func, const char *file, int line, const char *format, ...) throw () {
00416 int level = Log::LEVEL_INFO;
00417 va_list arguments;
00418 char buffer[BUFFER_SIZE];
00419 ssize_t c;
00420 struct timeval stamp;
00421
00422 if (!isTraceOption(option)) {
00423 return false;
00424 }
00425
00426 gettimeofday(&stamp, NULL);
00427
00428 if (format == NULL) {
00429 buffer[0] = NULL;
00430 } else {
00431 va_start(arguments, format);
00432 vsnprintf(buffer, sizeof(buffer), format, arguments);
00433 va_end(arguments);
00434 }
00435
00436 pthread_mutex_lock(&mutex);
00437
00438 std::string text = this->format->format(level, this->format->format(stamp).c_str(), func, file, line, option.c_str(), buffer);
00439
00440 if (this->syslog) {
00441 resize(text);
00442 ::syslog(facility|level, text.c_str());
00443 } else {
00444 c = ::write(this->facility, text.c_str(), text.size());
00445 c = ::write(this->facility, "\n", 1);
00446 }
00447
00448 pthread_mutex_unlock(&mutex);
00449
00450 return true;
00451 }
00452
00453 bool Log::trace(const char *option, const char *func, const char *file, int line, const std::string &format, ...) throw () {
00454 int level = Log::LEVEL_INFO;
00455 va_list arguments;
00456 char buffer[BUFFER_SIZE];
00457 ssize_t c;
00458 struct timeval stamp;
00459
00460 if (!isTraceOption(option)) {
00461 return false;
00462 }
00463
00464 gettimeofday(&stamp, NULL);
00465
00466 va_start(arguments, format);
00467 vsnprintf(buffer, sizeof(buffer), format.c_str(), arguments);
00468 va_end(arguments);
00469
00470 pthread_mutex_lock(&mutex);
00471
00472 std::string text = this->format->format(level, this->format->format(stamp).c_str(), func, file, line, option, buffer);
00473
00474 if (this->syslog) {
00475 resize(text);
00476 ::syslog(facility|level, text.c_str());
00477 } else {
00478 c = ::write(this->facility, text.c_str(), text.size());
00479 c = ::write(this->facility, "\n", 1);
00480 }
00481
00482 pthread_mutex_unlock(&mutex);
00483
00484 return true;
00485 }
00486
00487 bool Log::trace(std::string &option, const char *func, const char *file, int line, const std::string &format, ...) throw () {
00488 int level = Log::LEVEL_INFO;
00489 va_list arguments;
00490 char buffer[BUFFER_SIZE];
00491 ssize_t c;
00492 struct timeval stamp;
00493
00494 if (!isTraceOption(option)) {
00495 return false;
00496 }
00497
00498 gettimeofday(&stamp, NULL);
00499
00500 va_start(arguments, format);
00501 vsnprintf(buffer, sizeof(buffer), format.c_str(), arguments);
00502 va_end(arguments);
00503
00504 pthread_mutex_lock(&mutex);
00505
00506 std::string text = this->format->format(level, this->format->format(stamp).c_str(), func, file, line, option.c_str(), buffer);
00507
00508 if (this->syslog) {
00509 resize(text);
00510 ::syslog(facility|level, text.c_str());
00511 } else {
00512 c = ::write(this->facility, text.c_str(), text.size());
00513 c = ::write(this->facility, "\n", 1);
00514 }
00515
00516 pthread_mutex_unlock(&mutex);
00517
00518 return true;
00519 }
00520
00521 bool Log::write(int facility, int level, const char *func, const char *file, int line, const sella::Exception &e, const std::string &format, ...) throw () {
00522 va_list arguments;
00523 char buffer[BUFFER_SIZE];
00524 ssize_t c;
00525 struct timeval stamp;
00526
00527 if (!isLogMask(level)) {
00528 return false;
00529 }
00530
00531 gettimeofday(&stamp, NULL);
00532
00533 if (format.empty()) {
00534 strncpy(buffer, "Exception", sizeof(buffer));
00535 } else {
00536 va_start(arguments, format);
00537 vsnprintf(buffer, sizeof(buffer), format.c_str(), arguments);
00538 va_end(arguments);
00539 }
00540
00541 pthread_mutex_lock(&mutex);
00542
00543 std::string text = this->format->format(level, this->format->format(stamp).c_str(), func, file, line, e, buffer);
00544
00545 if (this->syslog) {
00546 resize(text);
00547 ::syslog(facility|level, text.c_str());
00548 } else {
00549 c = ::write(this->facility, text.c_str(), text.size());
00550 c = ::write(this->facility, "\n", 1);
00551 }
00552
00553 pthread_mutex_unlock(&mutex);
00554
00555 return true;
00556 }
00557
00558 bool Log::write(int facility, int level, const char *func, const char *file, int line, const std::string &format, ...) throw () {
00559 va_list arguments;
00560 char buffer[BUFFER_SIZE];
00561 ssize_t c;
00562 struct timeval stamp;
00563
00564 if (!isLogMask(level)) {
00565 return false;
00566 }
00567
00568 gettimeofday(&stamp, NULL);
00569
00570 va_start(arguments, format);
00571 vsnprintf(buffer, sizeof(buffer), format.c_str(), arguments);
00572 va_end(arguments);
00573
00574 pthread_mutex_lock(&mutex);
00575
00576 std::string text = this->format->format(level, this->format->format(stamp).c_str(), func, file, line, buffer);
00577
00578 if (this->syslog) {
00579 resize(text);
00580 ::syslog(facility|level, text.c_str());
00581 } else {
00582 c = ::write(this->facility, text.c_str(), text.size());
00583 c = ::write(this->facility, "\n", 1);
00584 }
00585
00586 pthread_mutex_unlock(&mutex);
00587
00588 return true;
00589 }
00590
00591 bool Log::write(int level, const char *func, const char *file, int line, const sella::Exception &e) throw () {
00592 ssize_t c;
00593 struct timeval stamp;
00594
00595 if (!isLogMask(level)) {
00596 return false;
00597 }
00598
00599 gettimeofday(&stamp, NULL);
00600
00601 pthread_mutex_lock(&mutex);
00602
00603 std::string text = this->format->format(level, this->format->format(stamp).c_str(), func, file, line, e, NULL);
00604
00605 if (this->syslog) {
00606 resize(text);
00607 ::syslog(level, text.c_str());
00608 } else {
00609 c = ::write(this->facility, text.c_str(), text.size());
00610 c = ::write(this->facility, "\n", 1);
00611 }
00612
00613 pthread_mutex_unlock(&mutex);
00614
00615 return true;
00616 }
00617
00618 bool Log::write(int level, const char *func, const char *file, int line, const sella::Exception &e, const std::string &format, ...) throw () {
00619 va_list arguments;
00620 char buffer[BUFFER_SIZE];
00621 ssize_t c;
00622 struct timeval stamp;
00623
00624 if (!isLogMask(level)) {
00625 return false;
00626 }
00627
00628 gettimeofday(&stamp, NULL);
00629
00630 if (format.empty()) {
00631 strncpy(buffer, "Exception", sizeof(buffer));
00632 } else {
00633 va_start(arguments, format);
00634 vsnprintf(buffer, sizeof(buffer), format.c_str(), arguments);
00635 va_end(arguments);
00636 }
00637
00638 pthread_mutex_lock(&mutex);
00639
00640 std::string text = this->format->format(level, this->format->format(stamp).c_str(), func, file, line, e, buffer);
00641
00642 if (this->syslog) {
00643 resize(text);
00644 ::syslog(level, text.c_str());
00645 } else {
00646 c = ::write(this->facility, text.c_str(), text.size());
00647 c = ::write(this->facility, "\n", 1);
00648 }
00649
00650 pthread_mutex_unlock(&mutex);
00651
00652 return true;
00653 }
00654
00655 bool Log::write(int level, const char *func, const char *file, int line, const std::string &format, ...) throw () {
00656 va_list arguments;
00657 char buffer[BUFFER_SIZE];
00658 ssize_t c;
00659 struct timeval stamp;
00660
00661 if (!isLogMask(level)) {
00662 return false;
00663 }
00664
00665 gettimeofday(&stamp, NULL);
00666
00667 va_start(arguments, format);
00668 vsnprintf(buffer, sizeof(buffer), format.c_str(), arguments);
00669 va_end(arguments);
00670
00671 pthread_mutex_lock(&mutex);
00672
00673 std::string text = this->format->format(level, this->format->format(stamp).c_str(), func, file, line, buffer);
00674
00675 if (this->syslog) {
00676 resize(text);
00677 ::syslog(level, text.c_str());
00678 } else {
00679 c = ::write(this->facility, text.c_str(), text.size());
00680 c = ::write(this->facility, "\n", 1);
00681 }
00682
00683 pthread_mutex_unlock(&mutex);
00684
00685 return true;
00686 }
00687
00688 bool Log::write(int facility, int level, const char *func, const char *file, int line, const sella::Exception &e, const char *format, ...) throw () {
00689 va_list arguments;
00690 char buffer[BUFFER_SIZE];
00691 ssize_t c;
00692 struct timeval stamp;
00693
00694 if (!isLogMask(level)) {
00695 return false;
00696 }
00697
00698 gettimeofday(&stamp, NULL);
00699
00700 if (format == NULL) {
00701 buffer[0] = NULL;
00702 } else if (format[0] == '\0') {
00703 strncpy(buffer, "Exception", sizeof(buffer));
00704 } else {
00705 va_start(arguments, format);
00706 vsnprintf(buffer, sizeof(buffer), format, arguments);
00707 va_end(arguments);
00708 }
00709
00710 pthread_mutex_lock(&mutex);
00711
00712 std::string text = this->format->format(level, this->format->format(stamp).c_str(), func, file, line, e, buffer);
00713
00714 if (this->syslog) {
00715 resize(text);
00716 ::syslog(facility|level, text.c_str());
00717 } else {
00718 c = ::write(this->facility, text.c_str(), text.size());
00719 c = ::write(this->facility, "\n", 1);
00720 }
00721
00722 pthread_mutex_unlock(&mutex);
00723
00724 return true;
00725 }
00726
00727 bool Log::write(int facility, int level, const char *func, const char *file, int line, const char *format, ...) throw () {
00728 va_list arguments;
00729 char buffer[BUFFER_SIZE];
00730 ssize_t c;
00731 struct timeval stamp;
00732
00733 if (!isLogMask(level)) {
00734 return false;
00735 }
00736
00737 gettimeofday(&stamp, NULL);
00738
00739 if (format == NULL) {
00740 buffer[0] = NULL;
00741 } else {
00742 va_start(arguments, format);
00743 vsnprintf(buffer, sizeof(buffer), format, arguments);
00744 va_end(arguments);
00745 }
00746
00747 pthread_mutex_lock(&mutex);
00748
00749 std::string text = this->format->format(level, this->format->format(stamp).c_str(), func, file, line, buffer);
00750
00751 if (this->syslog) {
00752 resize(text);
00753 ::syslog(facility|level, text.c_str());
00754 } else {
00755 c = ::write(this->facility, text.c_str(), text.size());
00756 c = ::write(this->facility, "\n", 1);
00757 }
00758
00759 pthread_mutex_unlock(&mutex);
00760
00761 return true;
00762 }
00763
00764 bool Log::write(int level, const char *func, const char *file, int line, const sella::Exception &e, const char *format, ...) throw () {
00765 va_list arguments;
00766 char buffer[BUFFER_SIZE];
00767 ssize_t c;
00768 struct timeval stamp;
00769
00770 if (!isLogMask(level)) {
00771 return false;
00772 }
00773
00774 gettimeofday(&stamp, NULL);
00775
00776 if (format == NULL) {
00777 buffer[0] = NULL;
00778 } else if (format[0] == '\0') {
00779 strncpy(buffer, "Exception", sizeof(buffer));
00780 } else {
00781 va_start(arguments, format);
00782 vsnprintf(buffer, sizeof(buffer), format, arguments);
00783 va_end(arguments);
00784 }
00785
00786 pthread_mutex_lock(&mutex);
00787
00788 std::string text = this->format->format(level, this->format->format(stamp).c_str(), func, file, line, e, buffer);
00789
00790 if (this->syslog) {
00791 resize(text);
00792 ::syslog(level, text.c_str());
00793 } else {
00794 c = ::write(this->facility, text.c_str(), text.size());
00795 c = ::write(this->facility, "\n", 1);
00796 }
00797
00798 pthread_mutex_unlock(&mutex);
00799
00800 return true;
00801 }
00802
00803 bool Log::write(int level, const char *func, const char *file, int line, const char *format, ...) throw () {
00804 va_list arguments;
00805 char buffer[BUFFER_SIZE];
00806 ssize_t c;
00807 struct timeval stamp;
00808
00809 if (!isLogMask(level)) {
00810 return false;
00811 }
00812
00813 gettimeofday(&stamp, NULL);
00814
00815 if (format == NULL) {
00816 buffer[0] = NULL;
00817 } else {
00818 va_start(arguments, format);
00819 vsnprintf(buffer, sizeof(buffer), format, arguments);
00820 va_end(arguments);
00821 }
00822
00823 pthread_mutex_lock(&mutex);
00824
00825 std::string text = this->format->format(level, this->format->format(stamp).c_str(), func, file, line, buffer);
00826
00827 if (this->syslog) {
00828 resize(text);
00829 ::syslog(level, text.c_str());
00830 } else {
00831 c = ::write(this->facility, text.c_str(), text.size());
00832 c = ::write(this->facility, "\n", 1);
00833 }
00834
00835 pthread_mutex_unlock(&mutex);
00836
00837 return true;
00838 }
00839
00840 void Log::resize(std::string &text) throw () {
00841 if (text.size() > size) {
00842 text.resize(size);
00843 }
00844 }
00845
00846 Log::shared& Log::instance(const std::string &identifier) {
00847 static Log::shared logger = Log::shared_ptr(identifier, LOG_LOCAL0, Log::WithStderrOption);
00848
00849 return logger;
00850 }
00851
00852
00853
00854