寫入和檢視記錄


記錄是偵錯和監控程式碼的重要工具。 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 記錄檔探索工具中,依執行 ID 檢查及關聯記錄。

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

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

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

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

如要在記錄檔探索工具中更清楚地顯示執行 ID,可以將其新增為自訂摘要欄位。這會在每行記錄項目的開頭,以資訊方塊的形式顯示執行 ID,與第 1 代函式顯示所有記錄項目執行 ID 的方式類似。

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

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

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

現在每筆記錄項目都會在摘要欄位中醒目顯示 executionId,方便您找出與特定執行 ID 相關聯的記錄並加以分組。