-
Notifications
You must be signed in to change notification settings - Fork 1.2k
/
context_resolver.go
87 lines (72 loc) · 2.93 KB
/
context_resolver.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
// Unless explicitly stated otherwise all files in this repository are licensed
// under the Apache License Version 2.0.
// This product includes software developed at Datadog (https://www.datadoghq.com/).
// Copyright 2016-2020 Datadog, Inc.
package aggregator
import (
"fmt"
"github.com/DataDog/datadog-agent/pkg/aggregator/ckey"
"github.com/DataDog/datadog-agent/pkg/metrics"
)
// Context holds the elements that form a context, and can be serialized into a context key
type Context struct {
Name string
Tags []string
Host string
}
// ContextResolver allows tracking and expiring contexts
type ContextResolver struct {
contextsByKey map[ckey.ContextKey]*Context
lastSeenByKey map[ckey.ContextKey]float64
keyGenerator *ckey.KeyGenerator
}
// generateContextKey generates the contextKey associated with the context of the metricSample
func (cr *ContextResolver) generateContextKey(metricSampleContext metrics.MetricSampleContext) ckey.ContextKey {
return cr.keyGenerator.Generate(metricSampleContext.GetName(), metricSampleContext.GetHost(), metricSampleContext.GetTags())
}
func newContextResolver() *ContextResolver {
return &ContextResolver{
contextsByKey: make(map[ckey.ContextKey]*Context),
lastSeenByKey: make(map[ckey.ContextKey]float64),
keyGenerator: ckey.NewKeyGenerator(),
}
}
// trackContext returns the contextKey associated with the context of the metricSample and tracks that context
func (cr *ContextResolver) trackContext(metricSampleContext metrics.MetricSampleContext, currentTimestamp float64) ckey.ContextKey {
contextKey := cr.generateContextKey(metricSampleContext)
if _, ok := cr.contextsByKey[contextKey]; !ok {
cr.contextsByKey[contextKey] = &Context{
Name: metricSampleContext.GetName(),
Tags: metricSampleContext.GetTags(),
Host: metricSampleContext.GetHost(),
}
}
cr.lastSeenByKey[contextKey] = currentTimestamp
return contextKey
}
// updateTrackedContext updates the last seen timestamp on a given context key
func (cr *ContextResolver) updateTrackedContext(contextKey ckey.ContextKey, timestamp float64) error {
if _, ok := cr.lastSeenByKey[contextKey]; ok && cr.lastSeenByKey[contextKey] < timestamp {
cr.lastSeenByKey[contextKey] = timestamp
} else if !ok {
return fmt.Errorf("Trying to update a context that is not tracked")
}
return nil
}
// expireContexts cleans up the contexts that haven't been tracked since the given timestamp
// and returns the associated contextKeys
func (cr *ContextResolver) expireContexts(expireTimestamp float64) []ckey.ContextKey {
var expiredContextKeys []ckey.ContextKey
// Find expired context keys
for contextKey, lastSeen := range cr.lastSeenByKey {
if lastSeen < expireTimestamp {
expiredContextKeys = append(expiredContextKeys, contextKey)
}
}
// Delete expired context keys
for _, expiredContextKey := range expiredContextKeys {
delete(cr.contextsByKey, expiredContextKey)
delete(cr.lastSeenByKey, expiredContextKey)
}
return expiredContextKeys
}