Отправка журналов Logback в LogStash через RabbitMQ с использованием JSON Encoder (Spring)

Я использую Spring Boot (1.5.4). Я хочу отправлять (logback) журналы из моих служб в Logstash через RabbitMQ в формате JSON, а не в виде простого текста. Это избавит меня от необходимости устанавливать фильтр на стороне Logstash, чтобы можно было управлять форматированием на стороне приложения (используя Logback Encoder).

Мне известно о весеннем входе в систему AMQP Appender для RabbitMQ org.springframework.amqp.rabbit.logback.AmqpAppender однако при этом используется формат (простой текст), а не форматированный JSON. Я хотел бы использовать LogStash Encoder net.logstash.logback.encoder.LogstashEncoder, Я хотел бы использовать Appender с Encoder (я хочу все это:").

1 ответ

Решение

Сначала я расширил AMQPAppender, добавив кодировщик следующим образом:

package nz.govt.mpi.util;

import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.logback.AmqpAppender;

import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.encoder.Encoder;
import lombok.Getter;
import lombok.Setter;

public class AmqpLogbackAppender extends AmqpAppender {

    @Getter
    @Setter
    private Encoder<ILoggingEvent> encoder;

    /**
     * We remove the default message layout and replace with the JSON {@link Encoder}
     */
    @Override
    public Message postProcessMessageBeforeSend(Message message, Event event) {
        return new Message(this.encoder.encode(event.getEvent()), message.getMessageProperties());
    }

    @Override
    public void start() {
        super.start();
        encoder.setContext(getContext());

        if (!encoder.isStarted()) {
            encoder.start();
        }

    }

    @Override
    public void stop() {
        super.stop();
        encoder.stop();
    }

}

И тогда я настроил файл конфигурации logback-spring.xml так:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <springProperty scope="context" name="rabbitMQHost" source="logback.amqp.host" defaultValue="localhost"/>
    <springProperty scope="context" name="rabbitMQPort" source="logback.amqp.port" defaultValue="5672"/>
    <springProperty scope="context" name="rabbitMQUsername" source="spring.rabbitmq.username" />
    <springProperty scope="context" name="rabbitMQPassword" source="spring.rabbitmq.password" />
    <springProperty scope="context" name="rabbitMQExchangeName" source="logback.amqp.exchange.name" defaultValue="mpi.tradedev"/>
    <springProperty scope="context" name="rabbitMQRoutingKey" source="logback.amqp.routing.key" defaultValue="mpi.tradedev.logging"/>
    <springProperty scope="context" name="serviceName" source="spring.application.name" />

    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{HH:mm:ss.SSS} [%thread, %X{X-B3-TraceId:-},%X{X-B3-SpanId:-}] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>

    <appender name="AMQP" class="nz.govt.mpi.util.AmqpLogbackAppender">
        <!-- layout is required but ignored as using the encoder for the AMQP message body -->
        <layout><pattern><![CDATA[ %level ]]></pattern></layout>

        <encoder class="net.logstash.logback.encoder.LogstashEncoder">
            <customFields>{"serviceName": "${serviceName}"}</customFields>
        </encoder>

    <!-- RabbitMQ connection -->
    <host>${rabbitMQHost}</host>
    <port>${rabbitMQPort}</port>
    <username>${rabbitMQUsername}</username>
    <password>${rabbitMQPassword}</password>
    <exchangeName>${rabbitMQExchangeName}</exchangeName>
    <routingKeyPattern>${rabbitMQRoutingKey}</routingKeyPattern>

    <declareExchange>true</declareExchange>
    <exchangeType>topic</exchangeType>
    <generateId>true</generateId>
    <charset>UTF-8</charset>
    <durable>true</durable>
    <deliveryMode>PERSISTENT</deliveryMode>

 </appender>

    <root level="info">
        <appender-ref ref="STDOUT" />
        <appender-ref ref="AMQP" />
    </root>
</configuration>

Я наконец добавил необходимые свойства в application.properties файл так:-

spring.application.name=my-app
logback.amqp.host=localhost
logback.amqp.port=5672
logback.amqp.exchange.name=ex_logstash
logback.amqp.routing.key=my-app.logging
spring.rabbitmq.username=rquser
spring.rabbitmq.password=rqpass

Мне также пришлось настроить необходимую учетную запись пользователя в RabbitMQ. Когда приложение запускается, оно создает тему (ex_logstash), но вы должны создать очередь (qu_logstash), которая связана с этой темой с помощью ключа маршрутизации (my-app.*). Затем вы создаете конфигурацию logstash, соответствующую имени очереди.

ex_logstash -> qu_logstash

logstash.json Пример файла конфигурации:-

input {
  rabbitmq {
    host => "localhost"
    queue => "qu_logstash"
    durable => true
    exchange => "ex_logstash"
    key => "my-app.*"
    threads => 10
    type => "topic"
    prefetch_count => 200
    port => 5672
    user => "rquser"
    password => "rqpass"
  }
}

На стороне приложения вам понадобятся необходимые зависимости в вашем pom.xml. Вот те, которые я использую, которые охватывают обязательные классы YMMV:-

<dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-stream-rabbit</artifactId>
    </dependency>
    <dependency>
        <groupId>net.logstash.logback</groupId>
        <artifactId>logstash-logback-encoder</artifactId>
        <version>4.9</version>
    </dependency>
    <dependency>
        <groupId>ch.qos.logback</groupId>
        <artifactId>logback-classic</artifactId>
        <version>1.2.3</version>
    </dependency>
    <dependency>
        <groupId>ch.qos.logback</groupId>
        <artifactId>logback-core</artifactId>
        <version>1.2.3</version>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <scope>provided</scope>
    </dependency>
Другие вопросы по тегам