Skip to content

Commit

Permalink
Refactor big metric file into multiple files (#20)
Browse files Browse the repository at this point in the history
  • Loading branch information
Emil Ingerslev authored Apr 28, 2020
1 parent d96c60b commit d5811fe
Show file tree
Hide file tree
Showing 7 changed files with 498 additions and 402 deletions.
79 changes: 79 additions & 0 deletions internal/metrics/daemon.go
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()
},
}
}
100 changes: 100 additions & 0 deletions internal/metrics/helpers.go
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
}
209 changes: 209 additions & 0 deletions internal/metrics/ikesa.go
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)
}
Loading

0 comments on commit d5811fe

Please sign in to comment.