static processTrace()

in src/sdk/lh-trace-processor.ts [668:769]


  static processTrace(trace, options) {
    const { timeOriginDeterminationMethod = 'auto' } = options || {};

    // Parse the trace for our key events and sort them by timestamp. Note: sort
    // *must* be stable to keep events correctly nested.
    const keyEvents = this.filteredTraceSort(trace.traceEvents, e => {
      return (
        e.cat.includes('blink.user_timing') ||
        e.cat.includes('loading') ||
        e.cat.includes('devtools.timeline') ||
        e.cat === '__metadata'
      );
    });

    // Find the inspected frame
    const mainFrameIds = this.findMainFrameIds(keyEvents);

    const frames = keyEvents
      .filter(
        /** @return {evt is FrameCommittedEvent} */ evt => {
          return Boolean(
            evt.name === 'FrameCommittedInBrowser' &&
              evt.args.data &&
              evt.args.data.frame &&
              evt.args.data.url
          );
        }
      )
      .map(evt => {
        return {
          id: evt.args.data.frame,
          url: evt.args.data.url,
          parent: evt.args.data.parent,
        };
      });
    const frameIdToRootFrameId = this.resolveRootFrames(frames);

    // Filter to just events matching the main frame ID, just to make sure.
    const frameEvents = keyEvents.filter(
      e => e.args.frame === mainFrameIds.frameId
    );

    // Filter to just events matching the main frame ID or any child frame IDs.
    // In practice, there should always be FrameCommittedInBrowser events to define the frame tree.
    // Unfortunately, many test traces do not include FrameCommittedInBrowser events due to minification.
    // This ensures there is always a minimal frame tree and events so those tests don't fail.
    let frameTreeEvents = [];
    if (frameIdToRootFrameId.has(mainFrameIds.frameId)) {
      frameTreeEvents = keyEvents.filter(e => {
        return (
          e.args.frame &&
          frameIdToRootFrameId.get(e.args.frame) === mainFrameIds.frameId
        );
      });
    } else {
      log(
        'frameTreeEvents may be incomplete, make sure the trace has FrameCommittedInBrowser events'
      );
      frameIdToRootFrameId.set(mainFrameIds.frameId, mainFrameIds.frameId);
      frameTreeEvents = frameEvents;
    }

    // Compute our time origin to use for all relative timings.
    const timeOriginEvt = this.computeTimeOrigin(
      { keyEvents, frameEvents, mainFrameIds },
      timeOriginDeterminationMethod
    );

    // Subset all trace events to just our tab's process (incl threads other than main)
    // stable-sort events to keep them correctly nested.
    const processEvents = TraceProcessor.filteredTraceSort(
      trace.traceEvents,
      e => e.pid === mainFrameIds.pid
    );

    const mainThreadEvents = processEvents.filter(
      e => e.tid === mainFrameIds.tid
    );

    // Ensure our traceEnd reflects all page activity.
    const traceEnd = this.computeTraceEnd(trace.traceEvents, timeOriginEvt);

    // This could be much more concise with object spread, but the consensus is that explicitness is
    // preferred over brevity here.
    return {
      frames,
      mainThreadEvents,
      frameEvents,
      frameTreeEvents,
      processEvents,
      mainFrameIds,
      timeOriginEvt,
      timings: {
        timeOrigin: 0,
        traceEnd: traceEnd.timing,
      },
      timestamps: {
        timeOrigin: timeOriginEvt.ts,
        traceEnd: traceEnd.timestamp,
      },
    };
  }