Как перенаправить вывод журнала AWS sdk

Я продолжаю получать их на STDOUT, даже если я использую logback и настроил его. Я не могу извлечь AWS из консоли.

Jun 19, 2014 3:46:40 PM com.amazonaws.http.AmazonHttpClient executeHelper
INFO: Unable to execute HTTP request: The target server failed to respond
org.apache.http.NoHttpResponseException: The target server failed to respond
        at org.apache.http.impl.conn.DefaultHttpResponseParser.parseHead(DefaultHttpResponseParser.java:95)
        at org.apache.http.impl.conn.DefaultHttpResponseParser.parseHead(DefaultHttpResponseParser.java:62)
        at org.apache.http.impl.io.AbstractMessageParser.parse(AbstractMessageParser.java:254)
        at org.apache.http.impl.AbstractHttpClientConnection.receiveResponseHeader(AbstractHttpClientConnection.java:289)
        at org.apache.http.impl.conn.DefaultClientConnection.receiveResponseHeader(DefaultClientConnection.java:252)  
        at org.apache.http.impl.conn.ManagedClientConnectionImpl.receiveResponseHeader(ManagedClientConnectionImpl.java:191)   
        at org.apache.http.protocol.HttpRequestExecutor.doReceiveResponse(HttpRequestExecutor.java:300)
        at com.amazonaws.http.protocol.SdkHttpRequestExecutor.doReceiveResponse(SdkHttpRequestExecutor.java:66)
        at org.apache.http.protocol.HttpRequestExecutor.execute(HttpRequestExecutor.java:127)
        at org.apache.http.impl.client.DefaultRequestDirector.tryExecute(DefaultRequestDirector.java:713)
        at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:518)
        at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:906)
        at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:805)
        at com.amazonaws.http.AmazonHttpClient.executeHelper(AmazonHttpClient.java:402)
        at com.amazonaws.http.AmazonHttpClient.execute(AmazonHttpClient.java:245)
        at com.amazonaws.services.s3.AmazonS3Client.invoke(AmazonS3Client.java:3573)
        at com.amazonaws.services.s3.AmazonS3Client.getObjectMetadata(AmazonS3Client.java:990)
        at com.amazonaws.services.s3.AmazonS3Client.getObjectMetadata(AmazonS3Client.java:970)
        at com.here.prime.cdtfilter.S3MapStore$$anonfun$1.apply(S3MapStore.scala:49)
        at com.here.prime.cdtfilter.S3MapStore$$anonfun$1.apply(S3MapStore.scala:48)
        at com.here.prime.utils.Utils$.retry(Utils.scala:26)

Это моя конфигурация журнала:

<configuration debug="false" scan="true" scanPeriod="30 seconds">
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>

    <appender name="FILE" class="ch.qos.logback.core.FileAppender">
        <file>cdtxfilter.log</file>
        <append>true</append>
        <encoder>
            <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>

    <logger name="com.amazonaws.request" level="WARN">
    </logger>

    <root level="DEBUG">
        <!--<appender-ref ref="STDOUT" />-->
        <appender-ref ref="FILE" />
    </root>
</configuration>

Решение:

Принудительное ведение журнала через logback, а не commons-logging:

В build.sbt добавлено:

resolvers ++= Seq(
  "version99 Empty loggers" at "http://version99.qos.ch",
)

libraryDependencies ++= Seq(
  "org.slf4j" % "jcl-over-slf4j" % "1.7.7",
  "commons-logging" % "commons-logging" % "99-empty",
  "ch.qos.logback" % "logback-classic" % "1.0.13",
)

В logback.xml тонкая настройка уровня журнала для шумных классов внутри AWS SDK:

<configuration...
[..]
    <logger name="com.amazonaws" level="ERROR"/>
    <logger name="org.apache.http" level="INFO" />
</configuration>

Ответ 1

Сначала я хотел бы сказать, что из-за исторических причин регистрация в java - это беспорядок, и вы должны быть готовы приложить некоторые усилия, чтобы сделать это правильно.

Теперь, к вашей проблеме.

Прежде всего, это действительно похоже на журналы, которые вы получаете в своем обходном журнале STDOUT (по крайней мере, они не соответствуют ни одному из шаблонов, определенных в вашей конфигурации журнала).

Могут быть две причины:

  • Вы неправильно сконфигурировали logback, что менее вероятно (проверьте это, проверив, попадают ли какие-либо записи в файлы, в которые вы настроили logback, записываете их в).

  • Журналы формируют AWS sdk, обрабатывая ведение журналов сообщества (скорее всего, поскольку это система протоколирования, используемая AWS sdk) или что-то, что имитирует ведение журнала Commons для перенаправления журналов, например, SLF4J (менее вероятно, так как для этого требуется некоторая явная конфигурация пути к классам.)

Теперь, чтобы разобраться с этим, я предлагаю вам начать с этой статьи, чтобы получить обзор зоопарка java logging.

Затем, чтобы решить вашу проблему, я бы предложил вам настроить популярные системы ведения журналов (commons logging, log4j и т.д.), чтобы направлять свои журналы на SLF4j и использовать logback как реализацию SLF4j.

Прочитайте этот и этот (если вы используете maven, иначе найдете способ исключить jcl и log4j, относящийся к вашей системе сборки), чтобы понять, что должно и то, что не должно быть помещено в ваш путь к классам.

Один из моих проектов использует AWS sdk и имеет регистрацию, как было предложено выше.

В моем pom.xml я устанавливал зависимости вроде этого:

...

<repositories>
    <repository>
        <id>version99</id>
        <url>http://version99.qos.ch/</url>
    </repository>
</repositories>

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
            <version>99-empty</version>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>99-empty</version>
        </dependency>
    </dependencies>
</dependencyManagement>

<dependencies>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>1.7.7</version>
    </dependency>
    <dependency>
        <groupId>ch.qos.logback</groupId>
        <artifactId>logback-classic</artifactId>
        <version>1.1.2</version>
    </dependency>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>log4j-over-slf4j</artifactId>
        <version>1.7.7</version>
    </dependency>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>jcl-over-slf4j</artifactId>
        <version>1.7.7</version>
    </dependency>

    ...

</dependencies>

...

... а также в моем пути к классам у меня есть logback.xml следующим образом:

<appender name="FILE" class="ch.qos.logback.core.FileAppender">
    <file>logs.log</file>
    <append>false</append>
    <encoder>
        <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
    </encoder>
</appender>

<root level="debug">
    <appender-ref ref="FILE" />
</root>

... и все записи в конечном итоге записаны в файл журнала.

Это должно дать вам представление о том, как настроить зависимости/протоколирование.

Не стесняйтесь прояснять непонятные моменты в комментариях.

Ответ 2

Вы получаете сообщения в STDOUT, скорее всего, потому что у вас есть что-то в своем пути к классам во время выполнения, которое регистрируется в STDOUT (f.ex. класс, который использует apache commons logging, как это было предложено в предыдущей статье). Не только, что вы используете logback, означает, что все протоколирования проходят через logback.

Чтобы получить контроль над всеми входами в ваше приложение, вы должны:

A) Проверьте свой путь к классу и удалите все другие двоичные файлы журналов регистрации (commons-logging, log4j и т.д.). Если вы используете maven, запустите mvn dependency:tree -X, затем используйте исключение, чтобы удалить зависимости для протоколирования библиотек.

B) Замените эти библиотеки на мосты, чтобы направить ваш журнал на SLF4J

C) Направьте свой журнал с исходного кода через SLF4J на Logback. Для смягчения вашей работы существует migrator. Проверьте, может ли он вам помочь.

D) Настройте свой логин в logback.xml или logback.groovy.