Support <springProperty> in logback configurations
Include support for a new <springProperty> element which can be used in
`logback-spring.xml` files to add properties from the Spring
Environment. For example:
<configuration>
...
<springProperty name="destination" source="my.loggger.extradest"/>
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<file>${destination}</file>
...
</file>
</appender>
...
</configuration>
Fixes gh-1788
This commit is contained in:
parent
f3f562f386
commit
055ace37f0
|
|
@ -17,6 +17,7 @@
|
|||
package org.springframework.boot.logging.logback;
|
||||
|
||||
import org.springframework.boot.logging.LoggingInitializationContext;
|
||||
import org.springframework.core.env.Environment;
|
||||
|
||||
import ch.qos.logback.classic.joran.JoranConfigurator;
|
||||
import ch.qos.logback.core.joran.action.NOPAction;
|
||||
|
|
@ -40,6 +41,9 @@ class SpringBootJoranConfigurator extends JoranConfigurator {
|
|||
@Override
|
||||
public void addInstanceRules(RuleStore rs) {
|
||||
super.addInstanceRules(rs);
|
||||
Environment environment = this.initializationContext.getEnvironment();
|
||||
rs.addRule(new ElementSelector("configuration/springProperty"),
|
||||
new SpringPropertyAction(environment));
|
||||
rs.addRule(new ElementSelector("*/springProfile"), new SpringProfileAction(
|
||||
this.initializationContext.getEnvironment()));
|
||||
rs.addRule(new ElementSelector("*/springProfile/*"), new NOPAction());
|
||||
|
|
|
|||
|
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
* Copyright 2012-2015 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.boot.logging.logback;
|
||||
|
||||
import org.springframework.boot.bind.RelaxedPropertyResolver;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.xml.sax.Attributes;
|
||||
|
||||
import ch.qos.logback.core.joran.action.Action;
|
||||
import ch.qos.logback.core.joran.action.ActionUtil;
|
||||
import ch.qos.logback.core.joran.action.ActionUtil.Scope;
|
||||
import ch.qos.logback.core.joran.spi.ActionException;
|
||||
import ch.qos.logback.core.joran.spi.InterpretationContext;
|
||||
import ch.qos.logback.core.util.OptionHelper;
|
||||
|
||||
/**
|
||||
* Lockback {@link Action} to support {@code <springProperty>} tags. Allows logback
|
||||
* properties to be sourced from the Spring environment.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
class SpringPropertyAction extends Action {
|
||||
|
||||
private static final String SOURCE_ATTRIBUTE = "source";
|
||||
|
||||
private final Environment environment;
|
||||
|
||||
public SpringPropertyAction(Environment environment) {
|
||||
this.environment = environment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void begin(InterpretationContext ic, String elementName, Attributes attributes)
|
||||
throws ActionException {
|
||||
String name = attributes.getValue(NAME_ATTRIBUTE);
|
||||
String source = attributes.getValue(SOURCE_ATTRIBUTE);
|
||||
Scope scope = ActionUtil.stringToScope(attributes.getValue(SCOPE_ATTRIBUTE));
|
||||
if (OptionHelper.isEmpty(name) || OptionHelper.isEmpty(source)) {
|
||||
addError("The \"name\" and \"source\" attributes of <springProperty> must be set");
|
||||
}
|
||||
ActionUtil.setProperty(ic, name, getValue(source), scope);
|
||||
}
|
||||
|
||||
private String getValue(String source) {
|
||||
if (this.environment == null) {
|
||||
addWarn("No Spring Environment available to resolve " + source);
|
||||
return null;
|
||||
}
|
||||
String value = this.environment.getProperty(source);
|
||||
if (value != null) {
|
||||
return value;
|
||||
}
|
||||
int lastDot = source.lastIndexOf(".");
|
||||
if (lastDot > 0) {
|
||||
String prefix = source.substring(0, lastDot + 1);
|
||||
RelaxedPropertyResolver resolver = new RelaxedPropertyResolver(
|
||||
this.environment, prefix);
|
||||
return resolver.getProperty(source.substring(lastDot + 1));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void end(InterpretationContext ic, String name) throws ActionException {
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -23,6 +23,7 @@ import org.junit.Test;
|
|||
import org.slf4j.Logger;
|
||||
import org.slf4j.impl.StaticLoggerBinder;
|
||||
import org.springframework.boot.logging.LoggingInitializationContext;
|
||||
import org.springframework.boot.test.EnvironmentTestUtils;
|
||||
import org.springframework.boot.test.OutputCapture;
|
||||
import org.springframework.mock.env.MockEnvironment;
|
||||
|
||||
|
|
@ -31,7 +32,9 @@ import ch.qos.logback.classic.joran.JoranConfigurator;
|
|||
import ch.qos.logback.core.joran.spi.JoranException;
|
||||
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.not;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link SpringBootJoranConfigurator}.
|
||||
|
|
@ -103,6 +106,20 @@ public class SpringBootJoranConfiguratorTests {
|
|||
doTestNestedProfile(false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void springProperty() throws Exception {
|
||||
EnvironmentTestUtils.addEnvironment(this.environment, "my.example-property:test");
|
||||
initialize("property.xml");
|
||||
assertThat(this.context.getProperty("MINE"), equalTo("test"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void relaxedSpringProperty() throws Exception {
|
||||
EnvironmentTestUtils.addEnvironment(this.environment, "my.EXAMPLE_PROPERTY:test");
|
||||
initialize("property.xml");
|
||||
assertThat(this.context.getProperty("MINE"), equalTo("test"));
|
||||
}
|
||||
|
||||
private void doTestNestedProfile(boolean expected, String... profiles)
|
||||
throws JoranException {
|
||||
this.environment.setActiveProfiles(profiles);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration>
|
||||
<include resource="org/springframework/boot/logging/logback/base.xml" />
|
||||
<springProperty scope="context" name="MINE" source="my.example-property"/>
|
||||
</configuration>
|
||||
Loading…
Reference in New Issue