- 可观测性
- 后端
- 微服务
- 云原生
【免费下载链接】skywalking
APM, Application Performance Monitoring System
浏览器端监控是 SkyWalking 前端可观测性体系的重要一环:通过客户端 JavaScript 库在浏览器页面中采集页面性能与运行时错误,并上报到 OAP 后端进行聚合分析。本文以仓库文档 docs/en/setup/service-agent/browser-agent.md 为核心,结合 OAP 端skywalking-browser-receiver-plugin模块的真实源码,完整讲解浏览器监控的接入方式、后端receiver-browser配置、数据上报协议与底层处理链路,帮助你从"浏览器页面上报"到"后端指标产出"建立一条完整可验证的认知。
什么是 Browser Monitoring
Apache SkyWalking 官方提供了名为Apache SkyWalking Client JS的客户端 JavaScript 异常与链路追踪库,它作为浏览器的探针(Probe),负责在用户浏览器环境中采集数据并上报给 SkyWalking 后端。
根据原文档,该库具备以下核心特性:
- 提供指标与错误采集能力:将页面性能指标(如 DNS 解析、TCP 建连、首屏时间、DOM Ready 等)与运行时错误(Ajax 错误、资源加载错误、JS 异常等)采集并上报到 SkyWalking 后端;
- 轻量级:它是一个纯 JavaScript 库,无需安装任何浏览器插件即可工作;
- 作为分布式追踪的起点:浏览器是整个分布式链路追踪系统的起始端(First Span 的发起方),通过它可以将一次页面请求的前端部分与后端服务调用串联起来,形成端到端的完整链路视图。
Client JS 与后端的完整数据交互格式由 Browser Protocol 定义,同时提供了 HTTP 1.1 封装版本,便于纯浏览器环境直接通过 HTTP 上报。
前置条件:启用 receiver-browser 接收器
浏览器数据要进入 OAP 后端,前提是后端已启用receiver-browser接收器模块。原文档明确指出:
确保 receiver-browser 已启用。自 8.2.0 版本起它默认开启(ON)。
该模块的完整实现位于仓库oap-server/server-receiver-plugin/skywalking-browser-receiver-plugin,模块装配入口是 BrowserModuleProvider.java。从源码可以看到,该 Provider 在start()阶段会完成三件事:
- 通过
OALEngineLoaderService加载浏览器专用 OAL 指标定义BrowserOALDefine.INSTANCE; - 向 gRPC 共享服务器注册
BrowserPerfServiceHandler(及其兼容处理器BrowserPerfServiceHandlerCompat); - 向 HTTP 共享服务器注册
BrowserPerfServiceHTTPHandler(仅注册POST方法)。
因此浏览器数据同时支持 gRPC 与 HTTP 两种上报通道,二者共用同一套解析与监听器机制。
receiver-browser 配置详解
receiver-browser在 OAP 默认配置 application.yml 中对应如下配置块:
receiver-browser: selector: ${SW_RECEIVER_BROWSER:default} default: # The sample rate precision is 1/10000. 10000 means 100% sample in default. sampleRate: ${SW_RECEIVER_BROWSER_SAMPLE_RATE:10000}各配置项说明如下:
| 配置项 | 默认值 | 说明 |
|---|---|---|
selector | ${SW_RECEIVER_BROWSER:default} | 选择器,用于激活/切换 receiver 实现,default表示激活默认实现。可通过环境变量SW_RECEIVER_BROWSER覆盖 |
sampleRate | ${SW_RECEIVER_BROWSER_SAMPLE_RATE:10000} | 采样率,精度为 1/10000,10000表示 100% 全量采样。可通过环境变量SW_RECEIVER_BROWSER_SAMPLE_RATE覆盖 |
该配置对应的 Java 配置类为 BrowserServiceModuleConfig.java,其内部sampleRate字段默认值即10000,注释与原文档完全一致:
/** * The sample rate precision is 1/10000. 10000 means 100% sample in default. */ private int sampleRate = 10000;采样机制在后端的真实实现
sampleRate并非客户端控制,而是后端接收侧执行的采样逻辑,实现在 ErrorLogRecordSampler.java 中:
/** * The sampler makes the sampling mechanism works at backend side. Sample result: [0,sampleRate) sampled, (sampleRate,~) * ignored */ public boolean shouldSample(int hashCode) { return hashCode % 10000 < sampleRate; }采样规则解读:
- 以错误日志的
uniqueId的哈希值对10000取模,结果落在[0, sampleRate)区间内的日志被保留,其余被丢弃; sampleRate = 10000时,hashCode % 10000 < 10000恒成立,即 100% 采样;sampleRate = 0时全部丢弃;- 例如设置为
5000,则约 50% 的错误日志会被保留,适合高流量场景下控制存储成本。
采样发生在 ErrorLogRecordListener.java 的parse()阶段:当uniqueId为空或未通过采样时,该日志被标记为IGNORED,不会进入后续落库流程。
数据上报协议:gRPC 与 HTTP 双通道
浏览器客户端(Client JS)向后端上报两类数据:性能数据(Perf Data)与错误日志(Error Log),协议定义见 Browser Protocol。
gRPC 服务
Browser Protocol 以 gRPC 格式定义了两个服务方法:
| 服务方法 | 用途 |
|---|---|
BrowserPerfService#collectPerfData | 上报页面性能数据 |
BrowserPerfService#collectErrorLogs | 上报错误日志(流式) |
gRPC 侧实现位于 BrowserPerfServiceHandler.java,其中:
collectPerfData为 Unary 调用,接收单条BrowserPerfData,处理完成后返回空Commands;collectErrorLogs为流式调用,通过StreamObserver<BrowserErrorLog>逐条接收错误日志,onCompleted时返回空Commands。
同时 BrowserPerfServiceHandlerCompat.java 提供了旧协议兼容处理,保证不同版本 Client JS 均可上报。
HTTP API
对于无法使用 gRPC 的场景(如纯浏览器环境),可直接使用 HTTP 1.1 协议上报,端点与 JSON 格式见 HTTP API Protocol,实现类为 BrowserPerfServiceHTTPHandler.java。
① 上报单条性能数据
POST http://localhost:12800/browser/perfData请求体(JSON):
{ "service": "web", "serviceVersion": "v0.0.1", "pagePath": "/index.html", "redirectTime": 10, "dnsTime": 10, "ttfbTime": 10, "tcpTime": 10, "transTime": 10, "domAnalysisTime": 10, "fptTime": 10, "domReadyTime": 10, "loadPageTime": 10, "resTime": 10, "sslTime": 10, "ttlTime": 10, "firstPackTime": 10, "fmpTime": 10 }响应:HTTP Status204。
② 上报错误日志列表
POST http://localhost:12800/browser/errorLogs请求体(JSON 数组,可一次上报多条):
[ { "uniqueId": "55ec6178-3fb7-43ef-899c-a26944407b01", "service": "web", "serviceVersion": "v0.0.1", "pagePath": "/index.html", "category": "ajax", "message": "error", "line": 1, "col": 1, "stack": "error", "errorUrl": "/index.html" } ]响应:HTTP Status204。
③ 上报单条错误日志
POST http://localhost:12800/browser/errorLog请求体为单个错误日志对象(字段与上例一致),响应同样为 HTTP Status204。
需要特别注意的是,Browser Protocol 文档强调:BrowserErrorLog#uniqueId必须在分布式环境中全局唯一。这一点在后端代码中也得到印证——ErrorLogRecordListener在uniqueId为空时直接忽略该日志,且后端采样正是基于该uniqueId的哈希值进行的。
性能数据字段含义
HTTP 示例中 14 个时间字段分别对应页面加载生命周期的各阶段,在后端被原样透传并用于指标聚合(对应字段见 MultiScopesPerfDataAnalysisListener.java):
| 字段 | 含义 |
|---|---|
redirectTime | 页面重定向耗时 |
dnsTime | DNS 解析耗时 |
ttfbTime | 首字节时间(Time To First Byte) |
tcpTime | TCP 建连耗时 |
transTime | 内容传输耗时 |
domAnalysisTime | DOM 解析耗时 |
fptTime | 首次渲染时间(First Paint Time) |
domReadyTime | DOM Ready 耗时 |
loadPageTime | 页面完全加载耗时 |
resTime | 资源加载耗时 |
sslTime | SSL 握手耗时 |
ttlTime | 总耗时(Time To Load) |
firstPackTime | 首包时间 |
fmpTime | 首次有内容绘制(First Meaningful Paint) |
后端处理链路源码解析
1. 数据入口与预处理
无论数据来自 gRPC 还是 HTTP,最终都会进入对应的 Analyzer。以性能数据为例,PerfDataAnalyzer.java 的处理逻辑如下:
- 校验
service字段:若为空,直接丢弃该条数据(return),不进入任何后续处理; - 时间戳对齐:不使用客户端时间,而是以服务器端当前时间
System.currentTimeMillis()为准; - 默认值兜底:
serviceVersion为空时置为"latest"(视为当前运行版本);pagePath为空时置为"/"(根路径); - 通知监听器:将装饰后的数据依次交给各
PerfDataAnalysisListener进行解析与指标构建。
2. 性能数据:多 Scope 指标构建
MutiScopesPerfDataAnalysisListener(注意源码类名为MultiScopesPerfDataAnalysisListener)在build()阶段会构造并发送四类 Source 到SourceReceiver:
BrowserAppTraffic:应用级流量(PV/错误量);BrowserAppSingleVersionTraffic:按版本维度的流量;BrowserAppPageTraffic:按页面维度的流量;BrowserAppPagePerf:页面级性能数据(当前仅分析页面级别的性能)。
时间维度上,性能数据按TimeBucket.getMinuteTimeBucket聚合到分钟级时间桶。
3. 错误日志:错误分类与落库
错误日志的解析由 MultiScopesErrorLogAnalysisListener.java 与 ErrorLogRecordListener.java 协作完成:
- 流量分类:
MultiScopesErrorLogAnalysisListener依据isFirstReportedError将流量分为FIRST_ERROR(首次错误)与ERROR(普通错误)两类,并记录错误类别(errorCategory,如 AJAX、资源、JS 等); - 明细落库:
ErrorLogRecordListener负责将满足采样条件的错误日志明细写入存储,通过IDManager构造serviceId、serviceVersionId、pagePathId,并保留原始数据dataBinary供查询时反序列化展示。
4. OAL 指标定义
浏览器相关指标并非写死在代码中,而是由 OAL 脚本 oal/browser.oal 定义,并在启动时由BrowserOALDefine(见 BrowserOALDefine.java)加载。脚本覆盖三类指标:
流量与错误率(应用/版本/页面三个维度):
browser_app_pv = from(BrowserAppTraffic.count).filter(trafficCategory == BrowserAppTrafficCategory.NORMAL).sum(); browser_app_error_rate = from(BrowserAppTraffic.*).rate(trafficCategory == BrowserAppTrafficCategory.FIRST_ERROR,trafficCategory == BrowserAppTrafficCategory.NORMAL); browser_app_error_sum = from(BrowserAppTraffic.count).filter(trafficCategory != BrowserAppTrafficCategory.NORMAL).sum();对应browser_app_single_version_*与browser_app_page_*系列,且页面维度还按错误类别细分:
browser_app_page_ajax_error_sum = from(BrowserAppPageTraffic.count).filter(trafficCategory != BrowserAppTrafficCategory.NORMAL).filter(errorCategory == BrowserErrorCategory.AJAX).sum(); browser_app_page_resource_error_sum = ... filter(errorCategory == BrowserErrorCategory.RESOURCE) ... browser_app_page_js_error_sum = ... filter(errorCategory in [BrowserErrorCategory.JS,BrowserErrorCategory.VUE,BrowserErrorCategory.PROMISE]) ... browser_app_page_unknown_error_sum = ... filter(errorCategory == BrowserErrorCategory.UNKNOWN) ...性能指标(平均值):通过longAvg对redirectTime、dnsTime、ttfbTime、tcpTime、transTime、domAnalysisTime、fptTime、domReadyTime、loadPageTime、resTime、sslTime、ttlTime、firstPackTime、fmpTime等 14 项耗时求平均。
性能指标(百分位):通过percentile2(10)计算fptTime、ttlTime、domReadyTime、loadPageTime、firstPackTime、fmpTime的 P10 百分位值,用于观察长尾分布。
注意脚本末尾的//disable(browser_error_log);注释表明:错误日志明细(Record 类型)默认不参与硬编码核心流,仅按需启用,避免明细数据占用过多存储。
运维与排障:遥测指标
BrowserPerfServiceHandler(gRPC)与BrowserPerfServiceHTTPHandler(HTTP)在构造函数中均向 Telemetry 模块注册了四类自监控指标,可用于观察接收器自身的处理健康状况:
| 指标名 | 类型 | 说明 |
|---|---|---|
browser_perf_data_in_latency | Histogram | 性能数据处理延迟 |
browser_perf_data_analysis_error_count | Counter | 性能数据分析错误次数 |
browser_error_log_in_latency | Histogram | 错误日志处理延迟 |
browser_error_log_analysis_error_count | Counter | 错误日志分析错误次数 |
这些指标带有protocol=grpc/protocol=http标签,可通过 OAP 的 Telemetry(如 Prometheus)暴露出来,用于排查"数据上报了但没看到指标"类问题。
常见问题与建议
- 数据上报后查不到指标:首先确认
receiver-browser是否处于激活状态(selector: ${SW_RECEIVER_BROWSER:default}),其次检查service字段是否为空(后端会直接丢弃)、uniqueId是否为空且全局唯一; - 错误日志量过大:调低
sampleRate(如SW_RECEIVER_BROWSER_SAMPLE_RATE=1000即 10% 采样),注意该采样基于uniqueId哈希,同一错误的多次上报会命中相同的采样结果; - 区分明细与聚合:PV、错误率、性能平均值/百分位等聚合指标始终会产出,而错误日志明细默认被禁用(
disable(browser_error_log)),若需要明细查询能力需评估存储开销后按需开启; - 协议选择:gRPC 适合可编程环境(如 Node 服务端代理),纯浏览器环境请使用 HTTP API(端口
12800为 OAP 共享 HTTP 端口,实际端口以部署配置为准)。
总结
通过本文可以完整掌握 SkyWalking 浏览器监控的接入闭环:
- 客户端:SkyWalking Client JS 作为浏览器探针采集页面性能与运行时错误,是分布式追踪的起点;
- 协议层:数据经 gRPC(
BrowserPerfService)或 HTTP(/browser/perfData、/browser/errorLog(s))双通道上报; - 后端:
receiver-browser模块(默认自 8.2.0 起激活)负责接收、采样、解析并构建多维度 Source; - 指标层:由 oal/browser.oal 定义 PV、错误率、错误分类计数及 14 项性能指标的平均值与百分位,最终供 SkyWalking UI 或 GraphQL 查询展示。
按本文配置好sampleRate并确认receiver-browser激活后,你的 Web 应用即可无缝接入 SkyWalking 的浏览器端可观测性体系。
- 可观测性
- 后端
- 微服务
- 云原生
【免费下载链接】skywalking
APM, Application Performance Monitoring System
相关推荐
Apache SkyWalking 浏览器监控协议(Browser Protocol)全解析:gRPC 与 HTTP 1.1 数据上报实战
Apache SkyWalking 浏览器监控协议(Browser Protocol)全解析:gRPC 与 HTTP 1.1 数据上报实战 本文围绕 Apach
可观测性后端微服务云原生SkyWalking Browser Protocol 详解:浏览器性能与错误数据上报接口规范
SkyWalking Browser Protocol 详解:浏览器性能与错误数据上报接口规范 导读 本篇文章围绕 docs/en/api/browser pr
可观测性APM链路追踪指标监控日志分析微服务SkyWalking OAP Zabbix Receiver 接入指南:将 Zabbix Agent 指标纳入 Meter System 统一监控
SkyWalking OAP Zabbix Receiver 接入指南:将 Zabbix Agent 指标纳入 Meter System 统一监控 本文围绕 A
可观测性后端微服务云原生
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考