前端优化数据量化必备神器:Grafana《现代前端工程体验优化》第一章 数据驱动 第二节 用户体验数据收集与可视化

上一节:《你做的前端优化都错了!《现代前端工程体验优化》前言 && 第一章 数据驱动》

3. 用户体验数据收集与可视化:基于 Prometheus 及 Grafana 的实现简介

有了获取用户体验指标数据的工具,还需要进一步大量收集、细致分析这些数据,以便了解现状、确定优化方向。

笔者推荐一套经过实践检验、开发体验较好的开源工具:Prometheus 和 Grafana。

1. Prometheus 及 Grafana 简介

Prometheus (prometheus.io/ )是一款开源的数据监控解决方案,包括针对各种编程语言的数据采集SDK(例如面向 Node.js 的NPM包客户端:www.npmjs.com/package/pro… )、接收数据上报的后端服务器应用、基于时间序的数据库、以及基础的数据可视化前端应用,具有很强大的拓展性,可以方便快速地融合进已有的项目中,作为数据监控的中台工具。

Grafana (grafana.com/ )是一款开源的数据可视化工具,包括兼容Promethrus在内各种数据库的数据查询工具、内置各种图表模板的数据可视化前端应用,并且支持免费的私有化部署。

将 Prometheus 与 Grafana 整合进我们的项目中便可快捷的实现强大的数据收集、可视化能力。

下面我们以Node.js为例,演示如何接入这2款工具。

2. 接入演示

我们基于:

  • Grafana 官方的云端应用
  • 本地环境自建的 Node.js 服务器应用
  • Node.js 的 Prometheus 数据收集SDK:prom-client

演示如何从本地环境收集 web-vitals 数据,并上传到 Grafana,最终创建出数据可视化图表。

首先我们注册并登录 Grafana 官方的云端应用:grafana.com/get/?pg=gra… ,每个账户都有足够的免费试用额度供我们测试。

前端优化数据量化必备神器:Grafana《现代前端工程体验优化》第一章 数据驱动 第二节 用户体验数据收集与可视化

完成注册后,我们就会进入Grafana的看板页面,这里是我们管理数据可视化图表、接入数据源的主要工作区域。

但因为此时我们还没有接入数据,所以内容还是一片空白。接下来我们启动一个基于prom-client的Node.js服务器作为我们的数据收集应用。

首先我们从左侧边栏访问 Connection > Connect data 目录,搜索 node.js 即可找到官网推荐的Node.js 应用接入基础设施:

前端优化数据量化必备神器:Grafana《现代前端工程体验优化》第一章 数据驱动 第二节 用户体验数据收集与可视化

前端优化数据量化必备神器:Grafana《现代前端工程体验优化》第一章 数据驱动 第二节 用户体验数据收集与可视化

不同的数据源有不同的特性,例如:

  • 查询语句的格式
  • 是否支持日志全文查询

Grafana 支持众多数据源,如果 prometheus 不适合你的前后端架构,可以参考官方文档选择ElasticsearchGraphite等其他数据源:grafana.com/docs/grafan…

如果只需要指标收集和存储,可以选择 Prometheus 或 Graphite;
如果需要进行日志收集和分析,可以选择 Elasticsearch。

点击进入后,接下来我们按照官方文档首先检查必要准备:

安装 Grafana Agent 应用用于收集转发本地的Prometheus数据:

选择对应系统,输入API key的备注名,点击 Greater API token 生成接口令牌,随后会提示生成已完成:Your API token has been generated below.

前端优化数据量化必备神器:Grafana《现代前端工程体验优化》第一章 数据驱动 第二节 用户体验数据收集与可视化

接下来我们要运行官方提供的命令行从而下载、安装并配置 Grafana Agent 应用,下载和安装可能需要一定时间并克服网络限制:

注意:需要以管理员身份运行 PowerShell,运行方式如下图:
前端优化数据量化必备神器:Grafana《现代前端工程体验优化》第一章 数据驱动 第二节 用户体验数据收集与可视化

前端优化数据量化必备神器:Grafana《现代前端工程体验优化》第一章 数据驱动 第二节 用户体验数据收集与可视化

命令执行完成后,点击左下角的 Test agengt connection 即可验证安装是否完成。

验证通过、安装完成后,就可以在本地通过Node.js应用收集并上报数据了,让我们新建一个空白 Node.js 项目:

  • 创建新目录:grafana-node-demo
  • 执行 npm init 初始化生成 package.json,并添加启动脚本:"start": "node app.js"
  • 安装必要NPM包依赖:npm install express prom-client
  • 新建 app.js ,将官方的代码示例复制粘贴下来

前端优化数据量化必备神器:Grafana《现代前端工程体验优化》第一章 数据驱动 第二节 用户体验数据收集与可视化

官方示例需要Node.js环境支持 ES module,你也可以参考示例项目,直接使用更方便的 CommonJS module:

这部分可以参考笔者提供示例中的《feat: 引入express && prom-client;初始化服务》commit:github.com/JuniorTour/…

运行 npm run start 后,即可开始自动采集一批默认的 Node.js 应用数据。

最后,让我们把对应默认Node.js 应用数据的预置可视化图表,添加到我们的看板中,点击下图中的 Install 按钮:

前端优化数据量化必备神器:Grafana《现代前端工程体验优化》第一章 数据驱动 第二节 用户体验数据收集与可视化

一套监控 Node.js 应用内存用量、CPU使用率等指标的可视化看板就被添加到我们的看板中了:

前端优化数据量化必备神器:Grafana《现代前端工程体验优化》第一章 数据驱动 第二节 用户体验数据收集与可视化

我们的目标不只是监控这些基础指标,下面让我们试试如何增加收集 web-vitals 数据的自定义指标。

Grafana 官方 Node.js 集成文档:grafana.com/docs/grafan…

各大云服务供应商也有集成 Grafana:

3. 增加自定义指标上报并创建可视化图表

为了将前端利用 web-vitals 收集的数据,发送到 Grafana,后端服务需要基于 prom-client 的能力,增加一批自定义指标。

让我继续在 app.js 中添加以下代码:

这部分可以参考笔者提供示例中的《feat: 增加自定义计数指标 webVitalsRatingCounter》commit:github.com/JuniorTour/…

// 3. 对所有接口增加 跨域资源共享(CORS)配置
// Enable CORS for all routes
app.use((req, res, next) => {
  res.header("Access-Control-Allow-Origin", "*"); // Allow any origin
  res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept"); // Allow these headers
  if (req.method === 'OPTIONS') {
    res.header("Access-Control-Allow-Methods", "POST"); // Allow POST method
    return res.sendStatus(200);
  }
  next();
});

// 2. 新建了一个自定义计数指标webVitalsRatingCounter
// https://www.npmjs.com/package/prom-client#:~:text=()%3B-,Custom%20Metrics,-All%20metric%20types
const webVitalsRatingCounter = new client.Counter({
  name: 'webVitalsRatingCounter',
  help: 'counter to store web-vitals rating data',
  registers: [register],
  labelNames: ['name', 'rating'],
});

// 1. 增加了一个POST方法的接口
app.post('/post-web-vitals', function(req, res) {
  console.log(`req.body=${req.body}`)
  const labels = req.body.labels

  webVitalsRatingCounter.inc(labels)

  const message = `Get web-vitals: labels=${JSON.stringify(labels)}`
  console.log(message)
  res.status(200).json({ message });
});

通过这段代码,我们:

  1. 增加了一个POST方法的接口/post-web-vitals,用于接收前端发送来的 web-vitals 数据;
  2. 新建了一个自定义计数指标webVitalsRatingCounter,用于收到 web-vitals 数据计数、统计数据名称(name)、评分(rating);
  3. 对所有接口增加 跨域资源共享(CORS)配置,以便我们稍后从DEMO中获取的数据可以跨域发送给我们本地的http://localhost:4001/post-web-vitals接口;

基于这段代码我们就可以从前端应用中通过HTTP 异步请求发送 web-vitals 数据到这个后端服务,并借助 prom-client 的自定义计数指标webVitalsRatingCounter将数据上报到 Grafana 供我们查询、创建可视化图表。

接下来我们为之前的《获取web-vitals数据在线 DEMO: output.jsbin.com/bizanep 》增加上报数据到 Node.js 后端的逻辑:

// https://jsbin.com/xifudez/edit?html,output
async function sendDataToBackend(data) {
  if (!data) {
    return
  }
  await fetch('http://localhost:4001/post-web-vitals', {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        labels: {
          name: data?.name,
          rating: data?.rating
        }
      }),
  })
}

function onGetWebVitalsData(data) {
  if (!data?.name) {
    return
  }
  const name = data.name
  const value = data.value
  const rating = data.rating
  sendDataToBackend(data)
  const msg = (`(已发送到后端)${name}: value=${value}, rating=${rating}`)
  console.log(msg)
  setInnerHtml(name?.toLowerCase(), msg)
}

onFCP(onGetWebVitalsData);

我们的改动主要是:

  • 增加sendDataToBackend方法,用于接受到web-vitals库的数据后发送HTTP请求到后端接口,并把name, rating这2个字段作为请求体;
  • 在之前已有的onGetWebVitalsData方法中增加sendDataToBackend(data)方法的调用,将指标数据作为参数传入;

完整示例请参考《发送 web-vitals 数据 DEMO》output.jsbin.com/xifudez

运行这些新增改动后,我们将能在开发中工具的Network面板中看发送数据的HTTP请求,以及后端的响应信息:

前端优化数据量化必备神器:Grafana《现代前端工程体验优化》第一章 数据驱动 第二节 用户体验数据收集与可视化

有了这样一套前后端逻辑,我们的web-vitals数据就成功的发送到了 Grafana,接下来我们试着基于这些数据创建几张可视化图表。

4. 创建 Grafana 可视化图表指南

下面我们一起来试试创建一张Grafana的可视化图表,主要有以下几步:

1. 访问仪表盘(Dashboard)页面,点击新建仪表盘(New Dashboard)按钮

前端优化数据量化必备神器:Grafana《现代前端工程体验优化》第一章 数据驱动 第二节 用户体验数据收集与可视化

2. 点击增加可视化(Add visualization)

前端优化数据量化必备神器:Grafana《现代前端工程体验优化》第一章 数据驱动 第二节 用户体验数据收集与可视化

3. 选择(或确认)数据源

如果按照上文的接入演示一路操作过来,会有默认的数据源grafanaclound-yourName-prom

前端优化数据量化必备神器:Grafana《现代前端工程体验优化》第一章 数据驱动 第二节 用户体验数据收集与可视化

4. 输入查询语录

Grafana 中不同的数据源对应不同的查询器面板及语法,我们以前文示例的 Prometheus 数据源为例,其主要有 交互界面选择查询语句(Builder)和 直接输入查询语句文本(Code)2种模式。

前端优化数据量化必备神器:Grafana《现代前端工程体验优化》第一章 数据驱动 第二节 用户体验数据收集与可视化

推荐使用对新用户更为友好的Builder模式,可以看到包含以下各选项:

  • 指标(Metric)
  • 标签过滤(Label filters)

分别对应我们调用 prom-client 的 new Counter API 时传入的name,labelNames字段:

const webVitalsRatingCounter = new client.Counter({
  name: 'webVitalsRatingCounter',
  help: 'counter to store web-vitals rating data',
  registers: [register],
  labelNames: ['name', 'rating'],
});

我们分别输入并选择 webVitalsRatingCountername=FCPrating=good 三项后,

前端优化数据量化必备神器:Grafana《现代前端工程体验优化》第一章 数据驱动 第二节 用户体验数据收集与可视化

点击刷新仪表盘(Refresh Dashboard)即可看到我们刚刚上传的数据:

前端优化数据量化必备神器:Grafana《现代前端工程体验优化》第一章 数据驱动 第二节 用户体验数据收集与可视化

不同的数据源有各自不同的查询语句语法

5. 调整样式、配置等细节

有了数据后,我们就可以进一步完善可视化图表的细节,常用的功能主要有:

  1. 图表类型:常用的有折线图、柱状图,纯文本;

  2. 标题和描述

  3. 提示(Tooltip)和图例(Legend):设置何时显示提示、图例的样式和内容;

  4. 度量选项(Standard Options):设置当前查询的值是什么单位,常用的有:

    1. 其他-短数值
    2. 其他-百分比
    3. 时间-毫秒
  5. 时间间隔:设置以多久的时间间隔聚合数据为图中的一个数据点,例如截图中5m即表示将5分钟内的数据统一计入可视化图中的一个点。例如下图中时间范围(Time Range)选择最近15分钟(Last 15 minutes),对应折线图就有3个点。

  6. 覆盖配置:设置查询语句显示名称、颜色等特殊配置

前端优化数据量化必备神器:Grafana《现代前端工程体验优化》第一章 数据驱动 第二节 用户体验数据收集与可视化

以上各项配置是个人总结较为常用的配置项,可以随意尝试调整,观察效果。

6. 分别保存图表和仪表盘

先后点击:

  • 图表编辑界面的右上角的应用(Apply)按钮,保存图表;
  • 仪表盘页面的保存仪表盘按钮,保存整体仪表盘,在此处可以输入仪表盘的名称及所属目录;

前端优化数据量化必备神器:Grafana《现代前端工程体验优化》第一章 数据驱动 第二节 用户体验数据收集与可视化

至此,我们就创建了第一张可视化图表,后续可以在实践中逐步熟悉 Grafana 的强大功能。这只是我们的第一步,接下来我会分享实践中遇到的问题和解决方案。

将数据记录并可视化,非常有成就感,可以让我们明确的感知到工作的产出。

当我们的数据和图表越来越多,我们对维护项目的了解也会越来越深入。

5. 堆叠百分比图优点及示例说明

从 web-vitals获得的数据中比较有统计意义的主要是:

  • 各指标的数值(value),例如累计布局变化CLS的0.2;
  • 评分(ratings):按官方标准对值进行划分得到的字符串值,共有优('good'),待提升('needs-improvement'),差('poor')三类值,用于对数据进行标准化处理;
  • 指标的统计来源(sources):记录了计算各指标的来源,例如累计布局变化CLS的sources字段记录的就是每次意外布局变化对应的DOM元素,及其变化前后的位置尺寸数据;

例如这条从onFCPAPI获取的LCP数据:

{
    delta: 382.80000019073486
    entries: [
        {
            duration: 0
            element: p
            entryType: "largest-contentful-paint"
            id: ""
            loadTime: 0
            name: ""
            renderTime: 382.8
            size: 8985
            startTime: 382.80000019073486
            url: ""
        }
    ]
    id: "v3-1683034382854-2926018174544"
    name: "LCP"
    navigationType: "reload"
    rating: "good"
    value: 382.80000019073486
}

笔者更推荐使用评分字段作为可视化图表的主要指标。

原因是直接使用值经常会有异常波动,经常在前端项目没有任何变更的情况下,观察到值产生了显著的变化。

但是评分相当于对值做了一次标准化处理,将一定范围内的值处理成统一的评分,有助于规避个别极端值导致的异常波动。

如下图,4/22 前后的 LCP 平均值在我们的前端项目没有变更的情况下就出现了减少11%的变化,这样的异常波动显然不利于评估我们优化的效果
前端优化数据量化必备神器:Grafana《现代前端工程体验优化》第一章 数据驱动 第二节 用户体验数据收集与可视化

笔者最初基于web-vitals制作数据可视化图时,用的就是值字段,计算了fcp等指标的平均值,观察一段时间后发现即使前后端项目没有上线变更,各指标的平均值也会有10%以上的波动,这显然是不符合预期的,这种波动将会降低我们评估优化效果的准确性。

后来改成基于评分字段制作各评分占比变化图后,数据波动问题就不再出现了,各评分的占比在长时间内都能保持不超过5%的波动。当我们主动进行一些用户优化后也能观察到更客观,更有说服力的指标变化。

分享一张基于模拟数据的“堆叠百分比图”示例及配置源码,各位读者可以根据需要复制后粘贴到自己的仪表盘内,并替换为真实数据,从而得到客观稳定的优化效果评估参考。

前端优化数据量化必备神器:Grafana《现代前端工程体验优化》第一章 数据驱动 第二节 用户体验数据收集与可视化

堆叠百分比图配置源码

{
"datasource": {
"type": "testdata",
"uid": "a95c7111-f01f-4e29-b3a6-9b0ac81d9094"
},
"description": "“堆叠百分比图”配置源码,作者:https://github.com/JuniorTour",
"fieldConfig": {
"defaults": {
"custom": {
"drawStyle": "line",
"lineInterpolation": "linear",
"barAlignment": 0,
"lineWidth": 1,
"fillOpacity": 70,
"gradientMode": "none",
"spanNulls": false,
"showPoints": "auto",
"pointSize": 1,
"stacking": {
"mode": "normal",
"group": "A"
},
"axisPlacement": "auto",
"axisLabel": "",
"axisColorMode": "text",
"scaleDistribution": {
"type": "linear"
},
"axisCenteredZero": false,
"hideFrom": {
"tooltip": false,
"viz": false,
"legend": false
},
"thresholdsStyle": {
"mode": "off"
}
},
"color": {
"mode": "palette-classic"
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
},
"max": 1,
"min": 0,
"unit": "percentunit"
},
"overrides": [
{
"matcher": {
"id": "byName",
"options": "G"
},
"properties": [
{
"id": "color",
"value": {
"fixedColor": "red",
"mode": "fixed"
}
},
{
"id": "displayName",
"value": "差"
}
]
},
{
"matcher": {
"id": "byName",
"options": "E"
},
"properties": [
{
"id": "displayName",
"value": "优"
}
]
},
{
"matcher": {
"id": "byName",
"options": "F"
},
"properties": [
{
"id": "displayName",
"value": "待改进"
}
]
}
]
},
"gridPos": {
"h": 8,
"w": 12,
"x": 0,
"y": 16
},
"id": 4,
"options": {
"tooltip": {
"mode": "multi",
"sort": "none"
},
"legend": {
"showLegend": true,
"displayMode": "table",
"placement": "right",
"calcs": [
"min",
"max",
"mean"
]
}
},
"targets": [
{
"alias": "good",
"datasource": {
"type": "testdata",
"uid": "a95c7111-f01f-4e29-b3a6-9b0ac81d9094"
},
"hide": true,
"refId": "A",
"scenarioId": "csv_metric_values",
"stringInput": "47,57,46,54,54,57,47,46,54,54,55,52,46,53,46"
},
{
"alias": "needsImprove",
"datasource": {
"type": "testdata",
"uid": "a95c7111-f01f-4e29-b3a6-9b0ac81d9094"
},
"hide": true,
"refId": "B",
"scenarioId": "csv_metric_values",
"stringInput": "10,14,11,11,19,13,15,19,15,13,16,17,12,9,19"
},
{
"alias": "poor",
"datasource": {
"type": "testdata",
"uid": "a95c7111-f01f-4e29-b3a6-9b0ac81d9094"
},
"hide": true,
"refId": "C",
"scenarioId": "csv_metric_values",
"stringInput": "15,18,6,12,9,17,10,16,5,8,15,12,11,12,16"
},
{
"datasource": {
"name": "Expression",
"type": "__expr__",
"uid": "__expr__"
},
"expression": "$A+$B+$C",
"hide": true,
"refId": "D",
"type": "math"
},
{
"datasource": {
"name": "Expression",
"type": "__expr__",
"uid": "__expr__"
},
"expression": "$A/$D",
"hide": false,
"refId": "E",
"type": "math"
},
{
"datasource": {
"name": "Expression",
"type": "__expr__",
"uid": "__expr__"
},
"expression": "$B/$D",
"hide": false,
"refId": "F",
"type": "math"
},
{
"datasource": {
"name": "Expression",
"type": "__expr__",
"uid": "__expr__"
},
"expression": "$C/$D",
"hide": false,
"refId": "G",
"type": "math"
}
],
"title": "堆叠百分比统计 WebVitals CLS 指标示例",
"type": "timeseries"
}

粘贴图表方式:
创建一张空图表后,点击更多选项-Inspect-Panel JSON,粘贴上述配置源码,点击应用(Apply)后即可立即生效

前端优化数据量化必备神器:Grafana《现代前端工程体验优化》第一章 数据驱动 第二节 用户体验数据收集与可视化

通过创建多张针对不同指标的堆叠百分比图,我们就能对web-vitals的各项指标有客观、可量化的监控,从而根据数据驱动我们优化体验:

前端优化数据量化必备神器:Grafana《现代前端工程体验优化》第一章 数据驱动 第二节 用户体验数据收集与可视化

《现代前端工程体验优化》目录

  • 第一章、数据驱动,指标先行
  • 第二章、用户体验优化
  • 第三章、开发体验优化
  • 第四章、制度建设
  • 第五章、持续集成:用自动化工具保持优化效果

未完待续,欢迎催更

原文链接:https://juejin.cn/post/7229899772769140773 作者:少游_JuniorTour

(0)
上一篇 2023年5月7日 上午10:56
下一篇 2023年5月7日 上午11:07

相关推荐

发表回复

登录后才能评论