كتابة السجلّات وعرضها

يُعدّ التسجيل أداة مهمة لتصحيح أخطاء الرموز البرمجية ومراقبتها. تتيح لك منصة Cloud Functions استخدام حزمة تطوير البرامج (SDK) الخاصة بمسجّل البيانات في Node.js أو Python، أو معيار عنصر console للتطوير على الويب.

‫Cloud Logging هي خدمة مدفوعة، وقد يتم تحصيل رسوم منك إذا تجاوزت الحصة المجانية. لمزيد من المعلومات، يُرجى الاطّلاع على أسعار Cloud Logging.

كتابة السجلات

استخدام حزمة SDK الخاصة بمسجّل Cloud Functions

توفّر حزمة تطوير البرامج (SDK) الخاصة بمسجّل Cloud Functions واجهة عادية لإرسال تقارير عن الحالة من الدوال إلى 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() مستوى السجلّ تحذير.

  • يتضمّن الأمران (logger.error()) مستوى السجلّ ERROR.

  • تتضمّن أوامر logger.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.
  • تحتوي رسائل النظام الداخلية على مستوى السجلّ تصحيح الأخطاء.

عرض السجلّات

يمكن الاطّلاع على سجلّات Cloud Functions إما في وحدة تحكّم Google Cloud أو واجهة مستخدم Cloud Logging أو من خلال أداة سطر الأوامر 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

يمكنك الاطّلاع على سجلّات "Cloud Functions" في واجهة مستخدم "Cloud Logging".

تحليل السجلّات

يوفّر Cloud Logging حزمة فعّالة من أدوات تحليل السجلّات التي يمكنك استخدامها لمراقبة Cloud Functions.

الرسومات البيانية والتنبيهات

بعد إنشاء مقاييس مستندة إلى السجلّات لمراقبة دوالّك، يمكنك إنشاء رسوم بيانية وتنبيهات استنادًا إلى هذه المقاييس. على سبيل المثال، يمكنك إنشاء رسم بياني لعرض وقت الاستجابة بمرور الوقت، أو إنشاء تنبيه لإعلامك في حال حدوث خطأ معيّن بشكل متكرر.

يمكنك الاطّلاع على إنشاء الرسوم البيانية والتنبيهات للحصول على معلومات تفصيلية حول كيفية استخدام المقاييس المستندة إلى السجلّات في الرسوم البيانية وسياسات التنبيه.

فهم أرقام تعريف التنفيذ واستخدامها

تتيح دوال Cloud Run (الجيل الثاني) تلقائيًا التنفيذ المتزامن لطلبات متعددة ضمن مثيل دالة واحد. وهذا يعني أنّه يمكن تداخل السجلّات من طلبات مختلفة، ما يجعل من الصعب تتبُّع مسار عملية تنفيذ واحدة.

للمساعدة في ذلك، يتم نشر الدوال باستخدام الإصدار 13.33.0 من Firebase CLI والإصدارات الأحدث تلقائيًا مع خيار ربط معرّف تنفيذ بكل إدخال في السجلّ يتم إصداره أثناء معالجة هذا التنفيذ.

يحدّد رقم تعريف التنفيذ بشكل فريد جميع السجلّات المرتبطة بطلب واحد تعالجه الدالة. ولا يلزم إجراء أي تغييرات على الرموز، إذ ستتم إضافة معرّف التنفيذ تلقائيًا إلى سجلّاتك.

لإيقاف تسجيل معرّف التنفيذ في إدخالات السجلّ، اضبط متغيّر البيئة LOG_EXECUTION_ID على "خطأ" في ملف dotenv.

العثور على السجلّات وربطها حسب معرّف التنفيذ

يمكنك فحص السجلّات وربطها حسب رقم تعريف التنفيذ في "مستكشف سجلّات Cloud".

  1. وسِّع الإدخال في السجلّ من الدالة. يقع معرّف التنفيذ ضمن بيانات السجلّ المنظَّمة، وهو مُضمَّن ضمن التصنيفات باسم labels.execution_id.

  2. انقر على قيمة execution_id واختَر "عرض الإدخالات المطابقة" من القائمة المنسدلة للاطّلاع على جميع السجلّات الأخرى المرتبطة بتنفيذ الدالة نفسها.

باستخدام رقم تعريف التنفيذ، يمكنك تجميع كل الرسائل المسجّلة ذات الصلة بطلب واحد، حتى إذا كانت الدالة تعالج طلبات متعددة في الوقت نفسه.

تحسين مستوى ظهور السجلّات باستخدام حقول الملخّص المخصّصة

لتسهيل رؤية معرّف التنفيذ في &quot;مستكشف السجلّات&quot;، يمكنك إضافته كـ [حقل ملخّص مخصّص][cloud-logging-preference]. بعد إضافة رقم تعريف التنفيذ كحقل ملخّص، سيعرض كل إدخال في السجلّ رقم تعريف التنفيذ كشريحة في بداية سطر السجلّ، على غرار الطريقة التي عرضت بها دوال الجيل الأول رقم تعريف التنفيذ لجميع إدخالات السجلّ.

لإضافة معرّف التنفيذ إلى حقل الملخّص:

  1. انقر على قيمة رقم تعريف التنفيذ في إدخال السجلّ المنظَّم ضمن labels.execution_id.

  2. اختَر "إضافة حقل إلى سطر الملخّص" من القائمة المنسدلة.

يعرض كل إدخال في السجلّ الآن executionId بشكل بارز في حقل الملخّص، ما يسهّل تحديد السجلّات المرتبطة برقم تعريف تنفيذ معيّن وتجميعها.