반응형
Spring을 사용하지 않은 프로젝트에서 log4j 를 설정하기 위해서는 다음의 경로에 log4j.properties 또는 log4j.xml 파일이 있어야 한다.
src/main/resources/log4j.properties
이 파일을 읽을 수 있는건 org.apache.log4j.LogManager 에서 가능한데, 나중에 로그레벨을 변경하는 것도 여기서 한다. 파일안을 보면 다음으로 구성되어 있다
/**
* Use the <code>LogManager</code> class to retreive {@link Logger}
* instances or to operate on the current {@link
* LoggerRepository}. When the <code>LogManager</code> class is loaded
* into memory the default initalzation procedure is inititated. The
* default intialization procedure</a> is described in the <a
* href="../../../../manual.html#defaultInit">short log4j manual</a>.
*
* @author Ceki Gülcü */
public class LogManager {
/**
* @deprecated This variable is for internal use only. It will
* become package protected in future versions.
* */
static public final String DEFAULT_CONFIGURATION_FILE = "log4j.properties";
static final String DEFAULT_XML_CONFIGURATION_FILE = "log4j.xml";
...
static {
// By default we use a DefaultRepositorySelector which always returns 'h'.
Hierarchy h = new Hierarchy(new RootLogger((Level) Level.DEBUG));
repositorySelector = new DefaultRepositorySelector(h);
/** Search for the properties file log4j.properties in the CLASSPATH. */
String override =OptionConverter.getSystemProperty(DEFAULT_INIT_OVERRIDE_KEY,
null);
// if there is no default init override, then get the resource
// specified by the user or the default config file.
if(override == null || "false".equalsIgnoreCase(override)) {
String configurationOptionStr = OptionConverter.getSystemProperty(
DEFAULT_CONFIGURATION_KEY,
null);
String configuratorClassName = OptionConverter.getSystemProperty(
CONFIGURATOR_CLASS_KEY,
null);
URL url = null;
// if the user has not specified the log4j.configuration
// property, we search first for the file "log4j.xml" and then
// "log4j.properties"
if(configurationOptionStr == null) {
url = Loader.getResource(DEFAULT_XML_CONFIGURATION_FILE);
if(url == null) {
url = Loader.getResource(DEFAULT_CONFIGURATION_FILE);
}
} else {
try {
url = new URL(configurationOptionStr);
} catch (MalformedURLException ex) {
// so, resource is not a URL:
// attempt to get the resource from the class path
url = Loader.getResource(configurationOptionStr);
}
}
// If we have a non-null url, then delegate the rest of the
// configuration to the OptionConverter.selectAndConfigure
// method.
if(url != null) {
LogLog.debug("Using URL ["+url+"] for automatic log4j configuration.");
try {
OptionConverter.selectAndConfigure(url, configuratorClassName,
LogManager.getLoggerRepository());
} catch (NoClassDefFoundError e) {
LogLog.warn("Error during default initialization", e);
}
} else {
LogLog.debug("Could not find resource: ["+configurationOptionStr+"].");
}
} else {
LogLog.debug("Default initialization of overridden by " +
DEFAULT_INIT_OVERRIDE_KEY + "property.");
}
}
static 메서드에서 보면 해당경로에서 읽는 것을 확인할 수 있다. 때문에 어플리케이션이 시작되면 여기서 파일을 읽는다.
그럼 중간에 바꾸려면 어떻게 해야할까?
LogManager 에서 아래 2개를 변경해야 한다
1) RootLevel 변경
2) Package 기준 Level 변경
다음처럼 변경할 수 있다
String packageName = "com.deoklab.app";
Level level = Level.WARN;
LogManager.getRootLogger().setLevel(level);
LogManager.getLogger(packageName).setLevel(level);
packageName의 경우는 프로젝트의 Root 패키지 이름을 가져오면 된다. 참고로 같은 방식을 설정을 log4j.properties 에다가 할때에는 다음처럼 설정한다
log4j.rootLoger=debug # root 로그 설정
log4j.logger.com.deoklab.app=WARN # 패키지별 로그 설정
그럼 다음처럼 메서드를 만든 후에 변경됐는지 확인해보자
...
private void setLogLevel(String logLevel) {
Level level;
switch (logLevel.toUpperCase()) {
case "TRACE":
level = Level.TRACE;
break;
case "DEBUG":
level = Level.DEBUG;
break;
case "INFO":
level = Level.INFO;
break;
case "WARN":
level = Level.WARN;
break;
case "ERROR":
level = Level.ERROR;
break;
case "":
level = Level.INFO;
break;
default:
throw new WidetnsException("로그레벨이 잘못 설정되었습니다");
}
// 변경기준 패키지명(root package name)
String packageName = "com.deoklab.app";
// 변경 전 로그레벨
Level beforeLevelRoot = LogManager.getRootLogger().getLevel();
Level beforeLevelPackage = LogManager.getLogger(packageName).getLevel();
Logger loggerBefore = LoggerFactory.getLogger(packageName);
System.out.println("loggerBefore root level=" + beforeLevelRoot);
System.out.println("loggerBefore package debug=" + loggerBefore.isDebugEnabled());
System.out.println("loggerBefore package info=" + loggerBefore.isInfoEnabled());
System.out.println("loggerBefore package warn=" + loggerBefore.isWarnEnabled());
System.out.println("------------------------------------------");
// root level 변경
LogManager.getRootLogger().setLevel(level);
// 패키지 기준 하위 레벨 변경
LogManager.getLogger(packageName).setLevel(level);
Level LevelRootAfter = LogManager.getRootLogger().getLevel();
Logger loggerAfter = LoggerFactory.getLogger(packageName);
System.out.println("loggerAfter root level=" + LevelRootAfter);
System.out.println("loggerAfter package debug=" + loggerAfter.isDebugEnabled());
System.out.println("loggerAfter package info=" + loggerAfter.isInfoEnabled());
System.out.println("loggerAfter package warn=" + loggerAfter.isWarnEnabled());
// lombok의 @Slf4j를 사용하여 로그출력
log.info("log root level change {} => {}", beforeLevelRoot, level);
log.info("log package level change {} => {}", beforeLevelPackage, level);
}
...
로그 (WARN => INFO 로 변경)
loggerBefore root level=DEBUG
loggerBefore package debug=false
loggerBefore package info=false
loggerBefore package warn=true
------------------------------------------
loggerAfter root level=INFO
loggerAfter package debug=false
loggerAfter package info=true
loggerAfter package warn=true
log root level change DEBUG => INFO
log package level change WARN => INFO
잘 변경된 것을 확인할 수 있다.
내 경우 Lombok을 이용해서 @Slf4j를 사용하고 있는데 같이 적용된다.
끝.
반응형
'공부 > 프로그래밍' 카테고리의 다른 글
[react] window is not defined 에러 (apexchart) (0) | 2022.01.12 |
---|---|
[log4j] SLF4J: Class path contains multiple SLF4J bindings. 에러 (0) | 2022.01.05 |
[linux] ec2(aws) 에서 jenkins 설치 중 demonize 에러가 발생할경우 (0) | 2021.12.13 |
[log4j] 로그레벨 package 별로 설정하기 (0) | 2021.12.03 |
[JPA] 쿼리 로깅에 p6spy multi line 적용하기 (0) | 2021.11.05 |
댓글