-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Refactor big metric file into multiple files (#20)
- Loading branch information
Emil Ingerslev
authored
Apr 28, 2020
1 parent
d96c60b
commit d5811fe
Showing
7 changed files
with
498 additions
and
402 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
package metrics | ||
|
||
import ( | ||
"time" | ||
|
||
daemonpkg "github.com/lunarway/strong-duckling/internal/daemon" | ||
"github.com/prometheus/client_golang/prometheus" | ||
"github.com/prometheus/common/log" | ||
) | ||
|
||
const ( | ||
subSystemDaemon = "daemon" | ||
) | ||
|
||
type daemon struct { | ||
logger log.Logger | ||
|
||
started *prometheus.CounterVec | ||
stopped *prometheus.CounterVec | ||
skipped *prometheus.CounterVec | ||
ticked *prometheus.CounterVec | ||
} | ||
|
||
func newDaemon() *daemon { | ||
return &daemon{ | ||
started: prometheus.NewCounterVec(prometheus.CounterOpts{ | ||
Namespace: namespace, | ||
Subsystem: subSystemDaemon, | ||
Name: "starts_total", | ||
Help: "Total number of times started", | ||
}, []string{"name", "interval"}), | ||
stopped: prometheus.NewCounterVec(prometheus.CounterOpts{ | ||
Namespace: namespace, | ||
Subsystem: subSystemDaemon, | ||
Name: "stops_total", | ||
Help: "Total number of times stopped", | ||
}, []string{"name"}), | ||
skipped: prometheus.NewCounterVec(prometheus.CounterOpts{ | ||
Namespace: namespace, | ||
Subsystem: subSystemDaemon, | ||
Name: "skips_total", | ||
Help: "Total number of times tick was skipped", | ||
}, []string{"name"}), | ||
ticked: prometheus.NewCounterVec(prometheus.CounterOpts{ | ||
Namespace: namespace, | ||
Subsystem: subSystemDaemon, | ||
Name: "ticks_total", | ||
Help: "Total number of times tick was invoked", | ||
}, []string{"name"}), | ||
} | ||
} | ||
|
||
func (d *daemon) getCollectors() []prometheus.Collector { | ||
return []prometheus.Collector{ | ||
d.started, | ||
d.stopped, | ||
d.skipped, | ||
d.ticked, | ||
} | ||
} | ||
|
||
func (d *daemon) DefaultDaemonReporter(logger log.Logger, name string) *daemonpkg.Reporter { | ||
return &daemonpkg.Reporter{ | ||
Started: func(duration time.Duration) { | ||
logger.With("state", "started").Infof("%s daemon started with interval %v", name, duration) | ||
d.started.WithLabelValues(name, duration.String()).Inc() | ||
}, | ||
Stopped: func() { | ||
logger.With("state", "stopped").Infof("%s daemon stopped", name) | ||
d.stopped.WithLabelValues(name).Inc() | ||
}, | ||
Skipped: func() { | ||
d.skipped.WithLabelValues(name).Inc() | ||
}, | ||
Ticked: func() { | ||
d.ticked.WithLabelValues(name).Inc() | ||
}, | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
package metrics | ||
|
||
import ( | ||
"strconv" | ||
|
||
"github.com/prometheus/client_golang/prometheus" | ||
"github.com/prometheus/common/log" | ||
) | ||
|
||
func newHelper(logger log.Logger) *helper { | ||
return &helper{ | ||
previousValues: make(map[string]float64), | ||
logger: logger, | ||
} | ||
} | ||
|
||
type helper struct { | ||
previousValues map[string]float64 | ||
logger log.Logger | ||
} | ||
|
||
func (p *helper) setGauge(g *prometheus.GaugeVec, value, name string, labels childSALabels) { | ||
f, err := strconv.ParseFloat(value, 64) | ||
if err != nil { | ||
p.logger.Errorf("metrics: failed to convert %s '%s' to float64: %v", name, value, err) | ||
return | ||
} | ||
g.WithLabelValues(labels.values()...).Set(f) | ||
} | ||
|
||
func (p *helper) setCounterByMax(c *prometheus.CounterVec, value, name string, labels childSALabels) { | ||
// if this is the first time it is called it should be increased as well | ||
_, ok := p.previousValues[name] | ||
if !ok { | ||
c.WithLabelValues(labels.values()...).Inc() | ||
} | ||
_, ok = p.maxValue(name, value) | ||
if !ok { | ||
return | ||
} | ||
c.WithLabelValues(labels.values()...).Inc() | ||
} | ||
|
||
func (p *helper) setGaugeByMax(g *prometheus.GaugeVec, value, name string, labels ikeSALabels) { | ||
max, ok := p.maxValue(name, value) | ||
if !ok { | ||
return | ||
} | ||
g.WithLabelValues(labels.values()...).Set(max) | ||
} | ||
|
||
func (p *helper) setHistogramByMax(h *prometheus.HistogramVec, value, name string, labels childSALabels) { | ||
max, ok := p.maxValue(name, value) | ||
if !ok { | ||
return | ||
} | ||
h.WithLabelValues(labels.values()...).Observe(max) | ||
} | ||
|
||
func (p *helper) setHistogramByMin(h *prometheus.HistogramVec, value, name string, labels childSALabels) { | ||
min, ok := p.minValue(name, value) | ||
if !ok { | ||
return | ||
} | ||
h.WithLabelValues(labels.values()...).Observe(min) | ||
} | ||
|
||
// maxValue detects the max value of value. If max is detected the returned | ||
// bool is true otherwise it returns the current value. | ||
func (p *helper) maxValue(name, value string) (float64, bool) { | ||
f, err := strconv.ParseFloat(value, 64) | ||
if err != nil { | ||
p.logger.Errorf("metrics: failed to convert %s '%s' to float64: %v", name, value, err) | ||
return 0, false | ||
} | ||
previousValue, ok := p.previousValues[name] | ||
// store the value for future reference when this call finishes | ||
p.previousValues[name] = f | ||
if ok && previousValue > f { | ||
return previousValue, true | ||
} | ||
return f, false | ||
} | ||
|
||
// minValue detects the min value of value. If min is detected the returned | ||
// bool is true otherwise it returns the current value. | ||
func (p *helper) minValue(name, value string) (float64, bool) { | ||
f, err := strconv.ParseFloat(value, 64) | ||
if err != nil { | ||
p.logger.Errorf("metrics: failed to convert %s '%s' to float64: %v", name, value, err) | ||
return 0, false | ||
} | ||
previousValue, ok := p.previousValues[name] | ||
// store the value for future reference when this call finishes | ||
p.previousValues[name] = f | ||
if ok && previousValue < f { | ||
return previousValue, true | ||
} | ||
return f, false | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,209 @@ | ||
package metrics | ||
|
||
import ( | ||
"strings" | ||
"strconv" | ||
|
||
"github.com/prometheus/client_golang/prometheus" | ||
"github.com/lunarway/strong-duckling/internal/vici" | ||
"github.com/prometheus/common/log" | ||
) | ||
|
||
const ( | ||
subSystemIKE = "ike_sa" | ||
) | ||
|
||
|
||
type ikeSA struct { | ||
logger log.Logger | ||
helper *helper | ||
|
||
establishedSeconds *prometheus.GaugeVec | ||
packetsIn *prometheus.GaugeVec | ||
packetsOut *prometheus.GaugeVec | ||
lastPacketInSeconds *prometheus.HistogramVec | ||
lastPacketOutSeconds *prometheus.HistogramVec | ||
bytesIn *prometheus.GaugeVec | ||
bytesOut *prometheus.GaugeVec | ||
installs *prometheus.CounterVec | ||
rekeySeconds *prometheus.HistogramVec | ||
lifeTimeSeconds *prometheus.HistogramVec | ||
state *prometheus.GaugeVec | ||
childSAState *prometheus.GaugeVec | ||
} | ||
|
||
type ikeSALabels struct { | ||
name, localPeerIP, remotePeerIP string | ||
} | ||
|
||
func (i ikeSALabels) names() []string { | ||
return []string{"ike_sa_name", "local_peer_ip", "remote_peer_ip"} | ||
} | ||
|
||
func (i ikeSALabels) values() []string { | ||
return []string{i.name, i.localPeerIP, i.remotePeerIP} | ||
} | ||
|
||
type childSALabels struct { | ||
ikeSALabels | ||
localIPRange, remoteIPRange, childSAName string | ||
} | ||
|
||
func (c childSALabels) names() []string { | ||
return append(c.ikeSALabels.names(), "local_ip_range", "remote_ip_range", "child_sa_name") | ||
} | ||
|
||
func (c childSALabels) values() []string { | ||
return append(c.ikeSALabels.values(), c.localIPRange, c.remoteIPRange, c.childSAName) | ||
} | ||
|
||
func newIkeSA(logger log.Logger) *ikeSA { | ||
return &ikeSA{ | ||
logger: logger, | ||
helper: newHelper(logger), | ||
establishedSeconds: prometheus.NewGaugeVec(prometheus.GaugeOpts{ | ||
Namespace: namespace, | ||
Subsystem: subSystemIKE, | ||
Name: "established_seconds", | ||
Help: "Number of seconds the SA has been established", | ||
}, ikeSALabels{}.names()), | ||
packetsIn: prometheus.NewGaugeVec(prometheus.GaugeOpts{ | ||
Namespace: namespace, | ||
Subsystem: subSystemIKE, | ||
Name: "packets_in_total", | ||
Help: "Total number of received packets", | ||
}, childSALabels{}.names()), | ||
packetsOut: prometheus.NewGaugeVec(prometheus.GaugeOpts{ | ||
Namespace: namespace, | ||
Subsystem: subSystemIKE, | ||
Name: "packets_out_total", | ||
Help: "Total number of transmitted packets", | ||
}, childSALabels{}.names()), | ||
lastPacketInSeconds: prometheus.NewHistogramVec(prometheus.HistogramOpts{ | ||
Namespace: namespace, | ||
Subsystem: subSystemIKE, | ||
Name: "packets_in_silence_duration_seconds", | ||
Help: "Duration of silences between packets in", | ||
Buckets: prometheus.ExponentialBuckets(15, 2, 14), | ||
}, childSALabels{}.names()), | ||
lastPacketOutSeconds: prometheus.NewHistogramVec(prometheus.HistogramOpts{ | ||
Namespace: namespace, | ||
Subsystem: subSystemIKE, | ||
Name: "packets_out_silence_duration_seconds", | ||
Help: "Duration of silences between packets out", | ||
Buckets: prometheus.ExponentialBuckets(15, 2, 14), | ||
}, childSALabels{}.names()), | ||
bytesIn: prometheus.NewGaugeVec(prometheus.GaugeOpts{ | ||
Namespace: namespace, | ||
Subsystem: subSystemIKE, | ||
Name: "bytes_in_total", | ||
Help: "Total number of received bytes", | ||
}, childSALabels{}.names()), | ||
bytesOut: prometheus.NewGaugeVec(prometheus.GaugeOpts{ | ||
Namespace: namespace, | ||
Subsystem: subSystemIKE, | ||
Name: "bytes_out_total", | ||
Help: "Total number of transmitted bytes", | ||
}, childSALabels{}.names()), | ||
installs: prometheus.NewCounterVec(prometheus.CounterOpts{ | ||
Namespace: namespace, | ||
Subsystem: subSystemIKE, | ||
Name: "installs_total", | ||
Help: "Total number of SA installs", | ||
}, childSALabels{}.names()), | ||
rekeySeconds: prometheus.NewHistogramVec(prometheus.HistogramOpts{ | ||
Namespace: namespace, | ||
Subsystem: subSystemIKE, | ||
Name: "rekey_seconds", | ||
Help: "Duration between re-keying", | ||
Buckets: prometheus.ExponentialBuckets(15, 2, 12), | ||
}, childSALabels{}.names()), | ||
lifeTimeSeconds: prometheus.NewHistogramVec(prometheus.HistogramOpts{ | ||
Namespace: namespace, | ||
Subsystem: subSystemIKE, | ||
Name: "lifetime_seconds", | ||
Help: "Duration of each IKE session", | ||
Buckets: prometheus.ExponentialBuckets(15, 2, 14), | ||
}, childSALabels{}.names()), | ||
state: prometheus.NewGaugeVec(prometheus.GaugeOpts{ | ||
Namespace: namespace, | ||
Subsystem: subSystemIKE, | ||
Name: "state_info", | ||
Help: "Current state of the SA", | ||
}, ikeSALabels{}.names()), | ||
childSAState: prometheus.NewGaugeVec(prometheus.GaugeOpts{ | ||
Namespace: namespace, | ||
Subsystem: subSystemIKE, | ||
Name: "child_state_info", | ||
Help: "Current state of the child SA", | ||
}, childSALabels{}.names()), | ||
} | ||
} | ||
|
||
func (i *ikeSA) getCollectors() []prometheus.Collector { | ||
return []prometheus.Collector { | ||
i.establishedSeconds, | ||
i.packetsIn, | ||
i.packetsOut, | ||
i.lastPacketInSeconds, | ||
i.lastPacketOutSeconds, | ||
i.bytesIn, | ||
i.bytesOut, | ||
i.installs, | ||
i.rekeySeconds, | ||
i.lifeTimeSeconds, | ||
i.state, | ||
i.childSAState, | ||
} | ||
} | ||
|
||
func (p *ikeSA) IKESAStatus(ikeName string, conn vici.IKEConf, sa *vici.IkeSa) { | ||
if sa == nil { | ||
p.logger.Errorf("No SA for connecetion configuration: %#v", conn) | ||
return | ||
} | ||
ikeSALabels := ikeSALabels{ | ||
name: ikeName, | ||
localPeerIP: sa.LocalHost, | ||
remotePeerIP: sa.RemoteHost, | ||
} | ||
p.helper.setGaugeByMax(p.establishedSeconds, sa.EstablishedSeconds, "EstablishedSeconds", ikeSALabels) | ||
p.logger.Infof("prometheusReporter: IKESAStatus: IKE_SA state: %v", sa.State) | ||
for _, child := range sa.ChildSAs { | ||
labels := childSALabels{ | ||
ikeSALabels: ikeSALabels, | ||
childSAName: child.Name, | ||
localIPRange: strings.Join(child.LocalTrafficSelectors, ","), | ||
remoteIPRange: strings.Join(child.RemoteTrafficSelectors, ","), | ||
} | ||
p.logger.Infof("prometheusReporter: IKESAStatus: IKE_SA child state: %v", child.State) | ||
p.helper.setCounterByMax(p.installs, child.InstallTimeSeconds, "InstallTimeSeconds", labels) | ||
p.helper.setGauge(p.packetsIn, child.PacketsIn, "PacketsIn", labels) | ||
p.helper.setGauge(p.packetsOut, child.PacketsOut, "PacketsOut", labels) | ||
p.helper.setGauge(p.bytesIn, child.BytesIn, "BytesIn", labels) | ||
p.helper.setGauge(p.bytesOut, child.BytesOut, "BytesOut", labels) | ||
p.helper.setHistogramByMax(p.lastPacketInSeconds, child.LastPacketInSeconds, "LastPacketInSeconds", labels) | ||
p.helper.setHistogramByMax(p.lastPacketOutSeconds, child.LastPacketOutSeconds, "LastPacketOutSeconds", labels) | ||
p.helper.setHistogramByMin(p.rekeySeconds, child.RekeyTimeSeconds, "RekeyTimeSeconds", labels) | ||
p.helper.setHistogramByMax(p.lifeTimeSeconds, child.LifeTimeSeconds, "LifeTimeSeconds", labels) | ||
p.setRekeySeconds(conn, child, labels) | ||
} | ||
} | ||
|
||
func (p *ikeSA) setRekeySeconds(conn vici.IKEConf, child vici.ChildSA, labels childSALabels) { | ||
// RekeyTimeSeconds on the conn conf is the start value and on the child the | ||
// time left from this value. We want to track how long each rekey session | ||
// was, ie. the ellapsed time from max to when it increases again. This is | ||
// done by finding a min value on the child field and subtracting that from | ||
// the max value on the conf. | ||
minRekeyTimeSeconds, ok := p.helper.minValue("RekeyTimeSeconds", child.RekeyTimeSeconds) | ||
if !ok { | ||
return | ||
} | ||
connRekeyTimeSeconds, err := strconv.ParseFloat(conn.RekeyTimeSeconds, 64) | ||
if err != nil { | ||
p.logger.Errorf("metrics: failed to convert RekeyTimeSeconds '%s' to float64: %v", conn.RekeyTimeSeconds, err) | ||
return | ||
} | ||
p.rekeySeconds.WithLabelValues(labels.values()...).Observe(connRekeyTimeSeconds - minRekeyTimeSeconds) | ||
} |
Oops, something went wrong.