Branch data Line data Source code
1 : : // Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC")
2 : : //
3 : : // Permission to use, copy, modify, and/or distribute this software for any
4 : : // purpose with or without fee is hereby granted, provided that the above
5 : : // copyright notice and this permission notice appear in all copies.
6 : : //
7 : : // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
8 : : // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
9 : : // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
10 : : // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
11 : : // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
12 : : // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
13 : : // PERFORMANCE OF THIS SOFTWARE.
14 : :
15 : : #include <algorithm>
16 : : #include <iostream>
17 : :
18 : : #include <log4cplus/logger.h>
19 : : #include <log4cplus/configurator.h>
20 : : #include <log4cplus/consoleappender.h>
21 : : #include <log4cplus/fileappender.h>
22 : : #include <log4cplus/syslogappender.h>
23 : :
24 : : #include <log/logger.h>
25 : : #include <log/logger_level_impl.h>
26 : : #include <log/logger_manager.h>
27 : : #include <log/logger_manager_impl.h>
28 : : #include <log/log_messages.h>
29 : : #include <log/logger_name.h>
30 : : #include <log/logger_specification.h>
31 : :
32 : : using namespace std;
33 : :
34 : : namespace isc {
35 : : namespace log {
36 : :
37 : : // Reset hierarchy of loggers back to default settings. This removes all
38 : : // appenders from loggers, sets their severity to NOT_SET (so that events are
39 : : // passed back to the parent) and resets the root logger to logging
40 : : // informational messages. (This last is not a log4cplus default, so we have to
41 : : // explicitly reset the logging severity.)
42 : :
43 : : void
44 : 200 : LoggerManagerImpl::processInit() {
45 : 200 : log4cplus::Logger::getDefaultHierarchy().resetConfiguration();
46 : 200 : initRootLogger();
47 : 200 : }
48 : :
49 : : // Process logging specification. Set up the common states then dispatch to
50 : : // add output specifications.
51 : :
52 : : void
53 : 62 : LoggerManagerImpl::processSpecification(const LoggerSpecification& spec) {
54 : :
55 : : log4cplus::Logger logger = log4cplus::Logger::getInstance(
56 [ + - ][ + - ]: 124 : expandLoggerName(spec.getName()));
57 : :
58 : : // Set severity level according to specification entry.
59 : : logger.setLogLevel(LoggerLevelImpl::convertFromBindLevel(
60 [ + - ][ + - ]: 62 : Level(spec.getSeverity(), spec.getDbglevel())));
61 : :
62 : : // Set the additive flag.
63 [ + - ]: 62 : logger.setAdditivity(spec.getAdditive());
64 : :
65 : : // Output options given?
66 [ + - ]: 62 : if (spec.optionCount() > 0) {
67 : :
68 : : // Yes, so replace all appenders for this logger.
69 [ + - ]: 62 : logger.removeAllAppenders();
70 : :
71 : : // Now process output specifications.
72 [ + + ]: 125 : for (LoggerSpecification::const_iterator i = spec.begin();
73 : 125 : i != spec.end(); ++i) {
74 [ + + - - ]: 63 : switch (i->destination) {
75 : : case OutputOption::DEST_CONSOLE:
76 [ + - ]: 14 : createConsoleAppender(logger, *i);
77 : : break;
78 : :
79 : : case OutputOption::DEST_FILE:
80 [ + - ]: 49 : createFileAppender(logger, *i);
81 : : break;
82 : :
83 : : case OutputOption::DEST_SYSLOG:
84 [ # # ]: 0 : createSyslogAppender(logger, *i);
85 : : break;
86 : :
87 : : default:
88 : : // Not a valid destination. As we are in the middle of updating
89 : : // logging destinations, we could be in the situation where
90 : : // there are no valid appenders. For this reason, throw an
91 : : // exception.
92 [ # # ][ # # ]: 0 : isc_throw(UnknownLoggingDestination,
[ # # ]
93 : : "Unknown logging destination, code = " <<
94 : : i->destination);
95 : : }
96 : : }
97 : : }
98 : 62 : }
99 : :
100 : : // Console appender - log to either stdout or stderr.
101 : : void
102 : 364 : LoggerManagerImpl::createConsoleAppender(log4cplus::Logger& logger,
103 : : const OutputOption& opt)
104 : : {
105 : : log4cplus::SharedAppenderPtr console(
106 : : new log4cplus::ConsoleAppender(
107 [ + - ]: 728 : (opt.stream == OutputOption::STR_STDERR), opt.flush));
108 [ + - ]: 364 : setConsoleAppenderLayout(console);
109 [ + - ][ + - ]: 364 : logger.addAppender(console);
110 : 364 : }
111 : :
112 : : // File appender. Depending on whether a maximum size is given, either
113 : : // a standard file appender or a rolling file appender will be created.
114 : : void
115 : 49 : LoggerManagerImpl::createFileAppender(log4cplus::Logger& logger,
116 : : const OutputOption& opt)
117 : : {
118 : : // Append to existing file
119 : 49 : std::ios::openmode mode = std::ios::app;
120 : :
121 : 49 : log4cplus::SharedAppenderPtr fileapp;
122 [ + + ]: 49 : if (opt.maxsize == 0) {
123 : : fileapp = log4cplus::SharedAppenderPtr(new log4cplus::FileAppender(
124 [ + - ][ + - ]: 94 : opt.filename, mode, opt.flush));
[ + - ]
125 : : } else {
126 : : fileapp = log4cplus::SharedAppenderPtr(
127 : : new log4cplus::RollingFileAppender(opt.filename, opt.maxsize,
128 [ + - ][ + - ]: 4 : opt.maxver, opt.flush));
[ + - ]
129 : : }
130 : :
131 : : // use the same console layout for the files.
132 [ + - ]: 49 : setConsoleAppenderLayout(fileapp);
133 [ + - ][ + - ]: 49 : logger.addAppender(fileapp);
134 : 49 : }
135 : :
136 : : // Syslog appender.
137 : : void
138 : 0 : LoggerManagerImpl::createSyslogAppender(log4cplus::Logger& logger,
139 : : const OutputOption& opt)
140 : : {
141 : : log4cplus::SharedAppenderPtr syslogapp(
142 [ # # ]: 0 : new log4cplus::SysLogAppender(opt.facility));
143 [ # # ]: 0 : setSyslogAppenderLayout(syslogapp);
144 [ # # ][ # # ]: 0 : logger.addAppender(syslogapp);
145 : 0 : }
146 : :
147 : :
148 : : // One-time initialization of the log4cplus system
149 : :
150 : : void
151 : 120 : LoggerManagerImpl::init(isc::log::Severity severity, int dbglevel) {
152 : :
153 : : // Set up basic configurator. This attaches a ConsoleAppender to the
154 : : // root logger with suitable output. This is used until we we have
155 : : // actually read the logging configuration, in which case the output
156 : : // may well be changed.
157 : 240 : log4cplus::BasicConfigurator config;
158 [ + - ]: 120 : config.configure();
159 : :
160 : : // Add the additional debug levels
161 [ + - ]: 120 : LoggerLevelImpl::init();
162 : :
163 [ + - ]: 120 : reset(severity, dbglevel);
164 : 120 : }
165 : :
166 : : // Reset logging to default configuration. This closes all appenders
167 : : // and resets the root logger to output INFO messages to the console.
168 : : // It is principally used in testing.
169 : : void
170 : 150 : LoggerManagerImpl::reset(isc::log::Severity severity, int dbglevel) {
171 : :
172 : : // Initialize the root logger
173 : 150 : initRootLogger(severity, dbglevel);
174 : 150 : }
175 : :
176 : : // Initialize the root logger
177 : 350 : void LoggerManagerImpl::initRootLogger(isc::log::Severity severity,
178 : : int dbglevel)
179 : : {
180 : 350 : log4cplus::Logger::getDefaultHierarchy().resetConfiguration();
181 : :
182 : : // Set the log4cplus root to not output anything - effectively we are
183 : : // ignoring it.
184 [ + - ]: 350 : log4cplus::Logger::getRoot().setLogLevel(log4cplus::OFF_LOG_LEVEL);
185 : :
186 : : // Set the level for the BIND 10 root logger to the given severity and
187 : : // debug level.
188 : : log4cplus::Logger b10root = log4cplus::Logger::getInstance(
189 : 700 : getRootLoggerName());
190 : : b10root.setLogLevel(LoggerLevelImpl::convertFromBindLevel(
191 [ + - ][ + - ]: 350 : Level(severity, dbglevel)));
192 : :
193 : : // Set the BIND 10 root to use a console logger.
194 : : OutputOption opt;
195 [ + - ]: 350 : createConsoleAppender(b10root, opt);
196 : 350 : }
197 : :
198 : : // Set the the "console" layout for the given appenders. This layout includes
199 : : // a date/time and the name of the logger.
200 : :
201 : 413 : void LoggerManagerImpl::setConsoleAppenderLayout(
202 : : log4cplus::SharedAppenderPtr& appender)
203 : : {
204 : : // Create the pattern we want for the output - local time.
205 : 826 : string pattern = "%D{%Y-%m-%d %H:%M:%S.%q} %-5p [%c] %m\n";
206 : :
207 : : // Finally the text of the message
208 [ + - ][ + - ]: 413 : auto_ptr<log4cplus::Layout> layout(new log4cplus::PatternLayout(pattern));
209 [ + - ]: 413 : appender->setLayout(layout);
210 : 413 : }
211 : :
212 : : // Set the the "syslog" layout for the given appenders. This is the same
213 : : // as the console, but without the timestamp (which is expected to be
214 : : // set by syslogd).
215 : :
216 : 0 : void LoggerManagerImpl::setSyslogAppenderLayout(
217 : : log4cplus::SharedAppenderPtr& appender)
218 : : {
219 : : // Create the pattern we want for the output - local time.
220 : 0 : string pattern = "%-5p [%c] %m\n";
221 : :
222 : : // Finally the text of the message
223 [ # # ][ # # ]: 0 : auto_ptr<log4cplus::Layout> layout(new log4cplus::PatternLayout(pattern));
224 [ # # ]: 0 : appender->setLayout(layout);
225 : 0 : }
226 : :
227 : : } // namespace log
228 : 141 : } // namespace isc
|