Registro estructurado

En este documento, se analiza el concepto de registro estructurado y los métodos para agregar estructura a los campos de carga útil de entrada de registro. Cuando se formatea la carga útil del registro como un objeto JSON, y ese objeto se almacena en el campo jsonPayload, la se denomina registro estructurado. Para estos registros, puedes crear consultas que buscan rutas de JSON específicas y puedes indexar campos específicos en el carga útil de registro. En cambio, cuando la carga útil del registro tiene el formato de una cadena almacenado en el campo textPayload, la entrada de registro es no estructurada. Puedes realizar búsquedas en el campo de texto, pero no puedes indexar su contenido.

Para crear entradas de registro estructuradas, realiza una de las siguientes acciones:

  • Llama al método de la API entries.write y suministra un elemento LogEntry con formato completo
  • Usar una biblioteca cliente de Cloud Logging que escribe registros estructurados.
  • Usa el comando gcloud logging write.
  • Usa el servicio de BindPlane.
  • Usa un agente para escribir registros:

    • Algunos servicios de Google Cloud contienen un agente de Logging integrado que envía los datos escritos en stdout o stderr como registros en Cloud Logging Puedes usar este enfoque para los servicios de Google Cloud, como Google Kubernetes Engine, el entorno flexible de App Engine y las funciones de Cloud Run.

    • Para las máquinas virtuales (VMs) de Compute Engine, puedes instalar y configurar el Agente de operaciones o el agente de Logging heredado y, luego, usa el agente instalado para enviar registros a Cloud Logging.

Para obtener más información sobre estos enfoques, consulta las siguientes secciones.

Escribe registros mediante bibliotecas cliente o la API

Puedes escribir datos de registro usando bibliotecas cliente de Cloud Logging, que llamar a la API de Cloud Logging o llamando directamente a la API de Cloud Logging. Las bibliotecas cliente pueden simplificar la propagación de los campos JSON especiales, ya que capta automáticamente cierta información y proporciona interfaces para completar correctamente los campos. Sin embargo, para tener un control total del de tus cargas útiles, llama directamente a la API de Cloud Logging y pasa el Estructura completa de LogEntry a la API de Cloud Logging

Para obtener más información, consulta la referencia entries.write.

Para ver ejemplos de código, consulta Escribe registros estructurados.

Escribe registros con gcloud CLI

Puedes escribir datos de registro con gcloud CLI. La interfaz admite registros no estructurados y registros estructurados. Cuando quieras escribir un registro estructurado, proporcionan al comando un objeto JSON serializado.

Para ver una guía de inicio rápido, consulta Escribe y consulta entradas de registro con Google Cloud CLI.

Para ver ejemplos de código, consulta la Referencia de gcloud logging write.

Escribe registros con BindPlane

Puedes usar el servicio de BindPlane para enviar registros a Logging. Para estos registros, las cargas útiles están en formato JSON y se estructuran según el sistema de origen. Para obtener información sobre búsqueda y visualización de registros transferidos mediante BindPlane, consulta el documento Guía de inicio rápido.

Escribe registros con un agente

Para obtener registros de tus instancias de Compute Engine, puedes usar el Agente de operaciones o el agente de Cloud Logging heredado. Ambos agentes pueden recopilar métricas de aplicaciones de terceros y ambas admiten registros estructurados:

  • El agente de operaciones es el agente recomendado para coleccionar telemetría de tus instancias de Compute Engine. Este agente combina de registro y métricas en un único agente, proporciona configuración del servidor y cuenta con registros de alta capacidad de procesamiento.

    Para obtener información sobre cómo configurar el Agente de operaciones para que admita registros estructurados o para personalizar la forma de un registro estructurado, consulta Configura el Agente de operaciones.

  • El agente de Cloud Logging heredado recopila los registros del sistema operativo. Este agente no recopila otras formas de telemetría.

El resto de esta sección es específico agente de Logging heredado.

Agente de Logging: Campos JSON especiales

Algunos campos del objeto JSON son reconocidos como especiales por el de agente de Logging heredado y extraído del Estructura de LogEntry. Estos campos JSON especiales se pueden usar para configurar los siguientes campos en LogEntry:

  • severity
  • spanId
  • labels definido por el usuario
  • httpRequest

Como JSON es más preciso y versátil que las líneas de texto, puedes usar JSON objetos para escribir mensajes de varias líneas y agregar metadatos.

Crear entradas de registro estructuradas para tus aplicaciones con la consulta la siguiente tabla, que enumera los campos y sus valores en JSON:

Campo de registro JSON LogEntry Campo Función del agente de Cloud Logging Valor de ejemplo
severity severity El agente de Logging intenta hacer coincidir una variedad de strings de gravedad común, que incluye la lista de strings LogSeverity reconocidas por la API de Logging. "severity":"ERROR"
message textPayload (o parte de jsonPayload) El mensaje que aparece en la línea de entrada de registro en el Explorador de registros. "message":"There was an error in the application."

Nota: message se guarda como textPayload si es el único campo restante después de que el agente de Logging mueve los otros campos de propósito especial y detect_json no se habilitó; de lo contrario message permanece en jsonPayload. detect_json no es aplicable a entornos de registro administrados como Google Kubernetes Engine. Si tu entrada de registro contiene un seguimiento de pila de excepciones, esa pila se debe establecer en este campo de registro JSON message para que se pueda analizar y guardar en Error Reporting.
log (solo Google Kubernetes Engine heredado) textPayload Solo se aplica a Google Kubernetes Engine heredado: si después de mover los campos con propósito especial solo queda un campo log, ese campo se guarda como textPayload.
httpRequest httpRequest Un registro estructurado en el formato del campo LogEntry HttpRequest. "httpRequest":{"requestMethod":"GET"}
campos relacionados con la hora timestamp Para obtener más información, consulta Campos relacionados con la hora. "time":"2020-10-12T07:20:50.52Z"
logging.googleapis.com/insertId insertId Para obtener más información, consulta insertId en la página LogEntry. "logging.googleapis.com/insertId":"42"
logging.googleapis.com/labels labels El valor de este campo debe ser un registro estructurado. Para obtener más información, consulta labels en la página LogEntry. "logging.googleapis.com/labels": {"user_label_1":"value_1","user_label_2":"value_2"}
logging.googleapis.com/operation operation El Explorador de registros también usa el valor de este campo para agrupar entradas de registro relacionadas. Para obtener más información, consulta operation en la página LogEntry. "logging.googleapis.com/operation": {"id":"get_data","producer":"github.com/MyProject/MyApplication", "first":"true"}
logging.googleapis.com/sourceLocation sourceLocation Información de ubicación del código fuente asociada con la entrada de registro, si la hay. Para obtener más información, consulta LogEntrySourceLocation en la página LogEntry. "logging.googleapis.com/sourceLocation": {"file":"get_data.py","line":"142","function":"getData"}
logging.googleapis.com/spanId spanId El ID de intervalo dentro del seguimiento asociado a la entrada de registro. Para obtener más información, consulta spanId en la página LogEntry. "logging.googleapis.com/spanId":"000000000000004a"
logging.googleapis.com/trace trace El nombre del recurso del seguimiento asociado a la entrada de registro, si corresponde. Para obtener más información, consulta trace en la página LogEntry. "logging.googleapis.com/trace":"projects/my-projectid/traces/0679686673a"

Nota: Si no escribes en stdout o stderr, el valor de este campo debe tener el formato projects/[PROJECT-ID]/traces/[TRACE-ID], por lo que el Explorador de registros y el visor de seguimiento lo pueden usar para agrupar entradas de registro y mostrarlas alineadas con seguimientos. Si autoformat_stackdriver_trace es verdadero y [V] coincide con el formato del traceId de ResourceTrace, el campo trace de LogEntry tiene el valor projects/[PROJECT-ID]/traces/[V].
logging.googleapis.com/trace_sampled traceSampled El valor de este campo debe ser true o false. Para obtener más información, consulta traceSampled en la página LogEntry. "logging.googleapis.com/trace_sampled": false

Para crear entradas de registro en el formato simplificado, crea una representación JSON de la entrada usando los campos. Todos los campos son opcionales.

El siguiente es un ejemplo de una entrada de registro JSON simplificada:

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

El siguiente es un ejemplo de la entrada de registro resultante:

{
  "insertId": "42",
  "jsonPayload": {
    "message": "There was an error in the application",
    "times": "2020-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"
}

Agente de Logging: configuración

El agente de Logging heredado, google-fluentd, es un Empaquetado específico de Cloud Logging del Recopilador de datos de registro Fluentd. El agente de Logging viene con la configuración de Fluentd predeterminada y usa los complementos de entrada de Fluentd para extraer registros de eventos de fuentes externas, como archivos en disco, o analizar los registros entrantes.

Fluentd tiene una lista de analizadores compatibles que extraen registros y los convierten en cargas útiles estructuradas (JSON).

Si configuras una fuente de registro con format [PARSER_NAME], puedes compilar a partir del de los analizadores integrados que proporciona Fluentd. Para obtener información sobre cómo configurar el agente de Logging heredado, consulta Configura el agente de Logging.

En las siguientes muestras de código, se observa la configuración de Fluentd, el registro de entrada y la carga útil estructurada de salida, que es parte de una entrada de registro de Cloud Logging:

  • Configuración de 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>
    
  • Registro (entrada):

      <6>Feb 28 12:00:00 192.168.0.1 fluentd[11111]: [error] Syslog test
    
  • Carga útil estructurada (salida):

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

Para obtener más información sobre cómo funciona el analizador syslog, consulta la documentación de Fluentd.

Agente de Logging: Analizadores estándar habilitados de forma predeterminada

En la siguiente tabla, se incluyen los analizadores estándar incluidos en el agente si habilitas el registro estructurado:

Nombre del analizador Archivo de configuración
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

Para obtener instrucciones sobre cómo habilitar el registro estructurado al instalar el agente de Logging heredado, consulta la Instalación.

Agente de Logging: instalación

Para habilitar el registro estructurado, debes cambiar la configuración predeterminada de el agente de Logging heredado cuando lo instalas o lo reinstalas. La habilitación del registro estructurado reemplaza los archivos de configuración enumerados anteriormente. pero no cambia la operación del agente.

Cuando habilitas el registro estructurado, los registros de la lista se convierten en entradas de registro con formatos distintos a los que tenían antes de que habilitaras los registros estructurados. Si los registros se enrutan a destinos fuera de Logging, el cambio podría afectar a cualquier aplicación de procesamiento posterior. Por ejemplo, si enrutas registros a BigQuery, BigQuery rechaza las nuevas entradas de registro por el resto del día como si tuvieran esquema incorrecto.

Para obtener instrucciones sobre cómo instalar el agente de Logging heredado y para habilitar los registros estructurados, consulta Instalación .

Puedes encontrar los archivos de configuración del agente de Logging heredado en /etc/google-fluentd/config.d/, que ahora debe incluir el elemento Analizadores estándar habilitados de forma predeterminada.

Agente de Logging: Configura el formato de registro de acceso de Apache

De forma predeterminada, el agente de Logging heredado almacena el acceso de Apache datos de registro en el campo jsonPayload. Por ejemplo:

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

Como alternativa, puedes configurar el agente de Logging heredado para extraer ciertos campos al campo httpRequest Por ejemplo:

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

Configurar el campo httpRequest, como se muestra en el ejemplo anterior, ayuda seguimiento: la consola de Google Cloud presenta todos los registros de una solicitud HTTP determinada en una jerarquía superior-secundario.

Para configurar esta extracción, agrega lo siguiente al final de tu /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>

Para obtener más detalles sobre cómo configurar tus entradas de registro, consulta Modifica los registros.

Agente de Logging: Configura el formato de registro de acceso de nginx

De forma predeterminada, el agente de Logging heredado almacena el acceso de nginx datos de registro en el campo jsonPayload. Por ejemplo:

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

Como alternativa, puedes configurar el agente de Logging heredado para extraer ciertos campos al campo httpRequest Por ejemplo:

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

Configurar el campo httpRequest, como se muestra en el ejemplo anterior, ayuda seguimiento: la consola de Google Cloud presenta todos los registros de una solicitud HTTP determinada en una jerarquía superior-secundario.

Para configurar esta extracción, agrega lo siguiente al final de tu /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>

Para obtener más detalles sobre cómo configurar tus entradas de registro, consulta Modifica los registros.

Escribe tu propio analizador

Si tus registros no son compatibles con los analizadores estándar, puedes escribir el tuyo. Los analizadores consisten en una expresión regular usada para unir registros y aplicar etiquetas a las partes.

Los siguientes ejemplos de código muestran una línea en el registro, una configuración con una expresión regular que indique el formato de la línea de registro y los entrada de registro almacenado:

  • Una línea de registro en este:

    REPAIR CAR $500
    
  • Una configuración con una expresión regular que indica el formato de la línea de registro:

    $ 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>
    
  • La entrada de registro resultante:

    {
    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:  "2023-03-21T01:47:11.475065313Z"
    resource: {
      labels: {
        instance_id:  "3914079432219560274"
        project_id:  "my-sample-project-12345"
        zone:  "us-central1-c"
      }
      type:  "gce_instance"
    }
    timestamp:  "2023-03-21T01:47:05.051902169Z"
    }
    

Soluciona problemas

Para solucionar problemas habituales que se encuentran al instalar la aplicación o al interactuar con el servicio, agente de Logging heredado, consulta Solucionar problemas del agente.

¿Qué sigue?