Существует ли макет журнала, который создает объекты JSON с параметрами сообщений в качестве атрибутов?

Я хочу отправить события журнала в Loggly как объекты JSON с параметризованными строковыми сообщениями. В нашем проекте в настоящее время много кода, который выглядит так:

String someParameter = "1234";
logger.log("This is a log message with a parameter {}", someParameter);

В настоящее время мы используем Logback как наш бэкэнд SLF4J и Logback JsonLayout для сериализации наших объектов ILogEvent в JSON. В результате, к тому времени, когда наши события журнала отправляются в Loggly, они выглядят так:

{
    "message": "This is a log message with a parameter 1234",
    "level": INFO,
    ....
}

Пока это работает, он отправляет другую строку message для каждого значения someParameter, что делает автоматические фильтры Loggly рядом с бесполезными.

Вместо этого я хотел бы иметь макет, который создает JSON, который выглядит следующим образом:

{
    "message": "This is a log message with a parameter {}",
    "level": INFO,
    "parameters": [
        "1234"
    ]
}

Этот формат позволяет Loggly группировать все события журнала с сообщением This is a log message with a parameter вместе, независимо от значения someParameter.

Похоже, что фильтр Logstash KV делает что-то вроде этого - есть ли способ выполнить эту задачу с помощью Logback, за исключением написания собственного макет, который выполняет пользовательскую сериализацию объекта ILogEvent?

Ответы

Ответ 1

Вы можете использовать Mapped Diagnostic Context, чтобы установить штамп для каждого из этих типов сообщений журнала, которые вы затем могли бы фильтровать один раз в логгинге.

Согласно источнику JsonLayout штамп сохраняется как отдельное значение в JSON.

Ответ 2

Существует логарифмический кодер JSON для журнала, logstash-logback-encoder

Ответ 3

Вот недавно созданный проект, который предоставляет JSON-специфический API протоколирования и работает с SLF4J:

https://github.com/savoirtech/slf4j-json-logger

Ответ 4

Итак, для меня я пытался регистрировать время выполнения, я создал pojo под названием ExecutionTime с именем, методом, классом, продолжительностью.

Тогда я смог его создать:

ExecutionTime time = new ExecutionTime("Controller Hit", methodName, className, sw.getTotalTimeMillis());

Для ведения журнала я тогда использовал:

private final Logger logger = LoggerFactory.getLogger(this.getClass());
logger.info(append("metric", time), time.toString());

Убедитесь, что у вас есть:

import static net.logstash.logback.marker.Markers.append;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Это будет записывать что-то вроде этого:

{  
   "ts":"2017-02-16T07:41:36.680-08:00",
   "msg":"ExecutionTime [name=Controller Hit, method=setupSession, className=class com.xxx.services.controllers.SessionController, duration=3225]",
   "logger":"com.xxx.services.metrics.ExecutionTimeLogger",
   "level":"INFO",
   "metric":{  
      "name":"Controller Hit",
      "method":"setupSession",
      "className":"class com.xxx.services.controllers.SessionController",
      "duration":3225
   }
}

Возможно, это другая настройка, поскольку я использовал logback- spring.xml для вывода моих журналов в json:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <include resource="org/springframework/boot/logging/logback/base.xml"/>
    <property name="PROJECT_ID" value="my_service"/>
    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <File>app/logs/${PROJECT_ID}.json.log</File>
        <encoder class="net.logstash.logback.encoder.LogstashEncoder">
            <fieldNames>
                <timestamp>ts</timestamp>
                <message>msg</message>
                <thread>[ignore]</thread>
                <levelValue>[ignore]</levelValue>
                <logger>logger</logger>
                <version>[ignore]</version>
            </fieldNames>
        </encoder>
        <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
            <maxIndex>10</maxIndex>
            <FileNamePattern>app/logs/${PROJECT_ID}.json.log.%i</FileNamePattern>
        </rollingPolicy>
        <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
            <MaxFileSize>20MB</MaxFileSize>
        </triggeringPolicy>
    </appender>
    <logger name="com.xxx" additivity="false" level="DEBUG">
        <appender-ref ref="FILE"/>
        <appender-ref ref="CONSOLE"/>
    </logger>
    <root level="WARN">
        <appender-ref ref="FILE"/>
    </root>
</configuration>

Ответ 5

Как уже было сказано, вы получите одномерное дерево JSON с MDC и/или с помощью маркера с logstash-logback-encoder.

Если вы также ищете следующее:

  • кодовые книги для определения ключа и типа занесенного в журнал ключа,
  • конфигурация инструментов агрегирования журналов (например, elasticsearch)
  • генерируемый Java-хелпер-код для эффективного и правильного ведения журнала

затем попробуйте проект, который я создал: json-log-domain. Он определяет простое определение формата YAML, из которого может быть сгенерировано выше.

Пример вспомогательного кода будет

logger.info(host("localhost").port(8080), "Hello world");

в то время как сгенерированная уценка похожа на this.