You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by rg...@apache.org on 2019/10/20 01:58:47 UTC
[logging-log4j2] branch release-2.x updated: LOG4J2-2710 - Allow
Spring Boot application properties to be accessed in the Log4j 2
configuraiton. Add lower and upper case Lookups.
This is an automated email from the ASF dual-hosted git repository.
rgoers pushed a commit to branch release-2.x
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git
The following commit(s) were added to refs/heads/release-2.x by this push:
new 9d2655b LOG4J2-2710 - Allow Spring Boot application properties to be accessed in the Log4j 2 configuraiton. Add lower and upper case Lookups.
9d2655b is described below
commit 9d2655b5e3a1f1ebbc3f09f9a690dd8d3cd50550
Author: Ralph Goers <rg...@apache.org>
AuthorDate: Sat Oct 19 18:57:15 2019 -0700
LOG4J2-2710 - Allow Spring Boot application properties to be accessed in the Log4j 2 configuraiton. Add lower and upper case Lookups.
---
.../apache/logging/log4j/spi/LoggerContext.java | 52 ++++++++++++++++++++++
.../apache/logging/log4j/core/LoggerContext.java | 52 +++++++++++++++++++---
.../logging/log4j/core/lookup/Interpolator.java | 12 ++++-
.../logging/log4j/core/lookup/LowerLookup.java | 48 ++++++++++++++++++++
.../logging/log4j/core/lookup/UpperLookup.java | 48 ++++++++++++++++++++
.../logging/log4j/core/lookup/CaseLookupTest.java | 48 ++++++++++++++++++++
.../log4j-spring-cloud-config-client/pom.xml | 1 -
.../client/Log4j2CloudConfigLoggingSystem.java | 30 ++++++++++---
.../spring/cloud/config/client/SpringLookup.java | 50 +++++++++++++++++++++
.../src/main/config-repo/log4j2.xml | 11 +++++
src/changes/changes.xml | 4 ++
src/site/markdown/manual/cloud.md | 1 +
src/site/xdoc/manual/lookups.xml | 41 ++++++++++++++++-
13 files changed, 382 insertions(+), 16 deletions(-)
diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/spi/LoggerContext.java b/log4j-api/src/main/java/org/apache/logging/log4j/spi/LoggerContext.java
index 88c3b7e..25b0071 100644
--- a/log4j-api/src/main/java/org/apache/logging/log4j/spi/LoggerContext.java
+++ b/log4j-api/src/main/java/org/apache/logging/log4j/spi/LoggerContext.java
@@ -30,6 +30,58 @@ public interface LoggerContext {
Object getExternalContext();
/**
+ * Retrieve an object by its name.
+ * @param key The object's key.
+ * @since 2.13.0
+ */
+ default Object getObject(String key) {
+ return null;
+ }
+
+ /**
+ * Store an object into the LoggerContext by name for later use.
+ * @param key The object's key.
+ * @param value The object.
+ * @return The previous object or null.
+ * @since 2.13.0
+ */
+ default Object putObject(String key, Object value) {
+ return null;
+ }
+
+ /**
+ * Store an object into the LoggerContext by name for later use if an object is not already stored with that key.
+ * @param key The object's key.
+ * @param value The object.
+ * @return The previous object or null.
+ * @since 2.13.0
+ */
+ default Object putObjectIfAbsent(String key, Object value) {
+ return null;
+ }
+
+ /**
+ * Remove an object if it is present.
+ * @param key The object's key.
+ * @return The object if it was present, null if it was not.
+ * @since 2.13.0
+ */
+ default Object removeObject(String key) {
+ return null;
+ }
+
+ /**
+ * Remove an object if it is present and the provided object is stored.
+ * @param key The object's key.
+ * @param value The object.
+ * @return The object if it was present, null if it was not.
+ * @since 2.13.0
+ */
+ default boolean removeObject(String key, Object value) {
+ return false;
+ }
+
+ /**
* Returns an ExtendedLogger.
* @param name The name of the Logger to return.
* @return The logger with the specified name.
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/LoggerContext.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/LoggerContext.java
index 447e915..0247909 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/LoggerContext.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/LoggerContext.java
@@ -27,6 +27,7 @@ import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
+import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.TimeUnit;
@@ -93,7 +94,8 @@ public class LoggerContext extends AbstractLifeCycle
* reference is updated.
*/
private volatile Configuration configuration = new DefaultConfiguration();
- private Object externalContext;
+ private static final String EXTERNAL_CONTEXT_KEY = "__EXTERNAL_CONTEXT_KEY__";
+ private ConcurrentMap<String, Object> externalMap = new ConcurrentHashMap<>();
private String contextName;
private volatile URI configLocation;
private Cancellable shutdownCallback;
@@ -128,7 +130,11 @@ public class LoggerContext extends AbstractLifeCycle
*/
public LoggerContext(final String name, final Object externalContext, final URI configLocn) {
this.contextName = name;
- this.externalContext = externalContext;
+ if (externalContext == null) {
+ externalMap.remove(EXTERNAL_CONTEXT_KEY);
+ } else {
+ externalMap.put(EXTERNAL_CONTEXT_KEY, externalContext);
+ }
this.configLocation = configLocn;
}
@@ -142,7 +148,11 @@ public class LoggerContext extends AbstractLifeCycle
*/
public LoggerContext(final String name, final Object externalContext, final String configLocn) {
this.contextName = name;
- this.externalContext = externalContext;
+ if (externalContext == null) {
+ externalMap.remove(EXTERNAL_CONTEXT_KEY);
+ } else {
+ externalMap.put(EXTERNAL_CONTEXT_KEY, externalContext);
+ }
if (configLocn != null) {
URI uri;
try {
@@ -376,7 +386,7 @@ public class LoggerContext extends AbstractLifeCycle
} else {
prev.stop();
}
- externalContext = null;
+ externalMap.clear();
LogManager.getFactory().removeContext(this);
} finally {
configLock.unlock();
@@ -423,13 +433,42 @@ public class LoggerContext extends AbstractLifeCycle
contextName = Objects.requireNonNull(name);
}
+ @Override
+ public Object getObject(String key) {
+ return externalMap.get(key);
+ }
+
+ @Override
+ public Object putObject(String key, Object value) {
+ return externalMap.put(key, value);
+ }
+
+ @Override
+ public Object putObjectIfAbsent(String key, Object value) {
+ return externalMap.putIfAbsent(key, value);
+ }
+
+ @Override
+ public Object removeObject(String key) {
+ return externalMap.remove(key);
+ }
+
+ @Override
+ public boolean removeObject(String key, Object value) {
+ return externalMap.remove(key, value);
+ }
+
/**
* Sets the external context.
*
* @param context The external context.
*/
public void setExternalContext(final Object context) {
- this.externalContext = context;
+ if (context != null) {
+ this.externalMap.put(EXTERNAL_CONTEXT_KEY, context);
+ } else {
+ this.externalMap.remove(EXTERNAL_CONTEXT_KEY);
+ }
}
/**
@@ -439,7 +478,7 @@ public class LoggerContext extends AbstractLifeCycle
*/
@Override
public Object getExternalContext() {
- return this.externalContext;
+ return this.externalMap.get(EXTERNAL_CONTEXT_KEY);
}
/**
@@ -641,6 +680,7 @@ public class LoggerContext extends AbstractLifeCycle
* Reconfigures the context.
*/
private void reconfigure(final URI configURI) {
+ Object externalContext = externalMap.get(EXTERNAL_CONTEXT_KEY);
final ClassLoader cl = ClassLoader.class.isInstance(externalContext) ? (ClassLoader) externalContext : null;
LOGGER.debug("Reconfiguration started for context[name={}] at URI {} ({}) with optional ClassLoader: {}",
contextName, configURI, this, cl);
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/Interpolator.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/Interpolator.java
index 72e368f..400337a 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/Interpolator.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/Interpolator.java
@@ -40,6 +40,8 @@ public class Interpolator extends AbstractConfigurationAwareLookup {
private static final String LOOKUP_KEY_DOCKER = "docker";
+ private static final String LOOKUP_KEY_SPRING = "spring";
+
private static final String LOOKUP_KEY_JNDI = "jndi";
private static final String LOOKUP_KEY_JVMRUNARGS = "jvmrunargs";
@@ -99,6 +101,8 @@ public class Interpolator extends AbstractConfigurationAwareLookup {
strLookupMap.put("main", MainMapLookup.MAIN_SINGLETON);
strLookupMap.put("marker", new MarkerLookup());
strLookupMap.put("java", new JavaLookup());
+ strLookupMap.put("lower", new LowerLookup());
+ strLookupMap.put("upper", new UpperLookup());
// JNDI
try {
// [LOG4J2-703] We might be on Android
@@ -134,6 +138,12 @@ public class Interpolator extends AbstractConfigurationAwareLookup {
} catch (final Exception ignored) {
handleError(LOOKUP_KEY_DOCKER, ignored);
}
+ try {
+ strLookupMap.put(LOOKUP_KEY_SPRING,
+ Loader.newCheckedInstanceOf("org.apache.logging.log4j.spring.cloud.config.client.SpringLookup", StrLookup.class));
+ } catch (final Exception ignored) {
+ handleError(LOOKUP_KEY_SPRING, ignored);
+ }
}
public Map<String, StrLookup> getStrLookupMap() {
@@ -159,7 +169,7 @@ public class Interpolator extends AbstractConfigurationAwareLookup {
"available. If you want better web container support, please add the log4j-web JAR to your " +
"web archive or server lib directory.");
break;
- case LOOKUP_KEY_DOCKER:
+ case LOOKUP_KEY_DOCKER: case LOOKUP_KEY_SPRING:
break;
default:
LOGGER.error("Unable to create Lookup for {}", lookupKey, t);
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/LowerLookup.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/LowerLookup.java
new file mode 100644
index 0000000..ce80385
--- /dev/null
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/LowerLookup.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.core.lookup;
+
+import org.apache.logging.log4j.core.LogEvent;
+import org.apache.logging.log4j.core.config.plugins.Plugin;
+
+/**
+ * Converts values to lower case. The passed in "key" should be the value of another lookup.
+ */
+@Plugin(name = "lower", category = StrLookup.CATEGORY)
+public class LowerLookup implements StrLookup {
+
+ /**
+ * Converts the "key" to lower case.
+ * @param key the key to be looked up, may be null
+ * @return The value associated with the key.
+ */
+ @Override
+ public String lookup(final String key) {
+ return key != null ? key.toLowerCase() : null;
+ }
+
+ /**
+ * Converts the "key" to lower case.
+ * @param event The current LogEvent.
+ * @param key the key to be looked up, may be null
+ * @return The value associated with the key.
+ */
+ @Override
+ public String lookup(final LogEvent event, final String key) {
+ return lookup(key);
+ }
+}
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/UpperLookup.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/UpperLookup.java
new file mode 100644
index 0000000..abedf90
--- /dev/null
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/UpperLookup.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.core.lookup;
+
+import org.apache.logging.log4j.core.LogEvent;
+import org.apache.logging.log4j.core.config.plugins.Plugin;
+
+/**
+ * Converts values to upper case. The passed in "key" should be the value of another lookup.
+ */
+@Plugin(name = "upper", category = StrLookup.CATEGORY)
+public class UpperLookup implements StrLookup {
+
+ /**
+ * Converts the "key" to upper case.
+ * @param key the key to be looked up, may be null
+ * @return The value associated with the key.
+ */
+ @Override
+ public String lookup(final String key) {
+ return key != null ? key.toUpperCase() : null;
+ }
+
+ /**
+ * Converts the "key" to upper case.
+ * @param event The current LogEvent.
+ * @param key the key to be looked up, may be null
+ * @return The value associated with the key.
+ */
+ @Override
+ public String lookup(final LogEvent event, final String key) {
+ return lookup(key);
+ }
+}
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/lookup/CaseLookupTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/lookup/CaseLookupTest.java
new file mode 100644
index 0000000..ae7d5ac
--- /dev/null
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/lookup/CaseLookupTest.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.core.lookup;
+
+import java.util.Calendar;
+
+import org.apache.logging.log4j.core.AbstractLogEvent;
+import org.apache.logging.log4j.core.LogEvent;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+/**
+ *
+ */
+public class CaseLookupTest {
+
+
+ @Test
+ public void testLookup() {
+ final String testStr = "JabberWocky";
+ final String lower = "jabberwocky";
+ final String upper = "JABBERWOCKY";
+ StrLookup lookup = new LowerLookup();
+ String value = lookup.lookup(null, testStr);
+ assertNotNull(value);
+ assertEquals(lower, value);
+ lookup = new UpperLookup();
+ value = lookup.lookup(null, testStr);
+ assertNotNull(value);
+ assertEquals(upper, value);
+ }
+}
diff --git a/log4j-spring-cloud-config/log4j-spring-cloud-config-client/pom.xml b/log4j-spring-cloud-config/log4j-spring-cloud-config-client/pom.xml
index 098e554..5178b87 100644
--- a/log4j-spring-cloud-config/log4j-spring-cloud-config-client/pom.xml
+++ b/log4j-spring-cloud-config/log4j-spring-cloud-config-client/pom.xml
@@ -131,7 +131,6 @@
<configuration>
<source>1.8</source>
<target>1.8</target>
- <proc>none</proc>
</configuration>
</plugin>
<plugin>
diff --git a/log4j-spring-cloud-config/log4j-spring-cloud-config-client/src/main/java/org/apache/logging/log4j/spring/cloud/config/client/Log4j2CloudConfigLoggingSystem.java b/log4j-spring-cloud-config/log4j-spring-cloud-config-client/src/main/java/org/apache/logging/log4j/spring/cloud/config/client/Log4j2CloudConfigLoggingSystem.java
index 459be37..47dbfb3 100644
--- a/log4j-spring-cloud-config/log4j-spring-cloud-config-client/src/main/java/org/apache/logging/log4j/spring/cloud/config/client/Log4j2CloudConfigLoggingSystem.java
+++ b/log4j-spring-cloud-config/log4j-spring-cloud-config-client/src/main/java/org/apache/logging/log4j/spring/cloud/config/client/Log4j2CloudConfigLoggingSystem.java
@@ -27,7 +27,6 @@ import java.util.Properties;
import javax.net.ssl.HttpsURLConnection;
import org.apache.logging.log4j.LogManager;
-import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.core.LoggerContext;
import org.apache.logging.log4j.core.config.ConfigurationFactory;
import org.apache.logging.log4j.core.config.ConfigurationSource;
@@ -36,28 +35,39 @@ import org.apache.logging.log4j.core.net.ssl.SslConfiguration;
import org.apache.logging.log4j.core.net.ssl.SslConfigurationFactory;
import org.apache.logging.log4j.core.util.AuthorizationProvider;
import org.apache.logging.log4j.core.util.FileUtils;
-import org.apache.logging.log4j.status.StatusLogger;
import org.apache.logging.log4j.util.PropertiesUtil;
import org.springframework.boot.logging.LogFile;
import org.springframework.boot.logging.LoggingInitializationContext;
import org.springframework.boot.logging.log4j2.Log4J2LoggingSystem;
-import org.springframework.core.io.ClassPathResource;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.ResourceUtils;
/**
- *
+ * Override Spring's implementation of the Log4j 2 Logging System to properly support Spring Cloud Config.
*/
public class Log4j2CloudConfigLoggingSystem extends Log4J2LoggingSystem {
- private static final String FILE_PROTOCOL = "file";
private static final String HTTPS = "https";
- private Logger LOGGER = StatusLogger.getLogger();
+ public static final String ENVIRONMENT_KEY = "SpringEnvironment";
public Log4j2CloudConfigLoggingSystem(ClassLoader loader) {
super(loader);
}
+ /**
+ * Set the environment into the ExternalContext field so that it can be obtained by SpringLookup when it
+ * is constructed. Spring will replace the ExternalContext field with a String once initialization is
+ * complete.
+ * @param initializationContext The initialization context.
+ * @param configLocation The configuration location.
+ * @param logFile the log file.
+ */
+ @Override
+ public void initialize(LoggingInitializationContext initializationContext, String configLocation, LogFile logFile) {
+ getLoggerContext().putObjectIfAbsent(ENVIRONMENT_KEY, initializationContext.getEnvironment());
+ super.initialize(initializationContext, configLocation, logFile);
+ }
+
@Override
protected String[] getStandardConfigLocations() {
String[] locations = super.getStandardConfigLocations();
@@ -66,7 +76,7 @@ public class Log4j2CloudConfigLoggingSystem extends Log4J2LoggingSystem {
if (location != null) {
List<String> list = Arrays.asList(super.getStandardConfigLocations());
list.add(location);
- locations = list.toArray(new String[list.size()]);
+ locations = list.toArray(new String[0]);
}
return locations;
}
@@ -103,6 +113,12 @@ public class Log4j2CloudConfigLoggingSystem extends Log4J2LoggingSystem {
}
}
+ @Override
+ public void cleanUp() {
+ getLoggerContext().removeObject(ENVIRONMENT_KEY);
+ super.cleanUp();
+ }
+
private ConfigurationSource getConfigurationSource(URL url) throws IOException, URISyntaxException {
URLConnection urlConnection = url.openConnection();
AuthorizationProvider provider = ConfigurationFactory.getAuthorizationProvider();
diff --git a/log4j-spring-cloud-config/log4j-spring-cloud-config-client/src/main/java/org/apache/logging/log4j/spring/cloud/config/client/SpringLookup.java b/log4j-spring-cloud-config/log4j-spring-cloud-config-client/src/main/java/org/apache/logging/log4j/spring/cloud/config/client/SpringLookup.java
new file mode 100644
index 0000000..9d62dda
--- /dev/null
+++ b/log4j-spring-cloud-config/log4j-spring-cloud-config-client/src/main/java/org/apache/logging/log4j/spring/cloud/config/client/SpringLookup.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.spring.cloud.config.client;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.core.LogEvent;
+import org.apache.logging.log4j.core.config.plugins.Plugin;
+import org.apache.logging.log4j.core.lookup.StrLookup;
+import org.springframework.core.env.Environment;
+
+/**
+ * Lookup for Spring properties.
+ */
+@Plugin(name = "spring", category = StrLookup.CATEGORY)
+public class SpringLookup implements StrLookup {
+
+ private final Environment environment;
+
+ public SpringLookup() {
+ Object obj = LogManager.getContext(false).getObject(Log4j2CloudConfigLoggingSystem.ENVIRONMENT_KEY);
+ environment = obj instanceof Environment ? (Environment) obj : null;
+ }
+
+ @Override
+ public String lookup(String key) {
+ if (environment != null) {
+ return environment.getProperty(key);
+ }
+ return null;
+ }
+
+ @Override
+ public String lookup(LogEvent event, String key) {
+ return lookup((key));
+ }
+}
diff --git a/log4j-spring-cloud-config/log4j-spring-cloud-config-samples/log4j-spring-cloud-config-sample-server/src/main/config-repo/log4j2.xml b/log4j-spring-cloud-config/log4j-spring-cloud-config-samples/log4j-spring-cloud-config-sample-server/src/main/config-repo/log4j2.xml
index f11e4b1..416dbd1 100644
--- a/log4j-spring-cloud-config/log4j-spring-cloud-config-samples/log4j-spring-cloud-config-sample-server/src/main/config-repo/log4j2.xml
+++ b/log4j-spring-cloud-config/log4j-spring-cloud-config-samples/log4j-spring-cloud-config-sample-server/src/main/config-repo/log4j2.xml
@@ -17,9 +17,13 @@
-->
<Configuration status="ERROR" monitorInterval="0">
+ <Properties>
+ <Property name="spring.application.name">sampleapp</Property>
+ </Properties>
<Appenders>
<Console name="console" target="SYSTEM_OUT">
<JsonLayout properties="true" compact="true" eventEol="true" stackTraceAsString="true">
+ <KeyValuePair key="application" value="$\${spring:spring.application.name}"/>
</JsonLayout>
</Console>
<Flume name="flume" ignoreExceptions="false" type="Embedded" compress="false">
@@ -36,6 +40,7 @@
<KeyValuePair key="containerId" value="\${docker:containerId}"/>
<KeyValuePair key="containerName" value="\${docker:containerName}"/>
<KeyValuePair key="imageName" value="\${docker:imageName}"/>
+ <KeyValuePair key="application" value="\$\${lower:\${spring:spring.application.name}}"/>
</JsonLayout>
</Flume>
<Flume name="avro" ignoreExceptions="false" batchSize="1" compress="false">
@@ -44,6 +49,7 @@
<KeyValuePair key="containerId" value="\${docker:containerId}"/>
<KeyValuePair key="containerName" value="\${docker:containerName}"/>
<KeyValuePair key="imageName" value="\${docker:imageName}"/>
+ <KeyValuePair key="application" value="\$\${lower:\${spring:spring.application.name}}"/>
</JsonLayout>
</Flume>
<Flume name="avroSyslog" ignoreExceptions="false" batchSize="100" compress="false">
@@ -54,6 +60,7 @@
<KeyValuePair key="containerId" value="\${docker:containerId}"/>
<KeyValuePair key="containerName" value="\${docker:containerName}"/>
<KeyValuePair key="imageName" value="\${docker:imageName}"/>
+ <KeyValuePair key="application" value="\$\${lower:\${spring:spring.application.name}}"/>
</LoggerFields>
</RFC5424Layout>
</Flume>
@@ -62,6 +69,7 @@
<KeyValuePair key="containerId" value="\${docker:containerId}"/>
<KeyValuePair key="containerName" value="\${docker:containerName}"/>
<KeyValuePair key="imageName" value="\${docker:imageName}"/>
+ <KeyValuePair key="application" value="\$\${lower:\${spring:spring.application.name}}"/>
</JsonLayout>
<Property name="bootstrap.servers">host.docker.internal:9092</Property>
</Kafka>
@@ -70,6 +78,7 @@
<KeyValuePair key="containerId" value="\${docker:containerId}"/>
<KeyValuePair key="containerName" value="\${docker:containerName}"/>
<KeyValuePair key="imageName" value="\${docker:imageName}"/>
+ <KeyValuePair key="application" value="\$\${lower:\${spring:spring.application.name}}"/>
</JsonLayout>
</Socket>
<RollingFile name="RollingFile" fileName="/var/log/sampleapp/app.log"
@@ -78,6 +87,7 @@
<KeyValuePair key="containerId" value="\${docker:containerId}"/>
<KeyValuePair key="containerName" value="\${docker:containerName}"/>
<KeyValuePair key="imageName" value="\${docker:imageName}"/>
+ <KeyValuePair key="application" value="\$\${lower:\${spring:spring.application.name}}"/>
</JsonLayout>
<SizeBasedTriggeringPolicy size="10MB" />
<DefaultRolloverStrategy max="5"/>
@@ -90,6 +100,7 @@
<KeyValuePair key="containerId" value="\${docker:containerId}"/>
<KeyValuePair key="containerName" value="\${docker:containerName}"/>
<KeyValuePair key="imageName" value="\${docker:imageName}"/>
+ <KeyValuePair key="application" value="\$\${lower:\${spring:spring.application.name}}"/>
</LoggerFields>
</RFC5424Layout>
<SizeBasedTriggeringPolicy size="10MB" />
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 2439925..8159bd2 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -30,6 +30,10 @@
- "remove" - Removed
-->
<release version="2.13.0" date="2019-MM-DD" description="GA Release 2.13.0">
+ <action issue="LOG4J2-2710" dev="rgoers" type="add">
+ Allow Spring Boot application properties to be accessed in the Log4j 2 configuraiton. Add
+ lower and upper case Lookups.
+ </action>
<action issue="LOG4J2-2709" dev="rgoers" type="update">
Allow message portion of GELF layout to be formatted using a PatternLayout. Allow
ThreadContext attributes to be explicitly included or excluded in the GelfLayout.
diff --git a/src/site/markdown/manual/cloud.md b/src/site/markdown/manual/cloud.md
index 83046ba..d0c7a52 100644
--- a/src/site/markdown/manual/cloud.md
+++ b/src/site/markdown/manual/cloud.md
@@ -132,6 +132,7 @@ one ip address associated with its DNS entry the socket appender will fail throu
<ThreadContextIncludes>requestId,sessionId,loginId,userId,ipAddress,callingHost</ThreadContextIncludes>
<MessagePattern>%d [%t] %-5p %X{requestId, sessionId, loginId, userId, ipAddress} %C{1.}.%M:%L - %m%n</MessagePattern>
<KeyValuePair key="containerId" value="${docker:containerId:-}"/>
+ <KeyValuePair key="application" value="$${lower:${spring:spring.application.name:-spring}}"/>
</GelfLayout>
</Socket>
diff --git a/src/site/xdoc/manual/lookups.xml b/src/site/xdoc/manual/lookups.xml
index 051033f..4c10ed0 100644
--- a/src/site/xdoc/manual/lookups.xml
+++ b/src/site/xdoc/manual/lookups.xml
@@ -229,6 +229,19 @@
</PatternLayout>
</File>]]></pre>
</subsection>
+ <a name="LowerLookup"/>
+ <subsection name="Lower Lookup">
+ <p>
+ The LowerLookup converts the passed in argument to lower case. Presumably the value will be the
+ result of a nested lookup.
+ </p>
+ <pre class="prettyprint linenums"><![CDATA[
+<File name="Application" fileName="application.log">
+ <PatternLayout>
+ <pattern>%d %p %c{1.} [%t] $${lower:{${spring:spring.application.name}} %m%n</pattern>
+ </PatternLayout>
+</File>]]></pre>
+ </subsection>
<a name="AppMainArgsLookup"/>
<subsection name="Main Arguments Lookup (Application)">
<p>
@@ -420,6 +433,20 @@ logger.info(PERFORMANCE, "Message in Performance.log");]]></pre>
the name, otherwise <code>null</code>.
</p>
</subsection>
+ <a name="SpringLookup"/>
+ <subsection name="Spring Boot Lookup">
+ <p>
+ The Spring Boot Lookup retrieves the values of Spring properties from the Spring configuration. This Lookup
+ will return null values until Spring Boot initializes application logging.
+ </p>
+ <pre class="prettyprint linenums"><![CDATA[
+<File name="Application" fileName="application.log">
+ <PatternLayout>
+ <pattern>%d %p %c{1.} [%t] $${spring:spring.application.name} %m%n</pattern>
+ </PatternLayout>
+</File>]]></pre>
+ <p>This Lookup requires log4j-spring-cloud-config-client be included in the application.</p>
+ </subsection>
<a name="StructuredDataLookup"/>
<subsection name="Structured Data Lookup">
<p>
@@ -530,7 +557,19 @@ logger.info(PERFORMANCE, "Message in Performance.log");]]></pre>
<File name="ApplicationLog" fileName="${web:rootDir}/app.log"/>
</Appenders>]]></pre>
</subsection>
-
+ <a name="UpperLookup"/>
+ <subsection name="Upper Lookup">
+ <p>
+ The UpperLookup converts the passed in argument to upper case. Presumably the value will be the
+ result of a nested lookup.
+ </p>
+ <pre class="prettyprint linenums"><![CDATA[
+<File name="Application" fileName="application.log">
+ <PatternLayout>
+ <pattern>%d %p %c{1.} [%t] $$upper{${spring:spring.application.name}} %m%n</pattern>
+ </PatternLayout>
+</File>]]></pre>
+ </subsection>
</section>
</body>
</document>