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