Logging strutturato

Questo documento illustra il concetto di logging strutturato e i metodi per aggiungendo una struttura ai campi del payload voce di log. Quando il payload del log è formattato come oggetto JSON e l'oggetto è archiviato nel campo jsonPayload, la voce del log è chiamata log strutturato. Per questi log, puoi creare query che cercano specifici percorsi JSON e puoi indicizzare campi specifici di log del payload. Al contrario, quando il payload del log viene formattato come stringa e archiviata nel campo textPayload, la voce di log è non strutturata. Puoi cercare nel campo di testo, ma non puoi indicizzarne i contenuti.

Per creare voci di log strutturate, esegui una delle seguenti operazioni:

  • Chiama il metodo API entries.write e forniscilo un LogEntry completamente formattato.
  • Usa il comando gcloud logging write.
  • Utilizzare una libreria client di Cloud Logging che scrive i log strutturati.
  • Utilizzare il servizio BindPlane.
  • Utilizza un agente per scrivere i log:

    • Alcuni servizi Google Cloud contengono un agente di logging integrato che invia i dati scritti in stdout o stderr come log in Cloud Logging. Puoi utilizzare questo approccio per i servizi Google Cloud come Google Kubernetes Engine, ambiente flessibile di App Engine e funzioni di Cloud Run.

    • Per le macchine virtuali (VM) Compute Engine, puoi installare e configurare Ops Agent o l'agente Logging legacy e poi usa l'agente installato per inviare i log a Cloud Logging.

Per ulteriori informazioni su questi approcci, consulta le sezioni seguenti.

Scrivi i log utilizzando le librerie client o l'API

Puoi scrivere dati di log utilizzando il metodo librerie client di Cloud Logging, che chiamare l'API Cloud Logging o chiamando direttamente l'API Cloud Logging. Le librerie client possono semplificare l'inserimento dei campi JSON speciali acquisire automaticamente alcune informazioni e fornire interfacce compilare correttamente i campi. Tuttavia, per un controllo completo struttura dei tuoi payload, chiama direttamente l'API Cloud Logging e passa struttura completa di LogEntry all'API Cloud Logging.

Per ulteriori informazioni, consulta la documentazione di riferimento di entries.write.

Per esempi di codice, consulta Scrivere log strutturati.

Scrivi i log utilizzando gcloud CLI

Puoi scrivere dati di log utilizzando gcloud CLI. L'interfaccia supporta log non strutturati e log strutturati. Quando vuoi scrivere un log strutturato, fornisci al comando un oggetto JSON serializzato.

Per una guida rapida, vedi Scrivi ed esegui query sulle voci di log con Google Cloud CLI.

Per esempi di codice, consulta gcloud logging write.

Scrivere i log con BindPlane

Puoi utilizzare il servizio BindPlane per inviare log a Logging. Per questi log, i payload sono in formato JSON e sono strutturati in base al sistema di origine. Per informazioni su come trovare e visualizzare i log importati utilizzando BindPlane, consulta la guida rapida di BindPlane.

Scrivi i log utilizzando un agente

Per recuperare i log dalle istanze Compute Engine, puoi utilizzare Ops Agent o l'agente Cloud Logging legacy. Entrambi gli agenti possono raccogliere metriche da applicazioni di terze parti entrambi supportano il logging strutturato:

  • Ops Agent è l'agente consigliato per la raccolta dati di telemetria generati dalle istanze di Compute Engine. Questo agente combina il logging e le metriche in un singolo agente, fornisce una soluzione e offre logging a velocità effettiva elevata.

    Per informazioni su come configurare Ops Agent per il supporto log strutturato o per personalizzare il formato di un log strutturato, consulta Configura Ops Agent.

  • L'agente Cloud Logging legacy raccoglie i log. Questo agente non raccoglie altre forme di telemetria.

Il resto di questa sezione riguarda in modo specifico dell'agente Logging legacy.

Agente di logging: campi JSON speciali

Alcuni campi dell'oggetto JSON sono riconosciuti come speciali dal dell'agente Logging legacy ed estratto Struttura di LogEntry. Questi campi JSON speciali possono essere utilizzati per impostare i seguenti campi in LogEntry:

  • severity
  • spanId
  • labels definito dall'utente
  • httpRequest

Poiché JSON è più preciso e versatile delle righe di testo, puoi utilizzare JSON per scrivere messaggi multiriga e aggiungere metadati.

Per creare voci di log strutturate per le tue applicazioni utilizzando lo strumento consulta la tabella seguente, che elenca i campi e i relativi valori in JSON:

Campo log JSON LogEntry campo Cloud Logging funzione agente Valore di esempio
severity severity Il logging un agente tenta di abbinare le stringhe con gravità comune, che includono l'elenco di LogSeverity stringhe riconosciute l'API Logging. "severity":"ERROR"
message textPayload (o parte di jsonPayload) Il messaggio visualizzato nel log in Esplora log. "message":"There was an error in the application."

Nota: message viene salvato come textPayload se è il l'unico campo rimanente dopo il sposterà gli altri campi con scopi speciali e detect_json non è stato attivato; altrimenti message rimane in jsonPayload. detect_json non è applicabile agli ambienti di logging gestiti come Google Kubernetes Engine. Se la voce di log contiene un analisi dello stack delle eccezioni, l'analisi dello stack delle eccezioni essere impostata in questo campo di log JSON di message, in modo che l'eccezione l'analisi dello stack può essere analizzata e salvata in Error Reporting.
log (legacy Google Kubernetes Engine ) textPayload Si applica solo alla versione precedente di Google Kubernetes Engine: se, dopo lo spostamento di uno scopo speciale rimane solo un campo log, quindi il campo viene salvato come textPayload.
httpRequest httpRequest Un record strutturato nel formato di LogEntry HttpRequest. "httpRequest":{"requestMethod":"GET"}
correlato al tempo campi timestamp Per ulteriori informazioni, consulta Campi relativi al tempo. "time":"2020-10-12T07:20:50.52Z"
logging.googleapis.com/insertId insertId Per ulteriori informazioni, vedi insertId sulla pagina LogEntry. "logging.googleapis.com/insertId":"42"
logging.googleapis.com/labels labels Il valore di questo campo deve essere un record strutturato. Per ulteriori informazioni, vedi labels attivo la pagina LogEntry. "logging.googleapis.com/labels": {"user_label_1":"value_1","user_label_2":"value_2"}
logging.googleapis.com/operation operation Il valore di questo campo viene utilizzato anche da Logs Explorer per raggruppare le voci di log correlate. Per ulteriori informazioni, consulta operation nella pagina LogEntry. "logging.googleapis.com/operation": {"id":"get_data","producer":"github.com/MyProject/MyApplication", "first":"true"}
logging.googleapis.com/sourceLocation sourceLocation Posizione del codice sorgente informazioni associate con la voce di log, se ce ne sono. Per ulteriori informazioni, consulta LogEntrySourceLocation nella pagina LogEntry. "logging.googleapis.com/sourceLocation": {"file":"get_data.py","line":"142","function":"getData"}
logging.googleapis.com/spanId spanId L'ID intervallo all'interno della traccia associata alla voce di log. Per ulteriori informazioni, vedi spanId sulla pagina LogEntry. "logging.googleapis.com/spanId":"000000000000004a"
logging.googleapis.com/trace trace Nome della risorsa della traccia associata all'eventuale voce di log. Per ulteriori informazioni, vedi trace sulla pagina LogEntry. "logging.googleapis.com/trace":"projects/my-projectid/traces/0679686673a"

Nota: se non scrivi a stdout o stderr, il valore di questo campo deve essere formattato come projects/[PROJECT-ID]/traces/[TRACE-ID], in modo che possa essere utilizzato da Esplora log il visualizzatore tracce per raggruppare le voci di log e mostrarle in linea con le tracce. Se autoformat_stackdriver_trace è vero e [V] corrisponde al formato di ResourceTrace traceId il campo LogEntry trace ha il valore projects/[PROJECT-ID]/traces/[V].
logging.googleapis.com/trace_sampled traceSampled Il valore di questo campo deve essere true o false. Per ulteriori informazioni, vedi traceSampled sulla pagina LogEntry. "logging.googleapis.com/trace_sampled": false

Per creare voci di log nel formato semplificato, crea una rappresentazione JSON di la voce utilizzando i campi. Tutti i campi sono facoltativi.

Di seguito è riportato un esempio di voce di log JSON semplificata:

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

Di seguito è riportato un esempio della voce di log risultante:

{
  "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 Logging: configurazione

L'agente Logging legacy, google-fluentd, è un il pacchetto specifico di Cloud Logging Raccoglitore di dati di log Fluentd. L'agente Logging viene fornito con la configurazione Fluentd predefinita e utilizza plug-in di input Fluentd per eseguire il pull dei log eventi da origini esterne come i file sul disco, o per analizzare i record di log in entrata.

Fluentd ha creato un elenco analizzatori sintattico supportati che estraggono i log e li convertono in payload strutturati (JSON).

Configurando una sorgente log con format [PARSER_NAME], puoi creare parser integrati forniti da Fluentd. Per informazioni sulla configurazione dell'agente Logging legacy, Configura l'agente Logging.

I seguenti esempi di codice mostrano la configurazione Fluentd, il log di input e il payload strutturato di output, che fa parte di un Cloud Logging voce di log:

  • Configurazione di 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>
    
  • Record di log (input):

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

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

Per ulteriori informazioni sul funzionamento del parser syslog, consulta le Documentazione fluida.

Agente Logging: parser standard abilitati per impostazione predefinita

La tabella seguente include i parser standard inclusi nei se abiliti il logging strutturato:

Nome del parser File di configurazione
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

Per istruzioni su come attivare il logging strutturato durante l'installazione del dell'agente Logging legacy, Installazione.

Agente di logging: installazione

Per abilitare il logging strutturato, devi modificare la configurazione predefinita del l'agente Logging legacy durante l'installazione o la reinstallazione. L'attivazione del logging strutturato sostituisce i file di configurazione elencati in precedenza senza però modificare il funzionamento dell'agente stesso.

Quando abiliti il logging strutturato, i log elencati vengono convertiti in le voci di log con formati diversi rispetto a prima dell'attivazione strutturata logaritmi. Se i log vengono indirizzati a destinazioni all'esterno di Logging, la modifica potrebbe influire su tutte le applicazioni di post-elaborazione. Ad esempio, se esegui il routing dei log a BigQuery, BigQuery rifiuta le nuove voci di log per il resto della giornata come contenenti schema errato.

Per istruzioni sull'installazione dell'agente Logging legacy e per abilitare il logging strutturato, consulta l'articolo Installare il logging un agente.

Puoi trovare i file di configurazione dell'agente di logging precedente in /etc/google-fluentd/config.d/, che ora dovrebbe includere i parser standard abilitati per impostazione predefinita.

Agente Logging: configura il formato dei log di accesso Apache

Per impostazione predefinita, l'agente di logging legacy archivia i dati dei log di accesso di Apache nel campo jsonPayload. Ad esempio:

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

In alternativa, puoi configurare l'agente Logging legacy per estrarre alcuni campi nel campo httpRequest. Ad esempio:

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

La configurazione del campo httpRequest, come mostrato nell'esempio precedente, assiste tracciamento: la console Google Cloud presenta tutti i log per una determinata richiesta HTTP in una gerarchia padre-figlio.

Per configurare questa estrazione, aggiungi quanto segue alla fine del /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>

Per ulteriori dettagli su come configurare le voci di log, consulta Modifica dei record dei log.

Agente di logging: configura il formato del log di accesso nginx

Per impostazione predefinita, l'agente Logging legacy archivia l'accesso a nginx i dati di log nel campo jsonPayload. Ad esempio:

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

In alternativa, puoi configurare l'agente Logging legacy per estrarre alcuni campi nel campo httpRequest. Ad esempio:

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

La configurazione del campo httpRequest, come mostrato nell'esempio precedente, assiste tracciamento: la console Google Cloud presenta tutti i log per una determinata richiesta HTTP in una gerarchia padre-figlio.

Per configurare questa estrazione, aggiungi quanto segue alla fine del /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>

Per ulteriori dettagli su come configurare le voci di log, consulta Modifica dei record dei log.

Scrivi il tuo parser

Se i tuoi log non sono supportati dai parser standard, puoi scrivere analizzatore sintattico. I parser sono costituiti da un'espressione regolare utilizzata per trovare corrispondenze nei log e applicare etichette ai pezzi.

I seguenti esempi di codice mostrano una riga di log nel record di log, una configurazione con un'espressione regolare che indica il formato della riga di log e la voce di log archiviata:

  • Una riga di log nel record di log:

    REPAIR CAR $500
    
  • Una configurazione con un'espressione regolare che indica il formato la riga del log:

    $ 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 voce di log risultante:

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

Risoluzione dei problemi

Per risolvere i problemi comuni riscontrati durante l'installazione o l'interazione con il dell'agente Logging legacy, Risolvere i problemi dell'agente.

Passaggi successivi