Ведение логов — важный инструмент для отладки и мониторинга кода. Cloud Functions предоставляет возможность использовать SDK для логирования для Node.js или Python , либо стандартный объект console для веб-разработки.
Облачное логирование — это платная услуга; с вас может быть взиматься плата, если вы превысите бесплатный лимит. Для получения дополнительной информации см. раздел «Цены на облачное логирование» .
Ведение журналов
Использование 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()имеют уровень логирования WARNING .Команды
logger.error()имеют уровень логирования ERROR .Команды
logger.debug()имеют уровень логирования DEBUG .Внутренние системные сообщения имеют уровень логирования 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 . - Внутренние системные сообщения имеют уровень логирования DEBUG .
Просмотр журналов
Журналы 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 (2-го поколения) поддерживают одновременное выполнение нескольких запросов в рамках одного экземпляра функции. Это означает, что журналы разных запросов могут чередоваться, что затрудняет отслеживание хода выполнения одного запроса.
Для решения этой задачи функции, развернутые с помощью Firebase CLI версии 13.33.0 и более поздних версий, автоматически развертываются с возможностью присвоения идентификатора выполнения каждой записи в журнале, генерируемой во время обработки этого выполнения.
Идентификатор выполнения однозначно определяет все записи в логах, связанные с одним запросом, обработанным вашей функцией. Изменения в коде не требуются; идентификатор выполнения будет автоматически добавлен в ваши логи.
Чтобы отключить запись идентификатора выполнения в лог-файлы, установите переменную среды LOG_EXECUTION_ID в значение false в файле dotenv.
Найти и сопоставить журналы по идентификатору выполнения.
В Cloud Logs Explorer вы можете просматривать и сопоставлять журналы по идентификатору выполнения.
Разверните запись в журнале из вашей функции. Идентификатор выполнения находится в структурированных данных журнала, вложенных в метки как
labels.execution_id.Щелкните значение
execution_idи выберите в раскрывающемся меню «Показать соответствующие записи», чтобы просмотреть все остальные журналы, связанные с выполнением той же функции.
Используя идентификатор выполнения, вы можете сгруппировать все сообщения журнала, относящиеся к одному запросу, даже если ваша функция обрабатывает несколько запросов одновременно.
Повысьте наглядность журналов с помощью настраиваемых полей сводки.
Чтобы идентификатор выполнения был более наглядным в обозревателе журналов, вы можете добавить его в качестве [пользовательского поля сводки][настройки облачного логирования]. После добавления идентификатора выполнения в качестве поля сводки, каждая запись журнала будет отображать идентификатор выполнения в виде значка в начале строки журнала, аналогично тому, как функции первого поколения отображали идентификатор выполнения для всех записей журнала.
Чтобы добавить идентификатор выполнения в поле сводки:
Щелкните значение идентификатора выполнения в записи структурированного журнала в разделе
labels.execution_id.Выберите пункт «Добавить поле в сводную строку» из выпадающего меню.
Теперь в поле сводки для каждой записи журнала идентификатор executionId отображается четко, что упрощает идентификацию и группировку журналов, связанных с конкретным идентификатором выполнения.