Django的结构化日志记录

django-structlog的Python项目详细描述


django结构日志

PyPI versionPyPI - WheelBuild StatusDocumentation StatuscodecovGitHub issuesGitHub pull requests
PyPI - Django VersionSupported Python versionsLicenseBlack
GitHub watchersGitHub starsGitHub forks

django structlog是django项目的结构化日志集成,使用structlog

然后,日志记录将在每个日志上生成附加的内聚元数据,从而更容易跟踪事件或事件。

测井对比

标准日志:

>>>importlogging>>>logger=logging.get_logger(__name__)>>>logger.info("An error occurred")
An error occurred

好吧…好吧

带django structlog和扁平线:

>>>importstructlog>>>logger=structlog.get_logger(__name__)>>>logger.info("an_error_occurred",bar="Buz")
timestamp='2019-04-13T19:39:31.089925Z'level='info'event='an_error_occurred'logger='my_awesome_project.my_awesome_module'request_id='3a8f801c-072b-4805-8f38-e1337f363ed4'user_id=1ip='0.0.0.0'bar='Buz'

然后您可以使用以下命令进行搜索:

$ cat logs/flat_line.log | grep request_id='3a8f801c-072b-4805-8f38-e1337f363ed4'

使用django structlog和json
>>>importstructlog>>>logger=structlog.get_logger(__name__)>>>logger.info("an_error_occurred",bar="Buz")
{"request_id":"3a8f801c-072b-4805-8f38-e1337f363ed4","user_id":1,"ip":"0.0.0.0","event":"an_error_occurred","timestamp":"2019-04-13T19:39:31.089925Z","logger":"my_awesome_project.my_awesome_module","level":"info","bar":"Buz"}

然后您可以使用以下命令进行搜索:

$ cat logs/json.log | jq '.[] | select(.request_id="3a8f801c-072b-4805-8f38-e1337f363ed4")' -s

开始

这些步骤将展示如何将中间件集成到您出色的应用程序中。

安装

安装库

pip install django-structlog

添加中间件

MIDDLEWARE=[# ...'django_structlog.middlewares.RequestMiddleware',]

将适当的structlog配置添加到settings.py

importstructlogLOGGING={"version":1,"disable_existing_loggers":False,"formatters":{"json_formatter":{"()":structlog.stdlib.ProcessorFormatter,"processor":structlog.processors.JSONRenderer(),},"plain_console":{"()":structlog.stdlib.ProcessorFormatter,"processor":structlog.dev.ConsoleRenderer(),},"key_value":{"()":structlog.stdlib.ProcessorFormatter,"processor":structlog.processors.KeyValueRenderer(key_order=['timestamp','level','event','logger']),},},"handlers":{"console":{"class":"logging.StreamHandler","formatter":"plain_console",},"json_file":{"class":"logging.handlers.WatchedFileHandler","filename":"logs/json.log","formatter":"json_formatter",},"flat_line_file":{"class":"logging.handlers.WatchedFileHandler","filename":"logs/flat_line.log","formatter":"key_value",},},"loggers":{"django_structlog":{"handlers":["console","flat_line_file","json_file"],"level":"INFO",},"django_structlog_demo_project":{"handlers":["console","flat_line_file","json_file"],"level":"INFO",},}}structlog.configure(processors=[structlog.stdlib.filter_by_level,structlog.processors.TimeStamper(fmt="iso"),structlog.stdlib.add_logger_name,structlog.stdlib.add_log_level,structlog.stdlib.PositionalArgumentsFormatter(),structlog.processors.StackInfoRenderer(),structlog.processors.format_exc_info,structlog.processors.UnicodeDecoder(),structlog.processors.ExceptionPrettyPrinter(),structlog.stdlib.ProcessorFormatter.wrap_for_formatter,],context_class=structlog.threadlocal.wrap_dict(dict),logger_factory=structlog.stdlib.LoggerFactory(),wrapper_class=structlog.stdlib.BoundLogger,cache_logger_on_first_use=True,)

使用structlog而不是logging开始日志记录。

importstructloglogger=structlog.get_logger(__name__)

扩展请求日志元数据

默认情况下,只有一个request_iduser_id从请求绑定,但是相关的日志元数据可能因项目而异。

如果需要从请求中添加更多元数据,可以实现一个方便的信号接收器来绑定它们。

fromdjango.dispatchimportreceiverfromdjango_structlog.signalsimportbind_extra_request_metadata@receiver(bind_extra_request_metadata)defbind_user_email(request,logger,**kwargs):logger.bind(user_email=getattr(request.user,'email',''))

示例输出

平面线文件(logs/flat_lines.log

timestamp='2019-04-13T19:39:29.321453Z'level='info'event='request_started'logger='django_structlog.middlewares.request'request_id='c53dff1d-3fc5-4257-a78a-9a567c937561'user_id=1ip='0.0.0.0'request=<WSGIRequest: GET '/'> user_agent='Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36'timestamp='2019-04-13T19:39:29.345207Z'level='info'event='request_finished'logger='django_structlog.middlewares.request'request_id='c53dff1d-3fc5-4257-a78a-9a567c937561'user_id=1ip='0.0.0.0'code=200timestamp='2019-04-13T19:39:31.086155Z'level='info'event='request_started'logger='django_structlog.middlewares.request'request_id='3a8f801c-072b-4805-8f38-e1337f363ed4'user_id=1ip='0.0.0.0'request=<WSGIRequest: POST '/success_task'> user_agent='Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36'timestamp='2019-04-13T19:39:31.089925Z'level='info'event='Enqueuing successful task'logger='django_structlog_demo_project.home.views'request_id='3a8f801c-072b-4805-8f38-e1337f363ed4'user_id=1ip='0.0.0.0'timestamp='2019-04-13T19:39:31.147590Z'level='info'event='task_enqueued'logger='django_structlog.middlewares.celery'request_id='3a8f801c-072b-4805-8f38-e1337f363ed4'user_id=1ip='0.0.0.0'child_task_id='6b11fd80-3cdf-4de5-acc2-3fd4633aa654'timestamp='2019-04-13T19:39:31.153081Z'level='info'event='This is a successful task'logger='django_structlog_demo_project.taskapp.celery'task_id='6b11fd80-3cdf-4de5-acc2-3fd4633aa654'request_id='3a8f801c-072b-4805-8f38-e1337f363ed4'user_id=1ip='0.0.0.0'timestamp='2019-04-13T19:39:31.160043Z'level='info'event='request_finished'logger='django_structlog.middlewares.request'request_id='3a8f801c-072b-4805-8f38-e1337f363ed4'user_id=1ip='0.0.0.0'code=201timestamp='2019-04-13T19:39:31.162372Z'level='info'event='task_succeed'logger='django_structlog.middlewares.celery'task_id='6b11fd80-3cdf-4de5-acc2-3fd4633aa654'request_id='3a8f801c-072b-4805-8f38-e1337f363ed4'user_id=1ip='0.0.0.0'result='None'

json文件(logs/json.log

{"request_id":"c53dff1d-3fc5-4257-a78a-9a567c937561","user_id":1,"ip":"0.0.0.0","request":"<WSGIRequest: GET '/'>","user_agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36","event":"request_started","timestamp":"2019-04-13T19:39:29.321453Z","logger":"django_structlog.middlewares.request","level":"info"}{"request_id":"c53dff1d-3fc5-4257-a78a-9a567c937561","user_id":1,"ip":"0.0.0.0","code":200,"event":"request_finished","timestamp":"2019-04-13T19:39:29.345207Z","logger":"django_structlog.middlewares.request","level":"info"}{"request_id":"3a8f801c-072b-4805-8f38-e1337f363ed4","user_id":1,"ip":"0.0.0.0","request":"<WSGIRequest: POST '/success_task'>","user_agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36","event":"request_started","timestamp":"2019-04-13T19:39:31.086155Z","logger":"django_structlog.middlewares.request","level":"info"}{"request_id":"3a8f801c-072b-4805-8f38-e1337f363ed4","user_id":1,"ip":"0.0.0.0","event":"Enqueuing successful task","timestamp":"2019-04-13T19:39:31.089925Z","logger":"django_structlog_demo_project.home.views","level":"info"}{"request_id":"3a8f801c-072b-4805-8f38-e1337f363ed4","user_id":1,"ip":"0.0.0.0","child_task_id":"6b11fd80-3cdf-4de5-acc2-3fd4633aa654","event":"task_enqueued","timestamp":"2019-04-13T19:39:31.147590Z","logger":"django_structlog.middlewares.celery","level":"info"}{"task_id":"6b11fd80-3cdf-4de5-acc2-3fd4633aa654","request_id":"3a8f801c-072b-4805-8f38-e1337f363ed4","user_id":1,"ip":"0.0.0.0","event":"This is a successful task","timestamp":"2019-04-13T19:39:31.153081Z","logger":"django_structlog_demo_project.taskapp.celery","level":"info"}{"request_id":"3a8f801c-072b-4805-8f38-e1337f363ed4","user_id":1,"ip":"0.0.0.0","code":201,"event":"request_finished","timestamp":"2019-04-13T19:39:31.160043Z","logger":"django_structlog.middlewares.request","level":"info"}{"task_id":"6b11fd80-3cdf-4de5-acc2-3fd4633aa654","request_id":"3a8f801c-072b-4805-8f38-e1337f363ed4","user_id":1,"ip":"0.0.0.0","result":"None","event":"task_succeed","timestamp":"2019-04-13T19:39:31.162372Z","logger":"django_structlog.middlewares.celery","level":"info"}

运行测试

注意:目前需要redis来运行测试。最简单的方法开始Docker的演示。

docker-compose up --build

在另一个壳中

pip install -r requirements/base.txt
pytest

演示应用程序

docker-compose up --build

在浏览器中打开http://0.0.0.0:8000/

浏览日志文件和shell的输出。

作者

另请参阅参与此项目的contributors列表。

致谢

许可证

这个项目是根据麻省理工学院的许可证授权的-请参见LICENSE文件以了解详细信息

欢迎加入QQ群-->: 979659372 Python中文网_新手群

推荐PyPI第三方库


热门话题
java将时区应用于日期格式不起作用   你能用Java编写虚拟函数/方法吗?   用Android设备测量心跳频率的java   在AsyncTask类中调用方法时发生java NetworkOnMainThreadException   Java中的swing事件键箭头   java如何在Object[]类变量中添加元素?   Java有一个长时间运行的方法返回它的执行状态   java Mockito的Matcher vs Hamcrest Matcher?   Java CDI:具有多个泛型参数的装饰器   java在扩展的trywithresources语句中究竟捕获了什么?   java我找不到我的结果集。JDBC中提供的下一个方法实现   java如何在Cream文本编辑器上进入命令模式?   LucenePDFDocument从pdfbox中消失了吗?   javascript如何将值从Java控制器传递回Thymeleaf前端?   java一次构建并部署到多个环境   API级别低于24时不支持java默认方法boolean methodname()