Как опустить пользовательский обработчик журналирования при особых условиях? - PullRequest
0 голосов
/ 24 февраля 2020

Я написал собственный обработчик, который помещает сообщения журнала в базу данных MySQL. Я хочу использовать этот обработчик, только если я правильно подключился с использованием библиотеки mysql -connector python. В противном случае я хочу опустить этот обработчик.

class LogDBHandler(logging.Handler):
    """Customized logging handler that puts logs to the database."""

    def __init__(self):
        super().__init__()
        self.table_name = 'log'
        self.counter = 0
        self.chunk = []
        self.sql_conn, self.sql_cursor = self.connect_to_db()
        # create log table if doesn't exist
        try:
            self.create_table()
        except mysql.connector.errors.ProgrammingError:
            pass

    @staticmethod
    def connect_to_db():
        """Connect to MySQL database to perform logging."""
        credentials = {
            "user": os.environ.get("DARWIN_DB_USER"),
            "password": os.environ.get("DARWIN_DB_PASSWORD"),
            "host": os.environ.get("DARWIN_DB_HOST", "127.0.0.1"),
            "port": os.environ.get("DARWIN_DB_PORT", "3306"),
            "database": os.environ.get("DARWIN_DB_NAME"),
        }
        db = mysql.connector.connect(**credentials)
        cursor = db.cursor()
        return db, cursor
    ...

Это файл конфигурации регистрации, где я храню все регистраторы, обработчики и т. Д. c.

[loggers]
keys=root

[handlers]
keys=root, db

[formatters]
keys=formatter

[logger_root]
level=DEBUG
handlers=root, db

[handler_root]
class=FileHandler
level=DEBUG
formatter=formatter
args=('darwin.log', 'w')

[handler_db]
class=libs.logger.LogDBHandler
level=DEBUG
formatter=formatter
args=()

[formatter_formatter]
format=%(asctime)s - %(name)-12s - %(levelname)-8s - %(message)s

Все отлично работает, если учетные данные базы данных действительны. Если они не правы, mysql.connector.errors.ProgrammingError исключение. Вместо того, чтобы закрывать всю программу, я хотел бы опустить этот пользовательский обработчик, если self.connect_to_db() вызывает исключение. Есть идеи, как этого добиться?

Заранее спасибо;)

Ответы [ 2 ]

1 голос
/ 24 февраля 2020

Повтор с рабочим макетом:

class LogDBHandler(logging.Handler):

    def __init__(self):
        super().__init__()
        self.sql_conn = None
        try:
            self.sql_conn, self.sql_cursor = self.connect_to_db()
        except:
            return None
    def emit(self, msg):
        pass

logging.handlers.LogDBHandler = LogDBHandler

Main: импорт logging.config из logdbhandler import LogDBHandler logging.config.fileConfig ('logconf.yaml',)

logger = logging.getLogger()
for l in logger.handlers:
    if isinstance(l, LogDBHandler):
        if not l.sql_conn:
            logger.removeHandler(l)

print(logger.handlers)
0 голосов
/ 25 февраля 2020

Решение, которое сработало для меня. Я знаю, что это не элегантно, но работает.

class LogDBHandler(logging.Handler):
    """Customized logging handler that puts logs to the database."""

    def __init__(self):
        super().__init__()
        self.table_name = 'log'
        self.counter = 0
        self.chunk = []
        self.sql_conn = self.connect_to_db()
        if self.sql_conn:
            self.sql_cursor = self.sql_conn.cursor()
            # create log table if doesn't exist
            self.create_log_table()
        else:
            print("DB Connection error")

    def emit(self, record):
        """Called on each log attempt."""
        if self.sql_conn:
            timestamp = time.strftime("%Y-%m-%d %H:%M:%S",
                                      time.localtime(record.created))
            self.chunk.append((record.name, record.levelname,
                               str(record.getMessage()), timestamp))
            self.counter += 1
            # Insert chunk of data into DB
            if self.counter % 1000 == 0:
                self.insert_chunk()

    def flush(self):
        """
        Handler destructor, close all db connection and insert final
        records into db.
        """
        if self.sql_conn:
            # Insert last chunk of data
            self.insert_chunk()
            # Close connection with DB
            self.sql_cursor.close()
            self.sql_conn.close()

    @staticmethod
    def connect_to_db():
        """Connect to MySQL database to perform logging."""
        credentials = {
            "user": os.environ.get("DARWIN_DB_USER"),
            "password": os.environ.get("DARWIN_DB_PASSWORD"),
            "host": os.environ.get("DARWIN_DB_HOST", "127.0.0.1"),
            "port": os.environ.get("DARWIN_DB_PORT", "3306"),
            "database": os.environ.get("DARWIN_DB_NAME"),
        }
        try:
            connection = mysql.connector.connect(**credentials)
            return connection
        except mysql.connector.errors.ProgrammingError:
            return None
...