1 | // |
---|
2 | // Logger.h |
---|
3 | // |
---|
4 | // $Id: //poco/1.3/Foundation/include/Poco/Logger.h#3 $ |
---|
5 | // |
---|
6 | // Library: Foundation |
---|
7 | // Package: Logging |
---|
8 | // Module: Logger |
---|
9 | // |
---|
10 | // Definition of the Logger class. |
---|
11 | // |
---|
12 | // Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. |
---|
13 | // and Contributors. |
---|
14 | // |
---|
15 | // Permission is hereby granted, free of charge, to any person or organization |
---|
16 | // obtaining a copy of the software and accompanying documentation covered by |
---|
17 | // this license (the "Software") to use, reproduce, display, distribute, |
---|
18 | // execute, and transmit the Software, and to prepare derivative works of the |
---|
19 | // Software, and to permit third-parties to whom the Software is furnished to |
---|
20 | // do so, all subject to the following: |
---|
21 | // |
---|
22 | // The copyright notices in the Software and this entire statement, including |
---|
23 | // the above license grant, this restriction and the following disclaimer, |
---|
24 | // must be included in all copies of the Software, in whole or in part, and |
---|
25 | // all derivative works of the Software, unless such copies or derivative |
---|
26 | // works are solely in the form of machine-executable object code generated by |
---|
27 | // a source language processor. |
---|
28 | // |
---|
29 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
---|
30 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
---|
31 | // FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT |
---|
32 | // SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE |
---|
33 | // FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, |
---|
34 | // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
---|
35 | // DEALINGS IN THE SOFTWARE. |
---|
36 | // |
---|
37 | |
---|
38 | |
---|
39 | #ifndef Foundation_Logger_INCLUDED |
---|
40 | #define Foundation_Logger_INCLUDED |
---|
41 | |
---|
42 | |
---|
43 | #include "Poco/Foundation.h" |
---|
44 | #include "Poco/Channel.h" |
---|
45 | #include "Poco/Message.h" |
---|
46 | #include <map> |
---|
47 | #include <vector> |
---|
48 | #include <cstddef> |
---|
49 | |
---|
50 | |
---|
51 | namespace Poco { |
---|
52 | |
---|
53 | |
---|
54 | class Exception; |
---|
55 | |
---|
56 | |
---|
57 | class Foundation_API Logger: public Channel |
---|
58 | /// Logger is a special Channel that acts as the main |
---|
59 | /// entry point into the logging framework. |
---|
60 | /// |
---|
61 | /// An application uses instances of the Logger class to generate its log messages |
---|
62 | /// and send them on their way to their final destination. Logger instances |
---|
63 | /// are organized in a hierarchical, tree-like manner and are maintained by |
---|
64 | /// the framework. Every Logger object has exactly one direct ancestor, with |
---|
65 | /// the exception of the root logger. A newly created logger inherits its properties - |
---|
66 | /// channel and level - from its direct ancestor. Every logger is connected |
---|
67 | /// to a channel, to which it passes on its messages. Furthermore, every logger |
---|
68 | /// has a log level, which is used for filtering messages based on their priority. |
---|
69 | /// Only messages with a priority equal to or higher than the specified level |
---|
70 | /// are passed on. For example, if the level of a logger is set to three (PRIO_ERROR), |
---|
71 | /// only messages with priority PRIO_ERROR, PRIO_CRITICAL and PRIO_FATAL will |
---|
72 | /// propagate. If the level is set to zero, the logger is effectively disabled. |
---|
73 | /// |
---|
74 | /// The name of a logger determines the logger's place within the logger hierarchy. |
---|
75 | /// The name of the root logger is always "", the empty string. For all other |
---|
76 | /// loggers, the name is made up of one or more components, separated by a period. |
---|
77 | /// For example, the loggers with the name HTTPServer.RequestHandler and HTTPServer.Listener |
---|
78 | /// are descendants of the logger HTTPServer, which itself is a descendant of |
---|
79 | /// the root logger. There is not limit as to how deep |
---|
80 | /// the logger hierarchy can become. Once a logger has been created and it has |
---|
81 | /// inherited the channel and level from its ancestor, it loses the connection |
---|
82 | /// to it. So changes to the level or channel of a logger do not affect its |
---|
83 | /// descendants. This greatly simplifies the implementation of the framework |
---|
84 | /// and is no real restriction, because almost always levels and channels are |
---|
85 | /// set up at application startup and never changed afterwards. Nevertheless, |
---|
86 | /// there are methods to simultaneously change the level and channel of all |
---|
87 | /// loggers in a certain hierarchy. |
---|
88 | { |
---|
89 | public: |
---|
90 | const std::string& name() const; |
---|
91 | /// Returns the name of the logger, which is set as the |
---|
92 | /// message source on all messages created by the logger. |
---|
93 | |
---|
94 | void setChannel(Channel* pChannel); |
---|
95 | /// Attaches the given Channel to the Logger. |
---|
96 | |
---|
97 | Channel* getChannel() const; |
---|
98 | /// Returns the Channel attached to the logger. |
---|
99 | |
---|
100 | void setLevel(int level); |
---|
101 | /// Sets the Logger's log level. |
---|
102 | |
---|
103 | int getLevel() const; |
---|
104 | /// Returns the Logger's log level. |
---|
105 | |
---|
106 | void setLevel(const std::string& level); |
---|
107 | /// Sets the Logger's log level using a symbolic value. |
---|
108 | /// |
---|
109 | /// Valid values are: |
---|
110 | /// - fatal |
---|
111 | /// - critical |
---|
112 | /// - error |
---|
113 | /// - warning |
---|
114 | /// - notice |
---|
115 | /// - information |
---|
116 | /// - debug |
---|
117 | /// - trace |
---|
118 | |
---|
119 | void setProperty(const std::string& name, const std::string& value); |
---|
120 | /// Sets or changes a configuration property. |
---|
121 | /// |
---|
122 | /// Only the "channel" and "level" properties are supported, which allow |
---|
123 | /// setting the target channel and log level, respectively, via the LoggingRegistry. |
---|
124 | /// The "channel" and "level" properties are set-only. |
---|
125 | |
---|
126 | void log(const Message& msg); |
---|
127 | /// Logs the given message if its priority is |
---|
128 | /// greater than or equal to the Logger's log level. |
---|
129 | |
---|
130 | void log(const Exception& exc); |
---|
131 | /// Logs the given exception with priority PRIO_ERROR. |
---|
132 | |
---|
133 | void fatal(const std::string& msg); |
---|
134 | /// If the Logger's log level is at least PRIO_FATAL, |
---|
135 | /// creates a Message with priority PRIO_FATAL |
---|
136 | /// and the given message text and sends it |
---|
137 | /// to the attached channel. |
---|
138 | |
---|
139 | void critical(const std::string& msg); |
---|
140 | /// If the Logger's log level is at least PRIO_CRITICAL, |
---|
141 | /// creates a Message with priority PRIO_CRITICAL |
---|
142 | /// and the given message text and sends it |
---|
143 | /// to the attached channel. |
---|
144 | |
---|
145 | void error(const std::string& msg); |
---|
146 | /// If the Logger's log level is at least PRIO_ERROR, |
---|
147 | /// creates a Message with priority PRIO_ERROR |
---|
148 | /// and the given message text and sends it |
---|
149 | /// to the attached channel. |
---|
150 | |
---|
151 | void warning(const std::string& msg); |
---|
152 | /// If the Logger's log level is at least PRIO_WARNING, |
---|
153 | /// creates a Message with priority PRIO_WARNING |
---|
154 | /// and the given message text and sends it |
---|
155 | /// to the attached channel. |
---|
156 | |
---|
157 | void notice(const std::string& msg); |
---|
158 | /// If the Logger's log level is at least PRIO_NOTICE, |
---|
159 | /// creates a Message with priority PRIO_NOTICE |
---|
160 | /// and the given message text and sends it |
---|
161 | /// to the attached channel. |
---|
162 | |
---|
163 | void information(const std::string& msg); |
---|
164 | /// If the Logger's log level is at least PRIO_INFORMATION, |
---|
165 | /// creates a Message with priority PRIO_INFORMATION |
---|
166 | /// and the given message text and sends it |
---|
167 | /// to the attached channel. |
---|
168 | |
---|
169 | void debug(const std::string& msg); |
---|
170 | /// If the Logger's log level is at least PRIO_DEBUG, |
---|
171 | /// creates a Message with priority PRIO_DEBUG |
---|
172 | /// and the given message text and sends it |
---|
173 | /// to the attached channel. |
---|
174 | |
---|
175 | void trace(const std::string& msg); |
---|
176 | /// If the Logger's log level is at least PRIO_TRACE, |
---|
177 | /// creates a Message with priority PRIO_TRACE |
---|
178 | /// and the given message text and sends it |
---|
179 | /// to the attached channel. |
---|
180 | |
---|
181 | void dump(const std::string& msg, const void* buffer, std::size_t length, Message::Priority prio = Message::PRIO_DEBUG); |
---|
182 | /// Logs the given message, followed by the data in buffer. |
---|
183 | /// |
---|
184 | /// The data in buffer is written in canonical hex+ASCII form: |
---|
185 | /// Offset (4 bytes) in hexadecimal, followed by sixteen |
---|
186 | /// space-separated, two column, hexadecimal bytes, |
---|
187 | /// followed by the same sixteen bytes as ASCII characters. |
---|
188 | /// For bytes outside the range 32 .. 127, a dot is printed. |
---|
189 | |
---|
190 | bool is(int level) const; |
---|
191 | /// Returns true if at least the given log level is set. |
---|
192 | |
---|
193 | bool fatal() const; |
---|
194 | /// Returns true if the log level is at least PRIO_FATAL. |
---|
195 | |
---|
196 | bool critical() const; |
---|
197 | /// Returns true if the log level is at least PRIO_CRITICAL. |
---|
198 | |
---|
199 | bool error() const; |
---|
200 | /// Returns true if the log level is at least PRIO_ERROR. |
---|
201 | |
---|
202 | bool warning() const; |
---|
203 | /// Returns true if the log level is at least PRIO_WARNING. |
---|
204 | |
---|
205 | bool notice() const; |
---|
206 | /// Returns true if the log level is at least PRIO_NOTICE. |
---|
207 | |
---|
208 | bool information() const; |
---|
209 | /// Returns true if the log level is at least PRIO_INFORMATION. |
---|
210 | |
---|
211 | bool debug() const; |
---|
212 | /// Returns true if the log level is at least PRIO_DEBUG. |
---|
213 | |
---|
214 | bool trace() const; |
---|
215 | /// Returns true if the log level is at least PRIO_TRACE. |
---|
216 | |
---|
217 | static std::string format(const std::string& fmt, const std::string& arg); |
---|
218 | /// Replaces all occurences of $0 in fmt with the string given in arg and |
---|
219 | /// returns the result. To include a dollar sign in the result string, |
---|
220 | /// specify two dollar signs ($$) in the format string. |
---|
221 | |
---|
222 | static std::string format(const std::string& fmt, const std::string& arg0, const std::string& arg1); |
---|
223 | /// Replaces all occurences of $<n> in fmt with the string given in arg<n> and |
---|
224 | /// returns the result. To include a dollar sign in the result string, |
---|
225 | /// specify two dollar signs ($$) in the format string. |
---|
226 | |
---|
227 | static std::string format(const std::string& fmt, const std::string& arg0, const std::string& arg1, const std::string& arg2); |
---|
228 | /// Replaces all occurences of $<n> in fmt with the string given in arg<n> and |
---|
229 | /// returns the result. To include a dollar sign in the result string, |
---|
230 | /// specify two dollar signs ($$) in the format string. |
---|
231 | |
---|
232 | static std::string format(const std::string& fmt, const std::string& arg0, const std::string& arg1, const std::string& arg2, const std::string& arg3); |
---|
233 | /// Replaces all occurences of $<n> in fmt with the string given in arg<n> and |
---|
234 | /// returns the result. To include a dollar sign in the result string, |
---|
235 | /// specify two dollar signs ($$) in the format string. |
---|
236 | |
---|
237 | static void setLevel(const std::string& name, int level); |
---|
238 | /// Sets the given log level on all loggers that are |
---|
239 | /// descendants of the Logger with the given name. |
---|
240 | |
---|
241 | static void setChannel(const std::string& name, Channel* pChannel); |
---|
242 | /// Attaches the given Channel to all loggers that are |
---|
243 | /// descendants of the Logger with the given name. |
---|
244 | |
---|
245 | static void setProperty(const std::string& loggerName, const std::string& propertyName, const std::string& value); |
---|
246 | /// Sets or changes a configuration property for all loggers |
---|
247 | /// that are descendants of the Logger with the given name. |
---|
248 | |
---|
249 | static Logger& get(const std::string& name); |
---|
250 | /// Returns a reference to the Logger with the given name. |
---|
251 | /// If the Logger does not yet exist, it is created, based |
---|
252 | /// on its parent logger. |
---|
253 | |
---|
254 | static Logger& unsafeGet(const std::string& name); |
---|
255 | /// Returns a reference to the Logger with the given name. |
---|
256 | /// If the Logger does not yet exist, it is created, based |
---|
257 | /// on its parent logger. |
---|
258 | /// |
---|
259 | /// WARNING: This method is not thread safe. You should |
---|
260 | /// probably use get() instead. |
---|
261 | /// The only time this method should be used is during |
---|
262 | /// program initialization, when only one thread is running. |
---|
263 | |
---|
264 | static Logger& create(const std::string& name, Channel* pChannel, int level = Message::PRIO_INFORMATION); |
---|
265 | /// Creates and returns a reference to a Logger with the |
---|
266 | /// given name. The Logger's Channel and log level as set as |
---|
267 | /// specified. |
---|
268 | |
---|
269 | static Logger& root(); |
---|
270 | /// Returns a reference to the root logger, which is the ultimate |
---|
271 | /// ancestor of all Loggers. |
---|
272 | |
---|
273 | static Logger* has(const std::string& name); |
---|
274 | /// Returns a pointer to the Logger with the given name if it |
---|
275 | /// exists, or a null pointer otherwse. |
---|
276 | |
---|
277 | static void destroy(const std::string& name); |
---|
278 | /// Destroys the logger with the specified name. Does nothing |
---|
279 | /// if the logger is not found. |
---|
280 | /// |
---|
281 | /// After a logger has been destroyed, all references to it |
---|
282 | /// become invalid. |
---|
283 | |
---|
284 | static void shutdown(); |
---|
285 | /// Shuts down the logging framework and releases all |
---|
286 | /// Loggers. |
---|
287 | |
---|
288 | static void names(std::vector<std::string>& names); |
---|
289 | /// Fills the given vector with the names |
---|
290 | /// of all currently defined loggers. |
---|
291 | |
---|
292 | static const std::string ROOT; /// The name of the root logger (""). |
---|
293 | |
---|
294 | protected: |
---|
295 | typedef std::map<std::string, Logger*> LoggerMap; |
---|
296 | |
---|
297 | Logger(const std::string& name, Channel* pChannel, int level); |
---|
298 | ~Logger(); |
---|
299 | |
---|
300 | void log(const std::string& text, Message::Priority prio); |
---|
301 | |
---|
302 | static std::string format(const std::string& fmt, int argc, std::string argv[]); |
---|
303 | static void formatDump(std::string& message, const void* buffer, std::size_t length); |
---|
304 | static Logger& parent(const std::string& name); |
---|
305 | static void add(Logger* pLogger); |
---|
306 | static Logger* find(const std::string& name); |
---|
307 | |
---|
308 | private: |
---|
309 | Logger(); |
---|
310 | Logger(const Logger&); |
---|
311 | Logger& operator = (const Logger&); |
---|
312 | |
---|
313 | std::string _name; |
---|
314 | Channel* _pChannel; |
---|
315 | int _level; |
---|
316 | |
---|
317 | static LoggerMap* _pLoggerMap; |
---|
318 | static Mutex _mapMtx; |
---|
319 | }; |
---|
320 | |
---|
321 | |
---|
322 | // |
---|
323 | // convenience macros |
---|
324 | // |
---|
325 | #define poco_fatal(logger, msg) \ |
---|
326 | if ((logger).fatal()) (logger).fatal(msg); else (void) 0 |
---|
327 | |
---|
328 | #define poco_critical(logger, msg) \ |
---|
329 | if ((logger).critical()) (logger).critical(msg); else (void) 0 |
---|
330 | |
---|
331 | #define poco_error(logger, msg) \ |
---|
332 | if ((logger).error()) (logger).error(msg); else (void) 0 |
---|
333 | |
---|
334 | #define poco_warning(logger, msg) \ |
---|
335 | if ((logger).warning()) (logger).warning(msg); else (void) 0 |
---|
336 | |
---|
337 | #define poco_notice(logger, msg) \ |
---|
338 | if ((logger).notice()) (logger).notice(msg); else (void) 0 |
---|
339 | |
---|
340 | #define poco_information(logger, msg) \ |
---|
341 | if ((logger).information()) (logger).information(msg); else (void) 0 |
---|
342 | |
---|
343 | #if defined(_DEBUG) |
---|
344 | #define poco_debug(logger, msg) \ |
---|
345 | if ((logger).debug()) (logger).debug(msg); else (void) 0 |
---|
346 | |
---|
347 | #define poco_trace(logger, msg) \ |
---|
348 | if ((logger).trace()) (logger).trace(msg); else (void) 0 |
---|
349 | #else |
---|
350 | #define poco_debug(logger, msg) |
---|
351 | #define poco_trace(logger, msg) |
---|
352 | #endif |
---|
353 | |
---|
354 | |
---|
355 | // |
---|
356 | // inlines |
---|
357 | // |
---|
358 | inline const std::string& Logger::name() const |
---|
359 | { |
---|
360 | return _name; |
---|
361 | } |
---|
362 | |
---|
363 | |
---|
364 | inline int Logger::getLevel() const |
---|
365 | { |
---|
366 | return _level; |
---|
367 | } |
---|
368 | |
---|
369 | |
---|
370 | inline void Logger::log(const std::string& text, Message::Priority prio) |
---|
371 | { |
---|
372 | if (_level >= prio && _pChannel) |
---|
373 | { |
---|
374 | _pChannel->log(Message(_name, text, prio)); |
---|
375 | } |
---|
376 | } |
---|
377 | |
---|
378 | |
---|
379 | inline void Logger::fatal(const std::string& msg) |
---|
380 | { |
---|
381 | log(msg, Message::PRIO_FATAL); |
---|
382 | } |
---|
383 | |
---|
384 | |
---|
385 | inline void Logger::critical(const std::string& msg) |
---|
386 | { |
---|
387 | log(msg, Message::PRIO_CRITICAL); |
---|
388 | } |
---|
389 | |
---|
390 | |
---|
391 | inline void Logger::error(const std::string& msg) |
---|
392 | { |
---|
393 | log(msg, Message::PRIO_ERROR); |
---|
394 | } |
---|
395 | |
---|
396 | |
---|
397 | inline void Logger::warning(const std::string& msg) |
---|
398 | { |
---|
399 | log(msg, Message::PRIO_WARNING); |
---|
400 | } |
---|
401 | |
---|
402 | |
---|
403 | inline void Logger::notice(const std::string& msg) |
---|
404 | { |
---|
405 | log(msg, Message::PRIO_NOTICE); |
---|
406 | } |
---|
407 | |
---|
408 | |
---|
409 | inline void Logger::information(const std::string& msg) |
---|
410 | { |
---|
411 | log(msg, Message::PRIO_INFORMATION); |
---|
412 | } |
---|
413 | |
---|
414 | |
---|
415 | inline void Logger::debug(const std::string& msg) |
---|
416 | { |
---|
417 | log(msg, Message::PRIO_DEBUG); |
---|
418 | } |
---|
419 | |
---|
420 | |
---|
421 | inline void Logger::trace(const std::string& msg) |
---|
422 | { |
---|
423 | log(msg, Message::PRIO_TRACE); |
---|
424 | } |
---|
425 | |
---|
426 | |
---|
427 | inline bool Logger::is(int level) const |
---|
428 | { |
---|
429 | return _level >= level; |
---|
430 | } |
---|
431 | |
---|
432 | |
---|
433 | inline bool Logger::fatal() const |
---|
434 | { |
---|
435 | return _level >= Message::PRIO_FATAL; |
---|
436 | } |
---|
437 | |
---|
438 | |
---|
439 | inline bool Logger::critical() const |
---|
440 | { |
---|
441 | return _level >= Message::PRIO_CRITICAL; |
---|
442 | } |
---|
443 | |
---|
444 | |
---|
445 | inline bool Logger::error() const |
---|
446 | { |
---|
447 | return _level >= Message::PRIO_ERROR; |
---|
448 | } |
---|
449 | |
---|
450 | |
---|
451 | inline bool Logger::warning() const |
---|
452 | { |
---|
453 | return _level >= Message::PRIO_WARNING; |
---|
454 | } |
---|
455 | |
---|
456 | |
---|
457 | inline bool Logger::notice() const |
---|
458 | { |
---|
459 | return _level >= Message::PRIO_NOTICE; |
---|
460 | } |
---|
461 | |
---|
462 | |
---|
463 | inline bool Logger::information() const |
---|
464 | { |
---|
465 | return _level >= Message::PRIO_INFORMATION; |
---|
466 | } |
---|
467 | |
---|
468 | |
---|
469 | inline bool Logger::debug() const |
---|
470 | { |
---|
471 | return _level >= Message::PRIO_DEBUG; |
---|
472 | } |
---|
473 | |
---|
474 | |
---|
475 | inline bool Logger::trace() const |
---|
476 | { |
---|
477 | return _level >= Message::PRIO_TRACE; |
---|
478 | } |
---|
479 | |
---|
480 | |
---|
481 | } // namespace Poco |
---|
482 | |
---|
483 | |
---|
484 | #endif // Foundation_Logger_INCLUDED |
---|