Skip to content

Commit 1141a76

Browse files
committed
feat: flag to enable gauge replacement
1 parent b2868dd commit 1141a76

File tree

6 files changed

+36
-10
lines changed

6 files changed

+36
-10
lines changed

cmd/root.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ func Execute() {
2626
rootCmd.PersistentFlags().StringVar(&cfg.ApiListen, "apiListen", ":80", "Listen for API requests on this host/port.")
2727
rootCmd.PersistentFlags().StringVar(&cfg.LifecycleListen, "lifecycleListen", ":8888", "Listen for lifecycle requests (health, metrics) on this host/port")
2828
rootCmd.PersistentFlags().StringVar(&cfg.CorsDomain, "cors", "*", "The 'Access-Control-Allow-Origin' value to be returned.")
29+
rootCmd.PersistentFlags().StringVar(&cfg.GaugeBehavior, "gaugeBehavior", "sum", "How gauges are aggregated.")
2930

3031
if err := rootCmd.Execute(); err != nil {
3132
os.Exit(1)

cmd/start.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ func startFunc(cmd *cobra.Command, args []string) error {
2323
Accounts: cfg.AuthUsers,
2424
}
2525

26-
routers.RunServers(apiCfg, cfg.ApiListen, cfg.LifecycleListen)
26+
routers.RunServers(apiCfg, cfg.ApiListen, cfg.LifecycleListen, cfg.GaugeBehavior)
2727

2828
return nil
2929
}

config/config.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ type Server struct {
2020
LifecycleListen string
2121
CorsDomain string
2222
AuthUsers []string
23+
GaugeBehavior string
2324
}
2425

2526
const (

metrics/aggregate.go

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ import (
1717

1818
type metricFamily struct {
1919
*dto.MetricFamily
20-
lock sync.RWMutex
20+
lock sync.RWMutex
21+
options *aggregateOptions
2122
}
2223

2324
type Aggregate struct {
@@ -28,9 +29,17 @@ type Aggregate struct {
2829

2930
type ignoredLabels []string
3031

32+
type gaugeBehavior string
33+
34+
const (
35+
sumBehavior gaugeBehavior = "sum"
36+
replaceBehavior = "replace"
37+
)
38+
3139
type aggregateOptions struct {
3240
ignoredLabels ignoredLabels
3341
metricTTLDuration *time.Duration
42+
gaugeBehavior gaugeBehavior
3443
}
3544

3645
type aggregateOptionsFunc func(a *Aggregate)
@@ -47,6 +56,16 @@ func SetTTLMetricTime(duration *time.Duration) aggregateOptionsFunc {
4756
}
4857
}
4958

59+
func SetGaugeBehavior(behavior string) aggregateOptionsFunc {
60+
return func(a *Aggregate) {
61+
if behavior == replaceBehavior {
62+
a.options.gaugeBehavior = replaceBehavior
63+
} else {
64+
a.options.gaugeBehavior = sumBehavior
65+
}
66+
}
67+
}
68+
5069
func NewAggregate(opts ...aggregateOptionsFunc) *Aggregate {
5170
a := &Aggregate{
5271
families: map[string]*metricFamily{},
@@ -91,7 +110,7 @@ func (a *Aggregate) setFamilyOrGetExistingFamily(familyName string, family *dto.
91110
defer a.familiesLock.Unlock()
92111
existingFamily, ok := a.families[familyName]
93112
if !ok {
94-
a.families[familyName] = &metricFamily{MetricFamily: family}
113+
a.families[familyName] = &metricFamily{MetricFamily: family, options: &a.options}
95114
return nil
96115
}
97116
return existingFamily

metrics/merge.go

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ func mergeBuckets(a, b []*dto.Bucket) []*dto.Bucket {
7171
return output
7272
}
7373

74-
func mergeMetric(ty dto.MetricType, a, b *dto.Metric) *dto.Metric {
74+
func mergeMetric(ty dto.MetricType, a, b *dto.Metric, options *aggregateOptions) *dto.Metric {
7575
switch ty {
7676
case dto.MetricType_COUNTER:
7777
return &dto.Metric{
@@ -82,9 +82,14 @@ func mergeMetric(ty dto.MetricType, a, b *dto.Metric) *dto.Metric {
8282
}
8383

8484
case dto.MetricType_GAUGE:
85-
// No very meaningful way for us to merge gauges. We'll sum them
86-
// and clear out any gauges on scrape, as a best approximation, but
87-
// this relies on client pushing with the same interval as we scrape.
85+
if options.gaugeBehavior == replaceBehavior {
86+
return &dto.Metric{
87+
Label: a.Label,
88+
Gauge: &dto.Gauge{
89+
Value: float64ptr(*b.Gauge.Value),
90+
},
91+
}
92+
}
8893
return &dto.Metric{
8994
Label: a.Label,
9095
Gauge: &dto.Gauge{
@@ -143,7 +148,7 @@ func (mf *metricFamily) mergeFamily(b *dto.MetricFamily) error {
143148
newMetric = append(newMetric, b.Metric[j])
144149
j++
145150
} else {
146-
merged := mergeMetric(*mf.Type, mf.Metric[i], b.Metric[j])
151+
merged := mergeMetric(*mf.Type, mf.Metric[i], b.Metric[j], mf.options)
147152
if merged != nil {
148153
newMetric = append(newMetric, merged)
149154
}

routers/server.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,11 @@ import (
1111
"github.com/zapier/prom-aggregation-gateway/metrics"
1212
)
1313

14-
func RunServers(cfg ApiRouterConfig, apiListen string, lifecycleListen string) {
14+
func RunServers(cfg ApiRouterConfig, apiListen string, lifecycleListen string, gaugeBehavior string) {
1515
sigChannel := make(chan os.Signal, 1)
1616
signal.Notify(sigChannel, syscall.SIGTERM, syscall.SIGINT)
1717

18-
agg := metrics.NewAggregate()
18+
agg := metrics.NewAggregate(metrics.SetGaugeBehavior(gaugeBehavior))
1919

2020
promMetricsConfig := promMetrics.Config{
2121
Registry: metrics.PromRegistry,

0 commit comments

Comments
 (0)