调研下初出茅庐市值达到1亿美金的监控产品sentry,因为我会花一周时间复制出其功能。
从错误跟踪到性能监控,开发人员可以从前端到后端看到真正重要的内容,更快地解决问题,并不断了解他们的应用程序。
支持的类型如下图
这里我选择React项目。
创建项目后就会展示React客户端的配置文档:
完整文档可见:https://docs.sentry.io/platforms/javascript/guides/react/
在本地创建一个React项目来测试.
参考文档:
https://zh-hans.reactjs.org/tutorial/tutorial.html#setup-option-2-local-development-environment
在第一次等待事件到来
为了看到报错,我们写一个报错的按钮
上传到sentry后,可以看到报错:
点进去是详细的异常链
分成了所有事务、web、前端、后端、移动端
Performance监控需要客户端开启监控
export default Sentry.withProfiler(App);
然后可以看到访问性能
是对比各个版本引发的错误,发现问题是哪个版本引入的。
这功能是付费功能,可以免费体验14天。用于发现过去事件的趋势,支持各种过滤查询。
就是通用的仪表盘功能,配置各种展示的图表组件。
https://develop.sentry.dev/architecture/
Relay:中转服务,负责过滤事件,将事件发送到Kafka。
Kafka:事件队列。
Snuba:用于搜索事件,消费Kafka的事件信息,存到CK里 。
Redis: 高可用redis集群,缓存配置、事件数据。
Postgres:根据文档 ,存的是性能监控的trace数据,并且会定期清理。
Symbolicator:一个辅助处理事件的服务,处理stacktrace。
Sentry(web):后台管理界面,服务端使用python,django框架开发。
完整的数据流向,完整文档里将鼠标移上去有解释。
https://develop.sentry.dev/sdk/overview/
其建议所有语言的客户端使用都应该像下面这样:
1、初始化服务器信息和配置(一般在服务启动最前面)
2、在你希望捕获异常的地方拦截,或想埋点的地方上报一些数据;
3、上报后会返回一个ID,可以打到日志里方便查询。
https://develop.sentry.dev/sdk/event-payloads/
Sentry的客户端提交事件的各种接口字段说明,也就是上报数据时的数据结构。
对应的是stacktrace.
下面是一个实例
{
"exception": {
"values": [
{
"type": "ReferenceError",
"value": "methodDoesNotExist is not defined",
"stacktrace": {
"frames": [
{
"filename": "http://localhost:3000/static/js/bundle.js",
"function": "MessagePort.performWorkUntilDeadline",
"in_app": true,
"lineno": 56254,
"colno": 25
},
{
"filename": "http://localhost:3000/static/js/bundle.js",
"function": "flushWork",
"in_app": true,
"lineno": 55970,
"colno": 18
}
]
},
"mechanism": {
"type": "instrument",
"handled": true,
"data": {
"function": "addEventListener",
"handler": "callCallback",
"target": "EventTarget"
}
}
}
]
},
"level": "error",
"event_id": "febea4ba507b43f4becce8532af35301",
"platform": "javascript",
"timestamp": 1655258077.609,
"environment": "production",
"sdk": {
"integrations": [
"InboundFilters",
"FunctionToString",
"TryCatch",
"Breadcrumbs",
"GlobalHandlers",
"LinkedErrors",
"Dedupe",
"HttpContext",
"BrowserTracing"
],
"name": "sentry.javascript.react",
"version": "7.1.1",
"packages": [
{
"name": "npm:@sentry/react",
"version": "7.1.1"
}
]
},
"contexts": {
"trace": {
"op": "pageload",
"span_id": "90c96f00acb84b79",
"status": "internal_error",
"trace_id": "d1dc3bd5f3fd437ba801d29f256685e2"
}
},
"tags": {
"transaction": "/"
},
"request": {
"url": "http://localhost:3000/",
"headers": {
"Referer": "http://localhost:3000/",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36"
}
},
"extra": {
"arguments": [
{
"type": "react-invokeguardedcallback",
"target": "react",
"currentTarget": "react",
"isTrusted": false
}
]
}
}
https://develop.sentry.dev/sdk/event-payloads/span/
对应Span接口,下面是一个实例:
{
"contexts": {
"trace": {
"op": "pageload",
"span_id": "98b78c94df7c269b",
"tags": {
"effectiveConnectionType": "4g",
"deviceMemory": "8 GB",
"hardwareConcurrency": "8",
"sentry_reportAllChanges": false
},
"trace_id": "40c91f4ff47744d092ccc9accfdc966a"
}
},
"spans": [
{
"data": {
"Transfer Size": 300,
"Encoded Body Size": 3461,
"Decoded Body Size": 3870
},
"description": "/favicon.ico",
"op": "resource.other",
"parent_span_id": "98b78c94df7c269b",
"span_id": "b98e6c4f5cc0d19a",
"start_timestamp": 1655259235.3195002,
"timestamp": 1655259235.3388002,
"trace_id": "40c91f4ff47744d092ccc9accfdc966a"
},
{
"data": {
"Transfer Size": 300,
"Encoded Body Size": 5347,
"Decoded Body Size": 5347
},
"description": "/logo192.png",
"op": "resource.other",
"parent_span_id": "98b78c94df7c269b",
"span_id": "a63b2692832e459e",
"start_timestamp": 1655259235.3198001,
"timestamp": 1655259235.3390002,
"trace_id": "40c91f4ff47744d092ccc9accfdc966a"
}
],
"start_timestamp": 1655259235.0829,
"tags": {
"effectiveConnectionType": "4g",
"deviceMemory": "8 GB",
"hardwareConcurrency": "8",
"sentry_reportAllChanges": false
},
"timestamp": 1655259235.3390002,
"transaction": "/",
"type": "transaction",
"measurements": {
"fp": {
"value": 179.0001392364502,
"unit": "millisecond"
},
"mark.fp": {
"value": 1655259235.2619002,
"unit": "second"
},
"fcp": {
"value": 179.0001392364502,
"unit": "millisecond"
},
"mark.fcp": {
"value": 1655259235.2619002,
"unit": "second"
},
"connection.rtt": {
"value": 250,
"unit": "millisecond"
},
"connection.downlink": {
"value": 0.45,
"unit": ""
},
"ttfb": {
"value": 9.999990463256836,
"unit": "millisecond"
},
"ttfb.requestTime": {
"value": 2.79998779296875,
"unit": "second"
}
},
"platform": "javascript",
"event_id": "78eb3ad4228b4ff6a50b4ec097623380",
"environment": "production",
"sdk": {
"integrations": [
"InboundFilters",
"FunctionToString",
"TryCatch",
"Breadcrumbs",
"GlobalHandlers",
"LinkedErrors",
"Dedupe",
"HttpContext",
"BrowserTracing"
],
"name": "sentry.javascript.react",
"version": "7.1.1",
"packages": [
{
"name": "npm:@sentry/react",
"version": "7.1.1"
}
]
},
"request": {
"url": "http://localhost:3000/",
"headers": {
"Referer": "http://localhost:3000/",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36"
}
},
"extra": {}
}