diff --git a/.github/workflows/xk6-tests/xk6-js-test/jstest.go b/.github/workflows/xk6-tests/xk6-js-test/jstest.go index a12c80aa0be..a81b4f01025 100644 --- a/.github/workflows/xk6-tests/xk6-js-test/jstest.go +++ b/.github/workflows/xk6-tests/xk6-js-test/jstest.go @@ -5,7 +5,7 @@ import ( "time" "go.k6.io/k6/js/modules" - "go.k6.io/k6/stats" + "go.k6.io/k6/metrics" ) func init() { @@ -19,7 +19,7 @@ type ( JSTest struct { vu modules.VU - foos *stats.Metric + foos *metrics.Metric } ) @@ -39,7 +39,7 @@ func New() *RootModule { func (*RootModule) NewModuleInstance(vu modules.VU) modules.Instance { return &JSTest{ vu: vu, - foos: vu.InitEnv().Registry.MustNewMetric("foos", stats.Counter), + foos: vu.InitEnv().Registry.MustNewMetric("foos", metrics.Counter), } } @@ -60,9 +60,9 @@ func (j *JSTest) Foo(arg float64) (bool, error) { tags := state.CloneTags() tags["foo"] = "bar" - stats.PushIfNotDone(ctx, state.Samples, stats.Sample{ + metrics.PushIfNotDone(ctx, state.Samples, metrics.Sample{ Time: time.Now(), - Metric: j.foos, Tags: stats.IntoSampleTags(&tags), + Metric: j.foos, Tags: metrics.IntoSampleTags(&tags), Value: arg, }) diff --git a/.github/workflows/xk6-tests/xk6-output-test/outputtest.go b/.github/workflows/xk6-tests/xk6-output-test/outputtest.go index 82fff1ae2ec..146a133bf63 100644 --- a/.github/workflows/xk6-tests/xk6-output-test/outputtest.go +++ b/.github/workflows/xk6-tests/xk6-output-test/outputtest.go @@ -22,9 +22,9 @@ package outputtest import ( "strconv" - "go.k6.io/k6/output" - "go.k6.io/k6/stats" "github.com/spf13/afero" + "go.k6.io/k6/metrics" + "go.k6.io/k6/output" ) func init() { @@ -57,7 +57,7 @@ func (o *Output) Start() error { } // AddMetricSamples just plucks out the metric we're interested in. -func (o *Output) AddMetricSamples(sampleContainers []stats.SampleContainer) { +func (o *Output) AddMetricSamples(sampleContainers []metrics.SampleContainer) { for _, sc := range sampleContainers { for _, sample := range sc.GetSamples() { if sample.Metric.Name == "foos" { diff --git a/api/v1/metric.go b/api/v1/metric.go index b06f83dc0f2..3e4bed998e6 100644 --- a/api/v1/metric.go +++ b/api/v1/metric.go @@ -27,11 +27,11 @@ import ( "gopkg.in/guregu/null.v3" - "go.k6.io/k6/stats" + "go.k6.io/k6/metrics" ) type NullMetricType struct { - Type stats.MetricType + Type metrics.MetricType Valid bool } @@ -52,7 +52,7 @@ func (t *NullMetricType) UnmarshalJSON(data []byte) error { } type NullValueType struct { - Type stats.ValueType + Type metrics.ValueType Valid bool } @@ -82,7 +82,8 @@ type Metric struct { Sample map[string]float64 `json:"sample" yaml:"sample"` } -func NewMetric(m *stats.Metric, t time.Duration) Metric { +// NewMetric constructs a new Metric +func NewMetric(m *metrics.Metric, t time.Duration) Metric { return Metric{ Name: m.Name, Type: NullMetricType{m.Type, true}, diff --git a/api/v1/metric_jsonapi.go b/api/v1/metric_jsonapi.go index d433000cd51..a89c29c4235 100644 --- a/api/v1/metric_jsonapi.go +++ b/api/v1/metric_jsonapi.go @@ -23,7 +23,7 @@ package v1 import ( "time" - "go.k6.io/k6/stats" + "go.k6.io/k6/metrics" ) // MetricsJSONAPI is JSON API envelop for metrics @@ -41,13 +41,13 @@ type metricData struct { Attributes Metric `json:"attributes"` } -func newMetricEnvelope(m *stats.Metric, t time.Duration) metricJSONAPI { +func newMetricEnvelope(m *metrics.Metric, t time.Duration) metricJSONAPI { return metricJSONAPI{ Data: newMetricData(m, t), } } -func newMetricsJSONAPI(list map[string]*stats.Metric, t time.Duration) MetricsJSONAPI { +func newMetricsJSONAPI(list map[string]*metrics.Metric, t time.Duration) MetricsJSONAPI { metrics := make([]metricData, 0, len(list)) for _, m := range list { @@ -59,7 +59,7 @@ func newMetricsJSONAPI(list map[string]*stats.Metric, t time.Duration) MetricsJS } } -func newMetricData(m *stats.Metric, t time.Duration) metricData { +func newMetricData(m *metrics.Metric, t time.Duration) metricData { metric := NewMetric(m, t) return metricData{ diff --git a/api/v1/metric_routes_test.go b/api/v1/metric_routes_test.go index 9cb661169c8..9e5aa2d728f 100644 --- a/api/v1/metric_routes_test.go +++ b/api/v1/metric_routes_test.go @@ -37,7 +37,6 @@ import ( "go.k6.io/k6/lib/testutils" "go.k6.io/k6/lib/testutils/minirunner" "go.k6.io/k6/metrics" - "go.k6.io/k6/stats" ) func TestGetMetrics(t *testing.T) { @@ -47,14 +46,14 @@ func TestGetMetrics(t *testing.T) { logger.SetOutput(testutils.NewTestOutput(t)) registry := metrics.NewRegistry() builtinMetrics := metrics.RegisterBuiltinMetrics(registry) - testMetric, err := registry.NewMetric("my_metric", stats.Trend, stats.Time) + testMetric, err := registry.NewMetric("my_metric", metrics.Trend, metrics.Time) require.NoError(t, err) execScheduler, err := local.NewExecutionScheduler(&minirunner.MiniRunner{}, builtinMetrics, logger) require.NoError(t, err) engine, err := core.NewEngine(execScheduler, lib.Options{}, lib.RuntimeOptions{}, nil, logger, registry) require.NoError(t, err) - engine.MetricsEngine.ObservedMetrics = map[string]*stats.Metric{ + engine.MetricsEngine.ObservedMetrics = map[string]*metrics.Metric{ "my_metric": testMetric, } engine.MetricsEngine.ObservedMetrics["my_metric"].Tainted = null.BoolFrom(true) @@ -81,18 +80,18 @@ func TestGetMetrics(t *testing.T) { var envelop MetricsJSONAPI assert.NoError(t, json.Unmarshal(rw.Body.Bytes(), &envelop)) - metrics := envelop.Data - if !assert.Len(t, metrics, 1) { + metricsData := envelop.Data + if !assert.Len(t, metricsData, 1) { return } - metric := metrics[0].Attributes + metric := metricsData[0].Attributes - assert.Equal(t, "my_metric", metrics[0].ID) + assert.Equal(t, "my_metric", metricsData[0].ID) assert.True(t, metric.Type.Valid) - assert.Equal(t, stats.Trend, metric.Type.Type) + assert.Equal(t, metrics.Trend, metric.Type.Type) assert.True(t, metric.Contains.Valid) - assert.Equal(t, stats.Time, metric.Contains.Type) + assert.Equal(t, metrics.Time, metric.Contains.Type) assert.True(t, metric.Tainted.Valid) assert.True(t, metric.Tainted.Bool) @@ -108,7 +107,7 @@ func TestGetMetric(t *testing.T) { logger := logrus.New() logger.SetOutput(testutils.NewTestOutput(t)) registry := metrics.NewRegistry() - testMetric, err := registry.NewMetric("my_metric", stats.Trend, stats.Time) + testMetric, err := registry.NewMetric("my_metric", metrics.Trend, metrics.Time) require.NoError(t, err) builtinMetrics := metrics.RegisterBuiltinMetrics(registry) execScheduler, err := local.NewExecutionScheduler(&minirunner.MiniRunner{}, builtinMetrics, logger) @@ -116,7 +115,7 @@ func TestGetMetric(t *testing.T) { engine, err := core.NewEngine(execScheduler, lib.Options{}, lib.RuntimeOptions{}, nil, logger, registry) require.NoError(t, err) - engine.MetricsEngine.ObservedMetrics = map[string]*stats.Metric{ + engine.MetricsEngine.ObservedMetrics = map[string]*metrics.Metric{ "my_metric": testMetric, } engine.MetricsEngine.ObservedMetrics["my_metric"].Tainted = null.BoolFrom(true) @@ -156,9 +155,9 @@ func TestGetMetric(t *testing.T) { assert.Equal(t, "my_metric", envelop.Data.ID) assert.True(t, metric.Type.Valid) - assert.Equal(t, stats.Trend, metric.Type.Type) + assert.Equal(t, metrics.Trend, metric.Type.Type) assert.True(t, metric.Contains.Valid) - assert.Equal(t, stats.Time, metric.Contains.Type) + assert.Equal(t, metrics.Time, metric.Contains.Type) assert.True(t, metric.Tainted.Valid) assert.True(t, metric.Tainted.Bool) }) diff --git a/api/v1/metric_test.go b/api/v1/metric_test.go index cfd092b9a2e..31a73b69df8 100644 --- a/api/v1/metric_test.go +++ b/api/v1/metric_test.go @@ -29,18 +29,17 @@ import ( "gopkg.in/guregu/null.v3" "go.k6.io/k6/metrics" - "go.k6.io/k6/stats" ) func TestNullMetricTypeJSON(t *testing.T) { t.Parallel() values := map[NullMetricType]string{ - {}: `null`, - {stats.Counter, true}: `"counter"`, - {stats.Gauge, true}: `"gauge"`, - {stats.Trend, true}: `"trend"`, - {stats.Rate, true}: `"rate"`, + {}: `null`, + {metrics.Counter, true}: `"counter"`, + {metrics.Gauge, true}: `"gauge"`, + {metrics.Trend, true}: `"trend"`, + {metrics.Rate, true}: `"rate"`, } t.Run("Marshal", func(t *testing.T) { t.Parallel() @@ -74,9 +73,9 @@ func TestNullValueTypeJSON(t *testing.T) { t.Parallel() values := map[NullValueType]string{ - {}: `null`, - {stats.Default, true}: `"default"`, - {stats.Time, true}: `"time"`, + {}: `null`, + {metrics.Default, true}: `"default"`, + {metrics.Time, true}: `"time"`, } t.Run("Marshal", func(t *testing.T) { t.Parallel() @@ -109,16 +108,16 @@ func TestNullValueTypeJSON(t *testing.T) { func TestNewMetric(t *testing.T) { t.Parallel() - old, err := metrics.NewRegistry().NewMetric("test_metric", stats.Trend, stats.Time) + old, err := metrics.NewRegistry().NewMetric("test_metric", metrics.Trend, metrics.Time) require.NoError(t, err) old.Tainted = null.BoolFrom(true) m := NewMetric(old, 0) assert.Equal(t, "test_metric", m.Name) assert.True(t, m.Type.Valid) - assert.Equal(t, stats.Trend, m.Type.Type) + assert.Equal(t, metrics.Trend, m.Type.Type) assert.True(t, m.Contains.Valid) assert.True(t, m.Tainted.Bool) assert.True(t, m.Tainted.Valid) - assert.Equal(t, stats.Time, m.Contains.Type) + assert.Equal(t, metrics.Time, m.Contains.Type) assert.NotEmpty(t, m.Sample) } diff --git a/cmd/config.go b/cmd/config.go index df1243a7665..bdfba86634a 100644 --- a/cmd/config.go +++ b/cmd/config.go @@ -39,7 +39,7 @@ import ( "go.k6.io/k6/lib" "go.k6.io/k6/lib/executor" "go.k6.io/k6/lib/types" - "go.k6.io/k6/stats" + "go.k6.io/k6/metrics" ) // configFlagSet returns a FlagSet with the default run configuration flags. @@ -201,7 +201,7 @@ func getConsolidatedConfig(globalState *globalState, cliConf Config, runnerOpts // for CLI flags in cmd.getOptions, in case other configuration sources // (e.g. env vars) overrode our default value. This is not done in // lib.Options.Validate to avoid circular imports. - if _, err = stats.GetResolversForTrendColumns(conf.SummaryTrendStats); err != nil { + if _, err = metrics.GetResolversForTrendColumns(conf.SummaryTrendStats); err != nil { return conf, err } @@ -214,7 +214,7 @@ func getConsolidatedConfig(globalState *globalState, cliConf Config, runnerOpts // Note that if you add option default value here, also add it in command line argument help text. func applyDefault(conf Config) Config { if conf.Options.SystemTags == nil { - conf.Options.SystemTags = &stats.DefaultSystemTagSet + conf.Options.SystemTags = &metrics.DefaultSystemTagSet } if conf.Options.SummaryTrendStats == nil { conf.Options.SummaryTrendStats = lib.DefaultSummaryTrendStats diff --git a/cmd/config_consolidation_test.go b/cmd/config_consolidation_test.go index a1dceb5d5dc..881dd1e5ce3 100644 --- a/cmd/config_consolidation_test.go +++ b/cmd/config_consolidation_test.go @@ -33,7 +33,7 @@ import ( "go.k6.io/k6/lib" "go.k6.io/k6/lib/executor" "go.k6.io/k6/lib/types" - "go.k6.io/k6/stats" + "go.k6.io/k6/metrics" ) func verifyOneIterPerOneVU(t *testing.T, c Config) { @@ -350,22 +350,22 @@ func getConfigConsolidationTestCases() []configConsolidationTestCase { // Test system tags {opts{}, exp{}, func(t *testing.T, c Config) { - assert.Equal(t, &stats.DefaultSystemTagSet, c.Options.SystemTags) + assert.Equal(t, &metrics.DefaultSystemTagSet, c.Options.SystemTags) }}, {opts{cli: []string{"--system-tags", `""`}}, exp{}, func(t *testing.T, c Config) { - assert.Equal(t, stats.SystemTagSet(0), *c.Options.SystemTags) + assert.Equal(t, metrics.SystemTagSet(0), *c.Options.SystemTags) }}, { opts{ runner: &lib.Options{ - SystemTags: stats.NewSystemTagSet(stats.TagSubproto, stats.TagURL), + SystemTags: metrics.NewSystemTagSet(metrics.TagSubproto, metrics.TagURL), }, }, exp{}, func(t *testing.T, c Config) { assert.Equal( t, - *stats.NewSystemTagSet(stats.TagSubproto, stats.TagURL), + *metrics.NewSystemTagSet(metrics.TagSubproto, metrics.TagURL), *c.Options.SystemTags, ) }, diff --git a/cmd/integration_tests/eventloop/eventloop_test.go b/cmd/integration_tests/eventloop/eventloop_test.go index 1de4efb3c15..8b1812c4b7d 100644 --- a/cmd/integration_tests/eventloop/eventloop_test.go +++ b/cmd/integration_tests/eventloop/eventloop_test.go @@ -20,7 +20,6 @@ import ( "go.k6.io/k6/lib/types" "go.k6.io/k6/loader" "go.k6.io/k6/metrics" - "go.k6.io/k6/stats" "gopkg.in/guregu/null.v3" ) @@ -201,7 +200,7 @@ export default function() { func newTestExecutionScheduler( t *testing.T, runner lib.Runner, logger *logrus.Logger, opts lib.Options, builtinMetrics *metrics.BuiltinMetrics, -) (ctx context.Context, cancel func(), execScheduler *local.ExecutionScheduler, samples chan stats.SampleContainer) { +) (ctx context.Context, cancel func(), execScheduler *local.ExecutionScheduler, samples chan metrics.SampleContainer) { if runner == nil { runner = &minirunner.MiniRunner{} } @@ -222,7 +221,7 @@ func newTestExecutionScheduler( execScheduler, err = local.NewExecutionScheduler(runner, builtinMetrics, logger) require.NoError(t, err) - samples = make(chan stats.SampleContainer, newOpts.MetricSamplesBufferSize.Int64) + samples = make(chan metrics.SampleContainer, newOpts.MetricSamplesBufferSize.Int64) go func() { for { select { diff --git a/cmd/options.go b/cmd/options.go index 4795f63c5fd..9981b4a2945 100644 --- a/cmd/options.go +++ b/cmd/options.go @@ -32,7 +32,7 @@ import ( "go.k6.io/k6/lib" "go.k6.io/k6/lib/consts" "go.k6.io/k6/lib/types" - "go.k6.io/k6/stats" + "go.k6.io/k6/metrics" ) var ( @@ -86,7 +86,7 @@ func optionFlagSet() *pflag.FlagSet { // set it to nil here, and add the default in applyDefault() instead. systemTagsCliHelpText := fmt.Sprintf( "only include these system tags in metrics (default %q)", - stats.DefaultSystemTagSet.SetString(), + metrics.DefaultSystemTagSet.SetString(), ) flags.StringSlice("system-tags", nil, systemTagsCliHelpText) flags.StringSlice("tag", nil, "add a `tag` to be applied to all samples, as `[name]=[value]`") @@ -181,7 +181,7 @@ func getOptions(flags *pflag.FlagSet) (lib.Options, error) { if err != nil { return opts, err } - opts.SystemTags = stats.ToSystemTagSet(systemTagList) + opts.SystemTags = metrics.ToSystemTagSet(systemTagList) } blacklistIPStrings, err := flags.GetStringSlice("blacklist-ip") @@ -223,7 +223,7 @@ func getOptions(flags *pflag.FlagSet) (lib.Options, error) { if errSts != nil { return opts, errSts } - if _, errSts = stats.GetResolversForTrendColumns(trendStats); err != nil { + if _, errSts = metrics.GetResolversForTrendColumns(trendStats); err != nil { return opts, errSts } opts.SummaryTrendStats = trendStats @@ -255,7 +255,7 @@ func getOptions(flags *pflag.FlagSet) (lib.Options, error) { } parsedRunTags[name] = value } - opts.RunTags = stats.IntoSampleTags(&parsedRunTags) + opts.RunTags = metrics.IntoSampleTags(&parsedRunTags) } redirectConFile, err := flags.GetString("console-output") diff --git a/core/engine.go b/core/engine.go index 07e9ea8cc00..41c7e7f6833 100644 --- a/core/engine.go +++ b/core/engine.go @@ -34,7 +34,6 @@ import ( "go.k6.io/k6/metrics" "go.k6.io/k6/metrics/engine" "go.k6.io/k6/output" - "go.k6.io/k6/stats" ) const ( @@ -66,7 +65,7 @@ type Engine struct { stopOnce sync.Once stopChan chan struct{} - Samples chan stats.SampleContainer + Samples chan metrics.SampleContainer // Are thresholds tainted? thresholdsTaintedLock sync.Mutex @@ -86,7 +85,7 @@ func NewEngine( ExecutionScheduler: ex, runtimeOptions: rtOpts, - Samples: make(chan stats.SampleContainer, opts.MetricSamplesBufferSize.Int64), + Samples: make(chan metrics.SampleContainer, opts.MetricSamplesBufferSize.Int64), stopChan: make(chan struct{}), logger: logger.WithField("component", "engine"), } @@ -246,7 +245,7 @@ func (e *Engine) startBackgroundProcesses( } func (e *Engine) processMetrics(globalCtx context.Context, processMetricsAfterRun chan struct{}) { - sampleContainers := []stats.SampleContainer{} + sampleContainers := []metrics.SampleContainer{} defer func() { // Process any remaining metrics in the pipeline, by this point Run() @@ -278,7 +277,7 @@ func (e *Engine) processMetrics(globalCtx context.Context, processMetricsAfterRu // Make the new container with the same size as the previous // one, assuming that we produce roughly the same amount of // metrics data between ticks... - sampleContainers = make([]stats.SampleContainer, 0, cap(sampleContainers)) + sampleContainers = make([]metrics.SampleContainer, 0, cap(sampleContainers)) } } for { diff --git a/core/engine_test.go b/core/engine_test.go index 7f45d4bf19d..3a6f955641e 100644 --- a/core/engine_test.go +++ b/core/engine_test.go @@ -47,7 +47,6 @@ import ( "go.k6.io/k6/loader" "go.k6.io/k6/metrics" "go.k6.io/k6/output" - "go.k6.io/k6/stats" ) const isWindows = runtime.GOOS == "windows" @@ -117,7 +116,7 @@ func TestEngineRun(t *testing.T) { t.Parallel() done := make(chan struct{}) runner := &minirunner.MiniRunner{ - Fn: func(ctx context.Context, _ *lib.State, _ chan<- stats.SampleContainer) error { + Fn: func(ctx context.Context, _ *lib.State, _ chan<- metrics.SampleContainer) error { <-ctx.Done() close(done) return nil @@ -151,17 +150,17 @@ func TestEngineRun(t *testing.T) { t.Parallel() registry := metrics.NewRegistry() - testMetric, err := registry.NewMetric("test_metric", stats.Trend) + testMetric, err := registry.NewMetric("test_metric", metrics.Trend) require.NoError(t, err) signalChan := make(chan interface{}) runner := &minirunner.MiniRunner{ - Fn: func(ctx context.Context, _ *lib.State, out chan<- stats.SampleContainer) error { - stats.PushIfNotDone(ctx, out, stats.Sample{Metric: testMetric, Time: time.Now(), Value: 1}) + Fn: func(ctx context.Context, _ *lib.State, out chan<- metrics.SampleContainer) error { + metrics.PushIfNotDone(ctx, out, metrics.Sample{Metric: testMetric, Time: time.Now(), Value: 1}) close(signalChan) <-ctx.Done() - stats.PushIfNotDone(ctx, out, stats.Sample{Metric: testMetric, Time: time.Now(), Value: 1}) + metrics.PushIfNotDone(ctx, out, metrics.Sample{Metric: testMetric, Time: time.Now(), Value: 1}) return nil }, } @@ -226,12 +225,12 @@ func TestEngineOutput(t *testing.T) { t.Parallel() registry := metrics.NewRegistry() - testMetric, err := registry.NewMetric("test_metric", stats.Trend) + testMetric, err := registry.NewMetric("test_metric", metrics.Trend) require.NoError(t, err) runner := &minirunner.MiniRunner{ - Fn: func(ctx context.Context, _ *lib.State, out chan<- stats.SampleContainer) error { - out <- stats.Sample{Metric: testMetric} + Fn: func(ctx context.Context, _ *lib.State, out chan<- metrics.SampleContainer) error { + out <- metrics.Sample{Metric: testMetric} return nil }, } @@ -245,7 +244,7 @@ func TestEngineOutput(t *testing.T) { assert.NoError(t, run()) wait() - cSamples := []stats.Sample{} + cSamples := []metrics.Sample{} for _, sample := range mockOutput.Samples { if sample.Metric == testMetric { cSamples = append(cSamples, sample) @@ -253,7 +252,7 @@ func TestEngineOutput(t *testing.T) { } metric := e.MetricsEngine.ObservedMetrics["test_metric"] if assert.NotNil(t, metric) { - sink := metric.Sink.(*stats.TrendSink) + sink := metric.Sink.(*metrics.TrendSink) // nolint: forcetypeassert if assert.NotNil(t, sink) { numOutputSamples := len(cSamples) numEngineSamples := len(sink.Values) @@ -269,39 +268,39 @@ func TestEngine_processSamples(t *testing.T) { t.Parallel() registry := metrics.NewRegistry() - metric, err := registry.NewMetric("my_metric", stats.Gauge) + metric, err := registry.NewMetric("my_metric", metrics.Gauge) require.NoError(t, err) e, _, wait := newTestEngineWithRegistry(t, nil, nil, nil, lib.Options{}, registry) e.OutputManager.AddMetricSamples( - []stats.SampleContainer{stats.Sample{Metric: metric, Value: 1.25, Tags: stats.IntoSampleTags(&map[string]string{"a": "1"})}}, + []metrics.SampleContainer{metrics.Sample{Metric: metric, Value: 1.25, Tags: metrics.IntoSampleTags(&map[string]string{"a": "1"})}}, ) e.Stop() wait() - assert.IsType(t, &stats.GaugeSink{}, e.MetricsEngine.ObservedMetrics["my_metric"].Sink) + assert.IsType(t, &metrics.GaugeSink{}, e.MetricsEngine.ObservedMetrics["my_metric"].Sink) }) t.Run("submetric", func(t *testing.T) { t.Parallel() registry := metrics.NewRegistry() - metric, err := registry.NewMetric("my_metric", stats.Gauge) + metric, err := registry.NewMetric("my_metric", metrics.Gauge) require.NoError(t, err) - ths := stats.NewThresholds([]string{`value<2`}) + ths := metrics.NewThresholds([]string{`value<2`}) gotParseErr := ths.Parse() require.NoError(t, gotParseErr) e, _, wait := newTestEngineWithRegistry(t, nil, nil, nil, lib.Options{ - Thresholds: map[string]stats.Thresholds{ + Thresholds: map[string]metrics.Thresholds{ "my_metric{a:1}": ths, }, }, registry) e.OutputManager.AddMetricSamples( - []stats.SampleContainer{stats.Sample{Metric: metric, Value: 1.25, Tags: stats.IntoSampleTags(&map[string]string{"a": "1", "b": "2"})}}, + []metrics.SampleContainer{metrics.Sample{Metric: metric, Value: 1.25, Tags: metrics.IntoSampleTags(&map[string]string{"a": "1", "b": "2"})}}, ) e.Stop() @@ -311,8 +310,8 @@ func TestEngine_processSamples(t *testing.T) { sms := e.MetricsEngine.ObservedMetrics["my_metric{a:1}"] assert.EqualValues(t, map[string]string{"a": "1"}, sms.Sub.Tags.CloneTags()) - assert.IsType(t, &stats.GaugeSink{}, e.MetricsEngine.ObservedMetrics["my_metric"].Sink) - assert.IsType(t, &stats.GaugeSink{}, e.MetricsEngine.ObservedMetrics["my_metric{a:1}"].Sink) + assert.IsType(t, &metrics.GaugeSink{}, e.MetricsEngine.ObservedMetrics["my_metric"].Sink) + assert.IsType(t, &metrics.GaugeSink{}, e.MetricsEngine.ObservedMetrics["my_metric{a:1}"].Sink) }) } @@ -320,23 +319,23 @@ func TestEngineThresholdsWillAbort(t *testing.T) { t.Parallel() registry := metrics.NewRegistry() - metric, err := registry.NewMetric("my_metric", stats.Gauge) + metric, err := registry.NewMetric("my_metric", metrics.Gauge) require.NoError(t, err) // The incoming samples for the metric set it to 1.25. Considering // the metric is of type Gauge, value > 1.25 should always fail, and // trigger an abort. - ths := stats.NewThresholds([]string{"value>1.25"}) + ths := metrics.NewThresholds([]string{"value>1.25"}) gotParseErr := ths.Parse() require.NoError(t, gotParseErr) ths.Thresholds[0].AbortOnFail = true - thresholds := map[string]stats.Thresholds{metric.Name: ths} + thresholds := map[string]metrics.Thresholds{metric.Name: ths} e, _, wait := newTestEngineWithRegistry(t, nil, nil, nil, lib.Options{Thresholds: thresholds}, registry) e.OutputManager.AddMetricSamples( - []stats.SampleContainer{stats.Sample{Metric: metric, Value: 1.25, Tags: stats.IntoSampleTags(&map[string]string{"a": "1"})}}, + []metrics.SampleContainer{metrics.Sample{Metric: metric, Value: 1.25, Tags: metrics.IntoSampleTags(&map[string]string{"a": "1"})}}, ) e.Stop() wait() @@ -347,24 +346,24 @@ func TestEngineAbortedByThresholds(t *testing.T) { t.Parallel() registry := metrics.NewRegistry() - metric, err := registry.NewMetric("my_metric", stats.Gauge) + metric, err := registry.NewMetric("my_metric", metrics.Gauge) require.NoError(t, err) // The MiniRunner sets the value of the metric to 1.25. Considering // the metric is of type Gauge, value > 1.25 should always fail, and // trigger an abort. // **N.B**: a threshold returning an error, won't trigger an abort. - ths := stats.NewThresholds([]string{"value>1.25"}) + ths := metrics.NewThresholds([]string{"value>1.25"}) gotParseErr := ths.Parse() require.NoError(t, gotParseErr) ths.Thresholds[0].AbortOnFail = true - thresholds := map[string]stats.Thresholds{metric.Name: ths} + thresholds := map[string]metrics.Thresholds{metric.Name: ths} done := make(chan struct{}) runner := &minirunner.MiniRunner{ - Fn: func(ctx context.Context, _ *lib.State, out chan<- stats.SampleContainer) error { - out <- stats.Sample{Metric: metric, Value: 1.25, Tags: stats.IntoSampleTags(&map[string]string{"a": "1"})} + Fn: func(ctx context.Context, _ *lib.State, out chan<- metrics.SampleContainer) error { + out <- metrics.Sample{Metric: metric, Value: 1.25, Tags: metrics.IntoSampleTags(&map[string]string{"a": "1"})} <-ctx.Done() close(done) return nil @@ -422,16 +421,16 @@ func TestEngine_processThresholds(t *testing.T) { t.Parallel() registry := metrics.NewRegistry() - gaugeMetric, err := registry.NewMetric("my_metric", stats.Gauge) + gaugeMetric, err := registry.NewMetric("my_metric", metrics.Gauge) require.NoError(t, err) - counterMetric, err := registry.NewMetric("used_counter", stats.Counter) + counterMetric, err := registry.NewMetric("used_counter", metrics.Counter) require.NoError(t, err) - _, err = registry.NewMetric("unused_counter", stats.Counter) + _, err = registry.NewMetric("unused_counter", metrics.Counter) require.NoError(t, err) - thresholds := make(map[string]stats.Thresholds, len(data.ths)) + thresholds := make(map[string]metrics.Thresholds, len(data.ths)) for m, srcs := range data.ths { - ths := stats.NewThresholds(srcs) + ths := metrics.NewThresholds(srcs) gotParseErr := ths.Parse() require.NoError(t, gotParseErr) thresholds[m] = ths @@ -444,9 +443,9 @@ func TestEngine_processThresholds(t *testing.T) { ) e.OutputManager.AddMetricSamples( - []stats.SampleContainer{ - stats.Sample{Metric: gaugeMetric, Value: 1.25, Tags: stats.IntoSampleTags(&map[string]string{"a": "1"})}, - stats.Sample{Metric: counterMetric, Value: 2, Tags: stats.IntoSampleTags(&map[string]string{"b": "1"})}, + []metrics.SampleContainer{ + metrics.Sample{Metric: gaugeMetric, Value: 1.25, Tags: metrics.IntoSampleTags(&map[string]string{"a": "1"})}, + metrics.Sample{Metric: counterMetric, Value: 2, Tags: metrics.IntoSampleTags(&map[string]string{"b": "1"})}, }, ) @@ -635,7 +634,7 @@ func TestRunTags(t *testing.T) { tb := httpmultibin.NewHTTPMultiBin(t) runTagsMap := map[string]string{"foo": "bar", "test": "mest", "over": "written"} - runTags := stats.NewSampleTags(runTagsMap) + runTags := metrics.NewSampleTags(runTagsMap) script := []byte(tb.Replacer.Replace(` import http from "k6/http"; @@ -706,7 +705,7 @@ func TestRunTags(t *testing.T) { VUs: null.IntFrom(2), Hosts: tb.Dialer.Hosts, RunTags: runTags, - SystemTags: &stats.DefaultSystemTagSet, + SystemTags: &metrics.DefaultSystemTagSet, InsecureSkipTLSVerify: null.BoolFrom(true), }) @@ -796,7 +795,7 @@ func TestSetupTeardownThresholds(t *testing.T) { require.NoError(t, err) engine, run, wait := newTestEngine(t, nil, runner, nil, lib.Options{ - SystemTags: &stats.DefaultSystemTagSet, + SystemTags: &metrics.DefaultSystemTagSet, SetupTimeout: types.NullDurationFrom(3 * time.Second), TeardownTimeout: types.NullDurationFrom(3 * time.Second), VUs: null.IntFrom(3), @@ -849,7 +848,7 @@ func TestSetupException(t *testing.T) { require.NoError(t, err) _, run, wait := newTestEngine(t, nil, runner, nil, lib.Options{ - SystemTags: &stats.DefaultSystemTagSet, + SystemTags: &metrics.DefaultSystemTagSet, SetupTimeout: types.NullDurationFrom(3 * time.Second), TeardownTimeout: types.NullDurationFrom(3 * time.Second), VUs: null.IntFrom(3), @@ -1192,18 +1191,18 @@ func TestEngineRunsTeardownEvenAfterTestRunIsAborted(t *testing.T) { t.Parallel() registry := metrics.NewRegistry() - testMetric, err := registry.NewMetric("teardown_metric", stats.Counter) + testMetric, err := registry.NewMetric("teardown_metric", metrics.Counter) require.NoError(t, err) ctx, cancel := context.WithCancel(context.Background()) runner := &minirunner.MiniRunner{ - Fn: func(ctx context.Context, _ *lib.State, out chan<- stats.SampleContainer) error { + Fn: func(ctx context.Context, _ *lib.State, out chan<- metrics.SampleContainer) error { cancel() // we cancel the runCtx immediately after the test starts return nil }, - TeardownFn: func(ctx context.Context, out chan<- stats.SampleContainer) error { - out <- stats.Sample{Metric: testMetric, Value: 1} + TeardownFn: func(ctx context.Context, out chan<- metrics.SampleContainer) error { + out <- metrics.Sample{Metric: testMetric, Value: 1} return nil }, } diff --git a/core/local/local.go b/core/local/local.go index 25f52b1d029..62482d82d82 100644 --- a/core/local/local.go +++ b/core/local/local.go @@ -34,7 +34,6 @@ import ( "go.k6.io/k6/lib" "go.k6.io/k6/lib/executor" "go.k6.io/k6/metrics" - "go.k6.io/k6/stats" "go.k6.io/k6/ui/pb" ) @@ -167,7 +166,7 @@ func (e *ExecutionScheduler) GetExecutionPlan() []lib.ExecutionStep { // in the Init() method, and also passed to executors so they can initialize // any unplanned VUs themselves. func (e *ExecutionScheduler) initVU( - samplesOut chan<- stats.SampleContainer, logger *logrus.Entry, + samplesOut chan<- metrics.SampleContainer, logger *logrus.Entry, ) (lib.InitializedVU, error) { // Get the VU IDs here, so that the VUs are (mostly) ordered by their // number in the channel buffer @@ -202,7 +201,7 @@ func (e *ExecutionScheduler) getRunStats() string { } func (e *ExecutionScheduler) initVUsConcurrently( - ctx context.Context, samplesOut chan<- stats.SampleContainer, count uint64, + ctx context.Context, samplesOut chan<- metrics.SampleContainer, count uint64, concurrency int, logger *logrus.Entry, ) chan error { doneInits := make(chan error, count) // poor man's early-return waitgroup @@ -234,13 +233,13 @@ func (e *ExecutionScheduler) initVUsConcurrently( return doneInits } -func (e *ExecutionScheduler) emitVUsAndVUsMax(ctx context.Context, out chan<- stats.SampleContainer) { +func (e *ExecutionScheduler) emitVUsAndVUsMax(ctx context.Context, out chan<- metrics.SampleContainer) { e.logger.Debug("Starting emission of VUs and VUsMax metrics...") emitMetrics := func() { t := time.Now() - samples := stats.ConnectedSamples{ - Samples: []stats.Sample{ + samples := metrics.ConnectedSamples{ + Samples: []metrics.Sample{ { Time: t, Metric: e.state.BuiltinMetrics.VUs, @@ -256,7 +255,7 @@ func (e *ExecutionScheduler) emitVUsAndVUsMax(ctx context.Context, out chan<- st Tags: e.options.RunTags, Time: t, } - stats.PushIfNotDone(ctx, out, samples) + metrics.PushIfNotDone(ctx, out, samples) } ticker := time.NewTicker(1 * time.Second) @@ -282,7 +281,7 @@ func (e *ExecutionScheduler) emitVUsAndVUsMax(ctx context.Context, out chan<- st // Init concurrently initializes all of the planned VUs and then sequentially // initializes all of the configured executors. -func (e *ExecutionScheduler) Init(ctx context.Context, samplesOut chan<- stats.SampleContainer) error { +func (e *ExecutionScheduler) Init(ctx context.Context, samplesOut chan<- metrics.SampleContainer) error { e.emitVUsAndVUsMax(ctx, samplesOut) logger := e.logger.WithField("phase", "local-execution-scheduler-init") @@ -348,7 +347,7 @@ func (e *ExecutionScheduler) Init(ctx context.Context, samplesOut chan<- stats.S // configured startTime for the specific executor and then running its Run() // method. func (e *ExecutionScheduler) runExecutor( - runCtx context.Context, runResults chan<- error, engineOut chan<- stats.SampleContainer, executor lib.Executor, + runCtx context.Context, runResults chan<- error, engineOut chan<- metrics.SampleContainer, executor lib.Executor, ) { executorConfig := executor.GetConfig() executorStartTime := executorConfig.GetStartTime() @@ -397,7 +396,7 @@ func (e *ExecutionScheduler) runExecutor( // Run the ExecutionScheduler, funneling all generated metric samples through the supplied // out channel. //nolint:funlen -func (e *ExecutionScheduler) Run(globalCtx, runCtx context.Context, engineOut chan<- stats.SampleContainer) error { +func (e *ExecutionScheduler) Run(globalCtx, runCtx context.Context, engineOut chan<- metrics.SampleContainer) error { defer func() { close(e.stopVUsEmission) <-e.vusEmissionStopped diff --git a/core/local/local_test.go b/core/local/local_test.go index cbdbf673c4f..bebfc73d321 100644 --- a/core/local/local_test.go +++ b/core/local/local_test.go @@ -51,12 +51,11 @@ import ( "go.k6.io/k6/lib/types" "go.k6.io/k6/loader" "go.k6.io/k6/metrics" - "go.k6.io/k6/stats" ) func newTestExecutionScheduler( t *testing.T, runner lib.Runner, logger *logrus.Logger, opts lib.Options, -) (ctx context.Context, cancel func(), execScheduler *ExecutionScheduler, samples chan stats.SampleContainer) { +) (ctx context.Context, cancel func(), execScheduler *ExecutionScheduler, samples chan metrics.SampleContainer) { if runner == nil { runner = &minirunner.MiniRunner{} } @@ -79,7 +78,7 @@ func newTestExecutionScheduler( execScheduler, err = NewExecutionScheduler(runner, builtinMetrics, logger) require.NoError(t, err) - samples = make(chan stats.SampleContainer, newOpts.MetricSamplesBufferSize.Int64) + samples = make(chan metrics.SampleContainer, newOpts.MetricSamplesBufferSize.Int64) go func() { for { select { @@ -147,7 +146,7 @@ func TestExecutionSchedulerRunNonDefault(t *testing.T) { defer cancel() done := make(chan struct{}) - samples := make(chan stats.SampleContainer) + samples := make(chan metrics.SampleContainer) go func() { err := execScheduler.Init(ctx, samples) if tc.expErr != "" { @@ -259,7 +258,7 @@ func TestExecutionSchedulerRunEnv(t *testing.T) { defer cancel() done := make(chan struct{}) - samples := make(chan stats.SampleContainer) + samples := make(chan metrics.SampleContainer) go func() { assert.NoError(t, execScheduler.Init(ctx, samples)) assert.NoError(t, execScheduler.Run(ctx, ctx, samples)) @@ -268,7 +267,7 @@ func TestExecutionSchedulerRunEnv(t *testing.T) { for { select { case sample := <-samples: - if s, ok := sample.(stats.Sample); ok && s.Metric.Name == "errors" { + if s, ok := sample.(metrics.Sample); ok && s.Metric.Name == "errors" { assert.FailNow(t, "received error sample from test") } case <-done: @@ -320,7 +319,7 @@ func TestExecutionSchedulerSystemTags(t *testing.T) { require.NoError(t, err) require.NoError(t, runner.SetOptions(runner.GetOptions().Apply(lib.Options{ - SystemTags: &stats.DefaultSystemTagSet, + SystemTags: &metrics.DefaultSystemTagSet, }))) execScheduler, err := NewExecutionScheduler(runner, builtinMetrics, logger) @@ -329,7 +328,7 @@ func TestExecutionSchedulerSystemTags(t *testing.T) { ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) defer cancel() - samples := make(chan stats.SampleContainer) + samples := make(chan metrics.SampleContainer) done := make(chan struct{}) go func() { defer close(done) @@ -337,7 +336,7 @@ func TestExecutionSchedulerSystemTags(t *testing.T) { require.NoError(t, execScheduler.Run(ctx, ctx, samples)) }() - expCommonTrailTags := stats.IntoSampleTags(&map[string]string{ + expCommonTrailTags := metrics.IntoSampleTags(&map[string]string{ "group": "", "method": "GET", "name": sr("HTTPBIN_IP_URL/"), @@ -348,15 +347,15 @@ func TestExecutionSchedulerSystemTags(t *testing.T) { }) expTrailPVUTagsRaw := expCommonTrailTags.CloneTags() expTrailPVUTagsRaw["scenario"] = "per_vu_test" - expTrailPVUTags := stats.IntoSampleTags(&expTrailPVUTagsRaw) + expTrailPVUTags := metrics.IntoSampleTags(&expTrailPVUTagsRaw) expTrailSITagsRaw := expCommonTrailTags.CloneTags() expTrailSITagsRaw["scenario"] = "shared_test" - expTrailSITags := stats.IntoSampleTags(&expTrailSITagsRaw) - expNetTrailPVUTags := stats.IntoSampleTags(&map[string]string{ + expTrailSITags := metrics.IntoSampleTags(&expTrailSITagsRaw) + expNetTrailPVUTags := metrics.IntoSampleTags(&map[string]string{ "group": "", "scenario": "per_vu_test", }) - expNetTrailSITags := stats.IntoSampleTags(&map[string]string{ + expNetTrailSITags := metrics.IntoSampleTags(&map[string]string{ "group": "", "scenario": "shared_test", }) @@ -467,7 +466,7 @@ func TestExecutionSchedulerRunCustomTags(t *testing.T) { defer cancel() done := make(chan struct{}) - samples := make(chan stats.SampleContainer) + samples := make(chan metrics.SampleContainer) go func() { defer close(done) require.NoError(t, execScheduler.Init(ctx, samples)) @@ -629,7 +628,7 @@ func TestExecutionSchedulerRunCustomConfigNoCrossover(t *testing.T) { ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second) defer cancel() - samples := make(chan stats.SampleContainer) + samples := make(chan metrics.SampleContainer) go func() { assert.NoError(t, execScheduler.Init(ctx, samples)) assert.NoError(t, execScheduler.Run(ctx, ctx, samples)) @@ -654,7 +653,7 @@ func TestExecutionSchedulerRunCustomConfigNoCrossover(t *testing.T) { var gotSampleTags int for sample := range samples { switch s := sample.(type) { - case stats.Sample: + case metrics.Sample: if s.Metric.Name == "errors" { assert.FailNow(t, "received error sample from test") } @@ -680,7 +679,7 @@ func TestExecutionSchedulerRunCustomConfigNoCrossover(t *testing.T) { gotSampleTags++ } } - case stats.ConnectedSamples: + case metrics.ConnectedSamples: for _, sm := range s.Samples { tags := sm.Tags.CloneTags() if reflect.DeepEqual(expectedConnSampleTags, tags) { @@ -699,11 +698,11 @@ func TestExecutionSchedulerSetupTeardownRun(t *testing.T) { setupC := make(chan struct{}) teardownC := make(chan struct{}) runner := &minirunner.MiniRunner{ - SetupFn: func(ctx context.Context, out chan<- stats.SampleContainer) ([]byte, error) { + SetupFn: func(ctx context.Context, out chan<- metrics.SampleContainer) ([]byte, error) { close(setupC) return nil, nil }, - TeardownFn: func(ctx context.Context, out chan<- stats.SampleContainer) error { + TeardownFn: func(ctx context.Context, out chan<- metrics.SampleContainer) error { close(teardownC) return nil }, @@ -720,7 +719,7 @@ func TestExecutionSchedulerSetupTeardownRun(t *testing.T) { t.Run("Setup Error", func(t *testing.T) { t.Parallel() runner := &minirunner.MiniRunner{ - SetupFn: func(ctx context.Context, out chan<- stats.SampleContainer) ([]byte, error) { + SetupFn: func(ctx context.Context, out chan<- metrics.SampleContainer) ([]byte, error) { return nil, errors.New("setup error") }, } @@ -731,10 +730,10 @@ func TestExecutionSchedulerSetupTeardownRun(t *testing.T) { t.Run("Don't Run Setup", func(t *testing.T) { t.Parallel() runner := &minirunner.MiniRunner{ - SetupFn: func(ctx context.Context, out chan<- stats.SampleContainer) ([]byte, error) { + SetupFn: func(ctx context.Context, out chan<- metrics.SampleContainer) ([]byte, error) { return nil, errors.New("setup error") }, - TeardownFn: func(ctx context.Context, out chan<- stats.SampleContainer) error { + TeardownFn: func(ctx context.Context, out chan<- metrics.SampleContainer) error { return errors.New("teardown error") }, } @@ -750,10 +749,10 @@ func TestExecutionSchedulerSetupTeardownRun(t *testing.T) { t.Run("Teardown Error", func(t *testing.T) { t.Parallel() runner := &minirunner.MiniRunner{ - SetupFn: func(ctx context.Context, out chan<- stats.SampleContainer) ([]byte, error) { + SetupFn: func(ctx context.Context, out chan<- metrics.SampleContainer) ([]byte, error) { return nil, nil }, - TeardownFn: func(ctx context.Context, out chan<- stats.SampleContainer) error { + TeardownFn: func(ctx context.Context, out chan<- metrics.SampleContainer) error { return errors.New("teardown error") }, } @@ -768,10 +767,10 @@ func TestExecutionSchedulerSetupTeardownRun(t *testing.T) { t.Run("Don't Run Teardown", func(t *testing.T) { t.Parallel() runner := &minirunner.MiniRunner{ - SetupFn: func(ctx context.Context, out chan<- stats.SampleContainer) ([]byte, error) { + SetupFn: func(ctx context.Context, out chan<- metrics.SampleContainer) ([]byte, error) { return nil, nil }, - TeardownFn: func(ctx context.Context, out chan<- stats.SampleContainer) error { + TeardownFn: func(ctx context.Context, out chan<- metrics.SampleContainer) error { return errors.New("teardown error") }, } @@ -816,7 +815,7 @@ func TestExecutionSchedulerStages(t *testing.T) { t.Run(name, func(t *testing.T) { t.Parallel() runner := &minirunner.MiniRunner{ - Fn: func(ctx context.Context, _ *lib.State, out chan<- stats.SampleContainer) error { + Fn: func(ctx context.Context, _ *lib.State, out chan<- metrics.SampleContainer) error { time.Sleep(100 * time.Millisecond) return nil }, @@ -835,7 +834,7 @@ func TestExecutionSchedulerStages(t *testing.T) { func TestExecutionSchedulerEndTime(t *testing.T) { t.Parallel() runner := &minirunner.MiniRunner{ - Fn: func(ctx context.Context, _ *lib.State, out chan<- stats.SampleContainer) error { + Fn: func(ctx context.Context, _ *lib.State, out chan<- metrics.SampleContainer) error { time.Sleep(100 * time.Millisecond) return nil }, @@ -860,7 +859,7 @@ func TestExecutionSchedulerEndTime(t *testing.T) { func TestExecutionSchedulerRuntimeErrors(t *testing.T) { t.Parallel() runner := &minirunner.MiniRunner{ - Fn: func(ctx context.Context, _ *lib.State, out chan<- stats.SampleContainer) error { + Fn: func(ctx context.Context, _ *lib.State, out chan<- metrics.SampleContainer) error { time.Sleep(10 * time.Millisecond) return errors.New("hi") }, @@ -898,7 +897,7 @@ func TestExecutionSchedulerEndErrors(t *testing.T) { exec.GracefulStop = types.NullDurationFrom(0 * time.Second) runner := &minirunner.MiniRunner{ - Fn: func(ctx context.Context, _ *lib.State, out chan<- stats.SampleContainer) error { + Fn: func(ctx context.Context, _ *lib.State, out chan<- metrics.SampleContainer) error { <-ctx.Done() return errors.New("hi") }, @@ -925,7 +924,7 @@ func TestExecutionSchedulerEndErrors(t *testing.T) { func TestExecutionSchedulerEndIterations(t *testing.T) { t.Parallel() - metric := &stats.Metric{Name: "test_metric"} + metric := &metrics.Metric{Name: "test_metric"} options, err := executor.DeriveScenariosFromShortcuts(lib.Options{ VUs: null.IntFrom(1), @@ -936,13 +935,13 @@ func TestExecutionSchedulerEndIterations(t *testing.T) { var i int64 runner := &minirunner.MiniRunner{ - Fn: func(ctx context.Context, _ *lib.State, out chan<- stats.SampleContainer) error { + Fn: func(ctx context.Context, _ *lib.State, out chan<- metrics.SampleContainer) error { select { case <-ctx.Done(): default: atomic.AddInt64(&i, 1) } - out <- stats.Sample{Metric: metric, Value: 1.0} + out <- metrics.Sample{Metric: metric, Value: 1.0} return nil }, Options: options, @@ -959,7 +958,7 @@ func TestExecutionSchedulerEndIterations(t *testing.T) { execScheduler, err := NewExecutionScheduler(runner, builtinMetrics, logger) require.NoError(t, err) - samples := make(chan stats.SampleContainer, 300) + samples := make(chan metrics.SampleContainer, 300) require.NoError(t, execScheduler.Init(ctx, samples)) require.NoError(t, execScheduler.Run(ctx, ctx, samples)) @@ -970,14 +969,14 @@ func TestExecutionSchedulerEndIterations(t *testing.T) { for i := 0; i < 100; i++ { mySample, ok := <-samples require.True(t, ok) - assert.Equal(t, stats.Sample{Metric: metric, Value: 1.0}, mySample) + assert.Equal(t, metrics.Sample{Metric: metric, Value: 1.0}, mySample) } } func TestExecutionSchedulerIsRunning(t *testing.T) { t.Parallel() runner := &minirunner.MiniRunner{ - Fn: func(ctx context.Context, _ *lib.State, out chan<- stats.SampleContainer) error { + Fn: func(ctx context.Context, _ *lib.State, out chan<- metrics.SampleContainer) error { <-ctx.Done() return nil }, @@ -1153,7 +1152,7 @@ func TestRealTimeAndSetupTeardownMetrics(t *testing.T) { options, err := executor.DeriveScenariosFromShortcuts(runner.GetOptions().Apply(lib.Options{ Iterations: null.IntFrom(2), VUs: null.IntFrom(1), - SystemTags: &stats.DefaultSystemTagSet, + SystemTags: &metrics.DefaultSystemTagSet, SetupTimeout: types.NullDurationFrom(4 * time.Second), TeardownTimeout: types.NullDurationFrom(4 * time.Second), }), nil) @@ -1167,14 +1166,14 @@ func TestRealTimeAndSetupTeardownMetrics(t *testing.T) { defer cancel() done := make(chan struct{}) - sampleContainers := make(chan stats.SampleContainer) + sampleContainers := make(chan metrics.SampleContainer) go func() { require.NoError(t, execScheduler.Init(ctx, sampleContainers)) assert.NoError(t, execScheduler.Run(ctx, ctx, sampleContainers)) close(done) }() - expectIn := func(from, to time.Duration, expected stats.SampleContainer) { + expectIn := func(from, to time.Duration, expected metrics.SampleContainer) { start := time.Now() from *= time.Millisecond to *= time.Millisecond @@ -1220,24 +1219,24 @@ func TestRealTimeAndSetupTeardownMetrics(t *testing.T) { } } - getTags := func(args ...string) *stats.SampleTags { + getTags := func(args ...string) *metrics.SampleTags { tags := map[string]string{} for i := 0; i < len(args)-1; i += 2 { tags[args[i]] = args[i+1] } - return stats.IntoSampleTags(&tags) + return metrics.IntoSampleTags(&tags) } - testCounter, err := registry.NewMetric("test_counter", stats.Counter) + testCounter, err := registry.NewMetric("test_counter", metrics.Counter) require.NoError(t, err) - getSample := func(expValue float64, expMetric *stats.Metric, expTags ...string) stats.SampleContainer { - return stats.Sample{ + getSample := func(expValue float64, expMetric *metrics.Metric, expTags ...string) metrics.SampleContainer { + return metrics.Sample{ Metric: expMetric, Time: time.Now(), Tags: getTags(expTags...), Value: expValue, } } - getDummyTrail := func(group string, emitIterations bool, addExpTags ...string) stats.SampleContainer { + getDummyTrail := func(group string, emitIterations bool, addExpTags ...string) metrics.SampleContainer { expTags := []string{"group", group} expTags = append(expTags, addExpTags...) return netext.NewDialer( diff --git a/js/console_test.go b/js/console_test.go index fc2bc220c1f..35e992f7d63 100644 --- a/js/console_test.go +++ b/js/console_test.go @@ -40,7 +40,6 @@ import ( "go.k6.io/k6/lib/testutils" "go.k6.io/k6/loader" "go.k6.io/k6/metrics" - "go.k6.io/k6/stats" ) func TestConsoleContext(t *testing.T) { @@ -137,7 +136,7 @@ func TestConsole(t *testing.T) { )) assert.NoError(t, err) - samples := make(chan stats.SampleContainer, 100) + samples := make(chan metrics.SampleContainer, 100) initVU, err := r.newVU(1, 1, samples) assert.NoError(t, err) @@ -239,7 +238,7 @@ func TestFileConsole(t *testing.T) { }) assert.NoError(t, err) - samples := make(chan stats.SampleContainer, 100) + samples := make(chan metrics.SampleContainer, 100) initVU, err := r.newVU(1, 1, samples) assert.NoError(t, err) diff --git a/js/empty_iterations_bench_test.go b/js/empty_iterations_bench_test.go index a2c6490d508..9c4e67d8f6b 100644 --- a/js/empty_iterations_bench_test.go +++ b/js/empty_iterations_bench_test.go @@ -28,7 +28,7 @@ import ( "github.com/stretchr/testify/require" "go.k6.io/k6/lib" - "go.k6.io/k6/stats" + "go.k6.io/k6/metrics" ) func BenchmarkEmptyIteration(b *testing.B) { @@ -40,7 +40,7 @@ func BenchmarkEmptyIteration(b *testing.B) { } require.NoError(b, err) - ch := make(chan stats.SampleContainer, 100) + ch := make(chan metrics.SampleContainer, 100) defer close(ch) go func() { // read the channel so it doesn't block for range ch { diff --git a/js/http_bench_test.go b/js/http_bench_test.go index 99415406f13..fc14418f7b4 100644 --- a/js/http_bench_test.go +++ b/js/http_bench_test.go @@ -30,7 +30,7 @@ import ( "go.k6.io/k6/lib" "go.k6.io/k6/lib/testutils/httpmultibin" - "go.k6.io/k6/stats" + "go.k6.io/k6/metrics" ) func BenchmarkHTTPRequests(b *testing.B) { @@ -56,7 +56,7 @@ func BenchmarkHTTPRequests(b *testing.B) { }) require.NoError(b, err) - ch := make(chan stats.SampleContainer, 100) + ch := make(chan metrics.SampleContainer, 100) defer close(ch) go func() { // read the channel so it doesn't block for range ch { @@ -99,7 +99,7 @@ func BenchmarkHTTPRequestsBase(b *testing.B) { }) require.NoError(b, err) - ch := make(chan stats.SampleContainer, 100) + ch := make(chan metrics.SampleContainer, 100) defer close(ch) go func() { // read the channel so it doesn't block for range ch { diff --git a/js/init_and_modules_test.go b/js/init_and_modules_test.go index 7e7c9fe7b0f..72d5f8010ef 100644 --- a/js/init_and_modules_test.go +++ b/js/init_and_modules_test.go @@ -39,7 +39,6 @@ import ( "go.k6.io/k6/lib/testutils" "go.k6.io/k6/loader" "go.k6.io/k6/metrics" - "go.k6.io/k6/stats" ) type CheckModule struct { @@ -93,7 +92,7 @@ func TestNewJSRunnerWithCustomModule(t *testing.T) { assert.Equal(t, checkModule.initCtxCalled, 1) assert.Equal(t, checkModule.vuCtxCalled, 0) - vu, err := runner.NewVU(1, 1, make(chan stats.SampleContainer, 100)) + vu, err := runner.NewVU(1, 1, make(chan metrics.SampleContainer, 100)) require.NoError(t, err) assert.Equal(t, checkModule.initCtxCalled, 2) assert.Equal(t, checkModule.vuCtxCalled, 0) @@ -117,7 +116,7 @@ func TestNewJSRunnerWithCustomModule(t *testing.T) { require.NoError(t, err) assert.Equal(t, checkModule.initCtxCalled, 3) // changes because we need to get the exported functions assert.Equal(t, checkModule.vuCtxCalled, 2) - vuFromArc, err := runnerFromArc.NewVU(2, 2, make(chan stats.SampleContainer, 100)) + vuFromArc, err := runnerFromArc.NewVU(2, 2, make(chan metrics.SampleContainer, 100)) require.NoError(t, err) assert.Equal(t, checkModule.initCtxCalled, 4) assert.Equal(t, checkModule.vuCtxCalled, 2) diff --git a/js/initcontext_test.go b/js/initcontext_test.go index 8a941f42171..c1999c8ab65 100644 --- a/js/initcontext_test.go +++ b/js/initcontext_test.go @@ -44,7 +44,6 @@ import ( "go.k6.io/k6/lib/testutils" "go.k6.io/k6/lib/types" "go.k6.io/k6/metrics" - "go.k6.io/k6/stats" ) func TestInitContextRequire(t *testing.T) { @@ -405,7 +404,7 @@ func TestRequestWithBinaryFile(t *testing.T) { )).DialContext, }, BPool: bpool.NewBufferPool(1), - Samples: make(chan stats.SampleContainer, 500), + Samples: make(chan metrics.SampleContainer, 500), BuiltinMetrics: builtinMetrics, Tags: lib.NewTagMap(nil), } @@ -553,7 +552,7 @@ func TestRequestWithMultipleBinaryFiles(t *testing.T) { )).DialContext, }, BPool: bpool.NewBufferPool(1), - Samples: make(chan stats.SampleContainer, 500), + Samples: make(chan metrics.SampleContainer, 500), BuiltinMetrics: builtinMetrics, Tags: lib.NewTagMap(nil), } diff --git a/js/module_loading_test.go b/js/module_loading_test.go index ae601dbe09e..47a52c8237d 100644 --- a/js/module_loading_test.go +++ b/js/module_loading_test.go @@ -34,11 +34,10 @@ import ( "go.k6.io/k6/lib/testutils" "go.k6.io/k6/lib/testutils/httpmultibin" "go.k6.io/k6/metrics" - "go.k6.io/k6/stats" ) -func newDevNullSampleChannel() chan stats.SampleContainer { - ch := make(chan stats.SampleContainer, 100) +func newDevNullSampleChannel() chan metrics.SampleContainer { + ch := make(chan metrics.SampleContainer, 100) go func() { for range ch { } @@ -468,7 +467,7 @@ func TestBrowserified(t *testing.T) { r := r t.Run(name, func(t *testing.T) { t.Parallel() - ch := make(chan stats.SampleContainer, 100) + ch := make(chan metrics.SampleContainer, 100) defer close(ch) initVU, err := r.NewVU(1, 1, ch) require.NoError(t, err) diff --git a/js/modules/k6/execution/execution_test.go b/js/modules/k6/execution/execution_test.go index e4f8507f971..85b3784f667 100644 --- a/js/modules/k6/execution/execution_test.go +++ b/js/modules/k6/execution/execution_test.go @@ -34,7 +34,7 @@ import ( "go.k6.io/k6/js/modulestest" "go.k6.io/k6/lib" "go.k6.io/k6/lib/testutils" - "go.k6.io/k6/stats" + "go.k6.io/k6/metrics" "gopkg.in/guregu/null.v3" ) @@ -52,7 +52,7 @@ func setupTagsExecEnv(t *testing.T) execEnv { state := &lib.State{ Options: lib.Options{ - SystemTags: stats.NewSystemTagSet(stats.TagVU), + SystemTags: metrics.NewSystemTagSet(metrics.TagVU), }, Tags: lib.NewTagMap(map[string]string{ "vu": "42", diff --git a/js/modules/k6/grpc/client.go b/js/modules/k6/grpc/client.go index 1f74e6ac5b0..a7c28d079a4 100644 --- a/js/modules/k6/grpc/client.go +++ b/js/modules/k6/grpc/client.go @@ -55,7 +55,7 @@ import ( "go.k6.io/k6/js/common" "go.k6.io/k6/js/modules" "go.k6.io/k6/lib/types" - "go.k6.io/k6/stats" + "go.k6.io/k6/metrics" reflectpb "google.golang.org/grpc/reflection/grpc_reflection_v1alpha" ) @@ -482,19 +482,19 @@ func (c *Client) Invoke( tags[k] = v } - if state.Options.SystemTags.Has(stats.TagURL) { + if state.Options.SystemTags.Has(metrics.TagURL) { tags["url"] = fmt.Sprintf("%s%s", c.conn.Target(), method) } parts := strings.Split(method[1:], "/") - if state.Options.SystemTags.Has(stats.TagService) { + if state.Options.SystemTags.Has(metrics.TagService) { tags["service"] = parts[0] } - if state.Options.SystemTags.Has(stats.TagMethod) { + if state.Options.SystemTags.Has(metrics.TagMethod) { tags["method"] = parts[1] } // Only set the name system tag if the user didn't explicitly set it beforehand - if _, ok := tags["name"]; !ok && state.Options.SystemTags.Has(stats.TagName) { + if _, ok := tags["name"]; !ok && state.Options.SystemTags.Has(metrics.TagName) { tags["name"] = method } @@ -574,47 +574,47 @@ func (c *Client) Close() error { return err } -// TagConn implements the stats.Handler interface +// TagConn implements the metrics.Handler interface func (*Client) TagConn(ctx context.Context, _ *grpcstats.ConnTagInfo) context.Context { // noop return ctx } -// HandleConn implements the stats.Handler interface +// HandleConn implements the metrics.Handler interface func (*Client) HandleConn(context.Context, grpcstats.ConnStats) { // noop } -// TagRPC implements the stats.Handler interface +// TagRPC implements the metrics.Handler interface func (*Client) TagRPC(ctx context.Context, _ *grpcstats.RPCTagInfo) context.Context { // noop return ctx } -// HandleRPC implements the stats.Handler interface +// HandleRPC implements the metrics.Handler interface func (c *Client) HandleRPC(ctx context.Context, stat grpcstats.RPCStats) { state := c.vu.State() tags := getTags(ctx) switch s := stat.(type) { case *grpcstats.OutHeader: - if state.Options.SystemTags.Has(stats.TagIP) && s.RemoteAddr != nil { + if state.Options.SystemTags.Has(metrics.TagIP) && s.RemoteAddr != nil { if ip, _, err := net.SplitHostPort(s.RemoteAddr.String()); err == nil { tags["ip"] = ip } } case *grpcstats.End: - if state.Options.SystemTags.Has(stats.TagStatus) { + if state.Options.SystemTags.Has(metrics.TagStatus) { tags["status"] = strconv.Itoa(int(status.Code(s.Error))) } mTags := map[string]string(tags) - sampleTags := stats.IntoSampleTags(&mTags) - stats.PushIfNotDone(ctx, state.Samples, stats.ConnectedSamples{ - Samples: []stats.Sample{ + sampleTags := metrics.IntoSampleTags(&mTags) + metrics.PushIfNotDone(ctx, state.Samples, metrics.ConnectedSamples{ + Samples: []metrics.Sample{ { Metric: state.BuiltinMetrics.GRPCReqDuration, Tags: sampleTags, - Value: stats.D(s.EndTime.Sub(s.BeginTime)), + Value: metrics.D(s.EndTime.Sub(s.BeginTime)), Time: s.EndTime, }, }, diff --git a/js/modules/k6/grpc/client_test.go b/js/modules/k6/grpc/client_test.go index d34c1fbb2c2..d3dfe8ad985 100644 --- a/js/modules/k6/grpc/client_test.go +++ b/js/modules/k6/grpc/client_test.go @@ -59,7 +59,6 @@ import ( "go.k6.io/k6/lib/testutils" "go.k6.io/k6/lib/testutils/httpmultibin" "go.k6.io/k6/metrics" - "go.k6.io/k6/stats" ) const isWindows = runtime.GOOS == "windows" @@ -70,7 +69,7 @@ type codeBlock struct { val interface{} err string windowsErr string - asserts func(*testing.T, *httpmultibin.HTTPMultiBin, chan stats.SampleContainer, error) + asserts func(*testing.T, *httpmultibin.HTTPMultiBin, chan metrics.SampleContainer, error) } type testcase struct { @@ -88,7 +87,7 @@ func TestClient(t *testing.T) { vuState *lib.State env *common.InitEnvironment httpBin *httpmultibin.HTTPMultiBin - samples chan stats.SampleContainer + samples chan metrics.SampleContainer } setup := func(t *testing.T) testState { t.Helper() @@ -96,16 +95,16 @@ func TestClient(t *testing.T) { root, err := lib.NewGroup("", nil) require.NoError(t, err) tb := httpmultibin.NewHTTPMultiBin(t) - samples := make(chan stats.SampleContainer, 1000) + samples := make(chan metrics.SampleContainer, 1000) state := &lib.State{ Group: root, Dialer: tb.Dialer, TLSConfig: tb.TLSClientConfig, Samples: samples, Options: lib.Options{ - SystemTags: stats.NewSystemTagSet( - stats.TagName, - stats.TagURL, + SystemTags: metrics.NewSystemTagSet( + metrics.TagName, + metrics.TagURL, ), UserAgent: null.StringFrom("k6-test"), }, @@ -144,7 +143,7 @@ func TestClient(t *testing.T) { assertMetricEmitted := func( t *testing.T, metricName string, - sampleContainers []stats.SampleContainer, + sampleContainers []metrics.SampleContainer, url string, ) { seenMetric := false @@ -391,8 +390,8 @@ func TestClient(t *testing.T) { if (resp.status !== grpc.StatusOK) { throw new Error("unexpected error status: " + resp.status) }`, - asserts: func(t *testing.T, rb *httpmultibin.HTTPMultiBin, samples chan stats.SampleContainer, _ error) { - samplesBuf := stats.GetBufferedSamples(samples) + asserts: func(t *testing.T, rb *httpmultibin.HTTPMultiBin, samples chan metrics.SampleContainer, _ error) { + samplesBuf := metrics.GetBufferedSamples(samples) assertMetricEmitted(t, metrics.GRPCReqDurationName, samplesBuf, rb.Replacer.Replace("GRPCBIN_ADDR/grpc.testing.TestService/EmptyCall")) }, }, @@ -465,8 +464,8 @@ func TestClient(t *testing.T) { if (!resp.message || resp.message.username !== "" || resp.message.oauthScope !== "水") { throw new Error("unexpected response message: " + JSON.stringify(resp.message)) }`, - asserts: func(t *testing.T, rb *httpmultibin.HTTPMultiBin, samples chan stats.SampleContainer, _ error) { - samplesBuf := stats.GetBufferedSamples(samples) + asserts: func(t *testing.T, rb *httpmultibin.HTTPMultiBin, samples chan metrics.SampleContainer, _ error) { + samplesBuf := metrics.GetBufferedSamples(samples) assertMetricEmitted(t, metrics.GRPCReqDurationName, samplesBuf, rb.Replacer.Replace("GRPCBIN_ADDR/grpc.testing.TestService/UnaryCall")) }, }, @@ -493,8 +492,8 @@ func TestClient(t *testing.T) { if (!resp.error || resp.error.message !== "foobar" || resp.error.code !== 15) { throw new Error("unexpected error object: " + JSON.stringify(resp.error.code)) }`, - asserts: func(t *testing.T, rb *httpmultibin.HTTPMultiBin, samples chan stats.SampleContainer, _ error) { - samplesBuf := stats.GetBufferedSamples(samples) + asserts: func(t *testing.T, rb *httpmultibin.HTTPMultiBin, samples chan metrics.SampleContainer, _ error) { + samplesBuf := metrics.GetBufferedSamples(samples) assertMetricEmitted(t, metrics.GRPCReqDurationName, samplesBuf, rb.Replacer.Replace("GRPCBIN_ADDR/grpc.testing.TestService/EmptyCall")) }, }, @@ -523,8 +522,8 @@ func TestClient(t *testing.T) { if (!resp.headers || !resp.headers["foo"] || resp.headers["foo"][0] !== "bar") { throw new Error("unexpected headers object: " + JSON.stringify(resp.trailers)) }`, - asserts: func(t *testing.T, rb *httpmultibin.HTTPMultiBin, samples chan stats.SampleContainer, _ error) { - samplesBuf := stats.GetBufferedSamples(samples) + asserts: func(t *testing.T, rb *httpmultibin.HTTPMultiBin, samples chan metrics.SampleContainer, _ error) { + samplesBuf := metrics.GetBufferedSamples(samples) assertMetricEmitted(t, metrics.GRPCReqDurationName, samplesBuf, rb.Replacer.Replace("GRPCBIN_ADDR/grpc.testing.TestService/EmptyCall")) }, }, @@ -553,8 +552,8 @@ func TestClient(t *testing.T) { if (!resp.trailers || !resp.trailers["foo"] || resp.trailers["foo"][0] !== "bar") { throw new Error("unexpected trailers object: " + JSON.stringify(resp.trailers)) }`, - asserts: func(t *testing.T, rb *httpmultibin.HTTPMultiBin, samples chan stats.SampleContainer, _ error) { - samplesBuf := stats.GetBufferedSamples(samples) + asserts: func(t *testing.T, rb *httpmultibin.HTTPMultiBin, samples chan metrics.SampleContainer, _ error) { + samplesBuf := metrics.GetBufferedSamples(samples) assertMetricEmitted(t, metrics.GRPCReqDurationName, samplesBuf, rb.Replacer.Replace("GRPCBIN_ADDR/grpc.testing.TestService/EmptyCall")) }, }, diff --git a/js/modules/k6/http/request_test.go b/js/modules/k6/http/request_test.go index d98f447f37a..cfc1851abfd 100644 --- a/js/modules/k6/http/request_test.go +++ b/js/modules/k6/http/request_test.go @@ -53,11 +53,10 @@ import ( "go.k6.io/k6/lib/testutils" "go.k6.io/k6/lib/testutils/httpmultibin" "go.k6.io/k6/metrics" - "go.k6.io/k6/stats" ) // TODO replace this with the Single version -func assertRequestMetricsEmitted(t *testing.T, sampleContainers []stats.SampleContainer, method, url, name string, status int, group string) { +func assertRequestMetricsEmitted(t *testing.T, sampleContainers []metrics.SampleContainer, method, url, name string, status int, group string) { if name == "" { name = url } @@ -106,7 +105,7 @@ func assertRequestMetricsEmitted(t *testing.T, sampleContainers []stats.SampleCo assert.True(t, seenReceiving, "url %s didn't emit Receiving", url) } -func assertRequestMetricsEmittedSingle(t *testing.T, sampleContainer stats.SampleContainer, expectedTags map[string]string, metrics []string, callback func(sample stats.Sample)) { +func assertRequestMetricsEmittedSingle(t *testing.T, sampleContainer metrics.SampleContainer, expectedTags map[string]string, metrics []string, callback func(sample metrics.Sample)) { t.Helper() metricMap := make(map[string]bool, len(metrics)) @@ -130,7 +129,7 @@ func assertRequestMetricsEmittedSingle(t *testing.T, sampleContainer stats.Sampl } func newRuntime(t testing.TB) ( - *httpmultibin.HTTPMultiBin, *lib.State, chan stats.SampleContainer, *goja.Runtime, *ModuleInstance, + *httpmultibin.HTTPMultiBin, *lib.State, chan metrics.SampleContainer, *goja.Runtime, *ModuleInstance, ) { tb := httpmultibin.NewHTTPMultiBin(t) @@ -145,12 +144,12 @@ func newRuntime(t testing.TB) ( MaxRedirects: null.IntFrom(10), UserAgent: null.StringFrom("TestUserAgent"), Throw: null.BoolFrom(true), - SystemTags: &stats.DefaultSystemTagSet, + SystemTags: &metrics.DefaultSystemTagSet, Batch: null.IntFrom(20), BatchPerHost: null.IntFrom(20), // HTTPDebug: null.StringFrom("full"), } - samples := make(chan stats.SampleContainer, 1000) + samples := make(chan metrics.SampleContainer, 1000) state := &lib.State{ Options: options, @@ -186,7 +185,7 @@ func TestRequestAndBatch(t *testing.T) { var res = http.get("HTTPBIN_URL/redirect/9"); `)) assert.NoError(t, err) - bufSamples := stats.GetBufferedSamples(samples) + bufSamples := metrics.GetBufferedSamples(samples) reqsCount := 0 for _, container := range bufSamples { @@ -479,7 +478,7 @@ func TestRequestAndBatch(t *testing.T) { }) }) t.Run("HTTP/2", func(t *testing.T) { - stats.GetBufferedSamples(samples) // Clean up buffered samples from previous tests + metrics.GetBufferedSamples(samples) // Clean up buffered samples from previous tests _, err := rt.RunString(sr(` var res = http.request("GET", "HTTP2BIN_URL/get"); if (res.status != 200) { throw new Error("wrong status: " + res.status) } @@ -487,7 +486,7 @@ func TestRequestAndBatch(t *testing.T) { `)) assert.NoError(t, err) - bufSamples := stats.GetBufferedSamples(samples) + bufSamples := metrics.GetBufferedSamples(samples) assertRequestMetricsEmitted(t, bufSamples, "GET", sr("HTTP2BIN_URL/get"), "", 200, "") for _, sampleC := range bufSamples { for _, sample := range sampleC.GetSamples() { @@ -616,7 +615,7 @@ func TestRequestAndBatch(t *testing.T) { if (res.status != 200) { throw new Error("wrong status: " + res.status); } `), literal)) assert.NoError(t, err) - assertRequestMetricsEmitted(t, stats.GetBufferedSamples(samples), "GET", sr("HTTPBIN_URL/headers"), "", 200, "") + assertRequestMetricsEmitted(t, metrics.GetBufferedSamples(samples), "GET", sr("HTTPBIN_URL/headers"), "", 200, "") }) } @@ -640,7 +639,7 @@ func TestRequestAndBatch(t *testing.T) { } `)) assert.NoError(t, err) - assertRequestMetricsEmitted(t, stats.GetBufferedSamples(samples), "GET", sr("HTTPBIN_URL/cookies/set?key=value"), "", 302, "") + assertRequestMetricsEmitted(t, metrics.GetBufferedSamples(samples), "GET", sr("HTTPBIN_URL/cookies/set?key=value"), "", 302, "") }) t.Run("vuJar", func(t *testing.T) { @@ -658,7 +657,7 @@ func TestRequestAndBatch(t *testing.T) { if (jarCookies.key2 != undefined) { throw new Error("unexpected cookie in jar"); } `)) assert.NoError(t, err) - assertRequestMetricsEmitted(t, stats.GetBufferedSamples(samples), "GET", sr("HTTPBIN_URL/cookies"), "", 200, "") + assertRequestMetricsEmitted(t, metrics.GetBufferedSamples(samples), "GET", sr("HTTPBIN_URL/cookies"), "", 200, "") }) t.Run("requestScope", func(t *testing.T) { @@ -673,7 +672,7 @@ func TestRequestAndBatch(t *testing.T) { if (jarCookies.key != undefined) { throw new Error("unexpected cookie in jar"); } `)) assert.NoError(t, err) - assertRequestMetricsEmitted(t, stats.GetBufferedSamples(samples), "GET", sr("HTTPBIN_URL/cookies"), "", 200, "") + assertRequestMetricsEmitted(t, metrics.GetBufferedSamples(samples), "GET", sr("HTTPBIN_URL/cookies"), "", 200, "") }) t.Run("requestScopeReplace", func(t *testing.T) { @@ -689,7 +688,7 @@ func TestRequestAndBatch(t *testing.T) { if (jarCookies.key[0] != "value") { throw new Error("wrong cookie value in jar"); } `)) assert.NoError(t, err) - assertRequestMetricsEmitted(t, stats.GetBufferedSamples(samples), "GET", sr("HTTPBIN_URL/cookies"), "", 200, "") + assertRequestMetricsEmitted(t, metrics.GetBufferedSamples(samples), "GET", sr("HTTPBIN_URL/cookies"), "", 200, "") }) t.Run("redirect", func(t *testing.T) { @@ -723,7 +722,7 @@ func TestRequestAndBatch(t *testing.T) { assertRequestMetricsEmitted( t, - stats.GetBufferedSamples(samples), + metrics.GetBufferedSamples(samples), "GET", sr("HTTPSBIN_URL/set-cookie-without-redirect"), sr("HTTPSBIN_URL/set-cookie-without-redirect"), @@ -750,7 +749,7 @@ func TestRequestAndBatch(t *testing.T) { assertRequestMetricsEmitted( t, - stats.GetBufferedSamples(samples), + metrics.GetBufferedSamples(samples), "GET", sr("HTTPSBIN_URL/cookies"), sr("HTTPSBIN_URL/cookies"), @@ -797,7 +796,7 @@ func TestRequestAndBatch(t *testing.T) { assertRequestMetricsEmitted( t, - stats.GetBufferedSamples(samples), + metrics.GetBufferedSamples(samples), "GET", sr("HTTPBIN_IP_URL/get"), sr("HTTPBIN_IP_URL/get"), @@ -828,7 +827,7 @@ func TestRequestAndBatch(t *testing.T) { } `)) assert.NoError(t, err) - assertRequestMetricsEmitted(t, stats.GetBufferedSamples(samples), "GET", sr("HTTPBIN_URL/cookies"), "", 200, "") + assertRequestMetricsEmitted(t, metrics.GetBufferedSamples(samples), "GET", sr("HTTPBIN_URL/cookies"), "", 200, "") }) t.Run("path", func(t *testing.T) { @@ -852,7 +851,7 @@ func TestRequestAndBatch(t *testing.T) { } `)) assert.NoError(t, err) - assertRequestMetricsEmitted(t, stats.GetBufferedSamples(samples), "GET", sr("HTTPBIN_URL/cookies"), "", 200, "") + assertRequestMetricsEmitted(t, metrics.GetBufferedSamples(samples), "GET", sr("HTTPBIN_URL/cookies"), "", 200, "") }) t.Run("expires", func(t *testing.T) { @@ -873,7 +872,7 @@ func TestRequestAndBatch(t *testing.T) { } `)) assert.NoError(t, err) - assertRequestMetricsEmitted(t, stats.GetBufferedSamples(samples), "GET", sr("HTTPBIN_URL/cookies"), "", 200, "") + assertRequestMetricsEmitted(t, metrics.GetBufferedSamples(samples), "GET", sr("HTTPBIN_URL/cookies"), "", 200, "") }) t.Run("secure", func(t *testing.T) { @@ -889,7 +888,7 @@ func TestRequestAndBatch(t *testing.T) { } `)) assert.NoError(t, err) - assertRequestMetricsEmitted(t, stats.GetBufferedSamples(samples), "GET", sr("HTTPSBIN_IP_URL/cookies"), "", 200, "") + assertRequestMetricsEmitted(t, metrics.GetBufferedSamples(samples), "GET", sr("HTTPSBIN_IP_URL/cookies"), "", 200, "") }) t.Run("localJar", func(t *testing.T) { @@ -907,7 +906,7 @@ func TestRequestAndBatch(t *testing.T) { if (jarCookies.key2 != undefined) { throw new Error("unexpected cookie in jar"); } `)) assert.NoError(t, err) - assertRequestMetricsEmitted(t, stats.GetBufferedSamples(samples), "GET", sr("HTTPBIN_URL/cookies"), "", 200, "") + assertRequestMetricsEmitted(t, metrics.GetBufferedSamples(samples), "GET", sr("HTTPBIN_URL/cookies"), "", 200, "") }) }) @@ -921,7 +920,7 @@ func TestRequestAndBatch(t *testing.T) { if (res.status != 200) { throw new Error("wrong status: " + res.status); } `, url)) assert.NoError(t, err) - assertRequestMetricsEmitted(t, stats.GetBufferedSamples(samples), "GET", urlExpected, urlExpected, 200, "") + assertRequestMetricsEmitted(t, metrics.GetBufferedSamples(samples), "GET", urlExpected, urlExpected, 200, "") }) t.Run("digest", func(t *testing.T) { t.Run("success", func(t *testing.T) { @@ -935,7 +934,7 @@ func TestRequestAndBatch(t *testing.T) { `, url)) assert.NoError(t, err) - sampleContainers := stats.GetBufferedSamples(samples) + sampleContainers := metrics.GetBufferedSamples(samples) assertRequestMetricsEmitted(t, sampleContainers[0:1], "GET", urlRaw, urlRaw, 401, "") assertRequestMetricsEmitted(t, sampleContainers[1:2], "GET", @@ -960,7 +959,7 @@ func TestRequestAndBatch(t *testing.T) { if (res.status != 200) { throw new Error("wrong status: " + res.status); } `), literal)) assert.NoError(t, err) - assertRequestMetricsEmitted(t, stats.GetBufferedSamples(samples), "GET", sr("HTTPBIN_URL/headers"), "", 200, "") + assertRequestMetricsEmitted(t, metrics.GetBufferedSamples(samples), "GET", sr("HTTPBIN_URL/headers"), "", 200, "") }) } @@ -973,7 +972,7 @@ func TestRequestAndBatch(t *testing.T) { if (res.json().headers["X-My-Header"] != "value") { throw new Error("wrong X-My-Header: " + res.json().headers["X-My-Header"]); } `)) assert.NoError(t, err) - assertRequestMetricsEmitted(t, stats.GetBufferedSamples(samples), "GET", sr("HTTPBIN_URL/headers"), "", 200, "") + assertRequestMetricsEmitted(t, metrics.GetBufferedSamples(samples), "GET", sr("HTTPBIN_URL/headers"), "", 200, "") }) t.Run("Host", func(t *testing.T) { @@ -985,7 +984,7 @@ func TestRequestAndBatch(t *testing.T) { if (res.json().headers["Host"] != "HTTPBIN_DOMAIN") { throw new Error("wrong Host: " + res.json().headers["Host"]); } `)) assert.NoError(t, err) - assertRequestMetricsEmitted(t, stats.GetBufferedSamples(samples), "GET", sr("HTTPBIN_URL/headers"), "", 200, "") + assertRequestMetricsEmitted(t, metrics.GetBufferedSamples(samples), "GET", sr("HTTPBIN_URL/headers"), "", 200, "") }) t.Run("response_request", func(t *testing.T) { @@ -997,7 +996,7 @@ func TestRequestAndBatch(t *testing.T) { if (res.request.headers["Host"] != "HTTPBIN_DOMAIN") { throw new Error("wrong Host: " + res.request.headers["Host"]); } `)) assert.NoError(t, err) - assertRequestMetricsEmitted(t, stats.GetBufferedSamples(samples), "GET", sr("HTTPBIN_URL/headers"), "", 200, "") + assertRequestMetricsEmitted(t, metrics.GetBufferedSamples(samples), "GET", sr("HTTPBIN_URL/headers"), "", 200, "") }) t.Run("differentHost", func(t *testing.T) { @@ -1010,7 +1009,7 @@ func TestRequestAndBatch(t *testing.T) { if (res.request.headers["Host"] != custHost) { throw new Error("wrong Host: " + res.request.headers["Host"]); } `)) assert.NoError(t, err) - assertRequestMetricsEmitted(t, stats.GetBufferedSamples(samples), "GET", sr("HTTPBIN_URL/headers"), "", 200, "") + assertRequestMetricsEmitted(t, metrics.GetBufferedSamples(samples), "GET", sr("HTTPBIN_URL/headers"), "", 200, "") }) }) @@ -1022,7 +1021,7 @@ func TestRequestAndBatch(t *testing.T) { if (res.status != 200) { throw new Error("wrong status: " + res.status); } `), literal)) assert.NoError(t, err) - assertRequestMetricsEmitted(t, stats.GetBufferedSamples(samples), "GET", sr("HTTPBIN_URL/headers"), "", 200, "") + assertRequestMetricsEmitted(t, metrics.GetBufferedSamples(samples), "GET", sr("HTTPBIN_URL/headers"), "", 200, "") }) } @@ -1032,7 +1031,7 @@ func TestRequestAndBatch(t *testing.T) { if (res.status != 200) { throw new Error("wrong status: " + res.status); } `)) assert.NoError(t, err) - assertRequestMetricsEmitted(t, stats.GetBufferedSamples(samples), "GET", + assertRequestMetricsEmitted(t, metrics.GetBufferedSamples(samples), "GET", sr("HTTPBIN_URL/headers"), sr("HTTPBIN_URL/headers"), 200, "") }) @@ -1042,7 +1041,7 @@ func TestRequestAndBatch(t *testing.T) { if (res.status != 200) { throw new Error("wrong status: " + res.status); } `)) assert.NoError(t, err) - assertRequestMetricsEmitted(t, stats.GetBufferedSamples(samples), "GET", + assertRequestMetricsEmitted(t, metrics.GetBufferedSamples(samples), "GET", sr("HTTPBIN_URL/headers"), "myReq", 200, "") }) @@ -1051,7 +1050,7 @@ func TestRequestAndBatch(t *testing.T) { assert.NoError(t, err) // There's no /anything endpoint in the go-httpbin library we're using, hence the 404, // but it doesn't matter for this test. - assertRequestMetricsEmitted(t, stats.GetBufferedSamples(samples), "GET", + assertRequestMetricsEmitted(t, metrics.GetBufferedSamples(samples), "GET", sr("HTTPBIN_URL/anything/2"), sr("HTTPBIN_URL/anything/${}"), 404, "") }) @@ -1061,7 +1060,7 @@ func TestRequestAndBatch(t *testing.T) { if (res.status != 200) { throw new Error("wrong status: " + res.status); } `)) assert.NoError(t, err) - bufSamples := stats.GetBufferedSamples(samples) + bufSamples := metrics.GetBufferedSamples(samples) assertRequestMetricsEmitted(t, bufSamples, "GET", sr("HTTPBIN_URL/headers"), "", 200, "") for _, sampleC := range bufSamples { for _, sample := range sampleC.GetSamples() { @@ -1086,7 +1085,7 @@ func TestRequestAndBatch(t *testing.T) { `)) assert.NoError(t, err) - bufSamples := stats.GetBufferedSamples(samples) + bufSamples := metrics.GetBufferedSamples(samples) assertRequestMetricsEmitted(t, bufSamples, "GET", sr("HTTPBIN_URL/headers"), "myName", 200, "") for _, sampleC := range bufSamples { for _, sample := range sampleC.GetSamples() { @@ -1120,7 +1119,7 @@ func TestRequestAndBatch(t *testing.T) { if (res.request.headers["X-We-Want-This"] != "value") { throw new Error("Missing or invalid X-We-Want-This header!"); } `)) require.NoError(t, err) - assertRequestMetricsEmitted(t, stats.GetBufferedSamples(samples), "GET", sr("HTTPBIN_URL/get?a=1&b=2"), "", 200, "") + assertRequestMetricsEmitted(t, metrics.GetBufferedSamples(samples), "GET", sr("HTTPBIN_URL/get?a=1&b=2"), "", 200, "") t.Run("Tagged", func(t *testing.T) { _, err := rt.RunString(` @@ -1132,7 +1131,7 @@ func TestRequestAndBatch(t *testing.T) { if (res.json().args.b != b) { throw new Error("wrong ?b: " + res.json().args.b); } `) assert.NoError(t, err) - assertRequestMetricsEmitted(t, stats.GetBufferedSamples(samples), "GET", sr("HTTPBIN_URL/get?a=1&b=2"), sr("HTTPBIN_URL/get?a=${}&b=${}"), 200, "") + assertRequestMetricsEmitted(t, metrics.GetBufferedSamples(samples), "GET", sr("HTTPBIN_URL/get?a=1&b=2"), sr("HTTPBIN_URL/get?a=${}&b=${}"), 200, "") }) }) t.Run("HEAD", func(t *testing.T) { @@ -1144,7 +1143,7 @@ func TestRequestAndBatch(t *testing.T) { if (res.request.headers["X-We-Want-This"] != "value") { throw new Error("Missing or invalid X-We-Want-This header!"); } `)) assert.NoError(t, err) - assertRequestMetricsEmitted(t, stats.GetBufferedSamples(samples), "HEAD", sr("HTTPBIN_URL/get?a=1&b=2"), "", 200, "") + assertRequestMetricsEmitted(t, metrics.GetBufferedSamples(samples), "HEAD", sr("HTTPBIN_URL/get?a=1&b=2"), "", 200, "") }) t.Run("OPTIONS", func(t *testing.T) { @@ -1155,7 +1154,7 @@ func TestRequestAndBatch(t *testing.T) { if (res.request.headers["X-We-Want-This"] != "value") { throw new Error("Missing or invalid X-We-Want-This header!"); } `)) require.NoError(t, err) - assertRequestMetricsEmitted(t, stats.GetBufferedSamples(samples), "OPTIONS", sr("HTTPBIN_URL/?a=1&b=2"), "", 200, "") + assertRequestMetricsEmitted(t, metrics.GetBufferedSamples(samples), "OPTIONS", sr("HTTPBIN_URL/?a=1&b=2"), "", 200, "") }) // DELETE HTTP requests shouldn't usually send a request body, they should use url parameters instead; references: @@ -1170,7 +1169,7 @@ func TestRequestAndBatch(t *testing.T) { if (res.request.headers["X-We-Want-This"] != "value") { throw new Error("Missing or invalid X-We-Want-This header!"); } `)) require.NoError(t, err) - assertRequestMetricsEmitted(t, stats.GetBufferedSamples(samples), "DELETE", sr("HTTPBIN_URL/delete?test=mest"), "", 200, "") + assertRequestMetricsEmitted(t, metrics.GetBufferedSamples(samples), "DELETE", sr("HTTPBIN_URL/delete?test=mest"), "", 200, "") }) postMethods := map[string]string{ @@ -1188,7 +1187,7 @@ func TestRequestAndBatch(t *testing.T) { if (res.request.headers["X-We-Want-This"] != "value") { throw new Error("Missing or invalid X-We-Want-This header!"); } `), fn, strings.ToLower(method))) require.NoError(t, err) - assertRequestMetricsEmitted(t, stats.GetBufferedSamples(samples), method, sr("HTTPBIN_URL/")+strings.ToLower(method), "", 200, "") + assertRequestMetricsEmitted(t, metrics.GetBufferedSamples(samples), method, sr("HTTPBIN_URL/")+strings.ToLower(method), "", 200, "") t.Run("object", func(t *testing.T) { _, err := rt.RunString(fmt.Sprintf(sr(` @@ -1203,7 +1202,7 @@ func TestRequestAndBatch(t *testing.T) { if (res.json().headers["Content-Type"] != "application/x-www-form-urlencoded") { throw new Error("wrong content type: " + res.json().headers["Content-Type"]); } `), fn, strings.ToLower(method))) assert.NoError(t, err) - assertRequestMetricsEmitted(t, stats.GetBufferedSamples(samples), method, sr("HTTPBIN_URL/")+strings.ToLower(method), "", 200, "") + assertRequestMetricsEmitted(t, metrics.GetBufferedSamples(samples), method, sr("HTTPBIN_URL/")+strings.ToLower(method), "", 200, "") t.Run("Content-Type", func(t *testing.T) { _, err := rt.RunString(fmt.Sprintf(sr(` var res = http.%s("HTTPBIN_URL/%s", {a: "a", b: 2}, {headers: {"Content-Type": "application/x-www-form-urlencoded; charset=utf-8"}}); @@ -1213,7 +1212,7 @@ func TestRequestAndBatch(t *testing.T) { if (res.json().headers["Content-Type"] != "application/x-www-form-urlencoded; charset=utf-8") { throw new Error("wrong content type: " + res.json().headers["Content-Type"]); } `), fn, strings.ToLower(method))) assert.NoError(t, err) - assertRequestMetricsEmitted(t, stats.GetBufferedSamples(samples), method, sr("HTTPBIN_URL/")+strings.ToLower(method), "", 200, "") + assertRequestMetricsEmitted(t, metrics.GetBufferedSamples(samples), method, sr("HTTPBIN_URL/")+strings.ToLower(method), "", 200, "") }) }) }) @@ -1374,7 +1373,7 @@ func TestRequestAndBatch(t *testing.T) { } }`)) require.NoError(t, err) - bufSamples := stats.GetBufferedSamples(samples) + bufSamples := metrics.GetBufferedSamples(samples) assertRequestMetricsEmitted(t, bufSamples, "GET", sr("HTTPBIN_URL/"), "", 200, "") assertRequestMetricsEmitted(t, bufSamples, "GET", sr("HTTPBIN_IP_URL/"), "", 200, "") @@ -1393,7 +1392,7 @@ func TestRequestAndBatch(t *testing.T) { } }`)) assert.NoError(t, err) - bufSamples := stats.GetBufferedSamples(samples) + bufSamples := metrics.GetBufferedSamples(samples) assertRequestMetricsEmitted(t, bufSamples, "GET", sr("HTTPBIN_URL/get"), sr("HTTPBIN_URL/${}"), 200, "") assertRequestMetricsEmitted(t, bufSamples, "GET", sr("HTTPBIN_IP_URL/"), "", 200, "") }) @@ -1412,7 +1411,7 @@ func TestRequestAndBatch(t *testing.T) { } }`)) assert.NoError(t, err) - bufSamples := stats.GetBufferedSamples(samples) + bufSamples := metrics.GetBufferedSamples(samples) assertRequestMetricsEmitted(t, bufSamples, "GET", sr("HTTPBIN_URL/"), "", 200, "") assertRequestMetricsEmitted(t, bufSamples, "GET", sr("HTTPBIN_IP_URL/"), "", 200, "") @@ -1431,7 +1430,7 @@ func TestRequestAndBatch(t *testing.T) { } }`)) assert.NoError(t, err) - bufSamples := stats.GetBufferedSamples(samples) + bufSamples := metrics.GetBufferedSamples(samples) assertRequestMetricsEmitted(t, bufSamples, "GET", sr("HTTPBIN_URL/get"), sr("HTTPBIN_URL/${}"), 200, "") assertRequestMetricsEmitted(t, bufSamples, "GET", sr("HTTPBIN_IP_URL/"), "", 200, "") }) @@ -1451,7 +1450,7 @@ func TestRequestAndBatch(t *testing.T) { } }`)) assert.NoError(t, err) - bufSamples := stats.GetBufferedSamples(samples) + bufSamples := metrics.GetBufferedSamples(samples) assertRequestMetricsEmitted(t, bufSamples, "GET", sr("HTTPBIN_URL/"), "", 200, "") assertRequestMetricsEmitted(t, bufSamples, "GET", sr("HTTPBIN_IP_URL/"), "", 200, "") }) @@ -1470,7 +1469,7 @@ func TestRequestAndBatch(t *testing.T) { if (res[key].json().args.r != key) { throw new Error("wrong request id: " + key); } }`)) assert.NoError(t, err) - bufSamples := stats.GetBufferedSamples(samples) + bufSamples := metrics.GetBufferedSamples(samples) assertRequestMetricsEmitted(t, bufSamples, "GET", sr("HTTPBIN_URL/get?r=shorthand"), "", 200, "") assertRequestMetricsEmitted(t, bufSamples, "GET", sr("HTTPBIN_URL/get?r=arr"), "arr", 200, "") assertRequestMetricsEmitted(t, bufSamples, "GET", sr("HTTPBIN_URL/get?r=obj1"), "", 200, "") @@ -1515,7 +1514,7 @@ func TestRequestAndBatch(t *testing.T) { if (res[key].json().data != "testbody" && res[key].json().form.hello != "world!") { throw new Error("wrong response for " + key + ": " + res[key].body); } }`)) assert.NoError(t, err) - bufSamples := stats.GetBufferedSamples(samples) + bufSamples := metrics.GetBufferedSamples(samples) assertRequestMetricsEmitted(t, bufSamples, "POST", sr("HTTPBIN_URL/post"), "", 200, "") assertRequestMetricsEmitted(t, bufSamples, "POST", sr("HTTPBIN_IP_URL/post"), "myname", 200, "") }) @@ -1528,7 +1527,7 @@ func TestRequestAndBatch(t *testing.T) { if (res[key].json().form.key != "value") { throw new Error("wrong form: " + key + ": " + JSON.stringify(res[key].json().form)); } }`)) assert.NoError(t, err) - assertRequestMetricsEmitted(t, stats.GetBufferedSamples(samples), "POST", sr("HTTPBIN_URL/post"), "", 200, "") + assertRequestMetricsEmitted(t, metrics.GetBufferedSamples(samples), "POST", sr("HTTPBIN_URL/post"), "", 200, "") }) t.Run("PUT", func(t *testing.T) { _, err := rt.RunString(sr(` @@ -1538,7 +1537,7 @@ func TestRequestAndBatch(t *testing.T) { if (res[key].json().form.key != "value") { throw new Error("wrong form: " + key + ": " + JSON.stringify(res[key].json().form)); } }`)) assert.NoError(t, err) - assertRequestMetricsEmitted(t, stats.GetBufferedSamples(samples), "PUT", sr("HTTPBIN_URL/put"), "", 200, "") + assertRequestMetricsEmitted(t, metrics.GetBufferedSamples(samples), "PUT", sr("HTTPBIN_URL/put"), "", 200, "") }) }) @@ -1963,7 +1962,7 @@ func TestResponseTypes(t *testing.T) { assert.NoError(t, err) } -func checkErrorCode(t testing.TB, tags *stats.SampleTags, code int, msg string) { +func checkErrorCode(t testing.TB, tags *metrics.SampleTags, code int, msg string) { errorMsg, ok := tags.Get("error") if msg == "" { assert.False(t, ok) @@ -2065,7 +2064,7 @@ func TestErrorCodes(t *testing.T) { for _, testCase := range testCases { testCase := testCase // clear the Samples - stats.GetBufferedSamples(samples) + metrics.GetBufferedSamples(samples) t.Run(testCase.name, func(t *testing.T) { _, err := rt.RunString(sr(testCase.script + "\n" + fmt.Sprintf(` if (res.status != %d) { throw new Error("wrong status: "+ res.status);} @@ -2078,7 +2077,7 @@ func TestErrorCodes(t *testing.T) { require.Error(t, err) require.Equal(t, err.Error(), testCase.expectedScriptError) } - cs := stats.GetBufferedSamples(samples) + cs := metrics.GetBufferedSamples(samples) assert.Len(t, cs, 1+testCase.moreSamples) for _, c := range cs[len(cs)-1:] { assert.NotZero(t, len(c.GetSamples())) @@ -2198,7 +2197,7 @@ func TestRedirectMetricTags(t *testing.T) { require.Len(t, samples, 2) - checkTags := func(sc stats.SampleContainer, expTags map[string]string) { + checkTags := func(sc metrics.SampleContainer, expTags map[string]string) { allSamples := sc.GetSamples() assert.Len(t, allSamples, 9) for _, s := range allSamples { @@ -2347,7 +2346,7 @@ func TestRequestAndBatchTLS(t *testing.T) { if (res.tls_version != %s) { throw new Error("wrong TLS version: " + res.tls_version); } `, versionTest.URL, versionTest.Version)) assert.NoError(t, err) - assertRequestMetricsEmitted(t, stats.GetBufferedSamples(samples), "GET", versionTest.URL, "", 200, "") + assertRequestMetricsEmitted(t, metrics.GetBufferedSamples(samples), "GET", versionTest.URL, "", 200, "") }) } tlsCipherSuiteTests := []struct { @@ -2364,7 +2363,7 @@ func TestRequestAndBatchTLS(t *testing.T) { if (res.tls_cipher_suite != "%s") { throw new Error("wrong TLS cipher suite: " + res.tls_cipher_suite); } `, cipherSuiteTest.URL, cipherSuiteTest.CipherSuite)) assert.NoError(t, err) - assertRequestMetricsEmitted(t, stats.GetBufferedSamples(samples), "GET", cipherSuiteTest.URL, "", 200, "") + assertRequestMetricsEmitted(t, metrics.GetBufferedSamples(samples), "GET", cipherSuiteTest.URL, "", 200, "") }) } t.Run("ocsp_stapled_good", func(t *testing.T) { @@ -2374,7 +2373,7 @@ func TestRequestAndBatchTLS(t *testing.T) { if (res.ocsp.status != http.OCSP_STATUS_GOOD) { throw new Error("wrong ocsp stapled response status: " + res.ocsp.status); } `, website)) assert.NoError(t, err) - assertRequestMetricsEmitted(t, stats.GetBufferedSamples(samples), "GET", website, "", 200, "") + assertRequestMetricsEmitted(t, metrics.GetBufferedSamples(samples), "GET", website, "", 200, "") }) } @@ -2407,7 +2406,7 @@ func TestDigestAuthWithBody(t *testing.T) { urlRaw := tb.Replacer.Replace( "http://HTTPBIN_IP:HTTPBIN_PORT/digest-auth-with-post/auth/testuser/testpwd") - sampleContainers := stats.GetBufferedSamples(samples) + sampleContainers := metrics.GetBufferedSamples(samples) assertRequestMetricsEmitted(t, sampleContainers[0:1], "POST", urlRaw, urlRaw, 401, "") assertRequestMetricsEmitted(t, sampleContainers[1:2], "POST", urlRaw, urlRaw, 200, "") } diff --git a/js/modules/k6/http/response_callback_test.go b/js/modules/k6/http/response_callback_test.go index 79c23615dcc..87e5036421d 100644 --- a/js/modules/k6/http/response_callback_test.go +++ b/js/modules/k6/http/response_callback_test.go @@ -30,7 +30,6 @@ import ( "github.com/stretchr/testify/require" "go.k6.io/k6/lib" "go.k6.io/k6/metrics" - "go.k6.io/k6/stats" ) func TestExpectedStatuses(t *testing.T) { @@ -278,7 +277,7 @@ func TestResponseCallbackInAction(t *testing.T) { _, err := rt.RunString(sr(testCase.code)) assert.NoError(t, err) - bufSamples := stats.GetBufferedSamples(samples) + bufSamples := metrics.GetBufferedSamples(samples) reqsCount := 0 for _, container := range bufSamples { @@ -387,7 +386,7 @@ func TestResponseCallbackBatch(t *testing.T) { _, err := rt.RunString(sr(testCase.code)) assert.NoError(t, err) - bufSamples := stats.GetBufferedSamples(samples) + bufSamples := metrics.GetBufferedSamples(samples) reqsCount := 0 for _, container := range bufSamples { @@ -427,11 +426,11 @@ func TestResponseCallbackInActionWithoutPassedTag(t *testing.T) { metrics.HTTPReqWaitingName, metrics.HTTPReqTLSHandshakingName, } - deleteSystemTag(state, stats.TagExpectedResponse.String()) + deleteSystemTag(state, metrics.TagExpectedResponse.String()) _, err := rt.RunString(sr(`http.request("GET", "HTTPBIN_URL/redirect/1", null, {responseCallback: http.expectedStatuses(200)});`)) assert.NoError(t, err) - bufSamples := stats.GetBufferedSamples(samples) + bufSamples := metrics.GetBufferedSamples(samples) reqsCount := 0 for _, container := range bufSamples { @@ -452,7 +451,7 @@ func TestResponseCallbackInActionWithoutPassedTag(t *testing.T) { "group": "", "proto": "HTTP/1.1", } - assertRequestMetricsEmittedSingle(t, bufSamples[0], tags, allHTTPMetrics, func(sample stats.Sample) { + assertRequestMetricsEmittedSingle(t, bufSamples[0], tags, allHTTPMetrics, func(sample metrics.Sample) { if sample.Metric.Name == metrics.HTTPReqFailedName { require.EqualValues(t, sample.Value, 1) } @@ -460,7 +459,7 @@ func TestResponseCallbackInActionWithoutPassedTag(t *testing.T) { tags["url"] = sr("HTTPBIN_URL/get") tags["name"] = tags["url"] tags["status"] = "200" - assertRequestMetricsEmittedSingle(t, bufSamples[1], tags, allHTTPMetrics, func(sample stats.Sample) { + assertRequestMetricsEmittedSingle(t, bufSamples[1], tags, allHTTPMetrics, func(sample metrics.Sample) { if sample.Metric.Name == metrics.HTTPReqFailedName { require.EqualValues(t, sample.Value, 0) } @@ -492,7 +491,7 @@ func TestDigestWithResponseCallback(t *testing.T) { if (res.error_code !== 0) { throw new Error("wrong error code: " + res.error_code); } `, urlWithCreds)) require.NoError(t, err) - bufSamples := stats.GetBufferedSamples(samples) + bufSamples := metrics.GetBufferedSamples(samples) reqsCount := 0 for _, container := range bufSamples { @@ -518,14 +517,14 @@ func TestDigestWithResponseCallback(t *testing.T) { "expected_response": "true", "error_code": "1401", } - assertRequestMetricsEmittedSingle(t, bufSamples[0], tags, allHTTPMetrics, func(sample stats.Sample) { + assertRequestMetricsEmittedSingle(t, bufSamples[0], tags, allHTTPMetrics, func(sample metrics.Sample) { if sample.Metric.Name == metrics.HTTPReqFailedName { require.EqualValues(t, sample.Value, 0) } }) tags["status"] = "200" delete(tags, "error_code") - assertRequestMetricsEmittedSingle(t, bufSamples[1], tags, allHTTPMetrics, func(sample stats.Sample) { + assertRequestMetricsEmittedSingle(t, bufSamples[1], tags, allHTTPMetrics, func(sample metrics.Sample) { if sample.Metric.Name == metrics.HTTPReqFailedName { require.EqualValues(t, sample.Value, 0) } @@ -539,5 +538,5 @@ func deleteSystemTag(state *lib.State, tag string) { for k := range enabledTags { tagsList = append(tagsList, k) } - state.Options.SystemTags = stats.ToSystemTagSet(tagsList) + state.Options.SystemTags = metrics.ToSystemTagSet(tagsList) } diff --git a/js/modules/k6/http/response_test.go b/js/modules/k6/http/response_test.go index 1bb36e7218c..75981fb0bb4 100644 --- a/js/modules/k6/http/response_test.go +++ b/js/modules/k6/http/response_test.go @@ -29,8 +29,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - - "go.k6.io/k6/stats" + "go.k6.io/k6/metrics" ) const testGetFormHTML = ` @@ -141,7 +140,7 @@ func TestResponse(t *testing.T) { if (res.body.indexOf("Herman Melville - Moby-Dick") == -1) { throw new Error("wrong body: " + res.body); } `)) assert.NoError(t, err) - assertRequestMetricsEmitted(t, stats.GetBufferedSamples(samples), "GET", sr("HTTPBIN_URL/html"), "", 200, "") + assertRequestMetricsEmitted(t, metrics.GetBufferedSamples(samples), "GET", sr("HTTPBIN_URL/html"), "", 200, "") t.Run("html", func(t *testing.T) { _, err := rt.RunString(` @@ -182,7 +181,7 @@ func TestResponse(t *testing.T) { if (res.body.indexOf("Herman Melville - Moby-Dick") == -1) { throw new Error("wrong body: " + res.body); } `)) assert.NoError(t, err) - assertRequestMetricsEmitted(t, stats.GetBufferedSamples(samples), "GET", sr("HTTPBIN_URL/html"), "", 200, "::my group") + assertRequestMetricsEmitted(t, metrics.GetBufferedSamples(samples), "GET", sr("HTTPBIN_URL/html"), "", 200, "::my group") }) t.Run("NoResponseBody", func(t *testing.T) { @@ -200,7 +199,7 @@ func TestResponse(t *testing.T) { if (res.json().args.b != "2") { throw new Error("wrong ?b: " + res.json().args.b); } `)) assert.NoError(t, err) - assertRequestMetricsEmitted(t, stats.GetBufferedSamples(samples), "GET", sr("HTTPBIN_URL/get?a=1&b=2"), "", 200, "") + assertRequestMetricsEmitted(t, metrics.GetBufferedSamples(samples), "GET", sr("HTTPBIN_URL/get?a=1&b=2"), "", 200, "") t.Run("Invalid", func(t *testing.T) { _, err := rt.RunString(sr(`http.request("GET", "HTTPBIN_URL/html").json();`)) @@ -261,7 +260,7 @@ func TestResponse(t *testing.T) { { throw new Error("Expected 'Dale', but got: " + value); } `)) assert.NoError(t, err) - assertRequestMetricsEmitted(t, stats.GetBufferedSamples(samples), "GET", sr("HTTPBIN_URL/json"), "", 200, "") + assertRequestMetricsEmitted(t, metrics.GetBufferedSamples(samples), "GET", sr("HTTPBIN_URL/json"), "", 200, "") }) t.Run("SubmitForm", func(t *testing.T) { @@ -281,7 +280,7 @@ func TestResponse(t *testing.T) { ) { throw new Error("incorrect body: " + JSON.stringify(data, null, 4) ); } `)) assert.NoError(t, err) - assertRequestMetricsEmitted(t, stats.GetBufferedSamples(samples), "POST", sr("HTTPBIN_URL/post"), "", 200, "") + assertRequestMetricsEmitted(t, metrics.GetBufferedSamples(samples), "POST", sr("HTTPBIN_URL/post"), "", 200, "") }) t.Run("withFields", func(t *testing.T) { @@ -300,7 +299,7 @@ func TestResponse(t *testing.T) { ) { throw new Error("incorrect body: " + JSON.stringify(data, null, 4) ); } `)) assert.NoError(t, err) - assertRequestMetricsEmitted(t, stats.GetBufferedSamples(samples), "POST", sr("HTTPBIN_URL/post"), "", 200, "") + assertRequestMetricsEmitted(t, metrics.GetBufferedSamples(samples), "POST", sr("HTTPBIN_URL/post"), "", 200, "") }) t.Run("withRequestParams", func(t *testing.T) { @@ -313,7 +312,7 @@ func TestResponse(t *testing.T) { if (headers["My-Fancy-Header"][0] !== "SomeValue" ) { throw new Error("incorrect headers: " + JSON.stringify(headers)); } `)) assert.NoError(t, err) - assertRequestMetricsEmitted(t, stats.GetBufferedSamples(samples), "POST", sr("HTTPBIN_URL/post"), "", 200, "") + assertRequestMetricsEmitted(t, metrics.GetBufferedSamples(samples), "POST", sr("HTTPBIN_URL/post"), "", 200, "") }) t.Run("withFormSelector", func(t *testing.T) { @@ -332,7 +331,7 @@ func TestResponse(t *testing.T) { ) { throw new Error("incorrect body: " + JSON.stringify(data, null, 4) ); } `)) assert.NoError(t, err) - assertRequestMetricsEmitted(t, stats.GetBufferedSamples(samples), "POST", sr("HTTPBIN_URL/post"), "", 200, "") + assertRequestMetricsEmitted(t, metrics.GetBufferedSamples(samples), "POST", sr("HTTPBIN_URL/post"), "", 200, "") }) t.Run("withNonExistentForm", func(t *testing.T) { @@ -360,7 +359,7 @@ func TestResponse(t *testing.T) { ) { throw new Error("incorrect body: " + JSON.stringify(data, null, 4) ); } `)) require.NoError(t, err) - assertRequestMetricsEmitted(t, stats.GetBufferedSamples(samples), "GET", sr("HTTPBIN_URL/myforms/get"), "", 200, "") + assertRequestMetricsEmitted(t, metrics.GetBufferedSamples(samples), "GET", sr("HTTPBIN_URL/myforms/get"), "", 200, "") }) }) @@ -373,7 +372,7 @@ func TestResponse(t *testing.T) { if (res.status != 200) { throw new Error("wrong status: " + res.status); } `)) assert.NoError(t, err) - assertRequestMetricsEmitted(t, stats.GetBufferedSamples(samples), "GET", sr("HTTPBIN_URL/links/10/1"), "", 200, "") + assertRequestMetricsEmitted(t, metrics.GetBufferedSamples(samples), "GET", sr("HTTPBIN_URL/links/10/1"), "", 200, "") }) t.Run("withSelector", func(t *testing.T) { @@ -384,7 +383,7 @@ func TestResponse(t *testing.T) { if (res.status != 200) { throw new Error("wrong status: " + res.status); } `)) assert.NoError(t, err) - assertRequestMetricsEmitted(t, stats.GetBufferedSamples(samples), "GET", sr("HTTPBIN_URL/links/10/4"), "", 200, "") + assertRequestMetricsEmitted(t, metrics.GetBufferedSamples(samples), "GET", sr("HTTPBIN_URL/links/10/4"), "", 200, "") }) t.Run("withNonExistentLink", func(t *testing.T) { @@ -407,7 +406,7 @@ func TestResponse(t *testing.T) { if (headers["My-Fancy-Header"][0] !== "SomeValue" ) { throw new Error("incorrect headers: " + JSON.stringify(headers)); } `)) assert.NoError(t, err) - assertRequestMetricsEmitted(t, stats.GetBufferedSamples(samples), "GET", sr("HTTPBIN_URL/get"), "", 200, "") + assertRequestMetricsEmitted(t, metrics.GetBufferedSamples(samples), "GET", sr("HTTPBIN_URL/get"), "", 200, "") }) }) } diff --git a/js/modules/k6/k6.go b/js/modules/k6/k6.go index b5e25d9c891..0e098f3044f 100644 --- a/js/modules/k6/k6.go +++ b/js/modules/k6/k6.go @@ -31,7 +31,7 @@ import ( "go.k6.io/k6/js/common" "go.k6.io/k6/js/modules" - "go.k6.io/k6/stats" + "go.k6.io/k6/metrics" ) var ( @@ -123,7 +123,7 @@ func (mi *K6) Group(name string, fn goja.Callable) (goja.Value, error) { old := state.Group state.Group = g - shouldUpdateTag := state.Options.SystemTags.Has(stats.TagGroup) + shouldUpdateTag := state.Options.SystemTags.Has(metrics.TagGroup) if shouldUpdateTag { state.Tags.Set("group", g.Path) } @@ -141,11 +141,11 @@ func (mi *K6) Group(name string, fn goja.Callable) (goja.Value, error) { tags := state.CloneTags() ctx := mi.vu.Context() - stats.PushIfNotDone(ctx, state.Samples, stats.Sample{ + metrics.PushIfNotDone(ctx, state.Samples, metrics.Sample{ Time: t, Metric: state.BuiltinMetrics.GroupDuration, - Tags: stats.IntoSampleTags(&tags), - Value: stats.D(t.Sub(startTime)), + Tags: metrics.IntoSampleTags(&tags), + Value: metrics.D(t.Sub(startTime)), }) return ret, err @@ -190,7 +190,7 @@ func (mi *K6) Check(arg0, checks goja.Value, extras ...goja.Value) (bool, error) if err != nil { return false, err } - if state.Options.SystemTags.Has(stats.TagCheck) { + if state.Options.SystemTags.Has(metrics.TagCheck) { tags["check"] = check.Name } @@ -205,7 +205,7 @@ func (mi *K6) Check(arg0, checks goja.Value, extras ...goja.Value) (bool, error) } } - sampleTags := stats.IntoSampleTags(&tags) + sampleTags := metrics.IntoSampleTags(&tags) // Emit! (But only if we have a valid context.) select { @@ -213,12 +213,12 @@ func (mi *K6) Check(arg0, checks goja.Value, extras ...goja.Value) (bool, error) default: if val.ToBoolean() { atomic.AddInt64(&check.Passes, 1) - stats.PushIfNotDone(ctx, state.Samples, - stats.Sample{Time: t, Metric: state.BuiltinMetrics.Checks, Tags: sampleTags, Value: 1}) + metrics.PushIfNotDone(ctx, state.Samples, + metrics.Sample{Time: t, Metric: state.BuiltinMetrics.Checks, Tags: sampleTags, Value: 1}) } else { atomic.AddInt64(&check.Fails, 1) - stats.PushIfNotDone(ctx, state.Samples, - stats.Sample{Time: t, Metric: state.BuiltinMetrics.Checks, Tags: sampleTags, Value: 0}) + metrics.PushIfNotDone(ctx, state.Samples, + metrics.Sample{Time: t, Metric: state.BuiltinMetrics.Checks, Tags: sampleTags, Value: 0}) // A single failure makes the return value false. succ = false } diff --git a/js/modules/k6/k6_test.go b/js/modules/k6/k6_test.go index 00c39927506..c0a7c909856 100644 --- a/js/modules/k6/k6_test.go +++ b/js/modules/k6/k6_test.go @@ -34,7 +34,6 @@ import ( "go.k6.io/k6/js/modulestest" "go.k6.io/k6/lib" "go.k6.io/k6/metrics" - "go.k6.io/k6/stats" ) func TestFail(t *testing.T) { @@ -161,10 +160,10 @@ func TestGroup(t *testing.T) { rt := goja.New() state := &lib.State{ Group: root, - Samples: make(chan stats.SampleContainer, 1000), + Samples: make(chan metrics.SampleContainer, 1000), Tags: lib.NewTagMap(nil), Options: lib.Options{ - SystemTags: stats.NewSystemTagSet(stats.TagGroup), + SystemTags: metrics.NewSystemTagSet(metrics.TagGroup), }, } state.BuiltinMetrics = metrics.RegisterBuiltinMetrics(metrics.NewRegistry()) @@ -209,16 +208,16 @@ func TestGroup(t *testing.T) { }) } -func checkTestRuntime(t testing.TB) (*goja.Runtime, chan stats.SampleContainer, *metrics.BuiltinMetrics) { +func checkTestRuntime(t testing.TB) (*goja.Runtime, chan metrics.SampleContainer, *metrics.BuiltinMetrics) { rt := goja.New() root, err := lib.NewGroup("", nil) assert.NoError(t, err) - samples := make(chan stats.SampleContainer, 1000) + samples := make(chan metrics.SampleContainer, 1000) state := &lib.State{ Group: root, Options: lib.Options{ - SystemTags: &stats.DefaultSystemTagSet, + SystemTags: &metrics.DefaultSystemTagSet, }, Samples: samples, Tags: lib.NewTagMap(map[string]string{ @@ -248,9 +247,9 @@ func TestCheckObject(t *testing.T) { _, err := rt.RunString(`k6.check(null, { "check": true })`) assert.NoError(t, err) - bufSamples := stats.GetBufferedSamples(samples) + bufSamples := metrics.GetBufferedSamples(samples) if assert.Len(t, bufSamples, 1) { - sample, ok := bufSamples[0].(stats.Sample) + sample, ok := bufSamples[0].(metrics.Sample) require.True(t, ok) assert.NotZero(t, sample.Time) @@ -269,7 +268,7 @@ func TestCheckObject(t *testing.T) { _, err := rt.RunString(`k6.check(null, { "a": true, "b": false })`) assert.NoError(t, err) - bufSamples := stats.GetBufferedSamples(samples) + bufSamples := metrics.GetBufferedSamples(samples) assert.Len(t, bufSamples, 2) var foundA, foundB bool for _, sampleC := range bufSamples { @@ -307,9 +306,9 @@ func TestCheckArray(t *testing.T) { _, err := rt.RunString(`k6.check(null, [ true ])`) assert.NoError(t, err) - bufSamples := stats.GetBufferedSamples(samples) + bufSamples := metrics.GetBufferedSamples(samples) if assert.Len(t, bufSamples, 1) { - sample, ok := bufSamples[0].(stats.Sample) + sample, ok := bufSamples[0].(metrics.Sample) require.True(t, ok) assert.NotZero(t, sample.Time) @@ -328,7 +327,7 @@ func TestCheckLiteral(t *testing.T) { _, err := rt.RunString(`k6.check(null, 12345)`) assert.NoError(t, err) - assert.Len(t, stats.GetBufferedSamples(samples), 0) + assert.Len(t, metrics.GetBufferedSamples(samples), 0) } func TestCheckNull(t *testing.T) { @@ -338,7 +337,7 @@ func TestCheckNull(t *testing.T) { _, err := rt.RunString(`k6.check(5)`) require.Error(t, err) assert.Contains(t, err.Error(), "no checks provided") - assert.Len(t, stats.GetBufferedSamples(samples), 0) + assert.Len(t, metrics.GetBufferedSamples(samples), 0) } func TestCheckThrows(t *testing.T) { @@ -352,9 +351,9 @@ func TestCheckThrows(t *testing.T) { `) assert.EqualError(t, err, "Error: error A at a (:3:28(3))") - bufSamples := stats.GetBufferedSamples(samples) + bufSamples := metrics.GetBufferedSamples(samples) if assert.Len(t, bufSamples, 1) { - sample, ok := bufSamples[0].(stats.Sample) + sample, ok := bufSamples[0].(metrics.Sample) require.True(t, ok) assert.NotZero(t, sample.Time) @@ -401,9 +400,9 @@ func TestCheckTypes(t *testing.T) { assert.Equal(t, succ, v.Export()) } - bufSamples := stats.GetBufferedSamples(samples) + bufSamples := metrics.GetBufferedSamples(samples) if assert.Len(t, bufSamples, 1) { - sample, ok := bufSamples[0].(stats.Sample) + sample, ok := bufSamples[0].(metrics.Sample) require.True(t, ok) assert.NotZero(t, sample.Time) @@ -432,11 +431,11 @@ func TestCheckContextExpiry(t *testing.T) { root, err := lib.NewGroup("", nil) require.NoError(t, err) - samples := make(chan stats.SampleContainer, 1000) + samples := make(chan metrics.SampleContainer, 1000) state := &lib.State{ Group: root, Options: lib.Options{ - SystemTags: &stats.DefaultSystemTagSet, + SystemTags: &metrics.DefaultSystemTagSet, }, Samples: samples, Tags: lib.NewTagMap(map[string]string{ @@ -484,9 +483,9 @@ func TestCheckTags(t *testing.T) { assert.Equal(t, true, v.Export()) } - bufSamples := stats.GetBufferedSamples(samples) + bufSamples := metrics.GetBufferedSamples(samples) if assert.Len(t, bufSamples, 1) { - sample, ok := bufSamples[0].(stats.Sample) + sample, ok := bufSamples[0].(metrics.Sample) require.True(t, ok) assert.NotZero(t, sample.Time) diff --git a/js/modules/k6/marshalling_test.go b/js/modules/k6/marshalling_test.go index 809b392531f..58ccb746168 100644 --- a/js/modules/k6/marshalling_test.go +++ b/js/modules/k6/marshalling_test.go @@ -36,7 +36,6 @@ import ( "go.k6.io/k6/lib/types" "go.k6.io/k6/loader" "go.k6.io/k6/metrics" - "go.k6.io/k6/stats" ) func TestSetupDataMarshalling(t *testing.T) { @@ -137,7 +136,7 @@ func TestSetupDataMarshalling(t *testing.T) { require.NoError(t, err) - samples := make(chan<- stats.SampleContainer, 100) + samples := make(chan<- metrics.SampleContainer, 100) ctx, cancel := context.WithCancel(context.Background()) defer cancel() diff --git a/js/modules/k6/metrics/metrics.go b/js/modules/k6/metrics/metrics.go index cf8516b5683..bbadad4aca5 100644 --- a/js/modules/k6/metrics/metrics.go +++ b/js/modules/k6/metrics/metrics.go @@ -32,27 +32,27 @@ import ( "go.k6.io/k6/js/common" "go.k6.io/k6/js/modules" - "go.k6.io/k6/stats" + "go.k6.io/k6/metrics" ) type Metric struct { - metric *stats.Metric + metric *metrics.Metric vu modules.VU } // ErrMetricsAddInInitContext is error returned when adding to metric is done in the init context var ErrMetricsAddInInitContext = common.NewInitContextError("Adding to metrics in the init context is not supported") -func (mi *ModuleInstance) newMetric(call goja.ConstructorCall, t stats.MetricType) (*goja.Object, error) { +func (mi *ModuleInstance) newMetric(call goja.ConstructorCall, t metrics.MetricType) (*goja.Object, error) { initEnv := mi.vu.InitEnv() if initEnv == nil { return nil, errors.New("metrics must be declared in the init context") } rt := mi.vu.Runtime() c, _ := goja.AssertFunction(rt.ToValue(func(name string, isTime ...bool) (*goja.Object, error) { - valueType := stats.Default + valueType := metrics.Default if len(isTime) > 0 && isTime[0] { - valueType = stats.Time + valueType = metrics.Time } m, err := initEnv.Registry.NewMetric(name, t, valueType) if err != nil { @@ -135,8 +135,8 @@ func (m Metric) add(v goja.Value, addTags ...map[string]string) (bool, error) { } } - sample := stats.Sample{Time: time.Now(), Metric: m.metric, Value: vfloat, Tags: stats.IntoSampleTags(&tags)} - stats.PushIfNotDone(m.vu.Context(), state.Samples, sample) + sample := metrics.Sample{Time: time.Now(), Metric: m.metric, Value: vfloat, Tags: metrics.IntoSampleTags(&tags)} + metrics.PushIfNotDone(m.vu.Context(), state.Samples, sample) return true, nil } @@ -178,7 +178,7 @@ func (mi *ModuleInstance) Exports() modules.Exports { // XCounter is a counter constructor func (mi *ModuleInstance) XCounter(call goja.ConstructorCall, rt *goja.Runtime) *goja.Object { - v, err := mi.newMetric(call, stats.Counter) + v, err := mi.newMetric(call, metrics.Counter) if err != nil { common.Throw(rt, err) } @@ -187,7 +187,7 @@ func (mi *ModuleInstance) XCounter(call goja.ConstructorCall, rt *goja.Runtime) // XGauge is a gauge constructor func (mi *ModuleInstance) XGauge(call goja.ConstructorCall, rt *goja.Runtime) *goja.Object { - v, err := mi.newMetric(call, stats.Gauge) + v, err := mi.newMetric(call, metrics.Gauge) if err != nil { common.Throw(rt, err) } @@ -196,7 +196,7 @@ func (mi *ModuleInstance) XGauge(call goja.ConstructorCall, rt *goja.Runtime) *g // XTrend is a trend constructor func (mi *ModuleInstance) XTrend(call goja.ConstructorCall, rt *goja.Runtime) *goja.Object { - v, err := mi.newMetric(call, stats.Trend) + v, err := mi.newMetric(call, metrics.Trend) if err != nil { common.Throw(rt, err) } @@ -205,7 +205,7 @@ func (mi *ModuleInstance) XTrend(call goja.ConstructorCall, rt *goja.Runtime) *g // XRate is a rate constructor func (mi *ModuleInstance) XRate(call goja.ConstructorCall, rt *goja.Runtime) *goja.Object { - v, err := mi.newMetric(call, stats.Rate) + v, err := mi.newMetric(call, metrics.Rate) if err != nil { common.Throw(rt, err) } diff --git a/js/modules/k6/metrics/metrics_test.go b/js/modules/k6/metrics/metrics_test.go index cfd5547880c..d6d9716c694 100644 --- a/js/modules/k6/metrics/metrics_test.go +++ b/js/modules/k6/metrics/metrics_test.go @@ -36,7 +36,6 @@ import ( "go.k6.io/k6/lib" "go.k6.io/k6/lib/testutils" "go.k6.io/k6/metrics" - "go.k6.io/k6/stats" ) type addTestValue struct { @@ -50,10 +49,10 @@ type addTest struct { val addTestValue rt *goja.Runtime hook *testutils.SimpleLogrusHook - samples chan stats.SampleContainer + samples chan metrics.SampleContainer isThrow bool - mtyp stats.MetricType - valueType stats.ValueType + mtyp metrics.MetricType + valueType metrics.ValueType js string expectedTags map[string]string } @@ -73,9 +72,9 @@ func (a addTest) run(t *testing.T) { return } } - bufSamples := stats.GetBufferedSamples(a.samples) + bufSamples := metrics.GetBufferedSamples(a.samples) if assert.Len(t, bufSamples, 1) { - sample, ok := bufSamples[0].(stats.Sample) + sample, ok := bufSamples[0].(metrics.Sample) require.True(t, ok) assert.NotZero(t, sample.Time) @@ -89,11 +88,11 @@ func (a addTest) run(t *testing.T) { func TestMetrics(t *testing.T) { t.Parallel() - types := map[string]stats.MetricType{ - "Counter": stats.Counter, - "Gauge": stats.Gauge, - "Trend": stats.Trend, - "Rate": stats.Rate, + types := map[string]metrics.MetricType{ + "Counter": metrics.Counter, + "Gauge": metrics.Gauge, + "Trend": metrics.Trend, + "Rate": metrics.Rate, } values := map[string]addTestValue{ "Float": {JS: `2.5`, Float: 2.5}, @@ -113,7 +112,7 @@ func TestMetrics(t *testing.T) { fn, mtyp := fn, mtyp t.Run(fn, func(t *testing.T) { t.Parallel() - for isTime, valueType := range map[bool]stats.ValueType{false: stats.Default, true: stats.Time} { + for isTime, valueType := range map[bool]metrics.ValueType{false: metrics.Default, true: metrics.Time} { isTime, valueType := isTime, valueType t.Run(fmt.Sprintf("isTime=%v", isTime), func(t *testing.T) { t.Parallel() @@ -131,7 +130,7 @@ func TestMetrics(t *testing.T) { m, ok := New().NewModuleInstance(mii).(*ModuleInstance) require.True(t, ok) require.NoError(t, test.rt.Set("metrics", m.Exports().Named)) - test.samples = make(chan stats.SampleContainer, 1000) + test.samples = make(chan metrics.SampleContainer, 1000) state := &lib.State{ Options: lib.Options{}, Samples: test.samples, diff --git a/js/modules/k6/ws/ws.go b/js/modules/k6/ws/ws.go index 0bcc011136f..e48e2a49147 100644 --- a/js/modules/k6/ws/ws.go +++ b/js/modules/k6/ws/ws.go @@ -40,7 +40,6 @@ import ( "go.k6.io/k6/js/modules" httpModule "go.k6.io/k6/js/modules/k6/http" "go.k6.io/k6/metrics" - "go.k6.io/k6/stats" ) type ( @@ -96,8 +95,8 @@ type Socket struct { pingSendTimestamps map[string]time.Time pingSendCounter int - sampleTags *stats.SampleTags - samplesOutput chan<- stats.SampleContainer + sampleTags *metrics.SampleTags + samplesOutput chan<- metrics.SampleContainer builtinMetrics *metrics.BuiltinMetrics } @@ -216,7 +215,7 @@ func (mi *WS) Connect(url string, args ...goja.Value) (*WSHTTPResponse, error) { } - if state.Options.SystemTags.Has(stats.TagURL) { + if state.Options.SystemTags.Has(metrics.TagURL) { tags["url"] = url } @@ -244,20 +243,20 @@ func (mi *WS) Connect(url string, args ...goja.Value) (*WSHTTPResponse, error) { start := time.Now() conn, httpResponse, connErr := wsd.DialContext(ctx, url, header) connectionEnd := time.Now() - connectionDuration := stats.D(connectionEnd.Sub(start)) + connectionDuration := metrics.D(connectionEnd.Sub(start)) - if state.Options.SystemTags.Has(stats.TagIP) && conn.RemoteAddr() != nil { + if state.Options.SystemTags.Has(metrics.TagIP) && conn.RemoteAddr() != nil { if ip, _, err := net.SplitHostPort(conn.RemoteAddr().String()); err == nil { tags["ip"] = ip } } if httpResponse != nil { - if state.Options.SystemTags.Has(stats.TagStatus) { + if state.Options.SystemTags.Has(metrics.TagStatus) { tags["status"] = strconv.Itoa(httpResponse.StatusCode) } - if state.Options.SystemTags.Has(stats.TagSubproto) { + if state.Options.SystemTags.Has(metrics.TagSubproto) { tags["subproto"] = httpResponse.Header.Get("Sec-WebSocket-Protocol") } } @@ -271,12 +270,12 @@ func (mi *WS) Connect(url string, args ...goja.Value) (*WSHTTPResponse, error) { scheduled: make(chan goja.Callable), done: make(chan struct{}), samplesOutput: state.Samples, - sampleTags: stats.IntoSampleTags(&tags), + sampleTags: metrics.IntoSampleTags(&tags), builtinMetrics: state.BuiltinMetrics, } - stats.PushIfNotDone(ctx, state.Samples, stats.ConnectedSamples{ - Samples: []stats.Sample{ + metrics.PushIfNotDone(ctx, state.Samples, metrics.ConnectedSamples{ + Samples: []metrics.Sample{ {Metric: state.BuiltinMetrics.WSSessions, Time: start, Tags: socket.sampleTags, Value: 1}, {Metric: state.BuiltinMetrics.WSConnecting, Time: start, Tags: socket.sampleTags, Value: connectionDuration}, }, @@ -331,9 +330,9 @@ func (mi *WS) Connect(url string, args ...goja.Value) (*WSHTTPResponse, error) { defer func() { socket.Close() // just in case end := time.Now() - sessionDuration := stats.D(end.Sub(start)) + sessionDuration := metrics.D(end.Sub(start)) - stats.PushIfNotDone(ctx, state.Samples, stats.Sample{ + metrics.PushIfNotDone(ctx, state.Samples, metrics.Sample{ Metric: socket.builtinMetrics.WSSessionDuration, Tags: socket.sampleTags, Time: start, @@ -361,7 +360,7 @@ func (mi *WS) Connect(url string, args ...goja.Value) (*WSHTTPResponse, error) { socket.handleEvent("pong") case msg := <-readDataChan: - stats.PushIfNotDone(ctx, socket.samplesOutput, stats.Sample{ + metrics.PushIfNotDone(ctx, socket.samplesOutput, metrics.Sample{ Metric: socket.builtinMetrics.WSMessagesReceived, Time: time.Now(), Tags: socket.sampleTags, @@ -421,7 +420,7 @@ func (s *Socket) Send(message string) { s.handleEvent("error", s.rt.ToValue(err)) } - stats.PushIfNotDone(s.ctx, s.samplesOutput, stats.Sample{ + metrics.PushIfNotDone(s.ctx, s.samplesOutput, metrics.Sample{ Metric: s.builtinMetrics.WSMessagesSent, Time: time.Now(), Tags: s.sampleTags, @@ -451,7 +450,7 @@ func (s *Socket) SendBinary(message goja.Value) { common.Throw(s.rt, fmt.Errorf("expected ArrayBuffer as argument, received: %s", jsType)) } - stats.PushIfNotDone(s.ctx, s.samplesOutput, stats.Sample{ + metrics.PushIfNotDone(s.ctx, s.samplesOutput, metrics.Sample{ Metric: s.builtinMetrics.WSMessagesSent, Time: time.Now(), Tags: s.sampleTags, @@ -484,11 +483,11 @@ func (s *Socket) trackPong(pingID string) { } pingTimestamp := s.pingSendTimestamps[pingID] - stats.PushIfNotDone(s.ctx, s.samplesOutput, stats.Sample{ + metrics.PushIfNotDone(s.ctx, s.samplesOutput, metrics.Sample{ Metric: s.builtinMetrics.WSPing, Time: pongTimestamp, Tags: s.sampleTags, - Value: stats.D(pongTimestamp.Sub(pingTimestamp)), + Value: metrics.D(pongTimestamp.Sub(pingTimestamp)), }) } diff --git a/js/modules/k6/ws/ws_test.go b/js/modules/k6/ws/ws_test.go index 84c031461ae..6df83bb506b 100644 --- a/js/modules/k6/ws/ws_test.go +++ b/js/modules/k6/ws/ws_test.go @@ -44,13 +44,11 @@ import ( "go.k6.io/k6/lib" "go.k6.io/k6/lib/testutils/httpmultibin" "go.k6.io/k6/metrics" - - "go.k6.io/k6/stats" ) const statusProtocolSwitch = 101 -func assertSessionMetricsEmitted(t *testing.T, sampleContainers []stats.SampleContainer, subprotocol, url string, status int, group string) { +func assertSessionMetricsEmitted(t *testing.T, sampleContainers []metrics.SampleContainer, subprotocol, url string, status int, group string) { //nolint:unparam seenSessions := false seenSessionDuration := false seenConnecting := false @@ -79,7 +77,7 @@ func assertSessionMetricsEmitted(t *testing.T, sampleContainers []stats.SampleCo assert.True(t, seenSessionDuration, "url %s didn't emit SessionDuration", url) } -func assertMetricEmittedCount(t *testing.T, metricName string, sampleContainers []stats.SampleContainer, url string, count int) { +func assertMetricEmittedCount(t *testing.T, metricName string, sampleContainers []metrics.SampleContainer, url string, count int) { t.Helper() actualCount := 0 @@ -100,7 +98,7 @@ type testState struct { rt *goja.Runtime tb *httpmultibin.HTTPMultiBin state *lib.State - samples chan stats.SampleContainer + samples chan metrics.SampleContainer } func newTestState(t testing.TB) testState { @@ -112,17 +110,17 @@ func newTestState(t testing.TB) testState { rt := goja.New() rt.SetFieldNameMapper(common.FieldNameMapper{}) - samples := make(chan stats.SampleContainer, 1000) + samples := make(chan metrics.SampleContainer, 1000) state := &lib.State{ Group: root, Dialer: tb.Dialer, Options: lib.Options{ - SystemTags: stats.NewSystemTagSet( - stats.TagURL, - stats.TagProto, - stats.TagStatus, - stats.TagSubproto, + SystemTags: metrics.NewSystemTagSet( + metrics.TagURL, + metrics.TagProto, + metrics.TagStatus, + metrics.TagSubproto, ), UserAgent: null.StringFrom("TestUserAgent"), }, @@ -159,16 +157,16 @@ func TestSession(t *testing.T) { rt := goja.New() rt.SetFieldNameMapper(common.FieldNameMapper{}) - samples := make(chan stats.SampleContainer, 1000) + samples := make(chan metrics.SampleContainer, 1000) state := &lib.State{ Group: root, Dialer: tb.Dialer, Options: lib.Options{ - SystemTags: stats.NewSystemTagSet( - stats.TagURL, - stats.TagProto, - stats.TagStatus, - stats.TagSubproto, + SystemTags: metrics.NewSystemTagSet( + metrics.TagURL, + metrics.TagProto, + metrics.TagStatus, + metrics.TagSubproto, ), }, Samples: samples, @@ -194,7 +192,7 @@ func TestSession(t *testing.T) { `)) require.NoError(t, err) }) - assertSessionMetricsEmitted(t, stats.GetBufferedSamples(samples), "", sr("WSBIN_URL/ws-echo"), statusProtocolSwitch, "") + assertSessionMetricsEmitted(t, metrics.GetBufferedSamples(samples), "", sr("WSBIN_URL/ws-echo"), statusProtocolSwitch, "") t.Run("connect_wss", func(t *testing.T) { _, err := rt.RunString(sr(` @@ -205,7 +203,7 @@ func TestSession(t *testing.T) { `)) require.NoError(t, err) }) - assertSessionMetricsEmitted(t, stats.GetBufferedSamples(samples), "", sr("WSSBIN_URL/ws-echo"), statusProtocolSwitch, "") + assertSessionMetricsEmitted(t, metrics.GetBufferedSamples(samples), "", sr("WSSBIN_URL/ws-echo"), statusProtocolSwitch, "") t.Run("open", func(t *testing.T) { _, err := rt.RunString(sr(` @@ -220,7 +218,7 @@ func TestSession(t *testing.T) { `)) require.NoError(t, err) }) - assertSessionMetricsEmitted(t, stats.GetBufferedSamples(samples), "", sr("WSBIN_URL/ws-echo"), statusProtocolSwitch, "") + assertSessionMetricsEmitted(t, metrics.GetBufferedSamples(samples), "", sr("WSBIN_URL/ws-echo"), statusProtocolSwitch, "") t.Run("send_receive", func(t *testing.T) { _, err := rt.RunString(sr(` @@ -239,7 +237,7 @@ func TestSession(t *testing.T) { require.NoError(t, err) }) - samplesBuf := stats.GetBufferedSamples(samples) + samplesBuf := metrics.GetBufferedSamples(samples) assertSessionMetricsEmitted(t, samplesBuf, "", sr("WSBIN_URL/ws-echo"), statusProtocolSwitch, "") assertMetricEmittedCount(t, metrics.WSMessagesSentName, samplesBuf, sr("WSBIN_URL/ws-echo"), 1) assertMetricEmittedCount(t, metrics.WSMessagesReceivedName, samplesBuf, sr("WSBIN_URL/ws-echo"), 1) @@ -257,7 +255,7 @@ func TestSession(t *testing.T) { `)) require.NoError(t, err) }) - assertSessionMetricsEmitted(t, stats.GetBufferedSamples(samples), "", sr("WSBIN_URL/ws-echo"), statusProtocolSwitch, "") + assertSessionMetricsEmitted(t, metrics.GetBufferedSamples(samples), "", sr("WSBIN_URL/ws-echo"), statusProtocolSwitch, "") t.Run("bad interval", func(t *testing.T) { _, err := rt.RunString(sr(` var counter = 0; @@ -303,7 +301,7 @@ func TestSession(t *testing.T) { require.Error(t, err) require.Contains(t, err.Error(), "setTimeout requires a >0 timeout parameter, received 0.00 ") }) - assertSessionMetricsEmitted(t, stats.GetBufferedSamples(samples), "", sr("WSBIN_URL/ws-echo"), statusProtocolSwitch, "") + assertSessionMetricsEmitted(t, metrics.GetBufferedSamples(samples), "", sr("WSBIN_URL/ws-echo"), statusProtocolSwitch, "") t.Run("ping", func(t *testing.T) { _, err := rt.RunString(sr(` @@ -325,7 +323,7 @@ func TestSession(t *testing.T) { require.NoError(t, err) }) - samplesBuf = stats.GetBufferedSamples(samples) + samplesBuf = metrics.GetBufferedSamples(samples) assertSessionMetricsEmitted(t, samplesBuf, "", sr("WSBIN_URL/ws-echo"), statusProtocolSwitch, "") assertMetricEmittedCount(t, metrics.WSPingName, samplesBuf, sr("WSBIN_URL/ws-echo"), 1) @@ -359,7 +357,7 @@ func TestSession(t *testing.T) { require.NoError(t, err) }) - samplesBuf = stats.GetBufferedSamples(samples) + samplesBuf = metrics.GetBufferedSamples(samples) assertSessionMetricsEmitted(t, samplesBuf, "", sr("WSBIN_URL/ws-echo"), statusProtocolSwitch, "") assertMetricEmittedCount(t, metrics.WSPingName, samplesBuf, sr("WSBIN_URL/ws-echo"), 1) @@ -378,7 +376,7 @@ func TestSession(t *testing.T) { `)) require.NoError(t, err) }) - assertSessionMetricsEmitted(t, stats.GetBufferedSamples(samples), "", sr("WSBIN_URL/ws-echo"), statusProtocolSwitch, "") + assertSessionMetricsEmitted(t, metrics.GetBufferedSamples(samples), "", sr("WSBIN_URL/ws-echo"), statusProtocolSwitch, "") serverCloseTests := []struct { name string @@ -469,7 +467,7 @@ func TestSession(t *testing.T) { require.NoError(t, err) }) - samplesBuf = stats.GetBufferedSamples(samples) + samplesBuf = metrics.GetBufferedSamples(samples) assertSessionMetricsEmitted(t, samplesBuf, "", sr("WSBIN_URL/ws-echo-multi"), statusProtocolSwitch, "") assertMetricEmittedCount(t, metrics.WSMessagesSentName, samplesBuf, sr("WSBIN_URL/ws-echo-multi"), 3) assertMetricEmittedCount(t, metrics.WSMessagesReceivedName, samplesBuf, sr("WSBIN_URL/ws-echo-multi"), 3) @@ -501,7 +499,7 @@ func TestSession(t *testing.T) { require.NoError(t, err) }) - samplesBuf = stats.GetBufferedSamples(samples) + samplesBuf = metrics.GetBufferedSamples(samples) assertSessionMetricsEmitted(t, samplesBuf, "", sr("WSSBIN_URL/ws-echo-multi"), statusProtocolSwitch, "") assertMetricEmittedCount(t, metrics.WSMessagesSentName, samplesBuf, sr("WSSBIN_URL/ws-echo-multi"), 2) assertMetricEmittedCount(t, metrics.WSMessagesReceivedName, samplesBuf, sr("WSSBIN_URL/ws-echo-multi"), 2) @@ -536,7 +534,7 @@ func TestSession(t *testing.T) { require.NoError(t, err) }) - samplesBuf = stats.GetBufferedSamples(samples) + samplesBuf = metrics.GetBufferedSamples(samples) assertSessionMetricsEmitted(t, samplesBuf, "", sr("WSBIN_URL/ws-echo-multi"), statusProtocolSwitch, "") assertMetricEmittedCount(t, metrics.WSMessagesSentName, samplesBuf, sr("WSBIN_URL/ws-echo-multi"), 2) assertMetricEmittedCount(t, metrics.WSMessagesReceivedName, samplesBuf, sr("WSBIN_URL/ws-echo-multi"), 2) @@ -553,16 +551,16 @@ func TestSocketSendBinary(t *testing.T) { //nolint: tparallel rt := goja.New() rt.SetFieldNameMapper(common.FieldNameMapper{}) - samples := make(chan stats.SampleContainer, 1000) + samples := make(chan metrics.SampleContainer, 1000) state := &lib.State{ //nolint: exhaustivestruct Group: root, Dialer: tb.Dialer, Options: lib.Options{ //nolint: exhaustivestruct - SystemTags: stats.NewSystemTagSet( - stats.TagURL, - stats.TagProto, - stats.TagStatus, - stats.TagSubproto, + SystemTags: metrics.NewSystemTagSet( + metrics.TagURL, + metrics.TagProto, + metrics.TagStatus, + metrics.TagSubproto, ), }, Samples: samples, @@ -651,12 +649,12 @@ func TestErrors(t *testing.T) { rt := goja.New() rt.SetFieldNameMapper(common.FieldNameMapper{}) - samples := make(chan stats.SampleContainer, 1000) + samples := make(chan metrics.SampleContainer, 1000) state := &lib.State{ Group: root, Dialer: tb.Dialer, Options: lib.Options{ - SystemTags: &stats.DefaultSystemTagSet, + SystemTags: &metrics.DefaultSystemTagSet, }, Samples: samples, BuiltinMetrics: metrics.RegisterBuiltinMetrics(metrics.NewRegistry()), @@ -719,7 +717,7 @@ func TestErrors(t *testing.T) { } `)) require.NoError(t, err) - assertSessionMetricsEmitted(t, stats.GetBufferedSamples(samples), "", sr("WSBIN_URL/ws-echo-invalid"), statusProtocolSwitch, "") + assertSessionMetricsEmitted(t, metrics.GetBufferedSamples(samples), "", sr("WSBIN_URL/ws-echo-invalid"), statusProtocolSwitch, "") }) t.Run("error on close", func(t *testing.T) { @@ -748,7 +746,7 @@ func TestErrors(t *testing.T) { }); `)) require.NoError(t, err) - assertSessionMetricsEmitted(t, stats.GetBufferedSamples(samples), "", sr("WSBIN_URL/ws-close"), statusProtocolSwitch, "") + assertSessionMetricsEmitted(t, metrics.GetBufferedSamples(samples), "", sr("WSBIN_URL/ws-close"), statusProtocolSwitch, "") }) } @@ -767,11 +765,11 @@ func TestSystemTags(t *testing.T) { // external service demos.kaazing.com (https://github.com/k6io/k6/issues/537) testedSystemTags := []string{"group", "status", "subproto", "url", "ip"} - samples := make(chan stats.SampleContainer, 1000) + samples := make(chan metrics.SampleContainer, 1000) state := &lib.State{ Group: root, Dialer: tb.Dialer, - Options: lib.Options{SystemTags: stats.ToSystemTagSet(testedSystemTags)}, + Options: lib.Options{SystemTags: metrics.ToSystemTagSet(testedSystemTags)}, Samples: samples, TLSConfig: tb.TLSClientConfig, BuiltinMetrics: metrics.RegisterBuiltinMetrics(metrics.NewRegistry()), @@ -789,7 +787,7 @@ func TestSystemTags(t *testing.T) { for _, expectedTag := range testedSystemTags { expectedTag := expectedTag t.Run("only "+expectedTag, func(t *testing.T) { - state.Options.SystemTags = stats.ToSystemTagSet([]string{expectedTag}) + state.Options.SystemTags = metrics.ToSystemTagSet([]string{expectedTag}) _, err := rt.RunString(sr(` var res = ws.connect("WSBIN_URL/ws-echo", function(socket){ socket.on("open", function() { @@ -805,7 +803,7 @@ func TestSystemTags(t *testing.T) { `)) require.NoError(t, err) - for _, sampleContainer := range stats.GetBufferedSamples(samples) { + for _, sampleContainer := range metrics.GetBufferedSamples(samples) { for _, sample := range sampleContainer.GetSamples() { for emittedTag := range sample.Tags.CloneTags() { assert.Equal(t, expectedTag, emittedTag) @@ -826,17 +824,17 @@ func TestTLSConfig(t *testing.T) { rt := goja.New() rt.SetFieldNameMapper(common.FieldNameMapper{}) - samples := make(chan stats.SampleContainer, 1000) + samples := make(chan metrics.SampleContainer, 1000) state := &lib.State{ Group: root, Dialer: tb.Dialer, Options: lib.Options{ - SystemTags: stats.NewSystemTagSet( - stats.TagURL, - stats.TagProto, - stats.TagStatus, - stats.TagSubproto, - stats.TagIP, + SystemTags: metrics.NewSystemTagSet( + metrics.TagURL, + metrics.TagProto, + metrics.TagStatus, + metrics.TagSubproto, + metrics.TagIP, ), }, Samples: samples, @@ -865,7 +863,7 @@ func TestTLSConfig(t *testing.T) { `)) require.NoError(t, err) }) - assertSessionMetricsEmitted(t, stats.GetBufferedSamples(samples), "", sr("WSSBIN_URL/ws-close"), statusProtocolSwitch, "") + assertSessionMetricsEmitted(t, metrics.GetBufferedSamples(samples), "", sr("WSSBIN_URL/ws-close"), statusProtocolSwitch, "") t.Run("custom certificates", func(t *testing.T) { state.TLSConfig = tb.TLSClientConfig @@ -880,7 +878,7 @@ func TestTLSConfig(t *testing.T) { `)) require.NoError(t, err) }) - assertSessionMetricsEmitted(t, stats.GetBufferedSamples(samples), "", sr("WSSBIN_URL/ws-close"), statusProtocolSwitch, "") + assertSessionMetricsEmitted(t, metrics.GetBufferedSamples(samples), "", sr("WSSBIN_URL/ws-close"), statusProtocolSwitch, "") } func TestReadPump(t *testing.T) { @@ -967,16 +965,16 @@ func TestUserAgent(t *testing.T) { rt := goja.New() rt.SetFieldNameMapper(common.FieldNameMapper{}) - samples := make(chan stats.SampleContainer, 1000) + samples := make(chan metrics.SampleContainer, 1000) state := &lib.State{ Group: root, Dialer: tb.Dialer, Options: lib.Options{ - SystemTags: stats.NewSystemTagSet( - stats.TagURL, - stats.TagProto, - stats.TagStatus, - stats.TagSubproto, + SystemTags: metrics.NewSystemTagSet( + metrics.TagURL, + metrics.TagProto, + metrics.TagStatus, + metrics.TagSubproto, ), UserAgent: null.StringFrom("TestUserAgent"), }, @@ -1009,7 +1007,7 @@ func TestUserAgent(t *testing.T) { `)) require.NoError(t, err) - assertSessionMetricsEmitted(t, stats.GetBufferedSamples(samples), "", sr("WSBIN_URL/ws-echo-useragent"), statusProtocolSwitch, "") + assertSessionMetricsEmitted(t, metrics.GetBufferedSamples(samples), "", sr("WSBIN_URL/ws-echo-useragent"), statusProtocolSwitch, "") } func TestCompression(t *testing.T) { @@ -1072,7 +1070,7 @@ func TestCompression(t *testing.T) { `)) require.NoError(t, err) - assertSessionMetricsEmitted(t, stats.GetBufferedSamples(ts.samples), "", sr("WSBIN_URL/ws-compression"), statusProtocolSwitch, "") + assertSessionMetricsEmitted(t, metrics.GetBufferedSamples(ts.samples), "", sr("WSBIN_URL/ws-compression"), statusProtocolSwitch, "") }) t.Run("params", func(t *testing.T) { @@ -1146,7 +1144,7 @@ func TestCompression(t *testing.T) { }) } -func clearSamples(tb *httpmultibin.HTTPMultiBin, samples chan stats.SampleContainer) { +func clearSamples(tb *httpmultibin.HTTPMultiBin, samples chan metrics.SampleContainer) { ctxDone := tb.Context.Done() for { select { @@ -1288,5 +1286,5 @@ func TestCookieJar(t *testing.T) { `)) require.NoError(t, err) - assertSessionMetricsEmitted(t, stats.GetBufferedSamples(ts.samples), "", sr("WSBIN_URL/ws-echo-someheader"), statusProtocolSwitch, "") + assertSessionMetricsEmitted(t, metrics.GetBufferedSamples(ts.samples), "", sr("WSBIN_URL/ws-echo-someheader"), statusProtocolSwitch, "") } diff --git a/js/runner.go b/js/runner.go index a8e56588d23..d26e1477704 100644 --- a/js/runner.go +++ b/js/runner.go @@ -53,7 +53,6 @@ import ( "go.k6.io/k6/lib/types" "go.k6.io/k6/loader" "go.k6.io/k6/metrics" - "go.k6.io/k6/stats" ) // Ensure Runner implements the lib.Runner interface @@ -145,7 +144,7 @@ func (r *Runner) MakeArchive() *lib.Archive { } // NewVU returns a new initialized VU. -func (r *Runner) NewVU(idLocal, idGlobal uint64, samplesOut chan<- stats.SampleContainer) (lib.InitializedVU, error) { +func (r *Runner) NewVU(idLocal, idGlobal uint64, samplesOut chan<- metrics.SampleContainer) (lib.InitializedVU, error) { vu, err := r.newVU(idLocal, idGlobal, samplesOut) if err != nil { return nil, err @@ -154,7 +153,7 @@ func (r *Runner) NewVU(idLocal, idGlobal uint64, samplesOut chan<- stats.SampleC } // nolint:funlen -func (r *Runner) newVU(idLocal, idGlobal uint64, samplesOut chan<- stats.SampleContainer) (*VU, error) { +func (r *Runner) newVU(idLocal, idGlobal uint64, samplesOut chan<- metrics.SampleContainer) (*VU, error) { // Instantiate a new bundle, make a VU out of it. moduleVUImpl := newModuleVUImpl() bi, err := r.Bundle.Instantiate(r.Logger, idLocal, moduleVUImpl) @@ -305,7 +304,7 @@ func forceHTTP1() bool { } // Setup runs the setup function if there is one and sets the setupData to the returned value -func (r *Runner) Setup(ctx context.Context, out chan<- stats.SampleContainer) error { +func (r *Runner) Setup(ctx context.Context, out chan<- metrics.SampleContainer) error { setupCtx, setupCancel := context.WithTimeout(ctx, r.getTimeoutFor(consts.SetupFn)) defer setupCancel() @@ -337,7 +336,8 @@ func (r *Runner) SetSetupData(data []byte) { r.setupData = data } -func (r *Runner) Teardown(ctx context.Context, out chan<- stats.SampleContainer) error { +// Teardown runs the teardown function if there is one. +func (r *Runner) Teardown(ctx context.Context, out chan<- metrics.SampleContainer) error { teardownCtx, teardownCancel := context.WithTimeout(ctx, r.getTimeoutFor(consts.TeardownFn)) defer teardownCancel() @@ -372,7 +372,7 @@ func (r *Runner) IsExecutable(name string) bool { func (r *Runner) HandleSummary(ctx context.Context, summary *lib.Summary) (map[string]io.Reader, error) { summaryDataForJS := summarizeMetricsToObject(summary, r.Bundle.Options, r.setupData) - out := make(chan stats.SampleContainer, 100) + out := make(chan metrics.SampleContainer, 100) defer close(out) go func() { // discard all metrics @@ -516,7 +516,12 @@ func parseTTL(ttlS string) (time.Duration, error) { // Runs an exported function in its own temporary VU, optionally with an argument. Execution is // interrupted if the context expires. No error is returned if the part does not exist. -func (r *Runner) runPart(ctx context.Context, out chan<- stats.SampleContainer, name string, arg interface{}) (goja.Value, error) { +func (r *Runner) runPart( + ctx context.Context, + out chan<- metrics.SampleContainer, + name string, + arg interface{}, +) (goja.Value, error) { vu, err := r.newVU(0, 0, out) if err != nil { return goja.Undefined(), err @@ -543,7 +548,7 @@ func (r *Runner) runPart(ctx context.Context, out chan<- stats.SampleContainer, return goja.Undefined(), err } - if r.Bundle.Options.SystemTags.Has(stats.TagGroup) { + if r.Bundle.Options.SystemTags.Has(metrics.TagGroup) { vu.state.Tags.Set("group", group.Path) } vu.state.Group = group @@ -592,7 +597,7 @@ type VU struct { Console *console BPool *bpool.BufferPool - Samples chan<- stats.SampleContainer + Samples chan<- metrics.SampleContainer setupData goja.Value @@ -649,16 +654,16 @@ func (u *VU) Activate(params *lib.VUActivationParams) lib.ActiveVU { for k, v := range params.Tags { u.state.Tags.Set(k, v) } - if opts.SystemTags.Has(stats.TagVU) { + if opts.SystemTags.Has(metrics.TagVU) { u.state.Tags.Set("vu", strconv.FormatUint(u.ID, 10)) } - if opts.SystemTags.Has(stats.TagIter) { + if opts.SystemTags.Has(metrics.TagIter) { u.state.Tags.Set("iter", strconv.FormatInt(u.iteration, 10)) } - if opts.SystemTags.Has(stats.TagGroup) { + if opts.SystemTags.Has(metrics.TagGroup) { u.state.Tags.Set("group", u.state.Group.Path) } - if opts.SystemTags.Has(stats.TagScenario) { + if opts.SystemTags.Has(metrics.TagScenario) { u.state.Tags.Set("scenario", params.Scenario) } @@ -783,7 +788,7 @@ func (u *VU) runFn( } opts := &u.Runner.Bundle.Options - if opts.SystemTags.Has(stats.TagIter) { + if opts.SystemTags.Has(metrics.TagIter) { u.state.Tags.Set("iter", strconv.FormatInt(u.state.Iteration, 10)) } @@ -820,7 +825,7 @@ func (u *VU) runFn( u.Transport.CloseIdleConnections() } - sampleTags := stats.NewSampleTags(u.state.CloneTags()) + sampleTags := metrics.NewSampleTags(u.state.CloneTags()) u.state.Samples <- u.Dialer.GetTrail( startTime, endTime, isFullIteration, isDefault, sampleTags, u.Runner.builtinMetrics) diff --git a/js/runner_test.go b/js/runner_test.go index 111d4f61725..7d6d5342478 100644 --- a/js/runner_test.go +++ b/js/runner_test.go @@ -63,7 +63,6 @@ import ( "go.k6.io/k6/loader" "go.k6.io/k6/metrics" "go.k6.io/k6/output" - "go.k6.io/k6/stats" ) func TestRunnerNew(t *testing.T) { @@ -78,7 +77,7 @@ func TestRunnerNew(t *testing.T) { t.Run("NewVU", func(t *testing.T) { t.Parallel() - initVU, err := r.NewVU(1, 1, make(chan stats.SampleContainer, 100)) + initVU, err := r.NewVU(1, 1, make(chan metrics.SampleContainer, 100)) assert.NoError(t, err) vuc, ok := initVU.(*VU) assert.True(t, ok) @@ -176,7 +175,7 @@ func TestOptionsSettingToScript(t *testing.T) { r.SetOptions(newOptions) require.Equal(t, newOptions, r.GetOptions()) - samples := make(chan stats.SampleContainer, 100) + samples := make(chan metrics.SampleContainer, 100) initVU, err := r.NewVU(1, 1, samples) if assert.NoError(t, err) { ctx, cancel := context.WithCancel(context.Background()) @@ -228,7 +227,7 @@ func TestOptionsPropagationToScript(t *testing.T) { r := r t.Run(name, func(t *testing.T) { t.Parallel() - samples := make(chan stats.SampleContainer, 100) + samples := make(chan metrics.SampleContainer, 100) initVU, err := r.NewVU(1, 1, samples) if assert.NoError(t, err) { @@ -364,7 +363,7 @@ func testSetupDataHelper(t *testing.T, data string) { t.Parallel() ctx, cancel := context.WithCancel(context.Background()) defer cancel() - samples := make(chan stats.SampleContainer, 100) + samples := make(chan metrics.SampleContainer, 100) if !assert.NoError(t, r.Setup(ctx, samples)) { return @@ -431,7 +430,7 @@ func TestConsoleInInitContext(t *testing.T) { r := r t.Run(name, func(t *testing.T) { t.Parallel() - samples := make(chan stats.SampleContainer, 100) + samples := make(chan metrics.SampleContainer, 100) initVU, err := r.NewVU(1, 1, samples) if assert.NoError(t, err) { ctx, cancel := context.WithCancel(context.Background()) @@ -517,7 +516,7 @@ func TestRunnerIntegrationImports(t *testing.T) { for name, r := range testdata { r := r t.Run(name, func(t *testing.T) { - initVU, err := r.NewVU(1, 1, make(chan stats.SampleContainer, 100)) + initVU, err := r.NewVU(1, 1, make(chan metrics.SampleContainer, 100)) require.NoError(t, err) ctx, cancel := context.WithCancel(context.Background()) defer cancel() @@ -550,7 +549,7 @@ func TestVURunContext(t *testing.T) { r := r t.Run(name, func(t *testing.T) { t.Parallel() - vu, err := r.newVU(1, 1, make(chan stats.SampleContainer, 100)) + vu, err := r.newVU(1, 1, make(chan metrics.SampleContainer, 100)) require.NoError(t, err) fnCalled := false @@ -595,7 +594,7 @@ func TestVURunInterrupt(t *testing.T) { name, r := name, r t.Run(name, func(t *testing.T) { t.Parallel() - samples := make(chan stats.SampleContainer, 100) + samples := make(chan metrics.SampleContainer, 100) defer close(samples) go func() { for range samples { @@ -634,7 +633,7 @@ func TestVURunInterruptDoesntPanic(t *testing.T) { t.Parallel() ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() - samples := make(chan stats.SampleContainer, 100) + samples := make(chan metrics.SampleContainer, 100) defer close(samples) go func() { for range samples { @@ -693,7 +692,7 @@ func TestVUIntegrationGroups(t *testing.T) { r := r t.Run(name, func(t *testing.T) { t.Parallel() - vu, err := r.newVU(1, 1, make(chan stats.SampleContainer, 100)) + vu, err := r.newVU(1, 1, make(chan metrics.SampleContainer, 100)) require.NoError(t, err) fnOuterCalled := false @@ -748,7 +747,7 @@ func TestVUIntegrationMetrics(t *testing.T) { r := r t.Run(name, func(t *testing.T) { t.Parallel() - samples := make(chan stats.SampleContainer, 100) + samples := make(chan metrics.SampleContainer, 100) defer close(samples) vu, err := r.newVU(1, 1, samples) require.NoError(t, err) @@ -759,14 +758,14 @@ func TestVUIntegrationMetrics(t *testing.T) { err = activeVU.RunOnce() assert.NoError(t, err) sampleCount := 0 - for i, sampleC := range stats.GetBufferedSamples(samples) { + for i, sampleC := range metrics.GetBufferedSamples(samples) { for j, s := range sampleC.GetSamples() { sampleCount++ switch i + j { case 0: assert.Equal(t, 5.0, s.Value) assert.Equal(t, "my_metric", s.Metric.Name) - assert.Equal(t, stats.Trend, s.Metric.Type) + assert.Equal(t, metrics.Trend, s.Metric.Type) case 1: assert.Equal(t, 0.0, s.Value) assert.Equal(t, builtinMetrics.DataSent, s.Metric, "`data_sent` sample is before `data_received` and `iteration_duration`") @@ -827,7 +826,7 @@ func TestVUIntegrationInsecureRequests(t *testing.T) { t.Parallel() r.Logger, _ = logtest.NewNullLogger() - initVU, err := r.NewVU(1, 1, make(chan stats.SampleContainer, 100)) + initVU, err := r.NewVU(1, 1, make(chan metrics.SampleContainer, 100)) require.NoError(t, err) ctx, cancel := context.WithCancel(context.Background()) @@ -872,7 +871,7 @@ func TestVUIntegrationBlacklistOption(t *testing.T) { r := r t.Run(name, func(t *testing.T) { t.Parallel() - initVU, err := r.NewVU(1, 1, make(chan stats.SampleContainer, 100)) + initVU, err := r.NewVU(1, 1, make(chan metrics.SampleContainer, 100)) require.NoError(t, err) ctx, cancel := context.WithCancel(context.Background()) defer cancel() @@ -909,7 +908,7 @@ func TestVUIntegrationBlacklistScript(t *testing.T) { r := r t.Run(name, func(t *testing.T) { t.Parallel() - initVU, err := r.NewVU(1, 1, make(chan stats.SampleContainer, 100)) + initVU, err := r.NewVU(1, 1, make(chan metrics.SampleContainer, 100)) require.NoError(t, err) ctx, cancel := context.WithCancel(context.Background()) defer cancel() @@ -947,7 +946,7 @@ func TestVUIntegrationBlockHostnamesOption(t *testing.T) { r := r t.Run(name, func(t *testing.T) { t.Parallel() - initVu, err := r.NewVU(1, 1, make(chan stats.SampleContainer, 100)) + initVu, err := r.NewVU(1, 1, make(chan metrics.SampleContainer, 100)) require.NoError(t, err) ctx, cancel := context.WithCancel(context.Background()) @@ -985,7 +984,7 @@ func TestVUIntegrationBlockHostnamesScript(t *testing.T) { r := r t.Run(name, func(t *testing.T) { t.Parallel() - initVu, err := r.NewVU(0, 0, make(chan stats.SampleContainer, 100)) + initVu, err := r.NewVU(0, 0, make(chan metrics.SampleContainer, 100)) require.NoError(t, err) ctx, cancel := context.WithCancel(context.Background()) defer cancel() @@ -1033,7 +1032,7 @@ func TestVUIntegrationHosts(t *testing.T) { r := r t.Run(name, func(t *testing.T) { t.Parallel() - initVU, err := r.NewVU(1, 1, make(chan stats.SampleContainer, 100)) + initVU, err := r.NewVU(1, 1, make(chan metrics.SampleContainer, 100)) require.NoError(t, err) ctx, cancel := context.WithCancel(context.Background()) @@ -1106,7 +1105,7 @@ func TestVUIntegrationTLSConfig(t *testing.T) { t.Parallel() r.Logger, _ = logtest.NewNullLogger() - initVU, err := r.NewVU(1, 1, make(chan stats.SampleContainer, 100)) + initVU, err := r.NewVU(1, 1, make(chan metrics.SampleContainer, 100)) require.NoError(t, err) ctx, cancel := context.WithCancel(context.Background()) defer cancel() @@ -1131,7 +1130,7 @@ func TestVUIntegrationOpenFunctionError(t *testing.T) { `) assert.NoError(t, err) - initVU, err := r.NewVU(1, 1, make(chan stats.SampleContainer, 100)) + initVU, err := r.NewVU(1, 1, make(chan metrics.SampleContainer, 100)) assert.NoError(t, err) ctx, cancel := context.WithCancel(context.Background()) defer cancel() @@ -1149,7 +1148,7 @@ func TestVUIntegrationOpenFunctionErrorWhenSneaky(t *testing.T) { `) assert.NoError(t, err) - initVU, err := r.NewVU(1, 1, make(chan stats.SampleContainer, 100)) + initVU, err := r.NewVU(1, 1, make(chan metrics.SampleContainer, 100)) assert.NoError(t, err) ctx, cancel := context.WithCancel(context.Background()) defer cancel() @@ -1179,7 +1178,7 @@ func TestVUDoesOpenUnderV0Condition(t *testing.T) { r, err := getSimpleRunner(t, "/script.js", data, fs) require.NoError(t, err) - _, err = r.NewVU(1, 1, make(chan stats.SampleContainer, 100)) + _, err = r.NewVU(1, 1, make(chan metrics.SampleContainer, 100)) assert.NoError(t, err) } @@ -1203,7 +1202,7 @@ func TestVUDoesNotOpenUnderConditions(t *testing.T) { r, err := getSimpleRunner(t, "/script.js", data, fs) require.NoError(t, err) - _, err = r.NewVU(1, 1, make(chan stats.SampleContainer, 100)) + _, err = r.NewVU(1, 1, make(chan metrics.SampleContainer, 100)) assert.Error(t, err) assert.Contains(t, err.Error(), "open() can't be used with files that weren't previously opened during initialization (__VU==0)") } @@ -1227,7 +1226,7 @@ func TestVUDoesNonExistingPathnUnderConditions(t *testing.T) { r, err := getSimpleRunner(t, "/script.js", data, fs) require.NoError(t, err) - _, err = r.NewVU(1, 1, make(chan stats.SampleContainer, 100)) + _, err = r.NewVU(1, 1, make(chan metrics.SampleContainer, 100)) assert.Error(t, err) assert.Contains(t, err.Error(), "open() can't be used with files that weren't previously opened during initialization (__VU==0)") } @@ -1270,7 +1269,7 @@ func TestVUIntegrationCookiesReset(t *testing.T) { r := r t.Run(name, func(t *testing.T) { t.Parallel() - initVU, err := r.NewVU(1, 1, make(chan stats.SampleContainer, 100)) + initVU, err := r.NewVU(1, 1, make(chan metrics.SampleContainer, 100)) require.NoError(t, err) ctx, cancel := context.WithCancel(context.Background()) defer cancel() @@ -1326,7 +1325,7 @@ func TestVUIntegrationCookiesNoReset(t *testing.T) { r := r t.Run(name, func(t *testing.T) { t.Parallel() - initVU, err := r.NewVU(1, 1, make(chan stats.SampleContainer, 100)) + initVU, err := r.NewVU(1, 1, make(chan metrics.SampleContainer, 100)) require.NoError(t, err) ctx, cancel := context.WithCancel(context.Background()) @@ -1361,7 +1360,7 @@ func TestVUIntegrationVUID(t *testing.T) { r := r t.Run(name, func(t *testing.T) { t.Parallel() - initVU, err := r.NewVU(1234, 1234, make(chan stats.SampleContainer, 100)) + initVU, err := r.NewVU(1234, 1234, make(chan metrics.SampleContainer, 100)) require.NoError(t, err) ctx, cancel := context.WithCancel(context.Background()) @@ -1513,7 +1512,7 @@ func TestVUIntegrationClientCerts(t *testing.T) { t.Run(name, func(t *testing.T) { t.Parallel() r.Logger, _ = logtest.NewNullLogger() - initVU, err := r.NewVU(1, 1, make(chan stats.SampleContainer, 100)) + initVU, err := r.NewVU(1, 1, make(chan metrics.SampleContainer, 100)) if assert.NoError(t, err) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() @@ -1676,7 +1675,7 @@ func TestArchiveRunningIntegrity(t *testing.T) { t.Run(name, func(t *testing.T) { t.Parallel() var err error - ch := make(chan stats.SampleContainer, 100) + ch := make(chan metrics.SampleContainer, 100) ctx, cancel := context.WithCancel(context.Background()) defer cancel() err = r.Setup(ctx, ch) @@ -1759,7 +1758,7 @@ func TestStuffNotPanicking(t *testing.T) { `)) require.NoError(t, err) - ch := make(chan stats.SampleContainer, 1000) + ch := make(chan metrics.SampleContainer, 1000) initVU, err := r.NewVU(1, 1, ch) require.NoError(t, err) @@ -1793,7 +1792,7 @@ func TestPanicOnSimpleHTML(t *testing.T) { `) require.NoError(t, err) - ch := make(chan stats.SampleContainer, 1000) + ch := make(chan metrics.SampleContainer, 1000) initVU, err := r.NewVU(1, 1, ch) require.NoError(t, err) @@ -1850,7 +1849,7 @@ func TestSystemTags(t *testing.T) { num, tc := num, tc t.Run(fmt.Sprintf("TC %d with only %s", num, tc.tag), func(t *testing.T) { t.Parallel() - samples := make(chan stats.SampleContainer, 100) + samples := make(chan metrics.SampleContainer, 100) r, err := getSimpleRunner(t, "/script.js", tb.Replacer.Replace(` var http = require("k6/http"); @@ -1869,7 +1868,7 @@ func TestSystemTags(t *testing.T) { require.NoError(t, r.SetOptions(r.GetOptions().Apply(lib.Options{ Throw: null.BoolFrom(false), TLSVersion: &lib.TLSVersions{Max: tls.VersionTLS13}, - SystemTags: stats.ToSystemTagSet([]string{tc.tag}), + SystemTags: metrics.ToSystemTagSet([]string{tc.tag}), InsecureSkipTLSVerify: null.BoolFrom(true), }))) @@ -1885,7 +1884,7 @@ func TestSystemTags(t *testing.T) { }) require.NoError(t, activeVU.RunOnce()) - bufSamples := stats.GetBufferedSamples(samples) + bufSamples := metrics.GetBufferedSamples(samples) require.NotEmpty(t, bufSamples) for _, sample := range bufSamples[0].GetSamples() { assert.NotEmpty(t, sample.Tags) @@ -1923,7 +1922,7 @@ func TestVUPanic(t *testing.T) { r := r t.Run(name, func(t *testing.T) { t.Parallel() - initVU, err := r.NewVU(1, 1234, make(chan stats.SampleContainer, 100)) + initVU, err := r.NewVU(1, 1234, make(chan metrics.SampleContainer, 100)) require.NoError(t, err) logger := logrus.New() @@ -1970,7 +1969,7 @@ type multiFileTestCase struct { script string expInitErr bool expVUErr bool - samples chan stats.SampleContainer + samples chan metrics.SampleContainer } func runMultiFileTestCase(t *testing.T, tc multiFileTestCase, tb *httpmultibin.HTTPMultiBin) { @@ -2084,7 +2083,7 @@ func TestComplicatedFileImportsForGRPC(t *testing.T) { return multiFileTestCase{ fses: map[string]afero.Fs{"file": fs, "https": afero.NewMemMapFs()}, rtOpts: lib.RuntimeOptions{CompatibilityMode: null.NewString("base", true)}, - samples: make(chan stats.SampleContainer, 100), + samples: make(chan metrics.SampleContainer, 100), cwd: cwd, expInitErr: expInitErr, expVUErr: expVUErr, script: script, } } @@ -2155,7 +2154,7 @@ func TestMinIterationDurationIsCancellable(t *testing.T) { `) require.NoError(t, err) - ch := make(chan stats.SampleContainer, 1000) + ch := make(chan metrics.SampleContainer, 1000) initVU, err := r.NewVU(1, 1, ch) require.NoError(t, err) @@ -2244,7 +2243,7 @@ func TestForceHTTP1Feature(t *testing.T) { for name, r := range runners { r := r t.Run(name, func(t *testing.T) { - initVU, err := r.NewVU(1, 1, make(chan stats.SampleContainer, 100)) + initVU, err := r.NewVU(1, 1, make(chan metrics.SampleContainer, 100)) require.NoError(t, err) ctx, cancel := context.WithCancel(context.Background()) @@ -2324,8 +2323,8 @@ func TestExecutionInfo(t *testing.T) { } require.NoError(t, err) - r.Bundle.Options.SystemTags = stats.NewSystemTagSet(stats.DefaultSystemTagSet) - samples := make(chan stats.SampleContainer, 100) + r.Bundle.Options.SystemTags = metrics.NewSystemTagSet(metrics.DefaultSystemTagSet) + samples := make(chan metrics.SampleContainer, 100) initVU, err := r.NewVU(1, 10, samples) require.NoError(t, err) diff --git a/js/share_test.go b/js/share_test.go index fadfe122436..2978c34b07b 100644 --- a/js/share_test.go +++ b/js/share_test.go @@ -32,7 +32,6 @@ import ( "go.k6.io/k6/lib" "go.k6.io/k6/lib/testutils" "go.k6.io/k6/metrics" - "go.k6.io/k6/stats" ) func TestNewSharedArrayIntegration(t *testing.T) { @@ -97,7 +96,7 @@ exports.default = function() { r := r t.Run(name, func(t *testing.T) { t.Parallel() - samples := make(chan stats.SampleContainer, 100) + samples := make(chan metrics.SampleContainer, 100) initVU, err := r.NewVU(1, 1, samples) require.NoError(t, err) diff --git a/js/summary.go b/js/summary.go index 405006cbfb9..44b743e4788 100644 --- a/js/summary.go +++ b/js/summary.go @@ -30,7 +30,7 @@ import ( "github.com/dop251/goja" "go.k6.io/k6/js/common" "go.k6.io/k6/lib" - "go.k6.io/k6/stats" + "go.k6.io/k6/metrics" ) // Copied from https://github.com/k6io/jslib.k6.io/tree/master/lib/k6-summary @@ -42,32 +42,32 @@ var summaryWrapperLambdaCode string //nolint:gochecknoglobals // TODO: figure out something saner... refactor the sinks and how we deal with // metrics in general... so much pain and misery... :sob: -func metricValueGetter(summaryTrendStats []string) func(stats.Sink, time.Duration) map[string]float64 { - trendResolvers, err := stats.GetResolversForTrendColumns(summaryTrendStats) +func metricValueGetter(summaryTrendStats []string) func(metrics.Sink, time.Duration) map[string]float64 { + trendResolvers, err := metrics.GetResolversForTrendColumns(summaryTrendStats) if err != nil { panic(err.Error()) // this should have been validated already } - return func(sink stats.Sink, t time.Duration) (result map[string]float64) { + return func(sink metrics.Sink, t time.Duration) (result map[string]float64) { sink.Calc() switch sink := sink.(type) { - case *stats.CounterSink: + case *metrics.CounterSink: result = sink.Format(t) rate := 0.0 if t > 0 { rate = sink.Value / (float64(t) / float64(time.Second)) } result["rate"] = rate - case *stats.GaugeSink: + case *metrics.GaugeSink: result = sink.Format(t) result["min"] = sink.Min result["max"] = sink.Max - case *stats.RateSink: + case *metrics.RateSink: result = sink.Format(t) result["passes"] = float64(sink.Trues) result["fails"] = float64(sink.Total - sink.Trues) - case *stats.TrendSink: + case *metrics.TrendSink: result = make(map[string]float64, len(summaryTrendStats)) for _, col := range summaryTrendStats { result[col] = trendResolvers[col](sink) diff --git a/js/summary_test.go b/js/summary_test.go index 335847270fc..cf3bc52efed 100644 --- a/js/summary_test.go +++ b/js/summary_test.go @@ -36,7 +36,6 @@ import ( "go.k6.io/k6/lib" "go.k6.io/k6/lib/testutils" "go.k6.io/k6/metrics" - "go.k6.io/k6/stats" ) const ( @@ -100,23 +99,23 @@ func TestTextSummaryWithSubMetrics(t *testing.T) { t.Parallel() registry := metrics.NewRegistry() - parentMetric, err := registry.NewMetric("my_parent", stats.Counter) + parentMetric, err := registry.NewMetric("my_parent", metrics.Counter) require.NoError(t, err) - parentMetric.Sink.Add(stats.Sample{Value: 11}) + parentMetric.Sink.Add(metrics.Sample{Value: 11}) - parentMetricPost, err := registry.NewMetric("my_parent_post", stats.Counter) + parentMetricPost, err := registry.NewMetric("my_parent_post", metrics.Counter) require.NoError(t, err) - parentMetricPost.Sink.Add(stats.Sample{Value: 22}) + parentMetricPost.Sink.Add(metrics.Sample{Value: 22}) subMetric, err := parentMetric.AddSubmetric("sub:1") require.NoError(t, err) - subMetric.Metric.Sink.Add(stats.Sample{Value: 1}) + subMetric.Metric.Sink.Add(metrics.Sample{Value: 1}) subMetricPost, err := parentMetricPost.AddSubmetric("sub:2") require.NoError(t, err) - subMetricPost.Metric.Sink.Add(stats.Sample{Value: 2}) + subMetricPost.Metric.Sink.Add(metrics.Sample{Value: 2}) - metrics := map[string]*stats.Metric{ + metrics := map[string]*metrics.Metric{ parentMetric.Name: parentMetric, parentMetricPost.Name: parentMetricPost, subMetric.Name: subMetric.Metric, @@ -154,42 +153,42 @@ func TestTextSummaryWithSubMetrics(t *testing.T) { assert.Equal(t, "\n"+expected+"\n", string(summaryOut)) } -func createTestMetrics(t *testing.T) (map[string]*stats.Metric, *lib.Group) { +func createTestMetrics(t *testing.T) (map[string]*metrics.Metric, *lib.Group) { registry := metrics.NewRegistry() - metrics := make(map[string]*stats.Metric) + testMetrics := make(map[string]*metrics.Metric) - gaugeMetric, err := registry.NewMetric("vus", stats.Gauge) + gaugeMetric, err := registry.NewMetric("vus", metrics.Gauge) require.NoError(t, err) - gaugeMetric.Sink.Add(stats.Sample{Value: 1}) + gaugeMetric.Sink.Add(metrics.Sample{Value: 1}) - countMetric, err := registry.NewMetric("http_reqs", stats.Counter) + countMetric, err := registry.NewMetric("http_reqs", metrics.Counter) require.NoError(t, err) countMetric.Tainted = null.BoolFrom(true) - countMetric.Thresholds = stats.Thresholds{Thresholds: []*stats.Threshold{{Source: "rate<100", LastFailed: true}}} + countMetric.Thresholds = metrics.Thresholds{Thresholds: []*metrics.Threshold{{Source: "rate<100", LastFailed: true}}} - checksMetric, err := registry.NewMetric("checks", stats.Rate) + checksMetric, err := registry.NewMetric("checks", metrics.Rate) require.NoError(t, err) checksMetric.Tainted = null.BoolFrom(false) - checksMetric.Thresholds = stats.Thresholds{Thresholds: []*stats.Threshold{{Source: "rate>70", LastFailed: false}}} - sink := &stats.TrendSink{} + checksMetric.Thresholds = metrics.Thresholds{Thresholds: []*metrics.Threshold{{Source: "rate>70", LastFailed: false}}} + sink := &metrics.TrendSink{} samples := []float64{10.0, 15.0, 20.0} for _, s := range samples { - sink.Add(stats.Sample{Value: s}) - countMetric.Sink.Add(stats.Sample{Value: 1}) + sink.Add(metrics.Sample{Value: s}) + countMetric.Sink.Add(metrics.Sample{Value: 1}) } - metrics["vus"] = gaugeMetric - metrics["http_reqs"] = countMetric - metrics["checks"] = checksMetric - metrics["my_trend"] = &stats.Metric{ + testMetrics["vus"] = gaugeMetric + testMetrics["http_reqs"] = countMetric + testMetrics["checks"] = checksMetric + testMetrics["my_trend"] = &metrics.Metric{ Name: "my_trend", - Type: stats.Trend, - Contains: stats.Time, + Type: metrics.Trend, + Contains: metrics.Time, Sink: sink, Tainted: null.BoolFrom(true), - Thresholds: stats.Thresholds{ - Thresholds: []*stats.Threshold{ + Thresholds: metrics.Thresholds{ + Thresholds: []*metrics.Threshold{ { Source: "my_trend<1000", LastFailed: true, @@ -217,13 +216,13 @@ func createTestMetrics(t *testing.T) (map[string]*stats.Metric, *lib.Group) { check2.Fails = 10 for i := 0; i < int(check1.Passes+check2.Passes+check3.Passes); i++ { - checksMetric.Sink.Add(stats.Sample{Value: 1}) + checksMetric.Sink.Add(metrics.Sample{Value: 1}) } for i := 0; i < int(check1.Fails+check2.Fails+check3.Fails); i++ { - checksMetric.Sink.Add(stats.Sample{Value: 0}) + checksMetric.Sink.Add(metrics.Sample{Value: 0}) } - return metrics, rootG + return testMetrics, rootG } func createTestSummary(t *testing.T) *lib.Summary { diff --git a/lib/archive_test.go b/lib/archive_test.go index 67faf13e950..40b8fc78cf1 100644 --- a/lib/archive_test.go +++ b/lib/archive_test.go @@ -37,7 +37,7 @@ import ( "go.k6.io/k6/lib/consts" "go.k6.io/k6/lib/fsext" - "go.k6.io/k6/stats" + "go.k6.io/k6/metrics" ) func TestNormalizeAndAnonymizePath(t *testing.T) { @@ -142,7 +142,7 @@ func TestArchiveReadWrite(t *testing.T) { K6Version: consts.Version, Options: Options{ VUs: null.IntFrom(12345), - SystemTags: &stats.DefaultSystemTagSet, + SystemTags: &metrics.DefaultSystemTagSet, }, FilenameURL: &url.URL{Scheme: "file", Path: "/path/to/a.js"}, Data: []byte(`// a contents`), @@ -192,7 +192,7 @@ func TestArchiveReadWrite(t *testing.T) { Type: "js", Options: Options{ VUs: null.IntFrom(12345), - SystemTags: &stats.DefaultSystemTagSet, + SystemTags: &metrics.DefaultSystemTagSet, }, FilenameURL: &url.URL{Scheme: "file", Path: fmt.Sprintf("%s/a.js", entry.Pwd)}, K6Version: consts.Version, @@ -215,7 +215,7 @@ func TestArchiveReadWrite(t *testing.T) { Type: "js", Options: Options{ VUs: null.IntFrom(12345), - SystemTags: &stats.DefaultSystemTagSet, + SystemTags: &metrics.DefaultSystemTagSet, }, FilenameURL: &url.URL{Scheme: "file", Path: fmt.Sprintf("%s/a.js", entry.PwdNormAnon)}, K6Version: consts.Version, @@ -344,7 +344,7 @@ func TestStrangePaths(t *testing.T) { K6Version: consts.Version, Options: Options{ VUs: null.IntFrom(12345), - SystemTags: &stats.DefaultSystemTagSet, + SystemTags: &metrics.DefaultSystemTagSet, }, FilenameURL: &url.URL{Scheme: "file", Path: pathToChange}, Data: []byte(`// ` + pathToChange + ` contents`), diff --git a/lib/execution.go b/lib/execution.go index 69c8b6c4dc3..dd8959b5828 100644 --- a/lib/execution.go +++ b/lib/execution.go @@ -31,7 +31,6 @@ import ( "github.com/sirupsen/logrus" "go.k6.io/k6/metrics" - "go.k6.io/k6/stats" ) // An ExecutionScheduler is in charge of initializing executors and using them @@ -58,11 +57,11 @@ type ExecutionScheduler interface { GetExecutors() []Executor // Init initializes all executors, including all of their needed VUs. - Init(ctx context.Context, samplesOut chan<- stats.SampleContainer) error + Init(ctx context.Context, samplesOut chan<- metrics.SampleContainer) error // Run the ExecutionScheduler, funneling the generated metric samples // through the supplied out channel. - Run(globalCtx, runCtx context.Context, samplesOut chan<- stats.SampleContainer) error + Run(globalCtx, runCtx context.Context, samplesOut chan<- metrics.SampleContainer) error // Pause a test, or start/resume it. To check if a test is paused, use // GetState().IsPaused(). diff --git a/lib/executor/base_executor.go b/lib/executor/base_executor.go index 9a65d4e5e9b..830abf234f7 100644 --- a/lib/executor/base_executor.go +++ b/lib/executor/base_executor.go @@ -28,7 +28,7 @@ import ( "github.com/sirupsen/logrus" "go.k6.io/k6/lib" - "go.k6.io/k6/stats" + "go.k6.io/k6/metrics" "go.k6.io/k6/ui/pb" ) @@ -92,13 +92,13 @@ func (bs *BaseExecutor) GetProgress() *pb.ProgressBar { // getMetricTags returns a tag set that can be used to emit metrics by the // executor. The VU ID is optional. -func (bs *BaseExecutor) getMetricTags(vuID *uint64) *stats.SampleTags { +func (bs *BaseExecutor) getMetricTags(vuID *uint64) *metrics.SampleTags { tags := bs.executionState.Options.RunTags.CloneTags() - if bs.executionState.Options.SystemTags.Has(stats.TagScenario) { + if bs.executionState.Options.SystemTags.Has(metrics.TagScenario) { tags["scenario"] = bs.config.GetName() } - if vuID != nil && bs.executionState.Options.SystemTags.Has(stats.TagVU) { + if vuID != nil && bs.executionState.Options.SystemTags.Has(metrics.TagVU) { tags["vu"] = strconv.FormatUint(*vuID, 10) } - return stats.IntoSampleTags(&tags) + return metrics.IntoSampleTags(&tags) } diff --git a/lib/executor/common_test.go b/lib/executor/common_test.go index 8e876dd6b08..60783cdfe96 100644 --- a/lib/executor/common_test.go +++ b/lib/executor/common_test.go @@ -31,12 +31,12 @@ import ( "go.k6.io/k6/lib" "go.k6.io/k6/lib/testutils" "go.k6.io/k6/lib/testutils/minirunner" - "go.k6.io/k6/stats" + "go.k6.io/k6/metrics" ) func simpleRunner(vuFn func(context.Context, *lib.State) error) lib.Runner { return &minirunner.MiniRunner{ - Fn: func(ctx context.Context, state *lib.State, _ chan<- stats.SampleContainer) error { + Fn: func(ctx context.Context, state *lib.State, _ chan<- metrics.SampleContainer) error { return vuFn(ctx, state) }, } @@ -46,7 +46,7 @@ func setupExecutor(t testing.TB, config lib.ExecutorConfig, es *lib.ExecutionSta context.Context, context.CancelFunc, lib.Executor, *testutils.SimpleLogrusHook, ) { ctx, cancel := context.WithCancel(context.Background()) - engineOut := make(chan stats.SampleContainer, 100) // TODO: return this for more complicated tests? + engineOut := make(chan metrics.SampleContainer, 100) // TODO: return this for more complicated tests? logHook := &testutils.SimpleLogrusHook{HookedLevels: []logrus.Level{logrus.WarnLevel}} testLog := logrus.New() diff --git a/lib/executor/constant_arrival_rate.go b/lib/executor/constant_arrival_rate.go index 2e5000c63f5..925d6feab06 100644 --- a/lib/executor/constant_arrival_rate.go +++ b/lib/executor/constant_arrival_rate.go @@ -34,7 +34,7 @@ import ( "go.k6.io/k6/lib" "go.k6.io/k6/lib/types" - "go.k6.io/k6/stats" + "go.k6.io/k6/metrics" "go.k6.io/k6/ui/pb" ) @@ -211,7 +211,7 @@ func (car *ConstantArrivalRate) Init(ctx context.Context) error { // This will allow us to implement https://github.com/k6io/k6/issues/1386 // and things like all of the TODOs below in one place only. //nolint:funlen,cyclop -func (car ConstantArrivalRate) Run(parentCtx context.Context, out chan<- stats.SampleContainer) (err error) { +func (car ConstantArrivalRate) Run(parentCtx context.Context, out chan<- metrics.SampleContainer) (err error) { gracefulStop := car.config.GetGracefulStop() duration := car.config.Duration.TimeDuration() preAllocatedVUs := car.config.GetPreAllocatedVUs(car.executionState.ExecutionTuple) @@ -344,7 +344,7 @@ func (car ConstantArrivalRate) Run(parentCtx context.Context, out chan<- stats.S // Since there aren't any free VUs available, consider this iteration // dropped - we aren't going to try to recover it, but - stats.PushIfNotDone(parentCtx, out, stats.Sample{ + metrics.PushIfNotDone(parentCtx, out, metrics.Sample{ Value: 1, Metric: droppedIterationMetric, Tags: metricTags, Time: time.Now(), }) diff --git a/lib/executor/constant_arrival_rate_test.go b/lib/executor/constant_arrival_rate_test.go index 563789aaf4c..7bca39fa9d8 100644 --- a/lib/executor/constant_arrival_rate_test.go +++ b/lib/executor/constant_arrival_rate_test.go @@ -37,7 +37,6 @@ import ( "go.k6.io/k6/lib/testutils/minirunner" "go.k6.io/k6/lib/types" "go.k6.io/k6/metrics" - "go.k6.io/k6/stats" ) func newExecutionSegmentFromString(str string) *lib.ExecutionSegment { @@ -83,7 +82,7 @@ func TestConstantArrivalRateRunNotEnoughAllocatedVUsWarn(t *testing.T) { }), ) defer cancel() - engineOut := make(chan stats.SampleContainer, 1000) + engineOut := make(chan metrics.SampleContainer, 1000) err = executor.Run(ctx, engineOut) require.NoError(t, err) entries := logHook.Drain() @@ -125,7 +124,7 @@ func TestConstantArrivalRateRunCorrectRate(t *testing.T) { require.InDelta(t, 50, currentCount, 1) } }() - engineOut := make(chan stats.SampleContainer, 1000) + engineOut := make(chan metrics.SampleContainer, 1000) err = executor.Run(ctx, engineOut) wg.Wait() require.NoError(t, err) @@ -248,7 +247,7 @@ func TestConstantArrivalRateRunCorrectTiming(t *testing.T) { } }() startTime = time.Now() - engineOut := make(chan stats.SampleContainer, 1000) + engineOut := make(chan metrics.SampleContainer, 1000) err = executor.Run(ctx, engineOut) wg.Wait() require.NoError(t, err) @@ -291,7 +290,7 @@ func TestArrivalRateCancel(t *testing.T) { go func() { defer wg.Done() - engineOut := make(chan stats.SampleContainer, 1000) + engineOut := make(chan metrics.SampleContainer, 1000) errCh <- executor.Run(ctx, engineOut) close(weAreDoneCh) }() @@ -341,7 +340,7 @@ func TestConstantArrivalRateDroppedIterations(t *testing.T) { }), ) defer cancel() - engineOut := make(chan stats.SampleContainer, 1000) + engineOut := make(chan metrics.SampleContainer, 1000) err = executor.Run(ctx, engineOut) require.NoError(t, err) logs := logHook.Drain() @@ -392,14 +391,14 @@ func TestConstantArrivalRateGlobalIters(t *testing.T) { gotIters := []uint64{} var mx sync.Mutex - runner.Fn = func(ctx context.Context, state *lib.State, _ chan<- stats.SampleContainer) error { + runner.Fn = func(ctx context.Context, state *lib.State, _ chan<- metrics.SampleContainer) error { mx.Lock() gotIters = append(gotIters, state.GetScenarioGlobalVUIter()) mx.Unlock() return nil } - engineOut := make(chan stats.SampleContainer, 100) + engineOut := make(chan metrics.SampleContainer, 100) err = executor.Run(ctx, engineOut) require.NoError(t, err) assert.Equal(t, tc.expIters, gotIters) diff --git a/lib/executor/constant_vus.go b/lib/executor/constant_vus.go index a32f2ca75cd..84a40c9aa71 100644 --- a/lib/executor/constant_vus.go +++ b/lib/executor/constant_vus.go @@ -31,7 +31,7 @@ import ( "go.k6.io/k6/lib" "go.k6.io/k6/lib/types" - "go.k6.io/k6/stats" + "go.k6.io/k6/metrics" "go.k6.io/k6/ui/pb" ) @@ -142,7 +142,7 @@ var _ lib.Executor = &ConstantVUs{} // Run constantly loops through as many iterations as possible on a fixed number // of VUs for the specified duration. -func (clv ConstantVUs) Run(parentCtx context.Context, out chan<- stats.SampleContainer) (err error) { +func (clv ConstantVUs) Run(parentCtx context.Context, out chan<- metrics.SampleContainer) (err error) { numVUs := clv.config.GetVUs(clv.executionState.ExecutionTuple) duration := clv.config.Duration.TimeDuration() gracefulStop := clv.config.GetGracefulStop() diff --git a/lib/executor/externally_controlled.go b/lib/executor/externally_controlled.go index 972564ded2b..1e9ed0e5881 100644 --- a/lib/executor/externally_controlled.go +++ b/lib/executor/externally_controlled.go @@ -34,7 +34,7 @@ import ( "go.k6.io/k6/lib" "go.k6.io/k6/lib/types" - "go.k6.io/k6/stats" + "go.k6.io/k6/metrics" "go.k6.io/k6/ui/pb" ) @@ -499,7 +499,7 @@ func (rs *externallyControlledRunState) handleConfigChange(oldCfg, newCfg Extern // dynamically controlled number of VUs either for the specified duration, or // until the test is manually stopped. // nolint:funlen,gocognit,cyclop -func (mex *ExternallyControlled) Run(parentCtx context.Context, out chan<- stats.SampleContainer) (err error) { +func (mex *ExternallyControlled) Run(parentCtx context.Context, out chan<- metrics.SampleContainer) (err error) { mex.configLock.RLock() // Safely get the current config - it's important that the close of the // hasStarted channel is inside of the lock, so that there are no data races diff --git a/lib/executor/helpers_test.go b/lib/executor/helpers_test.go index 6fbf99194fc..f3a872bdd83 100644 --- a/lib/executor/helpers_test.go +++ b/lib/executor/helpers_test.go @@ -20,10 +20,10 @@ package executor -import "go.k6.io/k6/stats" +import "go.k6.io/k6/metrics" -func sumMetricValues(samples chan stats.SampleContainer, metricName string) (sum float64) { - for _, sc := range stats.GetBufferedSamples(samples) { +func sumMetricValues(samples chan metrics.SampleContainer, metricName string) (sum float64) { // nolint: unparam + for _, sc := range metrics.GetBufferedSamples(samples) { samples := sc.GetSamples() for _, s := range samples { if s.Metric.Name == metricName { diff --git a/lib/executor/per_vu_iterations.go b/lib/executor/per_vu_iterations.go index 494f13b474c..fd38a22a82b 100644 --- a/lib/executor/per_vu_iterations.go +++ b/lib/executor/per_vu_iterations.go @@ -32,7 +32,7 @@ import ( "go.k6.io/k6/lib" "go.k6.io/k6/lib/types" - "go.k6.io/k6/stats" + "go.k6.io/k6/metrics" "go.k6.io/k6/ui/pb" ) @@ -151,7 +151,7 @@ var _ lib.Executor = &PerVUIterations{} // Run executes a specific number of iterations with each configured VU. // nolint:funlen -func (pvi PerVUIterations) Run(parentCtx context.Context, out chan<- stats.SampleContainer) (err error) { +func (pvi PerVUIterations) Run(parentCtx context.Context, out chan<- metrics.SampleContainer) (err error) { numVUs := pvi.config.GetVUs(pvi.executionState.ExecutionTuple) iterations := pvi.config.GetIterations() duration := pvi.config.MaxDuration.TimeDuration() @@ -225,7 +225,7 @@ func (pvi PerVUIterations) Run(parentCtx context.Context, out chan<- stats.Sampl for i := int64(0); i < iterations; i++ { select { case <-regDurationDone: - stats.PushIfNotDone(parentCtx, out, stats.Sample{ + metrics.PushIfNotDone(parentCtx, out, metrics.Sample{ Value: float64(iterations - i), Metric: droppedIterationMetric, Tags: pvi.getMetricTags(&vuID), Time: time.Now(), }) diff --git a/lib/executor/per_vu_iterations_test.go b/lib/executor/per_vu_iterations_test.go index f00d2cae38e..517b76a49ea 100644 --- a/lib/executor/per_vu_iterations_test.go +++ b/lib/executor/per_vu_iterations_test.go @@ -34,7 +34,6 @@ import ( "go.k6.io/k6/lib" "go.k6.io/k6/lib/types" "go.k6.io/k6/metrics" - "go.k6.io/k6/stats" ) func getTestPerVUIterationsConfig() PerVUIterationsConfig { @@ -64,7 +63,7 @@ func TestPerVUIterationsRun(t *testing.T) { }), ) defer cancel() - engineOut := make(chan stats.SampleContainer, 1000) + engineOut := make(chan metrics.SampleContainer, 1000) err = executor.Run(ctx, engineOut) require.NoError(t, err) @@ -103,7 +102,7 @@ func TestPerVUIterationsRunVariableVU(t *testing.T) { }), ) defer cancel() - engineOut := make(chan stats.SampleContainer, 1000) + engineOut := make(chan metrics.SampleContainer, 1000) err = executor.Run(ctx, engineOut) require.NoError(t, err) @@ -150,7 +149,7 @@ func TestPerVuIterationsEmitDroppedIterations(t *testing.T) { }), ) defer cancel() - engineOut := make(chan stats.SampleContainer, 1000) + engineOut := make(chan metrics.SampleContainer, 1000) err = executor.Run(ctx, engineOut) require.NoError(t, err) assert.Empty(t, logHook.Drain()) diff --git a/lib/executor/ramping_arrival_rate.go b/lib/executor/ramping_arrival_rate.go index 7b83d640da8..301ec550a34 100644 --- a/lib/executor/ramping_arrival_rate.go +++ b/lib/executor/ramping_arrival_rate.go @@ -33,7 +33,7 @@ import ( "go.k6.io/k6/lib" "go.k6.io/k6/lib/types" - "go.k6.io/k6/stats" + "go.k6.io/k6/metrics" "go.k6.io/k6/ui/pb" ) @@ -319,7 +319,7 @@ func noNegativeSqrt(f float64) float64 { // This will allow us to implement https://github.com/k6io/k6/issues/1386 // and things like all of the TODOs below in one place only. //nolint:funlen,cyclop -func (varr RampingArrivalRate) Run(parentCtx context.Context, out chan<- stats.SampleContainer) (err error) { +func (varr RampingArrivalRate) Run(parentCtx context.Context, out chan<- metrics.SampleContainer) (err error) { segment := varr.executionState.ExecutionTuple.Segment gracefulStop := varr.config.GetGracefulStop() duration := sumStagesDuration(varr.config.Stages) @@ -479,7 +479,7 @@ func (varr RampingArrivalRate) Run(parentCtx context.Context, out chan<- stats.S // Since there aren't any free VUs available, consider this iteration // dropped - we aren't going to try to recover it, but - stats.PushIfNotDone(parentCtx, out, droppedIterationMetric.Sample(time.Now(), metricTags, 1)) + metrics.PushIfNotDone(parentCtx, out, droppedIterationMetric.Sample(time.Now(), metricTags, 1)) // We'll try to start allocating another VU in the background, // non-blockingly, if we have remainingUnplannedVUs... diff --git a/lib/executor/ramping_arrival_rate_test.go b/lib/executor/ramping_arrival_rate_test.go index 980303f0272..13ce6100de5 100644 --- a/lib/executor/ramping_arrival_rate_test.go +++ b/lib/executor/ramping_arrival_rate_test.go @@ -38,7 +38,6 @@ import ( "go.k6.io/k6/lib/testutils/minirunner" "go.k6.io/k6/lib/types" "go.k6.io/k6/metrics" - "go.k6.io/k6/stats" ) func getTestRampingArrivalRateConfig() *RampingArrivalRateConfig { @@ -80,7 +79,7 @@ func TestRampingArrivalRateRunNotEnoughAllocatedVUsWarn(t *testing.T) { }), ) defer cancel() - engineOut := make(chan stats.SampleContainer, 1000) + engineOut := make(chan metrics.SampleContainer, 1000) err = executor.Run(ctx, engineOut) require.NoError(t, err) entries := logHook.Drain() @@ -128,7 +127,7 @@ func TestRampingArrivalRateRunCorrectRate(t *testing.T) { currentCount = atomic.SwapInt64(&count, 0) assert.InDelta(t, 50, currentCount, 3) }() - engineOut := make(chan stats.SampleContainer, 1000) + engineOut := make(chan metrics.SampleContainer, 1000) err = executor.Run(ctx, engineOut) wg.Wait() require.NoError(t, err) @@ -171,7 +170,7 @@ func TestRampingArrivalRateRunUnplannedVUs(t *testing.T) { }, es, runner) defer cancel() - engineOut := make(chan stats.SampleContainer, 1000) + engineOut := make(chan metrics.SampleContainer, 1000) es.SetInitVUFunc(func(_ context.Context, logger *logrus.Entry) (lib.InitializedVU, error) { cur := atomic.LoadInt64(&count) require.Equal(t, cur, int64(1)) @@ -234,7 +233,7 @@ func TestRampingArrivalRateRunCorrectRateWithSlowRate(t *testing.T) { }, es, runner) defer cancel() - engineOut := make(chan stats.SampleContainer, 1000) + engineOut := make(chan metrics.SampleContainer, 1000) es.SetInitVUFunc(func(_ context.Context, logger *logrus.Entry) (lib.InitializedVU, error) { t.Log("init") cur := atomic.LoadInt64(&count) @@ -287,7 +286,7 @@ func TestRampingArrivalRateRunGracefulStop(t *testing.T) { es, runner) defer cancel() - engineOut := make(chan stats.SampleContainer, 1000) + engineOut := make(chan metrics.SampleContainer, 1000) defer close(engineOut) err = executor.Run(ctx, engineOut) @@ -309,7 +308,7 @@ func BenchmarkRampingArrivalRateRun(b *testing.B) { for _, tc := range tests { b.Run(fmt.Sprintf("VUs%d", tc.prealloc.ValueOrZero()), func(b *testing.B) { - engineOut := make(chan stats.SampleContainer, 1000) + engineOut := make(chan metrics.SampleContainer, 1000) defer close(engineOut) go func() { for range engineOut { @@ -757,14 +756,14 @@ func TestRampingArrivalRateGlobalIters(t *testing.T) { gotIters := []uint64{} var mx sync.Mutex - runner.Fn = func(ctx context.Context, state *lib.State, _ chan<- stats.SampleContainer) error { + runner.Fn = func(ctx context.Context, state *lib.State, _ chan<- metrics.SampleContainer) error { mx.Lock() gotIters = append(gotIters, state.GetScenarioGlobalVUIter()) mx.Unlock() return nil } - engineOut := make(chan stats.SampleContainer, 100) + engineOut := make(chan metrics.SampleContainer, 100) err = executor.Run(ctx, engineOut) require.NoError(t, err) assert.Equal(t, tc.expIters, gotIters) diff --git a/lib/executor/ramping_vus.go b/lib/executor/ramping_vus.go index 9b7b81f3e44..2c235a2695d 100644 --- a/lib/executor/ramping_vus.go +++ b/lib/executor/ramping_vus.go @@ -32,7 +32,7 @@ import ( "go.k6.io/k6/lib" "go.k6.io/k6/lib/types" - "go.k6.io/k6/stats" + "go.k6.io/k6/metrics" "go.k6.io/k6/ui/pb" ) @@ -506,7 +506,7 @@ func (vlv *RampingVUs) Init(_ context.Context) error { // Run constantly loops through as many iterations as possible on a variable // number of VUs for the specified stages. -func (vlv *RampingVUs) Run(ctx context.Context, _ chan<- stats.SampleContainer) error { +func (vlv *RampingVUs) Run(ctx context.Context, _ chan<- metrics.SampleContainer) error { regularDuration, isFinal := lib.GetEndOffset(vlv.rawSteps) if !isFinal { return fmt.Errorf("%s expected raw end offset at %s to be final", vlv.config.GetName(), regularDuration) diff --git a/lib/executor/shared_iterations.go b/lib/executor/shared_iterations.go index 86d749b04b0..31e17e59886 100644 --- a/lib/executor/shared_iterations.go +++ b/lib/executor/shared_iterations.go @@ -32,7 +32,7 @@ import ( "go.k6.io/k6/lib" "go.k6.io/k6/lib/types" - "go.k6.io/k6/stats" + "go.k6.io/k6/metrics" "go.k6.io/k6/ui/pb" ) @@ -183,7 +183,7 @@ func (si *SharedIterations) Init(ctx context.Context) error { // Run executes a specific total number of iterations, which are all shared by // the configured VUs. // nolint:funlen -func (si SharedIterations) Run(parentCtx context.Context, out chan<- stats.SampleContainer) (err error) { +func (si SharedIterations) Run(parentCtx context.Context, out chan<- metrics.SampleContainer) (err error) { numVUs := si.config.GetVUs(si.executionState.ExecutionTuple) iterations := si.et.ScaleInt64(si.config.Iterations.Int64) duration := si.config.MaxDuration.TimeDuration() @@ -223,7 +223,7 @@ func (si SharedIterations) Run(parentCtx context.Context, out chan<- stats.Sampl defer func() { activeVUs.Wait() if attemptedIters < totalIters { - stats.PushIfNotDone(parentCtx, out, stats.Sample{ + metrics.PushIfNotDone(parentCtx, out, metrics.Sample{ Value: float64(totalIters - attemptedIters), Metric: si.executionState.BuiltinMetrics.DroppedIterations, Tags: si.getMetricTags(nil), Time: time.Now(), diff --git a/lib/executor/shared_iterations_test.go b/lib/executor/shared_iterations_test.go index 7220d8d1d92..f4e65f6aa6a 100644 --- a/lib/executor/shared_iterations_test.go +++ b/lib/executor/shared_iterations_test.go @@ -37,7 +37,6 @@ import ( "go.k6.io/k6/lib/testutils/minirunner" "go.k6.io/k6/lib/types" "go.k6.io/k6/metrics" - "go.k6.io/k6/stats" ) func getTestSharedIterationsConfig() SharedIterationsConfig { @@ -142,7 +141,7 @@ func TestSharedIterationsEmitDroppedIterations(t *testing.T) { }), ) defer cancel() - engineOut := make(chan stats.SampleContainer, 1000) + engineOut := make(chan metrics.SampleContainer, 1000) err = executor.Run(ctx, engineOut) require.NoError(t, err) assert.Empty(t, logHook.Drain()) @@ -188,14 +187,14 @@ func TestSharedIterationsGlobalIters(t *testing.T) { gotIters := []uint64{} var mx sync.Mutex - runner.Fn = func(ctx context.Context, state *lib.State, _ chan<- stats.SampleContainer) error { + runner.Fn = func(ctx context.Context, state *lib.State, _ chan<- metrics.SampleContainer) error { mx.Lock() gotIters = append(gotIters, state.GetScenarioGlobalVUIter()) mx.Unlock() return nil } - engineOut := make(chan stats.SampleContainer, 100) + engineOut := make(chan metrics.SampleContainer, 100) err = executor.Run(ctx, engineOut) require.NoError(t, err) sort.Slice(gotIters, func(i, j int) bool { return gotIters[i] < gotIters[j] }) diff --git a/lib/executor/vu_handle_test.go b/lib/executor/vu_handle_test.go index e3485a30e6e..a6169c33b05 100644 --- a/lib/executor/vu_handle_test.go +++ b/lib/executor/vu_handle_test.go @@ -34,7 +34,7 @@ import ( "go.k6.io/k6/lib" "go.k6.io/k6/lib/testutils" "go.k6.io/k6/lib/testutils/minirunner" - "go.k6.io/k6/stats" + "go.k6.io/k6/metrics" ) func mockNextIterations() (uint64, uint64) { @@ -55,7 +55,7 @@ func TestVUHandleRace(t *testing.T) { logEntry := logrus.NewEntry(testLog) runner := &minirunner.MiniRunner{} - runner.Fn = func(ctx context.Context, _ *lib.State, out chan<- stats.SampleContainer) error { + runner.Fn = func(ctx context.Context, _ *lib.State, out chan<- metrics.SampleContainer) error { return nil } @@ -144,7 +144,7 @@ func TestVUHandleStartStopRace(t *testing.T) { logEntry := logrus.NewEntry(testLog) runner := &minirunner.MiniRunner{} - runner.Fn = func(ctx context.Context, _ *lib.State, out chan<- stats.SampleContainer) error { + runner.Fn = func(ctx context.Context, _ *lib.State, out chan<- metrics.SampleContainer) error { return nil } @@ -387,7 +387,7 @@ func BenchmarkVUHandleIterations(b *testing.B) { } runner := &minirunner.MiniRunner{} - runner.Fn = func(ctx context.Context, _ *lib.State, out chan<- stats.SampleContainer) error { + runner.Fn = func(ctx context.Context, _ *lib.State, out chan<- metrics.SampleContainer) error { return nil } getVU := func() (lib.InitializedVU, error) { diff --git a/lib/executors.go b/lib/executors.go index e8ef95f49aa..f0d39afa4f7 100644 --- a/lib/executors.go +++ b/lib/executors.go @@ -31,7 +31,7 @@ import ( "github.com/sirupsen/logrus" - "go.k6.io/k6/stats" + "go.k6.io/k6/metrics" "go.k6.io/k6/ui/pb" ) @@ -128,7 +128,7 @@ type Executor interface { GetLogger() *logrus.Entry Init(ctx context.Context) error - Run(ctx context.Context, engineOut chan<- stats.SampleContainer) error + Run(ctx context.Context, engineOut chan<- metrics.SampleContainer) error } // PausableExecutor should be implemented by the executors that can be paused diff --git a/lib/netext/dialer.go b/lib/netext/dialer.go index 2f94178623d..578d0e88b86 100644 --- a/lib/netext/dialer.go +++ b/lib/netext/dialer.go @@ -31,7 +31,6 @@ import ( "go.k6.io/k6/lib" "go.k6.io/k6/lib/types" "go.k6.io/k6/metrics" - "go.k6.io/k6/stats" ) // Dialer wraps net.Dialer and provides k6 specific functionality - @@ -95,12 +94,12 @@ func (d *Dialer) DialContext(ctx context.Context, proto, addr string) (net.Conn, // TODO: Refactor this according to // https://github.com/k6io/k6/pull/1203#discussion_r337938370 func (d *Dialer) GetTrail( - startTime, endTime time.Time, fullIteration bool, emitIterations bool, tags *stats.SampleTags, + startTime, endTime time.Time, fullIteration bool, emitIterations bool, tags *metrics.SampleTags, builtinMetrics *metrics.BuiltinMetrics, ) *NetTrail { bytesWritten := atomic.SwapInt64(&d.BytesWritten, 0) bytesRead := atomic.SwapInt64(&d.BytesRead, 0) - samples := []stats.Sample{ + samples := []metrics.Sample{ { Time: endTime, Metric: builtinMetrics.DataSent, @@ -115,14 +114,14 @@ func (d *Dialer) GetTrail( }, } if fullIteration { - samples = append(samples, stats.Sample{ + samples = append(samples, metrics.Sample{ Time: endTime, Metric: builtinMetrics.IterationDuration, - Value: stats.D(endTime.Sub(startTime)), + Value: metrics.D(endTime.Sub(startTime)), Tags: tags, }) if emitIterations { - samples = append(samples, stats.Sample{ + samples = append(samples, metrics.Sample{ Time: endTime, Metric: builtinMetrics.Iterations, Value: 1, @@ -223,24 +222,24 @@ type NetTrail struct { FullIteration bool StartTime time.Time EndTime time.Time - Tags *stats.SampleTags - Samples []stats.Sample + Tags *metrics.SampleTags + Samples []metrics.Sample } // Ensure that interfaces are implemented correctly -var _ stats.ConnectedSampleContainer = &NetTrail{} +var _ metrics.ConnectedSampleContainer = &NetTrail{} -// GetSamples implements the stats.SampleContainer interface. -func (ntr *NetTrail) GetSamples() []stats.Sample { +// GetSamples implements the metrics.SampleContainer interface. +func (ntr *NetTrail) GetSamples() []metrics.Sample { return ntr.Samples } -// GetTags implements the stats.ConnectedSampleContainer interface. -func (ntr *NetTrail) GetTags() *stats.SampleTags { +// GetTags implements the metrics.ConnectedSampleContainer interface. +func (ntr *NetTrail) GetTags() *metrics.SampleTags { return ntr.Tags } -// GetTime implements the stats.ConnectedSampleContainer interface. +// GetTime implements the metrics.ConnectedSampleContainer interface. func (ntr *NetTrail) GetTime() time.Time { return ntr.EndTime } diff --git a/lib/netext/httpext/request.go b/lib/netext/httpext/request.go index 44ef0622644..47ce4c03518 100644 --- a/lib/netext/httpext/request.go +++ b/lib/netext/httpext/request.go @@ -39,7 +39,7 @@ import ( "gopkg.in/guregu/null.v3" "go.k6.io/k6/lib" - "go.k6.io/k6/stats" + "go.k6.io/k6/metrics" ) // HTTPRequestCookie is a representation of a cookie used for request objects @@ -117,13 +117,13 @@ func updateK6Response(k6Response *Response, finishedReq *finishedRequest) { k6Response.RemotePort = remotePort } k6Response.Timings = ResponseTimings{ - Duration: stats.D(trail.Duration), - Blocked: stats.D(trail.Blocked), - Connecting: stats.D(trail.Connecting), - TLSHandshaking: stats.D(trail.TLSHandshaking), - Sending: stats.D(trail.Sending), - Waiting: stats.D(trail.Waiting), - Receiving: stats.D(trail.Receiving), + Duration: metrics.D(trail.Duration), + Blocked: metrics.D(trail.Blocked), + Connecting: metrics.D(trail.Connecting), + TLSHandshaking: metrics.D(trail.TLSHandshaking), + Sending: metrics.D(trail.Sending), + Waiting: metrics.D(trail.Waiting), + Receiving: metrics.D(trail.Receiving), } } @@ -195,7 +195,7 @@ func MakeRequest(ctx context.Context, state *lib.State, preq *ParsedHTTPRequest) // Only set the name system tag if the user didn't explicitly set it beforehand, // and the Name was generated from a tagged template string (via http.url). - if _, ok := tags["name"]; !ok && state.Options.SystemTags.Has(stats.TagName) && + if _, ok := tags["name"]; !ok && state.Options.SystemTags.Has(metrics.TagName) && preq.URL.Name != "" && preq.URL.Name != preq.URL.Clean() { tags["name"] = preq.URL.Name } diff --git a/lib/netext/httpext/request_test.go b/lib/netext/httpext/request_test.go index 1b93383db41..5c6f3b0227d 100644 --- a/lib/netext/httpext/request_test.go +++ b/lib/netext/httpext/request_test.go @@ -43,7 +43,6 @@ import ( "go.k6.io/k6/lib" "go.k6.io/k6/metrics" - "go.k6.io/k6/stats" ) type reader func([]byte) (int, error) @@ -119,7 +118,7 @@ func TestMakeRequestError(t *testing.T) { Compressions: []CompressionType{badCompressionType}, } state := &lib.State{ - Options: lib.Options{RunTags: &stats.SampleTags{}}, + Options: lib.Options{RunTags: &metrics.SampleTags{}}, Transport: http.DefaultTransport, Logger: logrus.New(), Tags: lib.NewTagMap(nil), @@ -142,7 +141,7 @@ func TestMakeRequestError(t *testing.T) { logger := logrus.New() logger.Level = logrus.DebugLevel state := &lib.State{ - Options: lib.Options{RunTags: &stats.SampleTags{}}, + Options: lib.Options{RunTags: &metrics.SampleTags{}}, Transport: srv.Client().Transport, Logger: logger, Tags: lib.NewTagMap(nil), @@ -190,10 +189,10 @@ func TestResponseStatus(t *testing.T) { defer server.Close() logger := logrus.New() logger.Level = logrus.DebugLevel - samples := make(chan<- stats.SampleContainer, 1) + samples := make(chan<- metrics.SampleContainer, 1) registry := metrics.NewRegistry() state := &lib.State{ - Options: lib.Options{RunTags: &stats.SampleTags{}}, + Options: lib.Options{RunTags: &metrics.SampleTags{}}, Transport: server.Client().Transport, Logger: logger, Samples: samples, @@ -266,14 +265,14 @@ func TestMakeRequestTimeoutInTheMiddle(t *testing.T) { defer srv.Close() ctx, cancel := context.WithCancel(context.Background()) defer cancel() - samples := make(chan stats.SampleContainer, 10) + samples := make(chan metrics.SampleContainer, 10) logger := logrus.New() logger.Level = logrus.DebugLevel registry := metrics.NewRegistry() state := &lib.State{ Options: lib.Options{ - RunTags: &stats.SampleTags{}, - SystemTags: &stats.DefaultSystemTagSet, + RunTags: &metrics.SampleTags{}, + SystemTags: &metrics.DefaultSystemTagSet, }, Transport: srv.Client().Transport, Samples: samples, @@ -343,14 +342,14 @@ func TestTrailFailed(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) t.Cleanup(cancel) - samples := make(chan stats.SampleContainer, 10) + samples := make(chan metrics.SampleContainer, 10) logger := logrus.New() logger.Level = logrus.DebugLevel registry := metrics.NewRegistry() state := &lib.State{ Options: lib.Options{ - RunTags: &stats.SampleTags{}, - SystemTags: &stats.DefaultSystemTagSet, + RunTags: &metrics.SampleTags{}, + SystemTags: &metrics.DefaultSystemTagSet, }, Transport: srv.Client().Transport, Samples: samples, @@ -405,14 +404,14 @@ func TestMakeRequestDialTimeout(t *testing.T) { }() ctx, cancel := context.WithCancel(context.Background()) defer cancel() - samples := make(chan stats.SampleContainer, 10) + samples := make(chan metrics.SampleContainer, 10) logger := logrus.New() logger.Level = logrus.DebugLevel registry := metrics.NewRegistry() state := &lib.State{ Options: lib.Options{ - RunTags: &stats.SampleTags{}, - SystemTags: &stats.DefaultSystemTagSet, + RunTags: &metrics.SampleTags{}, + SystemTags: &metrics.DefaultSystemTagSet, }, Transport: &http.Transport{ DialContext: (&net.Dialer{ @@ -464,14 +463,14 @@ func TestMakeRequestTimeoutInTheBegining(t *testing.T) { defer srv.Close() ctx, cancel := context.WithCancel(context.Background()) defer cancel() - samples := make(chan stats.SampleContainer, 10) + samples := make(chan metrics.SampleContainer, 10) logger := logrus.New() logger.Level = logrus.DebugLevel registry := metrics.NewRegistry() state := &lib.State{ Options: lib.Options{ - RunTags: &stats.SampleTags{}, - SystemTags: &stats.DefaultSystemTagSet, + RunTags: &metrics.SampleTags{}, + SystemTags: &metrics.DefaultSystemTagSet, }, Transport: srv.Client().Transport, Samples: samples, diff --git a/lib/netext/httpext/tracer.go b/lib/netext/httpext/tracer.go index 3af2b29015c..d920394e439 100644 --- a/lib/netext/httpext/tracer.go +++ b/lib/netext/httpext/tracer.go @@ -28,7 +28,6 @@ import ( "time" "go.k6.io/k6/metrics" - "go.k6.io/k6/stats" "gopkg.in/guregu/null.v3" ) @@ -56,43 +55,43 @@ type Trail struct { Failed null.Bool // Populated by SaveSamples() - Tags *stats.SampleTags - Samples []stats.Sample + Tags *metrics.SampleTags + Samples []metrics.Sample } // SaveSamples populates the Trail's sample slice so they're accesible via GetSamples() -func (tr *Trail) SaveSamples(builtinMetrics *metrics.BuiltinMetrics, tags *stats.SampleTags) { +func (tr *Trail) SaveSamples(builtinMetrics *metrics.BuiltinMetrics, tags *metrics.SampleTags) { tr.Tags = tags - tr.Samples = make([]stats.Sample, 0, 9) // this is with 1 more for a possible HTTPReqFailed - tr.Samples = append(tr.Samples, []stats.Sample{ + tr.Samples = make([]metrics.Sample, 0, 9) // this is with 1 more for a possible HTTPReqFailed + tr.Samples = append(tr.Samples, []metrics.Sample{ {Metric: builtinMetrics.HTTPReqs, Time: tr.EndTime, Tags: tags, Value: 1}, - {Metric: builtinMetrics.HTTPReqDuration, Time: tr.EndTime, Tags: tags, Value: stats.D(tr.Duration)}, - {Metric: builtinMetrics.HTTPReqBlocked, Time: tr.EndTime, Tags: tags, Value: stats.D(tr.Blocked)}, - {Metric: builtinMetrics.HTTPReqConnecting, Time: tr.EndTime, Tags: tags, Value: stats.D(tr.Connecting)}, - {Metric: builtinMetrics.HTTPReqTLSHandshaking, Time: tr.EndTime, Tags: tags, Value: stats.D(tr.TLSHandshaking)}, - {Metric: builtinMetrics.HTTPReqSending, Time: tr.EndTime, Tags: tags, Value: stats.D(tr.Sending)}, - {Metric: builtinMetrics.HTTPReqWaiting, Time: tr.EndTime, Tags: tags, Value: stats.D(tr.Waiting)}, - {Metric: builtinMetrics.HTTPReqReceiving, Time: tr.EndTime, Tags: tags, Value: stats.D(tr.Receiving)}, + {Metric: builtinMetrics.HTTPReqDuration, Time: tr.EndTime, Tags: tags, Value: metrics.D(tr.Duration)}, + {Metric: builtinMetrics.HTTPReqBlocked, Time: tr.EndTime, Tags: tags, Value: metrics.D(tr.Blocked)}, + {Metric: builtinMetrics.HTTPReqConnecting, Time: tr.EndTime, Tags: tags, Value: metrics.D(tr.Connecting)}, + {Metric: builtinMetrics.HTTPReqTLSHandshaking, Time: tr.EndTime, Tags: tags, Value: metrics.D(tr.TLSHandshaking)}, + {Metric: builtinMetrics.HTTPReqSending, Time: tr.EndTime, Tags: tags, Value: metrics.D(tr.Sending)}, + {Metric: builtinMetrics.HTTPReqWaiting, Time: tr.EndTime, Tags: tags, Value: metrics.D(tr.Waiting)}, + {Metric: builtinMetrics.HTTPReqReceiving, Time: tr.EndTime, Tags: tags, Value: metrics.D(tr.Receiving)}, }...) } -// GetSamples implements the stats.SampleContainer interface. -func (tr *Trail) GetSamples() []stats.Sample { +// GetSamples implements the metrics.SampleContainer interface. +func (tr *Trail) GetSamples() []metrics.Sample { return tr.Samples } -// GetTags implements the stats.ConnectedSampleContainer interface. -func (tr *Trail) GetTags() *stats.SampleTags { +// GetTags implements the metrics.ConnectedSampleContainer interface. +func (tr *Trail) GetTags() *metrics.SampleTags { return tr.Tags } -// GetTime implements the stats.ConnectedSampleContainer interface. +// GetTime implements the metrics.ConnectedSampleContainer interface. func (tr *Trail) GetTime() time.Time { return tr.EndTime } // Ensure that interfaces are implemented correctly -var _ stats.ConnectedSampleContainer = &Trail{} +var _ metrics.ConnectedSampleContainer = &Trail{} // A Tracer wraps "net/http/httptrace" to collect granular timings for HTTP requests. // Note that since there is not yet an event for the end of a request (there's a PR to diff --git a/lib/netext/httpext/tracer_test.go b/lib/netext/httpext/tracer_test.go index 049379d9c3d..8112d2b3fb5 100644 --- a/lib/netext/httpext/tracer_test.go +++ b/lib/netext/httpext/tracer_test.go @@ -44,7 +44,6 @@ import ( "go.k6.io/k6/lib/netext" "go.k6.io/k6/lib/types" "go.k6.io/k6/metrics" - "go.k6.io/k6/stats" ) const traceDelay = 100 * time.Millisecond @@ -150,7 +149,7 @@ func TestTracer(t *testing.T) { time.Sleep(traceDelay) } trail := tracer.Done() - trail.SaveSamples(builtinMetrics, stats.IntoSampleTags(&map[string]string{"tag": "value"})) + trail.SaveSamples(builtinMetrics, metrics.IntoSampleTags(&map[string]string{"tag": "value"})) samples := trail.GetSamples() assertLaterOrZero(t, tracer.getConn, isReuse) @@ -166,7 +165,7 @@ func TestTracer(t *testing.T) { assert.Equal(t, strings.TrimPrefix(srv.URL, "https://"), trail.ConnRemoteAddr.String()) assert.Len(t, samples, 8) - seenMetrics := map[*stats.Metric]bool{} + seenMetrics := map[*metrics.Metric]bool{} for i, s := range samples { assert.NotContains(t, seenMetrics, s.Metric) seenMetrics[s.Metric] = true diff --git a/lib/netext/httpext/transport.go b/lib/netext/httpext/transport.go index d5cab8ac9d2..67cdb503fc7 100644 --- a/lib/netext/httpext/transport.go +++ b/lib/netext/httpext/transport.go @@ -31,7 +31,7 @@ import ( "go.k6.io/k6/lib" "go.k6.io/k6/lib/netext" - "go.k6.io/k6/stats" + "go.k6.io/k6/metrics" ) // transport is an implementation of http.RoundTripper that will measure and emit @@ -106,9 +106,9 @@ func (t *transport) measureAndEmitMetrics(unfReq *unfinishedRequest) *finishedRe } enabledTags := t.state.Options.SystemTags - urlEnabled := enabledTags.Has(stats.TagURL) + urlEnabled := enabledTags.Has(metrics.TagURL) var setName bool - if _, ok := tags["name"]; !ok && enabledTags.Has(stats.TagName) { + if _, ok := tags["name"]; !ok && enabledTags.Has(metrics.TagName) { setName = true } if urlEnabled || setName { @@ -121,49 +121,49 @@ func (t *transport) measureAndEmitMetrics(unfReq *unfinishedRequest) *finishedRe } } - if enabledTags.Has(stats.TagMethod) { + if enabledTags.Has(metrics.TagMethod) { tags["method"] = unfReq.request.Method } if unfReq.err != nil { result.errorCode, result.errorMsg = errorCodeForError(unfReq.err) - if enabledTags.Has(stats.TagError) { + if enabledTags.Has(metrics.TagError) { tags["error"] = result.errorMsg } - if enabledTags.Has(stats.TagErrorCode) { + if enabledTags.Has(metrics.TagErrorCode) { tags["error_code"] = strconv.Itoa(int(result.errorCode)) } - if enabledTags.Has(stats.TagStatus) { + if enabledTags.Has(metrics.TagStatus) { tags["status"] = "0" } } else { - if enabledTags.Has(stats.TagStatus) { + if enabledTags.Has(metrics.TagStatus) { tags["status"] = strconv.Itoa(unfReq.response.StatusCode) } if unfReq.response.StatusCode >= 400 { - if enabledTags.Has(stats.TagErrorCode) { + if enabledTags.Has(metrics.TagErrorCode) { result.errorCode = errCode(1000 + unfReq.response.StatusCode) tags["error_code"] = strconv.Itoa(int(result.errorCode)) } } - if enabledTags.Has(stats.TagProto) { + if enabledTags.Has(metrics.TagProto) { tags["proto"] = unfReq.response.Proto } if unfReq.response.TLS != nil { tlsInfo, oscp := netext.ParseTLSConnState(unfReq.response.TLS) - if enabledTags.Has(stats.TagTLSVersion) { + if enabledTags.Has(metrics.TagTLSVersion) { tags["tls_version"] = tlsInfo.Version } - if enabledTags.Has(stats.TagOCSPStatus) { + if enabledTags.Has(metrics.TagOCSPStatus) { tags["ocsp_status"] = oscp.Status } result.tlsInfo = tlsInfo } } - if enabledTags.Has(stats.TagIP) && trail.ConnRemoteAddr != nil { + if enabledTags.Has(metrics.TagIP) && trail.ConnRemoteAddr != nil { if ip, _, err := net.SplitHostPort(trail.ConnRemoteAddr.String()); err == nil { tags["ip"] = ip } @@ -179,12 +179,12 @@ func (t *transport) measureAndEmitMetrics(unfReq *unfinishedRequest) *finishedRe failed = 1 } - if enabledTags.Has(stats.TagExpectedResponse) { - tags[stats.TagExpectedResponse.String()] = strconv.FormatBool(expected) + if enabledTags.Has(metrics.TagExpectedResponse) { + tags[metrics.TagExpectedResponse.String()] = strconv.FormatBool(expected) } } - finalTags := stats.IntoSampleTags(&tags) + finalTags := metrics.IntoSampleTags(&tags) builtinMetrics := t.state.BuiltinMetrics trail.SaveSamples(builtinMetrics, finalTags) if t.responseCallback != nil { @@ -193,12 +193,12 @@ func (t *transport) measureAndEmitMetrics(unfReq *unfinishedRequest) *finishedRe trail.Failed.Bool = true } trail.Samples = append(trail.Samples, - stats.Sample{ + metrics.Sample{ Metric: builtinMetrics.HTTPReqFailed, Time: trail.EndTime, Tags: finalTags, Value: failed, }, ) } - stats.PushIfNotDone(t.ctx, t.state.Samples, trail) + metrics.PushIfNotDone(t.ctx, t.state.Samples, trail) return result } diff --git a/lib/netext/httpext/transport_test.go b/lib/netext/httpext/transport_test.go index 382eff6a375..3f707809e72 100644 --- a/lib/netext/httpext/transport_test.go +++ b/lib/netext/httpext/transport_test.go @@ -28,13 +28,13 @@ import ( "github.com/sirupsen/logrus" "go.k6.io/k6/lib" - "go.k6.io/k6/stats" + "go.k6.io/k6/metrics" ) func BenchmarkMeasureAndEmitMetrics(b *testing.B) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - samples := make(chan stats.SampleContainer, 10) + samples := make(chan metrics.SampleContainer, 10) defer close(samples) go func() { for range samples { @@ -45,8 +45,8 @@ func BenchmarkMeasureAndEmitMetrics(b *testing.B) { state := &lib.State{ Options: lib.Options{ - RunTags: &stats.SampleTags{}, - SystemTags: &stats.DefaultSystemTagSet, + RunTags: &metrics.SampleTags{}, + SystemTags: &metrics.DefaultSystemTagSet, }, Samples: samples, Logger: logger, diff --git a/lib/options.go b/lib/options.go index 86ed96c66b0..c4bbf8e24d7 100644 --- a/lib/options.go +++ b/lib/options.go @@ -29,7 +29,7 @@ import ( "strconv" "go.k6.io/k6/lib/types" - "go.k6.io/k6/stats" + "go.k6.io/k6/metrics" "gopkg.in/guregu/null.v3" ) @@ -335,7 +335,7 @@ type Options struct { // Define thresholds; these take the form of 'metric=["snippet1", "snippet2"]'. // To create a threshold on a derived metric based on tag queries ("submetrics"), create a // metric on a nonexistent metric named 'real_metric{tagA:valueA,tagB:valueB}'. - Thresholds map[string]stats.Thresholds `json:"thresholds" envconfig:"K6_THRESHOLDS"` + Thresholds map[string]metrics.Thresholds `json:"thresholds" envconfig:"K6_THRESHOLDS"` // Blacklist IP ranges that tests may not contact. Mainly useful in hosted setups. BlacklistIPs []*IPNet `json:"blacklistIPs" envconfig:"K6_BLACKLIST_IPS"` @@ -370,10 +370,10 @@ type Options struct { // Which system tags to include with metrics ("method", "vu" etc.) // Use pointer for identifying whether user provide any tag or not. - SystemTags *stats.SystemTagSet `json:"systemTags" envconfig:"K6_SYSTEM_TAGS"` + SystemTags *metrics.SystemTagSet `json:"systemTags" envconfig:"K6_SYSTEM_TAGS"` // Tags to be applied to all samples for this running - RunTags *stats.SampleTags `json:"tags" envconfig:"K6_TAGS"` + RunTags *metrics.SampleTags `json:"tags" envconfig:"K6_TAGS"` // Buffer size of the channel for metric samples; 0 means unbuffered MetricSamplesBufferSize null.Int `json:"metricSamplesBufferSize" envconfig:"K6_METRIC_SAMPLES_BUFFER_SIZE"` diff --git a/lib/options_test.go b/lib/options_test.go index 8f0cab3bf76..f46801d8b1b 100644 --- a/lib/options_test.go +++ b/lib/options_test.go @@ -34,7 +34,7 @@ import ( "gopkg.in/guregu/null.v3" "go.k6.io/k6/lib/types" - "go.k6.io/k6/stats" + "go.k6.io/k6/metrics" ) func TestOptions(t *testing.T) { @@ -355,9 +355,9 @@ func TestOptions(t *testing.T) { }) t.Run("Thresholds", func(t *testing.T) { - opts := Options{}.Apply(Options{Thresholds: map[string]stats.Thresholds{ + opts := Options{}.Apply(Options{Thresholds: map[string]metrics.Thresholds{ "metric": { - Thresholds: []*stats.Threshold{{}}, + Thresholds: []*metrics.Threshold{{}}, }, }}) assert.NotNil(t, opts.Thresholds) @@ -377,23 +377,23 @@ func TestOptions(t *testing.T) { assert.Equal(t, Options{}, opts) }) t.Run("SystemTags", func(t *testing.T) { - opts := Options{}.Apply(Options{SystemTags: stats.NewSystemTagSet(stats.TagProto)}) + opts := Options{}.Apply(Options{SystemTags: metrics.NewSystemTagSet(metrics.TagProto)}) assert.NotNil(t, opts.SystemTags) assert.NotEmpty(t, opts.SystemTags) - assert.True(t, opts.SystemTags.Has(stats.TagProto)) + assert.True(t, opts.SystemTags.Has(metrics.TagProto)) t.Run("JSON", func(t *testing.T) { t.Run("Array", func(t *testing.T) { var opts Options jsonStr := `{"systemTags":["url"]}` assert.NoError(t, json.Unmarshal([]byte(jsonStr), &opts)) - assert.Equal(t, *stats.NewSystemTagSet(stats.TagURL), *opts.SystemTags) + assert.Equal(t, *metrics.NewSystemTagSet(metrics.TagURL), *opts.SystemTags) t.Run("Roundtrip", func(t *testing.T) { data, err := json.Marshal(opts.SystemTags) assert.NoError(t, err) assert.Equal(t, `["url"]`, string(data)) - var vers2 stats.SystemTagSet + var vers2 metrics.SystemTagSet assert.NoError(t, json.Unmarshal(data, &vers2)) assert.Equal(t, vers2, *opts.SystemTags) }) @@ -402,7 +402,7 @@ func TestOptions(t *testing.T) { var opts Options jsonStr := `{"systemTags":[]}` assert.NoError(t, json.Unmarshal([]byte(jsonStr), &opts)) - assert.Equal(t, stats.SystemTagSet(0), *opts.SystemTags) + assert.Equal(t, metrics.SystemTagSet(0), *opts.SystemTags) }) }) }) @@ -412,7 +412,7 @@ func TestOptions(t *testing.T) { assert.Equal(t, stats, opts.SummaryTrendStats) }) t.Run("RunTags", func(t *testing.T) { - tags := stats.IntoSampleTags(&map[string]string{"myTag": "hello"}) + tags := metrics.IntoSampleTags(&map[string]string{"myTag": "hello"}) opts := Options{}.Apply(Options{RunTags: tags}) assert.Equal(t, tags, opts.RunTags) }) diff --git a/lib/runner.go b/lib/runner.go index 9cad5f6c420..0265ec0d6cd 100644 --- a/lib/runner.go +++ b/lib/runner.go @@ -25,7 +25,7 @@ import ( "io" "time" - "go.k6.io/k6/stats" + "go.k6.io/k6/metrics" ) // ActiveVU represents an actively running virtual user. @@ -74,10 +74,10 @@ type Runner interface { // Spawns a new VU. It's fine to make this function rather heavy, if it means a performance // improvement at runtime. Remember, this is called once per VU and normally only at the start // of a test - RunOnce() may be called hundreds of thousands of times, and must be fast. - NewVU(idLocal, idGlobal uint64, out chan<- stats.SampleContainer) (InitializedVU, error) + NewVU(idLocal, idGlobal uint64, out chan<- metrics.SampleContainer) (InitializedVU, error) // Runs pre-test setup, if applicable. - Setup(ctx context.Context, out chan<- stats.SampleContainer) error + Setup(ctx context.Context, out chan<- metrics.SampleContainer) error // Returns json representation of the setup data if setup() is specified and run, nil otherwise GetSetupData() []byte @@ -86,7 +86,7 @@ type Runner interface { SetSetupData([]byte) // Runs post-test teardown, if applicable. - Teardown(ctx context.Context, out chan<- stats.SampleContainer) error + Teardown(ctx context.Context, out chan<- metrics.SampleContainer) error // Returns the default (root) Group. GetDefaultGroup() *Group @@ -113,7 +113,7 @@ type UIState struct { // Summary contains all of the data the summary handler gets. type Summary struct { - Metrics map[string]*stats.Metric + Metrics map[string]*metrics.Metric RootGroup *Group TestRunDuration time.Duration // TODO: use lib.ExecutionState-based interface instead? NoColor bool // TODO: drop this when noColor is part of the (runtime) options diff --git a/lib/state.go b/lib/state.go index efa1a27c3f7..89be0af3b17 100644 --- a/lib/state.go +++ b/lib/state.go @@ -33,7 +33,6 @@ import ( "golang.org/x/time/rate" "go.k6.io/k6/metrics" - "go.k6.io/k6/stats" ) // DialContexter is an interface that can dial with a context @@ -66,7 +65,7 @@ type State struct { RPSLimit *rate.Limiter // Sample channel, possibly buffered - Samples chan<- stats.SampleContainer + Samples chan<- metrics.SampleContainer // Buffer pool; use instead of allocating fresh buffers when possible. // TODO: maybe use https://golang.org/pkg/sync/#Pool ? diff --git a/lib/testutils/minirunner/minirunner.go b/lib/testutils/minirunner/minirunner.go index b640123dc22..cf606902556 100644 --- a/lib/testutils/minirunner/minirunner.go +++ b/lib/testutils/minirunner/minirunner.go @@ -25,7 +25,7 @@ import ( "io" "go.k6.io/k6/lib" - "go.k6.io/k6/stats" + "go.k6.io/k6/metrics" ) // Ensure mock implementations conform to the interfaces. @@ -39,9 +39,9 @@ var ( // using a real JS runtime, it allows us to directly specify the options and // functions with Go code. type MiniRunner struct { - Fn func(ctx context.Context, state *lib.State, out chan<- stats.SampleContainer) error - SetupFn func(ctx context.Context, out chan<- stats.SampleContainer) ([]byte, error) - TeardownFn func(ctx context.Context, out chan<- stats.SampleContainer) error + Fn func(ctx context.Context, state *lib.State, out chan<- metrics.SampleContainer) error + SetupFn func(ctx context.Context, out chan<- metrics.SampleContainer) ([]byte, error) + TeardownFn func(ctx context.Context, out chan<- metrics.SampleContainer) error HandleSummaryFn func(context.Context, *lib.Summary) (map[string]io.Reader, error) SetupData []byte @@ -57,7 +57,7 @@ func (r MiniRunner) MakeArchive() *lib.Archive { } // NewVU returns a new VU with an incremental ID. -func (r *MiniRunner) NewVU(idLocal, idGlobal uint64, out chan<- stats.SampleContainer) (lib.InitializedVU, error) { +func (r *MiniRunner) NewVU(idLocal, idGlobal uint64, out chan<- metrics.SampleContainer) (lib.InitializedVU, error) { state := &lib.State{VUID: idLocal, VUIDGlobal: idGlobal, Iteration: int64(-1)} return &VU{ R: r, @@ -70,7 +70,7 @@ func (r *MiniRunner) NewVU(idLocal, idGlobal uint64, out chan<- stats.SampleCont } // Setup calls the supplied mock setup() function, if present. -func (r *MiniRunner) Setup(ctx context.Context, out chan<- stats.SampleContainer) (err error) { +func (r *MiniRunner) Setup(ctx context.Context, out chan<- metrics.SampleContainer) (err error) { if fn := r.SetupFn; fn != nil { r.SetupData, err = fn(ctx, out) } @@ -89,7 +89,7 @@ func (r *MiniRunner) SetSetupData(data []byte) { } // Teardown calls the supplied mock teardown() function, if present. -func (r MiniRunner) Teardown(ctx context.Context, out chan<- stats.SampleContainer) error { +func (r MiniRunner) Teardown(ctx context.Context, out chan<- metrics.SampleContainer) error { if fn := r.TeardownFn; fn != nil { return fn(ctx, out) } @@ -132,7 +132,7 @@ func (r *MiniRunner) HandleSummary(ctx context.Context, s *lib.Summary) (map[str // VU is a mock VU, spawned by a MiniRunner. type VU struct { R *MiniRunner - Out chan<- stats.SampleContainer + Out chan<- metrics.SampleContainer ID, IDGlobal uint64 Iteration int64 state *lib.State diff --git a/lib/testutils/mockoutput/mockoutput.go b/lib/testutils/mockoutput/mockoutput.go index 23a2dac9c55..096ab3aa77e 100644 --- a/lib/testutils/mockoutput/mockoutput.go +++ b/lib/testutils/mockoutput/mockoutput.go @@ -22,8 +22,8 @@ package mockoutput import ( "go.k6.io/k6/lib" + "go.k6.io/k6/metrics" "go.k6.io/k6/output" - "go.k6.io/k6/stats" ) // New exists so that the usage from tests avoids repetition, i.e. is @@ -34,8 +34,8 @@ func New() *MockOutput { // MockOutput can be used in tests to mock an actual output. type MockOutput struct { - SampleContainers []stats.SampleContainer - Samples []stats.Sample + SampleContainers []metrics.SampleContainer + Samples []metrics.Sample RunStatus lib.RunStatus DescFn func() string @@ -46,7 +46,7 @@ type MockOutput struct { var _ output.WithRunStatusUpdates = &MockOutput{} // AddMetricSamples just saves the results in memory. -func (mo *MockOutput) AddMetricSamples(scs []stats.SampleContainer) { +func (mo *MockOutput) AddMetricSamples(scs []metrics.SampleContainer) { mo.SampleContainers = append(mo.SampleContainers, scs...) for _, sc := range scs { mo.Samples = append(mo.Samples, sc.GetSamples()...) diff --git a/metrics/builtin.go b/metrics/builtin.go index fde4a9b728b..c53102f31d1 100644 --- a/metrics/builtin.go +++ b/metrics/builtin.go @@ -20,10 +20,6 @@ package metrics -import ( - "go.k6.io/k6/stats" -) - const ( VUsName = "vus" //nolint:revive VUsMaxName = "vus_max" @@ -59,75 +55,75 @@ const ( // BuiltinMetrics represent all the builtin metrics of k6 type BuiltinMetrics struct { - VUs *stats.Metric - VUsMax *stats.Metric - Iterations *stats.Metric - IterationDuration *stats.Metric - DroppedIterations *stats.Metric + VUs *Metric + VUsMax *Metric + Iterations *Metric + IterationDuration *Metric + DroppedIterations *Metric // Runner-emitted. - Checks *stats.Metric - GroupDuration *stats.Metric + Checks *Metric + GroupDuration *Metric // HTTP-related. - HTTPReqs *stats.Metric - HTTPReqFailed *stats.Metric - HTTPReqDuration *stats.Metric - HTTPReqBlocked *stats.Metric - HTTPReqConnecting *stats.Metric - HTTPReqTLSHandshaking *stats.Metric - HTTPReqSending *stats.Metric - HTTPReqWaiting *stats.Metric - HTTPReqReceiving *stats.Metric + HTTPReqs *Metric + HTTPReqFailed *Metric + HTTPReqDuration *Metric + HTTPReqBlocked *Metric + HTTPReqConnecting *Metric + HTTPReqTLSHandshaking *Metric + HTTPReqSending *Metric + HTTPReqWaiting *Metric + HTTPReqReceiving *Metric // Websocket-related - WSSessions *stats.Metric - WSMessagesSent *stats.Metric - WSMessagesReceived *stats.Metric - WSPing *stats.Metric - WSSessionDuration *stats.Metric - WSConnecting *stats.Metric + WSSessions *Metric + WSMessagesSent *Metric + WSMessagesReceived *Metric + WSPing *Metric + WSSessionDuration *Metric + WSConnecting *Metric // gRPC-related - GRPCReqDuration *stats.Metric + GRPCReqDuration *Metric // Network-related; used for future protocols as well. - DataSent *stats.Metric - DataReceived *stats.Metric + DataSent *Metric + DataReceived *Metric } // RegisterBuiltinMetrics register and returns the builtin metrics in the provided registry func RegisterBuiltinMetrics(registry *Registry) *BuiltinMetrics { return &BuiltinMetrics{ - VUs: registry.MustNewMetric(VUsName, stats.Gauge), - VUsMax: registry.MustNewMetric(VUsMaxName, stats.Gauge), - Iterations: registry.MustNewMetric(IterationsName, stats.Counter), - IterationDuration: registry.MustNewMetric(IterationDurationName, stats.Trend, stats.Time), - DroppedIterations: registry.MustNewMetric(DroppedIterationsName, stats.Counter), - - Checks: registry.MustNewMetric(ChecksName, stats.Rate), - GroupDuration: registry.MustNewMetric(GroupDurationName, stats.Trend, stats.Time), - - HTTPReqs: registry.MustNewMetric(HTTPReqsName, stats.Counter), - HTTPReqFailed: registry.MustNewMetric(HTTPReqFailedName, stats.Rate), - HTTPReqDuration: registry.MustNewMetric(HTTPReqDurationName, stats.Trend, stats.Time), - HTTPReqBlocked: registry.MustNewMetric(HTTPReqBlockedName, stats.Trend, stats.Time), - HTTPReqConnecting: registry.MustNewMetric(HTTPReqConnectingName, stats.Trend, stats.Time), - HTTPReqTLSHandshaking: registry.MustNewMetric(HTTPReqTLSHandshakingName, stats.Trend, stats.Time), - HTTPReqSending: registry.MustNewMetric(HTTPReqSendingName, stats.Trend, stats.Time), - HTTPReqWaiting: registry.MustNewMetric(HTTPReqWaitingName, stats.Trend, stats.Time), - HTTPReqReceiving: registry.MustNewMetric(HTTPReqReceivingName, stats.Trend, stats.Time), - - WSSessions: registry.MustNewMetric(WSSessionsName, stats.Counter), - WSMessagesSent: registry.MustNewMetric(WSMessagesSentName, stats.Counter), - WSMessagesReceived: registry.MustNewMetric(WSMessagesReceivedName, stats.Counter), - WSPing: registry.MustNewMetric(WSPingName, stats.Trend, stats.Time), - WSSessionDuration: registry.MustNewMetric(WSSessionDurationName, stats.Trend, stats.Time), - WSConnecting: registry.MustNewMetric(WSConnectingName, stats.Trend, stats.Time), - - GRPCReqDuration: registry.MustNewMetric(GRPCReqDurationName, stats.Trend, stats.Time), - - DataSent: registry.MustNewMetric(DataSentName, stats.Counter, stats.Data), - DataReceived: registry.MustNewMetric(DataReceivedName, stats.Counter, stats.Data), + VUs: registry.MustNewMetric(VUsName, Gauge), + VUsMax: registry.MustNewMetric(VUsMaxName, Gauge), + Iterations: registry.MustNewMetric(IterationsName, Counter), + IterationDuration: registry.MustNewMetric(IterationDurationName, Trend, Time), + DroppedIterations: registry.MustNewMetric(DroppedIterationsName, Counter), + + Checks: registry.MustNewMetric(ChecksName, Rate), + GroupDuration: registry.MustNewMetric(GroupDurationName, Trend, Time), + + HTTPReqs: registry.MustNewMetric(HTTPReqsName, Counter), + HTTPReqFailed: registry.MustNewMetric(HTTPReqFailedName, Rate), + HTTPReqDuration: registry.MustNewMetric(HTTPReqDurationName, Trend, Time), + HTTPReqBlocked: registry.MustNewMetric(HTTPReqBlockedName, Trend, Time), + HTTPReqConnecting: registry.MustNewMetric(HTTPReqConnectingName, Trend, Time), + HTTPReqTLSHandshaking: registry.MustNewMetric(HTTPReqTLSHandshakingName, Trend, Time), + HTTPReqSending: registry.MustNewMetric(HTTPReqSendingName, Trend, Time), + HTTPReqWaiting: registry.MustNewMetric(HTTPReqWaitingName, Trend, Time), + HTTPReqReceiving: registry.MustNewMetric(HTTPReqReceivingName, Trend, Time), + + WSSessions: registry.MustNewMetric(WSSessionsName, Counter), + WSMessagesSent: registry.MustNewMetric(WSMessagesSentName, Counter), + WSMessagesReceived: registry.MustNewMetric(WSMessagesReceivedName, Counter), + WSPing: registry.MustNewMetric(WSPingName, Trend, Time), + WSSessionDuration: registry.MustNewMetric(WSSessionDurationName, Trend, Time), + WSConnecting: registry.MustNewMetric(WSConnectingName, Trend, Time), + + GRPCReqDuration: registry.MustNewMetric(GRPCReqDurationName, Trend, Time), + + DataSent: registry.MustNewMetric(DataSentName, Counter, Data), + DataReceived: registry.MustNewMetric(DataReceivedName, Counter, Data), } } diff --git a/metrics/engine/engine.go b/metrics/engine/engine.go index e5ce9944b04..3c64e11b074 100644 --- a/metrics/engine/engine.go +++ b/metrics/engine/engine.go @@ -11,7 +11,6 @@ import ( "go.k6.io/k6/lib" "go.k6.io/k6/metrics" "go.k6.io/k6/output" - "go.k6.io/k6/stats" "gopkg.in/guregu/null.v3" ) @@ -26,7 +25,7 @@ type MetricsEngine struct { logger logrus.FieldLogger // These can be both top-level metrics or sub-metrics - metricsWithThresholds []*stats.Metric + metricsWithThresholds []*metrics.Metric // TODO: completely refactor: // - make these private, @@ -34,7 +33,7 @@ type MetricsEngine struct { // - have one lock per metric instead of a a global one, when // the metrics are decoupled from their types MetricsLock sync.Mutex - ObservedMetrics map[string]*stats.Metric + ObservedMetrics map[string]*metrics.Metric } // NewMetricsEngine creates a new metrics Engine with the given parameters. @@ -49,7 +48,7 @@ func NewMetricsEngine( runtimeOptions: rtOpts, logger: logger.WithField("component", "metrics-engine"), - ObservedMetrics: make(map[string]*stats.Metric), + ObservedMetrics: make(map[string]*metrics.Metric), } if !(me.runtimeOptions.NoSummary.Bool && me.runtimeOptions.NoThresholds.Bool) { @@ -71,7 +70,7 @@ func (me *MetricsEngine) GetIngester() output.Output { } } -func (me *MetricsEngine) getThresholdMetricOrSubmetric(name string) (*stats.Metric, error) { +func (me *MetricsEngine) getThresholdMetricOrSubmetric(name string) (*metrics.Metric, error) { // TODO: replace with strings.Cut after Go 1.18 nameParts := strings.SplitN(name, "{", 2) @@ -94,7 +93,7 @@ func (me *MetricsEngine) getThresholdMetricOrSubmetric(name string) (*stats.Metr return sm.Metric, nil } -func (me *MetricsEngine) markObserved(metric *stats.Metric) { +func (me *MetricsEngine) markObserved(metric *metrics.Metric) { if !metric.Observed { metric.Observed = true me.ObservedMetrics[metric.Name] = metric @@ -130,7 +129,7 @@ func (me *MetricsEngine) initSubMetricsAndThresholds() error { // TODO: refactor out of here when https://github.com/grafana/k6/issues/1321 // lands and there is a better way to enable a metric with tag - if me.options.SystemTags.Has(stats.TagExpectedResponse) { + if me.options.SystemTags.Has(metrics.TagExpectedResponse) { _, err := me.getThresholdMetricOrSubmetric("http_req_duration{expected_response:true}") if err != nil { return err // shouldn't happen, but ¯\_(ツ)_/¯ diff --git a/metrics/engine/ingester.go b/metrics/engine/ingester.go index 87bdceeadf2..83a514552a0 100644 --- a/metrics/engine/ingester.go +++ b/metrics/engine/ingester.go @@ -58,7 +58,7 @@ func (oi *outputIngester) flushMetrics() { oi.metricsEngine.MetricsLock.Lock() defer oi.metricsEngine.MetricsLock.Unlock() - // TODO: split metric samples in buckets with a *stats.Metric key; this will + // TODO: split metric samples in buckets with a *metrics.Metric key; this will // allow us to have a per-bucket lock, instead of one global one, and it // will allow us to split apart the metric Name and Type from its Sink and // Observed fields... diff --git a/metrics/metric.go b/metrics/metric.go new file mode 100644 index 00000000000..0165991419e --- /dev/null +++ b/metrics/metric.go @@ -0,0 +1,123 @@ +package metrics + +import ( + "fmt" + "strings" + "time" + + "gopkg.in/guregu/null.v3" +) + +// A Metric defines the shape of a set of data. +type Metric struct { + Name string `json:"name"` + Type MetricType `json:"type"` + Contains ValueType `json:"contains"` + + // TODO: decouple the metrics from the sinks and thresholds... have them + // linked, but not in the same struct? + Tainted null.Bool `json:"tainted"` + Thresholds Thresholds `json:"thresholds"` + Submetrics []*Submetric `json:"submetrics"` + Sub *Submetric `json:"-"` + Sink Sink `json:"-"` + Observed bool `json:"-"` +} + +// Sample samples the metric at the given time, with the provided tags and value +func (m *Metric) Sample(t time.Time, tags *SampleTags, value float64) Sample { + return Sample{ + Time: t, + Tags: tags, + Value: value, + Metric: m, + } +} + +// newMetric instantiates a new Metric +func newMetric(name string, mt MetricType, vt ...ValueType) *Metric { + valueType := Default + if len(vt) > 0 { + valueType = vt[0] + } + var sink Sink + switch mt { + case Counter: + sink = &CounterSink{} + case Gauge: + sink = &GaugeSink{} + case Trend: + sink = &TrendSink{} + case Rate: + sink = &RateSink{} + default: + return nil + } + return &Metric{ + Name: name, + Type: mt, + Contains: valueType, + Sink: sink, + } +} + +// A Submetric represents a filtered dataset based on a parent metric. +type Submetric struct { + Name string `json:"name"` + Suffix string `json:"suffix"` // TODO: rename? + Tags *SampleTags `json:"tags"` + + Metric *Metric `json:"-"` + Parent *Metric `json:"-"` +} + +// AddSubmetric creates a new submetric from the key:value threshold definition +// and adds it to the metric's submetrics list. +func (m *Metric) AddSubmetric(keyValues string) (*Submetric, error) { + keyValues = strings.TrimSpace(keyValues) + if len(keyValues) == 0 { + return nil, fmt.Errorf("submetric criteria for metric '%s' cannot be empty", m.Name) + } + kvs := strings.Split(keyValues, ",") + rawTags := make(map[string]string, len(kvs)) + for _, kv := range kvs { + if kv == "" { + continue + } + parts := strings.SplitN(kv, ":", 2) + + key := strings.Trim(strings.TrimSpace(parts[0]), `"'`) + if len(parts) != 2 { + rawTags[key] = "" + continue + } + + value := strings.Trim(strings.TrimSpace(parts[1]), `"'`) + rawTags[key] = value + } + + tags := IntoSampleTags(&rawTags) + + for _, sm := range m.Submetrics { + if sm.Tags.IsEqual(tags) { + return nil, fmt.Errorf( + "sub-metric with params '%s' already exists for metric %s: %s", + keyValues, m.Name, sm.Name, + ) + } + } + + subMetric := &Submetric{ + Name: m.Name + "{" + keyValues + "}", + Suffix: keyValues, + Tags: tags, + Parent: m, + } + subMetricMetric := newMetric(subMetric.Name, m.Type, m.Contains) + subMetricMetric.Sub = subMetric // sigh + subMetric.Metric = subMetricMetric + + m.Submetrics = append(m.Submetrics, subMetric) + + return subMetric, nil +} diff --git a/metrics/metric_test.go b/metrics/metric_test.go new file mode 100644 index 00000000000..7db2239b76d --- /dev/null +++ b/metrics/metric_test.go @@ -0,0 +1,68 @@ +package metrics + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestNewMetric(t *testing.T) { + t.Parallel() + testdata := map[string]struct { + Type MetricType + SinkType Sink + }{ + "Counter": {Counter, &CounterSink{}}, + "Gauge": {Gauge, &GaugeSink{}}, + "Trend": {Trend, &TrendSink{}}, + "Rate": {Rate, &RateSink{}}, + } + + for name, data := range testdata { + name, data := name, data + t.Run(name, func(t *testing.T) { + t.Parallel() + m := newMetric("my_metric", data.Type) + assert.Equal(t, "my_metric", m.Name) + assert.IsType(t, data.SinkType, m.Sink) + }) + } +} + +func TestAddSubmetric(t *testing.T) { + t.Parallel() + testdata := map[string]struct { + err bool + tags map[string]string + }{ + "": {true, nil}, + " ": {true, nil}, + "a": {false, map[string]string{"a": ""}}, + "a:1": {false, map[string]string{"a": "1"}}, + " a : 1 ": {false, map[string]string{"a": "1"}}, + "a,b": {false, map[string]string{"a": "", "b": ""}}, + ` a:"",b: ''`: {false, map[string]string{"a": "", "b": ""}}, + `a:1,b:2`: {false, map[string]string{"a": "1", "b": "2"}}, + ` a : 1, b : 2 `: {false, map[string]string{"a": "1", "b": "2"}}, + `a : '1' , b : "2"`: {false, map[string]string{"a": "1", "b": "2"}}, + `" a" : ' 1' , b : "2 " `: {false, map[string]string{" a": " 1", "b": "2 "}}, //nolint:gocritic + } + + for name, expected := range testdata { + name, expected := name, expected + t.Run(name, func(t *testing.T) { + t.Parallel() + + m := newMetric("metric", Trend) + sm, err := m.AddSubmetric(name) + if expected.err { + require.Error(t, err) + return + } + require.NoError(t, err) + require.NotNil(t, sm) + assert.EqualValues(t, expected.tags, sm.Tags.tags) + }) + } +} diff --git a/metrics/metric_type.go b/metrics/metric_type.go new file mode 100644 index 00000000000..ce0b9f4b8c3 --- /dev/null +++ b/metrics/metric_type.go @@ -0,0 +1,86 @@ +package metrics + +import "errors" + +// A MetricType specifies the type of a metric. +type MetricType int + +// Possible values for MetricType. +const ( + Counter = MetricType(iota) // A counter that sums its data points + Gauge // A gauge that displays the latest value + Trend // A trend, min/max/avg/med are interesting + Rate // A rate, displays % of values that aren't 0 +) + +// ErrInvalidMetricType indicates the serialized metric type is invalid. +var ErrInvalidMetricType = errors.New("invalid metric type") + +const ( + counterString = "counter" + gaugeString = "gauge" + trendString = "trend" + rateString = "rate" + + defaultString = "default" + timeString = "time" + dataString = "data" +) + +// MarshalJSON serializes a MetricType as a human readable string. +func (t MetricType) MarshalJSON() ([]byte, error) { + txt, err := t.MarshalText() + if err != nil { + return nil, err + } + return []byte(`"` + string(txt) + `"`), nil +} + +// MarshalText serializes a MetricType as a human readable string. +func (t MetricType) MarshalText() ([]byte, error) { + switch t { + case Counter: + return []byte(counterString), nil + case Gauge: + return []byte(gaugeString), nil + case Trend: + return []byte(trendString), nil + case Rate: + return []byte(rateString), nil + default: + return nil, ErrInvalidMetricType + } +} + +// UnmarshalText deserializes a MetricType from a string representation. +func (t *MetricType) UnmarshalText(data []byte) error { + switch string(data) { + case counterString: + *t = Counter + case gaugeString: + *t = Gauge + case trendString: + *t = Trend + case rateString: + *t = Rate + default: + return ErrInvalidMetricType + } + + return nil +} + +func (t MetricType) String() string { + switch t { + case Counter: + return counterString + case Gauge: + return gaugeString + case Trend: + return trendString + case Rate: + return rateString + default: + return "[INVALID]" + } +} diff --git a/metrics/registry.go b/metrics/registry.go index bfc28a44290..1d40c615bdc 100644 --- a/metrics/registry.go +++ b/metrics/registry.go @@ -24,20 +24,18 @@ import ( "fmt" "regexp" "sync" - - "go.k6.io/k6/stats" ) // Registry is what can create metrics type Registry struct { - metrics map[string]*stats.Metric + metrics map[string]*Metric l sync.RWMutex } // NewRegistry returns a new registry func NewRegistry() *Registry { return &Registry{ - metrics: make(map[string]*stats.Metric), + metrics: make(map[string]*Metric), } } @@ -51,7 +49,7 @@ func checkName(name string) bool { // NewMetric returns new metric registered to this registry // TODO have multiple versions returning specific metric types when we have such things -func (r *Registry) NewMetric(name string, typ stats.MetricType, t ...stats.ValueType) (*stats.Metric, error) { +func (r *Registry) NewMetric(name string, typ MetricType, t ...ValueType) (*Metric, error) { r.l.Lock() defer r.l.Unlock() @@ -78,7 +76,7 @@ func (r *Registry) NewMetric(name string, typ stats.MetricType, t ...stats.Value } // MustNewMetric is like NewMetric, but will panic if there is an error -func (r *Registry) MustNewMetric(name string, typ stats.MetricType, t ...stats.ValueType) *stats.Metric { +func (r *Registry) MustNewMetric(name string, typ MetricType, t ...ValueType) *Metric { m, err := r.NewMetric(name, typ, t...) if err != nil { panic(err) @@ -88,32 +86,6 @@ func (r *Registry) MustNewMetric(name string, typ stats.MetricType, t ...stats.V // Get returns the Metric with the given name. If that metric doesn't exist, // Get() will return a nil value. -func (r *Registry) Get(name string) *stats.Metric { +func (r *Registry) Get(name string) *Metric { return r.metrics[name] } - -func newMetric(name string, mt stats.MetricType, vt ...stats.ValueType) *stats.Metric { - valueType := stats.Default - if len(vt) > 0 { - valueType = vt[0] - } - var sink stats.Sink - switch mt { - case stats.Counter: - sink = &stats.CounterSink{} - case stats.Gauge: - sink = &stats.GaugeSink{} - case stats.Trend: - sink = &stats.TrendSink{} - case stats.Rate: - sink = &stats.RateSink{} - default: - return nil - } - return &stats.Metric{ - Name: name, - Type: mt, - Contains: valueType, - Sink: sink, - } -} diff --git a/metrics/registry_test.go b/metrics/registry_test.go index 890b84d3fdf..820df0a7e73 100644 --- a/metrics/registry_test.go +++ b/metrics/registry_test.go @@ -25,26 +25,25 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "go.k6.io/k6/stats" ) func TestRegistryNewMetric(t *testing.T) { t.Parallel() r := NewRegistry() - somethingCounter, err := r.NewMetric("something", stats.Counter) + somethingCounter, err := r.NewMetric("something", Counter) require.NoError(t, err) require.Equal(t, "something", somethingCounter.Name) - somethingCounterAgain, err := r.NewMetric("something", stats.Counter) + somethingCounterAgain, err := r.NewMetric("something", Counter) require.NoError(t, err) require.Equal(t, "something", somethingCounterAgain.Name) require.Same(t, somethingCounter, somethingCounterAgain) - _, err = r.NewMetric("something", stats.Gauge) + _, err = r.NewMetric("something", Gauge) require.Error(t, err) - _, err = r.NewMetric("something", stats.Counter, stats.Time) + _, err = r.NewMetric("something", Counter, Time) require.Error(t, err) } diff --git a/stats/stats.go b/metrics/sample.go similarity index 54% rename from stats/stats.go rename to metrics/sample.go index eaae2bf0967..cf9cf723205 100644 --- a/stats/stats.go +++ b/metrics/sample.go @@ -1,184 +1,175 @@ -/* - * - * k6 - a next-generation load testing tool - * Copyright (C) 2016 Load Impact - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - * - */ - -package stats +package metrics import ( "context" "encoding/json" - "errors" "fmt" "strconv" "strings" "time" "github.com/mailru/easyjson/jwriter" - "gopkg.in/guregu/null.v3" ) -const ( - counterString = "counter" - gaugeString = "gauge" - trendString = "trend" - rateString = "rate" +// A Sample is a single measurement. +type Sample struct { + Metric *Metric + Time time.Time + Tags *SampleTags + Value float64 +} - defaultString = "default" - timeString = "time" - dataString = "data" -) +// SampleContainer is a simple abstraction that allows sample +// producers to attach extra information to samples they return +type SampleContainer interface { + GetSamples() []Sample +} -// Possible values for MetricType. -const ( - Counter = MetricType(iota) // A counter that sums its data points - Gauge // A gauge that displays the latest value - Trend // A trend, min/max/avg/med are interesting - Rate // A rate, displays % of values that aren't 0 -) +// Samples is just the simplest SampleContainer implementation +// that will be used when there's no need for extra information +type Samples []Sample -// Possible values for ValueType. -const ( - Default = ValueType(iota) // Values are presented as-is - Time // Values are timestamps (nanoseconds) - Data // Values are data amounts (bytes) -) +// GetSamples just implements the SampleContainer interface +func (s Samples) GetSamples() []Sample { + return s +} -// The serialized metric type is invalid. -var ErrInvalidMetricType = errors.New("invalid metric type") +// ConnectedSampleContainer is an extension of the SampleContainer +// interface that should be implemented when emitted samples +// are connected and share the same time and tags. +type ConnectedSampleContainer interface { + SampleContainer + GetTags() *SampleTags + GetTime() time.Time +} -// The serialized value type is invalid. -var ErrInvalidValueType = errors.New("invalid value type") +// ConnectedSamples is the simplest ConnectedSampleContainer +// implementation that will be used when there's no need for +// extra information +type ConnectedSamples struct { + Samples []Sample + Tags *SampleTags + Time time.Time +} -// A MetricType specifies the type of a metric. -type MetricType int +// GetSamples implements the SampleContainer and ConnectedSampleContainer +// interfaces and returns the stored slice with samples. +func (cs ConnectedSamples) GetSamples() []Sample { + return cs.Samples +} -// MarshalJSON serializes a MetricType as a human readable string. -func (t MetricType) MarshalJSON() ([]byte, error) { - txt, err := t.MarshalText() - if err != nil { - return nil, err - } - return []byte(`"` + string(txt) + `"`), nil +// GetTags implements ConnectedSampleContainer interface and returns stored tags. +func (cs ConnectedSamples) GetTags() *SampleTags { + return cs.Tags } -// MarshalText serializes a MetricType as a human readable string. -func (t MetricType) MarshalText() ([]byte, error) { - switch t { - case Counter: - return []byte(counterString), nil - case Gauge: - return []byte(gaugeString), nil - case Trend: - return []byte(trendString), nil - case Rate: - return []byte(rateString), nil - default: - return nil, ErrInvalidMetricType - } +// GetTime implements ConnectedSampleContainer interface and returns stored time. +func (cs ConnectedSamples) GetTime() time.Time { + return cs.Time } -// UnmarshalText deserializes a MetricType from a string representation. -func (t *MetricType) UnmarshalText(data []byte) error { - switch string(data) { - case counterString: - *t = Counter - case gaugeString: - *t = Gauge - case trendString: - *t = Trend - case rateString: - *t = Rate - default: - return ErrInvalidMetricType - } +// GetSamples implement the ConnectedSampleContainer interface +// for a single Sample, since it's obviously connected with itself :) +func (s Sample) GetSamples() []Sample { + return []Sample{s} +} - return nil +// GetTags implements ConnectedSampleContainer interface +// and returns the sample's tags. +func (s Sample) GetTags() *SampleTags { + return s.Tags } -func (t MetricType) String() string { - switch t { - case Counter: - return counterString - case Gauge: - return gaugeString - case Trend: - return trendString - case Rate: - return rateString - default: - return "[INVALID]" - } +// GetTime just implements ConnectedSampleContainer interface +// and returns the sample's time. +func (s Sample) GetTime() time.Time { + return s.Time } -// The type of values a metric contains. -type ValueType int +// Ensure that interfaces are implemented correctly +var ( + _ SampleContainer = Sample{} + _ SampleContainer = Samples{} +) -// MarshalJSON serializes a ValueType to a JSON string. -func (t ValueType) MarshalJSON() ([]byte, error) { - txt, err := t.MarshalText() - if err != nil { - return nil, err +var ( + _ ConnectedSampleContainer = Sample{} + _ ConnectedSampleContainer = ConnectedSamples{} +) + +// GetBufferedSamples will read all present (i.e. buffered or currently being pushed) +// values in the input channel and return them as a slice. +func GetBufferedSamples(input <-chan SampleContainer) (result []SampleContainer) { + for { + select { + case val, ok := <-input: + if !ok { + return + } + result = append(result, val) + default: + return + } } - return []byte(`"` + string(txt) + `"`), nil } -// MarshalText serializes a ValueType as a human readable string. -func (t ValueType) MarshalText() ([]byte, error) { - switch t { - case Default: - return []byte(defaultString), nil - case Time: - return []byte(timeString), nil - case Data: - return []byte(dataString), nil - default: - return nil, ErrInvalidValueType +// PushIfNotDone first checks if the supplied context is done and doesn't push +// the sample container if it is. +func PushIfNotDone(ctx context.Context, output chan<- SampleContainer, sample SampleContainer) bool { + if ctx.Err() != nil { + return false } + output <- sample + return true } -// UnmarshalText deserializes a ValueType from a string representation. -func (t *ValueType) UnmarshalText(data []byte) error { - switch string(data) { - case defaultString: - *t = Default - case timeString: - *t = Time - case dataString: - *t = Data - default: - return ErrInvalidValueType +// GetResolversForTrendColumns checks if passed trend columns are valid for use in +// the summary output and then returns a map of the corresponding resolvers. +func GetResolversForTrendColumns(trendColumns []string) (map[string]func(s *TrendSink) float64, error) { + staticResolvers := map[string]func(s *TrendSink) float64{ + "avg": func(s *TrendSink) float64 { return s.Avg }, + "min": func(s *TrendSink) float64 { return s.Min }, + "med": func(s *TrendSink) float64 { return s.Med }, + "max": func(s *TrendSink) float64 { return s.Max }, + "count": func(s *TrendSink) float64 { return float64(s.Count) }, } + dynamicResolver := func(percentile float64) func(s *TrendSink) float64 { + return func(s *TrendSink) float64 { + return s.P(percentile / 100) + } + } + + result := make(map[string]func(s *TrendSink) float64, len(trendColumns)) - return nil + for _, stat := range trendColumns { + if staticStat, ok := staticResolvers[stat]; ok { + result[stat] = staticStat + continue + } + + percentile, err := parsePercentile(stat) + if err != nil { + return nil, err + } + result[stat] = dynamicResolver(percentile) + } + + return result, nil } -func (t ValueType) String() string { - switch t { - case Default: - return defaultString - case Time: - return timeString - case Data: - return dataString - default: - return "[INVALID]" +// parsePercentile is a helper function to parse and validate percentile notations +func parsePercentile(stat string) (float64, error) { + if !strings.HasPrefix(stat, "p(") || !strings.HasSuffix(stat, ")") { + return 0, fmt.Errorf("invalid trend stat '%s', unknown format", stat) } + + percentile, err := strconv.ParseFloat(stat[2:len(stat)-1], 64) + + if err != nil || (percentile < 0) || (percentile > 100) { + return 0, fmt.Errorf("invalid percentile trend stat value '%s', provide a number between 0 and 100", stat) + } + + return percentile, nil } // SampleTags is an immutable string[string] map for tags. Once a tag @@ -325,277 +316,3 @@ func IntoSampleTags(data *map[string]string) *SampleTags { *data = nil return &res } - -// A Sample is a single measurement. -type Sample struct { - Metric *Metric - Time time.Time - Tags *SampleTags - Value float64 -} - -// SampleContainer is a simple abstraction that allows sample -// producers to attach extra information to samples they return -type SampleContainer interface { - GetSamples() []Sample -} - -// Samples is just the simplest SampleContainer implementation -// that will be used when there's no need for extra information -type Samples []Sample - -// GetSamples just implements the SampleContainer interface -func (s Samples) GetSamples() []Sample { - return s -} - -// ConnectedSampleContainer is an extension of the SampleContainer -// interface that should be implemented when emitted samples -// are connected and share the same time and tags. -type ConnectedSampleContainer interface { - SampleContainer - GetTags() *SampleTags - GetTime() time.Time -} - -// ConnectedSamples is the simplest ConnectedSampleContainer -// implementation that will be used when there's no need for -// extra information -type ConnectedSamples struct { - Samples []Sample - Tags *SampleTags - Time time.Time -} - -// GetSamples implements the SampleContainer and ConnectedSampleContainer -// interfaces and returns the stored slice with samples. -func (cs ConnectedSamples) GetSamples() []Sample { - return cs.Samples -} - -// GetTags implements ConnectedSampleContainer interface and returns stored tags. -func (cs ConnectedSamples) GetTags() *SampleTags { - return cs.Tags -} - -// GetTime implements ConnectedSampleContainer interface and returns stored time. -func (cs ConnectedSamples) GetTime() time.Time { - return cs.Time -} - -// GetSamples implement the ConnectedSampleContainer interface -// for a single Sample, since it's obviously connected with itself :) -func (s Sample) GetSamples() []Sample { - return []Sample{s} -} - -// GetTags implements ConnectedSampleContainer interface -// and returns the sample's tags. -func (s Sample) GetTags() *SampleTags { - return s.Tags -} - -// GetTime just implements ConnectedSampleContainer interface -// and returns the sample's time. -func (s Sample) GetTime() time.Time { - return s.Time -} - -// Ensure that interfaces are implemented correctly -var ( - _ SampleContainer = Sample{} - _ SampleContainer = Samples{} -) - -var ( - _ ConnectedSampleContainer = Sample{} - _ ConnectedSampleContainer = ConnectedSamples{} -) - -// GetBufferedSamples will read all present (i.e. buffered or currently being pushed) -// values in the input channel and return them as a slice. -func GetBufferedSamples(input <-chan SampleContainer) (result []SampleContainer) { - for { - select { - case val, ok := <-input: - if !ok { - return - } - result = append(result, val) - default: - return - } - } -} - -// PushIfNotDone first checks if the supplied context is done and doesn't push -// the sample container if it is. -func PushIfNotDone(ctx context.Context, output chan<- SampleContainer, sample SampleContainer) bool { - if ctx.Err() != nil { - return false - } - output <- sample - return true -} - -// TODO: move to the metrics/ package - -// A Metric defines the shape of a set of data. -type Metric struct { - Name string `json:"name"` - Type MetricType `json:"type"` - Contains ValueType `json:"contains"` - - // TODO: decouple the metrics from the sinks and thresholds... have them - // linked, but not in the same struct? - Tainted null.Bool `json:"tainted"` - Thresholds Thresholds `json:"thresholds"` - Submetrics []*Submetric `json:"submetrics"` - Sub *Submetric `json:"-"` - Sink Sink `json:"-"` - Observed bool `json:"-"` -} - -// Sample samples the metric at the given time, with the provided tags and value -func (m *Metric) Sample(t time.Time, tags *SampleTags, value float64) Sample { - return Sample{ - Time: t, - Tags: tags, - Value: value, - Metric: m, - } -} - -// newMetric instantiates a new Metric -func newMetric(name string, mt MetricType, vt ...ValueType) *Metric { - contains := Default - if len(vt) > 0 { - contains = vt[0] - } - - var sink Sink - switch mt { - case Counter: - sink = &CounterSink{} - case Gauge: - sink = &GaugeSink{} - case Trend: - sink = &TrendSink{} - case Rate: - sink = &RateSink{} - default: - return nil - } - - return &Metric{Name: name, Type: mt, Contains: contains, Sink: sink} -} - -// A Submetric represents a filtered dataset based on a parent metric. -type Submetric struct { - Name string `json:"name"` - Suffix string `json:"suffix"` // TODO: rename? - Tags *SampleTags `json:"tags"` - - Metric *Metric `json:"-"` - Parent *Metric `json:"-"` -} - -// AddSubmetric creates a new submetric from the key:value threshold definition -// and adds it to the metric's submetrics list. -func (m *Metric) AddSubmetric(keyValues string) (*Submetric, error) { - keyValues = strings.TrimSpace(keyValues) - if len(keyValues) == 0 { - return nil, fmt.Errorf("submetric criteria for metric '%s' cannot be empty", m.Name) - } - kvs := strings.Split(keyValues, ",") - rawTags := make(map[string]string, len(kvs)) - for _, kv := range kvs { - if kv == "" { - continue - } - parts := strings.SplitN(kv, ":", 2) - - key := strings.Trim(strings.TrimSpace(parts[0]), `"'`) - if len(parts) != 2 { - rawTags[key] = "" - continue - } - - value := strings.Trim(strings.TrimSpace(parts[1]), `"'`) - rawTags[key] = value - } - - tags := IntoSampleTags(&rawTags) - - for _, sm := range m.Submetrics { - if sm.Tags.IsEqual(tags) { - return nil, fmt.Errorf( - "sub-metric with params '%s' already exists for metric %s: %s", - keyValues, m.Name, sm.Name, - ) - } - } - - subMetric := &Submetric{ - Name: m.Name + "{" + keyValues + "}", - Suffix: keyValues, - Tags: tags, - Parent: m, - } - subMetricMetric := newMetric(subMetric.Name, m.Type, m.Contains) - subMetricMetric.Sub = subMetric // sigh - subMetric.Metric = subMetricMetric - - m.Submetrics = append(m.Submetrics, subMetric) - - return subMetric, nil -} - -// parsePercentile is a helper function to parse and validate percentile notations -func parsePercentile(stat string) (float64, error) { - if !strings.HasPrefix(stat, "p(") || !strings.HasSuffix(stat, ")") { - return 0, fmt.Errorf("invalid trend stat '%s', unknown format", stat) - } - - percentile, err := strconv.ParseFloat(stat[2:len(stat)-1], 64) - - if err != nil || (percentile < 0) || (percentile > 100) { - return 0, fmt.Errorf("invalid percentile trend stat value '%s', provide a number between 0 and 100", stat) - } - - return percentile, nil -} - -// GetResolversForTrendColumns checks if passed trend columns are valid for use in -// the summary output and then returns a map of the corresponding resolvers. -func GetResolversForTrendColumns(trendColumns []string) (map[string]func(s *TrendSink) float64, error) { - staticResolvers := map[string]func(s *TrendSink) float64{ - "avg": func(s *TrendSink) float64 { return s.Avg }, - "min": func(s *TrendSink) float64 { return s.Min }, - "med": func(s *TrendSink) float64 { return s.Med }, - "max": func(s *TrendSink) float64 { return s.Max }, - "count": func(s *TrendSink) float64 { return float64(s.Count) }, - } - dynamicResolver := func(percentile float64) func(s *TrendSink) float64 { - return func(s *TrendSink) float64 { - return s.P(percentile / 100) - } - } - - result := make(map[string]func(s *TrendSink) float64, len(trendColumns)) - - for _, stat := range trendColumns { - if staticStat, ok := staticResolvers[stat]; ok { - result[stat] = staticStat - continue - } - - percentile, err := parsePercentile(stat) - if err != nil { - return nil, err - } - result[stat] = dynamicResolver(percentile) - } - - return result, nil -} diff --git a/stats/stats_test.go b/metrics/sample_test.go similarity index 63% rename from stats/stats_test.go rename to metrics/sample_test.go index 7ec7ae3887c..fddd5383226 100644 --- a/stats/stats_test.go +++ b/metrics/sample_test.go @@ -1,24 +1,4 @@ -/* - * - * k6 - a next-generation load testing tool - * Copyright (C) 2016 Load Impact - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - * - */ - -package stats +package metrics import ( "encoding/json" @@ -27,69 +7,8 @@ import ( "time" "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" ) -func TestNewMetric(t *testing.T) { - t.Parallel() - testdata := map[string]struct { - Type MetricType - SinkType Sink - }{ - "Counter": {Counter, &CounterSink{}}, - "Gauge": {Gauge, &GaugeSink{}}, - "Trend": {Trend, &TrendSink{}}, - "Rate": {Rate, &RateSink{}}, - } - - for name, data := range testdata { - name, data := name, data - t.Run(name, func(t *testing.T) { - t.Parallel() - m := newMetric("my_metric", data.Type) - assert.Equal(t, "my_metric", m.Name) - assert.IsType(t, data.SinkType, m.Sink) - }) - } -} - -func TestAddSubmetric(t *testing.T) { - t.Parallel() - testdata := map[string]struct { - err bool - tags map[string]string - }{ - "": {true, nil}, - " ": {true, nil}, - "a": {false, map[string]string{"a": ""}}, - "a:1": {false, map[string]string{"a": "1"}}, - " a : 1 ": {false, map[string]string{"a": "1"}}, - "a,b": {false, map[string]string{"a": "", "b": ""}}, - ` a:"",b: ''`: {false, map[string]string{"a": "", "b": ""}}, - `a:1,b:2`: {false, map[string]string{"a": "1", "b": "2"}}, - ` a : 1, b : 2 `: {false, map[string]string{"a": "1", "b": "2"}}, - `a : '1' , b : "2"`: {false, map[string]string{"a": "1", "b": "2"}}, - `" a" : ' 1' , b : "2 " `: {false, map[string]string{" a": " 1", "b": "2 "}}, //nolint:gocritic - } - - for name, expected := range testdata { - name, expected := name, expected - t.Run(name, func(t *testing.T) { - t.Parallel() - - m := newMetric("metric", Trend) - sm, err := m.AddSubmetric(name) - if expected.err { - require.Error(t, err) - return - } - require.NoError(t, err) - require.NotNil(t, sm) - assert.EqualValues(t, expected.tags, sm.Tags.tags) - }) - } -} - func TestSampleTags(t *testing.T) { t.Parallel() @@ -208,17 +127,9 @@ func TestGetResolversForTrendColumnsValidation(t *testing.T) { } } -func createTestTrendSink(count int) *TrendSink { - sink := TrendSink{} - - for i := 0; i < count; i++ { - sink.Add(Sample{Value: float64(i)}) - } - - return &sink -} +func TestGetResolversForTrendColumnsCalculation(t *testing.T) { + t.Parallel() -func TestResolversForTrendColumnsCalculation(t *testing.T) { customResolversTests := []struct { stats string percentile float64 @@ -230,11 +141,12 @@ func TestResolversForTrendColumnsCalculation(t *testing.T) { {"p(99.999)", 0.99999}, } - sink := createTestTrendSink(100) - for _, tc := range customResolversTests { tc := tc t.Run(fmt.Sprintf("%v", tc.stats), func(t *testing.T) { + t.Parallel() + sink := createTestTrendSink(100) + res, err := GetResolversForTrendColumns([]string{tc.stats}) assert.NoError(t, err) assert.Len(t, res, 1) @@ -244,3 +156,13 @@ func TestResolversForTrendColumnsCalculation(t *testing.T) { }) } } + +func createTestTrendSink(count int) *TrendSink { + sink := TrendSink{} + + for i := 0; i < count; i++ { + sink.Add(Sample{Value: float64(i)}) + } + + return &sink +} diff --git a/stats/sink.go b/metrics/sink.go similarity index 99% rename from stats/sink.go rename to metrics/sink.go index 8834454ada3..01b5d5263a9 100644 --- a/stats/sink.go +++ b/metrics/sink.go @@ -18,7 +18,7 @@ * */ -package stats +package metrics import ( "errors" diff --git a/stats/sink_test.go b/metrics/sink_test.go similarity index 99% rename from stats/sink_test.go rename to metrics/sink_test.go index 6c629da3f86..585a2950acb 100644 --- a/stats/sink_test.go +++ b/metrics/sink_test.go @@ -18,7 +18,7 @@ * */ -package stats +package metrics import ( "testing" diff --git a/stats/system_tag.go b/metrics/system_tag.go similarity index 99% rename from stats/system_tag.go rename to metrics/system_tag.go index d68a905caf4..6a9d0513935 100644 --- a/stats/system_tag.go +++ b/metrics/system_tag.go @@ -18,7 +18,7 @@ * */ -package stats +package metrics import ( "bytes" diff --git a/stats/system_tag_set_gen.go b/metrics/system_tag_set_gen.go similarity index 99% rename from stats/system_tag_set_gen.go rename to metrics/system_tag_set_gen.go index b65604d01ec..08ae3fc19df 100644 --- a/stats/system_tag_set_gen.go +++ b/metrics/system_tag_set_gen.go @@ -1,7 +1,7 @@ // Code generated by "enumer -type=SystemTagSet -transform=snake -trimprefix=Tag -output system_tag_set_gen.go"; DO NOT EDIT. // -package stats +package metrics import ( "fmt" diff --git a/stats/system_tag_test.go b/metrics/system_tag_test.go similarity index 97% rename from stats/system_tag_test.go rename to metrics/system_tag_test.go index 86f91e53974..623b822fb6c 100644 --- a/stats/system_tag_test.go +++ b/metrics/system_tag_test.go @@ -18,7 +18,7 @@ * */ -package stats +package metrics import ( "encoding/json" @@ -29,6 +29,8 @@ import ( ) func TestSystemTagSetMarshalJSON(t *testing.T) { + t.Parallel() + tests := []struct { tagset SystemTagSet expected string @@ -47,6 +49,8 @@ func TestSystemTagSetMarshalJSON(t *testing.T) { } func TestSystemTagSet_UnmarshalJSON(t *testing.T) { + t.Parallel() + tests := []struct { tags []byte sets []SystemTagSet @@ -65,6 +69,8 @@ func TestSystemTagSet_UnmarshalJSON(t *testing.T) { } func TestSystemTagSetTextUnmarshal(t *testing.T) { + t.Parallel() + testMatrix := map[string]SystemTagSet{ "": 0, "ip": TagIP, @@ -83,6 +89,8 @@ func TestSystemTagSetTextUnmarshal(t *testing.T) { } func TestTagSetMarshalJSON(t *testing.T) { + t.Parallel() + tests := []struct { tagset TagSet expected string @@ -100,6 +108,8 @@ func TestTagSetMarshalJSON(t *testing.T) { } func TestTagSet_UnmarshalJSON(t *testing.T) { + t.Parallel() + tests := []struct { tags []byte sets TagSet @@ -118,6 +128,8 @@ func TestTagSet_UnmarshalJSON(t *testing.T) { } func TestTagSetTextUnmarshal(t *testing.T) { + t.Parallel() + testMatrix := map[string]TagSet{ "": make(TagSet), "ip": {"ip": true}, diff --git a/stats/thresholds.go b/metrics/thresholds.go similarity index 97% rename from stats/thresholds.go rename to metrics/thresholds.go index 3b513dc57b0..90e5f816389 100644 --- a/stats/thresholds.go +++ b/metrics/thresholds.go @@ -17,7 +17,7 @@ * along with this program. If not, see . * */ -package stats +package metrics import ( "bytes" @@ -188,10 +188,10 @@ func (ts *Thresholds) Run(sink Sink, duration time.Duration) (bool, error) { // Initialize the sinks store ts.sinked = make(map[string]float64) - // FIXME: Remove this comment as soon as the stats.Sink does not expose Format anymore. + // FIXME: Remove this comment as soon as the metrics.Sink does not expose Format anymore. // // As of December 2021, this block reproduces the behavior of the - // stats.Sink.Format behavior. As we intend to try to get away from it, + // metrics.Sink.Format behavior. As we intend to try to get away from it, // we instead implement the behavior directly here. // // For more details, see https://github.com/grafana/k6/issues/2320 diff --git a/stats/thresholds_parser.go b/metrics/thresholds_parser.go similarity index 99% rename from stats/thresholds_parser.go rename to metrics/thresholds_parser.go index cdb0a28190b..cd9c7b2e531 100644 --- a/stats/thresholds_parser.go +++ b/metrics/thresholds_parser.go @@ -18,7 +18,7 @@ * */ -package stats +package metrics import ( "fmt" diff --git a/stats/thresholds_parser_test.go b/metrics/thresholds_parser_test.go similarity index 99% rename from stats/thresholds_parser_test.go rename to metrics/thresholds_parser_test.go index 25120684d6e..ac751cbf57b 100644 --- a/stats/thresholds_parser_test.go +++ b/metrics/thresholds_parser_test.go @@ -18,7 +18,7 @@ * */ -package stats +package metrics import ( "testing" diff --git a/stats/thresholds_test.go b/metrics/thresholds_test.go similarity index 99% rename from stats/thresholds_test.go rename to metrics/thresholds_test.go index 91ff5cf89c4..f1bcfe1ff35 100644 --- a/stats/thresholds_test.go +++ b/metrics/thresholds_test.go @@ -18,7 +18,7 @@ * */ -package stats +package metrics import ( "encoding/json" diff --git a/stats/units.go b/metrics/units.go similarity index 98% rename from stats/units.go rename to metrics/units.go index e414f8d20d7..8a7bcb8315b 100644 --- a/stats/units.go +++ b/metrics/units.go @@ -18,7 +18,7 @@ * */ -package stats +package metrics import ( "time" diff --git a/metrics/value_type.go b/metrics/value_type.go new file mode 100644 index 00000000000..59cd49cab77 --- /dev/null +++ b/metrics/value_type.go @@ -0,0 +1,68 @@ +package metrics + +import "errors" + +// Possible values for ValueType. +const ( + Default = ValueType(iota) // Values are presented as-is + Time // Values are timestamps (nanoseconds) + Data // Values are data amounts (bytes) +) + +// ErrInvalidValueType indicates the serialized value type is invalid. +var ErrInvalidValueType = errors.New("invalid value type") + +// ValueType holds the type of values a metric contains. +type ValueType int + +// MarshalJSON serializes a ValueType to a JSON string. +func (t ValueType) MarshalJSON() ([]byte, error) { + txt, err := t.MarshalText() + if err != nil { + return nil, err + } + return []byte(`"` + string(txt) + `"`), nil +} + +// MarshalText serializes a ValueType as a human readable string. +func (t ValueType) MarshalText() ([]byte, error) { + switch t { + case Default: + return []byte(defaultString), nil + case Time: + return []byte(timeString), nil + case Data: + return []byte(dataString), nil + default: + return nil, ErrInvalidValueType + } +} + +// UnmarshalText deserializes a ValueType from a string representation. +func (t *ValueType) UnmarshalText(data []byte) error { + switch string(data) { + case defaultString: + *t = Default + case timeString: + *t = Time + case dataString: + *t = Data + default: + return ErrInvalidValueType + } + + return nil +} + +func (t ValueType) String() string { + switch t { + case Default: + return defaultString + case Time: + return timeString + case Data: + return dataString + default: + return "[INVALID]" + } +} diff --git a/output/cloud/bench_test.go b/output/cloud/bench_test.go index 04b6a291dbe..f18d6d3d7d7 100644 --- a/output/cloud/bench_test.go +++ b/output/cloud/bench_test.go @@ -42,8 +42,8 @@ import ( "go.k6.io/k6/lib/testutils" "go.k6.io/k6/lib/testutils/httpmultibin" "go.k6.io/k6/lib/types" + "go.k6.io/k6/metrics" "go.k6.io/k6/output" - "go.k6.io/k6/stats" ) func BenchmarkAggregateHTTP(b *testing.B) { @@ -52,7 +52,7 @@ func BenchmarkAggregateHTTP(b *testing.B) { JSONConfig: json.RawMessage(`{"noCompress": true, "aggregationCalcInterval": "200ms","aggregationPeriod": "200ms"}`), ScriptOptions: lib.Options{ Duration: types.NullDurationFrom(1 * time.Second), - SystemTags: &stats.DefaultSystemTagSet, + SystemTags: &metrics.DefaultSystemTagSet, }, ScriptPath: &url.URL{Path: "/script.js"}, }) @@ -67,7 +67,7 @@ func BenchmarkAggregateHTTP(b *testing.B) { b.ResetTimer() for s := 0; s < b.N; s++ { b.StopTimer() - container := make([]stats.SampleContainer, containersCount) + container := make([]metrics.SampleContainer, containersCount) for i := 1; i <= containersCount; i++ { status := "200" if i%tagCount%7 == 6 { @@ -88,7 +88,7 @@ func BenchmarkAggregateHTTP(b *testing.B) { } } -func generateTags(i, tagCount int, additionals ...map[string]string) *stats.SampleTags { +func generateTags(i, tagCount int, additionals ...map[string]string) *metrics.SampleTags { res := map[string]string{ "test": "mest", "a": "b", "custom": fmt.Sprintf("group%d", i%tagCount%9), @@ -102,7 +102,7 @@ func generateTags(i, tagCount int, additionals ...map[string]string) *stats.Samp } } - return stats.IntoSampleTags(&res) + return metrics.IntoSampleTags(&res) } func BenchmarkMetricMarshal(b *testing.B) { @@ -241,7 +241,7 @@ func generateSamples(count int) []*Sample { Metric: "something", Data: &SampleDataSingle{ Time: toMicroSecond(now), - Type: stats.Counter, + Type: metrics.Counter, Tags: tags, Value: float64(i), }, @@ -273,7 +273,7 @@ func generateSamples(count int) []*Sample { return samples } -func generateHTTPExtTrail(now time.Time, i time.Duration, tags *stats.SampleTags) *httpext.Trail { +func generateHTTPExtTrail(now time.Time, i time.Duration, tags *metrics.SampleTags) *httpext.Trail { return &httpext.Trail{ Blocked: i % 200 * 100 * time.Millisecond, Connecting: i % 200 * 200 * time.Millisecond, @@ -313,7 +313,7 @@ func BenchmarkHTTPPush(b *testing.B) { }`, tb.ServerHTTP.URL)), ScriptOptions: lib.Options{ Duration: types.NullDurationFrom(1 * time.Second), - SystemTags: &stats.DefaultSystemTagSet, + SystemTags: &metrics.DefaultSystemTagSet, }, ScriptPath: &url.URL{Path: "/script.js"}, }) diff --git a/output/cloud/cloud_easyjson.go b/output/cloud/cloud_easyjson.go index a62045d5f63..cd13c2b2bbd 100644 --- a/output/cloud/cloud_easyjson.go +++ b/output/cloud/cloud_easyjson.go @@ -7,7 +7,7 @@ import ( easyjson "github.com/mailru/easyjson" jlexer "github.com/mailru/easyjson/jlexer" jwriter "github.com/mailru/easyjson/jwriter" - stats "go.k6.io/k6/stats" + metrics "go.k6.io/k6/metrics" ) // suppress unused package warning @@ -113,7 +113,7 @@ func easyjson9def2ecdDecodeGoK6IoK6OutputCloud1(in *jlexer.Lexer, out *SampleDat out.Tags = nil } else { if out.Tags == nil { - out.Tags = new(stats.SampleTags) + out.Tags = new(metrics.SampleTags) } if data := in.Raw(); in.Ok() { in.AddError((*out.Tags).UnmarshalJSON(data)) @@ -198,7 +198,7 @@ func easyjson9def2ecdDecodeGoK6IoK6OutputCloud2(in *jlexer.Lexer, out *SampleDat out.Tags = nil } else { if out.Tags == nil { - out.Tags = new(stats.SampleTags) + out.Tags = new(metrics.SampleTags) } if data := in.Raw(); in.Ok() { in.AddError((*out.Tags).UnmarshalJSON(data)) @@ -315,7 +315,7 @@ func easyjson9def2ecdDecodeGoK6IoK6OutputCloud3(in *jlexer.Lexer, out *SampleDat out.Tags = nil } else { if out.Tags == nil { - out.Tags = new(stats.SampleTags) + out.Tags = new(metrics.SampleTags) } if data := in.Raw(); in.Ok() { in.AddError((*out.Tags).UnmarshalJSON(data)) diff --git a/output/cloud/data.go b/output/cloud/data.go index 1178ddaf8fc..2bd98968628 100644 --- a/output/cloud/data.go +++ b/output/cloud/data.go @@ -29,7 +29,6 @@ import ( "go.k6.io/k6/lib/netext/httpext" "go.k6.io/k6/metrics" - "go.k6.io/k6/stats" ) // DataType constants @@ -90,10 +89,10 @@ func (ct *Sample) UnmarshalJSON(p []byte) error { // SampleDataSingle is used in all simple un-aggregated single-value samples. //easyjson:json type SampleDataSingle struct { - Time int64 `json:"time,string"` - Type stats.MetricType `json:"type"` - Tags *stats.SampleTags `json:"tags,omitempty"` - Value float64 `json:"value"` + Time int64 `json:"time,string"` + Type metrics.MetricType `json:"type"` + Tags *metrics.SampleTags `json:"tags,omitempty"` + Value float64 `json:"value"` } // SampleDataMap is used by samples that contain multiple values, currently @@ -101,10 +100,10 @@ type SampleDataSingle struct { // requests (`http_req_li_all`). //easyjson:json type SampleDataMap struct { - Time int64 `json:"time,string"` - Type stats.MetricType `json:"type"` - Tags *stats.SampleTags `json:"tags,omitempty"` - Values map[string]float64 `json:"values,omitempty"` + Time int64 `json:"time,string"` + Type metrics.MetricType `json:"type"` + Tags *metrics.SampleTags `json:"tags,omitempty"` + Values map[string]float64 `json:"values,omitempty"` } // NewSampleFromTrail just creates a ready-to-send Sample instance @@ -117,15 +116,15 @@ func NewSampleFromTrail(trail *httpext.Trail) *Sample { values := make(map[string]float64, length) values[metrics.HTTPReqsName] = 1 - values[metrics.HTTPReqDurationName] = stats.D(trail.Duration) - values[metrics.HTTPReqBlockedName] = stats.D(trail.Blocked) - values[metrics.HTTPReqConnectingName] = stats.D(trail.Connecting) - values[metrics.HTTPReqTLSHandshakingName] = stats.D(trail.TLSHandshaking) - values[metrics.HTTPReqSendingName] = stats.D(trail.Sending) - values[metrics.HTTPReqWaitingName] = stats.D(trail.Waiting) - values[metrics.HTTPReqReceivingName] = stats.D(trail.Receiving) + values[metrics.HTTPReqDurationName] = metrics.D(trail.Duration) + values[metrics.HTTPReqBlockedName] = metrics.D(trail.Blocked) + values[metrics.HTTPReqConnectingName] = metrics.D(trail.Connecting) + values[metrics.HTTPReqTLSHandshakingName] = metrics.D(trail.TLSHandshaking) + values[metrics.HTTPReqSendingName] = metrics.D(trail.Sending) + values[metrics.HTTPReqWaitingName] = metrics.D(trail.Waiting) + values[metrics.HTTPReqReceivingName] = metrics.D(trail.Receiving) if trail.Failed.Valid { // this is done so the adding of 1 map element doesn't reexpand the map as this is a hotpath - values[metrics.HTTPReqFailedName] = stats.B(trail.Failed.Bool) + values[metrics.HTTPReqFailedName] = metrics.B(trail.Failed.Bool) } return &Sample{ Type: DataTypeMap, @@ -141,10 +140,10 @@ func NewSampleFromTrail(trail *httpext.Trail) *Sample { // SampleDataAggregatedHTTPReqs is used in aggregated samples for HTTP requests. //easyjson:json type SampleDataAggregatedHTTPReqs struct { - Time int64 `json:"time,string"` - Type string `json:"type"` - Count uint64 `json:"count"` - Tags *stats.SampleTags `json:"tags,omitempty"` + Time int64 `json:"time,string"` + Type string `json:"type"` + Count uint64 `json:"count"` + Tags *metrics.SampleTags `json:"tags,omitempty"` Values struct { Duration AggregatedMetric `json:"http_req_duration"` Blocked AggregatedMetric `json:"http_req_blocked"` @@ -229,12 +228,12 @@ func (am *AggregatedMetric) Add(t time.Duration) { // Calc populates the float fields for min and max and calculates the average value func (am *AggregatedMetric) Calc(count float64) { - am.Min = stats.D(am.minD) - am.Max = stats.D(am.maxD) - am.Avg = stats.D(am.sumD) / count + am.Min = metrics.D(am.minD) + am.Max = metrics.D(am.maxD) + am.Avg = metrics.D(am.sumD) / count } -type aggregationBucket map[*stats.SampleTags][]*httpext.Trail +type aggregationBucket map[*metrics.SampleTags][]*httpext.Trail type durations []time.Duration diff --git a/output/cloud/data_test.go b/output/cloud/data_test.go index 8e614dad2ac..3b1fd5c4608 100644 --- a/output/cloud/data_test.go +++ b/output/cloud/data_test.go @@ -33,7 +33,6 @@ import ( "go.k6.io/k6/lib/netext/httpext" "go.k6.io/k6/metrics" - "go.k6.io/k6/stats" ) func TestSampleMarshaling(t *testing.T) { @@ -54,7 +53,7 @@ func TestSampleMarshaling(t *testing.T) { Data: &SampleDataSingle{ Type: builtinMetrics.VUs.Type, Time: toMicroSecond(now), - Tags: stats.IntoSampleTags(&map[string]string{"aaa": "bbb", "ccc": "123"}), + Tags: metrics.IntoSampleTags(&map[string]string{"aaa": "bbb", "ccc": "123"}), Value: 999, }, }, @@ -66,11 +65,11 @@ func TestSampleMarshaling(t *testing.T) { Metric: "iter_li_all", Data: &SampleDataMap{ Time: toMicroSecond(now), - Tags: stats.IntoSampleTags(&map[string]string{"test": "mest"}), + Tags: metrics.IntoSampleTags(&map[string]string{"test": "mest"}), Values: map[string]float64{ metrics.DataSentName: 1234.5, metrics.DataReceivedName: 6789.1, - metrics.IterationDurationName: stats.D(10 * time.Second), + metrics.IterationDurationName: metrics.D(10 * time.Second), }, }, }, @@ -108,7 +107,7 @@ func TestSampleMarshaling(t *testing.T) { aggrData := &SampleDataAggregatedHTTPReqs{ Time: exptoMicroSecond, Type: "aggregated_trend", - Tags: stats.IntoSampleTags(&map[string]string{"test": "mest"}), + Tags: metrics.IntoSampleTags(&map[string]string{"test": "mest"}), } aggrData.Add( &httpext.Trail{ @@ -150,7 +149,7 @@ func TestSampleMarshaling(t *testing.T) { aggrData := &SampleDataAggregatedHTTPReqs{ Time: exptoMicroSecond, Type: "aggregated_trend", - Tags: stats.IntoSampleTags(&map[string]string{"test": "mest"}), + Tags: metrics.IntoSampleTags(&map[string]string{"test": "mest"}), } aggrData.Add( &httpext.Trail{ @@ -218,9 +217,9 @@ func TestMetricAggregation(t *testing.T) { m.Add(5 * time.Second) m.Add(10 * time.Second) m.Calc(5) - assert.Equal(t, m.Min, stats.D(1*time.Second)) - assert.Equal(t, m.Max, stats.D(10*time.Second)) - assert.Equal(t, m.Avg, stats.D(4*time.Second)) + assert.Equal(t, m.Min, metrics.D(1*time.Second)) + assert.Equal(t, m.Max, metrics.D(10*time.Second)) + assert.Equal(t, m.Avg, metrics.D(4*time.Second)) } // For more realistic request time distributions, import diff --git a/output/cloud/output.go b/output/cloud/output.go index 2da3baadb21..22bcc8229aa 100644 --- a/output/cloud/output.go +++ b/output/cloud/output.go @@ -40,7 +40,6 @@ import ( "go.k6.io/k6/lib/netext" "go.k6.io/k6/lib/netext/httpext" "go.k6.io/k6/metrics" - "go.k6.io/k6/stats" ) // TestName is the default Load Impact Cloud test name @@ -53,7 +52,7 @@ type Output struct { executionPlan []lib.ExecutionStep duration int64 // in seconds - thresholds map[string][]*stats.Threshold + thresholds map[string][]*metrics.Threshold client *MetricsClient runStatus lib.RunStatus @@ -110,7 +109,7 @@ func newOutput(params output.Params) (*Output, error) { logger := params.Logger.WithFields(logrus.Fields{"output": "cloud"}) if conf.AggregationPeriod.Duration > 0 && - (params.ScriptOptions.SystemTags.Has(stats.TagVU) || params.ScriptOptions.SystemTags.Has(stats.TagIter)) { + (params.ScriptOptions.SystemTags.Has(metrics.TagVU) || params.ScriptOptions.SystemTags.Has(metrics.TagIter)) { return nil, errors.New("aggregation cannot be enabled if the 'vu' or 'iter' system tag is also enabled") } @@ -163,10 +162,15 @@ func newOutput(params output.Params) (*Output, error) { } // validateRequiredSystemTags checks if all required tags are present. -func validateRequiredSystemTags(scriptTags *stats.SystemTagSet) error { +func validateRequiredSystemTags(scriptTags *metrics.SystemTagSet) error { missingRequiredTags := []string{} - requiredTags := stats.TagName | stats.TagMethod | stats.TagStatus | stats.TagError | stats.TagCheck | stats.TagGroup - for _, tag := range stats.SystemTagSetValues() { + requiredTags := metrics.TagName | + metrics.TagMethod | + metrics.TagStatus | + metrics.TagError | + metrics.TagCheck | + metrics.TagGroup + for _, tag := range metrics.SystemTagSetValues() { if requiredTags.Has(tag) && !scriptTags.Has(tag) { missingRequiredTags = append(missingRequiredTags, tag.String()) } @@ -309,8 +313,8 @@ func (out *Output) SetRunStatus(status lib.RunStatus) { } // SetThresholds receives the thresholds before the output is Start()-ed. -func (out *Output) SetThresholds(scriptThresholds map[string]stats.Thresholds) { - thresholds := make(map[string][]*stats.Threshold) +func (out *Output) SetThresholds(scriptThresholds map[string]metrics.Thresholds) { + thresholds := make(map[string][]*metrics.Threshold) for name, t := range scriptThresholds { thresholds[name] = append(thresholds[name], t.Thresholds...) } @@ -334,7 +338,7 @@ func useCloudTags(source *httpext.Trail) *httpext.Trail { dest := new(httpext.Trail) *dest = *source - dest.Tags = stats.IntoSampleTags(&newTags) + dest.Tags = metrics.IntoSampleTags(&newTags) dest.Samples = nil return dest @@ -343,7 +347,7 @@ func useCloudTags(source *httpext.Trail) *httpext.Trail { // AddMetricSamples receives a set of metric samples. This method is never // called concurrently, so it defers as much of the work as possible to the // asynchronous goroutines initialized in Start(). -func (out *Output) AddMetricSamples(sampleContainers []stats.SampleContainer) { +func (out *Output) AddMetricSamples(sampleContainers []metrics.SampleContainer) { select { case <-out.stopSendingMetrics: return @@ -375,7 +379,7 @@ func (out *Output) AddMetricSamples(sampleContainers []stats.SampleContainer) { } if sc.FullIteration { - values[metrics.IterationDurationName] = stats.D(sc.EndTime.Sub(sc.StartTime)) + values[metrics.IterationDurationName] = metrics.D(sc.EndTime.Sub(sc.StartTime)) values[metrics.IterationsName] = 1 } diff --git a/output/cloud/output_test.go b/output/cloud/output_test.go index 17637397b23..9643d72478d 100644 --- a/output/cloud/output_test.go +++ b/output/cloud/output_test.go @@ -50,10 +50,9 @@ import ( "go.k6.io/k6/lib/types" "go.k6.io/k6/metrics" "go.k6.io/k6/output" - "go.k6.io/k6/stats" ) -func tagEqual(expected, got *stats.SampleTags) bool { +func tagEqual(expected, got *metrics.SampleTags) bool { expectedMap := expected.CloneTags() gotMap := got.CloneTags() @@ -185,7 +184,7 @@ func runCloudOutputTestCase(t *testing.T, minSamples int) { JSONConfig: json.RawMessage(fmt.Sprintf(`{"host": "%s", "noCompress": true}`, tb.ServerHTTP.URL)), ScriptOptions: lib.Options{ Duration: types.NullDurationFrom(1 * time.Second), - SystemTags: &stats.DefaultSystemTagSet, + SystemTags: &metrics.DefaultSystemTagSet, }, ScriptPath: &url.URL{Path: "/script.js"}, }) @@ -210,10 +209,10 @@ func runCloudOutputTestCase(t *testing.T, minSamples int) { now := time.Now() tagMap := map[string]string{"test": "mest", "a": "b", "name": "name", "url": "url"} - tags := stats.IntoSampleTags(&tagMap) + tags := metrics.IntoSampleTags(&tagMap) expectedTagMap := tags.CloneTags() expectedTagMap["url"], _ = tags.Get("name") - expectedTags := stats.IntoSampleTags(&expectedTagMap) + expectedTags := metrics.IntoSampleTags(&expectedTagMap) expSamples := make(chan []Sample) defer close(expSamples) @@ -222,7 +221,7 @@ func runCloudOutputTestCase(t *testing.T, minSamples int) { rw.WriteHeader(http.StatusOK) // silence a test warning }) - out.AddMetricSamples([]stats.SampleContainer{stats.Sample{ + out.AddMetricSamples([]metrics.SampleContainer{metrics.Sample{ Time: now, Metric: builtinMetrics.VUs, Tags: tags, @@ -252,12 +251,12 @@ func runCloudOutputTestCase(t *testing.T, minSamples int) { Duration: 1500 * time.Millisecond, Tags: tags, } - out.AddMetricSamples([]stats.SampleContainer{&simpleTrail}) + out.AddMetricSamples([]metrics.SampleContainer{&simpleTrail}) expSamples <- []Sample{*NewSampleFromTrail(&simpleTrail)} smallSkew := 0.02 - trails := []stats.SampleContainer{} + trails := []metrics.SampleContainer{} durations := make([]time.Duration, len(trails)) for i := int64(0); i < out.config.AggregationMinSamples.Int64; i++ { similarTrail := skewTrail(r, simpleTrail, 1.0, 1.0+smallSkew) @@ -270,9 +269,9 @@ func runCloudOutputTestCase(t *testing.T, minSamples int) { checkAggrMetric := func(normal time.Duration, aggr AggregatedMetric) { assert.True(t, aggr.Min <= aggr.Avg) assert.True(t, aggr.Avg <= aggr.Max) - assert.InEpsilon(t, normal, stats.ToD(aggr.Min), smallSkew) - assert.InEpsilon(t, normal, stats.ToD(aggr.Avg), smallSkew) - assert.InEpsilon(t, normal, stats.ToD(aggr.Max), smallSkew) + assert.InEpsilon(t, normal, metrics.ToD(aggr.Min), smallSkew) + assert.InEpsilon(t, normal, metrics.ToD(aggr.Avg), smallSkew) + assert.InEpsilon(t, normal, metrics.ToD(aggr.Max), smallSkew) } outlierTrail := skewTrail(r, simpleTrail, 2.0+smallSkew, 3.0+smallSkew) @@ -330,14 +329,14 @@ func TestCloudOutputMaxPerPacket(t *testing.T) { JSONConfig: json.RawMessage(fmt.Sprintf(`{"host": "%s", "noCompress": true}`, tb.ServerHTTP.URL)), ScriptOptions: lib.Options{ Duration: types.NullDurationFrom(1 * time.Second), - SystemTags: &stats.DefaultSystemTagSet, + SystemTags: &metrics.DefaultSystemTagSet, }, ScriptPath: &url.URL{Path: "/script.js"}, }) require.NoError(t, err) require.NoError(t, err) now := time.Now() - tags := stats.IntoSampleTags(&map[string]string{"test": "mest", "a": "b"}) + tags := metrics.IntoSampleTags(&map[string]string{"test": "mest", "a": "b"}) gotTheLimit := false var m sync.Mutex @@ -357,14 +356,14 @@ func TestCloudOutputMaxPerPacket(t *testing.T) { require.NoError(t, out.Start()) - out.AddMetricSamples([]stats.SampleContainer{stats.Sample{ + out.AddMetricSamples([]metrics.SampleContainer{metrics.Sample{ Time: now, Metric: builtinMetrics.VUs, - Tags: stats.NewSampleTags(tags.CloneTags()), + Tags: metrics.NewSampleTags(tags.CloneTags()), Value: 1.0, }}) for j := time.Duration(1); j <= 200; j++ { - container := make([]stats.SampleContainer, 0, 500) + container := make([]metrics.SampleContainer, 0, 500) for i := time.Duration(1); i <= 50; i++ { container = append(container, &httpext.Trail{ Blocked: i % 200 * 100 * time.Millisecond, @@ -377,7 +376,7 @@ func TestCloudOutputMaxPerPacket(t *testing.T) { EndTime: now.Add(i * 100), ConnDuration: 500 * time.Millisecond, Duration: j * i * 1500 * time.Millisecond, - Tags: stats.NewSampleTags(tags.CloneTags()), + Tags: metrics.NewSampleTags(tags.CloneTags()), }) } out.AddMetricSamples(container) @@ -435,7 +434,7 @@ func testCloudOutputStopSendingMetric(t *testing.T, stopOnError bool) { }`, tb.ServerHTTP.URL, stopOnError)), ScriptOptions: lib.Options{ Duration: types.NullDurationFrom(1 * time.Second), - SystemTags: &stats.DefaultSystemTagSet, + SystemTags: &metrics.DefaultSystemTagSet, External: map[string]json.RawMessage{ "loadimpact": json.RawMessage(`{"name": "my-custom-name"}`), }, @@ -452,7 +451,7 @@ func testCloudOutputStopSendingMetric(t *testing.T, stopOnError bool) { } require.NoError(t, err) now := time.Now() - tags := stats.IntoSampleTags(&map[string]string{"test": "mest", "a": "b"}) + tags := metrics.IntoSampleTags(&map[string]string{"test": "mest", "a": "b"}) count := 1 max := 5 @@ -482,14 +481,14 @@ func testCloudOutputStopSendingMetric(t *testing.T, stopOnError bool) { require.NoError(t, out.Start()) - out.AddMetricSamples([]stats.SampleContainer{stats.Sample{ + out.AddMetricSamples([]metrics.SampleContainer{metrics.Sample{ Time: now, Metric: builtinMetrics.VUs, - Tags: stats.NewSampleTags(tags.CloneTags()), + Tags: metrics.NewSampleTags(tags.CloneTags()), Value: 1.0, }}) for j := time.Duration(1); j <= 200; j++ { - container := make([]stats.SampleContainer, 0, 500) + container := make([]metrics.SampleContainer, 0, 500) for i := time.Duration(1); i <= 50; i++ { container = append(container, &httpext.Trail{ Blocked: i % 200 * 100 * time.Millisecond, @@ -502,7 +501,7 @@ func testCloudOutputStopSendingMetric(t *testing.T, stopOnError bool) { EndTime: now.Add(i * 100), ConnDuration: 500 * time.Millisecond, Duration: j * i * 1500 * time.Millisecond, - Tags: stats.NewSampleTags(tags.CloneTags()), + Tags: metrics.NewSampleTags(tags.CloneTags()), }) } out.AddMetricSamples(container) @@ -522,10 +521,10 @@ func testCloudOutputStopSendingMetric(t *testing.T, stopOnError bool) { nBufferSamples := len(out.bufferSamples) nBufferHTTPTrails := len(out.bufferHTTPTrails) - out.AddMetricSamples([]stats.SampleContainer{stats.Sample{ + out.AddMetricSamples([]metrics.SampleContainer{metrics.Sample{ Time: now, Metric: builtinMetrics.VUs, - Tags: stats.NewSampleTags(tags.CloneTags()), + Tags: metrics.NewSampleTags(tags.CloneTags()), Value: 1.0, }}) if nBufferSamples != len(out.bufferSamples) || nBufferHTTPTrails != len(out.bufferHTTPTrails) { @@ -539,7 +538,7 @@ func TestCloudOutputRequireScriptName(t *testing.T) { Logger: testutils.NewLogger(t), ScriptOptions: lib.Options{ Duration: types.NullDurationFrom(1 * time.Second), - SystemTags: &stats.DefaultSystemTagSet, + SystemTags: &metrics.DefaultSystemTagSet, }, ScriptPath: &url.URL{Path: ""}, }) @@ -572,7 +571,7 @@ func TestCloudOutputAggregationPeriodZeroNoBlock(t *testing.T) { }`, tb.ServerHTTP.URL)), ScriptOptions: lib.Options{ Duration: types.NullDurationFrom(1 * time.Second), - SystemTags: &stats.DefaultSystemTagSet, + SystemTags: &metrics.DefaultSystemTagSet, }, ScriptPath: &url.URL{Path: "/script.js"}, }) @@ -627,7 +626,7 @@ func TestCloudOutputPushRefID(t *testing.T) { }`, tb.ServerHTTP.URL)), ScriptOptions: lib.Options{ Duration: types.NullDurationFrom(1 * time.Second), - SystemTags: &stats.DefaultSystemTagSet, + SystemTags: &metrics.DefaultSystemTagSet, }, ScriptPath: &url.URL{Path: "/script.js"}, }) @@ -638,9 +637,9 @@ func TestCloudOutputPushRefID(t *testing.T) { assert.Equal(t, "333", out.referenceID) now := time.Now() - tags := stats.IntoSampleTags(&map[string]string{"test": "mest", "a": "b"}) + tags := metrics.IntoSampleTags(&map[string]string{"test": "mest", "a": "b"}) - out.AddMetricSamples([]stats.SampleContainer{stats.Sample{ + out.AddMetricSamples([]metrics.SampleContainer{metrics.Sample{ Time: now, Metric: builtinMetrics.HTTPReqDuration, Tags: tags, @@ -691,7 +690,7 @@ func TestCloudOutputRecvIterLIAllIterations(t *testing.T) { }`, tb.ServerHTTP.URL)), ScriptOptions: lib.Options{ Duration: types.NullDurationFrom(1 * time.Second), - SystemTags: &stats.DefaultSystemTagSet, + SystemTags: &metrics.DefaultSystemTagSet, }, ScriptPath: &url.URL{Path: "path/to/script.js"}, }) @@ -735,7 +734,7 @@ func TestCloudOutputRecvIterLIAllIterations(t *testing.T) { FullIteration: true, StartTime: now.Add(-time.Minute), EndTime: now, - Samples: []stats.Sample{ + Samples: []metrics.Sample{ { Time: now, Metric: builtinMetrics.DataSent, @@ -754,7 +753,7 @@ func TestCloudOutputRecvIterLIAllIterations(t *testing.T) { }, } - out.AddMetricSamples([]stats.SampleContainer{&simpleNetTrail}) + out.AddMetricSamples([]metrics.SampleContainer{&simpleNetTrail}) require.NoError(t, out.Stop()) require.True(t, gotIterations) } @@ -799,7 +798,7 @@ func TestNewName(t *testing.T) { Logger: testutils.NewLogger(t), ScriptOptions: lib.Options{ Duration: types.NullDurationFrom(1 * time.Second), - SystemTags: &stats.DefaultSystemTagSet, + SystemTags: &metrics.DefaultSystemTagSet, }, ScriptPath: testCase.url, }) @@ -838,7 +837,7 @@ func TestPublishMetric(t *testing.T) { JSONConfig: json.RawMessage(fmt.Sprintf(`{"host": "%s", "noCompress": false}`, server.URL)), ScriptOptions: lib.Options{ Duration: types.NullDurationFrom(1 * time.Second), - SystemTags: &stats.DefaultSystemTagSet, + SystemTags: &metrics.DefaultSystemTagSet, }, ScriptPath: &url.URL{Path: "script.js"}, }) @@ -872,7 +871,7 @@ func TestNewOutputClientTimeout(t *testing.T) { JSONConfig: json.RawMessage(fmt.Sprintf(`{"host": "%s", "timeout": "2ms"}`, ts.URL)), ScriptOptions: lib.Options{ Duration: types.NullDurationFrom(1 * time.Second), - SystemTags: &stats.DefaultSystemTagSet, + SystemTags: &metrics.DefaultSystemTagSet, }, ScriptPath: &url.URL{Path: "script.js"}, }) diff --git a/output/csv/output.go b/output/csv/output.go index 1a3f754a0c0..bfba60fba28 100644 --- a/output/csv/output.go +++ b/output/csv/output.go @@ -33,8 +33,8 @@ import ( "github.com/sirupsen/logrus" + "go.k6.io/k6/metrics" "go.k6.io/k6/output" - "go.k6.io/k6/stats" ) // Output implements the lib.Output interface for saving to CSV files. @@ -200,7 +200,7 @@ func MakeHeader(tags []string) []string { } // SampleToRow converts sample into array of strings -func SampleToRow(sample *stats.Sample, resTags []string, ignoredTags []string, row []string) []string { +func SampleToRow(sample *metrics.Sample, resTags []string, ignoredTags []string, row []string) []string { row[0] = sample.Metric.Name row[1] = fmt.Sprintf("%d", sample.Time.Unix()) row[2] = fmt.Sprintf("%f", sample.Value) diff --git a/output/csv/output_test.go b/output/csv/output_test.go index 0a60bbf9bcf..d0fa3c13bcc 100644 --- a/output/csv/output_test.go +++ b/output/csv/output_test.go @@ -39,7 +39,6 @@ import ( "go.k6.io/k6/lib/testutils" "go.k6.io/k6/metrics" "go.k6.io/k6/output" - "go.k6.io/k6/stats" ) func TestMakeHeader(t *testing.T) { @@ -66,22 +65,22 @@ func TestMakeHeader(t *testing.T) { } func TestSampleToRow(t *testing.T) { - testMetric, err := metrics.NewRegistry().NewMetric("my_metric", stats.Gauge) + testMetric, err := metrics.NewRegistry().NewMetric("my_metric", metrics.Gauge) require.NoError(t, err) testData := []struct { testname string - sample *stats.Sample + sample *metrics.Sample resTags []string ignoredTags []string }{ { testname: "One res tag, one ignored tag, one extra tag", - sample: &stats.Sample{ + sample: &metrics.Sample{ Time: time.Unix(1562324644, 0), Metric: testMetric, Value: 1, - Tags: stats.NewSampleTags(map[string]string{ + Tags: metrics.NewSampleTags(map[string]string{ "tag1": "val1", "tag2": "val2", "tag3": "val3", @@ -92,11 +91,11 @@ func TestSampleToRow(t *testing.T) { }, { testname: "Two res tags, three extra tags", - sample: &stats.Sample{ + sample: &metrics.Sample{ Time: time.Unix(1562324644, 0), Metric: testMetric, Value: 1, - Tags: stats.NewSampleTags(map[string]string{ + Tags: metrics.NewSampleTags(map[string]string{ "tag1": "val1", "tag2": "val2", "tag3": "val3", @@ -109,11 +108,11 @@ func TestSampleToRow(t *testing.T) { }, { testname: "Two res tags, two ignored", - sample: &stats.Sample{ + sample: &metrics.Sample{ Time: time.Unix(1562324644, 0), Metric: testMetric, Value: 1, - Tags: stats.NewSampleTags(map[string]string{ + Tags: metrics.NewSampleTags(map[string]string{ "tag1": "val1", "tag2": "val2", "tag3": "val3", @@ -219,32 +218,32 @@ func readCompressedFile(fileName string, fs afero.Fs) string { func TestRun(t *testing.T) { t.Parallel() - testMetric, err := metrics.NewRegistry().NewMetric("my_metric", stats.Gauge) + testMetric, err := metrics.NewRegistry().NewMetric("my_metric", metrics.Gauge) require.NoError(t, err) testData := []struct { - samples []stats.SampleContainer + samples []metrics.SampleContainer fileName string fileReaderFunc func(fileName string, fs afero.Fs) string outputContent string }{ { - samples: []stats.SampleContainer{ - stats.Sample{ + samples: []metrics.SampleContainer{ + metrics.Sample{ Time: time.Unix(1562324643, 0), Metric: testMetric, Value: 1, - Tags: stats.NewSampleTags(map[string]string{ + Tags: metrics.NewSampleTags(map[string]string{ "check": "val1", "url": "val2", "error": "val3", }), }, - stats.Sample{ + metrics.Sample{ Time: time.Unix(1562324644, 0), Metric: testMetric, Value: 1, - Tags: stats.NewSampleTags(map[string]string{ + Tags: metrics.NewSampleTags(map[string]string{ "check": "val1", "url": "val2", "error": "val3", @@ -257,22 +256,22 @@ func TestRun(t *testing.T) { outputContent: "metric_name,timestamp,metric_value,check,error,extra_tags\n" + "my_metric,1562324643,1.000000,val1,val3,url=val2\n" + "my_metric,1562324644,1.000000,val1,val3,tag4=val4&url=val2\n", }, { - samples: []stats.SampleContainer{ - stats.Sample{ + samples: []metrics.SampleContainer{ + metrics.Sample{ Time: time.Unix(1562324643, 0), Metric: testMetric, Value: 1, - Tags: stats.NewSampleTags(map[string]string{ + Tags: metrics.NewSampleTags(map[string]string{ "check": "val1", "url": "val2", "error": "val3", }), }, - stats.Sample{ + metrics.Sample{ Time: time.Unix(1562324644, 0), Metric: testMetric, Value: 1, - Tags: stats.NewSampleTags(map[string]string{ + Tags: metrics.NewSampleTags(map[string]string{ "check": "val1", "url": "val2", "error": "val3", @@ -293,7 +292,7 @@ func TestRun(t *testing.T) { FS: mem, ConfigArgument: data.fileName, ScriptOptions: lib.Options{ - SystemTags: stats.NewSystemTagSet(stats.TagError | stats.TagCheck), + SystemTags: metrics.NewSystemTagSet(metrics.TagError | metrics.TagCheck), }, }) require.NoError(t, err) diff --git a/output/helpers.go b/output/helpers.go index 52376c883df..91d46bd69e6 100644 --- a/output/helpers.go +++ b/output/helpers.go @@ -25,7 +25,7 @@ import ( "sync" "time" - "go.k6.io/k6/stats" + "go.k6.io/k6/metrics" ) // SampleBuffer is a simple thread-safe buffer for metric samples. It should be @@ -34,12 +34,12 @@ import ( // and we don't want to block the Engine in the meantime. type SampleBuffer struct { sync.Mutex - buffer []stats.SampleContainer + buffer []metrics.SampleContainer maxLen int } // AddMetricSamples adds the given metric samples to the internal buffer. -func (sc *SampleBuffer) AddMetricSamples(samples []stats.SampleContainer) { +func (sc *SampleBuffer) AddMetricSamples(samples []metrics.SampleContainer) { if len(samples) == 0 { return } @@ -51,7 +51,7 @@ func (sc *SampleBuffer) AddMetricSamples(samples []stats.SampleContainer) { // GetBufferedSamples returns the currently buffered metric samples and makes a // new internal buffer with some hopefully realistic size. If the internal // buffer is empty, it will return nil. -func (sc *SampleBuffer) GetBufferedSamples() []stats.SampleContainer { +func (sc *SampleBuffer) GetBufferedSamples() []metrics.SampleContainer { sc.Lock() defer sc.Unlock() @@ -64,7 +64,7 @@ func (sc *SampleBuffer) GetBufferedSamples() []stats.SampleContainer { } // Make the new buffer halfway between the previously allocated size and the // maximum buffer size we've seen so far, to hopefully reduce copying a bit. - sc.buffer = make([]stats.SampleContainer, 0, (bufferedLen+sc.maxLen)/2) + sc.buffer = make([]metrics.SampleContainer, 0, (bufferedLen+sc.maxLen)/2) return buffered } diff --git a/output/helpers_test.go b/output/helpers_test.go index 0200c5f5769..626ec7e7600 100644 --- a/output/helpers_test.go +++ b/output/helpers_test.go @@ -30,41 +30,40 @@ import ( "github.com/stretchr/testify/require" "go.k6.io/k6/metrics" - "go.k6.io/k6/stats" ) func TestSampleBufferBasics(t *testing.T) { t.Parallel() registry := metrics.NewRegistry() - metric, err := registry.NewMetric("my_metric", stats.Rate) + metric, err := registry.NewMetric("my_metric", metrics.Rate) require.NoError(t, err) - single := stats.Sample{ + single := metrics.Sample{ Time: time.Now(), Metric: metric, Value: float64(123), - Tags: stats.NewSampleTags(map[string]string{"tag1": "val1"}), + Tags: metrics.NewSampleTags(map[string]string{"tag1": "val1"}), } - connected := stats.ConnectedSamples{Samples: []stats.Sample{single, single}, Time: single.Time} + connected := metrics.ConnectedSamples{Samples: []metrics.Sample{single, single}, Time: single.Time} buffer := SampleBuffer{} assert.Empty(t, buffer.GetBufferedSamples()) - buffer.AddMetricSamples([]stats.SampleContainer{single, single}) - buffer.AddMetricSamples([]stats.SampleContainer{single, connected, single}) - assert.Equal(t, []stats.SampleContainer{single, single, single, connected, single}, buffer.GetBufferedSamples()) + buffer.AddMetricSamples([]metrics.SampleContainer{single, single}) + buffer.AddMetricSamples([]metrics.SampleContainer{single, connected, single}) + assert.Equal(t, []metrics.SampleContainer{single, single, single, connected, single}, buffer.GetBufferedSamples()) assert.Empty(t, buffer.GetBufferedSamples()) // Verify some internals assert.Equal(t, cap(buffer.buffer), 5) - buffer.AddMetricSamples([]stats.SampleContainer{single, connected}) + buffer.AddMetricSamples([]metrics.SampleContainer{single, connected}) buffer.AddMetricSamples(nil) - buffer.AddMetricSamples([]stats.SampleContainer{}) - buffer.AddMetricSamples([]stats.SampleContainer{single}) - assert.Equal(t, []stats.SampleContainer{single, connected, single}, buffer.GetBufferedSamples()) + buffer.AddMetricSamples([]metrics.SampleContainer{}) + buffer.AddMetricSamples([]metrics.SampleContainer{single}) + assert.Equal(t, []metrics.SampleContainer{single, connected, single}, buffer.GetBufferedSamples()) assert.Equal(t, cap(buffer.buffer), 4) - buffer.AddMetricSamples([]stats.SampleContainer{single}) - assert.Equal(t, []stats.SampleContainer{single}, buffer.GetBufferedSamples()) + buffer.AddMetricSamples([]metrics.SampleContainer{single}) + assert.Equal(t, []metrics.SampleContainer{single}, buffer.GetBufferedSamples()) assert.Equal(t, cap(buffer.buffer), 3) assert.Empty(t, buffer.GetBufferedSamples()) } @@ -77,7 +76,7 @@ func TestSampleBufferConcurrently(t *testing.T) { t.Logf("Random source seeded with %d\n", seed) registry := metrics.NewRegistry() - metric, err := registry.NewMetric("my_metric", stats.Gauge) + metric, err := registry.NewMetric("my_metric", metrics.Gauge) require.NoError(t, err) producersCount := 50 + r.Intn(50) @@ -88,11 +87,11 @@ func TestSampleBufferConcurrently(t *testing.T) { wg := make(chan struct{}) fillBuffer := func() { for i := 0; i < sampleCount; i++ { - buffer.AddMetricSamples([]stats.SampleContainer{stats.Sample{ + buffer.AddMetricSamples([]metrics.SampleContainer{metrics.Sample{ Time: time.Unix(1562324644, 0), Metric: metric, Value: float64(i), - Tags: stats.NewSampleTags(map[string]string{"tag1": "val1"}), + Tags: metrics.NewSampleTags(map[string]string{"tag1": "val1"}), }}) time.Sleep(time.Duration(i*sleepModifier) * time.Microsecond) } @@ -105,7 +104,7 @@ func TestSampleBufferConcurrently(t *testing.T) { timer := time.NewTicker(5 * time.Millisecond) timeout := time.After(5 * time.Second) defer timer.Stop() - readSamples := make([]stats.SampleContainer, 0, sampleCount*producersCount) + readSamples := make([]metrics.SampleContainer, 0, sampleCount*producersCount) finishedProducers := 0 loop: for { diff --git a/output/influxdb/bench_test.go b/output/influxdb/bench_test.go index 2b8a20552d1..99093df09b4 100644 --- a/output/influxdb/bench_test.go +++ b/output/influxdb/bench_test.go @@ -29,11 +29,10 @@ import ( "github.com/stretchr/testify/require" "go.k6.io/k6/metrics" - "go.k6.io/k6/stats" ) func benchmarkInfluxdb(b *testing.B, t time.Duration) { - metric, err := metrics.NewRegistry().NewMetric("test_gauge", stats.Gauge) + metric, err := metrics.NewRegistry().NewMetric("test_gauge", metrics.Gauge) require.NoError(b, err) testOutputCycle(b, func(rw http.ResponseWriter, r *http.Request) { @@ -49,12 +48,12 @@ func benchmarkInfluxdb(b *testing.B, t time.Duration) { b = tb.(*testing.B) b.ResetTimer() - samples := make(stats.Samples, 10) + samples := make(metrics.Samples, 10) for i := 0; i < len(samples); i++ { - samples[i] = stats.Sample{ + samples[i] = metrics.Sample{ Metric: metric, Time: time.Now(), - Tags: stats.NewSampleTags(map[string]string{ + Tags: metrics.NewSampleTags(map[string]string{ "something": "else", "VU": "21", "else": "something", @@ -65,7 +64,7 @@ func benchmarkInfluxdb(b *testing.B, t time.Duration) { b.ResetTimer() for i := 0; i < b.N; i++ { - c.AddMetricSamples([]stats.SampleContainer{samples}) + c.AddMetricSamples([]metrics.SampleContainer{samples}) time.Sleep(time.Nanosecond * 20) } }) diff --git a/output/influxdb/output.go b/output/influxdb/output.go index f322933c69f..8b71111c1fc 100644 --- a/output/influxdb/output.go +++ b/output/influxdb/output.go @@ -31,8 +31,8 @@ import ( client "github.com/influxdata/influxdb1-client/v2" "github.com/sirupsen/logrus" + "go.k6.io/k6/metrics" "go.k6.io/k6/output" - "go.k6.io/k6/stats" ) // FieldKind defines Enum for tag-to-field type conversion @@ -124,7 +124,7 @@ func (o *Output) extractTagsToValues(tags map[string]string, values map[string]i return values } -func (o *Output) batchFromSamples(containers []stats.SampleContainer) (client.BatchPoints, error) { +func (o *Output) batchFromSamples(containers []metrics.SampleContainer) (client.BatchPoints, error) { batch, err := client.NewBatchPoints(o.BatchConf) if err != nil { return nil, fmt.Errorf("couldn't make a batch: %w", err) @@ -134,7 +134,7 @@ func (o *Output) batchFromSamples(containers []stats.SampleContainer) (client.Ba tags map[string]string values map[string]interface{} } - cache := map[*stats.SampleTags]cacheItem{} + cache := map[*metrics.SampleTags]cacheItem{} for _, container := range containers { samples := container.GetSamples() for _, sample := range samples { diff --git a/output/influxdb/output_test.go b/output/influxdb/output_test.go index 6708cd7ccfe..830e85790ee 100644 --- a/output/influxdb/output_test.go +++ b/output/influxdb/output_test.go @@ -38,7 +38,6 @@ import ( "go.k6.io/k6/lib/testutils" "go.k6.io/k6/metrics" "go.k6.io/k6/output" - "go.k6.io/k6/stats" ) func TestBadConcurrentWrites(t *testing.T) { @@ -109,7 +108,7 @@ func testOutputCycle(t testing.TB, handler http.HandlerFunc, body func(testing.T func TestOutput(t *testing.T) { t.Parallel() - metric, err := metrics.NewRegistry().NewMetric("test_gauge", stats.Gauge) + metric, err := metrics.NewRegistry().NewMetric("test_gauge", metrics.Gauge) require.NoError(t, err) var samplesRead int @@ -132,12 +131,12 @@ func TestOutput(t *testing.T) { rw.WriteHeader(204) }, func(tb testing.TB, c *Output) { - samples := make(stats.Samples, 10) + samples := make(metrics.Samples, 10) for i := 0; i < len(samples); i++ { - samples[i] = stats.Sample{ + samples[i] = metrics.Sample{ Metric: metric, Time: time.Now(), - Tags: stats.NewSampleTags(map[string]string{ + Tags: metrics.NewSampleTags(map[string]string{ "something": "else", "VU": "21", "else": "something", @@ -145,8 +144,8 @@ func TestOutput(t *testing.T) { Value: 2.0, } } - c.AddMetricSamples([]stats.SampleContainer{samples}) - c.AddMetricSamples([]stats.SampleContainer{samples}) + c.AddMetricSamples([]metrics.SampleContainer{samples}) + c.AddMetricSamples([]metrics.SampleContainer{samples}) }) } @@ -176,7 +175,7 @@ func TestOutputFlushMetricsConcurrency(t *testing.T) { ts.Close() }() - metric, err := metrics.NewRegistry().NewMetric("test_gauge", stats.Gauge) + metric, err := metrics.NewRegistry().NewMetric("test_gauge", metrics.Gauge) require.NoError(t, err) o, err := newOutput(output.Params{ @@ -190,8 +189,8 @@ func TestOutputFlushMetricsConcurrency(t *testing.T) { case o.semaphoreCh <- struct{}{}: <-o.semaphoreCh wg.Add(1) - o.AddMetricSamples([]stats.SampleContainer{stats.Samples{ - stats.Sample{ + o.AddMetricSamples([]metrics.SampleContainer{metrics.Samples{ + metrics.Sample{ Metric: metric, Value: 2.0, }, diff --git a/output/json/json.go b/output/json/json.go index b0f190d93e9..928056ec9c5 100644 --- a/output/json/json.go +++ b/output/json/json.go @@ -33,8 +33,8 @@ import ( "github.com/sirupsen/logrus" + "go.k6.io/k6/metrics" "go.k6.io/k6/output" - "go.k6.io/k6/stats" ) // TODO: add option for emitting proper JSON files (https://github.com/k6io/k6/issues/737) @@ -52,7 +52,7 @@ type Output struct { out io.Writer closeFn func() error seenMetrics map[string]struct{} - thresholds map[string][]*stats.Threshold + thresholds map[string][]*metrics.Threshold } // New returns a new JSON output. @@ -131,8 +131,8 @@ func (o *Output) Stop() error { } // SetThresholds receives the thresholds before the output is Start()-ed. -func (o *Output) SetThresholds(thresholds map[string]stats.Thresholds) { - ths := make(map[string][]*stats.Threshold) +func (o *Output) SetThresholds(thresholds map[string]metrics.Thresholds) { + ths := make(map[string][]*metrics.Threshold) for name, t := range thresholds { ths[name] = append(ths[name], t.Thresholds...) } @@ -165,7 +165,7 @@ func (o *Output) flushMetrics() { } } -func (o *Output) handleMetric(m *stats.Metric, jw *jwriter.Writer) { +func (o *Output) handleMetric(m *metrics.Metric, jw *jwriter.Writer) { if _, ok := o.seenMetrics[m.Name]; ok { return } diff --git a/output/json/json_easyjson.go b/output/json/json_easyjson.go index 85210d84a77..e35f1b7452f 100644 --- a/output/json/json_easyjson.go +++ b/output/json/json_easyjson.go @@ -7,7 +7,7 @@ import ( easyjson "github.com/mailru/easyjson" jlexer "github.com/mailru/easyjson/jlexer" jwriter "github.com/mailru/easyjson/jwriter" - stats "go.k6.io/k6/stats" + metrics "go.k6.io/k6/metrics" time "time" ) @@ -86,9 +86,9 @@ func (v *sampleEnvelope) UnmarshalEasyJSON(l *jlexer.Lexer) { easyjson42239ddeDecodeGoK6IoK6OutputJson(l, v) } func easyjson42239ddeDecode(in *jlexer.Lexer, out *struct { - Time time.Time `json:"time"` - Value float64 `json:"value"` - Tags *stats.SampleTags `json:"tags"` + Time time.Time `json:"time"` + Value float64 `json:"value"` + Tags *metrics.SampleTags `json:"tags"` }) { isTopLevel := in.IsStart() if in.IsNull() { @@ -120,7 +120,7 @@ func easyjson42239ddeDecode(in *jlexer.Lexer, out *struct { out.Tags = nil } else { if out.Tags == nil { - out.Tags = new(stats.SampleTags) + out.Tags = new(metrics.SampleTags) } if data := in.Raw(); in.Ok() { in.AddError((*out.Tags).UnmarshalJSON(data)) @@ -137,9 +137,9 @@ func easyjson42239ddeDecode(in *jlexer.Lexer, out *struct { } } func easyjson42239ddeEncode(out *jwriter.Writer, in struct { - Time time.Time `json:"time"` - Value float64 `json:"value"` - Tags *stats.SampleTags `json:"tags"` + Time time.Time `json:"time"` + Value float64 `json:"value"` + Tags *metrics.SampleTags `json:"tags"` }) { out.RawByte('{') first := true @@ -192,9 +192,9 @@ func easyjson42239ddeDecodeGoK6IoK6OutputJson1(in *jlexer.Lexer, out *metricEnve out.Data = nil } else { if out.Data == nil { - out.Data = new(stats.Metric) + out.Data = new(metrics.Metric) } - easyjson42239ddeDecodeGoK6IoK6Stats(in, out.Data) + easyjson42239ddeDecodeGoK6IoK6Metrics(in, out.Data) } case "metric": out.Metric = string(in.String()) @@ -223,7 +223,7 @@ func easyjson42239ddeEncodeGoK6IoK6OutputJson1(out *jwriter.Writer, in metricEnv if in.Data == nil { out.RawString("null") } else { - easyjson42239ddeEncodeGoK6IoK6Stats(out, *in.Data) + easyjson42239ddeEncodeGoK6IoK6Metrics(out, *in.Data) } } { @@ -243,7 +243,7 @@ func (v metricEnvelope) MarshalEasyJSON(w *jwriter.Writer) { func (v *metricEnvelope) UnmarshalEasyJSON(l *jlexer.Lexer) { easyjson42239ddeDecodeGoK6IoK6OutputJson1(l, v) } -func easyjson42239ddeDecodeGoK6IoK6Stats(in *jlexer.Lexer, out *stats.Metric) { +func easyjson42239ddeDecodeGoK6IoK6Metrics(in *jlexer.Lexer, out *metrics.Metric) { isTopLevel := in.IsStart() if in.IsNull() { if isTopLevel { @@ -288,23 +288,23 @@ func easyjson42239ddeDecodeGoK6IoK6Stats(in *jlexer.Lexer, out *stats.Metric) { in.Delim('[') if out.Submetrics == nil { if !in.IsDelim(']') { - out.Submetrics = make([]*stats.Submetric, 0, 8) + out.Submetrics = make([]*metrics.Submetric, 0, 8) } else { - out.Submetrics = []*stats.Submetric{} + out.Submetrics = []*metrics.Submetric{} } } else { out.Submetrics = (out.Submetrics)[:0] } for !in.IsDelim(']') { - var v1 *stats.Submetric + var v1 *metrics.Submetric if in.IsNull() { in.Skip() v1 = nil } else { if v1 == nil { - v1 = new(stats.Submetric) + v1 = new(metrics.Submetric) } - easyjson42239ddeDecodeGoK6IoK6Stats1(in, v1) + easyjson42239ddeDecodeGoK6IoK6Metrics1(in, v1) } out.Submetrics = append(out.Submetrics, v1) in.WantComma() @@ -321,7 +321,7 @@ func easyjson42239ddeDecodeGoK6IoK6Stats(in *jlexer.Lexer, out *stats.Metric) { in.Consumed() } } -func easyjson42239ddeEncodeGoK6IoK6Stats(out *jwriter.Writer, in stats.Metric) { +func easyjson42239ddeEncodeGoK6IoK6Metrics(out *jwriter.Writer, in metrics.Metric) { out.RawByte('{') first := true _ = first @@ -364,7 +364,7 @@ func easyjson42239ddeEncodeGoK6IoK6Stats(out *jwriter.Writer, in stats.Metric) { if v3 == nil { out.RawString("null") } else { - easyjson42239ddeEncodeGoK6IoK6Stats1(out, *v3) + easyjson42239ddeEncodeGoK6IoK6Metrics1(out, *v3) } } out.RawByte(']') @@ -372,7 +372,7 @@ func easyjson42239ddeEncodeGoK6IoK6Stats(out *jwriter.Writer, in stats.Metric) { } out.RawByte('}') } -func easyjson42239ddeDecodeGoK6IoK6Stats1(in *jlexer.Lexer, out *stats.Submetric) { +func easyjson42239ddeDecodeGoK6IoK6Metrics1(in *jlexer.Lexer, out *metrics.Submetric) { isTopLevel := in.IsStart() if in.IsNull() { if isTopLevel { @@ -401,7 +401,7 @@ func easyjson42239ddeDecodeGoK6IoK6Stats1(in *jlexer.Lexer, out *stats.Submetric out.Tags = nil } else { if out.Tags == nil { - out.Tags = new(stats.SampleTags) + out.Tags = new(metrics.SampleTags) } if data := in.Raw(); in.Ok() { in.AddError((*out.Tags).UnmarshalJSON(data)) @@ -417,7 +417,7 @@ func easyjson42239ddeDecodeGoK6IoK6Stats1(in *jlexer.Lexer, out *stats.Submetric in.Consumed() } } -func easyjson42239ddeEncodeGoK6IoK6Stats1(out *jwriter.Writer, in stats.Submetric) { +func easyjson42239ddeEncodeGoK6IoK6Metrics1(out *jwriter.Writer, in metrics.Submetric) { out.RawByte('{') first := true _ = first diff --git a/output/json/json_test.go b/output/json/json_test.go index 49da4037740..af0ca08f20b 100644 --- a/output/json/json_test.go +++ b/output/json/json_test.go @@ -35,7 +35,6 @@ import ( "go.k6.io/k6/lib/testutils" "go.k6.io/k6/metrics" "go.k6.io/k6/output" - "go.k6.io/k6/stats" ) func getValidator(t testing.TB, expected []string) func(io.Reader) { @@ -55,28 +54,29 @@ func getValidator(t testing.TB, expected []string) func(io.Reader) { } } -func generateTestMetricSamples(t testing.TB) ([]stats.SampleContainer, func(io.Reader)) { +func generateTestMetricSamples(t testing.TB) ([]metrics.SampleContainer, func(io.Reader)) { registry := metrics.NewRegistry() - metric1, err := registry.NewMetric("my_metric1", stats.Gauge) + metric1, err := registry.NewMetric("my_metric1", metrics.Gauge) require.NoError(t, err) - metric2, err := registry.NewMetric("my_metric2", stats.Counter, stats.Data) + metric2, err := registry.NewMetric("my_metric2", metrics.Counter, metrics.Data) require.NoError(t, err) time1 := time.Date(2021, time.February, 24, 13, 37, 10, 0, time.UTC) time2 := time1.Add(10 * time.Second) time3 := time2.Add(10 * time.Second) - connTags := stats.NewSampleTags(map[string]string{"key": "val"}) - samples := []stats.SampleContainer{ - stats.Sample{Time: time1, Metric: metric1, Value: float64(1), Tags: stats.NewSampleTags(map[string]string{"tag1": "val1"})}, - stats.Sample{Time: time1, Metric: metric1, Value: float64(2), Tags: stats.NewSampleTags(map[string]string{"tag2": "val2"})}, - stats.ConnectedSamples{Samples: []stats.Sample{ + connTags := metrics.NewSampleTags(map[string]string{"key": "val"}) + + samples := []metrics.SampleContainer{ + metrics.Sample{Time: time1, Metric: metric1, Value: float64(1), Tags: metrics.NewSampleTags(map[string]string{"tag1": "val1"})}, + metrics.Sample{Time: time1, Metric: metric1, Value: float64(2), Tags: metrics.NewSampleTags(map[string]string{"tag2": "val2"})}, + metrics.ConnectedSamples{Samples: []metrics.Sample{ {Time: time2, Metric: metric2, Value: float64(3), Tags: connTags}, {Time: time2, Metric: metric1, Value: float64(4), Tags: connTags}, }, Time: time2, Tags: connTags}, - stats.Sample{Time: time3, Metric: metric2, Value: float64(5), Tags: stats.NewSampleTags(map[string]string{"tag3": "val3"})}, + metrics.Sample{Time: time3, Metric: metric2, Value: float64(5), Tags: metrics.NewSampleTags(map[string]string{"tag3": "val3"})}, } expected := []string{ `{"type":"Metric","data":{"name":"my_metric1","type":"gauge","contains":"default","tainted":null,"thresholds":["rate<0.01","p(99)<250"],"submetrics":null},"metric":"my_metric1"}`, @@ -186,15 +186,15 @@ func TestJsonOutputFileGzipped(t *testing.T) { func TestWrapSampleWithSamplePointer(t *testing.T) { t.Parallel() - out := wrapSample(stats.Sample{ - Metric: &stats.Metric{}, + out := wrapSample(metrics.Sample{ + Metric: &metrics.Metric{}, }) assert.NotEqual(t, out, (*sampleEnvelope)(nil)) } func TestWrapMetricWithMetricPointer(t *testing.T) { t.Parallel() - out := wrapMetric(&stats.Metric{}) + out := wrapMetric(&metrics.Metric{}) assert.NotEqual(t, out, (*metricEnvelope)(nil)) } @@ -204,7 +204,7 @@ func setThresholds(t *testing.T, out output.Output) { jout, ok := out.(*Output) require.True(t, ok) - ts := stats.NewThresholds([]string{"rate<0.01", "p(99)<250"}) + ts := metrics.NewThresholds([]string{"rate<0.01", "p(99)<250"}) - jout.SetThresholds(map[string]stats.Thresholds{"my_metric1": ts}) + jout.SetThresholds(map[string]metrics.Thresholds{"my_metric1": ts}) } diff --git a/output/json/wrapper.go b/output/json/wrapper.go index 61fa649c90c..3410ea9b00a 100644 --- a/output/json/wrapper.go +++ b/output/json/wrapper.go @@ -23,7 +23,7 @@ package json import ( "time" - "go.k6.io/k6/stats" + "go.k6.io/k6/metrics" ) //go:generate easyjson -pkg -no_std_marshalers -gen_build_flags -mod=mod . @@ -34,14 +34,14 @@ type sampleEnvelope struct { Data struct { Time time.Time `json:"time"` Value float64 `json:"value"` - Tags *stats.SampleTags `json:"tags"` + Tags *metrics.SampleTags `json:"tags"` } `json:"data"` Metric string `json:"metric"` } // wrapSample is used to package a metric sample in a way that's nice to export // to JSON. -func wrapSample(sample stats.Sample) sampleEnvelope { +func wrapSample(sample metrics.Sample) sampleEnvelope { s := sampleEnvelope{ Type: "Point", Metric: sample.Metric.Name, @@ -55,11 +55,11 @@ func wrapSample(sample stats.Sample) sampleEnvelope { //easyjson:json type metricEnvelope struct { Type string `json:"type"` - Data *stats.Metric `json:"data"` + Data *metrics.Metric `json:"data"` Metric string `json:"metric"` } -func wrapMetric(metric *stats.Metric) metricEnvelope { +func wrapMetric(metric *metrics.Metric) metricEnvelope { return metricEnvelope{ Type: "Metric", Metric: metric.Name, diff --git a/output/manager.go b/output/manager.go index fdb88743e19..38d72e53b78 100644 --- a/output/manager.go +++ b/output/manager.go @@ -3,7 +3,7 @@ package output import ( "github.com/sirupsen/logrus" "go.k6.io/k6/lib" - "go.k6.io/k6/stats" + "go.k6.io/k6/metrics" ) // Manager can be used to manage multiple outputs at the same time. @@ -70,7 +70,7 @@ func (om *Manager) SetRunStatus(status lib.RunStatus) { // current Engine. It needs to be replaced with the full metric pump. // // TODO: refactor -func (om *Manager) AddMetricSamples(sampleContainers []stats.SampleContainer) { +func (om *Manager) AddMetricSamples(sampleContainers []metrics.SampleContainer) { if len(sampleContainers) == 0 { return } diff --git a/output/statsd/config.go b/output/statsd/config.go index e7f2a8b3bf1..cff9dabd449 100644 --- a/output/statsd/config.go +++ b/output/statsd/config.go @@ -28,7 +28,7 @@ import ( "gopkg.in/guregu/null.v3" "go.k6.io/k6/lib/types" - "go.k6.io/k6/stats" + "go.k6.io/k6/metrics" ) // config defines the StatsD configuration. @@ -37,11 +37,11 @@ type config struct { BufferSize null.Int `json:"bufferSize,omitempty" envconfig:"K6_STATSD_BUFFER_SIZE"` Namespace null.String `json:"namespace,omitempty" envconfig:"K6_STATSD_NAMESPACE"` PushInterval types.NullDuration `json:"pushInterval,omitempty" envconfig:"K6_STATSD_PUSH_INTERVAL"` - TagBlocklist stats.TagSet `json:"tagBlocklist,omitempty" envconfig:"K6_STATSD_TAG_BLOCKLIST"` + TagBlocklist metrics.TagSet `json:"tagBlocklist,omitempty" envconfig:"K6_STATSD_TAG_BLOCKLIST"` EnableTags null.Bool `json:"enableTags,omitempty" envconfig:"K6_STATSD_ENABLE_TAGS"` } -func processTags(t stats.TagSet, tags map[string]string) []string { +func processTags(t metrics.TagSet, tags map[string]string) []string { var res []string for key, value := range tags { if value != "" && !t[key] { @@ -82,7 +82,7 @@ func newConfig() config { BufferSize: null.NewInt(20, false), Namespace: null.NewString("k6.", false), PushInterval: types.NewNullDuration(1*time.Second, false), - TagBlocklist: (stats.TagVU | stats.TagIter | stats.TagURL).Map(), + TagBlocklist: (metrics.TagVU | metrics.TagIter | metrics.TagURL).Map(), EnableTags: null.NewBool(false, false), } } diff --git a/output/statsd/output.go b/output/statsd/output.go index d21fd4c460f..10e6b097cf9 100644 --- a/output/statsd/output.go +++ b/output/statsd/output.go @@ -27,8 +27,8 @@ import ( "github.com/DataDog/datadog-go/statsd" "github.com/sirupsen/logrus" + "go.k6.io/k6/metrics" "go.k6.io/k6/output" - "go.k6.io/k6/stats" ) // New creates a new statsd connector client @@ -63,20 +63,20 @@ type Output struct { client *statsd.Client } -func (o *Output) dispatch(entry stats.Sample) error { +func (o *Output) dispatch(entry metrics.Sample) error { var tagList []string if o.config.EnableTags.Bool { tagList = processTags(o.config.TagBlocklist, entry.Tags.CloneTags()) } switch entry.Metric.Type { - case stats.Counter: + case metrics.Counter: return o.client.Count(entry.Metric.Name, int64(entry.Value), tagList, 1) - case stats.Trend: + case metrics.Trend: return o.client.TimeInMilliseconds(entry.Metric.Name, entry.Value, tagList, 1) - case stats.Gauge: + case metrics.Gauge: return o.client.Gauge(entry.Metric.Name, entry.Value, tagList, 1) - case stats.Rate: + case metrics.Rate: if check, ok := entry.Tags.Get("check"); ok { return o.client.Count( checkToString(check, entry.Value), diff --git a/output/statsd/output_test.go b/output/statsd/output_test.go index 3b3fea75cfa..2b73855fe53 100644 --- a/output/statsd/output_test.go +++ b/output/statsd/output_test.go @@ -33,8 +33,8 @@ import ( "go.k6.io/k6/lib/testutils" "go.k6.io/k6/lib/types" + "go.k6.io/k6/metrics" "go.k6.io/k6/output" - "go.k6.io/k6/stats" ) func getOutput( @@ -55,14 +55,14 @@ func getOutput( func TestStatsdOutput(t *testing.T) { t.Parallel() baseTest(t, getOutput, - func(t *testing.T, _ []stats.SampleContainer, expectedOutput, output string) { + func(t *testing.T, _ []metrics.SampleContainer, expectedOutput, output string) { assert.Equal(t, expectedOutput, output) }) } func TestStatsdEnabledTags(t *testing.T) { t.Parallel() - tagMap := stats.TagSet{"tag1": true, "tag2": true} + tagMap := metrics.TagSet{"tag1": true, "tag2": true} baseTest(t, func( logger logrus.FieldLogger, addr, namespace null.String, bufferSize null.Int, pushInterval types.NullDuration, @@ -79,7 +79,7 @@ func TestStatsdEnabledTags(t *testing.T) { "enableTags": true }`, addr.String, namespace.String, bufferSize.Int64, pushInterval.Duration.String())), }) - }, func(t *testing.T, containers []stats.SampleContainer, expectedOutput, output string) { + }, func(t *testing.T, containers []metrics.SampleContainer, expectedOutput, output string) { outputLines := strings.Split(output, "\n") expectedOutputLines := strings.Split(expectedOutput, "\n") var lines int diff --git a/output/statsd/test_helper.go b/output/statsd/test_helper.go index 3e1cf72e064..2cbd763ea4b 100644 --- a/output/statsd/test_helper.go +++ b/output/statsd/test_helper.go @@ -32,7 +32,6 @@ import ( "go.k6.io/k6/lib/testutils" "go.k6.io/k6/lib/types" "go.k6.io/k6/metrics" - "go.k6.io/k6/stats" ) type getOutputFn func( @@ -45,7 +44,7 @@ type getOutputFn func( //nolint:funlen func baseTest(t *testing.T, getOutput getOutputFn, - checkResult func(t *testing.T, samples []stats.SampleContainer, expectedOutput, output string), + checkResult func(t *testing.T, samples []metrics.SampleContainer, expectedOutput, output string), ) { t.Helper() testNamespace := "testing.things." // to be dynamic @@ -86,31 +85,31 @@ func baseTest(t *testing.T, defer func() { require.NoError(t, collector.Stop()) }() - newSample := func(m *stats.Metric, value float64, tags map[string]string) stats.Sample { - return stats.Sample{ + newSample := func(m *metrics.Metric, value float64, tags map[string]string) metrics.Sample { + return metrics.Sample{ Time: time.Now(), - Metric: m, Value: value, Tags: stats.IntoSampleTags(&tags), + Metric: m, Value: value, Tags: metrics.IntoSampleTags(&tags), } } registry := metrics.NewRegistry() - myCounter, err := registry.NewMetric("my_counter", stats.Counter) + myCounter, err := registry.NewMetric("my_counter", metrics.Counter) require.NoError(t, err) - myGauge, err := registry.NewMetric("my_gauge", stats.Gauge) + myGauge, err := registry.NewMetric("my_gauge", metrics.Gauge) require.NoError(t, err) - myTrend, err := registry.NewMetric("my_trend", stats.Trend) + myTrend, err := registry.NewMetric("my_trend", metrics.Trend) require.NoError(t, err) - myRate, err := registry.NewMetric("my_rate", stats.Rate) + myRate, err := registry.NewMetric("my_rate", metrics.Rate) require.NoError(t, err) - myCheck, err := registry.NewMetric("my_check", stats.Rate) + myCheck, err := registry.NewMetric("my_check", metrics.Rate) require.NoError(t, err) testMatrix := []struct { - input []stats.SampleContainer + input []metrics.SampleContainer output string }{ { - input: []stats.SampleContainer{ + input: []metrics.SampleContainer{ newSample(myCounter, 12, map[string]string{ "tag1": "value1", "tag3": "value3", @@ -119,7 +118,7 @@ func baseTest(t *testing.T, output: "testing.things.my_counter:12|c", }, { - input: []stats.SampleContainer{ + input: []metrics.SampleContainer{ newSample(myGauge, 13, map[string]string{ "tag1": "value1", "tag3": "value3", @@ -128,7 +127,7 @@ func baseTest(t *testing.T, output: "testing.things.my_gauge:13.000000|g", }, { - input: []stats.SampleContainer{ + input: []metrics.SampleContainer{ newSample(myTrend, 14, map[string]string{ "tag1": "value1", "tag3": "value3", @@ -137,7 +136,7 @@ func baseTest(t *testing.T, output: "testing.things.my_trend:14.000000|ms", }, { - input: []stats.SampleContainer{ + input: []metrics.SampleContainer{ newSample(myRate, 15, map[string]string{ "tag1": "value1", "tag3": "value3", @@ -146,7 +145,7 @@ func baseTest(t *testing.T, output: "testing.things.my_rate:15|c", }, { - input: []stats.SampleContainer{ + input: []metrics.SampleContainer{ newSample(myCheck, 16, map[string]string{ "tag1": "value1", "tag3": "value3", diff --git a/output/types.go b/output/types.go index 42227e9e8f1..dce2da702aa 100644 --- a/output/types.go +++ b/output/types.go @@ -33,7 +33,6 @@ import ( "go.k6.io/k6/lib" "go.k6.io/k6/metrics" - "go.k6.io/k6/stats" ) // Params contains all possible constructor parameters an output may need. @@ -74,7 +73,7 @@ type Output interface { // method is never called concurrently, so do not do anything blocking here // that might take a long time. Preferably, just use the SampleBuffer or // something like it to buffer metrics until they are flushed. - AddMetricSamples(samples []stats.SampleContainer) + AddMetricSamples(samples []metrics.SampleContainer) // Flush all remaining metrics and finalize the test run. Stop() error @@ -84,7 +83,7 @@ type Output interface { // thresholds before it can be started. type WithThresholds interface { Output - SetThresholds(map[string]stats.Thresholds) + SetThresholds(map[string]metrics.Thresholds) } // WithTestRunStop is an output that can stop the Engine mid-test, interrupting