Logs schreiben und aufrufen

Das Logging ist ein wichtiges Tool zum Debuggen und Überwachen von Code. Mit Cloud Functions haben Sie die Möglichkeit, das Logger SDK für Node.js oder Python oder das console-Objektstandard für die Webentwicklung zu verwenden.

Cloud Logging ist ein kostenpflichtiger Dienst. Wenn Sie das kostenlose Kontingent überschreiten, werden Ihnen möglicherweise Gebühren in Rechnung gestellt. Weitere Informationen finden Sie unter Cloud Logging – Preise.

Logs schreiben

Cloud Functions-Logger-SDK verwenden

Das Cloud Functions-Logger-SDK bietet eine Standardschnittstelle zum Melden des Status von Funktionen an Cloud Logging. Mit diesem SDK können Sie Ereignisse mit strukturierten Daten protokollieren, was die Analyse und Überwachung erleichtert.

Importieren aus dem Unterpaket logger:

Node.js

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

Python

from firebase_functions import logger
  • logger.log()-Befehle haben die Logebene INFO.

  • logger.info()-Befehle haben die Logebene INFO.

  • logger.warn()-Befehle haben die Logebene WARNING.

  • logger.error()-Befehle haben die Logebene ERROR.

  • logger.debug()-Befehle haben die Logebene DEBUG.

  • Interne Systemmeldungen haben die Logebene DEBUG.

In diesem Beispiel wird eine Funktion gezeigt, die ein einfaches Log schreibt:

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!")

Verwenden Sie unterschiedliche Logebenen für verschiedene Arten von Logs in Ihrem Funktionscode. Strukturierte Daten können als letztes Argument an ein Log angehängt werden. Hier sehen Sie ein Beispiel dafür, wie eine Funktion die einzelnen Logtypen verwenden kann:

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!")

Mit logger.write() können Sie Logeinträge mit zusätzlichen Schweregraden für Logs schreiben: CRITICAL, ALERT und EMERGENCY. Weitere Informationen finden Sie unter 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)

console.log verwenden

Die empfohlene Lösung für das Logging aus einer Funktion ist die Verwendung des Logger-SDK für Ihre Plattform. Mit Node.js können Sie stattdessen Standard-JavaScript-Logging-Aufrufe wie console.log und console.error verwenden. Sie müssen jedoch zuerst ein spezielles Modul einbinden, um die Standardmethoden so zu patchen, dass sie richtig funktionieren:

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

Nachdem Sie das Logger-Kompatibilitätsmodul angefordert haben, können Sie console.log()-Methoden wie gewohnt in Ihrem Code verwenden:

exports.helloError = functions.https.onRequest((request, response) => {
  console.log('I am a log entry!');
  response.send('Hello World...');
});
  • console.log()-Befehle haben die Logebene INFO.
  • console.info()-Befehle haben die Logebene INFO.
  • console.warn()-Befehle haben die Logebene ERROR.
  • console.error()-Befehle haben die Logebene ERROR.
  • Interne Systemmeldungen haben die Logebene DEBUG.

Logs ansehen

Logs für Cloud Functions können entweder in der Google Cloud-Konsole, der Cloud Logging-Benutzeroberfläche oder über das firebase-Befehlszeilentool aufgerufen werden.

Mit der Firebase CLI

Wenn Sie Logs mit dem firebase-Tool aufrufen möchten, verwenden Sie den Befehl functions:log:

firebase functions:log

Wenn Sie Logs für eine bestimmte Funktion aufrufen möchten, geben Sie den Funktionsnamen als Argument an:

firebase functions:log --only <FUNCTION_NAME>

Informationen zu allen Loganzeigeoptionen finden Sie in der Hilfe zu functions:log:

firebase help functions:log

Google Cloud-Konsole verwenden

Sie können Logs für Funktionen in der Google Cloud-Konsole aufrufen.

Cloud Logging-Benutzeroberfläche verwenden

Sie können Logs für Cloud Functions in der Cloud Logging-Benutzeroberfläche aufrufen.

Logs analysieren

Cloud Logging bietet eine leistungsstarke Suite von Tools zur Protokollanalyse, mit denen Sie Ihre Cloud Functions überwachen können.

Diagramme und Benachrichtigungen

Nachdem Sie logbasierte Messwerte zum Überwachen Ihrer Funktionen erstellt haben, können Sie auf Grundlage dieser Messwerte Diagramme und Benachrichtigungen erstellen. Sie können beispielsweise ein Diagramm erstellen, um die Latenz im Zeitverlauf zu visualisieren, oder eine Benachrichtigung erstellen, um sich informieren zu lassen, wenn ein bestimmter Fehler zu häufig auftritt.

Ausführliche Informationen zur Verwendung von logbasierten Messwerten in Diagrammen und Benachrichtigungsrichtlinien finden Sie unter Diagramme und Benachrichtigungen erstellen.

Ausführungs-IDs verstehen und verwenden

Standardmäßig unterstützt Cloud Run Functions (2. Generation) die gleichzeitige Ausführung mehrerer Anfragen in einer einzelnen Funktionsinstanz. Das bedeutet, dass Logs aus verschiedenen Anfragen verschachtelt werden können, was es erschwert, dem Ablauf einer einzelnen Ausführung zu folgen.

Um dies zu erleichtern, werden Funktionen, die mit der Firebase CLI-Version 13.33.0 und höher bereitgestellt werden, automatisch mit einer Option bereitgestellt, mit der jeder Logeintrag, der während der Verarbeitung dieser Ausführung ausgegeben wird, einer Ausführungs-ID zugeordnet werden kann.

Die Ausführungs-ID identifiziert eindeutig alle Logs, die mit einer einzelnen Anfrage verknüpft sind, die von Ihrer Funktion verarbeitet wird. Es sind keine Codeänderungen erforderlich. Die Ausführungs-ID wird automatisch in Ihre Logs aufgenommen.

Wenn Sie die Ausführungs-ID nicht in Ihre Logeinträge aufnehmen möchten, setzen Sie die Umgebungsvariable LOG_EXECUTION_ID in Ihrer dotenv-Datei auf „false“.

Logs anhand der Ausführungs-ID suchen und korrelieren

Sie können Logs nach Ausführungs-ID im Cloud Logs Explorer ansehen und korrelieren.

  1. Maximieren Sie den Logeintrag Ihrer Funktion. Die Ausführungs-ID befindet sich in den strukturierten Logdaten, verschachtelt unter Labels als labels.execution_id.

  2. Klicken Sie auf den Wert von execution_id und wählen Sie im Drop-down-Menü „Übereinstimmende Einträge anzeigen“ aus, um alle anderen Logs aufzurufen, die mit derselben Funktionsausführung verknüpft sind.

Mithilfe der Ausführungs-ID können Sie alle Logmeldungen, die sich auf eine einzelne Anfrage beziehen, gruppieren, auch wenn Ihre Funktion mehrere Anfragen gleichzeitig verarbeitet.

Protokollübersicht mit benutzerdefinierten Zusammenfassungsfeldern verbessern

Damit die Ausführungs-ID im Log-Explorer besser sichtbar ist, können Sie sie als [benutzerdefiniertes Zusammenfassungsfeld][cloud-logging-preference] hinzufügen. Nachdem Sie die Ausführungs-ID als Zusammenfassungsfeld hinzugefügt haben, wird in jedem Logeintrag die Ausführungs-ID als Chip am Anfang der Logzeile angezeigt. Das ist ähnlich wie bei Funktionen der 1. Generation, bei denen die Ausführungs-ID für alle Logeinträge angezeigt wurde.

So fügen Sie dem Zusammenfassungsfeld die Ausführungs-ID hinzu:

  1. Klicken Sie im strukturierten Logeintrag unter labels.execution_id auf den Wert der Ausführungs-ID.

  2. Wählen Sie im Drop-down-Menü die Option „Feld in Zusammenfassungszeile einfügen“ aus.

In jedem Logeintrag wird die executionId jetzt deutlich im Zusammenfassungsfeld angezeigt. So lassen sich Logs, die mit einer bestimmten Ausführungs-ID verknüpft sind, leichter identifizieren und gruppieren.