Skip to content

Commit

Permalink
Register custom k6 metrics on module init
Browse files Browse the repository at this point in the history
This is a fix for a breaking change introduced in k6 v0.38.0[1].

[1]: grafana/k6#2442
  • Loading branch information
Ivan Mirić committed May 5, 2022
1 parent 43ec8eb commit 5787918
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 20 deletions.
15 changes: 15 additions & 0 deletions common/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ const (
ctxKeyPid
ctxKeyHooks
ctxKeyVU
ctxKeyCustomK6Metrics
)

func WithHooks(ctx context.Context, hooks *Hooks) context.Context {
Expand Down Expand Up @@ -87,6 +88,20 @@ func GetVU(ctx context.Context) k6modules.VU {
return nil
}

// WithCustomK6Metrics attaches the CustomK6Metrics object to the context.
func WithCustomK6Metrics(ctx context.Context, k6m *CustomK6Metrics) context.Context {
return context.WithValue(ctx, ctxKeyCustomK6Metrics, k6m)
}

// GetCustomK6Metrics returns the CustomK6Metrics object attached to the context.
func GetCustomK6Metrics(ctx context.Context) *CustomK6Metrics {
v := ctx.Value(ctxKeyCustomK6Metrics)
if k6m, ok := v.(*CustomK6Metrics); ok {
return k6m
}
return nil
}

// contextWithDoneChan returns a new context that is canceled either
// when the done channel is closed or ctx is canceled.
func contextWithDoneChan(ctx context.Context, done chan struct{}) context.Context {
Expand Down
14 changes: 8 additions & 6 deletions common/frame_session.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ type FrameSession struct {
parent *FrameSession
manager *FrameManager
networkManager *NetworkManager
k6Metrics *CustomK6Metrics

targetID target.ID
windowID browser.WindowID
Expand Down Expand Up @@ -103,6 +104,7 @@ func NewFrameSession(
eventCh: make(chan Event),
childSessions: make(map[cdp.FrameID]*FrameSession),
vu: GetVU(ctx),
k6Metrics: GetCustomK6Metrics(ctx),
logger: l,
serializer: &logrus.Logger{
Out: l.log.Out,
Expand Down Expand Up @@ -714,12 +716,12 @@ func (fs *FrameSession) onPageLifecycle(event *cdppage.EventLifecycleEvent) {
fs.manager.frameLifecycleEvent(event.FrameID, LifecycleEventDOMContentLoad)
}

eventToMetric := map[string]*k6stats.Metric{
"load": BrowserLoaded,
"DOMContentLoaded": BrowserDOMContentLoaded,
"firstPaint": BrowserFirstPaint,
"firstContentfulPaint": BrowserFirstContentfulPaint,
"firstMeaningfulPaint": BrowserFirstMeaningfulPaint,
eventToMetric := map[string]*k6metrics.Metric{
"load": fs.k6Metrics.BrowserLoaded,
"DOMContentLoaded": fs.k6Metrics.BrowserDOMContentLoaded,
"firstPaint": fs.k6Metrics.BrowserFirstPaint,
"firstContentfulPaint": fs.k6Metrics.BrowserFirstContentfulPaint,
"firstMeaningfulPaint": fs.k6Metrics.BrowserFirstMeaningfulPaint,
}

if m, ok := eventToMetric[event.Name]; ok {
Expand Down
34 changes: 26 additions & 8 deletions common/metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,30 @@

package common

import k6stats "go.k6.io/k6/stats"
import k6metrics "go.k6.io/k6/metrics"

var (
BrowserDOMContentLoaded = k6stats.New("browser_dom_content_loaded", k6stats.Trend, k6stats.Time)
BrowserFirstPaint = k6stats.New("browser_first_paint", k6stats.Trend, k6stats.Time)
BrowserFirstContentfulPaint = k6stats.New("browser_first_contentful_paint", k6stats.Trend, k6stats.Time)
BrowserFirstMeaningfulPaint = k6stats.New("browser_first_meaningful_paint", k6stats.Trend, k6stats.Time)
BrowserLoaded = k6stats.New("browser_loaded", k6stats.Trend, k6stats.Time)
)
// CustomK6Metrics are the custom k6 metrics used by xk6-browser.
type CustomK6Metrics struct {
BrowserDOMContentLoaded *k6metrics.Metric
BrowserFirstPaint *k6metrics.Metric
BrowserFirstContentfulPaint *k6metrics.Metric
BrowserFirstMeaningfulPaint *k6metrics.Metric
BrowserLoaded *k6metrics.Metric
}

// RegisterCustomK6Metrics creates and registers our custom metrics with the k6
// VU Registry and returns our internal struct pointer.
func RegisterCustomK6Metrics(registry *k6metrics.Registry) *CustomK6Metrics {
return &CustomK6Metrics{
BrowserDOMContentLoaded: registry.MustNewMetric(
"browser_dom_content_loaded", k6metrics.Trend, k6metrics.Time),
BrowserFirstPaint: registry.MustNewMetric(
"browser_first_paint", k6metrics.Trend, k6metrics.Time),
BrowserFirstContentfulPaint: registry.MustNewMetric(
"browser_first_contentful_paint", k6metrics.Trend, k6metrics.Time),
BrowserFirstMeaningfulPaint: registry.MustNewMetric(
"browser_first_meaningful_paint", k6metrics.Trend, k6metrics.Time),
BrowserLoaded: registry.MustNewMetric(
"browser_loaded", k6metrics.Trend, k6metrics.Time),
}
}
16 changes: 10 additions & 6 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,10 @@ type (

// JSModule is the entrypoint into the browser JS module.
JSModule struct {
vu k6modules.VU
Devices map[string]common.Device
Version string
vu k6modules.VU
k6Metrics *common.CustomK6Metrics
Devices map[string]common.Device
Version string
}

// ModuleInstance represents an instance of the JS module.
Expand All @@ -65,11 +66,13 @@ func New() *RootModule {
// NewModuleInstance implements the k6modules.Module interface to return
// a new instance for each VU.
func (*RootModule) NewModuleInstance(vu k6modules.VU) k6modules.Instance {
k6m := common.RegisterCustomK6Metrics(vu.InitEnv().Registry)
return &ModuleInstance{
mod: &JSModule{
vu: vu,
Devices: common.GetDevices(),
Version: version,
vu: vu,
k6Metrics: k6m,
Devices: common.GetDevices(),
Version: version,
},
}
}
Expand All @@ -92,6 +95,7 @@ func (m *JSModule) Launch(browserName string, opts goja.Value) api.Browser {
}()*/

ctx := common.WithVU(m.vu.Context(), m.vu)
ctx = common.WithCustomK6Metrics(ctx, m.k6Metrics)

if browserName == "chromium" {
bt := chromium.NewBrowserType(ctx)
Expand Down
4 changes: 4 additions & 0 deletions tests/test_browser.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,10 @@ func newTestBrowser(tb testing.TB, opts ...interface{}) *testBrowser {
mockVU.CtxField = ctx
}

registry := k6metrics.NewRegistry()
k6m := common.RegisterCustomK6Metrics(registry)
mockVU.CtxField = common.WithCustomK6Metrics(mockVU.CtxField, k6m)

var (
state = mockVU.StateField
rt = mockVU.RuntimeField
Expand Down

0 comments on commit 5787918

Please sign in to comment.