Geração de registros estruturados

No Cloud Logging, registros estruturados se referem a entradas de registro que usam o campo jsonPayload para adicionar estrutura a seus payloads.

Se você usa a Cloud Logging API ou a ferramenta de linha de comando gcloud, é possível controlar a estrutura dos seus payloads. Consulte Como gravar registros estruturados para ver exemplos.

Se você usar o agente do Cloud Logging para receber suas entradas de registro, poderá especificar que o agente do Logging converta os payloads em formato JSON.

Se você usar o serviço BindPlane para ingerir os registros, seus payloads estarão no formato JSON e estruturados de acordo com o sistema de origem. Para informações sobre como localizar e visualizar registros ingeridos por meio do BindPlane, consulte a documentação dessa solução em Como encontrar dados do registro (em inglês).

Como usar campos especiais em payloads JSON para estruturar registros com o agente do Logging

É possível gravar registros estruturados no Logging das seguintes maneiras:

  • Envie a estrutura completa LogEntry com um jsonPayload para a API Cloud Logging
  • Fornecer objetos JSON serializados para o agente do Logging

Se você estiver usando o Google Kubernetes Engine ou o ambiente flexível do App Engine, poderá gravar registros estruturados como objetos JSON serializados em uma única linha para stdout ou stderr. O agente do Logging envia os registros estruturados para o Cloud Logging como o jsonPayload da estrutura LogEntry.

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

  • severity
  • spanId
  • labels definido pelo usuário
  • httpRequest

Como o JSON é mais preciso e versátil que linhas de texto, você pode usar objetos JSON para escrever mensagens multilinha e adicionar metadados.

Para criar entradas de registro estruturadas para seus aplicativos usando o formato simplificado, consulte a tabela a seguir, que lista os campos e seus valores em JSON:

Campo do registro JSON campo LogEntry Função do agente do Cloud Logging Valor de exemplo
severity severity O agente do Logging tenta corresponder diversas strings de gravidade comum, que incluem a lista de strings LogSeverity reconhecida pela API Logging. "severity":"ERROR"
message textPayload (ou parte de jsonPayload) A mensagem que aparece na linha de entrada do registro no Explorador de registros. "message":"There was an error in the application."

Observação: message é salvo como textPayload se for o único campo restante depois que o agente do Logging remover os outros campos de finalidade especial e detect_json não tiver sido ativado. Caso contrário, message permanecerá em jsonPayload. Se a entrada de registro tiver um rastreamento de pilha de exceção, o rastreamento precisa ser definido neste campo de registro JSON message para que o rastreamento de pilha de exceção possa ser analisado e salvo no Error Reporting.
log (somente Google Kubernetes Engine legado) textPayload Aplica-se somente ao Google Kubernetes Engine legado: se, após a remoção de campos de finalidade especial, somente um campo de registro permanecer, esse registro será salvo como textPayload.
httpRequest httpRequest Um registro estruturado no formato do campo LogEntry HttpRequest. "httpRequest":{"requestMethod":"GET"}
campos relacionados ao tempo timestamp Para mais informações, consulte Campos relacionados ao tempo. "timestamp":"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 desse campo precisa ser um registro 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 desse campo também é usado pelo Explorador de registros para agrupar entradas de registro 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 do local do código-fonte associadas à entrada do registro, se houver. 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 período dentro do trace associado à entrada de registro. Para mais informações, consulte spanId na página LogEntry. "logging.googleapis.com/spanId":"000000000000004a
logging.googleapis.com/trace trace Nome do recurso do trace associado à entrada de registro, se houver. Para mais informações, consulte trace na página LogEntry. "logging.googleapis.com/trace":"projects/my-projectid/traces/0679686673a"

Observação: se não for gravando em stdout ou stderr, o valor deste campo deverá ser formatado como projects/[PROJECT-ID]/traces/[TRACE-ID] para que possa ser usado pelo Explorador de registros e pelo Visualizador de Trace para agrupar entradas de registro e exibi-las alinhadas aos traces. Se autoformat_stackdriver_trace for verdadeiro e [V] corresponder ao formato traceId do ResourceTrace, o campo trace do LogEntry tem o valor. projects/[PROJECT-ID]/traces/[V].
logging.googleapis.com/trace_sampled traceSampled O valor desse campo precisa ser true ou false. Para mais informações, consulte traceSampled na página LogEntry. logging.googleapis.com/trace_sampled": false

Para criar entradas de registro no formato simplificado, crie uma representação JSON da entrada usando os campos. Todos os campos são opcionais. Veja a seguir um exemplo de 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
}

Veja a seguir um exemplo da entrada de registro resultante:

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

O agente do Logging google-fluentd é um pacote específico do Cloud Logging do coletor de dados de registro Fluentd (em inglês). Esse agente acompanha a configuração padrão do Fluentd e usa plug-ins de entrada dele para receber registros de evento de origens externas, como arquivos em disco, ou para analisar registros de entrada.

O Fluentd tem uma lista de analisadores compatíveis (em inglês) que extraem e convertem os registros em payloads (JSON) estruturados.

Ao configurar uma origem de registro com format [PARSER_NAME], é possível aproveitar os analisadores integrados fornecidos pelo Fluentd.

As amostras de código a seguir mostram a configuração do Fluentd, o registro de entrada e o payload estruturado de saída, que faz parte de uma entrada de registro 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>
    
  • Registro (entrada):

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

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

Para mais informações sobre como o analisador syslog funciona, consulte a documentação detalhada do Fluentd (em inglês).

Analisadores padrão já ativados

A tabela a seguir mostra os analisadores padrão que serão incluídos no agente se você ativar a geração de registros estruturados:

Nome do analisador Arquivo 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 instruções sobre como ativar a geração de registros estruturados ao instalar o agente do Logging, consulte a seção "Instalação".

Instalação

Para ativar a geração de registros estruturados, você precisa alterar a configuração padrão do agente do Stackdriver Logging ao instalá-lo (ou reinstalá-lo). A ativação da geração de registros estruturados substitui os arquivos de configuração listados anteriormente. Não há alteração na operação do próprio agente.

Quando você ativa a geração de registros estruturados, os registros listados são convertidos em entradas de registro com formatos diferentes dos anteriores à ativação de registros estruturados. Se os registros estiverem sendo exportados do Cloud Logging, a alteração poderá afetar os aplicativos de pós-processamento. No caso de exportações do BigQuery, ele rejeita as novas entradas de registro para o restante do dia como se tivesse um esquema incorreto.

Para instruções sobre como instalar o agente do Logging e ativar a geração de registros estruturada, consulte Como instalar o agente do Logging.

É possível encontrar os arquivos de configuração do agente do Logging em /etc/google-fluentd/config.d/, que agora precisam incluir os analisadores padrão já ativados.

Configurar o formato do registro de acesso do Apache

Por padrão, o agente do Logging armazena dados do registro 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"
  },
  ...
}

Como alternativa, é possível configurar o agente Logging 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, como exibido na amostra anterior, auxilia no rastreamento: o Console do Cloud apresenta todos os registros de uma determinada solicitação HTTP em uma hierarquia pai-filho.

Para configurar essa extração, adicione o seguinte ao final do /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 suas entradas de registro, consulte Como modificar registros.

Configurar o formato de registro de acesso nginx

Por padrão, o agente do Logging armazena dados de registro de acesso 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"
    },
    ...
  }

Como alternativa, é possível configurar o agente Logging 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, como exibido na amostra anterior, auxilia no rastreamento: o Console do Cloud apresenta todos os registros de uma determinada solicitação HTTP em uma hierarquia pai-filho.

Para configurar essa extração, adicione o seguinte ao final do /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 suas entradas de registro, consulte Como modificar registros.

Como escrever o próprio analisador

Se os registros não forem compatíveis com os analisadores padrão, será possível criar seus próprios. Os analisadores consistem em uma expressão regular usada para combinar registros e aplicar rótulos às partes.

Estes três exemplos mostram uma linha no registro, uma configuração com uma expressão regular que indica o formato da linha de registro e a entrada de registro ingerida:

  • Uma linha no registro:

    REPAIR CAR $500
    
  • Uma configuração com uma expressão regular que indica o formato da linha 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>
    
  • A 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:  "2018-03-21T01:47:11.475065313Z"
      resource: {
        labels: {
          instance_id:  "3914079432219560274"
          project_id:  "my-sample-project-12345"
          zone:  "us-central1-c"
        }
        type:  "gce_instance"
      }
      timestamp:  "2018-03-21T01:47:05.051902169Z"
     }
    

Como visualizar registros estruturados

Para pesquisar registros e visualizar entradas de registro com o Explorador de registros do Console do Cloud, consulte esta página.

Para ler entradas de registro usando a ferramenta de linha de comando gcloud ou a API, consulte esta página.

Solução de problemas

Para resolver problemas comuns encontrados na instalação ou interação com o agente do Logging, consulte Como resolver problemas do agente.