diff --git a/example/example.cpp b/example/example.cpp index 48c4b19e..b1b2e32f 100644 --- a/example/example.cpp +++ b/example/example.cpp @@ -47,7 +47,9 @@ int main(int, char *[]) // Create a file rotating logger with 5mb size max and 3 rotated files auto rotating_logger = spd::rotating_logger_mt("some_logger_name", "logs/rotating.txt", 1048576 * 5, 3); for (int i = 0; i < 10; ++i) + { rotating_logger->info("{} * {} equals {:>10}", i, i, i * i); + } // Create a daily logger - a new file is created every day on 2:30am auto daily_logger = spd::daily_logger_mt("daily_logger", "logs/daily.txt", 2, 30); @@ -106,7 +108,9 @@ void async_example() spdlog::set_async_mode(q_size); auto async_file = spd::daily_logger_st("async_file_logger", "logs/async_log.txt"); for (int i = 0; i < 100; ++i) + { async_file->info("Async message #{}", i); + } } // syslog example (linux/osx/freebsd) diff --git a/include/spdlog/details/async_log_helper.h b/include/spdlog/details/async_log_helper.h index 569e8e48..a7780740 100644 --- a/include/spdlog/details/async_log_helper.h +++ b/include/spdlog/details/async_log_helper.h @@ -247,13 +247,17 @@ inline void spdlog::details::async_log_helper::flush(bool wait_for_q) { push_msg(async_msg(async_msg_type::flush)); if (wait_for_q) + { wait_empty_q(); // return when queue is empty + } } inline void spdlog::details::async_log_helper::worker_loop() { if (_worker_warmup_cb) + { _worker_warmup_cb(); + } auto last_pop = details::os::now(); auto last_flush = last_pop; auto active = true; @@ -273,7 +277,9 @@ inline void spdlog::details::async_log_helper::worker_loop() } } if (_worker_teardown_cb) + { _worker_teardown_cb(); + } } // process next message in the queue @@ -327,7 +333,9 @@ inline void spdlog::details::async_log_helper::handle_flush_interval(log_clock:: if (should_flush) { for (auto &s : _sinks) + { s->flush(); + } now = last_flush = details::os::now(); _flush_requested = false; } @@ -349,15 +357,21 @@ inline void spdlog::details::async_log_helper::sleep_or_yield( // spin upto 50 micros if (time_since_op <= microseconds(50)) + { return; + } // yield upto 150 micros if (time_since_op <= microseconds(100)) + { return std::this_thread::yield(); + } // sleep for 20 ms upto 200 ms if (time_since_op <= milliseconds(200)) + { return details::os::sleep_for_millis(20); + } // sleep for 500 ms return details::os::sleep_for_millis(500); diff --git a/include/spdlog/details/async_logger_impl.h b/include/spdlog/details/async_logger_impl.h index 36e2ec68..748a53ac 100644 --- a/include/spdlog/details/async_logger_impl.h +++ b/include/spdlog/details/async_logger_impl.h @@ -79,7 +79,9 @@ inline void spdlog::async_logger::_sink_it(details::log_msg &msg) #endif _async_log_helper->log(msg); if (_should_flush_on(msg)) + { _async_log_helper->flush(false); // do async flush + } } catch (const std::exception &ex) { diff --git a/include/spdlog/details/file_helper.h b/include/spdlog/details/file_helper.h index dc0fa141..d30a79b7 100644 --- a/include/spdlog/details/file_helper.h +++ b/include/spdlog/details/file_helper.h @@ -47,7 +47,9 @@ public: for (int tries = 0; tries < open_tries; ++tries) { if (!os::fopen_s(&_fd, fname, mode)) + { return; + } details::os::sleep_for_millis(open_interval); } @@ -58,7 +60,9 @@ public: void reopen(bool truncate) { if (_filename.empty()) + { throw spdlog_ex("Failed re opening file - was not opened before"); + } open(_filename, truncate); } @@ -81,7 +85,9 @@ public: size_t msg_size = msg.formatted.size(); auto data = msg.formatted.data(); if (std::fwrite(data, 1, msg_size, _fd) != msg_size) + { throw spdlog_ex("Failed writing to file " + os::filename_to_str(_filename), errno); + } } size_t size() const @@ -122,12 +128,16 @@ public: // no valid extension found - return whole path and empty string as extension if (ext_index == filename_t::npos || ext_index == 0 || ext_index == fname.size() - 1) + { return std::make_tuple(fname, spdlog::filename_t()); + } // treat casese like "/etc/rc.d/somelogfile or "/abc/.hiddenfile" auto folder_index = fname.rfind(details::os::folder_sep); if (folder_index != fname.npos && folder_index >= ext_index - 1) + { return std::make_tuple(fname, spdlog::filename_t()); + } // finally - return a valid base and extension tuple return std::make_tuple(fname.substr(0, ext_index), fname.substr(ext_index)); diff --git a/include/spdlog/details/logger_impl.h b/include/spdlog/details/logger_impl.h index 38ff0b8f..d5487249 100644 --- a/include/spdlog/details/logger_impl.h +++ b/include/spdlog/details/logger_impl.h @@ -54,7 +54,9 @@ template inline void spdlog::logger::log(level::level_enum lvl, const char *fmt, const Args &... args) { if (!should_log(lvl)) + { return; + } try { @@ -82,7 +84,9 @@ template inline void spdlog::logger::log(level::level_enum lvl, const char *msg) { if (!should_log(lvl)) + { return; + } try { details::log_msg log_msg(&_name, lvl); @@ -104,7 +108,9 @@ template inline void spdlog::logger::log(level::level_enum lvl, const T &msg) { if (!should_log(lvl)) + { return; + } try { details::log_msg log_msg(&_name, lvl); @@ -309,7 +315,9 @@ inline void spdlog::logger::_sink_it(details::log_msg &msg) } if (_should_flush_on(msg)) + { flush(); + } } inline void spdlog::logger::_set_pattern(const std::string &pattern, pattern_time_type pattern_time) @@ -325,14 +333,18 @@ inline void spdlog::logger::_set_formatter(formatter_ptr msg_formatter) inline void spdlog::logger::flush() { for (auto &sink : _sinks) + { sink->flush(); + } } inline void spdlog::logger::_default_err_handler(const std::string &msg) { auto now = time(nullptr); if (now - _last_err_time < 60) + { return; + } auto tm_time = details::os::localtime(now); char date_buf[100]; std::strftime(date_buf, sizeof(date_buf), "%Y-%m-%d %H:%M:%S", &tm_time); diff --git a/include/spdlog/details/mpmc_bounded_q.h b/include/spdlog/details/mpmc_bounded_q.h index 13c7f605..fd41e4c8 100644 --- a/include/spdlog/details/mpmc_bounded_q.h +++ b/include/spdlog/details/mpmc_bounded_q.h @@ -64,10 +64,14 @@ public: { // queue size must be power of two if (!((buffer_size >= 2) && ((buffer_size & (buffer_size - 1)) == 0))) + { throw spdlog_ex("async logger queue size must be power of two"); + } for (size_t i = 0; i != buffer_size; i += 1) + { buffer_[i].sequence_.store(i, std::memory_order_relaxed); + } enqueue_pos_.store(0, std::memory_order_relaxed); dequeue_pos_.store(0, std::memory_order_relaxed); } @@ -92,7 +96,9 @@ public: if (dif == 0) { if (enqueue_pos_.compare_exchange_weak(pos, pos + 1, std::memory_order_relaxed)) + { break; + } } else if (dif < 0) { @@ -120,12 +126,18 @@ public: if (dif == 0) { if (dequeue_pos_.compare_exchange_weak(pos, pos + 1, std::memory_order_relaxed)) + { break; + } } else if (dif < 0) + { return false; + } else + { pos = dequeue_pos_.load(std::memory_order_relaxed); + } } data = std::move(cell->data_); cell->sequence_.store(pos + buffer_mask_ + 1, std::memory_order_release); diff --git a/include/spdlog/details/os.h b/include/spdlog/details/os.h index c51eb6ce..b87f00fd 100644 --- a/include/spdlog/details/os.h +++ b/include/spdlog/details/os.h @@ -148,7 +148,9 @@ inline void prevent_child_fd(FILE *f) #else auto fd = fileno(f); if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1) + { throw spdlog_ex("fcntl with FD_CLOEXEC failed", errno); + } #endif } @@ -167,7 +169,9 @@ inline bool fopen_s(FILE **fp, const filename_t &filename, const filename_t &mod #ifdef SPDLOG_PREVENT_CHILD_FD if (*fp != nullptr) + { prevent_child_fd(*fp); + } #endif return *fp == nullptr; } @@ -210,18 +214,24 @@ inline bool file_exists(const filename_t &filename) inline size_t filesize(FILE *f) { if (f == nullptr) + { throw spdlog_ex("Failed getting file size. fd is null"); + } #if defined(_WIN32) && !defined(__CYGWIN__) int fd = _fileno(f); #if _WIN64 // 64 bits struct _stat64 st; if (_fstat64(fd, &st) == 0) + { return st.st_size; + } #else // windows 32 bits long ret = _filelength(fd); if (ret >= 0) + { return static_cast(ret); + } #endif #else // unix @@ -230,11 +240,15 @@ inline size_t filesize(FILE *f) #if !defined(__FreeBSD__) && !defined(__APPLE__) && (defined(__x86_64__) || defined(__ppc64__)) && !defined(__CYGWIN__) struct stat64 st; if (fstat64(fd, &st) == 0) + { return static_cast(st.st_size); + } #else // unix 32 bits or cygwin struct stat st; if (fstat(fd, &st) == 0) + { return static_cast(st.st_size); + } #endif #endif throw spdlog_ex("Failed getting file size from fd", errno); @@ -257,9 +271,13 @@ inline int utc_minutes_offset(const std::tm &tm = details::os::localtime()) int offset = -tzinfo.Bias; if (tm.tm_isdst) + { offset -= tzinfo.DaylightBias; + } else + { offset -= tzinfo.StandardBias; + } return offset; #else @@ -386,17 +404,25 @@ inline std::string errno_str(int err_num) #ifdef _WIN32 if (strerror_s(buf, buf_size, err_num) == 0) + { return std::string(buf); + } else + { return "Unknown error"; + } #elif defined(__FreeBSD__) || defined(__APPLE__) || defined(ANDROID) || defined(__SUNPRO_CC) || \ ((_POSIX_C_SOURCE >= 200112L) && !defined(_GNU_SOURCE)) // posix version if (strerror_r(err_num, buf, buf_size) == 0) + { return std::string(buf); + } else + { return "Unknown error"; + } #else // gnu version (might not use the given buf, so its retval pointer must be used) auto err = strerror_r(err_num, buf, buf_size); // let compiler choose type diff --git a/include/spdlog/details/pattern_formatter_impl.h b/include/spdlog/details/pattern_formatter_impl.h index c12c3d68..9aa634e7 100644 --- a/include/spdlog/details/pattern_formatter_impl.h +++ b/include/spdlog/details/pattern_formatter_impl.h @@ -488,16 +488,24 @@ inline void spdlog::pattern_formatter::compile_pattern(const std::string &patter if (*it == '%') { if (user_chars) // append user chars found so far + { _formatters.push_back(std::move(user_chars)); + } if (++it != end) + { handle_flag(*it); + } else + { break; + } } else // chars not following the % sign should be displayed as is { if (!user_chars) + { user_chars = std::unique_ptr(new details::aggregate_formatter()); + } user_chars->add_ch(*it); } } diff --git a/include/spdlog/details/registry.h b/include/spdlog/details/registry.h index 46397302..339b025d 100644 --- a/include/spdlog/details/registry.h +++ b/include/spdlog/details/registry.h @@ -53,16 +53,24 @@ public: throw_if_exists(logger_name); std::shared_ptr new_logger; if (_async_mode) + { new_logger = std::make_shared(logger_name, sinks_begin, sinks_end, _async_q_size, _overflow_policy, _worker_warmup_cb, _flush_interval_ms, _worker_teardown_cb); + } else + { new_logger = std::make_shared(logger_name, sinks_begin, sinks_end); + } if (_formatter) + { new_logger->set_formatter(_formatter); + } if (_err_handler) + { new_logger->set_error_handler(_err_handler); + } new_logger->set_level(_level); new_logger->flush_on(_flush_level); @@ -84,10 +92,14 @@ public: logger_name, sinks_begin, sinks_end, queue_size, overflow_policy, worker_warmup_cb, flush_interval_ms, worker_teardown_cb); if (_formatter) + { new_logger->set_formatter(_formatter); + } if (_err_handler) + { new_logger->set_error_handler(_err_handler); + } new_logger->set_level(_level); new_logger->flush_on(_flush_level); @@ -101,7 +113,9 @@ public: { std::lock_guard lock(_mutex); for (auto &l : _loggers) + { fun(l.second); + } } void drop(const std::string &logger_name) @@ -146,7 +160,9 @@ public: std::lock_guard lock(_mutex); _formatter = f; for (auto &l : _loggers) + { l.second->set_formatter(_formatter); + } } void set_pattern(const std::string &pattern) @@ -154,14 +170,18 @@ public: std::lock_guard lock(_mutex); _formatter = std::make_shared(pattern); for (auto &l : _loggers) + { l.second->set_formatter(_formatter); + } } void set_level(level::level_enum log_level) { std::lock_guard lock(_mutex); for (auto &l : _loggers) + { l.second->set_level(log_level); + } _level = log_level; } @@ -169,14 +189,18 @@ public: { std::lock_guard lock(_mutex); for (auto &l : _loggers) + { l.second->flush_on(log_level); + } _flush_level = log_level; } void set_error_handler(log_err_handler handler) { for (auto &l : _loggers) + { l.second->set_error_handler(handler); + } _err_handler = handler; } @@ -210,7 +234,9 @@ private: void throw_if_exists(const std::string &logger_name) { if (_loggers.find(logger_name) != _loggers.end()) + { throw spdlog_ex("logger with name '" + logger_name + "' already exists"); + } } Mutex _mutex; diff --git a/include/spdlog/sinks/file_sinks.h b/include/spdlog/sinks/file_sinks.h index 7d755587..109c493a 100644 --- a/include/spdlog/sinks/file_sinks.h +++ b/include/spdlog/sinks/file_sinks.h @@ -43,7 +43,9 @@ protected: { _file_helper.write(msg); if (_force_flush) + { _file_helper.flush(); + } } void _flush() override @@ -199,7 +201,9 @@ public: , _rotation_m(rotation_minute) { if (rotation_hour < 0 || rotation_hour > 23 || rotation_minute < 0 || rotation_minute > 59) + { throw spdlog_ex("daily_file_sink: Invalid rotation time in ctor"); + } _rotation_tp = _next_rotation_tp(); _file_helper.open(FileNameCalc::calc_filename(_base_filename)); }