Подтвердить что ты не робот

Ведение журнала python в базе данных

Я ищу способ позволить модулю журнала python регистрироваться в базе данных и возвращаться в файловую систему, когда db не работает.

Итак, в основном 2 вещи: как разрешить журнал регистрации в базе данных и как заставить его упасть до регистрации файлов, когда db не работает.

4b9b3361

Ответ 1

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

Ответ 2

Недавно мне удалось написать собственный регистратор баз данных на Python. Так как я не смог найти ни одного примера, я решил опубликовать свой здесь. Работает с MS SQL.

Таблица базы данных может выглядеть следующим образом:

CREATE TABLE [db_name].[log](
    [id] [bigint] IDENTITY(1,1) NOT NULL,
    [log_level] [int] NULL,
    [log_levelname] [char](32) NULL,
    [log] [char](2048) NOT NULL,
    [created_at] [datetime2](7) NOT NULL,
    [created_by] [char](32) NOT NULL,
) ON [PRIMARY]

Сам класс:

class LogDBHandler(logging.Handler):
    '''
    Customized logging handler that puts logs to the database.
    pymssql required
    '''
    def __init__(self, sql_conn, sql_cursor, db_tbl_log):
        logging.Handler.__init__(self)
        self.sql_cursor = sql_cursor
        self.sql_conn = sql_conn
        self.db_tbl_log = db_tbl_log

    def emit(self, record):
        # Set current time
        tm = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(record.created))
        # Clear the log message so it can be put to db via sql (escape quotes)
        self.log_msg = record.msg
        self.log_msg = self.log_msg.strip()
        self.log_msg = self.log_msg.replace('\'', '\'\'')
        # Make the SQL insert
        sql = 'INSERT INTO ' + self.db_tbl_log + ' (log_level, ' + \
            'log_levelname, log, created_at, created_by) ' + \
            'VALUES (' + \
            ''   + str(record.levelno) + ', ' + \
            '\'' + str(record.levelname) + '\', ' + \
            '\'' + str(self.log_msg) + '\', ' + \
            '(convert(datetime2(7), \'' + tm + '\')), ' + \
            '\'' + str(record.name) + '\')'
        try:
            self.sql_cursor.execute(sql)
            self.sql_conn.commit()
        # If error - print it out on screen. Since DB is not working - there's
        # no point making a log about it to the database :)
        except pymssql.Error as e:
            print sql
            print 'CRITICAL DB ERROR! Logging to database not possible!'

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

import pymssql
import time
import logging

db_server = 'servername'
db_user = 'db_user'
db_password = 'db_pass'
db_dbname = 'db_name'
db_tbl_log = 'log'

log_file_path = 'C:\\Users\\Yourname\\Desktop\\test_log.txt'
log_error_level     = 'DEBUG'       # LOG error level (file)
log_to_db = True                    # LOG to database?

class LogDBHandler(logging.Handler):
    [...]

# Main settings for the database logging use
if (log_to_db):
    # Make the connection to database for the logger
    log_conn = pymssql.connect(db_server, db_user, db_password, db_dbname, 30)
    log_cursor = log_conn.cursor()
    logdb = LogDBHandler(log_conn, log_cursor, db_tbl_log)

# Set logger
logging.basicConfig(filename=log_file_path)

# Set db handler for root logger
if (log_to_db):
    logging.getLogger('').addHandler(logdb)
# Register MY_LOGGER
log = logging.getLogger('MY_LOGGER')
log.setLevel(log_error_level)

# Example variable
test_var = 'This is test message'

# Log the variable contents as an error
log.error('This error occurred: %s' % test_var)

Выше войдет как в базу данных, так и в файл. Если файл не нужен - пропустите строку 'logging.basicConfig(filename = log_file_path)'. Все, что зарегистрировано с помощью 'log' - будет зарегистрировано как MY_LOGGER. Если появляется какая-то внешняя ошибка (то есть в импортированном модуле или что-то в этом роде) - ошибка будет отображаться как "root", так как "root" logger также активен и использует обработчик базы данных.

Ответ 3

Я снова выкапываю это.

Существует решение с SqlAlchemy (пирамида НЕ требуется для этого рецепта):

https://docs.pylonsproject.org/projects/pyramid-cookbook/en/latest/logging/sqlalchemy_logger.html

И вы можете улучшить регистрацию, добавив дополнительные поля, вот руководство: fooobar.com/questions/122082/...

Возврат к FS

Не уверен, что это на 100% правильно, но у вас может быть 2 обработчика:

  • обработчик базы данных (запись в БД)
  • обработчик файла (запись в файл или поток)

Просто оберните DB-commit с помощью try-except. Но имейте в виду: файл будет содержать ВСЕ записи журнала, но не только записи, для которых было выполнено сбой БД.

Ответ 4

Вы видели библиотеку log4mongo? https://pypi.python.org/pypi/log4mongo/ Он обеспечивает ручку для Mongo. Резервного отказа нет, но я полагаю, что было бы относительно легко добавить.

Ответ 5

Старый вопрос, но отбрасывающий это для других. Если вы хотите использовать ведение журнала python, вы можете добавить два обработчика. Один для записи в файл, вращающийся обработчик файлов. Это надежное и может быть выполнено независимо от того, вставлен ли дБ или нет. Другой может написать другой сервис/модуль, например, интеграцию pymongo.

Посмотрите logging.config о том, как настроить обработчики из кода или json.