Diviser les entrées du journal d'audit

Ce document explique comment Cloud Logging divise les entrées de journal d'audit trop volumineuses et fournit des conseils pour les réassembler.

Lorsqu'une entrée de journal d'audit dépasse la limite de taille, Cloud Logging divise cette entrée et distribue les données contenues dans l'entrée d'origine du journal d'audit sur plusieurs entrées. Les utilisateurs voudront peut-être réassembler les journaux d'audit fractionnés, car les entrées de journal individuelles ne contiennent pas toutes les du journal d'audit d'origine.

Reconnaître les entrées de journal d'audit fractionnées

Les entrées de journal fractionnées contiennent des informations sur l'entrée d'origine à partir de laquelle elles ont été fractionnées. Si une entrée de journal contient un champ split, elle résulte de la scission d'une entrée de journal d'origine plus grande. split est un LogSplit objet qui contient les informations nécessaires pour identifier le journal de fractionnement associé les entrées correspondantes.

Chaque entrée de journal fractionnée contient les champs suivants :

  • split.uid : identifiant unique du groupe d'entrées de journal qui ont été divisées à partir d'une entrée de journal d'origine commune. La valeur de ce champ est identique pour toutes les entrées issues de l'entrée de journal d'origine.

  • split.index : position de cette entrée dans la série d'entrées fractionnées. La la première entrée de l'écran fractionné possède l'index 0. split.index est également ajouté au champ LogEntry.insertId.

  • split.totalSplits : nombre d'entrées de journal dans lesquelles l'entrée de journal d'origine a été divisée. La valeur de ce champ est identique pour toutes les entrées de l'entrée de journal d'origine.

Comment une entrée de journal est-elle divisée ?

Lorsqu'une entrée de journal d'audit surdimensionnée est divisée, les champs sont répartis entre les entrées de journal divisées résultantes comme suit :

  • Tous les champs, à l'exception du champ protoPayload, sont dupliqués dans chaque fractionnement entrée.

  • Les sous-champs protoPayload suivants peuvent être répartis sur plusieurs entrées :

    • protoPayload.metadata
    • protoPayload.request
    • protoPayload.response
  • Tous les autres sous-champs protoPayload sont inclus dans toutes les entrées de fractionnement.

  • Pour protoPayload.metadata, protoPayload.request et protoPayload.response, les types de champs suivants peuvent être divisés dans plusieurs entrées:

Si un champ appartient à un champ pouvant être fractionné, mais ne fait pas partie des champs pour la division il n'est présent que dans un seul des journaux fractionnés.

Par exemple, un champ booléen dans le sous-champ protoPayload.request ne peut apparaître que dans une seule entrée de journal fractionnée, mais le contenu d'un champ de chaîne dans le sous-champ protoPayload.request peut être réparti sur plusieurs entrées de journal fractionnées.

Pour obtenir un exemple de fractionnement d'une entrée de longue durée, reportez-vous à la section Exemple de entrée de journal journal.

Champs répétés avec de nombreuses valeurs

Lorsque la valeur de protoPayload.metadata, protoPayload.request ou protoPayload.response contient une liste de valeurs répétées, la liste peut être divisées et distribuées sur plusieurs entrées de journal fractionnées.

Par exemple, la liste de valeurs ["foo", "bar", "baz"] peut être divisée en deux listes : ["foo", "ba"] et ["", "r", "baz"]. La première liste correspond à l'entrée avec le split.index de 0, et la deuxième liste correspond à l'entrée avec le split.index de 1. La deuxième liste commence par une chaîne vide pour conserver les positions des éléments de la liste et pour indiquer que ceux qui se trouvent aux mêmes positions les différentes listes doivent être jointes. Dans cet exemple, ba est le deuxième élément de liste dans l'entrée 0, r étant le deuxième élément de liste dans l'entrée 1. elles sont recombinées dans l'ordre bar lors du remaniement de la liste d'origine.

Champs volumineux et non répétés

Lorsque de grands champs Struct et string non répétés sont divisés, ces champs sont traités comme suit:

  • Un champ string est divisé au niveau des caractères et non au niveau de l'octet. Par conséquent, les caractères multi-octets ne sont pas modifiés.

  • LogEntry.split.index contrôle l'ordre des contenus de la division, non répétés.

Recomposer une entrée de journal divisée

Pour réassembler un ensemble de journaux fractionnés, procédez comme suit :

  1. Triez l'ensemble des journaux d'audit fractionnés par LogEntry.split.index dans l'ordre croissant.

  2. Créez une copie du premier journal fractionné, où LogEntry.split.index == 0. Cette copie correspond au début du journal réassemblé.

  3. Pour les autres entrées de journal, itérez sur tous les champs séparables de protoPayload et procédez comme suit pour chaque champ :

    1. Si le champ existe déjà dans le journal réassemblé, ajoutez le contenu de ce champ dans le journal réassemblé.

    2. Si le champ n'existe pas dans le journal réassemblé, copiez-le dans la bûche reassemblée

      Lors de la division, les champs répétés conservent l'index de leurs éléments. Vous pouvez donc appliquer ces étapes au niveau de l'élément lorsque vous réassemblez un champ répété.

  4. Après avoir itéré sur les champs séparables, effacez LogEntry.split du journal réassemblé.

  5. Supprimez le suffixe .0 du LogEntry.insert_id du journal réassemblé.

Exemples de requêtes

Pour rechercher toutes les entrées de journal qui ont été divisées à partir de la même entrée de journal d'origine, exécutez la requête suivante dans l'explorateur de journaux, en remplaçant la variable UID par la valeur souhaitée :

split.uid="UID"

Exemple :

split.uid="abc123"

Pour rechercher toutes les entrées de journal faisant partie d'un fractionnement, exécutez la requête suivante:

split:*

Filtrer les journaux d'audit fractionnés

Vous pouvez exclure tous les journaux d'audit fractionnés d'une requête à l'aide du filtre suivant :

split.totalSplits = 0

Vous pouvez également n'inclure que la première entrée d'un journal d'audit fractionné et exclure le reste des entrées à l'aide du filtre suivant :

split.index = 0

Exemple de fractionnement d'une entrée de journal

L'exemple suivant montre une entrée de journal d'audit avant qu'elle ne soit divisée en quatre nouvelles entrées de journal. Les nouvelles entrées montrent comment les différents champs sont gérés dans l'opération de fractionnement.

Entrée de journal d'audit surdimensionnée avant le fractionnement

{
  "insertId": "567",
  "logName": "projects/1234/logs/cloudaudit.googleapis.com%2Fdata_access",
  "resource": {
    "type": "audited_resource"
  },
  "protoPayload": {
    "serviceName": "example.googleapis.com",
    "methodName": "google.cloud.example.ExampleMethod",
    "resourceName": "projects/1234/resources/123",
    "status": {
      "code": 0
    },
    "authenticationInfo": {
      "principalEmail": "user@example_company.com"
    },
    "authorizationInfo": [
      {
        "resource": "example.googleapis.com/projects/1234/resources/123",
        "permission": "examples.get",
        "granted": "true"
      }
    ],
    "request" {
      "boolField": true,
      "numberField": 123,
      "stringField": "Very long string that needs 2 log entries.",
      "structField": {
        "nestedNumberField": 1337,
        "nestedStringField": "Another long string that needs 2 log entries.",
      },
      "listField" [
        {"value": "short 1"},
        {"value": "Yet another long string."},
        {"value": "short 2"},
        {"value": "short 3"},
      ]
    }
  }
}

Entrée de journal d'audit surdimensionnée après division

L'entrée de journal d'origine est divisée en entrées suivantes. Notez que chaque entrée inclut l'objet split avec un uid et une valeur totalSplits pour 4. Chaque entrée a une valeur split.index de 0, 1, 2 ou 3, qui indique l'ordre des entrées de journal fractionnées.

Entrée de journal fractionnée, index 0

Voici la première entrée de journal fractionné, avec la valeur split.index 0.

{
  "insertId": "567.0",
  "logName": "projects/1234/logs/cloudaudit.googleapis.com%2Fdata_access",
  "resource": {
    "type": "audited_resource"
  },
  "split": { 
    "uid": "789+2022-02-22T12:22:22.22+05:00",
    "index": 0,
    "totalSplits": 4,
  },
  "protoPayload": {
    // The following fields are included in all split entries
    "serviceName": "example.googleapis.com",
    "methodName": "google.cloud.example.ExampleMethod",
    "resourceName": "projects/1234/resources/123",
    "status": {
      "code": 0
    },
    "authenticationInfo": {  // small size; included in all split entries
      "principalEmail": "user@example_company.com"
    },
   // The following field is included in this split entry only.
   "authorizationInfo": [
      {
        "resource": "spanner.googleapis.com/projects/1234/datasets/123",
        "permission": "databases.read",
        "granted": "true"
      }
    ],
    // The following field is split across all the split entries
    "request" { 
      // boolField and numberField can only be in one split.
      "boolField": true,
      "numberField": 123,
      // Split with the next LogEntry.
      "stringField": "Very long string that ",
    }
  }
}

Diviser l'entrée de journal, index 1

Voici la prochaine entrée de journal de fractionnement, avec une valeur split.index de 1.

{
  "insertId": "567.1",
  "logName": "projects/1234/logs/cloudaudit.googleapis.com%2Fdata_access",
  "resource": {
    "type": "audited_resource"
  },
  "split": { 
    "uid": "567+2022-02-22T12:22:22.22+05:00",
    "index": 1,
    "totalSplits": 4,
  },
  "protoPayload": { 
    "serviceName": "example.googleapis.com",
    "methodName": "google.cloud.example.ExampleMethod",
    "resourceName": "projects/1234/resources/123",
    "status": {
      "code": 0
    },
    "authenticationInfo": {
      "principalEmail": "user@example_company.com"
    },
    "request" { 
      // boolField and numberField aren't present
      // Continued from the previous entry.
      "stringField": "needs 2 log entries.",
      "structField": { 
        "nestedNumberField": 1337,
        // Split with the next LogEntry.
        "nestedStringField": "Another long string ",
      }
    }
  }
}

Diviser l'entrée de journal, index 2

Voici l'entrée de journal de fractionnement suivante, avec une valeur split.index de 2.

{
  "insertId": "567.2",
  "logName": "projects/1234/logs/cloudaudit.googleapis.com%2Fdata_access",
  "resource": {
    "type": "audited_resource"
  },
  "split": { 
    "uid": "567+2022-02-22T12:22:22.22+05:00",
    "index": 2,
    "totalSplits": 4,
  },
  "protoPayload": { 
    "serviceName": "example.googleapis.com",
    "methodName": "google.cloud.example.ExampleMethod",
    "resourceName": "projects/1234/resources/123",
    "status": {
      "code": 0
    },
    "authenticationInfo": {
      "principalEmail": "user@example_company.com"
    },
    request { 
      "structField": { 
        // Continued from the previous entry.
        "nestedStringField": "that needs 2 log entries.",
      }
      "listField" [ 
         {"value": "short 1"},
         {"value": "Yet another "}, // Split with the next LogEntry.
        // Missing two values, split with the next LogEntry.
      ]
    }
  }
}

Entrée de journal fractionnée, indice 3

Voici l'entrée de journal de division finale, avec une valeur split.index de 3.

{
  "insertId": "567.3",
  "logName": "projects/1234/logs/cloudaudit.googleapis.com%2Fdata_access",
  "resource": {
    "type": "audited_resource"
  },
  "split": { 
    "uid": "567+2022-02-22T12:22:22.22+05:00",
    "index": 3,
    "totalSplits": 4,
  },
  "protoPayload": { 
    "serviceName": "example.googleapis.com",
    "methodName": "google.cloud.example.ExampleMethod",
    "resourceName": "projects/1234/resources/123",
    "status": {
      "code": 0
    },
    "authenticationInfo": {
      "principalEmail": "user@example_company.com"
    },
    "request" { 
      "listField" [ 
        {}, // Padding to ensure correct positioning of elements in split repeated fields.
         {"value": "long string."}, // Continuation of the second repeated field.
         {"value": "short 2"},
         {"value": "short 3"},
      ]
    }
  }
}