কোড ডিবাগিং এবং মনিটরিংয়ের জন্য লগিং একটি গুরুত্বপূর্ণ টুল। Cloud Functions আপনাকে Node.js বা Python-এর জন্য লগার SDK, অথবা ওয়েব ডেভেলপমেন্টের জন্য ব্যবহৃত console অবজেক্ট ব্যবহার করার সুযোগ দেয়।
ক্লাউড লগিং একটি সচার্জযোগ্য পরিষেবা; আপনি বিনামূল্যের কোটা অতিক্রম করলে আপনাকে বিল করা হতে পারে। আরও তথ্যের জন্য, ক্লাউড লগিং প্রাইসিং দেখুন।
লগ লেখা
Cloud Functions লগার SDK ব্যবহার করে
Cloud Functions লগার এসডিকে, ফাংশনগুলো থেকে ক্লাউড লগিং-এ স্ট্যাটাস রিপোর্ট করার জন্য একটি স্ট্যান্ডার্ড ইন্টারফেস প্রদান করে। আপনি এই এসডিকে ব্যবহার করে স্ট্রাকচার্ড ডেটা সহ ইভেন্ট লগ করতে পারেন, যা বিশ্লেষণ এবং পর্যবেক্ষণকে আরও সহজ করে তোলে।
logger সাবপ্যাকেজ থেকে ইম্পোর্ট করুন:
নোড.জেএস
// All available logging functions
const {
log,
info,
debug,
warn,
error,
write,
} = require("firebase-functions/logger");
পাইথন
from firebase_functions import logger
logger.log()কমান্ডগুলোর লগ লেভেল হলো INFO ।logger.info()কমান্ডগুলোর লগ লেভেল হলো INFO ।logger.warn()কমান্ডগুলোর লগ লেভেল হলো WARNING ।logger.error()কমান্ডগুলোর লগ লেভেল হলো ERROR ।logger.debug()কমান্ডগুলোর লগ লেভেল হলো DEBUG ।অভ্যন্তরীণ সিস্টেম বার্তাগুলোর লগ লেভেল হলো DEBUG ।
এই উদাহরণটি একটি সাধারণ লগ লেখার ফাংশন প্রদর্শন করে:
নোড.জেএস
exports.helloWorld = onRequest((request, response) => {
// sends a log to Cloud Logging
log("Hello logs!");
response.send("Hello from Firebase!");
});
পাইথন
@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!")
আপনার ফাংশন কোডে বিভিন্ন ধরণের লগের জন্য ভিন্ন ভিন্ন লগ লেভেল ব্যবহার করুন। স্ট্রাকচার্ড ডেটা একটি লগের সাথে শেষ আর্গুমেন্ট হিসেবে সংযুক্ত করা যেতে পারে। একটি ফাংশন কীভাবে প্রতিটি লগ টাইপ ব্যবহার করতে পারে তার একটি উদাহরণ নিচে দেওয়া হলো:
নোড.জেএস
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});
});
পাইথন
@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 দেখুন।
নোড.জেএস
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,
});
});
পাইথন
@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 ব্যবহার করতে পারেন, কিন্তু স্ট্যান্ডার্ড মেথডগুলোকে সঠিকভাবে কাজ করানোর জন্য আপনাকে প্রথমে একটি বিশেষ মডিউল রিকোয়ার করতে হবে।
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 ।
লগ দেখা
Cloud Functions লগগুলো Google Cloud কনসোল , Cloud Logging ইউআই, অথবা firebase কমান্ড-লাইন টুলের মাধ্যমে দেখা যায়।
ফায়ারবেস সিএলআই ব্যবহার করে
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 নিরীক্ষণ করতে পারেন।
চার্ট এবং সতর্কতা
একবার আপনার ফাংশনগুলো নিরীক্ষণ করার জন্য লগ-ভিত্তিক মেট্রিক তৈরি করে নিলে, আপনি এই মেট্রিকগুলোর উপর ভিত্তি করে চার্ট এবং অ্যালার্ট তৈরি করতে পারেন। উদাহরণস্বরূপ, আপনি সময়ের সাথে সাথে লেটেন্সি দেখানোর জন্য একটি চার্ট তৈরি করতে পারেন, অথবা কোনো নির্দিষ্ট ত্রুটি খুব ঘন ঘন ঘটলে তা জানানোর জন্য একটি অ্যালার্ট তৈরি করতে পারেন।
চার্ট এবং অ্যালার্টিং পলিসিতে লগ-ভিত্তিক মেট্রিক্স কীভাবে ব্যবহার করতে হয়, সে সম্পর্কে বিস্তারিত তথ্যের জন্য “চার্ট এবং অ্যালার্ট তৈরি করা” দেখুন।
এক্সিকিউশন আইডিগুলো বুঝুন এবং ব্যবহার করুন
ডিফল্টরূপে, ক্লাউড রান ফাংশন (২য় প্রজন্ম) একটি একক ফাংশন ইনস্ট্যান্সের মধ্যে একাধিক অনুরোধের যুগপৎ নির্বাহ সমর্থন করে। এর মানে হলো, বিভিন্ন অনুরোধের লগগুলো একে অপরের সাথে মিশে যেতে পারে, যার ফলে একটি একক নির্বাহের প্রবাহ অনুসরণ করা কঠিন হয়ে পড়ে।
এই কাজে সাহায্য করার জন্য, Firebase CLI সংস্করণ 13.33.0 এবং তার পরবর্তী সংস্করণ ব্যবহার করে ডেপ্লয় করা ফাংশনগুলো স্বয়ংক্রিয়ভাবে এমন একটি বিকল্পসহ ডেপ্লয় হয়, যা কোনো এক্সিকিউশন পরিচালনার সময় নির্গত প্রতিটি লগ এন্ট্রির সাথে একটি এক্সিকিউশন আইডি যুক্ত করে দেয়।
এক্সিকিউশন আইডি আপনার ফাংশন দ্বারা পরিচালিত একটিমাত্র অনুরোধের সাথে যুক্ত সমস্ত লগ-কে অনন্যভাবে শনাক্ত করে। কোনো কোড পরিবর্তনের প্রয়োজন নেই; এক্সিকিউশন আইডি স্বয়ংক্রিয়ভাবে আপনার লগ-এ যুক্ত হয়ে যাবে।
আপনার লগ এন্ট্রিতে এক্সিকিউশন আইডি লগিং নিষ্ক্রিয় করতে, আপনার dotenv ফাইলে LOG_EXECUTION_ID এনভায়রনমেন্ট ভেরিয়েবলটির মান false সেট করুন।
এক্সিকিউশন আইডি দ্বারা লগগুলি খুঁজুন এবং সম্পর্কযুক্ত করুন।
আপনি ক্লাউড লগস এক্সপ্লোরারে এক্সিকিউশন আইডি দিয়ে লগগুলো পরিদর্শন ও সম্পর্ক স্থাপন করতে পারেন।
আপনার ফাংশন থেকে লগ এন্ট্রিটি প্রসারিত করুন। এক্সিকিউশন আইডিটি স্ট্রাকচার্ড লগ ডেটার মধ্যে,
labels.execution_idহিসেবে labels-এর অধীনে অবস্থিত।একই ফাংশন এক্সিকিউশনের সাথে সম্পর্কিত অন্য সমস্ত লগ দেখতে,
execution_idএর মানে ক্লিক করুন এবং ড্রপ-ডাউন মেনু থেকে "Show matching entries" নির্বাচন করুন।
এক্সিকিউশন আইডি ব্যবহার করে, আপনি একটিমাত্র অনুরোধের সাথে সম্পর্কিত সমস্ত লগ বার্তা একসাথে গ্রুপ করতে পারেন, এমনকি যদি আপনার ফাংশনটি একই সাথে একাধিক অনুরোধ পরিচালনা করে থাকে।
কাস্টম সারাংশ ফিল্ডের মাধ্যমে লগের দৃশ্যমানতা বৃদ্ধি করুন
লগস এক্সপ্লোরারে এক্সিকিউশন আইডি আরও সহজে দৃশ্যমান করার জন্য, আপনি এটিকে একটি [কাস্টম সামারি ফিল্ড][ক্লাউড-লগিং-প্রেফারেন্স] হিসেবে যোগ করতে পারেন। এক্সিকিউশন আইডিকে সামারি ফিল্ড হিসেবে যোগ করার পর, প্রতিটি লগ এন্ট্রির শুরুতে একটি চিপের মতো এক্সিকিউশন আইডি দেখা যাবে; ঠিক যেভাবে প্রথম প্রজন্মের ফাংশনগুলো সমস্ত লগ এন্ট্রির জন্য এক্সিকিউশন আইডি প্রদর্শন করত।
সামারি ফিল্ডে এক্সিকিউশন আইডি যোগ করতে:
স্ট্রাকচার্ড লগ এন্ট্রির
labels.execution_idঅধীনে থাকা এক্সিকিউশন আইডির মানটিতে ক্লিক করুন।ড্রপ-ডাউন মেনু থেকে 'সারাংশ লাইনে ফিল্ড যোগ করুন' নির্বাচন করুন।
এখন প্রতিটি লগ এন্ট্রির সামারি ফিল্ডে executionId স্পষ্টভাবে প্রদর্শিত হয়, ফলে একটি নির্দিষ্ট এক্সিকিউশন আইডির সাথে যুক্ত লগগুলোকে শনাক্ত করা এবং গ্রুপ করা সহজ হয়।