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

[receiver/statsd] Add an exponential histogram option #12951

Merged
merged 52 commits into from
Oct 14, 2022
Merged
Show file tree
Hide file tree
Changes from 48 commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
c27b8ed
improving testbed for metrics snapshot
Aug 3, 2022
57c107a
found bug in structure
Aug 3, 2022
6eab4ca
document
Aug 4, 2022
be6e4fe
update readme
Aug 4, 2022
a1fa7f9
Merge branch 'main' of github.com:open-telemetry/opentelemetry-collec…
Aug 4, 2022
9b507a3
update otel-launcher-go version
Aug 4, 2022
c5e8f40
Merge branch 'main' of github.com:open-telemetry/opentelemetry-collec…
Aug 4, 2022
a881748
Merge branch 'main' of github.com:open-telemetry/opentelemetry-collec…
Aug 5, 2022
621f69b
Merge branch 'main' of github.com:open-telemetry/opentelemetry-collec…
Aug 9, 2022
dcff3c2
Merge branch 'main' of github.com:open-telemetry/opentelemetry-collec…
Aug 16, 2022
c8efe24
fix changelog
Aug 16, 2022
4626e84
untabify
Aug 16, 2022
b1f913e
verify histogram config w/ testdata
Aug 16, 2022
f3c1d29
comment
Aug 16, 2022
4a8ad5c
Merge branch 'main' of github.com:open-telemetry/opentelemetry-collec…
Aug 18, 2022
39f9551
move the old opencensus metrics test utils out of the way
Aug 18, 2022
9e82130
move new test utilities out of testbed
Aug 18, 2022
5bc2bc6
Merge branch 'main' of github.com:open-telemetry/opentelemetry-collec…
Aug 25, 2022
eef42c1
tidy
Aug 25, 2022
4aaa2ab
tidy chlog
Aug 25, 2022
fd9f8eb
dependency update
Sep 6, 2022
c2221a0
lint
Sep 6, 2022
6d95bfc
Merge branch 'main' of github.com:open-telemetry/opentelemetry-collec…
Sep 12, 2022
9ae90bc
tidy
Sep 12, 2022
99fe364
tidy again
Sep 12, 2022
48985d3
lint
Sep 12, 2022
afc98c1
Merge branch 'main' of github.com:open-telemetry/opentelemetry-collec…
Sep 12, 2022
886721c
goimports guesswork
Sep 12, 2022
c49d352
real tidy
Sep 12, 2022
834374e
update deps
Sep 13, 2022
637b5b6
tidy
Sep 13, 2022
3ffa365
Merge branch 'main' of github.com:open-telemetry/opentelemetry-collec…
Sep 14, 2022
4328e9d
lint
Sep 14, 2022
009851b
Merge branch 'main' of github.com:open-telemetry/opentelemetry-collec…
Sep 14, 2022
3ae3d2f
Merge branch 'main' of github.com:open-telemetry/opentelemetry-collec…
Oct 5, 2022
62baab6
tidy & fmt
Oct 5, 2022
c2d6ffc
lint
Oct 5, 2022
2ff4c15
Merge branch 'main' of github.com:open-telemetry/opentelemetry-collec…
Oct 12, 2022
4a4fa03
stale comment
Oct 12, 2022
da3a4e9
duplicative code
Oct 12, 2022
724cffe
adjust readme.md content
Oct 12, 2022
7a9a282
more testing, remove whitespace
Oct 12, 2022
6296fae
add min/max support (and test support)
Oct 12, 2022
633e9a0
updates for v0.62
Oct 13, 2022
5771ec1
Merge branch 'main' of github.com:open-telemetry/opentelemetry-collec…
Oct 13, 2022
0ee7b1c
lint
Oct 13, 2022
3092869
restore unused symbol
Oct 13, 2022
fe9f7a3
update chlog
Oct 13, 2022
5611572
Update receiver/statsdreceiver/go.mod
jmacd Oct 13, 2022
088563f
update go.sum
Oct 13, 2022
28c2585
add replace
Oct 13, 2022
3f95b9b
testing fixes
Oct 13, 2022
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
4 changes: 4 additions & 0 deletions .chloggen/expo_statsd_receiver.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
change_type: enhancement
component: receiver/statsdreceiver
note: "Add OTLP exponential histogram aggregator support for high-resolution histogram and timing metrics"
issues: [5742]
1 change: 1 addition & 0 deletions cmd/configschema/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,7 @@ require (
github.com/kylelemons/godebug v1.1.0 // indirect
github.com/leoluk/perflib_exporter v0.2.0 // indirect
github.com/lib/pq v1.10.7 // indirect
github.com/lightstep/go-expohisto v1.0.0 // indirect
github.com/linkedin/goavro/v2 v2.9.8 // indirect
github.com/linode/linodego v1.8.0 // indirect
github.com/lufia/plan9stats v0.0.0-20220517141722-cf486979b281 // indirect
Expand Down
2 changes: 2 additions & 0 deletions cmd/configschema/go.sum

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -422,6 +422,7 @@ require (
github.com/kylelemons/godebug v1.1.0 // indirect
github.com/leoluk/perflib_exporter v0.2.0 // indirect
github.com/lib/pq v1.10.7 // indirect
github.com/lightstep/go-expohisto v1.0.0 // indirect
github.com/linkedin/goavro/v2 v2.9.8 // indirect
github.com/linode/linodego v1.8.0 // indirect
github.com/lufia/plan9stats v0.0.0-20220517141722-cf486979b281 // indirect
Expand Down
2 changes: 2 additions & 0 deletions go.sum

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions internal/coreinternal/metricstestutil/metric_diff.go
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,8 @@ func diffExponentialHistogramPt(
diffs = diffMetricAttrs(diffs, expected.Attributes(), actual.Attributes())
diffs = diff(diffs, expected.Count(), actual.Count(), "ExponentialHistogramDataPoint Count")
diffs = diff(diffs, expected.Sum(), actual.Sum(), "ExponentialHistogramDataPoint Sum")
diffs = diff(diffs, expected.Min(), actual.Min(), "ExponentialHistogramDataPoint Min")
diffs = diff(diffs, expected.Max(), actual.Max(), "ExponentialHistogramDataPoint Max")
diffs = diff(diffs, expected.ZeroCount(), actual.ZeroCount(), "ExponentialHistogramDataPoint ZeroCount")
diffs = diff(diffs, expected.Scale(), actual.Scale(), "ExponentialHistogramDataPoint Scale")

Expand Down
16 changes: 10 additions & 6 deletions receiver/statsdreceiver/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@ The Following settings are optional:

`"statsd_type"` specifies received Statsd data type. Possible values for this setting are `"timing"`, `"timer"` and `"histogram"`.

`"observer_type"` specifies OTLP data type to convert to. We support `"gauge"` and `"summary"`. For `"gauge"`, it does not perform any aggregation.
For `"summary`, the statsD receiver will aggregate to one OTLP summary metric for one metric description(the same metric name with the same tags). It will send percentile 0, 10, 50, 90, 95, 100 to the downstream.
TODO: Add a new option to use a smoothed summary like Promethetheus: https://github.com/open-telemetry/opentelemetry-collector-contrib/pull/3261
`"observer_type"` specifies OTLP data type to convert to. We support `"gauge"`, `"summary"`, and `"histogram"`. For `"gauge"`, it does not perform any aggregation.
For `"summary`, the statsD receiver will aggregate to one OTLP summary metric for one metric description (the same metric name with the same tags). It will send percentile 0, 10, 50, 90, 95, 100 to the downstream. The `"histogram"` setting selects an [auto-scaling exponential histogram configured with only a maximum size](https://github.com/lightstep/go-expohisto#readme), as shown in the example below.
TODO: Add a new option to use a smoothed summary like Prometheus: https://github.com/open-telemetry/opentelemetry-collector-contrib/pull/3261

Example:

Expand All @@ -48,7 +48,9 @@ receivers:
- statsd_type: "histogram"
observer_type: "gauge"
- statsd_type: "timing"
observer_type: "gauge"
observer_type: "histogram"
histogram:
max_size: 100
```

The full list of settings exposed for this receiver are documented [here](./config.go)
Expand Down Expand Up @@ -123,9 +125,11 @@ receivers:
is_monotonic_counter: false # default
timer_histogram_mapping:
- statsd_type: "histogram"
observer_type: "gauge"
observer_type: "histogram"
histogram:
max_size: 50
- statsd_type: "timing"
observer_type: "gauge"
observer_type: "summary"

exporters:
file:
Expand Down
16 changes: 14 additions & 2 deletions receiver/statsdreceiver/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"fmt"
"time"

"github.com/lightstep/go-expohisto/structure"
"go.opentelemetry.io/collector/config"
"go.opentelemetry.io/collector/config/confignet"
"go.uber.org/multierr"
Expand All @@ -36,7 +37,6 @@ type Config struct {
}

func (c *Config) validate() error {

var errs error

if c.AggregationInterval <= 0 {
Expand All @@ -63,10 +63,22 @@ func (c *Config) validate() error {
}

switch eachMap.ObserverType {
case protocol.GaugeObserver, protocol.SummaryObserver:
case protocol.GaugeObserver, protocol.SummaryObserver, protocol.HistogramObserver:
default:
errs = multierr.Append(errs, fmt.Errorf("observer_type is not supported: %s", eachMap.ObserverType))
}

if eachMap.ObserverType == protocol.HistogramObserver {
if eachMap.Histogram.MaxSize != 0 && (eachMap.Histogram.MaxSize < structure.MinSize || eachMap.Histogram.MaxSize > structure.MaximumMaxSize) {
mx-psi marked this conversation as resolved.
Show resolved Hide resolved
errs = multierr.Append(errs, fmt.Errorf("histogram max_size out of range: %v", eachMap.Histogram.MaxSize))
}
} else {
// Non-histogram observer w/ histogram config
var empty protocol.HistogramConfig
if eachMap.Histogram != empty {
errs = multierr.Append(errs, fmt.Errorf("histogram configuration requires observer_type: histogram"))
}
}
}

if TimerHistogramMappingMissingObjectName {
Expand Down
6 changes: 4 additions & 2 deletions receiver/statsdreceiver/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,10 @@ func TestLoadConfig(t *testing.T) {
},
{
StatsdType: "timing",
ObserverType: "gauge",
ObserverType: "histogram",
Histogram: protocol.HistogramConfig{
MaxSize: 170,
},
},
},
},
Expand Down Expand Up @@ -153,5 +156,4 @@ func TestValidate(t *testing.T) {
require.EqualError(t, test.cfg.validate(), test.expectedErr)
})
}

}
92 changes: 92 additions & 0 deletions receiver/statsdreceiver/factory_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,30 @@ package statsdreceiver
import (
"context"
"testing"
"time"

"github.com/lightstep/go-expohisto/structure"
"github.com/stretchr/testify/assert"
"go.opentelemetry.io/collector/component"
"go.opentelemetry.io/collector/component/componenttest"
"go.opentelemetry.io/collector/config/configtest"
"go.opentelemetry.io/collector/consumer/consumertest"

"github.com/open-telemetry/opentelemetry-collector-contrib/receiver/statsdreceiver/protocol"
)

type testHost struct {
component.Host
t *testing.T
}

// ReportFatalError causes the test to be run to fail.
func (h *testHost) ReportFatalError(err error) {
h.t.Fatalf("receiver reported a fatal error: %v", err)
}

var _ component.Host = (*testHost)(nil)

func TestCreateDefaultConfig(t *testing.T) {
factory := NewFactory()
cfg := factory.CreateDefaultConfig()
Expand Down Expand Up @@ -61,6 +76,83 @@ func TestCreateReceiverWithConfigErr(t *testing.T) {

}

func TestCreateReceiverWithHistogramConfigError(t *testing.T) {
jmacd marked this conversation as resolved.
Show resolved Hide resolved
for _, maxSize := range []int32{structure.MaximumMaxSize + 1, -1, -structure.MaximumMaxSize} {
cfg := &Config{
AggregationInterval: 20 * time.Second,
TimerHistogramMapping: []protocol.TimerHistogramMapping{
{
StatsdType: "timing",
ObserverType: "histogram",
Histogram: protocol.HistogramConfig{
MaxSize: maxSize,
},
},
},
}
receiver, err := createMetricsReceiver(
context.Background(),
componenttest.NewNopReceiverCreateSettings(),
cfg,
consumertest.NewNop(),
)
assert.Error(t, err)
assert.Contains(t, err.Error(), "histogram max_size out of range")
assert.Nil(t, receiver)
}
}

func TestCreateReceiverWithHistogramGoodConfig(t *testing.T) {
for _, maxSize := range []int32{structure.MaximumMaxSize, 0, 2} {
cfg := &Config{
AggregationInterval: 20 * time.Second,
TimerHistogramMapping: []protocol.TimerHistogramMapping{
{
StatsdType: "timing",
ObserverType: "histogram",
Histogram: protocol.HistogramConfig{
MaxSize: maxSize,
},
},
},
}
receiver, err := createMetricsReceiver(
context.Background(),
componenttest.NewNopReceiverCreateSettings(),
cfg,
consumertest.NewNop(),
)
assert.NoError(t, err)
assert.NotNil(t, receiver)
assert.NoError(t, receiver.Start(context.Background(), &testHost{t: t}))
assert.NoError(t, receiver.Shutdown(context.Background()))
}
}

func TestCreateReceiverWithInvalidHistogramConfig(t *testing.T) {
cfg := &Config{
AggregationInterval: 20 * time.Second,
TimerHistogramMapping: []protocol.TimerHistogramMapping{
{
StatsdType: "timing",
ObserverType: "gauge",
Histogram: protocol.HistogramConfig{
MaxSize: 100,
},
},
},
}
receiver, err := createMetricsReceiver(
context.Background(),
componenttest.NewNopReceiverCreateSettings(),
cfg,
consumertest.NewNop(),
)
assert.Error(t, err)
assert.Contains(t, err.Error(), "histogram configuration requires observer_type: histogram")
assert.Nil(t, receiver)
}

func TestCreateMetricsReceiverWithNilConsumer(t *testing.T) {
receiver, err := createMetricsReceiver(
context.Background(),
Expand Down
8 changes: 4 additions & 4 deletions receiver/statsdreceiver/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ module github.com/open-telemetry/opentelemetry-collector-contrib/receiver/statsd
go 1.18
mx-psi marked this conversation as resolved.
Show resolved Hide resolved

require (
github.com/lightstep/go-expohisto v1.0.0
github.com/open-telemetry/opentelemetry-collector-contrib/internal/common v0.62.0
github.com/open-telemetry/opentelemetry-collector-contrib/internal/coreinternal v0.61.0
jmacd marked this conversation as resolved.
Show resolved Hide resolved
github.com/stretchr/testify v1.8.0
go.opencensus.io v0.23.0
go.opentelemetry.io/collector v0.62.0
Expand All @@ -16,7 +18,6 @@ require (

require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/fsnotify/fsnotify v1.5.4 // indirect
github.com/go-logr/logr v1.2.3 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
Expand All @@ -30,17 +31,16 @@ require (
github.com/mitchellh/reflectwalk v1.0.2 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/pelletier/go-toml v1.9.4 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
go.opentelemetry.io/otel/metric v0.32.1 // indirect
go.opentelemetry.io/otel/sdk v1.10.0 // indirect
go.opentelemetry.io/otel/trace v1.10.0 // indirect
go.uber.org/atomic v1.10.0 // indirect
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6 // indirect
golang.org/x/net v0.0.0-20220225172249-27dd8689420f // indirect
golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e // indirect
golang.org/x/sys v0.0.0-20220808155132-1c4a2a72c664 // indirect
golang.org/x/text v0.3.7 // indirect
google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa // indirect
google.golang.org/genproto v0.0.0-20220822174746-9e6da59bd2fc // indirect
google.golang.org/grpc v1.50.0 // indirect
google.golang.org/protobuf v1.28.1 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
Expand Down
Loading