statsd: remove global cardinality#346
Conversation
| func WithCardinality(card Cardinality) Option { | ||
| return func(o *Options) error { | ||
| o.tagCardinality = card | ||
| if !card.isValid() { |
There was a problem hiding this comment.
Here we ensure user can never pass invalid cardinality to the client during construction.
| channelModeErrorsWhenFull bool | ||
| errorHandler ErrorHandler | ||
| tagCardinality Cardinality | ||
| tagCardinality *Cardinality |
There was a problem hiding this comment.
nil is default unset
There was a problem hiding this comment.
If we redefine Cardinality as above so that NotSet is 0, then we don't need to worry about pointers and nil errors. I think this would be cleaner.
There was a problem hiding this comment.
I agree -1 enum value is annoying.
Here pointer is used to signal that value was explicitly set via options, e.g. for the usecase when there is an env variable DD_CARDINALITY=low and user wants to unset cardinality via WithCardinality(CardinalityNotSet)
There was a problem hiding this comment.
Yes, that's a good point.
| if o.tagCardinality != nil { | ||
| c.defaultCardinality = *o.tagCardinality | ||
| } else if card, ok := envTagCardinality(); ok { | ||
| c.defaultCardinality = card | ||
| } else { | ||
| c.defaultCardinality = CardinalityNotSet | ||
| } |
There was a problem hiding this comment.
Here we ensure that c.defaultCardinality is always a valid value.
| c, ok := o.(Cardinality) | ||
| if ok { | ||
| cardinality = c | ||
| if ok && c.isValid() { |
There was a problem hiding this comment.
Here we ensure that cardinality is always valid when passed via parameter.
StephenWakely
left a comment
There was a problem hiding this comment.
Yes this is much cleaner. Thank you. I just have a couple of minor nits which I think would make things a little cleaner.
| ) | ||
|
|
||
| func (c Cardinality) isValid() bool { | ||
| return c >= CardinalityNotSet && c <= CardinalityHigh |
There was a problem hiding this comment.
A Cardinality value of 0 is also not valid, due to the way the consts are setup with iota.
| return c >= CardinalityNotSet && c <= CardinalityHigh | |
| return c >= CardinalityNotSet && c <= CardinalityHigh && c != 0 |
Alternatively, I can't really think of a reason why NotSet has to be -1, so we could possibly just change the definition to make it start at 0.
There was a problem hiding this comment.
A Cardinality value of 0 is also not valid
This method checks user input for options and per metrics call to ensure a supported value is passed; maybe its better to rename into isSupported.
The CardinalityNotSet vs CardinalityNone split is shady and the difference is not clear.
Existing code checks string value for emptiness which is not empty for CardinalityNone 🙈 :
datadog-go/statsd/aggregator.go
Lines 184 to 224 in 2132689
Is the CardinalityNone ("none") a valid value to use in the aggregation context?
Also CardinalityNotSet is exported so I am not sure we can drop it easily.
There was a problem hiding this comment.
I've made CardinalityNotSet equal to zero to avoid gap between it and CardinalityNone.
| channelModeErrorsWhenFull bool | ||
| errorHandler ErrorHandler | ||
| tagCardinality Cardinality | ||
| tagCardinality *Cardinality |
There was a problem hiding this comment.
If we redefine Cardinality as above so that NotSet is 0, then we don't need to worry about pointers and nil errors. I think this would be cleaner.
The change DataDog#327 introduced support for tag cardinality with global default value that could be overriden per metric call via parameter. Default cardinality value is stored in a global variable guarded by a mutex which has two downsides: * performance impact - each measure call has to obtain mutex to get the default value * two clients created with different default cardinality override the same global value This change eliminates global default value and uses default value per statsd client specified during client construction with a fallback to environment variables. User supplied cardinality value is validated during client construction and during parameter parsing with a fallback to default value such that all internal components can assume they always receive a valid value. Performance improvement (via `Statsd.*Aggregation` benchmarks): ``` goos: darwin goarch: arm64 pkg: github.com/DataDog/datadog-go/v5/statsd cpu: Apple M4 Max │ master │ HEAD │ │ sec/op │ sec/op vs base │ StatsdUDPSameMetricMutexAggregation-16 248.3n ± 1% 142.3n ± 0% -42.68% (p=0.000 n=10) StatsdUDPSameMetricChannelAggregation-16 252.3n ± 0% 143.8n ± 1% -43.02% (p=0.000 n=10) StatsdUDPDifferentMetricMutexAggregation-16 250.7n ± 1% 148.6n ± 0% -40.71% (p=0.000 n=10) StatsdUDPDifferentMetricChannelAggregation-16 252.5n ± 1% 150.3n ± 0% -40.48% (p=0.000 n=10) StatsdUDSSameMetricMutexAggregation-16 248.9n ± 1% 143.0n ± 1% -42.53% (p=0.000 n=10) StatsdUDSSameMetricChannelAggregation-16 251.9n ± 1% 144.0n ± 1% -42.87% (p=0.000 n=10) StatsdUDPSifferentMetricMutexAggregation-16 252.1n ± 0% 148.8n ± 1% -40.97% (p=0.000 n=10) StatsdUDSDifferentMetricChannelAggregation-16 252.8n ± 1% 149.5n ± 0% -40.85% (p=0.000 n=10) geomean 251.2n 146.3n -41.77% │ master │ HEAD │ │ %_dropRate │ %_dropRate vs base │ StatsdUDPSameMetricMutexAggregation-16 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=10) ¹ StatsdUDPSameMetricChannelAggregation-16 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=10) ¹ StatsdUDPDifferentMetricMutexAggregation-16 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=10) ¹ StatsdUDPDifferentMetricChannelAggregation-16 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=10) ¹ StatsdUDSSameMetricMutexAggregation-16 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=10) ¹ StatsdUDSSameMetricChannelAggregation-16 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=10) ¹ StatsdUDPSifferentMetricMutexAggregation-16 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=10) ¹ StatsdUDSDifferentMetricChannelAggregation-16 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=10) ¹ geomean ² +0.00% ² ¹ all samples are equal ² summaries must be >0 to compute geomean ```
f9627ac to
a834205
Compare
Set CardinalityNotSet to zero to avoid gap between it and CardinalityNone which equals to one.

The change #327 introduced support for tag cardinality with global default value that could be overriden per metric call via parameter.
Default cardinality value is stored in a global variable guarded by a mutex which has two downsides:
This change eliminates global default value and uses default value per statsd client specified during client construction with a fallback to environment variables.
User supplied cardinality value is validated during client construction and during parameter parsing with a fallback to default value such that all internal components can assume they always receive a valid value.
Performance improvement (via
Statsd.*Aggregationbenchmarks):