Registo estruturado

Este documento aborda o conceito de registo estruturado e os métodos para adicionar estrutura aos campos de payload das entradas de registo. Quando o payload do registo é formatado como um objeto JSON e esse objeto é armazenado no campo jsonPayload, a entrada do registo é denominada registo estruturado. Para estes registos, pode criar consultas que pesquisem caminhos JSON específicos e pode indexar campos específicos no payload do registo. Por outro lado, quando o payload do registo é formatado como uma string e armazenado no campo textPayload, a entrada do registo é não estruturada. Pode pesquisar o campo de texto, mas não pode indexar o respetivo conteúdo.

Para criar entradas de registo estruturadas, faça qualquer uma das seguintes ações:

  • Chame o método da API entries.write e forneça um LogEntry totalmente formatado.
  • Use o comando gcloud logging write.
  • Use uma biblioteca cliente do Cloud Logging que escreve registos estruturados.
  • Use o serviço BindPlane.
  • Use um agente para escrever registos:

    • Alguns Google Cloud serviços contêm um agente de registo integrado que envia os dados escritos para stdout ou stderr como registos para o Cloud Logging. Pode usar esta abordagem para Google Cloud serviços como o Google Kubernetes Engine, o ambiente flexível do App Engine e as funções do Cloud Run.

    • Para máquinas virtuais (VMs) do Compute Engine, pode instalar e configurar o agente Ops ou o agente Logging antigo e, em seguida, usar o agente instalado para enviar registos para o Cloud Logging.

Para mais informações acerca destas abordagens, consulte as secções seguintes.

Escreva registos através das bibliotecas cliente ou da API

Pode escrever dados de registo através das bibliotecas cliente do Cloud Logging, que chamam a API Cloud Logging, ou chamando diretamente a API Cloud Logging. As bibliotecas de cliente podem simplificar o preenchimento dos campos JSON especiais capturando automaticamente algumas informações e fornecendo interfaces para preencher os campos adequadamente. No entanto, para ter controlo total sobre a estrutura dos seus payloads, chame diretamente a API Cloud Logging e transmita a estrutura LogEntry completa para a API Cloud Logging.

Para mais informações, consulte a referência entries.write.

Para ver exemplos de código, consulte o artigo Escrever registos estruturados.

Escreva registos através da CLI gcloud

Pode escrever dados de registo através da CLI gcloud. A interface suporta registos não estruturados e registos estruturados. Quando quiser escrever um registo estruturado, forneça ao comando um objeto JSON serializado.

Para um início rápido, consulte o artigo Escreva e consulte entradas de registo com a CLI do Google Cloud.

Para ver exemplos de código, consulte a referência de gcloud logging write.

Escreva registos com o BindPlane

Pode usar o serviço BindPlane para enviar registos para o Logging. Para estes registos, as cargas úteis estão no formato JSON e são estruturadas de acordo com o sistema de origem. Para obter informações sobre como encontrar e ver registos carregados através do BindPlane, consulte o guia de início rápido do BindPlane.

Escreva registos usando um agente

Para obter registos das suas instâncias do Compute Engine, pode usar o agente Ops ou o agente do Cloud Logging antigo. Ambos os agentes podem recolher métricas de aplicações de terceiros e ambos oferecem suporte para registo estruturado:

  • O agente Ops é o agente recomendado para recolher telemetria das suas instâncias do Compute Engine. Este agente combina o registo e as métricas num único agente, oferece uma configuração baseada em YAML e inclui registo de elevado débito.

    Para ver informações sobre como configurar o agente Ops para suportar o registo estruturado ou personalizar o formulário de um registo estruturado, consulte o artigo Configure o agente Ops.

  • O agente do Cloud Logging antigo recolhe registos. Este agente não recolhe outras formas de telemetria.

O restante desta secção é específico do agente de registo antigo.

Agente de registos: campos JSON especiais

Alguns campos no objeto JSON são reconhecidos como especiais pelo agente de registo antigo e extraídos para a estrutura LogEntry. Estes campos JSON especiais podem ser usados para definir os seguintes campos em LogEntry:

  • severity
  • spanId
  • labels definida pelo utilizador
  • httpRequest

Uma vez que o JSON é mais preciso e versátil do que as linhas de texto, pode usar objetos JSON para escrever mensagens de várias linhas e adicionar metadados.

Para criar entradas de registo estruturadas para as suas aplicações através do formato simplificado, consulte a tabela seguinte, que lista os campos e os respetivos valores em JSON:

Campo de registo JSON LogEntry campo Função do agente do Cloud Logging Valor de exemplo
severity severity O agente Logging tenta encontrar correspondência com várias strings de gravidade comuns, incluindo a lista de strings LogSeverity reconhecidas pela API Logging. "severity":"ERROR"
message textPayload (ou parte de jsonPayload) A mensagem que aparece na linha de entrada do registo no Logs Explorer. "message":"There was an error in the application."

Nota: message é guardado como textPayload se for o único campo restante após o agente de registo mover os outros campos de fins especiais e detect_json não tiver sido ativado; caso contrário, message permanece em jsonPayload. detect_json não é aplicável a ambientes de registo geridos, como o Google Kubernetes Engine. Se a entrada do registo contiver um rastreio da pilha de exceções, o rastreio da pilha de exceções deve ser definido neste campo do registo JSON message, para que o rastreio da pilha de exceções possa ser analisado e guardado no Error Reporting.
log(Apenas Google Kubernetes Engine antigo) textPayload Aplica-se apenas ao Google Kubernetes Engine antigo: se, após mover os campos de fins especiais, restar apenas um campo log, esse campo é guardado como textPayload.
httpRequest httpRequest Um registo estruturado no formato do campo LogEntry HttpRequest. "httpRequest":{"requestMethod":"GET"}
campos relacionados com o tempo timestamp Para mais informações, consulte a secção Campos relacionados com o tempo. "time":"2020-10-12T07:20:50.52Z"
logging.googleapis.com/insertId insertId Para mais informações, consulte insertId na página LogEntry. "logging.googleapis.com/insertId":"42"
logging.googleapis.com/labels labels O valor deste campo tem de ser um registo estruturado. Para mais informações, consulte labels na página LogEntry. "logging.googleapis.com/labels": {"user_label_1":"value_1","user_label_2":"value_2"}
logging.googleapis.com/operation operation O valor deste campo também é usado pelo Logs Explorer para agrupar entradas de registo relacionadas. Para mais informações, consulte operation na página LogEntry. "logging.googleapis.com/operation": {"id":"get_data","producer":"github.com/MyProject/MyApplication", "first":"true"}
logging.googleapis.com/sourceLocation sourceLocation Informações de localização do código-fonte associadas à entrada do registo, se existirem. Para mais informações, consulte LogEntrySourceLocation na página LogEntry. "logging.googleapis.com/sourceLocation": {"file":"get_data.py","line":"142","function":"getData"}
logging.googleapis.com/spanId spanId O ID do intervalo na rastreio associado à entrada do registo. Para mais informações, consulte spanId na página LogEntry. "logging.googleapis.com/spanId":"000000000000004a"
logging.googleapis.com/trace trace Nome do recurso do rastreio associado à entrada do registo se existir. Para mais informações, consulte trace na página LogEntry. "logging.googleapis.com/trace":"projects/my-projectid/traces/0679686673a"

Nota: se não estiver a escrever para stdout ou stderr, o valor deste campo deve ser formatado como projects/[PROJECT-ID]/traces/[TRACE-ID], para que possa ser usado pelo Explorador de registos e pelo visualizador de rastreios para agrupar entradas de registo e apresentá-las em linha com os rastreios. Se autoformat_stackdriver_trace for verdadeiro e [V] corresponder ao formato de ResourceTrace, o campo traceId LogEntry tem o valor trace.projects/[PROJECT-ID]/traces/[V]
logging.googleapis.com/trace_sampled traceSampled O valor deste campo tem de ser true ou false. Para mais informações, consulte traceSampled na página LogEntry. "logging.googleapis.com/trace_sampled": false

Para criar entradas de registo no formato simplificado, crie uma representação JSON da entrada através dos campos. Todos os campos são opcionais.

Segue-se um exemplo de uma entrada de registo JSON simplificada:

{
  "severity":"ERROR",
  "message":"There was an error in the application.",
  "httpRequest":{
    "requestMethod":"GET"
  },
  "time":"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
}

Segue-se um exemplo da entrada de registo resultante:

{
  "insertId": "42",
  "jsonPayload": {
    "message": "There was an error in the application",
    "time": "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-10-12T07:20:50.52Z",
  "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-10-12T07:20:57.52Z",
  "spanId": "000000000000004a"
}

Agente de registos: configuração

O agente de registos antigo, google-fluentd, é uma embalagem específica do Cloud Logging do coletor de dados de registo Fluentd. O agente Logging é fornecido com a configuração predefinida do Fluentd e usa plug-ins de entrada do Fluentd para extrair registos de eventos de origens externas, como ficheiros no disco, ou para analisar registos de registos recebidos.

O Fluentd tem uma lista de analisadores suportados que extraem registos e os convertem em payloads estruturados (JSON).

Ao configurar uma origem de registos com format [PARSER_NAME], pode basear-se nos analisadores incorporados fornecidos pelo Fluentd. Para ver informações sobre a configuração do agente Logging antigo, consulte o artigo Configure o agente Logging.

Os seguintes exemplos de código mostram a configuração do Fluentd, o registo de registo de entrada e a carga útil estruturada de saída, que faz parte de uma entrada de registo do Cloud Logging:

  • Configuração do 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>
    
  • Registo de registo (entrada):

      <6>Feb 28 12:00:00 192.168.0.1 fluentd[11111]: [error] Syslog test
    
  • Payload estruturado (resultado):

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

Para mais informações sobre o funcionamento do analisador syslog, consulte a documentação detalhada do Fluentd.

Agente de registos: analisadores padrão ativados por predefinição

A tabela seguinte inclui os analisadores padrão incluídos no agente se ativar o registo estruturado:

Nome do analisador Ficheiro de configuração
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 obter instruções sobre como ativar o registo estruturado ao instalar o agente de registo antigo, consulte a secção Instalação.

Agente de registos: instalação

Para ativar o registo estruturado, tem de alterar a configuração predefinida do agente de registo antigo quando o instalar ou reinstalar. A ativação do registo estruturado substitui os ficheiros de configuração indicados anteriormente, mas não altera o funcionamento do próprio agente.

Quando ativa o registo estruturado, os registos apresentados são convertidos em entradas de registo com formatos diferentes dos que tinham antes de ativar os registos estruturados. Se os registos estiverem a ser encaminhados para destinos fora do Logging, a alteração pode afetar quaisquer aplicações de pós-processamento. Por exemplo, se encaminhar registos para o BigQuery, o BigQuery rejeita as novas entradas de registo durante o resto do dia por terem um esquema incorreto.

Para ver instruções sobre como instalar o agente Logging antigo e ativar o registo estruturado, consulte o artigo Instalar o agente Logging.

Pode encontrar os ficheiros de configuração do agente Logging antigo em /etc/google-fluentd/config.d/, que devem agora incluir os analisadores padrão ativados por predefinição.

Agente de registos: configure o formato do registo de acesso do Apache

Por predefinição, o agente Logging antigo armazena os dados do registo de acesso do Apache no campo jsonPayload. Por exemplo:

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

Em alternativa, pode configurar o agente Logging antigo para extrair determinados campos para o campo httpRequest. Por exemplo:

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

A configuração do campo httpRequest, conforme mostrado no exemplo anterior, ajuda a rastrear: a consola Google Cloud apresenta todos os registos de um determinado pedido HTTP numa hierarquia principal-secundário.

Para configurar esta extração, adicione o seguinte ao final do elemento /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 mais detalhes sobre como configurar as entradas do registo, consulte o artigo Modificar registos do registo.

Agente de registos: configure o formato do registo de acesso do nginx

Por predefinição, o agente de registo antigo armazena os dados do registo de acesso do nginx no campo jsonPayload. Por exemplo:

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

Em alternativa, pode configurar o agente Logging antigo para extrair determinados campos para o campo httpRequest. Por exemplo:

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

A configuração do campo httpRequest, conforme mostrado no exemplo anterior, ajuda a rastrear: a consola Google Cloud apresenta todos os registos de um determinado pedido HTTP numa hierarquia principal-secundário.

Para configurar esta extração, adicione o seguinte ao final do elemento /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 mais detalhes sobre como configurar as entradas do registo, consulte o artigo Modificar registos do registo.

Escreva o seu próprio analisador

Se os seus registos não forem suportados pelos analisadores padrão, pode escrever o seu próprio analisador. Os analisadores consistem numa expressão regular que é usada para fazer corresponder registos e aplicar etiquetas às partes.

Os exemplos de código seguintes mostram uma linha de registo no registo de registo, uma configuração com uma expressão regular que indica o formato da linha de registo e a entrada de registo armazenada:

  • Uma linha de registo no registo de registos:

    REPAIR CAR $500
    
  • Uma configuração com uma expressão regular que indica o formato da linha de registo:

    $ 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>
    
  • A entrada do registo 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"
    }
    

Resolver problemas

Para resolver problemas comuns encontrados com a instalação ou a interação com o agente de registo antigo, consulte o artigo Resolução de problemas do agente.

O que se segue?