Skip metrics collect on first pass and more unit tests

This commit is contained in:
Stephen Marshall
2018-05-24 17:10:16 +01:00
parent a4b9a9abaf
commit 4bbdb36da0
3 changed files with 134 additions and 11 deletions

View File

@@ -30,14 +30,16 @@ const (
)
type exporter struct {
qmName string
gaugeMap map[string]*prometheus.GaugeVec
qmName string
gaugeMap map[string]*prometheus.GaugeVec
firstCollect bool
}
func newExporter(qmName string) *exporter {
return &exporter{
qmName: qmName,
gaugeMap: make(map[string]*prometheus.GaugeVec),
qmName: qmName,
gaugeMap: make(map[string]*prometheus.GaugeVec),
firstCollect: true,
}
}
@@ -71,17 +73,24 @@ func (e *exporter) Collect(ch chan<- prometheus.Metric) {
gaugeVec.Reset()
// Populate Prometheus Gauge with metric values
for label, value := range metric.values {
if label == qmgrLabelValue {
gaugeVec.WithLabelValues(e.qmName).Set(value)
} else {
gaugeVec.WithLabelValues(label, e.qmName).Set(value)
// - Skip on first collect to avoid build-up of accumulated values
if !e.firstCollect {
for label, value := range metric.values {
if label == qmgrLabelValue {
gaugeVec.WithLabelValues(e.qmName).Set(value)
} else {
gaugeVec.WithLabelValues(label, e.qmName).Set(value)
}
}
}
// Collect metric
gaugeVec.Collect(ch)
}
if e.firstCollect {
e.firstCollect = false
}
}
// createGaugeVec returns a Prometheus GaugeVec populated with metric details

View File

@@ -17,10 +17,88 @@ package metrics
import (
"testing"
"time"
"github.com/prometheus/client_golang/prometheus"
dto "github.com/prometheus/client_model/go"
)
func TestDescribe(t *testing.T) {
teardownTestCase := setupTestCase()
defer teardownTestCase()
ch := make(chan *prometheus.Desc)
go func() {
exporter := newExporter("qmName")
exporter.Describe(ch)
}()
collect := <-requestChannel
if collect {
t.Errorf("Received unexpected collect request")
}
metrics := initialiseMetrics()
responseChannel <- metrics
select {
case prometheusDesc := <-ch:
expected := "Desc{fqName: \"ibmmq_qmgr_Element1Name\", help: \"Element1Description\", constLabels: {}, variableLabels: [qmgr]}"
actual := prometheusDesc.String()
if actual != expected {
t.Errorf("Expected value=%s; actual %s", expected, actual)
}
case <-time.After(1 * time.Second):
t.Error("Did not receive channel response from describe")
}
}
func TestCollect(t *testing.T) {
teardownTestCase := setupTestCase()
defer teardownTestCase()
exporter := newExporter("qmName")
exporter.gaugeMap["ClassName/Type1Name/Element1Name"] = createGaugeVec("Element1Name", "Element1Description", false)
for i := 1; i <= 3; i++ {
ch := make(chan prometheus.Metric)
go func() {
exporter.Collect(ch)
close(ch)
}()
collect := <-requestChannel
if !collect {
t.Errorf("Received unexpected describe request")
}
populateTestMetrics(i)
metrics := initialiseMetrics()
updateMetrics(metrics)
responseChannel <- metrics
select {
case <-ch:
prometheusMetric := dto.Metric{}
exporter.gaugeMap["ClassName/Type1Name/Element1Name"].WithLabelValues("qmName").Write(&prometheusMetric)
actual := prometheusMetric.GetGauge().GetValue()
if i == 1 {
if actual != float64(0) {
t.Errorf("Expected values to be zero on first collect; actual %f", actual)
}
} else if actual != float64(i) {
t.Errorf("Expected value=%f; actual %f", float64(i), actual)
}
case <-time.After(1 * time.Second):
t.Error("Did not receive channel response from collect")
}
}
}
func TestCreateGaugeVec(t *testing.T) {
ch := make(chan *prometheus.Desc)

View File

@@ -55,6 +55,39 @@ func TestInitialiseMetrics(t *testing.T) {
}
}
func TestUpdateMetrics(t *testing.T) {
teardownTestCase := setupTestCase()
defer teardownTestCase()
metrics := initialiseMetrics()
updateMetrics(metrics)
metric, _ := metrics["ClassName/Type1Name/Element1Name"]
actual, ok := metric.values[qmgrLabelValue]
if !ok {
t.Error("No metric values found for queue manager label")
} else {
if actual != float64(1) {
t.Errorf("Expected metric value=%f; actual %f", float64(1), actual)
}
if len(metric.values) != 1 {
t.Errorf("Expected values-size=%d; actual %d", 1, len(metric.values))
}
}
if len(mqmetric.Metrics.Classes[0].Types[0].Elements[0].Values) != 0 {
t.Error("Unexpected cached value; publication data should have been reset")
}
updateMetrics(metrics)
if len(metric.values) != 0 {
t.Errorf("Unexpected metric value; data should have been cleared")
}
}
func TestMakeKey(t *testing.T) {
teardownTestCase := setupTestCase()
@@ -68,13 +101,13 @@ func TestMakeKey(t *testing.T) {
}
func setupTestCase() func() {
populateTestMetrics()
populateTestMetrics(1)
return func() {
cleanTestMetrics()
}
}
func populateTestMetrics() {
func populateTestMetrics(testValue int) {
metricClass := new(mqmetric.MonClass)
metricType1 := new(mqmetric.MonType)
@@ -87,8 +120,11 @@ func populateTestMetrics() {
metricType2.Name = "Type2Name"
metricElement1.MetricName = "Element1Name"
metricElement1.Description = "Element1Description"
metricElement1.Values = make(map[string]int64)
metricElement1.Values[qmgrLabelValue] = int64(testValue)
metricElement2.MetricName = "Element2Name"
metricElement2.Description = "Element2Description"
metricElement2.Values = make(map[string]int64)
metricType1.ObjectTopic = "ObjectTopic"
metricType2.ObjectTopic = "%s"
metricElement1.Parent = metricType1