diff --git a/.chloggen/telemetrygen-add-metric-types.yaml b/.chloggen/telemetrygen-add-metric-types.yaml new file mode 100644 index 000000000000..6e69c0dc1206 --- /dev/null +++ b/.chloggen/telemetrygen-add-metric-types.yaml @@ -0,0 +1,25 @@ +# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix' +change_type: 'enhancement' + +# The name of the component, or a single word describing the area of concern, (e.g. filelogreceiver) +component: cmd/telemetrygen + +# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`). +note: Add CLI option for selecting different metric types + +# Mandatory: One or more tracking issues related to the change. You can use the PR number here if no issue exists. +issues: [26667] + +# (Optional) One or more lines of additional information to render under the primary note. +# These lines will be padded with 2 spaces and then inserted directly into the document. +# Use pipe (|) for multiline entries. +subtext: + +# If your change doesn't affect end users or the exported elements of any package, +# you should instead start your pull request title with [chore] or use the "Skip Changelog" label. +# Optional: The change log or logs in which this entry should be included. +# e.g. '[user]' or '[user, api]' +# Include 'user' if the change is relevant to end users. +# Include 'api' if there is a change to a library API. +# Default: '[user]' +change_logs: [user] \ No newline at end of file diff --git a/cmd/telemetrygen/internal/metrics/config.go b/cmd/telemetrygen/internal/metrics/config.go index dbcd5f72ebe0..44bb4ef98aae 100644 --- a/cmd/telemetrygen/internal/metrics/config.go +++ b/cmd/telemetrygen/internal/metrics/config.go @@ -13,10 +13,15 @@ import ( type Config struct { common.Config NumMetrics int + MetricType metricType } // Flags registers config flags. func (c *Config) Flags(fs *pflag.FlagSet) { + // Use Gauge as default metric type. + c.MetricType = metricTypeGauge + c.CommonFlags(fs) + fs.Var(&c.MetricType, "metric-type", "Metric type enum. must be one of 'Gauge' or 'Sum'") fs.IntVar(&c.NumMetrics, "metrics", 1, "Number of metrics to generate in each worker (ignored if duration is provided)") } diff --git a/cmd/telemetrygen/internal/metrics/metrics.go b/cmd/telemetrygen/internal/metrics/metrics.go index 6418f7228a95..310796cb9563 100644 --- a/cmd/telemetrygen/internal/metrics/metrics.go +++ b/cmd/telemetrygen/internal/metrics/metrics.go @@ -28,6 +28,7 @@ func Start(cfg *Config) error { if err != nil { return err } + logger.Info("starting the metrics generator with configuration", zap.Any("config", cfg)) grpcExpOpt := []otlpmetricgrpc.Option{ otlpmetricgrpc.WithEndpoint(cfg.Endpoint), @@ -104,6 +105,7 @@ func Run(c *Config, exp sdkmetric.Exporter, logger *zap.Logger) error { wg.Add(1) w := worker{ numMetrics: c.NumMetrics, + metricType: c.MetricType, limitPerSecond: limit, totalDuration: c.TotalDuration, running: running, diff --git a/cmd/telemetrygen/internal/metrics/metrics_types.go b/cmd/telemetrygen/internal/metrics/metrics_types.go new file mode 100644 index 000000000000..84318afc4fab --- /dev/null +++ b/cmd/telemetrygen/internal/metrics/metrics_types.go @@ -0,0 +1,36 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package metrics + +import ( + "errors" +) + +type metricType string + +const ( + metricTypeGauge = "Gauge" + metricTypeSum = "Sum" +) + +// String is used both by fmt.Print and by Cobra in help text +func (e *metricType) String() string { + return string(*e) +} + +// Set must have pointer receiver so it doesn't change the value of a copy +func (e *metricType) Set(v string) error { + switch v { + case "Gauge", "Sum": + *e = metricType(v) + return nil + default: + return errors.New(`must be one of "Gauge" or "Sum"`) + } +} + +// Type is only used in help text +func (e *metricType) Type() string { + return "metricType" +} diff --git a/cmd/telemetrygen/internal/metrics/worker.go b/cmd/telemetrygen/internal/metrics/worker.go index 6056cc5eb4ab..069f1b12e545 100644 --- a/cmd/telemetrygen/internal/metrics/worker.go +++ b/cmd/telemetrygen/internal/metrics/worker.go @@ -18,6 +18,7 @@ import ( type worker struct { running *atomic.Bool // pointer to shared flag that indicates it's time to stop the test + metricType metricType // type of metric to generate numMetrics int // how many metrics the worker has to generate (only when duration==0) totalDuration time.Duration // how long to run the test for (overrides `numMetrics`) limitPerSecond rate.Limit // how many metrics per second to generate @@ -28,29 +29,48 @@ type worker struct { func (w worker) simulateMetrics(res *resource.Resource, exporter sdkmetric.Exporter) { limiter := rate.NewLimiter(w.limitPerSecond, 1) - var i int64 + var i int64 for w.running.Load() { - rm := metricdata.ResourceMetrics{ - Resource: res, - ScopeMetrics: []metricdata.ScopeMetrics{ - { - Metrics: []metricdata.Metrics{ + var metrics []metricdata.Metrics + + switch w.metricType { + case metricTypeGauge: + metrics = append(metrics, metricdata.Metrics{ + Name: "gen", + Data: metricdata.Gauge[int64]{ + DataPoints: []metricdata.DataPoint[int64]{ + { + Time: time.Now(), + Value: i, + }, + }, + }, + }) + case metricTypeSum: + metrics = append(metrics, metricdata.Metrics{ + Name: "gen", + Data: metricdata.Sum[int64]{ + IsMonotonic: true, + Temporality: metricdata.CumulativeTemporality, + DataPoints: []metricdata.DataPoint[int64]{ { - Name: "gen", - Data: metricdata.Gauge[int64]{ - DataPoints: []metricdata.DataPoint[int64]{ - { - Time: time.Now(), - Value: i, - }, - }, - }, + StartTime: time.Now().Add(-1 * time.Second), + Time: time.Now(), + Value: i, }, }, }, - }, + }) + default: + w.logger.Fatal("unknown metric type") + } + + rm := metricdata.ResourceMetrics{ + Resource: res, + ScopeMetrics: []metricdata.ScopeMetrics{{Metrics: metrics}}, } + if err := exporter.Export(context.Background(), &rm); err != nil { w.logger.Fatal("exporter failed", zap.Error(err)) } diff --git a/cmd/telemetrygen/internal/metrics/worker_test.go b/cmd/telemetrygen/internal/metrics/worker_test.go index 832d8aa914bc..3944d875c47c 100644 --- a/cmd/telemetrygen/internal/metrics/worker_test.go +++ b/cmd/telemetrygen/internal/metrics/worker_test.go @@ -48,6 +48,7 @@ func TestFixedNumberOfMetrics(t *testing.T) { WorkerCount: 1, }, NumMetrics: 5, + MetricType: metricTypeSum, } exp := &mockExporter{} @@ -69,6 +70,7 @@ func TestRateOfMetrics(t *testing.T) { TotalDuration: time.Second / 2, WorkerCount: 1, }, + MetricType: metricTypeSum, } exp := &mockExporter{} @@ -88,6 +90,7 @@ func TestUnthrottled(t *testing.T) { TotalDuration: 1 * time.Second, WorkerCount: 1, }, + MetricType: metricTypeSum, } exp := &mockExporter{}