1
0
mirror of https://github.com/open-telemetry/opentelemetry-go.git synced 2024-12-12 10:04:29 +02:00
opentelemetry-go/sdk/metric/internal/aggregate/limit.go
Tyler Yahn e3bf787c21
Add cardinality limiting to the metric SDK as an experimental feature (#4457)
* Add agg limiting func

* Add unit test for limitAttr

* Add limiting to aggregate types

* Add internal x pkg for experimental feature-flagging

* Connect cardinality limit to metric SDK

* Replace limitAttr fn with limiter type

The Attribute method is still inlinable.

* Use x.CardinalityLimit directly

* Simplify limiter test

* Add limiter benchmark

* Document the AggregationLimit field

* Test sum limits

* Test limit for last value

* Test histogram limit

* Refactor expo hist test to use existing fixtures

The tests for the exponential histogram create their own testing
fixtures. There is nothing these new fixtures do that cannot already be
done with the existing testing fixtures used by all the other aggregate
functions. Unify the exponential histogram testing to use the existing
fixtures.

* Test the ExponentialHistogram limit

* Fix lint

* Add docs

* Rename aggregation field to aggLimit

---------

Co-authored-by: Robert Pająk <pellared@hotmail.com>
2023-12-19 07:53:01 -08:00

54 lines
2.1 KiB
Go

// Copyright The OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package aggregate // import "go.opentelemetry.io/otel/sdk/metric/internal/aggregate"
import "go.opentelemetry.io/otel/attribute"
// overflowSet is the attribute set used to record a measurement when adding
// another distinct attribute set to the aggregate would exceed the aggregate
// limit.
var overflowSet = attribute.NewSet(attribute.Bool("otel.metric.overflow", true))
// limiter limits aggregate values.
type limiter[V any] struct {
// aggLimit is the maximum number of metric streams that can be aggregated.
//
// Any metric stream with attributes distinct from any set already
// aggregated once the aggLimit will be meet will instead be aggregated
// into an "overflow" metric stream. That stream will only contain the
// "otel.metric.overflow"=true attribute.
aggLimit int
}
// newLimiter returns a new Limiter with the provided aggregation limit.
func newLimiter[V any](aggregation int) limiter[V] {
return limiter[V]{aggLimit: aggregation}
}
// Attributes checks if adding a measurement for attrs will exceed the
// aggregation cardinality limit for the existing measurements. If it will,
// overflowSet is returned. Otherwise, if it will not exceed the limit, or the
// limit is not set (limit <= 0), attr is returned.
func (l limiter[V]) Attributes(attrs attribute.Set, measurements map[attribute.Set]V) attribute.Set {
if l.aggLimit > 0 {
_, exists := measurements[attrs]
if !exists && len(measurements) >= l.aggLimit-1 {
return overflowSet
}
}
return attrs
}