为什么这条异常没有上报? HTTP 429
这是一个在优化前端异常上报时出现的问题
❝山月人肉盯着异常报了半个小时,但是在 Sentry 中仍然没有收到一条报错,郁闷不已,反复踌躇徘徊。喝一杯水后顿悟,然后发现了那条 http 状态码为 429 的异常上报请求。❞
捉虫
刚开始碰到 Sentry 中未收到报错 (Event) 时,一直在尝试去找 Sentry 服务器端的 Inbound Filter
设置以及 Sentry 客户端的 beforeSend
设置,这两个均与 Event
的过滤有关。以致于耽搁了半个小时。
「日志是排查问题时最重要的线索!!!」
后来回过神来,在控制台网络中找到了 http 429 的这条请求,而 429 的描述语为 Too Many Requests
。出现了 429,往往代表着 API 被限流了。
原因
在 Sentry 上对于异常上报设置了 Rate Limit
,每小时最多只能上报 1000 个 Event,导致许多异常被丢弃。
Rate Limit By Org
Rate Limit By Project
「图中红色的部分是丢弃的 Event,可以看出丢弃的比捕捉到的更要多!」
解决
基于以往上报及丢弃的 Event 数量,往大调整 Rate Limit
Rate Limit By Org
总结
- 还好这次问题暴露在前端的 Sentry 上报,可以很方便地通过
devtools -> network
来查询日志,如果本次是后端上报异常的话,就会较难调试,可能得用上一天时间 - 「对 Sentry 此类异常上报系统,作为业务层重要的基础设施,还是要多一分熟悉,平时才能更好地定位 Bug」
反思
关于异常监控系统,很多开发同学往往只注重如何去上报,但这远远不够!因为只注重如何去上报只是异常上报链路中的一个生产侧,不谋全局者不足谋一域。此时开发更应该在更高的角度去思考:
- 每个异常有没有都上报上去,会不会被限流或其他原因(如磁盘满了)被丢弃掉
- 每个异常上报上去后,如何去设计 Alert 规则:邮箱还是钉钉?警告要触发吗?
拓展
这里拓展一些关于异常上报的注意点,关于 Sentry 异常上报信息有三大关键字段及两大核心概念
三大关键字段指:
-
Tags
,也可以认为是Index
,作为索引,方便查询。如 userId,errorCode 前端还会涉及到浏览器及一些业务相关要素。 -
Stack
,异常堆栈,方便在异常系统直接定位代码 -
Context
,相关上下文信息,如发请求的url
及body
,执行数据库查询的sql
等
两大核心概念:
-
Event
,报一次错就是一个Event
-
Issue
,如一个 Bug 导致了 N 次 Event,则会聚合为一个Issue
,关于聚合算法,会根据fingerprint
来辨别
如果以上这些做好了,无论采用 ElaticSearch
还是 Sentry
做异常上报都是无关紧要的。
❝好吧,其实还是有很大不一样的,比如 Sentry 作为专一的异常上报系统,则会有更好的 Alert,而 ES 做 Alert 就很难了。且 Sentry 对 User Feedback,Event Group,Bug workflow 及与 jira,gitlab 的集成更好。 ❞
关于 Node
服务端的异常上报可以参考我以前的文章:
- Node 异常结构化与上报[1]
Reference
[1]Node 异常结构化与上报: https://shanyue.tech/node/error.html
- 如何调用finecms指定栏目的描述关键词
- finecms栏目文章页seo设置
- Logistic回归实战篇之预测病马死亡率(一)
- DedeCMS后台500错误一种原因是不支持PHP5.3、5.4及以上版本
- finecms指定从第几篇文章开始调用5条记录,并调用文章所在栏目
- finecms如何调用多个栏目的子栏目
- 从傅立叶变换到Gabor滤波器
- 三个小时学会wordpress模板制作
- The each() function is deprecated报错的解决方法
- 书接上文:薛定谔的猫是如何诞生的?
- docker源码分析(3)---镜像(1)
- k8s源码分析-----kubelet(8)pod管理
- 大会 | DiracNets:无需跳层连接的ResNet
- golang时间戳格式化与解析
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- JNI线程相关
- JNI函数加载
- CSS中的传统布局、多列布局、弹性伸缩布局及Emmet工具
- 数据分析可视化(四)|Pyecharts制作地图的几种方法评析
- tensorflow运行提示未编译使用SSE4.1,SSE4.2等问题的解决方法
- [手把手系列之二]实现多层神经网络
- 使用SystemVerilog简化FPGA中的接口
- 想用深度学习谱写自己的音乐吗?这篇指南来帮你!(附代码)
- 你不是说你会aop吗?
- 开源:推荐一个不错的离线IP地址定位库
- 武磊告别西甲!Python带你解读「全村的希望」武磊职业数据
- 谁在崛起,谁在没落?新一线城市竞争力盘点,用Python绘制动态图带你看懂!
- 两数相加
- 这样设置 IDEA,让你爽到飞起!
- Tensorflow基础入门十大操作总结