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:09 UTC
[logging-log4j2] branch master 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 master
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git
The following commit(s) were added to refs/heads/master by this push:
new 195134b LOG4J2-2710 - Allow Spring Boot application properties to be accessed in the Log4j 2 configuraiton. Add lower and upper case Lookups.
195134b is described below
commit 195134b6cb8ae86fe7070c7ebe2c0beefebffc10
Author: Ralph Goers <rg...@apache.org>
AuthorDate: Sat Oct 19 18:57:48 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 ++++++++++++++++++++
.../client/Log4j2CloudConfigLoggingSystem.java | 29 +++++++++---
.../spring/cloud/config/client/SpringLookup.java | 50 +++++++++++++++++++++
.../src/main/config-repo/log4j2.xml | 10 +++++
src/changes/changes.xml | 4 ++
src/site/asciidoc/manual/lookups.adoc | 47 +++++++++++++++++++
src/site/markdown/manual/cloud.md | 1 +
12 files changed, 388 insertions(+), 13 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 d84ab2a..351b2ae 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 {
@@ -372,7 +382,7 @@ public class LoggerContext extends AbstractLifeCycle
configuration = NULL_CONFIGURATION;
updateLoggers();
((LifeCycle) prev).stop(timeout, timeUnit);
- externalContext = null;
+ externalMap.clear();
LogManager.getFactory().removeContext(this);
} finally {
configLock.unlock();
@@ -419,13 +429,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);
+ }
}
/**
@@ -435,7 +474,7 @@ public class LoggerContext extends AbstractLifeCycle
*/
@Override
public Object getExternalContext() {
- return this.externalContext;
+ return this.externalMap.get(EXTERNAL_CONTEXT_KEY);
}
/**
@@ -637,6 +676,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 854a762..10a63b0 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";
@@ -100,6 +102,8 @@ public class Interpolator extends AbstractConfigurationAwareLookup {
strLookupMap.put("marker", new MarkerLookup());
strLookupMap.put("java", new JavaLookup());
strLookupMap.put("base64", new Base64StrLookup());
+ strLookupMap.put("lower", new LowerLookup());
+ strLookupMap.put("upper", new UpperLookup());
// JNDI
try {
// [LOG4J2-703] We might be on Android
@@ -135,6 +139,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() {
@@ -160,7 +170,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..366ff9a
--- /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.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..94737b9
--- /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.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/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..5c4aea0 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,40 @@ 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();
@@ -103,6 +114,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..53c97ea
--- /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.lookup.StrLookup;
+import org.apache.logging.log4j.plugins.Plugin;
+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 84b9673..40d3098 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
@@ -1,6 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="DEBUG" 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">
@@ -20,6 +23,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">
@@ -28,6 +32,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">
@@ -38,6 +43,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>
@@ -46,6 +52,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>
@@ -54,6 +61,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"
@@ -62,6 +70,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"/>
@@ -74,6 +83,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 59dbd6b..5ecb436 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -157,6 +157,10 @@
</action>
</release>
<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/asciidoc/manual/lookups.adoc b/src/site/asciidoc/manual/lookups.adoc
index bf745c4..cea14ff 100644
--- a/src/site/asciidoc/manual/lookups.adoc
+++ b/src/site/asciidoc/manual/lookups.adoc
@@ -241,6 +241,21 @@ relative to the log4j configuration file.
</File>
----
+[#LowerLookup]
+== Lower Lookup
+
+The LowerLookup converts the passed in argument to lower case. Presumably the value will be the
+result of a nested lookup.
+
+[source,xml]
+----
+<File name="Application" fileName="application.log">
+ <PatternLayout>
+ <pattern>%d %p %c{1.} [%t] $${lower:{${spring:spring.application.name}} %m%n</pattern>
+ </PatternLayout>
+</File>
+----
+
[#AppMainArgsLookup]
== Main Arguments Lookup (Application)
@@ -450,6 +465,23 @@ while "type" would have to be an item in the Map in a MapMessage.
</Routing>
----
+[#SpringLookup]
+== Spring Boot Lookup
+
+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.
+
+[source,xml]
+----
+<File name="Application" fileName="application.log">
+ <PatternLayout>
+ <pattern>%d %p %c{1.} [%t] $${spring:spring.application.name} %m%n</pattern>
+ </PatternLayout>
+</File>
+----
+
+This Lookup requires log4j-spring-cloud-config-client be included in the application.
+
[#SystemPropertiesLookup]
== System Properties Lookup
@@ -477,6 +509,21 @@ when the `logPath` system property is undefined, the default value
</Appenders>
----
+[#UpperLookup]
+== Upper Lookup
+
+The LowerLookup converts the passed in argument to upper case. Presumably the value will be the
+result of a nested lookup.
+
+[source,xml]
+----
+<File name="Application" fileName="application.log">
+ <PatternLayout>
+ <pattern>%d %p %c{1.} [%t] $${upper:{${spring:spring.application.name}} %m%n</pattern>
+ </PatternLayout>
+</File>
+----
+
[#WebLookup]
== Web Lookup
diff --git a/src/site/markdown/manual/cloud.md b/src/site/markdown/manual/cloud.md
index a9c919f..9336914 100644
--- a/src/site/markdown/manual/cloud.md
+++ b/src/site/markdown/manual/cloud.md
@@ -133,6 +133,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>