背景
在日常线上运行的应用中如果报了异常,怎么在第一时间收到报错告警并且查看报错日志呢?周五就因为缺乏报错日志,导致构建服务受影响超过了 2 小时,虽然不至于「死人」,但是也确实让我意识到日志的重要性!后来临时在相关的地方加上日志,通过错误信息很快定位了到了原因,原来是数据库被运维人员做了新特性的改动,而我们服务还未适配好。想想当时的场景,还真是有点紧张~囧
今天就学习一下利用 Sentry 作为日志收集系统,结合之前学习的 log4j2 日志输出,主动收集异常日志。
Sentry
我们先来 Sentry 是怎么介绍自己的:
Open-source error tracking that helps developers monitor and fix crashes in real time. Iterate continuously. Boost efficiency. Improve user experience
大体意思就是:Sentry 是一款开源的错误跟踪系统,可帮助开发人员实时监控和修复崩溃。它是不断迭代的,提高效率,改善用户体验。Sentry 本身的文档也记载的比较全面,强烈安利,一般问题可以通过阅读 Doc 学习或者论坛咨询。
OK,下面我们就开始通过 Docker 安装 Sentry。
PS:如果你的 Docker 环境还未配置好,可以阅读我之前的总结:Linux——CentOS 安装 Docker 教程
前提
在 Sentry Installation 页面,官方做了总结,Sentry 需要和几个服务有交互:
- PostgreSQL:Docker image postgres:9.5,这里明确版本是 9.5,我觉得非常棒!这保证了在未来部署的可重现,避免了不同版本差异造成部署失败的问题。
- Redis
- 官方说如果你使用的 Ubuntu < 15.04,推荐安装 chirs-lea/redis-server
- 文档推荐的是 Docker image redis:3.2-alpine.
硬件要求,具体的可以阅读官方文档,我这里仅仅是家里测试使用,因此无所谓。
下面的步骤其实是官方文档的翻译,但是,跟着走了一遍之后发现,服务并不能正常运行起来,但是也没啥坏处,主要步骤其实就和这个差不多,可能是某些细节漏了,因此,你可以大体浏览一下步骤。如果不想浪费时间,可以直接跳到下面的 「脚本一键安装 Sentry」小节。
创建容器
需要 Docker 版本 1.10+
克隆仓库 getsentry/onpremise。这个仓库是定制化构建你自己 Sentry 镜像的基础:
1 | cd /data |
仓库里的 sentry.conf.py and config.yml
可供你 配置 Sentry 所用,建议先浏览一下这个配置文档。
现在开始构建我们定制好的镜像。如果你构建的镜像需要推送到你本地的镜像仓中,那么可以用如下方式先定义好镜像名再构建:
1 | REPOSITORY=registry.michael.com/sentry make build push |
我本地没有镜像仓,只需要用如下方式构建即可:
1 | make build |
运行依赖的服务
Redis:
1 | docker run \ |
PostgreSQL:
1 | docker run \ |
Outbound Email:
1 | docker run \ |
运行 Sentry 服务
${REPOSITORY}
只的是你刚刚定义的镜像名,如果没有,默认是 sentry-onpremise
。
为了测试镜像是 OK 的,可以运行如下命令:
1 | docker run \ |
现在可以生成一个 secret-key
值:
1 | docker run \ |
生成的值可以在 config.yml
中设置给 system.secret-key
,或者通过环境变量。如果是设置在 config.yml
文件中,这时候你必须重新构建你的镜像。
运行的基本命令举例如下:
1 | docker run \ |
官方文档里有一行小字,说明的是后面的文档,不会特地的写上 –link 去表示链接容器,但是这些都是必须的!同时,${REPOSITORY} 会被引用为 sentry-onpremise。
运行 Web 服务
暴露的是 9000 的端口,这样部署之后,可以通过 http://localhost:9000/
访问。
1 | docker run \ |
脚本一键安装 Sentry
发现了 getsentry/onpremise/install.sh 这个脚本,看懂这个脚本里的内容基本上就差不多知道安装步骤了。
读一下脚本:
LATEST_STABLE_SENTRY_IMAGE='sentry:9.1.2'
安装的是sentry:9.1.2
- 在
docker-compose.yml
中会去创建两个卷,分别是sentry-data
和sentry-postgres
,这和上面步骤是不是发现区别了,上面创建postgres
时,可没有创建卷; cp -n .env.example "$ENV_FILE"
会将仓库下的 .env.example 文件重命名为.env
文件,其实里面就是为了设置一个环境变量SENTRY_SECRET_KEY
export SENTRY_IMAGE=$LATEST_STABLE_SENTRY_IMAGE
命名了一个环境变量,记录了镜像名docker-compose build
开始构建镜像啦,其实就是类似这个命令docker build .
SECRET_KEY=$(docker-compose run --rm web config generate-secret-key 2> /dev/null | tail -n1 | sed -e 's/[\/&]/\\&/g')
运行命令获得secret-key
值,赋值给了变量SECRET_KEY
sed -i -e 's/^SENTRY_SECRET_KEY=.*$/SENTRY_SECRET_KEY='"$SECRET_KEY"'/' $ENV_FILE
将SECRET_KEY
变量值填写到环境变量文件.env
中- 接着就是设置数据库的步骤,这其实是就是为了在数据库中添加账号数据和其他一些数据表生成
- 最后就是执行
cleanup
函数
执行脚本之前,我们先把之前创建的几个服务删除掉吧:
1 | docker stop sentry-smtp sentry-postgres sentry-redis |
配置邮箱
通过上面的阅读,可以发现,运行脚本时,会去执行 docker build .
,这个会将配置文件 config.yml
和环境变量 .env
放入镜像的。因此,我们启用发生异常时获取邮箱告警的功能,需要现在配置文件中设置好邮箱配置。
这里我们选择在 .env
中配置好环境变量,实现邮箱的配置:
配置 config.yml
:
1 | SENTRY_SECRET_KEY=)g=lkl1)uugx236%#)mq2o34^@a&g3q85q**co*hbapm5y1*bs |
- 网上的教程,大多数是
SENTRY_EMAIL_HOST: 'smtp.exmail.qq.com'
,这个是企业邮箱,我们个人的不这么设置。 SENTRY_EMAIL_USER
和SENTRY_SERVER_EMAIL
要保持一致;
这里我设置 1 分钟,就能及时收到邮箱,但是设置 5 分钟,等了 5 分钟,也没收到,不知道是何原因:
经过上面的设置,可以试试邮箱发送功能是否 OK:点击左上角头像,选择 Admin
-》Mail
-》测试设置
部署 sentry
下面开始安装步骤:
sh install.sh
执行安装脚本,脚本执行完需要一点时间,运行完成之后,会退出。中间过程会让你选择是否创建账号:
- 接着运行
docker-compose up -d
即可;
PS:为何容器的名称是都是 onpremise
开头的呢?因为不指定名称时,会默认取目录名的。
这时候输入刚刚创建的账号登录:
配置 Sentry
创建 project
那我之前的 log4j2 的 demo 作为演示,这里选择一个 Java 项目,并且,我还创建了一个叫 spring-boot
的 Team。
spring-boot 项目适配
官方文档-Java 给出了适用于 Java 项目的全面的适配指南,咱们使用的是 log4j2。
引入依赖
1 | <dependency> |
log4j2.xml 配置修改
configuration
中加上packages="org.apache.logging.log4j.core,io.sentry.log4j2"
下面示例中的 SentryAppender
表示发送 warn
级别的日志到 Sentry Server。ConsoleAppender
仅仅表示是一个示例,表示你项目中之前使用的非 sentryappener 的例子。
1 |
|
经过测试,,因为原有项目中的 apppender 都是为了之前的作用设置的,比如控制台打印、比如输出到文件。要想将异常信息发送到 Sentry,这里的SentryAppender
是必不可少的。别忘了 appender-ref
也要设置!
配置 DSN
配置页面 介绍了如何设置 DSN(Data Source Name)。
进入 Sentry,项目的 DSN 在项目页面-》setings-》Clinet Keys(DSN) 中可以发现:
配置 DSN 有好几种方式,具体的可以在页面查看,这里介绍我采用的:
在 resources
文件夹下,新建 sentry.properties
:
1 | dsn=http://8d53042c89774e5dba599ee67c5c8804@192.168.3.43:9000/3 |
默认的就是 sentry.properties
,一开始我直接写在了 application.properties
中,Sentry 怎么也收不到异常日志。
代码中
代码示例:
1 | import org.apache.logging.log4j.LogManager; |
可以发现,Sentry 使用的接口和之前 log4j2 是有区别的:
1 | // 原来 |
实际过程中,这里是很多人忽视的,一定要仔细一点!
这时候,使用我们之前的错误接口故意打印错误日志,看看 Sentry 的捕获效果吧:
总结
今天在之前加入的一个技术微信群里,一位同学发了一篇怎么搭建 Zabbix 的文章,被群主踢了。后来大家讨论,这种搭建的文章,普遍质量比较低,没有太多分享的意义,应该要更多的关注一些前言的知识、或者底层的基础知识。这种观点我是比较认同的,但是谁不是一步一步慢慢来的呢?
今天搭建 Sentry 的过程,对之前 docker-compose 的用法又有了进一步的认识,学习到了使用 .env
的方式设置容器内环境变量的方式,同时,也学习到了可以公用一种配置,让 docker-compose 文件内多个服务公用的方式。其实,自己的每一点的折腾,都会是后面的基石。只要持续积累,才会越走越顺!
示例代码
- awesome-spring-boot-examples/log4j2
参考
- 神奇的展示-用 Docker 部署 Sentry Bug 日志收集服务
- 掘金-搭建私有的前端监控服务: sentry
- sentry配置邮件
- 自建sentry后,配置了邮件服务,但是还是收不到验证邮件? 这个问题有参考意义,还是推荐通过环境变量的方式而不是
config.yml
配置邮箱