Cette page a été traduite par l'API Cloud Translation.
Switch to English

Journalisation structurée

Dans Cloud Logging, les journaux structurés font référence aux entrées de journal qui utilisent le champ jsonPayload pour ajouter une structure à leurs charges utiles.

Si vous utilisez l'API Cloud Logging ou l'outil de ligne de commande gcloud, vous pouvez contrôler la structure de vos charges utiles. Pour obtenir des exemples, consultez la section Écrire des journaux structurés.

Si vous utilisez l'agent Cloud Logging pour obtenir vos entrées de journal, vous pouvez spécifier à l'agent Logging de convertir vos charges utiles au format JSON.

Si vous utilisez le service BindPlane pour ingérer les journaux, vos charges utiles sont au format JSON et structurées en fonction du système source. Pour plus d'informations sur la recherche et l'affichage des journaux ingérés via BindPlane, consultez la documentation BindPlane sur la recherche de données de journaux.

Structurer les journaux avec l'agent Logging à l'aide de champs spéciaux dans les charges utiles JSON

Pour écrire des journaux structurés dans Logging, vous pouvez procéder de différentes manières:

  • Envoyez la structure complète LogEntry avec un jsonPayload à l'API Cloud Logging.
  • Fournir des objets JSON sérialisés à l'agent Logging

Si vous utilisez Google Kubernetes Engine ou l'environnement flexible App Engine, vous pouvez écrire des journaux structurés sous forme d'objets JSON sérialisés sur une seule ligne dans stdout ou stderr. L'agent Logging envoie ensuite les journaux structurés à Cloud Logging en tant que jsonPayload de la structure LogEntry.

Certains champs de l'objet JSON sont reconnus comme spéciaux par l'agent Logging et extraits dans la structure LogEntry. Ces champs JSON spéciaux peuvent être utilisés pour définir les champs suivants dans LogEntry :

  • severity
  • spanId
  • labels défini par l'utilisateur
  • httpRequest

JSON étant plus précis et plus polyvalent que les lignes de texte, vous pouvez utiliser des objets JSON pour écrire des messages multilignes et ajouter des métadonnées.

Pour créer des entrées de journal structurées pour vos applications à l'aide d'un format simplifié, consultez le tableau suivant, qui répertorie les champs et leurs valeurs au format JSON:

Champ de journal JSON LogEntry Fonction de l'agent Cloud Logging Exemple de valeur
severity severity L'agent Logging tente de faire correspondre différentes chaînes de gravité courantes, qui incluent la liste des chaînes LogSeverity reconnues par l'API Logging. "severity":"ERROR"
message textPayload (ou partie de jsonPayload) Le message qui apparaît sur la ligne d'entrée de journal dans l'explorateur de journaux. "message":"There was an error in the application."

Remarque: message est enregistré en tant que textPayload s'il s'agit du seul champ restant après la L'agent Logging supprime les autres champs spécifiques et detect_json n'ont pas été activés. sinon message reste dans jsonPayload. Si votre entrée de journal contient une trace de la pile d'exception, celle-ci doit être définie dans le champ de journal JSON message, de sorte qu'elle puisse être analysée et enregistrée dans Error Reporting. s'affiche en haut de l'écran.
log (ancien Google Kubernetes Engine uniquement) textPayload Ne s'applique qu'à l'ancien Google Kubernetes Engine : si, après suppression des champs spéciaux, il ne reste qu'un champ de journal, ce journal est enregistré en tant que textPayload.
httpRequest httpRequest Un enregistrement structuré au format du champ HttpRequest LogEntry. "httpRequest":{"requestMethod":"GET"}
Champs liés au temps timestamp Pour plus d'informations, consultez la section Champs liés au temps. "times":"2020-10-12T07:20:50.52Z"
logging.googleapis.com/insertId insertId Pour en savoir plus, consultez la section insertId de la page LogEntry. "logging.googleapis.com/insertId":"42"
logging.googleapis.com/labels labels La valeur de ce champ doit être un enregistrement structuré. Pour en savoir plus, consultez la section labels sur la page LogEntry. "logging.googleapis.com/labels": {"user_label_1":"value_1","user_label_2":"value_2"}
logging.googleapis.com/operation operation La valeur de ce champ est également utilisée par l'explorateur de journaux pour regrouper les entrées de journal associées. Pour en savoir plus, consultez la section operation sur la page LogEntry. "logging.googleapis.com/operation": {"id":"get_data","producer":"github.com/MyProject/MyApplication", "first":"true"}
logging.googleapis.com/sourceLocation sourceLocation Les informations d'emplacement du code source associées à l'entrée de journal, le cas échéant. Pour en savoir plus, consultez la section LogEntrySourceLocation de la page LogEntry. "logging.googleapis.com/sourceLocation": {"file":"get_data.py","line":"142","function":"getData"}
logging.googleapis.com/spanId spanId ID de délai dans la trace associée à l'entrée de journal. Pour en savoir plus, consultez la section spanId de la page LogEntry. "logging.googleapis.com/spanId":"000000000000004a
logging.googleapis.com/trace trace Nom de ressource de la trace associée à l'entrée de journal, le cas échéant. Pour en savoir plus, consultez la section trace de la page LogEntry. "logging.googleapis.com/trace":"projects/my-projectid/traces/0679686673a"

Remarque: Si le champ n'écrit pas stdout ou stderr, la valeur de ce champ doit doit être mis en forme en tant que projects/[PROJECT-ID]/traces/[TRACE-ID]. Il peut donc être utilisé par l'explorateur de journaux et le lecteur de traces pour regrouper les entrées de journal et les afficher en parallèle avec les traces. Si autoformat_stackdriver_trace est vrai et [V] correspond au format de ResourceTrace traceId, le champ LogEntry trace a la valeur . projects/[PROJECT-ID]/traces/[V]
logging.googleapis.com/trace_sampled traceSampled La valeur de ce champ doit être true ou false. Pour en savoir plus, consultez la section traceSampled de la page LogEntry. logging.googleapis.com/trace_sampled":"false"

Pour créer des entrées de journal au format simplifié, créez une représentation JSON de l'entrée à l'aide des champs. Tous les champs sont facultatifs. Voici un exemple d'entrée de journal JSON simplifiée:

{
  "severity":"ERROR",
  "message":"There was an error in the application.",
    "httpRequest":{
    "requestMethod":"GET"
    },
  "times":"2020-10-12T07:20:50.52Z",
  "logging.googleapis.com/insertId":"42",
  "logging.googleapis.com/labels":{
    "user_label_1":"value_1",
    "user_label_2":"value_2"
    },
  "logging.googleapis.com/operation":{
    "id":"get_data",
    "producer":"github.com/MyProject/MyApplication",
     "first":"true"
      },
  "logging.googleapis.com/sourceLocation":{
    "file":"get_data.py",
    "line":"142",
    "function":"getData"
    },
  "logging.googleapis.com/spanId":"000000000000004a",
  "logging.googleapis.com/trace":"projects/my-projectid/traces/06796866738c859f2f19b7cfb3214824",
  "logging.googleapis.com/trace_sampled":"false"
}

Voici un exemple d'entrée de journal résultante:

{
  "insertId": "42",
  "jsonPayload": {
    "message": "There was an error in the application",
    "times": "2019-10-12T07:20:50.52Z"
  },
  "httpRequest": {
    "requestMethod": "GET"
  },
  "resource": {
    "type": "k8s_container",
    "labels": {
      "container_name": "hello-app",
      "pod_name": "helloworld-gke-6cfd6f4599-9wff8",
      "project_id": "stackdriver-sandbox-92334288",
      "namespace_name": "default",
      "location": "us-west4",
      "cluster_name": "helloworld-gke"
    }
  },
  "timestamp": "2020-11-07T15:57:35.945508391Z",
  "severity": "ERROR",
  "labels": {
    "user_label_2": "value_2",
    "user_label_1": "value_1"
  },
  "logName": "projects/stackdriver-sandbox-92334288/logs/stdout",
  "operation": {
    "id": "get_data",
    "producer": "github.com/MyProject/MyApplication",
    "first": true
  },
  "trace": "projects/my-projectid/traces/06796866738c859f2f19b7cfb3214824",
  "sourceLocation": {
    "file": "get_data.py",
    "line": "142",
    "function": "getData"
  },
  "receiveTimestamp": "2020-11-07T15:57:42.411414059Z",
  "spanId": "000000000000004a"
}

Agent Logging

L'agent Logging google-fluentd est un empaquetage spécifique à Cloud Logging du collecteur de données de journal Fluentd. L'agent Logging est fourni avec la configuration Fluentd par défaut et utilise les plug-ins d'entrée Fluentd pour extraire les journaux des événements à partir de sources externes telles que les fichiers sur disque ou pour analyser les enregistrements de journaux entrants.

Fluentd dispose d'une liste d'analyseurs disponibles qui extraient les journaux et les convertissent en charges utiles (JSON) structurées.

En configurant une source de journal avec le format [PARSER_NAME], vous pouvez exploiter les analyseurs intégrés fournis par Fluentd.

Les exemples de code suivants montrent la configuration Fluentd, l'enregistrement du journal d'entrée et la charge utile structurée de sortie, qui fait partie d'une entrée de journal Cloud Logging :

  • Configuration Fluentd :

      <source>
        @type tail
    
        format syslog # <--- This uses a predefined log format regex named
                      # `syslog`. See details at https://docs.fluentd.org/parser/syslog.
    
        path /var/log/syslog
        pos_file /var/lib/google-fluentd/pos/syslog.pos
        read_from_head true
        tag syslog
      </source>
    
  • Enregistrement du journal (entrée) :

      <6>Feb 28 12:00:00 192.168.0.1 fluentd[11111]: [error] Syslog test
    
  • Charge utile structurée (sortie) :

        jsonPayload: {
            "pri": "6",
            "host": "192.168.0.1",
            "ident": "fluentd",
            "pid": "11111",
            "message": "[error] Syslog test"
        }
    

Pour plus d'informations sur le fonctionnement de l'analyseur syslog, consultez la documentation détaillée de Fluentd.

Analyseurs standards activés par défaut

Le tableau suivant présente les analyseurs standards inclus dans l'agent si vous activez la journalisation structurée :

Nom de l'analyseur Fichier de configuration
syslog /etc/google-fluentd/config.d/syslog.conf
nginx /etc/google-fluentd/config.d/nginx.conf
apache2 /etc/google-fluentd/config.d/apache.conf
apache_error /etc/google-fluentd/config.d/apache.conf

Reportez-vous à la section Installation ci-dessous pour connaître la procédure d'activation de la journalisation structurée lors de l'installation de l'agent Logging.

Installation

Pour activer la journalisation structurée, vous devez modifier la configuration par défaut de l'agent Logging lors de son installation (ou de sa réinstallation). L'activation de la journalisation structurée remplace les fichiers de configuration précédemment répertoriés. Le fonctionnement de l'agent lui-même ne change pas.

Lorsque vous activez la journalisation structurée, les journaux répertoriés sont convertis en entrées de journal sous des formats différents de ceux utilisés avant l'activation des journaux structurés. Si les journaux sont exportés hors de Cloud Logging, ce changement peut affecter les applications de post-traitement. Dans le cas des exportations BigQuery, BigQuery refusera les nouvelles entrées de journal pour le reste de la journée en raison de leur schéma incorrect.

Pour obtenir des instructions sur l'installation de l'agent Logging et l'activation de la journalisation structurée, consultez la page Installer l'agent Logging.

Les fichiers de configuration de l'agent Logging se trouvent dans /etc/google-fluentd/config.d/. Ils doivent désormais inclure les analyseurs standards activés par défaut.

Configurer le format du journal d'accès Apache

Par défaut, l'agent Logging stocke les données du journal d'accès Apache dans le champ jsonPayload. Exemple :

{
  "logName": ...,
  "resource": ...,
  "httpRequest": ...,
  "jsonPayload": {
    "user"   : "some-user",
    "method" : "GET",
    "code"   : 200,
    "size"   : 777,
    "host"   : "192.168.0.1",
    "path"   : "/some-path",
    "referer": "some-referer",
    "agent"  : "Opera/12.0"
  },
  ...
}

Vous pouvez également configurer l'agent Logging pour extraire certains champs dans le champ httpRequest. Exemple :

{
  "logName": ...,
  "resource": ...,
  "httpRequest": {
    "requestMethod": "GET",
    "requestUrl": "/some-path",
    "requestSize": "777",
    "status": "200",
    "userAgent": "Opera/12.0",
    "serverIp": "192.168.0.1",
    "referrer":"some-referrer",
  },
  "jsonPayload": {
    "user":"some-user"
  },
  ...
}

La configuration du champ httpRequest, comme illustré dans l'exemple précédent, facilite le traçage : Google Cloud Console présente tous les journaux d'une requête HTTP donnée dans une hiérarchie parent-enfant.

Pour configurer cette extraction, ajoutez les éléments suivants à la fin de /etc/google-fluentd/config.d/apache.conf :

  <filter apache-access>
    @type record_transformer
    enable_ruby true
    <record>
      httpRequest ${ {"requestMethod" => record['method'], "requestUrl" => record['path'], "requestSize" => record['size'], "status" => record['code'], "userAgent" => record['agent'], "serverIp" => record['host'],
      "referer" => record['referer']} }
    </record>
    remove_keys method, path, size, code, agent, host, referer
  </filter>

Pour plus d'informations sur la configuration de vos entrées de journal, consultez la section Modifier des enregistrements de journal.

Configurer le format du journal d'accès nginx

Par défaut, l'agent Logging stocke les données du journal d'accès nginx dans le champ jsonPayload. Exemple :

  {
    "logName": ...,
    "resource": ...,
    "httpRequest": ...,
    "jsonPayload": {
      "remote":"127.0.0.1",
      "host":"192.168.0.1",
      "user":"some-user",
      "method":"GET",
      "path":"/some-path",
      "code":"200",
      "size":"777",
      "referrer":"some-referrer",
      "agent":"Opera/12.0",
      "http_x_forwarded_for":"192.168.3.3"
    },
    ...
  }

Vous pouvez également configurer l'agent Logging pour extraire certains champs dans le champ httpRequest. Exemple :

  {
    "logName": ...,
    "resource": ...,
    "httpRequest": {
      "requestMethod": "GET",
      "requestUrl": "/some-path",
      "requestSize": "777",
      "status": "200",
      "userAgent": "Opera/12.0",
      "remoteIp": "127.0.0.1",
      "serverIp": "192.168.0.1",
      "referrer":"some-referrer",
    },
    "jsonPayload": {
      "user":"some-user",
      "http_x_forwarded_for":"192.168.3.3"
    },
    ...
  }

La configuration du champ httpRequest, comme illustré dans l'exemple précédent, facilite le traçage : Google Cloud Console présente tous les journaux d'une requête HTTP donnée dans une hiérarchie parent-enfant.

Pour configurer cette extraction, ajoutez les éléments suivants à la fin de /etc/google-fluentd/config.d/nginx.conf :

<filter nginx-access>
  @type record_transformer
  enable_ruby true
  <record>
    httpRequest ${ {"requestMethod" => record['method'], "requestUrl" => record['path'], "requestSize" => record['size'], "status" => record['code'], "userAgent" => record['agent'], "remoteIp" => record['remote'], "serverIp" => record['host'], "referer" => record['referer']} }
  </record>
  remove_keys method, path, size, code, agent, remote, host, referer
</filter>

Pour plus d'informations sur la configuration de vos entrées de journal, consultez la section Modifier des enregistrements de journal.

Écrire votre propre analyseur

Si vos journaux ne sont pas compatibles avec les analyseurs standards, vous pouvez écrire les vôtres. Les analyseurs consistent en une expression régulière permettant de faire correspondre les enregistrements du journal et d'appliquer des libellés aux éléments.

Les 3 exemples de code suivants affichent une ligne de journal dans l'enregistrement de journal, une configuration avec une expression régulière indiquant le format de la ligne de journal et l'entrée de journal ingérée :

  • Ligne de journal dans l'enregistrement du journal :

    REPAIR CAR $500
    
  • Configuration avec une expression régulière qui indique le format de la ligne de journal :

    $ sudo vim /etc/google-fluentd/config.d/test-structured-log.conf
    $ cat /etc/google-fluentd/config.d/test-structured-log.conf
    <source>
      @type tail
    
      # Format indicates the log should be translated from text to
      # structured (JSON) with three fields, "action", "thing" and "cost",
      # using the following regex:
      format /(?<action>\w+) (?<thing>\w+) \$(?<cost>\d+)/
      # The path of the log file.
      path /tmp/test-structured-log.log
      # The path of the position file that records where in the log file
      # we have processed already. This is useful when the agent
      # restarts.
      pos_file /var/lib/google-fluentd/pos/test-structured-log.pos
      read_from_head true
      # The log tag for this log input.
      tag structured-log
    </source>
    
  • Entrée de journal correspondante :

     {
      insertId:  "eps2n7g1hq99qp"
      jsonPayload: {
        "action": "REPAIR"
        "thing": "CAR"
        "cost": "500"
      }
      labels: {
        compute.googleapis.com/resource_name:  "add-structured-log-resource"
      }
      logName:  "projects/my-sample-project-12345/logs/structured-log"
      receiveTimestamp:  "2018-03-21T01:47:11.475065313Z"
      resource: {
        labels: {
          instance_id:  "3914079432219560274"
          project_id:  "my-sample-project-12345"
          zone:  "us-central1-c"
        }
        type:  "gce_instance"
      }
      timestamp:  "2018-03-21T01:47:05.051902169Z"
     }
    

Afficher les journaux structurés

Pour rechercher des journaux et afficher les entrées de journal à l'aide de l'explorateur de journaux de Cloud Console, consultez la page Utiliser l'explorateur de journaux.

Pour lire des entrées de journaux à l'aide de l'outil de ligne de commande gcloud ou de l'API, consultez la page Lire les entrées de journaux.

Dépannage

Pour résoudre les problèmes courants rencontrés lors de l'installation de l'agent Stackdriver Logging ou de l'interaction avec ce dernier, consultez la page relative au dépannage de l'agent.