From 9871661cb6223d461530ec9454225ecb9a0c7d37 Mon Sep 17 00:00:00 2001 From: David Ashpole Date: Tue, 10 Oct 2023 19:03:49 +0000 Subject: [PATCH] Add WithExplicitBucketBoundaries Histogram option to the metric api --- CHANGELOG.md | 1 + metric/example_test.go | 1 + metric/instrument.go | 21 +++++++++++++++++++++ metric/syncfloat64.go | 10 ++++++++-- metric/syncfloat64_test.go | 6 ++++++ metric/syncint64.go | 10 ++++++++-- metric/syncint64_test.go | 6 ++++++ 7 files changed, 51 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 94870c638d6a..7ffcd4212398 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm ### Added - Add `go.opentelemetry.io/otel/bridge/opencensus.InstallTraceBridge`, which installs the OpenCensus trace bridge, and replaces `opencensus.NewTracer`. (#4567) +- Add `go.opentelemetry.io/otel/metric.WithExplicitBucketBoundaries`, which allows defining default explicit bucket boundaries when creating histogram instruments. (#4603) ### Deprecated diff --git a/metric/example_test.go b/metric/example_test.go index 5c28d2f29265..35f0965d91a4 100644 --- a/metric/example_test.go +++ b/metric/example_test.go @@ -161,6 +161,7 @@ func ExampleMeter_histogram() { "task.duration", metric.WithDescription("The duration of task execution."), metric.WithUnit("s"), + metric.WithExplicitBucketBoundaries([]float64{.005, .01, .025, .05, .075, .1, .25, .5, .75, 1, 2.5, 5, 7.5, 10}), ) if err != nil { panic(err) diff --git a/metric/instrument.go b/metric/instrument.go index cdca00058c68..fc3be5caa398 100644 --- a/metric/instrument.go +++ b/metric/instrument.go @@ -39,6 +39,12 @@ type InstrumentOption interface { Float64ObservableGaugeOption } +// HistogramOption applies options to histogram instruments. +type HistogramOption interface { + Int64HistogramOption + Float64HistogramOption +} + type descOpt string func (o descOpt) applyFloat64Counter(c Float64CounterConfig) Float64CounterConfig { @@ -171,6 +177,21 @@ func (o unitOpt) applyInt64ObservableGauge(c Int64ObservableGaugeConfig) Int64Ob // The unit u should be defined using the appropriate [UCUM](https://ucum.org) case-sensitive code. func WithUnit(u string) InstrumentOption { return unitOpt(u) } +// WithExplicitBucketBoundaries sets the instrument explicit bucket boundaries. +func WithExplicitBucketBoundaries(bounds []float64) HistogramOption { return bucketOpt(bounds) } + +type bucketOpt []float64 + +func (o bucketOpt) applyFloat64Histogram(c Float64HistogramConfig) Float64HistogramConfig { + c.explicitBucketBoundaries = o + return c +} + +func (o bucketOpt) applyInt64Histogram(c Int64HistogramConfig) Int64HistogramConfig { + c.explicitBucketBoundaries = o + return c +} + // AddOption applies options to an addition measurement. See // [MeasurementOption] for other options that can be used as an AddOption. type AddOption interface { diff --git a/metric/syncfloat64.go b/metric/syncfloat64.go index f0b063721d81..0a4825ae6a79 100644 --- a/metric/syncfloat64.go +++ b/metric/syncfloat64.go @@ -147,8 +147,9 @@ type Float64Histogram interface { // Float64HistogramConfig contains options for synchronous counter instruments // that record int64 values. type Float64HistogramConfig struct { - description string - unit string + description string + unit string + explicitBucketBoundaries []float64 } // NewFloat64HistogramConfig returns a new [Float64HistogramConfig] with all @@ -171,6 +172,11 @@ func (c Float64HistogramConfig) Unit() string { return c.unit } +// ExplicitBucketBoundaries returns the configured explicit bucket boundaries. +func (c Float64HistogramConfig) ExplicitBucketBoundaries() []float64 { + return c.explicitBucketBoundaries +} + // Float64HistogramOption applies options to a [Float64HistogramConfig]. See // [InstrumentOption] for other options that can be used as a // Float64HistogramOption. diff --git a/metric/syncfloat64_test.go b/metric/syncfloat64_test.go index 7132680b1316..51cef235317e 100644 --- a/metric/syncfloat64_test.go +++ b/metric/syncfloat64_test.go @@ -51,3 +51,9 @@ type float64Config interface { Description() string Unit() string } + +func TestFloat64ExplicitBucketHistogramConfiguration(t *testing.T) { + bounds := []float64{0.1, 0.5, 1.0} + got := NewFloat64HistogramConfig(WithExplicitBucketBoundaries(bounds)) + assert.Equal(t, bounds, got.ExplicitBucketBoundaries(), "boundaries") +} diff --git a/metric/syncint64.go b/metric/syncint64.go index 6f508eb66d40..56667d32fc01 100644 --- a/metric/syncint64.go +++ b/metric/syncint64.go @@ -147,8 +147,9 @@ type Int64Histogram interface { // Int64HistogramConfig contains options for synchronous counter instruments // that record int64 values. type Int64HistogramConfig struct { - description string - unit string + description string + unit string + explicitBucketBoundaries []float64 } // NewInt64HistogramConfig returns a new [Int64HistogramConfig] with all opts @@ -171,6 +172,11 @@ func (c Int64HistogramConfig) Unit() string { return c.unit } +// ExplicitBucketBoundaries returns the configured explicit bucket boundaries. +func (c Int64HistogramConfig) ExplicitBucketBoundaries() []float64 { + return c.explicitBucketBoundaries +} + // Int64HistogramOption applies options to a [Int64HistogramConfig]. See // [InstrumentOption] for other options that can be used as an // Int64HistogramOption. diff --git a/metric/syncint64_test.go b/metric/syncint64_test.go index 51c02f5e041a..dcc351075c46 100644 --- a/metric/syncint64_test.go +++ b/metric/syncint64_test.go @@ -51,3 +51,9 @@ type int64Config interface { Description() string Unit() string } + +func TestInt64ExplicitBucketHistogramConfiguration(t *testing.T) { + bounds := []float64{0.1, 0.5, 1.0} + got := NewInt64HistogramConfig(WithExplicitBucketBoundaries(bounds)) + assert.Equal(t, bounds, got.ExplicitBucketBoundaries(), "boundaries") +}