SLF4J를 사용하기 위해 Hibernate 4에서 로깅을 구성하는 방법


114

Hibernate 3.x 사용 로깅을 위해. Hibernate 4.x 사용. 로깅을 위해 Hibernate 4와 SLF4J를 사용하는 독립형 애플리케이션을 작성 중입니다.

SLF4J에 로그인하도록 Hibernate를 어떻게 구성 할 수 있습니까?

가능하지 않다면 어떻게 Hibernate의 로깅을 구성 할 수 있습니까?

로깅에 대한 Hibernate 4.1 매뉴얼 섹션 은 다음과 같은 경고로 시작됩니다.

완전히 구식입니다. Hibernate는 4.0부터 JBoss 로깅을 사용합니다. 이 내용은 개발자 가이드로 마이그레이션 할 때 문서화됩니다.

... SLF4J에 대해 계속 이야기하기 때문에 쓸모가 없습니다. 어느 시작 안내서개발자 가이드 모두에서 로깅에 대한 이야기. 마이그레이션 가이드 도 마찬가지 입니다.

jboss-logging 자체에 대한 문서를 찾았지만 전혀 찾을 수 없었습니다. GitHub의 페이지는 침묵 하고, 보스의 사회 프로젝트 페이지 도 목록 JBoss의 로깅을하지 않습니다. 프로젝트의 버그 추적기에 문서 제공과 관련된 문제가 있는지 궁금 했지만 그렇지 않습니다.

좋은 소식은 JBoss AS7과 같은 애플리케이션 서버 내에서 Hibernate 4를 사용할 때 로깅이 대부분 처리된다는 것입니다. 그러나 독립 실행 형 응용 프로그램에서 어떻게 구성 할 수 있습니까?


13
로깅이 최대 절전 모드 문서를 강조하기위한 하나의 유효 기간이 있습니다
mhnagaoka

시스템 속성 org.jboss.logging.provide = slf4j를 설정할 수 있습니다. 자세한 내용은 docs.jboss.org/hibernate/orm/4.3/topical/html/logging/… 링크를 방문하십시오. 최대 절전 버전 3 이상인 경우
Abhishek Ranjan

답변:


60

https://github.com/jboss-logging/jboss-logging/blob/master/src/main/java/org/jboss/logging/LoggerProviders.java를 찾습니다 .

static final String LOGGING_PROVIDER_KEY = "org.jboss.logging.provider";

private static LoggerProvider findProvider() {
    // Since the impl classes refer to the back-end frameworks directly, if this classloader can't find the target
    // log classes, then it doesn't really matter if they're possibly available from the TCCL because we won't be
    // able to find it anyway
    final ClassLoader cl = LoggerProviders.class.getClassLoader();
    try {
        // Check the system property
        final String loggerProvider = AccessController.doPrivileged(new PrivilegedAction<String>() {
            public String run() {
                return System.getProperty(LOGGING_PROVIDER_KEY);
            }
        });
        if (loggerProvider != null) {
            if ("jboss".equalsIgnoreCase(loggerProvider)) {
                return tryJBossLogManager(cl);
            } else if ("jdk".equalsIgnoreCase(loggerProvider)) {
                return tryJDK();
            } else if ("log4j".equalsIgnoreCase(loggerProvider)) {
                return tryLog4j(cl);
            } else if ("slf4j".equalsIgnoreCase(loggerProvider)) {
                return trySlf4j();
            }
        }
    } catch (Throwable t) {
    }
    try {
        return tryJBossLogManager(cl);
    } catch (Throwable t) {
        // nope...
    }
    try {
        return tryLog4j(cl);
    } catch (Throwable t) {
        // nope...
    }
    try {
        // only use slf4j if Logback is in use
        Class.forName("ch.qos.logback.classic.Logger", false, cl);
        return trySlf4j();
    } catch (Throwable t) {
        // nope...
    }
    return tryJDK();
}

그래서 사용할 수있는 값은 org.jboss.logging.provider다음과 같습니다 jboss, jdk, log4j, slf4j.

설정하지 않으면 org.jboss.logging.providerjboss, log4j, slf4j (로그 백이 사용 된 경우에만)를 시도하고 jdk로 폴백합니다.

나는 다음 slf4j과 함께 사용 합니다 logback-classic.

    <dependency>
        <groupId>ch.qos.logback</groupId>
        <artifactId>logback-classic</artifactId>
        <version>1.0.13</version>
        <scope>${logging.scope}</scope>
    </dependency>

그리고 모두 잘 작동합니다!

업데이트 일부 사용자는 매우 주요 App.java에서 사용합니다.

static { //runs when the main class is loaded.
    System.setProperty("org.jboss.logging.provider", "slf4j");
}

그러나 컨테이너 기반 솔루션의 경우 이것은 작동하지 않습니다.

업데이트 2 Log4j를 SLF4J로 관리한다고 생각하는 사람들 jboss-logging은 정확히 그렇지 않습니다. jboss-loggingSLF4J없이 Log4j를 직접 사용합니다!


1
어디에 설정 org.jboss.logging.provider할까요?
Suzan Cioc 2014

1
@SuzanCioc System.getProperty(LOGGING_PROVIDER_KEY);당신 에 따라 시스템 속성을 설정해야합니다. java -D...=...컨테이너에 대한 문서를 통해 또는 확인하십시오.
gavenkoa nov.

1
slf4j를 통해 log4j를 사용할 수 없다는 두 번째 업데이트가 도움이되었습니다. org.jboss.logging.provider를 slf4j로 설정하면 log4j의 지원이 시작될 것이라고 생각했습니다. 그래도 그렇지 않았습니다. 작동하려면 log4j로 직접 설정해야했습니다. 이상한. 이 구성의 옵션으로 slf4j의 요점은 무엇입니까?
Travis Spencer

27

백엔드가 시스템 속성을 사용해야하기 때문에 SLF4J가 Logback없이 JBoss 로깅과 함께 작동하도록하려면 org.jboss.logging.provider=slf4j. log4j-over-slf4jLogback이나 log4j가 클래스 경로에 실제로 존재하지 않으면 로깅이 JDK로 폴백되기 때문에이 경우 전술이 작동하지 않는 것 같습니다.

이것은 약간의 성가신 일이며 자동 감지가 작동하려면 클래스 로더에 최소한 ch.qos.logback.classic.Loggerlogback-classic 또는 org.apache.log4j.Hierarchylog4j에서 JDK 로깅으로 폴백하지 않도록 JBoss 로깅을 속이기 위해 포함되어 있음을 알 수 있습니다 .

마법은 다음과 같이 해석됩니다. org.jboss.logging.LoggerProviders

업데이트 : 서비스 로더 지원이 추가되어 META-INF/services/org.jboss.logging.LoggerProvider( org.jboss.logging.Slf4jLoggerProvider값으로) 선언하여 자동 감지 문제를 피할 수 있습니다 . log4j2 지원도 추가 된 것 같습니다.


1
이 시스템 속성은 어디에서 설정합니까?
jhegedus

설정에 따라 다르지만 일반적으로 명령 줄 스위치 -Dorg.jboss.logging.provider=slf4j로 충분합니다. LoggingProviders.java 는 현재 허용되는 값과 클래스 경로에 표시 될 것으로 예상되는 값에 대한 더 나은 통찰력을 제공합니다.
Tuomas Kiviaho 2014 년

2
클래스 Slf4jLoggerProvider가 아니기 때문에 서비스 로더 접근 방식이 작동하지 않는다고 생각 public합니까?
holmis83

웹 로직 WAR의 org.jboss.logging.provider를 소스 코드로 설정해야하지만, 모든 정적 클래스 초기화 프로그램은 LoggingProviders 이후에 호출됩니다!
Antonio Petricca 2019

12

Leif의 Hypoport 게시물 에서 영감을 받아 Hibernate 4를 slf4j로 "구부린"방법입니다.

Maven을 사용한다고 가정 해 보겠습니다.

  • org.slf4j:log4j-over-slf4j종속성으로 추가 하십시오.pom.xml
  • 명령을 사용하여 사용 중인 아티팩트가 종속 되지 않았mvn dependency:tree 는지 확인 합니다 (정확히 말하자면 아티팩트에 컴파일 범위 종속성 또는 런타임 범위 종속성이 없음 ).slf4j:slf4jslf4j:slf4j

배경 : Hibernate 4.x는 아티팩트에 의존합니다 org.jboss.logging:jboss-logging. 일시적으로이 아티팩트에는 아티팩트에 대해 제공된 범위 종속성이 있습니다 slf4j:slf4j.

이제 org.slf4j:log4j-over-slf4j아티팩트를 추가 org.slf4j:log4j-over-slf4j했으므로 아티팩트를 모방합니다 slf4j:slf4j. 따라서 JBoss Logging기록하는 모든 것은 이제 실제로 slf4j를 통해 이동합니다.

Logback 을 로깅 백엔드로 사용하고 있다고 가정 해 보겠습니다 . 다음은 샘플입니다.pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>

    ....
    <properties>
        ....
        <slf4j-api-version>1.7.2</slf4j-api-version>
        <log4j-over-slf4j-version>1.7.2</log4j-over-slf4j-version>
        <jcl-over-slf4j-version>1.7.2</jcl-over-slf4j-version> <!-- no problem to have yet another slf4j bridge -->
        <logback-core-version>1.0.7</logback-core-version>
        <logback-classic-version>1.0.7</logback-classic-version>
        <hibernate-entitymanager-version>4.1.7.Final</hibernate-entitymanager-version> <!-- our logging problem child -->
    </properties>

    <dependencies>
            <!-- begin: logging-related artifacts .... -->
            <dependency>
                <groupId>org.slf4j</groupId>
                <artifactId>slf4j-api</artifactId>
                <version>${slf4j-api-version}</version>
            </dependency>
            <dependency>
                <groupId>org.slf4j</groupId>
                <artifactId>jcl-over-slf4j</artifactId>
                <version>${jcl-over-slf4j-version}</version>
            </dependency>
            <dependency>
                <groupId>org.slf4j</groupId>
                <artifactId>log4j-over-slf4j</artifactId>
                <version>${log4j-over-slf4j-version}</version>
            </dependency>   
            <dependency>
                <groupId>ch.qos.logback</groupId>
                <artifactId>logback-core</artifactId>
                <version>${logback-core-version}</version>
            </dependency>
            <dependency>
                <groupId>ch.qos.logback</groupId>
                <artifactId>logback-classic</artifactId>
                <version>${logback-classic-version}</version>
            </dependency>
            <!-- end: logging-related artifacts .... -->

            <!-- begin: some artifact with direct dependency on log4j:log4j ....  -->
            <dependency>
            <groupId>org.foo</groupId>
                <artifactId>some-artifact-with-compile-or-runtime-scope-dependency-on-log4j:log4j</artifactId>
                <version>${bla}</version>
                <exclusions>
                    <exclusion>
                        <groupId>log4j</groupId>
                        <artifactId>log4j</artifactId>
                    </exclusion>
                </exclusions>   
            </dependency>
            <!-- begin: some artifact with direct dependency on log4j:log4j ....  -->

            <!-- begin: a hibernate 4.x problem child........... -->
            <dependency>
                <groupId>org.hibernate</groupId>
                <artifactId>hibernate-entitymanager</artifactId>
                <version>${hibernate-entitymanager-version}</version>
            </dependencies>
            <!-- end: a hibernate 4.x problem child........... -->
    ....
</project>

클래스 경로 logback.xml에서 src/main/java다음 과 같은 .

<!-- begin: logback.xml -->
<configuration>
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
    <encoder>
        <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
    </encoder>
</appender> 

<logger name="org.hibernate" level="debug"/>

<root level="info">
    <appender-ref ref="console"/>
</root>

</configuration>
<!-- end: logback.xml -->

logback.xmlJetty Maven 플러그인과 같은 일부 구성 요소는 적절한 로깅을 위해 JVM 시작 시간에 액세스 할 수 있습니다 . 이 경우 logback.configurationFile=./path/to/logback.xml명령에 Java 시스템 을 추가 하십시오 (예 :) mvn -Dlogback.configurationFile=./target/classes/logback.xml jetty:run.

여전히 "raw"콘솔 stdout Hibernate 출력 (예 :)을 얻는 경우 Hibernate: select ...스택 오버플로 질문 " Turn off hibernate logging to console "이 적용될 수 있습니다.


1
다른 라이브러리가 log4j를 포함하지 않는지 확인하십시오. 그렇지 않으면 작동하지 않습니다. 예 : activemq-all.jar에는 log4j가 포함됩니다. 힌트 : IDE를 열고 코드에서 log4j를 쉽게 찾으십시오.
디미트리 Dewaele

JBoss Hibernate4와 (너무) 오래된 서버에서이 문제가 발생했습니다. 이 게시물은 application.properties의 한 줄을 포함하여 나를 위해 트릭을했습니다. 그래서 TNX !!! 그리고 내 속성의 마지막 줄은 여기에 또 다른 답변으로 작성되었습니다.org.jboss.logging.provider=slf4j
Jeroen van Dijk-Jun

8

먼저 SLF4J가 로깅 라이브러리 권한이 아니라 로깅 래퍼라는 것을 알게됩니다. 자체적으로 아무것도 기록하지 않고 단순히 "백엔드"에 위임합니다.

jboss-logging을 "구성"하려면 클래스 경로에 사용할 로그 프레임 워크를 추가하면됩니다 (jboss-logging과 함께). 나머지는 jboss-logging이 알아냅니다.

JBoss 로깅 구성에 대한 Hibernate 중심 가이드를 만들었습니다. http://docs.jboss.org/hibernate/orm/4.3/topical/html/logging/Logging.html


2
나는 SLF4J가 외관이라는 것을 알고 있습니다. Hibernate 로깅을 SLF4J로 보내는 것은 내가 원하는 나머지 애플리케이션을 위해 선택한 백엔드에서 종료된다는 것을 의미합니다.
Tom Anderson

10
그래서 구성에 대해 말하는 것은 구성이 없다는 것입니다 (좋습니다!).하지만 jboss-logging은 어떻게 든 백엔드를 감지하고 선택합니까? 아, 이제 코드를 실제로 살펴 보겠습니다 . 정확히 무슨 일일어나는지 알았습니다 . 특히 jboss-logging은 JBoss LogManager, log4j, SLF4J를 통한 Logback 및 JDK 로깅을 순서대로 시도합니다. 그러나 이것은 시스템 속성 으로 재정의 될 있습니다 org.jboss.logging.provider.
Tom Anderson

2
우리 중 많은 사람들이 commons-logging이 당신을 위해 일을 알아내는 것에 지 쳤기 때문에 jboss-logging이 어떻게 작동하는지 정확히 아는 것이 예상치 못한 일이 발생할 때 현실 세계에서 그것을 지원할 수있는 데 중요합니다.
ams aug

1
그래서 다음하지 당신이 정말로보고 싶어 그게 무엇을하면 어떻게 정확하게 사실 쇼에서 위의 링크를 ...
스티브 Ebersole

3

독립 실행 형 앱에서 Hibernate Core 4.1.7.Final과 Spring 3.1.2.RELEASE를 사용하고 있습니다. Log4j 1.2.17을 내 종속성에 추가했는데 JBoss Logging이 가능한 경우 log4j에 직접 기록하고 Spring은 Commons Logging을 사용하고 마녀도 사용 가능한 경우 Log4j를 사용하므로 모든 로깅은 Log4J를 통해 구성 할 수 있습니다.

관련 종속성 목록은 다음과 같습니다.

<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.17</version>
</dependency>
<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-core</artifactId>
    <version>4.1.7.Final</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>3.1.2.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-orm</artifactId>
    <version>3.1.2.RELEASE</version>
</dependency>

3

그래서 내 프로젝트에서 작동하도록했습니다. 최대 절전 모드 4, slf4j, 로그 백. 내 프로젝트는 gradle이지만 maven과 동일해야합니다.

기본적으로 Abdull이 옳습니다. 그가 옳지 않은 곳은 의존성에서 slf4j를 제거 할 필요가 없다는 것입니다.

  1. 컴파일 범위에 포함 :

    org.slf4j : slf4j-api

    org.slf4j : log4j-over-slf4j

    예 : logback (ch.qos.logback : logback-classic, ch.qos.logback : logback-core : 1.0.12)

  2. 종속성에서 log4j libs를 완전히 제외

결과 : slf4j를 통해 로그를 최대 절전 모드로 전환합니다. 물론 로그 백과는 다른 로그 구현을 사용할 수 있어야합니다.

log4j가 없는지 확인하려면 클래스 경로 또는 web-inf / lib에서 libs에서 war 파일을 확인하십시오.

물론 logback.xml에 로거를 설정했습니다. 예 :

<logger name="org.hibernate.SQL" level="TRACE"/>


이 정확한 문제가있었습니다. log4j는 다른 라이브러리에서 전이 종속성으로 가져 왔습니다. 이를 제외하고 최대 절전 모드 로깅은 logback 및 slf4j log4j 브리지를 사용하여 예상대로 작동하기 시작했습니다
Paul Zepernick

3

Hibernate 4.3에는 제어 방법에 대한 몇 가지 문서 가 있습니다 org.jboss.logging.

  • 로깅 공급자에 대한 클래스 경로를 검색합니다 . log4j를 검색 한 후 slf4j를 검색합니다. 따라서 이론적으로 클래스 경로 (WAR)에 log4j가 포함되지 않고 slf4j API가 포함되어 있는지 확인하고 백엔드가 작동해야합니다.

  • 마지막 수단으로 org.jboss.logging.provider시스템 속성을로 설정할 수 있습니다 slf4j.


문서의 org.jboss.logging주장에도 불구하고, log4j가없고 SLF4J가 있음에도 불구하고 log4j를 사용하려고 고집하여 Tomcat 로그 파일 ( /var/log/tomcat/catalina.out) 에 다음 메시지가 표시되었습니다 .

 log4j:WARN No appenders could be found for logger (org.jboss.logging).
 log4j:WARN Please initialize the log4j system properly.
 log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.

나는 dasAnderl ausMinga 의 답변 제안에 따라 log4j-over-slf4j다리를 포함해야했습니다 .


2

나는 maven을 사용하고 다음 종속성을 추가했습니다.

<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-log4j12</artifactId>
    <version>1.6.6</version>
</dependency>

그런 다음 다음 위치에 log4j.properties파일을 만들었습니다 /src/main/resources.

# direct log messages to stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
# set log levels
log4j.rootLogger=warn

이것은 당신의 .jar. 매력처럼 작동합니다 ...


3
이것은 log4j의 사용을 구성합니다. OP는 log4j를 사용하고 싶지 않습니다. 그들은 slf4j를 사용하려고합니다.
Raedwald 2014

1

weblogic 12c 및 log4j에서 최대 절전 모드 4 로깅 작업을 수행하는 데 문제가 있습니다. 해결책은 weblogic-application.xml에 다음을 넣는 것입니다.

<prefer-application-packages>
    <package-name>org.apache.log4j.*</package-name>
    <package-name>org.jboss.logging.*</package-name>
</prefer-application-packages>

0

내가 가진 동일한 문제에 직면 할 수있는 사람에게. 여기에 설명 된 다른 모든 솔루션을 시도했지만 여전히 slf4j와 함께 작동하는 최대 절전 로깅이 표시되지 않는 경우, 그의 폴더 라이브러리에 jboss-logging.jar이있는 컨테이너를 사용하고 있기 때문일 수 있습니다. 즉, 영향을 줄 구성을 설정하기 전에 미리로드됩니다. weblogic에서이 문제를 방지하려면 ear / META-INF의 weblogic-application.xml 파일에서 애플리케이션에서로드 된 라이브러리를 선호하도록 지정할 수 있습니다. 다른 서버 컨테이너에도 유사한 메커니즘이 있어야합니다. 제 경우에는 다음을 추가해야했습니다.

<?xml version="1.0" encoding="UTF-8"?>
<wls:weblogic-application xmlns:wls="http://xmlns.oracle.com/weblogic/weblogic-application" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/javaee_5.xsd http://xmlns.oracle.com/weblogic/weblogic-application http://xmlns.oracle.com/weblogic/weblogic-application/1.5/weblogic-application.xsd">
   <wls:prefer-application-packages>    
       <!-- logging -->
       <wls:package-name>org.slf4j.*</wls:package-name>
       <wls:package-name>org.jboss.logging.*</wls:package-name>             
   </wls:prefer-application-packages>
   <wls:prefer-application-resources>
        <wls:resource-name>org/slf4j/impl/StaticLoggerBinder.class</wls:resource-name>
    </wls:prefer-application-resources>     
</wls:weblogic-application>

-2

당신은 이것을 시도 했습니까 :

-Log4J의 경우 slf4j-log4j12.jar. 자세한 내용은 SLF4J 문서를 참조하십시오. Log4j를 사용하려면 클래스 경로에 log4j.properties 파일도 배치해야합니다. 예제 속성 파일은 src / 디렉토리에 Hibernate와 함께 배포됩니다.

이러한 jar 및 속성 또는 log4j xml을 클래스 경로에 추가하십시오.


4
그것은 Hibernate 3.x 문서에서 인용 한 것입니다. SLF4J를 사용하지 않는 Hibernate 4.x에서도 여전히 작동 할 것이라고 생각하십니까?
Tom Anderson

지금까지 내가 기억하는 log4j에 충분하다
Avihai Marchiano
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.