Как добавить номер строки кода, используя structlog - PullRequest
0 голосов
/ 25 февраля 2019

Используя стандартный модуль регистрации Python, можно добавить номер строки для исходного вызова журнала, используя: %(lineno)s.

Как это можно сделать с помощью structlog?

Ответы [ 2 ]

0 голосов
/ 05 июля 2019

Я закончил тем, что создал пользовательский процессор

Я посмотрел на что structlog делает для вывода модуля и номера строки, когда ему говорят "притворись" для форматирования в совместимом режиме с библиотекой logging (имеется в виду, когда он использует обычный stdlib.LoggerFactory), и я нашел в этом вдохновение.Ключ, в котором слова ...

Используя structlog structlog.stdlib.LoggerFactory, также обеспечивается правильное расширение переменных, таких как имена функций и номера строк, в формате журнала.

... С этой страницы документации

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

У меня есть все настройки для structlog внутри модуля с именем my_libs.util.logger, поэтому я хочу получить первый кадр, который НЕ находится внутри этого модуля, поэтому я сказал ему добавить к этим исключениям мой связанный с журналированием my_libs.util.logger.Вот что делает additional_ignores в приведенном ниже коде.

В примере я жестко закодировал имя модуля ('my_libs.util.logger') в списке исключений для ясности, но если у вас есть аналогичная настройка, вы, вероятно, будетелучше вместо этого использовать __name__.

Как только он найдет правильный кадр, извлечь любую информацию (имя модуля, имя функции, номер строки ...) очень легко, особенноиспользуя осмотреть модуль .Я решил вывести имя модуля и номер строки, но можно было бы добавить больше полей.

# file my_libs/util/logger.py
from structlog._frames import _find_first_app_frame_and_name

def show_module_info_processor(logger, _, event_dict):
    # If by any chance the record already contains a `modline` key,
    # (very rare) move that into a 'modline_original' key
    if 'modline' in event_dict:
        event_dict['modline_original'] = event_dict['modline']
    f, name = _find_first_app_frame_and_name(additional_ignores=[
        "logging",
        'my_libs.util.logger',  # could just be __name__
    ])
    if not f:
        return event_dict
    frameinfo = inspect.getframeinfo(f)
    if not frameinfo:
        return event_dict
    module = inspect.getmodule(f)
    if not module:
        return event_dict
    if frameinfo and module:
        event_dict['modline'] = '{}:{}'.format(
            module.__name__,
            frameinfo.lineno,
        )
    return event_dict

def setup_structlog(env=None):
    # . . . 
    ch.setFormatter(logging.Formatter('%(message)s'))

    logging.getLogger().handlers = [ch]

    processors = [
        structlog.stdlib.add_logger_name,
        structlog.stdlib.add_log_level,
        # . . . more . . . 
        show_module_info_processor,  # THIS!!!
        structlog.processors.TimeStamper(fmt="%Y-%m-%d %H:%M:%S"),
        structlog.processors.format_exc_info,
        structlog.processors.StackInfoRenderer(),
        # . . . more . . . 
    ]

    # . . . more . . . 
    structlog.configure_once(
        logger_factory=structlog.stdlib.LoggerFactory(),
        wrapper_class=structlog.stdlib.BoundLogger,
        context_class=structlog.threadlocal.wrap_dict(dict),
        processors=processors,
    )

Это приводит к выводу типа:

server_1                           
| INFO  [my_libs.hdfs] 2019-07-01 01:01:01 [info     ] Initialized HDFS               
[my_libs.hdfs] modline=my_libs.hdfs:31
0 голосов
/ 18 марта 2019

Посмотрите на этот ответ на более общий вопрос о том, как получить номер строки.https://stackoverflow.com/a/3056270/5909155 Это не может быть связано с регистратором с log.bind (...), потому что он должен оцениваться каждый раз, когда вы входите в систему.Таким образом, вы должны каждый раз добавлять пару ключ-значение, например,

logger.log(..., lineno=inspect.getframeinfo(inspect.currentframe()).lineno)

.Может быть, обернуть это в функцию, например, так: https://stackoverflow.com/a/20372465/5909155 Не забудьте

import inspect
...