forked from open-telemetry/opentelemetry-go
/
view.go
95 lines (87 loc) · 3.35 KB
/
view.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
// 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 (
"regexp"
"strings"
"go.opentelemetry.io/otel/internal/global"
"go.opentelemetry.io/otel/sdk/metric/aggregation"
)
// 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.
//
// 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 "*" will match
// 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 returned Stream
// and no Aggregation or AttributeFilter are set. If mask has a non-zero-value
// value for any of the Aggregation or AttributeFilter fields, or any of the
// Instrument fields, that value is 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() {
return func(Instrument) (Stream, bool) { return Stream{}, false }
}
var matchFunc func(Instrument) bool
if strings.ContainsAny(criteria.Name, "*?") {
pattern := regexp.QuoteMeta(criteria.Name)
pattern = "^" + pattern + "$"
pattern = strings.ReplaceAll(pattern, "\\?", ".")
pattern = strings.ReplaceAll(pattern, "\\*", ".*")
re := regexp.MustCompile(pattern)
matchFunc = func(p Instrument) bool {
return re.MatchString(p.Name) &&
criteria.matchesDescription(p) &&
criteria.matchesKind(p) &&
criteria.matchesUnit(p) &&
criteria.matchesScope(p)
}
} else {
matchFunc = criteria.matches
}
var agg aggregation.Aggregation
if mask.Aggregation != nil {
agg = mask.Aggregation.Copy()
if err := agg.Err(); err != nil {
global.Error(
err, "not using aggregation with view",
"aggregation", agg,
"view", criteria,
)
agg = nil
}
}
return func(p Instrument) (Stream, bool) {
if matchFunc(p) {
stream := Stream{
Instrument: p.mask(mask.Instrument),
Aggregation: agg,
AttributeFilter: mask.AttributeFilter,
}
return stream, true
}
return Stream{}, false
}
}