前端异常解析

目录

引子

前端异常示例里面观察了各类异常的示例,按照区分判断的思路 3 ,看下该如何解析异常信息。主要还是 SentryTraceKit 里面部分处理逻辑。

@sentry/browser 版本 : 5.9.1 。 TraceKit 版本: 0.4.6 。

TraceKit 解析

TraceKit 对于 JavaScript 定义的 Error 中几种类型有比较好的处理,对异常相关信息进行再解析格式化。具体可见 Read TraceKit

Sentry 解析

Sentry 中在之前提过区分的逻辑上,提供了对应的几种处理方法:

// 非完整源码,主要为了体现思路
let event
if (isErrorEvent(exception) && exception.error) {
  event = eventFromStacktrace(computeStackTrace(exception));
  return event;
}

if (isDOMError(exception) || isDOMException(exception)) {
  event = eventFromString(exception);
  return event;
}

// isError 包含的类型有 [object Error] [object Exception] [object DOMException] ,以及继承自 Error 对象的自定义对象。
if (isError(exception)) {
  event = eventFromStacktrace(computeStackTrace(exception));
  return event;
}

// isPlainObject 检查类型是 [object Object],isEvent检查的是 wat instanceof Event
if (isPlainObject(exception) || isEvent(exception)) {
  event = eventFromPlainObject(exception);
  return event;
}

event = eventFromString(exception);

return event;

其中 computeStackTrace(ex) 方法是基于 TraceKit 中的处理方法进行一些改造。

下面对处理的方法进一步的了解。

eventFromStacktrace

export function eventFromStacktrace(stacktrace: TraceKitStackTrace): Event {
  const exception = exceptionFromStacktrace(stacktrace);

  return {
    exception: {
      values: [exception],
    },
  };
}

export function exceptionFromStacktrace(stacktrace: TraceKitStackTrace): Exception {
  const frames = prepareFramesForEvent(stacktrace.stack); // 该方法进行一些数据过滤

  const exception: Exception = {
    type: stacktrace.name,
    value: stacktrace.message,
  };

  if (frames && frames.length) {
    exception.stacktrace = { frames };
  }

  // tslint:disable-next-line:strict-type-predicates
  if (exception.type === undefined && exception.value === '') {
    exception.value = 'Unrecoverable error caught';
  }

  return exception;
}

该方法主要是对处理过后的异常信息,进行数据再次格式化,以及对一些情况的补充完善,例如 Unrecoverable error caught 。

最后产生的数据格式比较完整的是这样:

{
  type: '',
  value: '',
  stacktrace: {},
}

eventFromString

export function eventFromString(
  input: string,
  syntheticException?: Error,
  options: {
    attachStacktrace?: boolean;
  } = {},
): Event {
  const event: Event = {
    message: input,
  };

  //  这块逻辑跟自定义的异常有关,暂不讨论
  if (options.attachStacktrace && syntheticException) {
    const stacktrace = computeStackTrace(syntheticException);
    const frames = prepareFramesForEvent(stacktrace.stack);
    event.stacktrace = {
      frames,
    };
  }

  return event;
}

该方法主要对数据进行再组装格式化。

最后产生的数据格式比较完整的是这样:

{
  message: '',
  stacktrace: {},
}

eventFromPlainObject

export function eventFromPlainObject(exception: {}, syntheticException?: Error, rejection?: boolean): Event {
  const event: Event = {
    exception: {
      values: [
        {
          type: isEvent(exception) ? exception.constructor.name : rejection ? 'UnhandledRejection' : 'Error',
          value: `Non-Error ${
            rejection ? 'promise rejection' : 'exception'
          } captured with keys: ${extractExceptionKeysForMessage(exception)}`,
        },
      ],
    },
    extra: {
      __serialized__: normalizeToSize(exception),
    },
  };

  //  这块逻辑跟自定义的异常有关,暂不讨论
  if (syntheticException) {
    const stacktrace = computeStackTrace(syntheticException);
    const frames = prepareFramesForEvent(stacktrace.stack);
    event.stacktrace = {
      frames,
    };
  }

  return event;
}

该方法主要对数据进行再组装格式化。

最后产生的数据格式比较完整的是这样:

{
  values: [{}],
  extra: {},
  stacktrace: {},
}

小结

Sentry 相对于 TraceKit 提供了更多异常类型的处理,并且不同类型的异常可能会有单独的描述属性。如果需要根据自身的需求定制数据格式,建议基于 TraceKit 的处理结果再次处理。

参考资料

posted @ 2020-12-07 08:43  XXHolic  阅读(497)  评论(0编辑  收藏  举报