0

I have a long running app that I'd like to monitor in real time. HAR files allow me to do this after the fact, but as they are an "archive", they don't allow me to do this in real time.

Is their anyway to stream the "events" array of the HAR file so I can process them as they are generated?

This can be firefox or chrome.

spotter
  • 1,178
  • 1
  • 9
  • 19

1 Answers1

0

So with some help from https://github.com/mafredri/cdp/tree/master/example/screencast I figured out how to do this in go with chrome's debugger api

What this code doesn't do is tie the request body to the response (where it isn't available), but as I show the RequestID will be consistent so if one serializes event processing (say via locking) one can save the body and use it when the response event is seen.

package main

import (
    "context"
    "log"

    "github.com/mafredri/cdp"
    "github.com/mafredri/cdp/cdpcmd"
    "github.com/mafredri/cdp/devtool"
    "github.com/mafredri/cdp/rpcc"
)

func main() {
    if err := run(); err != nil {
        panic(err)
    }
}

func run() error {
    ctx, cancel := context.WithCancel(context.TODO())
    defer cancel()

    devt := devtool.New("http://localhost:9222")

    page, err := devt.Get(ctx, devtool.Page)
    if err != nil {
        return err
    }

    conn, err := rpcc.DialContext(ctx, page.WebSocketDebuggerURL)
    if err != nil {
        return err
    }
    defer conn.Close()

    c := cdp.NewClient(conn)

    err = c.Page.Enable(ctx)
    if err != nil {
        return err
    }

    loadEventFired, err := c.Page.LoadEventFired(ctx)
    if err != nil {
        return err
    }

    _, err = c.Page.Navigate(ctx, cdpcmd.NewPageNavigateArgs("https://github.com/"))
    if err != nil {
        return err
    }

    _, err = loadEventFired.Recv()
    if err != nil {
        return err
    }
    loadEventFired.Close()

    a := &cdpcmd.NetworkEnableArgs{}
    a.SetMaxResourceBufferSize(32000)
    a.SetMaxTotalBufferSize(96000)

    err = c.Network.Enable(ctx, a)

    responseEvents, err := c.Network.ResponseReceived(ctx)
    requestEvents, err := c.Network.RequestWillBeSent(ctx)

    go func() {
        defer responseEvents.Close()

        for {
            ev, err := responseEvents.Recv()
            if err != nil {
                log.Printf("Failed to receive network event: %v", err)
                return
            }
            log.Printf("requestid = %v, url = %v", ev.RequestID, ev.Response.URL)
        }
    }()

    go func() {
        defer requestEvents.Close()

        for {
            ev, err := requestEvents.Recv()
            if err != nil {
                log.Printf("Failed to receive network event: %v", err)
                return
            }
            log.Printf("requestid = %v, url = %v", ev.RequestID, ev.Request.URL)
        }
    }()

    select {}

    return nil
}
spotter
  • 1,178
  • 1
  • 9
  • 19