Commit 1df30a07 authored by gabime's avatar gabime

support flush_on(..) in async loggers too

parent 3a12f3c5
...@@ -102,6 +102,10 @@ void async_example() ...@@ -102,6 +102,10 @@ void async_example()
size_t q_size = 4096; //queue size must be power of 2 size_t q_size = 4096; //queue size must be power of 2
spdlog::set_async_mode(q_size); spdlog::set_async_mode(q_size);
auto async_file = spd::daily_logger_st("async_file_logger", "logs/async_log.txt"); auto async_file = spd::daily_logger_st("async_file_logger", "logs/async_log.txt");
// auto flush if the log severity is error or higher
async_file->flush_on(spd::level::err);
for (int i = 0; i < 100; ++i) for (int i = 0; i < 100; ++i)
async_file->info("Async message #{}", i); async_file->info("Async message #{}", i);
} }
......
// //
// Copyright(c) 2015 Gabi Melman. // Copyright(c) 2015 Gabi Melman.
// Distributed under the MIT License (http://opensource.org/licenses/MIT) // Distributed under the MIT License (http://opensource.org/licenses/MIT)
// //
#pragma once #pragma once
// Async Logger implementation // Async Logger implementation
// Use an async_sink (queue per logger) to perform the logging in a worker thread // Use an async_sink (queue per logger) to perform the logging in a worker thread
#include <spdlog/details/async_log_helper.h> #include <spdlog/details/async_log_helper.h>
#include <spdlog/async_logger.h> #include <spdlog/async_logger.h>
#include <string> #include <string>
#include <functional> #include <functional>
#include <chrono> #include <chrono>
#include <memory> #include <memory>
template<class It> template<class It>
inline spdlog::async_logger::async_logger(const std::string& logger_name, inline spdlog::async_logger::async_logger(const std::string& logger_name,
const It& begin, const It& begin,
const It& end, const It& end,
size_t queue_size, size_t queue_size,
const async_overflow_policy overflow_policy, const async_overflow_policy overflow_policy,
const std::function<void()>& worker_warmup_cb, const std::function<void()>& worker_warmup_cb,
const std::chrono::milliseconds& flush_interval_ms, const std::chrono::milliseconds& flush_interval_ms,
const std::function<void()>& worker_teardown_cb) : const std::function<void()>& worker_teardown_cb) :
logger(logger_name, begin, end), logger(logger_name, begin, end),
_async_log_helper(new details::async_log_helper(_formatter, _sinks, queue_size, _err_handler, overflow_policy, worker_warmup_cb, flush_interval_ms, worker_teardown_cb)) _async_log_helper(new details::async_log_helper(_formatter, _sinks, queue_size, _err_handler, overflow_policy, worker_warmup_cb, flush_interval_ms, worker_teardown_cb))
{ {
} }
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, sinks_init_list sinks,
size_t queue_size, size_t queue_size,
const async_overflow_policy overflow_policy, const async_overflow_policy overflow_policy,
const std::function<void()>& worker_warmup_cb, const std::function<void()>& worker_warmup_cb,
const std::chrono::milliseconds& flush_interval_ms, const std::chrono::milliseconds& flush_interval_ms,
const std::function<void()>& worker_teardown_cb) : const std::function<void()>& worker_teardown_cb) :
async_logger(logger_name, sinks.begin(), sinks.end(), queue_size, overflow_policy, worker_warmup_cb, flush_interval_ms, worker_teardown_cb) {} async_logger(logger_name, sinks.begin(), sinks.end(), queue_size, overflow_policy, worker_warmup_cb, flush_interval_ms, worker_teardown_cb) {}
inline spdlog::async_logger::async_logger(const std::string& logger_name, inline spdlog::async_logger::async_logger(const std::string& logger_name,
sink_ptr single_sink, sink_ptr single_sink,
size_t queue_size, size_t queue_size,
const async_overflow_policy overflow_policy, const async_overflow_policy overflow_policy,
const std::function<void()>& worker_warmup_cb, const std::function<void()>& worker_warmup_cb,
const std::chrono::milliseconds& flush_interval_ms, const std::chrono::milliseconds& flush_interval_ms,
const std::function<void()>& worker_teardown_cb) : const std::function<void()>& worker_teardown_cb) :
async_logger(logger_name, async_logger(logger_name,
{ {
single_sink single_sink
}, queue_size, overflow_policy, worker_warmup_cb, flush_interval_ms, worker_teardown_cb) {} }, queue_size, overflow_policy, worker_warmup_cb, flush_interval_ms, worker_teardown_cb) {}
inline void spdlog::async_logger::flush() inline void spdlog::async_logger::flush()
{ {
_async_log_helper->flush();
_async_log_helper->flush(); }
}
inline void spdlog::async_logger::_set_formatter(spdlog::formatter_ptr msg_formatter)
inline void spdlog::async_logger::_set_formatter(spdlog::formatter_ptr msg_formatter) {
{ _formatter = msg_formatter;
_formatter = msg_formatter; _async_log_helper->set_formatter(_formatter);
_async_log_helper->set_formatter(_formatter); }
}
inline void spdlog::async_logger::_set_pattern(const std::string& pattern)
inline void spdlog::async_logger::_set_pattern(const std::string& pattern) {
{ _formatter = std::make_shared<pattern_formatter>(pattern);
_formatter = std::make_shared<pattern_formatter>(pattern); _async_log_helper->set_formatter(_formatter);
_async_log_helper->set_formatter(_formatter); }
}
inline void spdlog::async_logger::_sink_it(details::log_msg& msg)
inline void spdlog::async_logger::_sink_it(details::log_msg& msg) {
{ try
try {
{ _async_log_helper->log(msg);
_async_log_helper->log(msg); if (_should_flush_on(msg))
} flush();
catch (const std::exception &ex) }
{ catch (const std::exception &ex)
_err_handler(ex.what()); {
} _err_handler(ex.what());
catch (...) }
{ catch (...)
_err_handler("Unknown exception"); {
} _err_handler("Unknown exception");
} }
}
This diff is collapsed.
// //
// Copyright(c) 2015 Gabi Melman. // Copyright(c) 2015 Gabi Melman.
// Distributed under the MIT License (http://opensource.org/licenses/MIT) // Distributed under the MIT License (http://opensource.org/licenses/MIT)
// //
#pragma once #pragma once
// Thread safe logger // Thread safe logger
// Has name, log level, vector of std::shared sink pointers and formatter // Has name, log level, vector of std::shared sink pointers and formatter
// Upon each log write the logger: // Upon each log write the logger:
// 1. Checks if its log level is enough to log the message // 1. Checks if its log level is enough to log the message
// 2. Format the message using the formatter function // 2. Format the message using the formatter function
// 3. Pass the formatted message to its sinks to performa the actual logging // 3. Pass the formatted message to its sinks to performa the actual logging
#include <spdlog/sinks/base_sink.h> #include <spdlog/sinks/base_sink.h>
#include <spdlog/common.h> #include <spdlog/common.h>
#include <vector> #include <vector>
#include <memory> #include <memory>
#include <string> #include <string>
namespace spdlog namespace spdlog
{ {
class logger class logger
{ {
public: public:
logger(const std::string& logger_name, sink_ptr single_sink); logger(const std::string& logger_name, sink_ptr single_sink);
logger(const std::string& name, sinks_init_list); logger(const std::string& name, sinks_init_list);
template<class It> template<class It>
logger(const std::string& name, const It& begin, const It& end); logger(const std::string& name, const It& begin, const It& end);
virtual ~logger(); virtual ~logger();
logger(const logger&) = delete; logger(const logger&) = delete;
logger& operator=(const logger&) = delete; logger& operator=(const logger&) = delete;
template <typename... Args> void log(level::level_enum lvl, const char* fmt, const Args&... args); template <typename... Args> void log(level::level_enum lvl, const char* fmt, const Args&... args);
template <typename... Args> void log(level::level_enum lvl, const char* msg); template <typename... Args> void log(level::level_enum lvl, const char* msg);
template <typename... Args> void trace(const char* fmt, const Args&... args); template <typename... Args> void trace(const char* fmt, const Args&... args);
template <typename... Args> void debug(const char* fmt, const Args&... args); template <typename... Args> void debug(const char* fmt, const Args&... args);
template <typename... Args> void info(const char* fmt, const Args&... args); template <typename... Args> void info(const char* fmt, const Args&... args);
template <typename... Args> void warn(const char* fmt, const Args&... args); template <typename... Args> void warn(const char* fmt, const Args&... args);
template <typename... Args> void error(const char* fmt, const Args&... args); template <typename... Args> void error(const char* fmt, const Args&... args);
template <typename... Args> void critical(const char* fmt, const Args&... args); template <typename... Args> void critical(const char* fmt, const Args&... args);
template <typename T> void log(level::level_enum lvl, const T&); template <typename T> void log(level::level_enum lvl, const T&);
template <typename T> void trace(const T&); template <typename T> void trace(const T&);
template <typename T> void debug(const T&); template <typename T> void debug(const T&);
template <typename T> void info(const T&); template <typename T> void info(const T&);
template <typename T> void warn(const T&); template <typename T> void warn(const T&);
template <typename T> void error(const T&); template <typename T> void error(const T&);
template <typename T> void critical(const T&); template <typename T> void critical(const T&);
bool should_log(level::level_enum) const; bool should_log(level::level_enum) const;
void set_level(level::level_enum); void set_level(level::level_enum);
level::level_enum level() const; level::level_enum level() const;
const std::string& name() const; const std::string& name() const;
void set_pattern(const std::string&); void set_pattern(const std::string&);
void set_formatter(formatter_ptr); void set_formatter(formatter_ptr);
// error handler // error handler
void set_error_handler(log_err_handler); void set_error_handler(log_err_handler);
log_err_handler error_handler(); log_err_handler error_handler();
// automatically call flush() if message level >= log_level // automatically call flush() if message level >= log_level
void flush_on(level::level_enum log_level); void flush_on(level::level_enum log_level);
virtual void flush();
virtual void flush();
protected:
virtual void _sink_it(details::log_msg&); protected:
virtual void _set_pattern(const std::string&); virtual void _sink_it(details::log_msg&);
virtual void _set_formatter(formatter_ptr); virtual void _set_pattern(const std::string&);
virtual void _set_formatter(formatter_ptr);
// default error handler: print the error to stderr with the max rate of 1 message/minute
virtual void _default_err_handler(const std::string &msg); // default error handler: print the error to stderr with the max rate of 1 message/minute
virtual void _default_err_handler(const std::string &msg);
const std::string _name;
std::vector<sink_ptr> _sinks; // return true if the given message level should trigger a flush
formatter_ptr _formatter; bool _should_flush_on(const details::log_msg&);
spdlog::level_t _level;
spdlog::level_t _flush_level; const std::string _name;
log_err_handler _err_handler; std::vector<sink_ptr> _sinks;
std::atomic<time_t> _last_err_time; formatter_ptr _formatter;
}; spdlog::level_t _level;
} spdlog::level_t _flush_level;
log_err_handler _err_handler;
#include <spdlog/details/logger_impl.h> std::atomic<time_t> _last_err_time;
};
}
#include <spdlog/details/logger_impl.h>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment