Commit | Line | Data |
---|---|---|
0e23f538 TJ |
1 | /* |
2 | The software in this package is distributed under the GNU General | |
3 | Public License version 2 (with a special exception described below). | |
4 | ||
5 | A copy of GNU General Public License (GPL) is included in this distribution, | |
6 | in the file COPYING.GPL. | |
7 | ||
8 | As a special exception, if other files instantiate templates or use macros | |
9 | or inline functions from this file, or you compile this file and link it | |
10 | with other works to produce a work based on this file, this file | |
11 | does not by itself cause the resulting work to be covered | |
12 | by the GNU General Public License. | |
13 | ||
14 | However the source code for this file must still be made available | |
15 | in accordance with section (3) of the GNU General Public License. | |
16 | ||
17 | This exception does not invalidate any other reasons why a work based | |
18 | on this file might be covered by the GNU General Public License. | |
19 | */ | |
b6fb82a2 RP |
20 | /** @file |
21 | * @brief implementaton of logging functions. | |
22 | * | |
23 | * @copyright © Copyright 2007-2008 by Intra2net AG | |
57924725 TJ |
24 | * |
25 | * @note Don't call loggers from global constructed objects | |
26 | * as this depends on the global object construction sequence. | |
b6fb82a2 RP |
27 | */ |
28 | ||
29 | #include "logfunc.hpp" | |
30 | ||
31 | #include <syslog.h> | |
32 | #include <cstdlib> | |
33 | #include <ctime> | |
34 | #include <algorithm> | |
35 | #include <iostream> | |
36 | #include <fstream> | |
37 | #include <unistd.h> | |
5efd35b1 | 38 | #include <string.h> |
b6fb82a2 | 39 | #include <boost/shared_ptr.hpp> |
57924725 TJ |
40 | #include <boost/thread/recursive_mutex.hpp> |
41 | #include <boost/thread/thread.hpp> | |
b6fb82a2 RP |
42 | |
43 | #include <stringfunc.hxx> | |
44 | #include <filefunc.hxx> | |
45 | ||
46 | ||
47 | namespace I2n | |
48 | { | |
49 | namespace Logger | |
50 | { | |
51 | ||
b6fb82a2 RP |
52 | /** |
53 | * @brief the global logger instance. | |
54 | * | |
55 | * This may be used in all cases wheer a specialized logger is not available | |
56 | * or shouldn't be used for some reason. | |
57 | */ | |
58 | PartLogger GlobalLogger(""); | |
59 | ||
60 | ||
61 | namespace | |
62 | { | |
63 | ||
f4fcef65 TJ |
64 | /// Global lock for the logger. Used during all syslog operations |
65 | /// and modification of our shared local variables. | |
66 | static boost::recursive_mutex LoggerLock; | |
67 | ||
b6fb82a2 RP |
68 | /* |
69 | ** local globals: | |
70 | */ | |
71 | ||
57924725 TJ |
72 | static std::string g_ident; |
73 | static Facility g_facility; | |
74 | static bool g_syslog_opened = false; | |
75 | static int g_max_level= LogLevel::Warning; | |
b6fb82a2 | 76 | |
57924725 | 77 | static bool g_stderr_log = false; |
b6fb82a2 | 78 | |
57924725 TJ |
79 | static std::string g_log_file_name; |
80 | static boost::shared_ptr< std::ofstream > g_log_stream_ptr; | |
b6fb82a2 RP |
81 | |
82 | /** | |
83 | * @brief lookup array for translating our log levels to syslog level. | |
84 | */ | |
57924725 | 85 | static int loglevel_2_syslog_level[ LogLevel::_LogLevel_END ] = { |
f61aeac1 RP |
86 | LOG_EMERG, |
87 | LOG_ALERT, | |
88 | LOG_CRIT, | |
89 | LOG_ERR, | |
90 | LOG_WARNING, | |
91 | LOG_NOTICE, | |
92 | LOG_INFO, | |
93 | LOG_DEBUG | |
b6fb82a2 RP |
94 | }; |
95 | ||
96 | ||
97 | /** | |
98 | * @brief lookup array for translating our log levels to a short (4 character) tag. | |
99 | * | |
100 | * These tags are used when logs are written to stderr or into a log file. | |
101 | */ | |
57924725 | 102 | static std::string loglevel_2_short_tag[ LogLevel::_LogLevel_END ] = { |
f61aeac1 RP |
103 | "EMRG", |
104 | "ALRT", | |
105 | "CRIT", | |
106 | "ERR ", | |
107 | "WARN", | |
108 | "NOTE", | |
109 | "INFO", | |
110 | "DBUG" | |
b6fb82a2 RP |
111 | }; |
112 | ||
113 | ||
114 | /** | |
115 | * @brief a copy of the current identifier used for syslog. | |
116 | * | |
117 | * Keeping a copy of this ident is necessary since openlog doen't copy it's first | |
118 | * argument but copies only the pointer! (what a **censored**!) | |
119 | */ | |
57924725 | 120 | static char* syslog_ident= NULL; |
b6fb82a2 RP |
121 | |
122 | ||
123 | /* | |
124 | ** functions: | |
125 | */ | |
126 | ||
127 | /** | |
128 | * @brief close syslog. | |
129 | */ | |
130 | void close_syslog() | |
131 | { | |
57924725 TJ |
132 | boost::recursive_mutex::scoped_lock lock(LoggerLock); |
133 | ||
f61aeac1 RP |
134 | if (g_syslog_opened) |
135 | { | |
136 | closelog(); | |
137 | if (syslog_ident) | |
138 | { | |
139 | free(syslog_ident); | |
140 | syslog_ident= NULL; | |
141 | } | |
142 | g_syslog_opened= false; | |
143 | } | |
b6fb82a2 RP |
144 | } // eo close_syslog() |
145 | ||
146 | ||
147 | /** | |
148 | * @brief open syslog. | |
149 | */ | |
150 | void open_syslog() | |
151 | { | |
57924725 TJ |
152 | boost::recursive_mutex::scoped_lock lock(LoggerLock); |
153 | ||
f61aeac1 RP |
154 | close_syslog(); |
155 | syslog_ident= strdup(g_ident.c_str()); | |
156 | openlog( syslog_ident, LOG_CONS|LOG_PID, g_facility); | |
157 | g_syslog_opened= true; | |
b6fb82a2 RP |
158 | } // eo open_syslog() |
159 | ||
160 | ||
161 | /** | |
162 | * @brief get syslog level from internal log level. | |
163 | * @param level log level. | |
164 | * @return syslog level | |
165 | */ | |
166 | int get_syslog_level( int level ) | |
167 | { | |
57924725 TJ |
168 | // Note: Thread safe |
169 | ||
d0d6eef7 | 170 | if (level >=0 && level < LogLevel::_LogLevel_END) |
f61aeac1 RP |
171 | { |
172 | return loglevel_2_syslog_level[level]; | |
173 | } | |
174 | return (level<0) ? (LOG_EMERG) : (LOG_DEBUG); | |
b6fb82a2 RP |
175 | } // eo get_syslog_level(int) |
176 | ||
177 | ||
178 | /** | |
179 | * @brief get a short tag for the log level (/ message type) | |
180 | * @param level the log level | |
181 | * @return a short tag for the level. | |
182 | */ | |
183 | std::string get_level_tag( int level ) | |
184 | { | |
57924725 TJ |
185 | // Note: Thread safe |
186 | ||
d0d6eef7 | 187 | if (level >=0 && level < LogLevel::_LogLevel_END) |
f61aeac1 RP |
188 | { |
189 | return loglevel_2_short_tag[level]; | |
190 | } | |
191 | return (level<0) ? loglevel_2_short_tag[0] : loglevel_2_short_tag[ LogLevel::_LogLevel_END -1 ]; | |
b6fb82a2 RP |
192 | } // eo get_level_tag(int) |
193 | ||
194 | ||
195 | /** | |
196 | * @brief the "real" log function which logs a message at a given level. | |
197 | * @param level the log level to log the message at. | |
198 | * @param msg the message. | |
199 | * | |
200 | * Write the message to every enabled log channel. | |
201 | * | |
202 | * If syslog is enabled the message is passed unmodified to syslog. | |
203 | * | |
204 | * If a stream log is enabled (stderr or file) then the message is prepended with date, time | |
205 | * and process information (like syslog does). The message is splitted at line ends and | |
206 | * consecutive lines are indented. | |
207 | */ | |
208 | void log_msg( int level, const std::string& msg) | |
209 | { | |
57924725 TJ |
210 | boost::recursive_mutex::scoped_lock lock(LoggerLock); |
211 | ||
f61aeac1 RP |
212 | if (not g_syslog_opened and not g_stderr_log and not g_log_stream_ptr) |
213 | { | |
214 | // if nothing is opened for logging: we activate syslog! | |
215 | enable_syslog(true); | |
216 | } | |
217 | ||
218 | if (g_syslog_opened) | |
219 | { | |
220 | ::syslog( get_syslog_level(level), "%s", msg.c_str()); | |
221 | } | |
222 | // file(/stream) logging: | |
223 | if (g_stderr_log or g_log_stream_ptr) // add more log "enabled" expressions here... | |
224 | { | |
225 | // here we need must do something more with the msg... | |
226 | std::string new_msg; | |
227 | std::string prefix; | |
228 | { | |
b6fb82a2 | 229 | std::ostringstream ostr; |
f61aeac1 | 230 | // add time stamp (syslog like: "Mon DD HH:MM:SS") : |
b6fb82a2 | 231 | { |
f61aeac1 RP |
232 | time_t t = time(NULL); |
233 | char buffer[32]; | |
234 | std::strftime(buffer, sizeof(buffer),"%b %d %H:%M:%S ", std::localtime(&t)); | |
235 | ostr << buffer; | |
b6fb82a2 | 236 | } |
f61aeac1 RP |
237 | ostr << get_level_tag(level) << " "; |
238 | ostr << g_ident << "[" << getpid() << "]: "; | |
239 | prefix= ostr.str(); | |
240 | } | |
241 | { | |
242 | { | |
243 | std::string indent_string(prefix.size(), ' '); | |
244 | std::list< std::string > parts; | |
245 | split_string( chomp(msg,"\n"), parts, "\n"); | |
246 | std::ostringstream ostr; | |
247 | ostr << prefix; | |
248 | for(std::list< std::string >::const_iterator it= parts.begin(); | |
249 | it != parts.end(); | |
250 | ++it) | |
251 | { | |
252 | if (it != parts.begin()) | |
253 | { | |
254 | ostr << indent_string; | |
255 | } | |
256 | ostr << *it << std::endl; | |
257 | } | |
258 | new_msg= ostr.str(); | |
259 | } | |
260 | } | |
261 | if (g_stderr_log) | |
262 | { | |
263 | std::cerr << new_msg; | |
264 | } | |
265 | if (g_log_stream_ptr) | |
266 | { | |
267 | *g_log_stream_ptr << new_msg << std::flush; | |
268 | } | |
269 | } | |
b6fb82a2 RP |
270 | } // eo log_msg |
271 | ||
272 | ||
273 | /** | |
274 | * @brief "real" log function for part messages. | |
275 | * @param level the log level. | |
276 | * @param part the part(/module) name(/id) | |
277 | * @param msg the log message. | |
278 | * | |
279 | * basically calls @a log(), but prepends the part (if not empty) in square brackets to the message. | |
280 | */ | |
281 | void log_part_msg( | |
f61aeac1 RP |
282 | int level, |
283 | const std::string& part, | |
284 | const std::string& msg) | |
285 | { | |
57924725 TJ |
286 | // Note: Locking is done in log_msg() |
287 | ||
f61aeac1 RP |
288 | if (!part.empty()) |
289 | { | |
290 | std::ostringstream ostr; | |
291 | ostr << "[" << part << "] " << msg; | |
292 | log_msg(level, ostr.str()); | |
293 | } | |
294 | else | |
295 | { | |
296 | log_msg(level, msg); | |
297 | } | |
b6fb82a2 RP |
298 | } // eo log_part_msg(int,const std::string&,const std::string&) |
299 | ||
300 | ||
b5d5a346 RP |
301 | /** |
302 | * @brief returns the name of the program (/binary) | |
303 | * @return the program name if it could be determined; generated name else. | |
304 | * | |
305 | * Tries to determine the name of the binary. | |
306 | * | |
307 | * If no name could be determined, one is built. | |
308 | */ | |
309 | std::string get_program_name() | |
310 | { | |
57924725 TJ |
311 | // Note: Thread safe |
312 | ||
b5d5a346 RP |
313 | std::string result; |
314 | // determine the program name: | |
315 | { | |
316 | // try to determine the name using the exe link: | |
317 | std::string exe_path; | |
318 | { | |
319 | std::ostringstream ostr; | |
320 | ostr << "/proc/" << ::getpid() << "/exe"; | |
321 | exe_path= ostr.str(); | |
322 | } | |
323 | std::string binary_path= read_link(exe_path); | |
324 | if (!binary_path.empty()) | |
325 | { | |
326 | result= basename(binary_path); | |
327 | } | |
328 | } | |
329 | if (result.empty()) | |
330 | { | |
331 | // no program name found up to this point. | |
332 | // make a name (as fallback solution): | |
333 | std::ostringstream ostr; | |
334 | ostr << "prg-" << ::getpid(); | |
335 | result= ostr.str(); | |
336 | } | |
337 | return result; | |
338 | } // eo get_program_name | |
339 | ||
340 | ||
b6fb82a2 RP |
341 | |
342 | void _cleanup() | |
343 | { | |
57924725 | 344 | // Note: Locking is done in close_syslog(); |
f61aeac1 RP |
345 | close_syslog(); |
346 | //TODO other cleanups? | |
b6fb82a2 RP |
347 | } // _cleanup |
348 | ||
349 | ||
350 | class __Initializer | |
351 | { | |
f61aeac1 RP |
352 | public: |
353 | __Initializer() | |
354 | { | |
355 | std::atexit( _cleanup ); | |
356 | } | |
b6fb82a2 RP |
357 | } __initialize; |
358 | ||
359 | ||
360 | } // eo namespace <anonymous> | |
361 | ||
362 | ||
363 | ||
364 | /* | |
365 | ** implementation of Facility | |
366 | */ | |
367 | ||
368 | ||
369 | const int Facility::AuthPriv= LOG_AUTH; | |
370 | const int Facility::Cron = LOG_CRON; | |
371 | const int Facility::Daemon = LOG_DAEMON; | |
372 | const int Facility::Kern = LOG_KERN; | |
373 | const int Facility::Mail = LOG_MAIL; | |
374 | const int Facility::News = LOG_NEWS; | |
375 | const int Facility::Syslog = LOG_SYSLOG; | |
376 | const int Facility::User = LOG_USER; | |
377 | const int Facility::UUCP = LOG_UUCP; | |
378 | const int Facility::Local0 = LOG_LOCAL0; | |
379 | const int Facility::Local1 = LOG_LOCAL1; | |
380 | const int Facility::Local2 = LOG_LOCAL2; | |
381 | const int Facility::Local3 = LOG_LOCAL3; | |
382 | const int Facility::Local4 = LOG_LOCAL4; | |
383 | const int Facility::Local5 = LOG_LOCAL5; | |
384 | const int Facility::Local6 = LOG_LOCAL6; | |
385 | const int Facility::Local7 = LOG_LOCAL7; | |
386 | ||
387 | ||
388 | ||
389 | /* | |
390 | ** implementation of PartLogger::LogHelper | |
391 | */ | |
392 | ||
393 | PartLogger::LogHelper::LogHelper(PartLogger& logger, int level, const SourceLocation& loc) | |
394 | : Logger(logger) | |
395 | , Level(level) | |
396 | , Location(loc) | |
397 | { | |
f61aeac1 | 398 | StreamPtr.reset(new std::ostringstream()); |
b6fb82a2 RP |
399 | } // eo PartLogger::LogHelper::LogHelper(PartLogger&,int) |
400 | ||
401 | PartLogger::LogHelper::LogHelper(const LogHelper& helper) | |
402 | : Logger(helper.Logger) | |
403 | , Level(helper.Level) | |
404 | , Location(helper.Location) | |
405 | , StreamPtr(helper.StreamPtr) | |
406 | { | |
407 | } // eo PartLogger::LogHelper::LogHelper(const LogHelper&) | |
408 | ||
409 | ||
410 | PartLogger::LogHelper::~LogHelper() | |
411 | { | |
f61aeac1 RP |
412 | if (StreamPtr.get()) |
413 | { | |
414 | if (Location) | |
415 | { | |
416 | //*m_stream_ptr << " at " << m_loc.Line << " in " << m_loc.FunctionName; | |
417 | *StreamPtr << " @" << Location.get_location_tag(); | |
418 | } | |
419 | std::string msg(StreamPtr->str()); | |
420 | if (!msg.empty()) | |
421 | { | |
422 | Logger.log(Level,msg); | |
423 | } | |
424 | } | |
b6fb82a2 RP |
425 | } // eo PartLogger::LogHelper::~LogHelper |
426 | ||
427 | ||
428 | /* | |
429 | ** implementation of PartLogger | |
430 | */ | |
431 | ||
432 | /** | |
433 | * constructor for a part logger. | |
434 | * @param part name of the part (module name) using the logger instance. | |
435 | */ | |
436 | PartLogger::PartLogger(const std::string& part) | |
437 | : Part(part) | |
438 | { | |
439 | } // eo PartLogger::PartLogger(const std.:string&) | |
440 | ||
441 | ||
442 | /** | |
443 | * @brief constructor for a part logger at module level. | |
444 | * @param loc the source location where the PartLogger is constructed. | |
445 | * | |
446 | * The part name is derived from the filename given with the source location by | |
447 | * using the basename and cutting off the C++ file suffix (if it is a well known one; | |
448 | * currently known extensions: cpp, cxx, c++, cc, C). | |
449 | */ | |
450 | PartLogger::PartLogger( const SourceLocation& loc ) | |
451 | { | |
f61aeac1 RP |
452 | if (loc.Line>0 && ! loc.File.empty()) |
453 | { | |
454 | std::string str= basename(loc.File); | |
455 | Part= remove_suffix(str,".cpp"); | |
456 | if (Part == str) Part= remove_suffix(str,".cxx"); | |
457 | if (Part == str) Part= remove_suffix(str,".c++"); | |
458 | if (Part == str) Part= remove_suffix(str,".cc"); | |
459 | if (Part == str) Part= remove_suffix(str,".C"); | |
460 | } | |
461 | else | |
462 | { | |
463 | Part="Unknown"; | |
464 | } | |
b6fb82a2 RP |
465 | }// PartLogger::PartLogger(const SourceLocation&) |
466 | ||
467 | ||
468 | PartLogger::~PartLogger() | |
469 | { | |
470 | } | |
471 | ||
472 | ||
473 | /** | |
474 | * generic log function. | |
475 | * @param level the log level. | |
476 | * @param msg the log message. | |
477 | */ | |
478 | void PartLogger::log(int level, const std::string msg) | |
479 | { | |
57924725 TJ |
480 | boost::recursive_mutex::scoped_lock lock(LoggerLock); |
481 | ||
f61aeac1 RP |
482 | if (level <= g_max_level) |
483 | { | |
484 | log_part_msg(level, Part, msg); | |
485 | } | |
b6fb82a2 RP |
486 | } // eo PartLogger::log(int,const std::string); |
487 | ||
488 | ||
489 | void PartLogger::fatal(const std::string& msg) | |
490 | { | |
f61aeac1 | 491 | log(LOG_EMERG,msg); |
b6fb82a2 RP |
492 | } // eo PartLogger::fatal(const std::string&) |
493 | ||
494 | ||
495 | void PartLogger::alert(const std::string& msg) | |
496 | { | |
f61aeac1 | 497 | log(LOG_ALERT,msg); |
b6fb82a2 RP |
498 | } // eo PartLogger::alert(const std::string&) |
499 | ||
500 | ||
501 | void PartLogger::critical(const std::string& msg) | |
502 | { | |
f61aeac1 | 503 | log(LOG_CRIT,msg); |
b6fb82a2 RP |
504 | } // eo PartLogger::critical(const std::string&) |
505 | ||
506 | ||
507 | void PartLogger::error(const std::string& msg) | |
508 | { | |
f61aeac1 | 509 | log(LOG_ERR, msg); |
b6fb82a2 RP |
510 | } // eo PartLogger::error(const std::string&) |
511 | ||
512 | ||
513 | void PartLogger::warning(const std::string& msg) | |
514 | { | |
f61aeac1 | 515 | log(LOG_WARNING, msg); |
b6fb82a2 RP |
516 | } // eo PartLogger::warning(const std::string&) |
517 | ||
518 | ||
519 | void PartLogger::notice(const std::string& msg) | |
520 | { | |
f61aeac1 | 521 | log(LOG_NOTICE, msg); |
b6fb82a2 RP |
522 | } // eo PartLogger::notice(const std::string&) |
523 | ||
524 | ||
525 | void PartLogger::info(const std::string& msg) | |
526 | { | |
f61aeac1 | 527 | log(LOG_INFO, msg); |
b6fb82a2 RP |
528 | } // eo PartLogger::info(const std::string&) |
529 | ||
530 | ||
531 | void PartLogger::debug(const std::string& msg) | |
532 | { | |
f61aeac1 | 533 | log(LOG_DEBUG, msg); |
b6fb82a2 RP |
534 | } // eo PartLogger::debug(const std::string&) |
535 | ||
536 | ||
537 | ||
538 | PartLogger::LogHelper PartLogger::fatal(const SourceLocation& loc) | |
539 | { | |
f61aeac1 | 540 | return PartLogger::LogHelper(*this,LOG_EMERG,loc); |
b6fb82a2 RP |
541 | } // eo PartLogger::fatal(const SourceLocation&) |
542 | ||
543 | ||
544 | PartLogger::LogHelper PartLogger::alert(const SourceLocation& loc) | |
545 | { | |
f61aeac1 | 546 | return PartLogger::LogHelper(*this,LOG_ALERT,loc); |
b6fb82a2 RP |
547 | } // eo PartLogger::alert(const SourceLocation&) |
548 | ||
549 | ||
550 | PartLogger::LogHelper PartLogger::critical(const SourceLocation& loc) | |
551 | { | |
f61aeac1 | 552 | return PartLogger::LogHelper(*this,LOG_CRIT,loc); |
b6fb82a2 RP |
553 | } // eo PartLogger::critical(const SourceLocation&) |
554 | ||
555 | ||
556 | PartLogger::LogHelper PartLogger::error(const SourceLocation& loc) | |
557 | { | |
f61aeac1 | 558 | return PartLogger::LogHelper(*this,LOG_ERR,loc); |
b6fb82a2 RP |
559 | } // eo PartLogger::error(const SourceLocation&) |
560 | ||
561 | ||
562 | PartLogger::LogHelper PartLogger::warning(const SourceLocation& loc) | |
563 | { | |
f61aeac1 | 564 | return PartLogger::LogHelper(*this,LOG_WARNING,loc); |
b6fb82a2 RP |
565 | } // eo PartLogger::warning(const SourceLocation&) |
566 | ||
567 | ||
568 | PartLogger::LogHelper PartLogger::notice(const SourceLocation& loc) | |
569 | { | |
f61aeac1 | 570 | return PartLogger::LogHelper(*this,LOG_NOTICE,loc); |
b6fb82a2 RP |
571 | } // eo PartLogger::notice(const SourceLocation&) |
572 | ||
573 | ||
574 | PartLogger::LogHelper PartLogger::info(const SourceLocation& loc) | |
575 | { | |
f61aeac1 | 576 | return PartLogger::LogHelper(*this,LOG_INFO,loc); |
b6fb82a2 RP |
577 | } // eo PartLogger::info(const SourceLocation&) |
578 | ||
579 | ||
580 | PartLogger::LogHelper PartLogger::debug(const SourceLocation& loc) | |
581 | { | |
f61aeac1 | 582 | return PartLogger::LogHelper(*this,LOG_DEBUG,loc); |
b6fb82a2 RP |
583 | } // eo PartLogger::debug(const SourceLocation&) |
584 | ||
585 | /* | |
586 | ** | |
587 | */ | |
588 | ||
589 | ||
590 | /** | |
591 | * enable logging to syslog with a name and a facility. | |
592 | * @param name the name used as ident. | |
593 | * @param facility the facility which should be used. | |
594 | */ | |
595 | void enable_syslog( const std::string& name, Facility facility ) | |
596 | { | |
57924725 TJ |
597 | boost::recursive_mutex::scoped_lock lock(LoggerLock); |
598 | ||
f61aeac1 RP |
599 | close_syslog(); |
600 | g_ident= name; | |
601 | g_facility= facility; | |
602 | open_syslog(); | |
b6fb82a2 RP |
603 | } // eo enable_syslog(const std::string,Facility) |
604 | ||
605 | ||
606 | /** | |
607 | * enable logging to syslog with a facility. | |
608 | * The ident is used from a previous call or (if none was set) is | |
609 | * determined by reading the program path from /proc/\<pid\>/exe. | |
610 | * @param facility the facility which should be used. | |
611 | */ | |
612 | void enable_syslog( Facility facility ) | |
613 | { | |
57924725 TJ |
614 | boost::recursive_mutex::scoped_lock lock(LoggerLock); |
615 | ||
f61aeac1 RP |
616 | if (g_ident.empty()) |
617 | { | |
b5d5a346 | 618 | g_ident= get_program_name(); |
f61aeac1 RP |
619 | } |
620 | close_syslog(); | |
621 | g_facility = facility; | |
622 | open_syslog(); | |
b6fb82a2 RP |
623 | } // eo enable_syslog(Facility) |
624 | ||
625 | ||
626 | /** | |
627 | * enable or disable logging to syslog. | |
628 | * @param enable whether the logging to syslog should be enabled or not. | |
629 | */ | |
630 | void enable_syslog( bool enable ) | |
631 | { | |
57924725 TJ |
632 | boost::recursive_mutex::scoped_lock lock(LoggerLock); |
633 | ||
f61aeac1 RP |
634 | if (enable) |
635 | { | |
636 | if (!g_syslog_opened) | |
637 | { | |
638 | enable_syslog( g_facility ); | |
639 | } | |
640 | } | |
641 | else // ! enable | |
642 | { | |
643 | close_syslog(); | |
644 | } | |
b6fb82a2 RP |
645 | } // eo enable_syslog(bool) |
646 | ||
647 | ||
648 | /** | |
649 | * enable/ disable loggin to stderr. | |
650 | * @param enable whether to enable or disable logging to stderr. | |
651 | */ | |
652 | void enable_stderr_log(bool enable) | |
653 | { | |
57924725 TJ |
654 | boost::recursive_mutex::scoped_lock lock(LoggerLock); |
655 | ||
f61aeac1 | 656 | g_stderr_log= enable; |
b6fb82a2 RP |
657 | } // eo enableStderr; |
658 | ||
659 | ||
660 | ||
661 | /** | |
662 | * enable logging to a file. | |
663 | * @param name path to the file. | |
664 | * | |
665 | * @note only one log file can be use at a time. | |
666 | */ | |
667 | void enable_log_file( const std::string& name ) | |
668 | { | |
57924725 TJ |
669 | boost::recursive_mutex::scoped_lock lock(LoggerLock); |
670 | ||
f61aeac1 RP |
671 | g_log_file_name= name; |
672 | g_log_stream_ptr.reset( new std::ofstream() ); | |
673 | g_log_stream_ptr->open( name.c_str(), std::ios::out|std::ios::app ); | |
674 | //std::cerr << "### opened \"" << name << "\"" << g_log_stream_ptr->good() << std::endl; | |
b6fb82a2 RP |
675 | } // eo enable_log_file(const std::string&) |
676 | ||
677 | ||
678 | /** | |
679 | * enable or disable loggin to a file. | |
b5d5a346 RP |
680 | * if a logfile was already set by a previous call to enable_log_file(const std::string&) |
681 | * that one is used; else it logs to <tt>/var/log/</tt><em>program name</em><tt>.log</tt>. | |
b6fb82a2 RP |
682 | * @param enable whether to enable or disable logging to a file. |
683 | */ | |
684 | void enable_log_file( bool enable ) | |
685 | { | |
57924725 TJ |
686 | boost::recursive_mutex::scoped_lock lock(LoggerLock); |
687 | ||
f61aeac1 RP |
688 | if (enable) |
689 | { | |
b5d5a346 RP |
690 | if (g_log_file_name.empty()) |
691 | { | |
692 | std::ostringstream ostr; | |
693 | ostr << "/var/log/" << get_program_name() << ".log"; | |
694 | enable_log_file( ostr.str() ); | |
695 | } | |
696 | else | |
f61aeac1 RP |
697 | { |
698 | enable_log_file( g_log_file_name ); | |
699 | } | |
700 | } | |
701 | else // ! enable | |
702 | { | |
703 | g_log_stream_ptr.reset(); | |
704 | } | |
b6fb82a2 RP |
705 | } // eo enable_log_file(bool) |
706 | ||
707 | ||
b5d5a346 RP |
708 | /** |
709 | * @brief returns if loging to file is enabled and active. | |
710 | * @return @a true if logfile is enabled and opened. | |
711 | */ | |
712 | bool is_logging_to_file() | |
713 | { | |
57924725 TJ |
714 | boost::recursive_mutex::scoped_lock lock(LoggerLock); |
715 | ||
b5d5a346 RP |
716 | return g_log_stream_ptr and g_log_stream_ptr->good(); |
717 | } // eo is_logging_to_file() | |
718 | ||
0ed59edf | 719 | |
0415b981 RP |
720 | |
721 | /** | |
722 | * @brief returns the current name of the log file. | |
723 | * @return the name of the log file; empty if none was given. | |
724 | * | |
725 | * This function returns the last used log file name; even | |
726 | * when logging to that file is currently disabled. | |
727 | */ | |
728 | std::string get_log_file_name() | |
729 | { | |
57924725 TJ |
730 | boost::recursive_mutex::scoped_lock lock(LoggerLock); |
731 | ||
0415b981 RP |
732 | return g_log_file_name; |
733 | } // eo get_log_file_name() | |
734 | ||
735 | ||
0ed59edf RP |
736 | /** |
737 | * @brief re-opens the logfiles (if applicable). | |
738 | */ | |
739 | void reopen() | |
740 | { | |
57924725 TJ |
741 | boost::recursive_mutex::scoped_lock lock(LoggerLock); |
742 | ||
0ed59edf RP |
743 | if (g_log_stream_ptr) |
744 | { | |
745 | enable_log_file(false); // closes log, but holds the name. | |
746 | enable_log_file(true); // opens the log file again. | |
747 | } | |
748 | } // eo reopen() | |
749 | ||
750 | ||
b6fb82a2 RP |
751 | /** |
752 | * set a new log level. | |
753 | * @param level the new log level. | |
754 | * @return the previous log level. | |
755 | */ | |
756 | int set_log_level(int level) | |
757 | { | |
57924725 TJ |
758 | boost::recursive_mutex::scoped_lock lock(LoggerLock); |
759 | ||
a47d646e TJ |
760 | int previous = g_max_level; |
761 | ||
762 | // Sanity check | |
763 | if (level < LogLevel::Emergency) | |
764 | level = LogLevel::Emergency; | |
765 | else if (level > LogLevel::Debug) | |
766 | level = LogLevel::Debug; | |
767 | ||
768 | g_max_level = level; | |
769 | ||
770 | return previous; | |
b6fb82a2 RP |
771 | } // eo set_log_level(int) |
772 | ||
773 | ||
774 | /** | |
775 | * returns the current log level. | |
776 | * @return the current log level. | |
777 | */ | |
778 | int get_log_level() | |
779 | { | |
57924725 TJ |
780 | boost::recursive_mutex::scoped_lock lock(LoggerLock); |
781 | ||
f61aeac1 | 782 | return g_max_level; |
b6fb82a2 RP |
783 | } // eo get_log_level() |
784 | ||
785 | ||
786 | /** | |
787 | * returns if the current log level covers the given level. | |
788 | * This is a convenience function for optimization of log output (especially debug output). | |
789 | * @param level the level which should be tested for. | |
790 | * @return @a true iff a message with the level would be written out. | |
791 | */ | |
792 | bool has_log_level(int level) | |
793 | { | |
57924725 TJ |
794 | boost::recursive_mutex::scoped_lock lock(LoggerLock); |
795 | ||
f61aeac1 | 796 | return (g_max_level >= level); |
b6fb82a2 RP |
797 | } // eo has_log_level(int) |
798 | ||
799 | ||
800 | ||
801 | } // eo namespace Logger | |
802 | } // eo namespace I2n |