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/factory.h>
25 #include <logging/console.h>
26 #include <logging/file.h>
27 #include <logging/syslog.h>
28 #include <logging/multi.h>
29 
30 #include <cstring>
31 #include <cstdlib>
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 
52 /** @class LoggerFactory <logging/factory.h>
53  * Logger factory.
54  * This logging factory provides access to all loggers in a unified
55  * way. You just supply a logger argument string and depending on the
56  * logger type an instance of the desired logger is returned or
57  * otherwise an exception is thrown. See instance() for a list of
58  * supported logger types.
59  *
60  * @author Tim Niemueller
61  */
62 
63 /** Convert a string to a log level.
64  * @param log_level log level as string
65  * @return log level
66  */
68 LoggerFactory::string_to_loglevel(const char *log_level)
69 {
70  std::string ll = log_level;
71 
72  if (ll == "info" || ll == "INFO") {
73  return Logger::LL_INFO;
74  } else if (ll == "warn" || ll == "WARN") {
75  return Logger::LL_WARN;
76  } else if (ll == "error" || ll == "ERROR") {
77  return Logger::LL_ERROR;
78  } else {
79  return Logger::LL_DEBUG;
80  }
81 }
82 
83 /** Get logger instance.
84  * Get an instance of a logger of the given type. The argument string is used for
85  * logger arguments.
86  * Supported logger types:
87  * - console, ConsoleLogger
88  * - file, FileLogger
89  * - syslog, SyslogLogger
90  * NOT supported:
91  * - NetworkLogger, needs a FawkesNetworkHub which cannot be passed by parameter
92  * @param type logger type
93  * @param as logger argument string
94  * @return logger instance of requested type
95  * @exception UnknownLoggerTypeException thrown, if the desired logger could
96  * not be instantiated. This could be a misspelled logger type.
97  */
98 Logger *
99 LoggerFactory::instance(const char *type, const char *as)
100 {
101  Logger *l = NULL;
102 
103  if ( strcmp(type, "console") == 0 ) {
104  // no supported arguments
105  l = new ConsoleLogger();
106  } else if ( strcmp(type, "file") == 0 ) {
107  char *tmp = strdup(as);
108  char *saveptr;
109  char *r = strtok_r(tmp, ":", &saveptr);
110  const char *file_name;
111  r = strtok_r(tmp, ":", &saveptr);
112  if ( r == NULL ) {
113  file_name = "unnamed.log";
114  } else {
115  file_name = r;
116  }
117  l = new FileLogger(file_name);
118  free(tmp);
119  } else if ( strcmp(type, "syslog") == 0 ) {
120  l = new SyslogLogger(as);
121  }
122 
123  if ( l == NULL ) throw UnknownLoggerTypeException();
124  return l;
125 }
126 
127 
128 /** Create MultiLogger instance.
129  * This creates a multi logger instance based on the supplied argument string.
130  * The argument string is of the form
131  * @code
132  * ltype:largs[;ltype2:largs2[;...]]
133  * @endcode
134  * So it is a list of logger type/argument tuples separated by columns concatenated
135  * to one list with exclamation marks. The list is not pre-processed, so if you
136  * mention a logger twice this logger is added twice.
137  * @param as logger argument string
138  * @param default_ll default log level for multi logger
139  * @return multi logger instance with requested loggers
140  * @exception UnknownLoggerTypeException thrown if any of the loggers was unknown.
141  */
142 MultiLogger *
144 {
145  MultiLogger *m = new MultiLogger();
146  m->set_loglevel(default_ll);
147 
148  char *logger_string = strdup(as);
149  char *str = logger_string;
150  char *saveptr, *r;
151  const char *type, *args, *level;
152  char *typeargs_saveptr, *level_saveptr, *type_str;
153  const char *logger_delim = ";";
154  const char *logger_typeargs_delim = ":";
155  const char *logger_level_delim = "/";
156  while ((r = strtok_r(str, logger_delim, &saveptr)) != NULL ) {
157  type = strtok_r(r, logger_typeargs_delim, &typeargs_saveptr);
158  args = strtok_r(NULL, logger_typeargs_delim, &typeargs_saveptr);
159 
160  type_str = strdup(type);
161 
162  type = strtok_r(type_str, logger_level_delim, &level_saveptr);
163  level = strtok_r(NULL, logger_level_delim, &level_saveptr);
164 
165  if ( type == NULL ) {
167  }
168  if ( args == NULL ) {
169  args = "";
170  }
171 
172  try {
173  Logger *l = instance(type, args);
174  m->add_logger(l);
175  if (level) {
176  Logger::LogLevel ll = string_to_loglevel(level);
177  l->set_loglevel(ll);
178  }
179  } catch (Exception &e) {
180  e.append("Could not open logger '%s:%s'", type, args);
181  free(type_str);
182  free(logger_string);
183  delete m;
184  throw;
185  }
186  str = NULL;
187 
188  free(type_str);
189  }
190 
191  free(logger_string);
192 
193  return m;
194 }
195 
196 
197 } // end namespace fawkes
LogLevel
Log level.
Definition: logger.h:45
informational output about normal procedures
Definition: logger.h:47
Interface for logging to a specified file.
Definition: file.h:36
Interface for logging to stderr.
Definition: console.h:36
Fawkes library namespace.
warning, should be investigated but software still functions, an example is that something was reques...
Definition: logger.h:48
static Logger * instance(const char *type, const char *as)
Get logger instance.
Definition: factory.cpp:99
static MultiLogger * multilogger_instance(const char *as, Logger::LogLevel default_ll=Logger::LL_DEBUG)
Create MultiLogger instance.
Definition: factory.cpp:143
Log through multiple loggers.
Definition: multi.h:35
error, may be recoverable (software still running) or not (software has to terminate).
Definition: logger.h:51
virtual void set_loglevel(LogLevel level)
Sets the log level.
Definition: multi.cpp:146
Base class for exceptions in Fawkes.
Definition: exception.h:36
void add_logger(Logger *logger)
Add a logger.
Definition: multi.cpp:115
debug output, relevant only when tracking down problems
Definition: logger.h:46
Interface for logging to syslog.
Definition: syslog.h:35
UnknownLoggerTypeException(const char *msg=NULL)
Constructor.
Definition: factory.cpp:45
void append(const char *format,...)
Append messages to the message list.
Definition: exception.cpp:341
Interface for logging.
Definition: logger.h:34
virtual void set_loglevel(LogLevel level)
Sets the log level.
Definition: logger.cpp:244