Облачные функции Google Python Logging проблема

Я не уверен, как это сказать, но я чувствую, что под капотом есть что-то, что было изменено Google без моего ведома об этом. Раньше я получал журналы от своих облачных функций python в консоли Google Cloud на панели инструментов журналов. И теперь он просто перестал работать.

Так что я долго занимался исследованиями, я просто сделал журнал Hello World Python Cloud Function:

import logging

def cf_endpoint(req):
    logging.debug('log debug')
    logging.info('log info')
    logging.warning('log warning')
    logging.error('log error')
    logging.critical('log critical')
    return 'ok'

Так что это мой main.py, который я развернул как облачную функцию с триггером http.

Так как у меня был фильтр исключения входа в систему со всеми журналами уровня "отладки", я ничего не видел на панели управления журналами. Но когда я удалил это, я обнаружил это:

Таким образом, кажется, что то, что анализировало встроенные записи журнала python в stackdriver, перестало анализировать параметр серьезности журнала! Извините, если выгляжу глупо, но это единственное, о чем я могу думать: /

У вас есть какие-нибудь объяснения или решения для этого? я делаю это неправильно?

Спасибо заранее за вашу помощь.

6 ответов

Stackdriver Фильтры серьезности ведения журнала больше не поддерживаются при использовании собственного модуля ведения журнала Python.

Однако вы все равно можете создавать журналы с определенной степенью серьезности с помощью клиентских библиотек журналирования Stackdriver. Посмотрите эту документацию в отношении библиотек Python, а также несколько примеров использования.

Обратите внимание, что для того, чтобы журналы находились под правильным ресурсом, вам придется вручную настроить их, см. Этот список поддерживаемых типов ресурсов. Кроме того, каждый тип ресурса имеет некоторые обязательные метки, которые должны присутствовать в структуре журнала.

Например, следующий код запишет журнал в ресурс Cloud Function, в журнале Stackdriver, с ERROR строгость:

from google.cloud import logging
from google.cloud.logging.resource import Resource

log_client = logging.Client()

# This is the resource type of the log
log_name = 'cloudfunctions.googleapis.com%2Fcloud-functions' 

# Inside the resource, nest the required labels specific to the resource type
res = Resource(type="cloud_function", 
               labels={
                   "function_name": "YOUR-CLOUD-FUNCTION-NAME", 
                   "region": "YOUR-FUNCTION-LOCATION"
               },
              )
logger = log_client.logger(log_name.format("YOUR-PROJECT-ID"))
logger.log_struct(
 {"message": "message string to log"}, resource=res, severity='ERROR')

return 'Wrote logs to {}.'.format(logger.name) # Return cloud function response

Обратите внимание, что строки в YOUR-CLOUD-FUNCTION-NAME, YOUR-FUNCTION-LOCATION а также YOUR-PROJECT-ID, должны быть конкретными для вашего проекта / ресурса.

Я столкнулся с той же проблемой.

В ссылке, которой поделился @joan Grau, я также вижу, что есть способ интегрировать облачный регистратор с модулем ведения журнала Python, чтобы вы могли использовать корневой регистратор Python, как обычно, и все журналы будут отправляться в StackDriver Logging.

https://googleapis.github.io/google-cloud-python/latest/logging/usage.html

...

Я попробовал, и все работает. Короче говоря, вы можете сделать это двумя способами

Один простой способ привязать облачный логгер к корневому журналу

from google.cloud import logging as cloudlogging
import logging
lg_client = cloudlogging.Client()
lg_client.setup_logging(log_level=logging.INFO) # to attach the handler to the root Python logger, so that for example a plain logging.warn call would be sent to Stackdriver Logging, as well as any other loggers created.

В качестве альтернативы вы можете настроить регистратор с более точным контролем

from google.cloud import logging as cloudlogging
import logging
lg_client = cloudlogging.Client()

lg_handler = lg_client.get_default_handler()
cloud_logger = logging.getLogger("cloudLogger")
cloud_logger.setLevel(logging.INFO)
cloud_logger.addHandler(lg_handler)
cloud_logger.info("test out logger carrying normal news")
cloud_logger.error("test out logger carrying bad news")

Не желая иметь дело с библиотеками облачного логирования, я создал кастомный Formatter, который выдает структурированный лог с нужными полями, как этого ожидает облачное логирование.

      class CloudLoggingFormatter(logging.Formatter):
    """Produces messages compatible with google cloud logging"""
    def format(self, record: logging.LogRecord) -> str:
        s = super().format(record)
        return json.dumps(
            {
                "message": s,
                "severity": record.levelname,
                "timestamp": {"seconds": int(record.created), "nanos": 0},
            }
        )

Присоединение этого обработчика к регистратору приводит к тому, что журналы анализируются и правильно отображаются в консоли ведения журналов. В облачных функциях я бы настроил корневой регистратор для отправки на стандартный вывод и прикрепил к нему средство форматирования.

      # setup logging
root = logging.getLogger()
handler = logging.StreamHandler(sys.stdout)
formatter = CloudLoggingFormatter(fmt="[%(name)s] %(message)s")
handler.setFormatter(formatter)
root.addHandler(handler)
root.setLevel(logging.DEBUG)

Начиная с Python 3.8, вы можете просто printструктура JSON с severityа также messageхарактеристики. Например:

      print(
    json.dumps(
        dict(
            severity="ERROR",
            message="This is an error message",
            custom_property="I will appear inside the log's jsonPayload field",
        )
    )
)

Официальная документация: https://cloud.google.com/functions/docs/monitoring/logging#writing_structured_logs .

Чтобы использовать стандартный модуль ведения журнала Python в GCP (протестирован на Python 3.9), вы можете сделать следующее:

      import google.cloud.logging
client = google.cloud.logging.Client()
client.setup_logging()

import logging
logging.warning("A warning")

См. также: https://cloud.google.com/logging/docs/setup/python .

Я использую очень простую пользовательскую функцию ведения журнала для входа в Cloud Logging:

      import json

def cloud_logging(severity, message):
    print(json.dumps({"severity": severity, "message": message}))

cloud_logging(severity="INFO", message="Your logging message")
Другие вопросы по тегам