Fawkes API  Fawkes Development Version
factory.cpp
1 
2 /***************************************************************************
3  * factory.cpp - Logger factory
4  *
5  * Created: Mon Jun 04 10:57:21 2007
6  * Copyright 2007-2011 Tim Niemueller [www.niemueller.de]
7  *
8  ****************************************************************************/
9 
10 /* This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version. A runtime exception applies to
14  * this software (see LICENSE.GPL_WRE file mentioned below for details).
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU Library General Public License for more details.
20  *
21  * Read the full text in the LICENSE.GPL_WRE file in the doc directory.
22  */
23 
24 #include <logging/console.h>
25 #include <logging/factory.h>
26 #include <logging/file.h>
27 #include <logging/multi.h>
28 #include <logging/syslog.h>
29 
30 #include <cstdlib>
31 #include <cstring>
32 #include <string>
33 
34 namespace fawkes {
35 
36 /** @class UnknownLoggerTypeException <logging/factory.h>
37  * Unknown logger type exception.
38  * Thrown if the requested logger has not been recognized.
39  * @author Tim Niemueller
40  */
41 
42 /** Constructor.
43  * @param msg optional explanation
44  */
46 : Exception("Unknown logger type")
47 {
48  append(msg);
49 }
50 
51 /** @class LoggerFactory <logging/factory.h>
52  * Logger factory.
53  * This logging factory provides access to all loggers in a unified
54  * way. You just supply a logger argument string and depending on the
55  * logger type an instance of the desired logger is returned or
56  * otherwise an exception is thrown. See instance() for a list of
57  * supported logger types.
58  *
59  * @author Tim Niemueller
60  */
61 
62 /** Convert a string to a log level.
63  * @param log_level log level as string
64  * @return log level
65  */
67 LoggerFactory::string_to_loglevel(const char *log_level)
68 {
69  std::string ll = log_level;
70 
71  if (ll == "info" || ll == "INFO") {
72  return Logger::LL_INFO;
73  } else if (ll == "warn" || ll == "WARN") {
74  return Logger::LL_WARN;
75  } else if (ll == "error" || ll == "ERROR") {
76  return Logger::LL_ERROR;
77  } else {
78  return Logger::LL_DEBUG;
79  }
80 }
81 
82 /** Get logger instance.
83  * Get an instance of a logger of the given type. The argument string is used for
84  * logger arguments.
85  * Supported logger types:
86  * - console, ConsoleLogger
87  * - file, FileLogger
88  * - syslog, SyslogLogger
89  * NOT supported:
90  * - NetworkLogger, needs a FawkesNetworkHub which cannot be passed by parameter
91  * @param type logger type
92  * @param as logger argument string
93  * @return logger instance of requested type
94  * @exception UnknownLoggerTypeException thrown, if the desired logger could
95  * not be instantiated. This could be a misspelled logger type.
96  */
97 Logger *
98 LoggerFactory::instance(const char *type, const char *as)
99 {
100  Logger *l = NULL;
101 
102  if (strcmp(type, "console") == 0) {
103  // no supported arguments
104  l = new ConsoleLogger();
105  } else if (strcmp(type, "file") == 0) {
106  char * tmp = strdup(as);
107  char * saveptr;
108  char * r = strtok_r(tmp, ":", &saveptr);
109  const char *file_name;
110  r = strtok_r(tmp, ":", &saveptr);
111  if (r == NULL) {
112  file_name = "unnamed.log";
113  } else {
114  file_name = r;
115  }
116  l = new FileLogger(file_name);
117  free(tmp);
118  } else if (strcmp(type, "syslog") == 0) {
119  l = new SyslogLogger(as);
120  }
121 
122  if (l == NULL)
124  return l;
125 }
126 
127 /** Create MultiLogger instance.
128  * This creates a multi logger instance based on the supplied argument string.
129  * The argument string is of the form
130  * @code
131  * ltype:largs[;ltype2:largs2[;...]]
132  * @endcode
133  * So it is a list of logger type/argument tuples separated by columns concatenated
134  * to one list with exclamation marks. The list is not pre-processed, so if you
135  * mention a logger twice this logger is added twice.
136  * @param as logger argument string
137  * @param default_ll default log level for multi logger
138  * @return multi logger instance with requested loggers
139  * @exception UnknownLoggerTypeException thrown if any of the loggers was unknown.
140  */
141 MultiLogger *
143 {
144  MultiLogger *m = new MultiLogger();
145  m->set_loglevel(default_ll);
146 
147  char * logger_string = strdup(as);
148  char * str = logger_string;
149  char * saveptr, *r;
150  const char *type, *args, *level;
151  char * typeargs_saveptr, *level_saveptr, *type_str;
152  const char *logger_delim = ";";
153  const char *logger_typeargs_delim = ":";
154  const char *logger_level_delim = "/";
155  while ((r = strtok_r(str, logger_delim, &saveptr)) != NULL) {
156  type = strtok_r(r, logger_typeargs_delim, &typeargs_saveptr);
157  args = strtok_r(NULL, logger_typeargs_delim, &typeargs_saveptr);
158 
159  type_str = strdup(type);
160 
161  type = strtok_r(type_str, logger_level_delim, &level_saveptr);
162  level = strtok_r(NULL, logger_level_delim, &level_saveptr);
163 
164  if (type == NULL) {
166  }
167  if (args == NULL) {
168  args = "";
169  }
170 
171  try {
172  Logger *l = instance(type, args);
173  m->add_logger(l);
174  if (level) {
175  Logger::LogLevel ll = string_to_loglevel(level);
176  l->set_loglevel(ll);
177  }
178  } catch (Exception &e) {
179  e.append("Could not open logger '%s:%s'", type, args);
180  free(type_str);
181  free(logger_string);
182  delete m;
183  throw;
184  }
185  str = NULL;
186 
187  free(type_str);
188  }
189 
190  free(logger_string);
191 
192  return m;
193 }
194 
195 } // end namespace fawkes
fawkes::Logger::set_loglevel
virtual void set_loglevel(LogLevel level)
Sets the log level.
Definition: logger.cpp:258
fawkes::ConsoleLogger
Interface for logging to stderr.
Definition: console.h:37
fawkes::LoggerFactory::multilogger_instance
static MultiLogger * multilogger_instance(const char *as, Logger::LogLevel default_ll=Logger::LL_DEBUG)
Create MultiLogger instance.
Definition: factory.cpp:142
fawkes::MultiLogger
Log through multiple loggers.
Definition: multi.h:35
fawkes::MultiLogger::add_logger
void add_logger(Logger *logger)
Add a logger.
Definition: multi.cpp:110
fawkes::FileLogger
Interface for logging to a specified file.
Definition: file.h:38
fawkes::SyslogLogger
Interface for logging to syslog.
Definition: syslog.h:36
fawkes::Logger::LL_DEBUG
@ LL_DEBUG
debug output, relevant only when tracking down problems
Definition: logger.h:52
fawkes::Exception::append
void append(const char *format,...)
Append messages to the message list.
Definition: exception.cpp:333
fawkes::LoggerFactory::instance
static Logger * instance(const char *type, const char *as)
Get logger instance.
Definition: factory.cpp:98
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::MultiLogger::set_loglevel
virtual void set_loglevel(LogLevel level)
Sets the log level.
Definition: multi.cpp:139
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::UnknownLoggerTypeException::UnknownLoggerTypeException
UnknownLoggerTypeException(const char *msg=NULL)
Constructor.
Definition: factory.cpp:45
fawkes::Logger::LogLevel
LogLevel
Log level.
Definition: logger.h:51
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::UnknownLoggerTypeException
Unknown logger type exception.
Definition: factory.h:36
fawkes::Exception
Base class for exceptions in Fawkes.
Definition: exception.h:36