1 //
2 // Copyright(c) 2015 Gabi Melman.
3 // Distributed under the MIT License (http://opensource.org/licenses/MIT)
4 //
5
6 #pragma once
7
8 #include <spdlog/logger.h>
9 #include <spdlog/sinks/stdout_sinks.h>
10
11 #include <memory>
12 #include <string>
13
14
15 // create logger with given name, sinks and the default pattern formatter
16 // all other ctors will call this one
17 template<class It>
logger(const std::string & logger_name,const It & begin,const It & end)18 inline spdlog::logger::logger(const std::string& logger_name, const It& begin, const It& end):
19 _name(logger_name),
20 _sinks(begin, end),
21 _formatter(std::make_shared<pattern_formatter>("%+"))
22 {
23 _level = level::info;
24 _flush_level = level::off;
25 _last_err_time = 0;
26 _err_handler = [this](const std::string &msg)
27 {
28 this->_default_err_handler(msg);
29 };
30 }
31
32 // ctor with sinks as init list
logger(const std::string & logger_name,sinks_init_list sinks_list)33 inline spdlog::logger::logger(const std::string& logger_name, sinks_init_list sinks_list):
34 logger(logger_name, sinks_list.begin(), sinks_list.end())
35 {}
36
37
38 // ctor with single sink
logger(const std::string & logger_name,spdlog::sink_ptr single_sink)39 inline spdlog::logger::logger(const std::string& logger_name, spdlog::sink_ptr single_sink):
40 logger(logger_name,
41 {
42 single_sink
43 })
44 {}
45
46
47 inline spdlog::logger::~logger() = default;
48
49
set_formatter(spdlog::formatter_ptr msg_formatter)50 inline void spdlog::logger::set_formatter(spdlog::formatter_ptr msg_formatter)
51 {
52 _set_formatter(msg_formatter);
53 }
54
set_pattern(const std::string & pattern)55 inline void spdlog::logger::set_pattern(const std::string& pattern)
56 {
57 _set_pattern(pattern);
58 }
59
60
61 template <typename... Args>
log(level::level_enum lvl,const char * fmt,const Args &...args)62 inline void spdlog::logger::log(level::level_enum lvl, const char* fmt, const Args&... args)
63 {
64 if (!should_log(lvl)) return;
65
66 try
67 {
68 details::log_msg log_msg(&_name, lvl);
69 log_msg.raw.write(fmt, args...);
70 _sink_it(log_msg);
71 }
72 catch (const std::exception &ex)
73 {
74 _err_handler(ex.what());
75 }
76 catch (...)
77 {
78 _err_handler("Unknown exception");
79 }
80 }
81
82 template <typename... Args>
log(level::level_enum lvl,const char * msg)83 inline void spdlog::logger::log(level::level_enum lvl, const char* msg)
84 {
85 if (!should_log(lvl)) return;
86 try
87 {
88 details::log_msg log_msg(&_name, lvl);
89 log_msg.raw << msg;
90 _sink_it(log_msg);
91 }
92 catch (const std::exception &ex)
93 {
94 _err_handler(ex.what());
95 }
96 catch (...)
97 {
98 _err_handler("Unknown exception");
99 }
100
101 }
102
103 template<typename T>
log(level::level_enum lvl,const T & msg)104 inline void spdlog::logger::log(level::level_enum lvl, const T& msg)
105 {
106 if (!should_log(lvl)) return;
107 try
108 {
109 details::log_msg log_msg(&_name, lvl);
110 log_msg.raw << msg;
111 _sink_it(log_msg);
112 }
113 catch (const std::exception &ex)
114 {
115 _err_handler(ex.what());
116 }
117 catch (...)
118 {
119 _err_handler("Unknown exception");
120 }
121 }
122
123
124 template <typename... Args>
trace(const char * fmt,const Args &...args)125 inline void spdlog::logger::trace(const char* fmt, const Args&... args)
126 {
127 log(level::trace, fmt, args...);
128 }
129
130 template <typename... Args>
debug(const char * fmt,const Args &...args)131 inline void spdlog::logger::debug(const char* fmt, const Args&... args)
132 {
133 log(level::debug, fmt, args...);
134 }
135
136 template <typename... Args>
info(const char * fmt,const Args &...args)137 inline void spdlog::logger::info(const char* fmt, const Args&... args)
138 {
139 log(level::info, fmt, args...);
140 }
141
142
143 template <typename... Args>
warn(const char * fmt,const Args &...args)144 inline void spdlog::logger::warn(const char* fmt, const Args&... args)
145 {
146 log(level::warn, fmt, args...);
147 }
148
149 template <typename... Args>
error(const char * fmt,const Args &...args)150 inline void spdlog::logger::error(const char* fmt, const Args&... args)
151 {
152 log(level::err, fmt, args...);
153 }
154
155 template <typename... Args>
critical(const char * fmt,const Args &...args)156 inline void spdlog::logger::critical(const char* fmt, const Args&... args)
157 {
158 log(level::critical, fmt, args...);
159 }
160
161
162 template<typename T>
trace(const T & msg)163 inline void spdlog::logger::trace(const T& msg)
164 {
165 log(level::trace, msg);
166 }
167
168 template<typename T>
debug(const T & msg)169 inline void spdlog::logger::debug(const T& msg)
170 {
171 log(level::debug, msg);
172 }
173
174
175 template<typename T>
info(const T & msg)176 inline void spdlog::logger::info(const T& msg)
177 {
178 log(level::info, msg);
179 }
180
181
182 template<typename T>
warn(const T & msg)183 inline void spdlog::logger::warn(const T& msg)
184 {
185 log(level::warn, msg);
186 }
187
188 template<typename T>
error(const T & msg)189 inline void spdlog::logger::error(const T& msg)
190 {
191 log(level::err, msg);
192 }
193
194 template<typename T>
critical(const T & msg)195 inline void spdlog::logger::critical(const T& msg)
196 {
197 log(level::critical, msg);
198 }
199
200
201
202
203 //
204 // name and level
205 //
name()206 inline const std::string& spdlog::logger::name() const
207 {
208 return _name;
209 }
210
set_level(spdlog::level::level_enum log_level)211 inline void spdlog::logger::set_level(spdlog::level::level_enum log_level)
212 {
213 _level.store(log_level);
214 }
215
set_error_handler(spdlog::log_err_handler err_handler)216 inline void spdlog::logger::set_error_handler(spdlog::log_err_handler err_handler)
217 {
218 _err_handler = err_handler;
219 }
220
error_handler()221 inline spdlog::log_err_handler spdlog::logger::error_handler()
222 {
223 return _err_handler;
224 }
225
226
flush_on(level::level_enum log_level)227 inline void spdlog::logger::flush_on(level::level_enum log_level)
228 {
229 _flush_level.store(log_level);
230 }
231
level()232 inline spdlog::level::level_enum spdlog::logger::level() const
233 {
234 return static_cast<spdlog::level::level_enum>(_level.load(std::memory_order_relaxed));
235 }
236
should_log(spdlog::level::level_enum msg_level)237 inline bool spdlog::logger::should_log(spdlog::level::level_enum msg_level) const
238 {
239 return msg_level >= _level.load(std::memory_order_relaxed);
240 }
241
242 //
243 // protected virtual called at end of each user log call (if enabled) by the line_logger
244 //
_sink_it(details::log_msg & msg)245 inline void spdlog::logger::_sink_it(details::log_msg& msg)
246 {
247 _formatter->format(msg);
248 for (auto &sink : _sinks)
249 {
250 if( sink->should_log( msg.level))
251 {
252 sink->log(msg);
253 }
254 }
255
256 if(_should_flush_on(msg))
257 flush();
258 }
259
_set_pattern(const std::string & pattern)260 inline void spdlog::logger::_set_pattern(const std::string& pattern)
261 {
262 _formatter = std::make_shared<pattern_formatter>(pattern);
263 }
_set_formatter(formatter_ptr msg_formatter)264 inline void spdlog::logger::_set_formatter(formatter_ptr msg_formatter)
265 {
266 _formatter = msg_formatter;
267 }
268
flush()269 inline void spdlog::logger::flush()
270 {
271 for (auto& sink : _sinks)
272 sink->flush();
273 }
274
_default_err_handler(const std::string & msg)275 inline void spdlog::logger::_default_err_handler(const std::string &msg)
276 {
277 auto now = time(nullptr);
278 if (now - _last_err_time < 60)
279 return;
280 auto tm_time = details::os::localtime(now);
281 char date_buf[100];
282 std::strftime(date_buf, sizeof(date_buf), "%Y-%m-%d %H:%M:%S", &tm_time);
283 details::log_msg err_msg;
284 err_msg.formatted.write("[*** LOG ERROR ***] [{}] [{}] [{}]{}", name(), msg, date_buf, details::os::eol);
285 sinks::stderr_sink_mt::instance()->log(err_msg);
286 _last_err_time = now;
287 }
288
_should_flush_on(const details::log_msg & msg)289 inline bool spdlog::logger::_should_flush_on(const details::log_msg &msg)
290 {
291 const auto flush_level = _flush_level.load(std::memory_order_relaxed);
292 return (msg.level >= flush_level) && (msg.level != level::off);
293 }
294
sinks()295 inline const std::vector<spdlog::sink_ptr>& spdlog::logger::sinks() const
296 {
297 return _sinks;
298 }
299