summaryrefslogtreecommitdiff
path: root/vendor/go.opentelemetry.io/otel/sdk/metric/view.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/go.opentelemetry.io/otel/sdk/metric/view.go')
-rw-r--r--vendor/go.opentelemetry.io/otel/sdk/metric/view.go128
1 files changed, 128 insertions, 0 deletions
diff --git a/vendor/go.opentelemetry.io/otel/sdk/metric/view.go b/vendor/go.opentelemetry.io/otel/sdk/metric/view.go
new file mode 100644
index 000000000..65f243bef
--- /dev/null
+++ b/vendor/go.opentelemetry.io/otel/sdk/metric/view.go
@@ -0,0 +1,128 @@
+// 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 metric // import "go.opentelemetry.io/otel/sdk/metric"
+
+import (
+ "errors"
+ "regexp"
+ "strings"
+
+ "go.opentelemetry.io/otel/internal/global"
+)
+
+var (
+ errMultiInst = errors.New("name replacement for multiple instruments")
+ errEmptyView = errors.New("no criteria provided for view")
+
+ emptyView = func(Instrument) (Stream, bool) { return Stream{}, false }
+)
+
+// View is an override to the default behavior of the SDK. It defines how data
+// should be collected for certain instruments. It returns true and the exact
+// Stream to use for matching Instruments. Otherwise, if the view does not
+// match, false is returned.
+type View func(Instrument) (Stream, bool)
+
+// NewView returns a View that applies the Stream mask for all instruments that
+// match criteria. The returned View will only apply mask if all non-zero-value
+// fields of criteria match the corresponding Instrument passed to the view. If
+// no criteria are provided, all field of criteria are their zero-values, a
+// view that matches no instruments is returned. If you need to match a
+// zero-value field, create a View directly.
+//
+// The Name field of criteria supports wildcard pattern matching. The "*"
+// wildcard is recognized as matching zero or more characters, and "?" is
+// recognized as matching exactly one character. For example, a pattern of "*"
+// matches all instrument names.
+//
+// The Stream mask only applies updates for non-zero-value fields. By default,
+// the Instrument the View matches against will be use for the Name,
+// Description, and Unit of the returned Stream and no Aggregation or
+// AttributeFilter are set. All non-zero-value fields of mask are used instead
+// of the default. If you need to zero out an Stream field returned from a
+// View, create a View directly.
+func NewView(criteria Instrument, mask Stream) View {
+ if criteria.empty() {
+ global.Error(
+ errEmptyView, "dropping view",
+ "mask", mask,
+ )
+ return emptyView
+ }
+
+ var matchFunc func(Instrument) bool
+ if strings.ContainsAny(criteria.Name, "*?") {
+ if mask.Name != "" {
+ global.Error(
+ errMultiInst, "dropping view",
+ "criteria", criteria,
+ "mask", mask,
+ )
+ return emptyView
+ }
+
+ // Handle branching here in NewView instead of criteria.matches so
+ // criteria.matches remains inlinable for the simple case.
+ pattern := regexp.QuoteMeta(criteria.Name)
+ pattern = "^" + pattern + "$"
+ pattern = strings.ReplaceAll(pattern, `\?`, ".")
+ pattern = strings.ReplaceAll(pattern, `\*`, ".*")
+ re := regexp.MustCompile(pattern)
+ matchFunc = func(i Instrument) bool {
+ return re.MatchString(i.Name) &&
+ criteria.matchesDescription(i) &&
+ criteria.matchesKind(i) &&
+ criteria.matchesUnit(i) &&
+ criteria.matchesScope(i)
+ }
+ } else {
+ matchFunc = criteria.matches
+ }
+
+ var agg Aggregation
+ if mask.Aggregation != nil {
+ agg = mask.Aggregation.copy()
+ if err := agg.err(); err != nil {
+ global.Error(
+ err, "not using aggregation with view",
+ "criteria", criteria,
+ "mask", mask,
+ )
+ agg = nil
+ }
+ }
+
+ return func(i Instrument) (Stream, bool) {
+ if matchFunc(i) {
+ return Stream{
+ Name: nonZero(mask.Name, i.Name),
+ Description: nonZero(mask.Description, i.Description),
+ Unit: nonZero(mask.Unit, i.Unit),
+ Aggregation: agg,
+ AttributeFilter: mask.AttributeFilter,
+ }, true
+ }
+ return Stream{}, false
+ }
+}
+
+// nonZero returns v if it is non-zero-valued, otherwise alt.
+func nonZero[T comparable](v, alt T) T {
+ var zero T
+ if v != zero {
+ return v
+ }
+ return alt
+}