From dda8962e1d084ed518510fb2176686b5161201d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan-Otto=20Kr=C3=B6pke?= Date: Fri, 9 Oct 2026 10:47:31 +0200 Subject: [PATCH] mssql: correct latency and request-count units (#2596) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jan-Otto Kröpke --- .../collector/mssql/counter_units_test.go | 68 +++++++++++++++++++ internal/collector/mssql/mssql_database.go | 10 ++- .../collector/mssql/mssql_database_replica.go | 12 ++-- internal/collector/mssql/mssql_locks.go | 10 ++- 4 files changed, 90 insertions(+), 10 deletions(-) create mode 100644 internal/collector/mssql/counter_units_test.go diff --git a/internal/collector/mssql/counter_units_test.go b/internal/collector/mssql/counter_units_test.go new file mode 100644 index 00000000..20597e7e --- /dev/null +++ b/internal/collector/mssql/counter_units_test.go @@ -0,0 +1,68 @@ +// SPDX-License-Identifier: Apache-2.0 +// +// Copyright The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build windows + +package mssql + +import ( + "testing" + + "github.com/prometheus/client_golang/prometheus" + dto "github.com/prometheus/client_model/go" + "github.com/stretchr/testify/require" +) + +func TestCounterUnitConversions(t *testing.T) { + t.Parallel() + + c := New(nil) + // No SQL instances are needed to build the metric descriptors. + require.NoError(t, c.buildDatabases()) + require.NoError(t, c.buildDatabaseReplica()) + require.NoError(t, c.buildLocks()) + c.databasesPerfDataObject = []perfDataCounterValuesDatabases{{Name: "db", DatabasesXTPControllerDLCPeakLatency: 1000}} + c.dbReplicaPerfDataObject = []perfDataCounterValuesDBReplica{{Name: "replica", DbReplicaDatabaseFlowControlDelay: 1000, DbReplicaGroupCommitTime: 1000}} + c.locksPerfDataObject = []perfDataCounterValuesLocks{{Name: "locks", LocksAverageWaitTimeMSBase: 1000}} + instance := mssqlInstance{name: "test"} + metrics := make(chan prometheus.Metric, 200) + c.emitDatabasesMetrics(metrics, instance) + c.emitDatabaseReplicaMetrics(metrics, instance) + c.emitLocksMetrics(metrics, instance) + close(metrics) + + want := map[*prometheus.Desc]float64{ + c.databasesXTPControllerDLCPeakLatency: 0.001, + c.dbReplicaDatabaseFlowControlDelay: 0.001, + c.dbReplicaGroupCommitTime: 0.001, + c.locksCount: 1000, + } + found := make(map[*prometheus.Desc]bool) + + for metric := range metrics { + expected, ok := want[metric.Desc()] + if !ok { + continue + } + + var value dto.Metric + require.NoError(t, metric.Write(&value)) + require.InDelta(t, expected, value.GetGauge().GetValue(), 1e-9) + + found[metric.Desc()] = true + } + + require.Len(t, found, len(want)) +} diff --git a/internal/collector/mssql/mssql_database.go b/internal/collector/mssql/mssql_database.go index 04382099..85b3153a 100644 --- a/internal/collector/mssql/mssql_database.go +++ b/internal/collector/mssql/mssql_database.go @@ -466,6 +466,12 @@ func (c *Collector) collectDatabasesInstance(ch chan<- prometheus.Metric, sqlIns return fmt.Errorf("failed to collect %s metrics: %w", c.mssqlGetPerfObjectName(sqlInstance, "Databases"), err) } + c.emitDatabasesMetrics(ch, sqlInstance) + + return nil +} + +func (c *Collector) emitDatabasesMetrics(ch chan<- prometheus.Metric, sqlInstance mssqlInstance) { for _, data := range c.databasesPerfDataObject { ch <- prometheus.MustNewConstMetric( c.databasesActiveTransactions, @@ -778,7 +784,7 @@ func (c *Collector) collectDatabasesInstance(ch chan<- prometheus.Metric, sqlIns ch <- prometheus.MustNewConstMetric( c.databasesXTPControllerDLCPeakLatency, prometheus.GaugeValue, - data.DatabasesXTPControllerDLCPeakLatency*1000000.0, + data.DatabasesXTPControllerDLCPeakLatency/1e6, sqlInstance.name, data.Name, ) @@ -796,8 +802,6 @@ func (c *Collector) collectDatabasesInstance(ch chan<- prometheus.Metric, sqlIns sqlInstance.name, data.Name, ) } - - return nil } func (c *Collector) collectDatabasesInstance2019(ch chan<- prometheus.Metric, sqlInstance mssqlInstance, perfDataCollector *pdh.Collector[perfDataCounterValuesDatabases2019]) error { diff --git a/internal/collector/mssql/mssql_database_replica.go b/internal/collector/mssql/mssql_database_replica.go index 5fe47224..0510bfd9 100644 --- a/internal/collector/mssql/mssql_database_replica.go +++ b/internal/collector/mssql/mssql_database_replica.go @@ -257,11 +257,17 @@ func (c *Collector) collectDatabaseReplicaInstance(ch chan<- prometheus.Metric, return fmt.Errorf("failed to collect %s metrics: %w", c.mssqlGetPerfObjectName(sqlInstance, "Database Replica"), err) } + c.emitDatabaseReplicaMetrics(ch, sqlInstance) + + return nil +} + +func (c *Collector) emitDatabaseReplicaMetrics(ch chan<- prometheus.Metric, sqlInstance mssqlInstance) { for _, data := range c.dbReplicaPerfDataObject { ch <- prometheus.MustNewConstMetric( c.dbReplicaDatabaseFlowControlDelay, prometheus.GaugeValue, - data.DbReplicaDatabaseFlowControlDelay, + data.DbReplicaDatabaseFlowControlDelay/1e6, sqlInstance.name, data.Name, ) @@ -289,7 +295,7 @@ func (c *Collector) collectDatabaseReplicaInstance(ch chan<- prometheus.Metric, ch <- prometheus.MustNewConstMetric( c.dbReplicaGroupCommitTime, prometheus.GaugeValue, - data.DbReplicaGroupCommitTime, + data.DbReplicaGroupCommitTime/1e6, sqlInstance.name, data.Name, ) @@ -426,8 +432,6 @@ func (c *Collector) collectDatabaseReplicaInstance(ch chan<- prometheus.Metric, sqlInstance.name, data.Name, ) } - - return nil } func (c *Collector) closeDatabaseReplica() { diff --git a/internal/collector/mssql/mssql_locks.go b/internal/collector/mssql/mssql_locks.go index eded127f..b7bbe1a3 100644 --- a/internal/collector/mssql/mssql_locks.go +++ b/internal/collector/mssql/mssql_locks.go @@ -129,6 +129,12 @@ func (c *Collector) collectLocksInstance(ch chan<- prometheus.Metric, sqlInstanc return fmt.Errorf("failed to collect %s metrics: %w", c.mssqlGetPerfObjectName(sqlInstance, "Locks"), err) } + c.emitLocksMetrics(ch, sqlInstance) + + return nil +} + +func (c *Collector) emitLocksMetrics(ch chan<- prometheus.Metric, sqlInstance mssqlInstance) { for _, data := range c.locksPerfDataObject { ch <- prometheus.MustNewConstMetric( c.locksWaitTime, @@ -140,7 +146,7 @@ func (c *Collector) collectLocksInstance(ch chan<- prometheus.Metric, sqlInstanc ch <- prometheus.MustNewConstMetric( c.locksCount, prometheus.GaugeValue, - data.LocksAverageWaitTimeMSBase/1000.0, + data.LocksAverageWaitTimeMSBase, sqlInstance.name, data.Name, ) @@ -186,8 +192,6 @@ func (c *Collector) collectLocksInstance(ch chan<- prometheus.Metric, sqlInstanc sqlInstance.name, data.Name, ) } - - return nil } func (c *Collector) closeLocks() {