Scrivi e visualizza i log

Il logging è uno strumento importante per il debug e il monitoraggio del codice. Cloud Functions ti offre la possibilità di utilizzare l'SDK del logger per Node.js o Python, oppure lo standard dell'oggetto console per lo sviluppo per il web.

Cloud Logging è un servizio a pagamento; se superi la quota senza costi, ti potrebbe essere addebitato un importo. Per ulteriori informazioni, consulta Prezzi di Cloud Logging.

Scrittura dei log

Utilizzo dell'SDK del logger Cloud Functions

L'SDK del logger Cloud Functions fornisce un'interfaccia standard per segnalare lo stato dalle funzioni a Cloud Logging. Puoi utilizzare questo SDK per registrare gli eventi con dati strutturati, semplificando l'analisi e il monitoraggio.

Importa dal sottopacchetto logger:

Node.js

// All available logging functions
const {
  log,
  info,
  debug,
  warn,
  error,
  write,
} = require("firebase-functions/logger");

Python

from firebase_functions import logger
  • I comandi logger.log() hanno il livello di log INFO.

  • I comandi logger.info() hanno il livello di log INFO.

  • I comandi logger.warn() hanno il livello di log WARNING.

  • I comandi logger.error() hanno il livello di log ERROR.

  • I comandi logger.debug() hanno il livello di log DEBUG.

  • I messaggi di sistema interni hanno il livello di log DEBUG.

Questo esempio mostra una funzione che scrive un log di base:

Node.js

exports.helloWorld = onRequest((request, response) => {
  // sends a log to Cloud Logging
  log("Hello logs!");

  response.send("Hello from Firebase!");
});

Python

@https_fn.on_request()
def hello_world(req: https_fn.Request) -> https_fn.Response:
    # sends a log to Cloud Logging
    logger.log("Hello logs!")

    return https_fn.Response("Hello from Firebase!")

Utilizza livelli di log diversi per i diversi tipi di log nel codice della funzione. I dati strutturati possono essere allegati a un log come ultimo argomento. Ecco un esempio di come una funzione può utilizzare ogni tipo di log:

Node.js

exports.getInspirationalQuote = onRequest(async (request, response) => {
  const db = getFirestore();
  const today = new Date();
  const quoteOfTheMonthRef = db
      .collection("quotes")
      .doc(`${today.getFullYear()}`)
      .collection("months")
      .doc(`${today.getMonth()}`);

  const DEFAULT_QUOTE =
      "You miss 100% of the shots you don't take. -Wayne Gretzky";
  let quote;
  try {
    const quoteOfTheMonthDocSnap = await quoteOfTheMonthRef.get();

    // Attach relevant debugging information with debug()
    debug("Monthly quote fetch result", {
      docRef: quoteOfTheMonthRef.path,
      exists: quoteOfTheMonthDocSnap.exists,
      createTime: quoteOfTheMonthDocSnap.createTime,
    });

    if (quoteOfTheMonthDocSnap.exists) {
      quote = quoteOfTheMonthDocSnap.data().text;
    } else {
      // Use warn() for lower-severity issues than error()
      warn("Quote not found for month, sending default instead", {
        docRef: quoteOfTheMonthRef.path,
        dateRequested: today.toLocaleDateString("en-US"),
      });

      quote = DEFAULT_QUOTE;
    }
  } catch (err) {
    // Attach an error object as the second argument
    error("Unable to read quote from Firestore, sending default instead",
        err);

    quote = DEFAULT_QUOTE;
  }

  // Attach relevant structured data to any log
  info("Sending a quote!", {quote: quote});
  response.json({inspirationalQuote: quote});
});

Python

@https_fn.on_request()
def get_inspirational_quote(req: https_fn.Request) -> https_fn.Response:
    firestore_client = firestore.client()
    today = datetime.date.today()
    quote_of_the_month_ref = (
        firestore_client.collection("quotes")
        .doc(str(today.year))
        .collection("months")
        .doc(str(today.month))
    )

    default_quote = "Python has been an important part of Google since the beginning, and remains so as the system grows and evolves."

    quote = None
    try:
        quote_of_the_month = quote_of_the_month_ref.get()

        # Attach relevant debugging information with debug()
        logger.debug(
            "Monthly quote fetch result",
            docRef=quote_of_the_month.path,
            exists=quote_of_the_month.exists,
            createTime=quote_of_the_month.createTime,
        )

        if quote_of_the_month.exists:
            quote = quote_of_the_month.to_dict()["text"]
        else:
            # Use warn() for lower-severity issues than error()
            logger.warn(
                "Quote not found for month, sending default instead",
                doc_reference=quote_of_the_month.path,
                date_requested=today.strftime("%Y-%m-%d"),
            )
            quote = default_quote
    except:
        e = sys.exc_info()[0]
        # Attach an error object as the second argument
        logger.error("Unable to read quote from Firestore, sending default instead", error=e)
        quote = default_quote

    # Attach relevant structured data to any log
    logger.info("Sending a quote!", quote=quote)
    return https_fn.Response("Hello from Firebase!")

Con logger.write(), puoi scrivere voci di log con livelli di gravità del log aggiuntivi di CRITICAL, ALERT e EMERGENCY. Consulta LogSeverity.

Node.js

exports.appHasARegression = onRegressionAlertPublished((event) => {
  write({
    // write() lets you set additional severity levels
    // beyond the built-in logger functions
    severity: "EMERGENCY",
    message: "Regression in production app",
    issue: event.data.payload.issue,
    lastOccurred: event.data.payload.resolveTime,
  });
});

Python

@crashlytics_fn.on_regression_alert_published()
def app_has_regression(alert: crashlytics_fn.CrashlyticsRegressionAlertEvent) -> None:
    logger.write(
        severity="EMERGENCY",
        message="Regression in production app",
        issue=alert.data.payload.issue,
        last_occurred=alert.data.payload.resolve_time,
    )
    print(alert)

Uso: console.log

La soluzione consigliata per il logging da una funzione è utilizzare l'SDK logger per la tua piattaforma. Con Node.js, puoi invece utilizzare le chiamate di logging JavaScript standard come console.log e console.error, ma devi prima richiedere un modulo speciale per applicare patch ai metodi standard affinché funzionino correttamente:

require("firebase-functions/logger/compat");

Dopo aver richiesto il modulo di compatibilità del logger, puoi utilizzare i metodi console.log() normalmente nel tuo codice:

exports.helloError = functions.https.onRequest((request, response) => {
  console.log('I am a log entry!');
  response.send('Hello World...');
});
  • I comandi console.log() hanno il livello di log INFO.
  • I comandi console.info() hanno il livello di log INFO.
  • I comandi console.warn() hanno il livello di log ERROR.
  • I comandi console.error() hanno il livello di log ERROR.
  • I messaggi di sistema interni hanno il livello di log DEBUG.

Visualizzazione dei log

I log per Cloud Functions sono visualizzabili nella consoleGoogle Cloud, nell'interfaccia utente di Cloud Logging o tramite lo strumento a riga di comando firebase.

Utilizzo dell'interfaccia a riga di comando di Firebase

Per visualizzare i log con lo strumento firebase, utilizza il comando functions:log:

firebase functions:log

Per visualizzare i log di una funzione specifica, fornisci il nome della funzione come argomento:

firebase functions:log --only <FUNCTION_NAME>

Per l'intera gamma di opzioni di visualizzazione dei log, consulta la guida di functions:log:

firebase help functions:log

Utilizzo della console Google Cloud

Puoi visualizzare i log per le funzioni nella console Google Cloud.

Utilizzo della UI di Cloud Logging

Puoi visualizzare i log per Cloud Functions nell'interfaccia utente di Cloud Logging.

Analisi dei log

Cloud Logging offre una potente suite di strumenti di analisi dei log che puoi utilizzare per monitorare Cloud Functions.

Grafici e avvisi

Dopo aver creato le metriche basate su log per monitorare le funzioni, puoi creare grafici e avvisi in base a queste metriche. Ad esempio, puoi creare un grafico per visualizzare la latenza nel tempo o creare un avviso per sapere se un determinato errore si verifica troppo spesso.

Per informazioni dettagliate su come utilizzare le metriche basate su log nei grafici e nelle policy di avviso, consulta Creazione di grafici e avvisi.

Comprendi e utilizza gli ID esecuzione

Per impostazione predefinita, Cloud Run Functions (2ª gen.) supporta l'esecuzione in parallelo di più richieste all'interno di una singola istanza di funzione. Ciò significa che i log di richieste diverse possono essere intercalati, rendendo più difficile seguire il flusso di una singola esecuzione.

Per facilitare questa operazione, il deployment delle funzioni eseguito utilizzando l'interfaccia a riga di comando di Firebase versione 13.33.0 e successive viene eseguito automaticamente con un'opzione per associare un ID esecuzione a ogni voce di log emessa durante la gestione dell'esecuzione.

L'ID esecuzione identifica in modo univoco tutti i log associati a una singola richiesta gestita dalla tua funzione. Non è necessario apportare modifiche al codice; l'ID esecuzione verrà aggiunto automaticamente ai log.

Per disattivare la registrazione dell'ID esecuzione nelle voci di log, imposta la variabile di ambiente LOG_EXECUTION_ID su false nel file dotenv.

Trova e correla i log in base all'ID esecuzione

Puoi ispezionare e correlare i log in base all'ID esecuzione in Esplora log di Cloud.

  1. Espandi la voce di log della funzione. L'ID esecuzione si trova all'interno dei dati di log strutturati, nidificati sotto le etichette come labels.execution_id.

  2. Fai clic sul valore di execution_id e seleziona "Mostra voci corrispondenti" dal menu a discesa per visualizzare tutti gli altri log associati alla stessa esecuzione della funzione.

Utilizzando l'ID esecuzione, puoi raggruppare tutti i messaggi di log correlati a una singola richiesta, anche se la funzione gestisce più richieste contemporaneamente.

Migliora la visibilità dei log con i campi di riepilogo personalizzati

Per rendere l'ID esecuzione più facilmente visibile in Esplora log, puoi aggiungerlo come [campo di riepilogo personalizzato][cloud-logging-preference]. Dopo aver aggiunto l'ID esecuzione come campo di riepilogo, ogni voce di log mostrerà l'ID esecuzione come chip all'inizio della riga di log, in modo simile a come le funzioni di 1ª gen. mostravano l'ID esecuzione per tutte le voci di log.

Per aggiungere l'ID esecuzione al campo di riepilogo:

  1. Fai clic sul valore dell'ID esecuzione nella voce di log strutturata in labels.execution_id.

  2. Seleziona "Aggiungi campo alla riga di riepilogo" dal menu a discesa.

Ora ogni voce di log mostra l'ID executionId in evidenza nel campo di riepilogo, semplificando l'identificazione e il raggruppamento dei log associati a un ID esecuzione specifico.