Skip to content

Commit d5d96df

Browse files
committed
Honor logback.debug property and write Logback statuses to console
Closes gh-16876
1 parent 60358da commit d5d96df

File tree

4 files changed

+110
-3
lines changed

4 files changed

+110
-3
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
/*
2+
* Copyright 2012-2019 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://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.springframework.boot.logging.logback;
18+
19+
import ch.qos.logback.classic.Level;
20+
import ch.qos.logback.classic.LoggerContext;
21+
import ch.qos.logback.classic.spi.ILoggingEvent;
22+
import ch.qos.logback.core.Appender;
23+
import ch.qos.logback.core.pattern.Converter;
24+
import ch.qos.logback.core.spi.LifeCycle;
25+
import ch.qos.logback.core.status.InfoStatus;
26+
import ch.qos.logback.core.status.Status;
27+
28+
/**
29+
* Custom {@link LogbackConfigurator} used to add {@link Status Statuses} when Logback
30+
* debugging is enabled.
31+
*
32+
* @author Andy Wilkinson
33+
*/
34+
class DebugLogbackConfigurator extends LogbackConfigurator {
35+
36+
DebugLogbackConfigurator(LoggerContext context) {
37+
super(context);
38+
}
39+
40+
@Override
41+
@SuppressWarnings("rawtypes")
42+
public void conversionRule(String conversionWord, Class<? extends Converter> converterClass) {
43+
info("Adding conversion rule of type '" + converterClass.getName() + "' for word '" + conversionWord);
44+
super.conversionRule(conversionWord, converterClass);
45+
}
46+
47+
@Override
48+
public void appender(String name, Appender<?> appender) {
49+
info("Adding appender '" + appender + "' named '" + name + "'");
50+
super.appender(name, appender);
51+
}
52+
53+
@Override
54+
public void logger(String name, Level level, boolean additive, Appender<ILoggingEvent> appender) {
55+
info("Configuring logger '" + name + "' with level '" + level + "'. Additive: " + additive);
56+
if (appender != null) {
57+
info("Adding appender '" + appender + "' to logger '" + name + "'");
58+
}
59+
super.logger(name, level, additive, appender);
60+
}
61+
62+
@Override
63+
public void start(LifeCycle lifeCycle) {
64+
info("Starting '" + lifeCycle + "'");
65+
super.start(lifeCycle);
66+
}
67+
68+
private void info(String message) {
69+
getContext().getStatusManager().add(new InfoStatus(message, this));
70+
}
71+
72+
}

spring-boot-project/spring-boot/src/main/java/org/springframework/boot/logging/logback/LogbackConfigurator.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@
2828
import ch.qos.logback.core.pattern.Converter;
2929
import ch.qos.logback.core.spi.ContextAware;
3030
import ch.qos.logback.core.spi.LifeCycle;
31-
import ch.qos.logback.core.spi.PropertyContainer;
3231

3332
import org.springframework.util.Assert;
3433

@@ -47,7 +46,7 @@ class LogbackConfigurator {
4746
this.context = context;
4847
}
4948

50-
public PropertyContainer getContext() {
49+
public LoggerContext getContext() {
5150
return this.context;
5251
}
5352

spring-boot-project/spring-boot/src/main/java/org/springframework/boot/logging/logback/LogbackLoggingSystem.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,9 @@
3333
import ch.qos.logback.classic.util.ContextInitializer;
3434
import ch.qos.logback.core.joran.spi.JoranException;
3535
import ch.qos.logback.core.spi.FilterReply;
36+
import ch.qos.logback.core.status.OnConsoleStatusListener;
3637
import ch.qos.logback.core.status.Status;
38+
import ch.qos.logback.core.util.StatusListenerConfigHelper;
3739
import org.slf4j.ILoggerFactory;
3840
import org.slf4j.Logger;
3941
import org.slf4j.Marker;
@@ -125,7 +127,12 @@ public void initialize(LoggingInitializationContext initializationContext, Strin
125127
protected void loadDefaults(LoggingInitializationContext initializationContext, LogFile logFile) {
126128
LoggerContext context = getLoggerContext();
127129
stopAndReset(context);
128-
LogbackConfigurator configurator = new LogbackConfigurator(context);
130+
boolean debug = Boolean.getBoolean("logback.debug");
131+
if (debug) {
132+
StatusListenerConfigHelper.addOnConsoleListenerInstance(context, new OnConsoleStatusListener());
133+
}
134+
LogbackConfigurator configurator = debug ? new DebugLogbackConfigurator(context)
135+
: new LogbackConfigurator(context);
129136
Environment environment = initializationContext.getEnvironment();
130137
context.putProperty(LoggingSystemProperties.LOG_LEVEL_PATTERN,
131138
environment.resolvePlaceholders("${logging.pattern.level:${LOG_LEVEL_PATTERN:%5p}}"));

spring-boot-project/spring-boot/src/test/java/org/springframework/boot/logging/logback/LogbackLoggingSystemTests.java

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -460,6 +460,35 @@ public void testDateformatPatternProperty() {
460460
.containsPattern("\\d{4}-\\d{2}\\-\\d{2}T\\d{2}:\\d{2}:\\d{2}");
461461
}
462462

463+
@Test
464+
public void noDebugOutputIsProducedByDefault() {
465+
System.clearProperty("logback.debug");
466+
this.loggingSystem.beforeInitialize();
467+
File file = new File(tmpDir(), "logback-test.log");
468+
LogFile logFile = getLogFile(file.getPath(), null);
469+
this.loggingSystem.initialize(this.initializationContext, null, logFile);
470+
String output = this.output.toString().trim();
471+
System.out.println(output);
472+
assertThat(output).doesNotContain("LevelChangePropagator").doesNotContain("SizeAndTimeBasedFNATP");
473+
}
474+
475+
@Test
476+
public void logbackDebugPropertyIsHonored() {
477+
System.setProperty("logback.debug", "true");
478+
try {
479+
this.loggingSystem.beforeInitialize();
480+
File file = new File(tmpDir(), "logback-test.log");
481+
LogFile logFile = getLogFile(file.getPath(), null);
482+
this.loggingSystem.initialize(this.initializationContext, null, logFile);
483+
String output = this.output.toString().trim();
484+
assertThat(output).contains("LevelChangePropagator").contains("SizeAndTimeBasedFNATP")
485+
.contains("DebugLogbackConfigurator");
486+
}
487+
finally {
488+
System.clearProperty("logback.debug");
489+
}
490+
}
491+
463492
private static Logger getRootLogger() {
464493
ILoggerFactory factory = StaticLoggerBinder.getSingleton().getLoggerFactory();
465494
LoggerContext context = (LoggerContext) factory;

0 commit comments

Comments
 (0)