Dividir entradas de registro de auditoria

Neste documento, descrevemos como o Cloud Logging divide as entradas de registro de auditoria grandes e oferece orientações sobre como remontar esses registros de auditoria divididos.

Quando uma única entrada de registro de auditoria excede o limite de tamanho, o Cloud Logging divide essa entrada e distribui os dados contidos na entrada original do registro de auditoria em várias entradas. Os usuários podem querer remontar os registros de auditoria divididos, já que as entradas de registro divididas individuais não contêm todos os campos do registro de auditoria original.

Como reconhecer entradas de registro de auditoria divididas

As entradas de registro divididas contêm informações sobre a entrada original de onde foram divididas. Se uma entrada de registro tiver um campo split, ela será o resultado da divisão de uma entrada de registro original maior. O campo split é um objeto LogSplit que contém as informações necessárias para identificar entradas de registro divididas relacionadas.

Cada entrada de registro de divisão contém os seguintes campos:

  • split.uid: um identificador exclusivo para o grupo de entradas de registro que foram divididas de uma entrada de registro original comum. O valor desse campo é o mesmo para todas as entradas divididas da entrada de registro original.

  • split.index: a posição dessa entrada na série de entradas divididas. A primeira entrada da divisão tem o índice 0. split.index também é anexado ao campo LogEntry.insertId.

  • split.totalSplits: o número de entradas de registro em que a entrada de registro original foi dividida. O valor desse campo é o mesmo para todas as entradas divididas da entrada de registro original.

Como uma entrada de registro é dividida

Quando uma entrada de registro de auditoria grande é dividida, os campos são distribuídos entre as entradas de registro divididas resultantes da seguinte maneira:

  • Todos os campos, exceto protoPayload, são duplicados em cada entrada dividida.

  • Os seguintes subcampos protoPayload podem ser divididos em várias entradas:

    • protoPayload.metadata
    • protoPayload.request
    • protoPayload.response
  • Todos os outros subcampos protoPayload são incluídos em todas as entradas divididas.

  • Para os subcampos protoPayload.metadata, protoPayload.request e protoPayload.response, os seguintes tipos de campo podem ser divididos em várias entradas:

Se um campo for membro de um campo divisível, mas não for um dos tipos de campo divisível, ele só vai estar presente em um dos registros de divisão.

Por exemplo, um campo booleano no subcampo protoPayload.request só pode aparecer em uma entrada de registro dividida, mas um campo de string no subcampo protoPayload.request pode ter o conteúdo dividido em várias entradas de registro divididas.

Para conferir um exemplo de como uma entrada longa é dividida, consulte Exemplo de divisão de entrada de registro.

Campos repetidos com muitos valores

Quando o valor do campo protoPayload.metadata, protoPayload.request ou protoPayload.response contém uma lista de valores repetidos, a lista pode ser dividida e distribuída em várias entradas de registro divididas.

Por exemplo, a lista de valores ["foo", "bar", "baz"] pode ser dividida em duas listas: ["foo", "ba"] e ["", "r", "baz"]. A primeira lista é a entrada com o split.index de 0, e a segunda lista está na entrada com split.index de 1. A segunda lista começa com uma string vazia para manter as posições dos elementos na lista e indicar que os elementos nas mesmas posições nas diferentes listas precisam ser unidos. No exemplo, ba é o segundo elemento da lista na entrada 0, e r é o segundo elemento da lista na entrada 1. Portanto, eles são recombinados na ordem bar ao remontar a lista original.

Campos grandes e não repetidos

Quando campos Struct e string grandes e não repetidos são divididos, eles são tratados da seguinte maneira:

  • Um campo string é dividido no nível do caractere, não no nível do byte. Assim, os caracteres de vários bytes não são alterados.

  • LogEntry.split.index controla a ordem do conteúdo de campos divididos não repetidos.

Refazer a entrada de registro dividida

Para remontar um conjunto de registros divididos, siga estas etapas:

  1. Ordene o conjunto de registros de auditoria divididos por LogEntry.split.index em ordem crescente.

  2. Crie uma cópia do primeiro registro de divisão, onde LogEntry.split.index == 0. Essa cópia é o início do registro remontado.

  3. Para as entradas de registro restantes, itere por todos os campos divisíveis de protoPayload e siga as etapas a seguir para cada campo:

    1. Se o campo já existir no registro remontado, anexe o conteúdo dele ao registro remontado.

    2. Se o campo não existir no registro remontado, copie-o para o registro remontado

      Quando divididos, os campos repetidos preservam o índice dos elementos. Assim, é possível aplicar essas etapas no nível do elemento ao remontar um campo repetido.

  4. Depois de iterar pelos campos divisíveis, limpe LogEntry.split do registro remontado.

  5. Remova o sufixo .0 do LogEntry.insert_id do registro remontado.

Amostras de consultas

Para encontrar todas as entradas de registro que foram divididas da mesma entrada de registro original, execute a consulta a seguir no Explorador de registros, substituindo a variável UID pelo valor desejado:

split.uid="UID"

Exemplo:

split.uid="abc123"

Para encontrar todas as entradas de registro que fazem parte de qualquer divisão, execute a seguinte consulta:

split:*

Filtrar registros de auditoria divididos

Para excluir todos os registros de auditoria divididos de uma consulta, use o seguinte filtro:

split.totalSplits = 0

Também é possível incluir apenas a primeira entrada de um registro de auditoria dividido e excluir o restante das entradas usando o seguinte filtro:

split.index = 0

Exemplo de divisão de entrada de registro

O exemplo a seguir mostra uma entrada de registro de auditoria antes de ser dividida em quatro novas entradas de registro. As novas entradas mostram como campos diferentes são processados na operação de divisão.

Entrada de registro de auditoria grande antes da divisão

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

Entrada de registro de auditoria grande após a divisão

A entrada de registro original é dividida nas seguintes entradas. Cada entrada inclui o objeto split com um uid e um valor totalSplits de 4. Cada entrada tem um valor split.index de 0, 1, 2 ou 3, que indica a ordem das entradas de registro divididas.

Entrada de registro dividida, índice 0

Esta é a primeira entrada de registro de divisão, com um valor de split.index de 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 ",
    }
  }
}

Entrada de registro dividida, índice 1

Esta é a próxima entrada de registro de divisão, com um valor de 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 ",
      }
    }
  }
}

Entrada de registro dividida, índice 2

Esta é a próxima entrada de registro de divisão, com um valor de 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.
      ]
    }
  }
}

Entrada de registro dividida, índice 3

Esta é a entrada de registro de divisão final, com um valor de 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"},
      ]
    }
  }
}