npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

se-data-monitor

v0.0.4

Published

监控前端的通信、错误、打印等行为,以及计算各类性能参数,包括 FMP、LCP、FP 等

Downloads

6

Readme

:star: 特性

在经过两年多的线上沉淀后,将监控代码重新用 TypeScript 编写,删除冗余逻辑,正式开源。

不过,我所处的线上场景可能无法覆盖到所有的情况,因此 shin-monitor 在各方面还有很大的提升空间。

  • 通过 JavaScript 采集监控数据和性能参数,并统一发送到后台,参考源码分析
  • 监控的异常包括运行时错误、Promise 错误、框架错误和资源错误
  • 对于白屏错误,借助 rrweb 库增加了录像回放功能,恢复案发现场
  • 监控的行为包括路由、打印、点击事件、异步通信等
  • 性能参数包括首屏、白屏、LCP、FMP、资源信息等
  • 在我的专栏中,详细记录了监控脚本的研发迭代过程

:smiley: 快速安装

常规安装

npm install shin-monitor

或使用 unpkg 提供的 CDN,shin-monitor 后跟的是版本号,可自行选择版本,建议使用最新版本。

若不填版本号会自动做 302 跳转,跳转至最新版本。

<script src="https://unpkg.com/[email protected]/dist/shin.umd.js"></script>

:open_file_folder: 目录介绍

├── dist            编译代码
├── config          配置目录
├── demo            示例目录
├── src             源码目录
├── test            单元测试
├── CHANGELOG.md    变更日志
└── TODO.md         计划功能

1)dist

dist 是运行编译命令后的输出代码,不会提交到版本中。

$ npm run build

本项目使用的模块打包工具是 rollup,而不是 webpack

rollup 的配置文件存在于 config 目录中。

2)config

在 config 目录中,有多个配置文件,支持 CommonJS、ESM 和 UMD 模块规范。

const shin = require('shin-monitor');
import shin from 'shin-monitor';

推荐的引入方式是 UMD,不过在实际使用中,可以将 index.umd.js 上传至自己公司的静态资源服务器中。

<script src="node_modules/shin-monitor/dist/index.umd.js"></script>

在上传后,可以改名,例如叫 shin.js。

注意,shin.js 需要放置在最顶部,但是在 flexible.js 这些移动端屏幕适配脚本之后。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <script src="//pwstrick.com/js/xx.flexible.js"></script>
  <script src="//pwstrick.com/js/shin.js"></script>
</head>
</html>

3)demo

在 demo 目录中,保存着多个使用示例,但是若要访问,推荐安装 http-server

运行命令后,就能在本地搭建服务器。

$ http-server ./shin-monitor/

在浏览器地址栏中,输入 http://localhost:8080/demo/xxx.html 就能访问指定的示例了。

像监控通信,是必须要有服务器的,否则将无法访问。

4)test

在 test 目录中,保存着单元测试代码,运行命令后,就能开启。

$ npm run test

不过目前的测试用例还不够完善。测试框架使用的是 mocha.js,断言使用的是 expect.js

:rocket: 使用指南

在正确引入 shin-monitor 之后,就需要调用 setParams() 方法,将必要的参数传入后,就可以开始监控了。

shin.setParams({
  token: "pwstrick",
  src: "//pwstrick.com/ma.gif",
  psrc: "//pwstrick.com/pe.gif",
  pkey: "7c891ae43d330f73"
});

上述 4 个参数是必传的,具体的作用,可以参考下文说明。

1)参数详解

为了能更灵活的配置监控,提供了多个参数。

  • src:必填项,采集监控数据的后台接收地址,默认是 //127.0.0.1:3000/ma.gif
  • psrc:必填项,采集性能参数的后台接收地址,默认是 //127.0.0.1:3000/pe.gif
  • token:必填项,项目标识符,可自定义,用于区分监控的不同项目
  • pkey:必填项,性能监控的项目 key,一个项目下面可能有多个不同的子项目,这样就能单独监控子项目的性能
  • subdir:一个项目下的子目录,用于拼接 source map 的脚本地址
  • rate:随机采样率,用于性能搜集,默认值是 5,范围在 1~10 之间,10 表示百分百发送
  • version:版本,便于追查出错源
  • author:页面维护人员,便于追踪错源出自谁的手
  • record:录像配置
    • isOpen:是否开启录像,默认是 true
    • isSendInPerformance:是否将性能监控的录像发送到服务器,默认是 false
    • src:rrweb 地址,默认是官方提供的 CDN 地址 //cdn.jsdelivr.net/npm/rrweb@latest/dist/rrweb.min.js
  • error:错误配置
    • isFilterErrorFunc:需要过滤的脚本错误,默认是 null,可设置一个函数,参考 demo/error.html
    • isFilterPromiseFunc:需要过滤的 Promise 错误,默认是 null,可设置一个函数,参考 demo/error.html
shin.setParams({
  error: {
    /**
     * 过滤掉与业务无关或无意义的错误
     */
    isFilterErrorFunc: (event) =>   // (event: ErrorEvent) => boolean
        event.message === "Script error.", 
    isFilterPromiseFunc: (desc) =>  // (desc: TypeAjaxDesc) => boolean
        desc.status == 401 || desc.url.indexOf("reports/ai/logs") >= 0
  }
});
  • console: console 配置
    • isOpen: 是否开启,默认是 true,在本地调试时,可以将其关闭
    • isFilterLogFunc: 过滤要打印的内容,默认是 null,可设置一个函数,参考 demo/console.html
shin.setParams({
  console: {
    isFilterLogFunc: (desc) =>     // (desc: string) => boolean
        desc && desc.indexOf("Agora-SDK") >= 0
  }
});
  • crash:页面白屏配置
    • isOpen: 是否监控页面奔溃,默认是 true
    • validateFunc: 自定义页面白屏的判断条件,默认是 null,可设置一个函数,参考 demo/crash.html
shin.setParams({
  validateCrash: () => {    // () => TypeCrashResult
    /**
     * 当root标签中的内容为空时,可认为页面已奔溃
     * 响应值格式:{success: true, prompt:'提示'}
     */
    return {
      success: document.getElementById("root").innerHTML.length > 0,
      prompt: "页面出现空白"
    };
  }
});
  • event: 事件配置
    • isFilterClickFunc: 在点击事件中需要过滤的元素,默认是 null,可设置一个函数,参考 demo/event.html
shin.setParams({
  event: {
    isFilterFunc: (node) => {    // (element: HTMLElement) => boolean
      const nodeName = node.nodeName.toLowerCase();
      return nodeName !== 'a' && nodeName !== 'button' && nodeName !== 'li';
    }
  }
});
  • ajax:异步 Ajax 配置
    • isFilterSendFunc: 在发送监控日志时需要过滤的通信,默认是 null,可设置一个函数,参考 demo/ajax.html
shin.setParams({
  ajax: {
    isFilterSendFunc: (req) => {    // (req: TypeAjaxRequest) => boolean
      return req.status >= 500 || req.ajax.url === '/user';
    }
  }
});
  • identity:身份信息配置
    • value: 自定义的身份信息字段
    • getFunc: 自定义的身份信息获取函数,默认是 null,可设置一个函数,参考 demo/identity.html
shin.setParams({
  ajax: {
    getFunc: (params) => {    // (params: TypeShinParams) => void
      params.identity.value = 'test';
    }
  }
});

2)特殊属性

在调用 setParams() 方法后,自动会在 shin 对象中增加 reactError() 和 vueError()。

可在 React 项目中创建一个 ErrorBoundary 类,手动调用 reactError() 方法,下面是 reactError() 的源码。

public reactError(err: any, info: any): void {
  this.handleError({
    type: CONSTANT.ERROR_REACT,
    desc: {
      prompt: err.toString(),
      url: location.href
    },
    stack: info.componentStack,
  });
}

如果要对 Vue 进行错误捕获,那么就得重写 Vue.config.errorHandler(),其参数就是 Vue 对象,下面是 vueError() 的源码。

public vueError (vue: any): void {
  const _vueConfigErrorHandler = vue.config.errorHandler;
  vue.config.errorHandler =  (err: any, vm: any, info: any): void => {
    this.handleError({
      type: CONSTANT.ERROR_VUE,
      desc: {
        prompt: err.toString(), // 描述
        url: location.href
      },
      stack: err.stack,         // 堆栈
    });
    // 控制台打印错误
    if (typeof console !== 'undefined' && typeof console.error !== 'undefined') {
      console.error(err);
    }
    // 执行原始的错误处理程序
    if (typeof _vueConfigErrorHandler === 'function') {
      _vueConfigErrorHandler.call(err, vm, info);
    }
  };
}

3)性能参数

在提交到后台之前,脚本会对搜集到的性能参数进行计算,计算后取整或保留 1 位小数,单位都为毫秒(ms)。

  • loadTime:页面加载总时间,有可能为0,未触发load事件
  • unloadEventTime:Unload 事件耗时
  • loadEventTime:执行 onload 回调函数的时间
  • interactiveTime:首次可交互时间
  • domReadyTime:用户可操作时间(DOM Ready时间)
    • 在初始 HTML 文档已完全加载和解析时触发,无需等待图像和 iframe 完成加载
  • firstPaint:首次渲染的时间,即白屏时间(FP)
  • firstPaintStart:记录 FP 时间点
  • firstContentfulPaint:首次有实际内容渲染的时间(FCP)
  • firstContentfulPaintStart:记录 FCP 时间点
  • parseDomTime:解析 DOM 树的时间,DOM 中的所有脚本
    • 包括具有 async 属性的脚本,都已执行。并且加载 DOM 中定义的所有页面静态资源(图像、iframe 等)
  • initDomTreeTime:请求完毕至 DOM 加载的耗时,在加载 DOM 并执行网页的阻塞脚本时触发
  • readyStart:准备新页面的耗时
  • redirectCount:重定向次数
  • compression:传输内容压缩百分比
  • redirectTime:重定向的时间
    • 拒绝重定向,例如 https://pwstrick.com 就不该写成 http://pwstrick.com
  • appcacheTime:DNS 缓存耗时
  • lookupDomainTime:DNS 查询耗时
  • connectSslTime:SSL 连接耗时
  • connectTime:TCP 连接耗时
  • requestTime:内容加载完成的时间
  • requestDocumentTime:请求文档,开始请求文档到开始接收文档之间的耗时
  • responseDocumentTime:接收文档(内容传输),开始接收文档到文档接收完成之间的耗时
  • TTFB:读取页面第一个字节的时间,包含重定向时间
  • firstScreen:首屏时间,取 LCP、FMP 和 domReadyTime 之间的最大值
  • maxDOMTreeDepth:DOM 节点的最大深度
  • maxChildrenCount:DOM 节点的最大子节点数
  • totalElementCount:DOM 的总节点数
  • timing:原始性能参数
    • 通过 performance.getEntriesByType('navigation')[0]performance.timing 得到的性能参数
    • fid:用户第一次与页面交互到浏览器对交互作出响应的时间
    • fmp:首次有效绘制时间,即首屏最有意义的内容的渲染时间
      • time:时间
      • element:字符串形式的最有意义的元素
    • lcp:最大内容在可视区域内变得可见的时间
      • time:时间
      • url:资源地址
      • element:字符串形式的最大内容的元素
  • resource:静态资源的性能参数列表,只存储 1 分钟内的资源
    • name:资源名称
    • duration:资源接收的耗时,responseEnd 和 startTime 之间的差值
    • startTime:开始获取该资源的时间

:open_book: 源码修改

在将代码下载下来后,首次运行需要先安装依赖。

$ npm install

一键打包生成 4 个脚本,3 种规范和 1 个 UMD 的压缩版本。

$ npm run build

还有个 build-custom 命令,可以基于 shin-monitor 生成自定义逻辑的 UMD 脚本。

$ npm run build-custom

不过运行上述命令之前,要先在 src 目录中创建 index-custom.ts,那些自定义逻辑可以在该文件中编辑。

注意,此文件已被版本忽略。

:wrench: 可视化监控系统

本项目只给出了前端监控的 SDK,监控系统的管理界面可参考 shin-admin,后台服务可参考 shin-server

下面列出的是几张我自己制作的监控系统的界面示例图。