Logowanie to ważne narzędzie do debugowania i monitorowania kodu.
Cloud Functions daje możliwość używania pakietu SDK rejestratora w przypadku Node.js lub Pythona albo standardowego obiektu console do 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 logowania WARNING.Polecenia
logger.error()mają poziom logowania ERROR.Polecenia
logger.debug()mają poziom logowania DEBUG.Wewnętrzne wiadomości systemowe mają poziom logowania DEBUG.
Ten przykład pokazuje funkcję zapisującą 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. Dane strukturalne 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!")
Dzięki logger.write() możesz pisać wpisy w dzienniku z dodatkowymi poziomami ważności logów: 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życie 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 zażądać specjalnego modułu, aby poprawić standardowe metody i zapewnić ich prawidłowe działanie:
require("firebase-functions/logger/compat");
Po zażądaniu modułu zgodności rejestratora możesz używać metod console.log() w kodzie w normalny 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 logowania ERROR. - Polecenia
console.error()mają poziom logowania ERROR. - Wewnętrzne wiadomości systemowe mają poziom logowania DEBUG.
Wyświetlanie logów
Logi Cloud Functions można wyświetlać w Google Cloudkonsoli, w interfejsie Cloud Logging 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 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
W interfejsie Cloud Logging możesz wyświetlać logi dotyczące Cloud Functions.
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 w wykresach i zasadach tworzenia alertów, znajdziesz w artykule Tworzenie wykresów i alertów.
Informacje o identyfikatorach wykonania i ich używanie
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 dzienniku 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 logów.
Aby wyłączyć rejestrowanie identyfikatora wykonania we wpisach dziennika, 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 w postaci elementu na początku wiersza logu, podobnie jak w przypadku funkcji 1 generacji, które wyświetlały identyfikator wykonania dla wszystkich wpisów logu.
Aby dodać identyfikator wykonania do pola podsumowania:
W strukturalnym wpisie logu kliknij wartość identyfikatora wykonania w sekcji
labels.execution_id.W menu kliknij „Dodaj pole do wiersza podsumowania”.
W przypadku każdego wpisu logu w polu podsumowania jest teraz wyraźnie widoczny symbol executionId, co ułatwia identyfikowanie i grupowanie logów powiązanych z określonym identyfikatorem wykonania.