@sdc-monitor/demo
Version:
<div align="center"> <a href="#" target="_blank"> <img src="https://i.loli.net/2021/07/28/EvPwd4NjVH3tBfO.jpg" alt="mito-logo" height="90"> </a> <p>A Lightweight SDK For Monitor Web</p>
195 lines (171 loc) • 6.44 kB
text/typescript
import { noop, getPageUrl, getDeviceId } from '../utils'
import { generateUUID, toStringValidateOption } from '@sdc-monitor/utils'
import { WxPerformanceDataType, WxPerformanceItemType } from '../constant'
import Event from './event'
import {
WxPerformanceData,
WxPerformanceAnyObj,
WxPerformanceInitOptions,
WxNetworkType,
WxPerformanceItem,
WxPerformanceEntryObj
} from '../types/index'
import { ToStringTypes } from '@sdc-monitor/shared'
class Store extends Event {
appId: string
report: (data: Array<WxPerformanceData>) => void
immediately?: boolean
ignoreUrl?: RegExp
maxBreadcrumbs?: number
private stack: Array<WxPerformanceData>
// wx
getBatteryInfo: () => WechatMiniprogram.GetBatteryInfoSyncResult
getNetworkType: <T extends WechatMiniprogram.GetNetworkTypeOption = WechatMiniprogram.GetNetworkTypeOption>(
option?: T
) => WechatMiniprogram.PromisifySuccessResult<T, WechatMiniprogram.GetNetworkTypeOption>
systemInfo: WechatMiniprogram.SystemInfo
// 小程序launch时间
wxLaunchTime: number
// 首次点击标志位
private firstAction = false
// 路由跳转start时间记录
private navigationMap: WxPerformanceAnyObj = {}
constructor(options: WxPerformanceInitOptions) {
super()
const { appId, report, maxBreadcrumbs, immediately, ignoreUrl } = options
toStringValidateOption(appId, 'appId', ToStringTypes.String) && (this.appId = appId)
toStringValidateOption(maxBreadcrumbs, 'maxBreadcrumbs', ToStringTypes.Number) && (this.maxBreadcrumbs = maxBreadcrumbs)
toStringValidateOption(ignoreUrl, 'ignoreUrl', ToStringTypes.RegExp) && (this.ignoreUrl = ignoreUrl)
toStringValidateOption(immediately, 'immediately', ToStringTypes.Boolean) && (this.immediately = immediately)
this.report = toStringValidateOption(report, 'report', ToStringTypes.Function) ? report : noop
this.stack = []
}
// eslint-disable-next-line @typescript-eslint/require-await
async _pushData(data: Array<WxPerformanceData>) {
if (this.immediately) {
this.report(data)
return
}
this.stack = this.stack.concat(data)
if (this.stack.length >= this.maxBreadcrumbs) {
this.reportLeftData()
}
}
// eslint-disable-next-line @typescript-eslint/require-await
async reportLeftData() {
this.report([...this.stack])
this.stack = []
}
_getSystemInfo(): WechatMiniprogram.SystemInfo {
!this.systemInfo && (this.systemInfo = wx.getSystemInfoSync())
return this.systemInfo
}
async _getNetworkType(): Promise<WxNetworkType> {
let nk = { networkType: 'none', errMsg: '' } as WechatMiniprogram.GetNetworkTypeSuccessCallbackResult
try {
nk = await this.getNetworkType()
} catch (err) {
console.warn(`getNetworkType err = `, err)
}
return nk.networkType
}
async _createPerformanceData(type: WxPerformanceDataType, item: Array<WxPerformanceItem>): Promise<WxPerformanceData> {
const networkType = await this._getNetworkType()
const date = new Date()
return {
appId: this.appId,
timestamp: date.getTime(),
time: date.toLocaleString(),
uuid: generateUUID(),
deviceId: getDeviceId(),
networkType: networkType,
batteryLevel: this.getBatteryInfo().level,
systemInfo: this._getSystemInfo(),
wxLaunch: this.wxLaunchTime,
page: getPageUrl(),
type: type,
item: item
}
}
push(type: WxPerformanceDataType, data: WxPerformanceItem | Array<WxPerformanceItem>) {
switch (type) {
case WxPerformanceDataType.WX_LIFE_STYLE:
case WxPerformanceDataType.WX_NETWORK:
this.simpleHandle(type, data as WxPerformanceItem)
break
case WxPerformanceDataType.MEMORY_WARNING:
this.handleMemoryWarning(data as WechatMiniprogram.OnMemoryWarningCallbackResult)
break
case WxPerformanceDataType.WX_PERFORMANCE:
this.handleWxPerformance(data as Array<WxPerformanceItem>)
break
case WxPerformanceDataType.WX_USER_ACTION:
this.handleWxAction(data as WxPerformanceItem)
// eslint-disable-next-line no-fallthrough
default:
break
}
}
async simpleHandle(type: WxPerformanceDataType, data: WxPerformanceItem) {
const d = await this._createPerformanceData(type as WxPerformanceDataType, [data])
this._pushData([d])
}
// 内存警告会立即上报
async handleMemoryWarning(data: WechatMiniprogram.OnMemoryWarningCallbackResult) {
const d = await this._createPerformanceData(WxPerformanceDataType.MEMORY_WARNING, [
{ ...data, itemType: WxPerformanceItemType.MemoryWarning, timestamp: Date.now() }
])
this.report([d])
}
buildNavigationStart(entry: WxPerformanceEntryObj) {
if (entry.entryType === 'navigation') {
// appLaunch时没有navigationStart
this.navigationMap[entry.path] = entry.navigationStart || entry.startTime
}
}
async handleWxPerformance(data: Array<WxPerformanceItem> = []) {
const _data: Array<WxPerformanceItem> = data.map((d) => {
this.buildNavigationStart(d)
d.itemType = WxPerformanceItemType.Performance
d.timestamp = Date.now()
return d
})
const item = await this._createPerformanceData(WxPerformanceDataType.WX_PERFORMANCE, _data)
this._pushData([item])
}
// 只统计首次点击
async handleWxAction(data: WxPerformanceItem) {
if (!this.firstAction) {
const d = await this._createPerformanceData(WxPerformanceDataType.WX_USER_ACTION, [data])
this._pushData([d])
this.firstAction = true
}
}
setLaunchTime(now: number) {
this.wxLaunchTime = now
}
filterUrl(url: string) {
if (this.ignoreUrl && this.ignoreUrl.test(url)) return true
return false
}
customPaint() {
const now = Date.now()
const path = getPageUrl(false)
// eslint-disable-next-line @typescript-eslint/no-misused-promises
setTimeout(async () => {
if (path && this.navigationMap[path]) {
const navigationStart = this.navigationMap[path]
const data = await this._createPerformanceData(WxPerformanceDataType.WX_LIFE_STYLE, [
{
itemType: WxPerformanceItemType.WxCustomPaint,
navigationStart: navigationStart,
timestamp: now,
duration: now - navigationStart
}
])
this._pushData([data])
}
}, 1000)
}
}
export default Store