Agora  1.2.0
Agora project
rotating_file_sink-inl.h
Go to the documentation of this file.
1 // Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
2 // Distributed under the MIT License (http://opensource.org/licenses/MIT)
3 
4 #pragma once
5 
6 #ifndef SPDLOG_HEADER_ONLY
8 #endif
9 
10 #include <spdlog/common.h>
11 
14 #include <spdlog/fmt/fmt.h>
15 
16 #include <cerrno>
17 #include <chrono>
18 #include <ctime>
19 #include <mutex>
20 #include <string>
21 #include <tuple>
22 
23 namespace spdlog {
24 namespace sinks {
25 
26 template<typename Mutex>
28  filename_t base_filename, std::size_t max_size, std::size_t max_files, bool rotate_on_open, const file_event_handlers &event_handlers)
29  : base_filename_(std::move(base_filename))
30  , max_size_(max_size)
31  , max_files_(max_files)
32  , file_helper_{event_handlers}
33 {
34  if (max_size == 0)
35  {
36  throw_spdlog_ex("rotating sink constructor: max_size arg cannot be zero");
37  }
38 
39  if (max_files > 200000)
40  {
41  throw_spdlog_ex("rotating sink constructor: max_files arg cannot exceed 200000");
42  }
43  file_helper_.open(calc_filename(base_filename_, 0));
44  current_size_ = file_helper_.size(); // expensive. called only once
45  if (rotate_on_open && current_size_ > 0)
46  {
47  rotate_();
48  current_size_ = 0;
49  }
50 }
51 
52 // calc filename according to index and file extension if exists.
53 // e.g. calc_filename("logs/mylog.txt, 3) => "logs/mylog.3.txt".
54 template<typename Mutex>
56 {
57  if (index == 0u)
58  {
59  return filename;
60  }
61 
62  filename_t basename, ext;
63  std::tie(basename, ext) = details::file_helper::split_by_extension(filename);
64  return fmt_lib::format(SPDLOG_FILENAME_T("{}.{}{}"), basename, index, ext);
65 }
66 
67 template<typename Mutex>
69 {
70  std::lock_guard<Mutex> lock(base_sink<Mutex>::mutex_);
71  return file_helper_.filename();
72 }
73 
74 template<typename Mutex>
76 {
77  memory_buf_t formatted;
78  base_sink<Mutex>::formatter_->format(msg, formatted);
79  auto new_size = current_size_ + formatted.size();
80 
81  // rotate if the new estimated file size exceeds max size.
82  // rotate only if the real size > 0 to better deal with full disk (see issue #2261).
83  // we only check the real size when new_size > max_size_ because it is relatively expensive.
84  if (new_size > max_size_)
85  {
86  file_helper_.flush();
87  if (file_helper_.size() > 0)
88  {
89  rotate_();
90  new_size = formatted.size();
91  }
92  }
93  file_helper_.write(formatted);
94  current_size_ = new_size;
95 }
96 
97 template<typename Mutex>
99 {
100  file_helper_.flush();
101 }
102 
103 // Rotate files:
104 // log.txt -> log.1.txt
105 // log.1.txt -> log.2.txt
106 // log.2.txt -> log.3.txt
107 // log.3.txt -> delete
108 template<typename Mutex>
110 {
113 
114  file_helper_.close();
115  for (auto i = max_files_; i > 0; --i)
116  {
117  filename_t src = calc_filename(base_filename_, i - 1);
118  if (!path_exists(src))
119  {
120  continue;
121  }
122  filename_t target = calc_filename(base_filename_, i);
123 
124  if (!rename_file_(src, target))
125  {
126  // if failed try again after a small delay.
127  // this is a workaround to a windows issue, where very high rotation
128  // rates can cause the rename to fail with permission denied (because of antivirus?).
130  if (!rename_file_(src, target))
131  {
132  file_helper_.reopen(true); // truncate the log file anyway to prevent it to grow beyond its limit!
133  current_size_ = 0;
134  throw_spdlog_ex("rotating_file_sink: failed renaming " + filename_to_str(src) + " to " + filename_to_str(target), errno);
135  }
136  }
137  }
138  file_helper_.reopen(true);
139 }
140 
141 // delete the target if exists, and rename the src file to target
142 // return true on success, false otherwise.
143 template<typename Mutex>
144 SPDLOG_INLINE bool rotating_file_sink<Mutex>::rename_file_(const filename_t &src_filename, const filename_t &target_filename)
145 {
146  // try to delete the target file in case it already exists.
147  (void)details::os::remove(target_filename);
148  return details::os::rename(src_filename, target_filename) == 0;
149 }
150 
151 } // namespace sinks
152 } // namespace spdlog
file_helper.h
spdlog::file_event_handlers
Definition: common.h:308
mm_gui.target
target
Definition: mm_gui.py:125
spdlog::details::os::rename
SPDLOG_INLINE int rename(const filename_t &filename1, const filename_t &filename2) SPDLOG_NOEXCEPT
Definition: os-inl.h:177
spdlog::details::file_helper::split_by_extension
static std::tuple< filename_t, filename_t > split_by_extension(const filename_t &fname)
Definition: file_helper-inl.h:149
spdlog::details::os::sleep_for_millis
SPDLOG_INLINE void sleep_for_millis(unsigned int milliseconds) SPDLOG_NOEXCEPT
Definition: os-inl.h:376
spdlog::sinks::rotating_file_sink::rename_file_
bool rename_file_(const filename_t &src_filename, const filename_t &target_filename)
Definition: rotating_file_sink-inl.h:144
spdlog::sinks::rotating_file_sink::filename
filename_t filename()
Definition: rotating_file_sink-inl.h:68
spdlog::details::os::path_exists
SPDLOG_INLINE bool path_exists(const filename_t &filename) SPDLOG_NOEXCEPT
Definition: os-inl.h:187
fmt::v8::detail::buffer::size
constexpr auto size() const -> size_t
Definition: core.h:820
spdlog::sinks::rotating_file_sink::rotating_file_sink
rotating_file_sink(filename_t base_filename, std::size_t max_size, std::size_t max_files, bool rotate_on_open=false, const file_event_handlers &event_handlers={})
Definition: rotating_file_sink-inl.h:27
rotating_file_sink.h
index
index
Definition: parse_all_dl.m:11
filename
filename
Definition: parse_all_dl.m:14
null_mutex.h
fmt::v8::basic_memory_buffer
Definition: format.h:677
spdlog
Definition: async.h:25
spdlog::throw_spdlog_ex
SPDLOG_INLINE void throw_spdlog_ex(const std::string &msg, int last_errno)
Definition: common-inl.h:72
spdlog::sinks::rotating_file_sink::calc_filename
static filename_t calc_filename(const filename_t &filename, std::size_t index)
Definition: rotating_file_sink-inl.h:55
spdlog::sinks::base_sink
Definition: base_sink.h:19
i
for i
Definition: generate_data.m:107
spdlog::details::os::filename_to_str
SPDLOG_INLINE std::string filename_to_str(const filename_t &filename)
Definition: os-inl.h:398
nlohmann::json_v3_11_1NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON::detail::void
j template void())
Definition: json.hpp:4744
u
Plot Rx waveform for u
Definition: inspect_single_frame.m:108
spdlog::sinks::rotating_file_sink::flush_
void flush_() override
Definition: rotating_file_sink-inl.h:98
SPDLOG_INLINE
#define SPDLOG_INLINE
Definition: common.h:42
SPDLOG_FILENAME_T
#define SPDLOG_FILENAME_T(s)
Definition: common.h:123
spdlog::sinks::rotating_file_sink::rotate_
void rotate_()
Definition: rotating_file_sink-inl.h:109
common.h
spdlog::details::log_msg
Definition: log_msg.h:11
std
Definition: json.hpp:5213
spdlog::details::os::remove
SPDLOG_INLINE int remove(const filename_t &filename) SPDLOG_NOEXCEPT
Definition: os-inl.h:163
spdlog::sinks::rotating_file_sink::sink_it_
void sink_it_(const details::log_msg &msg) override
Definition: rotating_file_sink-inl.h:75
spdlog::filename_t
std::string filename_t
Definition: common.h:122
fmt.h
utils::format
std::string format(const T &value)
Definition: utils.h:15