在测试环境中落地 PageSpy 的实践记录

HuolalaTech/page-spy: 📦 The platform SDKs for PageSpy (github.com)

打破边界,PageSpy 新增重磅功能 - 掘金 (juejin.cn)

在看到 PageSpy 新增了 DataHarborPlugin 数据港口 插件后有觉得被直击了痛点

测试:你看这里有个 Bug,丢来一个截图

开发: 什么 Bug?! 在我这明明就是好的啊!!!你复现看看

测试:(复现不出)明明我刚刚就是有问题啊...

开发:这功能这么久了都这样,你懂不懂用啊,不懂就不要乱说,研发也很难的好吧

我们如何做的错误检测和回溯

我司前端(包括桌面浏览器端)主要使用 Uniapp进行开发,对接的是 UniApp 的 Uni 统计。在构建时输出 SourceMap 并上传至统计后台,应用发生错误即可将错误上报,在统计后台可以根据 SourceMap 定位到构建前的代码片段。

后端对每个请求都生成了 Request ID 并贯穿于整个请求链路,当后端抛出错误时响应中会携带 Request ID,同时将 Request ID 和错误堆栈写入日志。使用阿里云 SLS 日志平台对日志进行分析查询。

PageSpy 后对我们的改变

引入 PgaeSpy 之前,测试同学需要描述错误情况和所做的操作。有时甚至还需要附加 Console 控制台中的一些信息或后端接口返回的 Error ID 以辅助定位问题。(甚至有的时候测试同学的信息描述不全,研发还需要进一步询问具体的操作细节)

引入了 PageSpy 后借助 下载日志数据 功能,测试同学只需要描述错误情况,而不需要描述复现步骤和具体的页面操作情况。直接将日志发给开发,开发可以在 PageSpy 中进行日志回放。

我们的一些小修改

看似上面的流程已经比较方便了,但在我的使用过程中觉得在移动端进行下载日志数据的操作存在一些困难。

例如:某些应用的内置浏览器会提示需要使用外部浏览器打开才可以下载文件,而错误情况又于当前平台存在关联关系,又并且在外部浏览器中打开后日志文件就会丢失。。。

开发者工具中显示下载成功但是没有任何反应 / 安卓真机上提示需要在外部浏览器下载

查看文档后发现,在 DataHarborPlugin 中提供了一个 onDownload 参数,提供的入参就是客户端缓存的日志数据。

客户端可以使用传入的数据生成 Blob 文件,将文件通过接口上传给服务端。

经测试,如果将数据以 application/json 直接 POST 上传在网页中导入数据后会提示 JSON 解析失败。在客户端创建文件通过 FormData 上传即可正常解析。

typescript 复制代码
// 客户端
PageSpy.registerPlugin(
  new DataHarborPlugin({
    onDownload: async (data) => {
      const id = UUIDv4();

      const blob = new Blob([JSON.stringify(data)], {
        type: "application/json",
      });

      const formData = new FormData();
      formData.append("file", blob, `${id}.json`);

      await fetch("https://pagespy.example.com", {
        method: "POST",
        body: formData,
      }).then((res) => {
        if (res.ok) {
          alert(`日志已自动上报至服务器,请向开发提供错误 ID: ${id}`);
        } else {
          alert("日志上报错误,请重试");
        }
      });
    },
  }),
);
typescript 复制代码
// 服务端
const express = require('express');
const multer = require('multer');
const path = require('path');
const fs = require('fs');

const app = express();
const port = 6753;

// 设置 CORS 头部,允许所有来源的请求
app.use((req, res, next) => {
  res.header('Access-Control-Allow-Origin', '*');
  res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');
  next();
});

// 配置 Multer 存储的目录和文件名
const storage = multer.diskStorage({
  destination: function (req, file, cb) {
    cb(null, 'data/');
  },
  filename: function (req, file, cb) {
    cb(null, file.originalname);
  }
});

const upload = multer({ storage: storage });

// POST 接口 /pagespy,处理文件上传
app.post('/pagespy', upload.single('file'), (req, res) => {
  if (req.file) {
    res.json({ message: 'File uploaded successfully', filename: req.file.originalname });
  } else {
    res.status(400).json({ error: 'No file uploaded' });
  }
});

app.listen(port, () => {
  console.log(`Server is running on http://localhost:${port}`);
});                              

之后的操作感觉就比较行了,测试可以告知开发错误 ID,开发在服务器上将日志文件下载回来回放即可。

相关推荐
小杨同学494 分钟前
C 语言实战:动态规划求解最长公共子串(连续),附完整实现与优化
后端
Cache技术分享6 分钟前
290. Java Stream API - 从文本文件的行创建 Stream
前端·后端
用户948357016516 分钟前
拒绝 try-catch:如何设计全局通用的异常拦截体系?
后端
陈_杨8 分钟前
前端成功转鸿蒙开发者真实案例,教大家如何开发鸿蒙APP--ArkTS 卡片开发完全指南
前端·harmonyos
golang学习记9 分钟前
Go 1.22 隐藏彩蛋:cmp.Or —— 让“默认值”写起来像呼吸一样自然!
后端
阿里巴巴P8高级架构师10 分钟前
从0到1:用 Spring Boot 4 + Java 21 打造一个智能AI面试官平台
java·后端
桦说编程13 分钟前
并发编程踩坑实录:这些原则,帮你少走80%的弯路
java·后端·性能优化
小杨同学4914 分钟前
C 语言实战:枚举类型实现数字转星期(输入 1~7 对应星期几)
前端·后端
用户83071968408214 分钟前
Shiro登录验证与鉴权核心流程详解
spring boot·后端
码头整点薯条15 分钟前
基于Java实现的简易规则引擎(日常开发难点记录)
java·后端