Skip to content
This repository has been archived by the owner on Jan 30, 2025. It is now read-only.

Commit

Permalink
Refactor onFrameNavigated tracing
Browse files Browse the repository at this point in the history
Reduces nested levels.
  • Loading branch information
ka3de committed Dec 4, 2023
1 parent 797a7c6 commit 6865873
Showing 1 changed file with 39 additions and 31 deletions.
70 changes: 39 additions & 31 deletions common/frame_session.go
Original file line number Diff line number Diff line change
Expand Up @@ -750,39 +750,47 @@ func (fs *FrameSession) onFrameNavigated(frame *cdp.Frame, initial bool) {

// Trace navigation only for the main frame.
// TODO: How will this affect sub frames such as iframes?
if isMainFrame := frame.ParentID == ""; isMainFrame {
_, fs.mainFrameSpan = TraceNavigation(
fs.ctx, fs.targetID.String(), frame.URL,
trace.WithAttributes(attribute.String("url", frame.URL)),
)

var (
spanID = fs.mainFrameSpan.SpanContext().SpanID().String()
newFrame = fs.manager.getFrameByID(frame.ID)
)
// Set k6SpanId property in the page so it can be retrieved when pushing
// the Web Vitals events from the page execution context and used to
// correlate them with the navigation span to which they belong to.
if newFrame != nil {
// Executing a CDP command in the event parsing goroutine might deadlock in some cases.
// For example a deadlock happens if the content loaded in the frame that has navigated
// includes a JavaScript initiated dialog which we have to explicitly accept or dismiss
// (see onEventJavascriptDialogOpening). In that case our EvaluateGlobal call can't be
// executed, as the browser is waiting for us to accept/dismiss the JS dialog, but we
// can't act on that because the event parsing goroutine is stuck in onFrameNavigated.
// Because in this case the action is to set an attribute to the global object (window)
// it should be safe to just execute this in a separate goroutine.
go func() {
js := fmt.Sprintf("window.k6SpanId = '%s';", spanID)
err := newFrame.EvaluateGlobal(fs.ctx, js)
if err != nil {
fs.logger.Errorf(
"FrameSession:onFrameNavigated", "error on evaluating window.k6SpanId: %v", err,
)
}
}()
if isMainFrame := frame.ParentID == ""; !isMainFrame {
return
}

_, fs.mainFrameSpan = TraceNavigation(
fs.ctx, fs.targetID.String(), frame.URL,
trace.WithAttributes(attribute.String("url", frame.URL)),
)

var (
spanID = fs.mainFrameSpan.SpanContext().SpanID().String()
newFrame = fs.manager.getFrameByID(frame.ID)
)

// Only set the k6SpanId reference if it's a new frame.
if newFrame == nil {
return
}

// Set k6SpanId property in the page so it can be retrieved when pushing
// the Web Vitals events from the page execution context and used to
// correlate them with the navigation span to which they belong to.
setSpanIDProp := func() {
js := fmt.Sprintf("window.k6SpanId = '%s';", spanID)
err := newFrame.EvaluateGlobal(fs.ctx, js)
if err != nil {
fs.logger.Errorf(
"FrameSession:onFrameNavigated", "error on evaluating window.k6SpanId: %v", err,
)
}
}

// Executing a CDP command in the event parsing goroutine might deadlock in some cases.
// For example a deadlock happens if the content loaded in the frame that has navigated
// includes a JavaScript initiated dialog which we have to explicitly accept or dismiss
// (see onEventJavascriptDialogOpening). In that case our EvaluateGlobal call can't be
// executed, as the browser is waiting for us to accept/dismiss the JS dialog, but we
// can't act on that because the event parsing goroutine is stuck in onFrameNavigated.
// Because in this case the action is to set an attribute to the global object (window)
// it should be safe to just execute this in a separate goroutine.
go setSpanIDProp()
}

func (fs *FrameSession) onFrameRequestedNavigation(event *cdppage.EventFrameRequestedNavigation) {
Expand Down

0 comments on commit 6865873

Please sign in to comment.