前言
自从去年sentry又挂了之后,再加上大部分项目都是 C# 的,使用 ExceptionLess 的体验已经很不错了,所以我们就一直没再使用 sentry 🦎
前天刚把 Gitlab 配置好,接下来有一些其他语言☕️的项目要监控,我想着继续把 sentry 也重启了。然后 ExceptionLess 也很久没更新了,官方已经出到8.x版本,我们还在用 7.x,这次也顺便升级一下⛰️
没想到这一搞就折腾了一整天时间🥱,人都麻了🐎
sentry
关于sentry📄
❝在软件开发的世界里,错误跟踪和性能监控是保证应用健康和用户满意度的关键。这就是 Sentry 发挥作用的地方。Sentry 是一个开源的实时错误跟踪工具,它能有效帮助开发者监控和修复各种编程语言中的错误。无论是前端 JavaScript 错误还是后端 Python 异常,Sentry 都能捕捉到,并提供详尽的错误报告和分析。
核心功能
-
实时监控:Sentry 提供实时错误监控,一旦应用出现错误,它会立即捕获并通知开发者。
- 跨平台支持:支持多种编程语言和框架,包括 JavaScript, Python, Java, Ruby, PHP 等。
- 详细的错误报告:每个错误报告都包含了足够的信息,帮助开发者快速定位问题源头。这些信息包括错误发生的堆栈跟踪、受影响的用户、错误发生的时间以及错误前后的应用状态。
- 性能监控:不仅可以跟踪错误,还能监控应用的性能状况,如页面加载时间、API响应时间等,帮助开发者优化用户体验。
- 问题分析与解决:提供问题的趋势分析、影响范围评估及解决方案建议,使问题处理更加高效。
使用场景
❝Sentry 的使用场景广泛,它不仅适用于大型企业的复杂应用,也适合小型开发团队和个人项目。例如,在开发过程中集成 Sentry 可以持续监控应用状态,一旦部署新版本后出现问题,Sentry 可以帮助快速回滚并修复。此外,其用户友好的界面和强大的配置能力,让它成为处理错误和提升应用质量的得力工具。
self hosted
首先是部署 sentry,实际上并不难
为什么会折腾那么久,最后总结下来最主要的就是网络问题,其次是版本问题,官方文档用的是 24.1.0
,我一开始用了 github 上最新的 24.7.0
一直不行🙅♀️
最终是通过 cloudflare worker 解决的,可以参考之前这篇文章:使用Cloudflare Worker加速docker镜像
官方文档写得很详细: https://develop.sentry.dev/self-hosted/
按照官方的步骤走就完事了
解决网络问题之后,基本没啥障碍🥱
安装sentry⏬
VERSION="24.1.0"
git clone https://github.com/getsentry/self-hosted.git
cd self-hosted
git checkout ${VERSION}
sudo ./install.sh
如果要安装过程显示详细一点,可以加上 DEBUG=1
环境变量,然后顺便把遥测关了📴
sudo DEBUG=1 ./install.sh --no-report-self-hosted-issues
问题记录📝
当时安装时真的一波三折😭,这里记录遇到的一些问题
- 配置了
.env.custom
文件,导致执行 upgrade-clickhouse.sh
出错,一开始我还没用 Cloudflare Worker 来加速docker,所以打算用代理来pull image,官网文档说要把代理写在 /etc/environment
里,但我不想这么做,于是把代理配置放在 .env.custom
里,结果一直报错。 - 然后是 docker compose 版本的问题,本地的 compose 版本小于他要求的版本,升级这个 compose 也遇到一点小小的问题,我的 compose 执行文件在
~/.docker/cli-plugins/docker-compose
,表现是 docker plugins ,不过却识别不到,没法用 docker plugins 命令来更新,最后是直接在 github 下载可执行文件去替换,真正的解决方法往往是这么朴实无华。
主要组件⚙️
Sentry 的本体是基于 Django 开发的,Python 的灵活性和生态系统中的丰富库使其成为开发复杂应用程序如 Sentry 的一个理想选择,前端页面是 React 开发的。
整个 sentry 还是比较复杂的,当前版本跑起来之后有28个容器,对服务器的性能有一定要求。
主要🈶️这些组件:
- ClickHouse: 一个高性能的列式数据库,专门用于处理大规模数据分析,Sentry 用它来存储和查询事件数据。
- Redis: 一个内存中的数据结构存储系统,用作数据库、缓存和消息代理,Sentry 用它来处理队列和缓存任务。
- PostgreSQL: 一个强大的开源关系数据库,Sentry 使用它来存储核心数据,包括项目配置和用户数据。
- Kafka: 一个分布式流处理平台,Sentry 使用 Kafka 来处理事件流和确保数据的弹性处理。
- Zookeeper: 主要用于服务协调和配置管理,在 Sentry 中与 Kafka 配合使用,用于维护 Kafka 的服务状态。
- Snuba: Sentry 的服务组件之一,用 Python 编写,主要负责查询 ClickHouse 中的数据。
- Symbolicator: 用于处理原生堆栈跟踪的服务,帮助解析和符号化未处理的堆栈跟踪。
- Relay: 一个独立的服务,用于处理从客户端发送到 Sentry 的事件,提供数据清洗和安全性控制。
各个容器介绍📂
这些容器共同构成了 Sentry 的复杂架构,确保从数据收集到处理再到存储的每一环节都能高效、稳定地运行。
可以看到 sentry 是个非常重的监控服务
- attachments-consumer: 处理和存储错误报告中的附件数据。
- billing-metrics-consumer: 管理和处理与计费相关的度量数据。
- cron: 处理定时任务,如清理作业和触发定期任务。
- events-consumer: 接收和处理事件数据,确保它们被正确地存储和索引。
- generic-metrics-consumer: 处理通用度量数据,用于监控和分析。
- ingest-monitors: 处理和监控数据摄取过程中的事件和状态。
- ingest-occurrences: 处理事件发生的数据摄取。
- ingest-profiles: 管理用户的性能分析数据摄取。
- ingest-replay-recordings: 处理回放录像的数据摄取,用于错误复现。
- memcached: 提供内存缓存服务,增强数据读写速度和效率。
- metrics-consumer: 处理和聚合应用性能监控(APM)的度量数据。
- nginx: 作为反向代理服务器,处理 HTTP 请求和负载平衡。
- post-process-forwarder-errors: 处理错误事件的后处理和转发任务。
- post-process-forwarder-issue-platform: 处理问题平台的事件后处理和转发。
- post-process-forwarder-transactions: 处理事务事件的后处理和转发。
- postgres: 为 Sentry 提供关系数据库服务,存储配置和用户数据。
-
redis: 提供队列管理和缓存服务,支持事件处理和数据缓存。
- relay: 接收客户端的事件,进行清洗和安全校验后转发到 Sentry。
- snuba-api: 提供 API 接口访问 ClickHouse 存储的数据。
- snuba-replacer: 处理和替换 Snuba 中的数据,用于数据修正和去重。
- subscription-consumer-events: 管理事件数据订阅,处理相关通知。
- subscription-consumer-generic-metrics: 管理通用度量数据的订阅和通知。
- subscription-consumer-metrics: 管理度量数据的订阅和处理。
- subscription-consumer-transactions: 管理事务数据的订阅和处理。
- transactions-consumer: 处理和存储事务数据,支持应用性能监控。
- vroom: 处理特定于 Sentry 的内部请求和作业。
- zookeeper: 作为分布式服务的协调者,管理 Kafka 和其他服务的状态信息。
sentry有替代品吗?
🈶️
折腾的过程中,我一度想过要放弃,然后找到了两个看起来好像不错的开源替代品:
- https://www.highlight.io/
还没尝试,有空来部署试试,虽然现在sentry能用了,但毕竟还是太重了。
ExceptionLess
🌟 遇见 Exceptionless:你的代码的小小守护精灵! 🌟
嘿,亲爱的开发者朋友们!有没有想过,如果你的代码中有一个小小的守护精灵,它会帮你捕捉所有那些调皮的错误和异常,然后偷偷地告诉你哪里出了问题,让你的调试工作变得轻松又愉快呢?好消息,这个小精灵已经存在了,它的名字叫 Exceptionless!🎉
🚀 什么是 Exceptionless?
Exceptionless 不仅仅是一个工具,它是一个超级可爱的、功能强大的开源错误和事件报告服务。它就像是你的编程旅程中的忠实伙伴,一旦集成到你的应用中,它就会自动捕获未处理的异常和事件。想象一下,无论何时你的代码有点小插曲,Exceptionless 都会在第一时间抓住它们,并把这些信息安静地放在你的仪表板上,等你去查看。🐞
🌈 为什么它如此特别?
- 自动化监控:你只需轻轻一集成,Exceptionless 就会自动开始监控,你甚至不需要告诉它从何处开始!
- 实时反馈:收到实时错误报告,让你可以即刻了解发生了什么,就像有一个小精灵在你耳边低语。
- 深入洞察:不仅仅是告诉你“出错啦”,Exceptionless 还会告诉你为什么出错,哪里出错,甚至是谁遇到了这个错误。🕵️♂️
💖 开发者的最佳朋友
是否厌倦了那些冷冰冰的日志文件?让 Exceptionless 加入你的开发生活吧!它会用它那可爱的方式,带给你错误跟踪的全新体验。它不仅能帮助你修复错误,还能帮助你优化你的应用,让用户体验更上一层楼!
所以,让我们一起欢迎 Exceptionless,让它成为我们代码世界中的小英雄吧!使用 Exceptionless,一起把“糟糕”的时刻变成“搞定啦”的时刻!🌟
升级版本
OK,就像之前说的那样,我要把7.x升级到8.x
ExceptionLess 的文档比 sentry 差太多了,写得不清不楚的,不过好在我已经熟练使用这玩意了。
这个也比 sentry 简单一些,就几个组件。
- ExceptionLess 官网文档是虚假的文档 ✖
直接使用这个配置: https://github.com/exceptionless/Exceptionless/blob/main/samples/docker-compose.yml
不过为了更好的部署,还需要做一些小小的修改:
- 每个容器加上了
container_name
配置 - 关闭 app 容器的 HTTPS 功能,使用 swag 来提供就行
- 把 volumes 映射全改成当前目录了,记得先创建这些目录,并且赋权,例如
chmod -R 1000:1000 esdata/
- 与 swag 网络桥接,外部无法访问到这组容器,只能通过 swag 进行反代
services:
app:
restart: always
depends_on:
- elasticsearch
- redis
image: exceptionless/app:latest
container_name: exless_app
environment:
EX_AppMode: Production
EX_ConnectionStrings__Cache: provider=redis
EX_ConnectionStrings__Elasticsearch: server=http://elasticsearch:9200
EX_ConnectionStrings__MessageBus: provider=redis
#EX_ConnectionStrings__Metrics: provider=statsd;server=statsd;
EX_ConnectionStrings__Queue: provider=redis
EX_ConnectionStrings__Redis: server=redis,abortConnect=false
EX_ConnectionStrings__Storage: provider=folder;path=/app/storage
#ASPNETCORE_URLS: http://+;https://+
ASPNETCORE_URLS: http://+:80
#ASPNETCORE_HTTPS_PORT: 5001
#ASPNETCORE_Kestrel__Certificates__Default__Password: password
#ASPNETCORE_Kestrel__Certificates__Default__Path: /https/aspnetapp.pfx
EX_RunJobsInProcess: 'false'
volumes:
- ./appdata:/app/storage
- ./ssldata:/https
networks:
- default
- swag
jobs:
restart: always
depends_on:
- app
image: exceptionless/job:latest
container_name: exless_jobs
environment:
EX_AppMode: Production
EX_BaseURL: http://app:80
EX_ConnectionStrings__Cache: provider=redis
EX_ConnectionStrings__Elasticsearch: server=http://elasticsearch:9200
EX_ConnectionStrings__Email: smtps://邮箱(需转义):密码@smtp.exmail.qq.com:465
EX_SmtpFrom: 邮箱地址
EX_ConnectionStrings__MessageBus: provider=redis
#EX_ConnectionStrings__Metrics: provider=statsd;server=statsd;
EX_ConnectionStrings__Queue: provider=redis
EX_ConnectionStrings__Redis: server=redis,abortConnect=false
EX_ConnectionStrings__Storage: provider=folder;path=/app/storage
volumes:
- ./appdata:/app/storage
networks:
- default
elasticsearch:
image: exceptionless/elasticsearch:8.14.1
restart: always
container_name: exless_es
environment:
discovery.type: single-node
xpack.security.enabled: "false"
ES_JAVA_OPTS: -Xms1g -Xmx2g
expose:
- 9200
- 9300
volumes:
- ./esdata:/usr/share/elasticsearch/data
networks:
- default
kibana:
restart: always
depends_on:
- elasticsearch
image: docker.elastic.co/kibana/kibana:8.14.1
container_name: exless_kibana
expose:
- 5601
networks:
- default
redis:
restart: always
image: redis:7.2-alpine
container_name: exless_redis
expose:
- 6379
networks:
- default
networks:
default:
name: exless
swag:
name: swag
external: true
折腾的问题
- Elasticseach 版本升级问题: 之前是7.x版本,现在升级后是8.x版本,这俩版本的数据文件都不一样,需要做迁移,但因为前一天部署 sentry 把环境搞烂了,这次 ExceptionLess 也跑不起来,最后干脆整个 Elasticsearch 都删掉了
-
Elasticsearch 健康检查不通过问题: 一直报错提示
[02:22:16 ERR] Health check Elasticsearch with status Unhealthy completed after 242.2644ms with message 'null'
,这个是多方面的问题,等下来说 - docker 内部的DNS解析问题: 很奇怪,其他的项目都不会这样,后面也莫名其妙解决了,真实奇怪,盲猜和代理可能有点关系?🥱
Elasticsearch Unhealthy 问题
这个是最折磨的
一开始是7升级8的问题
然后把数据清理掉从头开始,已经能正常启动es8了
但是app和jobs容器还一直连不上
然后又经历了漫长的排错阶段,包括使用 busybox 和 alpine 容器去各种测网络
其中的玄学问题自不必说
一会就 docker DNS 失效
一会就各种连不上,最终在代理服务器的日志上发现了一堆标红的 elasticsearch:9200
访问,才发现问题出在代理上。
但我把环境变量、~/.docker/config.json
的代理都去掉了,还是会走代理,真的服了,这也成玄学问题了。
最终只能在代理服务器上加了个规则……
docker排坑
折腾花了好多时间
技术没学到
docker 排坑经验倒是增加了一丢丢
查容器的IP地址
其实用 portainer 这类工具可以很方便查看的,不过用命令也不难
exless-es 是容器名称,下面都会用这个作为栗子
docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' exless-es
使用临时容器测试网络连通性
现在的容器一般都是基于 alpine 这种轻量级发行版构建,没有 curl 之类的工具可以测试网络
没事,我们可以创建一个临时容器,加入到这组 compose 的网络里来测试,本文里这个网络名称是 exless
curl
以下命令是启动一个 curl 容器来测试 http://elasticsearch:9200
地址能否访问
docker run --rm --network=exless appropriate/curl http://elasticsearch:9200
busybox/alpine
docker run --rm -it --network=exless busybox
或者🔥
docker run --rm -it --network=exless alpine
这样就可以使用 ping, nslookup, dig 之类的工具,来排查网络问题
在 compose 配置里加入临时容器
这个方法也可以
services:
busybox:
image: busybox
container_name: exless-busybox
command: sleep 3600 # 让容器运行一个小时,足够进行测试
networks:
- default # 确保这是你其他服务使用的网络
小结
就这样吧
折腾的过程真的是究极折磨
写这篇文章仿佛又被折磨了一遍……
参考资料
- https://develop.sentry.dev/self-hosted/
- https://github.com/exceptionless/Exceptionless