Skip to content

Commit 1786e2f

Browse files
authored
support set console level separately (rabbitmq#143)
1 parent 2667483 commit 1786e2f

File tree

13 files changed

+270
-60
lines changed

13 files changed

+270
-60
lines changed

src/main/java/com/alipay/sofa/common/log/factory/AbstractLoggerSpaceFactory.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,9 @@
2828
*/
2929
public abstract class AbstractLoggerSpaceFactory implements ILoggerFactory {
3030

31-
private String source;
31+
protected static final String CONSOLE = "CONSOLE";
32+
33+
private String source;
3234

3335
/***
3436
* 改变指定日志的级别,子类需要复写此方法来实现动态改变日志级别

src/main/java/com/alipay/sofa/common/log/factory/Log4j2LoggerSpaceFactory.java

+29-29
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,13 @@
2525
import org.apache.logging.log4j.LogManager;
2626
import org.apache.logging.log4j.Marker;
2727
import org.apache.logging.log4j.ThreadContext;
28+
import org.apache.logging.log4j.core.Filter;
2829
import org.apache.logging.log4j.core.LoggerContext;
2930
import org.apache.logging.log4j.core.appender.ConsoleAppender;
3031
import org.apache.logging.log4j.core.config.Configuration;
3132
import org.apache.logging.log4j.core.config.ConfigurationFactory;
3233
import org.apache.logging.log4j.core.filter.AbstractFilter;
34+
import org.apache.logging.log4j.core.filter.ThresholdFilter;
3335
import org.apache.logging.log4j.core.layout.PatternLayout;
3436
import org.apache.logging.log4j.message.Message;
3537
import org.apache.logging.slf4j.Log4jLogger;
@@ -49,16 +51,18 @@
4951
* @since 1.0.15
5052
*/
5153
public class Log4j2LoggerSpaceFactory extends AbstractLoggerSpaceFactory {
52-
private static final String CONSOLE = "CONSOLE";
5354

5455
private ConcurrentMap<String, Logger> loggerMap = new ConcurrentHashMap<>();
5556
private SpaceId spaceId;
5657
private Properties properties;
5758
private LoggerContext loggerContext;
5859
private URL confFile;
5960

60-
private final ConsoleAppender consoleAppender;
61-
private final Level consoleLevel;
61+
/**
62+
* key: loggerName, value: consoleAppender
63+
* each logger have their own consoleAppender if had configured
64+
**/
65+
private ConcurrentMap<String, ConsoleAppender> consoleAppenders = new ConcurrentHashMap<>();
6266

6367
/**
6468
* @param source logback,log4j2,log4j,temp,nop
@@ -69,10 +73,6 @@ public Log4j2LoggerSpaceFactory(SpaceId spaceId, Properties properties, URL conf
6973
this.spaceId = spaceId;
7074
this.properties = properties;
7175
this.confFile = confFile;
72-
73-
consoleAppender = createConsoleAppender();
74-
consoleLevel = getConsoleLevel();
75-
7676
this.loggerContext = initialize();
7777
attachConsoleAppender();
7878
}
@@ -128,38 +128,32 @@ private void attachConsoleAppender() {
128128

129129
if (Boolean.TRUE.toString().equalsIgnoreCase(value)) {
130130
loggerContext.addFilter(new AbstractFilter() {
131-
private void process(org.apache.logging.log4j.core.Logger logger, Level level) {
131+
private void process(org.apache.logging.log4j.core.Logger logger) {
132+
ConsoleAppender appender = getOrCreateConsoleAppender(logger.getName());
132133
if (CommonLoggingConfigurations.shouldAttachConsoleAppender(logger.getName())
133134
&& !logger.getAppenders().containsKey(CONSOLE)) {
134-
logger.addAppender(consoleAppender);
135-
int intLevel = Level.DEBUG.intLevel();
136-
if (logger.getLevel() != null) {
137-
intLevel = logger.getLevel().intLevel();
138-
}
139-
if (intLevel > consoleLevel.intLevel()) {
140-
logger.setLevel(level);
141-
}
135+
logger.addAppender(appender);
142136
}
143137
}
144138

145139
@Override
146140
public Result filter(org.apache.logging.log4j.core.Logger logger, Level level, Marker marker, Message msg,
147141
Throwable t) {
148-
process(logger, level);
142+
process(logger);
149143
return Result.NEUTRAL;
150144
}
151145

152146
@Override
153147
public Result filter(org.apache.logging.log4j.core.Logger logger, Level level, Marker marker, Object msg,
154148
Throwable t) {
155-
process(logger, level);
149+
process(logger);
156150
return Result.NEUTRAL;
157151
}
158152

159153
@Override
160154
public Result filter(org.apache.logging.log4j.core.Logger logger, Level level, Marker marker, String msg,
161155
Object... params) {
162-
process(logger, level);
156+
process(logger);
163157
return Result.NEUTRAL;
164158
}
165159
});
@@ -191,16 +185,21 @@ public Logger getLogger(String name) {
191185
return loggerMap.get(name);
192186
}
193187

194-
private ConsoleAppender createConsoleAppender() {
195-
String logPattern = properties.getProperty(Constants.SOFA_MIDDLEWARE_LOG_CONSOLE_LOG4J2_PATTERN,
196-
Constants.SOFA_MIDDLEWARE_LOG_CONSOLE_LOG4J2_PATTERN_DEFAULT);
197-
198-
PatternLayout patternLayout = PatternLayout.newBuilder().withPattern(logPattern).build();
199-
ConsoleAppender.Builder builder = ConsoleAppender.newBuilder();
200-
builder.withLayout(patternLayout).withName(CONSOLE);
201-
ConsoleAppender appender = builder.build();
202-
appender.start();
203-
return appender;
188+
private ConsoleAppender getOrCreateConsoleAppender(String loggerName){
189+
return consoleAppenders.computeIfAbsent(loggerName, k -> {
190+
String logPattern = properties.getProperty(Constants.SOFA_MIDDLEWARE_LOG_CONSOLE_LOG4J2_PATTERN,
191+
Constants.SOFA_MIDDLEWARE_LOG_CONSOLE_LOG4J2_PATTERN_DEFAULT);
192+
Level level = getConsoleLevel();
193+
PatternLayout patternLayout = PatternLayout.newBuilder().withPattern(logPattern).build();
194+
Filter filter = ThresholdFilter.createFilter(level, Filter.Result.NEUTRAL, Filter.Result.DENY);
195+
ConsoleAppender.Builder<?> builder = ConsoleAppender.newBuilder()
196+
.setLayout(patternLayout)
197+
.setName(CONSOLE)
198+
.setFilter(filter);
199+
ConsoleAppender appender = builder.build();
200+
appender.start();
201+
return appender;
202+
});
204203
}
205204

206205
private Level getConsoleLevel() {
@@ -235,4 +234,5 @@ private Level toLog4j2Level(AdapterLevel adapterLevel) {
235234
+ " is unknown when adapter to log4j2.");
236235
}
237236
}
237+
238238
}

src/main/java/com/alipay/sofa/common/log/factory/LogbackLoggerSpaceFactory.java

+35-25
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import ch.qos.logback.classic.Level;
2020
import ch.qos.logback.classic.LoggerContext;
2121
import ch.qos.logback.classic.encoder.PatternLayoutEncoder;
22+
import ch.qos.logback.classic.filter.ThresholdFilter;
2223
import ch.qos.logback.classic.spi.ILoggingEvent;
2324
import ch.qos.logback.classic.turbo.TurboFilter;
2425
import ch.qos.logback.classic.util.ContextInitializer;
@@ -28,14 +29,17 @@
2829
import ch.qos.logback.core.util.OptionHelper;
2930
import com.alipay.sofa.common.log.CommonLoggingConfigurations;
3031
import com.alipay.sofa.common.log.Constants;
31-
import com.alipay.sofa.common.space.SpaceId;
3232
import com.alipay.sofa.common.log.adapter.level.AdapterLevel;
33+
import com.alipay.sofa.common.space.SpaceId;
3334
import com.alipay.sofa.common.utils.StringUtil;
3435
import org.slf4j.Logger;
3536
import org.slf4j.Marker;
3637

3738
import java.net.URL;
38-
import java.util.*;
39+
import java.util.Map;
40+
import java.util.Properties;
41+
import java.util.concurrent.ConcurrentHashMap;
42+
import java.util.concurrent.ConcurrentMap;
3943

4044
/**
4145
* @author qilong.zql
@@ -47,18 +51,18 @@ public class LogbackLoggerSpaceFactory extends AbstractLoggerSpaceFactory {
4751
private LoggerContext loggerContext;
4852
private Properties properties;
4953

50-
// Console appender on this logger context
51-
private final ConsoleAppender<ILoggingEvent> consoleAppender;
52-
private final Level consoleLevel;
54+
/**
55+
* key: spanId, value: consoleAppender
56+
* each logger have their own consoleAppender if had configured
57+
**/
58+
private ConcurrentMap<String, ConsoleAppender<ILoggingEvent>> consoleAppenders = new ConcurrentHashMap<>();
5359

5460
public LogbackLoggerSpaceFactory(SpaceId spaceId, LoggerContext loggerContext,
5561
Properties properties, URL confFile, String source) {
5662
super(source);
5763
this.spaceId = spaceId;
5864
this.loggerContext = loggerContext;
5965
this.properties = properties;
60-
consoleAppender = createConsoleAppender(loggerContext, properties);
61-
consoleLevel = getConsoleLevel(spaceId.getSpaceName(), properties);
6266

6367
for (Map.Entry<Object, Object> entry : properties.entrySet()) {
6468
loggerContext.putProperty((String) entry.getKey(), (String) entry.getValue());
@@ -79,33 +83,39 @@ public LogbackLoggerSpaceFactory(SpaceId spaceId, LoggerContext loggerContext,
7983
@Override
8084
public FilterReply decide(Marker marker, ch.qos.logback.classic.Logger logger,
8185
Level level, String format, Object[] params, Throwable t) {
86+
ConsoleAppender<ILoggingEvent> consoleAppender = getOrCreateConsoleAppender(logger.getName());
8287
if (CommonLoggingConfigurations.shouldAttachConsoleAppender(logger.getName())
8388
&& !logger.isAttached(consoleAppender)) {
8489
logger.addAppender(consoleAppender);
85-
// effective level won't be null
86-
if (logger.getEffectiveLevel().isGreaterOrEqual(consoleLevel)) {
87-
logger.setLevel(consoleLevel);
88-
}
8990
}
9091
return FilterReply.NEUTRAL;
9192
}
9293
});
9394
}
9495
}
9596

96-
private ConsoleAppender<ILoggingEvent> createConsoleAppender(LoggerContext loggerContext, Properties properties) {
97-
ConsoleAppender<ILoggingEvent> appender = new ConsoleAppender<>();
98-
PatternLayoutEncoder encoder = new PatternLayoutEncoder();
99-
String logPattern = properties.getProperty(
100-
Constants.SOFA_MIDDLEWARE_LOG_CONSOLE_LOGBACK_PATTERN,
101-
Constants.SOFA_MIDDLEWARE_LOG_CONSOLE_LOGBACK_PATTERN_DEFAULT);
102-
encoder.setPattern(OptionHelper.substVars(logPattern, loggerContext));
103-
encoder.setContext(loggerContext);
104-
encoder.start();
105-
appender.setEncoder(encoder);
106-
appender.setName("CONSOLE");
107-
appender.start();
108-
return appender;
97+
private ConsoleAppender<ILoggingEvent> getOrCreateConsoleAppender(String loggerName) {
98+
return consoleAppenders.computeIfAbsent(loggerName, k -> {
99+
ConsoleAppender<ILoggingEvent> appender = new ConsoleAppender<>();
100+
PatternLayoutEncoder encoder = new PatternLayoutEncoder();
101+
String logPattern = properties.getProperty(
102+
Constants.SOFA_MIDDLEWARE_LOG_CONSOLE_LOGBACK_PATTERN,
103+
Constants.SOFA_MIDDLEWARE_LOG_CONSOLE_LOGBACK_PATTERN_DEFAULT);
104+
// create appender filter
105+
Level consoleLevel = getConsoleLevel(spaceId.getSpaceName());
106+
ThresholdFilter filter = new ThresholdFilter();
107+
filter.setLevel(consoleLevel.toString());
108+
109+
encoder.setPattern(OptionHelper.substVars(logPattern, loggerContext));
110+
encoder.setContext(loggerContext);
111+
encoder.start();
112+
appender.setEncoder(encoder);
113+
appender.setName(CONSOLE);
114+
filter.start();
115+
appender.addFilter(filter);
116+
appender.start();
117+
return appender;
118+
});
109119
}
110120

111121
public SpaceId getSpaceId() {
@@ -116,7 +126,7 @@ public Properties getProperties() {
116126
return properties;
117127
}
118128

119-
private Level getConsoleLevel(String spaceId, Properties properties) {
129+
private Level getConsoleLevel(String spaceId) {
120130
String defaultLevel = properties.getProperty(
121131
Constants.SOFA_MIDDLEWARE_ALL_LOG_CONSOLE_LEVEL, "INFO");
122132
String level = properties.getProperty(
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
package com.alipay.sofa.common.log;
18+
19+
import com.alipay.sofa.common.log.env.LogEnvUtils;
20+
import com.alipay.sofa.common.log.factory.AbstractLoggerSpaceFactory;
21+
import com.alipay.sofa.common.log.factory.LoggerSpaceFactory4Log4j2Builder;
22+
import com.alipay.sofa.common.space.SpaceId;
23+
import org.junit.Assert;
24+
import org.junit.Test;
25+
import org.slf4j.Logger;
26+
27+
import java.io.ByteArrayOutputStream;
28+
import java.io.PrintStream;
29+
30+
public class Log4j2ConsoleLoggingTest {
31+
@Test
32+
public void testConsoleLogLevel() throws Exception {
33+
String loggerName = "com.foo.bar.console";
34+
String spaceName = "sofa.console";
35+
ByteArrayOutputStream outContent = new ByteArrayOutputStream();
36+
System.setOut(new PrintStream(outContent));
37+
38+
// Flip the global console logging switch on and set the level to WARN
39+
LogSpace spaceInfo = new LogSpace()
40+
.setProperty(Constants.SOFA_MIDDLEWARE_ALL_LOG_CONSOLE_SWITCH, "true")
41+
.setProperty(Constants.SOFA_MIDDLEWARE_ALL_LOG_CONSOLE_LEVEL, "WARN")
42+
.putAll(LogEnvUtils.processGlobalSystemLogProperties());
43+
44+
LoggerSpaceFactory4Log4j2Builder loggerSpaceFactory4Log4j2Builder = new LoggerSpaceFactory4Log4j2Builder(
45+
new SpaceId(spaceName), spaceInfo);
46+
AbstractLoggerSpaceFactory loggerSpaceFactory = loggerSpaceFactory4Log4j2Builder.build(
47+
spaceName, this.getClass().getClassLoader());
48+
CommonLoggingConfigurations.appendConsoleLoggerName(loggerName);
49+
50+
Logger logger = loggerSpaceFactory.getLogger(loggerName);
51+
Assert.assertTrue(logger.isErrorEnabled());
52+
Assert.assertTrue(logger.isWarnEnabled());
53+
Assert.assertTrue(logger.isInfoEnabled());
54+
Assert.assertFalse(logger.isDebugEnabled());
55+
Assert.assertFalse(logger.isTraceEnabled());
56+
57+
String traceLog = "test trace info";
58+
String debugLog = "test debug info";
59+
String infoLog = "test info info";
60+
String warnLog = "test warn info";
61+
String errorLog = "test error info";
62+
logger.trace(traceLog);
63+
logger.debug(debugLog);
64+
logger.info(infoLog);
65+
logger.warn(warnLog);
66+
logger.error(errorLog);
67+
68+
String logString = outContent.toString();
69+
Assert.assertTrue(logString.contains(warnLog));
70+
Assert.assertTrue(logString.contains(errorLog));
71+
Assert.assertFalse(logString.contains(traceLog));
72+
Assert.assertFalse(logString.contains(debugLog));
73+
Assert.assertFalse(logString.contains(infoLog));
74+
}
75+
}

0 commit comments

Comments
 (0)