Sentry 为一套开源的利用监控和谬误追踪的解决方案。这套解决方案由对应各种语言的 SDK 和一套宏大的数据后盾服务组成。利用须要通过与之绑定的 token 接入 Sentry SDK 实现数据上报的配置。通过 Sentry SDK 的配置,还能够上报谬误关联的版本信息、公布环境。同时 Sentry SDK 会主动捕获异样产生前的相干操作,便于后续异样追踪。异样数据上报到数据服务之后,会通过过滤、要害信息提取、演绎展现在数据后盾的 Web 界面中。
在实现接入后咱们就能够从管理系统中实时查看利用的异样,从而被动监控利用在客户端的运行状况。通过配置报警、剖析异样产生趋势更被动的将异样扼杀在萌芽状态,影响更少的用户。通过异样详情剖析、异样操作追踪,防止对客户端利用异样两眼一抹黑的状态,更高效的解决问题。
这篇文章也将会从一键部署服务开始,通过解决部署过程中遇到的问题,分享到实现前端利用监控和异样数据应用的整个具体过程,心愿会对你的部署和应用中遇到的问题有所帮忙。
疾速部署 Sentry 服务
Sentry 的治理后盾是基于 Python Django 开发的。这个治理后盾由背地的 Postgres 数据库(治理后盾默认的数据库,后续会以 Postgres 代指治理后盾数据库并进行分享)、ClickHouse(存数据特色的数据库)、relay、kafka、redis 等一些根底服务或由 Sentry 官网保护的总共 23 个服务撑持运行。可见的是,如果独立的部署和保护这 23 个服务将是异样简单和艰难的。侥幸的是,官网提供了基于 docker 镜像的一键部署实现 getsentry/onpremise。
这种部署形式依赖于 Docker 19.03.6+ 和 Compose 1.24.1+
筹备工作
Docker 是能够用来构建和容器化利用的开源容器化技术。
Compose 是用于配置和运行多 Docker 利用的工具,能够通过一个配置文件配置利用的所有服务,并一键创立和运行这些服务。
在筹备好 linux 服务器之后,并依照官网文档装置好对应版本的 Docker 和 Compose 之后,将 onpremise 的源代码克隆到工作台目录:
git clone https://github.com/getsentry/onpremise.git
# 切换到 20.10.1 版本,后续的分享将会基于这个版本进行
git checkout release/20.10.1
docker 镜像减速
在后续部署的过程中,须要拉取大量镜像,官网源拉取较慢,能够批改 docker 镜像源,批改或生成 /etc/docker/daemon.json
文件:
{"registry-mirrors": ["镜像地址"]
}
而后从新加载配置,并重启 docker 服务:
sudo systemctl daemon-reload
sudo systemctl restart docker
一键部署
在 onpremise 的根门路下有一个 install.sh 文件,只须要执行此脚本即可实现疾速部署,脚本运行的过程中,大抵会经验以下步骤:
- 环境查看
- 生成服务配置
- docker volume 数据卷创立(可了解为 docker 运行的利用的数据存储门路的创立)
- 拉取和降级根底镜像
- 构建镜像
- 服务初始化
- 设置管理员账号(如果跳过此步,可手动创立)
在执行完结后,会提醒创立结束,运行 docker-compose up -d
启动服务。
在应用不增加 -d
参数运行 docker-compose up
命令后,咱们能够看到服务的启动日志,须要期待外部 web、relay、snuba、kafka 等全副启动并联动初始化后,服务才算齐全启动,此刻才能够应用默认端口拜访治理端默认服务地址,此时能够进行域名配置,并将 80 端口解析到服务的默认端口上,便能够应用域名进行拜访。
第一次拜访治理后盾,能够看到欢送页面,实现必填项的配置,即可正式拜访治理后盾。
- Root URL:异样上报接口的公网根地址(在做网络解析配置时,后盾服务能够配置到内网外网两个域名,只将上报接口的解析规定
/api/[id]/store/
配置到公网环境,保证数据不会泄密)。 - Admin Email:在 install.sh 阶段创立的管理员账号。
- Outbound email:这部分内容为邮件服务配置,能够先不配置。
实现这部分工作后,对服务没有定制化需要的能够跳至 前端接入和应用 局部。
docker 数据存储地位批改
能够看到在服务运行的过程中,会在 docker volume 数据卷挂载地位存储数据,如 Postgres、运行日志等,docker volume 默认挂载在 /var 目录下,如果你的 /var 目录容量较小,随着服务的运行会很快占满,须要对 docker volume 挂载目录进行批改。
# 在容量最大的目录下创立文件夹
mkdir -p /data/var/lib/
# 进行 docker 服务
systemctl stop docker
# 将 docker 的默认数据复制到新门路下,删除旧数据并创立软连贯,即便得存储理论占用磁盘为新门路
/bin/cp -a /var/lib/docker /data/var/lib/docker && rm -rf /var/lib/docker && ln -s /data/var/lib/docker /var/lib/docker
# 重启 docker 服务
systemctl start docker
服务定制
一键部署的 Sentry 服务总会有不合乎咱们应用和保护设计的中央,这个时候,就须要通过对部署配置的批改来满足本人的需要。
服务组成与运行机制
在通过 docker-compose 疾速部署之后,咱们先来察看下启动了哪些服务,并为后续的适配和批改剖析下这些服务的作用,运行 docker 查看所有容器的命令:
docker ps
能够看到当初启动的所有服务,并且一些服务是应用的同一个镜像通过不同的启动参数启动的,依照镜像辨别并且通过笔者的钻研揣测,各个服务的作用如下:
-
nginx:1.16
- sentry_onpremise_nginx_1:进行服务间的网络配置
-
sentry-onpremise-local:以下服务应用同一个镜像,即应用同一套环境变量
-
sentry_onpremise_worker_1
- 可能是解决后台任务,邮件,报警相干
-
sentry_onpremise_cron_1
- 定时工作,不确定是什么定时工作,可能也是定时清理
-
sentry_onpremise_web_1
- web 服务(UI + web api)
- sentry_onpremise_post-process-forwarder_1
-
sentry_onpremise_ingest-consumer_1
- 解决 kafka 音讯
-
-
sentry-cleanup-onpremise-local
-
sentry_onpremise_sentry-cleanup_1
- 数据清理,临时不重要,然而应该和其余的 sentry 服务专用一些配置
-
sentry_onpremise_snuba-cleanup_1
- 数据清理,临时不重要
-
-
getsentry/relay:20.10.1
-
sentry_onpremise_relay_1
- 来自利用上报的数据先到 relay,
- relay 间接返回响应状态
- 后在后台任务中持续解决数据
- 解析事件、格局调整、启用过滤规定等抛弃数据
- 数据写入 kafka
-
-
symbolicator-cleanup-onpremise-local
-
sentry_onpremise_symbolicator-cleanup_1
- 数据清理的,临时不重要
-
-
getsentry/snuba:20.10.1
- 看起来是生产 kafka 音讯,往 ClickHouse 写,用到了 redis,用处不明
-
sentry_onpremise_snuba-api_1
- snuba 的接口服务,如同没什么作用
-
sentry_onpremise_snuba-consumer_1
- 生产 Kafka 给 ClickHouse 提供事件
-
sentry_onpremise_snuba-outcomes-consumer_1
- 生产 Kafka 给 ClickHouse outcomes
-
sentry_onpremise_snuba-sessions-consumer_1
- 生产 Kafka 给 ClickHouse sessions
-
sentry_onpremise_snuba-replacer_1
- 看起来是转换老(或者别的转换性能)数据的,从 kafka 拿后写到 kafka
-
tianon/exim4
-
sentry_onpremise_smtp_1
- 邮件服务
-
-
memcached:1.5-alpine
- sentry_onpremise_memcached_1
- 兴许是用来升高数据存储的频次和抵触的
-
getsentry/symbolicator:bc041908c8259a0fd28d84f3f0b12daa066b49f6
-
sentry_onpremise_symbolicator_1
- 最根底的设施:解析(native)错误信息
-
-
postgres:9.6
-
sentry_onpremise_postgres_1
- 根底的设施,服务后盾默认的数据库,存储异样数据
-
-
confluentinc/cp-kafka:5.5.0
-
sentry_onpremise_kafka_1
- 根底的设施,ClickHouse 和 pg 的数据必定都是从 kafka 来的
-
-
redis:5.0-alpine
-
sentry_onpremise_redis_1
- 根底的设施,有一些拦挡配置在这
-
-
confluentinc/cp-zookeeper:5.5.0
-
sentry_onpremise_zookeeper_1
- 根底的设施
-
-
yandex/ClickHouse-server:19.17
-
sentry_onpremise_ClickHouse_1
- 与 pg 不同的存储,存储是异样的要害信息,用于疾速检索
-
同时,依据异样上报到服务后,日志的记录状况可知,运行机制大略如下:
- 异样数据通过 nginx 解析到 relay 服务。
- relay 通过 pg 获取最新的利用与 token 匹配关系,并验证数据中的 token,间接返回 403 或 200,并对数据进行拦挡过滤。
- relay 将数据发送给 kafka 的不同 topic。
- sentry 订阅其中局部 topic,解析数据存入 Postgres,用做后续查看谬误详情。
- snuba 订阅其余 topic,对数据打标签,提取要害特色,存入 ClickHouse,用来疾速依据要害特色检索数据。
文件构造与作用
要对部署和运行进行批改的话,须要找到对应的配置文件,先看下 onpremise 部署实现的次要文件构造和作用:
- clickhouse/config.xml:clickhouse 配置文件
- cron/:定时工作的镜像构建配置和启动脚本
- nginx/nginx.conf:nginx 配置
- relay/config.example.yml:relay 服务配置文件
-
sentry/:sentry-onpremise-local 镜像的构建和基于此镜像启动的主服务的配置都在这个文件夹下
- Dockerfile:sentry-onpremise-local 的镜像构建配置,会以此启动很多服务
- requirements.example.txt:由此生成 requirements.txt,须要额定装置的 Django 插件须要被写在这外面
- .dockerignore:Docker 的疏忽配置,初始疏忽了 requirements.txt 之外的所有文件,如果构建新镜像时须要 COPY 新货色则须要批改此文件
- config.example.yml:由此生成 config.yml,个别放运行时不能通过治理后盾批改的配置
- sentry.conf.example.py:由此生成 sentry.conf.py,为 python 代码,笼罩或合并至 sentry 服务中,从而影响 sentry 运行。
- .env:镜像版本、数据保留天数、端口等配置
- docker-compose.yml:Compose 工具配置,多 docker 的批量配置和启动设置
- install.sh:Sentry 一键部署流程脚本
同时须要留神的是,一旦部署过之后,install.sh 脚本就会依据 xx.example.xx 生成理论失效的文件,而且,再次执行 install.sh 脚本时会检测这些文件存不存在,存在则不会再次生成,所以须要批改配置后重新部署的状况下,咱们最好将生成的文件删除,在 xx.example.xx 文件中批改配置。
依据服务组成和运行机制得悉,主服务是基于 sentry-onpremise-local
镜像启动的,而 sentry-onpremise-local
镜像中的 sentry 配置会合并 sentry.conf.py
,此文件又是由 sentry.conf.example.py
生成,所以后续定制化服务时,会重点批改 sentry.conf.example.py
配置模板文件。
应用独立数据库确保数据稳定性
在数据库单机化部署的状况下,一旦呈现机器故障,数据会损坏失落,而 onpremise 的一键部署就是以 docker 的模式单机运行的数据库服务,且数据库数据也存储在本地。
能够看到 Sentry 的数据库有两个,Postgres 和 ClickHouse。
尽管 Sentry 不是业务利用,在宕机后不影响业务失常运行,数据的稳固并不是特地重要,然而 Postgres 中存储了接入 Sentry 的业务利用的 id 和 token 与对应关系,在这些数据失落后,业务利用必须要批改代码以批改 token 从新上线。为了防止这种影响,且公司有现成的可容灾和定期备份的 Postgres 数据库,所以将数据库切换为内部数据库。
批改 sentry.conf.example.py
文件中 DATABASES
变量即可:
DATABASES = {
'default': {
'ENGINE': 'sentry.db.postgres',
'NAME': '数据库名',
'USER': '数据库用户名',
'PASSWORD': '数据库明码',
'HOST': '数据库域名',
'PORT': '数据库端口号',
}
}
因为不再须要以 Docker 启动 Postgres 数据库服务,所以将 Postgres 相干信息从 docker-compose.yml 文件中删除。删掉其中的 Postgres 相干配置即可。
depends_on:
- redis
- postgres # 删除
# ...
services:
# ...
# 删除开始
postgres:
<< : *restart_policy
image: 'postgres:9.6'
environment:
POSTGRES_HOST_AUTH_METHOD: 'trust'
volumes:
- 'sentry-postgres:/var/lib/postgresql/data'
# 删除完结
# ...
volumes:
sentry-data:
external: true
sentry-postgres: # 删除
external: true # 删除
同时,因为 Sentry 在启动前,初始化数据库构造的应用会 pg/citext 扩大,创立函数,所以对数据库的用户权限有肯定要求,也须要将扩大提前启用,否则会导致 install.sh 执行失败。
管制磁盘占用
随着数据的上报,服务器本地的磁盘占用和数据库大小会越来越大,在接入 300 万 / 日的流量后,磁盘总占用每天约减少 1.4G-2G,依照 Sentry 定时数据工作的配置保留 90 天来说,全量接入后磁盘占用会维持在一个比拟大的值,同时这么大的数据量对数据的查问也是一个累赘。为了减轻负担,须要从服务端和业务利用端同时动手。综合思考咱们将数据保留时长改为 7 天。批改 .env
文件即可:
SENTRY_EVENT_RETENTION_DAYS=7
也能够间接批改 sentry.conf.example.py
:
SENTRY_OPTIONS["system.event-retention-days"] = int(env("SENTRY_EVENT_RETENTION_DAYS", "90")
)
# 改为
SENTRY_OPTIONS["system.event-retention-days"] = 7
须要留神的是,定时工作应用 delete 语句删除过期数据,此时磁盘空间不会被开释,如果数据库没有定时回收的机制,则须要手动进行物理删除。
# 作为参考的回收语句
vacuumdb -U [用户名] -d [数据库名] -v -f --analyze
单点登录 CAS 登录接入
Sentry 自身反对 SAML2、Auth0 等单点登录形式,然而咱们须要反对 CAS3.0,Sentry 和 Django 没有对此有良好反对的插件,所以笔者组装了一个根本可用的插件 sentry_cas_ng。
应用时,须要进行插件的装置、注册和配置,插件应用 github 地址装置,须要一些前置的命令行工具,就不在 requirements.txt 文件中进行配置,间接批改 sentry/Dockerfile
文件进行装置,追加以下内容:
# 设置镜像源减速
RUN echo 'deb http://mirrors.aliyun.com/debian/ buster main non-free contrib \n\
deb http://mirrors.aliyun.com/debian/ buster-updates main non-free contrib \n\
deb http://mirrors.aliyun.com/debian/ buster-backports main non-free contrib \n\
deb http://mirrors.aliyun.com/debian-security/ buster/updates main non-free contrib \n\
deb-src http://mirrors.aliyun.com/debian/ buster main non-free contrib \n\
deb-src http://mirrors.aliyun.com/debian/ buster-updates main non-free contrib \n\
deb-src http://mirrors.aliyun.com/debian/ buster-backports main non-free contrib \n\
deb-src http://mirrors.aliyun.com/debian-security/ buster/updates main non-free contrib' > /etc/apt/sources.list
# 降级和装置前置工具
RUN apt-get update && apt-get -y build-dep gcc \
&& apt-get install -y -q libxslt1-dev libxml2-dev libpq-dev libldap2-dev libsasl2-dev libssl-dev sysvinit-utils procps
RUN apt-get install -y git
# 装置这个根本可用的 cas 登录插件
RUN pip install git+https://github.com/toBeTheLight/sentry_cas_ng.git
同时批改 sentry.conf.example.py
文件,以进行插件的注册和配置项配置:
# 批改 session 库,解决 session 较长的问题
SESSION_ENGINE = 'django.contrib.sessions.backends.db'
# 在 django 中装置插件
INSTALLED_APPS = INSTALLED_APPS + ('sentry_cas_ng',)
# 注册插件中间件
MIDDLEWARE_CLASSES = MIDDLEWARE_CLASSES + ('sentry_cas_ng.middleware.CASMiddleware',)
# 注册插件数据管理端
AUTHENTICATION_BACKENDS = ('sentry_cas_ng.backends.CASBackend',) + AUTHENTICATION_BACKENDS
# 配置 CAS3.0 单点登录的登录地址
CAS_SERVER_URL = 'https://xxx.xxx.com/cas/'
# 配置 cas 版本信息
CAS_VERSION = '3'
# 因为插件是应用拦挡登录页强制跳转至 SSO 页面的形式实现的
# 所以须要配置登录拦挡做跳转 SSO 登录操作
# 须要将 pathReg 配置为你的我的项目的登录 url 的正则
# 同时,当页面带有 ?admin=true 参数时,不跳转至 SSO
def CAS_LOGIN_REQUEST_JUDGE(request):
import re
pathReg = r'.*/auth/login/.*'
return not request.GET.get('admin', None) and re.match(pathReg, request.path) is not None
# 配置登出拦挡做登出操作
# 让插件辨认以后为登出操作,销毁以后用户 session
# 为固定内容,不变
def CAS_LOGOUT_REQUEST_JUDGE(request):
import re
pathReg = r'.*/api/0/auth/.*'
return re.match(pathReg, request.path) is not None and request.method == 'DELETE'
# 是否主动关联 sso cas 信息至 sentry 用户
CAS_APPLY_ATTRIBUTES_TO_USER = True
# 登录后调配的默认组织名称,必须与治理端 UI 设置的组织名雷同
AUTH_CAS_DEFAULT_SENTRY_ORGANIZATION = '[组织名]'
# 登录后默认的角色权限
AUTH_CAS_SENTRY_ORGANIZATION_ROLE_TYPE = 'member'
# 登录后默认的用户邮箱后缀,如 @163.com 中的 163.com
AUTH_CAS_DEFAULT_EMAIL_DOMAIN = '[邮箱后缀]'
实现配置后,须要应用 Sentry 的默认组织名 sentry,拜访 xxx/auth/login/sentry?admin=true
,避过 CAS 插件拦挡,以管理员身份登录,而后批改 Sentry 设置的组织名为插件中的配置的组织名变量 AUTH_CAS_DEFAULT_SENTRY_ORGANIZATION
的值。否则新用户通过 SSO 登录后会因为要调配的组织名和服务设置的组织名不匹配呈现谬误。
批改默认时区
在登录 Sentry 之后,能够发现异常的工夫为 UTC 工夫,每个用户都能够在设置中将时区改为本地时区:
出于用户敌对思考,能够间接批改服务的默认时区,在 sentry.conf.example.py
文件中增加配置:
# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
SENTRY_DEFAULT_TIME_ZONE = 'Asia/Shanghai'
获取实在 IP
Sentry 会获取申请头中 X-Forwarded-For(构造为ip1,ip2,ip3
)的第一个 IP 为实在用户 IP,Sentry 一键部署启动的服务的最靠前的服务是一个 Nginx 服务,它的配置就是之前提到的 nginx/nginx.conf
文件,在其中能够看到一行 proxy_set_header X-Forwarded-For $remote_addr;
,其中 $remote_addr
示意“客户端”IP,然而这个客户端是绝对于 Nginx 服务的而言的,如果后面有其余的代理服务器,那么拿到的就是代理服务器的 IP。在咱们的部署环境中,X-Forwarded-For 由前置的 Nginx 服务提供,且曾经解决成须要的格局,所以删除此行即可。
角色权限批改
在 Sentry 的默认的角色权限零碎中有以下名词,在信息结构依照蕴含关系有组织、团队、我的项目、事件。
在角色层面又具备:
- superuser:系统管理员(非常规角色),可删除用户账号,在 install.sh 脚本执行时创立的账号就是系统管理员。
- owner:组织管理员,在私有化部署的状况下只有一个组织,即能够批改服务配置之外的信息,能够管制组织及以下层面的配置、删除。
- manager:团队管理员,可从团队中移除用户,可创立删除所有我的项目,可创立删除所有团队。
- admin:可进行我的项目的设置(如报警、入站规定),批准用户退出团队,创立团队、删除所在团队,调整所在团队的工程的配置。
- member:可进行问题的解决。
且角色是追随账号的,也就是说,一个 admin 会在他退出的所有的团队中都是 admin。
在咱们的权限设计中,心愿的是由 owner 创立团队和团队下的我的项目,而后给团队调配 admin。即 admin 角色治理团队下的权限配置,然而不能创立和删除团队和我的项目。在 Sentry 的现状下,最靠近这套权限设计的状况中,只能勾销 admin 对团队、我的项目的增删权限,而无奈设置他只领有某个团队的权限。
在 Sentry 的配置中是这么管理权限的:
SENTRY_ROLES = (
# 其余角色
# ...
{
'id': 'admin',
'name': 'Admin',
'desc': '省略'
'of.',
'scopes': set(
[
"org:read","org:integrations",
"team:read","team:write","team:admin",
"project:read", "project:write","project:admin","project:releases",
"member:read",
"event:read", "event:write","event:admin",
]),
}
)
其中 read、write 为配置读写,admin 则是增删,咱们只须要删掉 "team:admin"
和 "project:admin"
后在 sentry.conf.example.py
文件中复写 SENTRY_ROLES
变量即可。须要调整其余角色权限能够自行调整。
其余配置批改
至此,咱们的定制化配置就实现了。
基本上所有的配置都能够通过在 sentry.conf.example.py
文件中从新赋值整个变量或某个字段的形式调整,有哪些配置项的话能够去源代码的 src/sentry/conf/server.py 文件中查问,有其余需要的话能够自行尝试批改。
前端接入和应用
后续的接入应用,咱们以 Vue 我的项目示范。
SDK 接入
首先须要进行对应团队和我的项目的创立:
选取平台语言等信息后,能够创立团队和我的项目:
npm i @sentry/browser @sentry/integrations
其中 @sentry/browser
为浏览器端的接入 sdk,须要留神的是,它只反对 ie11 及以上版本的浏览器的谬误上报,低版本须要应用 raven.js
,咱们就不再介绍。
@sentry/integrations
包里是官网提供的针对前端各个框架的性能加强,后续会介绍。
在进行接入是,咱们必须要晓得的是和你以后我的项目绑定的 DSN(客户端秘钥),可在治理端由 Settings 进入具体我的项目的配置中查看。
import * as Sentry from '@sentry/browser'
import {Vue as VueIntegration} from '@sentry/integrations'
import Vue from 'vue'
Sentry.init({
// 高访问量利用能够管制上报百分比
tracesSampleRate: 0.3,
// 不同的环境上报到不同的 environment 分类
environment: process.env.ENVIRONMENT,
// 以后我的项目的 dsn 配置
dsn: 'https://[clientKey]@sentry.xxx.com/[id]',
// 追踪 vue 谬误,上报 props,保留控制台谬误输入
integrations: [new VueIntegration({ Vue, attachProps: true, logErrors: true})]
})
能够看到的是 VueIntegration 加强上报了 Vue 组件的 props,同时咱们还能够额定上报构建的版本信息 release。此时,Sentry 曾经开始上报 console.error、ajax error、uncatch promise 等信息。同时,咱们还能够进行被动上报、关联用户。
Sentry.captureException(err)
Sentry.setUser({id: user.id})
Sentry 还提供了基于 Webpack 的 plugin:webpack-sentry-plugin 帮忙实现接入,就不再做介绍。
如何应用监控数据
进入某个具体的我的项目后,能够看到 Sentry 依据谬误的 message、stack、产生地位进行演绎分类后的 Issue 列表:
在右侧,能够看到每个谬误的产生趋势、产生次数、影响用户数和指派给谁解决这个问题的按钮。咱们能够通过这些指标进行错误处理的优先级调配和指派。
通过发展趋势,咱们也能够察看到是否与某次上线无关,还能够通过左侧的 Discover 创立自定义的趋势看板,更有针对性的进行察看。
点击进入每个 issue 后,能够看到详细信息:
从上到下,能够看到谬误的名称,产生的次要环境信息,Sentry 提取的谬误特色,谬误堆栈,在最上面的 BREADCRUMBS
中能够看到异样产生前的前置操作有哪些,能够帮忙你进行问题操作步骤的还原,帮助进行问题排查。
Sentry 的入门应用到此为止。其余的性能,如报警配置、性能监控能够自行摸索。
招聘
作为智联招聘的前端架构团队,咱们始终在寻找气味相投的前后端架构师和高级工程师,如果您也和咱们一样酷爱技术、酷爱学习、酷爱摸索,就请退出咱们吧!请将简历请发送至邮箱 zpfe@group.zhaopin.com.cn,或者微信扫码沟通。