27 #ifndef TURI_LOG_LOG_HPP 28 #define TURI_LOG_LOG_HPP 30 #ifndef TURI_LOGGER_THROW_ON_FAILURE 31 #define TURI_LOGGER_THROW_ON_FAILURE 34 #if defined(COMPILER_HAS_IOS_BASE_FAILURE_WITH_ERROR_CODE) && (_MSC_VER < 1600) 35 #undef COMPILER_HAS_IOS_BASE_FAILURE_WITH_ERROR_CODE 44 #ifdef COMPILER_HAS_IOS_BASE_FAILURE_WITH_ERROR_CODE 45 #include <system_error> 48 #include <core/parallel/pthread_h.h> 49 #include <timer/timer.hpp> 50 #include <core/logging/fail_method.hpp> 51 #include <core/logging/backtrace.hpp> 52 #include <core/logging/error.hpp> 53 #include <core/system/cppipc/server/cancel_ops.hpp> 54 #include <core/util/code_optimization.hpp> 55 #include <process/process_util.hpp> 99 #define LOG_PROGRESS 4 103 #define LOG_EVERYTHING 0 113 #define OUTPUTLEVEL LOG_DEBUG 248 #if OUTPUTLEVEL == LOG_NONE 250 #define logger(lvl,fmt,...) 251 #define logbuf(lvl,buflen, 252 #define logstream(lvl) if(0) null_stream() 254 #define logger_once(lvl,fmt,...) 255 #define logstream_once(lvl) if(0) null_stream() 257 #define logger_ontick(sec,lvl,fmt,...) 258 #define logstream_ontick(sec, lvl) if(0) null_stream() 260 #define logprogress(fmt,...) 261 #define logprogress_stream if(0) null_stream() 263 #define logprogress_ontick(sec,fmt,...) 264 #define logprogress_stream_ontick(sec) if(0) null_stream() 268 #define logger(lvl, fmt, ...) \ 269 (log_dispatch<(lvl >= OUTPUTLEVEL)>::exec(lvl, __FILE__, __func__, __LINE__, \ 272 #define logbuf(lvl, buf, len) \ 273 (log_dispatch<(lvl >= OUTPUTLEVEL)>::exec(lvl, __FILE__, __func__, __LINE__, \ 276 #define logstream(lvl) \ 277 if (lvl >= global_logger().get_log_level()) \ 278 (log_stream_dispatch<(lvl >= OUTPUTLEVEL)>::exec(lvl, __FILE__, __func__, \ 281 #define logger_once(lvl, fmt, ...) \ 283 static bool __printed__ = false; \ 284 if (!__printed__) { \ 285 __printed__ = true; \ 286 (log_dispatch<(lvl >= OUTPUTLEVEL)>::exec( \ 287 lvl, __FILE__, __func__, __LINE__, fmt, ##__VA_ARGS__)); \ 291 #define logstream_once(lvl) \ 293 static bool __printed__ = false; \ 294 bool __prev_printed__ = __printed__; \ 295 if (!__printed__) __printed__ = true; \ 296 &(log_stream_dispatch<(lvl >= OUTPUTLEVEL)>::exec( \ 297 lvl, __FILE__, __func__, __LINE__, !__prev_printed__)); \ 300 #define logger_ontick(sec, lvl, fmt, ...) \ 302 static float last_print = -sec - 1; \ 303 float curtime = turi::timer::approx_time_seconds(); \ 304 if (last_print + sec <= curtime) { \ 305 last_print = curtime; \ 306 (log_dispatch<(lvl >= OUTPUTLEVEL)>::exec( \ 307 lvl, __FILE__, __func__, __LINE__, fmt, ##__VA_ARGS__)); \ 311 #define logstream_ontick(sec, lvl) \ 313 static float last_print = -sec - 1; \ 314 float curtime = turi::timer::approx_time_seconds(); \ 315 bool print_now = false; \ 316 if (last_print + sec <= curtime) { \ 317 last_print = curtime; \ 320 &(log_stream_dispatch<(lvl >= OUTPUTLEVEL)>::exec(lvl, __FILE__, __func__, \ 321 __LINE__, print_now)); \ 324 #define logprogress(fmt,...) logger(LOG_PROGRESS, fmt, ##__VA_ARGS__) 325 #define logprogress_stream logstream(LOG_PROGRESS) 327 #define logprogress_ontick(sec,fmt,...) logger_ontick(sec, LOG_PROGRESS, fmt, ##__VA_ARGS__) 328 #define logprogress_stream_ontick(sec) logstream_ontick(sec, LOG_PROGRESS) 334 #define log_and_throw(message) \ 336 auto throw_error = [&]() GL_COLD_NOINLINE_ERROR { \ 337 logstream(LOG_ERROR) << (message) << std::endl; \ 338 throw(std::string(message)); \ 343 #define std_log_and_throw(key_type, message) \ 345 auto throw_error = [&]() GL_COLD_NOINLINE_ERROR { \ 346 logstream(LOG_ERROR) << (message) << std::endl; \ 347 throw(key_type(message)); \ 352 #ifdef COMPILER_HAS_IOS_BASE_FAILURE_WITH_ERROR_CODE 353 #define log_and_throw_io_failure(message) \ 355 auto throw_error = [&]() GL_COLD_NOINLINE_ERROR { \ 356 logstream(LOG_ERROR) << (message) << std::endl; \ 357 throw(turi::error::io_error(message, std::error_code())); \ 362 #define log_and_throw_io_failure(message) \ 364 auto throw_error = [&]() GL_COLD_NOINLINE_ERROR { \ 365 logstream(LOG_ERROR) << (message) << std::endl; \ 366 throw(turi::error::io_error(message)); \ 374 #define log_and_throw(message) \ 376 auto throw_error = [&]() GL_COLD_NOINLINE_ERROR { \ 377 std::stringstream _turi_ss; \ 378 _turi_ss << (message) << ". " << __func__ << " from " << __FILE__ \ 379 << " at " << __LINE__ << std::endl; \ 380 logstream(LOG_ERROR) << message << std::endl; \ 381 throw(_turi_ss.str()); \ 386 #define std_log_and_throw(key_type, message) \ 388 auto throw_error = [&]() GL_COLD_NOINLINE_ERROR { \ 389 std::stringstream _turi_ss; \ 390 _turi_ss << (message) << ". " << __func__ << " from " << __FILE__ \ 391 << " at " << __LINE__ << std::endl; \ 392 logstream(LOG_ERROR) << message << std::endl; \ 393 throw(key_type(_turi_ss.str())); \ 398 #ifdef COMPILER_HAS_IOS_BASE_FAILURE_WITH_ERROR_CODE 399 #define log_and_throw_io_failure(message) \ 401 auto throw_error = [&]() GL_COLD_NOINLINE_ERROR { \ 402 std::stringstream _turi_ss; \ 403 _turi_ss << (message) << ". " << __func__ << " from " << __FILE__ \ 404 << " at " << __LINE__ << std::endl; \ 405 logstream(LOG_ERROR) << message << std::endl; \ 406 throw(turi::error::io_error(__turi_ss.str(), std::error_code())); \ 411 #define log_and_throw_io_failure(message) \ 413 auto throw_error = [&]() GL_COLD_NOINLINE_ERROR { \ 414 std::stringstream _turi_ss; \ 415 _turi_ss << (message) << ". " << __func__ << " from " << __FILE__ \ 416 << " at " << __LINE__ << std::endl; \ 417 logstream(LOG_ERROR) << message << std::endl; \ 418 throw(turi::error::io_error(_turi_ss.str())); \ 424 #endif // end of NDEBUG 426 #define log_and_throw_current_io_failure() \ 428 auto error_code = errno; \ 429 std::string error_message = std::strerror(error_code); \ 431 log_and_throw_io_failure(error_message); \ 434 #define log_func_entry() \ 436 logstream(LOG_INFO) << "Function entry" << std::endl; \ 439 #define Dlog_func_entry() \ 441 logstream(LOG_DEBUG) << "Function entry" << std::endl; \ 445 struct streambuff_tls_entry {
446 std::stringstream streambuffer;
453 #define LOG_DEBUG_WITH_PID(...) \ 455 auto __log_funct = [&]() { \ 456 std::ostringstream ss; \ 457 ss << "PID-" << global_logger().get_pid() << ": "; \ 459 logstream(LOG_DEBUG) << ss.str() << std::endl; \ 461 if(LOG_DEBUG >= global_logger().get_log_level()) { __log_funct(); } \ 465 extern void __print_back_trace();
489 bool set_log_file(std::string file);
495 log_to_console = consolelog;
496 log_to_stderr = _log_to_stderr;
510 return reference_pid;
520 return log_to_console;
533 std::function<
void(
int lineloglevel,
const char* buf,
size_t len)> callback_fn) {
534 pthread_mutex_lock(&mut);
535 callback[loglevel] = callback_fn;
537 has_callback[loglevel] = !!callback_fn;
538 pthread_mutex_unlock(&mut);
545 inline std::function<void(int lineloglevel, const char* buf, size_t len)>
get_observer(
int loglevel) {
546 return callback[loglevel];
549 file_logger& start_stream(
int lineloglevel,
const char* file,
const char*
function,
int line,
bool do_start =
true);
554 template <
typename T>
557 logger_impl::streambuff_tls_entry* streambufentry =
reinterpret_cast<logger_impl::streambuff_tls_entry*
>(
558 pthread_getspecific(streambuffkey));
559 if (streambufentry != NULL) {
560 std::stringstream& streambuffer = streambufentry->streambuffer;
561 bool& streamactive = streambufentry->streamactive;
575 logger_impl::streambuff_tls_entry* streambufentry =
reinterpret_cast<logger_impl::streambuff_tls_entry*
>(
576 pthread_getspecific(streambuffkey));
577 if (streambufentry != NULL) {
578 std::stringstream& streambuffer = streambufentry->streambuffer;
579 bool& streamactive = streambufentry->streamactive;
583 size_t s = strlen(a);
584 if (s > 0 && a[s-1] ==
'\n') {
597 logger_impl::streambuff_tls_entry* streambufentry =
reinterpret_cast<logger_impl::streambuff_tls_entry*
>(
598 pthread_getspecific(streambuffkey));
599 if (streambufentry != NULL) {
600 std::stringstream& streambuffer = streambufentry->streambuffer;
601 bool& streamactive = streambufentry->streamactive;
613 __print_back_trace();
614 TURI_LOGGER_FAIL_METHOD(
"LOG_FATAL encountered");
626 log_level = new_log_level;
640 void _log(
int loglevel,
const char* file,
const char*
function,
641 size_t line,
const char* fmt, va_list arg );
643 void _logbuf(
int loglevel,
const char* file,
const char*
function,
644 size_t line,
const char* buf,
size_t len);
646 void _lograw(
int loglevel,
const char* buf,
size_t len);
648 inline void stream_flush() {
650 logger_impl::streambuff_tls_entry* streambufentry =
651 reinterpret_cast<logger_impl::streambuff_tls_entry*
>(
652 pthread_getspecific(streambuffkey));
653 if (streambufentry != NULL) {
654 std::stringstream& streambuffer = streambufentry->streambuffer;
655 int lineloglevel = streambufentry->loglevel;
657 streambuffer.flush();
658 std::string msg = streambuffer.str();
659 _lograw(streamloglevel, msg.c_str(), msg.length());
662 if (has_callback[lineloglevel]) {
663 pthread_mutex_lock(&mut);
664 if (callback[lineloglevel]) {
665 callback[lineloglevel](lineloglevel,
666 msg.c_str() + streambufentry->header_len,
667 msg.length() - streambufentry->header_len);
669 streambufentry->header_len = 0;
670 pthread_mutex_unlock(&mut);
672 streambuffer.str(
"");
677 std::string log_file;
679 pthread_key_t streambuffkey;
688 size_t reference_pid = size_t(-1);
691 std::function<void(int lineloglevel, const char* buf, size_t len)> callback[LOG_NONE];
692 int has_callback[LOG_NONE];
704 template <
bool dostuff>
709 inline static void exec(
int loglevel,
const char* file,
const char*
function,
710 int line,
const char* fmt, ... ) {
716 __print_back_trace();
717 TURI_LOGGER_FAIL_METHOD(
"LOG_FATAL encountered");
724 inline static void exec(
int loglevel,
const char* file,
const char*
function,
725 int line,
const char* fmt, ... ) {}
731 inline null_stream
operator<<(T t) {
return null_stream(); }
732 inline null_stream
operator<<(
const char* a) {
return null_stream(); }
733 inline null_stream
operator<<(std::ostream& (*f)(std::ostream&)) {
return null_stream(); }
737 template <
bool dostuff>
738 struct log_stream_dispatch {};
741 struct log_stream_dispatch<true> {
742 inline static file_logger& exec(
int lineloglevel,
const char* file,
const char*
function,
int line,
bool do_start =
true) {
744 if(cppipc::must_cancel()) {
745 log_and_throw(
"Canceled by user.");
749 return global_logger().start_stream(lineloglevel, file,
function, line, do_start);
754 struct log_stream_dispatch<false> {
755 inline static null_stream exec(
int lineloglevel,
const char* file,
const char*
function,
int line,
bool do_start =
true) {
758 if(cppipc::must_cancel()) {
759 log_and_throw(
"Canceled by user.");
762 return null_stream();
767 #define TEXTCOLOR_RESET 0 768 #define TEXTCOLOR_BRIGHT 1 769 #define TEXTCOLOR_DIM 2 770 #define TEXTCOLOR_UNDERLINE 3 771 #define TEXTCOLOR_BLINK 4 772 #define TEXTCOLOR_REVERSE 7 773 #define TEXTCOLOR_HIDDEN 8 775 #define TEXTCOLOR_BLACK 0 776 #define TEXTCOLOR_RED 1 777 #define TEXTCOLOR_GREEN 2 778 #define TEXTCOLOR_YELLOW 3 779 #define TEXTCOLOR_BLUE 4 780 #define TEXTCOLOR_MAGENTA 5 781 #define TEXTCOLOR_CYAN 6 782 #define TEXTCOLOR_WHITE 7 784 void textcolor(FILE* handle,
int attr,
int fg);
785 std::string textcolor(
int attr,
int fg);
786 void reset_color(FILE* handle);
787 std::string reset_color();
int get_log_level()
Returns the current logger level.
void add_observer(int loglevel, std::function< void(int lineloglevel, const char *buf, size_t len)> callback_fn)
std::string get_log_file(void)
Returns the current logger file.
file_logger & operator<<(std::ostream &(*f)(std::ostream &))
static std::ostream & operator<<(std::ostream &out, const uint128_t &x)
Enables printing of uint128_t values.
std::function< void(int lineloglevel, const char *buf, size_t len)> get_observer(int loglevel)
void set_log_level(int new_log_level)
file_logger & operator<<(T a)
void set_log_to_console(bool consolelog, bool _log_to_stderr=false)
file_logger & operator<<(const char *a)
bool get_log_to_console()
Returns true if output is being written to stderr.
file_logger & global_logger()
void _log(int loglevel, const char *file, const char *function, size_t line, const char *fmt, va_list arg)