-
Notifications
You must be signed in to change notification settings - Fork 183
/
filters.go
111 lines (99 loc) · 3.31 KB
/
filters.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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
package config
import "github.com/signalfx/signalfx-agent/internal/core/dpfilters"
// MetricFilter describes a set of subtractive filters applied to datapoints
// right before they are sent.
type MetricFilter struct {
// A map of dimension key/values to match against. All key/values must
// match a datapoint for it to be matched.
Dimensions map[string]string `yaml:"dimensions" default:"{}"`
// A list of metric names to match against, OR'd together
MetricNames []string `yaml:"metricNames"`
// A single metric name to match against
MetricName string `yaml:"metricName"`
// (**Only applicable for the top level filters**) Limits this scope of the
// filter to datapoints from a specific monitor. If specified, any
// datapoints not from this monitor type will never match against this
// filter.
MonitorType string `yaml:"monitorType"`
// Negates the result of the match so that it matches all datapoints that
// do NOT match the metric name and dimension values given. This does not
// negate monitorType, if given.
Negated bool `yaml:"negated"`
}
// MakeFilter returns an actual filter instance from the config
func (mf *MetricFilter) MakeFilter() (dpfilters.DatapointFilter, error) {
if mf.MetricName != "" {
mf.MetricNames = append(mf.MetricNames, mf.MetricName)
}
return dpfilters.New(mf.MonitorType, mf.MetricNames, mf.Dimensions, mf.Negated)
}
func makeFilterSet(excludes []MetricFilter, includes []MetricFilter) (*dpfilters.FilterSet, error) {
excludeSet := make([]dpfilters.DatapointFilter, 0)
includeSet := make([]dpfilters.DatapointFilter, 0)
mtes := make([]MetricFilter, 0, len(excludes))
mtis := make([]MetricFilter, 0, len(includes))
for _, mte := range excludes {
mtes = AddOrMerge(mtes, mte)
}
for _, mti := range includes {
mtis = AddOrMerge(mtis, mti)
}
for _, mte := range mtes {
f, err := mte.MakeFilter()
if err != nil {
return nil, err
}
excludeSet = append(excludeSet, f)
}
for _, mti := range mtis {
f, err := mti.MakeFilter()
if err != nil {
return nil, err
}
includeSet = append(includeSet, f)
}
return &dpfilters.FilterSet{
ExcludeFilters: excludeSet,
IncludeFilters: includeSet,
}, nil
}
// AddOrMerge MetricFilter to list or merge with existing MetricFilter
func AddOrMerge(mtes []MetricFilter, mf2 MetricFilter) []MetricFilter {
for i, mf1 := range mtes {
if mf1.ShouldMerge(mf2) {
mtes[i] = mf1.MergeWith(mf2)
return mtes
}
}
return append(mtes, mf2)
}
// MergeWith merges mf2's MetricFilter.MetricNames into receiver mf MetricFilter.MetricNames
func (mf *MetricFilter) MergeWith(mf2 MetricFilter) MetricFilter {
if mf2.MetricName != "" {
mf2.MetricNames = append(mf2.MetricNames, mf2.MetricName)
}
for _, metricName := range mf2.MetricNames {
mf.MetricNames = append(mf.MetricNames, metricName)
}
return *mf
}
// ShouldMerge checks if mf2 MetricFilter should be merged into receiver mf MetricFilter
// Filters with same monitorType, negation, and dimensions should be merged
func (mf *MetricFilter) ShouldMerge(mf2 MetricFilter) bool {
if mf.MonitorType != mf2.MonitorType {
return false
}
if mf.Negated != mf2.Negated {
return false
}
if len(mf.Dimensions) != len(mf2.Dimensions) {
return false
}
// Ensure no differing dimension values
for k, v := range mf.Dimensions {
if mf2.Dimensions[k] != v {
return false
}
}
return true
}