로깅 프레임 워크와 로깅 파사드 프레임 워크를보고 싶습니다.
시간이 지남에 따라 많은 사람들이 공통 API에 의존하도록 진화했거나 외관 프레임 워크를 통해 사용을 추상화하고 교체 할 수 있도록 여러 로깅 프레임 워크가 종종 중복 기능을 갖습니다. 필요한 경우.
프레임 워크
일부 로깅 프레임 워크
일부 로깅 파사드
용법
기본 예
이러한 프레임 워크의 대부분은 당신이 (여기에 사용하는 형태의 무언가를 작성할 수 있습니다 것입니다 slf4j-api
과 logback-core
) :
package chapters.introduction;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
// copied from: http://www.slf4j.org/manual.html
public class HelloWorld {
public static void main(String[] args) {
final Logger logger = LoggerFactory.getLogger(HelloWorld.class);
logger.debug("Hello world, I'm a DEBUG level message");
logger.info("Hello world, I'm an INFO level message");
logger.warn("Hello world, I'm a WARNING level message");
logger.error("Hello world, I'm an ERROR level message");
}
}
현재 클래스를 사용하여 전용 로거를 작성하면 SLF4J / LogBack이 출력을 형식화하고 로깅 메시지의 출처를 표시 할 수 있습니다.
SLF4J 매뉴얼 에서 언급했듯이 클래스의 일반적인 사용 패턴은 일반적으로 다음과 같습니다.
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class MyClass {
final Logger logger = LoggerFactory.getLogger(MyCLASS.class);
public void doSomething() {
// some code here
logger.debug("this is useful");
if (isSomeConditionTrue()) {
logger.info("I entered by conditional block!");
}
}
}
그러나 실제로 로거를 다음 형식으로 선언하는 것이 훨씬 일반적입니다.
private static final Logger LOGGER = LoggerFactory.getLogger(MyClass.class);
이를 통해 정적 메소드 내에서 로거를 사용할 수 있으며 클래스의 모든 인스턴스간에 공유됩니다. 이것은 당신이 선호하는 형태 일 것입니다. 그러나 Brendan Long이 언급 한대로, 그 의미 를 이해하고 적절하게 결정하기 를 원합니다 (이 관용구 다음의 모든 로깅 프레임 워크에 적용됨).
예를 들어 문자열 매개 변수를 사용하여 명명 된 로거를 작성하는 등 로거를 인스턴스화하는 다른 방법이 있습니다.
Logger logger = LoggerFactory.getLogger("MyModuleName");
디버그 레벨
디버그 수준은 프레임 워크마다 다르지만 공통적 인 수준은 중요합니다 (중요도 순, 악순환, 나쁜 수준, 매우 일반적이거나 매우 희귀 한 수준).
TRACE
매우 자세한 정보. 로그에만 작성해야합니다. 검사 점에서 프로그램 흐름을 추적하는 데만 사용됩니다.
DEBUG
자세한 정보. 로그에만 작성해야합니다.
INFO
주목할만한 런타임 이벤트. 콘솔에 즉시 표시되어야하므로 조금만 사용하십시오.
WARNING
런타임 이상과 복구 가능한 오류.
ERROR
기타 런타임 오류 또는 예기치 않은 조건
FATAL
조기 종료를 유발하는 심각한 오류.
블록과 가드
이제 많은 디버그 문을 작성하려는 코드 섹션이 있다고 가정 해보십시오. 이는 로깅 자체의 영향과 로깅 방법으로 전달할 수있는 매개 변수 생성으로 인해 성능에 빠르게 영향을 줄 수 있습니다.
이런 종류의 문제를 피하기 위해 종종 다음과 같은 형식으로 무언가를 작성하려고합니다.
if (LOGGER.isDebugEnabled()) {
// lots of debug logging here, or even code that
// is only used in a debugging context.
LOGGER.debug(" result: " + heavyComputation());
}
메시지가 출력되지 않을 수 있지만 (예를 들어, 로거가 현재 INFO
레벨 이상의 것만 인쇄하도록 구성된 경우) 디버그 명령문 블록 전에이 가드를 사용하지 않은 경우 heavyComputation()
메소드가 여전히 실행 된 것입니다 .
구성
구성은 로깅 프레임 워크에 따라 다르지만 대부분 동일한 기술을 제공합니다.
- 프로그래밍 방식 구성 (런타임에서 API를 통해- 런타임 변경 허용 )
- 정적 선언적 구성 (시작시 일반적으로 XML 또는 특성 파일을 통해- 처음에 필요할 수 있음 )
또한 대부분 동일한 기능을 제공합니다.
- 출력 메시지 형식 (타임 스탬프, 마커 등) 구성
- 출력 레벨 구성
- 세분화 된 필터 구성 (예 : 패키지 또는 클래스 포함 / 제외)
- 로깅 할 위치 (콘솔, 파일, 웹 서비스 ...) 및 이전 로그 (예 : 자동 롤링 파일)로 수행 할 작업을 결정하기위한 어 펜더 구성.
다음은 logback.xml
파일을 사용하는 선언적 구성의 일반적인 예입니다 .
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<!-- encoders are assigned the type
ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<root level="debug">
<appender-ref ref="STDOUT" />
</root>
</configuration>
언급 한 바와 같이, 이것은 프레임 워크에 따라 다르며 다른 대안이있을 수도 있습니다 (예를 들어, LogBack은 Groovy 스크립트 사용을 허용합니다). XML 구성 형식은 구현마다 다를 수 있습니다.
더 많은 구성 예는 다음을 참조하십시오.
역사적인 재미
것을 제발 참고 하여 Log4j 버전에서 전환, 순간에 주요 업데이트를보고있다 1.x에서 에 2.X . 더 역사적인 재미 나 혼란을 모두보고 싶을 수 있으며 Log4J 를 선택 하면 2.x 버전을 선호합니다.
Mike Partridge가 언급했듯이 LogBack은 이전 Log4J 팀원이 작성했다는 점에 주목할 가치가 있습니다. Java Logging 프레임 워크의 단점을 해결하기 위해 작성되었습니다. 그리고 다가오는 주요 Log4J 2.x 버전 자체가 이제 LogBack에서 가져온 몇 가지 기능을 통합하고 있습니다.
추천
결론은, 가능한 한 많이 분리 된 상태로 유지하고, 몇 가지를 가지고 놀며, 자신에게 가장 적합한 것을 확인하십시오. 결국 그것은 단지 로깅 프레임 워크 입니다. 사용의 용이성과 개인 취향을 제외하고 매우 구체적인 이유가있는 경우를 제외하고는 이러한 방법 중 어느 것도 괜찮을 것이므로 그 위에 매달릴 필요가 없습니다. 대부분은 필요에 따라 확장 할 수도 있습니다.
여전히 오늘 조합을 선택해야한다면 LogBack + SLF4J로 갈 것입니다. 그러나 몇 년 후에 나에게 물었다면 Apache Commons Logging과 함께 Log4J를 추천 했으므로 종속성을 주시하고 함께 발전하십시오.