From 3cab260814613b0a7e6889d2a030b2992c916d1a Mon Sep 17 00:00:00 2001 From: Mohammad Ali Date: Thu, 19 Jan 2023 21:16:34 +0330 Subject: [PATCH 1/5] Add a trivial callback sink (#2610) Add a trivial callback sink --- README.md | 22 ++++++++++ example/example.cpp | 11 +++++ include/spdlog/sinks/callback_sink.h | 61 ++++++++++++++++++++++++++++ tests/CMakeLists.txt | 1 + tests/test_custom_callbacks.cpp | 34 ++++++++++++++++ 5 files changed, 129 insertions(+) create mode 100644 include/spdlog/sinks/callback_sink.h create mode 100644 tests/test_custom_callbacks.cpp diff --git a/README.md b/README.md index b98a920b..d650b3ed 100644 --- a/README.md +++ b/README.md @@ -232,6 +232,28 @@ void multi_sink_example() } ``` +--- +#### Logger with a custom callback function that receives the logs +```c++ + +// create logger with a lambda function callback, the callback will be called +// each time something is logged to the logger +void callback_example() +{ + auto callback_sink = std::make_shared([](const spdlog::details::log_msg &msg) { + // for example you can be notified by sending an email to yourself + }); + callback_sink->set_level(spdlog::level::err); + + auto console_sink = std::make_shared(); + spdlog::logger logger("custom_callback_logger", {console_sink, callback_sink}); + + logger.info("some info log"); + logger.debug("some debug log"); + logger.error("critical issue"); // will notify you +} +``` + --- #### Asynchronous logging ```c++ diff --git a/example/example.cpp b/example/example.cpp index ccfdcf2f..316a22b1 100644 --- a/example/example.cpp +++ b/example/example.cpp @@ -12,6 +12,7 @@ void stdout_logger_example(); void basic_example(); void rotating_example(); void daily_example(); +void callback_example(); void async_example(); void binary_example(); void vector_example(); @@ -72,6 +73,7 @@ int main(int, char *[]) basic_example(); rotating_example(); daily_example(); + callback_example(); async_example(); binary_example(); vector_example(); @@ -136,6 +138,15 @@ void daily_example() auto daily_logger = spdlog::daily_logger_mt("daily_logger", "logs/daily.txt", 2, 30); } +#include "spdlog/sinks/callback_sink.h" +void callback_example() +{ + // Create the logger + auto logger = spdlog::callback_logger_mt("custom_callback_logger", [](const spdlog::details::log_msg &/*msg*/) { + // do what you need to do with msg + }); +} + #include "spdlog/cfg/env.h" void load_levels_example() { diff --git a/include/spdlog/sinks/callback_sink.h b/include/spdlog/sinks/callback_sink.h new file mode 100644 index 00000000..bcd31383 --- /dev/null +++ b/include/spdlog/sinks/callback_sink.h @@ -0,0 +1,61 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#include +#include +#include + +#include +#include + +namespace spdlog { + +// callbacks type +typedef std::function custom_log_callback; + +namespace sinks { +/* + * Trivial callback sink, gets a callback function and calls it on each log + */ +template +class callback_sink final : public base_sink +{ +public: + explicit callback_sink(const custom_log_callback &callback) + : callback_{callback} + {} + +protected: + void sink_it_(const details::log_msg &msg) override + { + callback_(msg); + } + void flush_() override{}; + +private: + custom_log_callback callback_; +}; + +using callback_sink_mt = callback_sink; +using callback_sink_st = callback_sink; + +} // namespace sinks + +// +// factory functions +// +template +inline std::shared_ptr callback_logger_mt(const std::string &logger_name, const custom_log_callback &callback) +{ + return Factory::template create(logger_name, callback); +} + +template +inline std::shared_ptr callback_logger_st(const std::string &logger_name, const custom_log_callback &callback) +{ + return Factory::template create(logger_name, callback); +} + +} // namespace spdlog diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 7fe4791e..12204e2b 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -31,6 +31,7 @@ set(SPDLOG_UTESTS_SOURCES test_stdout_api.cpp test_backtrace.cpp test_create_dir.cpp + test_custom_callbacks.cpp test_cfg.cpp test_time_point.cpp test_stopwatch.cpp) diff --git a/tests/test_custom_callbacks.cpp b/tests/test_custom_callbacks.cpp new file mode 100644 index 00000000..877e1608 --- /dev/null +++ b/tests/test_custom_callbacks.cpp @@ -0,0 +1,34 @@ +/* + * This content is released under the MIT License as specified in https://raw.githubusercontent.com/gabime/spdlog/master/LICENSE + */ +#include "includes.h" +#include "test_sink.h" +#include "spdlog/sinks/callback_sink.h" +#include "spdlog/async.h" +#include "spdlog/common.h" + +TEST_CASE("custom_callback_logger", "[custom_callback_logger]]") +{ + std::vector lines; + spdlog::pattern_formatter formatter; + auto callback_logger = std::make_shared([&](const spdlog::details::log_msg &msg) { + spdlog::memory_buf_t formatted; + formatter.format(msg, formatted); + auto eol_len = strlen(spdlog::details::os::default_eol); + lines.emplace_back(formatted.begin(), formatted.end() - eol_len); + }); + std::shared_ptr test_sink(new spdlog::sinks::test_sink_st); + + spdlog::logger logger("test-callback", {callback_logger, test_sink}); + + logger.info("test message 1"); + logger.info("test message 2"); + logger.info("test message 3"); + + std::vector ref_lines = test_sink->lines(); + + REQUIRE(lines[0] == ref_lines[0]); + REQUIRE(lines[1] == ref_lines[1]); + REQUIRE(lines[2] == ref_lines[2]); + spdlog::drop_all(); +} From d8c061aa6e160ac25a5b44ccf9a93bb13dbfc3be Mon Sep 17 00:00:00 2001 From: Gabi Melman Date: Sat, 21 Jan 2023 00:35:53 +0200 Subject: [PATCH 2/5] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d650b3ed..afcd1958 100644 --- a/README.md +++ b/README.md @@ -233,7 +233,7 @@ void multi_sink_example() ``` --- -#### Logger with a custom callback function that receives the logs +#### User defined callbacks about log events ```c++ // create logger with a lambda function callback, the callback will be called From 5a589438d2d2abc67bdbec2aad7e2a94800c00ea Mon Sep 17 00:00:00 2001 From: Gabi Melman Date: Sat, 21 Jan 2023 00:36:56 +0200 Subject: [PATCH 3/5] Update README.md --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index afcd1958..9f6291b9 100644 --- a/README.md +++ b/README.md @@ -249,7 +249,6 @@ void callback_example() spdlog::logger logger("custom_callback_logger", {console_sink, callback_sink}); logger.info("some info log"); - logger.debug("some debug log"); logger.error("critical issue"); // will notify you } ``` From 927cc29444a294d76e83dfb898e797dc431ce094 Mon Sep 17 00:00:00 2001 From: Li Z Date: Wed, 1 Feb 2023 18:04:30 +0800 Subject: [PATCH 4/5] Fix unexpected delimiter at start of line in to_hex formatter (#2627) --- include/spdlog/fmt/bin_to_hex.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/spdlog/fmt/bin_to_hex.h b/include/spdlog/fmt/bin_to_hex.h index 47fec05b..1cb51ce6 100644 --- a/include/spdlog/fmt/bin_to_hex.h +++ b/include/spdlog/fmt/bin_to_hex.h @@ -196,7 +196,7 @@ struct formatter, char> continue; } - if (put_delimiters) + if (put_delimiters && i != the_range.get_begin()) { *inserter++ = delimiter; } From da14258533cb951ce85087ceb45556e0b8253660 Mon Sep 17 00:00:00 2001 From: Zeus James <39390245+zEuS0390@users.noreply.github.com> Date: Sun, 12 Feb 2023 16:34:22 +0800 Subject: [PATCH 5/5] Fix MinGW build issue on example (#2642) * Fix MinGW build issue on example #2638 * Move the cmake change to example\CMakeLists.txt * Update CMakeLists.txt on the example --- CMakeLists.txt | 1 - example/CMakeLists.txt | 2 +- include/spdlog/details/udp_client-windows.h | 10 ++++++---- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 61d21781..3389c04b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -176,7 +176,6 @@ if(SPDLOG_SYSTEM_INCLUDES) set(SPDLOG_INCLUDES_LEVEL "SYSTEM") endif() - target_compile_definitions(spdlog PUBLIC SPDLOG_COMPILED_LIB) target_include_directories(spdlog ${SPDLOG_INCLUDES_LEVEL} PUBLIC "$" "$") diff --git a/example/CMakeLists.txt b/example/CMakeLists.txt index 83336e98..a7863493 100644 --- a/example/CMakeLists.txt +++ b/example/CMakeLists.txt @@ -12,7 +12,7 @@ endif() # Example of using pre-compiled library # --------------------------------------------------------------------------------------- add_executable(example example.cpp) -target_link_libraries(example PRIVATE spdlog::spdlog) +target_link_libraries(example PRIVATE spdlog::spdlog $<$:ws2_32>) # --------------------------------------------------------------------------------------- # Example of using header-only library diff --git a/include/spdlog/details/udp_client-windows.h b/include/spdlog/details/udp_client-windows.h index 8e763356..7d25f037 100644 --- a/include/spdlog/details/udp_client-windows.h +++ b/include/spdlog/details/udp_client-windows.h @@ -15,9 +15,11 @@ #include #include -#pragma comment(lib, "Ws2_32.lib") -#pragma comment(lib, "Mswsock.lib") -#pragma comment(lib, "AdvApi32.lib") +#if defined(_MSC_VER) +# pragma comment(lib, "Ws2_32.lib") +# pragma comment(lib, "Mswsock.lib") +# pragma comment(lib, "AdvApi32.lib") +#endif namespace spdlog { namespace details { @@ -25,7 +27,7 @@ class udp_client { static constexpr int TX_BUFFER_SIZE = 1024 * 10; SOCKET socket_ = INVALID_SOCKET; - sockaddr_in addr_ = {0}; + sockaddr_in addr_ = {}; static void init_winsock_() {