寫入和檢視記錄


記錄是用於偵錯及監控程式碼的重要工具。Cloud Functions 可讓您選擇使用 Node.jsPython 的記錄器 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() 時,您可以編寫記錄項目,並使用其他記錄嚴重性層級 CRITICALALERTEMERGENCY。請參閱「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.logconsole.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 函式 (第 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,您可以將其新增為自訂摘要欄位。這會在每個記錄項目列的開頭顯示執行 ID 做為方塊,類似第 1 代函式為所有記錄項目顯示執行 ID 的方式。

如何在摘要欄位中新增執行 ID:

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

  2. 從下拉式選單中選取「新增欄位至摘要行」。

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