Logowanie to ważne narzędzie do debugowania i monitorowania kodu.
Cloud Functions umożliwia korzystanie z pakietu SDK rejestratora w przypadku Node.js lub Pythona albo obiektu console, który jest standardem w przypadku tworzenia aplikacji internetowych.
Cloud Logging to usługa płatna. Jeśli przekroczysz bezpłatny limit, możesz otrzymać rachunek. Więcej informacji znajdziesz w cenniku Cloud Logging.
Pisanie dzienników
Korzystanie z pakietu SDK rejestratora Cloud Functions
Pakiet SDK rejestratora Cloud Functions udostępnia standardowy interfejs do przekazywania stanu funkcji do Cloud Logging. Za pomocą tego pakietu SDK możesz rejestrować zdarzenia z danymi strukturalnymi, co ułatwia analizowanie i monitorowanie.
Importowanie z podpakietu logger:
Node.js
// All available logging functions
const {
log,
info,
debug,
warn,
error,
write,
} = require("firebase-functions/logger");
Python
from firebase_functions import logger
Polecenia
logger.log()mają poziom rejestrowania INFO.Polecenia
logger.info()mają poziom rejestrowania INFO.Polecenia
logger.warn()mają poziom logu WARNING.Polecenia
logger.error()mają poziom logu ERROR.Polecenia
logger.debug()mają poziom logowania DEBUG.Wewnętrzne wiadomości systemowe mają poziom dziennika DEBUG.
W tym przykładzie funkcja zapisuje podstawowy log:
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!")
Używaj różnych poziomów logowania dla różnych typów logów w kodzie funkcji. Uporządkowane dane można dołączyć do logu jako ostatni argument. Oto przykład, jak funkcja może używać poszczególnych typów logów:
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!")
Za pomocą logger.write() możesz pisać wpisy logu z dodatkowymi poziomami ważności logu: CRITICAL, ALERT i EMERGENCY. Zobacz 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)
Jak korzystać z aplikacji console.log
Zalecanym rozwiązaniem do rejestrowania danych z funkcji jest używanie pakietu SDK rejestratora na Twojej platformie. W Node.js możesz zamiast tego używać standardowych wywołań logowania w JavaScript, takich jak console.log i console.error, ale najpierw musisz zaimportować specjalny moduł, aby poprawić standardowe metody i zapewnić ich prawidłowe działanie:
require("firebase-functions/logger/compat");
Po zaimportowaniu modułu zgodności rejestratora możesz używać metod console.log() w kodzie w zwykły sposób:
exports.helloError = functions.https.onRequest((request, response) => {
console.log('I am a log entry!');
response.send('Hello World...');
});
- Polecenia
console.log()mają poziom rejestrowania INFO. - Polecenia
console.info()mają poziom rejestrowania INFO. - Polecenia
console.warn()mają poziom logu ERROR. - Polecenia
console.error()mają poziom logu ERROR. - Wewnętrzne wiadomości systemowe mają poziom dziennika DEBUG.
Wyświetlanie logów
Logi Cloud Functions można wyświetlać w Google Cloud konsoli,Cloud Logging interfejsie lub za pomocą narzędzia wiersza poleceń firebase.
Korzystanie z wiersza poleceń Firebase
Aby wyświetlić logi za pomocą narzędzia firebase, użyj polecenia functions:log:
firebase functions:log
Aby wyświetlić logi dotyczące konkretnej funkcji, podaj jej nazwę jako argument:
firebase functions:log --only <FUNCTION_NAME>
Pełny zakres opcji wyświetlania logów znajdziesz w pomocy dotyczącej functions:log:
firebase help functions:log
Korzystanie z konsoli Google Cloud
Logi funkcji możesz wyświetlać w Google Cloudkonsoli.
Korzystanie z interfejsu Cloud Logging
Logi Cloud Functions możesz wyświetlać w interfejsie Cloud Logging.
Analizowanie logów
Cloud Logging oferuje zaawansowany zestaw narzędzi do analizy logów, których możesz używać do monitorowania Cloud Functions.
Wykresy i alerty
Po utworzeniu wskaźników opartych na logach do monitorowania funkcji możesz tworzyć wykresy i alerty na podstawie tych wskaźników. Możesz na przykład utworzyć wykres, aby wizualizować opóźnienie w czasie, lub utworzyć alert, który będzie Cię informować, czy dany błąd występuje zbyt często.
Szczegółowe informacje o tym, jak używać wskaźników opartych na logach na wykresach i w zasadach tworzenia alertów, znajdziesz w artykule Tworzenie wykresów i alertów.
Zrozumienie i używanie identyfikatorów wykonania
Domyślnie funkcje Cloud Run (2 generacji) obsługują równoczesne wykonywanie wielu żądań w ramach jednej instancji funkcji. Oznacza to, że dzienniki z różnych żądań mogą być przeplatane, co utrudnia śledzenie przebiegu pojedynczego wykonania.
Aby to ułatwić, funkcje wdrażane za pomocą wiersza poleceń Firebase w wersji 13.33.0 i nowszych są automatycznie wdrażane z opcją powiązania identyfikatora wykonania z każdym wpisem w logu wygenerowanym podczas obsługi tego wykonania.
Identyfikator wykonania jednoznacznie identyfikuje wszystkie logi powiązane z pojedynczym żądaniem obsługiwanym przez funkcję. Nie musisz wprowadzać żadnych zmian w kodzie. Identyfikator wykonania zostanie automatycznie dodany do Twoich logów.
Aby wyłączyć rejestrowanie identyfikatora wykonania w swoich wpisach w logu, ustaw zmienną środowiskową LOG_EXECUTION_ID na wartość false w pliku dotenv.
Znajdowanie i korelacja logów według identyfikatora wykonania
W eksploratorze logów Cloud możesz sprawdzać i korelować logi według identyfikatora wykonania.
Rozwiń wpis logu z funkcji. Identyfikator wykonania znajduje się w danych dziennika strukturalnego, zagnieżdżonych pod etykietami jako
labels.execution_id.Kliknij wartość
execution_idi w menu wybierz „Pokaż pasujące wpisy”, aby wyświetlić wszystkie inne logi powiązane z tym samym wykonaniem funkcji.
Używając identyfikatora wykonania, możesz grupować wszystkie komunikaty dziennika związane z jednym żądaniem, nawet jeśli funkcja obsługuje wiele żądań jednocześnie.
Zwiększanie widoczności logów za pomocą niestandardowych pól podsumowania
Aby identyfikator wykonania był lepiej widoczny w Eksploratorze logów, możesz dodać go jako [niestandardowe pole podsumowania][cloud-logging-preference]. Po dodaniu identyfikatora wykonania jako pola podsumowania każdy wpis logu będzie zawierać identyfikator wykonania jako element na początku wiersza logu, podobnie jak funkcje 1 generacji wyświetlały identyfikator wykonania dla wszystkich wpisów logu.
Aby dodać identyfikator wykonania do pola podsumowania:
W strukturalnym wpisie dziennika kliknij wartość identyfikatora wykonania w sekcji
labels.execution_id.Z menu wybierz „Dodaj pole do wiersza podsumowania”.
W przypadku każdego wpisu w dzienniku w polu podsumowania jest teraz wyraźnie widoczny symbol executionId, co ułatwia identyfikowanie i grupowanie dzienników powiązanych z określonym identyfikatorem wykonania.