diff --git a/internal/metrics/exporter.go b/internal/metrics/exporter.go index 241c97e..9c06cd9 100644 --- a/internal/metrics/exporter.go +++ b/internal/metrics/exporter.go @@ -33,6 +33,7 @@ const ( type exporter struct { qmName string gaugeMap map[string]*prometheus.GaugeVec + counterMap map[string]*prometheus.CounterVec firstCollect bool log *logger.Logger } @@ -41,6 +42,7 @@ func newExporter(qmName string, log *logger.Logger) *exporter { return &exporter{ qmName: qmName, gaugeMap: make(map[string]*prometheus.GaugeVec), + counterMap: make(map[string]*prometheus.CounterVec), firstCollect: true, log: log, } @@ -54,12 +56,22 @@ func (e *exporter) Describe(ch chan<- *prometheus.Desc) { for key, metric := range response { - // Allocate a Prometheus Gauge for each available metric - gaugeVec := createGaugeVec(metric.name, metric.description, metric.objectType) - e.gaugeMap[key] = gaugeVec + if metric.isDelta { + // For delta type metrics - allocate a Prometheus Counter + counterVec := createCounterVec(metric.name, metric.description, metric.objectType) + e.counterMap[key] = counterVec - // Describe metric - gaugeVec.Describe(ch) + // Describe metric + counterVec.Describe(ch) + + } else { + // For non-delta type metrics - allocate a Prometheus Gauge + gaugeVec := createGaugeVec(metric.name, metric.description, metric.objectType) + e.gaugeMap[key] = gaugeVec + + // Describe metric + gaugeVec.Describe(ch) + } } } @@ -71,32 +83,61 @@ func (e *exporter) Collect(ch chan<- prometheus.Metric) { for key, metric := range response { - // Reset Prometheus Gauge - gaugeVec := e.gaugeMap[key] - gaugeVec.Reset() + if metric.isDelta { + // For delta type metrics - update their Prometheus Counter + counterVec := e.counterMap[key] - // Populate Prometheus Gauge with metric values - // - Skip on first collect to avoid build-up of accumulated values - if !e.firstCollect { - for label, value := range metric.values { - var err error - var gauge prometheus.Gauge + // Populate Prometheus Counter with metric values + // - Skip on first collect to avoid build-up of accumulated values + if !e.firstCollect { + for label, value := range metric.values { + var err error + var counter prometheus.Counter - if label == qmgrLabelValue { - gauge, err = gaugeVec.GetMetricWithLabelValues(e.qmName) - } else { - gauge, err = gaugeVec.GetMetricWithLabelValues(label, e.qmName) - } - if err == nil { - gauge.Set(value) - } else { - e.log.Errorf("Metrics Error: %s", err.Error()) + if label == qmgrLabelValue { + counter, err = counterVec.GetMetricWithLabelValues(e.qmName) + } else { + counter, err = counterVec.GetMetricWithLabelValues(label, e.qmName) + } + if err == nil { + counter.Add(value) + } else { + e.log.Errorf("Metrics Error: %s", err.Error()) + } } } - } - // Collect metric - gaugeVec.Collect(ch) + // Collect metric + counterVec.Collect(ch) + + } else { + // For non-delta type metrics - reset their Prometheus Gauge + gaugeVec := e.gaugeMap[key] + gaugeVec.Reset() + + // Populate Prometheus Gauge with metric values + // - Skip on first collect to avoid build-up of accumulated values + if !e.firstCollect { + for label, value := range metric.values { + var err error + var gauge prometheus.Gauge + + if label == qmgrLabelValue { + gauge, err = gaugeVec.GetMetricWithLabelValues(e.qmName) + } else { + gauge, err = gaugeVec.GetMetricWithLabelValues(label, e.qmName) + } + if err == nil { + gauge.Set(value) + } else { + e.log.Errorf("Metrics Error: %s", err.Error()) + } + } + } + + // Collect metric + gaugeVec.Collect(ch) + } } if e.firstCollect { @@ -104,16 +145,26 @@ func (e *exporter) Collect(ch chan<- prometheus.Metric) { } } +// createCounterVec returns a Prometheus CounterVec populated with metric details +func createCounterVec(name, description string, objectType bool) *prometheus.CounterVec { + + prefix, labels := getVecDetails(objectType) + + counterVec := prometheus.NewCounterVec( + prometheus.CounterOpts{ + Namespace: namespace, + Name: prefix + "_" + name, + Help: description, + }, + labels, + ) + return counterVec +} + // createGaugeVec returns a Prometheus GaugeVec populated with metric details func createGaugeVec(name, description string, objectType bool) *prometheus.GaugeVec { - prefix := qmgrPrefix - labels := []string{qmgrLabel} - - if objectType { - prefix = objectPrefix - labels = []string{objectLabel, qmgrLabel} - } + prefix, labels := getVecDetails(objectType) gaugeVec := prometheus.NewGaugeVec( prometheus.GaugeOpts{ @@ -125,3 +176,16 @@ func createGaugeVec(name, description string, objectType bool) *prometheus.Gauge ) return gaugeVec } + +// getVecDetails returns the required prefix and labels for a metric +func getVecDetails(objectType bool) (prefix string, labels []string) { + + prefix = qmgrPrefix + labels = []string{qmgrLabel} + + if objectType { + prefix = objectPrefix + labels = []string{objectLabel, qmgrLabel} + } + return prefix, labels +} diff --git a/internal/metrics/exporter_test.go b/internal/metrics/exporter_test.go index e8db353..7281a12 100644 --- a/internal/metrics/exporter_test.go +++ b/internal/metrics/exporter_test.go @@ -19,11 +19,21 @@ import ( "testing" "time" + "github.com/ibm-messaging/mq-golang/ibmmq" + "github.com/ibm-messaging/mq-golang/mqmetric" "github.com/prometheus/client_golang/prometheus" dto "github.com/prometheus/client_model/go" ) -func TestDescribe(t *testing.T) { +func TestDescribe_Counter(t *testing.T) { + testDescribe(t, true) +} + +func TestDescribe_Gauge(t *testing.T) { + testDescribe(t, false) +} + +func testDescribe(t *testing.T, isDelta bool) { teardownTestCase := setupTestCase(false) defer teardownTestCase() @@ -40,6 +50,9 @@ func TestDescribe(t *testing.T) { t.Errorf("Received unexpected collect request") } + if isDelta { + mqmetric.Metrics.Classes[0].Types[0].Elements[0].Datatype = ibmmq.MQIAMO_MONITOR_DELTA + } metrics, _ := initialiseMetrics(log) responseChannel <- metrics @@ -55,14 +68,26 @@ func TestDescribe(t *testing.T) { } } -func TestCollect(t *testing.T) { +func TestCollect_Counter(t *testing.T) { + testCollect(t, true) +} + +func TestCollect_Gauge(t *testing.T) { + testCollect(t, false) +} + +func testCollect(t *testing.T, isDelta bool) { teardownTestCase := setupTestCase(false) defer teardownTestCase() log := getTestLogger() exporter := newExporter("qmName", log) - exporter.gaugeMap[testKey1] = createGaugeVec(testElement1Name, testElement1Description, false) + if isDelta { + exporter.counterMap[testKey1] = createCounterVec(testElement1Name, testElement1Description, false) + } else { + exporter.gaugeMap[testKey1] = createGaugeVec(testElement1Name, testElement1Description, false) + } for i := 1; i <= 3; i++ { @@ -78,20 +103,33 @@ func TestCollect(t *testing.T) { } populateTestMetrics(i, false) + if isDelta { + mqmetric.Metrics.Classes[0].Types[0].Elements[0].Datatype = ibmmq.MQIAMO_MONITOR_DELTA + } metrics, _ := initialiseMetrics(log) updateMetrics(metrics) responseChannel <- metrics select { case <-ch: + var actual float64 prometheusMetric := dto.Metric{} - exporter.gaugeMap[testKey1].WithLabelValues("qmName").Write(&prometheusMetric) - actual := prometheusMetric.GetGauge().GetValue() + if isDelta { + exporter.counterMap[testKey1].WithLabelValues("qmName").Write(&prometheusMetric) + actual = prometheusMetric.GetCounter().GetValue() + } else { + exporter.gaugeMap[testKey1].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 isDelta && i != 2 { + if actual != float64(i+(i-1)) { + t.Errorf("Expected value=%f; actual %f", float64(i+(i-1)), actual) + } } else if actual != float64(i) { t.Errorf("Expected value=%f; actual %f", float64(i), actual) } @@ -101,6 +139,38 @@ func TestCollect(t *testing.T) { } } +func TestCreateCounterVec(t *testing.T) { + + ch := make(chan *prometheus.Desc) + counterVec := createCounterVec("MetricName", "MetricDescription", false) + go func() { + counterVec.Describe(ch) + }() + description := <-ch + + expected := "Desc{fqName: \"ibmmq_qmgr_MetricName\", help: \"MetricDescription\", constLabels: {}, variableLabels: [qmgr]}" + actual := description.String() + if actual != expected { + t.Errorf("Expected value=%s; actual %s", expected, actual) + } +} + +func TestCreateCounterVec_ObjectLabel(t *testing.T) { + + ch := make(chan *prometheus.Desc) + counterVec := createCounterVec("MetricName", "MetricDescription", true) + go func() { + counterVec.Describe(ch) + }() + description := <-ch + + expected := "Desc{fqName: \"ibmmq_object_MetricName\", help: \"MetricDescription\", constLabels: {}, variableLabels: [object qmgr]}" + actual := description.String() + if actual != expected { + t.Errorf("Expected value=%s; actual %s", expected, actual) + } +} + func TestCreateGaugeVec(t *testing.T) { ch := make(chan *prometheus.Desc) diff --git a/internal/metrics/mapping.go b/internal/metrics/mapping.go index 646a939..8c6ff8a 100644 --- a/internal/metrics/mapping.go +++ b/internal/metrics/mapping.go @@ -43,8 +43,8 @@ func generateMetricNamesMap() map[string]metricLookup { "DISK/SystemSummary/MQ FDC file count": metricLookup{"fdc_files", true}, "DISK/QMgrSummary/Queue Manager file system - free space": metricLookup{"queue_manager_file_system_free_space_percentage", true}, "DISK/QMgrSummary/Queue Manager file system - bytes in use": metricLookup{"queue_manager_file_system_in_use_bytes", true}, - "DISK/Log/Log - logical bytes written": metricLookup{"log_logical_written_bytes_interval_total", true}, - "DISK/Log/Log - physical bytes written": metricLookup{"log_physical_written_bytes_interval_total", true}, + "DISK/Log/Log - logical bytes written": metricLookup{"log_logical_written_bytes_total", true}, + "DISK/Log/Log - physical bytes written": metricLookup{"log_physical_written_bytes_total", true}, "DISK/Log/Log - current primary space in use": metricLookup{"log_primary_space_in_use_percentage", true}, "DISK/Log/Log - workload primary space utilization": metricLookup{"log_workload_primary_space_utilization_percentage", true}, "DISK/Log/Log - write latency": metricLookup{"log_write_latency_seconds", true}, @@ -56,69 +56,69 @@ func generateMetricNamesMap() map[string]metricLookup { "DISK/Log/Log - bytes occupied by reusable extents": metricLookup{"log_occupied_by_reusable_extents_bytes", true}, "DISK/Log/Log - bytes occupied by extents waiting to be archived": metricLookup{"log_occupied_by_extents_waiting_to_be_archived_bytes", true}, "DISK/Log/Log - bytes required for media recovery": metricLookup{"log_required_for_media_recovery_bytes", true}, - "STATMQI/SUBSCRIBE/Create durable subscription count": metricLookup{"durable_subscription_create_interval_total", true}, - "STATMQI/SUBSCRIBE/Alter durable subscription count": metricLookup{"durable_subscription_alter_interval_total", true}, - "STATMQI/SUBSCRIBE/Resume durable subscription count": metricLookup{"durable_subscription_resume_interval_total", true}, - "STATMQI/SUBSCRIBE/Delete durable subscription count": metricLookup{"durable_subscription_delete_interval_total", true}, - "STATMQI/SUBSCRIBE/Create non-durable subscription count": metricLookup{"non_durable_subscription_create_interval_total", true}, - "STATMQI/SUBSCRIBE/Delete non-durable subscription count": metricLookup{"non_durable_subscription_delete_interval_total", true}, - "STATMQI/SUBSCRIBE/Failed create/alter/resume subscription count": metricLookup{"failed_subscription_create_alter_resume_interval_total", true}, - "STATMQI/SUBSCRIBE/Subscription delete failure count": metricLookup{"failed_subscription_delete_interval_total", true}, - "STATMQI/SUBSCRIBE/MQSUBRQ count": metricLookup{"mqsubrq_interval_total", true}, - "STATMQI/SUBSCRIBE/Failed MQSUBRQ count": metricLookup{"failed_mqsubrq_interval_total", true}, + "STATMQI/SUBSCRIBE/Create durable subscription count": metricLookup{"durable_subscription_create_total", true}, + "STATMQI/SUBSCRIBE/Alter durable subscription count": metricLookup{"durable_subscription_alter_total", true}, + "STATMQI/SUBSCRIBE/Resume durable subscription count": metricLookup{"durable_subscription_resume_total", true}, + "STATMQI/SUBSCRIBE/Delete durable subscription count": metricLookup{"durable_subscription_delete_total", true}, + "STATMQI/SUBSCRIBE/Create non-durable subscription count": metricLookup{"non_durable_subscription_create_total", true}, + "STATMQI/SUBSCRIBE/Delete non-durable subscription count": metricLookup{"non_durable_subscription_delete_total", true}, + "STATMQI/SUBSCRIBE/Failed create/alter/resume subscription count": metricLookup{"failed_subscription_create_alter_resume_total", true}, + "STATMQI/SUBSCRIBE/Subscription delete failure count": metricLookup{"failed_subscription_delete_total", true}, + "STATMQI/SUBSCRIBE/MQSUBRQ count": metricLookup{"mqsubrq_total", true}, + "STATMQI/SUBSCRIBE/Failed MQSUBRQ count": metricLookup{"failed_mqsubrq_total", true}, "STATMQI/SUBSCRIBE/Durable subscriber - high water mark": metricLookup{"durable_subscriber_high_water_mark", true}, "STATMQI/SUBSCRIBE/Durable subscriber - low water mark": metricLookup{"durable_subscriber_low_water_mark", true}, "STATMQI/SUBSCRIBE/Non-durable subscriber - high water mark": metricLookup{"non_durable_subscriber_high_water_mark", true}, "STATMQI/SUBSCRIBE/Non-durable subscriber - low water mark": metricLookup{"non_durable_subscriber_low_water_mark", true}, - "STATMQI/PUBLISH/Topic MQPUT/MQPUT1 interval total": metricLookup{"topic_mqput_mqput1_interval_total", true}, - "STATMQI/PUBLISH/Interval total topic bytes put": metricLookup{"topic_put_bytes_interval_total", true}, - "STATMQI/PUBLISH/Failed topic MQPUT/MQPUT1 count": metricLookup{"failed_topic_mqput_mqput1_interval_total", true}, - "STATMQI/PUBLISH/Persistent - topic MQPUT/MQPUT1 count": metricLookup{"persistent_topic_mqput_mqput1_interval_total", true}, - "STATMQI/PUBLISH/Non-persistent - topic MQPUT/MQPUT1 count": metricLookup{"non_persistent_topic_mqput_mqput1_interval_total", true}, - "STATMQI/PUBLISH/Published to subscribers - message count": metricLookup{"published_to_subscribers_message_interval_total", true}, - "STATMQI/PUBLISH/Published to subscribers - byte count": metricLookup{"published_to_subscribers_bytes_interval_total", true}, - "STATMQI/CONNDISC/MQCONN/MQCONNX count": metricLookup{"mqconn_mqconnx_interval_total", true}, - "STATMQI/CONNDISC/Failed MQCONN/MQCONNX count": metricLookup{"failed_mqconn_mqconnx_interval_total", true}, - "STATMQI/CONNDISC/MQDISC count": metricLookup{"mqdisc_interval_total", true}, + "STATMQI/PUBLISH/Topic MQPUT/MQPUT1 interval total": metricLookup{"topic_mqput_mqput1_total", true}, + "STATMQI/PUBLISH/Interval total topic bytes put": metricLookup{"topic_put_bytes_total", true}, + "STATMQI/PUBLISH/Failed topic MQPUT/MQPUT1 count": metricLookup{"failed_topic_mqput_mqput1_total", true}, + "STATMQI/PUBLISH/Persistent - topic MQPUT/MQPUT1 count": metricLookup{"persistent_topic_mqput_mqput1_total", true}, + "STATMQI/PUBLISH/Non-persistent - topic MQPUT/MQPUT1 count": metricLookup{"non_persistent_topic_mqput_mqput1_total", true}, + "STATMQI/PUBLISH/Published to subscribers - message count": metricLookup{"published_to_subscribers_message_total", true}, + "STATMQI/PUBLISH/Published to subscribers - byte count": metricLookup{"published_to_subscribers_bytes_total", true}, + "STATMQI/CONNDISC/MQCONN/MQCONNX count": metricLookup{"mqconn_mqconnx_total", true}, + "STATMQI/CONNDISC/Failed MQCONN/MQCONNX count": metricLookup{"failed_mqconn_mqconnx_total", true}, + "STATMQI/CONNDISC/MQDISC count": metricLookup{"mqdisc_total", true}, "STATMQI/CONNDISC/Concurrent connections - high water mark": metricLookup{"concurrent_connections_high_water_mark", true}, - "STATMQI/OPENCLOSE/MQOPEN count": metricLookup{"mqopen_interval_total", true}, - "STATMQI/OPENCLOSE/Failed MQOPEN count": metricLookup{"failed_mqopen_interval_total", true}, - "STATMQI/OPENCLOSE/MQCLOSE count": metricLookup{"mqclose_interval_total", true}, - "STATMQI/OPENCLOSE/Failed MQCLOSE count": metricLookup{"failed_mqclose_interval_total", true}, - "STATMQI/INQSET/MQINQ count": metricLookup{"mqinq_interval_total", true}, - "STATMQI/INQSET/Failed MQINQ count": metricLookup{"failed_mqinq_interval_total", true}, - "STATMQI/INQSET/MQSET count": metricLookup{"mqset_interval_total", true}, - "STATMQI/INQSET/Failed MQSET count": metricLookup{"failed_mqset_interval_total", true}, - "STATMQI/PUT/Persistent message MQPUT count": metricLookup{"persistent_message_mqput_interval_total", true}, - "STATMQI/PUT/Persistent message MQPUT1 count": metricLookup{"persistent_message_mqput1_interval_total", true}, - "STATMQI/PUT/Put persistent messages - byte count": metricLookup{"persistent_message_put_bytes_interval_total", true}, - "STATMQI/PUT/Non-persistent message MQPUT count": metricLookup{"non_persistent_message_mqput_interval_total", true}, - "STATMQI/PUT/Non-persistent message MQPUT1 count": metricLookup{"non_persistent_message_mqput1_interval_total", true}, - "STATMQI/PUT/Put non-persistent messages - byte count": metricLookup{"non_persistent_message_put_bytes_interval_total", true}, - "STATMQI/PUT/Interval total MQPUT/MQPUT1 count": metricLookup{"mqput_mqput1_interval_total", true}, - "STATMQI/PUT/Interval total MQPUT/MQPUT1 byte count": metricLookup{"mqput_mqput1_bytes_interval_total", true}, - "STATMQI/PUT/Failed MQPUT count": metricLookup{"failed_mqput_interval_total", true}, - "STATMQI/PUT/Failed MQPUT1 count": metricLookup{"failed_mqput1_interval_total", true}, - "STATMQI/PUT/MQSTAT count": metricLookup{"mqstat_interval_total", true}, - "STATMQI/GET/Persistent message destructive get - count": metricLookup{"persistent_message_destructive_get_interval_total", true}, - "STATMQI/GET/Persistent message browse - count": metricLookup{"persistent_message_browse_interval_total", true}, - "STATMQI/GET/Got persistent messages - byte count": metricLookup{"persistent_message_get_bytes_interval_total", true}, - "STATMQI/GET/Persistent message browse - byte count": metricLookup{"persistent_message_browse_bytes_interval_total", true}, - "STATMQI/GET/Non-persistent message destructive get - count": metricLookup{"non_persistent_message_destructive_get_interval_total", true}, - "STATMQI/GET/Non-persistent message browse - count": metricLookup{"non_persistent_message_browse_interval_total", true}, - "STATMQI/GET/Got non-persistent messages - byte count": metricLookup{"non_persistent_message_get_bytes_interval_total", true}, - "STATMQI/GET/Non-persistent message browse - byte count": metricLookup{"non_persistent_message_browse_bytes_interval_total", true}, - "STATMQI/GET/Interval total destructive get- count": metricLookup{"destructive_get_interval_total", true}, - "STATMQI/GET/Interval total destructive get - byte count": metricLookup{"destructive_get_bytes_interval_total", true}, - "STATMQI/GET/Failed MQGET - count": metricLookup{"failed_mqget_interval_total", true}, - "STATMQI/GET/Failed browse count": metricLookup{"failed_browse_interval_total", true}, - "STATMQI/GET/MQCTL count": metricLookup{"mqctl_interval_total", true}, - "STATMQI/GET/Expired message count": metricLookup{"expired_message_interval_total", true}, - "STATMQI/GET/Purged queue count": metricLookup{"purged_queue_interval_total", true}, - "STATMQI/GET/MQCB count": metricLookup{"mqcb_interval_total", true}, - "STATMQI/GET/Failed MQCB count": metricLookup{"failed_mqcb_interval_total", true}, - "STATMQI/SYNCPOINT/Commit count": metricLookup{"commit_interval_total", true}, - "STATMQI/SYNCPOINT/Rollback count": metricLookup{"rollback_interval_total", true}, + "STATMQI/OPENCLOSE/MQOPEN count": metricLookup{"mqopen_total", true}, + "STATMQI/OPENCLOSE/Failed MQOPEN count": metricLookup{"failed_mqopen_total", true}, + "STATMQI/OPENCLOSE/MQCLOSE count": metricLookup{"mqclose_total", true}, + "STATMQI/OPENCLOSE/Failed MQCLOSE count": metricLookup{"failed_mqclose_total", true}, + "STATMQI/INQSET/MQINQ count": metricLookup{"mqinq_total", true}, + "STATMQI/INQSET/Failed MQINQ count": metricLookup{"failed_mqinq_total", true}, + "STATMQI/INQSET/MQSET count": metricLookup{"mqset_total", true}, + "STATMQI/INQSET/Failed MQSET count": metricLookup{"failed_mqset_total", true}, + "STATMQI/PUT/Persistent message MQPUT count": metricLookup{"persistent_message_mqput_total", true}, + "STATMQI/PUT/Persistent message MQPUT1 count": metricLookup{"persistent_message_mqput1_total", true}, + "STATMQI/PUT/Put persistent messages - byte count": metricLookup{"persistent_message_put_bytes_total", true}, + "STATMQI/PUT/Non-persistent message MQPUT count": metricLookup{"non_persistent_message_mqput_total", true}, + "STATMQI/PUT/Non-persistent message MQPUT1 count": metricLookup{"non_persistent_message_mqput1_total", true}, + "STATMQI/PUT/Put non-persistent messages - byte count": metricLookup{"non_persistent_message_put_bytes_total", true}, + "STATMQI/PUT/Interval total MQPUT/MQPUT1 count": metricLookup{"mqput_mqput1_total", true}, + "STATMQI/PUT/Interval total MQPUT/MQPUT1 byte count": metricLookup{"mqput_mqput1_bytes_total", true}, + "STATMQI/PUT/Failed MQPUT count": metricLookup{"failed_mqput_total", true}, + "STATMQI/PUT/Failed MQPUT1 count": metricLookup{"failed_mqput1_total", true}, + "STATMQI/PUT/MQSTAT count": metricLookup{"mqstat_total", true}, + "STATMQI/GET/Persistent message destructive get - count": metricLookup{"persistent_message_destructive_get_total", true}, + "STATMQI/GET/Persistent message browse - count": metricLookup{"persistent_message_browse_total", true}, + "STATMQI/GET/Got persistent messages - byte count": metricLookup{"persistent_message_get_bytes_total", true}, + "STATMQI/GET/Persistent message browse - byte count": metricLookup{"persistent_message_browse_bytes_total", true}, + "STATMQI/GET/Non-persistent message destructive get - count": metricLookup{"non_persistent_message_destructive_get_total", true}, + "STATMQI/GET/Non-persistent message browse - count": metricLookup{"non_persistent_message_browse_total", true}, + "STATMQI/GET/Got non-persistent messages - byte count": metricLookup{"non_persistent_message_get_bytes_total", true}, + "STATMQI/GET/Non-persistent message browse - byte count": metricLookup{"non_persistent_message_browse_bytes_total", true}, + "STATMQI/GET/Interval total destructive get- count": metricLookup{"destructive_get_total", true}, + "STATMQI/GET/Interval total destructive get - byte count": metricLookup{"destructive_get_bytes_total", true}, + "STATMQI/GET/Failed MQGET - count": metricLookup{"failed_mqget_total", true}, + "STATMQI/GET/Failed browse count": metricLookup{"failed_browse_total", true}, + "STATMQI/GET/MQCTL count": metricLookup{"mqctl_total", true}, + "STATMQI/GET/Expired message count": metricLookup{"expired_message_total", true}, + "STATMQI/GET/Purged queue count": metricLookup{"purged_queue_total", true}, + "STATMQI/GET/MQCB count": metricLookup{"mqcb_total", true}, + "STATMQI/GET/Failed MQCB count": metricLookup{"failed_mqcb_total", true}, + "STATMQI/SYNCPOINT/Commit count": metricLookup{"commit_total", true}, + "STATMQI/SYNCPOINT/Rollback count": metricLookup{"rollback_total", true}, } return metricNamesMap } diff --git a/internal/metrics/update.go b/internal/metrics/update.go index b8429b5..9aceceb 100644 --- a/internal/metrics/update.go +++ b/internal/metrics/update.go @@ -23,6 +23,7 @@ import ( "time" "github.com/ibm-messaging/mq-container/internal/logger" + "github.com/ibm-messaging/mq-golang/ibmmq" "github.com/ibm-messaging/mq-golang/mqmetric" ) @@ -43,6 +44,7 @@ type metricData struct { description string objectType bool values map[string]float64 + isDelta bool } // processMetrics processes publications of metric data and handles describe/collect/stop requests @@ -148,10 +150,17 @@ func initialiseMetrics(log *logger.Logger) (map[string]*metricData, error) { // Check if metric is enabled if metricLookup.enabled { + // Check if metric is a delta type + isDelta := false + if metricElement.Datatype == ibmmq.MQIAMO_MONITOR_DELTA { + isDelta = true + } + // Set metric details metric := metricData{ name: metricLookup.name, description: metricElement.Description, + isDelta: isDelta, } // Add metric diff --git a/test/docker/mqmetric_test_util.go b/test/docker/mqmetric_test_util.go index cfe42a2..ab10ff0 100644 --- a/test/docker/mqmetric_test_util.go +++ b/test/docker/mqmetric_test_util.go @@ -181,8 +181,8 @@ func metricNames() []string { "fdc_files", "queue_manager_file_system_free_space_percentage", "queue_manager_file_system_in_use_bytes", - "log_logical_written_bytes_interval_total", - "log_physical_written_bytes_interval_total", + "log_logical_written_bytes_total", + "log_physical_written_bytes_total", "log_primary_space_in_use_percentage", "log_workload_primary_space_utilization_percentage", "log_write_latency_seconds", @@ -191,69 +191,69 @@ func metricNames() []string { "log_in_use_bytes", "log_file_system_max_bytes", "log_file_system_in_use_bytes", - "durable_subscription_create_interval_total", - "durable_subscription_alter_interval_total", - "durable_subscription_resume_interval_total", - "durable_subscription_delete_interval_total", - "non_durable_subscription_create_interval_total", - "non_durable_subscription_delete_interval_total", - "failed_subscription_create_alter_resume_interval_total", - "failed_subscription_delete_interval_total", - "mqsubrq_interval_total", - "failed_mqsubrq_interval_total", + "durable_subscription_create_total", + "durable_subscription_alter_total", + "durable_subscription_resume_total", + "durable_subscription_delete_total", + "non_durable_subscription_create_total", + "non_durable_subscription_delete_total", + "failed_subscription_create_alter_resume_total", + "failed_subscription_delete_total", + "mqsubrq_total", + "failed_mqsubrq_total", "durable_subscriber_high_water_mark", "durable_subscriber_low_water_mark", "non_durable_subscriber_high_water_mark", "non_durable_subscriber_low_water_mark", - "topic_mqput_mqput1_interval_total", - "topic_put_bytes_interval_total", - "failed_topic_mqput_mqput1_interval_total", - "persistent_topic_mqput_mqput1_interval_total", - "non_persistent_topic_mqput_mqput1_interval_total", - "published_to_subscribers_message_interval_total", - "published_to_subscribers_bytes_interval_total", - "mqconn_mqconnx_interval_total", - "failed_mqconn_mqconnx_interval_total", - "mqdisc_interval_total", + "topic_mqput_mqput1_total", + "topic_put_bytes_total", + "failed_topic_mqput_mqput1_total", + "persistent_topic_mqput_mqput1_total", + "non_persistent_topic_mqput_mqput1_total", + "published_to_subscribers_message_total", + "published_to_subscribers_bytes_total", + "mqconn_mqconnx_total", + "failed_mqconn_mqconnx_total", + "mqdisc_total", "concurrent_connections_high_water_mark", - "mqopen_interval_total", - "failed_mqopen_interval_total", - "mqclose_interval_total", - "failed_mqclose_interval_total", - "mqinq_interval_total", - "failed_mqinq_interval_total", - "mqset_interval_total", - "failed_mqset_interval_total", - "persistent_message_mqput_interval_total", - "persistent_message_mqput1_interval_total", - "persistent_message_put_bytes_interval_total", - "non_persistent_message_mqput_interval_total", - "non_persistent_message_mqput1_interval_total", - "non_persistent_message_put_bytes_interval_total", - "mqput_mqput1_interval_total", - "mqput_mqput1_bytes_interval_total", - "failed_mqput_interval_total", - "failed_mqput1_interval_total", - "mqstat_interval_total", - "persistent_message_destructive_get_interval_total", - "persistent_message_browse_interval_total", - "persistent_message_get_bytes_interval_total", - "persistent_message_browse_bytes_interval_total", - "non_persistent_message_destructive_get_interval_total", - "non_persistent_message_browse_interval_total", - "non_persistent_message_get_bytes_interval_total", - "non_persistent_message_browse_bytes_interval_total", - "destructive_get_interval_total", - "destructive_get_bytes_interval_total", - "failed_mqget_interval_total", - "failed_browse_interval_total", - "mqctl_interval_total", - "expired_message_interval_total", - "purged_queue_interval_total", - "mqcb_interval_total", - "failed_mqcb_interval_total", - "commit_interval_total", - "rollback_interval_total", + "mqopen_total", + "failed_mqopen_total", + "mqclose_total", + "failed_mqclose_total", + "mqinq_total", + "failed_mqinq_total", + "mqset_total", + "failed_mqset_total", + "persistent_message_mqput_total", + "persistent_message_mqput1_total", + "persistent_message_put_bytes_total", + "non_persistent_message_mqput_total", + "non_persistent_message_mqput1_total", + "non_persistent_message_put_bytes_total", + "mqput_mqput1_total", + "mqput_mqput1_bytes_total", + "failed_mqput_total", + "failed_mqput1_total", + "mqstat_total", + "persistent_message_destructive_get_total", + "persistent_message_browse_total", + "persistent_message_get_bytes_total", + "persistent_message_browse_bytes_total", + "non_persistent_message_destructive_get_total", + "non_persistent_message_browse_total", + "non_persistent_message_get_bytes_total", + "non_persistent_message_browse_bytes_total", + "destructive_get_total", + "destructive_get_bytes_total", + "failed_mqget_total", + "failed_browse_total", + "mqctl_total", + "expired_message_total", + "purged_queue_total", + "mqcb_total", + "failed_mqcb_total", + "commit_total", + "rollback_total", } return names }