This repository has been archived by the owner on Aug 23, 2023. It is now read-only.
/
meta_tag_record.go
128 lines (102 loc) · 3.34 KB
/
meta_tag_record.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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
package tagquery
import (
"github.com/grafana/metrictank/errors"
"github.com/grafana/metrictank/schema"
)
type MetaTagRecord struct {
MetaTags Tags `json:"metaTags"`
Expressions Expressions `json:"expressions"`
}
func ParseMetaTagRecord(metaTags []string, expressions []string) (MetaTagRecord, error) {
res := MetaTagRecord{}
var err error
res.MetaTags, err = ParseTags(metaTags)
if err != nil {
return res, err
}
res.Expressions, err = ParseExpressions(expressions)
if err != nil {
return res, err
}
// we don't actually need to instantiate a query at this point, but we want to verify
// that it is possible to instantiate a query from the given meta record expressions.
// if we can't instantiate a query from the given expressions, then the meta record
// upsert request should be considered invalid and should get rejected.
_, err = NewQuery(res.Expressions, 0)
if err != nil {
return res, errors.NewBadRequestf("Failed to instantiate query from given expressions: %s", err)
}
if len(res.Expressions) == 0 {
return res, errors.NewBadRequestf("Meta Tag Record must have at least one query")
}
return res, nil
}
// Equals takes another MetaTagRecord and compares all its properties to its
// own properties. It is assumed that the expressions of both meta tag records
// are already sorted.
func (m *MetaTagRecord) Equals(other *MetaTagRecord) bool {
if len(m.MetaTags) != len(other.MetaTags) {
return false
}
for i := range m.MetaTags {
if m.MetaTags[i] != other.MetaTags[i] {
return false
}
}
return m.Expressions.Equal(other.Expressions)
}
// HashExpressions returns a hash of all expressions in this meta tag record
// It is assumed that the expressions are already sorted
func (m *MetaTagRecord) HashExpressions() uint32 {
h := QueryHash()
for _, expression := range m.Expressions {
expression.StringIntoWriter(h)
// trailing ";" doesn't matter, this is only hash input
h.WriteString(";")
}
return h.Sum32()
}
// HashMetaTags returns a hash of all meta tags in this meta tag record
// It is assumed that the meta tags are already sorted
func (m *MetaTagRecord) HashMetaTags() uint32 {
h := QueryHash()
for _, metaTag := range m.MetaTags {
metaTag.StringIntoWriter(h)
// trailing ";" doesn't matter, this is only hash input
h.WriteString(";")
}
return h.Sum32()
}
func (m *MetaTagRecord) HashRecord() uint64 {
expressionsHash := m.HashExpressions()
metaTagHash := m.HashMetaTags()
return uint64(expressionsHash) | uint64(metaTagHash)<<32
}
// HasMetaTags returns true if the meta tag record has one or more
// meta tags, otherwise it returns false
func (m *MetaTagRecord) HasMetaTags() bool {
return len(m.MetaTags) > 0
}
func (m *MetaTagRecord) GetMetricDefinitionFilter(lookup IdTagLookup) MetricDefinitionFilter {
filters := make([]MetricDefinitionFilter, len(m.Expressions))
defaultDecisions := make([]FilterDecision, len(m.Expressions))
for i, expr := range m.Expressions {
filters[i] = expr.GetMetricDefinitionFilter(lookup)
defaultDecisions[i] = expr.GetDefaultDecision()
}
return func(id schema.MKey, name string, tags []string) FilterDecision {
for i := range filters {
decision := filters[i](id, name, tags)
if decision == None {
return defaultDecisions[i]
}
if decision == Pass {
continue
}
if decision == Fail {
return Fail
}
}
return Pass
}
}