Как сгруппировать связанные записи журнала запросов GAE python 3.7 стандарт env - PullRequest
2 голосов
/ 13 мая 2019

Я использую стандарт Google App Engine python 3.7 и пытаюсь сгруппировать связанные записи в журнале запросов. Согласно документации Запись журналов приложений , я должен:

Установите идентификатор трассировки в поле трассировки LogEntry журнала приложения. записей. Ожидаемый формат проекты / [PROJECT_ID] / следы / [TRACE_ID]

Где / Как следует использовать LogEntry?

Документация Stackdriver Logging не показывает, как это возможно. Я что-то упустил?

Примеры кода очень приветствуются.

[ОБНОВЛЕНО] Следуя совету Duck Hunt Duo , я безуспешно пробовал следующее:

    trace_id = request.headers.get('X-Cloud-Trace-Context', 'no_trace_id').split('/')[0]
    client = logging.Client()
    logger = client.logger('appengine.googleapis.com%2Fstdout')  # Not shown
    # logger = client.logger('projects/{}/logs/stdout'.format(GOOGLE_CLOUD_PROJECT)) # error
    # logger = client.logger('projects/{}/logs/appengine.googleapis.com%2Fstdout'.format(GOOGLE_CLOUD_PROJECT)) # error

    logger.log_text('log_message', trace=trace_id)

Журнал не отображается в веб-консоли GAE service log

Ответы [ 3 ]

1 голос
/ 19 мая 2019

Возможно, вы захотите взглянуть на ответ, который я предоставил здесь .

(Этот ответ описывает, как добавить строгость ведения журналов в журналы Cloud Functions, записанные в Stackdriver, но основной рабочий процесс такой же)

Цитирование:

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

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

Редактировать:

Обновлениепредыдущий ответ с примером для App Engine:

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

app = Flask(__name__)

@app.route('/')
def logger():
    log_client = logging.Client()
    log_name = 'appengine.googleapis.com%2Fstdout'

    res = Resource( type='gae_app',
                    labels={
                        "project_id": "MY-PROJECT-ID",
                        "module_id": "MY-SERVICE-NAME"
                       })

    logger = log_client.logger(log_name)

    logger.log_struct({"message": "message string to log"}, resource=res, severity='ERROR') # As an example log message with a ERROR warning level

    return 'Wrote logs to {}.'.format(logger.name)

. Используя этот код в качестве примера, измените тип ресурса журнала на appengine.googleapis.com%2Fstdout, и измените поля Resource натак же, как в метках gae_app, описанных в здесь .

1 голос
/ 20 мая 2019

Это мое основное решение:

    trace_id = request.headers.get('X-Cloud-Trace-Context', 'no_trace_id').split('/')[0]
    trace_str = "projects/{}/traces/{}".format(os.getenv('GOOGLE_CLOUD_PROJECT'), trace_id)
    log_client = logging.Client()

    # This is the resource type of the log
    log_name = 'stdout'

    # Inside the resource, nest the required labels specific to the resource type
    labels = {
        'module_id': os.getenv('GAE_SERVICE'),
        'project_id': os.getenv('GOOGLE_CLOUD_PROJECT'),
        'version_id': os.getenv('GAE_VERSION')
    }
    res = Resource(type="gae_app",
                   labels=labels,
                   )
    logger = log_client.logger(log_name)
    logger.log_text("MESSAGE_STRING_TO_LOG", resource=res, severity='ERROR', trace=trace_str)

После того, как он заработал, я обернул его в файл, чтобы он работал аналогично логгеру Google для python2.7.

Вот мой_gae_logging.py:

import logging as python_logging
import os

from flask import request
from google.cloud import logging as gcp_logging
from google.cloud.logging.resource import Resource

# From GCP logging lib for Python2.7
CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0

_levelNames = {
    CRITICAL: 'CRITICAL',
    ERROR: 'ERROR',
    WARNING: 'WARNING',
    INFO: 'INFO',
    DEBUG: 'DEBUG',
    NOTSET: 'NOTSET',
    'CRITICAL': CRITICAL,
    'ERROR': ERROR,
    'WARN': WARNING,
    'WARNING': WARNING,
    'INFO': INFO,
    'DEBUG': DEBUG,
    'NOTSET': NOTSET,
}


def get_trace_id():
    trace_str = None
    try:
        trace_id = request.headers.get('X-Cloud-Trace-Context', 'no_trace_id').split('/')[0]
        trace_str = "projects/{project_id}/traces/{trace_id}".format(
            project_id=os.getenv('GOOGLE_CLOUD_PROJECT'),
            trace_id=trace_id)
    except:
        pass
    return trace_str


class Logging:
def __init__(self):
    self._logger = None

@property
def logger(self):
    if self._logger is not None:
        return self._logger

    log_client = gcp_logging.Client()

    # This is the resource type of the log
    log_name = 'appengine.googleapis.com%2Fstdout'

    # Inside the resource, nest the required labels specific to the resource type

    self._logger = log_client.logger(log_name)
    return self._logger

@property
def resource(self):
    resource = Resource(
        type="gae_app",
        labels={
            'module_id': os.getenv('GAE_SERVICE'),
            'project_id': os.getenv('GOOGLE_CLOUD_PROJECT'),
            'version_id': os.getenv('GAE_VERSION')
        }
    )
    return resource

def log(self, text):
    text = str(text)
    self.logger.log_text(text, resource=self.resource, trace=get_trace_id())

def debug(self, text):
    text = str(text)
    self.logger.log_text(text, resource=self.resource, severity=_levelNames.get(DEBUG), trace=get_trace_id())

def info(self, text):
    text = str(text)
    self.logger.log_text(text, resource=self.resource, severity=_levelNames.get(INFO), trace=get_trace_id())

def warning(self, text):
    text = str(text)
    self.logger.log_text(text, resource=self.resource, severity=_levelNames.get(WARNING), trace=get_trace_id())

def warn(self, text):
    return self.warning(text)

def error(self, text):
    text = str(text)
    self.logger.log_text(text, resource=self.resource, severity=_levelNames.get(ERROR), trace=get_trace_id())

def critical(self, text):
    text = str(text)
    self.logger.log_text(text, resource=self.resource, severity=_levelNames.get(CRITICAL), trace=get_trace_id())


if os.getenv('GAE_VERSION'):  # check if running under gcp env
    logging = Logging()
else:
    # when not running under gcp env, use standard python_logging
    logging = python_logging

Использование:

from my_gae_logging import logging

logging.warn('this is my warning')
1 голос
/ 15 мая 2019

Клиентская библиотека Stackdriver Logging может использоваться для достижения этой цели. Функция logger.log_text отправляет объект LogEntry в API. Пример:

from google.cloud import logging

client = logging.Client()
logger = client.logger('appengine.googleapis.com%2Fstdout')
logger.log_text('log_message', trace=trace_id)

trace_id должен быть извлечен из заголовков запроса, как указано в документации. Способ выполнения этого будет зависеть от того, как вы обслуживаете запросы, но, например, во Flask это будет просто: trace_id = request.headers['X-Cloud-Trace-Context'].split('/')[0]

...