Logs schreiben und aufrufen

Logging ist ein wichtiges Tool für das Debugging und Monitoring von Code. Cloud Functions bietet Ihnen die Möglichkeit, das Logger SDK für Node.js oder Python oder den console-Objektstandard für die Webentwicklung zu verwenden.

Cloud Logging ist ein kostenpflichtiger Dienst. Wenn Sie das kostenlose Kontingent überschreiten, werden Ihnen möglicherweise Kosten 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, um den Status von Funktionen an Cloud Logging zu melden. Mit diesem SDK können Sie Ereignisse mit strukturierten Daten protokollieren, was die Analyse und Überwachung vereinfacht.

Importieren Sie 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 Systemnachrichten 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 in Ihrem Funktionscode unterschiedliche Logebenen für verschiedene Logtypen. Strukturierte Daten können als letztes Argument an ein Log angehängt werden. Hier ist 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 den zusätzlichen Logschweregraden CRITICAL, ALERT und EMERGENCY schreiben. 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-SDKs 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 anfordern, um die Standardmethoden so zu patchen, dass sie korrekt 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 Systemnachrichten haben die Logebene DEBUG.

Logs ansehen

Logs für Cloud Functions können entweder in der Google Cloud Console, in der Cloud Logging-UI 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

Zum Anzeigen der Logs für eine bestimmte Funktion 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 Console verwenden

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

Cloud Logging-Benutzeroberfläche verwenden

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

Logs analysieren

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

Diagramme und Benachrichtigungen

Nachdem Sie logbasierte Messwerte zum Monitoring Ihrer Funktionen erstellt haben, können Sie Diagramme und Benachrichtigungen auf Grundlage dieser Messwerte erstellen. Sie können beispielsweise ein Diagramm erstellen, um die Latenz im Zeitverlauf zu visualisieren, oder eine Benachrichtigung erstellen, die Sie informiert, wenn ein bestimmter Fehler zu oft auftritt.

Ausführliche Informationen zur Verwendung logbasierter Messwerte in Diagrammen und Benachrichtigungsrichtlinien finden Sie unter Diagramme und Benachrichtigungen erstellen.

Ausführungs-IDs verstehen und verwenden

Standardmäßig unterstützen Cloud Run-Funktionen (2. Generation) die gleichzeitige Ausführung mehrerer Anfragen innerhalb einer einzelnen Funktionsinstanz. Das bedeutet, dass Logs von verschiedenen Anfragen verschachtelt sein können, was es schwieriger macht, den Ablauf einer einzelnen Ausführung zu verfolgen.

Um dies zu vereinfachen, werden Funktionen, die mit der Firebase CLI-Version 13.33.0 und höher bereitgestellt werden, automatisch mit einer Option bereitgestellt, mit der jedem Logeintrag, der während der Verarbeitung dieser Ausführung ausgegeben wird, eine 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 Ihren Logs hinzugefügt.

Wenn Sie das Logging der Ausführungs-ID in Ihren Logeinträgen deaktivieren möchten, setzen Sie die Umgebungsvariable LOG_EXECUTION_ID in Ihrer dotenv-Datei auf „false“.

Logs nach Ausführungs-ID suchen und korrelieren

Sie können Logs im Cloud-Log-Explorer nach Ausführungs-ID prüfen 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 zu sehen, die mit derselben Funktionsausführung verknüpft sind.

Mithilfe der Ausführungs-ID können Sie alle Logeinträge zu einer einzelnen Anfrage gruppieren, auch wenn Ihre Funktion mehrere Anfragen gleichzeitig verarbeitet.

Sichtbarkeit von Logs mit benutzerdefinierten Zusammenfassungsfeldern verbessern

Damit die Ausführungs-ID im Log-Explorer leichter zu finden 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 die Ausführungs-ID in jedem Logeintrag als Chip am Anfang der Logzeile angezeigt, ähnlich wie die Ausführungs-ID bei Funktionen der 1. Generation 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 zur Zusammenfassungszeile hinzufügen“ aus.

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