Jak zapobiec wyświetlaniu przez funkcję logback własnego stanu na początku każdego dziennika?

145

Wygląda to na błąd niedbalstwa, ale nie mogę znaleźć przyczyny. Logowanie za pomocą logback / slf4j (najnowsza wersja slf4j-api-1.6.1, logback core / classic 0.9.24). Najprostsza konfiguracja dziennika do testowania to:

<configuration>
 <appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
  <layout class="ch.qos.logback.classic.PatternLayout">
   <!-- DONT USE THIS FORMATTER FOR LIVE LOGGING THE %L LINE NUMBER OUTPUTTER IS SLOW -->
   <pattern>%le %-1r [%c{1}:%L] %m%n</pattern>
  </layout>
 </appender>
 <root level="DEBUG">
  <appender-ref ref="stdout" />
 </root>
</configuration>

Każda konfiguracja dziennika rozpoczyna się od wewnętrznych linii stanu wylogowania:

11:21:27,825 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Could NOT find resource [logback.groovy]
11:21:27,826 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Found resource [logback-test.xml] at [file:.../logback-test.xml]
11:21:28,116 |-INFO in ch.qos.logback.classic.joran.action.ConfigurationAction - debug attribute not set
11:21:28,124 |-INFO in ch.qos.logback.core.joran.action.AppenderAction - About to instantiate appender of type [ch.qos.logback.core.ConsoleAppender]
11:21:28,129 |-INFO in ch.qos.logback.core.joran.action.AppenderAction - Naming appender as [stdout]
11:21:28,180 |-INFO in ch.qos.logback.core.joran.action.NestedComplexPropertyIA - Pushing component [layout] on top of the object stack.
11:21:28,206 |-WARN in ch.qos.logback.core.ConsoleAppender[stdout] - This appender no longer admits a layout as a sub-component, set an encoder instead.
11:21:28,206 |-WARN in ch.qos.logback.core.ConsoleAppender[stdout] - To ensure compatibility, wrapping your layout in LayoutWrappingEncoder.
11:21:28,206 |-WARN in ch.qos.logback.core.ConsoleAppender[stdout] - See also http://logback.qos.ch/codes.html#layoutInsteadOfEncoder for details
11:21:28,207 |-INFO in ch.qos.logback.classic.joran.action.RootLoggerAction - Setting level of ROOT logger to DEBUG
11:21:28,207 |-INFO in ch.qos.logback.core.joran.action.AppenderRefAction - Attaching appender named [stdout] to Logger[ROOT]

czyli zgodnie z dokumentacją format, którego logback używa domyślnie. Następnie kończy odczytywanie konfiguracji (która jest skonfigurowana do wyprowadzania innego formatu) i kontynuuje z prawidłowo sformatowanym wyjściem. Istnieje parametr konfiguracyjny, <configuration debug="false">który nie ma na to wpływu.

Czy ktoś wie, jak to wyłączyć?

Steve B.
źródło
Najnowsze wersje logowania są znacznie szybsze w obliczaniu% L.
Thorbjørn Ravn Andersen
@ ThorbjørnRavnAndersen dokumentacja mówi "L / linia: Generowanie informacji o numerze linii nie jest szczególnie szybkie. Dlatego należy unikać jego użycia, chyba że szybkość wykonywania nie jest problemem." FWIW: logback.qos.ch/manual/layouts.html (więc może jest szybszy, ale wciąż nie super szybki czy coś ...)
rogerdpack
@rogerdpack yes. Można go znaleźć, analizując ślad stosu wyjątku. To stało się szybsze.
Thorbjørn Ravn Andersen

Odpowiedzi:

249

Jeśli ustawisz debugatrybut configurationelementu na true, otrzymasz wszystkie informacje o statusie do konsoli. Jeśli to jest twój problem, po prostu ustaw go na fałsz lub usuń.

Jeśli masz jakiekolwiek problemy z konfiguracją poziomu WARNlub wyższego, otrzymasz również wszystkie informacje o statusie zarejestrowane na konsoli (w tym komunikaty poziomu INFO). Najlepszym rozwiązaniem tego problemu jest naprawienie problemu (w Twoim przypadku zastąpienie <layout>elementu <encoder>elementem).

Jeśli z jakiegoś powodu nie możesz rozwiązać problemu, ale chcesz usunąć informacje o stanie z konsoli, możesz zamiast tego skonfigurować alternatywę StatusListener. Użyj, NopStatusListeneraby całkowicie usunąć informacje o statusie:

<configuration>
  <statusListener class="ch.qos.logback.core.status.NopStatusListener" />
  <!-- etc -->
</configuration>
Rasmus Faber
źródło
9
To jest właściwa odpowiedź, powinna być bardziej głosowana, dziękuję. (logback 1.0.11)
Jakub Kulhan
3
To zadziałało. Nie byłem do końca pewien, czy INFOkomunikaty dziennika też znikną, ale w rzeczywistości tak. Wiem, że odpowiedź tak mówi, ale z jakiegoś powodu nie było to dla mnie jasne. Żeby było jasne: napraw problem z koderem / układem, a nie tylko znikną komunikaty ostrzegawcze, ale także komunikaty informacyjne, nawet jeśli nie są one związane z problemem.
Jason
3
Nie działał z atrybutem debug, ale działał bezbłędnie z detektorem stanu.
Ameba Spugnosa
Dzięki - potrzebny status słuchacza.
Ezekiel Victor
2
Ostrożnie stosując to podejście, wydaje się działać, ale ukrywa fakt, że masz błąd konfiguracji w swoim pliku. Prawdziwym problemem są logi WARN, te problemy powinny zostać naprawione w config, a następnie wszystkie logi inc. INFO odejdź.
teknopaul
45

Tak jak opisano w dokumentacji , jeśli podczas analizowania pliku konfiguracyjnego wystąpią ostrzeżenia lub błędy, logback automatycznie wydrukuje dane o stanie na konsoli.

Postępuj zgodnie z http://logback.qos.ch/codes.html#layoutInsteadOfEncoder, tj. Odsyłaczem wymienionym przez logback w komunikacie ostrzegawczym. Po wykonaniu opisanych tam czynności, czyli zastąpieniu elementu <layout> elementem <encoder>, logback przestanie wyświetlać komunikaty na konsoli.

Ceki
źródło
4
W pewnym sensie słusznie, chociaż wskazałeś mi właściwy kierunek. Zmieniłem na tę składnię kodera bez efektu, chociaż okazuje się, że usunięcie innego wiersza w pliku logback.xml, który powodował ostrzeżenie, załatwiło sprawę. Mylące jest to, że dane wyjściowe wydają się przedstawiać decyzje podjęte przed faktycznym przeanalizowaniem pliku dziennika (1> Nie można znaleźć zasobu [logback.groovy], 2> Znaleziono zasób [logback-test.xml]). Jest to dość mylące, jeśli chodzi o poprawkę w teście logback, aby ukryć komunikaty o stanie dla tego, co się dzieje, zanim zostanie przeanalizowany. Ale dzięki za wskazówkę.
Steve B.
5
Myślę, że Steve B. miał na myśli to, że jest sprzeczne z intuicją (lub przynajmniej niekonwencjonalne), że Logback powinien blokować wszystkie komunikaty o stanie, w tym (w szczególności) te, które poprzedzają ładowanie pliku konfiguracyjnego, chyba że napotka błąd później w konfiguracji. Gdy nie jesteś zaznajomiony z tą regułą i po raz pierwszy zobaczysz te komunikaty o stanie (które sugerują ostrzeżenie lub błąd konfiguracji), większość użytkowników spodziewałaby się, że po usunięciu błędu Logback nie będzie już drukował powiązanych komunikatów o błędach, ale nadal będzie drukował pozostałe komunikaty o stanie.
Derek Mahar,
6
FWIW, również uważam to za dość zagmatwane zachowanie. Wyrzucanie komunikatów na poziomie INFO całkiem nieźle ukrywa komunikaty ERROR, które mówią mi, co tak naprawdę muszę naprawić. Brak DTD lub jakiejkolwiek innej specyfikacji składni pliku konfiguracyjnego sprawił, że debugowanie było dość trudne, nawet gdy zauważyłem komunikat.
Tom Anderson
4
@Ceki: W końcu to rozgryzłem: Drugim sposobem na wywołanie tych wiadomości jest posiadanie debug="true"atrybutu w configurationelemencie logback.xml. Wspomnij o tym dla dobra innych osób, które wpadną w tę dziurę!
Carl Smotricz
6
Być może przed pierwszą instrukcją INFO powinno znajdować się `` Wykryto ostrzeżenie, wyświetlające wszystkie informacje o stanie z przeszłości. Aby zatrzymać ten komunikat, napraw ostrzeżenia / błędy ”
David Roussel
7

Odpowiedź Ceki jest poprawna:

(...) jeśli podczas analizowania pliku konfiguracyjnego wystąpią ostrzeżenia lub błędy, logback automatycznie wydrukuje dane stanu na konsoli.

Gdy dobrze to zrobisz, w pierwszych wierszach dziennika nie będzie już żadnych zanieczyszczeń.

Od marca 2015 r. W Logback 1.1.2 musisz używać <encoder>podkomponentu - <layout>jest teraz przestarzały i jeśli go użyjesz, pojawią się komunikaty o błędach. Nie możesz tego kontrolować, jest to domyślne zachowanie Logback .

Nazwy niektórych klas wewnętrznych również zostały zmienione, a nawet przykłady na ich stronach podręcznika są nieaktualne!

Oto fragment kodu ze strony pomocy dotyczącej kodu błędów , która zawiera poprawny sposób konfiguracji programu rejestrującego. To rozwiązało problem całkowicie w moim projekcie. http://logback.qos.ch/codes.html#layoutInsteadOfEncoder

<appender name="FILE" class="ch.qos.logback.core.FileAppender">
  <file>testFile.log</file>
  ...
  <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
    <pattern>%msg%n</pattern>
  </encoder>
</appender>
Cbaldan
źródło
4

Zrozumiałem, że Steve znalazł poprawkę, ale nie wspomniał o tym w wątku. Jeśli jakakolwiek inna osoba napotka ten sam problem, tutaj jest poprawka.

Zastąpić "<>" Układ elementów z "<koder> .. </ koder>"

Winowajcą jest: <layout class = "ch.qos.logback.classic.PatternLayout">

Intesar Mohammed
źródło
1
Jeśli chcesz całkowicie usunąć te wiadomości, użyj NopStatusListener zgodnie z opisem Rasmusa. Podejście z koderem a układem nie pomija komunikatów, takich jak na przykład „nie znaleziono logback.groovy”. Używam logback-classic 1.1.3 (marzec 2015)
Cristian Botiza
3

Sam zmagałem się z tym samym problemem, tj. Na początku zarejestrowano kilka linii, które nie były związane z moim kodem. Oto jak to naprawiłem.

<configuration debug="false">

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

<root level="error">
    <appender-ref ref="STDOUT" />
</root>

<logger name="fun.n.games" level="DEBUG" />

To działa z następującym wpisem w pom.xml

        <dependency>
        <groupId>ch.qos.logback</groupId>
        <artifactId>logback-classic</artifactId>
        <version>1.2.3</version>
    </dependency>
kaun jovi
źródło
2

Wydaje się, że jest to naprawione w wersji 0.9.29. Właśnie wykonałem kilka testów. Żadnych joranskich INFO już. Wydaje mi się, że to jest ustalenie zobowiązania.

Michael-O
źródło
2

Miałem ten sam problem, kiedy dodałem tę linię

        <!-- Stop output INFO at start -->
        <statusListener class="ch.qos.logback.core.status.NopStatusListener" />

w logbacku i udało się

Zineb Hachmaoui
źródło
To działa, jednak zapobiega również wysyłaniu komunikatów o błędach - w przypadku poważnego problemu z konfiguracją logowania zwrotnego nie są generowane żadne dane wyjściowe.
Honza
0

Próbowałem wszystkiego i nic mi nie pomogło. Mój problem był spowodowany wieloma plikami logback.xml w mojej ścieżce klas. Jest to częsty przypadek w projektach wielomodułowych. Gdy w ścieżce klas znajduje się tylko jeden plik logback.xml, nie ma niejednoznaczności i problem został rozwiązany.

Filip
źródło
jakie daje to wyjście?
rogerdpack
0

Używanie logback.groovy:statusListener(NopStatusListener) (w src/test/resources/logback.groovy) działa.

(Prawidłowy przypadek użycia to np. Praca z ANT w Eclipse, korzystanie z logowania logback, klas groovy i testów jednostkowych, w których testy jednostkowe przyjmują src/test/resources/logback.groovy, ale zobaczą również src/main/resources/logback.groovy(lub podobne), których nie można wykluczyć (jeśli mówi się, że ścieżka klas ANT używa ścieżki klas projektów).)

Andreas Dietrich
źródło
0

Wolę używać nasłuchiwania statusu, aby wyłączyć własne dzienniki logowania:

<configuration>
  <statusListener class="ch.qos.logback.core.status.NopStatusListener" />
  ...
</configuration>

Ale jak wspomniano, NopStatusListener zapobiega również wyświetlaniu ostrzeżeń i błędów. Możesz więc napisać własny odbiornik statusu ręcznie i zmienić poziom dziennika:

package com.your.package;

import ch.qos.logback.core.status.OnConsoleStatusListener;
import ch.qos.logback.core.status.Status;

import java.util.List;

public class PrintOnlyWarningLogbackStatusListener extends OnConsoleStatusListener {

    private static final int LOG_LEVEL = Status.WARN;

    @Override
    public void addStatusEvent(Status status) {
        if (status.getLevel() == LOG_LEVEL) {
            super.addStatusEvent(status);
        }
    }

    @Override
    public void start() {
        final List<Status> statuses = context.getStatusManager().getCopyOfStatusList();
        for (Status status : statuses) {
            if (status.getLevel() == LOG_LEVEL) {
                super.start();
            }
        }
    }

}    

Następnie użyj go w swoim pliku logback.xml:

<configuration>
  <statusListener class="com.your.package.PrintOnlyWarningLogbackStatusListener" />
  ...
</configuration>
Maksym Pecheniuk
źródło