ロギングは、コードのデバッグとモニタリングに重要なツールです。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 では、代わりに、console.log や console.error などの標準の JavaScript のロギング呼び出しを使用することもできますが、その場合は、標準のメソッドを正しく動作させるためのパッチとなる特別なモジュールを require する必要があります。
require("firebase-functions/logger/compat");
Logger 互換性モジュールを require したら、コード内で通常どおり 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 です。
ログの表示
Cloud Functions のログは、Google Cloud コンソール、Cloud Logging UI、firebase コマンドライン ツールで表示できます。
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 世代)は、1 つの関数インスタンス内で複数のリクエストを同時に実行することをサポートしています。つまり、異なるリクエストのログが交互に表示されるため、単一の実行のフローを追跡するのが難しくなります。
これを支援するため、Firebase CLI バージョン 13.33.0 以降を使用してデプロイされた関数は、実行の処理中に出力された各ログエントリに実行 ID を関連付けるオプションとともに自動的にデプロイされます。
実行 ID は、関数によって処理された単一のリクエストに関連付けられたすべてのログを一意に識別します。コードを変更する必要はありません。実行 ID はログに自動的に追加されます。
ログエントリでの実行 ID のロギングを無効にするには、dotenv ファイルで環境変数 LOG_EXECUTION_ID を false に設定します。
実行 ID でログを検索して関連付ける
Cloud ログ エクスプローラでは、実行 ID でログを検査して関連付けることができます。
- 関数からのログエントリを開きます。実行 ID は、構造化ログデータ内の - labels.execution_idというラベルの下にネストされて配置されています。
- execution_idの値をクリックし、プルダウン メニューから [一致するエントリを表示] を選択すると、同じ関数の実行に関連付けられている他のすべてのログが表示されます。
実行 ID を使用すると、関数が複数のリクエストを同時に処理している場合でも、単一のリクエストに関連するすべてのログメッセージをグループ化できます。
カスタム概要フィールドでログの可視性を高める
実行 ID をログ エクスプローラでより簡単に表示するには、実行 ID を [カスタム概要フィールド][cloud-logging-preference] として追加します。実行 ID を概要フィールドとして追加すると、第 1 世代の関数がすべてのログエントリの実行 ID を表示する方法と同様に、すべてのログエントリのログ行の先頭に実行 ID がチップとして表示されます。
概要フィールドに実行 ID を追加するには:
- 構造化ログエントリの - labels.execution_idにある実行 ID の値をクリックします。
- プルダウン メニューから [サマリー行にフィールドを追加] を選択します。 
各ログエントリのサマリー フィールドに executionId が目立つように表示されるようになりました。これにより、特定の実行 ID に関連付けられたログを簡単に識別してグループ化できるようになりました。