8 #include "../details/file_helper.h" 9 #include "../details/null_mutex.h" 10 #include "../fmt/fmt.h" 11 #include "base_sink.h" 27 class simple_file_sink SPDLOG_FINAL :
public base_sink<Mutex>
30 explicit simple_file_sink(
const filename_t &filename,
bool truncate =
false)
33 _file_helper.open(filename, truncate);
36 void set_force_flush(
bool force_flush)
38 _force_flush = force_flush;
42 void _sink_it(
const details::log_msg &msg)
override 44 _file_helper.write(msg);
51 void _flush()
override 57 details::file_helper _file_helper;
61 using simple_file_sink_mt = simple_file_sink<std::mutex>;
62 using simple_file_sink_st = simple_file_sink<details::null_mutex>;
68 class rotating_file_sink SPDLOG_FINAL :
public base_sink<Mutex>
71 rotating_file_sink(filename_t base_filename, std::size_t max_size, std::size_t max_files)
72 : _base_filename(
std::move(base_filename))
74 , _max_files(max_files)
76 _file_helper.open(calc_filename(_base_filename, 0));
77 _current_size = _file_helper.size();
82 static filename_t calc_filename(
const filename_t &filename, std::size_t index)
87 filename_t basename, ext;
88 std::tie(basename, ext) = details::file_helper::split_by_extenstion(filename);
89 w.write(SPDLOG_FILENAME_T(
"{}.{}{}"), basename, index, ext);
93 w.write(SPDLOG_FILENAME_T(
"{}"), filename);
99 void _sink_it(
const details::log_msg &msg)
override 101 _current_size += msg.formatted.size();
102 if (_current_size > _max_size)
105 _current_size = msg.formatted.size();
107 _file_helper.write(msg);
110 void _flush()
override 112 _file_helper.flush();
123 using details::os::filename_to_str;
124 _file_helper.close();
125 for (
auto i = _max_files; i > 0; --i)
127 filename_t src = calc_filename(_base_filename, i - 1);
128 filename_t target = calc_filename(_base_filename, i);
130 if (details::file_helper::file_exists(target))
132 if (details::os::remove(target) != 0)
134 throw spdlog_ex(
"rotating_file_sink: failed removing " + filename_to_str(target), errno);
137 if (details::file_helper::file_exists(src) && details::os::rename(src, target) != 0)
139 throw spdlog_ex(
"rotating_file_sink: failed renaming " + filename_to_str(src) +
" to " + filename_to_str(target), errno);
142 _file_helper.reopen(
true);
145 filename_t _base_filename;
146 std::size_t _max_size;
147 std::size_t _max_files;
148 std::size_t _current_size;
149 details::file_helper _file_helper;
152 using rotating_file_sink_mt = rotating_file_sink<std::mutex>;
153 using rotating_file_sink_st = rotating_file_sink<details::null_mutex>;
161 static filename_t calc_filename(
const filename_t &filename)
163 std::tm tm = spdlog::details::os::localtime();
164 filename_t basename, ext;
165 std::tie(basename, ext) = details::file_helper::split_by_extenstion(filename);
166 std::conditional<std::is_same<filename_t::value_type, char>::value, fmt::MemoryWriter,
fmt::WMemoryWriter>::type w;
167 w.
write(SPDLOG_FILENAME_T(
"{}_{:04d}-{:02d}-{:02d}_{:02d}-{:02d}{}"), basename, tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
168 tm.tm_hour, tm.tm_min, ext);
179 static filename_t calc_filename(
const filename_t &filename)
181 std::tm tm = spdlog::details::os::localtime();
182 filename_t basename, ext;
183 std::tie(basename, ext) = details::file_helper::split_by_extenstion(filename);
184 std::conditional<std::is_same<filename_t::value_type, char>::value, fmt::MemoryWriter,
fmt::WMemoryWriter>::type w;
185 w.
write(SPDLOG_FILENAME_T(
"{}_{:04d}-{:02d}-{:02d}{}"), basename, tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, ext);
193 template<
class Mutex,
class FileNameCalc = default_daily_file_name_calculator>
194 class daily_file_sink SPDLOG_FINAL :
public base_sink<Mutex>
198 daily_file_sink(filename_t base_filename,
int rotation_hour,
int rotation_minute)
199 : _base_filename(std::move(base_filename))
200 , _rotation_h(rotation_hour)
201 , _rotation_m(rotation_minute)
203 if (rotation_hour < 0 || rotation_hour > 23 || rotation_minute < 0 || rotation_minute > 59)
205 throw spdlog_ex(
"daily_file_sink: Invalid rotation time in ctor");
207 _rotation_tp = _next_rotation_tp();
208 _file_helper.open(FileNameCalc::calc_filename(_base_filename));
214 if (std::chrono::system_clock::now() >= _rotation_tp)
216 _file_helper.open(FileNameCalc::calc_filename(_base_filename));
217 _rotation_tp = _next_rotation_tp();
219 _file_helper.write(msg);
222 void _flush()
override 224 _file_helper.flush();
228 std::chrono::system_clock::time_point _next_rotation_tp()
230 auto now = std::chrono::system_clock::now();
231 time_t tnow = std::chrono::system_clock::to_time_t(now);
232 tm date = spdlog::details::os::localtime(tnow);
233 date.tm_hour = _rotation_h;
234 date.tm_min = _rotation_m;
236 auto rotation_time = std::chrono::system_clock::from_time_t(std::mktime(&date));
237 if (rotation_time > now)
239 return rotation_time;
241 return {rotation_time + std::chrono::hours(24)};
244 filename_t _base_filename;
247 std::chrono::system_clock::time_point _rotation_tp;
251 using daily_file_sink_mt = daily_file_sink<std::mutex>;
252 using daily_file_sink_st = daily_file_sink<details::null_mutex>;
Definition: lib/spdlog/common.h:146
Definition: file_helper.h:25
Definition: file_sinks.h:176
Definition: async_logger.h:26
void write(BasicCStringRef< Char > format, ArgList args)
Definition: format.h:3332
Definition: format.h:3924
Definition: file_sinks.h:158
Definition: base_sink.h:23