mirror of
https://github.com/gabime/spdlog.git
synced 2025-11-16 09:28:56 +08:00
Merge remote-tracking branch 'origin/v1.x' into pwm1234/rotate_on_open
This commit is contained in:
@@ -5,6 +5,10 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef SPDLOG_H
|
||||
#error "spdlog.h must be included before this file."
|
||||
#endif
|
||||
|
||||
#include "spdlog/details/fmt_helper.h"
|
||||
#include "spdlog/details/null_mutex.h"
|
||||
#include "spdlog/details/os.h"
|
||||
@@ -27,7 +31,7 @@ namespace sinks {
|
||||
* Android sink (logging using __android_log_write)
|
||||
*/
|
||||
template<typename Mutex>
|
||||
class android_sink SPDLOG_FINAL : public base_sink<Mutex>
|
||||
class android_sink final : public base_sink<Mutex>
|
||||
{
|
||||
public:
|
||||
explicit android_sink(std::string tag = "spdlog", bool use_raw_msg = false)
|
||||
@@ -43,7 +47,7 @@ protected:
|
||||
fmt::memory_buffer formatted;
|
||||
if (use_raw_msg_)
|
||||
{
|
||||
details::fmt_helper::append_buf(msg.raw, formatted);
|
||||
details::fmt_helper::append_string_view(msg.payload, formatted);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -5,9 +5,14 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef SPDLOG_H
|
||||
#error "spdlog.h must be included before this file."
|
||||
#endif
|
||||
|
||||
#include "spdlog/details/console_globals.h"
|
||||
#include "spdlog/details/null_mutex.h"
|
||||
#include "spdlog/details/os.h"
|
||||
#include "spdlog/sinks/sink.h"
|
||||
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
@@ -24,7 +29,7 @@ namespace sinks {
|
||||
* If no color terminal detected, omit the escape codes.
|
||||
*/
|
||||
template<typename TargetStream, class ConsoleMutex>
|
||||
class ansicolor_sink SPDLOG_FINAL : public sink
|
||||
class ansicolor_sink final : public sink
|
||||
{
|
||||
public:
|
||||
using mutex_t = typename ConsoleMutex::mutex_t;
|
||||
@@ -116,7 +121,7 @@ public:
|
||||
fflush(target_file_);
|
||||
}
|
||||
|
||||
void set_pattern(const std::string &pattern) SPDLOG_FINAL
|
||||
void set_pattern(const std::string &pattern) final
|
||||
{
|
||||
std::lock_guard<mutex_t> lock(mutex_);
|
||||
formatter_ = std::unique_ptr<spdlog::formatter>(new pattern_formatter(pattern));
|
||||
|
||||
@@ -22,41 +22,47 @@ template<typename Mutex>
|
||||
class base_sink : public sink
|
||||
{
|
||||
public:
|
||||
base_sink()
|
||||
: sink()
|
||||
{
|
||||
}
|
||||
|
||||
base_sink() = default;
|
||||
base_sink(const base_sink &) = delete;
|
||||
base_sink &operator=(const base_sink &) = delete;
|
||||
|
||||
void log(const details::log_msg &msg) SPDLOG_FINAL
|
||||
void log(const details::log_msg &msg) final
|
||||
{
|
||||
std::lock_guard<Mutex> lock(mutex_);
|
||||
sink_it_(msg);
|
||||
}
|
||||
|
||||
void flush() SPDLOG_FINAL override
|
||||
void flush() final
|
||||
{
|
||||
std::lock_guard<Mutex> lock(mutex_);
|
||||
flush_();
|
||||
}
|
||||
|
||||
void set_pattern(const std::string &pattern) SPDLOG_FINAL override
|
||||
void set_pattern(const std::string &pattern) final
|
||||
{
|
||||
std::lock_guard<Mutex> lock(mutex_);
|
||||
formatter_ = std::unique_ptr<spdlog::formatter>(new pattern_formatter(pattern));
|
||||
set_pattern_(pattern);
|
||||
}
|
||||
|
||||
void set_formatter(std::unique_ptr<spdlog::formatter> sink_formatter) SPDLOG_FINAL override
|
||||
void set_formatter(std::unique_ptr<spdlog::formatter> sink_formatter) final
|
||||
{
|
||||
std::lock_guard<Mutex> lock(mutex_);
|
||||
formatter_ = std::move(sink_formatter);
|
||||
set_formatter_(std::move(sink_formatter));
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void sink_it_(const details::log_msg &msg) = 0;
|
||||
virtual void flush_() = 0;
|
||||
|
||||
virtual void set_pattern_(const std::string &pattern)
|
||||
{
|
||||
set_formatter_(details::make_unique<spdlog::pattern_formatter>(pattern));
|
||||
}
|
||||
|
||||
virtual void set_formatter_(std::unique_ptr<spdlog::formatter> sink_formatter)
|
||||
{
|
||||
formatter_ = std::move(sink_formatter);
|
||||
}
|
||||
Mutex mutex_;
|
||||
};
|
||||
} // namespace sinks
|
||||
|
||||
@@ -4,10 +4,14 @@
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef SPDLOG_H
|
||||
#error "spdlog.h must be included before this file."
|
||||
#endif
|
||||
|
||||
#include "spdlog/details/file_helper.h"
|
||||
#include "spdlog/details/null_mutex.h"
|
||||
#include "spdlog/sinks/base_sink.h"
|
||||
#include "spdlog/spdlog.h"
|
||||
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
@@ -18,7 +22,7 @@ namespace sinks {
|
||||
* Trivial file sink with single file as target
|
||||
*/
|
||||
template<typename Mutex>
|
||||
class basic_file_sink SPDLOG_FINAL : public base_sink<Mutex>
|
||||
class basic_file_sink final : public base_sink<Mutex>
|
||||
{
|
||||
public:
|
||||
explicit basic_file_sink(const filename_t &filename, bool truncate = false)
|
||||
|
||||
@@ -4,11 +4,15 @@
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef SPDLOG_H
|
||||
#error "spdlog.h must be included before this file."
|
||||
#endif
|
||||
|
||||
#include "spdlog/details/file_helper.h"
|
||||
#include "spdlog/details/null_mutex.h"
|
||||
#include "spdlog/fmt/fmt.h"
|
||||
#include "spdlog/sinks/base_sink.h"
|
||||
#include "spdlog/spdlog.h"
|
||||
|
||||
#include <chrono>
|
||||
#include <cstdio>
|
||||
@@ -28,7 +32,7 @@ struct daily_filename_calculator
|
||||
static filename_t calc_filename(const filename_t &filename, const tm &now_tm)
|
||||
{
|
||||
filename_t basename, ext;
|
||||
std::tie(basename, ext) = details::file_helper::split_by_extenstion(filename);
|
||||
std::tie(basename, ext) = details::file_helper::split_by_extension(filename);
|
||||
std::conditional<std::is_same<filename_t::value_type, char>::value, fmt::memory_buffer, fmt::wmemory_buffer>::type w;
|
||||
fmt::format_to(
|
||||
w, SPDLOG_FILENAME_T("{}_{:04d}-{:02d}-{:02d}{}"), basename, now_tm.tm_year + 1900, now_tm.tm_mon + 1, now_tm.tm_mday, ext);
|
||||
@@ -40,7 +44,7 @@ struct daily_filename_calculator
|
||||
* Rotating file sink based on date. rotates at midnight
|
||||
*/
|
||||
template<typename Mutex, typename FileNameCalc = daily_filename_calculator>
|
||||
class daily_file_sink SPDLOG_FINAL : public base_sink<Mutex>
|
||||
class daily_file_sink final : public base_sink<Mutex>
|
||||
{
|
||||
public:
|
||||
// create daily file sink which rotates on given time
|
||||
|
||||
@@ -5,6 +5,10 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef SPDLOG_H
|
||||
#error "spdlog.h must be included before this file."
|
||||
#endif
|
||||
|
||||
#include "base_sink.h"
|
||||
#include "spdlog/details/log_msg.h"
|
||||
#include "spdlog/details/null_mutex.h"
|
||||
@@ -62,7 +66,23 @@ protected:
|
||||
void flush_() override
|
||||
{
|
||||
for (auto &sink : sinks_)
|
||||
{
|
||||
sink->flush();
|
||||
}
|
||||
}
|
||||
|
||||
void set_pattern_(const std::string &pattern) override
|
||||
{
|
||||
set_formatter_(details::make_unique<spdlog::pattern_formatter>(pattern));
|
||||
}
|
||||
|
||||
void set_formatter_(std::unique_ptr<spdlog::formatter> sink_formatter) override
|
||||
{
|
||||
base_sink<Mutex>::formatter_ = std::move(sink_formatter);
|
||||
for (auto &sink : sinks_)
|
||||
{
|
||||
sink->set_formatter(base_sink<Mutex>::formatter_->clone());
|
||||
}
|
||||
}
|
||||
std::vector<std::shared_ptr<sink>> sinks_;
|
||||
};
|
||||
|
||||
@@ -5,6 +5,10 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef SPDLOG_H
|
||||
#error "spdlog.h must be included before this file."
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32)
|
||||
|
||||
#include "spdlog/details/null_mutex.h"
|
||||
|
||||
@@ -5,6 +5,10 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef SPDLOG_H
|
||||
#error "spdlog.h must be included before this file."
|
||||
#endif
|
||||
|
||||
#include "spdlog/details/null_mutex.h"
|
||||
#include "spdlog/sinks/base_sink.h"
|
||||
|
||||
@@ -25,4 +29,21 @@ using null_sink_mt = null_sink<std::mutex>;
|
||||
using null_sink_st = null_sink<details::null_mutex>;
|
||||
|
||||
} // namespace sinks
|
||||
|
||||
template<typename Factory = default_factory>
|
||||
inline std::shared_ptr<logger> null_logger_mt(const std::string &logger_name)
|
||||
{
|
||||
auto null_logger = Factory::template create<sinks::null_sink_mt>(logger_name);
|
||||
null_logger->set_level(level::off);
|
||||
return null_logger;
|
||||
}
|
||||
|
||||
template<typename Factory = default_factory>
|
||||
inline std::shared_ptr<logger> null_logger_st(const std::string &logger_name)
|
||||
{
|
||||
auto null_logger = Factory::template create<sinks::null_sink_st>(logger_name);
|
||||
null_logger->set_level(level::off);
|
||||
return null_logger;
|
||||
}
|
||||
|
||||
} // namespace spdlog
|
||||
|
||||
@@ -5,6 +5,10 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef SPDLOG_H
|
||||
#error "spdlog.h must be included before this file."
|
||||
#endif
|
||||
|
||||
#include "spdlog/details/null_mutex.h"
|
||||
#include "spdlog/sinks/base_sink.h"
|
||||
|
||||
@@ -14,7 +18,7 @@
|
||||
namespace spdlog {
|
||||
namespace sinks {
|
||||
template<typename Mutex>
|
||||
class ostream_sink SPDLOG_FINAL : public base_sink<Mutex>
|
||||
class ostream_sink final : public base_sink<Mutex>
|
||||
{
|
||||
public:
|
||||
explicit ostream_sink(std::ostream &os, bool force_flush = false)
|
||||
@@ -32,7 +36,9 @@ protected:
|
||||
sink::formatter_->format(msg, formatted);
|
||||
ostream_.write(formatted.data(), static_cast<std::streamsize>(formatted.size()));
|
||||
if (force_flush_)
|
||||
{
|
||||
ostream_.flush();
|
||||
}
|
||||
}
|
||||
|
||||
void flush_() override
|
||||
|
||||
@@ -4,11 +4,15 @@
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef SPDLOG_H
|
||||
#error "spdlog.h must be included before this file."
|
||||
#endif
|
||||
|
||||
#include "spdlog/details/file_helper.h"
|
||||
#include "spdlog/details/null_mutex.h"
|
||||
#include "spdlog/fmt/fmt.h"
|
||||
#include "spdlog/sinks/base_sink.h"
|
||||
#include "spdlog/spdlog.h"
|
||||
|
||||
#include <cerrno>
|
||||
#include <chrono>
|
||||
@@ -24,7 +28,7 @@ namespace sinks {
|
||||
// Rotating file sink based on size
|
||||
//
|
||||
template<typename Mutex>
|
||||
class rotating_file_sink SPDLOG_FINAL : public base_sink<Mutex>
|
||||
class rotating_file_sink final : public base_sink<Mutex>
|
||||
{
|
||||
public:
|
||||
rotating_file_sink(filename_t base_filename, std::size_t max_size, std::size_t max_files, bool rotate_on_open=false)
|
||||
@@ -46,7 +50,7 @@ public:
|
||||
if (index != 0u)
|
||||
{
|
||||
filename_t basename, ext;
|
||||
std::tie(basename, ext) = details::file_helper::split_by_extenstion(filename);
|
||||
std::tie(basename, ext) = details::file_helper::split_by_extension(filename);
|
||||
fmt::format_to(w, SPDLOG_FILENAME_T("{}.{}{}"), basename, index, ext);
|
||||
}
|
||||
else
|
||||
@@ -88,24 +92,22 @@ private:
|
||||
for (auto i = max_files_; i > 0; --i)
|
||||
{
|
||||
filename_t src = calc_filename(base_filename_, i - 1);
|
||||
if (!details::file_helper::file_exists(src))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
filename_t target = calc_filename(base_filename_, i);
|
||||
|
||||
if (details::file_helper::file_exists(target))
|
||||
if (!rename_file(src, target))
|
||||
{
|
||||
if (details::os::remove(target) != 0)
|
||||
{
|
||||
throw spdlog_ex("rotating_file_sink: failed removing " + filename_to_str(target), errno);
|
||||
}
|
||||
}
|
||||
if (details::file_helper::file_exists(src) && details::os::rename(src, target) != 0)
|
||||
{
|
||||
// if failed try again after small delay.
|
||||
// if failed try again after a small delay.
|
||||
// this is a workaround to a windows issue, where very high rotation
|
||||
// rates sometimes fail (because of antivirus?).
|
||||
details::os::sleep_for_millis(20);
|
||||
details::os::remove(target);
|
||||
if (details::os::rename(src, target) != 0)
|
||||
// rates can cause the rename to fail with permission denied (because of antivirus?).
|
||||
details::os::sleep_for_millis(100);
|
||||
if (!rename_file(src, target))
|
||||
{
|
||||
file_helper_.reopen(true); // truncate the log file anyway to prevent it to grow beyond its limit!
|
||||
current_size_ = 0;
|
||||
throw spdlog_ex(
|
||||
"rotating_file_sink: failed renaming " + filename_to_str(src) + " to " + filename_to_str(target), errno);
|
||||
}
|
||||
@@ -114,6 +116,15 @@ private:
|
||||
file_helper_.reopen(true);
|
||||
}
|
||||
|
||||
// delete the target if exists, and rename the src file to target
|
||||
// return true on success, false otherwise.
|
||||
bool rename_file(const filename_t &src_filename, const filename_t &target_filename)
|
||||
{
|
||||
// try to delete the target file in case it already exists.
|
||||
(void)details::os::remove(target_filename);
|
||||
return details::os::rename(src_filename, target_filename) == 0;
|
||||
}
|
||||
|
||||
filename_t base_filename_;
|
||||
std::size_t max_size_;
|
||||
std::size_t max_files_;
|
||||
|
||||
@@ -16,7 +16,7 @@ class sink
|
||||
public:
|
||||
sink()
|
||||
: level_(level::trace)
|
||||
, formatter_(new pattern_formatter("%+"))
|
||||
, formatter_(new pattern_formatter())
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,10 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "spdlog/spdlog.h"
|
||||
#ifndef SPDLOG_H
|
||||
#error "spdlog.h must be included before this file."
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#include "spdlog/sinks/wincolor_sink.h"
|
||||
#else
|
||||
|
||||
@@ -5,9 +5,12 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef SPDLOG_H
|
||||
#error "spdlog.h must be included before this file."
|
||||
#endif
|
||||
|
||||
#include "spdlog/details/console_globals.h"
|
||||
#include "spdlog/details/null_mutex.h"
|
||||
#include "spdlog/spdlog.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <memory>
|
||||
@@ -18,7 +21,7 @@ namespace spdlog {
|
||||
namespace sinks {
|
||||
|
||||
template<typename TargetStream, typename ConsoleMutex>
|
||||
class stdout_sink SPDLOG_FINAL : public sink
|
||||
class stdout_sink final : public sink
|
||||
{
|
||||
public:
|
||||
using mutex_t = typename ConsoleMutex::mutex_t;
|
||||
|
||||
@@ -5,8 +5,11 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef SPDLOG_H
|
||||
#error "spdlog.h must be included before this file."
|
||||
#endif
|
||||
|
||||
#include "spdlog/sinks/base_sink.h"
|
||||
#include "spdlog/spdlog.h"
|
||||
|
||||
#include <array>
|
||||
#include <string>
|
||||
@@ -50,7 +53,7 @@ public:
|
||||
protected:
|
||||
void sink_it_(const details::log_msg &msg) override
|
||||
{
|
||||
::syslog(syslog_prio_from_level(msg), "%s", fmt::to_string(msg.raw).c_str());
|
||||
::syslog(syslog_prio_from_level(msg), "%s", fmt::to_string(msg.payload).c_str());
|
||||
}
|
||||
|
||||
void flush_() override {}
|
||||
|
||||
@@ -5,6 +5,10 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef SPDLOG_H
|
||||
#error "spdlog.h must be included before this file."
|
||||
#endif
|
||||
|
||||
#include "spdlog/common.h"
|
||||
#include "spdlog/details/console_globals.h"
|
||||
#include "spdlog/details/null_mutex.h"
|
||||
@@ -61,7 +65,7 @@ public:
|
||||
colors_[level] = color;
|
||||
}
|
||||
|
||||
void log(const details::log_msg &msg) SPDLOG_FINAL override
|
||||
void log(const details::log_msg &msg) final override
|
||||
{
|
||||
std::lock_guard<mutex_t> lock(mutex_);
|
||||
fmt::memory_buffer formatted;
|
||||
@@ -85,18 +89,18 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void flush() SPDLOG_FINAL override
|
||||
void flush() final override
|
||||
{
|
||||
// windows console always flushed?
|
||||
}
|
||||
|
||||
void set_pattern(const std::string &pattern) override SPDLOG_FINAL
|
||||
void set_pattern(const std::string &pattern) override final
|
||||
{
|
||||
std::lock_guard<mutex_t> lock(mutex_);
|
||||
formatter_ = std::unique_ptr<spdlog::formatter>(new pattern_formatter(pattern));
|
||||
}
|
||||
|
||||
void set_formatter(std::unique_ptr<spdlog::formatter> sink_formatter) override SPDLOG_FINAL
|
||||
void set_formatter(std::unique_ptr<spdlog::formatter> sink_formatter) override final
|
||||
{
|
||||
std::lock_guard<mutex_t> lock(mutex_);
|
||||
formatter_ = std::move(sink_formatter);
|
||||
|
||||
Reference in New Issue
Block a user