Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

[Refactor] Refactor common code between all benchmark commands #1611

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
119 changes: 119 additions & 0 deletions internal/benchrunner/runners/common/scenario.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
// or more contributor license agreements. Licensed under the Elastic License;
// you may not use this file except in compliance with the Elastic License.

package common
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit. common seems too generic, could this go directly in the internal/benchrunner/runners package? Or to an internal/benchrunner/scenario package?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@aspacca Any thoughts?


import (
"errors"
"fmt"
"os"
"path/filepath"
"strings"

"github.com/elastic/go-ucfg/yaml"
)

// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
// or more contributor license agreements. Licensed under the Elastic License;
// you may not use this file except in compliance with the Elastic License.

const DevPath = "_dev/benchmark/rally"

type Scenario struct {
Package string `config:"package" json:"package"`
Description string `config:"description" json:"description"`
Version string `config:"version" json:"version"`
DataStream DataStream `config:"data_stream" json:"data_stream"`
Corpora Corpora `config:"corpora" json:"corpora"`
}

type DataStream struct {
Name string `config:"name" json:"name"`
}

type Corpora struct {
Generator *Generator `config:"generator" json:"generator"`
}

type Generator struct {
TotalEvents uint64 `config:"total_events" json:"total_events"`
Template CorporaTemplate `config:"template" json:"template"`
Config CorporaAsset `config:"config" json:"config"`
Fields CorporaAsset `config:"fields" json:"fields"`
}

type CorporaAsset struct {
Raw map[string]interface{} `config:"raw" json:"raw"`
Path string `config:"path" json:"path"`
}
type CorporaTemplate struct {
Raw string `config:"raw" json:"raw"`
Path string `config:"path" json:"path"`
Type string `config:"type" json:"type"`
}

func DefaultConfig() *Scenario {
return &Scenario{}
}

func ReadConfig(path, scenario, packageName, packageVersion string) (*Scenario, error) {
configPath := filepath.Join(path, DevPath, fmt.Sprintf("%s.yml", scenario))
c := DefaultConfig()
cfg, err := yaml.NewConfigWithFile(configPath)
if err != nil {
return nil, fmt.Errorf("can't load benchmark configuration: %s: %w", configPath, err)
}

if err == nil {
if err := cfg.Unpack(c); err != nil {
return nil, fmt.Errorf("can't unpack benchmark configuration: %s: %w", configPath, err)
}
}

c.Package = packageName
c.Version = packageVersion

if c.DataStream.Name == "" {
return nil, errors.New("can't read data stream name from benchmark configuration: empty")
}

return c, nil
}

func ReadScenarios(path, scenarioName, packageName, packageVersion string) (map[string]*Scenario, error) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit. Do we have any benefit on returning scenarios as a map? Returning a list would help controlling the order of execution and results. Scenario could have a field for the name.

Suggested change
func ReadScenarios(path, scenarioName, packageName, packageVersion string) (map[string]*Scenario, error) {
func ReadScenarios(path, scenarioName, packageName, packageVersion string) ([]*Scenario, error) {

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jsoriano I would prefer to delay code changes to a different PR. The reason is for this PR I only moved code around, not type / logic change to make sure the refactoring does not affect any of the logic.

scenarios := make(map[string]*Scenario)
if len(scenarioName) > 0 {
scenario, err := ReadConfig(path, scenarioName, packageName, packageVersion)
if err != nil {
return nil, fmt.Errorf("error loading scenario: %w", err)
}
scenarios[scenarioName] = scenario
} else {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit. I think we can remove the else to have one less nesting level.

Suggested change
} else {
return scenarios
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See my comment above, happy to follow up further code changes but now trying to focus on only moving things around, no logical changes.

err := filepath.Walk(filepath.Join(path, DevPath), func(_ string, info os.FileInfo, err error) error {
if err != nil {
return err
}

if info.IsDir() {
return nil
}

if strings.HasSuffix(info.Name(), "-benchmark.yml") {
scenarioName = strings.TrimSuffix(info.Name(), ".yml")
scenario, err := ReadConfig(path, scenarioName, packageName, packageVersion)
if err != nil {
return err
}
scenarios[scenarioName] = scenario
}

return nil
})
if err != nil {
return nil, fmt.Errorf("error loading scenario: %w", err)
}
}

return scenarios, nil
}
6 changes: 4 additions & 2 deletions internal/benchrunner/runners/rally/metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import (
"sync/atomic"
"time"

"github.com/elastic/elastic-package/internal/benchrunner/runners/common"

"github.com/elastic/elastic-package/internal/elasticsearch"
"github.com/elastic/elastic-package/internal/elasticsearch/ingest"
"github.com/elastic/elastic-package/internal/logger"
Expand All @@ -23,7 +25,7 @@ import (
type collector struct {
ctxt servicedeployer.ServiceContext
metadata benchMeta
scenario scenario
scenario common.Scenario

interval time.Duration
esAPI *elasticsearch.API
Expand Down Expand Up @@ -66,7 +68,7 @@ type metricsSummary struct {
func newCollector(
ctxt servicedeployer.ServiceContext,
benchName string,
scenario scenario,
scenario common.Scenario,
esAPI, metricsAPI *elasticsearch.API,
interval time.Duration,
datastream, pipelinePrefix string,
Expand Down
10 changes: 6 additions & 4 deletions internal/benchrunner/runners/rally/report.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import (
"strings"
"time"

"github.com/elastic/elastic-package/internal/benchrunner/runners/common"

"github.com/dustin/go-humanize"
"github.com/jedib0t/go-pretty/table"
"github.com/jedib0t/go-pretty/text"
Expand All @@ -31,8 +33,8 @@ type report struct {
}
Parameters struct {
PackageVersion string
DataStream dataStream
Corpora corpora
DataStream common.DataStream
Corpora common.Corpora
}
ClusterName string
Nodes int
Expand All @@ -43,7 +45,7 @@ type report struct {
RallyStats []rallyStat
}

func createReport(benchName, corporaFile string, s *scenario, sum *metricsSummary, stats []rallyStat) (reporters.Reportable, error) {
func createReport(benchName, corporaFile string, s *common.Scenario, sum *metricsSummary, stats []rallyStat) (reporters.Reportable, error) {
r := newReport(benchName, corporaFile, s, sum, stats)
human := reporters.NewReport(s.Package, reportHumanFormat(r))

Expand All @@ -59,7 +61,7 @@ func createReport(benchName, corporaFile string, s *scenario, sum *metricsSummar
return mr, nil
}

func newReport(benchName, corporaFile string, s *scenario, sum *metricsSummary, stats []rallyStat) *report {
func newReport(benchName, corporaFile string, s *common.Scenario, sum *metricsSummary, stats []rallyStat) *report {
var report report
report.Info.Benchmark = benchName
report.Info.Description = s.Description
Expand Down
14 changes: 8 additions & 6 deletions internal/benchrunner/runners/rally/runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ import (
"text/template"
"time"

"github.com/elastic/elastic-package/internal/benchrunner/runners/common"

"github.com/elastic/elastic-package/internal/packages/installer"

"github.com/magefile/mage/sh"
Expand Down Expand Up @@ -150,7 +152,7 @@ type rallyStat struct {

type runner struct {
options Options
scenario *scenario
scenario *common.Scenario

ctxt servicedeployer.ServiceContext
runtimeDataStream string
Expand Down Expand Up @@ -262,7 +264,7 @@ func (r *runner) setUp() error {
return fmt.Errorf("reading package manifest failed: %w", err)
}

scenario, err := readConfig(r.options.PackageRootPath, r.options.BenchName, pkgManifest.Name, pkgManifest.Version)
scenario, err := common.ReadConfig(r.options.PackageRootPath, r.options.BenchName, pkgManifest.Name, pkgManifest.Version)
if err != nil {
return err
}
Expand Down Expand Up @@ -596,7 +598,7 @@ func (r *runner) getGeneratorConfig() (*config.Config, error) {
)

if r.scenario.Corpora.Generator.Config.Path != "" {
configPath := filepath.Clean(filepath.Join(devPath, r.scenario.Corpora.Generator.Config.Path))
configPath := filepath.Clean(filepath.Join(common.DevPath, r.scenario.Corpora.Generator.Config.Path))
configPath = os.ExpandEnv(configPath)
if _, err := os.Stat(configPath); err != nil {
return nil, fmt.Errorf("can't find config file %s: %w", configPath, err)
Expand Down Expand Up @@ -627,7 +629,7 @@ func (r *runner) getGeneratorFields() (fields.Fields, error) {
)

if r.scenario.Corpora.Generator.Fields.Path != "" {
fieldsPath := filepath.Clean(filepath.Join(devPath, r.scenario.Corpora.Generator.Fields.Path))
fieldsPath := filepath.Clean(filepath.Join(common.DevPath, r.scenario.Corpora.Generator.Fields.Path))
fieldsPath = os.ExpandEnv(fieldsPath)
if _, err := os.Stat(fieldsPath); err != nil {
return nil, fmt.Errorf("can't find fields file %s: %w", fieldsPath, err)
Expand Down Expand Up @@ -659,7 +661,7 @@ func (r *runner) getGeneratorTemplate() ([]byte, error) {
)

if r.scenario.Corpora.Generator.Template.Path != "" {
tplPath := filepath.Clean(filepath.Join(devPath, r.scenario.Corpora.Generator.Template.Path))
tplPath := filepath.Clean(filepath.Join(common.DevPath, r.scenario.Corpora.Generator.Template.Path))
tplPath = os.ExpandEnv(tplPath)
if _, err := os.Stat(tplPath); err != nil {
return nil, fmt.Errorf("can't find template file %s: %w", tplPath, err)
Expand Down Expand Up @@ -1113,7 +1115,7 @@ type benchMeta struct {
Benchmark string `json:"benchmark"`
RunID string `json:"run_id"`
} `json:"info"`
Parameters scenario `json:"parameter"`
Parameters common.Scenario `json:"parameter"`
}

func (r *runner) enrichEventWithBenchmarkMetadata(e map[string]interface{}) map[string]interface{} {
Expand Down
71 changes: 0 additions & 71 deletions internal/benchrunner/runners/rally/scenario.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,74 +3,3 @@
// you may not use this file except in compliance with the Elastic License.

package rally

import (
"errors"
"fmt"
"path/filepath"

"github.com/elastic/go-ucfg/yaml"
)

const devPath = "_dev/benchmark/rally"

type scenario struct {
Package string `config:"package" json:"package"`
Description string `config:"description" json:"description"`
Version string `config:"version" json:"version"`
DataStream dataStream `config:"data_stream" json:"data_stream"`
Corpora corpora `config:"corpora" json:"corpora"`
}

type dataStream struct {
Name string `config:"name" json:"name"`
}

type corpora struct {
Generator *generator `config:"generator" json:"generator"`
}

type generator struct {
TotalEvents uint64 `config:"total_events" json:"total_events"`
Template corporaTemplate `config:"template" json:"template"`
Config corporaAsset `config:"config" json:"config"`
Fields corporaAsset `config:"fields" json:"fields"`
}

type corporaAsset struct {
Raw map[string]interface{} `config:"raw" json:"raw"`
Path string `config:"path" json:"path"`
}
type corporaTemplate struct {
Raw string `config:"raw" json:"raw"`
Path string `config:"path" json:"path"`
Type string `config:"type" json:"type"`
}

func defaultConfig() *scenario {
return &scenario{}
}

func readConfig(path, scenario, packageName, packageVersion string) (*scenario, error) {
configPath := filepath.Join(path, devPath, fmt.Sprintf("%s.yml", scenario))
c := defaultConfig()
cfg, err := yaml.NewConfigWithFile(configPath)
if err != nil {
return nil, fmt.Errorf("can't load benchmark configuration: %s: %w", configPath, err)
}

if err == nil {
if err := cfg.Unpack(c); err != nil {
return nil, fmt.Errorf("can't unpack benchmark configuration: %s: %w", configPath, err)
}
}

c.Package = packageName
c.Version = packageVersion

if c.DataStream.Name == "" {
return nil, errors.New("can't read data stream name from benchmark configuration: empty")
}

return c, nil
}
Loading