3 #include "../../details/file_helper.h" 4 #include "../../details/null_mutex.h" 5 #include "../../fmt/fmt.h" 6 #include "../../sinks/base_sink.h" 52 static std::tuple<filename_t, filename_t> calc_filename(
const filename_t &filename,
const filename_t &tmp_ext)
54 std::tm tm = spdlog::details::os::localtime();
55 filename_t basename, ext;
56 std::tie(basename, ext) = details::file_helper::split_by_extenstion(filename);
58 w.
write(SPDLOG_FILENAME_T(
"{}_{:04d}-{:02d}-{:02d}_{:02d}-{:02d}-{:02d}{}"), basename, tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
59 tm.tm_hour, tm.tm_min, tm.tm_sec, tmp_ext);
60 return std::make_tuple(w.str(), ext);
67 template<
class Mutex,
class FileNameCalc = default_step_file_name_calculator>
71 step_file_sink(filename_t base_filename,
unsigned step_seconds, filename_t tmp_ext,
unsigned max_size,
bool delete_empty_files,
72 filename_t file_header)
73 : _base_filename(std::move(base_filename))
74 , _tmp_ext(std::move(tmp_ext))
75 , _step_seconds(step_seconds)
77 , _delete_empty_files(delete_empty_files)
79 if (step_seconds == 0)
81 throw spdlog_ex(
"step_file_sink: Invalid time step in ctor");
84 if (!file_header.empty())
86 pattern_formatter formatter_for_file_header(
"%v");
87 _file_header.raw << file_header;
88 formatter_for_file_header.format(_file_header);
91 if (max_size <= _file_header.formatted.size())
93 throw spdlog_ex(
"step_file_sink: Invalid max log size in ctor");
97 std::tie(_current_filename, _ext) = FileNameCalc::calc_filename(_base_filename, _tmp_ext);
101 throw spdlog_ex(
"step_file_sink: The temporary extension matches the specified in ctor");
104 _file_helper.open(_current_filename);
105 _current_size = _file_helper.size();
109 _current_size += _file_header.formatted.size();
111 _file_helper.write(_file_header);
119 close_current_file();
129 auto msg_size = msg.formatted.
size();
131 if (std::chrono::system_clock::now() >= _tp || _current_size + msg_size > _max_size)
133 filename_t new_filename;
134 std::tie(new_filename, std::ignore) = FileNameCalc::calc_filename(_base_filename, _tmp_ext);
136 bool change_occured = !details::file_helper::file_exists(new_filename);
139 close_current_file();
141 _current_filename = std::move(new_filename);
143 _file_helper.open(_current_filename);
150 _current_size = _file_header.formatted.size();
152 _file_helper.write(_file_header);
156 _current_size += msg_size;
157 _file_helper.write(msg);
160 void _flush()
override 162 _file_helper.flush();
166 std::chrono::system_clock::time_point _next_tp()
168 return std::chrono::system_clock::now() + _step_seconds;
171 void close_current_file()
173 using details::os::filename_to_str;
176 if (_delete_empty_files && _current_size <= _file_header.formatted.size())
178 if (details::os::remove(_current_filename) != 0)
180 throw spdlog_ex(
"step_file_sink: not remove " + filename_to_str(_current_filename), errno);
187 std::tie(target, std::ignore) = details::file_helper::split_by_extenstion(_current_filename);
190 if (details::file_helper::file_exists(_current_filename) && details::os::rename(_current_filename, target) != 0)
193 "step_file_sink: failed renaming " + filename_to_str(_current_filename) +
" to " + filename_to_str(target), errno);
197 const filename_t _base_filename;
198 const filename_t _tmp_ext;
199 const std::chrono::seconds _step_seconds;
200 const unsigned _max_size;
201 const bool _delete_empty_files;
203 std::chrono::system_clock::time_point _tp;
204 filename_t _current_filename;
206 unsigned _current_size;
212 using step_file_sink_mt = step_file_sink<std::mutex>;
213 using step_file_sink_st = step_file_sink<details::null_mutex>;
Definition: lib/spdlog/common.h:146
Definition: file_helper.h:25
Definition: async_logger.h:26
std::size_t size() const
Definition: format.h:3271
Definition: step_file_sink.h:49
void write(BasicCStringRef< Char > format, ArgList args)
Definition: format.h:3332
Definition: step_file_sink.h:68
Definition: format.h:3924
Definition: base_sink.h:23