ChromeDevTools / timeline-viewer

View DevTools Timeline trace files from Google Drive wicked easily
https://chromedevtools.github.io/timeline-viewer/
Other
323 stars 43 forks source link

Programmatically load local trace files #76

Open flekschas opened 4 years ago

flekschas commented 4 years ago

First of all, thanks for this awesome tool! 👏

I am wondering if it's possible to programmatically load local trace files with https://chromedevtools.github.io/timeline-viewer/

I've been experimenting with puppeteer to automate the drag-and-drop interaction but I can't get a file to load. I noticed that on the initial dragover event, the UI changes from #dropbox to the timeline widget. I also figured out how to retrieve the drop target element from https://github.com/ChromeDevTools/timeline-viewer/blob/f3e7ce081667e9607ac1d924ca876ab83b3bc9f6/docs/dev_tools.js#L154. Unfortunately, when I dispatch a dragenter, dragover, drop event on window.Timeline.TimelinePanel.instance()._dropTarget._element nothing happens.

With puppeteer, I am doing the following:

const fileInputIdentifier = 'some-unique-identifier';

await page.evaluate(() => {
  document.querySelector('#dropbox').dispatchEvent(new Event('dragover'));
});

await page.waitFor(2500);

await page.evaluate(
  id => {
    document.body.appendChild(
      Object.assign(document.createElement('input'), {
        id,
        type: 'file',
        onchange: async e => {
          ['dragenter', 'dragover', 'drop'].forEach(event => {
            window.Timeline.TimelinePanel.instance()._dropTarget._element.dispatchEvent(
              Object.assign(new Event(event), {
                dataTransfer: { files: e.target.files }
              })
            );
          });
        }
      })
    );
  },
  fileInputIdentifier
);

const fileInput = await page.$(`#${fileInputIdentifier}`);
await fileInput.uploadFile(filePath);
await fileInput.evaluate(upload =>
  upload.dispatchEvent(new Event('change', { bubbles: true }))
);

It appears as if the drop event is registered, but the file is not loaded due to the following error:

Uncaught TypeError: Cannot convert undefined or null to object
    at Function.from (<anonymous>)
    at UI.DropTarget._hasMatchingType (shell.js:1724)
    at UI.DropTarget._onDragEnter (shell.js:1722)
    at HTMLInputElement.onchange (VM49 __puppeteer_evaluation_script__:11)
    at VM46 __puppeteer_evaluation_script__:2

Maybe my approach is overkill or simply not feasible. Any idea? Thanks a lot :)

paulirish commented 4 years ago

interesting!

backing up.. what is the situation you have? (eg. you just traced a page with puppeteer and you have traces saved as files on disk. now you want to open a tab showing them)

flekschas commented 4 years ago

Yes exactly. To give you a little bit more context, I am using puppeteer to trace the performance of my web app during certain interactions. Now comes the slightly hacky part, I am loading the trace files with the timeline viewer to extract the recorded frame rate. Besides just extracting the framerate it's also nice to be able to immediately browse the trace for debugging. If there's was a way to automatically add a local trace file, I could get do both things at the same time: extract the frame rate and analyze why it improved or not.

paulirish commented 3 years ago

FYI i fixed the drag n drop back in June: https://github.com/ChromeDevTools/timeline-viewer/pull/77

paulirish commented 3 years ago

Given your attempt to synthesize a drop event (and that DnD is now fixed).... that could probably work.

The less-involved solutions of something like ?loadTimelineFromURL=file://localpath/timeline.json are challenges because of origin restrictions on file protocol... but if you have a local server that sets CORS headers.. that would would work. Lastly someone could explore the newer File System Access API and perhaps that'd make for a nice UX.