Codebase list apache-log4j2 / 3c1cf1c
New upstream version 2.7 Emmanuel Bourg 7 years ago
755 changed file(s) with 37999 addition(s) and 12317 deletion(s). Raw diff Collapse all Expand all
0 /.project
1 /.idea
0 .project
1 .idea
22 **/*.iml
33 **/target
4 /target/
5 /.settings
4 target/
5 .settings
6 .classpath
7 .cache-main
8 .cache-tests
9 velocity.log
10 felix-cache/
11 bin/
2020
2121 [How to download Log4j](http://logging.apache.org/log4j/2.x/download.html),
2222 and [how to use it from Maven, Ivy and Gradle](http://logging.apache.org/log4j/2.x/maven-artifacts.html).
23
24 ## Issue Tracking
25
26 Issues, bugs, and feature requests should be submitted to the
27 [JIRA issue tracking system for this project](https://issues.apache.org/jira/browse/LOG4J2).
28
29 Pull request on GitHub are welcome, but please open a ticket in the JIRA issue tracker first, and mention the
30 JIRA issue in the Pull Request.
00
1 Apache Log4j 2.6.2 RELEASE NOTES
1 Apache Log4j 2.7 RELEASE NOTES
22
3 The Apache Log4j 2 team is pleased to announce the Log4j 2.6.2 release!
3 The Apache Log4j 2 team is pleased to announce the Log4j 2.7 release!
44
55 Apache Log4j is a well known framework for logging application behavior. Log4j 2 is an upgrade
66 to Log4j that provides significant improvements over its predecessor, Log4j 1.x, and provides
99 Loggers. Another notable Log4j 2 feature is the ability to be "garbage-free" (avoid allocating
1010 temporary objects) while logging. In addition, Log4j 2 will not lose events while reconfiguring.
1111
12 This is the twelfth GA release. It is primarily a bugfix release. More details on the
13 fixes are itemized below.
12 This release contains several bugfixes and new features. The new features include new logging API
13 modules for Scala 2.10 and 2.11, and support for various non-blocking queue implementations in
14 AsyncAppender. Furthermore the ThreadContext map can now be configured to be garbage-free, and
15 users can now inject context data from other sources than ThreadContext. Context data values can
16 be any Object, not just Strings. More details on the fixes are itemized below.
1417
1518 Note that subsequent to the 2.6 release a minor source incompatibility was found due to the
1619 addition of new methods to the Logger interface. If you have code that does:
2629
2730 logger.error((Marker) null, “This is the log message”, throwable);
2831
29 Log4j 2.6.2 maintains binary compatibility with previous releases.
32 The Log4j 2.7 API, as well as many core components, maintains binary compatibility with previous releases.
3033
31 GA Release 2.6.2
34 GA Release 2.7
3235
3336 Changes in this version include:
3437
3538 New features:
36 o LOG4J2-1395: Add "direct" option to ConsoleAppender for increased performance.
37 o LOG4J2-1437: (GC) ObjectMessage and ReusableObjectMessage now avoid calling toString() on auto-boxed primitive parameters.
38 o LOG4J2-1415: (GC) ParameterFormatter now avoids calling toString() on auto-boxed primitive message parameters.
39 o LOG4J2-1412: Unbox utility's ringbuffer of StringBuilders is now configurable.
39 o LOG4J2-1578: RoutingAppender can be configured with scripts. Add Script in a Routes element.
40 o LOG4J2-1597: Add a ScriptAppenderSelector to create an Appender specified by a Script.
41 o LOG4J2-1349: (GC) Added support for garbage-free ThreadContext map. Disabled by default, users need to enable this explicitly.
42 o LOG4J2-1447: (GC) Changed LogEvent's internal data structure for context data to be garbage-free. Added method LogEvent#getContextData(), deprecated method #getContextMap().
43 o LOG4J2-1010: Users can now inject context data from other sources than ThreadContext. Values can be any Object, not just Strings. Thanks to Mikael Ståldal.
44 o LOG4J2-1568: Added support for java.util.concurrent.LinkedTransferQueue to AsyncAppender.
45 o LOG4J2-1430: Added optional support for Conversant DisruptorBlockingQueue in AsyncAppender. Thanks to John Cairns.
46 o LOG4J2-1439: Added optional support for JCTools MPSC bounded lock-free queue in AsyncAppender. Thanks to Anthony Maire.
47 o LOG4J2-1558: SocketAppender now supports IO buffering.
48 o LOG4J2-1557: Add a Builder for the SocketAppender (deprecates factory method).
49 o LOG4J2-1609: Add a Builder to ServletAppender and deprecate factory method.
50 o LOG4J2-1553: AbstractManager now implements AutoCloseable.
51 o LOG4J2-1528: Added ability to generate Log4j 2-style XML configuration file from ConfigurationBuilder.
52 o LOG4J2-1181: Added Logging API for Scala 2.10 and 2.11.
53 o LOG4J2-1512: Added options to exclude stack trace from JSON, XML and YAML layouts.
54 o LOG4J2-1539: Added Core API Configurator.shutdown(LoggerContext, long, TimeUnit).
55 o LOG4J2-1501: FileAppender is now able to create files on-demand.
56 o LOG4J2-1504: RollingFileAppender is now able to create files on-demand.
57 o LOG4J2-1471: [PatternLayout] Add an ANSI option to %xThrowable.
58 o LOG4J2-1472: org.apache.logging.log4j.core.LoggerContext now implements Closeable.
59 o LOG4J2-1458: [PatternLayout] Add an ANSI option to %message.
60 o LOG4J2-1505: Create a Builder for the FileAppender plugin to facilitate adding attributes in the future.
61 o LOG4J2-1507: Allow Builders to be completely generic.
62 o LOG4J2-1508: Allow a Builder to subclass another Builder.
63 o LOG4J2-1516: Add ThreadContextMap2 interface supporting method putAll(Map<String, String>). Thanks to Gary Gregory.
64 o LOG4J2-1519: Add ThreadContext.putAll(Map<String, String>).
65 o LOG4J2-1520: Add JUnit Rule implementations to manage the thread context.
66 o LOG4J2-1547: The Core AbstractConfiguration now tracks its LoggerContext and add Configuration.getLoggerContext().
67 o LOG4J2-1540: The Core AbstractManager now tracks its LoggerContext.
68 o LOG4J2-1577: Add a Builder to the RoutingAppender and deprecate factory method.
4069
4170 Fixed Bugs:
42 o LOG4J2-1414: Fixed minor issues with the 2.6.1 web site. Thanks to Ralph Goers.
43 o LOG4J2-1434: Ensure that the thread-local StringBuilders used by Layouts to format log events to text will not
44 retain excessive memory after a large message was logged. Thanks to Luke Butters.
45 o LOG4J2-1418: Provide MessageFactory2 to custom Logger implementations.
46 o LOG4J2-1420: RollingRandomAccessFileManager was not properly rolling over on startup and was getting a NullPointerException.
47 o LOG4J2-1417: Fixed issue where Unbox utility ignored the value Constants.ENABLE_THREADLOCALS and always stored non-JDK classes in ThreadLocals.
48 o LOG4J2-1422: Fixed issue where AsyncAppenderQueueFullPolicyTest sometimes hangs.
49 o LOG4J2-1445: OnStartupTriggeringPolicyTest fails on Windows saying the file is used by another process. Thanks to Ludovic HOCHET.
71 o LOG4J2-1618: Fixed ClassCastException when using JUL logging during shutdown. Thanks to Raman Gupta.
72 o LOG4J2-1620: 2.7-rc1: RollingFileAppender immediateFlush default value should be true, not false. Thanks to Sascha Scholz.
73 o LOG4J2-1611: Improved performance of context data injector for web applications to be on par with standalone applications.
74 o LOG4J2-1591: Introduced new interface LifeCycle2 with stop(long,TimeUnit) method to avoid breaking backwards compatibility with new Configurator.shutdown(LoggerContext, long, TimeUnit) API.
75 o LOG4J2-1590: Fixed issue with filters extending AbstractFilter that did not override methods with unrolled varargs.
76 o LOG4J2-1583: Fixed scrambled log messages triggered by nested logging from toString() method of a logging parameter object. Thanks to Larry West.
77 o LOG4J2-1259: Log4j threads are no longer leaking on Tomcat shutdown. Thanks to Misagh Moayyed, Steffen Offermann.
78 o LOG4J2-1051: When starting on Google App Engine, Interpolator now suppresses the NoClassDefFoundError stack trace for the jvmrunargs lookup. Thanks to Lukasz Lenart.
79 o LOG4J2-1582: When initializing on platforms where JMX is not available, Interpolator component no longer prints stack trace for warning messages.
80 o LOG4J2-1581: Unregistering JMX components no longer prints a stack trace when the MBean has already been unregistered.
81 o LOG4J2-1313: Support Property values to be specified in configuration as a value attribute as well as an element. Thanks to Philipp Knobel, Leon Finker.
82 o LOG4J2-1575: (GC) LoggerConfig now stores configuration properties in a List, not a Map to prevent creating temporary Iterator objects. Added method LoggerConfig#getPropertyList(), deprecated method #getProperties().
83 o LOG4J2-1457: Fixed class loader deadlock when using async logging and extended stack trace pattern. Thanks to Leon Finker.
84 o LOG4J2-1563: Fix to prevent Log4j 2.6.2 and higher from losing exceptions when a security manager is present. Thanks to Jason Tedor.
85 o LOG4J2-1530: Fixed issue where LogEvent.getContextStack() returned null.
86 o LOG4J2-1518: Prevent deadlock in Async Loggers when queue is full and logged Object's toString() logs another message. Thanks to Leon Finker.
87 o LOG4J2-1542: Prevent ArrayIndexOutOfBoundsException in ParameterizedMessage.formatTo for single-char or empty messages. Thanks to Rogério Lecarião Leite.
88 o LOG4J2-1549: Fixed issue where AsyncLoggerContextSelector+PropertiesConfigurationBuilder defaulted to includeLocation=true. Thanks to Jason Bedard.
89 o LOG4J2-1562: Prevent SocketAppender memory usage from growing unbounded if it cannot connect to a server.
90 o LOG4J2-1559: Prevent NPE in Level.isInRange. Thanks to Andrey Plotkin.
91 o LOG4J2-1511: DynamicThresholdFilter filtered incorrectly when params were passed as individual arguments instead of varargs. Thanks to Srikanth Surukuntu.
92 o LOG4J2-1548: [CronTriggeringPolicy] ConfigurationScheduler scheduled the task infinitely after first fire.
93 o LOG4J2-1506: Log4j should not unregister JMX MBeans when log4j2.disable.jmx property is true. Thanks to Johannes Schleger.
94 o LOG4J2-1490: Log4j2 should postpone creating log file until the appender actually receives an event. Thanks to Krzysztof Taborski.
95 o LOG4J2-1320: Support loading custom plugins from jar files and directories whose classpath entries use the "vfs" URL protocol. Thanks to Paresh Varke, Pierrick Hymbert.
96 o LOG4J2-1541: Fix file handle resource leak in XmlConfiguration.XmlConfiguration(ConfigurationSource).
97 o LOG4J2-1538: Prevent NPE when dynamically removing filters. Thanks to Igor Karpov.
98 o LOG4J2-1532: Attributes were not merged properly in composite configurations.
99 o LOG4J2-1529: Attributes were not merged properly in composite configurations. Thanks to Sridevi Narra.
100 o LOG4J2-1527: Prevent NPE in RingBufferLogEvent.getFormattedMessage() when used in web applications. Thanks to Jose Leon.
101 o LOG4J2-905: Added ability to disable (date) lookup completely for compatibility with other libraries like Camel. Thanks to Moritz Löser.
102 o LOG4J2-1526: Added support for setting StatusLogger destination in ConfigurationBuilder.
103 o LOG4J2-1448: Allow comma separated agents, host list to be passed to FlumeAppender. Thanks to Keith Laban.
104 o LOG4J2-1500: Merging configurations failed with an NPE when comparing Nodes with different attributes. Thanks to Jose Leon.
105 o LOG4J2-1482: Fixed improper header in CsvParameterLayout. Thanks to Sumit Singhal.
106 o LOG4J2-1199: Documented that JVM Input Arguments Lookup (JMX) is not available on Google App Engine.
107 o LOG4J2-1438: (GC) Added method getParameter() to ObjectMessage (and ReusableObjectMessage).
108 o LOG4J2-1488: (GC) Fixed ISO8601 %date conversion pattern with a period '.' separator for milliseconds is now garbage free. Thanks to Richard Zschech.
109 o LOG4J2-1489: (GC) Fixed %date conversion patterns with a timezone parameter are now garbage free. Thanks to Richard Zschech.
110 o LOG4J2-1279: Prevent NullPointerException in FastDateParser$TimeZoneStrategy. Thanks to Tony Baines.
111 o LOG4J2-1341: (GC) HighlightConverter and StyleConverter are now GC-free. Thanks to Richard Zschech.
112 o LOG4J2-1467: [OSGi] Fixed missing import package. Thanks to Ralf, Gary Gregory.
113 o LOG4J2-351: [OSGi] Fixed wrong Fragment-Host in manifest files. Thanks to Roland Weiglhofer.
114 o LOG4J2-1313: Properties declared in configuration can now have their value either in the element body or in an attribute named "value". Thanks to Philipp Knobel.
115 o LOG4J2-1235: org.apache.logging.log4j.core.appender.routing.IdlePurgePolicy was not working correctly. Thanks to Niranjan Rao, Sascha Scholz, Aleksey Zvolinsky.
116 o LOG4J2-1502: Fixed issue where CsvParameterLayout and CsvLogEventLayout inserted NUL characters if data starts with {, (, [ or " Thanks to Sumit Singhal.
117 o LOG4J2-1573: Layout is no longer optional. Thanks to Steffen Offermann.
118 o LOG4J2-1608: ServletAppender does not provide throwable object to ServletContext.
119 o LOG4J2-1599: Prevent potential NPE in org.apache.logging.log4j.message.ParameterFormatter.formatMessage3(StringBuilder, char[], int, Object[], int, int[]).
120 o LOG4J2-1600: Prevent potential NPE due to org.apache.logging.log4j.core.layout.MarkerPatternSelector.createSelector(PatternMatch[], String, boolean, boolean, Configuration).
121 o LOG4J2-1601: Prevent potential NPE due to org.apache.logging.log4j.core.layout.ScriptPatternSelector.createSelector(AbstractScript, PatternMatch[], String, boolean, boolean, Configuration).
122 o LOG4J2-1602: Prevent potential NPE in org.apache.logging.log4j.core.util.datetime.FormatCache.MultipartKey.equals(Object) when object is null.
123 o LOG4J2-1603: Redo hashCode() and equals() methods in org.apache.logging.log4j.core.net.ssl classes.
124 o LOG4J2-1610: Add targetNamespace to log4j-config.xsd. GitHub #43. Thanks to Shubhankar.
125 o LOG4J2-1619: new Log4jLogEvent().toString() throws an NPE.
50126
51127 Changes:
52 o LOG4J2-1432: Update Jackson from 2.7.4 to 2.7.5.
53 o LOG4J2-1433: Update Jansi from 1.11 to 1.13.
54 o LOG4J2-1444: Update Apache Commons Compress from 1.11 to 1.12.
128 o LOG4J2-1604: Log4j2 TcpSocketServer in background. Thanks to Colin Hillman.
129 o LOG4J2-1574: Allow the RollingFileAppender to use default pattern layout.
130 o LOG4J2-1556: Custom Log4j threads now extend Log4jThread.
131 o LOG4J2-1605: Improve error messages for TcpSocketServer and UdpSocketServer.
132 o LOG4J2-1458: Updated Jackson from 2.7.5 to 2.8.0.
133 o LOG4J2-1494: Updated Jackson from 2.8.0 to 2.8.1.
134 o LOG4J2-1569: Updated Jackson from 2.8.1 to 2.8.2.
135 o LOG4J2-1598: Updated Jackson from 2.8.2 to 2.8.3.
136 o LOG4J2-1495: Updated LMAX Disruptor from 3.3.4 to 3.3.5.
137 o LOG4J2-1496: Updated Kafka client from 0.9.1.0 to 0.10.0.0.
138 o LOG4J2-1533: Updated Kafka client from 0.10.0.0 to 0.10.0.1.
139 o LOG4J2-1487: Updated JMS test from ActiveMQ 5.13.3 to 5.13.4.
140 o LOG4J2-1551: Updated JMS test from ActiveMQ 5.13.4 to 5.14.0.
141 o LOG4J2-1543: Removed deprecated Core API org.apache.logging.log4j.core.util.Constants.UTF_8.
142 o LOG4J2-1544: Removed deprecated Core API org.apache.logging.log4j.core.util.Assert.requireNonNull(T, String).
143 o LOG4J2-1545: Removed deprecated Web API org.apache.logging.log4j.web.WebLookup.getServletContext().
55144
56145
57 Apache Log4j 2.6.2 requires a minimum of Java 7 to build and run. Log4j 2.3 was the last release that
58 supported Java 6.
146 Apache Log4j 2.7 requires a minimum of Java 7 to build and run. Log4j 2.3 was the
147 last release that supported Java 6.
59148
60 Basic compatibility with Log4j 1.x is provided through the log4j-1.2-api component, however it does not implement some of the
61 very implementation specific classes and methods. The package names and Maven groupId have been changed to
62 org.apache.logging.log4j to avoid any conflicts with log4j 1.x.
149 Basic compatibility with Log4j 1.x is provided through the log4j-1.2-api component, however it
150 does not implement some of the very implementation specific classes and methods. The package
151 names and Maven groupId have been changed to org.apache.logging.log4j to avoid any conflicts
152 with log4j 1.x.
63153
64 For complete information on Apache Log4j 2, including instructions on how to submit bug reports,
65 patches, or suggestions for improvement, see the Apache Apache Log4j 2 website:
154 For complete information on Apache Log4j 2, including instructions on how to submit bug
155 reports, patches, or suggestions for improvement, see the Apache Apache Log4j 2 website:
66156
67157 http://logging.apache.org/log4j/2.x/
+0
-5
log4j-1.2-api/.gitignore less more
0 /.settings/
1 /target/
2 /.classpath
3 /.project
4 /velocity.log
1919 <parent>
2020 <groupId>org.apache.logging.log4j</groupId>
2121 <artifactId>log4j</artifactId>
22 <version>2.6.2</version>
22 <version>2.7</version>
2323 <relativePath>../</relativePath>
2424 </parent>
2525 <artifactId>log4j-1.2-api</artifactId>
3232 <projectDir>/log4j12-api</projectDir>
3333 </properties>
3434 <dependencies>
35 <!-- Command line for configuration file conversion -->
36 <dependency>
37 <groupId>com.beust</groupId>
38 <artifactId>jcommander</artifactId>
39 <optional>true</optional>
40 </dependency>
3541 <dependency>
3642 <groupId>junit</groupId>
3743 <artifactId>junit</artifactId>
107113 <artifactId>maven-bundle-plugin</artifactId>
108114 <configuration>
109115 <instructions>
116 <Fragment-Host>org.apache.logging.log4j.core</Fragment-Host>
110117 <Export-Package>org.apache.log4j.*</Export-Package>
111118 </instructions>
112119 </configuration>
1616 package org.apache.log4j;
1717
1818 import org.apache.log4j.spi.LoggingEvent;
19 import org.apache.logging.log4j.core.util.Constants;
19 import org.apache.logging.log4j.util.Strings;
2020
2121 /**
2222 *
2424 public abstract class Layout {
2525
2626 /** Note that the line.separator property can be looked up even by applets. */
27 public static final int LINE_SEP_LEN = Constants.LINE_SEPARATOR.length();
27 public static final int LINE_SEP_LEN = Strings.LINE_SEPARATOR.length();
2828
2929 /**
3030 * Implement this method to create your own layout format.
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.log4j.config;
17
18 import java.io.IOException;
19 import java.io.InputStream;
20
21 class InputStreamWrapper extends InputStream {
22
23 private final String description;
24 private final InputStream input;
25
26 public InputStreamWrapper(final InputStream input, final String description) {
27 this.input = input;
28 this.description = description;
29 }
30
31 @Override
32 public int available() throws IOException {
33 return input.available();
34 }
35
36 @Override
37 public void close() throws IOException {
38 input.close();
39 }
40
41 @Override
42 public boolean equals(final Object obj) {
43 return input.equals(obj);
44 }
45
46 @Override
47 public int hashCode() {
48 return input.hashCode();
49 }
50
51 @Override
52 public synchronized void mark(final int readlimit) {
53 input.mark(readlimit);
54 }
55
56 @Override
57 public boolean markSupported() {
58 return input.markSupported();
59 }
60
61 @Override
62 public int read() throws IOException {
63 return input.read();
64 }
65
66 @Override
67 public int read(final byte[] b) throws IOException {
68 return input.read(b);
69 }
70
71 @Override
72 public int read(final byte[] b, final int off, final int len) throws IOException {
73 return input.read(b, off, len);
74 }
75
76 @Override
77 public synchronized void reset() throws IOException {
78 input.reset();
79 }
80
81 @Override
82 public long skip(final long n) throws IOException {
83 return input.skip(n);
84 }
85
86 @Override
87 public String toString() {
88 return getClass().getSimpleName() + " [description=" + description + ", input=" + input + "]";
89 }
90
91 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.log4j.config;
17
18 import java.io.IOException;
19 import java.io.InputStream;
20 import java.io.OutputStream;
21 import java.nio.file.FileVisitResult;
22 import java.nio.file.Files;
23 import java.nio.file.Path;
24 import java.nio.file.SimpleFileVisitor;
25 import java.nio.file.attribute.BasicFileAttributes;
26 import java.util.concurrent.atomic.AtomicInteger;
27
28 import org.apache.logging.log4j.core.config.ConfigurationException;
29 import org.apache.logging.log4j.core.config.builder.api.ConfigurationBuilder;
30 import org.apache.logging.log4j.core.config.builder.impl.BuiltConfiguration;
31 import org.apache.logging.log4j.core.util.BasicCommandLineArguments;
32
33 import com.beust.jcommander.Parameter;
34
35 /**
36 * Tool for converting a Log4j 1.x properties configuration file to Log4j 2.x XML configuration file.
37 *
38 * <p>
39 * Run with "--help" on the command line.
40 * </p>
41 *
42 * <p>
43 * Example:
44 * </p>
45 *
46 * <pre>
47 * java org.apache.log4j.config.Log4j1ConfigurationConverter --recurse
48 * E:\vcs\git\apache\logging\logging-log4j2\log4j-1.2-api\src\test\resources\config-1.2\hadoop --in log4j.properties --verbose
49 * </pre>
50 */
51 public final class Log4j1ConfigurationConverter {
52
53 public static class CommandLineArguments extends BasicCommandLineArguments {
54
55 @Parameter(names = { "--failfast", "-f" }, description = "Fails on the first failure in recurse mode.")
56 private boolean failFast;
57
58 @Parameter(names = { "--in", "-i" }, description = "Specifies the input file.")
59 private Path pathIn;
60
61 @Parameter(names = { "--out", "-o" }, description = "Specifies the output file.")
62 private Path pathOut;
63
64 @Parameter(names = { "--recurse", "-r" }, description = "Recurses into this folder looking for the input file")
65 private Path recurseIntoPath;
66
67 @Parameter(names = { "--verbose", "-v" }, description = "Be verbose.")
68 private boolean verbose;
69
70 public Path getPathIn() {
71 return pathIn;
72 }
73
74 public Path getPathOut() {
75 return pathOut;
76 }
77
78 public Path getRecurseIntoPath() {
79 return recurseIntoPath;
80 }
81
82 public boolean isFailFast() {
83 return failFast;
84 }
85
86 public boolean isVerbose() {
87 return verbose;
88 }
89
90 public void setFailFast(final boolean failFast) {
91 this.failFast = failFast;
92 }
93
94 public void setPathIn(final Path pathIn) {
95 this.pathIn = pathIn;
96 }
97
98 public void setPathOut(final Path pathOut) {
99 this.pathOut = pathOut;
100 }
101
102 public void setRecurseIntoPath(final Path recurseIntoPath) {
103 this.recurseIntoPath = recurseIntoPath;
104 }
105
106 public void setVerbose(final boolean verbose) {
107 this.verbose = verbose;
108 }
109
110 @Override
111 public String toString() {
112 return "CommandLineArguments [recurseIntoPath=" + recurseIntoPath + ", verbose=" + verbose + ", pathIn="
113 + pathIn + ", pathOut=" + pathOut + "]";
114 }
115
116 }
117
118 private static final String FILE_EXT_XML = ".xml";
119
120 public static void main(final String[] args) {
121 new Log4j1ConfigurationConverter(BasicCommandLineArguments.parseCommandLine(args,
122 Log4j1ConfigurationConverter.class, new CommandLineArguments())).run();
123 }
124
125 public static Log4j1ConfigurationConverter run(CommandLineArguments cla) {
126 final Log4j1ConfigurationConverter log4j1ConfigurationConverter = new Log4j1ConfigurationConverter(cla);
127 log4j1ConfigurationConverter.run();
128 return log4j1ConfigurationConverter;
129 }
130
131 private final CommandLineArguments cla;
132
133 private Log4j1ConfigurationConverter(final CommandLineArguments cla) {
134 this.cla = cla;
135 }
136
137 protected void convert(final InputStream input, final OutputStream output) throws IOException {
138 final ConfigurationBuilder<BuiltConfiguration> builder = new Log4j1ConfigurationParser()
139 .buildConfigurationBuilder(input);
140 builder.writeXmlConfiguration(output);
141 }
142
143 InputStream getInputStream() throws IOException {
144 final Path pathIn = cla.getPathIn();
145 return pathIn == null ? System.in : new InputStreamWrapper(Files.newInputStream(pathIn), pathIn.toString());
146 }
147
148 OutputStream getOutputStream() throws IOException {
149 final Path pathOut = cla.getPathOut();
150 return pathOut == null ? System.out : Files.newOutputStream(pathOut);
151 }
152
153 private void run() {
154 if (cla.getRecurseIntoPath() != null) {
155 final AtomicInteger countOKs = new AtomicInteger();
156 final AtomicInteger countFails = new AtomicInteger();
157 try {
158 Files.walkFileTree(cla.getRecurseIntoPath(), new SimpleFileVisitor<Path>() {
159 @Override
160 public FileVisitResult visitFile(final Path file, final BasicFileAttributes attrs)
161 throws IOException {
162 if (cla.getPathIn() == null || file.getFileName().equals(cla.getPathIn())) {
163 verbose("Reading %s", file);
164 String newFile = file.getFileName().toString();
165 final int lastIndex = newFile.lastIndexOf(".");
166 newFile = lastIndex < 0 ? newFile + FILE_EXT_XML
167 : newFile.substring(0, lastIndex) + FILE_EXT_XML;
168 final Path resolved = file.resolveSibling(newFile);
169 try (final InputStream input = new InputStreamWrapper(Files.newInputStream(file), file.toString());
170 final OutputStream output = Files.newOutputStream(resolved)) {
171 try {
172 convert(input, output);
173 countOKs.incrementAndGet();
174 } catch (ConfigurationException | IOException e) {
175 countFails.incrementAndGet();
176 if (cla.isFailFast()) {
177 throw e;
178 }
179 e.printStackTrace();
180 }
181 verbose("Wrote %s", resolved);
182 }
183 }
184 return FileVisitResult.CONTINUE;
185 }
186 });
187 } catch (IOException e) {
188 throw new ConfigurationException(e);
189 } finally {
190 verbose("OK = %,d, Failures = %,d, Total = %,d", countOKs.get(), countFails.get(),
191 countOKs.get() + countFails.get());
192 }
193 } else {
194 verbose("Reading %s", cla.getPathIn());
195 try (final InputStream input = getInputStream(); final OutputStream output = getOutputStream()) {
196 convert(input, output);
197 } catch (IOException e) {
198 throw new ConfigurationException(e);
199 }
200 verbose("Wrote %s", cla.getPathOut());
201 }
202 }
203
204 private void verbose(final String template, final Object... args) {
205 if (cla.isVerbose()) {
206 System.err.println(String.format(template, args));
207 }
208 }
209
210 }
1717
1818 import java.io.IOException;
1919 import java.io.InputStream;
20 import java.net.URI;
21 import java.util.Arrays;
22 import java.util.HashMap;
23 import java.util.Map;
24 import java.util.Map.Entry;
25 import java.util.Properties;
2620
27 import org.apache.logging.log4j.Level;
28 import org.apache.logging.log4j.core.appender.ConsoleAppender;
29 import org.apache.logging.log4j.core.appender.ConsoleAppender.Target;
21 import org.apache.logging.log4j.core.LoggerContext;
3022 import org.apache.logging.log4j.core.config.Configuration;
23 import org.apache.logging.log4j.core.config.ConfigurationException;
3124 import org.apache.logging.log4j.core.config.ConfigurationFactory;
3225 import org.apache.logging.log4j.core.config.ConfigurationSource;
33 import org.apache.logging.log4j.core.config.builder.api.AppenderComponentBuilder;
3426 import org.apache.logging.log4j.core.config.builder.api.ConfigurationBuilder;
35 import org.apache.logging.log4j.core.config.builder.api.LayoutComponentBuilder;
3627 import org.apache.logging.log4j.core.config.builder.impl.BuiltConfiguration;
37 import org.apache.logging.log4j.status.StatusLogger;
3828
3929 /**
40 * Experimental ConfigurationFactory for Log4j 1.2 properties files.
41 * <p>
42 * Currently supports:
43 * </p>
44 * <ul>
45 * <li>log4j.debug</li>
46 * <li>log4j.rootLogger</li>
47 * <li>log4j.logger</li>
48 * <li>log4j.appender</li>
49 * <li>org.apache.log4j.ConsoleAppender</li>
50 * <li>org.apache.log4j.PatternLayout</li>
51 * <ul>
52 * <li>Follow</li>
53 * <li>Target</li>
54 * <li>layout = org.apache.log4j.PatternLayout</li>
55 * <li>layout = org.apache.log4j.SimpleLayout</li>
56 * <li>layout = org.apache.log4j.TTCCLayout (partial)</li>
57 * <li>layout = org.apache.log4j.HtmlLayout (partial)</li>
58 * <li>layout = org.apache.log4j.XmlLayout (partial)</li>
59 * <li>layout.ConversionPattern</li>
60 * </ul>
61 * </ul>
30 * Experimental ConfigurationFactory for Log4j 1.2 properties configuration files.
6231 */
6332 // TODO
6433 // @Plugin(name = "Log4j1ConfigurationFactory", category = ConfigurationFactory.CATEGORY)
6736 // @Order(50)
6837 public class Log4j1ConfigurationFactory extends ConfigurationFactory {
6938
70 private Map<String, String> buildClassToPropertyPrefixMap(final Properties properties,
71 final String[] sortedAppenderNames) {
72 final String prefix = "log4j.appender.";
73 final int preLength = prefix.length();
74 final Map<String, String> map = new HashMap<>(sortedAppenderNames.length);
75 for (final Entry<Object, Object> entry : properties.entrySet()) {
76 final Object keyObj = entry.getKey();
77 if (keyObj != null) {
78 final String key = keyObj.toString();
79 if (key.startsWith(prefix)) {
80 if (key.indexOf('.', preLength) < 0) {
81 final String name = key.substring(preLength);
82 if (Arrays.binarySearch(sortedAppenderNames, name) >= 0) {
83 final Object value = entry.getValue();
84 if (value != null) {
85 map.put(name, value.toString());
86 }
87 }
88 }
89 }
90 }
91 }
92 return map;
93 }
94
95 private void buildConsoleAppender(final Properties properties, final String name,
96 final ConfigurationBuilder<BuiltConfiguration> builder) {
97 final AppenderComponentBuilder appenderBuilder = builder.newAppender(name, "CONSOLE");
98 buildConsoleAppenderTarget(properties, name, builder, appenderBuilder);
99 buildAppenderLayout(properties, name, builder, appenderBuilder);
100 buildConsoleAppenderFollow(properties, name, builder, appenderBuilder);
101 builder.add(appenderBuilder);
102 }
103
104 private void buildAppenderLayout(final Properties properties, final String name,
105 final ConfigurationBuilder<BuiltConfiguration> builder, final AppenderComponentBuilder appenderBuilder) {
106 final String layoutValue = getLog4jAppenderValue(properties, name, "layout", null);
107 if (layoutValue != null) {
108 final String cpValue = getLog4jAppenderValue(properties, name, "layout.ConversionPattern", null);
109 switch (layoutValue) {
110 case "org.apache.log4j.PatternLayout": {
111 appenderBuilder.add(newPatternLayout(builder, cpValue));
112 break;
113 }
114 case "org.apache.log4j.EnhancedPatternLayout": {
115 appenderBuilder.add(newPatternLayout(builder, cpValue));
116 break;
117 }
118 case "org.apache.log4j.SimpleLayout": {
119 appenderBuilder.add(newPatternLayout(builder, "%level - %m%n"));
120 break;
121 }
122 case "org.apache.log4j.TTCCLayout": {
123 // TODO We do not have a %d for the time since the start of the app?
124 appenderBuilder.add(newPatternLayout(builder, "%relative [%threadName] %level %logger - %m%n"));
125 break;
126 }
127 case "org.apache.log4j.HTMLLayout": {
128 appenderBuilder.add(builder.newLayout("HtmlLayout"));
129 break;
130 }
131 case "org.apache.log4j.XMLLayout": {
132 appenderBuilder.add(builder.newLayout("XmlLayout"));
133 break;
134 }
135 default:
136 reportWarning("Unsupported value for console appender layout: " + layoutValue);
137 }
138 }
139 }
140
141 private LayoutComponentBuilder newPatternLayout(final ConfigurationBuilder<BuiltConfiguration> builder,
142 final String pattern) {
143 final LayoutComponentBuilder layoutBuilder = builder.newLayout("PatternLayout");
144 if (pattern != null) {
145 layoutBuilder.addAttribute("pattern", pattern);
146 }
147 return layoutBuilder;
148 }
149
150 private void buildConsoleAppenderTarget(final Properties properties, final String name,
151 final ConfigurationBuilder<BuiltConfiguration> builder, final AppenderComponentBuilder appenderBuilder) {
152 final String value = getLog4jAppenderValue(properties, name, "Target", "System.out");
153 if (value != null) {
154 final Target target;
155 switch (value) {
156 case "System.out":
157 target = ConsoleAppender.Target.SYSTEM_OUT;
158 break;
159 case "System.err":
160 target = ConsoleAppender.Target.SYSTEM_ERR;
161 break;
162 default:
163 reportWarning("Unknow value for console Target: " + value);
164 target = null;
165 }
166 if (target != null) {
167 appenderBuilder.addAttribute("target", target);
168 }
169 }
170 }
171
172 private void buildConsoleAppenderFollow(final Properties properties, final String name,
173 final ConfigurationBuilder<BuiltConfiguration> builder, final AppenderComponentBuilder appenderBuilder) {
174 final String value = getLog4jAppenderValue(properties, name, "Follow", "false");
175 if (value != null) {
176 appenderBuilder.addAttribute("follow", Boolean.valueOf(value).booleanValue());
177 }
178 }
179
180 Configuration createConfiguration(final String configName, final URI configLocation,
181 final ConfigurationBuilder<BuiltConfiguration> builder) throws IOException {
182 builder.setConfigurationName(configName);
183 final Properties properties = load(configLocation);
184 if (properties == null) {
185 return null;
186 }
187 // DEBUG
188 final String debugValue = getLog4jValue(properties, "debug");
189 if (Boolean.valueOf(debugValue)) {
190 builder.setStatusLevel(Level.DEBUG);
191 }
192 // Root
193 final String[] sortedAppenderNamesC = buildRootLogger(builder, getRootCategoryValue(properties));
194 final String[] sortedAppenderNamesL = buildRootLogger(builder, getRootLoggerValue(properties));
195 final String[] sortedAppenderNames = sortedAppenderNamesL.length > 0 ? sortedAppenderNamesL
196 : sortedAppenderNamesC;
197 // Appenders
198 final Map<String, String> classNameToProperty = buildClassToPropertyPrefixMap(properties, sortedAppenderNames);
199 for (final Entry<String, String> entry : classNameToProperty.entrySet()) {
200 final String appenderName = entry.getKey();
201 switch (entry.getValue()) {
202 case "org.apache.log4j.ConsoleAppender":
203 buildConsoleAppender(properties, appenderName, builder);
204 break;
205 default:
206 reportWarning("Ignoring appender " + appenderName
207 + "; consider porting your configuration file to the current Log4j format.");
208 }
209 }
210 // Loggers
211 buildLoggers(properties, "log4j.category.", builder);
212 buildLoggers(properties, "log4j.logger.", builder);
213 return builder.build();
214 }
215
216 private String[] buildRootLogger(final ConfigurationBuilder<BuiltConfiguration> builder,
217 final String rootLoggerValue) {
218 if (rootLoggerValue == null) {
219 return new String[0];
220 }
221 final String[] rootLoggerParts = rootLoggerValue.split("\\s*,\\s*");
222 final Level rootLoggerLevel = rootLoggerParts.length > 0 ? Level.valueOf(rootLoggerParts[0]) : Level.ERROR;
223 builder.add(builder.newRootLogger(rootLoggerLevel));
224 final String[] sortedAppenderNames = Arrays.copyOfRange(rootLoggerParts, 1, rootLoggerParts.length);
225 Arrays.sort(sortedAppenderNames);
226 return sortedAppenderNames;
227 }
228
229 private void buildLoggers(final Properties properties, final String prefix,
230 final ConfigurationBuilder<BuiltConfiguration> builder) {
231 final int preLength = prefix.length();
232 for (final Entry<Object, Object> entry : properties.entrySet()) {
233 final Object keyObj = entry.getKey();
234 if (keyObj != null) {
235 final String key = keyObj.toString();
236 if (key.startsWith(prefix)) {
237 final String name = key.substring(preLength);
238 final Object value = entry.getValue();
239 if (value != null) {
240 builder.add(builder.newLogger(name, Level.valueOf(value.toString())));
241 }
242 }
243 }
244 }
245
246 }
39 private static final String[] SUFFIXES = {".properties"};
24740
24841 @Override
249 public Configuration getConfiguration(final ConfigurationSource source) {
250 return getConfiguration(source.toString(), null);
251 }
252
253 @Override
254 public Configuration getConfiguration(final String name, final URI configLocation) {
255 try {
256 return createConfiguration(name, configLocation, newConfigurationBuilder());
42 public Configuration getConfiguration(final LoggerContext loggerContext, final ConfigurationSource source) {
43 final ConfigurationBuilder<BuiltConfiguration> builder;
44 try (final InputStream configStream = source.getInputStream()) {
45 builder = new Log4j1ConfigurationParser().buildConfigurationBuilder(configStream);
25746 } catch (final IOException e) {
258 StatusLogger.getLogger().error(e);
259 return null;
47 throw new ConfigurationException("Unable to load " + source, e);
26048 }
261 }
262
263 private String getLog4jAppenderValue(final Properties properties, final String appenderName,
264 final String attributeName, final String defaultValue) {
265 return properties.getProperty("log4j.appender." + appenderName + "." + attributeName, defaultValue);
266 }
267
268 private String getLog4jValue(final Properties properties, final String key) {
269 return properties.getProperty("log4j." + key);
270 }
271
272 private String getRootCategoryValue(final Properties properties) {
273 return getLog4jValue(properties, "rootCategory");
274 }
275
276 private String getRootLoggerValue(final Properties properties) {
277 return getLog4jValue(properties, "rootLogger");
49 return builder.build();
27850 }
27951
28052 @Override
28153 protected String[] getSupportedTypes() {
282 return new String[] { "*.properties", ".xml" };
54 return SUFFIXES;
28355 }
28456
285 private Properties load(final URI uri) throws IOException {
286 final Properties properties = toProperties(uri);
287 final String rootCategoryValue = getRootCategoryValue(properties);
288 final String rootLoggerValue = getRootLoggerValue(properties);
289 if (rootCategoryValue == null && rootLoggerValue == null) {
290 // This is not a Log4j 1 properties file.
291 return null;
292 }
293 return properties;
294 }
295
296 private void reportWarning(final String msg) {
297 StatusLogger.getLogger().warn("Log4j version 1 to 2 configuration bridge: " + msg);
298
299 }
300
301 private Properties toProperties(final URI uri) throws IOException {
302 final Properties properties;
303 try (InputStream in = uri.toURL().openStream()) {
304 properties = new Properties();
305 if (uri.toString().endsWith(".xml")) {
306 properties.loadFromXML(in);
307 } else {
308 properties.load(in);
309 }
310 }
311 return properties;
312 }
31357 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.log4j.config;
17
18 import java.io.IOException;
19 import java.io.InputStream;
20 import java.util.Arrays;
21 import java.util.HashMap;
22 import java.util.Map;
23 import java.util.Objects;
24 import java.util.Properties;
25 import java.util.TreeMap;
26
27 import org.apache.logging.log4j.Level;
28 import org.apache.logging.log4j.core.appender.ConsoleAppender;
29 import org.apache.logging.log4j.core.appender.FileAppender;
30 import org.apache.logging.log4j.core.appender.NullAppender;
31 import org.apache.logging.log4j.core.appender.RollingFileAppender;
32 import org.apache.logging.log4j.core.config.ConfigurationException;
33 import org.apache.logging.log4j.core.config.builder.api.AppenderComponentBuilder;
34 import org.apache.logging.log4j.core.config.builder.api.ComponentBuilder;
35 import org.apache.logging.log4j.core.config.builder.api.ConfigurationBuilder;
36 import org.apache.logging.log4j.core.config.builder.api.ConfigurationBuilderFactory;
37 import org.apache.logging.log4j.core.config.builder.api.LayoutComponentBuilder;
38 import org.apache.logging.log4j.core.config.builder.api.LoggerComponentBuilder;
39 import org.apache.logging.log4j.core.config.builder.api.RootLoggerComponentBuilder;
40 import org.apache.logging.log4j.core.config.builder.impl.BuiltConfiguration;
41 import org.apache.logging.log4j.core.lookup.StrSubstitutor;
42 import org.apache.logging.log4j.status.StatusLogger;
43 import org.apache.logging.log4j.util.Strings;
44
45 /**
46 * Experimental parser for Log4j 1.2 properties configuration files.
47 *
48 * This class is not thread-safe.
49 *
50 * <p>
51 * From the Log4j 1.2 Javadocs:
52 * </p>
53 * <p>
54 * All option values admit variable substitution. The syntax of variable substitution is similar to that of Unix shells. The string between
55 * an opening "${" and closing "}" is interpreted as a key. The value of the substituted variable can be defined as a system property or in
56 * the configuration file itself. The value of the key is first searched in the system properties, and if not found there, it is then
57 * searched in the configuration file being parsed. The corresponding value replaces the ${variableName} sequence. For example, if java.home
58 * system property is set to /home/xyz, then every occurrence of the sequence ${java.home} will be interpreted as /home/xyz.
59 * </p>
60 */
61 public class Log4j1ConfigurationParser {
62
63 private static final String COMMA_DELIMITED_RE = "\\s*,\\s*";
64 private static final String ROOTLOGGER = "rootLogger";
65 private static final String ROOTCATEGORY = "rootCategory";
66 private static final String TRUE = "true";
67 private static final String FALSE = "false";
68
69 private final Properties properties = new Properties();
70 private StrSubstitutor strSubstitutorProperties;
71 private StrSubstitutor strSubstitutorSystem;
72
73 private final ConfigurationBuilder<BuiltConfiguration> builder = ConfigurationBuilderFactory
74 .newConfigurationBuilder();
75
76 /**
77 * Parses a Log4j 1.2 properties configuration file in ISO 8859-1 encoding into a ConfigurationBuilder.
78 *
79 * @param input
80 * InputStream to read from is assumed to be ISO 8859-1, and will not be closed.
81 * @return the populated ConfigurationBuilder, never {@literal null}
82 * @throws IOException
83 * if unable to read the input
84 * @throws ConfigurationException
85 * if the input does not contain a valid configuration
86 */
87 public ConfigurationBuilder<BuiltConfiguration> buildConfigurationBuilder(final InputStream input)
88 throws IOException {
89 try {
90 properties.load(input);
91 strSubstitutorProperties = new StrSubstitutor(properties);
92 strSubstitutorSystem = new StrSubstitutor(System.getProperties());
93 final String rootCategoryValue = getLog4jValue(ROOTCATEGORY);
94 final String rootLoggerValue = getLog4jValue(ROOTLOGGER);
95 if (rootCategoryValue == null && rootLoggerValue == null) {
96 // This is not a Log4j 1 properties configuration file.
97 warn("Missing " + ROOTCATEGORY + " or " + ROOTLOGGER + " in " + input);
98 // throw new ConfigurationException(
99 // "Missing " + ROOTCATEGORY + " or " + ROOTLOGGER + " in " + input);
100 }
101 builder.setConfigurationName("Log4j1");
102 // DEBUG
103 final String debugValue = getLog4jValue("debug");
104 if (Boolean.valueOf(debugValue)) {
105 builder.setStatusLevel(Level.DEBUG);
106 }
107 // Root
108 buildRootLogger(getLog4jValue(ROOTCATEGORY));
109 buildRootLogger(getLog4jValue(ROOTLOGGER));
110 // Appenders
111 final Map<String, String> appenderNameToClassName = buildClassToPropertyPrefixMap();
112 for (final Map.Entry<String, String> entry : appenderNameToClassName.entrySet()) {
113 final String appenderName = entry.getKey();
114 final String appenderClass = entry.getValue();
115 buildAppender(appenderName, appenderClass);
116 }
117 // Loggers
118 buildLoggers("log4j.category.");
119 buildLoggers("log4j.logger.");
120 buildProperties();
121 return builder;
122 } catch (final IllegalArgumentException e) {
123 throw new ConfigurationException(e);
124 }
125 }
126
127 private void buildProperties() {
128 for (Map.Entry<Object, Object> entry : new TreeMap<>(properties).entrySet()) {
129 final String key = entry.getKey().toString();
130 if (!key.startsWith("log4j.") && !key.equals(ROOTCATEGORY) && !key.equals(ROOTLOGGER)) {
131 builder.addProperty(key, Objects.toString(entry.getValue(), Strings.EMPTY));
132 }
133 }
134 }
135
136 private void warn(String string) {
137 System.err.println(string);
138 }
139
140 private Map<String, String> buildClassToPropertyPrefixMap() {
141 final String prefix = "log4j.appender.";
142 final int preLength = prefix.length();
143 final Map<String, String> map = new HashMap<>();
144 for (final Map.Entry<Object, Object> entry : properties.entrySet()) {
145 final Object keyObj = entry.getKey();
146 if (keyObj != null) {
147 final String key = keyObj.toString();
148 if (key.startsWith(prefix)) {
149 if (key.indexOf('.', preLength) < 0) {
150 final String name = key.substring(preLength);
151 final Object value = entry.getValue();
152 if (value != null) {
153 map.put(name, value.toString());
154 }
155 }
156 }
157 }
158 }
159 return map;
160 }
161
162 private void buildAppender(final String appenderName, final String appenderClass) {
163 switch (appenderClass) {
164 case "org.apache.log4j.ConsoleAppender":
165 buildConsoleAppender(appenderName);
166 break;
167 case "org.apache.log4j.FileAppender":
168 buildFileAppender(appenderName);
169 break;
170 case "org.apache.log4j.DailyRollingFileAppender":
171 buildDailyRollingFileAppender(appenderName);
172 break;
173 case "org.apache.log4j.RollingFileAppender":
174 buildRollingFileAppender(appenderName);
175 break;
176 case "org.apache.log4j.varia.NullAppender":
177 buildNullAppender(appenderName);
178 break;
179 default:
180 reportWarning("Unknown appender class: " + appenderClass + "; ignoring appender: " + appenderName);
181 }
182 }
183
184 private void buildConsoleAppender(final String appenderName) {
185 final AppenderComponentBuilder appenderBuilder = builder.newAppender(appenderName, ConsoleAppender.PLUGIN_NAME);
186 final String targetValue = getLog4jAppenderValue(appenderName, "Target", "System.out");
187 if (targetValue != null) {
188 final ConsoleAppender.Target target;
189 switch (targetValue) {
190 case "System.out":
191 target = ConsoleAppender.Target.SYSTEM_OUT;
192 break;
193 case "System.err":
194 target = ConsoleAppender.Target.SYSTEM_ERR;
195 break;
196 default:
197 reportWarning("Unknown value for console Target: " + targetValue);
198 target = null;
199 }
200 if (target != null) {
201 appenderBuilder.addAttribute("target", target);
202 }
203 }
204 buildAttribute(appenderName, appenderBuilder, "Follow", "follow");
205 if (FALSE.equalsIgnoreCase(getLog4jAppenderValue(appenderName, "ImmediateFlush"))) {
206 reportWarning("ImmediateFlush=false is not supported on Console appender");
207 }
208 buildAppenderLayout(appenderName, appenderBuilder);
209 builder.add(appenderBuilder);
210 }
211
212 private void buildFileAppender(final String appenderName) {
213 final AppenderComponentBuilder appenderBuilder = builder.newAppender(appenderName, FileAppender.PLUGIN_NAME);
214 buildFileAppender(appenderName, appenderBuilder);
215 builder.add(appenderBuilder);
216 }
217
218 private void buildFileAppender(final String appenderName, final AppenderComponentBuilder appenderBuilder) {
219 buildMandatoryAttribute(appenderName, appenderBuilder, "File", "fileName");
220 buildAttribute(appenderName, appenderBuilder, "Append", "append");
221 buildAttribute(appenderName, appenderBuilder, "BufferedIO", "bufferedIo");
222 buildAttribute(appenderName, appenderBuilder, "BufferSize", "bufferSize");
223 buildAttribute(appenderName, appenderBuilder, "ImmediateFlush", "immediateFlush");
224 buildAppenderLayout(appenderName, appenderBuilder);
225 }
226
227 private void buildDailyRollingFileAppender(final String appenderName) {
228 final AppenderComponentBuilder appenderBuilder = builder.newAppender(appenderName,
229 RollingFileAppender.PLUGIN_NAME);
230 buildFileAppender(appenderName, appenderBuilder);
231 final String fileName = getLog4jAppenderValue(appenderName, "File");
232 final String datePattern = getLog4jAppenderValue(appenderName, "DatePattern", fileName + "'.'yyyy-MM-dd");
233 appenderBuilder.addAttribute("filePattern", fileName + "%d{" + datePattern + "}");
234 final ComponentBuilder<?> triggeringPolicy = builder.newComponent("Policies")
235 .addComponent(builder.newComponent("TimeBasedTriggeringPolicy").addAttribute("modulate", true));
236 appenderBuilder.addComponent(triggeringPolicy);
237 appenderBuilder
238 .addComponent(builder.newComponent("DefaultRolloverStrategy").addAttribute("max", Integer.MAX_VALUE));
239 builder.add(appenderBuilder);
240 }
241
242 private void buildRollingFileAppender(final String appenderName) {
243 final AppenderComponentBuilder appenderBuilder = builder.newAppender(appenderName,
244 RollingFileAppender.PLUGIN_NAME);
245 buildFileAppender(appenderName, appenderBuilder);
246 final String fileName = getLog4jAppenderValue(appenderName, "File");
247 appenderBuilder.addAttribute("filePattern", fileName + ".%i");
248 final String maxFileSizeString = getLog4jAppenderValue(appenderName, "MaxFileSize", "10485760");
249 final String maxBackupIndexString = getLog4jAppenderValue(appenderName, "MaxBackupIndex", "1");
250 final ComponentBuilder<?> triggeringPolicy = builder.newComponent("Policies").addComponent(
251 builder.newComponent("SizeBasedTriggeringPolicy").addAttribute("size", maxFileSizeString));
252 appenderBuilder.addComponent(triggeringPolicy);
253 appenderBuilder.addComponent(
254 builder.newComponent("DefaultRolloverStrategy").addAttribute("max", maxBackupIndexString));
255 builder.add(appenderBuilder);
256 }
257
258 private void buildAttribute(final String componentName, final ComponentBuilder componentBuilder,
259 final String sourceAttributeName, final String targetAttributeName) {
260 final String attributeValue = getLog4jAppenderValue(componentName, sourceAttributeName);
261 if (attributeValue != null) {
262 componentBuilder.addAttribute(targetAttributeName, attributeValue);
263 }
264 }
265
266 private void buildAttributeWithDefault(final String componentName, final ComponentBuilder componentBuilder,
267 final String sourceAttributeName, final String targetAttributeName, final String defaultValue) {
268 final String attributeValue = getLog4jAppenderValue(componentName, sourceAttributeName, defaultValue);
269 componentBuilder.addAttribute(targetAttributeName, attributeValue);
270 }
271
272 private void buildMandatoryAttribute(final String componentName, final ComponentBuilder componentBuilder,
273 final String sourceAttributeName, final String targetAttributeName) {
274 final String attributeValue = getLog4jAppenderValue(componentName, sourceAttributeName);
275 if (attributeValue != null) {
276 componentBuilder.addAttribute(targetAttributeName, attributeValue);
277 } else {
278 reportWarning("Missing " + sourceAttributeName + " for " + componentName);
279 }
280 }
281
282 private void buildNullAppender(String appenderName) {
283 final AppenderComponentBuilder appenderBuilder = builder.newAppender(appenderName, NullAppender.PLUGIN_NAME);
284 builder.add(appenderBuilder);
285 }
286
287 private void buildAppenderLayout(final String name, final AppenderComponentBuilder appenderBuilder) {
288 final String layoutClass = getLog4jAppenderValue(name, "layout", null);
289 if (layoutClass != null) {
290 switch (layoutClass) {
291 case "org.apache.log4j.PatternLayout":
292 case "org.apache.log4j.EnhancedPatternLayout": {
293 final String pattern = getLog4jAppenderValue(name, "layout.ConversionPattern", null)
294
295 // Log4j 2's %x (NDC) is not compatible with Log4j 1's
296 // %x
297 // Log4j 1: "foo bar baz"
298 // Log4j 2: "[foo, bar, baz]"
299 // Use %ndc to get the Log4j 1 format
300 .replace("%x", "%ndc")
301
302 // Log4j 2's %X (MDC) is not compatible with Log4j 1's
303 // %X
304 // Log4j 1: "{{foo,bar}{hoo,boo}}"
305 // Log4j 2: "{foo=bar,hoo=boo}"
306 // Use %properties to get the Log4j 1 format
307 .replace("%X", "%properties");
308
309 appenderBuilder.add(newPatternLayout(pattern));
310 break;
311 }
312 case "org.apache.log4j.SimpleLayout": {
313 appenderBuilder.add(newPatternLayout("%level - %m%n"));
314 break;
315 }
316 case "org.apache.log4j.TTCCLayout": {
317 String pattern = "%r ";
318 if (Boolean.parseBoolean(getLog4jAppenderValue(name, "layout.ThreadPrinting", TRUE))) {
319 pattern += "[%t] ";
320 }
321 pattern += "%p ";
322 if (Boolean.parseBoolean(getLog4jAppenderValue(name, "layout.CategoryPrefixing", TRUE))) {
323 pattern += "%c ";
324 }
325 if (Boolean.parseBoolean(getLog4jAppenderValue(name, "layout.ContextPrinting", TRUE))) {
326 pattern += "%notEmpty{%ndc }";
327 }
328 pattern += "- %m%n";
329 appenderBuilder.add(newPatternLayout(pattern));
330 break;
331 }
332 case "org.apache.log4j.HTMLLayout": {
333 final LayoutComponentBuilder htmlLayout = builder.newLayout("HtmlLayout");
334 htmlLayout.addAttribute("title", getLog4jAppenderValue(name, "layout.Title", "Log4J Log Messages"));
335 htmlLayout.addAttribute("locationInfo",
336 Boolean.parseBoolean(getLog4jAppenderValue(name, "layout.LocationInfo", FALSE)));
337 appenderBuilder.add(htmlLayout);
338 break;
339 }
340 case "org.apache.log4j.xml.XMLLayout": {
341 final LayoutComponentBuilder xmlLayout = builder.newLayout("Log4j1XmlLayout");
342 xmlLayout.addAttribute("locationInfo",
343 Boolean.parseBoolean(getLog4jAppenderValue(name, "layout.LocationInfo", FALSE)));
344 xmlLayout.addAttribute("properties",
345 Boolean.parseBoolean(getLog4jAppenderValue(name, "layout.Properties", FALSE)));
346 appenderBuilder.add(xmlLayout);
347 break;
348 }
349 default:
350 reportWarning("Unknown layout class: " + layoutClass);
351 }
352 }
353 }
354
355 private LayoutComponentBuilder newPatternLayout(final String pattern) {
356 final LayoutComponentBuilder layoutBuilder = builder.newLayout("PatternLayout");
357 if (pattern != null) {
358 layoutBuilder.addAttribute("pattern", pattern);
359 }
360 return layoutBuilder;
361 }
362
363 private void buildRootLogger(final String rootLoggerValue) {
364 if (rootLoggerValue == null) {
365 return;
366 }
367 final String[] rootLoggerParts = rootLoggerValue.split(COMMA_DELIMITED_RE);
368 final String rootLoggerLevel = getLevelString(rootLoggerParts, Level.ERROR.name());
369 final RootLoggerComponentBuilder loggerBuilder = builder.newRootLogger(rootLoggerLevel);
370 //
371 final String[] sortedAppenderNames = Arrays.copyOfRange(rootLoggerParts, 1, rootLoggerParts.length);
372 Arrays.sort(sortedAppenderNames);
373 for (final String appender : sortedAppenderNames) {
374 loggerBuilder.add(builder.newAppenderRef(appender));
375 }
376 builder.add(loggerBuilder);
377 }
378
379 private String getLevelString(final String[] loggerParts, final String defaultLevel) {
380 return loggerParts.length > 0 ? loggerParts[0] : defaultLevel;
381 }
382
383 private void buildLoggers(final String prefix) {
384 final int preLength = prefix.length();
385 for (final Map.Entry<Object, Object> entry : properties.entrySet()) {
386 final Object keyObj = entry.getKey();
387 if (keyObj != null) {
388 final String key = keyObj.toString();
389 if (key.startsWith(prefix)) {
390 final String name = key.substring(preLength);
391 final Object value = entry.getValue();
392 if (value != null) {
393 // a Level may be followed by a list of Appender refs.
394 final String valueStr = value.toString();
395 final String[] split = valueStr.split(COMMA_DELIMITED_RE);
396 final String level = getLevelString(split, null);
397 if (level == null) {
398 warn("Level is missing for entry " + entry);
399 } else {
400 final LoggerComponentBuilder newLogger = builder.newLogger(name, level);
401 if (split.length > 1) {
402 // Add Appenders to this logger
403 final String[] sortedAppenderNames = Arrays.copyOfRange(split, 1, split.length);
404 Arrays.sort(sortedAppenderNames);
405 for (String appenderName : sortedAppenderNames) {
406 newLogger.add(builder.newAppenderRef(appenderName));
407 }
408 }
409 builder.add(newLogger);
410 }
411 }
412 }
413 }
414 }
415 }
416
417 private String getLog4jAppenderValue(final String appenderName, final String attributeName) {
418 return getProperty("log4j.appender." + appenderName + "." + attributeName);
419 }
420
421 private String getProperty(final String key) {
422 final String value = properties.getProperty(key);
423 final String sysValue = strSubstitutorSystem.replace(value);
424 return strSubstitutorProperties.replace(sysValue);
425 }
426
427 private String getProperty(final String key, String defaultValue) {
428 final String value = getProperty(key);
429 return value == null ? defaultValue : value;
430 }
431
432 private String getLog4jAppenderValue(final String appenderName, final String attributeName,
433 final String defaultValue) {
434 return getProperty("log4j.appender." + appenderName + "." + attributeName, defaultValue);
435 }
436
437 private String getLog4jValue(final String key) {
438 return getProperty("log4j." + key);
439 }
440
441 private void reportWarning(final String msg) {
442 StatusLogger.getLogger().warn("Log4j 1 configuration parser: " + msg);
443 }
444
445 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.log4j.layout;
17
18 import org.apache.logging.log4j.core.Layout;
19 import org.apache.logging.log4j.core.LogEvent;
20 import org.apache.logging.log4j.core.config.Node;
21 import org.apache.logging.log4j.core.config.plugins.Plugin;
22 import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
23 import org.apache.logging.log4j.core.config.plugins.PluginFactory;
24 import org.apache.logging.log4j.core.layout.AbstractStringLayout;
25 import org.apache.logging.log4j.core.layout.ByteBufferDestination;
26 import org.apache.logging.log4j.core.util.Transform;
27 import org.apache.logging.log4j.util.Strings;
28
29 import java.nio.charset.StandardCharsets;
30 import java.util.Arrays;
31 import java.util.List;
32 import java.util.Map;
33
34 /**
35 * Port of XMLLayout in Log4j 1.x. Provided for compatibility with existing Log4j 1 configurations.
36 *
37 * Originally developed by Ceki G&uuml;lc&uuml;, Mathias Bogaert.
38 */
39 @Plugin(name = "Log4j1XmlLayout", category = Node.CATEGORY, elementType = Layout.ELEMENT_TYPE, printObject = true)
40 public final class Log4j1XmlLayout extends AbstractStringLayout {
41
42 private final boolean locationInfo;
43 private final boolean properties;
44
45 @PluginFactory
46 public static Log4j1XmlLayout createLayout(
47 // @formatter:off
48 @PluginAttribute(value = "locationInfo", defaultBoolean = false) final boolean locationInfo,
49 @PluginAttribute(value = "properties", defaultBoolean = false) final boolean properties
50 // @formatter:on
51 ) {
52 return new Log4j1XmlLayout(locationInfo, properties);
53 }
54
55 private Log4j1XmlLayout(final boolean locationInfo, final boolean properties) {
56 super(StandardCharsets.UTF_8);
57 this.locationInfo = locationInfo;
58 this.properties = properties;
59 }
60
61 public boolean isLocationInfo() {
62 return locationInfo;
63 }
64
65 public boolean isProperties() {
66 return properties;
67 }
68
69 @Override
70 public void encode(final LogEvent event, final ByteBufferDestination destination) {
71 final StringBuilder text = getStringBuilder();
72 formatTo(event, text);
73 getStringBuilderEncoder().encode(text, destination);
74 }
75
76 @Override
77 public String toSerializable(final LogEvent event) {
78 final StringBuilder text = getStringBuilder();
79 formatTo(event, text);
80 return text.toString();
81 }
82
83 private void formatTo(final LogEvent event, final StringBuilder buf) {
84 // We yield to the \r\n heresy.
85
86 buf.append("<log4j:event logger=\"");
87 buf.append(Transform.escapeHtmlTags(event.getLoggerName()));
88 buf.append("\" timestamp=\"");
89 buf.append(event.getTimeMillis());
90 buf.append("\" level=\"");
91 buf.append(Transform.escapeHtmlTags(String.valueOf(event.getLevel())));
92 buf.append("\" thread=\"");
93 buf.append(Transform.escapeHtmlTags(event.getThreadName()));
94 buf.append("\">\r\n");
95
96 buf.append("<log4j:message><![CDATA[");
97 // Append the rendered message. Also make sure to escape any existing CDATA sections.
98 Transform.appendEscapingCData(buf, event.getMessage().getFormattedMessage());
99 buf.append("]]></log4j:message>\r\n");
100
101 final List<String> ndc = event.getContextStack().asList();
102 if (!ndc.isEmpty()) {
103 buf.append("<log4j:NDC><![CDATA[");
104 Transform.appendEscapingCData(buf, Strings.join(ndc, ' '));
105 buf.append("]]></log4j:NDC>\r\n");
106 }
107
108 @SuppressWarnings("ThrowableResultOfMethodCallIgnored")
109 final
110 Throwable thrown = event.getThrown();
111 if (thrown != null) {
112 buf.append("<log4j:throwable><![CDATA[");
113 buf.append(thrown.toString());
114 buf.append("\r\n");
115 for (final StackTraceElement element : thrown.getStackTrace()) {
116 Transform.appendEscapingCData(buf, "\tat " + element.toString());
117 buf.append("\r\n");
118 }
119 buf.append("]]></log4j:throwable>\r\n");
120 }
121
122 if (locationInfo) {
123 final StackTraceElement source = event.getSource();
124 if (source != null) {
125 buf.append("<log4j:locationInfo class=\"");
126 buf.append(Transform.escapeHtmlTags(source.getClassName()));
127 buf.append("\" method=\"");
128 buf.append(Transform.escapeHtmlTags(source.getMethodName()));
129 buf.append("\" file=\"");
130 buf.append(Transform.escapeHtmlTags(source.getFileName()));
131 buf.append("\" line=\"");
132 buf.append(source.getLineNumber());
133 buf.append("\"/>\r\n");
134 }
135 }
136
137 if (properties) {
138 final Map<String, String> contextMap = event.getContextMap();
139 if (!contextMap.isEmpty()) {
140 buf.append("<log4j:properties>\r\n");
141 final Object[] keys = contextMap.keySet().toArray();
142 Arrays.sort(keys);
143 for (final Object key1 : keys) {
144 final String key = key1.toString();
145 final String val = contextMap.get(key);
146 if (val != null) {
147 buf.append("<log4j:data name=\"");
148 buf.append(Transform.escapeHtmlTags(key));
149 buf.append("\" value=\"");
150 buf.append(Transform.escapeHtmlTags(val));
151 buf.append("\"/>\r\n");
152 }
153 }
154 buf.append("</log4j:properties>\r\n");
155 }
156 }
157
158 buf.append("</log4j:event>\r\n\r\n");
159 }
160
161 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.log4j.pattern;
17
18 import org.apache.logging.log4j.core.LogEvent;
19 import org.apache.logging.log4j.core.config.plugins.Plugin;
20 import org.apache.logging.log4j.core.pattern.ConverterKeys;
21 import org.apache.logging.log4j.core.pattern.LogEventPatternConverter;
22 import org.apache.logging.log4j.core.pattern.PatternConverter;
23 import org.apache.logging.log4j.util.TriConsumer;
24
25 /**
26 * Able to handle the contents of the LogEvent's MDC and either
27 * output the entire contents of the properties, or to output the value of a specific key
28 * within the property bundle when this pattern converter has the option set.
29 */
30 @Plugin(name = "Log4j1MdcPatternConverter", category = PatternConverter.CATEGORY)
31 @ConverterKeys({ "properties" })
32 public final class Log4j1MdcPatternConverter extends LogEventPatternConverter {
33 /**
34 * Name of property to output.
35 */
36 private final String key;
37
38 /**
39 * Private constructor.
40 *
41 * @param options options, may be null.
42 */
43 private Log4j1MdcPatternConverter(final String[] options) {
44 super(options != null && options.length > 0 ? "Log4j1MDC{" + options[0] + '}' : "Log4j1MDC", "property");
45 if (options != null && options.length > 0) {
46 key = options[0];
47 } else {
48 key = null;
49 }
50 }
51
52 /**
53 * Obtains an instance of PropertiesPatternConverter.
54 *
55 * @param options options, may be null or first element contains name of property to format.
56 * @return instance of PropertiesPatternConverter.
57 */
58 public static Log4j1MdcPatternConverter newInstance(final String[] options) {
59 return new Log4j1MdcPatternConverter(options);
60 }
61
62 /**
63 * {@inheritDoc}
64 */
65 @Override
66 public void format(final LogEvent event, final StringBuilder toAppendTo) {
67 if (key == null) {
68 // if there is no additional options, we output every single Key/Value pair for the MDC
69 toAppendTo.append('{');
70 event.getContextData().forEach(APPEND_EACH, toAppendTo);
71 toAppendTo.append('}');
72 } else {
73 // otherwise they just want a single key output
74 final Object val = event.getContextData().getValue(key);
75 if (val != null) {
76 toAppendTo.append(val);
77 }
78 }
79 }
80
81 private static TriConsumer<String, Object, StringBuilder> APPEND_EACH = new TriConsumer<String, Object, StringBuilder>() {
82 @Override
83 public void accept(final String key, final Object value, final StringBuilder toAppendTo) {
84 toAppendTo.append('{').append(key).append(',').append(value).append('}');
85 }
86 };
87 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.log4j.pattern;
17
18 import org.apache.logging.log4j.core.LogEvent;
19 import org.apache.logging.log4j.core.config.plugins.Plugin;
20 import org.apache.logging.log4j.core.pattern.ConverterKeys;
21 import org.apache.logging.log4j.core.pattern.LogEventPatternConverter;
22 import org.apache.logging.log4j.core.pattern.PatternConverter;
23 import org.apache.logging.log4j.util.Strings;
24
25 import java.util.List;
26
27
28 /**
29 * Returns the event's NDC in a StringBuilder.
30 */
31 @Plugin(name = "Log4j1NdcPatternConverter", category = PatternConverter.CATEGORY)
32 @ConverterKeys({ "ndc" })
33 public final class Log4j1NdcPatternConverter extends LogEventPatternConverter {
34 /**
35 * Singleton.
36 */
37 private static final Log4j1NdcPatternConverter INSTANCE =
38 new Log4j1NdcPatternConverter();
39
40 /**
41 * Private constructor.
42 */
43 private Log4j1NdcPatternConverter() {
44 super("Log4j1NDC", "ndc");
45 }
46
47 /**
48 * Obtains an instance of NdcPatternConverter.
49 *
50 * @param options options, may be null.
51 * @return instance of NdcPatternConverter.
52 */
53 public static Log4j1NdcPatternConverter newInstance(final String[] options) {
54 return INSTANCE;
55 }
56
57 @Override
58 public void format(final LogEvent event, final StringBuilder toAppendTo) {
59 final List<String> ndc = event.getContextStack().asList();
60 toAppendTo.append(Strings.join(ndc, ' '));
61 }
62 }
1818 import java.net.URI;
1919
2020 import org.apache.logging.log4j.Level;
21 import org.apache.logging.log4j.core.LoggerContext;
2122 import org.apache.logging.log4j.core.config.AbstractConfiguration;
2223 import org.apache.logging.log4j.core.config.Configuration;
2324 import org.apache.logging.log4j.core.config.ConfigurationFactory;
3536 }
3637
3738 @Override
38 public Configuration getConfiguration(final ConfigurationSource source) {
39 return new BasicConfiguration();
39 public Configuration getConfiguration(final LoggerContext loggerContext, final ConfigurationSource source) {
40 return new BasicConfiguration(loggerContext);
4041 }
4142
4243 @Override
43 public Configuration getConfiguration(final String name, final URI configLocation) {
44 return new BasicConfiguration();
44 public Configuration getConfiguration(final LoggerContext loggerContext, final String name, final URI configLocation) {
45 return new BasicConfiguration(loggerContext);
4546 }
4647
4748 public class BasicConfiguration extends AbstractConfiguration {
5051
5152 private static final String DEFAULT_LEVEL = "org.apache.logging.log4j.level";
5253
53 public BasicConfiguration() {
54 super(ConfigurationSource.NULL_SOURCE);
54 public BasicConfiguration(final LoggerContext loggerContext) {
55 super(loggerContext, ConfigurationSource.NULL_SOURCE);
5556
5657 final LoggerConfig root = getRootLogger();
5758 setName("BasicConfiguration");
2828 import org.apache.logging.log4j.core.LoggerContext;
2929 import org.apache.logging.log4j.core.config.ConfigurationFactory;
3030 import org.apache.logging.log4j.core.layout.PatternLayout;
31 import org.apache.logging.log4j.core.util.Constants;
3231 import org.apache.logging.log4j.message.Message;
3332 import org.apache.logging.log4j.message.ObjectMessage;
3433 import org.apache.logging.log4j.test.appender.ListAppender;
179178 final String msg = msgs.get(0);
180179 appender.clear();
181180 final String threadName = Thread.currentThread().getName();
182 final String expected = "ERROR o.a.l.CategoryTest [" + threadName + "] Test Message" + Constants.LINE_SEPARATOR;
181 final String expected = "ERROR o.a.l.CategoryTest [" + threadName + "] Test Message" + Strings.LINE_SEPARATOR;
183182 assertTrue("Incorrect message " + Strings.dquote(msg) + " expected " + Strings.dquote(expected), msg.endsWith(expected));
184183 }
185184
0 package org.apache.log4j.config;
1
2 import java.io.IOException;
3 import java.nio.file.FileVisitResult;
4 import java.nio.file.Files;
5 import java.nio.file.Path;
6 import java.nio.file.Paths;
7 import java.nio.file.SimpleFileVisitor;
8 import java.nio.file.attribute.BasicFileAttributes;
9 import java.util.ArrayList;
10 import java.util.List;
11
12 import org.junit.After;
13 import org.junit.Test;
14 import org.junit.runner.RunWith;
15 import org.junit.runners.Parameterized;
16
17 /*
18 * Licensed to the Apache Software Foundation (ASF) under one or more
19 * contributor license agreements. See the NOTICE file distributed with
20 * this work for additional information regarding copyright ownership.
21 * The ASF licenses this file to You under the Apache license, Version 2.0
22 * (the "License"); you may not use this file except in compliance with
23 * the License. You may obtain a copy of the License at
24 *
25 * http://www.apache.org/licenses/LICENSE-2.0
26 *
27 * Unless required by applicable law or agreed to in writing, software
28 * distributed under the License is distributed on an "AS IS" BASIS,
29 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
30 * See the license for the specific language governing permissions and
31 * limitations under the license.
32 */
33
34 @RunWith(Parameterized.class)
35 public abstract class AbstractLog4j1ConfigurationConverterTest {
36
37 protected static List<Path> getPaths(final String root) throws IOException {
38 final List<Path> paths = new ArrayList<>();
39 Files.walkFileTree(Paths.get(root), new SimpleFileVisitor<Path>() {
40 @Override
41 public FileVisitResult visitFile(final Path file, final BasicFileAttributes attrs) throws IOException {
42 paths.add(file.toAbsolutePath());
43 return FileVisitResult.CONTINUE;
44 }
45 });
46 return paths;
47 }
48
49 private final Path pathIn;
50
51 public AbstractLog4j1ConfigurationConverterTest(final Path path) {
52 super();
53 this.pathIn = path;
54 }
55
56 @Test
57 public void test() throws IOException {
58 final Path tempFile = Files.createTempFile("log4j2", ".xml");
59 try {
60 final Log4j1ConfigurationConverter.CommandLineArguments cla = new Log4j1ConfigurationConverter.CommandLineArguments();
61 cla.setPathIn(pathIn);
62 cla.setPathOut(tempFile);
63 Log4j1ConfigurationConverter.run(cla);
64 } finally {
65 Files.deleteIfExists(tempFile);
66 }
67 }
68 }
0 package org.apache.log4j.config;
1
2 import java.io.IOException;
3 import java.nio.file.Path;
4 import java.util.List;
5
6 import org.junit.runner.RunWith;
7 import org.junit.runners.Parameterized;
8
9 /*
10 * Licensed to the Apache Software Foundation (ASF) under one or more
11 * contributor license agreements. See the NOTICE file distributed with
12 * this work for additional information regarding copyright ownership.
13 * The ASF licenses this file to You under the Apache license, Version 2.0
14 * (the "License"); you may not use this file except in compliance with
15 * the License. You may obtain a copy of the License at
16 *
17 * http://www.apache.org/licenses/LICENSE-2.0
18 *
19 * Unless required by applicable law or agreed to in writing, software
20 * distributed under the License is distributed on an "AS IS" BASIS,
21 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22 * See the license for the specific language governing permissions and
23 * limitations under the license.
24 */
25
26 @RunWith(Parameterized.class)
27 public class Log4j1ConfigurationConverterHadoopTest extends AbstractLog4j1ConfigurationConverterTest {
28
29 @Parameterized.Parameters(name = "{0}")
30 public static List<Path> data() throws IOException {
31 return getPaths("src/test/resources/config-1.2/hadoop");
32 }
33
34 public Log4j1ConfigurationConverterHadoopTest(final Path path) {
35 super(path);
36 }
37
38 }
0 package org.apache.log4j.config;
1
2 import java.io.IOException;
3 import java.nio.file.Path;
4 import java.util.List;
5
6 import org.junit.runner.RunWith;
7 import org.junit.runners.Parameterized;
8
9 /*
10 * Licensed to the Apache Software Foundation (ASF) under one or more
11 * contributor license agreements. See the NOTICE file distributed with
12 * this work for additional information regarding copyright ownership.
13 * The ASF licenses this file to You under the Apache license, Version 2.0
14 * (the "License"); you may not use this file except in compliance with
15 * the License. You may obtain a copy of the License at
16 *
17 * http://www.apache.org/licenses/LICENSE-2.0
18 *
19 * Unless required by applicable law or agreed to in writing, software
20 * distributed under the License is distributed on an "AS IS" BASIS,
21 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22 * See the license for the specific language governing permissions and
23 * limitations under the license.
24 */
25
26 @RunWith(Parameterized.class)
27 public class Log4j1ConfigurationConverterSparkTest extends AbstractLog4j1ConfigurationConverterTest {
28
29 @Parameterized.Parameters(name = "{0}")
30 public static List<Path> data() throws IOException {
31 return getPaths("src/test/resources/config-1.2/spark");
32 }
33
34 public Log4j1ConfigurationConverterSparkTest(final Path path) {
35 super(path);
36 }
37
38 }
1515 */
1616 package org.apache.log4j.config;
1717
18 import static org.junit.Assert.assertEquals;
19 import static org.junit.Assert.assertFalse;
20 import static org.junit.Assert.assertNotNull;
21 import static org.junit.Assert.assertTrue;
22
23 import java.io.File;
24 import java.net.URISyntaxException;
1825 import java.net.URL;
19
26 import java.nio.file.Files;
27 import java.nio.file.Path;
28 import java.util.concurrent.TimeUnit;
29
30 import org.apache.log4j.layout.Log4j1XmlLayout;
2031 import org.apache.logging.log4j.Level;
32 import org.apache.logging.log4j.core.Appender;
2133 import org.apache.logging.log4j.core.Layout;
2234 import org.apache.logging.log4j.core.appender.ConsoleAppender;
2335 import org.apache.logging.log4j.core.appender.ConsoleAppender.Target;
36 import org.apache.logging.log4j.core.appender.FileAppender;
37 import org.apache.logging.log4j.core.appender.NullAppender;
38 import org.apache.logging.log4j.core.appender.RollingFileAppender;
39 import org.apache.logging.log4j.core.appender.rolling.CompositeTriggeringPolicy;
40 import org.apache.logging.log4j.core.appender.rolling.DefaultRolloverStrategy;
41 import org.apache.logging.log4j.core.appender.rolling.RolloverStrategy;
42 import org.apache.logging.log4j.core.appender.rolling.SizeBasedTriggeringPolicy;
43 import org.apache.logging.log4j.core.appender.rolling.TimeBasedTriggeringPolicy;
44 import org.apache.logging.log4j.core.appender.rolling.TriggeringPolicy;
2445 import org.apache.logging.log4j.core.config.Configuration;
2546 import org.apache.logging.log4j.core.config.LoggerConfig;
2647 import org.apache.logging.log4j.core.layout.HtmlLayout;
2748 import org.apache.logging.log4j.core.layout.PatternLayout;
28 import org.apache.logging.log4j.core.layout.XmlLayout;
29 import org.junit.Assert;
3049 import org.junit.Test;
3150
3251 public class Log4j1ConfigurationFactoryTest {
3352
3453 private Layout<?> testConsole(final String configResource) throws Exception {
35 final URL configLocation = ClassLoader.getSystemResource(configResource);
36 Assert.assertNotNull(configLocation);
37 final Configuration configuration = new Log4j1ConfigurationFactory().getConfiguration("test",
38 configLocation.toURI());
39 Assert.assertNotNull(configuration);
40 final ConsoleAppender appender = configuration.getAppender("Console");
41 Assert.assertNotNull(appender);
42 // Can't set ImmediateFlush for a Console Appender in Log4j 2 like you can in 1.2
43 Assert.assertTrue(appender.getImmediateFlush());
44 Assert.assertEquals(Target.SYSTEM_ERR, appender.getTarget());
54 final Configuration configuration = getConfiguration(configResource);
55 final String name = "Console";
56 final ConsoleAppender appender = configuration.getAppender(name);
57 assertNotNull("Missing appender '" + name + "' in configuration " + configResource + " → " + configuration,
58 appender);
59 assertEquals(Target.SYSTEM_ERR, appender.getTarget());
4560 //
4661 final LoggerConfig loggerConfig = configuration.getLoggerConfig("com.example.foo");
47 Assert.assertNotNull(loggerConfig);
48 Assert.assertEquals(Level.DEBUG, loggerConfig.getLevel());
62 assertNotNull(loggerConfig);
63 assertEquals(Level.DEBUG, loggerConfig.getLevel());
64 configuration.start();
65 configuration.stop();
4966 return appender.getLayout();
5067 }
5168
52 @Test
53 public void testConsoleEnhancedPatternLayout() throws Exception {
54 final PatternLayout layout = (PatternLayout) testConsole("config-1.2/log4j-console-EnhancedPatternLayout.properties");
55 Assert.assertEquals("%d{ISO8601} [%t][%c] %-5p: %m%n", layout.getConversionPattern());
56 }
57
58 @Test
59 public void testConsoleHtmlLayout() throws Exception {
60 final Layout<?> layout = testConsole("config-1.2/log4j-console-HtmlLayout.properties");
61 Assert.assertTrue(layout instanceof HtmlLayout);
62 }
63
64 @Test
65 public void testConsolePatternLayout() throws Exception {
66 final PatternLayout layout = (PatternLayout) testConsole("config-1.2/log4j-console-PatternLayout.properties");
67 Assert.assertEquals("%d{ISO8601} [%t][%c] %-5p: %m%n", layout.getConversionPattern());
68 }
69
70 @Test
71 public void testConsoleSimpleLayout() throws Exception {
72 final PatternLayout layout = (PatternLayout) testConsole("config-1.2/log4j-console-SimpleLayout.properties");
73 Assert.assertEquals("%level - %m%n", layout.getConversionPattern());
74 }
75
76 @Test
77 public void testConsoleTtccLayout() throws Exception {
78 final PatternLayout layout = (PatternLayout) testConsole("config-1.2/log4j-console-TTCCLayout.properties");
79 Assert.assertEquals("%relative [%threadName] %level %logger - %m%n", layout.getConversionPattern());
80 }
81
82 @Test
83 public void testConsoleXmlLayout() throws Exception {
84 final Layout<?> layout = testConsole("config-1.2/log4j-console-XmlLayout.properties");
85 Assert.assertTrue(layout instanceof XmlLayout);
86 }
69 private Layout<?> testFile(final String configResource) throws Exception {
70 final Configuration configuration = getConfiguration(configResource);
71 final FileAppender appender = configuration.getAppender("File");
72 assertNotNull(appender);
73 assertEquals("target/mylog.txt", appender.getFileName());
74 //
75 final LoggerConfig loggerConfig = configuration.getLoggerConfig("com.example.foo");
76 assertNotNull(loggerConfig);
77 assertEquals(Level.DEBUG, loggerConfig.getLevel());
78 configuration.start();
79 configuration.stop();
80 return appender.getLayout();
81 }
82
83 private Configuration getConfiguration(final String configResource) throws URISyntaxException {
84 final URL configLocation = ClassLoader.getSystemResource(configResource);
85 assertNotNull(configResource, configLocation);
86 final Configuration configuration = new Log4j1ConfigurationFactory().getConfiguration(null, "test",
87 configLocation.toURI());
88 assertNotNull(configuration);
89 return configuration;
90 }
91
92 @Test
93 public void testConsoleEnhancedPatternLayout() throws Exception {
94 final PatternLayout layout = (PatternLayout) testConsole(
95 "config-1.2/log4j-console-EnhancedPatternLayout.properties");
96 assertEquals("%d{ISO8601} [%t][%c] %-5p %properties %ndc: %m%n", layout.getConversionPattern());
97 }
98
99 @Test
100 public void testConsoleHtmlLayout() throws Exception {
101 final HtmlLayout layout = (HtmlLayout) testConsole("config-1.2/log4j-console-HtmlLayout.properties");
102 assertEquals("Headline", layout.getTitle());
103 assertTrue(layout.isLocationInfo());
104 }
105
106 @Test
107 public void testConsolePatternLayout() throws Exception {
108 final PatternLayout layout = (PatternLayout) testConsole("config-1.2/log4j-console-PatternLayout.properties");
109 assertEquals("%d{ISO8601} [%t][%c] %-5p: %m%n", layout.getConversionPattern());
110 }
111
112 @Test
113 public void testConsoleSimpleLayout() throws Exception {
114 final PatternLayout layout = (PatternLayout) testConsole("config-1.2/log4j-console-SimpleLayout.properties");
115 assertEquals("%level - %m%n", layout.getConversionPattern());
116 }
117
118 @Test
119 public void testConsoleTtccLayout() throws Exception {
120 final PatternLayout layout = (PatternLayout) testConsole("config-1.2/log4j-console-TTCCLayout.properties");
121 assertEquals("%r [%t] %p %notEmpty{%ndc }- %m%n", layout.getConversionPattern());
122 }
123
124 @Test
125 public void testConsoleXmlLayout() throws Exception {
126 final Log4j1XmlLayout layout = (Log4j1XmlLayout) testConsole("config-1.2/log4j-console-XmlLayout.properties");
127 assertTrue(layout.isLocationInfo());
128 assertFalse(layout.isProperties());
129 }
130
131 @Test
132 public void testFileSimpleLayout() throws Exception {
133 final PatternLayout layout = (PatternLayout) testFile("config-1.2/log4j-file-SimpleLayout.properties");
134 assertEquals("%level - %m%n", layout.getConversionPattern());
135 }
136
137 @Test
138 public void testNullAppender() throws Exception {
139 final Configuration configuration = getConfiguration("config-1.2/log4j-NullAppender.properties");
140 final Appender appender = configuration.getAppender("NullAppender");
141 assertNotNull(appender);
142 assertEquals("NullAppender", appender.getName());
143 assertTrue(appender.getClass().getName(), appender instanceof NullAppender);
144 }
145
146 @Test
147 public void testRollingFileAppender() throws Exception {
148 testRollingFileAppender("config-1.2/log4j-RollingFileAppender.properties", "RFA", "target/hadoop.log.%i");
149 }
150
151 @Test
152 public void testDailyRollingFileAppender() throws Exception {
153 testDailyRollingFileAppender("config-1.2/log4j-DailyRollingFileAppender.properties", "DRFA", "target/hadoop.log%d{.yyyy-MM-dd}");
154 }
155
156 @Test
157 public void testRollingFileAppenderWithProperties() throws Exception {
158 testRollingFileAppender("config-1.2/log4j-RollingFileAppender-with-props.properties", "RFA", "target/hadoop.log.%i");
159 }
160
161 @Test
162 public void testSystemProperties1() throws Exception {
163 final Configuration configuration = getConfiguration("config-1.2/log4j-system-properties-1.properties");
164 final RollingFileAppender appender = configuration.getAppender("RFA");
165 String tempFileName = System.getProperty("java.io.tmpdir") + "/hadoop.log";
166 System.out.println("expected: " + tempFileName + " Actual: " + appender.getFileName());
167 assertEquals(tempFileName, appender.getFileName());
168 }
169
170 @Test
171 public void testSystemProperties2() throws Exception {
172 final Configuration configuration = getConfiguration("config-1.2/log4j-system-properties-2.properties");
173 final RollingFileAppender appender = configuration.getAppender("RFA");
174 assertEquals("${java.io.tmpdir}/hadoop.log", appender.getFileName());
175 appender.stop(10, TimeUnit.SECONDS);
176 Path path = new File(appender.getFileName()).toPath();
177 Files.deleteIfExists(path);
178 path = new File("${java.io.tmpdir}").toPath();
179 Files.deleteIfExists(path);
180 }
181
182 private void testRollingFileAppender(final String configResource, final String name, final String filePattern) throws URISyntaxException {
183 final Configuration configuration = getConfiguration(configResource);
184 final Appender appender = configuration.getAppender(name);
185 assertNotNull(appender);
186 assertEquals(name, appender.getName());
187 assertTrue(appender.getClass().getName(), appender instanceof RollingFileAppender);
188 final RollingFileAppender rfa = (RollingFileAppender) appender;
189 assertEquals("target/hadoop.log", rfa.getFileName());
190 assertEquals(filePattern, rfa.getFilePattern());
191 final TriggeringPolicy triggeringPolicy = rfa.getTriggeringPolicy();
192 assertNotNull(triggeringPolicy);
193 assertTrue(triggeringPolicy.getClass().getName(), triggeringPolicy instanceof CompositeTriggeringPolicy);
194 final CompositeTriggeringPolicy ctp = (CompositeTriggeringPolicy) triggeringPolicy;
195 final TriggeringPolicy[] triggeringPolicies = ctp.getTriggeringPolicies();
196 assertEquals(1, triggeringPolicies.length);
197 final TriggeringPolicy tp = triggeringPolicies[0];
198 assertTrue(tp.getClass().getName(), tp instanceof SizeBasedTriggeringPolicy);
199 final SizeBasedTriggeringPolicy sbtp = (SizeBasedTriggeringPolicy) tp;
200 assertEquals(256 * 1024 * 1024, sbtp.getMaxFileSize());
201 final RolloverStrategy rolloverStrategy = rfa.getManager().getRolloverStrategy();
202 assertTrue(rolloverStrategy.getClass().getName(), rolloverStrategy instanceof DefaultRolloverStrategy);
203 final DefaultRolloverStrategy drs = (DefaultRolloverStrategy) rolloverStrategy;
204 assertEquals(20, drs.getMaxIndex());
205 configuration.start();
206 configuration.stop();
207 }
208
209 private void testDailyRollingFileAppender(final String configResource, final String name, final String filePattern) throws URISyntaxException {
210 final Configuration configuration = getConfiguration(configResource);
211 final Appender appender = configuration.getAppender(name);
212 assertNotNull(appender);
213 assertEquals(name, appender.getName());
214 assertTrue(appender.getClass().getName(), appender instanceof RollingFileAppender);
215 final RollingFileAppender rfa = (RollingFileAppender) appender;
216 assertEquals("target/hadoop.log", rfa.getFileName());
217 assertEquals(filePattern, rfa.getFilePattern());
218 final TriggeringPolicy triggeringPolicy = rfa.getTriggeringPolicy();
219 assertNotNull(triggeringPolicy);
220 assertTrue(triggeringPolicy.getClass().getName(), triggeringPolicy instanceof CompositeTriggeringPolicy);
221 final CompositeTriggeringPolicy ctp = (CompositeTriggeringPolicy) triggeringPolicy;
222 final TriggeringPolicy[] triggeringPolicies = ctp.getTriggeringPolicies();
223 assertEquals(1, triggeringPolicies.length);
224 final TriggeringPolicy tp = triggeringPolicies[0];
225 assertTrue(tp.getClass().getName(), tp instanceof TimeBasedTriggeringPolicy);
226 final TimeBasedTriggeringPolicy tbtp = (TimeBasedTriggeringPolicy) tp;
227 assertEquals(1, tbtp.getInterval());
228 final RolloverStrategy rolloverStrategy = rfa.getManager().getRolloverStrategy();
229 assertTrue(rolloverStrategy.getClass().getName(), rolloverStrategy instanceof DefaultRolloverStrategy);
230 final DefaultRolloverStrategy drs = (DefaultRolloverStrategy) rolloverStrategy;
231 assertEquals(Integer.MAX_VALUE, drs.getMaxIndex());
232 configuration.start();
233 configuration.stop();
234 }
235
87236 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.log4j.layout;
17
18 import org.apache.logging.log4j.Level;
19 import org.apache.logging.log4j.core.impl.Log4jLogEvent;
20 import org.apache.logging.log4j.message.SimpleMessage;
21 import org.junit.Test;
22
23 import java.util.HashMap;
24 import java.util.Map;
25
26 import static org.junit.Assert.assertEquals;
27
28 public class Log4j1XmlLayoutTest {
29
30 @Test
31 public void testWithoutThrown() {
32 final Log4j1XmlLayout layout = Log4j1XmlLayout.createLayout(false, true);
33
34 final Log4jLogEvent event = Log4jLogEvent.newBuilder()
35 .setLoggerName("a.B")
36 .setLevel(Level.INFO)
37 .setMessage(new SimpleMessage("Hello, World"))
38 .setTimeMillis(System.currentTimeMillis() + 17)
39 .build();
40
41 final String result = layout.toSerializable(event);
42
43 final String expected =
44 "<log4j:event logger=\"a.B\" timestamp=\"" + event.getTimeMillis() + "\" level=\"INFO\" thread=\"main\">\r\n" +
45 "<log4j:message><![CDATA[Hello, World]]></log4j:message>\r\n" +
46 "</log4j:event>\r\n\r\n";
47
48 assertEquals(expected, result);
49 }
50
51 @Test
52 public void testWithPropertiesAndLocationInfo() {
53 final Log4j1XmlLayout layout = Log4j1XmlLayout.createLayout(true, true);
54
55 final Map<String, String> contextMap = new HashMap<>(2);
56 contextMap.put("key1", "value1");
57 contextMap.put("key2", "value2");
58 final Log4jLogEvent event = Log4jLogEvent.newBuilder()
59 .setLoggerName("a.B")
60 .setLevel(Level.INFO)
61 .setMessage(new SimpleMessage("Hello, World"))
62 .setTimeMillis(System.currentTimeMillis() + 17)
63 .setIncludeLocation(true)
64 .setSource(new StackTraceElement("pack.MyClass", "myMethod", "MyClass.java", 17))
65 .setContextMap(contextMap)
66 .build();
67
68 final String result = layout.toSerializable(event);
69
70 final String expected =
71 "<log4j:event logger=\"a.B\" timestamp=\"" + event.getTimeMillis() + "\" level=\"INFO\" thread=\"main\">\r\n" +
72 "<log4j:message><![CDATA[Hello, World]]></log4j:message>\r\n" +
73 "<log4j:locationInfo class=\"pack.MyClass\" method=\"myMethod\" file=\"MyClass.java\" line=\"17\"/>\r\n" +
74 "<log4j:properties>\r\n" +
75 "<log4j:data name=\"key1\" value=\"value1\"/>\r\n" +
76 "<log4j:data name=\"key2\" value=\"value2\"/>\r\n" +
77 "</log4j:properties>\r\n"+
78 "</log4j:event>\r\n\r\n";
79
80 assertEquals(expected, result);
81 }
82
83 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.log4j.pattern;
17
18 import org.apache.logging.log4j.Level;
19 import org.apache.logging.log4j.core.LogEvent;
20 import org.apache.logging.log4j.core.impl.Log4jLogEvent;
21 import org.apache.logging.log4j.message.SimpleMessage;
22 import org.junit.Test;
23
24 import java.util.HashMap;
25 import java.util.Map;
26
27 import static org.junit.Assert.assertEquals;
28
29 public class Log4j1MdcPatternConverterTest {
30
31 @Test
32 public void testConverter0() {
33 final Map<String, String> contextMap = new HashMap<>(0);
34 final String expected = "{}";
35 test(contextMap, expected, null);
36 }
37
38 @Test
39 public void testConverter1() {
40 final Map<String, String> contextMap = new HashMap<>(1);
41 contextMap.put("key1", "value1");
42 final String expected = "{{key1,value1}}";
43 test(contextMap, expected, null);
44 }
45
46 @Test
47 public void testConverter2() {
48 final Map<String, String> contextMap = new HashMap<>(2);
49 contextMap.put("key1", "value1");
50 contextMap.put("key2", "value2");
51 final String expected = "{{key1,value1}{key2,value2}}";
52 test(contextMap, expected, null);
53 }
54
55 @Test
56 public void testConverterWithKey() {
57 final Map<String, String> contextMap = new HashMap<>(2);
58 contextMap.put("key1", "value1");
59 contextMap.put("key2", "value2");
60 final String expected = "value1";
61 test(contextMap, expected, new String[] {"key1"});
62 }
63
64 private void test(final Map<String, String> contextMap, final String expected, final String[] options) {
65 final LogEvent event = Log4jLogEvent.newBuilder()
66 .setLoggerName("MyLogger")
67 .setLevel(Level.DEBUG)
68 .setMessage(new SimpleMessage("Hello"))
69 .setContextMap(contextMap)
70 .build();
71 final StringBuilder sb = new StringBuilder();
72 final Log4j1MdcPatternConverter converter = Log4j1MdcPatternConverter.newInstance(options);
73 converter.format(event, sb);
74 assertEquals(expected, sb.toString());
75 }
76
77 }
78
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.log4j.pattern;
17
18 import org.apache.logging.log4j.Level;
19 import org.apache.logging.log4j.ThreadContext;
20 import org.apache.logging.log4j.core.LogEvent;
21 import org.apache.logging.log4j.core.impl.Log4jLogEvent;
22 import org.apache.logging.log4j.junit.ThreadContextStackRule;
23 import org.apache.logging.log4j.message.SimpleMessage;
24 import org.junit.Rule;
25 import org.junit.Test;
26
27 import static org.junit.Assert.assertEquals;
28
29 public class Log4j1NdcPatternConverterTest {
30
31 @Rule
32 public final ThreadContextStackRule threadContextRule = new ThreadContextStackRule();
33
34 @Test
35 public void testEmpty() {
36 testConverter("");
37 }
38
39 @Test
40 public void test1() {
41 ThreadContext.push("foo");
42 testConverter("foo");
43 }
44
45 @Test
46 public void test2() {
47 ThreadContext.push("foo");
48 ThreadContext.push("bar");
49 testConverter("foo bar");
50 }
51
52 @Test
53 public void test3() {
54 ThreadContext.push("foo");
55 ThreadContext.push("bar");
56 ThreadContext.push("baz");
57 testConverter("foo bar baz");
58 }
59
60 private void testConverter(final String expected) {
61 final Log4j1NdcPatternConverter converter = Log4j1NdcPatternConverter.newInstance(null);
62 final LogEvent event = Log4jLogEvent.newBuilder()
63 .setLoggerName("MyLogger")
64 .setLevel(Level.DEBUG)
65 .setMessage(new SimpleMessage("Hello"))
66 .build();
67 final StringBuilder sb = new StringBuilder();
68 converter.format(event, sb);
69 assertEquals(expected, sb.toString());
70 }
71
72 }
73
0 #
1 # Licensed under the Apache License, Version 2.0 (the "License");
2 # you may not use this file except in compliance with the License.
3 # You may obtain a copy of the License at
4 #
5 # http://www.apache.org/licenses/LICENSE-2.0
6 #
7 # Unless required by applicable law or agreed to in writing, software
8 # distributed under the License is distributed on an "AS IS" BASIS,
9 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10 # See the License for the specific language governing permissions and
11 # limitations under the License. See accompanying LICENSE file.
12 #
13 log4j.appender.test=org.apache.log4j.ConsoleAppender
14 log4j.appender.test.Target=System.out
15 log4j.appender.test.layout=org.apache.log4j.PatternLayout
16 log4j.appender.test.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
17
18 log4j.logger.org.apache.hadoop.security.authentication=DEBUG, test
0 # Licensed to the Apache Software Foundation (ASF) under one
1 # or more contributor license agreements. See the NOTICE file
2 # distributed with this work for additional information
3 # regarding copyright ownership. The ASF licenses this file
4 # to you under the Apache License, Version 2.0 (the
5 # "License"); you may not use this file except in compliance
6 # with the License. You may obtain a copy of the License at
7 #
8 # http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15
16 # Define some default values that can be overridden by system properties
17 hadoop.root.logger=INFO,console
18 hadoop.log.dir=target
19 hadoop.log.file=hadoop.log
20
21 # Define the root logger to the system property "hadoop.root.logger".
22 log4j.rootLogger=${hadoop.root.logger}, EventCounter
23
24 # Logging Threshold
25 log4j.threshold=ALL
26
27 # Null Appender
28 log4j.appender.NullAppender=org.apache.log4j.varia.NullAppender
29
30 #
31 # Rolling File Appender - cap space usage at 5gb.
32 #
33 hadoop.log.maxfilesize=256MB
34 hadoop.log.maxbackupindex=20
35 log4j.appender.RFA=org.apache.log4j.RollingFileAppender
36 log4j.appender.RFA.File=${hadoop.log.dir}/${hadoop.log.file}
37
38 log4j.appender.RFA.MaxFileSize=${hadoop.log.maxfilesize}
39 log4j.appender.RFA.MaxBackupIndex=${hadoop.log.maxbackupindex}
40
41 log4j.appender.RFA.layout=org.apache.log4j.PatternLayout
42
43 # Pattern format: Date LogLevel LoggerName LogMessage
44 log4j.appender.RFA.layout.ConversionPattern=%d{ISO8601} %p %c: %m%n
45 # Debugging Pattern format
46 #log4j.appender.RFA.layout.ConversionPattern=%d{ISO8601} %-5p %c{2} (%F:%M(%L)) - %m%n
47
48
49 #
50 # Daily Rolling File Appender
51 #
52
53 log4j.appender.DRFA=org.apache.log4j.DailyRollingFileAppender
54 log4j.appender.DRFA.File=${hadoop.log.dir}/${hadoop.log.file}
55
56 # Rollover at midnight
57 log4j.appender.DRFA.DatePattern=.yyyy-MM-dd
58
59 log4j.appender.DRFA.layout=org.apache.log4j.PatternLayout
60
61 # Pattern format: Date LogLevel LoggerName LogMessage
62 log4j.appender.DRFA.layout.ConversionPattern=%d{ISO8601} %p %c: %m%n
63 # Debugging Pattern format
64 #log4j.appender.DRFA.layout.ConversionPattern=%d{ISO8601} %-5p %c{2} (%F:%M(%L)) - %m%n
65
66
67 #
68 # console
69 # Add "console" to rootlogger above if you want to use this
70 #
71
72 log4j.appender.console=org.apache.log4j.ConsoleAppender
73 log4j.appender.console.target=System.err
74 log4j.appender.console.layout=org.apache.log4j.PatternLayout
75 log4j.appender.console.layout.ConversionPattern=%d{ISO8601} %p %c{2}: %m%n
76
77 #
78 # TaskLog Appender
79 #
80
81 #Default values
82 hadoop.tasklog.taskid=null
83 hadoop.tasklog.iscleanup=false
84 hadoop.tasklog.noKeepSplits=4
85 hadoop.tasklog.totalLogFileSize=100
86 hadoop.tasklog.purgeLogSplits=true
87 hadoop.tasklog.logsRetainHours=12
88
89 log4j.appender.TLA=org.apache.hadoop.mapred.TaskLogAppender
90 log4j.appender.TLA.taskId=${hadoop.tasklog.taskid}
91 log4j.appender.TLA.isCleanup=${hadoop.tasklog.iscleanup}
92 log4j.appender.TLA.totalLogFileSize=${hadoop.tasklog.totalLogFileSize}
93
94 log4j.appender.TLA.layout=org.apache.log4j.PatternLayout
95 log4j.appender.TLA.layout.ConversionPattern=%d{ISO8601} %p %c: %m%n
96
97 #
98 # HDFS block state change log from block manager
99 #
100 # Uncomment the following to log normal block state change
101 # messages from BlockManager in NameNode.
102 #log4j.logger.BlockStateChange=DEBUG
103
104 #
105 #Security appender
106 #
107 hadoop.security.logger=INFO,NullAppender
108 hadoop.security.log.maxfilesize=256MB
109 hadoop.security.log.maxbackupindex=20
110 log4j.category.SecurityLogger=${hadoop.security.logger}
111 hadoop.security.log.file=SecurityAuth-${user.name}.audit
112 log4j.appender.RFAS=org.apache.log4j.RollingFileAppender
113 log4j.appender.RFAS.File=${hadoop.log.dir}/${hadoop.security.log.file}
114 log4j.appender.RFAS.layout=org.apache.log4j.PatternLayout
115 log4j.appender.RFAS.layout.ConversionPattern=%d{ISO8601} %p %c: %m%n
116 log4j.appender.RFAS.MaxFileSize=${hadoop.security.log.maxfilesize}
117 log4j.appender.RFAS.MaxBackupIndex=${hadoop.security.log.maxbackupindex}
118
119 #
120 # Daily Rolling Security appender
121 #
122 log4j.appender.DRFAS=org.apache.log4j.DailyRollingFileAppender
123 log4j.appender.DRFAS.File=${hadoop.log.dir}/${hadoop.security.log.file}
124 log4j.appender.DRFAS.layout=org.apache.log4j.PatternLayout
125 log4j.appender.DRFAS.layout.ConversionPattern=%d{ISO8601} %p %c: %m%n
126 log4j.appender.DRFAS.DatePattern=.yyyy-MM-dd
127
128 #
129 # hadoop configuration logging
130 #
131
132 # Uncomment the following line to turn off configuration deprecation warnings.
133 # log4j.logger.org.apache.hadoop.conf.Configuration.deprecation=WARN
134
135 #
136 # hdfs audit logging
137 #
138 hdfs.audit.logger=INFO,NullAppender
139 hdfs.audit.log.maxfilesize=256MB
140 hdfs.audit.log.maxbackupindex=20
141 log4j.logger.org.apache.hadoop.hdfs.server.namenode.FSNamesystem.audit=${hdfs.audit.logger}
142 log4j.additivity.org.apache.hadoop.hdfs.server.namenode.FSNamesystem.audit=false
143 log4j.appender.RFAAUDIT=org.apache.log4j.RollingFileAppender
144 log4j.appender.RFAAUDIT.File=${hadoop.log.dir}/hdfs-audit.log
145 log4j.appender.RFAAUDIT.layout=org.apache.log4j.PatternLayout
146 log4j.appender.RFAAUDIT.layout.ConversionPattern=%d{ISO8601} %p %c{2}: %m%n
147 log4j.appender.RFAAUDIT.MaxFileSize=${hdfs.audit.log.maxfilesize}
148 log4j.appender.RFAAUDIT.MaxBackupIndex=${hdfs.audit.log.maxbackupindex}
149
150 #
151 # NameNode metrics logging.
152 # The default is to retain two namenode-metrics.log files up to 64MB each.
153 #
154 namenode.metrics.logger=INFO,NullAppender
155 log4j.logger.NameNodeMetricsLog=${namenode.metrics.logger}
156 log4j.additivity.NameNodeMetricsLog=false
157 log4j.appender.NNMETRICSRFA=org.apache.log4j.RollingFileAppender
158 log4j.appender.NNMETRICSRFA.File=${hadoop.log.dir}/namenode-metrics.log
159 log4j.appender.NNMETRICSRFA.layout=org.apache.log4j.PatternLayout
160 log4j.appender.NNMETRICSRFA.layout.ConversionPattern=%d{ISO8601} %m%n
161 log4j.appender.NNMETRICSRFA.MaxBackupIndex=1
162 log4j.appender.NNMETRICSRFA.MaxFileSize=64MB
163
164 #
165 # DataNode metrics logging.
166 # The default is to retain two datanode-metrics.log files up to 64MB each.
167 #
168 datanode.metrics.logger=INFO,NullAppender
169 log4j.logger.DataNodeMetricsLog=${datanode.metrics.logger}
170 log4j.additivity.DataNodeMetricsLog=false
171 log4j.appender.DNMETRICSRFA=org.apache.log4j.RollingFileAppender
172 log4j.appender.DNMETRICSRFA.File=${hadoop.log.dir}/datanode-metrics.log
173 log4j.appender.DNMETRICSRFA.layout=org.apache.log4j.PatternLayout
174 log4j.appender.DNMETRICSRFA.layout.ConversionPattern=%d{ISO8601} %m%n
175 log4j.appender.DNMETRICSRFA.MaxBackupIndex=1
176 log4j.appender.DNMETRICSRFA.MaxFileSize=64MB
177
178 #
179 # mapred audit logging
180 #
181 mapred.audit.logger=INFO,NullAppender
182 mapred.audit.log.maxfilesize=256MB
183 mapred.audit.log.maxbackupindex=20
184 log4j.logger.org.apache.hadoop.mapred.AuditLogger=${mapred.audit.logger}
185 log4j.additivity.org.apache.hadoop.mapred.AuditLogger=false
186 log4j.appender.MRAUDIT=org.apache.log4j.RollingFileAppender
187 log4j.appender.MRAUDIT.File=${hadoop.log.dir}/mapred-audit.log
188 log4j.appender.MRAUDIT.layout=org.apache.log4j.PatternLayout
189 log4j.appender.MRAUDIT.layout.ConversionPattern=%d{ISO8601} %p %c{2}: %m%n
190 log4j.appender.MRAUDIT.MaxFileSize=${mapred.audit.log.maxfilesize}
191 log4j.appender.MRAUDIT.MaxBackupIndex=${mapred.audit.log.maxbackupindex}
192
193 # Custom Logging levels
194
195 #log4j.logger.org.apache.hadoop.mapred.JobTracker=DEBUG
196 #log4j.logger.org.apache.hadoop.mapred.TaskTracker=DEBUG
197 #log4j.logger.org.apache.hadoop.hdfs.server.namenode.FSNamesystem.audit=DEBUG
198
199 # Jets3t library
200 log4j.logger.org.jets3t.service.impl.rest.httpclient.RestS3Service=ERROR
201
202 # AWS SDK & S3A FileSystem
203 log4j.logger.com.amazonaws=ERROR
204 log4j.logger.com.amazonaws.http.AmazonHttpClient=ERROR
205 log4j.logger.org.apache.hadoop.fs.s3a.S3AFileSystem=WARN
206
207 #
208 # Event Counter Appender
209 # Sends counts of logging messages at different severity levels to Hadoop Metrics.
210 #
211 log4j.appender.EventCounter=org.apache.hadoop.log.metrics.EventCounter
212
213 #
214 # Job Summary Appender
215 #
216 # Use following logger to send summary to separate file defined by
217 # hadoop.mapreduce.jobsummary.log.file :
218 # hadoop.mapreduce.jobsummary.logger=INFO,JSA
219 #
220 hadoop.mapreduce.jobsummary.logger=${hadoop.root.logger}
221 hadoop.mapreduce.jobsummary.log.file=hadoop-mapreduce.jobsummary.log
222 hadoop.mapreduce.jobsummary.log.maxfilesize=256MB
223 hadoop.mapreduce.jobsummary.log.maxbackupindex=20
224 log4j.appender.JSA=org.apache.log4j.RollingFileAppender
225 log4j.appender.JSA.File=${hadoop.log.dir}/${hadoop.mapreduce.jobsummary.log.file}
226 log4j.appender.JSA.MaxFileSize=${hadoop.mapreduce.jobsummary.log.maxfilesize}
227 log4j.appender.JSA.MaxBackupIndex=${hadoop.mapreduce.jobsummary.log.maxbackupindex}
228 log4j.appender.JSA.layout=org.apache.log4j.PatternLayout
229 log4j.appender.JSA.layout.ConversionPattern=%d{ISO8601} %p %c{2}: %m%n
230 log4j.logger.org.apache.hadoop.mapred.JobInProgress$JobSummary=${hadoop.mapreduce.jobsummary.logger}
231 log4j.additivity.org.apache.hadoop.mapred.JobInProgress$JobSummary=false
232
233 #
234 # shuffle connection log from shuffleHandler
235 # Uncomment the following line to enable logging of shuffle connections
236 # log4j.logger.org.apache.hadoop.mapred.ShuffleHandler.audit=DEBUG
237
238 #
239 # Yarn ResourceManager Application Summary Log
240 #
241 # Set the ResourceManager summary log filename
242 yarn.server.resourcemanager.appsummary.log.file=rm-appsummary.log
243 # Set the ResourceManager summary log level and appender
244 yarn.server.resourcemanager.appsummary.logger=${hadoop.root.logger}
245 #yarn.server.resourcemanager.appsummary.logger=INFO,RMSUMMARY
246
247 # To enable AppSummaryLogging for the RM,
248 # set yarn.server.resourcemanager.appsummary.logger to
249 # <LEVEL>,RMSUMMARY in hadoop-env.sh
250
251 # Appender for ResourceManager Application Summary Log
252 # Requires the following properties to be set
253 # - hadoop.log.dir (Hadoop Log directory)
254 # - yarn.server.resourcemanager.appsummary.log.file (resource manager app summary log filename)
255 # - yarn.server.resourcemanager.appsummary.logger (resource manager app summary log level and appender)
256
257 log4j.logger.org.apache.hadoop.yarn.server.resourcemanager.RMAppManager$ApplicationSummary=${yarn.server.resourcemanager.appsummary.logger}
258 log4j.additivity.org.apache.hadoop.yarn.server.resourcemanager.RMAppManager$ApplicationSummary=false
259 log4j.appender.RMSUMMARY=org.apache.log4j.RollingFileAppender
260 log4j.appender.RMSUMMARY.File=${hadoop.log.dir}/${yarn.server.resourcemanager.appsummary.log.file}
261 log4j.appender.RMSUMMARY.MaxFileSize=256MB
262 log4j.appender.RMSUMMARY.MaxBackupIndex=20
263 log4j.appender.RMSUMMARY.layout=org.apache.log4j.PatternLayout
264 log4j.appender.RMSUMMARY.layout.ConversionPattern=%d{ISO8601} %p %c{2}: %m%n
265
266 # HS audit log configs
267 #mapreduce.hs.audit.logger=INFO,HSAUDIT
268 #log4j.logger.org.apache.hadoop.mapreduce.v2.hs.HSAuditLogger=${mapreduce.hs.audit.logger}
269 #log4j.additivity.org.apache.hadoop.mapreduce.v2.hs.HSAuditLogger=false
270 #log4j.appender.HSAUDIT=org.apache.log4j.DailyRollingFileAppender
271 #log4j.appender.HSAUDIT.File=${hadoop.log.dir}/hs-audit.log
272 #log4j.appender.HSAUDIT.layout=org.apache.log4j.PatternLayout
273 #log4j.appender.HSAUDIT.layout.ConversionPattern=%d{ISO8601} %p %c{2}: %m%n
274 #log4j.appender.HSAUDIT.DatePattern=.yyyy-MM-dd
275
276 # Http Server Request Logs
277 #log4j.logger.http.requests.namenode=INFO,namenoderequestlog
278 #log4j.appender.namenoderequestlog=org.apache.hadoop.http.HttpRequestLogAppender
279 #log4j.appender.namenoderequestlog.Filename=${hadoop.log.dir}/jetty-namenode-yyyy_mm_dd.log
280 #log4j.appender.namenoderequestlog.RetainDays=3
281
282 #log4j.logger.http.requests.datanode=INFO,datanoderequestlog
283 #log4j.appender.datanoderequestlog=org.apache.hadoop.http.HttpRequestLogAppender
284 #log4j.appender.datanoderequestlog.Filename=${hadoop.log.dir}/jetty-datanode-yyyy_mm_dd.log
285 #log4j.appender.datanoderequestlog.RetainDays=3
286
287 #log4j.logger.http.requests.resourcemanager=INFO,resourcemanagerrequestlog
288 #log4j.appender.resourcemanagerrequestlog=org.apache.hadoop.http.HttpRequestLogAppender
289 #log4j.appender.resourcemanagerrequestlog.Filename=${hadoop.log.dir}/jetty-resourcemanager-yyyy_mm_dd.log
290 #log4j.appender.resourcemanagerrequestlog.RetainDays=3
291
292 #log4j.logger.http.requests.jobhistory=INFO,jobhistoryrequestlog
293 #log4j.appender.jobhistoryrequestlog=org.apache.hadoop.http.HttpRequestLogAppender
294 #log4j.appender.jobhistoryrequestlog.Filename=${hadoop.log.dir}/jetty-jobhistory-yyyy_mm_dd.log
295 #log4j.appender.jobhistoryrequestlog.RetainDays=3
296
297 #log4j.logger.http.requests.nodemanager=INFO,nodemanagerrequestlog
298 #log4j.appender.nodemanagerrequestlog=org.apache.hadoop.http.HttpRequestLogAppender
299 #log4j.appender.nodemanagerrequestlog.Filename=${hadoop.log.dir}/jetty-nodemanager-yyyy_mm_dd.log
300 #log4j.appender.nodemanagerrequestlog.RetainDays=3
301
302
303 # WebHdfs request log on datanodes
304 # Specify -Ddatanode.webhdfs.logger=INFO,HTTPDRFA on datanode startup to
305 # direct the log to a separate file.
306 #datanode.webhdfs.logger=INFO,console
307 #log4j.logger.datanode.webhdfs=${datanode.webhdfs.logger}
308 #log4j.appender.HTTPDRFA=org.apache.log4j.DailyRollingFileAppender
309 #log4j.appender.HTTPDRFA.File=${hadoop.log.dir}/hadoop-datanode-webhdfs.log
310 #log4j.appender.HTTPDRFA.layout=org.apache.log4j.PatternLayout
311 #log4j.appender.HTTPDRFA.layout.ConversionPattern=%d{ISO8601} %m%n
312 #log4j.appender.HTTPDRFA.DatePattern=.yyyy-MM-dd
313
314
315 # Appender for viewing information for errors and warnings
316 yarn.ewma.cleanupInterval=300
317 yarn.ewma.messageAgeLimitSeconds=86400
318 yarn.ewma.maxUniqueMessages=250
319 log4j.appender.EWMA=org.apache.hadoop.yarn.util.Log4jWarningErrorMetricsAppender
320 log4j.appender.EWMA.cleanupInterval=${yarn.ewma.cleanupInterval}
321 log4j.appender.EWMA.messageAgeLimitSeconds=${yarn.ewma.messageAgeLimitSeconds}
322 log4j.appender.EWMA.maxUniqueMessages=${yarn.ewma.maxUniqueMessages}
0 # Licensed under the Apache License, Version 2.0 (the "License");
1 # you may not use this file except in compliance with the License.
2 # You may obtain a copy of the License at
3 #
4 # http://www.apache.org/licenses/LICENSE-2.0
5 #
6 # Unless required by applicable law or agreed to in writing, software
7 # distributed under the License is distributed on an "AS IS" BASIS,
8 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 # See the License for the specific language governing permissions and
10 # limitations under the License.
11 # log4j configuration used during build and unit tests
12
13 log4j.rootLogger=info,stdout
14 log4j.threshold=ALL
15 log4j.appender.stdout=org.apache.log4j.ConsoleAppender
16 log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
17 log4j.appender.stdout.layout.ConversionPattern=%d{ISO8601} %-5p %c{2} (%F:%M(%L)) - %m%n
0 #
1 # Licensed to the Apache Software Foundation (ASF) under one
2 # or more contributor license agreements. See the NOTICE file
3 # distributed with this work for additional information
4 # regarding copyright ownership. The ASF licenses this file
5 # to you under the Apache License, Version 2.0 (the
6 # "License"); you may not use this file except in compliance
7 # with 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 # STDOUT Appender
19 log4j.appender.stdout=org.apache.log4j.ConsoleAppender
20 log4j.appender.stdout.Target=System.out
21 log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
22 log4j.appender.stdout.layout.ConversionPattern=%d{ISO8601} %-5p %c{1} - %m%n
23
24 log4j.rootLogger=INFO, stdout
25 log4j.logger.org.apache.hadoop.conf=ERROR
26 log4j.logger.org.apache.hadoop.crytpo.key.kms.server=ALL
27 log4j.logger.com.sun.jersey.server.wadl.generators.WadlGeneratorJAXBGrammarGenerator=OFF
28 log4j.logger.org.apache.hadoop.security=OFF
29 log4j.logger.org.apache.directory.server.core=OFF
30 log4j.logger.org.apache.hadoop.util.NativeCodeLoader=OFF
0 #
1 # Licensed to the Apache Software Foundation (ASF) under one
2 # or more contributor license agreements. See the NOTICE file
3 # distributed with this work for additional information
4 # regarding copyright ownership. The ASF licenses this file
5 # to you under the Apache License, Version 2.0 (the
6 # "License"); you may not use this file except in compliance
7 # with 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 # STDOUT Appender
19 log4j.appender.stdout=org.apache.log4j.ConsoleAppender
20 log4j.appender.stdout.Target=System.err
21 log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
22 log4j.appender.stdout.layout.ConversionPattern=%d{ISO8601} %-5p %c{1} - %m%n
23
24 log4j.rootLogger=INFO, stdout
25
26 # Switching off most of Apache DS logqing which is QUITE verbose
27 log4j.logger.org.apache.directory=OFF
28 log4j.logger.org.apache.directory.server.kerberos=INFO, stdout
29 log4j.additivity.org.apache.directory=false
30 log4j.logger.net.sf.ehcache=INFO, stdout
0 # Licensed under the Apache License, Version 2.0 (the "License");
1 # you may not use this file except in compliance with the License.
2 # You may obtain a copy of the License at
3 #
4 # http://www.apache.org/licenses/LICENSE-2.0
5 #
6 # Unless required by applicable law or agreed to in writing, software
7 # distributed under the License is distributed on an "AS IS" BASIS,
8 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 # See the License for the specific language governing permissions and
10 # limitations under the License.
11 # log4j configuration used during build and unit tests
12
13 log4j.rootLogger=info,stdout
14 log4j.threshold=ALL
15 log4j.appender.stdout=org.apache.log4j.ConsoleAppender
16 log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
17 log4j.appender.stdout.layout.ConversionPattern=%d{ISO8601} %-5p %c{2} (%F:%M(%L)) - %m%n
0 #
1 #
2 # Licensed to the Apache Software Foundation (ASF) under one
3 # or more contributor license agreements. See the NOTICE file
4 # distributed with this work for additional information
5 # regarding copyright ownership. The ASF licenses this file
6 # to you under the Apache License, Version 2.0 (the
7 # "License"); you may not use this file except in compliance
8 # with the License. You may obtain a copy of the License at
9 #
10 # http://www.apache.org/licenses/LICENSE-2.0
11 #
12 # Unless required by applicable law or agreed to in writing,
13 # software distributed under the License is distributed on an
14 # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 # KIND, either express or implied. See the License for the
16 # specific language governing permissions and limitations
17 # under the License.
18 #
19 #
20
21 #
22 # Bookkeeper Journal Logging Configuration
23 #
24
25 # Format is "<default threshold> (, <appender>)+
26
27 # DEFAULT: console appender only
28 log4j.rootLogger=DEBUG, CONSOLE
29
30 # Example with rolling log file
31 #log4j.rootLogger=DEBUG, CONSOLE, ROLLINGFILE
32
33 # Example with rolling log file and tracing
34 #log4j.rootLogger=TRACE, CONSOLE, ROLLINGFILE, TRACEFILE
35
36 #
37 # Log INFO level and above messages to the console
38 #
39 log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
40 log4j.appender.CONSOLE.Threshold=INFO
41 log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
42 log4j.appender.CONSOLE.layout.ConversionPattern=%d{ISO8601} - %-5p - [%t:%C{1}@%L] - %m%n
43
44 #
45 # Add ROLLINGFILE to rootLogger to get log file output
46 # Log DEBUG level and above messages to a log file
47 log4j.appender.ROLLINGFILE=org.apache.log4j.DailyRollingFileAppender
48 log4j.appender.ROLLINGFILE.Threshold=DEBUG
49 log4j.appender.ROLLINGFILE.File=hdfs-namenode.log
50 log4j.appender.ROLLINGFILE.layout=org.apache.log4j.PatternLayout
51 log4j.appender.ROLLINGFILE.layout.ConversionPattern=%d{ISO8601} - %-5p - [%t:%C{1}@%L] - %m%n
52
53 # Max log file size of 10MB
54 log4j.appender.ROLLINGFILE.MaxFileSize=10MB
0 #
1 # Licensed to the Apache Software Foundation (ASF) under one or more
2 # contributor license agreements. See the NOTICE file distributed with
3 # this work for additional information regarding copyright ownership.
4 # The ASF licenses this file to You under the Apache License, Version 2.0
5 # (the "License"); you may not use this file except in compliance with
6 # the License. You may obtain a copy of the License at
7 #
8 # http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15 #
16 # log4j configuration used during build and unit tests
17
18 log4j.rootLogger=info,stdout
19 log4j.threshold=ALL
20 log4j.appender.stdout=org.apache.log4j.ConsoleAppender
21 log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
22 log4j.appender.stdout.layout.ConversionPattern=%d{ISO8601} [%t] %-5p %c{2} (%F:%M(%L)) - %m%n
23
24 #
25 # NameNode metrics logging.
26 # The default is to retain two namenode-metrics.log files up to 64MB each.
27 #
28 log4j.logger.NameNodeMetricsLog=INFO,NNMETRICSRFA
29 log4j.additivity.NameNodeMetricsLog=false
30 log4j.appender.NNMETRICSRFA=org.apache.log4j.RollingFileAppender
31 log4j.appender.NNMETRICSRFA.File=${hadoop.log.dir}/namenode-metrics.log
32 log4j.appender.NNMETRICSRFA.layout=org.apache.log4j.PatternLayout
33 log4j.appender.NNMETRICSRFA.layout.ConversionPattern=%d{ISO8601} %m%n
34 log4j.appender.NNMETRICSRFA.MaxBackupIndex=1
35 log4j.appender.NNMETRICSRFA.MaxFileSize=64MB
36
37 #
38 # DataNode metrics logging.
39 # The default is to retain two datanode-metrics.log files up to 64MB each.
40 #
41 log4j.logger.DataNodeMetricsLog=INFO,DNMETRICSRFA
42 log4j.additivity.DataNodeMetricsLog=false
43 log4j.appender.DNMETRICSRFA=org.apache.log4j.RollingFileAppender
44 log4j.appender.DNMETRICSRFA.File=${hadoop.log.dir}/datanode-metrics.log
45 log4j.appender.DNMETRICSRFA.layout=org.apache.log4j.PatternLayout
46 log4j.appender.DNMETRICSRFA.layout.ConversionPattern=%d{ISO8601} %m%n
47 log4j.appender.DNMETRICSRFA.MaxBackupIndex=1
48 log4j.appender.DNMETRICSRFA.MaxFileSize=64MB
0 #
1 # Licensed to the Apache Software Foundation (ASF) under one or more
2 # contributor license agreements. See the NOTICE file distributed with
3 # this work for additional information regarding copyright ownership.
4 # The ASF licenses this file to You under the Apache License, Version 2.0
5 # (the "License"); you may not use this file except in compliance with
6 # the License. You may obtain a copy of the License at
7 #
8 # http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15 #
16 # log4j configuration used during build and unit tests
17
18 log4j.rootLogger=info,stdout
19 log4j.threshold=ALL
20 log4j.appender.stdout=org.apache.log4j.ConsoleAppender
21 log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
22 log4j.appender.stdout.layout.ConversionPattern=%d{ISO8601} [%t] %-5p %c{2} (%F:%M(%L)) - %m%n
23
24 #
25 # NameNode metrics logging.
26 # The default is to retain two namenode-metrics.log files up to 64MB each.
27 #
28 log4j.logger.NameNodeMetricsLog=INFO,NNMETRICSRFA
29 log4j.additivity.NameNodeMetricsLog=false
30 log4j.appender.NNMETRICSRFA=org.apache.log4j.RollingFileAppender
31 log4j.appender.NNMETRICSRFA.File=${hadoop.log.dir}/namenode-metrics.log
32 log4j.appender.NNMETRICSRFA.layout=org.apache.log4j.PatternLayout
33 log4j.appender.NNMETRICSRFA.layout.ConversionPattern=%d{ISO8601} %m%n
34 log4j.appender.NNMETRICSRFA.MaxBackupIndex=1
35 log4j.appender.NNMETRICSRFA.MaxFileSize=64MB
36
37 #
38 # DataNode metrics logging.
39 # The default is to retain two datanode-metrics.log files up to 64MB each.
40 #
41 log4j.logger.DataNodeMetricsLog=INFO,DNMETRICSRFA
42 log4j.additivity.DataNodeMetricsLog=false
43 log4j.appender.DNMETRICSRFA=org.apache.log4j.RollingFileAppender
44 log4j.appender.DNMETRICSRFA.File=${hadoop.log.dir}/datanode-metrics.log
45 log4j.appender.DNMETRICSRFA.layout=org.apache.log4j.PatternLayout
46 log4j.appender.DNMETRICSRFA.layout.ConversionPattern=%d{ISO8601} %m%n
47 log4j.appender.DNMETRICSRFA.MaxBackupIndex=1
48 log4j.appender.DNMETRICSRFA.MaxFileSize=64MB
0 # Licensed under the Apache License, Version 2.0 (the "License");
1 # you may not use this file except in compliance with the License.
2 # You may obtain a copy of the License at
3 #
4 # http://www.apache.org/licenses/LICENSE-2.0
5 #
6 # Unless required by applicable law or agreed to in writing, software
7 # distributed under the License is distributed on an "AS IS" BASIS,
8 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 # See the License for the specific language governing permissions and
10 # limitations under the License.
11
12 # log4j configuration used during build and unit tests
13
14 log4j.rootLogger=info,stdout
15 log4j.threshold=ALL
16 log4j.appender.stdout=org.apache.log4j.ConsoleAppender
17 log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
18 log4j.appender.stdout.layout.ConversionPattern=%d{ISO8601} %-5p [%t] %c{2} (%F:%M(%L)) - %m%n
0 # Licensed under the Apache License, Version 2.0 (the "License");
1 # you may not use this file except in compliance with the License.
2 # You may obtain a copy of the License at
3 #
4 # http://www.apache.org/licenses/LICENSE-2.0
5 #
6 # Unless required by applicable law or agreed to in writing, software
7 # distributed under the License is distributed on an "AS IS" BASIS,
8 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 # See the License for the specific language governing permissions and
10 # limitations under the License.
11
12 # log4j configuration used during build and unit tests
13
14 log4j.rootLogger=info,stdout
15 log4j.threshold=ALL
16 log4j.appender.stdout=org.apache.log4j.ConsoleAppender
17 log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
18 log4j.appender.stdout.layout.ConversionPattern=%d{ISO8601} %-5p [%t] %c{2} (%F:%M(%L)) - %m%n
0 # Licensed under the Apache License, Version 2.0 (the "License");
1 # you may not use this file except in compliance with the License.
2 # You may obtain a copy of the License at
3 #
4 # http://www.apache.org/licenses/LICENSE-2.0
5 #
6 # Unless required by applicable law or agreed to in writing, software
7 # distributed under the License is distributed on an "AS IS" BASIS,
8 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 # See the License for the specific language governing permissions and
10 # limitations under the License.
11
12 # log4j configuration used during build and unit tests
13
14 log4j.rootLogger=info,stdout
15 log4j.threshold=ALL
16 log4j.appender.stdout=org.apache.log4j.ConsoleAppender
17 log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
18 log4j.appender.stdout.layout.ConversionPattern=%d{ISO8601} %-5p [%t] %c{2} (%F:%M(%L)) - %m%n
0 # Licensed under the Apache License, Version 2.0 (the "License");
1 # you may not use this file except in compliance with the License.
2 # You may obtain a copy of the License at
3 #
4 # http://www.apache.org/licenses/LICENSE-2.0
5 #
6 # Unless required by applicable law or agreed to in writing, software
7 # distributed under the License is distributed on an "AS IS" BASIS,
8 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 # See the License for the specific language governing permissions and
10 # limitations under the License.
11
12 # log4j configuration used during build and unit tests
13
14 log4j.rootLogger=info,stdout
15 log4j.threshold=ALL
16 log4j.appender.stdout=org.apache.log4j.ConsoleAppender
17 log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
18 log4j.appender.stdout.layout.ConversionPattern=%d{ISO8601} %-5p [%t] %c{2} (%F:%M(%L)) - %m%n
0 # Licensed under the Apache License, Version 2.0 (the "License");
1 # you may not use this file except in compliance with the License.
2 # You may obtain a copy of the License at
3 #
4 # http://www.apache.org/licenses/LICENSE-2.0
5 #
6 # Unless required by applicable law or agreed to in writing, software
7 # distributed under the License is distributed on an "AS IS" BASIS,
8 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 # See the License for the specific language governing permissions and
10 # limitations under the License.
11
12 # log4j configuration used during build and unit tests
13
14 log4j.rootLogger=info,stdout
15 log4j.threshold=ALL
16 log4j.appender.stdout=org.apache.log4j.ConsoleAppender
17 log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
18 log4j.appender.stdout.layout.ConversionPattern=%d{ISO8601} %-5p [%t] %c{2} (%F:%M(%L)) - %m%n
0 # Licensed under the Apache License, Version 2.0 (the "License");
1 # you may not use this file except in compliance with the License.
2 # You may obtain a copy of the License at
3 #
4 # http://www.apache.org/licenses/LICENSE-2.0
5 #
6 # Unless required by applicable law or agreed to in writing, software
7 # distributed under the License is distributed on an "AS IS" BASIS,
8 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 # See the License for the specific language governing permissions and
10 # limitations under the License.
11
12 # log4j configuration used during build and unit tests
13
14 log4j.rootLogger=info,stdout
15 log4j.threshold=ALL
16 log4j.appender.stdout=org.apache.log4j.ConsoleAppender
17 log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
18 log4j.appender.stdout.layout.ConversionPattern=%d{ISO8601} %-5p [%t] %c{2} (%F:%M(%L)) - %m%n
0 # Licensed under the Apache License, Version 2.0 (the "License");
1 # you may not use this file except in compliance with the License.
2 # You may obtain a copy of the License at
3 #
4 # http://www.apache.org/licenses/LICENSE-2.0
5 #
6 # Unless required by applicable law or agreed to in writing, software
7 # distributed under the License is distributed on an "AS IS" BASIS,
8 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 # See the License for the specific language governing permissions and
10 # limitations under the License.
11
12 # log4j configuration used during build and unit tests
13
14 log4j.rootLogger=info,stdout
15 log4j.threshold=ALL
16 log4j.appender.stdout=org.apache.log4j.ConsoleAppender
17 log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
18 log4j.appender.stdout.layout.ConversionPattern=%d{ISO8601} %-5p [%t] %c{2} (%F:%M(%L)) - %m%n
0 # Licensed under the Apache License, Version 2.0 (the "License");
1 # you may not use this file except in compliance with the License.
2 # You may obtain a copy of the License at
3 #
4 # http://www.apache.org/licenses/LICENSE-2.0
5 #
6 # Unless required by applicable law or agreed to in writing, software
7 # distributed under the License is distributed on an "AS IS" BASIS,
8 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 # See the License for the specific language governing permissions and
10 # limitations under the License.
11 # log4j configuration used during build and unit tests
12
13 log4j.rootLogger=info,stdout
14 log4j.threshold=ALL
15 log4j.appender.stdout=org.apache.log4j.ConsoleAppender
16 log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
17 log4j.appender.stdout.layout.ConversionPattern=%d{ISO8601} [%t] %-5p %c{2} (%F:%M(%L)) - %m%n
18
19 log4j.logger.org.apache.hadoop.util.NativeCodeLoader=ERROR
20
21 # for debugging low level S3a operations, uncomment this line
22 # log4j.logger.org.apache.hadoop.fs.s3a=DEBUG
0 #
1 # Licensed to the Apache Software Foundation (ASF) under one or more
2 # contributor license agreements. See the NOTICE file distributed with
3 # this work for additional information regarding copyright ownership.
4 # The ASF licenses this file to You under the Apache License, Version 2.0
5 # (the "License"); you may not use this file except in compliance with
6 # the License. You may obtain a copy of the License at
7 #
8 # http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15 #
16 # log4j configuration used during build and unit tests
17
18 log4j.rootLogger=INFO,stdout
19 log4j.threshold=ALL
20 log4j.appender.stdout=org.apache.log4j.ConsoleAppender
21 log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
22 log4j.appender.stdout.layout.ConversionPattern=%d{ISO8601} %-5p [%t]: %c{2} (%F:%M(%L)) - %m%n
23
24 log4j.logger.org.apache.hadoop.fs.azure.AzureFileSystemThreadPoolExecutor=DEBUG
0 #
1 # Licensed to the Apache Software Foundation (ASF) under one
2 # or more contributor license agreements. See the NOTICE file
3 # distributed with this work for additional information
4 # regarding copyright ownership. The ASF licenses this file
5 # to you under the Apache License, Version 2.0 (the
6 # "License"); you may not use this file except in compliance
7 # with 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 # Licensed under the Apache License, Version 2.0 (the "License");
19 # you may not use this file except in compliance with the License.
20 # You may obtain a copy of the License at
21 #
22 # http://www.apache.org/licenses/LICENSE-2.0
23 #
24 # Unless required by applicable law or agreed to in writing, software
25 # distributed under the License is distributed on an "AS IS" BASIS,
26 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
27 # See the License for the specific language governing permissions and
28 # limitations under the License.
29 # log4j configuration used during build and unit tests
30
31 log4j.rootLogger=INFO,stdout
32 log4j.threshold=ALL
33 log4j.appender.stdout=org.apache.log4j.ConsoleAppender
34 log4j.appender.stdout.target=System.out
35 log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
36 log4j.appender.stdout.layout.ConversionPattern=%d{ISO8601} [%t] %-5p %c{2} (%F:%M(%L)) - %m%n
37 #log4j.appender.stdout.layout.ConversionPattern=%d{ISO8601} [%t] %-5p %c %x - %m%n"
38 #log4j.logger.org.apache.hadoop.fs.swift=DEBUG
39
40 #crank back on warnings about -1 content length GETs
41 log4j.logger.org.apache.commons.httpclient.HttpMethodBase=ERROR
0 #
1 # Licensed under the Apache License, Version 2.0 (the "License");
2 # you may not use this file except in compliance with the License.
3 # You may obtain a copy of the License at
4 #
5 # http://www.apache.org/licenses/LICENSE-2.0
6 #
7 # Unless required by applicable law or agreed to in writing, software
8 # distributed under the License is distributed on an "AS IS" BASIS,
9 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10 # See the License for the specific language governing permissions and
11 # limitations under the License. See accompanying LICENSE file.
12 #
13 log4j.appender.test=org.apache.log4j.ConsoleAppender
14 log4j.appender.test.Target=System.out
15 log4j.appender.test.layout=org.apache.log4j.PatternLayout
16 log4j.appender.test.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
17
18 log4j.logger=NONE, test
0 # Licensed under the Apache License, Version 2.0 (the "License");
1 # you may not use this file except in compliance with the License.
2 # You may obtain a copy of the License at
3 #
4 # http://www.apache.org/licenses/LICENSE-2.0
5 #
6 # Unless required by applicable law or agreed to in writing, software
7 # distributed under the License is distributed on an "AS IS" BASIS,
8 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 # See the License for the specific language governing permissions and
10 # limitations under the License.
11
12 # log4j configuration used during build and unit tests
13
14 log4j.rootLogger=info,stdout
15 log4j.threshold=ALL
16 log4j.appender.stdout=org.apache.log4j.ConsoleAppender
17 log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
18 log4j.appender.stdout.layout.ConversionPattern=%d{ISO8601} %-5p [%t] %c{2} (%F:%M(%L)) - %m%n
0 #
1 # Licensed to the Apache Software Foundation (ASF) under one
2 # or more contributor license agreements. See the NOTICE file
3 # distributed with this work for additional information
4 # regarding copyright ownership. The ASF licenses this file
5 # to you under the Apache License, Version 2.0 (the
6 # "License"); you may not use this file except in compliance
7 # with 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 # Licensed under the Apache License, Version 2.0 (the "License");
19 # you may not use this file except in compliance with the License.
20 # You may obtain a copy of the License at
21 #
22 # http://www.apache.org/licenses/LICENSE-2.0
23 #
24 # Unless required by applicable law or agreed to in writing, software
25 # distributed under the License is distributed on an "AS IS" BASIS,
26 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
27 # See the License for the specific language governing permissions and
28 # limitations under the License.
29
30 # log4j configuration used during build and unit tests
31
32 log4j.rootLogger=INFO,stdout
33 log4j.threshold=ALL
34 log4j.appender.stdout=org.apache.log4j.ConsoleAppender
35 log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
36 log4j.appender.stdout.layout.ConversionPattern=%d{ISO8601} %-5p [%t] %c{2} (%F:%M(%L)) - %m%n
0 # Licensed under the Apache License, Version 2.0 (the "License");
1 # you may not use this file except in compliance with the License.
2 # You may obtain a copy of the License at
3 #
4 # http://www.apache.org/licenses/LICENSE-2.0
5 #
6 # Unless required by applicable law or agreed to in writing, software
7 # distributed under the License is distributed on an "AS IS" BASIS,
8 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 # See the License for the specific language governing permissions and
10 # limitations under the License.
11
12 # log4j configuration used during build and unit tests
13
14 log4j.rootLogger=info,stdout
15 log4j.threshold=ALL
16 log4j.appender.stdout=org.apache.log4j.ConsoleAppender
17 log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
18 log4j.appender.stdout.layout.ConversionPattern=%d{ISO8601} %-5p [%t] %c{2} (%F:%M(%L)) - %m%n
0 # Licensed to the Apache Software Foundation (ASF) under one
1 # or more contributor license agreements. See the NOTICE file
2 # distributed with this work for additional information
3 # regarding copyright ownership. The ASF licenses this file
4 # to you under the Apache License, Version 2.0 (the
5 # "License"); you may not use this file except in compliance
6 # with the License. You may obtain a copy of the License at
7 #
8 # http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15
16 # log4j configuration used during build and unit tests
17
18 log4j.rootLogger=INFO,stdout
19 log4j.threshold=ALL
20 log4j.appender.stdout=org.apache.log4j.ConsoleAppender
21 log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
22 log4j.appender.stdout.layout.ConversionPattern=%d{ISO8601} [%t] %-5p %c{2} (%F:%M(%L)) - %m%n
23
24 log4j.appender.subprocess=org.apache.log4j.ConsoleAppender
25 log4j.appender.subprocess.layout=org.apache.log4j.PatternLayout
26 log4j.appender.subprocess.layout.ConversionPattern=[%c{1}]: %m%n
27
28 # packages under test
29 log4j.logger.org.apache.hadoop.yarn.registry=DEBUG
30 log4j.logger.org.apache.hadoop.service=DEBUG
31
32 log4j.logger.org.apache.hadoop.security.UserGroupInformation=DEBUG
33
34
35 #crank back on some noise
36 log4j.logger.org.apache.hadoop.util.NativeCodeLoader=ERROR
37 log4j.logger.org.apache.hadoop.hdfs.server.datanode.BlockPoolSliceScanner=WARN
38 log4j.logger.org.apache.hadoop.hdfs.server.blockmanagement=WARN
39 log4j.logger.org.apache.hadoop.hdfs.server.namenode.FSNamesystem.audit=WARN
40 log4j.logger.org.apache.hadoop.hdfs=WARN
41
42
43 log4j.logger.org.apache.hadoop.yarn.server.nodemanager.containermanager.monitor=WARN
44 log4j.logger.org.apache.hadoop.yarn.server.nodemanager.NodeStatusUpdaterImpl=WARN
45 log4j.logger.org.apache.zookeeper=INFO
46 log4j.logger.org.apache.zookeeper.ClientCnxn=DEBUG
47
48 log4j.logger.org.apache.hadoop.yarn.server.resourcemanager.security=WARN
49 log4j.logger.org.apache.hadoop.metrics2=ERROR
50 log4j.logger.org.apache.hadoop.util.HostsFileReader=WARN
51 log4j.logger.org.apache.hadoop.yarn.event.AsyncDispatcher=WARN
52 log4j.logger.org.apache.hadoop.security.token.delegation=WARN
53 log4j.logger.org.apache.hadoop.yarn.util.AbstractLivelinessMonitor=WARN
54 log4j.logger.org.apache.hadoop.yarn.server.nodemanager.security=WARN
55 log4j.logger.org.apache.hadoop.yarn.server.resourcemanager.RMNMInfo=WARN
56
57 # curator noise
58 log4j.logger.org.apache.curator.framework.imps=WARN
59 log4j.logger.org.apache.curator.framework.state.ConnectionStateManager=ERROR
60
61 log4j.logger.org.apache.directory.api.ldap=ERROR
62 log4j.logger.org.apache.directory.server=ERROR
0 # Licensed under the Apache License, Version 2.0 (the "License");
1 # you may not use this file except in compliance with the License.
2 # You may obtain a copy of the License at
3 #
4 # http://www.apache.org/licenses/LICENSE-2.0
5 #
6 # Unless required by applicable law or agreed to in writing, software
7 # distributed under the License is distributed on an "AS IS" BASIS,
8 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 # See the License for the specific language governing permissions and
10 # limitations under the License.
11
12 # log4j configuration used during build and unit tests
13
14 log4j.rootLogger=info,stdout
15 log4j.threshold=ALL
16 log4j.appender.stdout=org.apache.log4j.ConsoleAppender
17 log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
18 log4j.appender.stdout.layout.ConversionPattern=%d{ISO8601} %-5p [%t] %c{2} (%F:%M(%L)) - %m%n
0 # Licensed under the Apache License, Version 2.0 (the "License");
1 # you may not use this file except in compliance with the License.
2 # You may obtain a copy of the License at
3 #
4 # http://www.apache.org/licenses/LICENSE-2.0
5 #
6 # Unless required by applicable law or agreed to in writing, software
7 # distributed under the License is distributed on an "AS IS" BASIS,
8 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 # See the License for the specific language governing permissions and
10 # limitations under the License.
11
12 # log4j configuration used during build and unit tests
13
14 log4j.rootLogger=info,stdout
15 log4j.threshold=ALL
16 log4j.appender.stdout=org.apache.log4j.ConsoleAppender
17 log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
18 log4j.appender.stdout.layout.ConversionPattern=%d{ISO8601} %-5p [%t] %c{2} (%F:%M(%L)) - %m%n
0 # Licensed under the Apache License, Version 2.0 (the "License");
1 # you may not use this file except in compliance with the License.
2 # You may obtain a copy of the License at
3 #
4 # http://www.apache.org/licenses/LICENSE-2.0
5 #
6 # Unless required by applicable law or agreed to in writing, software
7 # distributed under the License is distributed on an "AS IS" BASIS,
8 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 # See the License for the specific language governing permissions and
10 # limitations under the License.
11
12 # log4j configuration used during build and unit tests
13
14 log4j.rootLogger=info,stdout
15 log4j.threshold=ALL
16 log4j.appender.stdout=org.apache.log4j.ConsoleAppender
17 log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
18 log4j.appender.stdout.layout.ConversionPattern=%d{ISO8601} %-5p [%t] %c{2} (%F:%M(%L)) - %m%n
0 # Licensed under the Apache License, Version 2.0 (the "License");
1 # you may not use this file except in compliance with the License.
2 # You may obtain a copy of the License at
3 #
4 # http://www.apache.org/licenses/LICENSE-2.0
5 #
6 # Unless required by applicable law or agreed to in writing, software
7 # distributed under the License is distributed on an "AS IS" BASIS,
8 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 # See the License for the specific language governing permissions and
10 # limitations under the License.
11
12 # log4j configuration used during build and unit tests
13
14 log4j.rootLogger=INFO,stdout
15 log4j.threshold=ALL
16 log4j.appender.stdout=org.apache.log4j.ConsoleAppender
17 log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
18 log4j.appender.stdout.layout.ConversionPattern=%d{ISO8601} %-5p [%t] %c{2} (%F:%M(%L)) - %m%n
0 # Licensed under the Apache License, Version 2.0 (the "License");
1 # you may not use this file except in compliance with the License.
2 # You may obtain a copy of the License at
3 #
4 # http://www.apache.org/licenses/LICENSE-2.0
5 #
6 # Unless required by applicable law or agreed to in writing, software
7 # distributed under the License is distributed on an "AS IS" BASIS,
8 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 # See the License for the specific language governing permissions and
10 # limitations under the License.
11
12 # log4j configuration used during build and unit tests
13
14 log4j.rootLogger=info,stdout
15 log4j.threshold=ALL
16 log4j.appender.stdout=org.apache.log4j.ConsoleAppender
17 log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
18 log4j.appender.stdout.layout.ConversionPattern=%d{ISO8601} %-5p [%t] %c{2} (%F:%M(%L)) - %m%n
0 # Licensed under the Apache License, Version 2.0 (the "License");
1 # you may not use this file except in compliance with the License.
2 # You may obtain a copy of the License at
3 #
4 # http://www.apache.org/licenses/LICENSE-2.0
5 #
6 # Unless required by applicable law or agreed to in writing, software
7 # distributed under the License is distributed on an "AS IS" BASIS,
8 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 # See the License for the specific language governing permissions and
10 # limitations under the License.
11
12 # log4j configuration used during build and unit tests
13
14 log4j.rootLogger=info,stdout
15 log4j.threshold=ALL
16 log4j.appender.stdout=org.apache.log4j.ConsoleAppender
17 log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
18 log4j.appender.stdout.layout.ConversionPattern=%d{ISO8601} %-5p [%t] %c{2} (%F:%M(%L)) - %m%n
0 ###############################################################################
1 #
2 # Log4J 1.2 Configuration.
3 #
4
5 hadoop.log.dir=target
6 hadoop.log.file=hadoop.log
7
8 log4j.rootLogger=TRACE, DRFA
9
10 #
11 # Daily Rolling File Appender
12 #
13
14 log4j.appender.DRFA=org.apache.log4j.DailyRollingFileAppender
15 log4j.appender.DRFA.File=${hadoop.log.dir}/${hadoop.log.file}
16
17 # Rollover at midnight
18 log4j.appender.DRFA.DatePattern=.yyyy-MM-dd
19
20 log4j.appender.DRFA.layout=org.apache.log4j.PatternLayout
21
22 # Pattern format: Date LogLevel LoggerName LogMessage
23 log4j.appender.DRFA.layout.ConversionPattern=%d{ISO8601} %p %c: %m%n
24 # Debugging Pattern format
25 #log4j.appender.DRFA.layout.ConversionPattern=%d{ISO8601} %-5p %c{2} (%F:%M(%L)) - %m%n
0 ###############################################################################
1 #
2 # Log4J 1.2 Configuration.
3 #
4
5 log4j.rootLogger=TRACE, NullAppender
6
7 # Null Appender
8 log4j.appender.NullAppender=org.apache.log4j.varia.NullAppender
0 ###############################################################################
1 #
2 # Log4J 1.2 Configuration.
3 #
4
5 hadoop.log.dir=target
6 hadoop.log.file=hadoop.log
7
8 log4j.rootLogger=TRACE, RFA
9
10 #
11 # Rolling File Appender - cap space usage at 5gb.
12 #
13 hadoop.log.maxfilesize=256MB
14 hadoop.log.maxbackupindex=20
15 log4j.appender.RFA=org.apache.log4j.RollingFileAppender
16 log4j.appender.RFA.File=${hadoop.log.dir}/${hadoop.log.file}
17
18 log4j.appender.RFA.MaxFileSize=${hadoop.log.maxfilesize}
19 log4j.appender.RFA.MaxBackupIndex=${hadoop.log.maxbackupindex}
20
21 log4j.appender.RFA.layout=org.apache.log4j.PatternLayout
22
23 # Pattern format: Date LogLevel LoggerName LogMessage
24 log4j.appender.RFA.layout.ConversionPattern=%d{ISO8601} %p %c: %m%n
25 # Debugging Pattern format
26 #log4j.appender.RFA.layout.ConversionPattern=%d{ISO8601} %-5p %c{2} (%F:%M(%L)) - %m%n
0 ###############################################################################
1 #
2 # Log4J 1.2 Configuration.
3 #
4
5 log4j.rootLogger=TRACE, RFA
6
7 #
8 # Rolling File Appender - cap space usage at 5gb.
9 #
10 log4j.appender.RFA=org.apache.log4j.RollingFileAppender
11 log4j.appender.RFA.File=target/hadoop.log
12
13 log4j.appender.RFA.MaxFileSize=256MB
14 log4j.appender.RFA.MaxBackupIndex=20
15
16 log4j.appender.RFA.layout=org.apache.log4j.PatternLayout
17
18 # Pattern format: Date LogLevel LoggerName LogMessage
19 log4j.appender.RFA.layout.ConversionPattern=%d{ISO8601} %p %c: %m%n
20 # Debugging Pattern format
21 #log4j.appender.RFA.layout.ConversionPattern=%d{ISO8601} %-5p %c{2} (%F:%M(%L)) - %m%n
1010 #
1111
1212 log4j.appender.Console=org.apache.log4j.ConsoleAppender
13 log4j.appender.Console.ImmediateFlush=false
1413 log4j.appender.Console.Target=System.err
1514 log4j.appender.Console.layout=org.apache.log4j.EnhancedPatternLayout
16 log4j.appender.Console.layout.ConversionPattern=%d{ISO8601} [%t][%c] %-5p: %m%n
15 log4j.appender.Console.layout.ConversionPattern=%d{ISO8601} [%t][%c] %-5p %X %x: %m%n
1716
1817 log4j.logger.com.example.foo = DEBUG
1010 #
1111
1212 log4j.appender.Console=org.apache.log4j.ConsoleAppender
13 log4j.appender.Console.ImmediateFlush=false
1413 log4j.appender.Console.Target=System.err
1514 log4j.appender.Console.layout=org.apache.log4j.HTMLLayout
15 log4j.appender.Console.layout.Title=Headline
16 log4j.appender.Console.layout.LocationInfo=true
1617
1718 log4j.logger.com.example.foo = DEBUG
1010 #
1111
1212 log4j.appender.Console=org.apache.log4j.ConsoleAppender
13 log4j.appender.Console.ImmediateFlush=false
1413 log4j.appender.Console.Target=System.err
1514 log4j.appender.Console.layout=org.apache.log4j.PatternLayout
1615 log4j.appender.Console.layout.ConversionPattern=%d{ISO8601} [%t][%c] %-5p: %m%n
1010 #
1111
1212 log4j.appender.Console=org.apache.log4j.ConsoleAppender
13 log4j.appender.Console.ImmediateFlush=false
1413 log4j.appender.Console.Target=System.err
1514 log4j.appender.Console.layout=org.apache.log4j.SimpleLayout
1615
1010 #
1111
1212 log4j.appender.Console=org.apache.log4j.ConsoleAppender
13 log4j.appender.Console.ImmediateFlush=false
1413 log4j.appender.Console.Target=System.err
1514 log4j.appender.Console.layout=org.apache.log4j.TTCCLayout
15 log4j.appender.Console.layout.ThreadPrinting=true
16 log4j.appender.Console.layout.CategoryPrefixing=false
1617
1718 log4j.logger.com.example.foo = DEBUG
1010 #
1111
1212 log4j.appender.Console=org.apache.log4j.ConsoleAppender
13 log4j.appender.Console.ImmediateFlush=false
1413 log4j.appender.Console.Target=System.err
15 log4j.appender.Console.layout=org.apache.log4j.XMLLayout
14 log4j.appender.Console.layout=org.apache.log4j.xml.XMLLayout
15 log4j.appender.Console.layout.LocationInfo=true
16 log4j.appender.Console.layout.Properties=false
1617
1718 log4j.logger.com.example.foo = DEBUG
0 ###############################################################################
1 #
2 # Log4J 1.2 Configuration.
3 #
4
5 log4j.rootLogger=TRACE, File
6
7 ##############################################################################
8 #
9 # The Console log
10 #
11
12 log4j.appender.File=org.apache.log4j.FileAppender
13 log4j.appender.File.File=target/mylog.txt
14 log4j.appender.File.layout=org.apache.log4j.SimpleLayout
15
16 log4j.logger.com.example.foo = DEBUG
0 ###############################################################################
1 #
2 # Log4J 1.2 Configuration.
3 #
4
5 hadoop.log.file=hadoop.log
6
7 log4j.rootLogger=TRACE, RFA
8
9 #
10 # Rolling File Appender
11 #
12 log4j.appender.RFA=org.apache.log4j.RollingFileAppender
13 log4j.appender.RFA.File=${java.io.tmpdir}/${hadoop.log.file}
0 ###############################################################################
1 #
2 # Log4J 1.2 Configuration.
3 #
4
5 hadoop.log.dir=${java.io.tmpdir}
6 hadoop.log.file=hadoop.log
7
8 log4j.rootLogger=TRACE, RFA
9
10 #
11 # Rolling File Appender
12 #
13 log4j.appender.RFA=org.apache.log4j.RollingFileAppender
14 log4j.appender.RFA.File=${hadoop.log.dir}/${hadoop.log.file}
0 #
1 # Licensed to the Apache Software Foundation (ASF) under one or more
2 # contributor license agreements. See the NOTICE file distributed with
3 # this work for additional information regarding copyright ownership.
4 # The ASF licenses this file to You under the Apache License, Version 2.0
5 # (the "License"); you may not use this file except in compliance with
6 # the License. You may obtain a copy of the License at
7 #
8 # http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15 #
16
17 # Set everything to be logged to the file target/unit-tests.log
18 log4j.rootCategory=INFO, file
19 log4j.appender.file=org.apache.log4j.FileAppender
20 log4j.appender.file.append=true
21 log4j.appender.file.file=R/target/unit-tests.log
22 log4j.appender.file.layout=org.apache.log4j.PatternLayout
23 log4j.appender.file.layout.ConversionPattern=%d{yy/MM/dd HH:mm:ss.SSS} %t %p %c{1}: %m%n
24
25 # Ignore messages below warning level from Jetty, because it's a bit verbose
26 log4j.logger.org.eclipse.jetty=WARN
27 org.eclipse.jetty.LEVEL=WARN
0 #
1 # Licensed to the Apache Software Foundation (ASF) under one or more
2 # contributor license agreements. See the NOTICE file distributed with
3 # this work for additional information regarding copyright ownership.
4 # The ASF licenses this file to You under the Apache License, Version 2.0
5 # (the "License"); you may not use this file except in compliance with
6 # the License. You may obtain a copy of the License at
7 #
8 # http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15 #
16
17 # Set everything to be logged to the file target/unit-tests.log
18 log4j.rootCategory=DEBUG, file
19 log4j.appender.file=org.apache.log4j.FileAppender
20 log4j.appender.file.append=true
21 log4j.appender.file.file=target/unit-tests.log
22 log4j.appender.file.layout=org.apache.log4j.PatternLayout
23 log4j.appender.file.layout.ConversionPattern=%d{yy/MM/dd HH:mm:ss.SSS} %t %p %c{1}: %m%n
24
25 # Silence verbose logs from 3rd-party libraries.
26 log4j.logger.io.netty=INFO
0 #
1 # Licensed to the Apache Software Foundation (ASF) under one or more
2 # contributor license agreements. See the NOTICE file distributed with
3 # this work for additional information regarding copyright ownership.
4 # The ASF licenses this file to You under the Apache License, Version 2.0
5 # (the "License"); you may not use this file except in compliance with
6 # the License. You may obtain a copy of the License at
7 #
8 # http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15 #
16
17 # Set everything to be logged to the file target/unit-tests.log
18 log4j.rootCategory=DEBUG, file
19 log4j.appender.file=org.apache.log4j.FileAppender
20 log4j.appender.file.append=true
21 log4j.appender.file.file=target/unit-tests.log
22 log4j.appender.file.layout=org.apache.log4j.PatternLayout
23 log4j.appender.file.layout.ConversionPattern=%d{yy/MM/dd HH:mm:ss.SSS} %t %p %c{1}: %m%n
0 #
1 # Licensed to the Apache Software Foundation (ASF) under one or more
2 # contributor license agreements. See the NOTICE file distributed with
3 # this work for additional information regarding copyright ownership.
4 # The ASF licenses this file to You under the Apache License, Version 2.0
5 # (the "License"); you may not use this file except in compliance with
6 # the License. You may obtain a copy of the License at
7 #
8 # http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15 #
16
17 # Set everything to be logged to the file target/unit-tests.log
18 test.appender=file
19 log4j.rootCategory=INFO, ${test.appender}
20 log4j.appender.file=org.apache.log4j.FileAppender
21 log4j.appender.file.append=true
22 log4j.appender.file.file=target/unit-tests.log
23 log4j.appender.file.layout=org.apache.log4j.PatternLayout
24 log4j.appender.file.layout.ConversionPattern=%d{yy/MM/dd HH:mm:ss.SSS} %t %p %c{1}: %m%n
25
26 # Tests that launch java subprocesses can set the "test.appender" system property to
27 # "console" to avoid having the child process's logs overwrite the unit test's
28 # log file.
29 log4j.appender.console=org.apache.log4j.ConsoleAppender
30 log4j.appender.console.target=System.err
31 log4j.appender.console.layout=org.apache.log4j.PatternLayout
32 log4j.appender.console.layout.ConversionPattern=%t: %m%n
33
34 # Ignore messages below warning level from Jetty, because it's a bit verbose
35 log4j.logger.org.spark_project.jetty=WARN
0 #
1 # Licensed to the Apache Software Foundation (ASF) under one or more
2 # contributor license agreements. See the NOTICE file distributed with
3 # this work for additional information regarding copyright ownership.
4 # The ASF licenses this file to You under the Apache License, Version 2.0
5 # (the "License"); you may not use this file except in compliance with
6 # the License. You may obtain a copy of the License at
7 #
8 # http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15 #
16
17 # Set everything to be logged to the file target/unit-tests.log
18 log4j.rootCategory=INFO, file
19 log4j.appender.file=org.apache.log4j.FileAppender
20 log4j.appender.file.append=true
21 log4j.appender.file.file=target/unit-tests.log
22 log4j.appender.file.layout=org.apache.log4j.PatternLayout
23 log4j.appender.file.layout.ConversionPattern=%d{yy/MM/dd HH:mm:ss.SSS} %t %p %c{1}: %m%n
24
25 # Ignore messages below warning level from Jetty, because it's a bit verbose
26 log4j.logger.org.spark_project.jetty=WARN
27
0 #
1 # Licensed to the Apache Software Foundation (ASF) under one or more
2 # contributor license agreements. See the NOTICE file distributed with
3 # this work for additional information regarding copyright ownership.
4 # The ASF licenses this file to You under the Apache License, Version 2.0
5 # (the "License"); you may not use this file except in compliance with
6 # the License. You may obtain a copy of the License at
7 #
8 # http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15 #
16
17 # Set everything to be logged to the file streaming/target/unit-tests.log
18 log4j.rootCategory=INFO, file
19 log4j.appender.file=org.apache.log4j.FileAppender
20 log4j.appender.file.append=true
21 log4j.appender.file.file=target/unit-tests.log
22 log4j.appender.file.layout=org.apache.log4j.PatternLayout
23 log4j.appender.file.layout.ConversionPattern=%d{yy/MM/dd HH:mm:ss.SSS} %t %p %c{1}: %m%n
24
25 # Ignore messages below warning level from Jetty, because it's a bit verbose
26 log4j.logger.org.spark_project.jetty=WARN
27
0 #
1 # Licensed to the Apache Software Foundation (ASF) under one or more
2 # contributor license agreements. See the NOTICE file distributed with
3 # this work for additional information regarding copyright ownership.
4 # The ASF licenses this file to You under the Apache License, Version 2.0
5 # (the "License"); you may not use this file except in compliance with
6 # the License. You may obtain a copy of the License at
7 #
8 # http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15 #
16
17 # Set everything to be logged to the file target/unit-tests.log
18 log4j.rootCategory=INFO, file
19 log4j.appender.file=org.apache.log4j.FileAppender
20 log4j.appender.file.append=true
21 log4j.appender.file.file=target/unit-tests.log
22 log4j.appender.file.layout=org.apache.log4j.PatternLayout
23 log4j.appender.file.layout.ConversionPattern=%d{yy/MM/dd HH:mm:ss.SSS} %t %p %c{1}: %m%n
24
25 # Ignore messages below warning level from Jetty, because it's a bit verbose
26 log4j.logger.org.spark_project.jetty=WARN
0 #
1 # Licensed to the Apache Software Foundation (ASF) under one or more
2 # contributor license agreements. See the NOTICE file distributed with
3 # this work for additional information regarding copyright ownership.
4 # The ASF licenses this file to You under the Apache License, Version 2.0
5 # (the "License"); you may not use this file except in compliance with
6 # the License. You may obtain a copy of the License at
7 #
8 # http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15 #
16
17 # Set everything to be logged to the file target/unit-tests.log
18 log4j.rootCategory=INFO, file
19 log4j.appender.file=org.apache.log4j.FileAppender
20 log4j.appender.file.append=true
21 log4j.appender.file.file=target/unit-tests.log
22 log4j.appender.file.layout=org.apache.log4j.PatternLayout
23 log4j.appender.file.layout.ConversionPattern=%d{yy/MM/dd HH:mm:ss.SSS} %t %p %c{1}: %m%n
24
25 # Ignore messages below warning level from Jetty, because it's a bit verbose
26 log4j.logger.org.spark-project.jetty=WARN
27
0 #
1 # Licensed to the Apache Software Foundation (ASF) under one or more
2 # contributor license agreements. See the NOTICE file distributed with
3 # this work for additional information regarding copyright ownership.
4 # The ASF licenses this file to You under the Apache License, Version 2.0
5 # (the "License"); you may not use this file except in compliance with
6 # the License. You may obtain a copy of the License at
7 #
8 # http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15 #
16
17 # Set everything to be logged to the file target/unit-tests.log
18 log4j.rootCategory=INFO, file
19 log4j.appender.file=org.apache.log4j.FileAppender
20 log4j.appender.file.append=true
21 log4j.appender.file.file=target/unit-tests.log
22 log4j.appender.file.layout=org.apache.log4j.PatternLayout
23 log4j.appender.file.layout.ConversionPattern=%d{yy/MM/dd HH:mm:ss.SSS} %t %p %c{1}: %m%n
24
25 # Ignore messages below warning level from Jetty, because it's a bit verbose
26 log4j.logger.org.spark_project.jetty=WARN
27
0 #
1 # Licensed to the Apache Software Foundation (ASF) under one or more
2 # contributor license agreements. See the NOTICE file distributed with
3 # this work for additional information regarding copyright ownership.
4 # The ASF licenses this file to You under the Apache License, Version 2.0
5 # (the "License"); you may not use this file except in compliance with
6 # the License. You may obtain a copy of the License at
7 #
8 # http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15 #
16
17 log4j.rootCategory=WARN, console
18
19 # File appender
20 log4j.appender.file=org.apache.log4j.FileAppender
21 log4j.appender.file.append=false
22 log4j.appender.file.file=target/unit-tests.log
23 log4j.appender.file.layout=org.apache.log4j.PatternLayout
24 log4j.appender.file.layout.ConversionPattern=%d{yy/MM/dd HH:mm:ss.SSS} %p %c{1}: %m%n
25
26 # Console appender
27 log4j.appender.console=org.apache.log4j.ConsoleAppender
28 log4j.appender.console.target=System.out
29 log4j.appender.console.layout=org.apache.log4j.PatternLayout
30 log4j.appender.console.layout.ConversionPattern=%d{yy/MM/dd HH:mm:ss} %p %c{1}: %m%n
31
32 # Settings to quiet third party logs that are too verbose
33 log4j.logger.org.spark_project.jetty=WARN
34 log4j.logger.org.spark_project.jetty.util.component.AbstractLifeCycle=ERROR
35 log4j.logger.org.apache.spark.repl.SparkIMain$exprTyper=INFO
36 log4j.logger.org.apache.spark.repl.SparkILoop$SparkILoopInterpreter=INFO
0 #
1 # Licensed to the Apache Software Foundation (ASF) under one or more
2 # contributor license agreements. See the NOTICE file distributed with
3 # this work for additional information regarding copyright ownership.
4 # The ASF licenses this file to You under the Apache License, Version 2.0
5 # (the "License"); you may not use this file except in compliance with
6 # the License. You may obtain a copy of the License at
7 #
8 # http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15 #
16
17 # Set everything to be logged to the file target/unit-tests.log
18 log4j.rootCategory=INFO, file
19 log4j.appender.file=org.apache.log4j.FileAppender
20 log4j.appender.file.append=true
21 log4j.appender.file.file=target/unit-tests.log
22 log4j.appender.file.layout=org.apache.log4j.PatternLayout
23 log4j.appender.file.layout.ConversionPattern=%d{yy/MM/dd HH:mm:ss.SSS} %t %p %c{1}: %m%n
24
25 # Ignore messages below warning level from Jetty, because it's a bit verbose
26 log4j.logger.org.spark_project.jetty=WARN
0 #
1 # Licensed to the Apache Software Foundation (ASF) under one or more
2 # contributor license agreements. See the NOTICE file distributed with
3 # this work for additional information regarding copyright ownership.
4 # The ASF licenses this file to You under the Apache License, Version 2.0
5 # (the "License"); you may not use this file except in compliance with
6 # the License. You may obtain a copy of the License at
7 #
8 # http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15 #
16
17 # Set everything to be logged to the file target/unit-tests.log
18 log4j.rootCategory=INFO, file
19 log4j.appender.file=org.apache.log4j.FileAppender
20 log4j.appender.file.append=true
21 log4j.appender.file.file=target/unit-tests.log
22 log4j.appender.file.layout=org.apache.log4j.PatternLayout
23 log4j.appender.file.layout.ConversionPattern=%d{yy/MM/dd HH:mm:ss.SSS} %t %p %c{1}: %m%n
24
25 # Ignore messages below warning level from Jetty, because it's a bit verbose
26 log4j.logger.org.spark_project.jetty=WARN
0 #
1 # Licensed to the Apache Software Foundation (ASF) under one or more
2 # contributor license agreements. See the NOTICE file distributed with
3 # this work for additional information regarding copyright ownership.
4 # The ASF licenses this file to You under the Apache License, Version 2.0
5 # (the "License"); you may not use this file except in compliance with
6 # the License. You may obtain a copy of the License at
7 #
8 # http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15 #
16
17 # Set everything to be logged to the file core/target/unit-tests.log
18 test.appender=file
19 log4j.rootCategory=INFO, ${test.appender}
20 log4j.appender.file=org.apache.log4j.FileAppender
21 log4j.appender.file.append=false
22 log4j.appender.file.file=target/unit-tests.log
23 log4j.appender.file.layout=org.apache.log4j.PatternLayout
24 log4j.appender.file.layout.ConversionPattern=%d{yy/MM/dd HH:mm:ss.SSS} %t %p %c{1}: %m%n
25
26 log4j.appender.childproc=org.apache.log4j.ConsoleAppender
27 log4j.appender.childproc.target=System.err
28 log4j.appender.childproc.layout=org.apache.log4j.PatternLayout
29 log4j.appender.childproc.layout.ConversionPattern=%t: %m%n
30
31 # Ignore messages below warning level from Jetty, because it's a bit verbose
32 log4j.logger.org.spark_project.jetty=WARN
0 #
1 # Licensed to the Apache Software Foundation (ASF) under one or more
2 # contributor license agreements. See the NOTICE file distributed with
3 # this work for additional information regarding copyright ownership.
4 # The ASF licenses this file to You under the Apache License, Version 2.0
5 # (the "License"); you may not use this file except in compliance with
6 # the License. You may obtain a copy of the License at
7 #
8 # http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15 #
16
17 # Set everything to be logged to the file target/unit-tests.log
18 log4j.rootCategory=INFO, file
19 log4j.appender.file=org.apache.log4j.FileAppender
20 log4j.appender.file.append=true
21 log4j.appender.file.file=target/unit-tests.log
22 log4j.appender.file.layout=org.apache.log4j.PatternLayout
23 log4j.appender.file.layout.ConversionPattern=%d{yy/MM/dd HH:mm:ss.SSS} %t %p %c{1}: %m%n
24
25 # Ignore messages below warning level from Jetty, because it's a bit verbose
26 log4j.logger.org.spark_project.jetty=WARN
27
0 #
1 # Licensed to the Apache Software Foundation (ASF) under one or more
2 # contributor license agreements. See the NOTICE file distributed with
3 # this work for additional information regarding copyright ownership.
4 # The ASF licenses this file to You under the Apache License, Version 2.0
5 # (the "License"); you may not use this file except in compliance with
6 # the License. You may obtain a copy of the License at
7 #
8 # http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15 #
16
17 # Set everything to be logged to the target/unit-tests.log
18 log4j.rootCategory=INFO, file
19 log4j.appender.file=org.apache.log4j.FileAppender
20 log4j.appender.file.append=true
21 log4j.appender.file.file=target/unit-tests.log
22 log4j.appender.file.layout=org.apache.log4j.PatternLayout
23 log4j.appender.file.layout.ConversionPattern=%d{yy/MM/dd HH:mm:ss.SSS} %t %p %c{1}: %m%n
24
25 # Ignore messages below warning level from Jetty, because it's a bit verbose
26 log4j.logger.org.spark_project.jetty=WARN
0 #
1 # Licensed to the Apache Software Foundation (ASF) under one or more
2 # contributor license agreements. See the NOTICE file distributed with
3 # this work for additional information regarding copyright ownership.
4 # The ASF licenses this file to You under the Apache License, Version 2.0
5 # (the "License"); you may not use this file except in compliance with
6 # the License. You may obtain a copy of the License at
7 #
8 # http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15 #
16
17 # Set everything to be logged to the file target/unit-tests.log
18 log4j.rootCategory=INFO, file
19 log4j.appender.file=org.apache.log4j.FileAppender
20 log4j.appender.file.append=true
21 log4j.appender.file.file=target/unit-tests.log
22 log4j.appender.file.layout=org.apache.log4j.PatternLayout
23 log4j.appender.file.layout.ConversionPattern=%d{yy/MM/dd HH:mm:ss.SSS} %t %p %c{1}: %m%n
24
25 # Ignore messages below warning level from Jetty, because it's a bit verbose
26 log4j.logger.org.spark_project.jetty=WARN
0 #
1 # Licensed to the Apache Software Foundation (ASF) under one or more
2 # contributor license agreements. See the NOTICE file distributed with
3 # this work for additional information regarding copyright ownership.
4 # The ASF licenses this file to You under the Apache License, Version 2.0
5 # (the "License"); you may not use this file except in compliance with
6 # the License. You may obtain a copy of the License at
7 #
8 # http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15 #
16
17 # Set everything to be logged to the file core/target/unit-tests.log
18 log4j.rootLogger=INFO, CA, FA
19
20 #Console Appender
21 log4j.appender.CA=org.apache.log4j.ConsoleAppender
22 log4j.appender.CA.layout=org.apache.log4j.PatternLayout
23 log4j.appender.CA.layout.ConversionPattern=%d{HH:mm:ss.SSS} %p %c: %m%n
24 log4j.appender.CA.Threshold = WARN
25 log4j.appender.CA.follow = true
26
27
28 #File Appender
29 log4j.appender.FA=org.apache.log4j.FileAppender
30 log4j.appender.FA.append=false
31 log4j.appender.FA.file=target/unit-tests.log
32 log4j.appender.FA.layout=org.apache.log4j.PatternLayout
33 log4j.appender.FA.layout.ConversionPattern=%d{HH:mm:ss.SSS} %t %p %c{1}: %m%n
34
35 # Set the logger level of File Appender to WARN
36 log4j.appender.FA.Threshold = INFO
37
38 # Some packages are noisy for no good reason.
39 log4j.additivity.org.apache.parquet.hadoop.ParquetRecordReader=false
40 log4j.logger.org.apache.parquet.hadoop.ParquetRecordReader=OFF
41
42 log4j.additivity.org.apache.parquet.hadoop.ParquetOutputCommitter=false
43 log4j.logger.org.apache.parquet.hadoop.ParquetOutputCommitter=OFF
44
45 log4j.additivity.org.apache.hadoop.hive.serde2.lazy.LazyStruct=false
46 log4j.logger.org.apache.hadoop.hive.serde2.lazy.LazyStruct=OFF
47
48 log4j.additivity.org.apache.hadoop.hive.metastore.RetryingHMSHandler=false
49 log4j.logger.org.apache.hadoop.hive.metastore.RetryingHMSHandler=OFF
50
51 log4j.additivity.hive.ql.metadata.Hive=false
52 log4j.logger.hive.ql.metadata.Hive=OFF
53
54 # Parquet related logging
55 log4j.logger.org.apache.parquet.hadoop=WARN
56 log4j.logger.org.apache.spark.sql.parquet=INFO
0 #
1 # Licensed to the Apache Software Foundation (ASF) under one or more
2 # contributor license agreements. See the NOTICE file distributed with
3 # this work for additional information regarding copyright ownership.
4 # The ASF licenses this file to You under the Apache License, Version 2.0
5 # (the "License"); you may not use this file except in compliance with
6 # the License. You may obtain a copy of the License at
7 #
8 # http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15 #
16
17 # Set everything to be logged to the file core/target/unit-tests.log
18 log4j.rootLogger=DEBUG, CA, FA
19
20 #Console Appender
21 log4j.appender.CA=org.apache.log4j.ConsoleAppender
22 log4j.appender.CA.layout=org.apache.log4j.PatternLayout
23 log4j.appender.CA.layout.ConversionPattern=%d{HH:mm:ss.SSS} %p %c: %m%n
24 log4j.appender.CA.Threshold = WARN
25
26
27 #File Appender
28 log4j.appender.FA=org.apache.log4j.FileAppender
29 log4j.appender.FA.append=false
30 log4j.appender.FA.file=target/unit-tests.log
31 log4j.appender.FA.layout=org.apache.log4j.PatternLayout
32 log4j.appender.FA.layout.ConversionPattern=%d{HH:mm:ss.SSS} %t %p %c{1}: %m%n
33
34 # Set the logger level of File Appender to WARN
35 log4j.appender.FA.Threshold = DEBUG
36
37 # Some packages are noisy for no good reason.
38 log4j.additivity.org.apache.hadoop.hive.serde2.lazy.LazyStruct=false
39 log4j.logger.org.apache.hadoop.hive.serde2.lazy.LazyStruct=OFF
40
41 log4j.additivity.org.apache.hadoop.hive.metastore.RetryingHMSHandler=false
42 log4j.logger.org.apache.hadoop.hive.metastore.RetryingHMSHandler=OFF
43
44 log4j.additivity.hive.log=false
45 log4j.logger.hive.log=OFF
46
47 log4j.additivity.parquet.hadoop.ParquetRecordReader=false
48 log4j.logger.parquet.hadoop.ParquetRecordReader=OFF
49
50 log4j.additivity.org.apache.parquet.hadoop.ParquetRecordReader=false
51 log4j.logger.org.apache.parquet.hadoop.ParquetRecordReader=OFF
52
53 log4j.additivity.org.apache.parquet.hadoop.ParquetOutputCommitter=false
54 log4j.logger.org.apache.parquet.hadoop.ParquetOutputCommitter=OFF
55
56 log4j.additivity.hive.ql.metadata.Hive=false
57 log4j.logger.hive.ql.metadata.Hive=OFF
58
59 log4j.additivity.org.apache.hadoop.hive.ql.io.RCFile=false
60 log4j.logger.org.apache.hadoop.hive.ql.io.RCFile=ERROR
0 #
1 # Licensed to the Apache Software Foundation (ASF) under one or more
2 # contributor license agreements. See the NOTICE file distributed with
3 # this work for additional information regarding copyright ownership.
4 # The ASF licenses this file to You under the Apache License, Version 2.0
5 # (the "License"); you may not use this file except in compliance with
6 # the License. You may obtain a copy of the License at
7 #
8 # http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15 #
16
17 # Set everything to be logged to the file target/unit-tests.log
18 log4j.rootCategory=INFO, file
19 log4j.appender.file=org.apache.log4j.FileAppender
20 log4j.appender.file.append=true
21 log4j.appender.file.file=target/unit-tests.log
22 log4j.appender.file.layout=org.apache.log4j.PatternLayout
23 log4j.appender.file.layout.ConversionPattern=%d{yy/MM/dd HH:mm:ss.SSS} %t %p %c{1}: %m%n
24
25 # Ignore messages below warning level from Jetty, because it's a bit verbose
26 log4j.logger.org.spark_project.jetty=WARN
27
0 #
1 # Licensed to the Apache Software Foundation (ASF) under one or more
2 # contributor license agreements. See the NOTICE file distributed with
3 # this work for additional information regarding copyright ownership.
4 # The ASF licenses this file to You under the Apache License, Version 2.0
5 # (the "License"); you may not use this file except in compliance with
6 # the License. You may obtain a copy of the License at
7 #
8 # http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15 #
16
17 # Set everything to be logged to the file target/unit-tests.log
18 log4j.rootCategory=DEBUG, file
19 log4j.appender.file=org.apache.log4j.FileAppender
20 log4j.appender.file.append=true
21 log4j.appender.file.file=target/unit-tests.log
22 log4j.appender.file.layout=org.apache.log4j.PatternLayout
23 log4j.appender.file.layout.ConversionPattern=%d{yy/MM/dd HH:mm:ss.SSS} %t %p %c{1}: %m%n
24
25 # Ignore messages below warning level from a few verbose libraries.
26 log4j.logger.com.sun.jersey=WARN
27 log4j.logger.org.apache.hadoop=WARN
28 log4j.logger.org.eclipse.jetty=WARN
29 log4j.logger.org.mortbay=WARN
30 log4j.logger.org.spark_project.jetty=WARN
+0
-5
log4j-api/.gitignore less more
0 /.settings/
1 /target/
2 /.classpath
3 /.project
4 /felix-cache/
1919 <parent>
2020 <groupId>org.apache.logging.log4j</groupId>
2121 <artifactId>log4j</artifactId>
22 <version>2.6.2</version>
22 <version>2.7</version>
2323 <relativePath>../</relativePath>
2424 </parent>
2525 <artifactId>log4j-api</artifactId>
2626 * try (final CloseableThreadContext.Instance ignored = CloseableThreadContext.put(key1, value1).put(key2, value2)) {
2727 * callSomeMethodThatLogsALot();
2828 *
29 * // key1 and key2 are automatically removed from the ThreadContext map when done
29 * // Entries for key1 and key2 are automatically removed from the ThreadContext map when done.
3030 * }
3131 * </pre>
3232 *
27122712 /**
27132713 * Logs a message with parameters at the specified level.
27142714 *
2715 * @param level the logging level
27152716 * @param marker the marker data specific to this log statement
27162717 * @param message the message to log; the format depends on the message factory.
27172718 * @param p0 parameter to the message.
27212722 /**
27222723 * Logs a message with parameters at the specified level.
27232724 *
2725 * @param level the logging level
27242726 * @param marker the marker data specific to this log statement
27252727 * @param message the message to log; the format depends on the message factory.
27262728 * @param p0 parameter to the message.
27312733 /**
27322734 * Logs a message with parameters at the specified level.
27332735 *
2736 * @param level the logging level
27342737 * @param marker the marker data specific to this log statement
27352738 * @param message the message to log; the format depends on the message factory.
27362739 * @param p0 parameter to the message.
27422745 /**
27432746 * Logs a message with parameters at the specified level.
27442747 *
2748 * @param level the logging level
27452749 * @param marker the marker data specific to this log statement
27462750 * @param message the message to log; the format depends on the message factory.
27472751 * @param p0 parameter to the message.
27542758 /**
27552759 * Logs a message with parameters at the specified level.
27562760 *
2761 * @param level the logging level
27572762 * @param marker the marker data specific to this log statement
27582763 * @param message the message to log; the format depends on the message factory.
27592764 * @param p0 parameter to the message.
27672772 /**
27682773 * Logs a message with parameters at the specified level.
27692774 *
2775 * @param level the logging level
27702776 * @param marker the marker data specific to this log statement
27712777 * @param message the message to log; the format depends on the message factory.
27722778 * @param p0 parameter to the message.
27812787 /**
27822788 * Logs a message with parameters at the specified level.
27832789 *
2790 * @param level the logging level
27842791 * @param marker the marker data specific to this log statement
27852792 * @param message the message to log; the format depends on the message factory.
27862793 * @param p0 parameter to the message.
27972804 /**
27982805 * Logs a message with parameters at the specified level.
27992806 *
2807 * @param level the logging level
28002808 * @param marker the marker data specific to this log statement
28012809 * @param message the message to log; the format depends on the message factory.
28022810 * @param p0 parameter to the message.
28142822 /**
28152823 * Logs a message with parameters at the specified level.
28162824 *
2825 * @param level the logging level
28172826 * @param marker the marker data specific to this log statement
28182827 * @param message the message to log; the format depends on the message factory.
28192828 * @param p0 parameter to the message.
28322841 /**
28332842 * Logs a message with parameters at the specified level.
28342843 *
2844 * @param level the logging level
28352845 * @param marker the marker data specific to this log statement
28362846 * @param message the message to log; the format depends on the message factory.
28372847 * @param p0 parameter to the message.
28512861 /**
28522862 * Logs a message with parameters at the specified level.
28532863 *
2864 * @param level the logging level
28542865 * @param message the message to log; the format depends on the message factory.
28552866 * @param p0 parameter to the message.
28562867 */
28592870 /**
28602871 * Logs a message with parameters at the specified level.
28612872 *
2873 * @param level the logging level
28622874 * @param message the message to log; the format depends on the message factory.
28632875 * @param p0 parameter to the message.
28642876 * @param p1 parameter to the message.
28682880 /**
28692881 * Logs a message with parameters at the specified level.
28702882 *
2883 * @param level the logging level
28712884 * @param message the message to log; the format depends on the message factory.
28722885 * @param p0 parameter to the message.
28732886 * @param p1 parameter to the message.
28782891 /**
28792892 * Logs a message with parameters at the specified level.
28802893 *
2894 * @param level the logging level
28812895 * @param message the message to log; the format depends on the message factory.
28822896 * @param p0 parameter to the message.
28832897 * @param p1 parameter to the message.
28892903 /**
28902904 * Logs a message with parameters at the specified level.
28912905 *
2906 * @param level the logging level
28922907 * @param message the message to log; the format depends on the message factory.
28932908 * @param p0 parameter to the message.
28942909 * @param p1 parameter to the message.
29012916 /**
29022917 * Logs a message with parameters at the specified level.
29032918 *
2919 * @param level the logging level
29042920 * @param message the message to log; the format depends on the message factory.
29052921 * @param p0 parameter to the message.
29062922 * @param p1 parameter to the message.
29142930 /**
29152931 * Logs a message with parameters at the specified level.
29162932 *
2933 * @param level the logging level
29172934 * @param message the message to log; the format depends on the message factory.
29182935 * @param p0 parameter to the message.
29192936 * @param p1 parameter to the message.
29282945 /**
29292946 * Logs a message with parameters at the specified level.
29302947 *
2948 * @param level the logging level
29312949 * @param message the message to log; the format depends on the message factory.
29322950 * @param p0 parameter to the message.
29332951 * @param p1 parameter to the message.
29432961 /**
29442962 * Logs a message with parameters at the specified level.
29452963 *
2964 * @param level the logging level
29462965 * @param message the message to log; the format depends on the message factory.
29472966 * @param p0 parameter to the message.
29482967 * @param p1 parameter to the message.
29602979 /**
29612980 * Logs a message with parameters at the specified level.
29622981 *
2982 * @param level the logging level
29632983 * @param message the message to log; the format depends on the message factory.
29642984 * @param p0 parameter to the message.
29652985 * @param p1 parameter to the message.
8181 if (parentMarker == null) {
8282 throw new IllegalArgumentException("Parent Marker " + parent + " has not been defined");
8383 }
84 @SuppressWarnings("deprecation")
85 final Marker marker = getMarker(name, parentMarker);
86 return marker;
84 return getMarker(name, parentMarker);
8785 }
8886
8987 /**
2828 import org.apache.logging.log4j.message.ParameterizedMessage;
2929 import org.apache.logging.log4j.spi.DefaultThreadContextMap;
3030 import org.apache.logging.log4j.spi.DefaultThreadContextStack;
31 import org.apache.logging.log4j.spi.Provider;
31 import org.apache.logging.log4j.spi.NoOpThreadContextMap;
3232 import org.apache.logging.log4j.spi.ThreadContextMap;
33 import org.apache.logging.log4j.spi.ThreadContextMap2;
34 import org.apache.logging.log4j.spi.ThreadContextMapFactory;
3335 import org.apache.logging.log4j.spi.ThreadContextStack;
3436 import org.apache.logging.log4j.status.StatusLogger;
3537 import org.apache.logging.log4j.util.PropertiesUtil;
36 import org.apache.logging.log4j.util.ProviderUtil;
3738
3839 /**
3940 * The ThreadContext allows applications to store information either in a Map or a Stack.
148149
149150 /**
150151 * An empty iterator. Since Java 1.7 added the Collections.emptyIterator() method, we have to make do.
151 *
152 *
152153 * @param <E> the type of the empty iterator
153154 */
154155 private static class EmptyIterator<E> implements Iterator<E> {
187188 private static final String DISABLE_MAP = "disableThreadContextMap";
188189 private static final String DISABLE_STACK = "disableThreadContextStack";
189190 private static final String DISABLE_ALL = "disableThreadContext";
190 private static final String THREAD_CONTEXT_KEY = "log4j2.threadContextMap";
191191
192192 private static boolean disableAll;
193193 private static boolean useMap;
215215 useMap = !(managerProps.getBooleanProperty(DISABLE_MAP) || disableAll);
216216
217217 contextStack = new DefaultThreadContextStack(useStack);
218 final String threadContextMapName = managerProps.getStringProperty(THREAD_CONTEXT_KEY);
219 final ClassLoader cl = ProviderUtil.findClassLoader();
220 if (threadContextMapName != null) {
221 try {
222 final Class<?> clazz = cl.loadClass(threadContextMapName);
223 if (ThreadContextMap.class.isAssignableFrom(clazz)) {
224 contextMap = (ThreadContextMap) clazz.newInstance();
225 }
226 } catch (final ClassNotFoundException cnfe) {
227 LOGGER.error("Unable to locate configured ThreadContextMap {}", threadContextMapName);
228 } catch (final Exception ex) {
229 LOGGER.error("Unable to create configured ThreadContextMap {}", threadContextMapName, ex);
230 }
231 }
232 if (contextMap == null && ProviderUtil.hasProviders()) {
233 final String factoryClassName = LogManager.getFactory().getClass().getName();
234 for (final Provider provider : ProviderUtil.getProviders()) {
235 if (factoryClassName.equals(provider.getClassName())) {
236 final Class<? extends ThreadContextMap> clazz = provider.loadThreadContextMap();
237 if (clazz != null) {
238 try {
239 contextMap = clazz.newInstance();
240 break;
241 } catch (final Exception e) {
242 LOGGER.error("Unable to locate or load configured ThreadContextMap {}",
243 provider.getThreadContextMap(), e);
244 contextMap = new DefaultThreadContextMap(useMap);
245 }
246 }
247 }
248 }
249 }
250 if (contextMap == null) {
251 contextMap = new DefaultThreadContextMap(useMap);
218 if (!useMap) {
219 contextMap = new NoOpThreadContextMap();
220 } else {
221 contextMap = ThreadContextMapFactory.createThreadContextMap();
252222 }
253223 }
254224
259229 * <p>
260230 * If the current thread does not have a context map it is created as a side effect.
261231 * </p>
262 *
232 *
263233 * @param key The key name.
264234 * @param value The key value.
265235 */
268238 }
269239
270240 /**
241 * Puts all given context map entries into the current thread's
242 * context map.
243 *
244 * <p>If the current thread does not have a context map it is
245 * created as a side effect.</p>
246 * @param m The map.
247 * @since 2.7
248 */
249 public static void putAll(final Map<String, String> m) {
250 if (contextMap instanceof ThreadContextMap2) {
251 ((ThreadContextMap2) contextMap).putAll(m);
252 } else if (contextMap instanceof DefaultThreadContextMap) {
253 ((DefaultThreadContextMap) contextMap).putAll(m);
254 } else {
255 for (final Map.Entry<String, String> entry: m.entrySet()) {
256 contextMap.put(entry.getKey(), entry.getValue());
257 }
258 }
259 }
260
261 /**
271262 * Gets the context value identified by the <code>key</code> parameter.
272263 *
273264 * <p>
274265 * This method has no side effects.
275266 * </p>
276 *
267 *
277268 * @param key The key to locate.
278269 * @return The value associated with the key or null.
279270 */
283274
284275 /**
285276 * Removes the context value identified by the <code>key</code> parameter.
286 *
277 *
287278 * @param key The key to remove.
288279 */
289280 public static void remove(final String key) {
307298
308299 /**
309300 * Determines if the key is in the context.
310 *
301 *
311302 * @param key The key to locate.
312303 * @return True if the key is in the context, false otherwise.
313304 */
317308
318309 /**
319310 * Returns a mutable copy of current thread's context Map.
320 *
311 *
321312 * @return a mutable copy of the context.
322313 */
323314 public static Map<String, String> getContext() {
326317
327318 /**
328319 * Returns an immutable view of the current thread's context Map.
329 *
320 *
330321 * @return An immutable view of the ThreadContext Map.
331322 */
332323 public static Map<String, String> getImmutableContext() {
335326 }
336327
337328 /**
329 * Returns the internal data structure used to store thread context key-value pairs.
330 * <p><em>
331 * This data structure is not intended to be used directly by applications. This method is package protected for
332 * internal log4j2 usage.
333 * </em></p>
334 * @return the internal data structure used to store thread context key-value pairs
335 */
336 static ThreadContextMap getThreadContextMap() {
337 return contextMap;
338 }
339
340 /**
338341 * Returns true if the Map is empty.
339 *
342 *
340343 * @return true if the Map is empty, false otherwise.
341344 */
342345 public static boolean isEmpty() {
352355
353356 /**
354357 * Returns a copy of this thread's stack.
355 *
358 *
356359 * @return A copy of this thread's stack.
357360 */
358361 public static ContextStack cloneStack() {
361364
362365 /**
363366 * Gets an immutable copy of this current thread's context stack.
364 *
367 *
365368 * @return an immutable copy of the ThreadContext stack.
366369 */
367370 public static ContextStack getImmutableStack() {
371374
372375 /**
373376 * Sets this thread's stack.
374 *
377 *
375378 * @param stack The stack to use.
376379 */
377380 public static void setStack(final Collection<String> stack) {
384387
385388 /**
386389 * Gets the current nesting depth of this thread's stack.
387 *
390 *
388391 * @return the number of items in the stack.
389392 *
390393 * @see #trim
484487 * <p>
485488 * For example, the combination
486489 * </p>
487 *
490 *
488491 * <pre>
489492 * void foo() {
490493 * final int depth = ThreadContext.getDepth();
491 *
494 *
492495 * // ... complex sequence of calls
493 *
496 *
494497 * ThreadContext.trim(depth);
495498 * }
496499 * </pre>
513516
514517 /**
515518 * Returns the element at the top of the stack.
516 *
519 *
517520 * @return The element at the top of the stack.
518521 * @throws java.util.NoSuchElementException if the stack is empty.
519522 */
521524
522525 /**
523526 * Returns the element at the top of the stack without removing it or null if the stack is empty.
524 *
527 *
525528 * @return the element at the top of the stack or null if the stack is empty.
526529 */
527530 String peek();
528531
529532 /**
530533 * Pushes an element onto the stack.
531 *
534 *
532535 * @param message The element to add.
533536 */
534537 void push(String message);
535538
536539 /**
537540 * Returns the number of elements in the stack.
538 *
541 *
539542 * @return the number of elements in the stack.
540543 */
541544 int getDepth();
542545
543546 /**
544547 * Returns all the elements in the stack in a List.
545 *
548 *
546549 * @return all the elements in the stack in a List.
547550 */
548551 List<String> asList();
549552
550553 /**
551554 * Trims elements from the end of the stack.
552 *
555 *
553556 * @param depth The maximum number of items in the stack to keep.
554557 */
555558 void trim(int depth);
556559
557560 /**
558561 * Returns a copy of the ContextStack.
559 *
562 *
560563 * @return a copy of the ContextStack.
561564 */
562565 ContextStack copy();
564567 /**
565568 * Returns a ContextStack with the same contents as this ContextStack or {@code null}. Attempts to modify the
566569 * returned stack may or may not throw an exception, but will not affect the contents of this ContextStack.
567 *
570 *
568571 * @return a ContextStack with the same contents as this ContextStack or {@code null}.
569572 */
570573 ContextStack getImmutableStackOrNull();
280280 formattedMessage = in.readUTF();
281281 key = in.readUTF();
282282 baseName = in.readUTF();
283 final int length = in.readInt();
283 in.readInt();
284284 stringArgs = (String[]) in.readObject();
285285 logger = StatusLogger.getLogger();
286286 resourceBundle = null;
2121 import java.io.Serializable;
2222
2323 import org.apache.logging.log4j.util.StringBuilderFormattable;
24 import org.apache.logging.log4j.util.StringBuilders;
2425
2526 /**
2627 * Handles messages that contain an Object.
5758
5859 @Override
5960 public void formatTo(final StringBuilder buffer) {
60 if (obj == null || obj instanceof String) {
61 buffer.append((String) obj);
62 } else if (obj instanceof StringBuilderFormattable) {
63 ((StringBuilderFormattable) obj).formatTo(buffer);
64 } else if (obj instanceof CharSequence) {
65 buffer.append((CharSequence) obj);
66 } else if (obj instanceof Integer) { // LOG4J2-1437 unbox auto-boxed primitives to avoid calling toString()
67 buffer.append(((Integer) obj).intValue());
68 } else if (obj instanceof Long) {
69 buffer.append(((Long) obj).longValue());
70 } else if (obj instanceof Double) {
71 buffer.append(((Double) obj).doubleValue());
72 } else if (obj instanceof Boolean) {
73 buffer.append(((Boolean) obj).booleanValue());
74 } else if (obj instanceof Character) {
75 buffer.append(((Character) obj).charValue());
76 } else if (obj instanceof Short) {
77 buffer.append(((Short) obj).shortValue());
78 } else if (obj instanceof Float) {
79 buffer.append(((Float) obj).floatValue());
80 } else {
81 buffer.append(obj);
82 }
61 StringBuilders.appendValue(buffer, obj);
8362 }
8463
8564 /**
9069 @Override
9170 public String getFormat() {
9271 return getFormattedMessage();
72 }
73
74 /**
75 * Returns the object parameter.
76 *
77 * @return The object.
78 * @since 2.7
79 */
80 public Object getParameter() {
81 return obj;
9382 }
9483
9584 /**
199199 */
200200 static void formatMessage3(final StringBuilder buffer, final char[] messagePattern, final int patternLength,
201201 final Object[] arguments, final int argCount, final int[] indices) {
202 if (messagePattern == null || arguments == null || argCount == 0) {
202 if (messagePattern == null) {
203 return;
204 }
205 if (arguments == null || argCount == 0) {
203206 buffer.append(messagePattern);
204207 return;
205208 }
2828 * </p>
2929 */
3030 public class ParameterizedMessage implements Message, StringBuilderFormattable {
31
31
3232 // Should this be configurable?
3333 private static final int DEFAULT_STRING_BUILDER_SIZE = 255;
34
34
3535 /**
3636 * Prefix for recursion.
3737 */
4545 * Prefix for errors.
4646 */
4747 public static final String ERROR_PREFIX = ParameterFormatter.ERROR_PREFIX;
48
48
4949 /**
5050 * Separator for errors.
5151 */
5252 public static final String ERROR_SEPARATOR = ParameterFormatter.ERROR_SEPARATOR;
53
53
5454 /**
5555 * Separator for error messages.
5656 */
5757 public static final String ERROR_MSG_SEPARATOR = ParameterFormatter.ERROR_MSG_SEPARATOR;
58
58
5959 /**
6060 * Suffix for errors.
6161 */
141141
142142 private void init(final String messagePattern) {
143143 this.messagePattern = messagePattern;
144 this.indices = new int[messagePattern == null ? 0 : messagePattern.length() >> 1]; // divide by 2
144 final int len = Math.max(1, messagePattern == null ? 0 : messagePattern.length() >> 1); // divide by 2
145 this.indices = new int[len]; // LOG4J2-1542 ensure non-zero array length
145146 final int placeholders = ParameterFormatter.countArgumentPlaceholders2(messagePattern, indices);
146147 initThrowable(argArray, placeholders);
147148 this.usedCount = Math.min(placeholders, argArray == null ? 0 : argArray.length);
5454 result = new ReusableParameterizedMessage();
5555 threadLocalParameterized.set(result);
5656 }
57 return result;
57 return result.reserved ? new ReusableParameterizedMessage().reserve() : result.reserve();
5858 }
5959
6060 private static ReusableSimpleMessage getSimple() {
7575 return result;
7676 }
7777
78 /**
79 * Switches the {@code reserved} flag off if the specified message is a ReusableParameterizedMessage,
80 * otherwise does nothing. This flag is used internally to verify that a reusable message is no longer in use and
81 * can be reused.
82 * @param message the message to make available again
83 * @since 2.7
84 */
85 public static void release(final Message message) { // LOG4J2-1583
86 if (message instanceof ReusableParameterizedMessage) {
87 ((ReusableParameterizedMessage) message).reserved = false;
88 }
89 }
90
7891 @Override
7992 public Message newMessage(final CharSequence charSequence) {
8093 final ReusableSimpleMessage result = getSimple();
8181 }
8282
8383 /**
84 * Returns the object parameter.
85 *
86 * @return The object.
87 * @since 2.7
88 */
89 public Object getParameter() {
90 return obj;
91 }
92
93 /**
8494 * Returns the object as if it were a parameter.
8595 *
8696 * @return The object.
3232 private static final int MIN_BUILDER_SIZE = 512;
3333 private static final int MAX_PARMS = 10;
3434 private static final long serialVersionUID = 7800075879295123856L;
35 private static ThreadLocal<StringBuilder> buffer = new ThreadLocal<>();
35 private transient ThreadLocal<StringBuilder> buffer; // non-static: LOG4J2-1583
3636
3737 private String messagePattern;
3838 private int argCount;
4141 private transient Object[] varargs;
4242 private transient Object[] params = new Object[MAX_PARMS];
4343 private transient Throwable throwable;
44 transient boolean reserved = false; // LOG4J2-1583 prevent scrambled logs with nested logging calls
4445
4546 /**
4647 * Creates a reusable message.
288289 }
289290
290291 private StringBuilder getBuffer() {
292 if (buffer == null) {
293 buffer = new ThreadLocal<>();
294 }
291295 StringBuilder result = buffer.get();
292296 if (result == null) {
293297 final int currentPatternLength = messagePattern == null ? 0 : messagePattern.length();
307311 }
308312 }
309313
314 /**
315 * Sets the reserved flag to true and returns this object.
316 * @return this object
317 * @since 2.7
318 */
319 ReusableParameterizedMessage reserve() {
320 reserved = true;
321 return this;
322 }
310323
311324 @Override
312325 public String toString() {
3131 *
3232 */
3333 public class SimpleLoggerContext implements LoggerContext {
34
35 private static final String SYSTEM_OUT = "system.out";
36
37 private static final String SYSTEM_ERR = "system.err";
3438
3539 /** The default format to use when formatting dates */
3640 protected static final String DEFAULT_DATE_TIME_FORMAT = "yyyy/MM/dd HH:mm:ss:SSS zzz";
7478 dateTimeFormat = showDateTime ? props.getStringProperty(SimpleLoggerContext.SYSTEM_PREFIX + "dateTimeFormat",
7579 DEFAULT_DATE_TIME_FORMAT) : null;
7680
77 final String fileName = props.getStringProperty(SYSTEM_PREFIX + "logFile", "system.err");
81 final String fileName = props.getStringProperty(SYSTEM_PREFIX + "logFile", SYSTEM_ERR);
7882 PrintStream ps;
79 if ("system.err".equalsIgnoreCase(fileName)) {
83 if (SYSTEM_ERR.equalsIgnoreCase(fileName)) {
8084 ps = System.err;
81 } else if ("system.out".equalsIgnoreCase(fileName)) {
85 } else if (SYSTEM_OUT.equalsIgnoreCase(fileName)) {
8286 ps = System.out;
8387 } else {
8488 try {
4141
4242 @Override
4343 public void removeContext(final LoggerContext removeContext) {
44 // do nothing
4445 }
4546 }
168168 */
169169 protected void catching(final String fqcn, final Level level, final Throwable t) {
170170 if (isEnabled(level, CATCHING_MARKER, (Object) null, null)) {
171 logMessage(fqcn, level, CATCHING_MARKER, catchingMsg(t), t);
171 logMessageSafely(fqcn, level, CATCHING_MARKER, catchingMsg(t), t);
172172 }
173173 }
174174
175175 @Override
176176 public void catching(final Throwable t) {
177177 if (isEnabled(Level.ERROR, CATCHING_MARKER, (Object) null, null)) {
178 logMessage(FQCN, Level.ERROR, CATCHING_MARKER, catchingMsg(t), t);
178 logMessageSafely(FQCN, Level.ERROR, CATCHING_MARKER, catchingMsg(t), t);
179179 }
180180 }
181181
500500 protected EntryMessage enter(final String fqcn, final String format, final Supplier<?>... paramSuppliers) {
501501 EntryMessage entryMsg = null;
502502 if (isEnabled(Level.TRACE, ENTRY_MARKER, (Object) null, null)) {
503 logMessage(fqcn, Level.TRACE, ENTRY_MARKER, entryMsg = entryMsg(format, paramSuppliers), null);
503 logMessageSafely(fqcn, Level.TRACE, ENTRY_MARKER, entryMsg = entryMsg(format, paramSuppliers), null);
504504 }
505505 return entryMsg;
506506 }
516516 protected EntryMessage enter(final String fqcn, final String format, final MessageSupplier... paramSuppliers) {
517517 EntryMessage entryMsg = null;
518518 if (isEnabled(Level.TRACE, ENTRY_MARKER, (Object) null, null)) {
519 logMessage(fqcn, Level.TRACE, ENTRY_MARKER, entryMsg = entryMsg(format, paramSuppliers), null);
519 logMessageSafely(fqcn, Level.TRACE, ENTRY_MARKER, entryMsg = entryMsg(format, paramSuppliers), null);
520520 }
521521 return entryMsg;
522522 }
531531 protected EntryMessage enter(final String fqcn, final String format, final Object... params) {
532532 EntryMessage entryMsg = null;
533533 if (isEnabled(Level.TRACE, ENTRY_MARKER, (Object) null, null)) {
534 logMessage(fqcn, Level.TRACE, ENTRY_MARKER, entryMsg = entryMsg(format, params), null);
534 logMessageSafely(fqcn, Level.TRACE, ENTRY_MARKER, entryMsg = entryMsg(format, params), null);
535535 }
536536 return entryMsg;
537537 }
546546 protected EntryMessage enter(final String fqcn, final MessageSupplier msgSupplier) {
547547 EntryMessage message = null;
548548 if (isEnabled(Level.TRACE, ENTRY_MARKER, (Object) null, null)) {
549 logMessage(fqcn, Level.TRACE, ENTRY_MARKER, message = flowMessageFactory.newEntryMessage(
549 logMessageSafely(fqcn, Level.TRACE, ENTRY_MARKER, message = flowMessageFactory.newEntryMessage(
550550 msgSupplier.get()), null);
551551 }
552552 return message;
564564 protected EntryMessage enter(final String fqcn, final Message message) {
565565 EntryMessage flowMessage = null;
566566 if (isEnabled(Level.TRACE, ENTRY_MARKER, (Object) null, null)) {
567 logMessage(fqcn, Level.TRACE, ENTRY_MARKER, flowMessage = flowMessageFactory.newEntryMessage(message),
567 logMessageSafely(fqcn, Level.TRACE, ENTRY_MARKER, flowMessage = flowMessageFactory.newEntryMessage(message),
568568 null);
569569 }
570570 return flowMessage;
589589 protected void entry(final String fqcn, final Object... params) {
590590 if (isEnabled(Level.TRACE, ENTRY_MARKER, (Object) null, null)) {
591591 if (params == null) {
592 logMessage(fqcn, Level.TRACE, ENTRY_MARKER, entryMsg(null, (Supplier<?>[]) null), null);
592 logMessageSafely(fqcn, Level.TRACE, ENTRY_MARKER, entryMsg(null, (Supplier<?>[]) null), null);
593593 } else {
594 logMessage(fqcn, Level.TRACE, ENTRY_MARKER, entryMsg(null, params), null);
594 logMessageSafely(fqcn, Level.TRACE, ENTRY_MARKER, entryMsg(null, params), null);
595595 }
596596 }
597597 }
18091809 public void logIfEnabled(final String fqcn, final Level level, final Marker marker, final Message msg,
18101810 final Throwable t) {
18111811 if (isEnabled(level, marker, msg, t)) {
1812 logMessage(fqcn, level, marker, msg, t);
1812 logMessageSafely(fqcn, level, marker, msg, t);
18131813 }
18141814 }
18151815
19621962
19631963 protected void logMessage(final String fqcn, final Level level, final Marker marker, final CharSequence message,
19641964 final Throwable t) {
1965 logMessage(fqcn, level, marker, messageFactory.newMessage(message), t);
1965 logMessageSafely(fqcn, level, marker, messageFactory.newMessage(message), t);
19661966 }
19671967
19681968 protected void logMessage(final String fqcn, final Level level, final Marker marker, final Object message,
19691969 final Throwable t) {
1970 logMessage(fqcn, level, marker, messageFactory.newMessage(message), t);
1970 logMessageSafely(fqcn, level, marker, messageFactory.newMessage(message), t);
19711971 }
19721972
19731973 protected void logMessage(final String fqcn, final Level level, final Marker marker,
19741974 final MessageSupplier msgSupplier, final Throwable t) {
19751975 final Message message = LambdaUtil.get(msgSupplier);
1976 logMessage(fqcn, level, marker, message, t);
1976 logMessageSafely(fqcn, level, marker, message, t);
19771977 }
19781978
19791979 protected void logMessage(final String fqcn, final Level level, final Marker marker, final Supplier<?> msgSupplier,
19801980 final Throwable t) {
19811981 final Message message = LambdaUtil.getMessage(msgSupplier, messageFactory);
1982 logMessage(fqcn, level, marker, message, t);
1982 logMessageSafely(fqcn, level, marker, message, t);
19831983 }
19841984
19851985 protected void logMessage(final String fqcn, final Level level, final Marker marker, final String message,
19861986 final Throwable t) {
1987 logMessage(fqcn, level, marker, messageFactory.newMessage(message), t);
1987 logMessageSafely(fqcn, level, marker, messageFactory.newMessage(message), t);
19881988 }
19891989
19901990 protected void logMessage(final String fqcn, final Level level, final Marker marker, final String message) {
19911991 final Message msg = messageFactory.newMessage(message);
1992 logMessage(fqcn, level, marker, msg, msg.getThrowable());
1992 logMessageSafely(fqcn, level, marker, msg, msg.getThrowable());
19931993 }
19941994
19951995 protected void logMessage(final String fqcn, final Level level, final Marker marker, final String message,
19961996 final Object... params) {
19971997 final Message msg = messageFactory.newMessage(message, params);
1998 logMessage(fqcn, level, marker, msg, msg.getThrowable());
1998 logMessageSafely(fqcn, level, marker, msg, msg.getThrowable());
19991999 }
20002000
20012001 protected void logMessage(final String fqcn, final Level level, final Marker marker, final String message,
20022002 final Object p0) {
20032003 final Message msg = messageFactory.newMessage(message, p0);
2004 logMessage(fqcn, level, marker, msg, msg.getThrowable());
2004 logMessageSafely(fqcn, level, marker, msg, msg.getThrowable());
20052005 }
20062006
20072007 protected void logMessage(final String fqcn, final Level level, final Marker marker, final String message,
20082008 final Object p0, final Object p1) {
20092009 final Message msg = messageFactory.newMessage(message, p0, p1);
2010 logMessage(fqcn, level, marker, msg, msg.getThrowable());
2010 logMessageSafely(fqcn, level, marker, msg, msg.getThrowable());
20112011 }
20122012
20132013 protected void logMessage(final String fqcn, final Level level, final Marker marker, final String message,
20142014 final Object p0, final Object p1, final Object p2) {
20152015 final Message msg = messageFactory.newMessage(message, p0, p1, p2);
2016 logMessage(fqcn, level, marker, msg, msg.getThrowable());
2016 logMessageSafely(fqcn, level, marker, msg, msg.getThrowable());
20172017 }
20182018
20192019 protected void logMessage(final String fqcn, final Level level, final Marker marker, final String message,
20202020 final Object p0, final Object p1, final Object p2, final Object p3) {
20212021 final Message msg = messageFactory.newMessage(message, p0, p1, p2, p3);
2022 logMessage(fqcn, level, marker, msg, msg.getThrowable());
2022 logMessageSafely(fqcn, level, marker, msg, msg.getThrowable());
20232023 }
20242024
20252025 protected void logMessage(final String fqcn, final Level level, final Marker marker, final String message,
20262026 final Object p0, final Object p1, final Object p2, final Object p3, final Object p4) {
20272027 final Message msg = messageFactory.newMessage(message, p0, p1, p2, p3, p4);
2028 logMessage(fqcn, level, marker, msg, msg.getThrowable());
2028 logMessageSafely(fqcn, level, marker, msg, msg.getThrowable());
20292029 }
20302030
20312031 protected void logMessage(final String fqcn, final Level level, final Marker marker, final String message,
20322032 final Object p0, final Object p1, final Object p2, final Object p3, final Object p4, final Object p5) {
20332033 final Message msg = messageFactory.newMessage(message, p0, p1, p2, p3, p4, p5);
2034 logMessage(fqcn, level, marker, msg, msg.getThrowable());
2034 logMessageSafely(fqcn, level, marker, msg, msg.getThrowable());
20352035 }
20362036
20372037 protected void logMessage(final String fqcn, final Level level, final Marker marker, final String message,
20382038 final Object p0, final Object p1, final Object p2, final Object p3, final Object p4, final Object p5,
20392039 final Object p6) {
20402040 final Message msg = messageFactory.newMessage(message, p0, p1, p2, p3, p4, p5, p6);
2041 logMessage(fqcn, level, marker, msg, msg.getThrowable());
2041 logMessageSafely(fqcn, level, marker, msg, msg.getThrowable());
20422042 }
20432043
20442044 protected void logMessage(final String fqcn, final Level level, final Marker marker, final String message,
20452045 final Object p0, final Object p1, final Object p2, final Object p3, final Object p4, final Object p5,
20462046 final Object p6, final Object p7) {
20472047 final Message msg = messageFactory.newMessage(message, p0, p1, p2, p3, p4, p5, p6, p7);
2048 logMessage(fqcn, level, marker, msg, msg.getThrowable());
2048 logMessageSafely(fqcn, level, marker, msg, msg.getThrowable());
20492049 }
20502050
20512051 protected void logMessage(final String fqcn, final Level level, final Marker marker, final String message,
20522052 final Object p0, final Object p1, final Object p2, final Object p3, final Object p4, final Object p5,
20532053 final Object p6, final Object p7, final Object p8) {
20542054 final Message msg = messageFactory.newMessage(message, p0, p1, p2, p3, p4, p5, p6, p7, p8);
2055 logMessage(fqcn, level, marker, msg, msg.getThrowable());
2055 logMessageSafely(fqcn, level, marker, msg, msg.getThrowable());
20562056 }
20572057
20582058 protected void logMessage(final String fqcn, final Level level, final Marker marker, final String message,
20592059 final Object p0, final Object p1, final Object p2, final Object p3, final Object p4, final Object p5,
20602060 final Object p6, final Object p7, final Object p8, final Object p9) {
20612061 final Message msg = messageFactory.newMessage(message, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9);
2062 logMessage(fqcn, level, marker, msg, msg.getThrowable());
2062 logMessageSafely(fqcn, level, marker, msg, msg.getThrowable());
20632063 }
20642064
20652065 protected void logMessage(final String fqcn, final Level level, final Marker marker, final String message,
20662066 final Supplier<?>... paramSuppliers) {
20672067 final Message msg = messageFactory.newMessage(message, LambdaUtil.getAll(paramSuppliers));
2068 logMessage(fqcn, level, marker, msg, msg.getThrowable());
2068 logMessageSafely(fqcn, level, marker, msg, msg.getThrowable());
20692069 }
20702070
20712071 @Override
20722072 public void printf(final Level level, final Marker marker, final String format, final Object... params) {
20732073 if (isEnabled(level, marker, format, params)) {
20742074 final Message msg = new StringFormattedMessage(format, params);
2075 logMessage(FQCN, level, marker, msg, msg.getThrowable());
2075 logMessageSafely(FQCN, level, marker, msg, msg.getThrowable());
20762076 }
20772077 }
20782078
20802080 public void printf(final Level level, final String format, final Object... params) {
20812081 if (isEnabled(level, null, format, params)) {
20822082 final Message msg = new StringFormattedMessage(format, params);
2083 logMessage(FQCN, level, null, msg, msg.getThrowable());
2083 logMessageSafely(FQCN, level, null, msg, msg.getThrowable());
2084 }
2085 }
2086
2087 private void logMessageSafely(final String fqcn, final Level level, final Marker marker, final Message msg,
2088 final Throwable throwable) {
2089 try {
2090 logMessage(fqcn, level, marker, msg, throwable);
2091 } finally {
2092 // LOG4J2-1583 prevent scrambled logs when logging calls are nested (logging in toString())
2093 ReusableMessageFactory.release(msg);
20842094 }
20852095 }
20862096
21052115 */
21062116 protected <T extends Throwable> T throwing(final String fqcn, final Level level, final T t) {
21072117 if (isEnabled(level, THROWING_MARKER, (Object) null, null)) {
2108 logMessage(fqcn, level, THROWING_MARKER, throwingMsg(t), t);
2118 logMessageSafely(fqcn, level, THROWING_MARKER, throwingMsg(t), t);
21092119 }
21102120 return t;
21112121 }
24132423 public void traceExit(final EntryMessage message) {
24142424 // If the message is null, traceEnter returned null because flow logging was disabled, we can optimize out calling isEnabled().
24152425 if (message != null && isEnabled(Level.TRACE, EXIT_MARKER, message, null)) {
2416 logMessage(FQCN, Level.TRACE, EXIT_MARKER, flowMessageFactory.newExitMessage(message), null);
2426 logMessageSafely(FQCN, Level.TRACE, EXIT_MARKER, flowMessageFactory.newExitMessage(message), null);
24172427 }
24182428 }
24192429
24212431 public <R> R traceExit(final EntryMessage message, final R result) {
24222432 // If the message is null, traceEnter returned null because flow logging was disabled, we can optimize out calling isEnabled().
24232433 if (message != null && isEnabled(Level.TRACE, EXIT_MARKER, message, null)) {
2424 logMessage(FQCN, Level.TRACE, EXIT_MARKER, flowMessageFactory.newExitMessage(result, message), null);
2434 logMessageSafely(FQCN, Level.TRACE, EXIT_MARKER, flowMessageFactory.newExitMessage(result, message), null);
24252435 }
24262436 return result;
24272437 }
24302440 public <R> R traceExit(final Message message, final R result) {
24312441 // If the message is null, traceEnter returned null because flow logging was disabled, we can optimize out calling isEnabled().
24322442 if (message != null && isEnabled(Level.TRACE, EXIT_MARKER, message, null)) {
2433 logMessage(FQCN, Level.TRACE, EXIT_MARKER, flowMessageFactory.newExitMessage(result, message), null);
2443 logMessageSafely(FQCN, Level.TRACE, EXIT_MARKER, flowMessageFactory.newExitMessage(result, message), null);
24342444 }
24352445 return result;
24362446 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.spi;
17
18 /**
19 * Marker interface indicating that the implementing class is a copy-on-write data structure.
20 *
21 * @since 2.7
22 */
23 public interface CopyOnWrite {
24 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.spi;
17
18 import java.util.Collections;
19 import java.util.HashMap;
20 import java.util.Map;
21
22 import org.apache.logging.log4j.util.ReadOnlyStringMap;
23 import org.apache.logging.log4j.util.SortedArrayStringMap;
24 import org.apache.logging.log4j.util.StringMap;
25 import org.apache.logging.log4j.util.PropertiesUtil;
26
27 /**
28 * {@code SortedArrayStringMap}-based implementation of the {@code ThreadContextMap} interface that creates a copy of
29 * the data structure on every modification. Any particular instance of the data structure is a snapshot of the
30 * ThreadContext at some point in time and can safely be passed off to other threads. Since it is
31 * expected that the Map will be passed to many more log events than the number of keys it contains the performance
32 * should be much better than if the Map was copied for each event.
33 *
34 * @since 2.7
35 */
36 class CopyOnWriteSortedArrayThreadContextMap implements ThreadContextMap2, CopyOnWrite {
37
38 /**
39 * Property name ({@value} ) for selecting {@code InheritableThreadLocal} (value "true") or plain
40 * {@code ThreadLocal} (value is not "true") in the implementation.
41 */
42 public static final String INHERITABLE_MAP = "isThreadContextMapInheritable";
43
44 /**
45 * The default initial capacity.
46 */
47 protected static final int DEFAULT_INITIAL_CAPACITY = 16;
48
49 /**
50 * System property name that can be used to control the data structure's initial capacity.
51 */
52 protected static final String PROPERTY_NAME_INITIAL_CAPACITY = "log4j2.ThreadContext.initial.capacity";
53
54 private static final StringMap EMPTY_CONTEXT_DATA = new SortedArrayStringMap();
55 static {
56 EMPTY_CONTEXT_DATA.freeze();
57 }
58
59 private final ThreadLocal<StringMap> localMap;
60
61 public CopyOnWriteSortedArrayThreadContextMap() {
62 this.localMap = createThreadLocalMap();
63 }
64
65 // LOG4J2-479: by default, use a plain ThreadLocal, only use InheritableThreadLocal if configured.
66 // (This method is package protected for JUnit tests.)
67 private ThreadLocal<StringMap> createThreadLocalMap() {
68 final PropertiesUtil managerProps = PropertiesUtil.getProperties();
69 final boolean inheritable = managerProps.getBooleanProperty(INHERITABLE_MAP);
70 if (inheritable) {
71 return new InheritableThreadLocal<StringMap>() {
72 @Override
73 protected StringMap childValue(final StringMap parentValue) {
74 return parentValue != null ? createStringMap(parentValue) : null;
75 }
76 };
77 }
78 // if not inheritable, return plain ThreadLocal with null as initial value
79 return new ThreadLocal<>();
80 }
81
82 /**
83 * Returns an implementation of the {@code StringMap} used to back this thread context map.
84 * <p>
85 * Subclasses may override.
86 * </p>
87 * @return an implementation of the {@code StringMap} used to back this thread context map
88 */
89 protected StringMap createStringMap() {
90 return new SortedArrayStringMap(PropertiesUtil.getProperties().getIntegerProperty(
91 PROPERTY_NAME_INITIAL_CAPACITY, DEFAULT_INITIAL_CAPACITY));
92 }
93
94 /**
95 * Returns an implementation of the {@code StringMap} used to back this thread context map, pre-populated
96 * with the contents of the specified context data.
97 * <p>
98 * Subclasses may override.
99 * </p>
100 * @param original the key-value pairs to initialize the returned context data with
101 * @return an implementation of the {@code StringMap} used to back this thread context map
102 */
103 protected StringMap createStringMap(final ReadOnlyStringMap original) {
104 return new SortedArrayStringMap(original);
105 }
106
107 @Override
108 public void put(final String key, final String value) {
109 StringMap map = localMap.get();
110 map = map == null ? createStringMap() : createStringMap(map);
111 map.putValue(key, value);
112 map.freeze();
113 localMap.set(map);
114 }
115
116 @Override
117 public void putAll(final Map<String, String> values) {
118 if (values == null || values.isEmpty()) {
119 return;
120 }
121 StringMap map = localMap.get();
122 map = map == null ? createStringMap() : createStringMap(map);
123 for (final Map.Entry<String, String> entry : values.entrySet()) {
124 map.putValue(entry.getKey(), entry.getValue());
125 }
126 map.freeze();
127 localMap.set(map);
128 }
129
130 @Override
131 public String get(final String key) {
132 final StringMap map = localMap.get();
133 return map == null ? null : (String) map.getValue(key);
134 }
135
136 @Override
137 public void remove(final String key) {
138 final StringMap map = localMap.get();
139 if (map != null) {
140 final StringMap copy = createStringMap(map);
141 copy.remove(key);
142 copy.freeze();
143 localMap.set(copy);
144 }
145 }
146
147 @Override
148 public void clear() {
149 localMap.remove();
150 }
151
152 @Override
153 public boolean containsKey(final String key) {
154 final StringMap map = localMap.get();
155 return map != null && map.containsKey(key);
156 }
157
158 @Override
159 public Map<String, String> getCopy() {
160 final StringMap map = localMap.get();
161 return map == null ? new HashMap<String, String>() : map.toMap();
162 }
163
164 /**
165 * {@inheritDoc}
166 */
167 @Override
168 public StringMap getReadOnlyContextData() {
169 final StringMap map = localMap.get();
170 return map == null ? EMPTY_CONTEXT_DATA : map;
171 }
172
173 @Override
174 public Map<String, String> getImmutableMapOrNull() {
175 final StringMap map = localMap.get();
176 return map == null ? null : Collections.unmodifiableMap(map.toMap());
177 }
178
179 @Override
180 public boolean isEmpty() {
181 final StringMap map = localMap.get();
182 return map == null || map.size() == 0;
183 }
184
185 @Override
186 public String toString() {
187 final StringMap map = localMap.get();
188 return map == null ? "{}" : map.toString();
189 }
190
191 @Override
192 public int hashCode() {
193 final int prime = 31;
194 int result = 1;
195 final StringMap map = this.localMap.get();
196 result = prime * result + ((map == null) ? 0 : map.hashCode());
197 return result;
198 }
199
200 @Override
201 public boolean equals(final Object obj) {
202 if (this == obj) {
203 return true;
204 }
205 if (obj == null) {
206 return false;
207 }
208 if (!(obj instanceof ThreadContextMap)) {
209 return false;
210 }
211 final ThreadContextMap other = (ThreadContextMap) obj;
212 final Map<String, String> map = this.getImmutableMapOrNull();
213 final Map<String, String> otherMap = other.getImmutableMapOrNull();
214 if (map == null) {
215 if (otherMap != null) {
216 return false;
217 }
218 } else if (!map.equals(otherMap)) {
219 return false;
220 }
221 return true;
222 }
223 }
1919 import java.util.HashMap;
2020 import java.util.Map;
2121
22 import org.apache.logging.log4j.util.BiConsumer;
23 import org.apache.logging.log4j.util.ReadOnlyStringMap;
2224 import org.apache.logging.log4j.util.PropertiesUtil;
25 import org.apache.logging.log4j.util.TriConsumer;
2326
2427 /**
2528 * The actual ThreadContext Map. A new ThreadContext Map is created each time it is updated and the Map stored is always
2730 * expected that the Map will be passed to many more log events than the number of keys it contains the performance
2831 * should be much better than if the Map was copied for each event.
2932 */
30 public class DefaultThreadContextMap implements ThreadContextMap {
33 public class DefaultThreadContextMap implements ThreadContextMap, ReadOnlyStringMap {
34
3135 /**
3236 * Property name ({@value} ) for selecting {@code InheritableThreadLocal} (value "true") or plain
3337 * {@code ThreadLocal} (value is not "true") in the implementation.
3640
3741 private final boolean useMap;
3842 private final ThreadLocal<Map<String, String>> localMap;
43
44 public DefaultThreadContextMap() {
45 this(true);
46 }
3947
4048 public DefaultThreadContextMap(final boolean useMap) {
4149 this.useMap = useMap;
6775 return;
6876 }
6977 Map<String, String> map = localMap.get();
70 map = map == null ? new HashMap<String, String>() : new HashMap<>(map);
78 map = map == null ? new HashMap<String, String>(1) : new HashMap<>(map);
7179 map.put(key, value);
80 localMap.set(Collections.unmodifiableMap(map));
81 }
82
83 public void putAll(final Map<String, String> m) {
84 if (!useMap) {
85 return;
86 }
87 Map<String, String> map = localMap.get();
88 map = map == null ? new HashMap<String, String>(m.size()) : new HashMap<>(map);
89 for (final Map.Entry<String, String> e : m.entrySet()) {
90 map.put(e.getKey(), e.getValue());
91 }
7292 localMap.set(Collections.unmodifiableMap(map));
7393 }
7494
94114 }
95115
96116 @Override
117 public Map<String, String> toMap() {
118 return getCopy();
119 }
120
121 @Override
97122 public boolean containsKey(final String key) {
98123 final Map<String, String> map = localMap.get();
99124 return map != null && map.containsKey(key);
125 }
126
127 @Override
128 public <V> void forEach(final BiConsumer<String, ? super V> action) {
129 final Map<String, String> map = localMap.get();
130 if (map == null) {
131 return;
132 }
133 for (final Map.Entry<String, String> entry : map.entrySet()) {
134 action.accept(entry.getKey(), (V) entry.getValue());
135 }
136 }
137
138 @Override
139 public <V, S> void forEach(final TriConsumer<String, ? super V, S> action, final S state) {
140 final Map<String, String> map = localMap.get();
141 if (map == null) {
142 return;
143 }
144 for (final Map.Entry<String, String> entry : map.entrySet()) {
145 action.accept(entry.getKey(), (V) entry.getValue(), state);
146 }
147 }
148
149 @SuppressWarnings("unchecked")
150 @Override
151 public <V> V getValue(final String key) {
152 final Map<String, String> map = localMap.get();
153 return (V) (map == null ? null : map.get(key));
100154 }
101155
102156 @Override
114168 public boolean isEmpty() {
115169 final Map<String, String> map = localMap.get();
116170 return map == null || map.size() == 0;
171 }
172
173 @Override
174 public int size() {
175 final Map<String, String> map = localMap.get();
176 return map == null ? 0 : map.size();
117177 }
118178
119179 @Override
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.spi;
17
18 import java.util.Collections;
19 import java.util.HashMap;
20 import java.util.Map;
21
22 import org.apache.logging.log4j.util.ReadOnlyStringMap;
23 import org.apache.logging.log4j.util.StringMap;
24 import org.apache.logging.log4j.util.PropertiesUtil;
25 import org.apache.logging.log4j.util.SortedArrayStringMap;
26
27 /**
28 * {@code SortedArrayStringMap}-based implementation of the {@code ThreadContextMap} interface that attempts not to
29 * create temporary objects. Adding and removing key-value pairs will not create temporary objects.
30 * <p>
31 * This implementation does <em>not</em> make a copy of its contents on every operation, so this data structure cannot
32 * be passed to log events. Instead, client code needs to copy the contents when interacting with another thread.
33 * </p>
34 * @since 2.7
35 */
36 class GarbageFreeSortedArrayThreadContextMap implements ThreadContextMap2 {
37
38 /**
39 * Property name ({@value} ) for selecting {@code InheritableThreadLocal} (value "true") or plain
40 * {@code ThreadLocal} (value is not "true") in the implementation.
41 */
42 public static final String INHERITABLE_MAP = "isThreadContextMapInheritable";
43
44 /**
45 * The default initial capacity.
46 */
47 protected static final int DEFAULT_INITIAL_CAPACITY = 16;
48
49 /**
50 * System property name that can be used to control the data structure's initial capacity.
51 */
52 protected static final String PROPERTY_NAME_INITIAL_CAPACITY = "log4j2.ThreadContext.initial.capacity";
53
54 protected final ThreadLocal<StringMap> localMap;
55
56 public GarbageFreeSortedArrayThreadContextMap() {
57 this.localMap = createThreadLocalMap();
58 }
59
60 // LOG4J2-479: by default, use a plain ThreadLocal, only use InheritableThreadLocal if configured.
61 // (This method is package protected for JUnit tests.)
62 private ThreadLocal<StringMap> createThreadLocalMap() {
63 final PropertiesUtil managerProps = PropertiesUtil.getProperties();
64 final boolean inheritable = managerProps.getBooleanProperty(INHERITABLE_MAP);
65 if (inheritable) {
66 return new InheritableThreadLocal<StringMap>() {
67 @Override
68 protected StringMap childValue(final StringMap parentValue) {
69 return parentValue != null ? createStringMap(parentValue) : null;
70 }
71 };
72 }
73 // if not inheritable, return plain ThreadLocal with null as initial value
74 return new ThreadLocal<>();
75 }
76
77 /**
78 * Returns an implementation of the {@code StringMap} used to back this thread context map.
79 * <p>
80 * Subclasses may override.
81 * </p>
82 * @return an implementation of the {@code StringMap} used to back this thread context map
83 */
84 protected StringMap createStringMap() {
85 return new SortedArrayStringMap(PropertiesUtil.getProperties().getIntegerProperty(
86 PROPERTY_NAME_INITIAL_CAPACITY, DEFAULT_INITIAL_CAPACITY));
87 }
88
89 /**
90 * Returns an implementation of the {@code StringMap} used to back this thread context map, pre-populated
91 * with the contents of the specified context data.
92 * <p>
93 * Subclasses may override.
94 * </p>
95 * @param original the key-value pairs to initialize the returned context data with
96 * @return an implementation of the {@code StringMap} used to back this thread context map
97 */
98 protected StringMap createStringMap(final ReadOnlyStringMap original) {
99 return new SortedArrayStringMap(original);
100 }
101
102 private StringMap getThreadLocalMap() {
103 StringMap map = localMap.get();
104 if (map == null) {
105 map = createStringMap();
106 localMap.set(map);
107 }
108 return map;
109 }
110
111 @Override
112 public void put(final String key, final String value) {
113 getThreadLocalMap().putValue(key, value);
114 }
115
116 @Override
117 public void putAll(final Map<String, String> values) {
118 if (values == null || values.isEmpty()) {
119 return;
120 }
121 final StringMap map = getThreadLocalMap();
122 for (final Map.Entry<String, String> entry : values.entrySet()) {
123 map.putValue(entry.getKey(), entry.getValue());
124 }
125 }
126
127 @Override
128 public String get(final String key) {
129 final StringMap map = localMap.get();
130 return map == null ? null : (String) map.getValue(key);
131 }
132
133 @Override
134 public void remove(final String key) {
135 final StringMap map = localMap.get();
136 if (map != null) {
137 map.remove(key);
138 }
139 }
140
141 @Override
142 public void clear() {
143 final StringMap map = localMap.get();
144 if (map != null) {
145 map.clear();
146 }
147 }
148
149 @Override
150 public boolean containsKey(final String key) {
151 final StringMap map = localMap.get();
152 return map != null && map.containsKey(key);
153 }
154
155 @Override
156 public Map<String, String> getCopy() {
157 final StringMap map = localMap.get();
158 return map == null ? new HashMap<String, String>() : map.toMap();
159 }
160
161 /**
162 * {@inheritDoc}
163 */
164 @Override
165 public StringMap getReadOnlyContextData() {
166 StringMap map = localMap.get();
167 if (map == null) {
168 map = createStringMap();
169 localMap.set(map);
170 }
171 return map;
172 }
173
174 @Override
175 public Map<String, String> getImmutableMapOrNull() {
176 final StringMap map = localMap.get();
177 return map == null ? null : Collections.unmodifiableMap(map.toMap());
178 }
179
180 @Override
181 public boolean isEmpty() {
182 final StringMap map = localMap.get();
183 return map == null || map.size() == 0;
184 }
185
186 @Override
187 public String toString() {
188 final StringMap map = localMap.get();
189 return map == null ? "{}" : map.toString();
190 }
191
192 @Override
193 public int hashCode() {
194 final int prime = 31;
195 int result = 1;
196 final StringMap map = this.localMap.get();
197 result = prime * result + ((map == null) ? 0 : map.hashCode());
198 return result;
199 }
200
201 @Override
202 public boolean equals(final Object obj) {
203 if (this == obj) {
204 return true;
205 }
206 if (obj == null) {
207 return false;
208 }
209 if (!(obj instanceof ThreadContextMap)) {
210 return false;
211 }
212 final ThreadContextMap other = (ThreadContextMap) obj;
213 final Map<String, String> map = this.getImmutableMapOrNull();
214 final Map<String, String> otherMap = other.getImmutableMapOrNull();
215 if (map == null) {
216 if (otherMap != null) {
217 return false;
218 }
219 } else if (!map.equals(otherMap)) {
220 return false;
221 }
222 return true;
223 }
224 }
2323 import org.apache.logging.log4j.ThreadContext.ContextStack;
2424
2525 /**
26 *
26 * TODO
2727 */
2828 public class MutableThreadContextStack implements ThreadContextStack {
2929
4242 this(new ArrayList<String>());
4343 }
4444
45 /**
46 * Constructs a new instance.
47 * @param list
48 */
4549 public MutableThreadContextStack(final List<String> list) {
4650 this.list = new ArrayList<>(list);
4751 }
234238 frozen = true;
235239 }
236240
241 /**
242 * Returns whether this context stack is frozen.
243 * @return whether this context stack is frozen.
244 */
237245 public boolean isFrozen() {
238246 return frozen;
239247 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.spi;
17
18 import java.util.HashMap;
19 import java.util.Map;
20
21 /**
22 * {@code ThreadContextMap} implementation used when either of system properties {@code disableThreadContextMap} or .
23 * {@code disableThreadContext} is {@code true}. This implementation does nothing.
24 *
25 * @since 2.7
26 */
27 public class NoOpThreadContextMap implements ThreadContextMap {
28 @Override
29 public void clear() {
30 }
31
32 @Override
33 public boolean containsKey(final String key) {
34 return false;
35 }
36
37 @Override
38 public String get(final String key) {
39 return null;
40 }
41
42 @Override
43 public Map<String, String> getCopy() {
44 return new HashMap<>();
45 }
46
47 @Override
48 public Map<String, String> getImmutableMapOrNull() {
49 return null;
50 }
51
52 @Override
53 public boolean isEmpty() {
54 return true;
55 }
56
57 @Override
58 public void put(final String key, final String value) {
59 }
60
61 @Override
62 public void remove(final String key) {
63 }
64 }
147147 @Override
148148 public String toString() {
149149 String result = "Provider[";
150 if (priority != DEFAULT_PRIORITY) {
150 if (!DEFAULT_PRIORITY.equals(priority)) {
151151 result += "priority=" + priority + ", ";
152152 }
153153 if (threadContextMap != null) {
2121 * Service provider interface to implement custom MDC behavior for {@link org.apache.logging.log4j.ThreadContext}.
2222 */
2323 public interface ThreadContextMap {
24
2425 /**
25 * Put a context value (the <code>o</code> parameter) as identified
26 * Clears the context.
27 */
28 void clear();
29
30 /**
31 * Determines if the key is in the context.
32 * @param key The key to locate.
33 * @return True if the key is in the context, false otherwise.
34 */
35 boolean containsKey(final String key);
36
37 /**
38 * Gets the context identified by the <code>key</code> parameter.
39 *
40 * <p>This method has no side effects.</p>
41 * @param key The key to locate.
42 * @return The value associated with the key or null.
43 */
44 String get(final String key);
45
46 /**
47 * Gets a non-{@code null} mutable copy of current thread's context Map.
48 * @return a mutable copy of the context.
49 */
50 Map<String, String> getCopy();
51
52 /**
53 * Returns an immutable view on the context Map or {@code null} if the context map is empty.
54 * @return an immutable context Map or {@code null}.
55 */
56 Map<String, String> getImmutableMapOrNull();
57
58 /**
59 * Returns true if the Map is empty.
60 * @return true if the Map is empty, false otherwise.
61 */
62 boolean isEmpty();
63
64 /**
65 * Puts a context value (the <code>o</code> parameter) as identified
2666 * with the <code>key</code> parameter into the current thread's
2767 * context map.
2868 *
3474 void put(final String key, final String value);
3575
3676 /**
37 * Get the context identified by the <code>key</code> parameter.
38 *
39 * <p>This method has no side effects.</p>
40 * @param key The key to locate.
41 * @return The value associated with the key or null.
42 */
43 String get(final String key);
44
45 /**
46 * Remove the the context identified by the <code>key</code>
77 * Removes the the context identified by the <code>key</code>
4778 * parameter.
4879 * @param key The key to remove.
4980 */
5081 void remove(final String key);
51
52 /**
53 * Clear the context.
54 */
55 void clear();
56
57 /**
58 * Determine if the key is in the context.
59 * @param key The key to locate.
60 * @return True if the key is in the context, false otherwise.
61 */
62 boolean containsKey(final String key);
63
64 /**
65 * Get a non-{@code null} mutable copy of current thread's context Map.
66 * @return a mutable copy of the context.
67 */
68 Map<String, String> getCopy();
69
70 /**
71 * Return an immutable view on the context Map or {@code null} if the context map is empty.
72 * @return an immutable context Map or {@code null}.
73 */
74 Map<String, String> getImmutableMapOrNull();
75
76 /**
77 * Returns true if the Map is empty.
78 * @return true if the Map is empty, false otherwise.
79 */
80 boolean isEmpty();
8182 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.spi;
17
18 import java.util.Map;
19
20 import org.apache.logging.log4j.util.StringMap;
21
22 /**
23 * Extension service provider interface to implement additional custom MDC behavior for
24 * {@link org.apache.logging.log4j.ThreadContext}.
25 *
26 * @see ThreadContextMap
27 * @since 2.7
28 */
29 public interface ThreadContextMap2 extends ThreadContextMap {
30
31 /**
32 * Puts all given context map entries into the current thread's
33 * context map.
34 *
35 * <p>If the current thread does not have a context map it is
36 * created as a side effect.</p>
37 * @param map The map.
38 * @since 2.7
39 */
40 void putAll(final Map<String, String> map);
41
42 /**
43 * Returns the context data for reading. Note that regardless of whether the returned context data has been
44 * {@linkplain StringMap#freeze() frozen} (made read-only) or not, callers should not attempt to modify
45 * the returned data structure.
46 *
47 * @return the {@code StringMap}
48 */
49 StringMap getReadOnlyContextData();
50 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.spi;
17
18 import org.apache.logging.log4j.LogManager;
19 import org.apache.logging.log4j.Logger;
20 import org.apache.logging.log4j.status.StatusLogger;
21 import org.apache.logging.log4j.util.Constants;
22 import org.apache.logging.log4j.util.PropertiesUtil;
23 import org.apache.logging.log4j.util.ProviderUtil;
24
25 /**
26 * Creates the ThreadContextMap instance used by the ThreadContext.
27 *
28 * @see ThreadContextMap
29 * @see org.apache.logging.log4j.ThreadContext
30 * @since 2.7
31 */
32 public final class ThreadContextMapFactory {
33 private static final Logger LOGGER = StatusLogger.getLogger();
34 private static final String THREAD_CONTEXT_KEY = "log4j2.threadContextMap";
35 private static final String GC_FREE_THREAD_CONTEXT_KEY = "log4j2.garbagefree.threadContextMap";
36
37 private ThreadContextMapFactory() {
38 }
39
40 public static ThreadContextMap createThreadContextMap() {
41 final PropertiesUtil managerProps = PropertiesUtil.getProperties();
42 final String threadContextMapName = managerProps.getStringProperty(THREAD_CONTEXT_KEY);
43 final ClassLoader cl = ProviderUtil.findClassLoader();
44 ThreadContextMap result = null;
45 if (threadContextMapName != null) {
46 try {
47 final Class<?> clazz = cl.loadClass(threadContextMapName);
48 if (ThreadContextMap.class.isAssignableFrom(clazz)) {
49 result = (ThreadContextMap) clazz.newInstance();
50 }
51 } catch (final ClassNotFoundException cnfe) {
52 LOGGER.error("Unable to locate configured ThreadContextMap {}", threadContextMapName);
53 } catch (final Exception ex) {
54 LOGGER.error("Unable to create configured ThreadContextMap {}", threadContextMapName, ex);
55 }
56 }
57 if (result == null && ProviderUtil.hasProviders()) {
58 final String factoryClassName = LogManager.getFactory().getClass().getName();
59 for (final Provider provider : ProviderUtil.getProviders()) {
60 if (factoryClassName.equals(provider.getClassName())) {
61 final Class<? extends ThreadContextMap> clazz = provider.loadThreadContextMap();
62 if (clazz != null) {
63 try {
64 result = clazz.newInstance();
65 break;
66 } catch (final Exception e) {
67 LOGGER.error("Unable to locate or load configured ThreadContextMap {}",
68 provider.getThreadContextMap(), e);
69 result = createDefaultThreadContextMap();
70 }
71 }
72 }
73 }
74 }
75 if (result == null) {
76 result = createDefaultThreadContextMap();
77 }
78 return result;
79 }
80
81 private static ThreadContextMap createDefaultThreadContextMap() {
82 if (Constants.ENABLE_THREADLOCALS) {
83 if (PropertiesUtil.getProperties().getBooleanProperty(GC_FREE_THREAD_CONTEXT_KEY)) {
84 return new GarbageFreeSortedArrayThreadContextMap();
85 }
86 return new CopyOnWriteSortedArrayThreadContextMap();
87 }
88 return new DefaultThreadContextMap(true);
89 }
90 }
2121 * Service provider interface to implement custom NDC behavior for {@link ThreadContext}.
2222 */
2323 public interface ThreadContextStack extends ThreadContext.ContextStack {
24 // empty
2425 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.util;
17
18 /**
19 * An operation that accepts two input arguments and returns no result.
20 *
21 * @param <K> type of the first argument
22 * @param <V> type of the second argument
23 * @see ReadOnlyStringMap
24 * @since 2.7
25 */
26 public interface BiConsumer<K, V> {
27
28 /**
29 * Performs the operation given the specified arguments.
30 * @param k the first input argument
31 * @param v the second input argument
32 */
33 void accept(K k, V v);
34 }
3434 * <p>
3535 * {@code True} for non-{@link #IS_WEB_APP web apps}, disable by setting system property
3636 * "log4j2.enable.threadlocals" to "false".
37 * </p>
3738 */
3839 public static final boolean ENABLE_THREADLOCALS = !IS_WEB_APP && PropertiesUtil.getProperties().getBooleanProperty(
3940 "log4j2.enable.threadlocals", true);
103103 }
104104
105105 /**
106 * Determines if a named Class can be loaded or not.
107 *
108 * @param className The class name.
109 * @return {@code true} if the class could be found or {@code false} otherwise.
110 * @since 2.7
111 */
112 public static boolean isClassAvailable(final String className) {
113 try {
114 final Class<?> clazz = loadClass(className);
115 return clazz != null;
116 } catch (final ClassNotFoundException e) {
117 return false;
118 } catch (final Throwable e) {
119 LowLevelLogUtil.logException("Unknown error checking for existence of class: " + className, e);
120 return false;
121 }
122 }
123
124 /**
106125 * Loads a class by name. This method respects the {@link #IGNORE_TCCL_PROPERTY} Log4j property. If this property is
107126 * specified and set to anything besides {@code false}, then the default ClassLoader will be used.
108127 *
119138 return getThreadContextClassLoader().loadClass(className);
120139 } catch (final Throwable ignored) {
121140 return Class.forName(className);
141 }
142 }
143
144 /**
145 * Loads and instantiates a Class using the default constructor.
146 *
147 * @param clazz The class.
148 * @return new instance of the class.
149 * @throws IllegalAccessException if the class can't be instantiated through a public constructor
150 * @throws InstantiationException if there was an exception whilst instantiating the class
151 * @throws InvocationTargetException if there was an exception whilst constructing the class
152 * @since 2.7
153 */
154 public static <T> T newInstanceOf(final Class<T> clazz)
155 throws InstantiationException, IllegalAccessException, InvocationTargetException {
156 try {
157 return clazz.getConstructor().newInstance();
158 } catch (final NoSuchMethodException ignored) {
159 // FIXME: looking at the code for Class.newInstance(), this seems to do the same thing as above
160 return clazz.newInstance();
122161 }
123162 }
124163
137176 @SuppressWarnings("unchecked")
138177 public static <T> T newInstanceOf(final String className) throws ClassNotFoundException, IllegalAccessException,
139178 InstantiationException, NoSuchMethodException, InvocationTargetException {
140 final Class<?> clazz = loadClass(className);
141 try {
142 return (T) clazz.getConstructor().newInstance();
143 } catch (final NoSuchMethodException ignored) {
144 // FIXME: looking at the code for Class.newInstance(), this seems to do the same thing as above
145 return (T) clazz.newInstance();
146 }
179 return newInstanceOf((Class<T>) loadClass(className));
147180 }
148181
149182 /**
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.util;
17
18 import java.io.Serializable;
19 import java.util.Map;
20
21 /**
22 * A read-only collection of String keys mapped to values of arbitrary type.
23 *
24 * @since 2.7
25 */
26 public interface ReadOnlyStringMap extends Serializable {
27 /**
28 * Returns a non-{@code null} mutable {@code Map<String, String>} containing a snapshot of this data structure.
29 *
30 * @return a mutable copy of this data structure in {@code Map<String, String>} form
31 */
32 Map<String, String> toMap();
33
34 /**
35 * Returns {@code true} if this data structure contains the specified key, {@code false} otherwise.
36 *
37 * @param key the key whose presence to check. May be {@code null}.
38 * @return {@code true} if this data structure contains the specified key, {@code false} otherwise
39 */
40 boolean containsKey(String key);
41
42 /**
43 * Performs the given action for each key-value pair in this data structure
44 * until all entries have been processed or the action throws an exception.
45 * <p>
46 * Some implementations may not support structural modifications (adding new elements or removing elements) while
47 * iterating over the contents. In such implementations, attempts to add or remove elements from the
48 * {@code BiConsumer}'s {@link BiConsumer#accept(Object, Object)} accept} method may cause a
49 * {@code ConcurrentModificationException} to be thrown.
50 * </p>
51 *
52 * @param action The action to be performed for each key-value pair in this collection
53 * @param <V> type of the value
54 * @throws java.util.ConcurrentModificationException some implementations may not support structural modifications
55 * to this data structure while iterating over the contents with {@link #forEach(BiConsumer)} or
56 * {@link #forEach(TriConsumer, Object)}.
57 */
58 <V> void forEach(final BiConsumer<String, ? super V> action);
59
60 /**
61 * Performs the given action for each key-value pair in this data structure
62 * until all entries have been processed or the action throws an exception.
63 * <p>
64 * The third parameter lets callers pass in a stateful object to be modified with the key-value pairs,
65 * so the TriConsumer implementation itself can be stateless and potentially reusable.
66 * </p>
67 * <p>
68 * Some implementations may not support structural modifications (adding new elements or removing elements) while
69 * iterating over the contents. In such implementations, attempts to add or remove elements from the
70 * {@code TriConsumer}'s {@link TriConsumer#accept(Object, Object, Object) accept} method may cause a
71 * {@code ConcurrentModificationException} to be thrown.
72 * </p>
73 *
74 * @param action The action to be performed for each key-value pair in this collection
75 * @param state the object to be passed as the third parameter to each invocation on the specified
76 * triconsumer
77 * @param <V> type of the value
78 * @param <S> type of the third parameter
79 * @throws java.util.ConcurrentModificationException some implementations may not support structural modifications
80 * to this data structure while iterating over the contents with {@link #forEach(BiConsumer)} or
81 * {@link #forEach(TriConsumer, Object)}.
82 */
83 <V, S> void forEach(final TriConsumer<String, ? super V, S> action, final S state);
84
85 /**
86 * Returns the value for the specified key, or {@code null} if the specified key does not exist in this collection.
87 *
88 * @param key the key whose value to return
89 * @return the value for the specified key or {@code null}
90 */
91 <V> V getValue(final String key);
92
93 /**
94 * Returns {@code true} if this collection is empty (size is zero), {@code false} otherwise.
95 * @return {@code true} if this collection is empty (size is zero)
96 */
97 boolean isEmpty();
98
99 /**
100 * Returns the number of key-value pairs in this collection.
101 *
102 * @return the number of key-value pairs in this collection
103 */
104 int size();
105 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.util;
17
18 import java.io.IOException;
19 import java.io.InvalidObjectException;
20 import java.util.Arrays;
21 import java.util.ConcurrentModificationException;
22 import java.util.HashMap;
23 import java.util.Map;
24 import java.util.Objects;
25
26 /**
27 * <em>Consider this class private.</em>
28 * Array-based implementation of the {@code ReadOnlyStringMap} interface. Keys are held in a sorted array.
29 * <p>
30 * This is not a generic collection, but makes some trade-offs to optimize for the Log4j context data use case:
31 * </p>
32 * <ul>
33 * <li>Garbage-free iteration over key-value pairs with {@code BiConsumer} and {@code TriConsumer}.</li>
34 * <li>Fast copy. If the ThreadContextMap is also an instance of {@code SortedArrayStringMap}, the full thread context
35 * data can be transferred with two array copies and two field updates.</li>
36 * <li>Acceptable performance for small data sets. The current implementation stores keys in a sorted array, values
37 * are stored in a separate array at the same index.
38 * Worst-case performance of {@code get} and {@code containsKey} is O(log N),
39 * worst-case performance of {@code put} and {@code remove} is O(N log N).
40 * The expectation is that for the small values of {@code N} (less than 100) that are the vast majority of
41 * ThreadContext use cases, the constants dominate performance more than the asymptotic performance of the
42 * algorithms used.
43 * </li>
44 * <li>Compact representation.</li>
45 * </ul>
46 *
47 * @since 2.7
48 */
49 public class SortedArrayStringMap implements StringMap {
50
51 /**
52 * The default initial capacity.
53 */
54 private static final int DEFAULT_INITIAL_CAPACITY = 4;
55 private static final long serialVersionUID = -5748905872274478116L;
56 private static final int HASHVAL = 31;
57
58 private static final TriConsumer<String, Object, StringMap> PUT_ALL = new TriConsumer<String, Object, StringMap>() {
59 @Override
60 public void accept(final String key, final Object value, final StringMap contextData) {
61 contextData.putValue(key, value);
62 }
63 };
64
65 /**
66 * An empty array instance to share when the table is not inflated.
67 */
68 private static final String[] EMPTY = {};
69 private static final String FROZEN = "Frozen collection cannot be modified";
70
71 private transient String[] keys = EMPTY;
72 private transient Object[] values = EMPTY;
73
74 /**
75 * The number of key-value mappings contained in this map.
76 */
77 private transient int size;
78
79 /**
80 * The next size value at which to resize (capacity * load factor).
81 * @serial
82 */
83 // If table == EMPTY_TABLE then this is the initial capacity at which the
84 // table will be created when inflated.
85 private int threshold;
86 private boolean immutable;
87 private transient boolean iterating;
88
89 public SortedArrayStringMap() {
90 this(DEFAULT_INITIAL_CAPACITY);
91 }
92
93 public SortedArrayStringMap(final int initialCapacity) {
94 if (initialCapacity < 1) {
95 throw new IllegalArgumentException("Initial capacity must be at least one but was " + initialCapacity);
96 }
97 threshold = ceilingNextPowerOfTwo(initialCapacity);
98 }
99
100 public SortedArrayStringMap(final ReadOnlyStringMap other) {
101 if (other instanceof SortedArrayStringMap) {
102 initFrom0((SortedArrayStringMap) other);
103 } else if (other != null) {
104 resize(ceilingNextPowerOfTwo(other.size()));
105 other.forEach(PUT_ALL, this);
106 }
107 }
108
109 private void assertNotFrozen() {
110 if (immutable) {
111 throw new UnsupportedOperationException(FROZEN);
112 }
113 }
114
115 private void assertNoConcurrentModification() {
116 if (iterating) {
117 throw new ConcurrentModificationException();
118 }
119 }
120
121 @Override
122 public void clear() {
123 if (keys == EMPTY) {
124 return;
125 }
126 assertNotFrozen();
127 assertNoConcurrentModification();
128
129 Arrays.fill(keys, 0, size, null);
130 Arrays.fill(values, 0, size, null);
131 size = 0;
132 }
133
134 @Override
135 public boolean containsKey(final String key) {
136 return indexOfKey(key) >= 0;
137 }
138
139 @Override
140 public Map<String, String> toMap() {
141 final Map<String, String> result = new HashMap<>(size());
142 for (int i = 0; i < size(); i++) {
143 final Object value = getValueAt(i);
144 result.put(getKeyAt(i), value == null ? null : String.valueOf(value));
145 }
146 return result;
147 }
148
149 @Override
150 public void freeze() {
151 immutable = true;
152 }
153
154 @Override
155 public boolean isFrozen() {
156 return immutable;
157 }
158
159 @SuppressWarnings("unchecked")
160 @Override
161 public <V> V getValue(final String key) {
162 final int index = indexOfKey(key);
163 if (index < 0) {
164 return null;
165 }
166 return (V) values[index];
167 }
168
169 @Override
170 public boolean isEmpty() {
171 return size == 0;
172 }
173
174 int indexOfKey(final String key) {
175 if (keys == EMPTY) {
176 return -1;
177 }
178 if (key == null) { // null key is located at the start of the array
179 return nullKeyIndex(); // insert at index zero
180 }
181 final int start = size > 0 && keys[0] == null ? 1 : 0;
182 return Arrays.binarySearch(keys, start, size, key);
183 }
184
185 private int nullKeyIndex() {
186 return size > 0 && keys[0] == null ? 0 : ~0;
187 }
188
189 @Override
190 public void putValue(final String key, final Object value) {
191 assertNotFrozen();
192 assertNoConcurrentModification();
193
194 if (keys == EMPTY) {
195 inflateTable(threshold);
196 }
197 final int index = indexOfKey(key);
198 if (index >= 0) {
199 keys[index] = key;
200 values[index] = value;
201 } else { // not found, so insert.
202 insertAt(~index, key, value);
203 }
204 }
205
206 private void insertAt(final int index, final String key, final Object value) {
207 ensureCapacity();
208 System.arraycopy(keys, index, keys, index + 1, size - index);
209 System.arraycopy(values, index, values, index + 1, size - index);
210 keys[index] = key;
211 values[index] = value;
212 size++;
213 }
214
215 @Override
216 public void putAll(final ReadOnlyStringMap source) {
217 if (source == this || source.isEmpty()) { // throw NPE if null
218 return; // this.putAll(this) does not modify this collection
219 }
220 assertNotFrozen();
221 assertNoConcurrentModification();
222
223 if (source instanceof SortedArrayStringMap) {
224 if (this.size == 0) {
225 initFrom0((SortedArrayStringMap) source);
226 } else {
227 merge((SortedArrayStringMap) source);
228 }
229 } else if (source != null) {
230 source.forEach(PUT_ALL, this);
231 }
232 }
233
234 private void initFrom0(final SortedArrayStringMap other) {
235 if (keys.length < other.size) {
236 keys = new String[other.threshold];
237 values = new Object[other.threshold];
238 }
239 System.arraycopy(other.keys, 0, keys, 0, other.size);
240 System.arraycopy(other.values, 0, values, 0, other.size);
241
242 size = other.size;
243 threshold = other.threshold;
244 }
245
246 private void merge(final SortedArrayStringMap other) {
247 final String[] myKeys = keys;
248 final Object[] myVals = values;
249 final int newSize = other.size + this.size;
250 threshold = ceilingNextPowerOfTwo(newSize);
251 if (keys.length < threshold) {
252 keys = new String[threshold];
253 values = new Object[threshold];
254 }
255 // move largest collection to the beginning of this data structure, smallest to the end
256 boolean overwrite = true;
257 if (other.size() > size()) {
258 // move original key-values to end
259 System.arraycopy(myKeys, 0, keys, other.size, this.size);
260 System.arraycopy(myVals, 0, values, other.size, this.size);
261
262 // insert additional key-value pairs at the beginning
263 System.arraycopy(other.keys, 0, keys, 0, other.size);
264 System.arraycopy(other.values, 0, values, 0, other.size);
265 size = other.size;
266
267 // loop over original keys and insert (drop values for same key)
268 overwrite = false;
269 } else {
270 System.arraycopy(myKeys, 0, keys, 0, this.size);
271 System.arraycopy(myVals, 0, values, 0, this.size);
272
273 // move additional key-value pairs to end
274 System.arraycopy(other.keys, 0, keys, this.size, other.size);
275 System.arraycopy(other.values, 0, values, this.size, other.size);
276
277 // new values are at the end, will be processed below. Overwrite is true.
278 }
279 for (int i = size; i < newSize; i++) {
280 final int index = indexOfKey(keys[i]);
281 if (index < 0) { // key does not exist
282 insertAt(~index, keys[i], values[i]);
283 } else if (overwrite) { // existing key: only overwrite when looping over the new values
284 keys[index] = keys[i];
285 values[index] = values[i];
286 }
287 }
288 // prevent memory leak: null out references
289 Arrays.fill(keys, size, newSize, null);
290 Arrays.fill(values, size, newSize, null);
291 }
292
293 private void ensureCapacity() {
294 if (size >= threshold) {
295 resize(threshold * 2);
296 }
297 }
298
299 private void resize(final int newCapacity) {
300 final String[] oldKeys = keys;
301 final Object[] oldValues = values;
302
303 keys = new String[newCapacity];
304 values = new Object[newCapacity];
305
306 System.arraycopy(oldKeys, 0, keys, 0, size);
307 System.arraycopy(oldValues, 0, values, 0, size);
308
309 threshold = newCapacity;
310 }
311
312 /**
313 * Inflates the table.
314 */
315 private void inflateTable(final int toSize) {
316 threshold = toSize;
317 keys = new String[toSize];
318 values = new Object[toSize];
319 }
320
321 @Override
322 public void remove(final String key) {
323 if (keys == EMPTY) {
324 return;
325 }
326
327 final int index = indexOfKey(key);
328 if (index >= 0) {
329 assertNotFrozen();
330 assertNoConcurrentModification();
331
332 System.arraycopy(keys, index + 1, keys, index, size - 1 - index);
333 System.arraycopy(values, index + 1, values, index, size - 1 - index);
334 keys[size - 1] = null;
335 values[size - 1] = null;
336 size--;
337 }
338 }
339
340 String getKeyAt(final int index) {
341 if (index < 0 || index >= size) {
342 return null;
343 }
344 return keys[index];
345 }
346
347 @SuppressWarnings("unchecked")
348 <V> V getValueAt(final int index) {
349 if (index < 0 || index >= size) {
350 return null;
351 }
352 return (V) values[index];
353 }
354
355 @Override
356 public int size() {
357 return size;
358 }
359
360 @SuppressWarnings("unchecked")
361 @Override
362 public <V> void forEach(final BiConsumer<String, ? super V> action) {
363 iterating = true;
364 try {
365 for (int i = 0; i < size; i++) {
366 action.accept(keys[i], (V) values[i]);
367 }
368 } finally {
369 iterating = false;
370 }
371 }
372
373 @SuppressWarnings("unchecked")
374 @Override
375 public <V, T> void forEach(final TriConsumer<String, ? super V, T> action, final T state) {
376 iterating = true;
377 try {
378 for (int i = 0; i < size; i++) {
379 action.accept(keys[i], (V) values[i], state);
380 }
381 } finally {
382 iterating = false;
383 }
384 }
385
386 @Override
387 public boolean equals(final Object obj) {
388 if (obj == this) {
389 return true;
390 }
391 if (!(obj instanceof SortedArrayStringMap)) {
392 return false;
393 }
394 final SortedArrayStringMap other = (SortedArrayStringMap) obj;
395 if (this.size() != other.size()) {
396 return false;
397 }
398 for (int i = 0; i < size(); i++) {
399 if (!Objects.equals(keys[i], other.keys[i])) {
400 return false;
401 }
402 if (!Objects.equals(values[i], other.values[i])) {
403 return false;
404 }
405 }
406 return true;
407 }
408
409 @Override
410 public int hashCode() {
411 int result = 37;
412 result = HASHVAL * result + size;
413 result = HASHVAL * result + hashCode(keys, size);
414 result = HASHVAL * result + hashCode(values, size);
415 return result;
416 }
417
418 private static int hashCode(final Object[] values, final int length) {
419 int result = 1;
420 for (int i = 0; i < length; i++) {
421 result = HASHVAL * result + (values[i] == null ? 0 : values[i].hashCode());
422 }
423 return result;
424 }
425
426 @Override
427 public String toString() {
428 final StringBuilder sb = new StringBuilder(256);
429 sb.append('{');
430 for (int i = 0; i < size; i++) {
431 if (i > 0) {
432 sb.append(", ");
433 }
434 sb.append(keys[i]).append('=');
435 sb.append(values[i] == this ? "(this map)" : values[i]);
436 }
437 sb.append('}');
438 return sb.toString();
439 }
440
441 /**
442 * Save the state of the {@code SortedArrayStringMap} instance to a stream (i.e.,
443 * serialize it).
444 *
445 * @serialData The <i>capacity</i> of the SortedArrayStringMap (the length of the
446 * bucket array) is emitted (int), followed by the
447 * <i>size</i> (an int, the number of key-value
448 * mappings), followed by the key (Object) and value (Object)
449 * for each key-value mapping. The key-value mappings are
450 * emitted in no particular order.
451 */
452 private void writeObject(final java.io.ObjectOutputStream s) throws IOException {
453 // Write out the threshold, and any hidden stuff
454 s.defaultWriteObject();
455
456 // Write out number of buckets
457 if (keys == EMPTY) {
458 s.writeInt(ceilingNextPowerOfTwo(threshold));
459 } else {
460 s.writeInt(keys.length);
461 }
462
463 // Write out size (number of Mappings)
464 s.writeInt(size);
465
466 // Write out keys and values (alternating)
467 if (size > 0) {
468 for (int i = 0; i < size; i++) {
469 s.writeObject(keys[i]);
470 s.writeObject(values[i]);
471 }
472 }
473 }
474
475
476 /**
477 * Calculate the next power of 2, greater than or equal to x.
478 * <p>
479 * From Hacker's Delight, Chapter 3, Harry S. Warren Jr.
480 *
481 * @param x Value to round up
482 * @return The next power of 2 from x inclusive
483 */
484 private static int ceilingNextPowerOfTwo(final int x) {
485 final int BITS_PER_INT = 32;
486 return 1 << (BITS_PER_INT - Integer.numberOfLeadingZeros(x - 1));
487 }
488
489 /**
490 * Reconstitute the {@code SortedArrayStringMap} instance from a stream (i.e.,
491 * deserialize it).
492 */
493 private void readObject(final java.io.ObjectInputStream s) throws IOException, ClassNotFoundException {
494 // Read in the threshold (ignored), and any hidden stuff
495 s.defaultReadObject();
496
497 // set other fields that need values
498 keys = EMPTY;
499 values = EMPTY;
500
501 // Read in number of buckets
502 final int capacity = s.readInt();
503 if (capacity < 0) {
504 throw new InvalidObjectException("Illegal capacity: " + capacity);
505 }
506
507 // Read number of mappings
508 final int mappings = s.readInt();
509 if (mappings < 0) {
510 throw new InvalidObjectException("Illegal mappings count: " + mappings);
511 }
512
513 // allocate the bucket array;
514 if (mappings > 0) {
515 inflateTable(capacity);
516 } else {
517 threshold = capacity;
518 }
519
520 // Read the keys and values, and put the mappings in the arrays
521 for (int i = 0; i < mappings; i++) {
522 keys[i] = (String) s.readObject();
523 values[i] = s.readObject();
524 }
525 size = mappings;
526 }
527 }
2626
2727 /**
2828 * Appends in the following format: double quoted value.
29 *
29 *
3030 * @param sb a string builder
3131 * @param value a value
3232 * @return {@code "value"}
3737
3838 /**
3939 * Appends in the following format: key=double quoted value.
40 *
40 *
4141 * @param sb a string builder
4242 * @param entry a map entry
4343 * @return {@code key="value"}
4848
4949 /**
5050 * Appends in the following format: key=double quoted value.
51 *
51 *
5252 * @param sb a string builder
5353 * @param key a key
5454 * @param value a value
5858 return sb.append(key).append(Chars.EQ).append(Chars.DQUOTE).append(value).append(Chars.DQUOTE);
5959 }
6060
61 /**
62 * Appends a text representation of the specified object to the specified StringBuilder,
63 * if possible without allocating temporary objects.
64 *
65 * @param stringBuilder the StringBuilder to append the value to
66 * @param obj the object whose text representation to append to the StringBuilder
67 */
68 public static void appendValue(final StringBuilder stringBuilder, final Object obj) {
69 if (obj == null || obj instanceof String) {
70 stringBuilder.append((String) obj);
71 } else if (obj instanceof StringBuilderFormattable) {
72 ((StringBuilderFormattable) obj).formatTo(stringBuilder);
73 } else if (obj instanceof CharSequence) {
74 stringBuilder.append((CharSequence) obj);
75 } else if (obj instanceof Integer) { // LOG4J2-1437 unbox auto-boxed primitives to avoid calling toString()
76 stringBuilder.append(((Integer) obj).intValue());
77 } else if (obj instanceof Long) {
78 stringBuilder.append(((Long) obj).longValue());
79 } else if (obj instanceof Double) {
80 stringBuilder.append(((Double) obj).doubleValue());
81 } else if (obj instanceof Boolean) {
82 stringBuilder.append(((Boolean) obj).booleanValue());
83 } else if (obj instanceof Character) {
84 stringBuilder.append(((Character) obj).charValue());
85 } else if (obj instanceof Short) {
86 stringBuilder.append(((Short) obj).shortValue());
87 } else if (obj instanceof Float) {
88 stringBuilder.append(((Float) obj).floatValue());
89 } else {
90 stringBuilder.append(obj);
91 }
92 }
6193 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.util;
17
18 /**
19 * Exposes methods to add and remove key-value pairs to and from {@code ReadOnlyStringMap}.
20 *
21 * @see ReadOnlyStringMap
22 * @since 2.7
23 */
24 public interface StringMap extends ReadOnlyStringMap {
25
26 /**
27 * Removes all key-value pairs from this collection.
28 * @throws java.util.ConcurrentModificationException some implementations may not support structural modifications
29 * to this data structure while iterating over the contents with {@link #forEach(BiConsumer)} or
30 * {@link #forEach(TriConsumer, Object)}.
31 * @throws UnsupportedOperationException if this collection has been {@linkplain #isFrozen() frozen}.
32 */
33 void clear();
34
35 /**
36 * Indicates whether some other object is "equal to" this one.
37 *
38 * @param obj
39 * the reference object with which to compare.
40 * @return {@code true} if this object is the same as the obj argument; {@code false} otherwise.
41 * @see #hashCode()
42 */
43 @Override
44 boolean equals(final Object obj);
45
46 /**
47 * Makes this collection immutable. Attempts to modify the collection after the {@code freeze()} method was called
48 * will result in an {@code UnsupportedOperationException} being thrown.
49 */
50 void freeze();
51
52 /**
53 * Returns a hash code value for the object.
54 * @return a hash code value for this object.
55 */
56 @Override
57 int hashCode();
58
59 /**
60 * Returns {@code true} if this object has been {@linkplain #freeze() frozen}, {@code false} otherwise.
61 * @return {@code true} if this object has been {@linkplain #freeze() frozen}, {@code false} otherwise
62 */
63 boolean isFrozen();
64
65 /**
66 * Copy all key-value pairs from the specified {@code ReadOnlyStringMap} into this {@code StringMap}.
67 * @param source the {@code ReadOnlyStringMap} to copy key-value pairs from
68 * @throws java.util.ConcurrentModificationException some implementations may not support structural modifications
69 * to this data structure while iterating over the contents with {@link #forEach(BiConsumer)} or
70 * {@link #forEach(TriConsumer, Object)}.
71 * @throws UnsupportedOperationException if this collection has been {@linkplain #isFrozen() frozen}.
72 */
73 void putAll(final ReadOnlyStringMap source);
74
75 /**
76 * Puts the specified key-value pair into the collection.
77 *
78 * @param key the key to add or remove. Keys may be {@code null}.
79 * @param value the value to add. Values may be {@code null}.
80 * @throws java.util.ConcurrentModificationException some implementations may not support structural modifications
81 * to this data structure while iterating over the contents with {@link #forEach(BiConsumer)} or
82 * {@link #forEach(TriConsumer, Object)}.
83 * @throws UnsupportedOperationException if this collection has been {@linkplain #isFrozen() frozen}.
84 */
85 void putValue(final String key, final Object value);
86
87 /**
88 * Removes the key-value pair for the specified key from this data structure.
89 *
90 * @param key the key to remove. May be {@code null}.
91 * @throws java.util.ConcurrentModificationException some implementations may not support structural modifications
92 * to this data structure while iterating over the contents with {@link #forEach(BiConsumer)} or
93 * {@link #forEach(TriConsumer, Object)}.
94 * @throws UnsupportedOperationException if this collection has been {@linkplain #isFrozen() frozen}.
95 */
96 void remove(final String key);
97 }
1515 */
1616 package org.apache.logging.log4j.util;
1717
18 import java.util.Iterator;
1819 import java.util.Locale;
20 import java.util.Objects;
1921
2022 /**
2123 * <em>Consider this class private.</em>
2830 * The empty string.
2931 */
3032 public static final String EMPTY = "";
33
34 /**
35 * OS-dependent line separator, defaults to {@code "\n"} if the system property {@code ""line.separator"} cannot be
36 * read.
37 */
38 public static final String LINE_SEPARATOR = PropertiesUtil.getProperties().getStringProperty("line.separator",
39 "\n");
3140
3241 private Strings() {
3342 // empty
165174 final String ts = str == null ? null : str.trim();
166175 return isEmpty(ts) ? null : ts;
167176 }
177
178 /**
179 * <p>Joins the elements of the provided {@code Iterable} into
180 * a single String containing the provided elements.</p>
181 *
182 * <p>No delimiter is added before or after the list. Null objects or empty
183 * strings within the iteration are represented by empty strings.</p>
184 *
185 * @param iterable the {@code Iterable} providing the values to join together, may be null
186 * @param separator the separator character to use
187 * @return the joined String, {@code null} if null iterator input
188 */
189 public static String join(final Iterable<?> iterable, final char separator) {
190 if (iterable == null) {
191 return null;
192 }
193 return join(iterable.iterator(), separator);
194 }
195
196 /**
197 * <p>Joins the elements of the provided {@code Iterator} into
198 * a single String containing the provided elements.</p>
199 *
200 * <p>No delimiter is added before or after the list. Null objects or empty
201 * strings within the iteration are represented by empty strings.</p>
202 *
203 * @param iterator the {@code Iterator} of values to join together, may be null
204 * @param separator the separator character to use
205 * @return the joined String, {@code null} if null iterator input
206 */
207 public static String join(final Iterator<?> iterator, final char separator) {
208
209 // handle null, zero and one elements before building a buffer
210 if (iterator == null) {
211 return null;
212 }
213 if (!iterator.hasNext()) {
214 return EMPTY;
215 }
216 final Object first = iterator.next();
217 if (!iterator.hasNext()) {
218 return Objects.toString(first);
219 }
220
221 // two or more elements
222 final StringBuilder buf = new StringBuilder(256); // Java default is 16, probably too small
223 if (first != null) {
224 buf.append(first);
225 }
226
227 while (iterator.hasNext()) {
228 buf.append(separator);
229 final Object obj = iterator.next();
230 if (obj != null) {
231 buf.append(obj);
232 }
233 }
234
235 return buf.toString();
236 }
237
168238 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.util;
17
18 /**
19 * An operation that accepts three input arguments and returns no result.
20 *
21 * @param <K> type of the first argument
22 * @param <V> type of the second argument
23 * @param <S> type of the third argument
24 * @see ReadOnlyStringMap
25 * @since 2.7
26 */
27 public interface TriConsumer<K, V, S> {
28
29 /**
30 * Performs the operation given the specified arguments.
31 * @param k the first input argument
32 * @param v the second input argument
33 * @param s the third input argument
34 */
35 void accept(K k, V v, S s);
36 }
4242 * If more slots are required, set system property {@code log4j.unbox.ringbuffer.size} to the desired ring buffer size.
4343 * Note that the specified number will be rounded up to the nearest power of 2.
4444 * </p>
45 * @since 2.6
4546 */
4647 @PerformanceSensitive("allocation")
4748 public class Unbox {
1818 import static org.hamcrest.CoreMatchers.is;
1919 import static org.junit.Assert.assertThat;
2020
21 import org.junit.Before;
21 import org.apache.logging.log4j.junit.ThreadContextRule;
22 import org.junit.Rule;
2223 import org.junit.Test;
2324
2425 /**
3031
3132 private final String key = "key";
3233 private final String value = "value";
33
34 @Before
35 public void setUp() throws Exception {
36 ThreadContext.clearAll();
37 }
34
35 @Rule
36 public final ThreadContextRule threadContextRule = new ThreadContextRule();
3837
3938 @Test
4039 public void shouldAddAnEntryToTheMap() throws Exception {
251251 assertEquals(String.format(" DEBUG %,d", Integer.MAX_VALUE), testLogger.getEntries().get(0));
252252 }
253253
254 private static void assertMessageFactoryInstanceOf(MessageFactory factory, final Class cls) {
254 private static void assertMessageFactoryInstanceOf(MessageFactory factory, final Class<?> cls) {
255255 if (factory instanceof MessageFactory2Adapter) {
256256 factory = ((MessageFactory2Adapter) factory).getOriginal();
257257 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16
17 package org.apache.logging.log4j;
18
19 import java.util.Map;
20
21 import org.apache.logging.log4j.ThreadContext.ContextStack;
22
23 /**
24 * Holds an immutable copy of the ThreadContext stack and map.
25 *
26 * TODO Use LOG4J2-1517 Add ThreadContext.setContext(Map<String, String>)
27 *
28 * or
29 *
30 * TODO Might be replaced by something from LOG4J2-1447.
31 *
32 * or do nothing.
33 *
34 * @since 2.7
35 */
36 public class ThreadContextHolder {
37
38 private final Map<String, String> immutableContext;
39 private final ContextStack immutableStack;
40 private final boolean restoreContext;
41 private final boolean restoreStack;
42
43 /**
44 * Constructs a new holder initialized with an immutable copy of the ThreadContext stack and map.
45 *
46 * @param restoreContext
47 * @param restoreStack
48 */
49 public ThreadContextHolder(final boolean restoreContext, final boolean restoreStack) {
50 this.restoreContext = restoreContext;
51 this.restoreStack = restoreStack;
52 this.immutableContext = restoreContext ? ThreadContext.getImmutableContext() : null;
53 this.immutableStack = restoreStack ? ThreadContext.getImmutableStack() : null;
54 }
55
56 /**
57 * Restores the ThreadContext stack and map based on the values saved in the constructor.
58 */
59 public void restore() {
60 if (restoreStack) {
61 ThreadContext.setStack(immutableStack);
62 }
63 if (restoreContext) {
64 // TODO LOG4J2-1517 Add ThreadContext.setContext(Map<String, String>)
65 // Use:
66 // ThreadContext.setContext(immutableContext);
67 // Instead of:
68 ThreadContext.clearMap();
69 ThreadContext.putAll(immutableContext);
70 //
71 // or:
72 // ThreadContext.clearMap();
73 // for (Map.Entry<String, String> entry : immutableContext.entrySet()) {
74 // ThreadContext.put(entry.getKey(), entry.getValue());
75 // }
76 }
77 }
78 }
1515 */
1616 package org.apache.logging.log4j;
1717
18 import java.util.HashMap;
1819 import java.util.Map;
1920
2021 import org.junit.Test;
150151 }
151152
152153 @Test
154 public void testPutAll() {
155 ThreadContext.clearMap();
156 //
157 assertTrue(ThreadContext.isEmpty());
158 assertFalse(ThreadContext.containsKey("key"));
159 final int mapSize = 10;
160 final Map<String, String> newMap = new HashMap<>(mapSize);
161 for (int i = 1; i <= mapSize; i++) {
162 newMap.put("key" + i, "value" + i);
163 }
164 ThreadContext.putAll(newMap);
165 assertFalse(ThreadContext.isEmpty());
166 for (int i = 1; i <= mapSize; i++) {
167 assertTrue(ThreadContext.containsKey("key" + i));
168 assertEquals("value" + i, ThreadContext.get("key" + i));
169 }
170 }
171
172 @Test
153173 public void testRemove() {
154174 ThreadContext.clearMap();
155175 assertNull(ThreadContext.get("testKey"));
2323 import org.apache.logging.log4j.message.ParameterizedMessage;
2424 import org.apache.logging.log4j.message.ReusableParameterizedMessage;
2525 import org.apache.logging.log4j.message.ReusableParameterizedMessageTest;
26 import org.apache.logging.log4j.message.ReusableSimpleMessage;
2726 import org.apache.logging.log4j.message.SimpleMessage;
2827 import org.apache.logging.log4j.spi.AbstractLogger;
2928 import org.junit.Test;
266265 @Test
267266 public void testTraceEntryExit() {
268267 currentLevel = Level.TRACE;
269 FlowMessageFactory fact = new DefaultFlowMessageFactory();
270
271 ParameterizedMessage paramMsg = new ParameterizedMessage("Tracy {}", "Logan");
268 final FlowMessageFactory fact = new DefaultFlowMessageFactory();
269
270 final ParameterizedMessage paramMsg = new ParameterizedMessage("Tracy {}", "Logan");
272271 currentEvent = new LogEvent(ENTRY_MARKER.getName(), fact.newEntryMessage(paramMsg), null);
273 EntryMessage entry = traceEntry("Tracy {}", "Logan");
274
275 ReusableParameterizedMessage msg = ReusableParameterizedMessageTest.set(
272 final EntryMessage entry = traceEntry("Tracy {}", "Logan");
273
274 final ReusableParameterizedMessage msg = ReusableParameterizedMessageTest.set(
276275 new ReusableParameterizedMessage(), "Tracy {}", "Logan");
277276 ReusableParameterizedMessageTest.set(msg, "Some other message {}", 123);
278277 currentEvent = new LogEvent(null, msg, null);
291290 @Test
292291 public void testTraceEntryMessage() {
293292 currentLevel = Level.TRACE;
294 FlowMessageFactory fact = new DefaultFlowMessageFactory();
295
296 ParameterizedMessage paramMsg = new ParameterizedMessage("Tracy {}", "Logan");
293 final FlowMessageFactory fact = new DefaultFlowMessageFactory();
294
295 final ParameterizedMessage paramMsg = new ParameterizedMessage("Tracy {}", "Logan");
297296 currentEvent = new LogEvent(ENTRY_MARKER.getName(), fact.newEntryMessage(paramMsg), null);
298297
299 ReusableParameterizedMessage msg = ReusableParameterizedMessageTest.set(
298 final ReusableParameterizedMessage msg = ReusableParameterizedMessageTest.set(
300299 new ReusableParameterizedMessage(), "Tracy {}", "Logan");
301 EntryMessage entry = traceEntry(msg);
300 final EntryMessage entry = traceEntry(msg);
302301
303302 ReusableParameterizedMessageTest.set(msg, "Some other message {}", 123);
304303 currentEvent = new LogEvent(null, msg, null);
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16
17 package org.apache.logging.log4j.junit;
18
19 import java.io.FileReader;
20 import java.io.IOException;
21
22 import org.apache.maven.model.Model;
23 import org.apache.maven.model.io.xpp3.MavenXpp3Reader;
24 import org.apache.maven.project.MavenProject;
25 import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
26
27 /**
28 * Provides tests with bundle information. Reads the {@code pom.xml} in the current directory to get project settings.
29 */
30 public class BundleTestInfo {
31
32 private final MavenProject project;
33
34 /**
35 * Constructs a new helper objects and initializes itself.
36 */
37 public BundleTestInfo() {
38 try (final FileReader reader = new FileReader("pom.xml")) {
39 // get a raw POM view, not a fully realized POM object.
40 final Model model = new MavenXpp3Reader().read(reader);
41 this.project = new MavenProject(model);
42 } catch (final IOException | XmlPullParserException e) {
43 throw new IllegalStateException("Could not read pom.xml", e);
44 }
45 }
46
47 /**
48 * Gets the Maven artifact ID.
49 *
50 * @return the Maven artifact ID.
51 */
52 public String getArtifactId() {
53 return project.getArtifactId();
54 }
55
56 /**
57 * Gets the Maven version String.
58 *
59 * @return the Maven version String.
60 */
61 public String getVersion() {
62 return project.getVersion();
63 }
64
65 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16
17 package org.apache.logging.log4j.junit;
18
19 import java.io.FileReader;
20 import java.io.IOException;
21
22 import org.apache.maven.model.Model;
23 import org.apache.maven.model.io.xpp3.MavenXpp3Reader;
24 import org.apache.maven.project.MavenProject;
25 import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
26
27 /**
28 * Provides tests with bundle information. Reads the {@code pom.xml} in the current directory to get project settings.
29 */
30 public class BundleTestInfo {
31
32 private final MavenProject project;
33
34 /**
35 * Constructs a new helper objects and initializes itself.
36 */
37 public BundleTestInfo() {
38 try (final FileReader reader = new FileReader("pom.xml")) {
39 // get a raw POM view, not a fully realized POM object.
40 final Model model = new MavenXpp3Reader().read(reader);
41 this.project = new MavenProject(model);
42 } catch (final IOException | XmlPullParserException e) {
43 throw new IllegalStateException("Could not read pom.xml", e);
44 }
45 }
46
47 /**
48 * Gets the Maven artifact ID.
49 *
50 * @return the Maven artifact ID.
51 */
52 public String getArtifactId() {
53 return project.getArtifactId();
54 }
55
56 /**
57 * Gets the Maven version String.
58 *
59 * @return the Maven version String.
60 */
61 public String getVersion() {
62 return project.getVersion();
63 }
64
65 @Override
66 public String toString() {
67 return "BundleTestInfo [project=" + project + "]";
68 }
69
70 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16
17 package org.apache.logging.log4j.junit;
18
19 import java.util.HashMap;
20 import java.util.Map;
21
22 import org.junit.rules.ExternalResource;
23 import org.osgi.framework.BundleException;
24 import org.osgi.framework.launch.Framework;
25 import org.osgi.framework.launch.FrameworkFactory;
26
27 /**
28 * JUnit rule to initialize and shutdown an OSGi framework.
29 */
30 public class OsgiRule extends ExternalResource {
31
32 private final FrameworkFactory factory;
33 private Framework framework;
34
35 public OsgiRule(final FrameworkFactory factory) {
36 this.factory = factory;
37 }
38
39 public Framework getFramework() {
40 return framework;
41 }
42
43 @Override
44 protected void before() throws Throwable {
45 final Map<String, String> configMap = new HashMap<>(2);
46 // Cleans framework before first init. Subsequent init invocations do not clean framework.
47 configMap.put("org.osgi.framework.storage.clean", "onFirstInit");
48 // Delegates loading of endorsed libraries to JVM classloader
49 // config.put("org.osgi.framework.bootdelegation", "javax.*,org.w3c.*,org.xml.*");
50 framework = factory.newFramework(configMap);
51 framework.init();
52 framework.start();
53 }
54
55 @Override
56 protected void after() {
57 if (framework != null) {
58 try {
59 framework.stop();
60 } catch (final BundleException e) {
61 throw new RuntimeException(e);
62 } finally {
63 framework = null;
64 }
65 }
66 }
67 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16
17 package org.apache.logging.log4j.junit;
18
19 import java.util.HashMap;
20 import java.util.Map;
21
22 import org.junit.rules.ExternalResource;
23 import org.osgi.framework.BundleException;
24 import org.osgi.framework.launch.Framework;
25 import org.osgi.framework.launch.FrameworkFactory;
26
27 /**
28 * JUnit rule to initialize and shutdown an OSGi framework.
29 */
30 public class OsgiRule extends ExternalResource {
31
32 private final FrameworkFactory factory;
33 private Framework framework;
34
35 public OsgiRule(final FrameworkFactory factory) {
36 this.factory = factory;
37 }
38
39 public Framework getFramework() {
40 return framework;
41 }
42
43 @Override
44 protected void before() throws Throwable {
45 final Map<String, String> configMap = new HashMap<>(2);
46 // Cleans framework before first init. Subsequent init invocations do not clean framework.
47 configMap.put("org.osgi.framework.storage.clean", "onFirstInit");
48 // Delegates loading of endorsed libraries to JVM classloader
49 // config.put("org.osgi.framework.bootdelegation", "javax.*,org.w3c.*,org.xml.*");
50 framework = factory.newFramework(configMap);
51 framework.init();
52 framework.start();
53 }
54
55 @Override
56 protected void after() {
57 if (framework != null) {
58 try {
59 framework.stop();
60 } catch (final BundleException e) {
61 throw new RuntimeException(e);
62 } finally {
63 framework = null;
64 }
65 }
66 }
67
68 @Override
69 public String toString() {
70 return "OsgiRule [factory=" + factory + ", framework=" + framework + "]";
71 }
72 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.junit;
17
18 /**
19 * Restores the ThreadContext to it's initial map values after a JUnit test.
20 *
21 * Usage:
22 *
23 * <pre>
24 * &#64;Rule
25 * public final ThreadContextMapRule threadContextRule = new ThreadContextMapRule();
26 * </pre>
27 */
28 public class ThreadContextMapRule extends ThreadContextRule {
29
30 /**
31 * Constructs an initialized instance.
32 */
33 public ThreadContextMapRule() {
34 super(true, false);
35 }
36 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.junit;
17
18 import org.apache.logging.log4j.ThreadContext;
19 import org.apache.logging.log4j.ThreadContextHolder;
20 import org.junit.rules.ExternalResource;
21
22 /**
23 * Restores the ThreadContext to it's initial map and stack values after a JUnit test.
24 *
25 * Usage:
26 *
27 * <pre>
28 * &#64;Rule
29 * public final ThreadContextRule threadContextRule = new ThreadContextRule();
30 * </pre>
31 */
32 public class ThreadContextRule extends ExternalResource {
33
34 private final boolean restoreMap;
35 private final boolean restoreStack;
36 private ThreadContextHolder threadContextHolder;
37
38 /**
39 * Constructs an instance initialized to restore the stack and map.
40 */
41 public ThreadContextRule() {
42 this(true, true);
43 }
44
45 /**
46 * Constructs an instance initialized to restore the given structures.
47 *
48 * @param restoreMap
49 * Whether to restore the thread context map.
50 * @param restoreStack
51 * Whether to restore the thread context stack.
52 */
53 public ThreadContextRule(final boolean restoreMap, final boolean restoreStack) {
54 super();
55 this.restoreMap = restoreMap;
56 this.restoreStack = restoreStack;
57 }
58
59 @Override
60 protected void after() {
61 if (threadContextHolder != null) {
62 threadContextHolder.restore();
63 }
64 }
65
66 @Override
67 protected void before() throws Throwable {
68 threadContextHolder = new ThreadContextHolder(restoreMap, restoreStack);
69 if (restoreMap) {
70 ThreadContext.clearMap();
71 }
72 if (restoreStack) {
73 ThreadContext.clearStack();
74 }
75 }
76
77 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.junit;
17
18 /**
19 * Restores the ThreadContext to it's initial stack values after a JUnit test.
20 *
21 * Usage:
22 *
23 * <pre>
24 * &#64;Rule
25 * public final ThreadContextStackRule threadContextRule = new ThreadContextStackRule();
26 * </pre>
27 */
28 public class ThreadContextStackRule extends ThreadContextRule {
29
30 /**
31 * Constructs an initialized instance.
32 */
33 public ThreadContextStackRule() {
34 super(false, true);
35 }
36 }
2929 public void testNoArgs() {
3030 final String testMsg = "Test message {}";
3131 ParameterizedMessage msg = new ParameterizedMessage(testMsg, null);
32 String result = msg.getFormattedMessage();
33 assertEquals(testMsg, result);
34 final Object[] array = null;
35 msg = new ParameterizedMessage(testMsg, array, null);
36 result = msg.getFormattedMessage();
37 assertEquals(testMsg, result);
38 }
39
40 @Test
41 public void testZeroLength() {
42 final String testMsg = "";
43 ParameterizedMessage msg = new ParameterizedMessage(testMsg, new String[]{"arg"});
44 String result = msg.getFormattedMessage();
45 assertEquals(testMsg, result);
46 final Object[] array = null;
47 msg = new ParameterizedMessage(testMsg, array, null);
48 result = msg.getFormattedMessage();
49 assertEquals(testMsg, result);
50 }
51
52 @Test
53 public void testOneCharLength() {
54 final String testMsg = "d";
55 ParameterizedMessage msg = new ParameterizedMessage(testMsg, new String[]{"arg"});
3256 String result = msg.getFormattedMessage();
3357 assertEquals(testMsg, result);
3458 final Object[] array = null;
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.message;
17
18 import org.junit.Test;
19
20 import static org.junit.Assert.*;
21
22 /**
23 * Tests the ReusableMessageFactory class.
24 */
25 public class ReusableMessageFactoryTest {
26
27 @Test
28 public void testCreateEventReturnsDifferentInstanceIfNotReleased() throws Exception {
29 final ReusableMessageFactory factory = new ReusableMessageFactory();
30 final Message message1 = factory.newMessage("text, p0={} p1={} p2={} p3={}", 1, 2, 3, 4);
31 final Message message2 = factory.newMessage("text, p0={} p1={} p2={} p3={}", 9, 8, 7, 6);
32 assertNotSame(message1, message2);
33 ReusableMessageFactory.release(message1);
34 ReusableMessageFactory.release(message2);
35 }
36
37 @Test
38 public void testCreateEventReturnsSameInstance() throws Exception {
39 final ReusableMessageFactory factory = new ReusableMessageFactory();
40 final Message message1 = factory.newMessage("text, p0={} p1={} p2={} p3={}", 1, 2, 3, 4);
41
42 ReusableMessageFactory.release(message1);
43 final Message message2 = factory.newMessage("text, p0={} p1={} p2={} p3={}", 9, 8, 7, 6);
44 assertSame(message1, message2);
45
46 ReusableMessageFactory.release(message2);
47 final Message message3 = factory.newMessage("text, AAA={} BBB={} p2={} p3={}", 9, 8, 7, 6);
48 assertSame(message2, message3);
49 ReusableMessageFactory.release(message3);
50 }
51
52 private void assertReusableParameterizeMessage(final Message message, final String txt, final Object[] params) {
53 assertTrue(message instanceof ReusableParameterizedMessage);
54 final ReusableParameterizedMessage msg = (ReusableParameterizedMessage) message;
55 assertTrue("reserved", msg.reserved);
56
57 assertEquals(txt, msg.getFormat());
58 assertEquals("count", msg.getParameterCount(), params.length);
59 final Object[] messageParams = msg.getParameters();
60 for (int i = 0; i < params.length; i++) {
61 assertEquals(messageParams[i], params[i]);
62 }
63 }
64
65 @Test
66 public void testCreateEventOverwritesFields() throws Exception {
67 final ReusableMessageFactory factory = new ReusableMessageFactory();
68 final Message message1 = factory.newMessage("text, p0={} p1={} p2={} p3={}", 1, 2, 3, 4);
69 assertReusableParameterizeMessage(message1, "text, p0={} p1={} p2={} p3={}", new Object[]{
70 new Integer(1), //
71 new Integer(2), //
72 new Integer(3), //
73 new Integer(4), //
74 });
75
76 ReusableMessageFactory.release(message1);
77 final Message message2 = factory.newMessage("other, A={} B={} C={} D={}", 1, 2, 3, 4);
78 assertReusableParameterizeMessage(message1, "other, A={} B={} C={} D={}", new Object[]{
79 new Integer(1), //
80 new Integer(2), //
81 new Integer(3), //
82 new Integer(4), //
83 });
84 assertSame(message1, message2);
85 ReusableMessageFactory.release(message2);
86 }
87
88 @Test
89 public void testCreateEventReturnsThreadLocalInstance() throws Exception {
90 final ReusableMessageFactory factory = new ReusableMessageFactory();
91 final Message[] message1 = new Message[1];
92 final Message[] message2 = new Message[1];
93 final Thread t1 = new Thread("THREAD 1") {
94 @Override
95 public void run() {
96 message1[0] = factory.newMessage("text, p0={} p1={} p2={} p3={}", 1, 2, 3, 4);
97 }
98 };
99 final Thread t2 = new Thread("Thread 2") {
100 @Override
101 public void run() {
102 message2[0] = factory.newMessage("other, A={} B={} C={} D={}", 1, 2, 3, 4);
103 }
104 };
105 t1.start();
106 t2.start();
107 t1.join();
108 t2.join();
109 assertNotNull(message1[0]);
110 assertNotNull(message2[0]);
111 assertNotSame(message1[0], message2[0]);
112 assertReusableParameterizeMessage(message1[0], "text, p0={} p1={} p2={} p3={}", new Object[]{
113 new Integer(1), //
114 new Integer(2), //
115 new Integer(3), //
116 new Integer(4), //
117 });
118
119 assertReusableParameterizeMessage(message2[0], "other, A={} B={} C={} D={}", new Object[]{
120 new Integer(1), //
121 new Integer(2), //
122 new Integer(3), //
123 new Integer(4), //
124 });
125 ReusableMessageFactory.release(message1[0]);
126 ReusableMessageFactory.release(message2[0]);
127 }
128
129 }
1515 */
1616 package org.apache.logging.log4j.spi;
1717
18 import static org.junit.Assert.assertEquals;
19 import static org.junit.Assert.assertFalse;
20 import static org.junit.Assert.assertNull;
21 import static org.junit.Assert.assertTrue;
22
23 import java.util.HashMap;
1824 import java.util.Map;
1925
2026 import org.junit.Test;
21
22 import static org.junit.Assert.*;
2327
2428 /**
2529 * Tests the {@code DefaultThreadContextMap} class.
6569 assertFalse(map.isEmpty());
6670 assertTrue(map.containsKey("key"));
6771 assertEquals("value", map.get("key"));
72 }
73
74 @Test
75 public void testPutAll() {
76 final DefaultThreadContextMap map = new DefaultThreadContextMap(true);
77 assertTrue(map.isEmpty());
78 assertFalse(map.containsKey("key"));
79 final int mapSize = 10;
80 final Map<String, String> newMap = new HashMap<>(mapSize);
81 for (int i = 1; i <= mapSize; i++) {
82 newMap.put("key" + i, "value" + i);
83 }
84 map.putAll(newMap);
85 assertFalse(map.isEmpty());
86 for (int i = 1; i <= mapSize; i++) {
87 assertTrue(map.containsKey("key" + i));
88 assertEquals("value" + i, map.get("key" + i));
89 }
6890 }
6991
7092 /**
0 package org.apache.logging.log4j.util;/*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16
17 import java.io.ByteArrayInputStream;
18 import java.io.ByteArrayOutputStream;
19 import java.io.IOException;
20 import java.io.ObjectInputStream;
21 import java.io.ObjectOutputStream;
22 import java.lang.reflect.Field;
23 import java.util.ConcurrentModificationException;
24 import java.util.HashMap;
25 import java.util.Map;
26
27 import org.junit.Test;
28
29 import static org.junit.Assert.*;
30
31 /**
32 * Tests the SortedArrayStringMap class.
33 */
34 public class SortedArrayStringMapTest {
35
36 @Test(expected = IllegalArgumentException.class)
37 public void testConstructorDisallowsNegativeCapacity() throws Exception {
38 new SortedArrayStringMap(-1);
39 }
40
41 @Test(expected = IllegalArgumentException.class)
42 public void testConstructorDisallowsZeroCapacity() throws Exception {
43 new SortedArrayStringMap(0);
44 }
45
46 @Test
47 public void testConstructorIgnoresNull() throws Exception {
48 assertEquals(0, new SortedArrayStringMap(null).size());
49 }
50
51 @Test
52 public void testToString() {
53 final SortedArrayStringMap original = new SortedArrayStringMap();
54 original.putValue("a", "avalue");
55 original.putValue("B", "Bvalue");
56 original.putValue("3", "3value");
57 assertEquals("{3=3value, B=Bvalue, a=avalue}", original.toString());
58 }
59
60 @Test
61 public void testSerialization() throws Exception {
62 final SortedArrayStringMap original = new SortedArrayStringMap();
63 original.putValue("a", "avalue");
64 original.putValue("B", "Bvalue");
65 original.putValue("3", "3value");
66
67 final byte[] binary = serialize(original);
68 final SortedArrayStringMap copy = deserialize(binary);
69 assertEquals(original, copy);
70 }
71
72 private byte[] serialize(final SortedArrayStringMap data) throws IOException {
73 final ByteArrayOutputStream arr = new ByteArrayOutputStream();
74 final ObjectOutputStream out = new ObjectOutputStream(arr);
75 out.writeObject(data);
76 return arr.toByteArray();
77 }
78
79 private SortedArrayStringMap deserialize(final byte[] binary) throws IOException, ClassNotFoundException {
80 final ByteArrayInputStream inArr = new ByteArrayInputStream(binary);
81 final ObjectInputStream in = new ObjectInputStream(inArr);
82 final SortedArrayStringMap result = (SortedArrayStringMap) in.readObject();
83 return result;
84 }
85
86 @Test
87 public void testPutAll() throws Exception {
88 final SortedArrayStringMap original = new SortedArrayStringMap();
89 original.putValue("a", "avalue");
90 original.putValue("B", "Bvalue");
91 original.putValue("3", "3value");
92
93 final SortedArrayStringMap other = new SortedArrayStringMap();
94 other.putAll(original);
95 assertEquals(original, other);
96
97 other.putValue("3", "otherValue");
98 assertNotEquals(original, other);
99
100 other.putValue("3", null);
101 assertNotEquals(original, other);
102
103 other.putValue("3", "3value");
104 assertEquals(original, other);
105 }
106
107 @Test
108 public void testPutAll_overwritesSameKeys2() throws Exception {
109 final SortedArrayStringMap original = new SortedArrayStringMap();
110 original.putValue("a", "aORIG");
111 original.putValue("b", "bORIG");
112 original.putValue("c", "cORIG");
113 original.putValue("d", "dORIG");
114 original.putValue("e", "eORIG");
115
116 final SortedArrayStringMap other = new SortedArrayStringMap();
117 other.putValue("1", "11");
118 other.putValue("2", "22");
119 other.putValue("a", "aa");
120 other.putValue("c", "cc");
121 original.putAll(other);
122
123 assertEquals("size after put other", 7, original.size());
124 assertEquals("aa", original.getValue("a"));
125 assertEquals("bORIG", original.getValue("b"));
126 assertEquals("cc", original.getValue("c"));
127 assertEquals("dORIG", original.getValue("d"));
128 assertEquals("eORIG", original.getValue("e"));
129 assertEquals("11", original.getValue("1"));
130 assertEquals("22", original.getValue("2"));
131 }
132
133 @Test
134 public void testPutAll_nullKeyInLargeOriginal() throws Exception {
135 final SortedArrayStringMap original = new SortedArrayStringMap();
136 original.putValue(null, "nullORIG");
137 original.putValue("a", "aORIG");
138 original.putValue("b", "bORIG");
139 original.putValue("c", "cORIG");
140 original.putValue("d", "dORIG");
141 original.putValue("e", "eORIG");
142
143 final SortedArrayStringMap other = new SortedArrayStringMap();
144 other.putValue("1", "11");
145 other.putValue("a", "aa");
146 original.putAll(other);
147
148 assertEquals("size after put other", 7, original.size());
149 assertEquals("aa", original.getValue("a"));
150 assertEquals("bORIG", original.getValue("b"));
151 assertEquals("cORIG", original.getValue("c"));
152 assertEquals("dORIG", original.getValue("d"));
153 assertEquals("eORIG", original.getValue("e"));
154 assertEquals("11", original.getValue("1"));
155 assertEquals("nullORIG", original.getValue(null));
156 }
157
158 @Test
159 public void testPutAll_nullKeyInSmallOriginal() throws Exception {
160 final SortedArrayStringMap original = new SortedArrayStringMap();
161 original.putValue(null, "nullORIG");
162 original.putValue("a", "aORIG");
163 original.putValue("b", "bORIG");
164
165 final SortedArrayStringMap other = new SortedArrayStringMap();
166 other.putValue("1", "11");
167 other.putValue("2", "22");
168 other.putValue("3", "33");
169 other.putValue("a", "aa");
170 original.putAll(other);
171
172 assertEquals("size after put other", 6, original.size());
173 assertEquals("aa", original.getValue("a"));
174 assertEquals("bORIG", original.getValue("b"));
175 assertEquals("11", original.getValue("1"));
176 assertEquals("22", original.getValue("2"));
177 assertEquals("33", original.getValue("3"));
178 assertEquals("nullORIG", original.getValue(null));
179 }
180
181 @Test
182 public void testPutAll_nullKeyInSmallAdditional() throws Exception {
183 final SortedArrayStringMap original = new SortedArrayStringMap();
184 original.putValue("a", "aORIG");
185 original.putValue("b", "bORIG");
186 original.putValue("c", "cORIG");
187 original.putValue("d", "dORIG");
188 original.putValue("e", "eORIG");
189
190 final SortedArrayStringMap other = new SortedArrayStringMap();
191 other.putValue(null, "nullNEW");
192 other.putValue("1", "11");
193 other.putValue("a", "aa");
194 original.putAll(other);
195
196 assertEquals("size after put other", 7, original.size());
197 assertEquals("aa", original.getValue("a"));
198 assertEquals("bORIG", original.getValue("b"));
199 assertEquals("cORIG", original.getValue("c"));
200 assertEquals("dORIG", original.getValue("d"));
201 assertEquals("eORIG", original.getValue("e"));
202 assertEquals("11", original.getValue("1"));
203 assertEquals("nullNEW", original.getValue(null));
204 }
205
206 @Test
207 public void testPutAll_nullKeyInLargeAdditional() throws Exception {
208 final SortedArrayStringMap original = new SortedArrayStringMap();
209 original.putValue("a", "aORIG");
210 original.putValue("b", "bORIG");
211
212 final SortedArrayStringMap other = new SortedArrayStringMap();
213 other.putValue(null, "nullNEW");
214 other.putValue("1", "11");
215 other.putValue("2", "22");
216 other.putValue("3", "33");
217 other.putValue("a", "aa");
218 original.putAll(other);
219
220 assertEquals("size after put other", 6, original.size());
221 assertEquals("aa", original.getValue("a"));
222 assertEquals("bORIG", original.getValue("b"));
223 assertEquals("11", original.getValue("1"));
224 assertEquals("22", original.getValue("2"));
225 assertEquals("33", original.getValue("3"));
226 assertEquals("nullNEW", original.getValue(null));
227 }
228
229 @Test
230 public void testPutAll_nullKeyInBoth_LargeOriginal() throws Exception {
231 final SortedArrayStringMap original = new SortedArrayStringMap();
232 original.putValue(null, "nullORIG");
233 original.putValue("a", "aORIG");
234 original.putValue("b", "bORIG");
235 original.putValue("c", "cORIG");
236 original.putValue("d", "dORIG");
237 original.putValue("e", "eORIG");
238
239 final SortedArrayStringMap other = new SortedArrayStringMap();
240 other.putValue(null, "nullNEW");
241 other.putValue("1", "11");
242 other.putValue("a", "aa");
243 original.putAll(other);
244
245 assertEquals("size after put other", 7, original.size());
246 assertEquals("aa", original.getValue("a"));
247 assertEquals("bORIG", original.getValue("b"));
248 assertEquals("cORIG", original.getValue("c"));
249 assertEquals("dORIG", original.getValue("d"));
250 assertEquals("eORIG", original.getValue("e"));
251 assertEquals("11", original.getValue("1"));
252 assertEquals("nullNEW", original.getValue(null));
253 }
254
255 @Test
256 public void testPutAll_nullKeyInBoth_SmallOriginal() throws Exception {
257 final SortedArrayStringMap original = new SortedArrayStringMap();
258 original.putValue(null, "nullORIG");
259 original.putValue("a", "aORIG");
260 original.putValue("b", "bORIG");
261
262 final SortedArrayStringMap other = new SortedArrayStringMap();
263 other.putValue(null, "nullNEW");
264 other.putValue("1", "11");
265 other.putValue("2", "22");
266 other.putValue("3", "33");
267 other.putValue("a", "aa");
268 original.putAll(other);
269
270 assertEquals("size after put other", 6, original.size());
271 assertEquals("aa", original.getValue("a"));
272 assertEquals("bORIG", original.getValue("b"));
273 assertEquals("11", original.getValue("1"));
274 assertEquals("22", original.getValue("2"));
275 assertEquals("33", original.getValue("3"));
276 assertEquals("nullNEW", original.getValue(null));
277 }
278
279 @Test
280 public void testPutAll_overwritesSameKeys1() throws Exception {
281 final SortedArrayStringMap original = new SortedArrayStringMap();
282 original.putValue("a", "aORIG");
283 original.putValue("b", "bORIG");
284 original.putValue("c", "cORIG");
285
286 final SortedArrayStringMap other = new SortedArrayStringMap();
287 other.putValue("1", "11");
288 other.putValue("2", "22");
289 other.putValue("a", "aa");
290 other.putValue("c", "cc");
291 original.putAll(other);
292
293 assertEquals("size after put other", 5, original.size());
294 assertEquals("aa", original.getValue("a"));
295 assertEquals("bORIG", original.getValue("b"));
296 assertEquals("cc", original.getValue("c"));
297 assertEquals("11", original.getValue("1"));
298 assertEquals("22", original.getValue("2"));
299 }
300
301 @Test
302 public void testEquals() {
303 final SortedArrayStringMap original = new SortedArrayStringMap();
304 original.putValue("a", "avalue");
305 original.putValue("B", "Bvalue");
306 original.putValue("3", "3value");
307 assertEquals(original, original); // equal to itself
308
309 final SortedArrayStringMap other = new SortedArrayStringMap();
310 other.putValue("a", "avalue");
311 assertNotEquals(original, other);
312
313 other.putValue("B", "Bvalue");
314 assertNotEquals(original, other);
315
316 other.putValue("3", "3value");
317 assertEquals(original, other);
318
319 other.putValue("3", "otherValue");
320 assertNotEquals(original, other);
321
322 other.putValue("3", null);
323 assertNotEquals(original, other);
324
325 other.putValue("3", "3value");
326 assertEquals(original, other);
327 }
328
329 @Test
330 public void testToMap() throws Exception {
331 final SortedArrayStringMap original = new SortedArrayStringMap();
332 original.putValue("a", "avalue");
333 original.putValue("B", "Bvalue");
334 original.putValue("3", "3value");
335
336 final Map<String, Object> expected = new HashMap<>();
337 expected.put("a", "avalue");
338 expected.put("B", "Bvalue");
339 expected.put("3", "3value");
340
341 assertEquals(expected, original.toMap());
342
343 try {
344 original.toMap().put("abc", "xyz");
345 } catch (final UnsupportedOperationException ex) {
346 fail("Expected map to be mutable, but " + ex);
347 }
348 }
349
350 @Test
351 public void testPutAll_KeepsExistingValues() {
352 final SortedArrayStringMap original = new SortedArrayStringMap();
353 original.putValue("a", "aaa");
354 original.putValue("b", "bbb");
355 original.putValue("c", "ccc");
356 assertEquals("size", 3, original.size());
357
358 // add empty context data
359 original.putAll(new SortedArrayStringMap());
360 assertEquals("size after put empty", 3, original.size());
361 assertEquals("aaa", original.getValue("a"));
362 assertEquals("bbb", original.getValue("b"));
363 assertEquals("ccc", original.getValue("c"));
364
365 final SortedArrayStringMap other = new SortedArrayStringMap();
366 other.putValue("1", "111");
367 other.putValue("2", "222");
368 other.putValue("3", "333");
369 original.putAll(other);
370
371 assertEquals("size after put other", 6, original.size());
372 assertEquals("aaa", original.getValue("a"));
373 assertEquals("bbb", original.getValue("b"));
374 assertEquals("ccc", original.getValue("c"));
375 assertEquals("111", original.getValue("1"));
376 assertEquals("222", original.getValue("2"));
377 assertEquals("333", original.getValue("3"));
378 }
379
380 @Test
381 public void testPutAll_sizePowerOfTwo() {
382 final SortedArrayStringMap original = new SortedArrayStringMap();
383 original.putValue("a", "aaa");
384 original.putValue("b", "bbb");
385 original.putValue("c", "ccc");
386 original.putValue("d", "ddd");
387 assertEquals("size", 4, original.size());
388
389 // add empty context data
390 original.putAll(new SortedArrayStringMap());
391 assertEquals("size after put empty", 4, original.size());
392 assertEquals("aaa", original.getValue("a"));
393 assertEquals("bbb", original.getValue("b"));
394 assertEquals("ccc", original.getValue("c"));
395 assertEquals("ddd", original.getValue("d"));
396
397 final SortedArrayStringMap other = new SortedArrayStringMap();
398 other.putValue("1", "111");
399 other.putValue("2", "222");
400 other.putValue("3", "333");
401 other.putValue("4", "444");
402 original.putAll(other);
403
404 assertEquals("size after put other", 8, original.size());
405 assertEquals("aaa", original.getValue("a"));
406 assertEquals("bbb", original.getValue("b"));
407 assertEquals("ccc", original.getValue("c"));
408 assertEquals("ddd", original.getValue("d"));
409 assertEquals("111", original.getValue("1"));
410 assertEquals("222", original.getValue("2"));
411 assertEquals("333", original.getValue("3"));
412 assertEquals("444", original.getValue("4"));
413 }
414
415 @Test
416 public void testPutAll_largeAddition() {
417 final SortedArrayStringMap original = new SortedArrayStringMap();
418 original.putValue(null, "nullVal");
419 original.putValue("a", "aaa");
420 original.putValue("b", "bbb");
421 original.putValue("c", "ccc");
422 original.putValue("d", "ddd");
423 assertEquals("size", 5, original.size());
424
425 final SortedArrayStringMap other = new SortedArrayStringMap();
426 for (int i = 0 ; i < 500; i++) {
427 other.putValue(String.valueOf(i), String.valueOf(i));
428 }
429 other.putValue(null, "otherVal");
430 original.putAll(other);
431
432 assertEquals("size after put other", 505, original.size());
433 assertEquals("otherVal", original.getValue(null));
434 assertEquals("aaa", original.getValue("a"));
435 assertEquals("bbb", original.getValue("b"));
436 assertEquals("ccc", original.getValue("c"));
437 assertEquals("ddd", original.getValue("d"));
438 for (int i = 0 ; i < 500; i++) {
439 assertEquals(String.valueOf(i), original.getValue(String.valueOf(i)));
440 }
441 }
442
443 @Test
444 public void testPutAllSelfDoesNotModify() {
445 final SortedArrayStringMap original = new SortedArrayStringMap();
446 original.putValue("a", "aaa");
447 original.putValue("b", "bbb");
448 original.putValue("c", "ccc");
449 assertEquals("size", 3, original.size());
450
451 // putAll with self
452 original.putAll(original);
453 assertEquals("size after put empty", 3, original.size());
454 assertEquals("aaa", original.getValue("a"));
455 assertEquals("bbb", original.getValue("b"));
456 assertEquals("ccc", original.getValue("c"));
457 }
458
459 @Test(expected = ConcurrentModificationException.class)
460 public void testConcurrentModificationBiConsumerPut() {
461 final SortedArrayStringMap original = new SortedArrayStringMap();
462 original.putValue("a", "aaa");
463 original.forEach(new BiConsumer<String, Object>() {
464 @Override
465 public void accept(final String s, final Object o) {
466 original.putValue("c", "other");
467 }
468 });
469 }
470
471 @Test(expected = ConcurrentModificationException.class)
472 public void testConcurrentModificationBiConsumerPutValue() {
473 final SortedArrayStringMap original = new SortedArrayStringMap();
474 original.putValue("a", "aaa");
475 original.forEach(new BiConsumer<String, Object>() {
476 @Override
477 public void accept(final String s, final Object o) {
478 original.putValue("c", "other");
479 }
480 });
481 }
482
483 @Test(expected = ConcurrentModificationException.class)
484 public void testConcurrentModificationBiConsumerRemove() {
485 final SortedArrayStringMap original = new SortedArrayStringMap();
486 original.putValue("a", "aaa");
487 original.forEach(new BiConsumer<String, Object>() {
488 @Override
489 public void accept(final String s, final Object o) {
490 original.remove("a");
491 }
492 });
493 }
494
495 @Test(expected = ConcurrentModificationException.class)
496 public void testConcurrentModificationBiConsumerClear() {
497 final SortedArrayStringMap original = new SortedArrayStringMap();
498 original.putValue("a", "aaa");
499 original.forEach(new BiConsumer<String, Object>() {
500 @Override
501 public void accept(final String s, final Object o) {
502 original.clear();
503 }
504 });
505 }
506
507 @Test(expected = ConcurrentModificationException.class)
508 public void testConcurrentModificationTriConsumerPut() {
509 final SortedArrayStringMap original = new SortedArrayStringMap();
510 original.putValue("a", "aaa");
511 original.forEach(new TriConsumer<String, Object, Object>() {
512 @Override
513 public void accept(final String s, final Object o, final Object o2) {
514 original.putValue("c", "other");
515 }
516 }, null);
517 }
518
519 @Test(expected = ConcurrentModificationException.class)
520 public void testConcurrentModificationTriConsumerPutValue() {
521 final SortedArrayStringMap original = new SortedArrayStringMap();
522 original.putValue("a", "aaa");
523 original.forEach(new TriConsumer<String, Object, Object>() {
524 @Override
525 public void accept(final String s, final Object o, final Object o2) {
526 original.putValue("c", "other");
527 }
528 }, null);
529 }
530
531 @Test(expected = ConcurrentModificationException.class)
532 public void testConcurrentModificationTriConsumerRemove() {
533 final SortedArrayStringMap original = new SortedArrayStringMap();
534 original.putValue("a", "aaa");
535 original.forEach(new TriConsumer<String, Object, Object>() {
536 @Override
537 public void accept(final String s, final Object o, final Object o2) {
538 original.remove("a");
539 }
540 }, null);
541 }
542
543 @Test(expected = ConcurrentModificationException.class)
544 public void testConcurrentModificationTriConsumerClear() {
545 final SortedArrayStringMap original = new SortedArrayStringMap();
546 original.putValue("a", "aaa");
547 original.forEach(new TriConsumer<String, Object, Object>() {
548 @Override
549 public void accept(final String s, final Object o, final Object o2) {
550 original.clear();
551 }
552 }, null);
553 }
554
555 @Test
556 public void testInitiallyNotFrozen() {
557 assertFalse(new SortedArrayStringMap().isFrozen());
558 }
559
560 @Test
561 public void testIsFrozenAfterCallingFreeze() {
562 final SortedArrayStringMap original = new SortedArrayStringMap();
563 assertFalse("before freeze", original.isFrozen());
564 original.freeze();
565 assertTrue("after freeze", original.isFrozen());
566 }
567
568 @Test(expected = UnsupportedOperationException.class)
569 public void testFreezeProhibitsPutValue() {
570 final SortedArrayStringMap original = new SortedArrayStringMap();
571 original.freeze();
572 original.putValue("a", "aaa");
573 }
574
575 @Test(expected = UnsupportedOperationException.class)
576 public void testFreezeProhibitsRemove() {
577 final SortedArrayStringMap original = new SortedArrayStringMap();
578 original.putValue("b", "bbb");
579 original.freeze();
580 original.remove("b"); // existing key: modifies the collection
581 }
582
583 @Test
584 public void testFreezeAllowsRemoveOfNonExistingKey() {
585 final SortedArrayStringMap original = new SortedArrayStringMap();
586 original.putValue("b", "bbb");
587 original.freeze();
588 original.remove("a"); // no actual modification
589 }
590
591 @Test
592 public void testFreezeAllowsRemoveIfEmpty() {
593 final SortedArrayStringMap original = new SortedArrayStringMap();
594 original.freeze();
595 original.remove("a"); // no exception
596 }
597
598 @Test(expected = UnsupportedOperationException.class)
599 public void testFreezeProhibitsClear() {
600 final SortedArrayStringMap original = new SortedArrayStringMap();
601 original.putValue("a", "aaa");
602 original.freeze();
603 original.clear();
604 }
605
606 @Test
607 public void testFreezeAllowsClearIfEmpty() {
608 final SortedArrayStringMap original = new SortedArrayStringMap();
609 original.freeze();
610 original.clear();
611 }
612
613 @Test
614 public void testPutInsertsInAlphabeticOrder() throws Exception {
615 final SortedArrayStringMap original = new SortedArrayStringMap();
616 original.putValue("a", "avalue");
617 original.putValue("B", "Bvalue");
618 original.putValue("3", "3value");
619 original.putValue("c", "cvalue");
620 original.putValue("d", "dvalue");
621
622 assertEquals("avalue", original.getValue("a"));
623 assertEquals("avalue", original.getValueAt(2));
624
625 assertEquals("Bvalue", original.getValue("B"));
626 assertEquals("Bvalue", original.getValueAt(1));
627
628 assertEquals("3value", original.getValue("3"));
629 assertEquals("3value", original.getValueAt(0));
630
631 assertEquals("cvalue", original.getValue("c"));
632 assertEquals("cvalue", original.getValueAt(3));
633
634 assertEquals("dvalue", original.getValue("d"));
635 assertEquals("dvalue", original.getValueAt(4));
636 }
637
638 @Test
639 public void testPutValueInsertsInAlphabeticOrder() throws Exception {
640 final SortedArrayStringMap original = new SortedArrayStringMap();
641 original.putValue("a", "avalue");
642 original.putValue("B", "Bvalue");
643 original.putValue("3", "3value");
644 original.putValue("c", "cvalue");
645 original.putValue("d", "dvalue");
646
647 assertEquals("avalue", original.getValue("a"));
648 assertEquals("avalue", original.getValueAt(2));
649
650 assertEquals("Bvalue", original.getValue("B"));
651 assertEquals("Bvalue", original.getValueAt(1));
652
653 assertEquals("3value", original.getValue("3"));
654 assertEquals("3value", original.getValueAt(0));
655
656 assertEquals("cvalue", original.getValue("c"));
657 assertEquals("cvalue", original.getValueAt(3));
658
659 assertEquals("dvalue", original.getValue("d"));
660 assertEquals("dvalue", original.getValueAt(4));
661 }
662
663 @Test
664 public void testNullKeysAllowed() {
665 final SortedArrayStringMap original = new SortedArrayStringMap();
666 original.putValue("a", "avalue");
667 original.putValue("B", "Bvalue");
668 original.putValue("3", "3value");
669 original.putValue("c", "cvalue");
670 original.putValue("d", "dvalue");
671 assertEquals(5, original.size());
672 assertEquals("{3=3value, B=Bvalue, a=avalue, c=cvalue, d=dvalue}", original.toString());
673
674 original.putValue(null, "nullvalue");
675 assertEquals(6, original.size());
676 assertEquals("{null=nullvalue, 3=3value, B=Bvalue, a=avalue, c=cvalue, d=dvalue}", original.toString());
677
678 original.putValue(null, "otherNullvalue");
679 assertEquals("{null=otherNullvalue, 3=3value, B=Bvalue, a=avalue, c=cvalue, d=dvalue}", original.toString());
680 assertEquals(6, original.size());
681
682 original.putValue(null, "nullvalue");
683 assertEquals(6, original.size());
684 assertEquals("{null=nullvalue, 3=3value, B=Bvalue, a=avalue, c=cvalue, d=dvalue}", original.toString());
685
686 original.putValue(null, "abc");
687 assertEquals(6, original.size());
688 assertEquals("{null=abc, 3=3value, B=Bvalue, a=avalue, c=cvalue, d=dvalue}", original.toString());
689 }
690
691 @Test
692 public void testNullKeysCopiedToAsMap() {
693 final SortedArrayStringMap original = new SortedArrayStringMap();
694 original.putValue("a", "avalue");
695 original.putValue("B", "Bvalue");
696 original.putValue("3", "3value");
697 original.putValue("c", "cvalue");
698 original.putValue("d", "dvalue");
699 assertEquals(5, original.size());
700
701 final HashMap<String, String> expected = new HashMap<>();
702 expected.put("a", "avalue");
703 expected.put("B", "Bvalue");
704 expected.put("3", "3value");
705 expected.put("c", "cvalue");
706 expected.put("d", "dvalue");
707 assertEquals("initial", expected, original.toMap());
708
709 original.putValue(null, "nullvalue");
710 expected.put(null, "nullvalue");
711 assertEquals(6, original.size());
712 assertEquals("with null key", expected, original.toMap());
713
714 original.putValue(null, "otherNullvalue");
715 expected.put(null, "otherNullvalue");
716 assertEquals(6, original.size());
717 assertEquals("with null key value2", expected, original.toMap());
718
719 original.putValue(null, "nullvalue");
720 expected.put(null, "nullvalue");
721 assertEquals(6, original.size());
722 assertEquals("with null key value1 again", expected, original.toMap());
723
724 original.putValue(null, "abc");
725 expected.put(null, "abc");
726 assertEquals(6, original.size());
727 assertEquals("with null key value3", expected, original.toMap());
728 }
729
730 @Test
731 public void testRemove() {
732 final SortedArrayStringMap original = new SortedArrayStringMap();
733 original.putValue("a", "avalue");
734 assertEquals(1, original.size());
735 assertEquals("avalue", original.getValue("a"));
736
737 original.remove("a");
738 assertEquals(0, original.size());
739 assertNull("no a val", original.getValue("a"));
740
741 original.remove("B");
742 assertEquals(0, original.size());
743 assertNull("no B val", original.getValue("B"));
744 }
745
746 @Test
747 public void testRemoveNullsOutRemovedSlot() throws Exception {
748 final SortedArrayStringMap original = new SortedArrayStringMap();
749 original.putValue("a", "avalue");
750 original.putValue("b", "bvalue");
751 original.putValue("c", "cvalue");
752 original.putValue("d", "dvalue");
753 original.remove("a");
754 original.remove("b");
755 original.remove("c");
756 original.remove("d");
757 assertNull(original.getValueAt(0));
758
759 // ensure slots in the values array are nulled out
760 final Field f = SortedArrayStringMap.class.getDeclaredField("values");
761 f.setAccessible(true);
762 final Object[] values = (Object[]) f.get(original);
763 for (int i = 0; i < values.length; i++) {
764 assertNull(values[i]);
765 }
766 }
767
768 @Test
769 public void testRemoveWhenFull() throws Exception {
770 final SortedArrayStringMap original = new SortedArrayStringMap();
771 original.putValue("a", "avalue");
772 original.putValue("b", "bvalue");
773 original.putValue("c", "cvalue");
774 original.putValue("d", "dvalue"); // default capacity = 4
775 original.remove("d");
776 }
777
778 @Test
779 public void testNullValuesArePreserved() {
780 final SortedArrayStringMap original = new SortedArrayStringMap();
781 original.putValue("a", "avalue");
782 assertEquals(1, original.size());
783 assertEquals("avalue", original.getValue("a"));
784
785 original.putValue("a", null);
786 assertEquals(1, original.size());
787 assertNull("no a val", original.getValue("a"));
788
789 original.putValue("B", null);
790 assertEquals(2, original.size());
791 assertNull("no B val", original.getValue("B"));
792 }
793
794 @Test
795 public void testGet() throws Exception {
796 final SortedArrayStringMap original = new SortedArrayStringMap();
797 original.putValue("a", "avalue");
798 original.putValue("B", "Bvalue");
799 original.putValue("3", "3value");
800
801 assertEquals("avalue", original.getValue("a"));
802 assertEquals("Bvalue", original.getValue("B"));
803 assertEquals("3value", original.getValue("3"));
804
805 original.putValue("0", "0value");
806 assertEquals("0value", original.getValue("0"));
807 assertEquals("3value", original.getValue("3"));
808 assertEquals("Bvalue", original.getValue("B"));
809 assertEquals("avalue", original.getValue("a"));
810 }
811
812 @Test
813 public void testGetValue_GetValueAt() throws Exception {
814 final SortedArrayStringMap original = new SortedArrayStringMap();
815 original.putValue("a", "avalue");
816 original.putValue("B", "Bvalue");
817 original.putValue("3", "3value");
818
819 assertEquals("avalue", original.getValue("a"));
820 assertEquals("avalue", original.getValueAt(2));
821
822 assertEquals("Bvalue", original.getValue("B"));
823 assertEquals("Bvalue", original.getValueAt(1));
824
825 assertEquals("3value", original.getValue("3"));
826 assertEquals("3value", original.getValueAt(0));
827
828 original.putValue("0", "0value");
829 assertEquals("0value", original.getValue("0"));
830 assertEquals("0value", original.getValueAt(0));
831 assertEquals("3value", original.getValue("3"));
832 assertEquals("3value", original.getValueAt(1));
833 assertEquals("Bvalue", original.getValue("B"));
834 assertEquals("Bvalue", original.getValueAt(2));
835 assertEquals("avalue", original.getValue("a"));
836 assertEquals("avalue", original.getValueAt(3));
837 }
838
839 @Test
840 public void testClear() throws Exception {
841 final SortedArrayStringMap original = new SortedArrayStringMap();
842 original.putValue("a", "avalue");
843 original.putValue("B", "Bvalue");
844 original.putValue("3", "3value");
845 assertEquals(3, original.size());
846
847 original.clear();
848 assertEquals(0, original.size());
849
850 // ensure slots in the values array are nulled out
851 final Field f = SortedArrayStringMap.class.getDeclaredField("values");
852 f.setAccessible(true);
853 final Object[] values = (Object[]) f.get(original);
854 for (int i = 0; i < values.length; i++) {
855 assertNull(values[i]);
856 }
857 }
858
859 @Test
860 public void testIndexOfKey() throws Exception {
861 final SortedArrayStringMap original = new SortedArrayStringMap();
862 original.putValue("a", "avalue");
863 assertEquals(0, original.indexOfKey("a"));
864
865 original.putValue("B", "Bvalue");
866 assertEquals(1, original.indexOfKey("a"));
867 assertEquals(0, original.indexOfKey("B"));
868
869 original.putValue("3", "3value");
870 assertEquals(2, original.indexOfKey("a"));
871 assertEquals(1, original.indexOfKey("B"));
872 assertEquals(0, original.indexOfKey("3"));
873
874 original.putValue("A", "AAA");
875 assertEquals(3, original.indexOfKey("a"));
876 assertEquals(2, original.indexOfKey("B"));
877 assertEquals(1, original.indexOfKey("A"));
878 assertEquals(0, original.indexOfKey("3"));
879
880 original.putValue("C", "CCC");
881 assertEquals(4, original.indexOfKey("a"));
882 assertEquals(3, original.indexOfKey("C"));
883 assertEquals(2, original.indexOfKey("B"));
884 assertEquals(1, original.indexOfKey("A"));
885 assertEquals(0, original.indexOfKey("3"));
886
887 original.putValue("2", "222");
888 assertEquals(5, original.indexOfKey("a"));
889 assertEquals(4, original.indexOfKey("C"));
890 assertEquals(3, original.indexOfKey("B"));
891 assertEquals(2, original.indexOfKey("A"));
892 assertEquals(1, original.indexOfKey("3"));
893 assertEquals(0, original.indexOfKey("2"));
894 }
895
896 @Test
897 public void testContainsKey() throws Exception {
898 final SortedArrayStringMap original = new SortedArrayStringMap();
899 assertFalse("a", original.containsKey("a"));
900 assertFalse("B", original.containsKey("B"));
901 assertFalse("3", original.containsKey("3"));
902 assertFalse("A", original.containsKey("A"));
903
904 original.putValue("a", "avalue");
905 assertTrue("a", original.containsKey("a"));
906 assertFalse("B", original.containsKey("B"));
907 assertFalse("3", original.containsKey("3"));
908 assertFalse("A", original.containsKey("A"));
909
910 original.putValue("B", "Bvalue");
911 assertTrue("a", original.containsKey("a"));
912 assertTrue("B", original.containsKey("B"));
913 assertFalse("3", original.containsKey("3"));
914 assertFalse("A", original.containsKey("A"));
915
916 original.putValue("3", "3value");
917 assertTrue("a", original.containsKey("a"));
918 assertTrue("B", original.containsKey("B"));
919 assertTrue("3", original.containsKey("3"));
920 assertFalse("A", original.containsKey("A"));
921
922 original.putValue("A", "AAA");
923 assertTrue("a", original.containsKey("a"));
924 assertTrue("B", original.containsKey("B"));
925 assertTrue("3", original.containsKey("3"));
926 assertTrue("A", original.containsKey("A"));
927 }
928
929 @Test
930 public void testGetValueAt() throws Exception {
931 final SortedArrayStringMap original = new SortedArrayStringMap();
932 original.putValue("a", "avalue");
933 assertEquals("a", original.getKeyAt(0));
934 assertEquals("avalue", original.getValueAt(0));
935
936 original.putValue("B", "Bvalue");
937 assertEquals("B", original.getKeyAt(0));
938 assertEquals("Bvalue", original.getValueAt(0));
939 assertEquals("a", original.getKeyAt(1));
940 assertEquals("avalue", original.getValueAt(1));
941
942 original.putValue("3", "3value");
943 assertEquals("3", original.getKeyAt(0));
944 assertEquals("3value", original.getValueAt(0));
945 assertEquals("B", original.getKeyAt(1));
946 assertEquals("Bvalue", original.getValueAt(1));
947 assertEquals("a", original.getKeyAt(2));
948 assertEquals("avalue", original.getValueAt(2));
949 }
950
951 @Test
952 public void testSizeAndIsEmpty() throws Exception {
953 final SortedArrayStringMap original = new SortedArrayStringMap();
954 assertEquals(0, original.size());
955 assertTrue("initial", original.isEmpty());
956
957 original.putValue("a", "avalue");
958 assertEquals(1, original.size());
959 assertFalse("size=" + original.size(), original.isEmpty());
960
961 original.putValue("B", "Bvalue");
962 assertEquals(2, original.size());
963 assertFalse("size=" + original.size(), original.isEmpty());
964
965 original.putValue("3", "3value");
966 assertEquals(3, original.size());
967 assertFalse("size=" + original.size(), original.isEmpty());
968
969 original.remove("B");
970 assertEquals(2, original.size());
971 assertFalse("size=" + original.size(), original.isEmpty());
972
973 original.remove("3");
974 assertEquals(1, original.size());
975 assertFalse("size=" + original.size(), original.isEmpty());
976
977 original.remove("a");
978 assertEquals(0, original.size());
979 assertTrue("size=" + original.size(), original.isEmpty());
980 }
981
982 @Test
983 public void testForEachBiConsumer() throws Exception {
984 final SortedArrayStringMap original = new SortedArrayStringMap();
985 original.putValue("a", "avalue");
986 original.putValue("B", "Bvalue");
987 original.putValue("3", "3value");
988
989 original.forEach(new BiConsumer<String, String>() {
990 int count = 0;
991 @Override
992 public void accept(final String key, final String value) {
993 assertEquals("key", key, original.getKeyAt(count));
994 assertEquals("val", value, original.getValueAt(count));
995 count++;
996 assertTrue("count should not exceed size but was " + count, count <= original.size());
997 }
998 });
999 }
1000
1001 static class State {
1002 SortedArrayStringMap data;
1003 int count;
1004 }
1005 static TriConsumer<String, String, State> COUNTER = new TriConsumer<String, String, State>() {
1006 @Override
1007 public void accept(final String key, final String value, final State state) {
1008 assertEquals("key", key, state.data.getKeyAt(state.count));
1009 assertEquals("val", value, state.data.getValueAt(state.count));
1010 state.count++;
1011 assertTrue("count should not exceed size but was " + state.count,
1012 state.count <= state.data.size());
1013 }
1014 };
1015
1016 @Test
1017 public void testForEachTriConsumer() throws Exception {
1018 final SortedArrayStringMap original = new SortedArrayStringMap();
1019 original.putValue("a", "avalue");
1020 original.putValue("B", "Bvalue");
1021 original.putValue("3", "3value");
1022
1023 final State state = new State();
1024 state.data = original;
1025 original.forEach(COUNTER, state);
1026 assertEquals(state.count, original.size());
1027 }
1028 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16
17 package org.apache.logging.log4j.util;
18
19 import org.junit.BeforeClass;
20 import org.junit.Test;
21
22 import static org.junit.Assert.*;
23
24 /**
25 * Tests the Unbox class.
26 */
27 public class Unbox1Test {
28 @BeforeClass
29 public static void beforeClass() {
30 System.clearProperty("log4j.unbox.ringbuffer.size");
31 }
32
33 @Test
34 public void testBoxClaimsItHas32Slots() throws Exception {
35 assertEquals(32, Unbox.getRingbufferSize());
36 }
37
38 @Test
39 public void testBoxHas32Slots() throws Exception {
40 final int MAX = 32;
41 final StringBuilder[] probe = new StringBuilder[MAX * 3];
42 for (int i = 0; i <= probe.length - 8; ) {
43 probe[i++] = Unbox.box(true);
44 probe[i++] = Unbox.box('c');
45 probe[i++] = Unbox.box(Byte.MAX_VALUE);
46 probe[i++] = Unbox.box(Double.MAX_VALUE);
47 probe[i++] = Unbox.box(Float.MAX_VALUE);
48 probe[i++] = Unbox.box(Integer.MAX_VALUE);
49 probe[i++] = Unbox.box(Long.MAX_VALUE);
50 probe[i++] = Unbox.box(Short.MAX_VALUE);
51 }
52 for (int i = 0; i < probe.length - MAX; i++) {
53 assertSame("probe[" + i +"], probe[" + (i + MAX) +"]", probe[i], probe[i + MAX]);
54 for (int j = 1; j < MAX - 1; j++) {
55 assertNotSame("probe[" + i +"], probe[" + (i + j) +"]", probe[i], probe[i + j]);
56 }
57 }
58 }
59
60 @Test
61 public void testBoxBoolean() throws Exception {
62 assertEquals("true", Unbox.box(true).toString());
63 assertEquals("false", Unbox.box(false).toString());
64 }
65
66 @Test
67 public void testBoxByte() throws Exception {
68 assertEquals("0", Unbox.box((byte) 0).toString());
69 assertEquals("1", Unbox.box((byte) 1).toString());
70 assertEquals("127", Unbox.box((byte) 127).toString());
71 assertEquals("-1", Unbox.box((byte) -1).toString());
72 assertEquals("-128", Unbox.box((byte) -128).toString());
73 }
74
75 @Test
76 public void testBoxChar() throws Exception {
77 assertEquals("a", Unbox.box('a').toString());
78 assertEquals("b", Unbox.box('b').toString());
79 assertEquals("字", Unbox.box('字').toString());
80 }
81
82 @Test
83 public void testBoxDouble() throws Exception {
84 assertEquals("3.14", Unbox.box(3.14).toString());
85 assertEquals(new Double(Double.MAX_VALUE).toString(), Unbox.box(Double.MAX_VALUE).toString());
86 assertEquals(new Double(Double.MIN_VALUE).toString(), Unbox.box(Double.MIN_VALUE).toString());
87 }
88
89 @Test
90 public void testBoxFloat() throws Exception {
91 assertEquals("3.14", Unbox.box(3.14F).toString());
92 assertEquals(new Float(Float.MAX_VALUE).toString(), Unbox.box(Float.MAX_VALUE).toString());
93 assertEquals(new Float(Float.MIN_VALUE).toString(), Unbox.box(Float.MIN_VALUE).toString());
94 }
95
96 @Test
97 public void testBoxInt() throws Exception {
98 assertEquals("0", Unbox.box(0).toString());
99 assertEquals("1", Unbox.box(1).toString());
100 assertEquals("127", Unbox.box(127).toString());
101 assertEquals("-1", Unbox.box(-1).toString());
102 assertEquals("-128", Unbox.box(-128).toString());
103 assertEquals(new Integer(Integer.MAX_VALUE).toString(), Unbox.box(Integer.MAX_VALUE).toString());
104 assertEquals(new Integer(Integer.MIN_VALUE).toString(), Unbox.box(Integer.MIN_VALUE).toString());
105 }
106
107 @Test
108 public void testBoxLong() throws Exception {
109 assertEquals("0", Unbox.box(0L).toString());
110 assertEquals("1", Unbox.box(1L).toString());
111 assertEquals("127", Unbox.box(127L).toString());
112 assertEquals("-1", Unbox.box(-1L).toString());
113 assertEquals("-128", Unbox.box(-128L).toString());
114 assertEquals(new Long(Long.MAX_VALUE).toString(), Unbox.box(Long.MAX_VALUE).toString());
115 assertEquals(new Long(Long.MIN_VALUE).toString(), Unbox.box(Long.MIN_VALUE).toString());
116 }
117
118 @Test
119 public void testBoxShort() throws Exception {
120 assertEquals("0", Unbox.box((short) 0).toString());
121 assertEquals("1", Unbox.box((short) 1).toString());
122 assertEquals("127", Unbox.box((short) 127).toString());
123 assertEquals("-1", Unbox.box((short) -1).toString());
124 assertEquals("-128", Unbox.box((short) -128).toString());
125 assertEquals(new Short(Short.MAX_VALUE).toString(), Unbox.box(Short.MAX_VALUE).toString());
126 assertEquals(new Short(Short.MIN_VALUE).toString(), Unbox.box(Short.MIN_VALUE).toString());
127 }
128
129 @Test
130 public void testBoxIsThreadLocal() throws Exception {
131 final StringBuilder[] probe = new StringBuilder[16 * 3];
132 populate(0, probe);
133 final Thread t1 = new Thread() {
134 @Override
135 public void run() {
136 populate(16, probe);
137 }
138 };
139 t1.start();
140 t1.join();
141 final Thread t2 = new Thread() {
142 @Override
143 public void run() {
144 populate(16, probe);
145 }
146 };
147 t2.start();
148 t2.join();
149 for (int i = 0; i < probe.length - 16; i++) {
150 for (int j = 1; j < 16; j++) {
151 assertNotSame("probe[" + i +"]=" + probe[i] + ", probe[" + (i + j) +"]=" + probe[i + j],
152 probe[i], probe[i + j]);
153 }
154 }
155 }
156
157 private void populate(final int start, final StringBuilder[] probe) {
158 for (int i = start; i <= start + 8; ) {
159 probe[i++] = Unbox.box(true);
160 probe[i++] = Unbox.box('c');
161 probe[i++] = Unbox.box(Byte.MAX_VALUE);
162 probe[i++] = Unbox.box(Double.MAX_VALUE);
163 probe[i++] = Unbox.box(Float.MAX_VALUE);
164 probe[i++] = Unbox.box(Integer.MAX_VALUE);
165 probe[i++] = Unbox.box(Long.MAX_VALUE);
166 probe[i++] = Unbox.box(Short.MAX_VALUE);
167 }
168 }
169 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.util;
17
18 import java.lang.reflect.Field;
19 import java.lang.reflect.Modifier;
20
21 import org.junit.AfterClass;
22 import org.junit.BeforeClass;
23 import org.junit.Ignore;
24 import org.junit.Test;
25
26 import static org.junit.Assert.*;
27
28 /**
29 * Tests that the Unbox ring buffer size is configurable.
30 * Must be run in a separate process as the other UnboxTest or the last-run test will fail.
31 */
32 public class Unbox2ConfigurableTest {
33 @Ignore
34 @BeforeClass
35 public static void beforeClass() {
36 System.setProperty("log4j.unbox.ringbuffer.size", "65");
37 }
38
39 @Ignore
40 @AfterClass
41 public static void afterClass() throws Exception {
42 System.clearProperty("log4j.unbox.ringbuffer.size");
43
44 // ensure subsequent tests (which assume 32 slots) pass
45 final Field field = Unbox.class.getDeclaredField("RINGBUFFER_SIZE");
46 field.setAccessible(true); // make non-private
47
48 final Field modifierField = Field.class.getDeclaredField("modifiers");
49 modifierField.setAccessible(true);
50 modifierField.setInt(field, field.getModifiers() &~ Modifier.FINAL); // make non-final
51
52 field.set(null, 32); // reset to default
53
54 final Field threadLocalField = Unbox.class.getDeclaredField("threadLocalState");
55 threadLocalField.setAccessible(true);
56 final ThreadLocal<?> threadLocal = (ThreadLocal<?>) threadLocalField.get(null);
57 threadLocal.remove();
58 threadLocalField.set(null, new ThreadLocal<>());
59 }
60
61 @Ignore
62 @Test
63 public void testBoxConfiguredTo128Slots() throws Exception {
64 // next power of 2 that is 65 or more
65 assertEquals(128, Unbox.getRingbufferSize());
66 }
67
68 @Ignore
69 @Test
70 public void testBoxSuccessfullyConfiguredTo128Slots() throws Exception {
71 final int MAX = 128;
72 final StringBuilder[] probe = new StringBuilder[MAX * 3];
73 for (int i = 0; i <= probe.length - 8; ) {
74 probe[i++] = Unbox.box(true);
75 probe[i++] = Unbox.box('c');
76 probe[i++] = Unbox.box(Byte.MAX_VALUE);
77 probe[i++] = Unbox.box(Double.MAX_VALUE);
78 probe[i++] = Unbox.box(Float.MAX_VALUE);
79 probe[i++] = Unbox.box(Integer.MAX_VALUE);
80 probe[i++] = Unbox.box(Long.MAX_VALUE);
81 probe[i++] = Unbox.box(Short.MAX_VALUE);
82 }
83 for (int i = 0; i < probe.length - MAX; i++) {
84 assertSame("probe[" + i +"], probe[" + (i + MAX) +"]", probe[i], probe[i + MAX]);
85 for (int j = 1; j < MAX - 1; j++) {
86 assertNotSame("probe[" + i +"], probe[" + (i + j) +"]", probe[i], probe[i + j]);
87 }
88 }
89 }
90 }
+0
-67
log4j-api/src/test/java/org/apache/logging/log4j/util/UnboxConfigurableTest.java less more
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.util;
17
18 import org.junit.AfterClass;
19 import org.junit.BeforeClass;
20 import org.junit.Test;
21
22 import static org.junit.Assert.*;
23
24 /**
25 * Tests that the Unbox ring buffer size is configurable.
26 * Must be run in a separate process as the other UnboxTest or the last-run test will fail.
27 */
28 public class UnboxConfigurableTest {
29 @BeforeClass
30 public static void beforeClass() {
31 System.setProperty("log4j.unbox.ringbuffer.size", "65");
32 }
33
34 @AfterClass
35 public static void afterClass() {
36 System.clearProperty("log4j.unbox.ringbuffer.size");
37 }
38
39 @Test
40 public void testBoxConfiguredTo128Slots() throws Exception {
41 // next power of 2 that is 65 or more
42 assertEquals(128, Unbox.getRingbufferSize());
43 }
44
45 @Test
46 public void testBoxSuccessfullyConfiguredTo128Slots() throws Exception {
47 final int MAX = 128;
48 final StringBuilder[] probe = new StringBuilder[MAX * 3];
49 for (int i = 0; i <= probe.length - 8; ) {
50 probe[i++] = Unbox.box(true);
51 probe[i++] = Unbox.box('c');
52 probe[i++] = Unbox.box(Byte.MAX_VALUE);
53 probe[i++] = Unbox.box(Double.MAX_VALUE);
54 probe[i++] = Unbox.box(Float.MAX_VALUE);
55 probe[i++] = Unbox.box(Integer.MAX_VALUE);
56 probe[i++] = Unbox.box(Long.MAX_VALUE);
57 probe[i++] = Unbox.box(Short.MAX_VALUE);
58 }
59 for (int i = 0; i < probe.length - MAX; i++) {
60 assertSame("probe[" + i +"], probe[" + (i + MAX) +"]", probe[i], probe[i + MAX]);
61 for (int j = 1; j < MAX - 1; j++) {
62 assertNotSame("probe[" + i +"], probe[" + (i + j) +"]", probe[i], probe[i + j]);
63 }
64 }
65 }
66 }
+0
-165
log4j-api/src/test/java/org/apache/logging/log4j/util/UnboxTest.java less more
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16
17 package org.apache.logging.log4j.util;
18
19 import org.junit.Test;
20
21 import static org.junit.Assert.*;
22
23 /**
24 * Tests the Unbox class.
25 */
26 public class UnboxTest {
27
28 @Test
29 public void testBoxClaimsItHas32Slots() throws Exception {
30 assertEquals(32, Unbox.getRingbufferSize());
31 }
32
33 @Test
34 public void testBoxHas32Slots() throws Exception {
35 final int MAX = 32;
36 final StringBuilder[] probe = new StringBuilder[MAX * 3];
37 for (int i = 0; i <= probe.length - 8; ) {
38 probe[i++] = Unbox.box(true);
39 probe[i++] = Unbox.box('c');
40 probe[i++] = Unbox.box(Byte.MAX_VALUE);
41 probe[i++] = Unbox.box(Double.MAX_VALUE);
42 probe[i++] = Unbox.box(Float.MAX_VALUE);
43 probe[i++] = Unbox.box(Integer.MAX_VALUE);
44 probe[i++] = Unbox.box(Long.MAX_VALUE);
45 probe[i++] = Unbox.box(Short.MAX_VALUE);
46 }
47 for (int i = 0; i < probe.length - MAX; i++) {
48 assertSame("probe[" + i +"], probe[" + (i + MAX) +"]", probe[i], probe[i + MAX]);
49 for (int j = 1; j < MAX - 1; j++) {
50 assertNotSame("probe[" + i +"], probe[" + (i + j) +"]", probe[i], probe[i + j]);
51 }
52 }
53 }
54
55 @Test
56 public void testBoxBoolean() throws Exception {
57 assertEquals("true", Unbox.box(true).toString());
58 assertEquals("false", Unbox.box(false).toString());
59 }
60
61 @Test
62 public void testBoxByte() throws Exception {
63 assertEquals("0", Unbox.box((byte) 0).toString());
64 assertEquals("1", Unbox.box((byte) 1).toString());
65 assertEquals("127", Unbox.box((byte) 127).toString());
66 assertEquals("-1", Unbox.box((byte) -1).toString());
67 assertEquals("-128", Unbox.box((byte) -128).toString());
68 }
69
70 @Test
71 public void testBoxChar() throws Exception {
72 assertEquals("a", Unbox.box('a').toString());
73 assertEquals("b", Unbox.box('b').toString());
74 assertEquals("字", Unbox.box('字').toString());
75 }
76
77 @Test
78 public void testBoxDouble() throws Exception {
79 assertEquals("3.14", Unbox.box(3.14).toString());
80 assertEquals(new Double(Double.MAX_VALUE).toString(), Unbox.box(Double.MAX_VALUE).toString());
81 assertEquals(new Double(Double.MIN_VALUE).toString(), Unbox.box(Double.MIN_VALUE).toString());
82 }
83
84 @Test
85 public void testBoxFloat() throws Exception {
86 assertEquals("3.14", Unbox.box(3.14F).toString());
87 assertEquals(new Float(Float.MAX_VALUE).toString(), Unbox.box(Float.MAX_VALUE).toString());
88 assertEquals(new Float(Float.MIN_VALUE).toString(), Unbox.box(Float.MIN_VALUE).toString());
89 }
90
91 @Test
92 public void testBoxInt() throws Exception {
93 assertEquals("0", Unbox.box(0).toString());
94 assertEquals("1", Unbox.box(1).toString());
95 assertEquals("127", Unbox.box(127).toString());
96 assertEquals("-1", Unbox.box(-1).toString());
97 assertEquals("-128", Unbox.box(-128).toString());
98 assertEquals(new Integer(Integer.MAX_VALUE).toString(), Unbox.box(Integer.MAX_VALUE).toString());
99 assertEquals(new Integer(Integer.MIN_VALUE).toString(), Unbox.box(Integer.MIN_VALUE).toString());
100 }
101
102 @Test
103 public void testBoxLong() throws Exception {
104 assertEquals("0", Unbox.box(0L).toString());
105 assertEquals("1", Unbox.box(1L).toString());
106 assertEquals("127", Unbox.box(127L).toString());
107 assertEquals("-1", Unbox.box(-1L).toString());
108 assertEquals("-128", Unbox.box(-128L).toString());
109 assertEquals(new Long(Long.MAX_VALUE).toString(), Unbox.box(Long.MAX_VALUE).toString());
110 assertEquals(new Long(Long.MIN_VALUE).toString(), Unbox.box(Long.MIN_VALUE).toString());
111 }
112
113 @Test
114 public void testBoxShort() throws Exception {
115 assertEquals("0", Unbox.box((short) 0).toString());
116 assertEquals("1", Unbox.box((short) 1).toString());
117 assertEquals("127", Unbox.box((short) 127).toString());
118 assertEquals("-1", Unbox.box((short) -1).toString());
119 assertEquals("-128", Unbox.box((short) -128).toString());
120 assertEquals(new Short(Short.MAX_VALUE).toString(), Unbox.box(Short.MAX_VALUE).toString());
121 assertEquals(new Short(Short.MIN_VALUE).toString(), Unbox.box(Short.MIN_VALUE).toString());
122 }
123
124 @Test
125 public void testBoxIsThreadLocal() throws Exception {
126 final StringBuilder[] probe = new StringBuilder[16 * 3];
127 populate(0, probe);
128 final Thread t1 = new Thread() {
129 @Override
130 public void run() {
131 populate(16, probe);
132 }
133 };
134 t1.start();
135 t1.join();
136 final Thread t2 = new Thread() {
137 @Override
138 public void run() {
139 populate(16, probe);
140 }
141 };
142 t2.start();
143 t2.join();
144 for (int i = 0; i < probe.length - 16; i++) {
145 for (int j = 1; j < 16; j++) {
146 assertNotSame("probe[" + i +"]=" + probe[i] + ", probe[" + (i + j) +"]=" + probe[i + j],
147 probe[i], probe[i + j]);
148 }
149 }
150 }
151
152 private void populate(final int start, final StringBuilder[] probe) {
153 for (int i = start; i <= start + 8; ) {
154 probe[i++] = Unbox.box(true);
155 probe[i++] = Unbox.box('c');
156 probe[i++] = Unbox.box(Byte.MAX_VALUE);
157 probe[i++] = Unbox.box(Double.MAX_VALUE);
158 probe[i++] = Unbox.box(Float.MAX_VALUE);
159 probe[i++] = Unbox.box(Integer.MAX_VALUE);
160 probe[i++] = Unbox.box(Long.MAX_VALUE);
161 probe[i++] = Unbox.box(Short.MAX_VALUE);
162 }
163 }
164 }
0 <?xml version="1.0" encoding="UTF-8"?>
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 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
18 <modelVersion>4.0.0</modelVersion>
19 <parent>
20 <groupId>org.apache.logging.log4j</groupId>
21 <artifactId>log4j</artifactId>
22 <version>2.7</version>
23 <relativePath>../</relativePath>
24 </parent>
25 <artifactId>log4j-api-scala_2.10</artifactId>
26 <packaging>jar</packaging>
27 <name>Apache Log4j Scala 2.10 wrapper for Log4j API</name>
28 <description>Scala wrapper for Log4j API</description>
29 <properties>
30 <log4jParentDir>${basedir}/..</log4jParentDir>
31 <projectDir>/scala_2.10</projectDir>
32 <scala.version>2.10.6</scala.version>
33 <scala.maven.plugin.version>3.2.2</scala.maven.plugin.version>
34 </properties>
35 <dependencies>
36 <dependency>
37 <groupId>org.apache.logging.log4j</groupId>
38 <artifactId>log4j-api</artifactId>
39 </dependency>
40 <dependency>
41 <groupId>org.scala-lang</groupId>
42 <artifactId>scala-library</artifactId>
43 <version>${scala.version}</version>
44 </dependency>
45 <dependency>
46 <groupId>org.scala-lang</groupId>
47 <artifactId>scala-reflect</artifactId>
48 <version>${scala.version}</version>
49 </dependency>
50 <dependency>
51 <groupId>org.apache.logging.log4j</groupId>
52 <artifactId>log4j-api</artifactId>
53 <type>test-jar</type>
54 <scope>test</scope>
55 </dependency>
56 <dependency>
57 <groupId>junit</groupId>
58 <artifactId>junit</artifactId>
59 <scope>test</scope>
60 </dependency>
61 <dependency>
62 <groupId>org.scalatest</groupId>
63 <artifactId>scalatest_2.10</artifactId>
64 <version>2.2.6</version>
65 <scope>test</scope>
66 </dependency>
67 <dependency>
68 <groupId>org.mockito</groupId>
69 <artifactId>mockito-core</artifactId>
70 <version>1.10.19</version>
71 <scope>test</scope>
72 </dependency>
73 </dependencies>
74 <build>
75 <sourceDirectory>src/main/scala</sourceDirectory>
76 <testSourceDirectory>src/test/scala</testSourceDirectory>
77 <plugins>
78 <plugin>
79 <groupId>net.alchim31.maven</groupId>
80 <artifactId>scala-maven-plugin</artifactId>
81 <version>${scala.maven.plugin.version}</version>
82 <executions>
83 <execution>
84 <goals>
85 <goal>compile</goal>
86 <goal>testCompile</goal>
87 </goals>
88 </execution>
89 </executions>
90 </plugin>
91 <plugin>
92 <groupId>org.apache.maven.plugins</groupId>
93 <artifactId>maven-surefire-plugin</artifactId>
94 </plugin>
95 <!-- Include the standard NOTICE and LICENSE -->
96 <plugin>
97 <groupId>org.apache.maven.plugins</groupId>
98 <artifactId>maven-remote-resources-plugin</artifactId>
99 <executions>
100 <execution>
101 <goals>
102 <goal>process</goal>
103 </goals>
104 <configuration>
105 <skip>false</skip>
106 </configuration>
107 </execution>
108 </executions>
109 </plugin>
110 <plugin>
111 <groupId>org.apache.felix</groupId>
112 <artifactId>maven-bundle-plugin</artifactId>
113 </plugin>
114 </plugins>
115 </build>
116 <reporting>
117 <plugins>
118 <plugin>
119 <groupId>org.apache.maven.plugins</groupId>
120 <artifactId>maven-changes-plugin</artifactId>
121 <version>${changes.plugin.version}</version>
122 <reportSets>
123 <reportSet>
124 <reports>
125 <report>changes-report</report>
126 </reports>
127 </reportSet>
128 </reportSets>
129 <configuration>
130 <issueLinkTemplate>%URL%/show_bug.cgi?id=%ISSUE%</issueLinkTemplate>
131 <useJql>true</useJql>
132 </configuration>
133 </plugin>
134 <plugin>
135 <groupId>org.apache.maven.plugins</groupId>
136 <artifactId>maven-pmd-plugin</artifactId>
137 <version>${pmd.plugin.version}</version>
138 <configuration>
139 <targetJdk>${maven.compile.target}</targetJdk>
140 </configuration>
141 </plugin>
142 <plugin>
143 <groupId>net.alchim31.maven</groupId>
144 <artifactId>scala-maven-plugin</artifactId>
145 <version>${scala.maven.plugin.version}</version>
146 </plugin>
147 </plugins>
148 </reporting>
149 </project>
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.scala
17
18 import org.apache.logging.log4j.message.{EntryMessage, Message, MessageFactory2}
19 import org.apache.logging.log4j.spi.ExtendedLogger
20 import org.apache.logging.log4j.{Level, LogManager, Marker}
21
22 import scala.language.experimental.macros
23
24 /**
25 * Factory for [[Logger]]s.
26 *
27 * The [[Logging]] trait provides a simple way to get a properly named logger into a class.
28 */
29 object Logger {
30
31 final val FQCN = getClass.getName
32
33 /**
34 * Create a properly named [[Logger]] for a given class.
35 *
36 * @param clazz the class
37 */
38 def apply(clazz: Class[_]): Logger = Logger(LogManager.getContext(clazz.getClassLoader, false).getLogger(clazz.getName))
39
40 /**
41 * Create a [[Logger]] wrapping the given Log4j logger.
42 *
43 * @param delegate the Log4j logger to wrap
44 */
45 def apply(delegate: ExtendedLogger): Logger = new Logger(delegate)
46
47 }
48
49 /**
50 * Scala wrapper for the Log4j `Logger` interface.
51 *
52 * Frequently the purpose of logging is to provide information about what is happening in the system,
53 * which requires including information about the objects being manipulated. In Scala, you can use
54 * [[http://docs.scala-lang.org/overviews/core/string-interpolation.html string interpolation]]
55 * to achieve this:
56 *
57 * {{{
58 * logger.debug(s"Logging in user ${user.getName} with birthday ${user.calcBirthday}")
59 * }}}
60 *
61 * Since this wrapper is implemented with macros, the String construction and method invocations
62 * will only occur when debug logging is enabled.
63 */
64 class Logger private(val delegate: ExtendedLogger) extends AnyVal {
65
66 def fatal(marker: Marker, message: Message): Unit =
67 macro LoggerMacro.fatalMarkerMsg
68
69 def fatal(marker: Marker, message: CharSequence): Unit =
70 macro LoggerMacro.fatalMarkerCseq
71
72 def fatal(marker: Marker, message: AnyRef): Unit =
73 macro LoggerMacro.fatalMarkerObject
74
75 def fatal(marker: Marker, message: Message, cause: Throwable): Unit =
76 macro LoggerMacro.fatalMarkerMsgThrowable
77
78 def fatal(marker: Marker, message: CharSequence, cause: Throwable): Unit =
79 macro LoggerMacro.fatalMarkerCseqThrowable
80
81 def fatal(marker: Marker, message: AnyRef, cause: Throwable): Unit =
82 macro LoggerMacro.fatalMarkerObjectThrowable
83
84 def fatal(message: Message): Unit =
85 macro LoggerMacro.fatalMsg
86
87 def fatal(message: CharSequence): Unit =
88 macro LoggerMacro.fatalCseq
89
90 def fatal(message: AnyRef): Unit =
91 macro LoggerMacro.fatalObject
92
93 def fatal(message: Message, cause: Throwable): Unit =
94 macro LoggerMacro.fatalMsgThrowable
95
96 def fatal(message: CharSequence, cause: Throwable): Unit =
97 macro LoggerMacro.fatalCseqThrowable
98
99 def fatal(message: AnyRef, cause: Throwable): Unit =
100 macro LoggerMacro.fatalObjectThrowable
101
102
103 def error(marker: Marker, message: Message): Unit =
104 macro LoggerMacro.errorMarkerMsg
105
106 def error(marker: Marker, message: CharSequence): Unit =
107 macro LoggerMacro.errorMarkerCseq
108
109 def error(marker: Marker, message: AnyRef): Unit =
110 macro LoggerMacro.errorMarkerObject
111
112 def error(marker: Marker, message: Message, cause: Throwable): Unit =
113 macro LoggerMacro.errorMarkerMsgThrowable
114
115 def error(marker: Marker, message: CharSequence, cause: Throwable): Unit =
116 macro LoggerMacro.errorMarkerCseqThrowable
117
118 def error(marker: Marker, message: AnyRef, cause: Throwable): Unit =
119 macro LoggerMacro.errorMarkerObjectThrowable
120
121 def error(message: Message): Unit =
122 macro LoggerMacro.errorMsg
123
124 def error(message: CharSequence): Unit =
125 macro LoggerMacro.errorCseq
126
127 def error(message: AnyRef): Unit =
128 macro LoggerMacro.errorObject
129
130 def error(message: Message, cause: Throwable): Unit =
131 macro LoggerMacro.errorMsgThrowable
132
133 def error(message: CharSequence, cause: Throwable): Unit =
134 macro LoggerMacro.errorCseqThrowable
135
136 def error(message: AnyRef, cause: Throwable): Unit =
137 macro LoggerMacro.errorObjectThrowable
138
139
140 def warn(marker: Marker, message: Message): Unit =
141 macro LoggerMacro.warnMarkerMsg
142
143 def warn(marker: Marker, message: CharSequence): Unit =
144 macro LoggerMacro.warnMarkerCseq
145
146 def warn(marker: Marker, message: AnyRef): Unit =
147 macro LoggerMacro.warnMarkerObject
148
149 def warn(marker: Marker, message: Message, cause: Throwable): Unit =
150 macro LoggerMacro.warnMarkerMsgThrowable
151
152 def warn(marker: Marker, message: CharSequence, cause: Throwable): Unit =
153 macro LoggerMacro.warnMarkerCseqThrowable
154
155 def warn(marker: Marker, message: AnyRef, cause: Throwable): Unit =
156 macro LoggerMacro.warnMarkerObjectThrowable
157
158 def warn(message: Message): Unit =
159 macro LoggerMacro.warnMsg
160
161 def warn(message: CharSequence): Unit =
162 macro LoggerMacro.warnCseq
163
164 def warn(message: AnyRef): Unit =
165 macro LoggerMacro.warnObject
166
167 def warn(message: Message, cause: Throwable): Unit =
168 macro LoggerMacro.warnMsgThrowable
169
170 def warn(message: CharSequence, cause: Throwable): Unit =
171 macro LoggerMacro.warnCseqThrowable
172
173 def warn(message: AnyRef, cause: Throwable): Unit =
174 macro LoggerMacro.warnObjectThrowable
175
176
177 def info(marker: Marker, message: Message): Unit =
178 macro LoggerMacro.infoMarkerMsg
179
180 def info(marker: Marker, message: CharSequence): Unit =
181 macro LoggerMacro.infoMarkerCseq
182
183 def info(marker: Marker, message: AnyRef): Unit =
184 macro LoggerMacro.infoMarkerObject
185
186 def info(marker: Marker, message: Message, cause: Throwable): Unit =
187 macro LoggerMacro.infoMarkerMsgThrowable
188
189 def info(marker: Marker, message: CharSequence, cause: Throwable): Unit =
190 macro LoggerMacro.infoMarkerCseqThrowable
191
192 def info(marker: Marker, message: AnyRef, cause: Throwable): Unit =
193 macro LoggerMacro.infoMarkerObjectThrowable
194
195 def info(message: Message): Unit =
196 macro LoggerMacro.infoMsg
197
198 def info(message: CharSequence): Unit =
199 macro LoggerMacro.infoCseq
200
201 def info(message: AnyRef): Unit =
202 macro LoggerMacro.infoObject
203
204 def info(message: Message, cause: Throwable): Unit =
205 macro LoggerMacro.infoMsgThrowable
206
207 def info(message: CharSequence, cause: Throwable): Unit =
208 macro LoggerMacro.infoCseqThrowable
209
210 def info(message: AnyRef, cause: Throwable): Unit =
211 macro LoggerMacro.infoObjectThrowable
212
213
214 def debug(marker: Marker, message: Message): Unit =
215 macro LoggerMacro.debugMarkerMsg
216
217 def debug(marker: Marker, message: CharSequence): Unit =
218 macro LoggerMacro.debugMarkerCseq
219
220 def debug(marker: Marker, message: AnyRef): Unit =
221 macro LoggerMacro.debugMarkerObject
222
223 def debug(marker: Marker, message: Message, cause: Throwable): Unit =
224 macro LoggerMacro.debugMarkerMsgThrowable
225
226 def debug(marker: Marker, message: CharSequence, cause: Throwable): Unit =
227 macro LoggerMacro.debugMarkerCseqThrowable
228
229 def debug(marker: Marker, message: AnyRef, cause: Throwable): Unit =
230 macro LoggerMacro.debugMarkerObjectThrowable
231
232 def debug(message: Message): Unit =
233 macro LoggerMacro.debugMsg
234
235 def debug(message: CharSequence): Unit =
236 macro LoggerMacro.debugCseq
237
238 def debug(message: AnyRef): Unit =
239 macro LoggerMacro.debugObject
240
241 def debug(message: Message, cause: Throwable): Unit =
242 macro LoggerMacro.debugMsgThrowable
243
244 def debug(message: CharSequence, cause: Throwable): Unit =
245 macro LoggerMacro.debugCseqThrowable
246
247 def debug(message: AnyRef, cause: Throwable): Unit =
248 macro LoggerMacro.debugObjectThrowable
249
250
251 def trace(marker: Marker, message: Message): Unit =
252 macro LoggerMacro.traceMarkerMsg
253
254 def trace(marker: Marker, message: CharSequence): Unit =
255 macro LoggerMacro.traceMarkerCseq
256
257 def trace(marker: Marker, message: AnyRef): Unit =
258 macro LoggerMacro.traceMarkerObject
259
260 def trace(marker: Marker, message: Message, cause: Throwable): Unit =
261 macro LoggerMacro.traceMarkerMsgThrowable
262
263 def trace(marker: Marker, message: CharSequence, cause: Throwable): Unit =
264 macro LoggerMacro.traceMarkerCseqThrowable
265
266 def trace(marker: Marker, message: AnyRef, cause: Throwable): Unit =
267 macro LoggerMacro.traceMarkerObjectThrowable
268
269 def trace(message: Message): Unit =
270 macro LoggerMacro.traceMsg
271
272 def trace(message: CharSequence): Unit =
273 macro LoggerMacro.traceCseq
274
275 def trace(message: AnyRef): Unit =
276 macro LoggerMacro.traceObject
277
278 def trace(message: Message, cause: Throwable): Unit =
279 macro LoggerMacro.traceMsgThrowable
280
281 def trace(message: CharSequence, cause: Throwable): Unit =
282 macro LoggerMacro.traceCseqThrowable
283
284 def trace(message: AnyRef, cause: Throwable): Unit =
285 macro LoggerMacro.traceObjectThrowable
286
287
288 /**
289 * Logs a `Message` with the specific `Marker` at the given `Level`.
290 *
291 * @param level the logging level
292 * @param marker the marker data specific to this log statement
293 * @param message the message to be logged
294 */
295 def apply(level: Level, marker: Marker, message: Message): Unit =
296 macro LoggerMacro.logMarkerMsg
297
298 /**
299 * Logs a string with the specific `Marker` at the given `Level`.
300 *
301 * @param level the logging level
302 * @param marker the marker data specific to this log statement
303 * @param message the message to be logged
304 */
305 def apply(level: Level, marker: Marker, message: CharSequence): Unit =
306 macro LoggerMacro.logMarkerCseq
307
308 /**
309 * Logs an object with the specific `Marker` at the given `Level`.
310 *
311 * @param level the logging level
312 * @param marker the marker data specific to this log statement
313 * @param message the message to be logged
314 */
315 def apply(level: Level, marker: Marker, message: AnyRef): Unit =
316 macro LoggerMacro.logMarkerObject
317
318 /**
319 * Logs a `Message` with the specific `Marker` at the given `Level` including the stack trace
320 * of the given `Throwable`.
321 *
322 * @param level the logging level
323 * @param marker the marker data specific to this log statement
324 * @param message the message to be logged
325 * @param cause the cause
326 */
327 def apply(level: Level, marker: Marker, message: Message, cause: Throwable): Unit =
328 macro LoggerMacro.logMarkerMsgThrowable
329
330 /**
331 * Logs a string with the specific `Marker` at the given `Level` including the stack trace
332 * of the given `Throwable`.
333 *
334 * @param level the logging level
335 * @param marker the marker data specific to this log statement
336 * @param message the message to be logged
337 * @param cause the cause
338 */
339 def apply(level: Level, marker: Marker, message: CharSequence, cause: Throwable): Unit =
340 macro LoggerMacro.logMarkerCseqThrowable
341
342 /**
343 * Logs an object with the specific `Marker` at the given `Level` including the stack trace
344 * of the given `Throwable`.
345 *
346 * @param level the logging level
347 * @param marker the marker data specific to this log statement
348 * @param message the message to be logged
349 * @param cause the cause
350 */
351 def apply(level: Level, marker: Marker, message: AnyRef, cause: Throwable): Unit =
352 macro LoggerMacro.logMarkerObjectThrowable
353
354 /**
355 * Logs a `Message` at the given `Level`.
356 *
357 * @param level the logging level
358 * @param message the message to be logged
359 */
360 def apply(level: Level, message: Message): Unit =
361 macro LoggerMacro.logMsg
362
363 /**
364 * Logs a string at the given `Level`.
365 *
366 * @param level the logging level
367 * @param message the message to be logged
368 */
369 def apply(level: Level, message: CharSequence): Unit =
370 macro LoggerMacro.logCseq
371
372 /**
373 * Logs an object at the given `Level`.
374 *
375 * @param level the logging level
376 * @param message the message to be logged
377 */
378 def apply(level: Level, message: AnyRef): Unit =
379 macro LoggerMacro.logObject
380
381 /**
382 * Logs a `Message` at the given `Level` including the stack trace of the given `Throwable`.
383 *
384 * @param level the logging level
385 * @param message the message to be logged
386 * @param cause a `Throwable`
387 */
388 def apply(level: Level, message: Message, cause: Throwable): Unit =
389 macro LoggerMacro.logMsgThrowable
390
391 /**
392 * Logs a string at the given `Level` including the stack trace of the given `Throwable`.
393 *
394 * @param level the logging level
395 * @param message the message to be logged
396 * @param cause a `Throwable`
397 */
398 def apply(level: Level, message: CharSequence, cause: Throwable): Unit =
399 macro LoggerMacro.logCseqThrowable
400
401 /**
402 * Logs an object at the given `Level` including the stack trace of the given `Throwable`.
403 *
404 * @param level the logging level
405 * @param message the message to be logged
406 * @param cause a `Throwable`
407 */
408 def apply(level: Level, message: AnyRef, cause: Throwable): Unit =
409 macro LoggerMacro.logObjectThrowable
410
411
412 /**
413 * Logs entry to a method. Used when the method in question has no parameters or when the parameters should not be
414 * logged.
415 *
416 * @return The built `EntryMessage`
417 */
418 def traceEntry(): EntryMessage =
419 macro LoggerMacro.traceEntry
420
421 /**
422 * Logs entry to a method along with its parameters.
423 *
424 * {{{
425 * def doSomething(foo: String, bar: Int): Unit = {
426 * logger.traceEntry(foo, bar)
427 * // do something
428 * }
429 * }}}
430 *
431 * @param params the parameters to the method.
432 * @return The built `EntryMessage`
433 */
434 def traceEntry(params: AnyRef*): EntryMessage =
435 macro LoggerMacro.traceEntryParams
436
437 /**
438 * Logs entry to a method using a `Message` to describe the parameters.
439 *
440 * {{{
441 * def doSomething(foo: Request): Unit = {
442 * logger.traceEntry(JsonMessage(foo))
443 * // do something
444 * }
445 * }}}
446 *
447 * @param message the message
448 * @return The built `EntryMessage`
449 */
450 def traceEntry(message: Message): EntryMessage =
451 macro LoggerMacro.traceEntryMessage
452
453 /**
454 * Logs exit from a method with no result.
455 */
456 def traceExit(): Unit =
457 macro LoggerMacro.traceExit
458
459 /**
460 * Logs exiting from a method with result.
461 *
462 * @param result The result being returned from the method call
463 * @return `result`
464 */
465 def traceExit[R](result: R): R =
466 macro LoggerMacro.traceExitResult[R]
467
468 /**
469 * Logs exiting from a method with no result.
470 *
471 * @param entryMessage the `EntryMessage` returned from one of the `traceEntry` methods
472 */
473 def traceExit(entryMessage: EntryMessage): Unit =
474 macro LoggerMacro.traceExitEntryMessage
475
476 /**
477 * Logs exiting from a method with result.
478 *
479 * {{{
480 * def doSomething(foo: String, bar: Int): Int = {
481 * val entryMessage = logger.traceEntry(foo, bar)
482 * // do something
483 * traceExit(entryMessage, value)
484 * }
485 * }}}
486 *
487 * @param entryMessage the `EntryMessage` returned from one of the `traceEntry` methods
488 * @param result The result being returned from the method call
489 * @return `result`
490 */
491 def traceExit[R](entryMessage: EntryMessage, result: R): R =
492 macro LoggerMacro.traceExitEntryMessageResult[R]
493
494 /**
495 * Logs exiting from a method with result. Allows custom formatting of the result.
496 *
497 * @param message the Message containing the formatted result
498 * @param result The result being returned from the method call.
499 * @return `result`
500 */
501 def traceExit[R](message: Message, result: R): R =
502 macro LoggerMacro.traceExitMessageResult[R]
503
504 /**
505 * Logs an exception or error to be thrown.
506 *
507 * {{{
508 * throw logger.throwing(myException)
509 * }}}
510 *
511 * @param t the Throwable
512 * @return `t`
513 */
514 def throwing[T <: Throwable](t: T): T =
515 macro LoggerMacro.throwing[T]
516
517 /**
518 * Logs an exception or error to be thrown to a specific logging level.
519 *
520 * {{{
521 * throw logger.throwing(Level.DEBUG, myException)
522 * }}}
523 *
524 * @param level the logging Level.
525 * @param t the Throwable
526 * @return `t`
527 */
528 def throwing[T <: Throwable](level: Level, t: T): T =
529 macro LoggerMacro.throwingLevel[T]
530
531 /**
532 * Logs an exception or error that has been caught.
533 *
534 * @param t the Throwable.
535 */
536 def catching(t: Throwable): Unit =
537 macro LoggerMacro.catching
538
539 /**
540 * Logs an exception or error that has been caught to a specific logging level.
541 *
542 * @param level The logging Level.
543 * @param t The Throwable.
544 */
545 def catching(level: Level, t: Throwable): Unit =
546 macro LoggerMacro.catchingLevel
547
548
549 /** Always logs a message at the specified level. It is the responsibility of the caller to ensure the specified
550 * level is enabled.
551 *
552 * Should normally not be used directly from application code, but needs to be public for access by macros.
553 *
554 * @param level log level
555 * @param marker marker or `null`
556 * @param message message
557 * @param cause cause or `null`
558 */
559 def logMessage(level: Level, marker: Marker, message: Message, cause: Throwable): Unit = {
560 delegate.logMessage(Logger.FQCN, level, marker, message, cause)
561 }
562
563 /** Always logs a message at the specified level. It is the responsibility of the caller to ensure the specified
564 * level is enabled.
565 *
566 * Should normally not be used directly from application code, but needs to be public for access by macros.
567 *
568 * @param level log level
569 * @param marker marker or `null`
570 * @param message message
571 * @param cause cause or `null`
572 */
573 def logMessage(level: Level, marker: Marker, message: CharSequence, cause: Throwable): Unit = {
574 delegate.logMessage(Logger.FQCN, level, marker, delegate.getMessageFactory.asInstanceOf[MessageFactory2].newMessage(message), cause)
575 }
576
577 /** Always logs a message at the specified level. It is the responsibility of the caller to ensure the specified
578 * level is enabled.
579 *
580 * Should normally not be used directly from application code, but needs to be public for access by macros.
581 *
582 * @param level log level
583 * @param marker marker or `null`
584 * @param message message
585 * @param cause cause or `null`
586 */
587 def logMessage(level: Level, marker: Marker, message: AnyRef, cause: Throwable): Unit = {
588 delegate.logMessage(Logger.FQCN, level, marker, delegate.getMessageFactory.asInstanceOf[MessageFactory2].newMessage(message), cause)
589 }
590
591 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.scala
17
18 import org.apache.logging.log4j.message.{EntryMessage, Message}
19 import org.apache.logging.log4j.spi.AbstractLogger
20 import org.apache.logging.log4j.{Level, Marker}
21
22 import scala.language.experimental.macros
23 import scala.reflect.macros.Context
24
25 /**
26 * Inspired from [[https://github.com/typesafehub/scalalogging ScalaLogging]].
27 */
28 private object LoggerMacro {
29
30 type LoggerContext = Context {type PrefixType = Logger}
31
32
33 def fatalMarkerMsg(c: LoggerContext)(marker: c.Expr[Marker], message: c.Expr[Message]) =
34 logMarkerMsg(c)(c.universe.reify(Level.FATAL), marker, message)
35
36 def fatalMarkerCseq(c: LoggerContext)(marker: c.Expr[Marker], message: c.Expr[CharSequence]) =
37 logMarkerCseq(c)(c.universe.reify(Level.FATAL), marker, message)
38
39 def fatalMarkerObject(c: LoggerContext)(marker: c.Expr[Marker], message: c.Expr[AnyRef]) =
40 logMarkerObject(c)(c.universe.reify(Level.FATAL), marker, message)
41
42 def fatalMarkerMsgThrowable(c: LoggerContext)(marker: c.Expr[Marker], message: c.Expr[Message], cause: c.Expr[Throwable]) =
43 logMarkerMsgThrowable(c)(c.universe.reify(Level.FATAL), marker, message, cause)
44
45 def fatalMarkerCseqThrowable(c: LoggerContext)(marker: c.Expr[Marker], message: c.Expr[CharSequence], cause: c.Expr[Throwable]) =
46 logMarkerCseqThrowable(c)(c.universe.reify(Level.FATAL), marker, message, cause)
47
48 def fatalMarkerObjectThrowable(c: LoggerContext)(marker: c.Expr[Marker], message: c.Expr[AnyRef], cause: c.Expr[Throwable]) =
49 logMarkerObjectThrowable(c)(c.universe.reify(Level.FATAL), marker, message, cause)
50
51 def fatalMsg(c: LoggerContext)(message: c.Expr[Message]) =
52 logMsg(c)(c.universe.reify(Level.FATAL), message)
53
54 def fatalCseq(c: LoggerContext)(message: c.Expr[CharSequence]) =
55 logCseq(c)(c.universe.reify(Level.FATAL), message)
56
57 def fatalObject(c: LoggerContext)(message: c.Expr[AnyRef]) =
58 logObject(c)(c.universe.reify(Level.FATAL), message)
59
60 def fatalMsgThrowable(c: LoggerContext)(message: c.Expr[Message], cause: c.Expr[Throwable]) =
61 logMsgThrowable(c)(c.universe.reify(Level.FATAL), message, cause)
62
63 def fatalCseqThrowable(c: LoggerContext)(message: c.Expr[CharSequence], cause: c.Expr[Throwable]) =
64 logCseqThrowable(c)(c.universe.reify(Level.FATAL), message, cause)
65
66 def fatalObjectThrowable(c: LoggerContext)(message: c.Expr[AnyRef], cause: c.Expr[Throwable]) =
67 logObjectThrowable(c)(c.universe.reify(Level.FATAL), message, cause)
68
69
70 def errorMarkerMsg(c: LoggerContext)(marker: c.Expr[Marker], message: c.Expr[Message]) =
71 logMarkerMsg(c)(c.universe.reify(Level.ERROR), marker, message)
72
73 def errorMarkerCseq(c: LoggerContext)(marker: c.Expr[Marker], message: c.Expr[CharSequence]) =
74 logMarkerCseq(c)(c.universe.reify(Level.ERROR), marker, message)
75
76 def errorMarkerObject(c: LoggerContext)(marker: c.Expr[Marker], message: c.Expr[AnyRef]) =
77 logMarkerObject(c)(c.universe.reify(Level.ERROR), marker, message)
78
79 def errorMarkerMsgThrowable(c: LoggerContext)(marker: c.Expr[Marker], message: c.Expr[Message], cause: c.Expr[Throwable]) =
80 logMarkerMsgThrowable(c)(c.universe.reify(Level.ERROR), marker, message, cause)
81
82 def errorMarkerCseqThrowable(c: LoggerContext)(marker: c.Expr[Marker], message: c.Expr[CharSequence], cause: c.Expr[Throwable]) =
83 logMarkerCseqThrowable(c)(c.universe.reify(Level.ERROR), marker, message, cause)
84
85 def errorMarkerObjectThrowable(c: LoggerContext)(marker: c.Expr[Marker], message: c.Expr[AnyRef], cause: c.Expr[Throwable]) =
86 logMarkerObjectThrowable(c)(c.universe.reify(Level.ERROR), marker, message, cause)
87
88 def errorMsg(c: LoggerContext)(message: c.Expr[Message]) =
89 logMsg(c)(c.universe.reify(Level.ERROR), message)
90
91 def errorCseq(c: LoggerContext)(message: c.Expr[CharSequence]) =
92 logCseq(c)(c.universe.reify(Level.ERROR), message)
93
94 def errorObject(c: LoggerContext)(message: c.Expr[AnyRef]) =
95 logObject(c)(c.universe.reify(Level.ERROR), message)
96
97 def errorMsgThrowable(c: LoggerContext)(message: c.Expr[Message], cause: c.Expr[Throwable]) =
98 logMsgThrowable(c)(c.universe.reify(Level.ERROR), message, cause)
99
100 def errorCseqThrowable(c: LoggerContext)(message: c.Expr[CharSequence], cause: c.Expr[Throwable]) =
101 logCseqThrowable(c)(c.universe.reify(Level.ERROR), message, cause)
102
103 def errorObjectThrowable(c: LoggerContext)(message: c.Expr[AnyRef], cause: c.Expr[Throwable]) =
104 logObjectThrowable(c)(c.universe.reify(Level.ERROR), message, cause)
105
106
107 def warnMarkerMsg(c: LoggerContext)(marker: c.Expr[Marker], message: c.Expr[Message]) =
108 logMarkerMsg(c)(c.universe.reify(Level.WARN), marker, message)
109
110 def warnMarkerCseq(c: LoggerContext)(marker: c.Expr[Marker], message: c.Expr[CharSequence]) =
111 logMarkerCseq(c)(c.universe.reify(Level.WARN), marker, message)
112
113 def warnMarkerObject(c: LoggerContext)(marker: c.Expr[Marker], message: c.Expr[AnyRef]) =
114 logMarkerObject(c)(c.universe.reify(Level.WARN), marker, message)
115
116 def warnMarkerMsgThrowable(c: LoggerContext)(marker: c.Expr[Marker], message: c.Expr[Message], cause: c.Expr[Throwable]) =
117 logMarkerMsgThrowable(c)(c.universe.reify(Level.WARN), marker, message, cause)
118
119 def warnMarkerCseqThrowable(c: LoggerContext)(marker: c.Expr[Marker], message: c.Expr[CharSequence], cause: c.Expr[Throwable]) =
120 logMarkerCseqThrowable(c)(c.universe.reify(Level.WARN), marker, message, cause)
121
122 def warnMarkerObjectThrowable(c: LoggerContext)(marker: c.Expr[Marker], message: c.Expr[AnyRef], cause: c.Expr[Throwable]) =
123 logMarkerObjectThrowable(c)(c.universe.reify(Level.WARN), marker, message, cause)
124
125 def warnMsg(c: LoggerContext)(message: c.Expr[Message]) =
126 logMsg(c)(c.universe.reify(Level.WARN), message)
127
128 def warnCseq(c: LoggerContext)(message: c.Expr[CharSequence]) =
129 logCseq(c)(c.universe.reify(Level.WARN), message)
130
131 def warnObject(c: LoggerContext)(message: c.Expr[AnyRef]) =
132 logObject(c)(c.universe.reify(Level.WARN), message)
133
134 def warnMsgThrowable(c: LoggerContext)(message: c.Expr[Message], cause: c.Expr[Throwable]) =
135 logMsgThrowable(c)(c.universe.reify(Level.WARN), message, cause)
136
137 def warnCseqThrowable(c: LoggerContext)(message: c.Expr[CharSequence], cause: c.Expr[Throwable]) =
138 logCseqThrowable(c)(c.universe.reify(Level.WARN), message, cause)
139
140 def warnObjectThrowable(c: LoggerContext)(message: c.Expr[AnyRef], cause: c.Expr[Throwable]) =
141 logObjectThrowable(c)(c.universe.reify(Level.WARN), message, cause)
142
143
144 def infoMarkerMsg(c: LoggerContext)(marker: c.Expr[Marker], message: c.Expr[Message]) =
145 logMarkerMsg(c)(c.universe.reify(Level.INFO), marker, message)
146
147 def infoMarkerCseq(c: LoggerContext)(marker: c.Expr[Marker], message: c.Expr[CharSequence]) =
148 logMarkerCseq(c)(c.universe.reify(Level.INFO), marker, message)
149
150 def infoMarkerObject(c: LoggerContext)(marker: c.Expr[Marker], message: c.Expr[AnyRef]) =
151 logMarkerObject(c)(c.universe.reify(Level.INFO), marker, message)
152
153 def infoMarkerMsgThrowable(c: LoggerContext)(marker: c.Expr[Marker], message: c.Expr[Message], cause: c.Expr[Throwable]) =
154 logMarkerMsgThrowable(c)(c.universe.reify(Level.INFO), marker, message, cause)
155
156 def infoMarkerCseqThrowable(c: LoggerContext)(marker: c.Expr[Marker], message: c.Expr[CharSequence], cause: c.Expr[Throwable]) =
157 logMarkerCseqThrowable(c)(c.universe.reify(Level.INFO), marker, message, cause)
158
159 def infoMarkerObjectThrowable(c: LoggerContext)(marker: c.Expr[Marker], message: c.Expr[AnyRef], cause: c.Expr[Throwable]) =
160 logMarkerObjectThrowable(c)(c.universe.reify(Level.INFO), marker, message, cause)
161
162 def infoMsg(c: LoggerContext)(message: c.Expr[Message]) =
163 logMsg(c)(c.universe.reify(Level.INFO), message)
164
165 def infoCseq(c: LoggerContext)(message: c.Expr[CharSequence]) =
166 logCseq(c)(c.universe.reify(Level.INFO), message)
167
168 def infoObject(c: LoggerContext)(message: c.Expr[AnyRef]) =
169 logObject(c)(c.universe.reify(Level.INFO), message)
170
171 def infoMsgThrowable(c: LoggerContext)(message: c.Expr[Message], cause: c.Expr[Throwable]) =
172 logMsgThrowable(c)(c.universe.reify(Level.INFO), message, cause)
173
174 def infoCseqThrowable(c: LoggerContext)(message: c.Expr[CharSequence], cause: c.Expr[Throwable]) =
175 logCseqThrowable(c)(c.universe.reify(Level.INFO), message, cause)
176
177 def infoObjectThrowable(c: LoggerContext)(message: c.Expr[AnyRef], cause: c.Expr[Throwable]) =
178 logObjectThrowable(c)(c.universe.reify(Level.INFO), message, cause)
179
180
181 def debugMarkerMsg(c: LoggerContext)(marker: c.Expr[Marker], message: c.Expr[Message]) =
182 logMarkerMsg(c)(c.universe.reify(Level.DEBUG), marker, message)
183
184 def debugMarkerCseq(c: LoggerContext)(marker: c.Expr[Marker], message: c.Expr[CharSequence]) =
185 logMarkerCseq(c)(c.universe.reify(Level.DEBUG), marker, message)
186
187 def debugMarkerObject(c: LoggerContext)(marker: c.Expr[Marker], message: c.Expr[AnyRef]) =
188 logMarkerObject(c)(c.universe.reify(Level.DEBUG), marker, message)
189
190 def debugMarkerMsgThrowable(c: LoggerContext)(marker: c.Expr[Marker], message: c.Expr[Message], cause: c.Expr[Throwable]) =
191 logMarkerMsgThrowable(c)(c.universe.reify(Level.DEBUG), marker, message, cause)
192
193 def debugMarkerCseqThrowable(c: LoggerContext)(marker: c.Expr[Marker], message: c.Expr[CharSequence], cause: c.Expr[Throwable]) =
194 logMarkerCseqThrowable(c)(c.universe.reify(Level.DEBUG), marker, message, cause)
195
196 def debugMarkerObjectThrowable(c: LoggerContext)(marker: c.Expr[Marker], message: c.Expr[AnyRef], cause: c.Expr[Throwable]) =
197 logMarkerObjectThrowable(c)(c.universe.reify(Level.DEBUG), marker, message, cause)
198
199 def debugMsg(c: LoggerContext)(message: c.Expr[Message]) =
200 logMsg(c)(c.universe.reify(Level.DEBUG), message)
201
202 def debugCseq(c: LoggerContext)(message: c.Expr[CharSequence]) =
203 logCseq(c)(c.universe.reify(Level.DEBUG), message)
204
205 def debugObject(c: LoggerContext)(message: c.Expr[AnyRef]) =
206 logObject(c)(c.universe.reify(Level.DEBUG), message)
207
208 def debugMsgThrowable(c: LoggerContext)(message: c.Expr[Message], cause: c.Expr[Throwable]) =
209 logMsgThrowable(c)(c.universe.reify(Level.DEBUG), message, cause)
210
211 def debugCseqThrowable(c: LoggerContext)(message: c.Expr[CharSequence], cause: c.Expr[Throwable]) =
212 logCseqThrowable(c)(c.universe.reify(Level.DEBUG), message, cause)
213
214 def debugObjectThrowable(c: LoggerContext)(message: c.Expr[AnyRef], cause: c.Expr[Throwable]) =
215 logObjectThrowable(c)(c.universe.reify(Level.DEBUG), message, cause)
216
217
218 def traceMarkerMsg(c: LoggerContext)(marker: c.Expr[Marker], message: c.Expr[Message]) =
219 logMarkerMsg(c)(c.universe.reify(Level.TRACE), marker, message)
220
221 def traceMarkerCseq(c: LoggerContext)(marker: c.Expr[Marker], message: c.Expr[CharSequence]) =
222 logMarkerCseq(c)(c.universe.reify(Level.TRACE), marker, message)
223
224 def traceMarkerObject(c: LoggerContext)(marker: c.Expr[Marker], message: c.Expr[AnyRef]) =
225 logMarkerObject(c)(c.universe.reify(Level.TRACE), marker, message)
226
227 def traceMarkerMsgThrowable(c: LoggerContext)(marker: c.Expr[Marker], message: c.Expr[Message], cause: c.Expr[Throwable]) =
228 logMarkerMsgThrowable(c)(c.universe.reify(Level.TRACE), marker, message, cause)
229
230 def traceMarkerCseqThrowable(c: LoggerContext)(marker: c.Expr[Marker], message: c.Expr[CharSequence], cause: c.Expr[Throwable]) =
231 logMarkerCseqThrowable(c)(c.universe.reify(Level.TRACE), marker, message, cause)
232
233 def traceMarkerObjectThrowable(c: LoggerContext)(marker: c.Expr[Marker], message: c.Expr[AnyRef], cause: c.Expr[Throwable]) =
234 logMarkerObjectThrowable(c)(c.universe.reify(Level.TRACE), marker, message, cause)
235
236 def traceMsg(c: LoggerContext)(message: c.Expr[Message]) =
237 logMsg(c)(c.universe.reify(Level.TRACE), message)
238
239 def traceCseq(c: LoggerContext)(message: c.Expr[CharSequence]) =
240 logCseq(c)(c.universe.reify(Level.TRACE), message)
241
242 def traceObject(c: LoggerContext)(message: c.Expr[AnyRef]) =
243 logObject(c)(c.universe.reify(Level.TRACE), message)
244
245 def traceMsgThrowable(c: LoggerContext)(message: c.Expr[Message], cause: c.Expr[Throwable]) =
246 logMsgThrowable(c)(c.universe.reify(Level.TRACE), message, cause)
247
248 def traceCseqThrowable(c: LoggerContext)(message: c.Expr[CharSequence], cause: c.Expr[Throwable]) =
249 logCseqThrowable(c)(c.universe.reify(Level.TRACE), message, cause)
250
251 def traceObjectThrowable(c: LoggerContext)(message: c.Expr[AnyRef], cause: c.Expr[Throwable]) =
252 logObjectThrowable(c)(c.universe.reify(Level.TRACE), message, cause)
253
254
255 def logMarkerMsg(c: LoggerContext)(level: c.Expr[Level], marker: c.Expr[Marker], message: c.Expr[Message]) =
256 c.universe.reify(
257 if (c.prefix.splice.delegate.isEnabled(level.splice, marker.splice)) {
258 c.prefix.splice.logMessage(level.splice, marker.splice, message.splice, null)
259 }
260 )
261
262 def logMarkerCseq(c: LoggerContext)(level: c.Expr[Level], marker: c.Expr[Marker], message: c.Expr[CharSequence]) =
263 c.universe.reify(
264 if (c.prefix.splice.delegate.isEnabled(level.splice, marker.splice)) {
265 c.prefix.splice.logMessage(level.splice, marker.splice, message.splice, null)
266 }
267 )
268
269 def logMarkerObject(c: LoggerContext)(level: c.Expr[Level], marker: c.Expr[Marker], message: c.Expr[AnyRef]) =
270 c.universe.reify(
271 if (c.prefix.splice.delegate.isEnabled(level.splice, marker.splice)) {
272 c.prefix.splice.logMessage(level.splice, marker.splice, message.splice, null)
273 }
274 )
275
276 def logMarkerMsgThrowable(c: LoggerContext)(level: c.Expr[Level], marker: c.Expr[Marker], message: c.Expr[Message], cause: c.Expr[Throwable]) =
277 c.universe.reify(
278 if (c.prefix.splice.delegate.isEnabled(level.splice, marker.splice)) {
279 c.prefix.splice.logMessage(level.splice, marker.splice, message.splice, cause.splice)
280 }
281 )
282
283 def logMarkerCseqThrowable(c: LoggerContext)(level: c.Expr[Level], marker: c.Expr[Marker], message: c.Expr[CharSequence], cause: c.Expr[Throwable]) =
284 c.universe.reify(
285 if (c.prefix.splice.delegate.isEnabled(level.splice, marker.splice)) {
286 c.prefix.splice.logMessage(level.splice, marker.splice, message.splice, cause.splice)
287 }
288 )
289
290 def logMarkerObjectThrowable(c: LoggerContext)(level: c.Expr[Level], marker: c.Expr[Marker], message: c.Expr[AnyRef], cause: c.Expr[Throwable]) =
291 c.universe.reify(
292 if (c.prefix.splice.delegate.isEnabled(level.splice, marker.splice)) {
293 c.prefix.splice.logMessage(level.splice, marker.splice, message.splice, cause.splice)
294 }
295 )
296
297 def logMsg(c: LoggerContext)(level: c.Expr[Level], message: c.Expr[Message]) =
298 c.universe.reify(
299 if (c.prefix.splice.delegate.isEnabled(level.splice)) {
300 c.prefix.splice.logMessage(level.splice, null, message.splice, null)
301 }
302 )
303
304 def logCseq(c: LoggerContext)(level: c.Expr[Level], message: c.Expr[CharSequence]) =
305 c.universe.reify(
306 if (c.prefix.splice.delegate.isEnabled(level.splice)) {
307 c.prefix.splice.logMessage(level.splice, null, message.splice, null)
308 }
309 )
310
311 def logObject(c: LoggerContext)(level: c.Expr[Level], message: c.Expr[AnyRef]) =
312 c.universe.reify(
313 if (c.prefix.splice.delegate.isEnabled(level.splice)) {
314 c.prefix.splice.logMessage(level.splice, null, message.splice, null)
315 }
316 )
317
318 def logMsgThrowable(c: LoggerContext)(level: c.Expr[Level], message: c.Expr[Message], cause: c.Expr[Throwable]) =
319 c.universe.reify(
320 if (c.prefix.splice.delegate.isEnabled(level.splice)) {
321 c.prefix.splice.logMessage(level.splice, null, message.splice, cause.splice)
322 }
323 )
324
325 def logCseqThrowable(c: LoggerContext)(level: c.Expr[Level], message: c.Expr[CharSequence], cause: c.Expr[Throwable]) =
326 c.universe.reify(
327 if (c.prefix.splice.delegate.isEnabled(level.splice)) {
328 c.prefix.splice.logMessage(level.splice, null, message.splice, cause.splice)
329 }
330 )
331
332 def logObjectThrowable(c: LoggerContext)(level: c.Expr[Level], message: c.Expr[AnyRef], cause: c.Expr[Throwable]) =
333 c.universe.reify(
334 if (c.prefix.splice.delegate.isEnabled(level.splice)) {
335 c.prefix.splice.logMessage(level.splice, null, message.splice, cause.splice)
336 }
337 )
338
339
340 def traceEntry(c: LoggerContext)(): c.Expr[EntryMessage] =
341 c.universe.reify(
342 c.prefix.splice.delegate.traceEntry()
343 )
344
345 def traceEntryParams(c: LoggerContext)(params: c.Expr[AnyRef]*): c.Expr[EntryMessage] = {
346 import c.universe._
347 val isEnabled = Apply(
348 Select(Select(c.prefix.tree, newTermName("delegate")), newTermName("isEnabled")),
349 List(
350 reify(Level.TRACE).tree,
351 reify(AbstractLogger.ENTRY_MARKER).tree,
352 reify(null: AnyRef).tree,
353 reify(null).tree
354 )
355 )
356
357 val log = Apply(
358 Select(Select(c.prefix.tree, newTermName("delegate")), newTermName("traceEntry")),
359 reify(null: String).tree :: (params map (_.tree)).toList
360 )
361 c.Expr[EntryMessage](If(isEnabled, log, reify(null).tree))
362 }
363
364
365 def traceEntryMessage(c: LoggerContext)(message: c.Expr[Message]): c.Expr[EntryMessage] =
366 c.universe.reify(
367 if (c.prefix.splice.delegate.isEnabled(Level.TRACE, AbstractLogger.ENTRY_MARKER, null: AnyRef, null)) {
368 c.prefix.splice.delegate.traceEntry(message.splice) // TODO should not do ifEnabled check
369 } else {
370 null
371 }
372 )
373
374 def traceExit(c: LoggerContext)(): c.Expr[Unit] =
375 c.universe.reify(
376 c.prefix.splice.delegate.traceExit()
377 )
378
379 def traceExitResult[R: c.WeakTypeTag](c: LoggerContext)(result: c.Expr[R]): c.Expr[R] =
380 c.universe.reify(
381 c.prefix.splice.delegate.traceExit(result.splice)
382 )
383
384 def traceExitEntryMessage(c: LoggerContext)(entryMessage: c.Expr[EntryMessage]): c.Expr[Unit] =
385 c.universe.reify(
386 c.prefix.splice.delegate.traceExit(entryMessage.splice)
387 )
388
389 def traceExitEntryMessageResult[R: c.WeakTypeTag](c: LoggerContext)(entryMessage: c.Expr[EntryMessage], result: c.Expr[R]): c.Expr[R] =
390 c.universe.reify(
391 c.prefix.splice.delegate.traceExit(entryMessage.splice, result.splice)
392 )
393
394 def traceExitMessageResult[R: c.WeakTypeTag](c: LoggerContext)(message: c.Expr[Message], result: c.Expr[R]): c.Expr[R] =
395 c.universe.reify(
396 {
397 if (message.splice != null && c.prefix.splice.delegate.isEnabled(Level.TRACE, AbstractLogger.EXIT_MARKER, message.splice, null)) {
398 c.prefix.splice.delegate.traceExit(message.splice, result.splice) // TODO should not do ifEnabled check
399 }
400 result.splice
401 }
402 )
403
404 def throwing[T <: Throwable: c.WeakTypeTag](c: LoggerContext)(t: c.Expr[T]): c.Expr[T] =
405 c.universe.reify(
406 c.prefix.splice.delegate.throwing(t.splice)
407 )
408
409 def throwingLevel[T <: Throwable: c.WeakTypeTag](c: LoggerContext)(level: c.Expr[Level], t: c.Expr[T]): c.Expr[T] =
410 c.universe.reify(
411 c.prefix.splice.delegate.throwing(level.splice, t.splice)
412 )
413
414 def catching(c: LoggerContext)(t: c.Expr[Throwable]): c.Expr[Unit] =
415 c.universe.reify(
416 c.prefix.splice.delegate.catching(t.splice)
417 )
418
419 def catchingLevel(c: LoggerContext)(level: c.Expr[Level], t: c.Expr[Throwable]): c.Expr[Unit] =
420 c.universe.reify(
421 c.prefix.splice.delegate.catching(level.splice, t.splice)
422 )
423
424 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.scala
17
18 /**
19 * Mix in this trait into classes from which you want to log,
20 * give you a `logger` value with a [[Logger]] named according to the class.
21 */
22 trait Logging {
23
24 /**
25 * A [[Logger]] named according to the class.
26 */
27 protected val logger: Logger = Logger(getClass)
28
29 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.scala
17
18 import org.apache.logging.log4j.message.{DefaultFlowMessageFactory, Message, ParameterizedMessage, ParameterizedMessageFactory}
19 import org.apache.logging.log4j.spi.{AbstractLogger, ExtendedLogger}
20 import org.apache.logging.log4j.{Level, Marker, MarkerManager}
21 import org.junit.runner.RunWith
22 import org.mockito.Matchers.{any, anyString, eq => eqv}
23 import org.mockito.Mockito._
24 import org.scalatest.junit.JUnitRunner
25 import org.scalatest.mock.MockitoSugar
26 import org.scalatest.{FunSuite, Matchers}
27
28 case class Custom(i: Int)
29
30 trait Manager {
31 def fetchValue(): Int
32 }
33
34 @RunWith(classOf[JUnitRunner])
35 class LoggerTest extends FunSuite with Matchers with MockitoSugar {
36
37 val msg = new ParameterizedMessage("msg {}", 17)
38 val entryMsg = new DefaultFlowMessageFactory().newEntryMessage(msg)
39 val cseqMsg: CharSequence = new StringBuilder().append("cseq msg")
40 val objectMsg = Custom(17)
41 val cause = new RuntimeException("cause")
42 val marker = MarkerManager.getMarker("marker")
43 val result = "foo"
44
45 def fixture =
46 new {
47 val mockLogger = {
48 val mockLogger = mock[ExtendedLogger]
49 when(mockLogger.getMessageFactory).thenReturn(new ParameterizedMessageFactory)
50 mockLogger
51 }
52 val manager = {
53 val mockManager = mock[Manager]
54 when(mockManager.fetchValue()).thenReturn(4711)
55 mockManager
56 }
57 }
58
59 test("fatal enabled with String message") {
60 val f = fixture
61 when(f.mockLogger.isEnabled(Level.FATAL)).thenReturn(true)
62 val logger = Logger(f.mockLogger)
63 logger.fatal(s"string msg with value: ${f.manager.fetchValue()}")
64 verify(f.mockLogger).logMessage(anyString(), eqv(Level.FATAL), eqv(null), any[Message], eqv(null))
65 verify(f.manager).fetchValue()
66 }
67
68 test("fatal disabled with String message") {
69 val f = fixture
70 when(f.mockLogger.isEnabled(Level.FATAL)).thenReturn(false)
71 val logger = Logger(f.mockLogger)
72 logger.fatal(s"string msg with value: ${f.manager.fetchValue()}")
73 verify(f.mockLogger, never).logMessage(anyString(), any[Level], any[Marker], any[Message], any[Throwable])
74 verify(f.manager, never).fetchValue()
75 }
76
77 test("error enabled with String message") {
78 val f = fixture
79 when(f.mockLogger.isEnabled(Level.ERROR)).thenReturn(true)
80 val logger = Logger(f.mockLogger)
81 logger.error(s"string msg with value: ${f.manager.fetchValue()}")
82 verify(f.mockLogger).logMessage(anyString(), eqv(Level.ERROR), eqv(null), any[Message], eqv(null))
83 verify(f.manager).fetchValue()
84 }
85
86 test("error disabled with String message") {
87 val f = fixture
88 when(f.mockLogger.isEnabled(Level.ERROR)).thenReturn(false)
89 val logger = Logger(f.mockLogger)
90 logger.error(s"string msg with value: ${f.manager.fetchValue()}")
91 verify(f.mockLogger, never).logMessage(anyString(), any[Level], any[Marker], any[Message], any[Throwable])
92 verify(f.manager, never).fetchValue()
93 }
94
95 test("warn enabled with String message") {
96 val f = fixture
97 when(f.mockLogger.isEnabled(Level.WARN)).thenReturn(true)
98 val logger = Logger(f.mockLogger)
99 logger.warn(s"string msg with value: ${f.manager.fetchValue()}")
100 verify(f.mockLogger).logMessage(anyString(), eqv(Level.WARN), eqv(null), any[Message], eqv(null))
101 verify(f.manager).fetchValue()
102 }
103
104 test("warn disabled with String message") {
105 val f = fixture
106 when(f.mockLogger.isEnabled(Level.WARN)).thenReturn(false)
107 val logger = Logger(f.mockLogger)
108 logger.warn(s"string msg with value: ${f.manager.fetchValue()}")
109 verify(f.mockLogger, never).logMessage(anyString(), any[Level], any[Marker], any[Message], any[Throwable])
110 verify(f.manager, never).fetchValue()
111 }
112
113 test("info enabled with String message") {
114 val f = fixture
115 when(f.mockLogger.isEnabled(Level.INFO)).thenReturn(true)
116 val logger = Logger(f.mockLogger)
117 logger.info(s"string msg with value: ${f.manager.fetchValue()}")
118 verify(f.mockLogger).logMessage(anyString(), eqv(Level.INFO), eqv(null), any[Message], eqv(null))
119 verify(f.manager).fetchValue()
120 }
121
122 test("info disabled with String message") {
123 val f = fixture
124 when(f.mockLogger.isEnabled(Level.INFO)).thenReturn(false)
125 val logger = Logger(f.mockLogger)
126 logger.info(s"string msg with value: ${f.manager.fetchValue()}")
127 verify(f.mockLogger, never).logMessage(anyString(), any[Level], any[Marker], any[Message], any[Throwable])
128 verify(f.manager, never).fetchValue()
129 }
130
131 test("debug enabled with String message") {
132 val f = fixture
133 when(f.mockLogger.isEnabled(Level.DEBUG)).thenReturn(true)
134 val logger = Logger(f.mockLogger)
135 logger.debug(s"string msg with value: ${f.manager.fetchValue()}")
136 verify(f.mockLogger).logMessage(anyString(), eqv(Level.DEBUG), eqv(null), any[Message], eqv(null))
137 verify(f.manager).fetchValue()
138 }
139
140 test("debug disabled with String message") {
141 val f = fixture
142 when(f.mockLogger.isEnabled(Level.DEBUG)).thenReturn(false)
143 val logger = Logger(f.mockLogger)
144 logger.debug(s"string msg with value: ${f.manager.fetchValue()}")
145 verify(f.mockLogger, never).logMessage(anyString(), any[Level], any[Marker], any[Message], any[Throwable])
146 verify(f.manager, never).fetchValue()
147 }
148
149 test("trace enabled with String message") {
150 val f = fixture
151 when(f.mockLogger.isEnabled(Level.TRACE)).thenReturn(true)
152 val logger = Logger(f.mockLogger)
153 logger.trace(s"string msg with value: ${f.manager.fetchValue()}")
154 verify(f.mockLogger).logMessage(anyString(), eqv(Level.TRACE), eqv(null), any[Message], eqv(null))
155 verify(f.manager).fetchValue()
156 }
157
158 test("trace disabled with String message") {
159 val f = fixture
160 when(f.mockLogger.isEnabled(Level.TRACE)).thenReturn(false)
161 val logger = Logger(f.mockLogger)
162 logger.trace(s"string msg with value: ${f.manager.fetchValue()}")
163 verify(f.mockLogger, never).logMessage(anyString(), any[Level], any[Marker], any[Message], any[Throwable])
164 verify(f.manager, never).fetchValue()
165 }
166
167
168 test("log enabled with Message message and Marker") {
169 val f = fixture
170 when(f.mockLogger.isEnabled(Level.INFO, marker)).thenReturn(true)
171 val logger = Logger(f.mockLogger)
172 logger(Level.INFO, marker, msg)
173 verify(f.mockLogger).logMessage(anyString(), eqv(Level.INFO), eqv(marker), eqv(msg), eqv(null))
174 }
175
176 test("log disabled with Message message and Marker") {
177 val f = fixture
178 when(f.mockLogger.isEnabled(Level.INFO, marker)).thenReturn(false)
179 val logger = Logger(f.mockLogger)
180 logger(Level.INFO, marker, msg)
181 verify(f.mockLogger, never).logMessage(anyString(), any[Level], any[Marker], any[Message], any[Throwable])
182 }
183
184 test("log enabled with String message and Marker") {
185 val f = fixture
186 when(f.mockLogger.isEnabled(Level.INFO, marker)).thenReturn(true)
187 val logger = Logger(f.mockLogger)
188 logger(Level.INFO, marker, s"string msg with value: ${f.manager.fetchValue()}")
189 verify(f.mockLogger).logMessage(anyString(), eqv(Level.INFO), eqv(marker), any[Message], eqv(null))
190 verify(f.manager).fetchValue()
191 }
192
193 test("log disabled with String message and Marker") {
194 val f = fixture
195 when(f.mockLogger.isEnabled(Level.INFO, marker)).thenReturn(false)
196 val logger = Logger(f.mockLogger)
197 logger(Level.INFO, marker, s"string msg with value: ${f.manager.fetchValue()}")
198 verify(f.mockLogger, never).logMessage(anyString(), any[Level], any[Marker], any[Message], any[Throwable])
199 verify(f.manager, never).fetchValue()
200 }
201
202 test("log enabled with CharSequence message and Marker") {
203 val f = fixture
204 when(f.mockLogger.isEnabled(Level.INFO, marker)).thenReturn(true)
205 val logger = Logger(f.mockLogger)
206 logger(Level.INFO, marker, cseqMsg)
207 verify(f.mockLogger).logMessage(anyString(), eqv(Level.INFO), eqv(marker), any[Message], eqv(null))
208 }
209
210 test("log disabled with CharSequence message and Marker") {
211 val f = fixture
212 when(f.mockLogger.isEnabled(Level.INFO, marker)).thenReturn(false)
213 val logger = Logger(f.mockLogger)
214 logger(Level.INFO, marker, cseqMsg)
215 verify(f.mockLogger, never).logMessage(anyString(), any[Level], any[Marker], any[Message], any[Throwable])
216 }
217
218 test("log enabled with Object message and Marker") {
219 val f = fixture
220 when(f.mockLogger.isEnabled(Level.INFO, marker)).thenReturn(true)
221 val logger = Logger(f.mockLogger)
222 logger(Level.INFO, marker, objectMsg)
223 verify(f.mockLogger).logMessage(anyString(), eqv(Level.INFO), eqv(marker), any[Message], eqv(null))
224 }
225
226 test("log disabled with Object message and Marker") {
227 val f = fixture
228 when(f.mockLogger.isEnabled(Level.INFO, marker)).thenReturn(false)
229 val logger = Logger(f.mockLogger)
230 logger(Level.INFO, marker, objectMsg)
231 verify(f.mockLogger, never).logMessage(anyString(), any[Level], any[Marker], any[Message], any[Throwable])
232 }
233
234 test("log enabled with Message message and cause and Marker") {
235 val f = fixture
236 when(f.mockLogger.isEnabled(Level.INFO, marker)).thenReturn(true)
237 val logger = Logger(f.mockLogger)
238 logger(Level.INFO, marker, msg, cause)
239 verify(f.mockLogger).logMessage(anyString(), eqv(Level.INFO), eqv(marker), eqv(msg), eqv(cause))
240 }
241
242 test("log disabled with Message message and cause and Marker") {
243 val f = fixture
244 when(f.mockLogger.isEnabled(Level.INFO, marker)).thenReturn(false)
245 val logger = Logger(f.mockLogger)
246 logger(Level.INFO, marker, msg, cause)
247 verify(f.mockLogger, never).logMessage(anyString(), any[Level], any[Marker], any[Message], any[Throwable])
248 }
249
250 test("log enabled with String message and cause and Marker") {
251 val f = fixture
252 when(f.mockLogger.isEnabled(Level.INFO, marker)).thenReturn(true)
253 val logger = Logger(f.mockLogger)
254 logger(Level.INFO, marker, s"string msg with value: ${f.manager.fetchValue()}", cause)
255 verify(f.mockLogger).logMessage(anyString(), eqv(Level.INFO), eqv(marker), any[Message], eqv(cause))
256 verify(f.manager).fetchValue()
257 }
258
259 test("log disabled with String message and cause and Marker") {
260 val f = fixture
261 when(f.mockLogger.isEnabled(Level.INFO, marker)).thenReturn(false)
262 val logger = Logger(f.mockLogger)
263 logger(Level.INFO, marker, s"string msg with value: ${f.manager.fetchValue()}", cause)
264 verify(f.mockLogger, never).logMessage(anyString(), any[Level], any[Marker], any[Message], any[Throwable])
265 verify(f.manager, never).fetchValue()
266 }
267
268 test("log enabled with CharSequence message and cause and Marker") {
269 val f = fixture
270 when(f.mockLogger.isEnabled(Level.INFO, marker)).thenReturn(true)
271 val logger = Logger(f.mockLogger)
272 logger(Level.INFO, marker, cseqMsg, cause)
273 verify(f.mockLogger).logMessage(anyString(), eqv(Level.INFO), eqv(marker), any[Message], eqv(cause))
274 }
275
276 test("log disabled with CharSequence message and cause and Marker") {
277 val f = fixture
278 when(f.mockLogger.isEnabled(Level.INFO, marker)).thenReturn(false)
279 val logger = Logger(f.mockLogger)
280 logger(Level.INFO, marker, cseqMsg, cause)
281 verify(f.mockLogger, never).logMessage(anyString(), any[Level], any[Marker], any[Message], any[Throwable])
282 }
283
284 test("log enabled with Object message and cause and Marker") {
285 val f = fixture
286 when(f.mockLogger.isEnabled(Level.INFO, marker)).thenReturn(true)
287 val logger = Logger(f.mockLogger)
288 logger(Level.INFO, marker, objectMsg, cause)
289 verify(f.mockLogger).logMessage(anyString(), eqv(Level.INFO), eqv(marker), any[Message], eqv(cause))
290 }
291
292 test("log disabled with Object message and cause and Marker") {
293 val f = fixture
294 when(f.mockLogger.isEnabled(Level.INFO, marker)).thenReturn(false)
295 val logger = Logger(f.mockLogger)
296 logger(Level.INFO, marker, objectMsg, cause)
297 verify(f.mockLogger, never).logMessage(anyString(), any[Level], any[Marker], any[Message], any[Throwable])
298 }
299
300 test("log enabled with Message message") {
301 val f = fixture
302 when(f.mockLogger.isEnabled(Level.INFO)).thenReturn(true)
303 val logger = Logger(f.mockLogger)
304 logger(Level.INFO, msg)
305 verify(f.mockLogger).logMessage(anyString(), eqv(Level.INFO), eqv(null), eqv(msg), eqv(null))
306 }
307
308 test("log disabled with Message message") {
309 val f = fixture
310 when(f.mockLogger.isEnabled(Level.INFO)).thenReturn(false)
311 val logger = Logger(f.mockLogger)
312 logger(Level.INFO, msg)
313 verify(f.mockLogger, never).logMessage(anyString(), any[Level], any[Marker], any[Message], any[Throwable])
314 }
315
316 test("log enabled with String message") {
317 val f = fixture
318 when(f.mockLogger.isEnabled(Level.INFO)).thenReturn(true)
319 val logger = Logger(f.mockLogger)
320 logger(Level.INFO, s"string msg with value: ${f.manager.fetchValue()}")
321 verify(f.mockLogger).logMessage(anyString(), eqv(Level.INFO), eqv(null), any[Message], eqv(null))
322 verify(f.manager).fetchValue()
323 }
324
325 test("log disabled with String message") {
326 val f = fixture
327 when(f.mockLogger.isEnabled(Level.INFO)).thenReturn(false)
328 val logger = Logger(f.mockLogger)
329 logger(Level.INFO, s"string msg with value: ${f.manager.fetchValue()}")
330 verify(f.mockLogger, never).logMessage(anyString(), any[Level], any[Marker], any[Message], any[Throwable])
331 verify(f.manager, never).fetchValue()
332 }
333
334 test("log enabled with CharSequence message") {
335 val f = fixture
336 when(f.mockLogger.isEnabled(Level.INFO)).thenReturn(true)
337 val logger = Logger(f.mockLogger)
338 logger(Level.INFO, cseqMsg)
339 verify(f.mockLogger).logMessage(anyString(), eqv(Level.INFO), eqv(null), any[Message], eqv(null))
340 }
341
342 test("log disabled with CharSequence message") {
343 val f = fixture
344 when(f.mockLogger.isEnabled(Level.INFO)).thenReturn(false)
345 val logger = Logger(f.mockLogger)
346 logger(Level.INFO, cseqMsg)
347 verify(f.mockLogger, never).logMessage(anyString(), any[Level], any[Marker], any[Message], any[Throwable])
348 }
349
350 test("log enabled with Object message") {
351 val f = fixture
352 when(f.mockLogger.isEnabled(Level.INFO)).thenReturn(true)
353 val logger = Logger(f.mockLogger)
354 logger(Level.INFO, objectMsg)
355 verify(f.mockLogger).logMessage(anyString(), eqv(Level.INFO), eqv(null), any[Message], eqv(null))
356 }
357
358 test("log disabled with Object message") {
359 val f = fixture
360 when(f.mockLogger.isEnabled(Level.INFO)).thenReturn(false)
361 val logger = Logger(f.mockLogger)
362 logger(Level.INFO, objectMsg)
363 verify(f.mockLogger, never).logMessage(anyString(), any[Level], any[Marker], any[Message], any[Throwable])
364 }
365
366 test("log enabled with Message message and cause") {
367 val f = fixture
368 when(f.mockLogger.isEnabled(Level.INFO)).thenReturn(true)
369 val logger = Logger(f.mockLogger)
370 logger(Level.INFO, msg, cause)
371 verify(f.mockLogger).logMessage(anyString(), eqv(Level.INFO), eqv(null), eqv(msg), eqv(cause))
372 }
373
374 test("log disabled with Message message and cause") {
375 val f = fixture
376 when(f.mockLogger.isEnabled(Level.INFO)).thenReturn(false)
377 val logger = Logger(f.mockLogger)
378 logger(Level.INFO, msg, cause)
379 verify(f.mockLogger, never).logMessage(anyString(), any[Level], any[Marker], any[Message], any[Throwable])
380 }
381
382 test("log enabled with String message and cause") {
383 val f = fixture
384 when(f.mockLogger.isEnabled(Level.INFO)).thenReturn(true)
385 val logger = Logger(f.mockLogger)
386 logger(Level.INFO, s"string msg with value: ${f.manager.fetchValue()}", cause)
387 verify(f.mockLogger).logMessage(anyString(), eqv(Level.INFO), eqv(null), any[Message], eqv(cause))
388 verify(f.manager).fetchValue()
389 }
390
391 test("log disabled with String message and cause") {
392 val f = fixture
393 when(f.mockLogger.isEnabled(Level.INFO)).thenReturn(false)
394 val logger = Logger(f.mockLogger)
395 logger(Level.INFO, s"string msg with value: ${f.manager.fetchValue()}", cause)
396 verify(f.mockLogger, never).logMessage(anyString(), any[Level], any[Marker], any[Message], any[Throwable])
397 verify(f.manager, never).fetchValue()
398 }
399
400 test("log enabled with CharSequence message and cause") {
401 val f = fixture
402 when(f.mockLogger.isEnabled(Level.INFO)).thenReturn(true)
403 val logger = Logger(f.mockLogger)
404 logger(Level.INFO, cseqMsg, cause)
405 verify(f.mockLogger).logMessage(anyString(), eqv(Level.INFO), eqv(null), any[Message], eqv(cause))
406 }
407
408 test("log disabled with CharSequence message and cause") {
409 val f = fixture
410 when(f.mockLogger.isEnabled(Level.INFO)).thenReturn(false)
411 val logger = Logger(f.mockLogger)
412 logger(Level.INFO, cseqMsg, cause)
413 verify(f.mockLogger, never).logMessage(anyString(), any[Level], any[Marker], any[Message], any[Throwable])
414 }
415
416 test("log enabled with Object message and cause") {
417 val f = fixture
418 when(f.mockLogger.isEnabled(Level.INFO)).thenReturn(true)
419 val logger = Logger(f.mockLogger)
420 logger(Level.INFO, objectMsg, cause)
421 verify(f.mockLogger).logMessage(anyString(), eqv(Level.INFO), eqv(null), any[Message], eqv(cause))
422 }
423
424 test("log disabled with Object message and cause") {
425 val f = fixture
426 when(f.mockLogger.isEnabled(Level.INFO)).thenReturn(false)
427 val logger = Logger(f.mockLogger)
428 logger(Level.INFO, objectMsg, cause)
429 verify(f.mockLogger, never).logMessage(anyString(), any[Level], any[Marker], any[Message], any[Throwable])
430 }
431
432
433 test("traceEntry") {
434 val f = fixture
435 when(f.mockLogger.isEnabled(Level.TRACE, AbstractLogger.ENTRY_MARKER, null.asInstanceOf[AnyRef], null)).thenReturn(true)
436 val logger = Logger(f.mockLogger)
437 logger.traceEntry()
438 verify(f.mockLogger).traceEntry()
439 }
440
441 test("traceEntry enabled with params") {
442 val f = fixture
443 when(f.mockLogger.isEnabled(Level.TRACE, AbstractLogger.ENTRY_MARKER, null.asInstanceOf[AnyRef], null)).thenReturn(true)
444 val logger = Logger(f.mockLogger)
445 logger.traceEntry("foo", "bar")
446 verify(f.mockLogger).traceEntry(null: String, "foo", "bar")
447 }
448
449 test("traceEntry disabled with params") {
450 val f = fixture
451 when(f.mockLogger.isEnabled(Level.TRACE, AbstractLogger.ENTRY_MARKER, null.asInstanceOf[AnyRef], null)).thenReturn(false)
452 val logger = Logger(f.mockLogger)
453 logger.traceEntry("foo", "bar")
454 verify(f.mockLogger, never).traceEntry(anyString(), anyString(), anyString())
455 }
456
457 test("traceEntry enabled with message") {
458 val f = fixture
459 when(f.mockLogger.isEnabled(Level.TRACE, AbstractLogger.ENTRY_MARKER, null.asInstanceOf[AnyRef], null)).thenReturn(true)
460 val logger = Logger(f.mockLogger)
461 logger.traceEntry(msg)
462 verify(f.mockLogger).traceEntry(eqv(msg))
463 }
464
465 test("traceEntry disabled with message") {
466 val f = fixture
467 when(f.mockLogger.isEnabled(Level.TRACE, AbstractLogger.ENTRY_MARKER, null.asInstanceOf[AnyRef], null)).thenReturn(false)
468 val logger = Logger(f.mockLogger)
469 logger.traceEntry(msg)
470 verify(f.mockLogger, never).traceEntry(any[Message])
471 }
472
473 test("traceExit") {
474 val f = fixture
475 when(f.mockLogger.isEnabled(Level.TRACE, AbstractLogger.EXIT_MARKER, msg, null)).thenReturn(true)
476 val logger = Logger(f.mockLogger)
477 logger.traceExit()
478 verify(f.mockLogger).traceExit()
479 }
480
481 test("traceExit with result") {
482 val f = fixture
483 when(f.mockLogger.isEnabled(Level.TRACE, AbstractLogger.EXIT_MARKER, msg, null)).thenReturn(true)
484 val logger = Logger(f.mockLogger)
485 logger.traceExit(result)
486 verify(f.mockLogger).traceExit(result)
487 }
488
489 test("traceExit with entrymessage") {
490 val f = fixture
491 when(f.mockLogger.isEnabled(Level.TRACE, AbstractLogger.EXIT_MARKER, msg, null)).thenReturn(true)
492 val logger = Logger(f.mockLogger)
493 logger.traceExit(entryMsg)
494 verify(f.mockLogger).traceExit(entryMsg)
495 }
496
497 test("traceExit with entrymessage and result") {
498 val f = fixture
499 when(f.mockLogger.isEnabled(Level.TRACE, AbstractLogger.EXIT_MARKER, msg, null)).thenReturn(true)
500 val logger = Logger(f.mockLogger)
501 logger.traceExit(entryMsg, result)
502 verify(f.mockLogger).traceExit(entryMsg, result)
503 }
504
505 test("traceExit enabled with message") {
506 val f = fixture
507 when(f.mockLogger.isEnabled(Level.TRACE, AbstractLogger.EXIT_MARKER, msg, null)).thenReturn(true)
508 val logger = Logger(f.mockLogger)
509 logger.traceExit(msg, result)
510 verify(f.mockLogger).traceExit(eqv(msg), eqv(result))
511 }
512
513 test("traceExit disabled with message") {
514 val f = fixture
515 when(f.mockLogger.isEnabled(Level.TRACE, AbstractLogger.EXIT_MARKER, msg, null)).thenReturn(false)
516 val logger = Logger(f.mockLogger)
517 logger.traceExit(msg, result)
518 verify(f.mockLogger, never).traceExit(any[Message], any[AnyRef])
519 }
520
521 test("throwing") {
522 val f = fixture
523 val logger = Logger(f.mockLogger)
524 logger.throwing(cause)
525 verify(f.mockLogger).throwing(eqv(cause))
526 }
527
528 test("throwing with level") {
529 val f = fixture
530 val logger = Logger(f.mockLogger)
531 logger.throwing(Level.INFO, cause)
532 verify(f.mockLogger).throwing(eqv(Level.INFO), eqv(cause))
533 }
534
535 test("catching") {
536 val f = fixture
537 val logger = Logger(f.mockLogger)
538 logger.catching(cause)
539 verify(f.mockLogger).catching(eqv(cause))
540 }
541
542 test("catching with level") {
543 val f = fixture
544 val logger = Logger(f.mockLogger)
545 logger.catching(Level.INFO, cause)
546 verify(f.mockLogger).catching(eqv(Level.INFO), eqv(cause))
547 }
548
549 }
0 <?xml version="1.0" encoding="UTF-8"?>
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 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
18 <modelVersion>4.0.0</modelVersion>
19 <parent>
20 <groupId>org.apache.logging.log4j</groupId>
21 <artifactId>log4j</artifactId>
22 <version>2.7</version>
23 <relativePath>../</relativePath>
24 </parent>
25 <artifactId>log4j-api-scala_2.11</artifactId>
26 <packaging>jar</packaging>
27 <name>Apache Log4j Scala 2.11 wrapper for Log4j API</name>
28 <description>Scala wrapper for Log4j API</description>
29 <properties>
30 <log4jParentDir>${basedir}/..</log4jParentDir>
31 <projectDir>/scala_2.11</projectDir>
32 <scala.version>2.11.8</scala.version>
33 <scala.maven.plugin.version>3.2.2</scala.maven.plugin.version>
34 </properties>
35 <dependencies>
36 <dependency>
37 <groupId>org.apache.logging.log4j</groupId>
38 <artifactId>log4j-api</artifactId>
39 </dependency>
40 <dependency>
41 <groupId>org.scala-lang</groupId>
42 <artifactId>scala-library</artifactId>
43 <version>${scala.version}</version>
44 </dependency>
45 <dependency>
46 <groupId>org.scala-lang</groupId>
47 <artifactId>scala-reflect</artifactId>
48 <version>${scala.version}</version>
49 </dependency>
50 <dependency>
51 <groupId>org.apache.logging.log4j</groupId>
52 <artifactId>log4j-api</artifactId>
53 <type>test-jar</type>
54 <scope>test</scope>
55 </dependency>
56 <dependency>
57 <groupId>junit</groupId>
58 <artifactId>junit</artifactId>
59 <scope>test</scope>
60 </dependency>
61 <dependency>
62 <groupId>org.scalatest</groupId>
63 <artifactId>scalatest_2.11</artifactId>
64 <version>2.2.6</version>
65 <scope>test</scope>
66 </dependency>
67 <dependency>
68 <groupId>org.mockito</groupId>
69 <artifactId>mockito-core</artifactId>
70 <version>1.10.19</version>
71 <scope>test</scope>
72 </dependency>
73 </dependencies>
74 <build>
75 <sourceDirectory>src/main/scala</sourceDirectory>
76 <testSourceDirectory>src/test/scala</testSourceDirectory>
77 <plugins>
78 <plugin>
79 <groupId>net.alchim31.maven</groupId>
80 <artifactId>scala-maven-plugin</artifactId>
81 <version>${scala.maven.plugin.version}</version>
82 <executions>
83 <execution>
84 <goals>
85 <goal>compile</goal>
86 <goal>testCompile</goal>
87 </goals>
88 </execution>
89 </executions>
90 </plugin>
91 <plugin>
92 <groupId>org.apache.maven.plugins</groupId>
93 <artifactId>maven-surefire-plugin</artifactId>
94 </plugin>
95 <!-- Include the standard NOTICE and LICENSE -->
96 <plugin>
97 <groupId>org.apache.maven.plugins</groupId>
98 <artifactId>maven-remote-resources-plugin</artifactId>
99 <executions>
100 <execution>
101 <goals>
102 <goal>process</goal>
103 </goals>
104 <configuration>
105 <skip>false</skip>
106 </configuration>
107 </execution>
108 </executions>
109 </plugin>
110 <plugin>
111 <groupId>org.apache.felix</groupId>
112 <artifactId>maven-bundle-plugin</artifactId>
113 </plugin>
114 </plugins>
115 </build>
116 <reporting>
117 <plugins>
118 <plugin>
119 <groupId>org.apache.maven.plugins</groupId>
120 <artifactId>maven-changes-plugin</artifactId>
121 <version>${changes.plugin.version}</version>
122 <reportSets>
123 <reportSet>
124 <reports>
125 <report>changes-report</report>
126 </reports>
127 </reportSet>
128 </reportSets>
129 <configuration>
130 <issueLinkTemplate>%URL%/show_bug.cgi?id=%ISSUE%</issueLinkTemplate>
131 <useJql>true</useJql>
132 </configuration>
133 </plugin>
134 <plugin>
135 <groupId>org.apache.maven.plugins</groupId>
136 <artifactId>maven-pmd-plugin</artifactId>
137 <version>${pmd.plugin.version}</version>
138 <configuration>
139 <targetJdk>${maven.compile.target}</targetJdk>
140 </configuration>
141 </plugin>
142 <plugin>
143 <groupId>net.alchim31.maven</groupId>
144 <artifactId>scala-maven-plugin</artifactId>
145 <version>${scala.maven.plugin.version}</version>
146 </plugin>
147 </plugins>
148 </reporting>
149 </project>
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.scala
17
18 import org.apache.logging.log4j.message.{EntryMessage, Message, MessageFactory2}
19 import org.apache.logging.log4j.spi.ExtendedLogger
20 import org.apache.logging.log4j.{Level, LogManager, Marker}
21
22 import scala.language.experimental.macros
23
24 /**
25 * Factory for [[Logger]]s.
26 *
27 * The [[Logging]] trait provides a simple way to get a properly named logger into a class.
28 */
29 object Logger {
30
31 final val FQCN = getClass.getName
32
33 /**
34 * Create a properly named [[Logger]] for a given class.
35 *
36 * @param clazz the class
37 */
38 def apply(clazz: Class[_]): Logger = Logger(LogManager.getContext(clazz.getClassLoader, false).getLogger(clazz.getName))
39
40 /**
41 * Create a [[Logger]] wrapping the given Log4j logger.
42 *
43 * @param delegate the Log4j logger to wrap
44 */
45 def apply(delegate: ExtendedLogger): Logger = new Logger(delegate)
46
47 }
48
49 /**
50 * Scala wrapper for the Log4j `Logger` interface.
51 *
52 * Frequently the purpose of logging is to provide information about what is happening in the system,
53 * which requires including information about the objects being manipulated. In Scala, you can use
54 * [[http://docs.scala-lang.org/overviews/core/string-interpolation.html string interpolation]]
55 * to achieve this:
56 *
57 * {{{
58 * logger.debug(s"Logging in user ${user.getName} with birthday ${user.calcBirthday}")
59 * }}}
60 *
61 * Since this wrapper is implemented with macros, the String construction and method invocations
62 * will only occur when debug logging is enabled.
63 */
64 class Logger private(val delegate: ExtendedLogger) extends AnyVal {
65
66 def fatal(marker: Marker, message: Message): Unit =
67 macro LoggerMacro.fatalMarkerMsg
68
69 def fatal(marker: Marker, message: CharSequence): Unit =
70 macro LoggerMacro.fatalMarkerCseq
71
72 def fatal(marker: Marker, message: AnyRef): Unit =
73 macro LoggerMacro.fatalMarkerObject
74
75 def fatal(marker: Marker, message: Message, cause: Throwable): Unit =
76 macro LoggerMacro.fatalMarkerMsgThrowable
77
78 def fatal(marker: Marker, message: CharSequence, cause: Throwable): Unit =
79 macro LoggerMacro.fatalMarkerCseqThrowable
80
81 def fatal(marker: Marker, message: AnyRef, cause: Throwable): Unit =
82 macro LoggerMacro.fatalMarkerObjectThrowable
83
84 def fatal(message: Message): Unit =
85 macro LoggerMacro.fatalMsg
86
87 def fatal(message: CharSequence): Unit =
88 macro LoggerMacro.fatalCseq
89
90 def fatal(message: AnyRef): Unit =
91 macro LoggerMacro.fatalObject
92
93 def fatal(message: Message, cause: Throwable): Unit =
94 macro LoggerMacro.fatalMsgThrowable
95
96 def fatal(message: CharSequence, cause: Throwable): Unit =
97 macro LoggerMacro.fatalCseqThrowable
98
99 def fatal(message: AnyRef, cause: Throwable): Unit =
100 macro LoggerMacro.fatalObjectThrowable
101
102
103 def error(marker: Marker, message: Message): Unit =
104 macro LoggerMacro.errorMarkerMsg
105
106 def error(marker: Marker, message: CharSequence): Unit =
107 macro LoggerMacro.errorMarkerCseq
108
109 def error(marker: Marker, message: AnyRef): Unit =
110 macro LoggerMacro.errorMarkerObject
111
112 def error(marker: Marker, message: Message, cause: Throwable): Unit =
113 macro LoggerMacro.errorMarkerMsgThrowable
114
115 def error(marker: Marker, message: CharSequence, cause: Throwable): Unit =
116 macro LoggerMacro.errorMarkerCseqThrowable
117
118 def error(marker: Marker, message: AnyRef, cause: Throwable): Unit =
119 macro LoggerMacro.errorMarkerObjectThrowable
120
121 def error(message: Message): Unit =
122 macro LoggerMacro.errorMsg
123
124 def error(message: CharSequence): Unit =
125 macro LoggerMacro.errorCseq
126
127 def error(message: AnyRef): Unit =
128 macro LoggerMacro.errorObject
129
130 def error(message: Message, cause: Throwable): Unit =
131 macro LoggerMacro.errorMsgThrowable
132
133 def error(message: CharSequence, cause: Throwable): Unit =
134 macro LoggerMacro.errorCseqThrowable
135
136 def error(message: AnyRef, cause: Throwable): Unit =
137 macro LoggerMacro.errorObjectThrowable
138
139
140 def warn(marker: Marker, message: Message): Unit =
141 macro LoggerMacro.warnMarkerMsg
142
143 def warn(marker: Marker, message: CharSequence): Unit =
144 macro LoggerMacro.warnMarkerCseq
145
146 def warn(marker: Marker, message: AnyRef): Unit =
147 macro LoggerMacro.warnMarkerObject
148
149 def warn(marker: Marker, message: Message, cause: Throwable): Unit =
150 macro LoggerMacro.warnMarkerMsgThrowable
151
152 def warn(marker: Marker, message: CharSequence, cause: Throwable): Unit =
153 macro LoggerMacro.warnMarkerCseqThrowable
154
155 def warn(marker: Marker, message: AnyRef, cause: Throwable): Unit =
156 macro LoggerMacro.warnMarkerObjectThrowable
157
158 def warn(message: Message): Unit =
159 macro LoggerMacro.warnMsg
160
161 def warn(message: CharSequence): Unit =
162 macro LoggerMacro.warnCseq
163
164 def warn(message: AnyRef): Unit =
165 macro LoggerMacro.warnObject
166
167 def warn(message: Message, cause: Throwable): Unit =
168 macro LoggerMacro.warnMsgThrowable
169
170 def warn(message: CharSequence, cause: Throwable): Unit =
171 macro LoggerMacro.warnCseqThrowable
172
173 def warn(message: AnyRef, cause: Throwable): Unit =
174 macro LoggerMacro.warnObjectThrowable
175
176
177 def info(marker: Marker, message: Message): Unit =
178 macro LoggerMacro.infoMarkerMsg
179
180 def info(marker: Marker, message: CharSequence): Unit =
181 macro LoggerMacro.infoMarkerCseq
182
183 def info(marker: Marker, message: AnyRef): Unit =
184 macro LoggerMacro.infoMarkerObject
185
186 def info(marker: Marker, message: Message, cause: Throwable): Unit =
187 macro LoggerMacro.infoMarkerMsgThrowable
188
189 def info(marker: Marker, message: CharSequence, cause: Throwable): Unit =
190 macro LoggerMacro.infoMarkerCseqThrowable
191
192 def info(marker: Marker, message: AnyRef, cause: Throwable): Unit =
193 macro LoggerMacro.infoMarkerObjectThrowable
194
195 def info(message: Message): Unit =
196 macro LoggerMacro.infoMsg
197
198 def info(message: CharSequence): Unit =
199 macro LoggerMacro.infoCseq
200
201 def info(message: AnyRef): Unit =
202 macro LoggerMacro.infoObject
203
204 def info(message: Message, cause: Throwable): Unit =
205 macro LoggerMacro.infoMsgThrowable
206
207 def info(message: CharSequence, cause: Throwable): Unit =
208 macro LoggerMacro.infoCseqThrowable
209
210 def info(message: AnyRef, cause: Throwable): Unit =
211 macro LoggerMacro.infoObjectThrowable
212
213
214 def debug(marker: Marker, message: Message): Unit =
215 macro LoggerMacro.debugMarkerMsg
216
217 def debug(marker: Marker, message: CharSequence): Unit =
218 macro LoggerMacro.debugMarkerCseq
219
220 def debug(marker: Marker, message: AnyRef): Unit =
221 macro LoggerMacro.debugMarkerObject
222
223 def debug(marker: Marker, message: Message, cause: Throwable): Unit =
224 macro LoggerMacro.debugMarkerMsgThrowable
225
226 def debug(marker: Marker, message: CharSequence, cause: Throwable): Unit =
227 macro LoggerMacro.debugMarkerCseqThrowable
228
229 def debug(marker: Marker, message: AnyRef, cause: Throwable): Unit =
230 macro LoggerMacro.debugMarkerObjectThrowable
231
232 def debug(message: Message): Unit =
233 macro LoggerMacro.debugMsg
234
235 def debug(message: CharSequence): Unit =
236 macro LoggerMacro.debugCseq
237
238 def debug(message: AnyRef): Unit =
239 macro LoggerMacro.debugObject
240
241 def debug(message: Message, cause: Throwable): Unit =
242 macro LoggerMacro.debugMsgThrowable
243
244 def debug(message: CharSequence, cause: Throwable): Unit =
245 macro LoggerMacro.debugCseqThrowable
246
247 def debug(message: AnyRef, cause: Throwable): Unit =
248 macro LoggerMacro.debugObjectThrowable
249
250
251 def trace(marker: Marker, message: Message): Unit =
252 macro LoggerMacro.traceMarkerMsg
253
254 def trace(marker: Marker, message: CharSequence): Unit =
255 macro LoggerMacro.traceMarkerCseq
256
257 def trace(marker: Marker, message: AnyRef): Unit =
258 macro LoggerMacro.traceMarkerObject
259
260 def trace(marker: Marker, message: Message, cause: Throwable): Unit =
261 macro LoggerMacro.traceMarkerMsgThrowable
262
263 def trace(marker: Marker, message: CharSequence, cause: Throwable): Unit =
264 macro LoggerMacro.traceMarkerCseqThrowable
265
266 def trace(marker: Marker, message: AnyRef, cause: Throwable): Unit =
267 macro LoggerMacro.traceMarkerObjectThrowable
268
269 def trace(message: Message): Unit =
270 macro LoggerMacro.traceMsg
271
272 def trace(message: CharSequence): Unit =
273 macro LoggerMacro.traceCseq
274
275 def trace(message: AnyRef): Unit =
276 macro LoggerMacro.traceObject
277
278 def trace(message: Message, cause: Throwable): Unit =
279 macro LoggerMacro.traceMsgThrowable
280
281 def trace(message: CharSequence, cause: Throwable): Unit =
282 macro LoggerMacro.traceCseqThrowable
283
284 def trace(message: AnyRef, cause: Throwable): Unit =
285 macro LoggerMacro.traceObjectThrowable
286
287
288 /**
289 * Logs a `Message` with the specific `Marker` at the given `Level`.
290 *
291 * @param level the logging level
292 * @param marker the marker data specific to this log statement
293 * @param message the message to be logged
294 */
295 def apply(level: Level, marker: Marker, message: Message): Unit =
296 macro LoggerMacro.logMarkerMsg
297
298 /**
299 * Logs a string with the specific `Marker` at the given `Level`.
300 *
301 * @param level the logging level
302 * @param marker the marker data specific to this log statement
303 * @param message the message to be logged
304 */
305 def apply(level: Level, marker: Marker, message: CharSequence): Unit =
306 macro LoggerMacro.logMarkerCseq
307
308 /**
309 * Logs an object with the specific `Marker` at the given `Level`.
310 *
311 * @param level the logging level
312 * @param marker the marker data specific to this log statement
313 * @param message the message to be logged
314 */
315 def apply(level: Level, marker: Marker, message: AnyRef): Unit =
316 macro LoggerMacro.logMarkerObject
317
318 /**
319 * Logs a `Message` with the specific `Marker` at the given `Level` including the stack trace
320 * of the given `Throwable`.
321 *
322 * @param level the logging level
323 * @param marker the marker data specific to this log statement
324 * @param message the message to be logged
325 * @param cause the cause
326 */
327 def apply(level: Level, marker: Marker, message: Message, cause: Throwable): Unit =
328 macro LoggerMacro.logMarkerMsgThrowable
329
330 /**
331 * Logs a string with the specific `Marker` at the given `Level` including the stack trace
332 * of the given `Throwable`.
333 *
334 * @param level the logging level
335 * @param marker the marker data specific to this log statement
336 * @param message the message to be logged
337 * @param cause the cause
338 */
339 def apply(level: Level, marker: Marker, message: CharSequence, cause: Throwable): Unit =
340 macro LoggerMacro.logMarkerCseqThrowable
341
342 /**
343 * Logs an object with the specific `Marker` at the given `Level` including the stack trace
344 * of the given `Throwable`.
345 *
346 * @param level the logging level
347 * @param marker the marker data specific to this log statement
348 * @param message the message to be logged
349 * @param cause the cause
350 */
351 def apply(level: Level, marker: Marker, message: AnyRef, cause: Throwable): Unit =
352 macro LoggerMacro.logMarkerObjectThrowable
353
354 /**
355 * Logs a `Message` at the given `Level`.
356 *
357 * @param level the logging level
358 * @param message the message to be logged
359 */
360 def apply(level: Level, message: Message): Unit =
361 macro LoggerMacro.logMsg
362
363 /**
364 * Logs a string at the given `Level`.
365 *
366 * @param level the logging level
367 * @param message the message to be logged
368 */
369 def apply(level: Level, message: CharSequence): Unit =
370 macro LoggerMacro.logCseq
371
372 /**
373 * Logs an object at the given `Level`.
374 *
375 * @param level the logging level
376 * @param message the message to be logged
377 */
378 def apply(level: Level, message: AnyRef): Unit =
379 macro LoggerMacro.logObject
380
381 /**
382 * Logs a `Message` at the given `Level` including the stack trace of the given `Throwable`.
383 *
384 * @param level the logging level
385 * @param message the message to be logged
386 * @param cause a `Throwable`
387 */
388 def apply(level: Level, message: Message, cause: Throwable): Unit =
389 macro LoggerMacro.logMsgThrowable
390
391 /**
392 * Logs a string at the given `Level` including the stack trace of the given `Throwable`.
393 *
394 * @param level the logging level
395 * @param message the message to be logged
396 * @param cause a `Throwable`
397 */
398 def apply(level: Level, message: CharSequence, cause: Throwable): Unit =
399 macro LoggerMacro.logCseqThrowable
400
401 /**
402 * Logs an object at the given `Level` including the stack trace of the given `Throwable`.
403 *
404 * @param level the logging level
405 * @param message the message to be logged
406 * @param cause a `Throwable`
407 */
408 def apply(level: Level, message: AnyRef, cause: Throwable): Unit =
409 macro LoggerMacro.logObjectThrowable
410
411
412 /**
413 * Logs entry to a method. Used when the method in question has no parameters or when the parameters should not be
414 * logged.
415 *
416 * @return The built `EntryMessage`
417 */
418 def traceEntry(): EntryMessage =
419 macro LoggerMacro.traceEntry
420
421 /**
422 * Logs entry to a method along with its parameters.
423 *
424 * {{{
425 * def doSomething(foo: String, bar: Int): Unit = {
426 * logger.traceEntry(foo, bar)
427 * // do something
428 * }
429 * }}}
430 *
431 * @param params the parameters to the method.
432 * @return The built `EntryMessage`
433 */
434 def traceEntry(params: AnyRef*): EntryMessage =
435 macro LoggerMacro.traceEntryParams
436
437 /**
438 * Logs entry to a method using a `Message` to describe the parameters.
439 *
440 * {{{
441 * def doSomething(foo: Request): Unit = {
442 * logger.traceEntry(JsonMessage(foo))
443 * // do something
444 * }
445 * }}}
446 *
447 * @param message the message
448 * @return The built `EntryMessage`
449 */
450 def traceEntry(message: Message): EntryMessage =
451 macro LoggerMacro.traceEntryMessage
452
453 /**
454 * Logs exit from a method with no result.
455 */
456 def traceExit(): Unit =
457 macro LoggerMacro.traceExit
458
459 /**
460 * Logs exiting from a method with result.
461 *
462 * @param result The result being returned from the method call
463 * @return `result`
464 */
465 def traceExit[R](result: R): R =
466 macro LoggerMacro.traceExitResult[R]
467
468 /**
469 * Logs exiting from a method with no result.
470 *
471 * @param entryMessage the `EntryMessage` returned from one of the `traceEntry` methods
472 */
473 def traceExit(entryMessage: EntryMessage): Unit =
474 macro LoggerMacro.traceExitEntryMessage
475
476 /**
477 * Logs exiting from a method with result.
478 *
479 * {{{
480 * def doSomething(foo: String, bar: Int): Int = {
481 * val entryMessage = logger.traceEntry(foo, bar)
482 * // do something
483 * traceExit(entryMessage, value)
484 * }
485 * }}}
486 *
487 * @param entryMessage the `EntryMessage` returned from one of the `traceEntry` methods
488 * @param result The result being returned from the method call
489 * @return `result`
490 */
491 def traceExit[R](entryMessage: EntryMessage, result: R): R =
492 macro LoggerMacro.traceExitEntryMessageResult[R]
493
494 /**
495 * Logs exiting from a method with result. Allows custom formatting of the result.
496 *
497 * @param message the Message containing the formatted result
498 * @param result The result being returned from the method call.
499 * @return `result`
500 */
501 def traceExit[R](message: Message, result: R): R =
502 macro LoggerMacro.traceExitMessageResult[R]
503
504 /**
505 * Logs an exception or error to be thrown.
506 *
507 * {{{
508 * throw logger.throwing(myException)
509 * }}}
510 *
511 * @param t the Throwable
512 * @return `t`
513 */
514 def throwing[T <: Throwable](t: T): T =
515 macro LoggerMacro.throwing[T]
516
517 /**
518 * Logs an exception or error to be thrown to a specific logging level.
519 *
520 * {{{
521 * throw logger.throwing(Level.DEBUG, myException)
522 * }}}
523 *
524 * @param level the logging Level.
525 * @param t the Throwable
526 * @return `t`
527 */
528 def throwing[T <: Throwable](level: Level, t: T): T =
529 macro LoggerMacro.throwingLevel[T]
530
531 /**
532 * Logs an exception or error that has been caught.
533 *
534 * @param t the Throwable.
535 */
536 def catching(t: Throwable): Unit =
537 macro LoggerMacro.catching
538
539 /**
540 * Logs an exception or error that has been caught to a specific logging level.
541 *
542 * @param level The logging Level.
543 * @param t The Throwable.
544 */
545 def catching(level: Level, t: Throwable): Unit =
546 macro LoggerMacro.catchingLevel
547
548
549 /** Always logs a message at the specified level. It is the responsibility of the caller to ensure the specified
550 * level is enabled.
551 *
552 * Should normally not be used directly from application code, but needs to be public for access by macros.
553 *
554 * @param level log level
555 * @param marker marker or `null`
556 * @param message message
557 * @param cause cause or `null`
558 */
559 def logMessage(level: Level, marker: Marker, message: Message, cause: Throwable): Unit = {
560 delegate.logMessage(Logger.FQCN, level, marker, message, cause)
561 }
562
563 /** Always logs a message at the specified level. It is the responsibility of the caller to ensure the specified
564 * level is enabled.
565 *
566 * Should normally not be used directly from application code, but needs to be public for access by macros.
567 *
568 * @param level log level
569 * @param marker marker or `null`
570 * @param message message
571 * @param cause cause or `null`
572 */
573 def logMessage(level: Level, marker: Marker, message: CharSequence, cause: Throwable): Unit = {
574 delegate.logMessage(Logger.FQCN, level, marker, delegate.getMessageFactory.asInstanceOf[MessageFactory2].newMessage(message), cause)
575 }
576
577 /** Always logs a message at the specified level. It is the responsibility of the caller to ensure the specified
578 * level is enabled.
579 *
580 * Should normally not be used directly from application code, but needs to be public for access by macros.
581 *
582 * @param level log level
583 * @param marker marker or `null`
584 * @param message message
585 * @param cause cause or `null`
586 */
587 def logMessage(level: Level, marker: Marker, message: AnyRef, cause: Throwable): Unit = {
588 delegate.logMessage(Logger.FQCN, level, marker, delegate.getMessageFactory.asInstanceOf[MessageFactory2].newMessage(message), cause)
589 }
590
591 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.scala
17
18 import org.apache.logging.log4j.message.{EntryMessage, Message}
19 import org.apache.logging.log4j.spi.AbstractLogger
20 import org.apache.logging.log4j.{Level, Marker}
21
22 import scala.language.experimental.macros
23 import scala.reflect.macros.blackbox
24
25 /**
26 * Inspired from [[https://github.com/typesafehub/scalalogging ScalaLogging]].
27 */
28 private object LoggerMacro {
29
30 type LoggerContext = blackbox.Context { type PrefixType = Logger }
31
32
33 def fatalMarkerMsg(c: LoggerContext)(marker: c.Expr[Marker], message: c.Expr[Message]) =
34 logMarkerMsg(c)(c.universe.reify(Level.FATAL), marker, message)
35
36 def fatalMarkerCseq(c: LoggerContext)(marker: c.Expr[Marker], message: c.Expr[CharSequence]) =
37 logMarkerCseq(c)(c.universe.reify(Level.FATAL), marker, message)
38
39 def fatalMarkerObject(c: LoggerContext)(marker: c.Expr[Marker], message: c.Expr[AnyRef]) =
40 logMarkerObject(c)(c.universe.reify(Level.FATAL), marker, message)
41
42 def fatalMarkerMsgThrowable(c: LoggerContext)(marker: c.Expr[Marker], message: c.Expr[Message], cause: c.Expr[Throwable]) =
43 logMarkerMsgThrowable(c)(c.universe.reify(Level.FATAL), marker, message, cause)
44
45 def fatalMarkerCseqThrowable(c: LoggerContext)(marker: c.Expr[Marker], message: c.Expr[CharSequence], cause: c.Expr[Throwable]) =
46 logMarkerCseqThrowable(c)(c.universe.reify(Level.FATAL), marker, message, cause)
47
48 def fatalMarkerObjectThrowable(c: LoggerContext)(marker: c.Expr[Marker], message: c.Expr[AnyRef], cause: c.Expr[Throwable]) =
49 logMarkerObjectThrowable(c)(c.universe.reify(Level.FATAL), marker, message, cause)
50
51 def fatalMsg(c: LoggerContext)(message: c.Expr[Message]) =
52 logMsg(c)(c.universe.reify(Level.FATAL), message)
53
54 def fatalCseq(c: LoggerContext)(message: c.Expr[CharSequence]) =
55 logCseq(c)(c.universe.reify(Level.FATAL), message)
56
57 def fatalObject(c: LoggerContext)(message: c.Expr[AnyRef]) =
58 logObject(c)(c.universe.reify(Level.FATAL), message)
59
60 def fatalMsgThrowable(c: LoggerContext)(message: c.Expr[Message], cause: c.Expr[Throwable]) =
61 logMsgThrowable(c)(c.universe.reify(Level.FATAL), message, cause)
62
63 def fatalCseqThrowable(c: LoggerContext)(message: c.Expr[CharSequence], cause: c.Expr[Throwable]) =
64 logCseqThrowable(c)(c.universe.reify(Level.FATAL), message, cause)
65
66 def fatalObjectThrowable(c: LoggerContext)(message: c.Expr[AnyRef], cause: c.Expr[Throwable]) =
67 logObjectThrowable(c)(c.universe.reify(Level.FATAL), message, cause)
68
69
70 def errorMarkerMsg(c: LoggerContext)(marker: c.Expr[Marker], message: c.Expr[Message]) =
71 logMarkerMsg(c)(c.universe.reify(Level.ERROR), marker, message)
72
73 def errorMarkerCseq(c: LoggerContext)(marker: c.Expr[Marker], message: c.Expr[CharSequence]) =
74 logMarkerCseq(c)(c.universe.reify(Level.ERROR), marker, message)
75
76 def errorMarkerObject(c: LoggerContext)(marker: c.Expr[Marker], message: c.Expr[AnyRef]) =
77 logMarkerObject(c)(c.universe.reify(Level.ERROR), marker, message)
78
79 def errorMarkerMsgThrowable(c: LoggerContext)(marker: c.Expr[Marker], message: c.Expr[Message], cause: c.Expr[Throwable]) =
80 logMarkerMsgThrowable(c)(c.universe.reify(Level.ERROR), marker, message, cause)
81
82 def errorMarkerCseqThrowable(c: LoggerContext)(marker: c.Expr[Marker], message: c.Expr[CharSequence], cause: c.Expr[Throwable]) =
83 logMarkerCseqThrowable(c)(c.universe.reify(Level.ERROR), marker, message, cause)
84
85 def errorMarkerObjectThrowable(c: LoggerContext)(marker: c.Expr[Marker], message: c.Expr[AnyRef], cause: c.Expr[Throwable]) =
86 logMarkerObjectThrowable(c)(c.universe.reify(Level.ERROR), marker, message, cause)
87
88 def errorMsg(c: LoggerContext)(message: c.Expr[Message]) =
89 logMsg(c)(c.universe.reify(Level.ERROR), message)
90
91 def errorCseq(c: LoggerContext)(message: c.Expr[CharSequence]) =
92 logCseq(c)(c.universe.reify(Level.ERROR), message)
93
94 def errorObject(c: LoggerContext)(message: c.Expr[AnyRef]) =
95 logObject(c)(c.universe.reify(Level.ERROR), message)
96
97 def errorMsgThrowable(c: LoggerContext)(message: c.Expr[Message], cause: c.Expr[Throwable]) =
98 logMsgThrowable(c)(c.universe.reify(Level.ERROR), message, cause)
99
100 def errorCseqThrowable(c: LoggerContext)(message: c.Expr[CharSequence], cause: c.Expr[Throwable]) =
101 logCseqThrowable(c)(c.universe.reify(Level.ERROR), message, cause)
102
103 def errorObjectThrowable(c: LoggerContext)(message: c.Expr[AnyRef], cause: c.Expr[Throwable]) =
104 logObjectThrowable(c)(c.universe.reify(Level.ERROR), message, cause)
105
106
107 def warnMarkerMsg(c: LoggerContext)(marker: c.Expr[Marker], message: c.Expr[Message]) =
108 logMarkerMsg(c)(c.universe.reify(Level.WARN), marker, message)
109
110 def warnMarkerCseq(c: LoggerContext)(marker: c.Expr[Marker], message: c.Expr[CharSequence]) =
111 logMarkerCseq(c)(c.universe.reify(Level.WARN), marker, message)
112
113 def warnMarkerObject(c: LoggerContext)(marker: c.Expr[Marker], message: c.Expr[AnyRef]) =
114 logMarkerObject(c)(c.universe.reify(Level.WARN), marker, message)
115
116 def warnMarkerMsgThrowable(c: LoggerContext)(marker: c.Expr[Marker], message: c.Expr[Message], cause: c.Expr[Throwable]) =
117 logMarkerMsgThrowable(c)(c.universe.reify(Level.WARN), marker, message, cause)
118
119 def warnMarkerCseqThrowable(c: LoggerContext)(marker: c.Expr[Marker], message: c.Expr[CharSequence], cause: c.Expr[Throwable]) =
120 logMarkerCseqThrowable(c)(c.universe.reify(Level.WARN), marker, message, cause)
121
122 def warnMarkerObjectThrowable(c: LoggerContext)(marker: c.Expr[Marker], message: c.Expr[AnyRef], cause: c.Expr[Throwable]) =
123 logMarkerObjectThrowable(c)(c.universe.reify(Level.WARN), marker, message, cause)
124
125 def warnMsg(c: LoggerContext)(message: c.Expr[Message]) =
126 logMsg(c)(c.universe.reify(Level.WARN), message)
127
128 def warnCseq(c: LoggerContext)(message: c.Expr[CharSequence]) =
129 logCseq(c)(c.universe.reify(Level.WARN), message)
130
131 def warnObject(c: LoggerContext)(message: c.Expr[AnyRef]) =
132 logObject(c)(c.universe.reify(Level.WARN), message)
133
134 def warnMsgThrowable(c: LoggerContext)(message: c.Expr[Message], cause: c.Expr[Throwable]) =
135 logMsgThrowable(c)(c.universe.reify(Level.WARN), message, cause)
136
137 def warnCseqThrowable(c: LoggerContext)(message: c.Expr[CharSequence], cause: c.Expr[Throwable]) =
138 logCseqThrowable(c)(c.universe.reify(Level.WARN), message, cause)
139
140 def warnObjectThrowable(c: LoggerContext)(message: c.Expr[AnyRef], cause: c.Expr[Throwable]) =
141 logObjectThrowable(c)(c.universe.reify(Level.WARN), message, cause)
142
143
144 def infoMarkerMsg(c: LoggerContext)(marker: c.Expr[Marker], message: c.Expr[Message]) =
145 logMarkerMsg(c)(c.universe.reify(Level.INFO), marker, message)
146
147 def infoMarkerCseq(c: LoggerContext)(marker: c.Expr[Marker], message: c.Expr[CharSequence]) =
148 logMarkerCseq(c)(c.universe.reify(Level.INFO), marker, message)
149
150 def infoMarkerObject(c: LoggerContext)(marker: c.Expr[Marker], message: c.Expr[AnyRef]) =
151 logMarkerObject(c)(c.universe.reify(Level.INFO), marker, message)
152
153 def infoMarkerMsgThrowable(c: LoggerContext)(marker: c.Expr[Marker], message: c.Expr[Message], cause: c.Expr[Throwable]) =
154 logMarkerMsgThrowable(c)(c.universe.reify(Level.INFO), marker, message, cause)
155
156 def infoMarkerCseqThrowable(c: LoggerContext)(marker: c.Expr[Marker], message: c.Expr[CharSequence], cause: c.Expr[Throwable]) =
157 logMarkerCseqThrowable(c)(c.universe.reify(Level.INFO), marker, message, cause)
158
159 def infoMarkerObjectThrowable(c: LoggerContext)(marker: c.Expr[Marker], message: c.Expr[AnyRef], cause: c.Expr[Throwable]) =
160 logMarkerObjectThrowable(c)(c.universe.reify(Level.INFO), marker, message, cause)
161
162 def infoMsg(c: LoggerContext)(message: c.Expr[Message]) =
163 logMsg(c)(c.universe.reify(Level.INFO), message)
164
165 def infoCseq(c: LoggerContext)(message: c.Expr[CharSequence]) =
166 logCseq(c)(c.universe.reify(Level.INFO), message)
167
168 def infoObject(c: LoggerContext)(message: c.Expr[AnyRef]) =
169 logObject(c)(c.universe.reify(Level.INFO), message)
170
171 def infoMsgThrowable(c: LoggerContext)(message: c.Expr[Message], cause: c.Expr[Throwable]) =
172 logMsgThrowable(c)(c.universe.reify(Level.INFO), message, cause)
173
174 def infoCseqThrowable(c: LoggerContext)(message: c.Expr[CharSequence], cause: c.Expr[Throwable]) =
175 logCseqThrowable(c)(c.universe.reify(Level.INFO), message, cause)
176
177 def infoObjectThrowable(c: LoggerContext)(message: c.Expr[AnyRef], cause: c.Expr[Throwable]) =
178 logObjectThrowable(c)(c.universe.reify(Level.INFO), message, cause)
179
180
181 def debugMarkerMsg(c: LoggerContext)(marker: c.Expr[Marker], message: c.Expr[Message]) =
182 logMarkerMsg(c)(c.universe.reify(Level.DEBUG), marker, message)
183
184 def debugMarkerCseq(c: LoggerContext)(marker: c.Expr[Marker], message: c.Expr[CharSequence]) =
185 logMarkerCseq(c)(c.universe.reify(Level.DEBUG), marker, message)
186
187 def debugMarkerObject(c: LoggerContext)(marker: c.Expr[Marker], message: c.Expr[AnyRef]) =
188 logMarkerObject(c)(c.universe.reify(Level.DEBUG), marker, message)
189
190 def debugMarkerMsgThrowable(c: LoggerContext)(marker: c.Expr[Marker], message: c.Expr[Message], cause: c.Expr[Throwable]) =
191 logMarkerMsgThrowable(c)(c.universe.reify(Level.DEBUG), marker, message, cause)
192
193 def debugMarkerCseqThrowable(c: LoggerContext)(marker: c.Expr[Marker], message: c.Expr[CharSequence], cause: c.Expr[Throwable]) =
194 logMarkerCseqThrowable(c)(c.universe.reify(Level.DEBUG), marker, message, cause)
195
196 def debugMarkerObjectThrowable(c: LoggerContext)(marker: c.Expr[Marker], message: c.Expr[AnyRef], cause: c.Expr[Throwable]) =
197 logMarkerObjectThrowable(c)(c.universe.reify(Level.DEBUG), marker, message, cause)
198
199 def debugMsg(c: LoggerContext)(message: c.Expr[Message]) =
200 logMsg(c)(c.universe.reify(Level.DEBUG), message)
201
202 def debugCseq(c: LoggerContext)(message: c.Expr[CharSequence]) =
203 logCseq(c)(c.universe.reify(Level.DEBUG), message)
204
205 def debugObject(c: LoggerContext)(message: c.Expr[AnyRef]) =
206 logObject(c)(c.universe.reify(Level.DEBUG), message)
207
208 def debugMsgThrowable(c: LoggerContext)(message: c.Expr[Message], cause: c.Expr[Throwable]) =
209 logMsgThrowable(c)(c.universe.reify(Level.DEBUG), message, cause)
210
211 def debugCseqThrowable(c: LoggerContext)(message: c.Expr[CharSequence], cause: c.Expr[Throwable]) =
212 logCseqThrowable(c)(c.universe.reify(Level.DEBUG), message, cause)
213
214 def debugObjectThrowable(c: LoggerContext)(message: c.Expr[AnyRef], cause: c.Expr[Throwable]) =
215 logObjectThrowable(c)(c.universe.reify(Level.DEBUG), message, cause)
216
217
218 def traceMarkerMsg(c: LoggerContext)(marker: c.Expr[Marker], message: c.Expr[Message]) =
219 logMarkerMsg(c)(c.universe.reify(Level.TRACE), marker, message)
220
221 def traceMarkerCseq(c: LoggerContext)(marker: c.Expr[Marker], message: c.Expr[CharSequence]) =
222 logMarkerCseq(c)(c.universe.reify(Level.TRACE), marker, message)
223
224 def traceMarkerObject(c: LoggerContext)(marker: c.Expr[Marker], message: c.Expr[AnyRef]) =
225 logMarkerObject(c)(c.universe.reify(Level.TRACE), marker, message)
226
227 def traceMarkerMsgThrowable(c: LoggerContext)(marker: c.Expr[Marker], message: c.Expr[Message], cause: c.Expr[Throwable]) =
228 logMarkerMsgThrowable(c)(c.universe.reify(Level.TRACE), marker, message, cause)
229
230 def traceMarkerCseqThrowable(c: LoggerContext)(marker: c.Expr[Marker], message: c.Expr[CharSequence], cause: c.Expr[Throwable]) =
231 logMarkerCseqThrowable(c)(c.universe.reify(Level.TRACE), marker, message, cause)
232
233 def traceMarkerObjectThrowable(c: LoggerContext)(marker: c.Expr[Marker], message: c.Expr[AnyRef], cause: c.Expr[Throwable]) =
234 logMarkerObjectThrowable(c)(c.universe.reify(Level.TRACE), marker, message, cause)
235
236 def traceMsg(c: LoggerContext)(message: c.Expr[Message]) =
237 logMsg(c)(c.universe.reify(Level.TRACE), message)
238
239 def traceCseq(c: LoggerContext)(message: c.Expr[CharSequence]) =
240 logCseq(c)(c.universe.reify(Level.TRACE), message)
241
242 def traceObject(c: LoggerContext)(message: c.Expr[AnyRef]) =
243 logObject(c)(c.universe.reify(Level.TRACE), message)
244
245 def traceMsgThrowable(c: LoggerContext)(message: c.Expr[Message], cause: c.Expr[Throwable]) =
246 logMsgThrowable(c)(c.universe.reify(Level.TRACE), message, cause)
247
248 def traceCseqThrowable(c: LoggerContext)(message: c.Expr[CharSequence], cause: c.Expr[Throwable]) =
249 logCseqThrowable(c)(c.universe.reify(Level.TRACE), message, cause)
250
251 def traceObjectThrowable(c: LoggerContext)(message: c.Expr[AnyRef], cause: c.Expr[Throwable]) =
252 logObjectThrowable(c)(c.universe.reify(Level.TRACE), message, cause)
253
254
255 def logMarkerMsg(c: LoggerContext)(level: c.Expr[Level], marker: c.Expr[Marker], message: c.Expr[Message]) =
256 c.universe.reify(
257 if (c.prefix.splice.delegate.isEnabled(level.splice, marker.splice)) {
258 c.prefix.splice.logMessage(level.splice, marker.splice, message.splice, null)
259 }
260 )
261
262 def logMarkerCseq(c: LoggerContext)(level: c.Expr[Level], marker: c.Expr[Marker], message: c.Expr[CharSequence]) =
263 c.universe.reify(
264 if (c.prefix.splice.delegate.isEnabled(level.splice, marker.splice)) {
265 c.prefix.splice.logMessage(level.splice, marker.splice, message.splice, null)
266 }
267 )
268
269 def logMarkerObject(c: LoggerContext)(level: c.Expr[Level], marker: c.Expr[Marker], message: c.Expr[AnyRef]) =
270 c.universe.reify(
271 if (c.prefix.splice.delegate.isEnabled(level.splice, marker.splice)) {
272 c.prefix.splice.logMessage(level.splice, marker.splice, message.splice, null)
273 }
274 )
275
276 def logMarkerMsgThrowable(c: LoggerContext)(level: c.Expr[Level], marker: c.Expr[Marker], message: c.Expr[Message], cause: c.Expr[Throwable]) =
277 c.universe.reify(
278 if (c.prefix.splice.delegate.isEnabled(level.splice, marker.splice)) {
279 c.prefix.splice.logMessage(level.splice, marker.splice, message.splice, cause.splice)
280 }
281 )
282
283 def logMarkerCseqThrowable(c: LoggerContext)(level: c.Expr[Level], marker: c.Expr[Marker], message: c.Expr[CharSequence], cause: c.Expr[Throwable]) =
284 c.universe.reify(
285 if (c.prefix.splice.delegate.isEnabled(level.splice, marker.splice)) {
286 c.prefix.splice.logMessage(level.splice, marker.splice, message.splice, cause.splice)
287 }
288 )
289
290 def logMarkerObjectThrowable(c: LoggerContext)(level: c.Expr[Level], marker: c.Expr[Marker], message: c.Expr[AnyRef], cause: c.Expr[Throwable]) =
291 c.universe.reify(
292 if (c.prefix.splice.delegate.isEnabled(level.splice, marker.splice)) {
293 c.prefix.splice.logMessage(level.splice, marker.splice, message.splice, cause.splice)
294 }
295 )
296
297 def logMsg(c: LoggerContext)(level: c.Expr[Level], message: c.Expr[Message]) =
298 c.universe.reify(
299 if (c.prefix.splice.delegate.isEnabled(level.splice)) {
300 c.prefix.splice.logMessage(level.splice, null, message.splice, null)
301 }
302 )
303
304 def logCseq(c: LoggerContext)(level: c.Expr[Level], message: c.Expr[CharSequence]) =
305 c.universe.reify(
306 if (c.prefix.splice.delegate.isEnabled(level.splice)) {
307 c.prefix.splice.logMessage(level.splice, null, message.splice, null)
308 }
309 )
310
311 def logObject(c: LoggerContext)(level: c.Expr[Level], message: c.Expr[AnyRef]) =
312 c.universe.reify(
313 if (c.prefix.splice.delegate.isEnabled(level.splice)) {
314 c.prefix.splice.logMessage(level.splice, null, message.splice, null)
315 }
316 )
317
318 def logMsgThrowable(c: LoggerContext)(level: c.Expr[Level], message: c.Expr[Message], cause: c.Expr[Throwable]) =
319 c.universe.reify(
320 if (c.prefix.splice.delegate.isEnabled(level.splice)) {
321 c.prefix.splice.logMessage(level.splice, null, message.splice, cause.splice)
322 }
323 )
324
325 def logCseqThrowable(c: LoggerContext)(level: c.Expr[Level], message: c.Expr[CharSequence], cause: c.Expr[Throwable]) =
326 c.universe.reify(
327 if (c.prefix.splice.delegate.isEnabled(level.splice)) {
328 c.prefix.splice.logMessage(level.splice, null, message.splice, cause.splice)
329 }
330 )
331
332 def logObjectThrowable(c: LoggerContext)(level: c.Expr[Level], message: c.Expr[AnyRef], cause: c.Expr[Throwable]) =
333 c.universe.reify(
334 if (c.prefix.splice.delegate.isEnabled(level.splice)) {
335 c.prefix.splice.logMessage(level.splice, null, message.splice, cause.splice)
336 }
337 )
338
339
340 def traceEntry(c: LoggerContext)(): c.Expr[EntryMessage] =
341 c.universe.reify(
342 c.prefix.splice.delegate.traceEntry()
343 )
344
345 def traceEntryParams(c: LoggerContext)(params: c.Expr[AnyRef]*): c.Expr[EntryMessage] = {
346 import c.universe._
347 val isEnabled = Apply(
348 Select(Select(c.prefix.tree, newTermName("delegate")), newTermName("isEnabled")),
349 List(
350 reify(Level.TRACE).tree,
351 reify(AbstractLogger.ENTRY_MARKER).tree,
352 reify(null: AnyRef).tree,
353 reify(null).tree
354 )
355 )
356
357 val log = Apply(
358 Select(Select(c.prefix.tree, newTermName("delegate")), newTermName("traceEntry")),
359 reify(null: String).tree :: (params map (_.tree)).toList
360 )
361 c.Expr[EntryMessage](If(isEnabled, log, reify(null).tree))
362 }
363
364
365 def traceEntryMessage(c: LoggerContext)(message: c.Expr[Message]): c.Expr[EntryMessage] =
366 c.universe.reify(
367 if (c.prefix.splice.delegate.isEnabled(Level.TRACE, AbstractLogger.ENTRY_MARKER, null: AnyRef, null)) {
368 c.prefix.splice.delegate.traceEntry(message.splice) // TODO should not do ifEnabled check
369 } else {
370 null
371 }
372 )
373
374 def traceExit(c: LoggerContext)(): c.Expr[Unit] =
375 c.universe.reify(
376 c.prefix.splice.delegate.traceExit()
377 )
378
379 def traceExitResult[R: c.WeakTypeTag](c: LoggerContext)(result: c.Expr[R]): c.Expr[R] =
380 c.universe.reify(
381 c.prefix.splice.delegate.traceExit(result.splice)
382 )
383
384 def traceExitEntryMessage(c: LoggerContext)(entryMessage: c.Expr[EntryMessage]): c.Expr[Unit] =
385 c.universe.reify(
386 c.prefix.splice.delegate.traceExit(entryMessage.splice)
387 )
388
389 def traceExitEntryMessageResult[R: c.WeakTypeTag](c: LoggerContext)(entryMessage: c.Expr[EntryMessage], result: c.Expr[R]): c.Expr[R] =
390 c.universe.reify(
391 c.prefix.splice.delegate.traceExit(entryMessage.splice, result.splice)
392 )
393
394 def traceExitMessageResult[R: c.WeakTypeTag](c: LoggerContext)(message: c.Expr[Message], result: c.Expr[R]): c.Expr[R] =
395 c.universe.reify(
396 {
397 if (message.splice != null && c.prefix.splice.delegate.isEnabled(Level.TRACE, AbstractLogger.EXIT_MARKER, message.splice, null)) {
398 c.prefix.splice.delegate.traceExit(message.splice, result.splice) // TODO should not do ifEnabled check
399 }
400 result.splice
401 }
402 )
403
404 def throwing[T <: Throwable: c.WeakTypeTag](c: LoggerContext)(t: c.Expr[T]): c.Expr[T] =
405 c.universe.reify(
406 c.prefix.splice.delegate.throwing(t.splice)
407 )
408
409 def throwingLevel[T <: Throwable: c.WeakTypeTag](c: LoggerContext)(level: c.Expr[Level], t: c.Expr[T]): c.Expr[T] =
410 c.universe.reify(
411 c.prefix.splice.delegate.throwing(level.splice, t.splice)
412 )
413
414 def catching(c: LoggerContext)(t: c.Expr[Throwable]): c.Expr[Unit] =
415 c.universe.reify(
416 c.prefix.splice.delegate.catching(t.splice)
417 )
418
419 def catchingLevel(c: LoggerContext)(level: c.Expr[Level], t: c.Expr[Throwable]): c.Expr[Unit] =
420 c.universe.reify(
421 c.prefix.splice.delegate.catching(level.splice, t.splice)
422 )
423
424 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.scala
17
18 /**
19 * Mix in this trait into classes from which you want to log,
20 * give you a `logger` value with a [[Logger]] named according to the class.
21 */
22 trait Logging {
23
24 /**
25 * A [[Logger]] named according to the class.
26 */
27 protected val logger: Logger = Logger(getClass)
28
29 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.scala
17
18 import org.apache.logging.log4j.message.{DefaultFlowMessageFactory, Message, ParameterizedMessage, ParameterizedMessageFactory}
19 import org.apache.logging.log4j.spi.{AbstractLogger, ExtendedLogger}
20 import org.apache.logging.log4j.{Level, Marker, MarkerManager}
21 import org.junit.runner.RunWith
22 import org.mockito.Matchers.{any, anyString, eq => eqv}
23 import org.mockito.Mockito._
24 import org.scalatest.junit.JUnitRunner
25 import org.scalatest.mock.MockitoSugar
26 import org.scalatest.{FunSuite, Matchers}
27
28 case class Custom(i: Int)
29
30 trait Manager {
31 def fetchValue(): Int
32 }
33
34 @RunWith(classOf[JUnitRunner])
35 class LoggerTest extends FunSuite with Matchers with MockitoSugar {
36
37 val msg = new ParameterizedMessage("msg {}", 17)
38 val entryMsg = new DefaultFlowMessageFactory().newEntryMessage(msg)
39 val cseqMsg: CharSequence = new StringBuilder().append("cseq msg")
40 val objectMsg = Custom(17)
41 val cause = new RuntimeException("cause")
42 val marker = MarkerManager.getMarker("marker")
43 val result = "foo"
44
45 def fixture =
46 new {
47 val mockLogger = {
48 val mockLogger = mock[ExtendedLogger]
49 when(mockLogger.getMessageFactory).thenReturn(new ParameterizedMessageFactory)
50 mockLogger
51 }
52 val manager = {
53 val mockManager = mock[Manager]
54 when(mockManager.fetchValue()).thenReturn(4711)
55 mockManager
56 }
57 }
58
59 test("fatal enabled with String message") {
60 val f = fixture
61 when(f.mockLogger.isEnabled(Level.FATAL)).thenReturn(true)
62 val logger = Logger(f.mockLogger)
63 logger.fatal(s"string msg with value: ${f.manager.fetchValue()}")
64 verify(f.mockLogger).logMessage(anyString(), eqv(Level.FATAL), eqv(null), any[Message], eqv(null))
65 verify(f.manager).fetchValue()
66 }
67
68 test("fatal disabled with String message") {
69 val f = fixture
70 when(f.mockLogger.isEnabled(Level.FATAL)).thenReturn(false)
71 val logger = Logger(f.mockLogger)
72 logger.fatal(s"string msg with value: ${f.manager.fetchValue()}")
73 verify(f.mockLogger, never).logMessage(anyString(), any[Level], any[Marker], any[Message], any[Throwable])
74 verify(f.manager, never).fetchValue()
75 }
76
77 test("error enabled with String message") {
78 val f = fixture
79 when(f.mockLogger.isEnabled(Level.ERROR)).thenReturn(true)
80 val logger = Logger(f.mockLogger)
81 logger.error(s"string msg with value: ${f.manager.fetchValue()}")
82 verify(f.mockLogger).logMessage(anyString(), eqv(Level.ERROR), eqv(null), any[Message], eqv(null))
83 verify(f.manager).fetchValue()
84 }
85
86 test("error disabled with String message") {
87 val f = fixture
88 when(f.mockLogger.isEnabled(Level.ERROR)).thenReturn(false)
89 val logger = Logger(f.mockLogger)
90 logger.error(s"string msg with value: ${f.manager.fetchValue()}")
91 verify(f.mockLogger, never).logMessage(anyString(), any[Level], any[Marker], any[Message], any[Throwable])
92 verify(f.manager, never).fetchValue()
93 }
94
95 test("warn enabled with String message") {
96 val f = fixture
97 when(f.mockLogger.isEnabled(Level.WARN)).thenReturn(true)
98 val logger = Logger(f.mockLogger)
99 logger.warn(s"string msg with value: ${f.manager.fetchValue()}")
100 verify(f.mockLogger).logMessage(anyString(), eqv(Level.WARN), eqv(null), any[Message], eqv(null))
101 verify(f.manager).fetchValue()
102 }
103
104 test("warn disabled with String message") {
105 val f = fixture
106 when(f.mockLogger.isEnabled(Level.WARN)).thenReturn(false)
107 val logger = Logger(f.mockLogger)
108 logger.warn(s"string msg with value: ${f.manager.fetchValue()}")
109 verify(f.mockLogger, never).logMessage(anyString(), any[Level], any[Marker], any[Message], any[Throwable])
110 verify(f.manager, never).fetchValue()
111 }
112
113 test("info enabled with String message") {
114 val f = fixture
115 when(f.mockLogger.isEnabled(Level.INFO)).thenReturn(true)
116 val logger = Logger(f.mockLogger)
117 logger.info(s"string msg with value: ${f.manager.fetchValue()}")
118 verify(f.mockLogger).logMessage(anyString(), eqv(Level.INFO), eqv(null), any[Message], eqv(null))
119 verify(f.manager).fetchValue()
120 }
121
122 test("info disabled with String message") {
123 val f = fixture
124 when(f.mockLogger.isEnabled(Level.INFO)).thenReturn(false)
125 val logger = Logger(f.mockLogger)
126 logger.info(s"string msg with value: ${f.manager.fetchValue()}")
127 verify(f.mockLogger, never).logMessage(anyString(), any[Level], any[Marker], any[Message], any[Throwable])
128 verify(f.manager, never).fetchValue()
129 }
130
131 test("debug enabled with String message") {
132 val f = fixture
133 when(f.mockLogger.isEnabled(Level.DEBUG)).thenReturn(true)
134 val logger = Logger(f.mockLogger)
135 logger.debug(s"string msg with value: ${f.manager.fetchValue()}")
136 verify(f.mockLogger).logMessage(anyString(), eqv(Level.DEBUG), eqv(null), any[Message], eqv(null))
137 verify(f.manager).fetchValue()
138 }
139
140 test("debug disabled with String message") {
141 val f = fixture
142 when(f.mockLogger.isEnabled(Level.DEBUG)).thenReturn(false)
143 val logger = Logger(f.mockLogger)
144 logger.debug(s"string msg with value: ${f.manager.fetchValue()}")
145 verify(f.mockLogger, never).logMessage(anyString(), any[Level], any[Marker], any[Message], any[Throwable])
146 verify(f.manager, never).fetchValue()
147 }
148
149 test("trace enabled with String message") {
150 val f = fixture
151 when(f.mockLogger.isEnabled(Level.TRACE)).thenReturn(true)
152 val logger = Logger(f.mockLogger)
153 logger.trace(s"string msg with value: ${f.manager.fetchValue()}")
154 verify(f.mockLogger).logMessage(anyString(), eqv(Level.TRACE), eqv(null), any[Message], eqv(null))
155 verify(f.manager).fetchValue()
156 }
157
158 test("trace disabled with String message") {
159 val f = fixture
160 when(f.mockLogger.isEnabled(Level.TRACE)).thenReturn(false)
161 val logger = Logger(f.mockLogger)
162 logger.trace(s"string msg with value: ${f.manager.fetchValue()}")
163 verify(f.mockLogger, never).logMessage(anyString(), any[Level], any[Marker], any[Message], any[Throwable])
164 verify(f.manager, never).fetchValue()
165 }
166
167
168 test("log enabled with Message message and Marker") {
169 val f = fixture
170 when(f.mockLogger.isEnabled(Level.INFO, marker)).thenReturn(true)
171 val logger = Logger(f.mockLogger)
172 logger(Level.INFO, marker, msg)
173 verify(f.mockLogger).logMessage(anyString(), eqv(Level.INFO), eqv(marker), eqv(msg), eqv(null))
174 }
175
176 test("log disabled with Message message and Marker") {
177 val f = fixture
178 when(f.mockLogger.isEnabled(Level.INFO, marker)).thenReturn(false)
179 val logger = Logger(f.mockLogger)
180 logger(Level.INFO, marker, msg)
181 verify(f.mockLogger, never).logMessage(anyString(), any[Level], any[Marker], any[Message], any[Throwable])
182 }
183
184 test("log enabled with String message and Marker") {
185 val f = fixture
186 when(f.mockLogger.isEnabled(Level.INFO, marker)).thenReturn(true)
187 val logger = Logger(f.mockLogger)
188 logger(Level.INFO, marker, s"string msg with value: ${f.manager.fetchValue()}")
189 verify(f.mockLogger).logMessage(anyString(), eqv(Level.INFO), eqv(marker), any[Message], eqv(null))
190 verify(f.manager).fetchValue()
191 }
192
193 test("log disabled with String message and Marker") {
194 val f = fixture
195 when(f.mockLogger.isEnabled(Level.INFO, marker)).thenReturn(false)
196 val logger = Logger(f.mockLogger)
197 logger(Level.INFO, marker, s"string msg with value: ${f.manager.fetchValue()}")
198 verify(f.mockLogger, never).logMessage(anyString(), any[Level], any[Marker], any[Message], any[Throwable])
199 verify(f.manager, never).fetchValue()
200 }
201
202 test("log enabled with CharSequence message and Marker") {
203 val f = fixture
204 when(f.mockLogger.isEnabled(Level.INFO, marker)).thenReturn(true)
205 val logger = Logger(f.mockLogger)
206 logger(Level.INFO, marker, cseqMsg)
207 verify(f.mockLogger).logMessage(anyString(), eqv(Level.INFO), eqv(marker), any[Message], eqv(null))
208 }
209
210 test("log disabled with CharSequence message and Marker") {
211 val f = fixture
212 when(f.mockLogger.isEnabled(Level.INFO, marker)).thenReturn(false)
213 val logger = Logger(f.mockLogger)
214 logger(Level.INFO, marker, cseqMsg)
215 verify(f.mockLogger, never).logMessage(anyString(), any[Level], any[Marker], any[Message], any[Throwable])
216 }
217
218 test("log enabled with Object message and Marker") {
219 val f = fixture
220 when(f.mockLogger.isEnabled(Level.INFO, marker)).thenReturn(true)
221 val logger = Logger(f.mockLogger)
222 logger(Level.INFO, marker, objectMsg)
223 verify(f.mockLogger).logMessage(anyString(), eqv(Level.INFO), eqv(marker), any[Message], eqv(null))
224 }
225
226 test("log disabled with Object message and Marker") {
227 val f = fixture
228 when(f.mockLogger.isEnabled(Level.INFO, marker)).thenReturn(false)
229 val logger = Logger(f.mockLogger)
230 logger(Level.INFO, marker, objectMsg)
231 verify(f.mockLogger, never).logMessage(anyString(), any[Level], any[Marker], any[Message], any[Throwable])
232 }
233
234 test("log enabled with Message message and cause and Marker") {
235 val f = fixture
236 when(f.mockLogger.isEnabled(Level.INFO, marker)).thenReturn(true)
237 val logger = Logger(f.mockLogger)
238 logger(Level.INFO, marker, msg, cause)
239 verify(f.mockLogger).logMessage(anyString(), eqv(Level.INFO), eqv(marker), eqv(msg), eqv(cause))
240 }
241
242 test("log disabled with Message message and cause and Marker") {
243 val f = fixture
244 when(f.mockLogger.isEnabled(Level.INFO, marker)).thenReturn(false)
245 val logger = Logger(f.mockLogger)
246 logger(Level.INFO, marker, msg, cause)
247 verify(f.mockLogger, never).logMessage(anyString(), any[Level], any[Marker], any[Message], any[Throwable])
248 }
249
250 test("log enabled with String message and cause and Marker") {
251 val f = fixture
252 when(f.mockLogger.isEnabled(Level.INFO, marker)).thenReturn(true)
253 val logger = Logger(f.mockLogger)
254 logger(Level.INFO, marker, s"string msg with value: ${f.manager.fetchValue()}", cause)
255 verify(f.mockLogger).logMessage(anyString(), eqv(Level.INFO), eqv(marker), any[Message], eqv(cause))
256 verify(f.manager).fetchValue()
257 }
258
259 test("log disabled with String message and cause and Marker") {
260 val f = fixture
261 when(f.mockLogger.isEnabled(Level.INFO, marker)).thenReturn(false)
262 val logger = Logger(f.mockLogger)
263 logger(Level.INFO, marker, s"string msg with value: ${f.manager.fetchValue()}", cause)
264 verify(f.mockLogger, never).logMessage(anyString(), any[Level], any[Marker], any[Message], any[Throwable])
265 verify(f.manager, never).fetchValue()
266 }
267
268 test("log enabled with CharSequence message and cause and Marker") {
269 val f = fixture
270 when(f.mockLogger.isEnabled(Level.INFO, marker)).thenReturn(true)
271 val logger = Logger(f.mockLogger)
272 logger(Level.INFO, marker, cseqMsg, cause)
273 verify(f.mockLogger).logMessage(anyString(), eqv(Level.INFO), eqv(marker), any[Message], eqv(cause))
274 }
275
276 test("log disabled with CharSequence message and cause and Marker") {
277 val f = fixture
278 when(f.mockLogger.isEnabled(Level.INFO, marker)).thenReturn(false)
279 val logger = Logger(f.mockLogger)
280 logger(Level.INFO, marker, cseqMsg, cause)
281 verify(f.mockLogger, never).logMessage(anyString(), any[Level], any[Marker], any[Message], any[Throwable])
282 }
283
284 test("log enabled with Object message and cause and Marker") {
285 val f = fixture
286 when(f.mockLogger.isEnabled(Level.INFO, marker)).thenReturn(true)
287 val logger = Logger(f.mockLogger)
288 logger(Level.INFO, marker, objectMsg, cause)
289 verify(f.mockLogger).logMessage(anyString(), eqv(Level.INFO), eqv(marker), any[Message], eqv(cause))
290 }
291
292 test("log disabled with Object message and cause and Marker") {
293 val f = fixture
294 when(f.mockLogger.isEnabled(Level.INFO, marker)).thenReturn(false)
295 val logger = Logger(f.mockLogger)
296 logger(Level.INFO, marker, objectMsg, cause)
297 verify(f.mockLogger, never).logMessage(anyString(), any[Level], any[Marker], any[Message], any[Throwable])
298 }
299
300 test("log enabled with Message message") {
301 val f = fixture
302 when(f.mockLogger.isEnabled(Level.INFO)).thenReturn(true)
303 val logger = Logger(f.mockLogger)
304 logger(Level.INFO, msg)
305 verify(f.mockLogger).logMessage(anyString(), eqv(Level.INFO), eqv(null), eqv(msg), eqv(null))
306 }
307
308 test("log disabled with Message message") {
309 val f = fixture
310 when(f.mockLogger.isEnabled(Level.INFO)).thenReturn(false)
311 val logger = Logger(f.mockLogger)
312 logger(Level.INFO, msg)
313 verify(f.mockLogger, never).logMessage(anyString(), any[Level], any[Marker], any[Message], any[Throwable])
314 }
315
316 test("log enabled with String message") {
317 val f = fixture
318 when(f.mockLogger.isEnabled(Level.INFO)).thenReturn(true)
319 val logger = Logger(f.mockLogger)
320 logger(Level.INFO, s"string msg with value: ${f.manager.fetchValue()}")
321 verify(f.mockLogger).logMessage(anyString(), eqv(Level.INFO), eqv(null), any[Message], eqv(null))
322 verify(f.manager).fetchValue()
323 }
324
325 test("log disabled with String message") {
326 val f = fixture
327 when(f.mockLogger.isEnabled(Level.INFO)).thenReturn(false)
328 val logger = Logger(f.mockLogger)
329 logger(Level.INFO, s"string msg with value: ${f.manager.fetchValue()}")
330 verify(f.mockLogger, never).logMessage(anyString(), any[Level], any[Marker], any[Message], any[Throwable])
331 verify(f.manager, never).fetchValue()
332 }
333
334 test("log enabled with CharSequence message") {
335 val f = fixture
336 when(f.mockLogger.isEnabled(Level.INFO)).thenReturn(true)
337 val logger = Logger(f.mockLogger)
338 logger(Level.INFO, cseqMsg)
339 verify(f.mockLogger).logMessage(anyString(), eqv(Level.INFO), eqv(null), any[Message], eqv(null))
340 }
341
342 test("log disabled with CharSequence message") {
343 val f = fixture
344 when(f.mockLogger.isEnabled(Level.INFO)).thenReturn(false)
345 val logger = Logger(f.mockLogger)
346 logger(Level.INFO, cseqMsg)
347 verify(f.mockLogger, never).logMessage(anyString(), any[Level], any[Marker], any[Message], any[Throwable])
348 }
349
350 test("log enabled with Object message") {
351 val f = fixture
352 when(f.mockLogger.isEnabled(Level.INFO)).thenReturn(true)
353 val logger = Logger(f.mockLogger)
354 logger(Level.INFO, objectMsg)
355 verify(f.mockLogger).logMessage(anyString(), eqv(Level.INFO), eqv(null), any[Message], eqv(null))
356 }
357
358 test("log disabled with Object message") {
359 val f = fixture
360 when(f.mockLogger.isEnabled(Level.INFO)).thenReturn(false)
361 val logger = Logger(f.mockLogger)
362 logger(Level.INFO, objectMsg)
363 verify(f.mockLogger, never).logMessage(anyString(), any[Level], any[Marker], any[Message], any[Throwable])
364 }
365
366 test("log enabled with Message message and cause") {
367 val f = fixture
368 when(f.mockLogger.isEnabled(Level.INFO)).thenReturn(true)
369 val logger = Logger(f.mockLogger)
370 logger(Level.INFO, msg, cause)
371 verify(f.mockLogger).logMessage(anyString(), eqv(Level.INFO), eqv(null), eqv(msg), eqv(cause))
372 }
373
374 test("log disabled with Message message and cause") {
375 val f = fixture
376 when(f.mockLogger.isEnabled(Level.INFO)).thenReturn(false)
377 val logger = Logger(f.mockLogger)
378 logger(Level.INFO, msg, cause)
379 verify(f.mockLogger, never).logMessage(anyString(), any[Level], any[Marker], any[Message], any[Throwable])
380 }
381
382 test("log enabled with String message and cause") {
383 val f = fixture
384 when(f.mockLogger.isEnabled(Level.INFO)).thenReturn(true)
385 val logger = Logger(f.mockLogger)
386 logger(Level.INFO, s"string msg with value: ${f.manager.fetchValue()}", cause)
387 verify(f.mockLogger).logMessage(anyString(), eqv(Level.INFO), eqv(null), any[Message], eqv(cause))
388 verify(f.manager).fetchValue()
389 }
390
391 test("log disabled with String message and cause") {
392 val f = fixture
393 when(f.mockLogger.isEnabled(Level.INFO)).thenReturn(false)
394 val logger = Logger(f.mockLogger)
395 logger(Level.INFO, s"string msg with value: ${f.manager.fetchValue()}", cause)
396 verify(f.mockLogger, never).logMessage(anyString(), any[Level], any[Marker], any[Message], any[Throwable])
397 verify(f.manager, never).fetchValue()
398 }
399
400 test("log enabled with CharSequence message and cause") {
401 val f = fixture
402 when(f.mockLogger.isEnabled(Level.INFO)).thenReturn(true)
403 val logger = Logger(f.mockLogger)
404 logger(Level.INFO, cseqMsg, cause)
405 verify(f.mockLogger).logMessage(anyString(), eqv(Level.INFO), eqv(null), any[Message], eqv(cause))
406 }
407
408 test("log disabled with CharSequence message and cause") {
409 val f = fixture
410 when(f.mockLogger.isEnabled(Level.INFO)).thenReturn(false)
411 val logger = Logger(f.mockLogger)
412 logger(Level.INFO, cseqMsg, cause)
413 verify(f.mockLogger, never).logMessage(anyString(), any[Level], any[Marker], any[Message], any[Throwable])
414 }
415
416 test("log enabled with Object message and cause") {
417 val f = fixture
418 when(f.mockLogger.isEnabled(Level.INFO)).thenReturn(true)
419 val logger = Logger(f.mockLogger)
420 logger(Level.INFO, objectMsg, cause)
421 verify(f.mockLogger).logMessage(anyString(), eqv(Level.INFO), eqv(null), any[Message], eqv(cause))
422 }
423
424 test("log disabled with Object message and cause") {
425 val f = fixture
426 when(f.mockLogger.isEnabled(Level.INFO)).thenReturn(false)
427 val logger = Logger(f.mockLogger)
428 logger(Level.INFO, objectMsg, cause)
429 verify(f.mockLogger, never).logMessage(anyString(), any[Level], any[Marker], any[Message], any[Throwable])
430 }
431
432
433 test("traceEntry") {
434 val f = fixture
435 when(f.mockLogger.isEnabled(Level.TRACE, AbstractLogger.ENTRY_MARKER, null.asInstanceOf[AnyRef], null)).thenReturn(true)
436 val logger = Logger(f.mockLogger)
437 logger.traceEntry()
438 verify(f.mockLogger).traceEntry()
439 }
440
441 test("traceEntry enabled with params") {
442 val f = fixture
443 when(f.mockLogger.isEnabled(Level.TRACE, AbstractLogger.ENTRY_MARKER, null.asInstanceOf[AnyRef], null)).thenReturn(true)
444 val logger = Logger(f.mockLogger)
445 logger.traceEntry("foo", "bar")
446 verify(f.mockLogger).traceEntry(null: String, "foo", "bar")
447 }
448
449 test("traceEntry disabled with params") {
450 val f = fixture
451 when(f.mockLogger.isEnabled(Level.TRACE, AbstractLogger.ENTRY_MARKER, null.asInstanceOf[AnyRef], null)).thenReturn(false)
452 val logger = Logger(f.mockLogger)
453 logger.traceEntry("foo", "bar")
454 verify(f.mockLogger, never).traceEntry(anyString(), anyString(), anyString())
455 }
456
457 test("traceEntry enabled with message") {
458 val f = fixture
459 when(f.mockLogger.isEnabled(Level.TRACE, AbstractLogger.ENTRY_MARKER, null.asInstanceOf[AnyRef], null)).thenReturn(true)
460 val logger = Logger(f.mockLogger)
461 logger.traceEntry(msg)
462 verify(f.mockLogger).traceEntry(eqv(msg))
463 }
464
465 test("traceEntry disabled with message") {
466 val f = fixture
467 when(f.mockLogger.isEnabled(Level.TRACE, AbstractLogger.ENTRY_MARKER, null.asInstanceOf[AnyRef], null)).thenReturn(false)
468 val logger = Logger(f.mockLogger)
469 logger.traceEntry(msg)
470 verify(f.mockLogger, never).traceEntry(any[Message])
471 }
472
473 test("traceExit") {
474 val f = fixture
475 when(f.mockLogger.isEnabled(Level.TRACE, AbstractLogger.EXIT_MARKER, msg, null)).thenReturn(true)
476 val logger = Logger(f.mockLogger)
477 logger.traceExit()
478 verify(f.mockLogger).traceExit()
479 }
480
481 test("traceExit with result") {
482 val f = fixture
483 when(f.mockLogger.isEnabled(Level.TRACE, AbstractLogger.EXIT_MARKER, msg, null)).thenReturn(true)
484 val logger = Logger(f.mockLogger)
485 logger.traceExit(result)
486 verify(f.mockLogger).traceExit(result)
487 }
488
489 test("traceExit with entrymessage") {
490 val f = fixture
491 when(f.mockLogger.isEnabled(Level.TRACE, AbstractLogger.EXIT_MARKER, msg, null)).thenReturn(true)
492 val logger = Logger(f.mockLogger)
493 logger.traceExit(entryMsg)
494 verify(f.mockLogger).traceExit(entryMsg)
495 }
496
497 test("traceExit with entrymessage and result") {
498 val f = fixture
499 when(f.mockLogger.isEnabled(Level.TRACE, AbstractLogger.EXIT_MARKER, msg, null)).thenReturn(true)
500 val logger = Logger(f.mockLogger)
501 logger.traceExit(entryMsg, result)
502 verify(f.mockLogger).traceExit(entryMsg, result)
503 }
504
505 test("traceExit enabled with message") {
506 val f = fixture
507 when(f.mockLogger.isEnabled(Level.TRACE, AbstractLogger.EXIT_MARKER, msg, null)).thenReturn(true)
508 val logger = Logger(f.mockLogger)
509 logger.traceExit(msg, result)
510 verify(f.mockLogger).traceExit(eqv(msg), eqv(result))
511 }
512
513 test("traceExit disabled with message") {
514 val f = fixture
515 when(f.mockLogger.isEnabled(Level.TRACE, AbstractLogger.EXIT_MARKER, msg, null)).thenReturn(false)
516 val logger = Logger(f.mockLogger)
517 logger.traceExit(msg, result)
518 verify(f.mockLogger, never).traceExit(any[Message], any[AnyRef])
519 }
520
521 test("throwing") {
522 val f = fixture
523 val logger = Logger(f.mockLogger)
524 logger.throwing(cause)
525 verify(f.mockLogger).throwing(eqv(cause))
526 }
527
528 test("throwing with level") {
529 val f = fixture
530 val logger = Logger(f.mockLogger)
531 logger.throwing(Level.INFO, cause)
532 verify(f.mockLogger).throwing(eqv(Level.INFO), eqv(cause))
533 }
534
535 test("catching") {
536 val f = fixture
537 val logger = Logger(f.mockLogger)
538 logger.catching(cause)
539 verify(f.mockLogger).catching(eqv(cause))
540 }
541
542 test("catching with level") {
543 val f = fixture
544 val logger = Logger(f.mockLogger)
545 logger.catching(Level.INFO, cause)
546 verify(f.mockLogger).catching(eqv(Level.INFO), eqv(cause))
547 }
548
549 }
+0
-3
log4j-bom/.gitignore less more
0 /target/
1 /.project
2 /.settings/
2525 <description>Apache Log4j Bill of Materials</description>
2626 <groupId>org.apache.logging.log4j</groupId>
2727 <artifactId>log4j-bom</artifactId>
28 <version>2.6.2</version>
28 <version>2.7</version>
2929 <packaging>pom</packaging>
3030 <dependencyManagement>
3131 <dependencies>
107107 <artifactId>log4j-liquibase</artifactId>
108108 <version>${project.version}</version>
109109 </dependency>
110 <!-- Scala 2.10 API -->
111 <dependency>
112 <groupId>org.apache.logging.log4j</groupId>
113 <artifactId>log4j-api-scala_2.10</artifactId>
114 <version>${project.version}</version>
115 </dependency>
116 <!-- Scala 2.11 API -->
117 <dependency>
118 <groupId>org.apache.logging.log4j</groupId>
119 <artifactId>log4j-api-scala_2.11</artifactId>
120 <version>${project.version}</version>
121 </dependency>
110122 </dependencies>
111123 </dependencyManagement>
112124 <build>
130142 </build>
131143
132144 <scm>
133 <tag>log4j-2.6.2-rc1</tag>
145 <tag>log4j-2.7-rc2</tag>
134146 </scm>
135147 </project>
+0
-5
log4j-core/.gitignore less more
0 /.settings/
1 /target/
2 /.classpath
3 /.project
4 /bin/
00 <?xml version="1.0" encoding="UTF-8"?>
1
21 <!--
32 ~ Licensed to the Apache Software Foundation (ASF) under one or more
43 ~ contributor license agreements. See the NOTICE file distributed with
2019 <parent>
2120 <groupId>org.apache.logging.log4j</groupId>
2221 <artifactId>log4j</artifactId>
23 <version>2.6.2</version>
22 <version>2.7</version>
2423 <relativePath>../</relativePath>
2524 </parent>
2625 <artifactId>log4j-core</artifactId>
5049 <artifactId>disruptor</artifactId>
5150 <optional>true</optional>
5251 </dependency>
52 <!-- Alternative implementation of BlockingQueue using Conversant Disruptor for AsyncAppender -->
53 <dependency>
54 <groupId>com.conversantmedia</groupId>
55 <artifactId>disruptor</artifactId>
56 <optional>true</optional>
57 </dependency>
58 <!-- Alternative implementation of BlockingQueue using JCTools for AsyncAppender -->
59 <dependency>
60 <groupId>org.jctools</groupId>
61 <artifactId>jctools-core</artifactId>
62 <optional>true</optional>
63 </dependency>
5364 <!-- Required for JSON support -->
5465 <dependency>
5566 <groupId>com.fasterxml.jackson.core</groupId>
7485 <artifactId>jackson-dataformat-xml</artifactId>
7586 <optional>true</optional>
7687 </dependency>
77 <!-- POM for jackson-dataformat-xml 2.7.3 depends on woodstox-core 5.0.2 -->
88 <!-- POM for jackson-dataformat-xml 2.8.3 depends on woodstox-core 5.0.2 -->
7889 <dependency>
7990 <groupId>com.fasterxml.woodstox</groupId>
8091 <artifactId>woodstox-core</artifactId>
129140 <dependency>
130141 <groupId>org.apache.commons</groupId>
131142 <artifactId>commons-csv</artifactId>
143 <optional>true</optional>
144 </dependency>
145 <!-- Command line for TCP and UDP servers -->
146 <dependency>
147 <groupId>com.beust</groupId>
148 <artifactId>jcommander</artifactId>
132149 <optional>true</optional>
133150 </dependency>
134151
244261 <artifactId>org.apache.felix.framework</artifactId>
245262 <scope>test</scope>
246263 </dependency>
264 <dependency>
265 <groupId>org.codehaus.plexus</groupId>
266 <artifactId>plexus-utils</artifactId>
267 <scope>test</scope>
268 </dependency>
269 <dependency>
270 <groupId>org.apache.maven</groupId>
271 <artifactId>maven-core</artifactId>
272 <scope>test</scope>
273 </dependency>
247274 <!-- GELF -->
248275 <dependency>
249276 <groupId>net.javacrumbs.json-unit</groupId>
250277 <artifactId>json-unit</artifactId>
278 <scope>test</scope>
279 </dependency>
280 <dependency>
281 <groupId>org.xmlunit</groupId>
282 <artifactId>xmlunit-core</artifactId>
283 <scope>test</scope>
284 </dependency>
285 <dependency>
286 <groupId>org.xmlunit</groupId>
287 <artifactId>xmlunit-matchers</artifactId>
251288 <scope>test</scope>
252289 </dependency>
253290 <dependency>
275312 <dependency>
276313 <groupId>org.codehaus.groovy</groupId>
277314 <artifactId>groovy-all</artifactId>
278 <version>2.4.5</version>
315 <version>2.4.7</version>
279316 <scope>test</scope>
280317 </dependency>
281318 <!-- GC-free -->
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16
17 package org.apache.logging.log4j;
18
19 import org.apache.logging.log4j.spi.ThreadContextMap;
20 import org.apache.logging.log4j.spi.ThreadContextMap2;
21
22 /**
23 * <em>This class is intended for internal log4j2 usage and should not be used directly by applications.</em>
24 * <p>
25 * Utility class to access package protected methods in {@code ThreadContext}.
26 * </p>
27 *
28 * @see ThreadContext
29 * @since 2.7
30 */
31 public final class ThreadContextAccess {
32 private ThreadContextAccess() { // this class should not be instantiated
33 }
34
35 /**
36 * Returns the internal data structure used to store thread context key-value pairs.
37 * <p><em>
38 * This method is intended for internal log4j2 usage.
39 * The returned data structure is not intended to be used directly by applications.
40 * </em></p>
41 * @return the internal data structure used to store thread context key-value pairs
42 */
43 public static ThreadContextMap getThreadContextMap() {
44 return ThreadContext.getThreadContextMap();
45 }
46
47 /**
48 * Returns the internal data structure used to store thread context key-value pairs.
49 * <p><em>
50 * This method is intended for internal log4j2 usage.
51 * The returned data structure is not intended to be used directly by applications.
52 * </em></p>
53 * @return the internal data structure used to store thread context key-value pairs
54 */
55 public static ThreadContextMap2 getThreadContextMap2() {
56 return (ThreadContextMap2) ThreadContext.getThreadContextMap();
57 }
58 }
1515 */
1616 package org.apache.logging.log4j.core;
1717
18 import java.util.concurrent.Future;
19 import java.util.concurrent.TimeUnit;
20
1821 import org.apache.logging.log4j.status.StatusLogger;
1922
2023 /**
2326 * Wraps a {@link LifeCycle.State}.
2427 * </p>
2528 */
26 public class AbstractLifeCycle implements LifeCycle {
29 public class AbstractLifeCycle implements LifeCycle2 {
30
31 public static final int DEFAULT_STOP_TIMEOUT = 0;
32 public static final TimeUnit DEFAULT_STOP_TIMEUNIT = TimeUnit.MILLISECONDS;
2733
2834 /**
2935 * Allow subclasses access to the status logger without creating another instance.
117123
118124 @Override
119125 public void stop() {
126 stop(DEFAULT_STOP_TIMEOUT, DEFAULT_STOP_TIMEUNIT);
127 }
128
129 protected boolean stop(final Future<?> future) {
130 boolean stopped = true;
131 if (future != null) {
132 if (future.isCancelled() || future.isDone()) {
133 return true;
134 }
135 stopped = future.cancel(true);
136 }
137 return stopped;
138 }
139
140 @Override
141 public boolean stop(final long timeout, final TimeUnit timeUnit) {
120142 this.state = LifeCycle.State.STOPPED;
143 return true;
121144 }
122145
123146 }
2424 import org.apache.logging.log4j.ThreadContext.ContextStack;
2525 import org.apache.logging.log4j.core.impl.ThrowableProxy;
2626 import org.apache.logging.log4j.message.Message;
27 import org.apache.logging.log4j.util.ReadOnlyStringMap;
2728
2829
2930 /**
3233 public abstract class AbstractLogEvent implements LogEvent {
3334
3435 private static final long serialVersionUID = 1L;
36
37 @Override
38 public ReadOnlyStringMap getContextData() {
39 return null;
40 }
3541
3642 /**
3743 * Returns {@link Collections#emptyMap()}.
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core;
17
18 import java.util.List;
19
20 import org.apache.logging.log4j.core.config.Property;
21 import org.apache.logging.log4j.core.impl.ContextDataInjectorFactory;
22 import org.apache.logging.log4j.core.impl.ThreadContextDataInjector;
23 import org.apache.logging.log4j.util.ReadOnlyStringMap;
24 import org.apache.logging.log4j.util.StringMap;
25
26 /**
27 * Responsible for initializing the context data of LogEvents. Context data is data that is set by the application to be
28 * included in all subsequent log events.
29 * <p>
30 * The source of the context data is implementation-specific. The default source for context data is the ThreadContext.
31 * </p><p>
32 * In some asynchronous models, work may be delegated to several threads, while conceptually this work shares the same
33 * context. In such models, storing context data in {@code ThreadLocal} variables is not convenient or desirable.
34 * Users can configure the {@code ContextDataInjectorFactory} to provide custom {@code ContextDataInjector} objects,
35 * in order to initialize log events with context data from any arbitrary context.
36 * </p><p>
37 * When providing a custom {@code ContextDataInjector}, be aware that the {@code ContextDataInjectorFactory} may be
38 * invoked multiple times and the various components in Log4j that need access to context data may each have their own
39 * instance of {@code ContextDataInjector}.
40 * This includes the object(s) that populate log events, but also various lookups and filters that look at
41 * context data to determine whether an event should be logged.
42 * </p><p>
43 * Implementors should take particular note of how the different methods in the interface have different thread-safety
44 * guarantees to enable optimal performance.
45 * </p>
46 *
47 * @see StringMap
48 * @see ReadOnlyStringMap
49 * @see ContextDataInjectorFactory
50 * @see org.apache.logging.log4j.ThreadContext
51 * @see ThreadContextDataInjector
52 * @since 2.7
53 */
54 public interface ContextDataInjector {
55 /**
56 * Returns a {@code StringMap} object initialized with the specified properties and the appropriate
57 * context data. The returned value may be the specified parameter or a different object.
58 * <p>
59 * This method will be called for each log event to initialize its context data and implementors should take
60 * care to make this method as performant as possible while preserving at least the following thread-safety
61 * guarantee.
62 * </p><p>
63 * Thread-safety note: The returned object can safely be passed off to another thread: future changes in the
64 * underlying context data will not be reflected in the returned object.
65 * </p><p>
66 * Example implementation:
67 * </p>
68 * <pre>
69 * public StringMap injectContextData(List<Property> properties, StringMap reusable) {
70 * if (properties == null || properties.isEmpty()) {
71 * // assume context data is stored in a copy-on-write data structure that is safe to pass to another thread
72 * return (StringMap) rawContextData();
73 * }
74 * // first copy configuration properties into the result
75 * ThreadContextDataInjector.copyProperties(properties, reusable);
76 *
77 * // then copy context data key-value pairs (may overwrite configuration properties)
78 * reusable.addAll(rawContextData());
79 * return reusable;
80 * }
81 * </pre>
82 *
83 * @param properties Properties from the log4j configuration to be added to the resulting ReadOnlyStringMap. May be
84 * {@code null} or empty
85 * @param reusable a {@code StringMap} instance that may be reused to avoid creating temporary objects
86 * @return a {@code StringMap} instance initialized with the specified properties and the appropriate
87 * context data. The returned value may be the specified parameter or a different object.
88 * @see ThreadContextDataInjector#copyProperties(List, StringMap)
89 */
90 StringMap injectContextData(final List<Property> properties, final StringMap reusable);
91
92 /**
93 * Returns a {@code ReadOnlyStringMap} object reflecting the current state of the context. Configuration properties
94 * are not included in the result.
95 * <p>
96 * This method may be called multiple times for each log event by Filters and Lookups and implementors should take
97 * care to make this method as performant as possible while preserving at least the following thread-safety
98 * guarantee.
99 * </p><p>
100 * Thread-safety note: The returned object can only be safely used <em>in the current thread</em>. Changes in the
101 * underlying context may or may not be reflected in the returned object, depending on the context data source and
102 * the implementation of this method. It is not safe to pass the returned object to another thread.
103 * </p>
104 * @return a {@code ReadOnlyStringMap} object reflecting the current state of the context
105 */
106 ReadOnlyStringMap rawContextData();
107 }
2525 * stopped, this goes into the {@link State#STOPPED} state. In most circumstances, implementation classes should
2626 * store their {@link State} in a {@code volatile} field or inside an
2727 * {@link java.util.concurrent.atomic.AtomicReference} dependent on synchronization and concurrency requirements.
28 *
29 * @see AbstractLifeCycle
2830 */
2931 public interface LifeCycle {
30
32
3133 /**
3234 * Status of a life cycle like a {@link LoggerContext}.
3335 */
4547 /** Has stopped. */
4648 STOPPED
4749 }
48
50
4951 /**
5052 * Gets the life-cycle state.
51 *
53 *
5254 * @return the life-cycle state
5355 */
5456 State getState();
5557
5658 void initialize();
57
59
5860 void start();
5961
6062 void stop();
6264 boolean isStarted();
6365
6466 boolean isStopped();
67
6568 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core;
17
18 import java.util.concurrent.TimeUnit;
19
20 /**
21 * Extends the LifeCycle interface.
22 * @since 2.7
23 */
24 public interface LifeCycle2 extends LifeCycle {
25
26 /**
27 * Blocks until all tasks have completed execution after a shutdown request, or the timeout occurs, or the current
28 * thread is interrupted, whichever happens first.
29 *
30 * @param timeout the maximum time to wait
31 * @param timeUnit the time unit of the timeout argument
32 * @return true if the receiver was stopped cleanly and normally, false otherwise.
33 * @since 2.7
34 */
35 boolean stop(long timeout, TimeUnit timeUnit);
36 }
2424 import org.apache.logging.log4j.ThreadContext;
2525 import org.apache.logging.log4j.core.impl.ThrowableProxy;
2626 import org.apache.logging.log4j.message.Message;
27 import org.apache.logging.log4j.util.ReadOnlyStringMap;
2728
2829 /**
2930 * Provides contextual information about a logged message. A LogEvent must be {@link java.io.Serializable} so that it
3738 * call, then it is provided via {@link #getThrown()}. When this class is serialized, the attached Throwable will
3839 * be wrapped into a {@link org.apache.logging.log4j.core.impl.ThrowableProxy} so that it may be safely serialized
3940 * and deserialized properly without causing problems if the exception class is not available on the other end.
41 * <p>
42 * Since version 2.7, {@link #getContextMap()} is deprecated in favor of {@link #getContextData()}, which
43 * can carry both {@code ThreadContext} data as well as other context data supplied by the
44 * {@linkplain org.apache.logging.log4j.core.impl.ContextDataInjectorFactory configured}
45 * {@link ContextDataInjector}.
46 * </p>
4047 */
4148 public interface LogEvent extends Serializable {
4249
4451 * Gets the context map (also know as Mapped Diagnostic Context or MDC).
4552 *
4653 * @return The context map, never {@code null}.
47 */
54 * @deprecated use {@link #getContextData()} instead
55 */
56 @Deprecated
4857 Map<String, String> getContextMap();
58
59 /**
60 * Returns the {@code ReadOnlyStringMap} object holding context data key-value pairs.
61 * <p>
62 * Context data (also known as Mapped Diagnostic Context or MDC) is data that is set by the application to be
63 * included in all subsequent log events. The default source for context data is the {@link ThreadContext} (and
64 * <a href="https://logging.apache.org/log4j/2.x/manual/configuration.html#PropertySubstitution">properties</a>
65 * configured on the Logger that logged the event), but users can configure a custom {@link ContextDataInjector}
66 * to inject key-value pairs from any arbitrary source.
67 *
68 * @return the {@code ReadOnlyStringMap} object holding context data key-value pairs
69 * @see ContextDataInjector
70 * @see ThreadContext
71 * @since 2.7
72 */
73 ReadOnlyStringMap getContextData();
4974
5075 /**
5176 * Gets the context stack (also known as Nested Diagnostic Context or NDC).
1515 */
1616 package org.apache.logging.log4j.core;
1717
18 import static org.apache.logging.log4j.core.util.ShutdownCallbackRegistry.SHUTDOWN_HOOK_MARKER;
19
1820 import java.beans.PropertyChangeEvent;
1921 import java.beans.PropertyChangeListener;
2022 import java.io.File;
2325 import java.util.Objects;
2426 import java.util.concurrent.ConcurrentMap;
2527 import java.util.concurrent.CopyOnWriteArrayList;
28 import java.util.concurrent.ExecutorService;
29 import java.util.concurrent.Executors;
30 import java.util.concurrent.Future;
31 import java.util.concurrent.RejectedExecutionException;
32 import java.util.concurrent.TimeUnit;
2633 import java.util.concurrent.locks.Lock;
2734 import java.util.concurrent.locks.ReentrantLock;
2835
3744 import org.apache.logging.log4j.core.impl.Log4jLogEvent;
3845 import org.apache.logging.log4j.core.jmx.Server;
3946 import org.apache.logging.log4j.core.util.Cancellable;
47 import org.apache.logging.log4j.core.util.ExecutorServices;
48 import org.apache.logging.log4j.core.util.Log4jThreadFactory;
4049 import org.apache.logging.log4j.core.util.NetUtils;
4150 import org.apache.logging.log4j.core.util.ShutdownCallbackRegistry;
4251 import org.apache.logging.log4j.message.MessageFactory;
4655 import org.apache.logging.log4j.spi.Terminable;
4756 import org.apache.logging.log4j.util.PropertiesUtil;
4857
49 import static org.apache.logging.log4j.core.util.ShutdownCallbackRegistry.*;
50
5158 /**
5259 * The LoggerContext is the anchor for the logging system. It maintains a list of all the loggers requested by
5360 * applications and a reference to the Configuration. The Configuration will contain the configured loggers, appenders,
5461 * filters, etc and will be atomically updated whenever a reconfigure occurs.
5562 */
56 public class LoggerContext extends AbstractLifeCycle implements org.apache.logging.log4j.spi.LoggerContext, Terminable,
57 ConfigurationListener {
63 public class LoggerContext extends AbstractLifeCycle
64 implements org.apache.logging.log4j.spi.LoggerContext, AutoCloseable, Terminable, ConfigurationListener {
5865
5966 /**
6067 * Property name of the property change event fired if the configuration is changed.
7178 * reference is updated.
7279 */
7380 private volatile Configuration configuration = new DefaultConfiguration();
81 private ExecutorService executorService;
82 private ExecutorService executorServiceDeamons;
7483 private Object externalContext;
7584 private String contextName;
7685 private volatile URI configLocation;
258267 this.shutdownCallback = ((ShutdownCallbackRegistry) factory).addShutdownCallback(new Runnable() {
259268 @Override
260269 public void run() {
270 @SuppressWarnings("resource")
261271 final LoggerContext context = LoggerContext.this;
262272 LOGGER.debug(SHUTDOWN_HOOK_MARKER, "Stopping LoggerContext[name={}, {}]",
263273 context.getName(), context);
281291 }
282292
283293 @Override
294 public void close() {
295 stop();
296 }
297
298 @Override
284299 public void terminate() {
285300 stop();
286301 }
287302
288303 @Override
289 public void stop() {
304 public boolean stop(final long timeout, final TimeUnit timeUnit) {
290305 LOGGER.debug("Stopping LoggerContext[name={}, {}]...", getName(), this);
291306 configLock.lock();
307 final boolean shutdownEs;
308 final boolean shutdownEsd;
292309 try {
293310 if (this.isStopped()) {
294 return;
311 return true;
295312 }
296313
297314 this.setStopping();
298315 try {
299316 Server.unregisterLoggerContext(getName()); // LOG4J2-406, LOG4J2-500
300 } catch (final Exception ex) {
301 LOGGER.error("Unable to unregister MBeans", ex);
317 } catch (final LinkageError | Exception e) {
318 // LOG4J2-1506 Hello Android, GAE
319 LOGGER.error("Unable to unregister MBeans", e);
302320 }
303321 if (shutdownCallback != null) {
304322 shutdownCallback.cancel();
307325 final Configuration prev = configuration;
308326 configuration = NULL_CONFIGURATION;
309327 updateLoggers();
310 prev.stop();
328 if (prev instanceof LifeCycle2) {
329 ((LifeCycle2) prev).stop(timeout, timeUnit);
330 } else {
331 prev.stop();
332 }
311333 externalContext = null;
312334 LogManager.getFactory().removeContext(this);
313 this.setStopped();
335 final String source = "LoggerContext \'" + getName() + "\'";
336 shutdownEs = ExecutorServices.shutdown(executorService, timeout, timeUnit, source);
337 // Do not wait for daemon threads
338 shutdownEsd = ExecutorServices.shutdown(executorServiceDeamons, -1, timeUnit, source);
314339 } finally {
315340 configLock.unlock();
341 this.setStopped();
316342 }
317343 LOGGER.debug("Stopped LoggerContext[name={}, {}]...", getName(), this);
344 return shutdownEs && shutdownEsd;
318345 }
319346
320347 /**
478505 * @return The previous Configuration.
479506 */
480507 private Configuration setConfiguration(final Configuration config) {
481 Objects.requireNonNull(config, "No Configuration was provided");
508 if (config == null) {
509 LOGGER.error("No configuration found for context '{}'.", contextName);
510 // No change, return the current configuration.
511 return this.configuration;
512 }
482513 configLock.lock();
483514 try {
484515 final Configuration prev = this.configuration;
485516 config.addListener(this);
517 executorService = Executors.newCachedThreadPool(Log4jThreadFactory.createThreadFactory(contextName));
518 executorServiceDeamons = Executors.newCachedThreadPool(Log4jThreadFactory.createDaemonThreadFactory(contextName));
519
486520 final ConcurrentMap<String, String> map = config.getComponent(Configuration.CONTEXT_PROPERTIES);
487521
488522 try { // LOG4J2-719 network access may throw android.os.NetworkOnMainThreadException
504538
505539 try {
506540 Server.reregisterMBeansAfterReconfigure();
507 } catch (final Throwable t) {
541 } catch (final LinkageError | Exception e) {
508542 // LOG4J2-716: Android has no java.lang.management
509 LOGGER.error("Could not reconfigure JMX", t);
543 LOGGER.error("Could not reconfigure JMX", e);
510544 }
511545 // AsyncLoggers update their nanoClock when the configuration changes
512546 Log4jLogEvent.setNanoClock(configuration.getNanoClock());
561595 final ClassLoader cl = ClassLoader.class.isInstance(externalContext) ? (ClassLoader) externalContext : null;
562596 LOGGER.debug("Reconfiguration started for context[name={}] at URI {} ({}) with optional ClassLoader: {}",
563597 contextName, configURI, this, cl);
564 final Configuration instance = ConfigurationFactory.getInstance().getConfiguration(contextName, configURI, cl);
565 setConfiguration(instance);
566 /*
567 * instance.start(); Configuration old = setConfiguration(instance); updateLoggers(); if (old != null) {
568 * old.stop(); }
569 */
570 final String location = configuration == null ? "?" : String.valueOf(configuration.getConfigurationSource());
571 LOGGER.debug("Reconfiguration complete for context[name={}] at URI {} ({}) with optional ClassLoader: {}",
572 contextName, location, this, cl);
598 final Configuration instance = ConfigurationFactory.getInstance().getConfiguration(this, contextName, configURI, cl);
599 if (instance == null) {
600 LOGGER.error("Reconfiguration failed: No configuration found for '{}' at '{}' in '{}'", contextName, configURI, cl);
601 } else {
602 setConfiguration(instance);
603 /*
604 * instance.start(); Configuration old = setConfiguration(instance); updateLoggers(); if (old != null) {
605 * old.stop(); }
606 */
607 final String location = configuration == null ? "?" : String.valueOf(configuration.getConfigurationSource());
608 LOGGER.debug("Reconfiguration complete for context[name={}] at URI {} ({}) with optional ClassLoader: {}",
609 contextName, location, this, cl);
610 }
573611 }
574612
575613 /**
623661 return new Logger(ctx, name, messageFactory);
624662 }
625663
664 /**
665 * Gets the executor service to submit normal tasks.
666 *
667 * @return the ExecutorService to submit normal tasks.
668 */
669 public ExecutorService getExecutorService() {
670 return executorService;
671 }
672
673 /**
674 * Gets the executor service to submit daemon tasks.
675 *
676 * @return the ExecutorService to submit normal daemon tasks.
677 */
678 public ExecutorService getExecutorServiceDeamons() {
679 return executorServiceDeamons;
680 }
681
682 /**
683 * Submits a Runnable task for normal execution and returns a Future representing that task. The Future's
684 * {@code get} method will return {@code null} upon <em>successful</em> completion.
685 *
686 * @param task the task to submit
687 * @return a Future representing pending completion of the task
688 * @throws RejectedExecutionException if the task cannot be
689 * scheduled for execution
690 * @throws NullPointerException if the task is null
691 */
692 public Future<?> submit(final Runnable task) {
693 return executorService.submit(task);
694 }
695
696 /**
697 * Submits a Runnable task for daemon execution and returns a Future representing that task. The Future's
698 * {@code get} method will return {@code null} upon <em>successful</em> completion.
699 *
700 * @param task
701 * the task to submit
702 * @return a Future representing pending completion of the task
703 * @throws RejectedExecutionException
704 * if the task cannot be scheduled for execution
705 * @throws NullPointerException
706 * if the task is null
707 */
708 public Future<?> submitDaemon(final Runnable task) {
709 return executorServiceDeamons.submit(task);
710 }
711
626712 }
2222 import org.apache.logging.log4j.core.Filter;
2323 import org.apache.logging.log4j.core.Layout;
2424 import org.apache.logging.log4j.core.LogEvent;
25 import org.apache.logging.log4j.core.config.plugins.PluginBuilderAttribute;
26 import org.apache.logging.log4j.core.config.plugins.PluginElement;
27 import org.apache.logging.log4j.core.config.plugins.validation.constraints.Required;
2528 import org.apache.logging.log4j.core.filter.AbstractFilterable;
29 import org.apache.logging.log4j.core.layout.PatternLayout;
2630 import org.apache.logging.log4j.core.util.Integers;
2731
2832 /**
3135 */
3236 public abstract class AbstractAppender extends AbstractFilterable implements Appender {
3337
38 /**
39 * Subclasses can extend this abstract Builder.
40 *
41 * @param <B> This builder class.
42 */
43 public abstract static class Builder<B extends Builder<B>> extends AbstractFilterable.Builder<B> {
44
45 @PluginBuilderAttribute
46 private boolean ignoreExceptions = true;
47
48 @PluginElement("Layout")
49 private Layout<? extends Serializable> layout;
50
51 @PluginBuilderAttribute
52 @Required
53 private String name;
54
55 public String getName() {
56 return name;
57 }
58
59 public boolean isIgnoreExceptions() {
60 return ignoreExceptions;
61 }
62
63 public Layout<? extends Serializable> getLayout() {
64 return layout;
65 }
66
67 public B withName(final String name) {
68 this.name = name;
69 return asBuilder();
70 }
71
72 public B withIgnoreExceptions(final boolean ignoreExceptions) {
73 this.ignoreExceptions = ignoreExceptions;
74 return asBuilder();
75 }
76
77 public B withLayout(final Layout<? extends Serializable> layout) {
78 this.layout = layout;
79 return asBuilder();
80 }
81
82 public Layout<? extends Serializable> getOrCreateLayout() {
83 if (layout == null) {
84 return PatternLayout.createDefaultLayout();
85 }
86 return layout;
87 }
88
89 }
90
3491 private final String name;
3592 private final boolean ignoreExceptions;
3693 private final Layout<? extends Serializable> layout;
1717
1818 import java.util.HashMap;
1919 import java.util.Map;
20 import java.util.concurrent.TimeUnit;
2021 import java.util.concurrent.locks.Lock;
2122 import java.util.concurrent.locks.ReentrantLock;
2223
2324 import org.apache.logging.log4j.Level;
2425 import org.apache.logging.log4j.Logger;
26 import org.apache.logging.log4j.core.AbstractLifeCycle;
27 import org.apache.logging.log4j.core.LoggerContext;
2528 import org.apache.logging.log4j.message.Message;
2629 import org.apache.logging.log4j.status.StatusLogger;
2730
2831 /**
2932 * Abstract base class used to register managers.
33 * <p>
34 * This class implements {@link AutoCloseable} mostly to allow unit tests to be written safely and succinctly. While
35 * managers do need to allocate resources (usually on construction) and then free these resources, a manager is longer
36 * lived than other auto-closeable objects like streams. None the less, making a manager AutoCloseable forces readers to
37 * be aware of the the pattern: allocate resources on construction and call {@link #close()} at some point.
38 * </p>
3039 */
31 public abstract class AbstractManager {
40 public abstract class AbstractManager implements AutoCloseable {
3241
3342 /**
3443 * Allow subclasses access to the status logger without creating another instance.
4756 protected int count;
4857
4958 private final String name;
50
51 protected AbstractManager(final String name) {
59
60 private final LoggerContext loggerContext;
61
62 protected AbstractManager(final LoggerContext loggerContext, final String name) {
63 this.loggerContext = loggerContext;
5264 this.name = name;
5365 LOGGER.debug("Starting {} {}", this.getClass().getSimpleName(), name);
66 }
67
68 /**
69 * Called to signify that this Manager is no longer required by an Appender.
70 */
71 @Override
72 public void close() {
73 stop(AbstractLifeCycle.DEFAULT_STOP_TIMEOUT, AbstractLifeCycle.DEFAULT_STOP_TIMEUNIT);
74 }
75
76 public boolean stop(final long timeout, final TimeUnit timeUnit) {
77 boolean stopped = true;
78 LOCK.lock();
79 try {
80 --count;
81 if (count <= 0) {
82 MAP.remove(name);
83 LOGGER.debug("Shutting down {} {}", this.getClass().getSimpleName(), getName());
84 stopped = releaseSub(timeout, timeUnit);
85 LOGGER.debug("Shut down {} {}, all resources released: {}", this.getClass().getSimpleName(), getName(), stopped);
86 }
87 } finally {
88 LOCK.unlock();
89 }
90 return stopped;
5491 }
5592
5693 /**
6299 * @param <T> The type of the Factory data.
63100 * @return A Manager with the specified name and type.
64101 */
102 // @SuppressWarnings("resource"): this is a factory method, the resource is allocated and released elsewhere.
103 @SuppressWarnings("resource")
65104 public static <M extends AbstractManager, T> M getManager(final String name, final ManagerFactory<M, T> factory,
66105 final T data) {
67106 LOCK.lock();
86125 }
87126
88127 public void updateData(final Object data) {
128 // This default implementation does nothing.
89129 }
90130
91131 /**
103143 }
104144
105145 /**
106 * May be overridden by Managers to perform processing while the Manager is being released and the
107 * lock is held.
108 */
109 protected void releaseSub() {
146 * May be overridden by managers to perform processing while the manager is being released and the
147 * lock is held. A timeout is passed for implementors to use as they see fit.
148 * @param timeout timeout
149 * @param timeUnit timeout time unit
150 * @return true if all resources were closed normally, false otherwise.
151 */
152 protected boolean releaseSub(final long timeout, final TimeUnit timeUnit) {
153 // This default implementation does nothing.
154 return true;
110155 }
111156
112157 protected int getCount() {
114159 }
115160
116161 /**
162 * Gets the logger context used to create this instance or null. The logger context is usually set when an appender
163 * creates a manager and that appender is given a Configuration. Not all appenders are given a Configuration by
164 * their factory method or builder.
165 *
166 * @return the logger context used to create this instance or null.
167 */
168 public LoggerContext getLoggerContext() {
169 return loggerContext;
170 }
171
172 /**
117173 * Called to signify that this Manager is no longer required by an Appender.
118 */
174 * @deprecated In 2.7, use {@link #close()}.
175 */
176 @Deprecated
119177 public void release() {
120 LOCK.lock();
121 try {
122 --count;
123 if (count <= 0) {
124 MAP.remove(name);
125 LOGGER.debug("Shutting down {} {}", this.getClass().getSimpleName(), getName());
126 releaseSub();
127 }
128 } finally {
129 LOCK.unlock();
130 }
178 close();
131179 }
132180
133181 /**
1616 package org.apache.logging.log4j.core.appender;
1717
1818 import java.io.Serializable;
19 import java.util.concurrent.TimeUnit;
1920
2021 import org.apache.logging.log4j.core.Filter;
2122 import org.apache.logging.log4j.core.Layout;
2223 import org.apache.logging.log4j.core.LogEvent;
24 import org.apache.logging.log4j.core.config.plugins.PluginBuilderAttribute;
2325 import org.apache.logging.log4j.core.util.Constants;
2426
2527 /**
2931 */
3032 public abstract class AbstractOutputStreamAppender<M extends OutputStreamManager> extends AbstractAppender {
3133
34 /**
35 * Subclasses can extend this abstract Builder.
36 *
37 * @param <B> This builder class.
38 */
39 public abstract static class Builder<B extends Builder<B>> extends AbstractAppender.Builder<B> {
40
41 @PluginBuilderAttribute
42 private boolean bufferedIo = true;
43
44 @PluginBuilderAttribute
45 private int bufferSize = Constants.ENCODER_BYTE_BUFFER_SIZE;
46
47 @PluginBuilderAttribute
48 private boolean immediateFlush = true;
49
50 public int getBufferSize() {
51 return bufferSize;
52 }
53
54 public boolean isBufferedIo() {
55 return bufferedIo;
56 }
57
58 public boolean isImmediateFlush() {
59 return immediateFlush;
60 }
61
62 public B withImmediateFlush(final boolean immediateFlush) {
63 this.immediateFlush = immediateFlush;
64 return asBuilder();
65 }
66
67 public B withBufferedIo(final boolean bufferedIo) {
68 this.bufferedIo = bufferedIo;
69 return asBuilder();
70 }
71
72 public B withBufferSize(final int bufferSize) {
73 this.bufferSize = bufferSize;
74 return asBuilder();
75 }
76
77 }
78
3279 /**
3380 * Immediate flush means that the underlying writer or output stream will be flushed at the end of each append
3481 * operation. Immediate flush is slower but ensures that each append request is actually written. If
84131 }
85132
86133 @Override
87 public void stop() {
88 super.stop();
89 manager.release();
134 public boolean stop(final long timeout, final TimeUnit timeUnit) {
135 return stop(timeout, timeUnit, true);
136 }
137
138 @Override
139 protected boolean stop(final long timeout, final TimeUnit timeUnit, final boolean changeLifeCycleState) {
140 boolean stopped = super.stop(timeout, timeUnit, changeLifeCycleState);
141 stopped &= manager.stop(timeout, timeUnit);
142 if (changeLifeCycleState) {
143 setStopped();
144 }
145 return stopped;
90146 }
91147
92148 /**
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.appender;
17
18 import java.util.concurrent.locks.Lock;
19 import java.util.concurrent.locks.ReadWriteLock;
20 import java.util.concurrent.locks.ReentrantReadWriteLock;
21
22 import org.apache.logging.log4j.core.Filter;
23 import org.apache.logging.log4j.core.LogEvent;
24 import org.apache.logging.log4j.core.StringLayout;
25
26 /**
27 * Appends log events as strings to a writer.
28 *
29 * @param <M>
30 * The kind of {@link WriterManager} under management
31 */
32 public abstract class AbstractWriterAppender<M extends WriterManager> extends AbstractAppender {
33
34 /**
35 * Immediate flush means that the underlying writer will be flushed at the
36 * end of each append operation. Immediate flush is slower but ensures that
37 * each append request is actually written. If <code>immediateFlush</code>
38 * is set to {@code false}, then there is a good chance that the last few
39 * logs events are not actually written to persistent media if and when the
40 * application crashes.
41 */
42 protected final boolean immediateFlush;
43 private final M manager;
44 private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
45 private final Lock readLock = readWriteLock.readLock();
46
47 /**
48 * Instantiates.
49 *
50 * @param name
51 * The name of the Appender.
52 * @param layout
53 * The layout to format the message.
54 * @param manager
55 * The OutputStreamManager.
56 */
57 protected AbstractWriterAppender(final String name, final StringLayout layout, final Filter filter,
58 final boolean ignoreExceptions, final boolean immediateFlush, final M manager) {
59 super(name, filter, layout, ignoreExceptions);
60 this.manager = manager;
61 this.immediateFlush = immediateFlush;
62 }
63
64 /**
65 * Actual writing occurs here.
66 * <p>
67 * Most subclasses will need to override this method.
68 * </p>
69 *
70 * @param event
71 * The LogEvent.
72 */
73 @Override
74 public void append(final LogEvent event) {
75 readLock.lock();
76 try {
77 final String str = getStringLayout().toSerializable(event);
78 if (str.length() > 0) {
79 manager.write(str);
80 if (this.immediateFlush || event.isEndOfBatch()) {
81 manager.flush();
82 }
83 }
84 } catch (final AppenderLoggingException ex) {
85 error("Unable to write " + manager.getName() + " for appender " + getName() + ": " + ex);
86 throw ex;
87 } finally {
88 readLock.unlock();
89 }
90 }
91
92 /**
93 * Gets the manager.
94 *
95 * @return the manager.
96 */
97 public M getManager() {
98 return manager;
99 }
100
101 public StringLayout getStringLayout() {
102 return (StringLayout) getLayout();
103 }
104
105 @Override
106 public void start() {
107 if (getLayout() == null) {
108 LOGGER.error("No layout set for the appender named [{}].", getName());
109 }
110 if (manager == null) {
111 LOGGER.error("No OutputStreamManager set for the appender named [{}].", getName());
112 }
113 super.start();
114 }
115
116 @Override
117 public void stop() {
118 super.stop();
119 manager.release();
120 }
121 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.appender;
17
18 import java.util.concurrent.TimeUnit;
19 import java.util.concurrent.locks.Lock;
20 import java.util.concurrent.locks.ReadWriteLock;
21 import java.util.concurrent.locks.ReentrantReadWriteLock;
22
23 import org.apache.logging.log4j.core.Filter;
24 import org.apache.logging.log4j.core.LogEvent;
25 import org.apache.logging.log4j.core.StringLayout;
26
27 /**
28 * Appends log events as strings to a writer.
29 *
30 * @param <M>
31 * The kind of {@link WriterManager} under management
32 */
33 public abstract class AbstractWriterAppender<M extends WriterManager> extends AbstractAppender {
34
35 /**
36 * Immediate flush means that the underlying writer will be flushed at the
37 * end of each append operation. Immediate flush is slower but ensures that
38 * each append request is actually written. If <code>immediateFlush</code>
39 * is set to {@code false}, then there is a good chance that the last few
40 * logs events are not actually written to persistent media if and when the
41 * application crashes.
42 */
43 protected final boolean immediateFlush;
44 private final M manager;
45 private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
46 private final Lock readLock = readWriteLock.readLock();
47
48 /**
49 * Instantiates.
50 *
51 * @param name
52 * The name of the Appender.
53 * @param layout
54 * The layout to format the message.
55 * @param manager
56 * The OutputStreamManager.
57 */
58 protected AbstractWriterAppender(final String name, final StringLayout layout, final Filter filter,
59 final boolean ignoreExceptions, final boolean immediateFlush, final M manager) {
60 super(name, filter, layout, ignoreExceptions);
61 this.manager = manager;
62 this.immediateFlush = immediateFlush;
63 }
64
65 /**
66 * Actual writing occurs here.
67 * <p>
68 * Most subclasses will need to override this method.
69 * </p>
70 *
71 * @param event
72 * The LogEvent.
73 */
74 @Override
75 public void append(final LogEvent event) {
76 readLock.lock();
77 try {
78 final String str = getStringLayout().toSerializable(event);
79 if (str.length() > 0) {
80 manager.write(str);
81 if (this.immediateFlush || event.isEndOfBatch()) {
82 manager.flush();
83 }
84 }
85 } catch (final AppenderLoggingException ex) {
86 error("Unable to write " + manager.getName() + " for appender " + getName() + ": " + ex);
87 throw ex;
88 } finally {
89 readLock.unlock();
90 }
91 }
92
93 /**
94 * Gets the manager.
95 *
96 * @return the manager.
97 */
98 public M getManager() {
99 return manager;
100 }
101
102 public StringLayout getStringLayout() {
103 return (StringLayout) getLayout();
104 }
105
106 @Override
107 public void start() {
108 if (getLayout() == null) {
109 LOGGER.error("No layout set for the appender named [{}].", getName());
110 }
111 if (manager == null) {
112 LOGGER.error("No OutputStreamManager set for the appender named [{}].", getName());
113 }
114 super.start();
115 }
116
117 @Override
118 public boolean stop(final long timeout, final TimeUnit timeUnit) {
119 setStopping();
120 boolean stopped = super.stop(timeout, timeUnit, false);
121 stopped &= manager.stop(timeout, timeUnit);
122 setStopped();
123 return stopped;
124 }
125 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.appender;
17
18 import java.util.HashMap;
19 import java.util.List;
20 import java.util.Map;
21
22 import org.apache.logging.log4j.core.Appender;
23 import org.apache.logging.log4j.core.config.Configuration;
24 import org.apache.logging.log4j.core.config.Node;
25 import org.apache.logging.log4j.core.config.plugins.Plugin;
26 import org.apache.logging.log4j.core.config.plugins.PluginBuilderFactory;
27 import org.apache.logging.log4j.core.config.plugins.PluginConfiguration;
28 import org.apache.logging.log4j.core.config.plugins.PluginNode;
29 import org.apache.logging.log4j.core.config.plugins.validation.constraints.Required;
30 import org.apache.logging.log4j.status.StatusLogger;
31
32 /**
33 * A deferred plugin for appenders.
34 */
35 @Plugin(name = "AppenderSet", category = "Core", printObject = true, deferChildren = true)
36 public class AppenderSet {
37
38 public static class Builder implements org.apache.logging.log4j.core.util.Builder<AppenderSet> {
39
40 @PluginNode
41 private Node node;
42
43 @PluginConfiguration
44 @Required
45 private Configuration configuration;
46
47 @Override
48 public AppenderSet build() {
49 if (configuration == null) {
50 LOGGER.error("Configuration is missing from AppenderSet {}", this);
51 return null;
52 }
53 if (node == null) {
54 LOGGER.error("No node in AppenderSet {}", this);
55 return null;
56 }
57 final List<Node> children = node.getChildren();
58 if (children == null) {
59 LOGGER.error("No children node in AppenderSet {}", this);
60 return null;
61 }
62 final Map<String, Node> map = new HashMap<>(children.size());
63 for (final Node childNode : children) {
64 final String key = childNode.getAttributes().get("name");
65 if (key == null) {
66 LOGGER.error("The attribute 'name' is missing from from the node {} in AppenderSet {}",
67 childNode, children);
68 } else {
69 map.put(key, childNode);
70 }
71 }
72 return new AppenderSet(configuration, map);
73 }
74
75 public Node getNode() {
76 return node;
77 }
78
79 public Configuration getConfiguration() {
80 return configuration;
81 }
82
83 public Builder withNode(@SuppressWarnings("hiding") final Node node) {
84 this.node = node;
85 return this;
86 }
87
88 public Builder withConfiguration(@SuppressWarnings("hiding") final Configuration configuration) {
89 this.configuration = configuration;
90 return this;
91 }
92
93 @Override
94 public String toString() {
95 return getClass().getName() + " [node=" + node + ", configuration=" + configuration + "]";
96 }
97
98 }
99
100 private static final StatusLogger LOGGER = StatusLogger.getLogger();
101
102 private final Configuration configuration;
103 private final Map<String, Node> nodeMap;
104
105 @PluginBuilderFactory
106 public static Builder newBuilder() {
107 return new Builder();
108 }
109
110 private AppenderSet(final Configuration configuration, final Map<String, Node> appenders) {
111 this.configuration = configuration;
112 this.nodeMap = appenders;
113 }
114
115 public Appender createAppender(final String appenderName, final String actualName) {
116 final Node node = nodeMap.get(appenderName);
117 if (node == null) {
118 LOGGER.error("No node named {} in {}", appenderName, this);
119 return null;
120 }
121 node.getAttributes().put("name", actualName);
122 if (node.getType().getElementName().equals(Appender.ELEMENT_TYPE)) {
123 final Node appNode = new Node(node);
124 configuration.createConfiguration(appNode, null);
125 if (appNode.getObject() instanceof Appender) {
126 final Appender app = appNode.getObject();
127 app.start();
128 return app;
129 }
130 LOGGER.error("Unable to create Appender of type " + node.getName());
131 return null;
132 }
133 LOGGER.error("No Appender was configured for name {} " + appenderName);
134 return null;
135 }
136 }
1818 import java.util.ArrayList;
1919 import java.util.List;
2020 import java.util.Map;
21 import java.util.concurrent.ArrayBlockingQueue;
2221 import java.util.concurrent.BlockingQueue;
22 import java.util.concurrent.TimeUnit;
23 import java.util.concurrent.TransferQueue;
2324 import java.util.concurrent.atomic.AtomicLong;
2425
2526 import org.apache.logging.log4j.core.AbstractLogEvent;
2627 import org.apache.logging.log4j.core.Appender;
2728 import org.apache.logging.log4j.core.Filter;
2829 import org.apache.logging.log4j.core.LogEvent;
30 import org.apache.logging.log4j.core.async.ArrayBlockingQueueFactory;
2931 import org.apache.logging.log4j.core.async.AsyncQueueFullPolicy;
3032 import org.apache.logging.log4j.core.async.AsyncQueueFullPolicyFactory;
33 import org.apache.logging.log4j.core.async.BlockingQueueFactory;
3134 import org.apache.logging.log4j.core.async.DiscardingAsyncQueueFullPolicy;
3235 import org.apache.logging.log4j.core.async.EventRoute;
3336 import org.apache.logging.log4j.core.config.AppenderControl;
3639 import org.apache.logging.log4j.core.config.ConfigurationException;
3740 import org.apache.logging.log4j.core.config.plugins.Plugin;
3841 import org.apache.logging.log4j.core.config.plugins.PluginAliases;
39 import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
42 import org.apache.logging.log4j.core.config.plugins.PluginBuilderAttribute;
43 import org.apache.logging.log4j.core.config.plugins.PluginBuilderFactory;
4044 import org.apache.logging.log4j.core.config.plugins.PluginConfiguration;
4145 import org.apache.logging.log4j.core.config.plugins.PluginElement;
42 import org.apache.logging.log4j.core.config.plugins.PluginFactory;
46 import org.apache.logging.log4j.core.config.plugins.validation.constraints.Required;
4347 import org.apache.logging.log4j.core.impl.Log4jLogEvent;
4448 import org.apache.logging.log4j.core.util.Constants;
49 import org.apache.logging.log4j.core.util.Log4jThread;
4550
4651 /**
4752 * Appends to one or more Appenders asynchronously. You can configure an AsyncAppender with one or more Appenders and an
4853 * Appender to append to if the queue is full. The AsyncAppender does not allow a filter to be specified on the Appender
4954 * references.
5055 */
51 @Plugin(name = "Async", category = "Core", elementType = "appender", printObject = true)
56 @Plugin(name = "Async", category = "Core", elementType = Appender.ELEMENT_TYPE, printObject = true)
5257 public final class AsyncAppender extends AbstractAppender {
5358
5459 private static final int DEFAULT_QUEUE_SIZE = 128;
7176
7277 private AsyncAppender(final String name, final Filter filter, final AppenderRef[] appenderRefs,
7378 final String errorRef, final int queueSize, final boolean blocking,
74 final boolean ignoreExceptions,
75 final long shutdownTimeout, final Configuration config, final boolean includeLocation) {
79 final boolean ignoreExceptions, final long shutdownTimeout, final Configuration config,
80 final boolean includeLocation, final BlockingQueueFactory<LogEvent> blockingQueueFactory) {
7681 super(name, filter, null, ignoreExceptions);
77 this.queue = new ArrayBlockingQueue<>(queueSize);
82 this.queue = blockingQueueFactory.create(queueSize);
7883 this.queueSize = queueSize;
7984 this.blocking = blocking;
8085 this.shutdownTimeout = shutdownTimeout;
117122 }
118123
119124 @Override
120 public void stop() {
121 super.stop();
125 public boolean stop(final long timeout, final TimeUnit timeUnit) {
126 setStopping();
127 super.stop(timeout, timeUnit, false);
122128 LOGGER.trace("AsyncAppender stopping. Queue still has {} events.", queue.size());
123129 thread.shutdown();
124130 try {
132138 LOGGER.trace("AsyncAppender: {} discarded {} events.", asyncQueueFullPolicy,
133139 DiscardingAsyncQueueFullPolicy.getDiscardCount(asyncQueueFullPolicy));
134140 }
141 setStopped();
142 return true;
135143 }
136144
137145 /**
148156 logEvent.getMessage().getFormattedMessage(); // LOG4J2-763: ask message to freeze parameters
149157 }
150158 final Log4jLogEvent memento = Log4jLogEvent.createMemento(logEvent, includeLocation);
151 if (!queue.offer(memento)) {
159 if (!transfer(memento)) {
152160 if (blocking) {
153161 // delegate to the event router (which may discard, enqueue and block, or log in current thread)
154162 final EventRoute route = asyncQueueFullPolicy.getRoute(thread.getId(), memento.getLevel());
158166 logToErrorAppenderIfNecessary(false, memento);
159167 }
160168 }
169 }
170
171 private boolean transfer(final LogEvent memento) {
172 return queue instanceof TransferQueue
173 ? ((TransferQueue<LogEvent>) queue).tryTransfer(memento)
174 : queue.offer(memento);
161175 }
162176
163177 /**
215229 }
216230
217231 /**
218 * Create an AsyncAppender.
232 * Create an AsyncAppender. This method is retained for backwards compatibility. New code should use the
233 * {@link Builder} instead. This factory will use {@link ArrayBlockingQueueFactory} by default as was the behavior
234 * pre-2.7.
219235 *
220236 * @param appenderRefs The Appenders to reference.
221237 * @param errorRef An optional Appender to write to if the queue is full or other errors occur.
230246 * @param ignoreExceptions If {@code "true"} (default) exceptions encountered when appending events are logged;
231247 * otherwise they are propagated to the caller.
232248 * @return The AsyncAppender.
233 */
234 @PluginFactory
235 public static AsyncAppender createAppender(
236 // @formatter:off
237 @PluginElement("AppenderRef") final AppenderRef[] appenderRefs,
238 @PluginAttribute("errorRef") @PluginAliases("error-ref") final String errorRef,
239 @PluginAttribute(value = "blocking", defaultBoolean = true) final boolean blocking,
240 @PluginAttribute(value = "shutdownTimeout", defaultLong = 0L) final long shutdownTimeout,
241 @PluginAttribute(value = "bufferSize", defaultInt = DEFAULT_QUEUE_SIZE) final int size,
242 @PluginAttribute("name") final String name,
243 @PluginAttribute(value = "includeLocation", defaultBoolean = false) final boolean includeLocation,
244 @PluginElement("Filter") final Filter filter,
245 @PluginConfiguration final Configuration config,
246 @PluginAttribute(value = "ignoreExceptions", defaultBoolean = true) final boolean ignoreExceptions) {
247 // @formatter:on
249 * @deprecated use {@link Builder} instead
250 */
251 @Deprecated
252 public static AsyncAppender createAppender(final AppenderRef[] appenderRefs, final String errorRef,
253 final boolean blocking, final long shutdownTimeout, final int size,
254 final String name, final boolean includeLocation, final Filter filter,
255 final Configuration config, final boolean ignoreExceptions) {
248256 if (name == null) {
249257 LOGGER.error("No name provided for AsyncAppender");
250258 return null;
254262 }
255263
256264 return new AsyncAppender(name, filter, appenderRefs, errorRef, size, blocking, ignoreExceptions,
257 shutdownTimeout, config, includeLocation);
265 shutdownTimeout, config, includeLocation, new ArrayBlockingQueueFactory<LogEvent>());
266 }
267
268 @PluginBuilderFactory
269 public static Builder newBuilder() {
270 return new Builder();
271 }
272
273 public static class Builder implements org.apache.logging.log4j.core.util.Builder<AsyncAppender> {
274
275 @PluginElement("AppenderRef")
276 @Required(message = "No appender references provided to AsyncAppender")
277 private AppenderRef[] appenderRefs;
278
279 @PluginBuilderAttribute
280 @PluginAliases("error-ref")
281 private String errorRef;
282
283 @PluginBuilderAttribute
284 private boolean blocking = true;
285
286 @PluginBuilderAttribute
287 private long shutdownTimeout = 0L;
288
289 @PluginBuilderAttribute
290 private int bufferSize = DEFAULT_QUEUE_SIZE;
291
292 @PluginBuilderAttribute
293 @Required(message = "No name provided for AsyncAppender")
294 private String name;
295
296 @PluginBuilderAttribute
297 private boolean includeLocation = false;
298
299 @PluginElement("Filter")
300 private Filter filter;
301
302 @PluginConfiguration
303 private Configuration configuration;
304
305 @PluginBuilderAttribute
306 private boolean ignoreExceptions = true;
307
308 @PluginElement(BlockingQueueFactory.ELEMENT_TYPE)
309 private BlockingQueueFactory<LogEvent> blockingQueueFactory = new ArrayBlockingQueueFactory<>();
310
311 public Builder setAppenderRefs(final AppenderRef[] appenderRefs) {
312 this.appenderRefs = appenderRefs;
313 return this;
314 }
315
316 public Builder setErrorRef(final String errorRef) {
317 this.errorRef = errorRef;
318 return this;
319 }
320
321 public Builder setBlocking(final boolean blocking) {
322 this.blocking = blocking;
323 return this;
324 }
325
326 public Builder setShutdownTimeout(final long shutdownTimeout) {
327 this.shutdownTimeout = shutdownTimeout;
328 return this;
329 }
330
331 public Builder setBufferSize(final int bufferSize) {
332 this.bufferSize = bufferSize;
333 return this;
334 }
335
336 public Builder setName(final String name) {
337 this.name = name;
338 return this;
339 }
340
341 public Builder setIncludeLocation(final boolean includeLocation) {
342 this.includeLocation = includeLocation;
343 return this;
344 }
345
346 public Builder setFilter(final Filter filter) {
347 this.filter = filter;
348 return this;
349 }
350
351 public Builder setConfiguration(final Configuration configuration) {
352 this.configuration = configuration;
353 return this;
354 }
355
356 public Builder setIgnoreExceptions(final boolean ignoreExceptions) {
357 this.ignoreExceptions = ignoreExceptions;
358 return this;
359 }
360
361 public Builder setBlockingQueueFactory(final BlockingQueueFactory<LogEvent> blockingQueueFactory) {
362 this.blockingQueueFactory = blockingQueueFactory;
363 return this;
364 }
365
366 @Override
367 public AsyncAppender build() {
368 return new AsyncAppender(name, filter, appenderRefs, errorRef, bufferSize, blocking, ignoreExceptions,
369 shutdownTimeout, configuration, includeLocation, blockingQueueFactory);
370 }
258371 }
259372
260373 /**
261374 * Thread that calls the Appenders.
262375 */
263 private class AsyncThread extends Thread {
376 private class AsyncThread extends Log4jThread {
264377
265378 private volatile boolean shutdown = false;
266379 private final List<AppenderControl> appenders;
267380 private final BlockingQueue<LogEvent> queue;
268381
269382 public AsyncThread(final List<AppenderControl> appenders, final BlockingQueue<LogEvent> queue) {
383 super("AsyncAppender-" + THREAD_SEQUENCE.getAndIncrement());
270384 this.appenders = appenders;
271385 this.queue = queue;
272386 setDaemon(true);
273 setName("AsyncAppenderThread" + THREAD_SEQUENCE.getAndIncrement());
274387 }
275388
276389 @Override
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.appender;
17
18 import org.apache.logging.log4j.core.LoggerContext;
19 import org.apache.logging.log4j.core.config.Configuration;
20
21 /**
22 * Factory Data that carries a configuration.
23 */
24 public class ConfigurationFactoryData {
25
26 /**
27 * This field is public to follow the style of existing FactoryData classes.
28 */
29 public final Configuration configuration;
30
31 public ConfigurationFactoryData(final Configuration configuration) {
32 super();
33 this.configuration = configuration;
34 }
35
36 public Configuration getConfiguration() {
37 return configuration;
38 }
39
40 /**
41 * Gets the LoggerContext from the Configuration or null.
42 *
43 * @return the LoggerContext from the Configuration or null.
44 */
45 public LoggerContext getLoggerContext() {
46 return configuration != null ? configuration.getLoggerContext() : null;
47 }
48
49 }
2626 import java.nio.charset.Charset;
2727 import java.util.concurrent.atomic.AtomicInteger;
2828
29 import org.apache.logging.log4j.core.Appender;
2930 import org.apache.logging.log4j.core.Filter;
3031 import org.apache.logging.log4j.core.Layout;
3132 import org.apache.logging.log4j.core.config.plugins.Plugin;
32 import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
3333 import org.apache.logging.log4j.core.config.plugins.PluginBuilderAttribute;
3434 import org.apache.logging.log4j.core.config.plugins.PluginBuilderFactory;
35 import org.apache.logging.log4j.core.config.plugins.PluginElement;
36 import org.apache.logging.log4j.core.config.plugins.PluginFactory;
3735 import org.apache.logging.log4j.core.config.plugins.validation.constraints.Required;
3836 import org.apache.logging.log4j.core.layout.PatternLayout;
3937 import org.apache.logging.log4j.core.util.Booleans;
4038 import org.apache.logging.log4j.core.util.CloseShieldOutputStream;
41 import org.apache.logging.log4j.core.util.Loader;
39 import org.apache.logging.log4j.util.LoaderUtil;
4240 import org.apache.logging.log4j.util.PropertiesUtil;
4341
4442 /**
4947 * encoding. (RG) Encoding is handled within the Layout. Typically, a Layout will generate a String and then call
5048 * getBytes which may use a configured encoding or the system default. OTOH, a Writer cannot print byte streams.
5149 */
52 @Plugin(name = "Console", category = "Core", elementType = "appender", printObject = true)
50 @Plugin(name = ConsoleAppender.PLUGIN_NAME, category = "Core", elementType = Appender.ELEMENT_TYPE, printObject = true)
5351 public final class ConsoleAppender extends AbstractOutputStreamAppender<OutputStreamManager> {
5452
53 public static final String PLUGIN_NAME = "Console";
5554 private static final String JANSI_CLASS = "org.fusesource.jansi.WindowsAnsiOutputStream";
5655 private static ConsoleManagerFactory factory = new ConsoleManagerFactory();
5756 private static final Target DEFAULT_TARGET = Target.SYSTEM_OUT;
8685 * @param ignore If {@code "true"} (default) exceptions encountered when appending events are logged; otherwise they
8786 * are propagated to the caller.
8887 * @return The ConsoleAppender.
89 * @deprecated Use {@link #createAppender(Layout, Filter, Target, String, boolean, boolean, boolean)}.
88 * @deprecated Deprecated in 2.7; use {@link #newBuilder()}.
9089 */
9190 @Deprecated
9291 public static ConsoleAppender createAppender(Layout<? extends Serializable> layout,
121120 * @param ignoreExceptions If {@code "true"} (default) exceptions encountered when appending events are logged; otherwise they
122121 * are propagated to the caller.
123122 * @return The ConsoleAppender.
124 */
125 @PluginFactory
123 * @deprecated Deprecated in 2.7; use {@link #newBuilder()}.
124 */
125 @Deprecated
126126 public static ConsoleAppender createAppender(
127127 // @formatter:off
128 @PluginElement("Layout") Layout<? extends Serializable> layout,
129 @PluginElement("Filter") final Filter filter,
130 @PluginAttribute(value = "target") Target target,
131 @PluginAttribute("name") final String name,
132 @PluginAttribute(value = "follow", defaultBoolean = false) final boolean follow,
133 @PluginAttribute(value = "direct", defaultBoolean = false) final boolean direct,
134 @PluginAttribute(value = "ignoreExceptions", defaultBoolean = true) final boolean ignoreExceptions) {
128 Layout<? extends Serializable> layout,
129 final Filter filter,
130 Target target,
131 final String name,
132 final boolean follow,
133 final boolean direct,
134 final boolean ignoreExceptions) {
135135 // @formatter:on
136136 if (name == null) {
137137 LOGGER.error("No name provided for ConsoleAppender");
155155 }
156156
157157 @PluginBuilderFactory
158 public static Builder newBuilder() {
159 return new Builder();
158 public static <B extends Builder<B>> B newBuilder() {
159 return new Builder<B>().asBuilder();
160160 }
161161
162162 /**
163163 * Builds ConsoleAppender instances.
164 */
165 public static class Builder implements org.apache.logging.log4j.core.util.Builder<ConsoleAppender> {
166
167 @PluginElement("Layout")
168 @Required
169 private Layout<? extends Serializable> layout = PatternLayout.createDefaultLayout();
170
171 @PluginElement("Filter")
172 private Filter filter;
164 * @param <B> This builder class
165 */
166 public static class Builder<B extends Builder<B>> extends AbstractOutputStreamAppender.Builder<B>
167 implements org.apache.logging.log4j.core.util.Builder<ConsoleAppender> {
173168
174169 @PluginBuilderAttribute
175170 @Required
176171 private Target target = DEFAULT_TARGET;
177172
178173 @PluginBuilderAttribute
179 @Required
180 private String name;
174 private boolean follow;
181175
182176 @PluginBuilderAttribute
183 private boolean follow = false;
184
185 @PluginBuilderAttribute
186 private boolean direct = false;
187
188 @PluginBuilderAttribute
189 private boolean ignoreExceptions = true;
190
191 public Builder setLayout(final Layout<? extends Serializable> aLayout) {
192 this.layout = aLayout;
193 return this;
194 }
195
196 public Builder setFilter(final Filter aFilter) {
197 this.filter = aFilter;
198 return this;
199 }
200
201 public Builder setTarget(final Target aTarget) {
177 private boolean direct;
178
179 public B setTarget(final Target aTarget) {
202180 this.target = aTarget;
203 return this;
204 }
205
206 public Builder setName(final String aName) {
207 this.name = aName;
208 return this;
209 }
210
211 public Builder setFollow(final boolean shouldFollow) {
181 return asBuilder();
182 }
183
184 public B setFollow(final boolean shouldFollow) {
212185 this.follow = shouldFollow;
213 return this;
214 }
215
216 public Builder setDirect(final boolean shouldDirect) {
186 return asBuilder();
187 }
188
189 public B setDirect(final boolean shouldDirect) {
217190 this.direct = shouldDirect;
218 return this;
219 }
220
221 public Builder setIgnoreExceptions(final boolean shouldIgnoreExceptions) {
222 this.ignoreExceptions = shouldIgnoreExceptions;
223 return this;
191 return asBuilder();
224192 }
225193
226194 @Override
227195 public ConsoleAppender build() {
228196 if (follow && direct) {
229 throw new IllegalArgumentException("Cannot use both follow and direct on ConsoleAppender");
197 throw new IllegalArgumentException("Cannot use both follow and direct on ConsoleAppender '" + getName() + "'");
230198 }
231 return new ConsoleAppender(name, layout, filter, getManager(target, follow, direct, layout), ignoreExceptions, target);
199 final Layout<? extends Serializable> layout = getOrCreateLayout();
200 return new ConsoleAppender(getName(), layout, getFilter(), getManager(target, follow, direct, layout),
201 isIgnoreExceptions(), target);
232202 }
233203 }
234204
269239 }
270240 try {
271241 // We type the parameter as a wildcard to avoid a hard reference to Jansi.
272 final Class<?> clazz = Loader.loadClass(JANSI_CLASS);
242 final Class<?> clazz = LoaderUtil.loadClass(JANSI_CLASS);
273243 final Constructor<?> constructor = clazz.getConstructor(OutputStream.class);
274244 return new CloseShieldOutputStream((OutputStream) constructor.newInstance(outputStream));
275245 } catch (final ClassNotFoundException cnfe) {
1818 import java.util.Objects;
1919 import java.util.concurrent.atomic.AtomicLong;
2020
21 import org.apache.logging.log4j.core.Appender;
2122 import org.apache.logging.log4j.core.Layout;
2223 import org.apache.logging.log4j.core.LogEvent;
2324 import org.apache.logging.log4j.core.config.plugins.Plugin;
2728 /**
2829 * No-Operation Appender that counts events.
2930 */
30 @Plugin(name = "CountingNoOp", category = "Core", elementType = "appender", printObject = true)
31 @Plugin(name = "CountingNoOp", category = "Core", elementType = Appender.ELEMENT_TYPE, printObject = true)
3132 public class CountingNoOpAppender extends AbstractAppender {
3233
3334 private final AtomicLong total = new AtomicLong();
4040 * to a different appender. Hopefully it is obvious that the Appenders must be configured
4141 * to not suppress exceptions for the FailoverAppender to work.
4242 */
43 @Plugin(name = "Failover", category = "Core", elementType = "appender", printObject = true)
43 @Plugin(name = "Failover", category = "Core", elementType = Appender.ELEMENT_TYPE, printObject = true)
4444 public final class FailoverAppender extends AbstractAppender {
4545
4646 private static final int DEFAULT_INTERVAL_SECONDS = 60;
1818 import java.io.Serializable;
1919 import java.util.HashMap;
2020 import java.util.Map;
21
21 import java.util.concurrent.TimeUnit;
22
23 import org.apache.logging.log4j.core.Appender;
2224 import org.apache.logging.log4j.core.Filter;
2325 import org.apache.logging.log4j.core.Layout;
2426 import org.apache.logging.log4j.core.config.Configuration;
2527 import org.apache.logging.log4j.core.config.plugins.Plugin;
26 import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
28 import org.apache.logging.log4j.core.config.plugins.PluginBuilderAttribute;
29 import org.apache.logging.log4j.core.config.plugins.PluginBuilderFactory;
2730 import org.apache.logging.log4j.core.config.plugins.PluginConfiguration;
28 import org.apache.logging.log4j.core.config.plugins.PluginElement;
29 import org.apache.logging.log4j.core.config.plugins.PluginFactory;
30 import org.apache.logging.log4j.core.layout.PatternLayout;
31 import org.apache.logging.log4j.core.config.plugins.validation.constraints.Required;
3132 import org.apache.logging.log4j.core.net.Advertiser;
3233 import org.apache.logging.log4j.core.util.Booleans;
3334 import org.apache.logging.log4j.core.util.Integers;
3536 /**
3637 * File Appender.
3738 */
38 @Plugin(name = "File", category = "Core", elementType = "appender", printObject = true)
39 @Plugin(name = FileAppender.PLUGIN_NAME, category = "Core", elementType = Appender.ELEMENT_TYPE, printObject = true)
3940 public final class FileAppender extends AbstractOutputStreamAppender<FileManager> {
4041
42 public static final String PLUGIN_NAME = "File";
43
44 /**
45 * Builds FileAppender instances.
46 *
47 * @param <B>
48 * This builder class
49 */
50 public static class Builder<B extends Builder<B>> extends AbstractOutputStreamAppender.Builder<B>
51 implements org.apache.logging.log4j.core.util.Builder<FileAppender> {
52
53 @PluginBuilderAttribute
54 @Required
55 private String fileName;
56
57 @PluginBuilderAttribute
58 private boolean append = true;
59
60 @PluginBuilderAttribute
61 private boolean locking;
62
63 @PluginBuilderAttribute
64 private boolean advertise;
65
66 @PluginBuilderAttribute
67 private String advertiseUri;
68
69 @PluginBuilderAttribute
70 private boolean createOnDemand;
71
72 @PluginConfiguration
73 private Configuration configuration;
74
75 @Override
76 public FileAppender build() {
77 boolean bufferedIo = isBufferedIo();
78 final int bufferSize = getBufferSize();
79 if (locking && bufferedIo) {
80 LOGGER.warn("Locking and buffering are mutually exclusive. No buffering will occur for {}", fileName);
81 bufferedIo = false;
82 }
83 if (!bufferedIo && bufferSize > 0) {
84 LOGGER.warn("The bufferSize is set to {} but bufferedIo is false: {}", bufferSize, bufferedIo);
85 }
86 final Layout<? extends Serializable> layout = getOrCreateLayout();
87
88 final FileManager manager = FileManager.getFileManager(fileName, append, locking, bufferedIo, createOnDemand,
89 advertiseUri, layout, bufferSize, configuration);
90 if (manager == null) {
91 return null;
92 }
93
94 return new FileAppender(getName(), layout, getFilter(), manager, fileName, isIgnoreExceptions(),
95 !bufferedIo || isImmediateFlush(), advertise ? configuration.getAdvertiser() : null);
96 }
97
98 public String getAdvertiseUri() {
99 return advertiseUri;
100 }
101
102 public Configuration getConfiguration() {
103 return configuration;
104 }
105
106 public String getFileName() {
107 return fileName;
108 }
109
110 public boolean isAdvertise() {
111 return advertise;
112 }
113
114 public boolean isAppend() {
115 return append;
116 }
117
118 public boolean isCreateOnDemand() {
119 return createOnDemand;
120 }
121
122 public boolean isLocking() {
123 return locking;
124 }
125
126 public B withAdvertise(final boolean advertise) {
127 this.advertise = advertise;
128 return asBuilder();
129 }
130
131 public B withAdvertiseUri(final String advertiseUri) {
132 this.advertiseUri = advertiseUri;
133 return asBuilder();
134 }
135
136 public B withAppend(final boolean append) {
137 this.append = append;
138 return asBuilder();
139 }
140
141 public B withConfiguration(final Configuration config) {
142 this.configuration = config;
143 return asBuilder();
144 }
145
146 public B withFileName(final String fileName) {
147 this.fileName = fileName;
148 return asBuilder();
149 }
150
151 public B withCreateOnDemand(final boolean createOnDemand) {
152 this.createOnDemand = createOnDemand;
153 return asBuilder();
154 }
155
156 public B withLocking(final boolean locking) {
157 this.locking = locking;
158 return asBuilder();
159 }
160
161 }
162
41163 private static final int DEFAULT_BUFFER_SIZE = 8192;
42 private final String fileName;
43 private final Advertiser advertiser;
44 private Object advertisement;
45
46 private FileAppender(final String name, final Layout<? extends Serializable> layout, final Filter filter,
47 final FileManager manager, final String filename, final boolean ignoreExceptions,
48 final boolean immediateFlush, final Advertiser advertiser) {
49
50 super(name, layout, filter, ignoreExceptions, immediateFlush, manager);
51 if (advertiser != null) {
52 final Map<String, String> configuration = new HashMap<>(layout.getContentFormat());
53 configuration.putAll(manager.getContentFormat());
54 configuration.put("contentType", layout.getContentType());
55 configuration.put("name", name);
56 advertisement = advertiser.advertise(configuration);
57 }
58 this.fileName = filename;
59 this.advertiser = advertiser;
60 }
61
62 @Override
63 public void stop() {
64 super.stop();
65 if (advertiser != null) {
66 advertiser.unadvertise(advertisement);
67 }
68 }
69
70 /**
71 * Returns the file name this appender is associated with.
72 * @return The File name.
73 */
74 public String getFileName() {
75 return this.fileName;
76 }
77
164
78165 /**
79166 * Create a File Appender.
80167 * @param fileName The name and path of the file.
84171 * @param name The name of the Appender.
85172 * @param immediateFlush "true" if the contents should be flushed on every write, "false" otherwise. The default
86173 * is "true".
87 * @param ignore If {@code "true"} (default) exceptions encountered when appending events are logged; otherwise
174 * @param ignoreExceptions If {@code "true"} (default) exceptions encountered when appending events are logged; otherwise
88175 * they are propagated to the caller.
89176 * @param bufferedIo "true" if I/O should be buffered, "false" otherwise. The default is "true".
90177 * @param bufferSizeStr buffer size for buffered IO (default is 8192).
95182 * @param advertiseUri The advertised URI which can be used to retrieve the file contents.
96183 * @param config The Configuration
97184 * @return The FileAppender.
185 * @deprecated Use {@link #newBuilder()}
98186 */
99 @PluginFactory
187 @Deprecated
100188 public static FileAppender createAppender(
101189 // @formatter:off
102 @PluginAttribute("fileName") final String fileName,
103 @PluginAttribute("append") final String append,
104 @PluginAttribute("locking") final String locking,
105 @PluginAttribute("name") final String name,
106 @PluginAttribute("immediateFlush") final String immediateFlush,
107 @PluginAttribute("ignoreExceptions") final String ignore,
108 @PluginAttribute("bufferedIo") final String bufferedIo,
109 @PluginAttribute("bufferSize") final String bufferSizeStr,
110 @PluginElement("Layout") Layout<? extends Serializable> layout,
111 @PluginElement("Filter") final Filter filter,
112 @PluginAttribute("advertise") final String advertise,
113 @PluginAttribute("advertiseUri") final String advertiseUri,
114 @PluginConfiguration final Configuration config) {
190 final String fileName,
191 final String append,
192 final String locking,
193 final String name,
194 final String immediateFlush,
195 final String ignoreExceptions,
196 final String bufferedIo,
197 final String bufferSizeStr,
198 final Layout<? extends Serializable> layout,
199 final Filter filter,
200 final String advertise,
201 final String advertiseUri,
202 final Configuration config) {
203 return newBuilder()
204 .withAdvertise(Boolean.parseBoolean(advertise))
205 .withAdvertiseUri(advertiseUri)
206 .withAppend(Booleans.parseBoolean(append, true))
207 .withBufferedIo(Booleans.parseBoolean(bufferedIo, true))
208 .withBufferSize(Integers.parseInt(bufferSizeStr, DEFAULT_BUFFER_SIZE))
209 .withConfiguration(config)
210 .withFileName(fileName)
211 .withFilter(filter)
212 .withIgnoreExceptions(Booleans.parseBoolean(ignoreExceptions, true))
213 .withImmediateFlush(Booleans.parseBoolean(immediateFlush, true))
214 .withLayout(layout)
215 .withLocking(Boolean.parseBoolean(locking))
216 .withName(name)
217 .build();
115218 // @formatter:on
116 final boolean isAppend = Booleans.parseBoolean(append, true);
117 final boolean isLocking = Boolean.parseBoolean(locking);
118 boolean isBuffered = Booleans.parseBoolean(bufferedIo, true);
119 final boolean isAdvertise = Boolean.parseBoolean(advertise);
120 if (isLocking && isBuffered) {
121 if (bufferedIo != null) {
122 LOGGER.warn("Locking and buffering are mutually exclusive. No buffering will occur for " + fileName);
123 }
124 isBuffered = false;
125 }
126 final int bufferSize = Integers.parseInt(bufferSizeStr, DEFAULT_BUFFER_SIZE);
127 if (!isBuffered && bufferSize > 0) {
128 LOGGER.warn("The bufferSize is set to {} but bufferedIO is not true: {}", bufferSize, bufferedIo);
129 }
130 final boolean isFlush = Booleans.parseBoolean(immediateFlush, true);
131 final boolean ignoreExceptions = Booleans.parseBoolean(ignore, true);
132
133 if (name == null) {
134 LOGGER.error("No name provided for FileAppender");
135 return null;
136 }
137
138 if (fileName == null) {
139 LOGGER.error("No filename provided for FileAppender with name " + name);
140 return null;
141 }
142 if (layout == null) {
143 layout = PatternLayout.createDefaultLayout();
144 }
145
146 final FileManager manager = FileManager.getFileManager(fileName, isAppend, isLocking, isBuffered, advertiseUri,
147 layout, bufferSize, isFlush);
148 if (manager == null) {
149 return null;
150 }
151
152 return new FileAppender(name, layout, filter, manager, fileName, ignoreExceptions, !isBuffered || isFlush,
153 isAdvertise ? config.getAdvertiser() : null);
219 }
220
221 @PluginBuilderFactory
222 public static <B extends Builder<B>> B newBuilder() {
223 return new Builder<B>().asBuilder();
224 }
225
226 private final String fileName;
227
228 private final Advertiser advertiser;
229
230 private final Object advertisement;
231
232 private FileAppender(final String name, final Layout<? extends Serializable> layout, final Filter filter,
233 final FileManager manager, final String filename, final boolean ignoreExceptions,
234 final boolean immediateFlush, final Advertiser advertiser) {
235
236 super(name, layout, filter, ignoreExceptions, immediateFlush, manager);
237 if (advertiser != null) {
238 final Map<String, String> configuration = new HashMap<>(layout.getContentFormat());
239 configuration.putAll(manager.getContentFormat());
240 configuration.put("contentType", layout.getContentType());
241 configuration.put("name", name);
242 advertisement = advertiser.advertise(configuration);
243 } else {
244 advertisement = null;
245 }
246 this.fileName = filename;
247 this.advertiser = advertiser;
248 }
249
250 /**
251 * Returns the file name this appender is associated with.
252 * @return The File name.
253 */
254 public String getFileName() {
255 return this.fileName;
256 }
257
258 @Override
259 public boolean stop(final long timeout, final TimeUnit timeUnit) {
260 setStopping();
261 super.stop(timeout, timeUnit, false);
262 if (advertiser != null) {
263 advertiser.unadvertise(advertisement);
264 }
265 setStopped();
266 return true;
154267 }
155268 }
2828 import java.util.Map;
2929
3030 import org.apache.logging.log4j.core.Layout;
31 import org.apache.logging.log4j.core.LoggerContext;
32 import org.apache.logging.log4j.core.config.Configuration;
3133 import org.apache.logging.log4j.core.util.Constants;
3234
3335
3941 private static final FileManagerFactory FACTORY = new FileManagerFactory();
4042
4143 private final boolean isAppend;
44 private final boolean createOnDemand;
4245 private final boolean isLocking;
4346 private final String advertiseURI;
4447 private final int bufferSize;
4548
49 /**
50 * @deprecated
51 */
4652 @Deprecated
4753 protected FileManager(final String fileName, final OutputStream os, final boolean append, final boolean locking,
4854 final String advertiseURI, final Layout<? extends Serializable> layout, final int bufferSize,
5056 this(fileName, os, append, locking, advertiseURI, layout, writeHeader, ByteBuffer.wrap(new byte[bufferSize]));
5157 }
5258
53 /** @since 2.6 */
59 /**
60 * @deprecated
61 * @since 2.6
62 */
63 @Deprecated
5464 protected FileManager(final String fileName, final OutputStream os, final boolean append, final boolean locking,
5565 final String advertiseURI, final Layout<? extends Serializable> layout, final boolean writeHeader,
5666 final ByteBuffer buffer) {
5767 super(os, fileName, layout, writeHeader, buffer);
5868 this.isAppend = append;
69 this.createOnDemand = false;
70 this.isLocking = locking;
71 this.advertiseURI = advertiseURI;
72 this.bufferSize = buffer.capacity();
73 }
74
75 /**
76 * @since 2.7
77 */
78 protected FileManager(final LoggerContext loggerContext, final String fileName, final OutputStream os, final boolean append, final boolean locking,
79 final boolean createOnDemand, final String advertiseURI, final Layout<? extends Serializable> layout,
80 final boolean writeHeader, final ByteBuffer buffer) {
81 super(loggerContext, os, fileName, createOnDemand, layout, writeHeader, buffer);
82 this.isAppend = append;
83 this.createOnDemand = createOnDemand;
5984 this.isLocking = locking;
6085 this.advertiseURI = advertiseURI;
6186 this.bufferSize = buffer.capacity();
6792 * @param append true if the file should be appended to, false if it should be overwritten.
6893 * @param locking true if the file should be locked while writing, false otherwise.
6994 * @param bufferedIo true if the contents should be buffered as they are written.
95 * @param createOnDemand true if you want to lazy-create the file (a.k.a. on-demand.)
7096 * @param advertiseUri the URI to use when advertising the file
7197 * @param layout The layout
7298 * @param bufferSize buffer size for buffered IO
73 * @param immediateFlush true if the contents should be flushed on every write, false otherwise.
99 * @param configuration The configuration.
74100 * @return A FileManager for the File.
75101 */
76102 public static FileManager getFileManager(final String fileName, final boolean append, boolean locking,
77 final boolean bufferedIo, final String advertiseUri, final Layout<? extends Serializable> layout,
78 final int bufferSize, final boolean immediateFlush) {
103 final boolean bufferedIo, final boolean createOnDemand, final String advertiseUri,
104 final Layout<? extends Serializable> layout, final int bufferSize, final Configuration configuration) {
79105
80106 if (locking && bufferedIo) {
81107 locking = false;
82108 }
83109 return (FileManager) getManager(fileName, new FactoryData(append, locking, bufferedIo, bufferSize,
84 immediateFlush, advertiseUri, layout), FACTORY);
110 createOnDemand, advertiseUri, layout, configuration), FACTORY);
85111 }
86112
87113 @Override
88 protected synchronized void write(final byte[] bytes, final int offset, final int length, final boolean immediateFlush) {
89
114 protected OutputStream createOutputStream() throws FileNotFoundException {
115 return new FileOutputStream(getFileName(), isAppend);
116 }
117
118 @Override
119 protected synchronized void write(final byte[] bytes, final int offset, final int length,
120 final boolean immediateFlush) {
90121 if (isLocking) {
91 final FileChannel channel = ((FileOutputStream) getOutputStream()).getChannel();
92122 try {
93 /* Lock the whole file. This could be optimized to only lock from the current file
94 position. Note that locking may be advisory on some systems and mandatory on others,
95 so locking just from the current position would allow reading on systems where
96 locking is mandatory. Also, Java 6 will throw an exception if the region of the
97 file is already locked by another FileChannel in the same JVM. Hopefully, that will
98 be avoided since every file should have a single file manager - unless two different
99 files strings are configured that somehow map to the same file.*/
100 final FileLock lock = channel.lock(0, Long.MAX_VALUE, false);
101 try {
123 @SuppressWarnings("resource")
124 final FileChannel channel = ((FileOutputStream) getOutputStream()).getChannel();
125 /*
126 * Lock the whole file. This could be optimized to only lock from the current file position. Note that
127 * locking may be advisory on some systems and mandatory on others, so locking just from the current
128 * position would allow reading on systems where locking is mandatory. Also, Java 6 will throw an
129 * exception if the region of the file is already locked by another FileChannel in the same JVM.
130 * Hopefully, that will be avoided since every file should have a single file manager - unless two
131 * different files strings are configured that somehow map to the same file.
132 */
133 try (final FileLock lock = channel.lock(0, Long.MAX_VALUE, false)) {
102134 super.write(bytes, offset, length, immediateFlush);
103 } finally {
104 lock.release();
105135 }
106136 } catch (final IOException ex) {
107137 throw new AppenderLoggingException("Unable to obtain lock on " + getName(), ex);
108138 }
109
110139 } else {
111140 super.write(bytes, offset, length, immediateFlush);
112141 }
126155 */
127156 public boolean isAppend() {
128157 return isAppend;
158 }
159
160 /**
161 * Returns the lazy-create.
162 * @return true if the file will be lazy-created.
163 */
164 public boolean isCreateOnDemand() {
165 return createOnDemand;
129166 }
130167
131168 /**
160197 /**
161198 * Factory Data.
162199 */
163 private static class FactoryData {
200 private static class FactoryData extends ConfigurationFactoryData {
164201 private final boolean append;
165202 private final boolean locking;
166 private final boolean bufferedIO;
203 private final boolean bufferedIo;
167204 private final int bufferSize;
168 private final boolean immediateFlush;
205 private final boolean createOnDemand;
169206 private final String advertiseURI;
170207 private final Layout<? extends Serializable> layout;
171208
173210 * Constructor.
174211 * @param append Append status.
175212 * @param locking Locking status.
176 * @param bufferedIO Buffering flag.
213 * @param bufferedIo Buffering flag.
177214 * @param bufferSize Buffer size.
178 * @param immediateFlush flush on every write or not
215 * @param createOnDemand if you want to lazy-create the file (a.k.a. on-demand.)
179216 * @param advertiseURI the URI to use when advertising the file
217 * @param layout The layout
218 * @param configuration the configuration
180219 */
181 public FactoryData(final boolean append, final boolean locking, final boolean bufferedIO, final int bufferSize,
182 final boolean immediateFlush, final String advertiseURI, final Layout<? extends Serializable> layout) {
220 public FactoryData(final boolean append, final boolean locking, final boolean bufferedIo, final int bufferSize,
221 final boolean createOnDemand, final String advertiseURI, final Layout<? extends Serializable> layout,
222 final Configuration configuration) {
223 super(configuration);
183224 this.append = append;
184225 this.locking = locking;
185 this.bufferedIO = bufferedIO;
226 this.bufferedIo = bufferedIo;
186227 this.bufferSize = bufferSize;
187 this.immediateFlush = immediateFlush;
228 this.createOnDemand = createOnDemand;
188229 this.advertiseURI = advertiseURI;
189230 this.layout = layout;
190231 }
196237 private static class FileManagerFactory implements ManagerFactory<FileManager, FactoryData> {
197238
198239 /**
199 * Create a FileManager.
240 * Creates a FileManager.
200241 * @param name The name of the File.
201242 * @param data The FactoryData
202243 * @return The FileManager for the File.
210251 }
211252
212253 final boolean writeHeader = !data.append || !file.exists();
213 OutputStream os;
214254 try {
215 os = new FileOutputStream(name, data.append);
216 final int actualSize = data.bufferedIO ? data.bufferSize : Constants.ENCODER_BYTE_BUFFER_SIZE;
217 final ByteBuffer buffer = ByteBuffer.wrap(new byte[actualSize]);
218 return new FileManager(name, os, data.append, data.locking, data.advertiseURI, data.layout,
219 writeHeader, buffer);
220 } catch (final FileNotFoundException ex) {
255 final int actualSize = data.bufferedIo ? data.bufferSize : Constants.ENCODER_BYTE_BUFFER_SIZE;
256 final ByteBuffer byteBuffer = ByteBuffer.wrap(new byte[actualSize]);
257 final FileOutputStream fos = data.createOnDemand ? null : new FileOutputStream(file, data.append);
258 return new FileManager(data.getLoggerContext(), name, fos, data.append, data.locking,
259 data.createOnDemand, data.advertiseURI, data.layout, writeHeader, byteBuffer);
260 } catch (final IOException ex) {
221261 LOGGER.error("FileManager (" + name + ") " + ex, ex);
222262 }
223263 return null;
1818 import java.io.Serializable;
1919 import java.util.HashMap;
2020 import java.util.Map;
21
21 import java.util.concurrent.TimeUnit;
22
23 import org.apache.logging.log4j.core.Appender;
2224 import org.apache.logging.log4j.core.Filter;
2325 import org.apache.logging.log4j.core.Layout;
2426 import org.apache.logging.log4j.core.LogEvent;
3840 *
3941 * @since 2.1
4042 */
41 @Plugin(name = "MemoryMappedFile", category = "Core", elementType = "appender", printObject = true)
43 @Plugin(name = "MemoryMappedFile", category = "Core", elementType = Appender.ELEMENT_TYPE, printObject = true)
4244 public final class MemoryMappedFileAppender extends AbstractOutputStreamAppender<MemoryMappedFileManager> {
4345
4446 private static final int BIT_POSITION_1GB = 30; // 2^30 ~= 1GB
6567 }
6668
6769 @Override
68 public void stop() {
69 super.stop();
70 public boolean stop(final long timeout, final TimeUnit timeUnit) {
71 setStopping();
72 super.stop(timeout, timeUnit, false);
7073 if (advertiser != null) {
7174 advertiser.unadvertise(advertisement);
7275 }
76 setStopped();
77 return true;
7378 }
7479
7580 /**
145145 this.byteBuffer = mappedBuffer;
146146 mappingOffset = offset;
147147 } catch (final Exception ex) {
148 logError("unable to remap", ex);
148 logError("Unable to remap", ex);
149149 }
150150 }
151151
155155 }
156156
157157 @Override
158 public synchronized void close() {
158 public synchronized boolean closeOutputStream() {
159159 final long position = mappedBuffer.position();
160160 final long length = mappingOffset + position;
161161 try {
162162 unsafeUnmap(mappedBuffer);
163163 } catch (final Exception ex) {
164 logError("unable to unmap MappedBuffer", ex);
164 logError("Unable to unmap MappedBuffer", ex);
165165 }
166166 try {
167167 LOGGER.debug("MMapAppender closing. Setting {} length to {} (offset {} + position {})", getFileName(),
168168 length, mappingOffset, position);
169169 randomAccessFile.setLength(length);
170170 randomAccessFile.close();
171 return true;
171172 } catch (final IOException ex) {
172 logError("unable to close MemoryMappedFile", ex);
173 logError("Unable to close MemoryMappedFile", ex);
174 return false;
173175 }
174176 }
175177
338340 }
339341
340342 final boolean writeHeader = !data.append || !file.exists();
341 final OutputStream os = NullOutputStream.NULL_OUTPUT_STREAM;
343 final OutputStream os = NullOutputStream.getInstance();
342344 RandomAccessFile raf = null;
343345 try {
344346 raf = new RandomAccessFile(name, "rw");
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.appender;
17
18 import org.apache.logging.log4j.core.Appender;
19 import org.apache.logging.log4j.core.LogEvent;
20 import org.apache.logging.log4j.core.config.plugins.Plugin;
21 import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
22 import org.apache.logging.log4j.core.config.plugins.PluginFactory;
23
24 /**
25 * An Appender that ignores log events. Use for compatibility with version 1.2.
26 */
27 @Plugin(name = NullAppender.PLUGIN_NAME, category = "Core", elementType = Appender.ELEMENT_TYPE, printObject = true)
28 public class NullAppender extends AbstractAppender {
29
30 public static final String PLUGIN_NAME = "Null";
31
32 @PluginFactory
33 public static NullAppender createAppender(@PluginAttribute("name") final String name) {
34 return new NullAppender(name);
35 }
36
37 private NullAppender(final String name) {
38 super(name, null, null);
39 // Do nothing
40 }
41
42 @Override
43 public void append(LogEvent event) {
44 // Do nothing
45 }
46
47 }
1818 import java.io.OutputStream;
1919 import java.io.Serializable;
2020
21 import org.apache.logging.log4j.core.Appender;
2122 import org.apache.logging.log4j.core.Filter;
2223 import org.apache.logging.log4j.core.Layout;
2324 import org.apache.logging.log4j.core.config.plugins.Plugin;
3233 * Character encoding is handled within the Layout.
3334 * </p>
3435 */
35 @Plugin(name = "OutputStream", category = "Core", elementType = "appender", printObject = true)
36 @Plugin(name = "OutputStream", category = "Core", elementType = Appender.ELEMENT_TYPE, printObject = true)
3637 public final class OutputStreamAppender extends AbstractOutputStreamAppender<OutputStreamManager> {
3738
3839 /**
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.appender;
17
18 import java.io.IOException;
19 import java.io.OutputStream;
20 import java.nio.ByteBuffer;
21 import java.util.Objects;
22
23 import org.apache.logging.log4j.core.Layout;
24 import org.apache.logging.log4j.core.layout.ByteBufferDestination;
25 import org.apache.logging.log4j.core.util.Constants;
26
27 /**
28 * Manages an OutputStream so that it can be shared by multiple Appenders and will
29 * allow appenders to reconfigure without requiring a new stream.
30 */
31 public class OutputStreamManager extends AbstractManager implements ByteBufferDestination {
32 protected final Layout<?> layout;
33 protected ByteBuffer byteBuffer;
34 private volatile OutputStream os;
35 private boolean skipFooter;
36
37 protected OutputStreamManager(final OutputStream os, final String streamName, final Layout<?> layout,
38 final boolean writeHeader) {
39 this(os, streamName, layout, writeHeader, ByteBuffer.wrap(new byte[Constants.ENCODER_BYTE_BUFFER_SIZE]));
40 }
41
42 /**
43 *
44 * @param os
45 * @param streamName
46 * @param layout
47 * @param writeHeader
48 * @param byteBuffer
49 * @since 2.6
50 */
51 protected OutputStreamManager(final OutputStream os, final String streamName, final Layout<?> layout,
52 final boolean writeHeader, final ByteBuffer byteBuffer) {
53 super(streamName);
54 this.os = os;
55 this.layout = layout;
56 if (writeHeader && layout != null) {
57 final byte[] header = layout.getHeader();
58 if (header != null) {
59 try {
60 this.os.write(header, 0, header.length);
61 } catch (final IOException e) {
62 logError("Unable to write header", e);
63 }
64 }
65 }
66 this.byteBuffer = Objects.requireNonNull(byteBuffer, "byteBuffer");
67 }
68
69 /**
70 * Creates a Manager.
71 *
72 * @param name The name of the stream to manage.
73 * @param data The data to pass to the Manager.
74 * @param factory The factory to use to create the Manager.
75 * @param <T> The type of the OutputStreamManager.
76 * @return An OutputStreamManager.
77 */
78 public static <T> OutputStreamManager getManager(final String name, final T data,
79 final ManagerFactory<? extends OutputStreamManager, T> factory) {
80 return AbstractManager.getManager(name, factory, data);
81 }
82
83 /**
84 * Indicate whether the footer should be skipped or not.
85 * @param skipFooter true if the footer should be skipped.
86 */
87 public void skipFooter(final boolean skipFooter) {
88 this.skipFooter = skipFooter;
89 }
90
91 /**
92 * Default hook to write footer during close.
93 */
94 @Override
95 public void releaseSub() {
96 writeFooter();
97 close();
98 }
99
100 /**
101 * Writes the footer.
102 */
103 protected void writeFooter() {
104 if (layout == null || skipFooter) {
105 return;
106 }
107 final byte[] footer = layout.getFooter();
108 if (footer != null) {
109 write(footer);
110 }
111 }
112
113 /**
114 * Returns the status of the stream.
115 * @return true if the stream is open, false if it is not.
116 */
117 public boolean isOpen() {
118 return getCount() > 0;
119 }
120
121 protected OutputStream getOutputStream() {
122 return os;
123 }
124
125 protected void setOutputStream(final OutputStream os) {
126 final byte[] header = layout.getHeader();
127 if (header != null) {
128 try {
129 os.write(header, 0, header.length);
130 this.os = os; // only update field if os.write() succeeded
131 } catch (final IOException ioe) {
132 logError("Unable to write header", ioe);
133 }
134 } else {
135 this.os = os;
136 }
137 }
138
139 /**
140 * Some output streams synchronize writes while others do not.
141 * @param bytes The serialized Log event.
142 * @throws AppenderLoggingException if an error occurs.
143 */
144 protected void write(final byte[] bytes) {
145 write(bytes, 0, bytes.length, false);
146 }
147
148 /**
149 * Some output streams synchronize writes while others do not.
150 * @param bytes The serialized Log event.
151 * @param immediateFlush If true, flushes after writing.
152 * @throws AppenderLoggingException if an error occurs.
153 */
154 protected void write(final byte[] bytes, final boolean immediateFlush) {
155 write(bytes, 0, bytes.length, immediateFlush);
156 }
157
158 /**
159 * Some output streams synchronize writes while others do not. Synchronizing here insures that
160 * log events won't be intertwined.
161 * @param bytes The serialized Log event.
162 * @param offset The offset into the byte array.
163 * @param length The number of bytes to write.
164 * @throws AppenderLoggingException if an error occurs.
165 */
166 protected void write(final byte[] bytes, final int offset, final int length) {
167 write(bytes, offset, length, false);
168 }
169
170 /**
171 * Some output streams synchronize writes while others do not. Synchronizing here insures that
172 * log events won't be intertwined.
173 * @param bytes The serialized Log event.
174 * @param offset The offset into the byte array.
175 * @param length The number of bytes to write.
176 * @param immediateFlush flushes immediately after writing.
177 * @throws AppenderLoggingException if an error occurs.
178 */
179 protected synchronized void write(final byte[] bytes, final int offset, final int length, final boolean immediateFlush) {
180 if (immediateFlush && byteBuffer.position() == 0) {
181 writeToDestination(bytes, offset, length);
182 flushDestination();
183 return;
184 }
185 if (length >= byteBuffer.capacity()) {
186 // if request length exceeds buffer capacity, flush the buffer and write the data directly
187 flush();
188 writeToDestination(bytes, offset, length);
189 } else {
190 if (length > byteBuffer.remaining()) {
191 flush();
192 }
193 byteBuffer.put(bytes, offset, length);
194 }
195 if (immediateFlush) {
196 flush();
197 }
198 }
199
200 /**
201 * Writes the specified section of the specified byte array to the stream.
202 *
203 * @param bytes the array containing data
204 * @param offset from where to write
205 * @param length how many bytes to write
206 * @since 2.6
207 */
208 protected synchronized void writeToDestination(final byte[] bytes, final int offset, final int length) {
209 try {
210 os.write(bytes, offset, length);
211 } catch (final IOException ex) {
212 final String msg = "Error writing to stream " + getName();
213 throw new AppenderLoggingException(msg, ex);
214 }
215 }
216
217 /**
218 * Calls {@code flush()} on the underlying output stream.
219 * @since 2.6
220 */
221 protected synchronized void flushDestination() {
222 try {
223 os.flush();
224 } catch (final IOException ex) {
225 final String msg = "Error flushing stream " + getName();
226 throw new AppenderLoggingException(msg, ex);
227 }
228 }
229
230 /**
231 * Drains the ByteBufferDestination's buffer into the destination. By default this calls
232 * {@link OutputStreamManager#write(byte[], int, int, boolean)} with the buffer contents.
233 * The underlying stream is not {@linkplain OutputStream#flush() flushed}.
234 *
235 * @see #flushDestination()
236 * @since 2.6
237 */
238 protected synchronized void flushBuffer(final ByteBuffer buf) {
239 buf.flip();
240 if (buf.limit() > 0) {
241 writeToDestination(buf.array(), 0, buf.limit());
242 }
243 buf.clear();
244 }
245
246 /**
247 * Flushes any buffers.
248 */
249 public synchronized void flush() {
250 flushBuffer(byteBuffer);
251 flushDestination();
252 }
253
254 protected synchronized void close() {
255 flush();
256 final OutputStream stream = os; // access volatile field only once per method
257 if (stream == System.out || stream == System.err) {
258 return;
259 }
260 try {
261 stream.close();
262 } catch (final IOException ex) {
263 logError("Unable to close stream", ex);
264 }
265 }
266
267 /**
268 * Returns this {@code ByteBufferDestination}'s buffer.
269 * @return the buffer
270 * @since 2.6
271 */
272 @Override
273 public ByteBuffer getByteBuffer() {
274 return byteBuffer;
275 }
276
277 /**
278 * Drains the ByteBufferDestination's buffer into the destination. By default this calls
279 * {@link #flushBuffer(ByteBuffer)} with the specified buffer. Subclasses may override.
280 * <p>
281 * Do not call this method lightly! For some subclasses this is a very expensive operation. For example,
282 * {@link MemoryMappedFileManager} will assume this method was called because the end of the mapped region
283 * was reached during a text encoding operation and will {@linkplain MemoryMappedFileManager#remap() remap} its
284 * buffer.
285 * </p><p>
286 * To just flush the buffered contents to the underlying stream, call
287 * {@link #flushBuffer(ByteBuffer)} directly instead.
288 * </p>
289 *
290 * @param buf the buffer whose contents to write the the destination
291 * @return the specified buffer
292 * @since 2.6
293 */
294 @Override
295 public ByteBuffer drain(final ByteBuffer buf) {
296 flushBuffer(buf);
297 return buf;
298 }
299 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.appender;
17
18 import java.io.IOException;
19 import java.io.OutputStream;
20 import java.io.Serializable;
21 import java.nio.ByteBuffer;
22 import java.util.Objects;
23 import java.util.concurrent.TimeUnit;
24
25 import org.apache.logging.log4j.core.Layout;
26 import org.apache.logging.log4j.core.LoggerContext;
27 import org.apache.logging.log4j.core.layout.ByteBufferDestination;
28 import org.apache.logging.log4j.core.util.Constants;
29
30 /**
31 * Manages an OutputStream so that it can be shared by multiple Appenders and will
32 * allow appenders to reconfigure without requiring a new stream.
33 */
34 public class OutputStreamManager extends AbstractManager implements ByteBufferDestination {
35 protected final Layout<?> layout;
36 protected ByteBuffer byteBuffer;
37 private volatile OutputStream os;
38 private boolean skipFooter;
39
40 protected OutputStreamManager(final OutputStream os, final String streamName, final Layout<?> layout,
41 final boolean writeHeader) {
42 // Can't use new ctor because it throws an exception
43 this(os, streamName, layout, writeHeader, Constants.ENCODER_BYTE_BUFFER_SIZE);
44 }
45
46 protected OutputStreamManager(final OutputStream os, final String streamName, final Layout<?> layout,
47 final boolean writeHeader, final int bufferSize) {
48 // Can't use new ctor because it throws an exception
49 this(os, streamName, layout, writeHeader, ByteBuffer.wrap(new byte[bufferSize]));
50 }
51
52 /**
53 * @since 2.6
54 * @deprecated
55 */
56 @Deprecated
57 protected OutputStreamManager(final OutputStream os, final String streamName, final Layout<?> layout,
58 final boolean writeHeader, final ByteBuffer byteBuffer) {
59 super(null, streamName);
60 this.os = os;
61 this.layout = layout;
62 if (writeHeader && layout != null) {
63 final byte[] header = layout.getHeader();
64 if (header != null) {
65 try {
66 getOutputStream().write(header, 0, header.length);
67 } catch (final IOException e) {
68 logError("Unable to write header", e);
69 }
70 }
71 }
72 this.byteBuffer = Objects.requireNonNull(byteBuffer, "byteBuffer");
73 }
74
75 /**
76 * @since 2.7
77 */
78 protected OutputStreamManager(final LoggerContext loggerContext, final OutputStream os, final String streamName,
79 final boolean createOnDemand, final Layout<? extends Serializable> layout, final boolean writeHeader,
80 final ByteBuffer byteBuffer) {
81 super(loggerContext, streamName);
82 if (createOnDemand && os != null) {
83 LOGGER.error(
84 "Invalid OutputStreamManager configuration for '{}': You cannot both set the OutputStream and request on-demand.",
85 streamName);
86 }
87 this.layout = layout;
88 this.byteBuffer = Objects.requireNonNull(byteBuffer, "byteBuffer");
89 this.os = os;
90 if (writeHeader && layout != null) {
91 final byte[] header = layout.getHeader();
92 if (header != null) {
93 try {
94 getOutputStream().write(header, 0, header.length);
95 } catch (final IOException e) {
96 logError("Unable to write header for " + streamName, e);
97 }
98 }
99 }
100 }
101
102 /**
103 * Creates a Manager.
104 *
105 * @param name The name of the stream to manage.
106 * @param data The data to pass to the Manager.
107 * @param factory The factory to use to create the Manager.
108 * @param <T> The type of the OutputStreamManager.
109 * @return An OutputStreamManager.
110 */
111 public static <T> OutputStreamManager getManager(final String name, final T data,
112 final ManagerFactory<? extends OutputStreamManager, T> factory) {
113 return AbstractManager.getManager(name, factory, data);
114 }
115
116 @SuppressWarnings("unused")
117 protected OutputStream createOutputStream() throws IOException {
118 throw new IllegalStateException(getClass().getCanonicalName() + " must implement createOutputStream()");
119 }
120
121 /**
122 * Indicate whether the footer should be skipped or not.
123 * @param skipFooter true if the footer should be skipped.
124 */
125 public void skipFooter(final boolean skipFooter) {
126 this.skipFooter = skipFooter;
127 }
128
129 /**
130 * Default hook to write footer during close.
131 */
132 @Override
133 public boolean releaseSub(final long timeout, final TimeUnit timeUnit) {
134 writeFooter();
135 return closeOutputStream();
136 }
137
138 /**
139 * Writes the footer.
140 */
141 protected void writeFooter() {
142 if (layout == null || skipFooter) {
143 return;
144 }
145 final byte[] footer = layout.getFooter();
146 if (footer != null) {
147 write(footer);
148 }
149 }
150
151 /**
152 * Returns the status of the stream.
153 * @return true if the stream is open, false if it is not.
154 */
155 public boolean isOpen() {
156 return getCount() > 0;
157 }
158
159 protected OutputStream getOutputStream() throws IOException {
160 if (os == null) {
161 os = createOutputStream();
162 }
163 return os;
164 }
165
166 protected void setOutputStream(final OutputStream os) {
167 final byte[] header = layout.getHeader();
168 if (header != null) {
169 try {
170 os.write(header, 0, header.length);
171 this.os = os; // only update field if os.write() succeeded
172 } catch (final IOException ioe) {
173 logError("Unable to write header", ioe);
174 }
175 } else {
176 this.os = os;
177 }
178 }
179
180 /**
181 * Some output streams synchronize writes while others do not.
182 * @param bytes The serialized Log event.
183 * @throws AppenderLoggingException if an error occurs.
184 */
185 protected void write(final byte[] bytes) {
186 write(bytes, 0, bytes.length, false);
187 }
188
189 /**
190 * Some output streams synchronize writes while others do not.
191 * @param bytes The serialized Log event.
192 * @param immediateFlush If true, flushes after writing.
193 * @throws AppenderLoggingException if an error occurs.
194 */
195 protected void write(final byte[] bytes, final boolean immediateFlush) {
196 write(bytes, 0, bytes.length, immediateFlush);
197 }
198
199 /**
200 * Some output streams synchronize writes while others do not. Synchronizing here insures that
201 * log events won't be intertwined.
202 * @param bytes The serialized Log event.
203 * @param offset The offset into the byte array.
204 * @param length The number of bytes to write.
205 * @throws AppenderLoggingException if an error occurs.
206 */
207 protected void write(final byte[] bytes, final int offset, final int length) {
208 write(bytes, offset, length, false);
209 }
210
211 /**
212 * Some output streams synchronize writes while others do not. Synchronizing here insures that
213 * log events won't be intertwined.
214 * @param bytes The serialized Log event.
215 * @param offset The offset into the byte array.
216 * @param length The number of bytes to write.
217 * @param immediateFlush flushes immediately after writing.
218 * @throws AppenderLoggingException if an error occurs.
219 */
220 protected synchronized void write(final byte[] bytes, final int offset, final int length, final boolean immediateFlush) {
221 if (immediateFlush && byteBuffer.position() == 0) {
222 writeToDestination(bytes, offset, length);
223 flushDestination();
224 return;
225 }
226 if (length >= byteBuffer.capacity()) {
227 // if request length exceeds buffer capacity, flush the buffer and write the data directly
228 flush();
229 writeToDestination(bytes, offset, length);
230 } else {
231 if (length > byteBuffer.remaining()) {
232 flush();
233 }
234 byteBuffer.put(bytes, offset, length);
235 }
236 if (immediateFlush) {
237 flush();
238 }
239 }
240
241 /**
242 * Writes the specified section of the specified byte array to the stream.
243 *
244 * @param bytes the array containing data
245 * @param offset from where to write
246 * @param length how many bytes to write
247 * @since 2.6
248 */
249 protected synchronized void writeToDestination(final byte[] bytes, final int offset, final int length) {
250 try {
251 getOutputStream().write(bytes, offset, length);
252 } catch (final IOException ex) {
253 throw new AppenderLoggingException("Error writing to stream " + getName(), ex);
254 }
255 }
256
257 /**
258 * Calls {@code flush()} on the underlying output stream.
259 * @since 2.6
260 */
261 protected synchronized void flushDestination() {
262 final OutputStream stream = os; // access volatile field only once per method
263 if (stream != null) {
264 try {
265 stream.flush();
266 } catch (final IOException ex) {
267 throw new AppenderLoggingException("Error flushing stream " + getName(), ex);
268 }
269 }
270 }
271
272 /**
273 * Drains the ByteBufferDestination's buffer into the destination. By default this calls
274 * {@link OutputStreamManager#write(byte[], int, int, boolean)} with the buffer contents.
275 * The underlying stream is not {@linkplain OutputStream#flush() flushed}.
276 *
277 * @see #flushDestination()
278 * @since 2.6
279 */
280 protected synchronized void flushBuffer(final ByteBuffer buf) {
281 buf.flip();
282 if (buf.limit() > 0) {
283 writeToDestination(buf.array(), 0, buf.limit());
284 }
285 buf.clear();
286 }
287
288 /**
289 * Flushes any buffers.
290 */
291 public synchronized void flush() {
292 flushBuffer(byteBuffer);
293 flushDestination();
294 }
295
296 protected synchronized boolean closeOutputStream() {
297 flush();
298 final OutputStream stream = os; // access volatile field only once per method
299 if (stream == null || stream == System.out || stream == System.err) {
300 return true;
301 }
302 try {
303 stream.close();
304 } catch (final IOException ex) {
305 logError("Unable to close stream", ex);
306 return false;
307 }
308 return true;
309 }
310
311 /**
312 * Returns this {@code ByteBufferDestination}'s buffer.
313 * @return the buffer
314 * @since 2.6
315 */
316 @Override
317 public ByteBuffer getByteBuffer() {
318 return byteBuffer;
319 }
320
321 /**
322 * Drains the ByteBufferDestination's buffer into the destination. By default this calls
323 * {@link #flushBuffer(ByteBuffer)} with the specified buffer. Subclasses may override.
324 * <p>
325 * Do not call this method lightly! For some subclasses this is a very expensive operation. For example,
326 * {@link MemoryMappedFileManager} will assume this method was called because the end of the mapped region
327 * was reached during a text encoding operation and will {@linkplain MemoryMappedFileManager#remap() remap} its
328 * buffer.
329 * </p><p>
330 * To just flush the buffered contents to the underlying stream, call
331 * {@link #flushBuffer(ByteBuffer)} directly instead.
332 * </p>
333 *
334 * @param buf the buffer whose contents to write the the destination
335 * @return the specified buffer
336 * @since 2.6
337 */
338 @Override
339 public ByteBuffer drain(final ByteBuffer buf) {
340 flushBuffer(buf);
341 return buf;
342 }
343 }
1818 import java.io.Serializable;
1919 import java.util.HashMap;
2020 import java.util.Map;
21 import java.util.concurrent.TimeUnit;
2122
23 import org.apache.logging.log4j.core.Appender;
2224 import org.apache.logging.log4j.core.Filter;
2325 import org.apache.logging.log4j.core.Layout;
2426 import org.apache.logging.log4j.core.LogEvent;
3638 /**
3739 * File Appender.
3840 */
39 @Plugin(name = "RandomAccessFile", category = "Core", elementType = "appender", printObject = true)
41 @Plugin(name = "RandomAccessFile", category = "Core", elementType = Appender.ELEMENT_TYPE, printObject = true)
4042 public final class RandomAccessFileAppender extends AbstractOutputStreamAppender<RandomAccessFileManager> {
4143
4244 private final String fileName;
6163 }
6264
6365 @Override
64 public void stop() {
65 super.stop();
66 public boolean stop(final long timeout, final TimeUnit timeUnit) {
67 setStopping();
68 super.stop(timeout, timeUnit, false);
6669 if (advertiser != null) {
6770 advertiser.unadvertise(advertisement);
6871 }
72 setStopped();
73 return true;
6974 }
7075
7176 /**
155160 }
156161
157162 if (fileName == null) {
158 LOGGER.error("No filename provided for FileAppender with name "
159 + name);
163 LOGGER.error("No filename provided for FileAppender with name " + name);
160164 return null;
161165 }
162166 if (layout == null) {
163167 layout = PatternLayout.createDefaultLayout();
164168 }
165 final RandomAccessFileManager manager = RandomAccessFileManager.getFileManager(
166 fileName, isAppend, isFlush, bufferSize, advertiseURI, layout
167 );
169 final RandomAccessFileManager manager = RandomAccessFileManager.getFileManager(fileName, isAppend, isFlush,
170 bufferSize, advertiseURI, layout, null);
168171 if (manager == null) {
169172 return null;
170173 }
171174
172 return new RandomAccessFileAppender(
173 name, layout, filter, manager, fileName, ignoreExceptions, isFlush,
174 isAdvertise ? config.getAdvertiser() : null
175 );
175 return new RandomAccessFileAppender(name, layout, filter, manager, fileName, ignoreExceptions, isFlush,
176 isAdvertise ? config.getAdvertiser() : null);
176177 }
177178 }
2525 import java.util.Map;
2626
2727 import org.apache.logging.log4j.core.Layout;
28 import org.apache.logging.log4j.core.LoggerContext;
29 import org.apache.logging.log4j.core.config.Configuration;
2830 import org.apache.logging.log4j.core.util.NullOutputStream;
2931
3032 /**
4143 private final RandomAccessFile randomAccessFile;
4244 private final ThreadLocal<Boolean> isEndOfBatch = new ThreadLocal<>();
4345
44 protected RandomAccessFileManager(final RandomAccessFile file,
45 final String fileName, final OutputStream os, final int bufferSize,
46 final String advertiseURI, final Layout<? extends Serializable> layout, final boolean writeHeader) {
47 super(os, fileName, layout, writeHeader, ByteBuffer.wrap(new byte[bufferSize]));
46 protected RandomAccessFileManager(final LoggerContext loggerContext, final RandomAccessFile file, final String fileName,
47 final OutputStream os, final int bufferSize, final String advertiseURI,
48 final Layout<? extends Serializable> layout, final boolean writeHeader) {
49 super(loggerContext, os, fileName, false, layout, writeHeader, ByteBuffer.wrap(new byte[bufferSize]));
4850 this.randomAccessFile = file;
4951 this.advertiseURI = advertiseURI;
5052 this.isEndOfBatch.set(Boolean.FALSE);
6163 * @param bufferSize The buffer size.
6264 * @param advertiseURI the URI to use when advertising the file
6365 * @param layout The layout.
66 * @param configuration The configuration.
6467 * @return A RandomAccessFileManager for the File.
6568 */
6669 public static RandomAccessFileManager getFileManager(final String fileName, final boolean append,
6770 final boolean isFlush, final int bufferSize, final String advertiseURI,
68 final Layout<? extends Serializable> layout) {
71 final Layout<? extends Serializable> layout, final Configuration configuration) {
6972 return (RandomAccessFileManager) getManager(fileName, new FactoryData(append,
70 isFlush, bufferSize, advertiseURI, layout), FACTORY);
73 isFlush, bufferSize, advertiseURI, layout, configuration), FACTORY);
7174 }
7275
7376 public Boolean isEndOfBatch() {
9497 }
9598
9699 @Override
97 public synchronized void close() {
100 public synchronized boolean closeOutputStream() {
98101 flush();
99102 try {
100103 randomAccessFile.close();
104 return true;
101105 } catch (final IOException ex) {
102 logError("unable to close RandomAccessFile", ex);
106 logError("Unable to close RandomAccessFile", ex);
107 return false;
103108 }
104109 }
105110
139144 /**
140145 * Factory Data.
141146 */
142 private static class FactoryData {
147 private static class FactoryData extends ConfigurationFactoryData {
143148 private final boolean append;
144149 private final boolean immediateFlush;
145150 private final int bufferSize;
151156 *
152157 * @param append Append status.
153158 * @param bufferSize size of the buffer
159 * @param configuration The configuration.
154160 */
155 public FactoryData(final boolean append, final boolean immediateFlush,
156 final int bufferSize, final String advertiseURI, final Layout<? extends Serializable> layout) {
161 public FactoryData(final boolean append, final boolean immediateFlush, final int bufferSize,
162 final String advertiseURI, final Layout<? extends Serializable> layout, final Configuration configuration) {
163 super(configuration);
157164 this.append = append;
158165 this.immediateFlush = immediateFlush;
159166 this.bufferSize = bufferSize;
187194 }
188195
189196 final boolean writeHeader = !data.append || !file.exists();
190 final OutputStream os = NullOutputStream.NULL_OUTPUT_STREAM;
197 final OutputStream os = NullOutputStream.getInstance();
191198 RandomAccessFile raf;
192199 try {
193200 raf = new RandomAccessFile(name, "rw");
196203 } else {
197204 raf.setLength(0);
198205 }
199 return new RandomAccessFileManager(raf, name, os,
200 data.bufferSize, data.advertiseURI, data.layout, writeHeader);
206 return new RandomAccessFileManager(data.getLoggerContext(), raf, name,
207 os, data.bufferSize, data.advertiseURI, data.layout, writeHeader);
201208 } catch (final Exception ex) {
202209 LOGGER.error("RandomAccessFileManager (" + name + ") " + ex, ex);
203210 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.appender;
17
18 import java.io.Serializable;
19 import java.util.HashMap;
20 import java.util.Map;
21 import java.util.zip.Deflater;
22
23 import org.apache.logging.log4j.core.Filter;
24 import org.apache.logging.log4j.core.Layout;
25 import org.apache.logging.log4j.core.LogEvent;
26 import org.apache.logging.log4j.core.appender.rolling.DefaultRolloverStrategy;
27 import org.apache.logging.log4j.core.appender.rolling.RollingFileManager;
28 import org.apache.logging.log4j.core.appender.rolling.RolloverStrategy;
29 import org.apache.logging.log4j.core.appender.rolling.TriggeringPolicy;
30 import org.apache.logging.log4j.core.config.Configuration;
31 import org.apache.logging.log4j.core.config.plugins.Plugin;
32 import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
33 import org.apache.logging.log4j.core.config.plugins.PluginConfiguration;
34 import org.apache.logging.log4j.core.config.plugins.PluginElement;
35 import org.apache.logging.log4j.core.config.plugins.PluginFactory;
36 import org.apache.logging.log4j.core.layout.PatternLayout;
37 import org.apache.logging.log4j.core.net.Advertiser;
38 import org.apache.logging.log4j.core.util.Booleans;
39 import org.apache.logging.log4j.core.util.Integers;
40
41 /**
42 * An appender that writes to files and can roll over at intervals.
43 */
44 @Plugin(name = "RollingFile", category = "Core", elementType = "appender", printObject = true)
45 public final class RollingFileAppender extends AbstractOutputStreamAppender<RollingFileManager> {
46
47 private static final int DEFAULT_BUFFER_SIZE = 8192;
48
49 private final String fileName;
50 private final String filePattern;
51 private Object advertisement;
52 private final Advertiser advertiser;
53
54 private RollingFileAppender(final String name, final Layout<? extends Serializable> layout, final Filter filter,
55 final RollingFileManager manager, final String fileName, final String filePattern,
56 final boolean ignoreExceptions, final boolean immediateFlush, final Advertiser advertiser) {
57 super(name, layout, filter, ignoreExceptions, immediateFlush, manager);
58 if (advertiser != null) {
59 final Map<String, String> configuration = new HashMap<>(layout.getContentFormat());
60 configuration.put("contentType", layout.getContentType());
61 configuration.put("name", name);
62 advertisement = advertiser.advertise(configuration);
63 }
64 this.fileName = fileName;
65 this.filePattern = filePattern;
66 this.advertiser = advertiser;
67 }
68
69 @Override
70 public void stop() {
71 super.stop();
72 if (advertiser != null) {
73 advertiser.unadvertise(advertisement);
74 }
75 }
76
77 /**
78 * Write the log entry rolling over the file when required.
79
80 * @param event The LogEvent.
81 */
82 @Override
83 public void append(final LogEvent event) {
84 getManager().checkRollover(event);
85 super.append(event);
86 }
87
88 /**
89 * Returns the File name for the Appender.
90 * @return The file name.
91 */
92 public String getFileName() {
93 return fileName;
94 }
95
96 /**
97 * Returns the file pattern used when rolling over.
98 * @return The file pattern.
99 */
100 public String getFilePattern() {
101 return filePattern;
102 }
103
104 /**
105 * Returns the triggering policy.
106 * @param <T> TriggeringPolicy type
107 * @return The TriggeringPolicy
108 */
109 public <T extends TriggeringPolicy> T getTriggeringPolicy() {
110 return getManager().getTriggeringPolicy();
111 }
112
113 /**
114 * Create a RollingFileAppender.
115 * @param fileName The name of the file that is actively written to. (required).
116 * @param filePattern The pattern of the file name to use on rollover. (required).
117 * @param append If true, events are appended to the file. If false, the file
118 * is overwritten when opened. Defaults to "true"
119 * @param name The name of the Appender (required).
120 * @param bufferedIO When true, I/O will be buffered. Defaults to "true".
121 * @param bufferSizeStr buffer size for buffered IO (default is 8192).
122 * @param immediateFlush When true, events are immediately flushed. Defaults to "true".
123 * @param policy The triggering policy. (required).
124 * @param strategy The rollover strategy. Defaults to DefaultRolloverStrategy.
125 * @param layout The layout to use (defaults to the default PatternLayout).
126 * @param filter The Filter or null.
127 * @param ignore If {@code "true"} (default) exceptions encountered when appending events are logged; otherwise
128 * they are propagated to the caller.
129 * @param advertise "true" if the appender configuration should be advertised, "false" otherwise.
130 * @param advertiseURI The advertised URI which can be used to retrieve the file contents.
131 * @param config The Configuration.
132 * @return A RollingFileAppender.
133 */
134 @PluginFactory
135 public static RollingFileAppender createAppender(
136 @PluginAttribute("fileName") final String fileName,
137 @PluginAttribute("filePattern") final String filePattern,
138 @PluginAttribute("append") final String append,
139 @PluginAttribute("name") final String name,
140 @PluginAttribute("bufferedIO") final String bufferedIO,
141 @PluginAttribute("bufferSize") final String bufferSizeStr,
142 @PluginAttribute("immediateFlush") final String immediateFlush,
143 @PluginElement("Policy") final TriggeringPolicy policy,
144 @PluginElement("Strategy") RolloverStrategy strategy,
145 @PluginElement("Layout") Layout<? extends Serializable> layout,
146 @PluginElement("Filter") final Filter filter,
147 @PluginAttribute("ignoreExceptions") final String ignore,
148 @PluginAttribute("advertise") final String advertise,
149 @PluginAttribute("advertiseURI") final String advertiseURI,
150 @PluginConfiguration final Configuration config) {
151
152 final boolean isAppend = Booleans.parseBoolean(append, true);
153 final boolean ignoreExceptions = Booleans.parseBoolean(ignore, true);
154 final boolean isBuffered = Booleans.parseBoolean(bufferedIO, true);
155 final boolean isFlush = Booleans.parseBoolean(immediateFlush, true);
156 final boolean isAdvertise = Boolean.parseBoolean(advertise);
157 final int bufferSize = Integers.parseInt(bufferSizeStr, DEFAULT_BUFFER_SIZE);
158 if (!isBuffered && bufferSize > 0) {
159 LOGGER.warn("The bufferSize is set to {} but bufferedIO is not true: {}", bufferSize, bufferedIO);
160 }
161 if (name == null) {
162 LOGGER.error("No name provided for FileAppender");
163 return null;
164 }
165
166 if (fileName == null) {
167 LOGGER.error("No filename was provided for FileAppender with name " + name);
168 return null;
169 }
170
171 if (filePattern == null) {
172 LOGGER.error("No filename pattern provided for FileAppender with name " + name);
173 return null;
174 }
175
176 if (policy == null) {
177 LOGGER.error("A TriggeringPolicy must be provided");
178 return null;
179 }
180
181 if (strategy == null) {
182 strategy = DefaultRolloverStrategy.createStrategy(null, null, null,
183 String.valueOf(Deflater.DEFAULT_COMPRESSION), null, true, config);
184 }
185
186 if (layout == null) {
187 layout = PatternLayout.createDefaultLayout();
188 }
189
190 final RollingFileManager manager = RollingFileManager.getFileManager(fileName, filePattern, isAppend,
191 isBuffered, policy, strategy, advertiseURI, layout, bufferSize, isFlush);
192 if (manager == null) {
193 return null;
194 }
195
196 manager.initialize();
197
198 return new RollingFileAppender(name, layout, filter, manager, fileName, filePattern,
199 ignoreExceptions, isFlush, isAdvertise ? config.getAdvertiser() : null);
200 }
201 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.appender;
17
18 import java.io.Serializable;
19 import java.util.HashMap;
20 import java.util.Map;
21 import java.util.concurrent.TimeUnit;
22 import java.util.zip.Deflater;
23
24 import org.apache.logging.log4j.core.Appender;
25 import org.apache.logging.log4j.core.Filter;
26 import org.apache.logging.log4j.core.Layout;
27 import org.apache.logging.log4j.core.LogEvent;
28 import org.apache.logging.log4j.core.appender.rolling.DefaultRolloverStrategy;
29 import org.apache.logging.log4j.core.appender.rolling.RollingFileManager;
30 import org.apache.logging.log4j.core.appender.rolling.RolloverStrategy;
31 import org.apache.logging.log4j.core.appender.rolling.TriggeringPolicy;
32 import org.apache.logging.log4j.core.config.Configuration;
33 import org.apache.logging.log4j.core.config.plugins.Plugin;
34 import org.apache.logging.log4j.core.config.plugins.PluginBuilderAttribute;
35 import org.apache.logging.log4j.core.config.plugins.PluginBuilderFactory;
36 import org.apache.logging.log4j.core.config.plugins.PluginConfiguration;
37 import org.apache.logging.log4j.core.config.plugins.PluginElement;
38 import org.apache.logging.log4j.core.config.plugins.validation.constraints.Required;
39 import org.apache.logging.log4j.core.net.Advertiser;
40 import org.apache.logging.log4j.core.util.Booleans;
41 import org.apache.logging.log4j.core.util.Integers;
42
43 /**
44 * An appender that writes to files and can roll over at intervals.
45 */
46 @Plugin(name = RollingFileAppender.PLUGIN_NAME, category = "Core", elementType = Appender.ELEMENT_TYPE, printObject = true)
47 public final class RollingFileAppender extends AbstractOutputStreamAppender<RollingFileManager> {
48
49 public static final String PLUGIN_NAME = "RollingFile";
50
51 /**
52 * Builds FileAppender instances.
53 *
54 * @param <B>
55 * This builder class
56 */
57 public static class Builder<B extends Builder<B>> extends AbstractOutputStreamAppender.Builder<B>
58 implements org.apache.logging.log4j.core.util.Builder<RollingFileAppender> {
59
60 @PluginBuilderAttribute
61 @Required
62 private String fileName;
63
64 @PluginBuilderAttribute
65 @Required
66 private String filePattern;
67
68 @PluginBuilderAttribute
69 private boolean append = true;
70
71 @PluginBuilderAttribute
72 private boolean locking;
73
74 @PluginElement("Policy")
75 @Required
76 private TriggeringPolicy policy;
77
78 @PluginElement("Strategy")
79 private RolloverStrategy strategy;
80
81 @PluginBuilderAttribute
82 private boolean advertise;
83
84 @PluginBuilderAttribute
85 private String advertiseUri;
86
87 @PluginBuilderAttribute
88 private boolean createOnDemand;
89
90 @PluginConfiguration
91 private Configuration configuration;
92
93 @Override
94 public RollingFileAppender build() {
95 // Even though some variables may be annotated with @Required, we must still perform validation here for
96 // call sites that build builders programmatically.
97 final boolean isBufferedIo = isBufferedIo();
98 final int bufferSize = getBufferSize();
99 if (getName() == null) {
100 LOGGER.error("RollingFileAppender '{}': No name provided.", getName());
101 return null;
102 }
103
104 if (!isBufferedIo && bufferSize > 0) {
105 LOGGER.warn("RollingFileAppender '{}': The bufferSize is set to {} but bufferedIO is not true", getName(), bufferSize);
106 }
107
108 if (fileName == null) {
109 LOGGER.error("RollingFileAppender '{}': No file name provided.", getName());
110 return null;
111 }
112
113 if (filePattern == null) {
114 LOGGER.error("RollingFileAppender '{}': No file name pattern provided.", getName());
115 return null;
116 }
117
118 if (policy == null) {
119 LOGGER.error("RollingFileAppender '{}': No TriggeringPolicy provided.", getName());
120 return null;
121 }
122
123 if (strategy == null) {
124 strategy = DefaultRolloverStrategy.createStrategy(null, null, null,
125 String.valueOf(Deflater.DEFAULT_COMPRESSION), null, true, configuration);
126 }
127
128 if (strategy == null) {
129 strategy = DefaultRolloverStrategy.createStrategy(null, null, null,
130 String.valueOf(Deflater.DEFAULT_COMPRESSION), null, true, configuration);
131 }
132
133 final Layout<? extends Serializable> layout = getOrCreateLayout();
134 final RollingFileManager manager = RollingFileManager.getFileManager(fileName, filePattern, append,
135 isBufferedIo, policy, strategy, advertiseUri, layout, bufferSize, isImmediateFlush(),
136 createOnDemand, configuration);
137 if (manager == null) {
138 return null;
139 }
140
141 manager.initialize();
142
143 return new RollingFileAppender(getName(), layout, getFilter(), manager, fileName, filePattern,
144 isIgnoreExceptions(), isImmediateFlush(), advertise ? configuration.getAdvertiser() : null);
145 }
146
147 public String getAdvertiseUri() {
148 return advertiseUri;
149 }
150
151 public Configuration getConfiguration() {
152 return configuration;
153 }
154
155 public String getFileName() {
156 return fileName;
157 }
158
159 public boolean isAdvertise() {
160 return advertise;
161 }
162
163 public boolean isAppend() {
164 return append;
165 }
166
167 public boolean isCreateOnDemand() {
168 return createOnDemand;
169 }
170
171 public boolean isLocking() {
172 return locking;
173 }
174
175 public B withAdvertise(final boolean advertise) {
176 this.advertise = advertise;
177 return asBuilder();
178 }
179
180 public B withAdvertiseUri(final String advertiseUri) {
181 this.advertiseUri = advertiseUri;
182 return asBuilder();
183 }
184
185 public B withAppend(final boolean append) {
186 this.append = append;
187 return asBuilder();
188 }
189
190 public B withConfiguration(final Configuration config) {
191 this.configuration = config;
192 return asBuilder();
193 }
194
195 public B withFileName(final String fileName) {
196 this.fileName = fileName;
197 return asBuilder();
198 }
199
200 public B withCreateOnDemand(final boolean createOnDemand) {
201 this.createOnDemand = createOnDemand;
202 return asBuilder();
203 }
204
205 public B withLocking(final boolean locking) {
206 this.locking = locking;
207 return asBuilder();
208 }
209
210 public String getFilePattern() {
211 return filePattern;
212 }
213
214 public TriggeringPolicy getPolicy() {
215 return policy;
216 }
217
218 public RolloverStrategy getStrategy() {
219 return strategy;
220 }
221
222 public B withFilePattern(final String filePattern) {
223 this.filePattern = filePattern;
224 return asBuilder();
225 }
226
227 public B withPolicy(final TriggeringPolicy policy) {
228 this.policy = policy;
229 return asBuilder();
230 }
231
232 public B withStrategy(final RolloverStrategy strategy) {
233 this.strategy = strategy;
234 return asBuilder();
235 }
236
237 }
238
239 private static final int DEFAULT_BUFFER_SIZE = 8192;
240
241 private final String fileName;
242 private final String filePattern;
243 private Object advertisement;
244 private final Advertiser advertiser;
245
246 private RollingFileAppender(final String name, final Layout<? extends Serializable> layout, final Filter filter,
247 final RollingFileManager manager, final String fileName, final String filePattern,
248 final boolean ignoreExceptions, final boolean immediateFlush, final Advertiser advertiser) {
249 super(name, layout, filter, ignoreExceptions, immediateFlush, manager);
250 if (advertiser != null) {
251 final Map<String, String> configuration = new HashMap<>(layout.getContentFormat());
252 configuration.put("contentType", layout.getContentType());
253 configuration.put("name", name);
254 advertisement = advertiser.advertise(configuration);
255 }
256 this.fileName = fileName;
257 this.filePattern = filePattern;
258 this.advertiser = advertiser;
259 }
260
261 @Override
262 public boolean stop(final long timeout, final TimeUnit timeUnit) {
263 setStopping();
264 final boolean stopped = super.stop(timeout, timeUnit, false);
265 if (advertiser != null) {
266 advertiser.unadvertise(advertisement);
267 }
268 setStopped();
269 return stopped;
270 }
271
272 /**
273 * Writes the log entry rolling over the file when required.
274
275 * @param event The LogEvent.
276 */
277 @Override
278 public void append(final LogEvent event) {
279 getManager().checkRollover(event);
280 super.append(event);
281 }
282
283 /**
284 * Returns the File name for the Appender.
285 * @return The file name.
286 */
287 public String getFileName() {
288 return fileName;
289 }
290
291 /**
292 * Returns the file pattern used when rolling over.
293 * @return The file pattern.
294 */
295 public String getFilePattern() {
296 return filePattern;
297 }
298
299 /**
300 * Returns the triggering policy.
301 * @param <T> TriggeringPolicy type
302 * @return The TriggeringPolicy
303 */
304 public <T extends TriggeringPolicy> T getTriggeringPolicy() {
305 return getManager().getTriggeringPolicy();
306 }
307
308 /**
309 * Creates a RollingFileAppender.
310 * @param fileName The name of the file that is actively written to. (required).
311 * @param filePattern The pattern of the file name to use on rollover. (required).
312 * @param append If true, events are appended to the file. If false, the file
313 * is overwritten when opened. Defaults to "true"
314 * @param name The name of the Appender (required).
315 * @param bufferedIO When true, I/O will be buffered. Defaults to "true".
316 * @param bufferSizeStr buffer size for buffered IO (default is 8192).
317 * @param immediateFlush When true, events are immediately flushed. Defaults to "true".
318 * @param policy The triggering policy. (required).
319 * @param strategy The rollover strategy. Defaults to DefaultRolloverStrategy.
320 * @param layout The layout to use (defaults to the default PatternLayout).
321 * @param filter The Filter or null.
322 * @param ignore If {@code "true"} (default) exceptions encountered when appending events are logged; otherwise
323 * they are propagated to the caller.
324 * @param advertise "true" if the appender configuration should be advertised, "false" otherwise.
325 * @param advertiseUri The advertised URI which can be used to retrieve the file contents.
326 * @param config The Configuration.
327 * @return A RollingFileAppender.
328 * @deprecated Use {@link #newBuilder()}.
329 */
330 @Deprecated
331 public static RollingFileAppender createAppender(
332 // @formatter:off
333 final String fileName,
334 final String filePattern,
335 final String append,
336 final String name,
337 final String bufferedIO,
338 final String bufferSizeStr,
339 final String immediateFlush,
340 final TriggeringPolicy policy,
341 final RolloverStrategy strategy,
342 final Layout<? extends Serializable> layout,
343 final Filter filter,
344 final String ignore,
345 final String advertise,
346 final String advertiseUri,
347 final Configuration config) {
348 // @formatter:on
349 final int bufferSize = Integers.parseInt(bufferSizeStr, DEFAULT_BUFFER_SIZE);
350 // @formatter:off
351 return newBuilder()
352 .withAdvertise(Boolean.parseBoolean(advertise))
353 .withAdvertiseUri(advertiseUri)
354 .withAppend(Booleans.parseBoolean(append, true))
355 .withBufferedIo(Booleans.parseBoolean(bufferedIO, true))
356 .withBufferSize(bufferSize)
357 .withConfiguration(config)
358 .withFileName(fileName)
359 .withFilePattern(filePattern)
360 .withFilter(filter)
361 .withIgnoreExceptions(Booleans.parseBoolean(ignore, true))
362 .withImmediateFlush(Booleans.parseBoolean(immediateFlush, true))
363 .withLayout(layout)
364 .withCreateOnDemand(false)
365 .withLocking(false)
366 .withName(name)
367 .withPolicy(policy)
368 .withStrategy(strategy)
369 .build();
370 // @formatter:on
371 }
372
373 @PluginBuilderFactory
374 public static <B extends Builder<B>> B newBuilder() {
375 return new Builder<B>().asBuilder();
376 }
377 }
1818 import java.io.Serializable;
1919 import java.util.HashMap;
2020 import java.util.Map;
21 import java.util.concurrent.TimeUnit;
2122 import java.util.zip.Deflater;
2223
24 import org.apache.logging.log4j.core.Appender;
2325 import org.apache.logging.log4j.core.Filter;
2426 import org.apache.logging.log4j.core.Layout;
2527 import org.apache.logging.log4j.core.LogEvent;
4244 * An appender that writes to random access files and can roll over at
4345 * intervals.
4446 */
45 @Plugin(name = "RollingRandomAccessFile", category = "Core", elementType = "appender", printObject = true)
47 @Plugin(name = "RollingRandomAccessFile", category = "Core", elementType = Appender.ELEMENT_TYPE, printObject = true)
4648 public final class RollingRandomAccessFileAppender extends AbstractOutputStreamAppender<RollingRandomAccessFileManager> {
4749
4850 private final String fileName;
6971 }
7072
7173 @Override
72 public void stop() {
73 super.stop();
74 public boolean stop(final long timeout, final TimeUnit timeUnit) {
75 setStopping();
76 super.stop(timeout, timeUnit, false);
7477 if (advertiser != null) {
7578 advertiser.unadvertise(advertisement);
7679 }
80 setStopped();
81 return true;
7782 }
7883
7984 /**
204209 }
205210
206211 final RollingRandomAccessFileManager manager = RollingRandomAccessFileManager.getRollingRandomAccessFileManager(
207 fileName, filePattern, isAppend, isFlush, bufferSize, policy, strategy, advertiseURI, layout);
212 fileName, filePattern, isAppend, isFlush, bufferSize, policy, strategy, advertiseURI, layout, config);
208213 if (manager == null) {
209214 return null;
210215 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.appender;
17
18 import java.io.Serializable;
19 import java.util.Objects;
20
21 import javax.script.Bindings;
22
23 import org.apache.logging.log4j.core.Appender;
24 import org.apache.logging.log4j.core.Filter;
25 import org.apache.logging.log4j.core.Layout;
26 import org.apache.logging.log4j.core.LogEvent;
27 import org.apache.logging.log4j.core.config.Configuration;
28 import org.apache.logging.log4j.core.config.plugins.Plugin;
29 import org.apache.logging.log4j.core.config.plugins.PluginBuilderAttribute;
30 import org.apache.logging.log4j.core.config.plugins.PluginBuilderFactory;
31 import org.apache.logging.log4j.core.config.plugins.PluginConfiguration;
32 import org.apache.logging.log4j.core.config.plugins.PluginElement;
33 import org.apache.logging.log4j.core.config.plugins.validation.constraints.Required;
34 import org.apache.logging.log4j.core.script.AbstractScript;
35 import org.apache.logging.log4j.core.script.ScriptManager;
36
37 @Plugin(name = "ScriptAppenderSelector", category = "Core", elementType = Appender.ELEMENT_TYPE, printObject = true)
38 public class ScriptAppenderSelector extends AbstractAppender {
39
40 /**
41 * Builds an appender.
42 */
43 public static final class Builder implements org.apache.logging.log4j.core.util.Builder<Appender> {
44
45 @PluginElement("AppenderSet")
46 @Required
47 private AppenderSet appenderSet;
48
49 @PluginConfiguration
50 @Required
51 private Configuration configuration;
52
53 @PluginBuilderAttribute
54 @Required
55 private String name;
56
57 @PluginElement("Script")
58 @Required
59 private AbstractScript script;
60
61 @Override
62 public Appender build() {
63 if (name == null) {
64 LOGGER.error("Name missing.");
65 return null;
66 }
67 if (script == null) {
68 LOGGER.error("Script missing for ScriptAppenderSelector appender {}", name);
69 return null;
70 }
71 if (appenderSet == null) {
72 LOGGER.error("AppenderSet missing for ScriptAppenderSelector appender {}", name);
73 return null;
74 }
75 if (configuration == null) {
76 LOGGER.error("Configuration missing for ScriptAppenderSelector appender {}", name);
77 return null;
78 }
79 final ScriptManager scriptManager = configuration.getScriptManager();
80 scriptManager.addScript(script);
81 final Bindings bindings = scriptManager.createBindings(script);
82 final Object object = scriptManager.execute(script.getName(), bindings);
83 final String appenderName = Objects.toString(object, null);
84 final Appender appender = appenderSet.createAppender(appenderName, name);
85 return appender;
86 }
87
88 public AppenderSet getAppenderSet() {
89 return appenderSet;
90 }
91
92 public Configuration getConfiguration() {
93 return configuration;
94 }
95
96 public String getName() {
97 return name;
98 }
99
100 public AbstractScript getScript() {
101 return script;
102 }
103
104 public Builder withAppenderNodeSet(@SuppressWarnings("hiding") final AppenderSet appenderSet) {
105 this.appenderSet = appenderSet;
106 return this;
107 }
108
109 public Builder withConfiguration(@SuppressWarnings("hiding") final Configuration configuration) {
110 this.configuration = configuration;
111 return this;
112 }
113
114 public Builder withName(@SuppressWarnings("hiding") final String name) {
115 this.name = name;
116 return this;
117 }
118
119 public Builder withScript(@SuppressWarnings("hiding") final AbstractScript script) {
120 this.script = script;
121 return this;
122 }
123
124 }
125
126 @PluginBuilderFactory
127 public static Builder newBuilder() {
128 return new Builder();
129 }
130
131 private ScriptAppenderSelector(final String name, final Filter filter, final Layout<? extends Serializable> layout) {
132 super(name, filter, layout);
133 }
134
135 @Override
136 public void append(final LogEvent event) {
137 // Do nothing: This appender is only used to discover and build another appender
138 }
139
140 }
1818
1919 import java.io.Serializable;
2020
21 import org.apache.logging.log4j.core.Appender;
2122 import org.apache.logging.log4j.core.Filter;
2223 import org.apache.logging.log4j.core.Layout;
2324 import org.apache.logging.log4j.core.LogEvent;
5152 * message is appended. This can be modified by setting a filter for the
5253 * appender.
5354 */
54 @Plugin(name = "SMTP", category = "Core", elementType = "appender", printObject = true)
55 @Plugin(name = "SMTP", category = "Core", elementType = Appender.ELEMENT_TYPE, printObject = true)
5556 public final class SmtpAppender extends AbstractAppender {
5657
5758 private static final int DEFAULT_BUFFER_SIZE = 512;
1818 import java.io.Serializable;
1919 import java.util.HashMap;
2020 import java.util.Map;
21
21 import java.util.concurrent.TimeUnit;
22
23 import org.apache.logging.log4j.core.Appender;
2224 import org.apache.logging.log4j.core.Filter;
2325 import org.apache.logging.log4j.core.Layout;
2426 import org.apache.logging.log4j.core.LogEvent;
2527 import org.apache.logging.log4j.core.config.Configuration;
2628 import org.apache.logging.log4j.core.config.plugins.Plugin;
2729 import org.apache.logging.log4j.core.config.plugins.PluginAliases;
28 import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
30 import org.apache.logging.log4j.core.config.plugins.PluginBuilderAttribute;
31 import org.apache.logging.log4j.core.config.plugins.PluginBuilderFactory;
2932 import org.apache.logging.log4j.core.config.plugins.PluginConfiguration;
3033 import org.apache.logging.log4j.core.config.plugins.PluginElement;
3134 import org.apache.logging.log4j.core.config.plugins.PluginFactory;
3841 import org.apache.logging.log4j.core.net.TcpSocketManager;
3942 import org.apache.logging.log4j.core.net.ssl.SslConfiguration;
4043 import org.apache.logging.log4j.core.util.Booleans;
44 import org.apache.logging.log4j.core.util.Constants;
4145
4246 /**
4347 * An Appender that delivers events over socket connections. Supports both TCP and UDP.
4448 */
45 @Plugin(name = "Socket", category = "Core", elementType = "appender", printObject = true)
49 @Plugin(name = "Socket", category = "Core", elementType = Appender.ELEMENT_TYPE, printObject = true)
4650 public class SocketAppender extends AbstractOutputStreamAppender<AbstractSocketManager> {
51
52 /**
53 * Subclasses can extend this abstract Builder.
54 *
55 * Removed deprecated "delayMillis", use "reconnectionDelayMillis".
56 * Removed deprecated "reconnectionDelay", use "reconnectionDelayMillis".
57 *
58 * @param <B>
59 * This builder class.
60 */
61 public static class Builder<B extends Builder<B>> extends AbstractOutputStreamAppender.Builder<B>
62 implements org.apache.logging.log4j.core.util.Builder<SocketAppender> {
63
64 @PluginBuilderAttribute
65 private boolean advertise;
66
67 @PluginConfiguration
68 private Configuration configuration;
69
70 @PluginBuilderAttribute
71 private int connectTimeoutMillis;
72
73 @PluginBuilderAttribute
74 private String host = "localhost";
75
76 @PluginBuilderAttribute
77 private boolean immediateFail = true;
78
79 @PluginBuilderAttribute
80 private int port;
81
82 @PluginBuilderAttribute
83 private Protocol protocol = Protocol.TCP;
84
85 @PluginBuilderAttribute
86 @PluginAliases({ "reconnectDelay, delayMillis" })
87 private int reconnectDelayMillis;
88
89 @PluginElement("SslConfiguration")
90 @PluginAliases({ "SslConfig" })
91 private SslConfiguration sslConfiguration;
92
93 @SuppressWarnings("resource")
94 @Override
95 public SocketAppender build() {
96 boolean immediateFlush = isImmediateFlush();
97 final boolean bufferedIo = isBufferedIo();
98 Layout<? extends Serializable> layout = getLayout();
99 if (layout == null) {
100 layout = SerializedLayout.createLayout();
101 }
102
103 final String name = getName();
104 if (name == null) {
105 SocketAppender.LOGGER.error("No name provided for SocketAppender");
106 return null;
107 }
108
109 final Protocol actualProtocol = protocol != null ? protocol : Protocol.TCP;
110 if (actualProtocol == Protocol.UDP) {
111 immediateFlush = true;
112 }
113
114 final AbstractSocketManager manager = SocketAppender.createSocketManager(name, actualProtocol, host, port,
115 connectTimeoutMillis, sslConfiguration, reconnectDelayMillis, immediateFail, layout, getBufferSize());
116
117 return new SocketAppender(name, layout, getFilter(), manager, isIgnoreExceptions(),
118 !bufferedIo || immediateFlush, advertise ? configuration.getAdvertiser() : null);
119 }
120
121 public boolean getAdvertise() {
122 return advertise;
123 }
124
125 public int getConnectTimeoutMillis() {
126 return connectTimeoutMillis;
127 }
128
129 public String getHost() {
130 return host;
131 }
132
133 public int getPort() {
134 return port;
135 }
136
137 public Protocol getProtocol() {
138 return protocol;
139 }
140
141 public SslConfiguration getSslConfiguration() {
142 return sslConfiguration;
143 }
144
145 public boolean getImmediateFail() {
146 return immediateFail;
147 }
148
149 public B withAdvertise(final boolean advertise) {
150 this.advertise = advertise;
151 return asBuilder();
152 }
153
154 public B withConfiguration(final Configuration configuration) {
155 this.configuration = configuration;
156 return asBuilder();
157 }
158
159 public B withConnectTimeoutMillis(final int connectTimeoutMillis) {
160 this.connectTimeoutMillis = connectTimeoutMillis;
161 return asBuilder();
162 }
163
164 public B withHost(final String host) {
165 this.host = host;
166 return asBuilder();
167 }
168
169 public B withImmediateFail(final boolean immediateFail) {
170 this.immediateFail = immediateFail;
171 return asBuilder();
172 }
173
174 public B withPort(final int port) {
175 this.port = port;
176 return asBuilder();
177 }
178
179 public B withProtocol(final Protocol protocol) {
180 this.protocol = protocol;
181 return asBuilder();
182 }
183
184 public B withReconnectDelayMillis(final int reconnectDelayMillis) {
185 this.reconnectDelayMillis = reconnectDelayMillis;
186 return asBuilder();
187 }
188
189 public B withSslConfiguration(final SslConfiguration sslConfiguration) {
190 this.sslConfiguration = sslConfiguration;
191 return asBuilder();
192 }
193 }
194
195 @PluginBuilderFactory
196 public static <B extends Builder<B>> B newBuilder() {
197 return new Builder<B>().asBuilder();
198 }
47199
48200 private final Object advertisement;
49201 private final Advertiser advertiser;
65217 }
66218
67219 @Override
68 public void stop() {
69 super.stop();
220 public boolean stop(final long timeout, final TimeUnit timeUnit) {
221 setStopping();
222 super.stop(timeout, timeUnit, false);
70223 if (this.advertiser != null) {
71224 this.advertiser.unadvertise(this.advertisement);
72225 }
226 setStopped();
227 return true;
73228 }
74229
75230 /**
102257 * The Filter or null.
103258 * @param advertise
104259 * "true" if the appender configuration should be advertised, "false" otherwise.
105 * @param config
260 * @param configuration
106261 * The Configuration
107262 * @return A SocketAppender.
263 * @deprecated Deprecated in 2.7; use {@link #newBuilder()}
108264 */
265 @Deprecated
109266 @PluginFactory
110267 public static SocketAppender createAppender(
111268 // @formatter:off
112 @PluginAttribute("host") final String host,
113 @PluginAttribute(value = "port", defaultInt = 0) final int port,
114 @PluginAttribute("protocol") final Protocol protocol,
115 @PluginElement("SSL") final SslConfiguration sslConfig,
116 @PluginAttribute(value = "connectTimeoutMillis", defaultInt = 0) final int connectTimeoutMillis,
117 @PluginAliases("reconnectionDelay") // deprecated
118 @PluginAttribute(value = "reconnectionDelayMillis", defaultInt = 0) final int reconnectDelayMillis,
119 @PluginAttribute(value = "immediateFail", defaultBoolean = true) final boolean immediateFail,
120 @PluginAttribute("name") final String name,
121 @PluginAttribute(value = "immediateFlush", defaultBoolean = true) boolean immediateFlush,
122 @PluginAttribute(value = "ignoreExceptions", defaultBoolean = true) final boolean ignoreExceptions,
123 @PluginElement("Layout") Layout<? extends Serializable> layout,
124 @PluginElement("Filter") final Filter filter,
125 @PluginAttribute(value = "advertise", defaultBoolean = false) final boolean advertise,
126 @PluginConfiguration final Configuration config) {
269 final String host,
270 final int port,
271 final Protocol protocol,
272 final SslConfiguration sslConfig,
273 final int connectTimeoutMillis,
274 final int reconnectDelayMillis,
275 final boolean immediateFail,
276 final String name,
277 boolean immediateFlush,
278 final boolean ignoreExceptions,
279 Layout<? extends Serializable> layout,
280 final Filter filter,
281 final boolean advertise,
282 final Configuration configuration) {
127283 // @formatter:on
128284
285 if (true) {
286 // @formatter:off
287 return newBuilder()
288 .withAdvertise(advertise)
289 .withConfiguration(configuration)
290 .withConnectTimeoutMillis(connectTimeoutMillis)
291 .withFilter(filter)
292 .withHost(host)
293 .withIgnoreExceptions(ignoreExceptions)
294 .withImmediateFail(immediateFail)
295 .withLayout(layout)
296 .withName(name)
297 .withPort(port)
298 .withProtocol(protocol)
299 .withReconnectDelayMillis(reconnectDelayMillis)
300 .withSslConfiguration(sslConfig)
301 .build();
302 // @formatter:on
303 }
129304 if (layout == null) {
130305 layout = SerializedLayout.createLayout();
131306 }
140315 immediateFlush = true;
141316 }
142317
143 final AbstractSocketManager manager = createSocketManager(name, actualProtocol, host, port, connectTimeoutMillis,
144 sslConfig, reconnectDelayMillis, immediateFail, layout);
318 final AbstractSocketManager manager = createSocketManager(name, actualProtocol, host, port,
319 connectTimeoutMillis, sslConfig, reconnectDelayMillis, immediateFail, layout, Constants.ENCODER_BYTE_BUFFER_SIZE);
145320
146321 return new SocketAppender(name, layout, filter, manager, ignoreExceptions, immediateFlush,
147 advertise ? config.getAdvertiser() : null);
148 }
149
322 advertise ? configuration.getAdvertiser() : null);
323 }
150324 /**
151325 * Creates a socket appender.
152326 *
180354 * @param config
181355 * The Configuration
182356 * @return A SocketAppender.
183 * @deprecated Deprecated in 2.5; use
184 * {@link #createAppender(String, int, Protocol, SslConfiguration, int, int, boolean, String, boolean, boolean, Layout, Filter, boolean, Configuration)}
185 * .
357 * @deprecated Deprecated in 2.5; use {@link #newBuilder()}
186358 */
187359 @Deprecated
188360 public static SocketAppender createAppender(
221393 * if the protocol cannot be handled.
222394 */
223395 protected static AbstractSocketManager createSocketManager(final String name, Protocol protocol, final String host,
224 final int port, final int connectTimeoutMillis, final SslConfiguration sslConfig, final int delayMillis,
225 final boolean immediateFail, final Layout<? extends Serializable> layout) {
396 final int port, final int connectTimeoutMillis, final SslConfiguration sslConfig, final int reconnectDelayMillis,
397 final boolean immediateFail, final Layout<? extends Serializable> layout, final int bufferSize) {
226398 if (protocol == Protocol.TCP && sslConfig != null) {
227399 // Upgrade TCP to SSL if an SSL config is specified.
228400 protocol = Protocol.SSL;
232404 }
233405 switch (protocol) {
234406 case TCP:
235 return TcpSocketManager.getSocketManager(host, port, connectTimeoutMillis, delayMillis, immediateFail,
236 layout);
407 return TcpSocketManager.getSocketManager(host, port, connectTimeoutMillis, reconnectDelayMillis, immediateFail,
408 layout, bufferSize);
237409 case UDP:
238 return DatagramSocketManager.getSocketManager(host, port, layout);
410 return DatagramSocketManager.getSocketManager(host, port, layout, bufferSize);
239411 case SSL:
240 return SslSocketManager.getSocketManager(sslConfig, host, port, connectTimeoutMillis, delayMillis,
241 immediateFail, layout);
412 return SslSocketManager.getSocketManager(sslConfig, host, port, connectTimeoutMillis, reconnectDelayMillis,
413 immediateFail, layout, bufferSize);
242414 default:
243415 throw new IllegalArgumentException(protocol.toString());
244416 }
1818 import java.io.Serializable;
1919 import java.nio.charset.Charset;
2020
21 import org.apache.logging.log4j.core.Appender;
2122 import org.apache.logging.log4j.core.Filter;
2223 import org.apache.logging.log4j.core.Layout;
2324 import org.apache.logging.log4j.core.config.Configuration;
3536 import org.apache.logging.log4j.core.net.Facility;
3637 import org.apache.logging.log4j.core.net.Protocol;
3738 import org.apache.logging.log4j.core.net.ssl.SslConfiguration;
39 import org.apache.logging.log4j.core.util.Constants;
3840 import org.apache.logging.log4j.util.EnglishEnums;
3941
4042 /**
4143 * The Syslog Appender.
4244 */
43 @Plugin(name = "Syslog", category = "Core", elementType = "appender", printObject = true)
45 @Plugin(name = "Syslog", category = "Core", elementType = Appender.ELEMENT_TYPE, printObject = true)
4446 public class SyslogAppender extends SocketAppender {
4547
4648 protected static final String RFC5424 = "RFC5424";
8890 * @param exceptionPattern The converter pattern to use for formatting exceptions.
8991 * @param loggerFields The logger fields
9092 * @param advertise Whether to advertise
91 * @param connectTimeoutMillis the connect timeout in milliseconds.
9293 * @return A SyslogAppender.
9394 */
9495 @PluginFactory
124125 @PluginConfiguration final Configuration config,
125126 @PluginAttribute(value = "charset", defaultString = "UTF-8") final Charset charsetName,
126127 @PluginAttribute("exceptionPattern") final String exceptionPattern,
127 @PluginElement("LoggerFields") final LoggerFields[] loggerFields, @PluginAttribute(value = "advertise", defaultBoolean = false) final boolean advertise) {
128 @PluginElement("LoggerFields") final LoggerFields[] loggerFields,
129 @PluginAttribute(value = "advertise", defaultBoolean = false) final boolean advertise) {
128130 // @formatter:on
129131
130 // TODO: add Protocol to TypeConverters
131132 final Protocol protocol = EnglishEnums.valueOf(Protocol.class, protocolStr);
132133 final boolean useTlsMessageFormat = sslConfig != null || protocol == Protocol.SSL;
133134 final Layout<? extends Serializable> layout = RFC5424.equalsIgnoreCase(format) ?
141142 return null;
142143 }
143144 final AbstractSocketManager manager = createSocketManager(name, protocol, host, port, connectTimeoutMillis,
144 sslConfig, reconnectionDelayMillis, immediateFail, layout);
145 sslConfig, reconnectionDelayMillis, immediateFail, layout, Constants.ENCODER_BYTE_BUFFER_SIZE);
145146
146147 return new SyslogAppender(name, layout, filter, ignoreExceptions, immediateFlush, manager,
147148 advertise ? config.getAdvertiser() : null);
1717
1818 import java.io.Writer;
1919
20 import org.apache.logging.log4j.core.Appender;
2021 import org.apache.logging.log4j.core.Filter;
2122 import org.apache.logging.log4j.core.StringLayout;
2223 import org.apache.logging.log4j.core.config.plugins.Plugin;
2829 /**
2930 * Appends log events to a {@link Writer}.
3031 */
31 @Plugin(name = "Writer", category = "Core", elementType = "appender", printObject = true)
32 @Plugin(name = "Writer", category = "Core", elementType = Appender.ELEMENT_TYPE, printObject = true)
3233 public final class WriterAppender extends AbstractWriterAppender<WriterManager> {
3334
3435 /**
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.appender;
17
18 import java.io.IOException;
19 import java.io.Writer;
20
21 import org.apache.logging.log4j.core.StringLayout;
22
23 /**
24 * Manages a Writer so that it can be shared by multiple Appenders and will
25 * allow appenders to reconfigure without requiring a new writer.
26 */
27 public class WriterManager extends AbstractManager {
28
29 /**
30 * Creates a Manager.
31 *
32 * @param name The name of the stream to manage.
33 * @param data The data to pass to the Manager.
34 * @param factory The factory to use to create the Manager.
35 * @param <T> The type of the WriterManager.
36 * @return A WriterManager.
37 */
38 public static <T> WriterManager getManager(final String name, final T data,
39 final ManagerFactory<? extends WriterManager, T> factory) {
40 return AbstractManager.getManager(name, factory, data);
41 }
42 protected final StringLayout layout;
43
44 private volatile Writer writer;
45
46 public WriterManager(final Writer writer, final String streamName, final StringLayout layout,
47 final boolean writeHeader) {
48 super(streamName);
49 this.writer = writer;
50 this.layout = layout;
51 if (writeHeader && layout != null) {
52 final byte[] header = layout.getHeader();
53 if (header != null) {
54 try {
55 this.writer.write(new String(header, layout.getCharset()));
56 } catch (final IOException e) {
57 logError("Unable to write header", e);
58 }
59 }
60 }
61 }
62
63 protected synchronized void close() {
64 final Writer w = writer; // access volatile field only once per method
65 try {
66 w.close();
67 } catch (final IOException ex) {
68 logError("Unable to close stream", ex);
69 }
70 }
71
72 /**
73 * Flushes any buffers.
74 */
75 public synchronized void flush() {
76 try {
77 writer.flush();
78 } catch (final IOException ex) {
79 final String msg = "Error flushing stream " + getName();
80 throw new AppenderLoggingException(msg, ex);
81 }
82 }
83
84 protected Writer getWriter() {
85 return writer;
86 }
87
88 /**
89 * Returns the status of the stream.
90 * @return true if the stream is open, false if it is not.
91 */
92 public boolean isOpen() {
93 return getCount() > 0;
94 }
95
96 /**
97 * Default hook to write footer during close.
98 */
99 @Override
100 public void releaseSub() {
101 writeFooter();
102 close();
103 }
104
105 protected void setWriter(final Writer writer) {
106 final byte[] header = layout.getHeader();
107 if (header != null) {
108 try {
109 writer.write(new String(header, layout.getCharset()));
110 this.writer = writer; // only update field if writer.write() succeeded
111 } catch (final IOException ioe) {
112 logError("Unable to write header", ioe);
113 }
114 } else {
115 this.writer = writer;
116 }
117 }
118
119 /**
120 * Some output streams synchronize writes while others do not. Synchronizing here insures that
121 * log events won't be intertwined.
122 * @param bytes The serialized Log event.
123 * @param offset The offset into the byte array.
124 * @param length The number of bytes to write.
125 * @throws AppenderLoggingException if an error occurs.
126 */
127 protected synchronized void write(final String str) {
128 try {
129 writer.write(str);
130 } catch (final IOException ex) {
131 final String msg = "Error writing to stream " + getName();
132 throw new AppenderLoggingException(msg, ex);
133 }
134 }
135
136 /**
137 * Writes the footer.
138 */
139 protected void writeFooter() {
140 if (layout == null) {
141 return;
142 }
143 final byte[] footer = layout.getFooter();
144 if (footer != null && footer.length > 0) {
145 write(new String(footer, layout.getCharset()));
146 }
147 }
148 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.appender;
17
18 import java.io.IOException;
19 import java.io.Writer;
20 import java.util.concurrent.TimeUnit;
21
22 import org.apache.logging.log4j.core.StringLayout;
23
24 /**
25 * Manages a Writer so that it can be shared by multiple Appenders and will
26 * allow appenders to reconfigure without requiring a new writer.
27 */
28 public class WriterManager extends AbstractManager {
29
30 /**
31 * Creates a Manager.
32 *
33 * @param name The name of the stream to manage.
34 * @param data The data to pass to the Manager.
35 * @param factory The factory to use to create the Manager.
36 * @param <T> The type of the WriterManager.
37 * @return A WriterManager.
38 */
39 public static <T> WriterManager getManager(final String name, final T data,
40 final ManagerFactory<? extends WriterManager, T> factory) {
41 return AbstractManager.getManager(name, factory, data);
42 }
43 protected final StringLayout layout;
44
45 private volatile Writer writer;
46
47 public WriterManager(final Writer writer, final String streamName, final StringLayout layout,
48 final boolean writeHeader) {
49 super(null, streamName);
50 this.writer = writer;
51 this.layout = layout;
52 if (writeHeader && layout != null) {
53 final byte[] header = layout.getHeader();
54 if (header != null) {
55 try {
56 this.writer.write(new String(header, layout.getCharset()));
57 } catch (final IOException e) {
58 logError("Unable to write header", e);
59 }
60 }
61 }
62 }
63
64 protected synchronized void closeWriter() {
65 final Writer w = writer; // access volatile field only once per method
66 try {
67 w.close();
68 } catch (final IOException ex) {
69 logError("Unable to close stream", ex);
70 }
71 }
72
73 /**
74 * Flushes any buffers.
75 */
76 public synchronized void flush() {
77 try {
78 writer.flush();
79 } catch (final IOException ex) {
80 final String msg = "Error flushing stream " + getName();
81 throw new AppenderLoggingException(msg, ex);
82 }
83 }
84
85 protected Writer getWriter() {
86 return writer;
87 }
88
89 /**
90 * Returns the status of the stream.
91 * @return true if the stream is open, false if it is not.
92 */
93 public boolean isOpen() {
94 return getCount() > 0;
95 }
96
97 /**
98 * Default hook to write footer during close.
99 */
100 @Override
101 public boolean releaseSub(final long timeout, final TimeUnit timeUnit) {
102 writeFooter();
103 closeWriter();
104 return true;
105 }
106
107 protected void setWriter(final Writer writer) {
108 final byte[] header = layout.getHeader();
109 if (header != null) {
110 try {
111 writer.write(new String(header, layout.getCharset()));
112 this.writer = writer; // only update field if writer.write() succeeded
113 } catch (final IOException ioe) {
114 logError("Unable to write header", ioe);
115 }
116 } else {
117 this.writer = writer;
118 }
119 }
120
121 /**
122 * Some output streams synchronize writes while others do not. Synchronizing here insures that
123 * log events won't be intertwined.
124 * @param bytes The serialized Log event.
125 * @param offset The offset into the byte array.
126 * @param length The number of bytes to write.
127 * @throws AppenderLoggingException if an error occurs.
128 */
129 protected synchronized void write(final String str) {
130 try {
131 writer.write(str);
132 } catch (final IOException ex) {
133 final String msg = "Error writing to stream " + getName();
134 throw new AppenderLoggingException(msg, ex);
135 }
136 }
137
138 /**
139 * Writes the footer.
140 */
141 protected void writeFooter() {
142 if (layout == null) {
143 return;
144 }
145 final byte[] footer = layout.getFooter();
146 if (footer != null && footer.length > 0) {
147 write(new String(footer, layout.getCharset()));
148 }
149 }
150 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.appender.db;
17
18 import java.util.concurrent.locks.Lock;
19 import java.util.concurrent.locks.ReadWriteLock;
20 import java.util.concurrent.locks.ReentrantReadWriteLock;
21
22 import org.apache.logging.log4j.LoggingException;
23 import org.apache.logging.log4j.core.Filter;
24 import org.apache.logging.log4j.core.Layout;
25 import org.apache.logging.log4j.core.LogEvent;
26 import org.apache.logging.log4j.core.appender.AbstractAppender;
27 import org.apache.logging.log4j.core.appender.AppenderLoggingException;
28
29 /**
30 * An abstract Appender for writing events to a database of some type, be it relational or NoSQL. All database appenders
31 * should inherit from this base appender. Three implementations are currently provided:
32 * {@link org.apache.logging.log4j.core.appender.db.jdbc JDBC}, {@link org.apache.logging.log4j.core.appender.db.jpa
33 * JPA}, and <a href="/log4j/2.x/log4j-nosql/apidocs/">NoSQL</a>.
34 *
35 * @param <T> Specifies which type of {@link AbstractDatabaseManager} this Appender requires.
36 */
37 public abstract class AbstractDatabaseAppender<T extends AbstractDatabaseManager> extends AbstractAppender {
38
39 private final ReadWriteLock lock = new ReentrantReadWriteLock();
40 private final Lock readLock = lock.readLock();
41 private final Lock writeLock = lock.writeLock();
42
43 private T manager;
44
45 /**
46 * Instantiates the base appender.
47 *
48 * @param name The appender name.
49 * @param filter The filter, if any, to use.
50 * @param ignoreExceptions If {@code true} exceptions encountered when appending events are logged; otherwise
51 * they are propagated to the caller.
52 * @param manager The matching {@link AbstractDatabaseManager} implementation.
53 */
54 protected AbstractDatabaseAppender(final String name, final Filter filter, final boolean ignoreExceptions,
55 final T manager) {
56 super(name, filter, null, ignoreExceptions);
57 this.manager = manager;
58 }
59
60 /**
61 * This always returns {@code null}, as database appenders do not use a single layout. The JPA and NoSQL appenders
62 * do not use a layout at all. The JDBC appender has a layout-per-column pattern.
63 *
64 * @return {@code null}.
65 */
66 @Override
67 public final Layout<LogEvent> getLayout() {
68 return null;
69 }
70
71 /**
72 * Returns the underlying manager in use within this appender.
73 *
74 * @return the manager.
75 */
76 public final T getManager() {
77 return this.manager;
78 }
79
80 @Override
81 public final void start() {
82 if (this.getManager() == null) {
83 LOGGER.error("No AbstractDatabaseManager set for the appender named [{}].", this.getName());
84 }
85 super.start();
86 if (this.getManager() != null) {
87 this.getManager().startup();
88 }
89 }
90
91 @Override
92 public final void stop() {
93 super.stop();
94 if (this.getManager() != null) {
95 this.getManager().release();
96 }
97 }
98
99 @Override
100 public final void append(final LogEvent event) {
101 this.readLock.lock();
102 try {
103 this.getManager().write(event);
104 } catch (final LoggingException e) {
105 LOGGER.error("Unable to write to database [{}] for appender [{}].", this.getManager().getName(),
106 this.getName(), e);
107 throw e;
108 } catch (final Exception e) {
109 LOGGER.error("Unable to write to database [{}] for appender [{}].", this.getManager().getName(),
110 this.getName(), e);
111 throw new AppenderLoggingException("Unable to write to database in appender: " + e.getMessage(), e);
112 } finally {
113 this.readLock.unlock();
114 }
115 }
116
117 /**
118 * Replaces the underlying manager in use within this appender. This can be useful for manually changing the way log
119 * events are written to the database without losing buffered or in-progress events. The existing manager is
120 * released only after the new manager has been installed. This method is thread-safe.
121 *
122 * @param manager The new manager to install.
123 */
124 protected final void replaceManager(final T manager) {
125 this.writeLock.lock();
126 try {
127 final T old = this.getManager();
128 if (!manager.isRunning()) {
129 manager.startup();
130 }
131 this.manager = manager;
132 old.release();
133 } finally {
134 this.writeLock.unlock();
135 }
136 }
137 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.appender.db;
17
18 import java.util.concurrent.TimeUnit;
19 import java.util.concurrent.locks.Lock;
20 import java.util.concurrent.locks.ReadWriteLock;
21 import java.util.concurrent.locks.ReentrantReadWriteLock;
22
23 import org.apache.logging.log4j.LoggingException;
24 import org.apache.logging.log4j.core.Filter;
25 import org.apache.logging.log4j.core.Layout;
26 import org.apache.logging.log4j.core.LogEvent;
27 import org.apache.logging.log4j.core.appender.AbstractAppender;
28 import org.apache.logging.log4j.core.appender.AppenderLoggingException;
29
30 /**
31 * An abstract Appender for writing events to a database of some type, be it relational or NoSQL. All database appenders
32 * should inherit from this base appender. Three implementations are currently provided:
33 * {@link org.apache.logging.log4j.core.appender.db.jdbc JDBC}, {@link org.apache.logging.log4j.core.appender.db.jpa
34 * JPA}, and <a href="/log4j/2.x/log4j-nosql/apidocs/">NoSQL</a>.
35 *
36 * @param <T> Specifies which type of {@link AbstractDatabaseManager} this Appender requires.
37 */
38 public abstract class AbstractDatabaseAppender<T extends AbstractDatabaseManager> extends AbstractAppender {
39
40 private final ReadWriteLock lock = new ReentrantReadWriteLock();
41 private final Lock readLock = lock.readLock();
42 private final Lock writeLock = lock.writeLock();
43
44 private T manager;
45
46 /**
47 * Instantiates the base appender.
48 *
49 * @param name The appender name.
50 * @param filter The filter, if any, to use.
51 * @param ignoreExceptions If {@code true} exceptions encountered when appending events are logged; otherwise
52 * they are propagated to the caller.
53 * @param manager The matching {@link AbstractDatabaseManager} implementation.
54 */
55 protected AbstractDatabaseAppender(final String name, final Filter filter, final boolean ignoreExceptions,
56 final T manager) {
57 super(name, filter, null, ignoreExceptions);
58 this.manager = manager;
59 }
60
61 /**
62 * This always returns {@code null}, as database appenders do not use a single layout. The JPA and NoSQL appenders
63 * do not use a layout at all. The JDBC appender has a layout-per-column pattern.
64 *
65 * @return {@code null}.
66 */
67 @Override
68 public final Layout<LogEvent> getLayout() {
69 return null;
70 }
71
72 /**
73 * Returns the underlying manager in use within this appender.
74 *
75 * @return the manager.
76 */
77 public final T getManager() {
78 return this.manager;
79 }
80
81 @Override
82 public final void start() {
83 if (this.getManager() == null) {
84 LOGGER.error("No AbstractDatabaseManager set for the appender named [{}].", this.getName());
85 }
86 super.start();
87 if (this.getManager() != null) {
88 this.getManager().startup();
89 }
90 }
91
92 @Override
93 public boolean stop(final long timeout, final TimeUnit timeUnit) {
94 setStopping();
95 boolean stopped = super.stop(timeout, timeUnit, false);
96 if (this.getManager() != null) {
97 stopped &= this.getManager().stop(timeout, timeUnit);
98 }
99 setStopped();
100 return stopped;
101 }
102
103 @Override
104 public final void append(final LogEvent event) {
105 this.readLock.lock();
106 try {
107 this.getManager().write(event);
108 } catch (final LoggingException e) {
109 LOGGER.error("Unable to write to database [{}] for appender [{}].", this.getManager().getName(),
110 this.getName(), e);
111 throw e;
112 } catch (final Exception e) {
113 LOGGER.error("Unable to write to database [{}] for appender [{}].", this.getManager().getName(),
114 this.getName(), e);
115 throw new AppenderLoggingException("Unable to write to database in appender: " + e.getMessage(), e);
116 } finally {
117 this.readLock.unlock();
118 }
119 }
120
121 /**
122 * Replaces the underlying manager in use within this appender. This can be useful for manually changing the way log
123 * events are written to the database without losing buffered or in-progress events. The existing manager is
124 * released only after the new manager has been installed. This method is thread-safe.
125 *
126 * @param manager The new manager to install.
127 */
128 protected final void replaceManager(final T manager) {
129 this.writeLock.lock();
130 try {
131 final T old = this.getManager();
132 if (!manager.isRunning()) {
133 manager.startup();
134 }
135 this.manager = manager;
136 old.close();
137 } finally {
138 this.writeLock.unlock();
139 }
140 }
141 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16
17 package org.apache.logging.log4j.core.appender.db;
18
19 import java.io.Flushable;
20 import java.util.ArrayList;
21
22 import org.apache.logging.log4j.core.LogEvent;
23 import org.apache.logging.log4j.core.appender.AbstractManager;
24 import org.apache.logging.log4j.core.appender.ManagerFactory;
25
26 /**
27 * Manager that allows database appenders to have their configuration reloaded without losing events.
28 */
29 public abstract class AbstractDatabaseManager extends AbstractManager implements Flushable {
30 private final ArrayList<LogEvent> buffer;
31 private final int bufferSize;
32
33 private boolean running = false;
34
35 /**
36 * Instantiates the base manager.
37 *
38 * @param name The manager name, which should include any configuration details that one might want to be able to
39 * reconfigure at runtime, such as database name, username, (hashed) password, etc.
40 * @param bufferSize The size of the log event buffer.
41 */
42 protected AbstractDatabaseManager(final String name, final int bufferSize) {
43 super(name);
44 this.bufferSize = bufferSize;
45 this.buffer = new ArrayList<>(bufferSize + 1);
46 }
47
48 /**
49 * Implementations should implement this method to perform any proprietary startup operations. This method will
50 * never be called twice on the same instance. It is safe to throw any exceptions from this method. This method
51 * does not necessarily connect to the database, as it is generally unreliable to connect once and use the same
52 * connection for hours.
53 */
54 protected abstract void startupInternal() throws Exception;
55
56 /**
57 * This method is called within the appender when the appender is started. If it has not already been called, it
58 * calls {@link #startupInternal()} and catches any exceptions it might throw.
59 */
60 public final synchronized void startup() {
61 if (!this.isRunning()) {
62 try {
63 this.startupInternal();
64 this.running = true;
65 } catch (final Exception e) {
66 logError("could not perform database startup operations", e);
67 }
68 }
69 }
70
71 /**
72 * Implementations should implement this method to perform any proprietary disconnection / shutdown operations. This
73 * method will never be called twice on the same instance, and it will only be called <em>after</em>
74 * {@link #startupInternal()}. It is safe to throw any exceptions from this method. This method does not
75 * necessarily disconnect from the database for the same reasons outlined in {@link #startupInternal()}.
76 */
77 protected abstract void shutdownInternal() throws Exception;
78
79 /**
80 * This method is called from the {@link #release()} method when the appender is stopped or the appender's manager
81 * is replaced. If it has not already been called, it calls {@link #shutdownInternal()} and catches any exceptions
82 * it might throw.
83 */
84 public final synchronized void shutdown() {
85 this.flush();
86 if (this.isRunning()) {
87 try {
88 this.shutdownInternal();
89 } catch (final Exception e) {
90 logWarn("caught exception while performing database shutdown operations", e);
91 } finally {
92 this.running = false;
93 }
94 }
95 }
96
97 /**
98 * Indicates whether the manager is currently connected {@link #startup()} has been called and {@link #shutdown()}
99 * has not been called).
100 *
101 * @return {@code true} if the manager is connected.
102 */
103 public final boolean isRunning() {
104 return this.running;
105 }
106
107 /**
108 * Connects to the database and starts a transaction (if applicable). With buffering enabled, this is called when
109 * flushing the buffer begins, before the first call to {@link #writeInternal}. With buffering disabled, this is
110 * called immediately before every invocation of {@link #writeInternal}.
111 */
112 protected abstract void connectAndStart();
113
114 /**
115 * Performs the actual writing of the event in an implementation-specific way. This method is called immediately
116 * from {@link #write(LogEvent)} if buffering is off, or from {@link #flush()} if the buffer has reached its limit.
117 *
118 * @param event The event to write to the database.
119 */
120 protected abstract void writeInternal(LogEvent event);
121
122 /**
123 * Commits any active transaction (if applicable) and disconnects from the database (returns the connection to the
124 * connection pool). With buffering enabled, this is called when flushing the buffer completes, after the last call
125 * to {@link #writeInternal}. With buffering disabled, this is called immediately after every invocation of
126 * {@link #writeInternal}.
127 */
128 protected abstract void commitAndClose();
129
130 /**
131 * This method is called automatically when the buffer size reaches its maximum or at the beginning of a call to
132 * {@link #shutdown()}. It can also be called manually to flush events to the database.
133 */
134 @Override
135 public final synchronized void flush() {
136 if (this.isRunning() && this.buffer.size() > 0) {
137 this.connectAndStart();
138 try {
139 for (final LogEvent event : this.buffer) {
140 this.writeInternal(event);
141 }
142 } finally {
143 this.commitAndClose();
144 // not sure if this should be done when writing the events failed
145 this.buffer.clear();
146 }
147 }
148 }
149
150 /**
151 * This method manages buffering and writing of events.
152 *
153 * @param event The event to write to the database.
154 */
155 public final synchronized void write(final LogEvent event) {
156 if (this.bufferSize > 0) {
157 this.buffer.add(event);
158 if (this.buffer.size() >= this.bufferSize || event.isEndOfBatch()) {
159 this.flush();
160 }
161 } else {
162 this.connectAndStart();
163 try {
164 this.writeInternal(event);
165 } finally {
166 this.commitAndClose();
167 }
168 }
169 }
170
171 @Override
172 public final void releaseSub() {
173 this.shutdown();
174 }
175
176 @Override
177 public final String toString() {
178 return this.getName();
179 }
180
181 /**
182 * Implementations should define their own getManager method and call this method from that to create or get
183 * existing managers.
184 *
185 * @param name The manager name, which should include any configuration details that one might want to be able to
186 * reconfigure at runtime, such as database name, username, (hashed) password, etc.
187 * @param data The concrete instance of {@link AbstractFactoryData} appropriate for the given manager.
188 * @param factory A factory instance for creating the appropriate manager.
189 * @param <M> The concrete manager type.
190 * @param <T> The concrete {@link AbstractFactoryData} type.
191 * @return a new or existing manager of the specified type and name.
192 */
193 protected static <M extends AbstractDatabaseManager, T extends AbstractFactoryData> M getManager(
194 final String name, final T data, final ManagerFactory<M, T> factory
195 ) {
196 return AbstractManager.getManager(name, factory, data);
197 }
198
199 /**
200 * Implementations should extend this class for passing data between the getManager method and the manager factory
201 * class.
202 */
203 protected abstract static class AbstractFactoryData {
204 private final int bufferSize;
205
206 /**
207 * Constructs the base factory data.
208 *
209 * @param bufferSize The size of the buffer.
210 */
211 protected AbstractFactoryData(final int bufferSize) {
212 this.bufferSize = bufferSize;
213 }
214
215 /**
216 * Gets the buffer size.
217 *
218 * @return the buffer size.
219 */
220 public int getBufferSize() {
221 return bufferSize;
222 }
223 }
224 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16
17 package org.apache.logging.log4j.core.appender.db;
18
19 import java.io.Flushable;
20 import java.util.ArrayList;
21 import java.util.concurrent.TimeUnit;
22
23 import org.apache.logging.log4j.core.LogEvent;
24 import org.apache.logging.log4j.core.appender.AbstractManager;
25 import org.apache.logging.log4j.core.appender.ManagerFactory;
26
27 /**
28 * Manager that allows database appenders to have their configuration reloaded without losing events.
29 */
30 public abstract class AbstractDatabaseManager extends AbstractManager implements Flushable {
31 private final ArrayList<LogEvent> buffer;
32 private final int bufferSize;
33
34 private boolean running = false;
35
36 /**
37 * Instantiates the base manager.
38 *
39 * @param name The manager name, which should include any configuration details that one might want to be able to
40 * reconfigure at runtime, such as database name, username, (hashed) password, etc.
41 * @param bufferSize The size of the log event buffer.
42 */
43 protected AbstractDatabaseManager(final String name, final int bufferSize) {
44 super(null, name);
45 this.bufferSize = bufferSize;
46 this.buffer = new ArrayList<>(bufferSize + 1);
47 }
48
49 /**
50 * Implementations should implement this method to perform any proprietary startup operations. This method will
51 * never be called twice on the same instance. It is safe to throw any exceptions from this method. This method
52 * does not necessarily connect to the database, as it is generally unreliable to connect once and use the same
53 * connection for hours.
54 */
55 protected abstract void startupInternal() throws Exception;
56
57 /**
58 * This method is called within the appender when the appender is started. If it has not already been called, it
59 * calls {@link #startupInternal()} and catches any exceptions it might throw.
60 */
61 public final synchronized void startup() {
62 if (!this.isRunning()) {
63 try {
64 this.startupInternal();
65 this.running = true;
66 } catch (final Exception e) {
67 logError("Could not perform database startup operations", e);
68 }
69 }
70 }
71
72 /**
73 * Implementations should implement this method to perform any proprietary disconnection / shutdown operations. This
74 * method will never be called twice on the same instance, and it will only be called <em>after</em>
75 * {@link #startupInternal()}. It is safe to throw any exceptions from this method. This method does not
76 * necessarily disconnect from the database for the same reasons outlined in {@link #startupInternal()}.
77 * @return true if all resources were closed normally, false otherwise.
78 */
79 protected abstract boolean shutdownInternal() throws Exception;
80
81 /**
82 * This method is called from the {@link #close()} method when the appender is stopped or the appender's manager
83 * is replaced. If it has not already been called, it calls {@link #shutdownInternal()} and catches any exceptions
84 * it might throw.
85 * @return true if all resources were closed normally, false otherwise.
86 */
87 public final synchronized boolean shutdown() {
88 boolean closed = true;
89 this.flush();
90 if (this.isRunning()) {
91 try {
92 closed &= this.shutdownInternal();
93 } catch (final Exception e) {
94 logWarn("Caught exception while performing database shutdown operations", e);
95 closed = false;
96 } finally {
97 this.running = false;
98 }
99 }
100 return closed;
101 }
102
103 /**
104 * Indicates whether the manager is currently connected {@link #startup()} has been called and {@link #shutdown()}
105 * has not been called).
106 *
107 * @return {@code true} if the manager is connected.
108 */
109 public final boolean isRunning() {
110 return this.running;
111 }
112
113 /**
114 * Connects to the database and starts a transaction (if applicable). With buffering enabled, this is called when
115 * flushing the buffer begins, before the first call to {@link #writeInternal}. With buffering disabled, this is
116 * called immediately before every invocation of {@link #writeInternal}.
117 */
118 protected abstract void connectAndStart();
119
120 /**
121 * Performs the actual writing of the event in an implementation-specific way. This method is called immediately
122 * from {@link #write(LogEvent)} if buffering is off, or from {@link #flush()} if the buffer has reached its limit.
123 *
124 * @param event The event to write to the database.
125 */
126 protected abstract void writeInternal(LogEvent event);
127
128 /**
129 * Commits any active transaction (if applicable) and disconnects from the database (returns the connection to the
130 * connection pool). With buffering enabled, this is called when flushing the buffer completes, after the last call
131 * to {@link #writeInternal}. With buffering disabled, this is called immediately after every invocation of
132 * {@link #writeInternal}.
133 * @return true if all resources were closed normally, false otherwise.
134 */
135 protected abstract boolean commitAndClose();
136
137 /**
138 * This method is called automatically when the buffer size reaches its maximum or at the beginning of a call to
139 * {@link #shutdown()}. It can also be called manually to flush events to the database.
140 */
141 @Override
142 public final synchronized void flush() {
143 if (this.isRunning() && this.buffer.size() > 0) {
144 this.connectAndStart();
145 try {
146 for (final LogEvent event : this.buffer) {
147 this.writeInternal(event);
148 }
149 } finally {
150 this.commitAndClose();
151 // not sure if this should be done when writing the events failed
152 this.buffer.clear();
153 }
154 }
155 }
156
157 /**
158 * This method manages buffering and writing of events.
159 *
160 * @param event The event to write to the database.
161 */
162 public final synchronized void write(final LogEvent event) {
163 if (this.bufferSize > 0) {
164 this.buffer.add(event);
165 if (this.buffer.size() >= this.bufferSize || event.isEndOfBatch()) {
166 this.flush();
167 }
168 } else {
169 this.connectAndStart();
170 try {
171 this.writeInternal(event);
172 } finally {
173 this.commitAndClose();
174 }
175 }
176 }
177
178 @Override
179 public final boolean releaseSub(final long timeout, final TimeUnit timeUnit) {
180 return this.shutdown();
181 }
182
183 @Override
184 public final String toString() {
185 return this.getName();
186 }
187
188 /**
189 * Implementations should define their own getManager method and call this method from that to create or get
190 * existing managers.
191 *
192 * @param name The manager name, which should include any configuration details that one might want to be able to
193 * reconfigure at runtime, such as database name, username, (hashed) password, etc.
194 * @param data The concrete instance of {@link AbstractFactoryData} appropriate for the given manager.
195 * @param factory A factory instance for creating the appropriate manager.
196 * @param <M> The concrete manager type.
197 * @param <T> The concrete {@link AbstractFactoryData} type.
198 * @return a new or existing manager of the specified type and name.
199 */
200 protected static <M extends AbstractDatabaseManager, T extends AbstractFactoryData> M getManager(
201 final String name, final T data, final ManagerFactory<M, T> factory
202 ) {
203 return AbstractManager.getManager(name, factory, data);
204 }
205
206 /**
207 * Implementations should extend this class for passing data between the getManager method and the manager factory
208 * class.
209 */
210 protected abstract static class AbstractFactoryData {
211 private final int bufferSize;
212
213 /**
214 * Constructs the base factory data.
215 *
216 * @param bufferSize The size of the buffer.
217 */
218 protected AbstractFactoryData(final int bufferSize) {
219 this.bufferSize = bufferSize;
220 }
221
222 /**
223 * Gets the buffer size.
224 *
225 * @return the buffer size.
226 */
227 public int getBufferSize() {
228 return bufferSize;
229 }
230 }
231 }
2626 import org.apache.logging.log4j.core.config.plugins.Plugin;
2727 import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
2828 import org.apache.logging.log4j.core.config.plugins.PluginFactory;
29 import org.apache.logging.log4j.core.util.Loader;
3029 import org.apache.logging.log4j.status.StatusLogger;
30 import org.apache.logging.log4j.util.LoaderUtil;
3131 import org.apache.logging.log4j.util.Strings;
3232
3333 /**
7878
7979 final Method method;
8080 try {
81 final Class<?> factoryClass = Loader.loadClass(className);
81 final Class<?> factoryClass = LoaderUtil.loadClass(className);
8282 method = factoryClass.getMethod(methodName);
8383 } catch (final Exception e) {
8484 LOGGER.error(e.toString(), e);
1515 */
1616 package org.apache.logging.log4j.core.appender.db.jdbc;
1717
18 import org.apache.logging.log4j.core.Appender;
1819 import org.apache.logging.log4j.core.Filter;
1920 import org.apache.logging.log4j.core.appender.AbstractAppender;
2021 import org.apache.logging.log4j.core.appender.db.AbstractDatabaseAppender;
3334 * @see ColumnConfig
3435 * @see ConnectionSource
3536 */
36 @Plugin(name = "JDBC", category = "Core", elementType = "appender", printObject = true)
37 @Plugin(name = "JDBC", category = "Core", elementType = Appender.ELEMENT_TYPE, printObject = true)
3738 public final class JdbcAppender extends AbstractDatabaseAppender<JdbcDatabaseManager> {
3839
3940 private final String description;
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.appender.db.jdbc;
17
18 import java.io.StringReader;
19 import java.sql.Connection;
20 import java.sql.DatabaseMetaData;
21 import java.sql.PreparedStatement;
22 import java.sql.SQLException;
23 import java.sql.Timestamp;
24 import java.util.ArrayList;
25 import java.util.List;
26
27 import org.apache.logging.log4j.core.LogEvent;
28 import org.apache.logging.log4j.core.appender.AppenderLoggingException;
29 import org.apache.logging.log4j.core.appender.ManagerFactory;
30 import org.apache.logging.log4j.core.appender.db.AbstractDatabaseManager;
31 import org.apache.logging.log4j.core.layout.PatternLayout;
32 import org.apache.logging.log4j.core.util.Closer;
33
34 /**
35 * An {@link AbstractDatabaseManager} implementation for relational databases accessed via JDBC.
36 */
37 public final class JdbcDatabaseManager extends AbstractDatabaseManager {
38
39 private static final JdbcDatabaseManagerFactory INSTANCE = new JdbcDatabaseManagerFactory();
40
41 private final List<Column> columns;
42 private final ConnectionSource connectionSource;
43 private final String sqlStatement;
44
45 private Connection connection;
46 private PreparedStatement statement;
47 private boolean isBatchSupported;
48
49 private JdbcDatabaseManager(final String name, final int bufferSize, final ConnectionSource connectionSource,
50 final String sqlStatement, final List<Column> columns) {
51 super(name, bufferSize);
52 this.connectionSource = connectionSource;
53 this.sqlStatement = sqlStatement;
54 this.columns = columns;
55 }
56
57 @Override
58 protected void startupInternal() throws Exception {
59 this.connection = this.connectionSource.getConnection();
60 final DatabaseMetaData metaData = this.connection.getMetaData();
61 this.isBatchSupported = metaData.supportsBatchUpdates();
62 Closer.closeSilently(this.connection);
63 }
64
65 @Override
66 protected void shutdownInternal() {
67 if (this.connection != null || this.statement != null) {
68 this.commitAndClose();
69 }
70 }
71
72 @Override
73 protected void connectAndStart() {
74 try {
75 this.connection = this.connectionSource.getConnection();
76 this.connection.setAutoCommit(false);
77 this.statement = this.connection.prepareStatement(this.sqlStatement);
78 } catch (final SQLException e) {
79 throw new AppenderLoggingException(
80 "Cannot write logging event or flush buffer; JDBC manager cannot connect to the database.", e
81 );
82 }
83 }
84
85 @Override
86 protected void writeInternal(final LogEvent event) {
87 StringReader reader = null;
88 try {
89 if (!this.isRunning() || this.connection == null || this.connection.isClosed() || this.statement == null
90 || this.statement.isClosed()) {
91 throw new AppenderLoggingException(
92 "Cannot write logging event; JDBC manager not connected to the database.");
93 }
94
95 int i = 1;
96 for (final Column column : this.columns) {
97 if (column.isEventTimestamp) {
98 this.statement.setTimestamp(i++, new Timestamp(event.getTimeMillis()));
99 } else {
100 if (column.isClob) {
101 reader = new StringReader(column.layout.toSerializable(event));
102 if (column.isUnicode) {
103 this.statement.setNClob(i++, reader);
104 } else {
105 this.statement.setClob(i++, reader);
106 }
107 } else {
108 if (column.isUnicode) {
109 this.statement.setNString(i++, column.layout.toSerializable(event));
110 } else {
111 this.statement.setString(i++, column.layout.toSerializable(event));
112 }
113 }
114 }
115 }
116
117 if (this.isBatchSupported) {
118 this.statement.addBatch();
119 } else if (this.statement.executeUpdate() == 0) {
120 throw new AppenderLoggingException(
121 "No records inserted in database table for log event in JDBC manager.");
122 }
123 } catch (final SQLException e) {
124 throw new AppenderLoggingException("Failed to insert record for log event in JDBC manager: " +
125 e.getMessage(), e);
126 } finally {
127 Closer.closeSilently(reader);
128 }
129 }
130
131 @Override
132 protected void commitAndClose() {
133 try {
134 if (this.connection != null && !this.connection.isClosed()) {
135 if (this.isBatchSupported) {
136 this.statement.executeBatch();
137 }
138 this.connection.commit();
139 }
140 } catch (final SQLException e) {
141 throw new AppenderLoggingException("Failed to commit transaction logging event or flushing buffer.", e);
142 } finally {
143 try {
144 Closer.close(this.statement);
145 } catch (final Exception e) {
146 logWarn("failed to close SQL statement logging event or flushing buffer", e);
147 } finally {
148 this.statement = null;
149 }
150
151 try {
152 Closer.close(this.connection);
153 } catch (final Exception e) {
154 logWarn("failed to close database connection logging event or flushing buffer", e);
155 } finally {
156 this.connection = null;
157 }
158 }
159 }
160
161 /**
162 * Creates a JDBC manager for use within the {@link JdbcAppender}, or returns a suitable one if it already exists.
163 *
164 * @param name The name of the manager, which should include connection details and hashed passwords where possible.
165 * @param bufferSize The size of the log event buffer.
166 * @param connectionSource The source for connections to the database.
167 * @param tableName The name of the database table to insert log events into.
168 * @param columnConfigs Configuration information about the log table columns.
169 * @return a new or existing JDBC manager as applicable.
170 */
171 public static JdbcDatabaseManager getJDBCDatabaseManager(final String name, final int bufferSize,
172 final ConnectionSource connectionSource,
173 final String tableName,
174 final ColumnConfig[] columnConfigs) {
175
176 return AbstractDatabaseManager.getManager(
177 name, new FactoryData(bufferSize, connectionSource, tableName, columnConfigs), getFactory()
178 );
179 }
180
181 private static JdbcDatabaseManagerFactory getFactory() {
182 return INSTANCE;
183 }
184
185 /**
186 * Encapsulates data that {@link JdbcDatabaseManagerFactory} uses to create managers.
187 */
188 private static final class FactoryData extends AbstractDatabaseManager.AbstractFactoryData {
189 private final ColumnConfig[] columnConfigs;
190 private final ConnectionSource connectionSource;
191 private final String tableName;
192
193 protected FactoryData(final int bufferSize, final ConnectionSource connectionSource, final String tableName,
194 final ColumnConfig[] columnConfigs) {
195 super(bufferSize);
196 this.connectionSource = connectionSource;
197 this.tableName = tableName;
198 this.columnConfigs = columnConfigs;
199 }
200 }
201
202 /**
203 * Creates managers.
204 */
205 private static final class JdbcDatabaseManagerFactory implements ManagerFactory<JdbcDatabaseManager, FactoryData> {
206 @Override
207 public JdbcDatabaseManager createManager(final String name, final FactoryData data) {
208 final StringBuilder columnPart = new StringBuilder();
209 final StringBuilder valuePart = new StringBuilder();
210 final List<Column> columns = new ArrayList<>();
211 int i = 0;
212 for (final ColumnConfig config : data.columnConfigs) {
213 if (i++ > 0) {
214 columnPart.append(',');
215 valuePart.append(',');
216 }
217
218 columnPart.append(config.getColumnName());
219
220 if (config.getLiteralValue() != null) {
221 valuePart.append(config.getLiteralValue());
222 } else {
223 columns.add(new Column(
224 config.getLayout(), config.isEventTimestamp(), config.isUnicode(), config.isClob()
225 ));
226 valuePart.append('?');
227 }
228 }
229
230 final String sqlStatement = "INSERT INTO " + data.tableName + " (" + columnPart + ") VALUES (" +
231 valuePart + ')';
232
233 return new JdbcDatabaseManager(name, data.getBufferSize(), data.connectionSource, sqlStatement, columns);
234 }
235 }
236
237 /**
238 * Encapsulates information about a database column and how to persist data to it.
239 */
240 private static final class Column {
241 private final PatternLayout layout;
242 private final boolean isEventTimestamp;
243 private final boolean isUnicode;
244 private final boolean isClob;
245
246 private Column(final PatternLayout layout, final boolean isEventDate, final boolean isUnicode,
247 final boolean isClob) {
248 this.layout = layout;
249 this.isEventTimestamp = isEventDate;
250 this.isUnicode = isUnicode;
251 this.isClob = isClob;
252 }
253 }
254 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.appender.db.jdbc;
17
18 import java.io.StringReader;
19 import java.sql.Connection;
20 import java.sql.DatabaseMetaData;
21 import java.sql.PreparedStatement;
22 import java.sql.SQLException;
23 import java.sql.Timestamp;
24 import java.util.ArrayList;
25 import java.util.List;
26
27 import org.apache.logging.log4j.core.LogEvent;
28 import org.apache.logging.log4j.core.appender.AppenderLoggingException;
29 import org.apache.logging.log4j.core.appender.ManagerFactory;
30 import org.apache.logging.log4j.core.appender.db.AbstractDatabaseManager;
31 import org.apache.logging.log4j.core.layout.PatternLayout;
32 import org.apache.logging.log4j.core.util.Closer;
33
34 /**
35 * An {@link AbstractDatabaseManager} implementation for relational databases accessed via JDBC.
36 */
37 public final class JdbcDatabaseManager extends AbstractDatabaseManager {
38
39 private static final JdbcDatabaseManagerFactory INSTANCE = new JdbcDatabaseManagerFactory();
40
41 private final List<Column> columns;
42 private final ConnectionSource connectionSource;
43 private final String sqlStatement;
44
45 private Connection connection;
46 private PreparedStatement statement;
47 private boolean isBatchSupported;
48
49 private JdbcDatabaseManager(final String name, final int bufferSize, final ConnectionSource connectionSource,
50 final String sqlStatement, final List<Column> columns) {
51 super(name, bufferSize);
52 this.connectionSource = connectionSource;
53 this.sqlStatement = sqlStatement;
54 this.columns = columns;
55 }
56
57 @Override
58 protected void startupInternal() throws Exception {
59 this.connection = this.connectionSource.getConnection();
60 final DatabaseMetaData metaData = this.connection.getMetaData();
61 this.isBatchSupported = metaData.supportsBatchUpdates();
62 Closer.closeSilently(this.connection);
63 }
64
65 @Override
66 protected boolean shutdownInternal() {
67 if (this.connection != null || this.statement != null) {
68 return this.commitAndClose();
69 }
70 return true;
71 }
72
73 @Override
74 protected void connectAndStart() {
75 try {
76 this.connection = this.connectionSource.getConnection();
77 this.connection.setAutoCommit(false);
78 this.statement = this.connection.prepareStatement(this.sqlStatement);
79 } catch (final SQLException e) {
80 throw new AppenderLoggingException(
81 "Cannot write logging event or flush buffer; JDBC manager cannot connect to the database.", e
82 );
83 }
84 }
85
86 @Override
87 protected void writeInternal(final LogEvent event) {
88 StringReader reader = null;
89 try {
90 if (!this.isRunning() || this.connection == null || this.connection.isClosed() || this.statement == null
91 || this.statement.isClosed()) {
92 throw new AppenderLoggingException(
93 "Cannot write logging event; JDBC manager not connected to the database.");
94 }
95
96 int i = 1;
97 for (final Column column : this.columns) {
98 if (column.isEventTimestamp) {
99 this.statement.setTimestamp(i++, new Timestamp(event.getTimeMillis()));
100 } else {
101 if (column.isClob) {
102 reader = new StringReader(column.layout.toSerializable(event));
103 if (column.isUnicode) {
104 this.statement.setNClob(i++, reader);
105 } else {
106 this.statement.setClob(i++, reader);
107 }
108 } else {
109 if (column.isUnicode) {
110 this.statement.setNString(i++, column.layout.toSerializable(event));
111 } else {
112 this.statement.setString(i++, column.layout.toSerializable(event));
113 }
114 }
115 }
116 }
117
118 if (this.isBatchSupported) {
119 this.statement.addBatch();
120 } else if (this.statement.executeUpdate() == 0) {
121 throw new AppenderLoggingException(
122 "No records inserted in database table for log event in JDBC manager.");
123 }
124 } catch (final SQLException e) {
125 throw new AppenderLoggingException("Failed to insert record for log event in JDBC manager: " +
126 e.getMessage(), e);
127 } finally {
128 Closer.closeSilently(reader);
129 }
130 }
131
132 @Override
133 protected boolean commitAndClose() {
134 boolean closed = true;
135 try {
136 if (this.connection != null && !this.connection.isClosed()) {
137 if (this.isBatchSupported) {
138 this.statement.executeBatch();
139 }
140 this.connection.commit();
141 }
142 } catch (final SQLException e) {
143 throw new AppenderLoggingException("Failed to commit transaction logging event or flushing buffer.", e);
144 } finally {
145 try {
146 Closer.close(this.statement);
147 } catch (final Exception e) {
148 logWarn("Failed to close SQL statement logging event or flushing buffer", e);
149 closed = false;
150 } finally {
151 this.statement = null;
152 }
153
154 try {
155 Closer.close(this.connection);
156 } catch (final Exception e) {
157 logWarn("Failed to close database connection logging event or flushing buffer", e);
158 closed = false;
159 } finally {
160 this.connection = null;
161 }
162 }
163 return closed;
164 }
165
166 /**
167 * Creates a JDBC manager for use within the {@link JdbcAppender}, or returns a suitable one if it already exists.
168 *
169 * @param name The name of the manager, which should include connection details and hashed passwords where possible.
170 * @param bufferSize The size of the log event buffer.
171 * @param connectionSource The source for connections to the database.
172 * @param tableName The name of the database table to insert log events into.
173 * @param columnConfigs Configuration information about the log table columns.
174 * @return a new or existing JDBC manager as applicable.
175 */
176 public static JdbcDatabaseManager getJDBCDatabaseManager(final String name, final int bufferSize,
177 final ConnectionSource connectionSource,
178 final String tableName,
179 final ColumnConfig[] columnConfigs) {
180
181 return AbstractDatabaseManager.getManager(
182 name, new FactoryData(bufferSize, connectionSource, tableName, columnConfigs), getFactory()
183 );
184 }
185
186 private static JdbcDatabaseManagerFactory getFactory() {
187 return INSTANCE;
188 }
189
190 /**
191 * Encapsulates data that {@link JdbcDatabaseManagerFactory} uses to create managers.
192 */
193 private static final class FactoryData extends AbstractDatabaseManager.AbstractFactoryData {
194 private final ColumnConfig[] columnConfigs;
195 private final ConnectionSource connectionSource;
196 private final String tableName;
197
198 protected FactoryData(final int bufferSize, final ConnectionSource connectionSource, final String tableName,
199 final ColumnConfig[] columnConfigs) {
200 super(bufferSize);
201 this.connectionSource = connectionSource;
202 this.tableName = tableName;
203 this.columnConfigs = columnConfigs;
204 }
205 }
206
207 /**
208 * Creates managers.
209 */
210 private static final class JdbcDatabaseManagerFactory implements ManagerFactory<JdbcDatabaseManager, FactoryData> {
211 @Override
212 public JdbcDatabaseManager createManager(final String name, final FactoryData data) {
213 final StringBuilder columnPart = new StringBuilder();
214 final StringBuilder valuePart = new StringBuilder();
215 final List<Column> columns = new ArrayList<>();
216 int i = 0;
217 for (final ColumnConfig config : data.columnConfigs) {
218 if (i++ > 0) {
219 columnPart.append(',');
220 valuePart.append(',');
221 }
222
223 columnPart.append(config.getColumnName());
224
225 if (config.getLiteralValue() != null) {
226 valuePart.append(config.getLiteralValue());
227 } else {
228 columns.add(new Column(
229 config.getLayout(), config.isEventTimestamp(), config.isUnicode(), config.isClob()
230 ));
231 valuePart.append('?');
232 }
233 }
234
235 final String sqlStatement = "INSERT INTO " + data.tableName + " (" + columnPart + ") VALUES (" +
236 valuePart + ')';
237
238 return new JdbcDatabaseManager(name, data.getBufferSize(), data.connectionSource, sqlStatement, columns);
239 }
240 }
241
242 /**
243 * Encapsulates information about a database column and how to persist data to it.
244 */
245 private static final class Column {
246 private final PatternLayout layout;
247 private final boolean isEventTimestamp;
248 private final boolean isUnicode;
249 private final boolean isClob;
250
251 private Column(final PatternLayout layout, final boolean isEventDate, final boolean isUnicode,
252 final boolean isClob) {
253 this.layout = layout;
254 this.isEventTimestamp = isEventDate;
255 this.isUnicode = isUnicode;
256 this.isClob = isClob;
257 }
258 }
259 }
1616 package org.apache.logging.log4j.core.appender.db.jpa;
1717
1818 import java.util.Map;
19
2019 import javax.persistence.Inheritance;
2120 import javax.persistence.InheritanceType;
2221 import javax.persistence.MappedSuperclass;
2625 import org.apache.logging.log4j.Marker;
2726 import org.apache.logging.log4j.ThreadContext;
2827 import org.apache.logging.log4j.core.AbstractLogEvent;
28 import org.apache.logging.log4j.util.ReadOnlyStringMap;
2929 import org.apache.logging.log4j.core.LogEvent;
30 import org.apache.logging.log4j.core.appender.db.jpa.converter.ContextDataAttributeConverter;
3031 import org.apache.logging.log4j.message.Message;
3132
3233 /**
218219 /**
219220 * A no-op mutator to satisfy JPA requirements, as this entity is write-only.
220221 *
221 * @param contextMap Ignored.
222 */
223 @SuppressWarnings("unused")
224 public void setContextMap(final Map<String, String> contextMap) {
222 * @param contextData Ignored.
223 */
224 @SuppressWarnings("unused")
225 public void setContextData(final ReadOnlyStringMap contextData) {
226 // this entity is write-only
227 }
228
229 /**
230 * A no-op mutator to satisfy JPA requirements, as this entity is write-only.
231 *
232 * @param map Ignored.
233 */
234 @SuppressWarnings("unused")
235 public void setContextMap(final Map<String, String> map) {
225236 // this entity is write-only
226237 }
227238
280291 }
281292
282293 /**
294 * Gets the context map. Transient, since the String version of the data is obtained via ReadOnlyStringMap.
295 *
296 * @return the context data.
297 * @see ContextDataAttributeConverter
298 * @see org.apache.logging.log4j.core.appender.db.jpa.converter.ContextDataAttributeConverter
299 */
300 @Override
301 @Transient
302 //@Convert(converter = ContextDataAttributeConverter.class)
303 public ReadOnlyStringMap getContextData() {
304 return this.getWrappedEvent().getContextData();
305 }
306
307 /**
283308 * A no-op log event class to prevent {@code NullPointerException}s. O/RMs tend to create instances of entities in
284309 * order to "play around" with them.
285310 */
1616 package org.apache.logging.log4j.core.appender.db.jpa;
1717
1818 import java.util.Map;
19
2019 import javax.persistence.Basic;
2120 import javax.persistence.Convert;
2221 import javax.persistence.MappedSuperclass;
1717
1818 import java.lang.reflect.Constructor;
1919
20 import org.apache.logging.log4j.core.Appender;
2021 import org.apache.logging.log4j.core.Filter;
2122 import org.apache.logging.log4j.core.LogEvent;
2223 import org.apache.logging.log4j.core.appender.AbstractAppender;
2627 import org.apache.logging.log4j.core.config.plugins.PluginElement;
2728 import org.apache.logging.log4j.core.config.plugins.PluginFactory;
2829 import org.apache.logging.log4j.core.util.Booleans;
29 import org.apache.logging.log4j.core.util.Loader;
30 import org.apache.logging.log4j.util.LoaderUtil;
3031 import org.apache.logging.log4j.util.Strings;
3132
3233 /**
3637 *
3738 * @see AbstractLogEventWrapperEntity
3839 */
39 @Plugin(name = "JPA", category = "Core", elementType = "appender", printObject = true)
40 @Plugin(name = "JPA", category = "Core", elementType = Appender.ELEMENT_TYPE, printObject = true)
4041 public final class JpaAppender extends AbstractDatabaseAppender<JpaDatabaseManager> {
4142
4243 private final String description;
8485
8586 try {
8687 final Class<? extends AbstractLogEventWrapperEntity> entityClass =
87 Loader.loadClass(entityClassName).asSubclass(AbstractLogEventWrapperEntity.class);
88 LoaderUtil.loadClass(entityClassName).asSubclass(AbstractLogEventWrapperEntity.class);
8889
8990 try {
9091 entityClass.getConstructor();
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.appender.db.jpa;
17
18 import java.lang.reflect.Constructor;
19
20 import javax.persistence.EntityManager;
21 import javax.persistence.EntityManagerFactory;
22 import javax.persistence.EntityTransaction;
23 import javax.persistence.Persistence;
24
25 import org.apache.logging.log4j.core.LogEvent;
26 import org.apache.logging.log4j.core.appender.AppenderLoggingException;
27 import org.apache.logging.log4j.core.appender.ManagerFactory;
28 import org.apache.logging.log4j.core.appender.db.AbstractDatabaseManager;
29
30 /**
31 * An {@link AbstractDatabaseManager} implementation for relational databases accessed via JPA.
32 */
33 public final class JpaDatabaseManager extends AbstractDatabaseManager {
34 private static final JPADatabaseManagerFactory FACTORY = new JPADatabaseManagerFactory();
35
36 private final String entityClassName;
37 private final Constructor<? extends AbstractLogEventWrapperEntity> entityConstructor;
38 private final String persistenceUnitName;
39
40 private EntityManagerFactory entityManagerFactory;
41
42 private EntityManager entityManager;
43 private EntityTransaction transaction;
44
45 private JpaDatabaseManager(final String name, final int bufferSize,
46 final Class<? extends AbstractLogEventWrapperEntity> entityClass,
47 final Constructor<? extends AbstractLogEventWrapperEntity> entityConstructor,
48 final String persistenceUnitName) {
49 super(name, bufferSize);
50 this.entityClassName = entityClass.getName();
51 this.entityConstructor = entityConstructor;
52 this.persistenceUnitName = persistenceUnitName;
53 }
54
55 @Override
56 protected void startupInternal() {
57 this.entityManagerFactory = Persistence.createEntityManagerFactory(this.persistenceUnitName);
58 }
59
60 @Override
61 protected void shutdownInternal() {
62 if (this.entityManager != null || this.transaction != null) {
63 this.commitAndClose();
64 }
65 if (this.entityManagerFactory != null && this.entityManagerFactory.isOpen()) {
66 this.entityManagerFactory.close();
67 }
68 }
69
70 @Override
71 protected void connectAndStart() {
72 try {
73 this.entityManager = this.entityManagerFactory.createEntityManager();
74 this.transaction = this.entityManager.getTransaction();
75 this.transaction.begin();
76 } catch (final Exception e) {
77 throw new AppenderLoggingException(
78 "Cannot write logging event or flush buffer; manager cannot create EntityManager or transaction.", e
79 );
80 }
81 }
82
83 @Override
84 protected void writeInternal(final LogEvent event) {
85 if (!this.isRunning() || this.entityManagerFactory == null || this.entityManager == null
86 || this.transaction == null) {
87 throw new AppenderLoggingException(
88 "Cannot write logging event; JPA manager not connected to the database.");
89 }
90
91 AbstractLogEventWrapperEntity entity;
92 try {
93 entity = this.entityConstructor.newInstance(event);
94 } catch (final Exception e) {
95 throw new AppenderLoggingException("Failed to instantiate entity class [" + this.entityClassName + "].", e);
96 }
97
98 try {
99 this.entityManager.persist(entity);
100 } catch (final Exception e) {
101 if (this.transaction != null && this.transaction.isActive()) {
102 this.transaction.rollback();
103 this.transaction = null;
104 }
105 throw new AppenderLoggingException("Failed to insert record for log event in JPA manager: " +
106 e.getMessage(), e);
107 }
108 }
109
110 @Override
111 protected void commitAndClose() {
112 try {
113 if (this.transaction != null && this.transaction.isActive()) {
114 this.transaction.commit();
115 }
116 } catch (final Exception e) {
117 if (this.transaction != null && this.transaction.isActive()) {
118 this.transaction.rollback();
119 }
120 } finally {
121 this.transaction = null;
122 try {
123 if (this.entityManager != null && this.entityManager.isOpen()) {
124 this.entityManager.close();
125 }
126 } catch (final Exception e) {
127 logWarn("failed to close entity manager while logging event or flushing buffer", e);
128 } finally {
129 this.entityManager = null;
130 }
131 }
132 }
133
134 /**
135 * Creates a JPA manager for use within the {@link JpaAppender}, or returns a suitable one if it already exists.
136 *
137 * @param name The name of the manager, which should include connection details, entity class name, etc.
138 * @param bufferSize The size of the log event buffer.
139 * @param entityClass The fully-qualified class name of the {@link AbstractLogEventWrapperEntity} concrete
140 * implementation.
141 * @param entityConstructor The one-arg {@link LogEvent} constructor for the concrete entity class.
142 * @param persistenceUnitName The name of the JPA persistence unit that should be used for persisting log events.
143 * @return a new or existing JPA manager as applicable.
144 */
145 public static JpaDatabaseManager getJPADatabaseManager(final String name, final int bufferSize,
146 final Class<? extends AbstractLogEventWrapperEntity>
147 entityClass,
148 final Constructor<? extends AbstractLogEventWrapperEntity>
149 entityConstructor,
150 final String persistenceUnitName) {
151
152 return AbstractDatabaseManager.getManager(
153 name, new FactoryData(bufferSize, entityClass, entityConstructor, persistenceUnitName), FACTORY
154 );
155 }
156
157 /**
158 * Encapsulates data that {@link JPADatabaseManagerFactory} uses to create managers.
159 */
160 private static final class FactoryData extends AbstractDatabaseManager.AbstractFactoryData {
161 private final Class<? extends AbstractLogEventWrapperEntity> entityClass;
162 private final Constructor<? extends AbstractLogEventWrapperEntity> entityConstructor;
163 private final String persistenceUnitName;
164
165 protected FactoryData(final int bufferSize, final Class<? extends AbstractLogEventWrapperEntity> entityClass,
166 final Constructor<? extends AbstractLogEventWrapperEntity> entityConstructor,
167 final String persistenceUnitName) {
168 super(bufferSize);
169
170 this.entityClass = entityClass;
171 this.entityConstructor = entityConstructor;
172 this.persistenceUnitName = persistenceUnitName;
173 }
174 }
175
176 /**
177 * Creates managers.
178 */
179 private static final class JPADatabaseManagerFactory implements ManagerFactory<JpaDatabaseManager, FactoryData> {
180 @Override
181 public JpaDatabaseManager createManager(final String name, final FactoryData data) {
182 return new JpaDatabaseManager(
183 name, data.getBufferSize(), data.entityClass, data.entityConstructor, data.persistenceUnitName
184 );
185 }
186 }
187 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.appender.db.jpa;
17
18 import java.lang.reflect.Constructor;
19
20 import javax.persistence.EntityManager;
21 import javax.persistence.EntityManagerFactory;
22 import javax.persistence.EntityTransaction;
23 import javax.persistence.Persistence;
24
25 import org.apache.logging.log4j.core.LogEvent;
26 import org.apache.logging.log4j.core.appender.AppenderLoggingException;
27 import org.apache.logging.log4j.core.appender.ManagerFactory;
28 import org.apache.logging.log4j.core.appender.db.AbstractDatabaseManager;
29
30 /**
31 * An {@link AbstractDatabaseManager} implementation for relational databases accessed via JPA.
32 */
33 public final class JpaDatabaseManager extends AbstractDatabaseManager {
34 private static final JPADatabaseManagerFactory FACTORY = new JPADatabaseManagerFactory();
35
36 private final String entityClassName;
37 private final Constructor<? extends AbstractLogEventWrapperEntity> entityConstructor;
38 private final String persistenceUnitName;
39
40 private EntityManagerFactory entityManagerFactory;
41
42 private EntityManager entityManager;
43 private EntityTransaction transaction;
44
45 private JpaDatabaseManager(final String name, final int bufferSize,
46 final Class<? extends AbstractLogEventWrapperEntity> entityClass,
47 final Constructor<? extends AbstractLogEventWrapperEntity> entityConstructor,
48 final String persistenceUnitName) {
49 super(name, bufferSize);
50 this.entityClassName = entityClass.getName();
51 this.entityConstructor = entityConstructor;
52 this.persistenceUnitName = persistenceUnitName;
53 }
54
55 @Override
56 protected void startupInternal() {
57 this.entityManagerFactory = Persistence.createEntityManagerFactory(this.persistenceUnitName);
58 }
59
60 @Override
61 protected boolean shutdownInternal() {
62 boolean closed = true;
63 if (this.entityManager != null || this.transaction != null) {
64 closed &= this.commitAndClose();
65 }
66 if (this.entityManagerFactory != null && this.entityManagerFactory.isOpen()) {
67 this.entityManagerFactory.close();
68 }
69 return closed;
70 }
71
72 @Override
73 protected void connectAndStart() {
74 try {
75 this.entityManager = this.entityManagerFactory.createEntityManager();
76 this.transaction = this.entityManager.getTransaction();
77 this.transaction.begin();
78 } catch (final Exception e) {
79 throw new AppenderLoggingException(
80 "Cannot write logging event or flush buffer; manager cannot create EntityManager or transaction.", e
81 );
82 }
83 }
84
85 @Override
86 protected void writeInternal(final LogEvent event) {
87 if (!this.isRunning() || this.entityManagerFactory == null || this.entityManager == null
88 || this.transaction == null) {
89 throw new AppenderLoggingException(
90 "Cannot write logging event; JPA manager not connected to the database.");
91 }
92
93 AbstractLogEventWrapperEntity entity;
94 try {
95 entity = this.entityConstructor.newInstance(event);
96 } catch (final Exception e) {
97 throw new AppenderLoggingException("Failed to instantiate entity class [" + this.entityClassName + "].", e);
98 }
99
100 try {
101 this.entityManager.persist(entity);
102 } catch (final Exception e) {
103 if (this.transaction != null && this.transaction.isActive()) {
104 this.transaction.rollback();
105 this.transaction = null;
106 }
107 throw new AppenderLoggingException("Failed to insert record for log event in JPA manager: " +
108 e.getMessage(), e);
109 }
110 }
111
112 @Override
113 protected boolean commitAndClose() {
114 boolean closed = true;
115 try {
116 if (this.transaction != null && this.transaction.isActive()) {
117 this.transaction.commit();
118 }
119 } catch (final Exception e) {
120 if (this.transaction != null && this.transaction.isActive()) {
121 this.transaction.rollback();
122 }
123 } finally {
124 this.transaction = null;
125 try {
126 if (this.entityManager != null && this.entityManager.isOpen()) {
127 this.entityManager.close();
128 }
129 } catch (final Exception e) {
130 logWarn("Failed to close entity manager while logging event or flushing buffer", e);
131 closed = false;
132 } finally {
133 this.entityManager = null;
134 }
135 }
136 return closed;
137 }
138
139 /**
140 * Creates a JPA manager for use within the {@link JpaAppender}, or returns a suitable one if it already exists.
141 *
142 * @param name The name of the manager, which should include connection details, entity class name, etc.
143 * @param bufferSize The size of the log event buffer.
144 * @param entityClass The fully-qualified class name of the {@link AbstractLogEventWrapperEntity} concrete
145 * implementation.
146 * @param entityConstructor The one-arg {@link LogEvent} constructor for the concrete entity class.
147 * @param persistenceUnitName The name of the JPA persistence unit that should be used for persisting log events.
148 * @return a new or existing JPA manager as applicable.
149 */
150 public static JpaDatabaseManager getJPADatabaseManager(final String name, final int bufferSize,
151 final Class<? extends AbstractLogEventWrapperEntity>
152 entityClass,
153 final Constructor<? extends AbstractLogEventWrapperEntity>
154 entityConstructor,
155 final String persistenceUnitName) {
156
157 return AbstractDatabaseManager.getManager(
158 name, new FactoryData(bufferSize, entityClass, entityConstructor, persistenceUnitName), FACTORY
159 );
160 }
161
162 /**
163 * Encapsulates data that {@link JPADatabaseManagerFactory} uses to create managers.
164 */
165 private static final class FactoryData extends AbstractDatabaseManager.AbstractFactoryData {
166 private final Class<? extends AbstractLogEventWrapperEntity> entityClass;
167 private final Constructor<? extends AbstractLogEventWrapperEntity> entityConstructor;
168 private final String persistenceUnitName;
169
170 protected FactoryData(final int bufferSize, final Class<? extends AbstractLogEventWrapperEntity> entityClass,
171 final Constructor<? extends AbstractLogEventWrapperEntity> entityConstructor,
172 final String persistenceUnitName) {
173 super(bufferSize);
174
175 this.entityClass = entityClass;
176 this.entityConstructor = entityConstructor;
177 this.persistenceUnitName = persistenceUnitName;
178 }
179 }
180
181 /**
182 * Creates managers.
183 */
184 private static final class JPADatabaseManagerFactory implements ManagerFactory<JpaDatabaseManager, FactoryData> {
185 @Override
186 public JpaDatabaseManager createManager(final String name, final FactoryData data) {
187 return new JpaDatabaseManager(
188 name, data.getBufferSize(), data.entityClass, data.entityConstructor, data.persistenceUnitName
189 );
190 }
191 }
192 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.appender.db.jpa.converter;
17
18 import javax.persistence.AttributeConverter;
19 import javax.persistence.Converter;
20
21 import org.apache.logging.log4j.util.ReadOnlyStringMap;
22
23 /**
24 * A JPA 2.1 attribute converter for {@link ReadOnlyStringMap}s in
25 * {@link org.apache.logging.log4j.core.LogEvent}s. This converter is only capable of converting to {@link String}s. The
26 * {@link #convertToEntityAttribute(String)} method throws an {@link UnsupportedOperationException}. If you need to
27 * support converting to an entity attribute, you should use the {@link ContextMapJsonAttributeConverter} for conversion
28 * both ways.
29 */
30 @Converter(autoApply = false)
31 public class ContextDataAttributeConverter implements AttributeConverter<ReadOnlyStringMap, String> {
32 @Override
33 public String convertToDatabaseColumn(final ReadOnlyStringMap contextData) {
34 if (contextData == null) {
35 return null;
36 }
37
38 return contextData.toString();
39 }
40
41 @Override
42 public ReadOnlyStringMap convertToEntityAttribute(final String s) {
43 throw new UnsupportedOperationException("Log events can only be persisted, not extracted.");
44 }
45 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.appender.db.jpa.converter;
17
18 import java.io.IOException;
19 import java.util.Iterator;
20 import java.util.Map;
21 import javax.persistence.AttributeConverter;
22 import javax.persistence.Converter;
23 import javax.persistence.PersistenceException;
24
25 import org.apache.logging.log4j.util.ReadOnlyStringMap;
26 import org.apache.logging.log4j.core.impl.ContextDataFactory;
27 import org.apache.logging.log4j.util.StringMap;
28 import org.apache.logging.log4j.util.BiConsumer;
29 import org.apache.logging.log4j.util.Strings;
30
31 import com.fasterxml.jackson.databind.JsonNode;
32 import com.fasterxml.jackson.databind.ObjectMapper;
33 import com.fasterxml.jackson.databind.node.JsonNodeFactory;
34 import com.fasterxml.jackson.databind.node.ObjectNode;
35
36 /**
37 * A JPA 2.1 attribute converter for {@link ReadOnlyStringMap}s in
38 * {@link org.apache.logging.log4j.core.LogEvent}s. This converter is capable of converting both to and from
39 * {@link String}s.
40 *
41 * In addition to other optional dependencies required by the JPA appender, this converter requires the Jackson Data
42 * Processor.
43 */
44 @Converter(autoApply = false)
45 public class ContextDataJsonAttributeConverter implements AttributeConverter<ReadOnlyStringMap, String> {
46 static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
47
48 @Override
49 public String convertToDatabaseColumn(final ReadOnlyStringMap contextData) {
50 if (contextData == null) {
51 return null;
52 }
53
54 try {
55 final JsonNodeFactory factory = OBJECT_MAPPER.getNodeFactory();
56 final ObjectNode root = factory.objectNode();
57 contextData.forEach(new BiConsumer<String, Object>() {
58 @Override
59 public void accept(final String key, final Object value) {
60 // we will cheat here and write the toString of the Object... meh, but ok.
61 root.put(key, String.valueOf(value));
62 }
63 });
64 return OBJECT_MAPPER.writeValueAsString(root);
65 } catch (final Exception e) {
66 throw new PersistenceException("Failed to convert contextData to JSON string.", e);
67 }
68 }
69
70 @Override
71 public ReadOnlyStringMap convertToEntityAttribute(final String s) {
72 if (Strings.isEmpty(s)) {
73 return null;
74 }
75 try {
76 final StringMap result = ContextDataFactory.createContextData();
77 final ObjectNode root = (ObjectNode) OBJECT_MAPPER.readTree(s);
78 final Iterator<Map.Entry<String, JsonNode>> entries = root.fields();
79 while (entries.hasNext()) {
80 final Map.Entry<String, JsonNode> entry = entries.next();
81
82 // Don't know what to do with non-text values.
83 // Maybe users who need this need to provide custom converter?
84 final Object value = entry.getValue().textValue();
85 result.putValue(entry.getKey(), value);
86 }
87 return result;
88 } catch (final IOException e) {
89 throw new PersistenceException("Failed to convert JSON string to map.", e);
90 }
91 }
92 }
2525 import javax.persistence.AttributeConverter;
2626 import javax.persistence.Converter;
2727
28 import org.apache.logging.log4j.core.util.Loader;
28 import org.apache.logging.log4j.util.LoaderUtil;
2929 import org.apache.logging.log4j.util.Strings;
3030
3131 /**
124124 final StackTraceElement[] stackTrace) {
125125 try {
126126 @SuppressWarnings("unchecked")
127 final Class<Throwable> throwableClass = (Class<Throwable>) Loader.loadClass(throwableClassName);
127 final Class<Throwable> throwableClass = (Class<Throwable>) LoaderUtil.loadClass(throwableClassName);
128128
129129 if (!Throwable.class.isAssignableFrom(throwableClass)) {
130130 return null;
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16
17 package org.apache.logging.log4j.core.appender.mom;
18
19 import java.io.Serializable;
20 import javax.jms.JMSException;
21 import javax.jms.Message;
22 import javax.jms.MessageProducer;
23
24 import org.apache.logging.log4j.core.Appender;
25 import org.apache.logging.log4j.core.Filter;
26 import org.apache.logging.log4j.core.Layout;
27 import org.apache.logging.log4j.core.LogEvent;
28 import org.apache.logging.log4j.core.appender.AbstractAppender;
29 import org.apache.logging.log4j.core.appender.AppenderLoggingException;
30 import org.apache.logging.log4j.core.config.Node;
31 import org.apache.logging.log4j.core.config.plugins.Plugin;
32 import org.apache.logging.log4j.core.config.plugins.PluginAliases;
33 import org.apache.logging.log4j.core.config.plugins.PluginBuilderAttribute;
34 import org.apache.logging.log4j.core.config.plugins.PluginBuilderFactory;
35 import org.apache.logging.log4j.core.config.plugins.PluginElement;
36 import org.apache.logging.log4j.core.config.plugins.validation.constraints.Required;
37 import org.apache.logging.log4j.core.layout.SerializedLayout;
38 import org.apache.logging.log4j.core.net.JndiManager;
39
40 /**
41 * Generic JMS Appender plugin for both queues and topics. This Appender replaces the previous split ones. However,
42 * configurations set up for the 2.0 version of the JMS appenders will still work.
43 */
44 @Plugin(name = "JMS", category = Node.CATEGORY, elementType = Appender.ELEMENT_TYPE, printObject = true)
45 @PluginAliases({"JMSQueue", "JMSTopic"})
46 public class JmsAppender extends AbstractAppender {
47
48 private final JmsManager manager;
49 private final MessageProducer producer;
50
51 protected JmsAppender(final String name, final Filter filter, final Layout<? extends Serializable> layout,
52 final boolean ignoreExceptions, final JmsManager manager)
53 throws JMSException {
54 super(name, filter, layout, ignoreExceptions);
55 this.manager = manager;
56 this.producer = this.manager.createMessageProducer();
57 }
58
59 @Override
60 public void append(final LogEvent event) {
61 try {
62 final Message message = this.manager.createMessage(getLayout().toSerializable(event));
63 message.setJMSTimestamp(event.getTimeMillis());
64 this.producer.send(message);
65 } catch (final JMSException e) {
66 throw new AppenderLoggingException(e);
67 }
68 }
69
70 @Override
71 public void stop() {
72 this.manager.release();
73 super.stop();
74 }
75
76 @PluginBuilderFactory
77 public static Builder newBuilder() {
78 return new Builder();
79 }
80
81 public static class Builder implements org.apache.logging.log4j.core.util.Builder<JmsAppender> {
82
83 @PluginBuilderAttribute
84 @Required(message = "A name for the JmsAppender must be specified")
85 private String name;
86
87 @PluginBuilderAttribute
88 private String factoryName;
89
90 @PluginBuilderAttribute
91 private String providerUrl;
92
93 @PluginBuilderAttribute
94 private String urlPkgPrefixes;
95
96 @PluginBuilderAttribute
97 private String securityPrincipalName;
98
99 @PluginBuilderAttribute(sensitive = true)
100 private String securityCredentials;
101
102 @PluginBuilderAttribute
103 @Required(message = "A javax.jms.ConnectionFactory JNDI name must be specified")
104 private String factoryBindingName;
105
106 @PluginBuilderAttribute
107 @PluginAliases({"queueBindingName", "topicBindingName"})
108 @Required(message = "A javax.jms.Destination JNDI name must be specified")
109 private String destinationBindingName;
110
111 @PluginBuilderAttribute
112 private String username;
113
114 @PluginBuilderAttribute(sensitive = true)
115 private String password;
116
117 @PluginElement("Layout")
118 private Layout<? extends Serializable> layout = SerializedLayout.createLayout();
119
120 @PluginElement("Filter")
121 private Filter filter;
122
123 @PluginBuilderAttribute
124 private boolean ignoreExceptions = true;
125
126 private Builder() {
127 }
128
129 public Builder setName(final String name) {
130 this.name = name;
131 return this;
132 }
133
134 public Builder setFactoryName(final String factoryName) {
135 this.factoryName = factoryName;
136 return this;
137 }
138
139 public Builder setProviderUrl(final String providerUrl) {
140 this.providerUrl = providerUrl;
141 return this;
142 }
143
144 public Builder setUrlPkgPrefixes(final String urlPkgPrefixes) {
145 this.urlPkgPrefixes = urlPkgPrefixes;
146 return this;
147 }
148
149 public Builder setSecurityPrincipalName(final String securityPrincipalName) {
150 this.securityPrincipalName = securityPrincipalName;
151 return this;
152 }
153
154 public Builder setSecurityCredentials(final String securityCredentials) {
155 this.securityCredentials = securityCredentials;
156 return this;
157 }
158
159 public Builder setFactoryBindingName(final String factoryBindingName) {
160 this.factoryBindingName = factoryBindingName;
161 return this;
162 }
163
164 public Builder setDestinationBindingName(final String destinationBindingName) {
165 this.destinationBindingName = destinationBindingName;
166 return this;
167 }
168
169 public Builder setUsername(final String username) {
170 this.username = username;
171 return this;
172 }
173
174 public Builder setPassword(final String password) {
175 this.password = password;
176 return this;
177 }
178
179 public Builder setLayout(final Layout<? extends Serializable> layout) {
180 this.layout = layout;
181 return this;
182 }
183
184 public Builder setFilter(final Filter filter) {
185 this.filter = filter;
186 return this;
187 }
188
189 public Builder setIgnoreExceptions(final boolean ignoreExceptions) {
190 this.ignoreExceptions = ignoreExceptions;
191 return this;
192 }
193
194 @Override
195 public JmsAppender build() {
196 final JndiManager jndiManager = JndiManager.getJndiManager(factoryName, providerUrl, urlPkgPrefixes,
197 securityPrincipalName, securityCredentials, null);
198 final JmsManager jmsManager = JmsManager.getJmsManager(name, jndiManager, factoryBindingName,
199 destinationBindingName, username, password);
200 try {
201 return new JmsAppender(name, filter, layout, ignoreExceptions, jmsManager);
202 } catch (final JMSException e) {
203 LOGGER.error("Error creating JmsAppender [{}].", name, e);
204 return null;
205 }
206 }
207 }
208
209 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16
17 package org.apache.logging.log4j.core.appender.mom;
18
19 import java.io.Serializable;
20 import java.util.concurrent.TimeUnit;
21
22 import javax.jms.JMSException;
23 import javax.jms.Message;
24 import javax.jms.MessageProducer;
25
26 import org.apache.logging.log4j.core.Appender;
27 import org.apache.logging.log4j.core.Filter;
28 import org.apache.logging.log4j.core.Layout;
29 import org.apache.logging.log4j.core.LogEvent;
30 import org.apache.logging.log4j.core.appender.AbstractAppender;
31 import org.apache.logging.log4j.core.appender.AppenderLoggingException;
32 import org.apache.logging.log4j.core.config.Node;
33 import org.apache.logging.log4j.core.config.plugins.Plugin;
34 import org.apache.logging.log4j.core.config.plugins.PluginAliases;
35 import org.apache.logging.log4j.core.config.plugins.PluginBuilderAttribute;
36 import org.apache.logging.log4j.core.config.plugins.PluginBuilderFactory;
37 import org.apache.logging.log4j.core.config.plugins.PluginElement;
38 import org.apache.logging.log4j.core.config.plugins.validation.constraints.Required;
39 import org.apache.logging.log4j.core.layout.SerializedLayout;
40 import org.apache.logging.log4j.core.net.JndiManager;
41
42 /**
43 * Generic JMS Appender plugin for both queues and topics. This Appender replaces the previous split ones. However,
44 * configurations set up for the 2.0 version of the JMS appenders will still work.
45 */
46 @Plugin(name = "JMS", category = Node.CATEGORY, elementType = Appender.ELEMENT_TYPE, printObject = true)
47 @PluginAliases({"JMSQueue", "JMSTopic"})
48 public class JmsAppender extends AbstractAppender {
49
50 private final JmsManager manager;
51 private final MessageProducer producer;
52
53 protected JmsAppender(final String name, final Filter filter, final Layout<? extends Serializable> layout,
54 final boolean ignoreExceptions, final JmsManager manager)
55 throws JMSException {
56 super(name, filter, layout, ignoreExceptions);
57 this.manager = manager;
58 this.producer = this.manager.createMessageProducer();
59 }
60
61 @Override
62 public void append(final LogEvent event) {
63 try {
64 final Message message = this.manager.createMessage(getLayout().toSerializable(event));
65 message.setJMSTimestamp(event.getTimeMillis());
66 this.producer.send(message);
67 } catch (final JMSException e) {
68 throw new AppenderLoggingException(e);
69 }
70 }
71
72 @Override
73 public boolean stop(final long timeout, final TimeUnit timeUnit) {
74 setStopping();
75 boolean stopped = super.stop(timeout, timeUnit, false);
76 stopped &= this.manager.stop(timeout, timeUnit);
77 setStopped();
78 return stopped;
79 }
80
81 @PluginBuilderFactory
82 public static Builder newBuilder() {
83 return new Builder();
84 }
85
86 public static class Builder implements org.apache.logging.log4j.core.util.Builder<JmsAppender> {
87
88 @PluginBuilderAttribute
89 @Required(message = "A name for the JmsAppender must be specified")
90 private String name;
91
92 @PluginBuilderAttribute
93 private String factoryName;
94
95 @PluginBuilderAttribute
96 private String providerUrl;
97
98 @PluginBuilderAttribute
99 private String urlPkgPrefixes;
100
101 @PluginBuilderAttribute
102 private String securityPrincipalName;
103
104 @PluginBuilderAttribute(sensitive = true)
105 private String securityCredentials;
106
107 @PluginBuilderAttribute
108 @Required(message = "A javax.jms.ConnectionFactory JNDI name must be specified")
109 private String factoryBindingName;
110
111 @PluginBuilderAttribute
112 @PluginAliases({"queueBindingName", "topicBindingName"})
113 @Required(message = "A javax.jms.Destination JNDI name must be specified")
114 private String destinationBindingName;
115
116 @PluginBuilderAttribute
117 private String username;
118
119 @PluginBuilderAttribute(sensitive = true)
120 private String password;
121
122 @PluginElement("Layout")
123 private Layout<? extends Serializable> layout = SerializedLayout.createLayout();
124
125 @PluginElement("Filter")
126 private Filter filter;
127
128 @PluginBuilderAttribute
129 private boolean ignoreExceptions = true;
130
131 private Builder() {
132 }
133
134 public Builder setName(final String name) {
135 this.name = name;
136 return this;
137 }
138
139 public Builder setFactoryName(final String factoryName) {
140 this.factoryName = factoryName;
141 return this;
142 }
143
144 public Builder setProviderUrl(final String providerUrl) {
145 this.providerUrl = providerUrl;
146 return this;
147 }
148
149 public Builder setUrlPkgPrefixes(final String urlPkgPrefixes) {
150 this.urlPkgPrefixes = urlPkgPrefixes;
151 return this;
152 }
153
154 public Builder setSecurityPrincipalName(final String securityPrincipalName) {
155 this.securityPrincipalName = securityPrincipalName;
156 return this;
157 }
158
159 public Builder setSecurityCredentials(final String securityCredentials) {
160 this.securityCredentials = securityCredentials;
161 return this;
162 }
163
164 public Builder setFactoryBindingName(final String factoryBindingName) {
165 this.factoryBindingName = factoryBindingName;
166 return this;
167 }
168
169 public Builder setDestinationBindingName(final String destinationBindingName) {
170 this.destinationBindingName = destinationBindingName;
171 return this;
172 }
173
174 public Builder setUsername(final String username) {
175 this.username = username;
176 return this;
177 }
178
179 public Builder setPassword(final String password) {
180 this.password = password;
181 return this;
182 }
183
184 public Builder setLayout(final Layout<? extends Serializable> layout) {
185 this.layout = layout;
186 return this;
187 }
188
189 public Builder setFilter(final Filter filter) {
190 this.filter = filter;
191 return this;
192 }
193
194 public Builder setIgnoreExceptions(final boolean ignoreExceptions) {
195 this.ignoreExceptions = ignoreExceptions;
196 return this;
197 }
198
199 @Override
200 public JmsAppender build() {
201 final JndiManager jndiManager = JndiManager.getJndiManager(factoryName, providerUrl, urlPkgPrefixes,
202 securityPrincipalName, securityCredentials, null);
203 final JmsManager jmsManager = JmsManager.getJmsManager(name, jndiManager, factoryBindingName,
204 destinationBindingName, username, password);
205 try {
206 return new JmsAppender(name, filter, layout, ignoreExceptions, jmsManager);
207 } catch (final JMSException e) {
208 LOGGER.error("Error creating JmsAppender [{}].", name, e);
209 return null;
210 }
211 }
212 }
213
214 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16
17 package org.apache.logging.log4j.core.appender.mom;
18
19 import java.io.Serializable;
20 import javax.jms.Connection;
21 import javax.jms.ConnectionFactory;
22 import javax.jms.Destination;
23 import javax.jms.JMSException;
24 import javax.jms.Message;
25 import javax.jms.MessageConsumer;
26 import javax.jms.MessageProducer;
27 import javax.jms.Session;
28 import javax.naming.NamingException;
29
30 import org.apache.logging.log4j.Logger;
31 import org.apache.logging.log4j.core.appender.AbstractManager;
32 import org.apache.logging.log4j.core.appender.ManagerFactory;
33 import org.apache.logging.log4j.core.net.JndiManager;
34 import org.apache.logging.log4j.status.StatusLogger;
35
36 /**
37 * JMS connection and session manager. Can be used to access MessageProducer, MessageConsumer, and Message objects
38 * involving a configured ConnectionFactory and Destination.
39 */
40 public class JmsManager extends AbstractManager {
41
42 private static final Logger LOGGER = StatusLogger.getLogger();
43
44 private static final JmsManagerFactory FACTORY = new JmsManagerFactory();
45
46 private final JndiManager jndiManager;
47 private final Connection connection;
48 private final Session session;
49 private final Destination destination;
50
51 private JmsManager(final String name, final JndiManager jndiManager, final String connectionFactoryName,
52 final String destinationName, final String username, final String password)
53 throws NamingException, JMSException {
54 super(name);
55 this.jndiManager = jndiManager;
56 final ConnectionFactory connectionFactory = this.jndiManager.lookup(connectionFactoryName);
57 if (username != null && password != null) {
58 this.connection = connectionFactory.createConnection(username, password);
59 } else {
60 this.connection = connectionFactory.createConnection();
61 }
62 this.session = this.connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
63 this.destination = this.jndiManager.lookup(destinationName);
64 this.connection.start();
65 }
66
67 /**
68 * Gets a JmsManager using the specified configuration parameters.
69 *
70 * @param name The name to use for this JmsManager.
71 * @param jndiManager The JndiManager to look up JMS information through.
72 * @param connectionFactoryName The binding name for the {@link javax.jms.ConnectionFactory}.
73 * @param destinationName The binding name for the {@link javax.jms.Destination}.
74 * @param username The username to connect with or {@code null} for no authentication.
75 * @param password The password to use with the given username or {@code null} for no authentication.
76 * @return The JmsManager as configured.
77 */
78 public static JmsManager getJmsManager(final String name, final JndiManager jndiManager,
79 final String connectionFactoryName, final String destinationName,
80 final String username, final String password) {
81 final JmsConfiguration configuration = new JmsConfiguration(jndiManager, connectionFactoryName, destinationName,
82 username, password);
83 return getManager(name, FACTORY, configuration);
84 }
85
86 /**
87 * Creates a MessageConsumer on this Destination using the current Session.
88 *
89 * @return A MessageConsumer on this Destination.
90 * @throws JMSException
91 */
92 public MessageConsumer createMessageConsumer() throws JMSException {
93 return this.session.createConsumer(this.destination);
94 }
95
96 /**
97 * Creates a MessageProducer on this Destination using the current Session.
98 *
99 * @return A MessageProducer on this Destination.
100 * @throws JMSException
101 */
102 public MessageProducer createMessageProducer() throws JMSException {
103 return this.session.createProducer(this.destination);
104 }
105
106 /**
107 * Creates a TextMessage or ObjectMessage from a Serializable object. For instance, when using a text-based
108 * {@link org.apache.logging.log4j.core.Layout} such as {@link org.apache.logging.log4j.core.layout.PatternLayout},
109 * the {@link org.apache.logging.log4j.core.LogEvent} message will be serialized to a String. When using a
110 * layout such as {@link org.apache.logging.log4j.core.layout.SerializedLayout}, the LogEvent message will be
111 * serialized as a Java object.
112 *
113 * @param object The LogEvent or String message to wrap.
114 * @return A new JMS message containing the provided object.
115 * @throws JMSException
116 */
117 public Message createMessage(final Serializable object) throws JMSException {
118 if (object instanceof String) {
119 return this.session.createTextMessage((String) object);
120 }
121 return this.session.createObjectMessage(object);
122 }
123
124 @Override
125 protected void releaseSub() {
126 try {
127 this.session.close();
128 } catch (final JMSException ignored) {
129 }
130 try {
131 this.connection.close();
132 } catch (final JMSException ignored) {
133 }
134 this.jndiManager.release();
135 }
136
137 private static class JmsConfiguration {
138 private final JndiManager jndiManager;
139 private final String connectionFactoryName;
140 private final String destinationName;
141 private final String username;
142 private final String password;
143
144 private JmsConfiguration(final JndiManager jndiManager, final String connectionFactoryName, final String destinationName,
145 final String username, final String password) {
146 this.jndiManager = jndiManager;
147 this.connectionFactoryName = connectionFactoryName;
148 this.destinationName = destinationName;
149 this.username = username;
150 this.password = password;
151 }
152 }
153
154 private static class JmsManagerFactory implements ManagerFactory<JmsManager, JmsConfiguration> {
155
156 @Override
157 public JmsManager createManager(final String name, final JmsConfiguration data) {
158 try {
159 return new JmsManager(name, data.jndiManager, data.connectionFactoryName, data.destinationName,
160 data.username, data.password);
161 } catch (final Exception e) {
162 LOGGER.error("Error creating JmsManager using ConnectionFactory [{}] and Destination [{}].",
163 data.connectionFactoryName, data.destinationName, e);
164 return null;
165 }
166 }
167 }
168
169 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16
17 package org.apache.logging.log4j.core.appender.mom;
18
19 import java.io.Serializable;
20 import java.util.concurrent.TimeUnit;
21
22 import javax.jms.Connection;
23 import javax.jms.ConnectionFactory;
24 import javax.jms.Destination;
25 import javax.jms.JMSException;
26 import javax.jms.Message;
27 import javax.jms.MessageConsumer;
28 import javax.jms.MessageProducer;
29 import javax.jms.Session;
30 import javax.naming.NamingException;
31
32 import org.apache.logging.log4j.Logger;
33 import org.apache.logging.log4j.core.appender.AbstractManager;
34 import org.apache.logging.log4j.core.appender.ManagerFactory;
35 import org.apache.logging.log4j.core.net.JndiManager;
36 import org.apache.logging.log4j.status.StatusLogger;
37
38 /**
39 * JMS connection and session manager. Can be used to access MessageProducer, MessageConsumer, and Message objects
40 * involving a configured ConnectionFactory and Destination.
41 */
42 public class JmsManager extends AbstractManager {
43
44 private static final Logger LOGGER = StatusLogger.getLogger();
45
46 private static final JmsManagerFactory FACTORY = new JmsManagerFactory();
47
48 private final JndiManager jndiManager;
49 private final Connection connection;
50 private final Session session;
51 private final Destination destination;
52
53 private JmsManager(final String name, final JndiManager jndiManager, final String connectionFactoryName,
54 final String destinationName, final String username, final String password)
55 throws NamingException, JMSException {
56 super(null, name);
57 this.jndiManager = jndiManager;
58 final ConnectionFactory connectionFactory = this.jndiManager.lookup(connectionFactoryName);
59 if (username != null && password != null) {
60 this.connection = connectionFactory.createConnection(username, password);
61 } else {
62 this.connection = connectionFactory.createConnection();
63 }
64 this.session = this.connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
65 this.destination = this.jndiManager.lookup(destinationName);
66 this.connection.start();
67 }
68
69 /**
70 * Gets a JmsManager using the specified configuration parameters.
71 *
72 * @param name The name to use for this JmsManager.
73 * @param jndiManager The JndiManager to look up JMS information through.
74 * @param connectionFactoryName The binding name for the {@link javax.jms.ConnectionFactory}.
75 * @param destinationName The binding name for the {@link javax.jms.Destination}.
76 * @param username The username to connect with or {@code null} for no authentication.
77 * @param password The password to use with the given username or {@code null} for no authentication.
78 * @return The JmsManager as configured.
79 */
80 public static JmsManager getJmsManager(final String name, final JndiManager jndiManager,
81 final String connectionFactoryName, final String destinationName,
82 final String username, final String password) {
83 final JmsConfiguration configuration = new JmsConfiguration(jndiManager, connectionFactoryName, destinationName,
84 username, password);
85 return getManager(name, FACTORY, configuration);
86 }
87
88 /**
89 * Creates a MessageConsumer on this Destination using the current Session.
90 *
91 * @return A MessageConsumer on this Destination.
92 * @throws JMSException
93 */
94 public MessageConsumer createMessageConsumer() throws JMSException {
95 return this.session.createConsumer(this.destination);
96 }
97
98 /**
99 * Creates a MessageProducer on this Destination using the current Session.
100 *
101 * @return A MessageProducer on this Destination.
102 * @throws JMSException
103 */
104 public MessageProducer createMessageProducer() throws JMSException {
105 return this.session.createProducer(this.destination);
106 }
107
108 /**
109 * Creates a TextMessage or ObjectMessage from a Serializable object. For instance, when using a text-based
110 * {@link org.apache.logging.log4j.core.Layout} such as {@link org.apache.logging.log4j.core.layout.PatternLayout},
111 * the {@link org.apache.logging.log4j.core.LogEvent} message will be serialized to a String. When using a
112 * layout such as {@link org.apache.logging.log4j.core.layout.SerializedLayout}, the LogEvent message will be
113 * serialized as a Java object.
114 *
115 * @param object The LogEvent or String message to wrap.
116 * @return A new JMS message containing the provided object.
117 * @throws JMSException
118 */
119 public Message createMessage(final Serializable object) throws JMSException {
120 if (object instanceof String) {
121 return this.session.createTextMessage((String) object);
122 }
123 return this.session.createObjectMessage(object);
124 }
125
126 @Override
127 protected boolean releaseSub(final long timeout, final TimeUnit timeUnit) {
128 boolean closed = true;
129 try {
130 this.session.close();
131 } catch (final JMSException ignored) {
132 // ignore
133 closed = false;
134 }
135 try {
136 this.connection.close();
137 } catch (final JMSException ignored) {
138 // ignore
139 closed = false;
140 }
141 return closed && this.jndiManager.stop(timeout, timeUnit);
142 }
143
144 private static class JmsConfiguration {
145 private final JndiManager jndiManager;
146 private final String connectionFactoryName;
147 private final String destinationName;
148 private final String username;
149 private final String password;
150
151 private JmsConfiguration(final JndiManager jndiManager, final String connectionFactoryName, final String destinationName,
152 final String username, final String password) {
153 this.jndiManager = jndiManager;
154 this.connectionFactoryName = connectionFactoryName;
155 this.destinationName = destinationName;
156 this.username = username;
157 this.password = password;
158 }
159 }
160
161 private static class JmsManagerFactory implements ManagerFactory<JmsManager, JmsConfiguration> {
162
163 @Override
164 public JmsManager createManager(final String name, final JmsConfiguration data) {
165 try {
166 return new JmsManager(name, data.jndiManager, data.connectionFactoryName, data.destinationName,
167 data.username, data.password);
168 } catch (final Exception e) {
169 LOGGER.error("Error creating JmsManager using ConnectionFactory [{}] and Destination [{}].",
170 data.connectionFactoryName, data.destinationName, e);
171 return null;
172 }
173 }
174 }
175
176 }
1919 import java.io.Serializable;
2020 import java.util.ArrayList;
2121 import java.util.List;
22 import java.util.concurrent.TimeUnit;
2223
2324 import org.apache.logging.log4j.core.Appender;
2425 import org.apache.logging.log4j.core.Filter;
148149 }
149150
150151 @Override
151 public void stop() {
152 manager.release();
153 super.stop();
152 public boolean stop(final long timeout, final TimeUnit timeUnit) {
153 setStopping();
154 boolean stopped = super.stop(timeout, timeUnit, false);
155 stopped &= manager.stop(timeout, timeUnit);
156 setStopped();
157 return stopped;
154158 }
155159
156160 // not public, handy for testing
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16
17 package org.apache.logging.log4j.core.appender.mom.jeromq;
18
19 import java.util.Arrays;
20 import java.util.List;
21
22 import org.apache.logging.log4j.LogManager;
23 import org.apache.logging.log4j.core.appender.AbstractManager;
24 import org.apache.logging.log4j.core.appender.ManagerFactory;
25 import org.apache.logging.log4j.core.util.ShutdownCallbackRegistry;
26 import org.apache.logging.log4j.util.PropertiesUtil;
27 import org.zeromq.ZMQ;
28
29 /**
30 * Manager for publishing messages via JeroMq.
31 *
32 * @since 2.6
33 */
34 public class JeroMqManager extends AbstractManager {
35
36 /**
37 * System property to enable shutdown hook.
38 */
39 public static final String SYS_PROPERTY_ENABLE_SHUTDOWN_HOOK = "log4j.jeromq.enableShutdownHook";
40
41 /**
42 * System property to control JeroMQ I/O thread count.
43 */
44 public static final String SYS_PROPERTY_IO_THREADS = "log4j.jeromq.ioThreads";
45
46 private static final JeroMqManagerFactory FACTORY = new JeroMqManagerFactory();
47 private static final ZMQ.Context CONTEXT;
48
49 static {
50 LOGGER.trace("JeroMqManager using ZMQ version {}", ZMQ.getVersionString());
51
52 final int ioThreads = PropertiesUtil.getProperties().getIntegerProperty(SYS_PROPERTY_IO_THREADS, 1);
53 LOGGER.trace("JeroMqManager creating ZMQ context with ioThreads = {}", ioThreads);
54 CONTEXT = ZMQ.context(ioThreads);
55
56 final boolean enableShutdownHook = PropertiesUtil.getProperties().getBooleanProperty(
57 SYS_PROPERTY_ENABLE_SHUTDOWN_HOOK, true);
58 if (enableShutdownHook) {
59 ((ShutdownCallbackRegistry) LogManager.getFactory()).addShutdownCallback(new Runnable() {
60 @Override
61 public void run() {
62 CONTEXT.close();
63 }
64 });
65 }
66 }
67
68 private final ZMQ.Socket publisher;
69
70 private JeroMqManager(final String name, final JeroMqConfiguration config) {
71 super(name);
72 publisher = CONTEXT.socket(ZMQ.PUB);
73 publisher.setAffinity(config.affinity);
74 publisher.setBacklog(config.backlog);
75 publisher.setDelayAttachOnConnect(config.delayAttachOnConnect);
76 if (config.identity != null) {
77 publisher.setIdentity(config.identity);
78 }
79 publisher.setIPv4Only(config.ipv4Only);
80 publisher.setLinger(config.linger);
81 publisher.setMaxMsgSize(config.maxMsgSize);
82 publisher.setRcvHWM(config.rcvHwm);
83 publisher.setReceiveBufferSize(config.receiveBufferSize);
84 publisher.setReceiveTimeOut(config.receiveTimeOut);
85 publisher.setReconnectIVL(config.reconnectIVL);
86 publisher.setReconnectIVLMax(config.reconnectIVLMax);
87 publisher.setSendBufferSize(config.sendBufferSize);
88 publisher.setSendTimeOut(config.sendTimeOut);
89 publisher.setSndHWM(config.sndHwm);
90 publisher.setTCPKeepAlive(config.tcpKeepAlive);
91 publisher.setTCPKeepAliveCount(config.tcpKeepAliveCount);
92 publisher.setTCPKeepAliveIdle(config.tcpKeepAliveIdle);
93 publisher.setTCPKeepAliveInterval(config.tcpKeepAliveInterval);
94 publisher.setXpubVerbose(config.xpubVerbose);
95 for (final String endpoint : config.endpoints) {
96 publisher.bind(endpoint);
97 }
98 LOGGER.debug("Created JeroMqManager with {}", config);
99 }
100
101 public boolean send(final byte[] data) {
102 return publisher.send(data);
103 }
104
105 @Override
106 protected void releaseSub() {
107 publisher.close();
108 }
109
110 public static JeroMqManager getJeroMqManager(final String name, final long affinity, final long backlog,
111 final boolean delayAttachOnConnect, final byte[] identity,
112 final boolean ipv4Only, final long linger, final long maxMsgSize,
113 final long rcvHwm, final long receiveBufferSize,
114 final int receiveTimeOut, final long reconnectIVL,
115 final long reconnectIVLMax, final long sendBufferSize,
116 final int sendTimeOut, final long sndHwm, final int tcpKeepAlive,
117 final long tcpKeepAliveCount, final long tcpKeepAliveIdle,
118 final long tcpKeepAliveInterval, final boolean xpubVerbose,
119 final List<String> endpoints) {
120 return getManager(name, FACTORY,
121 new JeroMqConfiguration(affinity, backlog, delayAttachOnConnect, identity, ipv4Only, linger, maxMsgSize,
122 rcvHwm, receiveBufferSize, receiveTimeOut, reconnectIVL, reconnectIVLMax, sendBufferSize, sendTimeOut,
123 sndHwm, tcpKeepAlive, tcpKeepAliveCount, tcpKeepAliveIdle, tcpKeepAliveInterval, xpubVerbose,
124 endpoints));
125 }
126
127 public static ZMQ.Context getContext() {
128 return CONTEXT;
129 }
130
131 private static class JeroMqConfiguration {
132 private final long affinity;
133 private final long backlog;
134 private final boolean delayAttachOnConnect;
135 private final byte[] identity;
136 private final boolean ipv4Only;
137 private final long linger;
138 private final long maxMsgSize;
139 private final long rcvHwm;
140 private final long receiveBufferSize;
141 private final int receiveTimeOut;
142 private final long reconnectIVL;
143 private final long reconnectIVLMax;
144 private final long sendBufferSize;
145 private final int sendTimeOut;
146 private final long sndHwm;
147 private final int tcpKeepAlive;
148 private final long tcpKeepAliveCount;
149 private final long tcpKeepAliveIdle;
150 private final long tcpKeepAliveInterval;
151 private final boolean xpubVerbose;
152 private final List<String> endpoints;
153
154 private JeroMqConfiguration(final long affinity, final long backlog, final boolean delayAttachOnConnect,
155 final byte[] identity, final boolean ipv4Only, final long linger,
156 final long maxMsgSize, final long rcvHwm, final long receiveBufferSize,
157 final int receiveTimeOut, final long reconnectIVL, final long reconnectIVLMax,
158 final long sendBufferSize, final int sendTimeOut, final long sndHwm,
159 final int tcpKeepAlive, final long tcpKeepAliveCount, final long tcpKeepAliveIdle,
160 final long tcpKeepAliveInterval, final boolean xpubVerbose,
161 final List<String> endpoints) {
162 this.affinity = affinity;
163 this.backlog = backlog;
164 this.delayAttachOnConnect = delayAttachOnConnect;
165 this.identity = identity;
166 this.ipv4Only = ipv4Only;
167 this.linger = linger;
168 this.maxMsgSize = maxMsgSize;
169 this.rcvHwm = rcvHwm;
170 this.receiveBufferSize = receiveBufferSize;
171 this.receiveTimeOut = receiveTimeOut;
172 this.reconnectIVL = reconnectIVL;
173 this.reconnectIVLMax = reconnectIVLMax;
174 this.sendBufferSize = sendBufferSize;
175 this.sendTimeOut = sendTimeOut;
176 this.sndHwm = sndHwm;
177 this.tcpKeepAlive = tcpKeepAlive;
178 this.tcpKeepAliveCount = tcpKeepAliveCount;
179 this.tcpKeepAliveIdle = tcpKeepAliveIdle;
180 this.tcpKeepAliveInterval = tcpKeepAliveInterval;
181 this.xpubVerbose = xpubVerbose;
182 this.endpoints = endpoints;
183 }
184
185 @Override
186 public String toString() {
187 return "JeroMqConfiguration{" +
188 "affinity=" + affinity +
189 ", backlog=" + backlog +
190 ", delayAttachOnConnect=" + delayAttachOnConnect +
191 ", identity=" + Arrays.toString(identity) +
192 ", ipv4Only=" + ipv4Only +
193 ", linger=" + linger +
194 ", maxMsgSize=" + maxMsgSize +
195 ", rcvHwm=" + rcvHwm +
196 ", receiveBufferSize=" + receiveBufferSize +
197 ", receiveTimeOut=" + receiveTimeOut +
198 ", reconnectIVL=" + reconnectIVL +
199 ", reconnectIVLMax=" + reconnectIVLMax +
200 ", sendBufferSize=" + sendBufferSize +
201 ", sendTimeOut=" + sendTimeOut +
202 ", sndHwm=" + sndHwm +
203 ", tcpKeepAlive=" + tcpKeepAlive +
204 ", tcpKeepAliveCount=" + tcpKeepAliveCount +
205 ", tcpKeepAliveIdle=" + tcpKeepAliveIdle +
206 ", tcpKeepAliveInterval=" + tcpKeepAliveInterval +
207 ", xpubVerbose=" + xpubVerbose +
208 ", endpoints=" + endpoints +
209 '}';
210 }
211 }
212
213 private static class JeroMqManagerFactory implements ManagerFactory<JeroMqManager, JeroMqConfiguration> {
214 @Override
215 public JeroMqManager createManager(final String name, final JeroMqConfiguration data) {
216 return new JeroMqManager(name, data);
217 }
218 }
219 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16
17 package org.apache.logging.log4j.core.appender.mom.jeromq;
18
19 import java.util.Arrays;
20 import java.util.List;
21 import java.util.concurrent.TimeUnit;
22
23 import org.apache.logging.log4j.LogManager;
24 import org.apache.logging.log4j.core.appender.AbstractManager;
25 import org.apache.logging.log4j.core.appender.ManagerFactory;
26 import org.apache.logging.log4j.core.util.ShutdownCallbackRegistry;
27 import org.apache.logging.log4j.util.PropertiesUtil;
28 import org.zeromq.ZMQ;
29
30 /**
31 * Manager for publishing messages via JeroMq.
32 *
33 * @since 2.6
34 */
35 public class JeroMqManager extends AbstractManager {
36
37 /**
38 * System property to enable shutdown hook.
39 */
40 public static final String SYS_PROPERTY_ENABLE_SHUTDOWN_HOOK = "log4j.jeromq.enableShutdownHook";
41
42 /**
43 * System property to control JeroMQ I/O thread count.
44 */
45 public static final String SYS_PROPERTY_IO_THREADS = "log4j.jeromq.ioThreads";
46
47 private static final JeroMqManagerFactory FACTORY = new JeroMqManagerFactory();
48 private static final ZMQ.Context CONTEXT;
49
50 static {
51 LOGGER.trace("JeroMqManager using ZMQ version {}", ZMQ.getVersionString());
52
53 final int ioThreads = PropertiesUtil.getProperties().getIntegerProperty(SYS_PROPERTY_IO_THREADS, 1);
54 LOGGER.trace("JeroMqManager creating ZMQ context with ioThreads = {}", ioThreads);
55 CONTEXT = ZMQ.context(ioThreads);
56
57 final boolean enableShutdownHook = PropertiesUtil.getProperties().getBooleanProperty(
58 SYS_PROPERTY_ENABLE_SHUTDOWN_HOOK, true);
59 if (enableShutdownHook) {
60 ((ShutdownCallbackRegistry) LogManager.getFactory()).addShutdownCallback(new Runnable() {
61 @Override
62 public void run() {
63 CONTEXT.close();
64 }
65 });
66 }
67 }
68
69 private final ZMQ.Socket publisher;
70
71 private JeroMqManager(final String name, final JeroMqConfiguration config) {
72 super(null, name);
73 publisher = CONTEXT.socket(ZMQ.PUB);
74 publisher.setAffinity(config.affinity);
75 publisher.setBacklog(config.backlog);
76 publisher.setDelayAttachOnConnect(config.delayAttachOnConnect);
77 if (config.identity != null) {
78 publisher.setIdentity(config.identity);
79 }
80 publisher.setIPv4Only(config.ipv4Only);
81 publisher.setLinger(config.linger);
82 publisher.setMaxMsgSize(config.maxMsgSize);
83 publisher.setRcvHWM(config.rcvHwm);
84 publisher.setReceiveBufferSize(config.receiveBufferSize);
85 publisher.setReceiveTimeOut(config.receiveTimeOut);
86 publisher.setReconnectIVL(config.reconnectIVL);
87 publisher.setReconnectIVLMax(config.reconnectIVLMax);
88 publisher.setSendBufferSize(config.sendBufferSize);
89 publisher.setSendTimeOut(config.sendTimeOut);
90 publisher.setSndHWM(config.sndHwm);
91 publisher.setTCPKeepAlive(config.tcpKeepAlive);
92 publisher.setTCPKeepAliveCount(config.tcpKeepAliveCount);
93 publisher.setTCPKeepAliveIdle(config.tcpKeepAliveIdle);
94 publisher.setTCPKeepAliveInterval(config.tcpKeepAliveInterval);
95 publisher.setXpubVerbose(config.xpubVerbose);
96 for (final String endpoint : config.endpoints) {
97 publisher.bind(endpoint);
98 }
99 LOGGER.debug("Created JeroMqManager with {}", config);
100 }
101
102 public boolean send(final byte[] data) {
103 return publisher.send(data);
104 }
105
106 @Override
107 protected boolean releaseSub(final long timeout, final TimeUnit timeUnit) {
108 publisher.close();
109 return true;
110 }
111
112 public static JeroMqManager getJeroMqManager(final String name, final long affinity, final long backlog,
113 final boolean delayAttachOnConnect, final byte[] identity,
114 final boolean ipv4Only, final long linger, final long maxMsgSize,
115 final long rcvHwm, final long receiveBufferSize,
116 final int receiveTimeOut, final long reconnectIVL,
117 final long reconnectIVLMax, final long sendBufferSize,
118 final int sendTimeOut, final long sndHwm, final int tcpKeepAlive,
119 final long tcpKeepAliveCount, final long tcpKeepAliveIdle,
120 final long tcpKeepAliveInterval, final boolean xpubVerbose,
121 final List<String> endpoints) {
122 return getManager(name, FACTORY,
123 new JeroMqConfiguration(affinity, backlog, delayAttachOnConnect, identity, ipv4Only, linger, maxMsgSize,
124 rcvHwm, receiveBufferSize, receiveTimeOut, reconnectIVL, reconnectIVLMax, sendBufferSize, sendTimeOut,
125 sndHwm, tcpKeepAlive, tcpKeepAliveCount, tcpKeepAliveIdle, tcpKeepAliveInterval, xpubVerbose,
126 endpoints));
127 }
128
129 public static ZMQ.Context getContext() {
130 return CONTEXT;
131 }
132
133 private static class JeroMqConfiguration {
134 private final long affinity;
135 private final long backlog;
136 private final boolean delayAttachOnConnect;
137 private final byte[] identity;
138 private final boolean ipv4Only;
139 private final long linger;
140 private final long maxMsgSize;
141 private final long rcvHwm;
142 private final long receiveBufferSize;
143 private final int receiveTimeOut;
144 private final long reconnectIVL;
145 private final long reconnectIVLMax;
146 private final long sendBufferSize;
147 private final int sendTimeOut;
148 private final long sndHwm;
149 private final int tcpKeepAlive;
150 private final long tcpKeepAliveCount;
151 private final long tcpKeepAliveIdle;
152 private final long tcpKeepAliveInterval;
153 private final boolean xpubVerbose;
154 private final List<String> endpoints;
155
156 private JeroMqConfiguration(final long affinity, final long backlog, final boolean delayAttachOnConnect,
157 final byte[] identity, final boolean ipv4Only, final long linger,
158 final long maxMsgSize, final long rcvHwm, final long receiveBufferSize,
159 final int receiveTimeOut, final long reconnectIVL, final long reconnectIVLMax,
160 final long sendBufferSize, final int sendTimeOut, final long sndHwm,
161 final int tcpKeepAlive, final long tcpKeepAliveCount, final long tcpKeepAliveIdle,
162 final long tcpKeepAliveInterval, final boolean xpubVerbose,
163 final List<String> endpoints) {
164 this.affinity = affinity;
165 this.backlog = backlog;
166 this.delayAttachOnConnect = delayAttachOnConnect;
167 this.identity = identity;
168 this.ipv4Only = ipv4Only;
169 this.linger = linger;
170 this.maxMsgSize = maxMsgSize;
171 this.rcvHwm = rcvHwm;
172 this.receiveBufferSize = receiveBufferSize;
173 this.receiveTimeOut = receiveTimeOut;
174 this.reconnectIVL = reconnectIVL;
175 this.reconnectIVLMax = reconnectIVLMax;
176 this.sendBufferSize = sendBufferSize;
177 this.sendTimeOut = sendTimeOut;
178 this.sndHwm = sndHwm;
179 this.tcpKeepAlive = tcpKeepAlive;
180 this.tcpKeepAliveCount = tcpKeepAliveCount;
181 this.tcpKeepAliveIdle = tcpKeepAliveIdle;
182 this.tcpKeepAliveInterval = tcpKeepAliveInterval;
183 this.xpubVerbose = xpubVerbose;
184 this.endpoints = endpoints;
185 }
186
187 @Override
188 public String toString() {
189 return "JeroMqConfiguration{" +
190 "affinity=" + affinity +
191 ", backlog=" + backlog +
192 ", delayAttachOnConnect=" + delayAttachOnConnect +
193 ", identity=" + Arrays.toString(identity) +
194 ", ipv4Only=" + ipv4Only +
195 ", linger=" + linger +
196 ", maxMsgSize=" + maxMsgSize +
197 ", rcvHwm=" + rcvHwm +
198 ", receiveBufferSize=" + receiveBufferSize +
199 ", receiveTimeOut=" + receiveTimeOut +
200 ", reconnectIVL=" + reconnectIVL +
201 ", reconnectIVLMax=" + reconnectIVLMax +
202 ", sendBufferSize=" + sendBufferSize +
203 ", sendTimeOut=" + sendTimeOut +
204 ", sndHwm=" + sndHwm +
205 ", tcpKeepAlive=" + tcpKeepAlive +
206 ", tcpKeepAliveCount=" + tcpKeepAliveCount +
207 ", tcpKeepAliveIdle=" + tcpKeepAliveIdle +
208 ", tcpKeepAliveInterval=" + tcpKeepAliveInterval +
209 ", xpubVerbose=" + xpubVerbose +
210 ", endpoints=" + endpoints +
211 '}';
212 }
213 }
214
215 private static class JeroMqManagerFactory implements ManagerFactory<JeroMqManager, JeroMqConfiguration> {
216 @Override
217 public JeroMqManager createManager(final String name, final JeroMqConfiguration data) {
218 return new JeroMqManager(name, data);
219 }
220 }
221 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16
17 package org.apache.logging.log4j.core.appender.mom.kafka;
18
19 import java.io.Serializable;
20 import java.nio.charset.StandardCharsets;
21
22 import org.apache.logging.log4j.core.Appender;
23 import org.apache.logging.log4j.core.Filter;
24 import org.apache.logging.log4j.core.Layout;
25 import org.apache.logging.log4j.core.LogEvent;
26 import org.apache.logging.log4j.core.appender.AbstractAppender;
27 import org.apache.logging.log4j.core.appender.AppenderLoggingException;
28 import org.apache.logging.log4j.core.config.Node;
29 import org.apache.logging.log4j.core.config.Property;
30 import org.apache.logging.log4j.core.config.plugins.Plugin;
31 import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
32 import org.apache.logging.log4j.core.config.plugins.PluginElement;
33 import org.apache.logging.log4j.core.config.plugins.PluginFactory;
34 import org.apache.logging.log4j.core.config.plugins.validation.constraints.Required;
35 import org.apache.logging.log4j.core.layout.SerializedLayout;
36 import org.apache.logging.log4j.core.util.StringEncoder;
37
38 /**
39 * Sends log events to an Apache Kafka topic.
40 */
41 @Plugin(name = "Kafka", category = Node.CATEGORY, elementType = Appender.ELEMENT_TYPE, printObject = true)
42 public final class KafkaAppender extends AbstractAppender {
43
44 @PluginFactory
45 public static KafkaAppender createAppender(
46 @PluginElement("Layout") final Layout<? extends Serializable> layout,
47 @PluginElement("Filter") final Filter filter,
48 @Required(message = "No name provided for KafkaAppender") @PluginAttribute("name") final String name,
49 @PluginAttribute(value = "ignoreExceptions", defaultBoolean = true) final boolean ignoreExceptions,
50 @Required(message = "No topic provided for KafkaAppender") @PluginAttribute("topic") final String topic,
51 @PluginElement("Properties") final Property[] properties) {
52 final KafkaManager kafkaManager = new KafkaManager(name, topic, properties);
53 return new KafkaAppender(name, layout, filter, ignoreExceptions, kafkaManager);
54 }
55
56 private final KafkaManager manager;
57
58 private KafkaAppender(final String name, final Layout<? extends Serializable> layout, final Filter filter, final boolean ignoreExceptions, final KafkaManager manager) {
59 super(name, filter, layout, ignoreExceptions);
60 this.manager = manager;
61 }
62
63 @Override
64 public void append(final LogEvent event) {
65 if (event.getLoggerName().startsWith("org.apache.kafka")) {
66 LOGGER.warn("Recursive logging from [{}] for appender [{}].", event.getLoggerName(), getName());
67 } else {
68 try {
69 final Layout<? extends Serializable> layout = getLayout();
70 byte[] data;
71 if (layout != null) {
72 if (layout instanceof SerializedLayout) {
73 final byte[] header = layout.getHeader();
74 final byte[] body = layout.toByteArray(event);
75 data = new byte[header.length + body.length];
76 System.arraycopy(header, 0, data, 0, header.length);
77 System.arraycopy(body, 0, data, header.length, body.length);
78 } else {
79 data = layout.toByteArray(event);
80 }
81 } else {
82 data = StringEncoder.toBytes(event.getMessage().getFormattedMessage(), StandardCharsets.UTF_8);
83 }
84 manager.send(data);
85 } catch (final Exception e) {
86 LOGGER.error("Unable to write to Kafka [{}] for appender [{}].", manager.getName(), getName(), e);
87 throw new AppenderLoggingException("Unable to write to Kafka in appender: " + e.getMessage(), e);
88 }
89 }
90 }
91
92 @Override
93 public void start() {
94 super.start();
95 manager.startup();
96 }
97
98 @Override
99 public void stop() {
100 super.stop();
101 manager.release();
102 }
103
104 @Override
105 public String toString() {
106 return "KafkaAppender{" +
107 "name=" + getName() +
108 ", state=" + getState() +
109 ", topic=" + manager.getTopic() +
110 '}';
111 }
112 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16
17 package org.apache.logging.log4j.core.appender.mom.kafka;
18
19 import java.io.Serializable;
20 import java.nio.charset.StandardCharsets;
21 import java.util.concurrent.TimeUnit;
22
23 import org.apache.logging.log4j.core.Appender;
24 import org.apache.logging.log4j.core.Filter;
25 import org.apache.logging.log4j.core.Layout;
26 import org.apache.logging.log4j.core.LogEvent;
27 import org.apache.logging.log4j.core.appender.AbstractAppender;
28 import org.apache.logging.log4j.core.appender.AppenderLoggingException;
29 import org.apache.logging.log4j.core.config.Configuration;
30 import org.apache.logging.log4j.core.config.Node;
31 import org.apache.logging.log4j.core.config.Property;
32 import org.apache.logging.log4j.core.config.plugins.Plugin;
33 import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
34 import org.apache.logging.log4j.core.config.plugins.PluginConfiguration;
35 import org.apache.logging.log4j.core.config.plugins.PluginElement;
36 import org.apache.logging.log4j.core.config.plugins.PluginFactory;
37 import org.apache.logging.log4j.core.config.plugins.validation.constraints.Required;
38 import org.apache.logging.log4j.core.layout.SerializedLayout;
39 import org.apache.logging.log4j.core.util.StringEncoder;
40
41 /**
42 * Sends log events to an Apache Kafka topic.
43 */
44 @Plugin(name = "Kafka", category = Node.CATEGORY, elementType = Appender.ELEMENT_TYPE, printObject = true)
45 public final class KafkaAppender extends AbstractAppender {
46
47 @PluginFactory
48 public static KafkaAppender createAppender(
49 @PluginElement("Layout") final Layout<? extends Serializable> layout,
50 @PluginElement("Filter") final Filter filter,
51 @Required(message = "No name provided for KafkaAppender") @PluginAttribute("name") final String name,
52 @PluginAttribute(value = "ignoreExceptions", defaultBoolean = true) final boolean ignoreExceptions,
53 @Required(message = "No topic provided for KafkaAppender") @PluginAttribute("topic") final String topic,
54 @PluginElement("Properties") final Property[] properties,
55 @PluginConfiguration final Configuration configuration) {
56 final KafkaManager kafkaManager = new KafkaManager(configuration.getLoggerContext(), name, topic, properties);
57 return new KafkaAppender(name, layout, filter, ignoreExceptions, kafkaManager);
58 }
59
60 private final KafkaManager manager;
61
62 private KafkaAppender(final String name, final Layout<? extends Serializable> layout, final Filter filter, final boolean ignoreExceptions, final KafkaManager manager) {
63 super(name, filter, layout, ignoreExceptions);
64 this.manager = manager;
65 }
66
67 @Override
68 public void append(final LogEvent event) {
69 if (event.getLoggerName().startsWith("org.apache.kafka")) {
70 LOGGER.warn("Recursive logging from [{}] for appender [{}].", event.getLoggerName(), getName());
71 } else {
72 try {
73 final Layout<? extends Serializable> layout = getLayout();
74 byte[] data;
75 if (layout != null) {
76 if (layout instanceof SerializedLayout) {
77 final byte[] header = layout.getHeader();
78 final byte[] body = layout.toByteArray(event);
79 data = new byte[header.length + body.length];
80 System.arraycopy(header, 0, data, 0, header.length);
81 System.arraycopy(body, 0, data, header.length, body.length);
82 } else {
83 data = layout.toByteArray(event);
84 }
85 } else {
86 data = StringEncoder.toBytes(event.getMessage().getFormattedMessage(), StandardCharsets.UTF_8);
87 }
88 manager.send(data);
89 } catch (final Exception e) {
90 LOGGER.error("Unable to write to Kafka [{}] for appender [{}].", manager.getName(), getName(), e);
91 throw new AppenderLoggingException("Unable to write to Kafka in appender: " + e.getMessage(), e);
92 }
93 }
94 }
95
96 @Override
97 public void start() {
98 super.start();
99 manager.startup();
100 }
101
102 @Override
103 public boolean stop(final long timeout, final TimeUnit timeUnit) {
104 setStopping();
105 boolean stopped = super.stop(timeout, timeUnit, false);
106 stopped &= manager.stop(timeout, timeUnit);
107 setStopped();
108 return stopped;
109 }
110
111 @Override
112 public String toString() {
113 return "KafkaAppender{" +
114 "name=" + getName() +
115 ", state=" + getState() +
116 ", topic=" + manager.getTopic() +
117 '}';
118 }
119 }
2323
2424 import org.apache.kafka.clients.producer.Producer;
2525 import org.apache.kafka.clients.producer.ProducerRecord;
26 import org.apache.logging.log4j.core.LoggerContext;
2627 import org.apache.logging.log4j.core.appender.AbstractManager;
2728 import org.apache.logging.log4j.core.config.Property;
28 import org.apache.logging.log4j.core.util.Log4jThread;
2929
3030 public class KafkaManager extends AbstractManager {
3131
3737 static KafkaProducerFactory producerFactory = new DefaultKafkaProducerFactory();
3838
3939 private final Properties config = new Properties();
40 private Producer<byte[], byte[]> producer = null;
40 private Producer<byte[], byte[]> producer;
4141 private final int timeoutMillis;
4242
4343 private final String topic;
4444
45 public KafkaManager(final String name, final String topic, final Property[] properties) {
46 super(name);
45 public KafkaManager(final LoggerContext loggerContext, final String name, final String topic, final Property[] properties) {
46 super(loggerContext, name);
4747 this.topic = topic;
4848 config.setProperty("key.serializer", "org.apache.kafka.common.serialization.ByteArraySerializer");
4949 config.setProperty("value.serializer", "org.apache.kafka.common.serialization.ByteArraySerializer");
5555 }
5656
5757 @Override
58 public void releaseSub() {
58 public boolean releaseSub(final long timeout, final TimeUnit timeUnit) {
59 if (timeout > 0) {
60 closeProducer(timeout, timeUnit);
61 } else {
62 closeProducer(timeoutMillis, TimeUnit.MILLISECONDS);
63 }
64 return true;
65 }
66
67 private void closeProducer(final long timeout, final TimeUnit timeUnit) {
5968 if (producer != null) {
6069 // This thread is a workaround for this Kafka issue: https://issues.apache.org/jira/browse/KAFKA-1660
61 final Thread closeThread = new Log4jThread(new Runnable() {
70 final Runnable task = new Runnable() {
6271 @Override
6372 public void run() {
64 producer.close();
73 if (producer != null) {
74 producer.close();
75 }
6576 }
66 });
67 closeThread.setName("KafkaManager-CloseThread");
68 closeThread.setDaemon(true); // avoid blocking JVM shutdown
69 closeThread.start();
77 };
7078 try {
71 closeThread.join(timeoutMillis);
72 } catch (final InterruptedException ignore) {
79 getLoggerContext().submitDaemon(task).get(timeout, timeUnit);
80 } catch (InterruptedException | ExecutionException | TimeoutException e) {
7381 // ignore
7482 }
7583 }
3535 /**
3636 * This Appender allows the logging event to be manipulated before it is processed by other Appenders.
3737 */
38 @Plugin(name = "Rewrite", category = "Core", elementType = "appender", printObject = true)
38 @Plugin(name = "Rewrite", category = "Core", elementType = Appender.ELEMENT_TYPE, printObject = true)
3939 public final class RewriteAppender extends AbstractAppender {
4040
4141 private final Configuration config;
6666 }
6767 }
6868 super.start();
69 }
70
71 @Override
72 public void stop() {
73 super.stop();
7469 }
7570
7671 /**
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16
17 package org.apache.logging.log4j.core.appender.rolling;
18
19 import org.apache.logging.log4j.core.AbstractLifeCycle;
20
21 /**
22 * Convenience abstract class for extends triggering policies to extend {@link AbstractLifeCycle} and implement
23 * {@link TriggeringPolicy}.
24 */
25 public abstract class AbstractTriggeringPolicy extends AbstractLifeCycle implements TriggeringPolicy {
26 // empty for now
27 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.appender.rolling;
17
18 import java.util.Arrays;
19
20 import org.apache.logging.log4j.core.LogEvent;
21 import org.apache.logging.log4j.core.config.plugins.Plugin;
22 import org.apache.logging.log4j.core.config.plugins.PluginElement;
23 import org.apache.logging.log4j.core.config.plugins.PluginFactory;
24
25 /**
26 * Triggering policy that wraps other policies.
27 */
28 @Plugin(name = "Policies", category = "Core", printObject = true)
29 public final class CompositeTriggeringPolicy implements TriggeringPolicy {
30
31 private final TriggeringPolicy[] triggeringPolicy;
32
33 private CompositeTriggeringPolicy(final TriggeringPolicy... policies) {
34 this.triggeringPolicy = policies;
35 }
36
37 public TriggeringPolicy[] getTriggeringPolicies() {
38 return triggeringPolicy;
39 }
40
41 /**
42 * Initializes the policy.
43 * @param manager The RollingFileManager.
44 */
45 @Override
46 public void initialize(final RollingFileManager manager) {
47 for (final TriggeringPolicy policy : triggeringPolicy) {
48 policy.initialize(manager);
49 }
50 }
51
52 /**
53 * Determines if a rollover should occur.
54 * @param event A reference to the currently event.
55 * @return true if a rollover should occur, false otherwise.
56 */
57 @Override
58 public boolean isTriggeringEvent(final LogEvent event) {
59 for (final TriggeringPolicy policy : triggeringPolicy) {
60 if (policy.isTriggeringEvent(event)) {
61 return true;
62 }
63 }
64 return false;
65 }
66
67 /**
68 * Create a CompositeTriggeringPolicy.
69 * @param policies The triggering policies.
70 * @return A CompositeTriggeringPolicy.
71 */
72 @PluginFactory
73 public static CompositeTriggeringPolicy createPolicy(
74 @PluginElement("Policies") final TriggeringPolicy... policies) {
75 return new CompositeTriggeringPolicy(policies);
76 }
77
78 @Override
79 public String toString() {
80 return "CompositeTriggeringPolicy(policies=" + Arrays.toString(triggeringPolicy) + ")";
81 }
82
83 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.appender.rolling;
17
18 import java.util.Arrays;
19 import java.util.concurrent.TimeUnit;
20
21 import org.apache.logging.log4j.core.LifeCycle;
22 import org.apache.logging.log4j.core.LifeCycle2;
23 import org.apache.logging.log4j.core.LogEvent;
24 import org.apache.logging.log4j.core.config.plugins.Plugin;
25 import org.apache.logging.log4j.core.config.plugins.PluginElement;
26 import org.apache.logging.log4j.core.config.plugins.PluginFactory;
27
28 /**
29 * Triggering policy that wraps other triggering policies.
30 */
31 @Plugin(name = "Policies", category = "Core", printObject = true)
32 public final class CompositeTriggeringPolicy extends AbstractTriggeringPolicy {
33
34 private final TriggeringPolicy[] triggeringPolicies;
35
36 private CompositeTriggeringPolicy(final TriggeringPolicy... triggeringPolicies) {
37 this.triggeringPolicies = triggeringPolicies;
38 }
39
40 public TriggeringPolicy[] getTriggeringPolicies() {
41 return triggeringPolicies;
42 }
43
44 /**
45 * Initializes the policy.
46 * @param manager The RollingFileManager.
47 */
48 @Override
49 public void initialize(final RollingFileManager manager) {
50 for (final TriggeringPolicy triggeringPolicy : triggeringPolicies) {
51 triggeringPolicy.initialize(manager);
52 }
53 }
54
55 /**
56 * Determines if a rollover should occur.
57 * @param event A reference to the currently event.
58 * @return true if a rollover should occur, false otherwise.
59 */
60 @Override
61 public boolean isTriggeringEvent(final LogEvent event) {
62 for (final TriggeringPolicy triggeringPolicy : triggeringPolicies) {
63 if (triggeringPolicy.isTriggeringEvent(event)) {
64 return true;
65 }
66 }
67 return false;
68 }
69
70 /**
71 * Creates a CompositeTriggeringPolicy.
72 * @param triggeringPolicy The triggering policies.
73 * @return A CompositeTriggeringPolicy.
74 */
75 @PluginFactory
76 public static CompositeTriggeringPolicy createPolicy(
77 @PluginElement("Policies") final TriggeringPolicy... triggeringPolicy) {
78 return new CompositeTriggeringPolicy(triggeringPolicy);
79 }
80
81 @Override
82 public boolean stop(final long timeout, final TimeUnit timeUnit) {
83 setStopping();
84 boolean stopped = true;
85 for (final TriggeringPolicy triggeringPolicy : triggeringPolicies) {
86 if (triggeringPolicy instanceof LifeCycle2) {
87 stopped &= ((LifeCycle2) triggeringPolicy).stop(timeout, timeUnit);
88 } else if (triggeringPolicy instanceof LifeCycle) {
89 ((LifeCycle) triggeringPolicy).stop();
90 stopped &= true;
91 }
92 }
93 setStopped();
94 return stopped;
95 }
96
97 @Override
98 public String toString() {
99 return "CompositeTriggeringPolicy(policies=" + Arrays.toString(triggeringPolicies) + ")";
100 }
101
102 }
1818 import java.text.ParseException;
1919 import java.util.Calendar;
2020 import java.util.Date;
21 import java.util.concurrent.TimeUnit;
2122
22 import org.apache.logging.log4j.Logger;
2323 import org.apache.logging.log4j.core.LogEvent;
2424 import org.apache.logging.log4j.core.config.Configuration;
2525 import org.apache.logging.log4j.core.config.CronScheduledFuture;
2929 import org.apache.logging.log4j.core.config.plugins.PluginConfiguration;
3030 import org.apache.logging.log4j.core.config.plugins.PluginFactory;
3131 import org.apache.logging.log4j.core.util.CronExpression;
32 import org.apache.logging.log4j.status.StatusLogger;
3332
3433 /**
3534 * Rolls a file over based on a cron schedule.
3635 */
3736 @Plugin(name = "CronTriggeringPolicy", category = "Core", printObject = true)
3837 @Scheduled
39 public final class CronTriggeringPolicy implements TriggeringPolicy {
38 public final class CronTriggeringPolicy extends AbstractTriggeringPolicy {
4039
41 private static final Logger LOGGER = StatusLogger.getLogger();
4240 private static final String defaultSchedule = "0 0 0 * * ?";
4341 private RollingFileManager manager;
4442 private final CronExpression cronExpression;
4543 private final Configuration configuration;
4644 private final boolean checkOnStartup;
4745 private volatile Date nextRollDate;
48 private CronScheduledFuture future;
46 private CronScheduledFuture<?> future;
4947
5048 private CronTriggeringPolicy(final CronExpression schedule, final boolean checkOnStartup,
5149 final Configuration configuration) {
5654
5755 /**
5856 * Initializes the policy.
59 * @param aManager The RollingFileManager.
57 *
58 * @param aManager
59 * The RollingFileManager.
6060 */
6161 @Override
6262 public void initialize(final RollingFileManager aManager) {
7373
7474 /**
7575 * Determines whether a rollover should occur.
76 * @param event A reference to the currently event.
76 *
77 * @param event
78 * A reference to the currently event.
7779 * @return true if a rollover should occur.
7880 */
7981 @Override
8789
8890 /**
8991 * Creates a ScheduledTriggeringPolicy.
90 * @param configuration the Configuration.
91 * @param evaluateOnStartup check if the file should be rolled over immediately.
92 * @param schedule the cron expression.
92 *
93 * @param configuration
94 * the Configuration.
95 * @param evaluateOnStartup
96 * check if the file should be rolled over immediately.
97 * @param schedule
98 * the cron expression.
9399 * @return a ScheduledTriggeringPolicy.
94100 */
95101 @PluginFactory
96 public static CronTriggeringPolicy createPolicy(
97 @PluginConfiguration final Configuration configuration,
102 public static CronTriggeringPolicy createPolicy(@PluginConfiguration final Configuration configuration,
98103 @PluginAttribute("evaluateOnStartup") final String evaluateOnStartup,
99104 @PluginAttribute("schedule") final String schedule) {
100105 CronExpression cronExpression;
125130 manager.getPatternProcessor().setPrevFileTime(nextRollDate.getTime());
126131 manager.rollover();
127132 final Date fireDate = future.getFireTime();
128 Calendar cal = Calendar.getInstance();
133 final Calendar cal = Calendar.getInstance();
129134 cal.setTime(fireDate);
130135 cal.add(Calendar.SECOND, -1);
131136 nextRollDate = cal.getTime();
137 }
138
139 @Override
140 public boolean stop(final long timeout, final TimeUnit timeUnit) {
141 setStopping();
142 final boolean stopped = stop(future);
143 setStopped();
144 return stopped;
132145 }
133146
134147 @Override
2424 import java.util.concurrent.TimeUnit;
2525 import java.util.zip.Deflater;
2626
27 import org.apache.logging.log4j.Logger;
2827 import org.apache.logging.log4j.core.appender.rolling.action.Action;
2928 import org.apache.logging.log4j.core.appender.rolling.action.CommonsCompressAction;
3029 import org.apache.logging.log4j.core.appender.rolling.action.CompositeAction;
3938 import org.apache.logging.log4j.core.config.plugins.PluginFactory;
4039 import org.apache.logging.log4j.core.lookup.StrSubstitutor;
4140 import org.apache.logging.log4j.core.util.Integers;
42 import org.apache.logging.log4j.status.StatusLogger;
4341
4442 /**
4543 * When rolling over, <code>DefaultRolloverStrategy</code> renames files according to an algorithm as described below.
7573 * </p>
7674 */
7775 @Plugin(name = "DefaultRolloverStrategy", category = "Core", printObject = true)
78 public class DefaultRolloverStrategy implements RolloverStrategy {
76 public class DefaultRolloverStrategy extends AbstractRolloverStrategy {
7977
8078 /**
8179 * Enumerates over supported file extensions.
168166 File target(final String fileName) {
169167 return new File(fileName);
170168 }
171 };
172
173 /**
174 * Allow subclasses access to the status logger without creating another instance.
175 */
176 protected static final Logger LOGGER = StatusLogger.getLogger();
169 }
177170
178171 private static final int MIN_WINDOW_SIZE = 1;
179172 private static final int DEFAULT_WINDOW_SIZE = 7;
180173
181174 /**
182 * Create the DefaultRolloverStrategy.
175 * Creates the DefaultRolloverStrategy.
183176 *
184177 * @param max The maximum number of files to keep.
185178 * @param min The minimum number of files to keep.
306299 }
307300
308301 /**
309 * Purge and rename old log files in preparation for rollover. The oldest file will have the smallest index, the
302 * Purges and renames old log files in preparation for rollover. The oldest file will have the smallest index, the
310303 * newest the highest.
311304 *
312305 * @param lowIndex low index
413406 }
414407
415408 /**
416 * Purge and rename old log files in preparation for rollover. The newest file will have the smallest index, the
409 * Purges and renames old log files in preparation for rollover. The newest file will have the smallest index, the
417410 * oldest will have the highest.
418411 *
419412 * @param lowIndex low index
508501 }
509502
510503 /**
511 * Perform the rollover.
504 * Performs the rollover.
512505 *
513506 * @param manager The RollingFileManager name for current active log file.
514507 * @return A RolloverDescription.
5050 * abbreviations KB, MB, and GB are also accepted. Matching is case insensitive.
5151 *
5252 * @param string The string to convert
53 * @param defaultValue The default value if a problem is detected parsing.
5354 * @return The Bytes value for the string
5455 */
5556 public static long parse(final String string, final long defaultValue) {
2828 * Triggers a rollover on every restart, but only if the file size is greater than zero.
2929 */
3030 @Plugin(name = "OnStartupTriggeringPolicy", category = "Core", printObject = true)
31 public class OnStartupTriggeringPolicy implements TriggeringPolicy {
31 public class OnStartupTriggeringPolicy extends AbstractTriggeringPolicy {
3232
3333 private static final long JVM_START_TIME = initStartTime();
3434
3535 private final long minSize;
3636
37 private OnStartupTriggeringPolicy(long minSize) {
37 private OnStartupTriggeringPolicy(final long minSize) {
3838 this.minSize = minSize;
3939 }
4040
9595 return prevFileTime;
9696 }
9797
98 public void setPrevFileTime(long prevFileTime) {
98 public void setPrevFileTime(final long prevFileTime) {
9999 this.prevFileTime = prevFileTime;
100100 }
101101
1616 package org.apache.logging.log4j.core.appender.rolling;
1717
1818 import java.io.File;
19 import java.io.FileNotFoundException;
2019 import java.io.FileOutputStream;
2120 import java.io.IOException;
2221 import java.io.OutputStream;
2322 import java.io.Serializable;
2423 import java.nio.ByteBuffer;
24 import java.util.concurrent.Future;
2525 import java.util.concurrent.Semaphore;
26 import java.util.concurrent.TimeUnit;
2627 import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
2728
2829 import org.apache.logging.log4j.core.Layout;
30 import org.apache.logging.log4j.core.LifeCycle;
31 import org.apache.logging.log4j.core.LifeCycle2;
2932 import org.apache.logging.log4j.core.LogEvent;
33 import org.apache.logging.log4j.core.LoggerContext;
34 import org.apache.logging.log4j.core.appender.ConfigurationFactoryData;
3035 import org.apache.logging.log4j.core.appender.FileManager;
3136 import org.apache.logging.log4j.core.appender.ManagerFactory;
3237 import org.apache.logging.log4j.core.appender.rolling.action.AbstractAction;
3338 import org.apache.logging.log4j.core.appender.rolling.action.Action;
39 import org.apache.logging.log4j.core.config.Configuration;
3440 import org.apache.logging.log4j.core.util.Constants;
35 import org.apache.logging.log4j.core.util.Log4jThread;
3641
3742 /**
3843 * The Rolling File Manager.
6469 writeHeader, ByteBuffer.wrap(new byte[Constants.ENCODER_BYTE_BUFFER_SIZE]));
6570 }
6671
72 @Deprecated
6773 protected RollingFileManager(final String fileName, final String pattern, final OutputStream os,
6874 final boolean append, final long size, final long time, final TriggeringPolicy triggeringPolicy,
6975 final RolloverStrategy rolloverStrategy, final String advertiseURI,
7783 this.patternProcessor.setPrevFileTime(time);
7884 }
7985
86 /**
87 * @since 2.7
88 */
89 protected RollingFileManager(final LoggerContext loggerContext, final String fileName, final String pattern, final OutputStream os,
90 final boolean append, final boolean createOnDemand, final long size, final long time,
91 final TriggeringPolicy triggeringPolicy, final RolloverStrategy rolloverStrategy,
92 final String advertiseURI, final Layout<? extends Serializable> layout, final boolean writeHeader, final ByteBuffer buffer) {
93 super(loggerContext, fileName, os, append, false, createOnDemand, advertiseURI, layout, writeHeader, buffer);
94 this.size = size;
95 this.initialTime = time;
96 this.triggeringPolicy = triggeringPolicy;
97 this.rolloverStrategy = rolloverStrategy;
98 this.patternProcessor = new PatternProcessor(pattern);
99 this.patternProcessor.setPrevFileTime(time);
100 }
101
80102 public void initialize() {
81103 triggeringPolicy.initialize(this);
82104 }
92114 * @param advertiseURI the URI to use when advertising the file
93115 * @param layout The Layout.
94116 * @param bufferSize buffer size to use if bufferedIO is true
117 * @param immediateFlush flush on every write or not
118 * @param createOnDemand true if you want to lazy-create the file (a.k.a. on-demand.)
119 * @param configuration The configuration.
95120 * @return A RollingFileManager.
96121 */
97122 public static RollingFileManager getFileManager(final String fileName, final String pattern, final boolean append,
98123 final boolean bufferedIO, final TriggeringPolicy policy, final RolloverStrategy strategy,
99124 final String advertiseURI, final Layout<? extends Serializable> layout, final int bufferSize,
100 final boolean immediateFlush) {
125 final boolean immediateFlush, final boolean createOnDemand, final Configuration configuration) {
101126
102127 return (RollingFileManager) getManager(fileName, new FactoryData(pattern, append,
103 bufferedIO, policy, strategy, advertiseURI, layout, bufferSize, immediateFlush), factory);
128 bufferedIO, policy, strategy, advertiseURI, layout, bufferSize, immediateFlush, createOnDemand, configuration), factory);
104129 }
105130
106131 // override to make visible for unit tests
120145 return renameEmptyFiles;
121146 }
122147
123 public void setRenameEmptyFiles(boolean renameEmptyFiles) {
148 public void setRenameEmptyFiles(final boolean renameEmptyFiles) {
124149 this.renameEmptyFiles = renameEmptyFiles;
125150 }
126151
141166 }
142167
143168 /**
144 * Determine if a rollover should occur.
169 * Determines if a rollover should occur.
145170 * @param event The LogEvent.
146171 */
147172 public synchronized void checkRollover(final LogEvent event) {
148173 if (triggeringPolicy.isTriggeringEvent(event)) {
149174 rollover();
150175 }
176 }
177
178 @Override
179 public boolean releaseSub(final long timeout, final TimeUnit timeUnit) {
180 boolean stopped = true;
181 if (triggeringPolicy instanceof LifeCycle2) {
182 stopped &= ((LifeCycle2) triggeringPolicy).stop(timeout, timeUnit);
183 } else if (triggeringPolicy instanceof LifeCycle) {
184 ((LifeCycle) triggeringPolicy).stop();
185 stopped &= true;
186 }
187 return stopped && super.releaseSub(timeout, timeUnit);
151188 }
152189
153190 public synchronized void rollover() {
213250 }
214251
215252 boolean success = false;
216 Thread thread = null;
253 Future<?> future = null;
217254
218255 try {
219256 final RolloverDescription descriptor = strategy.rollover(this);
220257 if (descriptor != null) {
221258 writeFooter();
222 close();
259 closeOutputStream();
223260 if (descriptor.getSynchronous() != null) {
224261 LOGGER.debug("RollingFileManager executing synchronous {}", descriptor.getSynchronous());
225262 try {
231268
232269 if (success && descriptor.getAsynchronous() != null) {
233270 LOGGER.debug("RollingFileManager executing async {}", descriptor.getAsynchronous());
234 thread = new Log4jThread(new AsyncAction(descriptor.getAsynchronous(), this));
235 thread.start();
271 future = LoggerContext.getContext(false).submit(new AsyncAction(descriptor.getAsynchronous(), this));
236272 }
237273 return true;
238274 }
239275 return false;
240276 } finally {
241 if (thread == null || !thread.isAlive()) {
277 if (future == null || future.isDone() || future.isCancelled()) {
242278 semaphore.release();
243279 }
244280 }
264300 }
265301
266302 /**
267 * Perform an action.
303 * Executes an action.
268304 *
269305 * @return true if action was successful. A return value of false will cause
270306 * the rollover to be aborted if possible.
318354 /**
319355 * Factory data.
320356 */
321 private static class FactoryData {
357 private static class FactoryData extends ConfigurationFactoryData {
322358 private final String pattern;
323359 private final boolean append;
324360 private final boolean bufferedIO;
325361 private final int bufferSize;
326362 private final boolean immediateFlush;
363 private final boolean createOnDemand;
327364 private final TriggeringPolicy policy;
328365 private final RolloverStrategy strategy;
329366 private final String advertiseURI;
330367 private final Layout<? extends Serializable> layout;
331368
332369 /**
333 * Create the data for the factory.
370 * Creates the data for the factory.
334371 * @param pattern The pattern.
335372 * @param append The append flag.
336373 * @param bufferedIO The bufferedIO flag.
338375 * @param layout The Layout.
339376 * @param bufferSize the buffer size
340377 * @param immediateFlush flush on every write or not
378 * @param createOnDemand true if you want to lazy-create the file (a.k.a. on-demand.)
379 * @param configuration The configuration
341380 */
342381 public FactoryData(final String pattern, final boolean append, final boolean bufferedIO,
343382 final TriggeringPolicy policy, final RolloverStrategy strategy, final String advertiseURI,
344 final Layout<? extends Serializable> layout, final int bufferSize, final boolean immediateFlush) {
383 final Layout<? extends Serializable> layout, final int bufferSize, final boolean immediateFlush,
384 final boolean createOnDemand, final Configuration configuration) {
385 super(configuration);
345386 this.pattern = pattern;
346387 this.append = append;
347388 this.bufferedIO = bufferedIO;
351392 this.advertiseURI = advertiseURI;
352393 this.layout = layout;
353394 this.immediateFlush = immediateFlush;
395 this.createOnDemand = createOnDemand;
354396 }
355397
356398 public TriggeringPolicy getTriggeringPolicy()
417459 // LOG4J2-1140: check writeHeader before creating the file
418460 final boolean writeHeader = !data.append || !file.exists();
419461 try {
420 file.createNewFile();
462 final boolean created = data.createOnDemand ? false : file.createNewFile();
463 LOGGER.trace("New file '{}' created = {}", name, created);
421464 } catch (final IOException ioe) {
422465 LOGGER.error("Unable to create file " + name, ioe);
423466 return null;
424467 }
425468 final long size = data.append ? file.length() : 0;
426469
427 OutputStream os;
428470 try {
429 os = new FileOutputStream(name, data.append);
430471 final int actualSize = data.bufferedIO ? data.bufferSize : Constants.ENCODER_BYTE_BUFFER_SIZE;
431472 final ByteBuffer buffer = ByteBuffer.wrap(new byte[actualSize]);
432
433 final long time = file.lastModified(); // LOG4J2-531 create file first so time has valid value
434 return new RollingFileManager(name, data.pattern, os, data.append, size, time, data.policy,
435 data.strategy, data.advertiseURI, data.layout, writeHeader, buffer);
436 } catch (final FileNotFoundException ex) {
437 LOGGER.error("FileManager (" + name + ") " + ex, ex);
473 final OutputStream os = data.createOnDemand ? null : new FileOutputStream(name, data.append);
474 final long time = data.createOnDemand? System.currentTimeMillis() : file.lastModified(); // LOG4J2-531 create file first so time has valid value
475
476 return new RollingFileManager(data.getLoggerContext(), name, data.pattern, os,
477 data.append, data.createOnDemand, size, time, data.policy, data.strategy, data.advertiseURI,
478 data.layout, writeHeader, buffer);
479 } catch (final IOException ex) {
480 LOGGER.error("RollingFileManager (" + name + ") " + ex, ex);
438481 }
439482 return null;
440483 }
2323 import java.nio.ByteBuffer;
2424
2525 import org.apache.logging.log4j.core.Layout;
26 import org.apache.logging.log4j.core.LoggerContext;
2627 import org.apache.logging.log4j.core.appender.AppenderLoggingException;
28 import org.apache.logging.log4j.core.appender.ConfigurationFactoryData;
2729 import org.apache.logging.log4j.core.appender.ManagerFactory;
30 import org.apache.logging.log4j.core.config.Configuration;
2831 import org.apache.logging.log4j.core.util.NullOutputStream;
2932
3033 /**
4245 private RandomAccessFile randomAccessFile;
4346 private final ThreadLocal<Boolean> isEndOfBatch = new ThreadLocal<>();
4447
45 public RollingRandomAccessFileManager(final RandomAccessFile raf, final String fileName, final String pattern,
46 final OutputStream os, final boolean append, final boolean immediateFlush, final int bufferSize,
47 final long size, final long time, final TriggeringPolicy policy, final RolloverStrategy strategy,
48 final String advertiseURI, final Layout<? extends Serializable> layout, final boolean writeHeader) {
49 super(fileName, pattern, os, append, size, time, policy, strategy, advertiseURI, layout, writeHeader,
50 ByteBuffer.wrap(new byte[bufferSize]));
48 public RollingRandomAccessFileManager(final LoggerContext loggerContext, final RandomAccessFile raf,
49 final String fileName, final String pattern, final OutputStream os, final boolean append,
50 final boolean immediateFlush, final int bufferSize, final long size, final long time,
51 final TriggeringPolicy policy, final RolloverStrategy strategy, final String advertiseURI,
52 final Layout<? extends Serializable> layout, final boolean writeHeader) {
53 super(loggerContext, fileName, pattern, os, append, false, size, time, policy, strategy, advertiseURI, layout,
54 writeHeader, ByteBuffer.wrap(new byte[bufferSize]));
5155 this.randomAccessFile = raf;
5256 isEndOfBatch.set(Boolean.FALSE);
5357 writeHeader();
7074 randomAccessFile.write(header, 0, header.length);
7175 }
7276 } catch (final IOException e) {
73 logError("unable to write header", e);
77 logError("Unable to write header", e);
7478 }
7579 }
7680
7781 public static RollingRandomAccessFileManager getRollingRandomAccessFileManager(final String fileName,
7882 final String filePattern, final boolean isAppend, final boolean immediateFlush, final int bufferSize,
7983 final TriggeringPolicy policy, final RolloverStrategy strategy, final String advertiseURI,
80 final Layout<? extends Serializable> layout) {
84 final Layout<? extends Serializable> layout, final Configuration configuration) {
8185 return (RollingRandomAccessFileManager) getManager(fileName, new FactoryData(filePattern, isAppend,
82 immediateFlush, bufferSize, policy, strategy, advertiseURI, layout), FACTORY);
86 immediateFlush, bufferSize, policy, strategy, advertiseURI, layout, configuration), FACTORY);
8387 }
8488
8589 public Boolean isEndOfBatch() {
123127 }
124128
125129 @Override
126 public synchronized void close() {
130 public synchronized boolean closeOutputStream() {
127131 flush();
128132 try {
129133 randomAccessFile.close();
134 return true;
130135 } catch (final IOException e) {
131 logError("unable to close RandomAccessFile", e);
136 logError("Unable to close RandomAccessFile", e);
137 return false;
132138 }
133139 }
134140
181187 LOGGER.trace("RandomAccessFile {} set length to 0", name);
182188 raf.setLength(0);
183189 }
184 return new RollingRandomAccessFileManager(raf, name, data.pattern, NullOutputStream.NULL_OUTPUT_STREAM,
185 data.append, data.immediateFlush, data.bufferSize, size, time, data.policy, data.strategy,
186 data.advertiseURI, data.layout, writeHeader);
190 return new RollingRandomAccessFileManager(data.getLoggerContext(), raf, name, data.pattern,
191 NullOutputStream.getInstance(), data.append, data.immediateFlush, data.bufferSize, size, time, data.policy,
192 data.strategy, data.advertiseURI, data.layout, writeHeader);
187193 } catch (final IOException ex) {
188194 LOGGER.error("Cannot access RandomAccessFile " + ex, ex);
189195 if (raf != null) {
201207 /**
202208 * Factory data.
203209 */
204 private static class FactoryData {
210 private static class FactoryData extends ConfigurationFactoryData {
205211 private final String pattern;
206212 private final boolean append;
207213 private final boolean immediateFlush;
222228 * @param strategy
223229 * @param advertiseURI
224230 * @param layout
231 * @param configuration
225232 */
226233 public FactoryData(final String pattern, final boolean append, final boolean immediateFlush,
227234 final int bufferSize, final TriggeringPolicy policy, final RolloverStrategy strategy,
228 final String advertiseURI, final Layout<? extends Serializable> layout) {
235 final String advertiseURI, final Layout<? extends Serializable> layout, final Configuration configuration) {
236 super(configuration);
229237 this.pattern = pattern;
230238 this.append = append;
231239 this.immediateFlush = immediateFlush;
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.appender.rolling;
17
18 import org.apache.logging.log4j.Logger;
19 import org.apache.logging.log4j.core.LogEvent;
20 import org.apache.logging.log4j.core.config.plugins.Plugin;
21 import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
22 import org.apache.logging.log4j.core.config.plugins.PluginFactory;
23 import org.apache.logging.log4j.status.StatusLogger;
24
25 /**
26 *
27 */
28 @Plugin(name = "SizeBasedTriggeringPolicy", category = "Core", printObject = true)
29 public class SizeBasedTriggeringPolicy implements TriggeringPolicy {
30 /**
31 * Allow subclasses access to the status logger without creating another instance.
32 */
33 protected static final Logger LOGGER = StatusLogger.getLogger();
34
35 /**
36 * Rollover threshold size in bytes.
37 */
38 private static final long MAX_FILE_SIZE = 10 * 1024 * 1024; // let 10 MB the default max size
39
40 private final long maxFileSize;
41
42 private RollingFileManager manager;
43
44 /**
45 * Constructs a new instance.
46 */
47 protected SizeBasedTriggeringPolicy() {
48 this.maxFileSize = MAX_FILE_SIZE;
49 }
50
51 /**
52 * Constructs a new instance.
53 *
54 * @param maxFileSize rollover threshold size in bytes.
55 */
56 protected SizeBasedTriggeringPolicy(final long maxFileSize) {
57 this.maxFileSize = maxFileSize;
58 }
59
60 public long getMaxFileSize() {
61 return maxFileSize;
62 }
63
64 /**
65 * Initialize the TriggeringPolicy.
66 * @param aManager The RollingFileManager.
67 */
68 @Override
69 public void initialize(final RollingFileManager aManager) {
70 this.manager = aManager;
71 }
72
73
74 /**
75 * Returns true if a rollover should occur.
76 * @param event A reference to the currently event.
77 * @return true if a rollover should take place, false otherwise.
78 */
79 @Override
80 public boolean isTriggeringEvent(final LogEvent event) {
81 final boolean triggered = manager.getFileSize() > maxFileSize;
82 if (triggered) {
83 manager.getPatternProcessor().updateTime();
84 }
85 return triggered;
86 }
87
88 @Override
89 public String toString() {
90 return "SizeBasedTriggeringPolicy(size=" + maxFileSize + ')';
91 }
92
93 /**
94 * Create a SizeBasedTriggeringPolicy.
95 * @param size The size of the file before rollover is required.
96 * @return A SizeBasedTriggeringPolicy.
97 */
98 @PluginFactory
99 public static SizeBasedTriggeringPolicy createPolicy(@PluginAttribute("size") final String size) {
100
101 final long maxSize = size == null ? MAX_FILE_SIZE : FileSize.parse(size, MAX_FILE_SIZE);
102 return new SizeBasedTriggeringPolicy(maxSize);
103 }
104
105 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.appender.rolling;
17
18 import org.apache.logging.log4j.core.LogEvent;
19 import org.apache.logging.log4j.core.config.plugins.Plugin;
20 import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
21 import org.apache.logging.log4j.core.config.plugins.PluginFactory;
22
23 /**
24 *
25 */
26 @Plugin(name = "SizeBasedTriggeringPolicy", category = "Core", printObject = true)
27 public class SizeBasedTriggeringPolicy extends AbstractTriggeringPolicy {
28
29 /**
30 * Rollover threshold size in bytes.
31 */
32 private static final long MAX_FILE_SIZE = 10 * 1024 * 1024; // let 10 MB the default max size
33
34 private final long maxFileSize;
35
36 private RollingFileManager manager;
37
38 /**
39 * Constructs a new instance.
40 */
41 protected SizeBasedTriggeringPolicy() {
42 this.maxFileSize = MAX_FILE_SIZE;
43 }
44
45 /**
46 * Constructs a new instance.
47 *
48 * @param maxFileSize rollover threshold size in bytes.
49 */
50 protected SizeBasedTriggeringPolicy(final long maxFileSize) {
51 this.maxFileSize = maxFileSize;
52 }
53
54 public long getMaxFileSize() {
55 return maxFileSize;
56 }
57
58 /**
59 * Initialize the TriggeringPolicy.
60 * @param aManager The RollingFileManager.
61 */
62 @Override
63 public void initialize(final RollingFileManager aManager) {
64 this.manager = aManager;
65 }
66
67
68 /**
69 * Returns true if a rollover should occur.
70 * @param event A reference to the currently event.
71 * @return true if a rollover should take place, false otherwise.
72 */
73 @Override
74 public boolean isTriggeringEvent(final LogEvent event) {
75 final boolean triggered = manager.getFileSize() > maxFileSize;
76 if (triggered) {
77 manager.getPatternProcessor().updateTime();
78 }
79 return triggered;
80 }
81
82 @Override
83 public String toString() {
84 return "SizeBasedTriggeringPolicy(size=" + maxFileSize + ')';
85 }
86
87 /**
88 * Create a SizeBasedTriggeringPolicy.
89 * @param size The size of the file before rollover is required.
90 * @return A SizeBasedTriggeringPolicy.
91 */
92 @PluginFactory
93 public static SizeBasedTriggeringPolicy createPolicy(@PluginAttribute("size") final String size) {
94
95 final long maxSize = size == null ? MAX_FILE_SIZE : FileSize.parse(size, MAX_FILE_SIZE);
96 return new SizeBasedTriggeringPolicy(maxSize);
97 }
98
99 }
2525 * Rolls a file over based on time.
2626 */
2727 @Plugin(name = "TimeBasedTriggeringPolicy", category = "Core", printObject = true)
28 public final class TimeBasedTriggeringPolicy implements TriggeringPolicy {
28 public final class TimeBasedTriggeringPolicy extends AbstractTriggeringPolicy {
2929
3030 private long nextRolloverMillis;
3131 private final int interval;
2121 * A <code>TriggeringPolicy</code> controls the conditions under which rollover
2222 * occurs. Such conditions include time of day, file size, an
2323 * external event, the log request or a combination thereof.
24 *
25 * @see AbstractTriggeringPolicy
2426 */
25 public interface TriggeringPolicy {
27 public interface TriggeringPolicy /* TODO 3.0: extends LifeCycle */ {
2628
2729 /**
28 * Initialize the Policy.
30 * Initializes this triggering policy.
2931 * @param manager The RollingFileManager.
3032 */
3133
3638 * true is returned, RolloverPolicy.rollover will be called but it
3739 * can determine that a rollover is not warranted.
3840 *
39 * @param event A reference to the currently event.
41 * @param logEvent A reference to the current log event.
4042 * @return true if a rollover should occur.
4143 */
42 boolean isTriggeringEvent(final LogEvent event);
44 boolean isTriggeringEvent(final LogEvent logEvent);
4345 }
1919 import java.io.IOException;
2020 import java.io.PrintWriter;
2121 import java.nio.file.Files;
22 import java.nio.file.Path;
2322 import java.nio.file.Paths;
2423 import java.nio.file.StandardCopyOption;
2524
2121 import java.util.concurrent.ScheduledFuture;
2222 import java.util.concurrent.TimeUnit;
2323
24 import org.apache.logging.log4j.Logger;
2524 import org.apache.logging.log4j.core.AbstractLifeCycle;
2625 import org.apache.logging.log4j.core.LogEvent;
2726 import org.apache.logging.log4j.core.config.Configuration;
3130 import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
3231 import org.apache.logging.log4j.core.config.plugins.PluginConfiguration;
3332 import org.apache.logging.log4j.core.config.plugins.PluginFactory;
34 import org.apache.logging.log4j.status.StatusLogger;
3533
3634 /**
3735 * Policy is purging appenders that were not in use specified time in minutes
4038 @Scheduled
4139 public class IdlePurgePolicy extends AbstractLifeCycle implements PurgePolicy, Runnable {
4240
43 private static final Logger LOGGER = StatusLogger.getLogger();
4441 private final long timeToLive;
42 private final long checkInterval;
4543 private final ConcurrentMap<String, Long> appendersUsage = new ConcurrentHashMap<>();
4644 private RoutingAppender routingAppender;
4745 private final ConfigurationScheduler scheduler;
48 private volatile ScheduledFuture<?> future = null;
46 private volatile ScheduledFuture<?> future;
4947
50 public IdlePurgePolicy(final long timeToLive, final ConfigurationScheduler scheduler) {
48 public IdlePurgePolicy(final long timeToLive, final long checkInterval, final ConfigurationScheduler scheduler) {
5149 this.timeToLive = timeToLive;
50 this.checkInterval = checkInterval;
5251 this.scheduler = scheduler;
5352 }
5453
5554 @Override
56 public void initialize(final RoutingAppender routingAppender) {
55 public void initialize(@SuppressWarnings("hiding") final RoutingAppender routingAppender) {
5756 this.routingAppender = routingAppender;
5857 }
5958
6059 @Override
61 public void stop() {
62 super.stop();
63 future.cancel(true);
60 public boolean stop(final long timeout, final TimeUnit timeUnit) {
61 setStopping();
62 final boolean stopped = stop(future);
63 setStopped();
64 return stopped;
6465 }
6566
6667 /**
7273 for (final Entry<String, Long> entry : appendersUsage.entrySet()) {
7374 if (entry.getValue() < createTime) {
7475 LOGGER.debug("Removing appender " + entry.getKey());
75 appendersUsage.remove(entry.getKey());
76 routingAppender.deleteAppender(entry.getKey());
76 if (appendersUsage.remove(entry.getKey(), entry.getValue())) {
77 routingAppender.deleteAppender(entry.getKey());
78 }
7779 }
7880 }
7981 }
99101 }
100102
101103 private void scheduleNext() {
102 long createTime = Long.MAX_VALUE;
104 long updateTime = Long.MAX_VALUE;
103105 for (final Entry<String, Long> entry : appendersUsage.entrySet()) {
104 if (entry.getValue() < createTime) {
105 createTime = entry.getValue();
106 if (entry.getValue() < updateTime) {
107 updateTime = entry.getValue();
106108 }
107109 }
108 if (createTime < Long.MAX_VALUE) {
109 final long interval = timeToLive - (System.currentTimeMillis() - createTime);
110
111 if (updateTime < Long.MAX_VALUE) {
112 final long interval = timeToLive - (System.currentTimeMillis() - updateTime);
110113 future = scheduler.schedule(this, interval, TimeUnit.MILLISECONDS);
114 } else {
115 // reset to initial state - in case of all appenders already purged
116 future = scheduler.schedule(this, checkInterval, TimeUnit.MILLISECONDS);
111117 }
112118 }
113119
114120 /**
115121 * Create the PurgePolicy
116122 *
117 * @param timeToLive the number of increments of timeUnit before the Appender should be purged.
118 * @param timeUnit the unit of time the timeToLive is expressed in.
123 * @param timeToLive the number of increments of timeUnit before the Appender should be purged.
124 * @param checkInterval when all appenders purged, the number of increments of timeUnit to check if any appenders appeared
125 * @param timeUnit the unit of time the timeToLive and the checkInterval is expressed in.
119126 * @return The Routes container.
120127 */
121128 @PluginFactory
122129 public static PurgePolicy createPurgePolicy(
123130 @PluginAttribute("timeToLive") final String timeToLive,
131 @PluginAttribute("checkInterval") final String checkInterval,
124132 @PluginAttribute("timeUnit") final String timeUnit,
125133 @PluginConfiguration final Configuration configuration) {
126134
127135 if (timeToLive == null) {
128 LOGGER.error("A timeToLive value is required");
136 LOGGER.error("A timeToLive value is required");
129137 return null;
130138 }
131139 TimeUnit units;
135143 try {
136144 units = TimeUnit.valueOf(timeUnit.toUpperCase());
137145 } catch (final Exception ex) {
138 LOGGER.error("Invalid time unit {}", timeUnit);
146 LOGGER.error("Invalid timeUnit value {}. timeUnit set to MINUTES", timeUnit, ex);
139147 units = TimeUnit.MINUTES;
140148 }
141149 }
142150
143 final long ttl = units.toMillis(Long.parseLong(timeToLive));
151 long ttl = units.toMillis(Long.parseLong(timeToLive));
152 if (ttl < 0) {
153 LOGGER.error("timeToLive must be positive. timeToLive set to 0");
154 ttl = 0;
155 }
156
157 long ci;
158 if (checkInterval == null) {
159 ci = ttl;
160 } else {
161 ci = units.toMillis(Long.parseLong(checkInterval));
162 if (ci < 0) {
163 LOGGER.error("checkInterval must be positive. checkInterval set equal to timeToLive = {}", ttl);
164 ci = ttl;
165 }
166 }
144167
145
146 return new IdlePurgePolicy(ttl, configuration.getScheduler());
168 return new IdlePurgePolicy(ttl, ci, configuration.getScheduler());
147169 }
148170
149171 @Override
1818 import org.apache.logging.log4j.core.LogEvent;
1919
2020 /**
21 *
2221 * Policy for purging routed appenders
23 *
2422 */
2523 public interface PurgePolicy {
2624
2725 /**
28 * Activate purging appenders
26 * Activates purging appenders
2927 */
3028 void purge();
3129
3735 void update(String key, LogEvent event);
3836
3937 /**
40 * Initialize with routing appender
38 * Initializes with routing appender
4139 *
4240 * @param routingAppender
4341 */
1515 */
1616 package org.apache.logging.log4j.core.appender.routing;
1717
18 import static org.apache.logging.log4j.core.appender.routing.RoutingAppender.STATIC_VARIABLES_KEY;
19
20 import java.util.Objects;
21 import java.util.concurrent.ConcurrentMap;
22
23 import javax.script.Bindings;
24
1825 import org.apache.logging.log4j.Logger;
26 import org.apache.logging.log4j.core.LogEvent;
27 import org.apache.logging.log4j.core.config.Configuration;
1928 import org.apache.logging.log4j.core.config.plugins.Plugin;
2029 import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
30 import org.apache.logging.log4j.core.config.plugins.PluginBuilderFactory;
31 import org.apache.logging.log4j.core.config.plugins.PluginConfiguration;
2132 import org.apache.logging.log4j.core.config.plugins.PluginElement;
22 import org.apache.logging.log4j.core.config.plugins.PluginFactory;
33 import org.apache.logging.log4j.core.config.plugins.validation.constraints.Required;
34 import org.apache.logging.log4j.core.script.AbstractScript;
35 import org.apache.logging.log4j.core.script.ScriptManager;
2336 import org.apache.logging.log4j.status.StatusLogger;
2437
2538 /**
26 * Used to contain the individual Route elements.
39 * Contains the individual Route elements.
2740 */
2841 @Plugin(name = "Routes", category = "Core", printObject = true)
2942 public final class Routes {
3043
44 private static final String LOG_EVENT_KEY = "logEvent";
45
46 public static class Builder implements org.apache.logging.log4j.core.util.Builder<Routes> {
47
48 @PluginConfiguration
49 private Configuration configuration;
50
51 @PluginAttribute("pattern")
52 private String pattern;
53
54 @PluginElement("Script")
55 private AbstractScript patternScript;
56
57 @PluginElement("Routes")
58 @Required
59 private Route[] routes;
60
61 @Override
62 public Routes build() {
63 if (routes == null || routes.length == 0) {
64 LOGGER.error("No Routes configured.");
65 return null;
66 }
67 if (patternScript != null && pattern != null) {
68 LOGGER.warn("In a Routes element, you must configure either a Script element or a pattern attribute.");
69 }
70 if (patternScript != null) {
71 if (configuration == null) {
72 LOGGER.error("No Configuration defined for Routes; required for Script");
73 } else {
74 configuration.getScriptManager().addScript(patternScript);
75 }
76 }
77 return new Routes(configuration, patternScript, pattern, routes);
78 }
79
80 public Configuration getConfiguration() {
81 return configuration;
82 }
83
84 public String getPattern() {
85 return pattern;
86 }
87
88 public AbstractScript getPatternScript() {
89 return patternScript;
90 }
91
92 public Route[] getRoutes() {
93 return routes;
94 }
95
96 public Builder withConfiguration(@SuppressWarnings("hiding") final Configuration configuration) {
97 this.configuration = configuration;
98 return this;
99 }
100
101 public Builder withPattern(@SuppressWarnings("hiding") final String pattern) {
102 this.pattern = pattern;
103 return this;
104 }
105
106 public Builder withPatternScript(@SuppressWarnings("hiding") final AbstractScript patternScript) {
107 this.patternScript = patternScript;
108 return this;
109 }
110
111 public Builder withRoutes(@SuppressWarnings("hiding") final Route[] routes) {
112 this.routes = routes;
113 return this;
114 }
115
116 }
117
31118 private static final Logger LOGGER = StatusLogger.getLogger();
32119
120 /**
121 * Creates the Routes.
122 * @param pattern The pattern.
123 * @param routes An array of Route elements.
124 * @return The Routes container.
125 * @deprecated since 2.7; use {@link #newBuilder()}.
126 */
127 @Deprecated
128 public static Routes createRoutes(
129 final String pattern,
130 final Route... routes) {
131 if (routes == null || routes.length == 0) {
132 LOGGER.error("No routes configured");
133 return null;
134 }
135 return new Routes(null, null, pattern, routes);
136 }
137
138 @PluginBuilderFactory
139 public static Builder newBuilder() {
140 return new Builder();
141 }
142
143 private final Configuration configuration;
144
33145 private final String pattern;
146
147 private final AbstractScript patternScript;
148
149 // TODO Why not make this a Map or add a Map.
34150 private final Route[] routes;
35
36 private Routes(final String pattern, final Route... routes) {
151
152 private Routes(final Configuration configuration, final AbstractScript patternScript, final String pattern, final Route... routes) {
153 this.configuration = configuration;
154 this.patternScript = patternScript;
37155 this.pattern = pattern;
38156 this.routes = routes;
39157 }
40158
41159 /**
42160 * Returns the pattern.
161 * @param event The log event passed to the script (if there is a script.)
162 * @param scriptStaticVariables The script's static variables.
43163 * @return the pattern.
44164 */
45 public String getPattern() {
165 public String getPattern(final LogEvent event, final ConcurrentMap<Object, Object> scriptStaticVariables) {
166 if (patternScript != null) {
167 final ScriptManager scriptManager = configuration.getScriptManager();
168 final Bindings bindings = scriptManager.createBindings(patternScript);
169 bindings.put(STATIC_VARIABLES_KEY, scriptStaticVariables);
170 bindings.put(LOG_EVENT_KEY, event);
171 final Object object = scriptManager.execute(patternScript.getName(), bindings);
172 bindings.remove(LOG_EVENT_KEY);
173 return Objects.toString(object, null);
174 }
46175 return pattern;
176 }
177
178 /**
179 * Gets the optional script that decides which route to pick.
180 * @return the optional script that decides which route to pick. May be null.
181 */
182 public AbstractScript getPatternScript() {
183 return patternScript;
184 }
185
186 public Route getRoute(final String key) {
187 for (final Route route : routes) {
188 if (Objects.equals(route.getKey(), key)) {
189 return route;
190 }
191 }
192 return null;
47193 }
48194
49195 /**
70216
71217 }
72218
73 /**
74 * Create the Routes.
75 * @param pattern The pattern.
76 * @param routes An array of Route elements.
77 * @return The Routes container.
78 */
79 @PluginFactory
80 public static Routes createRoutes(
81 @PluginAttribute("pattern") final String pattern,
82 @PluginElement("Routes") final Route... routes) {
83 if (pattern == null) {
84 LOGGER.error("A pattern is required");
85 return null;
86 }
87 if (routes == null || routes.length == 0) {
88 LOGGER.error("No routes configured");
89 return null;
90 }
91 return new Routes(pattern, routes);
92 }
93219 }
1717
1818 import java.util.Collections;
1919 import java.util.Map;
20 import java.util.Objects;
2021 import java.util.concurrent.ConcurrentHashMap;
2122 import java.util.concurrent.ConcurrentMap;
23 import java.util.concurrent.TimeUnit;
24
25 import javax.script.Bindings;
2226
2327 import org.apache.logging.log4j.core.Appender;
2428 import org.apache.logging.log4j.core.Filter;
29 import org.apache.logging.log4j.core.LifeCycle2;
2530 import org.apache.logging.log4j.core.LogEvent;
2631 import org.apache.logging.log4j.core.appender.AbstractAppender;
2732 import org.apache.logging.log4j.core.appender.rewrite.RewritePolicy;
2934 import org.apache.logging.log4j.core.config.Configuration;
3035 import org.apache.logging.log4j.core.config.Node;
3136 import org.apache.logging.log4j.core.config.plugins.Plugin;
32 import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
37 import org.apache.logging.log4j.core.config.plugins.PluginBuilderFactory;
3338 import org.apache.logging.log4j.core.config.plugins.PluginConfiguration;
3439 import org.apache.logging.log4j.core.config.plugins.PluginElement;
35 import org.apache.logging.log4j.core.config.plugins.PluginFactory;
40 import org.apache.logging.log4j.core.script.AbstractScript;
41 import org.apache.logging.log4j.core.script.ScriptManager;
3642 import org.apache.logging.log4j.core.util.Booleans;
3743
3844 /**
4349 * the form "$${[key:]token}". The pattern will be resolved each time the Appender is called using
4450 * the built in StrSubstitutor and the StrLookup plugin that matches the specified key.
4551 */
46 @Plugin(name = "Routing", category = "Core", elementType = "appender", printObject = true)
52 @Plugin(name = "Routing", category = "Core", elementType = Appender.ELEMENT_TYPE, printObject = true)
4753 public final class RoutingAppender extends AbstractAppender {
54
55 public static final String STATIC_VARIABLES_KEY = "staticVariables";
56
57 public static class Builder<B extends Builder<B>> extends AbstractAppender.Builder<B>
58 implements org.apache.logging.log4j.core.util.Builder<RoutingAppender> {
59
60 // Does not work unless the element is called "Script", I wanted "DefaultRounteScript"...
61 @PluginElement("Script")
62 private AbstractScript defaultRouteScript;
63
64 @PluginElement("Routes")
65 private Routes routes;
66
67 @PluginConfiguration
68 private Configuration configuration;
69
70 @PluginElement("RewritePolicy")
71 private RewritePolicy rewritePolicy;
72
73 @PluginElement("PurgePolicy")
74 private PurgePolicy purgePolicy;
75
76 @Override
77 public RoutingAppender build() {
78 final String name = getName();
79 if (name == null) {
80 LOGGER.error("No name defined for this RoutingAppender");
81 return null;
82 }
83 if (routes == null) {
84 LOGGER.error("No routes defined for RoutingAppender {}", name);
85 return null;
86 }
87 return new RoutingAppender(name, getFilter(), isIgnoreExceptions(), routes, rewritePolicy,
88 configuration, purgePolicy, defaultRouteScript);
89 }
90
91 public Routes getRoutes() {
92 return routes;
93 }
94
95 public Configuration getConfiguration() {
96 return configuration;
97 }
98
99 public AbstractScript getDefaultRouteScript() {
100 return defaultRouteScript;
101 }
102
103 public RewritePolicy getRewritePolicy() {
104 return rewritePolicy;
105 }
106
107 public PurgePolicy getPurgePolicy() {
108 return purgePolicy;
109 }
110
111 public B withRoutes(@SuppressWarnings("hiding") final Routes routes) {
112 this.routes = routes;
113 return asBuilder();
114 }
115
116 public B withConfiguration(@SuppressWarnings("hiding") final Configuration configuration) {
117 this.configuration = configuration;
118 return asBuilder();
119 }
120
121 public B withDefaultRouteScript(@SuppressWarnings("hiding") final AbstractScript defaultRouteScript) {
122 this.defaultRouteScript = defaultRouteScript;
123 return asBuilder();
124 }
125
126 public B withRewritePolicy(@SuppressWarnings("hiding") final RewritePolicy rewritePolicy) {
127 this.rewritePolicy = rewritePolicy;
128 return asBuilder();
129 }
130
131 public void withPurgePolicy(@SuppressWarnings("hiding") final PurgePolicy purgePolicy) {
132 this.purgePolicy = purgePolicy;
133 }
134
135 }
136
137 @PluginBuilderFactory
138 public static <B extends Builder<B>> B newBuilder() {
139 return new Builder<B>().asBuilder();
140 }
141
48142 private static final String DEFAULT_KEY = "ROUTING_APPENDER_DEFAULT";
143
49144 private final Routes routes;
50 private final Route defaultRoute;
51 private final Configuration config;
145 private Route defaultRoute;
146 private final Configuration configuration;
52147 private final ConcurrentMap<String, AppenderControl> appenders = new ConcurrentHashMap<>();
53148 private final RewritePolicy rewritePolicy;
54 private final PurgePolicy purgePolicy;
149 private final PurgePolicy purgePolicy;
150 private final AbstractScript defaultRouteScript;
151 private final ConcurrentMap<Object, Object> scriptStaticVariables = new ConcurrentHashMap<>();
55152
56153 private RoutingAppender(final String name, final Filter filter, final boolean ignoreExceptions, final Routes routes,
57 final RewritePolicy rewritePolicy, final Configuration config, final PurgePolicy purgePolicy) {
154 final RewritePolicy rewritePolicy, final Configuration configuration, final PurgePolicy purgePolicy,
155 final AbstractScript defaultRouteScript) {
58156 super(name, filter, null, ignoreExceptions);
59157 this.routes = routes;
60 this.config = config;
158 this.configuration = configuration;
61159 this.rewritePolicy = rewritePolicy;
62160 this.purgePolicy = purgePolicy;
63 if(this.purgePolicy != null) {
64 this.purgePolicy.initialize(this);
65 }
161 if (this.purgePolicy != null) {
162 this.purgePolicy.initialize(this);
163 }
164 this.defaultRouteScript = defaultRouteScript;
66165 Route defRoute = null;
67166 for (final Route route : routes.getRoutes()) {
68167 if (route.getKey() == null) {
78177
79178 @Override
80179 public void start() {
180 if (defaultRouteScript != null) {
181 if (configuration == null) {
182 error("No Configuration defined for RoutingAppender; required for Script element.");
183 } else {
184 final ScriptManager scriptManager = configuration.getScriptManager();
185 scriptManager.addScript(defaultRouteScript);
186 final Bindings bindings = scriptManager.createBindings(defaultRouteScript);
187 bindings.put(STATIC_VARIABLES_KEY, scriptStaticVariables);
188 final Object object = scriptManager.execute(defaultRouteScript.getName(), bindings);
189 final Route route = routes.getRoute(Objects.toString(object, null));
190 if (route != null) {
191 defaultRoute = route;
192 }
193 }
194 }
81195 // Register all the static routes.
82196 for (final Route route : routes.getRoutes()) {
83197 if (route.getAppenderRef() != null) {
84 final Appender appender = config.getAppender(route.getAppenderRef());
198 final Appender appender = configuration.getAppender(route.getAppenderRef());
85199 if (appender != null) {
86200 final String key = route == defaultRoute ? DEFAULT_KEY : route.getKey();
87201 appenders.put(key, new AppenderControl(appender, null, null));
88202 } else {
89 LOGGER.error("Appender " + route.getAppenderRef() + " cannot be located. Route ignored");
203 error("Appender " + route.getAppenderRef() + " cannot be located. Route ignored");
90204 }
91205 }
92206 }
94208 }
95209
96210 @Override
97 public void stop() {
98 super.stop();
99 final Map<String, Appender> map = config.getAppenders();
211 public boolean stop(final long timeout, final TimeUnit timeUnit) {
212 setStopping();
213 super.stop(timeout, timeUnit, false);
214 final Map<String, Appender> map = configuration.getAppenders();
100215 for (final Map.Entry<String, AppenderControl> entry : appenders.entrySet()) {
101 final String name = entry.getValue().getAppender().getName();
102 if (!map.containsKey(name)) {
103 entry.getValue().getAppender().stop();
104 }
105 }
216 final Appender appender = entry.getValue().getAppender();
217 if (!map.containsKey(appender.getName())) {
218 if (appender instanceof LifeCycle2) {
219 ((LifeCycle2) appender).stop(timeout, timeUnit);
220 } else {
221 appender.stop();
222 }
223 }
224 }
225 setStopped();
226 return true;
106227 }
107228
108229 @Override
110231 if (rewritePolicy != null) {
111232 event = rewritePolicy.rewrite(event);
112233 }
113 final String key = config.getStrSubstitutor().replace(event, routes.getPattern());
234 final String pattern = routes.getPattern(event, scriptStaticVariables);
235 final String key = pattern != null ? configuration.getStrSubstitutor().replace(event, pattern) : defaultRoute.getKey();
114236 final AppenderControl control = getControl(key, event);
115237 if (control != null) {
116238 control.callAppender(event);
117239 }
118
119 if(purgePolicy != null) {
120 purgePolicy.update(key, event);
121 }
122 }
123
124 private synchronized AppenderControl getControl(final String key, final LogEvent event) {
240
241 if (purgePolicy != null) {
242 purgePolicy.update(key, event);
243 }
244 }
245
246 private synchronized AppenderControl getControl(final String key, final LogEvent event) {
125247 AppenderControl control = appenders.get(key);
126248 if (control != null) {
127249 return control;
155277 private Appender createAppender(final Route route, final LogEvent event) {
156278 final Node routeNode = route.getNode();
157279 for (final Node node : routeNode.getChildren()) {
158 if (node.getType().getElementName().equals("appender")) {
280 if (node.getType().getElementName().equals(Appender.ELEMENT_TYPE)) {
159281 final Node appNode = new Node(node);
160 config.createConfiguration(appNode, event);
282 configuration.createConfiguration(appNode, event);
161283 if (appNode.getObject() instanceof Appender) {
162284 final Appender app = appNode.getObject();
163285 app.start();
164286 return app;
165287 }
166 LOGGER.error("Unable to create Appender of type " + node.getName());
288 error("Unable to create Appender of type " + node.getName());
167289 return null;
168290 }
169291 }
170 LOGGER.error("No Appender was configured for route " + route.getKey());
292 error("No Appender was configured for route " + route.getKey());
171293 return null;
172294 }
173
295
174296 public Map<String, AppenderControl> getAppenders() {
175 return Collections.unmodifiableMap(appenders);
176 }
177
297 return Collections.unmodifiableMap(appenders);
298 }
299
178300 /**
179 * Delete specified appender
180 *
301 * Deletes the specified appender.
302 *
181303 * @param key The appender's key
182304 */
183305 public void deleteAppender(final String key) {
184 LOGGER.debug("Stopping route with key" + key);
185 final AppenderControl control = appenders.remove(key);
186 control.getAppender().stop();
306 LOGGER.debug("Deleting route with " + key + " key ");
307 final AppenderControl control = appenders.remove(key);
308 if (null != control) {
309 LOGGER.debug("Stopping route with " + key + " key");
310 control.getAppender().stop();
311 } else {
312 LOGGER.debug("Route with " + key + " key already deleted");
313 }
187314 }
188315
189316 /**
190 * Create a RoutingAppender.
317 * Creates a RoutingAppender.
191318 * @param name The name of the Appender.
192319 * @param ignore If {@code "true"} (default) exceptions encountered when appending events are logged; otherwise
193320 * they are propagated to the caller.
196323 * @param rewritePolicy A RewritePolicy, if any.
197324 * @param filter A Filter to restrict events processed by the Appender or null.
198325 * @return The RoutingAppender
326 * @deprecated Since 2.7; use {@link #newBuilder()}
199327 */
200 @PluginFactory
328 @Deprecated
201329 public static RoutingAppender createAppender(
202 @PluginAttribute("name") final String name,
203 @PluginAttribute("ignoreExceptions") final String ignore,
204 @PluginElement("Routes") final Routes routes,
205 @PluginConfiguration final Configuration config,
206 @PluginElement("RewritePolicy") final RewritePolicy rewritePolicy,
207 @PluginElement("PurgePolicy") final PurgePolicy purgePolicy,
208 @PluginElement("Filter") final Filter filter) {
330 final String name,
331 final String ignore,
332 final Routes routes,
333 final Configuration config,
334 final RewritePolicy rewritePolicy,
335 final PurgePolicy purgePolicy,
336 final Filter filter) {
209337
210338 final boolean ignoreExceptions = Booleans.parseBoolean(ignore, true);
211339 if (name == null) {
216344 LOGGER.error("No routes defined for RoutingAppender");
217345 return null;
218346 }
219 return new RoutingAppender(name, filter, ignoreExceptions, routes, rewritePolicy, config, purgePolicy);
347 return new RoutingAppender(name, filter, ignoreExceptions, routes, rewritePolicy, config, purgePolicy, null);
348 }
349
350 public Route getDefaultRoute() {
351 return defaultRoute;
352 }
353
354 public AbstractScript getDefaultRouteScript() {
355 return defaultRouteScript;
356 }
357
358 public PurgePolicy getPurgePolicy() {
359 return purgePolicy;
360 }
361
362 public RewritePolicy getRewritePolicy() {
363 return rewritePolicy;
364 }
365
366 public Routes getRoutes() {
367 return routes;
368 }
369
370 public Configuration getConfiguration() {
371 return configuration;
372 }
373
374 public ConcurrentMap<Object, Object> getScriptStaticVariables() {
375 return scriptStaticVariables;
220376 }
221377 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.async;
17
18 import java.util.concurrent.ArrayBlockingQueue;
19 import java.util.concurrent.BlockingQueue;
20
21 import org.apache.logging.log4j.core.config.Node;
22 import org.apache.logging.log4j.core.config.plugins.Plugin;
23 import org.apache.logging.log4j.core.config.plugins.PluginFactory;
24
25 /**
26 * Factory for creating instances of {@link ArrayBlockingQueue}.
27 *
28 * @since 2.7
29 */
30 @Plugin(name = "ArrayBlockingQueue", category = Node.CATEGORY, elementType = BlockingQueueFactory.ELEMENT_TYPE)
31 public class ArrayBlockingQueueFactory<E> implements BlockingQueueFactory<E> {
32 @Override
33 public BlockingQueue<E> create(final int capacity) {
34 return new ArrayBlockingQueue<>(capacity);
35 }
36
37 @PluginFactory
38 public static <E> ArrayBlockingQueueFactory<E> createFactory() {
39 return new ArrayBlockingQueueFactory<>();
40 }
41 }
1515 */
1616 package org.apache.logging.log4j.core.async;
1717
18 import java.util.Map;
18 import java.util.List;
1919
2020 import org.apache.logging.log4j.Level;
2121 import org.apache.logging.log4j.Marker;
2626 import org.apache.logging.log4j.core.config.Configuration;
2727 import org.apache.logging.log4j.core.config.Property;
2828 import org.apache.logging.log4j.core.config.ReliabilityStrategy;
29 import org.apache.logging.log4j.core.impl.ContextDataFactory;
30 import org.apache.logging.log4j.core.ContextDataInjector;
31 import org.apache.logging.log4j.core.impl.ContextDataInjectorFactory;
2932 import org.apache.logging.log4j.core.impl.Log4jLogEvent;
3033 import org.apache.logging.log4j.core.util.Clock;
3134 import org.apache.logging.log4j.core.util.ClockFactory;
3437 import org.apache.logging.log4j.message.Message;
3538 import org.apache.logging.log4j.message.MessageFactory;
3639 import org.apache.logging.log4j.message.ReusableMessage;
40 import org.apache.logging.log4j.util.StringMap;
3741 import org.apache.logging.log4j.status.StatusLogger;
3842
3943 import com.lmax.disruptor.EventTranslatorVararg;
6670
6771 private static final StatusLogger LOGGER = StatusLogger.getLogger();
6872 private static final Clock CLOCK = ClockFactory.getClock(); // not reconfigurable
73 private static final ContextDataInjector CONTEXT_DATA_INJECTOR = ContextDataInjectorFactory.createInjector();
6974
7075 private static final ThreadNameCachingStrategy THREAD_NAME_CACHING_STRATEGY = ThreadNameCachingStrategy.create();
7176
185190 // don't construct ThrowableProxy until required
186191 thrown,
187192
188 // config properties are taken care of in the EventHandler thread
189 // in the AsyncLogger#actualAsyncLog method
190
191 // needs shallow copy to be fast (LOG4J2-154)
192 ThreadContext.getImmutableContext(), //
193
194193 // needs shallow copy to be fast (LOG4J2-154)
195194 ThreadContext.getImmutableStack(), //
195
196196 // location (expensive to calculate)
197197 calcLocationIfRequested(fqcn), //
198198 CLOCK.currentTimeMillis(), //
267267 final Throwable thrown = (Throwable) args[6];
268268
269269 // needs shallow copy to be fast (LOG4J2-154)
270 final Map<String, String> contextMap = ThreadContext.getImmutableContext();
271
272 // needs shallow copy to be fast (LOG4J2-154)
273270 final ContextStack contextStack = ThreadContext.getImmutableStack();
274271
275272 final Thread currentThread = Thread.currentThread();
276273 final String threadName = THREAD_NAME_CACHING_STRATEGY.getThreadName();
277 event.setValues(asyncLogger, asyncLogger.getName(), marker, fqcn, level, message, thrown, contextMap,
274 event.setValues(asyncLogger, asyncLogger.getName(), marker, fqcn, level, message, thrown,
275 // config properties are taken care of in the EventHandler thread
276 // in the AsyncLogger#actualAsyncLog method
277 CONTEXT_DATA_INJECTOR.injectContextData(null, (StringMap) event.getContextData()),
278278 contextStack, currentThread.getId(), threadName, currentThread.getPriority(), location,
279279 CLOCK.currentTimeMillis(), nanoClock.nanoTime());
280280 }
298298
299299 /**
300300 * This method is called by the EventHandler that processes the RingBufferLogEvent in a separate thread.
301 * Merges the contents of the configuration map into the contextData, after replacing any variables in the property
302 * values with the StrSubstitutor-supplied actual values.
301303 *
302304 * @param event the event to log
303305 */
304306 public void actualAsyncLog(final RingBufferLogEvent event) {
305 final Map<Property, Boolean> properties = privateConfig.loggerConfig.getProperties();
306 event.mergePropertiesIntoContextMap(properties, privateConfig.config.getStrSubstitutor());
307 final List<Property> properties = privateConfig.loggerConfig.getPropertyList();
308
309 if (properties != null) {
310 StringMap contextData = (StringMap) event.getContextData();
311 if (contextData.isFrozen()) {
312 final StringMap temp = ContextDataFactory.createContextData();
313 temp.putAll(contextData);
314 contextData = temp;
315 }
316 for (int i = 0; i < properties.size(); i++) {
317 final Property prop = properties.get(i);
318 if (contextData.getValue(prop.getName()) != null) {
319 continue; // contextMap overrides config properties
320 }
321 final String value = prop.isValueNeedsLookup() //
322 ? privateConfig.config.getStrSubstitutor().replace(event, prop.getValue()) //
323 : prop.getValue();
324 contextData.putValue(prop.getName(), prop.getValue());
325 }
326 event.setContextData(contextData);
327 }
328
307329 final ReliabilityStrategy strategy = privateConfig.loggerConfig.getReliabilityStrategy();
308330 strategy.log(this, event);
309331 }
1717
1818 import java.util.Arrays;
1919 import java.util.List;
20 import java.util.concurrent.TimeUnit;
2021
2122 import org.apache.logging.log4j.Level;
2223 import org.apache.logging.log4j.LogManager;
123124 }
124125
125126 @Override
126 public void stop() {
127 public boolean stop(final long timeout, final TimeUnit timeUnit) {
128 setStopping();
129 super.stop(timeout, timeUnit, false);
127130 LOGGER.trace("AsyncLoggerConfig[{}] stopping...", displayName());
128 super.stop();
131 setStopped();
132 return true;
129133 }
130134
131135 /**
1818 import java.util.concurrent.ExecutorService;
1919 import java.util.concurrent.Executors;
2020 import java.util.concurrent.ThreadFactory;
21 import java.util.concurrent.TimeUnit;
2122
2223 import org.apache.logging.log4j.Level;
23 import org.apache.logging.log4j.Logger;
24 import org.apache.logging.log4j.core.AbstractLifeCycle;
2425 import org.apache.logging.log4j.core.LogEvent;
2526 import org.apache.logging.log4j.core.impl.Log4jLogEvent;
2627 import org.apache.logging.log4j.core.impl.LogEventFactory;
2728 import org.apache.logging.log4j.core.impl.MutableLogEvent;
2829 import org.apache.logging.log4j.core.impl.ReusableLogEventFactory;
2930 import org.apache.logging.log4j.core.jmx.RingBufferAdmin;
31 import org.apache.logging.log4j.core.util.ExecutorServices;
32 import org.apache.logging.log4j.core.util.Log4jThreadFactory;
3033 import org.apache.logging.log4j.message.ReusableMessage;
31 import org.apache.logging.log4j.status.StatusLogger;
3234
3335 import com.lmax.disruptor.EventFactory;
3436 import com.lmax.disruptor.EventTranslatorTwoArg;
5254 * This class serves to make the dependency on the Disruptor optional, so that these classes are only loaded when the
5355 * {@code AsyncLoggerConfig} is actually used.
5456 */
55 public class AsyncLoggerConfigDisruptor implements AsyncLoggerConfigDelegate {
57 public class AsyncLoggerConfigDisruptor extends AbstractLifeCycle implements AsyncLoggerConfigDelegate {
5658
5759 private static final int MAX_DRAIN_ATTEMPTS_BEFORE_SHUTDOWN = 200;
5860 private static final int SLEEP_MILLIS_BETWEEN_DRAIN_ATTEMPTS = 50;
59 private static final Logger LOGGER = StatusLogger.getLogger();
6061
6162 /**
6263 * RingBuffer events contain all information necessary to perform the work in a separate thread.
175176 }
176177 };
177178
178 private static final ThreadFactory THREAD_FACTORY = new DaemonThreadFactory("AsyncLoggerConfig-");
179 private static final ThreadFactory THREAD_FACTORY = Log4jThreadFactory.createDaemonThreadFactory("AsyncLoggerConfig");
179180
180181 private int ringBufferSize;
181182 private AsyncQueueFullPolicy asyncQueueFullPolicy;
204205 *
205206 * @see #stop()
206207 */
208 @Override
207209 public synchronized void start() {
208210 if (disruptor != null) {
209211 LOGGER.trace("AsyncLoggerConfigDisruptor not starting new disruptor for this configuration, "
231233 + "waitStrategy={}, exceptionHandler={}...", disruptor.getRingBuffer().getBufferSize(), waitStrategy
232234 .getClass().getSimpleName(), errorHandler);
233235 disruptor.start();
236 super.start();
234237 }
235238
236239 /**
237240 * Decreases the reference count. If the reference count reached zero, the Disruptor and its associated thread are
238241 * shut down and their references set to {@code null}.
239242 */
240 public synchronized void stop() {
243 @Override
244 public boolean stop(final long timeout, final TimeUnit timeUnit) {
241245 final Disruptor<Log4jEventWrapper> temp = disruptor;
242246 if (temp == null) {
243247 LOGGER.trace("AsyncLoggerConfigDisruptor: disruptor for this configuration already shut down.");
244 return; // disruptor was already shut down by another thread
245 }
248 return true; // disruptor was already shut down by another thread
249 }
250 setStopping();
246251 LOGGER.trace("AsyncLoggerConfigDisruptor: shutting down disruptor for this configuration.");
247252
248253 // We must guarantee that publishing to the RingBuffer has stopped before we call disruptor.shutdown().
260265 temp.shutdown(); // busy-spins until all events currently in the disruptor have been processed
261266
262267 LOGGER.trace("AsyncLoggerConfigDisruptor: shutting down disruptor executor for this configuration.");
263 executor.shutdown(); // finally, kill the processor thread
268 // finally, kill the processor thread
269 ExecutorServices.shutdown(executor, timeout, timeUnit, toString());
264270 executor = null; // release reference to allow GC
265271
266272 if (DiscardingAsyncQueueFullPolicy.getDiscardCount(asyncQueueFullPolicy) > 0) {
267273 LOGGER.trace("AsyncLoggerConfigDisruptor: {} discarded {} events.", asyncQueueFullPolicy,
268274 DiscardingAsyncQueueFullPolicy.getDiscardCount(asyncQueueFullPolicy));
269275 }
276 setStopped();
277 return true;
270278 }
271279
272280 /**
1616 package org.apache.logging.log4j.core.async;
1717
1818 import java.net.URI;
19 import java.util.concurrent.TimeUnit;
1920
2021 import org.apache.logging.log4j.core.Logger;
2122 import org.apache.logging.log4j.core.LoggerContext;
9798 }
9899
99100 @Override
100 public void stop() {
101 loggerDisruptor.stop(); // first stop Disruptor
102 super.stop();
101 public boolean stop(final long timeout, final TimeUnit timeUnit) {
102 setStopping();
103 // first stop Disruptor
104 loggerDisruptor.stop(timeout, timeUnit);
105 super.stop(timeout, timeUnit);
106 return true;
103107 }
104108
105109 /**
1818
1919 import java.util.concurrent.ExecutorService;
2020 import java.util.concurrent.Executors;
21 import java.util.concurrent.TimeUnit;
2122
2223 import org.apache.logging.log4j.Level;
24 import org.apache.logging.log4j.core.AbstractLifeCycle;
2325 import org.apache.logging.log4j.core.jmx.RingBufferAdmin;
24 import org.apache.logging.log4j.status.StatusLogger;
26 import org.apache.logging.log4j.core.util.ExecutorServices;
27 import org.apache.logging.log4j.core.util.Log4jThreadFactory;
2528
2629 import com.lmax.disruptor.ExceptionHandler;
2730 import com.lmax.disruptor.RingBuffer;
31 import com.lmax.disruptor.TimeoutException;
2832 import com.lmax.disruptor.WaitStrategy;
2933 import com.lmax.disruptor.dsl.Disruptor;
3034 import com.lmax.disruptor.dsl.ProducerType;
3539 * life cycle of the context. The AsyncLoggerDisruptor of the context is shared by all AsyncLogger objects created by
3640 * that AsyncLoggerContext.
3741 */
38 class AsyncLoggerDisruptor {
42 class AsyncLoggerDisruptor extends AbstractLifeCycle {
3943 private static final int SLEEP_MILLIS_BETWEEN_DRAIN_ATTEMPTS = 50;
4044 private static final int MAX_DRAIN_ATTEMPTS_BEFORE_SHUTDOWN = 200;
41 private static final StatusLogger LOGGER = StatusLogger.getLogger();
4245
4346 private volatile Disruptor<RingBufferLogEvent> disruptor;
4447 private ExecutorService executor;
7073 *
7174 * @see #stop()
7275 */
73 synchronized void start() {
76 @Override
77 public synchronized void start() {
7478 if (disruptor != null) {
7579 LOGGER.trace(
7680 "[{}] AsyncLoggerDisruptor not starting new disruptor for this context, using existing object.",
8084 LOGGER.trace("[{}] AsyncLoggerDisruptor creating new disruptor for this context.", contextName);
8185 ringBufferSize = DisruptorUtil.calculateRingBufferSize("AsyncLogger.RingBufferSize");
8286 final WaitStrategy waitStrategy = DisruptorUtil.createWaitStrategy("AsyncLogger.WaitStrategy");
83 executor = Executors.newSingleThreadExecutor(new DaemonThreadFactory("AsyncLogger[" + contextName + "]"));
87 executor = Executors.newSingleThreadExecutor(Log4jThreadFactory.createDaemonThreadFactory("AsyncLogger[" + contextName + "]"));
8488 backgroundThreadId = DisruptorUtil.getExecutorThreadId(executor);
8589 asyncQueueFullPolicy = AsyncQueueFullPolicyFactory.create();
8690
100104
101105 LOGGER.trace("[{}] AsyncLoggers use a {} translator", contextName, useThreadLocalTranslator ? "threadlocal"
102106 : "vararg");
107 super.start();
103108 }
104109
105110 /**
106111 * Decreases the reference count. If the reference count reached zero, the Disruptor and its associated thread are
107112 * shut down and their references set to {@code null}.
108113 */
109 synchronized void stop() {
114 @Override
115 public boolean stop(final long timeout, final TimeUnit timeUnit) {
110116 final Disruptor<RingBufferLogEvent> temp = getDisruptor();
111117 if (temp == null) {
112118 LOGGER.trace("[{}] AsyncLoggerDisruptor: disruptor for this context already shut down.", contextName);
113 return; // disruptor was already shut down by another thread
114 }
119 return true; // disruptor was already shut down by another thread
120 }
121 setStopping();
115122 LOGGER.debug("[{}] AsyncLoggerDisruptor: shutting down disruptor for this context.", contextName);
116123
117124 // We must guarantee that publishing to the RingBuffer has stopped before we call disruptor.shutdown().
126133 } catch (final InterruptedException e) { // ignored
127134 }
128135 }
129 temp.shutdown(); // busy-spins until all events currently in the disruptor have been processed
136 try {
137 // busy-spins until all events currently in the disruptor have been processed
138 temp.shutdown(timeout, timeUnit);
139 } catch (final TimeoutException e) {
140 temp.shutdown();
141 }
130142
131143 LOGGER.trace("[{}] AsyncLoggerDisruptor: shutting down disruptor executor.", contextName);
132 executor.shutdown(); // finally, kill the processor thread
144 // finally, kill the processor thread
145 ExecutorServices.shutdown(executor, timeout, timeUnit, toString());
133146 executor = null;
134147
135148 if (DiscardingAsyncQueueFullPolicy.getDiscardCount(asyncQueueFullPolicy) > 0) {
136149 LOGGER.trace("AsyncLoggerDisruptor: {} discarded {} events.", asyncQueueFullPolicy,
137150 DiscardingAsyncQueueFullPolicy.getDiscardCount(asyncQueueFullPolicy));
138151 }
152 setStopped();
153 return true;
139154 }
140155
141156 /**
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.async;
17
18 import java.util.concurrent.BlockingQueue;
19
20 /**
21 * Factory for creating instances of {@link BlockingQueue}.
22 *
23 * @since 2.7
24 */
25 public interface BlockingQueueFactory<E> {
26
27 /**
28 * The {@link org.apache.logging.log4j.core.config.plugins.Plugin#elementType() element type} to use for plugins
29 * implementing this interface.
30 */
31 String ELEMENT_TYPE = "BlockingQueueFactory";
32
33 /**
34 * Creates a new BlockingQueue with the specified maximum capacity. Note that not all implementations of
35 * BlockingQueue support a bounded capacity in which case the value is ignored.
36 *
37 * @param capacity maximum size of the queue if supported
38 * @return a new BlockingQueue
39 */
40 BlockingQueue<E> create(int capacity);
41 }
+0
-53
log4j-core/src/main/java/org/apache/logging/log4j/core/async/DaemonThreadFactory.java less more
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.async;
17
18 import java.util.concurrent.ThreadFactory;
19 import java.util.concurrent.atomic.AtomicInteger;
20
21 import org.apache.logging.log4j.core.util.Log4jThread;
22
23 /**
24 * ThreadFactory that creates daemon threads for the async loggers.
25 */
26 public class DaemonThreadFactory implements ThreadFactory {
27
28 private static final AtomicInteger THREAD_NUMBER = new AtomicInteger(1);
29 private final ThreadGroup group;
30 private final String threadNamePrefix;
31
32 public DaemonThreadFactory(final String threadNamePrefix) {
33 this.threadNamePrefix = threadNamePrefix;
34 final SecurityManager securityManager = System.getSecurityManager();
35 group = (securityManager != null) ? securityManager.getThreadGroup()
36 : Thread.currentThread().getThreadGroup();
37 }
38
39 @Override
40 public Thread newThread(final Runnable runnable) {
41 final Thread thread = new Log4jThread(group, runnable, threadNamePrefix
42 + THREAD_NUMBER.getAndIncrement(), 0);
43 if (!thread.isDaemon()) {
44 thread.setDaemon(true);
45 }
46 if (thread.getPriority() != Thread.NORM_PRIORITY) {
47 thread.setPriority(Thread.NORM_PRIORITY);
48 }
49 return thread;
50 }
51
52 }
1818 import org.apache.logging.log4j.Level;
1919
2020 /**
21 * Default router: enqueue the event for asynchronous logging in the background thread, unless the current thread is the
22 * background thread and the queue is full (enqueueing would cause a deadlock). In that case send the event directly to
21 * Default: any logging done when queue is full bypasses the queue and logs synchronously: send the event directly to
2322 * the appender (in the current thread).
2423 */
2524 public class DefaultAsyncQueueFullPolicy implements AsyncQueueFullPolicy {
2625 @Override
2726 public EventRoute getRoute(final long backgroundThreadId, final Level level) {
2827
29 // LOG4J2-471: prevent deadlock when RingBuffer is full and object
30 // being logged calls Logger.log() from its toString() method
31 if (Thread.currentThread().getId() == backgroundThreadId) {
32 return EventRoute.SYNCHRONOUS;
33 }
34 return EventRoute.ENQUEUE;
28 // LOG4J2-1518: prevent deadlock when RingBuffer is full and object being logged calls
29 // Logger.log in application thread
30 // See also LOG4J2-471: prevent deadlock when RingBuffer is full and object
31 // being logged calls Logger.log() from its toString() method in background thread
32 return EventRoute.SYNCHRONOUS;
3533 }
3634 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.async;
17
18 import java.util.concurrent.BlockingQueue;
19
20 import com.conversantmedia.util.concurrent.DisruptorBlockingQueue;
21 import com.conversantmedia.util.concurrent.SpinPolicy;
22 import org.apache.logging.log4j.core.config.Node;
23 import org.apache.logging.log4j.core.config.plugins.Plugin;
24 import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
25 import org.apache.logging.log4j.core.config.plugins.PluginFactory;
26
27 /**
28 * Factory for creating instances of {@link DisruptorBlockingQueue}.
29 *
30 * @since 2.7
31 */
32 @Plugin(name = "DisruptorBlockingQueue", category = Node.CATEGORY, elementType = BlockingQueueFactory.ELEMENT_TYPE)
33 public class DisruptorBlockingQueueFactory<E> implements BlockingQueueFactory<E> {
34
35 private final SpinPolicy spinPolicy;
36
37 private DisruptorBlockingQueueFactory(final SpinPolicy spinPolicy) {
38 this.spinPolicy = spinPolicy;
39 }
40
41 @Override
42 public BlockingQueue<E> create(final int capacity) {
43 return new DisruptorBlockingQueue<>(capacity, spinPolicy);
44 }
45
46 @PluginFactory
47 public static <E> DisruptorBlockingQueueFactory<E> createFactory(
48 @PluginAttribute(value = "SpinPolicy", defaultString = "WAITING") final SpinPolicy spinPolicy
49 ) {
50 return new DisruptorBlockingQueueFactory<>(spinPolicy);
51 }
52 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.async;
17
18 import java.util.Collection;
19 import java.util.concurrent.BlockingQueue;
20 import java.util.concurrent.TimeUnit;
21 import java.util.concurrent.locks.LockSupport;
22
23 import org.apache.logging.log4j.core.config.Node;
24 import org.apache.logging.log4j.core.config.plugins.Plugin;
25 import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
26 import org.apache.logging.log4j.core.config.plugins.PluginFactory;
27 import org.jctools.queues.MpscArrayQueue;
28
29 /**
30 * Factory for creating instances of BlockingQueues backed by JCTools {@link MpscArrayQueue}.
31 *
32 * @since 2.7
33 */
34 @Plugin(name = "JCToolsBlockingQueue", category = Node.CATEGORY, elementType = BlockingQueueFactory.ELEMENT_TYPE)
35 public class JCToolsBlockingQueueFactory<E> implements BlockingQueueFactory<E> {
36
37 private final WaitStrategy waitStrategy;
38
39 private JCToolsBlockingQueueFactory(final WaitStrategy waitStrategy) {
40 this.waitStrategy = waitStrategy;
41 }
42
43 @Override
44 public BlockingQueue<E> create(final int capacity) {
45 return new MpscBlockingQueue<>(capacity, waitStrategy);
46 }
47
48 @PluginFactory
49 public static <E> JCToolsBlockingQueueFactory<E> createFactory(
50 @PluginAttribute(value = "WaitStrategy", defaultString = "PARK") final WaitStrategy waitStrategy) {
51 return new JCToolsBlockingQueueFactory<>(waitStrategy);
52 }
53
54 /**
55 * BlockingQueue wrapper for JCTools multiple producer single consumer array queue.
56 */
57 private static final class MpscBlockingQueue<E> extends MpscArrayQueue<E> implements BlockingQueue<E> {
58
59 private final JCToolsBlockingQueueFactory.WaitStrategy waitStrategy;
60
61 MpscBlockingQueue(final int capacity, final JCToolsBlockingQueueFactory.WaitStrategy waitStrategy) {
62 super(capacity);
63 this.waitStrategy = waitStrategy;
64 }
65
66 @Override
67 public int drainTo(final Collection<? super E> c) {
68 return drainTo(c, capacity());
69 }
70
71 @Override
72 public int drainTo(final Collection<? super E> c, final int maxElements) {
73 return drain(new Consumer<E>() {
74 @Override
75 public void accept(final E e) {
76 c.add(e);
77 }
78 }, maxElements);
79 }
80
81 @Override
82 public boolean offer(final E e, final long timeout, final TimeUnit unit) throws InterruptedException {
83 int idleCounter = 0;
84 final long timeoutNanos = System.nanoTime() + unit.toNanos(timeout);
85 do {
86 if (offer(e)) {
87 return true;
88 } else if (System.nanoTime() - timeoutNanos > 0) {
89 return false;
90 }
91 idleCounter = waitStrategy.idle(idleCounter);
92 } while (!Thread.interrupted()); //clear interrupted flag
93 throw new InterruptedException();
94 }
95
96 @Override
97 public E poll(final long timeout, final TimeUnit unit) throws InterruptedException {
98 int idleCounter = 0;
99 final long timeoutNanos = System.nanoTime() + unit.toNanos(timeout);
100 do {
101 final E result = poll();
102 if (result != null) {
103 return result;
104 } else if (System.nanoTime() - timeoutNanos > 0) {
105 return null;
106 }
107 idleCounter = waitStrategy.idle(idleCounter);
108 } while (!Thread.interrupted()); //clear interrupted flag
109 throw new InterruptedException();
110 }
111
112 @Override
113 public void put(final E e) throws InterruptedException {
114 int idleCounter = 0;
115 do {
116 if (offer(e)) {
117 return;
118 }
119 idleCounter = waitStrategy.idle(idleCounter);
120 } while (!Thread.interrupted()); //clear interrupted flag
121 throw new InterruptedException();
122 }
123
124 @Override
125 public boolean offer(final E e) {
126 //keep 2 cache lines empty to avoid false sharing that will slow the consumer thread when queue is full.
127 return offerIfBelowThreshold(e, capacity() - 32);
128 }
129
130 @Override
131 public int remainingCapacity() {
132 return capacity() - size();
133 }
134
135 @Override
136 public E take() throws InterruptedException {
137 int idleCounter = 100;
138 do {
139 final E result = relaxedPoll();
140 if (result != null) {
141 return result;
142 }
143 idleCounter = waitStrategy.idle(idleCounter);
144 } while (!Thread.interrupted()); //clear interrupted flag
145 throw new InterruptedException();
146 }
147 }
148
149 public enum WaitStrategy {
150 SPIN(new Idle() {
151 @Override
152 public int idle(final int idleCounter) {
153 return idleCounter + 1;
154 }
155 }),
156 YIELD(new Idle() {
157 @Override
158 public int idle(final int idleCounter) {
159 Thread.yield();
160 return idleCounter + 1;
161 }
162 }),
163 PARK(new Idle() {
164 @Override
165 public int idle(final int idleCounter) {
166 LockSupport.parkNanos(1L);
167 return idleCounter + 1;
168 }
169 }),
170 PROGRESSIVE(new Idle() {
171 @Override
172 public int idle(final int idleCounter) {
173 if (idleCounter > 200) {
174 LockSupport.parkNanos(1L);
175 } else if (idleCounter > 100) {
176 Thread.yield();
177 }
178 return idleCounter + 1;
179 }
180 });
181
182 private final Idle idle;
183
184 private int idle(final int idleCounter) {
185 return idle.idle(idleCounter);
186 }
187
188 WaitStrategy(final Idle idle) {
189 this.idle = idle;
190 }
191 }
192
193 private interface Idle {
194 int idle(int idleCounter);
195 }
196
197 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16
17 package org.apache.logging.log4j.core.async;
18
19 import java.util.concurrent.BlockingQueue;
20 import java.util.concurrent.LinkedTransferQueue;
21
22 import org.apache.logging.log4j.core.config.Node;
23 import org.apache.logging.log4j.core.config.plugins.Plugin;
24 import org.apache.logging.log4j.core.config.plugins.PluginFactory;
25
26 /**
27 * Factory for creating instances of {@link LinkedTransferQueue}.
28 *
29 * @since 2.7
30 */
31 @Plugin(name = "LinkedTransferQueue", category = Node.CATEGORY, elementType = BlockingQueueFactory.ELEMENT_TYPE)
32 public class LinkedTransferQueueFactory<E> implements BlockingQueueFactory<E> {
33 @Override
34 public BlockingQueue<E> create(final int capacity) {
35 return new LinkedTransferQueue<>();
36 }
37
38 @PluginFactory
39 public static <E> LinkedTransferQueueFactory<E> createFactory() {
40 return new LinkedTransferQueueFactory<>();
41 }
42 }
1717
1818 import java.io.IOException;
1919 import java.util.Arrays;
20 import java.util.HashMap;
2120 import java.util.Map;
2221
2322 import org.apache.logging.log4j.Level;
2423 import org.apache.logging.log4j.Marker;
2524 import org.apache.logging.log4j.ThreadContext.ContextStack;
25 import org.apache.logging.log4j.util.ReadOnlyStringMap;
2626 import org.apache.logging.log4j.core.LogEvent;
27 import org.apache.logging.log4j.core.config.Property;
27 import org.apache.logging.log4j.core.impl.ContextDataFactory;
2828 import org.apache.logging.log4j.core.impl.Log4jLogEvent;
29 import org.apache.logging.log4j.util.StringMap;
2930 import org.apache.logging.log4j.core.impl.ThrowableProxy;
30 import org.apache.logging.log4j.core.lookup.StrSubstitutor;
3131 import org.apache.logging.log4j.core.util.Constants;
3232 import org.apache.logging.log4j.message.Message;
3333 import org.apache.logging.log4j.message.ParameterizedMessage;
8181 private Object[] parameters;
8282 private transient Throwable thrown;
8383 private ThrowableProxy thrownProxy;
84 private Map<String, String> contextMap;
84 private StringMap contextData = ContextDataFactory.createContextData();
8585 private Marker marker;
8686 private String fqcn;
8787 private StackTraceElement location;
9191
9292 public void setValues(final AsyncLogger anAsyncLogger, final String aLoggerName, final Marker aMarker,
9393 final String theFqcn, final Level aLevel, final Message msg, final Throwable aThrowable,
94 final Map<String, String> aMap, final ContextStack aContextStack, final long threadId,
95 final String threadName, final int threadPriority, final StackTraceElement aLocation, final long aCurrentTimeMillis, final long aNanoTime) {
94 final StringMap mutableContextData, final ContextStack aContextStack, final long threadId,
95 final String threadName, final int threadPriority, final StackTraceElement aLocation,
96 final long aCurrentTimeMillis, final long aNanoTime) {
9697 this.threadPriority = threadPriority;
9798 this.threadId = threadId;
9899 this.currentTimeMillis = aCurrentTimeMillis;
103104 setMessage(msg);
104105 this.thrown = aThrowable;
105106 this.thrownProxy = null;
106 this.contextMap = aMap;
107107 this.marker = aMarker;
108108 this.fqcn = theFqcn;
109109 this.location = aLocation;
110 this.contextData = mutableContextData;
110111 this.contextStack = aContextStack;
111112 this.asyncLogger = anAsyncLogger;
112113 }
199200 @Override
200201 public Message getMessage() {
201202 if (message == null) {
202 return (messageText == null) ? EMPTY : this;
203 return messageText == null ? EMPTY : this;
203204 }
204205 return message;
205206 }
209210 */
210211 @Override
211212 public String getFormattedMessage() {
212 return messageText.toString();
213 return messageText != null // LOG4J2-1527: may be null in web apps
214 ? messageText.toString() // note: please keep below "redundant" braces for readability
215 : (message == null ? null : message.getFormattedMessage());
213216 }
214217
215218 /**
318321 return this.thrownProxy;
319322 }
320323
324 @SuppressWarnings("unchecked")
325 @Override
326 public ReadOnlyStringMap getContextData() {
327 return contextData;
328 }
329
330 void setContextData(final StringMap contextData) {
331 this.contextData = contextData;
332 }
333
334 @SuppressWarnings("unchecked")
321335 @Override
322336 public Map<String, String> getContextMap() {
323 return contextMap;
337 return contextData.toMap();
324338 }
325339
326340 @Override
356370 @Override
357371 public long getNanoTime() {
358372 return nanoTime;
359 }
360
361 /**
362 * Merges the contents of the specified map into the contextMap, after replacing any variables in the property
363 * values with the StrSubstitutor-supplied actual values.
364 *
365 * @param properties configured properties
366 * @param strSubstitutor used to lookup values of variables in properties
367 */
368 public void mergePropertiesIntoContextMap(final Map<Property, Boolean> properties,
369 final StrSubstitutor strSubstitutor) {
370 if (properties == null) {
371 return; // nothing to do
372 }
373
374 final Map<String, String> map = contextMap == null ? new HashMap<String, String>()
375 : new HashMap<>(contextMap);
376
377 for (final Map.Entry<Property, Boolean> entry : properties.entrySet()) {
378 final Property prop = entry.getKey();
379 if (map.containsKey(prop.getName())) {
380 continue; // contextMap overrides config properties
381 }
382 final String value = entry.getValue().booleanValue() ? strSubstitutor.replace(prop.getValue()) : prop
383 .getValue();
384 map.put(prop.getName(), value);
385 }
386 contextMap = map;
387373 }
388374
389375 /**
398384 this.message = null;
399385 this.thrown = null;
400386 this.thrownProxy = null;
401 this.contextMap = null;
402387 this.contextStack = null;
403388 this.location = null;
389 if (contextData != null) {
390 if (contextData.isFrozen()) { // came from CopyOnWrite thread context
391 contextData = null;
392 } else {
393 contextData.clear();
394 }
395 }
404396
405397 trimMessageText();
406398
439431 * @param builder the builder whose fields to populate
440432 */
441433 public void initializeBuilder(final Log4jLogEvent.Builder builder) {
442 builder.setContextMap(contextMap) //
434 builder.setContextData(contextData) //
443435 .setContextStack(contextStack) //
444436 .setEndOfBatch(endOfBatch) //
445437 .setIncludeLocation(includeLocation) //
1515 */
1616 package org.apache.logging.log4j.core.async;
1717
18 import java.util.Map;
19
2018 import org.apache.logging.log4j.Level;
2119 import org.apache.logging.log4j.Marker;
2220 import org.apache.logging.log4j.ThreadContext.ContextStack;
21 import org.apache.logging.log4j.core.ContextDataInjector;
22 import org.apache.logging.log4j.core.impl.ContextDataInjectorFactory;
23 import org.apache.logging.log4j.util.StringMap;
2324 import org.apache.logging.log4j.message.Message;
2425
2526 import com.lmax.disruptor.EventTranslator;
3334 public class RingBufferLogEventTranslator implements
3435 EventTranslator<RingBufferLogEvent> {
3536
37 private final ContextDataInjector injector = ContextDataInjectorFactory.createInjector();
3638 private AsyncLogger asyncLogger;
3739 private String loggerName;
3840 protected Marker marker;
4042 protected Level level;
4143 protected Message message;
4244 protected Throwable thrown;
43 private Map<String, String> contextMap;
4445 private ContextStack contextStack;
4546 private long threadId = Thread.currentThread().getId();
4647 private String threadName = Thread.currentThread().getName();
5253 // @Override
5354 @Override
5455 public void translateTo(final RingBufferLogEvent event, final long sequence) {
55 event.setValues(asyncLogger, loggerName, marker, fqcn, level, message, thrown, contextMap, contextStack,
56
57 event.setValues(asyncLogger, loggerName, marker, fqcn, level, message, thrown,
58 // config properties are taken care of in the EventHandler thread
59 // in the AsyncLogger#actualAsyncLog method
60 injector.injectContextData(null, (StringMap) event.getContextData()), contextStack,
5661 threadId, threadName, threadPriority, location, currentTimeMillis, nanoTime);
57 clear();
62
63 clear(); // clear the translator
5864 }
5965
6066 /**
6874 null, // level
6975 null, // data
7076 null, // t
71 null, // map
7277 null, // contextStack
7378 null, // location
7479 0, // currentTimeMillis
7883
7984 public void setBasicValues(final AsyncLogger anAsyncLogger, final String aLoggerName, final Marker aMarker,
8085 final String theFqcn, final Level aLevel, final Message msg, final Throwable aThrowable,
81 final Map<String, String> aMap, final ContextStack aContextStack, final StackTraceElement aLocation,
86 final ContextStack aContextStack, final StackTraceElement aLocation,
8287 final long aCurrentTimeMillis, final long aNanoTime) {
8388 this.asyncLogger = anAsyncLogger;
8489 this.loggerName = aLoggerName;
8792 this.level = aLevel;
8893 this.message = msg;
8994 this.thrown = aThrowable;
90 this.contextMap = aMap;
9195 this.contextStack = aContextStack;
9296 this.location = aLocation;
9397 this.currentTimeMillis = aCurrentTimeMillis;
1919 import java.io.IOException;
2020 import java.io.InputStream;
2121 import java.io.Serializable;
22 import java.lang.ref.WeakReference;
2223 import java.util.ArrayList;
2324 import java.util.Arrays;
2425 import java.util.Collection;
3233 import java.util.concurrent.ConcurrentHashMap;
3334 import java.util.concurrent.ConcurrentMap;
3435 import java.util.concurrent.CopyOnWriteArrayList;
36 import java.util.concurrent.TimeUnit;
3537
3638 import org.apache.logging.log4j.Level;
3739 import org.apache.logging.log4j.core.Appender;
3840 import org.apache.logging.log4j.core.Filter;
3941 import org.apache.logging.log4j.core.Layout;
42 import org.apache.logging.log4j.core.LifeCycle2;
4043 import org.apache.logging.log4j.core.LogEvent;
44 import org.apache.logging.log4j.core.LoggerContext;
4145 import org.apache.logging.log4j.core.appender.AsyncAppender;
4246 import org.apache.logging.log4j.core.appender.ConsoleAppender;
4347 import org.apache.logging.log4j.core.async.AsyncLoggerConfig;
121125 private final WatchManager watchManager = new WatchManager(configurationScheduler);
122126 private AsyncLoggerConfigDisruptor asyncLoggerConfigDisruptor;
123127 private NanoClock nanoClock = new DummyNanoClock();
128 private final WeakReference<LoggerContext> loggerContext;
124129
125130 /**
126131 * Constructor.
127132 */
128 protected AbstractConfiguration(final ConfigurationSource configurationSource) {
133 protected AbstractConfiguration(final LoggerContext loggerContext, final ConfigurationSource configurationSource) {
134 this.loggerContext = new WeakReference<>(loggerContext);
135 // The loggerContext is null for the NullConfiguration class.
136 // this.loggerContext = new WeakReference(Objects.requireNonNull(loggerContext, "loggerContext is null"));
129137 this.configurationSource = Objects.requireNonNull(configurationSource, "configurationSource is null");
130138 componentMap.put(Configuration.CONTEXT_PROPERTIES, properties);
131139 pluginManager = new PluginManager(Node.CATEGORY);
181189 }
182190
183191 @Override
184 public AsyncLoggerConfigDelegate getAsyncLoggerConfigDelegate() {
185 // lazily instantiate only when requested by AsyncLoggers:
186 // loading AsyncLoggerConfigDisruptor requires LMAX Disruptor jar on classpath
187 if (asyncLoggerConfigDisruptor == null) {
188 asyncLoggerConfigDisruptor = new AsyncLoggerConfigDisruptor();
189 }
190 return asyncLoggerConfigDisruptor;
191 }
192 public AsyncLoggerConfigDelegate getAsyncLoggerConfigDelegate() {
193 // lazily instantiate only when requested by AsyncLoggers:
194 // loading AsyncLoggerConfigDisruptor requires LMAX Disruptor jar on classpath
195 if (asyncLoggerConfigDisruptor == null) {
196 asyncLoggerConfigDisruptor = new AsyncLoggerConfigDisruptor();
197 }
198 return asyncLoggerConfigDisruptor;
199 }
192200
193201 /**
194202 * Initialize the configuration.
197205 public void initialize() {
198206 LOGGER.debug("Initializing configuration {}", this);
199207 subst.setConfiguration(this);
200 scriptManager = new ScriptManager(watchManager);
208 scriptManager = new ScriptManager(this, watchManager);
201209 pluginManager.collectPlugins(pluginPackages);
202210 final PluginManager levelPlugins = new PluginManager(Level.CATEGORY);
203211 levelPlugins.collectPlugins(pluginPackages);
235243 watchManager.start();
236244 }
237245 if (hasAsyncLoggers()) {
238 asyncLoggerConfigDisruptor.start();
246 asyncLoggerConfigDisruptor.start();
239247 }
240248 final Set<LoggerConfig> alreadyStarted = new HashSet<>();
241249 for (final LoggerConfig logger : loggerConfigs.values()) {
258266 }
259267 for (final LoggerConfig logger : loggerConfigs.values()) {
260268 if (logger instanceof AsyncLoggerConfig) {
261 return true;
262 }
263 }
264 return false;
265 }
266
267 /**
269 return true;
270 }
271 }
272 return false;
273 }
274
275 /**
268276 * Tear down the configuration.
269277 */
270278 @Override
271 public void stop() {
279 public boolean stop(final long timeout, final TimeUnit timeUnit) {
272280 this.setStopping();
281 super.stop(timeout, timeUnit, false);
273282 LOGGER.trace("Stopping {}...", this);
274283
275284 // Stop the components that are closest to the application first:
297306 if (!loggerConfigs.isEmpty()) {
298307 LOGGER.trace("{} stopping {} LoggerConfigs.", cls, loggerConfigs.size());
299308 for (final LoggerConfig logger : loggerConfigs.values()) {
300 logger.stop();
309 logger.stop(timeout, timeUnit);
301310 }
302311 }
303312 LOGGER.trace("{} stopping root LoggerConfig.", cls);
304313 if (!root.isStopped()) {
305 root.stop();
314 root.stop(timeout, timeUnit);
306315 }
307316
308317 if (hasAsyncLoggers()) {
309318 LOGGER.trace("{} stopping AsyncLoggerConfigDisruptor.", cls);
310 asyncLoggerConfigDisruptor.stop();
319 asyncLoggerConfigDisruptor.stop(timeout, timeUnit);
311320 }
312321
313322 // Stop the appenders in reverse order in case they still have activity.
317326 // LOG4J2-511, LOG4J2-392 stop AsyncAppenders first
318327 LOGGER.trace("{} stopping {} AsyncAppenders.", cls, async.size());
319328 for (final Appender appender : async) {
320 appender.stop();
329 if (appender instanceof LifeCycle2) {
330 ((LifeCycle2) appender).stop(timeout, timeUnit);
331 } else {
332 appender.stop();
333 }
321334 }
322335 }
323336
331344 int appenderCount = 0;
332345 for (int i = array.length - 1; i >= 0; --i) {
333346 if (array[i].isStarted()) { // then stop remaining Appenders
334 array[i].stop();
347 if (array[i] instanceof LifeCycle2) {
348 ((LifeCycle2) array[i]).stop(timeout, timeUnit);
349 } else {
350 array[i].stop();
351 }
335352 appenderCount++;
336353 }
337354 }
354371 }
355372 configurationScheduler.stop();
356373
357 super.stop();
358374 if (advertiser != null && advertisement != null) {
359375 advertiser.unadvertise(advertisement);
360376 }
377 setStopped();
361378 LOGGER.debug("Stopped {} OK", this);
379 return true;
362380 }
363381
364382 private List<Appender> getAsyncAppenders(final Appender[] all) {
377395 }
378396
379397 public void setup() {
398 // default does nothing, subclasses do work.
380399 }
381400
382401 protected Level getDefaultStatus() {
783802 }
784803 }
785804 return root;
805 }
806
807 @Override
808 public LoggerContext getLoggerContext() {
809 return loggerContext.get();
786810 }
787811
788812 /**
8989
9090 @PerformanceSensitive
9191 private boolean isFilteredByAppenderControl(final LogEvent event) {
92 return getFilter() != null && Filter.Result.DENY == getFilter().filter(event);
92 final Filter filter = getFilter();
93 return filter != null && Filter.Result.DENY == filter.filter(event);
9394 }
9495
9596 @PerformanceSensitive
3333 }
3434
3535 /**
36 * Create a Map of the Appenders.
36 * Creates a Map of the Appenders.
3737 * @param appenders An array of Appenders.
3838 * @return The Appender Map.
3939 */
4141 public static ConcurrentMap<String, Appender> createAppenders(
4242 @PluginElement("Appenders") final Appender[] appenders) {
4343
44 final ConcurrentMap<String, Appender> map = new ConcurrentHashMap<>();
44 final ConcurrentMap<String, Appender> map = new ConcurrentHashMap<>(appenders.length);
4545
4646 for (final Appender appender : appenders) {
4747 map.put(appender.getName(), appender);
2323 import org.apache.logging.log4j.core.Filter;
2424 import org.apache.logging.log4j.core.LogEvent;
2525 import org.apache.logging.log4j.core.Logger;
26 import org.apache.logging.log4j.core.LoggerContext;
2627 import org.apache.logging.log4j.core.async.AsyncLoggerConfigDelegate;
2728 import org.apache.logging.log4j.core.filter.Filterable;
2829 import org.apache.logging.log4j.core.lookup.StrSubstitutor;
3334
3435 /**
3536 * Interface that must be implemented to create a configuration.
37 * <p>
38 * Custom implementations are recommended to extend {@link AbstractConfiguration}.
39 * </p>
40 *
41 * @see AbstractConfiguration
42 * @see org.apache.logging.log4j.core.LifeCycle2
3643 */
3744 public interface Configuration extends Filterable {
3845
187194 * @param nanoClock the new nano clock for this configuration. Must be non-null.
188195 */
189196 void setNanoClock(NanoClock nanoClock);
197
198 /**
199 * Gets the logger context.
200 *
201 * @return the logger context.
202 */
203 LoggerContext getLoggerContext();
190204 }
2424 private static final long serialVersionUID = -2413951820300775294L;
2525
2626 /**
27 * Construct an exception with a message.
27 * Constructs an exception with a message.
2828 *
2929 * @param message The reason for the exception
3030 */
3333 }
3434
3535 /**
36 * Construct an exception with a message and underlying cause.
36 * Constructs an exception with a message and underlying cause.
3737 *
3838 * @param message The reason for the exception
3939 * @param cause The underlying cause of the exception
4141 public ConfigurationException(final String message, final Throwable cause) {
4242 super(message, cause);
4343 }
44
45 /**
46 * Constructs an exception with a message and underlying cause.
47 *
48 * @param cause The underlying cause of the exception
49 */
50 public ConfigurationException(final Throwable cause) {
51 super(cause);
52 }
53
4454 }
3434
3535 import org.apache.logging.log4j.Level;
3636 import org.apache.logging.log4j.Logger;
37 import org.apache.logging.log4j.core.LoggerContext;
3738 import org.apache.logging.log4j.core.config.builder.api.ConfigurationBuilderFactory;
3839 import org.apache.logging.log4j.core.config.composite.CompositeConfiguration;
3940 import org.apache.logging.log4j.core.config.plugins.util.PluginManager;
7374 * last if no configuration has been returned.
7475 */
7576 public abstract class ConfigurationFactory extends ConfigurationBuilderFactory {
76 /**
77 * Allow the ConfigurationFactory class to be specified as a system property.
77
78 public ConfigurationFactory() {
79 super();
80 // TEMP For breakpoints
81 }
82
83 /**
84 * Allows the ConfigurationFactory class to be specified as a system property.
7885 */
7986 public static final String CONFIGURATION_FACTORY_PROPERTY = "log4j.configurationFactory";
8087
8188 /**
82 * Allow the location of the configuration file to be specified as a system property.
89 * Allows the location of the configuration file to be specified as a system property.
8390 */
8491 public static final String CONFIGURATION_FILE_PROPERTY = "log4j.configurationFile";
8592
9299 public static final String CATEGORY = "ConfigurationFactory";
93100
94101 /**
95 * Allow subclasses access to the status logger without creating another instance.
102 * Allows subclasses access to the status logger without creating another instance.
96103 */
97104 protected static final Logger LOGGER = StatusLogger.getLogger();
98105
186193 }
187194
188195 /**
189 * Set the configuration factory. This method is not intended for general use and may not be thread safe.
196 * Sets the configuration factory. This method is not intended for general use and may not be thread safe.
190197 * @param factory the ConfigurationFactory.
191198 */
192199 public static void setConfigurationFactory(final ConfigurationFactory factory) {
194201 }
195202
196203 /**
197 * Reset the ConfigurationFactory to the default. This method is not intended for general use and may
204 * Resets the ConfigurationFactory to the default. This method is not intended for general use and may
198205 * not be thread safe.
199206 */
200207 public static void resetConfigurationFactory() {
202209 }
203210
204211 /**
205 * Remove the ConfigurationFactory. This method is not intended for general use and may not be thread safe.
212 * Removes the ConfigurationFactory. This method is not intended for general use and may not be thread safe.
206213 * @param factory The factory to remove.
207214 */
208215 public static void removeConfigurationFactory(final ConfigurationFactory factory) {
217224 return true;
218225 }
219226
220 public abstract Configuration getConfiguration(ConfigurationSource source);
227 public abstract Configuration getConfiguration(final LoggerContext loggerContext, ConfigurationSource source);
221228
222229 /**
223230 * Returns the Configuration.
231 * @param loggerContext The logger context
224232 * @param name The configuration name.
225233 * @param configLocation The configuration location.
226234 * @return The Configuration.
227235 */
228 public Configuration getConfiguration(final String name, final URI configLocation) {
236 public Configuration getConfiguration(final LoggerContext loggerContext, final String name, final URI configLocation) {
229237 if (!isActive()) {
230238 return null;
231239 }
232240 if (configLocation != null) {
233241 final ConfigurationSource source = getInputFromUri(configLocation);
234242 if (source != null) {
235 return getConfiguration(source);
243 return getConfiguration(loggerContext, source);
236244 }
237245 }
238246 return null;
240248
241249 /**
242250 * Returns the Configuration obtained using a given ClassLoader.
243 *
251 * @param loggerContext The logger context
244252 * @param name The configuration name.
245253 * @param configLocation A URI representing the location of the configuration.
246254 * @param loader The default ClassLoader to use. If this is {@code null}, then the
247255 * {@linkplain LoaderUtil#getThreadContextClassLoader() default ClassLoader} will be used.
256 *
248257 * @return The Configuration.
249 * @since 2.1
250 */
251 public Configuration getConfiguration(final String name, final URI configLocation, final ClassLoader loader) {
258 */
259 public Configuration getConfiguration(final LoggerContext loggerContext, final String name, final URI configLocation, final ClassLoader loader) {
252260 if (!isActive()) {
253261 return null;
254262 }
255263 if (loader == null) {
256 return getConfiguration(name, configLocation);
264 return getConfiguration(loggerContext, name, configLocation);
257265 }
258266 if (isClassLoaderUri(configLocation)) {
259267 final String path = extractClassLoaderUriPath(configLocation);
260268 final ConfigurationSource source = getInputFromResource(path, loader);
261269 if (source != null) {
262 final Configuration configuration = getConfiguration(source);
270 final Configuration configuration = getConfiguration(loggerContext, source);
263271 if (configuration != null) {
264272 return configuration;
265273 }
266274 }
267275 }
268 return getConfiguration(name, configLocation);
269 }
270
271 /**
272 * Load the configuration from a URI.
276 return getConfiguration(loggerContext, name, configLocation);
277 }
278
279 /**
280 * Loads the configuration from a URI.
273281 * @param configLocation A URI representing the location of the configuration.
274282 * @return The ConfigurationSource for the configuration.
275283 */
317325 }
318326
319327 /**
320 * Load the configuration from the location represented by the String.
328 * Loads the configuration from the location represented by the String.
321329 * @param config The configuration location.
322330 * @param loader The default ClassLoader to use.
323331 * @return The InputSource to use to read the configuration.
342350 }
343351
344352 /**
345 * Retrieve the configuration via the ClassLoader.
353 * Retrieves the configuration via the ClassLoader.
346354 * @param resource The resource to load.
347355 * @param loader The default ClassLoader to use.
348356 * @return The ConfigurationSource for the configuration.
378386 * Default Factory.
379387 */
380388 private static class Factory extends ConfigurationFactory {
389
390 private static final String ALL_TYPES = "*";
381391
382392 /**
383393 * Default Factory Constructor.
386396 * @return The Configuration.
387397 */
388398 @Override
389 public Configuration getConfiguration(final String name, final URI configLocation) {
399 public Configuration getConfiguration(final LoggerContext loggerContext, final String name, final URI configLocation) {
390400
391401 if (configLocation == null) {
392402 final String configLocationStr = this.substitutor.replace(PropertiesUtil.getProperties()
396406 if (sources.length > 1) {
397407 final List<AbstractConfiguration> configs = new ArrayList<>();
398408 for (final String sourceLocation : sources) {
399 final Configuration config = getConfiguration(sourceLocation.trim());
409 final Configuration config = getConfiguration(loggerContext, sourceLocation.trim());
400410 if (config != null && config instanceof AbstractConfiguration) {
401411 configs.add((AbstractConfiguration) config);
402412 } else {
406416 }
407417 return new CompositeConfiguration(configs);
408418 }
409 return getConfiguration(configLocationStr);
419 return getConfiguration(loggerContext, configLocationStr);
410420 }
411421 for (final ConfigurationFactory factory : getFactories()) {
412422 final String[] types = factory.getSupportedTypes();
413423 if (types != null) {
414424 for (final String type : types) {
415 if (type.equals("*")) {
416 final Configuration config = factory.getConfiguration(name, configLocation);
425 if (type.equals(ALL_TYPES)) {
426 final Configuration config = factory.getConfiguration(loggerContext, name, configLocation);
417427 if (config != null) {
418428 return config;
419429 }
428438 final String[] types = factory.getSupportedTypes();
429439 if (types != null) {
430440 for (final String type : types) {
431 if (type.equals("*") || configLocationStr.endsWith(type)) {
432 final Configuration config = factory.getConfiguration(name, configLocation);
441 if (type.equals(ALL_TYPES) || configLocationStr.endsWith(type)) {
442 final Configuration config = factory.getConfiguration(loggerContext, name, configLocation);
433443 if (config != null) {
434444 return config;
435445 }
439449 }
440450 }
441451
442 Configuration config = getConfiguration(true, name);
452 Configuration config = getConfiguration(loggerContext, true, name);
443453 if (config == null) {
444 config = getConfiguration(true, null);
454 config = getConfiguration(loggerContext, true, null);
445455 if (config == null) {
446 config = getConfiguration(false, name);
456 config = getConfiguration(loggerContext, false, name);
447457 if (config == null) {
448 config = getConfiguration(false, null);
458 config = getConfiguration(loggerContext, false, null);
449459 }
450460 }
451461 }
456466 return new DefaultConfiguration();
457467 }
458468
459 private Configuration getConfiguration(final String configLocationStr) {
469 private Configuration getConfiguration(final LoggerContext loggerContext, final String configLocationStr) {
460470 ConfigurationSource source = null;
461471 try {
462472 source = getInputFromUri(NetUtils.toURI(configLocationStr));
473483 final String[] types = factory.getSupportedTypes();
474484 if (types != null) {
475485 for (final String type : types) {
476 if (type.equals("*") || configLocationStr.endsWith(type)) {
477 final Configuration config = factory.getConfiguration(source);
486 if (type.equals(ALL_TYPES) || configLocationStr.endsWith(type)) {
487 final Configuration config = factory.getConfiguration(loggerContext, source);
478488 if (config != null) {
479489 return config;
480490 }
486496 return null;
487497 }
488498
489 private Configuration getConfiguration(final boolean isTest, final String name) {
499 private Configuration getConfiguration(final LoggerContext loggerContext, final boolean isTest, final String name) {
490500 final boolean named = Strings.isNotEmpty(name);
491501 final ClassLoader loader = LoaderUtil.getThreadContextClassLoader();
492502 for (final ConfigurationFactory factory : getFactories()) {
498508 }
499509
500510 for (final String suffix : types) {
501 if (suffix.equals("*")) {
511 if (suffix.equals(ALL_TYPES)) {
502512 continue;
503513 }
504514 configName = named ? prefix + name + suffix : prefix + suffix;
505515
506516 final ConfigurationSource source = getInputFromResource(configName, loader);
507517 if (source != null) {
508 return factory.getConfiguration(source);
518 return factory.getConfiguration(loggerContext, source);
509519 }
510520 }
511521 }
518528 }
519529
520530 @Override
521 public Configuration getConfiguration(final ConfigurationSource source) {
531 public Configuration getConfiguration(final LoggerContext loggerContext, final ConfigurationSource source) {
522532 if (source != null) {
523533 final String config = source.getLocation();
524534 for (final ConfigurationFactory factory : getFactories()) {
525535 final String[] types = factory.getSupportedTypes();
526536 if (types != null) {
527537 for (final String type : types) {
528 if (type.equals("*") || config != null && config.endsWith(type)) {
529 final Configuration c = factory.getConfiguration(source);
538 if (type.equals(ALL_TYPES) || config != null && config.endsWith(type)) {
539 final Configuration c = factory.getConfiguration(loggerContext, source);
530540 if (c != null) {
531541 LOGGER.debug("Loaded configuration from {}", source);
532542 return c;
1515 */
1616 package org.apache.logging.log4j.core.config;
1717
18 import org.apache.logging.log4j.Logger;
19 import org.apache.logging.log4j.core.AbstractLifeCycle;
20 import org.apache.logging.log4j.core.async.DaemonThreadFactory;
21 import org.apache.logging.log4j.core.util.CronExpression;
22 import org.apache.logging.log4j.status.StatusLogger;
23
2418 import java.util.Date;
2519 import java.util.concurrent.Callable;
2620 import java.util.concurrent.ScheduledExecutorService;
2822 import java.util.concurrent.ScheduledThreadPoolExecutor;
2923 import java.util.concurrent.TimeUnit;
3024
25 import org.apache.logging.log4j.core.AbstractLifeCycle;
26 import org.apache.logging.log4j.core.util.CronExpression;
27 import org.apache.logging.log4j.core.util.Log4jThreadFactory;
28
3129 /**
3230 *
3331 */
3432 public class ConfigurationScheduler extends AbstractLifeCycle {
3533
36 private static final Logger LOGGER = StatusLogger.getLogger();
34 private static final String SIMPLE_NAME = "Log4j2 " + ConfigurationScheduler.class.getSimpleName();
35 private static final int MAX_SCHEDULED_ITEMS = 5;
3736 private ScheduledExecutorService executorService;
3837
3938 private int scheduledItems = 0;
40
4139
4240 @Override
4341 public void start() {
4442 super.start();
4543 if (scheduledItems > 0) {
46 LOGGER.debug("Starting {} Log4j2Scheduled threads", scheduledItems);
47 if (scheduledItems > 5) {
48 scheduledItems = 5;
49 }
50 executorService = new ScheduledThreadPoolExecutor(scheduledItems, new DaemonThreadFactory("Log4j2Scheduled-"));
44 LOGGER.debug("{} starting {} threads", scheduledItems, SIMPLE_NAME);
45 scheduledItems = Math.min(scheduledItems, MAX_SCHEDULED_ITEMS);
46 executorService = new ScheduledThreadPoolExecutor(scheduledItems,
47 Log4jThreadFactory.createDaemonThreadFactory("Scheduled"));
5148 } else {
52 LOGGER.debug("No scheduled items");
49 LOGGER.debug("{}: No scheduled items", SIMPLE_NAME);
5350 }
5451 }
5552
5653 @Override
57 public void stop() {
54 public boolean stop(final long timeout, final TimeUnit timeUnit) {
55 setStopping();
5856 if (executorService != null) {
59 LOGGER.debug("Stopping Log4j2Scheduled threads.");
57 LOGGER.debug("{} shutting down threads in {}", SIMPLE_NAME, executorService);
6058 executorService.shutdown();
6159 }
62 super.stop();
60 setStopped();
61 return true;
6362 }
6463
6564 /**
6968 if (!isStarted()) {
7069 ++scheduledItems;
7170 } else {
72 LOGGER.error("Attempted to increment scheduled items after start");
71 LOGGER.error("{} attempted to increment scheduled items after start", SIMPLE_NAME);
7372 }
7473 }
7574
8483
8584 /**
8685 * Creates and executes a ScheduledFuture that becomes enabled after the given delay.
86 * @param <V> The result type returned by this Future
8787 * @param callable the function to execute.
8888 * @param delay the time from now to delay execution.
8989 * @param unit the time unit of the delay parameter.
114114 * @return a ScheduledFuture representing the next time the command will run.
115115 */
116116 public CronScheduledFuture<?> scheduleWithCron(final CronExpression cronExpression, final Runnable command) {
117 Date fireDate = cronExpression.getNextValidTimeAfter(new Date());
117 final Date fireDate = cronExpression.getNextValidTimeAfter(new Date());
118118 final CronRunnable runnable = new CronRunnable(command, cronExpression);
119119 final ScheduledFuture<?> future = schedule(runnable, nextFireInterval(fireDate), TimeUnit.MILLISECONDS);
120120 final CronScheduledFuture<?> cronScheduledFuture = new CronScheduledFuture<>(future, fireDate);
152152 return executorService.scheduleWithFixedDelay(command, initialDelay, delay, unit);
153153 }
154154
155 public long nextFireInterval(Date fireDate) {
155 public long nextFireInterval(final Date fireDate) {
156156 return fireDate.getTime() - new Date().getTime();
157157 }
158158
171171 this.scheduledFuture = future;
172172 }
173173
174
175
176174 @Override
177175 public void run() {
178176 try {
179177 runnable.run();
180178 } catch(final Throwable ex) {
181 LOGGER.error("Error running command", ex);
179 LOGGER.error("{} caught error running command", SIMPLE_NAME, ex);
182180 } finally {
183 Date fireDate = cronExpression.getNextInvalidTimeAfter(new Date());
181 final Date fireDate = cronExpression.getNextValidTimeAfter(new Date());
184182 final ScheduledFuture<?> future = schedule(this, nextFireInterval(fireDate), TimeUnit.MILLISECONDS);
185183 scheduledFuture.reset(future, fireDate);
186184 }
1515 */
1616 package org.apache.logging.log4j.core.config;
1717
18 import org.apache.logging.log4j.core.util.FileWatcher;
19 import org.apache.logging.log4j.core.util.Log4jThread;
20
2118 import java.io.File;
2219 import java.util.List;
20
21 import org.apache.logging.log4j.core.LoggerContext;
22 import org.apache.logging.log4j.core.util.FileWatcher;
2323
2424 /**
2525 * Watcher for configuration files. Causes a reconfiguration when a file changes.
2727 public class ConfiguratonFileWatcher implements FileWatcher {
2828
2929 private final Reconfigurable reconfigurable;
30 private final List<ConfigurationListener> listeners;
30 private final List<ConfigurationListener> configurationListeners;
3131
32 public ConfiguratonFileWatcher(final Reconfigurable reconfigurable, final List<ConfigurationListener> listeners) {
32 public ConfiguratonFileWatcher(final Reconfigurable reconfigurable, final List<ConfigurationListener> configurationListeners) {
3333 this.reconfigurable = reconfigurable;
34 this.listeners = listeners;
34 this.configurationListeners = configurationListeners;
3535 }
3636
3737 public List<ConfigurationListener> getListeners() {
38 return listeners;
38 return configurationListeners;
3939 }
4040
4141
4242 @Override
4343 public void fileModified(final File file) {
44 for (final ConfigurationListener listener : listeners) {
45 final Thread thread = new Log4jThread(new ReconfigurationWorker(listener, reconfigurable));
46 thread.setDaemon(true);
47 thread.start();
44 for (final ConfigurationListener configurationListener : configurationListeners) {
45 LoggerContext.getContext(false).submitDaemon(new ReconfigurationRunnable(configurationListener, reconfigurable));
4846 }
4947 }
5048
5149 /**
5250 * Helper class for triggering a reconfiguration in a background thread.
5351 */
54 private static class ReconfigurationWorker implements Runnable {
52 private static class ReconfigurationRunnable implements Runnable {
5553
56 private final ConfigurationListener listener;
54 private final ConfigurationListener configurationListener;
5755 private final Reconfigurable reconfigurable;
5856
59 public ReconfigurationWorker(final ConfigurationListener listener, final Reconfigurable reconfigurable) {
60 this.listener = listener;
57 public ReconfigurationRunnable(final ConfigurationListener configurationListener, final Reconfigurable reconfigurable) {
58 this.configurationListener = configurationListener;
6159 this.reconfigurable = reconfigurable;
6260 }
6361
6462 @Override
6563 public void run() {
66 listener.onChange(reconfigurable);
64 configurationListener.onChange(reconfigurable);
6765 }
6866 }
6967 }
1919 import java.util.ArrayList;
2020 import java.util.List;
2121 import java.util.Map;
22 import java.util.concurrent.TimeUnit;
2223
2324 import org.apache.logging.log4j.Level;
2425 import org.apache.logging.log4j.LogManager;
327328 }
328329
329330 /**
330 * Shuts down the given logging context.
331 * @param ctx the logging context to shut down, may be null.
331 * Shuts down the given logger context. This request does not wait for Log4j tasks to complete.
332 * <p>
333 * Log4j starts threads to perform certain actions like file rollovers; calling this method will not wait until the
334 * rollover thread is done. When this method returns, these tasks' status are undefined, the tasks may be done or
335 * not.
336 * </p>
337 *
338 * @param ctx
339 * the logger context to shut down, may be null.
332340 */
333341 public static void shutdown(final LoggerContext ctx) {
334342 if (ctx != null) {
336344 }
337345 }
338346
347 /**
348 * Blocks until all Log4j tasks have completed execution after a shutdown request, or the timeout occurs, or the
349 * current thread is interrupted, whichever happens first.
350 * <p>
351 * Log4j can start threads to perform certain actions like file rollovers, calling this method with a timeout will
352 * block until the rollover thread is done.
353 * </p>
354 *
355 * @param ctx
356 * the logger context to shut down, may be null.
357 * @param timeout
358 * the maximum time to wait
359 * @param timeUnit
360 * the time unit of the timeout argument
361 * @return {@code true} if the logger context terminated and {@code false} if the timeout elapsed before
362 * termination.
363 */
364 public static boolean shutdown(final LoggerContext ctx, final long timeout, final TimeUnit timeUnit) {
365 if (ctx != null) {
366 return ctx.stop(timeout, timeUnit);
367 }
368 return true;
369 }
370
339371 private Configurator() {
340372 // empty
341373 }
8484 private final ScheduledFuture<?> scheduledFuture;
8585 private final Date runDate;
8686
87 FutureData(ScheduledFuture<?> future, Date runDate) {
87 FutureData(final ScheduledFuture<?> future, final Date runDate) {
8888 this.scheduledFuture = future;
8989 this.runDate = runDate;
9090 }
4242 * Constructor to create the default configuration.
4343 */
4444 public DefaultConfiguration() {
45 super(ConfigurationSource.NULL_SOURCE);
45 super(null, ConfigurationSource.NULL_SOURCE);
4646 setToDefault();
4747 }
4848
4343 import org.apache.logging.log4j.core.lookup.StrSubstitutor;
4444 import org.apache.logging.log4j.core.util.Booleans;
4545 import org.apache.logging.log4j.core.util.Constants;
46 import org.apache.logging.log4j.core.util.Loader;
4746 import org.apache.logging.log4j.message.Message;
47 import org.apache.logging.log4j.util.LoaderUtil;
4848 import org.apache.logging.log4j.util.PerformanceSensitive;
4949 import org.apache.logging.log4j.util.PropertiesUtil;
5050 import org.apache.logging.log4j.util.Strings;
6666 private boolean additive = true;
6767 private boolean includeLocation = true;
6868 private LoggerConfig parent;
69 private final Map<Property, Boolean> properties;
69 private Map<Property, Boolean> propertiesMap;
70 private final List<Property> properties;
71 private final boolean propertiesRequireLookup;
7072 private final Configuration config;
7173 private final ReliabilityStrategy reliabilityStrategy;
7274
7476 final String factory = PropertiesUtil.getProperties().getStringProperty(Constants.LOG4J_LOG_EVENT_FACTORY);
7577 if (factory != null) {
7678 try {
77 final Class<?> clazz = Loader.loadClass(factory);
79 final Class<?> clazz = LoaderUtil.loadClass(factory);
7880 if (clazz != null && LogEventFactory.class.isAssignableFrom(clazz)) {
7981 LOG_EVENT_FACTORY = (LogEventFactory) clazz.newInstance();
8082 }
9799 this.level = Level.ERROR;
98100 this.name = Strings.EMPTY;
99101 this.properties = null;
102 this.propertiesRequireLookup = false;
100103 this.config = null;
101104 this.reliabilityStrategy = new DefaultReliabilityStrategy(this);
102105 }
114117 this.level = level;
115118 this.additive = additive;
116119 this.properties = null;
120 this.propertiesRequireLookup = false;
117121 this.config = null;
118122 this.reliabilityStrategy = new DefaultReliabilityStrategy(this);
119123 }
130134 this.includeLocation = includeLocation;
131135 this.config = config;
132136 if (properties != null && properties.length > 0) {
133 final Map<Property, Boolean> map = new HashMap<>(properties.length);
134 for (final Property prop : properties) {
135 final boolean interpolate = prop.getValue().contains("${");
136 map.put(prop, interpolate);
137 }
138 this.properties = Collections.unmodifiableMap(map);
137 this.properties = Collections.unmodifiableList(Arrays.asList(Arrays.copyOf(
138 properties, properties.length)));
139139 } else {
140140 this.properties = null;
141141 }
142 this.propertiesRequireLookup = containsPropertyRequiringLookup(properties);
142143 this.reliabilityStrategy = config.getReliabilityStrategy(this);
144 }
145
146 private static boolean containsPropertyRequiringLookup(final Property[] properties) {
147 if (properties == null) {
148 return false;
149 }
150 for (int i = 0; i < properties.length; i++) {
151 if (properties[i].isValueNeedsLookup()) {
152 return true;
153 }
154 }
155 return false;
143156 }
144157
145158 @Override
309322 * @return an unmodifiable map with the configuration properties, or {@code null}
310323 * @see Configuration#getStrSubstitutor()
311324 * @see StrSubstitutor
325 * @deprecated use {@link #getPropertyList()} instead
312326 */
313327 // LOG4J2-157
328 @Deprecated
314329 public Map<Property, Boolean> getProperties() {
330 if (properties == null) {
331 return null;
332 }
333 if (propertiesMap == null) { // lazily initialize: only used by user custom code, not by Log4j any more
334 final Map<Property, Boolean> result = new HashMap<>(properties.size() * 2);
335 for (int i = 0; i < properties.size(); i++) {
336 result.put(properties.get(i), Boolean.valueOf(properties.get(i).isValueNeedsLookup()));
337 }
338 propertiesMap = Collections.unmodifiableMap(result);
339 }
340 return propertiesMap;
341 }
342
343 /**
344 * Returns an unmodifiable list with the configuration properties, or {@code null} if this {@code LoggerConfig} does
345 * not have any configuration properties.
346 * <p>
347 * Each {@code Property} in the list has an attribute {@link Property#isValueNeedsLookup() valueNeedsLookup} that
348 * is {@code true} if the property value has a variable that needs to be substituted.
349 *
350 * @return an unmodifiable list with the configuration properties, or {@code null}
351 * @see Configuration#getStrSubstitutor()
352 * @see StrSubstitutor
353 * @since 2.7
354 */
355 public List<Property> getPropertyList() {
315356 return properties;
357 }
358
359 public boolean isPropertiesRequireLookup() {
360 return propertiesRequireLookup;
316361 }
317362
318363 /**
325370 * @param data The Message.
326371 * @param t A Throwable or null.
327372 */
373 @PerformanceSensitive("allocation")
328374 public void log(final String loggerName, final String fqcn, final Marker marker, final Level level,
329375 final Message data, final Throwable t) {
330376 List<Property> props = null;
331 if (properties != null) {
332 props = new ArrayList<>(properties.size());
333 final LogEvent event = Log4jLogEvent.newBuilder()
334 .setMessage(data)
335 .setMarker(marker)
336 .setLevel(level)
337 .setLoggerName(loggerName)
338 .setLoggerFqcn(fqcn)
339 .setThrown(t)
340 .build();
341 for (final Map.Entry<Property, Boolean> entry : properties.entrySet()) {
342 final Property prop = entry.getKey();
343 final String value = entry.getValue() ? config.getStrSubstitutor().replace(event, prop.getValue())
344 : prop.getValue();
345 props.add(Property.createProperty(prop.getName(), value));
377 if (!propertiesRequireLookup) {
378 props = properties;
379 } else {
380 if (properties != null) {
381 props = new ArrayList<>(properties.size());
382 final LogEvent event = Log4jLogEvent.newBuilder()
383 .setMessage(data)
384 .setMarker(marker)
385 .setLevel(level)
386 .setLoggerName(loggerName)
387 .setLoggerFqcn(fqcn)
388 .setThrown(t)
389 .build();
390 for (int i = 0; i < properties.size(); i++) {
391 final Property prop = properties.get(i);
392 final String value = prop.isValueNeedsLookup() // since LOG4J2-1575
393 ? config.getStrSubstitutor().replace(event, prop.getValue()) //
394 : prop.getValue();
395 props.add(Property.createProperty(prop.getName(), value));
396 }
346397 }
347398 }
348 log(logEventFactory.createEvent(loggerName, marker, fqcn, level, data, props, t));
399 final LogEvent logEvent = logEventFactory.createEvent(loggerName, marker, fqcn, level, data, props, t);
400 try {
401 log(logEvent);
402 } finally {
403 // LOG4J2-1583 prevent scrambled logs when logging calls are nested (logging in toString())
404 ReusableLogEventFactory.release(logEvent);
405 }
349406 }
350407
351408 /**
407464 * @param config The Configuration.
408465 * @param filter A Filter.
409466 * @return A new LoggerConfig.
410 * @deprecated Use {@link #createLogger(boolean, Level, String, String, AppenderRef[], Property[], Configuration, Filter)}
467 * @deprecated Deprecated in 2.7; use {@link #createLogger(boolean, Level, String, String, AppenderRef[], Property[], Configuration, Filter)}
411468 */
412469 @Deprecated
413 public static LoggerConfig createLogger(@PluginAttribute("additivity") final String additivity,
414 @PluginAttribute("level") final Level level, @PluginAttribute("name") final String loggerName,
415 @PluginAttribute("includeLocation") final String includeLocation,
416 @PluginElement("AppenderRef") final AppenderRef[] refs,
417 @PluginElement("Properties") final Property[] properties, @PluginConfiguration final Configuration config,
418 @PluginElement("Filter") final Filter filter) {
470 public static LoggerConfig createLogger(final String additivity,
471 // @formatter:off
472 final Level level,
473 @PluginAttribute("name") final String loggerName,
474 final String includeLocation,
475 final AppenderRef[] refs,
476 final Property[] properties,
477 @PluginConfiguration final Configuration config,
478 final Filter filter) {
479 // @formatter:on
419480 if (loggerName == null) {
420481 LOGGER.error("Loggers cannot be configured without a name");
421482 return null;
432493 /**
433494 * Factory method to create a LoggerConfig.
434495 *
435 * @param additivity True if additive, false otherwise.
496 * @param additivity true if additive, false otherwise.
436497 * @param level The Level to be associated with the Logger.
437498 * @param loggerName The name of the Logger.
438499 * @param includeLocation whether location should be passed downstream
445506 */
446507 @PluginFactory
447508 public static LoggerConfig createLogger(
509 // @formatter:off
448510 @PluginAttribute(value = "additivity", defaultBoolean = true) final boolean additivity,
449511 @PluginAttribute("level") final Level level,
450512 @Required(message = "Loggers cannot be configured without a name") @PluginAttribute("name") final String loggerName,
453515 @PluginElement("Properties") final Property[] properties,
454516 @PluginConfiguration final Configuration config,
455517 @PluginElement("Filter") final Filter filter
518 // @formatter:on
456519 ) {
457520 final String name = loggerName.equals(ROOT) ? Strings.EMPTY : loggerName;
458521 return new LoggerConfig(name, Arrays.asList(refs), filter, level, additivity, properties, config,
2828 public static final String NULL_NAME = "Null";
2929
3030 public NullConfiguration() {
31 super(ConfigurationSource.NULL_SOURCE);
31 super(null, ConfigurationSource.NULL_SOURCE);
3232
3333 setName(NULL_NAME);
3434 final LoggerConfig root = getRootLogger();
3232
3333 private final String name;
3434 private final String value;
35 private final boolean valueNeedsLookup;
3536
3637 private Property(final String name, final String value) {
3738 this.name = name;
3839 this.value = value;
40 this.valueNeedsLookup = value != null && value.contains("${");
3941 }
4042
4143 /**
5153 * @return the value of the property.
5254 */
5355 public String getValue() {
54 return value;
56 return value == null ? "" : value; // LOG4J2-1313 null would be same as Property not existing
57 }
58
59 /**
60 * Returns {@code true} if the value contains a substitutable property that requires a lookup to be resolved.
61 * @return {@code true} if the value contains {@code "${"}, {@code false} otherwise
62 */
63 public boolean isValueNeedsLookup() {
64 return valueNeedsLookup;
5565 }
5666
5767 /**
5868 * Creates a Property.
59 *
69 *
6070 * @param name The key.
6171 * @param value The value.
6272 * @return A Property.
7383
7484 @Override
7585 public String toString() {
76 return name + '=' + value;
86 return name + '=' + getValue();
7787 }
7888 }
1616 package org.apache.logging.log4j.core.config.builder.api;
1717
1818 import java.util.ArrayList;
19 import java.util.HashMap;
19 import java.util.LinkedHashMap;
2020 import java.util.List;
2121 import java.util.Map;
2222
2727 */
2828 public class Component {
2929
30 private final Map<String, String> attributes = new HashMap<>();
30 private final Map<String, String> attributes = new LinkedHashMap<>();
3131 private final List<Component> components = new ArrayList<>();
3232 private final String pluginType;
3333 private final String value;
1515 */
1616 package org.apache.logging.log4j.core.config.builder.api;
1717
18 import java.io.IOException;
19 import java.io.OutputStream;
20
1821 import org.apache.logging.log4j.Level;
1922 import org.apache.logging.log4j.core.Filter;
23 import org.apache.logging.log4j.core.LoggerContext;
2024 import org.apache.logging.log4j.core.config.Configuration;
2125 import org.apache.logging.log4j.core.config.ConfigurationSource;
2226 import org.apache.logging.log4j.core.util.Builder;
323327 /**
324328 * Set the Advertiser Plugin name.
325329 * @param advertiser The Advertiser Plugin name.
326 * @param includeLocation If true include location information.
327330 * @return this builder instance.
328331 */
329332 ConfigurationBuilder<T> setAdvertiser(String advertiser);
378381 * @return this builder instance.
379382 */
380383 ConfigurationBuilder<T> setVerbosity(String verbosity);
384
385 /**
386 * Specifies the destination for StatusLogger events. This can be {@code out} (default) for using
387 * {@link System#out standard out}, {@code err} for using {@link System#err standard error}, or a file URI to
388 * which log events will be written. If the provided URI is invalid, then the default destination of standard
389 * out will be used.
390 *
391 * @param destination where status log messages should be output.
392 * @return this builder instance.
393 */
394 ConfigurationBuilder<T> setDestination(String destination);
395
396 /**
397 * Sets the logger context.
398 * @param loggerContext the logger context.
399 */
400 void setLoggerContext(LoggerContext loggerContext);
381401
382402 /**
383403 * Add the properties for the root node.
394414 * @return The constructed Configuration.
395415 */
396416 T build(boolean initialize);
417
418 /**
419 * Constructs an XML configuration from this builder.
420 *
421 * @param output OutputStream to write to, will not be closed
422 *
423 * @since 2.7
424 */
425 void writeXmlConfiguration(OutputStream output) throws IOException;
426
427 /**
428 * Constructs an XML configuration from this builder.
429 *
430 * @return XML configuration
431 *
432 * @since 2.7
433 */
434 String toXmlConfiguration();
397435 }
2121 import java.util.Arrays;
2222 import java.util.List;
2323
24 import org.apache.logging.log4j.core.LoggerContext;
2425 import org.apache.logging.log4j.core.config.AbstractConfiguration;
2526 import org.apache.logging.log4j.core.config.ConfigurationSource;
2627 import org.apache.logging.log4j.core.config.ConfiguratonFileWatcher;
5253 private Component scriptsComponent;
5354 private String contentType = "text";
5455
55 public BuiltConfiguration(final ConfigurationSource source, final Component rootComponent) {
56 super(source);
56 public BuiltConfiguration(final LoggerContext loggerContext, final ConfigurationSource source, final Component rootComponent) {
57 super(loggerContext, source);
5758 statusConfig = new StatusConfiguration().withVerboseClasses(VERBOSE_CLASSES).withStatus(getDefaultStatus());
5859 for (final Component component : rootComponent.getComponents()) {
5960 switch (component.getPluginType()) {
1616 package org.apache.logging.log4j.core.config.builder.impl;
1717
1818 import java.util.ArrayList;
19 import java.util.HashMap;
19 import java.util.LinkedHashMap;
2020 import java.util.List;
2121 import java.util.Map;
2222
3737
3838 private final CB builder;
3939 private final String type;
40 private final Map<String, String> attributes = new HashMap<>();
40 private final Map<String, String> attributes = new LinkedHashMap<>();
4141 private final List<Component> components = new ArrayList<>();
4242 private final String name;
4343 private final String value;
1515 */
1616 package org.apache.logging.log4j.core.config.builder.impl;
1717
18 import java.io.IOException;
19 import java.io.OutputStream;
20 import java.io.StringWriter;
1821 import java.lang.reflect.Constructor;
1922 import java.util.List;
23 import java.util.Map;
24 import javax.xml.stream.XMLOutputFactory;
25 import javax.xml.stream.XMLStreamException;
26 import javax.xml.stream.XMLStreamWriter;
2027
2128 import org.apache.logging.log4j.Level;
2229 import org.apache.logging.log4j.core.Filter;
30 import org.apache.logging.log4j.core.LoggerContext;
2331 import org.apache.logging.log4j.core.config.Configuration;
2432 import org.apache.logging.log4j.core.config.ConfigurationException;
2533 import org.apache.logging.log4j.core.config.ConfigurationSource;
3644 import org.apache.logging.log4j.core.config.builder.api.RootLoggerComponentBuilder;
3745 import org.apache.logging.log4j.core.config.builder.api.ScriptComponentBuilder;
3846 import org.apache.logging.log4j.core.config.builder.api.ScriptFileComponentBuilder;
47 import org.apache.logging.log4j.core.util.Throwables;
3948
4049 /**
4150 * @param <T> The BuiltConfiguration type.
4352 */
4453 public class DefaultConfigurationBuilder<T extends BuiltConfiguration> implements ConfigurationBuilder<T> {
4554
55 private static final String INDENT = " ";
56 private static final String EOL = System.lineSeparator();
57
4658 private final Component root = new Component();
4759 private Component loggers;
4860 private Component appenders;
5264 private Component scripts;
5365 private final Class<T> clazz;
5466 private ConfigurationSource source;
55 private int monitorInterval = 0;
56 private Level level = null;
57 private String verbosity = null;
58 private String packages = null;
59 private String shutdownFlag = null;
60 private String advertiser = null;
61
62 private String name = null;
67 private int monitorInterval;
68 private Level level;
69 private String verbosity;
70 private String destination;
71 private String packages;
72 private String shutdownFlag;
73 private String advertiser;
74 private LoggerContext loggerContext;
75 private String name;
6376
6477 @SuppressWarnings("unchecked")
6578 public DefaultConfigurationBuilder() {
150163 if (source == null) {
151164 source = ConfigurationSource.NULL_SOURCE;
152165 }
153 final Constructor<T> constructor = clazz.getConstructor(ConfigurationSource.class, Component.class);
154 configuration = constructor.newInstance(source, root);
166 final Constructor<T> constructor = clazz.getConstructor(LoggerContext.class, ConfigurationSource.class, Component.class);
167 configuration = constructor.newInstance(loggerContext, source, root);
155168 configuration.setMonitorInterval(monitorInterval);
156169 configuration.getRootNode().getAttributes().putAll(root.getAttributes());
157170 if (name != null) {
163176 if (verbosity != null) {
164177 configuration.getStatusConfiguration().withVerbosity(verbosity);
165178 }
179 if (destination != null) {
180 configuration.getStatusConfiguration().withDestination(destination);
181 }
166182 if (packages != null) {
167183 configuration.setPluginPackages(packages);
168184 }
183199 }
184200
185201 @Override
202 public void writeXmlConfiguration(final OutputStream output) throws IOException {
203 try {
204 final XMLStreamWriter xmlWriter = XMLOutputFactory.newInstance().createXMLStreamWriter(output);
205 writeXmlConfiguration(xmlWriter);
206 xmlWriter.close();
207 } catch (final XMLStreamException e) {
208 if (e.getNestedException() instanceof IOException) {
209 throw (IOException)e.getNestedException();
210 }
211 Throwables.rethrow(e);
212 }
213 }
214
215 @Override
216 public String toXmlConfiguration() {
217 final StringWriter sw = new StringWriter();
218 try {
219 final XMLStreamWriter xmlWriter = XMLOutputFactory.newInstance().createXMLStreamWriter(sw);
220 writeXmlConfiguration(xmlWriter);
221 xmlWriter.close();
222 } catch (final XMLStreamException e) {
223 Throwables.rethrow(e);
224 }
225 return sw.toString();
226 }
227
228 private void writeXmlConfiguration(final XMLStreamWriter xmlWriter) throws XMLStreamException {
229 xmlWriter.writeStartDocument();
230 xmlWriter.writeCharacters(EOL);
231
232 xmlWriter.writeStartElement("Configuration");
233 if (name != null) {
234 xmlWriter.writeAttribute("name", name);
235 }
236 if (level != null) {
237 xmlWriter.writeAttribute("status", level.name());
238 }
239 if (verbosity != null) {
240 xmlWriter.writeAttribute("verbose", verbosity);
241 }
242 if (destination != null) {
243 xmlWriter.writeAttribute("dest", destination);
244 }
245 if (packages != null) {
246 xmlWriter.writeAttribute("packages", packages);
247 }
248 if (shutdownFlag != null) {
249 xmlWriter.writeAttribute("shutdownHook", shutdownFlag);
250 }
251 if (advertiser != null) {
252 xmlWriter.writeAttribute("advertiser", advertiser);
253 }
254 if (monitorInterval > 0) {
255 xmlWriter.writeAttribute("monitorInterval", String.valueOf(monitorInterval));
256 }
257
258 xmlWriter.writeCharacters(EOL);
259
260 writeXmlSection(xmlWriter, properties);
261 writeXmlSection(xmlWriter, scripts);
262 writeXmlSection(xmlWriter, customLevels);
263 if (filters.getComponents().size() == 1) {
264 writeXmlComponent(xmlWriter, filters.getComponents().get(0), 1);
265 } else if (filters.getComponents().size() > 1) {
266 writeXmlSection(xmlWriter, filters);
267 }
268 writeXmlSection(xmlWriter, appenders);
269 writeXmlSection(xmlWriter, loggers);
270
271 xmlWriter.writeEndElement(); // "Configuration"
272 xmlWriter.writeCharacters(EOL);
273
274 xmlWriter.writeEndDocument();
275 }
276
277 private void writeXmlSection(final XMLStreamWriter xmlWriter, final Component component) throws XMLStreamException {
278 if (!component.getAttributes().isEmpty() || !component.getComponents().isEmpty() || component.getValue() != null) {
279 writeXmlComponent(xmlWriter, component, 1);
280 }
281 }
282
283 private void writeXmlComponent(final XMLStreamWriter xmlWriter, final Component component, final int nesting) throws XMLStreamException {
284 if (!component.getComponents().isEmpty() || component.getValue() != null) {
285 writeXmlIndent(xmlWriter, nesting);
286 xmlWriter.writeStartElement(component.getPluginType());
287 writeXmlAttributes(xmlWriter, component);
288 if (!component.getComponents().isEmpty()) {
289 xmlWriter.writeCharacters(EOL);
290 }
291 for (final Component subComponent : component.getComponents()) {
292 writeXmlComponent(xmlWriter, subComponent, nesting + 1);
293 }
294 if (component.getValue() != null) {
295 xmlWriter.writeCharacters(component.getValue());
296 }
297 if (!component.getComponents().isEmpty()) {
298 writeXmlIndent(xmlWriter, nesting);
299 }
300 xmlWriter.writeEndElement();
301 } else {
302 writeXmlIndent(xmlWriter, nesting);
303 xmlWriter.writeEmptyElement(component.getPluginType());
304 writeXmlAttributes(xmlWriter, component);
305 }
306 xmlWriter.writeCharacters(EOL);
307 }
308
309 private void writeXmlIndent(final XMLStreamWriter xmlWriter, final int nesting) throws XMLStreamException {
310 for (int i = 0; i < nesting; i++) {
311 xmlWriter.writeCharacters(INDENT);
312 }
313 }
314
315 private void writeXmlAttributes(final XMLStreamWriter xmlWriter, final Component component) throws XMLStreamException {
316 for (final Map.Entry<String, String> attribute : component.getAttributes().entrySet()) {
317 xmlWriter.writeAttribute(attribute.getKey(), attribute.getValue());
318 }
319 }
320
321 @Override
186322 public ScriptComponentBuilder newScript(final String name, final String language, final String text) {
187323 return new DefaultScriptComponentBuilder(this, name, language, text);
188324 }
210346
211347 @Override
212348 public LoggerComponentBuilder newAsyncLogger(final String name, final Level level) {
213 return new DefaultLoggerComponentBuilder(this, name, level.toString(), "AsyncLogger", false);
349 return new DefaultLoggerComponentBuilder(this, name, level.toString(), "AsyncLogger");
214350 }
215351
216352 @Override
220356
221357 @Override
222358 public LoggerComponentBuilder newAsyncLogger(final String name, final String level) {
223 return new DefaultLoggerComponentBuilder(this, name, level, "AsyncLogger", false);
359 return new DefaultLoggerComponentBuilder(this, name, level, "AsyncLogger");
224360 }
225361
226362 @Override
230366
231367 @Override
232368 public RootLoggerComponentBuilder newAsyncRootLogger(final Level level) {
233 return new DefaultRootLoggerComponentBuilder(this, level.toString(), "AsyncRoot", false);
369 return new DefaultRootLoggerComponentBuilder(this, level.toString(), "AsyncRoot");
234370 }
235371
236372 @Override
240376
241377 @Override
242378 public RootLoggerComponentBuilder newAsyncRootLogger(final String level) {
243 return new DefaultRootLoggerComponentBuilder(this, level, "AsyncRoot", false);
379 return new DefaultRootLoggerComponentBuilder(this, level, "AsyncRoot");
244380 }
245381
246382 @Override
290426
291427 @Override
292428 public LoggerComponentBuilder newLogger(final String name, final Level level) {
293 return new DefaultLoggerComponentBuilder(this, name, level.toString(), true);
429 return new DefaultLoggerComponentBuilder(this, name, level.toString());
294430 }
295431
296432 @Override
300436
301437 @Override
302438 public LoggerComponentBuilder newLogger(final String name, final String level) {
303 return new DefaultLoggerComponentBuilder(this, name, level, true);
439 return new DefaultLoggerComponentBuilder(this, name, level);
304440 }
305441
306442 @Override
310446
311447 @Override
312448 public RootLoggerComponentBuilder newRootLogger(final Level level) {
313 return new DefaultRootLoggerComponentBuilder(this, level.toString(), true);
449 return new DefaultRootLoggerComponentBuilder(this, level.toString());
314450 }
315451
316452 @Override
320456
321457 @Override
322458 public RootLoggerComponentBuilder newRootLogger(final String level) {
323 return new DefaultRootLoggerComponentBuilder(this, level, true);
459 return new DefaultRootLoggerComponentBuilder(this, level);
324460 }
325461
326462 @Override
389525 }
390526
391527 @Override
528 public ConfigurationBuilder<T> setDestination(final String destination) {
529 this.destination = destination;
530 return this;
531 }
532
533 @Override
534 public void setLoggerContext(final LoggerContext loggerContext) {
535 this.loggerContext = loggerContext;
536 }
537
538 @Override
392539 public ConfigurationBuilder<T> addRootProperty(final String key, final String value) {
393540 root.getAttributes().put(key, value);
394541 return this;
395542 }
543
396544 }
2727 public DefaultCustomLevelComponentBuilder(final DefaultConfigurationBuilder<? extends Configuration> builder,
2828 final String name, final int level) {
2929 super(builder, name, "CustomLevel");
30 addAttribute("level", Integer.toString(level));
30 addAttribute("intLevel", level);
3131 }
3232 }
6161 * @param configurations The List of Configurations to merge.
6262 */
6363 public CompositeConfiguration(final List<? extends AbstractConfiguration> configurations) {
64 super(ConfigurationSource.NULL_SOURCE);
64 super(configurations.get(0).getLoggerContext(), ConfigurationSource.NULL_SOURCE);
6565 rootNode = configurations.get(0).getRootNode();
6666 this.configurations = configurations;
6767 final String mergeStrategyClassName = PropertiesUtil.getProperties().getStringProperty(MERGE_STRATEGY_PROPERTY,
151151 if (sourceURI != null) {
152152 LOGGER.warn("Unable to determine URI for configuration {}, changes to it will be ignored",
153153 config.getName());
154 currentConfig = factory.getConfiguration(config.getName(), sourceURI);
154 currentConfig = factory.getConfiguration(getLoggerContext(), config.getName(), sourceURI);
155155 if (currentConfig == null) {
156156 LOGGER.warn("Unable to reload configuration {}, changes to it will be ignored", config.getName());
157157 currentConfig = config;
154154 final Node targetNode = getLoggerNode(targetChildNode, node.getAttributes().get(NAME));
155155 final Node loggerNode = new Node(targetChildNode, node.getName(), node.getType());
156156 if (targetNode != null) {
157 targetNode.getAttributes().putAll(node.getAttributes());
157158 for (final Node sourceLoggerChild : node.getChildren()) {
158159 if (isFilterNode(sourceLoggerChild)) {
159160 boolean foundFilter = false;
259260 }
260261
261262 private boolean isSameName(final Node node1, final Node node2) {
262 return node1.getAttributes().get(NAME).toLowerCase().equals(node2.getAttributes().get(NAME).toLowerCase());
263 final String value = node1.getAttributes().get(NAME);
264 return value != null && value.toLowerCase().equals(node2.getAttributes().get(NAME).toLowerCase());
263265 }
264266
265267 private boolean isSameReference(final Node node1, final Node node2) {
266 return node1.getAttributes().get(REF).toLowerCase().equals(node2.getAttributes().get(REF).toLowerCase());
268 final String value = node1.getAttributes().get(REF);
269 return value != null && value.toLowerCase().equals(node2.getAttributes().get(REF).toLowerCase());
267270 }
268271 }
2525 import java.util.List;
2626 import java.util.Map;
2727
28 import com.fasterxml.jackson.core.JsonParser;
29 import com.fasterxml.jackson.databind.JsonNode;
30 import com.fasterxml.jackson.databind.ObjectMapper;
28 import org.apache.logging.log4j.core.LoggerContext;
3129 import org.apache.logging.log4j.core.config.AbstractConfiguration;
3230 import org.apache.logging.log4j.core.config.Configuration;
3331 import org.apache.logging.log4j.core.config.ConfigurationSource;
4139 import org.apache.logging.log4j.core.util.FileWatcher;
4240 import org.apache.logging.log4j.core.util.Patterns;
4341
42 import com.fasterxml.jackson.core.JsonParser;
43 import com.fasterxml.jackson.databind.JsonNode;
44 import com.fasterxml.jackson.databind.ObjectMapper;
45
4446 /**
4547 * Creates a Node hierarchy from a JSON file.
4648 */
5052 private final List<Status> status = new ArrayList<>();
5153 private JsonNode root;
5254
53 public JsonConfiguration(final ConfigurationSource configSource) {
54 super(configSource);
55 public JsonConfiguration(final LoggerContext loggerContext, final ConfigurationSource configSource) {
56 super(loggerContext, configSource);
5557 final File configFile = configSource.getFile();
5658 byte[] buffer;
5759 try {
127129 LOGGER.debug("Completed parsing configuration");
128130 if (status.size() > 0) {
129131 for (final Status s : status) {
130 LOGGER.error("Error processing element " + s.name + ": " + s.errorType);
132 LOGGER.error("Error processing element {}: {}", s.name, s.errorType);
131133 }
132134 }
133135 }
139141 if (source == null) {
140142 return null;
141143 }
142 return new JsonConfiguration(source);
144 return new JsonConfiguration(getLoggerContext(), source);
143145 } catch (final IOException ex) {
144146 LOGGER.error("Cannot locate file {}", getConfigurationSource(), ex);
145147 }
1515 */
1616 package org.apache.logging.log4j.core.config.json;
1717
18 import org.apache.logging.log4j.core.LoggerContext;
1819 import org.apache.logging.log4j.core.config.Configuration;
1920 import org.apache.logging.log4j.core.config.ConfigurationFactory;
2021 import org.apache.logging.log4j.core.config.ConfigurationSource;
5960 }
6061
6162 @Override
62 public Configuration getConfiguration(final ConfigurationSource source) {
63 public Configuration getConfiguration(final LoggerContext loggerContext, final ConfigurationSource source) {
6364 if (!isActive) {
6465 return null;
6566 }
66 return new JsonConfiguration(source);
67 return new JsonConfiguration(loggerContext, source);
6768 }
6869
6970 @Override
2929 @Retention(RetentionPolicy.RUNTIME)
3030 @Target(ElementType.METHOD)
3131 public @interface PluginBuilderFactory {
32 // empty
3233 }
3232 @Target({ElementType.PARAMETER, ElementType.FIELD})
3333 @PluginVisitorStrategy(PluginConfigurationVisitor.class)
3434 public @interface PluginConfiguration {
35 // empty
3536 }
3232 @Retention(RetentionPolicy.RUNTIME)
3333 @Target(ElementType.METHOD)
3434 public @interface PluginFactory {
35
35 // empty
3636 }
3131 @Target({ElementType.PARAMETER, ElementType.FIELD})
3232 @PluginVisitorStrategy(PluginNodeVisitor.class)
3333 public @interface PluginNode {
34 // empty
3435 }
3535 import org.apache.logging.log4j.core.appender.rolling.action.Duration;
3636 import org.apache.logging.log4j.core.config.plugins.Plugin;
3737 import org.apache.logging.log4j.core.util.CronExpression;
38 import org.apache.logging.log4j.core.util.Loader;
3938 import org.apache.logging.log4j.status.StatusLogger;
39 import org.apache.logging.log4j.util.LoaderUtil;
4040
4141 /**
4242 * Collection of basic TypeConverter implementations. May be used to register additional TypeConverters or find
174174 public static class ClassConverter implements TypeConverter<Class<?>> {
175175 @Override
176176 public Class<?> convert(final String s) throws ClassNotFoundException {
177 return Loader.loadClass(s);
177 return LoaderUtil.loadClass(s);
178178 }
179179 }
180180
146146 for (final Method method : clazz.getDeclaredMethods()) {
147147 if (method.isAnnotationPresent(PluginBuilderFactory.class) &&
148148 Modifier.isStatic(method.getModifiers()) &&
149 TypeUtil.isAssignable(Builder.class, method.getGenericReturnType())) {
149 TypeUtil.isAssignable(Builder.class, method.getReturnType())) {
150150 ReflectionUtil.makeAccessible(method);
151151 return (Builder<?>) method.invoke(null);
152152 }
155155 }
156156
157157 private void injectFields(final Builder<?> builder) throws IllegalAccessException {
158 final Field[] fields = builder.getClass().getDeclaredFields();
159 AccessibleObject.setAccessible(fields, true);
158 final List<Field> fields = TypeUtil.getAllDeclaredFields(builder.getClass());
159 AccessibleObject.setAccessible(fields.toArray(new Field[] {}), true);
160160 final StringBuilder log = new StringBuilder();
161161 boolean invalid = false;
162162 for (final Field field : fields) {
178178 final String className = entry.getClassName();
179179 try {
180180 final Class<?> clazz = loader.loadClass(className);
181 @SuppressWarnings({"unchecked","rawtypes"})
182181 final PluginType<?> type = new PluginType<>(entry, clazz, entry.getName());
183182 types.add(type);
184183 ++pluginCount;
8383
8484 private static final String VFSZIP = "vfszip";
8585
86 private static final String VFS = "vfs";
87
8688 private static final String BUNDLE_RESOURCE = "bundleresource";
8789
8890 /** The set of matches being accumulated. */
195197 } finally {
196198 close(stream, newURL);
197199 }
200 } else if (VFS.equals(url.getProtocol())) {
201 final String containerPath = urlPath.substring(1,
202 urlPath.length() - packageName.length() - 2);
203 final File containerFile = new File(containerPath);
204 if (containerFile.isDirectory()) {
205 loadImplementationsInDirectory(test, packageName, new File(containerFile, packageName));
206 } else {
207 loadImplementationsInJar(test, packageName, containerFile);
208 }
198209 } else if (BUNDLE_RESOURCE.equals(url.getProtocol())) {
199210 loadImplementationsInBundle(test, packageName);
200211 } else {
231242 // LOG4J2-445
232243 // Finally, decide whether to URL-decode the file name or not...
233244 final String protocol = url.getProtocol();
234 final List<String> neverDecode = Arrays.asList(VFSZIP, BUNDLE_RESOURCE);
245 final List<String> neverDecode = Arrays.asList(VFS, VFSZIP, BUNDLE_RESOURCE);
235246 if (neverDecode.contains(protocol)) {
236247 return urlPath;
237248 }
9696 private Node findNamedNode(final String name, final Iterable<Node> children) {
9797 for (final Node child : children) {
9898 final PluginType<?> childType = child.getType();
99 if (childType == null) {
100 //System.out.println();
101 }
99102 if (name.equalsIgnoreCase(childType.getElementName()) ||
100103 this.conversionType.isAssignableFrom(childType.getPluginClass())) {
101104 // FIXME: check child.getObject() for null?
2121 import org.apache.logging.log4j.core.config.Node;
2222 import org.apache.logging.log4j.core.config.plugins.PluginValue;
2323 import org.apache.logging.log4j.util.StringBuilders;
24 import org.apache.logging.log4j.util.Strings;
2425
2526 /**
2627 * PluginVisitor implementation for {@link PluginValue}.
3233
3334 @Override
3435 public Object visit(final Configuration configuration, final Node node, final LogEvent event,
35 final StringBuilder log) {
36 final StringBuilder log) {
3637 final String name = this.annotation.value();
37 final String rawValue = node.getValue() != null ? node.getValue() :
38 removeAttributeValue(node.getAttributes(), "value");
38 final String elementValue = node.getValue();
39 final String attributeValue = node.getAttributes().get("value");
40 String rawValue = null; // if neither is specified, return null (LOG4J2-1313)
41 if (Strings.isNotEmpty(elementValue)) {
42 if (Strings.isNotEmpty(attributeValue)) {
43 LOGGER.error("Configuration contains {} with both attribute value ({}) AND element" +
44 " value ({}). Please specify only one value. Using the element value.",
45 node.getName(), attributeValue, elementValue);
46 }
47 rawValue = elementValue;
48 } else {
49 rawValue = removeAttributeValue(node.getAttributes(), "value");
50 }
3951 final String value = this.substitutor.replace(event, rawValue);
4052 StringBuilders.appendKeyDqValue(log, name, value);
4153 return value;
1717
1818 import java.io.IOException;
1919
20 import org.apache.logging.log4j.core.LoggerContext;
2021 import org.apache.logging.log4j.core.config.Configuration;
2122 import org.apache.logging.log4j.core.config.ConfigurationSource;
2223 import org.apache.logging.log4j.core.config.Reconfigurable;
2930 */
3031 public class PropertiesConfiguration extends BuiltConfiguration implements Reconfigurable {
3132
32 public PropertiesConfiguration(final ConfigurationSource source, final Component root) {
33 super(source, root);
33 // ctor is called through reflection.
34 public PropertiesConfiguration(final LoggerContext loggerContext, final ConfigurationSource source, final Component root) {
35 super(loggerContext, source, root);
3436 }
3537
3638 @Override
4143 return null;
4244 }
4345 final PropertiesConfigurationFactory factory = new PropertiesConfigurationFactory();
44 final PropertiesConfiguration config = factory.getConfiguration(source);
46 final PropertiesConfiguration config = factory.getConfiguration(getLoggerContext(), source);
4547 return config == null || config.getState() != State.INITIALIZING ? null : config;
4648 } catch (final IOException ex) {
4749 LOGGER.error("Cannot locate file {}: {}", getConfigurationSource(), ex);
1616
1717 package org.apache.logging.log4j.core.config.properties;
1818
19 import java.util.HashMap;
2019 import java.util.Map;
2120 import java.util.Properties;
2221
2322 import org.apache.logging.log4j.Level;
23 import org.apache.logging.log4j.core.Appender;
24 import org.apache.logging.log4j.core.LoggerContext;
2425 import org.apache.logging.log4j.core.config.ConfigurationException;
2526 import org.apache.logging.log4j.core.config.ConfigurationSource;
2627 import org.apache.logging.log4j.core.config.LoggerConfig;
5354 private static final String STATUS_KEY = "status";
5455 private static final String SHUTDOWN_HOOK = "shutdownHook";
5556 private static final String VERBOSE = "verbose";
57 private static final String DEST = "dest";
5658 private static final String PACKAGES = "packages";
5759 private static final String CONFIG_NAME = "name";
5860 private static final String MONITOR_INTERVAL = "monitorInterval";
5961 private static final String CONFIG_TYPE = "type";
6062
6163 private final ConfigurationBuilder<PropertiesConfiguration> builder;
64 private LoggerContext loggerContext;
6265 private Properties rootProperties;
6366
6467 public PropertiesConfigurationBuilder() {
7780
7881 @Override
7982 public PropertiesConfiguration build() {
80 final Map<String, String> rootProps = new HashMap<>();
8183 for (final String key : rootProperties.stringPropertyNames()) {
8284 if (!key.contains(".")) {
8385 builder.addRootProperty(key, rootProperties.getProperty(key));
8789 .setStatusLevel(Level.toLevel(rootProperties.getProperty(STATUS_KEY), Level.ERROR))
8890 .setShutdownHook(rootProperties.getProperty(SHUTDOWN_HOOK))
8991 .setVerbosity(rootProperties.getProperty(VERBOSE))
92 .setDestination(rootProperties.getProperty(DEST))
9093 .setPackages(rootProperties.getProperty(PACKAGES))
9194 .setConfigurationName(rootProperties.getProperty(CONFIG_NAME))
9295 .setMonitorInterval(rootProperties.getProperty(MONITOR_INTERVAL, "0"))
145148 }
146149 } else {
147150 final Map<String, Properties> appenders = PropertiesUtil
148 .partitionOnCommonPrefixes(PropertiesUtil.extractSubset(rootProperties, "appender"));
151 .partitionOnCommonPrefixes(PropertiesUtil.extractSubset(rootProperties, Appender.ELEMENT_TYPE));
149152 for (final Map.Entry<String, Properties> entry : appenders.entrySet()) {
150153 builder.add(createAppender(entry.getKey().trim(), entry.getValue()));
151154 }
176179 if (props.size() > 0) {
177180 builder.add(createRootLogger(props));
178181 }
179
182
183 builder.setLoggerContext(loggerContext);
184
180185 return builder.build(false);
181186 }
182187
363368 }
364369 return loggerBuilder;
365370 }
371
372 public PropertiesConfigurationBuilder setLoggerContext(final LoggerContext loggerContext) {
373 this.loggerContext = loggerContext;
374 return this;
375 }
376
377 public LoggerContext getLoggerContext() {
378 return loggerContext;
379 }
366380 }
1919 import java.io.InputStream;
2020 import java.util.Properties;
2121
22 import org.apache.logging.log4j.core.LoggerContext;
2223 import org.apache.logging.log4j.core.config.ConfigurationException;
2324 import org.apache.logging.log4j.core.config.ConfigurationFactory;
2425 import org.apache.logging.log4j.core.config.ConfigurationSource;
4041 }
4142
4243 @Override
43 public PropertiesConfiguration getConfiguration(final ConfigurationSource source) {
44 final InputStream configStream = source.getInputStream();
44 public PropertiesConfiguration getConfiguration(final LoggerContext loggerContext, final ConfigurationSource source) {
4545 final Properties properties = new Properties();
46 try {
46 try (final InputStream configStream = source.getInputStream()) {
4747 properties.load(configStream);
4848 } catch (final IOException ioe) {
4949 throw new ConfigurationException("Unable to load " + source.toString(), ioe);
5050 }
51 return new PropertiesConfigurationBuilder().setConfigurationSource(source)
52 .setRootProperties(properties).build();
51 return new PropertiesConfigurationBuilder()
52 .setConfigurationSource(source)
53 .setRootProperties(properties)
54 .setLoggerContext(loggerContext)
55 .build();
5356 }
5457 }
3434 import javax.xml.validation.SchemaFactory;
3535 import javax.xml.validation.Validator;
3636
37 import org.apache.logging.log4j.core.LoggerContext;
3738 import org.apache.logging.log4j.core.config.AbstractConfiguration;
3839 import org.apache.logging.log4j.core.config.Configuration;
3940 import org.apache.logging.log4j.core.config.ConfigurationSource;
7475 private boolean strict;
7576 private String schemaResource;
7677
77 public XmlConfiguration(final ConfigurationSource configSource) {
78 super(configSource);
78 public XmlConfiguration(final LoggerContext loggerContext, final ConfigurationSource configSource) {
79 super(loggerContext, configSource);
7980 final File configFile = configSource.getFile();
8081 byte[] buffer = null;
8182
146147 LOGGER.error("Error parsing " + configSource.getLocation(), e);
147148 }
148149 if (strict && schemaResource != null && buffer != null) {
149 InputStream is = null;
150 try {
151 is = Loader.getResourceAsStream(schemaResource, XmlConfiguration.class.getClassLoader());
150 try (InputStream is = Loader.getResourceAsStream(schemaResource, XmlConfiguration.class.getClassLoader())) {
151 if (is != null) {
152 final Source src = new StreamSource(is, LOG4J_XSD);
153 final SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
154 Schema schema = null;
155 try {
156 schema = factory.newSchema(src);
157 } catch (final SAXException ex) {
158 LOGGER.error("Error parsing Log4j schema", ex);
159 }
160 if (schema != null) {
161 final Validator validator = schema.newValidator();
162 try {
163 validator.validate(new StreamSource(new ByteArrayInputStream(buffer)));
164 } catch (final IOException ioe) {
165 LOGGER.error("Error reading configuration for validation", ioe);
166 } catch (final SAXException ex) {
167 LOGGER.error("Error validating configuration", ex);
168 }
169 }
170 }
152171 } catch (final Exception ex) {
153172 LOGGER.error("Unable to access schema {}", this.schemaResource, ex);
154 }
155 if (is != null) {
156 final Source src = new StreamSource(is, LOG4J_XSD);
157 final SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
158 Schema schema = null;
159 try {
160 schema = factory.newSchema(src);
161 } catch (final SAXException ex) {
162 LOGGER.error("Error parsing Log4j schema", ex);
163 }
164 if (schema != null) {
165 final Validator validator = schema.newValidator();
166 try {
167 validator.validate(new StreamSource(new ByteArrayInputStream(buffer)));
168 } catch (final IOException ioe) {
169 LOGGER.error("Error reading configuration for validation", ioe);
170 } catch (final SAXException ex) {
171 LOGGER.error("Error validating configuration", ex);
172 }
173 }
174173 }
175174 }
176175
256255 if (source == null) {
257256 return null;
258257 }
259 final XmlConfiguration config = new XmlConfiguration(source);
258 final XmlConfiguration config = new XmlConfiguration(getLoggerContext(), source);
260259 return config.rootElement == null ? null : config;
261260 } catch (final IOException ex) {
262261 LOGGER.error("Cannot locate file {}", getConfigurationSource(), ex);
1515 */
1616 package org.apache.logging.log4j.core.config.xml;
1717
18 import org.apache.logging.log4j.core.LoggerContext;
1819 import org.apache.logging.log4j.core.config.Configuration;
1920 import org.apache.logging.log4j.core.config.ConfigurationFactory;
2021 import org.apache.logging.log4j.core.config.ConfigurationSource;
3536
3637 /**
3738 * Returns the Configuration.
39 * @param loggerContext The logger context.
3840 * @param source The InputSource.
3941 * @return The Configuration.
4042 */
4143 @Override
42 public Configuration getConfiguration(final ConfigurationSource source) {
43 return new XmlConfiguration(source);
44 public Configuration getConfiguration(final LoggerContext loggerContext, final ConfigurationSource source) {
45 return new XmlConfiguration(loggerContext, source);
4446 }
4547
4648 /**
1717
1818 import java.io.IOException;
1919
20 import org.apache.logging.log4j.core.LoggerContext;
2021 import org.apache.logging.log4j.core.config.Configuration;
2122 import org.apache.logging.log4j.core.config.ConfigurationSource;
2223 import org.apache.logging.log4j.core.config.json.JsonConfiguration;
2728
2829 public class YamlConfiguration extends JsonConfiguration {
2930
30 public YamlConfiguration(final ConfigurationSource configSource) {
31 super(configSource);
31 public YamlConfiguration(final LoggerContext loggerContext, final ConfigurationSource configSource) {
32 super(loggerContext, configSource);
3233 }
3334
3435 @Override
4344 if (source == null) {
4445 return null;
4546 }
46 return new YamlConfiguration(source);
47 return new YamlConfiguration(getLoggerContext(), source);
4748 } catch (final IOException ex) {
4849 LOGGER.error("Cannot locate file {}", getConfigurationSource(), ex);
4950 }
1515 */
1616 package org.apache.logging.log4j.core.config.yaml;
1717
18 import org.apache.logging.log4j.core.LoggerContext;
1819 import org.apache.logging.log4j.core.config.Configuration;
1920 import org.apache.logging.log4j.core.config.ConfigurationFactory;
2021 import org.apache.logging.log4j.core.config.ConfigurationSource;
5758 }
5859
5960 @Override
60 public Configuration getConfiguration(final ConfigurationSource source) {
61 public Configuration getConfiguration(final LoggerContext loggerContext, final ConfigurationSource source) {
6162 if (!isActive) {
6263 return null;
6364 }
64 return new YamlConfiguration(source);
65 return new YamlConfiguration(loggerContext, source);
6566 }
6667
6768 @Override
145145 @Override
146146 public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
147147 final Object p0) {
148 return Result.NEUTRAL;
148 return filter(logger, level, marker, msg, new Object[] {p0});
149149 }
150150
151151 /**
161161 @Override
162162 public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
163163 final Object p0, final Object p1) {
164 return Result.NEUTRAL;
164 return filter(logger, level, marker, msg, new Object[] {p0, p1});
165165 }
166166
167167 /**
178178 @Override
179179 public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
180180 final Object p0, final Object p1, final Object p2) {
181 return Result.NEUTRAL;
181 return filter(logger, level, marker, msg, new Object[] {p0, p1, p2});
182182 }
183183
184184 /**
196196 @Override
197197 public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
198198 final Object p0, final Object p1, final Object p2, final Object p3) {
199 return Result.NEUTRAL;
199 return filter(logger, level, marker, msg, new Object[] {p0, p1, p2, p3});
200200 }
201201
202202 /**
216216 public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
217217 final Object p0, final Object p1, final Object p2, final Object p3,
218218 final Object p4) {
219 return Result.NEUTRAL;
219 return filter(logger, level, marker, msg, new Object[] {p0, p1, p2, p3, p4});
220220 }
221221
222222 /**
237237 public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
238238 final Object p0, final Object p1, final Object p2, final Object p3,
239239 final Object p4, final Object p5) {
240 return Result.NEUTRAL;
240 return filter(logger, level, marker, msg, new Object[] {p0, p1, p2, p3, p4, p5});
241241 }
242242
243243 /**
259259 public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
260260 final Object p0, final Object p1, final Object p2, final Object p3,
261261 final Object p4, final Object p5, final Object p6) {
262 return Result.NEUTRAL;
262 return filter(logger, level, marker, msg, new Object[] {p0, p1, p2, p3, p4, p5, p6});
263263 }
264264
265265 /**
283283 final Object p0, final Object p1, final Object p2, final Object p3,
284284 final Object p4, final Object p5, final Object p6,
285285 final Object p7) {
286 return Result.NEUTRAL;
286 return filter(logger, level, marker, msg, new Object[] {p0, p1, p2, p3, p4, p5, p6, p7});
287287 }
288288
289289 /**
308308 final Object p0, final Object p1, final Object p2, final Object p3,
309309 final Object p4, final Object p5, final Object p6,
310310 final Object p7, final Object p8) {
311 return Result.NEUTRAL;
311 return filter(logger, level, marker, msg, new Object[] {p0, p1, p2, p3, p4, p5, p6, p7, p8});
312312 }
313313
314314 /**
334334 final Object p0, final Object p1, final Object p2, final Object p3,
335335 final Object p4, final Object p5, final Object p6,
336336 final Object p7, final Object p8, final Object p9) {
337 return Result.NEUTRAL;
337 return filter(logger, level, marker, msg, new Object[] {p0, p1, p2, p3, p4, p5, p6, p7, p8, p9});
338338 }
339339
340340 /**
1616 package org.apache.logging.log4j.core.filter;
1717
1818 import java.util.Iterator;
19 import java.util.concurrent.TimeUnit;
1920
2021 import org.apache.logging.log4j.core.AbstractLifeCycle;
2122 import org.apache.logging.log4j.core.Filter;
23 import org.apache.logging.log4j.core.LifeCycle2;
2224 import org.apache.logging.log4j.core.LogEvent;
25 import org.apache.logging.log4j.core.config.plugins.PluginElement;
2326
2427 /**
2528 * Enhances a Class by allowing it to contain Filters.
2629 */
2730 public abstract class AbstractFilterable extends AbstractLifeCycle implements Filterable {
31
32 /**
33 * Subclasses can extend this abstract Builder.
34 *
35 * @param <B> This builder class.
36 */
37 public abstract static class Builder<B extends Builder<B>> {
38
39 @PluginElement("Filter")
40 private Filter filter;
41
42 public Filter getFilter() {
43 return filter;
44 }
45
46 @SuppressWarnings("unchecked")
47 public B asBuilder() {
48 return (B) this;
49 }
50
51 public B withFilter(final Filter filter) {
52 this.filter = filter;
53 return asBuilder();
54 }
55
56 }
2857
2958 /**
3059 * May be null.
116145 * Cleanup the Filter.
117146 */
118147 @Override
119 public void stop() {
120 this.setStopping();
148 public boolean stop(final long timeout, final TimeUnit timeUnit) {
149 return stop(timeout, timeUnit, true);
150 }
151
152 /**
153 * Cleanup the Filter.
154 */
155 protected boolean stop(final long timeout, final TimeUnit timeUnit, final boolean changeLifeCycleState) {
156 if (changeLifeCycleState) {
157 this.setStopping();
158 }
159 boolean stopped = true;
121160 if (filter != null) {
122 filter.stop();
161 if (filter instanceof LifeCycle2) {
162 stopped = ((LifeCycle2) filter).stop(timeout, timeUnit);
163 } else {
164 filter.stop();
165 stopped = true;
166 }
123167 }
124 this.setStopped();
168 if (changeLifeCycleState) {
169 this.setStopped();
170 }
171 return stopped;
125172 }
126173
127174 /**
1919 import java.util.Arrays;
2020 import java.util.Iterator;
2121 import java.util.List;
22 import java.util.concurrent.TimeUnit;
2223
2324 import org.apache.logging.log4j.Level;
2425 import org.apache.logging.log4j.Marker;
2526 import org.apache.logging.log4j.core.AbstractLifeCycle;
2627 import org.apache.logging.log4j.core.Filter;
28 import org.apache.logging.log4j.core.LifeCycle2;
2729 import org.apache.logging.log4j.core.LogEvent;
2830 import org.apache.logging.log4j.core.Logger;
2931 import org.apache.logging.log4j.core.config.Node;
131133 }
132134
133135 @Override
134 public void stop() {
136 public boolean stop(final long timeout, final TimeUnit timeUnit) {
135137 this.setStopping();
136138 for (final Filter filter : filters) {
137 filter.stop();
138 }
139 this.setStopped();
139 if (filter instanceof LifeCycle2) {
140 ((LifeCycle2) filter).stop(timeout, timeUnit);
141 } else {
142 filter.stop();
143 }
144 }
145 setStopped();
146 return true;
140147 }
141148
142149 /**
3030 import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
3131 import org.apache.logging.log4j.core.config.plugins.PluginElement;
3232 import org.apache.logging.log4j.core.config.plugins.PluginFactory;
33 import org.apache.logging.log4j.core.ContextDataInjector;
34 import org.apache.logging.log4j.core.impl.ContextDataInjectorFactory;
3335 import org.apache.logging.log4j.core.util.KeyValuePair;
3436 import org.apache.logging.log4j.message.Message;
37 import org.apache.logging.log4j.util.ReadOnlyStringMap;
3538
3639 /**
37 * Compare against a log level that is associated with an MDC value.
40 * Compares against a log level that is associated with a context value. By default the context is the
41 * {@link ThreadContext}, but users may {@linkplain ContextDataInjectorFactory configure} a custom
42 * {@link ContextDataInjector} which obtains context data from some other source.
3843 */
3944 @Plugin(name = "DynamicThresholdFilter", category = Node.CATEGORY, elementType = Filter.ELEMENT_TYPE, printObject = true)
4045 public final class DynamicThresholdFilter extends AbstractFilter {
4146
4247 /**
43 * Create the DynamicThresholdFilter.
48 * Creates a DynamicThresholdFilter.
4449 * @param key The name of the key to compare.
4550 * @param pairs An array of value and Level pairs.
4651 * @param defaultThreshold The default Level.
6267 final Level level = defaultThreshold == null ? Level.ERROR : defaultThreshold;
6368 return new DynamicThresholdFilter(key, map, level, onMatch, onMismatch);
6469 }
70
6571 private Level defaultThreshold = Level.ERROR;
6672 private final String key;
67
73 private final ContextDataInjector injector = ContextDataInjectorFactory.createInjector();
6874 private Map<String, Level> levelMap = new HashMap<>();
6975
7076 private DynamicThresholdFilter(final String key, final Map<String, Level> pairs, final Level defaultLevel,
112118 return true;
113119 }
114120
115 private Result filter(final Level level, final Map<String, String> contextMap) {
116 final String value = contextMap.get(key);
121 private Result filter(final Level level, final ReadOnlyStringMap contextMap) {
122 final String value = contextMap.getValue(key);
117123 if (value != null) {
118124 Level ctxLevel = levelMap.get(value);
119125 if (ctxLevel == null) {
127133
128134 @Override
129135 public Result filter(final LogEvent event) {
130 return filter(event.getLevel(), event.getContextMap());
136 return filter(event.getLevel(), event.getContextData());
131137 }
132138
133139 @Override
134140 public Result filter(final Logger logger, final Level level, final Marker marker, final Message msg,
135141 final Throwable t) {
136 return filter(level, ThreadContext.getContext());
142 return filter(level, currentContextData());
137143 }
138144
139145 @Override
140146 public Result filter(final Logger logger, final Level level, final Marker marker, final Object msg,
141147 final Throwable t) {
142 return filter(level, ThreadContext.getContext());
148 return filter(level, currentContextData());
143149 }
144150
145151 @Override
146152 public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
147153 final Object... params) {
148 return filter(level, ThreadContext.getContext());
154 return filter(level, currentContextData());
155 }
156
157 private ReadOnlyStringMap currentContextData() {
158 return injector.rawContextData();
159 }
160
161 @Override
162 public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
163 final Object p0) {
164 return filter(level, currentContextData());
165
166 }
167
168 @Override
169 public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
170 final Object p0, final Object p1) {
171 return filter(level, currentContextData());
172
173 }
174
175 @Override
176 public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
177 final Object p0, final Object p1, final Object p2) {
178 return filter(level, currentContextData());
179
180 }
181
182 @Override
183 public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
184 final Object p0, final Object p1, final Object p2, final Object p3) {
185 return filter(level, currentContextData());
186
187 }
188
189 @Override
190 public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
191 final Object p0, final Object p1, final Object p2, final Object p3,
192 final Object p4) {
193 return filter(level, currentContextData());
194
195 }
196
197 @Override
198 public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
199 final Object p0, final Object p1, final Object p2, final Object p3,
200 final Object p4, final Object p5) {
201 return filter(level, currentContextData());
202
203 }
204
205 @Override
206 public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
207 final Object p0, final Object p1, final Object p2, final Object p3,
208 final Object p4, final Object p5, final Object p6) {
209 return filter(level, currentContextData());
210
211 }
212
213 @Override
214 public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
215 final Object p0, final Object p1, final Object p2, final Object p3,
216 final Object p4, final Object p5, final Object p6,
217 final Object p7) {
218 return filter(level, currentContextData());
219
220 }
221
222 @Override
223 public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
224 final Object p0, final Object p1, final Object p2, final Object p3,
225 final Object p4, final Object p5, final Object p6,
226 final Object p7, final Object p8) {
227 return filter(level, currentContextData());
228
229 }
230
231 @Override
232 public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
233 final Object p0, final Object p1, final Object p2, final Object p3,
234 final Object p4, final Object p5, final Object p6,
235 final Object p7, final Object p8, final Object p9) {
236 return filter(level, currentContextData());
237
149238 }
150239
151240 public String getKey() {
2727 import org.apache.logging.log4j.message.Message;
2828
2929 /**
30 * This filter returns the onMatch result if the level in the LogEvent is in the
31 * range of the configured min and max levels, otherwise it returns onMismatch
32 * value . For example, if the filter is configured with Level ERROR and Level
33 * INFO and the LogEvent contains Level WARN then the onMatch value will be
34 * returned since WARN events are in between ERROR and INFO.
35 *
36 * The default Levels are both ERROR.
30 * This filter returns the {@code onMatch} result if the level in the {@code LogEvent} is in the range of the configured
31 * min and max levels, otherwise it returns {@code onMismatch} value . For example, if the filter is configured with
32 * {@link Level#ERROR} and {@link Level#INFO} and the LogEvent contains {@link Level#WARN} then the onMatch value will
33 * be returned since {@link Level#WARN WARN} events are in between {@link Level#ERROR ERROR} and {@link Level#INFO
34 * INFO}.
35 * <p>
36 * The default Levels are both {@link Level#ERROR ERROR}.
37 * </p>
3738 */
3839 @Plugin(name = "LevelRangeFilter", category = Node.CATEGORY, elementType = Filter.ELEMENT_TYPE, printObject = true)
3940 public final class LevelRangeFilter extends AbstractFilter {
6061 @PluginAttribute("onMismatch") final Result mismatch) {
6162 // @formatter:on
6263 final Level actualMinLevel = minLevel == null ? Level.ERROR : minLevel;
63 final Level actualMaxLevel = minLevel == null ? Level.ERROR : maxLevel;
64 final Level actualMaxLevel = maxLevel == null ? Level.ERROR : maxLevel;
6465 final Result onMatch = match == null ? Result.NEUTRAL : match;
6566 final Result onMismatch = mismatch == null ? Result.DENY : mismatch;
6667 return new LevelRangeFilter(actualMinLevel, actualMaxLevel, onMatch, onMismatch);
3434 import org.apache.logging.log4j.core.util.KeyValuePair;
3535 import org.apache.logging.log4j.message.MapMessage;
3636 import org.apache.logging.log4j.message.Message;
37 import org.apache.logging.log4j.util.ReadOnlyStringMap;
3738
3839 /**
3940 * A Filter that operates on a Map.
7576 boolean match = false;
7677 for (final Map.Entry<String, List<String>> entry : map.entrySet()) {
7778 final String toMatch = data.get(entry.getKey());
78 if (toMatch != null) {
79 match = entry.getValue().contains(toMatch);
80 } else {
81 match = false;
79 match = toMatch != null && entry.getValue().contains(toMatch);
80 if ((!isAnd && match) || (isAnd && !match)) {
81 break;
8282 }
83 }
84 return match;
85 }
86
87 protected boolean filter(final ReadOnlyStringMap data) {
88 boolean match = false;
89 for (final Map.Entry<String, List<String>> entry : map.entrySet()) {
90 final String toMatch = data.getValue(entry.getKey());
91 match = toMatch != null && entry.getValue().contains(toMatch);
8392 if ((!isAnd && match) || (isAnd && !match)) {
8493 break;
8594 }
2323
2424 import org.apache.logging.log4j.Level;
2525 import org.apache.logging.log4j.Marker;
26 import org.apache.logging.log4j.ThreadContext;
2726 import org.apache.logging.log4j.core.Filter;
2827 import org.apache.logging.log4j.core.LogEvent;
2928 import org.apache.logging.log4j.core.Logger;
3029 import org.apache.logging.log4j.core.config.Node;
3130 import org.apache.logging.log4j.core.config.plugins.Plugin;
31 import org.apache.logging.log4j.core.config.plugins.PluginAliases;
3232 import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
3333 import org.apache.logging.log4j.core.config.plugins.PluginElement;
3434 import org.apache.logging.log4j.core.config.plugins.PluginFactory;
35 import org.apache.logging.log4j.core.ContextDataInjector;
36 import org.apache.logging.log4j.core.impl.ContextDataInjectorFactory;
3537 import org.apache.logging.log4j.core.util.KeyValuePair;
3638 import org.apache.logging.log4j.message.Message;
39 import org.apache.logging.log4j.util.ReadOnlyStringMap;
3740
3841 /**
3942 * Filter based on a value in the Thread Context Map (MDC).
4043 */
4144 @Plugin(name = "ThreadContextMapFilter", category = Node.CATEGORY, elementType = Filter.ELEMENT_TYPE, printObject = true)
45 @PluginAliases("ContextMapFilter")
4246 public class ThreadContextMapFilter extends MapFilter {
4347
48 private final ContextDataInjector injector = ContextDataInjectorFactory.createInjector();
4449 private final String key;
4550 private final String value;
4651
8994 private Result filter() {
9095 boolean match = false;
9196 if (useMap) {
97 ReadOnlyStringMap currentContextData = null;
9298 for (final Map.Entry<String, List<String>> entry : getMap().entrySet()) {
93 final String toMatch = ThreadContext.get(entry.getKey());
94 if (toMatch != null) {
95 match = entry.getValue().contains(toMatch);
96 } else {
97 match = false;
99 if (currentContextData == null) {
100 currentContextData = currentContextData();
98101 }
102 final String toMatch = currentContextData.getValue(entry.getKey());
103 match = toMatch != null && entry.getValue().contains(toMatch);
99104 if ((!isAnd() && match) || (isAnd() && !match)) {
100105 break;
101106 }
102107 }
103108 } else {
104 match = value.equals(ThreadContext.get(key));
109 match = value.equals(currentContextData().getValue(key));
105110 }
106111 return match ? onMatch : onMismatch;
107112 }
108113
114 private ReadOnlyStringMap currentContextData() {
115 return injector.rawContextData();
116 }
117
109118 @Override
110119 public Result filter(final LogEvent event) {
111 return super.filter(event.getContextMap()) ? onMatch : onMismatch;
120 return super.filter(event.getContextData()) ? onMatch : onMismatch;
112121 }
113122
114123 @PluginFactory
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.impl;
17
18 import java.lang.reflect.Constructor;
19
20 import org.apache.logging.log4j.core.ContextDataInjector;
21 import org.apache.logging.log4j.core.LogEvent;
22 import org.apache.logging.log4j.util.LoaderUtil;
23 import org.apache.logging.log4j.util.PropertiesUtil;
24 import org.apache.logging.log4j.util.SortedArrayStringMap;
25 import org.apache.logging.log4j.util.StringMap;
26
27 /**
28 * Factory for creating the StringMap instances used to initialize LogEvents'
29 * {@linkplain LogEvent#getContextData() context data}. When context data is
30 * {@linkplain ContextDataInjector injected} into the log event, these StringMap
31 * instances may be either populated with key-value pairs from the context, or completely replaced altogether.
32 * <p>
33 * By default returns {@code SortedArrayStringMap} objects. Can be configured by setting system property
34 * {@code "log4j2.ContextData"} to the fully qualified class name of a class implementing the
35 * {@code StringMap} interface. The class must have a public default constructor, and if possible should also have a
36 * public constructor that takes a single {@code int} argument for the initial capacity.
37 * </p>
38 *
39 * @see LogEvent#getContextData()
40 * @see ContextDataInjector
41 * @see SortedArrayStringMap
42 * @since 2.7
43 */
44 public class ContextDataFactory {
45 private static final String CLASS_NAME = PropertiesUtil.getProperties().getStringProperty("log4j2.ContextData");
46 private static final Class<?> CACHED_CLASS = createCachedClass(CLASS_NAME);
47 private static final Constructor<?> CACHED_CONSTRUCTOR = createCachedConstructor(CACHED_CLASS);
48
49 private static Class<?> createCachedClass(final String className) {
50 if (className == null) {
51 return null;
52 }
53 try {
54 return LoaderUtil.loadClass(className);
55 } catch (final Exception any) {
56 return null;
57 }
58 }
59
60 private static Constructor<?> createCachedConstructor(final Class<?> cachedClass) {
61 if (cachedClass == null) {
62 return null;
63 }
64 try {
65 return cachedClass.getDeclaredConstructor(int.class);
66 } catch (final Exception any) {
67 return null;
68 }
69 }
70
71 @SuppressWarnings("unchecked")
72 public static StringMap createContextData() {
73 if (CACHED_CLASS == null) {
74 return new SortedArrayStringMap();
75 }
76 try {
77 return (StringMap) CACHED_CLASS.newInstance();
78 } catch (final Exception any) {
79 return new SortedArrayStringMap();
80 }
81 }
82
83 @SuppressWarnings("unchecked")
84 public static StringMap createContextData(final int initialCapacity) {
85 if (CACHED_CONSTRUCTOR == null) {
86 return new SortedArrayStringMap(initialCapacity);
87 }
88 try {
89 return (StringMap) CACHED_CONSTRUCTOR.newInstance(initialCapacity);
90 } catch (final Exception any) {
91 return new SortedArrayStringMap(initialCapacity);
92 }
93 }
94 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.impl;
17
18 import org.apache.logging.log4j.ThreadContextAccess;
19 import org.apache.logging.log4j.core.ContextDataInjector;
20 import org.apache.logging.log4j.core.LogEvent;
21 import org.apache.logging.log4j.util.ReadOnlyStringMap;
22 import org.apache.logging.log4j.spi.CopyOnWrite;
23 import org.apache.logging.log4j.spi.ThreadContextMap;
24 import org.apache.logging.log4j.spi.ThreadContextMap2;
25 import org.apache.logging.log4j.status.StatusLogger;
26 import org.apache.logging.log4j.util.LoaderUtil;
27 import org.apache.logging.log4j.util.PropertiesUtil;
28
29 /**
30 * Factory for ContextDataInjectors. Returns a new {@code ContextDataInjector} instance based on the value of system
31 * property {@code log4j2.ContextDataInjector}. Users may use this system property to specify the fully qualified class
32 * name of a class that implements the {@code ContextDataInjector} interface.
33 * If no value was specified this factory method returns one of the injectors defined in
34 * {@code ThreadContextDataInjector}.
35 *
36 * @see ContextDataInjector
37 * @see ReadOnlyStringMap
38 * @see ThreadContextDataInjector
39 * @see LogEvent#getContextData()
40 * @since 2.7
41 */
42 public class ContextDataInjectorFactory {
43
44 /**
45 * Returns a new {@code ContextDataInjector} instance based on the value of system property
46 * {@code log4j2.ContextDataInjector}. If no value was specified this factory method returns one of the
47 * {@code ContextDataInjector} classes defined in {@link ThreadContextDataInjector} which is most appropriate for
48 * the ThreadContext implementation.
49 * <p>
50 * Users may use this system property to specify the fully qualified class name of a class that implements the
51 * {@code ContextDataInjector} interface.
52 * </p><p>
53 * When providing a custom {@code ContextDataInjector}, be aware that this method may be invoked multiple times by
54 * the various components in Log4j that need access to context data.
55 * This includes the object(s) that populate log events, but also various lookups and filters that look at
56 * context data to determine whether an event should be logged.
57 * </p>
58 *
59 * @return a ContextDataInjector that populates the {@code ReadOnlyStringMap} of all {@code LogEvent} objects
60 * @see LogEvent#getContextData()
61 * @see ContextDataInjector
62 */
63 public static ContextDataInjector createInjector() {
64 final String className = PropertiesUtil.getProperties().getStringProperty("log4j2.ContextDataInjector");
65 if (className == null) {
66 return createDefaultInjector();
67 }
68 try {
69 final Class<? extends ContextDataInjector> cls = LoaderUtil.loadClass(className).asSubclass(
70 ContextDataInjector.class);
71 return cls.newInstance();
72 } catch (final Exception dynamicFailed) {
73 final ContextDataInjector result = createDefaultInjector();
74 StatusLogger.getLogger().warn(
75 "Could not create ContextDataInjector for '{}', using default {}: {}",
76 className, result.getClass().getName(), dynamicFailed);
77 return result;
78 }
79 }
80
81 private static ContextDataInjector createDefaultInjector() {
82 final ThreadContextMap threadContextMap = ThreadContextAccess.getThreadContextMap();
83 if (threadContextMap instanceof CopyOnWrite && threadContextMap instanceof ThreadContextMap2) {
84 return new ThreadContextDataInjector.ForCopyOnWriteThreadContextMap();
85 }
86 if (threadContextMap instanceof ThreadContextMap2) {
87 return new ThreadContextDataInjector.ForGarbageFreeThreadContextMap();
88 }
89 return new ThreadContextDataInjector.ForDefaultThreadContextMap();
90 }
91 }
2424 import org.apache.logging.log4j.message.Message;
2525
2626 /**
27 *
27 * Always creates new LogEvent instances.
2828 */
2929 public class DefaultLogEventFactory implements LogEventFactory {
3030
31 private static final DefaultLogEventFactory instance = new DefaultLogEventFactory();
32
33 public static DefaultLogEventFactory getInstance() {
34 return instance;
35 }
3136
3237 /**
3338 * Creates a log event.
1616 package org.apache.logging.log4j.core.impl;
1717
1818 import java.io.Serializable;
19
20 import org.apache.logging.log4j.core.pattern.PlainTextRenderer;
21 import org.apache.logging.log4j.core.pattern.TextRenderer;
1922
2023 /**
2124 * Class and package data used with a {@link StackTraceElement} in a {@link ExtendedStackTraceElement}.
98101 return result;
99102 }
100103
104 public void renderOn(final StringBuilder output, final TextRenderer textRenderer) {
105 if (!this.exact) {
106 textRenderer.render("~", output, "ExtraClassInfo.Inexact");
107 }
108 textRenderer.render("[", output, "ExtraClassInfo.Container");
109 textRenderer.render(this.location, output, "ExtraClassInfo.Location");
110 textRenderer.render(":", output, "ExtraClassInfo.ContainerSeparator");
111 textRenderer.render(this.version, output, "ExtraClassInfo.Version");
112 textRenderer.render("]", output, "ExtraClassInfo.Container");
113 }
114
101115 @Override
102116 public String toString() {
103117 final StringBuilder sb = new StringBuilder();
104 if (!this.exact) {
105 sb.append('~');
106 }
107 sb.append('[');
108 sb.append(this.location);
109 sb.append(':');
110 sb.append(this.version);
111 sb.append(']');
118 renderOn(sb, PlainTextRenderer.getInstance());
112119 return sb.toString();
113120 }
114121
1717
1818 import java.io.Serializable;
1919
20 import org.apache.logging.log4j.core.pattern.PlainTextRenderer;
21 import org.apache.logging.log4j.core.pattern.TextRenderer;
22
2023 /**
2124 * Wraps and extends the concept of the JRE's final class {@link StackTraceElement} by adding more location information.
2225 * <p>
3639
3740 private final StackTraceElement stackTraceElement;
3841
39 public ExtendedStackTraceElement(final StackTraceElement stackTraceElement, final ExtendedClassInfo extraClassInfo) {
42 public ExtendedStackTraceElement(final StackTraceElement stackTraceElement,
43 final ExtendedClassInfo extraClassInfo) {
4044 this.stackTraceElement = stackTraceElement;
4145 this.extraClassInfo = extraClassInfo;
4246 }
4650 */
4751 public ExtendedStackTraceElement(final String declaringClass, final String methodName, final String fileName,
4852 final int lineNumber, final boolean exact, final String location, final String version) {
49 this(new StackTraceElement(declaringClass, methodName, fileName, lineNumber), new ExtendedClassInfo(exact,
50 location, version));
53 this(new StackTraceElement(declaringClass, methodName, fileName, lineNumber),
54 new ExtendedClassInfo(exact, location, version));
5155 }
5256
5357 @Override
128132 return this.stackTraceElement.isNativeMethod();
129133 }
130134
135 void renderOn(final StringBuilder output, final TextRenderer textRenderer) {
136 render(this.stackTraceElement, output, textRenderer);
137 textRenderer.render(" ", output, "Text");
138 this.extraClassInfo.renderOn(output, textRenderer);
139 }
140
141 private void render(final StackTraceElement stElement, final StringBuilder output, final TextRenderer textRenderer) {
142 final String fileName = stElement.getFileName();
143 final int lineNumber = stElement.getLineNumber();
144 textRenderer.render(getClassName(), output, "StackTraceElement.ClassName");
145 textRenderer.render(".", output, "StackTraceElement.ClassMethodSeparator");
146 textRenderer.render(stElement.getMethodName(), output, "StackTraceElement.MethodName");
147 if (stElement.isNativeMethod()) {
148 textRenderer.render("(Native Method)", output, "StackTraceElement.NativeMethod");
149 } else if (fileName != null && lineNumber >= 0) {
150 textRenderer.render("(", output, "StackTraceElement.Container");
151 textRenderer.render(fileName, output, "StackTraceElement.FileName");
152 textRenderer.render(":", output, "StackTraceElement.ContainerSeparator");
153 textRenderer.render(Integer.toString(lineNumber), output, "StackTraceElement.LineNumber");
154 textRenderer.render(")", output, "StackTraceElement.Container");
155 } else if (fileName != null) {
156 textRenderer.render("(", output, "StackTraceElement.Container");
157 textRenderer.render(fileName, output, "StackTraceElement.FileName");
158 textRenderer.render(")", output, "StackTraceElement.Container");
159 } else {
160 textRenderer.render("(", output, "StackTraceElement.Container");
161 textRenderer.render("Unknown Source", output, "StackTraceElement.UnknownSource");
162 textRenderer.render(")", output, "StackTraceElement.Container");
163 }
164 }
165
131166 @Override
132167 public String toString() {
133168 final StringBuilder sb = new StringBuilder();
134 sb.append(this.stackTraceElement);
135 sb.append(" ");
136 sb.append(this.extraClassInfo);
169 renderOn(sb, PlainTextRenderer.getInstance());
137170 return sb.toString();
138171 }
172
139173 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.impl;
17
18 import java.util.Arrays;
19 import java.util.Comparator;
20 import java.util.HashMap;
21 import java.util.Map;
22 import java.util.Objects;
23
24 import org.apache.logging.log4j.util.BiConsumer;
25 import org.apache.logging.log4j.util.ReadOnlyStringMap;
26 import org.apache.logging.log4j.util.StringMap;
27 import org.apache.logging.log4j.util.TriConsumer;
28
29 /**
30 * Provides a read-only {@code StringMap} view of a {@code Map<String, String>}.
31 */
32 class JdkMapAdapterStringMap implements StringMap {
33 private static final long serialVersionUID = -7348247784983193612L;
34 private static final String FROZEN = "Frozen collection cannot be modified";
35 private static final Comparator<? super String> NULL_FIRST_COMPARATOR = new Comparator<String>() {
36 @Override
37 public int compare(final String left, final String right) {
38 if (left == null) {
39 return -1;
40 }
41 if (right == null) {
42 return 1;
43 }
44 return left.compareTo(right);
45 }
46 };
47
48 private final Map<String, String> map;
49 private boolean immutable = false;
50 private transient String[] sortedKeys;
51
52 public JdkMapAdapterStringMap() {
53 this(new HashMap<String, String>());
54 }
55
56 public JdkMapAdapterStringMap(final Map<String, String> map) {
57 this.map = Objects.requireNonNull(map, "map");
58 }
59
60 @Override
61 public Map<String, String> toMap() {
62 return map;
63 }
64
65 private void assertNotFrozen() {
66 if (immutable) {
67 throw new UnsupportedOperationException(FROZEN);
68 }
69 }
70
71 @Override
72 public boolean containsKey(final String key) {
73 return map.containsKey(key);
74 }
75
76 @SuppressWarnings("unchecked")
77 @Override
78 public <V> void forEach(final BiConsumer<String, ? super V> action) {
79 final String[] keys = getSortedKeys();
80 for (int i = 0; i < keys.length; i++) {
81 action.accept(keys[i], (V) map.get(keys[i]));
82 }
83 }
84
85 @SuppressWarnings("unchecked")
86 @Override
87 public <V, S> void forEach(final TriConsumer<String, ? super V, S> action, final S state) {
88 final String[] keys = getSortedKeys();
89 for (int i = 0; i < keys.length; i++) {
90 action.accept(keys[i], (V) map.get(keys[i]), state);
91 }
92 }
93
94 private String[] getSortedKeys() {
95 if (sortedKeys == null) {
96 sortedKeys = map.keySet().toArray(new String[map.size()]);
97 Arrays.sort(sortedKeys, NULL_FIRST_COMPARATOR);
98 }
99 return sortedKeys;
100 }
101
102 @SuppressWarnings("unchecked")
103 @Override
104 public <V> V getValue(final String key) {
105 return (V) map.get(key);
106 }
107
108 @Override
109 public boolean isEmpty() {
110 return map.isEmpty();
111 }
112
113 @Override
114 public int size() {
115 return map.size();
116 }
117
118 @Override
119 public void clear() {
120 if (map.isEmpty()) {
121 return;
122 }
123 assertNotFrozen();
124 map.clear();
125 sortedKeys = null;
126 }
127
128 @Override
129 public void freeze() {
130 immutable = true;
131 }
132
133 @Override
134 public boolean isFrozen() {
135 return immutable;
136 }
137
138 @Override
139 public void putAll(final ReadOnlyStringMap source) {
140 assertNotFrozen();
141 source.forEach(PUT_ALL, map);
142 sortedKeys = null;
143 }
144
145 private static TriConsumer<String, String, Map<String, String>> PUT_ALL = new TriConsumer<String, String, Map<String, String>>() {
146 @Override
147 public void accept(final String key, final String value, final Map<String, String> stringStringMap) {
148 stringStringMap.put(key, value);
149 }
150 };
151
152 @Override
153 public void putValue(final String key, final Object value) {
154 assertNotFrozen();
155 map.put(key, value == null ? null : String.valueOf(value));
156 sortedKeys = null;
157 }
158
159 @Override
160 public void remove(final String key) {
161 if (!map.containsKey(key)) {
162 return;
163 }
164 assertNotFrozen();
165 map.remove(key);
166 sortedKeys = null;
167 }
168
169 @Override
170 public String toString() {
171 final StringBuilder result = new StringBuilder(map.size() * 13);
172 result.append('{');
173 final String[] keys = getSortedKeys();
174 for (int i = 0; i < keys.length; i++) {
175 if (i > 0) {
176 result.append(", ");
177 }
178 result.append(keys[i]).append('=').append(map.get(keys[i]));
179 }
180 result.append('}');
181 return result.toString();
182 }
183
184 @Override
185 public boolean equals(final Object object) {
186 if (object == this) {
187 return true;
188 }
189 if (!(object instanceof JdkMapAdapterStringMap)) {
190 return false;
191 }
192 JdkMapAdapterStringMap other = (JdkMapAdapterStringMap) object;
193 return map.equals(other.map) && immutable == other.immutable;
194 }
195
196 @Override
197 public int hashCode() {
198 return map.hashCode() + (immutable ? 31 : 0);
199 }
200 }
172172 if (ctx.getState() == LifeCycle.State.INITIALIZED) {
173173 if (source != null) {
174174 ContextAnchor.THREAD_CONTEXT.set(ctx);
175 final Configuration config = ConfigurationFactory.getInstance().getConfiguration(source);
175 final Configuration config = ConfigurationFactory.getInstance().getConfiguration(ctx, source);
176176 LOGGER.debug("Starting LoggerContext[name={}] from configuration {}", ctx.getName(), source);
177177 ctx.start(config);
178178 ContextAnchor.THREAD_CONTEXT.remove();
233233 if (ctx.getState() == LifeCycle.State.INITIALIZED) {
234234 if (configLocation != null || name != null) {
235235 ContextAnchor.THREAD_CONTEXT.set(ctx);
236 final Configuration config = ConfigurationFactory.getInstance().getConfiguration(name, configLocation);
236 final Configuration config = ConfigurationFactory.getInstance().getConfiguration(ctx, name, configLocation);
237237 LOGGER.debug("Starting LoggerContext[name={}] from configuration at {}", ctx.getName(), configLocation);
238238 ctx.start(config);
239239 ContextAnchor.THREAD_CONTEXT.remove();
260260 final List<AbstractConfiguration> configurations = new ArrayList<>(configLocations.size());
261261 for (final URI configLocation : configLocations) {
262262 final Configuration currentReadConfiguration = ConfigurationFactory.getInstance()
263 .getConfiguration(name, configLocation);
263 .getConfiguration(ctx, name, configLocation);
264264 if (currentReadConfiguration instanceof AbstractConfiguration) {
265265 configurations.add((AbstractConfiguration) currentReadConfiguration);
266266 } else {
1818 import java.io.InvalidObjectException;
1919 import java.io.ObjectInputStream;
2020 import java.io.Serializable;
21 import java.util.Collections;
22 import java.util.HashMap;
2321 import java.util.List;
2422 import java.util.Map;
2523 import java.util.Objects;
2725 import org.apache.logging.log4j.Level;
2826 import org.apache.logging.log4j.Marker;
2927 import org.apache.logging.log4j.ThreadContext;
28 import org.apache.logging.log4j.core.ContextDataInjector;
29 import org.apache.logging.log4j.util.ReadOnlyStringMap;
3030 import org.apache.logging.log4j.core.LogEvent;
3131 import org.apache.logging.log4j.core.async.RingBufferLogEvent;
3232 import org.apache.logging.log4j.core.config.LoggerConfig;
4040 import org.apache.logging.log4j.message.ReusableMessage;
4141 import org.apache.logging.log4j.message.SimpleMessage;
4242 import org.apache.logging.log4j.message.TimestampMessage;
43 import org.apache.logging.log4j.util.StringMap;
4344 import org.apache.logging.log4j.status.StatusLogger;
4445 import org.apache.logging.log4j.util.Strings;
4546
5152 private static final long serialVersionUID = -8393305700508709443L;
5253 private static final Clock CLOCK = ClockFactory.getClock();
5354 private static volatile NanoClock nanoClock = new DummyNanoClock();
55 private static final ContextDataInjector CONTEXT_DATA_INJECTOR = ContextDataInjectorFactory.createInjector();
56
5457 private final String loggerFqcn;
5558 private final Marker marker;
5659 private final Level level;
5962 private final long timeMillis;
6063 private final transient Throwable thrown;
6164 private ThrowableProxy thrownProxy;
62 private final Map<String, String> contextMap;
65 private final StringMap contextData;
6366 private final ThreadContext.ContextStack contextStack;
6467 private long threadId;
6568 private String threadName;
8184 private Throwable thrown;
8285 private long timeMillis = CLOCK.currentTimeMillis();
8386 private ThrowableProxy thrownProxy;
84 private Map<String, String> contextMap = ThreadContext.getImmutableContext();
87 private StringMap contextData = createContextData((List<Property>) null);
8588 private ThreadContext.ContextStack contextStack = ThreadContext.getImmutableStack();
8689 private long threadId;
8790 private String threadName;
111114 this.message = other.getMessage();
112115 this.timeMillis = other.getTimeMillis();
113116 this.thrown = other.getThrown();
114 this.contextMap = other.getContextMap();
115117 this.contextStack = other.getContextStack();
116118 this.includeLocation = other.isIncludeLocation();
117119 this.endOfBatch = other.isEndOfBatch();
120122 // Avoid unnecessarily initializing thrownProxy, threadName and source if possible
121123 if (other instanceof Log4jLogEvent) {
122124 final Log4jLogEvent evt = (Log4jLogEvent) other;
125 this.contextData = evt.contextData;
123126 this.thrownProxy = evt.thrownProxy;
124127 this.source = evt.source;
125128 this.threadId = evt.threadId;
126129 this.threadName = evt.threadName;
127130 this.threadPriority = evt.threadPriority;
128131 } else {
132 if (other.getContextData() instanceof StringMap) {
133 this.contextData = (StringMap) other.getContextData();
134 } else {
135 if (this.contextData.isFrozen()) {
136 this.contextData = ContextDataFactory.createContextData();
137 } else {
138 this.contextData.clear();
139 }
140 this.contextData.putAll(other.getContextData());
141
142 }
129143 this.thrownProxy = other.getThrownProxy();
130144 this.source = other.getSource();
131145 this.threadId = other.getThreadId();
174188 return this;
175189 }
176190
191 @Deprecated
177192 public Builder setContextMap(final Map<String, String> contextMap) {
178 this.contextMap = contextMap;
193 contextData = ContextDataFactory.createContextData(); // replace with new instance
194 if (contextMap != null) {
195 for (final Map.Entry<String, String> entry : contextMap.entrySet()) {
196 contextData.putValue(entry.getKey(), entry.getValue());
197 }
198 }
199 return this;
200 }
201
202 public Builder setContextData(final StringMap contextData) {
203 this.contextData = contextData;
179204 return this;
180205 }
181206
228253 @Override
229254 public Log4jLogEvent build() {
230255 final Log4jLogEvent result = new Log4jLogEvent(loggerName, marker, loggerFqcn, level, message, thrown,
231 thrownProxy, contextMap, contextStack, threadId, threadName, threadPriority, source, timeMillis, nanoTime);
256 thrownProxy, contextData, contextStack, threadId, threadName, threadPriority, source, timeMillis,
257 nanoTime);
232258 result.setIncludeLocation(includeLocation);
233259 result.setEndOfBatch(endOfBatch);
234260 return result;
281307 * @param loggerFQCN The fully qualified class name of the caller.
282308 * @param level The logging Level.
283309 * @param message The Message.
284 * @param properties properties to add to the event.
310 * @param properties the properties to be merged with ThreadContext key-value pairs into the event's ReadOnlyStringMap.
285311 * @param t A Throwable or null.
286312 */
287313 // This constructor is called from LogEventFactories.
288314 public Log4jLogEvent(final String loggerName, final Marker marker, final String loggerFQCN, final Level level,
289315 final Message message, final List<Property> properties, final Throwable t) {
290 this(loggerName, marker, loggerFQCN, level, message, t, null,
291 createMap(properties),
316 this(loggerName, marker, loggerFQCN, level, message, t, null, createContextData(properties),
292317 ThreadContext.getDepth() == 0 ? null : ThreadContext.cloneStack(), // mutable copy
293318 0, // thread name
294319 null, // stack trace element
315340 * @deprecated use {@link Log4jLogEvent.Builder} instead. This constructor will be removed in an upcoming release.
316341 */
317342 @Deprecated
318 public Log4jLogEvent(final String loggerName, final Marker marker, final String loggerFQCN, final Level level,
343 public Log4jLogEvent(final String loggerName, final Marker marker, final String loggerFQCN, final Level level,
319344 final Message message, final Throwable t, final Map<String, String> mdc,
320345 final ThreadContext.ContextStack ndc, final String threadName,
321346 final StackTraceElement location, final long timestampMillis) {
322 this(loggerName, marker, loggerFQCN, level, message, t, null, mdc, ndc, 0,
347 this(loggerName, marker, loggerFQCN, level, message, t, null, createContextData(mdc), ndc, 0,
323348 threadName, 0, location, timestampMillis, nanoClock.nanoTime());
324349 }
325350
348373 final String threadName, final StackTraceElement location,
349374 final long timestamp) {
350375 final Log4jLogEvent result = new Log4jLogEvent(loggerName, marker, loggerFQCN, level, message, thrown,
351 thrownProxy, mdc, ndc, 0, threadName, 0, location, timestamp, nanoClock.nanoTime());
376 thrownProxy, createContextData(mdc), ndc, 0, threadName, 0, location, timestamp, nanoClock.nanoTime());
352377 return result;
353378 }
354379
361386 * @param message The Message.
362387 * @param thrown A Throwable or null.
363388 * @param thrownProxy A ThrowableProxy or null.
364 * @param contextMap The mapped diagnostic context.
389 * @param contextData The key-value pairs from the context.
365390 * @param contextStack the nested diagnostic context.
366391 * @param threadId the thread ID
367392 * @param threadName The name of the thread.
373398 */
374399 private Log4jLogEvent(final String loggerName, final Marker marker, final String loggerFQCN, final Level level,
375400 final Message message, final Throwable thrown, final ThrowableProxy thrownProxy,
376 final Map<String, String> contextMap, final ThreadContext.ContextStack contextStack, final long threadId,
377 final String threadName, final int threadPriority, final StackTraceElement source, final long timestampMillis,
378 final long nanoTime) {
401 final StringMap contextData, final ThreadContext.ContextStack contextStack, final long threadId,
402 final String threadName, final int threadPriority, final StackTraceElement source,
403 final long timestampMillis, final long nanoTime) {
379404 this.loggerName = loggerName;
380405 this.marker = marker;
381406 this.loggerFqcn = loggerFQCN;
383408 this.message = message;
384409 this.thrown = thrown;
385410 this.thrownProxy = thrownProxy;
386 this.contextMap = contextMap == null ? ThreadContext.EMPTY_MAP : contextMap;
411 this.contextData = contextData == null ? ContextDataFactory.createContextData() : contextData;
387412 this.contextStack = contextStack == null ? ThreadContext.EMPTY_STACK : contextStack;
388413 this.timeMillis = message instanceof TimestampMessage
389414 ? ((TimestampMessage) message).getTimestamp()
398423 this.nanoTime = nanoTime;
399424 }
400425
401 static Map<String, String> createMap(final List<Property> properties) {
402 final Map<String, String> contextMap = ThreadContext.getImmutableContext();
403 if (properties == null || properties.isEmpty()) {
404 return contextMap; // may be ThreadContext.EMPTY_MAP but not null
405 }
406 final Map<String, String> map = new HashMap<>(contextMap);
407
408 for (final Property prop : properties) {
409 if (!map.containsKey(prop.getName())) {
410 map.put(prop.getName(), prop.getValue());
426 private static StringMap createContextData(final Map<String, String> contextMap) {
427 final StringMap result = ContextDataFactory.createContextData();
428 if (contextMap != null) {
429 for (final Map.Entry<String, String> entry : contextMap.entrySet()) {
430 result.putValue(entry.getKey(), entry.getValue());
411431 }
412432 }
413 return Collections.unmodifiableMap(map);
433 return result;
434 }
435
436 private static StringMap createContextData(final List<Property> properties) {
437 final StringMap reusable = ContextDataFactory.createContextData();
438 return CONTEXT_DATA_INJECTOR.injectContextData(properties, reusable);
414439 }
415440
416441 /**
551576 }
552577
553578 /**
579 * Returns the {@code ReadOnlyStringMap} containing context data key-value pairs.
580 * @return the {@code ReadOnlyStringMap} containing context data key-value pairs
581 * @since 2.7
582 */
583 @Override
584 public ReadOnlyStringMap getContextData() {
585 return contextData;
586 }
587 /**
554588 * Returns the immutable copy of the ThreadContext Map.
555589 * @return The context Map.
556590 */
557591 @Override
558592 public Map<String, String> getContextMap() {
559 return contextMap;
593 return contextData.toMap();
560594 }
561595
562596 /**
677711 final LogEventProxy proxy = (LogEventProxy) event;
678712 final Log4jLogEvent result = new Log4jLogEvent(proxy.loggerName, proxy.marker,
679713 proxy.loggerFQCN, proxy.level, proxy.message,
680 proxy.thrown, proxy.thrownProxy, proxy.contextMap, proxy.contextStack, proxy.threadId,
714 proxy.thrown, proxy.thrownProxy, proxy.contextData, proxy.contextStack, proxy.threadId,
681715 proxy.threadName, proxy.threadPriority, proxy.source, proxy.timeMillis, proxy.nanoTime);
682716 result.setEndOfBatch(proxy.isEndOfBatch);
683717 result.setIncludeLocation(proxy.isLocationRequired);
706740 final String n = loggerName.isEmpty() ? LoggerConfig.ROOT : loggerName;
707741 sb.append("Logger=").append(n);
708742 sb.append(" Level=").append(level.name());
709 sb.append(" Message=").append(message.getFormattedMessage());
743 sb.append(" Message=").append(message == null ? null : message.getFormattedMessage());
710744 return sb.toString();
711745 }
712746
745779 if (marker != null ? !marker.equals(that.marker) : that.marker != null) {
746780 return false;
747781 }
748 if (contextMap != null ? !contextMap.equals(that.contextMap) : that.contextMap != null) {
782 if (contextData != null ? !contextData.equals(that.contextData) : that.contextData != null) {
749783 return false;
750784 }
751785 if (!message.equals(that.message)) {
788822 result = 31 * result + (int) (nanoTime ^ (nanoTime >>> 32));
789823 result = 31 * result + (thrown != null ? thrown.hashCode() : 0);
790824 result = 31 * result + (thrownProxy != null ? thrownProxy.hashCode() : 0);
791 result = 31 * result + (contextMap != null ? contextMap.hashCode() : 0);
825 result = 31 * result + (contextData != null ? contextData.hashCode() : 0);
792826 result = 31 * result + (contextStack != null ? contextStack.hashCode() : 0);
793827 result = 31 * result + (int) (threadId ^ (threadId >>> 32));
794828 result = 31 * result + (threadName != null ? threadName.hashCode() : 0);
814848 private final long timeMillis;
815849 private final transient Throwable thrown;
816850 private final ThrowableProxy thrownProxy;
817 private final Map<String, String> contextMap;
851 /** @since 2.7 */
852 private final StringMap contextData;
818853 private final ThreadContext.ContextStack contextStack;
819854 /** @since 2.6 */
820855 private final long threadId;
838873 this.timeMillis = event.timeMillis;
839874 this.thrown = event.thrown;
840875 this.thrownProxy = event.thrownProxy;
841 this.contextMap = event.contextMap;
876 this.contextData = event.contextData;
842877 this.contextStack = event.contextStack;
843878 this.source = includeLocation ? event.getSource() : null;
844879 this.threadId = event.getThreadId();
862897 this.timeMillis = event.getTimeMillis();
863898 this.thrown = event.getThrown();
864899 this.thrownProxy = event.getThrownProxy();
865 this.contextMap = event.getContextMap();
900 this.contextData = memento(event.getContextData());
866901 this.contextStack = event.getContextStack();
867902 this.source = includeLocation ? event.getSource() : null;
868903 this.threadId = event.getThreadId();
873908 this.nanoTime = event.getNanoTime();
874909 }
875910
876 private Message memento(final ReusableMessage message) {
911 private static Message memento(final ReusableMessage message) {
877912 return message.memento();
913 }
914
915 private static StringMap memento(final ReadOnlyStringMap data) {
916 final StringMap result = ContextDataFactory.createContextData();
917 result.putAll(data);
918 return result;
878919 }
879920
880921 /**
883924 */
884925 protected Object readResolve() {
885926 final Log4jLogEvent result = new Log4jLogEvent(loggerName, marker, loggerFQCN, level, message, thrown,
886 thrownProxy, contextMap, contextStack, threadId, threadName, threadPriority, source, timeMillis, nanoTime);
927 thrownProxy, contextData, contextStack, threadId, threadName, threadPriority, source, timeMillis,
928 nanoTime);
887929 result.setEndOfBatch(isEndOfBatch);
888930 result.setIncludeLocation(isLocationRequired);
889931 return result;
2323 import org.apache.logging.log4j.Level;
2424 import org.apache.logging.log4j.Marker;
2525 import org.apache.logging.log4j.ThreadContext;
26 import org.apache.logging.log4j.util.ReadOnlyStringMap;
2627 import org.apache.logging.log4j.core.LogEvent;
2728 import org.apache.logging.log4j.core.util.Constants;
2829 import org.apache.logging.log4j.message.Message;
2930 import org.apache.logging.log4j.message.ParameterizedMessage;
3031 import org.apache.logging.log4j.message.ReusableMessage;
3132 import org.apache.logging.log4j.message.SimpleMessage;
33 import org.apache.logging.log4j.util.StringMap;
3234 import org.apache.logging.log4j.util.Strings;
3335
3436 /**
5355 private Object[] parameters;
5456 private Throwable thrown;
5557 private ThrowableProxy thrownProxy;
56 private Map<String, String> contextMap;
58 private StringMap contextData = ContextDataFactory.createContextData();
5759 private Marker marker;
5860 private String loggerFqcn;
5961 private StackTraceElement source;
6062 private ThreadContext.ContextStack contextStack;
63 transient boolean reserved = false;
6164
6265 public MutableLogEvent() {
6366 this(new StringBuilder(Constants.INITIAL_REUSABLE_MESSAGE_SIZE), new Object[10]);
8689 this.timeMillis = event.getTimeMillis();
8790 this.thrown = event.getThrown();
8891 this.thrownProxy = event.getThrownProxy();
89 this.contextMap = event.getContextMap();
92
93 // NOTE: this ringbuffer event SHOULD NOT keep a reference to the specified
94 // thread-local MutableLogEvent's context data, because then two threads would call
95 // ReadOnlyStringMap.clear() on the same shared instance, resulting in data corruption.
96 this.contextData.putAll(event.getContextData());
97
9098 this.contextStack = event.getContextStack();
9199 this.source = event.isIncludeLocation() ? event.getSource() : null;
92100 this.threadId = event.getThreadId();
100108
101109 /**
102110 * Clears all references this event has to other objects.
111 *
103112 */
104113 public void clear() {
105114 loggerFqcn = null;
110119 thrown = null;
111120 thrownProxy = null;
112121 source = null;
113 contextMap = null;
122 if (contextData != null) {
123 if (contextData.isFrozen()) { // came from CopyOnWrite thread context
124 contextData = null;
125 } else {
126 contextData.clear();
127 }
128 }
114129 contextStack = null;
115130
116131 // ThreadName should not be cleared: this field is set in the ReusableLogEventFactory
332347 return source;
333348 }
334349
350 @SuppressWarnings("unchecked")
351 @Override
352 public ReadOnlyStringMap getContextData() {
353 return contextData;
354 }
355
335356 @Override
336357 public Map<String, String> getContextMap() {
337 return contextMap;
338 }
339
340 public void setContextMap(final Map<String, String> contextMap) {
341 this.contextMap = contextMap;
358 return contextData.toMap();
359 }
360
361 public void setContextData(final StringMap mutableContextData) {
362 this.contextData = mutableContextData;
342363 }
343364
344365 @Override
433454 * @param builder the builder whose fields to populate
434455 */
435456 public void initializeBuilder(final Log4jLogEvent.Builder builder) {
436 builder.setContextMap(contextMap) //
457 builder.setContextData(contextData) //
437458 .setContextStack(contextStack) //
438459 .setEndOfBatch(endOfBatch) //
439460 .setIncludeLocation(includeLocation) //
2020 import org.apache.logging.log4j.Level;
2121 import org.apache.logging.log4j.Marker;
2222 import org.apache.logging.log4j.ThreadContext;
23 import org.apache.logging.log4j.core.ContextDataInjector;
2324 import org.apache.logging.log4j.core.LogEvent;
2425 import org.apache.logging.log4j.core.async.ThreadNameCachingStrategy;
2526 import org.apache.logging.log4j.core.config.Property;
2728 import org.apache.logging.log4j.core.util.ClockFactory;
2829 import org.apache.logging.log4j.message.Message;
2930 import org.apache.logging.log4j.message.TimestampMessage;
31 import org.apache.logging.log4j.util.StringMap;
3032
3133 /**
3234 * Garbage-free LogEventFactory that reuses a single mutable log event.
3739 private static final Clock CLOCK = ClockFactory.getClock();
3840
3941 private static ThreadLocal<MutableLogEvent> mutableLogEventThreadLocal = new ThreadLocal<>();
42 private final ContextDataInjector injector = ContextDataInjectorFactory.createInjector();
43
4044 /**
4145 * Creates a log event.
4246 *
5458 final String fqcn, final Level level, final Message message,
5559 final List<Property> properties, final Throwable t) {
5660 MutableLogEvent result = mutableLogEventThreadLocal.get();
57 if (result == null) {
61 if (result == null || result.reserved) {
62 final boolean initThreadLocal = result == null;
5863 result = new MutableLogEvent();
5964
6065 // usually no need to re-initialize thread-specific fields since the event is stored in a ThreadLocal
6166 result.setThreadId(Thread.currentThread().getId());
6267 result.setThreadName(Thread.currentThread().getName()); // Thread.getName() allocates Objects on each call
6368 result.setThreadPriority(Thread.currentThread().getPriority());
64 mutableLogEventThreadLocal.set(result);
69 if (initThreadLocal) {
70 mutableLogEventThreadLocal.set(result);
71 }
6572 }
73 result.reserved = true;
6674 result.clear(); // ensure any previously cached values (thrownProxy, source, etc.) are cleared
6775
6876 result.setLoggerName(loggerName);
7179 result.setLevel(level == null ? Level.OFF : level);
7280 result.setMessage(message);
7381 result.setThrown(t);
74 result.setContextMap(Log4jLogEvent.createMap(properties));
75 result.setContextStack(ThreadContext.getDepth() == 0 ? null : ThreadContext.cloneStack());// mutable copy
82 result.setContextData(injector.injectContextData(properties, (StringMap) result.getContextData()));
83 result.setContextStack(ThreadContext.getDepth() == 0 ? ThreadContext.EMPTY_STACK : ThreadContext.cloneStack());// mutable copy
7684 result.setTimeMillis(message instanceof TimestampMessage
7785 ? ((TimestampMessage) message).getTimestamp()
7886 : CLOCK.currentTimeMillis());
8492 }
8593 return result;
8694 }
95
96 /**
97 * Switches the {@code reserved} flag off if the specified event is a MutableLogEvent, otherwise does nothing.
98 * This flag is used internally to verify that a reusable log event is no longer in use and can be reused.
99 * @param logEvent the log event to make available again
100 * @since 2.7
101 */
102 public static void release(final LogEvent logEvent) { // LOG4J2-1583
103 if (logEvent instanceof MutableLogEvent) {
104 ((MutableLogEvent) logEvent).reserved = false;
105 }
106 }
87107 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.impl;
17
18 import java.util.HashMap;
19 import java.util.List;
20 import java.util.Map;
21
22 import org.apache.logging.log4j.ThreadContext;
23 import org.apache.logging.log4j.ThreadContextAccess;
24 import org.apache.logging.log4j.core.ContextDataInjector;
25 import org.apache.logging.log4j.core.config.Property;
26 import org.apache.logging.log4j.spi.ThreadContextMap;
27 import org.apache.logging.log4j.util.ReadOnlyStringMap;
28 import org.apache.logging.log4j.util.StringMap;
29
30 /**
31 * {@code ThreadContextDataInjector} contains a number of strategies for copying key-value pairs from the various
32 * {@code ThreadContext} map implementations into a {@code StringMap}. In the case of duplicate keys,
33 * thread context values overwrite configuration {@code Property} values.
34 * <p>
35 * These are the default {@code ContextDataInjector} objects returned by the {@link ContextDataInjectorFactory}.
36 * </p>
37 *
38 * @see org.apache.logging.log4j.ThreadContext
39 * @see Property
40 * @see ReadOnlyStringMap
41 * @see ContextDataInjector
42 * @see ContextDataInjectorFactory
43 * @since 2.7
44 */
45 public class ThreadContextDataInjector {
46
47 /**
48 * Default {@code ContextDataInjector} for the legacy {@code Map<String, String>}-based ThreadContext (which is
49 * also the ThreadContext implementation used for web applications).
50 * <p>
51 * This injector always puts key-value pairs into the specified reusable StringMap.
52 */
53 public static class ForDefaultThreadContextMap implements ContextDataInjector {
54 private static final StringMap EMPTY_STRING_MAP = ContextDataFactory.createContextData();
55 static {
56 EMPTY_STRING_MAP.freeze();
57 }
58
59 /**
60 * Puts key-value pairs from both the specified list of properties as well as the thread context into the
61 * specified reusable StringMap.
62 *
63 * @param props list of configuration properties, may be {@code null}
64 * @param ignore a {@code StringMap} instance from the log event
65 * @return a {@code StringMap} combining configuration properties with thread context data
66 */
67 @Override
68 public StringMap injectContextData(final List<Property> props, final StringMap ignore) {
69
70 final Map<String, String> copy = ThreadContext.getImmutableContext();
71
72 // The DefaultThreadContextMap stores context data in a Map<String, String>.
73 // This is a copy-on-write data structure so we are sure ThreadContext changes will not affect our copy.
74 // If there are no configuration properties returning a thin wrapper around the copy
75 // is faster than copying the elements into the LogEvent's reusable StringMap.
76 if (props == null || props.isEmpty()) {
77 // this will replace the LogEvent's context data with the returned instance.
78 // NOTE: must mark as frozen or downstream components may attempt to modify (UnsupportedOperationEx)
79 return copy.isEmpty() ? EMPTY_STRING_MAP : frozenStringMap(copy);
80 }
81 // If the list of Properties is non-empty we need to combine the properties and the ThreadContext
82 // data. Note that we cannot reuse the specified StringMap: some Loggers may have properties defined
83 // and others not, so the LogEvent's context data may have been replaced with an immutable copy from
84 // the ThreadContext - this will throw an UnsupportedOperationException if we try to modify it.
85 final StringMap result = new JdkMapAdapterStringMap(new HashMap<>(copy));
86 for (int i = 0; i < props.size(); i++) {
87 final Property prop = props.get(i);
88 if (!copy.containsKey(prop.getName())) {
89 result.putValue(prop.getName(), prop.getValue());
90 }
91 }
92 result.freeze();
93 return result;
94 }
95
96 private static JdkMapAdapterStringMap frozenStringMap(final Map<String, String> copy) {
97 final JdkMapAdapterStringMap result = new JdkMapAdapterStringMap(copy);
98 result.freeze();
99 return result;
100 }
101
102 @Override
103 public ReadOnlyStringMap rawContextData() {
104 final ThreadContextMap map = ThreadContextAccess.getThreadContextMap();
105 if (map instanceof ReadOnlyStringMap) {
106 return (ReadOnlyStringMap) map;
107 }
108 return map.isEmpty() ? EMPTY_STRING_MAP : new JdkMapAdapterStringMap(map.getImmutableMapOrNull());
109 }
110 }
111
112 /**
113 * The {@code ContextDataInjector} used when the ThreadContextMap implementation is a garbage-free
114 * StringMap-based data structure.
115 * <p>
116 * This injector always puts key-value pairs into the specified reusable StringMap.
117 */
118 public static class ForGarbageFreeThreadContextMap implements ContextDataInjector {
119 /**
120 * Puts key-value pairs from both the specified list of properties as well as the thread context into the
121 * specified reusable StringMap.
122 *
123 * @param props list of configuration properties, may be {@code null}
124 * @param reusable a {@code StringMap} instance that may be reused to avoid creating temporary objects
125 * @return a {@code StringMap} combining configuration properties with thread context data
126 */
127 @Override
128 public StringMap injectContextData(final List<Property> props, final StringMap reusable) {
129 // When the ThreadContext is garbage-free, we must copy its key-value pairs into the specified reusable
130 // StringMap. We cannot return the ThreadContext's internal data structure because it may be modified later
131 // and such modifications should not be reflected in the log event.
132 copyProperties(props, reusable);
133
134 final ReadOnlyStringMap immutableCopy = ThreadContextAccess.getThreadContextMap2().getReadOnlyContextData();
135 reusable.putAll(immutableCopy);
136 return reusable;
137 }
138
139 @Override
140 public ReadOnlyStringMap rawContextData() {
141 return ThreadContextAccess.getThreadContextMap2().getReadOnlyContextData();
142 }
143 }
144
145 /**
146 * The {@code ContextDataInjector} used when the ThreadContextMap implementation is a copy-on-write
147 * StringMap-based data structure.
148 * <p>
149 * If there are no configuration properties, this injector will return the thread context's internal data
150 * structure. Otherwise the configuration properties are combined with the thread context key-value pairs into the
151 * specified reusable StringMap.
152 */
153 public static class ForCopyOnWriteThreadContextMap implements ContextDataInjector {
154 /**
155 * If there are no configuration properties, this injector will return the thread context's internal data
156 * structure. Otherwise the configuration properties are combined with the thread context key-value pairs into the
157 * specified reusable StringMap.
158 *
159 * @param props list of configuration properties, may be {@code null}
160 * @param ignore a {@code StringMap} instance from the log event
161 * @return a {@code StringMap} combining configuration properties with thread context data
162 */
163 @Override
164 public StringMap injectContextData(final List<Property> props, final StringMap ignore) {
165 // If there are no configuration properties we want to just return the ThreadContext's StringMap:
166 // it is a copy-on-write data structure so we are sure ThreadContext changes will not affect our copy.
167 final StringMap immutableCopy = ThreadContextAccess.getThreadContextMap2().getReadOnlyContextData();
168 if (props == null || props.isEmpty()) {
169 return immutableCopy; // this will replace the LogEvent's context data with the returned instance
170 }
171 // However, if the list of Properties is non-empty we need to combine the properties and the ThreadContext
172 // data. Note that we cannot reuse the specified StringMap: some Loggers may have properties defined
173 // and others not, so the LogEvent's context data may have been replaced with an immutable copy from
174 // the ThreadContext - this will throw an UnsupportedOperationException if we try to modify it.
175 final StringMap result = ContextDataFactory.createContextData(props.size() + immutableCopy.size());
176 copyProperties(props, result);
177 result.putAll(immutableCopy);
178 return result;
179 }
180
181 @Override
182 public ReadOnlyStringMap rawContextData() {
183 return ThreadContextAccess.getThreadContextMap2().getReadOnlyContextData();
184 }
185 }
186
187 /**
188 * Copies key-value pairs from the specified property list into the specified {@code StringMap}.
189 *
190 * @param properties list of configuration properties, may be {@code null}
191 * @param result the {@code StringMap} object to add the key-values to. Must be non-{@code null}.
192 */
193 public static void copyProperties(final List<Property> properties, final StringMap result) {
194 if (properties != null) {
195 for (int i = 0; i < properties.size(); i++) {
196 final Property prop = properties.get(i);
197 result.putValue(prop.getName(), prop.getValue());
198 }
199 }
200 }
201 }
1919 import java.util.List;
2020 import java.util.Scanner;
2121
22 import org.apache.logging.log4j.core.util.Constants;
22 import org.apache.logging.log4j.core.pattern.JAnsiTextRenderer;
23 import org.apache.logging.log4j.core.pattern.TextRenderer;
24 import org.apache.logging.log4j.core.pattern.PlainTextRenderer;
25 import org.apache.logging.log4j.core.util.Loader;
2326 import org.apache.logging.log4j.core.util.Patterns;
27 import org.apache.logging.log4j.status.StatusLogger;
2428 import org.apache.logging.log4j.util.Strings;
2529
2630 /**
5155 private static final String SHORT = "short";
5256
5357 /**
58 * ANSI renderer
59 */
60 private final TextRenderer textRenderer;
61
62 /**
5463 * The number of lines to write.
5564 */
5665 private final int lines;
6372 /**
6473 * The list of packages to filter.
6574 */
66 private final List<String> packages;
75 private final List<String> ignorePackages;
6776
6877 public static final String CLASS_NAME = "short.className";
6978 public static final String METHOD_NAME = "short.methodName";
7382 public static final String LOCALIZED_MESSAGE = "short.localizedMessage";
7483
7584 /**
76 * Construct the options for printing stack trace.
77 * @param lines The number of lines.
78 * @param separator The stack trace separator.
79 * @param packages The packages to filter.
80 */
81 protected ThrowableFormatOptions(final int lines, final String separator, final List<String> packages) {
85 * Constructs the options for printing stack trace.
86 *
87 * @param lines
88 * The number of lines.
89 * @param separator
90 * The stack trace separator.
91 * @param ignorePackages
92 * The packages to filter.
93 * @param textRenderer
94 * The ANSI renderer
95 */
96 protected ThrowableFormatOptions(final int lines, final String separator, final List<String> ignorePackages,
97 final TextRenderer textRenderer) {
8298 this.lines = lines;
83 this.separator = separator == null ? Constants.LINE_SEPARATOR : separator;
84 this.packages = packages;
85 }
86
87 /**
88 * Construct the options for printing stack trace.
89 * @param packages The packages to filter.
99 this.separator = separator == null ? Strings.LINE_SEPARATOR : separator;
100 this.ignorePackages = ignorePackages;
101 this.textRenderer = textRenderer == null ? PlainTextRenderer.getInstance() : textRenderer;
102 }
103
104 /**
105 * Constructs the options for printing stack trace.
106 *
107 * @param packages
108 * The packages to filter.
90109 */
91110 protected ThrowableFormatOptions(final List<String> packages) {
92 this(DEFAULT_LINES, null, packages);
93 }
94
95 /**
96 * Construct the options for printing stack trace.
111 this(DEFAULT_LINES, null, packages, null);
112 }
113
114 /**
115 * Constructs the options for printing stack trace.
97116 */
98117 protected ThrowableFormatOptions() {
99 this(DEFAULT_LINES, null, null);
118 this(DEFAULT_LINES, null, null, null);
100119 }
101120
102121 /**
103122 * Returns the number of lines to write.
123 *
104124 * @return The number of lines to write.
105125 */
106126 public int getLines() {
109129
110130 /**
111131 * Returns the stack trace separator.
132 *
112133 * @return The stack trace separator.
113134 */
114135 public String getSeparator() {
116137 }
117138
118139 /**
119 * Returns the list of packages to filter.
120 * @return The list of packages to filter.
121 */
122 public List<String> getPackages() {
123 return this.packages;
140 * Returns the message rendered.
141 *
142 * @return the message rendered.
143 */
144 public TextRenderer getTextRenderer() {
145 return textRenderer;
146 }
147
148 /**
149 * Returns the list of packages to ignore (filter out).
150 *
151 * @return The list of packages to ignore (filter out).
152 */
153 public List<String> getIgnorePackages() {
154 return this.ignorePackages;
124155 }
125156
126157 /**
127158 * Determines if all lines should be printed.
159 *
128160 * @return true for all lines, false otherwise.
129161 */
130162 public boolean allLines() {
133165
134166 /**
135167 * Determines if any lines should be printed.
168 *
136169 * @return true for any lines, false otherwise.
137170 */
138171 public boolean anyLines() {
141174
142175 /**
143176 * Returns the minimum between the lines and the max lines.
144 * @param maxLines The maximum number of lines.
177 *
178 * @param maxLines
179 * The maximum number of lines.
145180 * @return The number of lines to print.
146181 */
147182 public int minLines(final int maxLines) {
150185
151186 /**
152187 * Determines if there are any packages to filter.
188 *
153189 * @return true if there are packages, false otherwise.
154190 */
155191 public boolean hasPackages() {
156 return this.packages != null && !this.packages.isEmpty();
192 return this.ignorePackages != null && !this.ignorePackages.isEmpty();
157193 }
158194
159195 /**
162198 @Override
163199 public String toString() {
164200 final StringBuilder s = new StringBuilder();
165 s.append('{').append(allLines() ? FULL : this.lines == 2 ? SHORT : anyLines() ? String.valueOf(this.lines) : NONE).append('}');
201 s.append('{')
202 .append(allLines() ? FULL : this.lines == 2 ? SHORT : anyLines() ? String.valueOf(this.lines) : NONE)
203 .append('}');
166204 s.append("{separator(").append(this.separator).append(")}");
167205 if (hasPackages()) {
168206 s.append("{filters(");
169 for (final String p : this.packages) {
207 for (final String p : this.ignorePackages) {
170208 s.append(p).append(',');
171209 }
172210 s.deleteCharAt(s.length() - 1);
176214 }
177215
178216 /**
179 * Create a new instance based on the array of options.
180 * @param options The array of options.
217 * Creates a new instance based on the array of options.
218 *
219 * @param options
220 * The array of options.
221 * @return A new initialized instance.
181222 */
182223 public static ThrowableFormatOptions newInstance(String[] options) {
183224 if (options == null || options.length == 0) {
186227 // NOTE: The following code is present for backward compatibility
187228 // and was copied from Extended/RootThrowablePatternConverter.
188229 // This supports a single option with the format:
189 // %xEx{["none"|"short"|"full"|depth],[filters(packages)}
230 // %xEx{["none"|"short"|"full"|depth],[filters(packages)}
190231 // However, the convention for multiple options should be:
191 // %xEx{["none"|"short"|"full"|depth]}[{filters(packages)}]
232 // %xEx{["none"|"short"|"full"|depth]}[{filters(packages)}]
192233 if (options.length == 1 && Strings.isNotEmpty(options[0])) {
193234 final String[] opts = options[0].split(Patterns.COMMA_SEPARATOR, 2);
194235 final String first = opts[0].trim();
195236 try (final Scanner scanner = new Scanner(first)) {
196 if (opts.length > 1
197 && (first.equalsIgnoreCase(FULL) || first.equalsIgnoreCase(SHORT)
198 || first.equalsIgnoreCase(NONE) || scanner.hasNextInt())) {
199 options = new String[] {
200 first,
201 opts[1].trim() };
237 if (opts.length > 1 && (first.equalsIgnoreCase(FULL) || first.equalsIgnoreCase(SHORT)
238 || first.equalsIgnoreCase(NONE) || scanner.hasNextInt())) {
239 options = new String[] { first, opts[1].trim() };
202240 }
203241 }
204242 }
205243
206244 int lines = DEFAULT.lines;
207245 String separator = DEFAULT.separator;
208 List<String> packages = DEFAULT.packages;
246 List<String> packages = DEFAULT.ignorePackages;
247 TextRenderer ansiRenderer = DEFAULT.textRenderer;
209248 for (final String rawOption : options) {
210249 if (rawOption != null) {
211250 final String option = rawOption.trim();
229268 }
230269 } else if (option.equalsIgnoreCase(NONE)) {
231270 lines = 0;
232 } else if (option.equalsIgnoreCase(SHORT) || option.equalsIgnoreCase(CLASS_NAME) ||
233 option.equalsIgnoreCase(METHOD_NAME) || option.equalsIgnoreCase(LINE_NUMBER) ||
234 option.equalsIgnoreCase(FILE_NAME) || option.equalsIgnoreCase(MESSAGE) ||
235 option.equalsIgnoreCase(LOCALIZED_MESSAGE)) {
271 } else if (option.equalsIgnoreCase(SHORT) || option.equalsIgnoreCase(CLASS_NAME)
272 || option.equalsIgnoreCase(METHOD_NAME) || option.equalsIgnoreCase(LINE_NUMBER)
273 || option.equalsIgnoreCase(FILE_NAME) || option.equalsIgnoreCase(MESSAGE)
274 || option.equalsIgnoreCase(LOCALIZED_MESSAGE)) {
236275 lines = 2;
276 } else if (option.startsWith("ansi(") && option.endsWith(")") || option.equals("ansi")) {
277 if (Loader.isJansiAvailable()) {
278 final String styleMapStr = option.equals("ansi") ? Strings.EMPTY
279 : option.substring("ansi(".length(), option.length() - 1);
280 ansiRenderer = new JAnsiTextRenderer(new String[] { null, styleMapStr },
281 JAnsiTextRenderer.DefaultExceptionStyleMap);
282 } else {
283 StatusLogger.getLogger().warn(
284 "You requested ANSI exception rendering but JANSI is not on the classpath. Please see https://logging.apache.org/log4j/2.x/runtime-dependencies.html");
285 }
237286 } else if (!option.equalsIgnoreCase(FULL)) {
238287 lines = Integer.parseInt(option);
239288 }
240289 }
241290 }
242 return new ThrowableFormatOptions(lines, separator, packages);
243 }
291 return new ThrowableFormatOptions(lines, separator, packages, ansiRenderer);
292 }
293
244294 }
2727 import java.util.Set;
2828 import java.util.Stack;
2929
30 import org.apache.logging.log4j.core.util.Loader;
30 import org.apache.logging.log4j.core.pattern.PlainTextRenderer;
31 import org.apache.logging.log4j.core.pattern.TextRenderer;
3132 import org.apache.logging.log4j.status.StatusLogger;
33 import org.apache.logging.log4j.util.LoaderUtil;
3234 import org.apache.logging.log4j.util.ReflectionUtil;
3335 import org.apache.logging.log4j.util.Strings;
3436
3537 /**
3638 * Wraps a Throwable to add packaging information about each stack trace element.
37 *
39 *
3840 * <p>
3941 * A proxy is used to represent a throwable that may not exist in a different class loader or JVM. When an application
4042 * deserializes a ThrowableProxy, the throwable may not be set, but the throwable's information is preserved in other
4143 * fields of the proxy like the message and stack trace.
4244 * </p>
43 *
45 *
4446 * <p>
4547 * TODO: Move this class to org.apache.logging.log4j.core because it is used from LogEvent.
4648 * </p>
5052 */
5153 public class ThrowableProxy implements Serializable {
5254
53 private static final String CAUSED_BY_LABEL = "Caused by: ";
54 private static final String SUPPRESSED_LABEL = "Suppressed: ";
55 private static final String TAB = "\t";
56 private static final String CAUSED_BY_LABEL = "Caused by: ";
57 private static final String SUPPRESSED_LABEL = "Suppressed: ";
5558 private static final String WRAPPED_BY_LABEL = "Wrapped by: ";
5659
57 /**
60 /**
5861 * Cached StackTracePackageElement and ClassLoader.
5962 * <p>
6063 * Consider this class private.
7376 private static final ThrowableProxy[] EMPTY_THROWABLE_PROXY_ARRAY = new ThrowableProxy[0];
7477
7578 private static final char EOL = '\n';
79
80 private static final String EOL_STR = String.valueOf(EOL);
7681
7782 private static final long serialVersionUID = -2752771578252251910L;
7883
108113
109114 /**
110115 * Constructs the wrapper for the Throwable that includes packaging data.
111 *
112 * @param throwable
113 * The Throwable to wrap, must not be null.
116 *
117 * @param throwable The Throwable to wrap, must not be null.
114118 */
115119 public ThrowableProxy(final Throwable throwable) {
116120 this(throwable, null);
118122
119123 /**
120124 * Constructs the wrapper for the Throwable that includes packaging data.
121 *
122 * @param throwable
123 * The Throwable to wrap, must not be null.
124 * @param visited
125 * The set of visited suppressed exceptions.
125 *
126 * @param throwable The Throwable to wrap, must not be null.
127 * @param visited The set of visited suppressed exceptions.
126128 */
127129 private ThrowableProxy(final Throwable throwable, final Set<Throwable> visited) {
128130 this.throwable = throwable;
134136 this.extendedStackTrace = this.toExtendedStackTrace(stack, map, null, throwable.getStackTrace());
135137 final Throwable throwableCause = throwable.getCause();
136138 final Set<Throwable> causeVisited = new HashSet<>(1);
137 this.causeProxy = throwableCause == null ? null : new ThrowableProxy(throwable, stack, map, throwableCause, visited, causeVisited);
139 this.causeProxy = throwableCause == null ? null : new ThrowableProxy(throwable, stack, map, throwableCause,
140 visited, causeVisited);
138141 this.suppressedProxies = this.toSuppressedProxies(throwable, visited);
139142 }
140143
141144 /**
142145 * Constructs the wrapper for a Throwable that is referenced as the cause by another Throwable.
143 *
144 * @param parent
145 * The Throwable referencing this Throwable.
146 * @param stack
147 * The Class stack.
148 * @param map
149 * The cache containing the packaging data.
150 * @param cause
151 * The Throwable to wrap.
146 *
147 * @param parent The Throwable referencing this Throwable.
148 * @param stack The Class stack.
149 * @param map The cache containing the packaging data.
150 * @param cause The Throwable to wrap.
152151 * @param suppressedVisited TODO
153 * @param causeVisited TODO
152 * @param causeVisited TODO
154153 */
155154 private ThrowableProxy(final Throwable parent, final Stack<Class<?>> stack, final Map<String, CacheEntry> map,
156 final Throwable cause, final Set<Throwable> suppressedVisited, final Set<Throwable> causeVisited) {
155 final Throwable cause, final Set<Throwable> suppressedVisited,
156 final Set<Throwable> causeVisited) {
157157 causeVisited.add(cause);
158158 this.throwable = cause;
159159 this.name = cause.getClass().getName();
162162 this.extendedStackTrace = this.toExtendedStackTrace(stack, map, parent.getStackTrace(), cause.getStackTrace());
163163 final Throwable causeCause = cause.getCause();
164164 this.causeProxy = causeCause == null || causeVisited.contains(causeCause) ? null : new ThrowableProxy(parent,
165 stack, map, causeCause, suppressedVisited, causeVisited);
165 stack, map, causeCause, suppressedVisited, causeVisited);
166166 this.suppressedProxies = this.toSuppressedProxies(cause, suppressedVisited);
167167 }
168168
204204 return true;
205205 }
206206
207 private void formatCause(final StringBuilder sb, final String prefix, final ThrowableProxy cause, final List<String> ignorePackages) {
208 formatThrowableProxy(sb, prefix, CAUSED_BY_LABEL, cause, ignorePackages);
209 }
210
211 private void formatThrowableProxy(final StringBuilder sb, final String prefix, final String causeLabel,
212 final ThrowableProxy throwableProxy, final List<String> ignorePackages) {
213 if (throwableProxy == null) {
214 return;
215 }
216 sb.append(prefix).append(causeLabel).append(throwableProxy).append(EOL);
217 this.formatElements(sb, prefix, throwableProxy.commonElementCount,
218 throwableProxy.getStackTrace(), throwableProxy.extendedStackTrace, ignorePackages);
219 this.formatSuppressed(sb, prefix + "\t", throwableProxy.suppressedProxies, ignorePackages);
220 this.formatCause(sb, prefix, throwableProxy.causeProxy, ignorePackages);
221 }
222
223 private void formatSuppressed(final StringBuilder sb, final String prefix, final ThrowableProxy[] suppressedProxies,
224 final List<String> ignorePackages) {
225 if (suppressedProxies == null) {
226 return;
227 }
228 for (final ThrowableProxy suppressedProxy : suppressedProxies) {
229 final ThrowableProxy cause = suppressedProxy;
230 formatThrowableProxy(sb, prefix, SUPPRESSED_LABEL, cause, ignorePackages);
231 }
232 }
233
234 private void formatElements(final StringBuilder sb, final String prefix, final int commonCount,
235 final StackTraceElement[] causedTrace, final ExtendedStackTraceElement[] extStackTrace,
236 final List<String> ignorePackages) {
237 if (ignorePackages == null || ignorePackages.isEmpty()) {
238 for (final ExtendedStackTraceElement element : extStackTrace) {
239 this.formatEntry(element, sb, prefix);
240 }
241 } else {
242 int count = 0;
243 for (int i = 0; i < extStackTrace.length; ++i) {
244 if (!this.ignoreElement(causedTrace[i], ignorePackages)) {
245 if (count > 0) {
246 appendSuppressedCount(sb, prefix, count);
247 count = 0;
248 }
249 this.formatEntry(extStackTrace[i], sb, prefix);
250 } else {
251 ++count;
252 }
253 }
254 if (count > 0) {
255 appendSuppressedCount(sb, prefix, count);
256 }
257 }
258 if (commonCount != 0) {
259 sb.append(prefix).append("\t... ").append(commonCount).append(" more").append(EOL);
260 }
261 }
262
263 private void appendSuppressedCount(final StringBuilder sb, final String prefix, final int count) {
264 sb.append(prefix);
207 private void formatCause(final StringBuilder sb, final String prefix, final ThrowableProxy cause,
208 final List<String> ignorePackages, final TextRenderer textRenderer) {
209 formatThrowableProxy(sb, prefix, CAUSED_BY_LABEL, cause, ignorePackages, textRenderer);
210 }
211
212 private void formatThrowableProxy(final StringBuilder sb, final String prefix, final String causeLabel,
213 final ThrowableProxy throwableProxy, final List<String> ignorePackages,
214 final TextRenderer textRenderer) {
215 if (throwableProxy == null) {
216 return;
217 }
218 textRenderer.render(prefix, sb, "Prefix");
219 textRenderer.render(causeLabel, sb, "CauseLabel");
220 throwableProxy.renderOn(sb, textRenderer);
221 textRenderer.render(EOL_STR, sb, "Text");
222 this.formatElements(sb, prefix, throwableProxy.commonElementCount,
223 throwableProxy.getStackTrace(), throwableProxy.extendedStackTrace, ignorePackages, textRenderer);
224 this.formatSuppressed(sb, prefix + TAB, throwableProxy.suppressedProxies, ignorePackages, textRenderer);
225 this.formatCause(sb, prefix, throwableProxy.causeProxy, ignorePackages, textRenderer);
226 }
227
228 void renderOn(final StringBuilder output, final TextRenderer textRenderer) {
229 final String msg = this.message;
230 textRenderer.render(this.name, output, "Name");
231 if (msg != null) {
232 textRenderer.render(": ", output, "NameMessageSeparator");
233 textRenderer.render(msg, output, "Message");
234 }
235 }
236
237 private void formatSuppressed(final StringBuilder sb, final String prefix, final ThrowableProxy[] suppressedProxies,
238 final List<String> ignorePackages, final TextRenderer textRenderer) {
239 if (suppressedProxies == null) {
240 return;
241 }
242 for (final ThrowableProxy suppressedProxy : suppressedProxies) {
243 formatThrowableProxy(sb, prefix, SUPPRESSED_LABEL, suppressedProxy, ignorePackages, textRenderer);
244 }
245 }
246
247 private void formatElements(final StringBuilder sb, final String prefix, final int commonCount,
248 final StackTraceElement[] causedTrace, final ExtendedStackTraceElement[] extStackTrace,
249 final List<String> ignorePackages, final TextRenderer textRenderer) {
250 if (ignorePackages == null || ignorePackages.isEmpty()) {
251 for (final ExtendedStackTraceElement element : extStackTrace) {
252 this.formatEntry(element, sb, prefix, textRenderer);
253 }
254 } else {
255 int count = 0;
256 for (int i = 0; i < extStackTrace.length; ++i) {
257 if (!this.ignoreElement(causedTrace[i], ignorePackages)) {
258 if (count > 0) {
259 appendSuppressedCount(sb, prefix, count, textRenderer);
260 count = 0;
261 }
262 this.formatEntry(extStackTrace[i], sb, prefix, textRenderer);
263 } else {
264 ++count;
265 }
266 }
267 if (count > 0) {
268 appendSuppressedCount(sb, prefix, count, textRenderer);
269 }
270 }
271 if (commonCount != 0) {
272 textRenderer.render(prefix, sb, "Prefix");
273 textRenderer.render("\t... ", sb, "More");
274 textRenderer.render(Integer.toString(commonCount), sb, "More");
275 textRenderer.render(" more", sb, "More");
276 textRenderer.render(EOL_STR, sb, "Text");
277 }
278 }
279
280 private void appendSuppressedCount(final StringBuilder sb, final String prefix, final int count,
281 final TextRenderer textRenderer) {
282 textRenderer.render(prefix, sb, "Prefix");
265283 if (count == 1) {
266 sb.append("\t....").append(EOL);
284 textRenderer.render("\t... ", sb, "Suppressed");
267285 } else {
268 sb.append("\t... suppressed ").append(count).append(" lines").append(EOL);
269 }
270 }
271
272 private void formatEntry(final ExtendedStackTraceElement extStackTraceElement, final StringBuilder sb, final String prefix) {
273 sb.append(prefix);
274 sb.append("\tat ");
275 sb.append(extStackTraceElement);
276 sb.append(EOL);
286 textRenderer.render("\t... suppressed ", sb, "Suppressed");
287 textRenderer.render(Integer.toString(count), sb, "Suppressed");
288 textRenderer.render(" lines", sb, "Suppressed");
289 }
290 textRenderer.render(EOL_STR, sb, "Text");
291 }
292
293 private void formatEntry(final ExtendedStackTraceElement extStackTraceElement, final StringBuilder sb,
294 final String prefix, final TextRenderer textRenderer) {
295 textRenderer.render(prefix, sb, "Prefix");
296 textRenderer.render("\tat ", sb, "At");
297 extStackTraceElement.renderOn(sb, textRenderer);
298 textRenderer.render(EOL_STR, sb, "Text");
277299 }
278300
279301 /**
280302 * Formats the specified Throwable.
281 *
282 * @param sb
283 * StringBuilder to contain the formatted Throwable.
284 * @param cause
285 * The Throwable to format.
303 *
304 * @param sb StringBuilder to contain the formatted Throwable.
305 * @param cause The Throwable to format.
286306 */
287307 public void formatWrapper(final StringBuilder sb, final ThrowableProxy cause) {
288 this.formatWrapper(sb, cause, null);
308 this.formatWrapper(sb, cause, null, PlainTextRenderer.getInstance());
289309 }
290310
291311 /**
292312 * Formats the specified Throwable.
293 *
294 * @param sb
295 * StringBuilder to contain the formatted Throwable.
296 * @param cause
297 * The Throwable to format.
298 * @param packages
299 * The List of packages to be suppressed from the trace.
313 *
314 * @param sb StringBuilder to contain the formatted Throwable.
315 * @param cause The Throwable to format.
316 * @param ignorePackages The List of packages to be suppressed from the trace.
300317 */
301318 @SuppressWarnings("ThrowableResultOfMethodCallIgnored")
302 public void formatWrapper(final StringBuilder sb, final ThrowableProxy cause, final List<String> packages) {
319 public void formatWrapper(final StringBuilder sb, final ThrowableProxy cause, final List<String> ignorePackages) {
320 this.formatWrapper(sb, cause, ignorePackages, PlainTextRenderer.getInstance());
321 }
322
323 /**
324 * Formats the specified Throwable.
325 *
326 * @param sb StringBuilder to contain the formatted Throwable.
327 * @param cause The Throwable to format.
328 * @param ignorePackages The List of packages to be suppressed from the trace.
329 * @param textRenderer The text render
330 */
331 @SuppressWarnings("ThrowableResultOfMethodCallIgnored")
332 public void formatWrapper(final StringBuilder sb, final ThrowableProxy cause, final List<String> ignorePackages,
333 final TextRenderer textRenderer) {
303334 final Throwable caused = cause.getCauseProxy() != null ? cause.getCauseProxy().getThrowable() : null;
304335 if (caused != null) {
305 this.formatWrapper(sb, cause.causeProxy);
336 this.formatWrapper(sb, cause.causeProxy, ignorePackages, textRenderer);
306337 sb.append(WRAPPED_BY_LABEL);
307338 }
308 sb.append(cause).append(EOL);
309 this.formatElements(sb, "", cause.commonElementCount,
310 cause.getThrowable().getStackTrace(), cause.extendedStackTrace, packages);
339 cause.renderOn(sb, textRenderer);
340 textRenderer.render(EOL_STR, sb, "Text");
341 this.formatElements(sb, Strings.EMPTY, cause.commonElementCount,
342 cause.getThrowable().getStackTrace(), cause.extendedStackTrace, ignorePackages, textRenderer);
311343 }
312344
313345 public ThrowableProxy getCauseProxy() {
315347 }
316348
317349 /**
318 * Format the Throwable that is the cause of this Throwable.
319 *
350 * Formats the Throwable that is the cause of this Throwable.
351 *
320352 * @return The formatted Throwable that caused this Throwable.
321353 */
322354 public String getCauseStackTraceAsString() {
323 return this.getCauseStackTraceAsString(null);
324 }
325
326 /**
327 * Format the Throwable that is the cause of this Throwable.
328 *
329 * @param packages
330 * The List of packages to be suppressed from the trace.
355 return this.getCauseStackTraceAsString(null, PlainTextRenderer.getInstance());
356 }
357
358 /**
359 * Formats the Throwable that is the cause of this Throwable.
360 *
361 * @param packages The List of packages to be suppressed from the trace.
331362 * @return The formatted Throwable that caused this Throwable.
332363 */
333364 public String getCauseStackTraceAsString(final List<String> packages) {
365 return getCauseStackTraceAsString(packages, PlainTextRenderer.getInstance());
366 }
367
368 /**
369 * Formats the Throwable that is the cause of this Throwable.
370 *
371 * @param ignorePackages The List of packages to be suppressed from the trace.
372 * @param textRenderer the text renderer
373 * @return The formatted Throwable that caused this Throwable.
374 */
375 public String getCauseStackTraceAsString(final List<String> ignorePackages, final TextRenderer textRenderer) {
334376 final StringBuilder sb = new StringBuilder();
335377 if (this.causeProxy != null) {
336 this.formatWrapper(sb, this.causeProxy);
378 this.formatWrapper(sb, this.causeProxy, ignorePackages, textRenderer);
337379 sb.append(WRAPPED_BY_LABEL);
338380 }
339 sb.append(this.toString());
340 sb.append(EOL);
341 this.formatElements(sb, "", 0, this.throwable.getStackTrace(), this.extendedStackTrace, packages);
381 this.renderOn(sb, textRenderer);
382 textRenderer.render(EOL_STR, sb, "Text");
383 this.formatElements(sb, Strings.EMPTY, 0, this.throwable.getStackTrace(), this.extendedStackTrace,
384 ignorePackages, textRenderer);
342385 return sb.toString();
343386 }
344387
345388 /**
346 * Return the number of elements that are being omitted because they are common with the parent Throwable's stack
389 * Returns the number of elements that are being omitted because they are common with the parent Throwable's stack
347390 * trace.
348 *
391 *
349392 * @return The number of elements omitted from the stack trace.
350393 */
351394 public int getCommonElementCount() {
354397
355398 /**
356399 * Gets the stack trace including packaging information.
357 *
400 *
358401 * @return The stack trace including packaging information.
359402 */
360403 public ExtendedStackTraceElement[] getExtendedStackTrace() {
363406
364407 /**
365408 * Format the stack trace including packaging information.
366 *
409 *
367410 * @return The formatted stack trace including packaging information.
368411 */
369412 public String getExtendedStackTraceAsString() {
370 return this.getExtendedStackTraceAsString(null);
413 return this.getExtendedStackTraceAsString(null, PlainTextRenderer.getInstance());
371414 }
372415
373416 /**
374417 * Format the stack trace including packaging information.
375 *
376 * @param ignorePackages
377 * List of packages to be ignored in the trace.
418 *
419 * @param ignorePackages List of packages to be ignored in the trace.
378420 * @return The formatted stack trace including packaging information.
379421 */
380422 public String getExtendedStackTraceAsString(final List<String> ignorePackages) {
381 final StringBuilder sb = new StringBuilder(this.name);
382 final String msg = this.message;
383 if (msg != null) {
384 sb.append(": ").append(msg);
385 }
386 sb.append(EOL);
423 return getExtendedStackTraceAsString(ignorePackages, PlainTextRenderer.getInstance());
424 }
425
426 /**
427 * Format the stack trace including packaging information.
428 *
429 * @param ignorePackages List of packages to be ignored in the trace.
430 * @param textRenderer The message renderer
431 * @return The formatted stack trace including packaging information.
432 */
433 public String getExtendedStackTraceAsString(final List<String> ignorePackages, final TextRenderer textRenderer) {
434 final StringBuilder sb = new StringBuilder(1024);
435 textRenderer.render(name, sb, "Name");
436 textRenderer.render(": ", sb, "NameMessageSeparator");
437 textRenderer.render(this.message, sb, "Message");
438 textRenderer.render(EOL_STR, sb, "Text");
387439 final StackTraceElement[] causedTrace = this.throwable != null ? this.throwable.getStackTrace() : null;
388 this.formatElements(sb, "", 0, causedTrace, this.extendedStackTrace, ignorePackages);
389 this.formatSuppressed(sb, "\t", this.suppressedProxies, ignorePackages);
390 this.formatCause(sb, "", this.causeProxy, ignorePackages);
440 this.formatElements(sb, Strings.EMPTY, 0, causedTrace, this.extendedStackTrace, ignorePackages, textRenderer);
441 this.formatSuppressed(sb, TAB, this.suppressedProxies, ignorePackages, textRenderer);
442 this.formatCause(sb, Strings.EMPTY, this.causeProxy, ignorePackages, textRenderer);
391443 return sb.toString();
392444 }
393445
401453
402454 /**
403455 * Return the FQCN of the Throwable.
404 *
456 *
405457 * @return The FQCN of the Throwable.
406458 */
407459 public String getName() {
414466
415467 /**
416468 * Gets proxies for suppressed exceptions.
417 *
469 *
418470 * @return proxies for suppressed exceptions.
419471 */
420472 public ThrowableProxy[] getSuppressedProxies() {
423475
424476 /**
425477 * Format the suppressed Throwables.
426 *
478 *
427479 * @return The formatted suppressed Throwables.
428480 */
429481 public String getSuppressedStackTrace() {
440492
441493 /**
442494 * The throwable or null if this object is deserialized from XML or JSON.
443 *
495 *
444496 * @return The throwable or null if this object is deserialized from XML or JSON.
445497 */
446498 public Throwable getThrowable() {
460512 }
461513
462514 private boolean ignoreElement(final StackTraceElement element, final List<String> ignorePackages) {
463 final String className = element.getClassName();
464 for (final String pkg : ignorePackages) {
465 if (className.startsWith(pkg)) {
466 return true;
515 if (ignorePackages != null) {
516 final String className = element.getClassName();
517 for (final String pkg : ignorePackages) {
518 if (className.startsWith(pkg)) {
519 return true;
520 }
467521 }
468522 }
469523 return false;
471525
472526 /**
473527 * Loads classes not located via Reflection.getCallerClass.
474 *
475 * @param lastLoader
476 * The ClassLoader that loaded the Class that called this Class.
477 * @param className
478 * The name of the Class.
528 *
529 * @param lastLoader The ClassLoader that loaded the Class that called this Class.
530 * @param className The name of the Class.
479531 * @return The Class object for the Class or null if it could not be located.
480532 */
481533 private Class<?> loadClass(final ClassLoader lastLoader, final String className) {
483535 Class<?> clazz;
484536 if (lastLoader != null) {
485537 try {
486 clazz = Loader.initializeClass(className, lastLoader);
538 clazz = lastLoader.loadClass(className);
487539 if (clazz != null) {
488540 return clazz;
489541 }
492544 }
493545 }
494546 try {
495 clazz = Loader.loadClass(className);
496 } catch (final ClassNotFoundException ignored) {
497 return initializeClass(className);
498 } catch (final NoClassDefFoundError ignored) {
499 return initializeClass(className);
547 clazz = LoaderUtil.loadClass(className);
548 } catch (final ClassNotFoundException | NoClassDefFoundError e) {
549 return loadClass(className);
550 } catch (final SecurityException e) {
551 return null;
500552 }
501553 return clazz;
502554 }
503555
504 private Class<?> initializeClass(final String className) {
556 private Class<?> loadClass(final String className) {
505557 try {
506 return Loader.initializeClass(className, this.getClass().getClassLoader());
507 } catch (final ClassNotFoundException ignore) {
558 return this.getClass().getClassLoader().loadClass(className);
559 } catch (final ClassNotFoundException | NoClassDefFoundError | SecurityException e) {
508560 return null;
509 } catch (final NoClassDefFoundError ignore) {
510 return null;
511561 }
512562 }
513563
514564 /**
515565 * Construct the CacheEntry from the Class's information.
516 *
517 * @param stackTraceElement
518 * The stack trace element
519 * @param callerClass
520 * The Class.
521 * @param exact
522 * True if the class was obtained via Reflection.getCallerClass.
523 *
566 *
567 * @param stackTraceElement The stack trace element
568 * @param callerClass The Class.
569 * @param exact True if the class was obtained via Reflection.getCallerClass.
524570 * @return The CacheEntry.
525571 */
526572 private CacheEntry toCacheEntry(final StackTraceElement stackTraceElement, final Class<?> callerClass,
527 final boolean exact) {
573 final boolean exact) {
528574 String location = "?";
529575 String version = "?";
530576 ClassLoader lastLoader = null;
561607
562608 /**
563609 * Resolve all the stack entries in this stack trace that are not common with the parent.
564 *
565 * @param stack
566 * The callers Class stack.
567 * @param map
568 * The cache of CacheEntry objects.
569 * @param rootTrace
570 * The first stack trace resolve or null.
571 * @param stackTrace
572 * The stack trace being resolved.
610 *
611 * @param stack The callers Class stack.
612 * @param map The cache of CacheEntry objects.
613 * @param rootTrace The first stack trace resolve or null.
614 * @param stackTrace The stack trace being resolved.
573615 * @return The StackTracePackageElement array.
574616 */
575617 ExtendedStackTraceElement[] toExtendedStackTrace(final Stack<Class<?>> stack, final Map<String, CacheEntry> map,
576 final StackTraceElement[] rootTrace, final StackTraceElement[] stackTrace) {
618 final StackTraceElement[] rootTrace,
619 final StackTraceElement[] stackTrace) {
577620 int stackLength;
578621 if (rootTrace != null) {
579622 int rootIndex = rootTrace.length - 1;
614657 }
615658 } else {
616659 final CacheEntry entry = this.toCacheEntry(stackTraceElement,
617 this.loadClass(lastLoader, className), false);
660 this.loadClass(lastLoader, className), false);
618661 extClassInfo = entry.element;
619662 map.put(stackTraceElement.toString(), entry);
620663 if (entry.loader != null) {
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.jackson;
17
18 import java.io.IOException;
19 import java.util.List;
20 import java.util.Map;
21
22 import org.apache.logging.log4j.core.impl.ContextDataFactory;
23 import org.apache.logging.log4j.util.StringMap;
24
25 import com.fasterxml.jackson.core.JsonParser;
26 import com.fasterxml.jackson.core.JsonProcessingException;
27 import com.fasterxml.jackson.core.type.TypeReference;
28 import com.fasterxml.jackson.databind.DeserializationContext;
29 import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
30
31 /**
32 * <p>
33 * <em>Consider this class private.</em>
34 * </p>
35 */
36 public class ContextDataAsEntryListDeserializer extends StdDeserializer<StringMap> {
37
38 private static final long serialVersionUID = 1L;
39
40 ContextDataAsEntryListDeserializer() {
41 super(Map.class);
42 }
43
44 @Override
45 public StringMap deserialize(final JsonParser jp, final DeserializationContext ctxt) throws IOException,
46 JsonProcessingException {
47 final List<MapEntry> list = jp.readValueAs(new TypeReference<List<MapEntry>>() {
48 // empty
49 });
50 final StringMap contextData = new ContextDataFactory().createContextData();
51 for (final MapEntry mapEntry : list) {
52 contextData.putValue(mapEntry.getKey(), mapEntry.getValue());
53 }
54 return contextData;
55 }
56 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.jackson;
17
18 import java.io.IOException;
19 import java.util.Map;
20
21 import org.apache.logging.log4j.util.ReadOnlyStringMap;
22 import org.apache.logging.log4j.util.BiConsumer;
23
24 import com.fasterxml.jackson.core.JsonGenerationException;
25 import com.fasterxml.jackson.core.JsonGenerator;
26 import com.fasterxml.jackson.databind.SerializerProvider;
27 import com.fasterxml.jackson.databind.ser.std.StdSerializer;
28
29 /**
30 * <p>
31 * <em>Consider this class private.</em>
32 * </p>
33 */
34 public class ContextDataAsEntryListSerializer extends StdSerializer<ReadOnlyStringMap> {
35
36 private static final long serialVersionUID = 1L;
37
38 protected ContextDataAsEntryListSerializer() {
39 super(Map.class, false);
40 }
41
42 @Override
43 public void serialize(final ReadOnlyStringMap contextData, final JsonGenerator jgen, final SerializerProvider provider)
44 throws IOException, JsonGenerationException {
45
46 final MapEntry[] pairs = new MapEntry[contextData.size()];
47 contextData.forEach(new BiConsumer<String, Object>() {
48 int i = 0;
49
50 @Override
51 public void accept(final String key, final Object value) {
52 pairs[i++] = new MapEntry(key, String.valueOf(value));
53 }
54 });
55 jgen.writeObject(pairs);
56 }
57 }
0
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 package org.apache.logging.log4j.core.jackson;
18
19 import java.io.IOException;
20 import java.util.Map;
21
22 import org.apache.logging.log4j.core.impl.ContextDataFactory;
23 import org.apache.logging.log4j.util.StringMap;
24
25 import com.fasterxml.jackson.core.JsonParser;
26 import com.fasterxml.jackson.core.JsonProcessingException;
27 import com.fasterxml.jackson.core.JsonToken;
28 import com.fasterxml.jackson.databind.DeserializationContext;
29 import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
30
31 /**
32 * <p>
33 * <em>Consider this class private.</em>
34 * </p>
35 */
36 public class ContextDataDeserializer extends StdDeserializer<StringMap> {
37
38 private static final long serialVersionUID = 1L;
39
40 ContextDataDeserializer() {
41 super(Map.class);
42 }
43
44 @Override
45 public StringMap deserialize(final JsonParser jp, final DeserializationContext ctxt) throws IOException,
46 JsonProcessingException {
47
48 // Sanity check: verify that we got "Json Object":
49 // JsonToken tok = jp.nextToken();
50 // if (tok != JsonToken.START_OBJECT) {
51 // throw new IOException("Expected data to start with an Object");
52 // }
53 final StringMap contextData = ContextDataFactory.createContextData();
54 // Iterate over object fields:
55 while (jp.nextToken() != JsonToken.END_OBJECT) {
56 final String fieldName = jp.getCurrentName();
57
58 // move to value
59 jp.nextToken();
60 contextData.putValue(fieldName, jp.getText());
61 }
62 return contextData;
63 }
64 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.jackson;
17
18 import java.io.IOException;
19 import java.util.Map;
20
21 import org.apache.logging.log4j.util.ReadOnlyStringMap;
22 import org.apache.logging.log4j.util.TriConsumer;
23
24 import com.fasterxml.jackson.core.JsonGenerationException;
25 import com.fasterxml.jackson.core.JsonGenerator;
26 import com.fasterxml.jackson.databind.SerializerProvider;
27 import com.fasterxml.jackson.databind.ser.std.StdSerializer;
28
29 /**
30 * <p>
31 * <em>Consider this class private.</em>
32 * </p>
33 */
34 public class ContextDataSerializer extends StdSerializer<ReadOnlyStringMap> {
35
36 private static final long serialVersionUID = 1L;
37
38 protected ContextDataSerializer() {
39 super(Map.class, false);
40 }
41
42 @Override
43 public void serialize(final ReadOnlyStringMap contextData, final JsonGenerator jgen,
44 final SerializerProvider provider) throws IOException, JsonGenerationException {
45
46 jgen.writeStartObject();
47 contextData.forEach(WRITE_STRING_FIELD_INTO, jgen);
48 jgen.writeEndObject();
49 }
50
51 private static final TriConsumer<String, Object, JsonGenerator> WRITE_STRING_FIELD_INTO =
52 new TriConsumer<String, Object, JsonGenerator>() {
53
54 @Override
55 public void accept(final String key, final Object value, final JsonGenerator jsonGenerator) {
56 try {
57 jsonGenerator.writeStringField(key, String.valueOf(value));
58 } catch (final Exception ex) {
59 throw new IllegalStateException("Problem with key " + key, ex);
60 }
61 }
62 };
63 }
3838 */
3939 static class SetupContextInitializer {
4040
41 void setupModule(final SetupContext context) {
41 void setupModule(final SetupContext context, final boolean includeStacktrace) {
4242 // JRE classes: we cannot edit those with Jackson annotations
4343 context.setMixInAnnotations(StackTraceElement.class, StackTraceElementMixIn.class);
4444 // Log4j API classes: we do not want to edit those with Jackson annotations because the API module should not depend on Jackson.
4545 context.setMixInAnnotations(Marker.class, MarkerMixIn.class);
4646 context.setMixInAnnotations(Level.class, LevelMixIn.class);
47 context.setMixInAnnotations(LogEvent.class, LogEventMixIn.class);
47 context.setMixInAnnotations(LogEvent.class, LogEventWithContextListMixIn.class);
4848 // Log4j Core classes: we do not want to bring in Jackson at runtime if we do not have to.
4949 context.setMixInAnnotations(ExtendedStackTraceElement.class, ExtendedStackTraceElementMixIn.class);
50 context.setMixInAnnotations(ThrowableProxy.class, ThrowableProxyMixIn.class);
50 context.setMixInAnnotations(ThrowableProxy.class,
51 includeStacktrace ? ThrowableProxyMixIn.class : ThrowableProxyWithoutStacktraceMixIn.class);
5152 }
5253 }
5354
5859 */
5960 static class SetupContextJsonInitializer {
6061
61 void setupModule(final SetupContext context) {
62 void setupModule(final SetupContext context, final boolean includeStacktrace) {
6263 // JRE classes: we cannot edit those with Jackson annotations
6364 context.setMixInAnnotations(StackTraceElement.class, StackTraceElementMixIn.class);
6465 // Log4j API classes: we do not want to edit those with Jackson annotations because the API module should not depend on Jackson.
6768 context.setMixInAnnotations(LogEvent.class, LogEventJsonMixIn.class); // different ThreadContext handling
6869 // Log4j Core classes: we do not want to bring in Jackson at runtime if we do not have to.
6970 context.setMixInAnnotations(ExtendedStackTraceElement.class, ExtendedStackTraceElementMixIn.class);
70 context.setMixInAnnotations(ThrowableProxy.class, ThrowableProxyMixIn.class);
71 context.setMixInAnnotations(ThrowableProxy.class,
72 includeStacktrace ? ThrowableProxyMixIn.class : ThrowableProxyWithoutStacktraceMixIn.class);
7173 }
7274 }
7375
1616 package org.apache.logging.log4j.core.jackson;
1717
1818 import org.apache.logging.log4j.core.jackson.Initializers.SetupContextInitializer;
19 import org.apache.logging.log4j.core.jackson.Initializers.SetupContextJsonInitializer;
1920 import org.apache.logging.log4j.core.jackson.Initializers.SimpleModuleInitializer;
2021
2122 import com.fasterxml.jackson.core.Version;
3031
3132 private static final long serialVersionUID = 1L;
3233 private final boolean encodeThreadContextAsList;
34 private final boolean includeStacktrace;
3335
34 Log4jJsonModule(final boolean encodeThreadContextAsList) {
36 Log4jJsonModule(final boolean encodeThreadContextAsList, final boolean includeStacktrace) {
3537 super(Log4jJsonModule.class.getName(), new Version(2, 0, 0, null, null, null));
3638 this.encodeThreadContextAsList = encodeThreadContextAsList;
39 this.includeStacktrace = includeStacktrace;
3740 // MUST init here.
3841 // Calling this from setupModule is too late!
3942 //noinspection ThisEscapedInObjectConstruction
4548 // Calling super is a MUST!
4649 super.setupModule(context);
4750 if (encodeThreadContextAsList) {
48 new SetupContextInitializer().setupModule(context);
51 new SetupContextInitializer().setupModule(context, includeStacktrace);
4952 } else {
50 new Initializers.SetupContextJsonInitializer().setupModule(context);
53 new SetupContextJsonInitializer().setupModule(context, includeStacktrace);
5154 }
5255 }
5356 }
3232 * Create a new instance using the {@link Log4jJsonModule}.
3333 */
3434 public Log4jJsonObjectMapper() {
35 this(false);
35 this(false, true);
3636 }
3737
3838 /**
3939 * Create a new instance using the {@link Log4jJsonModule}.
4040 */
41 public Log4jJsonObjectMapper(final boolean encodeThreadContextAsList) {
42 this.registerModule(new Log4jJsonModule(encodeThreadContextAsList));
41 public Log4jJsonObjectMapper(final boolean encodeThreadContextAsList, final boolean includeStacktrace) {
42 this.registerModule(new Log4jJsonModule(encodeThreadContextAsList, includeStacktrace));
4343 this.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
4444 }
4545
2828 final class Log4jXmlModule extends JacksonXmlModule {
2929
3030 private static final long serialVersionUID = 1L;
31 private final boolean includeStacktrace;
3132
32 Log4jXmlModule() {
33 Log4jXmlModule(final boolean includeStacktrace) {
3334 super();
35 this.includeStacktrace = includeStacktrace;
3436 // MUST init here.
3537 // Calling this from setupModule is too late!
3638 new SimpleModuleInitializer().initialize(this);
4042 public void setupModule(final SetupContext context) {
4143 // Calling super is a MUST!
4244 super.setupModule(context);
43 new SetupContextInitializer().setupModule(context);
45 new SetupContextInitializer().setupModule(context, includeStacktrace);
4446 }
4547 }
3333 * Create a new instance using the {@link Log4jXmlModule}.
3434 */
3535 public Log4jXmlObjectMapper() {
36 super(new Log4jXmlModule());
36 this(true);
37 }
38
39 /**
40 * Create a new instance using the {@link Log4jXmlModule}.
41 */
42 public Log4jXmlObjectMapper(final boolean includeStacktrace) {
43 super(new Log4jXmlModule(includeStacktrace));
3744 this.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
3845 }
3946
1616 package org.apache.logging.log4j.core.jackson;
1717
1818 import org.apache.logging.log4j.core.jackson.Initializers.SetupContextInitializer;
19 import org.apache.logging.log4j.core.jackson.Initializers.SetupContextJsonInitializer;
1920 import org.apache.logging.log4j.core.jackson.Initializers.SimpleModuleInitializer;
2021
2122 import com.fasterxml.jackson.core.Version;
3031
3132 private static final long serialVersionUID = 1L;
3233 private final boolean encodeThreadContextAsList;
34 private final boolean includeStacktrace;
3335
34 Log4jYamlModule(final boolean encodeThreadContextAsList) {
36 Log4jYamlModule(final boolean encodeThreadContextAsList, final boolean includeStacktrace) {
3537 super(Log4jYamlModule.class.getName(), new Version(2, 0, 0, null, null, null));
3638 this.encodeThreadContextAsList = encodeThreadContextAsList;
39 this.includeStacktrace = includeStacktrace;
3740 // MUST init here.
3841 // Calling this from setupModule is too late!
3942 //noinspection ThisEscapedInObjectConstruction
4548 // Calling super is a MUST!
4649 super.setupModule(context);
4750 if (encodeThreadContextAsList) {
48 new SetupContextInitializer().setupModule(context);
51 new SetupContextInitializer().setupModule(context, includeStacktrace);
4952 } else {
50 new Initializers.SetupContextJsonInitializer().setupModule(context);
53 new SetupContextJsonInitializer().setupModule(context, includeStacktrace);
5154 }
5255 }
5356 }
3333 * Create a new instance using the {@link Log4jYamlModule}.
3434 */
3535 public Log4jYamlObjectMapper() {
36 this(false);
36 this(false, true);
3737 }
3838
3939 /**
4040 * Create a new instance using the {@link Log4jYamlModule}.
4141 */
42 public Log4jYamlObjectMapper(final boolean encodeThreadContextAsList) {
43 this.registerModule(new Log4jYamlModule(encodeThreadContextAsList));
42 public Log4jYamlObjectMapper(final boolean encodeThreadContextAsList, final boolean includeStacktrace) {
43 this.registerModule(new Log4jYamlModule(encodeThreadContextAsList, includeStacktrace));
4444 this.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
4545 }
4646
2020 import org.apache.logging.log4j.Level;
2121 import org.apache.logging.log4j.Marker;
2222 import org.apache.logging.log4j.ThreadContext.ContextStack;
23 import org.apache.logging.log4j.util.ReadOnlyStringMap;
2324 import org.apache.logging.log4j.core.LogEvent;
2425 import org.apache.logging.log4j.core.impl.ThrowableProxy;
2526 import org.apache.logging.log4j.message.Message;
4445
4546 private static final long serialVersionUID = 1L;
4647
47 @JsonProperty(JsonConstants.ELT_CONTEXT_MAP)
48 @JacksonXmlProperty(namespace = XmlConstants.XML_NAMESPACE, localName = XmlConstants.ELT_CONTEXT_MAP)
48 // @JsonProperty(JsonConstants.ELT_CONTEXT_MAP)
49 // @JacksonXmlProperty(namespace = XmlConstants.XML_NAMESPACE, localName = XmlConstants.ELT_CONTEXT_MAP)
4950 // @JsonSerialize(using = MapSerializer.class)
5051 // @JsonDeserialize(using = MapDeserializer.class)
5152 @Override
53 @JsonIgnore
54 // @JsonProperty(JsonConstants.ELT_CONTEXT_MAP)
55 // @JacksonXmlProperty(namespace = XmlConstants.XML_NAMESPACE, localName = XmlConstants.ELT_CONTEXT_MAP)
5256 public abstract Map<String, String> getContextMap();
57
58 @JsonProperty(JsonConstants.ELT_CONTEXT_MAP)
59 @JacksonXmlProperty(namespace = XmlConstants.XML_NAMESPACE, localName = XmlConstants.ELT_CONTEXT_MAP)
60 @JsonSerialize(using = ContextDataSerializer.class)
61 @JsonDeserialize(using = ContextDataDeserializer.class)
62 //@JsonIgnore
63 @Override
64 public abstract ReadOnlyStringMap getContextData();
5365
5466 @JsonProperty(JsonConstants.ELT_CONTEXT_STACK)
5567 @JacksonXmlElementWrapper(namespace = XmlConstants.XML_NAMESPACE, localName = XmlConstants.ELT_CONTEXT_STACK)
+0
-138
log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/LogEventMixIn.java less more
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.jackson;
17
18 import java.util.Map;
19
20 import org.apache.logging.log4j.Level;
21 import org.apache.logging.log4j.Marker;
22 import org.apache.logging.log4j.ThreadContext.ContextStack;
23 import org.apache.logging.log4j.core.LogEvent;
24 import org.apache.logging.log4j.core.impl.ThrowableProxy;
25 import org.apache.logging.log4j.message.Message;
26
27 import com.fasterxml.jackson.annotation.JsonFilter;
28 import com.fasterxml.jackson.annotation.JsonIgnore;
29 import com.fasterxml.jackson.annotation.JsonProperty;
30 import com.fasterxml.jackson.annotation.JsonPropertyOrder;
31 import com.fasterxml.jackson.annotation.JsonRootName;
32 import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
33 import com.fasterxml.jackson.databind.annotation.JsonSerialize;
34 import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
35 import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
36 import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
37
38 @JsonRootName(XmlConstants.ELT_EVENT)
39 @JacksonXmlRootElement(namespace = XmlConstants.XML_NAMESPACE, localName = XmlConstants.ELT_EVENT)
40 @JsonFilter("org.apache.logging.log4j.core.impl.Log4jLogEvent")
41 @JsonPropertyOrder({ "timeMillis", "threadName", "level", "loggerName", "marker", "message", "thrown", XmlConstants.ELT_CONTEXT_MAP,
42 JsonConstants.ELT_CONTEXT_STACK, "loggerFQCN", "Source", "endOfBatch" })
43 abstract class LogEventMixIn implements LogEvent {
44
45 private static final long serialVersionUID = 1L;
46
47 @JsonProperty(JsonConstants.ELT_CONTEXT_MAP)
48 @JacksonXmlProperty(namespace = XmlConstants.XML_NAMESPACE, localName = XmlConstants.ELT_CONTEXT_MAP)
49 @JsonSerialize(using = ListOfMapEntrySerializer.class)
50 @JsonDeserialize(using = ListOfMapEntryDeserializer.class)
51 @Override
52 public abstract Map<String, String> getContextMap();
53
54 @JsonProperty(JsonConstants.ELT_CONTEXT_STACK)
55 @JacksonXmlElementWrapper(namespace = XmlConstants.XML_NAMESPACE, localName = XmlConstants.ELT_CONTEXT_STACK)
56 @JacksonXmlProperty(namespace = XmlConstants.XML_NAMESPACE, localName = XmlConstants.ELT_CONTEXT_STACK_ITEM)
57 @Override
58 public abstract ContextStack getContextStack();
59
60 @JsonProperty()
61 @JacksonXmlProperty(isAttribute = true)
62 @Override
63 public abstract Level getLevel();
64
65 @JsonProperty()
66 @JacksonXmlProperty(isAttribute = true)
67 @Override
68 public abstract String getLoggerFqcn();
69
70 @JsonProperty()
71 @JacksonXmlProperty(isAttribute = true)
72 @Override
73 public abstract String getLoggerName();
74
75 @JsonProperty(JsonConstants.ELT_MARKER)
76 @JacksonXmlProperty(namespace = XmlConstants.XML_NAMESPACE, localName = XmlConstants.ELT_MARKER)
77 @Override
78 public abstract Marker getMarker();
79
80 @JsonProperty(JsonConstants.ELT_MESSAGE)
81 @JsonSerialize(using = MessageSerializer.class)
82 @JsonDeserialize(using = SimpleMessageDeserializer.class)
83 @JacksonXmlProperty(namespace = XmlConstants.XML_NAMESPACE, localName = XmlConstants.ELT_MESSAGE)
84 @Override
85 public abstract Message getMessage();
86
87 @JsonProperty(JsonConstants.ELT_SOURCE)
88 @JsonDeserialize(using = Log4jStackTraceElementDeserializer.class)
89 @JacksonXmlProperty(namespace = XmlConstants.XML_NAMESPACE, localName = XmlConstants.ELT_SOURCE)
90 @Override
91 public abstract StackTraceElement getSource();
92
93 @Override
94 @JsonProperty("threadId")
95 @JacksonXmlProperty(isAttribute = true, localName = "threadId")
96 public abstract long getThreadId();
97
98 @Override
99 @JsonProperty("thread")
100 @JacksonXmlProperty(isAttribute = true, localName = "thread")
101 public abstract String getThreadName();
102
103 @Override
104 @JsonProperty("threadPriority")
105 @JacksonXmlProperty(isAttribute = true, localName = "threadPriority")
106 public abstract int getThreadPriority();
107
108 @JsonIgnore
109 @Override
110 public abstract Throwable getThrown();
111
112 @JsonProperty(JsonConstants.ELT_THROWN)
113 @JacksonXmlProperty(namespace = XmlConstants.XML_NAMESPACE, localName = XmlConstants.ELT_THROWN)
114 @Override
115 public abstract ThrowableProxy getThrownProxy();
116
117 @JsonProperty()
118 @JacksonXmlProperty(isAttribute = true)
119 @Override
120 public abstract long getTimeMillis();
121
122 @JsonProperty()
123 @JacksonXmlProperty(isAttribute = true)
124 @Override
125 public abstract boolean isEndOfBatch();
126
127 @JsonIgnore
128 @Override
129 public abstract boolean isIncludeLocation();
130
131 @Override
132 public abstract void setEndOfBatch(boolean endOfBatch);
133
134 @Override
135 public abstract void setIncludeLocation(boolean locationRequired);
136
137 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.jackson;
17
18 import java.util.Map;
19
20 import org.apache.logging.log4j.Level;
21 import org.apache.logging.log4j.Marker;
22 import org.apache.logging.log4j.ThreadContext.ContextStack;
23 import org.apache.logging.log4j.util.ReadOnlyStringMap;
24 import org.apache.logging.log4j.core.LogEvent;
25 import org.apache.logging.log4j.core.impl.ThrowableProxy;
26 import org.apache.logging.log4j.message.Message;
27
28 import com.fasterxml.jackson.annotation.JsonFilter;
29 import com.fasterxml.jackson.annotation.JsonIgnore;
30 import com.fasterxml.jackson.annotation.JsonProperty;
31 import com.fasterxml.jackson.annotation.JsonPropertyOrder;
32 import com.fasterxml.jackson.annotation.JsonRootName;
33 import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
34 import com.fasterxml.jackson.databind.annotation.JsonSerialize;
35 import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
36 import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
37 import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
38
39 @JsonRootName(XmlConstants.ELT_EVENT)
40 @JacksonXmlRootElement(namespace = XmlConstants.XML_NAMESPACE, localName = XmlConstants.ELT_EVENT)
41 @JsonFilter("org.apache.logging.log4j.core.impl.Log4jLogEvent")
42 @JsonPropertyOrder({ "timeMillis", "threadName", "level", "loggerName", "marker", "message", "thrown", XmlConstants.ELT_CONTEXT_MAP,
43 JsonConstants.ELT_CONTEXT_STACK, "loggerFQCN", "Source", "endOfBatch" })
44 abstract class LogEventWithContextListMixIn implements LogEvent {
45
46 private static final long serialVersionUID = 1L;
47
48 // @JsonProperty(JsonConstants.ELT_CONTEXT_MAP)
49 // @JacksonXmlProperty(namespace = XmlConstants.XML_NAMESPACE, localName = XmlConstants.ELT_CONTEXT_MAP)
50 // @JsonSerialize(using = ListOfMapEntrySerializer.class)
51 // @JsonDeserialize(using = ListOfMapEntryDeserializer.class)
52 @Override
53 @JsonIgnore
54 public abstract Map<String, String> getContextMap();
55
56 @JsonProperty(JsonConstants.ELT_CONTEXT_MAP)
57 @JacksonXmlProperty(namespace = XmlConstants.XML_NAMESPACE, localName = XmlConstants.ELT_CONTEXT_MAP)
58 @JsonSerialize(using = ContextDataAsEntryListSerializer.class)
59 @JsonDeserialize(using = ContextDataAsEntryListDeserializer.class)
60 // @JsonIgnore
61 @Override
62 public abstract ReadOnlyStringMap getContextData();
63
64 @JsonProperty(JsonConstants.ELT_CONTEXT_STACK)
65 @JacksonXmlElementWrapper(namespace = XmlConstants.XML_NAMESPACE, localName = XmlConstants.ELT_CONTEXT_STACK)
66 @JacksonXmlProperty(namespace = XmlConstants.XML_NAMESPACE, localName = XmlConstants.ELT_CONTEXT_STACK_ITEM)
67 @Override
68 public abstract ContextStack getContextStack();
69
70 @JsonProperty()
71 @JacksonXmlProperty(isAttribute = true)
72 @Override
73 public abstract Level getLevel();
74
75 @JsonProperty()
76 @JacksonXmlProperty(isAttribute = true)
77 @Override
78 public abstract String getLoggerFqcn();
79
80 @JsonProperty()
81 @JacksonXmlProperty(isAttribute = true)
82 @Override
83 public abstract String getLoggerName();
84
85 @JsonProperty(JsonConstants.ELT_MARKER)
86 @JacksonXmlProperty(namespace = XmlConstants.XML_NAMESPACE, localName = XmlConstants.ELT_MARKER)
87 @Override
88 public abstract Marker getMarker();
89
90 @JsonProperty(JsonConstants.ELT_MESSAGE)
91 @JsonSerialize(using = MessageSerializer.class)
92 @JsonDeserialize(using = SimpleMessageDeserializer.class)
93 @JacksonXmlProperty(namespace = XmlConstants.XML_NAMESPACE, localName = XmlConstants.ELT_MESSAGE)
94 @Override
95 public abstract Message getMessage();
96
97 @JsonProperty(JsonConstants.ELT_SOURCE)
98 @JsonDeserialize(using = Log4jStackTraceElementDeserializer.class)
99 @JacksonXmlProperty(namespace = XmlConstants.XML_NAMESPACE, localName = XmlConstants.ELT_SOURCE)
100 @Override
101 public abstract StackTraceElement getSource();
102
103 @Override
104 @JsonProperty("threadId")
105 @JacksonXmlProperty(isAttribute = true, localName = "threadId")
106 public abstract long getThreadId();
107
108 @Override
109 @JsonProperty("thread")
110 @JacksonXmlProperty(isAttribute = true, localName = "thread")
111 public abstract String getThreadName();
112
113 @Override
114 @JsonProperty("threadPriority")
115 @JacksonXmlProperty(isAttribute = true, localName = "threadPriority")
116 public abstract int getThreadPriority();
117
118 @JsonIgnore
119 @Override
120 public abstract Throwable getThrown();
121
122 @JsonProperty(JsonConstants.ELT_THROWN)
123 @JacksonXmlProperty(namespace = XmlConstants.XML_NAMESPACE, localName = XmlConstants.ELT_THROWN)
124 @Override
125 public abstract ThrowableProxy getThrownProxy();
126
127 @JsonProperty()
128 @JacksonXmlProperty(isAttribute = true)
129 @Override
130 public abstract long getTimeMillis();
131
132 @JsonProperty()
133 @JacksonXmlProperty(isAttribute = true)
134 @Override
135 public abstract boolean isEndOfBatch();
136
137 @JsonIgnore
138 @Override
139 public abstract boolean isIncludeLocation();
140
141 @Override
142 public abstract void setEndOfBatch(boolean endOfBatch);
143
144 @Override
145 public abstract void setIncludeLocation(boolean locationRequired);
146
147 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.jackson;
17
18 import com.fasterxml.jackson.annotation.JsonIgnore;
19 import com.fasterxml.jackson.annotation.JsonProperty;
20 import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
21 import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
22 import org.apache.logging.log4j.core.impl.ExtendedStackTraceElement;
23 import org.apache.logging.log4j.core.impl.ThrowableProxy;
24
25 /**
26 * Mix-in for {@link ThrowableProxy}.
27 */
28 abstract class ThrowableProxyWithoutStacktraceMixIn {
29
30 @JsonProperty(JsonConstants.ELT_CAUSE)
31 @JacksonXmlProperty(namespace = XmlConstants.XML_NAMESPACE, localName = XmlConstants.ELT_CAUSE)
32 private ThrowableProxyWithoutStacktraceMixIn causeProxy;
33
34 @JsonProperty
35 @JacksonXmlProperty(isAttribute = true)
36 private int commonElementCount;
37
38 @JsonIgnore
39 private ExtendedStackTraceElement[] extendedStackTrace;
40
41 @JsonProperty
42 @JacksonXmlProperty(isAttribute = true)
43 private String localizedMessage;
44
45 @JsonProperty
46 @JacksonXmlProperty(isAttribute = true)
47 private String message;
48
49 @JsonProperty
50 @JacksonXmlProperty(isAttribute = true)
51 private String name;
52
53 @JsonIgnore
54 private transient Throwable throwable;
55
56 @JsonIgnore
57 public abstract String getCauseStackTraceAsString();
58
59 @JsonIgnore
60 public abstract String getExtendedStackTraceAsString();
61
62 @JsonIgnore
63 public abstract StackTraceElement[] getStackTrace();
64
65 @JsonProperty(JsonConstants.ELT_SUPPRESSED)
66 @JacksonXmlElementWrapper(namespace = XmlConstants.XML_NAMESPACE, localName = XmlConstants.ELT_SUPPRESSED)
67 @JacksonXmlProperty(namespace = XmlConstants.XML_NAMESPACE, localName = XmlConstants.ELT_SUPPRESSED_ITEM)
68 public abstract ThrowableProxy[] getSuppressedProxies();
69
70 @JsonIgnore
71 public abstract String getSuppressedStackTrace();
72
73 @JsonIgnore
74 public abstract Throwable getThrowable();
75
76 }
131131 LOGGER.debug("Opening config URL {}", configURL);
132132 configSource = new ConfigurationSource(configURL.openStream(), configURL);
133133 }
134 final Configuration config = ConfigurationFactory.getInstance().getConfiguration(configSource);
134 final Configuration config = ConfigurationFactory.getInstance().getConfiguration(loggerContext, configSource);
135135 loggerContext.start(config);
136136 LOGGER.debug("Completed remote request to reconfigure.");
137137 }
196196 try {
197197 final InputStream in = new ByteArrayInputStream(configText.getBytes(charsetName));
198198 final ConfigurationSource source = new ConfigurationSource(in);
199 final Configuration updated = ConfigurationFactory.getInstance().getConfiguration(source);
199 final Configuration updated = ConfigurationFactory.getInstance().getConfiguration(loggerContext, source);
200200 loggerContext.start(updated);
201201 LOGGER.debug("Completed remote request to reconfigure from config text.");
202202 } catch (final Exception ex) {
2424 import java.util.concurrent.Executors;
2525
2626 import javax.management.InstanceAlreadyExistsException;
27 import javax.management.InstanceNotFoundException;
2728 import javax.management.MBeanRegistrationException;
2829 import javax.management.MBeanServer;
2930 import javax.management.NotCompliantMBeanException;
3536 import org.apache.logging.log4j.core.appender.AsyncAppender;
3637 import org.apache.logging.log4j.core.async.AsyncLoggerConfig;
3738 import org.apache.logging.log4j.core.async.AsyncLoggerContext;
38 import org.apache.logging.log4j.core.async.DaemonThreadFactory;
3939 import org.apache.logging.log4j.core.config.LoggerConfig;
4040 import org.apache.logging.log4j.core.impl.Log4jContextFactory;
4141 import org.apache.logging.log4j.core.selector.ContextSelector;
4242 import org.apache.logging.log4j.core.util.Constants;
43 import org.apache.logging.log4j.core.util.Log4jThreadFactory;
4344 import org.apache.logging.log4j.spi.LoggerContextFactory;
4445 import org.apache.logging.log4j.status.StatusLogger;
4546 import org.apache.logging.log4j.util.PropertiesUtil;
5859 public static final String DOMAIN = "org.apache.logging.log4j2";
5960 private static final String PROPERTY_DISABLE_JMX = "log4j2.disable.jmx";
6061 private static final String PROPERTY_ASYNC_NOTIF = "log4j2.jmx.notify.async";
61 private static final String THREAD_NAME_PREFIX = "log4j2.jmx.notif";
62 private static final String THREAD_NAME_PREFIX = "jmx.notif";
6263 private static final StatusLogger LOGGER = StatusLogger.getLogger();
6364 static final Executor executor = isJmxDisabled() ? null : createExecutor();
6465
7576 private static ExecutorService createExecutor() {
7677 final boolean defaultAsync = !Constants.IS_WEB_APP;
7778 final boolean async = PropertiesUtil.getProperties().getBooleanProperty(PROPERTY_ASYNC_NOTIF, defaultAsync);
78 return async ? Executors.newFixedThreadPool(1, new DaemonThreadFactory(THREAD_NAME_PREFIX)) : null;
79 return async ? Executors.newFixedThreadPool(1, Log4jThreadFactory.createDaemonThreadFactory(THREAD_NAME_PREFIX))
80 : null;
7981 }
8082
8183 /**
130132 public static void reregisterMBeansAfterReconfigure() {
131133 // avoid creating Platform MBean Server if JMX disabled
132134 if (isJmxDisabled()) {
133 LOGGER.debug("JMX disabled for log4j2. Not registering MBeans.");
135 LOGGER.debug("JMX disabled for Log4j2. Not registering MBeans.");
134136 return;
135137 }
136138 final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
139141
140142 public static void reregisterMBeansAfterReconfigure(final MBeanServer mbs) {
141143 if (isJmxDisabled()) {
142 LOGGER.debug("JMX disabled for log4j2. Not registering MBeans.");
144 LOGGER.debug("JMX disabled for Log4j2. Not registering MBeans.");
143145 return;
144146 }
145147
191193 * Unregister all log4j MBeans from the platform MBean server.
192194 */
193195 public static void unregisterMBeans() {
196 if (isJmxDisabled()) {
197 LOGGER.debug("JMX disabled for Log4j2. Not unregistering MBeans.");
198 return;
199 }
194200 final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
195201 unregisterMBeans(mbs);
196202 }
232238 * @param loggerContextName name of the logger context to unregister
233239 */
234240 public static void unregisterLoggerContext(final String loggerContextName) {
241 if (isJmxDisabled()) {
242 LOGGER.debug("JMX disabled for Log4j2. Not unregistering MBeans.");
243 return;
244 }
235245 final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
236246 unregisterLoggerContext(loggerContextName, mbs);
237247 }
244254 * @param mbs the MBean Server to unregister the instrumented objects from
245255 */
246256 public static void unregisterLoggerContext(final String contextName, final MBeanServer mbs) {
247 final String pattern = LoggerContextAdminMBean.PATTERN;
248 final String search = String.format(pattern, escape(contextName), "*");
257 final String search = String.format(LoggerContextAdminMBean.PATTERN, escape(contextName), "*");
249258 unregisterAllMatching(search, mbs); // unregister context mbean
250259
251260 // now unregister all MBeans associated with this logger context
274283 }
275284
276285 private static void unregisterStatusLogger(final String contextName, final MBeanServer mbs) {
277 final String pattern = StatusLoggerAdminMBean.PATTERN;
278 final String search = String.format(pattern, escape(contextName), "*");
286 final String search = String.format(StatusLoggerAdminMBean.PATTERN, escape(contextName), "*");
279287 unregisterAllMatching(search, mbs);
280288 }
281289
282290 private static void unregisterContextSelector(final String contextName, final MBeanServer mbs) {
283 final String pattern = ContextSelectorAdminMBean.PATTERN;
284 final String search = String.format(pattern, escape(contextName), "*");
291 final String search = String.format(ContextSelectorAdminMBean.PATTERN, escape(contextName), "*");
285292 unregisterAllMatching(search, mbs);
286293 }
287294
333340 for (final ObjectName objectName : found) {
334341 mbs.unregisterMBean(objectName);
335342 }
343 } catch (final InstanceNotFoundException ex) {
344 LOGGER.debug("Could not unregister MBeans for " + search + ". Ignoring " + ex);
336345 } catch (final Exception ex) {
337346 LOGGER.error("Could not unregister MBeans for " + search, ex);
338347 }
3737 protected static CSVFormat createFormat(final String format, final Character delimiter, final Character escape,
3838 final Character quote, final QuoteMode quoteMode, final String nullString, final String recordSeparator) {
3939 CSVFormat csvFormat = CSVFormat.valueOf(format);
40 if (delimiter != null) {
40 if (isNotNul(delimiter)) {
4141 csvFormat = csvFormat.withDelimiter(delimiter);
4242 }
43 if (escape != null) {
43 if (isNotNul(escape)) {
4444 csvFormat = csvFormat.withEscape(escape);
4545 }
46 if (quote != null) {
46 if (isNotNul(quote)) {
4747 csvFormat = csvFormat.withQuote(quote);
4848 }
4949 if (quoteMode != null) {
5656 csvFormat = csvFormat.withRecordSeparator(recordSeparator);
5757 }
5858 return csvFormat;
59 }
60
61 private static boolean isNotNul(final Character character) {
62 return character != null && character.charValue() != 0;
5963 }
6064
6165 private final CSVFormat format;
1919 import org.apache.logging.log4j.core.StringLayout;
2020 import org.apache.logging.log4j.core.config.Configuration;
2121 import org.apache.logging.log4j.core.config.LoggerConfig;
22 import org.apache.logging.log4j.core.impl.DefaultLogEventFactory;
2223 import org.apache.logging.log4j.core.util.Constants;
2324 import org.apache.logging.log4j.core.util.StringEncoder;
2425 import org.apache.logging.log4j.util.PropertiesUtil;
6263
6364 private static final ThreadLocal<StringBuilder> threadLocal = new ThreadLocal<>();
6465
65 private Encoder<StringBuilder> textEncoder;
66
67 private static int size(final String property, final int defaultValue) {
68 return PropertiesUtil.getProperties().getIntegerProperty(property, defaultValue);
69 }
70
7166 /**
7267 * Returns a {@code StringBuilder} that this Layout implementation can use to write the formatted log event to.
7368 *
8277 trimToMaxSize(result);
8378 result.setLength(0);
8479 return result;
85 }
86
87 protected static void trimToMaxSize(final StringBuilder stringBuilder) {
88 if (stringBuilder.length() > MAX_STRING_BUILDER_SIZE) {
89 stringBuilder.setLength(MAX_STRING_BUILDER_SIZE);
90 stringBuilder.trimToSize();
91 }
9280 }
9381
9482 // LOG4J2-1151: If the built-in JDK 8 encoders are available we should use them.
10290 return true;
10391 }
10492 }
93
94 private static int size(final String property, final int defaultValue) {
95 return PropertiesUtil.getProperties().getIntegerProperty(property, defaultValue);
96 }
97
98 protected static void trimToMaxSize(final StringBuilder stringBuilder) {
99 if (stringBuilder.length() > MAX_STRING_BUILDER_SIZE) {
100 stringBuilder.setLength(MAX_STRING_BUILDER_SIZE);
101 stringBuilder.trimToSize();
102 }
103 }
104
105 private Encoder<StringBuilder> textEncoder;
105106 /**
106107 * The charset for the formatted message.
107108 */
158159 textEncoder = Constants.ENABLE_DIRECT_ENCODERS ? new StringBuilderEncoder(charset) : null;
159160 }
160161
161 /**
162 * Returns a {@code Encoder<StringBuilder>} that this Layout implementation can use for encoding log events.
163 *
164 * @return a {@code Encoder<StringBuilder>}
165 */
166 protected Encoder<StringBuilder> getStringBuilderEncoder() {
167 if (textEncoder == null) {
168 textEncoder = new StringBuilderEncoder(getCharset());
169 }
170 return textEncoder;
171 }
172
173162 protected byte[] getBytes(final String s) {
174163 if (useCustomEncoding) { // rely on branch prediction to eliminate this check if false
175164 return StringEncoder.encodeSingleByteChars(s);
222211 return headerSerializer;
223212 }
224213
214 private DefaultLogEventFactory getLogEventFactory() {
215 return DefaultLogEventFactory.getInstance();
216 }
217
218 /**
219 * Returns a {@code Encoder<StringBuilder>} that this Layout implementation can use for encoding log events.
220 *
221 * @return a {@code Encoder<StringBuilder>}
222 */
223 protected Encoder<StringBuilder> getStringBuilderEncoder() {
224 if (textEncoder == null) {
225 textEncoder = new StringBuilderEncoder(getCharset());
226 }
227 return textEncoder;
228 }
229
225230 protected byte[] serializeToBytes(final Serializer serializer, final byte[] defaultValue) {
226231 final String serializable = serializeToString(serializer);
227232 if (serializer == null) {
236241 }
237242 final LoggerConfig rootLogger = getConfiguration().getRootLogger();
238243 // Using "" for the FQCN, does it matter?
239 final LogEvent logEvent = rootLogger.getLogEventFactory().createEvent(rootLogger.getName(), null, Strings.EMPTY,
244 final LogEvent logEvent = getLogEventFactory().createEvent(rootLogger.getName(), null, Strings.EMPTY,
240245 rootLogger.getLevel(), null, null, null);
241246 return serializer.toSerializable(logEvent);
242247 }
3737 import org.apache.logging.log4j.core.net.Severity;
3838 import org.apache.logging.log4j.core.util.JsonUtils;
3939 import org.apache.logging.log4j.core.util.KeyValuePair;
40 import org.apache.logging.log4j.util.TriConsumer;
4041 import org.apache.logging.log4j.message.Message;
4142 import org.apache.logging.log4j.status.StatusLogger;
4243 import org.apache.logging.log4j.util.StringBuilderFormattable;
207208 JsonUtils.quoteAsString(toNullSafeString(additionalField.getValue()), builder);
208209 builder.append(QC);
209210 }
210 for (final Map.Entry<String, String> entry : event.getContextMap().entrySet()) {
211 builder.append(QU);
212 JsonUtils.quoteAsString(entry.getKey(), builder);
213 builder.append("\":\"");
214 JsonUtils.quoteAsString(toNullSafeString(entry.getValue()), builder);
215 builder.append(QC);
216 }
211 event.getContextData().forEach(WRITE_KEY_VALUES_INTO, builder);
217212 if (event.getThrown() != null) {
218213 builder.append("\"full_message\":\"");
219214 if (includeStacktrace) {
244239 return builder;
245240 }
246241
242 private static final TriConsumer<String, Object, StringBuilder> WRITE_KEY_VALUES_INTO = new TriConsumer<String, Object, StringBuilder>() {
243 @Override
244 public void accept(final String key, final Object value, final StringBuilder stringBuilder) {
245 stringBuilder.append(QU);
246 JsonUtils.quoteAsString(key, stringBuilder);
247 stringBuilder.append("\":\"");
248 JsonUtils.quoteAsString(toNullSafeString(String.valueOf(value)), stringBuilder);
249 stringBuilder.append(QC);
250 }
251 };
252
247253 private static final ThreadLocal<StringBuilder> messageStringBuilder = new ThreadLocal<>();
248254
249255 private static StringBuilder getMessageStringBuilder() {
256262 return result;
257263 }
258264
259 private CharSequence toNullSafeString(final CharSequence s) {
265 private static CharSequence toNullSafeString(final CharSequence s) {
260266 return s == null ? Strings.EMPTY : s;
261267 }
262268
3636 import org.apache.logging.log4j.core.config.plugins.PluginBuilderAttribute;
3737 import org.apache.logging.log4j.core.config.plugins.PluginBuilderFactory;
3838 import org.apache.logging.log4j.core.config.plugins.PluginFactory;
39 import org.apache.logging.log4j.core.util.Constants;
4039 import org.apache.logging.log4j.core.util.Transform;
40 import org.apache.logging.log4j.util.Strings;
4141
4242 /**
4343 * Outputs events as rows in an HTML table on an HTML page.
5555 public static final String DEFAULT_FONT_FAMILY = "arial,sans-serif";
5656
5757 private static final String TRACE_PREFIX = "<br />&nbsp;&nbsp;&nbsp;&nbsp;";
58 private static final String REGEXP = Constants.LINE_SEPARATOR.equals("\n") ? "\n" : Constants.LINE_SEPARATOR + "|\n";
58 private static final String REGEXP = Strings.LINE_SEPARATOR.equals("\n") ? "\n" : Strings.LINE_SEPARATOR + "|\n";
5959 private static final String DEFAULT_TITLE = "Log4j Log Messages";
6060 private static final String DEFAULT_CONTENT_TYPE = "text/html";
6161
109109 this.headerSize = headerSize;
110110 }
111111
112 /**
113 * For testing purposes.
114 */
115 public String getTitle() {
116 return title;
117 }
118
119 /**
120 * For testing purposes.
121 */
122 public boolean isLocationInfo() {
123 return locationInfo;
124 }
125
112126 private String addCharsetToContentType(final String contentType) {
113127 if (contentType == null) {
114128 return DEFAULT_CONTENT_TYPE + "; charset=" + getCharset();
126140 public String toSerializable(final LogEvent event) {
127141 final StringBuilder sbuf = getStringBuilder();
128142
129 sbuf.append(Constants.LINE_SEPARATOR).append("<tr>").append(Constants.LINE_SEPARATOR);
143 sbuf.append(Strings.LINE_SEPARATOR).append("<tr>").append(Strings.LINE_SEPARATOR);
130144
131145 sbuf.append("<td>");
132146 sbuf.append(event.getTimeMillis() - jvmStartTime);
133 sbuf.append("</td>").append(Constants.LINE_SEPARATOR);
147 sbuf.append("</td>").append(Strings.LINE_SEPARATOR);
134148
135149 final String escapedThread = Transform.escapeHtmlTags(event.getThreadName());
136150 sbuf.append("<td title=\"").append(escapedThread).append(" thread\">");
137151 sbuf.append(escapedThread);
138 sbuf.append("</td>").append(Constants.LINE_SEPARATOR);
152 sbuf.append("</td>").append(Strings.LINE_SEPARATOR);
139153
140154 sbuf.append("<td title=\"Level\">");
141155 if (event.getLevel().equals(Level.DEBUG)) {
149163 } else {
150164 sbuf.append(Transform.escapeHtmlTags(String.valueOf(event.getLevel())));
151165 }
152 sbuf.append("</td>").append(Constants.LINE_SEPARATOR);
166 sbuf.append("</td>").append(Strings.LINE_SEPARATOR);
153167
154168 String escapedLogger = Transform.escapeHtmlTags(event.getLoggerName());
155169 if (escapedLogger.isEmpty()) {
157171 }
158172 sbuf.append("<td title=\"").append(escapedLogger).append(" logger\">");
159173 sbuf.append(escapedLogger);
160 sbuf.append("</td>").append(Constants.LINE_SEPARATOR);
174 sbuf.append("</td>").append(Strings.LINE_SEPARATOR);
161175
162176 if (locationInfo) {
163177 final StackTraceElement element = event.getSource();
165179 sbuf.append(Transform.escapeHtmlTags(element.getFileName()));
166180 sbuf.append(':');
167181 sbuf.append(element.getLineNumber());
168 sbuf.append("</td>").append(Constants.LINE_SEPARATOR);
182 sbuf.append("</td>").append(Strings.LINE_SEPARATOR);
169183 }
170184
171185 sbuf.append("<td title=\"Message\">");
172186 sbuf.append(Transform.escapeHtmlTags(event.getMessage().getFormattedMessage()).replaceAll(REGEXP, "<br />"));
173 sbuf.append("</td>").append(Constants.LINE_SEPARATOR);
174 sbuf.append("</tr>").append(Constants.LINE_SEPARATOR);
187 sbuf.append("</td>").append(Strings.LINE_SEPARATOR);
188 sbuf.append("</tr>").append(Strings.LINE_SEPARATOR);
175189
176190 if (event.getContextStack() != null && !event.getContextStack().isEmpty()) {
177191 sbuf.append("<tr><td bgcolor=\"#EEEEEE\" style=\"font-size : ").append(fontSize);
178192 sbuf.append(";\" colspan=\"6\" ");
179193 sbuf.append("title=\"Nested Diagnostic Context\">");
180194 sbuf.append("NDC: ").append(Transform.escapeHtmlTags(event.getContextStack().toString()));
181 sbuf.append("</td></tr>").append(Constants.LINE_SEPARATOR);
195 sbuf.append("</td></tr>").append(Strings.LINE_SEPARATOR);
182196 }
183197
184198 if (event.getContextMap() != null && !event.getContextMap().isEmpty()) {
186200 sbuf.append(";\" colspan=\"6\" ");
187201 sbuf.append("title=\"Mapped Diagnostic Context\">");
188202 sbuf.append("MDC: ").append(Transform.escapeHtmlTags(event.getContextMap().toString()));
189 sbuf.append("</td></tr>").append(Constants.LINE_SEPARATOR);
203 sbuf.append("</td></tr>").append(Strings.LINE_SEPARATOR);
190204 }
191205
192206 final Throwable throwable = event.getThrown();
194208 sbuf.append("<tr><td bgcolor=\"#993300\" style=\"color:White; font-size : ").append(fontSize);
195209 sbuf.append(";\" colspan=\"6\">");
196210 appendThrowableAsHtml(throwable, sbuf);
197 sbuf.append("</td></tr>").append(Constants.LINE_SEPARATOR);
211 sbuf.append("</td></tr>").append(Strings.LINE_SEPARATOR);
198212 }
199213
200214 return sbuf.toString();
239253 first = false;
240254 }
241255 sbuf.append(Transform.escapeHtmlTags(line));
242 sbuf.append(Constants.LINE_SEPARATOR);
256 sbuf.append(Strings.LINE_SEPARATOR);
243257 }
244258 }
245259
252266 final StringBuilder sbuf = new StringBuilder();
253267 sbuf.append("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" ");
254268 sbuf.append("\"http://www.w3.org/TR/html4/loose.dtd\">");
255 sbuf.append(Constants.LINE_SEPARATOR);
256 sbuf.append("<html>").append(Constants.LINE_SEPARATOR);
257 sbuf.append("<head>").append(Constants.LINE_SEPARATOR);
258 sbuf.append("<meta charset=\"").append(getCharset()).append("\"/>").append(Constants.LINE_SEPARATOR);
259 sbuf.append("<title>").append(title).append("</title>").append(Constants.LINE_SEPARATOR);
260 sbuf.append("<style type=\"text/css\">").append(Constants.LINE_SEPARATOR);
261 sbuf.append("<!--").append(Constants.LINE_SEPARATOR);
269 sbuf.append(Strings.LINE_SEPARATOR);
270 sbuf.append("<html>").append(Strings.LINE_SEPARATOR);
271 sbuf.append("<head>").append(Strings.LINE_SEPARATOR);
272 sbuf.append("<meta charset=\"").append(getCharset()).append("\"/>").append(Strings.LINE_SEPARATOR);
273 sbuf.append("<title>").append(title).append("</title>").append(Strings.LINE_SEPARATOR);
274 sbuf.append("<style type=\"text/css\">").append(Strings.LINE_SEPARATOR);
275 sbuf.append("<!--").append(Strings.LINE_SEPARATOR);
262276 sbuf.append("body, table {font-family:").append(font).append("; font-size: ");
263 sbuf.append(headerSize).append(";}").append(Constants.LINE_SEPARATOR);
264 sbuf.append("th {background: #336699; color: #FFFFFF; text-align: left;}").append(Constants.LINE_SEPARATOR);
265 sbuf.append("-->").append(Constants.LINE_SEPARATOR);
266 sbuf.append("</style>").append(Constants.LINE_SEPARATOR);
267 sbuf.append("</head>").append(Constants.LINE_SEPARATOR);
268 sbuf.append("<body bgcolor=\"#FFFFFF\" topmargin=\"6\" leftmargin=\"6\">").append(Constants.LINE_SEPARATOR);
269 sbuf.append("<hr size=\"1\" noshade=\"noshade\">").append(Constants.LINE_SEPARATOR);
270 sbuf.append("Log session start time " + new java.util.Date() + "<br>").append(Constants.LINE_SEPARATOR);
271 sbuf.append("<br>").append(Constants.LINE_SEPARATOR);
277 sbuf.append(headerSize).append(";}").append(Strings.LINE_SEPARATOR);
278 sbuf.append("th {background: #336699; color: #FFFFFF; text-align: left;}").append(Strings.LINE_SEPARATOR);
279 sbuf.append("-->").append(Strings.LINE_SEPARATOR);
280 sbuf.append("</style>").append(Strings.LINE_SEPARATOR);
281 sbuf.append("</head>").append(Strings.LINE_SEPARATOR);
282 sbuf.append("<body bgcolor=\"#FFFFFF\" topmargin=\"6\" leftmargin=\"6\">").append(Strings.LINE_SEPARATOR);
283 sbuf.append("<hr size=\"1\" noshade=\"noshade\">").append(Strings.LINE_SEPARATOR);
284 sbuf.append("Log session start time " + new java.util.Date() + "<br>").append(Strings.LINE_SEPARATOR);
285 sbuf.append("<br>").append(Strings.LINE_SEPARATOR);
272286 sbuf.append(
273287 "<table cellspacing=\"0\" cellpadding=\"4\" border=\"1\" bordercolor=\"#224466\" width=\"100%\">");
274 sbuf.append(Constants.LINE_SEPARATOR);
275 sbuf.append("<tr>").append(Constants.LINE_SEPARATOR);
276 sbuf.append("<th>Time</th>").append(Constants.LINE_SEPARATOR);
277 sbuf.append("<th>Thread</th>").append(Constants.LINE_SEPARATOR);
278 sbuf.append("<th>Level</th>").append(Constants.LINE_SEPARATOR);
279 sbuf.append("<th>Logger</th>").append(Constants.LINE_SEPARATOR);
288 sbuf.append(Strings.LINE_SEPARATOR);
289 sbuf.append("<tr>").append(Strings.LINE_SEPARATOR);
290 sbuf.append("<th>Time</th>").append(Strings.LINE_SEPARATOR);
291 sbuf.append("<th>Thread</th>").append(Strings.LINE_SEPARATOR);
292 sbuf.append("<th>Level</th>").append(Strings.LINE_SEPARATOR);
293 sbuf.append("<th>Logger</th>").append(Strings.LINE_SEPARATOR);
280294 if (locationInfo) {
281 sbuf.append("<th>File:Line</th>").append(Constants.LINE_SEPARATOR);
282 }
283 sbuf.append("<th>Message</th>").append(Constants.LINE_SEPARATOR);
284 sbuf.append("</tr>").append(Constants.LINE_SEPARATOR);
295 sbuf.append("<th>File:Line</th>").append(Strings.LINE_SEPARATOR);
296 }
297 sbuf.append("<th>Message</th>").append(Strings.LINE_SEPARATOR);
298 sbuf.append("</tr>").append(Strings.LINE_SEPARATOR);
285299 return sbuf.toString().getBytes(getCharset());
286300 }
287301
292306 @Override
293307 public byte[] getFooter() {
294308 final StringBuilder sbuf = new StringBuilder();
295 sbuf.append("</table>").append(Constants.LINE_SEPARATOR);
296 sbuf.append("<br>").append(Constants.LINE_SEPARATOR);
309 sbuf.append("</table>").append(Strings.LINE_SEPARATOR);
310 sbuf.append("<br>").append(Strings.LINE_SEPARATOR);
297311 sbuf.append("</body></html>");
298312 return getBytes(sbuf.toString());
299313 }
4242 static class JSON extends JacksonFactory {
4343
4444 private final boolean encodeThreadContextAsList;
45
46 public JSON(final boolean encodeThreadContextAsList) {
45 private final boolean includeStacktrace;
46
47 public JSON(final boolean encodeThreadContextAsList, final boolean includeStacktrace) {
4748 this.encodeThreadContextAsList = encodeThreadContextAsList;
49 this.includeStacktrace = includeStacktrace;
4850 }
4951
5052 @Override
6971
7072 @Override
7173 protected ObjectMapper newObjectMapper() {
72 return new Log4jJsonObjectMapper(encodeThreadContextAsList);
74 return new Log4jJsonObjectMapper(encodeThreadContextAsList, includeStacktrace);
7375 }
7476
7577 @Override
8183 static class XML extends JacksonFactory {
8284
8385 static final int DEFAULT_INDENT = 1;
86
87 private final boolean includeStacktrace;
88
89 public XML(final boolean includeStacktrace) {
90 this.includeStacktrace = includeStacktrace;
91 }
8492
8593 @Override
8694 protected String getPropertNameForContextMap() {
105113
106114 @Override
107115 protected ObjectMapper newObjectMapper() {
108 return new Log4jXmlObjectMapper();
116 return new Log4jXmlObjectMapper(includeStacktrace);
109117 }
110118
111119 @Override
116124
117125 static class YAML extends JacksonFactory {
118126
127 private final boolean includeStacktrace;
128
129 public YAML(final boolean includeStacktrace) {
130 this.includeStacktrace = includeStacktrace;
131 }
132
119133 @Override
120134 protected String getPropertNameForContextMap() {
121135 return JsonConstants.ELT_CONTEXT_MAP;
138152
139153 @Override
140154 protected ObjectMapper newObjectMapper() {
141 return new Log4jYamlObjectMapper(false);
155 return new Log4jYamlObjectMapper(false, includeStacktrace);
142156 }
143157
144158 @Override
809809 protected JsonLayout(final Configuration config, final boolean locationInfo, final boolean properties,
810810 final boolean encodeThreadContextAsList,
811811 final boolean complete, final boolean compact, final boolean eventEol, final String headerPattern,
812 final String footerPattern, final Charset charset) {
813 super(config, new JacksonFactory.JSON(encodeThreadContextAsList).newWriter(locationInfo, properties, compact),
812 final String footerPattern, final Charset charset, final boolean includeStacktrace) {
813 super(config, new JacksonFactory.JSON(encodeThreadContextAsList, includeStacktrace).newWriter(
814 locationInfo, properties, compact),
814815 charset, compact, complete, eventEol,
815816 PatternLayout.createSerializer(config, null, headerPattern, DEFAULT_HEADER, null, false, false),
816817 PatternLayout.createSerializer(config, null, footerPattern, DEFAULT_FOOTER, null, false, false));
896897 * The header pattern, defaults to {@code "]"} if null.
897898 * @param charset
898899 * The character set to use, if {@code null}, uses "UTF-8".
900 * @param includeStacktrace
901 * If "true", includes the stacktrace of any Throwable in the generated JSON, defaults to "true".
899902 * @return A JSON Layout.
900903 */
901904 @PluginFactory
910913 @PluginAttribute(value = "eventEol", defaultBoolean = false) final boolean eventEol,
911914 @PluginAttribute(value = "header", defaultString = DEFAULT_HEADER) final String headerPattern,
912915 @PluginAttribute(value = "footer", defaultString = DEFAULT_FOOTER) final String footerPattern,
913 @PluginAttribute(value = "charset", defaultString = "UTF-8") final Charset charset
916 @PluginAttribute(value = "charset", defaultString = "UTF-8") final Charset charset,
917 @PluginAttribute(value = "includeStacktrace", defaultBoolean = true) final boolean includeStacktrace
914918 // @formatter:on
915919 ) {
916920 final boolean encodeThreadContextAsList = properties && propertiesAsList;
917921 return new JsonLayout(config, locationInfo, properties, encodeThreadContextAsList, complete, compact, eventEol,
918 headerPattern, footerPattern, charset);
922 headerPattern, footerPattern, charset, includeStacktrace);
919923 }
920924
921925 /**
925929 */
926930 public static JsonLayout createDefaultLayout() {
927931 return new JsonLayout(new DefaultConfiguration(), false, false, false, false, false, false,
928 DEFAULT_HEADER, DEFAULT_FOOTER, StandardCharsets.UTF_8);
932 DEFAULT_HEADER, DEFAULT_FOOTER, StandardCharsets.UTF_8, true);
929933 }
930934
931935 @Override
9797 defaultPattern = PatternLayout.DEFAULT_CONVERSION_PATTERN;
9898 }
9999 if (properties == null || properties.length == 0) {
100 LOGGER.warn("No marker patterns were provided");
100 LOGGER.warn("No marker patterns were provided with PatternMatch");
101 return null;
101102 }
102103 return new MarkerPatternSelector(properties, defaultPattern, alwaysWriteExceptions,
103104 noConsoleNoAnsi, config);
6363 public static final String DEFAULT_CONVERSION_PATTERN = "%m%n";
6464
6565 /**
66 * A conversion pattern equivalent to the TTCCCLayout. Current value is <b>%r [%t] %p %c %x - %m%n</b>.
67 */
68 public static final String TTCC_CONVERSION_PATTERN = "%r [%t] %p %c %x - %m%n";
66 * A conversion pattern equivalent to the TTCCLayout. Current value is <b>%r [%t] %p %c %notEmpty{%x }- %m%n</b>.
67 */
68 public static final String TTCC_CONVERSION_PATTERN = "%r [%t] %p %c %notEmpty{%x }- %m%n";
6969
7070 /**
7171 * A simple pattern. Current value is <b>%d [%t] %p %c - %m%n</b>.
8383 private final Serializer eventSerializer;
8484
8585 /**
86 * Constructs a EnhancedPatternLayout using the supplied conversion pattern.
86 * Constructs a PatternLayout using the supplied conversion pattern.
8787 *
8888 * @param config The Configuration.
8989 * @param replace The regular expression to match.
407407 private String pattern = PatternLayout.DEFAULT_CONVERSION_PATTERN;
408408
409409 @PluginElement("PatternSelector")
410 private PatternSelector patternSelector = null;
410 private PatternSelector patternSelector;
411411
412412 @PluginConfiguration
413 private Configuration configuration = null;
413 private Configuration configuration;
414414
415415 @PluginElement("Replace")
416 private RegexReplacement regexReplacement = null;
416 private RegexReplacement regexReplacement;
417417
418418 // LOG4J2-783 use platform default by default
419419 @PluginBuilderAttribute
423423 private boolean alwaysWriteExceptions = true;
424424
425425 @PluginBuilderAttribute
426 private boolean noConsoleNoAnsi = false;
427
428 @PluginBuilderAttribute
429 private String header = null;
430
431 @PluginBuilderAttribute
432 private String footer = null;
426 private boolean noConsoleNoAnsi;
427
428 @PluginBuilderAttribute
429 private String header;
430
431 @PluginBuilderAttribute
432 private String footer;
433433
434434 private Builder() {
435435 }
119119 }
120120 if (properties == null || properties.length == 0) {
121121 LOGGER.warn("No marker patterns were provided");
122 return null;
122123 }
123124 return new ScriptPatternSelector(script, properties, defaultPattern, alwaysWriteExceptions, noConsoleNoAnsi, config);
124125 }
193193
194194 private static final String ROOT_TAG = "Events";
195195
196 protected XmlLayout(final boolean locationInfo, final boolean properties, final boolean complete, final boolean compact, final Charset charset) {
197 super(null, new JacksonFactory.XML().newWriter(locationInfo, properties, compact), charset, compact, complete, false, null, null);
196 protected XmlLayout(final boolean locationInfo, final boolean properties, final boolean complete,
197 final boolean compact, final Charset charset, final boolean includeStacktrace) {
198 super(null, new JacksonFactory.XML(includeStacktrace).newWriter(
199 locationInfo, properties, compact), charset, compact, complete, false, null, null);
198200 }
199201
200202 /**
271273 * @param complete If "true", includes the XML header and footer, defaults to "false".
272274 * @param compact If "true", does not use end-of-lines and indentation, defaults to "false".
273275 * @param charset The character set to use, if {@code null}, uses "UTF-8".
276 * @param includeStacktrace
277 * If "true", includes the stacktrace of any Throwable in the generated XML, defaults to "true".
274278 * @return An XML Layout.
275279 */
276280 @PluginFactory
280284 @PluginAttribute(value = "properties", defaultBoolean = false) final boolean properties,
281285 @PluginAttribute(value = "complete", defaultBoolean = false) final boolean complete,
282286 @PluginAttribute(value = "compact", defaultBoolean = false) final boolean compact,
283 @PluginAttribute(value = "charset", defaultString = "UTF-8") final Charset charset)
287 @PluginAttribute(value = "charset", defaultString = "UTF-8") final Charset charset,
288 @PluginAttribute(value = "includeStacktrace", defaultBoolean = true) final boolean includeStacktrace)
284289 // @formatter:on
285290 {
286 return new XmlLayout(locationInfo, properties, complete, compact, charset);
291 return new XmlLayout(locationInfo, properties, complete, compact, charset, includeStacktrace);
287292 }
288293
289294 /**
292297 * @return an XML Layout.
293298 */
294299 public static XmlLayout createDefaultLayout() {
295 return new XmlLayout(false, false, false, false, StandardCharsets.UTF_8);
300 return new XmlLayout(false, false, false, false, StandardCharsets.UTF_8, true);
296301 }
297302 }
709709
710710 protected YamlLayout(final Configuration config, final boolean locationInfo, final boolean properties,
711711 final boolean complete, final boolean compact, final boolean eventEol, final String headerPattern,
712 final String footerPattern, final Charset charset) {
713 super(config, new JacksonFactory.YAML().newWriter(locationInfo, properties, compact), charset, compact,
712 final String footerPattern, final Charset charset, final boolean includeStacktrace) {
713 super(config, new JacksonFactory.YAML(includeStacktrace).newWriter(locationInfo, properties, compact), charset, compact,
714714 complete, eventEol,
715715 PatternLayout.createSerializer(config, null, headerPattern, DEFAULT_HEADER, null, false, false),
716716 PatternLayout.createSerializer(config, null, footerPattern, DEFAULT_FOOTER, null, false, false));
785785 * The header pattern, defaults to {@code ""} if null.
786786 * @param charset
787787 * The character set to use, if {@code null}, uses "UTF-8".
788 * @param includeStacktrace
789 * If "true", includes the stacktrace of any Throwable in the generated YAML, defaults to "true".
788790 * @return A YAML Layout.
789791 */
790792 @PluginFactory
795797 @PluginAttribute(value = "properties", defaultBoolean = false) final boolean properties,
796798 @PluginAttribute(value = "header", defaultString = DEFAULT_HEADER) final String headerPattern,
797799 @PluginAttribute(value = "footer", defaultString = DEFAULT_FOOTER) final String footerPattern,
798 @PluginAttribute(value = "charset", defaultString = "UTF-8") final Charset charset
800 @PluginAttribute(value = "charset", defaultString = "UTF-8") final Charset charset,
801 @PluginAttribute(value = "includeStacktrace", defaultBoolean = true) final boolean includeStacktrace
799802 // @formatter:on
800803 ) {
801804 return new YamlLayout(config, locationInfo, properties, false, false, true, headerPattern, footerPattern,
802 charset);
805 charset, includeStacktrace);
803806 }
804807
805808 /**
809812 */
810813 public static AbstractJacksonLayout createDefaultLayout() {
811814 return new YamlLayout(new DefaultConfiguration(), false, false, false, false, false, DEFAULT_HEADER,
812 DEFAULT_FOOTER, StandardCharsets.UTF_8);
815 DEFAULT_FOOTER, StandardCharsets.UTF_8, true);
813816 }
814817
815818 @Override
1818 import org.apache.logging.log4j.ThreadContext;
1919 import org.apache.logging.log4j.core.LogEvent;
2020 import org.apache.logging.log4j.core.config.plugins.Plugin;
21 import org.apache.logging.log4j.core.ContextDataInjector;
22 import org.apache.logging.log4j.core.impl.ContextDataInjectorFactory;
23 import org.apache.logging.log4j.util.ReadOnlyStringMap;
2124
2225 /**
23 * Looks up keys from {@link ThreadContext} objects..
26 * Looks up keys from the context. By default this is the {@link ThreadContext}, but users may
27 * {@linkplain ContextDataInjectorFactory configure} a custom {@link ContextDataInjector} which obtains context data
28 * from some other source.
2429 */
2530 @Plugin(name = "ctx", category = StrLookup.CATEGORY)
2631 public class ContextMapLookup implements StrLookup {
32
33 private final ContextDataInjector injector = ContextDataInjectorFactory.createInjector();
2734
2835 /**
2936 * Looks up the value from the ThreadContext Map.
3239 */
3340 @Override
3441 public String lookup(final String key) {
35 return ThreadContext.get(key);
42 return currentContextData().getValue(key);
43 }
44
45 private ReadOnlyStringMap currentContextData() {
46 return injector.rawContextData();
3647 }
3748
3849 /**
4354 */
4455 @Override
4556 public String lookup(final LogEvent event, final String key) {
46 return event.getContextMap().get(key);
57 return event.getContextData().getValue(key);
4758 }
4859 }
3333 */
3434 public class Interpolator extends AbstractConfigurationAwareLookup {
3535
36 private static final String LOOKUP_KEY_WEB = "web";
37
38 private static final String LOOKUP_KEY_JNDI = "jndi";
39
40 private static final String LOOKUP_KEY_JVMRUNARGS = "jvmrunargs";
41
3642 private static final Logger LOGGER = StatusLogger.getLogger();
3743
3844 /** Constant for the prefix separator. */
6369 try {
6470 final Class<? extends StrLookup> clazz = entry.getValue().getPluginClass().asSubclass(StrLookup.class);
6571 lookups.put(entry.getKey(), ReflectionUtil.instantiate(clazz));
66 } catch (final Exception ex) {
67 LOGGER.error("Unable to create Lookup for {}", entry.getKey(), ex);
72 } catch (final Throwable t) {
73 handleError(entry.getKey(), t);
6874 }
6975 }
7076 }
9197 // JNDI
9298 try {
9399 // [LOG4J2-703] We might be on Android
94 lookups.put("jndi",
100 lookups.put(LOOKUP_KEY_JNDI,
95101 Loader.newCheckedInstanceOf("org.apache.logging.log4j.core.lookup.JndiLookup", StrLookup.class));
96 } catch (final Throwable e) {
97 // java.lang.VerifyError: org/apache/logging/log4j/core/lookup/JndiLookup
98 LOGGER.warn(
99 "JNDI lookup class is not available because this JRE does not support JNDI. JNDI string lookups will not be available, continuing configuration.",
100 e);
102 } catch (final LinkageError | Exception e) {
103 handleError(LOOKUP_KEY_JNDI, e);
101104 }
102105 // JMX input args
103106 try {
104107 // We might be on Android
105 lookups.put("jvmrunargs",
106 Loader.newCheckedInstanceOf("org.apache.logging.log4j.core.lookup.JmxRuntimeInputArgumentsLookup", StrLookup.class));
107 } catch (final Throwable e) {
108 // java.lang.VerifyError: org/apache/logging/log4j/core/lookup/JmxRuntimeInputArgumentsLookup
109 LOGGER.warn(
110 "JMX runtime input lookup class is not available because this JRE does not support JMX. JMX lookups will not be available, continuing configuration.",
111 e);
108 lookups.put(LOOKUP_KEY_JVMRUNARGS,
109 Loader.newCheckedInstanceOf("org.apache.logging.log4j.core.lookup.JmxRuntimeInputArgumentsLookup",
110 StrLookup.class));
111 } catch (final LinkageError | Exception e) {
112 handleError(LOOKUP_KEY_JVMRUNARGS, e);
112113 }
113114 lookups.put("date", new DateLookup());
114115 lookups.put("ctx", new ContextMapLookup());
115116 if (Loader.isClassAvailable("javax.servlet.ServletContext")) {
116117 try {
117 lookups.put("web",
118 lookups.put(LOOKUP_KEY_WEB,
118119 Loader.newCheckedInstanceOf("org.apache.logging.log4j.web.WebLookup", StrLookup.class));
119120 } catch (final Exception ignored) {
120 LOGGER.info("Log4j appears to be running in a Servlet environment, but there's no log4j-web module " +
121 "available. If you want better web container support, please add the log4j-web JAR to your " +
122 "web archive or server lib directory.");
121 handleError(LOOKUP_KEY_WEB, ignored);
123122 }
124123 } else {
125124 LOGGER.debug("Not in a ServletContext environment, thus not loading WebLookup plugin.");
125 }
126 }
127
128 private void handleError(final String lookupKey, final Throwable t) {
129 switch (lookupKey) {
130 case LOOKUP_KEY_JNDI:
131 // java.lang.VerifyError: org/apache/logging/log4j/core/lookup/JndiLookup
132 LOGGER.warn( // LOG4J2-1582 don't print the whole stack trace (it is just a warning...)
133 "JNDI lookup class is not available because this JRE does not support JNDI." +
134 " JNDI string lookups will not be available, continuing configuration. Ignoring " + t);
135 break;
136 case LOOKUP_KEY_JVMRUNARGS:
137 // java.lang.VerifyError: org/apache/logging/log4j/core/lookup/JmxRuntimeInputArgumentsLookup
138 LOGGER.warn(
139 "JMX runtime input lookup class is not available because this JRE does not support JMX. " +
140 "JMX lookups will not be available, continuing configuration. Ignoring " + t);
141 break;
142 case LOOKUP_KEY_WEB:
143 LOGGER.info("Log4j appears to be running in a Servlet environment, but there's no log4j-web module " +
144 "available. If you want better web container support, please add the log4j-web JAR to your " +
145 "web archive or server lib directory.");
146 break;
147 default:
148 LOGGER.error("Unable to create Lookup for {}", lookupKey, t);
126149 }
127150 }
128151
5757 LOGGER.warn(LOOKUP, "Error looking up JNDI resource [{}].", jndiName, e);
5858 return null;
5959 } finally {
60 jndiManager.release();
60 jndiManager.close();
6161 }
6262 }
6363
198198 public StrSubstitutor() {
199199 this(null, DEFAULT_PREFIX, DEFAULT_SUFFIX, DEFAULT_ESCAPE);
200200 }
201
201202 /**
202203 * Creates a new instance and initializes it. Uses defaults for variable
203204 * prefix and suffix and the escaping character.
249250 this(new MapLookup(valueMap), prefix, suffix, escape, valueDelimiter);
250251 }
251252
253 /**
254 * Creates a new instance and initializes it. Uses defaults for variable
255 * prefix and suffix and the escaping character.
256 *
257 * @param properties the map with the variables' values, may be null
258 */
259 public StrSubstitutor(Properties properties) {
260 this(toTypeSafeMap(properties));
261 }
262
252263 /**
253264 * Creates a new instance and initializes it.
254265 *
377388 valueMap.put(propName, propValue);
378389 }
379390 return StrSubstitutor.replace(source, valueMap);
391 }
392
393 private static Map<String, String> toTypeSafeMap(Properties properties) {
394 Map<String, String> map = new HashMap<>(properties.size());
395 for (final String name : properties.stringPropertyNames()) {
396 map.put(name, properties.getProperty(name));
397 }
398 return map;
380399 }
381400
382401 //-----------------------------------------------------------------------
5151 * @param inetAddress The Internet address.
5252 * @param host The target host name.
5353 * @param port The target port number.
54 * @param bufferSize The buffer size.
5455 */
5556 public AbstractSocketManager(final String name, final OutputStream os, final InetAddress inetAddress,
56 final String host, final int port, final Layout<? extends Serializable> layout, final boolean writeHeader) {
57 super(os, name, layout, writeHeader);
57 final String host, final int port, final Layout<? extends Serializable> layout, final boolean writeHeader,
58 final int bufferSize) {
59 super(os, name, layout, writeHeader, bufferSize);
5860 this.inetAddress = inetAddress;
5961 this.host = host;
6062 this.port = port;
4141 * @param host The host to connect to.
4242 * @param port The port on the host.
4343 * @param layout The layout
44 * @param bufferSize The buffer size
4445 */
4546 protected DatagramSocketManager(final String name, final OutputStream os, final InetAddress inetAddress, final String host,
46 final int port, final Layout<? extends Serializable> layout) {
47 super(name, os, inetAddress, host, port, layout, true);
47 final int port, final Layout<? extends Serializable> layout, final int bufferSize) {
48 super(name, os, inetAddress, host, port, layout, true, bufferSize);
4849 }
4950
5051 /**
5253 * @param host The host to connect to.
5354 * @param port The port on the host.
5455 * @param layout The layout.
56 * @param bufferSize The buffer size.
5557 * @return A DatagramSocketManager.
5658 */
57 public static DatagramSocketManager getSocketManager(final String host, final int port, final Layout<? extends Serializable> layout) {
59 public static DatagramSocketManager getSocketManager(final String host, final int port,
60 final Layout<? extends Serializable> layout, final int bufferSize) {
5861 if (Strings.isEmpty(host)) {
5962 throw new IllegalArgumentException("A host name is required");
6063 }
6164 if (port <= 0) {
6265 throw new IllegalArgumentException("A port value is required");
6366 }
64 return (DatagramSocketManager) getManager("UDP:" + host + ':' + port, new FactoryData(host, port, layout),
65 FACTORY);
67 return (DatagramSocketManager) getManager("UDP:" + host + ':' + port,
68 new FactoryData(host, port, layout, bufferSize), FACTORY);
6669 }
6770
6871 /**
8992 private final String host;
9093 private final int port;
9194 private final Layout<? extends Serializable> layout;
92
93 public FactoryData(final String host, final int port, final Layout<? extends Serializable> layout) {
95 private final int bufferSize;
96
97 public FactoryData(final String host, final int port, final Layout<? extends Serializable> layout, final int bufferSize) {
9498 this.host = host;
9599 this.port = port;
96100 this.layout = layout;
101 this.bufferSize = bufferSize;
97102 }
98103 }
99104
113118 }
114119 final OutputStream os = new DatagramOutputStream(data.host, data.port, data.layout.getHeader(),
115120 data.layout.getFooter());
116 return new DatagramSocketManager(name, os, inetAddress, data.host, data.port, data.layout);
121 return new DatagramSocketManager(name, os, inetAddress, data.host, data.port, data.layout, data.bufferSize);
117122 }
118123 }
119124 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16
17 package org.apache.logging.log4j.core.net;
18
19 import java.util.Properties;
20
21 import javax.naming.Context;
22 import javax.naming.InitialContext;
23 import javax.naming.NamingException;
24
25 import org.apache.logging.log4j.core.appender.AbstractManager;
26 import org.apache.logging.log4j.core.appender.ManagerFactory;
27 import org.apache.logging.log4j.core.util.JndiCloser;
28
29 /**
30 * JNDI {@link javax.naming.Context} manager.
31 *
32 * @since 2.1
33 */
34 public class JndiManager extends AbstractManager {
35
36 private static final JndiManagerFactory FACTORY = new JndiManagerFactory();
37
38 private final Context context;
39
40 private JndiManager(final String name, final Context context) {
41 super(name);
42 this.context = context;
43 }
44
45 /**
46 * Gets the default JndiManager using the default {@link javax.naming.InitialContext}.
47 *
48 * @return the default JndiManager
49 */
50 public static JndiManager getDefaultManager() {
51 return getManager(JndiManager.class.getName(), FACTORY, null);
52 }
53
54 /**
55 * Gets a named JndiManager using the default {@link javax.naming.InitialContext}.
56 * @param name the name of the JndiManager instance to create or use if available
57 * @return a default JndiManager
58 */
59 public static JndiManager getDefaultManager(final String name) {
60 return getManager(name, FACTORY, null);
61 }
62
63 /**
64 * Gets a JndiManager with the provided configuration information.
65 *
66 * @param initialContextFactoryName Fully qualified class name of an implementation of
67 * {@link javax.naming.spi.InitialContextFactory}.
68 * @param providerURL The provider URL to use for the JNDI connection (specific to the above factory).
69 * @param urlPkgPrefixes A colon-separated list of package prefixes for the class name of the factory
70 * class that will create a URL context factory
71 * @param securityPrincipal The name of the identity of the Principal.
72 * @param securityCredentials The security credentials of the Principal.
73 * @param additionalProperties Any additional JNDI environment properties to set or {@code null} for none.
74 * @return the JndiManager for the provided parameters.
75 */
76 public static JndiManager getJndiManager(final String initialContextFactoryName,
77 final String providerURL,
78 final String urlPkgPrefixes,
79 final String securityPrincipal,
80 final String securityCredentials,
81 final Properties additionalProperties) {
82 final String name = JndiManager.class.getName() + '@' + JndiManager.class.hashCode();
83 if (initialContextFactoryName == null) {
84 return getManager(name, FACTORY, null);
85 }
86 final Properties properties = new Properties();
87 properties.setProperty(Context.INITIAL_CONTEXT_FACTORY, initialContextFactoryName);
88 if (providerURL != null) {
89 properties.setProperty(Context.PROVIDER_URL, providerURL);
90 } else {
91 LOGGER.warn("The JNDI InitialContextFactory class name [{}] was provided, but there was no associated " +
92 "provider URL. This is likely to cause problems.", initialContextFactoryName);
93 }
94 if (urlPkgPrefixes != null) {
95 properties.setProperty(Context.URL_PKG_PREFIXES, urlPkgPrefixes);
96 }
97 if (securityPrincipal != null) {
98 properties.setProperty(Context.SECURITY_PRINCIPAL, securityPrincipal);
99 if (securityCredentials != null) {
100 properties.setProperty(Context.SECURITY_CREDENTIALS, securityCredentials);
101 } else {
102 LOGGER.warn("A security principal [{}] was provided, but with no corresponding security credentials.",
103 securityPrincipal);
104 }
105 }
106 if (additionalProperties != null) {
107 properties.putAll(additionalProperties);
108 }
109 return getManager(name, FACTORY, properties);
110 }
111
112 @Override
113 protected void releaseSub() {
114 JndiCloser.closeSilently(this.context);
115 }
116
117 /**
118 * Looks up a named object through this JNDI context.
119 *
120 * @param name name of the object to look up.
121 * @param <T> the type of the object.
122 * @return the named object if it could be located.
123 * @throws NamingException
124 */
125 @SuppressWarnings("unchecked")
126 public <T> T lookup(final String name) throws NamingException {
127 return (T) this.context.lookup(name);
128 }
129
130 private static class JndiManagerFactory implements ManagerFactory<JndiManager, Properties> {
131
132 @Override
133 public JndiManager createManager(final String name, final Properties data) {
134 try {
135 return new JndiManager(name, new InitialContext(data));
136 } catch (final NamingException e) {
137 LOGGER.error("Error creating JNDI InitialContext.", e);
138 return null;
139 }
140 }
141 }
142 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16
17 package org.apache.logging.log4j.core.net;
18
19 import java.util.Properties;
20 import java.util.concurrent.TimeUnit;
21
22 import javax.naming.Context;
23 import javax.naming.InitialContext;
24 import javax.naming.NamingException;
25
26 import org.apache.logging.log4j.core.appender.AbstractManager;
27 import org.apache.logging.log4j.core.appender.ManagerFactory;
28 import org.apache.logging.log4j.core.util.JndiCloser;
29
30 /**
31 * JNDI {@link javax.naming.Context} manager.
32 *
33 * @since 2.1
34 */
35 public class JndiManager extends AbstractManager {
36
37 private static final JndiManagerFactory FACTORY = new JndiManagerFactory();
38
39 private final Context context;
40
41 private JndiManager(final String name, final Context context) {
42 super(null, name);
43 this.context = context;
44 }
45
46 /**
47 * Gets the default JndiManager using the default {@link javax.naming.InitialContext}.
48 *
49 * @return the default JndiManager
50 */
51 public static JndiManager getDefaultManager() {
52 return getManager(JndiManager.class.getName(), FACTORY, null);
53 }
54
55 /**
56 * Gets a named JndiManager using the default {@link javax.naming.InitialContext}.
57 * @param name the name of the JndiManager instance to create or use if available
58 * @return a default JndiManager
59 */
60 public static JndiManager getDefaultManager(final String name) {
61 return getManager(name, FACTORY, null);
62 }
63
64 /**
65 * Gets a JndiManager with the provided configuration information.
66 *
67 * @param initialContextFactoryName Fully qualified class name of an implementation of
68 * {@link javax.naming.spi.InitialContextFactory}.
69 * @param providerURL The provider URL to use for the JNDI connection (specific to the above factory).
70 * @param urlPkgPrefixes A colon-separated list of package prefixes for the class name of the factory
71 * class that will create a URL context factory
72 * @param securityPrincipal The name of the identity of the Principal.
73 * @param securityCredentials The security credentials of the Principal.
74 * @param additionalProperties Any additional JNDI environment properties to set or {@code null} for none.
75 * @return the JndiManager for the provided parameters.
76 */
77 public static JndiManager getJndiManager(final String initialContextFactoryName,
78 final String providerURL,
79 final String urlPkgPrefixes,
80 final String securityPrincipal,
81 final String securityCredentials,
82 final Properties additionalProperties) {
83 final String name = JndiManager.class.getName() + '@' + JndiManager.class.hashCode();
84 if (initialContextFactoryName == null) {
85 return getManager(name, FACTORY, null);
86 }
87 final Properties properties = new Properties();
88 properties.setProperty(Context.INITIAL_CONTEXT_FACTORY, initialContextFactoryName);
89 if (providerURL != null) {
90 properties.setProperty(Context.PROVIDER_URL, providerURL);
91 } else {
92 LOGGER.warn("The JNDI InitialContextFactory class name [{}] was provided, but there was no associated " +
93 "provider URL. This is likely to cause problems.", initialContextFactoryName);
94 }
95 if (urlPkgPrefixes != null) {
96 properties.setProperty(Context.URL_PKG_PREFIXES, urlPkgPrefixes);
97 }
98 if (securityPrincipal != null) {
99 properties.setProperty(Context.SECURITY_PRINCIPAL, securityPrincipal);
100 if (securityCredentials != null) {
101 properties.setProperty(Context.SECURITY_CREDENTIALS, securityCredentials);
102 } else {
103 LOGGER.warn("A security principal [{}] was provided, but with no corresponding security credentials.",
104 securityPrincipal);
105 }
106 }
107 if (additionalProperties != null) {
108 properties.putAll(additionalProperties);
109 }
110 return getManager(name, FACTORY, properties);
111 }
112
113 @Override
114 protected boolean releaseSub(final long timeout, final TimeUnit timeUnit) {
115 return JndiCloser.closeSilently(this.context);
116 }
117
118 /**
119 * Looks up a named object through this JNDI context.
120 *
121 * @param name name of the object to look up.
122 * @param <T> the type of the object.
123 * @return the named object if it could be located.
124 * @throws NamingException
125 */
126 @SuppressWarnings("unchecked")
127 public <T> T lookup(final String name) throws NamingException {
128 return (T) this.context.lookup(name);
129 }
130
131 private static class JndiManagerFactory implements ManagerFactory<JndiManager, Properties> {
132
133 @Override
134 public JndiManager createManager(final String name, final Properties data) {
135 try {
136 return new JndiManager(name, new InitialContext(data));
137 } catch (final NamingException e) {
138 LOGGER.error("Error creating JNDI InitialContext.", e);
139 return null;
140 }
141 }
142 }
143 }
2424 import org.apache.logging.log4j.Logger;
2525 import org.apache.logging.log4j.core.config.plugins.Plugin;
2626 import org.apache.logging.log4j.core.util.Integers;
27 import org.apache.logging.log4j.core.util.Loader;
2827 import org.apache.logging.log4j.status.StatusLogger;
28 import org.apache.logging.log4j.util.LoaderUtil;
2929
3030 /**
3131 * Advertise an entity via ZeroConf/MulticastDNS and the JmDNS library.
185185
186186 private static Object initializeJmDns() {
187187 try {
188 jmDNSClass = Loader.loadClass("javax.jmdns.JmDNS");
189 serviceInfoClass = Loader.loadClass("javax.jmdns.ServiceInfo");
188 jmDNSClass = LoaderUtil.loadClass("javax.jmdns.JmDNS");
189 serviceInfoClass = LoaderUtil.loadClass("javax.jmdns.ServiceInfo");
190190 // if version 3 is available, use it to constuct a serviceInfo instance, otherwise support the version1 API
191191 boolean isVersion3 = false;
192192 try {
7676
7777 protected SmtpManager(final String name, final Session session, final MimeMessage message,
7878 final FactoryData data) {
79 super(name);
79 super(null, name);
8080 this.session = session;
8181 this.message = message;
8282 this.data = data;
170170
171171 sendMultipartMessage(message, mp);
172172 } catch (final MessagingException | IOException | RuntimeException e) {
173 logError("caught exception while sending e-mail notification.", e);
173 logError("Caught exception while sending e-mail notification.", e);
174174 throw new LoggingException("Error occurred while sending email", e);
175175 }
176176 }
5454 * @param delay Reconnection interval.
5555 * @param immediateFail
5656 * @param layout The Layout.
57 * @param bufferSize The buffer size.
5758 */
5859 public SslSocketManager(final String name, final OutputStream os, final Socket sock,
5960 final SslConfiguration sslConfig, final InetAddress inetAddress, final String host, final int port,
6061 final int connectTimeoutMillis, final int delay, final boolean immediateFail,
61 final Layout<? extends Serializable> layout) {
62 super(name, os, sock, inetAddress, host, port, connectTimeoutMillis, delay, immediateFail, layout);
62 final Layout<? extends Serializable> layout, final int bufferSize) {
63 super(name, os, sock, inetAddress, host, port, connectTimeoutMillis, delay, immediateFail, layout, bufferSize);
6364 this.sslConfig = sslConfig;
6465 }
6566
6667 private static class SslFactoryData {
67 protected SslConfiguration sslConfig;
68 protected SslConfiguration sslConfiguration;
6869 private final String host;
6970 private final int port;
7071 private final int connectTimeoutMillis;
7172 private final int delayMillis;
7273 private final boolean immediateFail;
7374 private final Layout<? extends Serializable> layout;
75 private final int bufferSize;
7476
75 public SslFactoryData(final SslConfiguration sslConfig, final String host, final int port,
77 public SslFactoryData(final SslConfiguration sslConfiguration, final String host, final int port,
7678 final int connectTimeoutMillis, final int delayMillis, final boolean immediateFail,
77 final Layout<? extends Serializable> layout) {
79 final Layout<? extends Serializable> layout, final int bufferSize) {
7880 this.host = host;
7981 this.port = port;
8082 this.connectTimeoutMillis = connectTimeoutMillis;
8183 this.delayMillis = delayMillis;
8284 this.immediateFail = immediateFail;
8385 this.layout = layout;
84 this.sslConfig = sslConfig;
86 this.sslConfiguration = sslConfiguration;
87 this.bufferSize = bufferSize;
8588 }
8689 }
8790
8891 public static SslSocketManager getSocketManager(final SslConfiguration sslConfig, final String host, int port,
89 final int connectTimeoutMillis, int delayMillis, final boolean immediateFail,
90 final Layout<? extends Serializable> layout) {
92 final int connectTimeoutMillis, int reconnectDelayMillis, final boolean immediateFail,
93 final Layout<? extends Serializable> layout, final int bufferSize) {
9194 if (Strings.isEmpty(host)) {
9295 throw new IllegalArgumentException("A host name is required");
9396 }
9497 if (port <= 0) {
9598 port = DEFAULT_PORT;
9699 }
97 if (delayMillis == 0) {
98 delayMillis = DEFAULT_RECONNECTION_DELAY_MILLIS;
100 if (reconnectDelayMillis == 0) {
101 reconnectDelayMillis = DEFAULT_RECONNECTION_DELAY_MILLIS;
99102 }
100103 return (SslSocketManager) getManager("TLS:" + host + ':' + port, new SslFactoryData(sslConfig, host, port,
101 connectTimeoutMillis, delayMillis, immediateFail, layout), FACTORY);
104 connectTimeoutMillis, reconnectDelayMillis, immediateFail, layout, bufferSize), FACTORY);
102105 }
103106
104107 @Override
150153 LOGGER.catching(Level.DEBUG, e);
151154 return null;
152155 }
153 return new SslSocketManager(name, os, socket, data.sslConfig, inetAddress, data.host, data.port, 0,
154 data.delayMillis, data.immediateFail, data.layout);
156 return new SslSocketManager(name, os, socket, data.sslConfiguration, inetAddress, data.host, data.port, 0,
157 data.delayMillis, data.immediateFail, data.layout, data.bufferSize);
155158 }
156159
157160 private InetAddress resolveAddress(final String hostName) throws TlsSocketManagerFactoryException {
177180 SSLSocketFactory socketFactory;
178181 SSLSocket socket;
179182
180 socketFactory = createSslSocketFactory(data.sslConfig);
183 socketFactory = createSslSocketFactory(data.sslConfiguration);
181184 socket = (SSLSocket) socketFactory.createSocket(data.host, data.port);
182185 return socket;
183186 }
1515 */
1616 package org.apache.logging.log4j.core.net;
1717
18 import java.io.ByteArrayOutputStream;
1918 import java.io.IOException;
2019 import java.io.OutputStream;
2120 import java.io.Serializable;
3231 import org.apache.logging.log4j.core.appender.AppenderLoggingException;
3332 import org.apache.logging.log4j.core.appender.ManagerFactory;
3433 import org.apache.logging.log4j.core.appender.OutputStreamManager;
34 import org.apache.logging.log4j.core.util.Log4jThread;
35 import org.apache.logging.log4j.core.util.NullOutputStream;
3536 import org.apache.logging.log4j.util.Strings;
3637
3738 /**
5152
5253 private final int reconnectionDelay;
5354
54 private Reconnector connector;
55 private Reconnector reconnector;
5556
5657 private Socket socket;
5758
6566 * The Constructor.
6667 * @param name The unique name of this connection.
6768 * @param os The OutputStream.
68 * @param sock The Socket.
69 * @param socket The Socket.
6970 * @param inetAddress The Internet address of the host.
7071 * @param host The name of the host.
7172 * @param port The port number on the host.
7273 * @param connectTimeoutMillis the connect timeout in milliseconds.
7374 * @param delay Reconnection interval.
74 * @param immediateFail
75 * @param immediateFail True if the write should fail if no socket is immediately available.
7576 * @param layout The Layout.
76 */
77 public TcpSocketManager(final String name, final OutputStream os, final Socket sock, final InetAddress inetAddress,
77 * @param bufferSize The buffer size.
78 */
79 public TcpSocketManager(final String name, final OutputStream os, final Socket socket, final InetAddress inetAddress,
7880 final String host, final int port, final int connectTimeoutMillis, final int delay,
79 final boolean immediateFail, final Layout<? extends Serializable> layout) {
80 super(name, os, inetAddress, host, port, layout, true);
81 final boolean immediateFail, final Layout<? extends Serializable> layout, final int bufferSize) {
82 super(name, os, inetAddress, host, port, layout, true, bufferSize);
8183 this.connectTimeoutMillis = connectTimeoutMillis;
8284 this.reconnectionDelay = delay;
83 this.socket = sock;
85 this.socket = socket;
8486 this.immediateFail = immediateFail;
8587 retry = delay > 0;
86 if (sock == null) {
87 connector = new Reconnector(this);
88 connector.setDaemon(true);
89 connector.setPriority(Thread.MIN_PRIORITY);
90 connector.start();
88 if (socket == null) {
89 reconnector = createReconnector();
90 reconnector.start();
9191 }
9292 }
9393
9696 * @param host The host to connect to.
9797 * @param port The port on the host.
9898 * @param connectTimeoutMillis the connect timeout in milliseconds
99 * @param delayMillis The interval to pause between retries.
99 * @param reconnectDelayMillis The interval to pause between retries.
100 * @param bufferSize The buffer size.
100101 * @return A TcpSocketManager.
101102 */
102103 public static TcpSocketManager getSocketManager(final String host, int port, final int connectTimeoutMillis,
103 int delayMillis, final boolean immediateFail, final Layout<? extends Serializable> layout) {
104 int reconnectDelayMillis, final boolean immediateFail, final Layout<? extends Serializable> layout, final int bufferSize) {
104105 if (Strings.isEmpty(host)) {
105106 throw new IllegalArgumentException("A host name is required");
106107 }
107108 if (port <= 0) {
108109 port = DEFAULT_PORT;
109110 }
110 if (delayMillis == 0) {
111 delayMillis = DEFAULT_RECONNECTION_DELAY_MILLIS;
112 }
113 return (TcpSocketManager) getManager("TCP:" + host + ':' + port, new FactoryData(host, port,
114 connectTimeoutMillis, delayMillis, immediateFail, layout), FACTORY);
111 if (reconnectDelayMillis == 0) {
112 reconnectDelayMillis = DEFAULT_RECONNECTION_DELAY_MILLIS;
113 }
114 return (TcpSocketManager) getManager("TCP:" + host + ':' + port, new FactoryData(
115 host, port, connectTimeoutMillis, reconnectDelayMillis, immediateFail, layout, bufferSize), FACTORY);
115116 }
116117
117118 @Override
118119 protected void write(final byte[] bytes, final int offset, final int length, final boolean immediateFlush) {
119120 if (socket == null) {
120 if (connector != null && !immediateFail) {
121 connector.latch();
121 if (reconnector != null && !immediateFail) {
122 reconnector.latch();
122123 }
123124 if (socket == null) {
124125 final String msg = "Error writing to " + getName() + " socket not available";
133134 outputStream.flush();
134135 }
135136 } catch (final IOException ex) {
136 if (retry && connector == null) {
137 connector = new Reconnector(this);
138 connector.setDaemon(true);
139 connector.setPriority(Thread.MIN_PRIORITY);
140 connector.start();
137 if (retry && reconnector == null) {
138 reconnector = createReconnector();
139 reconnector.start();
141140 }
142141 final String msg = "Error writing to " + getName();
143142 throw new AppenderLoggingException(msg, ex);
146145 }
147146
148147 @Override
149 protected synchronized void close() {
150 super.close();
151 if (connector != null) {
152 connector.shutdown();
153 connector.interrupt();
154 connector = null;
155 }
148 protected synchronized boolean closeOutputStream() {
149 final boolean closed = super.closeOutputStream();
150 if (reconnector != null) {
151 reconnector.shutdown();
152 reconnector.interrupt();
153 reconnector = null;
154 }
155 final Socket oldSocket = socket;
156 socket = null;
157 if (oldSocket != null) {
158 try {
159 oldSocket.close();
160 } catch (final IOException e) {
161 LOGGER.error("Could not close socket {}", socket);
162 return false;
163 }
164 }
165 return closed;
156166 }
157167
158168 public int getConnectTimeoutMillis() {
179189 /**
180190 * Handles reconnecting to a Thread.
181191 */
182 private class Reconnector extends Thread {
192 private class Reconnector extends Log4jThread {
183193
184194 private final CountDownLatch latch = new CountDownLatch(1);
185195
188198 private final Object owner;
189199
190200 public Reconnector(final OutputStreamManager owner) {
201 super("TcpSocketManager-Reconnector");
191202 this.owner = owner;
192203 }
193204
219230
220231 setOutputStream(newOS);
221232 socket = sock;
222 connector = null;
233 reconnector = null;
223234 shutdown = true;
224235 }
225236 LOGGER.debug("Connection to " + host + ':' + port + " reestablished.");
236247 }
237248 }
238249
250 private Reconnector createReconnector() {
251 final Reconnector recon = new Reconnector(this);
252 recon.setDaemon(true);
253 recon.setPriority(Thread.MIN_PRIORITY);
254 return recon;
255 }
256
239257 protected Socket createSocket(final InetAddress host, final int port) throws IOException {
240258 return createSocket(host.getHostName(), port);
241259 }
254272 private final String host;
255273 private final int port;
256274 private final int connectTimeoutMillis;
257 private final int delayMillis;
275 private final int reconnectDelayMillis;
258276 private final boolean immediateFail;
259277 private final Layout<? extends Serializable> layout;
260
261 public FactoryData(final String host, final int port, final int connectTimeoutMillis, final int delayMillis,
262 final boolean immediateFail, final Layout<? extends Serializable> layout) {
278 private final int bufferSize;
279
280 public FactoryData(final String host, final int port, final int connectTimeoutMillis, final int reconnectDelayMillis,
281 final boolean immediateFail, final Layout<? extends Serializable> layout, final int bufferSize) {
263282 this.host = host;
264283 this.port = port;
265284 this.connectTimeoutMillis = connectTimeoutMillis;
266 this.delayMillis = delayMillis;
285 this.reconnectDelayMillis = reconnectDelayMillis;
267286 this.immediateFail = immediateFail;
268287 this.layout = layout;
288 this.bufferSize = bufferSize;
269289 }
270290 }
271291
290310 socket.connect(new InetSocketAddress(data.host, data.port), data.connectTimeoutMillis);
291311 os = socket.getOutputStream();
292312 return new TcpSocketManager(name, os, socket, inetAddress, data.host, data.port,
293 data.connectTimeoutMillis, data.delayMillis, data.immediateFail, data.layout);
313 data.connectTimeoutMillis, data.reconnectDelayMillis, data.immediateFail, data.layout, data.bufferSize);
294314 } catch (final IOException ex) {
295315 LOGGER.error("TcpSocketManager (" + name + ") " + ex, ex);
296 os = new ByteArrayOutputStream();
297 }
298 if (data.delayMillis == 0) {
316 os = NullOutputStream.getInstance();
317 }
318 if (data.reconnectDelayMillis == 0) {
299319 return null;
300320 }
301321 return new TcpSocketManager(name, os, null, inetAddress, data.host, data.port, data.connectTimeoutMillis,
302 data.delayMillis, data.immediateFail, data.layout);
322 data.reconnectDelayMillis, data.immediateFail, data.layout, data.bufferSize);
303323 }
304324 }
305325
2020 import java.io.FileNotFoundException;
2121 import java.io.IOException;
2222 import java.io.InputStream;
23 import java.net.InetAddress;
2324 import java.net.MalformedURLException;
2425 import java.net.URI;
2526 import java.net.URL;
2829 import org.apache.logging.log4j.LogManager;
2930 import org.apache.logging.log4j.Logger;
3031 import org.apache.logging.log4j.core.LogEventListener;
32 import org.apache.logging.log4j.core.LoggerContext;
3133 import org.apache.logging.log4j.core.config.Configuration;
3234 import org.apache.logging.log4j.core.config.ConfigurationSource;
3335 import org.apache.logging.log4j.core.config.xml.XmlConfiguration;
3436 import org.apache.logging.log4j.core.config.xml.XmlConfigurationFactory;
37 import org.apache.logging.log4j.core.util.BasicCommandLineArguments;
38 import org.apache.logging.log4j.core.util.InetAddressConverter;
3539 import org.apache.logging.log4j.core.util.Log4jThread;
3640 import org.apache.logging.log4j.util.Strings;
41
42 import com.beust.jcommander.JCommander;
43 import com.beust.jcommander.Parameter;
44 import com.beust.jcommander.validators.PositiveInteger;
3745
3846 /**
3947 * Abstract socket server for TCP and UDP implementations.
4048 *
41 * @param <T> The kind of input stream read
49 * @param <T>
50 * The kind of input stream read
4251 *
43 * TODO Make a LifeCycle
52 * TODO Make a LifeCycle
4453 */
4554 public abstract class AbstractSocketServer<T extends InputStream> extends LogEventListener implements Runnable {
55
56 protected static class CommandLineArguments extends BasicCommandLineArguments {
57
58 @Parameter(names = { "--config", "-c" }, description = "Log4j configuration file location (path or URL).")
59 private String configLocation;
60
61 @Parameter(names = { "--interactive",
62 "-i" }, description = "Accepts commands on standard input (\"exit\" is the only command).")
63 private boolean interactive;
64
65 @Parameter(names = { "--port",
66 "-p" }, validateWith = PositiveInteger.class, description = "Server socket port.")
67 private int port;
68
69 @Parameter(names = { "--localbindaddress",
70 "-a" }, converter = InetAddressConverter.class, description = "Server socket local bind address.")
71 private InetAddress localBindAddress;
72
73 String getConfigLocation() {
74 return configLocation;
75 }
76
77 int getPort() {
78 return port;
79 }
80
81 protected boolean isInteractive() {
82 return interactive;
83 }
84
85 void setConfigLocation(final String configLocation) {
86 this.configLocation = configLocation;
87 }
88
89 void setInteractive(final boolean interactive) {
90 this.interactive = interactive;
91 }
92
93 void setPort(final int port) {
94 this.port = port;
95 }
96
97 InetAddress getLocalBindAddress() {
98 return localBindAddress;
99 }
100
101 void setLocalBindAddress(InetAddress localBindAddress) {
102 this.localBindAddress = localBindAddress;
103 }
104 }
46105
47106 /**
48107 * Factory that creates a Configuration for the server.
56115 }
57116
58117 @Override
59 public Configuration getConfiguration(final String name, final URI configLocation) {
118 public Configuration getConfiguration(final LoggerContext loggerContext, final String name,
119 final URI configLocation) {
60120 if (Strings.isNotEmpty(path)) {
61121 File file = null;
62122 ConfigurationSource source = null;
80140
81141 try {
82142 if (source != null) {
83 return new XmlConfiguration(source);
143 return new XmlConfiguration(loggerContext, source);
84144 }
85145 } catch (final Exception ex) {
86146 // Ignore this error.
87147 }
88148 System.err.println("Unable to process configuration at " + path + ", using default.");
89149 }
90 return super.getConfiguration(name, configLocation);
150 return super.getConfiguration(loggerContext, name, configLocation);
91151 }
92152 }
93153
94154 protected static final int MAX_PORT = 65534;
155
156 static <T extends CommandLineArguments> T parseCommandLine(final String[] mainArgs, final Class<?> clazz,
157 final T args) {
158 final JCommander jCommander = new JCommander(args);
159 jCommander.setProgramName(clazz.getName());
160 jCommander.setCaseSensitiveOptions(false);
161 jCommander.parse(mainArgs);
162 if (args.isHelp()) {
163 jCommander.usage();
164 }
165 return args;
166 }
95167
96168 private volatile boolean active = true;
97169
102174 /**
103175 * Creates a new socket server.
104176 *
105 * @param port listen to this port
106 * @param logEventInput Use this input to read log events.
177 * @param port
178 * listen to this port
179 * @param logEventInput
180 * Use this input to read log events.
107181 */
108182 public AbstractSocketServer(final int port, final LogEventBridge<T> logEventInput) {
109183 this.logger = LogManager.getLogger(this.getClass().getName() + '.' + port);
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16
17 package org.apache.logging.log4j.core.net.server;
18
19 import java.io.BufferedReader;
20 import java.io.IOException;
21 import java.io.InputStreamReader;
22 import java.nio.charset.Charset;
23 import java.util.concurrent.atomic.AtomicReference;
24 import javax.jms.JMSException;
25 import javax.jms.Message;
26 import javax.jms.MessageConsumer;
27 import javax.jms.MessageListener;
28 import javax.jms.ObjectMessage;
29
30 import org.apache.logging.log4j.LoggingException;
31 import org.apache.logging.log4j.core.LifeCycle;
32 import org.apache.logging.log4j.core.LogEvent;
33 import org.apache.logging.log4j.core.LogEventListener;
34 import org.apache.logging.log4j.core.appender.mom.JmsManager;
35 import org.apache.logging.log4j.core.net.JndiManager;
36
37 /**
38 * LogEventListener server that receives LogEvents over a JMS {@link javax.jms.Destination}.
39 *
40 * @since 2.1
41 */
42 public class JmsServer extends LogEventListener implements MessageListener, LifeCycle {
43
44 private final AtomicReference<State> state = new AtomicReference<>(State.INITIALIZED);
45 private final JmsManager jmsManager;
46 private MessageConsumer messageConsumer;
47
48 public JmsServer(final String connectionFactoryBindingName,
49 final String destinationBindingName,
50 final String username,
51 final String password) {
52 final String managerName = JmsServer.class.getName() + '@' + JmsServer.class.hashCode();
53 final JndiManager jndiManager = JndiManager.getDefaultManager(managerName);
54 jmsManager = JmsManager.getJmsManager(managerName, jndiManager, connectionFactoryBindingName,
55 destinationBindingName, username, password);
56 }
57
58 @Override
59 public State getState() {
60 return state.get();
61 }
62
63 @Override
64 public void onMessage(final Message message) {
65 try {
66 if (message instanceof ObjectMessage) {
67 final Object body = ((ObjectMessage) message).getObject();
68 if (body instanceof LogEvent) {
69 log((LogEvent) body);
70 } else {
71 LOGGER.warn("Expected ObjectMessage to contain LogEvent. Got type {} instead.", body.getClass());
72 }
73 } else {
74 LOGGER.warn("Received message of type {} and JMSType {} which cannot be handled.", message.getClass(),
75 message.getJMSType());
76 }
77 } catch (final JMSException e) {
78 LOGGER.catching(e);
79 }
80 }
81
82 @Override
83 public void initialize() {
84 }
85
86 @Override
87 public void start() {
88 if (state.compareAndSet(State.INITIALIZED, State.STARTING)) {
89 try {
90 messageConsumer = jmsManager.createMessageConsumer();
91 messageConsumer.setMessageListener(this);
92 } catch (final JMSException e) {
93 throw new LoggingException(e);
94 }
95 }
96 }
97
98 @Override
99 public void stop() {
100 try {
101 messageConsumer.close();
102 } catch (final JMSException ignored) {
103 }
104 jmsManager.release();
105 }
106
107 @Override
108 public boolean isStarted() {
109 return state.get() == State.STARTED;
110 }
111
112 @Override
113 public boolean isStopped() {
114 return state.get() == State.STOPPED;
115 }
116
117 /**
118 * Starts and runs this server until the user types "exit" into standard input.
119 *
120 * @throws IOException
121 * @since 2.6
122 */
123 public void run() throws IOException {
124 this.start();
125 System.out.println("Type \"exit\" to quit.");
126 final BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in, Charset.defaultCharset()));
127 while (true) {
128 final String line = stdin.readLine();
129 if (line == null || line.equalsIgnoreCase("exit")) {
130 System.out.println("Exiting. Kill the application if it does not exit due to daemon threads.");
131 this.stop();
132 return;
133 }
134 }
135 }
136
137 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16
17 package org.apache.logging.log4j.core.net.server;
18
19 import java.io.BufferedReader;
20 import java.io.IOException;
21 import java.io.InputStreamReader;
22 import java.nio.charset.Charset;
23 import java.util.concurrent.TimeUnit;
24 import java.util.concurrent.atomic.AtomicReference;
25 import javax.jms.JMSException;
26 import javax.jms.Message;
27 import javax.jms.MessageConsumer;
28 import javax.jms.MessageListener;
29 import javax.jms.ObjectMessage;
30
31 import org.apache.logging.log4j.LoggingException;
32 import org.apache.logging.log4j.core.AbstractLifeCycle;
33 import org.apache.logging.log4j.core.LifeCycle2;
34 import org.apache.logging.log4j.core.LogEvent;
35 import org.apache.logging.log4j.core.LogEventListener;
36 import org.apache.logging.log4j.core.appender.mom.JmsManager;
37 import org.apache.logging.log4j.core.net.JndiManager;
38
39 /**
40 * LogEventListener server that receives LogEvents over a JMS {@link javax.jms.Destination}.
41 *
42 * @since 2.1
43 */
44 public class JmsServer extends LogEventListener implements MessageListener, LifeCycle2 {
45
46 private final AtomicReference<State> state = new AtomicReference<>(State.INITIALIZED);
47 private final JmsManager jmsManager;
48 private MessageConsumer messageConsumer;
49
50 public JmsServer(final String connectionFactoryBindingName,
51 final String destinationBindingName,
52 final String username,
53 final String password) {
54 final String managerName = JmsServer.class.getName() + '@' + JmsServer.class.hashCode();
55 final JndiManager jndiManager = JndiManager.getDefaultManager(managerName);
56 jmsManager = JmsManager.getJmsManager(managerName, jndiManager, connectionFactoryBindingName,
57 destinationBindingName, username, password);
58 }
59
60 @Override
61 public State getState() {
62 return state.get();
63 }
64
65 @Override
66 public void onMessage(final Message message) {
67 try {
68 if (message instanceof ObjectMessage) {
69 final Object body = ((ObjectMessage) message).getObject();
70 if (body instanceof LogEvent) {
71 log((LogEvent) body);
72 } else {
73 LOGGER.warn("Expected ObjectMessage to contain LogEvent. Got type {} instead.", body.getClass());
74 }
75 } else {
76 LOGGER.warn("Received message of type {} and JMSType {} which cannot be handled.", message.getClass(),
77 message.getJMSType());
78 }
79 } catch (final JMSException e) {
80 LOGGER.catching(e);
81 }
82 }
83
84 @Override
85 public void initialize() {
86 }
87
88 @Override
89 public void start() {
90 if (state.compareAndSet(State.INITIALIZED, State.STARTING)) {
91 try {
92 messageConsumer = jmsManager.createMessageConsumer();
93 messageConsumer.setMessageListener(this);
94 } catch (final JMSException e) {
95 throw new LoggingException(e);
96 }
97 }
98 }
99
100 @Override
101 public void stop() {
102 stop(AbstractLifeCycle.DEFAULT_STOP_TIMEOUT, AbstractLifeCycle.DEFAULT_STOP_TIMEUNIT);
103 }
104
105 @Override
106 public boolean stop(final long timeout, final TimeUnit timeUnit) {
107 boolean stopped = true;
108 try {
109 messageConsumer.close();
110 } catch (final JMSException e) {
111 LOGGER.debug("Exception closing {}", messageConsumer, e);
112 stopped = false;
113 }
114 return stopped && jmsManager.stop(timeout, timeUnit);
115 }
116
117 @Override
118 public boolean isStarted() {
119 return state.get() == State.STARTED;
120 }
121
122 @Override
123 public boolean isStopped() {
124 return state.get() == State.STOPPED;
125 }
126
127 /**
128 * Starts and runs this server until the user types "exit" into standard input.
129 *
130 * @throws IOException
131 * @since 2.6
132 */
133 public void run() throws IOException {
134 this.start();
135 System.out.println("Type \"exit\" to quit.");
136 final BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in, Charset.defaultCharset()));
137 while (true) {
138 final String line = stdin.readLine();
139 if (line == null || line.equalsIgnoreCase("exit")) {
140 System.out.println("Exiting. Kill the application if it does not exit due to daemon threads.");
141 this.stop();
142 return;
143 }
144 }
145 }
146
147 }
3939 }
4040
4141 public JsonInputStreamLogEventBridge(final int bufferSize, final Charset charset) {
42 super(new Log4jJsonObjectMapper(THREAD_CONTEXT_MAP_AS_LIST), bufferSize, charset,
42 super(new Log4jJsonObjectMapper(THREAD_CONTEXT_MAP_AS_LIST, true), bufferSize, charset,
4343 String.valueOf(EVENT_END_MARKER));
4444 }
4545
2222 import java.io.InputStreamReader;
2323 import java.io.ObjectInputStream;
2424 import java.io.OptionalDataException;
25 import java.net.InetAddress;
2526 import java.net.ServerSocket;
2627 import java.net.Socket;
2728 import java.nio.charset.Charset;
3334 import org.apache.logging.log4j.core.util.Log4jThread;
3435 import org.apache.logging.log4j.message.EntryMessage;
3536
37 import com.beust.jcommander.Parameter;
38 import com.beust.jcommander.validators.PositiveInteger;
39
3640 /**
37 * Listens for events over a socket connection.
41 * Listens for Log4j events on a TCP server socket and passes them on to Log4j.
3842 *
3943 * @param <T>
4044 * The kind of input stream read
45 * @see #main(String[])
4146 */
4247 public class TcpSocketServer<T extends InputStream> extends AbstractSocketServer<T> {
4348
49 protected static class CommandLineArguments extends AbstractSocketServer.CommandLineArguments {
50
51 @Parameter(names = { "--backlog",
52 "-b" }, validateWith = PositiveInteger.class, description = "Server socket backlog.")
53 // Same default as ServerSocket
54 private int backlog = 50;
55
56 int getBacklog() {
57 return backlog;
58 }
59
60 void setBacklog(final int backlog) {
61 this.backlog = backlog;
62 }
63
64 }
65
4466 /**
4567 * Thread that processes the events.
4668 */
47 private class SocketHandler extends Thread {
69 private class SocketHandler extends Log4jThread {
4870
4971 private final T inputStream;
5072
89111 }
90112 }
91113
114 /**
115 * Creates a socket server that reads JSON log events.
116 *
117 * @param port
118 * the port to listen
119 * @return a new a socket server
120 * @throws IOException
121 * if an I/O error occurs when opening the socket.
122 */
123 public static TcpSocketServer<InputStream> createJsonSocketServer(final int port) throws IOException {
124 LOGGER.entry("createJsonSocketServer", port);
125 final TcpSocketServer<InputStream> socketServer = new TcpSocketServer<>(port, new JsonInputStreamLogEventBridge());
126 return LOGGER.exit(socketServer);
127 }
128
129 /**
130 * Creates a socket server that reads serialized log events.
131 *
132 * @param port
133 * the port to listen
134 * @return a new a socket server
135 * @throws IOException
136 * if an I/O error occurs when opening the socket.
137 */
138 public static TcpSocketServer<ObjectInputStream> createSerializedSocketServer(final int port) throws IOException {
139 LOGGER.entry(port);
140 final TcpSocketServer<ObjectInputStream> socketServer = new TcpSocketServer<>(port, new ObjectInputStreamLogEventBridge());
141 return LOGGER.exit(socketServer);
142 }
143
144 /**
145 * Creates a socket server that reads serialized log events.
146 *
147 * @param port the port to listen
148 * @param localBindAddress The server socket's local bin address
149 * @return a new a socket server
150 * @throws IOException
151 * if an I/O error occurs when opening the socket.
152 * @since 2.7
153 */
154 public static TcpSocketServer<ObjectInputStream> createSerializedSocketServer(final int port, final int backlog,
155 InetAddress localBindAddress) throws IOException {
156 LOGGER.entry(port);
157 final TcpSocketServer<ObjectInputStream> socketServer = new TcpSocketServer<>(port, backlog, localBindAddress,
158 new ObjectInputStreamLogEventBridge());
159 return LOGGER.exit(socketServer);
160 }
161
162 /**
163 * Creates a socket server that reads XML log events.
164 *
165 * @param port
166 * the port to listen
167 * @return a new a socket server
168 * @throws IOException
169 * if an I/O error occurs when opening the socket.
170 */
171 public static TcpSocketServer<InputStream> createXmlSocketServer(final int port) throws IOException {
172 LOGGER.entry(port);
173 final TcpSocketServer<InputStream> socketServer = new TcpSocketServer<>(port, new XmlInputStreamLogEventBridge());
174 return LOGGER.exit(socketServer);
175 }
176
177 /**
178 * Main startup for the server. Run with "--help" for to print command line help on the console.
179 *
180 * @param args
181 * The command line arguments.
182 * @throws Exception
183 * if an error occurs.
184 */
185 public static void main(final String[] args) throws Exception {
186 final CommandLineArguments cla = parseCommandLine(args, TcpSocketServer.class, new CommandLineArguments());
187 if (cla.isHelp()) {
188 return;
189 }
190 if (cla.getConfigLocation() != null) {
191 ConfigurationFactory.setConfigurationFactory(new ServerConfigurationFactory(cla.getConfigLocation()));
192 }
193 final TcpSocketServer<ObjectInputStream> socketServer = TcpSocketServer
194 .createSerializedSocketServer(cla.getPort(), cla.getBacklog(), cla.getLocalBindAddress());
195 final Thread serverThread = new Log4jThread(socketServer);
196 serverThread.start();
197 if (cla.isInteractive()) {
198 final Charset enc = Charset.defaultCharset();
199 final BufferedReader reader = new BufferedReader(new InputStreamReader(System.in, enc));
200 while (true) {
201 final String line = reader.readLine();
202 if (line == null || line.equalsIgnoreCase("Quit") || line.equalsIgnoreCase("Stop")
203 || line.equalsIgnoreCase("Exit")) {
204 socketServer.shutdown();
205 serverThread.join();
206 break;
207 }
208 }
209 }
210 }
211
92212 private final ConcurrentMap<Long, SocketHandler> handlers = new ConcurrentHashMap<>();
93213
94214 private final ServerSocket serverSocket;
215
216 /**
217 * Constructor.
218 *
219 * @param port
220 * The server socket port.
221 * @param backlog
222 * The server socket backlog.
223 * @param localBindAddress TODO
224 * @param logEventInput
225 * the log even input
226 * @throws IOException
227 * if an I/O error occurs when opening the socket.
228 * @since 2.7
229 */
230 @SuppressWarnings("resource")
231 public TcpSocketServer(final int port, final int backlog, InetAddress localBindAddress, final LogEventBridge<T> logEventInput) throws IOException {
232 this(port, logEventInput, new ServerSocket(port, backlog, localBindAddress));
233 }
95234
96235 /**
97236 * Constructor.
104243 * if an I/O error occurs when opening the socket.
105244 */
106245 public TcpSocketServer(final int port, final LogEventBridge<T> logEventInput) throws IOException {
107 this(port, logEventInput, new ServerSocket(port));
246 this(port, logEventInput, extracted(port));
247 }
248
249 private static ServerSocket extracted(final int port) throws IOException {
250 return new ServerSocket(port);
108251 }
109252
110253 /**
123266 throws IOException {
124267 super(port, logEventInput);
125268 this.serverSocket = serverSocket;
126 }
127
128 /**
129 * Creates a socket server that reads JSON log events.
130 *
131 * @param port
132 * the port to listen
133 * @return a new a socket server
134 * @throws IOException
135 * if an I/O error occurs when opening the socket.
136 */
137 public static TcpSocketServer<InputStream> createJsonSocketServer(final int port) throws IOException {
138 LOGGER.entry("createJsonSocketServer", port);
139 final TcpSocketServer<InputStream> socketServer = new TcpSocketServer<>(port, new JsonInputStreamLogEventBridge());
140 return LOGGER.exit(socketServer);
141 }
142
143 /**
144 * Creates a socket server that reads serialized log events.
145 *
146 * @param port
147 * the port to listen
148 * @return a new a socket server
149 * @throws IOException
150 * if an I/O error occurs when opening the socket.
151 */
152 public static TcpSocketServer<ObjectInputStream> createSerializedSocketServer(final int port) throws IOException {
153 LOGGER.entry(port);
154 final TcpSocketServer<ObjectInputStream> socketServer = new TcpSocketServer<>(port, new ObjectInputStreamLogEventBridge());
155 return LOGGER.exit(socketServer);
156 }
157
158 /**
159 * Creates a socket server that reads XML log events.
160 *
161 * @param port
162 * the port to listen
163 * @return a new a socket server
164 * @throws IOException
165 * if an I/O error occurs when opening the socket.
166 */
167 public static TcpSocketServer<InputStream> createXmlSocketServer(final int port) throws IOException {
168 LOGGER.entry(port);
169 final TcpSocketServer<InputStream> socketServer = new TcpSocketServer<>(port, new XmlInputStreamLogEventBridge());
170 return LOGGER.exit(socketServer);
171 }
172
173 /**
174 * Main startup for the server.
175 *
176 * @param args
177 * The command line arguments.
178 * @throws Exception
179 * if an error occurs.
180 */
181 public static void main(final String[] args) throws Exception {
182 if (args.length < 1 || args.length > 2) {
183 System.err.println("Incorrect number of arguments");
184 printUsage();
185 return;
186 }
187 final int port = Integer.parseInt(args[0]);
188 if (port <= 0 || port >= MAX_PORT) {
189 System.err.println("Invalid port number");
190 printUsage();
191 return;
192 }
193 if (args.length == 2 && args[1].length() > 0) {
194 ConfigurationFactory.setConfigurationFactory(new ServerConfigurationFactory(args[1]));
195 }
196 final TcpSocketServer<ObjectInputStream> socketServer = TcpSocketServer.createSerializedSocketServer(port);
197 final Thread serverThread = new Log4jThread(socketServer);
198 serverThread.start();
199 final Charset enc = Charset.defaultCharset();
200 final BufferedReader reader = new BufferedReader(new InputStreamReader(System.in, enc));
201 while (true) {
202 final String line = reader.readLine();
203 if (line == null || line.equalsIgnoreCase("Quit") || line.equalsIgnoreCase("Stop")
204 || line.equalsIgnoreCase("Exit")) {
205 socketServer.shutdown();
206 serverThread.join();
207 break;
208 }
209 }
210 }
211
212 private static void printUsage() {
213 System.out.println("Usage: ServerSocket port configFilePath");
214269 }
215270
216271 /**
225280 }
226281 try {
227282 // Accept incoming connections.
228 logger.debug("Socket accept()...");
283 logger.debug("Listening for a connection {}...", serverSocket);
229284 final Socket clientSocket = serverSocket.accept();
285 logger.debug("Acepted connection on {}...", serverSocket);
230286 logger.debug("Socket accepted: {}", clientSocket);
231287 clientSocket.setSoLinger(true, 0);
232288
243299 logger.traceExit(entry);
244300 return;
245301 }
246 logger.error("Exception encountered on accept. Ignoring. Stack Trace :", e);
302 logger.error("Exception encountered on accept. Ignoring. Stack trace :", e);
247303 }
248304 }
249305 for (final Map.Entry<Long, SocketHandler> handlerEntry : handlers.entrySet()) {
3030 import org.apache.logging.log4j.core.util.Log4jThread;
3131
3232 /**
33 * Listens for events over a socket connection.
33 * Listens for Log4j events on a datagram socket and passes them on to Log4j.
3434 *
3535 * @param <T>
3636 * The kind of input stream read
37 * @see #main(String[])
3738 */
3839 public class UdpSocketServer<T extends InputStream> extends AbstractSocketServer<T> {
39
40 private final DatagramSocket datagramSocket;
41
42 // max size so we only have to deal with one packet
43 private final int maxBufferSize = 1024 * 65 + 1024;
44
45 /**
46 * Constructor.
47 *
48 * @param port
49 * to listen on.
50 * @param logEventInput
51 * @throws IOException
52 * If an error occurs.
53 */
54 public UdpSocketServer(final int port, final LogEventBridge<T> logEventInput) throws IOException {
55 super(port, logEventInput);
56 this.datagramSocket = new DatagramSocket(port);
57 }
5840
5941 /**
6042 * Creates a socket server that reads JSON log events.
9678 }
9779
9880 /**
99 * Main startup for the server.
81 * Main startup for the server. Run with "--help" for to print command line help on the console.
10082 *
10183 * @param args
10284 * The command line arguments.
10486 * if an error occurs.
10587 */
10688 public static void main(final String[] args) throws Exception {
107 if (args.length < 1 || args.length > 2) {
108 System.err.println("Incorrect number of arguments");
109 printUsage();
89 final CommandLineArguments cla = parseCommandLine(args, UdpSocketServer.class, new CommandLineArguments());
90 if (cla.isHelp()) {
11091 return;
11192 }
112 final int port = Integer.parseInt(args[0]);
113 if (port <= 0 || port >= MAX_PORT) {
114 System.err.println("Invalid port number");
115 printUsage();
116 return;
93 if (cla.getConfigLocation() != null) {
94 ConfigurationFactory.setConfigurationFactory(new ServerConfigurationFactory(cla.getConfigLocation()));
11795 }
118 if (args.length == 2 && args[1].length() > 0) {
119 ConfigurationFactory.setConfigurationFactory(new ServerConfigurationFactory(args[1]));
120 }
121 final UdpSocketServer<ObjectInputStream> socketServer = UdpSocketServer.createSerializedSocketServer(port);
122 final Thread server = new Log4jThread(socketServer);
123 server.start();
124 final BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
125 while (true) {
126 final String line = reader.readLine();
127 if (line == null || line.equalsIgnoreCase("Quit") || line.equalsIgnoreCase("Stop")
128 || line.equalsIgnoreCase("Exit")) {
129 socketServer.shutdown();
130 server.join();
131 break;
96 final UdpSocketServer<ObjectInputStream> socketServer = UdpSocketServer
97 .createSerializedSocketServer(cla.getPort());
98 final Thread serverThread = new Log4jThread(socketServer);
99 serverThread.start();
100 if (cla.isInteractive()) {
101 final BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
102 while (true) {
103 final String line = reader.readLine();
104 if (line == null || line.equalsIgnoreCase("Quit") || line.equalsIgnoreCase("Stop")
105 || line.equalsIgnoreCase("Exit")) {
106 socketServer.shutdown();
107 serverThread.join();
108 break;
109 }
132110 }
133111 }
134112 }
135113
136 private static void printUsage() {
137 System.out.println("Usage: ServerSocket port configFilePath");
114 private final DatagramSocket datagramSocket;
115
116 // max size so we only have to deal with one packet
117 private final int maxBufferSize = 1024 * 65 + 1024;
118
119 /**
120 * Constructor.
121 *
122 * @param port
123 * to listen on.
124 * @param logEventInput
125 * @throws IOException
126 * If an error occurs.
127 */
128 public UdpSocketServer(final int port, final LogEventBridge<T> logEventInput) throws IOException {
129 super(port, logEventInput);
130 this.datagramSocket = new DatagramSocket(port);
138131 }
139132
140133 /**
7272 return this.keyStore;
7373 }
7474
75 @Override
76 public int hashCode() {
77 final int prime = 31;
78 int result = super.hashCode();
79 result = prime * result + ((keyStore == null) ? 0 : keyStore.hashCode());
80 result = prime * result + ((keyStoreType == null) ? 0 : keyStoreType.hashCode());
81 return result;
82 }
83
84 @Override
85 public boolean equals(Object obj) {
86 if (this == obj) {
87 return true;
88 }
89 if (!super.equals(obj)) {
90 return false;
91 }
92 if (getClass() != obj.getClass()) {
93 return false;
94 }
95 AbstractKeyStoreConfiguration other = (AbstractKeyStoreConfiguration) obj;
96 if (keyStore == null) {
97 if (other.keyStore != null) {
98 return false;
99 }
100 } else if (!keyStore.equals(other.keyStore)) {
101 return false;
102 }
103 if (keyStoreType == null) {
104 if (other.keyStoreType != null) {
105 return false;
106 }
107 } else if (!keyStoreType.equals(other.keyStoreType)) {
108 return false;
109 }
110 return true;
111 }
112
75113 }
3333
3434 private final String keyManagerFactoryAlgorithm;
3535
36 /**
37 *
38 * @throws StoreConfigurationException Thrown if this instance cannot load the KeyStore.
39 */
3640 public KeyStoreConfiguration(final String location, final String password, final String keyStoreType,
3741 final String keyManagerFactoryAlgorithm) throws StoreConfigurationException {
3842 super(location, password, keyStoreType);
5256 * @param keyManagerFactoryAlgorithm
5357 * The standard name of the requested algorithm. See the Java Secure Socket Extension Reference Guide for information about these names.
5458 * @return a new KeyStoreConfiguration
55 * @throws StoreConfigurationException
59 * @throws StoreConfigurationException Thrown if this call cannot load the KeyStore.
5660 */
5761 @PluginFactory
5862 public static KeyStoreConfiguration createKeyStoreConfiguration(
7175 kmFactory.init(this.getKeyStore(), this.getPasswordAsCharArray());
7276 return kmFactory;
7377 }
78
79 @Override
80 public int hashCode() {
81 final int prime = 31;
82 int result = super.hashCode();
83 result = prime * result + ((keyManagerFactoryAlgorithm == null) ? 0 : keyManagerFactoryAlgorithm.hashCode());
84 return result;
85 }
86
87 @Override
88 public boolean equals(Object obj) {
89 if (this == obj) {
90 return true;
91 }
92 if (!super.equals(obj)) {
93 return false;
94 }
95 if (getClass() != obj.getClass()) {
96 return false;
97 }
98 KeyStoreConfiguration other = (KeyStoreConfiguration) obj;
99 if (keyManagerFactoryAlgorithm == null) {
100 if (other.keyManagerFactoryAlgorithm != null) {
101 return false;
102 }
103 } else if (!keyManagerFactoryAlgorithm.equals(other.keyManagerFactoryAlgorithm)) {
104 return false;
105 }
106 return true;
107 }
74108 }
203203 }
204204 }
205205
206 public boolean equals(final SslConfiguration config) {
207 if (config == null) {
208 return false;
209 }
210
211 boolean keyStoreEquals = false;
212 boolean trustStoreEquals = false;
213
214 if (keyStoreConfig != null) {
215 keyStoreEquals = keyStoreConfig.equals(config.keyStoreConfig);
216 } else {
217 keyStoreEquals = keyStoreConfig == config.keyStoreConfig;
218 }
219
220 if (trustStoreConfig != null) {
221 trustStoreEquals = trustStoreConfig.equals(config.trustStoreConfig);
222 } else {
223 trustStoreEquals = trustStoreConfig == config.trustStoreConfig;
224 }
225
226 return keyStoreEquals && trustStoreEquals;
227 }
228
229206 /**
230207 * Creates an SslConfiguration from a KeyStoreConfiguration and a TrustStoreConfiguration.
231208 * @param protocol The protocol, see http://docs.oracle.com/javase/7/docs/technotes/guides/security/StandardNames.html#SSLContext
242219 // @formatter:on
243220 return new SslConfiguration(protocol, keyStoreConfig, trustStoreConfig);
244221 }
222
223 @Override
224 public int hashCode() {
225 final int prime = 31;
226 int result = 1;
227 result = prime * result + ((keyStoreConfig == null) ? 0 : keyStoreConfig.hashCode());
228 result = prime * result + ((protocol == null) ? 0 : protocol.hashCode());
229 result = prime * result + ((sslContext == null) ? 0 : sslContext.hashCode());
230 result = prime * result + ((trustStoreConfig == null) ? 0 : trustStoreConfig.hashCode());
231 return result;
232 }
233
234 @Override
235 public boolean equals(Object obj) {
236 if (this == obj) {
237 return true;
238 }
239 if (obj == null) {
240 return false;
241 }
242 if (getClass() != obj.getClass()) {
243 return false;
244 }
245 SslConfiguration other = (SslConfiguration) obj;
246 if (keyStoreConfig == null) {
247 if (other.keyStoreConfig != null) {
248 return false;
249 }
250 } else if (!keyStoreConfig.equals(other.keyStoreConfig)) {
251 return false;
252 }
253 if (protocol == null) {
254 if (other.protocol != null) {
255 return false;
256 }
257 } else if (!protocol.equals(other.protocol)) {
258 return false;
259 }
260 if (sslContext == null) {
261 if (other.sslContext != null) {
262 return false;
263 }
264 } else if (!sslContext.equals(other.sslContext)) {
265 return false;
266 }
267 if (trustStoreConfig == null) {
268 if (other.trustStoreConfig != null) {
269 return false;
270 }
271 } else if (!trustStoreConfig.equals(other.trustStoreConfig)) {
272 return false;
273 }
274 return true;
275 }
245276 }
5151 this.password = password;
5252 }
5353
54 /**
55 * @throws StoreConfigurationException May be thrown by subclasses
56 */
5457 protected T load() throws StoreConfigurationException {
5558 return null;
5659 }
5151 * @param trustManagerFactoryAlgorithm
5252 * The standard name of the requested trust management algorithm. See the Java Secure Socket Extension Reference Guide for information these names.
5353 * @return a new TrustStoreConfiguration
54 * @throws StoreConfigurationException
54 * @throws StoreConfigurationException Thrown if this instance cannot load the KeyStore.
5555 */
5656 @PluginFactory
5757 public static TrustStoreConfiguration createKeyStoreConfiguration(
6969 tmFactory.init(this.getKeyStore());
7070 return tmFactory;
7171 }
72
73 @Override
74 public int hashCode() {
75 final int prime = 31;
76 int result = super.hashCode();
77 result = prime * result
78 + ((trustManagerFactoryAlgorithm == null) ? 0 : trustManagerFactoryAlgorithm.hashCode());
79 return result;
80 }
81
82 @Override
83 public boolean equals(Object obj) {
84 if (this == obj) {
85 return true;
86 }
87 if (!super.equals(obj)) {
88 return false;
89 }
90 if (getClass() != obj.getClass()) {
91 return false;
92 }
93 TrustStoreConfiguration other = (TrustStoreConfiguration) obj;
94 if (trustManagerFactoryAlgorithm == null) {
95 if (other.trustManagerFactoryAlgorithm != null) {
96 return false;
97 }
98 } else if (!trustManagerFactoryAlgorithm.equals(other.trustManagerFactoryAlgorithm)) {
99 return false;
100 }
101 return true;
102 }
72103 }
223223 LOGGER.warn("Could not instantiate FastDateFormat with pattern " + pattern, e);
224224
225225 // default to the DEFAULT format
226 return createFixedFormatter(FixedDateFormat.create(FixedFormat.DEFAULT));
226 return createFixedFormatter(FixedDateFormat.create(FixedFormat.DEFAULT, tz));
227227 }
228228 }
229229
1818 import org.apache.logging.log4j.core.LogEvent;
1919 import org.apache.logging.log4j.core.config.plugins.Plugin;
2020 import org.apache.logging.log4j.core.impl.ThrowableProxy;
21 import org.apache.logging.log4j.core.util.Constants;
21 import org.apache.logging.log4j.util.Strings;
2222
2323 /**
2424 * Outputs the Throwable portion of the LoggingEvent as a full stack trace
6464 super.format(event, toAppendTo);
6565 return;
6666 }
67 final String extStackTrace = proxy.getExtendedStackTraceAsString(options.getPackages());
67 final String extStackTrace = proxy.getExtendedStackTraceAsString(options.getIgnorePackages(), options.getTextRenderer());
6868 final int len = toAppendTo.length();
6969 if (len > 0 && !Character.isWhitespace(toAppendTo.charAt(len - 1))) {
7070 toAppendTo.append(' ');
7171 }
72 if (!options.allLines() || !Constants.LINE_SEPARATOR.equals(options.getSeparator())) {
72 if (!options.allLines() || !Strings.LINE_SEPARATOR.equals(options.getSeparator())) {
7373 final StringBuilder sb = new StringBuilder();
74 final String[] array = extStackTrace.split(Constants.LINE_SEPARATOR);
74 final String[] array = extStackTrace.split(Strings.LINE_SEPARATOR);
7575 final int limit = options.minLines(array.length) - 1;
7676 for (int i = 0; i <= limit; ++i) {
7777 sb.append(array[i]);
8080 }
8181 }
8282 toAppendTo.append(sb.toString());
83
8483 } else {
8584 toAppendTo.append(extStackTrace);
8685 }
3333 * <p>
3434 * For example:
3535 * </p>
36 *
36 *
3737 * <pre>
3838 * %highlight{%d{ ISO8601 } [%t] %-5level: %msg%n%throwable}
3939 * </pre>
4040 * <p>
4141 * You can define custom colors for each Level:
4242 * </p>
43 *
43 *
4444 * <pre>
4545 * %highlight{%d{ ISO8601 } [%t] %-5level: %msg%n%throwable}{FATAL=red, ERROR=red, WARN=yellow, INFO=green, DEBUG=cyan,
4646 * TRACE=black}
4848 * <p>
4949 * You can use a predefined style:
5050 * </p>
51 *
51 *
5252 * <pre>
53 * %highlight{%d{ ISO8601 } [%t] %-5level: %msg%n%throwable}{STYLE=Log4j}
53 * %highlight{%d{ ISO8601 } [%t] %-5level: %msg%n%throwable}{STYLE=DEFAULT}
5454 * </pre>
5555 * <p>
5656 * The available predefined styles are:
107107 * <p>
108108 * The format of the option string in {@code option[1]} is:
109109 * </p>
110 *
110 *
111111 * <pre>
112112 * Level1=Value, Level2=Value, ...
113113 * </pre>
192192
193193 private final boolean noAnsi;
194194
195 private final String defaultStyle;
196
195197 /**
196198 * Construct the converter.
197199 *
204206 super("style", "style");
205207 this.patternFormatters = patternFormatters;
206208 this.levelStyles = levelStyles;
209 this.defaultStyle = AnsiEscape.getDefaultStyle();
207210 this.noAnsi = noAnsi;
208211 }
209212
212215 */
213216 @Override
214217 public void format(final LogEvent event, final StringBuilder toAppendTo) {
215 final StringBuilder buf = new StringBuilder();
216 for (final PatternFormatter formatter : patternFormatters) {
217 formatter.format(event, buf);
218 }
219
220 if (buf.length() > 0) {
221 if (noAnsi) {
222 toAppendTo.append(buf.toString());
218 int start = 0;
219 int end = 0;
220 if (!noAnsi) { // use ANSI: set prefix
221 start = toAppendTo.length();
222 toAppendTo.append(levelStyles.get(event.getLevel()));
223 end = toAppendTo.length();
224 }
225
226 //noinspection ForLoopReplaceableByForEach
227 for (int i = 0, size = patternFormatters.size(); i < size; i++) {
228 patternFormatters.get(i).format(event, toAppendTo);
229 }
230
231 // if we use ANSI we need to add the postfix or erase the unnecessary prefix
232 final boolean empty = toAppendTo.length() == end;
233 if (!noAnsi) {
234 if (empty) {
235 toAppendTo.setLength(start); // erase prefix
223236 } else {
224 toAppendTo.append(levelStyles.get(event.getLevel())).append(buf.toString()).
225 append(AnsiEscape.getDefaultStyle());
237 toAppendTo.append(defaultStyle); // add postfix
226238 }
227239 }
228240 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.pattern;
17
18 /**
19 * TODO Renders an input as HTML output.
20 */
21 public final class HtmlTextRenderer implements TextRenderer {
22
23 public HtmlTextRenderer(final String[] formats) {
24 // TODO Auto-generated constructor stub
25 }
26
27 @Override
28 public void render(final String input, final StringBuilder output, final String styleName) {
29 // TODO Auto-generated method stub
30 }
31
32 @Override
33 public void render(final StringBuilder input, final StringBuilder output) {
34 // TODO Auto-generated method stub
35 }
36
37 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.pattern;
17
18 import static org.fusesource.jansi.AnsiRenderer.Code.BG_RED;
19 import static org.fusesource.jansi.AnsiRenderer.Code.BOLD;
20 import static org.fusesource.jansi.AnsiRenderer.Code.RED;
21 import static org.fusesource.jansi.AnsiRenderer.Code.WHITE;
22 import static org.fusesource.jansi.AnsiRenderer.Code.YELLOW;
23
24 import java.util.Collections;
25 import java.util.HashMap;
26 import java.util.Locale;
27 import java.util.Map;
28
29 import org.apache.logging.log4j.status.StatusLogger;
30 import org.fusesource.jansi.Ansi;
31 import org.fusesource.jansi.AnsiRenderer;
32 import org.fusesource.jansi.AnsiRenderer.Code;
33
34 /**
35 * Renders an input as ANSI escaped output.
36 *
37 * Uses the JAnsi rendering syntax as the default to render a message into an ANSI escaped string.
38 *
39 * The default syntax for embedded ANSI codes is:
40 *
41 * <pre>
42 * &#64;|<em>code</em>(,<em>code</em>)* <em>text</em>|@
43 * </pre>
44 *
45 * For example, to render the message {@code "Hello"} in green, use:
46 *
47 * <pre>
48 * &#64;|green Hello|@
49 * </pre>
50 *
51 * To render the message {@code "Hello"} in bold and red, use:
52 *
53 * <pre>
54 * &#64;|bold,red Warning!|@
55 * </pre>
56 *
57 * You can also define custom style names in the configuration with the syntax:
58 *
59 * <pre>
60 * %message{ansi}{StyleName=value(,value)*( StyleName=value(,value)*)*}%n
61 * </pre>
62 *
63 * For example:
64 *
65 * <pre>
66 * %message{ansi}{WarningStyle=red,bold KeyStyle=white ValueStyle=blue}%n
67 * </pre>
68 *
69 * The call site can look like this:
70 *
71 * <pre>
72 * logger.info("@|KeyStyle {}|@ = @|ValueStyle {}|@", entry.getKey(), entry.getValue());
73 * </pre>
74 *
75 * Note: This class originally copied and then heavily modified code from JAnsi's AnsiRenderer (which is licensed as
76 * Apache 2.0.)
77 *
78 * @see AnsiRenderer
79 */
80 public final class JAnsiTextRenderer implements TextRenderer {
81
82 public static final Map<String, Code[]> DefaultExceptionStyleMap;
83 static final Map<String, Code[]> DefaultMessageStyleMap;
84 private static final Map<String, Map<String, Code[]>> PrefedinedStyleMaps;
85
86 private static void put(final Map<String, Code[]> map, final String name, final Code... codes) {
87 map.put(name, codes);
88 }
89
90 static {
91 final Map<String, Map<String, Code[]>> tempPreDefs = new HashMap<>();
92 // Default style: Spock
93 {
94 // TODO Should the keys be in an enum?
95 final Map<String, Code[]> map = new HashMap<>();
96 put(map, "Prefix", WHITE);
97 put(map, "Name", BG_RED, WHITE);
98 put(map, "NameMessageSeparator", BG_RED, WHITE);
99 put(map, "Message", BG_RED, WHITE, BOLD);
100 put(map, "At", WHITE);
101 put(map, "CauseLabel", WHITE);
102 put(map, "Text", WHITE);
103 put(map, "More", WHITE);
104 put(map, "Suppressed", WHITE);
105 // StackTraceElement
106 put(map, "StackTraceElement.ClassName", YELLOW);
107 put(map, "StackTraceElement.ClassMethodSeparator", YELLOW);
108 put(map, "StackTraceElement.MethodName", YELLOW);
109 put(map, "StackTraceElement.NativeMethod", YELLOW);
110 put(map, "StackTraceElement.FileName", RED);
111 put(map, "StackTraceElement.LineNumber", RED);
112 put(map, "StackTraceElement.Container", RED);
113 put(map, "StackTraceElement.ContainerSeparator", WHITE);
114 put(map, "StackTraceElement.UnknownSource", RED);
115 // ExtraClassInfo
116 put(map, "ExtraClassInfo.Inexact", YELLOW);
117 put(map, "ExtraClassInfo.Container", YELLOW);
118 put(map, "ExtraClassInfo.ContainerSeparator", YELLOW);
119 put(map, "ExtraClassInfo.Location", YELLOW);
120 put(map, "ExtraClassInfo.Version", YELLOW);
121 // Save
122 DefaultExceptionStyleMap = Collections.unmodifiableMap(map);
123 tempPreDefs.put("Spock", DefaultExceptionStyleMap);
124 }
125 // Style: Kirk
126 {
127 // TODO Should the keys be in an enum?
128 final Map<String, Code[]> map = new HashMap<>();
129 put(map, "Prefix", WHITE);
130 put(map, "Name", BG_RED, YELLOW, BOLD);
131 put(map, "NameMessageSeparator", BG_RED, YELLOW);
132 put(map, "Message", BG_RED, WHITE, BOLD);
133 put(map, "At", WHITE);
134 put(map, "CauseLabel", WHITE);
135 put(map, "Text", WHITE);
136 put(map, "More", WHITE);
137 put(map, "Suppressed", WHITE);
138 // StackTraceElement
139 put(map, "StackTraceElement.ClassName", BG_RED, WHITE);
140 put(map, "StackTraceElement.ClassMethodSeparator", BG_RED, YELLOW);
141 put(map, "StackTraceElement.MethodName", BG_RED, YELLOW);
142 put(map, "StackTraceElement.NativeMethod", BG_RED, YELLOW);
143 put(map, "StackTraceElement.FileName", RED);
144 put(map, "StackTraceElement.LineNumber", RED);
145 put(map, "StackTraceElement.Container", RED);
146 put(map, "StackTraceElement.ContainerSeparator", WHITE);
147 put(map, "StackTraceElement.UnknownSource", RED);
148 // ExtraClassInfo
149 put(map, "ExtraClassInfo.Inexact", YELLOW);
150 put(map, "ExtraClassInfo.Container", WHITE);
151 put(map, "ExtraClassInfo.ContainerSeparator", WHITE);
152 put(map, "ExtraClassInfo.Location", YELLOW);
153 put(map, "ExtraClassInfo.Version", YELLOW);
154 // Save
155 tempPreDefs.put("Kirk", Collections.unmodifiableMap(map));
156 }
157 {
158 final Map<String, Code[]> temp = new HashMap<>();
159 // TODO
160 DefaultMessageStyleMap = Collections.unmodifiableMap(temp);
161 }
162 PrefedinedStyleMaps = Collections.unmodifiableMap(tempPreDefs);
163 }
164
165 private final String beginToken;
166 private final int beginTokenLen;
167 private final String endToken;
168 private final int endTokenLen;
169 private final Map<String, Code[]> styleMap;
170
171 public JAnsiTextRenderer(final String[] formats, final Map<String, Code[]> defaultStyleMap) {
172 String tempBeginToken = AnsiRenderer.BEGIN_TOKEN;
173 String tempEndToken = AnsiRenderer.END_TOKEN;
174 Map<String, Code[]> map;
175 if (formats.length > 1) {
176 final String allStylesStr = formats[1];
177 // Style def split
178 final String[] allStyleAssignmentsArr = allStylesStr.split(" ");
179 map = new HashMap<>(allStyleAssignmentsArr.length + defaultStyleMap.size());
180 map.putAll(defaultStyleMap);
181 for (final String styleAssignmentStr : allStyleAssignmentsArr) {
182 final String[] styleAssignmentArr = styleAssignmentStr.split("=");
183 if (styleAssignmentArr.length != 2) {
184 StatusLogger.getLogger().warn("{} parsing style \"{}\", expected format: StyleName=Code(,Code)*",
185 getClass().getSimpleName(), styleAssignmentStr);
186 } else {
187 final String styleName = styleAssignmentArr[0];
188 final String codeListStr = styleAssignmentArr[1];
189 final String[] codeNames = codeListStr.split(",");
190 if (codeNames.length == 0) {
191 StatusLogger.getLogger().warn(
192 "{} parsing style \"{}\", expected format: StyleName=Code(,Code)*",
193 getClass().getSimpleName(), styleAssignmentStr);
194 } else {
195 switch (styleName) {
196 case "BeginToken":
197 tempBeginToken = codeNames[0];
198 break;
199 case "EndToken":
200 tempEndToken = codeNames[0];
201 break;
202 case "StyleMapName":
203 final String predefinedMapName = codeNames[0];
204 final Map<String, Code[]> predefinedMap = PrefedinedStyleMaps.get(predefinedMapName);
205 if (predefinedMap != null) {
206 map.putAll(predefinedMap);
207 } else {
208 StatusLogger.getLogger().warn("Unknown predefined map name {}, pick one of {}",
209 predefinedMapName, null);
210 }
211 break;
212 default:
213 final Code[] codes = new Code[codeNames.length];
214 for (int i = 0; i < codes.length; i++) {
215 codes[i] = toCode(codeNames[i]);
216 }
217 map.put(styleName, codes);
218 }
219 }
220 }
221 }
222 } else {
223 map = defaultStyleMap;
224 }
225 styleMap = map;
226 beginToken = tempBeginToken;
227 endToken = tempEndToken;
228 beginTokenLen = tempBeginToken.length();
229 endTokenLen = tempEndToken.length();
230 }
231
232 public Map<String, Code[]> getStyleMap() {
233 return styleMap;
234 }
235
236 private void render(final Ansi ansi, final Code code) {
237 if (code.isColor()) {
238 if (code.isBackground()) {
239 ansi.bg(code.getColor());
240 } else {
241 ansi.fg(code.getColor());
242 }
243 } else if (code.isAttribute()) {
244 ansi.a(code.getAttribute());
245 }
246 }
247
248 private void render(final Ansi ansi, final Code... codes) {
249 for (final Code code : codes) {
250 render(ansi, code);
251 }
252 }
253
254 /**
255 * Renders the given text with the given names which can be ANSI code names or Log4j style names.
256 *
257 * @param text
258 * The text to render
259 * @param names
260 * ANSI code names or Log4j style names.
261 * @return A rendered string containing ANSI codes.
262 */
263 private String render(final String text, final String... names) {
264 final Ansi ansi = Ansi.ansi();
265 for (final String name : names) {
266 final Code[] codes = styleMap.get(name);
267 if (codes != null) {
268 render(ansi, codes);
269 } else {
270 render(ansi, toCode(name));
271 }
272 }
273 return ansi.a(text).reset().toString();
274 }
275
276 // EXACT COPY OF StringBuilder version of the method but typed as String for input
277 @Override
278 public void render(final String input, final StringBuilder output, final String styleName)
279 throws IllegalArgumentException {
280 output.append(render(input, styleName));
281 }
282
283 @Override
284 public void render(final StringBuilder input, final StringBuilder output) throws IllegalArgumentException {
285 int i = 0;
286 int j, k;
287
288 while (true) {
289 j = input.indexOf(beginToken, i);
290 if (j == -1) {
291 if (i == 0) {
292 output.append(input);
293 return;
294 }
295 output.append(input.substring(i, input.length()));
296 return;
297 }
298 output.append(input.substring(i, j));
299 k = input.indexOf(endToken, j);
300
301 if (k == -1) {
302 output.append(input);
303 return;
304 }
305 j += beginTokenLen;
306 final String spec = input.substring(j, k);
307
308 final String[] items = spec.split(AnsiRenderer.CODE_TEXT_SEPARATOR, 2);
309 if (items.length == 1) {
310 output.append(input);
311 return;
312 }
313 final String replacement = render(items[1], items[0].split(","));
314
315 output.append(replacement);
316
317 i = k + endTokenLen;
318 }
319 }
320
321 private Code toCode(final String name) {
322 return Code.valueOf(name.toUpperCase(Locale.ENGLISH));
323 }
324
325 @Override
326 public String toString() {
327 return "JAnsiMessageRenderer [beginToken=" + beginToken + ", beginTokenLen=" + beginTokenLen + ", endToken="
328 + endToken + ", endTokenLen=" + endTokenLen + ", styleMap=" + styleMap + "]";
329 }
330
331 }
1717
1818 import org.apache.logging.log4j.core.LogEvent;
1919 import org.apache.logging.log4j.core.config.plugins.Plugin;
20 import org.apache.logging.log4j.core.util.Constants;
20 import org.apache.logging.log4j.util.Strings;
2121
2222 /**
2323 * Formats a line separator.
4141 */
4242 private LineSeparatorPatternConverter() {
4343 super("Line Sep", "lineSep");
44 lineSep = Constants.LINE_SEPARATOR;
44 lineSep = Strings.LINE_SEPARATOR;
4545 }
4646
4747 /**
1515 */
1616 package org.apache.logging.log4j.core.pattern;
1717
18 import java.util.Map;
19 import java.util.Set;
20 import java.util.TreeSet;
21
18 import org.apache.logging.log4j.util.ReadOnlyStringMap;
2219 import org.apache.logging.log4j.core.LogEvent;
2320 import org.apache.logging.log4j.core.config.plugins.Plugin;
21 import org.apache.logging.log4j.core.util.Constants;
22 import org.apache.logging.log4j.util.TriConsumer;
23 import org.apache.logging.log4j.util.StringBuilders;
2424
2525 /**
2626 * Able to handle the contents of the LogEvent's MDC and either
3232 @Plugin(name = "MdcPatternConverter", category = PatternConverter.CATEGORY)
3333 @ConverterKeys({ "X", "mdc", "MDC" })
3434 public final class MdcPatternConverter extends LogEventPatternConverter {
35
36 private static final ThreadLocal<StringBuilder> threadLocal = new ThreadLocal<>();
37 private static final int DEFAULT_STRING_BUILDER_SIZE = 64;
38 private static final int MAX_STRING_BUILDER_SIZE = Constants.MAX_REUSABLE_MESSAGE_SIZE;
39
3540 /**
3641 * Name of property to output.
3742 */
5055 full = false;
5156 if (options[0].indexOf(',') > 0) {
5257 keys = options[0].split(",");
58 for (int i = 0; i < keys.length; i++) {
59 keys[i] = keys[i].trim();
60 }
5361 key = null;
5462 } else {
5563 keys = null;
7280 return new MdcPatternConverter(options);
7381 }
7482
83 private static final TriConsumer<String, Object, StringBuilder> WRITE_KEY_VALUES_INTO = new TriConsumer<String, Object, StringBuilder>() {
84 @Override
85 public void accept(final String key, final Object value, final StringBuilder sb) {
86 if (sb.length() > 1) {
87 sb.append(", ");
88 }
89 sb.append(key).append('=');
90 StringBuilders.appendValue(sb, value);
91 }
92 };
93
7594 /**
7695 * {@inheritDoc}
7796 */
7897 @Override
7998 public void format(final LogEvent event, final StringBuilder toAppendTo) {
80 final Map<String, String> contextMap = event.getContextMap();
99 final ReadOnlyStringMap contextData = event.getContextData();
81100 // if there is no additional options, we output every single
82101 // Key/Value pair for the MDC in a similar format to Hashtable.toString()
83102 if (full) {
84 if (contextMap == null || contextMap.isEmpty()) {
103 if (contextData == null || contextData.size() == 0) {
85104 toAppendTo.append("{}");
86105 return;
87106 }
88 final StringBuilder sb = new StringBuilder("{");
89 final Set<String> eventKeys = new TreeSet<>(contextMap.keySet());
90 for (final String eventKey : eventKeys) {
91 if (sb.length() > 1) {
92 sb.append(", ");
93 }
94 sb.append(eventKey).append('=').append(contextMap.get(eventKey));
95
96 }
97 sb.append('}');
98 toAppendTo.append(sb);
107 appendFully(contextData, toAppendTo);
99108 } else {
100109 if (keys != null) {
101 if (contextMap == null || contextMap.isEmpty()) {
110 if (contextData == null || contextData.size() == 0) {
102111 toAppendTo.append("{}");
103112 return;
104113 }
105 // Print all the keys in the array that have a value.
106 final StringBuilder sb = new StringBuilder("{");
107 for (String key : keys) {
108 key = key.trim();
109 if (contextMap.containsKey(key)) {
110 if (sb.length() > 1) {
111 sb.append(", ");
112 }
113 sb.append(key).append('=').append(contextMap.get(key));
114 }
115 }
116 sb.append('}');
117 toAppendTo.append(sb);
118 } else if (contextMap != null){
114 appendSelectedKeys(keys, contextData, toAppendTo);
115 } else if (contextData != null){
119116 // otherwise they just want a single key output
120 final Object val = contextMap.get(key);
121
122 if (val != null) {
123 toAppendTo.append(val);
117 final Object value = contextData.getValue(key);
118 if (value != null) {
119 StringBuilders.appendValue(toAppendTo, value);
124120 }
125121 }
126122 }
127123 }
124
125 private static void appendFully(final ReadOnlyStringMap contextData, final StringBuilder toAppendTo) {
126 final StringBuilder sb = getStringBuilder();
127 sb.append("{");
128 contextData.forEach(WRITE_KEY_VALUES_INTO, sb);
129 sb.append('}');
130 toAppendTo.append(sb);
131 trimToMaxSize(sb);
132 }
133
134 private static void appendSelectedKeys(final String[] keys, final ReadOnlyStringMap contextData, final StringBuilder toAppendTo) {
135 // Print all the keys in the array that have a value.
136 final StringBuilder sb = getStringBuilder();
137 sb.append("{");
138 for (int i = 0; i < keys.length; i++) {
139 final String theKey = keys[i];
140 final Object value = contextData.getValue(theKey);
141 if (value != null) { // !contextData.containskey(theKey)
142 if (sb.length() > 1) {
143 sb.append(", ");
144 }
145 sb.append(theKey).append('=');
146 StringBuilders.appendValue(sb, value);
147 }
148 }
149 sb.append('}');
150 toAppendTo.append(sb);
151 trimToMaxSize(sb);
152 }
153
154 private static StringBuilder getStringBuilder() {
155 StringBuilder result = threadLocal.get();
156 if (result == null) {
157 result = new StringBuilder(DEFAULT_STRING_BUILDER_SIZE);
158 threadLocal.set(result);
159 }
160 result.setLength(0);
161 return result;
162 }
163
164 private static void trimToMaxSize(final StringBuilder stringBuilder) {
165 if (stringBuilder.length() > MAX_STRING_BUILDER_SIZE) {
166 stringBuilder.setLength(MAX_STRING_BUILDER_SIZE);
167 stringBuilder.trimToSize();
168 }
169 }
128170 }
1515 */
1616 package org.apache.logging.log4j.core.pattern;
1717
18 import java.util.Locale;
19
1820 import org.apache.logging.log4j.core.LogEvent;
1921 import org.apache.logging.log4j.core.config.Configuration;
2022 import org.apache.logging.log4j.core.config.plugins.Plugin;
23 import org.apache.logging.log4j.core.util.ArrayUtils;
24 import org.apache.logging.log4j.core.util.Loader;
2125 import org.apache.logging.log4j.message.Message;
2226 import org.apache.logging.log4j.message.MultiformatMessage;
27 import org.apache.logging.log4j.status.StatusLogger;
2328 import org.apache.logging.log4j.util.StringBuilderFormattable;
2429
2530 /**
2934 @ConverterKeys({ "m", "msg", "message" })
3035 public final class MessagePatternConverter extends LogEventPatternConverter {
3136
37 private static final String NOLOOKUPS = "nolookups";
38
3239 private final String[] formats;
3340 private final Configuration config;
41 private final TextRenderer textRenderer;
42 private final boolean noLookups;
3443
3544 /**
3645 * Private constructor.
37 * @param options options, may be null.
46 *
47 * @param options
48 * options, may be null.
3849 */
3950 private MessagePatternConverter(final Configuration config, final String[] options) {
4051 super("Message", "message");
41 formats = options;
52 this.formats = options;
4253 this.config = config;
54 final int noLookupsIdx = loadNoLookups(options);
55 this.noLookups = noLookupsIdx >= 0;
56 this.textRenderer = loadMessageRenderer(noLookupsIdx >= 0 ? ArrayUtils.remove(options, noLookupsIdx) : options);
57 }
58
59 private int loadNoLookups(final String[] options) {
60 if (options != null) {
61 for (int i = 0; i < options.length; i++) {
62 final String option = options[i];
63 if (NOLOOKUPS.equalsIgnoreCase(option)) {
64 return i;
65 }
66 }
67 }
68 return -1;
69 }
70
71 private TextRenderer loadMessageRenderer(final String[] options) {
72 if (options != null) {
73 for (final String option : options) {
74 switch (option.toUpperCase(Locale.ROOT)) {
75 case "ANSI":
76 if (Loader.isJansiAvailable()) {
77 return new JAnsiTextRenderer(options, JAnsiTextRenderer.DefaultMessageStyleMap);
78 }
79 StatusLogger.getLogger()
80 .warn("You requested ANSI message rendering but JANSI is not on the classpath.");
81 return null;
82 case "HTML":
83 return new HtmlTextRenderer(options);
84 }
85 }
86 }
87 return null;
4388 }
4489
4590 /**
4691 * Obtains an instance of pattern converter.
4792 *
48 * @param config The Configuration.
49 * @param options options, may be null.
93 * @param config
94 * The Configuration.
95 * @param options
96 * options, may be null.
5097 * @return instance of pattern converter.
5198 */
5299 public static MessagePatternConverter newInstance(final Configuration config, final String[] options) {
60107 public void format(final LogEvent event, final StringBuilder toAppendTo) {
61108 final Message msg = event.getMessage();
62109 if (msg instanceof StringBuilderFormattable) {
63 final int offset = toAppendTo.length();
64 ((StringBuilderFormattable) msg).formatTo(toAppendTo);
110
111 final boolean doRender = textRenderer != null;
112 final StringBuilder workingBuilder = doRender ? new StringBuilder(80) : toAppendTo;
113
114 final StringBuilderFormattable stringBuilderFormattable = (StringBuilderFormattable) msg;
115 final int offset = workingBuilder.length();
116 stringBuilderFormattable.formatTo(workingBuilder);
65117
66118 // TODO can we optimize this?
67 if (config != null) {
68 for (int i = offset; i < toAppendTo.length() - 1; i++) {
69 if (toAppendTo.charAt(i) == '$' && toAppendTo.charAt(i + 1) == '{') {
70 final String value = toAppendTo.substring(offset, toAppendTo.length());
71 toAppendTo.setLength(offset);
72 toAppendTo.append(config.getStrSubstitutor().replace(event, value));
119 if (config != null && !noLookups) {
120 for (int i = offset; i < workingBuilder.length() - 1; i++) {
121 if (workingBuilder.charAt(i) == '$' && workingBuilder.charAt(i + 1) == '{') {
122 final String value = workingBuilder.substring(offset, workingBuilder.length());
123 workingBuilder.setLength(offset);
124 workingBuilder.append(config.getStrSubstitutor().replace(event, value));
73125 }
74126 }
127 }
128 if (doRender) {
129 textRenderer.render(workingBuilder, toAppendTo);
75130 }
76131 return;
77132 }
83138 result = msg.getFormattedMessage();
84139 }
85140 if (result != null) {
86 toAppendTo.append(config != null && result.contains("${") ?
87 config.getStrSubstitutor().replace(event, result) : result);
141 toAppendTo.append(config != null && result.contains("${")
142 ? config.getStrSubstitutor().replace(event, result) : result);
88143 } else {
89144 toAppendTo.append("null");
90145 }
175175 */
176176 private enum Strategy {
177177 DROP(0) {
178 @Override
178179 void abbreviate(final int count, final String original, final StringBuilder destination) {
179180 // If a path does not contain enough path elements to drop, none will be dropped.
180181 int start = 0;
191192 }
192193 },
193194 RETAIN(1) {
195 @Override
194196 void abbreviate(final int count, final String original, final StringBuilder destination) {
195197 // We subtract 1 from 'len' when assigning to 'end' to avoid out of
196198 // bounds exception in return r.substring(end+1, len). This can happen if
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.pattern;
17
18 /**
19 Renders input unchanged.
20 */
21 public final class PlainTextRenderer implements TextRenderer {
22
23 private static final PlainTextRenderer INSTANCE = new PlainTextRenderer();
24
25 public static PlainTextRenderer getInstance() {
26 return INSTANCE;
27 }
28
29 @Override
30 public void render(final String input, final StringBuilder output, final String styleName) {
31 output.append(input);
32 }
33
34 @Override
35 public void render(final StringBuilder input, final StringBuilder output) {
36 output.append(input);
37 }
38
39 }
1818 import org.apache.logging.log4j.core.LogEvent;
1919 import org.apache.logging.log4j.core.config.plugins.Plugin;
2020 import org.apache.logging.log4j.core.impl.ThrowableProxy;
21 import org.apache.logging.log4j.core.util.Constants;
21 import org.apache.logging.log4j.util.Strings;
2222
2323 /**
2424 * Outputs the Throwable portion of the LoggingEvent as a full stack trace
6464 super.format(event, toAppendTo);
6565 return;
6666 }
67 final String trace = proxy.getCauseStackTraceAsString(options.getPackages());
67 final String trace = proxy.getCauseStackTraceAsString(options.getIgnorePackages());
6868 final int len = toAppendTo.length();
6969 if (len > 0 && !Character.isWhitespace(toAppendTo.charAt(len - 1))) {
7070 toAppendTo.append(' ');
7171 }
72 if (!options.allLines() || !Constants.LINE_SEPARATOR.equals(options.getSeparator())) {
72 if (!options.allLines() || !Strings.LINE_SEPARATOR.equals(options.getSeparator())) {
7373 final StringBuilder sb = new StringBuilder();
74 final String[] array = trace.split(Constants.LINE_SEPARATOR);
74 final String[] array = trace.split(Strings.LINE_SEPARATOR);
7575 final int limit = options.minLines(array.length) - 1;
7676 for (int i = 0; i <= limit; ++i) {
7777 sb.append(array[i]);
1919
2020 import org.apache.logging.log4j.core.LogEvent;
2121 import org.apache.logging.log4j.core.config.plugins.Plugin;
22
2322
2423 /**
2524 * Formats the event sequence number.
9393 */
9494 @Override
9595 public void format(final LogEvent event, final StringBuilder toAppendTo) {
96 final StringBuilder buf = new StringBuilder();
97 for (final PatternFormatter formatter : patternFormatters) {
98 formatter.format(event, buf);
96 int start = 0;
97 int end = 0;
98 if (!noAnsi) { // use ANSI: set prefix
99 start = toAppendTo.length();
100 toAppendTo.append(style);
101 end = toAppendTo.length();
99102 }
100103
101 if (buf.length() > 0) {
102 if (noAnsi) {
103 // faster to test and do this than setting style and defaultStyle to empty strings.
104 toAppendTo.append(buf.toString());
104 //noinspection ForLoopReplaceableByForEach
105 for (int i = 0, size = patternFormatters.size(); i < size; i++) {
106 patternFormatters.get(i).format(event, toAppendTo);
107 }
108
109 // if we use ANSI we need to add the postfix or erase the unnecessary prefix
110 if (!noAnsi) {
111 if (toAppendTo.length() == end) {
112 toAppendTo.setLength(start); // erase prefix
105113 } else {
106 toAppendTo.append(style).append(buf.toString()).append(defaultStyle);
114 toAppendTo.append(defaultStyle); // add postfix
107115 }
108116 }
109117 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.pattern;
17
18 /**
19 * Renders an input to an output.
20 */
21 public interface TextRenderer {
22
23 /**
24 * Renders input text to an output.
25 *
26 * @param input
27 * The input
28 * @param output
29 * The output
30 * @param styleName
31 * The style name to use to render the input on the output.
32 */
33 void render(String input, StringBuilder output, String styleName);
34
35 /**
36 * Renders input text to an output.
37 *
38 * @param input
39 * The input
40 * @param output
41 * The output
42 */
43 void render(StringBuilder input, StringBuilder output);
44
45 }
2121 import org.apache.logging.log4j.core.LogEvent;
2222 import org.apache.logging.log4j.core.config.plugins.Plugin;
2323 import org.apache.logging.log4j.core.impl.ThrowableFormatOptions;
24 import org.apache.logging.log4j.core.util.Constants;
2524 import org.apache.logging.log4j.util.Strings;
2625
2726
140139 if (len > 0 && !Character.isWhitespace(buffer.charAt(len - 1))) {
141140 buffer.append(' ');
142141 }
143 if (!options.allLines() || !Constants.LINE_SEPARATOR.equals(options.getSeparator())) {
142 if (!options.allLines() || !Strings.LINE_SEPARATOR.equals(options.getSeparator())) {
144143 final StringBuilder sb = new StringBuilder();
145 final String[] array = w.toString().split(Constants.LINE_SEPARATOR);
144 final String[] array = w.toString().split(Strings.LINE_SEPARATOR);
146145 final int limit = options.minLines(array.length) - 1;
147146 for (int i = 0; i <= limit; ++i) {
148147 sb.append(array[i]);
1515 */
1616 package org.apache.logging.log4j.core.script;
1717
18 import org.apache.logging.log4j.Logger;
19 import org.apache.logging.log4j.status.StatusLogger;
20
1821 /**
1922 * Container for the language and body of a script.
2023 */
2124 public abstract class AbstractScript {
2225
26 protected static final Logger LOGGER = StatusLogger.getLogger();
2327 protected static final String DEFAULT_LANGUAGE = "JavaScript";
28
2429 private final String language;
2530 private final String scriptText;
2631 private final String name;
1515 */
1616 package org.apache.logging.log4j.core.script;
1717
18 import org.apache.logging.log4j.Logger;
1918 import org.apache.logging.log4j.core.config.Node;
2019 import org.apache.logging.log4j.core.config.plugins.Plugin;
2120 import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
2221 import org.apache.logging.log4j.core.config.plugins.PluginFactory;
2322 import org.apache.logging.log4j.core.config.plugins.PluginValue;
24 import org.apache.logging.log4j.status.StatusLogger;
2523
2624 /**
2725 * Container for the language and body of a script.
2826 */
2927 @Plugin(name = "Script", category = Node.CATEGORY, printObject = true)
3028 public class Script extends AbstractScript {
31
32 private static final Logger logger = StatusLogger.getLogger();
3329
3430 public Script(final String name, final String language, final String scriptText) {
3531 super(name, language, scriptText);
4339 @PluginValue("scriptText") final String scriptText) {
4440 // @formatter:on
4541 if (language == null) {
46 logger.info("No script language supplied, defaulting to {}", DEFAULT_LANGUAGE);
42 LOGGER.info("No script language supplied, defaulting to {}", DEFAULT_LANGUAGE);
4743 language = DEFAULT_LANGUAGE;
4844 }
4945 if (scriptText == null) {
50 logger.error("No scriptText attribute provided for ScriptFile {}", name);
46 LOGGER.error("No scriptText attribute provided for ScriptFile {}", name);
5147 return null;
5248 }
5349 return new Script(name, language, scriptText);
2525 import java.nio.file.Path;
2626 import java.nio.file.Paths;
2727
28 import org.apache.logging.log4j.Logger;
2928 import org.apache.logging.log4j.core.config.Node;
3029 import org.apache.logging.log4j.core.config.plugins.Plugin;
3130 import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
3433 import org.apache.logging.log4j.core.util.FileUtils;
3534 import org.apache.logging.log4j.core.util.IOUtils;
3635 import org.apache.logging.log4j.core.util.NetUtils;
37 import org.apache.logging.log4j.status.StatusLogger;
3836
3937 /**
4038 * Container for the language and body of a script file along with the file location.
4240 @Plugin(name = "ScriptFile", category = Node.CATEGORY, printObject = true)
4341 public class ScriptFile extends AbstractScript {
4442
45 private static final Logger LOGGER = StatusLogger.getLogger();
4643 private final Path filePath;
4744 private final boolean isWatched;
4845
3131 import javax.script.ScriptEngineFactory;
3232 import javax.script.ScriptEngineManager;
3333 import javax.script.ScriptException;
34 import javax.script.SimpleBindings;
3435
3536 import org.apache.logging.log4j.Logger;
37 import org.apache.logging.log4j.core.config.Configuration;
3638 import org.apache.logging.log4j.core.util.FileWatcher;
3739 import org.apache.logging.log4j.core.util.WatchManager;
3840 import org.apache.logging.log4j.status.StatusLogger;
4143 * Manages the scripts use by the Configuration.
4244 */
4345 public class ScriptManager implements FileWatcher, Serializable {
46
47 private abstract class AbstractScriptRunner implements ScriptRunner {
48
49 private static final String KEY_STATUS_LOGGER = "statusLogger";
50 private static final String KEY_CONFIGURATION = "configuration";
51
52 @Override
53 public Bindings createBindings() {
54 final SimpleBindings bindings = new SimpleBindings();
55 bindings.put(KEY_CONFIGURATION, configuration);
56 bindings.put(KEY_STATUS_LOGGER, logger);
57 return bindings;
58 }
59
60 }
61
4462 private static final long serialVersionUID = -2534169384971965196L;
4563 private static final String KEY_THREADING = "THREADING";
4664 private static final Logger logger = StatusLogger.getLogger();
4765
66 private final Configuration configuration;
4867 private final ScriptEngineManager manager = new ScriptEngineManager();
49 private final ConcurrentMap<String, ScriptRunner> scripts = new ConcurrentHashMap<>();
68 private final ConcurrentMap<String, ScriptRunner> scriptRunners = new ConcurrentHashMap<>();
5069 private final String languages;
5170 private final WatchManager watchManager;
52 private static final SecurityManager SECURITY_MANAGER = System.getSecurityManager();
53
54 public ScriptManager(final WatchManager watchManager) {
71
72 public ScriptManager(final Configuration configuration, final WatchManager watchManager) {
73 this.configuration = configuration;
5574 this.watchManager = watchManager;
5675 final List<ScriptEngineFactory> factories = manager.getEngineFactories();
5776 if (logger.isDebugEnabled()) {
101120 return;
102121 }
103122 if (engine.getFactory().getParameter(KEY_THREADING) == null) {
104 scripts.put(script.getName(), new ThreadLocalScriptRunner(script));
123 scriptRunners.put(script.getName(), new ThreadLocalScriptRunner(script));
105124 } else {
106 scripts.put(script.getName(), new MainScriptRunner(engine, script));
125 scriptRunners.put(script.getName(), new MainScriptRunner(engine, script));
107126 }
108127
109128 if (script instanceof ScriptFile) {
110 final ScriptFile scriptFile = (ScriptFile)script;
129 final ScriptFile scriptFile = (ScriptFile) script;
111130 final Path path = scriptFile.getPath();
112131 if (scriptFile.isWatched() && path != null) {
113132 watchManager.watchFile(path.toFile(), this);
115134 }
116135 }
117136
137 public Bindings createBindings(final AbstractScript script) {
138 return getScriptRunner(script).createBindings();
139 }
140
118141 public AbstractScript getScript(final String name) {
119 final ScriptRunner runner = scripts.get(name);
142 final ScriptRunner runner = scriptRunners.get(name);
120143 return runner != null ? runner.getScript() : null;
121144 }
122145
123146 @Override
124147 public void fileModified(final File file) {
125 final ScriptRunner runner = scripts.get(file.toString());
148 final ScriptRunner runner = scriptRunners.get(file.toString());
126149 if (runner == null) {
127150 logger.info("{} is not a running script");
128151 return;
130153 final ScriptEngine engine = runner.getScriptEngine();
131154 final AbstractScript script = runner.getScript();
132155 if (engine.getFactory().getParameter(KEY_THREADING) == null) {
133 scripts.put(script.getName(), new ThreadLocalScriptRunner(script));
156 scriptRunners.put(script.getName(), new ThreadLocalScriptRunner(script));
134157 } else {
135 scripts.put(script.getName(), new MainScriptRunner(engine, script));
158 scriptRunners.put(script.getName(), new MainScriptRunner(engine, script));
136159 }
137160
138161 }
139162
140163 public Object execute(final String name, final Bindings bindings) {
141 final ScriptRunner scriptRunner = scripts.get(name);
164 final ScriptRunner scriptRunner = scriptRunners.get(name);
142165 if (scriptRunner == null) {
143166 logger.warn("No script named {} could be found");
144167 return null;
153176
154177 private interface ScriptRunner {
155178
179 Bindings createBindings();
180
156181 Object execute(Bindings bindings);
157182
158183 AbstractScript getScript();
160185 ScriptEngine getScriptEngine();
161186 }
162187
163 private class MainScriptRunner implements ScriptRunner {
188 private class MainScriptRunner extends AbstractScriptRunner {
164189 private final AbstractScript script;
165190 private final CompiledScript compiledScript;
166191 private final ScriptEngine scriptEngine;
167
168192
169193 public MainScriptRunner(final ScriptEngine scriptEngine, final AbstractScript script) {
170194 this.script = script;
220244 }
221245 }
222246
223 private class ThreadLocalScriptRunner implements ScriptRunner {
247 private class ThreadLocalScriptRunner extends AbstractScriptRunner {
224248 private final AbstractScript script;
225249
226250 private final ThreadLocal<MainScriptRunner> runners = new ThreadLocal<MainScriptRunner>() {
243267 public AbstractScript getScript() {
244268 return script;
245269 }
246
247 @Override
270 @Override
248271 public ScriptEngine getScriptEngine() {
249272 return runners.get().getScriptEngine();
250273 }
251274 }
275
276 private ScriptRunner getScriptRunner(final AbstractScript script) {
277 return scriptRunners.get(script.getName());
278 }
252279 }
1515 */
1616 package org.apache.logging.log4j.core.script;
1717
18 import org.apache.logging.log4j.Logger;
1918 import org.apache.logging.log4j.core.config.Configuration;
2019 import org.apache.logging.log4j.core.config.Node;
2120 import org.apache.logging.log4j.core.config.plugins.Plugin;
2221 import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
2322 import org.apache.logging.log4j.core.config.plugins.PluginConfiguration;
2423 import org.apache.logging.log4j.core.config.plugins.PluginFactory;
25 import org.apache.logging.log4j.status.StatusLogger;
2624
2725 /**
2826 * Contains a reference to a script defined elsewhere in the configuration.
3028 @Plugin(name = "ScriptRef", category = Node.CATEGORY, printObject = true)
3129 public class ScriptRef extends AbstractScript {
3230
33 private static final Logger logger = StatusLogger.getLogger();
3431 private final ScriptManager scriptManager;
3532
3633 public ScriptRef(final String name, final ScriptManager scriptManager) {
5855 @PluginConfiguration final Configuration configuration) {
5956 // @formatter:on
6057 if (name == null) {
61 logger.error("No script name provided");
58 LOGGER.error("No script name provided");
6259 return null;
6360 }
6461 return new ScriptRef(name, configuration.getScriptManager());
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.selector;
17
18 import java.net.URI;
19 import java.util.ArrayList;
20 import java.util.Collections;
21 import java.util.List;
22
23 import org.apache.logging.log4j.core.LoggerContext;
24 import org.apache.logging.log4j.core.impl.ContextAnchor;
25
26 /**
27 * Returns either this Thread's context or the default LoggerContext.
28 */
29 public class BasicContextSelector implements ContextSelector {
30
31 private static final LoggerContext CONTEXT = new LoggerContext("Default");
32
33 @Override
34 public LoggerContext getContext(final String fqcn, final ClassLoader loader, final boolean currentContext) {
35
36 final LoggerContext ctx = ContextAnchor.THREAD_CONTEXT.get();
37 return ctx != null ? ctx : CONTEXT;
38 }
39
40
41 @Override
42 public LoggerContext getContext(final String fqcn, final ClassLoader loader, final boolean currentContext,
43 final URI configLocation) {
44
45 final LoggerContext ctx = ContextAnchor.THREAD_CONTEXT.get();
46 return ctx != null ? ctx : CONTEXT;
47 }
48
49 public LoggerContext locateContext(final String name, final String configLocation) {
50 return CONTEXT;
51 }
52
53 @Override
54 public void removeContext(final LoggerContext context) {
55 }
56
57 @Override
58 public List<LoggerContext> getLoggerContexts() {
59 final List<LoggerContext> list = new ArrayList<>();
60 list.add(CONTEXT);
61 return Collections.unmodifiableList(list);
62 }
63
64 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.selector;
17
18 import java.net.URI;
19 import java.util.ArrayList;
20 import java.util.Collections;
21 import java.util.List;
22
23 import org.apache.logging.log4j.core.LoggerContext;
24 import org.apache.logging.log4j.core.impl.ContextAnchor;
25
26 /**
27 * Returns either this Thread's context or the default LoggerContext.
28 */
29 public class BasicContextSelector implements ContextSelector {
30
31 private static final LoggerContext CONTEXT = new LoggerContext("Default");
32
33 @Override
34 public LoggerContext getContext(final String fqcn, final ClassLoader loader, final boolean currentContext) {
35
36 final LoggerContext ctx = ContextAnchor.THREAD_CONTEXT.get();
37 return ctx != null ? ctx : CONTEXT;
38 }
39
40
41 @Override
42 public LoggerContext getContext(final String fqcn, final ClassLoader loader, final boolean currentContext,
43 final URI configLocation) {
44
45 final LoggerContext ctx = ContextAnchor.THREAD_CONTEXT.get();
46 return ctx != null ? ctx : CONTEXT;
47 }
48
49 public LoggerContext locateContext(final String name, final String configLocation) {
50 return CONTEXT;
51 }
52
53 @Override
54 public void removeContext(final LoggerContext context) {
55 // does not remove anything
56 }
57
58 @Override
59 public List<LoggerContext> getLoggerContexts() {
60 final List<LoggerContext> list = new ArrayList<>();
61 list.add(CONTEXT);
62 return Collections.unmodifiableList(list);
63 }
64
65 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.selector;
17
18 import org.apache.logging.log4j.core.async.AsyncLoggerContextSelector;
19
20 public class CoreContextSelectors {
21
22 public static final Class<?>[] CLASSES = new Class<?>[] { ClassLoaderContextSelector.class, BasicContextSelector.class, AsyncLoggerContextSelector.class };
23
24 }
113113 } catch (final NamingException ne) {
114114 LOGGER.error("Unable to lookup {}", Constants.JNDI_CONTEXT_NAME, ne);
115115 } finally {
116 jndiManager.release();
116 jndiManager.close();
117117 }
118118
119119 return loggingContextName == null ? CONTEXT : locateContext(loggingContextName, null, configLocation);
2020 import java.util.ArrayList;
2121 import java.util.Arrays;
2222 import java.util.List;
23
24 import org.apache.logging.log4j.util.Strings;
2325
2426 /**
2527 * Generates source code for custom or extended logger wrappers.
10931095 sb.append(String.format(phase2, ""));
10941096 }
10951097
1096 sb.append(String.format("}%n", "")); // yes, does not use args to apply %n
1098 sb.append('}');
1099 sb.append(Strings.LINE_SEPARATOR);
10971100 return sb.toString();
10981101 }
10991102
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16
17 package org.apache.logging.log4j.core.util;
18
19 import java.lang.reflect.Array;
20
21 /**
22 * Copied from Apache Commons Lang (including the {@code @since} tags.)
23 */
24 public class ArrayUtils {
25
26 /**
27 * <p>Returns the length of the specified array.
28 * This method can deal with {@code Object} arrays and with primitive arrays.</p>
29 *
30 * <p>If the input array is {@code null}, {@code 0} is returned.</p>
31 *
32 * <pre>
33 * ArrayUtils.getLength(null) = 0
34 * ArrayUtils.getLength([]) = 0
35 * ArrayUtils.getLength([null]) = 1
36 * ArrayUtils.getLength([true, false]) = 2
37 * ArrayUtils.getLength([1, 2, 3]) = 3
38 * ArrayUtils.getLength(["a", "b", "c"]) = 3
39 * </pre>
40 *
41 * @param array the array to retrieve the length from, may be null
42 * @return The length of the array, or {@code 0} if the array is {@code null}
43 * @throws IllegalArgumentException if the object argument is not an array.
44 * @since 2.1
45 */
46 public static int getLength(final Object array) {
47 if (array == null) {
48 return 0;
49 }
50 return Array.getLength(array);
51 }
52
53 /**
54 * <p>Removes the element at the specified position from the specified array.
55 * All subsequent elements are shifted to the left (subtracts one from
56 * their indices).</p>
57 *
58 * <p>This method returns a new array with the same elements of the input
59 * array except the element on the specified position. The component
60 * type of the returned array is always the same as that of the input
61 * array.</p>
62 *
63 * <p>If the input array is {@code null}, an IndexOutOfBoundsException
64 * will be thrown, because in that case no valid index can be specified.</p>
65 *
66 * @param array the array to remove the element from, may not be {@code null}
67 * @param index the position of the element to be removed
68 * @return A new array containing the existing elements except the element
69 * at the specified position.
70 * @throws IndexOutOfBoundsException if the index is out of range
71 * (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
72 * @since 2.1
73 */
74 private static Object remove(final Object array, final int index) {
75 final int length = getLength(array);
76 if (index < 0 || index >= length) {
77 throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + length);
78 }
79
80 final Object result = Array.newInstance(array.getClass().getComponentType(), length - 1);
81 System.arraycopy(array, 0, result, 0, index);
82 if (index < length - 1) {
83 System.arraycopy(array, index + 1, result, index, length - index - 1);
84 }
85
86 return result;
87 }
88
89 /**
90 * <p>Removes the element at the specified position from the specified array.
91 * All subsequent elements are shifted to the left (subtracts one from
92 * their indices).</p>
93 *
94 * <p>This method returns a new array with the same elements of the input
95 * array except the element on the specified position. The component
96 * type of the returned array is always the same as that of the input
97 * array.</p>
98 *
99 * <p>If the input array is {@code null}, an IndexOutOfBoundsException
100 * will be thrown, because in that case no valid index can be specified.</p>
101 *
102 * <pre>
103 * ArrayUtils.remove(["a"], 0) = []
104 * ArrayUtils.remove(["a", "b"], 0) = ["b"]
105 * ArrayUtils.remove(["a", "b"], 1) = ["a"]
106 * ArrayUtils.remove(["a", "b", "c"], 1) = ["a", "c"]
107 * </pre>
108 *
109 * @param <T> the component type of the array
110 * @param array the array to remove the element from, may not be {@code null}
111 * @param index the position of the element to be removed
112 * @return A new array containing the existing elements except the element
113 * at the specified position.
114 * @throws IndexOutOfBoundsException if the index is out of range
115 * (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
116 * @since 2.1
117 */
118 @SuppressWarnings("unchecked") // remove() always creates an array of the same type as its input
119 public static <T> T[] remove(final T[] array, final int index) {
120 return (T[]) remove((Object) array, index);
121 }
122
123 }
1515 */
1616 package org.apache.logging.log4j.core.util;
1717
18 import java.util.Objects;
19
2018 /**
2119 * Utility class providing common validation logic.
2220 */
3028 }
3129 return value;
3230 }
33
34 /**
35 * Throws a {@code NullPointerException} if the specified parameter is
36 * {@code null}, otherwise returns the specified parameter.
37 * <p>
38 * On Java 7, just use {@code Objects.requireNonNull(T, String)}
39 * </p>
40 * <p>
41 * Usage:
42 * </p>
43 * <pre>
44 * // earlier you would write this:
45 * public SomeConstructor(Object param) {
46 * if (param == null) {
47 * throw new NullPointerException(&quot;param&quot;);
48 * }
49 * this.field = param;
50 * }
51 *
52 * // now you can do the same in one line:
53 * public SomeConstructor(Object param) {
54 * this.field = Assert.requireNonNull(&quot;param&quot;);
55 * }
56 * </pre>
57 *
58 * @param <T> the type of the parameter to check and return
59 * @param object the parameter to check
60 * @param message message to populate the NPE with if necessary
61 * @return the specified parameter
62 * @throws NullPointerException if {@code object} is {@code null}
63 * @deprecated Will be removed in 2.5.
64 */
65 @Deprecated
66 public static <T> T requireNonNull(final T object, final String message) {
67 return Objects.requireNonNull(object, message);
68 }
6931 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.util;
17
18 import com.beust.jcommander.JCommander;
19 import com.beust.jcommander.Parameter;
20
21 public class BasicCommandLineArguments {
22
23 public static <T extends BasicCommandLineArguments> T parseCommandLine(final String[] mainArgs, final Class<?> clazz,
24 final T args) {
25 final JCommander jCommander = new JCommander(args);
26 jCommander.setProgramName(clazz.getName());
27 jCommander.setCaseSensitiveOptions(false); // for sanity
28 jCommander.parse(mainArgs);
29 if (args.isHelp()) {
30 jCommander.usage();
31 }
32 return args;
33 }
34
35 @Parameter(names = { "--help", "-?", "-h" }, help = true, description = "Prints this help.")
36 private boolean help;
37
38 public boolean isHelp() {
39 return help;
40 }
41
42 public void setHelp(boolean help) {
43 this.help = help;
44 }
45
46 }
4444 LockSupport.parkNanos(1000 * 1000);
4545 }
4646 }
47 }, "Clock Updater Thread");
47 }, "CachedClock Updater Thread");
4848 updater.setDaemon(true);
4949 updater.start();
5050 }
3838 *
3939 * @param closeable the resource to close, may be {@code null}
4040 */
41 public static void closeSilently(final Closeable closeable) {
41 public static boolean closeSilently(final Closeable closeable) {
4242 try {
4343 close(closeable);
44 return true;
4445 } catch (final Exception ignored) {
4546 // ignored
47 return false;
4648 }
4749 }
4850
2727 // ignore IDE complaints; volatile long is fine
2828 private volatile long millis = System.currentTimeMillis();
2929
30 private final Thread updater = new Log4jThread("Clock Updater Thread") {
30 private final Thread updater = new Log4jThread("CoarseCachedClock Updater Thread") {
3131 @Override
3232 public void run() {
3333 while (true) {
1414 * limitations under the license.
1515 */
1616 package org.apache.logging.log4j.core.util;
17
18 import java.nio.charset.Charset;
19 import java.nio.charset.StandardCharsets;
2017
2118 import org.apache.logging.log4j.util.PropertiesUtil;
2219
4643 public static final String JNDI_CONTEXT_NAME = "java:comp/env/log4j/context-name";
4744
4845 /**
49 * Line separator.
50 */
51 public static final String LINE_SEPARATOR = PropertiesUtil.getProperties().getStringProperty("line.separator",
52 "\n");
53
54 /**
5546 * Number of milliseconds in a second.
5647 */
5748 public static final int MILLIS_IN_SECONDS = 1000;
58
59 /**
60 * Equivalent to StandardCharsets.UTF_8.
61 *
62 * @deprecated Use {@link StandardCharsets#UTF_8}. Will be removed in 2.5.
63 */
64 @Deprecated
65 public static final Charset UTF_8 = StandardCharsets.UTF_8;
6649
6750 /**
6851 * Supports user request LOG4J2-898 to have the option to format a message in the background thread.
2323 import java.util.concurrent.CopyOnWriteArrayList;
2424 import java.util.concurrent.Executors;
2525 import java.util.concurrent.ThreadFactory;
26 import java.util.concurrent.TimeUnit;
2627 import java.util.concurrent.atomic.AtomicReference;
2728
2829 import org.apache.logging.log4j.Logger;
29 import org.apache.logging.log4j.core.LifeCycle;
30 import org.apache.logging.log4j.core.AbstractLifeCycle;
31 import org.apache.logging.log4j.core.LifeCycle2;
3032 import org.apache.logging.log4j.status.StatusLogger;
3133
3234 /**
3537 *
3638 * @since 2.1
3739 */
38 public class DefaultShutdownCallbackRegistry implements ShutdownCallbackRegistry, LifeCycle, Runnable {
40 public class DefaultShutdownCallbackRegistry implements ShutdownCallbackRegistry, LifeCycle2, Runnable {
3941 /** Status logger. */
4042 protected static final Logger LOGGER = StatusLogger.getLogger();
4143
148150 Runtime.getRuntime().addShutdownHook(thread);
149151 }
150152
153 @Override
154 public void stop() {
155 stop(AbstractLifeCycle.DEFAULT_STOP_TIMEOUT, AbstractLifeCycle.DEFAULT_STOP_TIMEUNIT);
156 }
157
151158 /**
152159 * Cancels the shutdown thread only if this is started.
153160 */
154161 @Override
155 public void stop() {
162 public boolean stop(final long timeout, final TimeUnit timeUnit) {
156163 if (state.compareAndSet(State.STARTED, State.STOPPING)) {
157164 try {
158165 removeShutdownHook();
160167 state.set(State.STOPPED);
161168 }
162169 }
170 return true;
163171 }
164172
165173 private void removeShutdownHook() {
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.util;
17
18 import java.util.concurrent.ExecutorService;
19 import java.util.concurrent.TimeUnit;
20
21 import org.apache.logging.log4j.Logger;
22 import org.apache.logging.log4j.status.StatusLogger;
23
24 public class ExecutorServices {
25
26 private static final Logger LOGGER = StatusLogger.getLogger();
27
28 /**
29 * Shuts down the given {@link ExecutorService} in an orderly fashion. Disables new tasks from submission and then
30 * waits for existing tasks to terminate. Eventually cancels running tasks if too much time elapses.
31 * <p>
32 * If the timeout is < 0, then a plain shutdown takes place.
33 * </p>
34 *
35 * @param executorService
36 * the pool to shutdown.
37 * @param timeout
38 * the maximum time to wait
39 * @param timeUnit
40 * the time unit of the timeout argument
41 * @param source
42 * use this string in any log messages.
43 * @return {@code true} if the given executor terminated and {@code false} if the timeout elapsed before
44 * termination.
45 */
46 public static boolean shutdown(final ExecutorService executorService, final long timeout, final TimeUnit timeUnit, final String source) {
47 if (executorService == null || executorService.isTerminated()) {
48 return true;
49 }
50 executorService.shutdown(); // Disable new tasks from being submitted
51 if (timeout > 0 && timeUnit == null) {
52 throw new IllegalArgumentException(
53 String.format("%s can't shutdown %s when timeout = %,d and timeUnit = %s.", source, executorService,
54 timeout, timeUnit));
55 }
56 if (timeout > 0) {
57 try {
58 // Wait a while for existing tasks to terminate
59 if (!executorService.awaitTermination(timeout, timeUnit)) {
60 executorService.shutdownNow(); // Cancel currently executing tasks
61 // Wait a while for tasks to respond to being cancelled
62 if (!executorService.awaitTermination(timeout, timeUnit)) {
63 LOGGER.error("{} pool {} did not terminate after {} {}", source, executorService, timeout,
64 timeUnit);
65 }
66 return false;
67 }
68 } catch (final InterruptedException ie) {
69 // (Re-)Cancel if current thread also interrupted
70 executorService.shutdownNow();
71 // Preserve interrupt status
72 Thread.currentThread().interrupt();
73 }
74 } else {
75 executorService.shutdown();
76 }
77 return true;
78 }
79
80 }
1818 import java.io.File;
1919
2020 /**
21 * Watches for changes in a Path and performs an action when the file is modified.
21 * Watches for changes in a File and performs an action when the file is modified.
2222 */
2323 public interface FileWatcher {
2424
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.util;
17
18 import java.net.InetAddress;
19 import java.net.UnknownHostException;
20
21 import com.beust.jcommander.IStringConverter;
22
23 public class InetAddressConverter implements IStringConverter<InetAddress> {
24
25 @Override
26 public InetAddress convert(String host) {
27 try {
28 return InetAddress.getByName(host);
29 } catch (UnknownHostException e) {
30 throw new IllegalArgumentException(host, e);
31 }
32 }
33
34 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16
17 package org.apache.logging.log4j.core.util;
18
19 import javax.naming.Context;
20 import javax.naming.NamingException;
21
22 /**
23 * Helper class for closing JNDI resources.
24 *
25 * This class is separate from {@link Closer} because JNDI is not in Android.
26 */
27 public final class JndiCloser {
28
29 private JndiCloser() {
30 }
31
32 /**
33 * Closes the specified {@code Context}.
34 *
35 * @param context the JNDI Context to close, may be {@code null}
36 * @throws NamingException if a problem occurred closing the specified JNDI Context
37 */
38 public static void close(final Context context) throws NamingException {
39 if (context != null) {
40 context.close();
41 }
42 }
43
44 /**
45 * Closes the specified {@code Context}, ignoring any exceptions thrown by the close operation.
46 *
47 * @param context the JNDI Context to close, may be {@code null}
48 */
49 public static void closeSilently(final Context context) {
50 try {
51 close(context);
52 } catch (final NamingException ignored) {
53 // ignored
54 }
55 }
56
57 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16
17 package org.apache.logging.log4j.core.util;
18
19 import javax.naming.Context;
20 import javax.naming.NamingException;
21
22 /**
23 * Helper class for closing JNDI resources.
24 *
25 * This class is separate from {@link Closer} because JNDI is not in Android.
26 */
27 public final class JndiCloser {
28
29 private JndiCloser() {
30 }
31
32 /**
33 * Closes the specified {@code Context}.
34 *
35 * @param context the JNDI Context to close, may be {@code null}
36 * @throws NamingException if a problem occurred closing the specified JNDI Context
37 */
38 public static void close(final Context context) throws NamingException {
39 if (context != null) {
40 context.close();
41 }
42 }
43
44 /**
45 * Closes the specified {@code Context}, ignoring any exceptions thrown by the close operation.
46 *
47 * @param context the JNDI Context to close, may be {@code null}
48 */
49 public static boolean closeSilently(final Context context) {
50 try {
51 close(context);
52 return true;
53 } catch (final NamingException ignored) {
54 // ignored
55 return false;
56 }
57 }
58
59 }
1515 */
1616 package org.apache.logging.log4j.core.util;
1717
18
1918 import java.io.InputStream;
2019 import java.lang.reflect.InvocationTargetException;
2120 import java.net.URL;
215214 }
216215
217216 /**
218 * Load a Class by name. Note that unlike {@link ClassLoader#loadClass(String) ClassLoader.loadClass}, this method
219 * will initialize the class as well if it hasn't been already. This is equivalent to the calling the
220 * {@link ClassLoader#loadClass(String, boolean) protected version} with the second parameter equal to {@code true}.
221 *
222 * @param className The class name.
223 * @return The Class.
224 * @throws ClassNotFoundException if the Class could not be found.
225 */
226 public static Class<?> loadClass(final String className) throws ClassNotFoundException {
227 return LoaderUtil.loadClass(className);
228 }
229
230 /**
231217 * Loads and initializes a named Class using a given ClassLoader.
232218 *
233219 * @param className The class name.
307293 * @return {@code true} if the class could be found or {@code false} otherwise.
308294 */
309295 public static boolean isClassAvailable(final String className) {
310 try {
311 final Class<?> clazz = loadClass(className);
312 return clazz != null;
313 } catch (final ClassNotFoundException e) {
314 return false;
315 } catch (final Throwable e) {
316 LOGGER.trace("Unknown error checking for existence of class [{}].", className, e);
317 return false;
318 }
319 }
296 return LoaderUtil.isClassAvailable(className);
297 }
298
299 public static boolean isJansiAvailable() {
300 return isClassAvailable("org.fusesource.jansi.AnsiRenderer");
301 }
302
320303 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16
17 package org.apache.logging.log4j.core.util;
18
19 /**
20 * Prefixes thread names with {@code "Log4j2-"}.
21 */
22 public class Log4jThread extends Thread {
23
24 private static final String PREFIX = "Log4j2-";
25
26 private static int threadInitNumber;
27
28 private static synchronized int nextThreadNum() {
29 return threadInitNumber++;
30 }
31
32 private static String toThreadName(final Object name) {
33 return PREFIX + name;
34 }
35
36 public Log4jThread() {
37 super(toThreadName(nextThreadNum()));
38 }
39
40 public Log4jThread(final Runnable target) {
41 super(target, toThreadName(nextThreadNum()));
42 }
43
44 public Log4jThread(final Runnable target, final String name) {
45 super(target, toThreadName(name));
46 }
47
48 public Log4jThread(final String name) {
49 super(toThreadName(name));
50 }
51
52 public Log4jThread(final ThreadGroup group, final Runnable target) {
53 super(group, target, toThreadName(nextThreadNum()));
54 }
55
56 public Log4jThread(final ThreadGroup group, final Runnable target, final String name) {
57 super(group, target, toThreadName(name));
58 }
59
60 public Log4jThread(final ThreadGroup group, final Runnable target, final String name, final long stackSize) {
61 super(group, target, toThreadName(name), stackSize);
62 }
63
64 public Log4jThread(final ThreadGroup group, final String name) {
65 super(group, toThreadName(name));
66 }
67
68 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16
17 package org.apache.logging.log4j.core.util;
18
19 /**
20 * Prefixes thread names with {@code "Log4j2-"}.
21 */
22 public class Log4jThread extends Thread {
23
24 static final String PREFIX = "Log4j2-";
25
26 private static int threadInitNumber;
27
28 private static synchronized int nextThreadNum() {
29 return threadInitNumber++;
30 }
31
32 private static String toThreadName(final Object name) {
33 return PREFIX + name;
34 }
35
36 public Log4jThread() {
37 super(toThreadName(nextThreadNum()));
38 }
39
40 public Log4jThread(final Runnable target) {
41 super(target, toThreadName(nextThreadNum()));
42 }
43
44 public Log4jThread(final Runnable target, final String name) {
45 super(target, toThreadName(name));
46 }
47
48 public Log4jThread(final String name) {
49 super(toThreadName(name));
50 }
51
52 public Log4jThread(final ThreadGroup group, final Runnable target) {
53 super(group, target, toThreadName(nextThreadNum()));
54 }
55
56 public Log4jThread(final ThreadGroup group, final Runnable target, final String name) {
57 super(group, target, toThreadName(name));
58 }
59
60 public Log4jThread(final ThreadGroup group, final Runnable target, final String name, final long stackSize) {
61 super(group, target, toThreadName(name), stackSize);
62 }
63
64 public Log4jThread(final ThreadGroup group, final String name) {
65 super(group, toThreadName(name));
66 }
67
68 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16
17 package org.apache.logging.log4j.core.util;
18
19 import java.util.concurrent.ThreadFactory;
20 import java.util.concurrent.atomic.AtomicInteger;
21
22 /**
23 * Creates {@link Log4jThread}s.
24 *
25 * @since 2.7
26 */
27 public class Log4jThreadFactory implements ThreadFactory {
28
29 private static final String PREFIX = "TF-";
30
31 /**
32 * Creates a new daemon thread factory.
33 *
34 * @param threadFactoryName
35 * The thread factory name.
36 * @return a new daemon thread factory.
37 */
38 public static Log4jThreadFactory createDaemonThreadFactory(final String threadFactoryName) {
39 return new Log4jThreadFactory(threadFactoryName, true, Thread.NORM_PRIORITY);
40 }
41
42 /**
43 * Creates a new thread factory.
44 *
45 * @param threadFactoryName
46 * The thread factory name.
47 * @return a new daemon thread factory.
48 */
49 public static Log4jThreadFactory createThreadFactory(final String threadFactoryName) {
50 return new Log4jThreadFactory(threadFactoryName, false, Thread.NORM_PRIORITY);
51 }
52
53 private static final AtomicInteger FACTORY_NUMBER = new AtomicInteger(1);
54 private static final AtomicInteger THREAD_NUMBER = new AtomicInteger(1);
55 private final boolean daemon;
56 private final ThreadGroup group;
57 private final int priority;
58 private final String threadNamePrefix;
59
60 /**
61 * Constructs an initialized thread factory.
62 *
63 * @param threadFactoryName
64 * The thread factory name.
65 * @param daemon
66 * Whether to create daemon threads.
67 * @param priority
68 * The thread priority.
69 */
70 public Log4jThreadFactory(final String threadFactoryName, final boolean daemon, final int priority) {
71 this.threadNamePrefix = PREFIX + FACTORY_NUMBER.getAndIncrement() + "-" + threadFactoryName + "-";
72 this.daemon = daemon;
73 this.priority = priority;
74 final SecurityManager securityManager = System.getSecurityManager();
75 this.group = securityManager != null ? securityManager.getThreadGroup()
76 : Thread.currentThread().getThreadGroup();
77 }
78
79 @Override
80 public Thread newThread(final Runnable runnable) {
81 // Log4jThread prefixes names with "Log4j2-".
82 final Thread thread = new Log4jThread(group, runnable, threadNamePrefix + THREAD_NUMBER.getAndIncrement(), 0);
83 if (thread.isDaemon() != daemon) {
84 thread.setDaemon(daemon);
85 }
86 if (thread.getPriority() != priority) {
87 thread.setPriority(priority);
88 }
89 return thread;
90 }
91
92 }
3030 */
3131 public class NullOutputStream extends OutputStream {
3232
33 private static final NullOutputStream INSTANCE = new NullOutputStream();
34
3335 /**
34 * A singleton.
36 * @deprecated Deprecated in 2.7: use {@link #getInstance()}.
3537 */
36 public static final NullOutputStream NULL_OUTPUT_STREAM = new NullOutputStream();
38 @Deprecated
39 public static final NullOutputStream NULL_OUTPUT_STREAM = INSTANCE;
3740
41 /**
42 * Gets the singleton instance.
43 *
44 * @return the singleton instance.
45 */
46 public static NullOutputStream getInstance() {
47 return INSTANCE;
48 }
49
50 private NullOutputStream() {
51 // do nothing
52 }
53
3854 /**
3955 * Does nothing - output to <code>/dev/null</code>.
4056 *
2020
2121 import org.apache.logging.log4j.Logger;
2222 import org.apache.logging.log4j.status.StatusLogger;
23 import org.apache.logging.log4j.util.LoaderUtil;
2324 import org.apache.logging.log4j.util.PropertiesUtil;
2425 import org.apache.logging.log4j.util.Strings;
2526
224225 final Object defaultValue) {
225226 if (className != null) {
226227 try {
227 final Class<?> classObj = Loader.loadClass(className);
228 final Class<?> classObj = LoaderUtil.loadClass(className);
228229 if (!superClass.isAssignableFrom(classObj)) {
229230 LOGGER.error("A \"{}\" object is not assignable to a \"{}\" variable.", className,
230231 superClass.getName());
185185 final Constructor<T> constructor = getDefaultConstructor(clazz);
186186 try {
187187 return constructor.newInstance();
188 } catch (final NoClassDefFoundError | InstantiationException e) {
188 } catch (final LinkageError | InstantiationException e) {
189189 // LOG4J2-1051
190190 // On platforms like Google App Engine and Android, some JRE classes are not supported: JMX, JNDI, etc.
191191 throw new IllegalArgumentException(e);
1515 */
1616 package org.apache.logging.log4j.core.util;
1717
18 import java.lang.reflect.Field;
1819 import java.lang.reflect.GenericArrayType;
1920 import java.lang.reflect.ParameterizedType;
2021 import java.lang.reflect.Type;
2122 import java.lang.reflect.WildcardType;
23 import java.util.ArrayList;
24 import java.util.List;
2225 import java.util.Objects;
2326
2427 /**
3538 * @since 2.1
3639 */
3740 public final class TypeUtil {
41
3842 private TypeUtil() {
3943 }
4044
45 /**
46 * Gets all declared fields for the given class (including superclasses).
47 *
48 * @param cls the class to examine
49 * @return all declared fields for the given class (including superclasses).
50 * @see Class#getDeclaredFields()
51 */
52 public static List<Field> getAllDeclaredFields(Class<?> cls) {
53 final List<Field> fields = new ArrayList<>();
54 while (cls != null) {
55 for (final Field field : cls.getDeclaredFields()) {
56 fields.add(field);
57 }
58 cls = cls.getSuperclass();
59 }
60 return fields;
61 }
4162 /**
4263 * Indicates if two {@link Type}s are assignment compatible.
4364 *
6262 public void start() {
6363 super.start();
6464 if (intervalSeconds > 0) {
65 future = scheduler.scheduleWithFixedDelay(new WatchWorker(), intervalSeconds, intervalSeconds,
65 future = scheduler.scheduleWithFixedDelay(new WatchRunnable(), intervalSeconds, intervalSeconds,
6666 TimeUnit.SECONDS);
6767 }
6868 }
6969
7070 @Override
71 public void stop() {
72 future.cancel(true);
73 super.stop();
71 public boolean stop(final long timeout, final TimeUnit timeUnit) {
72 setStopping();
73 final boolean stopped = stop(future);
74 setStopped();
75 return stopped;
7476 }
7577
7678 public void watchFile(final File file, final FileWatcher watcher) {
8688 return map;
8789 }
8890
89 private class WatchWorker implements Runnable {
91 private class WatchRunnable implements Runnable {
9092
9193 @Override
9294 public void run() {
9597 final FileMonitor fileMonitor = entry.getValue();
9698 final long lastModfied = file.lastModified();
9799 if (fileModified(fileMonitor, lastModfied)) {
98 logger.info("File {} was modified", file.toString());
100 logger.info("File {} was modified on {}, previous modification was {}", file, lastModfied, fileMonitor.lastModified);
99101 fileMonitor.lastModified = lastModfied;
100102 fileMonitor.fileWatcher.fileModified(file);
101103 }
118118 * <p>
119119 * Constructs a new FastDateParser.
120120 * </p>
121 *
121 *
122122 * Use {@link FastDateFormat#getInstance(String, TimeZone, Locale)} or another variation of the factory methods of
123123 * {@link FastDateFormat} to get a cached FastDateParser instance.
124124 *
235235 // -----------------------------------------------------------------------
236236 /*
237237 * (non-Javadoc)
238 *
238 *
239239 * @see org.apache.commons.lang3.time.DateParser#getPattern()
240240 */
241241 @Override
245245
246246 /*
247247 * (non-Javadoc)
248 *
248 *
249249 * @see org.apache.commons.lang3.time.DateParser#getTimeZone()
250250 */
251251 @Override
255255
256256 /*
257257 * (non-Javadoc)
258 *
258 *
259259 * @see org.apache.commons.lang3.time.DateParser#getLocale()
260260 */
261261 @Override
333333
334334 /*
335335 * (non-Javadoc)
336 *
336 *
337337 * @see org.apache.commons.lang3.time.DateParser#parseObject(java.lang.String)
338338 */
339339 @Override
343343
344344 /*
345345 * (non-Javadoc)
346 *
346 *
347347 * @see org.apache.commons.lang3.time.DateParser#parse(java.lang.String)
348348 */
349349 @Override
362362
363363 /*
364364 * (non-Javadoc)
365 *
365 *
366366 * @see org.apache.commons.lang3.time.DateParser#parseObject(java.lang.String, java.text.ParsePosition)
367367 */
368368 @Override
430430
431431 /**
432432 * Escape constant fields into regular expression
433 *
433 *
434434 * @param regex The destination regex
435435 * @param value The source field
436436 * @param unquote If true, replace two success quotes ('') with single quote (')
456456 /*
457457 * If we have found \E, we replace it with \E\\E\Q, i.e. we stop the quoting, quote the \ in \E, then
458458 * restart the quoting.
459 *
459 *
460460 * Otherwise we just output the two characters. In each case the initial \ needs to be output and the
461461 * final char is done at the end
462462 */
478478
479479 /**
480480 * Get the short and long values displayed for a field
481 *
481 *
482482 * @param field The field of interest
483483 * @param definingCalendar The calendar to obtain the short and long values
484484 * @param locale The locale of display names
491491
492492 /**
493493 * Adjust dates to be within appropriate century
494 *
494 *
495495 * @param twoDigitYear The year to adjust
496496 * @return A value between centuryStart(inclusive) to centuryStart+100(exclusive)
497497 */
502502
503503 /**
504504 * Is the next field a number?
505 *
505 *
506506 * @return true, if next field will be a number
507507 */
508508 boolean isNextNumber() {
511511
512512 /**
513513 * What is the width of the current field?
514 *
514 *
515515 * @return The number of characters in the current format field
516516 */
517517 int getFieldWidth() {
548548 /**
549549 * Generate a <code>Pattern</code> regular expression to the <code>StringBuilder</code> which will accept this
550550 * field
551 *
551 *
552552 * @param parser The parser calling this strategy
553553 * @param regex The <code>StringBuilder</code> to append to
554554 * @return true, if this field will set the calendar; false, if this field is a constant value
565565
566566 /**
567567 * Obtain a Strategy given a field from a SimpleDateFormat pattern
568 *
568 *
569569 * @param formatField A sub-sequence of the SimpleDateFormat pattern
570570 * @param definingCalendar The calendar to obtain the short and long values
571571 * @return The Strategy that will handle parsing for the field
634634
635635 /**
636636 * Get a cache of Strategies for a particular field
637 *
637 *
638638 * @param field The Calendar field
639639 * @return a cache of Locale to Strategy
640640 */
649649
650650 /**
651651 * Construct a Strategy that parses a Text field
652 *
652 *
653653 * @param field The Calendar field
654654 * @param definingCalendar The calendar to obtain the short and long values
655655 * @return a TextStrategy for the field and Locale
676676
677677 /**
678678 * Construct a Strategy that ensures the formatField has literal text
679 *
679 *
680680 * @param formatField The literal text to match
681681 */
682682 CopyQuotedStrategy(final String formatField) {
715715
716716 /**
717717 * Construct a Strategy that parses a Text field
718 *
718 *
719719 * @param field The Calendar field
720720 * @param definingCalendar The Calendar to use
721721 * @param locale The Locale to use
771771
772772 /**
773773 * Construct a Strategy that parses a Number field
774 *
774 *
775775 * @param field The Calendar field
776776 */
777777 NumberStrategy(final int field) {
810810
811811 /**
812812 * Make any modifications to parsed integer
813 *
813 *
814814 * @param iValue The parsed integer
815815 * @return The modified value
816816 */
837837
838838 /**
839839 * Construct a Strategy that parses a TimeZone
840 *
840 *
841841 * @param locale The Locale
842842 */
843843 TimeZoneStrategy(final Locale locale) {
854854 }
855855 final TimeZone tz = TimeZone.getTimeZone(tzId);
856856 for (int i = 1; i < zoneNames.length; ++i) {
857 final String zoneName = zoneNames[i].toLowerCase(locale);
857 final String currentZoneName = zoneNames[i];
858 if (currentZoneName == null) {
859 continue;
860 }
861 final String zoneName = currentZoneName.toLowerCase(locale);
858862 if (!tzNames.containsKey(zoneName)) {
859863 tzNames.put(zoneName, tz);
860864 simpleQuote(sb.append('|'), zoneName);
901905
902906 /**
903907 * Construct a Strategy that parses a TimeZone
904 *
908 *
905909 * @param pattern The Pattern
906910 */
907911 ISO8601TimeZoneStrategy(final String pattern) {
935939
936940 /**
937941 * Factory method for ISO8601TimeZoneStrategies.
938 *
942 *
939943 * @param tokenLen a token indicating the length of the TimeZone String to be formatted.
940944 * @return a ISO8601TimeZoneStrategy that can format TimeZone String of length {@code tokenLen}. If no such
941945 * strategy exists, an IllegalArgumentException will be thrown.
1818
1919 import java.util.Calendar;
2020 import java.util.Objects;
21 import java.util.TimeZone;
2122
2223 /**
2324 * Custom time formatter that trades flexibility for performance. This formatter only supports the date patterns defined
7475 ISO8601_BASIC("yyyyMMdd'T'HHmmss,SSS", "yyyyMMdd'T'", 2, ' ', 0, ',', 1),
7576
7677 /**
78 * ISO8601_BASIC time format: {@code "yyyyMMdd'T'HHmmss.SSS"}.
79 */
80 ISO8601_BASIC_PERIOD("yyyyMMdd'T'HHmmss.SSS", "yyyyMMdd'T'", 2, ' ', 0, '.', 1),
81
82 /**
7783 * ISO8601 time format: {@code "yyyy-MM-dd'T'HH:mm:ss,SSS"}.
7884 */
79 ISO8601("yyyy-MM-dd'T'HH:mm:ss,SSS", "yyyy-MM-dd'T'", 2, ':', 1, ',', 1);
85 ISO8601("yyyy-MM-dd'T'HH:mm:ss,SSS", "yyyy-MM-dd'T'", 2, ':', 1, ',', 1),
86
87 /**
88 * ISO8601 time format: {@code "yyyy-MM-dd'T'HH:mm:ss.SSS"}.
89 */
90 ISO8601_PERIOD("yyyy-MM-dd'T'HH:mm:ss.SSS", "yyyy-MM-dd'T'", 2, ':', 1, '.', 1);
8091
8192 private final String pattern;
8293 private final String datePattern;
155166 * @return the {@code FastDateFormat} object for formatting the date part of the pattern or {@code null}
156167 */
157168 public FastDateFormat getFastDateFormat() {
158 return getDatePattern() == null ? null : FastDateFormat.getInstance(getDatePattern());
169 return getFastDateFormat(null);
170 }
171
172 /**
173 * Returns the {@code FastDateFormat} object for formatting the date part of the pattern or {@code null} if the
174 * pattern does not have a date part.
175 *
176 * @param tz the time zone to use
177 * @return the {@code FastDateFormat} object for formatting the date part of the pattern or {@code null}
178 */
179 public FastDateFormat getFastDateFormat(final TimeZone tz) {
180 return getDatePattern() == null ? null : FastDateFormat.getInstance(getDatePattern(), tz);
159181 }
160182 }
161183
162184 private final FixedFormat fixedFormat;
185 private final TimeZone timeZone;
163186 private final int length;
164187 private final FastDateFormat fastDateFormat; // may be null
165188 private final char timeSeparatorChar;
185208 *
186209 * @param fixedFormat the fixed format
187210 */
188 FixedDateFormat(final FixedFormat fixedFormat) {
211 FixedDateFormat(final FixedFormat fixedFormat, final TimeZone tz) {
189212 this.fixedFormat = Objects.requireNonNull(fixedFormat);
213 this.timeZone = Objects.requireNonNull(tz);
190214 this.timeSeparatorChar = fixedFormat.timeSeparatorChar;
191215 this.timeSeparatorLength = fixedFormat.timeSeparatorLength;
192216 this.millisSeparatorChar = fixedFormat.millisSeparatorChar;
193217 this.millisSeparatorLength = fixedFormat.millisSeparatorLength;
194218 this.length = fixedFormat.getLength();
195 this.fastDateFormat = fixedFormat.getFastDateFormat();
219 this.fastDateFormat = fixedFormat.getFastDateFormat(tz);
196220 }
197221
198222 public static FixedDateFormat createIfSupported(final String... options) {
199223 if (options == null || options.length == 0 || options[0] == null) {
200 return new FixedDateFormat(FixedFormat.DEFAULT);
201 }
224 return new FixedDateFormat(FixedFormat.DEFAULT, TimeZone.getDefault());
225 }
226 final TimeZone tz;
202227 if (options.length > 1) {
203 return null; // time zone not supported
204 }
228 if (options[1] != null){
229 tz = TimeZone.getTimeZone(options[1]);
230 } else {
231 tz = TimeZone.getDefault();
232 }
233 } else if (options.length > 2) {
234 return null;
235 } else {
236 tz = TimeZone.getDefault();
237 }
238
205239 final FixedFormat type = FixedFormat.lookup(options[0]);
206 return type == null ? null : new FixedDateFormat(type);
207 }
208
209 /**
210 * Returns a new {@code FixedDateFormat} object for the specified {@code FixedFormat} and a {@code null} TimeZone.
240 return type == null ? null : new FixedDateFormat(type, tz);
241 }
242
243 /**
244 * Returns a new {@code FixedDateFormat} object for the specified {@code FixedFormat} and a {@code TimeZone.getDefault()} TimeZone.
211245 *
212246 * @param format the format to use
213247 * @return a new {@code FixedDateFormat} object
214248 */
215249 public static FixedDateFormat create(final FixedFormat format) {
216 return new FixedDateFormat(format);
250 return new FixedDateFormat(format, TimeZone.getDefault());
251 }
252
253 /**
254 * Returns a new {@code FixedDateFormat} object for the specified {@code FixedFormat} and TimeZone.
255 *
256 * @param format the format to use
257 * @param tz the time zone to use
258 * @return a new {@code FixedDateFormat} object
259 */
260 public static FixedDateFormat create(final FixedFormat format, final TimeZone tz) {
261 return new FixedDateFormat(format, tz != null ? tz : TimeZone.getDefault());
217262 }
218263
219264 /**
223268 */
224269 public String getFormat() {
225270 return fixedFormat.getPattern();
271 }
272
273 /**
274 * Returns the time zone.
275 *
276 * @return the time zone
277 */
278
279 public TimeZone getTimeZone() {
280 return timeZone;
226281 }
227282
228283 // Profiling showed this method is important to log4j performance. Modify with care!
242297 midnightTomorrow = calcMidnightMillis(now, 1);
243298 }
244299
245 static long calcMidnightMillis(final long time, final int addDays) {
246 final Calendar cal = Calendar.getInstance();
300 private long calcMidnightMillis(final long time, final int addDays) {
301 final Calendar cal = Calendar.getInstance(timeZone);
247302 cal.setTimeInMillis(time);
248303 cal.set(Calendar.HOUR_OF_DAY, 0);
249304 cal.set(Calendar.MINUTE, 0);
241241 // Eliminate the usual boilerplate because
242242 // this inner static class is only used in a generic ConcurrentHashMap
243243 // which will not compare against other Object types
244 return Arrays.equals(keys, ((MultipartKey) obj).keys);
244 return obj != null && Arrays.equals(keys, ((MultipartKey) obj).keys);
245245 }
246246
247247 /**
1515 limitations under the License.
1616
1717 -->
18 <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
18 <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://logging.apache.org/log4j/2.0/config" elementFormDefault="qualified" attributeFormDefault="unqualified">
1919 <xs:element name="Configuration" type="ConfigurationType"/>
2020 <xs:complexType name="ConfigurationType">
2121 <xs:sequence>
1515 */
1616 package org.apache.logging.log4j;
1717
18 import java.util.Collections;
19 import java.util.HashMap;
20 import java.util.Map;
21
1822 import org.apache.logging.log4j.categories.PerformanceTests;
1923 import org.apache.logging.log4j.core.config.ConfigurationFactory;
24 import org.junit.After;
2025 import org.junit.AfterClass;
2126 import org.junit.BeforeClass;
2227 import org.junit.Test;
2328 import org.junit.experimental.categories.Category;
29 import org.slf4j.MDC;
2430
2531 /**
2632 *
5460 System.clearProperty(LOGBACK_CONF);
5561 }
5662
57 @Test
58 public void testPerformance() throws Exception {
59 logback(WARMUP);
60 log4j2(WARMUP);
61
62 System.out.println("Starting Log4j 2.0");
63 final long result3 = log4j2(COUNT);
64 System.out.println("Starting Logback");
65 final long result2 = logback(COUNT);
63 @After
64 public void after() {
65 ThreadContext.clearAll();
66 }
67
68 @Test
69 public void testPerformanceEmptyContext() throws Exception {
70 testPerformance(Collections.<String, String>emptyMap());
71 }
72
73 @Test
74 public void testPerformanceNonEmptyContext() throws Exception {
75 testPerformance(createNonEmptyContextData());
76 }
77
78 private Map<String, String> createNonEmptyContextData() {
79 final Map<String, String> context = new HashMap<>();
80 context.put("user0", "Apache");
81 context.put("user1", "Apache");
82 return context;
83 }
84
85 private static void putContextData(final Map<String, String> contextData) {
86 ThreadContext.putAll(contextData);
87 for (Map.Entry<String, String> entry : contextData.entrySet()) {
88 MDC.put(entry.getKey(), entry.getValue());
89 }
90 }
91
92 private void testPerformance(final Map<String, String> contextData) throws Exception {
93 putContextData(contextData);
94 Target.LOGBACK.timedLoop(logger, logbacklogger, WARMUP);
95 Target.LOG4J2.timedLoop(logger, logbacklogger, WARMUP);
96
97 System.out.println("Single-threaded Log4j 2.0, "
98 + (contextData.isEmpty() ? "EMPTY context" : "NON-EMPTY context"));
99
100 final long result3 = Target.LOG4J2.timedLoop(logger, logbacklogger, COUNT);
101 System.out.println("Single-threaded Logback, "
102 + (contextData.isEmpty() ? "EMPTY context" : "NON-EMPTY context"));
103
104 final long result2 = Target.LOGBACK.timedLoop(logger, logbacklogger, COUNT);
66105
67106 System.out.println("###############################################");
68107 System.out.println("Logback: " + result2);
71110 }
72111
73112 @Test
74 public void testThreads() throws Exception {
113 public void testThreadsEmptyContext() throws Exception {
114 testThreads(Collections.<String, String>emptyMap());
115 }
116
117 @Test
118 public void testThreadsNonEmptyContext() throws Exception {
119 testThreads(createNonEmptyContextData());
120 }
121
122 private void testThreads(final Map<String, String> contextData) throws Exception {
75123 System.out.println("Testing multithreading");
76124 final int threadedCount = COUNT; // THREADED_COUNT * threadCount < COUNT ? COUNT / threadCount : THREADED_COUNT;
77125 final int[] threadCounts = new int[] {1, 2, 5, 10, 20, 50};
78126 for (final int threadCount : threadCounts) {
79 System.out.println("Testing " + threadCount + " threads");
127 System.out.println("Testing " + threadCount + " threads, "
128 + (contextData.isEmpty() ? "EMPTY context" : "NON-EMPTY context"));
80129 final Worker[] workers = new Worker[threadCount];
81130 final long[] results = new long[threadCount];
82131 for (int i=0; i < threadCount; ++i) {
83 workers[i] = new Worker(true, threadedCount, results, i);
132 workers[i] = new Worker(Target.LOG4J2, threadedCount, results, i, contextData);
84133 }
85134 for (int i=0; i < threadCount; ++i) {
86135 workers[i].start();
93142 final long result3 = total / threadCount;
94143 total = 0;
95144 for (int i=0; i < threadCount; ++i) {
96 workers[i] = new Worker(false, threadedCount, results, i);
145 workers[i] = new Worker(Target.LOGBACK, threadedCount, results, i, contextData);
97146 }
98147 for (int i=0; i < threadCount; ++i) {
99148 workers[i].start();
108157 System.out.println("Log4j 2.0: " + result3 );
109158 System.out.println("###############################################");
110159 }
111
112 }
113
114 private long logback(final int loop) {
115 final Integer j = Integer.valueOf(2);
116 final long start = System.nanoTime();
117 for (int i = 0; i < loop; i++) {
118 logbacklogger.debug("SEE IF THIS IS LOGGED {}.", j);
119 }
120 return (System.nanoTime() - start) / loop;
121 }
122
123
124 private long log4j2(final int loop) {
125 final Integer j = Integer.valueOf(2);
126 final long start = System.nanoTime();
127 for (int i = 0; i < loop; i++) {
128 logger.debug("SEE IF THIS IS LOGGED {}.", j);
129 }
130 return (System.nanoTime() - start) / loop;
160 }
161
162 private enum Target {
163 LOGBACK {
164 long timedLoop(final Logger logger, final org.slf4j.Logger logbacklogger, final int loop) {
165 final Integer j = Integer.valueOf(2);
166 final long start = System.nanoTime();
167 for (int i = 0; i < loop; i++) {
168 logbacklogger.debug("SEE IF THIS IS LOGGED {}.", j);
169 }
170 return (System.nanoTime() - start) / loop;
171 }
172 },
173
174 LOG4J2 {
175 long timedLoop(final Logger logger, final org.slf4j.Logger logbacklogger, final int loop) {
176 final Integer j = Integer.valueOf(2);
177 final long start = System.nanoTime();
178 for (int i = 0; i < loop; i++) {
179 logger.debug("SEE IF THIS IS LOGGED {}.", j);
180 }
181 return (System.nanoTime() - start) / loop;
182 }
183 };
184 abstract long timedLoop(final Logger logger, final org.slf4j.Logger logbacklogger, final int loop);
131185 }
132186
133187 private class Worker extends Thread {
134188
135 private final boolean isLog4j;
189 private final Target target;
136190 private final int count;
137191 private final long[] results;
138192 private final int index;
139
140 public Worker(final boolean isLog4j, final int count, final long[] results, final int index) {
141 this.isLog4j = isLog4j;
193 private Map<String, String> contextData;
194
195 public Worker(final Target target, final int count, final long[] results, final int index,
196 final Map<String, String> contextData) {
197 this.target = target;
142198 this.count = count;
143199 this.results = results;
144200 this.index = index;
201 this.contextData = contextData;
145202 }
146203
147204 @Override
148205 public void run() {
149 results[index] = isLog4j ? log4j2(count) : logback(count);
206 putContextData(contextData);
207 results[index] = target.timedLoop(logger, logbacklogger, count);
150208 }
151209 }
152210
3939 * @param args
4040 */
4141 public static void main(final String[] args) {
42 final LoggerContext ctx = Configurator.initialize(FormatterLoggerManualExample.class.getName(),
43 "target/test-classes/log4j2-console.xml");
44 try {
42 try (final LoggerContext ctx = Configurator.initialize(FormatterLoggerManualExample.class.getName(),
43 "target/test-classes/log4j2-console.xml");) {
4544 final User user = new User();
4645 logger.debug("User %s with birthday %s", user.getName(), user.getBirthdayCalendar());
4746 logger.debug("User %1$s with birthday %2$tm %2$te, %2$tY", user.getName(), user.getBirthdayCalendar());
4847 logger.debug("Integer.MAX_VALUE = %,d", Integer.MAX_VALUE);
4948 logger.debug("Long.MAX_VALUE = %,d", Long.MAX_VALUE);
50 } finally {
51 Configurator.shutdown(ctx);
5249 }
5350
5451 }
1515 */
1616 package org.apache.logging.log4j;
1717
18 import java.io.File;
19
20 import org.apache.logging.log4j.core.LoggerContext;
1821 import org.apache.logging.log4j.core.config.Configurator;
19
20 import java.io.File;
2122
2223 /**
2324 *
2627
2728 private static final String CONFIG = "src/test/resources/rollover-test.xml";
2829
29
3030 public static void main(final String[] args) throws Exception {
3131 final File file = new File(CONFIG);
32 Configurator.initialize("LogTest", LogRolloverTest.class.getClassLoader(), file.toURI());
33 final Logger logger = LogManager.getLogger("TestLogger");
32 try (final LoggerContext ctx = Configurator.initialize("LogTest", LogRolloverTest.class.getClassLoader(),
33 file.toURI())) {
34 final Logger logger = LogManager.getLogger("TestLogger");
3435
35 for (long i=0; ; i+=1) {
36 logger.debug("Sequence: " + i);
37 Thread.sleep(250);
36 for (long i = 0;; i += 1) {
37 logger.debug("Sequence: " + i);
38 Thread.sleep(250);
39 }
3840 }
3941 }
4042 }
2424
2525 @Override
2626 protected ObjectMapper newObjectMapper() {
27 return new Log4jXmlObjectMapper();
27 return new Log4jXmlObjectMapper(true);
2828 }
2929
3030 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j;
17
18 /**
19 * <p>
20 * Utility class to access package protected methods in {@code ThreadContext}.
21 * </p>
22 *
23 * @see ThreadContext
24 * @since 2.7
25 */
26 public final class ThreadContextTestAccess {
27 private ThreadContextTestAccess() { // prevent instantiation
28 }
29
30 public static void init() {
31 ThreadContext.init();
32 }
33 }
3030 public class BasicConfigurationFactory extends ConfigurationFactory {
3131
3232 @Override
33 public Configuration getConfiguration(final String name, final URI configLocation) {
33 public Configuration getConfiguration(final LoggerContext loggerContext, final String name, final URI configLocation) {
3434 return new BasicConfiguration();
3535 }
3636
4040 }
4141
4242 @Override
43 public Configuration getConfiguration(final ConfigurationSource source) {
43 public Configuration getConfiguration(final LoggerContext loggerContext, final ConfigurationSource source) {
4444 return null;
4545 }
4646
4949 private static final String DEFAULT_LEVEL = "org.apache.logging.log4j.level";
5050
5151 public BasicConfiguration() {
52 super(ConfigurationSource.NULL_SOURCE);
52 super(null, ConfigurationSource.NULL_SOURCE);
5353
5454 final LoggerConfig root = getRootLogger();
5555 final String name = System.getProperty(DEFAULT_LEVEL);
3131
3232 @Test
3333 public void deadlockOnReconfigure() {
34 context.getContext().reconfigure();
34 context.getLoggerContext().reconfigure();
3535 }
3636 }
3434 * This code runs in a separate process, instrumented with the Google Allocation Instrumenter.
3535 */
3636 public static void main(final String[] args) throws Exception {
37 System.setProperty("log4j2.garbagefree.threadContextMap", "true");
38 System.setProperty("AsyncLogger.RingBufferSize", "128"); // minimum ringbuffer size
3739 System.setProperty("Log4jContextSelector", AsyncLoggerContextSelector.class.getName());
3840 GcFreeLoggingTestUtil.executeLogging("gcFreeLogging.xml", GcFreeAsynchronousLoggingTest.class);
3941 }
1515 */
1616 package org.apache.logging.log4j.core;
1717
18 import static org.junit.Assert.assertEquals;
19 import static org.junit.Assert.assertFalse;
20 import static org.junit.Assert.assertTrue;
21
1822 import java.io.File;
1923 import java.net.URL;
2024 import java.nio.charset.Charset;
2226 import java.util.List;
2327 import java.util.concurrent.atomic.AtomicBoolean;
2428
25 import org.apache.logging.log4j.*;
29 import org.apache.logging.log4j.LogManager;
30 import org.apache.logging.log4j.MarkerManager;
31 import org.apache.logging.log4j.ThreadContext;
2632 import org.apache.logging.log4j.core.util.Constants;
33 import org.apache.logging.log4j.util.Strings;
2734
2835 import com.google.monitoring.runtime.instrumentation.AllocationRecorder;
2936 import com.google.monitoring.runtime.instrumentation.Sampler;
30
31 import static org.junit.Assert.*;
3237
3338 /**
3439 * Utily methods for the GC-free logging tests.s.
5257
5358 // initialize LoggerContext etc.
5459 // This is not steady-state logging and will allocate objects.
60 ThreadContext.put("aKey", "value1");
61 ThreadContext.put("key2", "value2");
62
5563 final org.apache.logging.log4j.Logger logger = LogManager.getLogger(testClass.getName());
5664 logger.debug("debug not set");
5765 logger.fatal("This message is logged to the console");
5866 logger.error("Sample error message");
5967 logger.error("Test parameterized message {}", "param");
60 for (int i = 0; i < 128; i++) {
68 for (int i = 0; i < 256; i++) {
6169 logger.debug("ensure all ringbuffer slots have been used once"); // allocate MutableLogEvent.messageText
6270 }
71 ThreadContext.remove("aKey");
72 ThreadContext.remove("key2");
6373
6474 // BlockingWaitStrategy uses ReentrantLock which allocates Node objects. Ignore this.
6575 final String[] exclude = new String[] {
92102 AllocationRecorder.addSampler(sampler);
93103
94104 // now do some steady-state logging
105
106 ThreadContext.put("aKey", "value1");
107 ThreadContext.put("key2", "value2");
108
95109 final int ITERATIONS = 5;
96110 for (int i = 0; i < ITERATIONS; i++) {
97111 logger.error(myCharSeq);
100114 logger.error("Test parameterized message {}", "param");
101115 logger.error("Test parameterized message {}{}", "param", "param2");
102116 logger.error("Test parameterized message {}{}{}", "param", "param2", "abc");
117 ThreadContext.remove("aKey");
118 ThreadContext.put("aKey", "value1");
103119 }
104120 Thread.sleep(50);
105121 samplingEnabled.set(false); // reliably ignore all allocations from now on
127143 final String text = new String(Files.readAllBytes(tempFile.toPath()));
128144 final List<String> lines = Files.readAllLines(tempFile.toPath(), Charset.defaultCharset());
129145 final String className = cls.getSimpleName();
130 assertEquals(text, "FATAL o.a.l.l.c." + className + " [main] This message is logged to the console",
146 assertEquals(text, "FATAL o.a.l.l.c." + className + " [main] value1 {aKey=value1, key2=value2, prop1=value1, prop2=value2} This message is logged to the console",
131147 lines.get(0));
132148
133 final String LINESEP = System.getProperty("line.separator");
134149 for (int i = 1; i < lines.size(); i++) {
135150 final String line = lines.get(i);
136 assertFalse(i + ": " + line + LINESEP + text, line.contains("allocated") || line.contains("array"));
151 assertFalse(i + ": " + line + Strings.LINE_SEPARATOR + text, line.contains("allocated") || line.contains("array"));
137152 }
138153 }
139154
3333 * This code runs in a separate process, instrumented with the Google Allocation Instrumenter.
3434 */
3535 public static void main(final String[] args) throws Exception {
36 System.setProperty("log4j2.garbagefree.threadContextMap", "true");
3637 System.setProperty("AsyncLoggerConfig.RingBufferSize", "128"); // minimum ringbuffer size
3738 GcFreeLoggingTestUtil.executeLogging("gcFreeMixedSyncAsyncLogging.xml", GcFreeMixedSyncAyncLoggingTest.class);
3839 }
3333 * This code runs in a separate process, instrumented with the Google Allocation Instrumenter.
3434 */
3535 public static void main(final String[] args) throws Exception {
36 System.setProperty("log4j2.garbagefree.threadContextMap", "true");
3637 GcFreeLoggingTestUtil.executeLogging("gcFreeLogging.xml", GcFreeSynchronousLoggingTest.class);
3738 }
3839 }
1818 import java.util.List;
1919
2020 import org.apache.logging.log4j.core.appender.RollingFileAppender;
21 import org.apache.logging.log4j.core.util.Constants;
2221 import org.apache.logging.log4j.core.util.NetUtils;
2322 import org.apache.logging.log4j.junit.LoggerContextRule;
2423 import org.apache.logging.log4j.test.appender.ListAppender;
24 import org.apache.logging.log4j.util.Strings;
2525 import org.junit.Before;
2626 import org.junit.ClassRule;
2727 import org.junit.Test;
5454 testLogger.debug("Hello, {}", "World");
5555 final List<String> msgs = host.getMessages();
5656 assertThat(msgs, hasSize(1));
57 String expected = NetUtils.getLocalHostname() + Constants.LINE_SEPARATOR;
57 String expected = NetUtils.getLocalHostname() + Strings.LINE_SEPARATOR;
5858 assertThat(msgs.get(0), endsWith(expected));
5959 assertNotNull("No Host FileAppender file name", hostFile.getFileName());
6060 expected = "target/" + NetUtils.getLocalHostname() + ".log";
6868
6969 @Test
7070 public void testUpdateLoggersPropertyListeners() throws Exception {
71 final LoggerContext ctx = context.getContext();
71 final LoggerContext ctx = context.getLoggerContext();
7272 ctx.addPropertyChangeListener(new PropertyChangeListener() {
7373 @Override
7474 public void propertyChange(final PropertyChangeEvent evt) {
1818 import java.util.List;
1919
2020 import org.apache.logging.log4j.LogManager;
21 import org.apache.logging.log4j.core.util.Constants;
2221 import org.apache.logging.log4j.junit.LoggerContextRule;
2322 import org.apache.logging.log4j.test.appender.ListAppender;
23 import org.apache.logging.log4j.util.Strings;
2424 import org.junit.ClassRule;
2525 import org.junit.Test;
2626
5050 final String expect = String.format("[TRACE] TestMarkerPatternSelector ====== "
5151 + "o.a.l.l.c.PatternSelectorTest.testMarkerPatternSelector:43 Enter ======%n");
5252 assertEquals(expect, messages.get(0));
53 assertEquals("[INFO ] TestMarkerPatternSelector Hello World" + Constants.LINE_SEPARATOR, messages.get(1));
53 assertEquals("[INFO ] TestMarkerPatternSelector Hello World" + Strings.LINE_SEPARATOR, messages.get(1));
5454 app.clear();
5555 }
5656
6868 assertNotNull("No Messages", messages);
6969 assertTrue("Incorrect number of messages. Expected 4, Actual " + messages.size() + ": " + messages, messages.size() == 4);
7070 String expect = "[TRACE] TestScriptPatternSelector ====== " +
71 "o.a.l.l.c.PatternSelectorTest.testScriptPatternSelector:62 Enter ======" + Constants.LINE_SEPARATOR;
71 "o.a.l.l.c.PatternSelectorTest.testScriptPatternSelector:62 Enter ======" + Strings.LINE_SEPARATOR;
7272 assertEquals(expect, messages.get(0));
7373 expect = "[INFO ] TestScriptPatternSelector o.a.l.l.c.PatternSelectorTest.testScriptPatternSelector.63 " +
74 "Hello World" + Constants.LINE_SEPARATOR;
74 "Hello World" + Strings.LINE_SEPARATOR;
7575 assertEquals(expect, messages.get(1));
76 assertEquals("[INFO ] NoLocation No location information" + Constants.LINE_SEPARATOR, messages.get(2));
76 assertEquals("[INFO ] NoLocation No location information" + Strings.LINE_SEPARATOR, messages.get(2));
7777 app.clear();
7878 }
7979
9191 assertNotNull("No Messages", messages);
9292 assertTrue("Incorrect number of messages. Expected 4, Actual " + messages.size() + ": " + messages, messages.size() == 4);
9393 String expect = "[TRACE] TestJavaScriptPatternSelector ====== " +
94 "o.a.l.l.c.PatternSelectorTest.testJavaScriptPatternSelector:85 Enter ======" + Constants.LINE_SEPARATOR;
94 "o.a.l.l.c.PatternSelectorTest.testJavaScriptPatternSelector:85 Enter ======" + Strings.LINE_SEPARATOR;
9595 assertEquals(expect, messages.get(0));
9696 expect = "[INFO ] TestJavaScriptPatternSelector " +
97 "o.a.l.l.c.PatternSelectorTest.testJavaScriptPatternSelector.86 Hello World" + Constants.LINE_SEPARATOR;
97 "o.a.l.l.c.PatternSelectorTest.testJavaScriptPatternSelector.86 Hello World" + Strings.LINE_SEPARATOR;
9898 assertEquals(expect, messages.get(1));
99 assertEquals("[INFO ] JavascriptNoLocation No location information" + Constants.LINE_SEPARATOR, messages.get(2));
99 assertEquals("[INFO ] JavascriptNoLocation No location information" + Strings.LINE_SEPARATOR, messages.get(2));
100100 app.clear();
101101 }
102102 }
114114
115115 @Test
116116 public void mdc() {
117
118117 ThreadContext.put("TestYear", "2010");
119118 logger.debug("Debug message");
120119 ThreadContext.clearMap();
5454
5555 @Before
5656 public void before() throws Exception {
57 blockingAppender = (BlockingAppender) context.getAppender("Block");
58 asyncAppender = (AsyncAppender) context.getAppender("Async");
57 blockingAppender = context.getAppender("Block", BlockingAppender.class);
58 asyncAppender = context.getAppender("Async", AsyncAppender.class);
5959
6060 final Field field = AsyncAppender.class.getDeclaredField("asyncQueueFullPolicy");
6161 field.setAccessible(true);
7474 public void testRouter() throws Exception {
7575 final Logger logger = LogManager.getLogger(AsyncAppenderQueueFullPolicyTest.class);
7676
77 assertEquals(3, asyncAppender.getQueueCapacity());
77 assertEquals(4, asyncAppender.getQueueCapacity());
7878 logger.error("event 1 - gets taken off the queue");
7979 logger.warn("event 2");
8080 logger.info("event 3");
81 logger.info("event 4");
8182 while (asyncAppender.getQueueRemainingCapacity() == 0) {
8283 Thread.yield(); // wait until background thread takes one element off the queue
8384 }
84 logger.info("event 4 - now the queue is full");
85 logger.info("event 5 - now the queue is full");
8586 assertEquals("queue remaining capacity", 0, asyncAppender.getQueueRemainingCapacity());
8687 assertEquals("EventRouter invocations", 0, policy.queueFull.get());
8788
1616 package org.apache.logging.log4j.core.appender;
1717
1818 import java.util.List;
19 import java.util.concurrent.TimeUnit;
1920
2021 import org.apache.logging.log4j.LogManager;
2122 import org.apache.logging.log4j.Logger;
2425 import org.apache.logging.log4j.test.appender.ListAppender;
2526 import org.junit.After;
2627 import org.junit.Before;
27 import org.junit.ClassRule;
28 import org.junit.Rule;
2829 import org.junit.Test;
30 import org.junit.runner.RunWith;
31 import org.junit.runners.Parameterized;
2932
3033 import static org.junit.Assert.*;
3134
3235 /**
3336 *
3437 */
38 @RunWith(Parameterized.class)
3539 public class AsyncAppenderTest {
36 private static final String CONFIG = "log4j-asynch.xml";
3740
38 @ClassRule
39 public static LoggerContextRule context = new LoggerContextRule(CONFIG);
41 private static final long TIMEOUT_MILLIS = 2000;
42
43 @Parameterized.Parameters(name = "{0}")
44 public static Object[] data() {
45 return new String[]{
46 // default async config uses array blocking queue
47 "log4j-asynch.xml",
48 // override default blocking queue implementations
49 "BlockingQueueFactory-ArrayBlockingQueue.xml",
50 "BlockingQueueFactory-DisruptorBlockingQueue.xml",
51 "BlockingQueueFactory-JCToolsBlockingQueue.xml",
52 "BlockingQueueFactory-LinkedTransferQueue.xml"
53 };
54 }
55
56 public AsyncAppenderTest(final String configFileName) {
57 context = new LoggerContextRule(configFileName);
58 }
59
60 @Rule
61 public LoggerContextRule context;
4062
4163 private ListAppender listAppender;
4264
5577 final Logger logger = LogManager.getLogger(AsyncAppender.class);
5678 logger.error("This is a test");
5779 logger.warn("Hello world!");
58 Thread.sleep(100);
59 final List<String> list = listAppender.getMessages();
80 final long timeoutMillis = TIMEOUT_MILLIS;
81 final TimeUnit timeUnit = TimeUnit.MILLISECONDS;
82 final List<String> list = listAppender.getMessages(2, timeoutMillis, timeUnit);
6083 assertNotNull("No events generated", list);
61 assertTrue("Incorrect number of events. Expected 2, got " + list.size(), list.size() == 2);
84 assertTrue("Incorrect number of events after " + timeoutMillis + " " + timeUnit + ". Expected 2, got "
85 + list.size(), list.size() == 2);
6286 String msg = list.get(0);
6387 String expected = AsyncAppenderTest.class.getName() + " rewriteTest This is a test";
6488 assertTrue("Expected " + expected + ", Actual " + msg, expected.equals(msg));
7397 final Exception parent = new IllegalStateException("Test");
7498 final Throwable child = new LoggingException("This is a test", parent);
7599 logger.error("This is a test", child);
76 Thread.sleep(100);
77 final List<String> list = listAppender.getMessages();
100 final long timeoutMillis = TIMEOUT_MILLIS;
101 final TimeUnit timeUnit = TimeUnit.MILLISECONDS;
102 final List<String> list = listAppender.getMessages(1, timeoutMillis, timeUnit);
78103 assertNotNull("No events generated", list);
79 assertTrue("Incorrect number of events. Expected 1, got " + list.size(), list.size() == 1);
104 assertTrue("Incorrect number of events after " + timeoutMillis + " " + timeUnit + ". Expected 1, got "
105 + list.size(), list.size() == 1);
80106 final String msg = list.get(0);
81107 assertTrue("No parent exception", msg.contains("java.lang.IllegalStateException"));
82108 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.appender;
17
18 import java.io.IOException;
19
20 import org.apache.logging.log4j.LogManager;
21 import org.apache.logging.log4j.Logger;
22 import org.apache.logging.log4j.core.LoggerContext;
23 import org.apache.logging.log4j.core.config.Configurator;
24
25 /**
26 * Shows how to use ANSI escape codes to color messages. Each message is printed to the console in color, but the rest of the log entry
27 * (time stamp for example) is in the default color for that console.
28 * <p>
29 * Running from a Windows command line from the root of the project:
30 * </p>
31 * <pre>
32 * java -classpath log4j-core\target\test-classes;log4j-core\target\classes;log4j-api\target\classes;%HOME%\.m2\repository\org\fusesource\jansi\jansi\1.11\jansi-1.11.jar; org.apache.logging.log4j.core.appender.ConsoleAppenderAnsiMessagesMain log4j-core/target/test-classes/log4j2-console.xml
33 * </pre>
34 */
35 public class ConsoleAppenderAnsiMessagesMain {
36
37 private static final Logger LOG = LogManager.getLogger(ConsoleAppenderAnsiMessagesMain.class);
38
39 public static void main(final String[] args) {
40 final LoggerContext ctx = Configurator.initialize(ConsoleAppenderAnsiMessagesMain.class.getName(),
41 "target/test-classes/log4j2-console.xml");
42 try {
43 LOG.fatal("\u001b[1;35mFatal message.\u001b[0m");
44 LOG.error("\u001b[1;31mError message.\u001b[0m");
45 LOG.warn("\u001b[0;33mWarning message.\u001b[0m");
46 LOG.info("\u001b[0;32mInformation message.\u001b[0m");
47 LOG.debug("\u001b[0;36mDebug message.\u001b[0m");
48 LOG.trace("\u001b[0;30mTrace message.\u001b[0m");
49 LOG.error("\u001b[1;31mError message.\u001b[0m", new IOException("test"));
50 } finally {
51 Configurator.shutdown(ctx);
52 }
53 }
54
55 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.appender;
17
18 import java.io.IOException;
19
20 import org.apache.logging.log4j.LogManager;
21 import org.apache.logging.log4j.Logger;
22 import org.apache.logging.log4j.core.LoggerContext;
23 import org.apache.logging.log4j.core.config.Configurator;
24
25 /**
26 * Shows how to use ANSI escape codes to color messages. Each message is printed to the console in color, but the rest
27 * of the log entry (time stamp for example) is in the default color for that console.
28 * <p>
29 * Running from a Windows command line from the root of the project:
30 * </p>
31 *
32 * <pre>
33 * java -classpath log4j-core\target\test-classes;log4j-core\target\classes;log4j-api\target\classes;%HOME%\.m2\repository\org\fusesource\jansi\jansi\1.13\jansi-1.13.jar; org.apache.logging.log4j.core.appender.ConsoleAppenderAnsiMessagesMain log4j-core/target/test-classes/log4j2-console.xml
34 * </pre>
35 */
36 public class ConsoleAppenderAnsiMessagesMain {
37
38 private static final Logger LOG = LogManager.getLogger(ConsoleAppenderAnsiMessagesMain.class);
39
40 public static void main(final String[] args) {
41 try (final LoggerContext ctx = Configurator.initialize(ConsoleAppenderAnsiMessagesMain.class.getName(),
42 "target/test-classes/log4j2-console.xml")) {
43 LOG.fatal("\u001b[1;35mFatal message.\u001b[0m");
44 LOG.error("\u001b[1;31mError message.\u001b[0m");
45 LOG.warn("\u001b[0;33mWarning message.\u001b[0m");
46 LOG.info("\u001b[0;32mInformation message.\u001b[0m");
47 LOG.debug("\u001b[0;36mDebug message.\u001b[0m");
48 LOG.trace("\u001b[0;30mTrace message.\u001b[0m");
49 LOG.error("\u001b[1;31mError message.\u001b[0m", new IOException("test"));
50 }
51 }
52
53 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.appender;
17
18 import org.apache.logging.log4j.Level;
19 import org.apache.logging.log4j.LogManager;
20 import org.apache.logging.log4j.Logger;
21 import org.apache.logging.log4j.core.LoggerContext;
22 import org.apache.logging.log4j.core.config.Configurator;
23
24 /**
25 * Tests https://issues.apache.org/jira/browse/LOG4J2-180
26 * <p>
27 * Running from a Windows command line from the root of the project:
28 * </p>
29 * <pre>
30 * java -classpath log4j-core\target\test-classes;log4j-core\target\classes;log4j-api\target\classes;%HOME%\.m2\repository\org\fusesource\jansi\jansi\1.11\jansi-1.11.jar; org.apache.logging.log4j.core.appender.ConsoleAppenderAnsiStyleJira180Main log4j-core/target/test-classes/log4j2-180.xml
31 * </pre>
32 */
33 public class ConsoleAppenderAnsiStyleJira180Main {
34
35 private static final Logger LOG = LogManager.getLogger(ConsoleAppenderAnsiStyleJira180Main.class);
36
37 public static void main(final String[] args) {
38 // System.out.println(System.getProperty("java.class.path"));
39 final String config = args.length == 0 ? "target/test-classes/log4j2-180.xml" : args[0];
40 final LoggerContext ctx = Configurator.initialize(ConsoleAppenderAnsiMessagesMain.class.getName(), config);
41 try {
42 LOG.fatal("Fatal message.");
43 LOG.error("Error message.");
44 LOG.warn("Warning message.");
45 LOG.info("Information message.");
46 LOG.debug("Debug message.");
47 LOG.trace("Trace message.");
48 try {
49 throw new NullPointerException();
50 } catch (final Exception e) {
51 LOG.error("Error message.", e);
52 LOG.catching(Level.ERROR, e);
53 }
54 } finally {
55 Configurator.shutdown(ctx);
56 }
57 }
58
59 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.appender;
17
18 import org.apache.logging.log4j.Level;
19 import org.apache.logging.log4j.LogManager;
20 import org.apache.logging.log4j.Logger;
21 import org.apache.logging.log4j.core.LoggerContext;
22 import org.apache.logging.log4j.core.config.Configurator;
23
24 /**
25 * Tests https://issues.apache.org/jira/browse/LOG4J2-180
26 * <p>
27 * Running from a Windows command line from the root of the project:
28 * </p>
29 *
30 * <pre>
31 * java -classpath log4j-core\target\test-classes;log4j-core\target\classes;log4j-api\target\classes;%HOME%\.m2\repository\org\fusesource\jansi\jansi\1.13\jansi-1.13.jar; org.apache.logging.log4j.core.appender.ConsoleAppenderAnsiStyleJira180Main log4j-core/target/test-classes/log4j2-180.xml
32 * </pre>
33 */
34 public class ConsoleAppenderAnsiStyleJira180Main {
35
36 private static final Logger LOG = LogManager.getLogger(ConsoleAppenderAnsiStyleJira180Main.class);
37
38 public static void main(final String[] args) {
39 // System.out.println(System.getProperty("java.class.path"));
40 final String config = args.length == 0 ? "target/test-classes/log4j2-180.xml" : args[0];
41 try (final LoggerContext ctx = Configurator.initialize(ConsoleAppenderAnsiMessagesMain.class.getName(),
42 config)) {
43 LOG.fatal("Fatal message.");
44 LOG.error("Error message.");
45 LOG.warn("Warning message.");
46 LOG.info("Information message.");
47 LOG.debug("Debug message.");
48 LOG.trace("Trace message.");
49 try {
50 throw new NullPointerException();
51 } catch (final Exception e) {
52 LOG.error("Error message.", e);
53 LOG.catching(Level.ERROR, e);
54 }
55 }
56 }
57
58 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.appender;
17
18 import org.apache.logging.log4j.Level;
19 import org.apache.logging.log4j.LogManager;
20 import org.apache.logging.log4j.Logger;
21 import org.apache.logging.log4j.core.LoggerContext;
22 import org.apache.logging.log4j.core.config.Configurator;
23
24 /**
25 * Tests https://issues.apache.org/jira/browse/LOG4J2-272
26 * <p>
27 * Running from a Windows command line from the root of the project:
28 * </p>
29 * <pre>
30 * java -classpath log4j-core\target\test-classes;log4j-core\target\classes;log4j-api\target\classes;%HOME%\.m2\repository\org\fusesource\jansi\jansi\1.11\jansi-1.11.jar; org.apache.logging.log4j.core.appender.ConsoleAppenderAnsiStyleJira272Main log4j-core/target/test-classes/log4j2-272.xml
31 * </pre>
32 */
33 public class ConsoleAppenderAnsiStyleJira272Main {
34
35 private static final Logger LOG = LogManager.getLogger(ConsoleAppenderAnsiStyleJira272Main.class);
36
37 public static void main(final String[] args) {
38 // System.out.println(System.getProperty("java.class.path"));
39 final String config = args.length == 0 ? "target/test-classes/log4j2-272.xml" : args[0];
40 final LoggerContext ctx = Configurator.initialize(ConsoleAppenderAnsiMessagesMain.class.getName(), config);
41 try {
42 LOG.fatal("Fatal message.");
43 LOG.error("Error message.");
44 LOG.warn("Warning message.");
45 LOG.info("Information message.");
46 LOG.debug("Debug message.");
47 LOG.trace("Trace message.");
48 try {
49 throw new NullPointerException();
50 } catch (final Exception e) {
51 LOG.error("Error message.", e);
52 LOG.catching(Level.ERROR, e);
53 }
54 LOG.warn("this is ok \n And all \n this have only\t\tblack colour \n and here is colour again?");
55 LOG.info("Information message.");
56 } finally {
57 Configurator.shutdown(ctx);
58 }
59 }
60
61 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.appender;
17
18 import org.apache.logging.log4j.Level;
19 import org.apache.logging.log4j.LogManager;
20 import org.apache.logging.log4j.Logger;
21 import org.apache.logging.log4j.core.LoggerContext;
22 import org.apache.logging.log4j.core.config.Configurator;
23
24 /**
25 * Tests https://issues.apache.org/jira/browse/LOG4J2-272
26 * <p>
27 * Running from a Windows command line from the root of the project:
28 * </p>
29 * <pre>
30 * java -classpath log4j-core\target\test-classes;log4j-core\target\classes;log4j-api\target\classes;%HOME%\.m2\repository\org\fusesource\jansi\jansi\1.13\jansi-1.13.jar; org.apache.logging.log4j.core.appender.ConsoleAppenderAnsiStyleJira272Main log4j-core/target/test-classes/log4j2-272.xml
31 * </pre>
32 */
33 public class ConsoleAppenderAnsiStyleJira272Main {
34
35 private static final Logger LOG = LogManager.getLogger(ConsoleAppenderAnsiStyleJira272Main.class);
36
37 public static void main(final String[] args) {
38 // System.out.println(System.getProperty("java.class.path"));
39 final String config = args.length == 0 ? "target/test-classes/log4j2-272.xml" : args[0];
40 try (final LoggerContext ctx = Configurator.initialize(ConsoleAppenderAnsiMessagesMain.class.getName(), config)) {
41 LOG.fatal("Fatal message.");
42 LOG.error("Error message.");
43 LOG.warn("Warning message.");
44 LOG.info("Information message.");
45 LOG.debug("Debug message.");
46 LOG.trace("Trace message.");
47 try {
48 throw new NullPointerException();
49 } catch (final Exception e) {
50 LOG.error("Error message.", e);
51 LOG.catching(Level.ERROR, e);
52 }
53 LOG.warn("this is ok \n And all \n this have only\t\tblack colour \n and here is colour again?");
54 LOG.info("Information message.");
55 }
56 }
57
58 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.appender;
17
18 import org.apache.logging.log4j.Level;
19 import org.apache.logging.log4j.LogManager;
20 import org.apache.logging.log4j.Logger;
21 import org.apache.logging.log4j.core.LoggerContext;
22 import org.apache.logging.log4j.core.config.Configurator;
23
24 /**
25 * Tests https://issues.apache.org/jira/browse/LOG4J2-319
26 * <p>
27 * Running from a Windows command line from the root of the project:
28 * </p>
29 * <pre>
30 * java -classpath log4j-core\target\test-classes;log4j-core\target\classes;log4j-api\target\classes;%HOME%\.m2\repository\org\fusesource\jansi\jansi\1.11\jansi-1.11.jar; org.apache.logging.log4j.core.appender.ConsoleAppenderAnsiStyleJira319Main log4j-core/target/test-classes/log4j2-319.xml
31 * </pre>
32 */
33 public class ConsoleAppenderAnsiStyleJira319Main {
34
35 private static final Logger LOG = LogManager.getLogger(ConsoleAppenderAnsiStyleJira319Main.class);
36
37 public static void main(final String[] args) {
38 // System.out.println(System.getProperty("java.class.path"));
39 final String config = args.length == 0 ? "target/test-classes/log4j2-319.xml" : args[0];
40 final LoggerContext ctx = Configurator.initialize(ConsoleAppenderAnsiMessagesMain.class.getName(), config);
41 try {
42 LOG.fatal("Fatal message.");
43 LOG.error("Error message.");
44 LOG.warn("Warning message.");
45 LOG.info("Information message.");
46 LOG.debug("Debug message.");
47 LOG.trace("Trace message.");
48 try {
49 throw new NullPointerException();
50 } catch (final Exception e) {
51 LOG.error("Error message.", e);
52 LOG.catching(Level.ERROR, e);
53 }
54 LOG.warn("this is ok \n And all \n this have only\t\tblack colour \n and here is colour again?");
55 LOG.info("Information message.");
56 } finally {
57 Configurator.shutdown(ctx);
58 }
59 }
60
61 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.appender;
17
18 import org.apache.logging.log4j.Level;
19 import org.apache.logging.log4j.LogManager;
20 import org.apache.logging.log4j.Logger;
21 import org.apache.logging.log4j.core.LoggerContext;
22 import org.apache.logging.log4j.core.config.Configurator;
23
24 /**
25 * Tests https://issues.apache.org/jira/browse/LOG4J2-319
26 * <p>
27 * Running from a Windows command line from the root of the project:
28 * </p>
29 *
30 * <pre>
31 * java -classpath log4j-core\target\test-classes;log4j-core\target\classes;log4j-api\target\classes;%HOME%\.m2\repository\org\fusesource\jansi\jansi\1.13\jansi-1.13.jar; org.apache.logging.log4j.core.appender.ConsoleAppenderAnsiStyleJira319Main log4j-core/target/test-classes/log4j2-319.xml
32 * </pre>
33 */
34 public class ConsoleAppenderAnsiStyleJira319Main {
35
36 private static final Logger LOG = LogManager.getLogger(ConsoleAppenderAnsiStyleJira319Main.class);
37
38 public static void main(final String[] args) {
39 // System.out.println(System.getProperty("java.class.path"));
40 final String config = args.length == 0 ? "target/test-classes/log4j2-319.xml" : args[0];
41 try (final LoggerContext ctx = Configurator.initialize(ConsoleAppenderAnsiMessagesMain.class.getName(),
42 config)) {
43 LOG.fatal("Fatal message.");
44 LOG.error("Error message.");
45 LOG.warn("Warning message.");
46 LOG.info("Information message.");
47 LOG.debug("Debug message.");
48 LOG.trace("Trace message.");
49 try {
50 throw new NullPointerException();
51 } catch (final Exception e) {
52 LOG.error("Error message.", e);
53 LOG.catching(Level.ERROR, e);
54 }
55 LOG.warn("this is ok \n And all \n this have only\t\tblack colour \n and here is colour again?");
56 LOG.info("Information message.");
57 }
58 }
59
60 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.appender;
17
18 import java.io.IOException;
19
20 import org.apache.logging.log4j.LogManager;
21 import org.apache.logging.log4j.Logger;
22 import org.apache.logging.log4j.core.LoggerContext;
23 import org.apache.logging.log4j.core.config.Configurator;
24 import org.junit.Test;
25
26 /**
27 * Shows how to use ANSI escape codes to color messages. Each message is printed to the console in color, but the rest
28 * of the log entry (time stamp for example) is in the default color for that console.
29 * <p>
30 * Running from a Windows command line from the root of the project:
31 * </p>
32 *
33 * <pre>
34 * mvn -Dtest=org.apache.logging.log4j.core.appender.ConsoleAppenderAnsiStyleLayoutMain test
35 * </pre>
36 * or:
37 * <pre>
38 * java -classpath log4j-core\target\test-classes;log4j-core\target\classes;log4j-api\target\classes;%HOME%\.m2\repository\org\fusesource\jansi\jansi\1.11\jansi-1.11.jar; org.apache.logging.log4j.core.appender.ConsoleAppenderAnsiStyleLayoutMain log4j-core/target/test-classes/log4j2-console-style-ansi.xml
39 * </pre>
40 *
41 */
42 public class ConsoleAppenderAnsiStyleLayoutMain {
43
44 public static void main(final String[] args) {
45 new ConsoleAppenderAnsiStyleLayoutMain().test(args);
46 }
47
48 /**
49 * This is a @Test method to make it easy to run from a command line with {@code mvn -Dtest=FQCN test}
50 */
51 @Test
52 public void test() {
53 test(null);
54 }
55
56 public void test(final String[] args) {
57 // System.out.println(System.getProperty("java.class.path"));
58 final String config = args == null || args.length == 0 ? "target/test-classes/log4j2-console-style-ansi.xml"
59 : args[0];
60 final LoggerContext ctx = Configurator.initialize(ConsoleAppenderAnsiMessagesMain.class.getName(), config);
61 final Logger logger = LogManager.getLogger(ConsoleAppenderAnsiStyleLayoutMain.class);
62 try {
63 logger.fatal("Fatal message.");
64 logger.error("Error message.");
65 logger.warn("Warning message.");
66 logger.info("Information message.");
67 logger.debug("Debug message.");
68 logger.trace("Trace message.");
69 logger.error("Error message.", new IOException("test"));
70 } finally {
71 Configurator.shutdown(ctx);
72 }
73 }
74
75 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.appender;
17
18 import java.io.IOException;
19
20 import org.apache.logging.log4j.LogManager;
21 import org.apache.logging.log4j.Logger;
22 import org.apache.logging.log4j.core.LoggerContext;
23 import org.apache.logging.log4j.core.config.Configurator;
24 import org.junit.Test;
25
26 /**
27 * Shows how to use ANSI escape codes to color messages. Each message is printed to the console in color, but the rest
28 * of the log entry (time stamp for example) is in the default color for that console.
29 * <p>
30 * Running from a Windows command line from the root of the project:
31 * </p>
32 *
33 * <pre>
34 * mvn -Dtest=org.apache.logging.log4j.core.appender.ConsoleAppenderAnsiStyleLayoutMain test
35 * </pre>
36 * or:
37 * <pre>
38 * java -classpath log4j-core\target\test-classes;log4j-core\target\classes;log4j-api\target\classes;%HOME%\.m2\repository\org\fusesource\jansi\jansi\1.13\jansi-1.13.jar; org.apache.logging.log4j.core.appender.ConsoleAppenderAnsiStyleLayoutMain log4j-core/target/test-classes/log4j2-console-style-ansi.xml
39 * </pre>
40 *
41 */
42 public class ConsoleAppenderAnsiStyleLayoutMain {
43
44 public static void main(final String[] args) {
45 new ConsoleAppenderAnsiStyleLayoutMain().test(args);
46 }
47
48 /**
49 * This is a @Test method to make it easy to run from a command line with {@code mvn -Dtest=FQCN test}
50 */
51 @Test
52 public void test() {
53 test(null);
54 }
55
56 public void test(final String[] args) {
57 // System.out.println(System.getProperty("java.class.path"));
58 final String config = args == null || args.length == 0 ? "target/test-classes/log4j2-console-style-ansi.xml"
59 : args[0];
60 try (final LoggerContext ctx = Configurator.initialize(ConsoleAppenderAnsiMessagesMain.class.getName(), config)) {
61 final Logger logger = LogManager.getLogger(ConsoleAppenderAnsiStyleLayoutMain.class);
62 logger.fatal("Fatal message.");
63 logger.error("Error message.");
64 logger.warn("Warning message.");
65 logger.info("Information message.");
66 logger.debug("Debug message.");
67 logger.trace("Trace message.");
68 logger.error("Error message.", new IOException("test"));
69 }
70 }
71
72 }
2323 import org.apache.logging.log4j.core.config.Configurator;
2424
2525 /**
26 * Shows how to use ANSI escape codes to color messages. Each message is printed to the console in color, but the rest of the log entry
27 * (time stamp for example) is in the default color for that console.
26 * Shows how to use ANSI escape codes to color messages. Each message is printed to the console in color, but the rest
27 * of the log entry (time stamp for example) is in the default color for that console.
2828 */
2929 public class ConsoleAppenderAnsiStyleNameLayoutMain {
3030
3131 private static final Logger LOG = LogManager.getLogger(ConsoleAppenderAnsiStyleNameLayoutMain.class);
3232
3333 public static void main(final String[] args) {
34 final LoggerContext ctx = Configurator.initialize(ConsoleAppenderAnsiMessagesMain.class.getName(),
35 "target/test-classes/log4j2-console-style-name-ansi.xml");
36 try {
34 try (final LoggerContext ctx = Configurator.initialize(ConsoleAppenderAnsiMessagesMain.class.getName(),
35 "target/test-classes/log4j2-console-style-name-ansi.xml")) {
3736 LOG.fatal("Fatal message.");
3837 LOG.error("Error message.");
3938 LOG.warn("Warning message.");
4140 LOG.debug("Debug message.");
4241 LOG.trace("Trace message.");
4342 LOG.error("Error message.", new IOException("test"));
44 } finally {
45 Configurator.shutdown(ctx);
4643 }
4744 }
4845
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.appender;
17
18 import org.junit.Assert;
19 import org.junit.Test;
20
21 public class ConsoleAppenderBuilderTest {
22
23 /**
24 * Tests https://issues.apache.org/jira/browse/LOG4J2-1620
25 */
26 @Test
27 public void testDefaultImmediateFlush() {
28 Assert.assertTrue(ConsoleAppender.newBuilder().isImmediateFlush());
29 }
30 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.appender;
17
18 import java.io.IOException;
19
20 import org.apache.logging.log4j.LogManager;
21 import org.apache.logging.log4j.Logger;
22 import org.apache.logging.log4j.core.LoggerContext;
23 import org.apache.logging.log4j.core.config.Configurator;
24
25 /**
26 * Shows how to use ANSI escape codes to color messages. Each message is printed
27 * to the console in color, but the rest of the log entry (time stamp for
28 * example) is in the default color for that console.
29 * <p>
30 * Running from a Windows command line from the root of the project:
31 * </p>
32 *
33 * <pre>
34 * java -classpath log4j-core\target\test-classes;log4j-core\target\classes;log4j-api\target\classes;%HOME%\.m2\repository\org\fusesource\jansi\jansi\1.11\jansi-1.11.jar; org.apache.logging.log4j.core.appender.ConsoleAppenderNoAnsiStyleLayoutMain log4j-core/target/test-classes/log4j2-console-style-ansi.xml
35 * </pre>
36 */
37 public class ConsoleAppenderDefaultSuppressedThrowable {
38
39 private static final Logger LOG = LogManager.getLogger(ConsoleAppenderDefaultSuppressedThrowable.class);
40
41 public static void main(final String[] args) {
42 final String config = args.length == 0 ? "target/test-classes/log4j2-console-default-suppressed-throwable.xml"
43 : args[0];
44 test(args, config);
45 }
46
47 static void test(final String[] args, final String config) {
48 // System.out.println(System.getProperty("java.class.path"));
49 final LoggerContext ctx = Configurator.initialize(ConsoleAppenderDefaultSuppressedThrowable.class.getName(),
50 config);
51 try {
52 final IOException ioEx = new IOException("test suppressed");
53 ioEx.addSuppressed(new IOException("test suppressed 1", new IOException("test 1")));
54 final IOException ioEx2 = new IOException("test 2");
55 ioEx2.addSuppressed(new IOException("test 3"));
56 ioEx.addSuppressed(new IOException("test suppressed 2", ioEx2));
57 final IOException e = new IOException("test", ioEx);
58 LOG.error("Error message {}, suppressed?", "Hi", e);
59 System.out.println("printStackTrace");
60 e.printStackTrace();
61 } finally {
62 Configurator.shutdown(ctx);
63 }
64 }
65
66 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.appender;
17
18 import java.io.IOException;
19
20 import org.apache.logging.log4j.LogManager;
21 import org.apache.logging.log4j.Logger;
22 import org.apache.logging.log4j.core.LoggerContext;
23 import org.apache.logging.log4j.core.config.Configurator;
24
25 /**
26 * Shows how to use ANSI escape codes to color messages. Each message is printed
27 * to the console in color, but the rest of the log entry (time stamp for
28 * example) is in the default color for that console.
29 * <p>
30 * Running from a Windows command line from the root of the project:
31 * </p>
32 *
33 * <pre>
34 * java -classpath log4j-core\target\test-classes;log4j-core\target\classes;log4j-api\target\classes;%HOME%\.m2\repository\org\fusesource\jansi\jansi\1.13\jansi-1.13.jar; org.apache.logging.log4j.core.appender.ConsoleAppenderNoAnsiStyleLayoutMain log4j-core/target/test-classes/log4j2-console-style-ansi.xml
35 * </pre>
36 */
37 public class ConsoleAppenderDefaultSuppressedThrowable {
38
39 private static final Logger LOG = LogManager.getLogger(ConsoleAppenderDefaultSuppressedThrowable.class);
40
41 public static void main(final String[] args) {
42 final String config = args.length == 0 ? "target/test-classes/log4j2-console-default-suppressed-throwable.xml"
43 : args[0];
44 test(args, config);
45 }
46
47 static void test(final String[] args, final String config) {
48 // System.out.println(System.getProperty("java.class.path"));
49 try (final LoggerContext ctx = Configurator
50 .initialize(ConsoleAppenderDefaultSuppressedThrowable.class.getName(), config)) {
51 final IOException ioEx = new IOException("test suppressed");
52 ioEx.addSuppressed(new IOException("test suppressed 1", new IOException("test 1")));
53 final IOException ioEx2 = new IOException("test 2");
54 ioEx2.addSuppressed(new IOException("test 3"));
55 ioEx.addSuppressed(new IOException("test suppressed 2", ioEx2));
56 final IOException e = new IOException("test", ioEx);
57 LOG.error("Error message {}, suppressed?", "Hi", e);
58 System.out.println("printStackTrace");
59 e.printStackTrace();
60 }
61 }
62
63 }
2323 import org.apache.logging.log4j.core.config.Configurator;
2424
2525 /**
26 * Shows how to use ANSI escape codes to color messages. Each message is printed to the console in color, but the rest of the log entry
27 * (time stamp for example) is in the default color for that console.
26 * Shows how to use ANSI escape codes to color messages. Each message is printed to the console in color, but the rest
27 * of the log entry (time stamp for example) is in the default color for that console.
2828 */
2929 public class ConsoleAppenderHighlightLayoutDefaultMain {
3030
3131 private static final Logger LOG = LogManager.getLogger(ConsoleAppenderHighlightLayoutDefaultMain.class);
3232
3333 public static void main(final String[] args) {
34 final LoggerContext ctx = Configurator.initialize(ConsoleAppenderAnsiMessagesMain.class.getName(),
35 "target/test-classes/log4j2-console-highlight-default.xml");
36 try {
34 try (final LoggerContext ctx = Configurator.initialize(ConsoleAppenderAnsiMessagesMain.class.getName(),
35 "target/test-classes/log4j2-console-highlight-default.xml")) {
3736 LOG.fatal("Fatal message.");
3837 LOG.error("Error message.");
3938 LOG.warn("Warning message.");
4140 LOG.debug("Debug message.");
4241 LOG.trace("Trace message.");
4342 LOG.error("Error message.", new IOException("test"));
44 } finally {
45 Configurator.shutdown(ctx);
4643 }
4744 }
4845
2323 import org.apache.logging.log4j.core.config.Configurator;
2424
2525 /**
26 * Shows how to use ANSI escape codes to color messages. Each message is printed to the console in color, but the rest of the log entry
27 * (time stamp for example) is in the default color for that console.
26 * Shows how to use ANSI escape codes to color messages. Each message is printed to the console in color, but the rest
27 * of the log entry (time stamp for example) is in the default color for that console.
2828 */
2929 public class ConsoleAppenderHighlightLayoutLogbackMain {
3030
3131 private static final Logger LOG = LogManager.getLogger(ConsoleAppenderHighlightLayoutLogbackMain.class);
3232
3333 public static void main(final String[] args) {
34 final LoggerContext ctx = Configurator.initialize(ConsoleAppenderAnsiMessagesMain.class.getName(),
35 "target/test-classes/log4j2-console-highlight-logback.xml");
36 try {
34 try (final LoggerContext ctx = Configurator.initialize(ConsoleAppenderAnsiMessagesMain.class.getName(),
35 "target/test-classes/log4j2-console-highlight-logback.xml")) {
3736 LOG.fatal("Fatal message.");
3837 LOG.error("Error message.");
3938 LOG.warn("Warning message.");
4140 LOG.debug("Debug message.");
4241 LOG.trace("Trace message.");
4342 LOG.error("Error message.", new IOException("test"));
44 } finally {
45 Configurator.shutdown(ctx);
4643 }
4744 }
4845
2323 import org.apache.logging.log4j.core.config.Configurator;
2424
2525 /**
26 * Shows how to use ANSI escape codes to color messages. Each message is printed to the console in color, but the rest of the log entry
27 * (time stamp for example) is in the default color for that console.
26 * Shows how to use ANSI escape codes to color messages. Each message is printed to the console in color, but the rest
27 * of the log entry (time stamp for example) is in the default color for that console.
2828 */
2929 public class ConsoleAppenderHighlightLayoutMain {
3030
3131 private static final Logger LOG = LogManager.getLogger(ConsoleAppenderHighlightLayoutMain.class);
3232
3333 public static void main(final String[] args) {
34 final LoggerContext ctx = Configurator.initialize(ConsoleAppenderAnsiMessagesMain.class.getName(),
35 "target/test-classes/log4j2-console-highlight.xml");
36 try {
34 try (final LoggerContext ctx = Configurator.initialize(ConsoleAppenderAnsiMessagesMain.class.getName(),
35 "target/test-classes/log4j2-console-highlight.xml")) {
3736 LOG.fatal("Fatal message.");
3837 LOG.error("Error message.");
3938 LOG.warn("Warning message.");
4140 LOG.debug("Debug message.");
4241 LOG.trace("Trace message.");
4342 LOG.error("Error message.", new IOException("test"));
44 } finally {
45 Configurator.shutdown(ctx);
4643 }
4744 }
4845
1515 */
1616 package org.apache.logging.log4j.core.appender;
1717
18 import static org.fusesource.jansi.Ansi.*;
19 import static org.fusesource.jansi.Ansi.Color.*;
18 import static org.fusesource.jansi.Ansi.ansi;
19 import static org.fusesource.jansi.Ansi.Color.CYAN;
20 import static org.fusesource.jansi.Ansi.Color.RED;
21
22 import java.util.Map.Entry;
2023
2124 import org.apache.logging.log4j.LogManager;
2225 import org.apache.logging.log4j.Logger;
3841 * or, on Windows:
3942 *
4043 * <pre>
41 * java -classpath log4j-core\target\test-classes;log4j-core\target\classes;log4j-api\target\classes;%HOMEDRIVE%\%HOMEPATH%\.m2\repository\org\fusesource\jansi\jansi\1.11\jansi-1.11.jar; org.apache.logging.log4j.core.appender.ConsoleAppenderJAnsiMessageMain log4j-core/target/test-classes/log4j2-console-style-ansi.xml
44 * java -classpath log4j-core\target\test-classes;log4j-core\target\classes;log4j-api\target\classes;%USERPROFILE%\.m2\repository\org\fusesource\jansi\jansi\1.13\jansi-1.13.jar; org.apache.logging.log4j.core.appender.ConsoleAppenderJAnsiMessageMain log4j-core/src/test/resources/log4j2-console-msg-ansi.xml
4245 * </pre>
4346 *
4447 */
5861
5962 public void test(final String[] args) {
6063 // System.out.println(System.getProperty("java.class.path"));
61 final String config = args == null || args.length == 0 ? "target/test-classes/log4j2-console-style-ansi.xml"
64 final String config = args == null || args.length == 0 ? "target/test-classes/log4j2-console-msg-ansi.xml"
6265 : args[0];
63 final LoggerContext ctx = Configurator.initialize(ConsoleAppenderAnsiMessagesMain.class.getName(), config);
64 final Logger logger = LogManager.getLogger(ConsoleAppenderJAnsiMessageMain.class);
65 try {
66 try (final LoggerContext ctx = Configurator.initialize(ConsoleAppenderAnsiMessagesMain.class.getName(),
67 config)) {
68 final Logger logger = LogManager.getLogger(ConsoleAppenderJAnsiMessageMain.class);
6669 logger.info(ansi().fg(RED).a("Hello").fg(CYAN).a(" World").reset());
6770 // JAnsi format:
6871 // logger.info("@|red Hello|@ @|cyan World|@");
69 } finally {
70 Configurator.shutdown(ctx);
72 for (final Entry<Object, Object> entry : System.getProperties().entrySet()) {
73 logger.info("@|KeyStyle {}|@ = @|ValueStyle {}|@", entry.getKey(), entry.getValue());
74 }
7175 }
7276 }
7377
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.appender;
17
18 import java.nio.file.Files;
19 import java.nio.file.Paths;
20
21 import org.apache.logging.log4j.LogManager;
22 import org.apache.logging.log4j.Logger;
23 import org.apache.logging.log4j.core.LoggerContext;
24 import org.apache.logging.log4j.core.config.Configurator;
25 import org.junit.Test;
26
27 /**
28 * Shows how to use ANSI escape codes to color messages. Each message is printed to the console in color, but the rest
29 * of the log entry (time stamp for example) is in the default color for that console.
30 * <p>
31 * Running from a Windows command line from the root of the project:
32 * </p>
33 *
34 * <pre>
35 * mvn -Dtest=org.apache.logging.log4j.core.appender.ConsoleAppenderJAnsiXExceptionMain test
36 * </pre>
37 *
38 * or, on Windows:
39 *
40 * <pre>
41 * java -classpath log4j-core\target\test-classes;log4j-core\target\classes;log4j-api\target\classes;%USERPROFILE%\.m2\repository\org\fusesource\jansi\jansi\1.13\jansi-1.13.jar; org.apache.logging.log4j.core.appender.ConsoleAppenderJAnsiXExceptionMain log4j-core/src/test/resources/log4j2-console-xex-ansi.xml
42 * </pre>
43 *
44 */
45 public class ConsoleAppenderJAnsiXExceptionMain {
46
47 public static void main(final String[] args) {
48 new ConsoleAppenderJAnsiXExceptionMain().test(args);
49 }
50
51 /**
52 * This is a @Test method to make it easy to run from a command line with {@code mvn -Dtest=FQCN test}
53 */
54 @Test
55 public void test() {
56 test(null);
57 }
58
59 public void test(final String[] args) {
60 // System.out.println(System.getProperty("java.class.path"));
61 final String config = args == null || args.length == 0 ? "target/test-classes/log4j2-console-xex-ansi.xml"
62 : args[0];
63 final LoggerContext ctx = Configurator.initialize(ConsoleAppenderAnsiMessagesMain.class.getName(), config);
64 final Logger logger = LogManager.getLogger(ConsoleAppenderJAnsiXExceptionMain.class);
65 try {
66 Files.getFileStore(Paths.get("?BOGUS?"));
67 } catch (final Exception e) {
68 final IllegalArgumentException logE = new IllegalArgumentException("Bad argument foo", e);
69 logger.error("Gotcha!", logE);
70 } finally {
71 Configurator.shutdown(ctx);
72 }
73 }
74
75 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.appender;
17
18 import java.io.IOException;
19
20 import org.apache.logging.log4j.LogManager;
21 import org.apache.logging.log4j.Logger;
22 import org.apache.logging.log4j.core.LoggerContext;
23 import org.apache.logging.log4j.core.config.Configurator;
24
25 /**
26 * Shows how to use ANSI escape codes to color messages. Each message is printed
27 * to the console in color, but the rest of the log entry (time stamp for
28 * example) is in the default color for that console.
29 * <p>
30 * Running from a Windows command line from the root of the project:
31 * </p>
32 *
33 * <pre>
34 * java -classpath log4j-core\target\test-classes;log4j-core\target\classes;log4j-api\target\classes;%HOME%\.m2\repository\org\fusesource\jansi\jansi\1.11\jansi-1.11.jar; org.apache.logging.log4j.core.appender.ConsoleAppenderNoAnsiStyleLayoutMain log4j-core/target/test-classes/log4j2-console-style-ansi.xml
35 * </pre>
36 */
37 public class ConsoleAppenderNoAnsiStyleLayoutMain {
38
39 private static final Logger LOG = LogManager.getLogger(ConsoleAppenderNoAnsiStyleLayoutMain.class);
40
41 private static void logThrowableFromMethod() {
42 LOG.error("Error message.", new IOException("test"));
43 }
44
45 public static void main(final String[] args) {
46 final String config = args.length == 0 ? "target/test-classes/log4j2-console-style-no-ansi.xml" : args[0];
47 test(args, config);
48 }
49
50 static void test(final String[] args, final String config) {
51 // System.out.println(System.getProperty("java.class.path"));
52 final LoggerContext ctx = Configurator.initialize(ConsoleAppenderNoAnsiStyleLayoutMain.class.getName(), config);
53 try {
54 LOG.fatal("Fatal message.");
55 LOG.error("Error message.");
56 LOG.warn("Warning message.");
57 LOG.info("Information message.");
58 LOG.debug("Debug message.");
59 LOG.trace("Trace message.");
60 logThrowableFromMethod();
61 // This will log the stack trace as well:
62 final IOException ioException = new IOException("test");
63 LOG.error("Error message {}", "Hi", ioException);
64 final Throwable t = new IOException("test suppressed");
65 t.addSuppressed(new IOException("test suppressed 2", ioException));
66 LOG.error("Error message {}, suppressed?", "Hi", t);
67 LOG.error("Error message {}, suppressed?", "Hi", new IOException("test", t));
68 } finally {
69 Configurator.shutdown(ctx);
70 }
71 }
72
73 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.appender;
17
18 import java.io.IOException;
19
20 import org.apache.logging.log4j.LogManager;
21 import org.apache.logging.log4j.Logger;
22 import org.apache.logging.log4j.core.LoggerContext;
23 import org.apache.logging.log4j.core.config.Configurator;
24
25 /**
26 * Shows how to use ANSI escape codes to color messages. Each message is printed to the console in color, but the rest
27 * of the log entry (time stamp for example) is in the default color for that console.
28 * <p>
29 * Running from a Windows command line from the root of the project:
30 * </p>
31 *
32 * <pre>
33 * java -classpath log4j-core\target\test-classes;log4j-core\target\classes;log4j-api\target\classes;%HOME%\.m2\repository\org\fusesource\jansi\jansi\1.13\jansi-1.13.jar; org.apache.logging.log4j.core.appender.ConsoleAppenderNoAnsiStyleLayoutMain log4j-core/target/test-classes/log4j2-console-style-ansi.xml
34 * </pre>
35 */
36 public class ConsoleAppenderNoAnsiStyleLayoutMain {
37
38 private static final Logger LOG = LogManager.getLogger(ConsoleAppenderNoAnsiStyleLayoutMain.class);
39
40 private static void logThrowableFromMethod() {
41 LOG.error("Error message.", new IOException("test"));
42 }
43
44 public static void main(final String[] args) {
45 final String config = args.length == 0 ? "target/test-classes/log4j2-console-style-no-ansi.xml" : args[0];
46 test(args, config);
47 }
48
49 static void test(final String[] args, final String config) {
50 // System.out.println(System.getProperty("java.class.path"));
51 try (final LoggerContext ctx = Configurator.initialize(ConsoleAppenderNoAnsiStyleLayoutMain.class.getName(),
52 config)) {
53 LOG.fatal("Fatal message.");
54 LOG.error("Error message.");
55 LOG.warn("Warning message.");
56 LOG.info("Information message.");
57 LOG.debug("Debug message.");
58 LOG.trace("Trace message.");
59 logThrowableFromMethod();
60 // This will log the stack trace as well:
61 final IOException ioException = new IOException("test");
62 LOG.error("Error message {}", "Hi", ioException);
63 final Throwable t = new IOException("test suppressed");
64 t.addSuppressed(new IOException("test suppressed 2", ioException));
65 LOG.error("Error message {}, suppressed?", "Hi", t);
66 LOG.error("Error message {}, suppressed?", "Hi", new IOException("test", t));
67 }
68 }
69
70 }
2424 import org.apache.logging.log4j.core.appender.ConsoleAppender.Target;
2525 import org.apache.logging.log4j.core.impl.Log4jLogEvent;
2626 import org.apache.logging.log4j.core.layout.PatternLayout;
27 import org.apache.logging.log4j.core.util.Constants;
2827 import org.apache.logging.log4j.message.SimpleMessage;
28 import org.apache.logging.log4j.util.Strings;
2929 import org.easymock.EasyMockSupport;
3030 import org.junit.AfterClass;
3131 import org.junit.Assert;
9696
9797 mocks.replayAll();
9898 systemSetter.systemSet(psMock);
99 final Layout<String> layout = PatternLayout.createLayout(null, null, null, null, null, false, false, null, null);
100 final ConsoleAppender app = ConsoleAppender.createAppender(layout, null, targetName, "Console", false, false,
101 false);
99 final Layout<String> layout = PatternLayout.newBuilder().withAlwaysWriteExceptions(true).build();
100 final ConsoleAppender app = ConsoleAppender.newBuilder().withLayout(layout).setTarget(targetName)
101 .withName("Console").withIgnoreExceptions(false).build();
102102 app.start();
103103 assertTrue("Appender did not start", app.isStarted());
104104
130130
131131 private void testFollowSystemPrintStream(final PrintStream ps, final Target target, final SystemSetter systemSetter) {
132132 final ConsoleAppender app = ConsoleAppender.newBuilder().setTarget(target).setFollow(true)
133 .setIgnoreExceptions(false).build();
133 .withIgnoreExceptions(false).build();
134134 Assert.assertEquals(target, app.getTarget());
135135 app.start();
136136 try {
150150 }
151151 final String msg = baos.toString();
152152 assertNotNull("No message", msg);
153 assertTrue("Incorrect message: \"" + msg + "\"", msg.endsWith("Test" + Constants.LINE_SEPARATOR));
153 assertTrue("Incorrect message: \"" + msg + "\"", msg.endsWith("Test" + Strings.LINE_SEPARATOR));
154154 } finally {
155155 app.stop();
156156 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16
17 package org.apache.logging.log4j.core.appender;
18
19 import java.io.File;
20 import java.io.IOException;
21 import java.nio.charset.Charset;
22 import java.util.List;
23
24 import org.apache.logging.log4j.core.Logger;
25 import org.apache.logging.log4j.core.LoggerContext;
26 import org.apache.logging.log4j.junit.LoggerContextRule;
27 import org.junit.Assert;
28 import org.junit.Rule;
29 import org.junit.Test;
30 import org.junit.rules.RuleChain;
31
32 import com.google.common.io.Files;
33
34 /**
35 * Tests https://issues.apache.org/jira/browse/LOG4J2-1502
36 */
37 public class CsvJsonParameterLayoutFileAppenderTest {
38
39 private static final String FILE_PATH = "target/CsvJsonParameterLayoutFileAppenderTest.log";
40
41 private static final LoggerContextRule loggerContextRule = new LoggerContextRule("log4j-cvs-json-parameter.xml");
42
43 @Rule
44 public RuleChain rule = loggerContextRule.withCleanFilesRule(FILE_PATH);
45
46 public void testNoNulCharacters(final String message, final String expected) throws IOException {
47 @SuppressWarnings("resource")
48 final LoggerContext loggerContext = loggerContextRule.getLoggerContext();
49 final Logger logger = loggerContext.getLogger("com.example");
50 logger.error("log:", message);
51 loggerContext.stop();
52 final File file = new File(FILE_PATH);
53 final byte[] contents = Files.toByteArray(file);
54 int count0s = 0;
55 final StringBuilder sb = new StringBuilder();
56 for (int i = 0; i < contents.length; i++) {
57 final byte b = contents[i];
58 if (b == 0) {
59 sb.append(i);
60 sb.append(", ");
61 count0s++;
62 }
63 }
64 Assert.assertEquals("File contains " + count0s + " 0x00 byte at indices " + sb, 0, count0s);
65 final List<String> readLines = Files.readLines(file, Charset.defaultCharset());
66 final String actual = readLines.get(0);
67 // Assert.assertTrue(actual, actual.contains(message));
68 Assert.assertEquals(actual, expected, actual);
69 Assert.assertEquals(1, readLines.size());
70 }
71
72 @Test
73 public void testNoNulCharactersDoubleQuote() throws IOException {
74 // TODO This does not seem right but there is no NULs. Check Apache Commons CSV.
75 testNoNulCharacters("\"", "\"\"\"\"");
76 }
77
78 @Test
79 public void testNoNulCharactersJson() throws IOException {
80 testNoNulCharacters("{\"id\":10,\"name\":\"Alice\"}", "\"{\"\"id\"\":10,\"\"name\"\":\"\"Alice\"\"}\"");
81 }
82
83 @Test
84 public void testNoNulCharactersOneChar() throws IOException {
85 testNoNulCharacters("A", "A");
86 }
87
88 @Test
89 public void testNoNulCharactersOpenCurly() throws IOException {
90 // TODO Why is the char quoted? Check Apache Commons CSV.
91 testNoNulCharacters("{", "\"{\"");
92 }
93
94 @Test
95 public void testNoNulCharactersOpenParen() throws IOException {
96 // TODO Why is the char quoted? Check Apache Commons CSV.
97 testNoNulCharacters("(", "\"(\"");
98 }
99
100 @Test
101 public void testNoNulCharactersOpenSquare() throws IOException {
102 // TODO Why is the char quoted? Check Apache Commons CSV.
103 testNoNulCharacters("[", "\"[\"");
104 }
105
106 @Test
107 public void testNoNulCharactersThreeChars() throws IOException {
108 testNoNulCharacters("ABC", "ABC");
109 }
110
111 @Test
112 public void testNoNulCharactersXml() throws IOException {
113 testNoNulCharacters("<test attr1='val1' attr2=\"value2\">X</test>",
114 "\"<test attr1='val1' attr2=\"\"value2\"\">X</test>\"");
115 }
116 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.appender;
17
18 import org.junit.Assert;
19 import org.junit.Test;
20
21 public class FileAppenderBuilderTest {
22
23 /**
24 * Tests https://issues.apache.org/jira/browse/LOG4J2-1620
25 */
26 @Test
27 public void testDefaultImmediateFlush() {
28 Assert.assertTrue(FileAppender.newBuilder().isImmediateFlush());
29 }
30 }
2222 import java.io.File;
2323 import java.io.FileInputStream;
2424 import java.io.InputStreamReader;
25 import java.nio.file.Files;
26 import java.nio.file.Path;
27 import java.nio.file.Paths;
2528 import java.util.concurrent.ExecutorService;
2629 import java.util.concurrent.Executors;
2730 import java.util.concurrent.TimeUnit;
3336 import org.apache.logging.log4j.core.LogEvent;
3437 import org.apache.logging.log4j.core.impl.Log4jLogEvent;
3538 import org.apache.logging.log4j.core.layout.PatternLayout;
39 import org.apache.logging.log4j.core.util.Throwables;
3640 import org.apache.logging.log4j.junit.CleanFiles;
3741 import org.apache.logging.log4j.message.SimpleMessage;
3842 import org.apache.logging.log4j.util.Strings;
3943 import org.junit.AfterClass;
44 import org.junit.Assert;
4045 import org.junit.Ignore;
4146 import org.junit.Rule;
4247 import org.junit.Test;
48 import org.junit.runner.RunWith;
49 import org.junit.runners.Parameterized;
50 import org.junit.runners.Parameterized.Parameters;
4351
4452 /**
45 *
53 * Tests {@link FileAppender}.
4654 */
55 @RunWith(Parameterized.class)
4756 public class FileAppenderTest {
4857
49 private static final String FILENAME = "target/fileAppenderTest.log";
58 @Parameters(name = "createOnDemand = {0}")
59 public static Boolean[] getParameters() {
60 return new Boolean[] { false, true };
61 }
62
63 private static final String FILE_NAME = "target/fileAppenderTest.log";
64 private static final Path PATH = Paths.get(FILE_NAME);
5065 private static final int THREADS = 2;
5166
67 public FileAppenderTest(final boolean createOnDemand) {
68 super();
69 this.createOnDemand = createOnDemand;
70 }
71
72 private final boolean createOnDemand;
73 private final int threadCount = THREADS;
74
5275 @Rule
53 public CleanFiles files = new CleanFiles(FILENAME);
76 public CleanFiles files = new CleanFiles(PATH);
5477
5578 @AfterClass
5679 public static void cleanupClass() {
57 assertTrue("Manager for " + FILENAME + " not removed", !AbstractManager.hasManager(FILENAME));
80 assertTrue("Manager for " + FILE_NAME + " not removed", !AbstractManager.hasManager(FILE_NAME));
5881 }
5982
6083 @Test
6184 public void testAppender() throws Exception {
62 writer(false, 1, "test");
63 verifyFile(1);
85 final int logEventCount = 1;
86 writer(false, logEventCount, "test", createOnDemand, false);
87 verifyFile(logEventCount);
88 }
89
90 @Test
91 public void testLazyCreate() throws Exception {
92 final Layout<String> layout = createPatternLayout();
93 // @formatter:off
94 final FileAppender appender = FileAppender.newBuilder()
95 .withFileName(FILE_NAME)
96 .withName("test")
97 .withImmediateFlush(false)
98 .withIgnoreExceptions(false)
99 .withBufferedIo(false)
100 .withBufferSize(1)
101 .withLayout(layout)
102 .withCreateOnDemand(createOnDemand)
103 .build();
104 // @formatter:on
105 Assert.assertEquals(createOnDemand, appender.getManager().isCreateOnDemand());
106 try {
107 Assert.assertNotEquals(createOnDemand, Files.exists(PATH));
108 appender.start();
109 Assert.assertNotEquals(createOnDemand, Files.exists(PATH));
110 } finally {
111 appender.stop();
112 }
113 Assert.assertNotEquals(createOnDemand, Files.exists(PATH));
114 }
115
116 private static PatternLayout createPatternLayout() {
117 return PatternLayout.newBuilder().withPattern(PatternLayout.SIMPLE_CONVERSION_PATTERN)
118 .build();
64119 }
65120
66121 @Test
67122 public void testSmallestBufferSize() throws Exception {
68 final Layout<String> layout = PatternLayout.newBuilder().withPattern(PatternLayout.SIMPLE_CONVERSION_PATTERN).build();
69 final String bufferSizeStr = "1";
70 final FileAppender appender = FileAppender.createAppender(FILENAME, "true", "false", "test", "false", "false",
71 "false", bufferSizeStr, layout, null, "false", null, null);
72 appender.start();
73 final File file = new File(FILENAME);
74 assertTrue("Appender did not start", appender.isStarted());
75 long curLen = file.length();
76 long prevLen = curLen;
77 assertTrue("File length: " + curLen, curLen == 0);
78 for (int i = 0; i < 100; ++i) {
79 final LogEvent event = Log4jLogEvent.newBuilder().setLoggerName("TestLogger") //
80 .setLoggerFqcn(FileAppenderTest.class.getName()).setLevel(Level.INFO) //
81 .setMessage(new SimpleMessage("Test")).setThreadName(this.getClass().getSimpleName()) //
82 .setTimeMillis(System.currentTimeMillis()).build();
83 try {
84 appender.append(event);
85 curLen = file.length();
86 assertTrue("File length: " + curLen, curLen > prevLen);
87 Thread.sleep(25); // Give up control long enough for another thread/process to occasionally do
88 // something.
89 } catch (final Exception ex) {
90 throw ex;
91 }
92 prevLen = curLen;
93 }
94 appender.stop();
123 final Layout<String> layout = createPatternLayout();
124 // @formatter:off
125 final FileAppender appender = FileAppender.newBuilder()
126 .withFileName(FILE_NAME)
127 .withName("test")
128 .withImmediateFlush(false)
129 .withIgnoreExceptions(false)
130 .withBufferedIo(false)
131 .withBufferSize(1)
132 .withLayout(layout)
133 .withCreateOnDemand(createOnDemand)
134 .build();
135 // @formatter:on
136 try {
137 appender.start();
138 final File file = new File(FILE_NAME);
139 assertTrue("Appender did not start", appender.isStarted());
140 Assert.assertNotEquals(createOnDemand, Files.exists(PATH));
141 long curLen = file.length();
142 long prevLen = curLen;
143 assertTrue("File length: " + curLen, curLen == 0);
144 for (int i = 0; i < 100; ++i) {
145 final LogEvent event = Log4jLogEvent.newBuilder().setLoggerName("TestLogger") //
146 .setLoggerFqcn(FileAppenderTest.class.getName()).setLevel(Level.INFO) //
147 .setMessage(new SimpleMessage("Test")).setThreadName(this.getClass().getSimpleName()) //
148 .setTimeMillis(System.currentTimeMillis()).build();
149 try {
150 appender.append(event);
151 curLen = file.length();
152 assertTrue("File length: " + curLen, curLen > prevLen);
153 // Give up control long enough for another thread/process to occasionally do something.
154 Thread.sleep(25);
155 } catch (final Exception ex) {
156 throw ex;
157 }
158 prevLen = curLen;
159 }
160 } finally {
161 appender.stop();
162 }
95163 assertFalse("Appender did not stop", appender.isStarted());
96164 }
97165
98166 @Test
99167 public void testLockingAppender() throws Exception {
100 writer(true, 1, "test");
101 verifyFile(1);
102 }
103
104 @Test
105 public void testMultipleAppenders() throws Exception {
106 final ExecutorService pool = Executors.newFixedThreadPool(THREADS);
107 final Exception[] error = new Exception[1];
108 final int count = 100;
109 final Runnable runnable = new FileWriterRunnable(false, count, error);
110 for (int i = 0; i < THREADS; ++i) {
111 pool.execute(runnable);
112 }
113 pool.shutdown();
114 pool.awaitTermination(10, TimeUnit.SECONDS);
115 if (error[0] != null) {
116 throw error[0];
117 }
118 verifyFile(THREADS * count);
119 }
120
121 @Test
122 public void testMultipleLockedAppenders() throws Exception {
123 final ExecutorService pool = Executors.newFixedThreadPool(THREADS);
124 final Exception[] error = new Exception[1];
125 final int count = 100;
126 final Runnable runnable = new FileWriterRunnable(true, count, error);
127 for (int i = 0; i < THREADS; ++i) {
128 pool.execute(runnable);
129 }
130 pool.shutdown();
131 pool.awaitTermination(10, TimeUnit.SECONDS);
132 if (error[0] != null) {
133 throw error[0];
134 }
135 verifyFile(THREADS * count);
168 final int logEventCount = 1;
169 writer(true, logEventCount, "test", createOnDemand, false);
170 verifyFile(logEventCount);
171 }
172
173 @Test
174 public void testMultipleAppenderThreads() throws Exception {
175 testMultipleLockingAppenderThreads(false, threadCount);
176 }
177
178 private void testMultipleLockingAppenderThreads(final boolean lock, final int threadCount)
179 throws InterruptedException, Exception {
180 final ExecutorService threadPool = Executors.newFixedThreadPool(threadCount);
181 final Exception[] exceptionRef = new Exception[1];
182 final int logEventCount = 100;
183 final Runnable runnable = new FileWriterRunnable(lock, logEventCount, exceptionRef);
184 for (int i = 0; i < threadCount; ++i) {
185 threadPool.execute(runnable);
186 }
187 threadPool.shutdown();
188 Assert.assertTrue("The thread pool has not shutdown: " + threadPool,
189 threadPool.awaitTermination(10, TimeUnit.SECONDS));
190 if (exceptionRef[0] != null) {
191 throw exceptionRef[0];
192 }
193 verifyFile(threadCount * logEventCount);
194 }
195
196 @Test
197 public void testMultipleLockingAppenders() throws Exception {
198 testMultipleLockingAppenderThreads(true, threadCount);
136199 }
137200
138201 @Test
139202 @Ignore
140203 public void testMultipleVMs() throws Exception {
141204 final String classPath = System.getProperty("java.class.path");
142 final Integer count = 10;
143 final int processeCount = 3;
144 final Process[] processes = new Process[processeCount];
145 final ProcessBuilder[] builders = new ProcessBuilder[processeCount];
146 for (int index = 0; index < processeCount; ++index) {
205 final Integer logEventCount = 10;
206 final int processCount = 3;
207 final Process[] processes = new Process[processCount];
208 final ProcessBuilder[] builders = new ProcessBuilder[processCount];
209 for (int index = 0; index < processCount; ++index) {
147210 builders[index] = new ProcessBuilder("java", "-cp", classPath, ProcessTest.class.getName(),
148 "Process " + index, count.toString(), "true");
149 }
150 for (int index = 0; index < processeCount; ++index) {
211 "Process " + index, logEventCount.toString(), "true", Boolean.toString(createOnDemand));
212 }
213 for (int index = 0; index < processCount; ++index) {
151214 processes[index] = builders[index].start();
152215 }
153 for (int index = 0; index < processeCount; ++index) {
216 for (int index = 0; index < processCount; ++index) {
154217 final Process process = processes[index];
155218 // System.out.println("Process " + index + " exited with " + p.waitFor());
156219 try (final BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
161224 }
162225 process.destroy();
163226 }
164 verifyFile(count * processeCount);
165 }
166
167 private static void writer(final boolean lock, final int count, final String name) throws Exception {
168 final Layout<String> layout = PatternLayout.newBuilder().withPattern(PatternLayout.SIMPLE_CONVERSION_PATTERN).build();
169 final FileAppender app = FileAppender.createAppender(FILENAME, "true", Boolean.toString(lock), "test", "false",
170 "false", "false", null, layout, null, "false", null, null);
171 app.start();
172 assertTrue("Appender did not start", app.isStarted());
173 for (int i = 0; i < count; ++i) {
174 final LogEvent event = Log4jLogEvent.newBuilder().setLoggerName("TestLogger")
175 .setLoggerFqcn(FileAppenderTest.class.getName()).setLevel(Level.INFO)
176 .setMessage(new SimpleMessage("Test")).setThreadName(name).setTimeMillis(System.currentTimeMillis())
177 .build();
178 try {
179 app.append(event);
180 Thread.sleep(25); // Give up control long enough for another thread/process to occasionally do
181 // something.
182 } catch (final Exception ex) {
183 throw ex;
184 }
185 }
186 app.stop();
187 assertFalse("Appender did not stop", app.isStarted());
227 verifyFile(logEventCount * processCount);
228 }
229
230 private static void writer(final boolean locking, final int logEventCount, final String name, final boolean createOnDemand,
231 final boolean concurrent) throws Exception {
232 final Layout<String> layout = createPatternLayout();
233 // @formatter:off
234 final FileAppender appender = FileAppender.newBuilder()
235 .withFileName(FILE_NAME)
236 .withName("test")
237 .withImmediateFlush(false)
238 .withIgnoreExceptions(false)
239 .withLocking(locking)
240 .withBufferedIo(false)
241 .withLayout(layout)
242 .withCreateOnDemand(createOnDemand)
243 .build();
244 // @formatter:on
245 Assert.assertEquals(createOnDemand, appender.getManager().isCreateOnDemand());
246 try {
247 appender.start();
248 assertTrue("Appender did not start", appender.isStarted());
249 final boolean exists = Files.exists(PATH);
250 final String msg = String.format("concurrent = %s, createOnDemand = %s, file exists = %s", concurrent, createOnDemand,
251 exists);
252 // If concurrent the file might have been created (or not.)
253 // Can't really test createOnDemand && concurrent.
254 final boolean expectFileCreated = !createOnDemand;
255 if (concurrent && expectFileCreated) {
256 Assert.assertTrue(msg, exists);
257 } else if (expectFileCreated) {
258 Assert.assertNotEquals(msg, createOnDemand, exists);
259 }
260 for (int i = 0; i < logEventCount; ++i) {
261 final LogEvent logEvent = Log4jLogEvent.newBuilder().setLoggerName("TestLogger")
262 .setLoggerFqcn(FileAppenderTest.class.getName()).setLevel(Level.INFO)
263 .setMessage(new SimpleMessage("Test")).setThreadName(name)
264 .setTimeMillis(System.currentTimeMillis()).build();
265 try {
266 appender.append(logEvent);
267 Thread.sleep(25); // Give up control long enough for another thread/process to occasionally do
268 // something.
269 } catch (final Exception ex) {
270 throw ex;
271 }
272 }
273 } finally {
274 appender.stop();
275 }
276 assertFalse("Appender did not stop", appender.isStarted());
188277 }
189278
190279 private void verifyFile(final int count) throws Exception {
191280 // String expected = "[\\w]* \\[\\s*\\] INFO TestLogger - Test$";
192281 final String expected = "^\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2},\\d{3} \\[[^\\]]*\\] INFO TestLogger - Test";
193282 final Pattern pattern = Pattern.compile(expected);
194 final FileInputStream fis = new FileInputStream(FILENAME);
195 final BufferedReader is = new BufferedReader(new InputStreamReader(fis));
196 int counter = 0;
197 String str = Strings.EMPTY;
198 while (is.ready()) {
199 str = is.readLine();
200 // System.out.println(str);
201 ++counter;
202 final Matcher matcher = pattern.matcher(str);
203 assertTrue("Bad data: " + str, matcher.matches());
204 }
205 fis.close();
206 assertTrue("Incorrect count: was " + counter + " should be " + count, count == counter);
207 fis.close();
208
283 int lines = 0;
284 try (final BufferedReader is = new BufferedReader(new InputStreamReader(new FileInputStream(FILE_NAME)))) {
285 String str = Strings.EMPTY;
286 while (is.ready()) {
287 str = is.readLine();
288 // System.out.println(str);
289 ++lines;
290 final Matcher matcher = pattern.matcher(str);
291 assertTrue("Unexpected data: " + str, matcher.matches());
292 }
293 }
294 Assert.assertEquals(count, lines);
209295 }
210296
211297 public class FileWriterRunnable implements Runnable {
212298 private final boolean lock;
213 private final int count;
214 private final Exception[] error;
215
216 public FileWriterRunnable(final boolean lock, final int count, final Exception[] error) {
299 private final int logEventCount;
300 private final Exception[] exceptionRef;
301
302 public FileWriterRunnable(final boolean lock, final int logEventCount, final Exception[] exceptionRef) {
217303 this.lock = lock;
218 this.count = count;
219 this.error = error;
304 this.logEventCount = logEventCount;
305 this.exceptionRef = exceptionRef;
220306 }
221307
222308 @Override
224310 final Thread thread = Thread.currentThread();
225311
226312 try {
227 writer(lock, count, thread.getName());
228
229 } catch (final Exception ex) {
230 error[0] = ex;
231 throw new RuntimeException(ex);
313 writer(lock, logEventCount, thread.getName(), createOnDemand, true);
314 } catch (final Exception e) {
315 exceptionRef[0] = e;
316 Throwables.rethrow(e);
232317 }
233318 }
234319 }
251336 }
252337 final boolean lock = Boolean.parseBoolean(args[2]);
253338
339 final boolean createOnDemand = Boolean.parseBoolean(args[2]);
340
254341 // System.out.println("Got arguments " + id + ", " + count + ", " + lock);
255342
256343 try {
257 writer(lock, count, id);
344 writer(lock, count, id, createOnDemand, true);
258345 // thread.sleep(50);
259346
260 } catch (final Exception ex) {
261 throw new RuntimeException(ex);
347 } catch (final Exception e) {
348 Throwables.rethrow(e);
262349 }
263350
264351 }
1515 */
1616 package org.apache.logging.log4j.core.appender;
1717
18 import java.io.Serializable;
19 import java.util.concurrent.TimeUnit;
20
21 import org.apache.logging.log4j.core.Appender;
1822 import org.apache.logging.log4j.core.Filter;
1923 import org.apache.logging.log4j.core.Layout;
2024 import org.apache.logging.log4j.core.LogEvent;
2428 import org.apache.logging.log4j.core.config.plugins.PluginFactory;
2529 import org.apache.logging.log4j.core.config.plugins.validation.constraints.Required;
2630
27 import java.io.Serializable;
28
29 @Plugin(name = "Hanging", category = "Core", elementType = "appender", printObject = true)
31 @Plugin(name = "Hanging", category = "Core", elementType = Appender.ELEMENT_TYPE, printObject = true)
3032 public class HangingAppender extends AbstractAppender {
3133
3234 private static final long serialVersionUID = 1L;
7577 }
7678
7779 @Override
78 public void stop() {
79 super.stop();
80 public boolean stop(final long timeout, final TimeUnit timeUnit) {
81 setStopping();
82 super.stop(timeout, timeUnit, false);
8083 try {
8184 Thread.sleep(shutdownDelay);
8285 } catch (final InterruptedException ignore) {
8386 // ignore
8487 }
88 setStopped();
89 return true;
8590 }
8691 }
2020 import org.apache.logging.log4j.core.LogEvent;
2121 import org.apache.logging.log4j.core.impl.Log4jLogEvent;
2222 import org.apache.logging.log4j.core.layout.PatternLayout;
23 import org.apache.logging.log4j.core.util.Constants;
2423 import org.apache.logging.log4j.message.SimpleMessage;
2524 import org.apache.logging.log4j.test.appender.InMemoryAppender;
25 import org.apache.logging.log4j.util.Strings;
2626 import org.junit.Test;
2727
2828 import static org.junit.Assert.*;
7373 final String msg = app.toString();
7474 assertNotNull("No message", msg);
7575 final String expectedHeader = header == null ? "" : header;
76 final String expected = expectedHeader + "Test" + Constants.LINE_SEPARATOR + "Test" + Constants.LINE_SEPARATOR;
76 final String expected = expectedHeader + "Test" + Strings.LINE_SEPARATOR + "Test" + Strings.LINE_SEPARATOR;
7777 assertTrue("Incorrect message: " + msg, msg.equals(expected));
7878 app.stop();
7979 assertFalse("Appender did not stop", app.isStarted());
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.appender;
17
18 import org.apache.logging.log4j.LogManager;
19 import org.apache.logging.log4j.Logger;
20 import org.apache.logging.log4j.core.LoggerContext;
21 import org.apache.logging.log4j.core.config.Configurator;
22
23 /**
24 * Shows how to use ANSI escape codes to color messages. Each message is printed to the console in color, but the rest
25 * of the log entry (time stamp for example) is in the default color for that console.
26 * <p>
27 * Running from a Windows command line from the root of the project:
28 * </p>
29 *
30 * <pre>
31 * java -classpath log4j-core\target\test-classes;log4j-core\target\classes;log4j-api\target\classes;%HOME%\.m2\repository\org\fusesource\jansi\jansi\1.11\jansi-1.11.jar; org.apache.logging.log4j.core.appender.ConsoleAppenderAnsiMessagesMain log4j-core/target/test-classes/log4j2-console.xml
32 * </pre>
33 */
34 public class Jira739Test {
35
36 private static final Logger LOG = LogManager.getLogger(Jira739Test.class);
37
38 public static void main(final String[] args) {
39 final LoggerContext ctx = Configurator.initialize(Jira739Test.class.getName(),
40 "target/test-classes/LOG4J2-739.xml");
41 try {
42 for (int i = 0; i < 10; i++) {
43 LOG.trace("Entering Log4j Example " + i + " times");
44 LOG.error("Ohh!Failed!");
45 LOG.trace("Exiting Log4j Example." + i + " times");
46 }
47 } finally {
48 Configurator.shutdown(ctx);
49 }
50 }
51
52 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.appender;
17
18 import org.apache.logging.log4j.LogManager;
19 import org.apache.logging.log4j.Logger;
20 import org.apache.logging.log4j.core.LoggerContext;
21 import org.apache.logging.log4j.core.config.Configurator;
22
23 /**
24 * Shows how to use ANSI escape codes to color messages. Each message is printed to the console in color, but the rest
25 * of the log entry (time stamp for example) is in the default color for that console.
26 * <p>
27 * Running from a Windows command line from the root of the project:
28 * </p>
29 *
30 * <pre>
31 * java -classpath log4j-core\target\test-classes;log4j-core\target\classes;log4j-api\target\classes;%HOME%\.m2\repository\org\fusesource\jansi\jansi\1.13\jansi-1.13.jar; org.apache.logging.log4j.core.appender.ConsoleAppenderAnsiMessagesMain log4j-core/target/test-classes/log4j2-console.xml
32 * </pre>
33 */
34 public class Jira739Test {
35
36 private static final Logger LOG = LogManager.getLogger(Jira739Test.class);
37
38 public static void main(final String[] args) {
39 try (final LoggerContext ctx = Configurator.initialize(Jira739Test.class.getName(),
40 "target/test-classes/LOG4J2-739.xml")) {
41 for (int i = 0; i < 10; i++) {
42 LOG.trace("Entering Log4j Example " + i + " times");
43 LOG.error("Ohh!Failed!");
44 LOG.trace("Exiting Log4j Example." + i + " times");
45 }
46 }
47 }
48
49 }
1515 */
1616 package org.apache.logging.log4j.core.appender;
1717
18 import static org.junit.Assert.assertNotNull;
19 import static org.junit.Assert.assertTrue;
20
1821 import java.io.BufferedReader;
1922 import java.io.File;
2023 import java.io.FileReader;
2124
2225 import org.apache.logging.log4j.Logger;
26 import org.apache.logging.log4j.core.selector.ContextSelector;
27 import org.apache.logging.log4j.core.selector.CoreContextSelectors;
2328 import org.apache.logging.log4j.junit.CleanFiles;
2429 import org.apache.logging.log4j.junit.LoggerContextRule;
2530 import org.junit.Rule;
2631 import org.junit.Test;
2732 import org.junit.rules.RuleChain;
28
29 import static org.junit.Assert.*;
33 import org.junit.runner.RunWith;
34 import org.junit.runners.Parameterized;
35 import org.junit.runners.Parameterized.Parameters;
3036
3137 /**
3238 * Tests a "complete" JSON file.
3339 */
40 @RunWith(Parameterized.class)
3441 public class JsonCompleteFileAppenderTest {
3542
43 public JsonCompleteFileAppenderTest(final Class<ContextSelector> contextSelector) {
44 this.loggerContextRule = new LoggerContextRule("JsonCompleteFileAppenderTest.xml", contextSelector);
45 this.cleanFiles = new CleanFiles(logFile);
46 this.ruleChain = RuleChain.outerRule(cleanFiles).around(loggerContextRule);
47 }
48
49 @Parameters(name = "{0}")
50 public static Class<?>[] getParameters() {
51 return CoreContextSelectors.CLASSES;
52 }
53
3654 private final File logFile = new File("target", "JsonCompleteFileAppenderTest.log");
37
38 private final LoggerContextRule init = new LoggerContextRule("JsonCompleteFileAppenderTest.xml");
39 private final CleanFiles files = new CleanFiles(logFile);
55 private final LoggerContextRule loggerContextRule;
56 private final CleanFiles cleanFiles;
4057
4158 @Rule
42 public RuleChain chain = RuleChain.outerRule(files).around(init);
59 public RuleChain ruleChain;
4360
4461 @Test
4562 public void testFlushAtEndOfBatch() throws Exception {
46 final Logger log = this.init.getLogger("com.foo.Bar");
63 final Logger logger = this.loggerContextRule.getLogger("com.foo.Bar");
4764 final String logMsg = "Message flushed with immediate flush=true";
48 log.info(logMsg);
49 log.error(logMsg, new IllegalArgumentException("badarg"));
50 this.init.getContext().stop(); // stops async thread
65 logger.info(logMsg);
66 logger.error(logMsg, new IllegalArgumentException("badarg"));
67 this.loggerContextRule.getLoggerContext().stop(); // stops async thread
5168 String line1;
5269 String line2;
5370 String line3;
4343
4444 final boolean append = false;
4545 final boolean force = false;
46 final MemoryMappedFileManager manager = MemoryMappedFileManager.getFileManager(file.getAbsolutePath(), append,
47 force, mapSize, null, null);
46 try (final MemoryMappedFileManager manager = MemoryMappedFileManager.getFileManager(file.getAbsolutePath(),
47 append, force, mapSize, null, null)) {
48 byte[] msg;
49 for (int i = 0; i < 1000; i++) {
50 msg = ("Message " + i + "\n").getBytes();
51 manager.write(msg, 0, msg.length, false);
52 }
4853
49 byte[] msg;
50
51 for (int i = 0; i < 1000; i++) {
52 msg = ("Message " + i + "\n").getBytes();
53 manager.write(msg, 0, msg.length, false);
5454 }
55
56 manager.release();
5755
5856 try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
5957 String line = reader.readLine();
8280
8381 final boolean isAppend = true;
8482 final boolean isForce = false;
85 final MemoryMappedFileManager manager = MemoryMappedFileManager.getFileManager(file.getAbsolutePath(),
86 isAppend, isForce, MemoryMappedFileManager.DEFAULT_REGION_LENGTH, null, null);
87
88 manager.write(new byte[initialLength], 0, initialLength);
89 manager.release();
83 try (final MemoryMappedFileManager manager = MemoryMappedFileManager.getFileManager(file.getAbsolutePath(),
84 isAppend, isForce, MemoryMappedFileManager.DEFAULT_REGION_LENGTH, null, null)) {
85 manager.write(new byte[initialLength], 0, initialLength);
86 }
9087 final int expected = initialLength * 2;
9188 assertEquals("appended, not overwritten", expected, file.length());
9289 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.appender;
17
18 import java.io.BufferedOutputStream;
19 import java.io.ByteArrayOutputStream;
20 import java.io.OutputStream;
21 import java.sql.SQLException;
22
23 import org.apache.logging.log4j.LogManager;
24 import org.apache.logging.log4j.Logger;
25 import org.apache.logging.log4j.core.Appender;
26 import org.apache.logging.log4j.core.Layout;
27 import org.apache.logging.log4j.core.LoggerContext;
28 import org.apache.logging.log4j.core.config.Configuration;
29 import org.apache.logging.log4j.core.layout.PatternLayout;
30 import org.junit.Assert;
31 import org.junit.Rule;
32 import org.junit.Test;
33 import org.junit.rules.TestName;
34
35 /**
36 * Tests {@link OutputStreamAppender}.
37 */
38 public class OutputStreamAppenderTest {
39
40 private static final String TEST_MSG = "FOO ERROR";
41
42 @Rule
43 public TestName testName = new TestName();
44
45 private String getName(final OutputStream out) {
46 return out.getClass().getSimpleName() + "." + testName.getMethodName();
47 }
48
49 /**
50 * Tests that you can add an output stream appender dynamically.
51 */
52 private void addAppender(final OutputStream outputStream, final String outputStreamName) {
53 final LoggerContext context = LoggerContext.getContext(false);
54 final Configuration config = context.getConfiguration();
55 final PatternLayout layout = PatternLayout.createDefaultLayout(config);
56 final Appender appender = OutputStreamAppender.createAppender(layout, null, outputStream, outputStreamName, false, true);
57 appender.start();
58 config.addAppender(appender);
59 ConfigurationTestUtils.updateLoggers(appender, config);
60 }
61
62 @Test
63 public void testOutputStreamAppenderToBufferedOutputStream() throws SQLException {
64 final ByteArrayOutputStream out = new ByteArrayOutputStream();
65 final OutputStream os = new BufferedOutputStream(out);
66 final String name = getName(out);
67 final Logger logger = LogManager.getLogger(name);
68 addAppender(os, name);
69 logger.error(TEST_MSG);
70 final String actual = out.toString();
71 Assert.assertTrue(actual, actual.contains(TEST_MSG));
72 }
73
74 @Test
75 public void testOutputStreamAppenderToByteArrayOutputStream() throws SQLException {
76 final OutputStream out = new ByteArrayOutputStream();
77 final String name = getName(out);
78 final Logger logger = LogManager.getLogger(name);
79 addAppender(out, name);
80 logger.error(TEST_MSG);
81 final String actual = out.toString();
82 Assert.assertTrue(actual, actual.contains(TEST_MSG));
83 }
84
85 /**
86 * Validates that the code pattern we use to add an appender on the fly
87 * works with a basic appender that is not the new OutputStream appender or
88 * new Writer appender.
89 */
90 @Test
91 public void testUpdatePatternWithFileAppender() {
92 final LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
93 final Configuration config = ctx.getConfiguration();
94 final Layout<?> layout = PatternLayout.createDefaultLayout();
95 final Appender appender = FileAppender.createAppender("target/" + getClass().getName() + ".log", "false",
96 "false", "File", "true", "false", "false", "4000", layout, null, "false", null, config);
97 appender.start();
98 config.addAppender(appender);
99 ConfigurationTestUtils.updateLoggers(appender, config);
100 LogManager.getLogger().error("FOO MSG");
101 }
102 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.appender;
17
18 import java.io.BufferedOutputStream;
19 import java.io.ByteArrayOutputStream;
20 import java.io.OutputStream;
21 import java.sql.SQLException;
22
23 import org.apache.logging.log4j.LogManager;
24 import org.apache.logging.log4j.Logger;
25 import org.apache.logging.log4j.core.Appender;
26 import org.apache.logging.log4j.core.LoggerContext;
27 import org.apache.logging.log4j.core.config.Configuration;
28 import org.apache.logging.log4j.core.layout.PatternLayout;
29 import org.junit.Assert;
30 import org.junit.Rule;
31 import org.junit.Test;
32 import org.junit.rules.TestName;
33
34 /**
35 * Tests {@link OutputStreamAppender}.
36 */
37 public class OutputStreamAppenderTest {
38
39 private static final String TEST_MSG = "FOO ERROR";
40
41 @Rule
42 public TestName testName = new TestName();
43
44 private String getName(final OutputStream out) {
45 return out.getClass().getSimpleName() + "." + testName.getMethodName();
46 }
47
48 /**
49 * Tests that you can add an output stream appender dynamically.
50 */
51 private void addAppender(final OutputStream outputStream, final String outputStreamName) {
52 final LoggerContext context = LoggerContext.getContext(false);
53 final Configuration config = context.getConfiguration();
54 final PatternLayout layout = PatternLayout.createDefaultLayout(config);
55 final Appender appender = OutputStreamAppender.createAppender(layout, null, outputStream, outputStreamName, false, true);
56 appender.start();
57 config.addAppender(appender);
58 ConfigurationTestUtils.updateLoggers(appender, config);
59 }
60
61 @Test
62 public void testOutputStreamAppenderToBufferedOutputStream() throws SQLException {
63 final ByteArrayOutputStream out = new ByteArrayOutputStream();
64 final OutputStream os = new BufferedOutputStream(out);
65 final String name = getName(out);
66 final Logger logger = LogManager.getLogger(name);
67 addAppender(os, name);
68 logger.error(TEST_MSG);
69 final String actual = out.toString();
70 Assert.assertTrue(actual, actual.contains(TEST_MSG));
71 }
72
73 @Test
74 public void testOutputStreamAppenderToByteArrayOutputStream() throws SQLException {
75 final OutputStream out = new ByteArrayOutputStream();
76 final String name = getName(out);
77 final Logger logger = LogManager.getLogger(name);
78 addAppender(out, name);
79 logger.error(TEST_MSG);
80 final String actual = out.toString();
81 Assert.assertTrue(actual, actual.contains(TEST_MSG));
82 }
83
84 /**
85 * Validates that the code pattern we use to add an appender on the fly
86 * works with a basic appender that is not the new OutputStream appender or
87 * new Writer appender.
88 */
89 @Test
90 public void testUpdatePatternWithFileAppender() {
91 final LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
92 final Configuration config = ctx.getConfiguration();
93 // @formatter:off
94 final Appender appender = FileAppender.newBuilder()
95 .withFileName("target/" + getClass().getName() + ".log")
96 .withAppend(false)
97 .withName("File")
98 .withIgnoreExceptions(false)
99 .withBufferedIo(false)
100 .withBufferSize(4000)
101 .withConfiguration(config)
102 .build();
103 // @formatter:on
104 appender.start();
105 config.addAppender(appender);
106 ConfigurationTestUtils.updateLoggers(appender, config);
107 LogManager.getLogger().error("FOO MSG");
108 }
109 }
3838 private static final Logger LOG = LogManager.getLogger(ProgressConsoleTest.class);
3939
4040 public static void main(final String[] args) {
41 final LoggerContext ctx = Configurator.initialize(ProgressConsoleTest.class.getName(),
42 "target/test-classes/log4j2-progress-console.xml");
4341 // src/test/resources/log4j2-console-progress.xml
4442 // target/test-classes/log4j2-progress-console.xml
45 try {
43 try (final LoggerContext ctx = Configurator.initialize(ProgressConsoleTest.class.getName(),
44 "target/test-classes/log4j2-progress-console.xml")) {
4645 for (double i = 0; i <= 1; i = i + 0.05) {
4746 updateProgress(i);
4847 try {
5251 e.printStackTrace();
5352 }
5453 }
55 } finally {
56 Configurator.shutdown(ctx);
5754 }
5855 }
5956
7676 final Logger logger = this.init.getLogger("com.foo.Bar");
7777 final String message = "This is a test log message brought to you by Slurm.";
7878 logger.info(message);
79 this.init.getContext().stop(); // stop async thread
79 this.init.getLoggerContext().stop(); // stop async thread
8080
8181 String line;
8282 try (final BufferedReader reader = new BufferedReader(new FileReader(this.logFile))) {
4545 public void testWrite_multiplesOfBufferSize() throws IOException {
4646 final File file = folder.newFile();
4747 try (final RandomAccessFile raf = new RandomAccessFile(file, "rw")) {
48 final OutputStream os = NullOutputStream.NULL_OUTPUT_STREAM;
49 final RandomAccessFileManager manager = new RandomAccessFileManager(raf, file.getName(), os,
50 RandomAccessFileManager.DEFAULT_BUFFER_SIZE, null, null, true);
48 final OutputStream os = NullOutputStream.getInstance();
49 final RandomAccessFileManager manager = new RandomAccessFileManager(null, raf, file.getName(),
50 os, RandomAccessFileManager.DEFAULT_BUFFER_SIZE, null, null, true);
5151
5252 final int size = RandomAccessFileManager.DEFAULT_BUFFER_SIZE * 3;
5353 final byte[] data = new byte[size];
6666 public void testWrite_dataExceedingBufferSize() throws IOException {
6767 final File file = folder.newFile();
6868 try (final RandomAccessFile raf = new RandomAccessFile(file, "rw")) {
69 final OutputStream os = NullOutputStream.NULL_OUTPUT_STREAM;
70 final RandomAccessFileManager manager = new RandomAccessFileManager(raf, file.getName(), os,
71 RandomAccessFileManager.DEFAULT_BUFFER_SIZE, null, null, true);
69 final OutputStream os = NullOutputStream.getInstance();
70 final RandomAccessFileManager manager = new RandomAccessFileManager(null, raf, file.getName(),
71 os, RandomAccessFileManager.DEFAULT_BUFFER_SIZE, null, null, true);
7272
7373 final int size = RandomAccessFileManager.DEFAULT_BUFFER_SIZE * 3 + 1;
7474 final byte[] data = new byte[size];
8484 public void testConfigurableBufferSize() throws IOException {
8585 final File file = folder.newFile();
8686 try (final RandomAccessFile raf = new RandomAccessFile(file, "rw")) {
87 final OutputStream os = NullOutputStream.NULL_OUTPUT_STREAM;
87 final OutputStream os = NullOutputStream.getInstance();
8888 final int bufferSize = 4 * 1024;
8989 assertNotEquals(bufferSize, RandomAccessFileManager.DEFAULT_BUFFER_SIZE);
9090
91 final RandomAccessFileManager manager = new RandomAccessFileManager(raf, file.getName(), os,
92 bufferSize, null, null, true);
91 final RandomAccessFileManager manager = new RandomAccessFileManager(null, raf, file.getName(),
92 os, bufferSize, null, null, true);
9393
9494 // check the resulting buffer size is what was requested
9595 assertEquals(bufferSize, manager.getBufferSize());
9999 public void testWrite_dataExceedingMinBufferSize() throws IOException {
100100 final File file = folder.newFile();
101101 try (final RandomAccessFile raf = new RandomAccessFile(file, "rw")) {
102 final OutputStream os = NullOutputStream.NULL_OUTPUT_STREAM;
102 final OutputStream os = NullOutputStream.getInstance();
103103 final int bufferSize = 1;
104 final RandomAccessFileManager manager = new RandomAccessFileManager(raf, file.getName(), os,
105 bufferSize, null, null, true);
104 final RandomAccessFileManager manager = new RandomAccessFileManager(null, raf, file.getName(),
105 os, bufferSize, null, null, true);
106106
107107 final int size = bufferSize * 3 + 1;
108108 final byte[] data = new byte[size];
130130 assertEquals("all flushed to disk", bytes.length, file.length());
131131
132132 final RandomAccessFileManager manager = RandomAccessFileManager.getFileManager(
133 file.getAbsolutePath(), isAppend, true, RandomAccessFileManager.DEFAULT_BUFFER_SIZE, null, null);
133 file.getAbsolutePath(), isAppend, true, RandomAccessFileManager.DEFAULT_BUFFER_SIZE, null, null, null);
134134 manager.write(bytes, 0, bytes.length, true);
135135 final int expected = bytes.length * 2;
136136 assertEquals("appended, not overwritten", expected, file.length());
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.appender;
17
18 import static org.junit.Assert.assertNotNull;
19 import static org.junit.Assert.assertTrue;
20
21 import java.util.List;
22
23 import org.apache.logging.log4j.Marker;
24 import org.apache.logging.log4j.MarkerManager;
25 import org.apache.logging.log4j.core.LogEvent;
26 import org.apache.logging.log4j.core.Logger;
27 import org.apache.logging.log4j.junit.LoggerContextRule;
28 import org.apache.logging.log4j.test.appender.ListAppender;
29 import org.junit.Rule;
30 import org.junit.Test;
31 import org.junit.runner.RunWith;
32 import org.junit.runners.Parameterized;
33
34 /**
35 *
36 */
37 @RunWith(Parameterized.class)
38 public class ScriptAppenderSelectorTest {
39
40 @Parameterized.Parameters(name = "{0}")
41 public static Object[][] getParameters() {
42 // @formatter:off
43 return new Object[][] {
44 { "log4j-appender-selector-groovy.xml" },
45 { "log4j-appender-selector-javascript.xml" },
46 };
47 // @formatter:on
48 }
49
50 @Rule
51 public final LoggerContextRule loggerContextRule;
52
53 public ScriptAppenderSelectorTest(final String configLocation) {
54 this.loggerContextRule = new LoggerContextRule(configLocation);
55 }
56
57 private ListAppender getListAppender() {
58 return loggerContextRule.getListAppender("SelectIt");
59 }
60
61 private void logAndCheck() {
62 final Marker marker = MarkerManager.getMarker("HEXDUMP");
63 final Logger logger = loggerContextRule.getLogger(ScriptAppenderSelectorTest.class);
64 logger.error("Hello");
65 final ListAppender listAppender = getListAppender();
66 final List<LogEvent> list = listAppender.getEvents();
67 assertNotNull("No events generated", list);
68 assertTrue("Incorrect number of events. Expected 1, got " + list.size(), list.size() == 1);
69 logger.error("World");
70 assertTrue("Incorrect number of events. Expected 2, got " + list.size(), list.size() == 2);
71 logger.error(marker, "DEADBEEF");
72 assertTrue("Incorrect number of events. Expected 3, got " + list.size(), list.size() == 3);
73 }
74
75 @Test(expected = AssertionError.class)
76 public void testAppender1Absence() {
77 loggerContextRule.getListAppender("List1");
78 }
79
80 @Test(expected = AssertionError.class)
81 public void testAppender2Absence() {
82 loggerContextRule.getListAppender("List2");
83 }
84
85 @Test
86 public void testAppenderPresence() {
87 getListAppender();
88 }
89
90 @Test
91 public void testLogging1() {
92 logAndCheck();
93 }
94
95 @Test
96 public void testLogging2() {
97 logAndCheck();
98 }
99 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.appender;
17
18 import org.apache.logging.log4j.ThreadContext;
19 import org.apache.logging.log4j.core.Logger;
20 import org.apache.logging.log4j.core.LoggerContext;
21 import org.apache.logging.log4j.core.appender.SocketAppenderTest.TcpSocketTestServer;
22 import org.apache.logging.log4j.core.util.Constants;
23 import org.apache.logging.log4j.junit.LoggerContextRule;
24 import org.apache.logging.log4j.test.AvailablePortFinder;
25 import org.junit.After;
26 import org.junit.Before;
27 import org.junit.Rule;
28 import org.junit.Test;
29
30 /**
31 *
32 */
33 public class SocketAppenderBufferSizeTest {
34
35 private TcpSocketTestServer tcpServer;
36
37 private LoggerContext loggerContext;
38 private Logger logger;
39
40 @Rule
41 public LoggerContextRule loggerContextRule = new LoggerContextRule("log4j-empty.xml");
42
43 @Before
44 public void setup() throws Exception {
45 tcpServer = new TcpSocketTestServer(AvailablePortFinder.getNextAvailable());
46 tcpServer.start();
47 ThreadContext.clearAll();
48 loggerContext = loggerContextRule.getLoggerContext();
49 logger = loggerContext.getLogger(SocketAppenderBufferSizeTest.class.getName());
50 }
51
52 @After
53 public void teardown() {
54 tcpServer.shutdown();
55 loggerContext = null;
56 logger = null;
57 tcpServer.reset();
58 ThreadContext.clearAll();
59 }
60
61 @Test
62 public void testTcpAppenderDefaultBufferSize() throws Exception {
63 SocketAppenderTest.testTcpAppender(tcpServer, logger, Constants.ENCODER_BYTE_BUFFER_SIZE);
64 }
65
66 @Test
67 public void testTcpAppenderLargeBufferSize() throws Exception {
68 SocketAppenderTest.testTcpAppender(tcpServer, logger, Constants.ENCODER_BYTE_BUFFER_SIZE * 100);
69 }
70
71 @Test
72 public void testTcpAppenderSmallestBufferSize() throws Exception {
73 SocketAppenderTest.testTcpAppender(tcpServer, logger, 1);
74 }
75
76 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.appender;
17
18 import org.apache.logging.log4j.core.appender.SocketAppender;
19 import org.junit.Assert;
20 import org.junit.Test;
21
22 public class SocketAppenderBuilderTest {
23
24 /**
25 * Tests https://issues.apache.org/jira/browse/LOG4J2-1620
26 */
27 @Test
28 public void testDefaultImmediateFlush() {
29 Assert.assertTrue(SocketAppender.newBuilder().isImmediateFlush());
30 }
31 }
4343 import org.apache.logging.log4j.core.Logger;
4444 import org.apache.logging.log4j.core.LoggerContext;
4545 import org.apache.logging.log4j.core.net.Protocol;
46 import org.apache.logging.log4j.core.util.Constants;
47 import org.apache.logging.log4j.core.util.Throwables;
4648 import org.apache.logging.log4j.test.AvailablePortFinder;
4749 import org.junit.After;
4850 import org.junit.AfterClass;
51 import org.junit.Assert;
4952 import org.junit.BeforeClass;
53 import org.junit.Ignore;
5054 import org.junit.Test;
5155
5256 /**
5862 private static final int DYN_PORT = AvailablePortFinder.getNextAvailable();
5963 private static final int ERROR_PORT = AvailablePortFinder.getNextAvailable();
6064
61 private static BlockingQueue<LogEvent> list = new ArrayBlockingQueue<>(10);
62
63 private static TCPSocketServer tcpServer;
64 private static UDPSocketServer udpServer;
65
66 LoggerContext context = LoggerContext.getContext();
67 Logger root = context.getLogger("SocketAppenderTest");
68
69 private static int tcpCount = 0;
70 private static int udpCount = 0;
65 private static TcpSocketTestServer tcpServer;
66 private static UdpSocketTestServer udpServer;
67
68 private final LoggerContext context = LoggerContext.getContext();
69 private final Logger logger = context.getLogger(SocketAppenderTest.class.getName());
7170
7271 @BeforeClass
7372 public static void setupClass() throws Exception {
74 tcpServer = new TCPSocketServer(PORT);
73 tcpServer = new TcpSocketTestServer(PORT);
7574 tcpServer.start();
76 udpServer = new UDPSocketServer();
75 udpServer = new UdpSocketTestServer();
7776 udpServer.start();
7877 (LoggerContext.getContext()).reconfigure();
78 ThreadContext.clearAll();
7979 }
8080
8181 @AfterClass
8282 public static void cleanupClass() {
8383 tcpServer.shutdown();
8484 udpServer.shutdown();
85 list.clear();
85 ThreadContext.clearAll();
8686 }
8787
8888 @After
8989 public void teardown() {
90 final Map<String, Appender> map = root.getAppenders();
90 ThreadContext.clearAll();
91 removeAndStopAppenders();
92 reset();
93 }
94
95 void removeAndStopAppenders() {
96 final Map<String, Appender> map = logger.getAppenders();
9197 for (final Map.Entry<String, Appender> entry : map.entrySet()) {
92 final Appender app = entry.getValue();
93 root.removeAppender(app);
94 app.stop();
95 }
96 tcpCount = 0;
97 udpCount = 0;
98 list.clear();
99 }
100
101 @Test
102 public void testTcpAppender() throws Exception {
103
104 final SocketAppender appender = SocketAppender.createAppender("localhost", PORT, Protocol.TCP, null, 0, -1,
105 false, "Test", true, true, null, null, false, null);
98 final Appender appender = entry.getValue();
99 logger.removeAppender(appender);
100 appender.stop();
101 }
102 }
103
104 static void reset() {
105 tcpServer.reset();
106 udpServer.reset();
107 }
108
109 @Test
110 public void testTcpAppender1() throws Exception {
111 testTcpAppender(tcpServer, logger, Constants.ENCODER_BYTE_BUFFER_SIZE);
112 }
113
114 @Test
115 @Ignore("WIP Bug when this method runs after testTcpAppender1()")
116 public void testTcpAppender2() throws Exception {
117 testTcpAppender(tcpServer, logger, Constants.ENCODER_BYTE_BUFFER_SIZE);
118 }
119
120 static void testTcpAppender(final TcpSocketTestServer tcpTestServer, final Logger logger, final int bufferSize)
121 throws Exception {
122 // @formatter:off
123 final SocketAppender appender = SocketAppender.newBuilder()
124 .withHost("localhost")
125 .withPort(tcpTestServer.getLocalPort())
126 .withReconnectDelayMillis(-1)
127 .withName("test")
128 .withImmediateFail(false)
129 .withBufferSize(bufferSize)
130 .build();
131 // @formatter:on
106132 appender.start();
133 Assert.assertEquals(bufferSize, appender.getManager().getByteBuffer().capacity());
107134
108135 // set appender on root and set level to debug
109 root.addAppender(appender);
110 root.setAdditive(false);
111 root.setLevel(Level.DEBUG);
136 logger.addAppender(appender);
137 logger.setAdditive(false);
138 logger.setLevel(Level.DEBUG);
112139 final String tcKey = "UUID";
113140 final String expectedUuidStr = UUID.randomUUID().toString();
114141 ThreadContext.put(tcKey, expectedUuidStr);
115142 ThreadContext.push(expectedUuidStr);
116143 final String expectedExMsg = "This is a test";
117144 try {
118 root.debug("This is a test message");
145 logger.debug("This is a test message");
119146 final Throwable child = new LoggingException(expectedExMsg);
120 root.error("Throwing an exception", child);
121 root.debug("This is another test message");
147 logger.error("Throwing an exception", child);
148 logger.debug("This is another test message");
122149 } finally {
123150 ThreadContext.remove(tcKey);
124151 ThreadContext.pop();
125152 }
126153 Thread.sleep(250);
127 LogEvent event = list.poll(3, TimeUnit.SECONDS);
154 LogEvent event = tcpTestServer.getQueue().poll(3, TimeUnit.SECONDS);
128155 assertNotNull("No event retrieved", event);
129156 assertTrue("Incorrect event", event.getMessage().getFormattedMessage().equals("This is a test message"));
130 assertTrue("Message not delivered via TCP", tcpCount > 0);
157 assertTrue("Message not delivered via TCP", tcpTestServer.getCount() > 0);
131158 assertEquals(expectedUuidStr, event.getContextMap().get(tcKey));
132 event = list.poll(3, TimeUnit.SECONDS);
159 event = tcpTestServer.getQueue().poll(3, TimeUnit.SECONDS);
133160 assertNotNull("No event retrieved", event);
134161 assertTrue("Incorrect event", event.getMessage().getFormattedMessage().equals("Throwing an exception"));
135 assertTrue("Message not delivered via TCP", tcpCount > 1);
162 assertTrue("Message not delivered via TCP", tcpTestServer.getCount() > 1);
136163 assertEquals(expectedUuidStr, event.getContextStack().pop());
137164 assertNotNull(event.getThrownProxy());
138165 assertEquals(expectedExMsg, event.getThrownProxy().getMessage());
140167
141168 @Test
142169 public void testDefaultProtocol() throws Exception {
143
144 final SocketAppender appender = SocketAppender.createAppender("localhost", PORT, (Protocol) null, null, 0, -1,
145 false, "Test", true, true, null, null, false, null);
170 // @formatter:off
171 final SocketAppender appender = SocketAppender.newBuilder()
172 .withPort(tcpServer.getLocalPort())
173 .withReconnectDelayMillis(-1)
174 .withName("test")
175 .withImmediateFail(false)
176 .build();
177 // @formatter:on
146178 assertNotNull(appender);
179 appender.stop();
147180 }
148181
149182 @Test
154187 ex.printStackTrace();
155188 }
156189
157 final SocketAppender appender = SocketAppender.createAppender("localhost", PORT, Protocol.UDP, null, 0, -1,
158 false, "Test", true, true, null, null, false, null);
190 // @formatter:off
191 final SocketAppender appender = SocketAppender.newBuilder()
192 .withProtocol(Protocol.UDP)
193 .withPort(tcpServer.getLocalPort())
194 .withReconnectDelayMillis(-1)
195 .withName("test")
196 .withImmediateFail(false)
197 .build();
198 // @formatter:on
159199 appender.start();
160200
161201 // set appender on root and set level to debug
162 root.addAppender(appender);
163 root.setAdditive(false);
164 root.setLevel(Level.DEBUG);
165 root.debug("This is a udp message");
166 final LogEvent event = list.poll(3, TimeUnit.SECONDS);
202 logger.addAppender(appender);
203 logger.setAdditive(false);
204 logger.setLevel(Level.DEBUG);
205 logger.debug("This is a udp message");
206 final LogEvent event = udpServer.getQueue().poll(3, TimeUnit.SECONDS);
167207 assertNotNull("No event retrieved", event);
168208 assertTrue("Incorrect event", event.getMessage().getFormattedMessage().equals("This is a udp message"));
169 assertTrue("Message not delivered via UDP", udpCount > 0);
209 assertTrue("Message not delivered via UDP", udpServer.getCount() > 0);
170210 }
171211
172212 @Test
173213 public void testTcpAppenderDeadlock() throws Exception {
174214
175 final SocketAppender appender = SocketAppender.createAppender("localhost", DYN_PORT, Protocol.TCP, null, 0,
176 100, false, "Test", true, true, null, null, false, null);
215 // @formatter:off
216 final SocketAppender appender = SocketAppender.newBuilder()
217 .withHost("localhost")
218 .withPort(DYN_PORT)
219 .withReconnectDelayMillis(100)
220 .withName("test")
221 .withImmediateFail(false)
222 .build();
223 // @formatter:on
177224 appender.start();
178225 // set appender on root and set level to debug
179 root.addAppender(appender);
180 root.setAdditive(false);
181 root.setLevel(Level.DEBUG);
182
183 new TCPSocketServer(DYN_PORT).start();
184
185 root.debug("This message is written because a deadlock never.");
186
187 final LogEvent event = list.poll(3, TimeUnit.SECONDS);
188 assertNotNull("No event retrieved", event);
226 logger.addAppender(appender);
227 logger.setAdditive(false);
228 logger.setLevel(Level.DEBUG);
229
230 final TcpSocketTestServer tcpSocketServer = new TcpSocketTestServer(DYN_PORT);
231 try {
232 tcpSocketServer.start();
233
234 logger.debug("This message is written because a deadlock never.");
235
236 final LogEvent event = tcpSocketServer.getQueue().poll(3, TimeUnit.SECONDS);
237 assertNotNull("No event retrieved", event);
238 } finally {
239 tcpSocketServer.shutdown();
240 }
189241 }
190242
191243 @Test
192244 public void testTcpAppenderNoWait() throws Exception {
193
194 final SocketAppender appender = SocketAppender.createAppender("localhost", ERROR_PORT, Protocol.TCP, null, 0,
195 100, true, "Test", true, false, null, null, false, null);
245 // @formatter:off
246 final SocketAppender appender = SocketAppender.newBuilder()
247 .withHost("localhost")
248 .withPort(ERROR_PORT)
249 .withReconnectDelayMillis(100)
250 .withName("test")
251 .withImmediateFail(false)
252 .withIgnoreExceptions(false)
253 .build();
254 // @formatter:on
196255 appender.start();
197256 // set appender on root and set level to debug
198 root.addAppender(appender);
199 root.setAdditive(false);
200 root.setLevel(Level.DEBUG);
257 logger.addAppender(appender);
258 logger.setAdditive(false);
259 logger.setLevel(Level.DEBUG);
201260
202261 try {
203 root.debug("This message is written because a deadlock never.");
262 logger.debug("This message is written because a deadlock never.");
204263 fail("No Exception was thrown");
205264 } catch (final Exception ex) {
206265 // TODO: move exception to @Test(expect = Exception.class)
207266 // Failure is expected.
208 }
209 }
210
211 public static class UDPSocketServer extends Thread {
267 // ex.printStackTrace();
268 }
269 }
270
271 public static class UdpSocketTestServer extends Thread {
272
212273 private final DatagramSocket sock;
213274 private boolean shutdown = false;
214275 private Thread thread;
215276 private final CountDownLatch latch = new CountDownLatch(1);
216
217 public UDPSocketServer() throws IOException {
277 private volatile int count = 0;
278 private final BlockingQueue<LogEvent> queue;
279
280 public UdpSocketTestServer() throws IOException {
218281 this.sock = new DatagramSocket(PORT);
282 this.queue = new ArrayBlockingQueue<>(10);
283 }
284
285 public void reset() {
286 queue.clear();
287 count = 0;
219288 }
220289
221290 public void shutdown() {
233302 latch.countDown();
234303 sock.receive(packet);
235304 final ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(packet.getData()));
236 ++udpCount;
305 ++count;
237306 final Object received = ois.readObject(); // separate lines for debugging
238307 final LogEvent event = (LogEvent) received;
239 list.add(event);
308 queue.add(event);
240309 }
241 } catch (final Throwable ex) {
242 ex.printStackTrace();
310 } catch (final Throwable e) {
311 e.printStackTrace();
243312 if (!shutdown) {
244 throw new RuntimeException(ex);
313 Throwables.rethrow(e);
245314 }
246315 }
247316 }
248 }
249
250 public static class TCPSocketServer extends Thread {
317
318 public int getCount() {
319 return count;
320 }
321
322 public BlockingQueue<LogEvent> getQueue() {
323 return queue;
324 }
325 }
326
327 public static class TcpSocketTestServer extends Thread {
251328
252329 private final ServerSocket sock;
253 private boolean shutdown = false;
254
255 public TCPSocketServer(final int port) throws IOException {
330 private volatile boolean shutdown = false;
331 private volatile int count = 0;
332 private final BlockingQueue<LogEvent> queue;
333
334 public TcpSocketTestServer(final int port) throws IOException {
256335 this.sock = new ServerSocket(port);
336 this.queue = new ArrayBlockingQueue<>(10);
337 }
338
339 public int getLocalPort() {
340 return sock.getLocalPort();
341 }
342
343 public void reset() {
344 queue.clear();
345 count = 0;
257346 }
258347
259348 public void shutdown() {
264353 @Override
265354 public void run() {
266355 try {
267 final Socket socket = sock.accept();
268 if (socket != null) {
269 final ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
270 while (!shutdown) {
271 list.add((LogEvent) ois.readObject());
272 ++tcpCount;
356 try (final Socket socket = sock.accept()) {
357 if (socket != null) {
358 final ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
359 while (!shutdown) {
360 queue.add((LogEvent) ois.readObject());
361 ++count;
362 }
273363 }
274364 }
275365 } catch (final EOFException eof) {
276366 // Socket is closed.
277 } catch (final Exception ex) {
367 } catch (final Exception e) {
278368 if (!shutdown) {
279 throw new RuntimeException(ex);
369 Throwables.rethrow(e);
280370 }
281371 }
282372 }
373
374 public BlockingQueue<LogEvent> getQueue() {
375 return queue;
376 }
377
378 public int getCount() {
379 return count;
380 }
283381 }
284382
285383 }
4848
4949 @BeforeClass
5050 public static void setupClass() throws Exception {
51 (LoggerContext.getContext()).reconfigure();
51 LoggerContext.getContext().reconfigure();
5252 }
5353
5454 protected void sendAndCheckLegacyBSDMessages(final List<String> messagesToSend) throws InterruptedException {
1515 */
1616 package org.apache.logging.log4j.core.appender;
1717
18 import static org.junit.Assert.assertFalse;
19 import static org.junit.Assert.assertNotNull;
20 import static org.junit.Assert.assertTrue;
21
1822 import java.io.BufferedReader;
1923 import java.io.File;
2024 import java.io.FileReader;
2125
22 import org.apache.logging.log4j.LogManager;
2326 import org.apache.logging.log4j.Logger;
2427 import org.apache.logging.log4j.core.CoreLoggerContexts;
25 import org.apache.logging.log4j.core.config.ConfigurationFactory;
26 import org.junit.BeforeClass;
28 import org.apache.logging.log4j.core.selector.ContextSelector;
29 import org.apache.logging.log4j.core.selector.CoreContextSelectors;
30 import org.apache.logging.log4j.junit.CleanFiles;
31 import org.apache.logging.log4j.junit.LoggerContextRule;
32 import org.junit.Rule;
2733 import org.junit.Test;
28
29 import static org.junit.Assert.*;
34 import org.junit.rules.RuleChain;
35 import org.junit.runner.RunWith;
36 import org.junit.runners.Parameterized;
37 import org.junit.runners.Parameterized.Parameters;
3038
3139 /**
3240 * Tests a "complete" XML file a.k.a. a well-formed XML file.
3341 */
42 @RunWith(Parameterized.class)
3443 public class XmlCompleteFileAppenderTest {
3544
36 @BeforeClass
37 public static void beforeClass() {
38 System.setProperty(ConfigurationFactory.CONFIGURATION_FILE_PROPERTY,
39 "XmlCompleteFileAppenderTest.xml");
45 public XmlCompleteFileAppenderTest(final Class<ContextSelector> contextSelector) {
46 this.loggerContextRule = new LoggerContextRule("XmlCompleteFileAppenderTest.xml", contextSelector);
47 this.cleanFiles = new CleanFiles(logFile);
48 this.ruleChain = RuleChain.outerRule(cleanFiles).around(loggerContextRule);
4049 }
50
51 @Parameters(name = "{0}")
52 public static Class<?>[] getParameters() {
53 return CoreContextSelectors.CLASSES;
54 }
55
56 private final File logFile = new File("target", "XmlCompleteFileAppenderTest.log");
57 private final LoggerContextRule loggerContextRule;
58 private final CleanFiles cleanFiles;
59
60 @Rule
61 public RuleChain ruleChain;
4162
4263 @Test
4364 public void testFlushAtEndOfBatch() throws Exception {
44 final File file = new File("target", "XmlCompleteFileAppenderTest.log");
45 // System.out.println(f.getAbsolutePath());
46 file.delete();
47 final Logger log = LogManager.getLogger("com.foo.Bar");
65 final Logger logger = this.loggerContextRule.getLogger("com.foo.Bar");
4866 final String logMsg = "Message flushed with immediate flush=false";
49 log.info(logMsg);
50 CoreLoggerContexts.stopLoggerContext(false, file); // stop async thread
67 logger.info(logMsg);
68 CoreLoggerContexts.stopLoggerContext(false, logFile); // stop async thread
5169
5270 String line1;
5371 String line2;
5472 String line3;
5573 String line4;
56 try (final BufferedReader reader = new BufferedReader(new FileReader(file))) {
74 try (final BufferedReader reader = new BufferedReader(new FileReader(logFile))) {
5775 line1 = reader.readLine();
5876 line2 = reader.readLine();
5977 reader.readLine(); // ignore the empty line after the <Events> root
6078 line3 = reader.readLine();
6179 line4 = reader.readLine();
6280 } finally {
63 file.delete();
81 logFile.delete();
6482 }
6583 assertNotNull("line1", line1);
6684 final String msg1 = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
102120 */
103121 @Test
104122 public void testChildElementsAreCorrectlyIndented() throws Exception {
105 final File file = new File("target", "XmlCompleteFileAppenderTest.log");
106 file.delete();
107 final Logger log = LogManager.getLogger("com.foo.Bar");
123 final Logger logger = this.loggerContextRule.getLogger("com.foo.Bar");
108124 final String firstLogMsg = "First Msg tag must be in level 2 after correct indentation";
109 log.info(firstLogMsg);
125 logger.info(firstLogMsg);
110126 final String secondLogMsg = "Second Msg tag must also be in level 2 after correct indentation";
111 log.info(secondLogMsg);
112 CoreLoggerContexts.stopLoggerContext(false, file); // stop async thread
127 logger.info(secondLogMsg);
128 CoreLoggerContexts.stopLoggerContext(false, logFile); // stop async thread
113129
114130 final String[] lines = new String[9];
115131
116 try (final BufferedReader reader = new BufferedReader(new FileReader(file))) {
132 try (final BufferedReader reader = new BufferedReader(new FileReader(logFile))) {
117133
118134 int usefulLinesIndex = 0;
119135 String readLine;
125141 }
126142 }
127143 } finally {
128 file.delete();
144 logFile.delete();
129145 }
130146
131147 String currentLine = lines[0];
3232 this.manager = createMockBuilder(LocalAbstractDatabaseManager.class)
3333 .withConstructor(String.class, int.class)
3434 .withArgs(name, 0)
35 .addMockedMethod("release")
35 .addMockedMethod("close")
3636 .createStrictMock();
3737
3838 this.appender = createMockBuilder(LocalAbstractDatabaseAppender.class)
7878
7979 verify(this.manager, this.appender);
8080 reset(this.manager, this.appender);
81 this.manager.release();
82 expectLastCall();
81 this.manager.shutdownInternal();
82 expectLastCall().andReturn(Boolean.TRUE);
8383 replay(this.manager, this.appender);
8484
8585 this.appender.stop();
9797
9898 verify(this.manager, this.appender);
9999 reset(this.manager, this.appender);
100 this.manager.release();
100 this.manager.close();
101101 expectLastCall();
102102 final LocalAbstractDatabaseManager newManager = createMockBuilder(LocalAbstractDatabaseManager.class)
103 .withConstructor(String.class, int.class).withArgs("name", 0).addMockedMethod("release")
103 .withConstructor(String.class, int.class).withArgs("name", 0).addMockedMethod("close")
104104 .createStrictMock();
105105 newManager.startupInternal();
106106 expectLastCall();
110110
111111 verify(this.manager, this.appender, newManager);
112112 reset(this.manager, this.appender, newManager);
113 newManager.release();
114 expectLastCall();
113 newManager.shutdownInternal();
114 expectLastCall().andReturn(Boolean.TRUE);
115115 replay(this.manager, this.appender, newManager);
116116
117117 this.appender.stop();
131131 this.manager.writeInternal(same(event1));
132132 expectLastCall();
133133 this.manager.commitAndClose();
134 expectLastCall();
134 expectLastCall().andReturn(Boolean.TRUE);
135135 replay(this.manager, this.appender);
136136
137137 this.appender.append(event1);
143143 this.manager.writeInternal(same(event2));
144144 expectLastCall();
145145 this.manager.commitAndClose();
146 expectLastCall();
146 expectLastCall().andReturn(Boolean.TRUE);
147147 replay(this.manager, this.appender);
148148
149149 this.appender.append(event2);
6060 verify(this.manager);
6161 reset(this.manager);
6262 this.manager.shutdownInternal();
63 expectLastCall();
63 expectLastCall().andReturn(Boolean.TRUE);
6464 replay(this.manager);
6565
6666 this.manager.shutdown();
8888 verify(this.manager);
8989 reset(this.manager);
9090 this.manager.shutdownInternal();
91 expectLastCall();
92 replay(this.manager);
93
94 this.manager.releaseSub();
91 expectLastCall().andReturn(Boolean.TRUE);
92 replay(this.manager);
93
94 this.manager.releaseSub(-1, null);
9595 assertFalse("The manager should not be running anymore.", this.manager.isRunning());
9696 }
9797
134134 this.manager.writeInternal(same(event1));
135135 expectLastCall();
136136 this.manager.commitAndClose();
137 expectLastCall();
138 replay(this.manager);
139
140 this.manager.write(event1);
141
142 verify(this.manager);
143 reset(this.manager);
144 this.manager.connectAndStart();
145 expectLastCall();
146 this.manager.writeInternal(same(event2));
147 expectLastCall();
148 this.manager.commitAndClose();
149 expectLastCall();
150 replay(this.manager);
151
152 this.manager.write(event2);
153
154 verify(this.manager);
155 reset(this.manager);
156 this.manager.connectAndStart();
157 expectLastCall();
158 this.manager.writeInternal(same(event3));
159 expectLastCall();
160 this.manager.commitAndClose();
161 expectLastCall();
137 expectLastCall().andReturn(Boolean.TRUE);
138 replay(this.manager);
139
140 this.manager.write(event1);
141
142 verify(this.manager);
143 reset(this.manager);
144 this.manager.connectAndStart();
145 expectLastCall();
146 this.manager.writeInternal(same(event2));
147 expectLastCall();
148 this.manager.commitAndClose();
149 expectLastCall().andReturn(Boolean.TRUE);
150 replay(this.manager);
151
152 this.manager.write(event2);
153
154 verify(this.manager);
155 reset(this.manager);
156 this.manager.connectAndStart();
157 expectLastCall();
158 this.manager.writeInternal(same(event3));
159 expectLastCall();
160 this.manager.commitAndClose();
161 expectLastCall().andReturn(Boolean.TRUE);
162162 replay(this.manager);
163163
164164 this.manager.write(event3);
196196 this.manager.writeInternal(same(event4));
197197 expectLastCall();
198198 this.manager.commitAndClose();
199 expectLastCall();
199 expectLastCall().andReturn(Boolean.TRUE);
200200 replay(this.manager);
201201
202202 this.manager.write(event4);
231231 this.manager.writeInternal(same(event3));
232232 expectLastCall();
233233 this.manager.commitAndClose();
234 expectLastCall();
234 expectLastCall().andReturn(Boolean.TRUE);
235235 replay(this.manager);
236236
237237 this.manager.flush();
266266 this.manager.writeInternal(same(event3));
267267 expectLastCall();
268268 this.manager.commitAndClose();
269 expectLastCall();
269 expectLastCall().andReturn(Boolean.TRUE);
270270 this.manager.shutdownInternal();
271 expectLastCall();
271 expectLastCall().andReturn(Boolean.TRUE);
272272 replay(this.manager);
273273
274274 this.manager.shutdown();
7676 final Appender appender = context.getConfiguration().getAppender("databaseAppender");
7777 assertNotNull("The appender should not be null.", appender);
7878 assertTrue("The appender should be a JdbcAppender.", appender instanceof JdbcAppender);
79 ((JdbcAppender) appender).getManager().release();
79 ((JdbcAppender) appender).getManager().close();
8080 } finally {
8181 System.clearProperty(ConfigurationFactory.CONFIGURATION_FILE_PROPERTY);
8282 context.reconfigure();
8383 StatusLogger.getLogger().reset();
8484
85 Statement statement = null;
86 try {
87 statement = this.connection.createStatement();
85 try (Statement statement = this.connection.createStatement()) {
8886 statement.execute("SHUTDOWN");
89 } finally {
90 try {
91 if (statement != null) {
92 statement.close();
93 }
94 } catch (final SQLException ignore) {
95 /* */
96 }
9787 }
9888
9989 this.connection.close();
6161 final Appender appender = context.getConfiguration().getAppender("databaseAppender");
6262 assertNotNull("The appender should not be null.", appender);
6363 assertTrue("The appender should be a JpaAppender.", appender instanceof JpaAppender);
64 ((JpaAppender) appender).getManager().release();
64 ((JpaAppender) appender).getManager().close();
6565 } finally {
6666 System.clearProperty(ConfigurationFactory.CONFIGURATION_FILE_PROPERTY);
6767 context.reconfigure();
6868 StatusLogger.getLogger().reset();
6969
70 Statement statement = null;
71 try {
72 statement = this.connection.createStatement();
70 try (Statement statement = this.connection.createStatement();) {
7371 statement.execute("SHUTDOWN");
74 } finally {
75 try {
76 if (statement != null) {
77 statement.close();
78 }
79 } catch (final SQLException ignore) {
80 /* */
81 }
8272 }
8373
8474 this.connection.close();
3434 protected Connection setUpConnection() throws SQLException {
3535 final Connection connection = DriverManager.getConnection("jdbc:h2:mem:Log4j", USER_ID, PASSWORD);
3636
37 Statement statement = connection.createStatement();
38 statement.executeUpdate("CREATE TABLE jpaBaseLogEntry ( " +
39 "id INTEGER IDENTITY, eventDate DATETIME, level NVARCHAR(10), logger NVARCHAR(255), " +
40 "message NVARCHAR(1024), exception NVARCHAR(1048576)" +
41 " )");
42 statement.close();
37 try (Statement statement = connection.createStatement()) {
38 statement.executeUpdate("CREATE TABLE jpaBaseLogEntry ( "
39 + "id INTEGER IDENTITY, eventDate DATETIME, level NVARCHAR(10), logger NVARCHAR(255), "
40 + "message NVARCHAR(1024), exception NVARCHAR(1048576)" + " )");
41 }
4342
44 statement = connection.createStatement();
45 statement.executeUpdate("CREATE TABLE jpaBasicLogEntry ( " +
46 "id INTEGER IDENTITY, timemillis BIGINT, nanoTime BIGINT, level NVARCHAR(10), loggerName NVARCHAR(255), " +
47 "message NVARCHAR(1024), thrown NVARCHAR(1048576), contextMapJson NVARCHAR(1048576)," +
48 "loggerFQCN NVARCHAR(1024), contextStack NVARCHAR(1048576), marker NVARCHAR(255), source NVARCHAR(2048)," +
49 "threadId BIGINT, threadName NVARCHAR(255), threadPriority INTEGER" +
50 " )");
51 statement.close();
43 try (Statement statement = connection.createStatement()) {
44 statement.executeUpdate("CREATE TABLE jpaBasicLogEntry ( "
45 + "id INTEGER IDENTITY, timemillis BIGINT, nanoTime BIGINT, level NVARCHAR(10), loggerName NVARCHAR(255), "
46 + "message NVARCHAR(1024), thrown NVARCHAR(1048576), contextMapJson NVARCHAR(1048576),"
47 + "loggerFQCN NVARCHAR(1024), contextStack NVARCHAR(1048576), marker NVARCHAR(255), source NVARCHAR(2048),"
48 + "threadId BIGINT, threadName NVARCHAR(255), threadPriority INTEGER" + " )");
49 }
5250
5351 return connection;
5452 }
3838 protected Connection setUpConnection() throws SQLException {
3939 final Connection connection = DriverManager.getConnection("jdbc:hsqldb:mem:Log4j", USER_ID, PASSWORD);
4040
41 Statement statement = connection.createStatement();
42 statement.executeUpdate("CREATE TABLE jpaBaseLogEntry ( " +
43 "id INTEGER IDENTITY, eventDate DATETIME, level VARCHAR(10), logger VARCHAR(255), " +
44 "message VARCHAR(1024), exception VARCHAR(1048576)" +
45 " )");
46 statement.close();
41 try (Statement statement = connection.createStatement()) {
42 statement.executeUpdate("CREATE TABLE jpaBaseLogEntry ( "
43 + "id INTEGER IDENTITY, eventDate DATETIME, level VARCHAR(10), logger VARCHAR(255), "
44 + "message VARCHAR(1024), exception VARCHAR(1048576)" + " )");
45 }
4746
48 statement = connection.createStatement();
49 statement.executeUpdate("CREATE TABLE jpaBasicLogEntry ( " +
50 "id INTEGER IDENTITY, timemillis BIGINT, nanoTime BIGINT, level VARCHAR(10), loggerName VARCHAR(255), " +
51 "message VARCHAR(1024), thrown VARCHAR(1048576), contextMapJson VARCHAR(1048576)," +
52 "loggerFQCN VARCHAR(1024), contextStack VARCHAR(1048576), marker VARCHAR(255), source VARCHAR(2048)," +
53 "threadId BIGINT, threadName NVARCHAR(255), threadPriority INTEGER" +
54 " )");
55 statement.close();
47 try (Statement statement = connection.createStatement()) {
48 statement.executeUpdate("CREATE TABLE jpaBasicLogEntry ( "
49 + "id INTEGER IDENTITY, timemillis BIGINT, nanoTime BIGINT, level VARCHAR(10), loggerName VARCHAR(255), "
50 + "message VARCHAR(1024), thrown VARCHAR(1048576), contextMapJson VARCHAR(1048576),"
51 + "loggerFQCN VARCHAR(1024), contextStack VARCHAR(1048576), marker VARCHAR(255), source VARCHAR(2048),"
52 + "threadId BIGINT, threadName NVARCHAR(255), threadPriority INTEGER" + " )");
53 }
5654
5755 return connection;
5856 }
3333 import org.apache.logging.log4j.Level;
3434 import org.apache.logging.log4j.Marker;
3535 import org.apache.logging.log4j.ThreadContext;
36 import org.apache.logging.log4j.util.ReadOnlyStringMap;
3637 import org.apache.logging.log4j.core.LogEvent;
3738 import org.apache.logging.log4j.core.appender.db.jpa.converter.LevelAttributeConverter;
3839 import org.apache.logging.log4j.core.appender.db.jpa.converter.MessageAttributeConverter;
160161
161162 @Override
162163 @Transient
164 public ReadOnlyStringMap getContextData() {
165 return this.getWrappedEvent().getContextData();
166 }
167
168 @Override
169 @Transient
163170 public ThreadContext.ContextStack getContextStack() {
164171 return this.getWrappedEvent().getContextStack();
165172 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.appender.db.jpa.converter;
17
18 import org.apache.logging.log4j.util.SortedArrayStringMap;
19 import org.apache.logging.log4j.util.StringMap;
20 import org.junit.After;
21 import org.junit.Before;
22 import org.junit.Test;
23
24 import static org.junit.Assert.*;
25
26 public class ContextDataAttributeConverterTest {
27 private ContextDataAttributeConverter converter;
28
29 @Before
30 public void setUp() {
31 this.converter = new ContextDataAttributeConverter();
32 }
33
34 @After
35 public void tearDown() {
36
37 }
38
39 @Test
40 public void testConvertToDatabaseColumn01() {
41 final StringMap map = new SortedArrayStringMap();
42 map.putValue("test1", "another1");
43 map.putValue("key2", "value2");
44
45 assertEquals("The converted value is not correct.", map.toString(),
46 this.converter.convertToDatabaseColumn(map));
47 }
48
49 @Test
50 public void testConvertToDatabaseColumn02() {
51 final StringMap map = new SortedArrayStringMap();
52 map.putValue("someKey", "coolValue");
53 map.putValue("anotherKey", "testValue");
54 map.putValue("myKey", "yourValue");
55
56 assertEquals("The converted value is not correct.", map.toString(),
57 this.converter.convertToDatabaseColumn(map));
58 }
59
60 @Test
61 public void testConvertNullToDatabaseColumn() {
62 assertNull("The converted value should be null.", this.converter.convertToDatabaseColumn(null));
63 }
64
65 @Test(expected = UnsupportedOperationException.class)
66 public void testConvertToEntityAttribute() {
67 this.converter.convertToEntityAttribute(null);
68 }
69 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.appender.db.jpa.converter;
17
18 import org.apache.logging.log4j.util.ReadOnlyStringMap;
19 import org.apache.logging.log4j.util.SortedArrayStringMap;
20 import org.apache.logging.log4j.util.StringMap;
21 import org.junit.After;
22 import org.junit.Before;
23 import org.junit.Test;
24
25 import static org.junit.Assert.*;
26
27 public class ContextDataJsonAttributeConverterTest {
28 private ContextDataJsonAttributeConverter converter;
29
30 @Before
31 public void setUp() {
32 this.converter = new ContextDataJsonAttributeConverter();
33 }
34
35 @After
36 public void tearDown() {
37
38 }
39
40 @Test
41 public void testConvert01() {
42 final StringMap map = new SortedArrayStringMap();
43 map.putValue("test1", "another1");
44 map.putValue("key2", "value2");
45
46 final String converted = this.converter.convertToDatabaseColumn(map);
47
48 assertNotNull("The converted value should not be null.", converted);
49
50 final ReadOnlyStringMap reversed = this.converter.convertToEntityAttribute(converted);
51
52 assertNotNull("The reversed value should not be null.", reversed);
53 assertEquals("The reversed value is not correct.", map, reversed);
54 }
55
56 @Test
57 public void testConvert02() {
58 final StringMap map = new SortedArrayStringMap();
59 map.putValue("someKey", "coolValue");
60 map.putValue("anotherKey", "testValue");
61 map.putValue("myKey", "yourValue");
62
63 final String converted = this.converter.convertToDatabaseColumn(map);
64
65 assertNotNull("The converted value should not be null.", converted);
66
67 final ReadOnlyStringMap reversed = this.converter.convertToEntityAttribute(converted);
68
69 assertNotNull("The reversed value should not be null.", reversed);
70 assertEquals("The reversed value is not correct.", map, reversed);
71 }
72
73 @Test
74 public void testConvertNullToDatabaseColumn() {
75 assertNull("The converted value should be null.", this.converter.convertToDatabaseColumn(null));
76 }
77
78 @Test
79 public void testConvertNullOrBlankToEntityAttribute() {
80 assertNull("The converted attribute should be null (1).", this.converter.convertToEntityAttribute(null));
81 assertNull("The converted attribute should be null (2).", this.converter.convertToEntityAttribute(""));
82 }
83 }
1515 */
1616 package org.apache.logging.log4j.core.appender.db.jpa.converter;
1717
18 import static org.junit.Assert.assertEquals;
19 import static org.junit.Assert.assertNotNull;
20 import static org.junit.Assert.assertNull;
21
1822 import java.util.Arrays;
1923
2024 import org.apache.logging.log4j.ThreadContext;
25 import org.apache.logging.log4j.junit.ThreadContextStackRule;
2126 import org.apache.logging.log4j.spi.MutableThreadContextStack;
22 import org.junit.After;
2327 import org.junit.Before;
28 import org.junit.Rule;
2429 import org.junit.Test;
25
26 import static org.junit.Assert.*;
2730
2831 public class ContextStackJsonAttributeConverterTest {
2932 private ContextStackJsonAttributeConverter converter;
33
34 @Rule
35 public final ThreadContextStackRule threadContextRule = new ThreadContextStackRule();
3036
3137 @Before
3238 public void setUp() {
3339 this.converter = new ContextStackJsonAttributeConverter();
3440 }
3541
36 @After
37 public void tearDown() {
38
39 }
40
4142 @Test
4243 public void testConvert01() {
43 ThreadContext.clearStack();
4444 final ThreadContext.ContextStack stack = new MutableThreadContextStack(
4545 Arrays.asList("value1", "another2"));
4646
5858
5959 @Test
6060 public void testConvert02() {
61 ThreadContext.clearStack();
6261 final ThreadContext.ContextStack stack = new MutableThreadContextStack(
6362 Arrays.asList("key1", "value2", "my3"));
6463
6262
6363 @AfterClass
6464 public static void tearDownClass() {
65 jmsManager.release();
65 jmsManager.close();
6666 }
6767
6868 @Before
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16
17 package org.apache.logging.log4j.core.appender.mom.jeromq;
18
19 import java.util.List;
20 import java.util.concurrent.ExecutorService;
21 import java.util.concurrent.Executors;
22 import java.util.concurrent.Future;
23
24 import org.apache.logging.log4j.ThreadContext;
25 import org.apache.logging.log4j.core.Logger;
26 import org.apache.logging.log4j.junit.LoggerContextRule;
27 import org.junit.Assert;
28 import org.junit.ClassRule;
29 import org.junit.Test;
30
31 public class JeroMqAppenderTest {
32
33 @ClassRule
34 public static LoggerContextRule ctx = new LoggerContextRule("JeroMqAppenderTest.xml");
35
36 @Test(timeout = 10000)
37 public void testAppenderLifeCycle() throws Exception {
38 // do nothing to make sure the appender starts and stops without
39 // locking up resources.
40 Assert.assertNotNull(JeroMqManager.getContext());
41 }
42
43 @Test(timeout = 10000)
44 public void testClientServer() throws Exception {
45 final JeroMqAppender appender = ctx.getRequiredAppender("JeroMQAppender", JeroMqAppender.class);
46 final int expectedReceiveCount = 3;
47 final JeroMqTestClient client = new JeroMqTestClient(JeroMqManager.getContext(), "tcp://localhost:5556", expectedReceiveCount);
48 final ExecutorService executor = Executors.newSingleThreadExecutor();
49 try {
50 final Future<List<String>> future = executor.submit(client);
51 Thread.sleep(100);
52 final Logger logger = ctx.getLogger(getClass().getName());
53 appender.resetSendRcs();
54 logger.info("Hello");
55 logger.info("Again");
56 ThreadContext.put("foo", "bar");
57 logger.info("World");
58 final List<String> list = future.get();
59 Assert.assertEquals(expectedReceiveCount, appender.getSendRcTrue());
60 Assert.assertEquals(0, appender.getSendRcFalse());
61 Assert.assertEquals("Hello", list.get(0));
62 Assert.assertEquals("Again", list.get(1));
63 Assert.assertEquals("barWorld", list.get(2));
64 } finally {
65 executor.shutdown();
66 }
67 }
68
69 @Test(timeout = 10000)
70 public void testMultiThreadedServer() throws Exception {
71 final int nThreads = 10;
72 final JeroMqAppender appender = ctx.getRequiredAppender("JeroMQAppender", JeroMqAppender.class);
73 final int expectedReceiveCount = 2 * nThreads;
74 final JeroMqTestClient client = new JeroMqTestClient(JeroMqManager.getContext(), "tcp://localhost:5556",
75 expectedReceiveCount);
76 final ExecutorService executor = Executors.newSingleThreadExecutor();
77 try {
78 final Future<List<String>> future = executor.submit(client);
79 Thread.sleep(100);
80 final Logger logger = ctx.getLogger(getClass().getName());
81 appender.resetSendRcs();
82 final ExecutorService fixedThreadPool = Executors.newFixedThreadPool(nThreads);
83 for (int i = 0; i < 10.; i++) {
84 fixedThreadPool.submit(new Runnable() {
85 @Override
86 public void run() {
87 logger.info("Hello");
88 logger.info("Again");
89 }
90 });
91 }
92 final List<String> list = future.get();
93 Assert.assertEquals(expectedReceiveCount, appender.getSendRcTrue());
94 Assert.assertEquals(0, appender.getSendRcFalse());
95 int hello = 0;
96 int again = 0;
97 for (final String string : list) {
98 switch (string) {
99 case "Hello":
100 hello++;
101 break;
102 case "Again":
103 again++;
104 break;
105 default:
106 Assert.fail("Unexpected message: " + string);
107 }
108 }
109 Assert.assertEquals(nThreads, hello);
110 Assert.assertEquals(nThreads, again);
111 } finally {
112 executor.shutdown();
113 }
114 }
115
116 @Test(timeout = 10000)
117 public void testServerOnly() throws Exception {
118 final Logger logger = ctx.getLogger(getClass().getName());
119 final JeroMqAppender appender = ctx.getRequiredAppender("JeroMQAppender", JeroMqAppender.class);
120 appender.resetSendRcs();
121 logger.info("Hello");
122 logger.info("Again");
123 Assert.assertEquals(2, appender.getSendRcTrue());
124 Assert.assertEquals(0, appender.getSendRcFalse());
125 }
126 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16
17 package org.apache.logging.log4j.core.appender.mom.jeromq;
18
19 import java.util.List;
20 import java.util.concurrent.ExecutorService;
21 import java.util.concurrent.Executors;
22 import java.util.concurrent.Future;
23 import java.util.concurrent.TimeUnit;
24
25 import org.apache.logging.log4j.ThreadContext;
26 import org.apache.logging.log4j.core.Logger;
27 import org.apache.logging.log4j.core.util.ExecutorServices;
28 import org.apache.logging.log4j.junit.LoggerContextRule;
29 import org.junit.Assert;
30 import org.junit.ClassRule;
31 import org.junit.Test;
32
33 public class JeroMqAppenderTest {
34
35 private static final String ENDPOINT = "tcp://localhost:5556";
36
37 private static final String APPENDER_NAME = "JeroMQAppender";
38
39 private static final int DEFAULT_TIMEOUT_MILLIS = 60000;
40
41 @ClassRule
42 public static LoggerContextRule ctx = new LoggerContextRule("JeroMqAppenderTest.xml");
43
44 @Test(timeout = DEFAULT_TIMEOUT_MILLIS)
45 public void testAppenderLifeCycle() throws Exception {
46 // do nothing to make sure the appender starts and stops without
47 // locking up resources.
48 Assert.assertNotNull(JeroMqManager.getContext());
49 }
50
51 @Test(timeout = DEFAULT_TIMEOUT_MILLIS)
52 public void testClientServer() throws Exception {
53 final JeroMqAppender appender = ctx.getRequiredAppender(APPENDER_NAME, JeroMqAppender.class);
54 final int expectedReceiveCount = 3;
55 final JeroMqTestClient client = new JeroMqTestClient(JeroMqManager.getContext(), ENDPOINT, expectedReceiveCount);
56 final ExecutorService executor = Executors.newSingleThreadExecutor();
57 try {
58 final Future<List<String>> future = executor.submit(client);
59 Thread.sleep(100);
60 final Logger logger = ctx.getLogger(getClass().getName());
61 appender.resetSendRcs();
62 logger.info("Hello");
63 logger.info("Again");
64 ThreadContext.put("foo", "bar");
65 logger.info("World");
66 final List<String> list = future.get();
67 Assert.assertEquals(expectedReceiveCount, appender.getSendRcTrue());
68 Assert.assertEquals(0, appender.getSendRcFalse());
69 Assert.assertEquals("Hello", list.get(0));
70 Assert.assertEquals("Again", list.get(1));
71 Assert.assertEquals("barWorld", list.get(2));
72 } finally {
73 executor.shutdown();
74 }
75 }
76
77 @Test(timeout = DEFAULT_TIMEOUT_MILLIS)
78 public void testMultiThreadedServer() throws Exception {
79 final int nThreads = 10;
80 final JeroMqAppender appender = ctx.getRequiredAppender(APPENDER_NAME, JeroMqAppender.class);
81 final int expectedReceiveCount = 2 * nThreads;
82 final JeroMqTestClient client = new JeroMqTestClient(JeroMqManager.getContext(), ENDPOINT,
83 expectedReceiveCount);
84 final ExecutorService executor = Executors.newSingleThreadExecutor();
85 try {
86 final Future<List<String>> future = executor.submit(client);
87 Thread.sleep(100);
88 final Logger logger = ctx.getLogger(getClass().getName());
89 appender.resetSendRcs();
90 final ExecutorService fixedThreadPool = Executors.newFixedThreadPool(nThreads);
91 for (int i = 0; i < 10.; i++) {
92 fixedThreadPool.submit(new Runnable() {
93 @Override
94 public void run() {
95 logger.info("Hello");
96 logger.info("Again");
97 }
98 });
99 }
100 final List<String> list = future.get();
101 Assert.assertEquals(expectedReceiveCount, appender.getSendRcTrue());
102 Assert.assertEquals(0, appender.getSendRcFalse());
103 int hello = 0;
104 int again = 0;
105 for (final String string : list) {
106 switch (string) {
107 case "Hello":
108 hello++;
109 break;
110 case "Again":
111 again++;
112 break;
113 default:
114 Assert.fail("Unexpected message: " + string);
115 }
116 }
117 Assert.assertEquals(nThreads, hello);
118 Assert.assertEquals(nThreads, again);
119 } finally {
120 ExecutorServices.shutdown(executor, DEFAULT_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS,
121 JeroMqAppenderTest.class.getSimpleName());
122 }
123 }
124
125 @Test(timeout = DEFAULT_TIMEOUT_MILLIS)
126 public void testServerOnly() throws Exception {
127 final Logger logger = ctx.getLogger(getClass().getName());
128 final JeroMqAppender appender = ctx.getRequiredAppender(APPENDER_NAME, JeroMqAppender.class);
129 appender.resetSendRcs();
130 logger.info("Hello");
131 logger.info("Again");
132 Assert.assertEquals(2, appender.getSendRcTrue());
133 Assert.assertEquals(0, appender.getSendRcFalse());
134 }
135 }
1919 import static org.junit.Assert.*;
2020
2121 /**
22 *
22 * Tests {@link FileSize}.
2323 */
2424 public class FileSizeTest {
2525
2626 private final static long EXPECTED = 10 * 1024;
27
2728 @Test
2829 public void testFileSize() throws Exception {
29
3030 long value = FileSize.parse("10KB", 0);
3131 assertTrue("unexpected value " + value, value == EXPECTED);
3232 value = FileSize.parse("10 KB", 0);
1515 */
1616 package org.apache.logging.log4j.core.appender.rolling;
1717
18 import static org.junit.Assert.assertEquals;
1819 import static org.junit.Assert.assertTrue;
1920
2021 import java.io.ByteArrayInputStream;
22 import java.io.File;
2123 import java.io.InputStream;
2224 import java.nio.file.Files;
2325 import java.nio.file.Path;
2426 import java.nio.file.Paths;
27 import java.nio.file.StandardCopyOption;
28 import java.util.Arrays;
2529
2630 import org.apache.logging.log4j.core.config.Configuration;
2731 import org.apache.logging.log4j.core.config.DefaultConfiguration;
2832 import org.apache.logging.log4j.core.layout.PatternLayout;
2933 import org.apache.logging.log4j.core.util.datetime.FastDateFormat;
30 import org.apache.logging.log4j.junit.CleanFiles;
34 import org.apache.logging.log4j.junit.CleanFolders;
35 import org.junit.Assert;
3136 import org.junit.Rule;
3237 import org.junit.Test;
3338
3439 /**
35 *
40 * Tests {@link OnStartupTriggeringPolicy}.
3641 */
42 //@Ignore
3743 public class OnStartupTriggeringPolicyTest {
3844
39 private static final String TARGET_FILE = "target/rollOnStartup/testfile";
40 private static final String TARGET_PATTERN = "target/rollOnStartup/test1-%d{MM-dd-yyyy}-%i.log";
41 private static final String ROLLED_FILE_PREFIX = "target/rollOnStartup/test1-";
45 private static final String TARGET_FOLDER = "target/rollOnStartup";
46 private static final String TARGET_FILE = TARGET_FOLDER + "/testfile";
47 private static final String TARGET_PATTERN = TARGET_FOLDER + "/test1-%d{MM-dd-yyyy}-%i.log";
48 private static final String ROLLED_FILE_PREFIX = TARGET_FOLDER + "/test1-";
4249 private static final String ROLLED_FILE_SUFFIX = "-1.log";
4350 private static final String TEST_DATA = "Hello world!";
4451 private static final FastDateFormat formatter = FastDateFormat.getInstance("MM-dd-yyyy");
4552
46 //@Rule
47 //public CleanFiles rule = new CleanFolders("target/rollOnStartup");
53 @Rule
54 public CleanFolders rule = new CleanFolders("target/rollOnStartup");
4855
4956 @Test
5057 public void testPolicy() throws Exception {
5562 final String expectedDate = formatter.format(timeStamp);
5663 final String rolledFileName = ROLLED_FILE_PREFIX + expectedDate + ROLLED_FILE_SUFFIX;
5764 final Path rolled = Paths.get(rolledFileName);
65 final long copied;
5866 try (final InputStream is = new ByteArrayInputStream(TEST_DATA.getBytes("UTF-8"))) {
59 Files.copy(is, target);
67 copied = Files.copy(is, target, StandardCopyOption.REPLACE_EXISTING);
6068 }
6169 final long size = Files.size(target);
6270 assertTrue(size > 0);
71 assertEquals(copied, size);
6372
64 target.toFile().setLastModified(timeStamp);
73 Assert.assertTrue(target.toFile().setLastModified(timeStamp));
6574 final PatternLayout layout = PatternLayout.newBuilder().withPattern("%msg").withConfiguration(configuration)
6675 .build();
6776 final RolloverStrategy strategy = DefaultRolloverStrategy.createStrategy(null, null, null, "0", null, true,
6877 configuration);
6978 final OnStartupTriggeringPolicy policy = OnStartupTriggeringPolicy.createPolicy(1);
70 final RollingFileManager manager = RollingFileManager.getFileManager(TARGET_FILE, TARGET_PATTERN, true, false,
71 policy, strategy, null, layout, 8192, true);
72 try {
79 try (final RollingFileManager manager = RollingFileManager.getFileManager(TARGET_FILE, TARGET_PATTERN, true, false,
80 policy, strategy, null, layout, 8192, true, false, configuration)) {
7381 manager.initialize();
74 assertTrue(Files.exists(target));
75 assertTrue(Files.size(target) == 0);
76 assertTrue(Files.exists(rolled));
77 assertTrue(Files.size(rolled) == size);
78 } finally {
79 manager.release();
82 final String files = Arrays.toString(new File(TARGET_FOLDER).listFiles());
83 assertTrue(target.toString() + ", files = " + files, Files.exists(target));
84 assertEquals(target.toString(), 0, Files.size(target));
85 assertTrue("Missing: " + rolled.toString() + ", files on disk = " + files, Files.exists(rolled));
86 assertEquals(rolled.toString(), size, Files.size(rolled));
8087 }
8188 }
8289
5656 public LoggerContextRule loggerContextRule;
5757
5858 public RandomRollingAppenderOnStartupTest(final String configFile) {
59 this.loggerContextRule = new LoggerContextRule(configFile);
59 this.loggerContextRule = LoggerContextRule.createShutdownTimeoutLoggerContextRule(configFile);
6060 }
6161
6262 @Before
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.appender.rolling;
17
18 import static org.apache.logging.log4j.hamcrest.Descriptors.that;
19 import static org.apache.logging.log4j.hamcrest.FileMatchers.hasName;
20 import static org.hamcrest.Matchers.endsWith;
21 import static org.junit.Assert.assertEquals;
22 import static org.junit.Assert.assertNotEquals;
23 import static org.junit.Assert.assertNotNull;
24 import static org.junit.Assert.assertTrue;
25
26 import java.io.File;
27 import java.nio.file.FileSystems;
28 import java.nio.file.Files;
29 import java.nio.file.Path;
30 import java.util.Calendar;
31
32 import org.apache.logging.log4j.Logger;
33 import org.apache.logging.log4j.core.appender.RollingFileAppender;
34 import org.apache.logging.log4j.core.util.CronExpression;
35 import org.apache.logging.log4j.junit.LoggerContextRule;
36 import org.apache.logging.log4j.status.StatusLogger;
37 import org.hamcrest.Matcher;
38 import org.junit.BeforeClass;
39 import org.junit.Rule;
40 import org.junit.Test;
41 import org.junit.rules.RuleChain;
42
43 /**
44 * This test currently takes about a minute to run.
45 */
46 public class RollingAppenderCronOnceADayTest {
47
48 private static final int CRON_DELAY = 10;
49 private static final String UTF_8 = "UTF-8";
50 private static final String CONFIG = "log4j-rolling-cron-once-a-day.xml";
51 private static final String CONFIG_TARGET = "log4j-rolling-cron-once-a-day-target.xml";
52 private static final String TARGET = "target";
53 private static final String DIR = TARGET + "/rolling-cron-once-a-day";
54 private static final String FILE = DIR + "/rollingtest.log";
55 private static final String TARGET_TEST_CLASSES = TARGET + "/test-classes";
56
57 private static String cronExpression;
58 private static long remainingTime;
59
60 @BeforeClass
61 public static void beforeClass() throws Exception {
62 final Path src = FileSystems.getDefault().getPath(TARGET_TEST_CLASSES, CONFIG);
63 String content = new String(Files.readAllBytes(src), UTF_8);
64 final Calendar cal = Calendar.getInstance();
65 cal.add(Calendar.SECOND, CRON_DELAY);
66 remainingTime = cal.getTimeInMillis() - System.currentTimeMillis();
67 cronExpression = String.format("%d %d %d * * ?",
68 cal.get(Calendar.SECOND),
69 cal.get(Calendar.MINUTE),
70 cal.get(Calendar.HOUR_OF_DAY));
71 content = content.replace("@CRON_EXPR@", cronExpression);
72 Files.write(FileSystems.getDefault()
73 .getPath(TARGET_TEST_CLASSES, CONFIG_TARGET), content.getBytes(UTF_8));
74 StatusLogger.getLogger().debug("Cron expression will be " + cronExpression + " in " + remainingTime + "ms");
75 }
76
77 private final LoggerContextRule loggerContextRule = new LoggerContextRule(CONFIG_TARGET);
78
79 @Rule
80 public RuleChain chain = loggerContextRule.withCleanFoldersRule(DIR);
81
82 @Test
83 public void testAppender() throws Exception {
84 // TODO Is there a better way to test than putting the thread to sleep all over the place?
85 final Logger logger = loggerContextRule.getLogger();
86 final File file = new File(FILE);
87 assertTrue("Log file does not exist", file.exists());
88 logger.debug("This is test message number 1, waiting for rolling");
89
90 final RollingFileAppender app = (RollingFileAppender) loggerContextRule.getLoggerContext().getConfiguration().getAppender("RollingFile");
91 final TriggeringPolicy policy = app.getManager().getTriggeringPolicy();
92 assertNotNull("No triggering policy", policy);
93 assertTrue("Incorrect policy type", policy instanceof CronTriggeringPolicy);
94 final CronExpression expression = ((CronTriggeringPolicy) policy).getCronExpression();
95 assertEquals("Incorrect cron expresion", cronExpression, expression.getCronExpression());
96 logger.debug("Cron expression will be {}", expression.getCronExpression());
97
98 // force a reconfiguration
99 for (int i = 1; i <= 20; ++i) {
100 logger.debug("Adding first event {}", i);
101 }
102
103 Thread.sleep(remainingTime);
104 final File dir = new File(DIR);
105 assertTrue("Directory not created", dir.exists() && dir.listFiles().length > 0);
106
107 for (int i = 1; i < 5; i++) {
108 logger.debug("Adding some more event {}", i);
109 Thread.sleep(1000);
110 }
111 final Matcher<File> hasGzippedFile = hasName(that(endsWith(".gz")));
112 int count = 0;
113 final File[] files = dir.listFiles();
114 for (final File generatedFile : files) {
115 if (hasGzippedFile.matches(generatedFile)) {
116 count++;
117 }
118 }
119
120 assertNotEquals("No compressed files found", 0, count);
121 assertEquals("Multiple files found" , 1, count);
122 }
123
124 }
3333 import org.apache.logging.log4j.Logger;
3434 import org.apache.logging.log4j.core.appender.RollingFileAppender;
3535 import org.apache.logging.log4j.core.util.CronExpression;
36 import org.apache.logging.log4j.core.util.datetime.FastDateFormat;
3736 import org.apache.logging.log4j.junit.LoggerContextRule;
3837 import org.hamcrest.Matcher;
3938 import org.junit.Rule;
4847 private static final String CONFIG = "log4j-rolling-cron.xml";
4948 private static final String DIR = "target/rolling-cron";
5049 private static final String FILE = "target/rolling-cron/rollingtest.log";
51 private static final FastDateFormat formatter = FastDateFormat.getInstance("MM-dd-yy-HH-mm-ss");
5250
53 private final LoggerContextRule loggerContextRule = new LoggerContextRule(CONFIG);
51 private final LoggerContextRule loggerContextRule = LoggerContextRule.createShutdownTimeoutLoggerContextRule(CONFIG);
5452
5553 @Rule
5654 public RuleChain chain = loggerContextRule.withCleanFoldersRule(DIR);
5755
5856 @Test
5957 public void testAppender() throws Exception {
58 // TODO Is there a better way to test than putting the thread to sleep all over the place?
6059 final Logger logger = loggerContextRule.getLogger();
61 File file = new File(FILE);
60 final File file = new File(FILE);
6261 assertTrue("Log file does not exist", file.exists());
6362 logger.debug("This is test message number 1");
6463 Thread.sleep(2500);
7473 succeeded = true;
7574 break;
7675 }
77 logger.debug("Adding additional event " + i);
76 logger.debug("Sleeping #" + i);
7877 Thread.sleep(100); // Allow time for rollover to complete
7978 }
8079 if (!succeeded) {
8180 final File[] files = dir.listFiles();
82 for (File dirFile : files) {
81 for (final File dirFile : files) {
8382 logger.error("Found file: " + dirFile.getPath());
8483 }
8584 fail("No compressed files found");
9493 logger.debug("Adding new event {}", i);
9594 }
9695 Thread.sleep(1000);
97 final RollingFileAppender app = (RollingFileAppender) loggerContextRule.getContext().getConfiguration().getAppender("RollingFile");
96 final RollingFileAppender app = (RollingFileAppender) loggerContextRule.getLoggerContext().getConfiguration().getAppender("RollingFile");
9897 final TriggeringPolicy policy = app.getManager().getTriggeringPolicy();
9998 assertNotNull("No triggering policy", policy);
10099 assertTrue("Incorrect policy type", policy instanceof CronTriggeringPolicy);
3636 private static final String CONFIG = "log4j-rolling-with-custom-delete.xml";
3737 private static final String DIR = "target/rolling-with-delete/test";
3838
39 private final LoggerContextRule loggerContextRule = new LoggerContextRule(CONFIG);
39 private final LoggerContextRule loggerContextRule = LoggerContextRule.createShutdownTimeoutLoggerContextRule(CONFIG);
4040
4141 @Rule
4242 public RuleChain chain = loggerContextRule.withCleanFoldersRule(DIR);
4646 private static final String CONFIG = "log4j-rolling-with-custom-delete-accum-count1.xml";
4747 private static final String DIR = "target/rolling-with-delete-accum-count1/test";
4848
49 private final LoggerContextRule loggerContextRule = new LoggerContextRule(CONFIG);
49 private final LoggerContextRule loggerContextRule = LoggerContextRule.createShutdownTimeoutLoggerContextRule(CONFIG);
5050
5151 @Rule
5252 public RuleChain chain = loggerContextRule.withCleanFoldersRule(DIR);
4646 private static final String CONFIG = "log4j-rolling-with-custom-delete-accum-count2.xml";
4747 private static final String DIR = "target/rolling-with-delete-accum-count2/test";
4848
49 private final LoggerContextRule loggerContextRule = new LoggerContextRule(CONFIG);
49 private final LoggerContextRule loggerContextRule = LoggerContextRule.createShutdownTimeoutLoggerContextRule(CONFIG);
5050
5151 @Rule
5252 public RuleChain chain = loggerContextRule.withCleanFoldersRule(DIR);
3636 private static final String CONFIG = "log4j-rolling-with-custom-delete-accum-size.xml";
3737 private static final String DIR = "target/rolling-with-delete-accum-size/test";
3838
39 private final LoggerContextRule loggerContextRule = new LoggerContextRule(CONFIG);
39 private final LoggerContextRule loggerContextRule = LoggerContextRule.createShutdownTimeoutLoggerContextRule(CONFIG);
4040
4141 @Rule
4242 public RuleChain chain = loggerContextRule.withCleanFoldersRule(DIR);
4343 private static final String CONFIG = "log4j-rolling-with-custom-delete-maxdepth.xml";
4444 private static final String DIR = "target/rolling-with-delete-depth/test";
4545
46 private final LoggerContextRule loggerContextRule = new LoggerContextRule(CONFIG);
46 private final LoggerContextRule loggerContextRule = LoggerContextRule.createShutdownTimeoutLoggerContextRule(CONFIG);
4747
4848 @Rule
4949 public RuleChain chain = loggerContextRule.withCleanFoldersRule(DIR);
4545 private static final String CONFIG = "log4j-rolling-with-custom-delete-nested.xml";
4646 private static final String DIR = "target/rolling-with-delete-nested/test";
4747
48 private final LoggerContextRule loggerContextRule = new LoggerContextRule(CONFIG);
48 private final LoggerContextRule loggerContextRule = LoggerContextRule.createShutdownTimeoutLoggerContextRule(CONFIG);
4949
5050 @Rule
5151 public RuleChain chain = loggerContextRule.withCleanFoldersRule(DIR);
3535 private static final String CONFIG = "log4j-rolling-with-custom-delete-script-fri13th.xml";
3636 private static final String DIR = "target/rolling-with-delete-script-fri13th/test";
3737
38 private final LoggerContextRule loggerContextRule = new LoggerContextRule(CONFIG);
38 private final LoggerContextRule loggerContextRule = LoggerContextRule.createShutdownTimeoutLoggerContextRule(CONFIG);
3939
4040 @Rule
4141 public RuleChain chain = loggerContextRule.withCleanFoldersRule(DIR);
3333 private static final String CONFIG = "log4j-rolling-with-custom-delete-script.xml";
3434 private static final String DIR = "target/rolling-with-delete-script/test";
3535
36 private final LoggerContextRule loggerContextRule = new LoggerContextRule(CONFIG);
36 private final LoggerContextRule loggerContextRule = LoggerContextRule.createShutdownTimeoutLoggerContextRule(CONFIG);
3737
3838 @Rule
3939 public RuleChain chain = loggerContextRule.withCleanFoldersRule(DIR);
5757
5858 public RollingAppenderNoUnconditionalDeleteTest(final String configFile, final String dir) {
5959 this.directory = new File(dir);
60 this.loggerContextRule = new LoggerContextRule(configFile);
60 this.loggerContextRule = LoggerContextRule.createShutdownTimeoutLoggerContextRule(configFile);
6161 deleteDir();
6262 deleteDirParent();
6363 }
5656 public LoggerContextRule loggerContextRule;
5757
5858 public RollingAppenderOnStartupTest(final String configFile) {
59 this.loggerContextRule = new LoggerContextRule(configFile);
59 this.loggerContextRule = LoggerContextRule.createShutdownTimeoutLoggerContextRule(configFile);
6060 }
6161
6262 @Before
2828 import java.io.File;
2929 import java.io.FileInputStream;
3030 import java.nio.charset.Charset;
31 import java.nio.file.Files;
32 import java.nio.file.Path;
33 import java.nio.file.Paths;
3134 import java.util.Arrays;
3235 import java.util.Collection;
36 import java.util.concurrent.TimeUnit;
3337
3438 import org.apache.commons.compress.compressors.CompressorException;
3539 import org.apache.commons.compress.compressors.CompressorInputStream;
3640 import org.apache.commons.compress.compressors.CompressorStreamFactory;
3741 import org.apache.commons.compress.utils.IOUtils;
3842 import org.apache.logging.log4j.Logger;
43 import org.apache.logging.log4j.core.appender.RollingFileAppender;
3944 import org.apache.logging.log4j.core.util.Closer;
4045 import org.apache.logging.log4j.junit.LoggerContextRule;
46 import org.junit.Assert;
4147 import org.junit.Before;
4248 import org.junit.Rule;
4349 import org.junit.Test;
6066
6167 private Logger logger;
6268
63 @Parameterized.Parameters(name = "{0} \u2192 {1}")
69 private final boolean createOnDemand;
70
71 @Parameterized.Parameters(name = "{0} \u2192 {1} (createOnDemand = {2})")
6472 public static Collection<Object[]> data() {
6573 return Arrays.asList(new Object[][] { //
6674 // @formatter:off
67 {"log4j-rolling-gz.xml", ".gz"}, //
68 {"log4j-rolling-zip.xml", ".zip"}, //
75 {"log4j-rolling-gz-lazy.xml", ".gz", true},
76 {"log4j-rolling-gz.xml", ".gz", false},
77 {"log4j-rolling-zip-lazy.xml", ".zip", true},
78 {"log4j-rolling-zip.xml", ".zip", false},
6979 // Apache Commons Compress
70 {"log4j-rolling-bzip2.xml", ".bz2"}, //
71 {"log4j-rolling-deflate.xml", ".deflate"}, //
72 {"log4j-rolling-pack200.xml", ".pack200"}, //
73 {"log4j-rolling-xz.xml", ".xz"}, //
80 {"log4j-rolling-bzip2-lazy.xml", ".bz2", true},
81 {"log4j-rolling-bzip2.xml", ".bz2", false},
82 {"log4j-rolling-deflate-lazy.xml", ".deflate", true},
83 {"log4j-rolling-deflate.xml", ".deflate", false},
84 {"log4j-rolling-pack200-lazy.xml", ".pack200", true},
85 {"log4j-rolling-pack200.xml", ".pack200", false},
86 {"log4j-rolling-xz-lazy.xml", ".xz", true},
87 {"log4j-rolling-xz.xml", ".xz", false},
7488 });
7589 // @formatter:on
7690 }
7791
78 private LoggerContextRule loggerContextRule;
92 private final LoggerContextRule loggerContextRule;
7993
80 public RollingAppenderSizeTest(final String configFile, final String fileExtension) {
94 public RollingAppenderSizeTest(final String configFile, final String fileExtension, final boolean createOnDemand) {
8195 this.fileExtension = fileExtension;
82 this.loggerContextRule = new LoggerContextRule(configFile);
96 this.createOnDemand = createOnDemand;
97 this.loggerContextRule = LoggerContextRule.createShutdownTimeoutLoggerContextRule(configFile);
8398 this.chain = loggerContextRule.withCleanFoldersRule(DIR);
8499 }
85100
89104 }
90105
91106 @Test
107 public void testIsCreateOnDemand() {
108 final RollingFileAppender rfAppender = loggerContextRule.getRequiredAppender("RollingFile",
109 RollingFileAppender.class);
110 final RollingFileManager manager = rfAppender.getManager();
111 Assert.assertNotNull(manager);
112 Assert.assertEquals(createOnDemand, manager.isCreateOnDemand());
113 }
114
115 @Test
92116 public void testAppender() throws Exception {
117 final Path path = Paths.get(DIR, "rollingtest.log");
118 if (Files.exists(path) && createOnDemand) {
119 Assert.fail(String.format("Unexpected file: %s (%s bytes)", path, Files.getAttribute(path, "size")));
120 }
93121 for (int i = 0; i < 100; ++i) {
94122 logger.debug("This is test message number " + i);
95123 }
96124 try {
97125 Thread.sleep(100);
98 } catch (InterruptedException ie) {
126 } catch (final InterruptedException ie) {
99127 // Ignore the error.
100128 }
101129
109137 if (ext == null || DefaultRolloverStrategy.FileExtensions.ZIP == ext
110138 || DefaultRolloverStrategy.FileExtensions.PACK200 == ext) {
111139 return; // Apache Commons Compress cannot deflate zip? TODO test decompressing these formats
140 }
141 // Stop the context to make sure all files are compressed and closed. Trying to remedy failures in CI builds.
142 if (loggerContextRule.getLoggerContext().stop(30, TimeUnit.SECONDS)) {
143 System.err.println("Could not stop cleanly " + loggerContextRule + " for " + this);
112144 }
113145 for (final File file : files) {
114146 if (file.getName().endsWith(fileExtension)) {
3737 */
3838 public class RollingAppenderTimeAndSizeTest {
3939
40 private static final String CONFIG = "log4j-rolling3.xml";
41
4042 private static final String DIR = "target/rolling3/test";
4143
42 public static LoggerContextRule loggerContextRule = new LoggerContextRule("log4j-rolling3.xml");
44 public static LoggerContextRule loggerContextRule = LoggerContextRule.createShutdownTimeoutLoggerContextRule(CONFIG);
4345
4446 @Rule
4547 public RuleChain chain = loggerContextRule.withCleanFoldersRule(DIR);
3939 private static final String CONFIG = "log4j-rolling2.xml";
4040 private static final String DIR = "target/rolling2";
4141
42 private final LoggerContextRule loggerContextRule = new LoggerContextRule(CONFIG);
42 private final LoggerContextRule loggerContextRule = LoggerContextRule.createShutdownTimeoutLoggerContextRule(CONFIG);
4343
4444 @Rule
4545 public RuleChain chain = loggerContextRule.withCleanFoldersRule(DIR);
3939 private static final String CONFIG = "log4j-rolling4.xml";
4040 private static final String DIR = "target/rolling4";
4141
42 private Logger logger = LogManager.getLogger(RollingAppenderUncompressedTest.class.getName());
42 private final Logger logger = LogManager.getLogger(RollingAppenderUncompressedTest.class.getName());
4343
4444 @ClassRule
4545 public static CleanFolders rule = new CleanFolders(CONFIG);
2121 import org.apache.logging.log4j.core.LoggerContext;
2222 import org.apache.logging.log4j.core.appender.RollingFileAppender;
2323 import org.apache.logging.log4j.core.config.Configuration;
24 import org.junit.Assert;
2425 import org.junit.Test;
2526
2627 public class RollingFileAppenderAccessTest {
3132 * @throws IOException
3233 */
3334 @Test
34 public void testAccessManager() throws IOException {
35 final LoggerContext ctx = LoggerContext.getContext(false);
36 final Configuration config = ctx.getConfiguration();
37 final File file = File.createTempFile("RollingFileAppenderAccessTest", ".tmp");
38 file.deleteOnExit();
39 final RollingFileAppender appender = RollingFileAppender.createAppender(file.getCanonicalPath(), "FilePattern",
40 null, "Name", null, null, null, OnStartupTriggeringPolicy.createPolicy(1), null, null, null, null, null,
41 null, config);
42 final RollingFileManager manager = appender.getManager();
43 // Since the RolloverStrategy and TriggeringPolicy are immutable, we could also use generics to type their
44 // access.
45 manager.getRolloverStrategy();
46 manager.getTriggeringPolicy();
35 public void testAccessManagerWithBuilder() throws IOException {
36 try (final LoggerContext ctx = LoggerContext.getContext(false)) {
37 final Configuration config = ctx.getConfiguration();
38 final File file = File.createTempFile("RollingFileAppenderAccessTest", ".tmp");
39 file.deleteOnExit();
40 // @formatter:off
41 final RollingFileAppender appender = RollingFileAppender.newBuilder()
42 .withFileName(file.getCanonicalPath())
43 .withFilePattern("FilePattern")
44 .withName("Name")
45 .withPolicy(OnStartupTriggeringPolicy.createPolicy(1))
46 .withConfiguration(config)
47 .build();
48 // @formatter:on
49 final RollingFileManager manager = appender.getManager();
50 // Since the RolloverStrategy and TriggeringPolicy are immutable, we could also use generics to type their
51 // access.
52 Assert.assertNotNull(manager.getRolloverStrategy());
53 Assert.assertNotNull(manager.getTriggeringPolicy());
54 }
55 }
56
57 /**
58 * Not a real test, just make sure we can compile access to the typed manager.
59 *
60 * @throws IOException
61 */
62 @Test
63 public void testAccessManagerWithStrings() throws IOException {
64 try (final LoggerContext ctx = LoggerContext.getContext(false)) {
65 final Configuration config = ctx.getConfiguration();
66 final File file = File.createTempFile("RollingFileAppenderAccessTest", ".tmp");
67 file.deleteOnExit();
68 final RollingFileAppender appender = RollingFileAppender.createAppender(file.getCanonicalPath(),
69 "FilePattern", null, "Name", null, null, null, OnStartupTriggeringPolicy.createPolicy(1), null,
70 null, null, null, null, null, config);
71 final RollingFileManager manager = appender.getManager();
72 // Since the RolloverStrategy and TriggeringPolicy are immutable, we could also use generics to type their
73 // access.
74 Assert.assertNotNull(manager.getRolloverStrategy());
75 Assert.assertNotNull(manager.getTriggeringPolicy());
76 }
4777 }
4878 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.appender.rolling;
17
18 import org.apache.logging.log4j.core.appender.RollingFileAppender;
19 import org.junit.Assert;
20 import org.junit.Test;
21
22 public class RollingFileAppenderBuilderTest {
23
24 /**
25 * Tests https://issues.apache.org/jira/browse/LOG4J2-1620
26 */
27 @Test
28 public void testDefaultImmediateFlush() {
29 Assert.assertTrue(RollingFileAppender.newBuilder().isImmediateFlush());
30 }
31 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.appender.rolling;
17
18 import org.apache.logging.log4j.core.appender.RollingFileAppender;
19 import org.apache.logging.log4j.core.config.DefaultConfiguration;
20 import org.junit.Assert;
21 import org.junit.Test;
22
23 public class RollingFileAppenderLayoutTest {
24
25 @Test
26 public void testDefaultLayout() throws Exception {
27 // @formatter:off
28 Assert.assertNotNull(RollingFileAppender.newBuilder()
29 .withName(RollingFileAppenderLayoutTest.class.getName())
30 .withConfiguration(new DefaultConfiguration())
31 .withFileName("log.txt")
32 .withFilePattern("FilePattern")
33 .withPolicy(OnStartupTriggeringPolicy.createPolicy(1))
34 .withCreateOnDemand(true) // no need to clutter up test folder with another file
35 .build().getLayout());
36 // @formatter:on
37 }
38 }
3838 */
3939 public class RollingRandomAccessFileManagerHeaderFooterTest {
4040
41 private static final String CONFIG = "RollingRandomAccessFileAppenderHeaderFooterTest.xml";
4142 private static final String DIR = "target/RollingRandomAccessFileAppenderHeaderFooterTest/";
4243 private static final String LOGFILE = "target/RollingRandomAccessFileAppenderHeaderFooterTest.log";
4344
44 public LoggerContextRule loggerContextRule = new LoggerContextRule("RollingRandomAccessFileAppenderHeaderFooterTest.xml");
45 public LoggerContextRule loggerContextRule = LoggerContextRule.createShutdownTimeoutLoggerContextRule(CONFIG);
4546
4647 @Rule
4748 public RuleChain chain = loggerContextRule.withCleanFoldersRule(DIR);
5050 final File file = File.createTempFile("log4j2", "test");
5151 file.deleteOnExit();
5252 try (final RandomAccessFile raf = new RandomAccessFile(file, "rw")) {
53 final OutputStream os = NullOutputStream.NULL_OUTPUT_STREAM;
53 final OutputStream os = NullOutputStream.getInstance();
5454 final boolean append = false;
5555 final boolean flushNow = false;
5656 final long triggerSize = Long.MAX_VALUE;
5757 final long time = System.currentTimeMillis();
5858 final TriggeringPolicy triggerPolicy = new SizeBasedTriggeringPolicy(triggerSize);
5959 final RolloverStrategy rolloverStrategy = null;
60 final RollingRandomAccessFileManager manager = new RollingRandomAccessFileManager(raf, file.getName(),
61 Strings.EMPTY, os, append, flushNow, RollingRandomAccessFileManager.DEFAULT_BUFFER_SIZE,
62 triggerSize, time, triggerPolicy, rolloverStrategy, null, null, true);
60 final RollingRandomAccessFileManager manager = new RollingRandomAccessFileManager(null, raf,
61 file.getName(), Strings.EMPTY, os, append, flushNow,
62 RollingRandomAccessFileManager.DEFAULT_BUFFER_SIZE, triggerSize, time, triggerPolicy, rolloverStrategy, null, null, true);
6363
6464 final int size = RollingRandomAccessFileManager.DEFAULT_BUFFER_SIZE * 3;
6565 final byte[] data = new byte[size];
7979 final File file = File.createTempFile("log4j2", "test");
8080 file.deleteOnExit();
8181 try (final RandomAccessFile raf = new RandomAccessFile(file, "rw")) {
82 final OutputStream os = NullOutputStream.NULL_OUTPUT_STREAM;
82 final OutputStream os = NullOutputStream.getInstance();
8383 final boolean append = false;
8484 final boolean flushNow = false;
8585 final long triggerSize = 0;
8686 final long time = System.currentTimeMillis();
8787 final TriggeringPolicy triggerPolicy = new SizeBasedTriggeringPolicy(triggerSize);
8888 final RolloverStrategy rolloverStrategy = null;
89 final RollingRandomAccessFileManager manager = new RollingRandomAccessFileManager(raf, file.getName(),
90 Strings.EMPTY, os, append, flushNow, RollingRandomAccessFileManager.DEFAULT_BUFFER_SIZE,
91 triggerSize, time, triggerPolicy, rolloverStrategy, null, null, true);
89 final RollingRandomAccessFileManager manager = new RollingRandomAccessFileManager(null, raf,
90 file.getName(), Strings.EMPTY, os, append, flushNow,
91 RollingRandomAccessFileManager.DEFAULT_BUFFER_SIZE, triggerSize, time, triggerPolicy, rolloverStrategy, null, null, true);
9292
9393 final int size = RollingRandomAccessFileManager.DEFAULT_BUFFER_SIZE * 3 + 1;
9494 final byte[] data = new byte[size];
105105 final File file = File.createTempFile("log4j2", "test");
106106 file.deleteOnExit();
107107 try (final RandomAccessFile raf = new RandomAccessFile(file, "rw")) {
108 final OutputStream os = NullOutputStream.NULL_OUTPUT_STREAM;
108 final OutputStream os = NullOutputStream.getInstance();
109109 final boolean append = false;
110110 final boolean flushNow = false;
111111 final long triggerSize = 0;
114114 final int bufferSize = 4 * 1024;
115115 assertNotEquals(bufferSize, RollingRandomAccessFileManager.DEFAULT_BUFFER_SIZE);
116116 final RolloverStrategy rolloverStrategy = null;
117 final RollingRandomAccessFileManager manager = new RollingRandomAccessFileManager(raf, file.getName(),
118 Strings.EMPTY, os, append, flushNow, bufferSize, triggerSize, time, triggerPolicy, rolloverStrategy,
119 null, null, true);
117 final RollingRandomAccessFileManager manager = new RollingRandomAccessFileManager(null, raf,
118 file.getName(), Strings.EMPTY, os, append, flushNow, bufferSize, triggerSize, time, triggerPolicy,
119 rolloverStrategy, null, null, true);
120120
121121 // check the resulting buffer size is what was requested
122122 assertEquals(bufferSize, manager.getBufferSize());
148148 //
149149 file.getAbsolutePath(), Strings.EMPTY, isAppend, immediateFlush,
150150 RollingRandomAccessFileManager.DEFAULT_BUFFER_SIZE, new SizeBasedTriggeringPolicy(Long.MAX_VALUE), //
151 null, null, null);
151 null, null, null, null);
152152 manager.write(bytes, 0, bytes.length, immediateFlush);
153153 final int expected = bytes.length * 2;
154154 assertThat("appended, not overwritten", file, hasLength(expected));
170170 //
171171 file.getAbsolutePath(), Strings.EMPTY, isAppend, true,
172172 RollingRandomAccessFileManager.DEFAULT_BUFFER_SIZE, new SizeBasedTriggeringPolicy(Long.MAX_VALUE), //
173 null, null, null);
173 null, null, null, null);
174174 assertTrue(manager.getFileTime() < expectedMax);
175175 assertTrue(manager.getFileTime() >= expectedMin);
176176 }
188188 //
189189 file.getAbsolutePath(), Strings.EMPTY, isAppend, true,
190190 RollingRandomAccessFileManager.DEFAULT_BUFFER_SIZE, new SizeBasedTriggeringPolicy(Long.MAX_VALUE), //
191 null, null, null);
191 null, null, null, null);
192192 assertThat(file, lastModified(equalTo(manager.getFileTime())));
193193 }
194194
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.appender.routing;
17
18 import static org.junit.Assert.assertNotNull;
19 import static org.junit.Assert.assertTrue;
20
21 import java.util.List;
22 import java.util.Map;
23 import java.util.concurrent.ConcurrentMap;
24
25 import org.apache.logging.log4j.Marker;
26 import org.apache.logging.log4j.MarkerManager;
27 import org.apache.logging.log4j.core.LogEvent;
28 import org.apache.logging.log4j.core.Logger;
29 import org.apache.logging.log4j.core.config.AppenderControl;
30 import org.apache.logging.log4j.junit.LoggerContextRule;
31 import org.apache.logging.log4j.test.appender.ListAppender;
32 import org.junit.Assert;
33 import org.junit.Rule;
34 import org.junit.Test;
35 import org.junit.runner.RunWith;
36 import org.junit.runners.Parameterized;
37
38 /**
39 *
40 */
41 @RunWith(Parameterized.class)
42 public class DefaultRouteScriptAppenderTest {
43
44 @Parameterized.Parameters(name = "{0} {1}")
45 public static Object[][] getParameters() {
46 // @formatter:off
47 return new Object[][] {
48 { "log4j-routing-default-route-script-groovy.xml", false },
49 { "log4j-routing-default-route-script-javascript.xml", false },
50 { "log4j-routing-script-staticvars-javascript.xml", true },
51 { "log4j-routing-script-staticvars-groovy.xml", true },
52 };
53 // @formatter:on
54 }
55
56 @Rule
57 public final LoggerContextRule loggerContextRule;
58
59 private final boolean expectBindingEntries;
60
61 public DefaultRouteScriptAppenderTest(final String configLocation, final boolean expectBindingEntries) {
62 this.loggerContextRule = new LoggerContextRule(configLocation);
63 this.expectBindingEntries = expectBindingEntries;
64 }
65
66 private void checkStaticVars() {
67 final RoutingAppender routingAppender = getRoutingAppender();
68 final ConcurrentMap<Object, Object> map = routingAppender.getScriptStaticVariables();
69 if (expectBindingEntries) {
70 Assert.assertEquals("TestValue2", map.get("TestKey"));
71 Assert.assertEquals("HEXDUMP", map.get("MarkerName"));
72 }
73 }
74
75 private ListAppender getListAppender() {
76 final String key = "Service2";
77 final RoutingAppender routingAppender = getRoutingAppender();
78 Assert.assertTrue(routingAppender.isStarted());
79 final Map<String, AppenderControl> appenders = routingAppender.getAppenders();
80 final AppenderControl appenderControl = appenders.get(key);
81 assertNotNull("No appender control generated for '" + key + "'; appenders = " + appenders, appenderControl);
82 final ListAppender listAppender = (ListAppender) appenderControl.getAppender();
83 return listAppender;
84 }
85
86 private RoutingAppender getRoutingAppender() {
87 return loggerContextRule.getRequiredAppender("Routing", RoutingAppender.class);
88 }
89
90 private void logAndCheck() {
91 final Marker marker = MarkerManager.getMarker("HEXDUMP");
92 final Logger logger = loggerContextRule.getLogger(DefaultRouteScriptAppenderTest.class);
93 logger.error("Hello");
94 final ListAppender listAppender = getListAppender();
95 final List<LogEvent> list = listAppender.getEvents();
96 assertNotNull("No events generated", list);
97 assertTrue("Incorrect number of events. Expected 1, got " + list.size(), list.size() == 1);
98 logger.error("World");
99 assertTrue("Incorrect number of events. Expected 2, got " + list.size(), list.size() == 2);
100 logger.error(marker, "DEADBEEF");
101 assertTrue("Incorrect number of events. Expected 3, got " + list.size(), list.size() == 3);
102 }
103
104 @Test(expected = AssertionError.class)
105 public void testAppenderAbsence() {
106 loggerContextRule.getListAppender("List1");
107 }
108
109 @Test
110 public void testListAppenderPresence() {
111 // No appender until an event is routed, even thought we initialized the default route on startup.
112 Assert.assertNull("No appender control generated", getRoutingAppender().getAppenders().get("Service2"));
113 }
114
115 @Test
116 public void testNoPurgePolicy() {
117 // No PurgePolicy in this test
118 Assert.assertNull("Unexpected PurgePolicy", getRoutingAppender().getPurgePolicy());
119 }
120
121 @Test
122 public void testNoRewritePolicy() {
123 // No RewritePolicy in this test
124 Assert.assertNull("Unexpected RewritePolicy", getRoutingAppender().getRewritePolicy());
125 }
126
127 @Test
128 public void testRoutingAppenderDefaultRouteKey() {
129 final RoutingAppender routingAppender = getRoutingAppender();
130 Assert.assertNotNull(routingAppender.getDefaultRouteScript());
131 Assert.assertNotNull(routingAppender.getDefaultRoute());
132 Assert.assertEquals("Service2", routingAppender.getDefaultRoute().getKey());
133 }
134
135 @Test
136 public void testRoutingAppenderPresence() {
137 getRoutingAppender();
138 }
139
140 @Test
141 public void testRoutingPresence1() {
142 logAndCheck();
143 checkStaticVars();
144 }
145
146 @Test
147 public void testRoutingPresence2() {
148 logAndCheck();
149 checkStaticVars();
150 }
151 }
3636 private static final String CONFIG = "log4j-routing2.json";
3737 private static final String LOG_FILENAME = "target/rolling1/rollingtest-Unknown.log";
3838
39 private LoggerContextRule loggerContextRule = new LoggerContextRule(CONFIG);
39 private final LoggerContextRule loggerContextRule = new LoggerContextRule(CONFIG);
4040
4141 @Rule
4242 public RuleChain rules = loggerContextRule.withCleanFilesRule(LOG_FILENAME);
3636 private static final String CONFIG = "log4j-routing.json";
3737 private static final String LOG_FILENAME = "target/rolling1/rollingtest-Unknown.log";
3838
39 private LoggerContextRule loggerContextRule = new LoggerContextRule(CONFIG);
39 private final LoggerContextRule loggerContextRule = new LoggerContextRule(CONFIG);
4040
4141 @Rule
4242 public RuleChain rules = loggerContextRule.withCleanFilesRule(LOG_FILENAME);
4343
4444 private ListAppender app;
4545
46 private LoggerContextRule loggerContextRule = new LoggerContextRule(CONFIG);
46 private final LoggerContextRule loggerContextRule = new LoggerContextRule(CONFIG);
4747
4848 @Rule
4949 public RuleChain rules = loggerContextRule.withCleanFilesRule(UNKNOWN_LOG_FILE, ALERT_LOG_FILE, ACTIVITY_LOG_FILE);
5656 @After
5757 public void tearDown() throws Exception {
5858 this.app.clear();
59 this.loggerContextRule.getContext().stop();
59 this.loggerContextRule.getLoggerContext().stop();
6060 }
6161
6262 @Test
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.appender.routing;
17
18 import static org.junit.Assert.assertNotNull;
19 import static org.junit.Assert.assertTrue;
20
21 import java.util.List;
22 import java.util.Map;
23 import java.util.concurrent.ConcurrentHashMap;
24 import java.util.concurrent.ConcurrentMap;
25
26 import org.apache.logging.log4j.Level;
27 import org.apache.logging.log4j.Marker;
28 import org.apache.logging.log4j.MarkerManager;
29 import org.apache.logging.log4j.core.LogEvent;
30 import org.apache.logging.log4j.core.Logger;
31 import org.apache.logging.log4j.core.config.AppenderControl;
32 import org.apache.logging.log4j.core.impl.DefaultLogEventFactory;
33 import org.apache.logging.log4j.junit.LoggerContextRule;
34 import org.apache.logging.log4j.test.appender.ListAppender;
35 import org.junit.Assert;
36 import org.junit.Rule;
37 import org.junit.Test;
38 import org.junit.runner.RunWith;
39 import org.junit.runners.Parameterized;
40
41 /**
42 *
43 */
44 @RunWith(Parameterized.class)
45 public class RoutesScriptAppenderTest {
46
47 @Parameterized.Parameters(name = "{0} {1}")
48 public static Object[][] getParameters() {
49 // @formatter:off
50 return new Object[][] {
51 { "log4j-routing-routes-script-groovy.xml", false },
52 { "log4j-routing-routes-script-javascript.xml", false },
53 { "log4j-routing-script-staticvars-javascript.xml", true },
54 { "log4j-routing-script-staticvars-groovy.xml", true },
55 };
56 // @formatter:on
57 }
58
59 @Rule
60 public final LoggerContextRule loggerContextRule;
61
62 private final boolean expectBindingEntries;
63
64 public RoutesScriptAppenderTest(final String configLocation, final boolean expectBindingEntries) {
65 this.loggerContextRule = new LoggerContextRule(configLocation);
66 this.expectBindingEntries = expectBindingEntries;
67 }
68
69 private void checkStaticVars() {
70 final RoutingAppender routingAppender = getRoutingAppender();
71 final ConcurrentMap<Object, Object> map = routingAppender.getScriptStaticVariables();
72 if (expectBindingEntries) {
73 Assert.assertEquals("TestValue2", map.get("TestKey"));
74 Assert.assertEquals("HEXDUMP", map.get("MarkerName"));
75 }
76 }
77 private ListAppender getListAppender() {
78 final String key = "Service2";
79 final RoutingAppender routingAppender = getRoutingAppender();
80 Assert.assertTrue(routingAppender.isStarted());
81 final Map<String, AppenderControl> appenders = routingAppender.getAppenders();
82 final AppenderControl appenderControl = appenders.get(key);
83 assertNotNull("No appender control generated for '" + key + "'; appenders = " + appenders, appenderControl);
84 final ListAppender listAppender = (ListAppender) appenderControl.getAppender();
85 return listAppender;
86 }
87
88 private RoutingAppender getRoutingAppender() {
89 return loggerContextRule.getRequiredAppender("Routing", RoutingAppender.class);
90 }
91
92 private void logAndCheck() {
93 final Marker marker = MarkerManager.getMarker("HEXDUMP");
94 final Logger logger = loggerContextRule.getLogger(RoutesScriptAppenderTest.class);
95 logger.error("Hello");
96 final ListAppender listAppender = getListAppender();
97 final List<LogEvent> list = listAppender.getEvents();
98 assertNotNull("No events generated", list);
99 assertTrue("Incorrect number of events. Expected 1, got " + list.size(), list.size() == 1);
100 logger.error("World");
101 assertTrue("Incorrect number of events. Expected 2, got " + list.size(), list.size() == 2);
102 logger.error(marker, "DEADBEEF");
103 assertTrue("Incorrect number of events. Expected 3, got " + list.size(), list.size() == 3);
104 }
105
106 @Test(expected = AssertionError.class)
107 public void testAppenderAbsence() {
108 loggerContextRule.getListAppender("List1");
109 }
110
111 @Test
112 public void testListAppenderPresence() {
113 // No appender until an event is routed, even thought we initialized the default route on startup.
114 Assert.assertNull("No appender control generated", getRoutingAppender().getAppenders().get("Service2"));
115 }
116
117 @Test
118 public void testNoPurgePolicy() {
119 // No PurgePolicy in this test
120 Assert.assertNull("Unexpected PurgePolicy", getRoutingAppender().getPurgePolicy());
121 }
122
123 @Test
124 public void testNoRewritePolicy() {
125 // No RewritePolicy in this test
126 Assert.assertNull("Unexpected RewritePolicy", getRoutingAppender().getRewritePolicy());
127 }
128
129 @Test
130 public void testRoutingAppenderRoutes() {
131 final RoutingAppender routingAppender = getRoutingAppender();
132 Assert.assertEquals(expectBindingEntries, routingAppender.getDefaultRouteScript() != null);
133 Assert.assertEquals(expectBindingEntries, routingAppender.getDefaultRoute() != null);
134 final Routes routes = routingAppender.getRoutes();
135 Assert.assertNotNull(routes);
136 Assert.assertNotNull(routes.getPatternScript());
137 final LogEvent logEvent = DefaultLogEventFactory.getInstance().createEvent("", null, "", Level.ERROR, null,
138 null, null);
139 Assert.assertEquals("Service2", routes.getPattern(logEvent, new ConcurrentHashMap<>()));
140 }
141
142 @Test
143 public void testRoutingAppenderPresence() {
144 getRoutingAppender();
145 }
146
147 @Test
148 public void testRoutingPresence1() {
149 logAndCheck();
150 checkStaticVars();
151 }
152
153 @Test
154 public void testRoutingPresence2() {
155 logAndCheck();
156 checkStaticVars();
157 }
158 }
4242
4343 private ListAppender app;
4444
45 private LoggerContextRule loggerContextRule = new LoggerContextRule(CONFIG);
45 private final LoggerContextRule loggerContextRule = new LoggerContextRule(CONFIG);
4646
4747 @Rule
4848 public RuleChain rules = loggerContextRule.withCleanFilesRule(UNKNOWN_LOG_FILE, ALERT_LOG_FILE, ACTIVITY_LOG_FILE);
5555 @After
5656 public void tearDown() throws Exception {
5757 this.app.clear();
58 this.loggerContextRule.getContext().stop();
58 this.loggerContextRule.getLoggerContext().stop();
5959 }
6060
6161 @Test
3434 import org.junit.rules.RuleChain;
3535
3636 /**
37 * Testing Routing appender purge facilities
37 * Tests Routing appender purge facilities
3838 */
3939 public class RoutingAppenderWithPurgingTest {
4040 private static final String CONFIG = "log4j-routing-purge.xml";
4545 private static final String MANUAL_LOG_FILE2 = "target/routing-purge-manual/routingtest-2.log";
4646 private static final String MANUAL_LOG_FILE3 = "target/routing-purge-manual/routingtest-3.log";
4747
48
4948 private ListAppender app;
5049 private RoutingAppender routingAppenderIdle;
5150 private RoutingAppender routingAppenderIdleWithHangingAppender;
5251 private RoutingAppender routingAppenderManual;
5352
54 private LoggerContextRule loggerContextRule = new LoggerContextRule(CONFIG);
53 private final LoggerContextRule loggerContextRule = new LoggerContextRule(CONFIG);
5554
5655 @Rule
5756 public RuleChain chain = loggerContextRule.withCleanFilesRule(IDLE_LOG_FILE1, IDLE_LOG_FILE2, IDLE_LOG_FILE3,
7069 @After
7170 public void tearDown() throws Exception {
7271 this.app.clear();
73 this.loggerContextRule.getContext().stop();
72 this.loggerContextRule.getLoggerContext().stop();
7473 }
7574
7675 @Test(timeout = 5000)
104103
105104 assertEquals("Incorrect number of appenders with IdlePurgePolicy.", 1, routingAppenderIdle.getAppenders().size());
106105 assertEquals("Incorrect number of appenders with manual purge.", 0, routingAppenderManual.getAppenders().size());
106
107 msg = new StructuredDataMessage("5", "This is a test 5", "Service");
108 EventLogger.logEvent(msg);
109
110 assertEquals("Incorrect number of appenders with manual purge.", 1, routingAppenderManual.getAppenders().size());
111
112 routingAppenderManual.deleteAppender("5");
113 routingAppenderManual.deleteAppender("5");
114
115 assertEquals("Incorrect number of appenders with manual purge.", 0, routingAppenderManual.getAppenders().size());
107116 }
108117
118
109119 private void assertFileExistance(final String... files) {
110 for (final String file : files) {
111 assertTrue("File should exist - " + file + " file ", new File(file).exists());
112 }
120 for (final String file : files) {
121 assertTrue("File should exist - " + file + " file ", new File(file).exists());
122 }
113123 }
114124 }
2525 import org.apache.logging.log4j.core.LogEvent;
2626 import org.apache.logging.log4j.junit.LoggerContextRule;
2727 import org.apache.logging.log4j.message.StructuredDataMessage;
28 import org.apache.logging.log4j.test.appender.ListAppender;
29 import org.junit.After;
30 import org.junit.Before;
3128 import org.junit.Rule;
3229 import org.junit.Test;
3330 import org.junit.rules.RuleChain;
3835 public class RoutingDefaultAppenderTest {
3936 private static final String LOG_FILE = "target/routing1/routingtest.log";
4037
41 private ListAppender app;
42
43 private LoggerContextRule loggerContextRule = new LoggerContextRule("log4j-routing3.xml");
38 private final LoggerContextRule loggerContextRule = new LoggerContextRule("log4j-routing3.xml");
4439
4540 @Rule
4641 public RuleChain rules = loggerContextRule.withCleanFilesRule(LOG_FILE);
47
48 @Before
49 public void setUp() throws Exception {
50 app = this.loggerContextRule.getListAppender("List");
51 }
52
53 @After
54 public void tearDown() throws Exception {
55 if (app != null) {
56 app.clear();
57 }
58 this.loggerContextRule.getContext().stop();
59 }
6042
6143 @Test
6244 public void routingTest() {
6345 StructuredDataMessage msg = new StructuredDataMessage("Test", "This is a test", "Service");
6446 EventLogger.logEvent(msg);
65 final List<LogEvent> list = app.getEvents();
47 final List<LogEvent> list = loggerContextRule.getListAppender("List").getEvents();
6648 assertNotNull("No events generated", list);
6749 assertTrue("Incorrect number of events. Expected 1, got " + list.size(), list.size() == 1);
6850 msg = new StructuredDataMessage("Test", "This is a test", "Alert");
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.async;
17
18 import java.io.BufferedReader;
19 import java.io.File;
20 import java.io.FileReader;
21 import java.io.IOException;
22
23 import org.apache.logging.log4j.LogManager;
24 import org.apache.logging.log4j.Logger;
25 import org.apache.logging.log4j.ThreadContext;
26 import org.apache.logging.log4j.ThreadContextAccess;
27 import org.apache.logging.log4j.ThreadContextTestAccess;
28 import org.apache.logging.log4j.core.CoreLoggerContexts;
29 import org.apache.logging.log4j.core.config.ConfigurationFactory;
30 import org.apache.logging.log4j.core.jmx.RingBufferAdmin;
31 import org.apache.logging.log4j.core.util.Constants;
32 import org.apache.logging.log4j.spi.DefaultThreadContextMap;
33 import org.apache.logging.log4j.spi.LoggerContext;
34 import org.apache.logging.log4j.util.Unbox;
35 import org.junit.AfterClass;
36 import org.junit.BeforeClass;
37 import org.junit.Test;
38
39 import static org.junit.Assert.*;
40
41 public abstract class AbstractAsyncThreadContextTestBase {
42
43 private final static int LINE_COUNT = 130;
44
45 @BeforeClass
46 public static void beforeClass() {
47 System.setProperty("AsyncLogger.RingBufferSize", "128"); // minimum ringbuffer size
48 System.setProperty("AsyncLoggerConfig.RingBufferSize", "128"); // minimum ringbuffer size
49 }
50
51 @AfterClass
52 public static void afterClass() {
53 System.clearProperty("AsyncLogger.RingBufferSize");
54 System.clearProperty("AsyncLoggerConfig.RingBufferSize");
55 System.clearProperty(Constants.LOG4J_CONTEXT_SELECTOR);
56 System.clearProperty(ConfigurationFactory.CONFIGURATION_FILE_PROPERTY);
57 System.clearProperty("log4j2.garbagefree.threadContextMap");
58 System.clearProperty("log4j2.is.webapp");
59 System.clearProperty("log4j2.threadContextMap");
60 }
61
62 enum Mode {
63 ALL_ASYNC, MIXED, BOTH_ALL_ASYNC_AND_MIXED;
64
65 void initSelector() {
66 if (this == ALL_ASYNC || this == BOTH_ALL_ASYNC_AND_MIXED) {
67 System.setProperty(Constants.LOG4J_CONTEXT_SELECTOR, AsyncLoggerContextSelector.class.getName());
68 } else {
69 System.clearProperty(Constants.LOG4J_CONTEXT_SELECTOR);
70 }
71 }
72
73 void initConfigFile() {
74 // NOTICE: PLEASE DON'T REFACTOR: keep "file" local variable for confirmation in debugger.
75 final String file = this == ALL_ASYNC //
76 ? "AsyncLoggerThreadContextTest.xml" //
77 : "AsyncLoggerConfigThreadContextTest.xml";
78 System.setProperty(ConfigurationFactory.CONFIGURATION_FILE_PROPERTY, file);
79 }
80 }
81
82 enum ContextImpl {
83 WEBAPP, GARBAGE_FREE, COPY_ON_WRITE;
84
85 void init() {
86 System.clearProperty("log4j2.threadContextMap");
87 final String PACKAGE = "org.apache.logging.log4j.spi.";
88 System.setProperty("log4j2.threadContextMap", PACKAGE + implClassSimpleName());
89 ThreadContextTestAccess.init();
90 }
91
92 public String implClassSimpleName() {
93 switch (this) {
94 case WEBAPP:
95 return DefaultThreadContextMap.class.getSimpleName();
96 case GARBAGE_FREE:
97 return "GarbageFreeSortedArrayThreadContextMap";
98 case COPY_ON_WRITE:
99 return "CopyOnWriteSortedArrayThreadContextMap";
100 }
101 throw new IllegalStateException("Unknown state " + this);
102 }
103 }
104
105 private final ContextImpl contextImpl;
106 private final Mode asyncMode;
107
108 public AbstractAsyncThreadContextTestBase(final ContextImpl contextImpl, final Mode asyncMode) {
109 this.contextImpl = contextImpl;
110 this.asyncMode = asyncMode;
111
112 asyncMode.initSelector();
113 asyncMode.initConfigFile();
114
115 contextImpl.init();
116 }
117
118 @Test
119 public void testAsyncLogWritesToLog() throws Exception {
120 final File[] files = new File[] {
121 new File("target", "AsyncLoggerTest.log"), //
122 new File("target", "SynchronousContextTest.log"), //
123 new File("target", "AsyncLoggerAndAsyncAppenderTest.log"), //
124 new File("target", "AsyncAppenderContextTest.log"), //
125 };
126 for (final File f : files) {
127 f.delete();
128 }
129
130 ThreadContext.push("stackvalue");
131 ThreadContext.put("KEY", "mapvalue");
132
133 final Logger log = LogManager.getLogger("com.foo.Bar");
134 final LoggerContext loggerContext = LogManager.getContext(false);
135 final String loggerContextName = loggerContext.getClass().getSimpleName();
136 RingBufferAdmin ring;
137 if (loggerContext instanceof AsyncLoggerContext) {
138 ring = ((AsyncLoggerContext) loggerContext).createRingBufferAdmin();
139 } else {
140 ring = ((AsyncLoggerConfig) ((org.apache.logging.log4j.core.Logger) log).get()).createRingBufferAdmin("");
141 }
142
143 for (int i = 0; i < LINE_COUNT; i++) {
144 while (i >= 128 && ring.getRemainingCapacity() == 0) { // buffer may be full
145 Thread.sleep(1);
146 }
147 if ((i & 1) == 1) {
148 ThreadContext.put("count", String.valueOf(i));
149 } else {
150 ThreadContext.remove("count");
151 }
152 final String contextmap = ThreadContextAccess.getThreadContextMap().getClass().getSimpleName();
153 log.info("{} {} {} i={}", contextImpl, contextmap, loggerContextName, Unbox.box(i));
154 }
155 ThreadContext.pop();
156 CoreLoggerContexts.stopLoggerContext(false, files[0]); // stop async thread
157
158 checkResult(files[0], loggerContextName);
159 if (asyncMode == Mode.MIXED || asyncMode == Mode.BOTH_ALL_ASYNC_AND_MIXED) {
160 for (int i = 1; i < files.length; i++) {
161 checkResult(files[i], loggerContextName);
162 }
163 }
164 LogManager.shutdown();
165 }
166
167 private void checkResult(final File file, final String loggerContextName) throws IOException {
168 final String contextDesc = contextImpl + " " + contextImpl.implClassSimpleName() + " " + loggerContextName;
169 try (final BufferedReader reader = new BufferedReader(new FileReader(file))) {
170 String expect;
171 for (int i = 0; i < LINE_COUNT; i++) {
172 final String line = reader.readLine();
173 if ((i & 1) == 1) {
174 expect = "INFO c.f.Bar mapvalue [stackvalue] {KEY=mapvalue, configProp=configValue, configProp2=configValue2, count=" + i + "} "
175 + contextDesc + " i=" + i;
176 } else {
177 expect = "INFO c.f.Bar mapvalue [stackvalue] {KEY=mapvalue, configProp=configValue, configProp2=configValue2} " + contextDesc + " i=" + i;
178 }
179 assertEquals(file.getName() + ": line " + i, expect, line);
180 }
181 final String noMoreLines = reader.readLine();
182 assertNull("done", noMoreLines);
183 } finally {
184 file.delete();
185 }
186 }
187 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.async;
17
18 import org.apache.logging.log4j.LogManager;
19 import org.apache.logging.log4j.Logger;
20
21 class AsyncLoggerClassLoadDeadlock {
22 static {
23 final Logger log = LogManager.getLogger("com.foo.bar.deadlock");
24 final Exception e = new Exception();
25 // the key to reproducing the problem is to fill up the ring buffer so that
26 // log.info call will block on ring buffer as well
27 for (int i = 0; i < AsyncLoggerClassLoadDeadlockTest.RING_BUFFER_SIZE * 2; ++i) {
28 log.info("clinit", e);
29 }
30 }
31 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.async;
17
18 import org.apache.logging.log4j.core.config.ConfigurationFactory;
19 import org.junit.BeforeClass;
20 import org.junit.Test;
21
22 import static org.junit.Assert.assertNotNull;
23
24 /**
25 * Test class loading deadlock condition from the LOG4J2-1457
26 */
27 public class AsyncLoggerClassLoadDeadlockTest {
28
29 static final int RING_BUFFER_SIZE = 128;
30
31 @BeforeClass
32 public static void beforeClass() {
33 System.setProperty("Log4jContextSelector", "org.apache.logging.log4j.core.async.AsyncLoggerContextSelector");
34 System.setProperty("AsyncLogger.RingBufferSize", String.valueOf(RING_BUFFER_SIZE));
35 System.setProperty(ConfigurationFactory.CONFIGURATION_FILE_PROPERTY, "AsyncLoggerConsoleTest.xml");
36 }
37
38 @Test(timeout = 30000)
39 public void testClassLoaderDeadlock() throws Exception {
40 //touch the class so static init will be called
41 final AsyncLoggerClassLoadDeadlock temp = new AsyncLoggerClassLoadDeadlock();
42 assertNotNull(temp);
43 }
44 }
4747 final String msg = "Additive logging: 2 for the price of 1!";
4848 log.info(msg);
4949 CoreLoggerContexts.stopLoggerContext(file); // stop async thread
50
50
5151 final BufferedReader reader = new BufferedReader(new FileReader(file));
5252 final String line1 = reader.readLine();
5353 final String line2 = reader.readLine();
6161 final String location = "testAdditivity";
6262 assertTrue("location", line1.contains(location) || line2.contains(location));
6363 }
64
64
6565 @Test
6666 public void testIncludeLocationDefaultsToFalse() {
67 final LoggerConfig rootLoggerConfig =
67 final LoggerConfig rootLoggerConfig =
6868 AsyncLoggerConfig.RootLogger.createLogger(
6969 null, "INFO", null, new AppenderRef[0], null, new DefaultConfiguration(), null);
7070 assertFalse("Include location should default to false for async logggers",
7171 rootLoggerConfig.isIncludeLocation());
72
72
7373 final LoggerConfig loggerConfig =
7474 AsyncLoggerConfig.createLogger(
7575 null, "INFO", "com.foo.Bar", null, new AppenderRef[0], null, new DefaultConfiguration(),
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.async;
17
18 // Note: the different ThreadContextMap implementations cannot be parameterized:
19 // ThreadContext initialization will result in static final fields being set in various components.
20 // To use a different ThreadContextMap, the test needs to be run in a new JVM.
21 public class AsyncLoggerConfigThreadContextCopyOnWriteTest extends AbstractAsyncThreadContextTestBase {
22 public AsyncLoggerConfigThreadContextCopyOnWriteTest() {
23 super(ContextImpl.COPY_ON_WRITE, Mode.MIXED);
24 }
25 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.async;
17
18 // Note: the different ThreadContextMap implementations cannot be parameterized:
19 // ThreadContext initialization will result in static final fields being set in various components.
20 // To use a different ThreadContextMap, the test needs to be run in a new JVM.
21 public class AsyncLoggerConfigThreadContextDefaultTest extends AbstractAsyncThreadContextTestBase {
22 public AsyncLoggerConfigThreadContextDefaultTest() {
23 super(ContextImpl.WEBAPP, Mode.MIXED);
24 }
25 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.async;
17
18 // Note: the different ThreadContextMap implementations cannot be parameterized:
19 // ThreadContext initialization will result in static final fields being set in various components.
20 // To use a different ThreadContextMap, the test needs to be run in a new JVM.
21 public class AsyncLoggerConfigThreadContextGarbageFreeTest extends AbstractAsyncThreadContextTestBase {
22 public AsyncLoggerConfigThreadContextGarbageFreeTest() {
23 super(ContextImpl.GARBAGE_FREE, Mode.MIXED);
24 }
25 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.async;
17
18 import java.util.Arrays;
19 import java.util.Collection;
20
21 import org.junit.runner.RunWith;
22 import org.junit.runners.Parameterized;
23
24 // Note: the different ThreadContextMap implementations cannot be parameterized:
25 // ThreadContext initialization will result in static final fields being set in various components.
26 // To use a different ThreadContextMap, the test needs to be run in a new JVM.
27 @RunWith(Parameterized.class)
28 public class AsyncLoggerThreadContextCopyOnWriteTest extends AbstractAsyncThreadContextTestBase {
29 @Parameterized.Parameters
30 public static Collection<Object[]> data() {
31 return Arrays.asList(new Object[][] {
32 { ContextImpl.COPY_ON_WRITE, Mode.ALL_ASYNC},
33 { ContextImpl.COPY_ON_WRITE, Mode.BOTH_ALL_ASYNC_AND_MIXED}
34 });
35 }
36 public AsyncLoggerThreadContextCopyOnWriteTest(final ContextImpl contextImpl, final Mode asyncMode) {
37 super(contextImpl, asyncMode);
38 }
39 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.async;
17
18 import java.util.Arrays;
19 import java.util.Collection;
20
21 import org.junit.runner.RunWith;
22 import org.junit.runners.Parameterized;
23
24 // Note: the different ThreadContextMap implementations cannot be parameterized:
25 // ThreadContext initialization will result in static final fields being set in various components.
26 // To use a different ThreadContextMap, the test needs to be run in a new JVM.
27 @RunWith(Parameterized.class)
28 public class AsyncLoggerThreadContextDefaultTest extends AbstractAsyncThreadContextTestBase {
29 @Parameterized.Parameters
30 public static Collection<Object[]> data() {
31 return Arrays.asList(new Object[][] {
32 { ContextImpl.WEBAPP, Mode.ALL_ASYNC},
33 { ContextImpl.WEBAPP, Mode.BOTH_ALL_ASYNC_AND_MIXED},
34 });
35 }
36 public AsyncLoggerThreadContextDefaultTest(final ContextImpl contextImpl, final Mode asyncMode) {
37 super(contextImpl, asyncMode);
38 }
39 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.async;
17
18 import java.util.Arrays;
19 import java.util.Collection;
20
21 import org.junit.runner.RunWith;
22 import org.junit.runners.Parameterized;
23
24 // Note: the different ThreadContextMap implementations cannot be parameterized:
25 // ThreadContext initialization will result in static final fields being set in various components.
26 // To use a different ThreadContextMap, the test needs to be run in a new JVM.
27 @RunWith(Parameterized.class)
28 public class AsyncLoggerThreadContextGarbageFreeTest extends AbstractAsyncThreadContextTestBase {
29 @Parameterized.Parameters
30 public static Collection<Object[]> data() {
31 return Arrays.asList(new Object[][] {
32 { ContextImpl.GARBAGE_FREE, Mode.ALL_ASYNC},
33 { ContextImpl.GARBAGE_FREE, Mode.BOTH_ALL_ASYNC_AND_MIXED},
34 });
35 }
36 public AsyncLoggerThreadContextGarbageFreeTest(final ContextImpl contextImpl, final Mode asyncMode) {
37 super(contextImpl, asyncMode);
38 }
39 }
3434 }
3535
3636 @Test
37 public void testGetRouteEnqueuesIfQueueFullAndCalledFromDifferentThread() throws Exception {
37 public void testGetRouteSynchronousIfQueueFullAndCalledFromDifferentThread() throws Exception {
3838 final DefaultAsyncQueueFullPolicy router = new DefaultAsyncQueueFullPolicy();
39 assertEquals(EventRoute.ENQUEUE, router.getRoute(otherThreadId(), Level.ALL));
40 assertEquals(EventRoute.ENQUEUE, router.getRoute(otherThreadId(), Level.OFF));
39 assertEquals(EventRoute.SYNCHRONOUS, router.getRoute(otherThreadId(), Level.ALL));
40 assertEquals(EventRoute.SYNCHRONOUS, router.getRoute(otherThreadId(), Level.OFF));
4141 }
4242
4343 @Test
7575
7676 for (final Level level : new Level[] {Level.ERROR, Level.FATAL, Level.OFF}) {
7777 assertEquals(level.name(), EventRoute.SYNCHRONOUS, router.getRoute(currentThreadId(), level));
78 assertEquals(level.name(), EventRoute.ENQUEUE, router.getRoute(otherThreadId(), level));
78 assertEquals(level.name(), EventRoute.SYNCHRONOUS, router.getRoute(otherThreadId(), level));
7979 assertEquals(level.name(), EventRoute.SYNCHRONOUS, router.getRoute(currentThreadId(), level));
80 assertEquals(level.name(), EventRoute.ENQUEUE, router.getRoute(otherThreadId(), level));
80 assertEquals(level.name(), EventRoute.SYNCHRONOUS, router.getRoute(otherThreadId(), level));
8181 }
8282 }
8383
8484 @Test
85 public void testGetRouteEnqueuesIfOtherThreadQueueFullAndLevelMoreSpecificThanThreshold() throws Exception {
85 public void testGetRouteSynchronousIfOtherThreadQueueFullAndLevelMoreSpecificThanThreshold() throws Exception {
8686 final DiscardingAsyncQueueFullPolicy router = new DiscardingAsyncQueueFullPolicy(Level.WARN);
8787
8888 for (final Level level : new Level[] {Level.ERROR, Level.FATAL, Level.OFF}) {
89 assertEquals(level.name(), EventRoute.ENQUEUE, router.getRoute(otherThreadId(), level));
89 assertEquals(level.name(), EventRoute.SYNCHRONOUS, router.getRoute(otherThreadId(), level));
9090 }
9191 }
9292
2222 import java.io.ObjectInputStream;
2323 import java.io.ObjectOutputStream;
2424 import java.util.Arrays;
25 import java.util.HashMap;
26 import java.util.Map;
2725
2826 import org.apache.logging.log4j.Level;
2927 import org.apache.logging.log4j.Marker;
3028 import org.apache.logging.log4j.MarkerManager;
3129 import org.apache.logging.log4j.ThreadContext.ContextStack;
3230 import org.apache.logging.log4j.core.LogEvent;
31 import org.apache.logging.log4j.util.StringMap;
3332 import org.apache.logging.log4j.core.impl.ThrowableProxy;
3433 import org.apache.logging.log4j.message.Message;
3534 import org.apache.logging.log4j.message.SimpleMessage;
5251 final Level level = null;
5352 final Message data = null;
5453 final Throwable t = null;
55 final Map<String, String> map = null;
5654 final ContextStack contextStack = null;
5755 final String threadName = null;
5856 final StackTraceElement location = null;
5957 final long currentTimeMillis = 0;
6058 final long nanoTime = 1;
61 evt.setValues(null, loggerName, marker, fqcn, level, data, t, map,
59 evt.setValues(null, loggerName, marker, fqcn, level, data, t, (StringMap) evt.getContextData(),
6260 contextStack, -1, threadName, -1, location, currentTimeMillis, nanoTime);
6361 assertEquals(Level.OFF, evt.getLevel());
6462 }
7270 final Level level = null;
7371 final Message data = null;
7472 final Throwable t = null;
75 final Map<String, String> map = null;
7673 final ContextStack contextStack = null;
7774 final String threadName = null;
7875 final StackTraceElement location = null;
7976 final long currentTimeMillis = 0;
8077 final long nanoTime = 1;
81 evt.setValues(null, loggerName, marker, fqcn, level, data, t, map,
78 evt.setValues(null, loggerName, marker, fqcn, level, data, t, (StringMap) evt.getContextData(),
8279 contextStack, -1, threadName, -1, location, currentTimeMillis, nanoTime);
8380 assertNotNull(evt.getMessage());
8481 }
9289 final Level level = null;
9390 final Message data = null;
9491 final Throwable t = null;
95 final Map<String, String> map = null;
9692 final ContextStack contextStack = null;
9793 final String threadName = null;
9894 final StackTraceElement location = null;
9995 final long currentTimeMillis = 123;
10096 final long nanoTime = 1;
101 evt.setValues(null, loggerName, marker, fqcn, level, data, t, map,
97 evt.setValues(null, loggerName, marker, fqcn, level, data, t, (StringMap) evt.getContextData(),
10298 contextStack, -1, threadName, -1, location, currentTimeMillis, nanoTime);
10399 assertEquals(123, evt.getTimeMillis());
104100 }
112108 final Level level = Level.TRACE;
113109 final Message data = new SimpleMessage("message");
114110 final Throwable t = new InternalError("not a real error");
115 final Map<String, String> map = null;
116111 final ContextStack contextStack = null;
117112 final String threadName = "main";
118113 final StackTraceElement location = null;
119114 final long currentTimeMillis = 12345;
120115 final long nanoTime = 1;
121 evt.setValues(null, loggerName, marker, fqcn, level, data, t, map,
116 evt.setValues(null, loggerName, marker, fqcn, level, data, t, (StringMap) evt.getContextData(),
122117 contextStack, -1, threadName, -1, location, currentTimeMillis, nanoTime);
123
118 ((StringMap) evt.getContextData()).putValue("key", "value");
119
124120 final ByteArrayOutputStream baos = new ByteArrayOutputStream();
125121 final ObjectOutputStream out = new ObjectOutputStream(baos);
126122 out.writeObject(evt);
127
123
128124 final ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray()));
129125 final RingBufferLogEvent other = (RingBufferLogEvent) in.readObject();
130126 assertEquals(loggerName, other.getLoggerName());
134130 assertEquals(data, other.getMessage());
135131 assertNull("null after serialization", other.getThrown());
136132 assertEquals(new ThrowableProxy(t), other.getThrownProxy());
137 assertEquals(map, other.getContextMap());
133 assertEquals(evt.getContextData(), other.getContextData());
138134 assertEquals(contextStack, other.getContextStack());
139135 assertEquals(threadName, other.getThreadName());
140136 assertEquals(location, other.getSource());
141137 assertEquals(currentTimeMillis, other.getTimeMillis());
142138 }
143
139
144140 @Test
145141 public void testCreateMementoReturnsCopy() {
146142 final RingBufferLogEvent evt = new RingBufferLogEvent();
150146 final Level level = Level.TRACE;
151147 final Message data = new SimpleMessage("message");
152148 final Throwable t = new InternalError("not a real error");
153 final Map<String, String> map = new HashMap<>();
154 map.put("key", "value");
155149 final ContextStack contextStack = new MutableThreadContextStack(Arrays.asList("a", "b"));
156150 final String threadName = "main";
157151 final StackTraceElement location = null;
158152 final long currentTimeMillis = 12345;
159153 final long nanoTime = 1;
160 evt.setValues(null, loggerName, marker, fqcn, level, data, t, map,
154 evt.setValues(null, loggerName, marker, fqcn, level, data, t, (StringMap) evt.getContextData(),
161155 contextStack, -1, threadName, -1, location, currentTimeMillis, nanoTime);
162
156 ((StringMap) evt.getContextData()).putValue("key", "value");
157
163158 final LogEvent actual = evt.createMemento();
164159 assertEquals(evt.getLoggerName(), actual.getLoggerName());
165160 assertEquals(evt.getMarker(), actual.getMarker());
174169 assertEquals(evt.getSource(), actual.getSource());
175170 assertEquals(evt.getThrownProxy(), actual.getThrownProxy());
176171 }
172
173 @Test
174 public void testMessageTextNeverThrowsNpe() {
175 final RingBufferLogEvent evt = new RingBufferLogEvent();
176 try {
177 evt.getFormattedMessage();
178 } catch (final NullPointerException e) {
179 fail("the messageText field was not set");
180 }
181 }
177182 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.async.perftest;
17
18 import java.util.Objects;
19 import java.util.concurrent.BlockingQueue;
20
21 import org.apache.logging.log4j.core.async.perftest.ResponseTimeTest.PrintingAsyncQueueFullPolicy;
22
23 import com.lmax.disruptor.collections.Histogram;
24
25 public abstract class AbstractRunQueue implements IPerfTestRunner {
26
27 abstract BlockingQueue<String> createQueue(int capacity);
28
29 private static final String STOP = "STOP_TEST";
30 private volatile boolean stopped = false;
31 private final BlockingQueue<String> queue = createQueue(256 * 1024);
32 private final Thread backGroundThread;
33
34 AbstractRunQueue() {
35 backGroundThread = new Thread(new Runnable() {
36 @Override
37 public void run() {
38 for (; ; ) {
39 try {
40 if (Objects.equals(queue.take(), STOP)) {
41 break;
42 }
43 } catch (final InterruptedException e) {
44 e.printStackTrace();
45 break;
46 }
47 }
48 }
49 });
50 backGroundThread.start();
51 }
52
53 @Override
54 public void runThroughputTest(final int lines, final Histogram histogram) {
55 }
56
57
58 @Override
59 public void runLatencyTest(final int samples, final Histogram histogram,
60 final long nanoTimeCost, final int threadCount) {
61 }
62
63
64 @Override
65 public final void shutdown() {
66 stopped = true;
67 try {
68 queue.put(STOP);
69 } catch (final InterruptedException e) {
70 e.printStackTrace();
71 }
72 }
73
74
75 @Override
76 public final void log(final String finalMessage) {
77 if (stopped) {
78 return;
79 }
80 if (!queue.offer(finalMessage)) {
81 PrintingAsyncQueueFullPolicy.ringbufferFull.incrementAndGet();
82 try {
83 queue.put(finalMessage);
84 } catch (final InterruptedException e) {
85 e.printStackTrace();
86 }
87 }
88
89 }
90 }
155155 final int COUNT = (1000 * 1000) / threadCount;
156156 runLatencyTest(logger, TEST_DURATION_MILLIS, COUNT, loadMessagesPerSec, idleStrategy, serviceTmHistograms,
157157 responseTmHistograms, threadCount);
158 logger.shutdown();
158159 final long end = System.currentTimeMillis();
159160
160161 // ... and report the results
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.async.perftest;
17
18 import java.util.concurrent.BlockingQueue;
19
20 import org.apache.logging.log4j.core.async.DisruptorBlockingQueueFactory;
21
22 import com.conversantmedia.util.concurrent.SpinPolicy;
23
24 public class RunConversant extends AbstractRunQueue {
25
26 @Override
27 BlockingQueue<String> createQueue(final int capacity) {
28 return DisruptorBlockingQueueFactory.<String>createFactory(SpinPolicy.SPINNING).create(capacity);
29 }
30 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.async.perftest;
17
18 import java.util.concurrent.BlockingQueue;
19
20 import org.apache.logging.log4j.core.async.JCToolsBlockingQueueFactory;
21 import org.apache.logging.log4j.core.async.JCToolsBlockingQueueFactory.WaitStrategy;
22
23 public class RunJCTools extends AbstractRunQueue {
24
25 @Override
26 BlockingQueue<String> createQueue(final int capacity) {
27 return JCToolsBlockingQueueFactory.<String>createFactory(WaitStrategy.SPIN).create(capacity);
28 }
29
30
31 }
1515 */
1616 package org.apache.logging.log4j.core.config;
1717
18 import static org.junit.Assert.assertEquals;
19 import static org.junit.Assert.assertTrue;
20
2118 import java.util.Map;
2219
20 import org.apache.logging.log4j.Level;
2321 import org.apache.logging.log4j.core.Appender;
2422 import org.apache.logging.log4j.core.appender.ConsoleAppender;
2523 import org.apache.logging.log4j.core.appender.FileAppender;
2624 import org.apache.logging.log4j.core.config.composite.CompositeConfiguration;
25 import org.apache.logging.log4j.core.util.Throwables;
2726 import org.apache.logging.log4j.junit.LoggerContextRule;
27 import org.junit.Assert;
2828 import org.junit.Test;
2929 import org.junit.runner.Description;
3030 import org.junit.runners.model.Statement;
31
32 import static org.junit.Assert.*;
3133
3234 public class CompositeConfigurationTest {
3335 /*
105107 appendersMap.size());
106108 assertTrue(appendersMap.get("File") instanceof FileAppender);
107109 assertTrue(appendersMap.get("STDOUT") instanceof ConsoleAppender);
110 }
111 };
112 runTest(lcr, test);
113 }
114
115 @Test
116 public void testAttributeCheckWhenMergingConfigurations() {
117 final LoggerContextRule lcr = new LoggerContextRule("classpath:log4j-comp-root-loggers.xml,log4j-comp-logger.json");
118 final Statement test = new Statement() {
119 @Override
120 public void evaluate() throws Throwable {
121 try {
122 final CompositeConfiguration config = (CompositeConfiguration) lcr.getConfiguration();
123 Assert.assertNotNull(config);
124 } catch (final NullPointerException e) {
125 fail("Should not throw NullPointerException when there are different nodes.");
126 }
127 }
128 };
129 runTest(lcr, test);
130 }
131
132 @Test
133 public void testAttributeMergeForLoggers() {
134 final LoggerContextRule lcr = new LoggerContextRule("classpath:log4j-comp-logger-root.xml,log4j-comp-logger-attr-override.json");
135 final Statement test = new Statement() {
136 @Override
137 public void evaluate() throws Throwable {
138 final CompositeConfiguration config = (CompositeConfiguration) lcr.getConfiguration();
139 //Test for Root log level override
140 assertEquals("Expected Root logger log level to be WARN", Level.WARN, config.getRootLogger().getLevel());
141
142 //Test for cat2 level override
143 final LoggerConfig cat2 = config.getLogger("cat2");
144 assertEquals("Expected cat2 log level to be INFO", Level.INFO, cat2.getLevel());
145
146 //Test for cat2 additivity override
147 assertTrue("Expected cat2 additivity to be true", cat2.isAdditive());
148
149 //Regression
150 //Check level on cat3 (not present in root config)
151 assertEquals("Expected cat3 log level to be ERROR", Level.ERROR, config.getLogger("cat3").getLevel());
152 //Check level on cat1 (not present in overriden config)
153 assertEquals("Expected cat1 log level to be DEBUG", Level.DEBUG, config.getLogger("cat1").getLevel());
108154 }
109155 };
110156 runTest(lcr, test);
162208 rule.apply(statement, Description
163209 .createTestDescription(getClass(), Thread.currentThread().getStackTrace()[1].getMethodName()))
164210 .evaluate();
165 } catch (final Throwable throwable) {
166 throw new RuntimeException(throwable);
211 } catch (final Throwable e) {
212 Throwables.rethrow(e);
167213 }
168214 }
169215 }
8888
8989 @Before
9090 public void setUp() throws Exception {
91 this.ctx = this.init.getContext();
91 this.ctx = this.init.getLoggerContext();
9292 }
9393
9494 @Test
9797 final Map<String, Appender> appenders = configuration.getAppenders();
9898 assertThat(appenders, is(notNullValue()));
9999 assertThat(appenders.size(), is(equalTo(3)));
100 }
101
102 @Test
103 public void testConfigurationLoggerContext() throws Exception {
104 final Configuration configuration = this.ctx.getConfiguration();
105 assertThat(configuration.getLoggerContext(), is(notNullValue()));
100106 }
101107
102108 @Test
3636 }
3737
3838 private void testInitializeFromFilePath(final String path) {
39 final LoggerContext loggerContext = Configurator.initialize(getClass().getName(), null, path);
40 try {
39 try (final LoggerContext loggerContext = Configurator.initialize(getClass().getName(), null, path)) {
4140 Assert.assertNotNull(loggerContext.getConfiguration().getAppender("List"));
42 } finally {
43 loggerContext.stop();
4441 }
4542 }
4643 }
2020
2121 import org.apache.logging.log4j.Level;
2222 import org.apache.logging.log4j.Logger;
23 import org.apache.logging.log4j.core.Appender;
2423 import org.apache.logging.log4j.core.Layout;
2524 import org.apache.logging.log4j.core.LoggerContext;
2625 import org.apache.logging.log4j.core.appender.FileAppender;
6564 @Test
6665 public void testConfig() {
6766 // don't bother using "error" since that's the default; try another level
68 final LoggerContext ctx = this.init.getContext();
67 final LoggerContext ctx = this.init.getLoggerContext();
6968 ctx.reconfigure();
7069 final Configuration config = ctx.getConfiguration();
7170 assertThat(config, instanceOf(XmlConfiguration.class));
7978 .withPattern(PatternLayout.SIMPLE_CONVERSION_PATTERN)
8079 .withConfiguration(config)
8180 .build();
82 final Appender appender = FileAppender.createAppender(LOG_FILE, "false", "false", "File", "true",
83 "false", "false", "4000", layout, null, "false", null, config);
81 // @formatter:off
82 final FileAppender appender = FileAppender.newBuilder()
83 .withFileName(LOG_FILE)
84 .withAppend(false)
85 .withName("File")
86 .withIgnoreExceptions(false)
87 .withBufferSize(4000)
88 .withBufferedIo(false)
89 .withLayout(layout)
90 .build();
91 // @formatter:on
8492 appender.start();
8593 config.addAppender(appender);
8694 final AppenderRef ref = AppenderRef.createAppenderRef("File", null, null);
0 package org.apache.logging.log4j.core.config;/*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16
17 import java.util.HashSet;
18 import java.util.List;
19
20 import org.apache.logging.log4j.Level;
21 import org.apache.logging.log4j.Marker;
22 import org.apache.logging.log4j.core.LogEvent;
23 import org.apache.logging.log4j.core.impl.Log4jLogEvent;
24 import org.apache.logging.log4j.core.impl.LogEventFactory;
25 import org.apache.logging.log4j.message.Message;
26 import org.apache.logging.log4j.message.SimpleMessage;
27 import org.junit.Test;
28
29 import static org.junit.Assert.*;
30
31 /**
32 * Tests for LoggerConfig.
33 */
34 public class LoggerConfigTest {
35
36 private static LoggerConfig createForProperties(final Property[] properties) {
37 return LoggerConfig.createLogger(true, Level.INFO, "name", "false", new AppenderRef[0], properties,
38 new NullConfiguration(), null);
39 }
40
41 @SuppressWarnings({"deprecation", "unchecked"})
42 @Test
43 public void testPropertiesWithoutSubstitution() {
44 assertNull("null propertiesList", createForProperties(null).getPropertyList());
45 assertNull("null property Map", createForProperties(null).getProperties());
46
47 final Property[] all = new Property[] {
48 Property.createProperty("key1", "value1"),
49 Property.createProperty("key2", "value2"),
50 };
51 final LoggerConfig loggerConfig = createForProperties(all);
52 final List<Property> list = loggerConfig.getPropertyList();
53 assertEquals("map and list contents equal", new HashSet(list), loggerConfig.getProperties().keySet());
54
55 final Object[] actualList = new Object[1];
56 loggerConfig.setLogEventFactory(new LogEventFactory() {
57 @Override
58 public LogEvent createEvent(final String loggerName, final Marker marker, final String fqcn,
59 final Level level, final Message data,
60 final List<Property> properties, final Throwable t) {
61 actualList[0] = properties;
62 return new Log4jLogEvent(System.currentTimeMillis());
63 }
64 });
65 loggerConfig.log("name", "fqcn", null, Level.INFO, new SimpleMessage("msg"), null);
66 assertSame("propertiesList passed in as is if no substitutions required", list, actualList[0]);
67 }
68
69 @SuppressWarnings({"deprecation", "unchecked"})
70 @Test
71 public void testPropertiesWithSubstitution() {
72 final Property[] all = new Property[] {
73 Property.createProperty("key1", "value1-${sys:user.name}"),
74 Property.createProperty("key2", "value2-${sys:user.name}"),
75 };
76 final LoggerConfig loggerConfig = createForProperties(all);
77 final List<Property> list = loggerConfig.getPropertyList();
78 assertEquals("map and list contents equal", new HashSet(list), loggerConfig.getProperties().keySet());
79
80 final Object[] actualListHolder = new Object[1];
81 loggerConfig.setLogEventFactory(new LogEventFactory() {
82 @Override
83 public LogEvent createEvent(final String loggerName, final Marker marker, final String fqcn,
84 final Level level, final Message data,
85 final List<Property> properties, final Throwable t) {
86 actualListHolder[0] = properties;
87 return new Log4jLogEvent(System.currentTimeMillis());
88 }
89 });
90 loggerConfig.log("name", "fqcn", null, Level.INFO, new SimpleMessage("msg"), null);
91 assertNotSame("propertiesList with substitutions", list, actualListHolder[0]);
92
93 final List<Property> actualList = (List<Property>) actualListHolder[0];
94
95 for (int i = 0; i < list.size(); i++) {
96 assertEquals("name[" + i + "]", list.get(i).getName(), actualList.get(i).getName());
97 final String value = list.get(i).getValue().replace("${sys:user.name}", System.getProperty("user.name"));
98 assertEquals("value[" + i + "]", value, actualList.get(i).getValue());
99 }
100 }
101 }
4141
4242 @Test
4343 public void testMissingRootLogger() throws Exception {
44 final LoggerContext ctx = context.getContext();
44 final LoggerContext ctx = context.getLoggerContext();
4545 final Logger logger = ctx.getLogger("sample.Logger1");
4646 assertTrue("Logger should have the INFO level enabled", logger.isInfoEnabled());
4747 assertFalse("Logger should have the DEBUG level disabled", logger.isDebugEnabled());
0 package org.apache.logging.log4j.core.config;/*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16
17 import static org.junit.Assert.assertEquals;
18 import static org.junit.Assert.assertFalse;
19 import static org.junit.Assert.assertNotNull;
20 import static org.junit.Assert.assertTrue;
21
22 import java.util.List;
23
24 import org.apache.logging.log4j.LogManager;
25 import org.apache.logging.log4j.junit.LoggerContextRule;
26 import org.apache.logging.log4j.test.appender.ListAppender;
27 import org.junit.ClassRule;
28 import org.junit.Test;
29
30 /**
31 * Test for LOG4J2-1313
32 * <Property name="" value="" /> not working
33 */
34 public class PropertyTest {
35 private static final String CONFIG = "configPropertyTest.xml";
36
37 @ClassRule
38 public static LoggerContextRule context = new LoggerContextRule(CONFIG);
39
40 @Test
41 public void testEmptyAttribute() throws Exception {
42 final org.apache.logging.log4j.Logger logger = LogManager.getLogger();
43 logger.info("msg");
44
45 final ListAppender app = (ListAppender) context.getRequiredAppender("List");
46 assertNotNull("No ListAppender", app);
47
48 final List<String> messages = app.getMessages();
49 assertNotNull("No Messages", messages);
50 assertEquals("message count" + messages, 1, messages.size());
51
52 //<Property name="emptyElementKey" />
53 //<Property name="emptyAttributeKey" value="" />
54 //<Property name="emptyAttributeKey2" value=""></Property>
55 //<Property name="elementKey">elementValue</Property>
56 //<Property name="attributeKey" value="attributeValue" />
57 //<Property name="attributeWithEmptyElementKey" value="attributeValue2"></Property>
58 //<Property name="bothElementAndAttributeKey" value="attributeValue3">elementValue3</Property>
59 final String expect = "1=elementValue" + // ${sys:elementKey}
60 ",2=" + // ${sys:emptyElementKey}
61 ",a=" + // ${sys:emptyAttributeKey}
62 ",b=" + // ${sys:emptyAttributeKey2}
63 ",3=attributeValue" + // ${sys:attributeKey}
64 ",4=attributeValue2" + // ${sys:attributeWithEmptyElementKey}
65 ",5=elementValue3,m=msg"; // ${sys:bothElementAndAttributeKey}
66 assertEquals(expect, messages.get(0));
67 app.clear();
68 }
69
70 @Test
71 public void testNullValueIsConvertedToEmptyString() { // LOG4J2-1313 <Property name="x" /> support
72 assertEquals("", Property.createProperty("name", null).getValue());
73 }
74
75 @Test
76 public void testIsValueNeedsLookup() {
77 assertTrue("with ${ as value", Property.createProperty("", "${").isValueNeedsLookup());
78 assertTrue("with ${ in value", Property.createProperty("", "blah${blah").isValueNeedsLookup());
79 assertFalse("empty value", Property.createProperty("", "").isValueNeedsLookup());
80 assertFalse("without ${ in value", Property.createProperty("", "blahblah").isValueNeedsLookup());
81 assertFalse("without $ in value", Property.createProperty("", "blahb{sys:lah").isValueNeedsLookup());
82 assertFalse("without { in value", Property.createProperty("", "blahb$sys:lah").isValueNeedsLookup());
83 }
84 }
9292 }
9393
9494 @Test
95 public void testFromFile() throws Exception {
95 public void testInitialize_Name_PathName() throws Exception {
9696 ctx = Configurator.initialize("Test1", "target/test-classes/log4j2-config.xml");
9797 LogManager.getLogger("org.apache.test.TestConfigurator");
9898 Configuration config = ctx.getConfiguration();
108108 }
109109
110110 @Test
111 public void testFromStream() throws Exception {
111 public void testInitialize_Name_ClassLoader_URI() throws Exception {
112 ctx = Configurator.initialize("Test1", null, new File("target/test-classes/log4j2-config.xml").toURI());
113 LogManager.getLogger("org.apache.test.TestConfigurator");
114 Configuration config = ctx.getConfiguration();
115 assertNotNull("No configuration", config);
116 assertEquals("Incorrect Configuration.", CONFIG_NAME, config.getName());
117 final Map<String, Appender> map = config.getAppenders();
118 assertNotNull("Appenders map should not be null.", map);
119 assertThat(map, hasSize(greaterThan(0)));
120 assertThat("Wrong configuration", map, hasKey("List"));
121 Configurator.shutdown(ctx);
122 config = ctx.getConfiguration();
123 assertEquals("Unexpected Configuration.", NullConfiguration.NULL_NAME, config.getName());
124 }
125
126 @Test
127 public void testInitialize_InputStream_File() throws Exception {
112128 final File file = new File("target/test-classes/log4j2-config.xml");
113129 final InputStream is = new FileInputStream(file);
114130 final ConfigurationSource source = new ConfigurationSource(is, file);
127143 }
128144
129145 @Test
130 public void testFromStreamNoId() throws Exception {
146 public void testInitialize_NullClassLoader_ConfigurationSourceWithInputStream_NoId() throws Exception {
131147 final InputStream is = new FileInputStream("target/test-classes/log4j2-config.xml");
132148 final ConfigurationSource source =
133149 new ConfigurationSource(is);
146162 }
147163
148164 @Test
149 public void testFromClassPath() throws Exception {
165 public void testInitialize_Name_LocationName() throws Exception {
150166 ctx = Configurator.initialize("Test1", "log4j2-config.xml");
151167 LogManager.getLogger("org.apache.test.TestConfigurator");
152168 Configuration config = ctx.getConfiguration();
2727 */
2828 public class TestConfiguratorError {
2929
30 private static final String FACTORY_PROPERTY_NAME = "log4j2.loggerContextFactory";
30 private static final String FACTORY_PROPERTY_NAME = "log4j2.loggerContextFactory";
3131
3232 @BeforeClass
3333 public static void beforeClass() {
3636
3737 @Test
3838 public void testErrorNoClassLoader() throws Exception {
39 final LoggerContext ctx = Configurator.initialize("Test1", "target/test-classes/log4j2-config.xml");
40 assertNull("No LoggerContext should have been returned", ctx);
39 try (final LoggerContext ctx = Configurator.initialize("Test1", "target/test-classes/log4j2-config.xml")) {
40 assertNull("No LoggerContext should have been returned", ctx);
41 }
4142 }
4243
4344 @Test
4445 public void testErrorNullClassLoader() throws Exception {
45 final LoggerContext ctx = Configurator.initialize("Test1", null, "target/test-classes/log4j2-config.xml");
46 assertNull("No LoggerContext should have been returned", ctx);
46 try (final LoggerContext ctx = Configurator.initialize("Test1", null,
47 "target/test-classes/log4j2-config.xml")) {
48 assertNull("No LoggerContext should have been returned", ctx);
49 }
4750 }
4851 }
8888
8989 @Before
9090 public void setUp() throws Exception {
91 this.ctx = this.init.getContext();
91 this.ctx = this.init.getLoggerContext();
9292 }
9393
9494 @Test
2020 import static org.junit.Assert.assertNotNull;
2121 import static org.junit.Assert.assertTrue;
2222
23 import java.util.List;
2324 import java.util.Map;
2425
26 import org.apache.logging.log4j.Level;
2527 import org.apache.logging.log4j.LogManager;
2628 import org.apache.logging.log4j.Logger;
2729 import org.apache.logging.log4j.core.Appender;
3133 import org.apache.logging.log4j.core.config.Configuration;
3234 import org.apache.logging.log4j.core.config.ConfigurationFactory;
3335 import org.apache.logging.log4j.core.config.Configurator;
36 import org.apache.logging.log4j.core.config.CustomLevelConfig;
3437 import org.apache.logging.log4j.core.config.LoggerConfig;
3538 import org.apache.logging.log4j.core.config.builder.api.ConfigurationBuilder;
3639 import org.apache.logging.log4j.core.config.builder.api.ConfigurationBuilderFactory;
3740 import org.apache.logging.log4j.core.config.builder.impl.BuiltConfiguration;
3841 import org.apache.logging.log4j.core.filter.ThresholdFilter;
42 import org.apache.logging.log4j.core.util.Constants;
3943 import org.junit.Test;
4044
4145 /**
4549
4650 @Test
4751 public void testBuildConfiguration() throws Exception {
48 final ConfigurationBuilder<BuiltConfiguration> builder = ConfigurationBuilderFactory.newConfigurationBuilder();
49 CustomConfigurationFactory.addTestFixtures("config name", builder);
50 final Configuration configuration = builder.build();
51 Configurator.initialize(configuration);
52 validate(configuration);
52 try {
53 System.setProperty(Constants.LOG4J_CONTEXT_SELECTOR,
54 "org.apache.logging.log4j.core.async.AsyncLoggerContextSelector");
55 final ConfigurationBuilder<BuiltConfiguration> builder = ConfigurationBuilderFactory.newConfigurationBuilder();
56 CustomConfigurationFactory.addTestFixtures("config name", builder);
57 final Configuration configuration = builder.build();
58 try (LoggerContext ctx = Configurator.initialize(configuration)) {
59 validate(configuration);
60 }
61 } finally {
62 System.getProperties().remove(Constants.LOG4J_CONTEXT_SELECTOR);
63 }
5364 }
5465
5566 @Test
5768 try {
5869 System.setProperty(ConfigurationFactory.CONFIGURATION_FACTORY_PROPERTY,
5970 "org.apache.logging.log4j.core.config.builder.CustomConfigurationFactory");
71 System.setProperty(Constants.LOG4J_CONTEXT_SELECTOR,
72 "org.apache.logging.log4j.core.async.AsyncLoggerContextSelector");
6073 final Configuration config = ((LoggerContext) LogManager.getContext(false)).getConfiguration();
6174 validate(config);
6275 } finally {
76 System.getProperties().remove(Constants.LOG4J_CONTEXT_SELECTOR);
6377 System.getProperties().remove(ConfigurationFactory.CONFIGURATION_FACTORY_PROPERTY);
6478 }
6579 }
7690 final Map<String, LoggerConfig> loggers = config.getLoggers();
7791 assertNotNull(loggers);
7892 assertTrue("Incorrect number of LoggerConfigs: " + loggers.size(), loggers.size() == 2);
93 final LoggerConfig rootLoggerConfig = loggers.get("");
94 assertEquals(Level.ERROR, rootLoggerConfig.getLevel());
95 assertFalse(rootLoggerConfig.isIncludeLocation());
96 final LoggerConfig loggerConfig = loggers.get("org.apache.logging.log4j");
97 assertEquals(Level.DEBUG, loggerConfig.getLevel());
98 assertTrue(loggerConfig.isIncludeLocation());
7999 final Filter filter = config.getFilter();
80100 assertNotNull("No Filter", filter);
81101 assertTrue("Not a Threshold Filter", filter instanceof ThresholdFilter);
102 final List<CustomLevelConfig> customLevels = config.getCustomLevels();
103 assertNotNull("No CustomLevels", filter);
104 assertEquals(1, customLevels.size());
105 final CustomLevelConfig customLevel = customLevels.get(0);
106 assertEquals("Panic", customLevel.getLevelName());
107 assertEquals(17, customLevel.getIntLevel());
82108 final Logger logger = LogManager.getLogger(getClass());
83109 logger.info("Welcome to Log4j!");
84110 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.config.builder;
17
18 import org.apache.logging.log4j.Level;
19 import org.apache.logging.log4j.core.Filter;
20 import org.apache.logging.log4j.core.appender.ConsoleAppender;
21 import org.apache.logging.log4j.core.config.builder.api.AppenderComponentBuilder;
22 import org.apache.logging.log4j.core.config.builder.api.ConfigurationBuilder;
23 import org.apache.logging.log4j.core.config.builder.api.ConfigurationBuilderFactory;
24 import org.apache.logging.log4j.core.config.builder.impl.BuiltConfiguration;
25 import org.junit.Test;
26
27 import static org.junit.Assert.*;
28 import static org.junit.Assume.assumeTrue;
29
30 public class ConfigurationBuilderTest {
31
32 private static final String INDENT = " ";
33 private static final String EOL = System.lineSeparator();
34
35 private void addTestFixtures(final String name, final ConfigurationBuilder<BuiltConfiguration> builder) {
36 builder.setConfigurationName(name);
37 builder.setStatusLevel(Level.ERROR);
38 builder.add(builder.newScriptFile("target/test-classes/scripts/filter.groovy").addIsWatched(true));
39 builder.add(builder.newFilter("ThresholdFilter", Filter.Result.ACCEPT, Filter.Result.NEUTRAL)
40 .addAttribute("level", Level.DEBUG));
41 final AppenderComponentBuilder appenderBuilder = builder.newAppender("Stdout", "CONSOLE").addAttribute("target", ConsoleAppender.Target.SYSTEM_OUT);
42 appenderBuilder.add(builder.newLayout("PatternLayout").
43 addAttribute("pattern", "%d [%t] %-5level: %msg%n%throwable"));
44 appenderBuilder.add(builder.newFilter("MarkerFilter", Filter.Result.DENY,
45 Filter.Result.NEUTRAL).addAttribute("marker", "FLOW"));
46 builder.add(appenderBuilder);
47 builder.add(builder.newLogger("org.apache.logging.log4j", Level.DEBUG, true).
48 add(builder.newAppenderRef("Stdout")).
49 addAttribute("additivity", false));
50 builder.add(builder.newRootLogger(Level.ERROR).add(builder.newAppenderRef("Stdout")));
51 builder.addProperty("MyKey", "MyValue");
52 builder.add(builder.newCustomLevel("Panic", 17));
53 builder.setPackages("foo,bar");
54 }
55
56 private final static String expectedXml =
57 "<?xml version='1.0' encoding='UTF-8'?>" + EOL +
58 "<Configuration name=\"config name\" status=\"ERROR\" packages=\"foo,bar\">" + EOL +
59 INDENT + "<Properties>" + EOL +
60 INDENT + INDENT + "<Property name=\"MyKey\">MyValue</Property>" + EOL +
61 INDENT + "</Properties>" + EOL +
62 INDENT + "<Scripts>" + EOL +
63 INDENT + INDENT + "<ScriptFile name=\"target/test-classes/scripts/filter.groovy\" path=\"target/test-classes/scripts/filter.groovy\" isWatched=\"true\"/>" + EOL +
64 INDENT + "</Scripts>" + EOL +
65 INDENT + "<CustomLevels>" + EOL +
66 INDENT + INDENT + "<CustomLevel name=\"Panic\" intLevel=\"17\"/>" + EOL +
67 INDENT + "</CustomLevels>" + EOL +
68 INDENT + "<ThresholdFilter onMatch=\"ACCEPT\" onMisMatch=\"NEUTRAL\" level=\"DEBUG\"/>" + EOL +
69 INDENT + "<Appenders>" + EOL +
70 INDENT + INDENT + "<CONSOLE name=\"Stdout\" target=\"SYSTEM_OUT\">" + EOL +
71 INDENT + INDENT + INDENT + "<PatternLayout pattern=\"%d [%t] %-5level: %msg%n%throwable\"/>" + EOL +
72 INDENT + INDENT + INDENT + "<MarkerFilter onMatch=\"DENY\" onMisMatch=\"NEUTRAL\" marker=\"FLOW\"/>" + EOL +
73 INDENT + INDENT + "</CONSOLE>" + EOL +
74 INDENT + "</Appenders>" + EOL +
75 INDENT + "<Loggers>" + EOL +
76 INDENT + INDENT + "<Logger name=\"org.apache.logging.log4j\" level=\"DEBUG\" includeLocation=\"true\" additivity=\"false\">" + EOL +
77 INDENT + INDENT + INDENT + "<AppenderRef ref=\"Stdout\"/>" + EOL +
78 INDENT + INDENT + "</Logger>" + EOL +
79 INDENT + INDENT + "<Root level=\"ERROR\">" + EOL +
80 INDENT + INDENT + INDENT + "<AppenderRef ref=\"Stdout\"/>" + EOL +
81 INDENT + INDENT + "</Root>" + EOL +
82 INDENT + "</Loggers>" + EOL +
83 "</Configuration>" + EOL;
84
85 // TODO make test run properly on Windows
86 @Test
87 public void testXmlConstructing() throws Exception {
88 assumeTrue(System.lineSeparator().length() == 1); // Only run test on platforms with single character line endings (such as Linux), not on Windows
89 final ConfigurationBuilder<BuiltConfiguration> builder = ConfigurationBuilderFactory.newConfigurationBuilder();
90 addTestFixtures("config name", builder);
91 final String xmlConfiguration = builder.toXmlConfiguration();
92 assertEquals(expectedXml, xmlConfiguration);
93 }
94
95 }
1515 */
1616 package org.apache.logging.log4j.core.config.builder;
1717
18 import java.net.URI;
19
1820 import org.apache.logging.log4j.Level;
1921 import org.apache.logging.log4j.core.Filter;
22 import org.apache.logging.log4j.core.LoggerContext;
2023 import org.apache.logging.log4j.core.appender.ConsoleAppender;
2124 import org.apache.logging.log4j.core.config.Configuration;
2225 import org.apache.logging.log4j.core.config.ConfigurationFactory;
2427 import org.apache.logging.log4j.core.config.builder.api.AppenderComponentBuilder;
2528 import org.apache.logging.log4j.core.config.builder.api.ConfigurationBuilder;
2629 import org.apache.logging.log4j.core.config.builder.impl.BuiltConfiguration;
27
28 import java.net.URI;
2930
3031 /**
3132 * Normally this would be a plugin. However, we don't want it used for everything so it will be defined
4748 appenderBuilder.add(builder.newFilter("MarkerFilter", Filter.Result.DENY,
4849 Filter.Result.NEUTRAL).addAttribute("marker", "FLOW"));
4950 builder.add(appenderBuilder);
50 builder.add(builder.newLogger("org.apache.logging.log4j", Level.DEBUG).
51 add(builder.newAppenderRef("Stdout")).
52 addAttribute("additivity", false));
51 builder.add(builder.newLogger("org.apache.logging.log4j", Level.DEBUG, true).
52 add(builder.newAppenderRef("Stdout")).
53 addAttribute("additivity", false));
5354 builder.add(builder.newRootLogger(Level.ERROR).add(builder.newAppenderRef("Stdout")));
55 builder.add(builder.newCustomLevel("Panic", 17));
5456 return builder.build();
5557 }
5658
5759 @Override
58 public Configuration getConfiguration(final ConfigurationSource source) {
59 return getConfiguration(source.toString(), null);
60 public Configuration getConfiguration(final LoggerContext loggerContext, final ConfigurationSource source) {
61 return getConfiguration(loggerContext, source.toString(), null);
6062 }
6163
6264 @Override
63 public Configuration getConfiguration(final String name, final URI configLocation) {
65 public Configuration getConfiguration(final LoggerContext loggerContext, final String name, final URI configLocation) {
6466 final ConfigurationBuilder<BuiltConfiguration> builder = newConfigurationBuilder();
6567 return addTestFixtures(name, builder);
6668 }
1414 * limitations under the license.
1515 */
1616 package org.apache.logging.log4j.core.config.plugins.util;
17
18 import static org.junit.Assert.assertEquals;
19 import static org.junit.Assert.assertTrue;
1720
1821 import java.io.File;
1922 import java.io.IOException;
3841 import org.apache.logging.log4j.status.StatusLogger;
3942 import org.apache.logging.log4j.test.appender.ListAppender;
4043 import org.junit.AfterClass;
41 import org.junit.BeforeClass;
4244 import org.junit.Test;
43
44 import static org.junit.Assert.*;
4545
4646 public class PluginManagerPackagesTest {
4747 private static Configuration config;
4848 private static ListAppender listAppender;
4949 private static LoggerContext ctx;
50
51 @BeforeClass
52 public static void setupClass() {
53 }
5450
5551 @AfterClass
5652 public static void cleanupClass() {
8884 assertEquals("abc123XYZ", messages.get(0));
8985 }
9086
91 private void compile(final File f) throws IOException {
87 static void compile(final File f) throws IOException {
9288 // set up compiler
9389 final JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
9490 final DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<>();
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16
17 package org.apache.logging.log4j.core.config.plugins.util;
18
19 import static org.junit.Assert.assertEquals;
20
21 import java.io.IOException;
22 import java.net.Proxy;
23 import java.net.URL;
24 import java.net.URLClassLoader;
25 import java.net.URLConnection;
26 import java.net.URLStreamHandler;
27 import java.net.URLStreamHandlerFactory;
28 import java.util.Arrays;
29 import java.util.Collections;
30 import java.util.Enumeration;
31
32 import org.apache.logging.log4j.core.config.plugins.util.PluginRegistry.PluginTest;
33 import org.apache.logging.log4j.junit.CleanFolders;
34 import org.apache.logging.log4j.junit.URLStreamHandlerFactoryRule;
35 import org.junit.Rule;
36 import org.junit.Test;
37 import org.junit.rules.RuleChain;
38
39 /**
40 * Tests the ResolverUtil class for custom protocol like bundleresource, vfs, vfszip.
41 */
42 public class ResolverUtilCustomProtocolTest {
43
44 @Rule
45 public URLStreamHandlerFactoryRule rule = new URLStreamHandlerFactoryRule(new NoopURLStreamHandlerFactory());
46
47 @Rule
48 public RuleChain chain = RuleChain.outerRule(new CleanFolders(ResolverUtilTest.WORK_DIR));
49
50 static class NoopURLStreamHandlerFactory implements URLStreamHandlerFactory {
51
52 @Override
53 public URLStreamHandler createURLStreamHandler(final String protocol) {
54 return new URLStreamHandler() {
55 @Override
56 protected URLConnection openConnection(final URL url) {
57 return open(url, null);
58 }
59
60 private URLConnection open(final URL url, final Proxy proxy) {
61 return new URLConnection(url) {
62 @Override
63 public void connect() throws IOException {
64 // do nothing
65 }
66 };
67 }
68
69 @Override
70 protected URLConnection openConnection(final URL url, final Proxy proxy) {
71 return open(url, proxy);
72 }
73
74 @Override
75 protected int getDefaultPort() {
76 return 1;
77 }
78 };
79 }
80 }
81
82 static class SingleURLClassLoader extends ClassLoader {
83 private final URL url;
84
85 public SingleURLClassLoader(final URL url) {
86 this.url = url;
87 }
88
89 public SingleURLClassLoader(final URL url, final ClassLoader parent) {
90 super(parent);
91 this.url = url;
92 }
93
94 @Override
95 protected URL findResource(final String name) {
96 return url;
97 }
98
99 @Override
100 public URL getResource(final String name) {
101 return findResource(name);
102 }
103
104 @Override
105 public Enumeration<URL> getResources(final String name) throws IOException {
106 return findResources(name);
107 }
108
109 @Override
110 protected Enumeration<URL> findResources(final String name) throws IOException {
111 return Collections.enumeration(Arrays.asList(findResource(name)));
112 }
113 }
114
115 @Test
116 public void testExtractPathFromVfsEarJarWindowsUrl() throws Exception {
117 final URL url = new URL(
118 "vfs:/C:/jboss/jboss-eap-6.4/standalone/deployments/com.xxx.yyy.application-ear.ear/lib/com.xxx.yyy.logging.jar/com/xxx/yyy/logging/config/");
119 final String expected = "/C:/jboss/jboss-eap-6.4/standalone/deployments/com.xxx.yyy.application-ear.ear/lib/com.xxx.yyy.logging.jar/com/xxx/yyy/logging/config/";
120 assertEquals(expected, new ResolverUtil().extractPath(url));
121 }
122
123 @Test
124 public void testExtractPathFromVfsWarClassesWindowsUrl() throws Exception {
125 final URL url = new URL(
126 "vfs:/C:/jboss/jboss-eap-6.4/standalone/deployments/test-log4j2-web-standalone.war/WEB-INF/classes/org/hypik/test/jboss/eap7/logging/config/");
127 final String expected = "/C:/jboss/jboss-eap-6.4/standalone/deployments/test-log4j2-web-standalone.war/WEB-INF/classes/org/hypik/test/jboss/eap7/logging/config/";
128 assertEquals(expected, new ResolverUtil().extractPath(url));
129 }
130
131 @Test
132 public void testExtractPathFromVfsWarClassesLinuxUrl() throws Exception {
133 final URL url = new URL(
134 "vfs:/content/mycustomweb.war/WEB-INF/classes/org/hypik/test/jboss/log4j2/logging/pluginweb/");
135 final String expected = "/content/mycustomweb.war/WEB-INF/classes/org/hypik/test/jboss/log4j2/logging/pluginweb/";
136 assertEquals(expected, new ResolverUtil().extractPath(url));
137 }
138
139 @Test
140 public void testExtractPathFromVfszipUrl() throws Exception {
141 final URL url = new URL(
142 "vfszip:/home2/jboss-5.0.1.CR2/jboss-as/server/ais/ais-deploy/myear.ear/mywar.war/WEB-INF/some.xsd");
143 final String expected = "/home2/jboss-5.0.1.CR2/jboss-as/server/ais/ais-deploy/myear.ear/mywar.war/WEB-INF/some.xsd";
144 assertEquals(expected, new ResolverUtil().extractPath(url));
145 }
146
147 @Test
148 public void testExtractPathFromVfsEarJarLinuxUrl() throws Exception {
149 final URL url = new URL(
150 "vfs:/content/test-log4k2-ear.ear/lib/test-log4j2-jar-plugins.jar/org/hypik/test/jboss/log4j2/pluginjar/");
151 final String expected = "/content/test-log4k2-ear.ear/lib/test-log4j2-jar-plugins.jar/org/hypik/test/jboss/log4j2/pluginjar/";
152 assertEquals(expected, new ResolverUtil().extractPath(url));
153 }
154
155 @Test
156 public void testExtractPathFromVfszipUrlWithPlusCharacters() throws Exception {
157 final URL url = new URL("vfszip:/path+with+plus/file+name+with+plus.xml");
158 final String expected = "/path+with+plus/file+name+with+plus.xml";
159 assertEquals(expected, new ResolverUtil().extractPath(url));
160 }
161
162 @Test
163 public void testExtractPathFromVfsUrlWithPlusCharacters() throws Exception {
164 final URL url = new URL("vfs:/path+with+plus/file+name+with+plus.xml");
165 final String expected = "/path+with+plus/file+name+with+plus.xml";
166 assertEquals(expected, new ResolverUtil().extractPath(url));
167 }
168
169 @Test
170 public void testExtractPathFromResourceBundleUrl() throws Exception {
171 final URL url = new URL("bundleresource:/some/path/some/file.properties");
172 final String expected = "/some/path/some/file.properties";
173 assertEquals(expected, new ResolverUtil().extractPath(url));
174 }
175
176 @Test
177 public void testExtractPathFromResourceBundleUrlWithPlusCharacters() throws Exception {
178 final URL url = new URL("bundleresource:/some+path/some+file.properties");
179 final String expected = "/some+path/some+file.properties";
180 assertEquals(expected, new ResolverUtil().extractPath(url));
181 }
182
183 @Test
184 public void testFindInPackageFromVfsDirectoryURL() throws Exception {
185 try (final URLClassLoader cl = ResolverUtilTest.compileAndCreateClassLoader("3")) {
186 final ResolverUtil resolverUtil = new ResolverUtil();
187 resolverUtil
188 .setClassLoader(new SingleURLClassLoader(new URL("vfs:/" + ResolverUtilTest.WORK_DIR + "/resolverutil3/customplugin3/"), cl));
189 resolverUtil.findInPackage(new PluginTest(), "customplugin3");
190 assertEquals("Class not found in packages", 1, resolverUtil.getClasses().size());
191 assertEquals("Unexpected class resolved", cl.loadClass("customplugin3.FixedString3Layout"),
192 resolverUtil.getClasses().iterator().next());
193 }
194 }
195
196 @Test
197 public void testFindInPackageFromVfsJarURL() throws Exception {
198 try (final URLClassLoader cl = ResolverUtilTest.compileJarAndCreateClassLoader("4")) {
199 final ResolverUtil resolverUtil = new ResolverUtil();
200 resolverUtil.setClassLoader(new SingleURLClassLoader(
201 new URL("vfs:/" + ResolverUtilTest.WORK_DIR + "/resolverutil4/customplugin4.jar/customplugin4/"), cl));
202 resolverUtil.findInPackage(new PluginTest(), "customplugin4");
203 assertEquals("Class not found in packages", 1, resolverUtil.getClasses().size());
204 assertEquals("Unexpected class resolved", cl.loadClass("customplugin4.FixedString4Layout"),
205 resolverUtil.getClasses().iterator().next());
206 }
207 }
208
209 }
1919 import static org.junit.Assert.assertEquals;
2020 import static org.junit.Assert.assertTrue;
2121
22 import java.io.File;
23 import java.io.IOException;
2224 import java.io.UnsupportedEncodingException;
2325 import java.net.MalformedURLException;
26 import java.net.URI;
2427 import java.net.URISyntaxException;
2528 import java.net.URL;
26
27 import org.junit.Ignore;
29 import java.net.URLClassLoader;
30 import java.nio.file.FileSystem;
31 import java.nio.file.FileSystems;
32 import java.nio.file.Files;
33 import java.nio.file.Path;
34 import java.nio.file.StandardCopyOption;
35 import java.util.HashMap;
36 import java.util.Map;
37
38 import org.apache.logging.log4j.core.config.plugins.util.PluginRegistry.PluginTest;
39 import org.apache.logging.log4j.junit.CleanFolders;
40 import org.junit.Rule;
2841 import org.junit.Test;
42 import org.junit.rules.RuleChain;
2943
3044 /**
3145 * Tests the ResolverUtil class.
3246 */
3347 public class ResolverUtilTest {
3448
49 static final String WORK_DIR = "target/testpluginsutil";
50
51 @Rule
52 public RuleChain chain = RuleChain.outerRule(new CleanFolders(WORK_DIR));
53
3554 @Test
3655 public void testExtractPathFromJarUrl() throws Exception {
3756 final URL url = new URL("jar:file:/C:/Users/me/.m2/repository/junit/junit/4.11/junit-4.11.jar!/org/junit/Test.class");
92111 assertEquals(expected, new ResolverUtil().extractPath(url));
93112 }
94113
95 @Ignore
96 @Test
97 public void testExtractPathFromVfszipUrl() throws Exception {
98 // need to install URLStreamHandlerFactory to prevent "unknown protocol" MalformedURLException
99 final URL url = new URL(
100 "vfszip:/home2/jboss-5.0.1.CR2/jboss-as/server/ais/ais-deploy/myear.ear/mywar.war/WEB-INF/some.xsd");
101 final String expected = "/home2/jboss-5.0.1.CR2/jboss-as/server/ais/ais-deploy/myear.ear/mywar.war/WEB-INF/some.xsd";
102 assertEquals(expected, new ResolverUtil().extractPath(url));
103 }
104
105 @Ignore
106 @Test
107 public void testExtractPathFromVfszipUrlWithPlusCharacters()
108 throws Exception {
109 // need to install URLStreamHandlerFactory to prevent "unknown protocol" MalformedURLException
110 final URL url = new URL("vfszip:/path+with+plus/file+name+with+plus.xml");
111 final String expected = "/path+with+plus/file+name+with+plus.xml";
112 assertEquals(expected, new ResolverUtil().extractPath(url));
113 }
114
115 @Ignore
116 @Test
117 public void testExtractPathFromResourceBundleUrl() throws Exception {
118 // need to install URLStreamHandlerFactory to prevent "unknown protocol" MalformedURLException
119 final URL url = new URL("resourcebundle:/some/path/some/file.properties");
120 final String expected = "/some/path/some/file.properties";
121 assertEquals(expected, new ResolverUtil().extractPath(url));
122 }
123
124 @Ignore
125 @Test
126 public void testExtractPathFromResourceBundleUrlWithPlusCharacters() throws Exception {
127 // need to install URLStreamHandlerFactory to prevent "unknown protocol" MalformedURLException
128 final URL url = new URL("resourcebundle:/some+path/some+file.properties");
129 final String expected = "/some+path/some+file.properties";
130 assertEquals(expected, new ResolverUtil().extractPath(url));
131 }
132
133114 @Test
134115 public void testExtractPathFromHttpUrl() throws Exception {
135116 final URL url = new URL("http://java.sun.com/index.html#chapter1");
165146 assertEquals(expected, new ResolverUtil().extractPath(url));
166147 }
167148
149 @Test
150 public void testFindInPackageFromDirectoryPath() throws Exception {
151 try (final URLClassLoader cl = compileAndCreateClassLoader("1")) {
152 final ResolverUtil resolverUtil = new ResolverUtil();
153 resolverUtil.setClassLoader(cl);
154 resolverUtil.findInPackage(new PluginTest(), "customplugin1");
155 assertEquals("Class not found in packages", 1, resolverUtil.getClasses().size());
156 assertEquals("Unexpected class resolved", cl.loadClass("customplugin1.FixedString1Layout"),
157 resolverUtil.getClasses().iterator().next());
158 }
159 }
160
161 @Test
162 public void testFindInPackageFromJarPath() throws Exception {
163 try (final URLClassLoader cl = compileJarAndCreateClassLoader("2")) {
164 final ResolverUtil resolverUtil = new ResolverUtil();
165 resolverUtil.setClassLoader(cl);
166 resolverUtil.findInPackage(new PluginTest(), "customplugin2");
167 assertEquals("Class not found in packages", 1, resolverUtil.getClasses().size());
168 assertEquals("Unexpected class resolved", cl.loadClass("customplugin2.FixedString2Layout"),
169 resolverUtil.getClasses().iterator().next());
170 }
171 }
172
173 static URLClassLoader compileJarAndCreateClassLoader(final String suffix) throws IOException, Exception {
174 final File workDir = compile(suffix);
175 final File jarFile = new File(workDir, "customplugin" + suffix + ".jar");
176 final URI jarURI = jarFile.toURI();
177 createJar(jarURI, workDir, new File(workDir,
178 "customplugin" + suffix + "/FixedString" + suffix + "Layout.class"));
179 return URLClassLoader.newInstance(new URL[] {jarURI.toURL()});
180 }
181
182 static URLClassLoader compileAndCreateClassLoader(final String suffix) throws IOException {
183 final File workDir = compile(suffix);
184 return URLClassLoader.newInstance(new URL[] {workDir.toURI().toURL()});
185 }
186
187 static File compile(final String suffix) throws IOException {
188 final File orig = new File("target/test-classes/customplugin/FixedStringLayout.java.source");
189 final File workDir = new File(WORK_DIR, "resolverutil" + suffix);
190 final File f = new File(workDir, "customplugin" + suffix + "/FixedString" + suffix + "Layout.java");
191 final File parent = f.getParentFile();
192 if (!parent.exists()) {
193 assertTrue("Create customplugin" + suffix + " folder KO", f.getParentFile().mkdirs());
194 }
195
196 final String content = new String(Files.readAllBytes(orig.toPath()))
197 .replaceAll("FixedString", "FixedString" + suffix)
198 .replaceAll("customplugin", "customplugin" + suffix);
199 Files.write(f.toPath(), content.getBytes());
200
201 PluginManagerPackagesTest.compile(f);
202 return workDir;
203 }
204
205 static void createJar(final URI jarURI, final File workDir, final File f) throws Exception {
206 final Map<String, String> env = new HashMap<>();
207 env.put("create", "true");
208 final URI uri = URI.create("jar:file://" + jarURI.getRawPath());
209 try (FileSystem zipfs = FileSystems.newFileSystem(uri, env)) {
210 final Path path = zipfs.getPath(workDir.toPath().relativize(f.toPath()).toString());
211 if (path.getParent() != null) {
212 Files.createDirectories(path.getParent());
213 }
214 Files.copy(f.toPath(),
215 path,
216 StandardCopyOption.REPLACE_EXISTING );
217 }
218 }
219
168220 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.config.plugins.validation;
17
18 import org.apache.logging.log4j.core.config.plugins.PluginBuilderAttribute;
19 import org.apache.logging.log4j.core.config.plugins.validation.constraints.Required;
20
21 /**
22 *
23 */
24 public class AbstractPluginWithGenericBuilder {
25
26 public static abstract class Builder<B extends Builder<B>> {
27
28 @PluginBuilderAttribute
29 @Required(message = "The thing given by the builder is null")
30 private String thing;
31
32 @SuppressWarnings("unchecked")
33 public B asBuilder() {
34 return (B) this;
35 }
36
37 public String getThing() {
38 return thing;
39 }
40
41 public B withThing(final String name) {
42 this.thing = name;
43 return asBuilder();
44 }
45
46 }
47
48 private final String thing;
49
50 public AbstractPluginWithGenericBuilder(final String thing) {
51 super();
52 this.thing = thing;
53 }
54
55 public String getThing() {
56 return thing;
57 }
58 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.config.plugins.validation;
17
18 import org.apache.logging.log4j.core.config.plugins.Plugin;
19 import org.apache.logging.log4j.core.config.plugins.PluginBuilderAttribute;
20 import org.apache.logging.log4j.core.config.plugins.PluginBuilderFactory;
21 import org.apache.logging.log4j.core.config.plugins.validation.constraints.Required;
22
23 @Plugin(name = "PluginWithGenericSubclassFoo1Builder", category = "Test")
24 public class PluginWithGenericSubclassFoo1Builder extends AbstractPluginWithGenericBuilder {
25
26 public static class Builder<B extends Builder<B>> extends AbstractPluginWithGenericBuilder.Builder<B>
27 implements org.apache.logging.log4j.core.util.Builder<PluginWithGenericSubclassFoo1Builder> {
28
29 @PluginBuilderFactory
30 public static <B extends Builder<B>> B newBuilder() {
31 return new Builder<B>().asBuilder();
32 }
33
34 @PluginBuilderAttribute
35 @Required(message = "The foo1 given by the builder is null")
36 private String foo1;
37
38 @Override
39 public PluginWithGenericSubclassFoo1Builder build() {
40 return new PluginWithGenericSubclassFoo1Builder(getThing(), getFoo1());
41 }
42
43 public String getFoo1() {
44 return foo1;
45 }
46
47 public B withFoo1(final String foo1) {
48 this.foo1 = foo1;
49 return asBuilder();
50 }
51
52 }
53
54 @PluginBuilderFactory
55 public static <B extends Builder<B>> B newBuilder() {
56 return new Builder<B>().asBuilder();
57 }
58
59 private final String foo1;
60
61 public PluginWithGenericSubclassFoo1Builder(final String thing, final String foo1) {
62 super(thing);
63 this.foo1 = foo1;
64 }
65
66 public String getFoo1() {
67 return foo1;
68 }
69
70 }
5656 @Required(message = "The name given by the builder is null")
5757 private String name;
5858
59 public Builder setName(final String name) {
59 public Builder withName(final String name) {
6060 this.name = name;
6161 return this;
6262 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.config.plugins.validation;
17
18 import java.util.Objects;
19
20 import org.apache.logging.log4j.core.config.plugins.Plugin;
21 import org.apache.logging.log4j.core.config.plugins.PluginBuilderAttribute;
22 import org.apache.logging.log4j.core.config.plugins.PluginBuilderFactory;
23 import org.apache.logging.log4j.core.config.plugins.PluginFactory;
24 import org.apache.logging.log4j.core.config.plugins.validation.constraints.Required;
25
26 /**
27 *
28 */
29 @Plugin(name = "ValidatingPluginWithGenericBuilder", category = "Test")
30 public class ValidatingPluginWithGenericBuilder {
31
32 private final String name;
33
34 public ValidatingPluginWithGenericBuilder(final String name) {
35 this.name = Objects.requireNonNull(name, "name");
36 }
37
38 public String getName() {
39 return name;
40 }
41
42 @PluginFactory
43 public static ValidatingPluginWithGenericBuilder newValidatingPlugin(
44 @Required(message = "The name given by the factory is null") final String name) {
45 return new ValidatingPluginWithGenericBuilder(name);
46 }
47
48 @PluginBuilderFactory
49 public static <B extends Builder<B>> B newBuilder() {
50 return new Builder<B>().asBuilder();
51 }
52
53 public static class Builder<B extends Builder<B>> implements org.apache.logging.log4j.core.util.Builder<ValidatingPluginWithGenericBuilder> {
54
55 @PluginBuilderAttribute
56 @Required(message = "The name given by the builder is null")
57 private String name;
58
59 public B withName(final String name) {
60 this.name = name;
61 return asBuilder();
62 }
63
64 @SuppressWarnings("unchecked")
65 public B asBuilder() {
66 return (B) this;
67 }
68
69 @Override
70 public ValidatingPluginWithGenericBuilder build() {
71 return new ValidatingPluginWithGenericBuilder(name);
72 }
73 }
74 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.config.plugins.validation;
17
18 import java.util.Objects;
19
20 import org.apache.logging.log4j.core.config.plugins.Plugin;
21 import org.apache.logging.log4j.core.config.plugins.PluginBuilderAttribute;
22 import org.apache.logging.log4j.core.config.plugins.PluginBuilderFactory;
23 import org.apache.logging.log4j.core.config.plugins.PluginFactory;
24 import org.apache.logging.log4j.core.config.plugins.validation.constraints.Required;
25
26 /**
27 *
28 */
29 @Plugin(name = "ValidatingPluginWithTypedBuilder", category = "Test")
30 public class ValidatingPluginWithTypedBuilder {
31
32 private final String name;
33
34 public ValidatingPluginWithTypedBuilder(final String name) {
35 this.name = Objects.requireNonNull(name, "name");
36 }
37
38 public String getName() {
39 return name;
40 }
41
42 @PluginFactory
43 public static ValidatingPluginWithTypedBuilder newValidatingPlugin(
44 @Required(message = "The name given by the factory is null") final String name) {
45 return new ValidatingPluginWithTypedBuilder(name);
46 }
47
48 @PluginBuilderFactory
49 public static Builder<Integer> newBuilder() {
50 return new Builder<>();
51 }
52
53 public static class Builder<T> implements org.apache.logging.log4j.core.util.Builder<ValidatingPluginWithTypedBuilder> {
54
55 @PluginBuilderAttribute
56 @Required(message = "The name given by the builder is null")
57 private String name;
58
59 public Builder<T> withName(final String name) {
60 this.name = name;
61 return this;
62 }
63
64 @Override
65 public ValidatingPluginWithTypedBuilder build() {
66 return new ValidatingPluginWithTypedBuilder(name);
67 }
68 }
69 }
3737 final PluginManager manager = new PluginManager("Test");
3838 manager.collectPlugins();
3939 plugin = (PluginType<ValidatingPlugin>) manager.getPluginType("Validator");
40 assertNotNull("Rebuild this module to make sure annotaion processing kicks in.", plugin);
4041 node = new Node(null, "Validator", plugin);
4142 }
4243
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.config.plugins.validation.validators;
17
18 import static org.junit.Assert.assertEquals;
19 import static org.junit.Assert.assertNotNull;
20 import static org.junit.Assert.assertNull;
21
22 import org.apache.logging.log4j.core.config.Node;
23 import org.apache.logging.log4j.core.config.NullConfiguration;
24 import org.apache.logging.log4j.core.config.plugins.util.PluginBuilder;
25 import org.apache.logging.log4j.core.config.plugins.util.PluginManager;
26 import org.apache.logging.log4j.core.config.plugins.util.PluginType;
27 import org.apache.logging.log4j.core.config.plugins.validation.ValidatingPluginWithGenericBuilder;
28 import org.junit.Before;
29 import org.junit.Test;
30
31 public class ValidatingPluginWithGenericBuilderTest {
32
33 private PluginType<ValidatingPluginWithGenericBuilder> plugin;
34 private Node node;
35
36 @SuppressWarnings("unchecked")
37 @Before
38 public void setUp() throws Exception {
39 final PluginManager manager = new PluginManager("Test");
40 manager.collectPlugins();
41 plugin = (PluginType<ValidatingPluginWithGenericBuilder>) manager.getPluginType("ValidatingPluginWithGenericBuilder");
42 assertNotNull("Rebuild this module to make sure annotaion processing kicks in.", plugin);
43 node = new Node(null, "Validator", plugin);
44 }
45
46 @Test
47 public void testNullDefaultValue() throws Exception {
48 final ValidatingPluginWithGenericBuilder validatingPlugin = (ValidatingPluginWithGenericBuilder) new PluginBuilder(plugin)
49 .withConfiguration(new NullConfiguration())
50 .withConfigurationNode(node)
51 .build();
52 assertNull(validatingPlugin);
53 }
54
55 @Test
56 public void testNonNullValue() throws Exception {
57 node.getAttributes().put("name", "foo");
58 final ValidatingPluginWithGenericBuilder validatingPlugin = (ValidatingPluginWithGenericBuilder) new PluginBuilder(plugin)
59 .withConfiguration(new NullConfiguration())
60 .withConfigurationNode(node)
61 .build();
62 assertNotNull(validatingPlugin);
63 assertEquals("foo", validatingPlugin.getName());
64 }
65 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.config.plugins.validation.validators;
17
18 import static org.junit.Assert.assertEquals;
19 import static org.junit.Assert.assertNotNull;
20 import static org.junit.Assert.assertNull;
21
22 import org.apache.logging.log4j.core.config.Node;
23 import org.apache.logging.log4j.core.config.NullConfiguration;
24 import org.apache.logging.log4j.core.config.plugins.util.PluginBuilder;
25 import org.apache.logging.log4j.core.config.plugins.util.PluginManager;
26 import org.apache.logging.log4j.core.config.plugins.util.PluginType;
27 import org.apache.logging.log4j.core.config.plugins.validation.PluginWithGenericSubclassFoo1Builder;
28 import org.junit.Before;
29 import org.junit.Test;
30
31 public class ValidatingPluginWithGenericSubclassFoo1BuilderTest {
32
33 private PluginType<PluginWithGenericSubclassFoo1Builder> plugin;
34 private Node node;
35
36 @SuppressWarnings("unchecked")
37 @Before
38 public void setUp() throws Exception {
39 final PluginManager manager = new PluginManager("Test");
40 manager.collectPlugins();
41 plugin = (PluginType<PluginWithGenericSubclassFoo1Builder>) manager.getPluginType("PluginWithGenericSubclassFoo1Builder");
42 assertNotNull("Rebuild this module to make sure annotaion processing kicks in.", plugin);
43 node = new Node(null, "Validator", plugin);
44 }
45
46 @Test
47 public void testNullDefaultValue() throws Exception {
48 final PluginWithGenericSubclassFoo1Builder validatingPlugin = (PluginWithGenericSubclassFoo1Builder) new PluginBuilder(plugin)
49 .withConfiguration(new NullConfiguration())
50 .withConfigurationNode(node)
51 .build();
52 assertNull(validatingPlugin);
53 }
54
55 @Test
56 public void testNonNullValue() throws Exception {
57 node.getAttributes().put("thing", "thing1");
58 node.getAttributes().put("foo1", "foo1");
59 final PluginWithGenericSubclassFoo1Builder validatingPlugin = (PluginWithGenericSubclassFoo1Builder) new PluginBuilder(plugin)
60 .withConfiguration(new NullConfiguration())
61 .withConfigurationNode(node)
62 .build();
63 assertNotNull(validatingPlugin);
64 assertEquals("thing1", validatingPlugin.getThing());
65 assertEquals("foo1", validatingPlugin.getFoo1());
66 }
67 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.config.plugins.validation.validators;
17
18 import static org.junit.Assert.assertEquals;
19 import static org.junit.Assert.assertNotNull;
20 import static org.junit.Assert.assertNull;
21
22 import org.apache.logging.log4j.core.config.Node;
23 import org.apache.logging.log4j.core.config.NullConfiguration;
24 import org.apache.logging.log4j.core.config.plugins.util.PluginBuilder;
25 import org.apache.logging.log4j.core.config.plugins.util.PluginManager;
26 import org.apache.logging.log4j.core.config.plugins.util.PluginType;
27 import org.apache.logging.log4j.core.config.plugins.validation.ValidatingPluginWithTypedBuilder;
28 import org.junit.Before;
29 import org.junit.Test;
30
31 public class ValidatingPluginWithTypedBuilderTest {
32
33 private PluginType<ValidatingPluginWithTypedBuilder> plugin;
34 private Node node;
35
36 @SuppressWarnings("unchecked")
37 @Before
38 public void setUp() throws Exception {
39 final PluginManager manager = new PluginManager("Test");
40 manager.collectPlugins();
41 plugin = (PluginType<ValidatingPluginWithTypedBuilder>) manager
42 .getPluginType("ValidatingPluginWithTypedBuilder");
43 assertNotNull("Rebuild this module to make sure annotaion processing kicks in.", plugin);
44 node = new Node(null, "Validator", plugin);
45 }
46
47 @Test
48 public void testNullDefaultValue() throws Exception {
49 // @formatter:off
50 final ValidatingPluginWithTypedBuilder validatingPlugin = (ValidatingPluginWithTypedBuilder)
51 new PluginBuilder(plugin).
52 withConfiguration(new NullConfiguration()).
53 withConfigurationNode(node).build();
54 // @formatter:on
55 assertNull(validatingPlugin);
56 }
57
58 @Test
59 public void testNonNullValue() throws Exception {
60 node.getAttributes().put("name", "foo");
61 // @formatter:off
62 final ValidatingPluginWithTypedBuilder validatingPlugin = (ValidatingPluginWithTypedBuilder)
63 new PluginBuilder(plugin).
64 withConfiguration(new NullConfiguration()).
65 withConfigurationNode(node).build();
66 // @formatter:on
67 assertNotNull(validatingPlugin);
68 assertEquals("foo", validatingPlugin.getName());
69 }
70 }
6565 containsString("phrasex=****"),
6666 containsString("test=test"),
6767 containsString("test2=test2default"),
68 containsString("test3=Unknown")
68 containsString("test3=Unknown"),
69 containsString("attribKey=attribValue"),
70 containsString("duplicateKey=nodeValue")
6971 ));
7072 assertThat(events.get(1), allOf(
7173 containsString("user="),
7274 containsString("phrasex=****"),
7375 containsString("test=test"),
7476 containsString("test2=test2default"),
75 containsString("test3=Unknown")
77 containsString("test3=Unknown"),
78 containsString("attribKey=attribValue"),
79 containsString("duplicateKey=nodeValue")
7680 ));
7781 } finally {
7882 System.clearProperty("test");
0 package org.apache.logging.log4j.core.filter;
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 import org.apache.logging.log4j.Level;
19 import org.apache.logging.log4j.Marker;
20 import org.apache.logging.log4j.core.Filter;
21 import org.apache.logging.log4j.core.LogEvent;
22 import org.apache.logging.log4j.core.Logger;
23 import org.apache.logging.log4j.message.Message;
24 import org.junit.Test;
25
26 import static org.junit.Assert.*;
27
28 /**
29 * Tests the AbstractFilter test.
30 */
31 public class AbstractFilterTest {
32
33 @Test
34 public void testUnrolledBackwardsCompatible() {
35 final ConcreteFilter filter = new ConcreteFilter();
36 final Filter.Result expected = Filter.Result.DENY;
37 verifyMethodsWithUnrolledVarargs(filter, Filter.Result.DENY);
38
39 filter.testResult = Filter.Result.ACCEPT;
40 verifyMethodsWithUnrolledVarargs(filter, Filter.Result.ACCEPT);
41 }
42
43 private void verifyMethodsWithUnrolledVarargs(final ConcreteFilter filter, final Filter.Result expected) {
44 final Logger logger = null;
45 final Level level = null;
46 final Marker marker = null;
47 assertEquals(expected, filter.filter(logger, level, marker, "", 1));
48 assertEquals(expected, filter.filter(logger, level, marker, "", 1, 2));
49 assertEquals(expected, filter.filter(logger, level, marker, "", 1, 2, 3));
50 assertEquals(expected, filter.filter(logger, level, marker, "", 1, 2, 3, 4));
51 assertEquals(expected, filter.filter(logger, level, marker, "", 1, 2, 3, 4, 5));
52 assertEquals(expected, filter.filter(logger, level, marker, "", 1, 2, 3, 4, 5, 6));
53 assertEquals(expected, filter.filter(logger, level, marker, "", 1, 2, 3, 4, 5, 6, 7));
54 assertEquals(expected, filter.filter(logger, level, marker, "", 1, 2, 3, 4, 5, 6, 7, 8));
55 assertEquals(expected, filter.filter(logger, level, marker, "", 1, 2, 3, 4, 5, 6, 7, 8, 9));
56 assertEquals(expected, filter.filter(logger, level, marker, "", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
57 }
58
59 /**
60 * Concreted filter class that does not override the methods with unrolled varargs.
61 */
62 static class ConcreteFilter extends AbstractFilter {
63 Result testResult = Result.DENY;
64 @Override
65 public Result filter(final LogEvent event) {
66 return testResult;
67 }
68
69 @Override
70 public Result filter(final Logger logger, final Level level, final Marker marker, final Message msg,
71 final Throwable t) {
72 return testResult;
73 }
74
75 @Override
76 public Result filter(final Logger logger, final Level level, final Marker marker, final Object msg,
77 final Throwable t) {
78 return testResult;
79 }
80
81 @Override
82 public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
83 final Object... params) {
84 return testResult;
85 }
86 }
87 }
0 /* Licensed to the Apache Software Foundation (ASF) under one
1 * or more contributor license agreements. See the NOTICE file
2 * distributed with this work for additional information
3 * regarding copyright ownership. The ASF licenses this file
4 * to you under the Apache License, Version 2.0 (the
5 * "License"); you may not use this file except in compliance
6 * with the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing,
11 * software distributed under the License is distributed on an
12 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
13 * KIND, either express or implied. See the License for the
14 * specific language governing permissions and limitations
15 * under the License.
16 */
17 package org.apache.logging.log4j.core.filter;
18
19 import java.util.List;
20
21 import org.apache.logging.log4j.Logger;
22 import org.apache.logging.log4j.junit.LoggerContextRule;
23 import org.apache.logging.log4j.test.appender.ListAppender;
24 import org.junit.Before;
25 import org.junit.ClassRule;
26 import org.junit.Test;
27
28 import static org.junit.Assert.*;
29 /**
30 * Unit test for <code>BurstFilter</code>.
31 */
32 public class BurstFilterTest {
33
34 private static final String CONFIG = "log4j-burst.xml";
35
36 @ClassRule
37 public static LoggerContextRule context = new LoggerContextRule(CONFIG);
38
39 @Before
40 public void setUp() throws Exception {
41 app = context.getListAppender("ListAppender");
42 filter = (BurstFilter) app.getFilter();
43 assertNotNull("No BurstFilter", filter);
44 }
45
46 private ListAppender app;
47 private BurstFilter filter;
48
49 private final Logger logger = context.getLogger();
50
51 /**
52 * Test BurstFilter by surpassing maximum number of log messages allowed by filter and
53 * making sure only the maximum number are indeed logged, then wait for while and make
54 * sure the filter allows the appropriate number of messages to be logged.
55 */
56 @Test
57 public void test() throws Exception {
58 // exceed the burst limit and make sure no more than 100 errors get logged
59 final long start = System.nanoTime();
60 for (int i = 0; i < 110; i++) {
61 if (i % 10 == 0) {
62 Thread.sleep(200);
63 }
64 logger.info("Logging 110 messages, should only see 100 logs # " + (i + 1));
65 assertTrue("Incorrect number of available slots", filter.getAvailable() < 100);
66 }
67 List<String> msgs = app.getMessages();
68 assertEquals("Incorrect message count. Should be 100, actual " + msgs.size(), 100, msgs.size());
69 app.clear();
70
71 assertTrue("Incorrect number of available slots", filter.getAvailable() < 100);
72 // Allow some of the events to clear
73 Thread.sleep(1500);
74
75 for (int i = 0; i < 110; i++) {
76 logger.info("Waited 1.5 seconds and trying to log again, should see more than 0 and less than 100" + (i + 1));
77 }
78
79 msgs = app.getMessages();
80 assertFalse("No messages were counted.", msgs.isEmpty());
81 assertTrue("Incorrect message count. Should be > 0 and < 100, actual " + msgs.size(), msgs.size() < 100);
82 app.clear();
83
84 filter.clear();
85
86 for (int i = 0; i < 110; i++) {
87 logger.info("Waited 1.5 seconds and trying to log again, should see more than 0 and less than 100" + (i + 1));
88 }
89 assertEquals("", 0, filter.getAvailable());
90 app.clear();
91
92
93 // now log 100 debugs, they shouldn't get through because there are no available slots.
94 for (int i = 0; i < 110; i++) {
95 logger.debug(
96 "TEST FAILED! Logging 110 debug messages, shouldn't see any of them because they are debugs #" + (i + 1));
97 }
98
99 msgs = app.getMessages();
100 assertTrue("Incorrect message count. Should be 0, actual " + msgs.size(), msgs.isEmpty());
101 app.clear();
102
103 // now log 100 warns, they should all get through because the filter's level is set at info
104 for (int i = 0; i < 110; i++) {
105 logger.warn("Logging 110 warn messages, should see all of them because they are warns #" + (i + 1));
106 }
107
108 msgs = app.getMessages();
109 assertEquals("Incorrect message count. Should be 110, actual " + msgs.size(), 110, msgs.size());
110 app.clear();
111
112 // now log 100 errors, they should all get through because the filter level is set at info
113 for (int i = 0; i < 110; i++) {
114 logger.error("Logging 110 error messages, should see all of them because they are errors #" + (i + 1));
115 }
116
117 msgs = app.getMessages();
118 assertEquals("Incorrect message count. Should be 110, actual " + msgs.size(), 110, msgs.size());
119 app.clear();
120
121 // now log 100 fatals, they should all get through because the filter level is set at info
122 for (int i = 0; i < 110; i++) {
123 logger.fatal("Logging 110 fatal messages, should see all of them because they are fatals #" + (i + 1));
124 }
125
126 msgs = app.getMessages();
127 assertEquals("Incorrect message count. Should be 110, actual " + msgs.size(), 110, msgs.size());
128 app.clear();
129
130 // wait and make sure we can log messages again despite the fact we just logged a bunch of warns, errors, fatals
131 Thread.sleep(3100);
132
133 for (int i = 0; i < 110; i++) {
134 logger.debug("Waited 3+ seconds, should see 100 logs #" + (i + 1));
135 }
136 msgs = app.getMessages();
137 assertEquals("Incorrect message count. Should be 100, actual " + msgs.size(), 100, msgs.size());
138 app.clear();
139
140 }
141 }
0 /* Licensed to the Apache Software Foundation (ASF) under one
1 * or more contributor license agreements. See the NOTICE file
2 * distributed with this work for additional information
3 * regarding copyright ownership. The ASF licenses this file
4 * to you under the Apache License, Version 2.0 (the
5 * "License"); you may not use this file except in compliance
6 * with the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing,
11 * software distributed under the License is distributed on an
12 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
13 * KIND, either express or implied. See the License for the
14 * specific language governing permissions and limitations
15 * under the License.
16 */
17 package org.apache.logging.log4j.core.filter;
18
19 import java.util.List;
20
21 import org.apache.logging.log4j.Logger;
22 import org.apache.logging.log4j.junit.LoggerContextRule;
23 import org.apache.logging.log4j.test.appender.ListAppender;
24 import org.junit.Before;
25 import org.junit.ClassRule;
26 import org.junit.Test;
27
28 import static org.junit.Assert.*;
29 /**
30 * Unit test for <code>BurstFilter</code>.
31 */
32 public class BurstFilterTest {
33
34 private static final String CONFIG = "log4j-burst.xml";
35
36 @ClassRule
37 public static LoggerContextRule context = new LoggerContextRule(CONFIG);
38
39 @Before
40 public void setUp() throws Exception {
41 app = context.getListAppender("ListAppender");
42 filter = (BurstFilter) app.getFilter();
43 assertNotNull("No BurstFilter", filter);
44 }
45
46 private ListAppender app;
47 private BurstFilter filter;
48
49 private final Logger logger = context.getLogger();
50
51 /**
52 * Test BurstFilter by surpassing maximum number of log messages allowed by filter and
53 * making sure only the maximum number are indeed logged, then wait for while and make
54 * sure the filter allows the appropriate number of messages to be logged.
55 */
56 @Test
57 public void test() throws Exception {
58 System.nanoTime();
59 for (int i = 0; i < 110; i++) {
60 if (i % 10 == 0) {
61 Thread.sleep(200);
62 }
63 logger.info("Logging 110 messages, should only see 100 logs # " + (i + 1));
64 assertTrue("Incorrect number of available slots", filter.getAvailable() < 100);
65 }
66 List<String> msgs = app.getMessages();
67 assertEquals("Incorrect message count. Should be 100, actual " + msgs.size(), 100, msgs.size());
68 app.clear();
69
70 assertTrue("Incorrect number of available slots", filter.getAvailable() < 100);
71 // Allow some of the events to clear
72 Thread.sleep(1500);
73
74 for (int i = 0; i < 110; i++) {
75 logger.info("Waited 1.5 seconds and trying to log again, should see more than 0 and less than 100" + (i + 1));
76 }
77
78 msgs = app.getMessages();
79 assertFalse("No messages were counted.", msgs.isEmpty());
80 assertTrue("Incorrect message count. Should be > 0 and < 100, actual " + msgs.size(), msgs.size() < 100);
81 app.clear();
82
83 filter.clear();
84
85 for (int i = 0; i < 110; i++) {
86 logger.info("Waited 1.5 seconds and trying to log again, should see more than 0 and less than 100" + (i + 1));
87 }
88 assertEquals("", 0, filter.getAvailable());
89 app.clear();
90
91
92 // now log 100 debugs, they shouldn't get through because there are no available slots.
93 for (int i = 0; i < 110; i++) {
94 logger.debug(
95 "TEST FAILED! Logging 110 debug messages, shouldn't see any of them because they are debugs #" + (i + 1));
96 }
97
98 msgs = app.getMessages();
99 assertTrue("Incorrect message count. Should be 0, actual " + msgs.size(), msgs.isEmpty());
100 app.clear();
101
102 // now log 100 warns, they should all get through because the filter's level is set at info
103 for (int i = 0; i < 110; i++) {
104 logger.warn("Logging 110 warn messages, should see all of them because they are warns #" + (i + 1));
105 }
106
107 msgs = app.getMessages();
108 assertEquals("Incorrect message count. Should be 110, actual " + msgs.size(), 110, msgs.size());
109 app.clear();
110
111 // now log 100 errors, they should all get through because the filter level is set at info
112 for (int i = 0; i < 110; i++) {
113 logger.error("Logging 110 error messages, should see all of them because they are errors #" + (i + 1));
114 }
115
116 msgs = app.getMessages();
117 assertEquals("Incorrect message count. Should be 110, actual " + msgs.size(), 110, msgs.size());
118 app.clear();
119
120 // now log 100 fatals, they should all get through because the filter level is set at info
121 for (int i = 0; i < 110; i++) {
122 logger.fatal("Logging 110 fatal messages, should see all of them because they are fatals #" + (i + 1));
123 }
124
125 msgs = app.getMessages();
126 assertEquals("Incorrect message count. Should be 110, actual " + msgs.size(), 110, msgs.size());
127 app.clear();
128
129 // wait and make sure we can log messages again despite the fact we just logged a bunch of warns, errors, fatals
130 Thread.sleep(3100);
131
132 for (int i = 0; i < 110; i++) {
133 logger.debug("Waited 3+ seconds, should see 100 logs #" + (i + 1));
134 }
135 msgs = app.getMessages();
136 assertEquals("Incorrect message count. Should be 100, actual " + msgs.size(), 100, msgs.size());
137 app.clear();
138
139 }
140 }
3131 import org.apache.logging.log4j.core.config.Configurator;
3232 import org.apache.logging.log4j.core.impl.Log4jLogEvent;
3333 import org.apache.logging.log4j.core.util.KeyValuePair;
34 import org.apache.logging.log4j.junit.ThreadContextMapRule;
3435 import org.apache.logging.log4j.message.SimpleMessage;
3536 import org.apache.logging.log4j.status.StatusLogger;
3637 import org.junit.After;
38 import org.junit.Rule;
3739 import org.junit.Test;
3840
3941 /**
4143 */
4244 public class DynamicThresholdFilterTest {
4345
46 @Rule
47 public final ThreadContextMapRule threadContextRule = new ThreadContextMapRule();
48
4449 @After
4550 public void cleanup() {
4651 final LoggerContext ctx = LoggerContext.getContext(false);
7277 }
7378
7479 @Test
80 public void testFilterWorksWhenParamsArePassedAsArguments() {
81 ThreadContext.put("userid", "testuser");
82 ThreadContext.put("organization", "apache");
83 final KeyValuePair[] pairs = new KeyValuePair[] {
84 new KeyValuePair("testuser", "DEBUG"),
85 new KeyValuePair("JohnDoe", "warn") };
86 final DynamicThresholdFilter filter = DynamicThresholdFilter.createFilter("userid", pairs, Level.ERROR, Filter.Result.ACCEPT, Filter.Result.NEUTRAL);
87 filter.start();
88 assertTrue(filter.isStarted());
89 final Object [] replacements = {"one", "two", "three"};
90 assertSame(Filter.Result.ACCEPT, filter.filter(null, Level.DEBUG, null, "some test message", replacements));
91 assertSame(Filter.Result.ACCEPT, filter.filter(null, Level.DEBUG, null, "some test message", "one", "two", "three"));
92 ThreadContext.clearMap();
93 }
94
95 @Test
7596 public void testConfig() {
76 final LoggerContext ctx = Configurator.initialize("Test1", "target/test-classes/log4j2-dynamicfilter.xml");
77 final Configuration config = ctx.getConfiguration();
78 final Filter filter = config.getFilter();
79 assertNotNull("No DynamicThresholdFilter", filter);
80 assertTrue("Not a DynamicThresholdFilter", filter instanceof DynamicThresholdFilter);
81 final DynamicThresholdFilter dynamic = (DynamicThresholdFilter) filter;
82 final String key = dynamic.getKey();
83 assertNotNull("Key is null", key);
84 assertEquals("Incorrect key value", "loginId", key);
85 final Map<String, Level> map = dynamic.getLevelMap();
86 assertNotNull("Map is null", map);
87 assertEquals("Incorrect number of map elements", 1, map.size());
97 try (final LoggerContext ctx = Configurator.initialize("Test1",
98 "target/test-classes/log4j2-dynamicfilter.xml")) {
99 final Configuration config = ctx.getConfiguration();
100 final Filter filter = config.getFilter();
101 assertNotNull("No DynamicThresholdFilter", filter);
102 assertTrue("Not a DynamicThresholdFilter", filter instanceof DynamicThresholdFilter);
103 final DynamicThresholdFilter dynamic = (DynamicThresholdFilter) filter;
104 final String key = dynamic.getKey();
105 assertNotNull("Key is null", key);
106 assertEquals("Incorrect key value", "loginId", key);
107 final Map<String, Level> map = dynamic.getLevelMap();
108 assertNotNull("Map is null", map);
109 assertEquals("Incorrect number of map elements", 1, map.size());
110 }
88111 }
89112 }
4747 .build();
4848 assertSame(Filter.Result.NEUTRAL, filter.filter(event));
4949 }
50
51 @Test
52 public void testMinimumOnlyLevel() {
53 final LevelRangeFilter filter = LevelRangeFilter.createFilter(Level.ERROR, null, null, null);
54 filter.start();
55 assertTrue(filter.isStarted());
56 assertSame(Filter.Result.NEUTRAL, filter.filter(null, Level.ERROR, null, (Object) null, (Throwable) null));
57 }
58
5059 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.impl;
17
18 import java.lang.reflect.Field;
19
20 import org.apache.logging.log4j.util.SortedArrayStringMap;
21 import org.junit.Test;
22
23 import static org.junit.Assert.*;
24
25 /**
26 * Tests the ContextDataFactory class.
27 */
28 public class ContextDataFactoryPropertySetMissingConstructorTest {
29
30 @Test
31 public void intArgReturnsSortedArrayStringMapIfPropertySpecifiedButMissingIntConstructor() throws Exception {
32 System.setProperty("log4j2.ContextData", FactoryTestStringMapWithoutIntConstructor.class.getName());
33 assertTrue(ContextDataFactory.createContextData(2) instanceof SortedArrayStringMap);
34 SortedArrayStringMap actual = (SortedArrayStringMap) ContextDataFactory.createContextData(2);
35 Field thresholdField = SortedArrayStringMap.class.getDeclaredField("threshold");
36 thresholdField.setAccessible(true);
37 assertEquals(2, thresholdField.getInt(actual));
38 System.clearProperty("log4j2.ContextData");
39 }
40 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.impl;
17
18 import org.junit.Test;
19
20 import static org.junit.Assert.*;
21
22 /**
23 * Tests the ContextDataFactory class.
24 */
25 public class ContextDataFactoryPropertySetTest {
26
27 @Test
28 public void noArgReturnsSpecifiedImplIfPropertySpecified() throws Exception {
29 System.setProperty("log4j2.ContextData", FactoryTestStringMap.class.getName());
30 assertTrue(ContextDataFactory.createContextData() instanceof FactoryTestStringMap);
31 System.clearProperty("log4j2.ContextData");
32 }
33
34 @Test
35 public void intArgReturnsSpecifiedImplIfPropertySpecified() throws Exception {
36 System.setProperty("log4j2.ContextData", FactoryTestStringMap.class.getName());
37 assertTrue(ContextDataFactory.createContextData(2) instanceof FactoryTestStringMap);
38 System.clearProperty("log4j2.ContextData");
39 }
40
41 @Test
42 public void intArgSetsCapacityIfPropertySpecified() throws Exception {
43 System.setProperty("log4j2.ContextData", FactoryTestStringMap.class.getName());
44 FactoryTestStringMap actual = (FactoryTestStringMap) ContextDataFactory.createContextData(2);
45 assertEquals(2, actual.initialCapacity);
46 System.clearProperty("log4j2.ContextData");
47 }
48 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.impl;
17
18 import java.lang.reflect.Field;
19
20 import org.apache.logging.log4j.util.SortedArrayStringMap;
21 import org.junit.Test;
22
23 import static org.junit.Assert.*;
24
25 /**
26 * Tests the ContextDataFactory class.
27 */
28 public class ContextDataFactoryTest {
29 @Test
30 public void noArgReturnsSortedArrayStringMapIfNoPropertySpecified() throws Exception {
31 assertTrue(ContextDataFactory.createContextData() instanceof SortedArrayStringMap);
32 }
33
34 @Test
35 public void intArgReturnsSortedArrayStringMapIfNoPropertySpecified() throws Exception {
36 assertTrue(ContextDataFactory.createContextData(2) instanceof SortedArrayStringMap);
37 }
38
39 @Test
40 public void intArgSetsCapacityIfNoPropertySpecified() throws Exception {
41 SortedArrayStringMap actual = (SortedArrayStringMap) ContextDataFactory.createContextData(2);
42 Field thresholdField = SortedArrayStringMap.class.getDeclaredField("threshold");
43 thresholdField.setAccessible(true);
44 assertEquals(2, thresholdField.getInt(actual));
45 }
46 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.impl;
17
18 import java.util.Map;
19
20 import org.apache.logging.log4j.util.BiConsumer;
21 import org.apache.logging.log4j.util.ReadOnlyStringMap;
22 import org.apache.logging.log4j.util.StringMap;
23 import org.apache.logging.log4j.util.TriConsumer;
24
25 /**
26 * Dummy implementation of the StringMap interface for testing.
27 */
28 public class FactoryTestStringMap implements StringMap {
29 private static final long serialVersionUID = -2035823164390218862L;
30 int initialCapacity;
31
32 public FactoryTestStringMap() {
33 }
34
35 public FactoryTestStringMap(final int initialCapacity) {
36 this.initialCapacity = initialCapacity;
37 }
38
39 @Override
40 public Map<String, String> toMap() {
41 return null;
42 }
43
44 @Override
45 public boolean containsKey(final String key) {
46 return false;
47 }
48
49 @Override
50 public <V> void forEach(final BiConsumer<String, ? super V> action) {
51
52 }
53
54 @Override
55 public <V, S> void forEach(final TriConsumer<String, ? super V, S> action, final S state) {
56
57 }
58
59 @Override
60 public <V> V getValue(final String key) {
61 return null;
62 }
63
64 @Override
65 public boolean isEmpty() {
66 return false;
67 }
68
69 @Override
70 public int size() {
71 return 0;
72 }
73
74 @Override
75 public void clear() {
76
77 }
78
79 @Override
80 public void freeze() {
81
82 }
83
84 @Override
85 public boolean isFrozen() {
86 return false;
87 }
88
89 @Override
90 public void putAll(final ReadOnlyStringMap source) {
91
92 }
93
94 @Override
95 public void putValue(final String key, final Object value) {
96
97 }
98
99 @Override
100 public void remove(final String key) {
101
102 }
103 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.impl;
17
18 import java.util.Map;
19
20 import org.apache.logging.log4j.util.BiConsumer;
21 import org.apache.logging.log4j.util.ReadOnlyStringMap;
22 import org.apache.logging.log4j.util.StringMap;
23 import org.apache.logging.log4j.util.TriConsumer;
24
25 /**
26 * Dummy implementation of the StringMap interface for testing.
27 */
28 public class FactoryTestStringMapWithoutIntConstructor implements StringMap {
29 private static final long serialVersionUID = -3239395494628445052L;
30 int initialCapacity;
31
32 public FactoryTestStringMapWithoutIntConstructor() {
33 }
34
35 @Override
36 public Map<String, String> toMap() {
37 return null;
38 }
39
40 @Override
41 public boolean containsKey(final String key) {
42 return false;
43 }
44
45 @Override
46 public <V> void forEach(final BiConsumer<String, ? super V> action) {
47
48 }
49
50 @Override
51 public <V, S> void forEach(final TriConsumer<String, ? super V, S> action, final S state) {
52
53 }
54
55 @Override
56 public <V> V getValue(final String key) {
57 return null;
58 }
59
60 @Override
61 public boolean isEmpty() {
62 return false;
63 }
64
65 @Override
66 public int size() {
67 return 0;
68 }
69
70 @Override
71 public void clear() {
72
73 }
74
75 @Override
76 public void freeze() {
77
78 }
79
80 @Override
81 public boolean isFrozen() {
82 return false;
83 }
84
85 @Override
86 public void putAll(final ReadOnlyStringMap source) {
87
88 }
89
90 @Override
91 public void putValue(final String key, final Object value) {
92
93 }
94
95 @Override
96 public void remove(final String key) {
97
98 }
99 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.impl;
17
18 import java.io.ByteArrayInputStream;
19 import java.io.ByteArrayOutputStream;
20 import java.io.IOException;
21 import java.io.ObjectInputStream;
22 import java.io.ObjectOutputStream;
23 import java.util.HashMap;
24 import java.util.Map;
25
26 import org.apache.logging.log4j.util.BiConsumer;
27 import org.apache.logging.log4j.util.TriConsumer;
28 import org.junit.Test;
29
30 import static org.junit.Assert.*;
31
32 /**
33 * Tests the JdkMapAdapterStringMap class.
34 */
35 public class JdkMapAdapterStringMapTest {
36
37 @Test(expected = NullPointerException.class)
38 public void testConstructorDisallowsNull() throws Exception {
39 new JdkMapAdapterStringMap(null);
40 }
41
42 @Test
43 public void testToString() {
44 final JdkMapAdapterStringMap original = new JdkMapAdapterStringMap();
45 original.putValue("a", "avalue");
46 original.putValue("a2", "bvalue");
47 original.putValue("B", "Bvalue");
48 original.putValue("C", "Cvalue");
49 original.putValue("3", "3value");
50 assertEquals("{3=3value, B=Bvalue, C=Cvalue, a=avalue, a2=bvalue}", original.toString());
51 }
52
53 @Test
54 public void testSerialization() throws Exception {
55 final JdkMapAdapterStringMap original = new JdkMapAdapterStringMap();
56 original.putValue("a", "avalue");
57 original.putValue("B", "Bvalue");
58 original.putValue("3", "3value");
59
60 final byte[] binary = serialize(original);
61 final JdkMapAdapterStringMap copy = deserialize(binary);
62 assertEquals(original, copy);
63 }
64
65 private byte[] serialize(final JdkMapAdapterStringMap data) throws IOException {
66 final ByteArrayOutputStream arr = new ByteArrayOutputStream();
67 final ObjectOutputStream out = new ObjectOutputStream(arr);
68 out.writeObject(data);
69 return arr.toByteArray();
70 }
71
72 private JdkMapAdapterStringMap deserialize(final byte[] binary) throws IOException, ClassNotFoundException {
73 final ByteArrayInputStream inArr = new ByteArrayInputStream(binary);
74 final ObjectInputStream in = new ObjectInputStream(inArr);
75 final JdkMapAdapterStringMap result = (JdkMapAdapterStringMap) in.readObject();
76 return result;
77 }
78
79 @Test
80 public void testPutAll() throws Exception {
81 final JdkMapAdapterStringMap original = new JdkMapAdapterStringMap();
82 original.putValue("a", "avalue");
83 original.putValue("B", "Bvalue");
84 original.putValue("3", "3value");
85
86 final JdkMapAdapterStringMap other = new JdkMapAdapterStringMap();
87 other.putAll(original);
88 assertEquals(original, other);
89
90 other.putValue("3", "otherValue");
91 assertNotEquals(original, other);
92
93 other.putValue("3", null);
94 assertNotEquals(original, other);
95
96 other.putValue("3", "3value");
97 assertEquals(original, other);
98 }
99
100 @Test
101 public void testPutAll_overwritesSameKeys2() throws Exception {
102 final JdkMapAdapterStringMap original = new JdkMapAdapterStringMap();
103 original.putValue("a", "aORIG");
104 original.putValue("b", "bORIG");
105 original.putValue("c", "cORIG");
106 original.putValue("d", "dORIG");
107 original.putValue("e", "eORIG");
108
109 final JdkMapAdapterStringMap other = new JdkMapAdapterStringMap();
110 other.putValue("1", "11");
111 other.putValue("2", "22");
112 other.putValue("a", "aa");
113 other.putValue("c", "cc");
114 original.putAll(other);
115
116 assertEquals("size after put other", 7, original.size());
117 assertEquals("aa", original.getValue("a"));
118 assertEquals("bORIG", original.getValue("b"));
119 assertEquals("cc", original.getValue("c"));
120 assertEquals("dORIG", original.getValue("d"));
121 assertEquals("eORIG", original.getValue("e"));
122 assertEquals("11", original.getValue("1"));
123 assertEquals("22", original.getValue("2"));
124 }
125
126 @Test
127 public void testPutAll_nullKeyInLargeOriginal() throws Exception {
128 final JdkMapAdapterStringMap original = new JdkMapAdapterStringMap();
129 original.putValue(null, "nullORIG");
130 original.putValue("a", "aORIG");
131 original.putValue("b", "bORIG");
132 original.putValue("c", "cORIG");
133 original.putValue("d", "dORIG");
134 original.putValue("e", "eORIG");
135
136 final JdkMapAdapterStringMap other = new JdkMapAdapterStringMap();
137 other.putValue("1", "11");
138 other.putValue("a", "aa");
139 original.putAll(other);
140
141 assertEquals("size after put other", 7, original.size());
142 assertEquals("aa", original.getValue("a"));
143 assertEquals("bORIG", original.getValue("b"));
144 assertEquals("cORIG", original.getValue("c"));
145 assertEquals("dORIG", original.getValue("d"));
146 assertEquals("eORIG", original.getValue("e"));
147 assertEquals("11", original.getValue("1"));
148 assertEquals("nullORIG", original.getValue(null));
149 }
150
151 @Test
152 public void testPutAll_nullKeyInSmallOriginal() throws Exception {
153 final JdkMapAdapterStringMap original = new JdkMapAdapterStringMap();
154 original.putValue(null, "nullORIG");
155 original.putValue("a", "aORIG");
156 original.putValue("b", "bORIG");
157
158 final JdkMapAdapterStringMap other = new JdkMapAdapterStringMap();
159 other.putValue("1", "11");
160 other.putValue("2", "22");
161 other.putValue("3", "33");
162 other.putValue("a", "aa");
163 original.putAll(other);
164
165 assertEquals("size after put other", 6, original.size());
166 assertEquals("aa", original.getValue("a"));
167 assertEquals("bORIG", original.getValue("b"));
168 assertEquals("11", original.getValue("1"));
169 assertEquals("22", original.getValue("2"));
170 assertEquals("33", original.getValue("3"));
171 assertEquals("nullORIG", original.getValue(null));
172 }
173
174 @Test
175 public void testPutAll_nullKeyInSmallAdditional() throws Exception {
176 final JdkMapAdapterStringMap original = new JdkMapAdapterStringMap();
177 original.putValue("a", "aORIG");
178 original.putValue("b", "bORIG");
179 original.putValue("c", "cORIG");
180 original.putValue("d", "dORIG");
181 original.putValue("e", "eORIG");
182
183 final JdkMapAdapterStringMap other = new JdkMapAdapterStringMap();
184 other.putValue(null, "nullNEW");
185 other.putValue("1", "11");
186 other.putValue("a", "aa");
187 original.putAll(other);
188
189 assertEquals("size after put other", 7, original.size());
190 assertEquals("aa", original.getValue("a"));
191 assertEquals("bORIG", original.getValue("b"));
192 assertEquals("cORIG", original.getValue("c"));
193 assertEquals("dORIG", original.getValue("d"));
194 assertEquals("eORIG", original.getValue("e"));
195 assertEquals("11", original.getValue("1"));
196 assertEquals("nullNEW", original.getValue(null));
197 }
198
199 @Test
200 public void testPutAll_nullKeyInLargeAdditional() throws Exception {
201 final JdkMapAdapterStringMap original = new JdkMapAdapterStringMap();
202 original.putValue("a", "aORIG");
203 original.putValue("b", "bORIG");
204
205 final JdkMapAdapterStringMap other = new JdkMapAdapterStringMap();
206 other.putValue(null, "nullNEW");
207 other.putValue("1", "11");
208 other.putValue("2", "22");
209 other.putValue("3", "33");
210 other.putValue("a", "aa");
211 original.putAll(other);
212
213 assertEquals("size after put other", 6, original.size());
214 assertEquals("aa", original.getValue("a"));
215 assertEquals("bORIG", original.getValue("b"));
216 assertEquals("11", original.getValue("1"));
217 assertEquals("22", original.getValue("2"));
218 assertEquals("33", original.getValue("3"));
219 assertEquals("nullNEW", original.getValue(null));
220 }
221
222 @Test
223 public void testPutAll_nullKeyInBoth_LargeOriginal() throws Exception {
224 final JdkMapAdapterStringMap original = new JdkMapAdapterStringMap();
225 original.putValue(null, "nullORIG");
226 original.putValue("a", "aORIG");
227 original.putValue("b", "bORIG");
228 original.putValue("c", "cORIG");
229 original.putValue("d", "dORIG");
230 original.putValue("e", "eORIG");
231
232 final JdkMapAdapterStringMap other = new JdkMapAdapterStringMap();
233 other.putValue(null, "nullNEW");
234 other.putValue("1", "11");
235 other.putValue("a", "aa");
236 original.putAll(other);
237
238 assertEquals("size after put other", 7, original.size());
239 assertEquals("aa", original.getValue("a"));
240 assertEquals("bORIG", original.getValue("b"));
241 assertEquals("cORIG", original.getValue("c"));
242 assertEquals("dORIG", original.getValue("d"));
243 assertEquals("eORIG", original.getValue("e"));
244 assertEquals("11", original.getValue("1"));
245 assertEquals("nullNEW", original.getValue(null));
246 }
247
248 @Test
249 public void testPutAll_nullKeyInBoth_SmallOriginal() throws Exception {
250 final JdkMapAdapterStringMap original = new JdkMapAdapterStringMap();
251 original.putValue(null, "nullORIG");
252 original.putValue("a", "aORIG");
253 original.putValue("b", "bORIG");
254
255 final JdkMapAdapterStringMap other = new JdkMapAdapterStringMap();
256 other.putValue(null, "nullNEW");
257 other.putValue("1", "11");
258 other.putValue("2", "22");
259 other.putValue("3", "33");
260 other.putValue("a", "aa");
261 original.putAll(other);
262
263 assertEquals("size after put other", 6, original.size());
264 assertEquals("aa", original.getValue("a"));
265 assertEquals("bORIG", original.getValue("b"));
266 assertEquals("11", original.getValue("1"));
267 assertEquals("22", original.getValue("2"));
268 assertEquals("33", original.getValue("3"));
269 assertEquals("nullNEW", original.getValue(null));
270 }
271
272 @Test
273 public void testPutAll_overwritesSameKeys1() throws Exception {
274 final JdkMapAdapterStringMap original = new JdkMapAdapterStringMap();
275 original.putValue("a", "aORIG");
276 original.putValue("b", "bORIG");
277 original.putValue("c", "cORIG");
278
279 final JdkMapAdapterStringMap other = new JdkMapAdapterStringMap();
280 other.putValue("1", "11");
281 other.putValue("2", "22");
282 other.putValue("a", "aa");
283 other.putValue("c", "cc");
284 original.putAll(other);
285
286 assertEquals("size after put other", 5, original.size());
287 assertEquals("aa", original.getValue("a"));
288 assertEquals("bORIG", original.getValue("b"));
289 assertEquals("cc", original.getValue("c"));
290 assertEquals("11", original.getValue("1"));
291 assertEquals("22", original.getValue("2"));
292 }
293
294 @Test
295 public void testEquals() {
296 final JdkMapAdapterStringMap original = new JdkMapAdapterStringMap();
297 original.putValue("a", "avalue");
298 original.putValue("B", "Bvalue");
299 original.putValue("3", "3value");
300 assertEquals(original, original); // equal to itself
301
302 final JdkMapAdapterStringMap other = new JdkMapAdapterStringMap();
303 other.putValue("a", "avalue");
304 assertNotEquals(original, other);
305
306 other.putValue("B", "Bvalue");
307 assertNotEquals(original, other);
308
309 other.putValue("3", "3value");
310 assertEquals(original, other);
311
312 other.putValue("3", "otherValue");
313 assertNotEquals(original, other);
314
315 other.putValue("3", null);
316 assertNotEquals(original, other);
317
318 other.putValue("3", "3value");
319 assertEquals(original, other);
320 }
321
322 @Test
323 public void testToMap() throws Exception {
324 final JdkMapAdapterStringMap original = new JdkMapAdapterStringMap();
325 original.putValue("a", "avalue");
326 original.putValue("B", "Bvalue");
327 original.putValue("3", "3value");
328
329 final Map<String, Object> expected = new HashMap<>();
330 expected.put("a", "avalue");
331 expected.put("B", "Bvalue");
332 expected.put("3", "3value");
333
334 assertEquals(expected, original.toMap());
335
336 try {
337 original.toMap().put("abc", "xyz");
338 } catch (final UnsupportedOperationException ex) {
339 fail("Expected map to be mutable, but " + ex);
340 }
341 }
342
343 @Test
344 public void testPutAll_KeepsExistingValues() {
345 final JdkMapAdapterStringMap original = new JdkMapAdapterStringMap();
346 original.putValue("a", "aaa");
347 original.putValue("b", "bbb");
348 original.putValue("c", "ccc");
349 assertEquals("size", 3, original.size());
350
351 // add empty context data
352 original.putAll(new JdkMapAdapterStringMap());
353 assertEquals("size after put empty", 3, original.size());
354 assertEquals("aaa", original.getValue("a"));
355 assertEquals("bbb", original.getValue("b"));
356 assertEquals("ccc", original.getValue("c"));
357
358 final JdkMapAdapterStringMap other = new JdkMapAdapterStringMap();
359 other.putValue("1", "111");
360 other.putValue("2", "222");
361 other.putValue("3", "333");
362 original.putAll(other);
363
364 assertEquals("size after put other", 6, original.size());
365 assertEquals("aaa", original.getValue("a"));
366 assertEquals("bbb", original.getValue("b"));
367 assertEquals("ccc", original.getValue("c"));
368 assertEquals("111", original.getValue("1"));
369 assertEquals("222", original.getValue("2"));
370 assertEquals("333", original.getValue("3"));
371 }
372
373 @Test
374 public void testPutAll_sizePowerOfTwo() {
375 final JdkMapAdapterStringMap original = new JdkMapAdapterStringMap();
376 original.putValue("a", "aaa");
377 original.putValue("b", "bbb");
378 original.putValue("c", "ccc");
379 original.putValue("d", "ddd");
380 assertEquals("size", 4, original.size());
381
382 // add empty context data
383 original.putAll(new JdkMapAdapterStringMap());
384 assertEquals("size after put empty", 4, original.size());
385 assertEquals("aaa", original.getValue("a"));
386 assertEquals("bbb", original.getValue("b"));
387 assertEquals("ccc", original.getValue("c"));
388 assertEquals("ddd", original.getValue("d"));
389
390 final JdkMapAdapterStringMap other = new JdkMapAdapterStringMap();
391 other.putValue("1", "111");
392 other.putValue("2", "222");
393 other.putValue("3", "333");
394 other.putValue("4", "444");
395 original.putAll(other);
396
397 assertEquals("size after put other", 8, original.size());
398 assertEquals("aaa", original.getValue("a"));
399 assertEquals("bbb", original.getValue("b"));
400 assertEquals("ccc", original.getValue("c"));
401 assertEquals("ddd", original.getValue("d"));
402 assertEquals("111", original.getValue("1"));
403 assertEquals("222", original.getValue("2"));
404 assertEquals("333", original.getValue("3"));
405 assertEquals("444", original.getValue("4"));
406 }
407
408 @Test
409 public void testPutAll_largeAddition() {
410 final JdkMapAdapterStringMap original = new JdkMapAdapterStringMap();
411 original.putValue(null, "nullVal");
412 original.putValue("a", "aaa");
413 original.putValue("b", "bbb");
414 original.putValue("c", "ccc");
415 original.putValue("d", "ddd");
416 assertEquals("size", 5, original.size());
417
418 final JdkMapAdapterStringMap other = new JdkMapAdapterStringMap();
419 for (int i = 0 ; i < 500; i++) {
420 other.putValue(String.valueOf(i), String.valueOf(i));
421 }
422 other.putValue(null, "otherVal");
423 original.putAll(other);
424
425 assertEquals("size after put other", 505, original.size());
426 assertEquals("otherVal", original.getValue(null));
427 assertEquals("aaa", original.getValue("a"));
428 assertEquals("bbb", original.getValue("b"));
429 assertEquals("ccc", original.getValue("c"));
430 assertEquals("ddd", original.getValue("d"));
431 for (int i = 0 ; i < 500; i++) {
432 assertEquals(String.valueOf(i), original.getValue(String.valueOf(i)));
433 }
434 }
435
436 @Test
437 public void testPutAllSelfDoesNotModify() {
438 final JdkMapAdapterStringMap original = new JdkMapAdapterStringMap();
439 original.putValue("a", "aaa");
440 original.putValue("b", "bbb");
441 original.putValue("c", "ccc");
442 assertEquals("size", 3, original.size());
443
444 // putAll with self
445 original.putAll(original);
446 assertEquals("size after put empty", 3, original.size());
447 assertEquals("aaa", original.getValue("a"));
448 assertEquals("bbb", original.getValue("b"));
449 assertEquals("ccc", original.getValue("c"));
450 }
451
452 @Test
453 public void testNoConcurrentModificationBiConsumerPut() {
454 final JdkMapAdapterStringMap original = new JdkMapAdapterStringMap();
455 original.putValue("a", "aaa");
456 original.putValue("b", "aaa");
457 original.putValue("c", "aaa");
458 original.putValue("d", "aaa");
459 original.putValue("e", "aaa");
460 original.forEach(new BiConsumer<String, Object>() {
461 @Override
462 public void accept(final String s, final Object o) {
463 original.putValue("c" + s, "other");
464 }
465 });
466 }
467
468 @Test
469 public void testNoConcurrentModificationBiConsumerPutValue() {
470 final JdkMapAdapterStringMap original = new JdkMapAdapterStringMap();
471 original.putValue("a", "aaa");
472 original.putValue("b", "aaa");
473 original.putValue("c", "aaa");
474 original.putValue("d", "aaa");
475 original.putValue("e", "aaa");
476 original.forEach(new BiConsumer<String, Object>() {
477 @Override
478 public void accept(final String s, final Object o) {
479 original.putValue("c" + s, "other");
480 }
481 });
482 }
483
484 @Test
485 public void testNoConcurrentModificationBiConsumerRemove() {
486 final JdkMapAdapterStringMap original = new JdkMapAdapterStringMap();
487 original.putValue("a", "aaa");
488 original.putValue("b", "aaa");
489 original.putValue("c", "aaa");
490 original.forEach(new BiConsumer<String, Object>() {
491 @Override
492 public void accept(final String s, final Object o) {
493 original.remove("a");
494 }
495 });
496 }
497
498 @Test
499 public void testNoConcurrentModificationBiConsumerClear() {
500 final JdkMapAdapterStringMap original = new JdkMapAdapterStringMap();
501 original.putValue("a", "aaa");
502 original.putValue("b", "aaa");
503 original.putValue("c", "aaa");
504 original.putValue("d", "aaa");
505 original.putValue("e", "aaa");
506 original.forEach(new BiConsumer<String, Object>() {
507 @Override
508 public void accept(final String s, final Object o) {
509 original.clear();
510 }
511 });
512 }
513
514 @Test
515 public void testNoConcurrentModificationTriConsumerPut() {
516 final JdkMapAdapterStringMap original = new JdkMapAdapterStringMap();
517 original.putValue("a", "aaa");
518 original.putValue("b", "aaa");
519 original.putValue("d", "aaa");
520 original.putValue("e", "aaa");
521 original.forEach(new TriConsumer<String, Object, Object>() {
522 @Override
523 public void accept(final String s, final Object o, final Object o2) {
524 original.putValue("c", "other");
525 }
526 }, null);
527 }
528
529 @Test
530 public void testNoConcurrentModificationTriConsumerPutValue() {
531 final JdkMapAdapterStringMap original = new JdkMapAdapterStringMap();
532 original.putValue("a", "aaa");
533 original.putValue("b", "aaa");
534 original.putValue("c", "aaa");
535 original.putValue("d", "aaa");
536 original.putValue("e", "aaa");
537 original.forEach(new TriConsumer<String, Object, Object>() {
538 @Override
539 public void accept(final String s, final Object o, final Object o2) {
540 original.putValue("c" + s, "other");
541 }
542 }, null);
543 }
544
545 @Test
546 public void testNoConcurrentModificationTriConsumerRemove() {
547 final JdkMapAdapterStringMap original = new JdkMapAdapterStringMap();
548 original.putValue("a", "aaa");
549 original.putValue("b", "aaa");
550 original.putValue("c", "aaa");
551 original.forEach(new TriConsumer<String, Object, Object>() {
552 @Override
553 public void accept(final String s, final Object o, final Object o2) {
554 original.remove("a");
555 }
556 }, null);
557 }
558
559 @Test
560 public void testNoConcurrentModificationTriConsumerClear() {
561 final JdkMapAdapterStringMap original = new JdkMapAdapterStringMap();
562 original.putValue("a", "aaa");
563 original.putValue("b", "aaa");
564 original.putValue("c", "aaa");
565 original.putValue("d", "aaa");
566 original.forEach(new TriConsumer<String, Object, Object>() {
567 @Override
568 public void accept(final String s, final Object o, final Object o2) {
569 original.clear();
570 }
571 }, null);
572 }
573
574 @Test
575 public void testInitiallyNotFrozen() {
576 assertFalse(new JdkMapAdapterStringMap().isFrozen());
577 }
578
579 @Test
580 public void testIsFrozenAfterCallingFreeze() {
581 final JdkMapAdapterStringMap original = new JdkMapAdapterStringMap();
582 assertFalse("before freeze", original.isFrozen());
583 original.freeze();
584 assertTrue("after freeze", original.isFrozen());
585 }
586
587 @Test(expected = UnsupportedOperationException.class)
588 public void testFreezeProhibitsPutValue() {
589 final JdkMapAdapterStringMap original = new JdkMapAdapterStringMap();
590 original.freeze();
591 original.putValue("a", "aaa");
592 }
593
594 @Test(expected = UnsupportedOperationException.class)
595 public void testFreezeProhibitsRemove() {
596 final JdkMapAdapterStringMap original = new JdkMapAdapterStringMap();
597 original.putValue("b", "bbb");
598 original.freeze();
599 original.remove("b"); // existing key: modifies the collection
600 }
601
602 @Test
603 public void testFreezeAllowsRemoveOfNonExistingKey() {
604 final JdkMapAdapterStringMap original = new JdkMapAdapterStringMap();
605 original.putValue("b", "bbb");
606 original.freeze();
607 original.remove("a"); // no actual modification
608 }
609
610 @Test
611 public void testFreezeAllowsRemoveIfEmpty() {
612 final JdkMapAdapterStringMap original = new JdkMapAdapterStringMap();
613 original.freeze();
614 original.remove("a"); // no exception
615 }
616
617 @Test(expected = UnsupportedOperationException.class)
618 public void testFreezeProhibitsClear() {
619 final JdkMapAdapterStringMap original = new JdkMapAdapterStringMap();
620 original.putValue("a", "aaa");
621 original.freeze();
622 original.clear();
623 }
624
625 @Test
626 public void testFreezeAllowsClearIfEmpty() {
627 final JdkMapAdapterStringMap original = new JdkMapAdapterStringMap();
628 original.freeze();
629 original.clear();
630 }
631
632 @Test
633 public void testNullKeysAllowed() {
634 final JdkMapAdapterStringMap original = new JdkMapAdapterStringMap();
635 original.putValue("a", "avalue");
636 original.putValue("B", "Bvalue");
637 original.putValue("3", "3value");
638 original.putValue("c", "cvalue");
639 original.putValue("d", "dvalue");
640 assertEquals(5, original.size());
641
642 original.putValue(null, "nullvalue");
643 assertEquals(6, original.size());
644 assertEquals("nullvalue", original.getValue(null));
645
646 original.putValue(null, "otherNullvalue");
647 assertEquals("otherNullvalue", original.getValue(null));
648 assertEquals(6, original.size());
649
650 original.putValue(null, "nullvalue");
651 assertEquals(6, original.size());
652 assertEquals("nullvalue", original.getValue(null));
653
654 original.putValue(null, "abc");
655 assertEquals(6, original.size());
656 assertEquals("abc", original.getValue(null));
657
658 }
659
660 @Test
661 public void testNullKeysCopiedToAsMap() {
662 final JdkMapAdapterStringMap original = new JdkMapAdapterStringMap();
663 original.putValue("a", "avalue");
664 original.putValue("B", "Bvalue");
665 original.putValue("3", "3value");
666 original.putValue("c", "cvalue");
667 original.putValue("d", "dvalue");
668 assertEquals(5, original.size());
669
670 final HashMap<String, String> expected = new HashMap<>();
671 expected.put("a", "avalue");
672 expected.put("B", "Bvalue");
673 expected.put("3", "3value");
674 expected.put("c", "cvalue");
675 expected.put("d", "dvalue");
676 assertEquals("initial", expected, original.toMap());
677
678 original.putValue(null, "nullvalue");
679 expected.put(null, "nullvalue");
680 assertEquals(6, original.size());
681 assertEquals("with null key", expected, original.toMap());
682
683 original.putValue(null, "otherNullvalue");
684 expected.put(null, "otherNullvalue");
685 assertEquals(6, original.size());
686 assertEquals("with null key value2", expected, original.toMap());
687
688 original.putValue(null, "nullvalue");
689 expected.put(null, "nullvalue");
690 assertEquals(6, original.size());
691 assertEquals("with null key value1 again", expected, original.toMap());
692
693 original.putValue(null, "abc");
694 expected.put(null, "abc");
695 assertEquals(6, original.size());
696 assertEquals("with null key value3", expected, original.toMap());
697 }
698
699 @Test
700 public void testRemove() {
701 final JdkMapAdapterStringMap original = new JdkMapAdapterStringMap();
702 original.putValue("a", "avalue");
703 assertEquals(1, original.size());
704 assertEquals("avalue", original.getValue("a"));
705
706 original.remove("a");
707 assertEquals(0, original.size());
708 assertNull("no a val", original.getValue("a"));
709
710 original.remove("B");
711 assertEquals(0, original.size());
712 assertNull("no B val", original.getValue("B"));
713 }
714
715 @Test
716 public void testRemoveWhenFull() throws Exception {
717 final JdkMapAdapterStringMap original = new JdkMapAdapterStringMap();
718 original.putValue("a", "avalue");
719 original.putValue("b", "bvalue");
720 original.putValue("c", "cvalue");
721 original.putValue("d", "dvalue"); // default capacity = 4
722 original.remove("d");
723 }
724
725 @Test
726 public void testNullValuesArePreserved() {
727 final JdkMapAdapterStringMap original = new JdkMapAdapterStringMap();
728 original.putValue("a", "avalue");
729 assertEquals(1, original.size());
730 assertEquals("avalue", original.getValue("a"));
731
732 original.putValue("a", null);
733 assertEquals(1, original.size());
734 assertNull("no a val", original.getValue("a"));
735
736 original.putValue("B", null);
737 assertEquals(2, original.size());
738 assertNull("no B val", original.getValue("B"));
739 }
740
741 @Test
742 public void testGet() throws Exception {
743 final JdkMapAdapterStringMap original = new JdkMapAdapterStringMap();
744 original.putValue("a", "avalue");
745 original.putValue("B", "Bvalue");
746 original.putValue("3", "3value");
747
748 assertEquals("avalue", original.getValue("a"));
749 assertEquals("Bvalue", original.getValue("B"));
750 assertEquals("3value", original.getValue("3"));
751
752 original.putValue("0", "0value");
753 assertEquals("0value", original.getValue("0"));
754 assertEquals("3value", original.getValue("3"));
755 assertEquals("Bvalue", original.getValue("B"));
756 assertEquals("avalue", original.getValue("a"));
757 }
758
759 @Test
760 public void testClear() throws Exception {
761 final JdkMapAdapterStringMap original = new JdkMapAdapterStringMap();
762 original.putValue("a", "avalue");
763 original.putValue("B", "Bvalue");
764 original.putValue("3", "3value");
765 assertEquals(3, original.size());
766
767 original.clear();
768 assertEquals(0, original.size());
769 }
770
771 @Test
772 public void testContainsKey() throws Exception {
773 final JdkMapAdapterStringMap original = new JdkMapAdapterStringMap();
774 assertFalse("a", original.containsKey("a"));
775 assertFalse("B", original.containsKey("B"));
776 assertFalse("3", original.containsKey("3"));
777 assertFalse("A", original.containsKey("A"));
778
779 original.putValue("a", "avalue");
780 assertTrue("a", original.containsKey("a"));
781 assertFalse("B", original.containsKey("B"));
782 assertFalse("3", original.containsKey("3"));
783 assertFalse("A", original.containsKey("A"));
784
785 original.putValue("B", "Bvalue");
786 assertTrue("a", original.containsKey("a"));
787 assertTrue("B", original.containsKey("B"));
788 assertFalse("3", original.containsKey("3"));
789 assertFalse("A", original.containsKey("A"));
790
791 original.putValue("3", "3value");
792 assertTrue("a", original.containsKey("a"));
793 assertTrue("B", original.containsKey("B"));
794 assertTrue("3", original.containsKey("3"));
795 assertFalse("A", original.containsKey("A"));
796
797 original.putValue("A", "AAA");
798 assertTrue("a", original.containsKey("a"));
799 assertTrue("B", original.containsKey("B"));
800 assertTrue("3", original.containsKey("3"));
801 assertTrue("A", original.containsKey("A"));
802 }
803
804 @Test
805 public void testSizeAndIsEmpty() throws Exception {
806 final JdkMapAdapterStringMap original = new JdkMapAdapterStringMap();
807 assertEquals(0, original.size());
808 assertTrue("initial", original.isEmpty());
809
810 original.putValue("a", "avalue");
811 assertEquals(1, original.size());
812 assertFalse("size=" + original.size(), original.isEmpty());
813
814 original.putValue("B", "Bvalue");
815 assertEquals(2, original.size());
816 assertFalse("size=" + original.size(), original.isEmpty());
817
818 original.putValue("3", "3value");
819 assertEquals(3, original.size());
820 assertFalse("size=" + original.size(), original.isEmpty());
821
822 original.remove("B");
823 assertEquals(2, original.size());
824 assertFalse("size=" + original.size(), original.isEmpty());
825
826 original.remove("3");
827 assertEquals(1, original.size());
828 assertFalse("size=" + original.size(), original.isEmpty());
829
830 original.remove("a");
831 assertEquals(0, original.size());
832 assertTrue("size=" + original.size(), original.isEmpty());
833 }
834
835 @Test
836 public void testForEachBiConsumer() throws Exception {
837 final JdkMapAdapterStringMap original = new JdkMapAdapterStringMap();
838 original.putValue("a", "avalue");
839 original.putValue("B", "Bvalue");
840 original.putValue("3", "3value");
841
842 original.forEach(new BiConsumer<String, String>() {
843 int count = 0;
844 @Override
845 public void accept(final String key, final String value) {
846 // assertEquals("key", key, original.getKeyAt(count));
847 // assertEquals("val", value, original.getValueAt(count));
848 count++;
849 assertTrue("count should not exceed size but was " + count, count <= original.size());
850 }
851 });
852 }
853
854 static class State {
855 JdkMapAdapterStringMap data;
856 int count;
857 }
858 static TriConsumer<String, String, JdkMapAdapterStringMapTest.State> COUNTER = new TriConsumer<String, String, JdkMapAdapterStringMapTest.State>() {
859 @Override
860 public void accept(final String key, final String value, final JdkMapAdapterStringMapTest.State state) {
861 // assertEquals("key", key, state.data.getKeyAt(state.count));
862 // assertEquals("val", value, state.data.getValueAt(state.count));
863 state.count++;
864 assertTrue("count should not exceed size but was " + state.count,
865 state.count <= state.data.size());
866 }
867 };
868
869 @Test
870 public void testForEachTriConsumer() throws Exception {
871 final JdkMapAdapterStringMap original = new JdkMapAdapterStringMap();
872 original.putValue("a", "avalue");
873 original.putValue("B", "Bvalue");
874 original.putValue("3", "3value");
875
876 final JdkMapAdapterStringMapTest.State state = new JdkMapAdapterStringMapTest.State();
877 state.data = original;
878 original.forEach(COUNTER, state);
879 assertEquals(state.count, original.size());
880 }
881
882 }
2424 import java.util.Collections;
2525 import java.util.HashMap;
2626 import java.util.Map;
27
2827 import javax.xml.bind.DatatypeConverter;
2928
3029 import org.apache.logging.log4j.Level;
4039 import org.apache.logging.log4j.message.Message;
4140 import org.apache.logging.log4j.message.ObjectMessage;
4241 import org.apache.logging.log4j.message.SimpleMessage;
42 import org.apache.logging.log4j.util.SortedArrayStringMap;
43 import org.apache.logging.log4j.util.StringMap;
4344 import org.apache.logging.log4j.util.Strings;
4445 import org.junit.AfterClass;
4546 import org.junit.BeforeClass;
174175 // System.out.println("final String base64 = \"" + base64Str.replaceAll("\r\n", "\\\\r\\\\n\" +\r\n\"") +
175176 // "\";");
176177
177 //final String base64_v_2_5 = "rO0ABXNyAD5vcmcuYXBhY2hlLmxvZ2dpbmcubG9nNGouY29yZS5pbXBsLkxvZzRqTG9nRXZlbnQkTG9nRXZlbnRQcm94eZztD11w2ioWAgANWgAMaXNFbmRPZkJhdGNoWgASaXNMb2NhdGlvblJlcXVpcmVkSgAKdGltZU1pbGxpc0wACmNvbnRleHRNYXB0AA9MamF2YS91dGlsL01hcDtMAAxjb250ZXh0U3RhY2t0ADVMb3JnL2FwYWNoZS9sb2dnaW5nL2xvZzRqL1RocmVhZENvbnRleHQkQ29udGV4dFN0YWNrO0wABWxldmVsdAAgTG9yZy9hcGFjaGUvbG9nZ2luZy9sb2c0ai9MZXZlbDtMAApsb2dnZXJGUUNOdAASTGphdmEvbGFuZy9TdHJpbmc7TAAKbG9nZ2VyTmFtZXEAfgAETAAGbWFya2VydAAhTG9yZy9hcGFjaGUvbG9nZ2luZy9sb2c0ai9NYXJrZXI7TAAHbWVzc2FnZXQAKkxvcmcvYXBhY2hlL2xvZ2dpbmcvbG9nNGovbWVzc2FnZS9NZXNzYWdlO0wABnNvdXJjZXQAHUxqYXZhL2xhbmcvU3RhY2tUcmFjZUVsZW1lbnQ7TAAKdGhyZWFkTmFtZXEAfgAETAALdGhyb3duUHJveHl0ADNMb3JnL2FwYWNoZS9sb2dnaW5nL2xvZzRqL2NvcmUvaW1wbC9UaHJvd2FibGVQcm94eTt4cAAAAAAAAEmWAtJzcgAeamF2YS51dGlsLkNvbGxlY3Rpb25zJEVtcHR5TWFwWTYUhVrc59ACAAB4cHNyAD5vcmcuYXBhY2hlLmxvZ2dpbmcubG9nNGouVGhyZWFkQ29udGV4dCRFbXB0eVRocmVhZENvbnRleHRTdGFjawAAAAAAAAABAgAAeHBzcgAeb3JnLmFwYWNoZS5sb2dnaW5nLmxvZzRqLkxldmVsAAAAAAAYIBoCAANJAAhpbnRMZXZlbEwABG5hbWVxAH4ABEwADXN0YW5kYXJkTGV2ZWx0ACxMb3JnL2FwYWNoZS9sb2dnaW5nL2xvZzRqL3NwaS9TdGFuZGFyZExldmVsO3hwAAABkHQABElORk9+cgAqb3JnLmFwYWNoZS5sb2dnaW5nLmxvZzRqLnNwaS5TdGFuZGFyZExldmVsAAAAAAAAAAASAAB4cgAOamF2YS5sYW5nLkVudW0AAAAAAAAAABIAAHhwdAAESU5GT3QAAHQACXNvbWUudGVzdHBzcgAub3JnLmFwYWNoZS5sb2dnaW5nLmxvZzRqLm1lc3NhZ2UuU2ltcGxlTWVzc2FnZYt0TTBgt6KoAgABTAAHbWVzc2FnZXEAfgAEeHB0AANhYmNwdAAEbWFpbnNyADFvcmcuYXBhY2hlLmxvZ2dpbmcubG9nNGouY29yZS5pbXBsLlRocm93YWJsZVByb3h52cww1Zp7rPoCAAdJABJjb21tb25FbGVtZW50Q291bnRMAApjYXVzZVByb3h5cQB+AAhbABJleHRlbmRlZFN0YWNrVHJhY2V0AD9bTG9yZy9hcGFjaGUvbG9nZ2luZy9sb2c0ai9jb3JlL2ltcGwvRXh0ZW5kZWRTdGFja1RyYWNlRWxlbWVudDtMABBsb2NhbGl6ZWRNZXNzYWdlcQB+AARMAAdtZXNzYWdlcQB+AARMAARuYW1lcQB+AARbABFzdXBwcmVzc2VkUHJveGllc3QANFtMb3JnL2FwYWNoZS9sb2dnaW5nL2xvZzRqL2NvcmUvaW1wbC9UaHJvd2FibGVQcm94eTt4cAAAAABwdXIAP1tMb3JnLmFwYWNoZS5sb2dnaW5nLmxvZzRqLmNvcmUuaW1wbC5FeHRlbmRlZFN0YWNrVHJhY2VFbGVtZW50O8rPiCOlx8+8AgAAeHAAAAAac3IAPG9yZy5hcGFjaGUubG9nZ2luZy5sb2c0ai5jb3JlLmltcGwuRXh0ZW5kZWRTdGFja1RyYWNlRWxlbWVudOHez7rGtpAHAgACTAAOZXh0cmFDbGFzc0luZm90ADZMb3JnL2FwYWNoZS9sb2dnaW5nL2xvZzRqL2NvcmUvaW1wbC9FeHRlbmRlZENsYXNzSW5mbztMABFzdGFja1RyYWNlRWxlbWVudHEAfgAHeHBzcgA0b3JnLmFwYWNoZS5sb2dnaW5nLmxvZzRqLmNvcmUuaW1wbC5FeHRlbmRlZENsYXNzSW5mbwAAAAAAAAABAgADWgAFZXhhY3RMAAhsb2NhdGlvbnEAfgAETAAHdmVyc2lvbnEAfgAEeHABdAANdGVzdC1jbGFzc2VzL3QAAT9zcgAbamF2YS5sYW5nLlN0YWNrVHJhY2VFbGVtZW50YQnFmiY23YUCAARJAApsaW5lTnVtYmVyTAAOZGVjbGFyaW5nQ2xhc3NxAH4ABEwACGZpbGVOYW1lcQB+AARMAAptZXRob2ROYW1lcQB+AAR4cAAAAJh0ADRvcmcuYXBhY2hlLmxvZ2dpbmcubG9nNGouY29yZS5pbXBsLkxvZzRqTG9nRXZlbnRUZXN0dAAWTG9nNGpMb2dFdmVudFRlc3QuamF2YXQAKnRlc3RKYXZhSW9TZXJpYWxpemFibGVXaXRoVW5rbm93blRocm93YWJsZXNxAH4AInNxAH4AJQBxAH4AKHQACDEuNy4wXzU1c3EAfgAp/////nQAJHN1bi5yZWZsZWN0Lk5hdGl2ZU1ldGhvZEFjY2Vzc29ySW1wbHB0AAdpbnZva2Uwc3EAfgAic3EAfgAlAHEAfgAocQB+ADBzcQB+ACn/////cQB+ADJwdAAGaW52b2tlc3EAfgAic3EAfgAlAHEAfgAocQB+ADBzcQB+ACn/////dAAoc3VuLnJlZmxlY3QuRGVsZWdhdGluZ01ldGhvZEFjY2Vzc29ySW1wbHBxAH4AN3NxAH4AInNxAH4AJQBxAH4AKHEAfgAwc3EAfgAp/////3QAGGphdmEubGFuZy5yZWZsZWN0Lk1ldGhvZHBxAH4AN3NxAH4AInNxAH4AJQF0AA5qdW5pdC00LjExLmphcnEAfgAoc3EAfgApAAAAL3QAKW9yZy5qdW5pdC5ydW5uZXJzLm1vZGVsLkZyYW1ld29ya01ldGhvZCQxdAAURnJhbWV3b3JrTWV0aG9kLmphdmF0ABFydW5SZWZsZWN0aXZlQ2FsbHNxAH4AInNxAH4AJQF0AA5qdW5pdC00LjExLmphcnEAfgAoc3EAfgApAAAADHQAM29yZy5qdW5pdC5pbnRlcm5hbC5ydW5uZXJzLm1vZGVsLlJlZmxlY3RpdmVDYWxsYWJsZXQAF1JlZmxlY3RpdmVDYWxsYWJsZS5qYXZhdAADcnVuc3EAfgAic3EAfgAlAXQADmp1bml0LTQuMTEuamFycQB+AChzcQB+ACkAAAAsdAAnb3JnLmp1bml0LnJ1bm5lcnMubW9kZWwuRnJhbWV3b3JrTWV0aG9kcQB+AEV0ABFpbnZva2VFeHBsb3NpdmVseXNxAH4AInNxAH4AJQF0AA5qdW5pdC00LjExLmphcnEAfgAoc3EAfgApAAAAEXQAMm9yZy5qdW5pdC5pbnRlcm5hbC5ydW5uZXJzLnN0YXRlbWVudHMuSW52b2tlTWV0aG9kdAARSW52b2tlTWV0aG9kLmphdmF0AAhldmFsdWF0ZXNxAH4AInNxAH4AJQF0AA5qdW5pdC00LjExLmphcnEAfgAoc3EAfgApAAABD3QAHm9yZy5qdW5pdC5ydW5uZXJzLlBhcmVudFJ1bm5lcnQAEVBhcmVudFJ1bm5lci5qYXZhdAAHcnVuTGVhZnNxAH4AInNxAH4AJQF0AA5qdW5pdC00LjExLmphcnEAfgAoc3EAfgApAAAARnQAKG9yZy5qdW5pdC5ydW5uZXJzLkJsb2NrSlVuaXQ0Q2xhc3NSdW5uZXJ0ABtCbG9ja0pVbml0NENsYXNzUnVubmVyLmphdmF0AAhydW5DaGlsZHNxAH4AInNxAH4AJQF0AA5qdW5pdC00LjExLmphcnEAfgAoc3EAfgApAAAAMnEAfgBmcQB+AGdxAH4AaHNxAH4AInNxAH4AJQF0AA5qdW5pdC00LjExLmphcnEAfgAoc3EAfgApAAAA7nQAIG9yZy5qdW5pdC5ydW5uZXJzLlBhcmVudFJ1bm5lciQzcQB+AGBxAH4ATXNxAH4AInNxAH4AJQF0AA5qdW5pdC00LjExLmphcnEAfgAoc3EAfgApAAAAP3QAIG9yZy5qdW5pdC5ydW5uZXJzLlBhcmVudFJ1bm5lciQxcQB+AGB0AAhzY2hlZHVsZXNxAH4AInNxAH4AJQF0AA5qdW5pdC00LjExLmphcnEAfgAoc3EAfgApAAAA7HEAfgBfcQB+AGB0AAtydW5DaGlsZHJlbnNxAH4AInNxAH4AJQF0AA5qdW5pdC00LjExLmphcnEAfgAoc3EAfgApAAAANXEAfgBfcQB+AGB0AAphY2Nlc3MkMDAwc3EAfgAic3EAfgAlAXQADmp1bml0LTQuMTEuamFycQB+AChzcQB+ACkAAADldAAgb3JnLmp1bml0LnJ1bm5lcnMuUGFyZW50UnVubmVyJDJxAH4AYHEAfgBac3EAfgAic3EAfgAlAXQADmp1bml0LTQuMTEuamFycQB+AChzcQB+ACkAAAAadAAwb3JnLmp1bml0LmludGVybmFsLnJ1bm5lcnMuc3RhdGVtZW50cy5SdW5CZWZvcmVzdAAPUnVuQmVmb3Jlcy5qYXZhcQB+AFpzcQB+ACJzcQB+ACUBdAAOanVuaXQtNC4xMS5qYXJxAH4AKHNxAH4AKQAAABt0AC9vcmcuanVuaXQuaW50ZXJuYWwucnVubmVycy5zdGF0ZW1lbnRzLlJ1bkFmdGVyc3QADlJ1bkFmdGVycy5qYXZhcQB+AFpzcQB+ACJzcQB+ACUBdAAOanVuaXQtNC4xMS5qYXJxAH4AKHNxAH4AKQAAATVxAH4AX3EAfgBgcQB+AE1zcQB+ACJzcQB+ACUBdAAELmNwL3EAfgAoc3EAfgApAAAAMnQAOm9yZy5lY2xpcHNlLmpkdC5pbnRlcm5hbC5qdW5pdDQucnVubmVyLkpVbml0NFRlc3RSZWZlcmVuY2V0ABhKVW5pdDRUZXN0UmVmZXJlbmNlLmphdmFxAH4ATXNxAH4AInNxAH4AJQF0AAQuY3AvcQB+AChzcQB+ACkAAAAmdAAzb3JnLmVjbGlwc2UuamR0LmludGVybmFsLmp1bml0LnJ1bm5lci5UZXN0RXhlY3V0aW9udAASVGVzdEV4ZWN1dGlvbi5qYXZhcQB+AE1zcQB+ACJzcQB+ACUBdAAELmNwL3EAfgAoc3EAfgApAAAB03QANm9yZy5lY2xpcHNlLmpkdC5pbnRlcm5hbC5qdW5pdC5ydW5uZXIuUmVtb3RlVGVzdFJ1bm5lcnQAFVJlbW90ZVRlc3RSdW5uZXIuamF2YXQACHJ1blRlc3Rzc3EAfgAic3EAfgAlAXQABC5jcC9xAH4AKHNxAH4AKQAAAqtxAH4Ap3EAfgCocQB+AKlzcQB+ACJzcQB+ACUBdAAELmNwL3EAfgAoc3EAfgApAAABhnEAfgCncQB+AKhxAH4ATXNxAH4AInNxAH4AJQF0AAQuY3AvcQB+AChzcQB+ACkAAADFcQB+AKdxAH4AqHQABG1haW50ABZPTUcgSSd2ZSBiZWVuIGRlbGV0ZWQhcQB+ALd0AEVvcmcuYXBhY2hlLmxvZ2dpbmcubG9nNGouY29yZS5pbXBsLkxvZzRqTG9nRXZlbnRUZXN0JERlbGV0ZWRFeGNlcHRpb251cgA0W0xvcmcuYXBhY2hlLmxvZ2dpbmcubG9nNGouY29yZS5pbXBsLlRocm93YWJsZVByb3h5O/rtAeCFous5AgAAeHAAAAAA";
178 final String base64_v_2_6 = "rO0ABXNyAD5vcmcuYXBhY2hlLmxvZ2dpbmcubG9nNGouY29yZS5pbXBsLkxvZzRqTG9nRXZlbnQkTG9nRXZlbnRQcm94eYgtmn+yXsP9AgAPWgAMaXNFbmRPZkJhdGNoWgASaXNMb2NhdGlvblJlcXVpcmVkSgAIdGhyZWFkSWRJAA50aHJlYWRQcmlvcml0eUoACnRpbWVNaWxsaXNMAApjb250ZXh0TWFwdAAPTGphdmEvdXRpbC9NYXA7TAAMY29udGV4dFN0YWNrdAA1TG9yZy9hcGFjaGUvbG9nZ2luZy9sb2c0ai9UaHJlYWRDb250ZXh0JENvbnRleHRTdGFjaztMAAVsZXZlbHQAIExvcmcvYXBhY2hlL2xvZ2dpbmcvbG9nNGovTGV2ZWw7TAAKbG9nZ2VyRlFDTnQAEkxqYXZhL2xhbmcvU3RyaW5nO0wACmxvZ2dlck5hbWVxAH4ABEwABm1hcmtlcnQAIUxvcmcvYXBhY2hlL2xvZ2dpbmcvbG9nNGovTWFya2VyO0wAB21lc3NhZ2V0ACpMb3JnL2FwYWNoZS9sb2dnaW5nL2xvZzRqL21lc3NhZ2UvTWVzc2FnZTtMAAZzb3VyY2V0AB1MamF2YS9sYW5nL1N0YWNrVHJhY2VFbGVtZW50O0wACnRocmVhZE5hbWVxAH4ABEwAC3Rocm93blByb3h5dAAzTG9yZy9hcGFjaGUvbG9nZ2luZy9sb2c0ai9jb3JlL2ltcGwvVGhyb3dhYmxlUHJveHk7eHAAAAAAAAAAAAABAAAABQAAAABJlgLSc3IAHmphdmEudXRpbC5Db2xsZWN0aW9ucyRFbXB0eU1hcFk2FIVa3OfQAgAAeHBzcgA+b3JnLmFwYWNoZS5sb2dnaW5nLmxvZzRqLlRocmVhZENvbnRleHQkRW1wdHlUaHJlYWRDb250ZXh0U3RhY2sAAAAAAAAAAQIAAHhwc3IAHm9yZy5hcGFjaGUubG9nZ2luZy5sb2c0ai5MZXZlbAAAAAAAGCAaAgADSQAIaW50TGV2ZWxMAARuYW1lcQB+AARMAA1zdGFuZGFyZExldmVsdAAsTG9yZy9hcGFjaGUvbG9nZ2luZy9sb2c0ai9zcGkvU3RhbmRhcmRMZXZlbDt4cAAAAZB0AARJTkZPfnIAKm9yZy5hcGFjaGUubG9nZ2luZy5sb2c0ai5zcGkuU3RhbmRhcmRMZXZlbAAAAAAAAAAAEgAAeHIADmphdmEubGFuZy5FbnVtAAAAAAAAAAASAAB4cHQABElORk90AAB0AAlzb21lLnRlc3Rwc3IALm9yZy5hcGFjaGUubG9nZ2luZy5sb2c0ai5tZXNzYWdlLlNpbXBsZU1lc3NhZ2WLdE0wYLeiqAMAAUwAB21lc3NhZ2VxAH4ABHhwdAADYWJjcQB+ABp4cHQABG1haW5zcgAxb3JnLmFwYWNoZS5sb2dnaW5nLmxvZzRqLmNvcmUuaW1wbC5UaHJvd2FibGVQcm94ednMMNWae6z6AgAHSQASY29tbW9uRWxlbWVudENvdW50TAAKY2F1c2VQcm94eXEAfgAIWwASZXh0ZW5kZWRTdGFja1RyYWNldAA/W0xvcmcvYXBhY2hlL2xvZ2dpbmcvbG9nNGovY29yZS9pbXBsL0V4dGVuZGVkU3RhY2tUcmFjZUVsZW1lbnQ7TAAQbG9jYWxpemVkTWVzc2FnZXEAfgAETAAHbWVzc2FnZXEAfgAETAAEbmFtZXEAfgAEWwARc3VwcHJlc3NlZFByb3hpZXN0ADRbTG9yZy9hcGFjaGUvbG9nZ2luZy9sb2c0ai9jb3JlL2ltcGwvVGhyb3dhYmxlUHJveHk7eHAAAAAAcHVyAD9bTG9yZy5hcGFjaGUubG9nZ2luZy5sb2c0ai5jb3JlLmltcGwuRXh0ZW5kZWRTdGFja1RyYWNlRWxlbWVudDvKz4gjpcfPvAIAAHhwAAAAHXNyADxvcmcuYXBhY2hlLmxvZ2dpbmcubG9nNGouY29yZS5pbXBsLkV4dGVuZGVkU3RhY2tUcmFjZUVsZW1lbnTh3s+6xraQBwIAAkwADmV4dHJhQ2xhc3NJbmZvdAA2TG9yZy9hcGFjaGUvbG9nZ2luZy9sb2c0ai9jb3JlL2ltcGwvRXh0ZW5kZWRDbGFzc0luZm87TAARc3RhY2tUcmFjZUVsZW1lbnRxAH4AB3hwc3IANG9yZy5hcGFjaGUubG9nZ2luZy5sb2c0ai5jb3JlLmltcGwuRXh0ZW5kZWRDbGFzc0luZm8AAAAAAAAAAQIAA1oABWV4YWN0TAAIbG9jYXRpb25xAH4ABEwAB3ZlcnNpb25xAH4ABHhwAXQADXRlc3QtY2xhc3Nlcy90AAE/c3IAG2phdmEubGFuZy5TdGFja1RyYWNlRWxlbWVudGEJxZomNt2FAgAESQAKbGluZU51bWJlckwADmRlY2xhcmluZ0NsYXNzcQB+AARMAAhmaWxlTmFtZXEAfgAETAAKbWV0aG9kTmFtZXEAfgAEeHAAAACqdAA0b3JnLmFwYWNoZS5sb2dnaW5nLmxvZzRqLmNvcmUuaW1wbC5Mb2c0akxvZ0V2ZW50VGVzdHQAFkxvZzRqTG9nRXZlbnRUZXN0LmphdmF0ACp0ZXN0SmF2YUlvU2VyaWFsaXphYmxlV2l0aFVua25vd25UaHJvd2FibGVzcQB+ACJzcQB+ACUAcQB+ACh0AAgxLjcuMF81NXNxAH4AKf////50ACRzdW4ucmVmbGVjdC5OYXRpdmVNZXRob2RBY2Nlc3NvckltcGx0AB1OYXRpdmVNZXRob2RBY2Nlc3NvckltcGwuamF2YXQAB2ludm9rZTBzcQB+ACJzcQB+ACUAcQB+AChxAH4AMHNxAH4AKQAAADlxAH4AMnEAfgAzdAAGaW52b2tlc3EAfgAic3EAfgAlAHEAfgAocQB+ADBzcQB+ACkAAAArdAAoc3VuLnJlZmxlY3QuRGVsZWdhdGluZ01ldGhvZEFjY2Vzc29ySW1wbHQAIURlbGVnYXRpbmdNZXRob2RBY2Nlc3NvckltcGwuamF2YXEAfgA4c3EAfgAic3EAfgAlAHEAfgAocQB+ADBzcQB+ACkAAAJedAAYamF2YS5sYW5nLnJlZmxlY3QuTWV0aG9kdAALTWV0aG9kLmphdmFxAH4AOHNxAH4AInNxAH4AJQF0AA5qdW5pdC00LjEyLmphcnQABDQuMTJzcQB+ACkAAAAydAApb3JnLmp1bml0LnJ1bm5lcnMubW9kZWwuRnJhbWV3b3JrTWV0aG9kJDF0ABRGcmFtZXdvcmtNZXRob2QuamF2YXQAEXJ1blJlZmxlY3RpdmVDYWxsc3EAfgAic3EAfgAlAXQADmp1bml0LTQuMTIuamFycQB+AEZzcQB+ACkAAAAMdAAzb3JnLmp1bml0LmludGVybmFsLnJ1bm5lcnMubW9kZWwuUmVmbGVjdGl2ZUNhbGxhYmxldAAXUmVmbGVjdGl2ZUNhbGxhYmxlLmphdmF0AANydW5zcQB+ACJzcQB+ACUBdAAOanVuaXQtNC4xMi5qYXJxAH4ARnNxAH4AKQAAAC90ACdvcmcuanVuaXQucnVubmVycy5tb2RlbC5GcmFtZXdvcmtNZXRob2RxAH4ASXQAEWludm9rZUV4cGxvc2l2ZWx5c3EAfgAic3EAfgAlAXQADmp1bml0LTQuMTIuamFycQB+AEZzcQB+ACkAAAARdAAyb3JnLmp1bml0LmludGVybmFsLnJ1bm5lcnMuc3RhdGVtZW50cy5JbnZva2VNZXRob2R0ABFJbnZva2VNZXRob2QuamF2YXQACGV2YWx1YXRlc3EAfgAic3EAfgAlAXQADmp1bml0LTQuMTIuamFycQB+AEZzcQB+ACkAAAFFdAAeb3JnLmp1bml0LnJ1bm5lcnMuUGFyZW50UnVubmVydAARUGFyZW50UnVubmVyLmphdmF0AAdydW5MZWFmc3EAfgAic3EAfgAlAXQADmp1bml0LTQuMTIuamFycQB+AEZzcQB+ACkAAABOdAAob3JnLmp1bml0LnJ1bm5lcnMuQmxvY2tKVW5pdDRDbGFzc1J1bm5lcnQAG0Jsb2NrSlVuaXQ0Q2xhc3NSdW5uZXIuamF2YXQACHJ1bkNoaWxkc3EAfgAic3EAfgAlAXQADmp1bml0LTQuMTIuamFycQB+AEZzcQB+ACkAAAA5cQB+AGpxAH4Aa3EAfgBsc3EAfgAic3EAfgAlAXQADmp1bml0LTQuMTIuamFycQB+AEZzcQB+ACkAAAEidAAgb3JnLmp1bml0LnJ1bm5lcnMuUGFyZW50UnVubmVyJDNxAH4AZHEAfgBRc3EAfgAic3EAfgAlAXQADmp1bml0LTQuMTIuamFycQB+AEZzcQB+ACkAAABHdAAgb3JnLmp1bml0LnJ1bm5lcnMuUGFyZW50UnVubmVyJDFxAH4AZHQACHNjaGVkdWxlc3EAfgAic3EAfgAlAXQADmp1bml0LTQuMTIuamFycQB+AEZzcQB+ACkAAAEgcQB+AGNxAH4AZHQAC3J1bkNoaWxkcmVuc3EAfgAic3EAfgAlAXQADmp1bml0LTQuMTIuamFycQB+AEZzcQB+ACkAAAA6cQB+AGNxAH4AZHQACmFjY2VzcyQwMDBzcQB+ACJzcQB+ACUBdAAOanVuaXQtNC4xMi5qYXJxAH4ARnNxAH4AKQAAAQx0ACBvcmcuanVuaXQucnVubmVycy5QYXJlbnRSdW5uZXIkMnEAfgBkcQB+AF5zcQB+ACJzcQB+ACUBdAAOanVuaXQtNC4xMi5qYXJxAH4ARnNxAH4AKQAAABp0ADBvcmcuanVuaXQuaW50ZXJuYWwucnVubmVycy5zdGF0ZW1lbnRzLlJ1bkJlZm9yZXN0AA9SdW5CZWZvcmVzLmphdmFxAH4AXnNxAH4AInNxAH4AJQF0AA5qdW5pdC00LjEyLmphcnEAfgBGc3EAfgApAAAAG3QAL29yZy5qdW5pdC5pbnRlcm5hbC5ydW5uZXJzLnN0YXRlbWVudHMuUnVuQWZ0ZXJzdAAOUnVuQWZ0ZXJzLmphdmFxAH4AXnNxAH4AInNxAH4AJQF0AA5qdW5pdC00LjEyLmphcnEAfgBGc3EAfgApAAABa3EAfgBjcQB+AGRxAH4AUXNxAH4AInNxAH4AJQF0AA5qdW5pdC00LjEyLmphcnEAfgBGc3EAfgApAAAAiXQAGm9yZy5qdW5pdC5ydW5uZXIuSlVuaXRDb3JldAAOSlVuaXRDb3JlLmphdmFxAH4AUXNxAH4AInNxAH4AJQF0AAxqdW5pdC1ydC5qYXJxAH4AKHNxAH4AKQAAAEV0AChjb20uaW50ZWxsaWouanVuaXQ0LkpVbml0NElkZWFUZXN0UnVubmVydAAZSlVuaXQ0SWRlYVRlc3RSdW5uZXIuamF2YXQAE3N0YXJ0UnVubmVyV2l0aEFyZ3NzcQB+ACJzcQB+ACUBdAAManVuaXQtcnQuamFycQB+AChzcQB+ACkAAADqdAAsY29tLmludGVsbGlqLnJ0LmV4ZWN1dGlvbi5qdW5pdC5KVW5pdFN0YXJ0ZXJ0ABFKVW5pdFN0YXJ0ZXIuamF2YXQAFnByZXBhcmVTdHJlYW1zQW5kU3RhcnRzcQB+ACJzcQB+ACUBdAAManVuaXQtcnQuamFycQB+AChzcQB+ACkAAABKcQB+AKxxAH4ArXQABG1haW5zcQB+ACJzcQB+ACUAcQB+AChxAH4AMHNxAH4AKf////5xAH4AMnEAfgAzcQB+ADRzcQB+ACJzcQB+ACUAcQB+AChxAH4AMHNxAH4AKQAAADlxAH4AMnEAfgAzcQB+ADhzcQB+ACJzcQB+ACUAcQB+AChxAH4AMHNxAH4AKQAAACtxAH4APHEAfgA9cQB+ADhzcQB+ACJzcQB+ACUAcQB+AChxAH4AMHNxAH4AKQAAAl5xAH4AQXEAfgBCcQB+ADhzcQB+ACJzcQB+ACUBdAALaWRlYV9ydC5qYXJxAH4AKHNxAH4AKQAAAJB0AC1jb20uaW50ZWxsaWoucnQuZXhlY3V0aW9uLmFwcGxpY2F0aW9uLkFwcE1haW50AAxBcHBNYWluLmphdmFxAH4As3QAFk9NRyBJJ3ZlIGJlZW4gZGVsZXRlZCFxAH4AxnQARW9yZy5hcGFjaGUubG9nZ2luZy5sb2c0ai5jb3JlLmltcGwuTG9nNGpMb2dFdmVudFRlc3QkRGVsZXRlZEV4Y2VwdGlvbnVyADRbTG9yZy5hcGFjaGUubG9nZ2luZy5sb2c0ai5jb3JlLmltcGwuVGhyb3dhYmxlUHJveHk7+u0B4IWi6zkCAAB4cAAAAAA=";
179178 final String base64 = "rO0ABXNyAD5vcmcuYXBhY2hlLmxvZ2dpbmcubG9nNGouY29yZS5pbXBsLkxvZzRqTG9nRXZlbnQkTG9nRXZlbnRQcm94eYgtmn+yXsP9AgAPWgAMaXNFbmRPZkJhdGNoWgASaXNMb2NhdGlvblJlcXVpcmVkSgAIdGhyZWFkSWRJAA50aHJlYWRQcmlvcml0eUoACnRpbWVNaWxsaXNMAApjb250ZXh0TWFwdAAPTGphdmEvdXRpbC9NYXA7TAAMY29udGV4dFN0YWNrdAA1TG9yZy9hcGFjaGUvbG9nZ2luZy9sb2c0ai9UaHJlYWRDb250ZXh0JENvbnRleHRTdGFjaztMAAVsZXZlbHQAIExvcmcvYXBhY2hlL2xvZ2dpbmcvbG9nNGovTGV2ZWw7TAAKbG9nZ2VyRlFDTnQAEkxqYXZhL2xhbmcvU3RyaW5nO0wACmxvZ2dlck5hbWVxAH4ABEwABm1hcmtlcnQAIUxvcmcvYXBhY2hlL2xvZ2dpbmcvbG9nNGovTWFya2VyO0wAB21lc3NhZ2V0ACpMb3JnL2FwYWNoZS9sb2dnaW5nL2xvZzRqL21lc3NhZ2UvTWVzc2FnZTtMAAZzb3VyY2V0AB1MamF2YS9sYW5nL1N0YWNrVHJhY2VFbGVtZW50O0wACnRocmVhZE5hbWVxAH4ABEwAC3Rocm93blByb3h5dAAzTG9yZy9hcGFjaGUvbG9nZ2luZy9sb2c0ai9jb3JlL2ltcGwvVGhyb3dhYmxlUHJveHk7eHAAAAAAAAAAAAABAAAABQAAAABJlgLSc3IAHmphdmEudXRpbC5Db2xsZWN0aW9ucyRFbXB0eU1hcFk2FIVa3OfQAgAAeHBzcgA+b3JnLmFwYWNoZS5sb2dnaW5nLmxvZzRqLlRocmVhZENvbnRleHQkRW1wdHlUaHJlYWRDb250ZXh0U3RhY2sAAAAAAAAAAQIAAHhwc3IAHm9yZy5hcGFjaGUubG9nZ2luZy5sb2c0ai5MZXZlbAAAAAAAGCAaAgADSQAIaW50TGV2ZWxMAARuYW1lcQB+AARMAA1zdGFuZGFyZExldmVsdAAsTG9yZy9hcGFjaGUvbG9nZ2luZy9sb2c0ai9zcGkvU3RhbmRhcmRMZXZlbDt4cAAAAZB0AARJTkZPfnIAKm9yZy5hcGFjaGUubG9nZ2luZy5sb2c0ai5zcGkuU3RhbmRhcmRMZXZlbAAAAAAAAAAAEgAAeHIADmphdmEubGFuZy5FbnVtAAAAAAAAAAASAAB4cHQABElORk90AAB0AAlzb21lLnRlc3Rwc3IALm9yZy5hcGFjaGUubG9nZ2luZy5sb2c0ai5tZXNzYWdlLlNpbXBsZU1lc3NhZ2WLdE0wYLeiqAMAAUwAB21lc3NhZ2VxAH4ABHhwdAADYWJjcQB+ABp4cHQABG1haW5zcgAxb3JnLmFwYWNoZS5sb2dnaW5nLmxvZzRqLmNvcmUuaW1wbC5UaHJvd2FibGVQcm94ednMMNWae6z6AgAHSQASY29tbW9uRWxlbWVudENvdW50TAAKY2F1c2VQcm94eXEAfgAIWwASZXh0ZW5kZWRTdGFja1RyYWNldAA/W0xvcmcvYXBhY2hlL2xvZ2dpbmcvbG9nNGovY29yZS9pbXBsL0V4dGVuZGVkU3RhY2tUcmFjZUVsZW1lbnQ7TAAQbG9jYWxpemVkTWVzc2FnZXEAfgAETAAHbWVzc2FnZXEAfgAETAAEbmFtZXEAfgAEWwARc3VwcHJlc3NlZFByb3hpZXN0ADRbTG9yZy9hcGFjaGUvbG9nZ2luZy9sb2c0ai9jb3JlL2ltcGwvVGhyb3dhYmxlUHJveHk7eHAAAAAAcHVyAD9bTG9yZy5hcGFjaGUubG9nZ2luZy5sb2c0ai5jb3JlLmltcGwuRXh0ZW5kZWRTdGFja1RyYWNlRWxlbWVudDvKz4gjpcfPvAIAAHhwAAAAHXNyADxvcmcuYXBhY2hlLmxvZ2dpbmcubG9nNGouY29yZS5pbXBsLkV4dGVuZGVkU3RhY2tUcmFjZUVsZW1lbnTh3s+6xraQBwIAAkwADmV4dHJhQ2xhc3NJbmZvdAA2TG9yZy9hcGFjaGUvbG9nZ2luZy9sb2c0ai9jb3JlL2ltcGwvRXh0ZW5kZWRDbGFzc0luZm87TAARc3RhY2tUcmFjZUVsZW1lbnRxAH4AB3hwc3IANG9yZy5hcGFjaGUubG9nZ2luZy5sb2c0ai5jb3JlLmltcGwuRXh0ZW5kZWRDbGFzc0luZm8AAAAAAAAAAQIAA1oABWV4YWN0TAAIbG9jYXRpb25xAH4ABEwAB3ZlcnNpb25xAH4ABHhwAXQADXRlc3QtY2xhc3Nlcy90AAE/c3IAG2phdmEubGFuZy5TdGFja1RyYWNlRWxlbWVudGEJxZomNt2FAgAESQAKbGluZU51bWJlckwADmRlY2xhcmluZ0NsYXNzcQB+AARMAAhmaWxlTmFtZXEAfgAETAAKbWV0aG9kTmFtZXEAfgAEeHAAAACqdAA0b3JnLmFwYWNoZS5sb2dnaW5nLmxvZzRqLmNvcmUuaW1wbC5Mb2c0akxvZ0V2ZW50VGVzdHQAFkxvZzRqTG9nRXZlbnRUZXN0LmphdmF0ACp0ZXN0SmF2YUlvU2VyaWFsaXphYmxlV2l0aFVua25vd25UaHJvd2FibGVzcQB+ACJzcQB+ACUAcQB+ACh0AAgxLjcuMF81NXNxAH4AKf////50ACRzdW4ucmVmbGVjdC5OYXRpdmVNZXRob2RBY2Nlc3NvckltcGx0AB1OYXRpdmVNZXRob2RBY2Nlc3NvckltcGwuamF2YXQAB2ludm9rZTBzcQB+ACJzcQB+ACUAcQB+AChxAH4AMHNxAH4AKQAAADlxAH4AMnEAfgAzdAAGaW52b2tlc3EAfgAic3EAfgAlAHEAfgAocQB+ADBzcQB+ACkAAAArdAAoc3VuLnJlZmxlY3QuRGVsZWdhdGluZ01ldGhvZEFjY2Vzc29ySW1wbHQAIURlbGVnYXRpbmdNZXRob2RBY2Nlc3NvckltcGwuamF2YXEAfgA4c3EAfgAic3EAfgAlAHEAfgAocQB+ADBzcQB+ACkAAAJedAAYamF2YS5sYW5nLnJlZmxlY3QuTWV0aG9kdAALTWV0aG9kLmphdmFxAH4AOHNxAH4AInNxAH4AJQF0AA5qdW5pdC00LjEyLmphcnQABDQuMTJzcQB+ACkAAAAydAApb3JnLmp1bml0LnJ1bm5lcnMubW9kZWwuRnJhbWV3b3JrTWV0aG9kJDF0ABRGcmFtZXdvcmtNZXRob2QuamF2YXQAEXJ1blJlZmxlY3RpdmVDYWxsc3EAfgAic3EAfgAlAXQADmp1bml0LTQuMTIuamFycQB+AEZzcQB+ACkAAAAMdAAzb3JnLmp1bml0LmludGVybmFsLnJ1bm5lcnMubW9kZWwuUmVmbGVjdGl2ZUNhbGxhYmxldAAXUmVmbGVjdGl2ZUNhbGxhYmxlLmphdmF0AANydW5zcQB+ACJzcQB+ACUBdAAOanVuaXQtNC4xMi5qYXJxAH4ARnNxAH4AKQAAAC90ACdvcmcuanVuaXQucnVubmVycy5tb2RlbC5GcmFtZXdvcmtNZXRob2RxAH4ASXQAEWludm9rZUV4cGxvc2l2ZWx5c3EAfgAic3EAfgAlAXQADmp1bml0LTQuMTIuamFycQB+AEZzcQB+ACkAAAARdAAyb3JnLmp1bml0LmludGVybmFsLnJ1bm5lcnMuc3RhdGVtZW50cy5JbnZva2VNZXRob2R0ABFJbnZva2VNZXRob2QuamF2YXQACGV2YWx1YXRlc3EAfgAic3EAfgAlAXQADmp1bml0LTQuMTIuamFycQB+AEZzcQB+ACkAAAFFdAAeb3JnLmp1bml0LnJ1bm5lcnMuUGFyZW50UnVubmVydAARUGFyZW50UnVubmVyLmphdmF0AAdydW5MZWFmc3EAfgAic3EAfgAlAXQADmp1bml0LTQuMTIuamFycQB+AEZzcQB+ACkAAABOdAAob3JnLmp1bml0LnJ1bm5lcnMuQmxvY2tKVW5pdDRDbGFzc1J1bm5lcnQAG0Jsb2NrSlVuaXQ0Q2xhc3NSdW5uZXIuamF2YXQACHJ1bkNoaWxkc3EAfgAic3EAfgAlAXQADmp1bml0LTQuMTIuamFycQB+AEZzcQB+ACkAAAA5cQB+AGpxAH4Aa3EAfgBsc3EAfgAic3EAfgAlAXQADmp1bml0LTQuMTIuamFycQB+AEZzcQB+ACkAAAEidAAgb3JnLmp1bml0LnJ1bm5lcnMuUGFyZW50UnVubmVyJDNxAH4AZHEAfgBRc3EAfgAic3EAfgAlAXQADmp1bml0LTQuMTIuamFycQB+AEZzcQB+ACkAAABHdAAgb3JnLmp1bml0LnJ1bm5lcnMuUGFyZW50UnVubmVyJDFxAH4AZHQACHNjaGVkdWxlc3EAfgAic3EAfgAlAXQADmp1bml0LTQuMTIuamFycQB+AEZzcQB+ACkAAAEgcQB+AGNxAH4AZHQAC3J1bkNoaWxkcmVuc3EAfgAic3EAfgAlAXQADmp1bml0LTQuMTIuamFycQB+AEZzcQB+ACkAAAA6cQB+AGNxAH4AZHQACmFjY2VzcyQwMDBzcQB+ACJzcQB+ACUBdAAOanVuaXQtNC4xMi5qYXJxAH4ARnNxAH4AKQAAAQx0ACBvcmcuanVuaXQucnVubmVycy5QYXJlbnRSdW5uZXIkMnEAfgBkcQB+AF5zcQB+ACJzcQB+ACUBdAAOanVuaXQtNC4xMi5qYXJxAH4ARnNxAH4AKQAAABp0ADBvcmcuanVuaXQuaW50ZXJuYWwucnVubmVycy5zdGF0ZW1lbnRzLlJ1bkJlZm9yZXN0AA9SdW5CZWZvcmVzLmphdmFxAH4AXnNxAH4AInNxAH4AJQF0AA5qdW5pdC00LjEyLmphcnEAfgBGc3EAfgApAAAAG3QAL29yZy5qdW5pdC5pbnRlcm5hbC5ydW5uZXJzLnN0YXRlbWVudHMuUnVuQWZ0ZXJzdAAOUnVuQWZ0ZXJzLmphdmFxAH4AXnNxAH4AInNxAH4AJQF0AA5qdW5pdC00LjEyLmphcnEAfgBGc3EAfgApAAABa3EAfgBjcQB+AGRxAH4AUXNxAH4AInNxAH4AJQF0AA5qdW5pdC00LjEyLmphcnEAfgBGc3EAfgApAAAAiXQAGm9yZy5qdW5pdC5ydW5uZXIuSlVuaXRDb3JldAAOSlVuaXRDb3JlLmphdmFxAH4AUXNxAH4AInNxAH4AJQF0AAxqdW5pdC1ydC5qYXJxAH4AKHNxAH4AKQAAAEV0AChjb20uaW50ZWxsaWouanVuaXQ0LkpVbml0NElkZWFUZXN0UnVubmVydAAZSlVuaXQ0SWRlYVRlc3RSdW5uZXIuamF2YXQAE3N0YXJ0UnVubmVyV2l0aEFyZ3NzcQB+ACJzcQB+ACUBdAAManVuaXQtcnQuamFycQB+AChzcQB+ACkAAADqdAAsY29tLmludGVsbGlqLnJ0LmV4ZWN1dGlvbi5qdW5pdC5KVW5pdFN0YXJ0ZXJ0ABFKVW5pdFN0YXJ0ZXIuamF2YXQAFnByZXBhcmVTdHJlYW1zQW5kU3RhcnRzcQB+ACJzcQB+ACUBdAAManVuaXQtcnQuamFycQB+AChzcQB+ACkAAABKcQB+AKxxAH4ArXQABG1haW5zcQB+ACJzcQB+ACUAcQB+AChxAH4AMHNxAH4AKf////5xAH4AMnEAfgAzcQB+ADRzcQB+ACJzcQB+ACUAcQB+AChxAH4AMHNxAH4AKQAAADlxAH4AMnEAfgAzcQB+ADhzcQB+ACJzcQB+ACUAcQB+AChxAH4AMHNxAH4AKQAAACtxAH4APHEAfgA9cQB+ADhzcQB+ACJzcQB+ACUAcQB+AChxAH4AMHNxAH4AKQAAAl5xAH4AQXEAfgBCcQB+ADhzcQB+ACJzcQB+ACUBdAALaWRlYV9ydC5qYXJxAH4AKHNxAH4AKQAAAJB0AC1jb20uaW50ZWxsaWoucnQuZXhlY3V0aW9uLmFwcGxpY2F0aW9uLkFwcE1haW50AAxBcHBNYWluLmphdmFxAH4As3QAFk9NRyBJJ3ZlIGJlZW4gZGVsZXRlZCFxAH4AxnQARW9yZy5hcGFjaGUubG9nZ2luZy5sb2c0ai5jb3JlLmltcGwuTG9nNGpMb2dFdmVudFRlc3QkRGVsZXRlZEV4Y2VwdGlvbnVyADRbTG9yZy5hcGFjaGUubG9nZ2luZy5sb2c0ai5jb3JlLmltcGwuVGhyb3dhYmxlUHJveHk7+u0B4IWi6zkCAAB4cAAAAAA=";
180179
181180 final byte[] binaryDecoded = DatatypeConverter.parseBase64Binary(base64);
263262 .setTimeMillis(987654321L)
264263 .build();
265264
266 assertSame(contextMap, event.getContextMap());
265 assertEquals(contextMap, event.getContextMap());
267266 assertSame(contextStack, event.getContextStack());
268267 assertEquals(true, event.isEndOfBatch());
269268 assertEquals(true, event.isIncludeLocation());
284283 }
285284
286285 @Test
287 public void testBuilderCorrectlyCopiesMutableLogEvent() throws Exception {
288 final Map<String, String> contextMap = new HashMap<>();
289 contextMap.put("A", "B");
286 public void testBuilderCorrectlyCopiesAllEventAttributesInclContextData() {
287 final StringMap contextData = new SortedArrayStringMap();
288 contextData.putValue("A", "B");
290289 final ContextStack contextStack = ThreadContext.getImmutableStack();
291290 final Exception exception = new Exception("test");
292291 final Marker marker = MarkerManager.getMarker("EVENTTEST");
295294 final String fqcn = "qualified";
296295 final String name = "Ceci n'est pas une pipe";
297296 final String threadName = "threadName";
297 final Log4jLogEvent event = Log4jLogEvent.newBuilder() //
298 .setContextData(contextData) //
299 .setContextStack(contextStack) //
300 .setEndOfBatch(true) //
301 .setIncludeLocation(true) //
302 .setLevel(Level.FATAL) //
303 .setLoggerFqcn(fqcn) //
304 .setLoggerName(name) //
305 .setMarker(marker) //
306 .setMessage(message) //
307 .setNanoTime(1234567890L) //
308 .setSource(stackTraceElement) //
309 .setThreadName(threadName) //
310 .setThrown(exception) //
311 .setTimeMillis(987654321L)
312 .build();
313
314 assertSame(contextData, event.getContextData());
315 assertSame(contextStack, event.getContextStack());
316 assertEquals(true, event.isEndOfBatch());
317 assertEquals(true, event.isIncludeLocation());
318 assertSame(Level.FATAL, event.getLevel());
319 assertSame(fqcn, event.getLoggerFqcn());
320 assertSame(name, event.getLoggerName());
321 assertSame(marker, event.getMarker());
322 assertSame(message, event.getMessage());
323 assertEquals(1234567890L, event.getNanoTime());
324 assertSame(stackTraceElement, event.getSource());
325 assertSame(threadName, event.getThreadName());
326 assertSame(exception, event.getThrown());
327 assertEquals(987654321L, event.getTimeMillis());
328
329 final LogEvent event2 = new Log4jLogEvent.Builder(event).build();
330 assertEquals("copy constructor builder", event2, event);
331 assertEquals("same hashCode", event2.hashCode(), event.hashCode());
332 }
333
334 @Test
335 public void testBuilderCorrectlyCopiesMutableLogEvent() throws Exception {
336 final StringMap contextData = new SortedArrayStringMap();
337 contextData.putValue("A", "B");
338 final ContextStack contextStack = ThreadContext.getImmutableStack();
339 final Exception exception = new Exception("test");
340 final Marker marker = MarkerManager.getMarker("EVENTTEST");
341 final Message message = new SimpleMessage("foo");
342 new StackTraceElement("A", "B", "file", 123);
343 final String fqcn = "qualified";
344 final String name = "Ceci n'est pas une pipe";
345 final String threadName = "threadName";
298346 final MutableLogEvent event = new MutableLogEvent();
299 event.setContextMap(contextMap);
347 event.setContextData(contextData);
300348 event.setContextStack(contextStack);
301349 event.setEndOfBatch(true);
302350 event.setIncludeLocation(true);
311359 event.setThrown(exception);
312360 event.setTimeMillis(987654321L);
313361
314 assertSame(contextMap, event.getContextMap());
362 assertSame(contextData, event.getContextData());
315363 assertSame(contextStack, event.getContextStack());
316364 assertEquals(true, event.isEndOfBatch());
317365 assertEquals(true, event.isIncludeLocation());
327375 assertEquals(987654321L, event.getTimeMillis());
328376
329377 final LogEvent e2 = new Log4jLogEvent.Builder(event).build();
330 assertSame(contextMap, e2.getContextMap());
378 assertEquals(contextData, e2.getContextData());
331379 assertSame(contextStack, e2.getContextStack());
332380 assertEquals(true, e2.isEndOfBatch());
333381 assertEquals(true, e2.isIncludeLocation());
380428 .setTimeMillis(987654321L)
381429 .build();
382430
383 assertSame(contextMap, event.getContextMap());
431 assertEquals(contextMap, event.getContextMap());
384432 assertSame(contextStack, event.getContextStack());
385433 assertEquals(true, event.isEndOfBatch());
386434 assertEquals(true, event.isIncludeLocation());
399447 assertEquals("copy constructor builder", event2, event);
400448 assertEquals("same hashCode", event2.hashCode(), event.hashCode());
401449
402 assertSame(contextMap, event2.getContextMap());
450 assertEquals(contextMap, event2.getContextMap());
403451 assertSame(contextStack, event2.getContextStack());
404452 assertEquals(true, event2.isEndOfBatch());
405453 assertEquals(true, event2.isIncludeLocation());
472520 assertNotEquals(reason, other, event);
473521 assertNotEquals(reason + " hashCode", other.hashCode(), event.hashCode());
474522 }
523
524 @Test
525 public void testToString() {
526 // Throws an NPE in 2.6.2
527 assertNotNull(new Log4jLogEvent().toString());
528 }
475529 }
2222 import java.io.ObjectInputStream;
2323 import java.io.ObjectOutputStream;
2424 import java.util.Arrays;
25 import java.util.HashMap;
26 import java.util.Map;
2725
2826 import org.apache.logging.log4j.Level;
2927 import org.apache.logging.log4j.MarkerManager;
3028 import org.apache.logging.log4j.ThreadContext;
3129 import org.apache.logging.log4j.message.ParameterizedMessage;
3230 import org.apache.logging.log4j.message.SimpleMessage;
31 import org.apache.logging.log4j.util.SortedArrayStringMap;
32 import org.apache.logging.log4j.util.StringMap;
3333 import org.apache.logging.log4j.spi.MutableThreadContextStack;
3434 import org.junit.Test;
3535
3939 * Tests the MutableLogEvent class.
4040 */
4141 public class MutableLogEventTest {
42 private static final Map<String, String> CONTEXTMAP = createContextMap();
42 private static final StringMap CONTEXT_DATA = createContextData();
4343 private static final ThreadContext.ContextStack STACK = new MutableThreadContextStack(Arrays.asList("abc", "xyz"));
4444
45 private static Map<String,String> createContextMap() {
46 final Map<String,String> result = new HashMap<>();
47 result.put("a", "1");
48 result.put("b", "2");
45 private static StringMap createContextData() {
46 final StringMap result = new SortedArrayStringMap();
47 result.putValue("a", "1");
48 result.putValue("b", "2");
4949 return result;
5050 }
5151
5353 public void testInitFromCopiesAllFields() {
5454 // private ThrowableProxy thrownProxy;
5555 final Log4jLogEvent source = Log4jLogEvent.newBuilder() //
56 .setContextMap(CONTEXTMAP) //
56 .setContextData(CONTEXT_DATA) //
5757 .setContextStack(STACK) //
5858 .setEndOfBatch(true) //
5959 .setIncludeLocation(true) //
7070 .build();
7171 final MutableLogEvent mutable = new MutableLogEvent();
7272 mutable.initFrom(source);
73 assertEquals("contextMap", CONTEXTMAP, mutable.getContextMap());
73 assertEquals("contextMap", CONTEXT_DATA, mutable.getContextData());
7474 assertEquals("stack", STACK, mutable.getContextStack());
7575 assertEquals("endOfBatch", true, mutable.isEndOfBatch());
7676 assertEquals("IncludeLocation()", true, mutable.isIncludeLocation());
9292 @Test
9393 public void testClear() {
9494 final MutableLogEvent mutable = new MutableLogEvent();
95 assertNull("context map", mutable.getContextMap());
95 assertEquals("context data", 0, mutable.getContextData().size());
9696 assertNull("context stack", mutable.getContextStack());
9797 assertFalse("end of batch", mutable.isEndOfBatch());
9898 assertFalse("incl loc", mutable.isIncludeLocation());
111111 assertNull("source", mutable.getSource());
112112 assertNull("thrownProxy", mutable.getThrownProxy());
113113
114 mutable.setContextMap(CONTEXTMAP);
114 mutable.setContextData(CONTEXT_DATA);
115115 mutable.setContextStack(STACK);
116116 mutable.setEndOfBatch(true);
117117 mutable.setIncludeLocation(true);
147147 assertNotNull("thrownProxy", mutable.getThrownProxy());
148148
149149 mutable.clear();
150 assertNull("context map", mutable.getContextMap());
150 assertEquals("context map", 0, mutable.getContextData().size());
151151 assertNull("context stack", mutable.getContextStack());
152152 assertSame("level", Level.OFF, mutable.getLevel());
153153 assertNull("fqcn", mutable.getLoggerFqcn());
174174 @Test
175175 public void testJavaIoSerializable() throws Exception {
176176 final MutableLogEvent evt = new MutableLogEvent();
177 evt.setContextMap(CONTEXTMAP);
177 evt.setContextData(CONTEXT_DATA);
178178 evt.setContextStack(STACK);
179179 evt.setEndOfBatch(true);
180180 evt.setIncludeLocation(true);
198198 assertEquals(evt.getLevel(), evt2.getLevel());
199199 assertEquals(evt.getLoggerName(), evt2.getLoggerName());
200200 assertEquals(evt.getMarker(), evt2.getMarker());
201 assertEquals(evt.getContextData(), evt2.getContextData());
201202 assertEquals(evt.getContextMap(), evt2.getContextMap());
202203 assertEquals(evt.getContextStack(), evt2.getContextStack());
203204 assertEquals(evt.getMessage(), evt2.getMessage());
215216
216217 @Test
217218 public void testJavaIoSerializableWithThrown() throws Exception {
218 final Error thrown = new InternalError("test error");
219 new InternalError("test error");
219220 final MutableLogEvent evt = new MutableLogEvent();
220 evt.setContextMap(CONTEXTMAP);
221 evt.setContextData(CONTEXT_DATA);
221222 evt.setContextStack(STACK);
222223 evt.setEndOfBatch(true);
223224 evt.setIncludeLocation(true);
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.impl;
17
18 import java.util.List;
19
20 import org.apache.logging.log4j.LogManager;
21 import org.apache.logging.log4j.Logger;
22 import org.apache.logging.log4j.junit.LoggerContextRule;
23 import org.apache.logging.log4j.test.appender.ListAppender;
24 import org.junit.Before;
25 import org.junit.Rule;
26 import org.junit.Test;
27
28 import static org.junit.Assert.*;
29
30 /**
31 * There are two logger.info() calls here.
32 *
33 * The outer one (in main()) indirectly invokes the inner one in the Thing.toString() method.
34 *
35 * The inner one comes out cleanly, but leaves ReusableParameterizedMessage.indices altered and this messes up
36 * the output of the outer call (which is still on the stack).
37 *
38 * <pre>
39 * 16:35:34.781 INFO [main] problem.demo.apache.log4j2.Log4j2ProblemDemo - getX: values x=3 y=4 z=5
40 * 16:35:34.782 INFO [main] problem.demo.apache.log4j2.Log4j2ProblemDemo - getX: values x=3 y=4 z=5[Thing x=3 y=4 z=5]
41 * </pre>
42 * @author lwest
43 * @since 2016-09-14 in recursion
44 */
45 public class NestedLoggingFromToStringTest {
46
47 @Rule
48 public LoggerContextRule context = new LoggerContextRule("log4j-sync-to-list.xml");
49 private ListAppender listAppender;
50 private Logger logger;
51
52 @Before
53 public void before() {
54 listAppender = context.getListAppender("List");
55 logger = LogManager.getLogger(NestedLoggingFromToStringTest.class);
56 }
57
58 static class ParameterizedLoggingThing {
59 final Logger innerLogger = LogManager.getLogger(ParameterizedLoggingThing.class);
60 private final int x = 3, y = 4, z = 5;
61 public int getX() {
62 innerLogger.debug("getX: values x={} y={} z={}", x, y, z);
63 return x;
64 }
65 @Override public String toString() {
66 return "[" + this.getClass().getSimpleName() + " x=" + getX() + " y=" + y + " z=" + z + "]";
67 }
68 }
69
70 static class ObjectLoggingThing1 {
71 final Logger innerLogger = LogManager.getLogger(ObjectLoggingThing1.class);
72 public int getX() {
73 innerLogger.trace(new ObjectLoggingThing2());
74 return 999;
75 }
76 @Override public String toString() {
77 return "[" + this.getClass().getSimpleName() + " y=" + getX() + "]";
78 }
79 }
80
81 static class ObjectLoggingThing2 {
82 final Logger innerLogger = LogManager.getLogger(ObjectLoggingThing2.class);
83 public int getX() {
84 innerLogger.trace(new ParameterizedLoggingThing());
85 return 123;
86 }
87 @Override public String toString() {
88 return "[" + this.getClass().getSimpleName() + " x=" + getX() + "]";
89 }
90 }
91
92 @Test
93 public void testNestedLoggingInLastArgument() {
94 final ParameterizedLoggingThing it = new ParameterizedLoggingThing();
95 logger.info("main: argCount={} it={}", "2", it);
96 final List<String> list = listAppender.getMessages();
97
98 final String expect1 = "DEBUG org.apache.logging.log4j.core.impl.NestedLoggingFromToStringTest$ParameterizedLoggingThing getX: values x=3 y=4 z=5";
99 final String expect2 = "INFO org.apache.logging.log4j.core.impl.NestedLoggingFromToStringTest main: argCount=2 it=[ParameterizedLoggingThing x=3 y=4 z=5]";
100 assertEquals(expect1, list.get(0));
101 assertEquals(expect2, list.get(1));
102 }
103
104 @Test
105 public void testNestedLoggingInFirstArgument() {
106 final ParameterizedLoggingThing it = new ParameterizedLoggingThing();
107 logger.info("next: it={} some{} other{}", it, "AA", "BB");
108 final List<String> list = listAppender.getMessages();
109
110 final String expect1 = "DEBUG org.apache.logging.log4j.core.impl.NestedLoggingFromToStringTest$ParameterizedLoggingThing getX: values x=3 y=4 z=5";
111 final String expect2 = "INFO org.apache.logging.log4j.core.impl.NestedLoggingFromToStringTest next: it=[ParameterizedLoggingThing x=3 y=4 z=5] someAA otherBB";
112 assertEquals(expect1, list.get(0));
113 assertEquals(expect2, list.get(1));
114 }
115
116 @Test
117 public void testDoublyNestedLogging() {
118 logger.info(new ObjectLoggingThing1());
119 final List<String> list = listAppender.getMessages();
120
121 final String expect1 = "DEBUG org.apache.logging.log4j.core.impl.NestedLoggingFromToStringTest$ParameterizedLoggingThing getX: values x=3 y=4 z=5";
122 final String expect2 = "TRACE org.apache.logging.log4j.core.impl.NestedLoggingFromToStringTest$ObjectLoggingThing2 [ParameterizedLoggingThing x=3 y=4 z=5]";
123 final String expect3 = "TRACE org.apache.logging.log4j.core.impl.NestedLoggingFromToStringTest$ObjectLoggingThing1 [ObjectLoggingThing2 x=123]";
124 final String expect4 = "INFO org.apache.logging.log4j.core.impl.NestedLoggingFromToStringTest [ObjectLoggingThing1 y=999]";
125 assertEquals(expect1, list.get(0));
126 assertEquals(expect2, list.get(1));
127 assertEquals(expect3, list.get(2));
128 assertEquals(expect4, list.get(3));
129 }
130
131 }
2929 public class ReusableLogEventFactoryTest {
3030
3131 @Test
32 public void testCreateEventReturnsDifferentInstanceIfNotReleased() throws Exception {
33 final ReusableLogEventFactory factory = new ReusableLogEventFactory();
34 final LogEvent event1 = callCreateEvent(factory, "a", Level.DEBUG, new SimpleMessage("abc"), null);
35 final LogEvent event2 = callCreateEvent(factory, "b", Level.INFO, new SimpleMessage("xyz"), null);
36 assertNotSame(event1, event2);
37 ReusableLogEventFactory.release(event1);
38 ReusableLogEventFactory.release(event2);
39 }
40
41 @Test
3242 public void testCreateEventReturnsSameInstance() throws Exception {
3343 final ReusableLogEventFactory factory = new ReusableLogEventFactory();
3444 final LogEvent event1 = callCreateEvent(factory, "a", Level.DEBUG, new SimpleMessage("abc"), null);
45 ReusableLogEventFactory.release(event1);
3546 final LogEvent event2 = callCreateEvent(factory, "b", Level.INFO, new SimpleMessage("xyz"), null);
3647 assertSame(event1, event2);
48
49 ReusableLogEventFactory.release(event2);
50 final LogEvent event3 = callCreateEvent(factory, "c", Level.INFO, new SimpleMessage("123"), null);
51 assertSame(event2, event3);
52 ReusableLogEventFactory.release(event3);
3753 }
3854
3955 @Test
4460 assertEquals("level", Level.DEBUG, event1.getLevel());
4561 assertEquals("msg", new SimpleMessage("abc"), event1.getMessage());
4662
63 ReusableLogEventFactory.release(event1);
4764 final LogEvent event2 = callCreateEvent(factory, "b", Level.INFO, new SimpleMessage("xyz"), null);
4865 assertSame(event1, event2);
4966
95112 assertEquals("msg", new SimpleMessage("xyz"), event2[0].getMessage());
96113 assertEquals("thread name", "Thread 2", event2[0].getThreadName());
97114 assertEquals("tid", t2.getId(), event2[0].getThreadId());
115 ReusableLogEventFactory.release(event1[0]);
116 ReusableLogEventFactory.release(event2[0]);
117 }
118
119 @Test
120 public void testCreateEventInitFieldsProperly() throws Exception {
121 final ReusableLogEventFactory factory = new ReusableLogEventFactory();
122 final LogEvent event = callCreateEvent(factory, "logger", Level.INFO, new SimpleMessage("xyz"), null);
123 ReusableLogEventFactory.release(event);
124 assertNotNull(event.getContextMap());
125 assertNotNull(event.getContextStack());
98126 }
99127
100128 }
1515 */
1616 package org.apache.logging.log4j.core.impl;
1717
18 import static org.junit.Assert.assertEquals;
19 import static org.junit.Assert.assertNotNull;
20
1821 import java.util.Arrays;
1922 import java.util.List;
20
21 import org.apache.logging.log4j.core.util.Constants;
23 import java.util.Map;
24
25 import org.apache.logging.log4j.core.pattern.JAnsiTextRenderer;
26 import org.apache.logging.log4j.core.pattern.TextRenderer;
2227 import org.apache.logging.log4j.util.Strings;
28 import org.fusesource.jansi.AnsiRenderer.Code;
29 import org.junit.Assert;
2330 import org.junit.Test;
24
25 import static org.junit.Assert.*;
2631
2732 /**
2833 * Unit tests for {@code ThrowableFormatOptions}.
3136
3237 /**
3338 * Runs a given test comparing against the expected values.
34 * @param options The list of options to parse.
35 * @param expectedLines The expected lines.
36 * @param expectedPackages The expected package filters.
37 * @param expectedSeparator The expected seperator.
38 */
39 private static void test(final String[] options, final int expectedLines, final String expectedSeparator, final List<String> expectedPackages) {
40 final ThrowableFormatOptions o = ThrowableFormatOptions.newInstance(options);
41 assertEquals("getLines", expectedLines, o.getLines());
42 assertEquals("getSeparator", expectedSeparator, o.getSeparator());
43 assertEquals("getPackages", expectedPackages, o.getPackages());
44 assertEquals("allLines", expectedLines == Integer.MAX_VALUE, o.allLines());
45 assertEquals("anyLines", expectedLines != 0, o.anyLines());
46 assertEquals("minLines", 0, o.minLines(0));
47 assertEquals("minLines", expectedLines, o.minLines(Integer.MAX_VALUE));
48 assertEquals("hasPackages", expectedPackages != null && !expectedPackages.isEmpty(), o.hasPackages());
49 assertNotNull("toString", o.toString());
39 *
40 * @param options
41 * The list of options to parse.
42 * @param expectedLines
43 * The expected lines.
44 * @param expectedPackages
45 * The expected package filters.
46 * @param expectedSeparator
47 * The expected separator.
48 */
49 private static ThrowableFormatOptions test(final String[] options, final int expectedLines,
50 final String expectedSeparator, final List<String> expectedPackages) {
51 final ThrowableFormatOptions tfo = ThrowableFormatOptions.newInstance(options);
52 assertEquals("getLines", expectedLines, tfo.getLines());
53 assertEquals("getSeparator", expectedSeparator, tfo.getSeparator());
54 assertEquals("getPackages", expectedPackages, tfo.getIgnorePackages());
55 assertEquals("allLines", expectedLines == Integer.MAX_VALUE, tfo.allLines());
56 assertEquals("anyLines", expectedLines != 0, tfo.anyLines());
57 assertEquals("minLines", 0, tfo.minLines(0));
58 assertEquals("minLines", expectedLines, tfo.minLines(Integer.MAX_VALUE));
59 assertEquals("hasPackages", expectedPackages != null && !expectedPackages.isEmpty(), tfo.hasPackages());
60 assertNotNull("toString", tfo.toString());
61 return tfo;
5062 }
5163
5264 /**
5466 */
5567 @Test
5668 public void testNull() {
57 test(null, Integer.MAX_VALUE, Constants.LINE_SEPARATOR, null);
69 test(null, Integer.MAX_VALUE, Strings.LINE_SEPARATOR, null);
5870 }
5971
6072 /**
6274 */
6375 @Test
6476 public void testEmpty() {
65 test(new String[]{}, Integer.MAX_VALUE, Constants.LINE_SEPARATOR, null);
77 test(new String[] {}, Integer.MAX_VALUE, Strings.LINE_SEPARATOR, null);
6678 }
6779
6880 /**
7082 */
7183 @Test
7284 public void testOneNullElement() {
73 test(new String[]{null}, Integer.MAX_VALUE, Constants.LINE_SEPARATOR, null);
85 test(new String[] { null }, Integer.MAX_VALUE, Strings.LINE_SEPARATOR, null);
7486 }
7587
7688 /**
7890 */
7991 @Test
8092 public void testOneEmptyElement() {
81 test(new String[]{""}, Integer.MAX_VALUE, Constants.LINE_SEPARATOR, null);
93 test(new String[] { "" }, Integer.MAX_VALUE, Strings.LINE_SEPARATOR, null);
8294 }
8395
8496 /**
8698 */
8799 @Test
88100 public void testFull() {
89 test(new String[]{"full"}, Integer.MAX_VALUE, Constants.LINE_SEPARATOR, null);
101 test(new String[] { "full" }, Integer.MAX_VALUE, Strings.LINE_SEPARATOR, null);
102 }
103
104 /**
105 * Test {@code %throwable{full}{ansi} }
106 */
107 @Test
108 public void testFullAnsi() {
109 final ThrowableFormatOptions tfo = test(new String[] { "full", "ansi" },
110 Integer.MAX_VALUE, Strings.LINE_SEPARATOR, null);
111 testFullAnsiEmptyConfig(tfo);
112 }
113
114 /**
115 * Test {@code %throwable{full}{ansi} }
116 */
117 @Test
118 public void testFullAnsiEmptyConfig() {
119 final ThrowableFormatOptions tfo = test(new String[] { "full", "ansi()" },
120 Integer.MAX_VALUE, Strings.LINE_SEPARATOR, null);
121 testFullAnsiEmptyConfig(tfo);
122 }
123
124 private void testFullAnsiEmptyConfig(final ThrowableFormatOptions tfo) {
125 final TextRenderer textRenderer = tfo.getTextRenderer();
126 Assert.assertNotNull(textRenderer);
127 Assert.assertTrue(textRenderer instanceof JAnsiTextRenderer);
128 final JAnsiTextRenderer jansiRenderer = (JAnsiTextRenderer) textRenderer;
129 final Map<String, Code[]> styleMap = jansiRenderer.getStyleMap();
130 // We have defaults
131 Assert.assertFalse(styleMap.isEmpty());
132 Assert.assertNotNull(styleMap.get("Name"));
133 }
134
135 /**
136 * Test {@code %throwable{full}{ansi(Warning=red))} }
137 */
138 @Test
139 public void testFullAnsiWithCustomStyle() {
140 final ThrowableFormatOptions tfo = test(new String[] { "full", "ansi(Warning=red)" },
141 Integer.MAX_VALUE, Strings.LINE_SEPARATOR, null);
142 final TextRenderer textRenderer = tfo.getTextRenderer();
143 Assert.assertNotNull(textRenderer);
144 Assert.assertTrue(textRenderer instanceof JAnsiTextRenderer);
145 final JAnsiTextRenderer jansiRenderer = (JAnsiTextRenderer) textRenderer;
146 final Map<String, Code[]> styleMap = jansiRenderer.getStyleMap();
147 Assert.assertArrayEquals(new Code[] { Code.RED }, styleMap.get("Warning"));
148 }
149
150 /**
151 * Test {@code %throwable{full}{ansi(Warning=red Key=blue Value=cyan))} }
152 */
153 @Test
154 public void testFullAnsiWithCustomStyles() {
155 final ThrowableFormatOptions tfo = test(new String[] { "full", "ansi(Warning=red Key=blue Value=cyan)" },
156 Integer.MAX_VALUE, Strings.LINE_SEPARATOR, null);
157 final TextRenderer textRenderer = tfo.getTextRenderer();
158 Assert.assertNotNull(textRenderer);
159 Assert.assertTrue(textRenderer instanceof JAnsiTextRenderer);
160 final JAnsiTextRenderer jansiRenderer = (JAnsiTextRenderer) textRenderer;
161 final Map<String, Code[]> styleMap = jansiRenderer.getStyleMap();
162 Assert.assertArrayEquals(new Code[] { Code.RED }, styleMap.get("Warning"));
163 Assert.assertArrayEquals(new Code[] { Code.BLUE }, styleMap.get("Key"));
164 Assert.assertArrayEquals(new Code[] { Code.CYAN }, styleMap.get("Value"));
165 }
166
167 /**
168 * Test {@code %throwable{full}{ansi(Warning=red Key=blue,bg_red Value=cyan,bg_black,underline)} }
169 */
170 @Test
171 public void testFullAnsiWithCustomComplexStyles() {
172 final ThrowableFormatOptions tfo = test(
173 new String[] { "full", "ansi(Warning=red Key=blue,bg_red Value=cyan,bg_black,underline)" }, Integer.MAX_VALUE,
174 Strings.LINE_SEPARATOR, null);
175 final TextRenderer textRenderer = tfo.getTextRenderer();
176 Assert.assertNotNull(textRenderer);
177 Assert.assertTrue(textRenderer instanceof JAnsiTextRenderer);
178 final JAnsiTextRenderer jansiRenderer = (JAnsiTextRenderer) textRenderer;
179 final Map<String, Code[]> styleMap = jansiRenderer.getStyleMap();
180 Assert.assertArrayEquals(new Code[] { Code.RED }, styleMap.get("Warning"));
181 Assert.assertArrayEquals(new Code[] { Code.BLUE, Code.BG_RED }, styleMap.get("Key"));
182 Assert.assertArrayEquals(new Code[] { Code.CYAN, Code.BG_BLACK, Code.UNDERLINE }, styleMap.get("Value"));
90183 }
91184
92185 /**
94187 */
95188 @Test
96189 public void testNone() {
97 test(new String[]{"none"}, 0, Constants.LINE_SEPARATOR, null);
190 test(new String[] { "none" }, 0, Strings.LINE_SEPARATOR, null);
98191 }
99192
100193 /**
102195 */
103196 @Test
104197 public void testShort() {
105 test(new String[]{"short"}, 2, Constants.LINE_SEPARATOR, null);
198 test(new String[] { "short" }, 2, Strings.LINE_SEPARATOR, null);
106199 }
107200
108201 /**
110203 */
111204 @Test
112205 public void testDepth() {
113 test(new String[]{"10"}, 10, Constants.LINE_SEPARATOR, null);
206 test(new String[] { "10" }, 10, Strings.LINE_SEPARATOR, null);
114207 }
115208
116209 /**
118211 */
119212 @Test
120213 public void testSeparator() {
121 test(new String[]{"separator(|)"}, Integer.MAX_VALUE, "|", null);
214 test(new String[] { "separator(|)" }, Integer.MAX_VALUE, "|", null);
122215 }
123216
124217 /**
126219 */
127220 @Test
128221 public void testSeparatorAsEmpty() {
129 test(new String[]{"separator()"}, Integer.MAX_VALUE, Strings.EMPTY, null);
222 test(new String[] { "separator()" }, Integer.MAX_VALUE, Strings.EMPTY, null);
130223 }
131224
132225 /**
134227 */
135228 @Test
136229 public void testSeparatorAsDefaultLineSeparator() {
137 test(new String[]{"separator(" + Constants.LINE_SEPARATOR + ')'}, Integer.MAX_VALUE, Constants.LINE_SEPARATOR, null);
230 test(new String[] { "separator(" + Strings.LINE_SEPARATOR + ')' }, Integer.MAX_VALUE,
231 Strings.LINE_SEPARATOR, null);
138232 }
139233
140234 /**
142236 */
143237 @Test
144238 public void testSeparatorAsMultipleCharacters() {
145 test(new String[]{"separator( | )"}, Integer.MAX_VALUE, " | ", null);
239 test(new String[] { "separator( | )" }, Integer.MAX_VALUE, " | ", null);
146240 }
147241
148242 /**
150244 */
151245 @Test
152246 public void testFullAndSeparator() {
153 test(new String[]{"full","separator(|)"}, Integer.MAX_VALUE, "|", null);
247 test(new String[] { "full", "separator(|)" }, Integer.MAX_VALUE, "|", null);
154248 }
155249
156250 /**
158252 */
159253 @Test
160254 public void testNoneAndSeparator() {
161 test(new String[]{"none","separator(|)"}, 0, "|", null);
255 test(new String[] { "none", "separator(|)" }, 0, "|", null);
162256 }
163257
164258 /**
166260 */
167261 @Test
168262 public void testShortAndSeparator() {
169 test(new String[]{"short","separator(|)"}, 2, "|", null);
263 test(new String[] { "short", "separator(|)" }, 2, "|", null);
170264 }
171265
172266 /**
174268 */
175269 @Test
176270 public void testDepthAndSeparator() {
177 test(new String[]{"10","separator(|)"}, 10, "|", null);
271 test(new String[] { "10", "separator(|)" }, 10, "|", null);
178272 }
179273
180274 /**
182276 */
183277 @Test
184278 public void testFilters() {
185 test(new String[]{"filters(packages)"}, Integer.MAX_VALUE, Constants.LINE_SEPARATOR, Arrays.asList("packages"));
279 test(new String[] { "filters(packages)" }, Integer.MAX_VALUE, Strings.LINE_SEPARATOR,
280 Arrays.asList("packages"));
186281 }
187282
188283 /**
190285 */
191286 @Test
192287 public void testFiltersAsEmpty() {
193 test(new String[]{"filters()"}, Integer.MAX_VALUE, Constants.LINE_SEPARATOR, null);
288 test(new String[] { "filters()" }, Integer.MAX_VALUE, Strings.LINE_SEPARATOR, null);
194289 }
195290
196291 /**
198293 */
199294 @Test
200295 public void testFiltersAsMultiplePackages() {
201 test(new String[]{"filters(package1,package2)"}, Integer.MAX_VALUE, Constants.LINE_SEPARATOR, Arrays.asList("package1","package2"));
296 test(new String[] { "filters(package1,package2)" }, Integer.MAX_VALUE, Strings.LINE_SEPARATOR,
297 Arrays.asList("package1", "package2"));
202298 }
203299
204300 /**
206302 */
207303 @Test
208304 public void testFullAndFilters() {
209 test(new String[]{"full","filters(packages)"}, Integer.MAX_VALUE, Constants.LINE_SEPARATOR, Arrays.asList("packages"));
305 test(new String[] { "full", "filters(packages)" }, Integer.MAX_VALUE, Strings.LINE_SEPARATOR,
306 Arrays.asList("packages"));
210307 }
211308
212309 /**
214311 */
215312 @Test
216313 public void testNoneAndFilters() {
217 test(new String[]{"none","filters(packages)"}, 0, Constants.LINE_SEPARATOR, Arrays.asList("packages"));
314 test(new String[] { "none", "filters(packages)" }, 0, Strings.LINE_SEPARATOR, Arrays.asList("packages"));
218315 }
219316
220317 /**
222319 */
223320 @Test
224321 public void testShortAndFilters() {
225 test(new String[]{"short","filters(packages)"}, 2, Constants.LINE_SEPARATOR, Arrays.asList("packages"));
322 test(new String[] { "short", "filters(packages)" }, 2, Strings.LINE_SEPARATOR, Arrays.asList("packages"));
226323 }
227324
228325 /**
230327 */
231328 @Test
232329 public void testDepthAndFilters() {
233 test(new String[]{"10","filters(packages)"}, 10, Constants.LINE_SEPARATOR, Arrays.asList("packages"));
330 test(new String[] { "10", "filters(packages)" }, 10, Strings.LINE_SEPARATOR, Arrays.asList("packages"));
234331 }
235332
236333 /**
238335 */
239336 @Test
240337 public void testFullAndSeparatorAndFilters() {
241 test(new String[]{"full","separator(|)","filters(packages)"}, Integer.MAX_VALUE, "|", Arrays.asList("packages"));
338 test(new String[] { "full", "separator(|)", "filters(packages)" }, Integer.MAX_VALUE, "|",
339 Arrays.asList("packages"));
242340 }
243341
244342 /**
246344 */
247345 @Test
248346 public void testNoneAndSeparatorAndFilters() {
249 test(new String[]{"none","separator(|)","filters(packages)"}, 0, "|", Arrays.asList("packages"));
347 test(new String[] { "none", "separator(|)", "filters(packages)" }, 0, "|", Arrays.asList("packages"));
250348 }
251349
252350 /**
254352 */
255353 @Test
256354 public void testShortAndSeparatorAndFilters() {
257 test(new String[]{"short","separator(|)","filters(packages)"}, 2, "|", Arrays.asList("packages"));
355 test(new String[] { "short", "separator(|)", "filters(packages)" }, 2, "|", Arrays.asList("packages"));
258356 }
259357
260358 /**
262360 */
263361 @Test
264362 public void testDepthAndSeparatorAndFilters() {
265 test(new String[]{"10","separator(|)","filters(packages)"}, 10, "|", Arrays.asList("packages"));
363 test(new String[] { "10", "separator(|)", "filters(packages)" }, 10, "|", Arrays.asList("packages"));
266364 }
267365
268366 /**
270368 */
271369 @Test
272370 public void testSingleOptionFullAndFilters() {
273 test(new String[]{"full,filters(packages)"}, Integer.MAX_VALUE, Constants.LINE_SEPARATOR, Arrays.asList("packages"));
371 test(new String[] { "full,filters(packages)" }, Integer.MAX_VALUE, Strings.LINE_SEPARATOR,
372 Arrays.asList("packages"));
274373 }
275374
276375 /**
278377 */
279378 @Test
280379 public void testSingleOptionNoneAndFilters() {
281 test(new String[]{"none,filters(packages)"}, 0, Constants.LINE_SEPARATOR, Arrays.asList("packages"));
380 test(new String[] { "none,filters(packages)" }, 0, Strings.LINE_SEPARATOR, Arrays.asList("packages"));
282381 }
283382
284383 /**
286385 */
287386 @Test
288387 public void testSingleOptionShortAndFilters() {
289 test(new String[]{"short,filters(packages)"}, 2, Constants.LINE_SEPARATOR, Arrays.asList("packages"));
388 test(new String[] { "short,filters(packages)" }, 2, Strings.LINE_SEPARATOR, Arrays.asList("packages"));
290389 }
291390
292391 /**
294393 */
295394 @Test
296395 public void testSingleOptionDepthAndFilters() {
297 test(new String[]{"10,filters(packages)"}, 10, Constants.LINE_SEPARATOR, Arrays.asList("packages"));
396 test(new String[] { "10,filters(packages)" }, 10, Strings.LINE_SEPARATOR, Arrays.asList("packages"));
298397 }
299398
300399 /**
302401 */
303402 @Test
304403 public void testSingleOptionFullAndMultipleFilters() {
305 test(new String[]{"full,filters(package1,package2)"}, Integer.MAX_VALUE, Constants.LINE_SEPARATOR, Arrays.asList("package1","package2"));
404 test(new String[] { "full,filters(package1,package2)" }, Integer.MAX_VALUE, Strings.LINE_SEPARATOR,
405 Arrays.asList("package1", "package2"));
306406 }
307407
308408 /**
310410 */
311411 @Test
312412 public void testSingleOptionNoneAndMultipleFilters() {
313 test(new String[]{"none,filters(package1,package2)"}, 0, Constants.LINE_SEPARATOR, Arrays.asList("package1","package2"));
413 test(new String[] { "none,filters(package1,package2)" }, 0, Strings.LINE_SEPARATOR,
414 Arrays.asList("package1", "package2"));
314415 }
315416
316417 /**
318419 */
319420 @Test
320421 public void testSingleOptionShortAndMultipleFilters() {
321 test(new String[]{"short,filters(package1,package2)"}, 2, Constants.LINE_SEPARATOR, Arrays.asList("package1","package2"));
422 test(new String[] { "short,filters(package1,package2)" }, 2, Strings.LINE_SEPARATOR,
423 Arrays.asList("package1", "package2"));
322424 }
323425
324426 /**
326428 */
327429 @Test
328430 public void testSingleOptionDepthAndMultipleFilters() {
329 test(new String[]{"10,filters(package1,package2)"}, 10, Constants.LINE_SEPARATOR, Arrays.asList("package1","package2"));
431 test(new String[] { "10,filters(package1,package2)" }, 10, Strings.LINE_SEPARATOR,
432 Arrays.asList("package1", "package2"));
330433 }
331434 }
2626 import java.io.IOException;
2727 import java.io.ObjectInputStream;
2828 import java.io.ObjectOutputStream;
29 import java.net.BindException;
30 import java.net.InetSocketAddress;
31 import java.net.SocketPermission;
32 import java.nio.channels.ServerSocketChannel;
33 import java.security.CodeSource;
34 import java.security.PermissionCollection;
35 import java.security.Permissions;
36 import java.security.Policy;
2937 import java.util.HashMap;
3038 import java.util.Map;
3139 import java.util.Stack;
122130 }
123131 }
124132
133 @Test
134 public void testLogStackTraceWithClassThatWillCauseSecurityException() throws IOException {
135 class SimplePolicy extends Policy {
136
137 private final Permissions permissions;
138
139 public SimplePolicy(final Permissions permissions) {
140 this.permissions = permissions;
141 }
142
143 @Override
144 public PermissionCollection getPermissions(final CodeSource codesource) {
145 return permissions;
146 }
147
148 }
149
150 final SecurityManager sm = System.getSecurityManager();
151 try {
152 final Permissions permissions = new Permissions();
153
154 // you know, for binding
155 permissions.add(new SocketPermission("localhost:9300", "listen,resolve"));
156
157 /**
158 * the JUnit test runner uses reflection to invoke the test; while leaving this
159 * permission out would display the same issue, it's clearer to grant this
160 * permission and show the real issue that would arise
161 */
162 // TODO: other JDKs might need a different permission here
163 permissions.add(new RuntimePermission("accessClassInPackage.sun.reflect"));
164
165 // for restoring the security manager after test execution
166 permissions.add(new RuntimePermission("setSecurityManager"));
167
168 Policy.setPolicy(new SimplePolicy(permissions));
169 System.setSecurityManager(new SecurityManager());
170 ServerSocketChannel.open().socket().bind(new InetSocketAddress("localhost", 9300));
171 ServerSocketChannel.open().socket().bind(new InetSocketAddress("localhost", 9300));
172 fail("expected a java.net.BindException");
173 } catch (final BindException e) {
174 new ThrowableProxy(e);
175 } finally {
176 // restore the security manager
177 System.setSecurityManager(sm);
178 }
179 }
180
125181 // DO NOT REMOVE THIS COMMENT:
126182 // UNCOMMENT WHEN GENERATING SERIALIZED THROWABLEPROXY FOR #testSerializationWithUnknownThrowable
127183 // public static class DeletedException extends Exception {
2222
2323 @Override
2424 protected ObjectMapper newObjectMapper() {
25 return new Log4jJsonObjectMapper(false);
25 return new Log4jJsonObjectMapper(false, true);
2626 }
2727
2828 }
7777 public void testFromJsonWithLog4jModule() throws Exception {
7878 final ObjectMapper mapper = new ObjectMapper();
7979 final boolean encodeThreadContextAsList = false;
80 final SimpleModule module = new Log4jJsonModule(encodeThreadContextAsList);
80 final SimpleModule module = new Log4jJsonModule(encodeThreadContextAsList, true);
8181 module.addDeserializer(StackTraceElement.class, new Log4jStackTraceElementDeserializer());
8282 mapper.registerModule(module);
8383 final StackTraceElement expected = new StackTraceElement("package.SomeClass", "someMethod", "SomeClass.java", 123);
2323
2424 import org.apache.commons.csv.CSVFormat;
2525 import org.apache.logging.log4j.Level;
26 import org.apache.logging.log4j.ThreadContext;
2726 import org.apache.logging.log4j.core.Appender;
2827 import org.apache.logging.log4j.core.BasicConfigurationFactory;
2928 import org.apache.logging.log4j.core.Logger;
3029 import org.apache.logging.log4j.core.LoggerContext;
3130 import org.apache.logging.log4j.core.config.ConfigurationFactory;
31 import org.apache.logging.log4j.junit.ThreadContextRule;
3232 import org.apache.logging.log4j.test.appender.ListAppender;
3333 import org.junit.AfterClass;
3434 import org.junit.Assert;
3535 import org.junit.BeforeClass;
36 import org.junit.Rule;
3637 import org.junit.Test;
3738
3839 /**
4344 public class CsvLogEventLayoutTest {
4445 static ConfigurationFactory cf = new BasicConfigurationFactory();
4546
47 @Rule
48 public final ThreadContextRule threadContextRule = new ThreadContextRule();
49
4650 @AfterClass
4751 public static void cleanupClass() {
4852 ConfigurationFactory.removeConfigurationFactory(cf);
49 ThreadContext.clearAll();
5053 }
5154
5255 @BeforeClass
5356 public static void setupClass() {
54 ThreadContext.clearAll();
5557 ConfigurationFactory.setConfigurationFactory(cf);
5658 final LoggerContext ctx = LoggerContext.getContext();
5759 ctx.reconfigure();
1515 */
1616 package org.apache.logging.log4j.core.layout;
1717
18 import static org.junit.Assert.assertEquals;
19
1820 import java.nio.charset.StandardCharsets;
1921 import java.util.Arrays;
2022 import java.util.Collection;
2527
2628 import org.apache.commons.csv.CSVFormat;
2729 import org.apache.logging.log4j.Level;
28 import org.apache.logging.log4j.ThreadContext;
30 import org.apache.logging.log4j.LogManager;
2931 import org.apache.logging.log4j.core.Appender;
3032 import org.apache.logging.log4j.core.Logger;
3133 import org.apache.logging.log4j.junit.LoggerContextRule;
34 import org.apache.logging.log4j.junit.ThreadContextRule;
3235 import org.apache.logging.log4j.message.ObjectArrayMessage;
3336 import org.apache.logging.log4j.test.appender.ListAppender;
34 import org.junit.AfterClass;
3537 import org.junit.Assert;
3638 import org.junit.Rule;
3739 import org.junit.Test;
3840 import org.junit.runner.RunWith;
3941 import org.junit.runners.Parameterized;
40
41 import static org.junit.Assert.*;
4242
4343 /**
4444 * Tests {@link AbstractCsvLayout}.
4949 public class CsvParameterLayoutTest {
5050 @Parameterized.Parameters(name = "{0}")
5151 public static Collection<Object[]> data() {
52 return Arrays.asList(
53 new Object[][]{
54 { new LoggerContextRule("csvParamsSync.xml"), },
55 { new LoggerContextRule("csvParamsMixedAsync.xml"), },
56 }
57 );
52 return Arrays.asList(new Object[][] { { new LoggerContextRule("csvParamsSync.xml"), },
53 { new LoggerContextRule("csvParamsMixedAsync.xml"), }, });
5854 }
5955
6056 @Rule
6157 public final LoggerContextRule init;
6258
59 @Rule
60 public final ThreadContextRule threadContextRule = new ThreadContextRule();
61
6362 public CsvParameterLayoutTest(final LoggerContextRule contextRule) {
6463 this.init = contextRule;
65 }
66
67 @AfterClass
68 public static void cleanupClass() {
69 // System.setProperty(Constants.LOG4J_CONTEXT_SELECTOR, null);
70 ThreadContext.clearAll();
7164 }
7265
7366 @Test
8982 assertEquals("text/csv; charset=UTF-8", layout.getContentType());
9083 }
9184
92 static void testLayoutNormalApi(final Logger root, final AbstractCsvLayout layout, final boolean messageApi) throws Exception {
93 final Map<String, Appender> appenders = root.getAppenders();
94 for (final Appender appender : appenders.values()) {
95 root.removeAppender(appender);
96 }
85 static void testLayoutNormalApi(final Logger root, final AbstractCsvLayout layout, final boolean messageApi)
86 throws Exception {
87 removeAppenders(root);
9788 // set up appender
9889 final ListAppender appender = new ListAppender("List", null, layout, true, false);
9990 appender.start();
110101 } else {
111102 logDebugNormalApi(root);
112103 }
113
114 // wait until background thread finished processing
115 appender.countDownLatch.await(10, TimeUnit.SECONDS);
116 assertEquals("Background thread did not finish processing: msg count", 4, appender.getMessages().size());
104 final int msgCount = 4;
105 if (appender.getMessages().size() < msgCount) {
106 // wait until background thread finished processing
107 appender.countDownLatch.await(10, TimeUnit.SECONDS);
108 }
109 assertEquals("Background thread did not finish processing: msg count", msgCount, appender.getMessages().size());
117110
118111 // don't stop appender until background thread is done
119112 appender.stop();
124117 Assert.assertEquals("2" + d + "3", list.get(1));
125118 Assert.assertEquals("5" + d + "6", list.get(2));
126119 Assert.assertEquals("7" + d + "8" + d + "9" + d + "10", list.get(3));
120 }
121
122 private static void removeAppenders(final Logger root) {
123 final Map<String, Appender> appenders = root.getAppenders();
124 for (final Appender appender : appenders.values()) {
125 root.removeAppender(appender);
126 }
127127 }
128128
129129 private static void logDebugNormalApi(final Logger root) {
157157 final Logger root = this.init.getRootLogger();
158158 testLayoutNormalApi(root, CsvParameterLayout.createLayout(CSVFormat.TDF), true);
159159 }
160
161 @Test
162 public void testLogJsonArgument() throws InterruptedException {
163 final ListAppender appender = (ListAppender) init.getAppender("List");
164 appender.countDownLatch = new CountDownLatch(4);
165 appender.clear();
166 final Logger logger = (Logger) LogManager.getRootLogger();
167 final String json = "{\"id\":10,\"name\":\"Alice\"}";
168 logger.error("log:{}", json);
169 // wait until background thread finished processing
170 final int msgCount = 1;
171 if (appender.getMessages().size() < msgCount) {
172 appender.countDownLatch.await(5, TimeUnit.SECONDS);
173 }
174 assertEquals("Background thread did not finish processing: msg count", msgCount, appender.getMessages().size());
175
176 // don't stop appender until background thread is done
177 appender.stop();
178 final List<String> list = appender.getMessages();
179 final String eventStr = list.get(0).toString();
180 Assert.assertTrue(eventStr, eventStr.contains(json));
181 }
182
160183 }
2323 import org.apache.logging.log4j.core.config.ConfigurationFactory;
2424 import org.apache.logging.log4j.core.layout.GelfLayout.CompressionType;
2525 import org.apache.logging.log4j.core.util.KeyValuePair;
26 import org.apache.logging.log4j.junit.ThreadContextRule;
2627 import org.apache.logging.log4j.test.appender.EncodingListAppender;
2728 import org.apache.logging.log4j.test.appender.ListAppender;
2829 import org.junit.AfterClass;
2930 import org.junit.BeforeClass;
31 import org.junit.Rule;
3032 import org.junit.Test;
3133
3234 import java.io.ByteArrayInputStream;
4042 import static org.junit.Assert.assertEquals;
4143
4244 public class GelfLayoutTest {
45
4346 static ConfigurationFactory configFactory = new BasicConfigurationFactory();
47
4448 private static final String HOSTNAME = "TheHost";
45
4649 private static final String KEY1 = "Key1";
4750 private static final String KEY2 = "Key2";
4851 private static final String LINE1 = "empty mdc";
5558 private static final String VALUE1 = "Value1";
5659 private static final String VALUE2 = "Value2";
5760
61 @Rule
62 public final ThreadContextRule threadContextRule = new ThreadContextRule();
63
5864 @AfterClass
5965 public static void cleanupClass() {
6066 ConfigurationFactory.removeConfigurationFactory(configFactory);
61 ThreadContext.clearAll();
6267 }
6368
6469 @BeforeClass
6570 public static void setupClass() {
66 ThreadContext.clearAll();
6771 ConfigurationFactory.setConfigurationFactory(configFactory);
6872 final LoggerContext ctx = LoggerContext.getContext();
6973 ctx.reconfigure();
106110
107111 final Exception exception = new RuntimeException("some error");
108112 root.error(LINE3, exception);
109
110 ThreadContext.clearMap();
111113
112114 formattedAppender.stop();
113115
2626 import org.apache.logging.log4j.core.Logger;
2727 import org.apache.logging.log4j.core.LoggerContext;
2828 import org.apache.logging.log4j.core.config.ConfigurationFactory;
29 import org.apache.logging.log4j.junit.ThreadContextRule;
2930 import org.apache.logging.log4j.test.appender.ListAppender;
3031 import org.junit.AfterClass;
3132 import org.junit.BeforeClass;
33 import org.junit.Rule;
3234 import org.junit.Test;
3335
3436 import static org.junit.Assert.*;
4244
4345 static ConfigurationFactory cf = new BasicConfigurationFactory();
4446
47 @Rule
48 public final ThreadContextRule threadContextRule = new ThreadContextRule();
49
4550 @BeforeClass
4651 public static void setupClass() {
47 ThreadContext.clearAll();
4852 ConfigurationFactory.setConfigurationFactory(cf);
4953 final LoggerContext ctx = LoggerContext.getContext();
5054 ctx.reconfigure();
5357 @AfterClass
5458 public static void cleanupClass() {
5559 ConfigurationFactory.removeConfigurationFactory(cf);
56 ThreadContext.clearAll();
5760 }
5861
5962 private static final String body = "<tr><td bgcolor=\"#993300\" style=\"color:White; font-size : small;\" colspan=\"6\">java.lang.NullPointerException: test";
1616 package org.apache.logging.log4j.core.layout;
1717
1818 import static org.junit.Assert.assertEquals;
19 import static org.junit.Assert.assertFalse;
1920 import static org.junit.Assert.assertNull;
2021 import static org.junit.Assert.assertTrue;
2122
8586
8687 private void checkMapEntry(final String key, final String value, final boolean compact, final String str,
8788 final boolean contextMapAslist) {
88 final String propSep = this.toPropertySeparator(compact);
89 this.toPropertySeparator(compact);
8990 if (contextMapAslist) {
9091 // {"key":"KEY", "value":"VALUE"}
9192 final String expected = String.format("{\"key\":\"%s\",\"value\":\"%s\"}", key, value);
109110 assertTrue(str, str.contains(DQUOTE + name + DQUOTE + propSep));
110111 }
111112
113 private void checkPropertyNameAbsent(final String name, final boolean compact, final String str) {
114 final String propSep = this.toPropertySeparator(compact);
115 assertFalse(str, str.contains(DQUOTE + name + DQUOTE + propSep));
116 }
117
112118 private void testAllFeatures(final boolean includeSource, final boolean compact, final boolean eventEol,
113 final boolean includeContext, final boolean contextMapAslist)
119 final boolean includeContext, final boolean contextMapAslist, final boolean includeStacktace)
114120 throws Exception {
115121 final Log4jLogEvent expected = LogEventFixtures.createLogEvent();
116122 final AbstractJacksonLayout layout = JsonLayout.createLayout(null, includeSource,
117 includeContext, contextMapAslist, false, compact, eventEol, null, null, StandardCharsets.UTF_8);
123 includeContext, contextMapAslist, false, compact, eventEol, null, null, StandardCharsets.UTF_8, includeStacktace);
118124 final String str = layout.toSerializable(expected);
119 // System.out.println(str);
120 final String propSep = this.toPropertySeparator(compact);
125 this.toPropertySeparator(compact);
121126 // Just check for \n since \r might or might not be there.
122127 assertEquals(str, !compact || eventEol, str.contains("\n"));
123128 assertEquals(str, includeSource, str.contains("source"));
124129 assertEquals(str, includeContext, str.contains("contextMap"));
125 final Log4jLogEvent actual = new Log4jJsonObjectMapper(contextMapAslist).readValue(str, Log4jLogEvent.class);
126 LogEventFixtures.assertEqualLogEvents(expected, actual, includeSource, includeContext);
130 final Log4jLogEvent actual = new Log4jJsonObjectMapper(contextMapAslist, includeStacktace).readValue(str, Log4jLogEvent.class);
131 LogEventFixtures.assertEqualLogEvents(expected, actual, includeSource, includeContext, includeStacktace);
127132 if (includeContext) {
128133 this.checkMapEntry("MDC.A", "A_Value", compact, str, contextMapAslist);
129134 this.checkMapEntry("MDC.B", "B_Value", compact, str, contextMapAslist);
141146 this.checkPropertyName("message", compact, str);
142147 this.checkPropertyName("thrown", compact, str);
143148 this.checkPropertyName("cause", compact, str);
144 this.checkPropertyName("class", compact, str);
145 this.checkPropertyName("method", compact, str);
146 this.checkPropertyName("file", compact, str);
147 this.checkPropertyName("line", compact, str);
148 this.checkPropertyName("exact", compact, str);
149 this.checkPropertyName("location", compact, str);
150 this.checkPropertyName("version", compact, str);
151149 this.checkPropertyName("commonElementCount", compact, str);
152150 this.checkPropertyName("localizedMessage", compact, str);
153 this.checkPropertyName("extendedStackTrace", compact, str);
151 if (includeStacktace) {
152 this.checkPropertyName("extendedStackTrace", compact, str);
153 this.checkPropertyName("class", compact, str);
154 this.checkPropertyName("method", compact, str);
155 this.checkPropertyName("file", compact, str);
156 this.checkPropertyName("line", compact, str);
157 this.checkPropertyName("exact", compact, str);
158 this.checkPropertyName("location", compact, str);
159 this.checkPropertyName("version", compact, str);
160 } else {
161 this.checkPropertyNameAbsent("extendedStackTrace", compact, str);
162 }
154163 this.checkPropertyName("suppressed", compact, str);
155164 this.checkPropertyName("loggerFqcn", compact, str);
156165 this.checkPropertyName("endOfBatch", compact, str);
157166 if (includeContext) {
158167 this.checkPropertyName("contextMap", compact, str);
168 } else {
169 this.checkPropertyNameAbsent("contextMap", compact, str);
159170 }
160171 this.checkPropertyName("contextStack", compact, str);
161172 if (includeSource) {
162173 this.checkPropertyName("source", compact, str);
174 } else {
175 this.checkPropertyNameAbsent("source", compact, str);
163176 }
164177 // check some attrs
165178 this.checkProperty("loggerFqcn", "f.q.c.n", compact, str);
188201 // set up appender
189202 final boolean propertiesAsList = false;
190203 final AbstractJacksonLayout layout = JsonLayout.createLayout(configuration, true, true, propertiesAsList,
191 true, false, false, null, null, null);
204 true, false, false, null, null, null, true);
192205 final ListAppender appender = new ListAppender("List", null, layout, true, false);
193206 appender.start();
194207
227240 // Use [[ and ]] to test header and footer (instead of [ and ])
228241 final boolean propertiesAsList = false;
229242 final AbstractJacksonLayout layout = JsonLayout.createLayout(configuration, true, true, propertiesAsList,
230 true, false, false, "[[", "]]", null);
243 true, false, false, "[[", "]]", null, true);
231244 final ListAppender appender = new ListAppender("List", null, layout, true, false);
232245 appender.start();
233246
268281 public void testLayoutLoggerName() throws Exception {
269282 final boolean propertiesAsList = false;
270283 final AbstractJacksonLayout layout = JsonLayout.createLayout(null, false, false, propertiesAsList,
271 false, true, false, null, null, StandardCharsets.UTF_8);
284 false, true, false, null, null, StandardCharsets.UTF_8, true);
272285 final Log4jLogEvent expected = Log4jLogEvent.newBuilder() //
273286 .setLoggerName("a.B") //
274287 .setLoggerFqcn("f.q.c.n") //
278291 .setTimeMillis(1).build();
279292 final String str = layout.toSerializable(expected);
280293 assertTrue(str, str.contains("\"loggerName\":\"a.B\""));
281 final Log4jLogEvent actual = new Log4jJsonObjectMapper(propertiesAsList).readValue(str, Log4jLogEvent.class);
294 final Log4jLogEvent actual = new Log4jJsonObjectMapper(propertiesAsList, true).readValue(str, Log4jLogEvent.class);
282295 assertEquals(expected.getLoggerName(), actual.getLoggerName());
283296 assertEquals(expected, actual);
284297 }
285298
286299 @Test
287300 public void testLocationOffCompactOffMdcOff() throws Exception {
288 this.testAllFeatures(false, false, false, false, false);
301 this.testAllFeatures(false, false, false, false, false, true);
289302 }
290303
291304 @Test
292305 public void testLocationOnCompactOnMdcOn() throws Exception {
293 this.testAllFeatures(true, true, false, true, false);
306 this.testAllFeatures(true, true, false, true, false, true);
294307 }
295308
296309 @Test
297310 public void testLocationOnCompactOnEventEolOnMdcOn() throws Exception {
298 this.testAllFeatures(true, true, true, true, false);
311 this.testAllFeatures(true, true, true, true, false, true);
299312 }
300313
301314 @Test
302315 public void testLocationOnCompactOnEventEolOnMdcOnMdcAsList() throws Exception {
303 this.testAllFeatures(true, true, true, true, true);
316 this.testAllFeatures(true, true, true, true, true, true);
317 }
318
319 @Test
320 public void testExcludeStacktrace() throws Exception {
321 this.testAllFeatures(false, false, false, false, false, false);
304322 }
305323
306324 private String toPropertySeparator(final boolean compact) {
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.layout;
17
18 import org.apache.logging.log4j.LogManager;
19 import org.apache.logging.log4j.Logger;
20
21 public class Log4j2_1482_CoreTest extends Log4j2_1482_Test {
22
23 @Override
24 protected void log(final int runNumber) {
25 if (runNumber == 2) {
26 // System.out.println("Set a breakpoint here.");
27 }
28 final Logger logger = LogManager.getLogger("auditcsvfile");
29 final int val1 = 9, val2 = 11, val3 = 12;
30 logger.info("Info Message!", val1, val2, val3);
31 logger.info("Info Message!", val1, val2, val3);
32 logger.info("Info Message!", val1, val2, val3);
33 }
34
35 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16
17 package org.apache.logging.log4j.core.layout;
18
19 import java.io.File;
20 import java.io.IOException;
21 import java.nio.charset.Charset;
22 import java.nio.file.Files;
23 import java.nio.file.Path;
24 import java.nio.file.Paths;
25 import java.util.Arrays;
26 import java.util.List;
27
28 import org.apache.logging.log4j.core.LoggerContext;
29 import org.apache.logging.log4j.core.config.Configurator;
30 import org.apache.logging.log4j.junit.CleanFolders;
31 import org.junit.Assert;
32 import org.junit.Rule;
33 import org.junit.Test;
34
35 /**
36 * Tests https://issues.apache.org/jira/browse/LOG4J2-1482
37 */
38 public abstract class Log4j2_1482_Test {
39
40 static final String CONFIG_LOCATION = "log4j2-1482.xml";
41
42 static final String FOLDER = "target/log4j2-1482";
43
44 private static final int LOOP_COUNT = 10;
45
46 static void assertFileContents(final int runNumber) throws IOException {
47 final Path path = Paths.get(FOLDER + "/audit.tmp");
48 final List<String> lines = Files.readAllLines(path, Charset.defaultCharset());
49 int i = 1;
50 final int size = lines.size();
51 for (final String string : lines) {
52 if (string.startsWith(",,")) {
53 final Path folder = Paths.get(FOLDER);
54 final File[] files = folder.toFile().listFiles();
55 Arrays.sort(files);
56 System.out.println("Run " + runNumber + ": " + Arrays.toString(files));
57 Assert.fail(
58 String.format("Run %,d, line %,d of %,d: \"%s\" in %s", runNumber, i++, size, string, lines));
59 }
60 }
61 }
62
63 @Rule
64 public CleanFolders cleanFolders = new CleanFolders(FOLDER);
65
66 protected abstract void log(int runNumber) ;
67
68 private void loopingRun(final int loopCount) throws IOException {
69 for (int i = 1; i <= loopCount; i++) {
70 try (LoggerContext loggerContext = Configurator.initialize(getClass().getName(),
71 CONFIG_LOCATION)) {
72 log(i);
73 }
74 assertFileContents(i);
75 }
76 }
77
78 @Test
79 public void testLoopingRun() throws IOException {
80 loopingRun(LOOP_COUNT);
81 }
82
83 @Test
84 public void testSingleRun() throws IOException {
85 loopingRun(1);
86 }
87
88 }
2424 import org.apache.logging.log4j.Marker;
2525 import org.apache.logging.log4j.MarkerManager;
2626 import org.apache.logging.log4j.core.LogEvent;
27 import org.apache.logging.log4j.core.impl.ContextDataFactory;
2728 import org.apache.logging.log4j.core.impl.Log4jLogEvent;
2829 import org.apache.logging.log4j.core.impl.ThrowableProxy;
2930 import org.apache.logging.log4j.message.SimpleMessage;
7980 return expected;
8081 }
8182
82 static void assertEqualLogEvents(final LogEvent expected, final LogEvent actual, final boolean includeSource,
83 final boolean includeContext) {
83 static void assertEqualLogEvents(final LogEvent expected, final LogEvent actual, final boolean includeSource,
84 final boolean includeContext, final boolean includeStacktrace) {
8485 assertEquals(expected.getClass(), actual.getClass());
86 assertEquals(includeContext ? expected.getContextData() : ContextDataFactory.createContextData(), actual.getContextData());
8587 assertEquals(includeContext ? expected.getContextMap() : Collections.EMPTY_MAP, actual.getContextMap());
8688 assertEquals(expected.getContextStack(), actual.getContextStack());
8789 assertEquals(expected.getLevel(), actual.getLevel());
9496 assertEquals(expected.getThreadName(), actual.getThreadName());
9597 assertNotNull("original should have an exception", expected.getThrown());
9698 assertNull("exception should not be serialized", actual.getThrown());
97 assertEquals(expected.getThrownProxy(), actual.getThrownProxy());
99 if (includeStacktrace) { // TODO should compare the rest of the ThrowableProxy
100 assertEquals(expected.getThrownProxy(), actual.getThrownProxy());
101 }
98102 assertEquals(expected.isEndOfBatch(), actual.isEndOfBatch());
99103 assertEquals(expected.isIncludeLocation(), actual.isIncludeLocation());
100104
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.layout;
17
18 import org.apache.logging.log4j.junit.LoggerContextRule;
19 import org.apache.logging.log4j.test.appender.ListAppender;
20 import org.junit.Assert;
21 import org.junit.Rule;
22 import org.junit.Test;
23
24 /**
25 * See (LOG4J2-905) Ability to disable (date) lookup completely, compatibility issues with other libraries like camel.
26 *
27 * This shows the behavior this user wants to disable.
28 */
29 public class PatternLayoutLookupDateTest {
30
31 @Rule
32 public final LoggerContextRule context = new LoggerContextRule("log4j-list.xml");
33
34 @Test
35 public void testDateLookupInMessage() {
36 final String template = "${date:YYYY-MM-dd}";
37 context.getLogger(PatternLayoutLookupDateTest.class.getName()).info(template);
38 final ListAppender listAppender = context.getListAppender("List");
39 final String string = listAppender.getMessages().get(0);
40 Assert.assertFalse(string, string.contains(template));
41 }
42
43 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.layout;
17
18 import org.apache.logging.log4j.junit.LoggerContextRule;
19 import org.apache.logging.log4j.test.appender.ListAppender;
20 import org.junit.Assert;
21 import org.junit.Rule;
22 import org.junit.Test;
23
24 /**
25 * See (LOG4J2-905) Ability to disable (date) lookup completely, compatibility issues with other libraries like camel.
26 */
27 public class PatternLayoutNoLookupDateTest {
28
29 @Rule
30 public final LoggerContextRule context = new LoggerContextRule("log4j-list-nolookups.xml");
31
32 @Test
33 public void testDateLookupInMessage() {
34 final String template = "${date:YYYY-MM-dd}";
35 context.getLogger(PatternLayoutNoLookupDateTest.class.getName()).info(template);
36 final ListAppender listAppender = context.getListAppender("List");
37 final String string = listAppender.getMessages().get(0);
38 Assert.assertTrue(string, string.contains(template));
39 }
40
41 }
1515 */
1616 package org.apache.logging.log4j.core.layout;
1717
18 import static org.junit.Assert.assertEquals;
19 import static org.junit.Assert.assertFalse;
20 import static org.junit.Assert.assertNotNull;
21 import static org.junit.Assert.assertTrue;
22
1823 import java.nio.ByteBuffer;
1924 import java.nio.charset.Charset;
2025 import java.nio.charset.StandardCharsets;
3035 import org.apache.logging.log4j.core.config.ConfigurationFactory;
3136 import org.apache.logging.log4j.core.impl.Log4jLogEvent;
3237 import org.apache.logging.log4j.core.lookup.MainMapLookup;
38 import org.apache.logging.log4j.junit.ThreadContextRule;
3339 import org.apache.logging.log4j.message.SimpleMessage;
3440 import org.apache.logging.log4j.util.Strings;
35 import org.junit.After;
3641 import org.junit.BeforeClass;
42 import org.junit.Rule;
3743 import org.junit.Test;
38
39 import static org.junit.Assert.*;
4044
4145 /**
4246 *
6973
7074 Logger root = ctx.getRootLogger();
7175
72 @After
73 public void after() {
74 ThreadContext.clearMap();
75 }
76 @Rule
77 public final ThreadContextRule threadContextRule = new ThreadContextRule();
7678
7779 private static class Destination implements ByteBufferDestination {
7880 ByteBuffer byteBuffer = ByteBuffer.wrap(new byte[2048]);
200202 }
201203
202204 @Test
205 public void testMdcPattern0() throws Exception {
206 testMdcPattern("%m : %X", "Hello : {key1=value1, key2=value2}", true);
207 }
208
209 @Test
203210 public void testMdcPattern1() throws Exception {
204211 testMdcPattern("%m : %X", "Hello : {}", false);
205212 }
238245 .setIncludeLocation(true)
239246 .setMessage(new SimpleMessage("entry")).build();
240247 final String result1 = new FauxLogger().formatEvent(event1, layout);
241 final String expectSuffix1 = String.format("====== PatternLayoutTest.testPatternSelector:241 entry ======%n");
248 final String expectSuffix1 = String.format("====== PatternLayoutTest.testPatternSelector:248 entry ======%n");
242249 assertTrue("Unexpected result: " + result1, result1.endsWith(expectSuffix1));
243250 final LogEvent event2 = Log4jLogEvent.newBuilder() //
244251 .setLoggerName(this.getClass().getName()).setLoggerFqcn("org.apache.logging.log4j.core.Logger") //
2929 import org.apache.logging.log4j.core.config.ConfigurationFactory;
3030 import org.apache.logging.log4j.core.net.Facility;
3131 import org.apache.logging.log4j.core.util.KeyValuePair;
32 import org.apache.logging.log4j.junit.ThreadContextRule;
3233 import org.apache.logging.log4j.message.StructuredDataMessage;
3334 import org.apache.logging.log4j.status.StatusLogger;
3435 import org.apache.logging.log4j.test.appender.ListAppender;
3637 import org.junit.AfterClass;
3738 import org.junit.Assert;
3839 import org.junit.BeforeClass;
40 import org.junit.Rule;
3941 import org.junit.Test;
4042
4143 import static org.junit.Assert.*;
5860
5961 static ConfigurationFactory cf = new BasicConfigurationFactory();
6062
63 @Rule
64 public final ThreadContextRule threadContextRule = new ThreadContextRule();
65
6166 @BeforeClass
6267 public static void setupClass() {
63 ThreadContext.clearAll();
6468 StatusLogger.getLogger().setLevel(Level.OFF);
6569 ConfigurationFactory.setConfigurationFactory(cf);
6670 final LoggerContext ctx = LoggerContext.getContext();
7074 @AfterClass
7175 public static void cleanupClass() {
7276 ConfigurationFactory.removeConfigurationFactory(cf);
73 ThreadContext.clearAll();
7477 }
7578
7679 /**
145148 assertTrue("No messages expected, found " + list.size(), list.isEmpty());
146149 } finally {
147150 root.removeAppender(appender);
148 ThreadContext.clearMap();
149
150151 appender.stop();
151152 }
152153 }
207208 assertTrue("No messages expected, found " + list.size(), list.isEmpty());
208209 } finally {
209210 root.removeAppender(appender);
210 ThreadContext.clearMap();
211
212211 appender.stop();
213212 }
214213 }
247246 appender.clear();
248247 } finally {
249248 root.removeAppender(appender);
250 ThreadContext.clearMap();
251
252249 appender.stop();
253250 }
254251 }
289286 appender.clear();
290287 } finally {
291288 root.removeAppender(appender);
292 ThreadContext.clearMap();
293
294289 appender.stop();
295290 }
296291 }
338333 appender.clear();
339334 } finally {
340335 root.removeAppender(appender);
341 ThreadContext.clearMap();
342
343336 appender.stop();
344337 }
345338 }
348341 public void testDiscardEmptyLoggerFields() {
349342 final String mdcId = "RequestContext";
350343
351 final List<String> expectedToContain = Arrays.asList(
344 Arrays.asList(
352345 "[BAZ@32473 baz=\"org.apache.logging.log4j.core.layout.Rfc5424LayoutTest.testLoggerFields\"]" +
353346 "[RequestContext@3692 bar=\"org.apache.logging.log4j.core.layout.Rfc5424LayoutTest.testLoggerFields\"]"
354347 );
386379 appender.clear();
387380 } finally {
388381 root.removeAppender(appender);
389 ThreadContext.clearMap();
390
391382 appender.stop();
392383 }
393384 }
420411 appender.clear();
421412 } finally {
422413 root.removeAppender(appender);
423 ThreadContext.clearMap();
424
425414 appender.stop();
426415 }
427416 }
3434 import org.apache.logging.log4j.core.LoggerContext;
3535 import org.apache.logging.log4j.core.config.ConfigurationFactory;
3636 import org.apache.logging.log4j.core.impl.Log4jLogEvent;
37 import org.apache.logging.log4j.junit.ThreadContextRule;
3738 import org.apache.logging.log4j.message.SimpleMessage;
3839 import org.apache.logging.log4j.test.appender.ListAppender;
3940 import org.junit.AfterClass;
4041 import org.junit.BeforeClass;
42 import org.junit.Rule;
4143 import org.junit.Test;
4244
4345 import static org.junit.Assert.*;
5254
5355 static ConfigurationFactory cf = new BasicConfigurationFactory();
5456
57 @Rule
58 public final ThreadContextRule threadContextRule = new ThreadContextRule();
59
5560 @BeforeClass
5661 public static void setupClass() {
57 ThreadContext.clearAll();
5862 ConfigurationFactory.setConfigurationFactory(cf);
5963 final LoggerContext ctx = LoggerContext.getContext();
6064 ctx.reconfigure();
6367 @AfterClass
6468 public static void cleanupClass() {
6569 ConfigurationFactory.removeConfigurationFactory(cf);
66 ThreadContext.clearAll();
6770 }
6871
6972 private static final String body =
2727 import org.apache.logging.log4j.core.LoggerContext;
2828 import org.apache.logging.log4j.core.config.ConfigurationFactory;
2929 import org.apache.logging.log4j.core.net.Facility;
30 import org.apache.logging.log4j.junit.ThreadContextRule;
3031 import org.apache.logging.log4j.message.StructuredDataMessage;
3132 import org.apache.logging.log4j.test.appender.ListAppender;
3233 import org.junit.AfterClass;
3334 import org.junit.BeforeClass;
35 import org.junit.Rule;
3436 import org.junit.Test;
3537
3638 import static org.junit.Assert.*;
5153
5254 static ConfigurationFactory cf = new BasicConfigurationFactory();
5355
56 @Rule
57 public final ThreadContextRule threadContextRule = new ThreadContextRule();
58
5459 @BeforeClass
5560 public static void setupClass() {
56 ThreadContext.clearAll();
5761 ConfigurationFactory.setConfigurationFactory(cf);
5862 final LoggerContext ctx = LoggerContext.getContext();
5963 ctx.reconfigure();
6266 @AfterClass
6367 public static void cleanupClass() {
6468 ConfigurationFactory.removeConfigurationFactory(cf);
65 ThreadContext.clearAll();
6669 }
6770
6871
105108 msg.put("Amount", "200.00");
106109 root.info(MarkerManager.getMarker("EVENT"), msg);
107110
108 ThreadContext.clearMap();
109
110111 appender.stop();
111112
112113 final List<String> list = appender.getMessages();
3131 import org.apache.logging.log4j.core.config.ConfigurationFactory;
3232 import org.apache.logging.log4j.core.impl.Log4jLogEvent;
3333 import org.apache.logging.log4j.core.jackson.Log4jXmlObjectMapper;
34 import org.apache.logging.log4j.junit.ThreadContextRule;
3435 import org.apache.logging.log4j.message.SimpleMessage;
3536 import org.apache.logging.log4j.spi.AbstractLogger;
3637 import org.apache.logging.log4j.test.appender.ListAppender;
3738 import org.junit.AfterClass;
3839 import org.junit.Assert;
3940 import org.junit.BeforeClass;
41 import org.junit.Rule;
4042 import org.junit.Test;
4143
4244 import com.fasterxml.jackson.core.JsonParseException;
5254 static ConfigurationFactory cf = new BasicConfigurationFactory();
5355 private static final String markerTag = "<Marker name=\"EVENT\"/>";
5456
57 @Rule
58 public final ThreadContextRule threadContextRule = new ThreadContextRule();
59
5560 @AfterClass
5661 public static void cleanupClass() {
5762 ConfigurationFactory.removeConfigurationFactory(cf);
58 ThreadContext.clearAll();
5963 }
6064
6165 @BeforeClass
6266 public static void setupClass() {
63 ThreadContext.clearAll();
6467 ConfigurationFactory.setConfigurationFactory(cf);
6568 final LoggerContext ctx = LoggerContext.getContext();
6669 ctx.reconfigure();
106109 Assert.assertTrue(str, endPos >= 0);
107110 }
108111
112 private void checkElementNameAbsent(final String name, final boolean compact, final String str) {
113 Assert.assertFalse(str.contains("<" + name));
114 }
115
109116 /**
110117 * @param includeSource TODO
111118 * @param compact
114121 * @throws JsonParseException
115122 * @throws JsonMappingException
116123 */
117 private void testAllFeatures(final boolean includeSource, final boolean compact, final boolean includeContext) throws IOException,
124 private void testAllFeatures(final boolean includeSource, final boolean compact, final boolean includeContext, final boolean includeStacktrace) throws IOException,
118125 JsonParseException, JsonMappingException {
119126 final Log4jLogEvent expected = LogEventFixtures.createLogEvent();
120 final XmlLayout layout = XmlLayout.createLayout(includeSource, includeContext, false, compact, StandardCharsets.UTF_8);
127 final XmlLayout layout = XmlLayout.createLayout(includeSource, includeContext, false, compact, StandardCharsets.UTF_8, includeStacktrace);
121128 final String str = layout.toSerializable(expected);
122129 // System.out.println(str);
123130 assertEquals(str, !compact, str.contains("\n"));
124131 assertEquals(str, includeSource, str.contains("Source"));
125132 assertEquals(str, includeContext, str.contains("ContextMap"));
126133 final Log4jLogEvent actual = new Log4jXmlObjectMapper().readValue(str, Log4jLogEvent.class);
127 LogEventFixtures.assertEqualLogEvents(expected, actual, includeSource, includeContext);
134 LogEventFixtures.assertEqualLogEvents(expected, actual, includeSource, includeContext, includeStacktrace);
128135 if (includeContext) {
129136 this.checkElement("MDC.A", "A_Value", compact, str);
130137 this.checkElement("MDC.B", "B_Value", compact, str);
137144 assertTrue(str, str.contains("loggerName=\"a.B\""));
138145 // make sure short names are used
139146 assertTrue(str, str.contains("<Event "));
140 assertTrue(str, str.contains("class="));
141 assertTrue(str, str.contains("method="));
142 assertTrue(str, str.contains("file="));
143 assertTrue(str, str.contains("line="));
147 if (includeStacktrace) {
148 assertTrue(str, str.contains("class="));
149 assertTrue(str, str.contains("method="));
150 assertTrue(str, str.contains("file="));
151 assertTrue(str, str.contains("line="));
152 }
144153 //
145154 // make sure the names we want are used
146155 this.checkAttributeName("timeMillis", compact, str);
152161 this.checkElementName("Parents", compact, str, false, true);
153162 this.checkElementName("Message", compact, str, false, true);
154163 this.checkElementName("Thrown", compact, str, true, true);
155 this.checkElementName("Cause", compact, str, true, true);
156 this.checkAttributeName("class", compact, str);
157 this.checkAttributeName("method", compact, str);
158 this.checkAttributeName("file", compact, str);
159 this.checkAttributeName("line", compact, str);
160 this.checkAttributeName("exact", compact, str);
161 this.checkAttributeName("location", compact, str);
162 this.checkAttributeName("version", compact, str);
164 this.checkElementName("Cause", compact, str, true, includeStacktrace);
163165 this.checkAttributeName("commonElementCount", compact, str);
164166 this.checkAttributeName("message", compact, str);
165167 this.checkAttributeName("localizedMessage", compact, str);
166 this.checkElementName("ExtendedStackTrace", compact, str, false, true);
168 if (includeStacktrace) {
169 this.checkElementName("ExtendedStackTrace", compact, str, false, true);
170 this.checkAttributeName("class", compact, str);
171 this.checkAttributeName("method", compact, str);
172 this.checkAttributeName("file", compact, str);
173 this.checkAttributeName("line", compact, str);
174 this.checkAttributeName("exact", compact, str);
175 this.checkAttributeName("location", compact, str);
176 this.checkAttributeName("version", compact, str);
177 } else {
178 this.checkElementNameAbsent("ExtendedStackTrace", compact, str);
179 }
167180 this.checkElementName("Suppressed", compact, str, false, true);
168181 this.checkAttributeName("loggerFqcn", compact, str);
169182 this.checkAttributeName("endOfBatch", compact, str);
170183 if (includeContext) {
171184 this.checkElementName("ContextMap", compact, str, false, true);
185 } else {
186 this.checkElementNameAbsent("ContextMap", compact, str);
172187 }
173188 this.checkElementName("ContextStack", compact, str, false, true);
174189 if (includeSource) {
175190 this.checkElementName("Source", compact, str, true, false);
191 } else {
192 this.checkElementNameAbsent("Source", compact, str);
176193 }
177194 // check some attrs
178195 this.checkAttribute("loggerFqcn", "f.q.c.n", compact, str);
201218 this.rootLogger.removeAppender(appender);
202219 }
203220 // set up appender
204 final XmlLayout layout = XmlLayout.createLayout(true, true, true, false, null);
221 final XmlLayout layout = XmlLayout.createLayout(true, true, true, false, null, true);
205222 final ListAppender appender = new ListAppender("List", null, layout, true, false);
206223 appender.start();
207224
250267
251268 @Test
252269 public void testLayoutLoggerName() {
253 final XmlLayout layout = XmlLayout.createLayout(false, true, true, false, null);
270 final XmlLayout layout = XmlLayout.createLayout(false, true, true, false, null, true);
254271 final Log4jLogEvent event = Log4jLogEvent.newBuilder() //
255272 .setLoggerName("a.B") //
256273 .setLoggerFqcn("f.q.c.n") //
264281
265282 @Test
266283 public void testLocationOffCompactOffMdcOff() throws Exception {
267 this.testAllFeatures(false, false, false);
284 this.testAllFeatures(false, false, false, true);
268285 }
269286
270287 @Test
271288 public void testLocationOnCompactOnMdcOn() throws Exception {
272 this.testAllFeatures(true, true, true);
289 this.testAllFeatures(true, true, true, true);
290 }
291
292 @Test
293 public void testExcludeStacktrace() throws Exception {
294 this.testAllFeatures(false, false, false, false);
273295 }
274296 }
1616 package org.apache.logging.log4j.core.layout;
1717
1818 import static org.junit.Assert.assertEquals;
19 import static org.junit.Assert.assertFalse;
1920 import static org.junit.Assert.assertNull;
2021 import static org.junit.Assert.assertTrue;
2122
102103 assertTrue(str, str.contains(name + propSep));
103104 }
104105
106 private void checkPropertyNameAbsent(final String name, final boolean compact, final String str, final boolean isValue) {
107 final String propSep = this.toPropertySeparator(compact, isValue);
108 assertFalse(str, str.contains(name + propSep));
109 }
110
105111 private void testAllFeatures(final boolean includeSource, final boolean compact, final boolean eventEol,
106 final boolean includeContext, final boolean contextMapAslist) throws Exception {
112 final boolean includeContext, final boolean contextMapAslist, final boolean includeStacktrace) throws Exception {
107113 final Log4jLogEvent expected = LogEventFixtures.createLogEvent();
108114 final AbstractJacksonLayout layout = YamlLayout.createLayout(null, includeSource, includeContext, null, null,
109 StandardCharsets.UTF_8);
115 StandardCharsets.UTF_8, includeStacktrace);
110116 final String str = layout.toSerializable(expected);
111117 // System.out.println(str);
112118 // Just check for \n since \r might or might not be there.
113119 assertEquals(str, !compact || eventEol, str.contains("\n"));
114120 assertEquals(str, includeSource, str.contains("source"));
115121 assertEquals(str, includeContext, str.contains("contextMap"));
116 final Log4jLogEvent actual = new Log4jYamlObjectMapper(contextMapAslist).readValue(str, Log4jLogEvent.class);
117 LogEventFixtures.assertEqualLogEvents(expected, actual, includeSource, includeContext);
122 final Log4jLogEvent actual = new Log4jYamlObjectMapper(contextMapAslist, includeStacktrace).readValue(str, Log4jLogEvent.class);
123 LogEventFixtures.assertEqualLogEvents(expected, actual, includeSource, includeContext, includeStacktrace);
118124 if (includeContext) {
119125 this.checkMapEntry("MDC.A", "A_Value", compact, str);
120126 this.checkMapEntry("MDC.B", "B_Value", compact, str);
132138 this.checkPropertyName("message", compact, str, true);
133139 this.checkPropertyName("thrown", compact, str, false);
134140 this.checkPropertyName("cause", compact, str, false);
135 this.checkPropertyName("class", compact, str, true);
136 this.checkPropertyName("method", compact, str, true);
137 this.checkPropertyName("file", compact, str, true);
138 this.checkPropertyName("line", compact, str, true);
139 this.checkPropertyName("exact", compact, str, true);
140 this.checkPropertyName("location", compact, str, true);
141 this.checkPropertyName("version", compact, str, true);
142141 this.checkPropertyName("commonElementCount", compact, str, true);
143142 this.checkPropertyName("localizedMessage", compact, str, true);
144 this.checkPropertyName("extendedStackTrace", compact, str, false);
143 if (includeStacktrace) {
144 this.checkPropertyName("extendedStackTrace", compact, str, false);
145 this.checkPropertyName("class", compact, str, true);
146 this.checkPropertyName("method", compact, str, true);
147 this.checkPropertyName("file", compact, str, true);
148 this.checkPropertyName("line", compact, str, true);
149 this.checkPropertyName("exact", compact, str, true);
150 this.checkPropertyName("location", compact, str, true);
151 this.checkPropertyName("version", compact, str, true);
152 } else {
153 this.checkPropertyNameAbsent("extendedStackTrace", compact, str, false);
154 }
145155 this.checkPropertyName("suppressed", compact, str, false);
146156 this.checkPropertyName("loggerFqcn", compact, str, true);
147157 this.checkPropertyName("endOfBatch", compact, str, true);
148158 if (includeContext) {
149159 this.checkPropertyName("contextMap", compact, str, false);
160 } else {
161 this.checkPropertyNameAbsent("contextMap", compact, str, false);
150162 }
151163 this.checkPropertyName("contextStack", compact, str, false);
152164 if (includeSource) {
153165 this.checkPropertyName("source", compact, str, false);
166 } else {
167 this.checkPropertyNameAbsent("source", compact, str, false);
154168 }
155169 // check some attrs
156170 this.checkProperty("loggerFqcn", "f.q.c.n", compact, str, true);
177191 }
178192 final Configuration configuration = rootLogger.getContext().getConfiguration();
179193 // set up appender
180 final AbstractJacksonLayout layout = YamlLayout.createLayout(configuration, true, true, null, null, null);
194 final AbstractJacksonLayout layout = YamlLayout.createLayout(configuration, true, true, null, null, null, true);
181195 final ListAppender appender = new ListAppender("List", null, layout, true, false);
182196 appender.start();
183197
213227 final Configuration configuration = rootLogger.getContext().getConfiguration();
214228 // set up appender
215229 // Use [[ and ]] to test header and footer (instead of [ and ])
216 final AbstractJacksonLayout layout = YamlLayout.createLayout(configuration, true, true, "[[", "]]", null);
230 final AbstractJacksonLayout layout = YamlLayout.createLayout(configuration, true, true, "[[", "]]", null, true);
217231 final ListAppender appender = new ListAppender("List", null, layout, true, false);
218232 appender.start();
219233
252266 @Test
253267 public void testLayoutLoggerName() throws Exception {
254268 final AbstractJacksonLayout layout = YamlLayout.createLayout(null, false, false, null, null,
255 StandardCharsets.UTF_8);
269 StandardCharsets.UTF_8, true);
256270 final Log4jLogEvent expected = Log4jLogEvent.newBuilder() //
257271 .setLoggerName("a.B") //
258272 .setLoggerFqcn("f.q.c.n") //
262276 .setTimeMillis(1).build();
263277 final String str = layout.toSerializable(expected);
264278 assertTrue(str, str.contains("loggerName: \"a.B\""));
265 final Log4jLogEvent actual = new Log4jYamlObjectMapper(false).readValue(str, Log4jLogEvent.class);
279 final Log4jLogEvent actual = new Log4jYamlObjectMapper(false, true).readValue(str, Log4jLogEvent.class);
266280 assertEquals(expected.getLoggerName(), actual.getLoggerName());
267281 assertEquals(expected, actual);
268282 }
269283
270284 @Test
271285 public void testLocationOffCompactOffMdcOff() throws Exception {
272 this.testAllFeatures(false, false, false, false, false);
286 this.testAllFeatures(false, false, false, false, false, true);
273287 }
274288
275289 @Test
276290 public void testLocationOnCompactOffEventEolOffMdcOn() throws Exception {
277 this.testAllFeatures(true, false, false, true, false);
291 this.testAllFeatures(true, false, false, true, false, true);
292 }
293
294 @Test
295 public void testExcludeStacktrace() throws Exception {
296 this.testAllFeatures(false, false, false, false, false, false);
278297 }
279298
280299 private String toPropertySeparator(final boolean compact, final boolean value) {
2020 import org.apache.logging.log4j.core.config.Configurator;
2121
2222 /**
23 * Tests {@link org.apache.logging.log4j.core.lookup.MainMapLookup#MAIN_SINGLETON} from the command line, not a real JUnit
24 * test.
23 * Tests {@link org.apache.logging.log4j.core.lookup.MainMapLookup#MAIN_SINGLETON} from the command line, not a real
24 * JUnit test.
2525 *
2626 * From an IDE or CLI: --file foo.txt
2727 *
3131
3232 public static void main(final String[] args) {
3333 MainMapLookup.setMainArguments(args);
34 final LoggerContext ctx = Configurator.initialize(MainInputArgumentsLookupTest.class.getName(),
35 "target/test-classes/log4j-lookup-main.xml");
36 try {
34 try (final LoggerContext ctx = Configurator.initialize(MainInputArgumentsLookupTest.class.getName(),
35 "target/test-classes/log4j-lookup-main.xml")) {
3736 LogManager.getLogger().error("this is an error message");
38 } finally {
39 Configurator.shutdown(ctx);
4037 }
4138 }
4239
3131 final String[] args = null;
3232 for (final Map.Entry<Thread, StackTraceElement[]> entry : allStackTraces.entrySet()) {
3333 final StackTraceElement[] stackTraceElements = entry.getValue();
34 final Thread thread = entry.getKey();
34 entry.getKey();
3535 // Can't use the thread name to look for "main" since anyone can set it.
3636 // Can't use thread ID since it can be any positive value, and is likely vender dependent. Oracle seems to
3737 // use 1.
2626 @Test
2727 public void testLookup() {
2828 final StrLookup lookup = new ResourceBundleLookup();
29 final String value = lookup.lookup("org.apache.logging.log4j.core.lookup.resource-bundle_en:KeyA");
29 lookup.lookup("org.apache.logging.log4j.core.lookup.resource-bundle_en:KeyA");
3030 Assert.assertEquals("ValueA", lookup.lookup("org.apache.logging.log4j.core.lookup.resource-bundle:KeyA"));
3131 }
3232
3333 @Test
3434 public void testLookupWithLocale() {
3535 final StrLookup lookup = new ResourceBundleLookup();
36 final String value = lookup.lookup("org.apache.logging.log4j.core.lookup.resource-bundle:KeyA");
36 lookup.lookup("org.apache.logging.log4j.core.lookup.resource-bundle:KeyA");
3737 Assert.assertEquals("ValueA", lookup.lookup("org.apache.logging.log4j.core.lookup.resource-bundle:KeyA"));
3838 }
3939
2424
2525 import org.apache.logging.log4j.Logger;
2626 import org.apache.logging.log4j.core.appender.AppenderLoggingException;
27 import org.apache.logging.log4j.core.util.Constants;
2827 import org.apache.logging.log4j.junit.LoggerContextRule;
2928 import org.apache.logging.log4j.test.AvailablePortFinder;
29 import org.apache.logging.log4j.util.Strings;
3030 import org.junit.ClassRule;
3131 import org.junit.Ignore;
3232 import org.junit.Test;
3939
4040 private static final String CONFIG = "log4j-socket.xml";
4141
42 private static final String SHUTDOWN = "Shutdown" + Constants.LINE_SEPARATOR +
43 "................................................................" + Constants.LINE_SEPARATOR +
44 "................................................................" + Constants.LINE_SEPARATOR +
45 "................................................................" + Constants.LINE_SEPARATOR +
46 "................................................................" + Constants.LINE_SEPARATOR;
42 private static final String SHUTDOWN = "Shutdown" + Strings.LINE_SEPARATOR +
43 "................................................................" + Strings.LINE_SEPARATOR +
44 "................................................................" + Strings.LINE_SEPARATOR +
45 "................................................................" + Strings.LINE_SEPARATOR +
46 "................................................................" + Strings.LINE_SEPARATOR;
4747
4848 @ClassRule
4949 public static LoggerContextRule context = new LoggerContextRule(CONFIG);
1818 import java.net.DatagramPacket;
1919 import java.net.DatagramSocket;
2020 import java.net.SocketException;
21
22 import org.apache.logging.log4j.core.util.Throwables;
2123
2224 public class MockUdpSyslogServer extends MockSyslogServer {
2325 private final DatagramSocket socket;
4749 final String str = new String(packet.getData(), 0, packet.getLength());
4850 messageList.add(str);
4951 }
50 } catch (final Exception ex) {
52 } catch (final Exception e) {
5153 if (!shutdown) {
52 throw new RuntimeException(ex);
54 Throwables.rethrow(e);
5355 }
5456 }
5557 }
7777 }
7878
7979 protected Layout<String> createJsonLayout() {
80 return JsonLayout.createLayout(null, true, true, false, false, false, false, null, null, null);
80 return JsonLayout.createLayout(null, true, true, false, false, false, false, null, null, null, true);
8181 }
8282
8383 protected abstract Layout<? extends Serializable> createLayout();
8787 }
8888
8989 protected Layout<String> createXmlLayout() {
90 return XmlLayout.createLayout(true, true, false, false, null);
90 return XmlLayout.createLayout(true, true, false, false, null, true);
9191 }
9292
9393 @After
205205
206206 protected SocketAppender createSocketAppender(final Filter socketFilter,
207207 final Layout<? extends Serializable> socketLayout) {
208 return SocketAppender.createAppender("localhost", this.port, this.protocol, null, 0, -1, true,
209 "Test", true, false, socketLayout, socketFilter, false, null);
208 // @formatter:off
209 return SocketAppender.newBuilder()
210 .withProtocol(this.protocol)
211 .withHost("localhost")
212 .withPort(this.port)
213 .withReconnectDelayMillis(-1)
214 .withName("test")
215 .withImmediateFlush(true)
216 .withImmediateFail(false)
217 .withIgnoreExceptions(false)
218 .withLayout(socketLayout)
219 .withFilter(socketFilter)
220 .build();
221 // @formatter:on
210222 }
211223
212224 }
3737
3838 private static TcpSocketServer<InputStream> server;
3939
40 private static SslConfiguration sslConfig;
40 private static SslConfiguration sslConfiguration;
4141
4242 private static void initServerSocketFactory() throws StoreConfigurationException {
4343 final KeyStoreConfiguration ksc = new KeyStoreConfiguration(TestConstants.KEYSTORE_FILE,
4444 TestConstants.KEYSTORE_PWD, TestConstants.KEYSTORE_TYPE, null);
4545 final TrustStoreConfiguration tsc = new TrustStoreConfiguration(TestConstants.TRUSTSTORE_FILE,
4646 TestConstants.TRUSTSTORE_PWD, null, null);
47 sslConfig = SslConfiguration.createSSLConfiguration(null, ksc, tsc);
47 sslConfiguration = SslConfiguration.createSSLConfiguration(null, ksc, tsc);
4848 }
4949
5050 @Override
5151 protected SocketAppender createSocketAppender(final Filter socketFilter,
5252 final Layout<? extends Serializable> socketLayout) {
53 return SocketAppender.createAppender("localhost", this.port, this.protocol, sslConfig, 0, -1, true,
54 "Test", true, false, socketLayout, socketFilter, false, null);
53 // @formatter:off
54 return SocketAppender.newBuilder()
55 .withProtocol(this.protocol)
56 .withHost("localhost")
57 .withPort(this.port)
58 .withReconnectDelayMillis(-1)
59 .withName("test")
60 .withImmediateFlush(true)
61 .withImmediateFail(false)
62 .withIgnoreExceptions(false)
63 .withLayout(socketLayout)
64 .withFilter(socketFilter)
65 .withSslConfiguration(sslConfiguration)
66 .build();
67 // @formatter:on
5568 }
5669
5770 @BeforeClass
6073 initServerSocketFactory();
6174 // Use a large buffer just to test the code, the UDP test uses a tiny buffer
6275 server = new SecureTcpSocketServer<>(PORT_NUM, new XmlInputStreamLogEventBridge(1024 * 100,
63 Charset.defaultCharset()), sslConfig);
76 Charset.defaultCharset()), sslConfiguration);
6477 thread = server.startNewThread();
6578 }
6679
4848 @Test(expected = StoreConfigurationException.class)
4949 public void wrongPassword() throws StoreConfigurationException {
5050 final KeyStoreConfiguration ksc = new KeyStoreConfiguration(TestConstants.KEYSTORE_FILE, "wrongPassword!", null, null);
51 final KeyStore ks = ksc.getKeyStore();
51 ksc.getKeyStore();
5252 }
5353 }
4646 @Test(expected = StoreConfigurationException.class)
4747 public void wrongPassword() throws StoreConfigurationException {
4848 final TrustStoreConfiguration ksc = new TrustStoreConfiguration(TestConstants.TRUSTSTORE_FILE, "wrongPassword!", null, null);
49 final KeyStore ks = ksc.getKeyStore();
49 ksc.getKeyStore();
5050 Assert.assertTrue(false);
5151 }
5252 }
2525 * Requires that "mvn package" has been previously run, otherwise test fails its JUnit {@link Assume}.
2626 * </p>
2727 * <p>
28 * For example, on Windows: "mvn clean package -DskipTests & mvn test"
28 * For example, on Windows: {@code mvn clean package -DskipTests & mvn test}
29 * </p>
30 * <p>
31 * To only test this class: {@code mvn -pl log4j-core -DskipTests clean package & mvn -pl log4j-core
32 * -Dtest=EquinoxLoadCoreBundleTest test}
2933 * </p>
3034 */
3135 @Ignore
2727 * <p>
2828 * For example, on Windows: "mvn clean package -DskipTests & mvn test"
2929 * </p>
30 * <p>
31 * To only test this class: {@code mvn -pl log4j-core -DskipTests clean package & mvn -pl log4j-core
32 * -Dtest=FelixLoadCoreBundleTest test}
33 * </p>
3034 */
3135 @Ignore
3236 public class FelixLoadCoreBundleTest extends AbstractFelixLoadBundleTest {
190190 }
191191
192192 @Test
193 public void testFormatDateStringBuilderIso8601WithPeriod() {
194 final String[] pattern = {FixedDateFormat.FixedFormat.ISO8601_PERIOD.name()};
195 final DatePatternConverter converter = DatePatternConverter.newInstance(pattern);
196 final StringBuilder sb = new StringBuilder();
197 converter.format(date(2001, 1, 1), sb);
198
199 final String expected = "2001-02-01T14:15:16.123";
200 assertEquals(expected, sb.toString());
201 }
202
203 @Test
204 public void testFormatDateStringBuilderIso8601BasicWithPeriod() {
205 final String[] pattern = {FixedDateFormat.FixedFormat.ISO8601_BASIC_PERIOD.name()};
206 final DatePatternConverter converter = DatePatternConverter.newInstance(pattern);
207 final StringBuilder sb = new StringBuilder();
208 converter.format(date(2001, 1, 1), sb);
209
210 final String expected = "20010201T141516.123";
211 assertEquals(expected, sb.toString());
212 }
213
214 @Test
193215 public void testFormatDateStringBuilderOriginalPattern() {
194216 final String[] pattern = {"yyyy/MM/dd HH-mm-ss.SSS"};
195217 final DatePatternConverter converter = DatePatternConverter.newInstance(pattern);
0 package org.apache.logging.log4j.core.pattern;/*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16
17 import org.apache.logging.log4j.Level;
18 import org.apache.logging.log4j.core.LogEvent;
19 import org.apache.logging.log4j.core.impl.Log4jLogEvent;
20 import org.apache.logging.log4j.message.SimpleMessage;
21 import org.junit.Test;
22
23 import static org.junit.Assert.*;
24
25 /**
26 * Tests the HighlightConverter.
27 */
28 public class HighlightConverterTest {
29
30 @Test
31 public void testAnsiEmpty() {
32 final String[] options = {"", PatternParser.NO_CONSOLE_NO_ANSI + "=false"};
33 final HighlightConverter converter = HighlightConverter.newInstance(null, options);
34
35 final LogEvent event = Log4jLogEvent.newBuilder().setLevel(Level.INFO).setLoggerName("a.b.c").setMessage(
36 new SimpleMessage("message in a bottle")).build();
37 final StringBuilder buffer = new StringBuilder();
38 converter.format(event, buffer);
39 assertEquals("", buffer.toString());
40 }
41
42 @Test
43 public void testAnsiNonEmpty() {
44 final String[] options = {"%-5level: %msg", PatternParser.NO_CONSOLE_NO_ANSI + "=false"};
45 final HighlightConverter converter = HighlightConverter.newInstance(null, options);
46
47 final LogEvent event = Log4jLogEvent.newBuilder().setLevel(Level.INFO).setLoggerName("a.b.c").setMessage(
48 new SimpleMessage("message in a bottle")).build();
49 final StringBuilder buffer = new StringBuilder();
50 converter.format(event, buffer);
51 assertEquals("\u001B[32mINFO : message in a bottle\u001B[m", buffer.toString());
52 }
53
54 @Test
55 public void testNoAnsiEmpty() {
56 final String[] options = {"", PatternParser.NO_CONSOLE_NO_ANSI + "=true"};
57 final HighlightConverter converter = HighlightConverter.newInstance(null, options);
58
59 final LogEvent event = Log4jLogEvent.newBuilder().setLevel(Level.INFO).setLoggerName("a.b.c").setMessage(
60 new SimpleMessage("message in a bottle")).build();
61 final StringBuilder buffer = new StringBuilder();
62 converter.format(event, buffer);
63 assertEquals("", buffer.toString());
64 }
65
66 @Test
67 public void testNoAnsiNonEmpty() {
68 final String[] options = {"%-5level: %msg", PatternParser.NO_CONSOLE_NO_ANSI + "=true"};
69 final HighlightConverter converter = HighlightConverter.newInstance(null, options);
70
71 final LogEvent event = Log4jLogEvent.newBuilder().setLevel(Level.INFO).setLoggerName("a.b.c").setMessage(
72 new SimpleMessage("message in a bottle")).build();
73 final StringBuilder buffer = new StringBuilder();
74 converter.format(event, buffer);
75 assertEquals("INFO : message in a bottle", buffer.toString());
76 }
77 }
1515 */
1616 package org.apache.logging.log4j.core.pattern;
1717
18 import static org.junit.Assert.assertEquals;
19 import static org.junit.Assert.assertTrue;
20
1821 import org.apache.logging.log4j.Level;
1922 import org.apache.logging.log4j.ThreadContext;
2023 import org.apache.logging.log4j.core.LogEvent;
2124 import org.apache.logging.log4j.core.impl.Log4jLogEvent;
25 import org.apache.logging.log4j.junit.ThreadContextMapRule;
2226 import org.apache.logging.log4j.message.Message;
2327 import org.apache.logging.log4j.message.SimpleMessage;
28 import org.junit.Before;
29 import org.junit.Rule;
2430 import org.junit.Test;
25
26 import static org.junit.Assert.*;
2731
2832 /**
2933 *
3034 */
3135 public class MdcPatternConverterTest {
3236
33 @Test
34 public void testConverter() {
37 @Rule
38 public final ThreadContextMapRule threadContextRule = new ThreadContextMapRule();
3539
36 final Message msg = new SimpleMessage("Hello");
40 @Before
41 public void setup() {
3742 ThreadContext.put("subject", "I");
3843 ThreadContext.put("verb", "love");
3944 ThreadContext.put("object", "Log4j");
45 }
46
47 @Test
48 public void testConverter() {
49 final Message msg = new SimpleMessage("Hello");
4050 final MdcPatternConverter converter = MdcPatternConverter.newInstance(null);
4151 final LogEvent event = Log4jLogEvent.newBuilder() //
4252 .setLoggerName("MyLogger") //
5262
5363 @Test
5464 public void testConverterWithKey() {
55
5665 final Message msg = new SimpleMessage("Hello");
5766 final String [] options = new String[] {"object"};
58 ThreadContext.put("subject", "I");
59 ThreadContext.put("verb", "love");
60 ThreadContext.put("object", "Log4j");
6167 final MdcPatternConverter converter = MdcPatternConverter.newInstance(options);
6268 final LogEvent event = Log4jLogEvent.newBuilder() //
6369 .setLoggerName("MyLogger") //
7379
7480 @Test
7581 public void testConverterWithKeys() {
76
7782 final Message msg = new SimpleMessage("Hello");
7883 final String [] options = new String[] {"object, subject"};
79 ThreadContext.put("subject", "I");
80 ThreadContext.put("verb", "love");
81 ThreadContext.put("object", "Log4j");
8284 final MdcPatternConverter converter = MdcPatternConverter.newInstance(options);
8385 final LogEvent event = Log4jLogEvent.newBuilder() //
8486 .setLoggerName("MyLogger") //
9193 final String expected = "{object=Log4j, subject=I}";
9294 assertEquals(expected, str);
9395 }
96
9497 }
9598
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.pattern;
17
18 import java.util.List;
19
20 import org.apache.logging.log4j.Logger;
21 import org.apache.logging.log4j.junit.LoggerContextRule;
22 import org.apache.logging.log4j.test.appender.ListAppender;
23 import org.apache.logging.log4j.util.Strings;
24 import org.junit.Before;
25 import org.junit.Rule;
26 import org.junit.Test;
27
28 import static org.junit.Assert.*;
29
30 /**
31 *
32 */
33 public class MessageJansiConverterTest {
34
35 private static final String EXPECTED = "\u001B[31;1mWarning!\u001B[m Pants on \u001B[31mfire!\u001B[m"
36 + Strings.LINE_SEPARATOR;
37
38 @Rule
39 public LoggerContextRule init = new LoggerContextRule("log4j-message-ansi.xml");
40
41 private Logger logger;
42 private ListAppender app;
43
44 @Before
45 public void setUp() throws Exception {
46 this.logger = this.init.getLogger("LoggerTest");
47 this.app = this.init.getListAppender("List").clear();
48 }
49
50 @Test
51 public void testReplacement() {
52 // See org.fusesource.jansi.AnsiRenderer
53 logger.error("@|red,bold Warning!|@ Pants on @|red fire!|@");
54
55 final List<String> msgs = app.getMessages();
56 assertNotNull(msgs);
57 assertEquals("Incorrect number of messages. Should be 1 is " + msgs.size(), 1, msgs.size());
58 assertTrue("Replacement failed - expected ending " + EXPECTED + ", actual " + msgs.get(0),
59 msgs.get(0).endsWith(EXPECTED));
60 }
61 }
1515 */
1616 package org.apache.logging.log4j.core.pattern;
1717
18 import static org.junit.Assert.assertEquals;
19
1820 import org.apache.logging.log4j.Level;
1921 import org.apache.logging.log4j.core.LogEvent;
2022 import org.apache.logging.log4j.core.config.Configuration;
2123 import org.apache.logging.log4j.core.config.DefaultConfiguration;
2224 import org.apache.logging.log4j.core.impl.Log4jLogEvent;
2325 import org.apache.logging.log4j.message.Message;
26 import org.apache.logging.log4j.message.ParameterizedMessage;
2427 import org.apache.logging.log4j.message.SimpleMessage;
2528 import org.junit.Test;
26
27 import static org.junit.Assert.*;
2829
2930 /**
3031 *
5758 sb = new StringBuilder();
5859 converter.format(event, sb);
5960 assertEquals("Incorrect length: " + sb, 4, sb.length());
61 }
6062
63 @Test
64 public void testPatternAndParameterizedMessageDateLookup() throws Exception {
65 final MessagePatternConverter converter = MessagePatternConverter.newInstance(null, null);
66 final Message msg = new ParameterizedMessage("${date:now:buhu}");
67 final LogEvent event = Log4jLogEvent.newBuilder() //
68 .setLoggerName("MyLogger") //
69 .setLevel(Level.DEBUG) //
70 .setMessage(msg).build();
71 final StringBuilder sb = new StringBuilder();
72 converter.format(event, sb);
73 assertEquals("Unexpected result", "${date:now:buhu}", sb.toString());
6174 }
6275
6376 @Test
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.pattern;
17
18 import java.util.List;
19
20 import org.apache.logging.log4j.Logger;
21 import org.apache.logging.log4j.junit.LoggerContextRule;
22 import org.apache.logging.log4j.test.appender.ListAppender;
23 import org.apache.logging.log4j.util.Strings;
24 import org.junit.Before;
25 import org.junit.Rule;
26 import org.junit.Test;
27
28 import static org.junit.Assert.*;
29
30 /**
31 *
32 */
33 public class MessageStyledConverterTest {
34
35 private static final String EXPECTED = "\u001B[31;1mWarning!\u001B[m Pants on \u001B[31;1mfire!\u001B[m"
36 + Strings.LINE_SEPARATOR;
37
38 @Rule
39 public LoggerContextRule init = new LoggerContextRule("log4j-message-styled.xml");
40
41 private Logger logger;
42 private ListAppender app;
43
44 @Before
45 public void setUp() throws Exception {
46 this.logger = this.init.getLogger("LoggerTest");
47 this.app = this.init.getListAppender("List").clear();
48 }
49
50 @Test
51 public void testReplacement() {
52 // See org.fusesource.jansi.AnsiRenderer
53 logger.error("@|WarningStyle Warning!|@ Pants on @|WarningStyle fire!|@");
54
55 final List<String> msgs = app.getMessages();
56 assertNotNull(msgs);
57 assertEquals("Incorrect number of messages. Should be 1 is " + msgs.size(), 1, msgs.size());
58 assertTrue("Replacement failed - expected ending " + EXPECTED + ", actual " + msgs.get(0),
59 msgs.get(0).endsWith(EXPECTED));
60 }
61 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.core.pattern;
17
18 import static org.junit.Assert.assertEquals;
19
20 import org.apache.logging.log4j.Level;
21 import org.apache.logging.log4j.ThreadContext;
22 import org.apache.logging.log4j.core.LogEvent;
23 import org.apache.logging.log4j.core.impl.Log4jLogEvent;
24 import org.apache.logging.log4j.junit.ThreadContextStackRule;
25 import org.apache.logging.log4j.message.Message;
26 import org.apache.logging.log4j.message.SimpleMessage;
27 import org.junit.Rule;
28 import org.junit.Test;
29
30 public class NdcPatternConverterTest {
31
32 @Rule
33 public final ThreadContextStackRule threadContextRule = new ThreadContextStackRule();
34
35 @Test
36 public void testEmpty() {
37 testConverter("[]");
38 }
39
40 @Test
41 public void test1() {
42 ThreadContext.push("foo");
43 testConverter("[foo]");
44 }
45
46 @Test
47 public void test2() {
48 ThreadContext.push("foo");
49 ThreadContext.push("bar");
50 testConverter("[foo, bar]");
51 }
52
53 @Test
54 public void test3() {
55 ThreadContext.push("foo");
56 ThreadContext.push("bar");
57 ThreadContext.push("baz");
58 testConverter("[foo, bar, baz]");
59 }
60
61 private void testConverter(final String expected) {
62 final Message msg = new SimpleMessage("Hello");
63 final NdcPatternConverter converter = NdcPatternConverter.newInstance(null);
64 final LogEvent event = Log4jLogEvent.newBuilder() //
65 .setLoggerName("MyLogger") //
66 .setLevel(Level.DEBUG) //
67 .setMessage(msg) //
68 .build();
69 final StringBuilder sb = new StringBuilder();
70 converter.format(event, sb);
71 final String str = sb.toString();
72 assertEquals(expected, str);
73 }
74
75 }
76
1818 import java.util.List;
1919
2020 import org.apache.logging.log4j.Logger;
21 import org.apache.logging.log4j.core.util.Constants;
2221 import org.apache.logging.log4j.junit.LoggerContextRule;
2322 import org.apache.logging.log4j.test.appender.ListAppender;
23 import org.apache.logging.log4j.util.Strings;
2424 import org.junit.Before;
2525 import org.junit.Rule;
2626 import org.junit.Test;
3333
3434 private static final String EXPECTED =
3535 "ERROR LoggerTest o.a.l.l.c.p.NoConsoleNoAnsiTest org.apache.logging.log4j.core.pattern.NoConsoleNoAnsiTest"
36 + Constants.LINE_SEPARATOR;
36 + Strings.LINE_SEPARATOR;
3737
3838 @Rule
3939 public LoggerContextRule init = new LoggerContextRule("log4j2-console-noConsoleNoAnsi.xml");
2828 import org.apache.logging.log4j.core.config.Configuration;
2929 import org.apache.logging.log4j.core.config.NullConfiguration;
3030 import org.apache.logging.log4j.core.impl.Log4jLogEvent;
31 import org.apache.logging.log4j.core.util.Constants;
3231 import org.apache.logging.log4j.core.util.DummyNanoClock;
3332 import org.apache.logging.log4j.core.util.SystemNanoClock;
3433 import org.apache.logging.log4j.message.SimpleMessage;
34 import org.apache.logging.log4j.util.Strings;
3535 import org.junit.Before;
3636 import org.junit.Test;
3737
113113 formatter.format(event, buf);
114114 }
115115 final String str = buf.toString();
116 final String expected = "INFO [PatternParserTest :100 ] - Hello, world" + Constants.LINE_SEPARATOR;
116 final String expected = "INFO [PatternParserTest :100 ] - Hello, world" + Strings.LINE_SEPARATOR;
117117 assertTrue("Expected to end with: " + expected + ". Actual: " + str, str.endsWith(expected));
118118 }
119119
134134 formatter.format(event, buf);
135135 }
136136 final String str = buf.toString();
137 final String expected = "INFO rTest Hello, world" + Constants.LINE_SEPARATOR;
137 final String expected = "INFO rTest Hello, world" + Strings.LINE_SEPARATOR;
138138 assertTrue("Expected to end with: " + expected + ". Actual: " + str, str.endsWith(expected));
139139 }
140140
155155 formatter.format(event, buf);
156156 }
157157 final String str = buf.toString();
158 final String expected = "INFO org.a Hello, world" + Constants.LINE_SEPARATOR;
158 final String expected = "INFO org.a Hello, world" + Strings.LINE_SEPARATOR;
159159 assertTrue("Expected to end with: " + expected + ". Actual: " + str, str.endsWith(expected));
160160 }
161161
205205 final List<PatternFormatter> formatters = parser.parse(nestedPatternHighlight);
206206 assertNotNull(formatters);
207207 final Throwable t = new Throwable();
208 final StackTraceElement[] stackTraceElement = t.getStackTrace();
208 t.getStackTrace();
209209 final LogEvent event = Log4jLogEvent.newBuilder() //
210210 .setLoggerName("org.apache.logging.log4j.PatternParserTest") //
211211 .setMarker(MarkerManager.getMarker("TEST")) //
221221 formatter.format(event, buf);
222222 }
223223 final String str = buf.toString();
224 final String expectedEnd = String.format("] %-5s: Hello, world%s\u001B[m", level, Constants.LINE_SEPARATOR);
224 final String expectedEnd = String.format("] %-5s: Hello, world%s\u001B[m", level, Strings.LINE_SEPARATOR);
225225 assertTrue("Expected to start with: " + expectedStart + ". Actual: " + str, str.startsWith(expectedStart));
226226 assertTrue("Expected to end with: \"" + expectedEnd + "\". Actual: \"" + str, str.endsWith(expectedEnd));
227227 }
2020 import org.apache.logging.log4j.core.LogEvent;
2121 import org.apache.logging.log4j.core.LoggerContext;
2222 import org.apache.logging.log4j.core.impl.Log4jLogEvent;
23 import org.apache.logging.log4j.core.util.Constants;
2423 import org.apache.logging.log4j.message.SimpleMessage;
24 import org.apache.logging.log4j.util.Strings;
2525 import org.junit.Test;
2626
2727 import static org.junit.Assert.*;
4848 options);
4949 converter.format(event, sb);
5050 assertEquals("org/apache/logging/log4j/core/pattern/RegexReplacementConverterTest This is a test" +
51 Constants.LINE_SEPARATOR, sb.toString());
51 Strings.LINE_SEPARATOR, sb.toString());
5252 }
5353 }
1515 */
1616 package org.apache.logging.log4j.core.pattern;
1717
18 import static org.junit.Assert.assertEquals;
19 import static org.junit.Assert.assertNotNull;
20 import static org.junit.Assert.assertTrue;
21
1822 import java.util.List;
1923
2024 import org.apache.logging.log4j.ThreadContext;
21 import org.apache.logging.log4j.core.util.Constants;
2225 import org.apache.logging.log4j.junit.LoggerContextRule;
26 import org.apache.logging.log4j.junit.ThreadContextMapRule;
2327 import org.apache.logging.log4j.test.appender.ListAppender;
24 import org.junit.After;
28 import org.apache.logging.log4j.util.Strings;
2529 import org.junit.Before;
2630 import org.junit.ClassRule;
31 import org.junit.Rule;
2732 import org.junit.Test;
28
29 import static org.junit.Assert.*;
3033
3134 /**
3235 *
3639 private static ListAppender app;
3740 private static ListAppender app2;
3841
39 private static final String EXPECTED = "/RegexReplacementTest" + Constants.LINE_SEPARATOR;
42 private static final String EXPECTED = "/RegexReplacementTest" + Strings.LINE_SEPARATOR;
4043
4144 @ClassRule
4245 public static LoggerContextRule context = new LoggerContextRule(CONFIG);
46
47 @Rule
48 public final ThreadContextMapRule threadContextRule = new ThreadContextMapRule();
4349
4450 @Before
4551 public void setUp() throws Exception {
4652 app = context.getListAppender("List").clear();
4753 app2 = context.getListAppender("List2").clear();
48 }
49
50 @After
51 public void tearDown() throws Exception {
52 ThreadContext.clearMap();
5354 }
5455
5556 org.apache.logging.log4j.Logger logger = context.getLogger("LoggerTest");
6970 msgs = app.getMessages();
7071 assertNotNull(msgs);
7172 assertEquals("Incorrect number of messages. Should be 1 is " + msgs.size(), 1, msgs.size());
72 assertEquals("LoggerTest This is a test for Apache" + Constants.LINE_SEPARATOR, msgs.get(0));
73 assertEquals("LoggerTest This is a test for Apache" + Strings.LINE_SEPARATOR, msgs.get(0));
7374 }
7475 @Test
7576 public void testConverter() {
1818 import java.util.List;
1919
2020 import org.apache.logging.log4j.Logger;
21 import org.apache.logging.log4j.core.util.Constants;
2221 import org.apache.logging.log4j.junit.LoggerContextRule;
2322 import org.apache.logging.log4j.test.appender.ListAppender;
23 import org.apache.logging.log4j.util.Strings;
2424 import org.junit.Before;
2525 import org.junit.Rule;
2626 import org.junit.Test;
3434
3535 private static final String EXPECTED =
3636 "\u001B[1;31mERROR\u001B[m \u001B[1;36mLoggerTest\u001B[m o.a.l.l.c.p.StyleConverterTest org.apache.logging.log4j.core.pattern.StyleConverterTest"
37 + Constants.LINE_SEPARATOR;
37 + Strings.LINE_SEPARATOR;
3838
3939 @Rule
4040 public LoggerContextRule init = new LoggerContextRule("log4j-style.xml");
1717
1818 import org.apache.logging.log4j.Logger;
1919 import org.apache.logging.log4j.status.StatusLogger;
20 import org.apache.logging.log4j.util.LoaderUtil;
2021 import org.apache.logging.log4j.util.Strings;
2122
2223 /**
3132
3233 static {
3334 try {
34 controllerClazz = Loader.loadClass("com.yourkit.api.Controller");
35 profilingModes = Loader.loadClass("com.yourkit.api.ProfilingModes");
35 controllerClazz = LoaderUtil.loadClass("com.yourkit.api.Controller");
36 profilingModes = LoaderUtil.loadClass("com.yourkit.api.ProfilingModes");
3637 try {
3738 profiler = controllerClazz.getConstructor().newInstance();
3839 } catch (final Exception e) {
4646
4747 @Test
4848 public void testShutdownCallbackRegistry() throws Exception {
49 final LoggerContext context = ctx.getContext();
49 final LoggerContext context = ctx.getLoggerContext();
5050 assertTrue("LoggerContext should be started", context.isStarted());
5151 assertThat(Registry.CALLBACKS, hasSize(1));
5252 Registry.shutdown();
1919 import java.text.SimpleDateFormat;
2020 import java.util.Date;
2121 import java.util.Locale;
22 import java.util.TimeZone;
2223 import java.util.concurrent.TimeUnit;
2324
2425 import org.apache.logging.log4j.core.util.datetime.FixedDateFormat.FixedFormat;
113114 public void testCreateIfSupported_defaultIfOptionsArrayWithSingleNullElement() {
114115 final FixedDateFormat fmt = FixedDateFormat.createIfSupported(new String[1]);
115116 assertEquals(FixedFormat.DEFAULT.getPattern(), fmt.getFormat());
116 }
117
118 @Test
119 public void testCreateIfSupported_nullIfOptionsArrayHasTwoElements() {
120 final String[] options = {FixedDateFormat.FixedFormat.ABSOLUTE.getPattern(), "+08:00"};
121 assertNull("timezone", FixedDateFormat.createIfSupported(options));
117 assertEquals(TimeZone.getDefault(), fmt.getTimeZone());
118 }
119
120 @Test
121 public void testCreateIfSupported_defaultTimeZoneIfOptionsArrayWithSecondNullElement() {
122 final FixedDateFormat fmt = FixedDateFormat.createIfSupported(new String[] {FixedFormat.DEFAULT.getPattern(), null, ""});
123 assertEquals(FixedFormat.DEFAULT.getPattern(), fmt.getFormat());
124 assertEquals(TimeZone.getDefault(), fmt.getTimeZone());
125 }
126
127 @Test
128 public void testCreateIfSupported_customTimeZoneIfOptionsArrayWithTimeZoneElement() {
129 final FixedDateFormat fmt = FixedDateFormat.createIfSupported(new String[] {FixedFormat.DEFAULT.getPattern(), "+08:00", ""});
130 assertEquals(FixedFormat.DEFAULT.getPattern(), fmt.getFormat());
131 assertEquals(TimeZone.getTimeZone("+08:00"), fmt.getTimeZone());
122132 }
123133
124134 @Test(expected = NullPointerException.class)
125 public void testConstructorDisallowsNull() {
126 new FixedDateFormat(null);
135 public void testConstructorDisallowsNullFormat() {
136 new FixedDateFormat(null, TimeZone.getDefault());
137 }
138
139 @Test(expected = NullPointerException.class)
140 public void testConstructorDisallowsNullTimeZone() {
141 new FixedDateFormat(FixedFormat.ABSOLUTE, null);
127142 }
128143
129144 @Test
130145 public void testGetFormatReturnsConstructorFixedFormatPattern() {
131 final FixedDateFormat format = new FixedDateFormat(FixedDateFormat.FixedFormat.ABSOLUTE);
146 final FixedDateFormat format = new FixedDateFormat(FixedDateFormat.FixedFormat.ABSOLUTE, TimeZone.getDefault());
132147 assertSame(FixedDateFormat.FixedFormat.ABSOLUTE.getPattern(), format.getFormat());
133148 }
134149
139154 final long end = now + TimeUnit.HOURS.toMillis(25);
140155 for (final FixedFormat format : FixedFormat.values()) {
141156 final SimpleDateFormat simpleDF = new SimpleDateFormat(format.getPattern(), Locale.getDefault());
142 final FixedDateFormat customTF = new FixedDateFormat(format);
157 final FixedDateFormat customTF = new FixedDateFormat(format, TimeZone.getDefault());
143158 for (long time = start; time < end; time += 12345) {
144159 final String actual = customTF.format(time);
145160 final String expected = simpleDF.format(new Date(time));
155170 final long end = now + TimeUnit.HOURS.toMillis(25);
156171 for (final FixedFormat format : FixedFormat.values()) {
157172 final SimpleDateFormat simpleDF = new SimpleDateFormat(format.getPattern(), Locale.getDefault());
158 final FixedDateFormat customTF = new FixedDateFormat(format);
173 final FixedDateFormat customTF = new FixedDateFormat(format, TimeZone.getDefault());
159174 for (long time = end; time > start; time -= 12345) {
160175 final String actual = customTF.format(time);
161176 final String expected = simpleDF.format(new Date(time));
172187 final char[] buffer = new char[128];
173188 for (final FixedFormat format : FixedFormat.values()) {
174189 final SimpleDateFormat simpleDF = new SimpleDateFormat(format.getPattern(), Locale.getDefault());
175 final FixedDateFormat customTF = new FixedDateFormat(format);
190 final FixedDateFormat customTF = new FixedDateFormat(format, TimeZone.getDefault());
176191 for (long time = start; time < end; time += 12345) {
177192 final int length = customTF.format(time, buffer, 23);
178193 final String actual = new String(buffer, 23, length);
190205 final char[] buffer = new char[128];
191206 for (final FixedFormat format : FixedFormat.values()) {
192207 final SimpleDateFormat simpleDF = new SimpleDateFormat(format.getPattern(), Locale.getDefault());
193 final FixedDateFormat customTF = new FixedDateFormat(format);
208 final FixedDateFormat customTF = new FixedDateFormat(format, TimeZone.getDefault());
194209 for (long time = end; time > start; time -= 12345) {
195210 final int length = customTF.format(time, buffer, 23);
196211 final String actual = new String(buffer, 23, length);
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.junit;
17
18 import java.io.File;
19 import java.util.ArrayList;
20 import java.util.Arrays;
21 import java.util.List;
22
23 import org.junit.rules.ExternalResource;
24
25 public abstract class AbstractExternalFileCleaner extends ExternalResource {
26
27 private final boolean cleanAfter;
28 private final boolean cleanBefore;
29 private final List<File> files;
30
31 public AbstractExternalFileCleaner(final boolean before, final boolean after, final File... files) {
32 this.cleanBefore = before;
33 this.cleanAfter = after;
34 this.files = Arrays.asList(files);
35 }
36
37 public AbstractExternalFileCleaner(final boolean before, final boolean after, final String... fileNames) {
38 this.cleanBefore = before;
39 this.cleanAfter = after;
40 this.files = new ArrayList<>(fileNames.length);
41 for (final String fileName : fileNames) {
42 this.files.add(new File(fileName));
43 }
44 }
45
46 @Override
47 protected void after() {
48 if (cleanAfter()) {
49 this.clean();
50 }
51 }
52
53 @Override
54 protected void before() {
55 if (cleanBefore()) {
56 this.clean();
57 }
58 }
59
60 abstract protected void clean();
61
62 public boolean cleanAfter() {
63 return cleanAfter;
64 }
65
66 public boolean cleanBefore() {
67 return cleanBefore;
68 }
69
70 public List<File> getFiles() {
71 return files;
72 }
73
74 @Override
75 public String toString() {
76 return getClass().getSimpleName() + " [files=" + files + ", cleanAfter=" + cleanAfter + ", cleanBefore="
77 + cleanBefore + "]";
78 }
79
80 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.junit;
17
18 import java.io.File;
19 import java.io.IOException;
20 import java.nio.file.Files;
21 import java.nio.file.Path;
22 import java.nio.file.Paths;
23 import java.util.Arrays;
24 import java.util.HashMap;
25 import java.util.HashSet;
26 import java.util.Map;
27 import java.util.Set;
28
29 import org.junit.Assert;
30 import org.junit.rules.ExternalResource;
31
32 public abstract class AbstractExternalFileCleaner extends ExternalResource {
33
34 private static final int SLEEP_RETRY_MILLIS = 200;
35 private final boolean cleanAfter;
36 private final boolean cleanBefore;
37 private final Set<Path> files;
38 private final int maxTries;
39
40 public AbstractExternalFileCleaner(final boolean before, final boolean after, final int maxTries,
41 final File... files) {
42 this.cleanBefore = before;
43 this.cleanAfter = after;
44 this.maxTries = maxTries;
45 this.files = new HashSet<>(files.length);
46 for (final File file : files) {
47 this.files.add(file.toPath());
48 }
49 }
50
51 public AbstractExternalFileCleaner(final boolean before, final boolean after, final int maxTries,
52 final Path... files) {
53 this.cleanBefore = before;
54 this.cleanAfter = after;
55 this.maxTries = maxTries;
56 this.files = new HashSet<>(Arrays.asList(files));
57 }
58
59 public AbstractExternalFileCleaner(final boolean before, final boolean after, final int maxTries,
60 final String... fileNames) {
61 this.cleanBefore = before;
62 this.cleanAfter = after;
63 this.maxTries = maxTries;
64 this.files = new HashSet<>(fileNames.length);
65 for (final String fileName : fileNames) {
66 this.files.add(Paths.get(fileName));
67 }
68 }
69
70 @Override
71 protected void after() {
72 if (cleanAfter()) {
73 this.clean();
74 }
75 }
76
77 @Override
78 protected void before() {
79 if (cleanBefore()) {
80 this.clean();
81 }
82 }
83
84 protected void clean() {
85 final Map<Path, IOException> failures = new HashMap<>();
86 // Clean and gather failures
87 for (final Path path : getPaths()) {
88 if (Files.exists(path)) {
89 for (int i = 0; i < getMaxTries(); i++) {
90 try {
91 if (clean(path, i)) {
92 if (failures.containsKey(path)) {
93 failures.remove(path);
94 }
95 break;
96 }
97 } catch (final IOException e) {
98 // We will try again.
99 failures.put(path, e);
100 }
101 try {
102 Thread.sleep(SLEEP_RETRY_MILLIS);
103 } catch (final InterruptedException ignored) {
104 // ignore
105 }
106 }
107 }
108 }
109 // Fail on failures
110 if (failures.size() > 0) {
111 final StringBuilder sb = new StringBuilder();
112 boolean first = true;
113 for (final Map.Entry<Path, IOException> failure : failures.entrySet()) {
114 failure.getValue().printStackTrace();
115 if (!first) {
116 sb.append(", ");
117 }
118 sb.append(failure.getKey()).append(" failed with ").append(failure.getValue());
119 first = false;
120 }
121 Assert.fail(sb.toString());
122 }
123
124 }
125
126 protected abstract boolean clean(Path path, int tryIndex) throws IOException;
127
128 public boolean cleanAfter() {
129 return cleanAfter;
130 }
131
132 public boolean cleanBefore() {
133 return cleanBefore;
134 }
135
136 public int getMaxTries() {
137 return maxTries;
138 }
139
140 public Set<Path> getPaths() {
141 return files;
142 }
143
144 @Override
145 public String toString() {
146 return getClass().getSimpleName() + " [files=" + files + ", cleanAfter=" + cleanAfter + ", cleanBefore="
147 + cleanBefore + "]";
148 }
149
150 }
1818 import java.io.File;
1919 import java.io.IOException;
2020 import java.nio.file.Files;
21
22 import org.junit.Assert;
21 import java.nio.file.Path;
2322
2423 /**
2524 * A JUnit test rule to automatically delete files after a test is run.
2726 public class CleanFiles extends AbstractExternalFileCleaner {
2827 private static final int MAX_TRIES = 10;
2928
30 public CleanFiles(final boolean before, final boolean after, final File... files) {
31 super(before, after, files);
29 public CleanFiles(final boolean before, final boolean after, final int maxTries, final File... files) {
30 super(before, after, maxTries, files);
3231 }
3332
34 public CleanFiles(final boolean before, final boolean after, final String... fileNames) {
35 super(before, after, fileNames);
33 public CleanFiles(final boolean before, final boolean after, final int maxTries, final String... fileNames) {
34 super(before, after, maxTries, fileNames);
3635 }
3736
3837 public CleanFiles(final File... files) {
39 super(true, true, files);
38 super(true, true, MAX_TRIES, files);
39 }
40
41 public CleanFiles(final Path... paths) {
42 super(true, true, MAX_TRIES, paths);
4043 }
4144
4245 public CleanFiles(final String... fileNames) {
43 super(true, true, fileNames);
46 super(true, true, MAX_TRIES, fileNames);
4447 }
4548
4649 @Override
47 protected void clean() {
48 for (final File file : getFiles()) {
49 for (int i = 0; i < MAX_TRIES; i++) {
50 try {
51 if (Files.deleteIfExists(file.toPath())) {
52 // Break from MAX_TRIES and move on to the next file.
53 break;
54 }
55 } catch (final IOException e) {
56 Assert.fail(file + ": " + e.toString());
57 }
58 try {
59 Thread.sleep(200);
60 } catch (final InterruptedException ignored) {
61 }
62 }
63 }
50 protected boolean clean(final Path path, final int tryIndex) throws IOException {
51 return Files.deleteIfExists(path);
6452 }
6553
6654 }
2222 import java.nio.file.Path;
2323 import java.nio.file.SimpleFileVisitor;
2424 import java.nio.file.attribute.BasicFileAttributes;
25 import java.util.HashMap;
26 import java.util.Map;
27
28 import org.junit.Assert;
2925
3026 /**
3127 * A JUnit test rule to automatically delete folders recursively before (optional) and after (optional) a test is run.
3329 public class CleanFolders extends AbstractExternalFileCleaner {
3430 private static final int MAX_TRIES = 10;
3531
36 public CleanFolders(final boolean before, final boolean after, final File... files) {
37 super(before, after, files);
32 public CleanFolders(final boolean before, final boolean after, final int maxTries, final File... files) {
33 super(before, after, maxTries, files);
3834 }
3935
40 public CleanFolders(final boolean before, final boolean after, final String... fileNames) {
41 super(before, after, fileNames);
36 public CleanFolders(final boolean before, final boolean after, final int maxTries, final String... fileNames) {
37 super(before, after, maxTries, fileNames);
4238 }
4339
4440 public CleanFolders(final File... folders) {
45 super(true, true, folders);
41 super(true, true, MAX_TRIES, folders);
42 }
43
44 public CleanFolders(final Path... paths) {
45 super(true, true, MAX_TRIES, paths);
4646 }
4747
4848 public CleanFolders(final String... folderNames) {
49 super(true, true, folderNames);
50 }
51
52 @Override
53 protected void clean() {
54 Map<Path, IOException> failures = new HashMap<>();
55
56 for (final File folder : getFiles()) {
57 final Path path = folder.toPath();
58 for (int i = 0; i < MAX_TRIES; i++) {
59 try {
60 cleanFolder(path);
61 if (failures.containsKey(path)) {
62 failures.remove(path);
63 }
64 // break from MAX_TRIES and goes to the next folder
65 break;
66 } catch (final IOException e) {
67 // We will try again.
68 failures.put(path, e);
69 }
70 }
71 }
72 if (failures.size() > 0) {
73 StringBuilder sb = new StringBuilder();
74 boolean first = true;
75 for (Map.Entry<Path, IOException> failure : failures.entrySet()) {
76 failure.getValue().printStackTrace();
77 if (!first) {
78 sb.append(", ");
79 }
80 sb.append(failure.getKey()).append(" failed with ").append(failure.getValue());
81 first = false;
82 }
83 Assert.fail(sb.toString());
84 }
49 super(true, true, MAX_TRIES, folderNames);
8550 }
8651
8752 private void cleanFolder(final Path folder) throws IOException {
10166 });
10267 }
10368 }
69
70 @Override
71 protected boolean clean(final Path path, final int tryIndex) throws IOException {
72 cleanFolder(path);
73 return true;
74 }
10475 }
1515 */
1616 package org.apache.logging.log4j.junit;
1717
18 import static org.junit.Assert.assertNotNull;
18 import java.util.concurrent.TimeUnit;
1919
2020 import org.apache.logging.log4j.Level;
21 import org.apache.logging.log4j.core.AbstractLifeCycle;
2122 import org.apache.logging.log4j.core.Appender;
2223 import org.apache.logging.log4j.core.Logger;
2324 import org.apache.logging.log4j.core.LoggerContext;
3233 import org.junit.runner.Description;
3334 import org.junit.runners.model.Statement;
3435
36 import static org.junit.Assert.*;
37
3538 /**
3639 * JUnit {@link TestRule} for constructing a new LoggerContext using a specified configuration file. If the system
3740 * property {@code EBUG} is set (e.g., through the command line option {@code -DEBUG}), then the StatusLogger will be
4043 */
4144 public class LoggerContextRule implements TestRule {
4245
46 public static LoggerContextRule createShutdownTimeoutLoggerContextRule(final String config) {
47 return new LoggerContextRule(config, 10, TimeUnit.SECONDS);
48 }
49
4350 private static final String SYS_PROP_KEY_CLASS_NAME = "org.apache.logging.log4j.junit.LoggerContextRule#ClassName";
4451 private static final String SYS_PROP_KEY_DISPLAY_NAME = "org.apache.logging.log4j.junit.LoggerContextRule#DisplayName";
4552 private final String configLocation;
46 private LoggerContext context;
47
53 private LoggerContext loggerContext;
4854 private Class<? extends ContextSelector> contextSelectorClass;
49
5055 private String testClassName;
56 private final long shutdownTimeout;
57 private final TimeUnit shutdownTimeUnit;
58
59 /**
60 * Constructs a new LoggerContextRule without a configuration file.
61 */
62 public LoggerContextRule() {
63 this(null, null);
64 }
5165
5266 /**
5367 * Constructs a new LoggerContextRule for a given configuration file.
6680 * path to configuration file
6781 * @param contextSelectorClass
6882 * custom ContextSelector class to use instead of default
69 * @since 2.5
7083 */
7184 public LoggerContextRule(final String configLocation, final Class<? extends ContextSelector> contextSelectorClass) {
85 this(configLocation, contextSelectorClass, AbstractLifeCycle.DEFAULT_STOP_TIMEOUT,
86 AbstractLifeCycle.DEFAULT_STOP_TIMEUNIT);
87 }
88
89 public LoggerContextRule(final String configLocation, final Class<? extends ContextSelector> contextSelectorClass,
90 final long shutdownTimeout, final TimeUnit shutdownTimeUnit) {
7291 this.configLocation = configLocation;
7392 this.contextSelectorClass = contextSelectorClass;
93 this.shutdownTimeout = shutdownTimeout;
94 this.shutdownTimeUnit = shutdownTimeUnit;
95 }
96
97 public LoggerContextRule(final String config, final int shutdownTimeout, final TimeUnit shutdownTimeUnit) {
98 this(config, null, shutdownTimeout, shutdownTimeUnit);
7499 }
75100
76101 @Override
86111 if (contextSelectorClass != null) {
87112 System.setProperty(Constants.LOG4J_CONTEXT_SELECTOR, contextSelectorClass.getName());
88113 }
114 // TODO Consider instead of the above:
115 // LogManager.setFactory(new Log4jContextFactory(LoaderUtil.newInstanceOf(contextSelectorClass)));
89116 System.setProperty(SYS_PROP_KEY_CLASS_NAME, description.getClassName());
90117 System.setProperty(SYS_PROP_KEY_DISPLAY_NAME, description.getDisplayName());
91 context = Configurator.initialize(description.getDisplayName(),
118 loggerContext = Configurator.initialize(description.getDisplayName(),
92119 description.getTestClass().getClassLoader(), configLocation);
93120 try {
94121 base.evaluate();
95122 } finally {
96 Configurator.shutdown(context);
97 context = null;
123 if (!Configurator.shutdown(loggerContext, shutdownTimeout, shutdownTimeUnit)) {
124 StatusLogger.getLogger().error("Logger context {} did not shutdown completely after {} {}.",
125 loggerContext.getName(), shutdownTimeout, shutdownTimeUnit);
126 }
127 loggerContext = null;
98128 contextSelectorClass = null;
99129 StatusLogger.getLogger().reset();
100130 System.clearProperty(Constants.LOG4J_CONTEXT_SELECTOR);
138168 * @return this LoggerContext's Configuration.
139169 */
140170 public Configuration getConfiguration() {
141 return context.getConfiguration();
171 return loggerContext.getConfiguration();
142172 }
143173
144174 /**
146176 *
147177 * @return the current LoggerContext.
148178 */
149 public LoggerContext getContext() {
150 return context;
179 public LoggerContext getLoggerContext() {
180 return loggerContext;
151181 }
152182
153183 /**
173203 * @return the test class's named Logger.
174204 */
175205 public Logger getLogger() {
176 return context.getLogger(testClassName);
206 return loggerContext.getLogger(testClassName);
207 }
208
209 /**
210 * Gets a named Logger for the given class in this LoggerContext.
211 *
212 * @param clazz
213 * The Class whose name should be used as the Logger name. If null it will default to the calling class.
214 * @return the named Logger.
215 */
216 public Logger getLogger(final Class<?> clazz) {
217 return loggerContext.getLogger(clazz.getName());
177218 }
178219
179220 /**
184225 * @return the named Logger.
185226 */
186227 public Logger getLogger(final String name) {
187 return context.getLogger(name);
228 return loggerContext.getLogger(name);
188229 }
189230
190231 /**
217258 */
218259 public <T extends Appender> T getRequiredAppender(final String name, final Class<T> cls) {
219260 final T appender = getAppender(name, cls);
220 assertNotNull("Appender named " + name + " was null.", appender);
261 assertNotNull("Appender named " + name + " was null in logger context " + loggerContext, appender);
221262 return appender;
222263 }
223264
227268 * @return the root logger.
228269 */
229270 public Logger getRootLogger() {
230 return context.getRootLogger();
271 return loggerContext.getRootLogger();
231272 }
232273
233274 @Override
245286 return RuleChain.outerRule(new CleanFiles(files)).around(this);
246287 }
247288
248 public RuleChain withCleanFoldersRule(final boolean before, final boolean after, final String... folders) {
249 return RuleChain.outerRule(new CleanFolders(before, after, folders)).around(this);
289 public RuleChain withCleanFoldersRule(final boolean before, final boolean after, final int maxTries, final String... folders) {
290 return RuleChain.outerRule(new CleanFolders(before, after, maxTries, folders)).around(this);
250291 }
251292
252293 public RuleChain withCleanFoldersRule(final String... folders) {
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16
17 package org.apache.logging.log4j.junit;
18
19 import java.lang.reflect.Field;
20 import java.net.URL;
21 import java.net.URLStreamHandler;
22 import java.net.URLStreamHandlerFactory;
23 import java.util.Hashtable;
24
25 import org.junit.Assert;
26 import org.junit.rules.TestRule;
27 import org.junit.runner.Description;
28 import org.junit.runners.model.Statement;
29
30 /**
31 * Installs and restores the URL URLStreamHandlerFactory before and after tests.
32 * <p>
33 * Might need tweaking for different JREs.
34 * </p>
35 */
36 public class URLStreamHandlerFactoryRule implements TestRule {
37
38 public URLStreamHandlerFactoryRule() {
39 this(null);
40 }
41
42 public URLStreamHandlerFactoryRule(final URLStreamHandlerFactory newURLStreamHandlerFactory) {
43 this.newURLStreamHandlerFactory = newURLStreamHandlerFactory;
44 }
45
46 private final URLStreamHandlerFactory newURLStreamHandlerFactory;
47
48 void clearURLHandlers() throws Exception {
49 final Field handlersFields = URL.class.getDeclaredField("handlers");
50 if (handlersFields != null) {
51 if (!handlersFields.isAccessible()) {
52 handlersFields.setAccessible(true);
53 }
54 @SuppressWarnings("unchecked")
55 final
56 Hashtable<String, URLStreamHandler> handlers = (Hashtable<String, URLStreamHandler>) handlersFields
57 .get(null);
58 if (handlers != null) {
59 handlers.clear();
60 }
61 }
62 }
63
64 @Override
65 public Statement apply(final Statement base, final Description description) {
66 return new Statement() {
67 @Override
68 public void evaluate() throws Throwable {
69 Field factoryField = null;
70 int matches = 0;
71 URLStreamHandlerFactory oldFactory = null;
72 for (final Field field : URL.class.getDeclaredFields()) {
73 if (URLStreamHandlerFactory.class.equals(field.getType())) {
74 factoryField = field;
75 matches++;
76 factoryField.setAccessible(true);
77 oldFactory = (URLStreamHandlerFactory) factoryField.get(null);
78 break;
79 }
80 }
81 Assert.assertNotNull("java.net URL does not declare a java.net.URLStreamHandlerFactory field",
82 factoryField);
83 Assert.assertEquals("java.net.URL declares multiple java.net.URLStreamHandlerFactory fields.", 1,
84 matches); // FIXME There is a break in the loop so always 0 or 1
85 URL.setURLStreamHandlerFactory(newURLStreamHandlerFactory);
86 try {
87 base.evaluate();
88 } finally {
89 clearURLHandlers();
90 factoryField.set(null, null);
91 URL.setURLStreamHandlerFactory(oldFactory);
92 }
93 }
94 };
95 }
96 }
2121 /**
2222 *
2323 */
24 @Plugin(name="ExtendedLevel", category="Level")
24 @Plugin(name="ExtendedLevel", category=Level.CATEGORY)
2525 public class ExtendedLevels {
2626
2727 public static final Level NOTE = Level.forName("NOTE", 350);
1616 package org.apache.logging.log4j.test.appender;
1717
1818 import org.apache.logging.log4j.LoggingException;
19 import org.apache.logging.log4j.core.Appender;
1920 import org.apache.logging.log4j.core.LogEvent;
2021 import org.apache.logging.log4j.core.appender.AbstractAppender;
2122 import org.apache.logging.log4j.core.config.plugins.Plugin;
2627 /**
2728 *
2829 */
29 @Plugin(name="AlwaysFail", category ="Core", elementType="appender", printObject=true)
30 @Plugin(name="AlwaysFail", category ="Core", elementType=Appender.ELEMENT_TYPE, printObject=true)
3031 public class AlwaysFailAppender extends AbstractAppender {
3132
3233 private AlwaysFailAppender(final String name) {
1515 */
1616 package org.apache.logging.log4j.test.appender;
1717
18 import java.util.concurrent.TimeUnit;
19
20 import org.apache.logging.log4j.core.Appender;
1821 import org.apache.logging.log4j.core.LogEvent;
1922 import org.apache.logging.log4j.core.appender.AbstractAppender;
2023 import org.apache.logging.log4j.core.config.plugins.Plugin;
2528 /**
2629 *
2730 */
28 @Plugin(name="Block", category ="Core", elementType="appender", printObject=true)
31 @Plugin(name="Block", category ="Core", elementType=Appender.ELEMENT_TYPE, printObject=true)
2932 public class BlockingAppender extends AbstractAppender {
3033 public volatile boolean running = true;
3134
4548 }
4649 }
4750 @Override
48 public void stop() {
51 public boolean stop(final long timeout, final TimeUnit timeUnit) {
52 setStopping();
53 super.stop(timeout, timeUnit, false);
4954 running = false;
50 super.stop();
55 setStopped();
56 return true;
5157 }
5258
5359 @PluginFactory
1515 */
1616 package org.apache.logging.log4j.test.appender;
1717
18 import java.util.concurrent.TimeUnit;
19
1820 import org.apache.logging.log4j.LogManager;
1921 import org.apache.logging.log4j.Logger;
2022 import org.apache.logging.log4j.LoggingException;
23 import org.apache.logging.log4j.core.Appender;
2124 import org.apache.logging.log4j.core.LogEvent;
2225 import org.apache.logging.log4j.core.appender.AbstractAppender;
2326 import org.apache.logging.log4j.core.config.plugins.Plugin;
2831 /**
2932 *
3033 */
31 @Plugin(name="Deadlock", category ="Core", elementType="appender", printObject=true)
34 @Plugin(name="Deadlock", category ="Core", elementType=Appender.ELEMENT_TYPE, printObject=true)
3235 public class DeadlockAppender extends AbstractAppender {
3336
3437 private WorkerThread thread = null;
4548 }
4649
4750 @Override
48 public void stop() {
49 super.stop();
51 public boolean stop(final long timeout, final TimeUnit timeUnit) {
52 setStopping();
53 super.stop(timeout, timeUnit, false);
5054 thread.start();
5155 try {
5256 thread.join();
5357 } catch (final Exception ex) {
5458 System.out.println("Thread interrupted");
5559 }
60 setStopped();
61 return true;
5662 }
5763
5864 @Override
1919 import java.util.List;
2020
2121 import org.apache.logging.log4j.LoggingException;
22 import org.apache.logging.log4j.core.Appender;
2223 import org.apache.logging.log4j.core.LogEvent;
2324 import org.apache.logging.log4j.core.appender.AbstractAppender;
2425 import org.apache.logging.log4j.core.config.plugins.Plugin;
2930 /**
3031 *
3132 */
32 @Plugin(name="FailOnce", category ="Core", elementType="appender", printObject=true)
33 @Plugin(name="FailOnce", category ="Core", elementType=Appender.ELEMENT_TYPE, printObject=true)
3334 public class FailOnceAppender extends AbstractAppender {
3435
3536 boolean fail = true;
1616 package org.apache.logging.log4j.test.appender;
1717
1818 import java.io.ByteArrayOutputStream;
19 import java.io.IOException;
1920 import java.io.Serializable;
2021
2122 import org.apache.logging.log4j.core.Layout;
4748
4849 @Override
4950 public String toString() {
50 return getOutputStream().toString();
51 try {
52 return getOutputStream().toString();
53 } catch (final IOException e) {
54 throw new IllegalStateException(e);
55 }
5156 }
5257 }
5358 }
2020 import java.util.Collections;
2121 import java.util.List;
2222 import java.util.concurrent.CountDownLatch;
23
23 import java.util.concurrent.TimeUnit;
24
25 import org.apache.logging.log4j.core.Appender;
2426 import org.apache.logging.log4j.core.Filter;
2527 import org.apache.logging.log4j.core.Layout;
2628 import org.apache.logging.log4j.core.LogEvent;
3739 /**
3840 * This appender is primarily used for testing. Use in a real environment is discouraged as the
3941 * List could eventually grow to cause an OutOfMemoryError.
42 *
43 * This appender is not thread-safe.
4044 *
4145 * This appender will use {@link Layout#toByteArray(LogEvent)}.
4246 *
4347 * @see org.apache.logging.log4j.junit.LoggerContextRule#getListAppender(String) ILC.getListAppender
4448 */
45 @Plugin(name = "List", category = "Core", elementType = "appender", printObject = true)
49 @Plugin(name = "List", category = "Core", elementType = Appender.ELEMENT_TYPE, printObject = true)
4650 public class ListAppender extends AbstractAppender {
4751
4852 // Use CopyOnWriteArrayList?
143147 }
144148
145149 @Override
146 public void stop() {
147 super.stop();
150 public boolean stop(final long timeout, final TimeUnit timeUnit) {
151 setStopping();
152 super.stop(timeout, timeUnit, false);
148153 final Layout<? extends Serializable> layout = getLayout();
149154 if (layout != null) {
150155 final byte[] bytes = layout.getFooter();
152157 write(bytes);
153158 }
154159 }
160 setStopped();
161 return true;
155162 }
156163
157164 public synchronized ListAppender clear() {
166173 }
167174
168175 public synchronized List<String> getMessages() {
176 return Collections.unmodifiableList(messages);
177 }
178
179 /**
180 * Polls the messages list for it to grow to a given minimum size at most timeout timeUnits and return a copy of
181 * what we have so far.
182 */
183 public List<String> getMessages(final int minSize, final long timeout, final TimeUnit timeUnit) throws InterruptedException {
184 final long endMillis = System.currentTimeMillis() + timeUnit.toMillis(timeout);
185 while (messages.size() < minSize && System.currentTimeMillis() < endMillis) {
186 Thread.sleep(100);
187 }
169188 return Collections.unmodifiableList(messages);
170189 }
171190
1515 */
1616 package org.apache.logging.log4j.test.appender;
1717
18 import org.apache.logging.log4j.core.Appender;
1819 import org.apache.logging.log4j.core.Filter;
1920 import org.apache.logging.log4j.core.Layout;
2021 import org.apache.logging.log4j.core.LogEvent;
2930 /**
3031 *
3132 */
32 @Plugin(name = "UsesLoggingAppender", category = "Core", elementType = "appender", printObject = true)
33 @Plugin(name = "UsesLoggingAppender", category = "Core", elementType = Appender.ELEMENT_TYPE, printObject = true)
3334 public final class UsesLoggingAppender extends AbstractAppender {
3435
3536 private final SomethingThatUsesLogging thing;
2222 import org.apache.logging.log4j.core.config.plugins.Plugin;
2323 import org.apache.logging.log4j.core.config.plugins.PluginFactory;
2424 import org.apache.logging.log4j.core.layout.AbstractStringLayout;
25 import org.apache.logging.log4j.core.util.Constants;
25 import org.apache.logging.log4j.util.Strings;
2626
2727 /**
2828 *
3030 @Plugin(name = "BasicLayout", category = "Core", elementType = "layout", printObject = true)
3131 public class BasicLayout extends AbstractStringLayout {
3232
33 private static final String HEADER = "Header" + Constants.LINE_SEPARATOR;
33 private static final String HEADER = "Header" + Strings.LINE_SEPARATOR;
3434
3535 public BasicLayout(final Charset charset) {
3636 super(charset);
4343
4444 @Override
4545 public String toSerializable(final LogEvent event) {
46 return event.getMessage().getFormattedMessage() + Constants.LINE_SEPARATOR;
46 return event.getMessage().getFormattedMessage() + Strings.LINE_SEPARATOR;
4747 }
4848
4949 /**
0 <?xml version="1.0" encoding="UTF-8"?>
1 <Configuration status="ERROR">
2 <Appenders>
3 <RandomAccessFile name="AsyncLoggerAndAsyncAppenderFile" fileName="target/AsyncLoggerAndAsyncAppenderTest.log"
4 immediateFlush="false" append="false">
5 <PatternLayout>
6 <Pattern>%p %c{1.} %X{KEY} %x %X %m%ex%n</Pattern>
7 </PatternLayout>
8 </RandomAccessFile>
9 <Async name="AsyncLoggerAndAsyncAppender">
10 <AppenderRef ref="AsyncLoggerAndAsyncAppenderFile" />
11 </Async>
12 <RandomAccessFile name="AsyncAppenderFile" fileName="target/AsyncAppenderContextTest.log"
13 immediateFlush="false" append="false">
14 <PatternLayout>
15 <Pattern>%p %c{1.} %X{KEY} %x %X %m%ex%n</Pattern>
16 </PatternLayout>
17 </RandomAccessFile>
18 <Async name="AsyncAppender">
19 <AppenderRef ref="AsyncAppenderFile" />
20 </Async>
21 <RandomAccessFile name="RandomAccessFile" fileName="target/AsyncLoggerTest.log"
22 immediateFlush="false" append="false">
23 <PatternLayout>
24 <Pattern>%p %c{1.} %X{KEY} %x %X %m%ex%n</Pattern>
25 </PatternLayout>
26 </RandomAccessFile>
27 <RandomAccessFile name="SynchronousRandomAccessFile" fileName="target/SynchronousContextTest.log"
28 immediateFlush="true" append="false">
29 <PatternLayout>
30 <Pattern>%p %c{1.} %X{KEY} %x %X %m%ex%n</Pattern>
31 </PatternLayout>
32 </RandomAccessFile>
33 </Appenders>
34
35 <Loggers>
36 <AsyncLogger name="com.foo" level="info" includeLocation="false" additivity="true">
37 <Property name="configProp">configValue</Property>
38 <Property name="configProp2">configValue2</Property>
39 <AppenderRef ref="RandomAccessFile"/>
40 <AppenderRef ref="AsyncLoggerAndAsyncAppender"/>
41 </AsyncLogger>
42 <Root level="info" includeLocation="false">
43 <Property name="configProp">configValue</Property>
44 <Property name="configProp2">configValue2</Property>
45 <AppenderRef ref="SynchronousRandomAccessFile"/>
46 <AppenderRef ref="AsyncAppender"/>
47 </Root>
48 </Loggers>
49 </Configuration>
0 <?xml version="1.0" encoding="UTF-8"?>
1 <Configuration status="warn">
2 <Appenders>
3 <Console name="Console" target="SYSTEM_OUT">
4 <PatternLayout>
5 <pattern>%xEx{0}</pattern>
6 </PatternLayout>
7 </Console>
8 </Appenders>
9
10 <Loggers>
11 <Root level="info">
12 <AppenderRef ref="Console"/>
13 </Root>
14 </Loggers>
15 </Configuration>
00 <?xml version="1.0" encoding="UTF-8"?>
11 <Configuration status="ERROR">
22 <Appenders>
3 <RandomAccessFile name="RandomAccessFile" fileName="target/AsyncLoggerTest.log"
3 <RandomAccessFile name="RandomAccessFile" fileName="target/AsyncLoggerTest.log"
44 immediateFlush="false" append="false">
55 <PatternLayout>
6 <Pattern>%d %p %c{1.} [%t] %X{KEY} %x %location %m %ex%n</Pattern>
6 <Pattern>%p %c{1.} %X{KEY} %x %X %m%ex%n</Pattern>
77 </PatternLayout>
88 </RandomAccessFile>
99 </Appenders>
10
10
1111 <Loggers>
1212 <Root level="info" includeLocation="false">
13 <Property name="configProp">configValue</Property>
14 <Property name="configProp2">configValue2</Property>
1315 <AppenderRef ref="RandomAccessFile"/>
1416 </Root>
1517 </Loggers>
0 <?xml version="1.0" encoding="UTF-8"?>
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 <Configuration status="OFF" name="ArrayBlockingQueueFactory">
19
20 <Appenders>
21 <Console name="STDOUT">
22 <PatternLayout pattern="%m%n"/>
23 </Console>
24 <List name="List">
25 <PatternLayout pattern="%C %M %m"/>
26 </List>
27 <Async name="Async" includeLocation="true" error-ref="STDOUT">
28 <AppenderRef ref="List"/>
29 <ArrayBlockingQueue/>
30 </Async>
31 </Appenders>
32
33 <Loggers>
34 <Root level="debug">
35 <AppenderRef ref="Async"/>
36 </Root>
37 </Loggers>
38
39 </Configuration>
0 <?xml version="1.0" encoding="UTF-8"?>
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 <Configuration status="OFF" name="DisruptorBlockingQueueFactory">
19
20 <Appenders>
21 <Console name="STDOUT">
22 <PatternLayout pattern="%m%n"/>
23 </Console>
24 <List name="List">
25 <PatternLayout pattern="%C %M %m"/>
26 </List>
27 <Async name="Async" includeLocation="true" error-ref="STDOUT">
28 <AppenderRef ref="List"/>
29 <DisruptorBlockingQueue/>
30 </Async>
31 </Appenders>
32
33 <Loggers>
34 <Root level="debug">
35 <AppenderRef ref="Async"/>
36 </Root>
37 </Loggers>
38
39 </Configuration>
0 <?xml version="1.0" encoding="UTF-8"?>
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 <Configuration status="OFF" name="JCToolsBlockingQueueFactory">
19
20 <Appenders>
21 <Console name="STDOUT">
22 <PatternLayout pattern="%m%n"/>
23 </Console>
24 <List name="List">
25 <PatternLayout pattern="%C %M %m"/>
26 </List>
27 <Async name="Async" includeLocation="true" error-ref="STDOUT">
28 <AppenderRef ref="List"/>
29 <JCToolsBlockingQueue/>
30 </Async>
31 </Appenders>
32
33 <Loggers>
34 <Root level="debug">
35 <AppenderRef ref="Async"/>
36 </Root>
37 </Loggers>
38
39 </Configuration>
0 <?xml version="1.0" encoding="UTF-8"?>
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 <Configuration status="OFF" name="LinkedTransferQueueFactory">
19
20 <Appenders>
21 <Console name="STDOUT">
22 <PatternLayout pattern="%m%n"/>
23 </Console>
24 <List name="List">
25 <PatternLayout pattern="%C %M %m"/>
26 </List>
27 <Async name="Async" includeLocation="true" error-ref="STDOUT">
28 <AppenderRef ref="List"/>
29 <LinkedTransferQueue/>
30 </Async>
31 </Appenders>
32
33 <Loggers>
34 <Root level="debug">
35 <AppenderRef ref="Async"/>
36 </Root>
37 </Loggers>
38
39 </Configuration>
0 <?xml version="1.0" encoding="UTF-8"?>
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 <Configuration name="JeroMQAppenderTest" status="WARN">
18 <Appenders>
19 <JeroMQ name="JeroMQAppender">
20 <Property name="endpoint">tcp://*:5556</Property>
21 <Property name="endpoint">ipc://info-topic</Property>
22 <PatternLayout pattern="%X{foo}%m"/>
23 </JeroMQ>
24 </Appenders>
25 <Loggers>
26 <Root level="info">
27 <AppenderRef ref="JeroMQAppender"/>
28 </Root>
29 </Loggers>
30 </Configuration>
0 <?xml version="1.0" encoding="UTF-8"?>
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 <Configuration name="JeroMQAppenderTest" status="all">
18 <Appenders>
19 <JeroMQ name="JeroMQAppender">
20 <Property name="endpoint">tcp://*:5556</Property>
21 <Property name="endpoint">ipc://info-topic</Property>
22 <PatternLayout pattern="%X{foo}%m"/>
23 </JeroMQ>
24 </Appenders>
25 <Loggers>
26 <Root level="info">
27 <AppenderRef ref="JeroMQAppender"/>
28 </Root>
29 </Loggers>
30 </Configuration>
0 <?xml version="1.0" encoding="UTF-8"?>
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 <Configuration status="ERROR">
18 <Properties>
19 <Property name="emptyElementKey" />
20 <Property name="emptyAttributeKey" value="" />
21 <Property name="emptyAttributeKey2" value=""></Property>
22 <Property name="elementKey">elementValue</Property>
23 <Property name="attributeKey" value="attributeValue" />
24 <Property name="attributeWithEmptyElementKey" value="attributeValue2"></Property>
25 <Property name="bothElementAndAttributeKey" value="attributeValue3">elementValue3</Property>
26 </Properties>
27 <Appenders>
28 <List name="List">
29 <PatternLayout pattern="1=${sys:elementKey},2=${sys:emptyElementKey},a=${sys:emptyAttributeKey},b=${sys:emptyAttributeKey2},3=${sys:attributeKey},4=${sys:attributeWithEmptyElementKey},5=${sys:bothElementAndAttributeKey},m=%m" />
30 </List>
31 </Appenders>
32 <Loggers>
33 <Root level="trace">
34 <AppenderRef ref="List" />
35 </Root>
36 </Loggers>
37 </Configuration>
11 <Configuration status="OFF">
22 <Appenders>
33 <Console name="Console" target="SYSTEM_OUT">
4 <PatternLayout pattern="%p %c{1.} [%t] %X{aKey} %m%ex%n" />
4 <PatternLayout pattern="%p %c{1.} [%t] %X{aKey} %X %m%ex%n" />
55 </Console>
66 <File name="File" fileName="target/gcfreefile.log" bufferedIO="false">
77 <PatternLayout>
8 <Pattern>%d %p %c{1.} [%t] %m%n</Pattern>
8 <Pattern>%d{DEFAULT}{UTC} %p %c{1.} [%t] %m%n %highlight{%style{%d}{bright,cyan} %p %c{1.} [%t] %m%n}</Pattern>
99 </PatternLayout>
1010 </File>
1111 <RollingFile name="RollingFile" fileName="target/gcfreeRollingFile.log"
1212 filePattern="target/gcfree-%d{MM-dd-yy-HH-mm-ss}.log.gz">
1313 <PatternLayout>
14 <Pattern>%d %p %c{1.} [%t] %m%n</Pattern>
14 <Pattern>%d{yyyy-MM-dd'T'HH:mm:ss,SSS}{UTC} %p %c{1.} [%t] %m%n %highlight{%style{%d}{bright,cyan} %p %c{1.} [%t] %m%n}</Pattern>
1515 </PatternLayout>
1616 <Policies>
1717 <SizeBasedTriggeringPolicy size="50M" />
1919 </RollingFile>
2020 <RandomAccessFile name="RandomAccessFile" fileName="target/gcfreeRAF.log" immediateFlush="false" append="false">
2121 <PatternLayout>
22 <Pattern>%d %p %c{1.} [%t] %X{aKey} %m %ex%n</Pattern>
22 <Pattern>%d{yyyy-MM-dd'T'HH:mm:ss.SSS}{UTC} %p %c{1.} [%t] %X{aKey} %m %ex%n %highlight{%style{%d}{bright,cyan} %p %c{1.} [%t] %X{aKey} %m %ex%n}</Pattern>
2323 </PatternLayout>
2424 </RandomAccessFile>
2525 <RollingRandomAccessFile name="RollingRandomAccessFile"
2727 filePattern="target/afterRollover-%i.log" append="false"
2828 immediateFlush="false">
2929 <PatternLayout>
30 <Pattern>%d %p %c{1.} [%t] %X{aKey} %m %location %ex%n</Pattern>
30 <Pattern>%d{DEFAULT}{UTC} %p %c{1.} [%t] %X{aKey} %m %location %ex%n %highlight{%style{%d}{bright,cyan} %p %c{1.} [%t] %X{aKey} %m %location %ex%n}</Pattern>
3131 </PatternLayout>
3232 <Policies>
3333 <SizeBasedTriggeringPolicy size="50 M"/>
3737 fileName="target/gcfreemmap.log"
3838 immediateFlush="false" append="false">
3939 <PatternLayout>
40 <Pattern>%d %p %c{1.} [%t] %X{aKey} %m%ex%n</Pattern>
40 <Pattern>%d{DEFAULT}{UTC} %p %c{1.} [%t] %X{aKey} %m%ex%n</Pattern>
41 <Pattern>%highlight{%style{%d}{bright,cyan} %p %c{1.} [%t] %X{aKey} %m%ex%n}</Pattern>
4142 </PatternLayout>
4243 </MemoryMappedFile>
4344 <RandomAccessFile name="RandomAccessFileGelf" fileName="target/gcfree.json" immediateFlush="false" append="false">
4546 </RandomAccessFile>
4647 </Appenders>
4748 <Loggers>
48 <Root level="info" includeLocation="false">
49 <Root level="trace" includeLocation="false">
50 <Property name="prop1">value1</Property>
51 <Property name="prop2">value2</Property>
4952 <appender-ref ref="Console" level="FATAL" />
5053 <appender-ref ref="File"/>
5154 <appender-ref ref="RandomAccessFile"/>
11 <Configuration status="OFF">
22 <Appenders>
33 <Console name="Console" target="SYSTEM_OUT">
4 <PatternLayout pattern="%p %c{1.} [%t] %X{aKey} %m%ex%n" />
4 <PatternLayout pattern="%p %c{1.} [%t] %X{aKey} %X %m%ex%n" />
55 </Console>
66 <File name="File" fileName="target/gcfreefileMixed.log" bufferedIO="false">
77 <PatternLayout>
8 <Pattern>%d %p %c{1.} [%t] %m%n</Pattern>
8 <Pattern>%d{yyyy-MM-dd'T'HH:mm:ss,SSS}{UTC} %p %c{1.} [%t] %m%n %highlight{%style{%d}{bright,cyan} %p %c{1.} [%t] %m%n}</Pattern>
99 </PatternLayout>
1010 </File>
1111 <RollingFile name="RollingFile" fileName="target/gcfreeRollingFileMixed.log"
1212 filePattern="target/gcfree-%d{MM-dd-yy-HH-mm-ss}.log.gz">
1313 <PatternLayout>
14 <Pattern>%d %p %c{1.} [%t] %m%n</Pattern>
14 <Pattern>%d{yyyy-MM-dd'T'HH:mm:ss.SSS}{UTC} %p %c{1.} [%t] %m%n %highlight{%style{%d}{bright,cyan} %p %c{1.} [%t] %m%n}</Pattern>
1515 </PatternLayout>
1616 <Policies>
1717 <SizeBasedTriggeringPolicy size="50M" />
1919 </RollingFile>
2020 <RandomAccessFile name="RandomAccessFile" fileName="target/gcfreeRAFMixed.log" immediateFlush="false" append="false">
2121 <PatternLayout>
22 <Pattern>%d %p %c{1.} [%t] %X{aKey} %m %ex%n</Pattern>
22 <Pattern>%d{DEFAULT}{UTC} %p %c{1.} [%t] %X{aKey} %m %ex%n %highlight{%style{%d}{bright,cyan} %p %c{1.} [%t] %X{aKey} %m %ex%n}</Pattern>
2323 </PatternLayout>
2424 </RandomAccessFile>
2525 <RollingRandomAccessFile name="RollingRandomAccessFile"
2727 filePattern="target/afterRollover-%i.log" append="false"
2828 immediateFlush="false">
2929 <PatternLayout>
30 <Pattern>%d %p %c{1.} [%t] %X{aKey} %m %location %ex%n</Pattern>
30 <Pattern>%d{DEFAULT}{UTC} %p %c{1.} [%t] %X{aKey} %m %location %ex%n %highlight{%style{%d}{bright,cyan} %p %c{1.} [%t] %X{aKey} %m %location %ex%n}</Pattern>
3131 </PatternLayout>
3232 <Policies>
3333 <SizeBasedTriggeringPolicy size="50 M"/>
3737 fileName="target/gcfreemmapMixed.log"
3838 immediateFlush="false" append="false">
3939 <PatternLayout>
40 <Pattern>%d %p %c{1.} [%t] %X{aKey} %m%ex%n</Pattern>
40 <Pattern>%d{DEFAULT}{UTC} %p %c{1.} [%t] %X{aKey} %m%ex%n %highlight{%style{%d}{bright,cyan} %p %c{1.} [%t] %X{aKey} %m%ex%n}</Pattern>
4141 </PatternLayout>
4242 </MemoryMappedFile>
4343 <RandomAccessFile name="RandomAccessFileGelf" fileName="target/gcfreeMixed.json" immediateFlush="false" append="false">
4646 </Appenders>
4747 <Loggers>
4848 <AsyncLogger name="org.apache.logging.log4j.core.GcFreeMixedSyncAyncLoggingTest"
49 level="info" includeLocation="false">
49 level="trace" includeLocation="false">
50 <Property name="prop1">value1</Property>
51 <Property name="prop2">value2</Property>
5052 <appender-ref ref="Console" level="FATAL" />
5153 <appender-ref ref="File"/>
5254 <appender-ref ref="RandomAccessFile"/>
5658 <appender-ref ref="MemoryMappedFile"/>
5759 <appender-ref ref="RandomAccessFileGelf"/>
5860 </AsyncLogger>
59 <Root level="info" includeLocation="false">
61 <Root level="trace" includeLocation="false">
62 <Property name="prop1">value1</Property>
63 <Property name="prop2">value2</Property>
6064 <appender-ref ref="Console" level="FATAL" />
6165 <appender-ref ref="File"/>
6266 <appender-ref ref="RandomAccessFile"/>
3131 </PatternLayout>
3232 </File>
3333 <Socket name="Socket1" host="localhost" port="5560" protocol="TCP" ignoreExceptions="false"
34 reconnectionDelay="250" advertise="true">
34 reconnectionDelayMillis="250" advertise="true">
3535 <PatternLayout pattern="%msg%n"/>
3636 </Socket>
3737 <Socket name="Socket2" host="localhost" port="5565" protocol="UDP" ignoreExceptions="false"
38 reconnectionDelay="250">
38 reconnectionDelayMillis="250">
3939 <PatternLayout pattern="%msg%n"/>
4040 </Socket>
4141 </Appenders>
0 <?xml version="1.0" encoding="UTF-8"?>
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 <Configuration status="WARN" name="RoutingTest">
18 <Appenders>
19 <ScriptAppenderSelector name="SelectIt">
20 <Script language="groovy"><![CDATA[
21 return "OSNameFoo".contains("Foo") ? "List2": "List1";]]>
22 </Script>
23 <AppenderSet>
24 <List name="List1" />
25 <List name="List2" />
26 </AppenderSet>
27 </ScriptAppenderSelector>
28 </Appenders>
29 <Loggers>
30 <Root level="error">
31 <AppenderRef ref="SelectIt" />
32 </Root>
33 </Loggers>
34 </Configuration>
0 <?xml version="1.0" encoding="UTF-8"?>
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 <Configuration status="WARN" name="RoutingTest">
18 <Appenders>
19 <ScriptAppenderSelector name="SelectIt">
20 <Script language="JavaScript"><![CDATA[
21 "OSNameFoo".search("Foo") > -1 ? "List2" : "List1";]]>
22 </Script>
23 <AppenderSet>
24 <List name="List1" />
25 <List name="List2" />
26 </AppenderSet>
27 </ScriptAppenderSelector>
28 </Appenders>
29 <Loggers>
30 <Root level="error">
31 <AppenderRef ref="SelectIt" />
32 </Root>
33 </Loggers>
34 </Configuration>
2323 </Console>
2424 <Block name="Block">
2525 </Block>
26 <Async name="Async" bufferSize="3" includeLocation="false" error-ref="STDOUT">
26 <Async name="Async" bufferSize="4" includeLocation="false" error-ref="STDOUT">
2727 <AppenderRef ref="Block"/>
2828 </Async>
2929 </Appenders>
3434 </Root>
3535 </Loggers>
3636
37 </Configuration>
37 </Configuration>
0 {
1 "Configuration" : {
2 "status": "error",
3 "name": "LoggerConfigTest",
4 "properties" : {
5 "property" : [{
6 "name" : "filename",
7 "value": "target/composite.log"
8 }]
9 },
10 "Loggers" : {
11 "logger" : [
12 {
13 "name" : "cat2",
14 "level" : "info",
15 "additivity" : true,
16 "AppenderRef" : {
17 "ref" : "File"
18 }
19
20 },
21 {
22 "name" : "cat3",
23 "level" : "error",
24 "AppenderRef" : {
25 "ref" : "STDOUT"
26 }
27 }
28 ],
29 "Root" : {
30 "level" : "warn",
31 "AppenderRef" : [{
32 "ref" : "File"
33 }]
34 }
35 }
36 }
37 }
0 <?xml version="1.0" encoding="UTF-8"?>
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 <Configuration status="ERROR" name="LoggerConfigTest">
19 <Appenders>
20 <Console name="STDOUT">
21 <PatternLayout pattern="%m%n"/>
22 </Console>
23 <File name="File" fileName="${filename}" bufferedIO="false">
24 <PatternLayout>
25 <Pattern>%d %p %C{1.} [%t] %m%n</Pattern>
26 </PatternLayout>
27 </File>
28 </Appenders>
29
30 <Loggers>
31 <Logger name="cat1" level="debug" additivity="false">
32 <AppenderRef ref="File"/>
33 </Logger>
34
35 <Logger name="cat2" level="debug" additivity="false">
36 <AppenderRef ref="File"/>
37 </Logger>
38 <Root>
39 <AppenderRef ref="STDOUT" />
40 </Root>
41 </Loggers>
42
43 </Configuration>
0 <?xml version="1.0" encoding="UTF-8"?>
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 <Configuration status="ERROR" name="LoggerConfigTest">
19 <Appenders>
20 <Console name="STDOUT">
21 <PatternLayout pattern="%m%n"/>
22 </Console>
23 <File name="File" fileName="${filename}" bufferedIO="false">
24 <PatternLayout>
25 <Pattern>%d %p %C{1.} [%t] %m%n</Pattern>
26 </PatternLayout>
27 </File>
28 </Appenders>
29
30 <Loggers>
31 <Logger name="cat1" level="debug" additivity="false">
32 <AppenderRef ref="File"/>
33 </Logger>
34
35 <Logger name="cat3" level="debug" additivity="false">
36 <AppenderRef ref="File"/>
37 </Logger>
38
39 <Root level="error">
40 <AppenderRef ref="STDOUT"/>
41 <Property name="hostname">server1</Property>
42 </Root>
43 </Loggers>
44
45 </Configuration>
0 <?xml version="1.0" encoding="UTF-8"?>
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 <Configuration status="WARN" name="XMLConfigTest">
18 <Appenders>
19 <Console name="STDOUT">
20 <PatternLayout pattern="%d %-5level [%t][%logger]%notEmpty{[%markerSimpleName]} %msg%n%xThrowable" />
21 </Console>
22 </Appenders>
23 <Loggers>
24 <Root level="debug">
25 <AppenderRef ref="STDOUT" />
26 </Root>
27 </Loggers>
28 </Configuration>
1616
1717 -->
1818 <Configuration status="OFF" name="XMLConfigTest">
19
20 <CustomLevels>
21 <CustomLevel name="NOTE" intLevel="350"/>
22 <CustomLevel name="DETAIL" intLevel="450"/>
23 </CustomLevels>
1924
2025 <Appenders>
2126 <Console name="STDOUT">
4449 </Root>
4550 </Loggers>
4651
47 </Configuration>
52 </Configuration>
0 <?xml version="1.0" encoding="UTF-8"?>
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 <Configuration status="warn" name="CsvJsonParameterLayoutFileAppenderTest">
18 <Appenders>
19 <File name="File" fileName="target/CsvJsonParameterLayoutFileAppenderTest.log" bufferedIO="false">
20 <CsvParameterLayout delimiter=",">
21 </CsvParameterLayout>
22 </File>
23 </Appenders>
24
25 <Loggers>
26 <Root level="error">
27 <AppenderRef ref="File"/>
28 </Root>
29 </Loggers>
30
31 </Configuration>
0 <?xml version="1.0" encoding="UTF-8"?>
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 <Configuration status="INFO" name="TestEmpty">
19 </Configuration>
0 <?xml version="1.0" encoding="UTF-8"?>
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 <Configuration status="WARN">
18 <Appenders>
19 <List name="List">
20 <PatternLayout pattern="[%-5level] %c{1.} %msg{ansi}{nolookups}%n" />
21 </List>
22 </Appenders>
23 <Loggers>
24 <Root level="debug">
25 <AppenderRef ref="List" />
26 </Root>
27 </Loggers>
28 </Configuration>
1717 <Configuration status="OFF" strict="false" name="DSI">
1818 <Properties>
1919 <Property name="test2">test2default</Property>
20 <Property name="attribKey" value="attribValue" />
21 <Property name="duplicateKey" value="attribValue">nodeValue</Property>
2022 </Properties>
2123 <Appenders>
2224 <List name="List">
23 <PatternLayout pattern="[%-5level] %c{1.} user=%X{user} phrasex=%X{phrasex} test=%X{test} test2=$${sys:test2} test3=$${sys:test3:-Unknown} %msg%n" />
25 <PatternLayout pattern="[%-5level] %c{1.} user=%X{user} phrasex=%X{phrasex} test=%X{test} test2=$${sys:test2} test3=$${sys:test3:-Unknown} attribKey=$${attribKey} duplicateKey=$${duplicateKey}%msg%n" />
2426 </List>
2527 </Appenders>
2628
0 <?xml version="1.0" encoding="UTF-8"?>
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 <Configuration status="OFF" name="StyleTest">
19 <Appenders>
20 <List name="List">
21 <PatternLayout>
22 <Pattern>%message{ansi}%n</Pattern>
23 </PatternLayout>
24 </List>
25 </Appenders>
26
27 <Loggers>
28 <Root level="trace">
29 <AppenderRef ref="List"/>
30 </Root>
31 </Loggers>
32
33 </Configuration>
0 <?xml version="1.0" encoding="UTF-8"?>
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 <Configuration status="OFF" name="StyledTest">
19 <Appenders>
20 <List name="List">
21 <PatternLayout>
22 <Pattern>%message{ansi}{WarningStyle=red,bold KeyStyle=white ValueStyle=blue}%n</Pattern>
23 </PatternLayout>
24 </List>
25 </Appenders>
26
27 <Loggers>
28 <Root level="trace">
29 <AppenderRef ref="List"/>
30 </Root>
31 </Loggers>
32
33 </Configuration>
0 <?xml version="1.0" encoding="UTF-8"?>
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 <Configuration status="OFF" name="XMLConfigTest">
19 <Properties>
20 <Property name="filename">target/rolling1/rollingtest.log</Property>
21 </Properties>
22 <ThresholdFilter level="debug"/>
23
24 <Appenders>
25 <Console name="STDOUT">
26 <PatternLayout pattern="%m%n"/>
27 </Console>
28 <RollingFile name="RollingFile" fileName="${filename}"
29 filePattern="target/rolling1/test1-$${date:MM-dd-yyyy}-%i.log.7z"
30 createOnDemand="true">
31 <PatternLayout>
32 <Pattern>%d %p %C{1.} [%t] %m%n</Pattern>
33 </PatternLayout>
34 <SizeBasedTriggeringPolicy size="500" />
35 </RollingFile>
36 <List name="List">
37 <ThresholdFilter level="error"/>
38 </List>
39 </Appenders>
40
41 <Loggers>
42 <Logger name="org.apache.logging.log4j.test1" level="debug" additivity="false">
43 <ThreadContextMapFilter>
44 <KeyValuePair key="test" value="123"/>
45 </ThreadContextMapFilter>
46 <AppenderRef ref="STDOUT"/>
47 </Logger>>
48
49 <Logger name="org.apache.logging.log4j.core.appender.rolling" level="debug" additivity="false">
50 <AppenderRef ref="RollingFile"/>
51 </Logger>>
52
53 <Root level="error">
54 <AppenderRef ref="STDOUT"/>
55 </Root>
56 </Loggers>
57
58 </Configuration>
0 <?xml version="1.0" encoding="UTF-8"?>
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 <Configuration status="OFF" name="XMLConfigTest">
19 <Properties>
20 <Property name="filename">target/rolling1/rollingtest.log</Property>
21 </Properties>
22 <ThresholdFilter level="debug"/>
23
24 <Appenders>
25 <Console name="STDOUT">
26 <PatternLayout pattern="%m%n"/>
27 </Console>
28 <RollingFile name="RollingFile" fileName="${filename}"
29 filePattern="target/rolling1/test1-$${date:MM-dd-yyyy}-%i.log.bz2"
30 createOnDemand="true">
31 <PatternLayout>
32 <Pattern>%d %p %C{1.} [%t] %m%n</Pattern>
33 </PatternLayout>
34 <SizeBasedTriggeringPolicy size="500" />
35 <DefaultRolloverStrategy compressionLevel="9" />
36 </RollingFile>
37 <List name="List">
38 <ThresholdFilter level="error"/>
39 </List>
40 </Appenders>
41
42 <Loggers>
43 <Logger name="org.apache.logging.log4j.test1" level="debug" additivity="false">
44 <ThreadContextMapFilter>
45 <KeyValuePair key="test" value="123"/>
46 </ThreadContextMapFilter>
47 <AppenderRef ref="STDOUT"/>
48 </Logger>>
49
50 <Logger name="org.apache.logging.log4j.core.appender.rolling" level="debug" additivity="false">
51 <AppenderRef ref="RollingFile"/>
52 </Logger>>
53
54 <Root level="error">
55 <AppenderRef ref="STDOUT"/>
56 </Root>
57 </Loggers>
58
59 </Configuration>
0 <?xml version="1.0" encoding="UTF-8"?>
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 <Configuration status="ERROR" name="RollingCronTestOnceADay">
19 <Properties>
20 <Property name="filename">target/rolling-cron-once-a-day/rollingtest.log</Property>
21 </Properties>
22
23 <Appenders>
24 <Console name="STDOUT" target="SYSTEM_OUT">
25 <PatternLayout pattern="%p %C{1.} [%t] %m%n"/>
26 </Console>
27 <RollingFile name="RollingFile"
28 fileName="${filename}"
29 filePattern="target/rolling-cron-once-a-day/rollingtest-%d{yyyyMMdd}_%d{HHmmss}-%i.log.gz"
30 immediateFlush="true">
31 <PatternLayout pattern="%d %p %C{1.} [%t] %m%n" />
32 <CronTriggeringPolicy schedule="@CRON_EXPR@"/>
33 </RollingFile>
34 </Appenders>
35
36 <Loggers>
37 <Logger name="org.apache.logging.log4j.core.appender.rolling" level="DEBUG" additivity="false">
38 <AppenderRef ref="RollingFile"/>
39 </Logger>
40
41 <Root level="ERROR">
42 <AppenderRef ref="STDOUT"/>
43 </Root>
44 </Loggers>
45
46 </Configuration>
4343 <Loggers>
4444 <Logger name="org.apache.logging.log4j.core.appender.rolling" level="debug" additivity="false">
4545 <AppenderRef ref="RollingFile"/>
46 </Logger>>
46 </Logger>
4747
4848 <Root level="error">
4949 <AppenderRef ref="STDOUT"/>
4343 <Loggers>
4444 <Logger name="org.apache.logging.log4j.core.appender.rolling" level="debug" additivity="false">
4545 <AppenderRef ref="RollingFile"/>
46 </Logger>>
46 </Logger>
4747
4848 <Root level="error">
4949 <AppenderRef ref="STDOUT"/>
0 <?xml version="1.0" encoding="UTF-8"?>
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 <Configuration status="OFF" name="XMLConfigTest">
19 <Properties>
20 <Property name="filename">target/rolling1/rollingtest.log</Property>
21 </Properties>
22 <ThresholdFilter level="debug"/>
23
24 <Appenders>
25 <Console name="STDOUT">
26 <PatternLayout pattern="%m%n"/>
27 </Console>
28 <RollingFile name="RollingFile" fileName="${filename}"
29 filePattern="target/rolling1/test1-$${date:MM-dd-yyyy}-%i.log.deflate"
30 createOnDemand="true">
31 <PatternLayout>
32 <Pattern>%d %p %C{1.} [%t] %m%n</Pattern>
33 </PatternLayout>
34 <SizeBasedTriggeringPolicy size="500" />
35 <DefaultRolloverStrategy compressionLevel="9" />
36 </RollingFile>
37 <List name="List">
38 <ThresholdFilter level="error"/>
39 </List>
40 </Appenders>
41
42 <Loggers>
43 <Logger name="org.apache.logging.log4j.test1" level="debug" additivity="false">
44 <ThreadContextMapFilter>
45 <KeyValuePair key="test" value="123"/>
46 </ThreadContextMapFilter>
47 <AppenderRef ref="STDOUT"/>
48 </Logger>>
49
50 <Logger name="org.apache.logging.log4j.core.appender.rolling" level="debug" additivity="false">
51 <AppenderRef ref="RollingFile"/>
52 </Logger>>
53
54 <Root level="error">
55 <AppenderRef ref="STDOUT"/>
56 </Root>
57 </Loggers>
58
59 </Configuration>
0 <?xml version="1.0" encoding="UTF-8"?>
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 <Configuration status="OFF" name="XMLConfigTest">
19 <Properties>
20 <Property name="filename">target/rolling1/rollingtest.log</Property>
21 </Properties>
22 <ThresholdFilter level="debug"/>
23
24 <Appenders>
25 <Console name="STDOUT">
26 <PatternLayout pattern="%m%n"/>
27 </Console>
28 <RollingFile name="RollingFile" fileName="${filename}"
29 filePattern="target/rolling1/test1-$${date:MM-dd-yyyy}-%i.log.gz"
30 createOnDemand="true">
31 <PatternLayout>
32 <Pattern>%d %p %C{1.} [%t] %m%n</Pattern>
33 </PatternLayout>
34 <SizeBasedTriggeringPolicy size="500" />
35 </RollingFile>
36 <List name="List">
37 <ThresholdFilter level="error"/>
38 </List>
39 </Appenders>
40
41 <Loggers>
42 <Logger name="org.apache.logging.log4j.test1" level="debug" additivity="false">
43 <ThreadContextMapFilter>
44 <KeyValuePair key="test" value="123"/>
45 </ThreadContextMapFilter>
46 <AppenderRef ref="STDOUT"/>
47 </Logger>>
48
49 <Logger name="org.apache.logging.log4j.core.appender.rolling" level="debug" additivity="false">
50 <AppenderRef ref="RollingFile"/>
51 </Logger>>
52
53 <Root level="error">
54 <AppenderRef ref="STDOUT"/>
55 </Root>
56 </Loggers>
57
58 </Configuration>
0 <?xml version="1.0" encoding="UTF-8"?>
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 <Configuration status="OFF" name="XMLConfigTest">
19 <Properties>
20 <Property name="filename">target/rolling1/rollingtest.log</Property>
21 </Properties>
22 <ThresholdFilter level="debug"/>
23
24 <Appenders>
25 <Console name="STDOUT">
26 <PatternLayout pattern="%m%n"/>
27 </Console>
28 <RollingFile name="RollingFile" fileName="${filename}"
29 filePattern="target/rolling1/test1-$${date:MM-dd-yyyy}-%i.log.pack200"
30 createOnDemand="true">
31 <PatternLayout>
32 <Pattern>%d %p %C{1.} [%t] %m%n</Pattern>
33 </PatternLayout>
34 <SizeBasedTriggeringPolicy size="500" />
35 <DefaultRolloverStrategy compressionLevel="9" />
36 </RollingFile>
37 <List name="List">
38 <ThresholdFilter level="error"/>
39 </List>
40 </Appenders>
41
42 <Loggers>
43 <Logger name="org.apache.logging.log4j.test1" level="debug" additivity="false">
44 <ThreadContextMapFilter>
45 <KeyValuePair key="test" value="123"/>
46 </ThreadContextMapFilter>
47 <AppenderRef ref="STDOUT"/>
48 </Logger>>
49
50 <Logger name="org.apache.logging.log4j.core.appender.rolling" level="debug" additivity="false">
51 <AppenderRef ref="RollingFile"/>
52 </Logger>>
53
54 <Root level="error">
55 <AppenderRef ref="STDOUT"/>
56 </Root>
57 </Loggers>
58
59 </Configuration>
0 <?xml version="1.0" encoding="UTF-8"?>
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 <Configuration status="OFF" name="XMLConfigTest">
19 <Properties>
20 <Property name="filename">target/rolling1/rollingtest.log</Property>
21 </Properties>
22 <ThresholdFilter level="debug"/>
23
24 <Appenders>
25 <Console name="STDOUT">
26 <PatternLayout pattern="%m%n"/>
27 </Console>
28 <RollingFile name="RollingFile" fileName="${filename}"
29 filePattern="target/rolling1/test1-$${date:MM-dd-yyyy}-%i.log.xz"
30 createOnDemand="true">
31 <PatternLayout>
32 <Pattern>%d %p %C{1.} [%t] %m%n</Pattern>
33 </PatternLayout>
34 <SizeBasedTriggeringPolicy size="500" />
35 <DefaultRolloverStrategy compressionLevel="9" />
36 </RollingFile>
37 <List name="List">
38 <ThresholdFilter level="error"/>
39 </List>
40 </Appenders>
41
42 <Loggers>
43 <Logger name="org.apache.logging.log4j.test1" level="debug" additivity="false">
44 <ThreadContextMapFilter>
45 <KeyValuePair key="test" value="123"/>
46 </ThreadContextMapFilter>
47 <AppenderRef ref="STDOUT"/>
48 </Logger>>
49
50 <Logger name="org.apache.logging.log4j.core.appender.rolling" level="debug" additivity="false">
51 <AppenderRef ref="RollingFile"/>
52 </Logger>>
53
54 <Root level="error">
55 <AppenderRef ref="STDOUT"/>
56 </Root>
57 </Loggers>
58
59 </Configuration>
0 <?xml version="1.0" encoding="UTF-8"?>
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 <Configuration status="OFF" name="XMLConfigTest">
19 <Properties>
20 <Property name="filename">target/rolling1/rollingtest.log</Property>
21 </Properties>
22 <ThresholdFilter level="debug"/>
23
24 <Appenders>
25 <Console name="STDOUT">
26 <PatternLayout pattern="%m%n"/>
27 </Console>
28 <RollingFile name="RollingFile" fileName="${filename}"
29 filePattern="target/rolling1/test1-$${date:MM-dd-yyyy}-%i.log.zip"
30 createOnDemand="true">
31 <PatternLayout>
32 <Pattern>%d %p %C{1.} [%t] %m%n</Pattern>
33 </PatternLayout>
34 <SizeBasedTriggeringPolicy size="500" />
35 <DefaultRolloverStrategy compressionLevel="9" />
36 </RollingFile>
37 <List name="List">
38 <ThresholdFilter level="error"/>
39 </List>
40 </Appenders>
41
42 <Loggers>
43 <Logger name="org.apache.logging.log4j.test1" level="debug" additivity="false">
44 <ThreadContextMapFilter>
45 <KeyValuePair key="test" value="123"/>
46 </ThreadContextMapFilter>
47 <AppenderRef ref="STDOUT"/>
48 </Logger>>
49
50 <Logger name="org.apache.logging.log4j.core.appender.rolling" level="debug" additivity="false">
51 <AppenderRef ref="RollingFile"/>
52 </Logger>>
53
54 <Root level="error">
55 <AppenderRef ref="STDOUT"/>
56 </Root>
57 </Loggers>
58
59 </Configuration>
0 <?xml version="1.0" encoding="UTF-8"?>
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 <Configuration status="WARN" name="RoutingTest">
19 <Appenders>
20 <Routing name="Routing">
21 <Script name="RoutingInit" language="groovy"><![CDATA[
22 return "OSNameFoo".contains("Foo") ? "Service2": "Service1";]]>
23 </Script>
24 <Routes>
25 <Route key="Service1">
26 <List name="List1" />
27 </Route>
28 <Route key="Service2">
29 <List name="List2" />
30 </Route>
31 </Routes>
32 </Routing>
33 </Appenders>
34 <Loggers>
35 <Root level="error">
36 <AppenderRef ref="Routing" />
37 </Root>
38 </Loggers>
39 </Configuration>
0 <?xml version="1.0" encoding="UTF-8"?>
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 <Configuration status="WARN" name="RoutingTest">
19 <Appenders>
20 <Routing name="Routing">
21 <Script name="RoutingInit" language="JavaScript"><![CDATA[
22 "OSNameFoo".search("Foo") > -1 ? "Service2" : "Service1";]]>
23 </Script>
24 <Routes>
25 <Route key="Service1">
26 <List name="List1" />
27 </Route>
28 <Route key="Service2">
29 <List name="List2" />
30 </Route>
31 </Routes>
32 </Routing>
33 </Appenders>
34 <Loggers>
35 <Root level="error">
36 <AppenderRef ref="Routing" />
37 </Root>
38 </Loggers>
39 </Configuration>
0 <?xml version="1.0" encoding="UTF-8"?>
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 <Configuration status="WARN" name="RoutingTest">
19 <Appenders>
20 <Routing name="Routing">
21 <Routes>
22 <Script name="RoutesInit" language="groovy"><![CDATA[
23 return "OSNameFoo".contains("Foo") ? "Service2": "Service1";]]>
24 </Script>
25 <Route key="Service1">
26 <List name="List1" />
27 </Route>
28 <Route key="Service2">
29 <List name="List2" />
30 </Route>
31 </Routes>
32 </Routing>
33 </Appenders>
34 <Loggers>
35 <Root level="error">
36 <AppenderRef ref="Routing" />
37 </Root>
38 </Loggers>
39 </Configuration>
0 <?xml version="1.0" encoding="UTF-8"?>
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 <Configuration status="WARN" name="RoutingTest">
19 <Appenders>
20 <Routing name="Routing">
21 <Routes>
22 <Script name="RoutesInit" language="JavaScript"><![CDATA[
23 "OSNameFoo".search("Foo") > -1 ? "Service2" : "Service1";]]>
24 </Script>
25 <Route key="Service1">
26 <List name="List1" />
27 </Route>
28 <Route key="Service2">
29 <List name="List2" />
30 </Route>
31 </Routes>
32 </Routing>
33 </Appenders>
34 <Loggers>
35 <Root level="error">
36 <AppenderRef ref="Routing" />
37 </Root>
38 </Loggers>
39 </Configuration>
0 <?xml version="1.0" encoding="UTF-8"?>
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 <Configuration status="WARN" name="RoutingTest">
19 <Appenders>
20 <Routing name="Routing">
21 <Script name="RoutingInit" language="groovy"><![CDATA[
22 staticVariables.put("TestKey", "TestValue1");
23 return "OSNameFoo".contains("Foo") ? "Service2": "Service1";]]>
24 </Script>
25 <Routes>
26 <Script name="RoutesInit" language="groovy"><![CDATA[
27 if (staticVariables.containsKey("TestKey")) {
28 staticVariables.put("TestKey", "TestValue2");
29 }
30 if (logEvent.getMarker() != null) {
31 staticVariables.put("MarkerName", logEvent.getMarker().getName());
32 }
33 return "OSNameFoo".contains("Foo") ? "Service2": "Service1";]]>
34 </Script>
35 <Route key="Service1">
36 <List name="List1" />
37 </Route>
38 <Route key="Service2">
39 <List name="List2" />
40 </Route>
41 </Routes>
42 </Routing>
43 </Appenders>
44 <Loggers>
45 <Root level="error">
46 <AppenderRef ref="Routing" />
47 </Root>
48 </Loggers>
49 </Configuration>
0 <?xml version="1.0" encoding="UTF-8"?>
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 <Configuration status="WARN" name="RoutingTest">
19 <Appenders>
20 <Routing name="Routing">
21 <Script name="RoutingInit" language="JavaScript"><![CDATA[
22 staticVariables.put("TestKey", "TestValue1");
23 "OSNameFoo".search("Foo") > -1 ? "Service2" : "Service1";]]>
24 </Script>
25 <Routes>
26 <Script name="RoutesInit" language="JavaScript"><![CDATA[
27 if (staticVariables.containsKey("TestKey")) {
28 staticVariables.put("TestKey", "TestValue2");
29 }
30 if (logEvent.getMarker() != null) {
31 staticVariables.put("MarkerName", logEvent.getMarker().getName());
32 }
33 "OSNameFoo".search("Foo") > -1 ? "Service2" : "Service1";]]>
34 </Script>
35 <Route key="Service1">
36 <List name="List1" />
37 </Route>
38 <Route key="Service2">
39 <List name="List2" />
40 </Route>
41 </Routes>
42 </Routing>
43 </Appenders>
44 <Loggers>
45 <Root level="error">
46 <AppenderRef ref="Routing" />
47 </Root>
48 </Loggers>
49 </Configuration>
1919 <Appenders>
2020 <List name="List">
2121 <PatternLayout>
22 <Pattern>%d %highlight{%p} %style{%logger}{bright,cyan} %C{1.} %msg%n</Pattern>
22 <Pattern>%d %highlight{%p} %style{%logger}{bright,cyan}%style{}{bright,cyan} %C{1.} %msg%n</Pattern>
2323 </PatternLayout>
2424 </List>
2525 </Appenders>
3030 </Root>
3131 </Loggers>
3232
33 </Configuration>
33 </Configuration>
0 <?xml version="1.0" encoding="UTF-8"?>
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 <Configuration status="OFF" name="NestedLoggingInToString">
19
20 <Appenders>
21 <Console name="STDOUT">
22 <PatternLayout pattern="%c %m%n"/>
23 </Console>
24 <List name="List">
25 <PatternLayout pattern="%level %logger %m"/>
26 </List>
27 </Appenders>
28
29 <Loggers>
30 <Root level="trace">
31 <AppenderRef ref="List"/>
32 </Root>
33 </Loggers>
34 </Configuration>
0 <?xml version="1.0" encoding="UTF-8"?>
1 <Configuration status="warn" name="MyApp" packages="">
2 <Properties>
3 <Property name="audit-path">target/log4j2-1482</Property>
4 <Property name="file-name">audit</Property>
5 <Property name="file-header">param1,param2,param3${sys:line.separator}
6 </Property>
7 </Properties>
8
9 <Appenders>
10 <RollingFile name="auditfile" fileName="${audit-path}/${file-name}.tmp"
11 filePattern="${audit-path}/${file-name}-%d{yyyy-MM-dd}-%i.csv">
12 <CsvParameterLayout delimiter="," header="${file-header}">
13 </CsvParameterLayout>
14 <Policies>
15 <SizeBasedTriggeringPolicy size="80 B" />
16 </Policies>
17 <DefaultRolloverStrategy max="2" />
18 </RollingFile>
19 </Appenders>
20
21 <Loggers>
22 <Root level="info">
23 <AppenderRef ref="auditfile" />
24 </Root>
25 </Loggers>
26 </Configuration>
0 <?xml version="1.0" encoding="UTF-8"?>
1 <Configuration status="warn">
2 <Appenders>
3 <Console name="myConsole" target="SYSTEM_OUT"/>
4 <Async name="myConsoleAsync">
5 <AppenderRef ref="myConsole" />
6 </Async>
7 </Appenders>
8 <Loggers>
9 <AsyncRoot level="info" />
10 </Loggers>
11 </Configuration>
0 <?xml version="1.0" encoding="UTF-8"?>
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 <Configuration status="OFF">
19 <Appenders>
20 <Console name="Console" target="SYSTEM_OUT">
21 <PatternLayout pattern="%style{%d}{white} %style{[%t]} %style{%-5level:}{yellow} %style{%msg{ansi}{KeyStyle=white ValueStyle=cyan,bold}%n%throwable}{green}" />
22 </Console>
23 </Appenders>
24 <Loggers>
25 <Logger name="org.foo" level="DEBUG" />
26 <Root level="TRACE">
27 <AppenderRef ref="Console" />
28 </Root>
29 </Loggers>
30 </Configuration>
0 <?xml version="1.0" encoding="UTF-8"?>
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 <Configuration status="OFF">
19 <Appenders>
20 <Console name="Console" target="SYSTEM_OUT">
21 <PatternLayout pattern="%d [%t] %-5level: %msg{ansi}{CaughtMsg=red}%n%xThrowable{full}{ansi(CaughtMsg=red)}" />
22 </Console>
23 </Appenders>
24 <Loggers>
25 <Logger name="org.foo" level="DEBUG" />
26 <Root level="TRACE">
27 <AppenderRef ref="Console" />
28 </Root>
29 </Loggers>
30 </Configuration>
0 <?xml version="1.0" encoding="UTF-8"?>
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 <Configuration status="OFF">
19 <Appenders>
20 <Console name="Console" target="SYSTEM_OUT">
21 <PatternLayout pattern="%d [%t] %-5level: %msg%n%xThrowable{full}{ansi(StyleMapName=Kirk)}" />
22 </Console>
23 </Appenders>
24 <Loggers>
25 <Logger name="org.foo" level="DEBUG" />
26 <Root level="TRACE">
27 <AppenderRef ref="Console" />
28 </Root>
29 </Loggers>
30 </Configuration>
0 <?xml version="1.0" encoding="UTF-8"?>
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 <Configuration status="OFF">
19 <Appenders>
20 <Console name="Console" target="SYSTEM_OUT">
21 <PatternLayout pattern="%d [%t] %highlight{%-5level: %msg}%n%xThrowable{full}{ansi}" />
22 </Console>
23 </Appenders>
24 <Loggers>
25 <Logger name="org.foo" level="DEBUG" />
26 <Root level="TRACE">
27 <AppenderRef ref="Console" />
28 </Root>
29 </Loggers>
30 </Configuration>
1313 # limitations under the License.
1414
1515 status = ERROR
16 dest = err
1617
1718 filter.Threshold.type = ThresholdFilter
1819 filter.Threshold.level = DEBUG
+0
-2
log4j-distribution/.gitignore less more
0 /.project
1 /.settings/
1919 <parent>
2020 <groupId>org.apache.logging.log4j</groupId>
2121 <artifactId>log4j</artifactId>
22 <version>2.6.2</version>
22 <version>2.7</version>
2323 <relativePath>../</relativePath>
2424 </parent>
2525 <artifactId>log4j-distribution</artifactId>
253253 <artifactId>log4j-nosql</artifactId>
254254 <version>${project.version}</version>
255255 <classifier>javadoc</classifier>
256 </dependency>
257 <dependency>
258 <groupId>org.apache.logging.log4j</groupId>
259 <artifactId>log4j-api-scala_2.10</artifactId>
260 <version>${project.version}</version>
261 </dependency>
262 <dependency>
263 <groupId>org.apache.logging.log4j</groupId>
264 <artifactId>log4j-api-scala_2.10</artifactId>
265 <version>${project.version}</version>
266 <classifier>sources</classifier>
267 </dependency>
268 <dependency>
269 <groupId>org.apache.logging.log4j</groupId>
270 <artifactId>log4j-api-scala_2.11</artifactId>
271 <version>${project.version}</version>
272 </dependency>
273 <dependency>
274 <groupId>org.apache.logging.log4j</groupId>
275 <artifactId>log4j-api-scala_2.11</artifactId>
276 <version>${project.version}</version>
277 <classifier>sources</classifier>
256278 </dependency>
257279 </dependencies>
258280 <build>
+0
-4
log4j-flume-ng/.gitignore less more
0 /.settings/
1 /target/
2 /.classpath
3 /.project
1919 <parent>
2020 <groupId>org.apache.logging.log4j</groupId>
2121 <artifactId>log4j</artifactId>
22 <version>2.6.2</version>
22 <version>2.7</version>
2323 <relativePath>../</relativePath>
2424 </parent>
2525 <artifactId>log4j-flume-ng</artifactId>
147147 <artifactId>maven-bundle-plugin</artifactId>
148148 <configuration>
149149 <instructions>
150 <Fragment-Host>org.apache.logging.log4j.core</Fragment-Host>
150151 <Bundle-SymbolicName>org.apache.logging.log4j.flume</Bundle-SymbolicName>
151152 <Export-Package>org.apache.logging.log4j.flume.appender</Export-Package>
152153 </instructions>
2424 public abstract class AbstractFlumeManager extends AbstractManager {
2525
2626 public AbstractFlumeManager(final String name) {
27 super(name);
27 super(null, name);
2828 }
2929
3030 public abstract void send(Event event);
1717
1818 import java.io.Serializable;
1919 import java.util.Locale;
20
20 import java.util.concurrent.TimeUnit;
21
22 import org.apache.logging.log4j.core.Appender;
2123 import org.apache.logging.log4j.core.Filter;
2224 import org.apache.logging.log4j.core.Layout;
2325 import org.apache.logging.log4j.core.LogEvent;
3638 /**
3739 * An Appender that uses the Avro protocol to route events to Flume.
3840 */
39 @Plugin(name = "Flume", category = "Core", elementType = "appender", printObject = true)
41 @Plugin(name = "Flume", category = "Core", elementType = Appender.ELEMENT_TYPE, printObject = true)
4042 public final class FlumeAppender extends AbstractAppender implements FlumeEventFactory {
4143
4244 private static final String[] EXCLUDED_PACKAGES = {"org.apache.flume", "org.apache.avro"};
105107 }
106108
107109 @Override
108 public void stop() {
109 super.stop();
110 manager.release();
110 public boolean stop(final long timeout, final TimeUnit timeUnit) {
111 setStopping();
112 boolean stopped = super.stop(timeout, timeUnit, false);
113 stopped &= manager.stop(timeout, timeUnit);
114 setStopped();
115 return stopped;
111116 }
112117
113118 /**
160165 * @return A Flume Avro Appender.
161166 */
162167 @PluginFactory
163 public static FlumeAppender createAppender(@PluginElement("Agents") Agent[] agents,
168 public static FlumeAppender createAppender(@PluginElement("Agents") final Agent[] agents,
164169 @PluginElement("Properties") final Property[] properties,
170 @PluginAttribute("hosts") final String hosts,
165171 @PluginAttribute("embedded") final String embedded,
166172 @PluginAttribute("type") final String type,
167173 @PluginAttribute("dataDir") final String dataDir,
187193 @PluginElement("Filter") final Filter filter) {
188194
189195 final boolean embed = embedded != null ? Boolean.parseBoolean(embedded) :
190 (agents == null || agents.length == 0) && properties != null && properties.length > 0;
196 (agents == null || agents.length == 0 || hosts == null || hosts.isEmpty()) && properties != null && properties.length > 0;
191197 final boolean ignoreExceptions = Booleans.parseBoolean(ignore, true);
192198 final boolean compress = Booleans.parseBoolean(compressBody, true);
193199 ManagerType managerType;
241247 manager = FlumeEmbeddedManager.getManager(name, agents, properties, batchCount, dataDir);
242248 break;
243249 case AVRO:
244 if (agents == null || agents.length == 0) {
245 LOGGER.debug("No agents provided, using defaults");
246 agents = new Agent[] {Agent.createAgent(null, null)};
247 }
248 manager = FlumeAvroManager.getManager(name, agents, batchCount, delayMillis, retries, connectTimeoutMillis, reqTimeoutMillis);
250 manager = FlumeAvroManager.getManager(name, getAgents(agents, hosts), batchCount, delayMillis, retries, connectTimeoutMillis, reqTimeoutMillis);
249251 break;
250252 case PERSISTENT:
251 if (agents == null || agents.length == 0) {
252 LOGGER.debug("No agents provided, using defaults");
253 agents = new Agent[] {Agent.createAgent(null, null)};
254 }
255 manager = FlumePersistentManager.getManager(name, agents, properties, batchCount, retries,
253 manager = FlumePersistentManager.getManager(name, getAgents(agents, hosts), properties, batchCount, retries,
256254 connectTimeoutMillis, reqTimeoutMillis, delayMillis, lockTimeoutRetryCount, dataDir);
257255 break;
258256 default:
259257 LOGGER.debug("No manager type specified. Defaulting to AVRO");
260 if (agents == null || agents.length == 0) {
261 LOGGER.debug("No agents provided, using defaults");
262 agents = new Agent[] {Agent.createAgent(null, null)};
263 }
264 manager = FlumeAvroManager.getManager(name, agents, batchCount, delayMillis, retries, connectTimeoutMillis, reqTimeoutMillis);
258 manager = FlumeAvroManager.getManager(name, getAgents(agents, hosts), batchCount, delayMillis, retries, connectTimeoutMillis, reqTimeoutMillis);
265259 }
266260
267261 if (manager == null) {
271265 return new FlumeAppender(name, filter, layout, ignoreExceptions, includes,
272266 excludes, required, mdcPrefix, eventPrefix, compress, factory, manager);
273267 }
268
269 private static Agent[] getAgents(Agent[] agents, final String hosts) {
270 if (agents == null || agents.length == 0) {
271 if (hosts != null && !hosts.isEmpty()) {
272 LOGGER.debug("Parsing agents from hosts parameter");
273 final String[] hostports = hosts.split(",");
274 agents = new Agent[hostports.length];
275 for(int i = 0; i < hostports.length; ++i) {
276 final String[] h = hostports[i].split(":");
277 agents[i] = Agent.createAgent(h[0], h.length > 1 ? h[1] : null);
278 }
279 } else {
280 LOGGER.debug("No agents provided, using defaults");
281 agents = new Agent[] {Agent.createAgent(null, null)};
282 }
283 }
284
285 LOGGER.debug("Using agents {}", agents);
286 return agents;
287 }
274288 }
255255 }
256256
257257 @Override
258 protected void releaseSub() {
258 protected boolean releaseSub(final long timeout, final TimeUnit timeUnit) {
259 boolean closed = true;
259260 if (rpcClient != null) {
260261 try {
261262 synchronized(this) {
265266 }
266267 } catch (final Exception ex) {
267268 LOGGER.error("Error sending final batch: {}", ex.getMessage());
269 closed = false;
268270 }
269271 }
270272 rpcClient.close();
271273 } catch (final Exception ex) {
272274 LOGGER.error("Attempt to close RPC client failed", ex);
275 closed = false;
273276 }
274277 }
275278 rpcClient = null;
279 return closed;
276280 }
277281
278282 /**
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.flume.appender;
17
18 import java.util.HashMap;
19 import java.util.Locale;
20 import java.util.Map;
21
22 import org.apache.flume.Event;
23 import org.apache.flume.EventDeliveryException;
24 import org.apache.flume.agent.embedded.EmbeddedAgent;
25 import org.apache.logging.log4j.LoggingException;
26 import org.apache.logging.log4j.core.appender.ManagerFactory;
27 import org.apache.logging.log4j.core.config.ConfigurationException;
28 import org.apache.logging.log4j.core.config.Property;
29 import org.apache.logging.log4j.core.util.NameUtil;
30 import org.apache.logging.log4j.util.PropertiesUtil;
31 import org.apache.logging.log4j.util.Strings;
32
33 /**
34 *
35 */
36 public class FlumeEmbeddedManager extends AbstractFlumeManager {
37
38 private static final String FILE_SEP = PropertiesUtil.getProperties().getStringProperty("file.separator");
39
40 private static final String IN_MEMORY = "InMemory";
41
42 private static FlumeManagerFactory factory = new FlumeManagerFactory();
43
44 private final EmbeddedAgent agent;
45
46 private final String shortName;
47
48
49 /**
50 * Constructor
51 * @param name The unique name of this manager.
52 * @param shortName The short version of the agent name.
53 * @param agent The embedded agent.
54 */
55 protected FlumeEmbeddedManager(final String name, final String shortName, final EmbeddedAgent agent) {
56 super(name);
57 this.agent = agent;
58 this.shortName = shortName;
59 }
60
61 /**
62 * Returns a FlumeEmbeddedManager.
63 * @param name The name of the manager.
64 * @param agents The agents to use.
65 * @param properties Properties for the embedded manager.
66 * @param batchSize The number of events to include in a batch.
67 * @param dataDir The directory where the Flume FileChannel should write to.
68 * @return A FlumeAvroManager.
69 */
70 public static FlumeEmbeddedManager getManager(final String name, final Agent[] agents, final Property[] properties,
71 int batchSize, final String dataDir) {
72
73 if (batchSize <= 0) {
74 batchSize = 1;
75 }
76
77 if ((agents == null || agents.length == 0) && (properties == null || properties.length == 0)) {
78 throw new IllegalArgumentException("Either an Agent or properties are required");
79 } else if (agents != null && agents.length > 0 && properties != null && properties.length > 0) {
80 throw new IllegalArgumentException("Cannot configure both Agents and Properties.");
81 }
82
83 final StringBuilder sb = new StringBuilder();
84 boolean first = true;
85
86 if (agents != null && agents.length > 0) {
87 sb.append(name).append('[');
88 for (final Agent agent : agents) {
89 if (!first) {
90 sb.append('_');
91 }
92 sb.append(agent.getHost()).append('-').append(agent.getPort());
93 first = false;
94 }
95 sb.append(']');
96 } else {
97 String sep = Strings.EMPTY;
98 sb.append(name).append('-');
99 final StringBuilder props = new StringBuilder();
100 for (final Property prop : properties) {
101 props.append(sep);
102 props.append(prop.getName()).append('=').append(prop.getValue());
103 sep = "_";
104 }
105 sb.append(NameUtil.md5(props.toString()));
106 }
107 return getManager(sb.toString(), factory,
108 new FactoryData(name, agents, properties, batchSize, dataDir));
109 }
110
111 @Override
112 public void send(final Event event) {
113 try {
114 agent.put(event);
115 } catch (final EventDeliveryException ex) {
116 throw new LoggingException("Unable to deliver event to Flume Appender " + shortName, ex);
117 }
118 }
119
120 @Override
121 protected void releaseSub() {
122 agent.stop();
123 }
124
125 /**
126 * Factory data.
127 */
128 private static class FactoryData {
129 private final Agent[] agents;
130 private final Property[] properties;
131 private final int batchSize;
132 private final String dataDir;
133 private final String name;
134
135 /**
136 * Constructor.
137 * @param name The name of the Appender.
138 * @param agents The agents.
139 * @param properties The Flume configuration properties.
140 * @param batchSize The number of events to include in a batch.
141 * @param dataDir The directory where Flume should write to.
142 */
143 public FactoryData(final String name, final Agent[] agents, final Property[] properties, final int batchSize,
144 final String dataDir) {
145 this.name = name;
146 this.agents = agents;
147 this.batchSize = batchSize;
148 this.properties = properties;
149 this.dataDir = dataDir;
150 }
151 }
152
153 /**
154 * Avro Manager Factory.
155 */
156 private static class FlumeManagerFactory implements ManagerFactory<FlumeEmbeddedManager, FactoryData> {
157
158 /**
159 * Create the FlumeAvroManager.
160 * @param name The name of the entity to manage.
161 * @param data The data required to create the entity.
162 * @return The FlumeAvroManager.
163 */
164 @Override
165 public FlumeEmbeddedManager createManager(final String name, final FactoryData data) {
166 try {
167 final Map<String, String> props = createProperties(data.name, data.agents, data.properties,
168 data.batchSize, data.dataDir);
169 final EmbeddedAgent agent = new EmbeddedAgent(name);
170 agent.configure(props);
171 agent.start();
172 LOGGER.debug("Created Agent " + name);
173 return new FlumeEmbeddedManager(name, data.name, agent);
174 } catch (final Exception ex) {
175 LOGGER.error("Could not create FlumeEmbeddedManager", ex);
176 }
177 return null;
178 }
179
180 private Map<String, String> createProperties(final String name, final Agent[] agents,
181 final Property[] properties, final int batchSize, String dataDir) {
182 final Map<String, String> props = new HashMap<>();
183
184 if ((agents == null || agents.length == 0) && (properties == null || properties.length == 0)) {
185 LOGGER.error("No Flume configuration provided");
186 throw new ConfigurationException("No Flume configuration provided");
187 }
188
189 if (agents != null && agents.length > 0 && properties != null && properties.length > 0) {
190 LOGGER.error("Agents and Flume configuration cannot both be specified");
191 throw new ConfigurationException("Agents and Flume configuration cannot both be specified");
192 }
193
194 if (agents != null && agents.length > 0) {
195
196 if (Strings.isNotEmpty(dataDir)) {
197 if (dataDir.equals(IN_MEMORY)) {
198 props.put("channel.type", "memory");
199 } else {
200 props.put("channel.type", "file");
201
202 if (!dataDir.endsWith(FILE_SEP)) {
203 dataDir = dataDir + FILE_SEP;
204 }
205
206 props.put("channel.checkpointDir", dataDir + "checkpoint");
207 props.put("channel.dataDirs", dataDir + "data");
208 }
209
210 } else {
211 props.put("channel.type", "file");
212 }
213
214 final StringBuilder sb = new StringBuilder();
215 String leading = Strings.EMPTY;
216 final int priority = agents.length;
217 for (int i = 0; i < priority; ++i) {
218 sb.append(leading).append("agent").append(i);
219 leading = " ";
220 final String prefix = "agent" + i;
221 props.put(prefix + ".type", "avro");
222 props.put(prefix + ".hostname", agents[i].getHost());
223 props.put(prefix + ".port", Integer.toString(agents[i].getPort()));
224 props.put(prefix + ".batch-size", Integer.toString(batchSize));
225 props.put("processor.priority." + prefix, Integer.toString(agents.length - i));
226 }
227 props.put("sinks", sb.toString());
228 props.put("processor.type", "failover");
229 } else {
230 String[] sinks = null;
231
232 for (final Property property : properties) {
233 final String key = property.getName();
234
235 if (Strings.isEmpty(key)) {
236 final String msg = "A property name must be provided";
237 LOGGER.error(msg);
238 throw new ConfigurationException(msg);
239 }
240
241 final String upperKey = key.toUpperCase(Locale.ENGLISH);
242
243 if (upperKey.startsWith(name.toUpperCase(Locale.ENGLISH))) {
244 final String msg =
245 "Specification of the agent name is not allowed in Flume Appender configuration: " + key;
246 LOGGER.error(msg);
247 throw new ConfigurationException(msg);
248 }
249
250 final String value = property.getValue();
251 if (Strings.isEmpty(value)) {
252 final String msg = "A value for property " + key + " must be provided";
253 LOGGER.error(msg);
254 throw new ConfigurationException(msg);
255 }
256
257 if (upperKey.equals("SINKS")) {
258 sinks = value.trim().split(" ");
259 }
260
261 props.put(key, value);
262 }
263
264 if (sinks == null || sinks.length == 0) {
265 final String msg = "At least one Sink must be specified";
266 LOGGER.error(msg);
267 throw new ConfigurationException(msg);
268 }
269 }
270 return props;
271 }
272
273 }
274
275 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.flume.appender;
17
18 import java.util.HashMap;
19 import java.util.Locale;
20 import java.util.Map;
21 import java.util.concurrent.TimeUnit;
22
23 import org.apache.flume.Event;
24 import org.apache.flume.EventDeliveryException;
25 import org.apache.flume.agent.embedded.EmbeddedAgent;
26 import org.apache.logging.log4j.LoggingException;
27 import org.apache.logging.log4j.core.appender.ManagerFactory;
28 import org.apache.logging.log4j.core.config.ConfigurationException;
29 import org.apache.logging.log4j.core.config.Property;
30 import org.apache.logging.log4j.core.util.NameUtil;
31 import org.apache.logging.log4j.util.PropertiesUtil;
32 import org.apache.logging.log4j.util.Strings;
33
34 /**
35 *
36 */
37 public class FlumeEmbeddedManager extends AbstractFlumeManager {
38
39 private static final String FILE_SEP = PropertiesUtil.getProperties().getStringProperty("file.separator");
40
41 private static final String IN_MEMORY = "InMemory";
42
43 private static FlumeManagerFactory factory = new FlumeManagerFactory();
44
45 private final EmbeddedAgent agent;
46
47 private final String shortName;
48
49
50 /**
51 * Constructor
52 * @param name The unique name of this manager.
53 * @param shortName The short version of the agent name.
54 * @param agent The embedded agent.
55 */
56 protected FlumeEmbeddedManager(final String name, final String shortName, final EmbeddedAgent agent) {
57 super(name);
58 this.agent = agent;
59 this.shortName = shortName;
60 }
61
62 /**
63 * Returns a FlumeEmbeddedManager.
64 * @param name The name of the manager.
65 * @param agents The agents to use.
66 * @param properties Properties for the embedded manager.
67 * @param batchSize The number of events to include in a batch.
68 * @param dataDir The directory where the Flume FileChannel should write to.
69 * @return A FlumeAvroManager.
70 */
71 public static FlumeEmbeddedManager getManager(final String name, final Agent[] agents, final Property[] properties,
72 int batchSize, final String dataDir) {
73
74 if (batchSize <= 0) {
75 batchSize = 1;
76 }
77
78 if ((agents == null || agents.length == 0) && (properties == null || properties.length == 0)) {
79 throw new IllegalArgumentException("Either an Agent or properties are required");
80 } else if (agents != null && agents.length > 0 && properties != null && properties.length > 0) {
81 throw new IllegalArgumentException("Cannot configure both Agents and Properties.");
82 }
83
84 final StringBuilder sb = new StringBuilder();
85 boolean first = true;
86
87 if (agents != null && agents.length > 0) {
88 sb.append(name).append('[');
89 for (final Agent agent : agents) {
90 if (!first) {
91 sb.append('_');
92 }
93 sb.append(agent.getHost()).append('-').append(agent.getPort());
94 first = false;
95 }
96 sb.append(']');
97 } else {
98 String sep = Strings.EMPTY;
99 sb.append(name).append('-');
100 final StringBuilder props = new StringBuilder();
101 for (final Property prop : properties) {
102 props.append(sep);
103 props.append(prop.getName()).append('=').append(prop.getValue());
104 sep = "_";
105 }
106 sb.append(NameUtil.md5(props.toString()));
107 }
108 return getManager(sb.toString(), factory,
109 new FactoryData(name, agents, properties, batchSize, dataDir));
110 }
111
112 @Override
113 public void send(final Event event) {
114 try {
115 agent.put(event);
116 } catch (final EventDeliveryException ex) {
117 throw new LoggingException("Unable to deliver event to Flume Appender " + shortName, ex);
118 }
119 }
120
121 @Override
122 protected boolean releaseSub(final long timeout, final TimeUnit timeUnit) {
123 agent.stop();
124 return true;
125 }
126
127 /**
128 * Factory data.
129 */
130 private static class FactoryData {
131 private final Agent[] agents;
132 private final Property[] properties;
133 private final int batchSize;
134 private final String dataDir;
135 private final String name;
136
137 /**
138 * Constructor.
139 * @param name The name of the Appender.
140 * @param agents The agents.
141 * @param properties The Flume configuration properties.
142 * @param batchSize The number of events to include in a batch.
143 * @param dataDir The directory where Flume should write to.
144 */
145 public FactoryData(final String name, final Agent[] agents, final Property[] properties, final int batchSize,
146 final String dataDir) {
147 this.name = name;
148 this.agents = agents;
149 this.batchSize = batchSize;
150 this.properties = properties;
151 this.dataDir = dataDir;
152 }
153 }
154
155 /**
156 * Avro Manager Factory.
157 */
158 private static class FlumeManagerFactory implements ManagerFactory<FlumeEmbeddedManager, FactoryData> {
159
160 /**
161 * Create the FlumeAvroManager.
162 * @param name The name of the entity to manage.
163 * @param data The data required to create the entity.
164 * @return The FlumeAvroManager.
165 */
166 @Override
167 public FlumeEmbeddedManager createManager(final String name, final FactoryData data) {
168 try {
169 final Map<String, String> props = createProperties(data.name, data.agents, data.properties,
170 data.batchSize, data.dataDir);
171 final EmbeddedAgent agent = new EmbeddedAgent(name);
172 agent.configure(props);
173 agent.start();
174 LOGGER.debug("Created Agent " + name);
175 return new FlumeEmbeddedManager(name, data.name, agent);
176 } catch (final Exception ex) {
177 LOGGER.error("Could not create FlumeEmbeddedManager", ex);
178 }
179 return null;
180 }
181
182 private Map<String, String> createProperties(final String name, final Agent[] agents,
183 final Property[] properties, final int batchSize, String dataDir) {
184 final Map<String, String> props = new HashMap<>();
185
186 if ((agents == null || agents.length == 0) && (properties == null || properties.length == 0)) {
187 LOGGER.error("No Flume configuration provided");
188 throw new ConfigurationException("No Flume configuration provided");
189 }
190
191 if (agents != null && agents.length > 0 && properties != null && properties.length > 0) {
192 LOGGER.error("Agents and Flume configuration cannot both be specified");
193 throw new ConfigurationException("Agents and Flume configuration cannot both be specified");
194 }
195
196 if (agents != null && agents.length > 0) {
197
198 if (Strings.isNotEmpty(dataDir)) {
199 if (dataDir.equals(IN_MEMORY)) {
200 props.put("channel.type", "memory");
201 } else {
202 props.put("channel.type", "file");
203
204 if (!dataDir.endsWith(FILE_SEP)) {
205 dataDir = dataDir + FILE_SEP;
206 }
207
208 props.put("channel.checkpointDir", dataDir + "checkpoint");
209 props.put("channel.dataDirs", dataDir + "data");
210 }
211
212 } else {
213 props.put("channel.type", "file");
214 }
215
216 final StringBuilder sb = new StringBuilder();
217 String leading = Strings.EMPTY;
218 final int priority = agents.length;
219 for (int i = 0; i < priority; ++i) {
220 sb.append(leading).append("agent").append(i);
221 leading = " ";
222 final String prefix = "agent" + i;
223 props.put(prefix + ".type", "avro");
224 props.put(prefix + ".hostname", agents[i].getHost());
225 props.put(prefix + ".port", Integer.toString(agents[i].getPort()));
226 props.put(prefix + ".batch-size", Integer.toString(batchSize));
227 props.put("processor.priority." + prefix, Integer.toString(agents.length - i));
228 }
229 props.put("sinks", sb.toString());
230 props.put("processor.type", "failover");
231 } else {
232 String[] sinks = null;
233
234 for (final Property property : properties) {
235 final String key = property.getName();
236
237 if (Strings.isEmpty(key)) {
238 final String msg = "A property name must be provided";
239 LOGGER.error(msg);
240 throw new ConfigurationException(msg);
241 }
242
243 final String upperKey = key.toUpperCase(Locale.ENGLISH);
244
245 if (upperKey.startsWith(name.toUpperCase(Locale.ENGLISH))) {
246 final String msg =
247 "Specification of the agent name is not allowed in Flume Appender configuration: " + key;
248 LOGGER.error(msg);
249 throw new ConfigurationException(msg);
250 }
251
252 final String value = property.getValue();
253 if (Strings.isEmpty(value)) {
254 final String msg = "A value for property " + key + " must be provided";
255 LOGGER.error(msg);
256 throw new ConfigurationException(msg);
257 }
258
259 if (upperKey.equals("SINKS")) {
260 sinks = value.trim().split(" ");
261 }
262
263 props.put(key, value);
264 }
265
266 if (sinks == null || sinks.length == 0) {
267 final String msg = "At least one Sink must be specified";
268 LOGGER.error(msg);
269 throw new ConfigurationException(msg);
270 }
271 }
272 return props;
273 }
274
275 }
276
277 }
2828 import org.apache.logging.log4j.LoggingException;
2929 import org.apache.logging.log4j.Marker;
3030 import org.apache.logging.log4j.ThreadContext;
31 import org.apache.logging.log4j.util.ReadOnlyStringMap;
3132 import org.apache.logging.log4j.core.LogEvent;
3233 import org.apache.logging.log4j.core.impl.ThrowableProxy;
3334 import org.apache.logging.log4j.core.util.Patterns;
320321 }
321322
322323 /**
324 * Returns the context data of the {@code LogEvent} that this {@code FlumeEvent} was constructed with.
325 * @return the context data of the {@code LogEvent} that this {@code FlumeEvent} was constructed with.
326 */
327 @Override
328 public ReadOnlyStringMap getContextData() {
329 return event.getContextData();
330 }
331
332 /**
323333 * Returns a copy of the context stack.
324334 * @return a copy of the context stack.
325335 */
2121 * Factory to create Flume events.
2222 */
2323 public interface FlumeEventFactory {
24
2425 /**
25 * Create a Flume event.
26 * Creates a Flume event.
2627 * @param event The Log4j LogEvent.
2728 * @param includes A comma separated list of MDC elements to include.
2829 * @param excludes A comma separated list of MDC elements to exclude.
2828 import java.util.concurrent.ExecutorService;
2929 import java.util.concurrent.Executors;
3030 import java.util.concurrent.Future;
31 import java.util.concurrent.ThreadFactory;
3231 import java.util.concurrent.TimeUnit;
33 import java.util.concurrent.atomic.AtomicInteger;
3432 import java.util.concurrent.atomic.AtomicLong;
35
3633 import javax.crypto.Cipher;
3734 import javax.crypto.SecretKey;
38
39 import org.apache.flume.Event;
40 import org.apache.flume.event.SimpleEvent;
41 import org.apache.logging.log4j.LoggingException;
42 import org.apache.logging.log4j.core.appender.ManagerFactory;
43 import org.apache.logging.log4j.core.config.Property;
44 import org.apache.logging.log4j.core.config.plugins.util.PluginManager;
45 import org.apache.logging.log4j.core.config.plugins.util.PluginType;
46 import org.apache.logging.log4j.core.util.FileUtils;
47 import org.apache.logging.log4j.core.util.Log4jThread;
48 import org.apache.logging.log4j.core.util.SecretKeyProvider;
49 import org.apache.logging.log4j.util.Strings;
5035
5136 import com.sleepycat.je.Cursor;
5237 import com.sleepycat.je.CursorConfig;
6045 import com.sleepycat.je.OperationStatus;
6146 import com.sleepycat.je.StatsConfig;
6247 import com.sleepycat.je.Transaction;
48 import org.apache.flume.Event;
49 import org.apache.flume.event.SimpleEvent;
50 import org.apache.logging.log4j.LoggingException;
51 import org.apache.logging.log4j.core.appender.ManagerFactory;
52 import org.apache.logging.log4j.core.config.Property;
53 import org.apache.logging.log4j.core.config.plugins.util.PluginManager;
54 import org.apache.logging.log4j.core.config.plugins.util.PluginType;
55 import org.apache.logging.log4j.core.util.ExecutorServices;
56 import org.apache.logging.log4j.core.util.FileUtils;
57 import org.apache.logging.log4j.core.util.Log4jThread;
58 import org.apache.logging.log4j.core.util.Log4jThreadFactory;
59 import org.apache.logging.log4j.core.util.SecretKeyProvider;
60 import org.apache.logging.log4j.util.Strings;
6361
6462 /**
6563 * Manager that persists data to Berkeley DB before passing it on to Flume.
7371
7472 private static final String DEFAULT_DATA_DIR = ".log4j/flumeData";
7573
76 private static final int SHUTDOWN_WAIT = 60;
77
78 private static final int MILLIS_PER_SECOND = 1000;
79
80 private static final int LOCK_TIMEOUT_SLEEP_MILLIS = 500;
74 private static final long SHUTDOWN_WAIT_MILLIS = 60000;
75
76 private static final long LOCK_TIMEOUT_SLEEP_MILLIS = 500;
8177
8278 private static BDBManagerFactory factory = new BDBManagerFactory();
8379
125121 lockTimeoutRetryCount);
126122 this.worker.start();
127123 this.secretKey = secretKey;
128 this.threadPool = Executors.newCachedThreadPool(new DaemonThreadFactory());
124 this.threadPool = Executors.newCachedThreadPool(Log4jThreadFactory.createDaemonThreadFactory("Flume"));
129125 this.lockTimeoutRetryCount = lockTimeoutRetryCount;
130126 }
131127
216212 }
217213
218214 @Override
219 protected void releaseSub() {
215 protected boolean releaseSub(final long timeout, final TimeUnit timeUnit) {
216 boolean closed = true;
220217 LOGGER.debug("Shutting down FlumePersistentManager");
221218 worker.shutdown();
222 try {
223 worker.join(SHUTDOWN_WAIT * MILLIS_PER_SECOND);
219 final long requestedTimeoutMillis = timeUnit.toMillis(timeout);
220 final long shutdownWaitMillis = requestedTimeoutMillis > 0 ? requestedTimeoutMillis : SHUTDOWN_WAIT_MILLIS;
221 try {
222 worker.join(shutdownWaitMillis);
224223 } catch (final InterruptedException ie) {
225224 // Ignore the exception and shutdown.
226225 }
227 threadPool.shutdown();
228 try {
229 threadPool.awaitTermination(SHUTDOWN_WAIT, TimeUnit.SECONDS);
230 } catch (final InterruptedException e) {
231 logWarn("PersistentManager Thread pool failed to shut down", e);
232 }
226 ExecutorServices.shutdown(threadPool, shutdownWaitMillis, TimeUnit.MILLISECONDS, toString());
233227 try {
234228 worker.join();
235229 } catch (final InterruptedException ex) {
239233 LOGGER.debug("FlumePersistenceManager dataset status: {}", database.getStats(new StatsConfig()));
240234 database.close();
241235 } catch (final Exception ex) {
242 logWarn("failed to close database", ex);
236 logWarn("Failed to close database", ex);
237 closed = false;
243238 }
244239 try {
245240 environment.cleanLog();
246241 environment.close();
247242 } catch (final Exception ex) {
248 logWarn("failed to close environment", ex);
249 }
250 super.releaseSub();
243 logWarn("Failed to close environment", ex);
244 closed = false;
245 }
246 return closed && super.releaseSub(timeout, timeUnit);
251247 }
252248
253249 private void doSend(final SimpleEvent event) {
476472 /**
477473 * Thread that sends data to Flume and pulls it from Berkeley DB.
478474 */
479 private static class WriterThread extends Thread {
475 private static class WriterThread extends Log4jThread {
480476 private volatile boolean shutdown = false;
481477 private final Database database;
482478 private final Environment environment;
490486 public WriterThread(final Database database, final Environment environment,
491487 final FlumePersistentManager manager, final Gate gate, final int batchsize,
492488 final SecretKey secretKey, final AtomicLong dbCount, final int lockTimeoutRetryCount) {
489 super("FlumePersistentManager-Writer");
493490 this.database = database;
494491 this.environment = environment;
495492 this.manager = manager;
825822 }
826823
827824 /**
828 * Factory that creates Daemon threads that can be properly shut down.
829 */
830 private static class DaemonThreadFactory implements ThreadFactory {
831 private static final AtomicInteger POOL_NUMBER = new AtomicInteger(1);
832 private final ThreadGroup group;
833 private final AtomicInteger threadNumber = new AtomicInteger(1);
834 private final String namePrefix;
835
836 public DaemonThreadFactory() {
837 final SecurityManager securityManager = System.getSecurityManager();
838 group = securityManager != null ? securityManager.getThreadGroup() :
839 Thread.currentThread().getThreadGroup();
840 namePrefix = "DaemonPool-" + POOL_NUMBER.getAndIncrement() + "-thread-";
841 }
842
843 @Override
844 public Thread newThread(final Runnable r) {
845 final Thread thread = new Log4jThread(group, r, namePrefix + threadNumber.getAndIncrement(), 0);
846 thread.setDaemon(true);
847 if (thread.getPriority() != Thread.NORM_PRIORITY) {
848 thread.setPriority(Thread.NORM_PRIORITY);
849 }
850 return thread;
851 }
852 }
853
854 /**
855825 * An internal class.
856826 */
857827 private static class Gate {
118118 final Agent[] agents = new Agent[] { Agent.createAgent("localhost",
119119 testPort) };
120120 final FlumeAppender avroAppender = FlumeAppender.createAppender(agents,
121 null, "false", "Avro", null, "1000", "1000", "1", "1000",
121 null, null, "false", "Avro", null, "1000", "1000", "1", "1000",
122122 "avro", "false", null, null, null, null, null, "true", "1",
123123 null, null, null, null);
124124 avroAppender.start();
143143 }
144144
145145 @Test
146 public void testLog4jAvroAppenderWithHostsParam() throws IOException {
147 final String hosts = String.format("localhost:%s", testPort);
148 final FlumeAppender avroAppender = FlumeAppender.createAppender(null,
149 null, hosts, "false", "Avro", null, "1000", "1000", "1", "1000",
150 "avro", "false", null, null, null, null, null, "true", "1",
151 null, null, null, null);
152 avroAppender.start();
153 avroLogger.addAppender(avroAppender);
154 avroLogger.setLevel(Level.ALL);
155
156 Assert.assertNotNull(avroLogger);
157
158 avroLogger.info("Test message");
159
160 final Transaction transaction = channel.getTransaction();
161 transaction.begin();
162
163 final Event event = channel.take();
164 Assert.assertNotNull(event);
165 Assert.assertTrue("Channel contained event, but not expected message",
166 getBody(event).endsWith("Test message"));
167 transaction.commit();
168 transaction.close();
169
170 eventSource.stop();
171 }
172
173 @Test
146174 public void testStructured() throws IOException {
147175 final Agent[] agents = new Agent[] { Agent.createAgent("localhost",
148176 testPort) };
149177 final FlumeAppender avroAppender = FlumeAppender.createAppender(agents,
150 null, "false", "Avro", null, "1000", "1000", "1", "1000",
178 null, null, "false", "Avro", null, "1000", "1000", "1", "1000",
151179 "avro", "false", null, null, null, "ReqCtx_", null, "true",
152180 "1", null, null, null, null);
153181 avroAppender.start();
186214 final Agent[] agents = new Agent[] { Agent.createAgent("localhost",
187215 testPort) };
188216 final FlumeAppender avroAppender = FlumeAppender.createAppender(agents,
189 null, "false", "Avro", null, "1000", "1000", "1", "1000",
217 null, null, "false", "Avro", null, "1000", "1000", "1", "1000",
190218 "avro", "false", null, null, null, null, null, "true", "1",
191219 null, null, null, null);
192220 avroAppender.start();
215243 eventSource.stop();
216244 }
217245
218
246 //@Ignore //(Remko: this test hangs my build...)
219247 @Test
220248 public void testIncompleteBatch() throws IOException {
221249 final Agent[] agents = new Agent[] { Agent.createAgent("localhost",
222250 testPort) };
223251 final FlumeAppender avroAppender = FlumeAppender.createAppender(agents,
224 null, "false", "Avro", null, "1000", "1000", "1", "500",
252 null, null, "false", "Avro", null, "1000", "1000", "1", "500",
225253 "avro", "false", null, null, null, null, null, "true", "10",
226254 null, null, null, null);
227255 avroAppender.start();
261289 final Agent[] agents = new Agent[] { Agent.createAgent("localhost",
262290 testPort) };
263291 final FlumeAppender avroAppender = FlumeAppender.createAppender(agents,
264 null, "false", "Avro", null, "1000", "1000", "1", "500",
292 null, null, "false", "Avro", null, "1000", "1000", "1", "500",
265293 "avro", "false", null, null, null, null, null, "true", "10",
266294 null, null, null, null);
267295 avroAppender.start();
295323 final Agent[] agents = new Agent[] { Agent.createAgent("localhost",
296324 testPort) };
297325 final FlumeAppender avroAppender = FlumeAppender.createAppender(agents,
298 null, "false", "Avro", null, "1000", "1000", "1", "1000",
326 null, null, "false", "Avro", null, "1000", "1000", "1", "1000",
299327 "avro", "false", null, null, null, null, null, "true", "10",
300328 null, null, null, null);
301329 avroAppender.start();
329357 final Agent[] agents = new Agent[] { Agent.createAgent("localhost",
330358 testPort) };
331359 final FlumeAppender avroAppender = FlumeAppender.createAppender(agents,
332 null, "false", "Avro", null, "1000", "1000", "1", "1000",
360 null, null, "false", "Avro", null, "1000", "1000", "1", "1000",
333361 "avro", "false", null, null, null, null, null, "true", "1",
334362 null, null, null, null);
335363 avroAppender.start();
359387 Agent.createAgent("localhost", testPort),
360388 Agent.createAgent("localhost", altPort) };
361389 final FlumeAppender avroAppender = FlumeAppender.createAppender(agents,
362 null, "false", "Avro", null, "1000", "1000", "1", "1000",
390 null, null, "false", "Avro", null, "1000", "1000", "1", "1000",
363391 "avro", "false", null, null, null, null, null, "true", "1",
364392 null, null, null, null);
365393 avroAppender.start();
407435 Agent.createAgent("localhost", testPort),
408436 Agent.createAgent("localhost", altPort) };
409437 final FlumeAppender avroAppender = FlumeAppender.createAppender(agents,
410 null, "false", "Avro", null, "1000", "1000", "1", "1000",
438 null, null, "false", "Avro", null, "1000", "1000", "1", "1000",
411439 "avro", "false", null, null, null, null, null, "true", "1",
412440 null, null, null, null);
413441 avroAppender.start();
8888 public void setUp() throws Exception {
8989
9090 final File file = new File("target/file-channel");
91 final boolean result = deleteFiles(file);
91 deleteFiles(file);
9292
9393 /*
9494 * Clear out all other appenders associated with this logger to ensure we're
112112 primary.stop();
113113 alternate.stop();
114114 final File file = new File("target/file-channel");
115 final boolean result = deleteFiles(file);
115 deleteFiles(file);
116116 final MBeanServer server = ManagementFactory.getPlatformMBeanServer();
117117 final Set<ObjectName> names = server.queryNames(new ObjectName("org.apache.flume.*:*"), null);
118118 for (final ObjectName name : names) {
8888 public void setUp() throws Exception {
8989
9090 final File file = new File("target/file-channel");
91 final boolean result = deleteFiles(file);
91 deleteFiles(file);
9292
9393 /*
9494 * Clear out all other appenders associated with this logger to ensure we're
112112 primary.stop();
113113 alternate.stop();
114114 final File file = new File("target/file-channel");
115 final boolean result = deleteFiles(file);
115 deleteFiles(file);
116116 final MBeanServer server = ManagementFactory.getPlatformMBeanServer();
117117 final Set<ObjectName> names = server.queryNames(new ObjectName("org.apache.flume.*:*"), null);
118118 for (final ObjectName name : names) {
9090 public void setUp() throws Exception {
9191
9292 final File file = new File("target/persistent");
93 final boolean result = deleteFiles(file);
93 deleteFiles(file);
9494
9595 /*
9696 * Clear out all other appenders associated with this logger to ensure we're
114114 primary.stop();
115115 alternate.stop();
116116 final File file = new File("target/file-channel");
117 final boolean result = deleteFiles(file);
117 deleteFiles(file);
118118 final MBeanServer server = ManagementFactory.getPlatformMBeanServer();
119119 final Set<ObjectName> names = server.queryNames(new ObjectName("org.apache.flume.*:*"), null);
120120 for (final ObjectName name : names) {
8585 public void setUp() throws Exception {
8686
8787 final File file = new File("target/persistent");
88 final boolean result = deleteFiles(file);
88 deleteFiles(file);
8989
9090 /*
9191 * Clear out all other appenders associated with this logger to ensure we're
109109 primary.stop();
110110 alternate.stop();
111111 final File file = new File("target/file-channel");
112 final boolean result = deleteFiles(file);
112 deleteFiles(file);
113113 final MBeanServer server = ManagementFactory.getPlatformMBeanServer();
114114 final Set<ObjectName> names = server.queryNames(new ObjectName("org.apache.flume.*:*"), null);
115115 for (final ObjectName name : names) {
log4j-iostreams/.gitignore less more
Binary diff not shown
1919 <parent>
2020 <groupId>org.apache.logging.log4j</groupId>
2121 <artifactId>log4j</artifactId>
22 <version>2.6.2</version>
22 <version>2.7</version>
2323 <relativePath>../</relativePath>
2424 </parent>
2525 <artifactId>log4j-iostreams</artifactId>
+0
-4
log4j-jcl/.gitignore less more
0 /.settings/
1 /target/
2 /.classpath
3 /.project
1919 <parent>
2020 <groupId>org.apache.logging.log4j</groupId>
2121 <artifactId>log4j</artifactId>
22 <version>2.6.2</version>
22 <version>2.7</version>
2323 <relativePath>../</relativePath>
2424 </parent>
2525 <artifactId>log4j-jcl</artifactId>
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.jcl;
17
18 import java.util.List;
19
20 import org.apache.commons.logging.Log;
21 import org.apache.commons.logging.LogFactory;
22 import org.apache.logging.log4j.core.util.Constants;
23 import org.apache.logging.log4j.junit.LoggerContextRule;
24 import org.apache.logging.log4j.test.appender.ListAppender;
25 import org.junit.ClassRule;
26 import org.junit.Test;
27
28 import static org.hamcrest.Matchers.equalTo;
29 import static org.hamcrest.Matchers.hasSize;
30 import static org.junit.Assert.*;
31
32 /**
33 *
34 */
35 public class LoggerTest {
36
37 private static final String CONFIG = "log4j-test1.xml";
38
39 @ClassRule
40 public static final LoggerContextRule context = new LoggerContextRule(CONFIG);
41
42 @Test
43 public void testLog() {
44 final Log logger = LogFactory.getLog("LoggerTest");
45 logger.debug("Test message");
46 verify("List", "o.a.l.l.j.LoggerTest Test message MDC{}" + Constants.LINE_SEPARATOR);
47 logger.debug("Exception: " , new NullPointerException("Test"));
48 verify("List", "o.a.l.l.j.LoggerTest Exception: MDC{}" + Constants.LINE_SEPARATOR);
49 logger.info("Info Message");
50 verify("List", "o.a.l.l.j.LoggerTest Info Message MDC{}" + Constants.LINE_SEPARATOR);
51 logger.info("Info Message {}");
52 verify("List", "o.a.l.l.j.LoggerTest Info Message {} MDC{}" + Constants.LINE_SEPARATOR);
53 }
54
55 private void verify(final String name, final String expected) {
56 final ListAppender listApp = context.getListAppender(name);
57 final List<String> events = listApp.getMessages();
58 assertThat(events, hasSize(1));
59 final String actual = events.get(0);
60 assertThat(actual, equalTo(expected));
61 listApp.clear();
62 }
63
64 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.jcl;
17
18 import java.util.List;
19
20 import org.apache.commons.logging.Log;
21 import org.apache.commons.logging.LogFactory;
22 import org.apache.logging.log4j.junit.LoggerContextRule;
23 import org.apache.logging.log4j.test.appender.ListAppender;
24 import org.apache.logging.log4j.util.Strings;
25 import org.junit.ClassRule;
26 import org.junit.Test;
27
28 import static org.hamcrest.Matchers.equalTo;
29 import static org.hamcrest.Matchers.hasSize;
30 import static org.junit.Assert.*;
31
32 /**
33 *
34 */
35 public class LoggerTest {
36
37 private static final String CONFIG = "log4j-test1.xml";
38
39 @ClassRule
40 public static final LoggerContextRule context = new LoggerContextRule(CONFIG);
41
42 @Test
43 public void testLog() {
44 final Log logger = LogFactory.getLog("LoggerTest");
45 logger.debug("Test message");
46 verify("List", "o.a.l.l.j.LoggerTest Test message MDC{}" + Strings.LINE_SEPARATOR);
47 logger.debug("Exception: " , new NullPointerException("Test"));
48 verify("List", "o.a.l.l.j.LoggerTest Exception: MDC{}" + Strings.LINE_SEPARATOR);
49 logger.info("Info Message");
50 verify("List", "o.a.l.l.j.LoggerTest Info Message MDC{}" + Strings.LINE_SEPARATOR);
51 logger.info("Info Message {}");
52 verify("List", "o.a.l.l.j.LoggerTest Info Message {} MDC{}" + Strings.LINE_SEPARATOR);
53 }
54
55 private void verify(final String name, final String expected) {
56 final ListAppender listApp = context.getListAppender(name);
57 final List<String> events = listApp.getMessages();
58 assertThat(events, hasSize(1));
59 final String actual = events.get(0);
60 assertThat(actual, equalTo(expected));
61 listApp.clear();
62 }
63
64 }
+0
-4
log4j-jmx-gui/.gitignore less more
0 /.settings/
1 /target/
2 /.classpath
3 /.project
1919 <parent>
2020 <groupId>org.apache.logging.log4j</groupId>
2121 <artifactId>log4j</artifactId>
22 <version>2.6.2</version>
22 <version>2.7</version>
2323 <relativePath>../</relativePath>
2424 </parent>
2525 <artifactId>log4j-jmx-gui</artifactId>
7777 <artifactId>maven-bundle-plugin</artifactId>
7878 <configuration>
7979 <instructions>
80 <Fragment-Host>org.apache.logging.log4j.core</Fragment-Host>
8081 <Export-Package>org.apache.logging.log4j.jmx.gui</Export-Package>
8182 </instructions>
8283 </configuration>
+0
-3
log4j-jul/.gitignore less more
0 /.settings/
1 /.classpath
2 /.project
1919 <parent>
2020 <artifactId>log4j</artifactId>
2121 <groupId>org.apache.logging.log4j</groupId>
22 <version>2.6.2</version>
22 <version>2.7</version>
2323 <relativePath>../</relativePath>
2424 </parent>
2525 <modelVersion>4.0.0</modelVersion>
8282 <artifactId>maven-bundle-plugin</artifactId>
8383 <configuration>
8484 <instructions>
85 <Fragment-Host>org.apache.logging.log4j.core</Fragment-Host>
8586 <Export-Package>org.apache.logging.log4j.jul</Export-Package>
8687 </instructions>
8788 </configuration>
2828 * {@code log4j-core}.
2929 */
3030 public static final String LOGGER_ADAPTOR_PROPERTY = "log4j.jul.LoggerAdapter";
31
3132 /**
3233 * The Log4j property to set to a custom implementation of {@link org.apache.logging.log4j.jul.LevelConverter}. The specified class must have
3334 * a default constructor.
3333
3434 @Override
3535 protected Logger newLogger(final String name, final LoggerContext context) {
36 return new CoreLogger((org.apache.logging.log4j.core.Logger) context.getLogger(name, MESSAGE_FACTORY));
36 final org.apache.logging.log4j.spi.ExtendedLogger original = context.getLogger(name, MESSAGE_FACTORY);
37 if (original instanceof org.apache.logging.log4j.core.Logger) {
38 return new CoreLogger((org.apache.logging.log4j.core.Logger) original);
39 }
40 return new ApiLogger(original); // LOG4J2-1618 during shutdown, a SimpleLogger may be returned
3741 }
38
3942 }
+0
-3
log4j-liquibase/.gitignore less more
0 /.classpath
1 /.project
2 /.settings/
1919 <parent>
2020 <groupId>org.apache.logging.log4j</groupId>
2121 <artifactId>log4j</artifactId>
22 <version>2.6.2</version>
22 <version>2.7</version>
2323 <relativePath>../</relativePath>
2424 </parent>
2525 <artifactId>log4j-liquibase</artifactId>
2323
2424 import liquibase.logging.Logger;
2525
26 import org.apache.logging.log4j.core.util.Constants;
2726 import org.apache.logging.log4j.test.appender.ListAppender;
27 import org.apache.logging.log4j.util.Strings;
2828 import org.junit.After;
2929 import org.junit.BeforeClass;
3030 import org.junit.Test;
4545 @Test
4646 public void debug() {
4747 logger.debug("Debug message");
48 verify(NAME + " " + getClass().getName() + " DEBUG Debug message" + Constants.LINE_SEPARATOR);
48 verify(NAME + " " + getClass().getName() + " DEBUG Debug message" + Strings.LINE_SEPARATOR);
4949 }
5050
5151 @Test
5252 public void info() {
5353 logger.info("Info message");
54 verify(NAME + " " + getClass().getName() + " INFO Info message" + Constants.LINE_SEPARATOR);
54 verify(NAME + " " + getClass().getName() + " INFO Info message" + Strings.LINE_SEPARATOR);
5555 }
5656
5757 @Test
5858 public void warning() {
5959 logger.warning("Warning message");
60 verify(NAME + " " + getClass().getName() + " WARN Warning message" + Constants.LINE_SEPARATOR);
60 verify(NAME + " " + getClass().getName() + " WARN Warning message" + Strings.LINE_SEPARATOR);
6161 }
6262
6363 @Test
6464 public void severe() {
6565 logger.severe("Severe message");
66 verify(NAME + " " + getClass().getName() + " ERROR Severe message" + Constants.LINE_SEPARATOR);
66 verify(NAME + " " + getClass().getName() + " ERROR Severe message" + Strings.LINE_SEPARATOR);
6767 }
6868
6969 @Test
7070 public void severeStacktrace() {
7171 logger.severe("Severe message with stacktrace", new RuntimeException("thrown error"));
72 verify(NAME + " " + getClass().getName() + " ERROR Severe message with stacktrace" + Constants.LINE_SEPARATOR
72 verify(NAME + " " + getClass().getName() + " ERROR Severe message with stacktrace" + Strings.LINE_SEPARATOR
7373 + "java.lang.RuntimeException: thrown error");
7474 }
7575
+0
-4
log4j-nosql/.gitignore less more
0 /.settings/
1 /target/
2 /.classpath
3 /.project
1919 <parent>
2020 <artifactId>log4j</artifactId>
2121 <groupId>org.apache.logging.log4j</groupId>
22 <version>2.6.2</version>
22 <version>2.7</version>
2323 </parent>
2424 <modelVersion>4.0.0</modelVersion>
2525
5858 </dependency>
5959 <dependency>
6060 <groupId>org.apache.logging.log4j</groupId>
61 <artifactId>log4j-api</artifactId>
62 <type>test-jar</type>
63 </dependency>
64 <dependency>
65 <groupId>org.apache.logging.log4j</groupId>
6166 <artifactId>log4j-core</artifactId>
6267 <type>test-jar</type>
6368 </dependency>
7075 <artifactId>maven-bundle-plugin</artifactId>
7176 <configuration>
7277 <instructions>
78 <Fragment-Host>org.apache.logging.log4j.core</Fragment-Host>
7379 <Export-Package>*</Export-Package>
7480 </instructions>
7581 </configuration>
1515 */
1616 package org.apache.logging.log4j.nosql.appender;
1717
18 import org.apache.logging.log4j.core.Appender;
1819 import org.apache.logging.log4j.core.Filter;
1920 import org.apache.logging.log4j.core.appender.AbstractAppender;
2021 import org.apache.logging.log4j.core.appender.db.AbstractDatabaseAppender;
4748 * @see NoSqlConnection
4849 * @see NoSqlProvider
4950 */
50 @Plugin(name = "NoSql", category = "Core", elementType = "appender", printObject = true)
51 @Plugin(name = "NoSql", category = "Core", elementType = Appender.ELEMENT_TYPE, printObject = true)
5152 public final class NoSqlAppender extends AbstractDatabaseAppender<NoSqlDatabaseManager<?>> {
5253 private final String description;
5354
4949 }
5050
5151 @Override
52 protected void shutdownInternal() {
52 protected boolean shutdownInternal() {
5353 // NoSQL doesn't use transactions, so all we need to do here is simply close the client
54 Closer.closeSilently(this.connection);
54 return Closer.closeSilently(this.connection);
5555 }
5656
5757 @Override
156156 }
157157
158158 @Override
159 protected void commitAndClose() {
159 protected boolean commitAndClose() {
160160 // all NoSQL drivers auto-commit (since NoSQL doesn't generally use the concept of transactions).
161161 // also, all our NoSQL drivers use internal connection pooling and provide clients, not connections.
162162 // thus, we should not be closing the client until shutdown as NoSQL is very different from SQL.
163163 // see LOG4J2-591 and LOG4J2-676
164 return true;
164165 }
165166
166167 private NoSqlObject<W>[] convertStackTrace(final StackTraceElement[] stackTrace) {
2222 import org.apache.logging.log4j.core.config.plugins.Plugin;
2323 import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
2424 import org.apache.logging.log4j.core.config.plugins.PluginFactory;
25 import org.apache.logging.log4j.core.util.Loader;
2625 import org.apache.logging.log4j.core.util.NameUtil;
2726 import org.apache.logging.log4j.nosql.appender.NoSqlProvider;
2827 import org.apache.logging.log4j.status.StatusLogger;
28 import org.apache.logging.log4j.util.LoaderUtil;
2929 import org.apache.logging.log4j.util.Strings;
3030 import org.lightcouch.CouchDbClient;
3131 import org.lightcouch.CouchDbProperties;
9292 String description;
9393 if (Strings.isNotEmpty(factoryClassName) && Strings.isNotEmpty(factoryMethodName)) {
9494 try {
95 final Class<?> factoryClass = Loader.loadClass(factoryClassName);
95 final Class<?> factoryClass = LoaderUtil.loadClass(factoryClassName);
9696 final Method method = factoryClass.getMethod(factoryMethodName);
9797 final Object object = method.invoke(null);
9898
2525 import org.apache.logging.log4j.core.config.plugins.Plugin;
2626 import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
2727 import org.apache.logging.log4j.core.config.plugins.PluginFactory;
28 import org.apache.logging.log4j.core.util.Loader;
2928 import org.apache.logging.log4j.core.util.NameUtil;
3029 import org.apache.logging.log4j.nosql.appender.NoSqlProvider;
3130 import org.apache.logging.log4j.status.StatusLogger;
31 import org.apache.logging.log4j.util.LoaderUtil;
3232 import org.apache.logging.log4j.util.Strings;
3333
3434 import com.mongodb.DB;
107107 String description;
108108 if (Strings.isNotEmpty(factoryClassName) && Strings.isNotEmpty(factoryMethodName)) {
109109 try {
110 final Class<?> factoryClass = Loader.loadClass(factoryClassName);
110 final Class<?> factoryClass = LoaderUtil.loadClass(factoryClassName);
111111 final Method method = factoryClass.getMethod(factoryMethodName);
112112 final Object object = method.invoke(null);
113113
205205 if (Strings.isNotEmpty(writeConcernConstant)) {
206206 if (Strings.isNotEmpty(writeConcernConstantClassName)) {
207207 try {
208 final Class<?> writeConcernConstantClass = Loader.loadClass(writeConcernConstantClassName);
208 final Class<?> writeConcernConstantClass = LoaderUtil.loadClass(writeConcernConstantClassName);
209209 final Field field = writeConcernConstantClass.getField(writeConcernConstant);
210210 writeConcern = (WriteConcern) field.get(null);
211211 } catch (final Exception e) {
4242 import org.apache.logging.log4j.ThreadContext;
4343 import org.apache.logging.log4j.core.LogEvent;
4444 import org.apache.logging.log4j.core.appender.AppenderLoggingException;
45 import org.apache.logging.log4j.junit.ThreadContextStackRule;
4546 import org.apache.logging.log4j.message.Message;
4647 import org.easymock.Capture;
4748 import org.easymock.EasyMock;
4849 import org.easymock.IAnswer;
4950 import org.junit.After;
5051 import org.junit.Before;
52 import org.junit.Rule;
5153 import org.junit.Test;
5254
5355 public class NoSqlDatabaseManagerTest {
5456 private NoSqlConnection<Map<String, Object>, DefaultNoSqlObject> connection;
5557 private NoSqlProvider<NoSqlConnection<Map<String, Object>, DefaultNoSqlObject>> provider;
5658
59 @Rule
60 public final ThreadContextStackRule threadContextRule = new ThreadContextStackRule();
61
5762 @Before
58 @SuppressWarnings("unchecked")
5963 public void setUp() {
6064 this.provider = createStrictMock(NoSqlProvider.class);
6165 this.connection = createStrictMock(NoSqlConnection.class);
6771 }
6872
6973 @Test
70 public void testConnection() {
71 replay(this.provider, this.connection);
72
74 public void testConnection() {
75 replay(this.provider, this.connection);
76
77 try (final NoSqlDatabaseManager<?> manager = NoSqlDatabaseManager.getNoSqlDatabaseManager("name", 0,
78 this.provider)) {
79
80 assertNotNull("The manager should not be null.", manager);
81
82 verify(this.provider, this.connection);
83 reset(this.provider, this.connection);
84 expect(this.provider.getConnection()).andReturn(this.connection);
85 replay(this.provider, this.connection);
86
87 manager.connectAndStart();
88 manager.commitAndClose();
89 }
90 }
91
92 @Test
93 public void testWriteInternalNotConnected01() {
94 replay(this.provider, this.connection);
95
96 try (final NoSqlDatabaseManager<?> manager = NoSqlDatabaseManager.getNoSqlDatabaseManager("name", 0,
97 this.provider)) {
98
99 verify(this.provider, this.connection);
100 reset(this.provider, this.connection);
101
102 final LogEvent event = createStrictMock(LogEvent.class);
103 replay(this.provider, this.connection, event);
104
105 try {
106 manager.writeInternal(event);
107 fail("Expected AppenderLoggingException.");
108 } catch (final AppenderLoggingException ignore) {
109 /* */
110 }
111
112 verify(event);
113 }
114 }
115
116 @Test
117 public void testWriteInternalNotConnected02() {
73118 final NoSqlDatabaseManager<?> manager = NoSqlDatabaseManager.getNoSqlDatabaseManager("name", 0, this.provider);
74119
75 assertNotNull("The manager should not be null.", manager);
76
77120 try {
121 replay(this.provider, this.connection);
122
123 manager.startup();
124
78125 verify(this.provider, this.connection);
79126 reset(this.provider, this.connection);
80127 expect(this.provider.getConnection()).andReturn(this.connection);
81128 replay(this.provider, this.connection);
82129
83130 manager.connectAndStart();
84 manager.commitAndClose();
85 } finally {
86 try {
87 manager.release();
88 } catch (final Throwable ignore) {
89 /* */
90 }
91 }
92 }
93
94 @Test
95 public void testWriteInternalNotConnected01() {
96 replay(this.provider, this.connection);
97
98 final NoSqlDatabaseManager<?> manager = NoSqlDatabaseManager.getNoSqlDatabaseManager("name", 0, this.provider);
99
100 try {
131
101132 verify(this.provider, this.connection);
102133 reset(this.provider, this.connection);
103134
104135 final LogEvent event = createStrictMock(LogEvent.class);
136 expect(this.connection.isClosed()).andReturn(true);
105137 replay(this.provider, this.connection, event);
106138
107139 try {
110142 } catch (final AppenderLoggingException ignore) {
111143 /* */
112144 }
113
114 verify(event);
115145 } finally {
116146 try {
117 manager.release();
118 } catch (final Throwable ignore) {
119 /* */
120 }
121 }
122 }
123
124 @Test
125 public void testWriteInternalNotConnected02() {
126 final NoSqlDatabaseManager<?> manager = NoSqlDatabaseManager.getNoSqlDatabaseManager("name", 0, this.provider);
127
128 try {
129 replay(this.provider, this.connection);
130
131 manager.startup();
132
133 verify(this.provider, this.connection);
134 reset(this.provider, this.connection);
135 expect(this.provider.getConnection()).andReturn(this.connection);
136 replay(this.provider, this.connection);
137
138 manager.connectAndStart();
139
140 verify(this.provider, this.connection);
141 reset(this.provider, this.connection);
142
143 final LogEvent event = createStrictMock(LogEvent.class);
144 expect(this.connection.isClosed()).andReturn(true);
145 replay(this.provider, this.connection, event);
146
147 try {
148 manager.writeInternal(event);
149 fail("Expected AppenderLoggingException.");
150 } catch (final AppenderLoggingException ignore) {
151 /* */
152 }
153 } finally {
154 try {
155 manager.release();
147 manager.close();
156148 } catch (final Throwable ignore) {
157149 /* */
158150 }
241233 verify(this.provider, this.connection, event, message);
242234 } finally {
243235 try {
244 manager.release();
236 manager.close();
245237 } catch (final Throwable ignore) {
246238 /* */
247239 }
378370 verify(this.provider, this.connection, event, message);
379371 } finally {
380372 try {
381 manager.release();
373 manager.close();
382374 } catch (final Throwable ignore) {
383375 /* */
384376 }
577569 verify(this.provider, this.connection, event, message);
578570 } finally {
579571 try {
580 manager.release();
572 manager.close();
581573 } catch (final Throwable ignore) {
582574 /* */
583575 }
+0
-4
log4j-perf/.gitignore less more
0 /.settings/
1 /target/
2 /.classpath
3 /.project
1919 <parent>
2020 <artifactId>log4j</artifactId>
2121 <groupId>org.apache.logging.log4j</groupId>
22 <version>2.6.2</version>
22 <version>2.7</version>
2323 <relativePath>../</relativePath>
2424 </parent>
2525
8888 <dependency>
8989 <groupId>com.lmax</groupId>
9090 <artifactId>disruptor</artifactId>
91 </dependency>
92 <dependency>
93 <groupId>com.conversantmedia</groupId>
94 <artifactId>disruptor</artifactId>
95 </dependency>
96 <dependency>
97 <groupId>org.jctools</groupId>
98 <artifactId>jctools-core</artifactId>
9199 </dependency>
92100 <!-- Embedded JDBC drivers for database appender tests -->
93101 <dependency>
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j;
17
18 /**
19 * <p>
20 * Utility class to access package protected methods in {@code ThreadContext}.
21 * </p>
22 *
23 * @see ThreadContext
24 * @since 2.7
25 */
26 public final class ThreadContextBenchmarkAccess {
27 private ThreadContextBenchmarkAccess() { // prevent instantiation
28 }
29
30 public static void init() {
31 ThreadContext.init();
32 }
33 }
2424 import org.apache.logging.log4j.perf.util.BenchmarkMessageParams;
2525 import org.openjdk.jmh.annotations.Benchmark;
2626 import org.openjdk.jmh.annotations.BenchmarkMode;
27 import org.openjdk.jmh.annotations.Fork;
2728 import org.openjdk.jmh.annotations.Level;
29 import org.openjdk.jmh.annotations.Measurement;
2830 import org.openjdk.jmh.annotations.Mode;
2931 import org.openjdk.jmh.annotations.OutputTimeUnit;
32 import org.openjdk.jmh.annotations.Param;
3033 import org.openjdk.jmh.annotations.Scope;
3134 import org.openjdk.jmh.annotations.Setup;
3235 import org.openjdk.jmh.annotations.State;
3336 import org.openjdk.jmh.annotations.TearDown;
37 import org.openjdk.jmh.annotations.Threads;
38 import org.openjdk.jmh.annotations.Warmup;
3439
35 import static org.apache.logging.log4j.perf.util.BenchmarkMessageParams.*;
40 import static org.apache.logging.log4j.perf.util.BenchmarkMessageParams.eight;
41 import static org.apache.logging.log4j.perf.util.BenchmarkMessageParams.eleven;
42 import static org.apache.logging.log4j.perf.util.BenchmarkMessageParams.five;
43 import static org.apache.logging.log4j.perf.util.BenchmarkMessageParams.four;
44 import static org.apache.logging.log4j.perf.util.BenchmarkMessageParams.nine;
45 import static org.apache.logging.log4j.perf.util.BenchmarkMessageParams.one;
46 import static org.apache.logging.log4j.perf.util.BenchmarkMessageParams.seven;
47 import static org.apache.logging.log4j.perf.util.BenchmarkMessageParams.six;
48 import static org.apache.logging.log4j.perf.util.BenchmarkMessageParams.ten;
49 import static org.apache.logging.log4j.perf.util.BenchmarkMessageParams.three;
50 import static org.apache.logging.log4j.perf.util.BenchmarkMessageParams.two;
3651
3752 /**
3853 * Tests Log4j2 Async Appender performance.
4055 // ============================== HOW TO RUN THIS TEST: ====================================
4156 //
4257 // single thread:
43 // java -jar log4j-perf/target/benchmarks.jar ".*AsyncAppenderLog4j2Benchmark.*" -f 1 -wi 10 -i 20
58 // java -jar log4j-perf/target/benchmarks.jar ".*AsyncAppenderLog4j2Benchmark.*"
4459 //
4560 // multiple threads (for example, 4 threads):
46 // java -jar log4j-perf/target/benchmarks.jar ".*AsyncAppenderLog4j2Benchmark.*" -f 1 -wi 10 -i 20 -t 4 -si true
61 // java -jar log4j-perf/target/benchmarks.jar ".*AsyncAppenderLog4j2Benchmark.*" -t 4 -si true
4762 //
4863 // Usage help:
4964 // java -jar log4j-perf/target/benchmarks.jar -help
5065 //
5166 @State(Scope.Benchmark)
67 @Fork(1)
68 @Warmup(iterations = 10)
69 @Measurement(iterations = 20)
70 @Threads(1)
5271 public class AsyncAppenderLog4j2Benchmark {
5372 Logger logger;
5473
74 @Param({
75 "perf5AsyncApndNoLoc-noOpAppender.xml",
76 "perf5AsyncApndDsrptrNoLoc-noOpAppender.xml",
77 "perf5AsyncApndMpscQNoLoc-noOpAppender.xml",
78 "perf5AsyncApndXferQNoLoc-noOpAppender.xml"
79 })
80 public String configFileName;
81
5582 @Setup(Level.Trial)
5683 public void up() {
57 System.setProperty("log4j.configurationFile", "perf5AsyncApndNoLoc-noOpAppender.xml");
84 System.setProperty("log4j.configurationFile", configFileName);
5885 logger = LogManager.getLogger(getClass());
5986 }
6087
2424 import org.apache.logging.log4j.perf.util.BenchmarkMessageParams;
2525 import org.openjdk.jmh.annotations.Benchmark;
2626 import org.openjdk.jmh.annotations.BenchmarkMode;
27 import org.openjdk.jmh.annotations.Fork;
2728 import org.openjdk.jmh.annotations.Level;
29 import org.openjdk.jmh.annotations.Measurement;
2830 import org.openjdk.jmh.annotations.Mode;
2931 import org.openjdk.jmh.annotations.OutputTimeUnit;
32 import org.openjdk.jmh.annotations.Param;
3033 import org.openjdk.jmh.annotations.Scope;
3134 import org.openjdk.jmh.annotations.Setup;
3235 import org.openjdk.jmh.annotations.State;
3336 import org.openjdk.jmh.annotations.TearDown;
37 import org.openjdk.jmh.annotations.Threads;
38 import org.openjdk.jmh.annotations.Warmup;
3439
3540 /**
3641 * Tests Log4j2 Async Appender performance when including caller location information.
3843 // ============================== HOW TO RUN THIS TEST: ====================================
3944 //
4045 // single thread:
41 // java -jar log4j-perf/target/benchmarks.jar ".*AsyncAppenderLog4j2LocationBenchmark.*" -f 1 -wi 10 -i 20
46 // java -jar log4j-perf/target/benchmarks.jar ".*AsyncAppenderLog4j2LocationBenchmark.*"
4247 //
4348 // multiple threads (for example, 4 threads):
44 // java -jar log4j-perf/target/benchmarks.jar ".*AsyncAppenderLog4j2LocationBenchmark.*" -f 1 -wi 10 -i 20 -t 4 -si true
49 // java -jar log4j-perf/target/benchmarks.jar ".*AsyncAppenderLog4j2LocationBenchmark.*" -t 4 -si true
4550 //
4651 // Usage help:
4752 // java -jar log4j-perf/target/benchmarks.jar -help
4853 //
4954 @State(Scope.Benchmark)
55 @Fork(1)
56 @Warmup(iterations = 10)
57 @Measurement(iterations = 20)
58 @Threads(1)
5059 public class AsyncAppenderLog4j2LocationBenchmark {
5160 Logger logger;
5261
62 @Param({
63 "perf5AsyncApndWithLoc-noOpAppender.xml",
64 "perf5AsyncApndDsrptrWithLoc-noOpAppender.xml",
65 "perf5AsyncApndMpscQWithLoc-noOpAppender.xml",
66 "perf5AsyncApndXferQWithLoc-noOpAppender.xml"
67 })
68 public String configFileName;
69
5370 @Setup(Level.Trial)
5471 public void up() {
55 System.setProperty("log4j.configurationFile", "perf5AsyncApndWithLoc-noOpAppender.xml");
72 System.setProperty("log4j.configurationFile", configFileName);
5673 logger = LogManager.getLogger(getClass());
5774 }
5875
135135 public void tearDown() throws SQLException {
136136 final LoggerContext context = LoggerContext.getContext(false);
137137 try {
138 ((JdbcAppender) context.getConfiguration().getAppender("H2Appender")).getManager().release();
139 ((JdbcAppender) context.getConfiguration().getAppender("HSQLDBAppender")).getManager().release();
138 ((JdbcAppender) context.getConfiguration().getAppender("H2Appender")).getManager().close();
139 ((JdbcAppender) context.getConfiguration().getAppender("HSQLDBAppender")).getManager().close();
140140 } finally {
141141 System.clearProperty(ConfigurationFactory.CONFIGURATION_FILE_PROPERTY);
142142 // context.reconfigure();
133133 public void tearDown() throws SQLException {
134134 final LoggerContext context = LoggerContext.getContext(false);
135135 try {
136 ((JpaAppender) context.getConfiguration().getAppender("H2Appender")).getManager().release();
137 ((JpaAppender) context.getConfiguration().getAppender("HSQLDBAppender")).getManager().release();
136 ((JpaAppender) context.getConfiguration().getAppender("H2Appender")).getManager().close();
137 ((JpaAppender) context.getConfiguration().getAppender("HSQLDBAppender")).getManager().close();
138138 } finally {
139139 System.clearProperty(ConfigurationFactory.CONFIGURATION_FILE_PROPERTY);
140140 // context.reconfigure();
2020 import org.apache.logging.log4j.Logger;
2121 import org.apache.logging.log4j.ThreadContext;
2222 import org.openjdk.jmh.annotations.Benchmark;
23 import org.openjdk.jmh.annotations.Param;
2324 import org.openjdk.jmh.annotations.Scope;
2425 import org.openjdk.jmh.annotations.Setup;
2526 import org.openjdk.jmh.annotations.State;
4445 Logger log4jLogger;
4546 org.slf4j.Logger slf4jLogger;
4647
48 @Param({"0", "4"})
49 public int size;
50
51 static int staticSize;
52
4753 @State(Scope.Thread)
4854 public static class ThreadContextState {
4955 // Thread scope: initialize MDC/ThreadContext here to ensure each thread has some value set
5056 public ThreadContextState() {
51 ThreadContext.put("user", "Apache");
52 MDC.put("user", "Apache");
57 for (int i = 0; i < staticSize; i++) {
58 ThreadContext.put("user" + i, "Apache");
59 MDC.put("user" + i, "Apache");
60 }
5361 }
5462
5563 public String message() {
6472
6573 log4jLogger = LogManager.getLogger(MDCFilterBenchmark.class);
6674 slf4jLogger = LoggerFactory.getLogger(MDCFilterBenchmark.class);
75
76 staticSize = size;
6777 }
6878
6979 @TearDown
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16
17 package org.apache.logging.log4j.perf.jmh;
18
19 import java.util.HashMap;
20 import java.util.Map;
21 import java.util.Random;
22 import java.util.concurrent.TimeUnit;
23
24 import org.apache.logging.log4j.perf.nogc.OpenHashStringMap;
25 import org.apache.logging.log4j.util.SortedArrayStringMap;
26 import org.apache.logging.log4j.util.BiConsumer;
27 import org.apache.logging.log4j.util.TriConsumer;
28 import org.openjdk.jmh.annotations.Benchmark;
29 import org.openjdk.jmh.annotations.BenchmarkMode;
30 import org.openjdk.jmh.annotations.Fork;
31 import org.openjdk.jmh.annotations.Measurement;
32 import org.openjdk.jmh.annotations.Mode;
33 import org.openjdk.jmh.annotations.OutputTimeUnit;
34 import org.openjdk.jmh.annotations.Param;
35 import org.openjdk.jmh.annotations.Scope;
36 import org.openjdk.jmh.annotations.Setup;
37 import org.openjdk.jmh.annotations.State;
38 import org.openjdk.jmh.annotations.Warmup;
39
40 /**
41 * Compares performance of SortedArrayStringMap vs. OpenHashMap vs. JDK HashMap.
42 */
43 // ============================== HOW TO RUN THIS TEST: ====================================
44 // (Quick build: mvn -DskipTests=true clean package -pl log4j-perf -am )
45 //
46 // single thread:
47 // java -jar log4j-perf/target/benchmarks.jar ".*SortedArrayVsHashMapBenchmark.*" -f 1 -wi 10 -i 20 -tu ns -bm sample
48 //
49 //
50 // Usage help:
51 // java -jar log4j-perf/target/benchmarks.jar -help
52 //
53
54 @BenchmarkMode(Mode.AverageTime)
55 @OutputTimeUnit(TimeUnit.NANOSECONDS)
56 @Warmup(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
57 @Measurement(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
58 @Fork(1)
59 @State(Scope.Benchmark)
60 public class SortedArrayVsHashMapBenchmark {
61
62 //@Param({"1", "2", "5", "11", "23", "47", "95", "191", "383"})
63 //@Param({"1", "5", "50", "500"})
64 @Param({ "5", "500"})
65 public int count;
66
67 //@Param({"5", "50"})
68 @Param({"20"})
69 public int length;
70
71 private String[] keys;
72 private static Object value = new Object();
73 private HashMap<String, Object> map;
74 private SortedArrayStringMap sortedStringArrayMap;
75 private OpenHashStringMap<String, Object> openHashMapContextData;
76
77 private HashMap<String, Object> populatedMap;
78 private SortedArrayStringMap populatedSortedStringArrayMap;
79 private OpenHashStringMap<String, Object> populatedOpenHashContextData;
80
81 @Setup
82 public void setup() {
83 openHashMapContextData = new OpenHashStringMap<>();
84 sortedStringArrayMap = new SortedArrayStringMap();
85 map = new HashMap<>();
86
87 keys = new String[count];
88 final Random r = new Random();
89 for (int j = 0; j < keys.length; j++) {
90 final char[] str = new char[length];
91 for (int i = 0; i < str.length; i++) {
92 str[i] = (char) r.nextInt();
93 }
94 keys[j] = new String(str);
95 }
96
97 populatedMap = new HashMap<>();
98 for (int i = 0; i < count; i++) {
99 populatedMap.put(keys[i], value);
100 }
101 populatedSortedStringArrayMap = new SortedArrayStringMap();
102 for (int i = 0; i < count; i++) {
103 populatedSortedStringArrayMap.putValue(keys[i], value);
104 }
105 populatedOpenHashContextData = new OpenHashStringMap<>();
106 for (int i = 0; i < count; i++) {
107 populatedOpenHashContextData.putValue(keys[i], value);
108 }
109 }
110
111 @Benchmark
112 public SortedArrayStringMap putAllArrayContextData() {
113 sortedStringArrayMap.clear();
114 sortedStringArrayMap.putAll(populatedSortedStringArrayMap);
115 return sortedStringArrayMap;
116 }
117
118 @Benchmark
119 public OpenHashStringMap<String, Object> putAllHashContextData() {
120 openHashMapContextData.clear();
121 openHashMapContextData.putAll(populatedOpenHashContextData);
122 return openHashMapContextData;
123 }
124
125 @Benchmark
126 public Map putAllMap() {
127 map.clear();
128 map.putAll(populatedMap);
129 return map;
130 }
131
132 @Benchmark
133 public SortedArrayStringMap cloneArrayContextData() {
134 return new SortedArrayStringMap(populatedSortedStringArrayMap);
135 }
136
137 @Benchmark
138 public OpenHashStringMap<String, Object> cloneHashContextData() {
139 return new OpenHashStringMap<>(populatedOpenHashContextData);
140 }
141
142 @Benchmark
143 public Map cloneMap() {
144 return new HashMap(populatedMap);
145 }
146
147 static TriConsumer<String, Object, int[]> COUNTER = new TriConsumer<String, Object, int[]>() {
148 @Override
149 public void accept(final String s, final Object o, final int[] result) {
150 result[0] += s.hashCode() + o.hashCode();
151 }
152 };
153
154 @Benchmark
155 public int iterateArrayContextDataTriConsumer() {
156 final int[] result = {0};
157
158 populatedSortedStringArrayMap.forEach(COUNTER, result);
159 return result[0];
160 }
161
162 @Benchmark
163 public int iterateHashContextDataTriConsumer() {
164 final int[] result = {0};
165
166 populatedOpenHashContextData.forEach(COUNTER, result);
167 return result[0];
168 }
169
170 @Benchmark
171 public int iterateArrayContextDataBiConsumer() {
172 final int[] result = {0};
173
174 populatedSortedStringArrayMap.forEach(new BiConsumer<String, Object>() {
175 @Override
176 public void accept(final String s, final Object o) {
177 result[0] += s.hashCode() + o.hashCode();
178 }
179 });
180 return result[0];
181 }
182
183 @Benchmark
184 public int iterateHashContextDataBiConsumer() {
185 final int[] result = {0};
186
187 populatedOpenHashContextData.forEach(new BiConsumer<String, Object>() {
188 @Override
189 public void accept(final String s, final Object o) {
190 result[0] += s.hashCode() + o.hashCode();
191 }
192 });
193 return result[0];
194 }
195
196 @Benchmark
197 public int iterateMap() {
198 final int[] result = {0};
199
200 for (final Map.Entry<String, Object> entry : populatedMap.entrySet()) {
201 result[0] += entry.getKey().hashCode() + entry.getValue().hashCode();
202 }
203 return result[0];
204 }
205
206 @Benchmark
207 public Object getValueArrayContextData() {
208 return populatedSortedStringArrayMap.getValue(keys[count - 1]);
209 }
210
211 @Benchmark
212 public Object getValueHashContextData() {
213 return populatedOpenHashContextData.getValue(keys[count - 1]);
214 }
215
216 @Benchmark
217 public Object getValueMap() {
218 return populatedMap.get(keys[count - 1]);
219 }
220
221 @Benchmark
222 public int putArrayContextData() {
223 populatedSortedStringArrayMap.putValue("someKey", "someValue");
224 return populatedSortedStringArrayMap.size();
225 }
226
227 @Benchmark
228 public int putHashContextData() {
229 openHashMapContextData.put("someKey", "someValue");
230 return openHashMapContextData.size();
231 }
232
233 @Benchmark
234 public int putMap() {
235 map.put("someKey", "someValue");
236 return map.size();
237 }
238 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16
17 package org.apache.logging.log4j.perf.jmh;
18
19 import java.util.ArrayList;
20 import java.util.Collections;
21 import java.util.HashMap;
22 import java.util.List;
23 import java.util.Map;
24 import java.util.Random;
25 import java.util.concurrent.TimeUnit;
26
27 import org.apache.logging.log4j.ThreadContext;
28 import org.apache.logging.log4j.ThreadContextBenchmarkAccess;
29 import org.apache.logging.log4j.core.config.Property;
30 import org.apache.logging.log4j.core.ContextDataInjector;
31 import org.apache.logging.log4j.core.impl.ContextDataInjectorFactory;
32 import org.apache.logging.log4j.perf.nogc.OpenHashStringMap;
33 import org.apache.logging.log4j.spi.CopyOnWriteOpenHashMapThreadContextMap;
34 import org.apache.logging.log4j.spi.DefaultThreadContextMap;
35 import org.apache.logging.log4j.spi.GarbageFreeOpenHashMapThreadContextMap;
36 import org.apache.logging.log4j.util.SortedArrayStringMap;
37 import org.apache.logging.log4j.util.StringMap;
38 import org.apache.logging.log4j.spi.ThreadContextMap;
39 import org.openjdk.jmh.annotations.Benchmark;
40 import org.openjdk.jmh.annotations.BenchmarkMode;
41 import org.openjdk.jmh.annotations.Fork;
42 import org.openjdk.jmh.annotations.Measurement;
43 import org.openjdk.jmh.annotations.Mode;
44 import org.openjdk.jmh.annotations.OutputTimeUnit;
45 import org.openjdk.jmh.annotations.Param;
46 import org.openjdk.jmh.annotations.Scope;
47 import org.openjdk.jmh.annotations.Setup;
48 import org.openjdk.jmh.annotations.State;
49 import org.openjdk.jmh.annotations.TearDown;
50 import org.openjdk.jmh.annotations.Warmup;
51
52 /**
53 * Compares performance of ThreadContextMap implementations.
54 */
55 // ============================== HOW TO RUN THIS TEST: ====================================
56 // (Quick build: mvn -DskipTests=true clean package -pl log4j-perf -am )
57 //
58 // single thread:
59 // java -jar log4j-perf/target/benchmarks.jar ".*ThreadContextBench.*"
60 //
61 // four threads:
62 // java -jar log4j-perf/target/benchmarks.jar ".*ThreadContextBench.*" -f 1 -wi 10 -i 20 -tu ns -bm sample -t 4
63 //
64 // Usage help:
65 // java -jar log4j-perf/target/benchmarks.jar -help
66 //
67 @BenchmarkMode(Mode.AverageTime)
68 @OutputTimeUnit(TimeUnit.NANOSECONDS)
69 @Warmup(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
70 @Measurement(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
71 @Fork(1)
72 @State(Scope.Benchmark)
73 public class ThreadContextBenchmark {
74 private static final String DEFAULT_CONTEXT_MAP = "Default";
75 private static final String COPY_OPENHASH_MAP = "CopyOpenHash";
76 private static final String COPY_ARRAY_MAP = "CopySortedArray";
77 private static final String NO_GC_OPENHASH_MAP = "NoGcOpenHash";
78 private static final String NO_GC_ARRAY_MAP = "NoGcSortedArray";
79 private static final Map<String, Class<? extends ThreadContextMap>> IMPLEMENTATIONS = new HashMap<>();
80 static {
81 IMPLEMENTATIONS.put(DEFAULT_CONTEXT_MAP, DefaultThreadContextMap.class);
82 IMPLEMENTATIONS.put(COPY_OPENHASH_MAP, CopyOnWriteOpenHashMapThreadContextMap.class);
83 IMPLEMENTATIONS.put(COPY_ARRAY_MAP, CopyOnWriteOpenHashMapThreadContextMap.SUPER); //CopyOnWriteSortedArrayThreadContextMap.class);
84 IMPLEMENTATIONS.put(NO_GC_OPENHASH_MAP, GarbageFreeOpenHashMapThreadContextMap.class);
85 IMPLEMENTATIONS.put(NO_GC_ARRAY_MAP, GarbageFreeOpenHashMapThreadContextMap.SUPER); //GarbageFreeSortedArrayThreadContextMap.class);
86 }
87
88 @Param({ "Default", "CopyOpenHash", "CopySortedArray", "NoGcOpenHash", "NoGcSortedArray"})
89 //@Param({ "Default", }) // for legecyInject benchmarks
90 public String threadContextMapAlias;
91
92 @Param({"5", "50", "500"})
93 public int count;
94
95 private final int KEY_LENGTH = 16;
96 private String[] keys;
97 private String[] values;
98 private List<Property> propertyList;
99
100 private ContextDataInjector injector;
101 private StringMap reusableContextData;
102
103 @Setup
104 public void setup() {
105 System.setProperty("log4j2.threadContextMap", IMPLEMENTATIONS.get(threadContextMapAlias).getName());
106 ThreadContextBenchmarkAccess.init();
107
108 injector = ContextDataInjectorFactory.createInjector();
109 System.out.println(threadContextMapAlias + ": Injector = " + injector);
110
111 reusableContextData = threadContextMapAlias.contains("Array")
112 ? new SortedArrayStringMap()
113 : new OpenHashStringMap<>();
114
115 keys = new String[count];
116 values = new String[count];
117 final Random r = new Random();
118 for (int j = 0; j < keys.length; j++) {
119 final char[] str = new char[KEY_LENGTH];
120 for (int i = 0; i < str.length; i++) {
121 str[i] = (char) r.nextInt();
122 }
123 keys[j] = new String(str);
124 values[j] = new String(str);
125 }
126 final int PROPERTIES_COUNT = 5; // count
127 propertyList = new ArrayList<>(PROPERTIES_COUNT);
128 for (int j = 0; j < PROPERTIES_COUNT; j++) {
129 final char[] str = new char[KEY_LENGTH];
130 for (int i = 0; i < str.length; i++) {
131 str[i] = (char) r.nextInt();
132 }
133 propertyList.add(Property.createProperty(new String(str), new String(str)));
134 }
135
136 clearAndPut(); // ensure ThreadContext contains values
137 }
138
139 @TearDown
140 public void tearDown() {
141 System.clearProperty("log4j2.threadContextMap");
142 ThreadContextBenchmarkAccess.init();
143 }
144
145 public void clearAndPut() {
146 ThreadContext.clearMap();
147 for (int i = 0; i < count; i++) {
148 ThreadContext.put(keys[i], values[i]);
149 }
150 }
151
152 @Benchmark
153 public Object get() {
154 return ThreadContext.get(keys[count - 1]);
155 }
156
157 @Benchmark
158 public void putAndRemove() {
159 ThreadContext.put("someKey", "someValue");
160 ThreadContext.remove("someKey");
161 }
162
163 @Benchmark
164 public StringMap injectWithoutProperties() {
165 reusableContextData.clear();
166 return injector.injectContextData(null, reusableContextData);
167 }
168
169 @Benchmark
170 public StringMap injectWithProperties() {
171 reusableContextData.clear();
172 return injector.injectContextData(propertyList, reusableContextData);
173 }
174
175 @Benchmark
176 public Map<String, String> legacyInjectWithoutProperties() {
177 return createMap(null);
178 }
179
180 @Benchmark
181 public Map<String, String> legacyInjectWithProperties() {
182 return createMap(propertyList);
183 }
184
185 // from Log4jLogEvent::createMap
186 static Map<String, String> createMap(final List<Property> properties) {
187 final Map<String, String> contextMap = ThreadContext.getImmutableContext();
188 if (properties == null || properties.isEmpty()) {
189 return contextMap; // may be ThreadContext.EMPTY_MAP but not null
190 }
191 final Map<String, String> map = new HashMap<>(contextMap);
192
193 for (final Property prop : properties) {
194 if (!map.containsKey(prop.getName())) {
195 map.put(prop.getName(), prop.getValue());
196 }
197 }
198 return Collections.unmodifiableMap(map);
199 }
200 }
8080 final Configuration config = new DefaultConfiguration();
8181 final PatternParser parser = new PatternParser(config, "Converter", LogEventPatternConverter.class);
8282 final List<PatternFormatter> result = parser.parse(LOG4JPATTERN, false, true);
83 return (PatternFormatter[]) result.toArray(new PatternFormatter[result.size()]);
83 return result.toArray(new PatternFormatter[result.size()]);
8484 }
8585
8686 @Benchmark
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.perf.nogc;
17
18 import java.io.IOException;
19 import java.io.ObjectInputStream;
20 import java.io.ObjectOutputStream;
21 import java.util.Arrays;
22 import java.util.Collections;
23 import java.util.ConcurrentModificationException;
24 import java.util.HashMap;
25 import java.util.Map;
26 import java.util.Objects;
27
28 import org.apache.logging.log4j.util.ReadOnlyStringMap;
29 import org.apache.logging.log4j.util.StringMap;
30 import org.apache.logging.log4j.spi.ThreadContextMap;
31 import org.apache.logging.log4j.util.BiConsumer;
32 import org.apache.logging.log4j.util.TriConsumer;
33
34 /**
35 * Open hash map-based implementation of the {@code ReadOnlyStringMap} interface.
36 * Implementation based on <a href="http://fastutil.di.unimi.it/">fastutil</a>'s
37 * <a href="http://fastutil.di.unimi.it/docs/it/unimi/dsi/fastutil/objects/Object2ObjectOpenHashMap.html">Object2ObjectOpenHashMap</a>.
38 * <p>
39 * A type-specific hash map with a fast, small-footprint implementation.
40 *
41 * <P>
42 * Instances of this class use a hash table to represent a map. The table is
43 * filled up to a specified <em>load factor</em>, and then doubled in size to
44 * accommodate new entries. If the table is emptied below <em>one fourth</em> of
45 * the load factor, it is halved in size. However, halving is not performed when
46 * deleting entries from an iterator, as it would interfere with the iteration
47 * process.
48 *
49 * <p>
50 * Note that {@link #clear()} does not modify the hash table size. Rather, the
51 * {@link #trim(int)} method lets you control the size of
52 * the table; this is particularly useful if you reuse instances of this class.
53 * <p>
54 * <ul>
55 * <li>Garbage-free iteration over key-value pairs with {@code BiConsumer} and {@code TriConsumer}.</li>
56 * <li>Fast copy. If the ThreadContextMap is also an instance of {@code OpenHashStringMap},
57 * the full thread context data can be transferred with two array copies and five field updates.</li>
58 * </ul>
59 *
60 * @since 2.7
61 */
62 public class OpenHashStringMap<K, V> implements StringMap, ThreadContextMap {
63 /** The initial default size of a hash table. */
64 public static final int DEFAULT_INITIAL_SIZE = 16;
65
66 /** The default load factor of a hash table. */
67 public static final float DEFAULT_LOAD_FACTOR = .75f;
68
69 private static final String FROZEN = "Frozen collection cannot be modified";
70 private static final long serialVersionUID = -1486744623338827187L;
71
72 /** The array of keys. */
73 protected transient K[] keys;
74 /** The array of values. */
75 protected transient V[] values;
76 /** The mask for wrapping a position counter. */
77 protected transient int mask;
78 /** Whether this set contains the key zero. */
79 protected transient boolean containsNullKey;
80 /** The current table size. */
81 protected transient int arraySize;
82 /**
83 * Threshold after which we rehash. It must be the table size times {@link #loadFactor}.
84 */
85 protected transient int maxFill;
86 /** Number of entries in the set (including the key zero, if present). */
87 protected int size;
88 /** The acceptable load factor. */
89 protected final float loadFactor;
90
91 private final V defRetValue = null;
92 private boolean immutable;
93 private transient boolean iterating;
94
95 /**
96 * Creates a new hash map with initial expected
97 * {@link #DEFAULT_INITIAL_SIZE} entries and
98 * {@link #DEFAULT_LOAD_FACTOR} as load factor.
99 */
100 public OpenHashStringMap() {
101 this(DEFAULT_INITIAL_SIZE, DEFAULT_LOAD_FACTOR);
102 }
103 /**
104 * Creates a new hash map with {@link #DEFAULT_LOAD_FACTOR} as load factor.
105 *
106 * @param expected
107 * the expected number of elements in the hash map.
108 */
109 public OpenHashStringMap(final int expected) {
110 this(expected, DEFAULT_LOAD_FACTOR);
111 }
112 /**
113 * Creates a new hash map.
114 *
115 * <p>
116 * The actual table size will be the least power of two greater than
117 * <code>expected</code>/<code>f</code>.
118 *
119 * @param expected
120 * the expected number of elements in the hash set.
121 * @param f
122 * the load factor.
123 */
124 @SuppressWarnings("unchecked")
125 public OpenHashStringMap(final int expected, final float f) {
126 if (f <= 0 || f > 1) {
127 throw new IllegalArgumentException(
128 "Load factor must be greater than 0 and smaller than or equal to 1");
129 }
130 if (expected < 0){
131 throw new IllegalArgumentException(
132 "The expected number of elements must be nonnegative");
133 }
134 this.loadFactor = f;
135 arraySize = HashCommon.arraySize(expected, f);
136 mask = arraySize - 1;
137 maxFill = HashCommon.maxFill(arraySize, f);
138 keys = (K[]) new Object[arraySize + 1];
139 values = (V[]) new Object[arraySize + 1];
140 }
141 /**
142 * Creates a new hash map with {@link #DEFAULT_LOAD_FACTOR} as load
143 * factor copying a given one.
144 *
145 * @param map
146 * a {@link Map} to be copied into the new hash map.
147 */
148 public OpenHashStringMap(final Map<? extends K, ? extends V> map) {
149 this(map, DEFAULT_LOAD_FACTOR);
150 }
151 /**
152 * Creates a new hash map copying a given one.
153 *
154 * @param map
155 * a {@link Map} to be copied into the new hash map.
156 * @param f
157 * the load factor.
158 */
159 public OpenHashStringMap(final Map<? extends K, ? extends V> map, final float f) {
160 this(map.size(), f);
161 putAll(map);
162 }
163
164 /**
165 * Creates a new hash map with {@link #DEFAULT_LOAD_FACTOR} as load
166 * factor copying a given type-specific one.
167 *
168 * @param contextData
169 * a type-specific map to be copied into the new hash map.
170 */
171 public OpenHashStringMap(final ReadOnlyStringMap contextData) {
172 this(contextData, DEFAULT_LOAD_FACTOR);
173 }
174 /**
175 * Creates a new hash map copying a given type-specific one.
176 *
177 * @param contextData
178 * a type-specific map to be copied into the new hash map.
179 * @param f
180 * the load factor.
181 */
182 public OpenHashStringMap(final ReadOnlyStringMap contextData, final float f) {
183 this(contextData.size(), f);
184 if (contextData instanceof OpenHashStringMap) {
185 initFrom0((OpenHashStringMap) contextData);
186 } else {
187 contextData.forEach(PUT_ALL, this);
188 }
189 }
190 private static final TriConsumer<String, Object, StringMap> PUT_ALL =
191 new TriConsumer<String, Object, StringMap>() {
192 @Override
193 public void accept(final String key, final Object value, final StringMap contextData) {
194 contextData.putValue(key, value);
195 }
196 };
197
198 private void assertNotFrozen() {
199 if (immutable) {
200 throw new UnsupportedOperationException(FROZEN);
201 }
202 }
203
204 private void assertNoConcurrentModification() {
205 if (iterating) {
206 throw new ConcurrentModificationException();
207 }
208 }
209
210 @SuppressWarnings("unchecked")
211 private void initFrom0(final OpenHashStringMap other) {
212 // this.loadFactor = other.loadFactor; // final field
213 this.arraySize = other.arraySize;
214 this.size = other.size;
215 this.containsNullKey = other.containsNullKey;
216 this.mask = other.mask;
217 this.maxFill = other.maxFill;
218 keys = (K[]) Arrays.copyOf(other.keys, arraySize + 1);
219 values = (V[]) Arrays.copyOf(other.values, arraySize + 1);
220 }
221
222 private int realSize() {
223 return containsNullKey ? size - 1 : size;
224 }
225
226 private void ensureCapacity(final int capacity) {
227 final int needed = HashCommon.arraySize(capacity, loadFactor);
228 if (needed > arraySize) {
229 rehash(needed);
230 }
231 }
232
233 private void tryCapacity(final long capacity) {
234 final int needed = Math.min(
235 1 << 30, Math.max(2, HashCommon.nextPowerOfTwo((int) Math.ceil(capacity / loadFactor))));
236 if (needed > arraySize) {
237 rehash(needed);
238 }
239 }
240
241 @Override
242 public Map<String, String> toMap() {
243 final Map<String, String> result = new HashMap<>(size);
244 forEach(COPY_INTO_MAP, result);
245 return result;
246 }
247
248 private static final TriConsumer<String, Object, Map<String, String>> COPY_INTO_MAP =
249 new TriConsumer<String, Object, Map<String, String>>() {
250 @Override
251 public void accept(final String k, final Object v, final Map<String, String> map) {
252 map.put(k, v == null ? null : v.toString());
253 }
254 };
255
256 /*
257 * Removes all elements from this map.
258 *
259 * <P>To increase object reuse, this method does not change the table size.
260 * If you want to reduce the table size, you must use {@link #trim()}.
261 */
262 @Override
263 public void clear() {
264 if (size == 0) {
265 return;
266 }
267 assertNotFrozen();
268 assertNoConcurrentModification();
269
270 size = 0;
271 containsNullKey = false;
272 Arrays.fill(keys, (null));
273 Arrays.fill(values, null);
274 }
275
276 @Override
277 public boolean containsKey(final String key) {
278 return containsObjectKey(key);
279 }
280
281 @SuppressWarnings("unchecked")
282 private boolean containsObjectKey(final Object k) {
283 if (k == null) {
284 return containsNullKey;
285 }
286 K curr;
287 final K[] key = this.keys;
288 int pos;
289 // The starting point.
290 if ((curr = key[pos = HashCommon.mix(k.hashCode()) & mask]) == null) {
291 return false;
292 }
293 if (k.equals(curr)) {
294 return true;
295 }
296 // There's always an unused entry.
297 while (true) {
298 if ((curr = key[pos = (pos + 1) & mask]) == null) {
299 return false;
300 }
301 if (k.equals(curr)) {
302 return true;
303 }
304 }
305 }
306
307 @Override
308 public boolean equals(final Object obj) {
309 if (obj == this) {
310 return true;
311 }
312 if (!(obj instanceof ReadOnlyStringMap)) {
313 return false;
314 }
315 final ReadOnlyStringMap other = (ReadOnlyStringMap) obj;
316 if (other.size() != size()) {
317 return false;
318 }
319 int pos = arraySize;
320 if (containsNullKey) {
321 if (!Objects.equals(getObjectValue(null), other.getValue(null))) {
322 return false;
323 }
324 }
325 --pos;
326 final K myKeys[] = this.keys;
327 for (; pos >= 0; pos--) {
328 K k;
329 if ((k = myKeys[pos]) != null) {
330 if (!Objects.equals(values[pos], other.getValue((String) k))) {
331 return false;
332 }
333 }
334 }
335 return true;
336 }
337
338 @Override
339 @SuppressWarnings("unchecked")
340 public <VAL> void forEach(final BiConsumer<String, ? super VAL> action) {
341 final int startSize = size;
342 final K myKeys[] = this.keys;
343 int pos = arraySize;
344
345 iterating = true;
346 try {
347 if (containsNullKey) {
348 action.accept((String) myKeys[pos], (VAL) values[pos]);
349 if (size != startSize) {
350 throw new ConcurrentModificationException();
351 }
352 }
353 --pos;
354 for (; pos >= 0; pos--) {
355 if (myKeys[pos] != null) {
356 action.accept((String) myKeys[pos], (VAL) values[pos]);
357 if (size != startSize) {
358 throw new ConcurrentModificationException();
359 }
360 }
361 }
362 } finally {
363 iterating = false;
364 }
365 }
366
367 @Override
368 @SuppressWarnings("unchecked")
369 public <VAL, STATE> void forEach(final TriConsumer<String, ? super VAL, STATE> action, final STATE state) {
370 final int startSize = size;
371 final K myKeys[] = this.keys;
372 int pos = arraySize;
373
374 iterating = true;
375 try {
376 if (containsNullKey) {
377 action.accept((String) myKeys[pos], (VAL) values[pos], state);
378 if (size != startSize) {
379 throw new ConcurrentModificationException();
380 }
381 }
382 --pos;
383 for (; pos >= 0; pos--) {
384 if (myKeys[pos] != null) {
385 action.accept((String) myKeys[pos], (VAL) values[pos], state);
386 if (size != startSize) {
387 throw new ConcurrentModificationException();
388 }
389 }
390 }
391 } finally {
392 iterating = false;
393 }
394 }
395
396 @Override
397 public String get(final String key) {
398 return (String) getObjectValue(key);
399 }
400
401 @SuppressWarnings("unchecked")
402 private V getObjectValue(final Object k) {
403 if (k == null) {
404 return containsNullKey ? values[arraySize] : defRetValue;
405 }
406 K curr;
407 final K[] key = this.keys;
408 int pos;
409 // The starting point.
410 if ((curr = key[pos = HashCommon.mix(k.hashCode()) & mask]) == null) {
411 return defRetValue;
412 }
413 if (k.equals(curr)) {
414 return values[pos];
415 }
416 // There's always an unused entry.
417 while (true) {
418 if (((curr = key[pos = (pos + 1) & mask]) == null)) {
419 return defRetValue;
420 }
421 if (k.equals(curr)) {
422 return values[pos];
423 }
424 }
425 }
426
427 @Override
428 public Map<String, String> getCopy() {
429 return toMap();
430 }
431
432 @Override
433 public Map<String, String> getImmutableMapOrNull() {
434 return isEmpty() ? null : Collections.unmodifiableMap(toMap());
435 }
436
437 @Override
438 public <VAL> VAL getValue(final String key) {
439 return (VAL) getObjectValue(key);
440 }
441
442 @Override
443 public boolean isEmpty() {
444 return size == 0;
445 }
446
447 @Override
448 @SuppressWarnings("unchecked")
449 public void put(final String key, final String value) {
450 putObjectValue((K) key, (V) value);
451 }
452
453 private int insert(final K k, final V v) {
454 int pos;
455 if (k == null) {
456 if (containsNullKey) {
457 return arraySize;
458 }
459 containsNullKey = true;
460 pos = arraySize;
461 } else {
462 K curr;
463 final K[] key = this.keys;
464 // The starting point.
465 if (!((curr = key[pos = HashCommon.mix(k.hashCode()) & mask]) == null)) {
466 if (curr.equals(k)) {
467 return pos;
468 }
469 while (!((curr = key[pos = (pos + 1) & mask]) == null)) {
470 if (curr.equals(k)) {
471 return pos;
472 }
473 }
474 }
475 }
476 keys[pos] = k;
477 values[pos] = v;
478 if (size++ >= maxFill) {
479 rehash(HashCommon.arraySize(size + 1, loadFactor));
480 }
481 return -1;
482 }
483
484 @Override
485 public void putAll(final ReadOnlyStringMap source) {
486 assertNotFrozen();
487 assertNoConcurrentModification();
488
489 if (size() == 0 && source instanceof OpenHashStringMap) {
490 initFrom0((OpenHashStringMap) source);
491 } else if (source != null) {
492 source.forEach(PUT_ALL, this);
493 }
494 }
495
496 /** {@inheritDoc} */
497 public void putAll(final Map<? extends K, ? extends V> map) {
498 if (loadFactor <= .5) {
499 // The resulting map will be sized for m.size() elements
500 ensureCapacity(map.size());
501 } else {
502 // The resulting map will be tentatively sized for size() + m.size() elements
503 tryCapacity(size() + map.size());
504 }
505 for (final Map.Entry<? extends K, ? extends V> entry : map.entrySet()) {
506 putObjectValue(entry.getKey(), entry.getValue());
507 }
508 }
509
510 private V putObjectValue(final K k, final V v) {
511 assertNotFrozen();
512 assertNoConcurrentModification();
513
514 final int pos = insert(k, v);
515 if (pos < 0) {
516 return defRetValue;
517 }
518 final V oldValue = values[pos];
519 values[pos] = v;
520 return oldValue;
521 }
522
523 @Override
524 @SuppressWarnings("unchecked")
525 public void putValue(final String key, final Object value) {
526 putObjectValue((K) key, (V) value);
527 }
528
529 @Override
530 public void remove(final String key) {
531 removeObjectKey(key);
532 }
533
534 @Override
535 public void freeze() {
536 immutable = true;
537 }
538
539 @Override
540 public boolean isFrozen() {
541 return immutable;
542 }
543
544 @SuppressWarnings("unchecked")
545 private V removeObjectKey(final Object k) {
546 assertNotFrozen();
547 assertNoConcurrentModification();
548
549 if (k == null) {
550 if (containsNullKey) {
551 return removeNullEntry();
552 }
553 return defRetValue;
554 }
555 final K[] key = this.keys;
556 int pos = HashCommon.mix(k.hashCode()) & mask;
557 K curr = key[pos & mask];
558 // The starting point.
559 if (curr == null) {
560 return defRetValue;
561 }
562 if (k.equals(curr)) {
563 return removeEntry(pos);
564 }
565 while (true) {
566 if ((curr = key[pos = (pos + 1) & mask]) == null) {
567 return defRetValue;
568 }
569 if (k.equals(curr)) {
570 return removeEntry(pos);
571 }
572 }
573 }
574 private V removeEntry(final int pos) {
575 final V oldValue = values[pos];
576 values[pos] = null;
577 size--;
578 shiftKeys(pos);
579 if (size < maxFill / 4 && arraySize > DEFAULT_INITIAL_SIZE) {
580 rehash(arraySize / 2);
581 }
582 return oldValue;
583 }
584 private V removeNullEntry() {
585 containsNullKey = false;
586 keys[arraySize] = null;
587 final V oldValue = values[arraySize];
588 values[arraySize] = null;
589 size--;
590 if (size < maxFill / 4 && arraySize > DEFAULT_INITIAL_SIZE) {
591 rehash(arraySize / 2);
592 }
593 return oldValue;
594 }
595 /**
596 * Shifts left entries with the specified hash code, starting at the
597 * specified position, and empties the resulting free entry.
598 *
599 * @param pos
600 * a starting position.
601 */
602 private void shiftKeys(int pos) {
603 // Shift entries with the same hash.
604 int last, slot;
605 K curr;
606 final K[] myKeys = this.keys;
607 for (;;) {
608 pos = ((last = pos) + 1) & mask;
609 for (;;) {
610 if (((curr = myKeys[pos]) == null)) {
611 myKeys[last] = (null);
612 values[last] = null;
613 return;
614 }
615 slot = HashCommon.mix(curr.hashCode()) & mask;
616 if (last <= pos ? (last >= slot || slot > pos) : (last >= slot && slot > pos)) {
617 break;
618 }
619 pos = (pos + 1) & mask;
620 }
621 myKeys[last] = curr;
622 values[last] = values[pos];
623 }
624 }
625
626 @Override
627 public int size() {
628 return size;
629 }
630
631 /**
632 * Rehashes this map if the table is too large.
633 *
634 * <P>
635 * Let <var>N</var> be the smallest table size that can hold
636 * <code>max(n,{@link #size()})</code> entries, still satisfying the load
637 * factor. If the current table size is smaller than or equal to
638 * <var>N</var>, this method does nothing. Otherwise, it rehashes this map
639 * in a table of size <var>N</var>.
640 *
641 * <P>
642 * This method is useful when reusing maps. {@linkplain #clear() Clearing a
643 * map} leaves the table size untouched. If you are reusing a map many times,
644 * you can call this method with a typical size to avoid keeping around a
645 * very large table just because of a few large transient maps.
646 *
647 * @param n
648 * the threshold for the trimming.
649 * @return true if there was enough memory to trim the map.
650 */
651 public boolean trim(final int n) {
652 final int l = HashCommon.nextPowerOfTwo((int) Math.ceil(n / loadFactor));
653 if (l >= n || size > HashCommon.maxFill(l, loadFactor)) {
654 return true;
655 }
656 try {
657 rehash(l);
658 } catch (final OutOfMemoryError cantDoIt) { // unusual to catch OOME but in this case appropriate
659 return false;
660 }
661 return true;
662 }
663 /**
664 * Rehashes the map.
665 *
666 * <P>
667 * This method implements the basic rehashing strategy, and may be overriden
668 * by subclasses implementing different rehashing strategies (e.g.,
669 * disk-based rehashing). However, you should not override this method
670 * unless you understand the internal workings of this class.
671 *
672 * @param newN
673 * the new size
674 */
675 @SuppressWarnings("unchecked")
676 protected void rehash(final int newN) {
677 final K myKeys[] = this.keys;
678 final V myValues[] = this.values;
679 final int mask = newN - 1; // Note that this is used by the hashing
680 // macro
681 final K newKey[] = (K[]) new Object[newN + 1];
682 final V newValue[] = (V[]) new Object[newN + 1];
683 int i = arraySize, pos;
684 for (int j = realSize(); j-- != 0;) {
685 while (myKeys[--i] == null) {
686 // advance i until we find an existing key
687 }
688 if (newKey[pos = HashCommon.mix(myKeys[i].hashCode()) & mask] != null) { // rehash & check slot availability
689 while (newKey[pos = (pos + 1) & mask] != null) {
690 // find available slot at (or immediately following) pos
691 }
692 }
693 newKey[pos] = myKeys[i];
694 newValue[pos] = myValues[i];
695 }
696 newValue[newN] = myValues[arraySize];
697 arraySize = newN;
698 this.mask = mask;
699 maxFill = HashCommon.maxFill(arraySize, loadFactor);
700 this.keys = newKey;
701 this.values = newValue;
702 }
703
704 /**
705 * Returns a hash code for this map.
706 *
707 * @return a hash code for this map.
708 */
709 @Override
710 public int hashCode() {
711 int result = 0;
712 for (int j = realSize(), i = 0, t = 0; j-- != 0;) {
713 while (keys[i] == null) {
714 i++;
715 }
716 if (this != keys[i]) {
717 t = keys[i].hashCode();
718 }
719 if (this != values[i]) {
720 t ^= (values[i] == null ? 0 : values[i].hashCode());
721 }
722 result += t;
723 i++;
724 }
725 // Zero / null keys have hash zero.
726 if (containsNullKey) {
727 result += (values[arraySize] == null ? 0 : values[arraySize].hashCode());
728 }
729 return result;
730 }
731
732 @SuppressWarnings("unchecked")
733 private void readObject(final ObjectInputStream s) throws IOException, ClassNotFoundException {
734 s.defaultReadObject();
735 arraySize = HashCommon.arraySize(size, loadFactor);
736 maxFill = HashCommon.maxFill(arraySize, loadFactor);
737 mask = arraySize - 1;
738 final K key[] = this.keys = (K[]) new Object[arraySize + 1];
739 final V value[] = this.values = (V[]) new Object[arraySize + 1];
740 K k;
741 V v;
742 for (int i = size, pos; i-- != 0;) {
743 k = (K) s.readObject();
744 v = (V) s.readObject();
745 if (k == null) {
746 pos = arraySize;
747 containsNullKey = true;
748 } else {
749 pos = HashCommon.mix(k.hashCode()) & mask;
750 while (key[pos] != null) {
751 pos = (pos + 1) & mask;
752 }
753 }
754 key[pos] = k;
755 value[pos] = v;
756 }
757 }
758
759 private void writeObject(final ObjectOutputStream s) throws IOException {
760 s.defaultWriteObject();
761 try {
762 forEach(SERIALIZER, s);
763 } catch (final RuntimeException runex) {
764 if (runex.getCause() instanceof IOException) {
765 throw (IOException) runex.getCause();
766 }
767 throw runex;
768 }
769 }
770
771 private static final TriConsumer<String, Object, ObjectOutputStream> SERIALIZER =
772 new TriConsumer<String, Object, ObjectOutputStream>() {
773 @Override
774 public void accept(final String k, final Object v, final ObjectOutputStream objectOutputStream) {
775 try {
776 objectOutputStream.writeObject(k);
777 objectOutputStream.writeObject(v);
778 } catch (final IOException ioex) {
779 throw new IllegalStateException(ioex);
780 }
781 }
782 };
783
784 @Override
785 public String toString() {
786 final StringBuilder sb = new StringBuilder(256);
787 sb.append('{');
788 final K myKeys[] = this.keys;
789 int pos = arraySize;
790 boolean first = true;
791 if (containsNullKey) {
792 sb.append(myKeys[pos] == this ? "(this map)" : myKeys[pos]);
793 sb.append('=');
794 sb.append(values[pos] == this ? "(this map)" : values[pos]);
795 first = false;
796 }
797 --pos;
798 for (; pos >= 0; pos--) {
799 if (myKeys[pos] != null) {
800 if (first) {
801 first = false;
802 } else {
803 sb.append(", ");
804 }
805 sb.append(myKeys[pos] == this ? "(this map)" : myKeys[pos]);
806 sb.append('=');
807 sb.append(values[pos] == this ? "(this map)" : values[pos]);
808 }
809 }
810 sb.append('}');
811 return sb.toString();
812 }
813
814 private static class HashCommon {
815 private HashCommon() {}
816
817 /** 2<sup>32</sup> &middot; &phi;, &phi; = (&#x221A;5 &minus; 1)/2. */
818 private static final int INT_PHI = 0x9E3779B9;
819
820 /** The reciprocal of {@link #INT_PHI} modulo 2<sup>32</sup>. */
821 private static final int INV_INT_PHI = 0x144cbc89;
822
823 /** Avalanches the bits of an integer by applying the finalisation step of MurmurHash3.
824 *
825 * <p>This method implements the finalisation step of Austin Appleby's
826 * <a href="http://code.google.com/p/smhasher/">MurmurHash3</a>.
827 * Its purpose is to avalanche the bits of the argument to within 0.25% bias.
828 *
829 * @param x an integer.
830 * @return a hash value with good avalanching properties.
831 */
832 public static int murmurHash3(int x) {
833 x ^= x >>> 16;
834 x *= 0x85ebca6b;
835 x ^= x >>> 13;
836 x *= 0xc2b2ae35;
837 x ^= x >>> 16;
838 return x;
839 }
840
841 /**
842 * Quickly mixes the bits of an integer.
843 *
844 * <p>This method mixes the bits of the argument by multiplying by the golden ratio and
845 * xorshifting the result. It is borrowed from <a href="https://github.com/OpenHFT/Koloboke">Koloboke</a>, and
846 * it has slightly worse behaviour than {@link #murmurHash3(int)} (in open-addressing hash tables the average
847 * number of probes is slightly larger), but it's much faster.
848 *
849 * @param x an integer.
850 * @return a hash value obtained by mixing the bits of {@code x}.
851 * @see #invMix(int)
852 */
853 public static int mix(final int x) {
854 final int h = x * INT_PHI;
855 return h ^ (h >>> 16);
856 }
857
858 /** The inverse of {@link #mix(int)}. This method is mainly useful to create unit tests.
859 *
860 * @param x an integer.
861 * @return a value that passed through {@link #mix(int)} would give {@code x}.
862 */
863 public static int invMix(final int x) {
864 return (x ^ x >>> 16) * INV_INT_PHI;
865 }
866
867 /** Return the least power of two greater than or equal to the specified value.
868 *
869 * <p>Note that this function will return 1 when the argument is 0.
870 *
871 * @param x an integer smaller than or equal to 2<sup>30</sup>.
872 * @return the least power of two greater than or equal to the specified value.
873 */
874 public static int nextPowerOfTwo(int x) {
875 if (x == 0) {
876 return 1;
877 }
878 x--;
879 x |= x >> 1;
880 x |= x >> 2;
881 x |= x >> 4;
882 x |= x >> 8;
883 return (x | x >> 16) + 1;
884 }
885
886 /** Return the least power of two greater than or equal to the specified value.
887 *
888 * <p>Note that this function will return 1 when the argument is 0.
889 *
890 * @param x a long integer smaller than or equal to 2<sup>62</sup>.
891 * @return the least power of two greater than or equal to the specified value.
892 */
893 public static long nextPowerOfTwo(long x) {
894 if (x == 0) {
895 return 1;
896 }
897 x--;
898 x |= x >> 1;
899 x |= x >> 2;
900 x |= x >> 4;
901 x |= x >> 8;
902 x |= x >> 16;
903 return (x | x >> 32) + 1;
904 }
905
906
907 /** Returns the maximum number of entries that can be filled before rehashing.
908 *
909 * @param n the size of the backing array.
910 * @param f the load factor.
911 * @return the maximum number of entries before rehashing.
912 */
913 public static int maxFill(final int n, final float f) {
914 /* We must guarantee that there is always at least
915 * one free entry (even with pathological load factors). */
916 return Math.min((int) Math.ceil(n * f), n - 1);
917 }
918
919 /**
920 * Returns the least power of two smaller than or equal to 2<sup>30</sup> and larger than or equal to
921 * <code>Math.ceil( expected / f )</code>.
922 *
923 * @param expected the expected number of elements in a hash table.
924 * @param f the load factor.
925 * @return the minimum possible size for a backing array.
926 * @throws IllegalArgumentException if the necessary size is larger than 2<sup>30</sup>.
927 */
928 public static int arraySize(final int expected, final float f) {
929 final long result = Math.max(2, nextPowerOfTwo((long) Math.ceil(expected / f)));
930 if (result > (1 << 30)) {
931 throw new IllegalArgumentException("Too large (" + expected +
932 " expected elements with load factor " + f + ")");
933 }
934 return (int) result;
935 }
936 }
937 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.spi;
17
18 import org.apache.logging.log4j.perf.nogc.OpenHashStringMap;
19 import org.apache.logging.log4j.util.ReadOnlyStringMap;
20 import org.apache.logging.log4j.util.StringMap;
21 import org.apache.logging.log4j.util.PropertiesUtil;
22
23 /**
24 * {@code OpenHashStringMap}-based implementation of the {@code ThreadContextMap} interface that creates a copy of
25 * the data structure on every modification. Any particular instance of the data structure is a snapshot of the
26 * ThreadContext at some point in time and can safely be passed off to other threads
27 *
28 * @since 2.7
29 */
30 public class CopyOnWriteOpenHashMapThreadContextMap extends CopyOnWriteSortedArrayThreadContextMap {
31
32 /** Constant used in benchmark code */
33 public static final Class<? extends ThreadContextMap> SUPER = CopyOnWriteSortedArrayThreadContextMap.class;
34
35 @Override
36 protected StringMap createStringMap() {
37 return new OpenHashStringMap<>(PropertiesUtil.getProperties().getIntegerProperty(
38 PROPERTY_NAME_INITIAL_CAPACITY, DEFAULT_INITIAL_CAPACITY));
39 }
40
41 @Override
42 protected StringMap createStringMap(final ReadOnlyStringMap original) {
43 return new OpenHashStringMap<>(original);
44 }
45 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.spi;
17
18 import org.apache.logging.log4j.perf.nogc.OpenHashStringMap;
19 import org.apache.logging.log4j.util.ReadOnlyStringMap;
20 import org.apache.logging.log4j.util.StringMap;
21 import org.apache.logging.log4j.util.PropertiesUtil;
22
23 /**
24 * {@code OpenHashStringMap}-based implementation of the {@code ThreadContextMap} interface that attempts not to
25 * create temporary objects. Adding and removing key-value pairs will not create temporary objects.
26 * <p>
27 * Since the underlying data structure is modified directly it is not suitable for passing by reference to other
28 * threads. Instead, client code needs to copy the contents when interacting with another thread.
29 * </p>
30 *
31 * @since 2.7
32 */
33 public class GarbageFreeOpenHashMapThreadContextMap extends GarbageFreeSortedArrayThreadContextMap {
34
35 /** Constant used in benchmark code */
36 public static final Class<? extends ThreadContextMap> SUPER = GarbageFreeSortedArrayThreadContextMap.class;
37
38 @Override
39 protected StringMap createStringMap() {
40 return new OpenHashStringMap<>(PropertiesUtil.getProperties().getIntegerProperty(
41 PROPERTY_NAME_INITIAL_CAPACITY, DEFAULT_INITIAL_CAPACITY));
42 }
43
44 @Override
45 protected StringMap createStringMap(final ReadOnlyStringMap original) {
46 return new OpenHashStringMap<>(original);
47 }
48 }
0 <?xml version="1.0" encoding="UTF-8"?>
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 <Configuration status="OFF">
18 <Appenders>
19 <CountingNoOp name="NoOp">
20 </CountingNoOp>
21 <Async name="Async" blocking="true" bufferSize="262144">
22 <appender-ref ref="NoOp"/>
23 <DisruptorBlockingQueue spinPolicy="SPINNING"/>
24 </Async>
25 </Appenders>
26 <Loggers>
27 <Root level="info" includeLocation="false">
28 <appender-ref ref="Async"/>
29 </Root>
30 </Loggers>
31 </Configuration>
0 <?xml version="1.0" encoding="UTF-8"?>
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 <Configuration status="OFF">
18 <Appenders>
19 <CountingNoOp name="NoOp">
20 </CountingNoOp>
21 <Async name="Async" blocking="true" bufferSize="262144" includeLocation="true">
22 <appender-ref ref="NoOp"/>
23 <DisruptorBlockingQueue spinPolicy="SPINNING"/>
24 </Async>
25 </Appenders>
26 <Loggers>
27 <Root level="info">
28 <appender-ref ref="Async"/>
29 </Root>
30 </Loggers>
31 </Configuration>
0 <?xml version="1.0" encoding="UTF-8"?>
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 <Configuration status="OFF">
18 <Appenders>
19 <CountingNoOp name="NoOp">
20 </CountingNoOp>
21 <Async name="Async" blocking="true" bufferSize="262144">
22 <appender-ref ref="NoOp"/>
23 <JCToolsBlockingQueue waitStrategy="SPIN"/>
24 </Async>
25 </Appenders>
26 <Loggers>
27 <Root level="info" includeLocation="false">
28 <appender-ref ref="Async"/>
29 </Root>
30 </Loggers>
31 </Configuration>
0 <?xml version="1.0" encoding="UTF-8"?>
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 <Configuration status="OFF">
18 <Appenders>
19 <CountingNoOp name="NoOp">
20 </CountingNoOp>
21 <Async name="Async" blocking="true" bufferSize="262144" includeLocation="true">
22 <appender-ref ref="NoOp"/>
23 <JCToolsBlockingQueue waitStrategy="SPIN"/>
24 </Async>
25 </Appenders>
26 <Loggers>
27 <Root level="info">
28 <appender-ref ref="Async"/>
29 </Root>
30 </Loggers>
31 </Configuration>
2020 </CountingNoOp>
2121 <Async name="Async" blocking="true" bufferSize="262144">
2222 <appender-ref ref="NoOp"/>
23 <ArrayBlockingQueue/>
2324 </Async>
2425 </Appenders>
2526 <Loggers>
0 <?xml version="1.0" encoding="UTF-8"?>
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 <Configuration status="OFF">
18 <Appenders>
19 <CountingNoOp name="NoOp">
20 </CountingNoOp>
21 <Async name="Async" blocking="true" bufferSize="262144">
22 <appender-ref ref="NoOp"/>
23 <LinkedTransferQueue/>
24 </Async>
25 </Appenders>
26 <Loggers>
27 <Root level="info" includeLocation="false">
28 <appender-ref ref="Async"/>
29 </Root>
30 </Loggers>
31 </Configuration>
0 <?xml version="1.0" encoding="UTF-8"?>
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 <Configuration status="OFF">
18 <Appenders>
19 <CountingNoOp name="NoOp">
20 </CountingNoOp>
21 <Async name="Async" blocking="true" bufferSize="262144" includeLocation="true">
22 <appender-ref ref="NoOp"/>
23 <LinkedTransferQueue/>
24 </Async>
25 </Appenders>
26 <Loggers>
27 <Root level="info">
28 <appender-ref ref="Async"/>
29 </Root>
30 </Loggers>
31 </Configuration>
+0
-5
log4j-samples/.gitignore less more
0 /target/
1 /.project
2 /configuration/target/
3 /loggerProperties/target/
4 /.settings/
1919 <parent>
2020 <artifactId>log4j-samples</artifactId>
2121 <groupId>org.apache.logging.log4j.samples</groupId>
22 <version>2.6.2</version>
22 <version>2.7</version>
2323 </parent>
2424 <artifactId>log4j-samples-configuration</artifactId>
2525 <packaging>jar</packaging>
1515 */
1616 package org.apache.logging.log4j.configuration;
1717
18 import java.io.Serializable;
19
1820 import org.apache.logging.log4j.Level;
1921 import org.apache.logging.log4j.core.Appender;
2022 import org.apache.logging.log4j.core.Layout;
23 import org.apache.logging.log4j.core.LoggerContext;
2124 import org.apache.logging.log4j.core.appender.ConsoleAppender;
2225 import org.apache.logging.log4j.core.config.AbstractConfiguration;
2326 import org.apache.logging.log4j.core.config.ConfigurationSource;
2427 import org.apache.logging.log4j.core.config.LoggerConfig;
2528 import org.apache.logging.log4j.core.layout.PatternLayout;
2629 import org.apache.logging.log4j.util.PropertiesUtil;
27
28 import java.io.Serializable;
2930
3031 /**
3132 * This Configuration is the same as the DefaultConfiguration but shows how a custom configuration can be built
4950 */
5051 public static final String DEFAULT_PATTERN = "%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n";
5152
52 public CustomConfiguration() {
53 this(ConfigurationSource.NULL_SOURCE);
53 public CustomConfiguration(final LoggerContext loggerContext) {
54 this(loggerContext, ConfigurationSource.NULL_SOURCE);
5455 }
5556
5657 /**
5758 * Constructor to create the default configuration.
5859 */
59 public CustomConfiguration(final ConfigurationSource source) {
60 super(source);
60 public CustomConfiguration(final LoggerContext loggerContext, final ConfigurationSource source) {
61 super(loggerContext, source);
6162
6263 setName(CONFIG_NAME);
6364 final Layout<? extends Serializable> layout = PatternLayout.newBuilder()
1515 */
1616 package org.apache.logging.log4j.configuration;
1717
18 import java.net.URI;
19
20 import org.apache.logging.log4j.core.LoggerContext;
1821 import org.apache.logging.log4j.core.config.Configuration;
1922 import org.apache.logging.log4j.core.config.ConfigurationFactory;
2023 import org.apache.logging.log4j.core.config.ConfigurationSource;
2124 import org.apache.logging.log4j.core.config.Order;
2225 import org.apache.logging.log4j.core.config.plugins.Plugin;
23 import java.net.URI;
2426
2527 /**
2628 * Factory to construct a CustomConfiguration.
4042 * @return The Configuration.
4143 */
4244 @Override
43 public Configuration getConfiguration(final ConfigurationSource source) {
44 return new CustomConfiguration(source);
45 public Configuration getConfiguration(final LoggerContext loggerContext, final ConfigurationSource source) {
46 return new CustomConfiguration(loggerContext, source);
4547 }
4648
4749 @Override
48 public Configuration getConfiguration(final String name, final URI configLocation) {
49 return new CustomConfiguration();
50 public Configuration getConfiguration(final LoggerContext loggerContext, final String name, final URI configLocation) {
51 return new CustomConfiguration(loggerContext);
5052 }
5153
5254 /**
1919 <parent>
2020 <artifactId>log4j-samples</artifactId>
2121 <groupId>org.apache.logging.log4j.samples</groupId>
22 <version>2.6.2</version>
22 <version>2.7</version>
2323 </parent>
2424 <artifactId>log4j-samples-flume-common</artifactId>
2525 <packaging>jar</packaging>
1919 <parent>
2020 <artifactId>log4j-samples</artifactId>
2121 <groupId>org.apache.logging.log4j.samples</groupId>
22 <version>2.6.2</version>
22 <version>2.7</version>
2323 </parent>
2424 <artifactId>log4j-samples-flume-embedded</artifactId>
2525 <packaging>war</packaging>
1919 <parent>
2020 <artifactId>log4j-samples</artifactId>
2121 <groupId>org.apache.logging.log4j.samples</groupId>
22 <version>2.6.2</version>
22 <version>2.7</version>
2323 </parent>
2424 <artifactId>log4j-samples-flume-remote</artifactId>
2525 <packaging>war</packaging>
1919 <parent>
2020 <artifactId>log4j-samples</artifactId>
2121 <groupId>org.apache.logging.log4j.samples</groupId>
22 <version>2.6.2</version>
22 <version>2.7</version>
2323 </parent>
2424 <artifactId>log4j-samples-loggerProperties</artifactId>
2525 <packaging>jar</packaging>
1919 <parent>
2020 <groupId>org.apache.logging.log4j</groupId>
2121 <artifactId>log4j</artifactId>
22 <version>2.6.2</version>
22 <version>2.7</version>
2323 <relativePath>../</relativePath>
2424 </parent>
2525 <groupId>org.apache.logging.log4j.samples</groupId>
8282 <module>flume-embedded</module>
8383 <module>configuration</module>
8484 <module>loggerProperties</module>
85 <module>scala-api</module>
8586 </modules>
8687 <build>
8788 <plugins>
0 /.settings/
1 /.classpath
2 /.project
0 <?xml version="1.0"?>
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 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
18 <modelVersion>4.0.0</modelVersion>
19 <parent>
20 <artifactId>log4j-samples</artifactId>
21 <groupId>org.apache.logging.log4j.samples</groupId>
22 <version>2.7</version>
23 </parent>
24 <artifactId>log4j-samples-scala-api</artifactId>
25 <packaging>jar</packaging>
26 <name>Apache Log4j Samples: Scala API</name>
27 <url>http://http://logging.apache.org/log4j/2.x/</url>
28 <properties>
29 <scala.version>2.11.7</scala.version>
30 <scala.maven.plugin.version>3.2.2</scala.maven.plugin.version>
31 </properties>
32 <dependencies>
33 <dependency>
34 <groupId>org.apache.logging.log4j</groupId>
35 <artifactId>log4j-api-scala_2.11</artifactId>
36 </dependency>
37 <dependency>
38 <groupId>org.apache.logging.log4j</groupId>
39 <artifactId>log4j-core</artifactId>
40 <scope>runtime</scope>
41 </dependency>
42 </dependencies>
43 <build>
44 <sourceDirectory>src/main/scala</sourceDirectory>
45 <plugins>
46 <plugin>
47 <groupId>net.alchim31.maven</groupId>
48 <artifactId>scala-maven-plugin</artifactId>
49 <version>${scala.maven.plugin.version}</version>
50 <executions>
51 <execution>
52 <goals>
53 <goal>compile</goal>
54 </goals>
55 </execution>
56 </executions>
57 </plugin>
58 <plugin>
59 <groupId>org.apache.felix</groupId>
60 <artifactId>maven-bundle-plugin</artifactId>
61 </plugin>
62 </plugins>
63 </build>
64 </project>
0 <?xml version="1.0" encoding="UTF-8"?>
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 <Configuration name="ScalaApiSample" status="error">
19 <Appenders>
20 <Console name="Console">
21 <PatternLayout>
22 <Pattern>%d %5p %c{1} %X %F:%L - %m%n</Pattern>
23 </PatternLayout>
24 </Console>
25 </Appenders>
26 <Loggers>
27 <Root level="TRACE">
28 <AppenderRef ref="Console"/>
29 </Root>
30 </Loggers>
31 </Configuration>
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.scalasample
17
18 import org.apache.logging.log4j.Level
19 import org.apache.logging.log4j.message.MessageFactory2
20 import org.apache.logging.log4j.scala.Logging
21
22 object LoggingApp extends App with Logging {
23
24 val s1 = "foo"
25 val s2 = "bar"
26 val t = new RuntimeException("error")
27
28 logger.info(s"Hello, world: $s1 $s2")
29
30 logger.traceEntry()
31 logger.traceEntry(s1, s2)
32 val entryMessage = logger.traceEntry(logger.delegate.getMessageFactory.asInstanceOf[MessageFactory2].newMessage("foobar": CharSequence))
33
34 logger.traceExit()
35 logger.traceExit(s2)
36 logger.traceExit(entryMessage)
37 logger.traceExit(entryMessage, s2)
38 logger.traceExit(logger.delegate.getMessageFactory.asInstanceOf[MessageFactory2].newMessage("bonsai": CharSequence), s2)
39
40 logger.throwing(t)
41 logger.throwing(Level.INFO, t)
42
43 logger.catching(t)
44 logger.catching(Level.INFO, t)
45
46 }
+0
-4
log4j-slf4j-impl/.gitignore less more
0 /.settings/
1 /target/
2 /.classpath
3 /.project
1919 <parent>
2020 <groupId>org.apache.logging.log4j</groupId>
2121 <artifactId>log4j</artifactId>
22 <version>2.6.2</version>
22 <version>2.7</version>
2323 <relativePath>../</relativePath>
2424 </parent>
2525 <artifactId>log4j-slf4j-impl</artifactId>
5454 <dependency>
5555 <groupId>org.apache.commons</groupId>
5656 <artifactId>commons-lang3</artifactId>
57 <scope>test</scope>
58 </dependency>
59 <dependency>
60 <groupId>org.apache.commons</groupId>
61 <artifactId>commons-csv</artifactId>
5762 <scope>test</scope>
5863 </dependency>
5964 <dependency>
1414 * limitations under the license.
1515 */
1616 package org.apache.logging.slf4j;
17
1817
1918 import org.junit.Test;
2019 import org.slf4j.Logger;
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16
17 package org.apache.logging.slf4j;
18
19 import org.apache.logging.log4j.core.layout.Log4j2_1482_Test;
20 import org.slf4j.Logger;
21 import org.slf4j.LoggerFactory;
22
23 /**
24 * Tests https://issues.apache.org/jira/browse/LOG4J2-1482
25 */
26 public class Log4j2_1482_Slf4jTest extends Log4j2_1482_Test {
27
28 @Override
29 protected void log(final int runNumber) {
30 if (runNumber == 2) {
31 // System.out.println("Set a breakpoint here.");
32 }
33 final Logger logger = LoggerFactory.getLogger("auditcsvfile");
34 final int val1 = 9, val2 = 11, val3 = 12;
35 logger.info("Info Message!", val1, val2, val3);
36 logger.info("Info Message!", val1, val2, val3);
37 logger.info("Info Message!", val1, val2, val3);
38 }
39
40 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.slf4j;
17
18 import static org.junit.Assert.assertEquals;
19 import static org.junit.Assert.assertNotNull;
20 import static org.junit.Assert.assertTrue;
21
22 import java.util.List;
23 import java.util.Locale;
24
25 import org.apache.logging.log4j.core.util.Constants;
26 import org.apache.logging.log4j.junit.LoggerContextRule;
27 import org.apache.logging.log4j.test.appender.ListAppender;
28 import org.junit.After;
29 import org.junit.Before;
30 import org.junit.ClassRule;
31 import org.junit.Test;
32 import org.slf4j.Logger;
33 import org.slf4j.LoggerFactory;
34 import org.slf4j.MDC;
35 import org.slf4j.Marker;
36 import org.slf4j.ext.EventData;
37 import org.slf4j.ext.EventLogger;
38 import org.slf4j.ext.XLogger;
39 import org.slf4j.ext.XLoggerFactory;
40 import org.slf4j.spi.LocationAwareLogger;
41
42 /**
43 *
44 */
45 public class LoggerTest {
46
47 private static final String CONFIG = "log4j-test1.xml";
48
49 @ClassRule
50 public static LoggerContextRule ctx = new LoggerContextRule(CONFIG);
51
52 Logger logger = LoggerFactory.getLogger("LoggerTest");
53 XLogger xlogger = XLoggerFactory.getXLogger("LoggerTest");
54
55 @Test
56 public void basicFlow() {
57 xlogger.entry();
58 verify("List", "o.a.l.s.LoggerTest entry MDC{}" + Constants.LINE_SEPARATOR);
59 xlogger.exit();
60 verify("List", "o.a.l.s.LoggerTest exit MDC{}" + Constants.LINE_SEPARATOR);
61 }
62
63 @Test
64 public void simpleFlow() {
65 xlogger.entry(CONFIG);
66 verify("List", "o.a.l.s.LoggerTest entry with (log4j-test1.xml) MDC{}" + Constants.LINE_SEPARATOR);
67 xlogger.exit(0);
68 verify("List", "o.a.l.s.LoggerTest exit with (0) MDC{}" + Constants.LINE_SEPARATOR);
69 }
70
71 @Test
72 public void throwing() {
73 xlogger.throwing(new IllegalArgumentException("Test Exception"));
74 verify("List", "o.a.l.s.LoggerTest throwing MDC{}" + Constants.LINE_SEPARATOR);
75 }
76
77 @Test
78 public void catching() {
79 try {
80 throw new NullPointerException();
81 } catch (final Exception e) {
82 xlogger.catching(e);
83 verify("List", "o.a.l.s.LoggerTest catching MDC{}" + Constants.LINE_SEPARATOR);
84 }
85 }
86
87 @Test
88 public void debug() {
89 logger.debug("Debug message");
90 verify("List", "o.a.l.s.LoggerTest Debug message MDC{}" + Constants.LINE_SEPARATOR);
91 }
92
93 @Test
94 public void debugNoParms() {
95 logger.debug("Debug message {}");
96 verify("List", "o.a.l.s.LoggerTest Debug message {} MDC{}" + Constants.LINE_SEPARATOR);
97 logger.debug("Debug message {}", (Object[]) null);
98 verify("List", "o.a.l.s.LoggerTest Debug message {} MDC{}" + Constants.LINE_SEPARATOR);
99 ((LocationAwareLogger)logger).log(null, Log4jLogger.class.getName(), LocationAwareLogger.DEBUG_INT,
100 "Debug message {}", null, null);
101 verify("List", "o.a.l.s.LoggerTest Debug message {} MDC{}" + Constants.LINE_SEPARATOR);
102 }
103
104
105 @Test
106 public void debugWithParms() {
107 logger.debug("Hello, {}", "World");
108 verify("List", "o.a.l.s.LoggerTest Hello, World MDC{}" + Constants.LINE_SEPARATOR);
109 }
110
111 @Test
112 public void mdc() {
113
114 MDC.put("TestYear", "2010");
115 logger.debug("Debug message");
116 verify("List", "o.a.l.s.LoggerTest Debug message MDC{TestYear=2010}" + Constants.LINE_SEPARATOR);
117 MDC.clear();
118 logger.debug("Debug message");
119 verify("List", "o.a.l.s.LoggerTest Debug message MDC{}" + Constants.LINE_SEPARATOR);
120 }
121
122 /**
123 * @see <a href="https://issues.apache.org/jira/browse/LOG4J2-793">LOG4J2-793</a>
124 */
125 @Test
126 public void supportsCustomSLF4JMarkers() {
127 final Marker marker = new CustomFlatMarker("TEST");
128 logger.debug(marker, "Test");
129 verify("List", "o.a.l.s.LoggerTest Test MDC{}" + Constants.LINE_SEPARATOR);
130 }
131
132 @Test
133 public void testRootLogger() {
134 final Logger l = LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME);
135 assertNotNull("No Root Logger", l);
136 assertEquals(Logger.ROOT_LOGGER_NAME, l.getName());
137 }
138
139 @Test
140 public void doubleSubst() {
141 logger.debug("Hello, {}", "Log4j {}");
142 verify("List", "o.a.l.s.LoggerTest Hello, Log4j {} MDC{}" + Constants.LINE_SEPARATOR);
143 xlogger.debug("Hello, {}", "Log4j {}");
144 verify("List", "o.a.l.s.LoggerTest Hello, Log4j Log4j {} MDC{}" + Constants.LINE_SEPARATOR);
145 }
146
147 @Test
148 public void testEventLogger() {
149 MDC.put("loginId", "JohnDoe");
150 MDC.put("ipAddress", "192.168.0.120");
151 MDC.put("locale", Locale.US.getDisplayName());
152 final EventData data = new EventData();
153 data.setEventType("Transfer");
154 data.setEventId("Audit@18060");
155 data.setMessage("Transfer Complete");
156 data.put("ToAccount", "123456");
157 data.put("FromAccount", "123457");
158 data.put("Amount", "200.00");
159 EventLogger.logEvent(data);
160 MDC.clear();
161 verify("EventLogger", "o.a.l.s.LoggerTest Transfer [Audit@18060 Amount=\"200.00\" FromAccount=\"123457\" ToAccount=\"123456\"] Transfer Complete" + Constants.LINE_SEPARATOR);
162 }
163
164 private void verify(final String name, final String expected) {
165 final ListAppender listApp = ctx.getListAppender(name);
166 assertNotNull("Missing Appender", listApp);
167 final List<String> events = listApp.getMessages();
168 assertTrue("Incorrect number of messages. Expected 1 Actual " + events.size(), events.size()== 1);
169 final String actual = events.get(0);
170 assertEquals("Incorrect message. Expected " + expected + ". Actual " + actual, expected, actual);
171 listApp.clear();
172 }
173
174 @Before
175 @After
176 public void cleanup() {
177 MDC.clear();
178 ctx.getListAppender("List").clear();
179 ctx.getListAppender("EventLogger").clear();
180 }
181 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.slf4j;
17
18 import static org.junit.Assert.assertEquals;
19 import static org.junit.Assert.assertNotNull;
20 import static org.junit.Assert.assertTrue;
21
22 import java.util.List;
23 import java.util.Locale;
24
25 import org.apache.logging.log4j.junit.LoggerContextRule;
26 import org.apache.logging.log4j.test.appender.ListAppender;
27 import org.apache.logging.log4j.util.Strings;
28 import org.junit.After;
29 import org.junit.Before;
30 import org.junit.ClassRule;
31 import org.junit.Test;
32 import org.slf4j.Logger;
33 import org.slf4j.LoggerFactory;
34 import org.slf4j.MDC;
35 import org.slf4j.Marker;
36 import org.slf4j.ext.EventData;
37 import org.slf4j.ext.EventLogger;
38 import org.slf4j.ext.XLogger;
39 import org.slf4j.ext.XLoggerFactory;
40 import org.slf4j.spi.LocationAwareLogger;
41
42 /**
43 *
44 */
45 public class LoggerTest {
46
47 private static final String CONFIG = "log4j-test1.xml";
48
49 @ClassRule
50 public static LoggerContextRule ctx = new LoggerContextRule(CONFIG);
51
52 Logger logger = LoggerFactory.getLogger("LoggerTest");
53 XLogger xlogger = XLoggerFactory.getXLogger("LoggerTest");
54
55 @Test
56 public void basicFlow() {
57 xlogger.entry();
58 verify("List", "o.a.l.s.LoggerTest entry MDC{}" + Strings.LINE_SEPARATOR);
59 xlogger.exit();
60 verify("List", "o.a.l.s.LoggerTest exit MDC{}" + Strings.LINE_SEPARATOR);
61 }
62
63 @Test
64 public void simpleFlow() {
65 xlogger.entry(CONFIG);
66 verify("List", "o.a.l.s.LoggerTest entry with (log4j-test1.xml) MDC{}" + Strings.LINE_SEPARATOR);
67 xlogger.exit(0);
68 verify("List", "o.a.l.s.LoggerTest exit with (0) MDC{}" + Strings.LINE_SEPARATOR);
69 }
70
71 @Test
72 public void throwing() {
73 xlogger.throwing(new IllegalArgumentException("Test Exception"));
74 verify("List", "o.a.l.s.LoggerTest throwing MDC{}" + Strings.LINE_SEPARATOR);
75 }
76
77 @Test
78 public void catching() {
79 try {
80 throw new NullPointerException();
81 } catch (final Exception e) {
82 xlogger.catching(e);
83 verify("List", "o.a.l.s.LoggerTest catching MDC{}" + Strings.LINE_SEPARATOR);
84 }
85 }
86
87 @Test
88 public void debug() {
89 logger.debug("Debug message");
90 verify("List", "o.a.l.s.LoggerTest Debug message MDC{}" + Strings.LINE_SEPARATOR);
91 }
92
93 @Test
94 public void debugNoParms() {
95 logger.debug("Debug message {}");
96 verify("List", "o.a.l.s.LoggerTest Debug message {} MDC{}" + Strings.LINE_SEPARATOR);
97 logger.debug("Debug message {}", (Object[]) null);
98 verify("List", "o.a.l.s.LoggerTest Debug message {} MDC{}" + Strings.LINE_SEPARATOR);
99 ((LocationAwareLogger)logger).log(null, Log4jLogger.class.getName(), LocationAwareLogger.DEBUG_INT,
100 "Debug message {}", null, null);
101 verify("List", "o.a.l.s.LoggerTest Debug message {} MDC{}" + Strings.LINE_SEPARATOR);
102 }
103
104
105 @Test
106 public void debugWithParms() {
107 logger.debug("Hello, {}", "World");
108 verify("List", "o.a.l.s.LoggerTest Hello, World MDC{}" + Strings.LINE_SEPARATOR);
109 }
110
111 @Test
112 public void mdc() {
113
114 MDC.put("TestYear", "2010");
115 logger.debug("Debug message");
116 verify("List", "o.a.l.s.LoggerTest Debug message MDC{TestYear=2010}" + Strings.LINE_SEPARATOR);
117 MDC.clear();
118 logger.debug("Debug message");
119 verify("List", "o.a.l.s.LoggerTest Debug message MDC{}" + Strings.LINE_SEPARATOR);
120 }
121
122 /**
123 * @see <a href="https://issues.apache.org/jira/browse/LOG4J2-793">LOG4J2-793</a>
124 */
125 @Test
126 public void supportsCustomSLF4JMarkers() {
127 final Marker marker = new CustomFlatMarker("TEST");
128 logger.debug(marker, "Test");
129 verify("List", "o.a.l.s.LoggerTest Test MDC{}" + Strings.LINE_SEPARATOR);
130 }
131
132 @Test
133 public void testRootLogger() {
134 final Logger l = LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME);
135 assertNotNull("No Root Logger", l);
136 assertEquals(Logger.ROOT_LOGGER_NAME, l.getName());
137 }
138
139 @Test
140 public void doubleSubst() {
141 logger.debug("Hello, {}", "Log4j {}");
142 verify("List", "o.a.l.s.LoggerTest Hello, Log4j {} MDC{}" + Strings.LINE_SEPARATOR);
143 xlogger.debug("Hello, {}", "Log4j {}");
144 verify("List", "o.a.l.s.LoggerTest Hello, Log4j Log4j {} MDC{}" + Strings.LINE_SEPARATOR);
145 }
146
147 @Test
148 public void testEventLogger() {
149 MDC.put("loginId", "JohnDoe");
150 MDC.put("ipAddress", "192.168.0.120");
151 MDC.put("locale", Locale.US.getDisplayName());
152 final EventData data = new EventData();
153 data.setEventType("Transfer");
154 data.setEventId("Audit@18060");
155 data.setMessage("Transfer Complete");
156 data.put("ToAccount", "123456");
157 data.put("FromAccount", "123457");
158 data.put("Amount", "200.00");
159 EventLogger.logEvent(data);
160 MDC.clear();
161 verify("EventLogger", "o.a.l.s.LoggerTest Transfer [Audit@18060 Amount=\"200.00\" FromAccount=\"123457\" ToAccount=\"123456\"] Transfer Complete" + Strings.LINE_SEPARATOR);
162 }
163
164 private void verify(final String name, final String expected) {
165 final ListAppender listApp = ctx.getListAppender(name);
166 assertNotNull("Missing Appender", listApp);
167 final List<String> events = listApp.getMessages();
168 assertTrue("Incorrect number of messages. Expected 1 Actual " + events.size(), events.size()== 1);
169 final String actual = events.get(0);
170 assertEquals("Incorrect message. Expected " + expected + ". Actual " + actual, expected, actual);
171 listApp.clear();
172 }
173
174 @Before
175 @After
176 public void cleanup() {
177 MDC.clear();
178 ctx.getListAppender("List").clear();
179 ctx.getListAppender("EventLogger").clear();
180 }
181 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.slf4j;
17
18 import java.util.List;
19
20 import org.apache.logging.log4j.core.util.Constants;
21 import org.apache.logging.log4j.junit.LoggerContextRule;
22 import org.apache.logging.log4j.test.appender.ListAppender;
23 import org.junit.Before;
24 import org.junit.ClassRule;
25 import org.junit.Test;
26 import org.slf4j.Logger;
27 import org.slf4j.LoggerFactory;
28 import org.slf4j.MDC;
29 import org.slf4j.Marker;
30 import org.slf4j.MarkerFactory;
31
32 import static org.junit.Assert.*;
33
34 /**
35 *
36 */
37 public class OptionalTest {
38
39 private static final String CONFIG = "log4j-test1.xml";
40
41 @ClassRule
42 public static final LoggerContextRule CTX = new LoggerContextRule(CONFIG);
43
44 Logger logger = LoggerFactory.getLogger("EventLogger");
45 Marker marker = MarkerFactory.getMarker("EVENT");
46
47 @Test
48 public void testEventLogger() {
49 logger.info(marker, "This is a test");
50 MDC.clear();
51 verify("EventLogger", "o.a.l.s.OptionalTest This is a test" + Constants.LINE_SEPARATOR);
52 }
53
54 private void verify(final String name, final String expected) {
55 final ListAppender listApp = CTX.getListAppender(name);
56 final List<String> events = listApp.getMessages();
57 assertTrue("Incorrect number of messages. Expected 1 Actual " + events.size(), events.size()== 1);
58 final String actual = events.get(0);
59 assertEquals("Incorrect message. Expected " + expected + ". Actual " + actual, expected, actual);
60 listApp.clear();
61 }
62
63 @Before
64 public void cleanup() {
65 CTX.getListAppender("List").clear();
66 CTX.getListAppender("EventLogger").clear();
67 }
68 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.slf4j;
17
18 import java.util.List;
19
20 import org.apache.logging.log4j.junit.LoggerContextRule;
21 import org.apache.logging.log4j.test.appender.ListAppender;
22 import org.apache.logging.log4j.util.Strings;
23 import org.junit.Before;
24 import org.junit.ClassRule;
25 import org.junit.Test;
26 import org.slf4j.Logger;
27 import org.slf4j.LoggerFactory;
28 import org.slf4j.MDC;
29 import org.slf4j.Marker;
30 import org.slf4j.MarkerFactory;
31
32 import static org.junit.Assert.*;
33
34 /**
35 *
36 */
37 public class OptionalTest {
38
39 private static final String CONFIG = "log4j-test1.xml";
40
41 @ClassRule
42 public static final LoggerContextRule CTX = new LoggerContextRule(CONFIG);
43
44 Logger logger = LoggerFactory.getLogger("EventLogger");
45 Marker marker = MarkerFactory.getMarker("EVENT");
46
47 @Test
48 public void testEventLogger() {
49 logger.info(marker, "This is a test");
50 MDC.clear();
51 verify("EventLogger", "o.a.l.s.OptionalTest This is a test" + Strings.LINE_SEPARATOR);
52 }
53
54 private void verify(final String name, final String expected) {
55 final ListAppender listApp = CTX.getListAppender(name);
56 final List<String> events = listApp.getMessages();
57 assertTrue("Incorrect number of messages. Expected 1 Actual " + events.size(), events.size()== 1);
58 final String actual = events.get(0);
59 assertEquals("Incorrect message. Expected " + expected + ". Actual " + actual, expected, actual);
60 listApp.clear();
61 }
62
63 @Before
64 public void cleanup() {
65 CTX.getListAppender("List").clear();
66 CTX.getListAppender("EventLogger").clear();
67 }
68 }
0 <?xml version="1.0" encoding="UTF-8"?>
1 <Configuration status="warn" name="MyApp" packages="">
2 <Properties>
3 <Property name="audit-path">target/log4j2-1482</Property>
4 <Property name="file-name">audit</Property>
5 <Property name="file-header">param1,param2,param3${sys:line.separator}
6 </Property>
7 </Properties>
8
9 <Appenders>
10 <RollingFile name="auditfile" fileName="${audit-path}/${file-name}.tmp"
11 filePattern="${audit-path}/${file-name}-%d{yyyy-MM-dd}-%i.csv">
12 <CsvParameterLayout delimiter="," header="${file-header}">
13 </CsvParameterLayout>
14 <Policies>
15 <SizeBasedTriggeringPolicy size="80 B" />
16 </Policies>
17 <DefaultRolloverStrategy max="2" />
18 </RollingFile>
19 </Appenders>
20
21 <Loggers>
22 <Root level="info">
23 <AppenderRef ref="auditfile" />
24 </Root>
25 </Loggers>
26 </Configuration>
+0
-4
log4j-taglib/.gitignore less more
0 /.settings/
1 /target/
2 /.classpath
3 /.project
1919 <parent>
2020 <groupId>org.apache.logging.log4j</groupId>
2121 <artifactId>log4j</artifactId>
22 <version>2.6.2</version>
22 <version>2.7</version>
2323 <relativePath>../</relativePath>
2424 </parent>
2525 <artifactId>log4j-taglib</artifactId>
+0
-4
log4j-to-slf4j/.gitignore less more
0 /.settings/
1 /target/
2 /.classpath
3 /.project
1919 <parent>
2020 <groupId>org.apache.logging.log4j</groupId>
2121 <artifactId>log4j</artifactId>
22 <version>2.6.2</version>
22 <version>2.7</version>
2323 <relativePath>../</relativePath>
2424 </parent>
2525 <artifactId>log4j-to-slf4j</artifactId>
1616 package org.apache.logging.slf4j;
1717
1818 import java.util.Map;
19 import java.util.Map.Entry;
1920
20 import org.apache.logging.log4j.spi.ThreadContextMap;
21 import org.apache.logging.log4j.util.StringMap;
22 import org.apache.logging.log4j.spi.ThreadContextMap2;
23 import org.apache.logging.log4j.util.SortedArrayStringMap;
2124 import org.slf4j.MDC;
2225
2326 /**
2427 * Bind the ThreadContextMap to the SLF4J MDC.
2528 */
26 public class MDCContextMap implements ThreadContextMap {
29 public class MDCContextMap implements ThreadContextMap2 {
30
31 private static final StringMap EMPTY_CONTEXT_DATA = new SortedArrayStringMap();
32 static {
33 EMPTY_CONTEXT_DATA.freeze();
34 }
35
2736 @Override
2837 public void put(final String key, final String value) {
2938 MDC.put(key, value);
39 }
40
41 @Override
42 public void putAll(final Map<String, String> m) {
43 for (final Entry<String, String> entry : m.entrySet()) {
44 MDC.put(entry.getKey(), entry.getValue());
45 }
3046 }
3147
3248 @Override
6581 public boolean isEmpty() {
6682 return MDC.getCopyOfContextMap().isEmpty();
6783 }
84
85 @Override
86 public StringMap getReadOnlyContextData() {
87 final Map<String, String> copy = getCopy();
88 if (copy.isEmpty()) {
89 return EMPTY_CONTEXT_DATA;
90 }
91 final StringMap result = new SortedArrayStringMap();
92 for (Entry<String, String> entry : copy.entrySet()) {
93 result.putValue(entry.getKey(), entry.getValue());
94 }
95 return result;
96 }
6897 }
+0
-4
log4j-web/.gitignore less more
0 /.settings/
1 /target/
2 /.classpath
3 /.project
1919 <parent>
2020 <artifactId>log4j</artifactId>
2121 <groupId>org.apache.logging.log4j</groupId>
22 <version>2.6.2</version>
22 <version>2.7</version>
2323 </parent>
2424 <modelVersion>4.0.0</modelVersion>
2525
8282 <configuration>
8383 <instructions>
8484 <!-- we compile against 3.0, but require 2.5 minimum -->
85 <Fragment-Host>org.apache.logging.log4j.core</Fragment-Host>
8586 <Import-Package>javax.servlet;version="[2.5,4)",*</Import-Package>
8687 <Export-Package>org.apache.logging.log4j.web</Export-Package>
8788 </instructions>
1515 */
1616 package org.apache.logging.log4j.web;
1717
18 import java.util.Locale;
19 import java.util.concurrent.TimeUnit;
20
1821 import javax.servlet.ServletContext;
1922 import javax.servlet.ServletContextEvent;
2023 import javax.servlet.ServletContextListener;
2124
2225 import org.apache.logging.log4j.Logger;
26 import org.apache.logging.log4j.core.LifeCycle2;
2327 import org.apache.logging.log4j.status.StatusLogger;
28 import org.apache.logging.log4j.util.Strings;
2429
2530 /**
2631 * In environments older than Servlet 3.0, this initializer is responsible for starting up Log4j logging before anything
2934 */
3035 public class Log4jServletContextListener implements ServletContextListener {
3136
32 private static final Logger LOGGER = StatusLogger.getLogger();
37 private static final int DEFAULT_STOP_TIMEOUT = 30;
38 private static final TimeUnit DEFAULT_STOP_TIMEOUT_TIMEUNIT = TimeUnit.SECONDS;
39
40 private static final String KEY_STOP_TIMEOUT = "log4j.stop.timeout";
41 private static final String KEY_STOP_TIMEOUT_TIMEUNIT = "log4j.stop.timeout.timeunit";
42
43 private static final Logger LOGGER = StatusLogger.getLogger();
3344
3445 private ServletContext servletContext;
3546 private Log4jWebLifeCycle initializer;
4960 }
5061
5162 @Override
52 public void contextDestroyed(final ServletContextEvent event) {
53 if (this.servletContext == null || this.initializer == null) {
54 LOGGER.warn("Context destroyed before it was initialized.");
55 return;
56 }
57 LOGGER.debug("Log4jServletContextListener ensuring that Log4j shuts down properly.");
63 public void contextDestroyed(final ServletContextEvent event) {
64 if (this.servletContext == null || this.initializer == null) {
65 LOGGER.warn("Context destroyed before it was initialized.");
66 return;
67 }
68 LOGGER.debug("Log4jServletContextListener ensuring that Log4j shuts down properly.");
5869
59 this.initializer.clearLoggerContext(); // the application is finished shutting down now
60 this.initializer.stop();
61 }
70 this.initializer.clearLoggerContext(); // the application is finished
71 // shutting down now
72 if (initializer instanceof LifeCycle2) {
73 final String stopTimeoutStr = servletContext.getInitParameter(KEY_STOP_TIMEOUT);
74 final long stopTimeout = Strings.isEmpty(stopTimeoutStr) ? DEFAULT_STOP_TIMEOUT
75 : Long.parseLong(stopTimeoutStr);
76 final String timeoutTimeUnitStr = servletContext.getInitParameter(KEY_STOP_TIMEOUT_TIMEUNIT);
77 final TimeUnit timeoutTimeUnit = Strings.isEmpty(timeoutTimeUnitStr) ? DEFAULT_STOP_TIMEOUT_TIMEUNIT
78 : TimeUnit.valueOf(timeoutTimeUnitStr.toUpperCase(Locale.ROOT));
79 ((LifeCycle2) this.initializer).stop(stopTimeout, timeoutTimeUnit);
80 } else {
81 this.initializer.stop();
82 }
83 }
6284 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.web;
17
18 import java.net.URI;
19 import java.net.URL;
20 import java.text.SimpleDateFormat;
21 import java.util.Arrays;
22 import java.util.Date;
23 import java.util.Map;
24 import java.util.concurrent.ConcurrentHashMap;
25
26 import javax.servlet.ServletContext;
27
28 import org.apache.logging.log4j.LogManager;
29 import org.apache.logging.log4j.core.AbstractLifeCycle;
30 import org.apache.logging.log4j.core.LoggerContext;
31 import org.apache.logging.log4j.core.async.AsyncLoggerContext;
32 import org.apache.logging.log4j.core.config.Configurator;
33 import org.apache.logging.log4j.core.impl.ContextAnchor;
34 import org.apache.logging.log4j.core.impl.Log4jContextFactory;
35 import org.apache.logging.log4j.core.lookup.Interpolator;
36 import org.apache.logging.log4j.core.lookup.StrSubstitutor;
37 import org.apache.logging.log4j.core.selector.ContextSelector;
38 import org.apache.logging.log4j.core.selector.NamedContextSelector;
39 import org.apache.logging.log4j.core.util.Loader;
40 import org.apache.logging.log4j.core.util.NetUtils;
41 import org.apache.logging.log4j.core.util.SetUtils;
42 import org.apache.logging.log4j.spi.LoggerContextFactory;
43 import org.apache.logging.log4j.util.LoaderUtil;
44
45 /**
46 * This class initializes and deinitializes Log4j no matter how the initialization occurs.
47 */
48 final class Log4jWebInitializerImpl extends AbstractLifeCycle implements Log4jWebLifeCycle {
49
50 private static final String WEB_INF = "/WEB-INF/";
51
52 static {
53 if (Loader.isClassAvailable("org.apache.logging.log4j.core.web.JNDIContextFilter")) {
54 throw new IllegalStateException("You are using Log4j 2 in a web application with the old, extinct "
55 + "log4j-web artifact. This is not supported and could cause serious runtime problems. Please"
56 + "remove the log4j-web JAR file from your application.");
57 }
58 }
59
60 private final Map<String, String> map = new ConcurrentHashMap<>();
61 private final StrSubstitutor substitutor = new StrSubstitutor(new Interpolator(map));
62 private final ServletContext servletContext;
63
64 private String name;
65 private NamedContextSelector namedContextSelector;
66 private LoggerContext loggerContext;
67
68 private Log4jWebInitializerImpl(final ServletContext servletContext) {
69 this.servletContext = servletContext;
70 this.map.put("hostName", NetUtils.getLocalHostname());
71 }
72
73 /**
74 * Initializes the Log4jWebLifeCycle attribute of a ServletContext. Those who wish to obtain this object should use
75 * the {@link org.apache.logging.log4j.web.WebLoggerContextUtils#getWebLifeCycle(javax.servlet.ServletContext)}
76 * method instead.
77 *
78 * @param servletContext
79 * the ServletContext to initialize
80 * @return a new Log4jWebLifeCycle
81 * @since 2.0.1
82 */
83 protected static Log4jWebInitializerImpl initialize(final ServletContext servletContext) {
84 final Log4jWebInitializerImpl initializer = new Log4jWebInitializerImpl(servletContext);
85 servletContext.setAttribute(SUPPORT_ATTRIBUTE, initializer);
86 return initializer;
87 }
88
89 @Override
90 public synchronized void start() {
91 if (this.isStopped() || this.isStopping()) {
92 throw new IllegalStateException("Cannot start this Log4jWebInitializerImpl after it was stopped.");
93 }
94
95 // only do this once
96 if (this.isInitialized()) {
97 super.setStarting();
98
99 this.name = this.substitutor.replace(this.servletContext.getInitParameter(LOG4J_CONTEXT_NAME));
100 final String location = this.substitutor.replace(this.servletContext
101 .getInitParameter(LOG4J_CONFIG_LOCATION));
102 final boolean isJndi = "true".equalsIgnoreCase(this.servletContext
103 .getInitParameter(IS_LOG4J_CONTEXT_SELECTOR_NAMED));
104
105 if (isJndi) {
106 this.initializeJndi(location);
107 } else {
108 this.initializeNonJndi(location);
109 }
110 if (this.loggerContext instanceof AsyncLoggerContext) {
111 ((AsyncLoggerContext) this.loggerContext).setUseThreadLocals(false);
112 }
113
114 this.servletContext.setAttribute(CONTEXT_ATTRIBUTE, this.loggerContext);
115 super.setStarted();
116 }
117 }
118
119 private void initializeJndi(final String location) {
120 final URI configLocation = getConfigURI(location);
121
122 if (this.name == null) {
123 throw new IllegalStateException("A log4jContextName context parameter is required");
124 }
125
126 LoggerContext context;
127 final LoggerContextFactory factory = LogManager.getFactory();
128 if (factory instanceof Log4jContextFactory) {
129 final ContextSelector selector = ((Log4jContextFactory) factory).getSelector();
130 if (selector instanceof NamedContextSelector) {
131 this.namedContextSelector = (NamedContextSelector) selector;
132 context = this.namedContextSelector.locateContext(this.name, this.servletContext, configLocation);
133 ContextAnchor.THREAD_CONTEXT.set(context);
134 if (context.isInitialized()) {
135 context.start();
136 }
137 ContextAnchor.THREAD_CONTEXT.remove();
138 } else {
139 LOGGER.warn("Potential problem: Selector is not an instance of NamedContextSelector.");
140 return;
141 }
142 } else {
143 LOGGER.warn("Potential problem: LoggerContextFactory is not an instance of Log4jContextFactory.");
144 return;
145 }
146 this.loggerContext = context;
147 LOGGER.debug("Created logger context for [{}] using [{}].", this.name, context.getClass().getClassLoader());
148 }
149
150 private void initializeNonJndi(final String location) {
151 if (this.name == null) {
152 this.name = this.servletContext.getServletContextName();
153 LOGGER.debug("Using the servlet context name \"{}\".", this.name);
154 }
155 if (this.name == null) {
156 this.name = this.servletContext.getContextPath();
157 LOGGER.debug("Using the servlet context context-path \"{}\".", this.name);
158 }
159
160 if (this.name == null && location == null) {
161 LOGGER.error("No Log4j context configuration provided. This is very unusual.");
162 this.name = new SimpleDateFormat("yyyyMMdd_HHmmss.SSS").format(new Date());
163 }
164
165 final URI uri = getConfigURI(location);
166 this.loggerContext = Configurator.initialize(this.name, this.getClassLoader(), uri, this.servletContext);
167 }
168
169 private URI getConfigURI(final String location) {
170 try {
171 String configLocation = location;
172 if (configLocation == null) {
173 final String[] paths = SetUtils.prefixSet(servletContext.getResourcePaths(WEB_INF), WEB_INF + "log4j2");
174 LOGGER.debug("getConfigURI found resource paths {} in servletContext at [{}]", Arrays.toString(paths), WEB_INF);
175 if (paths.length == 1) {
176 configLocation = paths[0];
177 } else if (paths.length > 1) {
178 final String prefix = WEB_INF + "log4j2-" + this.name + ".";
179 boolean found = false;
180 for (final String str : paths) {
181 if (str.startsWith(prefix)) {
182 configLocation = str;
183 found = true;
184 break;
185 }
186 }
187 if (!found) {
188 configLocation = paths[0];
189 }
190 }
191 }
192 if (configLocation != null) {
193 final URL url = servletContext.getResource(configLocation);
194 if (url != null) {
195 final URI uri = url.toURI();
196 LOGGER.debug("getConfigURI found resource [{}] in servletContext at [{}]", uri, configLocation);
197 return uri;
198 }
199 }
200 } catch (final Exception ex) {
201 // Just try passing the location.
202 }
203 if (location != null) {
204 try {
205 final URI correctedFilePathUri = NetUtils.toURI(location);
206 LOGGER.debug("getConfigURI found [{}] in servletContext at [{}]", correctedFilePathUri, location);
207 return correctedFilePathUri;
208 } catch (final Exception e) {
209 LOGGER.error("Unable to convert configuration location [{}] to a URI", location, e);
210 }
211 }
212 return null;
213 }
214
215 @Override
216 public synchronized void stop() {
217 if (!this.isStarted() && !this.isStopped()) {
218 throw new IllegalStateException("Cannot stop this Log4jWebInitializer because it has not started.");
219 }
220
221 // only do this once
222 if (this.isStarted()) {
223 this.setStopping();
224 if (this.loggerContext != null) {
225 LOGGER.debug("Removing LoggerContext for [{}].", this.name);
226 this.servletContext.removeAttribute(CONTEXT_ATTRIBUTE);
227 if (this.namedContextSelector != null) {
228 this.namedContextSelector.removeContext(this.name);
229 }
230 this.loggerContext.stop();
231 this.loggerContext.setExternalContext(null);
232 this.loggerContext = null;
233 }
234 this.setStopped();
235 }
236 }
237
238 @Override
239 public void setLoggerContext() {
240 if (this.loggerContext != null) {
241 ContextAnchor.THREAD_CONTEXT.set(this.loggerContext);
242 }
243 }
244
245 @Override
246 public void clearLoggerContext() {
247 ContextAnchor.THREAD_CONTEXT.remove();
248 }
249
250 @Override
251 public void wrapExecution(final Runnable runnable) {
252 this.setLoggerContext();
253
254 try {
255 runnable.run();
256 } finally {
257 this.clearLoggerContext();
258 }
259 }
260
261 private ClassLoader getClassLoader() {
262 try {
263 // if container is Servlet 3.0, use its getClassLoader method
264 // this may look odd, but the call below will throw NoSuchMethodError if user is on Servlet 2.5
265 // we compile against 3.0 to support Log4jServletContainerInitializer, but we don't require 3.0
266 return this.servletContext.getClassLoader();
267 } catch (final Throwable ignore) {
268 // LOG4J2-248: use TCCL if possible
269 return LoaderUtil.getThreadContextClassLoader();
270 }
271 }
272
273 }
0 /*
1 * Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache license, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16 package org.apache.logging.log4j.web;
17
18 import java.net.URI;
19 import java.net.URL;
20 import java.text.SimpleDateFormat;
21 import java.util.Arrays;
22 import java.util.Date;
23 import java.util.Map;
24 import java.util.concurrent.ConcurrentHashMap;
25 import java.util.concurrent.TimeUnit;
26
27 import javax.servlet.ServletContext;
28
29 import org.apache.logging.log4j.LogManager;
30 import org.apache.logging.log4j.core.AbstractLifeCycle;
31 import org.apache.logging.log4j.core.LoggerContext;
32 import org.apache.logging.log4j.core.async.AsyncLoggerContext;
33 import org.apache.logging.log4j.core.config.Configurator;
34 import org.apache.logging.log4j.core.impl.ContextAnchor;
35 import org.apache.logging.log4j.core.impl.Log4jContextFactory;
36 import org.apache.logging.log4j.core.lookup.Interpolator;
37 import org.apache.logging.log4j.core.lookup.StrSubstitutor;
38 import org.apache.logging.log4j.core.selector.ContextSelector;
39 import org.apache.logging.log4j.core.selector.NamedContextSelector;
40 import org.apache.logging.log4j.core.util.Loader;
41 import org.apache.logging.log4j.core.util.NetUtils;
42 import org.apache.logging.log4j.core.util.SetUtils;
43 import org.apache.logging.log4j.spi.LoggerContextFactory;
44 import org.apache.logging.log4j.util.LoaderUtil;
45
46 /**
47 * This class initializes and deinitializes Log4j no matter how the initialization occurs.
48 */
49 final class Log4jWebInitializerImpl extends AbstractLifeCycle implements Log4jWebLifeCycle {
50
51 private static final String WEB_INF = "/WEB-INF/";
52
53 static {
54 if (Loader.isClassAvailable("org.apache.logging.log4j.core.web.JNDIContextFilter")) {
55 throw new IllegalStateException("You are using Log4j 2 in a web application with the old, extinct "
56 + "log4j-web artifact. This is not supported and could cause serious runtime problems. Please"
57 + "remove the log4j-web JAR file from your application.");
58 }
59 }
60
61 private final Map<String, String> map = new ConcurrentHashMap<>();
62 private final StrSubstitutor substitutor = new StrSubstitutor(new Interpolator(map));
63 private final ServletContext servletContext;
64
65 private String name;
66 private NamedContextSelector namedContextSelector;
67 private LoggerContext loggerContext;
68
69 private Log4jWebInitializerImpl(final ServletContext servletContext) {
70 this.servletContext = servletContext;
71 this.map.put("hostName", NetUtils.getLocalHostname());
72 }
73
74 /**
75 * Initializes the Log4jWebLifeCycle attribute of a ServletContext. Those who wish to obtain this object should use
76 * the {@link org.apache.logging.log4j.web.WebLoggerContextUtils#getWebLifeCycle(javax.servlet.ServletContext)}
77 * method instead.
78 *
79 * @param servletContext
80 * the ServletContext to initialize
81 * @return a new Log4jWebLifeCycle
82 * @since 2.0.1
83 */
84 protected static Log4jWebInitializerImpl initialize(final ServletContext servletContext) {
85 final Log4jWebInitializerImpl initializer = new Log4jWebInitializerImpl(servletContext);
86 servletContext.setAttribute(SUPPORT_ATTRIBUTE, initializer);
87 return initializer;
88 }
89
90 @Override
91 public synchronized void start() {
92 if (this.isStopped() || this.isStopping()) {
93 throw new IllegalStateException("Cannot start this Log4jWebInitializerImpl after it was stopped.");
94 }
95
96 // only do this once
97 if (this.isInitialized()) {
98 super.setStarting();
99
100 this.name = this.substitutor.replace(this.servletContext.getInitParameter(LOG4J_CONTEXT_NAME));
101 final String location = this.substitutor.replace(this.servletContext
102 .getInitParameter(LOG4J_CONFIG_LOCATION));
103 final boolean isJndi = "true".equalsIgnoreCase(this.servletContext
104 .getInitParameter(IS_LOG4J_CONTEXT_SELECTOR_NAMED));
105
106 if (isJndi) {
107 this.initializeJndi(location);
108 } else {
109 this.initializeNonJndi(location);
110 }
111 if (this.loggerContext instanceof AsyncLoggerContext) {
112 ((AsyncLoggerContext) this.loggerContext).setUseThreadLocals(false);
113 }
114
115 this.servletContext.setAttribute(CONTEXT_ATTRIBUTE, this.loggerContext);
116 super.setStarted();
117 }
118 }
119
120 private void initializeJndi(final String location) {
121 final URI configLocation = getConfigURI(location);
122
123 if (this.name == null) {
124 throw new IllegalStateException("A log4jContextName context parameter is required");
125 }
126
127 LoggerContext context;
128 final LoggerContextFactory factory = LogManager.getFactory();
129 if (factory instanceof Log4jContextFactory) {
130 final ContextSelector selector = ((Log4jContextFactory) factory).getSelector();
131 if (selector instanceof NamedContextSelector) {
132 this.namedContextSelector = (NamedContextSelector) selector;
133 context = this.namedContextSelector.locateContext(this.name, this.servletContext, configLocation);
134 ContextAnchor.THREAD_CONTEXT.set(context);
135 if (context.isInitialized()) {
136 context.start();
137 }
138 ContextAnchor.THREAD_CONTEXT.remove();
139 } else {
140 LOGGER.warn("Potential problem: Selector is not an instance of NamedContextSelector.");
141 return;
142 }
143 } else {
144 LOGGER.warn("Potential problem: LoggerContextFactory is not an instance of Log4jContextFactory.");
145 return;
146 }
147 this.loggerContext = context;
148 LOGGER.debug("Created logger context for [{}] using [{}].", this.name, context.getClass().getClassLoader());
149 }
150
151 private void initializeNonJndi(final String location) {
152 if (this.name == null) {
153 this.name = this.servletContext.getServletContextName();
154 LOGGER.debug("Using the servlet context name \"{}\".", this.name);
155 }
156 if (this.name == null) {
157 this.name = this.servletContext.getContextPath();
158 LOGGER.debug("Using the servlet context context-path \"{}\".", this.name);
159 }
160
161 if (this.name == null && location == null) {
162 LOGGER.error("No Log4j context configuration provided. This is very unusual.");
163 this.name = new SimpleDateFormat("yyyyMMdd_HHmmss.SSS").format(new Date());
164 }
165
166 final URI uri = getConfigURI(location);
167 this.loggerContext = Configurator.initialize(this.name, this.getClassLoader(), uri, this.servletContext);
168 }
169
170 private URI getConfigURI(final String location) {
171 try {
172 String configLocation = location;
173 if (configLocation == null) {
174 final String[] paths = SetUtils.prefixSet(servletContext.getResourcePaths(WEB_INF), WEB_INF + "log4j2");
175 LOGGER.debug("getConfigURI found resource paths {} in servletContext at [{}]", Arrays.toString(paths), WEB_INF);
176 if (paths.length == 1) {
177 configLocation = paths[0];
178 } else if (paths.length > 1) {
179 final String prefix = WEB_INF + "log4j2-" + this.name + ".";
180 boolean found = false;
181 for (final String str : paths) {
182 if (str.startsWith(prefix)) {
183 configLocation = str;
184 found = true;
185 break;
186 }
187 }
188 if (!found) {
189 configLocation = paths[0];
190 }
191 }
192 }
193 if (configLocation != null) {
194 final URL url = servletContext.getResource(configLocation);
195 if (url != null) {
196 final URI uri = url.toURI();
197 LOGGER.debug("getConfigURI found resource [{}] in servletContext at [{}]", uri, configLocation);
198 return uri;
199 }
200 }
201 } catch (final Exception ex) {
202 // Just try passing the location.
203 }
204 if (location != null) {
205 try {
206 final URI correctedFilePathUri = NetUtils.toURI(location);
207 LOGGER.debug("getConfigURI found [{}] in servletContext at [{}]", correctedFilePathUri, location);
208 return correctedFilePathUri;
209 } catch (final Exception e) {
210 LOGGER.error("Unable to convert configuration location [{}] to a URI", location, e);
211 }
212 }
213 return null;
214 }
215
216 @Override
217 public synchronized boolean stop(final long timeout, final TimeUnit timeUnit) {
218 if (!this.isStarted() && !this.isStopped()) {
219 throw new IllegalStateException("Cannot stop this Log4jWebInitializer because it has not started.");
220 }
221
222 // only do this once
223 if (this.isStarted()) {
224 this.setStopping();
225 if (this.loggerContext != null) {
226 LOGGER.debug("Removing LoggerContext for [{}].", this.name);
227 this.servletContext.removeAttribute(CONTEXT_ATTRIBUTE);
228 if (this.namedContextSelector != null) {
229 this.namedContextSelector.removeContext(this.name);
230 }
231 this.loggerContext.stop(timeout, timeUnit);
232 this.loggerContext.setExternalContext(null);
233 this.loggerContext = null;
234 }
235 this.setStopped();
236 }
237 return super.stop(timeout, timeUnit);
238 }
239
240 @Override
241 public void setLoggerContext() {
242 if (this.loggerContext != null) {
243 ContextAnchor.THREAD_CONTEXT.set(this.loggerContext);
244 }
245 }
246
247 @Override
248 public void clearLoggerContext() {
249 ContextAnchor.THREAD_CONTEXT.remove();
250 }
251
252 @Override
253 public void wrapExecution(final Runnable runnable) {
254 this.setLoggerContext();
255
256 try {
257 runnable.run();
258 } finally {
259 this.clearLoggerContext();
260 }
261 }
262
263 private ClassLoader getClassLoader() {
264 try {
265 // if container is Servlet 3.0, use its getClassLoader method
266 // this may look odd, but the call below will throw NoSuchMethodError if user is on Servlet 2.5
267 // we compile against 3.0 to support Log4jServletContainerInitializer, but we don't require 3.0
268 return this.servletContext.getClassLoader();
269 } catch (final Throwable ignore) {
270 // LOG4J2-248: use TCCL if possible
271 return LoaderUtil.getThreadContextClassLoader();
272 }
273 }
274
275 }
2828 public class WebLookup extends AbstractLookup {
2929 private static final String ATTR_PREFIX = "attr.";
3030 private static final String INIT_PARAM_PREFIX = "initParam.";
31
32 /**
33 * @deprecated Use {@link WebLoggerContextUtils#getServletContext()}.
34 */
35 @Deprecated
36 protected ServletContext getServletContext() {
37 return WebLoggerContextUtils.getServletContext();
38 }
3931
4032 @Override
4133 public String lookup(final LogEvent event, final String key) {
1616 package org.apache.logging.log4j.web.appender;
1717
1818 import java.io.Serializable;
19
1920 import javax.servlet.ServletContext;
2021
2122 import org.apache.logging.log4j.core.Filter;
2324 import org.apache.logging.log4j.core.LogEvent;
2425 import org.apache.logging.log4j.core.appender.AbstractAppender;
2526 import org.apache.logging.log4j.core.config.plugins.Plugin;
26 import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
27 import org.apache.logging.log4j.core.config.plugins.PluginElement;
28 import org.apache.logging.log4j.core.config.plugins.PluginFactory;
29 import org.apache.logging.log4j.core.config.plugins.validation.constraints.Required;
27 import org.apache.logging.log4j.core.config.plugins.PluginBuilderAttribute;
28 import org.apache.logging.log4j.core.config.plugins.PluginBuilderFactory;
3029 import org.apache.logging.log4j.core.layout.AbstractStringLayout;
3130 import org.apache.logging.log4j.core.layout.PatternLayout;
3231 import org.apache.logging.log4j.web.WebLoggerContextUtils;
3736 @Plugin(name = "Servlet", category = "Core", elementType = "appender", printObject = true)
3837 public class ServletAppender extends AbstractAppender {
3938
39 public static class Builder<B extends Builder<B>> extends AbstractAppender.Builder<B>
40 implements org.apache.logging.log4j.core.util.Builder<ServletAppender> {
41
42 @PluginBuilderAttribute
43 private boolean logThrowables;
44
45 @Override
46 public ServletAppender build() {
47 final String name = getName();
48 if (name == null) {
49 LOGGER.error("No name provided for ServletAppender");
50 }
51 final ServletContext servletContext = WebLoggerContextUtils.getServletContext();
52 if (servletContext == null) {
53 LOGGER.error("No servlet context is available");
54 return null;
55 }
56 Layout<? extends Serializable> layout = getLayout();
57 if (layout == null) {
58 layout = PatternLayout.createDefaultLayout();
59 } else if (!(layout instanceof AbstractStringLayout)) {
60 LOGGER.error("Layout must be a StringLayout to log to ServletContext");
61 return null;
62 }
63 return new ServletAppender(name, layout, getFilter(), servletContext, isIgnoreExceptions(), logThrowables);
64 }
65
66 /**
67 * Logs with {@link ServletContext#log(String, Throwable)} if true and with {@link ServletContext#log(String)} if false.
68 *
69 * @return whether to log a Throwable with the servlet context.
70 */
71 public boolean isLogThrowables() {
72 return logThrowables;
73 }
74
75 /**
76 * Logs with {@link ServletContext#log(String, Throwable)} if true and with {@link ServletContext#log(String)} if false.
77 */
78 public void setLogThrowables(boolean logThrowables) {
79 this.logThrowables = logThrowables;
80 }
81
82 }
83
84 @PluginBuilderFactory
85 public static <B extends Builder<B>> B newBuilder() {
86 return new Builder<B>().asBuilder();
87 }
88
4089 private final ServletContext servletContext;
41
42 private ServletAppender(final String name, final AbstractStringLayout layout, final Filter filter,
43 final ServletContext servletContext, final boolean ignoreExceptions) {
90 private boolean logThrowables;
91
92 private ServletAppender(final String name, final Layout<? extends Serializable> layout, final Filter filter,
93 final ServletContext servletContext, final boolean ignoreExceptions, final boolean logThrowables) {
4494 super(name, filter, layout, ignoreExceptions);
4595 this.servletContext = servletContext;
96 this.logThrowables = logThrowables;
4697 }
4798
4899 @Override
49100 public void append(final LogEvent event) {
50 servletContext.log(((AbstractStringLayout) getLayout()).toSerializable(event));
101 final String serialized = ((AbstractStringLayout) getLayout()).toSerializable(event);
102 if (logThrowables) {
103 servletContext.log(serialized, event.getThrown());
104 } else {
105 servletContext.log(serialized);
106 }
51107 }
52108
53109 /**
54 * Create a Servlet Appender.
110 * Creates a Servlet Appender.
55111 * @param layout The layout to use (required). Must extend {@link AbstractStringLayout}.
56112 * @param filter The Filter or null.
57113 * @param name The name of the Appender (required).
58114 * @param ignoreExceptions If {@code true} (default) exceptions encountered when appending events are logged;
59115 * otherwise they are propagated to the caller.
60116 * @return The ServletAppender.
117 * @deprecated Use {@link #newBuilder()}.
61118 */
62 @PluginFactory
63 public static ServletAppender createAppender(
64 @PluginElement("Layout") Layout<? extends Serializable> layout,
65 @PluginElement("Filter") final Filter filter,
66 @PluginAttribute("name") @Required(message = "No name provided for ServletAppender") final String name,
67 @PluginAttribute(value = "ignoreExceptions", defaultBoolean = true) final boolean ignoreExceptions) {
68 final ServletContext servletContext = WebLoggerContextUtils.getServletContext();
69 if (servletContext == null) {
70 LOGGER.error("No servlet context is available");
71 return null;
72 }
73 if (layout == null) {
74 layout = PatternLayout.createDefaultLayout();
75 } else if (!(layout instanceof AbstractStringLayout)) {
76 LOGGER.error("Layout must be a StringLayout to log to ServletContext");
77 return null;
78 }
79 return new ServletAppender(name, (AbstractStringLayout) layout, filter, servletContext, ignoreExceptions);
119 @Deprecated
120 public static ServletAppender createAppender(Layout<? extends Serializable> layout, final Filter filter,
121 final String name, final boolean ignoreExceptions) {
122 // @formatter:off
123 return newBuilder()
124 .withFilter(filter)
125 .withIgnoreExceptions(ignoreExceptions)
126 .withLayout(layout)
127 .withName(name)
128 .build();
129 // @formatter:on
80130 }
81131
82132 }
5757 assertNotNull("No ServletAppender", appender);
5858 final Logger logger = LogManager.getLogger("Test");
5959 logger.info("This is a test");
60 logger.error("This is a test 2", new IllegalStateException().fillInStackTrace());
6061 } catch (final IllegalStateException e) {
6162 fail("Failed to initialize Log4j properly." + e.getMessage());
6263 } finally {
0 <?xml version="1.0" encoding="UTF-8"?>
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 <Configuration status="WARN" name="ServletTest">
19
20 <Appenders>
21 <Servlet name="Servlet">
22 <PatternLayout pattern="%m%n"/>
23 </Servlet>
24 </Appenders>
25
26 <Loggers>
27 <Root level="debug">
28 <AppenderRef ref="Servlet"/>
29 </Root>
30 </Loggers>
31
0 <?xml version="1.0" encoding="UTF-8"?>
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 <Configuration status="WARN" name="ServletTest">
19
20 <Appenders>
21 <Servlet name="Servlet" logThrowables="true">
22 <PatternLayout pattern="%m%n%ex{none}"/>
23 </Servlet>
24 </Appenders>
25
26 <Loggers>
27 <Root level="debug">
28 <AppenderRef ref="Servlet"/>
29 </Root>
30 </Loggers>
31
3232 </Configuration>
2121 <artifactId>log4j</artifactId>
2222 <packaging>pom</packaging>
2323 <name>Apache Log4j 2</name>
24 <version>2.6.2</version>
24 <version>2.7</version>
2525 <parent>
2626 <groupId>org.apache</groupId>
2727 <artifactId>apache</artifactId>
172172 <connection>scm:git:http://git-wip-us.apache.org/repos/asf/logging-log4j2.git</connection>
173173 <developerConnection>scm:git:https://git-wip-us.apache.org/repos/asf/logging-log4j2.git</developerConnection>
174174 <url>https://git-wip-us.apache.org/repos/asf?p=logging-log4j2.git;a=summary</url>
175 <tag>log4j-2.6.2-rc1</tag>
175 <tag>log4j-2.7-rc2</tag>
176176 </scm>
177177 <organization>
178178 <name>Apache Software Foundation</name>
181181 <properties>
182182 <!-- make sure to update these for each release! -->
183183 <log4jParentDir>${basedir}</log4jParentDir>
184 <Log4jReleaseVersion>2.6.2</Log4jReleaseVersion>
185 <Log4jReleaseCount>twelfth</Log4jReleaseCount>
184 <Log4jReleaseVersion>2.7</Log4jReleaseVersion>
186185 <Log4jReleaseManager>Ralph Goers</Log4jReleaseManager>
187186 <Log4jReleaseKey>B3D8E1BA</Log4jReleaseKey>
188187 <!-- <Log4jReleaseManager>Matt Sicker</Log4jReleaseManager>
191190 <slf4jVersion>1.7.21</slf4jVersion>
192191 <logbackVersion>1.1.7</logbackVersion>
193192 <jackson1Version>1.9.13</jackson1Version>
194 <jackson2Version>2.7.5</jackson2Version>
193 <jackson2Version>2.8.3</jackson2Version>
195194 <springVersion>3.2.13.RELEASE</springVersion>
196195 <flumeVersion>1.6.0</flumeVersion>
197 <disruptorVersion>3.3.4</disruptorVersion>
196 <disruptorVersion>3.3.5</disruptorVersion>
197 <conversantDisruptorVersion>1.2.8-JDK7</conversantDisruptorVersion>
198198 <compiler.plugin.version>3.5.1</compiler.plugin.version>
199199 <pmd.plugin.version>3.6</pmd.plugin.version>
200 <findbugs.plugin.version>3.0.3</findbugs.plugin.version>
200 <findbugs.plugin.version>3.0.4</findbugs.plugin.version>
201201 <changes.plugin.version>2.12</changes.plugin.version>
202202 <javadoc.plugin.version>2.10.4</javadoc.plugin.version>
203203 <!-- surefire.plugin.version 2.18 yields http://jira.codehaus.org/browse/SUREFIRE-1121, which is fixed in 2.18.1 -->
209209 <pdf.plugin.version>1.2</pdf.plugin.version>
210210 <cobertura.plugin.version>2.7</cobertura.plugin.version>
211211 <release.plugin.version>2.5.3</release.plugin.version>
212 <scm.plugin.version>1.9.4</scm.plugin.version>
212 <scm.plugin.version>1.9.5</scm.plugin.version>
213213 <jxr.plugin.version>2.5</jxr.plugin.version>
214214 <clirr.plugin.version>2.6.1</clirr.plugin.version>
215215 <site.plugin.version>3.4</site.plugin.version>
220220 <projectDir />
221221 <commonsLoggingVersion>1.2</commonsLoggingVersion>
222222 <osgi.api.version>4.3.1</osgi.api.version>
223 <activemq.version>5.13.3</activemq.version>
223 <activemq.version>5.14.0</activemq.version>
224224 <!-- Allow Clirr severity to be overriden by the command-line option -DminSeverity=level -->
225225 <minSeverity>info</minSeverity>
226 <jctoolsVersion>1.2.1</jctoolsVersion>
226227 </properties>
227228 <pluginRepositories>
228229 <pluginRepository>
289290 <version>3.4</version>
290291 </dependency>
291292 <dependency>
293 <groupId>com.beust</groupId>
294 <artifactId>jcommander</artifactId>
295 <version>1.48</version>
296 </dependency>
297 <dependency>
292298 <groupId>ch.qos.logback</groupId>
293299 <artifactId>logback-classic</artifactId>
294300 <version>${logbackVersion}</version>
371377 <version>${project.version}</version>
372378 </dependency>
373379 <dependency>
380 <groupId>org.apache.logging.log4j</groupId>
381 <artifactId>log4j-api-scala_2.10</artifactId>
382 <version>${project.version}</version>
383 </dependency>
384 <dependency>
385 <groupId>org.apache.logging.log4j</groupId>
386 <artifactId>log4j-api-scala_2.11</artifactId>
387 <version>${project.version}</version>
388 </dependency>
389 <dependency>
374390 <groupId>com.sleepycat</groupId>
375391 <artifactId>je</artifactId>
376392 <version>5.0.73</version>
590606 <dependency>
591607 <groupId>org.apache.kafka</groupId>
592608 <artifactId>kafka-clients</artifactId>
593 <version>0.9.0.1</version>
609 <version>0.10.0.1</version>
594610 </dependency>
595611 <dependency>
596612 <groupId>org.zeromq</groupId>
609625 <version>${disruptorVersion}</version>
610626 </dependency>
611627 <dependency>
628 <groupId>com.conversantmedia</groupId>
629 <artifactId>disruptor</artifactId>
630 <version>${conversantDisruptorVersion}</version>
631 </dependency>
632 <dependency>
633 <groupId>org.jctools</groupId>
634 <artifactId>jctools-core</artifactId>
635 <version>${jctoolsVersion}</version>
636 </dependency>
637 <dependency>
612638 <groupId>junit</groupId>
613639 <artifactId>junit</artifactId>
614640 <version>4.12</version>
618644 <groupId>org.hamcrest</groupId>
619645 <artifactId>hamcrest-all</artifactId>
620646 <version>1.3</version>
647 <scope>test</scope>
648 </dependency>
649 <dependency>
650 <groupId>org.codehaus.plexus</groupId>
651 <artifactId>plexus-utils</artifactId>
652 <version>3.0.24</version>
621653 <scope>test</scope>
622654 </dependency>
623655 <dependency>
711743 <groupId>net.javacrumbs.json-unit</groupId>
712744 <artifactId>json-unit</artifactId>
713745 <version>1.5.5</version>
746 <scope>test</scope>
747 </dependency>
748 <dependency>
749 <groupId>org.xmlunit</groupId>
750 <artifactId>xmlunit-core</artifactId>
751 <version>2.2.1</version>
752 <scope>test</scope>
753 </dependency>
754 <dependency>
755 <groupId>org.xmlunit</groupId>
756 <artifactId>xmlunit-matchers</artifactId>
757 <version>2.2.1</version>
714758 <scope>test</scope>
715759 </dependency>
716760 <dependency>
837881 <plugin>
838882 <groupId>org.apache.maven.plugins</groupId>
839883 <artifactId>maven-source-plugin</artifactId>
840 <version>3.0.0</version>
884 <version>3.0.1</version>
841885 <executions>
842886 <execution>
843887 <id>attach-sources</id>
12121256 <module>log4j-iostreams</module>
12131257 <module>log4j-jul</module>
12141258 <module>log4j-liquibase</module>
1259 <module>log4j-api-scala_2.10</module>
1260 <module>log4j-api-scala_2.11</module>
12151261 </modules>
12161262 <profiles>
12171263 <profile>
2727 Loggers. Another notable Log4j 2 feature is the ability to be "garbage-free" (avoid allocating
2828 temporary objects) while logging. In addition, Log4j 2 will not lose events while reconfiguring.
2929
30 This is the ${relCount} GA release. It is primarily a bugfix release. More details on the
31 fixes are itemized below.
30 This release contains several bugfixes and new features. The new features include new logging API
31 modules for Scala 2.10 and 2.11, and support for various non-blocking queue implementations in
32 AsyncAppender. Furthermore the ThreadContext map can now be configured to be garbage-free, and
33 users can now inject context data from other sources than ThreadContext. Context data values can
34 be any Object, not just Strings. More details on the fixes are itemized below.
3235
3336 Note that subsequent to the 2.6 release a minor source incompatibility was found due to the
3437 addition of new methods to the Logger interface. If you have code that does:
4447
4548 logger.error((Marker) null, “This is the log message”, throwable);
4649
47 Log4j 2.6.2 maintains binary compatibility with previous releases.
50 The Log4j ${relVersion} API, as well as many core components, maintains binary compatibility with previous releases.
4851
4952 ## Hack to improve layout: replace all pairs of spaces with a single new-line
5053 $release.description.replaceAll(" ", "
149152 ## End of main loop
150153 #end
151154
152 Apache Log4j ${relVersion} requires a minimum of Java 7 to build and run. Log4j 2.3 was the last release that
153 supported Java 6.
155 Apache Log4j ${relVersion} requires a minimum of Java 7 to build and run. Log4j 2.3 was the
156 last release that supported Java 6.
154157
155 Basic compatibility with Log4j 1.x is provided through the log4j-1.2-api component, however it does not implement some of the
156 very implementation specific classes and methods. The package names and Maven groupId have been changed to
157 org.apache.logging.log4j to avoid any conflicts with log4j 1.x.
158 Basic compatibility with Log4j 1.x is provided through the log4j-1.2-api component, however it
159 does not implement some of the very implementation specific classes and methods. The package
160 names and Maven groupId have been changed to org.apache.logging.log4j to avoid any conflicts
161 with log4j 1.x.
158162
159 For complete information on ${project.name}, including instructions on how to submit bug reports,
160 patches, or suggestions for improvement, see the Apache ${project.name} website:
163 For complete information on ${project.name}, including instructions on how to submit bug
164 reports, patches, or suggestions for improvement, see the Apache ${project.name} website:
161165
162166 ${project.url}
0 <?xml version="1.0" encoding="UTF-8"?>
1 <!-- vi: set sw=2: -->
2 <!--
3 Licensed to the Apache Software Foundation (ASF) under one or more
4 contributor license agreements. See the NOTICE file distributed with
5 this work for additional information regarding copyright ownership.
6 The ASF licenses this file to You under the Apache License, Version 2.0
7 (the "License"); you may not use this file except in compliance with
8 the License. You may obtain a copy of the License at
9
10 http://www.apache.org/licenses/LICENSE-2.0
11
12 Unless required by applicable law or agreed to in writing, software
13 distributed under the License is distributed on an "AS IS" BASIS,
14 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 See the License for the specific language governing permissions and
16 limitations under the License.
17 -->
18 <document xmlns="http://maven.apache.org/changes/1.0.0"
19 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
20 xsi:schemaLocation="http://maven.apache.org/changes/1.0.0 http://maven.apache.org/xsd/changes-1.0.0.xsd">
21 <properties>
22 <title>Changes</title>
23 </properties>
24 <body>
25 <release version="2.6.2" date="2016-07-05" description="GA Release 2.6.2">
26 <action issue="LOG4J2-904" dev="rgoers" due-to="Bernhard Mähr">
27 If copy and delete fails in rename action then resort to truncating the source file after copying it.
28 </action>
29 <action issue="LOG4J2-1250" dev="rgoers">
30 CronTriggeringPolicy was not properly setting the prevFileTime value for the PatternProcessor so
31 file dates and times on rolled files were incorrect.
32 </action>
33 <action issue="LOG4J2-1452" dev="rpopma" due-to="Mikael Ståldal">
34 Fixed issue where reusable messages broke flow tracing logic.
35 </action>
36 <action issue="LOG4J2-1440" dev="rgoers">
37 Fix bug in OnStartupTriggeringPolicy that allowed it to roll over on every reconfiguration. Added
38 minSize attribute.
39 </action>
40 <action issue="LOG4J2-1414" dev="rpopma" type="fix" due-to="Ralph Goers">
41 Fixed minor issues with the 2.6.1 web site.
42 </action>
43 <action issue="LOG4J2-1434" dev="rpopma" type="fix" due-to="Luke Butters">
44 Ensure that the thread-local StringBuilders used by Layouts to format log events to text will not
45 retain excessive memory after a large message was logged.
46 </action>
47 <action issue="LOG4J2-1395" dev="mikes" type="add">
48 Add "direct" option to ConsoleAppender for increased performance.
49 </action>
50 <action issue="LOG4J2-1418" dev="mikes" type="fix">
51 Provide MessageFactory2 to custom Logger implementations.
52 </action>
53 <action issue="LOG4J2-1420" dev="rgoers" type="fix">
54 RollingRandomAccessFileManager was not properly rolling over on startup and was getting a NullPointerException.
55 </action>
56 <action issue="LOG4J2-1417" dev="rpopma" type="fix">
57 Fixed issue where Unbox utility ignored the value Constants.ENABLE_THREADLOCALS and always stored non-JDK classes in ThreadLocals.
58 </action>
59 <action issue="LOG4J2-1422" dev="rpopma" type="fix">
60 Fixed issue where AsyncAppenderQueueFullPolicyTest sometimes hangs.
61 </action>
62 <action issue="LOG4J2-1445" dev="ggregory" type="fix" due-to="Ludovic HOCHET">
63 OnStartupTriggeringPolicyTest fails on Windows saying the file is used by another process.
64 </action>
65 <action issue="LOG4J2-1437" dev="rpopma" type="add">
66 (GC) ObjectMessage and ReusableObjectMessage now avoid calling toString() on auto-boxed primitive parameters.
67 </action>
68 <action issue="LOG4J2-1415" dev="rpopma" type="add">
69 (GC) ParameterFormatter now avoids calling toString() on auto-boxed primitive message parameters.
70 </action>
71 <action issue="LOG4J2-1412" dev="rpopma" type="add">
72 Unbox utility's ringbuffer of StringBuilders is now configurable.
73 </action>
74 <action issue="LOG4J2-1432" dev="ggregory" type="update">
75 Update Jackson from 2.7.4 to 2.7.5.
76 </action>
77 <action issue="LOG4J2-1433" dev="ggregory" type="update">
78 Update Jansi from 1.11 to 1.13.
79 </action>
80 <action issue="LOG4J2-1444" dev="ggregory" type="update">
81 Update Apache Commons Compress from 1.11 to 1.12.
82 </action>
83 </release>
84 <release version="2.6.1" date="2016-06-05" description="GA Release 2.6.1">
85 <action issue="LOG4J2-1405" dev="rgoers" type="fix">
86 OnStartupTriggeringPolicy was forcing a rollover of empty files at startup and would append a
87 second footer that was added by the prior shutdown.
88 </action>
89 <action issue="LOG4J2-1406" dev="rpopma" type="fix" due-to="Trask Stalnaker">
90 Fixed bug in ReusableParameterizedMessage where Throwable was never updated so first error was logged over
91 and over again and subsequent errors were not logged.
92 </action>
93 <action issue="LOG4J2-1409" dev="rpopma" type="fix" due-to="Shahan">
94 Fixed ArrayIndexOutOfBoundsException that may occur in ReusableParameterizedMessage.
95 </action>
96 <action issue="LOG4J2-997" dev="rgoers" type="fix" due-to="Maytee Chinavanichkit">
97 Add filter and remove filter were not working properly in AbstractFilterable.
98 </action>
99 <action issue="LOG4J2-1032" dev="rgoers" type="fix">
100 Change RenameAction to use java.nio to better report rename failures.
101 </action>
102 <action issue="LOG4J2-1407" dev="ggregory" type="fix" due-to="Gary Gregory">
103 Misleading WARN log events from Log4j about message factories and unexpected formatting.
104 </action>
105 <action issue="LOG4J2-1408" dev="ggregory" type="fix" due-to="Gary Gregory">
106 The module log4j-liquibase is missing from BOM POM.
107 </action>
108 <action issue="LOG4J2-1180" dev="ggregory" type="fix" due-to="Gary Gregory">
109 Logger cache does not account for message factory.
110 </action>
111 <action issue="LOG4J2-1402" dev="rgoers" type="fix">
112 Fix regression in properties configuration to support arbitrary component ids.
113 </action>
114 <action issue="LOG4J2-1385" dev="ggregory" type="update">
115 (GC) CSV layouts should not create a new CSVPrinter for each log event. Requires Apache Commons CSV 1.4.
116 </action>
117 <action issue="LOG4J2-1398" dev="ggregory" type="update">
118 Update liquibase-core from 3.4.2 to 3.5.1.
119 </action>
120 <action issue="LOG4J2-1399" dev="ggregory" type="update">
121 Update Apache Commons CSV from 1.3 to 1.4.
122 </action>
123 <action issue="LOG4J2-1411" dev="mattsicker" type="add">
124 Add documentation about plugin builders compared to factories.
125 </action>
126 <action issue="LOG4J2-1394" dev="mattsicker,mikes" type="fix">
127 Fixed minor issues with the 2.6 web site.
128 </action>
129 </release>
130 <release version="2.6" date="2016-05-25" description="GA Release 2.6">
131 <action issue="LOG4J2-1270" dev="rpopma" type="add">
132 (GC) Added support for garbage-free logging in steady state.
133 This includes Async Loggers and logging synchronously to the console and to a file,
134 but does not include the AsyncAppender. This release makes the GelfLayout and
135 the main patterns in the PatternLayout garbage-free.
136 </action>
137 <action issue="LOG4J2-1297" dev="rpopma" type="add">
138 (GC) Added manual page on garbage-free logging.
139 </action>
140 <action issue="LOG4J2-1373" dev="rpopma" type="add">
141 (GC) Update Logger wrapper Generator tool to generate methods for the new Logger methods.
142 </action>
143 <action issue="LOG4J2-1356" dev="mikes" type="update">
144 (GC) GelfLayout does now support garabage-free logging (with compressionType=OFF).
145 </action>
146 <action issue="LOG4J2-1326" dev="rpopma" type="add">
147 (GC) Added methods to the Logger interface for logging CharSequence messages.
148 </action>
149 <action issue="LOG4J2-1344" dev="rpopma" type="add">
150 (GC) FileAppender, RollingFileAppender and MemoryMappedFileAppender are now also garbage-free by default.
151 </action>
152 <action issue="LOG4J2-1343" dev="rpopma" type="update">
153 (GC) ConsoleAppender is now garbage-free by default. This logic is reusable for all AbstractOutputStreamAppender subclasses.
154 </action>
155 <action issue="LOG4J2-1278" dev="rpopma" type="add">
156 (GC) Added unrolled varargs methods to Logger API, added Unbox utility to avoid auto-boxing when logging primitive values.
157 </action>
158 <action issue="LOG4J2-1318" dev="rpopma" type="update">
159 (GC) Avoid allocating unnecessary temporary objects in LoggerContext's getLogger methods.
160 </action>
161 <action issue="LOG4J2-1333" dev="rpopma" type="update">
162 (GC) Avoid allocating unnecessary temporary objects in MarkerManager's getMarker methods.
163 </action>
164 <action issue="LOG4J2-1321" dev="rpopma" type="update">
165 (GC) Avoid allocating unnecessary temporary objects in PatternLayout's NamePatternConverter and ClassNamePatternConverter.
166 </action>
167 <action issue="LOG4J2-1271" dev="rpopma" type="add">
168 (GC) Add MessageFactory that avoid allocation by reusing a cached ParameterizedMessage instance.
169 </action>
170 <action issue="LOG4J2-1271" dev="rpopma" type="update">
171 (GC) ParameterizedMessage optimizations to avoid or at least postpone allocating temporary objects.
172 </action>
173 <action issue="LOG4J2-1283" dev="rpopma" type="update">
174 (GC) Provide ThreadLocal-based gc-free caching mechanism in DatePatternConverter for non-webapps.
175 </action>
176 <action issue="LOG4J2-1293" dev="rpopma" type="add">
177 (GC) Add interface StringBuilderFormattable to enable converting Messages and parameters to text without allocating temporary objects.
178 ParameterizedMessage, ObjectMessage, SimpleMessage and ThreadDumpMessage now implement StringBuilderFormattable.
179 </action>
180 <action issue="LOG4J2-1291" dev="rpopma" type="update">
181 (GC) Update PatternLayout to utilize gc-free mechanism for LogEvent processing.
182 </action>
183 <action issue="LOG4J2-1292" dev="rpopma" type="update">
184 (GC) Update RandomAccessFileAppender and RollingRandomAccessFileAppender to utilize gc-free Layout.encode() method.
185 </action>
186 <action issue="LOG4J2-1274" dev="rpopma" type="add">
187 (GC) Add encode(LogEvent, ByteBufferDestination) method to Layout API to enable converting LogEvents to bytes without creating temporary objects.
188 </action>
189 <action issue="LOG4J2-1281" dev="rpopma" type="fix">
190 (GC) LoggerConfig.getProperties() should not allocate on each call.
191 </action>
192 <action issue="LOG4J2-1272" dev="rpopma" type="update">
193 (GC) Improve LoggerConfig's data structure for AppenderControl objects to avoid allocating temporary objects during
194 traversal for each log event.
195 </action>
196 <action issue="LOG4J2-1269" dev="rpopma" type="fix">
197 (GC) AsyncLogger should use thread-local translator by default.
198 </action>
199 <action issue="LOG4J2-623" dev="rpopma" type="fix">
200 Generate MDC properties as a JSON map in JSONLayout, with option to output as list of map entries.
201 </action>
202 <action issue="LOG4J2-1362" dev="rpopma" type="add" due-to="Gary Gregory">
203 Added a YAML layout.
204 </action>
205 <action issue="LOG4J2-1387" dev="rpopma" type="fix">
206 Fixed memory leak related to shutdown hook.
207 </action>
208 <action issue="LOG4J2-1179" dev="rpopma" type="add">
209 Documented benchmark results comparing Log4j 2 performance to other logging libraries.
210 </action>
211 <action issue="LOG4J2-1382" dev="rpopma" type="fix">
212 Copying a MutableLogEvent using Log4jLogEvent.Builder should not unnecessarily obtain caller location information.
213 </action>
214 <action issue="LOG4J2-1011" dev="mikes" type="add">
215 Document dependencies for layouts.
216 </action>
217 <action issue="LOG4J2-621" dev="ggregory" type="add" due-to="Lee Theobald, Kamal Mettananda, Gary Gregory">
218 Pattern to drop first N package parts.
219 </action>
220 <action issue="LOG4J2-494" dev="rgoers" type="add" due-to="Philipp Knobel">
221 Support merging configurations to for a composite configuration.
222 </action>
223 <action issue="LOG4J2-1357" dev="mikes" type="add">
224 Option to not log stack traces for logged Throwables in GelfLayout.
225 </action>
226 <action issue="LOG4J2-1375" dev="rpopma" type="update">
227 Update SLF4J from 1.7.13 to 1.7.21.
228 </action>
229 <action issue="LOG4J2-1374" dev="rpopma" type="update">
230 Migrate tests from Logback 1.1.3 to 1.1.7.
231 </action>
232 <action issue="LOG4J2-1384" dev="ggregory" type="update">
233 Update Apache Commons CSV from 1.2 to 1.3.
234 </action>
235 <action issue="LOG4J2-1372" dev="rgoers" type="fix" due-to="Kamal Mettananda, Gary Gregory">
236 XMLLayout indents, but not the first child tag (Event).
237 </action>
238 <action issue="LOG4J2-1363" dev="rgoers" type="fix">
239 Properties Configuration did not support includeLocation attribute on Loggers.
240 </action>
241 <action issue="LOG4J2-1263" dev="rgoers" type="fix">
242 The ConfigurationSource was not saved for BuiltConfigurations so monitor interval had no effect.
243 </action>
244 <action issue="LOG4J2-1369" dev="ggregory" type="fix" due-to="Alex Birch, Gary Gregory">
245 "xz" compression results in plaintext, uncompressed files.
246 </action>
247 <action issue="LOG4J2-1365" dev="mikes" type="update">
248 (Log4j-internal) Provide message text as CharSequence for some message types to optimize some layouts.
249 </action>
250 <action issue="LOG4J2-1368" dev="rpopma" type="fix">
251 (Log4j-internal) StatusLogger dropped exceptions when logging parameterized messages.
252 </action>
253 <action issue="LOG4J2-1348" dev="ggregory" type="add" due-to="Greg Thomas, Gary Gregory">
254 Add an AutoCloseable ThreadContext class: CloseableThreadContext.
255 </action>
256 <action issue="LOG4J2-1345" dev="rpopma" type="update">
257 (Doc) Clarify documentation for properties that control Log4j behaviour.
258 </action>
259 <action issue="LOG4J2-1336" dev="ggregory" type="fix" due-to="Zbynek Vyskovsky">
260 LoggerFactory in 1.2 API module is not compatible with 1.2.
261 </action>
262 <action issue="LOG4J2-1354" dev="ggregory" type="fix" due-to="Arkadiusz Adolph">
263 No configuration reload is triggered under Windows when replacing the configuration file with one that has older last modified date.
264 </action>
265 <action issue="LOG4J2-1346" type="fix">
266 Exception from Log4jServletContextListener prevents jetty-maven-plugin run-forked.
267 </action>
268 <action issue="LOG4J2-1339" dev="rpopma" type="fix">
269 (Perf) AsyncLogger performance optimization: avoid calling instanceof TimestampMessage in hot path.
270 </action>
271 <action issue="LOG4J2-1324" dev="rpopma" type="fix">
272 Improve error handling in the Async Logger background thread: the new default exception handler no longer rethrows the error.
273 </action>
274 <action issue="LOG4J2-1309" dev="ggregory" type="fix">
275 Configuration file error does not show cause exception.
276 </action>
277 <action issue="LOG4J2-1299" dev="ggregory" type="add">
278 Add pattern converter for thread id and priority in PatternLayout.
279 </action>
280 <action issue="LOG4J2-1289" dev="ggregory" type="fix">
281 Change flow logging text from "entry' to "Enter" and "exit" to "Exit".
282 </action>
283 <action issue="LOG4J2-1284" dev="rpopma" type="fix">
284 Made default MessageFactory configurable.
285 </action>
286 <action issue="LOG4J2-1280" dev="ggregory" type="fix">
287 Deprecate org.apache.logging.log4j.util.MessageSupplier.
288 </action>
289 <action issue="LOG4J2-1280" dev="rpopma" type="fix">
290 Logger methods taking Supplier parameters now correctly handle cases where the supplied value is a Message.
291 </action>
292 <action issue="LOG4J2-1268" dev="rpopma" type="fix">
293 FixedDateFormat was incorrect for formats having MMM with the French locale.
294 </action>
295 <action issue="LOG4J2-1255" dev="rgoers" type="update">
296 Add enhanced entry and exit methods.
297 </action>
298 <action issue="LOG4J2-124" dev="rgoers" type="add">
299 Add shutdown methods to LogManager.
300 </action>
301 <action issue="LOG4J2-1222" dev="rgoers" type="fix">
302 Creation of a LoggerContext will fail if shutdown is in progress. LogManager will default to SimpleLogger instead.
303 </action>
304 <action issue="LOG4J2-1221" dev="rpopma" type="add" due-to="Michael Barker">
305 Added async logger Timeout wait strategy and made this the default wait strategy for async loggers.
306 This prevents a rare deadlock that may occur on Solaris.
307 </action>
308 <action issue="LOG4J2-1080" dev="rpopma" type="add">
309 Added option to discard events below a certain log level if the async logger ring buffer
310 or async appender queue is full.
311 </action>
312 <action issue="LOG4J2-1237" dev="ggregory" type="add" due-to="Mike Calmus, Gary Gregory">
313 Make PatternLayout header and footer accept a pattern.
314 </action>
315 <action issue="LOG4J2-1244" dev="ggregory" type="add" due-to="Anshu Garg, Remko Popma, Gary Gregory">
316 Make header and footer values customizable in JSONLayout.
317 </action>
318 <action issue="LOG4J2-1245" dev="ggregory" type="add">
319 Make CSV Layout header and footers accept patterns.
320 </action>
321 <action issue="LOG4J2-1192" dev="ggregory" type="add" due-to="Jörg Bretschneider, Gary Gregory">
322 Dynamic Subject for SMTP Appender.
323 </action>
324 <action issue="LOG4J2-1277" dev="ggregory" type="add" due-to="Gary Gregory, Ludovic Hochet">
325 FormattedMessage, MessageFormatMessage and StringFormattedMessage should support passing in a Locale to ensure appropriate formatting.
326 </action>
327 <action issue="LOG4J2-1260" dev="ggregory" type="fix" due-to="Blake Day, Gary Gregory">
328 TlsSyslogFrame calculates message length incorrectly.
329 </action>
330 <action issue="LOG4J2-1258" dev="ggregory" type="fix" due-to="Francis Lalonde">
331 Async DynamicThresholdFilter does not use the log event's context map.
332 </action>
333 <action issue="LOG4J2-1232" dev="ggregory" type="fix" due-to="Nikolai">
334 Incorrect log rotation in last week of year.
335 </action>
336 <action issue="LOG4J2-1248" dev="rpopma" type="fix">
337 Fixed broken nanotime in pattern layout.
338 </action>
339 <action issue="LOG4J2-908" dev="ggregory" type="fix" due-to="Konstantinos Liakos, Patrick Flaherty, Robin Coe, Gary Gregory">
340 JSONLayout doesn't add a comma between log events.
341 </action>
342 <action issue="LOG4J2-1230" dev="ggregory" type="fix" due-to="Vladimir Hudec, Ralph Goers, Gary Gregory">
343 Don't concatenate SYSLOG Messages.
344 </action>
345 <action issue="LOG4J2-1238" dev="ggregory" type="fix">
346 org.apache.logging.log4j.core.net.TcpSocketManager and other classes does not report internal exceptions to the status logger.
347 </action>
348 <action issue="LOG4J2-1212" dev="rpopma" type="fix">
349 Fix documentation to specify the correct default wait strategy used by async loggers.
350 </action>
351 <action issue="LOG4J2-1215" dev="ggregory" type="fix" due-to="Erik Kemperman">
352 Documentation/XSD inconsistencies.
353 </action>
354 <action issue="LOG4J2-1276" dev="ggregory" type="fix" due-to="Ludovic Hochet">
355 LoggerMessageSupplierTest and LoggerSupplierTest are Locale sensitive.
356 </action>
357 <action issue="LOG4J2-1380" dev="ggregory" type="update">
358 Update Jackson from 2.7.3 to 2.7.4.
359 </action>
360 <action issue="LOG4J2-1304" dev="ggregory" type="update">
361 Update Jackson from 2.7.0 to 2.7.2.
362 </action>
363 <action issue="LOG4J2-1253" dev="ggregory" type="update">
364 Update LMAX Disruptor from 3.3.2 to 3.3.4.
365 </action>
366 <action issue="LOG4J2-1219" dev="ggregory" type="update">
367 Update SLF4J from 1.7.12 to 1.7.13.
368 </action>
369 <action issue="LOG4J2-1239" dev="ggregory" type="update">
370 Update Jackson from 2.6.3 to 2.6.4.
371 </action>
372 <action issue="LOG4J2-1249" dev="ggregory" type="update">
373 Update Jackson from 2.6.4 to 2.7.0.
374 </action>
375 <action issue="LOG4J2-1351" dev="ggregory" type="update">
376 Update Jackson from 2.7.2 to 2.7.3.
377 </action>
378 <action issue="LOG4J2-1240" dev="ggregory" type="update">
379 Update Liquibase from 3.3.5 to 3.4.2.
380 </action>
381 <action issue="LOG4J2-1294" dev="ggregory" type="update">
382 Update Kafka client from 0.9.0.0 to 0.9.0.1.
383 </action>
384 <action issue="LOG4J2-1352" dev="ggregory" type="update">
385 Update javax.mail from 1.5.4 to 1.5.5.
386 </action>
387 <action issue="LOG4J2-1358" dev="ggregory" type="update">
388 Update Apache Commons Compress from 1.10 to 1.11.
389 </action>
390 <action issue="LOG4J2-1388" dev="rpopma" type="update">
391 Update Google java-allocation-instrumenter from 3.0 to 3.0.1.
392 </action>
393 <action issue="LOG4J2-1233" dev="ggregory" type="update" due-to="Bahri Gencsoy">
394 Misleading Value In Properties Example.
395 </action>
396 <action issue="LOG4J2-1251" dev="mattsicker" type="fix" due-to="Romain Manni-Bucau">
397 Fix JUL bridge issue where LogRecord.getParameters() is used when null.
398 </action>
399 <action issue="LOG4J2-1254" dev="rpopma" type="fix" due-to="Josh Trow">
400 Fix typo in Flow Tracing documentation.
401 </action>
402 <action issue="LOG4J2-920" dev="mattsicker" type="fix" due-to="Ludovic Hochet">
403 ClassNotFoundException for BundleContextSelector when initialising in an OSGi environment.
404 </action>
405 <action issue="LOG4J2-1300" dev="mattsicker" type="update">
406 Remove serializability from classes that don't need it.
407 </action>
408 <action issue="LOG4J2-1303" dev="mattsicker" type="add">
409 Add documentation links to runtime dependencies in each component intro page.
410 </action>
411 <action issue="LOG4J2-1275" dev="mattsicker" type="fix" due-to="Ludovic Hochet">
412 Fix RollingAppenderNoUnconditionalDeleteTest repeat test runs from failing.
413 </action>
414 <action issue="LOG4J2-1262" dev="mattsicker" type="fix">
415 Stop throwing unnecessary exception in Log4jServletContextListener.contextDestroyed().
416 </action>
417 <action issue="LOG4J2-1252" dev="mattsicker" type="add">
418 JeroMqAppender should support layouts.
419 </action>
420 <action issue="LOG4J2-1227" dev="mattsicker" type="fix" due-to="Olivier Lemasle">
421 NullPointerException in MapLookup.lookup if the event is null.
422 </action>
423 <action issue="LOG4J2-1306" dev="mattsicker" type="update">
424 JeroMqAppender should use ShutdownCallbackRegistry instead of runtime hooks.
425 </action>
426 <action issue="LOG4J2-1217" dev="mattsicker" type="add" due-to="Thies Wellpott">
427 PatternLayout option to limit length of text.
428 </action>
429 <action issue="LOG4J2-1308" dev="mattsicker" type="update">
430 Remove need to pre-specify appender et al. identifiers in property file config format.
431 </action>
432 <action issue="LOG4J2-1050" dev="mattsicker" type="fix" due-to="Adam Retter">
433 Add a Log4jLookup class to help write log files relative to log4j2.xml.
434 </action>
435 <action issue="LOG4J2-1133" dev="mattsicker" type="add">
436 Add JNDI lookup documentation.
437 </action>
438 <action issue="LOG4J2-1310" dev="mattsicker" type="fix">
439 JndiLookup mindlessly casts to String and should use String.valueOf().
440 </action>
441 <action issue="LOG4J2-1206" dev="mattsicker" type="update">
442 org.apache.logging.log4j.core.LoggerContext#updateLoggers should call firePropertyChangeEvent.
443 </action>
444 <action issue="LOG4J2-248" dev="mattsicker" type="fix">
445 Log4jWebInitializerImpl: Use Thread instead of Class for fallback classloader.
446 </action>
447 <action issue="LOG4J2-1169" dev="mattsicker" type="add" due-to="Gerald Kritzinger">
448 PatternLayout: Possible variable substitution in equals substitution parameter.
449 </action>
450 <action issue="LOG4J2-1322" dev="mattsicker" type="update">
451 Update Log4j 1.x migration guide to include information about system property lookup syntax changes.
452 </action>
453 <action issue="LOG4J2-1330" dev="mattsicker" type="fix">
454 Fix NoClassDefFoundError in ReflectionUtil on Google App Engine.
455 </action>
456 </release>
457 <release version="2.5" date="2015-12-06" description="GA Release 2.5">
458 <action issue="LOG4J2-324" dev="rpopma" type="fix">
459 Reduced memory usage of status messages in bounded queue; support zero-length queue that stores no messages.
460 </action>
461 <action issue="LOG4J2-1173" dev="rpopma" type="fix">
462 Fixed rollover error when copying to a directory mapped to a remote Linux host.
463 </action>
464 <action issue="LOG4J2-435" dev="rpopma" type="add" due-to="Robert Schaft">
465 Added support for custom delete actions triggered by a rollover.
466 </action>
467 <action issue="LOG4J2-649" dev="rgoers" type="update" due-to="Aleksey Zvolinsky">
468 Add PurgePolicy and IdlePurgePolicy to RoutingAppender.
469 </action>
470 <action issue="LOG4J2-1202" dev="rgoers" type="update">
471 Remove ConfigurationMonitor. The WatchManager is now used to check for configuration changes.
472 </action>
473 <action issue="LOG4J2-1195" dev="mikes" type="fix" due-to="Melvin Du">
474 Make KafkaAppender support SerializedLayout.
475 </action>
476 <action issue="LOG4J2-89" dev="rgoers" type="add">
477 Allow rollover to occur at any time. Add CronTriggeringPolicy.
478 </action>
479 <action issue="LOG4J2-381" dev="rgoers" type="fix" due-to="Anthony Baldocchi">
480 Allow triggering policy and rollover strategy to be modified during reconfiguration.
481 </action>
482 <action issue="LOG4J2-1136" dev="rgoers" type="add">
483 Add support for JSR 223 scripts in filters and the PatternSelector.
484 </action>
485 <action issue="LOG4J2-1168" dev="ggregory" type="add" due-to="Steven Swor">
486 Add getters for source and destination file in file rename action.
487 </action>
488 <action issue="LOG4J2-1175" dev="ggregory" type="add">
489 Add getters for classes in org.apache.logging.log4j.core.appender.rolling.action.
490 </action>
491 <action issue="LOG4J2-898" dev="rpopma" type="add">
492 Added system property to allow users to control whether messages should be formatted in the background.
493 </action>
494 <action issue="LOG4J2-1178" dev="ggregory" type="add">
495 Support use-case for JDBC's CommonDataSource.setLogWriter(PrintWriter) and java.sql.DriverManager.setLogWriter(PrintWriter).
496 </action>
497 <action issue="LOG4J2-1187" dev="ggregory" type="add">
498 Support use case for java.sql.DriverManager.setLogStream(PrintStream).
499 </action>
500 <action issue="LOG4J2-1029" dev="rpopma" type="fix" due-to="Stefan Leonhartsberger">
501 Performance improvement when gathering location information.
502 </action>
503 <action issue="LOG4J2-1172" dev="rpopma" type="fix">
504 Fixed ThreadLocal leak [AsyncLogger$Info] on Tomcat when using AsyncLoggerContextSelector.
505 </action>
506 <action issue="LOG4J2-1176" dev="rpopma" type="fix">
507 Fixed memory leak when log4j jars are in Tomcat's lib folder.
508 </action>
509 <action issue="LOG4J2-1180" dev="ggregory" type="fix" due-to="Mikael Ståldal">
510 Logger cache does not account for message factory.
511 </action>
512 <action issue="LOG4J2-879" dev="rpopma" type="fix">
513 Documentation: fixed minor issues with the site and manual pages.
514 </action>
515 <action issue="LOG4J2-999" dev="rpopma" type="fix" due-to="Joan Balagueró">
516 RollingFileAppender should also roll over when log event time is equal to rollover time, not only when later.
517 </action>
518 <action issue="LOG4J2-873" dev="rpopma" type="fix" due-to="Martin Dickins, LC, Luke Woodward">
519 Fixed bug where omitting the &lt;display-name&gt; element in web.xml caused incorrect log4j initialization,
520 resulting in memory leaks when the web application was stopped or reloaded.
521 </action>
522 <action issue="LOG4J2-323" dev="rpopma" type="fix">
523 Better web app support for async loggers: Fixed a memory leak that occurred when the logging jars are placed
524 in the container's classpath and the configuration file uses AsyncRoot/AsyncLogger.
525 The problem was that the first web application started the Disruptor background thread [AsyncLoggerConfig-1] but did not stop it until all web apps are stopped.
526 Each web application now has its own Disruptor which is stopped/started together with the web app.
527 </action>
528 <action issue="LOG4J2-493" dev="rpopma" type="fix">
529 Better web app support for async loggers: it is now possible to place the logging jars in the container's
530 classpath when making all loggers asynchronous by using AsyncLoggerContextSelector. This fixes a problem where
531 logging would stop working after stopping and restarting a web application.
532 </action>
533 <action issue="LOG4J2-1171" dev="rpopma" type="fix">
534 Use servlet context name for logger context name when available.
535 </action>
536 <action issue="LOG4J2-1159" dev="rpopma" type="fix">
537 Fixed a ThreadLocal memory leak in Tomcat8 that mentions AsyncLoggers when Async Loggers are not used.
538 </action>
539 <action issue="LOG4J2-1166" dev="rpopma" type="fix">
540 AbstractConfiguration executor should use a DaemonThreadFactory.
541 </action>
542 <action issue="LOG4J2-1165" dev="rpopma" type="fix">
543 Improve Log4j initialization status messages.
544 </action>
545 <action issue="LOG4J2-1156" dev="rpopma" type="fix">
546 Web site corrections and updates.
547 </action>
548 <action issue="LOG4J2-1158" dev="ggregory" type="fix" due-to="Michael Fortin, Gary Gregory">
549 Log4J JUL adapter is using MessageFormat on String passed by java.util.function.Supplier&lt;String>.
550 </action>
551 <action issue="LOG4J2-801" dev="mattsicker" type="fix">
552 org.apache.logging.log4j.core.Logger should be serializable.
553 </action>
554 <action issue="LOG4J2-1157" dev="mattsicker" type="fix" due-to="Norbert Bartels">
555 Fix compilation error for classes annotated with @Plugin.
556 </action>
557 <action issue="LOG4J2-948" dev="mattsicker" type="fix" due-to="Andrew Flower">
558 Fix plugin documentation error about Converters.
559 </action>
560 <action issue="LOG4J2-1193" dev="ggregory" type="fix">
561 Prefix all thread names Log4j creates with "Log4j2-".
562 </action>
563 <action issue="LOG4J2-1194" dev="ggregory" type="fix" due-to="Adam Brin">
564 Documentation does not match parameters for LoggerNameLevelRewritePolicy.
565 </action>
566 <action issue="LOG4J2-1196" dev="mattsicker" type="fix" due-to="René Zanner">
567 MongoDbConnection does not close MongoClient.
568 </action>
569 <action issue="LOG4J2-1174" dev="ggregory" type="update">
570 Update Jackson from 2.6.2 to 2.6.3.
571 </action>
572 <action issue="LOG4J2-1207" dev="ggregory" type="update">
573 Update kafka-clients from 0.8.2.2 to 0.9.0.0.
574 </action>
575 </release>
576 <release version="2.4.1" date="2015-10-08" description="GA Release 2.4.1">
577 <action issue="LOG4J2-1129" dev="rgoers" type="add">
578 Allow PatternLayout to select a pattern to use based on some selection criteria.
579 </action>
580 <action issue="LOG4J2-1145" dev="ggregory" type="add">
581 Add %equals to PatternLayout to test and replace patterns with strings.
582 </action>
583 <action issue="LOG4J2-1147" dev="ggregory" type="add">
584 Add %equalsIgnoreCase to PatternLayout to test and replace patterns with strings.
585 </action>
586 <action issue="LOG4J2-1146" dev="ggregory" type="add">
587 Add %notEmpty to PatternLayout to avoid output of patterns where all variables are empty.
588 </action>
589 <action issue="LOG4J2-1020" dev="mikes" type="add">
590 Add possibility to set shutdown timeout on AsyncAppender.
591 </action>
592 <action issue="LOG4J2-1153" dev="rpopma" type="fix">
593 Fixed NullPointerException when only root logger is defined (and no named loggers) in configuration properties file.
594 </action>
595 <action issue="LOG4J2-1140" dev="rpopma" type="fix">
596 Fixed bug where headers were not being written to first file with RollingFileAppender.
597 </action>
598 <action issue="LOG4J2-1149" dev="rpopma" type="fix">
599 Fixed bug where PatternLayout predefined date pattern with time zone always renders default date format.
600 </action>
601 <action issue="LOG4J2-1050" dev="rpopma" type="fix">
602 Fixed Log4jLookup.
603 </action>
604 <action issue="LOG4J2-1142" dev="rpopma" type="fix">
605 Fix potential memory leak in web applications by using a straight ThreadLocal field instead of subclassing ThreadLocal.
606 </action>
607 <action issue="LOG4J2-1135" dev="rpopma" type="fix">
608 Compression on rollover was broken: log file was renamed to .zip but not compressed.
609 </action>
610 <action issue="LOG4J2-1127" dev="ggregory" type="fix">
611 log4j2.xml cannot be parsed on Oracle Weblogic 12c.
612 </action>
613 <action issue="LOG4J2-1132" dev="ggregory" type="fix">
614 Do not use MongoDB driver 2.13.3 deprecated methods.
615 </action>
616 <action issue="LOG4J2-1144" dev="ggregory" type="fix">
617 Add %markerSimpleName in pattern layout should evaluate to marker name (not toString()).
618 </action>
619 <action issue="LOG4J2-1126" dev="ggregory" type="fix">
620 Web site corrections and updates.
621 </action>
622 <action issue="LOG4J2-1151" dev="rpopma" type="update">
623 Performance improvement: backport Java 8 fast ISO-8859-1 String to byte[] encoder to AbstractStringLayout.
624 </action>
625 <action issue="LOG4J2-935" dev="rpopma" type="update">
626 Performance improvement when converting Strings to byte[] arrays.
627 </action>
628 <action issue="LOG4J2-1040" dev="ggregory" type="update">
629 Update MongoDB driver from 2.13.3 to 3.0.4.
630 </action>
631 <action issue="LOG4J2-1128" dev="ggregory" type="update">
632 Reuse StringBuilder to improve performance for String-based layouts: CSV, GELF, HTML, RFC524, Syslog.
633 </action>
634 <action issue="LOG4J2-1131" dev="ggregory" type="update">
635 Update mongo-java-driver from 2.13.2 to 2.13.3.
636 </action>
637 <action issue="LOG4J2-1138" dev="ggregory" type="update">
638 Do not use Jackson deprecated methods.
639 </action>
640 <action issue="LOG4J2-1139" dev="ggregory" type="update">
641 Update Jackson from 2.6.1 to 2.6.2.
642 </action>
643 <action issue="LOG4J2-1150" dev="ggregory" type="update">
644 Update kafka-clients from 0.8.2.1 to 0.8.2.2.
645 </action>
646 </release>
647 <release version="2.4" date="2015-09-20" description="GA Release 2.4">
648 <action issue="LOG4J2-635" dev="rgoers" type="add">
649 Add support for configuration via Properties.
650 </action>
651 <action issue="LOG4J2-952" dev="rgoers" type="add">
652 Add ConfigurationBuilder for programmatic configuration.
653 </action>
654 <action issue="LOG4J2-1017" dev="ggregory" type="update">
655 Update Java platform from Java 6 to 7. From this version onwards, log4j 2 requires Java 7.
656 </action>
657 <action issue="LOG4J2-599" dev="rpopma" type="add">
658 Added support for Java 8 lambda expressions to lazily construct a log message only if
659 the requested log level is enabled.
660 </action>
661 <action issue="LOG4J2-1118" dev="rpopma" type="add">
662 Updated Logger wrapper generator tool to add Java 8 lambda support for custom log levels.
663 </action>
664 <action issue="LOG4J2-1107" dev="ggregory" type="add" due-to="Mikael Ståldal">
665 New Appender for Apache Kafka.
666 </action>
667 <action issue="LOG4J2-1113" dev="ggregory" type="add" due-to="Gary Gregory">
668 New publisher Appender for ZeroMQ (using JeroMQ).
669 </action>
670 <action issue="LOG4J2-1088" dev="ggregory" type="add" due-to="Gary Gregory">
671 Add Comma Separated Value (CSV) layouts for parameter and event logging.
672 </action>
673 <action issue="LOG4J2-812" dev="rgoers" type="update">
674 PatternLayout timestamp formatting performance improvement: replaced synchronized SimpleDateFormat with
675 Apache Commons FastDateFormat. This and better caching resulted in a ~3-30X faster timestamp formatting.
676 </action>
677 <action issue="LOG4J2-1097" dev="rpopma" type="update">
678 PatternLayout timestamp formatting performance improvement: predefined date formats (and variants using
679 a period '.' millisecond separator instead of ',') are now formatted ~2-10X faster than other date formats.
680 </action>
681 <action issue="LOG4J2-1096" dev="rpopma" type="update">
682 Improved performance of ParameterizedMessage::getFormattedMessage by ~2X.
683 </action>
684 <action issue="LOG4J2-1120" dev="rpopma" type="update">
685 LoggerConfig performance improvements: avoid unnecessary lock acquisition, use more efficient data structure.
686 </action>
687 <action issue="LOG4J2-1125" dev="rpopma" type="update">
688 PatternLayout performance improvement by caching and reusing a ThreadLocal StringBuilder.
689 </action>
690 <action issue="LOG4J2-1121" dev="rpopma" type="fix">
691 Fixed potential race condition on reconfiguration. Introduced ReliabilityStrategy to facilitate
692 switching between different mechanisms for preventing log events from being dropped on reconfiguration.
693 </action>
694 <action issue="LOG4J2-1114" dev="ggregory" type="update">
695 Add thread name to status logger layout.
696 </action>
697 <action issue="LOG4J2-1123" dev="ggregory" type="fix" due-to="Gary Gregory">
698 Core Configurator.initialize(String, ClassLoader, String) fails to work when config location is a file path.
699 </action>
700 <action issue="LOG4J2-1117" dev="ggregory" type="fix" due-to="Marcus Thiesen">
701 OutputStreamManager in ConsoleAppender leaking managers.
702 </action>
703 <action issue="LOG4J2-1044" dev="rgoers" type="fix">
704 Write pending events to Flume when the appender is stopped.
705 </action>
706 <action issue="LOG4J2-1108" dev="ggregory" type="fix" due-to="Mikael Ståldal">
707 NullPointerException when passing null to java.util.logging.Logger.setLevel().
708 </action>
709 <action issue="LOG4J2-1110" dev="ggregory" type="fix">
710 org.apache.logging.log4j.jul.CoreLogger.setLevel() checks for security permission too late.
711 </action>
712 <action dev="rpopma" type="remove">
713 Removed experimental interface LevelLogger which got committed to master by mistake.
714 </action>
715 <action issue="LOG4J2-1010" dev="rgoers" type="update">
716 Pass log event when interpolating logger properties.
717 </action>
718 <action issue="LOG4J2-1090" dev="ggregory" type="add">
719 Add Core Configurator APIs to change a logger's level.
720 </action>
721 <action issue="LOG4J2-1105" dev="ggregory" type="add" due-to="Gary Gregory">
722 Add API org.apache.logging.log4j.Level.isInRange(Level, Level).
723 </action>
724 <action issue="LOG4J2-1106" dev="ggregory" type="add" due-to="Gary Gregory">
725 Add a LevelRangeFilter class.
726 </action>
727 <action issue="LOG4J2-1074" dev="rpopma" type="add">
728 Added support for system nanosecond time in pattern layout.
729 </action>
730 <action issue="LOG4J2-1075" dev="rpopma" type="add">
731 Added support for compressing to bzip2 format on file rollover.
732 </action>
733 <action issue="LOG4J2-1077" dev="ggregory" type="add">
734 Support additional Apache Commons Compress compression formats on rollover: Deflate, Pack200, XY.
735 </action>
736 <action issue="LOG4J2-767" dev="ggregory" type="add" due-to="Mikael Ståldal">
737 New module for Liquibase integration.
738 </action>
739 <action issue="LOG4J2-1023" dev="ggregory" type="add" due-to="Mikael Ståldal">
740 New RewritePolicy for changing level of a log event.
741 </action>
742 <action issue="LOG4J2-1015" dev="ggregory" type="add" due-to="Daniel Marcotte">
743 Add a way to route messages based on the %marker in Layout for RoutingAppender.
744 </action>
745 <action issue="LOG4J2-1050" dev="ggregory" type="add" due-to="Adam Retter">
746 Add a Log4jLookup class to help write log files relative to log4j2.xml.
747 </action>
748 <action issue="LOG4J2-1057" dev="ggregory" type="add">
749 Add API org.apache.logging.log4j.LogManager.getFormatterLogger().
750 </action>
751 <action issue="LOG4J2-1066" dev="ggregory" type="add" due-to="Charles Allen">
752 Expose Log4jContextFactory's ShutdownCallbackRegistry.
753 </action>
754 <action issue="LOG4J2-1084" dev="ggregory" type="fix" due-to="Philipp Schneider">
755 Misleading StatusLogger WARN event in LogManager with java.util.Map.
756 </action>
757 <action issue="LOG4J2-1051" dev="ggregory" type="fix" due-to="Lukasz Lenart">
758 NoClassDefFoundError when starting app on Google App Engine.
759 </action>
760 <action issue="LOG4J2-684" dev="ggregory" type="fix" due-to="Joern Huxhorn, Mauro Molinari">
761 ExtendedThrowablePatternConverter does not print suppressed exceptions.
762 </action>
763 <action issue="LOG4J2-1069" dev="ggregory" type="fix" due-to="Sam Braam">
764 Improper handling of JSON escape chars when deserializing JSON log events.
765 </action>
766 <action issue="LOG4J2-1068" dev="ggregory" type="fix" due-to="Andy McMullan">
767 Exceptions not logged when using TcpSocketServer + SerializedLayout.
768 </action>
769 <action issue="LOG4J2-1067" dev="ggregory" type="fix" due-to="Sam Braam">
770 ThrowableProxy getExtendedStackTraceAsString throws NPE on deserialized nested exceptions.
771 </action>
772 <action issue="LOG4J2-1049" dev="rpopma" type="fix" due-to="Robert Schaft">
773 AsyncAppender now resets the thread interrupted flag after catching InterruptedException.
774 </action>
775 <action issue="LOG4J2-1048" dev="rpopma" type="fix" due-to="Nikhil">
776 FileConfigurationMonitor unnecessarily calls System.currentTimeMillis() causing high CPU usage.
777 </action>
778 <action issue="LOG4J2-1037" dev="ggregory" type="fix" due-to="Marc Dergacz">
779 Backward compatibility issue in log4j-1.2-api NDC pop() and peek().
780 </action>
781 <action issue="LOG4J2-1025" dev="ggregory" type="fix" due-to="Mikael Ståldal">
782 Custom java.util.logging.Level gives null Log4j Level and causes NPE.
783 </action>
784 <action issue="LOG4J2-1033" dev="ggregory" type="fix" due-to="Mikael Ståldal">
785 SimpleLogger creates unnecessary Map objects by calling ThreadContext.getContext() instead of getImmutableContext().
786 </action>
787 <action issue="LOG4J2-1026" dev="ggregory" type="fix">
788 HighlightConverter does not obey noConsoleNoAnsi.
789 </action>
790 <action issue="LOG4J2-1019" dev="ggregory" type="fix">
791 ZipCompressAction leaves files open until GC when an IO error takes place.
792 </action>
793 <action issue="LOG4J2-1020" dev="ggregory" type="fix">
794 GzCompressAction leaves files open until GC when an IO error takes place.
795 </action>
796 <action issue="LOG4J2-1038" dev="ggregory" type="fix" due-to="Gili">
797 Incorrect documentation for layout default charset.
798 </action>
799 <action issue="LOG4J2-1042" dev="ggregory" type="fix" due-to="Guillaume Turri">
800 Socket and Syslog appenders don't take timeout into account at startup.
801 </action>
802 <action issue="LOG4J2-934" dev="ggregory" type="fix" due-to="Kenneth Gendron">
803 Circular suppressed Exception throws StackOverflowError.
804 </action>
805 <action issue="LOG4J2-1046" dev="ggregory" type="fix" due-to="Kenneth Gendron">
806 Circular Exception cause throws StackOverflowError.
807 </action>
808 <action issue="LOG4J2-982" dev="ggregory" type="fix" due-to="Mikhail Mazurskiy">
809 Use System.nanoTime() to measure time intervals.
810 </action>
811 <action issue="LOG4J2-1045" dev="ggregory" type="fix" due-to="Günter Albrecht">
812 Externalize log4j2.xml via URL resource.
813 </action>
814 <action issue="LOG4J2-1058" dev="ggregory" type="fix" due-to="Daniel Branzea">
815 Log4jMarker#contains(String) does not respect org.slf4j.Marker contract.
816 </action>
817 <action issue="LOG4J2-1060" dev="ggregory" type="fix">
818 Log4jMarker#contains(Marker) does not respect org.slf4j.Marker contract.
819 </action>
820 <action issue="LOG4J2-1061" dev="ggregory" type="fix">
821 Log4jMarker#remove(Marker) does not respect org.slf4j.Marker contract.
822 </action>
823 <action issue="LOG4J2-1062" dev="ggregory" type="fix">
824 Log4jMarker#add(Marker) does not respect org.slf4j.Marker contract.
825 </action>
826 <action issue="LOG4J2-1064" dev="ggregory" type="fix">
827 org.apache.logging.slf4j.Log4jMarker does not implement org.slf4j.Marker.equals(Object) org.slf4j.Marker.hashCode().
828 </action>
829 <action issue="LOG4J2-889" dev="rpopma" type="fix" due-to="Maciej Karaś, Kenneth Leider">
830 Header in layout should not be written on application startup if appending to an existing file. Fixes LOG4J2-1030.
831 </action>
832 <action issue="LOG4J2-918" dev="rpopma" type="fix">
833 Clarify documentation for combining async with sync loggers.
834 </action>
835 <action issue="LOG4J2-1078" dev="ggregory" type="fix" due-to="Mikael Ståldal">
836 GelfLayout throws exception if some log event fields are null.
837 </action>
838 <action issue="LOG4J2-1044" dev="rgoers" type="update">
839 Support batchSize in FlumeAvroManager.
840 </action>
841 <action issue="LOG4J2-1065" dev="ggregory" type="update">
842 Define org.apache.logging.log4j.Marker.equals(Object) and org.apache.logging.log4j.Marker.hashCode().
843 </action>
844 <action issue="LOG4J2-1063" dev="ggregory" type="update">
845 Avoid creating temporary array object in org.apache.logging.slf4j.Log4jMarker.iterator().
846 </action>
847 <action issue="LOG4J2-890" dev="ggregory" type="update" due-to="Hassan Kalaldeh, Robert Andersson, Remko Popma">
848 log4j-web-2.1 should workaround a bug in JBOSS EAP 6.2.
849 </action>
850 <action issue="LOG4J2-403" dev="ggregory" type="update" due-to="Poorna Subhash P, Jeremy Lautman">
851 MongoDB appender, username and password should be optional.
852 </action>
853 <action issue="LOG4J2-1035" dev="ggregory" type="update">
854 Log4j2 tries to SystemClassLoader when running on Google AppEngine.
855 </action>
856 <action issue="LOG4J2-1022" dev="rgoers" type="update">
857 Allow a list of keys to be specified in the MDC pattern converter.
858 </action>
859 <action issue="LOG4J2-959" dev="ggregory" type="update">
860 Fix FindBugs DM_DEFAULT_ENCODING bug in SimpleLogger.logMessage() and simplify code.
861 </action>
862 <action issue="LOG4J2-1036" dev="ggregory" type="update">
863 Update Apache Flume from 1.5.2 to 1.6.0.
864 </action>
865 <action issue="LOG4J2-1041" dev="ggregory" type="update">
866 Update MongoDB driver from 2.11.2 to 2.13.2.
867 </action>
868 <action issue="LOG4J2-1018" dev="ggregory" type="update">
869 Update database tests from H2 1.3.175 to 1.3.176.
870 </action>
871 <action issue="LOG4J2-1070" dev="ggregory" type="update">
872 Update Java Mail from 1.5.2 to 1.5.4.
873 </action>
874 <action issue="LOG4J2-1079" dev="ggregory" type="update">
875 Update Jackson from 2.5.3 to 2.5.4.
876 </action>
877 <action issue="LOG4J2-1879" dev="ggregory" type="update">
878 Update Jackson from 2.5.4 to 2.6.0.
879 </action>
880 <action issue="LOG4J2-1092" dev="ggregory" type="update">
881 Update Jackson from 2.6.0 to 2.6.1.
882 </action>
883 <action issue="LOG4J2-1104" dev="ggregory" type="update">
884 Update Apache Commons Compress from 1.9 to 1.10.
885 </action>
886 </release>
887 <release version="2.3" date="2015-05-09" description="GA Release 2.3">
888 <action issue="LOG4J2-1009" dev="ggregory" type="fix" due-to="Mikael Ståldal">
889 Incorrectly defined compressionType parameter to GelfLayout.
890 </action>
891 <action issue="LOG4J2-1008" dev="ggregory" type="fix" due-to="Ralph Goers, Gary Gregory">
892 org.apache.logging.log4j.core.config.plugins.util.ResolverUtil.extractPath(URL) incorrectly converts '+' characters to spaces.
893 </action>
894 <action issue="LOG4J2-1007" dev="ggregory" type="fix" due-to="Ralph Goers, Gary Gregory">
895 org.apache.logging.log4j.core.util#fileFromUri(URI uri) incorrectly converts '+' characters to spaces.
896 </action>
897 <action issue="LOG4J2-1003" dev="ggregory" type="fix" due-to="Dan Armbrust">
898 JUL Logger.throwing is mis-mapped to ERROR when it should be TRACE.
899 </action>
900 <action issue="LOG4J2-965" dev="ggregory" type="fix" due-to="Khotyn Huang">
901 System.out no longer works after the Console appender and JANSI are initialized.
902 </action>
903 <action issue="LOG4J2-998" dev="ggregory" type="update" due-to="Mariano Gonzalez">
904 Make org.apache.logging.log4j.core.Logger#updateConfiguration protected.
905 </action>
906 <action issue="LOG4J2-995" dev="rgoers" type="update">
907 Move UTF-8 constant from Charsets to Constants class. Remove Charsets class.
908 </action>
909 <action issue="LOG4J2-993" dev="rgoers" type="fix">
910 Deadlock would occur if appender thread creates a new Logger during reconfiguration.
911 </action>
912 <action issue="LOG4J2-991" dev="rpopma" type="fix" due-to="Ryan Rupp">
913 Async root logger config should default includeLocation to false.
914 </action>
915 <action issue="LOG4J2-985" dev="rpopma" type="fix" due-to="Sean Dawson">
916 AbstractFilter should not implement equals() and hashCode().
917 </action>
918 <action issue="LOG4J2-984" dev="ggregory" type="add" due-to="Jonas Höpfner">
919 PatternLayout %highlight to support noConsoleNoAnsi like %style.
920 </action>
921 <action issue="LOG4J2-926" dev="ggregory" type="add" due-to="David Ohana">
922 Truncate from the end of text format modifier.
923 </action>
924 <action issue="LOG4J2-980" dev="ggregory" type="fix" due-to="Mikhail Mazurskiy">
925 Numerical overflow in BurstFilter not handled correctly.
926 </action>
927 <action issue="LOG4J2-981" dev="ggregory" type="fix" due-to="Mikhail Mazurskiy">
928 Incorrect unlock in ProviderUtil.
929 </action>
930 <action issue="LOG4J2-966" dev="ggregory" type="fix" due-to="Gary Gregory">
931 KeyStoreConfiguration.createKeyStoreConfiguration() ignores keyManagerFactoryAlgorithm.
932 </action>
933 <action issue="LOG4J2-976" dev="ggregory" type="fix" due-to="Matt Quinn">
934 Using monitorInterval with YAML config file format causes JSONParseException.
935 </action>
936 <action issue="LOG4J2-964" dev="ggregory" type="fix" due-to="Jonne Jyrylä">
937 StringFormattedMessage serialization is incorrect.
938 </action>
939 <action issue="LOG4J2-947" dev="ggregory" type="fix" due-to="Stefan Wehner">
940 A new StatusLoggerAdmin listener is added to StatusLogger every time the log is reconfigured.
941 </action>
942 <action issue="LOG4J2-968" dev="ggregory" type="fix" due-to="Paul D Johe">
943 SyslogLayout contains extra space.
944 </action>
945 <action issue="LOG4J2-967" dev="ggregory" type="fix" due-to="Stefan Wehner">
946 log4j2.component.properties not read for all properties.
947 </action>
948 <action issue="LOG4J2-971" dev="ggregory" type="fix" due-to="Paul D Johe">
949 Another bad priority in Syslog messages.
950 </action>
951 <action issue="LOG4J2-972" dev="ggregory" type="fix" due-to="Gary Gregory">
952 org.apache.logging.log4j.core.net.ssl.TlsSyslogInputStreamReader does not need to create temp Integer objects.
953 </action>
954 <action issue="LOG4J2-974" dev="ggregory" type="fix" due-to="Daniel Galán y Martins">
955 Typo in EventLogger documentation.
956 </action>
957 <action issue="LOG4J2-988" dev="ggregory" type="update" due-to="Gary Gregory">
958 Update LMAX Disruptor from 3.3.0 to 3.3.2.
959 </action>
960 <action issue="LOG4J2-987" dev="ggregory" type="update" due-to="Gary Gregory">
961 Migrate tests from Logback 1.1.2 to 1.1.3.
962 </action>
963 <action issue="LOG4J2-988" dev="ggregory" type="update" due-to="Gary Gregory">
964 Update tests to use ActiveMQ from 5.10 to 5.11.1.
965 </action>
966 <action issue="LOG4J2-1004" dev="ggregory" type="update">
967 Update Jackson from 2.5.1 to 2.5.3.
968 </action>
969 <action issue="LOG4J2-1005" dev="ggregory" type="update">
970 Update Slf4j from 1.7.7 to 1.7.12.
971 </action>
972 </release>
973 <release version="2.2" date="2015-02-22" description="GA Release 2.2">
974 <action issue="LOG4J2-938" dev="rpopma" type="fix" due-to="Mauro Molinari">
975 (JMX) To avoid memory leaks when web applications are restarted, JMX notifications are sent from
976 the caller thread in web applications. For non-web applications notifications are sent from a background thread
977 as before.
978 </action>
979 <action issue="LOG4J2-957" dev="ggregory" type="fix" due-to="fatih guleryuz">
980 Missing toUpperCase(Locale.ENGLISH).
981 </action>
982 <action issue="LOG4J2-956" dev="ggregory" type="fix" due-to="David Kellerman">
983 Manual refers to Route "AppenderRef" attribute, should be "ref".
984 </action>
985 <action issue="LOG4J2-955" dev="rpopma" type="update">
986 Documentation: clarify system properties to control status logger, improve troubleshooting FAQ entry.
987 </action>
988 <action issue="LOG4J2-950" dev="ggregory" type="update" due-to="Joel Edwards">
989 Incorrect attribute name in PropertiesRewritePolicy example.
990 </action>
991 <action issue="LOG4J2-944" dev="ggregory" type="fix" due-to="Vinayaka Ramachandra">
992 Log4j Flume appender is not adding millisecond to the event headers when the event is logged at 000 milliseconds.
993 </action>
994 <action issue="LOG4J2-941" dev="ggregory" type="add" due-to="Konstantinos Liakos">
995 Allow JSON layout to create one compact log record per line.
996 </action>
997 <action issue="LOG4J2-933" dev="ggregory" type="add" due-to="ppiman at gmail.com">
998 HTML layout should not use attribute minimalization for hr noshade.
999 </action>
1000 <action issue="LOG4J2-895" dev="ggregory" type="add">
1001 Specify the SyslogAppender connect timeout value as part of the configuration.
1002 The SyslogAppender takes a new parameter connectTimeoutMillis.
1003 </action>
1004 <action issue="LOG4J2-899" dev="ggregory" type="add">
1005 Specify the SocketAppender connect timeout value as part of the configuration.
1006 The SyslogAppender takes a new parameter connectTimeoutMillis.
1007 </action>
1008 <action issue="LOG4J2-924" dev="ggregory" type="fix" due-to="Ryan Rupp">
1009 Log4j 1.2 Bridge doesn't map level ALL correctly in Category.getEffectiveLevel().
1010 </action>
1011 <action issue="LOG4J2-931" dev="ggregory" type="fix" due-to="Robert Gacki">
1012 ConsoleAppender is missing @PluginFactory annotation at createAppender method.
1013 </action>
1014 <action issue="LOG4J2-919" dev="ggregory" type="fix" due-to="David Johle">
1015 Logging system fails to initialize if XInclude API is not available.
1016 </action>
1017 <action issue="LOG4J2-914" dev="ggregory" type="fix" due-to="Kaj Bjurman">
1018 ThrowableProxy.getExtendedStackTraceAsString causes NullPointerException.
1019 </action>
1020 <action issue="LOG4J2-912" dev="ggregory" type="fix">
1021 XML configuration does not report full error message for XInclude parser configuration problems.
1022 </action>
1023 <action issue="LOG4J2-903" dev="ggregory" type="fix" due-to="Mauro Molinari">
1024 ClassLoaderContextSelector uses ClassLoader.toString() as a key
1025 </action>
1026 <action issue="LOG4J2-834" dev="ggregory" type="fix" due-to="Nikita Koval, Leonard Broman, Thiago Kronig">
1027 ThrowableProxy throws NoClassDefFoundError.
1028 </action>
1029 <action issue="LOG4J2-893" dev="ggregory" type="fix">
1030 NullPointerException on filter when mapping JUL to Log4j2.
1031 </action>
1032 <action issue="LOG4J2-892" dev="ggregory" type="fix">
1033 JUL adapter does not map Log4j'2 FATAL level to a JUL level.
1034 </action>
1035 <action issue="LOG4J2-881" dev="ggregory" type="fix" due-to="Mariano Gonzalez">
1036 AbstractLifecycle should not implement equals() and hashCode().
1037 </action>
1038 <action issue="LOG4J2-897" dev="ggregory" type="fix">
1039 Javadoc for org.apache.log4j.BasicConfigurator.configure() is incorrect.
1040 </action>
1041 <action issue="LOG4J2-891" dev="ggregory" type="fix">
1042 AbstractLifecycle should not implement equals() and hashCode().
1043 </action>
1044 <action issue="LOG4J2-946" dev="ggregory" type="fix" due-to="artemonster">
1045 [docs] Using Log4j 2 in Web Applications: Update example (Log4jWebLifeCycle is not visible).
1046 </action>
1047 <action issue="LOG4J2-901" dev="ggregory" type="update" due-to="Tihomir Meščić, Siegfried Greisinger">
1048 Update docs for SyslogAppender: "No structured id name was supplied"
1049 </action>
1050 <action issue="LOG4J2-958" dev="ggregory" type="update">
1051 Update from Jackson 2.5.0 to 2.5.1.
1052 </action>
1053 <action issue="LOG4J2-925" dev="ggregory" type="update">
1054 Update from Jackson 2.4.4 to 2.5.0.
1055 </action>
1056 <action issue="LOG4J2-910" dev="ggregory" type="update">
1057 Update Jackson from 2.4.3 to 2.4.4.
1058 </action>
1059 <action issue="LOG4J2-881" dev="ggregory" type="update">
1060 Update Jackson from 2.4.2 to 2.4.3.
1061 </action>
1062 <action issue="LOG4J2-882" dev="ggregory" type="update">
1063 Update maven-core from 3.1.0 to 3.2.3.
1064 </action>
1065 <action issue="LOG4J2-883" dev="ggregory" type="update">
1066 Update tests from org.apache.felix.framework 4.2.1 to 4.4.1.
1067 </action>
1068 <action issue="LOG4J2-884" dev="ggregory" type="update">
1069 Update org.eclipse.osgi from 3.6.0 to 3.7.1.
1070 </action>
1071 <action issue="LOG4J2-900" dev="ggregory" type="update">
1072 Update Apache Flume from 1.5.0.1 to 1.5.2.
1073 </action>
1074 </release>
1075 <release version="2.1" date="2014-10-19" description="GA Release 2.1">
1076 <action issue="LOG4J2-676" dev="rgoers" type="fix" due-to="Stefan Bodewig">
1077 Some typo fixes and enhancements for the site.
1078 </action>
1079 <action issue="LOG4J2-868" dev="mattsicker" type="add">
1080 Add ShutdownCallbackRegistry interface for customizable shutdown callback handling. This is particularly
1081 useful for application servers that wish to integrate with Log4j 2.
1082 </action>
1083 <action issue="LOG4J2-866" dev="rpopma" type="fix" due-to="Gerard Weatherby">
1084 Documentation: fixed missing closing parenthesis in code example.
1085 </action>
1086 <action issue="LOG4J2-862" dev="mattsicker" type="fix" due-to="Michael Sutherland">
1087 Fixed classloader issue that prevented Log4j from finding the implementation when used in a custom Ant task.
1088 </action>
1089 <action issue="LOG4J2-589" dev="rpopma" type="add">
1090 Supported filtering on custom log levels in configuration.
1091 </action>
1092 <action issue="LOG4J2-861" dev="rpopma" type="fix">
1093 Documentation: fix broken links on left navigation Extending Log4j Configuration sub-menu.
1094 </action>
1095 <action issue="LOG4J2-856" dev="rpopma" type="add">
1096 Documentation: add sections on the JUL Adapter, IO Streams and NoSQL Appenders to the Maven and Ivy page.
1097 </action>
1098 <action issue="LOG4J2-797" dev="rpopma" type="fix" due-to="Andreas Rytina">
1099 Documentation: clarified why log4j-core is a compile time dependency in Maven and Ivy page.
1100 </action>
1101 <action issue="LOG4J2-855" dev="rpopma" type="fix">
1102 Documentation: fix broken links on Appenders manual page.
1103 </action>
1104 <action issue="LOG4J2-807" dev="rpopma" type="fix">
1105 Prevent NPE when configuration with AsyncLogger/AsyncRoot is reloaded.
1106 </action>
1107 <action issue="LOG4J2-848" dev="ggregory" type="add">
1108 Add a Java lookup to provide nicely formatted runtime version information.
1109 </action>
1110 <action issue="LOG4J2-809" dev="mattsicker" type="add">
1111 Move reflection utility class to API's private utility classes.
1112 </action>
1113 <action issue="LOG4J2-845" dev="mattsicker" type="update">
1114 Add 2.1.0 to compatible versions in Log4j API ProviderUtil and update Log4jAPIVersion to 2.1.0 in
1115 core META-INF/log4j-provider.properties.
1116 </action>
1117 <action issue="LOG4J2-833" dev="rpopma" type="add">
1118 Documentation: added Runtime Dependencies link to left nav-bar on site.
1119 </action>
1120 <action issue="LOG4J2-816" dev="rpopma" type="add">
1121 Documentation: added section on XInclude to user manual Configuration page.
1122 </action>
1123 <action issue="LOG4J2-678" dev="rpopma" type="fix" due-to="Matt Sicker">
1124 Documentation: fixed minor issues with Log4j2 web site/documentation.
1125 </action>
1126 <action issue="LOG4J2-844" dev="rpopma" type="update">
1127 Update JMH to 1.1 from 0.7.2.
1128 </action>
1129 <action issue="LOG4J2-843" dev="rpopma" type="fix">
1130 Migrate JpaHyperSqlAppenderTest JUnit performance test to log4j-perf.
1131 </action>
1132 <action issue="LOG4J2-842" dev="rpopma" type="fix">
1133 Migrate JpaH2AppenderTest JUnit performance test to log4j-perf.
1134 </action>
1135 <action issue="LOG4J2-841" dev="rpopma" type="fix">
1136 Migrate JdbcHyperSqlAppenderTest JUnit performance test to log4j-perf.
1137 </action>
1138 <action issue="LOG4J2-840" dev="rpopma" type="fix">
1139 Migrate JdbcH2AppenderTest JUnit performance test to log4j-perf.
1140 </action>
1141 <action issue="LOG4J2-830" dev="rpopma" type="fix">
1142 Respect external interrupt signal to allow application shutdown after joining AsyncAppender thread.
1143 </action>
1144 <action issue="LOG4J2-813" dev="ggregory" type="fix" due-to="David Erichsen, Brandon Barry">
1145 MarkerManager Log4jMarker.hasParents() returns opposite of correct result.
1146 </action>
1147 <action issue="LOG4J2-785" dev="rpopma" type="fix">
1148 Documentation: fixed capitalization inconsistency in user manual example config.
1149 </action>
1150 <action issue="LOG4J2-829" dev="rpopma" type="fix">
1151 Fixed issue in RollingFile filePattern: backslashes are path separators, not escape characters.
1152 </action>
1153 <action issue="LOG4J2-547" dev="mattsicker" type="add">
1154 Add the Log4j IOStreams component.
1155 </action>
1156 <action issue="LOG4J2-431" dev="rpopma" type="add" due-to="Claude Mamo">
1157 Added Memory-Mapped File Appender.
1158 </action>
1159 <action issue="LOG4J2-832" dev="ggregory" type="fix" due-to="Seth Leger">
1160 ThrowableProxy fails if a class in logged stack trace throws java.lang.Error from initializer
1161 </action>
1162 <action issue="LOG4J2-831" dev="rpopma" type="update">
1163 Documentation: updated FAQ "which jars" diagrams for JUL bridge and 2.1 version.
1164 </action>
1165 <action issue="LOG4J2-827" dev="mattsicker" type="add">
1166 Support use of TypeConverter classes through the standard Plugin system.
1167 </action>
1168 <action issue="LOG4J2-745" dev="mattsicker" type="fix" due-to="Scott Harrington">
1169 Avoid ConverterKey plugin clashes by using a more predictable plugin loading infrastructure.
1170 Plugins have been segmented into three parts: class path, user-specified packages, and OSGi bundles.
1171 </action>
1172 <action issue="LOG4J2-798" dev="mattsicker" type="fix" due-to="Scott Harrington">
1173 Fixed plugin scanning redundancy causing massive slowdowns in certain environments.
1174 </action>
1175 <action issue="LOG4J2-753" dev="rpopma" type="fix">
1176 Reduced CachedClock thread contention.
1177 </action>
1178 <action issue="LOG4J2-819" dev="mattsicker" type="fix" due-to="Gary Gregory">
1179 Fixed memory leak in Tomcat 6 caused by clock background threads unintentionally
1180 started by Tomcat after web application stop.
1181 </action>
1182 <action issue="LOG4J2-825" dev="mattsicker" type="add">
1183 Add simple validation constraint annotations for the Plugin system.
1184 </action>
1185 <action issue="LOG4J2-428" dev="ggregory" type="add" due-to="Mark Paluch, Mikael Ståldal">
1186 Implement a GELF layout.
1187 </action>
1188 <action issue="LOG4J2-391" dev="rgoers" type="fix" due-to="Kamal Bahadur">
1189 FlumePersistentManager now handles LockConflictExceptions in Berkeley Db when sending a batch.
1190 </action>
1191 <action issue="LOG4J2-782" dev="mattsicker" type="fix">
1192 Remove invalid Oracle Maven repository.
1193 </action>
1194 <action issue="LOG4J2-780" dev="mattsicker" type="update">
1195 Update Spring Framework to 3.2.11.RELEASE from 3.2.8.RELEASE.
1196 </action>
1197 <action issue="LOG4J2-815" dev="mattsicker" type="update">
1198 Unify the two JMS appenders into a single appender. Configurations written for 2.0 will still work in 2.1+.
1199 </action>
1200 <action issue="LOG4J2-608" dev="mattsicker" type="add">
1201 Add java.util.logging implementation based on log4j-api. See log4j-jul documentation for more details.
1202 </action>
1203 <action issue="LOG4J2-796" dev="rpopma" type="fix">
1204 Fixed issue where log4j-to-slf4j did not work correctly with SLF4J Simple Logger.
1205 </action>
1206 <action issue="LOG4J2-811" dev="ggregory" type="fix" due-to="Yogesh Rao">
1207 SimpleLogger throws ArrayIndexOutOfBoundsException for an empty array.
1208 </action>
1209 <action issue="LOG4J2-663" dev="mattsicker" type="fix" due-to="Florian Brunner">
1210 Fix OSGi Import-Package problem with the JMS API.
1211 </action>
1212 <action issue="LOG4J2-793" dev="mattsicker" type="add">
1213 Add support for custom SLF4J Markers in log4j-slf4j-impl module.
1214 </action>
1215 <action issue="LOG4J2-783" dev="rpopma" type="fix" due-to="Minglei Lee">
1216 PatternLayout should use platform character encoding by default, not UTF-8.
1217 </action>
1218 <action issue="LOG4J2-771" dev="ggregory" type="add">
1219 Add lookup for application main arguments.
1220 </action>
1221 <action issue="LOG4J2-787" dev="ggregory" type="add">
1222 Add lookup for JVM arguments.
1223 </action>
1224 <action issue="LOG4J2-790" dev="ggregory" type="update">
1225 Update Jackson to 2.4.2 from 2.4.1 (for XML and JSON processing).
1226 </action>
1227 <action issue="LOG4J2-766" dev="ggregory" type="update" due-to="Bruno P. Kinoshita">
1228 Incomplete documentation for JSONLayout.
1229 </action>
1230 <action issue="LOG4J2-800" dev="ggregory" type="update">
1231 All life cycle implementations should be serializable.
1232 This is still work in progress.
1233 </action>
1234 <action issue="LOG4J2-801" dev="ggregory" type="update">
1235 org.apache.logging.log4j.core.Logger should be serializable.
1236 This is still work in progress.
1237 </action>
1238 <action issue="LOG4J2-810" dev="ggregory" type="update">
1239 Update javax.mail to 1.5.2 from 1.5.0.
1240 </action>
1241 <action issue="LOG4J2-822" dev="ggregory" type="update">
1242 Update org.eclipse.persistence.jpa to 2.5.2 from 2.5.1.
1243 </action>
1244 <action issue="LOG4J2-867" dev="ggregory" type="update">
1245 FlumeAppender: maxDelay not in seconds, but milliseconds.
1246 Add time scale to some settings, for example maxDelayMillis instead of maxDelay.
1247 The old names are aliased for compatibility.
1248 </action>
1249 </release>
1250 <release version="2.0.2" date="2014-08-16" description="Bug fixes and enhancements">
1251 <action issue="LOG4J2-775" dev="ggregory" type="update">
1252 Update Apache Flume to 1.5.0.1 from 1.5.0.
1253 </action>
1254 <action issue="LOG4J2-773" dev="rpopma" type="fix">
1255 Site: log4j-core component pages were still using the old logo.
1256 </action>
1257 <action issue="LOG4J2-760" dev="rpopma" type="fix">
1258 Documentation improvement: link to dependency tree from log4j-core component page,
1259 link to log4j-core component page from FAQ page.
1260 </action>
1261 <action issue="LOG4J2-679" dev="rpopma" type="fix">
1262 Resolved race condition that caused log file rotation to fail with error: "Unable to create directory ..."
1263 </action>
1264 <action issue="LOG4J2-726" dev="rpopma" type="fix">
1265 Prevent application from hanging when PatternLayout configuration has opening '{' but no closing '}'.
1266 </action>
1267 <action issue="LOG4J2-769" dev="rpopma" type="fix" due-to="Scott Harrington">
1268 Startup takes a long time if you have empty packages attribute.
1269 </action>
1270 <action issue="LOG4J2-763" dev="rpopma" type="fix" due-to="Stephen Connolly">
1271 Improved asynchronous loggers and appenders to ensure the formatted message does not change even if
1272 parameters are modified by the application. (ParameterizedMessage was already safe.)
1273 Improved documentation.
1274 </action>
1275 <action issue="LOG4J2-729" dev="rpopma" type="fix">
1276 Emit warning message to console if no configuration file found.
1277 </action>
1278 <action issue="LOG4J2-765" dev="rpopma" type="fix">
1279 Improve warning message when missing log4j-core in the classpath.
1280 </action>
1281 <action issue="LOG4J2-722" dev="rpopma" type="fix">
1282 Clarified in documentation that Commons Logging jar is required when using log4j-jcl.
1283 </action>
1284 <action issue="LOG4J2-723" dev="rpopma" type="fix">
1285 Clarified in documentation that SLF4J API jar is required when using log4j-slf4j-impl.
1286 </action>
1287 <action issue="LOG4J2-730" dev="rpopma" type="update">
1288 Allow Log4jContextFactory subclasses to specify a custom ContextSelector.
1289 </action>
1290 <action issue="LOG4J2-759" dev="rpopma" type="fix">
1291 Fixed various minor site/documentation issues, mostly versioning related.
1292 </action>
1293 <action issue="LOG4J2-756" dev="rpopma" type="fix" due-to="Scott Harrington">
1294 Prevent JUnit test from creating unnecessary Log4j2Plugins.dat during build.
1295 </action>
1296 </release>
1297 <release version="2.0.1" date="2014-07-29" description="Bug fixes">
1298 <action issue="LOG4J2-744" dev="rpopma" type="fix" due-to="Scott Harrington">
1299 Avoid unnecessary Clock calls when TimestampMessage is logged.
1300 </action>
1301 <action issue="LOG4J2-704" dev="rpopma" type="fix">
1302 Improved error message if configuration file not found.
1303 </action>
1304 <action issue="LOG4J2-750" dev="ggregory" type="fix" due-to="Mike Calmus">
1305 Webapp configuration page has incorrect class name.
1306 </action>
1307 <action issue="LOG4J2-749" dev="rpopma" type="fix" due-to="Scott Harrington">
1308 Retain the default date pattern after fixing the ISO8601 pattern.
1309 </action>
1310 <action issue="LOG4J2-670" dev="rpopma" type="fix">
1311 DatePatternConverter ISO8601_PATTERN now conforms to ISO8601.
1312 </action>
1313 <action issue="LOG4J2-741" dev="rpopma" type="fix">
1314 Reinstate the package configuration attribute for discovering custom plugins.
1315 </action>
1316 <action issue="LOG4J2-742" dev="ggregory" type="fix" due-to="Pascal Chollet">
1317 XInclude not working with relative path.
1318 </action>
1319 <action issue="LOG4J2-740" dev="mattsicker" type="fix" due-to="Kosta Krauth">
1320 Fixed typo in webapp manual regarding sample web.xml file.
1321 </action>
1322 <action issue="LOG4J2-738" dev="ggregory" type="fix" due-to="Timothy Stack">
1323 RollingFileManager deadlock if async action thread fails to start.
1324 </action>
1325 <action issue="LOG4J2-736" dev="mattsicker" type="fix">
1326 Fixed log4j-bom so that it won't specify a default scope on any third party dependencies.
1327 </action>
1328 <action issue="LOG4J2-735" dev="mattsicker" type="fix">
1329 Fixed log4j-bom so that it won't interfere with spring-bom and others.
1330 </action>
1331 <action issue="LOG4J2-731" dev="mattsicker" type="fix">
1332 Updated documentation regarding extensions to LoggerContextFactory and Log4j 2 providers.
1333 </action>
1334 <action issue="LOG4J2-373" dev="mattsicker" type="fix">
1335 Fixed ClassLoader issues in loading Log4j providers in an OSGi environment.
1336 </action>
1337 <action issue="LOG4J2-725" dev="mattsicker" type="add">
1338 Added WebLoggerContextUtils class to log4j-web for helper methods useful for asynchronous servlets.
1339 </action>
1340 <action issue="LOG4J2-710" dev="rpopma" type="add">
1341 Added documentation for Custom Levels and Custom Loggers.
1342 </action>
1343 <action issue="LOG4J2-719" dev="rpopma" type="fix">
1344 Correctly handle NetworkOnMainThreadException thrown on Android during Log4j2 initialization.
1345 </action>
1346 <action issue="LOG4J2-716" dev="rpopma" type="fix">
1347 Automatically disable log4j JMX when detecting we are running on Android.
1348 </action>
1349 <action issue="LOG4J2-657" dev="rpopma" type="fix" due-to="Stefan Wehner">
1350 Fixed AbstractDatabaseManager to close connection on writeInternal error.
1351 </action>
1352 <action issue="LOG4J2-713" dev="ggregory" type="fix" due-to="Nelson Melina">
1353 Android: java.lang.VerifyError: org/apache/logging/log4j/core/util/Closer
1354 </action>
1355 <action issue="LOG4J2-703" dev="ggregory" type="fix" due-to="Nelson Melina">
1356 Android: Could not find class 'javax.naming.InitialContext', referenced from method org.apache.logging.log4j.core.lookup.JndiLookup.lookup.
1357 </action>
1358 <action issue="LOG4J2-732" dev="ggregory" type="updated">
1359 Update to LMAX Disruptor 3.3.0 from 3.2.1.
1360 </action>
1361 <action issue="LOG4J2-733" dev="ggregory" type="updated">
1362 Update to latest Jackson jars from the 2.4.1.X line.
1363 </action>
1364 </release>
1365 <release version="2.0" date="2014-07-12" description="GA Release">
1366 <action issue="LOG4J2-705" dev="rpopma" type="fix">
1367 Fixed issue where Async Logger does not log thread context stack data.
1368 API change: added method getImmutableStackOrNull() to ThreadContext.ContextStack interface.
1369 </action>
1370 <action issue="LOG4J2-631" dev="rpopma" type="fix">
1371 Update docs to clarify how to use formatter logger and standard logger together.
1372 </action>
1373 <action issue="LOG4J2-519" dev="rpopma" type="add">
1374 Added support for generating custom logger wrappers that replace the existing log levels
1375 and extended logger wrappers that add custom log levels to the existing ones.
1376 </action>
1377 <action issue="LOG4J2-441" dev="rgoers" type="fix">
1378 LoggerConfigs with no Level now inherit the Level from their parent.
1379 </action>
1380 <action issue="LOG4J2-696" dev="ggregory" type="add">
1381 RegexFilter does not match multiline log messages.
1382 </action>
1383 <action issue="LOG4J2-699" dev="rpopma" type="fix">
1384 PatternLayout manual page missing documentation on header/footer.
1385 </action>
1386 <action issue="LOG4J2-625" dev="rpopma" type="fix">
1387 Fixed Serialization error with SocketAppender and Async Loggers.
1388 (Fixed in RC2, but wasn't included in release notes.)
1389 </action>
1390 <action issue="LOG4J2-538" dev="rpopma" type="fix">
1391 JMX GUI: fixed occasional ArrayIndexOutOfBoundsException after pressing "reconfigure with XML below".
1392 (Fixed in RC2, but wasn't included in release notes.)
1393 </action>
1394 <action issue="LOG4J2-666" dev="rpopma" type="fix">
1395 AsyncLoggerContextSelector should ensure that different AsyncLoggerContext objects created by web app classloaders have unique names.
1396 </action>
1397 <action issue="LOG4J2-683" dev="mattsicker" type="fix" due-to="Jurriaan Mous">
1398 Fix annotation processor warnings on JDK 1.7+.
1399 </action>
1400 <action issue="LOG4J2-694" dev="mattsicker" type="fix">
1401 Fix strange compilation error that popped up in a test class.
1402 </action>
1403 <action issue="LOG4J2-692" dev="rgoers" type="fix">
1404 Update documentation to specify only Maven 3 is supported.
1405 </action>
1406 <action issue="LOG4J2-690" dev="rgoers" type="fix" due-to="Philip Helger">
1407 Log4j Web test dependencies should be in scope "test" in the pom.
1408 </action>
1409 <action issue="LOG4J2-682" dev="ggregory" type="fix" due-to="Scott Harrington">
1410 Special characters (tab and so on) in PatternLayout do not work.
1411 </action>
1412 <action issue="LOG4J2-685" dev="ggregory" type="update">
1413 Make org.apache.logging.log4j.core.layout.AbstractLayout immutable.
1414 </action>
1415 <action issue="LOG4J2-686" dev="ggregory" type="fix">
1416 Core's OptionConverter support for \b is broken (affects PatternLayout).
1417 </action>
1418 <action issue="LOG4J2-687" dev="ggregory" type="fix">
1419 Rename org.apache.logging.log4j.core.util.Closer.closeSilent() to closeSilently().
1420 </action>
1421 <action issue="LOG4J2-688" dev="ggregory" type="fix">
1422 Make org.apache.logging.log4j.core.layout.PatternLayout immutable.
1423 </action>
1424 <action issue="LOG4J2-689" dev="ggregory" type="update">
1425 Update Jackson to 2.4.1.
1426 </action>
1427 <action issue="LOG4J2-707" dev="ggregory" type="fix">
1428 Some exceptions are not logged when configuration problems are detected.
1429 </action>
1430 <action issue="LOG4J2-709" dev="ggregory" type="update">
1431 Update Apache Commons Logging to 1.2 from 1.1.3.
1432 </action>
1433 </release>
1434 <release version="2.0-rc2" date="2014-06-21" description="Bug fixes and enhancements">
1435 <action issue="LOG4J2-675" dev="rpopma" type="add">
1436 RollingFile and RollingRandomAccessFile now write the layout footer before rollover.
1437 </action>
1438 <action issue="LOG4J2-581" dev="rpopma" type="fix" due-to="Alexander Khokhlov">
1439 RollingRandomAccessFile now writes the layout header after rollover.
1440 </action>
1441 <action issue="LOG4J2-622" dev="rpopma" type="fix" due-to="Farooq Khan">
1442 RollingFileManager now correctly honours the bufferedIO configuration after rollover.
1443 </action>
1444 <action issue="LOG4J2-674" dev="rpopma" type="add">
1445 Made RollingFileAppender buffer size configurable.
1446 </action>
1447 <action issue="LOG4J2-141" dev="rpopma" type="fix" due-to="Joern Huxhorn">
1448 Improved documentation regarding log4j status logger.
1449 </action>
1450 <action issue="LOG4J2-539" dev="rpopma" type="fix" due-to="Colin Froggatt">
1451 Fixed issue with "Reconfigure using XML below" function in JMX Client GUI.
1452 ConfigurationSource is now a top-level class and can be obtained with Configuration.getConfigurationSource().
1453 LoggerContext.getConfiguration().getConfigurationSource()
1454 provides a reliable public method for obtaining a logger context's configuration location and content.
1455 </action>
1456 <action issue="LOG4J2-619" dev="rgoers" type="fix" due-to="Scott Harrington">
1457 Invalid XML configuration files do not prevent the config file from being checked again.
1458 </action>
1459 <action issue="LOG4J2-637" dev="rpopma" type="fix" due-to="Mansoor Sajjad, Jon Wilmoth">
1460 JMX: Updating a Logger's level via jConsole now correctly takes effect.
1461 </action>
1462 <action issue="LOG4J2-668" dev="rpopma" type="fix">
1463 Correctly process log events when combining AsyncLoggers with AsyncAppender.
1464 </action>
1465 <action issue="LOG4J2-669" dev="rpopma" type="fix">
1466 Prevent NPE when combining AsyncLoggers with AsyncLoggerConfigs.
1467 </action>
1468 <action issue="LOG4J2-42" dev="rgoers" type="add">
1469 Create an appender to route log events to the ServletContext log.
1470 </action>
1471 <action issue="LOG4J2-419" dev="rgoers" type="update" due-to="Woonsan Ko">
1472 Support default value for missing key in look ups with fallbacking to looking in the properties map.
1473 </action>
1474 <action issue="LOG4J2-563" dev="rgoers" type="fix" due-to="Michael Friedmann">
1475 FlumeAvroManager now always uses a client type of default_failover.
1476 </action>
1477 <action issue="LOG4J2-554" dev="rgoers" type="update">
1478 Allow configuration files to be located as Servlet Context resources.
1479 </action>
1480 <action issue="LOG4J2-535" dev="rgoers" type="fix">
1481 Reset rollover time when size rollover is triggered.
1482 </action>
1483 <action issue="LOG4J2-664" dev="mattsicker" type="fix">
1484 Moved plugin cache file to META-INF for OSGi compatibility.
1485 </action>
1486 <action issue="LOG4J2-640" dev="mattsicker" type="fix">
1487 Fix NPE that can be caused by a null ThreadContextClassLoader.
1488 </action>
1489 <action issue="LOG4J2-655" dev="mattsicker" type="add">
1490 Add Vagrantfile for testing in GNU+Linux.
1491 </action>
1492 <action issue="LOG4J2-651" dev="ggregory" type="fix">
1493 Log4j 2 throws ArrayIndexOutOfBoundsException.
1494 </action>
1495 <action issue="LOG4J2-654" dev="rpopma" type="add">
1496 Add log4j-perf module to provide a home for all log4j performance tests.
1497 Add support for JMH microbenchmark performance tests.
1498 </action>
1499 <action issue="LOG4J2-652" dev="mattsicker" type="add">
1500 Add support for default plugin values and attributes.
1501 </action>
1502 <action issue="LOG4J2-598" dev="mattsicker" type="add">
1503 Add support for types other than String for plugin factory values/attributes.
1504 </action>
1505 <action issue="LOG4J2-250" dev="rpopma" type="update">
1506 Refactor Log4jLogEvent to lazily create ThrowableProxy.
1507 </action>
1508 <action issue="LOG4J2-647" dev="ggregory" type="update">
1509 Upgrade to Flume 1.5.0.
1510 </action>
1511 <action issue="LOG4J2-644" dev="ggregory" type="add">
1512 Implement a SecureSocketAppender and secure server (SSL/TLS).
1513 </action>
1514 <action issue="LOG4J2-646" dev="ggregory" type="update">
1515 Merge the TLS Syslog appender into the Syslog appender.
1516 </action>
1517 <action issue="LOG4J2-620" dev="rgoers" type="fix">
1518 Perform reconfiguration in a separate thread to prevent deadlocks.
1519 </action>
1520 <action issue="LOG4J2-641" dev="mattsicker" type="update">
1521 Override commons-logging dependency version in tests.
1522 </action>
1523 <action issue="LOG4J2-639" dev="rpopma" type="fix" due-to="Mck SembWever">
1524 Prevent NPE in AsyncLogger and AsyncLoggerConfig if logger is used after log4j has been shut down.
1525 </action>
1526 <action issue="LOG4J2-469" dev="rgoers" type="fix">
1527 FailoverAppender was not resetting its status after the primary appender recovered.
1528 </action>
1529 <action issue="LOG4J2-623" dev="rgoers" type="fix">
1530 Generate MDC properties as a JSON map in JSONLayout.
1531 </action>
1532 <action issue="LOG4J2-566" dev="rpopma" type="update" due-to="Luigi Alice">
1533 Made RollingRandomAccessFileAppender buffer size configurable.
1534 </action>
1535 <action issue="LOG4J2-520" dev="rpopma" type="fix" due-to="JavaTech, Andre Bogus">
1536 Resolved issue where AsyncAppender dropped events if queue still contained
1537 events when application is stopped.
1538 </action>
1539 <action issue="LOG4J2-392" dev="rpopma" type="fix" due-to="Andre Bogus">
1540 Resolved a problem with the previous solution for LOG4J2-392 that resulted in dropped events
1541 when using AsyncLoggerConfig with slow appenders when application is stopped.
1542 </action>
1543 <action issue="LOG4J2-613" dev="mattsicker" type="fix">
1544 The OSGi version of log4j-web imports Servlet 2.5 at minimum instead of 3.0.
1545 </action>
1546 <action issue="LOG4J2-602" dev="rgoers" type="fix">
1547 Unit tests are now less verbose during the build process.
1548 </action>
1549 <action issue="LOG4J2-570" dev="mattsicker" type="fix">
1550 Fix shutdown thread memory leak in servlet containers.
1551 </action>
1552 <action issue="LOG4J2-628" dev="rpopma" type="update">
1553 Use Clock to generate all log event timestamps, not just for Async Loggers.
1554 </action>
1555 <action issue="LOG4J2-629" dev="rpopma" type="add">
1556 Document the system properties used in Log4J 2.
1557 </action>
1558 <action issue="LOG4J2-542" dev="rgoers" type="fix">
1559 Make Throwable transient in ThrowableProxy.
1560 </action>
1561 <action issue="LOG4J2-617" dev="mattsicker" type="update">
1562 Update SLF4J to 1.7.7.
1563 </action>
1564 <action issue="LOG4J2-616" dev="mattsicker" type="update">
1565 Update Jackson to 2.3.3.
1566 </action>
1567 <action issue="LOG4J2-440" dev="mattsicker" type="fix">
1568 During shutdown, a NullPointerException could be thrown due to the NullConfiguration class no longer being
1569 available to the ClassLoader.
1570 </action>
1571 <action issue="LOG4J2-346" dev="mattsicker" type="fix">
1572 Cyclic dependency with log4j-slf4j-impl in OSGi.
1573 </action>
1574 <action issue="LOG4J2-345" dev="mattsicker" type="fix">
1575 The log4j-1.2-api module didn't export any packages to OSGi.
1576 </action>
1577 <action issue="LOG4J2-605" dev="mattsicker" type="fix">
1578 Password data from the NoSQL plugins no longer shows up in cleartext in debug logging.
1579 </action>
1580 <action issue="LOG4J2-448" dev="rgoers" type="fix" due-to="X86core">
1581 A StringIndexOutOfBounds exception could occur during property substitution.
1582 </action>
1583 <action issue="LOG4J2-597" dev="rgoers" type="fix">
1584 StatusLogger was not skipping multiple instances of the FQCN class, causing messages from classes in
1585 the Verbose list to be printed.
1586 </action>
1587 <action issue="LOG4J2-585" dev="rgoers" type="update" due-to="Bruce Brouwer">
1588 Add support for multiple parents to Markers.
1589 </action>
1590 <action issue="LOG4J2-595" dev="mattsicker" type="add">
1591 Introduce Java annotation processor as the new plugin pre-caching mechanism. This is available in log4j-core.
1592 All custom plugins created before this should be re-built against the current log4j-core.
1593 </action>
1594 <action issue="LOG4J2-564" dev="mattsicker" type="fix">
1595 Renamed SLF4J logger class to Log4jLogger.
1596 </action>
1597 <action issue="LOG4J2-579" dev="ggregory" type="fix">
1598 Rework Level comparison APIs.
1599 </action>
1600 <action issue="LOG4J2-576" dev="ggregory" type="add">
1601 Add org.apache.logging.log4j.Logger.getLevel().
1602 </action>
1603 <action issue="LOG4J2-574" dev="rpopma" type="update">
1604 Make Blocking the default WaitStrategy for Async Loggers.
1605 </action>
1606 <action issue="LOG4J2-555" dev="rpopma" type="update" due-to="Bruce Brouwer">
1607 Introduce ExtendedLogger interface to facilitate implementing and extending Loggers.
1608 </action>
1609 <action issue="LOG4J2-560" dev="rgoers" type="fix">
1610 SyslogAppenderTest and RFC5424LayoutTest were failing in Java 8.
1611 </action>
1612 <action issue="LOG4J2-561" dev="ggregory" type="update" due-to="vibin">
1613 Allow spaces around commas in Configuration's package attribute.
1614 </action>
1615 <action issue="LOG4J2-547" dev="rgoers" type="update" due-to="Bruce Brouwer">
1616 Have Logger API expose a PrintWriter instead of custom LoggerStream.
1617 </action>
1618 <action issue="LOG4J2-439" dev="rgoers" type="add" due-to="Bruce Brouwer">
1619 Add EncodingPatternConverter to escape newlines and HTML special characters.
1620 </action>
1621 <action issue="LOG4J2-496" dev="rgoers" type="update">
1622 Allow header and footer to be specified as lookup patterns in PatternLayout.
1623 </action>
1624 <action issue="LOG4J2-499" dev="rgoers" type="fix">
1625 Add equals and hashcode to Log4jLogEvent.
1626 </action>
1627 <action issue="LOG4J2-410" dev="rgoers" type="update" due-to="Ivlin Zeng">
1628 SLf4JLogger is now Serializable.
1629 </action>
1630 <action issue="LOG4J2-427" dev="rgoers" type="add" due-to="Alexander Reelsen">
1631 Add support for configuration via YAML.
1632 </action>
1633 <action issue="LOG4J2-378" dev="rgoers" type="fix">
1634 Add DateLookup and ThreadContextLookup to default lookups.
1635 </action>
1636 <action issue="LOG4J2-468" dev="rgoers" type="update">
1637 Add support to add a LoggerConfig. Document two ways to modify the configuration.
1638 </action>
1639 <action issue="LOG4J2-582" dev="ggregory" type="update">
1640 Rename org.apache.logging.log4j.core.net.SocketServer to TCPSocketServer and refactor with UDP.
1641 </action>
1642 <action issue="LOG4J2-592" dev="ggregory" type="update">
1643 Update Jackson to 2.3.2 from 2.2.2.
1644 </action>
1645 </release>
1646 <release version="2.0-rc1" date="2014-02-16" description="Bug fixes and enhancements">
1647 <action dev="nickwilliams" type="delete">
1648 Removed the DataSourceConnectionSource and the &lt;DriverManager&gt; plugin for the JDBC Appender. It is not
1649 safe to use. Please use the DataSource or factory connection sources backed by a connection pool.
1650 </action>
1651 <action dev="nickwilliams" type="update">
1652 Renamed the org.apache.logging.log4j.core.appender.db.nosql.mongo package to
1653 org.apache.logging.log4j.core.appender.db.nosql.mongodb.
1654 </action>
1655 <action dev="grobmeier" type="update">
1656 Renamed the org.apache.logging.log4j.core.appender.db.nosql.couch package to
1657 org.apache.logging.log4j.core.appender.db.nosql.couchdb.
1658 </action>
1659 <action issue="LOG4J2-500" dev="rpopma" type="fix">
1660 (JMX - ObjectNames changed!) Unloading one web application unloads JMX MBeans for all web applications.
1661 </action>
1662 <action issue="LOG4J2-507" dev="ggregory" type="update">
1663 Space Level numbers by 100 instead of 1.
1664 </action>
1665 <action issue="LOG4J2-531" dev="rpopma" type="fix" due-to="Geoff Ballinger">
1666 Fixed bugs where rolled log files were overwritten by RollingFile appender with
1667 composite time and size based policies.
1668 </action>
1669 <action issue="LOG4J2-475" dev="nickwilliams" type="fix" due-to="Matt Sicker">
1670 Changed the MongoDBConnection to add a MongoDB encoding hook instead of a decoding hook.
1671 </action>
1672 <action issue="LOG4J2-489" dev="nickwilliams" type="fix">
1673 Fixed the JPAAppender's overuse of transactions by connecting (borrowing from pool) on new write internal or on
1674 flush.
1675 </action>
1676 <action issue="LOG4J2-457" dev="nickwilliams" type="fix">
1677 Fixed failure of JDBC and JPA appender to properly release database connections by connecting (borrowing from
1678 pool) on new write internal or on flush.
1679 </action>
1680 <action issue="LOG4J2-442" dev="nickwilliams" type="fix">
1681 Fixed problem with JDBC and JPA appender connectivity in WebSphere by connecting (borrowing from pool) on new
1682 write internal or on flush.
1683 </action>
1684 <action issue="LOG4J2-438" dev="nickwilliams" type="fix">
1685 Ensured the JDBCAppender commits transactions after a single write or a flush of multiple writes.
1686 </action>
1687 <action issue="LOG4J2-407" dev="nickwilliams" type="fix">
1688 Fixed inability to recover from lost database connection in database appenders by connecting (borrowing from
1689 pool) on new write internal or on flush.
1690 </action>
1691 <action issue="LOG4J2-530" dev="rpopma" type="add">
1692 (JMX) JMX Client GUI should dynamically update when LoggerContext MBeans are registered/unregistered in MBean
1693 server.
1694 </action>
1695 <action issue="LOG4J2-511" dev="rpopma" type="fix" due-to="James Pretorius">
1696 Stop AsyncLoggerConfig Disruptor thread(s), then AsyncAppender thread(s) first
1697 before stopping other appenders.
1698 </action>
1699 <action issue="LOG4J2-392" dev="rpopma" type="fix" due-to="ilynaf, Andre Bogus">
1700 Stop AsyncLoggerConfig Disruptor thread(s), then AsyncAppender thread(s) first
1701 before stopping other appenders.
1702 </action>
1703 <action issue="LOG4J2-345" dev="rpopma" type="fix" due-to="Roland Weiglhofer, Matt Sicker">
1704 (OSGi) logging.log4j-1.2-api doesn't export the log4j API 1.2. Dependent bundles can not be resolved.
1705 </action>
1706 <action issue="LOG4J2-523" dev="ggregory" type="fix">
1707 LocalizedMessage serialization is broken.
1708 </action>
1709 <action issue="LOG4J2-385" dev="rpopma" type="fix" due-to="Ace Funk, Porfirio Partida">
1710 Fixed issues with time-based file rollover (monthly, weekly, hourly and every minute).
1711 </action>
1712 <action issue="LOG4J2-452" dev="nickwilliams" type="fix">
1713 Added a ServletContext attribute that, when set to "true", disables Log4j's auto-initialization in
1714 Servlet 3.0+ web applications.
1715 </action>
1716 <action issue="LOG4J2-512" dev="nickwilliams" type="fix" due-to="Chandra Sekhar Kakarla, Matt Sicker">
1717 Exposed Log4j web support interface and methods and the LoggerContext through ServletContext attributes
1718 so that threads not affected by filters (such as asynchronous threads) can utilize the LoggerContext. Also
1719 updated the Log4j filter so that it supports async.
1720 </action>
1721 <action issue="LOG4J2-409" dev="nickwilliams" type="fix" due-to="Frank Steinmann, Thomas Neidhart">
1722 Created a utility to properly escape backslashes before creating URIs, and changed URI creation to use the
1723 utility instead of instantiating URI directly.
1724 </action>
1725 <action issue="LOG4J2-344" dev="nickwilliams" type="fix" due-to="Keir Lawson, Tomasz Wladzinski">
1726 Changed the Servlet 3.0 auto-initializer to add the filter by class to get around a WebLogic bug.
1727 </action>
1728 <action issue="LOG4J2-359" dev="nickwilliams" type="fix" due-to="Abhinav Shah">
1729 Changed the Servlet 3.0 auto-initializer so that it does nothing in a Servlet 2.5 or older application. This
1730 ensures behavioral consistency across containers. This includes additional fixes to abort initialization if a
1731 duplicate filter already exists and to check the actual Servlet EFFECTIVE version.
1732 </action>
1733 <action issue="LOG4J2-517" dev="rpopma" type="fix">
1734 Switch in log4j-1.2-api Category.getEffectiveLevel has no cases for FATAL, OFF.
1735 </action>
1736 <action issue="LOG4J2-41" dev="rgoers" type="update" due-to="Nick Williams">
1737 Add support for custom logging levels.
1738 </action>
1739 <action issue="LOG4J2-406" dev="rpopma" type="fix" due-to="Kerrigan Joseph">
1740 (JMX) Unregister all log4j JMX MBeans when the LoggerContext is stopped
1741 to allow web application classes to be GC-ed on undeploy.
1742 </action>
1743 <action issue="LOG4J2-405" dev="rgoers" type="fix">
1744 Configuration was being processed twice at startup.
1745 </action>
1746 <action issue="LOG4J2-479" dev="rpopma" type="add" due-to="MK">
1747 ThreadContext now uses plain ThreadLocal by default, unless system property
1748 isThreadContextMapInheritable has value "true".
1749 </action>
1750 <action issue="LOG4J2-398" dev="rgoers" type="fix">
1751 Configure properties and setup Interpolator before processing rest of configuration.
1752 </action>
1753 <action issue="LOG4J2-481" dev="rgoers" type="add" due-to="Matt Sicker">
1754 Add Stream interface to Loggers.
1755 </action>
1756 <action issue="LOG4J2-490" dev="rgoers" type="update" due-to="Matt Sicker">
1757 Update EasyMock to version 3.2.
1758 </action>
1759 <action issue="LOG4J2-470" dev="rgoers" type="fix">
1760 hostName property was not being set until after the first configuration element.
1761 </action>
1762 <action issue="LOG4J2-464" dev="rgoers" type="fix">
1763 Support arrays as sub-elements of a JSON configuration.
1764 </action>
1765 <action issue="LOG4J2-492" dev="rpopma" type="fix" due-to="Shaddy Baddah, Herlani Junior">
1766 (JMX) Fixed MalformedObjectNameException if context name contains '=' or newline characters.
1767 </action>
1768 <action issue="LOG4J2-377" dev="rpopma" type="fix" due-to="Roland Weiglhofer, Matt Sicker">
1769 (OSGi) Fix NPE during shutdown.
1770 </action>
1771 <action issue="LOG4J2-463" dev="rpopma" type="fix" due-to="Michael Diamond, Matt Sicker">
1772 Fixed documentation for MyApp example application in the Automatic Configuration section
1773 </action>
1774 <action issue="LOG4J2-408" dev="rpopma" type="fix" due-to="Dongqing Hu, Matt Sicker">
1775 Fixed error in documentation code example in manual/eventlogging.html
1776 </action>
1777 <action issue="LOG4J2-451" dev="rpopma" type="fix" due-to="Vinay Pothnis, Matt Sicker">
1778 Fixed typo in documentation: system property should be log4j2.loggerContextFactory
1779 </action>
1780 <action issue="LOG4J2-443" dev="rpopma" type="fix" due-to="Colin Froggatt, Tudor Har">
1781 (JMX) Fixed issue where log4j2 LoggerContext did not show up in JMX GUI or JConsole.
1782 </action>
1783 <action issue="LOG4J2-485" dev="rpopma" type="fix">
1784 Fixed issue where toString methods that perform logging could deadlock AsyncAppender.
1785 </action>
1786 <action issue="LOG4J2-445" dev="rpopma" type="fix" due-to="Anthony Baldocchi">
1787 ResolverUtil cannot find packages in file URLs which include the '+' character.
1788 </action>
1789 <action issue="LOG4J2-430" dev="rgoers" type="fix" due-to="David Gstir">
1790 Use the formatted Message in RFC5424Layout for non-StructuredDataMessages.
1791 </action>
1792 <action issue="LOG4J2-459" dev="rgoers" type="fix">
1793 Set external context when constructing the LoggerContext.
1794 </action>
1795 <action issue="LOG4J2-466" dev="rpopma" type="fix" due-to="Jan Tepke">
1796 Cannot load log4j2 config file if path contains plus '+' characters.
1797 </action>
1798 <action issue="LOG4J2-462" dev="rpopma" type="fix" due-to="Daisuke Baba">
1799 Fix LogEvent to never return null Level, fixes LevelPatternConverter.format may throw NPE.
1800 </action>
1801 <action issue="LOG4J2-465" dev="rpopma" type="fix" due-to="Daisuke Baba">
1802 Fix LogEvent to never return null Level, fixes ThresholdFilter throws NPE.
1803 </action>
1804 <action issue="LOG4J2-471" dev="rpopma" type="fix" due-to="Anthony Baldocchi">
1805 Fixed issue where toString methods that perform logging could deadlock AsyncLogger.
1806 </action>
1807 <action issue="LOG4J2-482" dev="rpopma" type="add" due-to="Hongdi Ren">
1808 Documentation fix: The attribute of Route to refer to an appender is "ref" not "AppenderRef".
1809 </action>
1810 <action issue="LOG4J2-467" dev="rpopma" type="add" due-to="Anthony Baldocchi">
1811 Added option to toggle Thread name caching in AsyncLogger.
1812 </action>
1813 <action issue="LOG4J2-478" dev="ggregory" type="fix" due-to="Michael Friedmann.">
1814 The message and ndc fields are not JavaScript escaped in JSONLayout.
1815 </action>
1816 <action issue="LOG4J2-455" dev="rpopma" type="fix" due-to="Robin Zhang Tao">
1817 RingBufferLogEvent should return Message timestamp for TimestampMessage messages.
1818 </action>
1819 <action issue="LOG4J2-477" dev="rpopma" type="fix" due-to="Tal Liron">
1820 NPE in ClassLoaderContextSelector.
1821 </action>
1822 <action issue="LOG4J2-454" dev="rpopma" type="fix" due-to="Robin Zhang Tao">
1823 TimeBasedTriggeringPolicy should use event time millis.
1824 </action>
1825 <action issue="LOG4J2-472" dev="rpopma" type="fix" due-to="Tal Liron">
1826 BaseConfiguration class does not properly implement Configuration interface.
1827 </action>
1828 <action issue="LOG4J2-447" dev="ggregory" type="fix" due-to="Jeff Hudren, Mark Paluch, Scott Deboy">
1829 XMLLayout does not include marker name.
1830 </action>
1831 <action issue="LOG4J2-453" dev="rgoers" type="update">
1832 Update Flume Appender to use Flume 1.4.0.
1833 </action>
1834 <action issue="LOG4J2-423" dev="rpopma" type="add">
1835 (JMX) Added MBeans for instrumenting AsyncAppenders and AsyncLogger RingBuffers,
1836 exposing queue size, remaining capacity and other attributes.
1837 </action>
1838 <action issue="LOG4J2-323" dev="rpopma" type="fix">
1839 Resolved memory leak by releasing reference to ThreadLocal when
1840 AsyncLogger is stopped.
1841 </action>
1842 <action issue="LOG4J2-425" dev="rpopma" type="fix">
1843 Resolved memory leak by populating AsyncLoggerConfigHelper ring buffer
1844 via EventTranslatorTwoArg, eliminating the need for a ThreadLocal.
1845 </action>
1846 <action issue="LOG4J2-420" dev="ggregory" type="add">
1847 Create a lookup for resource bundle substitution.
1848 </action>
1849 <action issue="LOG4J2-417" dev="ggregory" type="fix">
1850 Fix Event Level / LoggerConfig Level table at the architecture documentation page.
1851 </action>
1852 <action issue="LOG4J2-415" dev="ggregory" type="add">
1853 Format log event time as UNIX time (seconds or milliseconds).
1854 </action>
1855 <action issue="LOG4J2-404" dev="rgoers" type="fix" due-to="Kamal Bahadur">
1856 @EnterpriseNumber" was missing in the ID of structured data when RFC5424Layout is used
1857 </action>
1858 <action issue="LOG4J2-379" dev="rpopma" type="fix">
1859 Fixed issue that prevented Log4J from working in Google App Engine.
1860 </action>
1861 <action issue="LOG4J2-401" dev="ggregory" type="add">
1862 Configure FileAppender buffer size.
1863 </action>
1864 <action issue="LOG4J2-402" dev="ggregory" type="add">
1865 Configure RandomAccessFileAppender buffer size.
1866 </action>
1867 <action issue="LOG4J2-528" dev="ggregory" type="update">
1868 Rename package org.apache.logging.log4j.core.appender.rolling.helper to org.apache.logging.log4j.core.appender.rolling.action.
1869 </action>
1870 <action issue="LOG4J2-532" dev="ggregory" type="update">
1871 Resource leak in Flume appender when it cannot create a BerkeleyDB db.
1872 </action>
1873 <action issue="LOG4J2-413" dev="ggregory" type="update">
1874 PatternLayout option to not output ANSI escape codes if no Console is available.
1875 </action>
1876 </release>
1877 <release version="2.0-beta9" date="2013-09-14" description="Bug fixes and enhancements">
1878 <action issue="LOG4J2-317" dev="ggregory" type="update">
1879 Renamed FastFileAppender and FastRollingFileAppender to RandomAccessFileAppender
1880 and RollingRandomAccessFileAppender. Configurations using the Fast(Rolling)File element
1881 no longer work and should be modified to use the (Rolling)RandomAccessFile element.
1882 </action>
1883 <action dev="nickwilliams" type="update">
1884 Changed the "suppressExceptions" configuration attribute for all Appenders to "ignoreExceptions" to avoid
1885 confusion with Java 7 suppressed exceptions. Also renamed the Appender#isExceptionSuppressed() method to
1886 Appender#ignoreExceptions() to avoid the same confusion. All Appenders by default internally log and then ignore
1887 exceptions encountered while logging. Setting "ignoreExceptions" to "false" on an Appender causes it to allow
1888 exceptions to propagate to the caller. You must set "ignoreExceptions" to "false" for Appenders you are wrapping
1889 in the Failover Appender.
1890 </action>
1891 <action dev="nickwilliams" type="update">
1892 Changed the (relatively new) PatternLayout configuration attribute "suppressExceptions" to
1893 "alwaysWriteExceptions" to more correctly indicate what it does. As such, the meaning of this attribute has
1894 reversed (previous "true"s should become "false"s, and vice versa). Since this was an undocumented attribute up
1895 until now, it's unlikely this change will affect any users.
1896 </action>
1897 <action issue="LOG4J2-226" dev="rgoers" type="fix">
1898 Fix table of contents generation in pdf.
1899 </action>
1900 <action issue="LOG4J2-395" dev="rgoers" type="fix" due-to="Abhinav Shah">
1901 Allow classpath scheme when specifying configuration file location as a system property.
1902 </action>
1903 <action issue="LOG4J2-393" dev="rgoers" type="fix">
1904 Initialize PluginManager once during configuration. Move advertisement setup into BaseConfiguration.
1905 </action>
1906 <action issue="LOG4J2-391" dev="rgoers" type="fix" due-to="Kamal Bahadur">
1907 FlumePersistentManager now handles LockConflictExceptions in Berkeley Db.
1908 </action>
1909 <action issue="LOG4J2-399" dev="ggregory" type="add">
1910 Allow the default file rollover strategy to define the compression level.
1911 </action>
1912 <action issue="LOG4J2-338" dev="rgoers" type="add" due-to="Tibor Benke">
1913 Add TLSAppender. Also added missing license headers to several files.
1914 </action>
1915 <action issue="LOG4J2-380" dev="rgoers" type="fix">
1916 Use rollover date when substituting ${date} in the filePattern.
1917 </action>
1918 <action issue="LOG4J2-253" dev="rpopma" type="add">
1919 Added FAQ page to the site.
1920 </action>
1921 <action issue="LOG4J2-362" dev="rpopma" type="add">
1922 Add a diagram to the site (FAQ page) that explains when to use which jar.
1923 </action>
1924 <action issue="LOG4J2-322" dev="nickwilliams" type="fix">
1925 Centralized reflective use of Reflection#getCallerClass and properly handled its instability in various versions
1926 of Java.
1927 </action>
1928 <action issue="LOG4J2-293" dev="rgoers" type="fix">
1929 Reset the Configuration if the ClassLoaderContextSelector creates a LoggerContext without a configuration
1930 location and then is later provided one.
1931 </action>
1932 <action issue="LOG4J2-293" dev="nickwilliams" type="fix" due-to="Abhinav Shah">
1933 Changed the ConfigurationFactory to recognize and properly use the classpath: URI scheme in addition to the
1934 classloader: URI scheme.
1935 </action>
1936 <action issue="LOG4J2-359" dev="nickwilliams" type="fix" due-to="Abhinav Shah">
1937 Changed the Servlet 3.0 auto-initializer so that it does nothing in a Servlet 2.5 or older application. This
1938 ensures behavioral consistency across containers.
1939 </action>
1940 <action issue="LOG4J2-374" dev="ggregory" type="add" due-to="Tibor Benke">
1941 Add more options to PatternLayout to display more detailed information about a Throwable.
1942 </action>
1943 <action issue="LOG4J2-383" dev="ggregory" type="add">
1944 [Pattern Layout] Customize level names by length.
1945 </action>
1946 <action issue="LOG4J2-384" dev="ggregory" type="add">
1947 [Pattern Layout] Customize level names to lower-case.
1948 </action>
1949 <action issue="LOG4J2-355" dev="ggregory" type="update" due-to="Tibor Benke">
1950 Add support for multiple SD-ELEMENTs in a RFC 5424 syslog message.
1951 </action>
1952 <action dev="nickwilliams" type="update">
1953 Cleaned up tests and cleared up documentation for the JPA appender following the resolution of EclipseLink
1954 issue #412454.
1955 </action>
1956 <action issue="LOG4J2-310" dev="rpopma" type="fix" due-to="Olivier Lemasle">
1957 Fixed issue where SMTPAppender did not send mails with error or fatal level without prior info event.
1958 </action>
1959 <action issue="LOG4J2-368" dev="rgoers" type="fix">
1960 Add PatternLayout constructor to Log4j 1.2 bridge for Velocity.
1961 </action>
1962 <action issue="LOG4J2-333" dev="ggregory" type="fix" due-to="Hervé Boutemy">
1963 Match artifact ids with Maven module names.
1964 </action>
1965 <action issue="LOG4J2-364" dev="rgoers" type="add" due-to="David Nault">
1966 Add WebLookup to retrieve information from the ServletContext.
1967 </action>
1968 <action issue="LOG4J2-367" dev="ggregory" type="fix" due-to="David Parry">
1969 JMS appenders send two messages for one append.
1970 </action>
1971 <action issue="LOG4J2-319" dev="ggregory" type="fix">
1972 Double stack trace logging when using %throwable in %style and %highlight.
1973 </action>
1974 <action issue="LOG4J2-360" dev="rgoers" type="add">
1975 Allow Plugins to have aliases.
1976 </action>
1977 <action issue="LOG4J2-358" dev="nickwilliams" type="fix">
1978 NoSQLAppender using MongoDB provider ignores username and password attributes
1979 </action>
1980 <action issue="LOG4J2-356" dev="ggregory" type="add">
1981 Create a JSON Layout.
1982 </action>
1983 <action issue="LOG4J2-343" dev="rpopma" type="fix" due-to="Henning Schmiedehausen">
1984 Removed unnecessary generics from Appender interface and implementing classes.
1985 </action>
1986 <action issue="LOG4J2-351" dev="rpopma" type="fix" due-to="Roland Weiglhofer">
1987 [OSGi] wrong Fragment-Host in manifest files.
1988 </action>
1989 <action issue="LOG4J2-336" dev="rpopma" type="fix" due-to="Andre Bogus">
1990 AsyncLogger errors after multiple calls to LoggerContext.reconfigure().
1991 </action>
1992 <action issue="LOG4J2-347" dev="rpopma" type="fix" due-to="David Phillips">
1993 Give the AsyncAppender thread a more descriptive name for easier debugging/profiling.
1994 </action>
1995 <action issue="LOG4J2-332" dev="rgoers" type="fix" due-to="Hervé Boutemy">
1996 Modified documentation to refer to SLF4J Binding instead of SLF4J Bridge.
1997 </action>
1998 <action issue="LOG4J2-342" dev="rgoers" type="fix">
1999 Ignore xml:base attributes.
2000 </action>
2001 <action issue="LOG4J2-309" dev="rgoers" type="fix">
2002 Insure jars and distributions only have a single License and Notice file.
2003 </action>
2004 <action issue="LOG4J2-341" dev="ggregory" type="add">
2005 Enable XInclude for XML configurations.
2006 </action>
2007 <action issue="LOG4J2-320" dev="ggregory" type="fix">
2008 JPAAppender stops logging because META-INF/log4j-provider.properties is left open.
2009 </action>
2010 <action issue="LOG4J2-335" dev="rgoers" type="fix">
2011 FlumePersistentManager's writer thread had high CPU usage.
2012 </action>
2013 <action issue="LOG4J2-331" dev="nickwilliams" type="fix">
2014 Removed erroneous check for affected MongoDB records, which always returns zero on inserts.
2015 </action>
2016 <action issue="LOG4J2-330" dev="nickwilliams" type="fix">
2017 Added a BSON Transformer so that MongoDB can persist Log4j events.
2018 </action>
2019 <action issue="LOG4J2-329" dev="rgoers" type="fix">
2020 StatusLogger now only creates StatusData objects if they are the appropriate logging level.
2021 </action>
2022 <action issue="LOG4J2-328" dev="rgoers" type="fix">
2023 FlumePersistentManager was calling Berkeley DB's count method too frequently.
2024 </action>
2025 <action issue="LOG4J2-280" dev="rpopma" type="fix">
2026 Additional fix to make AsyncAppender threads daemon threads and improve their thread name.
2027 </action>
2028 <action issue="LOG4J2-165" dev="rgoers" type="fix">
2029 The slf4j-ext jar is now an optional dependency of the SLF4J bridge.
2030 </action>
2031 <action issue="LOG4J2-318" dev="rgoers" type="update">
2032 Allow shutdown hook to be disabled in the configuration.
2033 </action>
2034 <action issue="LOG4J2-166" dev="rgoers" type="fix">
2035 RoutingAppender's default Route can now be an appender reference.
2036 </action>
2037 <action issue="LOG4J2-313" dev="rgoers" type="add" due-to="Woonsan Ko">
2038 Add JNDILookup plugin.
2039 </action>
2040 <action issue="LOG4J2-299" dev="rgoers" type="fix">
2041 Add getThrowable method to ThrowableProxy.
2042 </action>
2043 <action issue="LOG4J2-216" dev="rgoers" type="fix">
2044 ThrowableProxy no longer extends Throwable.
2045 </action>
2046 <action issue="LOG4J2-311" dev="rpopma" type="fix">
2047 Synchronized flush() and close() methods in the XxxFileManager and OutputStreamManager classes.
2048 </action>
2049 <action issue="LOG4J2-312" dev="ggregory" type="update">
2050 XML layout improvements (compact vs. pretty, namespace, namespace prefix, root element).
2051 </action>
2052 <action issue="LOG4J2-388" dev="ggregory" type="update">
2053 Update Java Mail dependency to 1.5.0 from 1.4.7.
2054 </action>
2055 <action issue="LOG4J2-325" dev="ggregory" type="update">
2056 Update JDBC tests to use H2 database 1.3.173 from 1.3.172.
2057 </action>
2058 <action issue="LOG4J2-366" dev="ggregory" type="update">
2059 Update commons-logging to 1.1.3 from 1.1.1.
2060 </action>
2061 <action issue="LOG4J2-390" dev="ggregory" type="update">
2062 Update HSQLDB dependency to 2.3.0 from 2.2.9.
2063 </action>
2064 <action issue="LOG4J2-308" dev="rpopma" type="update">
2065 Clarified which library versions were used in Async Loggers performance test.
2066 </action>
2067 <action issue="LOG4J2-307" dev="rpopma" type="update">
2068 Updated Async Loggers' LMAX Disruptor library from 3.0.1 to 3.2.0.
2069 </action>
2070 <action issue="LOG4J2-306" dev="ggregory" type="update">
2071 Update JSON Jackson library to 2.2.2 from 2.2.1.
2072 </action>
2073 <action issue="LOG4J2-387" dev="ggregory" type="update">
2074 Update Jackson dependency to 1.9.13 from 1.9.11.
2075 </action>
2076 <action issue="LOG4J2-305" dev="ggregory" type="add">
2077 Ease porting from 1.x Logger.getRootLogger(): add LogManager.getRootLogger().
2078 </action>
2079 <action issue="LOG4J2-304" dev="rpopma" type="fix">
2080 Fixed Async Loggers memory leak.
2081 </action>
2082 <action issue="LOG4J2-291" dev="nickwilliams" type="fix">
2083 Fixed JDBC, JPA, and NoSQL appenders so that the failover appender properly fails over on error.
2084 </action>
2085 <action dev="nickwilliams" type="update">
2086 Improved site by adding quick jump-off page and menu for Javadoc links for all components.
2087 </action>
2088 <action issue="LOG4J2-397" dev="ggregory" type="fix" due-to="Yonatan Graber">
2089 Logger.info(Message) Javadoc is incorrect.
2090 </action>
2091 </release>
2092 <release version="2.0-beta8" date="2013-07-10" description="Bug fixes and enhancements">
2093 <action issue="LOG4J2-270" dev="nickwilliams" type="update">
2094 Improved logging initialization in Servlet containers, especially Servlet 3.0 and newer where Log4j now
2095 initializes and deinitializes automatically with no deployment descriptor configuration.
2096 </action>
2097 <action issue="LOG4J2-302" dev="rpopma" type="fix">
2098 Added toString methods to ThreadContextStack/Map implementation classes.
2099 </action>
2100 <action issue="LOG4J2-301" dev="rgoers" type="update">
2101 Add printf methods to Logger API.
2102 </action>
2103 <action issue="LOG4J2-300" dev="rgoers" type="fix">
2104 WriterThread was ending when no agents are available which caused an OutOfMemoryError.
2105 </action>
2106 <action issue="LOG4J2-282" dev="rgoers" type="update">
2107 Allow the default status level to be specified as a system property.
2108 </action>
2109 <action issue="LOG4J2-278" dev="rgoers" type="fix">
2110 Filter calls from Avro or Flume to be ignored by the FlumeAppender.
2111 </action>
2112 <action issue="LOG4J2-279" dev="rgoers" type="fix">
2113 FlumePersistentManager now calls Berkeley DB from threads to avoid encountering interrupts in the application.
2114 </action>
2115 <action issue="LOG4J2-296" dev="ggregory" type="fix">
2116 Wasted work in FlumePersistentManager.createManager.
2117 </action>
2118 <action issue="LOG4J2-297" dev="ggregory" type="fix">
2119 Wasted work in TestConfigurator.testEnvironment.
2120 </action>
2121 <action issue="LOG4J2-298" dev="ggregory" type="fix">
2122 Wasted work in StyleConverterTest.setupClass.
2123 </action>
2124 <action issue="LOG4J2-280" dev="rpopma" type="fix">
2125 AsyncLogger threads are now daemon threads and won't prevent the JVM from shutting down anymore.
2126 </action>
2127 <action issue="LOG4J2-295" dev="rpopma" type="fix">
2128 Fast(Rolling)FileAppender now correctly handles messages exceeding the buffer size.
2129 </action>
2130 <action issue="LOG4J2-271" dev="rpopma" type="fix">
2131 FastRollingFileAppender with TimeBasedTriggeringPolicy now works correctly if append=false.
2132 </action>
2133 <action issue="LOG4J2-267" dev="rpopma" type="fix">
2134 FastRollingFileAppender with TimeBasedTriggeringPolicy now works correctly if append=false.
2135 </action>
2136 <action issue="LOG4J2-292" dev="rpopma" type="fix">
2137 Fast(Rolling)FileAppender now correctly appends to (does not overwrite) existing file.
2138 </action>
2139 <action issue="LOG4J2-294" dev="rgoers" type="update">
2140 LogManager.getLogger can now be called without a logger name or with a null logger name.
2141 </action>
2142 <action issue="LOG4J2-289" dev="rgoers" type="fix">
2143 Upgrade javadoc plugin to 2.9.1 to fix javadoc security issue.
2144 </action>
2145 <action issue="LOG4J2-288" dev="gregory" type="update">
2146 Update JUnit to 4.11 from 4.7.
2147 </action>
2148 <action issue="LOG4J2-286" dev="gregory" type="update">
2149 Update test H2 JDBC driver to 1.172 from 1.171.
2150 </action>
2151 <action issue="LOG4J2-285" dev="gregory" type="update">
2152 Update Jansi jar to 1.11 from 1.9.
2153 </action>
2154 <action issue="LOG4J2-284" dev="gregory" type="update">
2155 Update Log4j 1 dependency to 1.2.17 from 1.2.16.
2156 </action>
2157 <action issue="LOG4J2-386" dev="gregory" type="update">
2158 Update NoSQL dependencies: lightcouch 0.0.6 from 0.0.5, mongodb 2.11.2 from 2.11.1.
2159 </action>
2160 <action issue="LOG4J2-283" dev="gregory" type="update">
2161 Remove dependency on Apache ORO jar.
2162 </action>
2163 <action issue="LOG4J2-277" dev="gregory" type="update">
2164 Wasted work in RollingAppenderSizeTest.testAppender() and others.
2165 </action>
2166 <action issue="LOG4J2-139" dev="rgoers" type="fix">
2167 Fix NullPointerException (regression due to fix for LOG4J2-228)
2168 </action>
2169 <action issue="LOG4J2-168" dev="rgoers" type="update" due-to="Scott Severtson">
2170 Include arbitrary message fields in RFC-5424 structured data.
2171 </action>
2172 <action issue="LOG4J2-275" dev="rgoers" type="fix">
2173 FlumeAvroManager fails to notify client of failing event if Flume RPCClient cannot be created.
2174 </action>
2175 <action issue="LOG4J2-274" dev="ggregory" type="update">
2176 Wasted work in UUIDUtil initialization.
2177 </action>
2178 <action issue="LOG4J2-273" dev="ggregory" type="update">
2179 Wasted work in XMLLayout.toSerializable().
2180 </action>
2181 </release>
2182 <release version="2.0-beta7" date="2013-06-01" description="Bug fixes and enhancements">
2183 <action issue="LOG4J2-249" dev="rgoers" type="update">
2184 Allow context parameters in Log4jContextListener to include properties.
2185 </action>
2186 <action issue="LOG4J2-263" dev="rgoers" type="fix">
2187 Do not allow a charset on RFC5424Layout - use UTF-8.
2188 </action>
2189 <action issue="LOG4J2-242" dev="rgoers" type="fix">
2190 StringFormattedMessage and MessageFormatMessage now will accept a Throwable as their last argument and
2191 pass it on.
2192 </action>
2193 <action issue="LOG4J2-243" dev="rgoers" type="update">
2194 Allow custom LogEventFactories.
2195 </action>
2196 <action issue="LOG4J2-262" dev="rgoers" type="update" due-to="Edward Sargisson">
2197 Add support for interceptors in the embedded Flume Appender.
2198 </action>
2199 <action issue="LOG4J2-269" dev="rgoers" type="fix">
2200 Use transaction when batch size is 1.
2201 </action>
2202 <action issue="LOG4J2-268" dev="rgoers" type="fix">
2203 Add guid to FlumeEvent headers for non-Map Messages.
2204 </action>
2205 <action issue="LOG4J2-246" dev="rgoers" type="fix">
2206 Data buffer is reset in finally clause.
2207 </action>
2208 <action issue="LOG4J2-228" dev="rgoers" type="fix">
2209 UDP now sends one event per packet.
2210 </action>
2211 <action dev="rpopma" type="update">
2212 Method name changes in interface org.apache.logging.log4j.spi.ThreadContextMap:
2213 getContext() to getCopy(), get() to getImmutableMapOrNull().
2214 </action>
2215 <action issue="LOG4J2-154" dev="rpopma" type="update">
2216 Improve ThreadContext performance with copy-on-write map and stack.
2217 </action>
2218 <action issue="LOG4J2-261" dev="rgoers" type="fix" due-to="Edward Sargisson">
2219 Add missing "not" to error message.
2220 </action>
2221 <action issue="LOG4J2-10" dev="rgoers" type="add" due-to="Timothy Ward">
2222 Break up core into multiple osgi jars.
2223 </action>
2224 <action issue="LOG4J2-223" dev="rgoers" type="fix">
2225 Remove LoggerContext when LoggerContext is stopped.
2226 </action>
2227 <action issue="LOG4J2-260" dev="ggregory" type="fix">
2228 XML layout does not specify charset in content type.
2229 </action>
2230 <action issue="LOG4J2-259" dev="ggregory" type="fix">
2231 HTML layout does not specify charset in content type.
2232 </action>
2233 <action issue="LOG4J2-258" dev="ggregory" type="fix">
2234 HTML layout does not output meta element for charset.
2235 </action>
2236 <action issue="LOG4J2-257" dev="ggregory" type="fix">
2237 XML layout ignores charset for the XML processing intruction's encoding attribute.
2238 </action>
2239 <action issue="LOG4J2-255" dev="rpopma" type="fix">
2240 Multi-byte character strings are now assumed to be in the platform default encoding, not UTF-8.
2241 </action>
2242 <action issue="LOG4J2-254" dev="rgoers" type="fix">
2243 Mark OutputStream in OutputStreamManager as volatile. Mark header and footer as final.
2244 </action>
2245 <action issue="LOG4J2-244" dev="rgoers" type="fix">
2246 Rewrite Appender was ignoring filters on referenced appenders.
2247 </action>
2248 <action issue="LOG4J2-245" dev="rgoers" type="fix">
2249 Avoid EmptyStack exception if getCallerClass and SecurityManager are not available.
2250 </action>
2251 <action issue="LOG4J2-229" dev="ggregory" type="add" due-to="Nick Williams">
2252 New JDBC, JPA, and NoSQL database Appenders.
2253 </action>
2254 <action issue="LOG4J2-247" dev="ggregory" type="fix">
2255 SocketServer.isActive should be volatile because it is accessed from different threads.
2256 </action>
2257 <action issue="LOG4J2-251" dev="sdeboy" type="add">
2258 Provide configuration information (location, content type, content if possible) via a registered Advertiser.
2259 </action>
2260 </release>
2261 <release version="2.0-beta6" date="2013-05-05" description="Bug fixes and enhancements">
2262 <action issue="LOG4J2-231" dev="rgoers" type="fix">
2263 Logger.getParent() was not returning the correct Logger.
2264 </action>
2265 <action issue="LOG4J2-201" dev="rgoers" type="fix">
2266 Renamed Plugin annotation attribute from "type" to "category".
2267 </action>
2268 <action issue="LOG4J2-237" dev="rpopma" type="update">
2269 Moved JMX Client GUI classes into separate jmx-gui submodule.
2270 </action>
2271 <action issue="LOG4J2-219" dev="rpopma" type="fix" due-to="Peter DePasquale">
2272 Fix: install default root logger if not configured (this is unchanged),
2273 but make sure to include configured named loggers. Clarified documentation.
2274 </action>
2275 <action issue="LOG4J2-159" dev="rgoers" type="fix">
2276 Use OSGi version format in Fragment-Host
2277 </action>
2278 <action issue="LOG4J2-234" dev="rgoers" type="fix">
2279 RegexFilter threw a NullPointerException when used as a context-wide filter.
2280 </action>
2281 <action issue="LOG4J2-192" dev="rgoers" type="fix">
2282 Add support for interpolating Environment variables when processing the configuration.
2283 </action>
2284 <action issue="LOG4J2-235" dev="rpopma" type="fix" due-to="Sebastian Oerding">
2285 Removed dependency on tools jar from core module, made jconsole dependency optional.
2286 </action>
2287 <action issue="LOG4J2-233" dev="rpopma" type="fix">
2288 Fixed link to log4j-user mailing list.
2289 </action>
2290 <action issue="LOG4J2-230" dev="rpopma" type="update" due-to="Wojciech Zaręba">
2291 Improved error reporting when misconfigured.
2292 </action>
2293 <action issue="LOG4J2-222" dev="rgoers" type="fix" due-to="Steven Yang">
2294 Disruptor will now shutdown during Tomcat shutdown.
2295 </action>
2296 <action dev="rpopma" type="update">
2297 Renamed AsynchAppender to AsyncAppender. Plugin name became Async (was Asynch).
2298 </action>
2299 <action dev="rpopma" type="update">
2300 Removed CheckStyle false positives for NewlineAtEndOfFile and whitespace following '*' at end of line in javadoc.
2301 </action>
2302 <action dev="rpopma" type="update">
2303 Moved Clock interface to package org.apache.logging.log4j.core.helpers.
2304 </action>
2305 <action issue="LOG4J2-225" dev="rpopma" type="update">
2306 Documentation updates to clarify use and impact of location in pattern layouts.
2307 </action>
2308 <action issue="LOG4J2-224" dev="rgoers" type="fix">
2309 The FlumeAppender failed to start if the Flume RPCClient could not connect to any Flume agents.
2310 </action>
2311 <action issue="LOG4J2-223" dev="rgoers" type="fix">
2312 Fix LoggerContext start and stop to eliminate IllegalStateException and NoClassDefFound errors.
2313 </action>
2314 <action issue="LOG4J2-221" dev="rgoers" type="fix" due-to="Nick Williams">
2315 Remove hundreds of compiler warnings.
2316 </action>
2317 <action issue="LOG4J2-215" dev="rpopma" type="fix">
2318 Various small documentation fixes.
2319 </action>
2320 <action issue="LOG4J2-217" dev="rpopma" type="fix" due-to="Fabien Sanglard">
2321 Ensure PluginManager streams are always closed.
2322 </action>
2323 </release>
2324 <release version="2.0-beta5" date="2013-04-20" description="Bug fixes and enhancements">
2325 <action issue="LOG4J2-205" dev="rgoers" type="fix">
2326 Fix deadlock in SocketAppender. Added option to not wait for socket reconnect.
2327 </action>
2328 <action issue="LOG4J2-207" dev="rgoers" type="add" due-to="Remko Popma">
2329 Add JMX support.
2330 </action>
2331 <action issue="LOG4J2-211" dev="rgoers" type="fix" due-to="Nick Williams">
2332 Removing extra spaces in entry and exit method output.
2333 </action>
2334 <action issue="LOG4J2-214" dev="rgoers" type="update" due-to="Remko Popma">
2335 Async documentation update.
2336 </action>
2337 <action issue="LOG4J2-212" dev="rgoers" type="fix">
2338 Loggers without a "." had no parent logger.
2339 </action>
2340 <action issue="LOG4J2-208" dev="rgoers" type="update" due-to="Remko Popma">
2341 Move async subproject into core.
2342 </action>
2343 <action issue="LOG4J2-212" dev="rgoers" type="fix">
2344 Call LoggerContext.stop when the application is shutdown.
2345 </action>
2346 <action issue="LOG4J2-210" dev="rgoers" type="fix" due-to="Arkin Yetis">
2347 MapMessage was not enclosing key value in quotes when generating XML.
2348 </action>
2349 <action issue="LOG4J2-198" dev="rgoers" type="fix">
2350 FlumeAvroManager now uses Flume RPCClient.
2351 </action>
2352 <action issue="LOG4J2-196" dev="rgoers" type="fix">
2353 FlumeAvroManager now uses Flume RPCClient.
2354 </action>
2355 <action issue="LOG4J2-207" dev="ggregory" type="fix">
2356 Use the Maven group ID org.apache.logging.log4j for all artifacts.
2357 </action>
2358 <action issue="LOG4J2-187" dev="rgoers" type="add" due-to="Nick Williams">
2359 Add tag library.
2360 </action>
2361 <action issue="LOG4J2-195" dev="rgoers" type="fix" due-to="Remko Popma">
2362 Unit tests now create files in the target directory.
2363 </action>
2364 <action issue="LOG4J2-193" dev="rgoers" type="fix" due-to="Remko Popma">
2365 RollingFastFileAppender (in log4j-async) did not roll over.
2366 </action>
2367 <action issue="LOG4J2-199" dev="rgoers" type="fix" due-to="Remko Popma">
2368 Highlight subprojects in sub-navigation.
2369 </action>
2370 <action issue="LOG4J2-200" dev="rgoers" type="fix" due-to="Remko Popma">
2371 LoggerContext method renamed to removeFilter from removeFiler.
2372 </action>
2373 <action issue="LOG4J2-194" dev="rgoers" type="fix" due-to="Remko Popma">
2374 ThrowableFormatOptionsTest failed on Windows due to CR/LF issue.
2375 </action>
2376 <action issue="LOG4J2-190" dev="rgoers" type="fix" due-to="Werner">
2377 BaseConfiguration addLoggerAppender saved appender using the Logger name.
2378 </action>
2379 <action issue="LOG4J2-160" dev="rgoers" type="update" due-to="Joanne Polsky">
2380 Move Throwable pattern converter options processing to ThrowableFormatOptions class.
2381 </action>
2382 <action issue="LOG4J2-157" dev="rgoers" type="update" due-to="Remko Popma">
2383 Allowed Loggers access to the properties in the LoggerConfig.
2384 </action>
2385 <action issue="LOG4J2-153" dev="rgoers" type="update" due-to="Remko Popma">
2386 Added ability to include or exclude location information.
2387 </action>
2388 <action issue="LOG4J2-151" dev="rgoers" type="update" due-to="Remko Popma">
2389 Allow Logger and LoggerContext to be subclassed.
2390 </action>
2391 <action issue="LOG4J2-164" dev="rgoers" type="add" due-to="Remko Popma">
2392 Add methods is/setEndOfBatch to LogEvent.
2393 </action>
2394 <action issue="LOG4J2-163" dev="rgoers" type="add" due-to="Remko Popma">
2395 Add support for asynchronous loggers.
2396 </action>
2397 <action issue="LOG4J2-189" dev="rgoers" type="fix" due-to="Werner">
2398 The blocking parameter did not work properly on AsynchAppender.
2399 </action>
2400 <action issue="LOG4J2-188" dev="rgoers" type="fix" due-to="Werner">
2401 AppenderRefs on AsynchAppender didn't support the level and filter elements.
2402 </action>
2403 <action issue="LOG4J2-176" dev="rgoers" type="fix" due-to="Remko Popma">
2404 Avoid IllegalArgumentException in AsynchAppender.
2405 </action>
2406 <action issue="LOG4J2-179" dev="ggregory" type="add">
2407 Add Logger interface APIs to log at given levels.
2408 </action>
2409 <action issue="LOG4J2-181" dev="rgoers" type="fix">
2410 OutputStreamManager now adds the layout header whenever the OutputStream is set.
2411 </action>
2412 <action issue="LOG4J2-177" dev="rgoers" type="fix" due-to="Remko Popma">
2413 Fix NullPointerException in DatagramOutputStream when flush is called from multiple threads.
2414 </action>
2415 <action dev="rgoers" type="add">
2416 Added FlumePersistentManager which writes to BerkeleyDB and then writes to Flume asynchronously.
2417 </action>
2418 <action issue="LOG4J2-175" dev="sdeboy" type="fix">
2419 Plugin cache should be reset when addPackages is called.
2420 </action>
2421 <action issue="LOG4J2-155" dev="sdeboy" type="add">
2422 Expose file appender configuration details via an advertisement mechanism.
2423 </action>
2424 <action issue="LOG4J2-159" dev="rgoers" type="fix" due-to="Jan Winter">
2425 Add Fragment-Host to MANIFEST.MF for log4j-core.
2426 </action>
2427 <action issue="LOG4J2-167" dev="rgoers" type="fix">
2428 Configurator throws a ClassCastException if LogManager returns a SimpleLoggerContext.
2429 </action>
2430 <action issue="LOG4J2-169" dev="rgoers" type="fix">
2431 ConfigurationFactory was adding factories on every call.
2432 </action>
2433 <action issue="LOG4J2-161" dev="rgoers" type="fix">
2434 Modify ClassLoaderContextSelector to use the first ClassLoader in the child parent hierarchy that
2435 has a Context with a configuration to allow JSPs to use the WebApp's context and configuration.
2436 </action>
2437 <action issue="LOG4J2-158" dev="rgoers" due-to="Scott Severtson">
2438 Add RFC 5424 compliant escaping rules to RFC5424Layout.
2439 </action>
2440 </release>
2441 <release version="2.0-beta4" date="2013-01-28" description="Bug fixes and enhancements">
2442 <action issue="LOG4J2-156" dev="ggregory" type="fix" due-to="Andreas Born">
2443 LocalizedMessageTest fails on linux system.
2444 </action>
2445 <action issue="LOG4J2-152" dev="rgoers" type="fix" due-to="Remko Popma">
2446 RollingFileAppender's FileRenameAction was throwing a NullPointerException if no directory was specified
2447 on the target file name.
2448 </action>
2449 <action issue="LOG4J2-150" dev="rgoers" type="fix">
2450 Convert all System.getProperty calls to use PropertiesUtil to suppress SecurityExceptions.
2451 </action>
2452 <action issue="LOG4J2-147" dev="rgoers" type="fix" due-to="William Burns">
2453 ThreadContextMapFilter was matching on the key instead of the value of the key.
2454 </action>
2455 <action dev="rgoers" type="fix">
2456 Allow FlumeAvroManager to initialize even if it cannot connect to an agent.
2457 </action>
2458 <action issue="LOG4J2-149" dev="rgoers" type="fix" due-to="Scott Severtson">
2459 SMTPAppender will only cache filtered events.
2460 </action>
2461 <action issue="LOG4J2-145" dev="ggregory" type="fix">
2462 Add missing serial version IDs.
2463 </action>
2464 <action issue="LOG4J2-144" dev="ggregory" type="fix">
2465 NullPointerException in RFC5424Layout.
2466 </action>
2467 <action issue="LOG4J2-143" dev="rgoers" type="fix">
2468 MessagePatternConverter now returns "null" if the log message is null.
2469 </action>
2470 <action issue="LOG4J2-142" dev="rgoers" type="fix">
2471 Serialized LogEvents were not reset in the output stream causing them to deserialize incorrectly.
2472 </action>
2473 <action issue="LOG4J2-139" dev="rgoers" type="fix">
2474 Fix null pointer exception in SocketAppender if no protocol is specified. The protocol will default
2475 to TCP for the SocketAppender and UDP for the SyslogAppender.
2476 </action>
2477 <action dev="rgoers" type="add">
2478 Added Log4j 2 to SLF4J adapter.
2479 </action>
2480 <action issue="LOG4J2-140" dev="ggregory" type="fix" due-to="Joern Huxhorn">
2481 Typo in documentation of SocketAppender.
2482 </action>
2483 <action issue="LOG4J2-137" dev="rgoers" type="fix">
2484 Fix hang in Dumbster SMTP test server.
2485 </action>
2486 <action issue="LOG4J2-136" dev="rgoers" type="update" due-to="Scott Severtson">
2487 Allow newlines to be escaped in Syslog and RFC5424 layouts. Allow Throwables to be included in
2488 the output from RFC5424Layout.
2489 </action>
2490 <action issue="LOG4J2-131" dev="rgoers" type="add" due-to="Scott Severtson">
2491 Add SMTPAppender.
2492 </action>
2493 <action issue="LOG4J2-130" dev="rgoers" type="fix">
2494 PatternLayout should format throwables without requiring a converter.
2495 </action>
2496 <action dev="rgoers" type="add">
2497 Added hostName and contextName to property map.
2498 </action>
2499 <action issue="LOG4J2-135" dev="ggregory" type="fix" due-to="Ingo Feltes">
2500 BaseConfiguration does not close the first appender.
2501 </action>
2502 <action dev="rgoers" type="add">
2503 Add MessageFormatMessage and FormattedMessage.
2504 </action>
2505 <action issue="LOG4J2-134" dev="ggregory" type="add">
2506 Use %red, %white, %blue, and so on in the console appender.
2507 </action>
2508 <action issue="LOG4J2-133" dev="ggregory" type="add">
2509 Allow custom message creation via a message factory.
2510 </action>
2511 <action issue="LOG4J2-132" dev="ggregory" type="fix">
2512 AbstractLogger.catching(Throwable) checks for DEBUG level but logs at ERROR level.
2513 </action>
2514 <action issue="LOG4J2-129" dev="rgoers" type="fix">
2515 RoutingAppender was only creating a single appender for the default Route.
2516 </action>
2517 <action issue="LOG4J2-126" dev="rgoers" type="fix">
2518 Allow JMS appenders to recover if the queue or topic is unavailable.
2519 </action>
2520 <action issue="LOG4J2-128" dev="rgoers" type="update">
2521 Add follow attribute to Console Appender.
2522 </action>
2523 <action issue="LOG4J2-127" dev="rgoers" type="fix">
2524 AbstractLogger methods were not passing Markers to the isEnabled methods.
2525 </action>
2526 <action dev="rgoers" type="add">
2527 Added Flume Appender samples.
2528 </action>
2529 <action issue="LOG4J2-122" dev="rgoers" type="update">
2530 Add unit test to verify exceptions are thrown when the socket connection fails.
2531 </action>
2532 <action issue="LOG4J2-125" dev="rgoers" type="fix">
2533 JMSQueue and JMSTopic Appenders did not allow name to be specified.
2534 </action>
2535 <action issue="LOG4J2-111" dev="rgoers" type="fix">
2536 Enhanced javadoc copyright statement.
2537 </action>
2538 <action issue="LOG4J2-110" dev="rgoers" type="update">
2539 Renamed log4j12-api to log4j-1.2-api.
2540 </action>
2541 <action issue="LOG4J2-120" dev="rgoers" type="fix">
2542 TCPSocketManager would fail if the initial connection could not be established.
2543 </action>
2544 <action issue="LOG4J2-119" dev="rgoers" type="fix">
2545 A broken socket connection would cause the TCPSocketManager to continuously reconnect.
2546 </action>
2547 <action issue="LOG4J2-123" dev="rgoers" type="fix" due-to="Olivier Lamy">
2548 The example for ThreadContextMapFilter was incorrect.
2549 </action>
2550 <action issue="LOG4J2-116" dev="rgoers" type="fix">
2551 File renaming was using the wrong date value. Enhanced DefaultRolloverStrategy to store newest files in
2552 highest index as well as lowest.
2553 </action>
2554 <action issue="LOG4J2-115" dev="rgoers" type="fix">
2555 ThreadContext Map elements with null values are now ignored when constructing a Flume event and in the
2556 RFC5424 Layout.
2557 </action>
2558 <action issue="LOG4J2-113" dev="rgoers" type="fix">
2559 StructuredDataFilter createFilter was annotated with PluginAttr instead of PluginElement for the
2560 KeyValuePairs.
2561 </action>
2562 <action issue="LOG4J2-114" dev="rgoers" type="fix" due-to="Arkin Yetis">
2563 StructuredDataMessage was validating the length of the values in the event Map instead of the lengths
2564 of the keys.
2565 </action>
2566 </release>
2567 <release version="2.0-beta3" date="2012-11-11" description= "Bug fixes and enhancements">
2568 <action issue="LOG4J2-108" dev="rgoers" type="fix">
2569 Fix NullPointerException in ClassLoaderContextSelector when no class is returned from
2570 the SecurityManager.
2571 </action>
2572 <action issue="LOG4J2-105" dev="rgoers" type="update">
2573 Add ability to customize the names of the Levels in the LevelPatternConverter.
2574 </action>
2575 <action issue="LOG4J2-107" dev="rgoers" type="fix">
2576 PatternParser was not properly handling adjacent nested options
2577 </action>
2578 <action issue="LOG4J2-95" dev="rgoers" type="fix">
2579 Add support for loading plugins inside the OSGi bundle.
2580 </action>
2581 <action issue="LOG4J2-85" dev="rgoers" type="update">
2582 Add ThreadContext.push(String format, Object... args)
2583 </action>
2584 <action issue="LOG4J2-103" dev="rgoers" type="fix" due-to="Das Archive">
2585 The LogEvent was wrapping a ThrowableProxy with another ThrowableProxy when deserializing.
2586 </action>
2587 <action dev="rgoers" type="update">
2588 Created combined jar to combine API and Core contents for users who only want the Log4j implementation.
2589 </action>
2590 <action issue="LOG4J2-104" dev="rgoers" type="fix">
2591 Convert LogManager binding to use "regular" java properties instead of XML properties to workaround a
2592 bug in Oracle's xmlparserv2 jar.
2593 </action>
2594 <action issue="LOG4J2-28" dev="rgoers" type="add">
2595 Added PropertiesRewritePolicy and ability to define properties on a Logger.
2596 </action>
2597 <action issue="LOG4J2-87" dev="rgoers" type="update">
2598 Build pdf of user's guide.
2599 </action>
2600 <action issue="LOG4J2-29" dev="rgoers" type="update">
2601 Added font and fontSize parameters to HTMLLayout. Replace newlines in message with br tag.
2602 </action>
2603 <action issue="LOG4J2-55" dev="rgoers" type="add">
2604 Added ability to configure from an InputSource.
2605 </action>
2606 <action issue="LOG4J2-102" dev="rgoers" type="fix" due-to="Emanuele Colombo">
2607 The Facility value was being improperly calculated.
2608 </action>
2609 <action issue="LOG4J2-101" dev="rgoers" type="fix" due-to="Emanuele Colombo">
2610 A NullPointerException would occur if no format value was passed to the SyslogAppender.
2611 </action>
2612 <action issue="LOG4J2-99" dev="rgoers" type="fix" due-to="Das Archive">
2613 MapRewritePolicy had an extra call to putAll that caused updates to behave like adds.
2614 </action>
2615 <action dev="rgoers" type="fix">
2616 Avoid NPE when duplicate LoggerContextFactorys are present. Allow factories to specify a weight to allow
2617 real implementations to outrank test implementations. Provide a simple default LoggerContextFactory.
2618 </action>
2619 <action issue="LOG4J2-97" dev="rgoers" type="fix">
2620 Added several missing classes and methods for Log4j 1.x compatibility.
2621 </action>
2622 <action issue="LOG4J2-94" dev="rgoers" type="fix" due-to="Denis Treskunov">
2623 Interpolator was not stripping Lookup key separator when trying to locate the default value for a variable.
2624 </action>
2625 <action dev="rgoers" type="fix">
2626 Log4j 1.2 Category.forcedLog was wrapping the message with an ObjectMessage even if the parameter was an
2627 ObjectMessage.
2628 </action>
2629 </release>
2630 <release version="2.0-beta2" date="2012-10-07" description="Bug fixes and enhancements">
2631 <action dev="rgoers" type="update">
2632 Made ParameterizedMessage, StringFormattedMessage and ThreadDumpMessage immutable. LocalizedMessage is
2633 immutable except that it will be updated with the logger name when it is added to the LogEvent.
2634 </action>
2635 <action dev="rgoers" type="fix">
2636 DefaultConfiguration was not starting the Console Appender.
2637 </action>
2638 <action issue="LOG4J2-35" dev="rgoers" type="add">
2639 Add interval and modulate options to TimeBasedTriggeringPolicy to allow more fine-grained control of
2640 when file rolling should occur.
2641 </action>
2642 <action issue="LOG4J2-58" dev="rgoers" type="add">
2643 Add support for filtering packages from stack traces.
2644 </action>
2645 <action issue="LOG4J2-84" dev="rgoers" type="add">
2646 If system property "disableThreadContextStack" is set pushes to the ThreadContext will be ignored. If
2647 system property "disableThreadContext" is set both puts and pushes will be ignored.
2648 </action>
2649 <action issue="LOG4J2-83" dev="rgoers" type="add">
2650 If system property "disableThreadContextMap" is set puts to the ThreadContext will be ignored. If
2651 system property "disableThreadContext" is set both puts and pushes will be ignored.
2652 </action>
2653 <action dev="rgoers" type="add">
2654 Add support for ANSI colors by adding the highlight and style pattern converters. Fix pattern
2655 parsing to allow nested patterns.
2656 </action>
2657 <action issue="LOG4J2-92" dev="rgoers" type="fix">
2658 Converted DynamicThresholdFilter to use KeyValuePair. Fixed bugs in the Map-based filters
2659 to allow declaration of multiple values for a key to match the documentation.
2660 </action>
2661 <action issue="LOG4J2-88" dev="rgoers" type="fix">
2662 Many logging methods in AbstractLogger were set to an incorrect logging level. catching was
2663 using the THROWING marker and was set to debug instead of error.
2664 </action>
2665 <action dev="rgoers" type="add">
2666 Allow the status logging to be directed to stderr or to a file.
2667 </action>
2668 <action issue="LOG4J2-91" dev="rgoers" type="fix">
2669 Log4j 1.2 adapter's Category class was missing 3 log methods.
2670 </action>
2671 <action issue="LOG4J2-84" dev="rgoers" type="fix">
2672 If the ThreadContext stack is empty the LogEvent will contain a null value to reduce the overhead of
2673 creating log events and in the size of the serialized object. Changed the ThreadContext stack to use
2674 a custom stack interface instead of java.util.Stack as that class is overly heavy. This change will
2675 cause an API incompatibility.
2676 </action>
2677 <action issue="LOG4J2-83" dev="rgoers" type="fix">
2678 If the ThreadContext map is empty the LogEvent will contain a null value to reduce the overhead of creating
2679 log events and in the size of the serialized object.
2680 </action>
2681 <action dev="rgoers" type="add">
2682 Add getFormats to MultiformatMessage and allow StructuredDataMessage to format as XML.
2683 </action>
2684 <action issue="LOG4J2-90" dev="rgoers" type="fix">
2685 Add documentation on client vs server mode to performance page.
2686 </action>
2687 <action dev="rgoers" type="fix">
2688 Move variable substitution from PatternLayout to appropriate converters to improve performance.
2689 </action>
2690 </release>
2691 <release version="2.0-beta1" date="2012-09-18" description="Bug fixes and enhancements">
2692 <action dev="rgoers" type="add">
2693 Added AsynchAppender.
2694 </action>
2695 <action issue="LOG4J-81" dev="rgoers" type="fix">
2696 PatternLayout was not honoring format modifiers.
2697 </action>
2698 <action dev="rgoers" type="fix">
2699 Created web module to allow web applications to include the Log4j context listener in WEB-INF/lib even if
2700 Log4j is in the container's class path. Allow locating the LoggerContext to include the ClassLoader. Updated
2701 the Loader utility to always choose the child ClassLoader. Verified in Jboss 5 and Tomcat.
2702 </action>
2703 <action issue="LOG4J2-82" dev="rgoers" type="fix">
2704 MarkerFilter called MarkerManager.getMarker causing the Marker to be created during the processing of the
2705 configuration. This prevents the application from creating the Marker with any parents. MarkerWrapper in
2706 SLF4J-impl was getting a ClassCastException in instanceOf because the Marker isn't a MarkerWrapper.
2707 </action>
2708 <action issue="LOG4J2-80" dev="rgoers" type="fix" due-to="Oliver Lamy">
2709 Allow Log4j 2 to be used as the implementation with SLF4J and SLF4J's jcl-over-slf4j by adding filtering
2710 to the log method in SLF4JLogger.
2711 </action>
2712 <action issue="LOG4J2-78" dev="rgoers" type="fix">
2713 LogFactoryImpl.setAttribute in the Commons Logging bridge got a NullPointerException when passed a null value.
2714 It will now remove the attribute.
2715 </action>
2716 <action issue="LOG4J2-77" dev="rgoers" type="fix">
2717 RoutingAppender was calling the stop method for each of its referenced Appenders and was calling
2718 the stop method of the default Appender a second time. It will now only call the stop method of
2719 Appenders it creates.
2720 </action>
2721 <action issue="LOG4J2-76" dev="rgoers" type="fix">
2722 RewriteAppender was calling the stop method of the referenced appender causing the referenced appender's
2723 manager to have its use count decremented too many times.
2724 </action>
2725 <action issue="LOG4J2-74" dev="rgoers" type="fix">
2726 Logger.error(Marker, Message, Throwable) was internally using Level.TRACE.
2727 </action>
2728 <action issue="LOG4J2-75" dev="rgoers" type="fix">
2729 Enhanced Log4jContextListener to accept a configuration file location. Modified FileConfigurationMonitor
2730 to monitor files configured that way. Fixed other reconfiguration related bugs. Tested in JBoss and
2731 Tomcat.
2732 </action>
2733 <action issue="LOG4J2-72" dev="rgoers" type="fix">
2734 NullPointerException in RollingFileManager when filePattern does not cause the file to be compressed.
2735 </action>
2736 <action issue="LOG4J2-71" dev="rgoers" type="fix">
2737 FileRenameAction did not create the parent directories of the archive files causing the rollover to fail.
2738 </action>
2739 <action dev="rgoers" type="update">
2740 Update the versions of SLF4J and Logback.
2741 </action>
2742 </release>
2743 <release version="2.0-alpha2" date="2012-08-24" description="Bug fixes and minor enhancements">
2744 <action issue="LOG4J2-70" dev="rgoers" type="add">
2745 Add getLogger(Class) to LogManager.
2746 </action>
2747 <action issue="LOG4J2-69" dev="rgoers" type="add">
2748 Allow Flume agents to be embedded into the Flume Appender.
2749 </action>
2750 <action issue="LOG4J2-68" dev="rgoers" type="add">
2751 Add support for formatting using String.format().
2752 </action>
2753 <action issue="LOG4J2-67" dev="rgoers" type="add">
2754 Allow components besides core to create a PluginMap for faster plugin loading and not
2755 having to specify the plugin package in the configuration.
2756 </action>
2757 <action issue="LOG4J2-64" dev="rgoers" type="fix">
2758 Fix compilation problems in Java 7.
2759 </action>
2760 <action issue="LOG4J2-65" dev="rgoers" type="fix">
2761 Allow variable substitution on the configuration attributes and on the root log level.
2762 </action>
2763 </release>
2764 <release version="2.0-alpha1" date="2012-07-29" description="Rewrite of Log4j">
2765 <action issue="LOG4J2-60" dev="rgoers" type="add" due-to="Shane Kelly">
2766 Added ability to filter on the AppenderRef by adding either a level or a filter.
2767 </action>
2768 <action issue="LOG4J2-56" dev="rgoers" type="fix" due-to="John Owen Atala">
2769 Level.toLevel would throw an IllegalArgumentException instead of returning the default value.
2770 </action>
2771 <action issue="LOG4J2-51" dev="rgoers" type="fix" due-to="John Vasileff">
2772 Remove LoggerContext support for custom logger factories. All Loggers returned
2773 by LoggerContext should be compatibile and of the same type.
2774 </action>
2775 <action issue="LOG4J2-50" dev="rgoers" type="fix" due-to="John Vasileff">
2776 Make sure all application facing log methods use their own FQCN. This patch
2777 resolves a unit test failure for the %C pattern when using the Category logger.
2778 </action>
2779 </release>
2780 </body>
2781 </document>
0 <?xml version="1.0" encoding="UTF-8"?>
1 <!-- vi: set sw=2: -->
2 <!--
3 Licensed to the Apache Software Foundation (ASF) under one or more
4 contributor license agreements. See the NOTICE file distributed with
5 this work for additional information regarding copyright ownership.
6 The ASF licenses this file to You under the Apache License, Version 2.0
7 (the "License"); you may not use this file except in compliance with
8 the License. You may obtain a copy of the License at
9
10 http://www.apache.org/licenses/LICENSE-2.0
11
12 Unless required by applicable law or agreed to in writing, software
13 distributed under the License is distributed on an "AS IS" BASIS,
14 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 See the License for the specific language governing permissions and
16 limitations under the License.
17 -->
18 <document xmlns="http://maven.apache.org/changes/1.0.0"
19 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
20 xsi:schemaLocation="http://maven.apache.org/changes/1.0.0 http://maven.apache.org/xsd/changes-1.0.0.xsd">
21 <properties>
22 <title>Changes</title>
23 </properties>
24 <body>
25 <release version="2.7" date="2016-10-02" description="GA Release 2.7">
26 <action issue="LOG4J2-1618" dev="rpopma" type="fix" due-to="Raman Gupta">
27 Fixed ClassCastException when using JUL logging during shutdown.
28 </action>
29 <action issue="LOG4J2-1620" dev="ggregory" type="fix" due-to="Sascha Scholz">
30 2.7-rc1: RollingFileAppender immediateFlush default value should be true, not false.
31 </action>
32 <action issue="LOG4J2-1611" dev="rpopma" type="fix">
33 Improved performance of context data injector for web applications to be on par with standalone applications.
34 </action>
35 <action issue="LOG4J2-1591" dev="rpopma" type="fix">
36 Introduced new interface LifeCycle2 with stop(long,TimeUnit) method to avoid breaking backwards compatibility with new Configurator.shutdown(LoggerContext, long, TimeUnit) API.
37 </action>
38 <action issue="LOG4J2-1590" dev="rpopma" type="fix">
39 Fixed issue with filters extending AbstractFilter that did not override methods with unrolled varargs.
40 </action>
41 <action issue="LOG4J2-1583" dev="rpopma" type="fix" due-to="Larry West">
42 Fixed scrambled log messages triggered by nested logging from toString() method of a logging parameter object.
43 </action>
44 <action issue="LOG4J2-1259" dev="ggregory" type="fix" due-to="Misagh Moayyed, Steffen Offermann">
45 Log4j threads are no longer leaking on Tomcat shutdown.
46 </action>
47 <action issue="LOG4J2-1051" dev="rpopma" type="fix" due-to="Lukasz Lenart">
48 When starting on Google App Engine, Interpolator now suppresses the NoClassDefFoundError stack trace for the jvmrunargs lookup.
49 </action>
50 <action issue="LOG4J2-1582" dev="rpopma" type="fix">
51 When initializing on platforms where JMX is not available, Interpolator component no longer prints stack trace for warning messages.
52 </action>
53 <action issue="LOG4J2-1581" dev="rpopma" type="fix">
54 Unregistering JMX components no longer prints a stack trace when the MBean has already been unregistered.
55 </action>
56 <action issue="LOG4J2-1313" dev="rpopma" type="fix" due-to="Philipp Knobel, Leon Finker">
57 Support Property values to be specified in configuration as a value attribute as well as an element.
58 </action>
59 <action issue="LOG4J2-1575" dev="rpopma" type="fix">
60 (GC) LoggerConfig now stores configuration properties in a List, not a Map to prevent creating temporary Iterator objects. Added method LoggerConfig#getPropertyList(), deprecated method #getProperties().
61 </action>
62 <action issue="LOG4J2-1457" dev="mattsicker" type="fix" due-to="Leon Finker">
63 Fixed class loader deadlock when using async logging and extended stack trace pattern.
64 </action>
65 <action issue="LOG4J2-1563" dev="ggregory" type="fix" due-to="Jason Tedor">
66 Fix to prevent Log4j 2.6.2 and higher from losing exceptions when a security manager is present.
67 </action>
68 <action issue="LOG4J2-1530" dev="mikes" type="fix">
69 Fixed issue where LogEvent.getContextStack() returned null.
70 </action>
71 <action issue="LOG4J2-1518" dev="rpopma" type="fix" due-to="Leon Finker">
72 Prevent deadlock in Async Loggers when queue is full and logged Object's toString() logs another message.
73 </action>
74 <action issue="LOG4J2-1542" dev="rpopma" type="fix" due-to="Rogério Lecarião Leite">
75 Prevent ArrayIndexOutOfBoundsException in ParameterizedMessage.formatTo for single-char or empty messages.
76 </action>
77 <action issue="LOG4J2-1549" dev="mikes" type="fix" due-to="Jason Bedard">
78 Fixed issue where AsyncLoggerContextSelector+PropertiesConfigurationBuilder defaulted to includeLocation=true.
79 </action>
80 <action issue="LOG4J2-1562" dev="ggregory" type="fix">
81 Prevent SocketAppender memory usage from growing unbounded if it cannot connect to a server.
82 </action>
83 <action issue="LOG4J2-1559" dev="ggregory" type="fix" due-to="Andrey Plotkin">
84 Prevent NPE in Level.isInRange.
85 </action>
86 <action issue="LOG4J2-1511" dev="ggregory" type="fix" due-to="Srikanth Surukuntu">
87 DynamicThresholdFilter filtered incorrectly when params were passed as individual arguments instead of varargs.
88 </action>
89 <action issue="LOG4J2-1548" dev="ggregory" type="fix">
90 [CronTriggeringPolicy] ConfigurationScheduler scheduled the task infinitely after first fire.
91 </action>
92 <action issue="LOG4J2-1506" dev="ggregory" type="fix" due-to="Johannes Schleger">
93 Log4j should not unregister JMX MBeans when log4j2.disable.jmx property is true.
94 </action>
95 <action issue="LOG4J2-1490" dev="ggregory" type="fix" due-to="Krzysztof Taborski">
96 Log4j2 should postpone creating log file until the appender actually receives an event.
97 </action>
98 <action issue="LOG4J2-1320" dev="ggregory" type="fix" due-to="Paresh Varke, Pierrick Hymbert">
99 Support loading custom plugins from jar files and directories whose classpath entries use the "vfs" URL protocol.
100 </action>
101 <action issue="LOG4J2-1541" dev="ggregory" type="fix">
102 Fix file handle resource leak in XmlConfiguration.XmlConfiguration(ConfigurationSource).
103 </action>
104 <action issue="LOG4J2-1538" dev="ggregory" type="fix" due-to="Igor Karpov">
105 Prevent NPE when dynamically removing filters.
106 </action>
107 <action issue="LOG4J2-1532" dev="ggregory" type="fix">
108 Attributes were not merged properly in composite configurations.
109 </action>
110 <action issue="LOG4J2-1529" dev="mattsicker" type="fix" due-to="Sridevi Narra">
111 Attributes were not merged properly in composite configurations.
112 </action>
113 <action issue="LOG4J2-1527" dev="rpopma" type="fix" due-to="Jose Leon">
114 Prevent NPE in RingBufferLogEvent.getFormattedMessage() when used in web applications.
115 </action>
116 <action issue="LOG4J2-905" dev="ggregory" type="fix" due-to="Moritz Löser">
117 Added ability to disable (date) lookup completely for compatibility with other libraries like Camel.
118 </action>
119 <action issue="LOG4J2-1526" dev="mikes" type="fix">
120 Added support for setting StatusLogger destination in ConfigurationBuilder.
121 </action>
122 <action issue="LOG4J2-1448" dev="rpopma" type="fix" due-to="Keith Laban">
123 Allow comma separated agents, host list to be passed to FlumeAppender.
124 </action>
125 <action issue="LOG4J2-1500" dev="ggregory" type="fix" due-to="Jose Leon">
126 Merging configurations failed with an NPE when comparing Nodes with different attributes.
127 </action>
128 <action issue="LOG4J2-1482" dev="ggregory" type="fix" due-to="Sumit Singhal">
129 Fixed improper header in CsvParameterLayout.
130 </action>
131 <action issue="LOG4J2-1199" dev="rpopma" type="fix">
132 Documented that JVM Input Arguments Lookup (JMX) is not available on Google App Engine.
133 </action>
134 <action issue="LOG4J2-1438" dev="rpopma" type="fix">
135 (GC) Added method getParameter() to ObjectMessage (and ReusableObjectMessage).
136 </action>
137 <action issue="LOG4J2-1488" dev="rpopma" type="fix" due-to="Richard Zschech">
138 (GC) Fixed ISO8601 %date conversion pattern with a period '.' separator for milliseconds is now garbage free.
139 </action>
140 <action issue="LOG4J2-1489" dev="rpopma" type="fix" due-to="Richard Zschech">
141 (GC) Fixed %date conversion patterns with a timezone parameter are now garbage free.
142 </action>
143 <action issue="LOG4J2-1279" dev="rpopma" type="fix" due-to="Tony Baines">
144 Prevent NullPointerException in FastDateParser$TimeZoneStrategy.
145 </action>
146 <action issue="LOG4J2-1341" dev="rpopma" type="fix" due-to="Richard Zschech">
147 (GC) HighlightConverter and StyleConverter are now GC-free.
148 </action>
149 <action issue="LOG4J2-1467" dev="rpopma, ggregory" type="fix" due-to="Ralf, Gary Gregory">
150 [OSGi] Fixed missing import package.
151 </action>
152 <action issue="LOG4J2-351" dev="rpopma, ggregory" type="fix" due-to="Roland Weiglhofer">
153 [OSGi] Fixed wrong Fragment-Host in manifest files.
154 </action>
155 <action issue="LOG4J2-1313" dev="rpopma" type="fix" due-to="Philipp Knobel">
156 Properties declared in configuration can now have their value either in the element body or in an attribute named "value".
157 </action>
158 <action issue="LOG4J2-1235" dev="ggregory" type="fix" due-to="Niranjan Rao, Sascha Scholz, Aleksey Zvolinsky">
159 org.apache.logging.log4j.core.appender.routing.IdlePurgePolicy was not working correctly.
160 </action>
161 <action issue="LOG4J2-1502" dev="ggregory" type="fix" due-to="Sumit Singhal">
162 Fixed issue where CsvParameterLayout and CsvLogEventLayout inserted NUL characters if data starts with {, (, [ or "
163 </action>
164 <action issue="LOG4J2-1573" dev="ggregory" type="fix" due-to="Steffen Offermann">
165 Layout is no longer optional.
166 </action>
167 <action issue="LOG4J2-1608" dev="ggregory" type="fix">
168 ServletAppender does not provide throwable object to ServletContext.
169 </action>
170 <action issue="LOG4J2-1599" dev="ggregory" type="fix">
171 Prevent potential NPE in org.apache.logging.log4j.message.ParameterFormatter.formatMessage3(StringBuilder, char[], int, Object[], int, int[]).
172 </action>
173 <action issue="LOG4J2-1600" dev="ggregory" type="fix">
174 Prevent potential NPE due to org.apache.logging.log4j.core.layout.MarkerPatternSelector.createSelector(PatternMatch[], String, boolean, boolean, Configuration).
175 </action>
176 <action issue="LOG4J2-1601" dev="ggregory" type="fix">
177 Prevent potential NPE due to org.apache.logging.log4j.core.layout.ScriptPatternSelector.createSelector(AbstractScript, PatternMatch[], String, boolean, boolean, Configuration).
178 </action>
179 <action issue="LOG4J2-1602" dev="ggregory" type="fix">
180 Prevent potential NPE in org.apache.logging.log4j.core.util.datetime.FormatCache.MultipartKey.equals(Object) when object is null.
181 </action>
182 <action issue="LOG4J2-1603" dev="ggregory" type="fix">
183 Redo hashCode() and equals() methods in org.apache.logging.log4j.core.net.ssl classes.
184 </action>
185 <action issue="LOG4J2-1610" dev="ggregory" type="fix" due-to="Shubhankar">
186 Add targetNamespace to log4j-config.xsd. GitHub #43.
187 </action>
188 <action issue="LOG4J2-1619" dev="ggregory" type="fix">
189 new Log4jLogEvent().toString() throws an NPE.
190 </action>
191 <action issue="LOG4J2-1578" dev="ggregory" type="add">
192 RoutingAppender can be configured with scripts. Add Script in a Routes element.
193 </action>
194 <action issue="LOG4J2-1597" dev="ggregory" type="add">
195 Add a ScriptAppenderSelector to create an Appender specified by a Script.
196 </action>
197 <action issue="LOG4J2-1349" dev="rpopma" type="add">
198 (GC) Added support for garbage-free ThreadContext map. Disabled by default, users need to enable this explicitly.
199 </action>
200 <action issue="LOG4J2-1447" dev="rpopma" type="add">
201 (GC) Changed LogEvent's internal data structure for context data to be garbage-free. Added method LogEvent#getContextData(), deprecated method #getContextMap().
202 </action>
203 <action issue="LOG4J2-1010" dev="rpopma" type="add" due-to="Mikael Ståldal">
204 Users can now inject context data from other sources than ThreadContext. Values can be any Object, not just Strings.
205 </action>
206 <action issue="LOG4J2-1568" dev="mattsicker" type="add">
207 Added support for java.util.concurrent.LinkedTransferQueue to AsyncAppender.
208 </action>
209 <action issue="LOG4J2-1430" dev="mattsicker" type="add" due-to="John Cairns">
210 Added optional support for Conversant DisruptorBlockingQueue in AsyncAppender.
211 </action>
212 <action issue="LOG4J2-1439" dev="mattsicker" type="add" due-to="Anthony Maire">
213 Added optional support for JCTools MPSC bounded lock-free queue in AsyncAppender.
214 </action>
215 <action issue="LOG4J2-1558" dev="ggregory" type="add">
216 SocketAppender now supports IO buffering.
217 </action>
218 <action issue="LOG4J2-1557" dev="ggregory" type="add">
219 Add a Builder for the SocketAppender (deprecates factory method).
220 </action>
221 <action issue="LOG4J2-1609" dev="ggregory" type="add">
222 Add a Builder to ServletAppender and deprecate factory method.
223 </action>
224 <action issue="LOG4J2-1553" dev="ggregory" type="add">
225 AbstractManager now implements AutoCloseable.
226 </action>
227 <action issue="LOG4J2-1528" dev="mikes" type="add">
228 Added ability to generate Log4j 2-style XML configuration file from ConfigurationBuilder.
229 </action>
230 <action issue="LOG4J2-1181" dev="mikes" type="add">
231 Added Logging API for Scala 2.10 and 2.11.
232 </action>
233 <action issue="LOG4J2-1512" dev="mikes" type="add">
234 Added options to exclude stack trace from JSON, XML and YAML layouts.
235 </action>
236 <action issue="LOG4J2-1539" dev="ggregory" type="add">
237 Added Core API Configurator.shutdown(LoggerContext, long, TimeUnit).
238 </action>
239 <action issue="LOG4J2-1501" dev="ggregory" type="add">
240 FileAppender is now able to create files on-demand.
241 </action>
242 <action issue="LOG4J2-1504" dev="ggregory" type="add">
243 RollingFileAppender is now able to create files on-demand.
244 </action>
245 <action issue="LOG4J2-1471" dev="ggregory" type="add">
246 [PatternLayout] Add an ANSI option to %xThrowable.
247 </action>
248 <action issue="LOG4J2-1472" dev="ggregory" type="add">
249 org.apache.logging.log4j.core.LoggerContext now implements Closeable.
250 </action>
251 <action issue="LOG4J2-1458" dev="ggregory" type="add">
252 [PatternLayout] Add an ANSI option to %message.
253 </action>
254 <action issue="LOG4J2-1505" dev="ggregory" type="add">
255 Create a Builder for the FileAppender plugin to facilitate adding attributes in the future.
256 </action>
257 <action issue="LOG4J2-1507" dev="ggregory" type="add">
258 Allow Builders to be completely generic.
259 </action>
260 <action issue="LOG4J2-1508" dev="ggregory" type="add">
261 Allow a Builder to subclass another Builder.
262 </action>
263 <action issue="LOG4J2-1516" dev="rpopma" type="add" due-to="Gary Gregory">
264 Add ThreadContextMap2 interface supporting method putAll(Map&lt;String, String&gt;).
265 </action>
266 <action issue="LOG4J2-1519" dev="ggregory" type="add">
267 Add ThreadContext.putAll(Map&lt;String, String&gt;).
268 </action>
269 <action issue="LOG4J2-1520" dev="ggregory" type="add">
270 Add JUnit Rule implementations to manage the thread context.
271 </action>
272 <action issue="LOG4J2-1547" dev="ggregory" type="add">
273 The Core AbstractConfiguration now tracks its LoggerContext and add Configuration.getLoggerContext().
274 </action>
275 <action issue="LOG4J2-1540" dev="ggregory" type="add">
276 The Core AbstractManager now tracks its LoggerContext.
277 </action>
278 <action issue="LOG4J2-1577" dev="ggregory" type="add">
279 Add a Builder to the RoutingAppender and deprecate factory method.
280 </action>
281 <action issue="LOG4J2-1604" dev="ggregory" type="update" due-to="Colin Hillman">
282 Log4j2 TcpSocketServer in background.
283 </action>
284 <action issue="LOG4J2-1574" dev="ggregory" type="update">
285 Allow the RollingFileAppender to use default pattern layout.
286 </action>
287 <action issue="LOG4J2-1556" dev="ggregory" type="update">
288 Custom Log4j threads now extend Log4jThread.
289 </action>
290 <action issue="LOG4J2-1605" dev="ggregory" type="update">
291 Improve error messages for TcpSocketServer and UdpSocketServer.
292 </action>
293 <action issue="LOG4J2-1458" dev="ggregory" type="update">
294 Updated Jackson from 2.7.5 to 2.8.0.
295 </action>
296 <action issue="LOG4J2-1494" dev="ggregory" type="update">
297 Updated Jackson from 2.8.0 to 2.8.1.
298 </action>
299 <action issue="LOG4J2-1569" dev="ggregory" type="update">
300 Updated Jackson from 2.8.1 to 2.8.2.
301 </action>
302 <action issue="LOG4J2-1598" dev="ggregory" type="update">
303 Updated Jackson from 2.8.2 to 2.8.3.
304 </action>
305 <action issue="LOG4J2-1495" dev="ggregory" type="update">
306 Updated LMAX Disruptor from 3.3.4 to 3.3.5.
307 </action>
308 <action issue="LOG4J2-1496" dev="ggregory" type="update">
309 Updated Kafka client from 0.9.1.0 to 0.10.0.0.
310 </action>
311 <action issue="LOG4J2-1533" dev="ggregory" type="update">
312 Updated Kafka client from 0.10.0.0 to 0.10.0.1.
313 </action>
314 <action issue="LOG4J2-1487" dev="ggregory" type="update">
315 Updated JMS test from ActiveMQ 5.13.3 to 5.13.4.
316 </action>
317 <action issue="LOG4J2-1551" dev="ggregory" type="update">
318 Updated JMS test from ActiveMQ 5.13.4 to 5.14.0.
319 </action>
320 <action issue="LOG4J2-1543" dev="ggregory" type="update">
321 Removed deprecated Core API org.apache.logging.log4j.core.util.Constants.UTF_8.
322 </action>
323 <action issue="LOG4J2-1544" dev="ggregory" type="update">
324 Removed deprecated Core API org.apache.logging.log4j.core.util.Assert.requireNonNull(T, String).
325 </action>
326 <action issue="LOG4J2-1545" dev="ggregory" type="update">
327 Removed deprecated Web API org.apache.logging.log4j.web.WebLookup.getServletContext().
328 </action>
329 </release>
330 <release version="2.6.2" date="2016-07-05" description="GA Release 2.6.2">
331 <action issue="LOG4J2-904" dev="rgoers" type="fix" due-to="Bernhard Mähr">
332 If copy and delete fails in rename action then resort to truncating the source file after copying it.
333 </action>
334 <action issue="LOG4J2-1250" dev="rgoers" type="fix">
335 CronTriggeringPolicy was not properly setting the prevFileTime value for the PatternProcessor so
336 file dates and times on rolled files were incorrect.
337 </action>
338 <action issue="LOG4J2-1452" dev="rpopma" type="fix" due-to="Mikael Ståldal">
339 Fixed issue where reusable messages broke flow tracing logic.
340 </action>
341 <action issue="LOG4J2-1440" dev="rgoers" type="fix">
342 Fix bug in OnStartupTriggeringPolicy that allowed it to roll over on every reconfiguration. Added
343 minSize attribute.
344 </action>
345 <action issue="LOG4J2-1414" dev="rpopma" type="fix" due-to="Ralph Goers">
346 Fixed minor issues with the 2.6.1 web site.
347 </action>
348 <action issue="LOG4J2-1434" dev="rpopma" type="fix" due-to="Luke Butters">
349 Ensure that the thread-local StringBuilders used by Layouts to format log events to text will not
350 retain excessive memory after a large message was logged.
351 </action>
352 <action issue="LOG4J2-1395" dev="mikes" type="add">
353 Add "direct" option to ConsoleAppender for increased performance.
354 </action>
355 <action issue="LOG4J2-1418" dev="mikes" type="fix">
356 Provide MessageFactory2 to custom Logger implementations.
357 </action>
358 <action issue="LOG4J2-1420" dev="rgoers" type="fix">
359 RollingRandomAccessFileManager was not properly rolling over on startup and was getting a NullPointerException.
360 </action>
361 <action issue="LOG4J2-1417" dev="rpopma" type="fix">
362 Fixed issue where Unbox utility ignored the value Constants.ENABLE_THREADLOCALS and always stored non-JDK classes in ThreadLocals.
363 </action>
364 <action issue="LOG4J2-1422" dev="rpopma" type="fix">
365 Fixed issue where AsyncAppenderQueueFullPolicyTest sometimes hangs.
366 </action>
367 <action issue="LOG4J2-1445" dev="ggregory" type="fix" due-to="Ludovic HOCHET">
368 OnStartupTriggeringPolicyTest fails on Windows saying the file is used by another process.
369 </action>
370 <action issue="LOG4J2-1437" dev="rpopma" type="add">
371 (GC) ObjectMessage and ReusableObjectMessage now avoid calling toString() on auto-boxed primitive parameters.
372 </action>
373 <action issue="LOG4J2-1415" dev="rpopma" type="add">
374 (GC) ParameterFormatter now avoids calling toString() on auto-boxed primitive message parameters.
375 </action>
376 <action issue="LOG4J2-1412" dev="rpopma" type="add">
377 Unbox utility's ringbuffer of StringBuilders is now configurable.
378 </action>
379 <action issue="LOG4J2-1432" dev="ggregory" type="update">
380 Update Jackson from 2.7.4 to 2.7.5.
381 </action>
382 <action issue="LOG4J2-1433" dev="ggregory" type="update">
383 Update Jansi from 1.11 to 1.13.
384 </action>
385 <action issue="LOG4J2-1444" dev="ggregory" type="update">
386 Update Apache Commons Compress from 1.11 to 1.12.
387 </action>
388 </release>
389 <release version="2.6.1" date="2016-06-05" description="GA Release 2.6.1">
390 <action issue="LOG4J2-1405" dev="rgoers" type="fix">
391 OnStartupTriggeringPolicy was forcing a rollover of empty files at startup and would append a second footer that was added by the prior shutdown.
392 </action>
393 <action issue="LOG4J2-1406" dev="rpopma" type="fix" due-to="Trask Stalnaker">
394 Fixed bug in ReusableParameterizedMessage where Throwable was never updated so first error was logged over and over again and subsequent errors were not logged.
395 </action>
396 <action issue="LOG4J2-1409" dev="rpopma" type="fix" due-to="Shahan">
397 Fixed ArrayIndexOutOfBoundsException that may occur in ReusableParameterizedMessage.
398 </action>
399 <action issue="LOG4J2-997" dev="rgoers" type="fix" due-to="Maytee Chinavanichkit">
400 Add filter and remove filter were not working properly in AbstractFilterable.
401 </action>
402 <action issue="LOG4J2-1032" dev="rgoers" type="fix">
403 Changed RenameAction to use java.nio to better report rename failures.
404 </action>
405 <action issue="LOG4J2-1407" dev="ggregory" type="fix">
406 Fixed misleading WARN log events from Log4j about message factories and unexpected formatting.
407 </action>
408 <action issue="LOG4J2-1408" dev="ggregory" type="fix">
409 Added the module log4j-liquibase to BOM POM.
410 </action>
411 <action issue="LOG4J2-1180" dev="ggregory" type="fix">
412 Logger cache now accounts for message factory.
413 </action>
414 <action issue="LOG4J2-1402" dev="rgoers" type="fix">
415 Fix regression in properties configuration to support arbitrary component ids.
416 </action>
417 <action issue="LOG4J2-1385" dev="ggregory" type="update">
418 (GC) CSV layouts should not create a new CSVPrinter for each log event. Requires Apache Commons CSV 1.4.
419 </action>
420 <action issue="LOG4J2-1398" dev="ggregory" type="update">
421 Update liquibase-core from 3.4.2 to 3.5.1.
422 </action>
423 <action issue="LOG4J2-1399" dev="ggregory" type="update">
424 Update Apache Commons CSV from 1.3 to 1.4.
425 </action>
426 <action issue="LOG4J2-1411" dev="mattsicker" type="add">
427 Added documentation about plugin builders compared to factories.
428 </action>
429 <action issue="LOG4J2-1394" dev="mattsicker,mikes" type="fix">
430 Fixed minor issues with the 2.6 web site.
431 </action>
432 </release>
433 <release version="2.6" date="2016-05-25" description="GA Release 2.6">
434 <action issue="LOG4J2-1270" dev="rpopma" type="add">
435 (GC) Added support for garbage-free logging in steady state.
436 This includes Async Loggers and logging synchronously to the console and to a file,
437 but does not include the AsyncAppender. This release makes the GelfLayout and
438 the main patterns in the PatternLayout garbage-free.
439 </action>
440 <action issue="LOG4J2-1297" dev="rpopma" type="add">
441 (GC) Added manual page on garbage-free logging.
442 </action>
443 <action issue="LOG4J2-1373" dev="rpopma" type="add">
444 (GC) Update Logger wrapper Generator tool to generate methods for the new Logger methods.
445 </action>
446 <action issue="LOG4J2-1356" dev="mikes" type="update">
447 (GC) GelfLayout does now support garabage-free logging (with compressionType=OFF).
448 </action>
449 <action issue="LOG4J2-1326" dev="rpopma" type="add">
450 (GC) Added methods to the Logger interface for logging CharSequence messages.
451 </action>
452 <action issue="LOG4J2-1344" dev="rpopma" type="add">
453 (GC) FileAppender, RollingFileAppender and MemoryMappedFileAppender are now also garbage-free by default.
454 </action>
455 <action issue="LOG4J2-1343" dev="rpopma" type="update">
456 (GC) ConsoleAppender is now garbage-free by default. This logic is reusable for all AbstractOutputStreamAppender subclasses.
457 </action>
458 <action issue="LOG4J2-1278" dev="rpopma" type="add">
459 (GC) Added unrolled varargs methods to Logger API, added Unbox utility to avoid auto-boxing when logging primitive values.
460 </action>
461 <action issue="LOG4J2-1318" dev="rpopma" type="update">
462 (GC) Avoid allocating unnecessary temporary objects in LoggerContext's getLogger methods.
463 </action>
464 <action issue="LOG4J2-1333" dev="rpopma" type="update">
465 (GC) Avoid allocating unnecessary temporary objects in MarkerManager's getMarker methods.
466 </action>
467 <action issue="LOG4J2-1321" dev="rpopma" type="update">
468 (GC) Avoid allocating unnecessary temporary objects in PatternLayout's NamePatternConverter and ClassNamePatternConverter.
469 </action>
470 <action issue="LOG4J2-1271" dev="rpopma" type="add">
471 (GC) Add MessageFactory that avoid allocation by reusing a cached ParameterizedMessage instance.
472 </action>
473 <action issue="LOG4J2-1271" dev="rpopma" type="update">
474 (GC) ParameterizedMessage optimizations to avoid or at least postpone allocating temporary objects.
475 </action>
476 <action issue="LOG4J2-1283" dev="rpopma" type="update">
477 (GC) Provide ThreadLocal-based gc-free caching mechanism in DatePatternConverter for non-webapps.
478 </action>
479 <action issue="LOG4J2-1293" dev="rpopma" type="add">
480 (GC) Add interface StringBuilderFormattable to enable converting Messages and parameters to text without allocating temporary objects.
481 ParameterizedMessage, ObjectMessage, SimpleMessage and ThreadDumpMessage now implement StringBuilderFormattable.
482 </action>
483 <action issue="LOG4J2-1291" dev="rpopma" type="update">
484 (GC) Update PatternLayout to utilize gc-free mechanism for LogEvent processing.
485 </action>
486 <action issue="LOG4J2-1292" dev="rpopma" type="update">
487 (GC) Update RandomAccessFileAppender and RollingRandomAccessFileAppender to utilize gc-free Layout.encode() method.
488 </action>
489 <action issue="LOG4J2-1274" dev="rpopma" type="add">
490 (GC) Add encode(LogEvent, ByteBufferDestination) method to Layout API to enable converting LogEvents to bytes without creating temporary objects.
491 </action>
492 <action issue="LOG4J2-1281" dev="rpopma" type="fix">
493 (GC) LoggerConfig.getProperties() should not allocate on each call.
494 </action>
495 <action issue="LOG4J2-1272" dev="rpopma" type="update">
496 (GC) Improve LoggerConfig's data structure for AppenderControl objects to avoid allocating temporary objects during
497 traversal for each log event.
498 </action>
499 <action issue="LOG4J2-1269" dev="rpopma" type="fix">
500 (GC) AsyncLogger should use thread-local translator by default.
501 </action>
502 <action issue="LOG4J2-623" dev="rpopma" type="fix">
503 Generate MDC properties as a JSON map in JSONLayout, with option to output as list of map entries.
504 </action>
505 <action issue="LOG4J2-1362" dev="rpopma" type="add" due-to="Gary Gregory">
506 Added a YAML layout.
507 </action>
508 <action issue="LOG4J2-1387" dev="rpopma" type="fix">
509 Fixed memory leak related to shutdown hook.
510 </action>
511 <action issue="LOG4J2-1179" dev="rpopma" type="add">
512 Documented benchmark results comparing Log4j 2 performance to other logging libraries.
513 </action>
514 <action issue="LOG4J2-1382" dev="rpopma" type="fix">
515 Copying a MutableLogEvent using Log4jLogEvent.Builder should not unnecessarily obtain caller location information.
516 </action>
517 <action issue="LOG4J2-1011" dev="mikes" type="add">
518 Document dependencies for layouts.
519 </action>
520 <action issue="LOG4J2-621" dev="ggregory" type="add" due-to="Lee Theobald, Kamal Mettananda, Gary Gregory">
521 Pattern to drop first N package parts.
522 </action>
523 <action issue="LOG4J2-494" dev="rgoers" type="add" due-to="Philipp Knobel">
524 Support merging configurations to for a composite configuration.
525 </action>
526 <action issue="LOG4J2-1357" dev="mikes" type="add">
527 Option to not log stack traces for logged Throwables in GelfLayout.
528 </action>
529 <action issue="LOG4J2-1375" dev="rpopma" type="update">
530 Update SLF4J from 1.7.13 to 1.7.21.
531 </action>
532 <action issue="LOG4J2-1374" dev="rpopma" type="update">
533 Migrate tests from Logback 1.1.3 to 1.1.7.
534 </action>
535 <action issue="LOG4J2-1384" dev="ggregory" type="update">
536 Update Apache Commons CSV from 1.2 to 1.3.
537 </action>
538 <action issue="LOG4J2-1372" dev="rgoers" type="fix" due-to="Kamal Mettananda, Gary Gregory">
539 XMLLayout indents, but not the first child tag (Event).
540 </action>
541 <action issue="LOG4J2-1363" dev="rgoers" type="fix">
542 Properties Configuration did not support includeLocation attribute on Loggers.
543 </action>
544 <action issue="LOG4J2-1263" dev="rgoers" type="fix">
545 The ConfigurationSource was not saved for BuiltConfigurations so monitor interval had no effect.
546 </action>
547 <action issue="LOG4J2-1369" dev="ggregory" type="fix" due-to="Alex Birch, Gary Gregory">
548 "xz" compression results in plaintext, uncompressed files.
549 </action>
550 <action issue="LOG4J2-1365" dev="mikes" type="update">
551 (Log4j-internal) Provide message text as CharSequence for some message types to optimize some layouts.
552 </action>
553 <action issue="LOG4J2-1368" dev="rpopma" type="fix">
554 (Log4j-internal) StatusLogger dropped exceptions when logging parameterized messages.
555 </action>
556 <action issue="LOG4J2-1348" dev="ggregory" type="add" due-to="Greg Thomas, Gary Gregory">
557 Add an AutoCloseable ThreadContext class: CloseableThreadContext.
558 </action>
559 <action issue="LOG4J2-1345" dev="rpopma" type="update">
560 (Doc) Clarify documentation for properties that control Log4j behaviour.
561 </action>
562 <action issue="LOG4J2-1336" dev="ggregory" type="fix" due-to="Zbynek Vyskovsky">
563 LoggerFactory in 1.2 API module is not compatible with 1.2.
564 </action>
565 <action issue="LOG4J2-1354" dev="ggregory" type="fix" due-to="Arkadiusz Adolph">
566 No configuration reload is triggered under Windows when replacing the configuration file with one that has older last modified date.
567 </action>
568 <action issue="LOG4J2-1346" type="fix">
569 Exception from Log4jServletContextListener prevents jetty-maven-plugin run-forked.
570 </action>
571 <action issue="LOG4J2-1339" dev="rpopma" type="fix">
572 (Perf) AsyncLogger performance optimization: avoid calling instanceof TimestampMessage in hot path.
573 </action>
574 <action issue="LOG4J2-1324" dev="rpopma" type="fix">
575 Improve error handling in the Async Logger background thread: the new default exception handler no longer rethrows the error.
576 </action>
577 <action issue="LOG4J2-1309" dev="ggregory" type="fix">
578 Configuration file error does not show cause exception.
579 </action>
580 <action issue="LOG4J2-1299" dev="ggregory" type="add">
581 Add pattern converter for thread id and priority in PatternLayout.
582 </action>
583 <action issue="LOG4J2-1289" dev="ggregory" type="fix">
584 Change flow logging text from "entry' to "Enter" and "exit" to "Exit".
585 </action>
586 <action issue="LOG4J2-1284" dev="rpopma" type="fix">
587 Made default MessageFactory configurable.
588 </action>
589 <action issue="LOG4J2-1280" dev="ggregory" type="fix">
590 Deprecate org.apache.logging.log4j.util.MessageSupplier.
591 </action>
592 <action issue="LOG4J2-1280" dev="rpopma" type="fix">
593 Logger methods taking Supplier parameters now correctly handle cases where the supplied value is a Message.
594 </action>
595 <action issue="LOG4J2-1268" dev="rpopma" type="fix">
596 FixedDateFormat was incorrect for formats having MMM with the French locale.
597 </action>
598 <action issue="LOG4J2-1255" dev="rgoers" type="update">
599 Add enhanced entry and exit methods.
600 </action>
601 <action issue="LOG4J2-124" dev="rgoers" type="add">
602 Add shutdown methods to LogManager.
603 </action>
604 <action issue="LOG4J2-1222" dev="rgoers" type="fix">
605 Creation of a LoggerContext will fail if shutdown is in progress. LogManager will default to SimpleLogger instead.
606 </action>
607 <action issue="LOG4J2-1221" dev="rpopma" type="add" due-to="Michael Barker">
608 Added async logger Timeout wait strategy and made this the default wait strategy for async loggers.
609 This prevents a rare deadlock that may occur on Solaris.
610 </action>
611 <action issue="LOG4J2-1080" dev="rpopma" type="add">
612 Added option to discard events below a certain log level if the async logger ring buffer
613 or async appender queue is full.
614 </action>
615 <action issue="LOG4J2-1237" dev="ggregory" type="add" due-to="Mike Calmus, Gary Gregory">
616 Make PatternLayout header and footer accept a pattern.
617 </action>
618 <action issue="LOG4J2-1244" dev="ggregory" type="add" due-to="Anshu Garg, Remko Popma, Gary Gregory">
619 Make header and footer values customizable in JSONLayout.
620 </action>
621 <action issue="LOG4J2-1245" dev="ggregory" type="add">
622 Make CSV Layout header and footers accept patterns.
623 </action>
624 <action issue="LOG4J2-1192" dev="ggregory" type="add" due-to="Jörg Bretschneider, Gary Gregory">
625 Dynamic Subject for SMTP Appender.
626 </action>
627 <action issue="LOG4J2-1277" dev="ggregory" type="add" due-to="Gary Gregory, Ludovic Hochet">
628 FormattedMessage, MessageFormatMessage and StringFormattedMessage should support passing in a Locale to ensure appropriate formatting.
629 </action>
630 <action issue="LOG4J2-1260" dev="ggregory" type="fix" due-to="Blake Day, Gary Gregory">
631 TlsSyslogFrame calculates message length incorrectly.
632 </action>
633 <action issue="LOG4J2-1258" dev="ggregory" type="fix" due-to="Francis Lalonde">
634 Async DynamicThresholdFilter does not use the log event's context map.
635 </action>
636 <action issue="LOG4J2-1232" dev="ggregory" type="fix" due-to="Nikolai">
637 Incorrect log rotation in last week of year.
638 </action>
639 <action issue="LOG4J2-1248" dev="rpopma" type="fix">
640 Fixed broken nanotime in pattern layout.
641 </action>
642 <action issue="LOG4J2-908" dev="ggregory" type="fix" due-to="Konstantinos Liakos, Patrick Flaherty, Robin Coe, Gary Gregory">
643 JSONLayout doesn't add a comma between log events.
644 </action>
645 <action issue="LOG4J2-1230" dev="ggregory" type="fix" due-to="Vladimir Hudec, Ralph Goers, Gary Gregory">
646 Don't concatenate SYSLOG Messages.
647 </action>
648 <action issue="LOG4J2-1238" dev="ggregory" type="fix">
649 org.apache.logging.log4j.core.net.TcpSocketManager and other classes does not report internal exceptions to the status logger.
650 </action>
651 <action issue="LOG4J2-1212" dev="rpopma" type="fix">
652 Fix documentation to specify the correct default wait strategy used by async loggers.
653 </action>
654 <action issue="LOG4J2-1215" dev="ggregory" type="fix" due-to="Erik Kemperman">
655 Documentation/XSD inconsistencies.
656 </action>
657 <action issue="LOG4J2-1276" dev="ggregory" type="fix" due-to="Ludovic Hochet">
658 LoggerMessageSupplierTest and LoggerSupplierTest are Locale sensitive.
659 </action>
660 <action issue="LOG4J2-1380" dev="ggregory" type="update">
661 Update Jackson from 2.7.3 to 2.7.4.
662 </action>
663 <action issue="LOG4J2-1304" dev="ggregory" type="update">
664 Update Jackson from 2.7.0 to 2.7.2.
665 </action>
666 <action issue="LOG4J2-1253" dev="ggregory" type="update">
667 Update LMAX Disruptor from 3.3.2 to 3.3.4.
668 </action>
669 <action issue="LOG4J2-1219" dev="ggregory" type="update">
670 Update SLF4J from 1.7.12 to 1.7.13.
671 </action>
672 <action issue="LOG4J2-1239" dev="ggregory" type="update">
673 Update Jackson from 2.6.3 to 2.6.4.
674 </action>
675 <action issue="LOG4J2-1249" dev="ggregory" type="update">
676 Update Jackson from 2.6.4 to 2.7.0.
677 </action>
678 <action issue="LOG4J2-1351" dev="ggregory" type="update">
679 Update Jackson from 2.7.2 to 2.7.3.
680 </action>
681 <action issue="LOG4J2-1240" dev="ggregory" type="update">
682 Update Liquibase from 3.3.5 to 3.4.2.
683 </action>
684 <action issue="LOG4J2-1294" dev="ggregory" type="update">
685 Update Kafka client from 0.9.0.0 to 0.9.0.1.
686 </action>
687 <action issue="LOG4J2-1352" dev="ggregory" type="update">
688 Update javax.mail from 1.5.4 to 1.5.5.
689 </action>
690 <action issue="LOG4J2-1358" dev="ggregory" type="update">
691 Update Apache Commons Compress from 1.10 to 1.11.
692 </action>
693 <action issue="LOG4J2-1388" dev="rpopma" type="update">
694 Update Google java-allocation-instrumenter from 3.0 to 3.0.1.
695 </action>
696 <action issue="LOG4J2-1233" dev="ggregory" type="update" due-to="Bahri Gencsoy">
697 Misleading Value In Properties Example.
698 </action>
699 <action issue="LOG4J2-1251" dev="mattsicker" type="fix" due-to="Romain Manni-Bucau">
700 Fix JUL bridge issue where LogRecord.getParameters() is used when null.
701 </action>
702 <action issue="LOG4J2-1254" dev="rpopma" type="fix" due-to="Josh Trow">
703 Fix typo in Flow Tracing documentation.
704 </action>
705 <action issue="LOG4J2-920" dev="mattsicker" type="fix" due-to="Ludovic Hochet">
706 ClassNotFoundException for BundleContextSelector when initialising in an OSGi environment.
707 </action>
708 <action issue="LOG4J2-1300" dev="mattsicker" type="update">
709 Remove serializability from classes that don't need it.
710 </action>
711 <action issue="LOG4J2-1303" dev="mattsicker" type="add">
712 Add documentation links to runtime dependencies in each component intro page.
713 </action>
714 <action issue="LOG4J2-1275" dev="mattsicker" type="fix" due-to="Ludovic Hochet">
715 Fix RollingAppenderNoUnconditionalDeleteTest repeat test runs from failing.
716 </action>
717 <action issue="LOG4J2-1262" dev="mattsicker" type="fix">
718 Stop throwing unnecessary exception in Log4jServletContextListener.contextDestroyed().
719 </action>
720 <action issue="LOG4J2-1252" dev="mattsicker" type="add">
721 JeroMqAppender should support layouts.
722 </action>
723 <action issue="LOG4J2-1227" dev="mattsicker" type="fix" due-to="Olivier Lemasle">
724 NullPointerException in MapLookup.lookup if the event is null.
725 </action>
726 <action issue="LOG4J2-1306" dev="mattsicker" type="update">
727 JeroMqAppender should use ShutdownCallbackRegistry instead of runtime hooks.
728 </action>
729 <action issue="LOG4J2-1217" dev="mattsicker" type="add" due-to="Thies Wellpott">
730 PatternLayout option to limit length of text.
731 </action>
732 <action issue="LOG4J2-1308" dev="mattsicker" type="update">
733 Remove need to pre-specify appender et al. identifiers in property file config format.
734 </action>
735 <action issue="LOG4J2-1050" dev="mattsicker" type="fix" due-to="Adam Retter">
736 Add a Log4jLookup class to help write log files relative to log4j2.xml.
737 </action>
738 <action issue="LOG4J2-1133" dev="mattsicker" type="add">
739 Add JNDI lookup documentation.
740 </action>
741 <action issue="LOG4J2-1310" dev="mattsicker" type="fix">
742 JndiLookup mindlessly casts to String and should use String.valueOf().
743 </action>
744 <action issue="LOG4J2-1206" dev="mattsicker" type="update">
745 org.apache.logging.log4j.core.LoggerContext#updateLoggers should call firePropertyChangeEvent.
746 </action>
747 <action issue="LOG4J2-248" dev="mattsicker" type="fix">
748 Log4jWebInitializerImpl: Use Thread instead of Class for fallback classloader.
749 </action>
750 <action issue="LOG4J2-1169" dev="mattsicker" type="add" due-to="Gerald Kritzinger">
751 PatternLayout: Possible variable substitution in equals substitution parameter.
752 </action>
753 <action issue="LOG4J2-1322" dev="mattsicker" type="update">
754 Update Log4j 1.x migration guide to include information about system property lookup syntax changes.
755 </action>
756 <action issue="LOG4J2-1330" dev="mattsicker" type="fix">
757 Fix NoClassDefFoundError in ReflectionUtil on Google App Engine.
758 </action>
759 </release>
760 <release version="2.5" date="2015-12-06" description="GA Release 2.5">
761 <action issue="LOG4J2-324" dev="rpopma" type="fix">
762 Reduced memory usage of status messages in bounded queue; support zero-length queue that stores no messages.
763 </action>
764 <action issue="LOG4J2-1173" dev="rpopma" type="fix">
765 Fixed rollover error when copying to a directory mapped to a remote Linux host.
766 </action>
767 <action issue="LOG4J2-435" dev="rpopma" type="add" due-to="Robert Schaft">
768 Added support for custom delete actions triggered by a rollover.
769 </action>
770 <action issue="LOG4J2-649" dev="rgoers" type="update" due-to="Aleksey Zvolinsky">
771 Add PurgePolicy and IdlePurgePolicy to RoutingAppender.
772 </action>
773 <action issue="LOG4J2-1202" dev="rgoers" type="update">
774 Remove ConfigurationMonitor. The WatchManager is now used to check for configuration changes.
775 </action>
776 <action issue="LOG4J2-1195" dev="mikes" type="fix" due-to="Melvin Du">
777 Make KafkaAppender support SerializedLayout.
778 </action>
779 <action issue="LOG4J2-89" dev="rgoers" type="add">
780 Allow rollover to occur at any time. Add CronTriggeringPolicy.
781 </action>
782 <action issue="LOG4J2-381" dev="rgoers" type="fix" due-to="Anthony Baldocchi">
783 Allow triggering policy and rollover strategy to be modified during reconfiguration.
784 </action>
785 <action issue="LOG4J2-1136" dev="rgoers" type="add">
786 Add support for JSR 223 scripts in filters and the PatternSelector.
787 </action>
788 <action issue="LOG4J2-1168" dev="ggregory" type="add" due-to="Steven Swor">
789 Add getters for source and destination file in file rename action.
790 </action>
791 <action issue="LOG4J2-1175" dev="ggregory" type="add">
792 Add getters for classes in org.apache.logging.log4j.core.appender.rolling.action.
793 </action>
794 <action issue="LOG4J2-898" dev="rpopma" type="add">
795 Added system property to allow users to control whether messages should be formatted in the background.
796 </action>
797 <action issue="LOG4J2-1178" dev="ggregory" type="add">
798 Support use-case for JDBC's CommonDataSource.setLogWriter(PrintWriter) and java.sql.DriverManager.setLogWriter(PrintWriter).
799 </action>
800 <action issue="LOG4J2-1187" dev="ggregory" type="add">
801 Support use case for java.sql.DriverManager.setLogStream(PrintStream).
802 </action>
803 <action issue="LOG4J2-1029" dev="rpopma" type="fix" due-to="Stefan Leonhartsberger">
804 Performance improvement when gathering location information.
805 </action>
806 <action issue="LOG4J2-1172" dev="rpopma" type="fix">
807 Fixed ThreadLocal leak [AsyncLogger$Info] on Tomcat when using AsyncLoggerContextSelector.
808 </action>
809 <action issue="LOG4J2-1176" dev="rpopma" type="fix">
810 Fixed memory leak when log4j jars are in Tomcat's lib folder.
811 </action>
812 <action issue="LOG4J2-1180" dev="ggregory" type="fix" due-to="Mikael Ståldal">
813 Logger cache does not account for message factory.
814 </action>
815 <action issue="LOG4J2-879" dev="rpopma" type="fix">
816 Documentation: fixed minor issues with the site and manual pages.
817 </action>
818 <action issue="LOG4J2-999" dev="rpopma" type="fix" due-to="Joan Balagueró">
819 RollingFileAppender should also roll over when log event time is equal to rollover time, not only when later.
820 </action>
821 <action issue="LOG4J2-873" dev="rpopma" type="fix" due-to="Martin Dickins, LC, Luke Woodward">
822 Fixed bug where omitting the &lt;display-name&gt; element in web.xml caused incorrect log4j initialization,
823 resulting in memory leaks when the web application was stopped or reloaded.
824 </action>
825 <action issue="LOG4J2-323" dev="rpopma" type="fix">
826 Better web app support for async loggers: Fixed a memory leak that occurred when the logging jars are placed
827 in the container's classpath and the configuration file uses AsyncRoot/AsyncLogger.
828 The problem was that the first web application started the Disruptor background thread [AsyncLoggerConfig-1] but did not stop it until all web apps are stopped.
829 Each web application now has its own Disruptor which is stopped/started together with the web app.
830 </action>
831 <action issue="LOG4J2-493" dev="rpopma" type="fix">
832 Better web app support for async loggers: it is now possible to place the logging jars in the container's
833 classpath when making all loggers asynchronous by using AsyncLoggerContextSelector. This fixes a problem where
834 logging would stop working after stopping and restarting a web application.
835 </action>
836 <action issue="LOG4J2-1171" dev="rpopma" type="fix">
837 Use servlet context name for logger context name when available.
838 </action>
839 <action issue="LOG4J2-1159" dev="rpopma" type="fix">
840 Fixed a ThreadLocal memory leak in Tomcat8 that mentions AsyncLoggers when Async Loggers are not used.
841 </action>
842 <action issue="LOG4J2-1166" dev="rpopma" type="fix">
843 AbstractConfiguration executor should use a DaemonThreadFactory.
844 </action>
845 <action issue="LOG4J2-1165" dev="rpopma" type="fix">
846 Improve Log4j initialization status messages.
847 </action>
848 <action issue="LOG4J2-1156" dev="rpopma" type="fix">
849 Web site corrections and updates.
850 </action>
851 <action issue="LOG4J2-1158" dev="ggregory" type="fix" due-to="Michael Fortin, Gary Gregory">
852 Log4J JUL adapter is using MessageFormat on String passed by java.util.function.Supplier&lt;String>.
853 </action>
854 <action issue="LOG4J2-801" dev="mattsicker" type="fix">
855 org.apache.logging.log4j.core.Logger should be serializable.
856 </action>
857 <action issue="LOG4J2-1157" dev="mattsicker" type="fix" due-to="Norbert Bartels">
858 Fix compilation error for classes annotated with @Plugin.
859 </action>
860 <action issue="LOG4J2-948" dev="mattsicker" type="fix" due-to="Andrew Flower">
861 Fix plugin documentation error about Converters.
862 </action>
863 <action issue="LOG4J2-1193" dev="ggregory" type="fix">
864 Prefix all thread names Log4j creates with "Log4j2-".
865 </action>
866 <action issue="LOG4J2-1194" dev="ggregory" type="fix" due-to="Adam Brin">
867 Documentation does not match parameters for LoggerNameLevelRewritePolicy.
868 </action>
869 <action issue="LOG4J2-1196" dev="mattsicker" type="fix" due-to="René Zanner">
870 MongoDbConnection does not close MongoClient.
871 </action>
872 <action issue="LOG4J2-1174" dev="ggregory" type="update">
873 Update Jackson from 2.6.2 to 2.6.3.
874 </action>
875 <action issue="LOG4J2-1207" dev="ggregory" type="update">
876 Update kafka-clients from 0.8.2.2 to 0.9.0.0.
877 </action>
878 </release>
879 <release version="2.4.1" date="2015-10-08" description="GA Release 2.4.1">
880 <action issue="LOG4J2-1129" dev="rgoers" type="add">
881 Allow PatternLayout to select a pattern to use based on some selection criteria.
882 </action>
883 <action issue="LOG4J2-1145" dev="ggregory" type="add">
884 Add %equals to PatternLayout to test and replace patterns with strings.
885 </action>
886 <action issue="LOG4J2-1147" dev="ggregory" type="add">
887 Add %equalsIgnoreCase to PatternLayout to test and replace patterns with strings.
888 </action>
889 <action issue="LOG4J2-1146" dev="ggregory" type="add">
890 Add %notEmpty to PatternLayout to avoid output of patterns where all variables are empty.
891 </action>
892 <action issue="LOG4J2-1020" dev="mikes" type="add">
893 Add possibility to set shutdown timeout on AsyncAppender.
894 </action>
895 <action issue="LOG4J2-1153" dev="rpopma" type="fix">
896 Fixed NullPointerException when only root logger is defined (and no named loggers) in configuration properties file.
897 </action>
898 <action issue="LOG4J2-1140" dev="rpopma" type="fix">
899 Fixed bug where headers were not being written to first file with RollingFileAppender.
900 </action>
901 <action issue="LOG4J2-1149" dev="rpopma" type="fix">
902 Fixed bug where PatternLayout predefined date pattern with time zone always renders default date format.
903 </action>
904 <action issue="LOG4J2-1050" dev="rpopma" type="fix">
905 Fixed Log4jLookup.
906 </action>
907 <action issue="LOG4J2-1142" dev="rpopma" type="fix">
908 Fix potential memory leak in web applications by using a straight ThreadLocal field instead of subclassing ThreadLocal.
909 </action>
910 <action issue="LOG4J2-1135" dev="rpopma" type="fix">
911 Compression on rollover was broken: log file was renamed to .zip but not compressed.
912 </action>
913 <action issue="LOG4J2-1127" dev="ggregory" type="fix">
914 log4j2.xml cannot be parsed on Oracle Weblogic 12c.
915 </action>
916 <action issue="LOG4J2-1132" dev="ggregory" type="fix">
917 Do not use MongoDB driver 2.13.3 deprecated methods.
918 </action>
919 <action issue="LOG4J2-1144" dev="ggregory" type="fix">
920 Add %markerSimpleName in pattern layout should evaluate to marker name (not toString()).
921 </action>
922 <action issue="LOG4J2-1126" dev="ggregory" type="fix">
923 Web site corrections and updates.
924 </action>
925 <action issue="LOG4J2-1151" dev="rpopma" type="update">
926 Performance improvement: backport Java 8 fast ISO-8859-1 String to byte[] encoder to AbstractStringLayout.
927 </action>
928 <action issue="LOG4J2-935" dev="rpopma" type="update">
929 Performance improvement when converting Strings to byte[] arrays.
930 </action>
931 <action issue="LOG4J2-1040" dev="ggregory" type="update">
932 Update MongoDB driver from 2.13.3 to 3.0.4.
933 </action>
934 <action issue="LOG4J2-1128" dev="ggregory" type="update">
935 Reuse StringBuilder to improve performance for String-based layouts: CSV, GELF, HTML, RFC524, Syslog.
936 </action>
937 <action issue="LOG4J2-1131" dev="ggregory" type="update">
938 Update mongo-java-driver from 2.13.2 to 2.13.3.
939 </action>
940 <action issue="LOG4J2-1138" dev="ggregory" type="update">
941 Do not use Jackson deprecated methods.
942 </action>
943 <action issue="LOG4J2-1139" dev="ggregory" type="update">
944 Update Jackson from 2.6.1 to 2.6.2.
945 </action>
946 <action issue="LOG4J2-1150" dev="ggregory" type="update">
947 Update kafka-clients from 0.8.2.1 to 0.8.2.2.
948 </action>
949 </release>
950 <release version="2.4" date="2015-09-20" description="GA Release 2.4">
951 <action issue="LOG4J2-635" dev="rgoers" type="add">
952 Add support for configuration via Properties.
953 </action>
954 <action issue="LOG4J2-952" dev="rgoers" type="add">
955 Add ConfigurationBuilder for programmatic configuration.
956 </action>
957 <action issue="LOG4J2-1017" dev="ggregory" type="update">
958 Update Java platform from Java 6 to 7. From this version onwards, log4j 2 requires Java 7.
959 </action>
960 <action issue="LOG4J2-599" dev="rpopma" type="add">
961 Added support for Java 8 lambda expressions to lazily construct a log message only if
962 the requested log level is enabled.
963 </action>
964 <action issue="LOG4J2-1118" dev="rpopma" type="add">
965 Updated Logger wrapper generator tool to add Java 8 lambda support for custom log levels.
966 </action>
967 <action issue="LOG4J2-1107" dev="ggregory" type="add" due-to="Mikael Ståldal">
968 New Appender for Apache Kafka.
969 </action>
970 <action issue="LOG4J2-1113" dev="ggregory" type="add" due-to="Gary Gregory">
971 New publisher Appender for ZeroMQ (using JeroMQ).
972 </action>
973 <action issue="LOG4J2-1088" dev="ggregory" type="add" due-to="Gary Gregory">
974 Add Comma Separated Value (CSV) layouts for parameter and event logging.
975 </action>
976 <action issue="LOG4J2-812" dev="rgoers" type="update">
977 PatternLayout timestamp formatting performance improvement: replaced synchronized SimpleDateFormat with
978 Apache Commons FastDateFormat. This and better caching resulted in a ~3-30X faster timestamp formatting.
979 </action>
980 <action issue="LOG4J2-1097" dev="rpopma" type="update">
981 PatternLayout timestamp formatting performance improvement: predefined date formats (and variants using
982 a period '.' millisecond separator instead of ',') are now formatted ~2-10X faster than other date formats.
983 </action>
984 <action issue="LOG4J2-1096" dev="rpopma" type="update">
985 Improved performance of ParameterizedMessage::getFormattedMessage by ~2X.
986 </action>
987 <action issue="LOG4J2-1120" dev="rpopma" type="update">
988 LoggerConfig performance improvements: avoid unnecessary lock acquisition, use more efficient data structure.
989 </action>
990 <action issue="LOG4J2-1125" dev="rpopma" type="update">
991 PatternLayout performance improvement by caching and reusing a ThreadLocal StringBuilder.
992 </action>
993 <action issue="LOG4J2-1121" dev="rpopma" type="fix">
994 Fixed potential race condition on reconfiguration. Introduced ReliabilityStrategy to facilitate
995 switching between different mechanisms for preventing log events from being dropped on reconfiguration.
996 </action>
997 <action issue="LOG4J2-1114" dev="ggregory" type="update">
998 Add thread name to status logger layout.
999 </action>
1000 <action issue="LOG4J2-1123" dev="ggregory" type="fix">
1001 Core Configurator.initialize(String, ClassLoader, String) fails to work when config location is a file path.
1002 </action>
1003 <action issue="LOG4J2-1117" dev="ggregory" type="fix" due-to="Marcus Thiesen">
1004 OutputStreamManager in ConsoleAppender leaking managers.
1005 </action>
1006 <action issue="LOG4J2-1044" dev="rgoers" type="fix">
1007 Write pending events to Flume when the appender is stopped.
1008 </action>
1009 <action issue="LOG4J2-1108" dev="ggregory" type="fix" due-to="Mikael Ståldal">
1010 NullPointerException when passing null to java.util.logging.Logger.setLevel().
1011 </action>
1012 <action issue="LOG4J2-1110" dev="ggregory" type="fix">
1013 org.apache.logging.log4j.jul.CoreLogger.setLevel() checks for security permission too late.
1014 </action>
1015 <action dev="rpopma" type="remove">
1016 Removed experimental interface LevelLogger which got committed to master by mistake.
1017 </action>
1018 <action issue="LOG4J2-1010" dev="rgoers" type="update">
1019 Pass log event when interpolating logger properties.
1020 </action>
1021 <action issue="LOG4J2-1090" dev="ggregory" type="add">
1022 Add Core Configurator APIs to change a logger's level.
1023 </action>
1024 <action issue="LOG4J2-1105" dev="ggregory" type="add" due-to="Gary Gregory">
1025 Add API org.apache.logging.log4j.Level.isInRange(Level, Level).
1026 </action>
1027 <action issue="LOG4J2-1106" dev="ggregory" type="add" due-to="Gary Gregory">
1028 Add a LevelRangeFilter class.
1029 </action>
1030 <action issue="LOG4J2-1074" dev="rpopma" type="add">
1031 Added support for system nanosecond time in pattern layout.
1032 </action>
1033 <action issue="LOG4J2-1075" dev="rpopma" type="add">
1034 Added support for compressing to bzip2 format on file rollover.
1035 </action>
1036 <action issue="LOG4J2-1077" dev="ggregory" type="add">
1037 Support additional Apache Commons Compress compression formats on rollover: Deflate, Pack200, XY.
1038 </action>
1039 <action issue="LOG4J2-767" dev="ggregory" type="add" due-to="Mikael Ståldal">
1040 New module for Liquibase integration.
1041 </action>
1042 <action issue="LOG4J2-1023" dev="ggregory" type="add" due-to="Mikael Ståldal">
1043 New RewritePolicy for changing level of a log event.
1044 </action>
1045 <action issue="LOG4J2-1015" dev="ggregory" type="add" due-to="Daniel Marcotte">
1046 Add a way to route messages based on the %marker in Layout for RoutingAppender.
1047 </action>
1048 <action issue="LOG4J2-1050" dev="ggregory" type="add" due-to="Adam Retter">
1049 Add a Log4jLookup class to help write log files relative to log4j2.xml.
1050 </action>
1051 <action issue="LOG4J2-1057" dev="ggregory" type="add">
1052 Add API org.apache.logging.log4j.LogManager.getFormatterLogger().
1053 </action>
1054 <action issue="LOG4J2-1066" dev="ggregory" type="add" due-to="Charles Allen">
1055 Expose Log4jContextFactory's ShutdownCallbackRegistry.
1056 </action>
1057 <action issue="LOG4J2-1084" dev="ggregory" type="fix" due-to="Philipp Schneider">
1058 Misleading StatusLogger WARN event in LogManager with java.util.Map.
1059 </action>
1060 <action issue="LOG4J2-1051" dev="ggregory" type="fix" due-to="Lukasz Lenart">
1061 NoClassDefFoundError when starting app on Google App Engine.
1062 </action>
1063 <action issue="LOG4J2-684" dev="ggregory" type="fix" due-to="Joern Huxhorn, Mauro Molinari">
1064 ExtendedThrowablePatternConverter does not print suppressed exceptions.
1065 </action>
1066 <action issue="LOG4J2-1069" dev="ggregory" type="fix" due-to="Sam Braam">
1067 Improper handling of JSON escape chars when deserializing JSON log events.
1068 </action>
1069 <action issue="LOG4J2-1068" dev="ggregory" type="fix" due-to="Andy McMullan">
1070 Exceptions not logged when using TcpSocketServer + SerializedLayout.
1071 </action>
1072 <action issue="LOG4J2-1067" dev="ggregory" type="fix" due-to="Sam Braam">
1073 ThrowableProxy getExtendedStackTraceAsString throws NPE on deserialized nested exceptions.
1074 </action>
1075 <action issue="LOG4J2-1049" dev="rpopma" type="fix" due-to="Robert Schaft">
1076 AsyncAppender now resets the thread interrupted flag after catching InterruptedException.
1077 </action>
1078 <action issue="LOG4J2-1048" dev="rpopma" type="fix" due-to="Nikhil">
1079 FileConfigurationMonitor unnecessarily calls System.currentTimeMillis() causing high CPU usage.
1080 </action>
1081 <action issue="LOG4J2-1037" dev="ggregory" type="fix" due-to="Marc Dergacz">
1082 Backward compatibility issue in log4j-1.2-api NDC pop() and peek().
1083 </action>
1084 <action issue="LOG4J2-1025" dev="ggregory" type="fix" due-to="Mikael Ståldal">
1085 Custom java.util.logging.Level gives null Log4j Level and causes NPE.
1086 </action>
1087 <action issue="LOG4J2-1033" dev="ggregory" type="fix" due-to="Mikael Ståldal">
1088 SimpleLogger creates unnecessary Map objects by calling ThreadContext.getContext() instead of getImmutableContext().
1089 </action>
1090 <action issue="LOG4J2-1026" dev="ggregory" type="fix">
1091 HighlightConverter does not obey noConsoleNoAnsi.
1092 </action>
1093 <action issue="LOG4J2-1019" dev="ggregory" type="fix">
1094 ZipCompressAction leaves files open until GC when an IO error takes place.
1095 </action>
1096 <action issue="LOG4J2-1020" dev="ggregory" type="fix">
1097 GzCompressAction leaves files open until GC when an IO error takes place.
1098 </action>
1099 <action issue="LOG4J2-1038" dev="ggregory" type="fix" due-to="Gili">
1100 Incorrect documentation for layout default charset.
1101 </action>
1102 <action issue="LOG4J2-1042" dev="ggregory" type="fix" due-to="Guillaume Turri">
1103 Socket and Syslog appenders don't take timeout into account at startup.
1104 </action>
1105 <action issue="LOG4J2-934" dev="ggregory" type="fix" due-to="Kenneth Gendron">
1106 Circular suppressed Exception throws StackOverflowError.
1107 </action>
1108 <action issue="LOG4J2-1046" dev="ggregory" type="fix" due-to="Kenneth Gendron">
1109 Circular Exception cause throws StackOverflowError.
1110 </action>
1111 <action issue="LOG4J2-982" dev="ggregory" type="fix" due-to="Mikhail Mazurskiy">
1112 Use System.nanoTime() to measure time intervals.
1113 </action>
1114 <action issue="LOG4J2-1045" dev="ggregory" type="fix" due-to="Günter Albrecht">
1115 Externalize log4j2.xml via URL resource.
1116 </action>
1117 <action issue="LOG4J2-1058" dev="ggregory" type="fix" due-to="Daniel Branzea">
1118 Log4jMarker#contains(String) does not respect org.slf4j.Marker contract.
1119 </action>
1120 <action issue="LOG4J2-1060" dev="ggregory" type="fix">
1121 Log4jMarker#contains(Marker) does not respect org.slf4j.Marker contract.
1122 </action>
1123 <action issue="LOG4J2-1061" dev="ggregory" type="fix">
1124 Log4jMarker#remove(Marker) does not respect org.slf4j.Marker contract.
1125 </action>
1126 <action issue="LOG4J2-1062" dev="ggregory" type="fix">
1127 Log4jMarker#add(Marker) does not respect org.slf4j.Marker contract.
1128 </action>
1129 <action issue="LOG4J2-1064" dev="ggregory" type="fix">
1130 org.apache.logging.slf4j.Log4jMarker does not implement org.slf4j.Marker.equals(Object) org.slf4j.Marker.hashCode().
1131 </action>
1132 <action issue="LOG4J2-889" dev="rpopma" type="fix" due-to="Maciej Karaś, Kenneth Leider">
1133 Header in layout should not be written on application startup if appending to an existing file. Fixes LOG4J2-1030.
1134 </action>
1135 <action issue="LOG4J2-918" dev="rpopma" type="fix">
1136 Clarify documentation for combining async with sync loggers.
1137 </action>
1138 <action issue="LOG4J2-1078" dev="ggregory" type="fix" due-to="Mikael Ståldal">
1139 GelfLayout throws exception if some log event fields are null.
1140 </action>
1141 <action issue="LOG4J2-1044" dev="rgoers" type="update">
1142 Support batchSize in FlumeAvroManager.
1143 </action>
1144 <action issue="LOG4J2-1065" dev="ggregory" type="update">
1145 Define org.apache.logging.log4j.Marker.equals(Object) and org.apache.logging.log4j.Marker.hashCode().
1146 </action>
1147 <action issue="LOG4J2-1063" dev="ggregory" type="update">
1148 Avoid creating temporary array object in org.apache.logging.slf4j.Log4jMarker.iterator().
1149 </action>
1150 <action issue="LOG4J2-890" dev="ggregory" type="update" due-to="Hassan Kalaldeh, Robert Andersson, Remko Popma">
1151 log4j-web-2.1 should workaround a bug in JBOSS EAP 6.2.
1152 </action>
1153 <action issue="LOG4J2-403" dev="ggregory" type="update" due-to="Poorna Subhash P, Jeremy Lautman">
1154 MongoDB appender, username and password should be optional.
1155 </action>
1156 <action issue="LOG4J2-1035" dev="ggregory" type="update">
1157 Log4j2 tries to SystemClassLoader when running on Google AppEngine.
1158 </action>
1159 <action issue="LOG4J2-1022" dev="rgoers" type="update">
1160 Allow a list of keys to be specified in the MDC pattern converter.
1161 </action>
1162 <action issue="LOG4J2-959" dev="ggregory" type="update">
1163 Fix FindBugs DM_DEFAULT_ENCODING bug in SimpleLogger.logMessage() and simplify code.
1164 </action>
1165 <action issue="LOG4J2-1036" dev="ggregory" type="update">
1166 Update Apache Flume from 1.5.2 to 1.6.0.
1167 </action>
1168 <action issue="LOG4J2-1041" dev="ggregory" type="update">
1169 Update MongoDB driver from 2.11.2 to 2.13.2.
1170 </action>
1171 <action issue="LOG4J2-1018" dev="ggregory" type="update">
1172 Update database tests from H2 1.3.175 to 1.3.176.
1173 </action>
1174 <action issue="LOG4J2-1070" dev="ggregory" type="update">
1175 Update Java Mail from 1.5.2 to 1.5.4.
1176 </action>
1177 <action issue="LOG4J2-1079" dev="ggregory" type="update">
1178 Update Jackson from 2.5.3 to 2.5.4.
1179 </action>
1180 <action issue="LOG4J2-1879" dev="ggregory" type="update">
1181 Update Jackson from 2.5.4 to 2.6.0.
1182 </action>
1183 <action issue="LOG4J2-1092" dev="ggregory" type="update">
1184 Update Jackson from 2.6.0 to 2.6.1.
1185 </action>
1186 <action issue="LOG4J2-1104" dev="ggregory" type="update">
1187 Update Apache Commons Compress from 1.9 to 1.10.
1188 </action>
1189 </release>
1190 <release version="2.3" date="2015-05-09" description="GA Release 2.3">
1191 <action issue="LOG4J2-1009" dev="ggregory" type="fix" due-to="Mikael Ståldal">
1192 Incorrectly defined compressionType parameter to GelfLayout.
1193 </action>
1194 <action issue="LOG4J2-1008" dev="ggregory" type="fix" due-to="Ralph Goers, Gary Gregory">
1195 org.apache.logging.log4j.core.config.plugins.util.ResolverUtil.extractPath(URL) incorrectly converts '+' characters to spaces.
1196 </action>
1197 <action issue="LOG4J2-1007" dev="ggregory" type="fix" due-to="Ralph Goers, Gary Gregory">
1198 org.apache.logging.log4j.core.util#fileFromUri(URI uri) incorrectly converts '+' characters to spaces.
1199 </action>
1200 <action issue="LOG4J2-1003" dev="ggregory" type="fix" due-to="Dan Armbrust">
1201 JUL Logger.throwing is mis-mapped to ERROR when it should be TRACE.
1202 </action>
1203 <action issue="LOG4J2-965" dev="ggregory" type="fix" due-to="Khotyn Huang">
1204 System.out no longer works after the Console appender and JANSI are initialized.
1205 </action>
1206 <action issue="LOG4J2-998" dev="ggregory" type="update" due-to="Mariano Gonzalez">
1207 Make org.apache.logging.log4j.core.Logger#updateConfiguration protected.
1208 </action>
1209 <action issue="LOG4J2-995" dev="rgoers" type="update">
1210 Move UTF-8 constant from Charsets to Constants class. Remove Charsets class.
1211 </action>
1212 <action issue="LOG4J2-993" dev="rgoers" type="fix">
1213 Deadlock would occur if appender thread creates a new Logger during reconfiguration.
1214 </action>
1215 <action issue="LOG4J2-991" dev="rpopma" type="fix" due-to="Ryan Rupp">
1216 Async root logger config should default includeLocation to false.
1217 </action>
1218 <action issue="LOG4J2-985" dev="rpopma" type="fix" due-to="Sean Dawson">
1219 AbstractFilter should not implement equals() and hashCode().
1220 </action>
1221 <action issue="LOG4J2-984" dev="ggregory" type="add" due-to="Jonas Höpfner">
1222 PatternLayout %highlight to support noConsoleNoAnsi like %style.
1223 </action>
1224 <action issue="LOG4J2-926" dev="ggregory" type="add" due-to="David Ohana">
1225 Truncate from the end of text format modifier.
1226 </action>
1227 <action issue="LOG4J2-980" dev="ggregory" type="fix" due-to="Mikhail Mazurskiy">
1228 Numerical overflow in BurstFilter not handled correctly.
1229 </action>
1230 <action issue="LOG4J2-981" dev="ggregory" type="fix" due-to="Mikhail Mazurskiy">
1231 Incorrect unlock in ProviderUtil.
1232 </action>
1233 <action issue="LOG4J2-966" dev="ggregory" type="fix">
1234 KeyStoreConfiguration.createKeyStoreConfiguration() ignores keyManagerFactoryAlgorithm.
1235 </action>
1236 <action issue="LOG4J2-976" dev="ggregory" type="fix" due-to="Matt Quinn">
1237 Using monitorInterval with YAML config file format causes JSONParseException.
1238 </action>
1239 <action issue="LOG4J2-964" dev="ggregory" type="fix" due-to="Jonne Jyrylä">
1240 StringFormattedMessage serialization is incorrect.
1241 </action>
1242 <action issue="LOG4J2-947" dev="ggregory" type="fix" due-to="Stefan Wehner">
1243 A new StatusLoggerAdmin listener is added to StatusLogger every time the log is reconfigured.
1244 </action>
1245 <action issue="LOG4J2-968" dev="ggregory" type="fix" due-to="Paul D Johe">
1246 SyslogLayout contains extra space.
1247 </action>
1248 <action issue="LOG4J2-967" dev="ggregory" type="fix" due-to="Stefan Wehner">
1249 log4j2.component.properties not read for all properties.
1250 </action>
1251 <action issue="LOG4J2-971" dev="ggregory" type="fix" due-to="Paul D Johe">
1252 Another bad priority in Syslog messages.
1253 </action>
1254 <action issue="LOG4J2-972" dev="ggregory" type="fix">
1255 org.apache.logging.log4j.core.net.ssl.TlsSyslogInputStreamReader does not need to create temp Integer objects.
1256 </action>
1257 <action issue="LOG4J2-974" dev="ggregory" type="fix" due-to="Daniel Galán y Martins">
1258 Typo in EventLogger documentation.
1259 </action>
1260 <action issue="LOG4J2-988" dev="ggregory" type="update">
1261 Update LMAX Disruptor from 3.3.0 to 3.3.2.
1262 </action>
1263 <action issue="LOG4J2-987" dev="ggregory" type="update">
1264 Migrate tests from Logback 1.1.2 to 1.1.3.
1265 </action>
1266 <action issue="LOG4J2-988" dev="ggregory" type="update">
1267 Update tests to use ActiveMQ from 5.10 to 5.11.1.
1268 </action>
1269 <action issue="LOG4J2-1004" dev="ggregory" type="update">
1270 Update Jackson from 2.5.1 to 2.5.3.
1271 </action>
1272 <action issue="LOG4J2-1005" dev="ggregory" type="update">
1273 Update Slf4j from 1.7.7 to 1.7.12.
1274 </action>
1275 </release>
1276 <release version="2.2" date="2015-02-22" description="GA Release 2.2">
1277 <action issue="LOG4J2-938" dev="rpopma" type="fix" due-to="Mauro Molinari">
1278 (JMX) To avoid memory leaks when web applications are restarted, JMX notifications are sent from
1279 the caller thread in web applications. For non-web applications notifications are sent from a background thread
1280 as before.
1281 </action>
1282 <action issue="LOG4J2-957" dev="ggregory" type="fix" due-to="fatih guleryuz">
1283 Missing toUpperCase(Locale.ENGLISH).
1284 </action>
1285 <action issue="LOG4J2-956" dev="ggregory" type="fix" due-to="David Kellerman">
1286 Manual refers to Route "AppenderRef" attribute, should be "ref".
1287 </action>
1288 <action issue="LOG4J2-955" dev="rpopma" type="update">
1289 Documentation: clarify system properties to control status logger, improve troubleshooting FAQ entry.
1290 </action>
1291 <action issue="LOG4J2-950" dev="ggregory" type="update" due-to="Joel Edwards">
1292 Incorrect attribute name in PropertiesRewritePolicy example.
1293 </action>
1294 <action issue="LOG4J2-944" dev="ggregory" type="fix" due-to="Vinayaka Ramachandra">
1295 Log4j Flume appender is not adding millisecond to the event headers when the event is logged at 000 milliseconds.
1296 </action>
1297 <action issue="LOG4J2-941" dev="ggregory" type="add" due-to="Konstantinos Liakos">
1298 Allow JSON layout to create one compact log record per line.
1299 </action>
1300 <action issue="LOG4J2-933" dev="ggregory" type="add" due-to="ppiman at gmail.com">
1301 HTML layout should not use attribute minimalization for hr noshade.
1302 </action>
1303 <action issue="LOG4J2-895" dev="ggregory" type="add">
1304 Specify the SyslogAppender connect timeout value as part of the configuration.
1305 The SyslogAppender takes a new parameter connectTimeoutMillis.
1306 </action>
1307 <action issue="LOG4J2-899" dev="ggregory" type="add">
1308 Specify the SocketAppender connect timeout value as part of the configuration.
1309 The SyslogAppender takes a new parameter connectTimeoutMillis.
1310 </action>
1311 <action issue="LOG4J2-924" dev="ggregory" type="fix" due-to="Ryan Rupp">
1312 Log4j 1.2 Bridge doesn't map level ALL correctly in Category.getEffectiveLevel().
1313 </action>
1314 <action issue="LOG4J2-931" dev="ggregory" type="fix" due-to="Robert Gacki">
1315 ConsoleAppender is missing @PluginFactory annotation at createAppender method.
1316 </action>
1317 <action issue="LOG4J2-919" dev="ggregory" type="fix" due-to="David Johle">
1318 Logging system fails to initialize if XInclude API is not available.
1319 </action>
1320 <action issue="LOG4J2-914" dev="ggregory" type="fix" due-to="Kaj Bjurman">
1321 ThrowableProxy.getExtendedStackTraceAsString causes NullPointerException.
1322 </action>
1323 <action issue="LOG4J2-912" dev="ggregory" type="fix">
1324 XML configuration does not report full error message for XInclude parser configuration problems.
1325 </action>
1326 <action issue="LOG4J2-903" dev="ggregory" type="fix" due-to="Mauro Molinari">
1327 ClassLoaderContextSelector uses ClassLoader.toString() as a key
1328 </action>
1329 <action issue="LOG4J2-834" dev="ggregory" type="fix" due-to="Nikita Koval, Leonard Broman, Thiago Kronig">
1330 ThrowableProxy throws NoClassDefFoundError.
1331 </action>
1332 <action issue="LOG4J2-893" dev="ggregory" type="fix">
1333 NullPointerException on filter when mapping JUL to Log4j2.
1334 </action>
1335 <action issue="LOG4J2-892" dev="ggregory" type="fix">
1336 JUL adapter does not map Log4j'2 FATAL level to a JUL level.
1337 </action>
1338 <action issue="LOG4J2-881" dev="ggregory" type="fix" due-to="Mariano Gonzalez">
1339 AbstractLifecycle should not implement equals() and hashCode().
1340 </action>
1341 <action issue="LOG4J2-897" dev="ggregory" type="fix">
1342 Javadoc for org.apache.log4j.BasicConfigurator.configure() is incorrect.
1343 </action>
1344 <action issue="LOG4J2-891" dev="ggregory" type="fix">
1345 AbstractLifecycle should not implement equals() and hashCode().
1346 </action>
1347 <action issue="LOG4J2-946" dev="ggregory" type="fix" due-to="artemonster">
1348 [docs] Using Log4j 2 in Web Applications: Update example (Log4jWebLifeCycle is not visible).
1349 </action>
1350 <action issue="LOG4J2-901" dev="ggregory" type="update" due-to="Tihomir Meščić, Siegfried Greisinger">
1351 Update docs for SyslogAppender: "No structured id name was supplied"
1352 </action>
1353 <action issue="LOG4J2-958" dev="ggregory" type="update">
1354 Update from Jackson 2.5.0 to 2.5.1.
1355 </action>
1356 <action issue="LOG4J2-925" dev="ggregory" type="update">
1357 Update from Jackson 2.4.4 to 2.5.0.
1358 </action>
1359 <action issue="LOG4J2-910" dev="ggregory" type="update">
1360 Update Jackson from 2.4.3 to 2.4.4.
1361 </action>
1362 <action issue="LOG4J2-881" dev="ggregory" type="update">
1363 Update Jackson from 2.4.2 to 2.4.3.
1364 </action>
1365 <action issue="LOG4J2-882" dev="ggregory" type="update">
1366 Update maven-core from 3.1.0 to 3.2.3.
1367 </action>
1368 <action issue="LOG4J2-883" dev="ggregory" type="update">
1369 Update tests from org.apache.felix.framework 4.2.1 to 4.4.1.
1370 </action>
1371 <action issue="LOG4J2-884" dev="ggregory" type="update">
1372 Update org.eclipse.osgi from 3.6.0 to 3.7.1.
1373 </action>
1374 <action issue="LOG4J2-900" dev="ggregory" type="update">
1375 Update Apache Flume from 1.5.0.1 to 1.5.2.
1376 </action>
1377 </release>
1378 <release version="2.1" date="2014-10-19" description="GA Release 2.1">
1379 <action issue="LOG4J2-676" dev="rgoers" type="fix" due-to="Stefan Bodewig">
1380 Some typo fixes and enhancements for the site.
1381 </action>
1382 <action issue="LOG4J2-868" dev="mattsicker" type="add">
1383 Add ShutdownCallbackRegistry interface for customizable shutdown callback handling. This is particularly
1384 useful for application servers that wish to integrate with Log4j 2.
1385 </action>
1386 <action issue="LOG4J2-866" dev="rpopma" type="fix" due-to="Gerard Weatherby">
1387 Documentation: fixed missing closing parenthesis in code example.
1388 </action>
1389 <action issue="LOG4J2-862" dev="mattsicker" type="fix" due-to="Michael Sutherland">
1390 Fixed classloader issue that prevented Log4j from finding the implementation when used in a custom Ant task.
1391 </action>
1392 <action issue="LOG4J2-589" dev="rpopma" type="add">
1393 Supported filtering on custom log levels in configuration.
1394 </action>
1395 <action issue="LOG4J2-861" dev="rpopma" type="fix">
1396 Documentation: fix broken links on left navigation Extending Log4j Configuration sub-menu.
1397 </action>
1398 <action issue="LOG4J2-856" dev="rpopma" type="add">
1399 Documentation: add sections on the JUL Adapter, IO Streams and NoSQL Appenders to the Maven and Ivy page.
1400 </action>
1401 <action issue="LOG4J2-797" dev="rpopma" type="fix" due-to="Andreas Rytina">
1402 Documentation: clarified why log4j-core is a compile time dependency in Maven and Ivy page.
1403 </action>
1404 <action issue="LOG4J2-855" dev="rpopma" type="fix">
1405 Documentation: fix broken links on Appenders manual page.
1406 </action>
1407 <action issue="LOG4J2-807" dev="rpopma" type="fix">
1408 Prevent NPE when configuration with AsyncLogger/AsyncRoot is reloaded.
1409 </action>
1410 <action issue="LOG4J2-848" dev="ggregory" type="add">
1411 Add a Java lookup to provide nicely formatted runtime version information.
1412 </action>
1413 <action issue="LOG4J2-809" dev="mattsicker" type="add">
1414 Move reflection utility class to API's private utility classes.
1415 </action>
1416 <action issue="LOG4J2-845" dev="mattsicker" type="update">
1417 Add 2.1.0 to compatible versions in Log4j API ProviderUtil and update Log4jAPIVersion to 2.1.0 in
1418 core META-INF/log4j-provider.properties.
1419 </action>
1420 <action issue="LOG4J2-833" dev="rpopma" type="add">
1421 Documentation: added Runtime Dependencies link to left nav-bar on site.
1422 </action>
1423 <action issue="LOG4J2-816" dev="rpopma" type="add">
1424 Documentation: added section on XInclude to user manual Configuration page.
1425 </action>
1426 <action issue="LOG4J2-678" dev="rpopma" type="fix" due-to="Matt Sicker">
1427 Documentation: fixed minor issues with Log4j2 web site/documentation.
1428 </action>
1429 <action issue="LOG4J2-844" dev="rpopma" type="update">
1430 Update JMH to 1.1 from 0.7.2.
1431 </action>
1432 <action issue="LOG4J2-843" dev="rpopma" type="fix">
1433 Migrate JpaHyperSqlAppenderTest JUnit performance test to log4j-perf.
1434 </action>
1435 <action issue="LOG4J2-842" dev="rpopma" type="fix">
1436 Migrate JpaH2AppenderTest JUnit performance test to log4j-perf.
1437 </action>
1438 <action issue="LOG4J2-841" dev="rpopma" type="fix">
1439 Migrate JdbcHyperSqlAppenderTest JUnit performance test to log4j-perf.
1440 </action>
1441 <action issue="LOG4J2-840" dev="rpopma" type="fix">
1442 Migrate JdbcH2AppenderTest JUnit performance test to log4j-perf.
1443 </action>
1444 <action issue="LOG4J2-830" dev="rpopma" type="fix">
1445 Respect external interrupt signal to allow application shutdown after joining AsyncAppender thread.
1446 </action>
1447 <action issue="LOG4J2-813" dev="ggregory" type="fix" due-to="David Erichsen, Brandon Barry">
1448 MarkerManager Log4jMarker.hasParents() returns opposite of correct result.
1449 </action>
1450 <action issue="LOG4J2-785" dev="rpopma" type="fix">
1451 Documentation: fixed capitalization inconsistency in user manual example config.
1452 </action>
1453 <action issue="LOG4J2-829" dev="rpopma" type="fix">
1454 Fixed issue in RollingFile filePattern: backslashes are path separators, not escape characters.
1455 </action>
1456 <action issue="LOG4J2-547" dev="mattsicker" type="add">
1457 Add the Log4j IOStreams component.
1458 </action>
1459 <action issue="LOG4J2-431" dev="rpopma" type="add" due-to="Claude Mamo">
1460 Added Memory-Mapped File Appender.
1461 </action>
1462 <action issue="LOG4J2-832" dev="ggregory" type="fix" due-to="Seth Leger">
1463 ThrowableProxy fails if a class in logged stack trace throws java.lang.Error from initializer
1464 </action>
1465 <action issue="LOG4J2-831" dev="rpopma" type="update">
1466 Documentation: updated FAQ "which jars" diagrams for JUL bridge and 2.1 version.
1467 </action>
1468 <action issue="LOG4J2-827" dev="mattsicker" type="add">
1469 Support use of TypeConverter classes through the standard Plugin system.
1470 </action>
1471 <action issue="LOG4J2-745" dev="mattsicker" type="fix" due-to="Scott Harrington">
1472 Avoid ConverterKey plugin clashes by using a more predictable plugin loading infrastructure.
1473 Plugins have been segmented into three parts: class path, user-specified packages, and OSGi bundles.
1474 </action>
1475 <action issue="LOG4J2-798" dev="mattsicker" type="fix" due-to="Scott Harrington">
1476 Fixed plugin scanning redundancy causing massive slowdowns in certain environments.
1477 </action>
1478 <action issue="LOG4J2-753" dev="rpopma" type="fix">
1479 Reduced CachedClock thread contention.
1480 </action>
1481 <action issue="LOG4J2-819" dev="mattsicker" type="fix" due-to="Gary Gregory">
1482 Fixed memory leak in Tomcat 6 caused by clock background threads unintentionally
1483 started by Tomcat after web application stop.
1484 </action>
1485 <action issue="LOG4J2-825" dev="mattsicker" type="add">
1486 Add simple validation constraint annotations for the Plugin system.
1487 </action>
1488 <action issue="LOG4J2-428" dev="ggregory" type="add" due-to="Mark Paluch, Mikael Ståldal">
1489 Implement a GELF layout.
1490 </action>
1491 <action issue="LOG4J2-391" dev="rgoers" type="fix" due-to="Kamal Bahadur">
1492 FlumePersistentManager now handles LockConflictExceptions in Berkeley Db when sending a batch.
1493 </action>
1494 <action issue="LOG4J2-782" dev="mattsicker" type="fix">
1495 Remove invalid Oracle Maven repository.
1496 </action>
1497 <action issue="LOG4J2-780" dev="mattsicker" type="update">
1498 Update Spring Framework to 3.2.11.RELEASE from 3.2.8.RELEASE.
1499 </action>
1500 <action issue="LOG4J2-815" dev="mattsicker" type="update">
1501 Unify the two JMS appenders into a single appender. Configurations written for 2.0 will still work in 2.1+.
1502 </action>
1503 <action issue="LOG4J2-608" dev="mattsicker" type="add">
1504 Add java.util.logging implementation based on log4j-api. See log4j-jul documentation for more details.
1505 </action>
1506 <action issue="LOG4J2-796" dev="rpopma" type="fix">
1507 Fixed issue where log4j-to-slf4j did not work correctly with SLF4J Simple Logger.
1508 </action>
1509 <action issue="LOG4J2-811" dev="ggregory" type="fix" due-to="Yogesh Rao">
1510 SimpleLogger throws ArrayIndexOutOfBoundsException for an empty array.
1511 </action>
1512 <action issue="LOG4J2-663" dev="mattsicker" type="fix" due-to="Florian Brunner">
1513 Fix OSGi Import-Package problem with the JMS API.
1514 </action>
1515 <action issue="LOG4J2-793" dev="mattsicker" type="add">
1516 Add support for custom SLF4J Markers in log4j-slf4j-impl module.
1517 </action>
1518 <action issue="LOG4J2-783" dev="rpopma" type="fix" due-to="Minglei Lee">
1519 PatternLayout should use platform character encoding by default, not UTF-8.
1520 </action>
1521 <action issue="LOG4J2-771" dev="ggregory" type="add">
1522 Add lookup for application main arguments.
1523 </action>
1524 <action issue="LOG4J2-787" dev="ggregory" type="add">
1525 Add lookup for JVM arguments.
1526 </action>
1527 <action issue="LOG4J2-790" dev="ggregory" type="update">
1528 Update Jackson to 2.4.2 from 2.4.1 (for XML and JSON processing).
1529 </action>
1530 <action issue="LOG4J2-766" dev="ggregory" type="update" due-to="Bruno P. Kinoshita">
1531 Incomplete documentation for JSONLayout.
1532 </action>
1533 <action issue="LOG4J2-800" dev="ggregory" type="update">
1534 All life cycle implementations should be serializable.
1535 This is still work in progress.
1536 </action>
1537 <action issue="LOG4J2-801" dev="ggregory" type="update">
1538 org.apache.logging.log4j.core.Logger should be serializable.
1539 This is still work in progress.
1540 </action>
1541 <action issue="LOG4J2-810" dev="ggregory" type="update">
1542 Update javax.mail to 1.5.2 from 1.5.0.
1543 </action>
1544 <action issue="LOG4J2-822" dev="ggregory" type="update">
1545 Update org.eclipse.persistence.jpa to 2.5.2 from 2.5.1.
1546 </action>
1547 <action issue="LOG4J2-867" dev="ggregory" type="update">
1548 FlumeAppender: maxDelay not in seconds, but milliseconds.
1549 Add time scale to some settings, for example maxDelayMillis instead of maxDelay.
1550 The old names are aliased for compatibility.
1551 </action>
1552 </release>
1553 <release version="2.0.2" date="2014-08-16" description="Bug fixes and enhancements">
1554 <action issue="LOG4J2-775" dev="ggregory" type="update">
1555 Update Apache Flume to 1.5.0.1 from 1.5.0.
1556 </action>
1557 <action issue="LOG4J2-773" dev="rpopma" type="fix">
1558 Site: log4j-core component pages were still using the old logo.
1559 </action>
1560 <action issue="LOG4J2-760" dev="rpopma" type="fix">
1561 Documentation improvement: link to dependency tree from log4j-core component page,
1562 link to log4j-core component page from FAQ page.
1563 </action>
1564 <action issue="LOG4J2-679" dev="rpopma" type="fix">
1565 Resolved race condition that caused log file rotation to fail with error: "Unable to create directory ..."
1566 </action>
1567 <action issue="LOG4J2-726" dev="rpopma" type="fix">
1568 Prevent application from hanging when PatternLayout configuration has opening '{' but no closing '}'.
1569 </action>
1570 <action issue="LOG4J2-769" dev="rpopma" type="fix" due-to="Scott Harrington">
1571 Startup takes a long time if you have empty packages attribute.
1572 </action>
1573 <action issue="LOG4J2-763" dev="rpopma" type="fix" due-to="Stephen Connolly">
1574 Improved asynchronous loggers and appenders to ensure the formatted message does not change even if
1575 parameters are modified by the application. (ParameterizedMessage was already safe.)
1576 Improved documentation.
1577 </action>
1578 <action issue="LOG4J2-729" dev="rpopma" type="fix">
1579 Emit warning message to console if no configuration file found.
1580 </action>
1581 <action issue="LOG4J2-765" dev="rpopma" type="fix">
1582 Improve warning message when missing log4j-core in the classpath.
1583 </action>
1584 <action issue="LOG4J2-722" dev="rpopma" type="fix">
1585 Clarified in documentation that Commons Logging jar is required when using log4j-jcl.
1586 </action>
1587 <action issue="LOG4J2-723" dev="rpopma" type="fix">
1588 Clarified in documentation that SLF4J API jar is required when using log4j-slf4j-impl.
1589 </action>
1590 <action issue="LOG4J2-730" dev="rpopma" type="update">
1591 Allow Log4jContextFactory subclasses to specify a custom ContextSelector.
1592 </action>
1593 <action issue="LOG4J2-759" dev="rpopma" type="fix">
1594 Fixed various minor site/documentation issues, mostly versioning related.
1595 </action>
1596 <action issue="LOG4J2-756" dev="rpopma" type="fix" due-to="Scott Harrington">
1597 Prevent JUnit test from creating unnecessary Log4j2Plugins.dat during build.
1598 </action>
1599 </release>
1600 <release version="2.0.1" date="2014-07-29" description="Bug fixes">
1601 <action issue="LOG4J2-744" dev="rpopma" type="fix" due-to="Scott Harrington">
1602 Avoid unnecessary Clock calls when TimestampMessage is logged.
1603 </action>
1604 <action issue="LOG4J2-704" dev="rpopma" type="fix">
1605 Improved error message if configuration file not found.
1606 </action>
1607 <action issue="LOG4J2-750" dev="ggregory" type="fix" due-to="Mike Calmus">
1608 Webapp configuration page has incorrect class name.
1609 </action>
1610 <action issue="LOG4J2-749" dev="rpopma" type="fix" due-to="Scott Harrington">
1611 Retain the default date pattern after fixing the ISO8601 pattern.
1612 </action>
1613 <action issue="LOG4J2-670" dev="rpopma" type="fix">
1614 DatePatternConverter ISO8601_PATTERN now conforms to ISO8601.
1615 </action>
1616 <action issue="LOG4J2-741" dev="rpopma" type="fix">
1617 Reinstate the package configuration attribute for discovering custom plugins.
1618 </action>
1619 <action issue="LOG4J2-742" dev="ggregory" type="fix" due-to="Pascal Chollet">
1620 XInclude not working with relative path.
1621 </action>
1622 <action issue="LOG4J2-740" dev="mattsicker" type="fix" due-to="Kosta Krauth">
1623 Fixed typo in webapp manual regarding sample web.xml file.
1624 </action>
1625 <action issue="LOG4J2-738" dev="ggregory" type="fix" due-to="Timothy Stack">
1626 RollingFileManager deadlock if async action thread fails to start.
1627 </action>
1628 <action issue="LOG4J2-736" dev="mattsicker" type="fix">
1629 Fixed log4j-bom so that it won't specify a default scope on any third party dependencies.
1630 </action>
1631 <action issue="LOG4J2-735" dev="mattsicker" type="fix">
1632 Fixed log4j-bom so that it won't interfere with spring-bom and others.
1633 </action>
1634 <action issue="LOG4J2-731" dev="mattsicker" type="fix">
1635 Updated documentation regarding extensions to LoggerContextFactory and Log4j 2 providers.
1636 </action>
1637 <action issue="LOG4J2-373" dev="mattsicker" type="fix">
1638 Fixed ClassLoader issues in loading Log4j providers in an OSGi environment.
1639 </action>
1640 <action issue="LOG4J2-725" dev="mattsicker" type="add">
1641 Added WebLoggerContextUtils class to log4j-web for helper methods useful for asynchronous servlets.
1642 </action>
1643 <action issue="LOG4J2-710" dev="rpopma" type="add">
1644 Added documentation for Custom Levels and Custom Loggers.
1645 </action>
1646 <action issue="LOG4J2-719" dev="rpopma" type="fix">
1647 Correctly handle NetworkOnMainThreadException thrown on Android during Log4j2 initialization.
1648 </action>
1649 <action issue="LOG4J2-716" dev="rpopma" type="fix">
1650 Automatically disable log4j JMX when detecting we are running on Android.
1651 </action>
1652 <action issue="LOG4J2-657" dev="rpopma" type="fix" due-to="Stefan Wehner">
1653 Fixed AbstractDatabaseManager to close connection on writeInternal error.
1654 </action>
1655 <action issue="LOG4J2-713" dev="ggregory" type="fix" due-to="Nelson Melina">
1656 Android: java.lang.VerifyError: org/apache/logging/log4j/core/util/Closer
1657 </action>
1658 <action issue="LOG4J2-703" dev="ggregory" type="fix" due-to="Nelson Melina">
1659 Android: Could not find class 'javax.naming.InitialContext', referenced from method org.apache.logging.log4j.core.lookup.JndiLookup.lookup.
1660 </action>
1661 <action issue="LOG4J2-732" dev="ggregory" type="updated">
1662 Update to LMAX Disruptor 3.3.0 from 3.2.1.
1663 </action>
1664 <action issue="LOG4J2-733" dev="ggregory" type="updated">
1665 Update to latest Jackson jars from the 2.4.1.X line.
1666 </action>
1667 </release>
1668 <release version="2.0" date="2014-07-12" description="GA Release">
1669 <action issue="LOG4J2-705" dev="rpopma" type="fix">
1670 Fixed issue where Async Logger does not log thread context stack data.
1671 API change: added method getImmutableStackOrNull() to ThreadContext.ContextStack interface.
1672 </action>
1673 <action issue="LOG4J2-631" dev="rpopma" type="fix">
1674 Update docs to clarify how to use formatter logger and standard logger together.
1675 </action>
1676 <action issue="LOG4J2-519" dev="rpopma" type="add">
1677 Added support for generating custom logger wrappers that replace the existing log levels
1678 and extended logger wrappers that add custom log levels to the existing ones.
1679 </action>
1680 <action issue="LOG4J2-441" dev="rgoers" type="fix">
1681 LoggerConfigs with no Level now inherit the Level from their parent.
1682 </action>
1683 <action issue="LOG4J2-696" dev="ggregory" type="add">
1684 RegexFilter does not match multiline log messages.
1685 </action>
1686 <action issue="LOG4J2-699" dev="rpopma" type="fix">
1687 PatternLayout manual page missing documentation on header/footer.
1688 </action>
1689 <action issue="LOG4J2-625" dev="rpopma" type="fix">
1690 Fixed Serialization error with SocketAppender and Async Loggers.
1691 (Fixed in RC2, but wasn't included in release notes.)
1692 </action>
1693 <action issue="LOG4J2-538" dev="rpopma" type="fix">
1694 JMX GUI: fixed occasional ArrayIndexOutOfBoundsException after pressing "reconfigure with XML below".
1695 (Fixed in RC2, but wasn't included in release notes.)
1696 </action>
1697 <action issue="LOG4J2-666" dev="rpopma" type="fix">
1698 AsyncLoggerContextSelector should ensure that different AsyncLoggerContext objects created by web app classloaders have unique names.
1699 </action>
1700 <action issue="LOG4J2-683" dev="mattsicker" type="fix" due-to="Jurriaan Mous">
1701 Fix annotation processor warnings on JDK 1.7+.
1702 </action>
1703 <action issue="LOG4J2-694" dev="mattsicker" type="fix">
1704 Fix strange compilation error that popped up in a test class.
1705 </action>
1706 <action issue="LOG4J2-692" dev="rgoers" type="fix">
1707 Update documentation to specify only Maven 3 is supported.
1708 </action>
1709 <action issue="LOG4J2-690" dev="rgoers" type="fix" due-to="Philip Helger">
1710 Log4j Web test dependencies should be in scope "test" in the pom.
1711 </action>
1712 <action issue="LOG4J2-682" dev="ggregory" type="fix" due-to="Scott Harrington">
1713 Special characters (tab and so on) in PatternLayout do not work.
1714 </action>
1715 <action issue="LOG4J2-685" dev="ggregory" type="update">
1716 Make org.apache.logging.log4j.core.layout.AbstractLayout immutable.
1717 </action>
1718 <action issue="LOG4J2-686" dev="ggregory" type="fix">
1719 Core's OptionConverter support for \b is broken (affects PatternLayout).
1720 </action>
1721 <action issue="LOG4J2-687" dev="ggregory" type="fix">
1722 Rename org.apache.logging.log4j.core.util.Closer.closeSilent() to closeSilently().
1723 </action>
1724 <action issue="LOG4J2-688" dev="ggregory" type="fix">
1725 Make org.apache.logging.log4j.core.layout.PatternLayout immutable.
1726 </action>
1727 <action issue="LOG4J2-689" dev="ggregory" type="update">
1728 Update Jackson to 2.4.1.
1729 </action>
1730 <action issue="LOG4J2-707" dev="ggregory" type="fix">
1731 Some exceptions are not logged when configuration problems are detected.
1732 </action>
1733 <action issue="LOG4J2-709" dev="ggregory" type="update">
1734 Update Apache Commons Logging to 1.2 from 1.1.3.
1735 </action>
1736 </release>
1737 <release version="2.0-rc2" date="2014-06-21" description="Bug fixes and enhancements">
1738 <action issue="LOG4J2-675" dev="rpopma" type="add">
1739 RollingFile and RollingRandomAccessFile now write the layout footer before rollover.
1740 </action>
1741 <action issue="LOG4J2-581" dev="rpopma" type="fix" due-to="Alexander Khokhlov">
1742 RollingRandomAccessFile now writes the layout header after rollover.
1743 </action>
1744 <action issue="LOG4J2-622" dev="rpopma" type="fix" due-to="Farooq Khan">
1745 RollingFileManager now correctly honours the bufferedIO configuration after rollover.
1746 </action>
1747 <action issue="LOG4J2-674" dev="rpopma" type="add">
1748 Made RollingFileAppender buffer size configurable.
1749 </action>
1750 <action issue="LOG4J2-141" dev="rpopma" type="fix" due-to="Joern Huxhorn">
1751 Improved documentation regarding log4j status logger.
1752 </action>
1753 <action issue="LOG4J2-539" dev="rpopma" type="fix" due-to="Colin Froggatt">
1754 Fixed issue with "Reconfigure using XML below" function in JMX Client GUI.
1755 ConfigurationSource is now a top-level class and can be obtained with Configuration.getConfigurationSource().
1756 LoggerContext.getConfiguration().getConfigurationSource()
1757 provides a reliable public method for obtaining a logger context's configuration location and content.
1758 </action>
1759 <action issue="LOG4J2-619" dev="rgoers" type="fix" due-to="Scott Harrington">
1760 Invalid XML configuration files do not prevent the config file from being checked again.
1761 </action>
1762 <action issue="LOG4J2-637" dev="rpopma" type="fix" due-to="Mansoor Sajjad, Jon Wilmoth">
1763 JMX: Updating a Logger's level via jConsole now correctly takes effect.
1764 </action>
1765 <action issue="LOG4J2-668" dev="rpopma" type="fix">
1766 Correctly process log events when combining AsyncLoggers with AsyncAppender.
1767 </action>
1768 <action issue="LOG4J2-669" dev="rpopma" type="fix">
1769 Prevent NPE when combining AsyncLoggers with AsyncLoggerConfigs.
1770 </action>
1771 <action issue="LOG4J2-42" dev="rgoers" type="add">
1772 Create an appender to route log events to the ServletContext log.
1773 </action>
1774 <action issue="LOG4J2-419" dev="rgoers" type="update" due-to="Woonsan Ko">
1775 Support default value for missing key in look ups with fallbacking to looking in the properties map.
1776 </action>
1777 <action issue="LOG4J2-563" dev="rgoers" type="fix" due-to="Michael Friedmann">
1778 FlumeAvroManager now always uses a client type of default_failover.
1779 </action>
1780 <action issue="LOG4J2-554" dev="rgoers" type="update">
1781 Allow configuration files to be located as Servlet Context resources.
1782 </action>
1783 <action issue="LOG4J2-535" dev="rgoers" type="fix">
1784 Reset rollover time when size rollover is triggered.
1785 </action>
1786 <action issue="LOG4J2-664" dev="mattsicker" type="fix">
1787 Moved plugin cache file to META-INF for OSGi compatibility.
1788 </action>
1789 <action issue="LOG4J2-640" dev="mattsicker" type="fix">
1790 Fix NPE that can be caused by a null ThreadContextClassLoader.
1791 </action>
1792 <action issue="LOG4J2-655" dev="mattsicker" type="add">
1793 Add Vagrantfile for testing in GNU+Linux.
1794 </action>
1795 <action issue="LOG4J2-651" dev="ggregory" type="fix">
1796 Log4j 2 throws ArrayIndexOutOfBoundsException.
1797 </action>
1798 <action issue="LOG4J2-654" dev="rpopma" type="add">
1799 Add log4j-perf module to provide a home for all log4j performance tests.
1800 Add support for JMH microbenchmark performance tests.
1801 </action>
1802 <action issue="LOG4J2-652" dev="mattsicker" type="add">
1803 Add support for default plugin values and attributes.
1804 </action>
1805 <action issue="LOG4J2-598" dev="mattsicker" type="add">
1806 Add support for types other than String for plugin factory values/attributes.
1807 </action>
1808 <action issue="LOG4J2-250" dev="rpopma" type="update">
1809 Refactor Log4jLogEvent to lazily create ThrowableProxy.
1810 </action>
1811 <action issue="LOG4J2-647" dev="ggregory" type="update">
1812 Upgrade to Flume 1.5.0.
1813 </action>
1814 <action issue="LOG4J2-644" dev="ggregory" type="add">
1815 Implement a SecureSocketAppender and secure server (SSL/TLS).
1816 </action>
1817 <action issue="LOG4J2-646" dev="ggregory" type="update">
1818 Merge the TLS Syslog appender into the Syslog appender.
1819 </action>
1820 <action issue="LOG4J2-620" dev="rgoers" type="fix">
1821 Perform reconfiguration in a separate thread to prevent deadlocks.
1822 </action>
1823 <action issue="LOG4J2-641" dev="mattsicker" type="update">
1824 Override commons-logging dependency version in tests.
1825 </action>
1826 <action issue="LOG4J2-639" dev="rpopma" type="fix" due-to="Mck SembWever">
1827 Prevent NPE in AsyncLogger and AsyncLoggerConfig if logger is used after log4j has been shut down.
1828 </action>
1829 <action issue="LOG4J2-469" dev="rgoers" type="fix">
1830 FailoverAppender was not resetting its status after the primary appender recovered.
1831 </action>
1832 <action issue="LOG4J2-623" dev="rgoers" type="fix">
1833 Generate MDC properties as a JSON map in JSONLayout.
1834 </action>
1835 <action issue="LOG4J2-566" dev="rpopma" type="update" due-to="Luigi Alice">
1836 Made RollingRandomAccessFileAppender buffer size configurable.
1837 </action>
1838 <action issue="LOG4J2-520" dev="rpopma" type="fix" due-to="JavaTech, Andre Bogus">
1839 Resolved issue where AsyncAppender dropped events if queue still contained
1840 events when application is stopped.
1841 </action>
1842 <action issue="LOG4J2-392" dev="rpopma" type="fix" due-to="Andre Bogus">
1843 Resolved a problem with the previous solution for LOG4J2-392 that resulted in dropped events
1844 when using AsyncLoggerConfig with slow appenders when application is stopped.
1845 </action>
1846 <action issue="LOG4J2-613" dev="mattsicker" type="fix">
1847 The OSGi version of log4j-web imports Servlet 2.5 at minimum instead of 3.0.
1848 </action>
1849 <action issue="LOG4J2-602" dev="rgoers" type="fix">
1850 Unit tests are now less verbose during the build process.
1851 </action>
1852 <action issue="LOG4J2-570" dev="mattsicker" type="fix">
1853 Fix shutdown thread memory leak in servlet containers.
1854 </action>
1855 <action issue="LOG4J2-628" dev="rpopma" type="update">
1856 Use Clock to generate all log event timestamps, not just for Async Loggers.
1857 </action>
1858 <action issue="LOG4J2-629" dev="rpopma" type="add">
1859 Document the system properties used in Log4J 2.
1860 </action>
1861 <action issue="LOG4J2-542" dev="rgoers" type="fix">
1862 Make Throwable transient in ThrowableProxy.
1863 </action>
1864 <action issue="LOG4J2-617" dev="mattsicker" type="update">
1865 Update SLF4J to 1.7.7.
1866 </action>
1867 <action issue="LOG4J2-616" dev="mattsicker" type="update">
1868 Update Jackson to 2.3.3.
1869 </action>
1870 <action issue="LOG4J2-440" dev="mattsicker" type="fix">
1871 During shutdown, a NullPointerException could be thrown due to the NullConfiguration class no longer being
1872 available to the ClassLoader.
1873 </action>
1874 <action issue="LOG4J2-346" dev="mattsicker" type="fix">
1875 Cyclic dependency with log4j-slf4j-impl in OSGi.
1876 </action>
1877 <action issue="LOG4J2-345" dev="mattsicker" type="fix">
1878 The log4j-1.2-api module didn't export any packages to OSGi.
1879 </action>
1880 <action issue="LOG4J2-605" dev="mattsicker" type="fix">
1881 Password data from the NoSQL plugins no longer shows up in cleartext in debug logging.
1882 </action>
1883 <action issue="LOG4J2-448" dev="rgoers" type="fix" due-to="X86core">
1884 A StringIndexOutOfBounds exception could occur during property substitution.
1885 </action>
1886 <action issue="LOG4J2-597" dev="rgoers" type="fix">
1887 StatusLogger was not skipping multiple instances of the FQCN class, causing messages from classes in
1888 the Verbose list to be printed.
1889 </action>
1890 <action issue="LOG4J2-585" dev="rgoers" type="update" due-to="Bruce Brouwer">
1891 Add support for multiple parents to Markers.
1892 </action>
1893 <action issue="LOG4J2-595" dev="mattsicker" type="add">
1894 Introduce Java annotation processor as the new plugin pre-caching mechanism. This is available in log4j-core.
1895 All custom plugins created before this should be re-built against the current log4j-core.
1896 </action>
1897 <action issue="LOG4J2-564" dev="mattsicker" type="fix">
1898 Renamed SLF4J logger class to Log4jLogger.
1899 </action>
1900 <action issue="LOG4J2-579" dev="ggregory" type="fix">
1901 Rework Level comparison APIs.
1902 </action>
1903 <action issue="LOG4J2-576" dev="ggregory" type="add">
1904 Add org.apache.logging.log4j.Logger.getLevel().
1905 </action>
1906 <action issue="LOG4J2-574" dev="rpopma" type="update">
1907 Make Blocking the default WaitStrategy for Async Loggers.
1908 </action>
1909 <action issue="LOG4J2-555" dev="rpopma" type="update" due-to="Bruce Brouwer">
1910 Introduce ExtendedLogger interface to facilitate implementing and extending Loggers.
1911 </action>
1912 <action issue="LOG4J2-560" dev="rgoers" type="fix">
1913 SyslogAppenderTest and RFC5424LayoutTest were failing in Java 8.
1914 </action>
1915 <action issue="LOG4J2-561" dev="ggregory" type="update" due-to="vibin">
1916 Allow spaces around commas in Configuration's package attribute.
1917 </action>
1918 <action issue="LOG4J2-547" dev="rgoers" type="update" due-to="Bruce Brouwer">
1919 Have Logger API expose a PrintWriter instead of custom LoggerStream.
1920 </action>
1921 <action issue="LOG4J2-439" dev="rgoers" type="add" due-to="Bruce Brouwer">
1922 Add EncodingPatternConverter to escape newlines and HTML special characters.
1923 </action>
1924 <action issue="LOG4J2-496" dev="rgoers" type="update">
1925 Allow header and footer to be specified as lookup patterns in PatternLayout.
1926 </action>
1927 <action issue="LOG4J2-499" dev="rgoers" type="fix">
1928 Add equals and hashcode to Log4jLogEvent.
1929 </action>
1930 <action issue="LOG4J2-410" dev="rgoers" type="update" due-to="Ivlin Zeng">
1931 SLf4JLogger is now Serializable.
1932 </action>
1933 <action issue="LOG4J2-427" dev="rgoers" type="add" due-to="Alexander Reelsen">
1934 Add support for configuration via YAML.
1935 </action>
1936 <action issue="LOG4J2-378" dev="rgoers" type="fix">
1937 Add DateLookup and ThreadContextLookup to default lookups.
1938 </action>
1939 <action issue="LOG4J2-468" dev="rgoers" type="update">
1940 Add support to add a LoggerConfig. Document two ways to modify the configuration.
1941 </action>
1942 <action issue="LOG4J2-582" dev="ggregory" type="update">
1943 Rename org.apache.logging.log4j.core.net.SocketServer to TCPSocketServer and refactor with UDP.
1944 </action>
1945 <action issue="LOG4J2-592" dev="ggregory" type="update">
1946 Update Jackson to 2.3.2 from 2.2.2.
1947 </action>
1948 </release>
1949 <release version="2.0-rc1" date="2014-02-16" description="Bug fixes and enhancements">
1950 <action dev="nickwilliams" type="delete">
1951 Removed the DataSourceConnectionSource and the &lt;DriverManager&gt; plugin for the JDBC Appender. It is not
1952 safe to use. Please use the DataSource or factory connection sources backed by a connection pool.
1953 </action>
1954 <action dev="nickwilliams" type="update">
1955 Renamed the org.apache.logging.log4j.core.appender.db.nosql.mongo package to
1956 org.apache.logging.log4j.core.appender.db.nosql.mongodb.
1957 </action>
1958 <action dev="grobmeier" type="update">
1959 Renamed the org.apache.logging.log4j.core.appender.db.nosql.couch package to
1960 org.apache.logging.log4j.core.appender.db.nosql.couchdb.
1961 </action>
1962 <action issue="LOG4J2-500" dev="rpopma" type="fix">
1963 (JMX - ObjectNames changed!) Unloading one web application unloads JMX MBeans for all web applications.
1964 </action>
1965 <action issue="LOG4J2-507" dev="ggregory" type="update">
1966 Space Level numbers by 100 instead of 1.
1967 </action>
1968 <action issue="LOG4J2-531" dev="rpopma" type="fix" due-to="Geoff Ballinger">
1969 Fixed bugs where rolled log files were overwritten by RollingFile appender with
1970 composite time and size based policies.
1971 </action>
1972 <action issue="LOG4J2-475" dev="nickwilliams" type="fix" due-to="Matt Sicker">
1973 Changed the MongoDBConnection to add a MongoDB encoding hook instead of a decoding hook.
1974 </action>
1975 <action issue="LOG4J2-489" dev="nickwilliams" type="fix">
1976 Fixed the JPAAppender's overuse of transactions by connecting (borrowing from pool) on new write internal or on
1977 flush.
1978 </action>
1979 <action issue="LOG4J2-457" dev="nickwilliams" type="fix">
1980 Fixed failure of JDBC and JPA appender to properly release database connections by connecting (borrowing from
1981 pool) on new write internal or on flush.
1982 </action>
1983 <action issue="LOG4J2-442" dev="nickwilliams" type="fix">
1984 Fixed problem with JDBC and JPA appender connectivity in WebSphere by connecting (borrowing from pool) on new
1985 write internal or on flush.
1986 </action>
1987 <action issue="LOG4J2-438" dev="nickwilliams" type="fix">
1988 Ensured the JDBCAppender commits transactions after a single write or a flush of multiple writes.
1989 </action>
1990 <action issue="LOG4J2-407" dev="nickwilliams" type="fix">
1991 Fixed inability to recover from lost database connection in database appenders by connecting (borrowing from
1992 pool) on new write internal or on flush.
1993 </action>
1994 <action issue="LOG4J2-530" dev="rpopma" type="add">
1995 (JMX) JMX Client GUI should dynamically update when LoggerContext MBeans are registered/unregistered in MBean
1996 server.
1997 </action>
1998 <action issue="LOG4J2-511" dev="rpopma" type="fix" due-to="James Pretorius">
1999 Stop AsyncLoggerConfig Disruptor thread(s), then AsyncAppender thread(s) first
2000 before stopping other appenders.
2001 </action>
2002 <action issue="LOG4J2-392" dev="rpopma" type="fix" due-to="ilynaf, Andre Bogus">
2003 Stop AsyncLoggerConfig Disruptor thread(s), then AsyncAppender thread(s) first
2004 before stopping other appenders.
2005 </action>
2006 <action issue="LOG4J2-345" dev="rpopma" type="fix" due-to="Roland Weiglhofer, Matt Sicker">
2007 (OSGi) logging.log4j-1.2-api doesn't export the log4j API 1.2. Dependent bundles can not be resolved.
2008 </action>
2009 <action issue="LOG4J2-523" dev="ggregory" type="fix">
2010 LocalizedMessage serialization is broken.
2011 </action>
2012 <action issue="LOG4J2-385" dev="rpopma" type="fix" due-to="Ace Funk, Porfirio Partida">
2013 Fixed issues with time-based file rollover (monthly, weekly, hourly and every minute).
2014 </action>
2015 <action issue="LOG4J2-452" dev="nickwilliams" type="fix">
2016 Added a ServletContext attribute that, when set to "true", disables Log4j's auto-initialization in
2017 Servlet 3.0+ web applications.
2018 </action>
2019 <action issue="LOG4J2-512" dev="nickwilliams" type="fix" due-to="Chandra Sekhar Kakarla, Matt Sicker">
2020 Exposed Log4j web support interface and methods and the LoggerContext through ServletContext attributes
2021 so that threads not affected by filters (such as asynchronous threads) can utilize the LoggerContext. Also
2022 updated the Log4j filter so that it supports async.
2023 </action>
2024 <action issue="LOG4J2-409" dev="nickwilliams" type="fix" due-to="Frank Steinmann, Thomas Neidhart">
2025 Created a utility to properly escape backslashes before creating URIs, and changed URI creation to use the
2026 utility instead of instantiating URI directly.
2027 </action>
2028 <action issue="LOG4J2-344" dev="nickwilliams" type="fix" due-to="Keir Lawson, Tomasz Wladzinski">
2029 Changed the Servlet 3.0 auto-initializer to add the filter by class to get around a WebLogic bug.
2030 </action>
2031 <action issue="LOG4J2-359" dev="nickwilliams" type="fix" due-to="Abhinav Shah">
2032 Changed the Servlet 3.0 auto-initializer so that it does nothing in a Servlet 2.5 or older application. This
2033 ensures behavioral consistency across containers. This includes additional fixes to abort initialization if a
2034 duplicate filter already exists and to check the actual Servlet EFFECTIVE version.
2035 </action>
2036 <action issue="LOG4J2-517" dev="rpopma" type="fix">
2037 Switch in log4j-1.2-api Category.getEffectiveLevel has no cases for FATAL, OFF.
2038 </action>
2039 <action issue="LOG4J2-41" dev="rgoers" type="update" due-to="Nick Williams">
2040 Add support for custom logging levels.
2041 </action>
2042 <action issue="LOG4J2-406" dev="rpopma" type="fix" due-to="Kerrigan Joseph">
2043 (JMX) Unregister all log4j JMX MBeans when the LoggerContext is stopped
2044 to allow web application classes to be GC-ed on undeploy.
2045 </action>
2046 <action issue="LOG4J2-405" dev="rgoers" type="fix">
2047 Configuration was being processed twice at startup.
2048 </action>
2049 <action issue="LOG4J2-479" dev="rpopma" type="add" due-to="MK">
2050 ThreadContext now uses plain ThreadLocal by default, unless system property
2051 isThreadContextMapInheritable has value "true".
2052 </action>
2053 <action issue="LOG4J2-398" dev="rgoers" type="fix">
2054 Configure properties and setup Interpolator before processing rest of configuration.
2055 </action>
2056 <action issue="LOG4J2-481" dev="rgoers" type="add" due-to="Matt Sicker">
2057 Add Stream interface to Loggers.
2058 </action>
2059 <action issue="LOG4J2-490" dev="rgoers" type="update" due-to="Matt Sicker">
2060 Update EasyMock to version 3.2.
2061 </action>
2062 <action issue="LOG4J2-470" dev="rgoers" type="fix">
2063 hostName property was not being set until after the first configuration element.
2064 </action>
2065 <action issue="LOG4J2-464" dev="rgoers" type="fix">
2066 Support arrays as sub-elements of a JSON configuration.
2067 </action>
2068 <action issue="LOG4J2-492" dev="rpopma" type="fix" due-to="Shaddy Baddah, Herlani Junior">
2069 (JMX) Fixed MalformedObjectNameException if context name contains '=' or newline characters.
2070 </action>
2071 <action issue="LOG4J2-377" dev="rpopma" type="fix" due-to="Roland Weiglhofer, Matt Sicker">
2072 (OSGi) Fix NPE during shutdown.
2073 </action>
2074 <action issue="LOG4J2-463" dev="rpopma" type="fix" due-to="Michael Diamond, Matt Sicker">
2075 Fixed documentation for MyApp example application in the Automatic Configuration section
2076 </action>
2077 <action issue="LOG4J2-408" dev="rpopma" type="fix" due-to="Dongqing Hu, Matt Sicker">
2078 Fixed error in documentation code example in manual/eventlogging.html
2079 </action>
2080 <action issue="LOG4J2-451" dev="rpopma" type="fix" due-to="Vinay Pothnis, Matt Sicker">
2081 Fixed typo in documentation: system property should be log4j2.loggerContextFactory
2082 </action>
2083 <action issue="LOG4J2-443" dev="rpopma" type="fix" due-to="Colin Froggatt, Tudor Har">
2084 (JMX) Fixed issue where log4j2 LoggerContext did not show up in JMX GUI or JConsole.
2085 </action>
2086 <action issue="LOG4J2-485" dev="rpopma" type="fix">
2087 Fixed issue where toString methods that perform logging could deadlock AsyncAppender.
2088 </action>
2089 <action issue="LOG4J2-445" dev="rpopma" type="fix" due-to="Anthony Baldocchi">
2090 ResolverUtil cannot find packages in file URLs which include the '+' character.
2091 </action>
2092 <action issue="LOG4J2-430" dev="rgoers" type="fix" due-to="David Gstir">
2093 Use the formatted Message in RFC5424Layout for non-StructuredDataMessages.
2094 </action>
2095 <action issue="LOG4J2-459" dev="rgoers" type="fix">
2096 Set external context when constructing the LoggerContext.
2097 </action>
2098 <action issue="LOG4J2-466" dev="rpopma" type="fix" due-to="Jan Tepke">
2099 Cannot load log4j2 config file if path contains plus '+' characters.
2100 </action>
2101 <action issue="LOG4J2-462" dev="rpopma" type="fix" due-to="Daisuke Baba">
2102 Fix LogEvent to never return null Level, fixes LevelPatternConverter.format may throw NPE.
2103 </action>
2104 <action issue="LOG4J2-465" dev="rpopma" type="fix" due-to="Daisuke Baba">
2105 Fix LogEvent to never return null Level, fixes ThresholdFilter throws NPE.
2106 </action>
2107 <action issue="LOG4J2-471" dev="rpopma" type="fix" due-to="Anthony Baldocchi">
2108 Fixed issue where toString methods that perform logging could deadlock AsyncLogger.
2109 </action>
2110 <action issue="LOG4J2-482" dev="rpopma" type="add" due-to="Hongdi Ren">
2111 Documentation fix: The attribute of Route to refer to an appender is "ref" not "AppenderRef".
2112 </action>
2113 <action issue="LOG4J2-467" dev="rpopma" type="add" due-to="Anthony Baldocchi">
2114 Added option to toggle Thread name caching in AsyncLogger.
2115 </action>
2116 <action issue="LOG4J2-478" dev="ggregory" type="fix" due-to="Michael Friedmann.">
2117 The message and ndc fields are not JavaScript escaped in JSONLayout.
2118 </action>
2119 <action issue="LOG4J2-455" dev="rpopma" type="fix" due-to="Robin Zhang Tao">
2120 RingBufferLogEvent should return Message timestamp for TimestampMessage messages.
2121 </action>
2122 <action issue="LOG4J2-477" dev="rpopma" type="fix" due-to="Tal Liron">
2123 NPE in ClassLoaderContextSelector.
2124 </action>
2125 <action issue="LOG4J2-454" dev="rpopma" type="fix" due-to="Robin Zhang Tao">
2126 TimeBasedTriggeringPolicy should use event time millis.
2127 </action>
2128 <action issue="LOG4J2-472" dev="rpopma" type="fix" due-to="Tal Liron">
2129 BaseConfiguration class does not properly implement Configuration interface.
2130 </action>
2131 <action issue="LOG4J2-447" dev="ggregory" type="fix" due-to="Jeff Hudren, Mark Paluch, Scott Deboy">
2132 XMLLayout does not include marker name.
2133 </action>
2134 <action issue="LOG4J2-453" dev="rgoers" type="update">
2135 Update Flume Appender to use Flume 1.4.0.
2136 </action>
2137 <action issue="LOG4J2-423" dev="rpopma" type="add">
2138 (JMX) Added MBeans for instrumenting AsyncAppenders and AsyncLogger RingBuffers,
2139 exposing queue size, remaining capacity and other attributes.
2140 </action>
2141 <action issue="LOG4J2-323" dev="rpopma" type="fix">
2142 Resolved memory leak by releasing reference to ThreadLocal when
2143 AsyncLogger is stopped.
2144 </action>
2145 <action issue="LOG4J2-425" dev="rpopma" type="fix">
2146 Resolved memory leak by populating AsyncLoggerConfigHelper ring buffer
2147 via EventTranslatorTwoArg, eliminating the need for a ThreadLocal.
2148 </action>
2149 <action issue="LOG4J2-420" dev="ggregory" type="add">
2150 Create a lookup for resource bundle substitution.
2151 </action>
2152 <action issue="LOG4J2-417" dev="ggregory" type="fix">
2153 Fix Event Level / LoggerConfig Level table at the architecture documentation page.
2154 </action>
2155 <action issue="LOG4J2-415" dev="ggregory" type="add">
2156 Format log event time as UNIX time (seconds or milliseconds).
2157 </action>
2158 <action issue="LOG4J2-404" dev="rgoers" type="fix" due-to="Kamal Bahadur">
2159 @EnterpriseNumber" was missing in the ID of structured data when RFC5424Layout is used
2160 </action>
2161 <action issue="LOG4J2-379" dev="rpopma" type="fix">
2162 Fixed issue that prevented Log4J from working in Google App Engine.
2163 </action>
2164 <action issue="LOG4J2-401" dev="ggregory" type="add">
2165 Configure FileAppender buffer size.
2166 </action>
2167 <action issue="LOG4J2-402" dev="ggregory" type="add">
2168 Configure RandomAccessFileAppender buffer size.
2169 </action>
2170 <action issue="LOG4J2-528" dev="ggregory" type="update">
2171 Rename package org.apache.logging.log4j.core.appender.rolling.helper to org.apache.logging.log4j.core.appender.rolling.action.
2172 </action>
2173 <action issue="LOG4J2-532" dev="ggregory" type="update">
2174 Resource leak in Flume appender when it cannot create a BerkeleyDB db.
2175 </action>
2176 <action issue="LOG4J2-413" dev="ggregory" type="update">
2177 PatternLayout option to not output ANSI escape codes if no Console is available.
2178 </action>
2179 </release>
2180 <release version="2.0-beta9" date="2013-09-14" description="Bug fixes and enhancements">
2181 <action issue="LOG4J2-317" dev="ggregory" type="update">
2182 Renamed FastFileAppender and FastRollingFileAppender to RandomAccessFileAppender
2183 and RollingRandomAccessFileAppender. Configurations using the Fast(Rolling)File element
2184 no longer work and should be modified to use the (Rolling)RandomAccessFile element.
2185 </action>
2186 <action dev="nickwilliams" type="update">
2187 Changed the "suppressExceptions" configuration attribute for all Appenders to "ignoreExceptions" to avoid
2188 confusion with Java 7 suppressed exceptions. Also renamed the Appender#isExceptionSuppressed() method to
2189 Appender#ignoreExceptions() to avoid the same confusion. All Appenders by default internally log and then ignore
2190 exceptions encountered while logging. Setting "ignoreExceptions" to "false" on an Appender causes it to allow
2191 exceptions to propagate to the caller. You must set "ignoreExceptions" to "false" for Appenders you are wrapping
2192 in the Failover Appender.
2193 </action>
2194 <action dev="nickwilliams" type="update">
2195 Changed the (relatively new) PatternLayout configuration attribute "suppressExceptions" to
2196 "alwaysWriteExceptions" to more correctly indicate what it does. As such, the meaning of this attribute has
2197 reversed (previous "true"s should become "false"s, and vice versa). Since this was an undocumented attribute up
2198 until now, it's unlikely this change will affect any users.
2199 </action>
2200 <action issue="LOG4J2-226" dev="rgoers" type="fix">
2201 Fix table of contents generation in pdf.
2202 </action>
2203 <action issue="LOG4J2-395" dev="rgoers" type="fix" due-to="Abhinav Shah">
2204 Allow classpath scheme when specifying configuration file location as a system property.
2205 </action>
2206 <action issue="LOG4J2-393" dev="rgoers" type="fix">
2207 Initialize PluginManager once during configuration. Move advertisement setup into BaseConfiguration.
2208 </action>
2209 <action issue="LOG4J2-391" dev="rgoers" type="fix" due-to="Kamal Bahadur">
2210 FlumePersistentManager now handles LockConflictExceptions in Berkeley Db.
2211 </action>
2212 <action issue="LOG4J2-399" dev="ggregory" type="add">
2213 Allow the default file rollover strategy to define the compression level.
2214 </action>
2215 <action issue="LOG4J2-338" dev="rgoers" type="add" due-to="Tibor Benke">
2216 Add TLSAppender. Also added missing license headers to several files.
2217 </action>
2218 <action issue="LOG4J2-380" dev="rgoers" type="fix">
2219 Use rollover date when substituting ${date} in the filePattern.
2220 </action>
2221 <action issue="LOG4J2-253" dev="rpopma" type="add">
2222 Added FAQ page to the site.
2223 </action>
2224 <action issue="LOG4J2-362" dev="rpopma" type="add">
2225 Add a diagram to the site (FAQ page) that explains when to use which jar.
2226 </action>
2227 <action issue="LOG4J2-322" dev="nickwilliams" type="fix">
2228 Centralized reflective use of Reflection#getCallerClass and properly handled its instability in various versions
2229 of Java.
2230 </action>
2231 <action issue="LOG4J2-293" dev="rgoers" type="fix">
2232 Reset the Configuration if the ClassLoaderContextSelector creates a LoggerContext without a configuration
2233 location and then is later provided one.
2234 </action>
2235 <action issue="LOG4J2-293" dev="nickwilliams" type="fix" due-to="Abhinav Shah">
2236 Changed the ConfigurationFactory to recognize and properly use the classpath: URI scheme in addition to the
2237 classloader: URI scheme.
2238 </action>
2239 <action issue="LOG4J2-359" dev="nickwilliams" type="fix" due-to="Abhinav Shah">
2240 Changed the Servlet 3.0 auto-initializer so that it does nothing in a Servlet 2.5 or older application. This
2241 ensures behavioral consistency across containers.
2242 </action>
2243 <action issue="LOG4J2-374" dev="ggregory" type="add" due-to="Tibor Benke">
2244 Add more options to PatternLayout to display more detailed information about a Throwable.
2245 </action>
2246 <action issue="LOG4J2-383" dev="ggregory" type="add">
2247 [Pattern Layout] Customize level names by length.
2248 </action>
2249 <action issue="LOG4J2-384" dev="ggregory" type="add">
2250 [Pattern Layout] Customize level names to lower-case.
2251 </action>
2252 <action issue="LOG4J2-355" dev="ggregory" type="update" due-to="Tibor Benke">
2253 Add support for multiple SD-ELEMENTs in a RFC 5424 syslog message.
2254 </action>
2255 <action dev="nickwilliams" type="update">
2256 Cleaned up tests and cleared up documentation for the JPA appender following the resolution of EclipseLink
2257 issue #412454.
2258 </action>
2259 <action issue="LOG4J2-310" dev="rpopma" type="fix" due-to="Olivier Lemasle">
2260 Fixed issue where SMTPAppender did not send mails with error or fatal level without prior info event.
2261 </action>
2262 <action issue="LOG4J2-368" dev="rgoers" type="fix">
2263 Add PatternLayout constructor to Log4j 1.2 bridge for Velocity.
2264 </action>
2265 <action issue="LOG4J2-333" dev="ggregory" type="fix" due-to="Hervé Boutemy">
2266 Match artifact ids with Maven module names.
2267 </action>
2268 <action issue="LOG4J2-364" dev="rgoers" type="add" due-to="David Nault">
2269 Add WebLookup to retrieve information from the ServletContext.
2270 </action>
2271 <action issue="LOG4J2-367" dev="ggregory" type="fix" due-to="David Parry">
2272 JMS appenders send two messages for one append.
2273 </action>
2274 <action issue="LOG4J2-319" dev="ggregory" type="fix">
2275 Double stack trace logging when using %throwable in %style and %highlight.
2276 </action>
2277 <action issue="LOG4J2-360" dev="rgoers" type="add">
2278 Allow Plugins to have aliases.
2279 </action>
2280 <action issue="LOG4J2-358" dev="nickwilliams" type="fix">
2281 NoSQLAppender using MongoDB provider ignores username and password attributes
2282 </action>
2283 <action issue="LOG4J2-356" dev="ggregory" type="add">
2284 Create a JSON Layout.
2285 </action>
2286 <action issue="LOG4J2-343" dev="rpopma" type="fix" due-to="Henning Schmiedehausen">
2287 Removed unnecessary generics from Appender interface and implementing classes.
2288 </action>
2289 <action issue="LOG4J2-351" dev="rpopma" type="fix" due-to="Roland Weiglhofer">
2290 [OSGi] wrong Fragment-Host in manifest files.
2291 </action>
2292 <action issue="LOG4J2-336" dev="rpopma" type="fix" due-to="Andre Bogus">
2293 AsyncLogger errors after multiple calls to LoggerContext.reconfigure().
2294 </action>
2295 <action issue="LOG4J2-347" dev="rpopma" type="fix" due-to="David Phillips">
2296 Give the AsyncAppender thread a more descriptive name for easier debugging/profiling.
2297 </action>
2298 <action issue="LOG4J2-332" dev="rgoers" type="fix" due-to="Hervé Boutemy">
2299 Modified documentation to refer to SLF4J Binding instead of SLF4J Bridge.
2300 </action>
2301 <action issue="LOG4J2-342" dev="rgoers" type="fix">
2302 Ignore xml:base attributes.
2303 </action>
2304 <action issue="LOG4J2-309" dev="rgoers" type="fix">
2305 Insure jars and distributions only have a single License and Notice file.
2306 </action>
2307 <action issue="LOG4J2-341" dev="ggregory" type="add">
2308 Enable XInclude for XML configurations.
2309 </action>
2310 <action issue="LOG4J2-320" dev="ggregory" type="fix">
2311 JPAAppender stops logging because META-INF/log4j-provider.properties is left open.
2312 </action>
2313 <action issue="LOG4J2-335" dev="rgoers" type="fix">
2314 FlumePersistentManager's writer thread had high CPU usage.
2315 </action>
2316 <action issue="LOG4J2-331" dev="nickwilliams" type="fix">
2317 Removed erroneous check for affected MongoDB records, which always returns zero on inserts.
2318 </action>
2319 <action issue="LOG4J2-330" dev="nickwilliams" type="fix">
2320 Added a BSON Transformer so that MongoDB can persist Log4j events.
2321 </action>
2322 <action issue="LOG4J2-329" dev="rgoers" type="fix">
2323 StatusLogger now only creates StatusData objects if they are the appropriate logging level.
2324 </action>
2325 <action issue="LOG4J2-328" dev="rgoers" type="fix">
2326 FlumePersistentManager was calling Berkeley DB's count method too frequently.
2327 </action>
2328 <action issue="LOG4J2-280" dev="rpopma" type="fix">
2329 Additional fix to make AsyncAppender threads daemon threads and improve their thread name.
2330 </action>
2331 <action issue="LOG4J2-165" dev="rgoers" type="fix">
2332 The slf4j-ext jar is now an optional dependency of the SLF4J bridge.
2333 </action>
2334 <action issue="LOG4J2-318" dev="rgoers" type="update">
2335 Allow shutdown hook to be disabled in the configuration.
2336 </action>
2337 <action issue="LOG4J2-166" dev="rgoers" type="fix">
2338 RoutingAppender's default Route can now be an appender reference.
2339 </action>
2340 <action issue="LOG4J2-313" dev="rgoers" type="add" due-to="Woonsan Ko">
2341 Add JNDILookup plugin.
2342 </action>
2343 <action issue="LOG4J2-299" dev="rgoers" type="fix">
2344 Add getThrowable method to ThrowableProxy.
2345 </action>
2346 <action issue="LOG4J2-216" dev="rgoers" type="fix">
2347 ThrowableProxy no longer extends Throwable.
2348 </action>
2349 <action issue="LOG4J2-311" dev="rpopma" type="fix">
2350 Synchronized flush() and close() methods in the XxxFileManager and OutputStreamManager classes.
2351 </action>
2352 <action issue="LOG4J2-312" dev="ggregory" type="update">
2353 XML layout improvements (compact vs. pretty, namespace, namespace prefix, root element).
2354 </action>
2355 <action issue="LOG4J2-388" dev="ggregory" type="update">
2356 Update Java Mail dependency to 1.5.0 from 1.4.7.
2357 </action>
2358 <action issue="LOG4J2-325" dev="ggregory" type="update">
2359 Update JDBC tests to use H2 database 1.3.173 from 1.3.172.
2360 </action>
2361 <action issue="LOG4J2-366" dev="ggregory" type="update">
2362 Update commons-logging to 1.1.3 from 1.1.1.
2363 </action>
2364 <action issue="LOG4J2-390" dev="ggregory" type="update">
2365 Update HSQLDB dependency to 2.3.0 from 2.2.9.
2366 </action>
2367 <action issue="LOG4J2-308" dev="rpopma" type="update">
2368 Clarified which library versions were used in Async Loggers performance test.
2369 </action>
2370 <action issue="LOG4J2-307" dev="rpopma" type="update">
2371 Updated Async Loggers' LMAX Disruptor library from 3.0.1 to 3.2.0.
2372 </action>
2373 <action issue="LOG4J2-306" dev="ggregory" type="update">
2374 Update JSON Jackson library to 2.2.2 from 2.2.1.
2375 </action>
2376 <action issue="LOG4J2-387" dev="ggregory" type="update">
2377 Update Jackson dependency to 1.9.13 from 1.9.11.
2378 </action>
2379 <action issue="LOG4J2-305" dev="ggregory" type="add">
2380 Ease porting from 1.x Logger.getRootLogger(): add LogManager.getRootLogger().
2381 </action>
2382 <action issue="LOG4J2-304" dev="rpopma" type="fix">
2383 Fixed Async Loggers memory leak.
2384 </action>
2385 <action issue="LOG4J2-291" dev="nickwilliams" type="fix">
2386 Fixed JDBC, JPA, and NoSQL appenders so that the failover appender properly fails over on error.
2387 </action>
2388 <action dev="nickwilliams" type="update">
2389 Improved site by adding quick jump-off page and menu for Javadoc links for all components.
2390 </action>
2391 <action issue="LOG4J2-397" dev="ggregory" type="fix" due-to="Yonatan Graber">
2392 Logger.info(Message) Javadoc is incorrect.
2393 </action>
2394 </release>
2395 <release version="2.0-beta8" date="2013-07-10" description="Bug fixes and enhancements">
2396 <action issue="LOG4J2-270" dev="nickwilliams" type="update">
2397 Improved logging initialization in Servlet containers, especially Servlet 3.0 and newer where Log4j now
2398 initializes and deinitializes automatically with no deployment descriptor configuration.
2399 </action>
2400 <action issue="LOG4J2-302" dev="rpopma" type="fix">
2401 Added toString methods to ThreadContextStack/Map implementation classes.
2402 </action>
2403 <action issue="LOG4J2-301" dev="rgoers" type="update">
2404 Add printf methods to Logger API.
2405 </action>
2406 <action issue="LOG4J2-300" dev="rgoers" type="fix">
2407 WriterThread was ending when no agents are available which caused an OutOfMemoryError.
2408 </action>
2409 <action issue="LOG4J2-282" dev="rgoers" type="update">
2410 Allow the default status level to be specified as a system property.
2411 </action>
2412 <action issue="LOG4J2-278" dev="rgoers" type="fix">
2413 Filter calls from Avro or Flume to be ignored by the FlumeAppender.
2414 </action>
2415 <action issue="LOG4J2-279" dev="rgoers" type="fix">
2416 FlumePersistentManager now calls Berkeley DB from threads to avoid encountering interrupts in the application.
2417 </action>
2418 <action issue="LOG4J2-296" dev="ggregory" type="fix">
2419 Wasted work in FlumePersistentManager.createManager.
2420 </action>
2421 <action issue="LOG4J2-297" dev="ggregory" type="fix">
2422 Wasted work in TestConfigurator.testEnvironment.
2423 </action>
2424 <action issue="LOG4J2-298" dev="ggregory" type="fix">
2425 Wasted work in StyleConverterTest.setupClass.
2426 </action>
2427 <action issue="LOG4J2-280" dev="rpopma" type="fix">
2428 AsyncLogger threads are now daemon threads and won't prevent the JVM from shutting down anymore.
2429 </action>
2430 <action issue="LOG4J2-295" dev="rpopma" type="fix">
2431 Fast(Rolling)FileAppender now correctly handles messages exceeding the buffer size.
2432 </action>
2433 <action issue="LOG4J2-271" dev="rpopma" type="fix">
2434 FastRollingFileAppender with TimeBasedTriggeringPolicy now works correctly if append=false.
2435 </action>
2436 <action issue="LOG4J2-267" dev="rpopma" type="fix">
2437 FastRollingFileAppender with TimeBasedTriggeringPolicy now works correctly if append=false.
2438 </action>
2439 <action issue="LOG4J2-292" dev="rpopma" type="fix">
2440 Fast(Rolling)FileAppender now correctly appends to (does not overwrite) existing file.
2441 </action>
2442 <action issue="LOG4J2-294" dev="rgoers" type="update">
2443 LogManager.getLogger can now be called without a logger name or with a null logger name.
2444 </action>
2445 <action issue="LOG4J2-289" dev="rgoers" type="fix">
2446 Upgrade javadoc plugin to 2.9.1 to fix javadoc security issue.
2447 </action>
2448 <action issue="LOG4J2-288" dev="gregory" type="update">
2449 Update JUnit to 4.11 from 4.7.
2450 </action>
2451 <action issue="LOG4J2-286" dev="gregory" type="update">
2452 Update test H2 JDBC driver to 1.172 from 1.171.
2453 </action>
2454 <action issue="LOG4J2-285" dev="gregory" type="update">
2455 Update Jansi jar to 1.11 from 1.9.
2456 </action>
2457 <action issue="LOG4J2-284" dev="gregory" type="update">
2458 Update Log4j 1 dependency to 1.2.17 from 1.2.16.
2459 </action>
2460 <action issue="LOG4J2-386" dev="gregory" type="update">
2461 Update NoSQL dependencies: lightcouch 0.0.6 from 0.0.5, mongodb 2.11.2 from 2.11.1.
2462 </action>
2463 <action issue="LOG4J2-283" dev="gregory" type="update">
2464 Remove dependency on Apache ORO jar.
2465 </action>
2466 <action issue="LOG4J2-277" dev="gregory" type="update">
2467 Wasted work in RollingAppenderSizeTest.testAppender() and others.
2468 </action>
2469 <action issue="LOG4J2-139" dev="rgoers" type="fix">
2470 Fix NullPointerException (regression due to fix for LOG4J2-228)
2471 </action>
2472 <action issue="LOG4J2-168" dev="rgoers" type="update" due-to="Scott Severtson">
2473 Include arbitrary message fields in RFC-5424 structured data.
2474 </action>
2475 <action issue="LOG4J2-275" dev="rgoers" type="fix">
2476 FlumeAvroManager fails to notify client of failing event if Flume RPCClient cannot be created.
2477 </action>
2478 <action issue="LOG4J2-274" dev="ggregory" type="update">
2479 Wasted work in UUIDUtil initialization.
2480 </action>
2481 <action issue="LOG4J2-273" dev="ggregory" type="update">
2482 Wasted work in XMLLayout.toSerializable().
2483 </action>
2484 </release>
2485 <release version="2.0-beta7" date="2013-06-01" description="Bug fixes and enhancements">
2486 <action issue="LOG4J2-249" dev="rgoers" type="update">
2487 Allow context parameters in Log4jContextListener to include properties.
2488 </action>
2489 <action issue="LOG4J2-263" dev="rgoers" type="fix">
2490 Do not allow a charset on RFC5424Layout - use UTF-8.
2491 </action>
2492 <action issue="LOG4J2-242" dev="rgoers" type="fix">
2493 StringFormattedMessage and MessageFormatMessage now will accept a Throwable as their last argument and
2494 pass it on.
2495 </action>
2496 <action issue="LOG4J2-243" dev="rgoers" type="update">
2497 Allow custom LogEventFactories.
2498 </action>
2499 <action issue="LOG4J2-262" dev="rgoers" type="update" due-to="Edward Sargisson">
2500 Add support for interceptors in the embedded Flume Appender.
2501 </action>
2502 <action issue="LOG4J2-269" dev="rgoers" type="fix">
2503 Use transaction when batch size is 1.
2504 </action>
2505 <action issue="LOG4J2-268" dev="rgoers" type="fix">
2506 Add guid to FlumeEvent headers for non-Map Messages.
2507 </action>
2508 <action issue="LOG4J2-246" dev="rgoers" type="fix">
2509 Data buffer is reset in finally clause.
2510 </action>
2511 <action issue="LOG4J2-228" dev="rgoers" type="fix">
2512 UDP now sends one event per packet.
2513 </action>
2514 <action dev="rpopma" type="update">
2515 Method name changes in interface org.apache.logging.log4j.spi.ThreadContextMap:
2516 getContext() to getCopy(), get() to getImmutableMapOrNull().
2517 </action>
2518 <action issue="LOG4J2-154" dev="rpopma" type="update">
2519 Improve ThreadContext performance with copy-on-write map and stack.
2520 </action>
2521 <action issue="LOG4J2-261" dev="rgoers" type="fix" due-to="Edward Sargisson">
2522 Add missing "not" to error message.
2523 </action>
2524 <action issue="LOG4J2-10" dev="rgoers" type="add" due-to="Timothy Ward">
2525 Break up core into multiple osgi jars.
2526 </action>
2527 <action issue="LOG4J2-223" dev="rgoers" type="fix">
2528 Remove LoggerContext when LoggerContext is stopped.
2529 </action>
2530 <action issue="LOG4J2-260" dev="ggregory" type="fix">
2531 XML layout does not specify charset in content type.
2532 </action>
2533 <action issue="LOG4J2-259" dev="ggregory" type="fix">
2534 HTML layout does not specify charset in content type.
2535 </action>
2536 <action issue="LOG4J2-258" dev="ggregory" type="fix">
2537 HTML layout does not output meta element for charset.
2538 </action>
2539 <action issue="LOG4J2-257" dev="ggregory" type="fix">
2540 XML layout ignores charset for the XML processing intruction's encoding attribute.
2541 </action>
2542 <action issue="LOG4J2-255" dev="rpopma" type="fix">
2543 Multi-byte character strings are now assumed to be in the platform default encoding, not UTF-8.
2544 </action>
2545 <action issue="LOG4J2-254" dev="rgoers" type="fix">
2546 Mark OutputStream in OutputStreamManager as volatile. Mark header and footer as final.
2547 </action>
2548 <action issue="LOG4J2-244" dev="rgoers" type="fix">
2549 Rewrite Appender was ignoring filters on referenced appenders.
2550 </action>
2551 <action issue="LOG4J2-245" dev="rgoers" type="fix">
2552 Avoid EmptyStack exception if getCallerClass and SecurityManager are not available.
2553 </action>
2554 <action issue="LOG4J2-229" dev="ggregory" type="add" due-to="Nick Williams">
2555 New JDBC, JPA, and NoSQL database Appenders.
2556 </action>
2557 <action issue="LOG4J2-247" dev="ggregory" type="fix">
2558 SocketServer.isActive should be volatile because it is accessed from different threads.
2559 </action>
2560 <action issue="LOG4J2-251" dev="sdeboy" type="add">
2561 Provide configuration information (location, content type, content if possible) via a registered Advertiser.
2562 </action>
2563 </release>
2564 <release version="2.0-beta6" date="2013-05-05" description="Bug fixes and enhancements">
2565 <action issue="LOG4J2-231" dev="rgoers" type="fix">
2566 Logger.getParent() was not returning the correct Logger.
2567 </action>
2568 <action issue="LOG4J2-201" dev="rgoers" type="fix">
2569 Renamed Plugin annotation attribute from "type" to "category".
2570 </action>
2571 <action issue="LOG4J2-237" dev="rpopma" type="update">
2572 Moved JMX Client GUI classes into separate jmx-gui submodule.
2573 </action>
2574 <action issue="LOG4J2-219" dev="rpopma" type="fix" due-to="Peter DePasquale">
2575 Fix: install default root logger if not configured (this is unchanged),
2576 but make sure to include configured named loggers. Clarified documentation.
2577 </action>
2578 <action issue="LOG4J2-159" dev="rgoers" type="fix">
2579 Use OSGi version format in Fragment-Host
2580 </action>
2581 <action issue="LOG4J2-234" dev="rgoers" type="fix">
2582 RegexFilter threw a NullPointerException when used as a context-wide filter.
2583 </action>
2584 <action issue="LOG4J2-192" dev="rgoers" type="fix">
2585 Add support for interpolating Environment variables when processing the configuration.
2586 </action>
2587 <action issue="LOG4J2-235" dev="rpopma" type="fix" due-to="Sebastian Oerding">
2588 Removed dependency on tools jar from core module, made jconsole dependency optional.
2589 </action>
2590 <action issue="LOG4J2-233" dev="rpopma" type="fix">
2591 Fixed link to log4j-user mailing list.
2592 </action>
2593 <action issue="LOG4J2-230" dev="rpopma" type="update" due-to="Wojciech Zaręba">
2594 Improved error reporting when misconfigured.
2595 </action>
2596 <action issue="LOG4J2-222" dev="rgoers" type="fix" due-to="Steven Yang">
2597 Disruptor will now shutdown during Tomcat shutdown.
2598 </action>
2599 <action dev="rpopma" type="update">
2600 Renamed AsynchAppender to AsyncAppender. Plugin name became Async (was Asynch).
2601 </action>
2602 <action dev="rpopma" type="update">
2603 Removed CheckStyle false positives for NewlineAtEndOfFile and whitespace following '*' at end of line in javadoc.
2604 </action>
2605 <action dev="rpopma" type="update">
2606 Moved Clock interface to package org.apache.logging.log4j.core.helpers.
2607 </action>
2608 <action issue="LOG4J2-225" dev="rpopma" type="update">
2609 Documentation updates to clarify use and impact of location in pattern layouts.
2610 </action>
2611 <action issue="LOG4J2-224" dev="rgoers" type="fix">
2612 The FlumeAppender failed to start if the Flume RPCClient could not connect to any Flume agents.
2613 </action>
2614 <action issue="LOG4J2-223" dev="rgoers" type="fix">
2615 Fix LoggerContext start and stop to eliminate IllegalStateException and NoClassDefFound errors.
2616 </action>
2617 <action issue="LOG4J2-221" dev="rgoers" type="fix" due-to="Nick Williams">
2618 Remove hundreds of compiler warnings.
2619 </action>
2620 <action issue="LOG4J2-215" dev="rpopma" type="fix">
2621 Various small documentation fixes.
2622 </action>
2623 <action issue="LOG4J2-217" dev="rpopma" type="fix" due-to="Fabien Sanglard">
2624 Ensure PluginManager streams are always closed.
2625 </action>
2626 </release>
2627 <release version="2.0-beta5" date="2013-04-20" description="Bug fixes and enhancements">
2628 <action issue="LOG4J2-205" dev="rgoers" type="fix">
2629 Fix deadlock in SocketAppender. Added option to not wait for socket reconnect.
2630 </action>
2631 <action issue="LOG4J2-207" dev="rgoers" type="add" due-to="Remko Popma">
2632 Add JMX support.
2633 </action>
2634 <action issue="LOG4J2-211" dev="rgoers" type="fix" due-to="Nick Williams">
2635 Removing extra spaces in entry and exit method output.
2636 </action>
2637 <action issue="LOG4J2-214" dev="rgoers" type="update" due-to="Remko Popma">
2638 Async documentation update.
2639 </action>
2640 <action issue="LOG4J2-212" dev="rgoers" type="fix">
2641 Loggers without a "." had no parent logger.
2642 </action>
2643 <action issue="LOG4J2-208" dev="rgoers" type="update" due-to="Remko Popma">
2644 Move async subproject into core.
2645 </action>
2646 <action issue="LOG4J2-212" dev="rgoers" type="fix">
2647 Call LoggerContext.stop when the application is shutdown.
2648 </action>
2649 <action issue="LOG4J2-210" dev="rgoers" type="fix" due-to="Arkin Yetis">
2650 MapMessage was not enclosing key value in quotes when generating XML.
2651 </action>
2652 <action issue="LOG4J2-198" dev="rgoers" type="fix">
2653 FlumeAvroManager now uses Flume RPCClient.
2654 </action>
2655 <action issue="LOG4J2-196" dev="rgoers" type="fix">
2656 FlumeAvroManager now uses Flume RPCClient.
2657 </action>
2658 <action issue="LOG4J2-207" dev="ggregory" type="fix">
2659 Use the Maven group ID org.apache.logging.log4j for all artifacts.
2660 </action>
2661 <action issue="LOG4J2-187" dev="rgoers" type="add" due-to="Nick Williams">
2662 Add tag library.
2663 </action>
2664 <action issue="LOG4J2-195" dev="rgoers" type="fix" due-to="Remko Popma">
2665 Unit tests now create files in the target directory.
2666 </action>
2667 <action issue="LOG4J2-193" dev="rgoers" type="fix" due-to="Remko Popma">
2668 RollingFastFileAppender (in log4j-async) did not roll over.
2669 </action>
2670 <action issue="LOG4J2-199" dev="rgoers" type="fix" due-to="Remko Popma">
2671 Highlight subprojects in sub-navigation.
2672 </action>
2673 <action issue="LOG4J2-200" dev="rgoers" type="fix" due-to="Remko Popma">
2674 LoggerContext method renamed to removeFilter from removeFiler.
2675 </action>
2676 <action issue="LOG4J2-194" dev="rgoers" type="fix" due-to="Remko Popma">
2677 ThrowableFormatOptionsTest failed on Windows due to CR/LF issue.
2678 </action>
2679 <action issue="LOG4J2-190" dev="rgoers" type="fix" due-to="Werner">
2680 BaseConfiguration addLoggerAppender saved appender using the Logger name.
2681 </action>
2682 <action issue="LOG4J2-160" dev="rgoers" type="update" due-to="Joanne Polsky">
2683 Move Throwable pattern converter options processing to ThrowableFormatOptions class.
2684 </action>
2685 <action issue="LOG4J2-157" dev="rgoers" type="update" due-to="Remko Popma">
2686 Allowed Loggers access to the properties in the LoggerConfig.
2687 </action>
2688 <action issue="LOG4J2-153" dev="rgoers" type="update" due-to="Remko Popma">
2689 Added ability to include or exclude location information.
2690 </action>
2691 <action issue="LOG4J2-151" dev="rgoers" type="update" due-to="Remko Popma">
2692 Allow Logger and LoggerContext to be subclassed.
2693 </action>
2694 <action issue="LOG4J2-164" dev="rgoers" type="add" due-to="Remko Popma">
2695 Add methods is/setEndOfBatch to LogEvent.
2696 </action>
2697 <action issue="LOG4J2-163" dev="rgoers" type="add" due-to="Remko Popma">
2698 Add support for asynchronous loggers.
2699 </action>
2700 <action issue="LOG4J2-189" dev="rgoers" type="fix" due-to="Werner">
2701 The blocking parameter did not work properly on AsynchAppender.
2702 </action>
2703 <action issue="LOG4J2-188" dev="rgoers" type="fix" due-to="Werner">
2704 AppenderRefs on AsynchAppender didn't support the level and filter elements.
2705 </action>
2706 <action issue="LOG4J2-176" dev="rgoers" type="fix" due-to="Remko Popma">
2707 Avoid IllegalArgumentException in AsynchAppender.
2708 </action>
2709 <action issue="LOG4J2-179" dev="ggregory" type="add">
2710 Add Logger interface APIs to log at given levels.
2711 </action>
2712 <action issue="LOG4J2-181" dev="rgoers" type="fix">
2713 OutputStreamManager now adds the layout header whenever the OutputStream is set.
2714 </action>
2715 <action issue="LOG4J2-177" dev="rgoers" type="fix" due-to="Remko Popma">
2716 Fix NullPointerException in DatagramOutputStream when flush is called from multiple threads.
2717 </action>
2718 <action dev="rgoers" type="add">
2719 Added FlumePersistentManager which writes to BerkeleyDB and then writes to Flume asynchronously.
2720 </action>
2721 <action issue="LOG4J2-175" dev="sdeboy" type="fix">
2722 Plugin cache should be reset when addPackages is called.
2723 </action>
2724 <action issue="LOG4J2-155" dev="sdeboy" type="add">
2725 Expose file appender configuration details via an advertisement mechanism.
2726 </action>
2727 <action issue="LOG4J2-159" dev="rgoers" type="fix" due-to="Jan Winter">
2728 Add Fragment-Host to MANIFEST.MF for log4j-core.
2729 </action>
2730 <action issue="LOG4J2-167" dev="rgoers" type="fix">
2731 Configurator throws a ClassCastException if LogManager returns a SimpleLoggerContext.
2732 </action>
2733 <action issue="LOG4J2-169" dev="rgoers" type="fix">
2734 ConfigurationFactory was adding factories on every call.
2735 </action>
2736 <action issue="LOG4J2-161" dev="rgoers" type="fix">
2737 Modify ClassLoaderContextSelector to use the first ClassLoader in the child parent hierarchy that
2738 has a Context with a configuration to allow JSPs to use the WebApp's context and configuration.
2739 </action>
2740 <action issue="LOG4J2-158" dev="rgoers" due-to="Scott Severtson">
2741 Add RFC 5424 compliant escaping rules to RFC5424Layout.
2742 </action>
2743 </release>
2744 <release version="2.0-beta4" date="2013-01-28" description="Bug fixes and enhancements">
2745 <action issue="LOG4J2-156" dev="ggregory" type="fix" due-to="Andreas Born">
2746 LocalizedMessageTest fails on linux system.
2747 </action>
2748 <action issue="LOG4J2-152" dev="rgoers" type="fix" due-to="Remko Popma">
2749 RollingFileAppender's FileRenameAction was throwing a NullPointerException if no directory was specified
2750 on the target file name.
2751 </action>
2752 <action issue="LOG4J2-150" dev="rgoers" type="fix">
2753 Convert all System.getProperty calls to use PropertiesUtil to suppress SecurityExceptions.
2754 </action>
2755 <action issue="LOG4J2-147" dev="rgoers" type="fix" due-to="William Burns">
2756 ThreadContextMapFilter was matching on the key instead of the value of the key.
2757 </action>
2758 <action dev="rgoers" type="fix">
2759 Allow FlumeAvroManager to initialize even if it cannot connect to an agent.
2760 </action>
2761 <action issue="LOG4J2-149" dev="rgoers" type="fix" due-to="Scott Severtson">
2762 SMTPAppender will only cache filtered events.
2763 </action>
2764 <action issue="LOG4J2-145" dev="ggregory" type="fix">
2765 Add missing serial version IDs.
2766 </action>
2767 <action issue="LOG4J2-144" dev="ggregory" type="fix">
2768 NullPointerException in RFC5424Layout.
2769 </action>
2770 <action issue="LOG4J2-143" dev="rgoers" type="fix">
2771 MessagePatternConverter now returns "null" if the log message is null.
2772 </action>
2773 <action issue="LOG4J2-142" dev="rgoers" type="fix">
2774 Serialized LogEvents were not reset in the output stream causing them to deserialize incorrectly.
2775 </action>
2776 <action issue="LOG4J2-139" dev="rgoers" type="fix">
2777 Fix null pointer exception in SocketAppender if no protocol is specified. The protocol will default
2778 to TCP for the SocketAppender and UDP for the SyslogAppender.
2779 </action>
2780 <action dev="rgoers" type="add">
2781 Added Log4j 2 to SLF4J adapter.
2782 </action>
2783 <action issue="LOG4J2-140" dev="ggregory" type="fix" due-to="Joern Huxhorn">
2784 Typo in documentation of SocketAppender.
2785 </action>
2786 <action issue="LOG4J2-137" dev="rgoers" type="fix">
2787 Fix hang in Dumbster SMTP test server.
2788 </action>
2789 <action issue="LOG4J2-136" dev="rgoers" type="update" due-to="Scott Severtson">
2790 Allow newlines to be escaped in Syslog and RFC5424 layouts. Allow Throwables to be included in
2791 the output from RFC5424Layout.
2792 </action>
2793 <action issue="LOG4J2-131" dev="rgoers" type="add" due-to="Scott Severtson">
2794 Add SMTPAppender.
2795 </action>
2796 <action issue="LOG4J2-130" dev="rgoers" type="fix">
2797 PatternLayout should format throwables without requiring a converter.
2798 </action>
2799 <action dev="rgoers" type="add">
2800 Added hostName and contextName to property map.
2801 </action>
2802 <action issue="LOG4J2-135" dev="ggregory" type="fix" due-to="Ingo Feltes">
2803 BaseConfiguration does not close the first appender.
2804 </action>
2805 <action dev="rgoers" type="add">
2806 Add MessageFormatMessage and FormattedMessage.
2807 </action>
2808 <action issue="LOG4J2-134" dev="ggregory" type="add">
2809 Use %red, %white, %blue, and so on in the console appender.
2810 </action>
2811 <action issue="LOG4J2-133" dev="ggregory" type="add">
2812 Allow custom message creation via a message factory.
2813 </action>
2814 <action issue="LOG4J2-132" dev="ggregory" type="fix">
2815 AbstractLogger.catching(Throwable) checks for DEBUG level but logs at ERROR level.
2816 </action>
2817 <action issue="LOG4J2-129" dev="rgoers" type="fix">
2818 RoutingAppender was only creating a single appender for the default Route.
2819 </action>
2820 <action issue="LOG4J2-126" dev="rgoers" type="fix">
2821 Allow JMS appenders to recover if the queue or topic is unavailable.
2822 </action>
2823 <action issue="LOG4J2-128" dev="rgoers" type="update">
2824 Add follow attribute to Console Appender.
2825 </action>
2826 <action issue="LOG4J2-127" dev="rgoers" type="fix">
2827 AbstractLogger methods were not passing Markers to the isEnabled methods.
2828 </action>
2829 <action dev="rgoers" type="add">
2830 Added Flume Appender samples.
2831 </action>
2832 <action issue="LOG4J2-122" dev="rgoers" type="update">
2833 Add unit test to verify exceptions are thrown when the socket connection fails.
2834 </action>
2835 <action issue="LOG4J2-125" dev="rgoers" type="fix">
2836 JMSQueue and JMSTopic Appenders did not allow name to be specified.
2837 </action>
2838 <action issue="LOG4J2-111" dev="rgoers" type="fix">
2839 Enhanced javadoc copyright statement.
2840 </action>
2841 <action issue="LOG4J2-110" dev="rgoers" type="update">
2842 Renamed log4j12-api to log4j-1.2-api.
2843 </action>
2844 <action issue="LOG4J2-120" dev="rgoers" type="fix">
2845 TCPSocketManager would fail if the initial connection could not be established.
2846 </action>
2847 <action issue="LOG4J2-119" dev="rgoers" type="fix">
2848 A broken socket connection would cause the TCPSocketManager to continuously reconnect.
2849 </action>
2850 <action issue="LOG4J2-123" dev="rgoers" type="fix" due-to="Olivier Lamy">
2851 The example for ThreadContextMapFilter was incorrect.
2852 </action>
2853 <action issue="LOG4J2-116" dev="rgoers" type="fix">
2854 File renaming was using the wrong date value. Enhanced DefaultRolloverStrategy to store newest files in
2855 highest index as well as lowest.
2856 </action>
2857 <action issue="LOG4J2-115" dev="rgoers" type="fix">
2858 ThreadContext Map elements with null values are now ignored when constructing a Flume event and in the
2859 RFC5424 Layout.
2860 </action>
2861 <action issue="LOG4J2-113" dev="rgoers" type="fix">
2862 StructuredDataFilter createFilter was annotated with PluginAttr instead of PluginElement for the
2863 KeyValuePairs.
2864 </action>
2865 <action issue="LOG4J2-114" dev="rgoers" type="fix" due-to="Arkin Yetis">
2866 StructuredDataMessage was validating the length of the values in the event Map instead of the lengths
2867 of the keys.
2868 </action>
2869 </release>
2870 <release version="2.0-beta3" date="2012-11-11" description= "Bug fixes and enhancements">
2871 <action issue="LOG4J2-108" dev="rgoers" type="fix">
2872 Fix NullPointerException in ClassLoaderContextSelector when no class is returned from
2873 the SecurityManager.
2874 </action>
2875 <action issue="LOG4J2-105" dev="rgoers" type="update">
2876 Add ability to customize the names of the Levels in the LevelPatternConverter.
2877 </action>
2878 <action issue="LOG4J2-107" dev="rgoers" type="fix">
2879 PatternParser was not properly handling adjacent nested options
2880 </action>
2881 <action issue="LOG4J2-95" dev="rgoers" type="fix">
2882 Add support for loading plugins inside the OSGi bundle.
2883 </action>
2884 <action issue="LOG4J2-85" dev="rgoers" type="update">
2885 Add ThreadContext.push(String format, Object... args)
2886 </action>
2887 <action issue="LOG4J2-103" dev="rgoers" type="fix" due-to="Das Archive">
2888 The LogEvent was wrapping a ThrowableProxy with another ThrowableProxy when deserializing.
2889 </action>
2890 <action dev="rgoers" type="update">
2891 Created combined jar to combine API and Core contents for users who only want the Log4j implementation.
2892 </action>
2893 <action issue="LOG4J2-104" dev="rgoers" type="fix">
2894 Convert LogManager binding to use "regular" java properties instead of XML properties to workaround a
2895 bug in Oracle's xmlparserv2 jar.
2896 </action>
2897 <action issue="LOG4J2-28" dev="rgoers" type="add">
2898 Added PropertiesRewritePolicy and ability to define properties on a Logger.
2899 </action>
2900 <action issue="LOG4J2-87" dev="rgoers" type="update">
2901 Build pdf of user's guide.
2902 </action>
2903 <action issue="LOG4J2-29" dev="rgoers" type="update">
2904 Added font and fontSize parameters to HTMLLayout. Replace newlines in message with br tag.
2905 </action>
2906 <action issue="LOG4J2-55" dev="rgoers" type="add">
2907 Added ability to configure from an InputSource.
2908 </action>
2909 <action issue="LOG4J2-102" dev="rgoers" type="fix" due-to="Emanuele Colombo">
2910 The Facility value was being improperly calculated.
2911 </action>
2912 <action issue="LOG4J2-101" dev="rgoers" type="fix" due-to="Emanuele Colombo">
2913 A NullPointerException would occur if no format value was passed to the SyslogAppender.
2914 </action>
2915 <action issue="LOG4J2-99" dev="rgoers" type="fix" due-to="Das Archive">
2916 MapRewritePolicy had an extra call to putAll that caused updates to behave like adds.
2917 </action>
2918 <action dev="rgoers" type="fix">
2919 Avoid NPE when duplicate LoggerContextFactorys are present. Allow factories to specify a weight to allow
2920 real implementations to outrank test implementations. Provide a simple default LoggerContextFactory.
2921 </action>
2922 <action issue="LOG4J2-97" dev="rgoers" type="fix">
2923 Added several missing classes and methods for Log4j 1.x compatibility.
2924 </action>
2925 <action issue="LOG4J2-94" dev="rgoers" type="fix" due-to="Denis Treskunov">
2926 Interpolator was not stripping Lookup key separator when trying to locate the default value for a variable.
2927 </action>
2928 <action dev="rgoers" type="fix">
2929 Log4j 1.2 Category.forcedLog was wrapping the message with an ObjectMessage even if the parameter was an
2930 ObjectMessage.
2931 </action>
2932 </release>
2933 <release version="2.0-beta2" date="2012-10-07" description="Bug fixes and enhancements">
2934 <action dev="rgoers" type="update">
2935 Made ParameterizedMessage, StringFormattedMessage and ThreadDumpMessage immutable. LocalizedMessage is
2936 immutable except that it will be updated with the logger name when it is added to the LogEvent.
2937 </action>
2938 <action dev="rgoers" type="fix">
2939 DefaultConfiguration was not starting the Console Appender.
2940 </action>
2941 <action issue="LOG4J2-35" dev="rgoers" type="add">
2942 Add interval and modulate options to TimeBasedTriggeringPolicy to allow more fine-grained control of
2943 when file rolling should occur.
2944 </action>
2945 <action issue="LOG4J2-58" dev="rgoers" type="add">
2946 Add support for filtering packages from stack traces.
2947 </action>
2948 <action issue="LOG4J2-84" dev="rgoers" type="add">
2949 If system property "disableThreadContextStack" is set pushes to the ThreadContext will be ignored. If
2950 system property "disableThreadContext" is set both puts and pushes will be ignored.
2951 </action>
2952 <action issue="LOG4J2-83" dev="rgoers" type="add">
2953 If system property "disableThreadContextMap" is set puts to the ThreadContext will be ignored. If
2954 system property "disableThreadContext" is set both puts and pushes will be ignored.
2955 </action>
2956 <action dev="rgoers" type="add">
2957 Add support for ANSI colors by adding the highlight and style pattern converters. Fix pattern
2958 parsing to allow nested patterns.
2959 </action>
2960 <action issue="LOG4J2-92" dev="rgoers" type="fix">
2961 Converted DynamicThresholdFilter to use KeyValuePair. Fixed bugs in the Map-based filters
2962 to allow declaration of multiple values for a key to match the documentation.
2963 </action>
2964 <action issue="LOG4J2-88" dev="rgoers" type="fix">
2965 Many logging methods in AbstractLogger were set to an incorrect logging level. catching was
2966 using the THROWING marker and was set to debug instead of error.
2967 </action>
2968 <action dev="rgoers" type="add">
2969 Allow the status logging to be directed to stderr or to a file.
2970 </action>
2971 <action issue="LOG4J2-91" dev="rgoers" type="fix">
2972 Log4j 1.2 adapter's Category class was missing 3 log methods.
2973 </action>
2974 <action issue="LOG4J2-84" dev="rgoers" type="fix">
2975 If the ThreadContext stack is empty the LogEvent will contain a null value to reduce the overhead of
2976 creating log events and in the size of the serialized object. Changed the ThreadContext stack to use
2977 a custom stack interface instead of java.util.Stack as that class is overly heavy. This change will
2978 cause an API incompatibility.
2979 </action>
2980 <action issue="LOG4J2-83" dev="rgoers" type="fix">
2981 If the ThreadContext map is empty the LogEvent will contain a null value to reduce the overhead of creating
2982 log events and in the size of the serialized object.
2983 </action>
2984 <action dev="rgoers" type="add">
2985 Add getFormats to MultiformatMessage and allow StructuredDataMessage to format as XML.
2986 </action>
2987 <action issue="LOG4J2-90" dev="rgoers" type="fix">
2988 Add documentation on client vs server mode to performance page.
2989 </action>
2990 <action dev="rgoers" type="fix">
2991 Move variable substitution from PatternLayout to appropriate converters to improve performance.
2992 </action>
2993 </release>
2994 <release version="2.0-beta1" date="2012-09-18" description="Bug fixes and enhancements">
2995 <action dev="rgoers" type="add">
2996 Added AsynchAppender.
2997 </action>
2998 <action issue="LOG4J-81" dev="rgoers" type="fix">
2999 PatternLayout was not honoring format modifiers.
3000 </action>
3001 <action dev="rgoers" type="fix">
3002 Created web module to allow web applications to include the Log4j context listener in WEB-INF/lib even if
3003 Log4j is in the container's class path. Allow locating the LoggerContext to include the ClassLoader. Updated
3004 the Loader utility to always choose the child ClassLoader. Verified in Jboss 5 and Tomcat.
3005 </action>
3006 <action issue="LOG4J2-82" dev="rgoers" type="fix">
3007 MarkerFilter called MarkerManager.getMarker causing the Marker to be created during the processing of the
3008 configuration. This prevents the application from creating the Marker with any parents. MarkerWrapper in
3009 SLF4J-impl was getting a ClassCastException in instanceOf because the Marker isn't a MarkerWrapper.
3010 </action>
3011 <action issue="LOG4J2-80" dev="rgoers" type="fix" due-to="Oliver Lamy">
3012 Allow Log4j 2 to be used as the implementation with SLF4J and SLF4J's jcl-over-slf4j by adding filtering
3013 to the log method in SLF4JLogger.
3014 </action>
3015 <action issue="LOG4J2-78" dev="rgoers" type="fix">
3016 LogFactoryImpl.setAttribute in the Commons Logging bridge got a NullPointerException when passed a null value.
3017 It will now remove the attribute.
3018 </action>
3019 <action issue="LOG4J2-77" dev="rgoers" type="fix">
3020 RoutingAppender was calling the stop method for each of its referenced Appenders and was calling
3021 the stop method of the default Appender a second time. It will now only call the stop method of
3022 Appenders it creates.
3023 </action>
3024 <action issue="LOG4J2-76" dev="rgoers" type="fix">
3025 RewriteAppender was calling the stop method of the referenced appender causing the referenced appender's
3026 manager to have its use count decremented too many times.
3027 </action>
3028 <action issue="LOG4J2-74" dev="rgoers" type="fix">
3029 Logger.error(Marker, Message, Throwable) was internally using Level.TRACE.
3030 </action>
3031 <action issue="LOG4J2-75" dev="rgoers" type="fix">
3032 Enhanced Log4jContextListener to accept a configuration file location. Modified FileConfigurationMonitor
3033 to monitor files configured that way. Fixed other reconfiguration related bugs. Tested in JBoss and
3034 Tomcat.
3035 </action>
3036 <action issue="LOG4J2-72" dev="rgoers" type="fix">
3037 NullPointerException in RollingFileManager when filePattern does not cause the file to be compressed.
3038 </action>
3039 <action issue="LOG4J2-71" dev="rgoers" type="fix">
3040 FileRenameAction did not create the parent directories of the archive files causing the rollover to fail.
3041 </action>
3042 <action dev="rgoers" type="update">
3043 Update the versions of SLF4J and Logback.
3044 </action>
3045 </release>
3046 <release version="2.0-alpha2" date="2012-08-24" description="Bug fixes and minor enhancements">
3047 <action issue="LOG4J2-70" dev="rgoers" type="add">
3048 Add getLogger(Class) to LogManager.
3049 </action>
3050 <action issue="LOG4J2-69" dev="rgoers" type="add">
3051 Allow Flume agents to be embedded into the Flume Appender.
3052 </action>
3053 <action issue="LOG4J2-68" dev="rgoers" type="add">
3054 Add support for formatting using String.format().
3055 </action>
3056 <action issue="LOG4J2-67" dev="rgoers" type="add">
3057 Allow components besides core to create a PluginMap for faster plugin loading and not
3058 having to specify the plugin package in the configuration.
3059 </action>
3060 <action issue="LOG4J2-64" dev="rgoers" type="fix">
3061 Fix compilation problems in Java 7.
3062 </action>
3063 <action issue="LOG4J2-65" dev="rgoers" type="fix">
3064 Allow variable substitution on the configuration attributes and on the root log level.
3065 </action>
3066 </release>
3067 <release version="2.0-alpha1" date="2012-07-29" description="Rewrite of Log4j">
3068 <action issue="LOG4J2-60" dev="rgoers" type="add" due-to="Shane Kelly">
3069 Added ability to filter on the AppenderRef by adding either a level or a filter.
3070 </action>
3071 <action issue="LOG4J2-56" dev="rgoers" type="fix" due-to="John Owen Atala">
3072 Level.toLevel would throw an IllegalArgumentException instead of returning the default value.
3073 </action>
3074 <action issue="LOG4J2-51" dev="rgoers" type="fix" due-to="John Vasileff">
3075 Remove LoggerContext support for custom logger factories. All Loggers returned
3076 by LoggerContext should be compatibile and of the same type.
3077 </action>
3078 <action issue="LOG4J2-50" dev="rgoers" type="fix" due-to="John Vasileff">
3079 Make sure all application facing log methods use their own FQCN. This patch
3080 resolves a unit test failure for the %C pattern when using the Category logger.
3081 </action>
3082 </release>
3083 </body>
3084 </document>
src/ide/Intellij/13/IntellijSettings.jar less more
Binary diff not shown
+0
-9
src/ide/eclipse/4.3.2/organize-imports.importorder less more
0 #Organize Import Order
1 #Sun May 18 22:45:33 EDT 2014
2 6=\#org.junit.Assert
3 5=\#org.hamcrest.CoreMatchers
4 4=\#org.easymock.EasyMock
5 3=com
6 2=org
7 1=javax
8 0=java