一、概述:
项目在部署到测试、生产环境后,我们便不可能像在开发时那样容易的及时发现处理错误了。首先,一般都是在错误发生后一段时间,才会传递到开发人员,这个时候去查看程序运行的日志,就得熟练使用awk
,grep
去分析日志了。然后我们找到了错误,也会因为日志中缺少上下文数据,难以分析真正的错误是什么。
Sentry(官网)是解决这个问题的一个工具,设计了很多特性来帮助开发者更快,更方便,更美观的监控错误。
Sentry为多种语言以及各种框架提供了SDK,配置得当后,sentry会在程序运行时,自动收集错误堆栈以及上下文数据,发送到配置的sentry server,开发可以通过sentry web实时查看错误。
二、Sentry Server安装部署:
官方服务:
如果是刚开始了解Sentry,可以直接使用官方提供的服务,前期有一定的免费额度。使用后觉得挺方便顺手的,土豪可以付费使用,闲杂人等可以自己搭建SentryServer。
自己搭建:
搭建server已经有网友给出比较好的教程了,推荐给大家。
PS: 2018年了,推荐直接使用docker-compose的方式安装,简单省心。
配置邮件服务
编辑docker-compose.yml
文件
让同事也可以访问Sentry
Sentry的权限分级是,团队拥有项目,用户有角色和所属团队。
进入主页。
点击项目和团队->团队设置。
输入同事的邮箱,邀请新成员。
三、收集错误
配置项目与Sentry之间的连接
访问sentry server, 点击右上角"新项目"。这里以Django
为例子,箭头处输入项目名称,Create Project。
接下来页面跳转到在项目中安装与配置sentry的指导页面,我们一条一条看。
安装
pip install raven --upgrade
raven
是sentry
在python语言上的sdk库
配置
在django
的settings
里配置sentry
。
INSTALLED_APPS = (
'raven.contrib.django.raven_compat',
)
配置连接到sentry server
的DSN
,DSN
就相当于连接到你sentry server的url,每个项目都单独对应一个DSN
。
import os
import raven
RAVEN_CONFIG = {
'dsn': 'http://afe50b021a4049558de19d18d40388d4:866b9b6eeb8d423f890f1a42060d2e76@sentry.vxiaocheng.com/5',
# If you are using git, you can also automatically configure the
# release based on the git info.
# 'release': raven.fetch_git_sha(os.path.abspath(os.pardir)),
}
release的配置官方是没注释的,用来获取当前项目的git hash code
,但一般部署生产环境的时候,都跟git没关联了。而且这玩意找不到git
还会报错,导致项目无法启动。
测试
执行python manage.py raven test
,配置正确的话,在页面上就能看到一条错误日志啦。
至此,我们已经解决了一开始的核心需求“收集错误日志”。
四、Django实战
日志捕捉
程序中除了错误日志需要捕捉外,我们还会有其他情况也要有实时的提醒日志。
我们会
try-catch
住一些会发生错误的情况,这些边界情况的发生会有对应的处理策略,而不中断主流程,但同时我们也希望能明确到底发生什么错误,如果发生断言不该发生的情况,这个时候我们也希望能记录住现场,并发送通知。
在程序中输出一些内容的时候,方便点就直接print
了,正式点用logging
。Sentry提供了一个logging handler
,能使logging
输出的内容发送到Sentry,就可以及时的发现边界情况,异常数据等情况了。
配置
在Django settings里添加logging配置:
LOGGING = {
'version': 1,
'disable_existing_loggers': True,
'root': {
'level': 'WARNING',
'handlers': ['sentry'],
},
'formatters': {
'verbose': {
'format': '%(levelname)s %(asctime)s %(module)s '
'%(process)d %(thread)d %(message)s'
},
},
'handlers': {
'sentry': {
'level': 'ERROR', # To capture more than ERROR, change to WARNING, INFO, etc.
'class': 'raven.contrib.django.raven_compat.handlers.SentryHandler',
'tags': {'custom-tag': 'x'},
},
'console': {
'level': 'DEBUG',
'class': 'logging.StreamHandler',
'formatter': 'verbose'
}
},
'loggers': {
'django.db.backends': {
'level': 'ERROR',
'handlers': ['console'],
'propagate': False,
},
'raven': {
'level': 'DEBUG',
'handlers': ['console'],
'propagate': False,
},
'sentry.errors': {
'level': 'DEBUG',
'handlers': ['console'],
'propagate': False,
},
},
}
使用
正常使用logging
输出就可以了。要注意的是,这种情况下,sentry不会自动获取上下文的数据,所以要利用好参数extra
,手动把上下文数据放到里面。如果在上下文中能获取到request
,放入extra
,sentry也会自动从request
中获取一些数据。
import logging
logger = logging.getLogger(__name__)
logger.error('There was some crazy error', exc_info=True, extra={
# Optionally pass a request and we'll grab any information we can
'request': request,
})
兼容Exception Middleware
我们可能在项目中已经配置了middleware
,在process_exception
里对异常做了一些处理。这种情况会抑制住Sentry对异常的收集。需要手动的在middleware
里添加代码,发送异常给Sentry。
from raven.contrib.django.raven_compat.models import sentry_exception_handler
class MyMiddleware(object):
def process_exception(self, request, exception):
# Make sure the exception signal is fired for Sentry
sentry_exception_handler(request=request)
return HttpResponse('foo')
自定义异常页面
用户在操作Web页面时,出现异常后,反馈的时候只能通过描述错误场景,开发根据错误场景去推测复现异常。比较麻烦。
有了Sentry之后,我们可以自定义异常页面,在页面上显示每个异常的x-sentry-id
,这样用户直接告知这个id,开发就可以定位处理问题了。
配置方法: https://docs.sentry.io/clients/python/integrations/django/#message-references
错误路由
记录用户访问到的404 url到sentry,实践用起来用处不大,可以不配置。
有兴趣的可以看官方介绍:https://docs.sentry.io/clients/python/integrations/django/#logging