Ведение журнала - всегда включать атрибуты класса - PullRequest
0 голосов
/ 06 августа 2020

В настоящее время мой код регистрирует два типа событий. Связанные с классом и не связанные с классом вещи.

Следовательно, у меня есть две функции, которые выводят информацию. Один за пределами класса и один внутри, потому что я хочу автоматически регистрировать атрибуты класса в каждом журнале без необходимости указывать их для каждой print() строки и просто передавать текст, который я хочу записать / распечатать, в функцию.

import datetime

def logging_andy(strng):
    print(datetime.datetime.now(), "---", strng)

class testClass():        
    def __init__(self, id, name):
        self.id = id
        self.name = name
        
    def logging_andy(self, strng):
        print(datetime.datetime.now(), "--- ID:", self.id, "/ Name:", "'" + self.name + "'", "---", strng)
        
test1 = testClass(123, "Test Class 1")
test1.logging_andy("This is a test log")

test2 = testClass(456, "Test Class 2")
test2.logging_andy("This is a test log")

logging_andy("This is a log unrelated to the testClass")

OUTPUT:
2020-08-06 19:15:03.747040 --- ID: 123 / Name: 'Test Class 1' --- This is a test log
2020-08-06 19:15:03.748040 --- ID: 456 / Name: 'Test Class 2' --- This is a test log
2020-08-06 19:15:03.748040 --- This is a log unrelated to the testClass

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

ЧТО Я ПЫТАЛ:

Я нашел это https://docs.python.org/2/howto/logging-cookbook.html#using -filters-to- impart-contextual-information , но возникли две проблемы:

  • Мне не удалось воспроизвести два типа ведения журнала, которые есть в моем примере (один атрибут класса ведения журнала и один просто текст, не связанный с классом )
  • А также в приведенном примере не регистрируется то, что на странице написано, по крайней мере, для меня

Мой результат:

2020-08-06 19:20:24 - a.b.c - DEBUG    A debug message
2020-08-06 19:20:24 - a.b.c - INFO     An info message with some parameters
2020-08-06 19:20:24 - d.e.f - CRITICAL A message at CRITICAL level with 2 parameters
2020-08-06 19:20:24 - d.e.f - DEBUG    A message at DEBUG level with 2 parameters
2020-08-06 19:20:24 - d.e.f - WARNING  A message at WARNING level with 2 parameters
2020-08-06 19:20:24 - d.e.f - INFO     A message at INFO level with 2 parameters
2020-08-06 19:20:24 - d.e.f - WARNING  A message at WARNING level with 2 parameters
2020-08-06 19:20:24 - d.e.f - CRITICAL A message at CRITICAL level with 2 parameters
2020-08-06 19:20:24 - d.e.f - INFO     A message at INFO level with 2 parameters
2020-08-06 19:20:24 - d.e.f - DEBUG    A message at DEBUG level with 2 parameters
2020-08-06 19:20:24 - d.e.f - INFO     A message at INFO level with 2 parameters
2020-08-06 19:20:24 - d.e.f - CRITICAL A message at CRITICAL level with 2 parameters

Пример вывода предоставлено по ссылке:

* 102 8 *

Ответы [ 2 ]

1 голос
/ 06 августа 2020

A Python 3 ответ, однако он также должен работать для синтаксиса Python 2.

Ведение журнала extras аргумент может помочь вам при необходимости включать переменные. При желании вы можете отправлять объекты (для контекста класса). Вот способ.

  1. ContextFilter для обработки отсутствующего объекта.
  2. Класс Test должен использовать функцию __repr__, чтобы представлять как интерпретировать ваш объект.
import logging, sys

class ContextFilter(logging.Filter):
    def filter(self, record):
        record.obj = record.obj if hasattr(record, "obj") else ""
        return True

class Test():
    def __init__(self, id, name):
        self.id = id
        self.name = name

    def __repr__(self):
        return " ".join(("{}: {}".format(k, v) for k, v in vars(self).items()))

    def log(self, msg):
        LOGGER.error(msg, extra={"obj": self})

Настройте простой регистратор следующим образом:

LOGGER = logging.getLogger(__name__)
HANDLE = logging.StreamHandler(sys.stdout)
HANDLE.setFormatter(logging.Formatter("%(asctime)-15s %(name)-5s %(levelname)-8s %(obj)-25s %(message)s"))

LOGGER.addFilter(ContextFilter())
LOGGER.addHandler(HANDLE)

Сравните два типа операторов.

t_andy = Test("001", "Andy")
t_mark = Test("002", "Mark")

t_andy.log("Andy can log.")
t_mark.log("Mark is no less.")

common_log("A common message not involving objects.")

Пора увидеть результаты:

2020-08-07 00:08:49,976 __main__ ERROR    id: 001 name: Andy        Andy can log.
2020-08-07 00:08:51,918 __main__ ERROR    id: 002 name: Mark        Mark is no less.
2020-08-07 00:08:52,401 __main__ ERROR                              A common message not involving objects.
0 голосов
/ 07 августа 2020

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

Спасибо @ Abhila sh за указание на это.

import logging

loglevel = "DEBUG"

logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s %(message)s',
#filename=localdir+'/logs/'+cc+'.log',
level=logging.getLevelName(loglevel),
datefmt='%Y-%m-%d %H:%M:%S')
logger=logging.getLogger('main')
logger.setLevel(loglevel)


def logging_andy(strng):
    logger.debug(strng)

class testClass():        
    def __init__(self, id, name):
        self.id = id
        self.name = name
        self.logger=logging.getLogger('classLogger')
        self.logger.setLevel(loglevel)
        
    def logging_andy(self, strng):
        self.logger.debug(f"--- ID: {self.id} / Name: '{self.name}' --- {strng}")
        
test1 = testClass(123, "Test Class 1")
test1.logging_andy("This is a text log")

test2 = testClass(456, "Test Class 2")
test2.logging_andy("This is a text log")

logging_andy("This is a log unrelated to a class")
...