diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 00000000..d27def8b --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,17 @@ +cmake_minimum_required(VERSION 3.0) +project(spdlog CXX) +set(${PROJECT_NAME}_SRCS + include/spdlog/details/spdlog_impl.cc + include/spdlog/details/logger_impl.cc + include/spdlog/details/async_logger_impl.cc + include/spdlog/details/async_log_helper.cc + include/spdlog/details/format.cc + include/spdlog/details/pattern_formatter_impl.cc +) + +add_library(${PROJECT_NAME} STATIC ${${PROJECT_NAME}_SRCS}) +set_property(TARGET ${PROJECT_NAME} PROPERTY CXX_STANDARD 11) +target_compile_definitions(${PROJECT_NAME} PUBLIC SPDLOG_LIBRARY) +target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include) + +add_subdirectory(tests) diff --git a/include/spdlog/async_logger.h b/include/spdlog/async_logger.h index 517ce92f..404f0d55 100644 --- a/include/spdlog/async_logger.h +++ b/include/spdlog/async_logger.h @@ -38,7 +38,6 @@ #include #include "common.h" #include "logger.h" -#include "spdlog.h" namespace spdlog diff --git a/include/spdlog/details/async_log_helper.cc b/include/spdlog/details/async_log_helper.cc new file mode 100644 index 00000000..7fac2580 --- /dev/null +++ b/include/spdlog/details/async_log_helper.cc @@ -0,0 +1,236 @@ +/*************************************************************************/ +/* spdlog - an extremely fast and easy to use c++11 logging library. */ +/* Copyright (c) 2014 Gabi Melman. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +// async log helper : +// Process logs asynchronously using a back thread. +// +// If the internal queue of log messages reaches its max size, +// then the client call will block until there is more room. +// +// If the back thread throws during logging, a spdlog::spdlog_ex exception +// will be thrown in client's thread when tries to log the next message +#ifdef SPDLOG_LIBRARY +#include "./async_log_helper.h" +#else +#pragma once +#endif +#include "../formatter.h" +#include "../sinks/sink.h" +#include "./log_msg.h" +#include "./os.h" +#include "./config.h" + + +SPDLOG_INLINE spdlog::details::async_log_helper::async_msg::async_msg(async_msg&& other) SPDLOG_NOEXCEPT: + logger_name(std::move(other.logger_name)), + level(std::move(other.level)), + time(std::move(other.time)), + txt(std::move(other.txt)) +{ + +} + +SPDLOG_INLINE spdlog::details::async_log_helper::async_msg& spdlog::details::async_log_helper::async_msg::operator=(async_msg&& other) SPDLOG_NOEXCEPT +{ + logger_name = std::move(other.logger_name); + level = other.level; + time = std::move(other.time); + thread_id = other.thread_id; + txt = std::move(other.txt); + return *this; +} + +// construct from log_msg +SPDLOG_INLINE spdlog::details::async_log_helper::async_msg::async_msg(const details::log_msg& m) : + logger_name(m.logger_name), + level(m.level), + time(m.time), + thread_id(m.thread_id), + txt(m.raw.data(), m.raw.size()) +{ + +} + + +// copy into log_msg +SPDLOG_INLINE void spdlog::details::async_log_helper::async_msg::fill_log_msg(log_msg &msg) +{ + msg.clear(); + msg.logger_name = logger_name; + msg.level = level; + msg.time = time; + msg.thread_id = thread_id; + msg.raw << txt; +} + +/////////////////////////////////////////////////////////////////////////////// +// async_sink class implementation +/////////////////////////////////////////////////////////////////////////////// +SPDLOG_INLINE spdlog::details::async_log_helper::async_log_helper(formatter_ptr formatter, const std::vector& sinks, size_t queue_size, const async_overflow_policy overflow_policy, const std::function& worker_warmup_cb, const std::chrono::milliseconds& flush_interval_ms): + _formatter(formatter), + _sinks(sinks), + _q(queue_size), + _overflow_policy(overflow_policy), + _worker_warmup_cb(worker_warmup_cb), + _flush_interval_ms(flush_interval_ms), + _worker_thread(&async_log_helper::worker_loop, this) +{} + +// Send to the worker thread termination message(level=off) +// and wait for it to finish gracefully +SPDLOG_INLINE spdlog::details::async_log_helper::~async_log_helper() +{ + + try + { + log(log_msg(level::off)); + _worker_thread.join(); + } + catch (...) //Dont crash if thread not joinable + {} +} + + +//Try to push and block until succeeded +SPDLOG_INLINE void spdlog::details::async_log_helper::log(const details::log_msg& msg) +{ + throw_if_bad_worker(); + async_msg new_msg(msg); + if (!_q.enqueue(std::move(new_msg)) && _overflow_policy != async_overflow_policy::discard_log_msg) + { + auto last_op_time = details::os::now(); + auto now = last_op_time; + do + { + now = details::os::now(); + sleep_or_yield(now, last_op_time); + } + while (!_q.enqueue(std::move(new_msg))); + } + +} + +SPDLOG_INLINE void spdlog::details::async_log_helper::worker_loop() +{ + try + { + if (_worker_warmup_cb) _worker_warmup_cb(); + auto last_pop = details::os::now(); + auto last_flush = last_pop; + while(process_next_msg(last_pop, last_flush)); + } + catch (const std::exception& ex) + { + _last_workerthread_ex = std::make_shared(std::string("async_logger worker thread exception: ") + ex.what()); + } + catch (...) + { + _last_workerthread_ex = std::make_shared("async_logger worker thread exception"); + } +} + +// process next message in the queue +// return true if this thread should still be active (no msg with level::off was received) +SPDLOG_INLINE bool spdlog::details::async_log_helper::process_next_msg(log_clock::time_point& last_pop, log_clock::time_point& last_flush) +{ + + async_msg incoming_async_msg; + log_msg incoming_log_msg; + + if (_q.dequeue(incoming_async_msg)) + { + last_pop = details::os::now(); + + if(incoming_async_msg.level == level::off) + return false; + + incoming_async_msg.fill_log_msg(incoming_log_msg); + _formatter->format(incoming_log_msg); + for (auto &s : _sinks) + s->log(incoming_log_msg); + } + else //empty queue + { + auto now = details::os::now(); + handle_flush_interval(now, last_flush); + sleep_or_yield(now, last_pop); + } + return true; +} + +SPDLOG_INLINE void spdlog::details::async_log_helper::handle_flush_interval(log_clock::time_point& now, log_clock::time_point& last_flush) +{ + if (_flush_interval_ms != std::chrono::milliseconds::zero() && now - last_flush >= _flush_interval_ms) + { + for (auto &s : _sinks) + s->flush(); + now = last_flush = details::os::now(); + } +} +SPDLOG_INLINE void spdlog::details::async_log_helper::set_formatter(formatter_ptr msg_formatter) +{ + _formatter = msg_formatter; +} + + +// sleep,yield or return immediatly using the time passed since last message as a hint +SPDLOG_INLINE void spdlog::details::async_log_helper::sleep_or_yield(const spdlog::log_clock::time_point& now, const spdlog::log_clock::time_point& last_op_time) +{ + using std::chrono::milliseconds; + using namespace std::this_thread; + + auto time_since_op = now - last_op_time; + + // spin upto 1 ms + if (time_since_op <= milliseconds(1)) + return; + + // yield upto 10ms + if (time_since_op <= milliseconds(10)) + return yield(); + + + // sleep for half of duration since last op + if (time_since_op <= milliseconds(100)) + return sleep_for(time_since_op / 2); + + return sleep_for(milliseconds(100)); +} + +// throw if the worker thread threw an exception or not active +SPDLOG_INLINE void spdlog::details::async_log_helper::throw_if_bad_worker() +{ + if (_last_workerthread_ex) + { + auto ex = std::move(_last_workerthread_ex); + throw *ex; + } +} + + + + + + + diff --git a/include/spdlog/details/async_log_helper.h b/include/spdlog/details/async_log_helper.h index 59c1b2dc..aeff74a2 100644 --- a/include/spdlog/details/async_log_helper.h +++ b/include/spdlog/details/async_log_helper.h @@ -32,24 +32,17 @@ // will be thrown in client's thread when tries to log the next message #pragma once - -#include #include -#include -#include +#include #include "../common.h" -#include "../sinks/sink.h" #include "./mpmc_bounded_q.h" -#include "./log_msg.h" -#include "./format.h" -#include "os.h" - namespace spdlog { namespace details { +class log_msg; class async_log_helper { @@ -66,46 +59,19 @@ class async_log_helper async_msg() = default; ~async_msg() = default; -async_msg(async_msg&& other) SPDLOG_NOEXCEPT: - logger_name(std::move(other.logger_name)), - level(std::move(other.level)), - time(std::move(other.time)), - txt(std::move(other.txt)) - {} - - async_msg& operator=(async_msg&& other) SPDLOG_NOEXCEPT - { - logger_name = std::move(other.logger_name); - level = other.level; - time = std::move(other.time); - thread_id = other.thread_id; - txt = std::move(other.txt); - return *this; - } + async_msg(async_msg&& other) SPDLOG_NOEXCEPT; + + async_msg& operator=(async_msg&& other) SPDLOG_NOEXCEPT; // never copy or assign. should only be moved.. async_msg(const async_msg&) = delete; async_msg& operator=(async_msg& other) = delete; // construct from log_msg - async_msg(const details::log_msg& m) : - logger_name(m.logger_name), - level(m.level), - time(m.time), - thread_id(m.thread_id), - txt(m.raw.data(), m.raw.size()) - {} + async_msg(const details::log_msg& m); // copy into log_msg - void fill_log_msg(log_msg &msg) - { - msg.clear(); - msg.logger_name = logger_name; - msg.level = level; - msg.time = time; - msg.thread_id = thread_id; - msg.raw << txt; - } + void fill_log_msg(log_msg &msg); }; public: @@ -174,153 +140,6 @@ private: } } -/////////////////////////////////////////////////////////////////////////////// -// async_sink class implementation -/////////////////////////////////////////////////////////////////////////////// -inline spdlog::details::async_log_helper::async_log_helper(formatter_ptr formatter, const std::vector& sinks, size_t queue_size, const async_overflow_policy overflow_policy, const std::function& worker_warmup_cb, const std::chrono::milliseconds& flush_interval_ms): - _formatter(formatter), - _sinks(sinks), - _q(queue_size), - _overflow_policy(overflow_policy), - _worker_warmup_cb(worker_warmup_cb), - _flush_interval_ms(flush_interval_ms), - _worker_thread(&async_log_helper::worker_loop, this) -{} - -// Send to the worker thread termination message(level=off) -// and wait for it to finish gracefully -inline spdlog::details::async_log_helper::~async_log_helper() -{ - - try - { - log(log_msg(level::off)); - _worker_thread.join(); - } - catch (...) //Dont crash if thread not joinable - {} -} - - -//Try to push and block until succeeded -inline void spdlog::details::async_log_helper::log(const details::log_msg& msg) -{ - throw_if_bad_worker(); - async_msg new_msg(msg); - if (!_q.enqueue(std::move(new_msg)) && _overflow_policy != async_overflow_policy::discard_log_msg) - { - auto last_op_time = details::os::now(); - auto now = last_op_time; - do - { - now = details::os::now(); - sleep_or_yield(now, last_op_time); - } - while (!_q.enqueue(std::move(new_msg))); - } - -} - -inline void spdlog::details::async_log_helper::worker_loop() -{ - try - { - if (_worker_warmup_cb) _worker_warmup_cb(); - auto last_pop = details::os::now(); - auto last_flush = last_pop; - while(process_next_msg(last_pop, last_flush)); - } - catch (const std::exception& ex) - { - _last_workerthread_ex = std::make_shared(std::string("async_logger worker thread exception: ") + ex.what()); - } - catch (...) - { - _last_workerthread_ex = std::make_shared("async_logger worker thread exception"); - } -} - -// process next message in the queue -// return true if this thread should still be active (no msg with level::off was received) -inline bool spdlog::details::async_log_helper::process_next_msg(log_clock::time_point& last_pop, log_clock::time_point& last_flush) -{ - - async_msg incoming_async_msg; - log_msg incoming_log_msg; - - if (_q.dequeue(incoming_async_msg)) - { - last_pop = details::os::now(); - - if(incoming_async_msg.level == level::off) - return false; - - incoming_async_msg.fill_log_msg(incoming_log_msg); - _formatter->format(incoming_log_msg); - for (auto &s : _sinks) - s->log(incoming_log_msg); - } - else //empty queue - { - auto now = details::os::now(); - handle_flush_interval(now, last_flush); - sleep_or_yield(now, last_pop); - } - return true; -} - -inline void spdlog::details::async_log_helper::handle_flush_interval(log_clock::time_point& now, log_clock::time_point& last_flush) -{ - if (_flush_interval_ms != std::chrono::milliseconds::zero() && now - last_flush >= _flush_interval_ms) - { - for (auto &s : _sinks) - s->flush(); - now = last_flush = details::os::now(); - } -} -inline void spdlog::details::async_log_helper::set_formatter(formatter_ptr msg_formatter) -{ - _formatter = msg_formatter; -} - - -// sleep,yield or return immediatly using the time passed since last message as a hint -inline void spdlog::details::async_log_helper::sleep_or_yield(const spdlog::log_clock::time_point& now, const spdlog::log_clock::time_point& last_op_time) -{ - using std::chrono::milliseconds; - using namespace std::this_thread; - - auto time_since_op = now - last_op_time; - - // spin upto 1 ms - if (time_since_op <= milliseconds(1)) - return; - - // yield upto 10ms - if (time_since_op <= milliseconds(10)) - return yield(); - - - // sleep for half of duration since last op - if (time_since_op <= milliseconds(100)) - return sleep_for(time_since_op / 2); - - return sleep_for(milliseconds(100)); -} - -// throw if the worker thread threw an exception or not active -inline void spdlog::details::async_log_helper::throw_if_bad_worker() -{ - if (_last_workerthread_ex) - { - auto ex = std::move(_last_workerthread_ex); - throw *ex; - } -} - - - - - - - +#ifndef SPDLOG_LIBRARY +#include "./async_log_helper.cc" +#endif diff --git a/include/spdlog/details/async_logger_impl.cc b/include/spdlog/details/async_logger_impl.cc new file mode 100644 index 00000000..38b06cab --- /dev/null +++ b/include/spdlog/details/async_logger_impl.cc @@ -0,0 +1,67 @@ +/*************************************************************************/ +/* spdlog - an extremely fast and easy to use c++11 logging library. */ +/* Copyright (c) 2014 Gabi Melman. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#ifdef SPDLOG_LIBRARY +#include "../async_logger.h" +#else +#pragma once +#endif + + +#include "./async_log_helper.h" +#include "./config.h" + +SPDLOG_INLINE spdlog::async_logger::async_logger(const std::string& logger_name, + sinks_init_list sinks, + size_t queue_size, + const async_overflow_policy overflow_policy, + const std::function& worker_warmup_cb, + const std::chrono::milliseconds& flush_interval_ms) : + async_logger(logger_name, sinks.begin(), sinks.end(), queue_size, overflow_policy, worker_warmup_cb, flush_interval_ms) {} + +SPDLOG_INLINE spdlog::async_logger::async_logger(const std::string& logger_name, + sink_ptr single_sink, + size_t queue_size, + const async_overflow_policy overflow_policy, + const std::function& worker_warmup_cb, + const std::chrono::milliseconds& flush_interval_ms) : + async_logger(logger_name, { single_sink }, queue_size, overflow_policy, worker_warmup_cb, flush_interval_ms) {} + + +SPDLOG_INLINE void spdlog::async_logger::_set_formatter(spdlog::formatter_ptr msg_formatter) +{ + _formatter = msg_formatter; + _async_log_helper->set_formatter(_formatter); +} + +SPDLOG_INLINE void spdlog::async_logger::_set_pattern(const std::string& pattern) +{ + _formatter = std::make_shared(pattern); + _async_log_helper->set_formatter(_formatter); +} + + +SPDLOG_INLINE void spdlog::async_logger::_log_msg(details::log_msg& msg) +{ + _async_log_helper->log(msg); +} diff --git a/include/spdlog/details/async_logger_impl.h b/include/spdlog/details/async_logger_impl.h index f60407e3..37377199 100644 --- a/include/spdlog/details/async_logger_impl.h +++ b/include/spdlog/details/async_logger_impl.h @@ -46,37 +46,6 @@ inline spdlog::async_logger::async_logger(const std::string& logger_name, { } -inline spdlog::async_logger::async_logger(const std::string& logger_name, - sinks_init_list sinks, - size_t queue_size, - const async_overflow_policy overflow_policy, - const std::function& worker_warmup_cb, - const std::chrono::milliseconds& flush_interval_ms) : - async_logger(logger_name, sinks.begin(), sinks.end(), queue_size, overflow_policy, worker_warmup_cb, flush_interval_ms) {} - -inline spdlog::async_logger::async_logger(const std::string& logger_name, - sink_ptr single_sink, - size_t queue_size, - const async_overflow_policy overflow_policy, - const std::function& worker_warmup_cb, - const std::chrono::milliseconds& flush_interval_ms) : - async_logger(logger_name, { single_sink }, queue_size, overflow_policy, worker_warmup_cb, flush_interval_ms) {} - - -inline void spdlog::async_logger::_set_formatter(spdlog::formatter_ptr msg_formatter) -{ - _formatter = msg_formatter; - _async_log_helper->set_formatter(_formatter); -} - -inline void spdlog::async_logger::_set_pattern(const std::string& pattern) -{ - _formatter = std::make_shared(pattern); - _async_log_helper->set_formatter(_formatter); -} - - -inline void spdlog::async_logger::_log_msg(details::log_msg& msg) -{ - _async_log_helper->log(msg); -} +#ifndef SPDLOG_LIBRARY +#include "./async_logger_impl.cc" +#endif diff --git a/include/spdlog/details/config.h b/include/spdlog/details/config.h new file mode 100644 index 00000000..ad5ee714 --- /dev/null +++ b/include/spdlog/details/config.h @@ -0,0 +1,30 @@ +/*************************************************************************/ +/* spdlog - an extremely fast and easy to use c++11 logging library. */ +/* Copyright (c) 2015 Gabi Melman. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#pragma once +#include "../tweakme.h" +#ifdef SPDLOG_LIBRARY +#define SPDLOG_INLINE +#else +#define SPDLOG_INLINE inline +#endif diff --git a/include/spdlog/details/flag_formatter.h b/include/spdlog/details/flag_formatter.h new file mode 100644 index 00000000..93d5c8f2 --- /dev/null +++ b/include/spdlog/details/flag_formatter.h @@ -0,0 +1,39 @@ +/*************************************************************************/ +/* spdlog - an extremely fast and easy to use c++11 logging library. */ +/* Copyright (c) 2014 Gabi Melman. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#pragma once +#include + +namespace spdlog +{ +namespace details +{ +class log_msg; +class flag_formatter +{ +public: + virtual ~flag_formatter() {} + virtual void format(details::log_msg& msg, const std::tm& tm_time) = 0; +}; +} // ns details +} // ns spdlog diff --git a/include/spdlog/details/format.h b/include/spdlog/details/format.h index bf02fc72..9af3dfdd 100644 --- a/include/spdlog/details/format.h +++ b/include/spdlog/details/format.h @@ -27,7 +27,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef FMT_FORMAT_H_ #define FMT_FORMAT_H_ +#ifndef SPDLOG_LIBRARY #define FMT_HEADER_ONLY +#endif #include @@ -3175,4 +3177,4 @@ FMT_VARIADIC(int, fprintf, std::FILE *, CStringRef) # include "format.cc" #endif -#endif // FMT_FORMAT_H_ \ No newline at end of file +#endif // FMT_FORMAT_H_ diff --git a/include/spdlog/details/line_logger.h b/include/spdlog/details/line_logger.h index 80d7cc13..5218ae79 100644 --- a/include/spdlog/details/line_logger.h +++ b/include/spdlog/details/line_logger.h @@ -26,6 +26,7 @@ #include #include "../common.h" #include "../logger.h" +#include "./os.h" // Line logger class - aggregates operator<< calls to fast ostream // and logs upon destruction diff --git a/include/spdlog/details/logger_impl.cc b/include/spdlog/details/logger_impl.cc new file mode 100644 index 00000000..67150b5f --- /dev/null +++ b/include/spdlog/details/logger_impl.cc @@ -0,0 +1,163 @@ +/*************************************************************************/ +/* spdlog - an extremely fast and easy to use c++11 logging library. */ +/* Copyright (c) 2014 Gabi Melman. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifdef SPDLOG_LIBRARY +#include "../logger.h" +#else +#pragma once +#endif +#include "../sinks/sink.h" +#include "./line_logger.h" +#include "./config.h" + +// ctor with sinks as init list +SPDLOG_INLINE spdlog::logger::logger(const std::string& logger_name, sinks_init_list sinks_list) : + logger(logger_name, sinks_list.begin(), sinks_list.end()) {} + + +// ctor with single sink +SPDLOG_INLINE spdlog::logger::logger(const std::string& logger_name, spdlog::sink_ptr single_sink) : + logger(logger_name, { + single_sink +}) {} + + +SPDLOG_INLINE spdlog::logger::~logger() = default; + + +SPDLOG_INLINE void spdlog::logger::set_formatter(spdlog::formatter_ptr msg_formatter) +{ + _set_formatter(msg_formatter); +} + +SPDLOG_INLINE void spdlog::logger::set_pattern(const std::string& pattern) +{ + _set_pattern(pattern); +} + +// +// log only if given level>=logger's log level +// + +SPDLOG_INLINE spdlog::details::line_logger spdlog::logger::_log_if_enabled(level::level_enum lvl) +{ + return details::line_logger(this, lvl, should_log(lvl)); +} + + +// +// logger.info() << ".." call style +// +SPDLOG_INLINE spdlog::details::line_logger spdlog::logger::trace() +{ + return _log_if_enabled(level::trace); +} + +SPDLOG_INLINE spdlog::details::line_logger spdlog::logger::debug() +{ + return _log_if_enabled(level::debug); +} + +SPDLOG_INLINE spdlog::details::line_logger spdlog::logger::info() +{ + return _log_if_enabled(level::info); +} + +SPDLOG_INLINE spdlog::details::line_logger spdlog::logger::notice() +{ + return _log_if_enabled(level::notice); +} + +SPDLOG_INLINE spdlog::details::line_logger spdlog::logger::warn() +{ + return _log_if_enabled(level::warn); +} + +SPDLOG_INLINE spdlog::details::line_logger spdlog::logger::error() +{ + return _log_if_enabled(level::err); +} + +SPDLOG_INLINE spdlog::details::line_logger spdlog::logger::critical() +{ + return _log_if_enabled(level::critical); +} + +SPDLOG_INLINE spdlog::details::line_logger spdlog::logger::alert() +{ + return _log_if_enabled(level::alert); +} + +SPDLOG_INLINE spdlog::details::line_logger spdlog::logger::emerg() +{ + return _log_if_enabled(level::emerg); +} + +// +// name and level +// +SPDLOG_INLINE const std::string& spdlog::logger::name() const +{ + return _name; +} + +SPDLOG_INLINE void spdlog::logger::set_level(spdlog::level::level_enum log_level) +{ + _level.store(log_level); +} + +SPDLOG_INLINE spdlog::level::level_enum spdlog::logger::level() const +{ + return static_cast(_level.load(std::memory_order_relaxed)); +} + +SPDLOG_INLINE bool spdlog::logger::should_log(spdlog::level::level_enum msg_level) const +{ + return msg_level >= _level.load(std::memory_order_relaxed); +} + +// +// protected virtual called at end of each user log call (if enabled) by the line_logger +// +SPDLOG_INLINE void spdlog::logger::_log_msg(details::log_msg& msg) +{ + _formatter->format(msg); + for (auto &sink : _sinks) + sink->log(msg); +} + +SPDLOG_INLINE void spdlog::logger::_set_pattern(const std::string& pattern) +{ + _formatter = std::make_shared(pattern); +} + +SPDLOG_INLINE void spdlog::logger::_set_formatter(formatter_ptr msg_formatter) +{ + _formatter = msg_formatter; +} + +SPDLOG_INLINE void spdlog::logger::flush() { + for (auto& sink : _sinks) + sink->flush(); +} diff --git a/include/spdlog/details/logger_impl.h b/include/spdlog/details/logger_impl.h index d658ac03..b944cfcf 100644 --- a/include/spdlog/details/logger_impl.h +++ b/include/spdlog/details/logger_impl.h @@ -26,14 +26,16 @@ // // Logger implementation // - +#include "../formatter.h" +#include "./flag_formatter.h" +#include "./log_msg.h" #include "./line_logger.h" // create logger with given name, sinks and the default pattern formatter // all other ctors will call this one template -inline spdlog::logger::logger(const std::string& logger_name, const It& begin, const It& end) : +spdlog::logger::logger(const std::string& logger_name, const It& begin, const It& end) : _name(logger_name), _sinks(begin, end), _formatter(std::make_shared("%+")) @@ -43,31 +45,6 @@ inline spdlog::logger::logger(const std::string& logger_name, const It& begin, c _level = level::info; } -// ctor with sinks as init list -inline spdlog::logger::logger(const std::string& logger_name, sinks_init_list sinks_list) : - logger(logger_name, sinks_list.begin(), sinks_list.end()) {} - - -// ctor with single sink -inline spdlog::logger::logger(const std::string& logger_name, spdlog::sink_ptr single_sink) : - logger(logger_name, { - single_sink -}) {} - - -inline spdlog::logger::~logger() = default; - - -inline void spdlog::logger::set_formatter(spdlog::formatter_ptr msg_formatter) -{ - _set_formatter(msg_formatter); -} - -inline void spdlog::logger::set_pattern(const std::string& pattern) -{ - _set_pattern(pattern); -} - // // log only if given level>=logger's log level // @@ -82,11 +59,6 @@ inline spdlog::details::line_logger spdlog::logger::_log_if_enabled(level::level return l; } -inline spdlog::details::line_logger spdlog::logger::_log_if_enabled(level::level_enum lvl) -{ - return details::line_logger(this, lvl, should_log(lvl)); -} - template inline spdlog::details::line_logger spdlog::logger::_log_if_enabled(level::level_enum lvl, const T& msg) { @@ -211,58 +183,6 @@ inline spdlog::details::line_logger spdlog::logger::emerg(const T& msg) return _log_if_enabled(level::emerg, msg); } - - - -// -// logger.info() << ".." call style -// -inline spdlog::details::line_logger spdlog::logger::trace() -{ - return _log_if_enabled(level::trace); -} - -inline spdlog::details::line_logger spdlog::logger::debug() -{ - return _log_if_enabled(level::debug); -} - -inline spdlog::details::line_logger spdlog::logger::info() -{ - return _log_if_enabled(level::info); -} - -inline spdlog::details::line_logger spdlog::logger::notice() -{ - return _log_if_enabled(level::notice); -} - -inline spdlog::details::line_logger spdlog::logger::warn() -{ - return _log_if_enabled(level::warn); -} - -inline spdlog::details::line_logger spdlog::logger::error() -{ - return _log_if_enabled(level::err); -} - -inline spdlog::details::line_logger spdlog::logger::critical() -{ - return _log_if_enabled(level::critical); -} - -inline spdlog::details::line_logger spdlog::logger::alert() -{ - return _log_if_enabled(level::alert); -} - -inline spdlog::details::line_logger spdlog::logger::emerg() -{ - return _log_if_enabled(level::emerg); -} - - // always log, no matter what is the actual logger's log level template inline spdlog::details::line_logger spdlog::logger::force_log(level::level_enum lvl, const char* fmt, const Args&... args) @@ -272,49 +192,6 @@ inline spdlog::details::line_logger spdlog::logger::force_log(level::level_enum return l; } -// -// name and level -// -inline const std::string& spdlog::logger::name() const -{ - return _name; -} - -inline void spdlog::logger::set_level(spdlog::level::level_enum log_level) -{ - _level.store(log_level); -} - -inline spdlog::level::level_enum spdlog::logger::level() const -{ - return static_cast(_level.load(std::memory_order_relaxed)); -} - -inline bool spdlog::logger::should_log(spdlog::level::level_enum msg_level) const -{ - return msg_level >= _level.load(std::memory_order_relaxed); -} - -// -// protected virtual called at end of each user log call (if enabled) by the line_logger -// -inline void spdlog::logger::_log_msg(details::log_msg& msg) -{ - _formatter->format(msg); - for (auto &sink : _sinks) - sink->log(msg); -} - -inline void spdlog::logger::_set_pattern(const std::string& pattern) -{ - _formatter = std::make_shared(pattern); -} -inline void spdlog::logger::_set_formatter(formatter_ptr msg_formatter) -{ - _formatter = msg_formatter; -} - -inline void spdlog::logger::flush() { - for (auto& sink : _sinks) - sink->flush(); -} \ No newline at end of file +#ifndef SPDLOG_LIBRARY +#include "./logger_impl.cc" +#endif diff --git a/include/spdlog/details/pattern_formatter_impl.h b/include/spdlog/details/pattern_formatter_impl.cc similarity index 97% rename from include/spdlog/details/pattern_formatter_impl.h rename to include/spdlog/details/pattern_formatter_impl.cc index 137037ec..45575f81 100644 --- a/include/spdlog/details/pattern_formatter_impl.h +++ b/include/spdlog/details/pattern_formatter_impl.cc @@ -21,30 +21,24 @@ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ - +#ifdef SPDLOG_LIBRARY +#include "../formatter.h" +#else #pragma once +#endif -#include -#include -#include -#include -#include - +#include -#include "../formatter.h" +#include "./flag_formatter.h" #include "./log_msg.h" #include "./os.h" +#include "./config.h" namespace spdlog { namespace details { -class flag_formatter -{ -public: - virtual ~flag_formatter() {} - virtual void format(details::log_msg& msg, const std::tm& tm_time) = 0; -}; + /////////////////////////////////////////////////////////////////////// // name & level pattern appenders @@ -462,12 +456,12 @@ class full_formatter :public flag_formatter /////////////////////////////////////////////////////////////////////////////// // pattern_formatter inline impl /////////////////////////////////////////////////////////////////////////////// -inline spdlog::pattern_formatter::pattern_formatter(const std::string& pattern) +SPDLOG_INLINE spdlog::pattern_formatter::pattern_formatter(const std::string& pattern) { compile_pattern(pattern); } -inline void spdlog::pattern_formatter::compile_pattern(const std::string& pattern) +SPDLOG_INLINE void spdlog::pattern_formatter::compile_pattern(const std::string& pattern) { auto end = pattern.end(); std::unique_ptr user_chars; @@ -496,7 +490,7 @@ inline void spdlog::pattern_formatter::compile_pattern(const std::string& patter } } -inline void spdlog::pattern_formatter::handle_flag(char flag) +SPDLOG_INLINE void spdlog::pattern_formatter::handle_flag(char flag) { switch (flag) { @@ -623,7 +617,7 @@ inline void spdlog::pattern_formatter::handle_flag(char flag) } -inline void spdlog::pattern_formatter::format(details::log_msg& msg) +SPDLOG_INLINE void spdlog::pattern_formatter::format(details::log_msg& msg) { try { diff --git a/include/spdlog/details/registry.h b/include/spdlog/details/registry.h index fd8e4be9..60137775 100644 --- a/include/spdlog/details/registry.h +++ b/include/spdlog/details/registry.h @@ -27,16 +27,11 @@ // An attempt to create a logger with an alreasy existing name will be ignored // If user requests a non existing logger, nullptr will be returned // This class is thread safe - -#include #include #include -#include -#include "./null_mutex.h" -#include "../logger.h" #include "../async_logger.h" -#include "../common.h" +#include "./flag_formatter.h" namespace spdlog { diff --git a/include/spdlog/details/spdlog_impl.cc b/include/spdlog/details/spdlog_impl.cc new file mode 100644 index 00000000..bb5afe87 --- /dev/null +++ b/include/spdlog/details/spdlog_impl.cc @@ -0,0 +1,146 @@ +/*************************************************************************/ +/* spdlog - an extremely fast and easy to use c++11 logging library. */ +/* Copyright (c) 2014 Gabi Melman. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#ifdef SPDLOG_LIBRARY +#include "../spdlog.h" +#else +#pragma once +#endif + +// +// Global registry functions +// +#include "./registry.h" +#include "../sinks/file_sinks.h" +#include "../sinks/stdout_sinks.h" +#include "../sinks/syslog_sink.h" +#include "./config.h" + +namespace spdlog +{ +SPDLOG_INLINE void register_logger(std::shared_ptr logger) +{ + return details::registry::instance().register_logger(logger); +} + +SPDLOG_INLINE std::shared_ptr get(const std::string& name) +{ + return details::registry::instance().get(name); +} + +SPDLOG_INLINE void drop(const std::string &name) +{ + details::registry::instance().drop(name); +} + +// Create multi/single threaded rotating file logger +SPDLOG_INLINE std::shared_ptr rotating_logger_mt(const std::string& logger_name, const std::string& filename, size_t max_file_size, size_t max_files, bool force_flush) +{ + return create(logger_name, filename, "txt", max_file_size, max_files, force_flush); +} + +SPDLOG_INLINE std::shared_ptr rotating_logger_st(const std::string& logger_name, const std::string& filename, size_t max_file_size, size_t max_files, bool force_flush) +{ + return create(logger_name, filename, "txt", max_file_size, max_files, force_flush); +} + +// Create file logger which creates new file at midnight): +SPDLOG_INLINE std::shared_ptr daily_logger_mt(const std::string& logger_name, const std::string& filename, int hour, int minute, bool force_flush) +{ + return create(logger_name, filename, "txt", hour, minute, force_flush); +} +SPDLOG_INLINE std::shared_ptr daily_logger_st(const std::string& logger_name, const std::string& filename, int hour, int minute, bool force_flush) +{ + return create(logger_name, filename, "txt", hour, minute, force_flush); +} + + +// Create stdout/stderr loggers +SPDLOG_INLINE std::shared_ptr stdout_logger_mt(const std::string& logger_name) +{ + return details::registry::instance().create(logger_name, sinks::stdout_sink_mt::instance()); +} + +SPDLOG_INLINE std::shared_ptr stdout_logger_st(const std::string& logger_name) +{ + return details::registry::instance().create(logger_name, sinks::stdout_sink_st::instance()); +} + +SPDLOG_INLINE std::shared_ptr stderr_logger_mt(const std::string& logger_name) +{ + return details::registry::instance().create(logger_name, sinks::stderr_sink_mt::instance()); +} + +SPDLOG_INLINE std::shared_ptr stderr_logger_st(const std::string& logger_name) +{ + return details::registry::instance().create(logger_name, sinks::stderr_sink_st::instance()); +} + +#ifdef __linux__ +// Create syslog logger +SPDLOG_INLINE std::shared_ptr syslog_logger(const std::string& logger_name, const std::string& syslog_ident, int syslog_option) +{ + return create(logger_name, syslog_ident, syslog_option); +} +#endif + + +//Create logger with multiple sinks + +SPDLOG_INLINE std::shared_ptr create(const std::string& logger_name, sinks_init_list sinks) +{ + return details::registry::instance().create(logger_name, sinks); +} + +SPDLOG_INLINE void set_formatter(formatter_ptr f) +{ + details::registry::instance().formatter(f); +} + +SPDLOG_INLINE void set_pattern(const std::string& format_string) +{ + return details::registry::instance().set_pattern(format_string); +} + +SPDLOG_INLINE void set_level(level::level_enum log_level) +{ + return details::registry::instance().set_level(log_level); +} + + +SPDLOG_INLINE void set_async_mode(size_t queue_size, const async_overflow_policy overflow_policy, const std::function& worker_warmup_cb, const std::chrono::milliseconds& flush_interval_ms) +{ + details::registry::instance().set_async_mode(queue_size, overflow_policy, worker_warmup_cb, flush_interval_ms); +} + +SPDLOG_INLINE void set_sync_mode() +{ + details::registry::instance().set_sync_mode(); +} + +SPDLOG_INLINE void drop_all() +{ + details::registry::instance().drop_all(); +} +} + diff --git a/include/spdlog/details/spdlog_impl.h b/include/spdlog/details/spdlog_impl.h index cfd6f826..41b1c529 100644 --- a/include/spdlog/details/spdlog_impl.h +++ b/include/spdlog/details/spdlog_impl.h @@ -27,88 +27,10 @@ // // Global registry functions // -#include "registry.h" -#include "../sinks/file_sinks.h" -#include "../sinks/stdout_sinks.h" -#include "../sinks/syslog_sink.h" - -inline void spdlog::register_logger(std::shared_ptr logger) -{ - return details::registry::instance().register_logger(logger); -} - -inline std::shared_ptr spdlog::get(const std::string& name) -{ - return details::registry::instance().get(name); -} - -inline void spdlog::drop(const std::string &name) -{ - details::registry::instance().drop(name); -} - -// Create multi/single threaded rotating file logger -inline std::shared_ptr spdlog::rotating_logger_mt(const std::string& logger_name, const std::string& filename, size_t max_file_size, size_t max_files, bool force_flush) -{ - return create(logger_name, filename, "txt", max_file_size, max_files, force_flush); -} - -inline std::shared_ptr spdlog::rotating_logger_st(const std::string& logger_name, const std::string& filename, size_t max_file_size, size_t max_files, bool force_flush) -{ - return create(logger_name, filename, "txt", max_file_size, max_files, force_flush); -} - -// Create file logger which creates new file at midnight): -inline std::shared_ptr spdlog::daily_logger_mt(const std::string& logger_name, const std::string& filename, int hour, int minute, bool force_flush) -{ - return create(logger_name, filename, "txt", hour, minute, force_flush); -} -inline std::shared_ptr spdlog::daily_logger_st(const std::string& logger_name, const std::string& filename, int hour, int minute, bool force_flush) -{ - return create(logger_name, filename, "txt", hour, minute, force_flush); -} - - -// Create stdout/stderr loggers -inline std::shared_ptr spdlog::stdout_logger_mt(const std::string& logger_name) -{ - return details::registry::instance().create(logger_name, spdlog::sinks::stdout_sink_mt::instance()); -} - -inline std::shared_ptr spdlog::stdout_logger_st(const std::string& logger_name) -{ - return details::registry::instance().create(logger_name, spdlog::sinks::stdout_sink_st::instance()); -} - -inline std::shared_ptr spdlog::stderr_logger_mt(const std::string& logger_name) -{ - return details::registry::instance().create(logger_name, spdlog::sinks::stderr_sink_mt::instance()); -} - -inline std::shared_ptr spdlog::stderr_logger_st(const std::string& logger_name) -{ - return details::registry::instance().create(logger_name, spdlog::sinks::stderr_sink_st::instance()); -} - -#ifdef __linux__ -// Create syslog logger -inline std::shared_ptr spdlog::syslog_logger(const std::string& logger_name, const std::string& syslog_ident, int syslog_option) -{ - return create(logger_name, syslog_ident, syslog_option); -} -#endif - - -//Create logger with multiple sinks - -inline std::shared_ptr spdlog::create(const std::string& logger_name, spdlog::sinks_init_list sinks) -{ - return details::registry::instance().create(logger_name, sinks); -} - +#include "./registry.h" template -inline std::shared_ptr spdlog::create(const std::string& logger_name, const Args&... args) +std::shared_ptr spdlog::create(const std::string& logger_name, const Args&... args) { sink_ptr sink = std::make_shared(args...); return details::registry::instance().create(logger_name, { sink }); @@ -116,39 +38,11 @@ inline std::shared_ptr spdlog::create(const std::string& logger_ template -inline std::shared_ptr spdlog::create(const std::string& logger_name, const It& sinks_begin, const It& sinks_end) +std::shared_ptr spdlog::create(const std::string& logger_name, const It& sinks_begin, const It& sinks_end) { return details::registry::instance().create(logger_name, sinks_begin, sinks_end); } -inline void spdlog::set_formatter(spdlog::formatter_ptr f) -{ - details::registry::instance().formatter(f); -} - -inline void spdlog::set_pattern(const std::string& format_string) -{ - return details::registry::instance().set_pattern(format_string); -} - -inline void spdlog::set_level(level::level_enum log_level) -{ - return details::registry::instance().set_level(log_level); -} - - -inline void spdlog::set_async_mode(size_t queue_size, const async_overflow_policy overflow_policy, const std::function& worker_warmup_cb, const std::chrono::milliseconds& flush_interval_ms) -{ - details::registry::instance().set_async_mode(queue_size, overflow_policy, worker_warmup_cb, flush_interval_ms); -} - -inline void spdlog::set_sync_mode() -{ - details::registry::instance().set_sync_mode(); -} - -inline void spdlog::drop_all() -{ - details::registry::instance().drop_all(); -} - +#ifndef SPDLOG_LIBRARY +#include "./spdlog_impl.cc" +#endif diff --git a/include/spdlog/formatter.h b/include/spdlog/formatter.h index 35ea0416..fa3ef03f 100644 --- a/include/spdlog/formatter.h +++ b/include/spdlog/formatter.h @@ -22,13 +22,16 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ #pragma once +#include +#include +#include -#include "details/log_msg.h" namespace spdlog { namespace details { class flag_formatter; +class log_msg; } class formatter @@ -54,5 +57,7 @@ private: }; } -#include "details/pattern_formatter_impl.h" +#ifndef SPDLOG_LIBRARY +#include "./details/pattern_formatter_impl.cc" +#endif diff --git a/include/spdlog/logger.h b/include/spdlog/logger.h index 7a5a31a7..69e7ebe7 100644 --- a/include/spdlog/logger.h +++ b/include/spdlog/logger.h @@ -31,9 +31,9 @@ // 2. Format the message using the formatter function // 3. Pass the formatted message to its sinks to performa the actual logging -#include -#include -#include "sinks/base_sink.h" +#include +#include +#include #include "common.h" namespace spdlog @@ -42,6 +42,7 @@ namespace spdlog namespace details { class line_logger; +class log_msg; } class logger diff --git a/include/spdlog/sinks/sink.h b/include/spdlog/sinks/sink.h index 88c423a0..1230d646 100644 --- a/include/spdlog/sinks/sink.h +++ b/include/spdlog/sinks/sink.h @@ -24,10 +24,9 @@ #pragma once -#include "../details/log_msg.h" - namespace spdlog { +namespace details { struct log_msg; } namespace sinks { class sink diff --git a/include/spdlog/spdlog.h b/include/spdlog/spdlog.h index aef04069..da02a7e6 100644 --- a/include/spdlog/spdlog.h +++ b/include/spdlog/spdlog.h @@ -152,4 +152,4 @@ void drop_all(); } -#include "details/spdlog_impl.h" +#include "./details/spdlog_impl.h" diff --git a/include/spdlog/tweakme.h b/include/spdlog/tweakme.h index b651658b..05482513 100644 --- a/include/spdlog/tweakme.h +++ b/include/spdlog/tweakme.h @@ -72,3 +72,9 @@ // Note that upon creating a logger the registry is modified by spdlog.. // #define SPDLOG_NO_REGISTRY_MUTEX /////////////////////////////////////////////////////////////////////////////// + + +/////////////////////////////////////////////////////////////////////////////// +// Uncomment if you want to compile as a static library +// #define SPDLOG_LIBRARY +/////////////////////////////////////////////////////////////////////////////// diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt new file mode 100644 index 00000000..a6d63009 --- /dev/null +++ b/tests/CMakeLists.txt @@ -0,0 +1,13 @@ +cmake_minimum_required(VERSION 3.0) +set(TESTS_SRCS + file_log.cpp + format.cpp + main.cpp + registry.cpp +) + +add_executable(spdlog-test ${TESTS_SRCS}) +target_link_libraries(spdlog-test spdlog) +target_include_directories(spdlog-test PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) +set_property(TARGET spdlog-test PROPERTY CXX_STANDARD 11) + diff --git a/tests/includes.h b/tests/includes.h index 7cda161d..68bd7f33 100644 --- a/tests/includes.h +++ b/tests/includes.h @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include #include @@ -10,3 +11,5 @@ #include "catch.hpp" #include "../include/spdlog/spdlog.h" #include "../include/spdlog/sinks/null_sink.h" +#include "../include/spdlog/sinks/file_sinks.h" +#include "../include/spdlog/sinks/ostream_sink.h"