2017-01-29 10 views
4

Мне было предложено, как захватить вывод журнала из приложения Spring Boot, которое выполняется как действие Java от Oozie.Весенняя ботинок для Кафки: как устранить предупреждение; лучшие практики

Моя первоначальная мысль заключалась в том, что можно было бы редактировать некоторые свойства log4j для захвата журналов приложений внутри YARN или Oozie. Затем мне пришло в голову, что Kafka станет гораздо более простым способом захвата и агрегации сообщений журнала для конкретного приложения, работающего на разных узлах кластера. Гораздо проще контролировать распределенную систему, подписываясь на тему, чем ловить рыбу через файлы журналов.

Я заметил, что у Kafka есть приложение log4j, поэтому я попытался создать минимальный воспроизводимый пример (размещен на github: https://github.com/alexwoolford/spring-boot-log-to-kafka-example). Вот отрывок из pom.xml:

<parent> 
    <groupId>org.springframework.boot</groupId> 
    <artifactId>spring-boot-starter-parent</artifactId> 
    <version>1.4.4.RELEASE</version> 
</parent> 

<dependencies> 
    <dependency> 
     <groupId>org.springframework.boot</groupId> 
     <artifactId>spring-boot-starter</artifactId> 
     <exclusions> 
      <exclusion> 
       <groupId>org.springframework.boot</groupId> 
       <artifactId>spring-boot-starter-logging</artifactId> 
      </exclusion> 
      <exclusion> 
       <groupId>org.springframework.boot</groupId> 
       <artifactId>logback-classic</artifactId> 
      </exclusion> 
     </exclusions> 
    </dependency> 
    <dependency> 
     <groupId>org.springframework.boot</groupId> 
     <artifactId>spring-boot-starter-log4j</artifactId> 
    </dependency> 
    <dependency> 
     <groupId>org.apache.kafka</groupId> 
     <artifactId>kafka-log4j-appender</artifactId> 
     <version>0.10.0.0</version> 
    </dependency> 
    <dependency> 
     <groupId>net.logstash.log4j</groupId> 
     <artifactId>jsonevent-layout</artifactId> 
     <version>1.7</version> 
    </dependency> 
    <dependency> 
     <groupId>commons-logging</groupId> 
     <artifactId>commons-logging</artifactId> 
     <version>1.2</version> 
    </dependency> 
</dependencies> 

Мой log4j.properties файл выглядит следующим образом:

log4j.rootLogger=INFO 
log4j.appender.KAFKA=org.apache.kafka.log4jappender.KafkaLog4jAppender 
log4j.appender.KAFKA.layout=net.logstash.log4j.JSONEventLayoutV1 
log4j.appender.KAFKA.topic=logs 
log4j.appender.KAFKA.brokerList=hdp-single-node:6667 
log4j.appender.KAFKA.syncSend=true 
log4j.appender.KAFKA.producer.type=async 
log4j.logger.io.woolford=INFO, KAFKA 

Это работает, за исключением того, что она генерирует предупреждение:

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

Даже если это приложение работает и делает то, что мне нужно, предупреждения показывают, что я что-то неправильно сконфигурировал. Вы видите, что нужно изменить?

Кроме того, я заметил, что Spring Boot по умолчанию использует Logback, и я замечаю, что есть проект с открытым исходным кодом, logback-kafka-appender, который позволяет Logback присоединяться к Kafka. Является ли приложение Kafka log4j лучшим способом для Spring Boot для входа в Kafka?

ответ

4

Log4j2 имеет Kafka appender. Это было необходимо, чтобы добавить spring-boot-starter-log4j2 и jackson-databind артефактов на pom.xml:

<dependencies> 
    <dependency> 
     <groupId>org.springframework.boot</groupId> 
     <artifactId>spring-boot-starter</artifactId> 
     <exclusions> 
      <exclusion> 
       <groupId>org.springframework.boot</groupId> 
       <artifactId>spring-boot-starter-logging</artifactId> 
      </exclusion> 
      <exclusion> 
       <groupId>org.springframework.boot</groupId> 
       <artifactId>logback-classic</artifactId> 
      </exclusion> 
     </exclusions> 
    </dependency> 
    <dependency> 
     <groupId>org.springframework.boot</groupId> 
     <artifactId>spring-boot-starter-log4j2</artifactId> 
    </dependency> 
    <dependency> 
     <groupId>org.apache.kafka</groupId> 
     <artifactId>kafka-log4j-appender</artifactId> 
     <version>0.10.0.0</version> 
     <exclusions> 
      <exclusion> 
       <groupId>org.slf4j</groupId> 
       <artifactId>slf4j-log4j12</artifactId> 
      </exclusion> 
     </exclusions> 
    </dependency> 
    <dependency> 
     <groupId>com.fasterxml.jackson.core</groupId> 
     <artifactId>jackson-databind</artifactId> 
     <version>2.8.6</version> 
    </dependency> 
</dependencies> 

Затем я создал XML отформатирован log4j2.xml файла:

<?xml version="1.0" encoding="UTF-8"?> 
<Configuration status="info" name="spring-boot-log-to-kafka-example" packages="io.woolford"> 
    <Appenders> 
     <Kafka name="kafkaAppender" topic="logs"> 
      <JSONLayout /> 
      <Property name="bootstrap.servers">hdp-single-node:6667</Property> 
     </Kafka> 
    </Appenders> 
    <Loggers> 
     <Root level="INFO"> 
      <AppenderRef ref="kafkaAppender"/> 
     </Root> 
     <Logger name="org.apache.kafka" level="WARN" /> 
    </Loggers> 
</Configuration> 

Сообщение лесозаготовительного отправляется Кафки в формате JSON, например,

{ 
    "timeMillis": 1485736022854, 
    "thread": "Thread-1", 
    "level": "INFO", 
    "loggerName": "org.springframework.context.annotation.AnnotationConfigApplicationContext", 
    "message": "Closing org.spring[email protected]20140db9: startup date [Sun Jan 29 17:26:52 MST 2017]; root of context hierarchy", 
    "endOfBatch": false, 
    "loggerFqcn": "org.apache.commons.logging.impl.SLF4JLocationAwareLog", 
    "threadId": 19, 
    "threadPriority": 5 
}