All files / core errorId.ts

54.9% Statements 28/51
35% Branches 7/20
50% Functions 4/8
55.1% Lines 27/49

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 1072x   2x         2x   10x 10x   4x 4x               6x 6x               10x 10x 3x   7x 2x   5x     7x                                                                                         2x 17x           2x 11x       10x 10x 10x 504x 504x 504x   10x    
import { ERRORTYPES, EVENTTYPES } from '../common/common'
import { ReportDataType } from '../types/transportData'
const allErrorNumber: unknown = {}
/**
 * error合并规则
 * @param data
 */
export default function createErrorId(data: ReportDataType): number | null {
  let id: any
  const originUrl = getRealPageOrigin(data.url)
  switch (data.type) {
    case ERRORTYPES.FETCH_ERROR:
      id = data.type + data.request.method + data.response.status + getRealPath(data.request.url) + originUrl
      break
    case ERRORTYPES.JAVASCRIPT_ERROR:
    case ERRORTYPES.VUE_ERROR:
    case ERRORTYPES.REACT_ERROR:
      id = data.type + data.name + data.message + originUrl
      break
    case ERRORTYPES.BUSINESS_ERROR:
    case ERRORTYPES.LOG_ERROR:
      id = data.customTag + data.type + data.name + originUrl
      break
    case ERRORTYPES.PROMISE_ERROR:
      id = generatePromiseErrorId(data, originUrl)
      break
    default:
      id = data.type + data.message + originUrl
      break
  }
  id = hashCode(id)
  if (allErrorNumber[id] > 1) {
    return null
  }
  if (typeof allErrorNumber[id] === 'number') {
    allErrorNumber[id]++
  } else {
    allErrorNumber[id] = 1
  }
 
  return id
}
 
function generatePromiseErrorId(data: ReportDataType, originUrl: string) {
  const locationUrl = getRealPath(data.url)
  if (data.name === EVENTTYPES.UNHANDLEDREJECTION) {
    return data.type + objectOrder(data.message) + originUrl
  }
  return data.type + data.name + objectOrder(data.message) + locationUrl
}
 
/**
 * 排序对象键值对
 * ../param reason promise.reject
 */
function objectOrder(reason: any) {
  const sortFn = (obj: any) => {
    return Object.keys(obj)
      .sort()
      .reduce((total, key) => {
        if (Object.prototype.toString.call(obj[key]) === '[object Object]') {
          total[key] = sortFn(obj[key])
        } else {
          total[key] = obj[key]
        }
        return total
      }, {})
  }
  try {
    if (/\{.*\}/.test(reason)) {
      let obj = JSON.parse(reason)
      obj = sortFn(obj)
      return JSON.stringify(obj)
    }
  } catch (error) {
    return reason
  }
}
 
/**
 * http://.../project?id=1#a => http://.../project
 * http://.../id/123=> http://.../id/{param}
 *
 * @param url
 */
export function getRealPath(url: string): string {
  return url.replace(/[\?#].*$/, '').replace(/\/\d+([\/]*$)/, '{param}$1')
}
/**
 * http://a.b.com/#/project?id=1 => a.b.com
 * @param url
 */
export function getRealPageOrigin(url: string): string {
  return getRealPath(url.replace(/(\S+)(\/#\/)(\S*)/, `$1`).replace(/(\S*)(\/\/)(\S+)/, '$3'))
}
 
function hashCode(str: string): number {
  let hash = 0
  Iif (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
}