Fawkes API Fawkes Development Version
file.cpp
1
2/***************************************************************************
3 * file.cpp - Fawkes file logger
4 *
5 * Created: Tue Jan 16 16:56:49 2007
6 * Copyright 2006-2007 Tim Niemueller [www.niemueller.de]
7 * 2007 Daniel Beck
8 *
9 ****************************************************************************/
10
11/* This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version. A runtime exception applies to
15 * this software (see LICENSE.GPL_WRE file mentioned below for details).
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU Library General Public License for more details.
21 *
22 * Read the full text in the LICENSE.GPL_WRE file in the doc directory.
23 */
24
25#include <core/threading/mutex.h>
26#include <logging/file.h>
27#include <sys/stat.h>
28#include <sys/time.h>
29#include <utils/system/file.h>
30
31#include <cerrno>
32#include <cstdlib>
33#include <fcntl.h>
34#include <stdio.h>
35#include <string>
36#include <time.h>
37#include <unistd.h>
38
39namespace fawkes {
40
41/** @class FileLogger <logging/file.h>
42 * Interface for logging to a specified file.
43 * The FileLogger will pipe all output into the given file. The
44 * output will be prepended by a single character which determines the
45 * type of output (E for error, W for warning, etc.).
46 *
47 */
48
49/** Constructor.
50 * The filename is generated from the filename pattern by replacing '$time' with
51 * the current time.
52 * @param filename_pattern the name pattern of the log-file
53 * @param log_level minimum log level
54 */
55FileLogger::FileLogger(const char *filename_pattern, LogLevel log_level) : Logger(log_level)
56{
57 now_s = (struct tm *)malloc(sizeof(struct tm));
58 struct timeval now;
59 gettimeofday(&now, NULL);
60 localtime_r(&now.tv_sec, now_s);
61 char *start_time;
62 if (asprintf(&start_time,
63 "%04d-%02d-%02d_%02d-%02d-%02d",
64 1900 + now_s->tm_year,
65 now_s->tm_mon + 1,
66 now_s->tm_mday,
67 now_s->tm_hour,
68 now_s->tm_min,
69 now_s->tm_sec)
70 == -1) {
71 throw Exception("Failed to print current time");
72 }
73 std::string pattern(filename_pattern);
74 std::string time_var = "$time";
75 size_t pos = pattern.find(time_var);
76 if (pos != std::string::npos) {
77 pattern.replace(pos, time_var.length(), std::string(start_time));
78 }
79 free(start_time);
80 const char *filename = pattern.c_str();
81 int fd = open(filename, O_RDWR | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
82 if (fd == -1) {
83 throw Exception(errno, "Failed to open log file %s", filename);
84 }
85 log_file = fdopen(fd, "a");
86 // make buffer line-buffered
87 setvbuf(log_file, NULL, _IOLBF, 0);
88
89 // create a symlink for the latest log if the filename has a time stamp
90 if (pos != std::string::npos) {
91 std::string latest_filename(filename_pattern);
92 latest_filename.replace(pos, time_var.length(), "latest");
93 int link_res = symlink(filename, latest_filename.c_str());
94 if (link_res == -1) {
95 if (errno == EEXIST) {
96 int unlink_res = unlink(latest_filename.c_str());
97 if (unlink_res == -1) {
98 throw Exception(errno, "Failed to update symlink at %s", latest_filename.c_str());
99 }
100 link_res = symlink(filename, latest_filename.c_str());
101 if (link_res == -1) {
102 throw Exception(errno,
103 "Failed ot create symlink from %s to %s",
104 filename,
105 latest_filename.c_str());
106 }
107 } else {
108 throw Exception(errno,
109 "Failed ot create symlink from %s to %s",
110 filename,
111 latest_filename.c_str());
112 }
113 }
114 }
115
116 mutex = new Mutex();
117}
118
119/** Destructor. */
121{
122 free(now_s);
123 fclose(log_file);
124 delete mutex;
125}
126
127void
128FileLogger::log_debug(const char *component, const char *format, ...)
129{
130 va_list arg;
131 va_start(arg, format);
132 vlog_debug(component, format, arg);
133 va_end(arg);
134}
135
136void
137FileLogger::log_info(const char *component, const char *format, ...)
138{
139 va_list arg;
140 va_start(arg, format);
141 vlog_info(component, format, arg);
142 va_end(arg);
143}
144
145void
146FileLogger::log_warn(const char *component, const char *format, ...)
147{
148 va_list arg;
149 va_start(arg, format);
150 vlog_warn(component, format, arg);
151 va_end(arg);
152}
153
154void
155FileLogger::log_error(const char *component, const char *format, ...)
156{
157 va_list arg;
158 va_start(arg, format);
159 vlog_error(component, format, arg);
160 va_end(arg);
161}
162
163void
164FileLogger::log_debug(const char *component, Exception &e)
165{
166 if (log_level <= LL_DEBUG) {
167 struct timeval now;
168 gettimeofday(&now, NULL);
169 mutex->lock();
170 localtime_r(&now.tv_sec, now_s);
171 for (Exception::iterator i = e.begin(); i != e.end(); ++i) {
172 fprintf(log_file,
173 "%s %02d:%02d:%02d.%06ld %s [EXCEPTION]: ",
174 "D",
175 now_s->tm_hour,
176 now_s->tm_min,
177 now_s->tm_sec,
178 (long)now.tv_usec,
179 component);
180 fprintf(log_file, "%s", *i);
181 fprintf(log_file, "\n");
182 }
183 fflush(log_file);
184 mutex->unlock();
185 }
186}
187
188void
189FileLogger::log_info(const char *component, Exception &e)
190{
191 if (log_level <= LL_INFO) {
192 struct timeval now;
193 gettimeofday(&now, NULL);
194 mutex->lock();
195 localtime_r(&now.tv_sec, now_s);
196 for (Exception::iterator i = e.begin(); i != e.end(); ++i) {
197 fprintf(log_file,
198 "%s %02d:%02d:%02d.%06ld %s [EXCEPTION]: ",
199 "I",
200 now_s->tm_hour,
201 now_s->tm_min,
202 now_s->tm_sec,
203 (long)now.tv_usec,
204 component);
205 fprintf(log_file, "%s", *i);
206 fprintf(log_file, "\n");
207 }
208 fflush(log_file);
209 mutex->unlock();
210 }
211}
212
213void
214FileLogger::log_warn(const char *component, Exception &e)
215{
216 if (log_level <= LL_WARN) {
217 struct timeval now;
218 gettimeofday(&now, NULL);
219 mutex->lock();
220 localtime_r(&now.tv_sec, now_s);
221 for (Exception::iterator i = e.begin(); i != e.end(); ++i) {
222 fprintf(log_file,
223 "%s %02d:%02d:%02d.%06ld %s [EXCEPTION]: ",
224 "W",
225 now_s->tm_hour,
226 now_s->tm_min,
227 now_s->tm_sec,
228 (long)now.tv_usec,
229 component);
230 fprintf(log_file, "%s", *i);
231 fprintf(log_file, "\n");
232 }
233 fflush(log_file);
234 mutex->unlock();
235 }
236}
237
238void
239FileLogger::log_error(const char *component, Exception &e)
240{
241 if (log_level <= LL_ERROR) {
242 struct timeval now;
243 gettimeofday(&now, NULL);
244 mutex->lock();
245 localtime_r(&now.tv_sec, now_s);
246 for (Exception::iterator i = e.begin(); i != e.end(); ++i) {
247 fprintf(log_file,
248 "%s %02d:%02d:%02d.%06ld %s [EXCEPTION]: ",
249 "E",
250 now_s->tm_hour,
251 now_s->tm_min,
252 now_s->tm_sec,
253 (long)now.tv_usec,
254 component);
255 fprintf(log_file, "%s", *i);
256 fprintf(log_file, "\n");
257 }
258 fflush(log_file);
259 mutex->unlock();
260 }
261}
262
263void
264FileLogger::vlog_debug(const char *component, const char *format, va_list va)
265{
266 if (log_level <= LL_DEBUG) {
267 struct timeval now;
268 gettimeofday(&now, NULL);
269 mutex->lock();
270 localtime_r(&now.tv_sec, now_s);
271 fprintf(log_file,
272 "%s %02d:%02d:%02d.%06ld %s: ",
273 "D",
274 now_s->tm_hour,
275 now_s->tm_min,
276 now_s->tm_sec,
277 (long)now.tv_usec,
278 component);
279 vfprintf(log_file, format, va);
280 fprintf(log_file, "\n");
281 fflush(log_file);
282 mutex->unlock();
283 }
284}
285
286void
287FileLogger::vlog_info(const char *component, const char *format, va_list va)
288{
289 if (log_level <= LL_INFO) {
290 struct timeval now;
291 gettimeofday(&now, NULL);
292 mutex->lock();
293 localtime_r(&now.tv_sec, now_s);
294 fprintf(log_file,
295 "%s %02d:%02d:%02d.%06ld %s: ",
296 "I",
297 now_s->tm_hour,
298 now_s->tm_min,
299 now_s->tm_sec,
300 (long)now.tv_usec,
301 component);
302 vfprintf(log_file, format, va);
303 fprintf(log_file, "\n");
304 fflush(log_file);
305 mutex->unlock();
306 }
307}
308
309void
310FileLogger::vlog_warn(const char *component, const char *format, va_list va)
311{
312 if (log_level <= LL_WARN) {
313 struct timeval now;
314 gettimeofday(&now, NULL);
315 mutex->lock();
316 localtime_r(&now.tv_sec, now_s);
317 fprintf(log_file,
318 "%s %02d:%02d:%02d.%06ld %s: ",
319 "W",
320 now_s->tm_hour,
321 now_s->tm_min,
322 now_s->tm_sec,
323 (long)now.tv_usec,
324 component);
325 vfprintf(log_file, format, va);
326 fprintf(log_file, "\n");
327 fflush(log_file);
328 mutex->unlock();
329 }
330}
331
332void
333FileLogger::vlog_error(const char *component, const char *format, va_list va)
334{
335 if (log_level <= LL_ERROR) {
336 struct timeval now;
337 gettimeofday(&now, NULL);
338 mutex->lock();
339 localtime_r(&now.tv_sec, now_s);
340 fprintf(log_file,
341 "%s %02d:%02d:%02d.%06ld %s: ",
342 "E",
343 now_s->tm_hour,
344 now_s->tm_min,
345 now_s->tm_sec,
346 (long)now.tv_usec,
347 component);
348 vfprintf(log_file, format, va);
349 fprintf(log_file, "\n");
350 fflush(log_file);
351 mutex->unlock();
352 }
353}
354
355void
356FileLogger::tlog_debug(struct timeval *t, const char *component, const char *format, ...)
357{
358 va_list arg;
359 va_start(arg, format);
360 vtlog_debug(t, component, format, arg);
361 va_end(arg);
362}
363
364void
365FileLogger::tlog_info(struct timeval *t, const char *component, const char *format, ...)
366{
367 va_list arg;
368 va_start(arg, format);
369 vtlog_info(t, component, format, arg);
370 va_end(arg);
371}
372
373void
374FileLogger::tlog_warn(struct timeval *t, const char *component, const char *format, ...)
375{
376 va_list arg;
377 va_start(arg, format);
378 vtlog_warn(t, component, format, arg);
379 va_end(arg);
380}
381
382void
383FileLogger::tlog_error(struct timeval *t, const char *component, const char *format, ...)
384{
385 va_list arg;
386 va_start(arg, format);
387 vtlog_error(t, component, format, arg);
388 va_end(arg);
389}
390
391void
392FileLogger::tlog_debug(struct timeval *t, const char *component, Exception &e)
393{
394 if (log_level <= LL_DEBUG) {
395 mutex->lock();
396 localtime_r(&t->tv_sec, now_s);
397 for (Exception::iterator i = e.begin(); i != e.end(); ++i) {
398 fprintf(log_file,
399 "%s %02d:%02d:%02d.%06ld %s [EXCEPTION]: ",
400 "D",
401 now_s->tm_hour,
402 now_s->tm_min,
403 now_s->tm_sec,
404 (long)t->tv_usec,
405 component);
406 fprintf(log_file, "%s", *i);
407 fprintf(log_file, "\n");
408 }
409 fflush(log_file);
410 mutex->unlock();
411 }
412}
413
414void
415FileLogger::tlog_info(struct timeval *t, const char *component, Exception &e)
416{
417 if (log_level <= LL_INFO) {
418 mutex->lock();
419 localtime_r(&t->tv_sec, now_s);
420 for (Exception::iterator i = e.begin(); i != e.end(); ++i) {
421 fprintf(log_file,
422 "%s %02d:%02d:%02d.%06ld %s [EXCEPTION]: ",
423 "I",
424 now_s->tm_hour,
425 now_s->tm_min,
426 now_s->tm_sec,
427 (long)t->tv_usec,
428 component);
429 fprintf(log_file, "%s", *i);
430 fprintf(log_file, "\n");
431 }
432 fflush(log_file);
433 mutex->unlock();
434 }
435}
436
437void
438FileLogger::tlog_warn(struct timeval *t, const char *component, Exception &e)
439{
440 if (log_level <= LL_WARN) {
441 mutex->lock();
442 localtime_r(&t->tv_sec, now_s);
443 for (Exception::iterator i = e.begin(); i != e.end(); ++i) {
444 fprintf(log_file,
445 "%s %02d:%02d:%02d.%06ld %s [EXCEPTION]: ",
446 "W",
447 now_s->tm_hour,
448 now_s->tm_min,
449 now_s->tm_sec,
450 (long)t->tv_usec,
451 component);
452 fprintf(log_file, "%s", *i);
453 fprintf(log_file, "\n");
454 }
455 fflush(log_file);
456 mutex->unlock();
457 }
458}
459
460void
461FileLogger::tlog_error(struct timeval *t, const char *component, Exception &e)
462{
463 if (log_level <= LL_ERROR) {
464 mutex->lock();
465 localtime_r(&t->tv_sec, now_s);
466 for (Exception::iterator i = e.begin(); i != e.end(); ++i) {
467 fprintf(log_file,
468 "%s %02d:%02d:%02d.%06ld %s [EXCEPTION]: ",
469 "E",
470 now_s->tm_hour,
471 now_s->tm_min,
472 now_s->tm_sec,
473 (long)t->tv_usec,
474 component);
475 fprintf(log_file, "%s", *i);
476 fprintf(log_file, "\n");
477 }
478 fflush(log_file);
479 mutex->unlock();
480 }
481}
482
483void
484FileLogger::vtlog_debug(struct timeval *t, const char *component, const char *format, va_list va)
485{
486 if (log_level <= LL_DEBUG) {
487 mutex->lock();
488 localtime_r(&t->tv_sec, now_s);
489 fprintf(log_file,
490 "%s %02d:%02d:%02d.%06ld %s: ",
491 "D",
492 now_s->tm_hour,
493 now_s->tm_min,
494 now_s->tm_sec,
495 (long)t->tv_usec,
496 component);
497 vfprintf(log_file, format, va);
498 fprintf(log_file, "\n");
499 fflush(log_file);
500 mutex->unlock();
501 }
502}
503
504void
505FileLogger::vtlog_info(struct timeval *t, const char *component, const char *format, va_list va)
506{
507 if (log_level <= LL_INFO) {
508 mutex->lock();
509 localtime_r(&t->tv_sec, now_s);
510 fprintf(log_file,
511 "%s %02d:%02d:%02d.%06ld %s: ",
512 "I",
513 now_s->tm_hour,
514 now_s->tm_min,
515 now_s->tm_sec,
516 (long)t->tv_usec,
517 component);
518 vfprintf(log_file, format, va);
519 fprintf(log_file, "\n");
520 fflush(log_file);
521 mutex->unlock();
522 }
523}
524
525void
526FileLogger::vtlog_warn(struct timeval *t, const char *component, const char *format, va_list va)
527{
528 if (log_level <= LL_WARN) {
529 mutex->lock();
530 localtime_r(&t->tv_sec, now_s);
531 fprintf(log_file,
532 "%s %02d:%02d:%02d.%06ld %s: ",
533 "W",
534 now_s->tm_hour,
535 now_s->tm_min,
536 now_s->tm_sec,
537 (long)t->tv_usec,
538 component);
539 vfprintf(log_file, format, va);
540 fprintf(log_file, "\n");
541 fflush(log_file);
542 mutex->unlock();
543 }
544}
545
546void
547FileLogger::vtlog_error(struct timeval *t, const char *component, const char *format, va_list va)
548{
549 if (log_level <= LL_ERROR) {
550 mutex->lock();
551 localtime_r(&t->tv_sec, now_s);
552 fprintf(log_file,
553 "%s %02d:%02d:%02d.%06ld %s: ",
554 "E",
555 now_s->tm_hour,
556 now_s->tm_min,
557 now_s->tm_sec,
558 (long)t->tv_usec,
559 component);
560 vfprintf(log_file, format, va);
561 fprintf(log_file, "\n");
562 fflush(log_file);
563 mutex->unlock();
564 }
565}
566
567} // end namespace fawkes
Message iterator for exceptions.
Definition: exception.h:73
Base class for exceptions in Fawkes.
Definition: exception.h:36
iterator end() noexcept
Get end iterator for messages.
Definition: exception.cpp:692
iterator begin() noexcept
Get iterator for messages.
Definition: exception.cpp:676
virtual void vtlog_debug(struct timeval *t, const char *component, const char *format, va_list va)
Log debug message for specific time.
Definition: file.cpp:484
virtual void log_error(const char *component, const char *format,...)
Log error message.
Definition: file.cpp:155
virtual void vlog_warn(const char *component, const char *format, va_list va)
Log warning message.
Definition: file.cpp:310
virtual void tlog_info(struct timeval *t, const char *component, const char *format,...)
Log informational message for specific time.
Definition: file.cpp:365
virtual void log_warn(const char *component, const char *format,...)
Log warning message.
Definition: file.cpp:146
virtual void vlog_debug(const char *component, const char *format, va_list va)
Log debug message.
Definition: file.cpp:264
virtual void tlog_debug(struct timeval *t, const char *component, const char *format,...)
Log debug message for specific time.
Definition: file.cpp:356
virtual void log_debug(const char *component, const char *format,...)
Log debug message.
Definition: file.cpp:128
virtual void tlog_warn(struct timeval *t, const char *component, const char *format,...)
Log warning message for specific time.
Definition: file.cpp:374
virtual void vtlog_info(struct timeval *t, const char *component, const char *format, va_list va)
Log informational message for specific time.
Definition: file.cpp:505
virtual void vlog_error(const char *component, const char *format, va_list va)
Log error message.
Definition: file.cpp:333
virtual void tlog_error(struct timeval *t, const char *component, const char *format,...)
Log error message for specific time.
Definition: file.cpp:383
FileLogger(const char *filename, LogLevel min_level=LL_DEBUG)
Constructor.
Definition: file.cpp:55
virtual void vtlog_warn(struct timeval *t, const char *component, const char *format, va_list va)
Log warning message for specific time.
Definition: file.cpp:526
virtual void vtlog_error(struct timeval *t, const char *component, const char *format, va_list va)
Log error message for specific time.
Definition: file.cpp:547
virtual void log_info(const char *component, const char *format,...)
Log informational message.
Definition: file.cpp:137
virtual ~FileLogger()
Destructor.
Definition: file.cpp:120
virtual void vlog_info(const char *component, const char *format, va_list va)
Log informational message.
Definition: file.cpp:287
Interface for logging.
Definition: logger.h:42
LogLevel
Log level.
Definition: logger.h:51
@ LL_INFO
informational output about normal procedures
Definition: logger.h:53
@ LL_WARN
warning, should be investigated but software still functions, an example is that something was reques...
Definition: logger.h:54
@ LL_ERROR
error, may be recoverable (software still running) or not (software has to terminate).
Definition: logger.h:57
@ LL_DEBUG
debug output, relevant only when tracking down problems
Definition: logger.h:52
LogLevel log_level
Minimum log level.
Definition: logger.h:126
Mutex mutual exclusion lock.
Definition: mutex.h:33
void lock()
Lock this mutex.
Definition: mutex.cpp:87
void unlock()
Unlock the mutex.
Definition: mutex.cpp:131
Fawkes library namespace.