file_sinks.h
Go to the documentation of this file.
1 //
2 // Copyright(c) 2015 Gabi Melman.
3 // Distributed under the MIT License (http://opensource.org/licenses/MIT)
4 //
5 
6 #pragma once
7 
11 #include "opc/spdlog/fmt/fmt.h"
12 
13 #include <algorithm>
14 #include <chrono>
15 #include <cstdio>
16 #include <ctime>
17 #include <mutex>
18 #include <string>
19 #include <cerrno>
20 
21 namespace spdlog
22 {
23 namespace sinks
24 {
25 /*
26  * Trivial file sink with single file as target
27  */
28 template<class Mutex>
29 class simple_file_sink SPDLOG_FINAL : public base_sink < Mutex >
30 {
31 public:
32  explicit simple_file_sink(const filename_t &filename, bool truncate = false):_force_flush(false)
33  {
34  _file_helper.open(filename, truncate);
35  }
36 
37  void set_force_flush(bool force_flush)
38  {
39  _force_flush = force_flush;
40  }
41 
42 protected:
43  void _sink_it(const details::log_msg& msg) override
44  {
45  _file_helper.write(msg);
46  if(_force_flush)
47  _file_helper.flush();
48  }
49  void _flush() override
50  {
51  _file_helper.flush();
52  }
53 private:
56 };
57 
58 typedef simple_file_sink<std::mutex> simple_file_sink_mt;
59 typedef simple_file_sink<details::null_mutex> simple_file_sink_st;
60 
61 /*
62  * Rotating file sink based on size
63  */
64 template<class Mutex>
65 class rotating_file_sink SPDLOG_FINAL : public base_sink < Mutex >
66 {
67 public:
68  rotating_file_sink(const filename_t &base_filename,
69  std::size_t max_size, std::size_t max_files) :
70  _base_filename(base_filename),
71  _max_size(max_size),
72  _max_files(max_files),
73  _current_size(0),
74  _file_helper()
75  {
76  _file_helper.open(calc_filename(_base_filename, 0));
77  _current_size = _file_helper.size(); //expensive. called only once
78  }
79 
80 
81 protected:
82  void _sink_it(const details::log_msg& msg) override
83  {
84  _current_size += msg.formatted.size();
85  if (_current_size > _max_size)
86  {
87  _rotate();
88  _current_size = msg.formatted.size();
89  }
90  _file_helper.write(msg);
91  }
92 
93  void _flush() override
94  {
95  _file_helper.flush();
96  }
97 
98 private:
99  static filename_t calc_filename(const filename_t& filename, std::size_t index)
100  {
101  std::conditional<std::is_same<filename_t::value_type, char>::value, fmt::MemoryWriter, fmt::WMemoryWriter>::type w;
102  if (index)
103  w.write(SPDLOG_FILENAME_T("{}.{}"), filename, index);
104  else
105  w.write(SPDLOG_FILENAME_T("{}"), filename);
106  return w.str();
107  }
108 
109  // Rotate files:
110  // log.txt -> log.txt.1
111  // log.txt.1 -> log.txt.2
112  // log.txt.2 -> log.txt.3
113  // lo3.txt.3 -> delete
114 
115  void _rotate()
116  {
118  _file_helper.close();
119  for (auto i = _max_files; i > 0; --i)
120  {
121  filename_t src = calc_filename(_base_filename, i - 1);
122  filename_t target = calc_filename(_base_filename, i);
123 
125  {
126  if (details::os::remove(target) != 0)
127  {
128  throw spdlog_ex("rotating_file_sink: failed removing " + filename_to_str(target), errno);
129  }
130  }
132  {
133  throw spdlog_ex("rotating_file_sink: failed renaming " + filename_to_str(src) + " to " + filename_to_str(target), errno);
134  }
135  }
136  _file_helper.reopen(true);
137  }
139  std::size_t _max_size;
140  std::size_t _max_files;
141  std::size_t _current_size;
142  details::file_helper _file_helper;
143 };
144 
145 typedef rotating_file_sink<std::mutex> rotating_file_sink_mt;
146 typedef rotating_file_sink<details::null_mutex>rotating_file_sink_st;
147 
148 /*
149  * Default generator of daily log file names.
150  */
152 {
153  // Create filename for the form basename.YYYY-MM-DD_hh-mm
154  static filename_t calc_filename(const filename_t& basename)
155  {
156  std::tm tm = spdlog::details::os::localtime();
157  std::conditional<std::is_same<filename_t::value_type, char>::value, fmt::MemoryWriter, fmt::WMemoryWriter>::type w;
158  w.write(SPDLOG_FILENAME_T("{}_{:04d}-{:02d}-{:02d}_{:02d}-{:02d}"), basename, tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min);
159  return w.str();
160  }
161 };
162 
163 /*
164  * Generator of daily log file names in format basename.YYYY-MM-DD
165  */
167 {
168  // Create filename for the form basename.YYYY-MM-DD
169  static filename_t calc_filename(const filename_t& basename)
170  {
171  std::tm tm = spdlog::details::os::localtime();
172  std::conditional<std::is_same<filename_t::value_type, char>::value, fmt::MemoryWriter, fmt::WMemoryWriter>::type w;
173  w.write(SPDLOG_FILENAME_T("{}_{:04d}-{:02d}-{:02d}"), basename, tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday);
174  return w.str();
175  }
176 };
177 
178 /*
179  * Rotating file sink based on date. rotates at midnight
180  */
181 template<class Mutex, class FileNameCalc = default_daily_file_name_calculator>
182 class daily_file_sink SPDLOG_FINAL :public base_sink < Mutex >
183 {
184 public:
185  //create daily file sink which rotates on given time
187  const filename_t& base_filename,
188  int rotation_hour,
189  int rotation_minute) : _base_filename(base_filename),
190  _rotation_h(rotation_hour),
191  _rotation_m(rotation_minute)
192  {
193  if (rotation_hour < 0 || rotation_hour > 23 || rotation_minute < 0 || rotation_minute > 59)
194  throw spdlog_ex("daily_file_sink: Invalid rotation time in ctor");
195  _rotation_tp = _next_rotation_tp();
196  _file_helper.open(FileNameCalc::calc_filename(_base_filename));
197  }
198 
199 
200 protected:
201  void _sink_it(const details::log_msg& msg) override
202  {
203  if (std::chrono::system_clock::now() >= _rotation_tp)
204  {
205  _file_helper.open(FileNameCalc::calc_filename(_base_filename));
206  _rotation_tp = _next_rotation_tp();
207  }
208  _file_helper.write(msg);
209  }
210 
211  void _flush() override
212  {
213  _file_helper.flush();
214  }
215 
216 private:
217  std::chrono::system_clock::time_point _next_rotation_tp()
218  {
220  time_t tnow = std::chrono::system_clock::to_time_t(now);
221  tm date = spdlog::details::os::localtime(tnow);
222  date.tm_hour = _rotation_h;
223  date.tm_min = _rotation_m;
224  date.tm_sec = 0;
225  auto rotation_time = std::chrono::system_clock::from_time_t(std::mktime(&date));
226  if (rotation_time > now)
227  return rotation_time;
228  else
229  return std::chrono::system_clock::time_point(rotation_time + std::chrono::hours(24));
230  }
231 
232  filename_t _base_filename;
235  std::chrono::system_clock::time_point _rotation_tp;
236  details::file_helper _file_helper;
237 };
238 
239 typedef daily_file_sink<std::mutex> daily_file_sink_mt;
240 typedef daily_file_sink<details::null_mutex> daily_file_sink_st;
241 }
242 }
daily_file_sink< std::mutex > daily_file_sink_mt
Definition: file_sinks.h:239
details::file_helper _file_helper
Definition: file_sinks.h:54
int rename(const filename_t &filename1, const filename_t &filename2)
Definition: os.h:190
int remove(const filename_t &filename)
Definition: os.h:181
void write(BasicCStringRef< Char > format, ArgList args)
Definition: format.h:2918
spdlog::log_clock::time_point now()
Definition: os.h:64
static bool file_exists(const filename_t &name)
Definition: file_helper.h:106
static filename_t calc_filename(const filename_t &basename)
Definition: file_sinks.h:154
BasicMemoryWriter< char > MemoryWriter
Definition: format.h:3558
rotating_file_sink(const filename_t &base_filename, std::size_t max_size, std::size_t max_files)
Definition: file_sinks.h:68
std::chrono::system_clock::time_point _rotation_tp
Definition: file_sinks.h:235
std::tm localtime(const std::time_t &time_tt)
Definition: os.h:80
rotating_file_sink< std::mutex > rotating_file_sink_mt
Definition: file_sinks.h:145
static filename_t calc_filename(const filename_t &basename)
Definition: file_sinks.h:169
std::string filename_t
simple_file_sink(const filename_t &filename, bool truncate=false)
Definition: file_sinks.h:32
void _flush() override
Definition: file_sinks.h:49
fmt::MemoryWriter formatted
Definition: log_msg.h:46
std::size_t size() const
Definition: format.h:2857
rotating_file_sink< details::null_mutex > rotating_file_sink_st
Definition: file_sinks.h:146
void _sink_it(const details::log_msg &msg) override
Definition: file_sinks.h:43
std::chrono::system_clock::time_point _next_rotation_tp()
Definition: file_sinks.h:217
daily_file_sink(const filename_t &base_filename, int rotation_hour, int rotation_minute)
Definition: file_sinks.h:186
#define SPDLOG_FILENAME_T(s)
Definition: os.h:365
static filename_t calc_filename(const filename_t &filename, std::size_t index)
Definition: file_sinks.h:99
daily_file_sink< details::null_mutex > daily_file_sink_st
Definition: file_sinks.h:240
void set_force_flush(bool force_flush)
Definition: file_sinks.h:37
std::string filename_to_str(const filename_t &filename)
Definition: os.h:366
simple_file_sink< std::mutex > simple_file_sink_mt
Definition: file_sinks.h:58
simple_file_sink< details::null_mutex > simple_file_sink_st
Definition: file_sinks.h:59


ros_opcua_impl_freeopcua
Author(s): Denis Štogl
autogenerated on Tue Jan 19 2021 03:06:04