Coverage Report

Created: 2026-02-26 06:58

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/logging-log4cxx/src/main/include/log4cxx/propertyconfigurator.h
Line
Count
Source
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
#if 15 < LOG4CXX_ABI_VERSION
253
  private:
254
    struct PrivateData;
255
    LOG4CXX_DECLARE_PRIVATE_MEMBER_PTR(PrivateData, m_priv)
256
#else
257
  protected:
258
259
    /**
260
    Used internally to keep track of configured appenders.
261
    */
262
    std::map<LogString, AppenderPtr>* registry;
263
264
    /**
265
    Used to create new instances of logger
266
    */
267
    LOG4CXX_DECLARE_PRIVATE_MEMBER(spi::LoggerFactoryPtr, loggerFactory)
268
#endif
269
  public:
270
    DECLARE_LOG4CXX_OBJECT(PropertyConfigurator)
271
0
    BEGIN_LOG4CXX_CAST_MAP()
272
#if 15 < LOG4CXX_ABI_VERSION
273
    LOG4CXX_CAST_ENTRY(PropertyConfigurator)
274
    LOG4CXX_CAST_ENTRY_CHAIN(spi::Configurator)
275
#else
276
0
    LOG4CXX_CAST_ENTRY(spi::Configurator)
277
0
#endif
278
0
    END_LOG4CXX_CAST_MAP()
279
280
    PropertyConfigurator();
281
    virtual ~PropertyConfigurator();
282
    /**
283
    Read configuration from \c configFileName.
284
    If \c repository is not provided,
285
    the spi::LoggerRepository held by LogManager is used.
286
    <b>The existing configuration is not cleared nor reset.</b>
287
    If you require a different behavior,
288
    call {@link spi::LoggerRepository::resetConfiguration resetConfiguration}
289
    before calling <code>doConfigure</code>.
290
291
    @param configFileName The file to parse.
292
    @param repository Where the Logger instances reside.
293
    */
294
    spi::ConfigurationStatus doConfigure
295
      ( const File&                     configFileName
296
#if LOG4CXX_ABI_VERSION <= 15
297
      , spi::LoggerRepositoryPtr        repository
298
#else
299
      , const spi::LoggerRepositoryPtr& repository = spi::LoggerRepositoryPtr()
300
#endif
301
      ) override;
302
303
    /**
304
    Read configuration options from file <code>configFilename</code>.
305
    Stores Logger instances in the spi::LoggerRepository held by LogManager.
306
    */
307
    static spi::ConfigurationStatus configure(const File& configFilename);
308
309
#if LOG4CXX_ABI_VERSION <= 15
310
    /**
311
    Like {@link #configureAndWatch(const File& configFilename, long delay)}
312
    except that the
313
    default delay as defined by helpers::FileWatchdog#DEFAULT_DELAY
314
    is used.
315
    @param configFilename A file in key=value format.
316
    */
317
    static spi::ConfigurationStatus configureAndWatch(const File& configFilename);
318
#endif
319
    /**
320
    Read configuration options from \c configFilename (if it exists).
321
    Stores Logger instances in the spi::LoggerRepository held by LogManager.
322
    A thread will be created that periodically checks
323
    whether \c configFilename has been created or modified.
324
    A period of log4cxx::helpers::FileWatchdog#DEFAULT_DELAY
325
    is used if \c delay is not a positive number.
326
    If a change or file creation is detected,
327
    then \c configFilename is read to configure Log4cxx.
328
329
    The thread will be stopped by a LogManager::shutdown call.
330
331
    @param configFilename A file in key=value format.
332
    @param delay The delay in milliseconds to wait between each check.
333
    */
334
    static spi::ConfigurationStatus configureAndWatch(const File& configFilename,
335
      long delay = 0);
336
337
    /**
338
    Read configuration options from <code>properties</code>.
339
    Stores Logger instances in the spi::LoggerRepository held by LogManager.
340
    See the \ref PropertyConfigurator_details "detailed description"
341
    for the expected format.
342
    */
343
    static spi::ConfigurationStatus configure(helpers::Properties& properties);
344
345
    /**
346
    Read configuration options from <code>properties</code>.
347
    See the \ref PropertyConfigurator_details "detailed description"
348
    for the expected format.
349
    */
350
    spi::ConfigurationStatus doConfigure(helpers::Properties& properties,
351
      spi::LoggerRepositoryPtr hierarchy);
352
353
    // --------------------------------------------------------------------------
354
    // Internal stuff
355
    // --------------------------------------------------------------------------
356
  protected:
357
    /**
358
    Check the provided <code>Properties</code> object for a LoggerFactory
359
    entry specified by *log4j.loggerFactory*.  If such an entry
360
    exists, an attempt is made to create an instance using the default
361
    constructor.  This instance is used for subsequent Logger creations
362
    within this configurator.
363
    @see #parseCatsAndRenderers
364
    */
365
    void configureLoggerFactory(helpers::Properties& props);
366
367
    void configureRootLogger(helpers::Properties& props,
368
      spi::LoggerRepositoryPtr& hierarchy);
369
370
    /**
371
    Parse non-root elements, such non-root categories and renderers.
372
    */
373
    void parseCatsAndRenderers(helpers::Properties& props,
374
      spi::LoggerRepositoryPtr& hierarchy);
375
376
    /**
377
    Parse the additivity option for a non-root logger.
378
    */
379
    bool parseAdditivityForLogger(helpers::Properties& props,
380
      LoggerPtr& cat, const LogString& loggerName);
381
382
    /**
383
    This method must work for the root logger as well.
384
    */
385
    void parseLogger(
386
      helpers::Properties& props, LoggerPtr& logger,
387
      const LogString& optionKey, const LogString& loggerName,
388
      const LogString& value, bool additivity);
389
390
    AppenderPtr parseAppender(
391
      helpers::Properties& props, const LogString& appenderName);
392
393
    void registryPut(const AppenderPtr& appender);
394
    AppenderPtr registryGet(const LogString& name);
395
396
  private:
397
    PropertyConfigurator(const PropertyConfigurator&);
398
    PropertyConfigurator& operator=(const PropertyConfigurator&);
399
}; // class PropertyConfigurator
400
}  // namespace log4cxx
401
402
403
#endif //_LOG4CXX_PROPERTY_CONFIGURATOR_H