/src/logging-log4cxx/src/main/include/log4cxx/propertyconfigurator.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Licensed to the Apache Software Foundation (ASF) under one or more |
3 | | * contributor license agreements. See the NOTICE file distributed with |
4 | | * this work for additional information regarding copyright ownership. |
5 | | * The ASF licenses this file to You under the Apache License, Version 2.0 |
6 | | * (the "License"); you may not use this file except in compliance with |
7 | | * the License. You may obtain a copy of the License at |
8 | | * |
9 | | * http://www.apache.org/licenses/LICENSE-2.0 |
10 | | * |
11 | | * Unless required by applicable law or agreed to in writing, software |
12 | | * distributed under the License is distributed on an "AS IS" BASIS, |
13 | | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
14 | | * See the License for the specific language governing permissions and |
15 | | * limitations under the License. |
16 | | */ |
17 | | |
18 | | #ifndef _LOG4CXX_PROPERTY_CONFIGURATOR_H |
19 | | #define _LOG4CXX_PROPERTY_CONFIGURATOR_H |
20 | | |
21 | | #include <log4cxx/helpers/object.h> |
22 | | #include <log4cxx/logstring.h> |
23 | | #include <log4cxx/spi/configurator.h> |
24 | | #include <map> |
25 | | |
26 | | #include <log4cxx/file.h> |
27 | | |
28 | | namespace LOG4CXX_NS |
29 | | { |
30 | | class Logger; |
31 | | typedef std::shared_ptr<Logger> LoggerPtr; |
32 | | |
33 | | class Appender; |
34 | | typedef std::shared_ptr<Appender> AppenderPtr; |
35 | | |
36 | | namespace helpers |
37 | | { |
38 | | class Properties; |
39 | | } |
40 | | |
41 | | |
42 | | namespace spi |
43 | | { |
44 | | class LoggerFactory; |
45 | | typedef std::shared_ptr<LoggerFactory> LoggerFactoryPtr; |
46 | | } |
47 | | |
48 | | class PropertyWatchdog; |
49 | | /** |
50 | | Allows the configuration of log4cxx from an external file. |
51 | | |
52 | | \anchor PropertyConfigurator_details |
53 | | The configuration file consists of statements in the format |
54 | | <code>key=value</code>. |
55 | | A line beginning with a <code>#</code> or <code>!</code> character |
56 | | is ignored by %log4cxx (use for a comment). |
57 | | The syntax of different configuration |
58 | | elements are discussed below. |
59 | | |
60 | | The <code>PropertyConfigurator</code> does not handle the |
61 | | advanced configuration features supported by the |
62 | | {@link xml::DOMConfigurator DOMConfigurator} such as |
63 | | support for {@link spi::Filter Filters}, custom |
64 | | {@link spi::ErrorHandler ErrorHandlers}, nested |
65 | | appenders such as the {@link AsyncAppender AsyncAppender}, etc. |
66 | | |
67 | | <h3>Configuring appenders</h3> |
68 | | |
69 | | %Appender configuration syntax is: |
70 | | <pre> |
71 | | # For appender named <i>appenderName</i>, set its class. |
72 | | # Note: The appender name can contain dots. |
73 | | log4j.appender.appenderName=fully.qualified.name.of.appender.class |
74 | | |
75 | | # Set appender specific options. |
76 | | log4j.appender.appenderName.option1=value1 |
77 | | ... |
78 | | log4j.appender.appenderName.optionN=valueN |
79 | | </pre> |
80 | | |
81 | | For each named appender you can configure its {@link Layout Layout}. The |
82 | | syntax for configuring an appender's layout is: |
83 | | <pre> |
84 | | log4j.appender.appenderName.layout=fully.qualified.name.of.layout.class |
85 | | log4j.appender.appenderName.layout.option1=value1 |
86 | | .... |
87 | | log4j.appender.appenderName.layout.optionN=valueN |
88 | | </pre> |
89 | | |
90 | | Refer to the Appender::setOption override of each implemented appender and |
91 | | Layout::setOption override of each implemented layout |
92 | | for class specific options. |
93 | | |
94 | | <h3>Configuring loggers</h3> |
95 | | |
96 | | The syntax for configuring the root logger is: |
97 | | <pre> |
98 | | log4j.rootLogger=[level], appenderName, appenderName, ... |
99 | | </pre> |
100 | | |
101 | | This syntax means that an optional <em>level</em> can be |
102 | | supplied followed by appender names separated by commas. |
103 | | |
104 | | The level value can consist of the string values OFF, FATAL, |
105 | | ERROR, WARN, INFO, DEBUG, ALL or a <em>custom level</em> value. A |
106 | | custom level value can be specified in the form |
107 | | <code>level#classname</code>. |
108 | | |
109 | | If a level value is specified, then the root level is set |
110 | | to the corresponding level. If no level value is specified, |
111 | | then the root level remains untouched. |
112 | | |
113 | | The root logger can be assigned multiple appenders. |
114 | | |
115 | | Each <i>appenderName</i> (separated by commas) will be added to |
116 | | the root logger. The named appender is defined using the |
117 | | appender syntax defined above. |
118 | | |
119 | | For non-root categories the syntax is almost the same: |
120 | | <pre> |
121 | | log4j.logger.logger_name=[level|INHERITED|NULL], appenderName, appenderName, |
122 | | ... |
123 | | </pre> |
124 | | |
125 | | The meaning of the optional level value is discussed above |
126 | | in relation to the root logger. In addition however, the value |
127 | | INHERITED can be specified meaning that the named logger should |
128 | | inherit its level from the logger hierarchy. |
129 | | |
130 | | If no level value is supplied, then the level of the |
131 | | named logger remains untouched. |
132 | | |
133 | | By default categories inherit their level from the |
134 | | hierarchy. However, if you set the level of a logger and later |
135 | | decide that that logger should inherit its level, then you should |
136 | | specify INHERITED as the value for the level value. NULL is a |
137 | | synonym for INHERITED. |
138 | | |
139 | | Similar to the root logger syntax, each <i>appenderName</i> |
140 | | (separated by commas) will be attached to the named logger. |
141 | | |
142 | | See the <a href="concepts.html#appender-additivity">appender |
143 | | additivity rule</a> in the usage guide for the meaning of the |
144 | | <code>additivity</code> flag. |
145 | | |
146 | | <h3>Example</h3> |
147 | | |
148 | | An example configuration is given below. |
149 | | |
150 | | <pre> |
151 | | # Set options for appender named "A1". |
152 | | # Appender "A1" will be a SyslogAppender |
153 | | log4j.appender.A1=SyslogAppender |
154 | | |
155 | | # The syslog daemon resides on www.abc.net |
156 | | log4j.appender.A1.SyslogHost=www.abc.net |
157 | | |
158 | | # A1's layout is a PatternLayout, using the conversion pattern |
159 | | # "%r %-5p %c{2} %M.%L %x - %m%n". Thus, the log output will include |
160 | | # the relative time since the start of the application in milliseconds, followed by |
161 | | # the level of the log request, followed by |
162 | | # the two rightmost components of the logger name, followed by |
163 | | # the callers method name, followed by the line number, |
164 | | # the nested disgnostic context and finally the message itself. |
165 | | # Refer to the documentation of PatternLayout for further information |
166 | | # on the syntax of the ConversionPattern key. |
167 | | log4j.appender.A1.layout=PatternLayout |
168 | | log4j.appender.A1.layout.ConversionPattern=%-4r %-5p %%c{2} %%M.%%L %%x - %%m%%n |
169 | | |
170 | | # Set options for appender named "A2" |
171 | | # A2 should be a RollingFileAppender, |
172 | | # with maximum file size of 10 MB using at most one backup file. |
173 | | # A2's layout is: date and time (using the ISO8061 date format), |
174 | | # thread, level, logger name, nested diagnostic context |
175 | | # and finally the message itself. |
176 | | log4j.appender.A2=RollingFileAppender |
177 | | log4j.appender.A2.MaxFileSize=10MB |
178 | | log4j.appender.A2.MaxBackupIndex=1 |
179 | | log4j.appender.A2.layout=PatternLayout |
180 | | log4j.appender.A2.layout.ConversionPattern=%%d [%%t] %%p %%c %%x - %%m%%n |
181 | | |
182 | | # Root logger set to DEBUG using the A2 appender defined above. |
183 | | log4j.rootLogger=DEBUG, A2 |
184 | | |
185 | | # Logger definitions: |
186 | | # The SECURITY logger inherits is level from root. However, it's output |
187 | | # will go to A1 appender defined above. It's additivity is non-cumulative. |
188 | | log4j.logger.SECURITY=INHERIT, A1 |
189 | | log4j.additivity.SECURITY=false |
190 | | |
191 | | # Only warnings or above will be logged for the logger "SECURITY.access". |
192 | | # Output will go to A1. |
193 | | log4j.logger.SECURITY.access=WARN |
194 | | |
195 | | # The logger "class.of.the.day" inherits its level from the |
196 | | # logger hierarchy. Output will go to the appender's of the root |
197 | | # logger, A2 in this case. |
198 | | log4j.logger.class.of.the.day=INHERIT |
199 | | </pre> |
200 | | |
201 | | <h3>Dynamic option values</h3> |
202 | | |
203 | | All option <em>values</em> admit variable substitution. The |
204 | | syntax of variable substitution is similar to that of Unix |
205 | | shells. The string between an opening <b>"${"</b> and |
206 | | closing <b>"}"</b> is interpreted as a key. The value of |
207 | | the substituted variable can be defined as a system property or in |
208 | | the configuration file itself. The value of the key is first |
209 | | searched in the system properties, and if not found there, it is |
210 | | then searched in the configuration file being parsed. The |
211 | | corresponding value replaces the ${variableName} sequence. For |
212 | | example, if <code>home</code> system property is set to |
213 | | <code>/home/xyz</code>, then every occurrence of the sequence |
214 | | <code>${home}</code> will be interpreted as |
215 | | <code>/home/xyz</code>. |
216 | | |
217 | | <h3>Repository-wide threshold</h3> |
218 | | |
219 | | The repository-wide threshold filters logging requests by level |
220 | | regardless of logger. The syntax is: |
221 | | |
222 | | <pre> |
223 | | log4j.threshold=[level] |
224 | | </pre> |
225 | | |
226 | | The level value can consist of the string values OFF, FATAL, |
227 | | ERROR, WARN, INFO, DEBUG, ALL or a <em>custom level</em> value. A |
228 | | custom level value can be specified in the form |
229 | | level#classname. By default the repository-wide threshold is set |
230 | | to the lowest possible value, namely the level <code>ALL</code>. |
231 | | |
232 | | <h3>Debugging</h3> |
233 | | |
234 | | It is sometimes useful to see how %log4cxx is reading configuration |
235 | | files. You can <a href="internal-debugging.html">enable %log4cxx internal logging</a> |
236 | | by defining the <b>log4j.debug</b> variable in the property file. |
237 | | <pre> |
238 | | # Enable internal logging |
239 | | log4j.debug=true |
240 | | </pre> |
241 | | |
242 | | <h3>Logger Factories</h3> |
243 | | |
244 | | The usage of custom logger factories is discouraged and no longer |
245 | | documented. |
246 | | |
247 | | */ |
248 | | class LOG4CXX_EXPORT PropertyConfigurator : |
249 | | virtual public spi::Configurator, |
250 | | virtual public helpers::Object |
251 | | { |
252 | | protected: |
253 | | |
254 | | /** |
255 | | Used internally to keep track of configured appenders. |
256 | | */ |
257 | | std::map<LogString, AppenderPtr>* registry; |
258 | | |
259 | | /** |
260 | | Used to create new instances of logger |
261 | | */ |
262 | | LOG4CXX_DECLARE_PRIVATE_MEMBER(spi::LoggerFactoryPtr, loggerFactory) |
263 | | |
264 | | public: |
265 | | DECLARE_LOG4CXX_OBJECT(PropertyConfigurator) |
266 | 0 | BEGIN_LOG4CXX_CAST_MAP() |
267 | | #if 15 < LOG4CXX_ABI_VERSION |
268 | | LOG4CXX_CAST_ENTRY(PropertyConfigurator) |
269 | | LOG4CXX_CAST_ENTRY_CHAIN(spi::Configurator) |
270 | | #else |
271 | 0 | LOG4CXX_CAST_ENTRY(spi::Configurator) |
272 | 0 | #endif |
273 | 0 | END_LOG4CXX_CAST_MAP() |
274 | | |
275 | | PropertyConfigurator(); |
276 | | virtual ~PropertyConfigurator(); |
277 | | /** |
278 | | Read configuration from \c configFileName. |
279 | | If \c repository is not provided, |
280 | | the spi::LoggerRepository held by LogManager is used. |
281 | | <b>The existing configuration is not cleared nor reset.</b> |
282 | | If you require a different behavior, |
283 | | call {@link spi::LoggerRepository::resetConfiguration resetConfiguration} |
284 | | before calling <code>doConfigure</code>. |
285 | | |
286 | | @param configFileName The file to parse. |
287 | | @param repository Where the Logger instances reside. |
288 | | */ |
289 | | spi::ConfigurationStatus doConfigure |
290 | | ( const File& configFileName |
291 | | #if LOG4CXX_ABI_VERSION <= 15 |
292 | | , spi::LoggerRepositoryPtr repository |
293 | | #else |
294 | | , const spi::LoggerRepositoryPtr& repository = spi::LoggerRepositoryPtr() |
295 | | #endif |
296 | | ) override; |
297 | | |
298 | | /** |
299 | | Read configuration options from file <code>configFilename</code>. |
300 | | Stores Logger instances in the spi::LoggerRepository held by LogManager. |
301 | | */ |
302 | | static spi::ConfigurationStatus configure(const File& configFilename); |
303 | | |
304 | | #if LOG4CXX_ABI_VERSION <= 15 |
305 | | /** |
306 | | Like {@link #configureAndWatch(const File& configFilename, long delay)} |
307 | | except that the |
308 | | default delay as defined by helpers::FileWatchdog#DEFAULT_DELAY |
309 | | is used. |
310 | | @param configFilename A file in key=value format. |
311 | | */ |
312 | | static spi::ConfigurationStatus configureAndWatch(const File& configFilename); |
313 | | #endif |
314 | | /** |
315 | | Read configuration options from \c configFilename (if it exists). |
316 | | Stores Logger instances in the spi::LoggerRepository held by LogManager. |
317 | | A thread will be created that periodically checks |
318 | | whether \c configFilename has been created or modified. |
319 | | A period of log4cxx::helpers::FileWatchdog#DEFAULT_DELAY |
320 | | is used if \c delay is not a positive number. |
321 | | If a change or file creation is detected, |
322 | | then \c configFilename is read to configure Log4cxx. |
323 | | |
324 | | The thread will be stopped by a LogManager::shutdown call. |
325 | | |
326 | | @param configFilename A file in key=value format. |
327 | | @param delay The delay in milliseconds to wait between each check. |
328 | | */ |
329 | | static spi::ConfigurationStatus configureAndWatch(const File& configFilename, |
330 | | long delay = 0); |
331 | | |
332 | | /** |
333 | | Read configuration options from <code>properties</code>. |
334 | | Stores Logger instances in the spi::LoggerRepository held by LogManager. |
335 | | See the \ref PropertyConfigurator_details "detailed description" |
336 | | for the expected format. |
337 | | */ |
338 | | static spi::ConfigurationStatus configure(helpers::Properties& properties); |
339 | | |
340 | | /** |
341 | | Read configuration options from <code>properties</code>. |
342 | | See the \ref PropertyConfigurator_details "detailed description" |
343 | | for the expected format. |
344 | | */ |
345 | | spi::ConfigurationStatus doConfigure(helpers::Properties& properties, |
346 | | spi::LoggerRepositoryPtr hierarchy); |
347 | | |
348 | | // -------------------------------------------------------------------------- |
349 | | // Internal stuff |
350 | | // -------------------------------------------------------------------------- |
351 | | protected: |
352 | | /** |
353 | | Check the provided <code>Properties</code> object for a LoggerFactory |
354 | | entry specified by *log4j.loggerFactory*. If such an entry |
355 | | exists, an attempt is made to create an instance using the default |
356 | | constructor. This instance is used for subsequent Logger creations |
357 | | within this configurator. |
358 | | @see #parseCatsAndRenderers |
359 | | */ |
360 | | void configureLoggerFactory(helpers::Properties& props); |
361 | | |
362 | | void configureRootLogger(helpers::Properties& props, |
363 | | spi::LoggerRepositoryPtr& hierarchy); |
364 | | |
365 | | /** |
366 | | Parse non-root elements, such non-root categories and renderers. |
367 | | */ |
368 | | void parseCatsAndRenderers(helpers::Properties& props, |
369 | | spi::LoggerRepositoryPtr& hierarchy); |
370 | | |
371 | | /** |
372 | | Parse the additivity option for a non-root logger. |
373 | | */ |
374 | | bool parseAdditivityForLogger(helpers::Properties& props, |
375 | | LoggerPtr& cat, const LogString& loggerName); |
376 | | |
377 | | /** |
378 | | This method must work for the root logger as well. |
379 | | */ |
380 | | void parseLogger( |
381 | | helpers::Properties& props, LoggerPtr& logger, |
382 | | const LogString& optionKey, const LogString& loggerName, |
383 | | const LogString& value, bool additivity); |
384 | | |
385 | | AppenderPtr parseAppender( |
386 | | helpers::Properties& props, const LogString& appenderName); |
387 | | |
388 | | void registryPut(const AppenderPtr& appender); |
389 | | AppenderPtr registryGet(const LogString& name); |
390 | | |
391 | | private: |
392 | | PropertyConfigurator(const PropertyConfigurator&); |
393 | | PropertyConfigurator& operator=(const PropertyConfigurator&); |
394 | | }; // class PropertyConfigurator |
395 | | } // namespace log4cxx |
396 | | |
397 | | |
398 | | #endif //_LOG4CXX_PROPERTY_CONFIGURATOR_H |