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


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

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

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

استخدام حزمة SDK لتسجيل Cloud Functions

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

  • تمتلك أوامر 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() مستوى التسجيل خطأ.
  • تتضمّن أوامر console.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.

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

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

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