Logging e visualizzazione dei log in Knative serving

Questa pagina descrive i log disponibili quando utilizzi Knative serving e come visualizzarli e scriverli.

Knative serving ha due tipi di log:

  • Log delle richieste: log delle richieste inviate ai servizi Knative serving. Questi log vengono creati automaticamente.
  • Log dei container: log generati dalle istanze container, in genere dal tuo codice, scritti nelle località supportate come descritto in Scrittura dei log dei container.

Abilitazione dei log

I Google Cloud log vengono inviati automaticamente a Cloud Logging. Per Google Distributed Cloud, devi prima abilitare i log.

Visualizzazione dei log

Puoi visualizzare i log del tuo servizio in due modi:

  • Utilizza la pagina Knative serving nella Google Cloud console.
  • Utilizza Esplora log di Cloud Logging nella Google Cloud console.

Entrambi questi metodi di visualizzazione esaminano gli stessi log archiviati in Cloud Logging, ma Esplora log di Cloud Logging fornisce maggiori dettagli e funzionalità di filtro.

Visualizzazione dei log in Knative serving

Per visualizzare i log nella pagina Knative serving:

  1. Vai a Knative serving.

  2. Fai clic sul servizio desiderato nell'elenco visualizzato.

  3. Fai clic sulla scheda LOG per visualizzare i log delle richieste e dei container per tutte le revisioni di questo servizio. Puoi filtrare in base al livello di gravità del log.

Visualizzazione dei log in Cloud Logging

Per visualizzare i log di Knative serving in Esplora log di Cloud Logging:

  1. Vai alla pagina Esplora log nella Google Cloud console.

  2. Seleziona un progetto Google Cloud esistente nella parte superiore della pagina o creane uno nuovo.

  3. Utilizzando i menu a discesa, seleziona la risorsa: Container Kubernetes.

Per ulteriori informazioni, vedi Utilizzo di Esplora log.

Visualizzazione dei log in Cloud Code

Per visualizzare i log in Cloud Code, consulta le guide di IntelliJ e Visual Studio Code.

Lettura programmatica dei log

Se vuoi leggere i log in modo programmatico, puoi utilizzare uno dei seguenti metodi:

Scrittura dei log dei container

Quando scrivi i log dal tuo servizio, questi vengono rilevati automaticamente da Cloud Logging, a condizione che vengano scritti in una delle seguenti località:

La maggior parte degli sviluppatori dovrebbe scrivere i log utilizzando l'output standard e l'errore standard.

I log dei container scritti in queste località supportate vengono associati automaticamente al servizio, alla revisione e alla località di Knative serving.

Utilizzo di testo semplice o JSON strutturato nei log

Quando scrivi i log, puoi inviare una semplice stringa di testo o una singola riga di JSON serializzato, chiamata anche dati "strutturati". Questi vengono rilevati e analizzati da Cloud Logging e inseriti in jsonPayload. Al contrario, il semplice messaggio di testo viene inserito in textPayload.

Scrittura di log strutturati

Lo snippet seguente mostra come scrivere voci di log strutturate. Mostra anche come correlare i messaggi di log con il log delle richieste corrispondente.

Node.js


// Uncomment and populate this variable in your code:
// const project = 'The project ID of your function or Cloud Run service';

// Build structured log messages as an object.
const globalLogFields = {};

// Add log correlation to nest all log messages beneath request log in Log Viewer.
// (This only works for HTTP-based invocations where `req` is defined.)
if (typeof req !== 'undefined') {
  const traceHeader = req.header('X-Cloud-Trace-Context');
  if (traceHeader && project) {
    const [trace] = traceHeader.split('/');
    globalLogFields['logging.googleapis.com/trace'] =
      `projects/${project}/traces/${trace}`;
  }
}

// Complete a structured log entry.
const entry = Object.assign(
  {
    severity: 'NOTICE',
    message: 'This is the default display field.',
    // Log viewer accesses 'component' as 'jsonPayload.component'.
    component: 'arbitrary-property',
  },
  globalLogFields
);

// Serialize to a JSON string and output.
console.log(JSON.stringify(entry));

Python

# Uncomment and populate this variable in your code:
# PROJECT = 'The project ID of your Cloud Run service';

# Build structured log messages as an object.
global_log_fields = {}

# Add log correlation to nest all log messages.
# This is only relevant in HTTP-based contexts, and is ignored elsewhere.
# (In particular, non-HTTP-based Cloud Functions.)
request_is_defined = "request" in globals() or "request" in locals()
if request_is_defined and request:
    trace_header = request.headers.get("X-Cloud-Trace-Context")

    if trace_header and PROJECT:
        trace = trace_header.split("/")
        global_log_fields[
            "logging.googleapis.com/trace"
        ] = f"projects/{PROJECT}/traces/{trace[0]}"

# Complete a structured log entry.
entry = dict(
    severity="NOTICE",
    message="This is the default display field.",
    # Log viewer accesses 'component' as jsonPayload.component'.
    component="arbitrary-property",
    **global_log_fields,
)

print(json.dumps(entry))

Vai

La struttura di ogni voce di log è fornita da un tipo Entry:


// Entry defines a log entry.
type Entry struct {
	Message  string `json:"message"`
	Severity string `json:"severity,omitempty"`
	Trace    string `json:"logging.googleapis.com/trace,omitempty"`

	// Logs Explorer allows filtering and display of this as `jsonPayload.component`.
	Component string `json:"component,omitempty"`
}

// String renders an entry structure to the JSON format expected by Cloud Logging.
func (e Entry) String() string {
	if e.Severity == "" {
		e.Severity = "INFO"
	}
	out, err := json.Marshal(e)
	if err != nil {
		log.Printf("json.Marshal: %v", err)
	}
	return string(out)
}

Quando viene registrato uno struct di voci, viene chiamato il metodo String per eseguirne il marshalling nel formato JSON previsto da Cloud Logging:


func init() {
	// Disable log prefixes such as the default timestamp.
	// Prefix text prevents the message from being parsed as JSON.
	// A timestamp is added when shipping logs to Cloud Logging.
	log.SetFlags(0)
}

func indexHandler(w http.ResponseWriter, r *http.Request) {
	// Uncomment and populate this variable in your code:
	// projectID = "The project ID of your Cloud Run service"

	// Derive the traceID associated with the current request.
	var trace string
	if projectID != "" {
		traceHeader := r.Header.Get("X-Cloud-Trace-Context")
		traceParts := strings.Split(traceHeader, "/")
		if len(traceParts) > 0 && len(traceParts[0]) > 0 {
			trace = fmt.Sprintf("projects/%s/traces/%s", projectID, traceParts[0])
		}
	}

	log.Println(Entry{
		Severity:  "NOTICE",
		Message:   "This is the default display field.",
		Component: "arbitrary-property",
		Trace:     trace,
	})

	fmt.Fprintln(w, "Hello Logger!")
}

Java

Abilita la registrazione JSON con Logback e SLF4J abilitando Logstash JSON Encoder nella configurazione di logback.xml.

// Add log correlation to nest all log messages beneath request log in Log Viewer.
// TODO(developer): delete this code if you're creating a Cloud
//                  Function and it is *NOT* triggered by HTTP.
String traceHeader = req.headers("x-cloud-trace-context");
if (traceHeader != null && project != null) {
  String trace = traceHeader.split("/")[0];
  MDC.put(
      "logging.googleapis.com/trace",
      String.format("projects/%s/traces/%s", project, trace));
}
// -- End log correlation code --

// Create a structured log entry using MDC (Mapped Diagnostic Context) keys.
// For instantiating the "logger" variable, see
// https://cloud.google.com/run/docs/logging#run_manual_logging-java
MDC.put("component", "arbitrary-property");

logger.info("This is the default display field.");

// Clear MDC at the end of the request to avoid resource leaks
MDC.clear();
<configuration>
  <appender name="CLOUD" class="com.google.cloud.logging.logback.LoggingAppender">
    <!-- Optional : filter logs at or above a level -->
    <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
      <level>INFO</level>
    </filter>
    <log>application.log</log> <!-- Optional : default java.log -->
    <resourceType>gae_app</resourceType> <!-- Optional : default: auto-detected, fallback: global -->
    <enhancer>com.example.logging.logback.enhancers.ExampleEnhancer</enhancer> <!-- Optional -->
    <flushLevel>WARN</flushLevel> <!-- Optional : default ERROR -->
    <!-- Redirect logs to stdout in JSON format for Cloud Run to capture -->
    <redirectToStdout>true</redirectToStdout>
  </appender>
  <root level="INFO">
    <appender-ref ref="CLOUD"/>
  </root>
</configuration>

Campi JSON speciali nei messaggi

Quando fornisci un log strutturato come dizionario JSON, alcuni campi speciali vengono rimossi da jsonPayload e scritti nel campo corrispondente della LogEntry generata, come descritto nella documentazione relativa ai campi speciali.

Ad esempio, se il file JSON include una proprietà severity, questa viene rimossa da jsonPayload e viene visualizzata come severity della voce di log. La proprietà message viene utilizzata come testo di visualizzazione principale della voce di log, se presente. Per ulteriori informazioni sulle proprietà speciali, consulta la sezione Risorsa di logging di seguito.

Correlazione dei log dei container con un log delle richieste

In Esplora log, i log correlati dalla stessa trace sono visualizzabili in formato "padre-figlio": quando fai clic sull'icona a forma di triangolo a sinistra della voce di log delle richieste, i log dei container correlati a quella richiesta vengono visualizzati nidificati sotto il log delle richieste.

I log dei container non vengono correlati automaticamente ai log delle richieste, a meno che tu non utilizzi una libreria client di Cloud Logging. Per correlare i log dei container con i log delle richieste senza utilizzare una libreria client, puoi utilizzare una riga di log JSON strutturata che contiene un campo logging.googleapis.com/trace con l'identificatore di traccia estratto da l'intestazione X-Cloud-Trace-Context come mostrato nell'esempio precedente per la registrazione strutturata.

Controllo dell'utilizzo delle risorse dei log delle richieste

I log delle richieste vengono creati automaticamente. Sebbene non sia possibile controllare la quantità di log delle richieste direttamente da Knative serving, puoi utilizzare la funzionalità di esclusione dei log di Cloud Logging.

Una nota sugli agenti di logging

Se hai utilizzato Cloud Logging con determinati Google Cloud prodotti, ad esempio Compute Engine, potresti aver utilizzato gli agenti di logging di Cloud Logging. Knative serving non utilizza agenti di logging perché supporta la raccolta di log integrata.

Risorsa di logging

Se fai clic su una voce di log in Esplora log, si apre una voce di log in formato JSON che ti consente di approfondire i dettagli che ti interessano.

Tutti i campi di una voce di log, come timestamp, gravità e httpRequest sono standard e sono descritti nella documentazione relativa a una voce di log.

Tuttavia, esistono alcune etichette o etichette delle risorse speciali per Knative serving. Questi sono elencati qui con contenuti di esempio:

{
 httpRequest: {}
 insertId:  "5c82b3d1000ece0000000000"
 labels: {
  instanceId:  "00bf4bf00000fb59c906a00000c9e29c2c4e06dce91500000000056008d2b6460f163c0057b97b2345f2725fb2423ee5f0bafd36df887fdb1122371563cf1ff453717282afe000001"
 }
 logName:  "projects/my-project/logs/kubernetes-engine/enterprise/knative-serving/.googleapis.com%2Frequests"
 receiveTimestamp:  "2019-03-08T18:26:25.981686167Z"
 resource: {
  labels: {
   configuration_name:  "myservice"
   location:  "us-central1"
   project_id:  "my-project"
   revision_name:  "myservice-00002"
   service_name:  "myservice"
  }
  type:  "cloud_run_revision"
 }
 severity:  "INFO"
 timestamp:  "2019-03-08T18:26:25.970397Z"
}
Campo Valori e note
instanceId L'istanza container che ha gestito la richiesta.
logName Identifica il log, ad esempio log delle richieste, errore standard, output standard e così via.
configuration_name La risorsa di configurazione che ha creato la revisione che ha gestito la richiesta.
location Identifica la località Google Cloud del servizio.
project_id Il progetto in cui è stato eseguito il deployment del servizio.
revision_name La revisione che ha gestito la richiesta.
service_name Il servizio che ha gestito la richiesta.
type cloud_run_revision. Il tipo di risorsa Knative serving.