Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rename metrics with a browser prefix #903

Merged
merged 10 commits into from
May 24, 2023
6 changes: 4 additions & 2 deletions common/frame_session.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ func NewFrameSession(
) (_ *FrameSession, err error) {
l.Debugf("NewFrameSession", "sid:%v tid:%v", s.ID(), tid)

k6Metrics := k6ext.GetCustomMetrics(ctx)

fs := FrameSession{
ctx: ctx, // TODO: create cancelable context that can be used to cancel and close all child sessions
session: s,
Expand All @@ -89,7 +91,7 @@ func NewFrameSession(
eventCh: make(chan Event),
childSessions: make(map[cdp.FrameID]*FrameSession),
vu: k6ext.GetVU(ctx),
k6Metrics: k6ext.GetCustomMetrics(ctx),
k6Metrics: k6Metrics,
logger: l,
serializer: l.ConsoleLogFormatterSerializer(),
}
Expand All @@ -98,7 +100,7 @@ func NewFrameSession(
if fs.parent != nil {
parentNM = fs.parent.networkManager
}
fs.networkManager, err = NewNetworkManager(ctx, s, fs.manager, parentNM)
fs.networkManager, err = NewNetworkManager(ctx, k6Metrics, s, fs.manager, parentNM)
if err != nil {
l.Debugf("NewFrameSession:NewNetworkManager", "sid:%v tid:%v err:%v",
s.ID(), tid, err)
Expand Down
36 changes: 19 additions & 17 deletions common/network_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,15 @@ var _ EventEmitter = &NetworkManager{}
type NetworkManager struct {
BaseEventEmitter

ctx context.Context
logger *log.Logger
session session
parent *NetworkManager
frameManager *FrameManager
credentials *Credentials
resolver k6netext.Resolver
vu k6modules.VU
ctx context.Context
logger *log.Logger
session session
parent *NetworkManager
frameManager *FrameManager
credentials *Credentials
resolver k6netext.Resolver
vu k6modules.VU
customMetrics *k6ext.CustomMetrics

// TODO: manage inflight requests separately (move them between the two maps
// as they transition from inflight -> completed)
Expand All @@ -59,7 +60,7 @@ type NetworkManager struct {

// NewNetworkManager creates a new network manager.
func NewNetworkManager(
ctx context.Context, s session, fm *FrameManager, parent *NetworkManager,
ctx context.Context, customMetrics *k6ext.CustomMetrics, s session, fm *FrameManager, parent *NetworkManager,
) (*NetworkManager, error) {
vu := k6ext.GetVU(ctx)
state := vu.State()
Expand All @@ -80,6 +81,7 @@ func NewNetworkManager(
frameManager: fm,
resolver: resolver,
vu: vu,
customMetrics: customMetrics,
reqIDToRequest: make(map[network.RequestID]*Request),
attemptedAuth: make(map[fetch.RequestID]bool),
extraHTTPHeaders: make(map[string]string),
Expand Down Expand Up @@ -156,7 +158,7 @@ func (m *NetworkManager) emitRequestMetrics(req *Request) {
k6metrics.PushIfNotDone(m.ctx, state.Samples, k6metrics.ConnectedSamples{
Samples: []k6metrics.Sample{
{
TimeSeries: k6metrics.TimeSeries{Metric: state.BuiltinMetrics.DataSent, Tags: tags},
TimeSeries: k6metrics.TimeSeries{Metric: m.customMetrics.BrowserDataSent, Tags: tags},
Value: float64(req.Size().Total()),
Time: req.wallTime,
},
Expand Down Expand Up @@ -216,17 +218,17 @@ func (m *NetworkManager) emitResponseMetrics(resp *Response, req *Request) {
k6metrics.PushIfNotDone(m.ctx, state.Samples, k6metrics.ConnectedSamples{
Samples: []k6metrics.Sample{
{
TimeSeries: k6metrics.TimeSeries{Metric: state.BuiltinMetrics.HTTPReqs, Tags: tags},
TimeSeries: k6metrics.TimeSeries{Metric: m.customMetrics.BrowserHTTPReqs, Tags: tags},
Value: 1,
Time: wallTime,
},
{
TimeSeries: k6metrics.TimeSeries{Metric: state.BuiltinMetrics.HTTPReqDuration, Tags: tags},
TimeSeries: k6metrics.TimeSeries{Metric: m.customMetrics.BrowserHTTPReqDuration, Tags: tags},
Value: k6metrics.D(wallTime.Sub(req.wallTime)),
Time: wallTime,
},
{
TimeSeries: k6metrics.TimeSeries{Metric: state.BuiltinMetrics.DataReceived, Tags: tags},
TimeSeries: k6metrics.TimeSeries{Metric: m.customMetrics.BrowserDataReceived, Tags: tags},
Value: float64(bodySize),
Time: wallTime,
},
Expand All @@ -237,22 +239,22 @@ func (m *NetworkManager) emitResponseMetrics(resp *Response, req *Request) {
k6metrics.PushIfNotDone(m.ctx, state.Samples, k6metrics.ConnectedSamples{
Samples: []k6metrics.Sample{
{
TimeSeries: k6metrics.TimeSeries{Metric: state.BuiltinMetrics.HTTPReqConnecting, Tags: tags},
TimeSeries: k6metrics.TimeSeries{Metric: m.customMetrics.BrowserHTTPReqConnecting, Tags: tags},
Value: k6metrics.D(time.Duration(resp.timing.ConnectEnd-resp.timing.ConnectStart) * time.Millisecond),
Time: wallTime,
},
{
TimeSeries: k6metrics.TimeSeries{Metric: state.BuiltinMetrics.HTTPReqTLSHandshaking, Tags: tags},
TimeSeries: k6metrics.TimeSeries{Metric: m.customMetrics.BrowserHTTPReqTLSHandshaking, Tags: tags},
Value: k6metrics.D(time.Duration(resp.timing.SslEnd-resp.timing.SslStart) * time.Millisecond),
Time: wallTime,
},
{
TimeSeries: k6metrics.TimeSeries{Metric: state.BuiltinMetrics.HTTPReqSending, Tags: tags},
TimeSeries: k6metrics.TimeSeries{Metric: m.customMetrics.BrowserHTTPReqSending, Tags: tags},
Value: k6metrics.D(time.Duration(resp.timing.SendEnd-resp.timing.SendStart) * time.Millisecond),
Time: wallTime,
},
{
TimeSeries: k6metrics.TimeSeries{Metric: state.BuiltinMetrics.HTTPReqReceiving, Tags: tags},
TimeSeries: k6metrics.TimeSeries{Metric: m.customMetrics.BrowserHTTPReqReceiving, Tags: tags},
Value: k6metrics.D(time.Duration(resp.timing.ReceiveHeadersEnd-resp.timing.SendEnd) * time.Millisecond),
Time: wallTime,
},
Expand Down
6 changes: 5 additions & 1 deletion common/network_manager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"testing"
"time"

"github.com/grafana/xk6-browser/k6ext"
"github.com/grafana/xk6-browser/k6ext/k6test"
"github.com/grafana/xk6-browser/log"

Expand Down Expand Up @@ -260,9 +261,12 @@ func TestNetworkManagerEmitRequestResponseMetricsTimingSkew(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()

registry := k6metrics.NewRegistry()
k6m := k6ext.RegisterCustomMetrics(registry)

var (
vu = k6test.NewVU(t)
nm = &NetworkManager{ctx: vu.Context(), vu: vu}
nm = &NetworkManager{ctx: vu.Context(), vu: vu, customMetrics: k6m}
)
vu.MoveToVUContext()

Expand Down
48 changes: 41 additions & 7 deletions k6ext/metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,23 +13,48 @@ const (
webVitalCLS = "CLS"
webVitalINP = "INP"
webVitalFCP = "FCP"

fidName = "browser_web_vital_fid"
ttfbName = "browser_web_vital_ttfb"
lcpName = "browser_web_vital_lcp"
clsName = "browser_web_vital_cls"
inpName = "browser_web_vital_inp"
fcpName = "browser_web_vital_fcp"

browserDataSentName = "browser_data_sent"
browserDataReceivedName = "browser_data_received"
browserHTTPReqsName = "browser_http_reqs"
browserHTTPReqDurationName = "browser_http_req_duration"
browserHTTPReqConnectingName = "browser_http_req_connecting"
browserHTTPReqTLSHandshakingName = "browser_http_req_tls_handshaking"
browserHTTPReqSendingName = "browser_http_req_sending"
browserHTTPReqReceivingName = "browser_http_req_receiving"
)

// CustomMetrics are the custom k6 metrics used by xk6-browser.
type CustomMetrics struct {
WebVitals map[string]*k6metrics.Metric

BrowserDataSent *k6metrics.Metric
BrowserDataReceived *k6metrics.Metric
BrowserHTTPReqs *k6metrics.Metric
BrowserHTTPReqDuration *k6metrics.Metric
BrowserHTTPReqConnecting *k6metrics.Metric
BrowserHTTPReqTLSHandshaking *k6metrics.Metric
BrowserHTTPReqSending *k6metrics.Metric
BrowserHTTPReqReceiving *k6metrics.Metric
}

// RegisterCustomMetrics creates and registers our custom metrics with the k6
// VU Registry and returns our internal struct pointer.
func RegisterCustomMetrics(registry *k6metrics.Registry) *CustomMetrics {
wvs := map[string]string{
webVitalFID: "browser_web_vital_fid", // first input delay
webVitalTTFB: "browser_web_vital_ttfb", // time to first byte
webVitalLCP: "browser_web_vital_lcp", // largest content paint
webVitalCLS: "browser_web_vital_cls", // cumulative layout shift
webVitalINP: "browser_web_vital_inp", // interaction to next paint
webVitalFCP: "browser_web_vital_fcp", // first contentful paint
webVitalFID: fidName, // first input delay
webVitalTTFB: ttfbName, // time to first byte
webVitalLCP: lcpName, // largest content paint
webVitalCLS: clsName, // cumulative layout shift
webVitalINP: inpName, // interaction to next paint
webVitalFCP: fcpName, // first contentful paint
}
webVitals := make(map[string]*k6metrics.Metric)

Expand All @@ -51,8 +76,17 @@ func RegisterCustomMetrics(registry *k6metrics.Registry) *CustomMetrics {
v+"_poor", k6metrics.Counter)
}

//nolint:lll
return &CustomMetrics{
WebVitals: webVitals,
WebVitals: webVitals,
BrowserDataSent: registry.MustNewMetric(browserDataSentName, k6metrics.Counter, k6metrics.Data),
BrowserDataReceived: registry.MustNewMetric(browserDataReceivedName, k6metrics.Counter, k6metrics.Data),
BrowserHTTPReqs: registry.MustNewMetric(browserHTTPReqsName, k6metrics.Counter),
BrowserHTTPReqDuration: registry.MustNewMetric(browserHTTPReqDurationName, k6metrics.Trend, k6metrics.Time),
BrowserHTTPReqConnecting: registry.MustNewMetric(browserHTTPReqConnectingName, k6metrics.Trend, k6metrics.Time),
BrowserHTTPReqTLSHandshaking: registry.MustNewMetric(browserHTTPReqTLSHandshakingName, k6metrics.Trend, k6metrics.Time),
BrowserHTTPReqSending: registry.MustNewMetric(browserHTTPReqSendingName, k6metrics.Trend, k6metrics.Time),
BrowserHTTPReqReceiving: registry.MustNewMetric(browserHTTPReqReceivingName, k6metrics.Trend, k6metrics.Time),
}
}

Expand Down