python:日志记录:我们可以向记录器添加多个过滤器吗?考虑哪一个

标签 python django logging

我试图了解 Python 日志记录中的多个过滤器(一个在配置中定义,另一个在代码中定义)如何工作。

我正在开发一个 Django 项目,下面是我在 settings.py 中的记录器配置

我的目标是随时打开关闭记录器。因此,使用过滤器,我尝试通过返回 False (0) 来关闭记录器

1)在开始时关闭记录器

class StartFilter(object):
    def filter(self, record):
        """
        Determine if the specified record is to be logged.

        Is the specified record to be logged? Returns 0 for no, nonzero for
        yes. If deemed appropriate, the record may be modified in-place.
        """
        return 0

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'formatters': {
        'verbose': {
            'format': '%(levelname)s %(funcName)s() %(pathname)s[:%(lineno)s] %(name)s \n%(message)s'
        }
    },
    'handlers': {
        'console': {
            'level': 'DEBUG',
            'formatter': 'verbose',
            'class': 'logging.StreamHandler',
        },
    },
    'filters': {
        'myfilter': {
            '()': StartFilter,
        }
    },
    'loggers': {
        'log_testing': {
            'handlers': ['console'],
            'level': 'DEBUG',
            'propagate': False,
            'filters': ['myfilter']
        },
    }
}

我已将过滤器添加到记录器中。 '过滤器':['myfilter']

2)在我希望看到日志记录的views.py文件中打开和关闭记录器

# to switch on logger
class LoggerGateStart(object):
    def filter(self, record):
        """
        Determine if the specified record is to be logged.

        Is the specified record to be logged? Returns 0 for no, nonzero for
        yes. If deemed appropriate, the record may be modified in-place.
        """
        return 1

# to switch off logger
class LoggerGateStop(object):
    def filter(self, record):
        """
        Determine if the specified record is to be logged.

        Is the specified record to be logged? Returns 0 for no, nonzero for
        yes. If deemed appropriate, the record may be modified in-place.
        """
        return 0

import logging
logger = logging.getLogger("log_testing")


...
logging.debug("Some text Before)  # i dont want this to be logged
...



gatestart = LoggerGateStart()
logger_database.addFilter(gatestart)

...
logging.debug("Some text)  # i want this to be logged
...

gatestop = LoggerGateStop()
logger_database.addFilter(gatestop)

...
logging.debug("Some text after")  # i dont want this to be logged even 
if it exist
...

我发现它不能这样工作。它仅考虑 StartFilter,不考虑 LoggerGateStart 或 LoggerGateStop,并且不会将任何日志打印到控制台

我该怎么做

我根据 Gabriel C 的答案使用的答案

我的目标是使用 django django.db.backends 记录 sql 。但它的问题是它会记录所有的sql。我只想在代码的特定部分或我想查看 sql 的任何地方记录 sql。所以我可以通过以下方式做到这一点。

在settings.py中记录配置:

# Filter class to stop or start logging for "django.db.backends"
class LoggerGate:
    def __init__(self, state='closed'):
        # We found that the settings.py runs twice and the filters are created twice. So we have to keep only one. So we delete all the previous filters before we create the new one
        import logging
        logger_database = logging.getLogger("django.db.backends")
        try:
            for filter in logger_database.filters:
                logger_database.removeFilter(filter)
        except Exception as e:
            pass
        self.state = state

    def open(self):
        self.state = 'open'

    def close(self):
        self.state = 'closed'

    def filter(self, record):
        """
        Determine if the specified record is to be logged.

        Is the specified record to be logged? Returns 0/False for no, nonzero/True for
        yes. If deemed appropriate, the record may be modified in-place.
        """
        return self.state == 'open'

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'handlers': {
        'sql': {
            'class': 'logging.StreamHandler',
            'level': 'DEBUG',
        }
    },
    'filters': {
        'myfilter': {
            '()': LoggerGate,
        }
    },
    'loggers': {
        'django.db.backends': {
            'handlers': ['sql'],
            'level': 'DEBUG',
            'propagate': False,
            'filters': ['myfilter']
        }
    }
}

然后在views.py中

import logging
logger = logging.getLogger(__name__)
logger_database = logging.getLogger("django.db.backends")

def test1(request):


    logger_database.filters[0].open()
    #Will allow priting of sql satatements from here

    from django import db
    user_set = User.objects.all()

    for user in user_set: # Here sql is executed and is printed to console
        pass
    #Will stop priting of sql satatements after this
    logger_database.filters[0].close()

    from django import db
    user_set = User.objects.all()

    for user in user_set:  # Here sql is executed and is not printed to console
        pass

    now = datetime.datetime.now()
    html = "<html><body>Internal purpose</body></html>"
    return HttpResponse(html)

如果想以格式化且彩色的方式打印sql,请在settings.py中使用它

# SQL formatter to be used for the handler used in logging "django.db.backends"
class SQLFormatter(logging.Formatter):
    def format(self, record):

        # Check if Pygments is available for coloring 
        try:
            import pygments
            from pygments.lexers import SqlLexer
            from pygments.formatters import TerminalTrueColorFormatter
        except ImportError:
            pygments = None

        # Check if sqlparse is available for indentation
        try:
            import sqlparse
        except ImportError:
            sqlparse = None

        # Remove leading and trailing whitespaces
        sql = record.sql.strip()

        if sqlparse:
            # Indent the SQL query
            sql = sqlparse.format(sql, reindent=True)

        if pygments:
            # Highlight the SQL query
            sql = pygments.highlight(
                sql,
                SqlLexer(),
                #TerminalTrueColorFormatter(style='monokai')
                TerminalTrueColorFormatter()
            )

        # Set the record's statement to the formatted query
        record.statement = sql
        return super(SQLFormatter, self).format(record)




# Filter class to stop or start logging for "django.db.backends"
class LoggerGate:
    def __init__(self, state='closed'):
        # We found that the settings.py runs twice and the filters are created twice. So we have to keep only one. So we delete all the previous filters before we create the new one
        import logging
        logger_database = logging.getLogger("django.db.backends")
        try:
            for filter in logger_database.filters:
                logger_database.removeFilter(filter)
        except Exception as e:
            pass
        self.state = state

    def open(self):
        self.state = 'open'

    def close(self):
        self.state = 'closed'

    def filter(self, record):
        """
        Determine if the specified record is to be logged.

        Is the specified record to be logged? Returns 0/False for no, nonzero/True for
        yes. If deemed appropriate, the record may be modified in-place.
        """
        return self.state == 'open'

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'formatters': {
        'sql': {
            '()': SQLFormatter,
            'format': '[%(duration).3f] %(statement)s',
        }
    },
    'handlers': {
        'sql': {
            'class': 'logging.StreamHandler',
            'formatter': 'sql',
            'level': 'DEBUG',
        }
    },
    'filters': {
        'myfilter': {
            '()': LoggerGate,
        }
    },
    'loggers': {
        'django.db.backends': {
            'handlers': ['sql'],
            'level': 'DEBUG',
            'propagate': False,
            'filters': ['myfilter']
        }
    }
}

最佳答案

仅创建一个过滤器并使用其实例来控制是否应接受日志。

from logging import getLogger

class LoggerGate(object):

    def __init__(self):
        self.started = False

    def start(self):
        self.started = True

    def stop(self):
        self.started = False

    def filter(self, record):
        """
        Determine if the specified record is to be logged.

        Returns True is this LoggerGate is started, False otherwise.
        """
        return self.started


logger_database = getLogger("log_testing")
logger_gate = LoggerGate()
logger_database.addFilter(logger_gate)

logger_database.critical('this is not logged')
logger_gate.start()
logger_database.critical('this is logged')
logger_gate.stop()
logger_database.critical('this is not logged')

关于python:日志记录:我们可以向记录器添加多个过滤器吗?考虑哪一个,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57795153/

相关文章:

django - Heroku 是否剥离传入的 X-Forwarded-Proto header ?

python - Pandas:欧式date_range

python - 樱桃皮 : which solutions for pages with large processing time

python - 带有 python 循环的多线程

java - 将写入 Tomcat 的 catalina.out 日志级别的 servlet 的日志级别限制为

php - 将URL添加到错误日志(Wordpress,Nginx,PHP7)

java - 不能从静态上下文引用非静态方法 'getLogger'

python - 有没有更简洁的方法来测试 python3 中的长参数列表?

python - Django REST Framework 序列化程序 - 访问现有的外键

python - 如何在 Django 中向查询集添加自定义属性?