web-dev-qa-db-fra.com

Existe-t-il une structure de journal qui crée des objets JSON avec des paramètres de message en tant qu'attributs?

Je souhaite envoyer des événements de journal à Loggly en tant qu’objets JSON avec des messages de chaîne paramétrés. Notre projet a actuellement beaucoup de code qui ressemble à ceci:

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

Nous utilisons actuellement Logback en tant que notre backend SLF4J, et Logback's JsonLayout pour sérialiser nos objets ILogEvent en JSON. Par conséquent, au moment où nos événements de journal sont envoyés à Loggly, ils ressemblent à ceci:

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

Bien que cela fonctionne, il envoie une chaîne message différente pour chaque valeur de someParameter, ce qui rend les filtres automatiques de Loggly presque inutiles.

Au lieu de cela, j'aimerais une disposition qui crée un JSON qui ressemble à ceci:

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

Ce format permettrait à Loggly de regrouper tous les événements de journal avec le message This is a log message with a parameter, quelle que soit la valeur de someParameter.

Il ressemble à le filtre KV de Logstash fait quelque chose comme ceci - y a-t-il un moyen d'accomplir cette tâche avec Logback, à moins d'écrire ma propre présentation qui effectue une sérialisation personnalisée de l'objet ILogEvent?

22
MusikPolice

Vous pouvez utiliser un contexte de diagnostic mappé pour définir un tampon pour chacun de ces types de messages de journal sur lesquels vous pouvez ensuite filtrer une fois de manière cohérente.

Selon la source de JsonLayout le tampon est stocké en tant que valeur distincte dans le fichier JSON. 

5
muttonUp

Il existe un encodeur JSON logstash pour Logback, logstash-logback-encoder

13
Mark Roper

Donc, pour moi, j'essayais de consigner les temps d'exécution, j'ai créé un pojo appelé ExecutionTime avec le nom, la méthode, la classe, la durée.

J'ai ensuite pu le créer:

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

Pour l'enregistrement, j'ai ensuite utilisé:

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

Assurez-vous que vous avez: 

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

Cela enregistrera quelque chose comme ceci:

{  
   "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
   }
}

Peut-être une configuration différente car j'utilisais logback-spring.xml pour exporter mes journaux vers 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
user2022484

Voici un projet récemment créé qui fournit une API de journalisation spécifique à JSON et qui fonctionne avec SLF4J:

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

4
ash

Comme déjà répondu, vous obtiendrez une arborescence JSON unidimensionnelle avec MDC et/ou en utilisant un marqueur avec logstash-logback-encoder.

Si vous recherchez également les éléments suivants:

  • les manuels de code pour la définition de la clé et du type de données enregistrés,
  • configuration des outils d'agrégation de journaux (comme elasticsearch)
  • code d'assistance Java généré pour une journalisation efficace et correcte

puis essayez un projet que j'ai créé: json-log-domain . Il définit une définition simple au format YAML à partir de laquelle les informations ci-dessus peuvent être générées.

Un exemple d'instruction de code d'assistance serait

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

alors que le démarquage généré aimerait quelque chose comme ceci .

0
ThomasRS