Dividir las entradas del registro de auditoría

En este documento se describe cómo divide Cloud Logging las entradas de registro de auditoría de gran tamaño y se explica cómo volver a montar estos registros de auditoría divididos.

Cuando una sola entrada de registro de auditoría supera el límite de tamaño, Registros de Cloud divide esa entrada y distribuye los datos que contiene en varias entradas. Es posible que los usuarios quieran volver a montar los registros de auditoría divididos, ya que las entradas de registro divididas no contienen todos los campos del registro de auditoría original.

Reconocer las entradas de registro de auditoría divididas

Las entradas de registro divididas contienen información sobre la entrada original de la que se han dividido. Si una entrada de registro contiene un campo split, significa que la entrada es el resultado de dividir una entrada de registro original más grande. El campo split es un objeto LogSplit que contiene la información necesaria para identificar las entradas de registro divididas relacionadas.

Cada entrada de registro dividida contiene los siguientes campos:

  • split.uid: identificador único del grupo de entradas de registro que se han dividido a partir de una entrada de registro original común. El valor de este campo es el mismo para todas las entradas divididas de la entrada de registro original.

  • split.index: la posición de esta entrada en la serie de entradas divididas. La primera entrada de la división tiene el índice 0. split.index también se añade al campo LogEntry.insertId.

  • split.totalSplits: el número de entradas de registro en las que se ha dividido la entrada de registro original. El valor de este campo es el mismo en todas las entradas divididas de la entrada de registro original.

Cómo se divide una entrada de registro

Cuando se divide una entrada de registro de auditoría de gran tamaño, los campos se distribuyen entre las entradas de registro divididas resultantes de la siguiente manera:

  • Todos los campos, excepto el campo protoPayload, se duplican en cada entrada dividida.

  • Los siguientes protoPayloadsubcampos se pueden dividir en varias entradas:

    • protoPayload.metadata
    • protoPayload.request
    • protoPayload.response
  • Todos los demás subcampos protoPayload se incluyen en todas las entradas divididas.

  • En el caso de los subcampos protoPayload.metadata, protoPayload.request y protoPayload.response, los siguientes tipos de campos se pueden dividir en varias entradas:

Si un campo es miembro de un campo divisible, pero no es uno de los tipos de campo divisibles, solo estará presente en uno de los registros divididos.

Por ejemplo, un campo booleano del subcampo protoPayload.request solo puede aparecer en una entrada de registro dividida, pero un campo de cadena del subcampo protoPayload.request puede tener su contenido dividido en varias entradas de registro divididas.

Para ver un ejemplo de cómo se divide una entrada larga, consulta Ejemplo de división de una entrada de registro.

Campos repetidos con muchos valores

Cuando el valor de los campos protoPayload.metadata, protoPayload.request o protoPayload.response contiene una lista de valores repetidos, la lista puede dividirse y distribuirse en varias entradas de registro divididas.

Por ejemplo, la lista de valores ["foo", "bar", "baz"] se puede dividir en dos listas: ["foo", "ba"] y ["", "r", "baz"]. La primera lista es la entrada con el split.index de 0, y la segunda lista es la entrada con el split.index de 1. La segunda lista empieza con una cadena vacía para mantener las posiciones de los elementos de la lista e indicar que los elementos que ocupan las mismas posiciones en las distintas listas deben combinarse. En el ejemplo, ba es el segundo elemento de la lista de la entrada 0 y r es el segundo elemento de la lista de la entrada 1, por lo que se vuelven a combinar en el orden bar al volver a montar la lista original.

Campos grandes no repetidos

Cuando se dividen los campos Struct y string grandes y no repetidos, estos campos se gestionan de la siguiente manera:

  • Un campo string se divide a nivel de carácter, no de byte. Por lo tanto, los caracteres multibyte no se modifican.

  • LogEntry.split.index controla el orden del contenido de los campos divididos y no repetidos.

Reconstruir una entrada de registro dividida

Para volver a montar un conjunto de registros divididos, sigue estos pasos:

  1. Ordena el conjunto de registros de auditoría divididos por LogEntry.split.index en orden ascendente.

  2. Crea una copia del primer registro dividido, donde LogEntry.split.index == 0. Esta copia es el principio del registro reensamblado.

  3. En el resto de las entradas de registro, itera por todos los campos divisibles de protoPayload y sigue estos pasos para cada campo:

    1. Si el campo ya existe en el registro reensamblado, añade el contenido de ese campo al registro reensamblado.

    2. Si el campo no existe en el registro reensamblado, cópialo en el registro reensamblado.

      Cuando se dividen, los campos repetidos conservan el índice de sus elementos, por lo que puede aplicar estos pasos a nivel de elemento al volver a ensamblar un campo repetido.

  4. Después de iterar por los campos que se pueden dividir, borra LogEntry.split del registro reensamblado.

  5. Quita el sufijo .0 del LogEntry.insert_id del registro reensamblado.

Consultas de ejemplo

Para encontrar todas las entradas de registro que se han dividido a partir de la misma entrada de registro original, ejecuta la siguiente consulta en el Explorador de registros después de sustituir la variable UID por el valor elegido:

split.uid="UID"

Por ejemplo:

split.uid="abc123"

Para encontrar todas las entradas de registro que forman parte de cualquier división, ejecuta la siguiente consulta:

split:*

Filtrar los registros de auditoría divididos

Para excluir todos los registros de auditoría divididos de una consulta, usa el siguiente filtro:

split.totalSplits = 0

También puede incluir solo la primera entrada de un registro de auditoría dividido y excluir el resto de las entradas mediante el siguiente filtro:

split.index = 0

Ejemplo de división de una entrada de registro

En el siguiente ejemplo se muestra una entrada de registro de auditoría antes de dividirse en cuatro entradas nuevas. Las nuevas entradas muestran cómo se gestionan los diferentes campos en la operación de división.

Entrada de registro de auditoría de gran tamaño antes de dividirse

{
  "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 auditoría de tamaño excesivo después de dividirla

La entrada de registro original se divide en las siguientes entradas. Ten en cuenta que cada entrada incluye el objeto split con un valor uid y un valor totalSplits de 4. Cada entrada tiene un valor split.index de 0, 1, 2 o 3, que indica el orden de las entradas de registro divididas.

Entrada de registro dividida, índice 0

Esta es la primera entrada de registro dividida, con un 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

Aquí tienes la siguiente entrada de registro dividida, con un valor 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

Aquí tienes la siguiente entrada de registro dividida, con un valor 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.
      ]
    }
  }
}

Dividir entrada de registro, índice 3

Esta es la entrada de registro final dividida, con un 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"},
      ]
    }
  }
}