mirror of
https://github.com/gabime/spdlog.git
synced 2024-12-26 10:31:34 +08:00
Restored error_handler as std::function
This commit is contained in:
parent
e8d99cee70
commit
ff89f1476d
@ -49,7 +49,7 @@ endif()
|
|||||||
|
|
||||||
option(SPDLOG_HEADER_ONLY "Header only version. Turn OFF to build as static lib" OFF)
|
option(SPDLOG_HEADER_ONLY "Header only version. Turn OFF to build as static lib" OFF)
|
||||||
option(SPDLOG_BUILD_EXAMPLES "Build examples" ${SPDLOG_MASTER_PROJECT})
|
option(SPDLOG_BUILD_EXAMPLES "Build examples" ${SPDLOG_MASTER_PROJECT})
|
||||||
option(SPDLOG_BUILD_BENCH "Build benchmarks (Requires https://github.com/google/benchmark.git to be installed)" OFF)
|
option(SPDLOG_BUILD_BENCH "Build benchmarks (Requires https://github.com/google/benchmark.git to be installed)" ON)
|
||||||
option(SPDLOG_BUILD_TESTS "Build tests" ${SPDLOG_MASTER_PROJECT})
|
option(SPDLOG_BUILD_TESTS "Build tests" ${SPDLOG_MASTER_PROJECT})
|
||||||
option(SPDLOG_FMT_EXTERNAL "Use external fmt library instead of bundled" OFF)
|
option(SPDLOG_FMT_EXTERNAL "Use external fmt library instead of bundled" OFF)
|
||||||
option(SPDLOG_INSTALL "Generate the install target." ${SPDLOG_MASTER_PROJECT})
|
option(SPDLOG_INSTALL "Generate the install target." ${SPDLOG_MASTER_PROJECT})
|
||||||
|
@ -12,7 +12,6 @@
|
|||||||
#include "spdlog/async.h"
|
#include "spdlog/async.h"
|
||||||
#include "spdlog/sinks/stdout_color_sinks.h"
|
#include "spdlog/sinks/stdout_color_sinks.h"
|
||||||
|
|
||||||
|
|
||||||
int main(int, char *[])
|
int main(int, char *[])
|
||||||
{
|
{
|
||||||
using spdlog::sinks::stderr_color_sink_mt;
|
using spdlog::sinks::stderr_color_sink_mt;
|
||||||
|
@ -1,121 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright(c) 2015 Gabi Melman.
|
|
||||||
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
|
|
||||||
//
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
// async logger implementation
|
|
||||||
// uses a thread pool to perform the actual logging
|
|
||||||
|
|
||||||
#include "spdlog/details/thread_pool.h"
|
|
||||||
|
|
||||||
#include <chrono>
|
|
||||||
#include <memory>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
template<typename It>
|
|
||||||
inline spdlog::async_logger::async_logger(
|
|
||||||
std::string logger_name, It begin, It end, std::weak_ptr<details::thread_pool> tp, async_overflow_policy overflow_policy)
|
|
||||||
: logger(std::move(logger_name), begin, end)
|
|
||||||
, thread_pool_(std::move(tp))
|
|
||||||
, overflow_policy_(overflow_policy)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
inline spdlog::async_logger::async_logger(
|
|
||||||
std::string logger_name, sinks_init_list sinks_list, std::weak_ptr<details::thread_pool> tp, async_overflow_policy overflow_policy)
|
|
||||||
: async_logger(std::move(logger_name), sinks_list.begin(), sinks_list.end(), std::move(tp), overflow_policy)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
inline spdlog::async_logger::async_logger(
|
|
||||||
std::string logger_name, sink_ptr single_sink, std::weak_ptr<details::thread_pool> tp, async_overflow_policy overflow_policy)
|
|
||||||
: async_logger(std::move(logger_name), {std::move(single_sink)}, std::move(tp), overflow_policy)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
// send the log message to the thread pool
|
|
||||||
inline void spdlog::async_logger::sink_it_(details::log_msg &msg)
|
|
||||||
{
|
|
||||||
if (auto pool_ptr = thread_pool_.lock())
|
|
||||||
{
|
|
||||||
pool_ptr->post_log(shared_from_this(), msg, overflow_policy_);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw spdlog_ex("async log: thread pool doesn't exist anymore");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// send flush request to the thread pool
|
|
||||||
inline void spdlog::async_logger::flush_()
|
|
||||||
{
|
|
||||||
if (auto pool_ptr = thread_pool_.lock())
|
|
||||||
{
|
|
||||||
pool_ptr->post_flush(shared_from_this(), overflow_policy_);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw spdlog_ex("async flush: thread pool doesn't exist anymore");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// backend functions - called from the thread pool to do the actual job
|
|
||||||
//
|
|
||||||
inline void spdlog::async_logger::backend_log_(const details::log_msg &incoming_log_msg)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
for (auto &s : sinks_)
|
|
||||||
{
|
|
||||||
if (s->should_log(incoming_log_msg.level))
|
|
||||||
{
|
|
||||||
s->log(incoming_log_msg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (const std::exception &ex)
|
|
||||||
{
|
|
||||||
err_handler_(ex.what());
|
|
||||||
}
|
|
||||||
catch (...)
|
|
||||||
{
|
|
||||||
err_handler_("Unknown exception in logger");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (should_flush_(incoming_log_msg))
|
|
||||||
{
|
|
||||||
backend_flush_();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void spdlog::async_logger::backend_flush_()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
for (auto &sink : sinks_)
|
|
||||||
{
|
|
||||||
sink->flush();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (const std::exception &ex)
|
|
||||||
{
|
|
||||||
err_handler_(ex.what());
|
|
||||||
}
|
|
||||||
catch (...)
|
|
||||||
{
|
|
||||||
err_handler_("Unknown exception in logger");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inline std::shared_ptr<spdlog::logger> spdlog::async_logger::clone(std::string new_name)
|
|
||||||
{
|
|
||||||
auto cloned = std::make_shared<spdlog::async_logger>(std::move(new_name), sinks_.begin(), sinks_.end(), thread_pool_, overflow_policy_);
|
|
||||||
|
|
||||||
cloned->set_level(this->level());
|
|
||||||
cloned->flush_on(this->flush_level());
|
|
||||||
cloned->set_error_handler(this->custom_err_handler_);
|
|
||||||
return std::move(cloned);
|
|
||||||
}
|
|
@ -27,12 +27,13 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
namespace spdlog {
|
namespace spdlog {
|
||||||
class logger
|
class logger
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using err_handler = void (*)(const std::string &msg);
|
using err_handler = std::function<void(const std::string &err_msg)>;
|
||||||
template<typename It>
|
template<typename It>
|
||||||
logger(std::string name, It begin, It end)
|
logger(std::string name, It begin, It end)
|
||||||
: name_(std::move(name))
|
: name_(std::move(name))
|
||||||
@ -333,9 +334,6 @@ public:
|
|||||||
// print the error to stderr with the max rate of 1 message/minute.
|
// print the error to stderr with the max rate of 1 message/minute.
|
||||||
void err_handler_(const std::string &msg);
|
void err_handler_(const std::string &msg);
|
||||||
|
|
||||||
// increment the message count (only if defined(SPDLOG_ENABLE_MESSAGE_COUNTER))
|
|
||||||
void incr_msg_counter_(details::log_msg &msg);
|
|
||||||
|
|
||||||
const std::string name_;
|
const std::string name_;
|
||||||
std::vector<sink_ptr> sinks_;
|
std::vector<sink_ptr> sinks_;
|
||||||
spdlog::level_t level_{spdlog::logger::default_level()};
|
spdlog::level_t level_{spdlog::logger::default_level()};
|
||||||
|
@ -41,18 +41,13 @@ TEST_CASE("default_error_handler", "[errors]]")
|
|||||||
struct custom_ex
|
struct custom_ex
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
|
||||||
static void custom_handler(const std::string &)
|
|
||||||
{
|
|
||||||
throw custom_ex();
|
|
||||||
}
|
|
||||||
TEST_CASE("custom_error_handler", "[errors]]")
|
TEST_CASE("custom_error_handler", "[errors]]")
|
||||||
{
|
{
|
||||||
prepare_logdir();
|
prepare_logdir();
|
||||||
std::string filename = "logs/simple_log.txt";
|
std::string filename = "logs/simple_log.txt";
|
||||||
auto logger = spdlog::create<spdlog::sinks::basic_file_sink_mt>("logger", filename, true);
|
auto logger = spdlog::create<spdlog::sinks::basic_file_sink_mt>("logger", filename, true);
|
||||||
logger->flush_on(spdlog::level::info);
|
logger->flush_on(spdlog::level::info);
|
||||||
logger->set_error_handler(custom_handler);
|
logger->set_error_handler([=](const std::string &) { throw custom_ex(); });
|
||||||
logger->info("Good message #1");
|
logger->info("Good message #1");
|
||||||
|
|
||||||
REQUIRE_THROWS_AS(logger->info("Bad format msg {} {}", "xxx"), custom_ex);
|
REQUIRE_THROWS_AS(logger->info("Bad format msg {} {}", "xxx"), custom_ex);
|
||||||
@ -64,7 +59,7 @@ TEST_CASE("default_error_handler2", "[errors]]")
|
|||||||
{
|
{
|
||||||
spdlog::drop_all();
|
spdlog::drop_all();
|
||||||
auto logger = spdlog::create<failing_sink>("failed_logger");
|
auto logger = spdlog::create<failing_sink>("failed_logger");
|
||||||
logger->set_error_handler(custom_handler);
|
logger->set_error_handler([=](const std::string &) { throw custom_ex(); });
|
||||||
REQUIRE_THROWS_AS(logger->info("Some message"), custom_ex);
|
REQUIRE_THROWS_AS(logger->info("Some message"), custom_ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,26 +67,26 @@ TEST_CASE("flush_error_handler", "[errors]]")
|
|||||||
{
|
{
|
||||||
spdlog::drop_all();
|
spdlog::drop_all();
|
||||||
auto logger = spdlog::create<failing_sink>("failed_logger");
|
auto logger = spdlog::create<failing_sink>("failed_logger");
|
||||||
logger->set_error_handler(custom_handler);
|
logger->set_error_handler([=](const std::string &) { throw custom_ex(); });
|
||||||
REQUIRE_THROWS_AS(logger->flush(), custom_ex);
|
REQUIRE_THROWS_AS(logger->flush(), custom_ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("async_error_handler", "[errors]]")
|
TEST_CASE("async_error_handler", "[errors]]")
|
||||||
{
|
{
|
||||||
prepare_logdir();
|
prepare_logdir();
|
||||||
|
std::string err_msg("log failed with some msg");
|
||||||
|
|
||||||
std::string filename = "logs/simple_async_log.txt";
|
std::string filename = "logs/simple_async_log.txt";
|
||||||
{
|
{
|
||||||
spdlog::init_thread_pool(128, 1);
|
spdlog::init_thread_pool(128, 1);
|
||||||
auto logger = spdlog::create_async<spdlog::sinks::basic_file_sink_mt>("logger", filename, true);
|
auto logger = spdlog::create_async<spdlog::sinks::basic_file_sink_mt>("logger", filename, true);
|
||||||
logger->set_error_handler([](const std::string &) {
|
logger->set_error_handler([=](const std::string &) {
|
||||||
std::ofstream ofs("logs/custom_err.txt");
|
std::ofstream ofs("logs/custom_err.txt");
|
||||||
if (!ofs)
|
if (!ofs)
|
||||||
{
|
{
|
||||||
throw std::runtime_error("Failed open logs/custom_err.txt");
|
throw std::runtime_error("Failed open logs/custom_err.txt");
|
||||||
}
|
}
|
||||||
ofs << "log failed with some msg";
|
ofs << err_msg;
|
||||||
});
|
});
|
||||||
logger->info("Good message #1");
|
logger->info("Good message #1");
|
||||||
logger->info("Bad format msg {} {}", "xxx");
|
logger->info("Bad format msg {} {}", "xxx");
|
||||||
@ -100,26 +95,27 @@ TEST_CASE("async_error_handler", "[errors]]")
|
|||||||
}
|
}
|
||||||
spdlog::init_thread_pool(128, 1);
|
spdlog::init_thread_pool(128, 1);
|
||||||
REQUIRE(count_lines(filename) == 2);
|
REQUIRE(count_lines(filename) == 2);
|
||||||
REQUIRE(file_contents("logs/custom_err.txt") == "log failed with some msg");
|
REQUIRE(file_contents("logs/custom_err.txt") == err_msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure async error handler is executed
|
// Make sure async error handler is executed
|
||||||
TEST_CASE("async_error_handler2", "[errors]]")
|
TEST_CASE("async_error_handler2", "[errors]]")
|
||||||
{
|
{
|
||||||
prepare_logdir();
|
prepare_logdir();
|
||||||
|
std::string err_msg("This is async handler error message");
|
||||||
{
|
{
|
||||||
spdlog::init_thread_pool(128, 1);
|
spdlog::init_thread_pool(128, 1);
|
||||||
auto logger = spdlog::create_async<failing_sink>("failed_logger");
|
auto logger = spdlog::create_async<failing_sink>("failed_logger");
|
||||||
logger->set_error_handler([](const std::string &) {
|
logger->set_error_handler([=](const std::string &) {
|
||||||
std::ofstream ofs("logs/custom_err2.txt");
|
std::ofstream ofs("logs/custom_err2.txt");
|
||||||
if (!ofs)
|
if (!ofs)
|
||||||
throw std::runtime_error("Failed open logs/custom_err2.txt");
|
throw std::runtime_error("Failed open logs/custom_err2.txt");
|
||||||
ofs << "handler error message";
|
ofs << err_msg;
|
||||||
});
|
});
|
||||||
logger->info("Hello failure");
|
logger->info("Hello failure");
|
||||||
spdlog::drop("failed_logger"); // force logger to drain the queue and shutdown
|
spdlog::drop("failed_logger"); // force logger to drain the queue and shutdown
|
||||||
}
|
}
|
||||||
|
|
||||||
spdlog::init_thread_pool(128, 1);
|
spdlog::init_thread_pool(128, 1);
|
||||||
REQUIRE(file_contents("logs/custom_err2.txt") == "handler error message");
|
REQUIRE(file_contents("logs/custom_err2.txt") == err_msg);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user