寫入和檢視記錄

記錄是偵錯和監控程式碼的重要工具。Cloud Functions 可讓您選擇使用適用於 Node.js 或 Python 的記錄器 SDK,或是使用 console 物件標準開發網頁應用程式。

Cloud Logging 是付費服務,如果超出免付費配額,可能需要支付費用。詳情請參閱 Cloud Logging 定價。

寫入記錄

使用 Cloud Functions 記錄器 SDK

Cloud Functions 記錄器 SDK 提供標準介面,可將函式狀態回報給 Cloud Logging。您可以使用這個 SDK 記錄含有結構化資料的事件,方便進行分析和監控。

從 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() 指令的記錄層級為 INFO。

  • logger.info() 指令的記錄層級為 INFO。

  • logger.warn() 指令的記錄層級為 WARNING。

  • logger.error() 指令的記錄層級為 ERROR。

  • logger.debug() 指令的記錄層級為 DEBUG。

  • 內部系統訊息具有 DEBUG 記錄層級。

這個範例說明函式如何寫入基本記錄:

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

針對函式程式碼中的不同記錄類型,使用不同的記錄層級。 結構化資料可以附加至記錄,做為最後一個引數。以下範例說明函式如何使用各種類型的記錄:

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

使用 logger.write(),您可以編寫記錄項目,並指定 CRITICAL、ALERT 和 EMERGENCY 等其他記錄嚴重性層級。請參閱「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

建議您使用適用於平台的記錄器 SDK,從函式記錄。使用 Node.js 時,您可以改用標準 JavaScript 記錄呼叫 (例如 console.log 和 console.error),但您必須先要求特殊模組,才能修補標準方法,確保這些方法正常運作:

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

要求記錄器相容性模組後,您可以在程式碼中照常使用 console.log() 方法:

exports.helloError = functions.https.onRequest((request, response) => {
  console.log('I am a log entry!');
  response.send('Hello World...');
});
  • console.log() 指令的記錄層級為 INFO。
  • console.info() 指令的記錄層級為 INFO。
  • console.warn() 指令的記錄層級為 ERROR。
  • console.error() 指令的記錄層級為 ERROR。
  • 內部系統訊息具有 DEBUG 記錄層級。

查看記錄

您可以在 Google Cloud 控制台、Cloud Logging UI 或透過 firebase 指令列工具查看 Cloud Functions 的記錄。

使用 Firebase CLI

如要使用 firebase 工具查看記錄,請使用 functions:log 指令:

firebase functions:log

如要查看特定函式的記錄檔,請提供函式名稱做為引數:

firebase functions:log --only <FUNCTION_NAME>

如需完整的記錄檢視選項,請參閱 functions:log 的說明:

firebase help functions:log

使用 Google Cloud 控制台

您可以在 Google Cloud 控制台查看函式記錄。

使用 Cloud Logging UI

您可以在 Cloud Logging UI 中查看 Cloud Functions 的記錄。

分析記錄檔

Cloud Logging 提供功能強大的記錄分析工具套件,可用於監控 Cloud Functions。

圖表和快訊

建立記錄指標來監控函式後,您就能根據這些指標建立圖表和快訊。舉例來說,您可以建立圖表,將延遲時間以視覺化方式呈現,也可以建立快訊,在特定錯誤發生次數過多時通知您。

如要進一步瞭解如何在圖表和快訊政策中使用記錄指標,請參閱「建立圖表和快訊」。

瞭解並使用執行 ID

根據預設,Cloud Run functions (第 2 代) 支援在單一函式執行個體中並行執行多個要求。也就是說,不同要求的記錄可能會交錯,導致難以追蹤單一執行的流程。

為此,使用 Firebase CLI 13.33.0 以上版本部署的函式,會自動部署並提供選項,可將執行 ID 與該執行作業處理期間發出的每個記錄項目建立關聯。

執行 ID 可明確識別與函式處理的單一要求相關聯的所有記錄。您不必變更程式碼,系統會自動將執行 ID 新增至記錄。

如要在記錄項目中停用記錄執行 ID,請在 dotenv 檔案中將環境變數 LOG_EXECUTION_ID 設為 false。

依執行 ID 尋找並關聯記錄

您可以在 Cloud Logs Explorer 中,依執行 ID 檢查及關聯記錄。

  1. 展開函式的記錄項目。執行 ID 位於結構化記錄資料中,並以 labels.execution_id 形式內嵌於標籤下方。

  2. 按一下 execution_id 的值,然後從下拉式選單中選取「Show matching entries」(顯示相符的項目),即可查看與該函式執行作業相關的所有其他記錄。

即使函式同時處理多個要求,您也可以使用執行 ID,將與單一要求相關的所有記錄訊息歸為一組。

使用自訂摘要欄位提升記錄可見度

如要在 Logs Explorer 中更清楚地顯示執行 ID,可以將其新增為 [自訂摘要欄位][cloud-logging-preference]。將執行 ID 新增為摘要欄位後,每個記錄項目都會在記錄行開頭顯示執行 ID 做為方塊,與第 1 代函式為所有記錄項目顯示執行 ID 的方式類似。

如要在摘要欄位中新增執行 ID,請按照下列步驟操作:

  1. 在 labels.execution_id 下的結構化記錄項目中,按一下執行 ID 的值。

  2. 從下拉式選單中選取「Add field to summary line」(在摘要行中新增欄位)。

現在每個記錄項目都會在摘要欄位中醒目顯示 executionId,方便您識別及分組與特定執行 ID 相關聯的記錄。