Skip to content
Merged
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
128 changes: 122 additions & 6 deletions include/spdlog/sinks/daily_file_sink.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@
#include <mutex>
#include <string>

extern std::array<const char *, 7> spdlog::details::days;
extern std::array<const char *, 7> spdlog::details::full_days;
extern const std::array<const char *, 12> spdlog::details::months;
extern const std::array<const char *, 12> spdlog::details::full_months;

namespace spdlog {
namespace sinks {

Expand All @@ -34,6 +39,98 @@ struct daily_filename_calculator
return fmt::format(
SPDLOG_FILENAME_T("{}_{:04d}-{:02d}-{:02d}{}"), basename, now_tm.tm_year + 1900, now_tm.tm_mon + 1, now_tm.tm_mday, ext);
}

// Create formatting filename for the form basename.
static filename_t calc_filename_fmt(const filename_t &filename, const tm &now_tm)
{
filename_t dest = "";
int total_minutes;
for (size_t i = 0; i < filename.size (); ++i)
{
if (filename [i] == '%') {
if (i == filename.size () - 1)
throw_spdlog_ex("daily_file_sink: Invalid format");
i += 1;
char ch = filename [i];
switch (ch)
{
case 'a':
dest += spdlog::details::days[static_cast<size_t>(now_tm.tm_wday)];
break;
case 'A':
dest += spdlog::details::full_days[static_cast<size_t>(now_tm.tm_wday)];
break;
case 'b':
dest += spdlog::details::months[static_cast<size_t>(now_tm.tm_mon)];
break;
case 'B':
dest += spdlog::details::full_months[static_cast<size_t>(now_tm.tm_mon)];
break;
case 'c':
dest += calc_filename_fmt("%a %b %d %H:%M:%S %Y", now_tm);
break;
case 'C':
dest += fmt::format ("{}", (now_tm.tm_year + 1900) % 100);
break;
case 'Y':
dest += fmt::format ("{}", now_tm.tm_year + 1900);
break;
case 'D':
case 'x':
dest += calc_filename_fmt("%m %d %C", now_tm);
break;
case 'm':
dest += fmt::format ("{:02}", now_tm.tm_mon + 1);
break;
case 'd':
dest += fmt::format ("{:02}", now_tm.tm_mday);
break;
case 'H':
dest += fmt::format ("{:02}", now_tm.tm_hour);
break;
case 'I':
dest += fmt::format ("{:02}", (now_tm.tm_hour % 12) == 0 ? 12 : (now_tm.tm_hour % 12));
break;
case 'M':
dest += fmt::format ("{:02}", now_tm.tm_min);
break;
case 'S':
dest += fmt::format ("{:02}", now_tm.tm_sec);
break;
case 'p':
dest += (now_tm.tm_hour >= 1 && now_tm.tm_hour <= 12 ? "AM" : "PM");
break;
case 'r':
dest += calc_filename_fmt("%I:%M:%S %p", now_tm);
break;
case 'R':
dest += calc_filename_fmt("%H:%M", now_tm);
break;
case 'T':
case 'X':
dest += calc_filename_fmt("%H:%M:%S", now_tm);
break;
case 'z':
total_minutes = spdlog::details::os::utc_minutes_offset ();
if (total_minutes >= 0) {
dest += fmt::format ("+{:02}:{:02}", total_minutes / 60, total_minutes % 60);
} else {
total_minutes = -total_minutes;
dest += fmt::format ("-{:02}:{:02}", total_minutes / 60, total_minutes % 60);
}
break;
case '%':
dest += '%';
break;
default:
throw_spdlog_ex("daily_file_sink: Invalid format");
}
} else {
dest += filename [i];
}
}
return dest;
}
};

/*
Expand All @@ -46,21 +143,23 @@ class daily_file_sink final : public base_sink<Mutex>
{
public:
// create daily file sink which rotates on given time
daily_file_sink(filename_t base_filename, int rotation_hour, int rotation_minute, bool truncate = false, uint16_t max_files = 0)
daily_file_sink(filename_t base_filename, int rotation_hour, int rotation_minute, bool truncate = false, uint16_t max_files = 0, bool is_fmt = false)
: base_filename_(std::move(base_filename))
, rotation_h_(rotation_hour)
, rotation_m_(rotation_minute)
, truncate_(truncate)
, max_files_(max_files)
, filenames_q_()
, is_fmt_(is_fmt)
{
if (rotation_hour < 0 || rotation_hour > 23 || rotation_minute < 0 || rotation_minute > 59)
{
throw_spdlog_ex("daily_file_sink: Invalid rotation time in ctor");
}

auto now = log_clock::now();
auto filename = FileNameCalc::calc_filename(base_filename_, now_tm(now));
auto filename = is_fmt_ ? FileNameCalc::calc_filename_fmt(base_filename_, now_tm(now))
: FileNameCalc::calc_filename(base_filename_, now_tm(now));
file_helper_.open(filename, truncate_);
rotation_tp_ = next_rotation_tp_();

Expand All @@ -83,7 +182,8 @@ class daily_file_sink final : public base_sink<Mutex>
bool should_rotate = time >= rotation_tp_;
if (should_rotate)
{
auto filename = FileNameCalc::calc_filename(base_filename_, now_tm(time));
auto filename = is_fmt_ ? FileNameCalc::calc_filename_fmt(base_filename_, now_tm(time))
: FileNameCalc::calc_filename(base_filename_, now_tm(time));
file_helper_.open(filename, truncate_);
rotation_tp_ = next_rotation_tp_();
}
Expand Down Expand Up @@ -113,7 +213,8 @@ class daily_file_sink final : public base_sink<Mutex>
auto now = log_clock::now();
while (filenames.size() < max_files_)
{
auto filename = FileNameCalc::calc_filename(base_filename_, now_tm(now));
auto filename = is_fmt_ ? FileNameCalc::calc_filename_fmt(base_filename_, now_tm(now))
: FileNameCalc::calc_filename(base_filename_, now_tm(now));
if (!path_exists(filename))
{
break;
Expand Down Expand Up @@ -178,6 +279,7 @@ class daily_file_sink final : public base_sink<Mutex>
bool truncate_;
uint16_t max_files_;
details::circular_q<filename_t> filenames_q_;
bool is_fmt_;
};

using daily_file_sink_mt = daily_file_sink<std::mutex>;
Expand All @@ -192,13 +294,27 @@ template<typename Factory = spdlog::synchronous_factory>
inline std::shared_ptr<logger> daily_logger_mt(
const std::string &logger_name, const filename_t &filename, int hour = 0, int minute = 0, bool truncate = false, uint16_t max_files = 0)
{
return Factory::template create<sinks::daily_file_sink_mt>(logger_name, filename, hour, minute, truncate, max_files);
return Factory::template create<sinks::daily_file_sink_mt>(logger_name, filename, hour, minute, truncate, max_files, false);
}

template<typename Factory = spdlog::synchronous_factory>
inline std::shared_ptr<logger> daily_logger_format_mt(
const std::string &logger_name, const filename_t &filename, int hour = 0, int minute = 0, bool truncate = false, uint16_t max_files = 0)
{
return Factory::template create<sinks::daily_file_sink_mt>(logger_name, filename, hour, minute, truncate, max_files, true);
}

template<typename Factory = spdlog::synchronous_factory>
inline std::shared_ptr<logger> daily_logger_st(
const std::string &logger_name, const filename_t &filename, int hour = 0, int minute = 0, bool truncate = false, uint16_t max_files = 0)
{
return Factory::template create<sinks::daily_file_sink_st>(logger_name, filename, hour, minute, truncate, max_files);
return Factory::template create<sinks::daily_file_sink_st>(logger_name, filename, hour, minute, truncate, max_files, false);
}

template<typename Factory = spdlog::synchronous_factory>
inline std::shared_ptr<logger> daily_logger_format_st(
const std::string &logger_name, const filename_t &filename, int hour = 0, int minute = 0, bool truncate = false, uint16_t max_files = 0)
{
return Factory::template create<sinks::daily_file_sink_st>(logger_name, filename, hour, minute, truncate, max_files, true);
}
} // namespace spdlog