Coverage Report

Created: 2025-08-24 06:21

/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>&quot;${&quot;</b> and
206
closing <b>&quot;}&quot;</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