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 
39 namespace 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  */
55 FileLogger::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 
127 void
128 FileLogger::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 
136 void
137 FileLogger::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 
145 void
146 FileLogger::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 
154 void
155 FileLogger::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 
163 void
164 FileLogger::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 
188 void
189 FileLogger::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 
213 void
214 FileLogger::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 
238 void
239 FileLogger::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 
263 void
264 FileLogger::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 
286 void
287 FileLogger::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 
309 void
310 FileLogger::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 
332 void
333 FileLogger::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 
355 void
356 FileLogger::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 
364 void
365 FileLogger::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 
373 void
374 FileLogger::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 
382 void
383 FileLogger::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 
391 void
392 FileLogger::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 
414 void
415 FileLogger::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 
437 void
438 FileLogger::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 
460 void
461 FileLogger::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 
483 void
484 FileLogger::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 
504 void
505 FileLogger::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 
525 void
526 FileLogger::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 
546 void
547 FileLogger::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
fawkes::Mutex::lock
void lock()
Lock this mutex.
Definition: mutex.cpp:87
fawkes::FileLogger::log_info
virtual void log_info(const char *component, const char *format,...)
Log informational message.
Definition: file.cpp:137
fawkes::FileLogger::~FileLogger
virtual ~FileLogger()
Destructor.
Definition: file.cpp:120
fawkes::FileLogger::vtlog_error
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
fawkes::FileLogger::log_debug
virtual void log_debug(const char *component, const char *format,...)
Log debug message.
Definition: file.cpp:128
fawkes::Exception::end
iterator end()
Get end iterator for messages.
Definition: exception.cpp:692
fawkes::FileLogger::vtlog_debug
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
fawkes::Logger::log_level
LogLevel log_level
Minimum log level.
Definition: logger.h:126
fawkes::Mutex
Mutex mutual exclusion lock.
Definition: mutex.h:33
fawkes::FileLogger::tlog_debug
virtual void tlog_debug(struct timeval *t, const char *component, const char *format,...)
Log debug message for specific time.
Definition: file.cpp:356
fawkes::FileLogger::FileLogger
FileLogger(const char *filename, LogLevel min_level=LL_DEBUG)
Constructor.
Definition: file.cpp:55
fawkes::FileLogger::log_error
virtual void log_error(const char *component, const char *format,...)
Log error message.
Definition: file.cpp:155
fawkes::FileLogger::log_warn
virtual void log_warn(const char *component, const char *format,...)
Log warning message.
Definition: file.cpp:146
fawkes::FileLogger::tlog_info
virtual void tlog_info(struct timeval *t, const char *component, const char *format,...)
Log informational message for specific time.
Definition: file.cpp:365
fawkes::Mutex::unlock
void unlock()
Unlock the mutex.
Definition: mutex.cpp:131
fawkes::FileLogger::vlog_warn
virtual void vlog_warn(const char *component, const char *format, va_list va)
Log warning message.
Definition: file.cpp:310
fawkes::Logger::LL_DEBUG
@ LL_DEBUG
debug output, relevant only when tracking down problems
Definition: logger.h:52
fawkes::FileLogger::vlog_error
virtual void vlog_error(const char *component, const char *format, va_list va)
Log error message.
Definition: file.cpp:333
fawkes::FileLogger::vlog_debug
virtual void vlog_debug(const char *component, const char *format, va_list va)
Log debug message.
Definition: file.cpp:264
fawkes::Logger::LL_INFO
@ LL_INFO
informational output about normal procedures
Definition: logger.h:53
fawkes::Logger
Interface for logging.
Definition: logger.h:42
fawkes::FileLogger::vlog_info
virtual void vlog_info(const char *component, const char *format, va_list va)
Log informational message.
Definition: file.cpp:287
fawkes
Fawkes library namespace.
fawkes::Logger::LL_ERROR
@ LL_ERROR
error, may be recoverable (software still running) or not (software has to terminate).
Definition: logger.h:57
fawkes::FileLogger::vtlog_warn
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
fawkes::Exception::begin
iterator begin()
Get iterator for messages.
Definition: exception.cpp:676
fawkes::Logger::LogLevel
LogLevel
Log level.
Definition: logger.h:51
fawkes::FileLogger::tlog_error
virtual void tlog_error(struct timeval *t, const char *component, const char *format,...)
Log error message for specific time.
Definition: file.cpp:383
fawkes::Logger::LL_WARN
@ LL_WARN
warning, should be investigated but software still functions, an example is that something was reques...
Definition: logger.h:54
fawkes::FileLogger::tlog_warn
virtual void tlog_warn(struct timeval *t, const char *component, const char *format,...)
Log warning message for specific time.
Definition: file.cpp:374
fawkes::Exception::iterator
Message iterator for exceptions.
Definition: exception.h:73
fawkes::FileLogger::vtlog_info
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
fawkes::Exception
Base class for exceptions in Fawkes.
Definition: exception.h:36