Формат журнала с несколькими отметками времени? - PullRequest
0 голосов
/ 09 мая 2018

В связи с конкретными требованиями моего приложения, мне нужно добавить одну и ту же метку времени к одной записи журнала, но с разными форматами для каждой метки времени. Эти две метки времени НЕ являются смежными друг с другом, поэтому другие поля записей журнала находятся между ними. Поскольку datefmt передается как второй параметр против format в formatter, мне еще предстоит выяснить, как вы можете предоставить два разных формата даты для одной записи в журнале.

Единственный вопрос, который я задаю, - возможно ли это с помощью Python БЕЗ пользовательских форматтеров или фильтров.

Ответы [ 2 ]

0 голосов
/ 17 мая 2018

Это невозможно в stdlib logging из-за способа написания исходного кода. Класс форматера установит asctime для каждого экземпляра LogRecord с помощью метода formatTime. Как видно из модуля ведения журнала, код здесь , соответствующее поле %(asctime) на самом деле является строковым атрибутом, а не экземпляром datetime. Это означает, что он не может принимать пользовательское форматирование, кроме простых строковых операций, таких как заполнение и выравнивание.

Я согласен с вами, что это является недостатком модуля stdlib logging, и призываю вас рассмотреть более мощную структуру ведения журналов, такую ​​как structlog .

Другие читатели вашего вопроса могут быть не против использования подкласса Formatter в журнале stdlib. Для них я бы предложил определить средство форматирования, которое использует экземпляр datetime для экземпляра LogRecord в сочетании со строкой шаблона форматера в фигурных скобках. Это позволяет неограниченно использовать поле asctime с несколькими форматами strftime.

Настройка проще, чем использование Filter или LoggingAdapter, это просто переопределение метода formatTime на одну строку:

import logging
from datetime import datetime

class MyFormatter(logging.Formatter):
    def formatTime(self, record, datefmt=None):
        return datetime.fromtimestamp(record.created)

fmt = '{asctime:%Y-%m-%d %H:%M:%S} - {levelname} - {asctime:%a %b %d %Y} - {message}'
logger = logging.getLogger()
handler = logging.StreamHandler()
handler.setFormatter(MyFormatter(fmt=fmt, style='{'))
logger.addHandler(handler)
logger.warning('the message')

Примечание: если один из необходимых вам форматов - это просто временная метка (секунды с начала эпохи), то вам вообще не нужна настраиваемая «гимнастика» Formatter - вы можете просто использовать created поле (которое принимает настройки форматирования с плавающей запятой) в сочетании с полем asctime.

0 голосов
/ 09 мая 2018

Очень простой пример с необработанной отметкой времени и удобочитаемой датой:

import logging
import sys
from datetime import datetime


class ContextFilter(logging.Filter):
    """
    This is a filter which injects contextual information into the log.
    """

    @staticmethod
    def some_format(timestamp):
        return datetime.fromtimestamp(
            timestamp
        ).strftime('%Y-%m-%d %H:%M:%S')

    def filter(self, record):

        record.format1 = record.created
        record.format2 = self.some_format(record.created)
        return True


formatter = logging.Formatter('%(format1)s - %(format2)s - %(name)s - %(levelname)s: %(message)s')
handler = logging.StreamHandler(sys.stdout)
handler.setFormatter(formatter)
handler.setLevel(logging.DEBUG)
logger = logging.Logger('test')
logger.addHandler(handler)

f = ContextFilter()
logger.addFilter(f)

logger.info('test')

Выход: 1525883052.4808118 - 2018-05-09 19:24:12 - test - INFO: test

...