tracker统一方案

202 阅读5分钟

1. 背景

业务发展到一定阶段,我们需要一个埋点监控SDK去做数据的收集,后续再统计分析。有了分析数据,才能有针对性对网站进行优化。 对于前端来说,考虑到埋点逻辑和业务逻辑解耦,并且统一上报。

2. 监控场景

2.1 用户行为监控

负责统计PV(页面访问次数)、UV(页面访问人数)以及用户的点击操作等行为。

2.2 页面性能监控

用户的环境和我们不一样,也许是3G网,也许是很老的机型,我们需要知道在实际使用场景中的性能数据,比如页面加载时间、白屏时间等。

2.3 错误监控

对页面错误error,白屏等场景进行监控。

3. 埋点方式

3.1 手动埋点

手动埋点,顾名思义,在需要上报的地方主动编写相应的上报代码。

3.1.1 手动调用

3.1.2 自定义类指令式埋点实现

该方式适合简单的埋点上报,埋点逻辑与业务逻辑清晰分离,埋点 sdk 给 document 对象加上监听 click / hover 事件触发时,从当前触发事件的 target 逐级向上遍历,查看是否有对应此事件的指令。如果有,则上报此埋点事件,直至遇到一个没有事件指令的元素节点。这样也可以在指令中控制是否要继续向上遍历。

// 类指令式埋点实现逐级上报
<section data-tracking="100023">
  <div data-tracking="100008">
    <Button>点击</Button>
  </div>
</section>

但是如果我们需要在上报事件前,对所上报的数据进行处理,那么这种方式就无法满足了。需要手动调用。

3.2 全埋点

全埋点,对应用中的行为进行无差别的记录上报。

4. 实现分析

4.1 实现流程

image.png

image.png 埋点主要就是两个步骤:

  1. 数据收集
  2. 数据上报

4.2 数据收集

image.png

4.3 数据上报

4.3.1 数据格式

export type ActionData = {
  type: 'click' | 'pageload''mouseover'; // 事件类型
	page_url: string; // 页面地址
	title: string; // 页面名称 例如:"首页 - 车队平台"
	opts: {
    [key: string]: any
  }
	event_id?: string; // 事件Id projectId+eventTypeId+pageId+locationId 例如'1010101'
	event_desc?: string; // 事件描述 例如:"webConvoy-businessOrder-search-click"
	btn_name?: string; // 按钮名称
};

export type ErrorData = {
  type: 'jsError' | 'networkError'; // 错误类型
  pageUrl: string; // 页面地址
	message: string; // 错误描述
	stack: any: // 错误堆栈
  position: string;// 错误位置 ${e.lineno}:${e.colno}
	opts: {
    [key: string]: any
  }
}

// 设备信息
export type DimData = {
  os_name: string; //系统类型
	os_version: string; //系统版本
	browser_name: string; // 浏览器名称
	browser_version: string; // 浏览器版本
	memory: number; // 内存大小
}

type TrackData = {
  app_id: string;      // 项目唯一标识
  version: string;    // 版本
  time: string;       // 事件发生的时间 2023-09-26 15:25:23
	tenant_id: number; 	// 租户id
	use_name: string; // 用户
	scene: 'action' | 'error' | 'performance';
	dim: DimData; 
  data: ActionData | ErrorData 
};
4.1.1.1 公共参数
key类型描述
scene'Action' | 'Error' | 'Performance'业务场景
app_idstring项目唯一标识,例如 车队: web-convoy
use_namestring用户名,登录之后从localStorage获取
timestring事件发生时间, 2023-09-26 15:25:23
tenant_idnumber租户id, 登录之后从localStorage获取
versionstring字段更新版本
dataany不同类型的自定义数据
dimDimData 见4.3.1图设备信息
4.1.1.2 业务场景(data里的具体信息)
4.1.1.2.1 用户行为-action

用户行为这一类型,收集的主要是以下方面:

  1. who 什么地方
  2. time 什么时间
  3. where 什么地方
  4. what 做了什么、
key类型描述
type'click' | 'pageload' | 'hover' | 'scroll';事件类型
event_idstring事件Id:
projectId(01开头) + pageId(二级路由01开头)+ pointId(元素id 00开头)+ typeId(type的枚举索引 01开头)
page_urlstring页面地址
event_descstring描述被点击的元素(webConvoy-orderEdit-submitButton/searchButton)
btn_namestring按钮名称
titlestring页面标题
opts{[key: string]: any}扩展参数

4.3.2 上报方式

数据上报也就是将数据发送给服务端,考虑到以下两个问题:

  1. 跨域
  2. 页面关闭时会中断正在发送的数据

选择使用图片或者navigator.sendBeacon来发送数据**。考虑到navigator.sendBeacon的浏览器支持程度,使用两者结合的方式(如果浏览器不支持sendBeancon,就使用图片的方式)。** **伪代码: **

function send(data) {
  const url = `xxxx`
  if (navigator.sendBeacon) {
    navigator.sendBeacon(url, JSON.stringify(data));
  } else {
    const imgReq = new Image();
    imgReq.src = `${url}?params=${JSON.stringify(
      data
    )}&t=${new Date().getTime()}`;
  }
}

综上,考虑到接入阿里云sls, 本期通过WebTracking的方式上传数据。 接入文档参考:help.aliyun.com/zh/sls/user…

import SlsTracker from '@aliyun-sls/web-track-browser'

const opts = {
  host: 'cn-shenzhen.log.aliyuncs.com', // 所在地域的服务入口。例如cn-hangzhou.log.aliyuncs.com
  project: 'falcon-bs-daily', // Project名称。
  logstore: 'falcon-base-web-event', // Logstore名称。
  time: 10, // 发送日志的时间间隔,默认是10秒。
  count: 10, // 发送日志的数量大小,默认是10条。
  topic: 'topic',// 自定义日志主题。
  source: 'source',
  tags: {
    tags: 'tags',
  },
}
const tracker = new SlsTracker(opts);


// 测试埋点
const sendLog = () => {
  tracker.send({
    customer: 'zhangsan',
    product: 'iphone 12',
    price: 7998,
  })
}

5. 字段详解

5.1 eventId

事件id通过projectId + pageId + pointId + typeId获取

5.1.1 事件类型-typeId

事件类型id映射表:

id含义描述
01click点击
02pageload页面显示
03hover鼠标移入

5.1.2 项目 - projectId

项目id映射表:

id含义描述
01webConvoy车队web端
02webAgent货代web端
03freight-cp网络货运货主端

5.1.3 页面 - pageId

以车队为例:精确到二级页面

id含义描述
01businessOrder业务/业务订单
02financeOverview财务/收付总览
.........

5.1.4 点位 - pointId

具体页面的点位,以车队业务订单为例:

id含义描述
01editOrder编辑订单
02editFare编辑费用
03addOrder新增订单
04search查询
05reset重置
.........