@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>
145 lines (136 loc) • 3.78 kB
text/typescript
import { ReportDataType } from '@sdc-monitor/types'
import { BrowserEventTypes, ErrorTypes } from '@sdc-monitor/shared'
import { variableTypeDetection } from './is'
const allErrorNumber: unknown = {}
/**
* generate error unique Id
*
* @export
* @param {ReportDataType} data 上报的数据结构
* @param {string} apikey 项目的唯一key
* @param {number} maxDuplicateCount init配置项,最多可重复上报同一个错误的次数
* @return {*} {(number | null)}
*/
export function createErrorId(data: ReportDataType, apikey: string, maxDuplicateCount: number): number | null {
let id: any
switch (data.type) {
case ErrorTypes.HTTP:
id = data.type + data.request.method + data.response.status + getRealPath(data.request.url) + apikey
break
case ErrorTypes.JAVASCRIPT:
case ErrorTypes.VUE:
case ErrorTypes.REACT:
id = data.type + data.name + data.message + apikey
break
case ErrorTypes.LOG:
id = data.customTag + data.type + data.name + apikey
break
case ErrorTypes.PROMISE:
id = generatePromiseErrorId(data, apikey)
break
default:
id = data.type + data.message + apikey
break
}
id = hashCode(id)
if (allErrorNumber[id] >= maxDuplicateCount) {
return null
}
if (typeof allErrorNumber[id] === 'number') {
allErrorNumber[id]++
} else {
allErrorNumber[id] = 1
}
return id
}
/**
* 如果是UNHANDLEDREJECTION,则按照项目apikey来生成
* 如果是其他的,按照当前页面来生成
* @param data
* @param originUrl
*/
function generatePromiseErrorId(data: ReportDataType, apikey: string) {
const locationUrl = getRealPath(data.url)
if (data.name === BrowserEventTypes.UNHANDLEDREJECTION) {
return data.type + stringToObjAndOrder(data.message) + apikey
}
return data.type + data.name + stringToObjAndOrder(data.message) + locationUrl
}
export function sortObjByKey<T = object>(obj: T): T {
return Object.keys(obj)
.sort()
.reduce((total, key) => {
if (variableTypeDetection.isObject(obj[key])) {
total[key] = sortObjByKey(obj[key])
} else {
total[key] = obj[key]
}
return total
}, {}) as T
}
/**
* sort object keys
* ../param reason promise.reject
*/
export function stringToObjAndOrder(reason: string) {
try {
if (/\{.*\}/.test(reason)) {
let obj = JSON.parse(reason)
obj = sortObjByKey(obj)
return JSON.stringify(obj)
}
return reason
} catch (error) {
return reason
}
}
/**
*
* 获取去掉query后的地主
* @export
* @param {string} url 地址
* @return {*} {string}
* @example http://.../project?id=1#a => http://.../project http://.../id/123=> http://.../id/{param}
*/
export function getRealPath(url: string): string {
return url
.replace(/[?#].*$/, '')
.replace(/\/(\d+)\//g, '/{param}/$1')
.replace(/\/\d+([/]*$)/g, '/{param}$1')
}
/**
*
* @param url
*/
export function getFlutterRealOrigin(url: string): string {
// for apple
return removeHashPath(getFlutterRealPath(url))
}
/**
* 获取flutter的原始地址:每个用户的文件夹hash不同
* @param url
*/
export function getFlutterRealPath(url: string): string {
// for apple
return url.replace(/(\S+)(\/Documents\/)(\S*)/, `$3`)
}
export function removeHashPath(url: string): string {
return url.replace(/(\S+)(\/#\/)(\S*)/, `$1`)
}
/**
* 根据字符串生成hashcode
*
* @export
* @param {string} str
* @return {*} {number} 可为正数和负数
*/
export function hashCode(str: string): number {
let hash = 0
if (str.length == 0) return hash
for (let i = 0; i < str.length; i++) {
const char = str.charCodeAt(i)
hash = (hash << 5) - hash + char
hash = hash & hash
}
return hash
}