返回介绍

使用 Sentry 收集错误信息

发布于 2025-04-20 18:52:16 字数 5906 浏览 0 评论 0 收藏

很多开发者都有这样不愉快的经历:代码在测试环境运行很正常,一到线上就收到用户的反馈和投诉。但是用户的环境各不相同又很复杂,很多错误用户很难描述,甚至开发者都无法复现。但是问题确实存在,怎么办?

在笔者之前的工作中,开发者没有线上服务器的登录权限,申请紧急调试多有不便,即便登录服务器还要要熟悉且遵守一系列的运维流程,这些都增加了我们定位问题的难度和时间。笔者当时想了如下一些办法:

  • 当代码出现问题登录服务器后,在对应的位置添加调试代码,模拟请求或者等待用户触发。然后进一步排查,直到找到问题的原因。
  • 开发时,在认为可能会有问题的地方加入一些异常处理,将异常和它相关的上下文捕捉到日志中,当出现问题时帮助定位。
  • 项目依赖了一些便于调试和更快找到问题的第三方或者自己实现的模块,例如 q(https://github.com/zestyping/q ),它是 PyCon US 2013 的一个主题演讲(http://bit.ly/28Sbq6f )提到的模块,它会把执行的函数或者类的参数存在一个独立的日志里面。

这些确实够用了,但是还有 3 个问题:

1.项目代码中出现一些带有调试意义的代码,既增加了代码量,也会让新的维护者感到疑惑。

2.这种手段完全靠开发者对于项目的熟悉程度和解决问题,其不可预知性和效率可想而知。

3.出现的异常都在时刻影响用户,需要第一时间修复解决,对于开发者的压力非常大,也扰乱了他们的日常工作。

Sentry 是一个基于 Django 的实时事件日志和聚合平台,于 2010 年诞生于 Disqus,它可以帮助我们将程序的所有异常自动记录下来,在 Sentry 自带的用户页面上呈现并支持搜索等功能。其事件监控功能却不局限于 Python,对 Node.js、Go、Java 等语言的项目都可以做到无缝集成,它还能对 iOS、Android 移动客户端以及 Web 前端异常进行跟踪。处理异常是所有应用的必要工作,可以说 Sentry 是 Web 应用必备组件之一。它可以做如下事情:

  • 系统发生异常时,可以通过 Sentry 查看到具体错误信息和触发错误的上下文,还能很容易地重现异常。
  • 可以通过邮件等方式第一时间告知开发者出现了异常。
  • 帮助我们了解系统都产生了哪些异常、异常发生的频率、开始时间、发生的频次等。
  • 可以对系统异常分组,提供高级搜索等功能。
  • 可以把它当成一个异常处理的在线讨论、反馈和事件跟踪的平台。

安装配置 Sentry

Sentry 依赖 PostgreSQL 等(Nginx、Redis 已安装过)软件包,需要先安装它们:

> echo"deb http://apt.postgresql.org/pub/repos/apt/trusty-pgdg main"|sudo tee/etc/
   apt/sources.list.d/postgresql.list
> wget--quiet-O-https://www.postgresql.org/media/keys/ACCC4CF8.asc|sudo apt-key
    add-
> sudo apt-get update
> sudo apt-get install python-dev libxslt1-dev libxml2-dev libz-dev libffi-dev libssl-
    dev libpq-dev libyaml-dev postgresql-9.3-yq
> sudo/etc/init.d/postgresql start

安装 Sentry:

> pip install sentry
> python-c 'import sentry;print sentry.__version__'
8.5.0 # Sentry 8 使用 React 对前端进行了组件化重构,大部分的页面不再要求页面刷新,这提高了页面的访问效率

生成配置文件:

> sentry init

由于数据迁移的问题,Sentry 8 官方不再支持 MySQL 数据库,唯一支持的生产环境数据库是 PostgreSQL。先配置 PostgreSQL 数据库:

> sudo su-postgres
$psql
postgres=# CREATE USER ubuntu WITH PASSWORD '123';
CREATE ROLE
postgres=# CREATE DATABASE sentry OWNER ubuntu;
CREATE DATABASE
postgres=# GRANT ALL PRIVILEGES ON DATABASE sentry to ubuntu;
GRANT
postgres=#\q

修改~/.sentry/sentry.conf.py 的如下部分:

DATABASES={
    'default':{
        'ENGINE':'sentry.db.postgres',
        'NAME':'sentry',
        'USER':'ubuntu',
        'PASSWORD':123,
        'HOST':'',
        'PORT':'',
    }
}

EMAIL_HOST='smtp.qq.com' #发送邮件配置,本例使用 QQ 邮箱
EMAIL_HOST_PASSWORD='SOME_PASSWORD' #这个密码是 QQ 邮箱需要用于登录第三方客户端的
    授权码,而不是 QQ 密码。详情请参考 http://service.mail.qq.com/cgi-bin/help?subtype
    =1&&id=28&&no=1001256
EMAIL_HOST_USER='xxx@qq.com'
EMAIL_PORT=25
EMAIL_USE_TLS=True

SERVER_EMAIL='xxx@qq.com'
BROKER_URL='redis://localhost:6379' #消息队列设置

初始化数据库:

> sentry upgrade

这个过程会提示创建新用户:

Would you like to create a user account now? [Y/n]:y
Email:xxx@qq.com
Password:
Repeat for confirmation:
Should this user be a superuser? [y/N]:y

也可以使用“sentry createuser”创建超级用户。

启动 Sentry

现在 Sentry 就可以启动了:

> sentry start

Sentry 的 Web 服务端口是 9000,访问 http://127.0.0.1:9000,使用刚才创建的 xxx@qq.com 就可以作为管理员登录了。

Sentry 使用 Celery 作为任务执行的 Worker 框架,Celery 在后面有专门的章节讲解,这里先启动它:

> sentry celery worker #执行 Sentry 生成的任务

Sentry 会生成很多任务,比如发送邮件,合并事件。需要启动定时任务进程,来创建任务:

> sentry celery beat

如果产生的异常太多又不想保留,可以通过定时任务定期清理旧数据。

$crontab-l
0 3***sentry cleanup--days=90 #清理三个月前的记录

Sentry 有非常好的数据迁移的设计,升级 Sentry 非常方便。每次使用 pip 更新 Sentry 包之后执行升级命令“sentry upgrade”即可。

创建团队和项目

登录后,默认存在一个叫作 Sentry 的团队(Team)。我们先创建一个 Team,单击 http://localhost:5000/sentry/右上角的 New Team 按钮,输入 Subject,如图 7.1 所示。

图 7.1 创建一个团队

单击 Save Changes 按钮进入创建项目页面(Project),输入项目名字 r,指定 Team 为 subject,如图 7.2 所示。

图 7.2 创建一个项目

再单击 Save Changes 按钮就完成了。

配置 SDK

安装 Sentry 的 Python 的 SDK:

> pip install raven

可以在 http://localhost:5000/sentry/r/settings/keys/页面上找到 r 的 DSN(Data Source Name 的简称),如图 7.3 所示。

图 7.3 找到 r 的 DSN

创建一个简单的 Flask 应用(app.py):

from flask import Flask
from raven.contrib.flask import Sentry

app=Flask(__name__)
sentry=Sentry(app, dsn='http://8bf67e879e8d48208cebd00b1994e812:0
    b9c297690dd477c8147ae6b19953914@localhost:5000/2') # noqa

应用中包含三个视图。

1./error:对可预知的异常进行捕获,它的优点是不影响用户访问。

@app.route('/error')
def error():
    try:
        1/0
    except ZeroDivisionError:
            sentry.captureException()
        return 'error'

2./raise:未做异常处理的捕获,一般不需要特别设置。只要出现不符合预期的异常,理论上就会进入 Sentry:

@app.route('/raise')
def auto_raise():
    raise IndexError

3./log:捕获非异常信息,可以把 Sentry 作为日志收集工具。

@app.route('/log')
def log():
    sentry.captureMessage('hello, world!')
    return 'logging'

现在分别访问这三个页面。然后刷新一个 Sentry 的 r 项目主页 http://localhost:5000/sentry/r,就可以看到 3 条记录,见图 7.4。

图 7.4 r 的项目主页上可以看到 3 条记录

看一下 ZeroDivisionError 这个异常的详情页,如图 7.5 所示。

图 7.5 ZeroDivisionError 异常的详情页

详情页直接定位错误的代码行数,上下文以及相关的参数和变量。可以在 Comments 这个 Tab 下讨论问题,对事件合并,标记为解决/未解决等。

收到的报警邮件如图 7.6 所示。

图 7.6 收到的报警邮件

Sentry 还可以和 Slack、Trello、GitHub、GitLab 等企业协作沟通工具相结合。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。