Skip to content

数据收集与可视化

收集生产数据的必要性

因开发环境和测试环境获取用户体验指标数据,用于评估优化效果存在两大明显弊端:

  • 样本总量少:开发、测试环境中用户数量有限,收集到的数据量太少,数据的波动会很大;
  • 不惧代表性:开发、测试环境缺少真实用户的网络状况、软硬件性能等差异化较大的因素。

所以在生产环境收集用户的真实数据,了解现状、确定优化目标、评估优化效果才是真实可靠的。

推荐数据收集工具

  • Prometheus 是一款开源的数据监控解决方案,主要包括以下模块:
    • 面相各种编程语言的数据采集 SDK(prom-client for Node.js)
    • 接收数据上报的服务端应用
    • 基于时序数据库
    • 基础数据可视化前端应用
  • Grafana 是一款开源的数据可视化工具,主要有以下特性:
    • 兼容 Prometheus 在内的各种数据库的数据查询
    • 内置海量的可视化图表模板
    • 支持免费的私有化部署

Grafana 数据可视化平台

  • 基于 Grafana 云端应用
  • 本地自建 Node.js 服务器应用,安装 Prometheus 数据收集 SDK(prom-client

1. 创建 Grafana Cloud 账户

访问 https://grafana.com/get/ 创建免费的 Grafana Cloud 账户,永久免费的权益包括:

  • 10k metrics
  • 50GB logs
  • 50GB traces
  • 50GB profiles
  • 500VUh k6 testing
  • 50k frontend sessions
  • 3 active users
  • 14 day retention

使用免费账户登录后进度 HOME 页面:

image-20240722102708172

2. 创建基于 Node.js 仪表盘

点击首页的 Get started 按钮开始设置 Grafana Cloud

image-20240722114222605

创建基于 Node.js 端的数据连接到 Grafana Cloud 平台:

image-20240722114310595

image-20240722114720189

3. 关于集成的配置细节

  1. 根据实际环境选择平台,后续操作步骤会根据不同的平台有所变化:

    Select platform

  2. 通过输入 Token name 创建新的 Token 或使用已有 Token 激活 Grafana Alloy 安装步骤:

    1. 按提示命令安装并运行 Grafana Alloy;
    2. 按提示命令对 Grafana Alloy 进行配置;
    3. 按提示命令运行 Grafana Alloy;
    4. 通过 Test Alloy connection 菜单验证连接状态;

    Install Grafana Alloy

  3. 根据实际环境选择 Simple set-up 或 Advanced set-up,仅单机演示选择 Simple set-up 即可:

    Make configuration selections

  4. 准备配置文件:

    1. 搭建 Node.js 运行环境:在 Node.js 服务中安装 prom-client 模块后启用默认指标,并将指标公开在 /metrics 端点;

      javascript
      import express from 'express';
      import { collectDefaultMetrics, register } from 'prom-client';
      
      collectDefaultMetrics();
      
      const app = express();
      
      app.get('/metrics', async (_req, res) => {
        try {
          res.set('Content-Type', register.contentType);
          res.end(await register.metrics());
        } catch (err) {
          res.status(500).end(err);
        }
      });
      
      app.listen(4001, '0.0.0.0');
    2. 设置 Grafana Alloy :将下面的配置追加到 /etc/alloy/config.alloy 配置文件;

      discovery.relabel "metrics_integrations_integrations_nodejs" {
      	targets = [{
      		__address__ = "localhost:4001",
      	}]
      
      	rule {
      		target_label = "instance"
      		replacement  = constants.hostname
      	}
      }
      
      prometheus.scrape "metrics_integrations_integrations_nodejs" {
      	targets    = discovery.relabel.metrics_integrations_integrations_nodejs.output
      	forward_to = [prometheus.relabel.metrics_integrations_integrations_nodejs.receiver]
      	job_name   = "integrations/nodejs"
      }
      
      prometheus.relabel "metrics_integrations_integrations_nodejs" {
      	forward_to = [prometheus.remote_write.metrics_service.receiver]
      
      	rule {
      		source_labels = ["__name__"]
      		regex         = "up|nodejs_active_handles_total|nodejs_active_requests_total|nodejs_eventloop_lag_p50_seconds|nodejs_eventloop_lag_p99_seconds|nodejs_eventloop_lag_seconds|nodejs_external_memory_bytes|nodejs_gc_duration_seconds_count|nodejs_gc_duration_seconds_sum|nodejs_heap_size_total_bytes|nodejs_heap_size_used_bytes|nodejs_heap_space_size_used_bytes|nodejs_version_info|process_cpu_seconds_total|process_cpu_system_seconds_total|process_cpu_user_seconds_total|process_resident_memory_bytes|process_start_time_seconds"
      		action        = "keep"
      	}
      }
    3. 运行命令重启 Grafana Alloy,重启后点击 Test connection 按钮测试连接状态:

      ./alloy-darwin-amd64 run /etc/alloy/config.alloy
    4. 安装仪表盘和警告窗口:点击 Install 按钮自动安装;

    5. 查看仪表盘和警告窗口:默认数据将每隔 30s 刷新一次;

      image-20240722144036663

      image-20240722144107838

      image-20240722144136755

      image-20240722144201971

4. 上报自定义指标

添加接收 POST 请求的 /metrics 端点,用来接收前端页面通过 web-vitals 收集到的指标数据,按 Prometheus 中自定义指标规范发送到 prom-client

JavaScript
// 接收 JSON 数据时需要添加此中间件
app.use(express.json());

// 用于接收前端页面的指标数据
app.post('/metrics', async (req, res) => {
    try {
        const { name, help, labels } = req.body;
        if (!name) {
            res.status(400).end('name is required');
        }
        if (!help) {
            res.status(400).end('help is required');
        }      
        res.status(200).end();
    } catch (err) {
        res.status(500).end(err);
    }
});

使用 Counter 计数器类型作为自定义指标的收集方案,具体可访问 prom-client 详细了解自定义指标的方式:

javascript
// prom-client.js

import client from 'prom-client';

const register = new client.Registry();
client.collectDefaultMetrics({ register });

function useCounter({ name, help, labels = [] }) {
    let counter = register.getSingleMetric(name);
    if (!counter) {
        counter = new client.Counter({
            name,
            help,
            registers: [register],
            labelNames: Object.keys(labels),
        });
    }

    counter.inc(labels, 1);
}

export { register, useCounter };

useCounter 添加到 POST /metrics 端点下:

javascript
import express from 'express';
import { useCounter, register } from './prom-client.js';

const app = express();

app.use(express.json());

app.get('/metrics', async (_req, res) => {
    // ... 
});

app.post('/metrics', async (req, res) => {
    try {
        const { name, help, labels } = req.body;
        if (!name) {
            res.status(400).end('name is required');
        }
        if (!help) {
            res.status(400).end('help is required');
        }
				
      	// 将数据发送到 prom-client
        useCounter({ name, help, labels });

        res.status(200).end();
    } catch (err) {
        res.status(500).end(err);
    }
});

app.listen(4001, '0.0.0.0');

在此需要更新 Grafana Alloy 配置文件以增加新指标(FCP)的收集:

prometheus.relabel "metrics_integrations_integrations_nodejs" {
	forward_to = [prometheus.remote_write.metrics_service.receiver]

	rule {
		source_labels = ["__name__"]
		regex         = "up|FCP|nodejs_active_handles_total|nodejs_active_requests_total|nodejs_eventloop_lag_p50_seconds|nodejs_eventloop_lag_p99_seconds|nodejs_eventloop_lag_seconds|nodejs_external_memory_bytes|nodejs_gc_duration_seconds_count|nodejs_gc_duration_seconds_sum|nodejs_heap_size_total_bytes|nodejs_heap_size_used_bytes|nodejs_heap_space_size_used_bytes|nodejs_version_info|process_cpu_seconds_total|process_cpu_system_seconds_total|process_cpu_user_seconds_total|process_resident_memory_bytes|process_start_time_seconds"
		action        = "keep"
	}
}

PS:更新配置后需要重启 Grafana Alloy

5. 创建可视化图表

按如图所示菜单创建一个新的仪表盘:

image-20240722202758361

image-20240722202940731

选中默认的数据源:

image-20240722203018840

在输入查询器面板按如图方式添加对 FCP 指标的过滤:

image-20240722203648816

在使用 PostMan 模拟前端上报 FCP 指标数据后,点击刷新图表即可看到图片正常开始渲染数据:

image-20240722205453309

最后分别保存图标和仪表盘:

image-20240722205018868

image-20240722205140380