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 2020/04/13 04:04:45 UTC

[logging-log4j2] branch release-2.x updated: LOG4J2-2818 - Allow Spring Lookup to return default and active profiles

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 30a9345  LOG4J2-2818 - Allow Spring Lookup to return default and active profiles
30a9345 is described below

commit 30a9345a1f6e02699402b7e5050fd2f32a687eae
Author: Ralph Goers <rg...@apache.org>
AuthorDate: Sun Apr 12 21:04:28 2020 -0700

    LOG4J2-2818 - Allow Spring Lookup to return default and active profiles
---
 .../log4j-spring-cloud-config-client/pom.xml       | 12 +++
 .../spring/cloud/config/client/SpringLookup.java   | 88 ++++++++++++++++++++++
 .../cloud/config/client/SpringLookupTest.java      | 60 +++++++++++++++
 src/changes/changes.xml                            |  3 +
 src/site/xdoc/manual/lookups.xml                   | 13 +++-
 5 files changed, 173 insertions(+), 3 deletions(-)

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 d5a65d1..b345279 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
@@ -82,6 +82,18 @@
       <type>test-jar</type>
       <scope>test</scope>
     </dependency>
+    <dependency>
+      <groupId>org.springframework.boot</groupId>
+      <artifactId>spring-boot-starter-test</artifactId>
+      <version>${spring-boot.version}</version>
+      <scope>test</scope>
+      <exclusions>
+        <exclusion>
+          <groupId>org.springframework.boot</groupId>
+          <artifactId>spring-boot-starter-logging</artifactId>
+        </exclusion>
+      </exclusions>
+    </dependency>
   </dependencies>
   <build>
     <plugins>
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
index d8e74eb..7da12ea 100644
--- 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
@@ -16,17 +16,29 @@
  */
 package org.apache.logging.log4j.spring.cloud.config.client;
 
+import org.apache.logging.log4j.Logger;
 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.apache.logging.log4j.status.StatusLogger;
 import org.springframework.core.env.Environment;
 
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
 /**
  * Lookup for Spring properties.
  */
 @Plugin(name = "spring", category = StrLookup.CATEGORY)
 public class SpringLookup extends SpringEnvironmentHolder implements StrLookup {
 
+    private static final Logger LOGGER = StatusLogger.getLogger();
+    private static final String ACTIVE = "profiles.active";
+    private static final String DEFAULT = "profiles.default";
+    private static final String PATTERN = "\\[(\\d+?)\\]";
+    private static final Pattern ACTIVE_PATTERN = Pattern.compile(ACTIVE + PATTERN);
+    private static final Pattern DEFAULT_PATTERN = Pattern.compile(DEFAULT + PATTERN);
+
     public SpringLookup() {
         getEnvironment();
     }
@@ -35,7 +47,83 @@ public class SpringLookup extends SpringEnvironmentHolder implements StrLookup {
     public String lookup(String key) {
         Environment env = getEnvironment();
         if (env != null) {
+            String lowerKey = key.toLowerCase();
+            if (lowerKey.startsWith(ACTIVE)) {
+                switch (env.getActiveProfiles().length) {
+                    case 0: {
+                        return null;
+                    }
+                    case 1: {
+                        return env.getActiveProfiles()[0];
+                    }
+                    default: {
+                        Matcher matcher = ACTIVE_PATTERN.matcher(key);
+                        if (matcher.matches()) {
+                            try {
+                                int index = Integer.parseInt(matcher.group(1));
+                                if (index < env.getActiveProfiles().length) {
+                                    return env.getActiveProfiles()[index];
+                                } else {
+                                    LOGGER.warn("Index out of bounds for Spring active profiles: {}", index);
+                                    return null;
+                                }
+                            } catch (Exception ex) {
+                                LOGGER.warn("Unable to parse {} as integer value", matcher.group(1));
+                                return null;
+                            }
+
+                        } else {
+                            StringBuilder sb = new StringBuilder();
+                            for (String profile : env.getActiveProfiles()) {
+                                if (sb.length() > 0) {
+                                    sb.append(",");
+                                }
+                                sb.append(profile);
+                            }
+                            return sb.toString();
+                        }
+                    }
+                }
+            } else if (lowerKey.startsWith(DEFAULT)) {
+                switch (env.getDefaultProfiles().length) {
+                    case 0: {
+                        return null;
+                    }
+                    case 1: {
+                        return env.getDefaultProfiles()[0];
+                    }
+                    default: {
+                        Matcher matcher = DEFAULT_PATTERN.matcher(key);
+                        if (matcher.matches()) {
+                            try {
+                                int index = Integer.parseInt(matcher.group(1));
+                                if (index < env.getDefaultProfiles().length) {
+                                    return env.getDefaultProfiles()[index];
+                                } else {
+                                    LOGGER.warn("Index out of bounds for Spring default profiles: {}", index);
+                                    return null;
+                                }
+                            } catch (Exception ex) {
+                                LOGGER.warn("Unable to parse {} as integer value", matcher.group(1));
+                                return null;
+                            }
+
+                        } else {
+                            StringBuilder sb = new StringBuilder();
+                            for (String profile : env.getDefaultProfiles()) {
+                                if (sb.length() > 0) {
+                                    sb.append(",");
+                                }
+                                sb.append(profile);
+                            }
+                            return sb.toString();
+                        }
+                    }
+                }
+            }
+
             return env.getProperty(key);
+
         }
         return null;
     }
diff --git a/log4j-spring-cloud-config/log4j-spring-cloud-config-client/src/test/java/org/apache/logging/log4j/spring/cloud/config/client/SpringLookupTest.java b/log4j-spring-cloud-config/log4j-spring-cloud-config-client/src/test/java/org/apache/logging/log4j/spring/cloud/config/client/SpringLookupTest.java
new file mode 100644
index 0000000..9fa8a21
--- /dev/null
+++ b/log4j-spring-cloud-config/log4j-spring-cloud-config-client/src/test/java/org/apache/logging/log4j/spring/cloud/config/client/SpringLookupTest.java
@@ -0,0 +1,60 @@
+/*
+ * 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.LoggerContext;
+import org.junit.Test;
+import org.springframework.mock.env.MockEnvironment;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+/**
+ * Test SpringLookup.
+ */
+public class SpringLookupTest {
+
+    @Test
+    public void testLookup() {
+        MockEnvironment env = new MockEnvironment();
+        env.setActiveProfiles("test");
+        env.setDefaultProfiles("one", "two");
+        env.setProperty("app.property", "test");
+        LoggerContext context = (LoggerContext) LogManager.getContext(false);
+        context.putObject(Log4j2CloudConfigLoggingSystem.ENVIRONMENT_KEY, env);
+        SpringLookup lookup = new SpringLookup();
+        String result = lookup.lookup("profiles.active");
+        assertNotNull("No active profiles", result);
+        assertEquals("Incorrect active profile", "test", result);
+        result = lookup.lookup("profiles.active[0]");
+        assertNotNull("No active profiles", result);
+        assertEquals("Incorrect active profile", "test", result);
+        result = lookup.lookup("profiles.default");
+        assertNotNull("No default profiles", result);
+        assertEquals("Incorrect default profiles", "one,two", result);
+        result = lookup.lookup("profiles.default[0]");
+        assertNotNull("No default profiles", result);
+        assertEquals("Incorrect default profiles", "one", result);
+        result = lookup.lookup("profiles.default[2]");
+        assertNull("Did not get index out of bounds", result);
+        result = lookup.lookup("app.property");
+        assertNotNull("Did not find property", result);
+        assertEquals("Incorrect property value", "test", result);
+    }
+}
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index c4b18af..c390c76 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -30,6 +30,9 @@
          - "remove" - Removed
     -->
     <release version="2.13.2" date="2020-MM-DD" description="GA Release 2.13.2">
+      <action issue="LOG4J2-2818" dev="rgoers" type="update">
+        Allow Spring Lookup to return default and active profiles.
+      </action>
       <action issue="LOG4J2-2791" dev="rgoers" type="fix" due-to="Johan Karlberg">
         Correct JsonLayout timestamp sorting issue.
       </action>
diff --git a/src/site/xdoc/manual/lookups.xml b/src/site/xdoc/manual/lookups.xml
index 132b462..69cb57a 100644
--- a/src/site/xdoc/manual/lookups.xml
+++ b/src/site/xdoc/manual/lookups.xml
@@ -582,11 +582,18 @@ logger.info(PERFORMANCE, "Message in Performance.log");]]></pre>
         <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.
+            The Spring Boot Lookup retrieves the values of Spring properties from the Spring configuration as well as
+            values of the active and default profiles. Specifying a key of "profiles.active" will reutrn the active
+            profiles while a key of "profiles.default" will return the default profiles. The default and active
+            profiles can be an array. If more than one profile is present they will be returned as a comma separated
+            list. To retrieve a single item from the array append "[{index}]" to the key. For example, to return the
+            first active profile in the list specify "profiles.active[0]".
+          </p>
+          <p>
+            This Lookup will return null values until Spring Boot initializes application logging.
           </p>
           <pre class="prettyprint linenums"><![CDATA[
-<File name="Application" fileName="application.log">
+<File name="Application" fileName="application-${spring:profiles.active[0]}.log">
   <PatternLayout>
     <pattern>%d %p %c{1.} [%t] $${spring:spring.application.name} %m%n</pattern>
   </PatternLayout>