From 1708485e1f321e480c752be6b0dbca00ec2ef033 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan-Otto=20Kr=C3=B6pke?= Date: Sat, 16 Nov 2024 18:57:57 +0100 Subject: [PATCH 1/6] wip MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jan-Otto Kröpke --- internal/headers/iphlpapi/const.go | 4 +-- internal/headers/iphlpapi/iphlpapi.go | 47 +++++++++++++++++++++++++-- test/main.go | 5 +++ 3 files changed, 52 insertions(+), 4 deletions(-) create mode 100644 test/main.go diff --git a/internal/headers/iphlpapi/const.go b/internal/headers/iphlpapi/const.go index 7aa55782b..2126071da 100644 --- a/internal/headers/iphlpapi/const.go +++ b/internal/headers/iphlpapi/const.go @@ -3,6 +3,6 @@ package iphlpapi const ( - TCPTableClass uint32 = 5 - TCP6TableClass uint32 = 5 + TCPTableOwnerPIDAll uint32 = 5 + TCPTableOwnerPIDListener uint32 = 3 ) diff --git a/internal/headers/iphlpapi/iphlpapi.go b/internal/headers/iphlpapi/iphlpapi.go index ed0152efc..8af9c07f9 100644 --- a/internal/headers/iphlpapi/iphlpapi.go +++ b/internal/headers/iphlpapi/iphlpapi.go @@ -3,6 +3,7 @@ package iphlpapi import ( + "encoding/binary" "fmt" "unsafe" @@ -19,11 +20,11 @@ func GetTCPConnectionStates(family uint32) (map[MIB_TCP_STATE]uint32, error) { stateCounts := make(map[MIB_TCP_STATE]uint32) rowSize := uint32(unsafe.Sizeof(MIB_TCPROW_OWNER_PID{})) - tableClass := TCPTableClass + tableClass := TCPTableOwnerPIDAll if family == windows.AF_INET6 { rowSize = uint32(unsafe.Sizeof(MIB_TCP6ROW_OWNER_PID{})) - tableClass = TCP6TableClass + tableClass = TCP6TableOwnerPIDAll } ret := getExtendedTcpTable(0, &size, true, family, tableClass, 0) @@ -57,6 +58,48 @@ func GetTCPConnectionStates(family uint32) (map[MIB_TCP_STATE]uint32, error) { return stateCounts, nil } +func GetOwnerPIDOfTCPPort(family uint32, tcpPort uint32) (uint32, error) { + var size uint32 + + stateCounts := make(map[MIB_TCP_STATE]uint32) + rowSize := uint32(unsafe.Sizeof(MIB_TCPROW_OWNER_PID{})) + tableClass := TCPTableOwnerPIDListener + + if family == windows.AF_INET6 { + rowSize = uint32(unsafe.Sizeof(MIB_TCP6ROW_OWNER_PID{})) + } + + ret := getExtendedTcpTable(0, &size, true, family, tableClass, 0) + if ret != 0 && ret != uintptr(windows.ERROR_INSUFFICIENT_BUFFER) { + return 0, fmt.Errorf("getExtendedTcpTable (size query) failed with code %d", ret) + } + + buf := make([]byte, size) + + ret = getExtendedTcpTable(uintptr(unsafe.Pointer(&buf[0])), &size, true, family, tableClass, 0) + if ret != 0 { + return nil, fmt.Errorf("getExtendedTcpTable (data query) failed with code %d", ret) + } + + numEntries := binary.LittleEndian.Uint32(buf) + entries := (*[1 << 24]MIB_TCPROW_OWNER_PID)(unsafe.Pointer(&rawbuf[4]))[:count:count] + for i := range numEntries { + var state MIB_TCP_STATE + + if family == windows.AF_INET6 { + row := (*MIB_TCP6ROW_OWNER_PID)(unsafe.Pointer(&buf[4+i*rowSize])) + state = row.dwState + } else { + row := (*MIB_TCPROW_OWNER_PID)(unsafe.Pointer(&buf[4+i*rowSize])) + state = row.dwState + } + + stateCounts[state]++ + } + + return stateCounts, nil +} + func getExtendedTcpTable(pTCPTable uintptr, pdwSize *uint32, bOrder bool, ulAf uint32, tableClass uint32, reserved uint32) uintptr { ret, _, _ := procGetExtendedTcpTable.Call( pTCPTable, diff --git a/test/main.go b/test/main.go new file mode 100644 index 000000000..1f4f71523 --- /dev/null +++ b/test/main.go @@ -0,0 +1,5 @@ +package test + +func main() { + +} From 0c3b4e094472e5d2edf01632e79dd52c5c603121 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan-Otto=20Kr=C3=B6pke?= Date: Sat, 16 Nov 2024 20:03:32 +0100 Subject: [PATCH 2/6] chore: optimize iphlpapi MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jan-Otto Kröpke --- internal/headers/iphlpapi/iphlpapi.go | 144 ++++++++++----------- internal/headers/iphlpapi/iphlpapi_test.go | 32 +++++ internal/headers/iphlpapi/types.go | 25 +++- 3 files changed, 118 insertions(+), 83 deletions(-) create mode 100644 internal/headers/iphlpapi/iphlpapi_test.go diff --git a/internal/headers/iphlpapi/iphlpapi.go b/internal/headers/iphlpapi/iphlpapi.go index 8af9c07f9..3ad4b0e48 100644 --- a/internal/headers/iphlpapi/iphlpapi.go +++ b/internal/headers/iphlpapi/iphlpapi.go @@ -16,107 +16,99 @@ var ( ) func GetTCPConnectionStates(family uint32) (map[MIB_TCP_STATE]uint32, error) { - var size uint32 - stateCounts := make(map[MIB_TCP_STATE]uint32) - rowSize := uint32(unsafe.Sizeof(MIB_TCPROW_OWNER_PID{})) - tableClass := TCPTableOwnerPIDAll - if family == windows.AF_INET6 { - rowSize = uint32(unsafe.Sizeof(MIB_TCP6ROW_OWNER_PID{})) - tableClass = TCP6TableOwnerPIDAll - } + switch family { + case windows.AF_INET: + table, err := getExtendedTcpTable[MIB_TCPROW_OWNER_PID](family, TCPTableOwnerPIDAll) + if err != nil { + return nil, err + } - ret := getExtendedTcpTable(0, &size, true, family, tableClass, 0) - if ret != 0 && ret != uintptr(windows.ERROR_INSUFFICIENT_BUFFER) { - return nil, fmt.Errorf("getExtendedTcpTable (size query) failed with code %d", ret) - } + for _, row := range table { + stateCounts[row.dwState]++ + } - buf := make([]byte, size) + return stateCounts, nil + case windows.AF_INET6: + table, err := getExtendedTcpTable[MIB_TCP6ROW_OWNER_PID](family, TCPTableOwnerPIDAll) + if err != nil { + return nil, err + } - ret = getExtendedTcpTable(uintptr(unsafe.Pointer(&buf[0])), &size, true, family, tableClass, 0) - if ret != 0 { - return nil, fmt.Errorf("getExtendedTcpTable (data query) failed with code %d", ret) + for _, row := range table { + stateCounts[row.dwState]++ + } + + return stateCounts, nil + default: + return nil, fmt.Errorf("unsupported address family %d", family) } +} + +func GetOwnerPIDOfTCPPort(family uint32, tcpPort uint16) (int, error) { + switch family { + case windows.AF_INET: + table, err := getExtendedTcpTable[MIB_TCPROW_OWNER_PID](family, TCPTableOwnerPIDListener) + if err != nil { + return 0, err + } - numEntries := *(*uint32)(unsafe.Pointer(&buf[0])) + for _, row := range table { + if row.dwLocalPort.uint16() == tcpPort { + return int(row.dwOwningPid), nil + } + } - for i := range numEntries { - var state MIB_TCP_STATE + return 0, fmt.Errorf("no process found for port %d", tcpPort) + case windows.AF_INET6: + table, err := getExtendedTcpTable[MIB_TCP6ROW_OWNER_PID](family, TCPTableOwnerPIDListener) + if err != nil { + return 0, err + } - if family == windows.AF_INET6 { - row := (*MIB_TCP6ROW_OWNER_PID)(unsafe.Pointer(&buf[4+i*rowSize])) - state = row.dwState - } else { - row := (*MIB_TCPROW_OWNER_PID)(unsafe.Pointer(&buf[4+i*rowSize])) - state = row.dwState + for _, row := range table { + if row.dwLocalPort.uint16() == tcpPort { + return int(row.dwOwningPid), nil + } } - stateCounts[state]++ + return 0, fmt.Errorf("no process found for port %d", tcpPort) + default: + return 0, fmt.Errorf("unsupported address family %d", family) } - - return stateCounts, nil } -func GetOwnerPIDOfTCPPort(family uint32, tcpPort uint32) (uint32, error) { +func getExtendedTcpTable[T any](ulAf uint32, tableClass uint32) ([]T, error) { var size uint32 - stateCounts := make(map[MIB_TCP_STATE]uint32) - rowSize := uint32(unsafe.Sizeof(MIB_TCPROW_OWNER_PID{})) - tableClass := TCPTableOwnerPIDListener - - if family == windows.AF_INET6 { - rowSize = uint32(unsafe.Sizeof(MIB_TCP6ROW_OWNER_PID{})) - } + ret, _, _ := procGetExtendedTcpTable.Call( + uintptr(0), + uintptr(unsafe.Pointer(&size)), + uintptr(0), + uintptr(ulAf), + uintptr(tableClass), + uintptr(0), + ) - ret := getExtendedTcpTable(0, &size, true, family, tableClass, 0) - if ret != 0 && ret != uintptr(windows.ERROR_INSUFFICIENT_BUFFER) { - return 0, fmt.Errorf("getExtendedTcpTable (size query) failed with code %d", ret) + if ret != uintptr(windows.ERROR_INSUFFICIENT_BUFFER) { + return nil, fmt.Errorf("getExtendedTcpTable (size query) failed with code %d", ret) } buf := make([]byte, size) - ret = getExtendedTcpTable(uintptr(unsafe.Pointer(&buf[0])), &size, true, family, tableClass, 0) - if ret != 0 { - return nil, fmt.Errorf("getExtendedTcpTable (data query) failed with code %d", ret) - } - - numEntries := binary.LittleEndian.Uint32(buf) - entries := (*[1 << 24]MIB_TCPROW_OWNER_PID)(unsafe.Pointer(&rawbuf[4]))[:count:count] - for i := range numEntries { - var state MIB_TCP_STATE - - if family == windows.AF_INET6 { - row := (*MIB_TCP6ROW_OWNER_PID)(unsafe.Pointer(&buf[4+i*rowSize])) - state = row.dwState - } else { - row := (*MIB_TCPROW_OWNER_PID)(unsafe.Pointer(&buf[4+i*rowSize])) - state = row.dwState - } - - stateCounts[state]++ - } - - return stateCounts, nil -} - -func getExtendedTcpTable(pTCPTable uintptr, pdwSize *uint32, bOrder bool, ulAf uint32, tableClass uint32, reserved uint32) uintptr { - ret, _, _ := procGetExtendedTcpTable.Call( - pTCPTable, - uintptr(unsafe.Pointer(pdwSize)), - uintptr(boolToInt(bOrder)), + ret, _, _ = procGetExtendedTcpTable.Call( + uintptr(unsafe.Pointer(&buf[0])), + uintptr(unsafe.Pointer(&size)), + uintptr(0), uintptr(ulAf), uintptr(tableClass), - uintptr(reserved), + uintptr(0), ) - return ret -} - -func boolToInt(b bool) int { - if b { - return 1 + if ret != 0 { + return nil, fmt.Errorf("getExtendedTcpTable (data query) failed with code %d", ret) } - return 0 + return unsafe.Slice((*T)(unsafe.Pointer(&buf[4])), binary.LittleEndian.Uint32(buf)), nil } diff --git a/internal/headers/iphlpapi/iphlpapi_test.go b/internal/headers/iphlpapi/iphlpapi_test.go new file mode 100644 index 000000000..8eed13fb2 --- /dev/null +++ b/internal/headers/iphlpapi/iphlpapi_test.go @@ -0,0 +1,32 @@ +package iphlpapi_test + +import ( + "net" + "os" + "testing" + + "github.com/prometheus-community/windows_exporter/internal/headers/iphlpapi" + "github.com/stretchr/testify/require" + "golang.org/x/sys/windows" +) + +func TestGetTCPConnectionStates(t *testing.T) { + t.Parallel() + + pid, err := iphlpapi.GetTCPConnectionStates(windows.AF_INET) + require.NoError(t, err) + require.NotEmpty(t, pid) +} + +func TestGetOwnerPIDOfTCPPort(t *testing.T) { + t.Parallel() + + lister, err := net.Listen("tcp", "127.0.0.1:0") + t.Cleanup(func() { + require.NoError(t, lister.Close()) + }) + + pid, err := iphlpapi.GetOwnerPIDOfTCPPort(windows.AF_INET, uint16(lister.Addr().(*net.TCPAddr).Port)) + require.NoError(t, err) + require.Equal(t, os.Getpid(), pid) +} diff --git a/internal/headers/iphlpapi/types.go b/internal/headers/iphlpapi/types.go index 97038a61d..448e00335 100644 --- a/internal/headers/iphlpapi/types.go +++ b/internal/headers/iphlpapi/types.go @@ -2,16 +2,19 @@ package iphlpapi -import "fmt" +import ( + "encoding/binary" + "fmt" +) // MIB_TCPROW_OWNER_PID structure for IPv4. // https://learn.microsoft.com/en-us/windows/win32/api/tcpmib/ns-tcpmib-mib_tcprow_owner_pid type MIB_TCPROW_OWNER_PID struct { dwState MIB_TCP_STATE - dwLocalAddr uint32 - dwLocalPort uint32 - dwRemoteAddr uint32 - dwRemotePort uint32 + dwLocalAddr BigEndianUint32 + dwLocalPort BigEndianUint32 + dwRemoteAddr BigEndianUint32 + dwRemotePort BigEndianUint32 dwOwningPid uint32 } @@ -20,10 +23,10 @@ type MIB_TCPROW_OWNER_PID struct { type MIB_TCP6ROW_OWNER_PID struct { ucLocalAddr [16]byte dwLocalScopeId uint32 - dwLocalPort uint32 + dwLocalPort BigEndianUint32 ucRemoteAddr [16]byte dwRemoteScopeId uint32 - dwRemotePort uint32 + dwRemotePort BigEndianUint32 dwState MIB_TCP_STATE dwOwningPid uint32 } @@ -76,3 +79,11 @@ func (state MIB_TCP_STATE) String() string { return fmt.Sprintf("UNKNOWN_%d", state) } } + +type BigEndianUint32 uint32 + +func (b BigEndianUint32) uint16() uint16 { + data := make([]byte, 2) + binary.BigEndian.PutUint16(data, uint16(b)) + return binary.LittleEndian.Uint16(data) +} From c9d65a9cc4aa7e07f958d4c7e872b5fd85e9a59e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan-Otto=20Kr=C3=B6pke?= Date: Sat, 16 Nov 2024 20:41:25 +0100 Subject: [PATCH 3/6] chore: optimize iphlpapi MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jan-Otto Kröpke --- internal/headers/iphlpapi/iphlpapi.go | 6 +++--- internal/headers/iphlpapi/iphlpapi_test.go | 2 +- test/main.go | 24 +++++++++++++++++++++- 3 files changed, 27 insertions(+), 5 deletions(-) diff --git a/internal/headers/iphlpapi/iphlpapi.go b/internal/headers/iphlpapi/iphlpapi.go index 3ad4b0e48..aedf758da 100644 --- a/internal/headers/iphlpapi/iphlpapi.go +++ b/internal/headers/iphlpapi/iphlpapi.go @@ -46,7 +46,7 @@ func GetTCPConnectionStates(family uint32) (map[MIB_TCP_STATE]uint32, error) { } } -func GetOwnerPIDOfTCPPort(family uint32, tcpPort uint16) (int, error) { +func GetOwnerPIDOfTCPPort(family uint32, tcpPort uint16) (uint32, error) { switch family { case windows.AF_INET: table, err := getExtendedTcpTable[MIB_TCPROW_OWNER_PID](family, TCPTableOwnerPIDListener) @@ -56,7 +56,7 @@ func GetOwnerPIDOfTCPPort(family uint32, tcpPort uint16) (int, error) { for _, row := range table { if row.dwLocalPort.uint16() == tcpPort { - return int(row.dwOwningPid), nil + return row.dwOwningPid, nil } } @@ -69,7 +69,7 @@ func GetOwnerPIDOfTCPPort(family uint32, tcpPort uint16) (int, error) { for _, row := range table { if row.dwLocalPort.uint16() == tcpPort { - return int(row.dwOwningPid), nil + return row.dwOwningPid, nil } } diff --git a/internal/headers/iphlpapi/iphlpapi_test.go b/internal/headers/iphlpapi/iphlpapi_test.go index 8eed13fb2..6ad1c48fb 100644 --- a/internal/headers/iphlpapi/iphlpapi_test.go +++ b/internal/headers/iphlpapi/iphlpapi_test.go @@ -28,5 +28,5 @@ func TestGetOwnerPIDOfTCPPort(t *testing.T) { pid, err := iphlpapi.GetOwnerPIDOfTCPPort(windows.AF_INET, uint16(lister.Addr().(*net.TCPAddr).Port)) require.NoError(t, err) - require.Equal(t, os.Getpid(), pid) + require.EqualValues(t, os.Getpid(), pid) } diff --git a/test/main.go b/test/main.go index 1f4f71523..d2414da3b 100644 --- a/test/main.go +++ b/test/main.go @@ -1,5 +1,27 @@ -package test +package main + +import ( + "fmt" + + "github.com/Microsoft/go-winio/pkg/process" + "github.com/prometheus-community/windows_exporter/internal/headers/iphlpapi" + "golang.org/x/sys/windows" +) func main() { + pid, err := iphlpapi.GetOwnerPIDOfTCPPort(windows.AF_INET, 135) + if err != nil { + panic(err) + } + + hProcess, err := windows.OpenProcess(windows.PROCESS_QUERY_LIMITED_INFORMATION, false, pid) + if err != nil { + panic(err) + } + cmdLine, err := process.QueryFullProcessImageName(hProcess, process.ImageNameFormatWin32Path) + if err != nil { + panic(err) + } + fmt.Println(cmdLine) } From ba066a84d1cb69da1af202334a391f63eca33ac5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan-Otto=20Kr=C3=B6pke?= Date: Sat, 16 Nov 2024 21:08:10 +0100 Subject: [PATCH 4/6] chore: optimize iphlpapi MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jan-Otto Kröpke --- test/main.go | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/test/main.go b/test/main.go index d2414da3b..3b2026003 100644 --- a/test/main.go +++ b/test/main.go @@ -2,6 +2,8 @@ package main import ( "fmt" + "syscall" + "unsafe" "github.com/Microsoft/go-winio/pkg/process" "github.com/prometheus-community/windows_exporter/internal/headers/iphlpapi" @@ -24,4 +26,27 @@ func main() { panic(err) } fmt.Println(cmdLine) + + // Load the file version information + size, err := windows.GetFileVersionInfoSize(cmdLine, nil) + if err != nil { + panic(err) + } + + data := make([]byte, size) + err = windows.GetFileVersionInfo(cmdLine, 0, uint32(len(data)), unsafe.Pointer(&data[0])) + if err != nil { + panic(err) + } + + var verSize uint32 + var verData *byte + + err = windows.VerQueryValue(unsafe.Pointer(&data[0]), `\StringFileInfo\040904E4\ProductVersion`, unsafe.Pointer(&verData), &verSize) + if err != nil { + panic(err) + } + + version := syscall.UTF16ToString((*[1 << 16]uint16)(unsafe.Pointer(verData))[:verSize]) + fmt.Println(version) } From 025a437b1f263480652bcb27e4f69791dadfca64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan-Otto=20Kr=C3=B6pke?= Date: Sat, 16 Nov 2024 21:24:35 +0100 Subject: [PATCH 5/6] mssql: expose server version info MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jan-Otto Kröpke --- docs/collector.mssql.md | 481 +++++++++++++++--------------- internal/collector/mssql/mssql.go | 104 ++++++- test/main.go | 4 +- 3 files changed, 348 insertions(+), 241 deletions(-) diff --git a/docs/collector.mssql.md b/docs/collector.mssql.md index 73fa6b905..d77d61e42 100644 --- a/docs/collector.mssql.md +++ b/docs/collector.mssql.md @@ -16,246 +16,251 @@ Comma-separated list of MSSQL WMI classes to use. Supported values are `accessme ### `--collectors.mssql.class-print` -If true, print available mssql WMI classes and exit. Only displays if the mssql collector is enabled. +If true, print available mssql WMI classes and exit. Only displays if the mssql collector is enabled.fman`, `databases`, `dbreplica`, `genstats`, `locks`, `memmgr`, `sqlstats`, `sqlerrors`, `transactions`, and `waitstats`. + +### `--collector.mssql.port` + +Port of MSSQL server used for `windows_mssql_info` metric. Default is `1433`. ## Metrics -Name | Description | Type | Labels ------|-------------|------|------- -`windows_mssql_collector_duration_seconds` | The time taken for each sub-collector to return | gauge | `collector`, `mssql_instance` -`windows_mssql_collector_success` | 1 if sub-collector succeeded, 0 otherwise | gauge | `collector`, `mssql_instance` -`windows_mssql_accessmethods_au_batch_cleanups` | The total number of batches that were completed successfully by the background task that cleans up deferred dropped allocation units | counter | `mssql_instance` -`windows_mssql_accessmethods_au_cleanups` | The total number of allocation units that were successfully dropped the background task that cleans up deferred dropped allocation units. Each allocation unit drop requires multiple batches | counter | `mssql_instance` -`windows_mssql_accessmethods_by_reference_lob_creates` | The total count of large object (lob) values that were passed by reference. By-reference lobs are used in certain bulk operations to avoid the cost of passing them by value | counter | `mssql_instance` -`windows_mssql_accessmethods_by_reference_lob_uses` | The total count of by-reference lob values that were used. By-reference lobs are used in certain bulk operations to avoid the cost of passing them by-value | counter | `mssql_instance` -`windows_mssql_accessmethods_lob_read_aheads` | The total count of lob pages on which readahead was issued | counter | `mssql_instance` -`windows_mssql_accessmethods_column_value_pulls` | The total count of column values that were pulled in-row from off-row | counter | `mssql_instance` -`windows_mssql_accessmethods_column_value_pushes` | The total count of column values that were pushed from in-row to off-row | counter | `mssql_instance` -`windows_mssql_accessmethods_deferred_dropped_aus` | The total number of allocation units waiting to be dropped by the background task that cleans up deferred dropped allocation units | gauge | `mssql_instance` -`windows_mssql_accessmethods_deferred_dropped_rowsets` | The number of rowsets created as a result of aborted online index build operations that are waiting to be dropped by the background task that cleans up deferred dropped rowsets | gauge | `mssql_instance` -`windows_mssql_accessmethods_dropped_rowset_cleanups` | The number of rowsets per second created as a result of aborted online index build operations that were successfully dropped by the background task that cleans up deferred dropped rowsets | counter | `mssql_instance` -`windows_mssql_accessmethods_dropped_rowset_skips` | The number of rowsets per second created as a result of aborted online index build operations that were skipped by the background task that cleans up deferred dropped rowsets created | counter | `mssql_instance` -`windows_mssql_accessmethods_extent_deallocations` | Number of extents deallocated per second in all databases in this instance of SQL Server | counter | `mssql_instance` -`windows_mssql_accessmethods_extent_allocations` | Number of extents allocated per second in all databases in this instance of SQL Server | counter | `mssql_instance` -`windows_mssql_accessmethods_au_batch_cleanup_failures` | The number of batches per second that failed and required retry, by the background task that cleans up deferred dropped allocation units. Failure could be due to lack of memory or disk space, hardware failure and other reasons | counter | `mssql_instance` -`windows_mssql_accessmethods_leaf_page_cookie_failures` | The number of times that a leaf page cookie could not be used during an index search since changes happened on the leaf page. The cookie is used to speed up index search | counter | `mssql_instance` -`windows_mssql_accessmethods_tree_page_cookie_failures` | The number of times that a tree page cookie could not be used during an index search since changes happened on the parent pages of those tree pages. The cookie is used to speed up index search | counter | `mssql_instance` -`windows_mssql_accessmethods_forwarded_records` | Number of records per second fetched through forwarded record pointers | counter | `mssql_instance` -`windows_mssql_accessmethods_free_space_page_fetches` | Number of pages fetched per second by free space scans. These scans search for free space within pages already allocated to an allocation unit, to satisfy requests to insert or modify record fragments | counter | `mssql_instance` -`windows_mssql_accessmethods_free_space_scans` | Number of scans per second that were initiated to search for free space within pages already allocated to an allocation unit to insert or modify record fragment. Each scan may find multiple pages | counter | `mssql_instance` -`windows_mssql_accessmethods_full_scans` | Number of unrestricted full scans per second. These can be either base-table or full-index scans | counter | `mssql_instance` -`windows_mssql_accessmethods_index_searches` | Number of index searches per second. These are used to start a range scan, reposition a range scan, revalidate a scan point, fetch a single index record, and search down the index to locate where to insert a new row | counter | `mssql_instance` -`windows_mssql_accessmethods_insysxact_waits` | Number of times a reader needs to wait for a page because the InSysXact bit is set | counter | `mssql_instance` -`windows_mssql_accessmethods_lob_handle_creates` | Count of temporary lobs created | counter | `mssql_instance` -`windows_mssql_accessmethods_lob_handle_destroys` | Count of temporary lobs destroyed | counter | `mssql_instance` -`windows_mssql_accessmethods_lob_ss_provider_creates` | Count of LOB Storage Service Providers (LobSSP) created. One worktable created per LobSSP | counter | `mssql_instance` -`windows_mssql_accessmethods_lob_ss_provider_destroys` | Count of LobSSP destroyed | counter | `mssql_instance` -`windows_mssql_accessmethods_lob_ss_provider_truncations` | Count of LobSSP truncated | counter | `mssql_instance` -`windows_mssql_accessmethods_mixed_page_allocations` | Number of pages allocated per second from mixed extents. These could be used for storing the IAM pages and the first eight pages that are allocated to an allocation unit | counter | `mssql_instance` -`windows_mssql_accessmethods_page_compression_attempts` | Number of pages evaluated for page-level compression. Includes pages that were not compressed because significant savings could be achieved. Includes all objects in the instance of SQL Server | counter | `mssql_instance` -`windows_mssql_accessmethods_page_deallocations` | Number of pages deallocated per second in all databases in this instance of SQL Server. These include pages from mixed extents and uniform extents | counter | `mssql_instance` -`windows_mssql_accessmethods_page_allocations` | Number of pages allocated per second in all databases in this instance of SQL Server. These include pages allocations from both mixed extents and uniform extents | counter | `mssql_instance` -`windows_mssql_accessmethods_page_compressions` | Number of data pages that are compressed by using PAGE compression. Includes all objects in the instance of SQL Server | counter | `mssql_instance` -`windows_mssql_accessmethods_page_splits` | Number of page splits per second that occur as the result of overflowing index pages | counter | `mssql_instance` -`windows_mssql_accessmethods_probe_scans` | Number of probe scans per second that are used to find at most one single qualified row in an index or base table directly | counter | `mssql_instance` -`windows_mssql_accessmethods_range_scans` | Number of qualified range scans through indexes per second | counter | `mssql_instance` -`windows_mssql_accessmethods_scan_point_revalidations` | Number of times per second that the scan point had to be revalidated to continue the scan | counter | `mssql_instance` -`windows_mssql_accessmethods_ghost_record_skips` | Number of ghosted records per second skipped during scans | counter | `mssql_instance` -`windows_mssql_accessmethods_table_lock_escalations` | Number of times locks on a table were escalated to the TABLE or HoBT granularity | counter | `mssql_instance` -`windows_mssql_accessmethods_leaf_page_cookie_uses` | Number of times a leaf page cookie is used successfully during an index search since no change happened on the leaf page. The cookie is used to speed up index search | counter | `mssql_instance` -`windows_mssql_accessmethods_tree_page_cookie_uses` | Number of times a tree page cookie is used successfully during an index search since no change happened on the parent page of the tree page. The cookie is used to speed up index search | counter | `mssql_instance` -`windows_mssql_accessmethods_workfile_creates` | Number of work files created per second. For example, work files could be used to store temporary results for hash joins and hash aggregates | counter | `mssql_instance` -`windows_mssql_accessmethods_worktables_creates` | Number of work tables created per second. For example, work tables could be used to store temporary results for query spool, lob variables, XML variables, and cursors | counter | `mssql_instance` -`windows_mssql_accessmethods_worktables_from_cache_ratio` | Percentage of work tables created where the initial two pages of the work table were not allocated but were immediately available from the work table cache | counter | `mssql_instance` -`windows_mssql_availreplica_received_from_replica_bytes` | Number of bytes received from the availability replica per second. Pings and status updates will generate network traffic even on databases with no user updates | counter | `mssql_instance`, `replica` -`windows_mssql_availreplica_sent_to_replica_bytes` | Number of bytes sent to the remote availability replica per second. On the primary replica this is the number of bytes sent to the secondary replica. On the secondary replica this is the number of bytes sent to the primary replica | counter | `mssql_instance`, `replica` -`windows_mssql_availreplica_sent_to_transport_bytes` | Actual number of bytes sent per second over the network to the remote availability replica. On the primary replica this is the number of bytes sent to the secondary replica. On the secondary replica this is the number of bytes sent to the primary replica | counter | `mssql_instance`, `replica` -`windows_mssql_availreplica_initiated_flow_controls` | Time in milliseconds that log stream messages waited for send flow control, in the last second | counter | `mssql_instance`, `replica` -`windows_mssql_availreplica_flow_control_wait_seconds` | Number of times flow-control initiated in the last second. Flow Control Time (ms/sec) divided by Flow Control/sec is the average time per wait | counter | `mssql_instance`, `replica` -`windows_mssql_availreplica_receives_from_replica` | Number of Always On messages received from thereplica per second | counter | `mssql_instance`, `replica` -`windows_mssql_availreplica_resent_messages` | Number of Always On messages resent in the last second | counter | `mssql_instance`, `replica` -`windows_mssql_availreplica_sends_to_replica` | Number of Always On messages sent to this availability replica per second | counter | `mssql_instance`, `replica` -`windows_mssql_availreplica_sends_to_transport` | Actual number of Always On messages sent per second over the network to the remote availability replica | counter | `mssql_instance`, `replica` -`windows_mssql_bufman_background_writer_pages` | Number of pages flushed to enforce the recovery interval settings | counter | `mssql_instance` -`windows_mssql_bufman_buffer_cache_hit_ratio` | Indicates the percentage of pages found in the buffer cache without having to read from disk. The ratio is the total number of cache hits divided by the total number of cache lookups over the last few thousand page accesses | gauge | `mssql_instance` -`windows_mssql_bufman_checkpoint_pages` | Indicates the number of pages flushed to disk per second by a checkpoint or other operation that require all dirty pages to be flushed | counter | `mssql_instance` -`windows_mssql_bufman_database_pages` | Indicates the number of pages in the buffer pool with database content | gauge | `mssql_instance` -`windows_mssql_bufman_extension_allocated_pages` | Total number of non-free cache pages in the buffer pool extension file | gauge | `mssql_instance` -`windows_mssql_bufman_extension_free_pages` | Total number of free cache pages in the buffer pool extension file | gauge | `mssql_instance` -`windows_mssql_bufman_extension_in_use_as_percentage` | _Not yet documented_ | gauge | `mssql_instance` -`windows_mssql_bufman_extension_outstanding_io` | Percentage of the buffer pool extension paging file occupied by buffer manager pages | gauge | `mssql_instance` -`windows_mssql_bufman_extension_page_evictions` | Number of pages evicted from the buffer pool extension file per second | counter | `mssql_instance` -`windows_mssql_bufman_extension_page_reads` | Number of pages read from the buffer pool extension file per second | counter | `mssql_instance` -`windows_mssql_bufman_extension_page_unreferenced_seconds` | Average seconds a page will stay in the buffer pool extension without references to it | gauge | `mssql_instance` -`windows_mssql_bufman_extension_page_writes` | Number of pages written to the buffer pool extension file per second | counter | `mssql_instance` -`windows_mssql_bufman_free_list_stalls` | Indicates the number of requests per second that had to wait for a free page | counter | `mssql_instance` -`windows_mssql_bufman_integral_controller_slope` | The slope that integral controller for the buffer pool last used, times -10 billion | gauge | `mssql_instance` -`windows_mssql_bufman_lazywrites` | Indicates the number of buffers written per second by the buffer manager's lazy writer | counter | `mssql_instance` -`windows_mssql_bufman_page_life_expectancy_seconds` | Indicates the number of seconds a page will stay in the buffer pool without references | gauge | `mssql_instance` -`windows_mssql_bufman_page_lookups` | Indicates the number of requests per second to find a page in the buffer pool | counter | `mssql_instance` -`windows_mssql_bufman_page_reads` | Indicates the number of physical database page reads that are issued per second | counter | `mssql_instance` -`windows_mssql_bufman_page_writes` | Indicates the number of physical database page writes that are issued per second | counter | `mssql_instance` -`windows_mssql_bufman_read_ahead_pages` | Indicates the number of pages read per second in anticipation of use | counter | `mssql_instance` -`windows_mssql_bufman_read_ahead_issuing_seconds` | Time (microseconds) spent issuing readahead | counter | `mssql_instance` -`windows_mssql_bufman_target_pages` | Ideal number of pages in the buffer pool | gauge | `mssql_instance` -`windows_mssql_dbreplica_database_flow_control_wait_seconds` | _Not yet documented_ | gauge | `mssql_instance`, `replica` -`windows_mssql_dbreplica_database_initiated_flow_controls` | _Not yet documented_ | counter | `mssql_instance`, `replica` -`windows_mssql_dbreplica_received_file_bytes` | _Not yet documented_ | counter | `mssql_instance`, `replica` -`windows_mssql_dbreplica_group_commits` | _Not yet documented_ | counter | `mssql_instance`, `replica` -`windows_mssql_dbreplica_group_commit_stall_seconds` | _Not yet documented_ | counter | `mssql_instance`, `replica` -`windows_mssql_dbreplica_log_apply_pending_queue` | _Not yet documented_ | gauge | `mssql_instance`, `replica` -`windows_mssql_dbreplica_log_apply_ready_queue` | _Not yet documented_ | gauge | `mssql_instance`, `replica` -`windows_mssql_dbreplica_log_compressed_bytes` | _Not yet documented_ | counter | `mssql_instance`, `replica` -`windows_mssql_dbreplica_log_decompressed_bytes` | _Not yet documented_ | counter | `mssql_instance`, `replica` -`windows_mssql_dbreplica_log_received_bytes` | _Not yet documented_ | counter | `mssql_instance`, `replica` -`windows_mssql_dbreplica_log_compression_cachehits` | _Not yet documented_ | counter | `mssql_instance`, `replica` -`windows_mssql_dbreplica_log_compression_cachemisses` | _Not yet documented_ | counter | `mssql_instance`, `replica` -`windows_mssql_dbreplica_log_compressions` | _Not yet documented_ | counter | `mssql_instance`, `replica` -`windows_mssql_dbreplica_log_decompressions` | _Not yet documented_ | counter | `mssql_instance`, `replica` -`windows_mssql_dbreplica_log_remaining_for_undo` | The amount of log, in bytes, remaining to complete the undo phase | gauge | `mssql_instance`, `replica` -`windows_mssql_dbreplica_log_send_queue` | Amount of log records in the log files of the primary database, in kilobytes, that haven't been sent to the secondary replica | gauge | `mssql_instance`, `replica` -`windows_mssql_dbreplica_mirrored_write_transactions` | Number of transactions that were written to the primary database and then waited to commit until the log was sent to the secondary database, in the last second | counter | `mssql_instance`, `replica` -`windows_mssql_dbreplica_recovery_queue_records` | Amount of log records in the log files of the secondary replica that have not been redone | gauge | `mssql_instance`, `replica` -`windows_mssql_dbreplica_redo_blocks` | Number of times the redo thread was blocked on locks held by readers of the database | counter | `mssql_instance`, `replica` -`windows_mssql_dbreplica_redo_remaining_bytes` | The amount of log, in kilobytes, remaining to be redone to finish the reverting phase | gauge | `mssql_instance`, `replica` -`windows_mssql_dbreplica_redone_bytes` | Amount of log records redone on the secondary database in the last second | counter | `mssql_instance`, `replica` -`windows_mssql_dbreplica_redones` | _Not yet documented_ | counter | `mssql_instance`, `replica` -`windows_mssql_dbreplica_total_log_requiring_undo` | Total kilobytes of log that must be undone | gauge | `mssql_instance`, `replica` -`windows_mssql_dbreplica_transaction_delay_seconds` | Delay in waiting for unterminated commit acknowledgment for all the current transactions | gauge | `mssql_instance`, `replica` -`windows_mssql_databases_active_transactions` | Number of active transactions for the database | gauge | `mssql_instance`, `database` -`windows_mssql_databases_backup_restore_operations` | Read/write throughput for backup and restore operations of a database per second | counter | `mssql_instance`, `database` -`windows_mssql_databases_bulk_copy_rows` | Number of rows bulk copied per second | counter | `mssql_instance`, `database` -`windows_mssql_databases_bulk_copy_bytes` | Amount of data bulk copied (in kilobytes) per second | counter | `mssql_instance`, `database` -`windows_mssql_databases_commit_table_entries` | he size (row count) of the in-memory portion of the commit table for the database | gauge | `mssql_instance`, `database` -`windows_mssql_databases_data_files_size_bytes` | Cumulative size (in kilobytes) of all the data files in the database including any automatic growth. Monitoring this counter is useful, for example, for determining the correct size of tempdb | gauge | `mssql_instance`, `database` -`windows_mssql_databases_dbcc_logical_scan_bytes` | Number of logical read scan bytes per second for database console commands (DBCC) | counter | `mssql_instance`, `database` -`windows_mssql_databases_group_commit_stall_seconds` | Group stall time (microseconds) per second | counter | `mssql_instance`, `database` -`windows_mssql_databases_log_flushed_bytes` | Total number of log bytes flushed | counter | `mssql_instance`, `database` -`windows_mssql_databases_log_cache_hit_ratio` | Percentage of log cache reads satisfied from the log cache | gauge | `mssql_instance`, `database` -`windows_mssql_databases_log_cache_reads` | Reads performed per second through the log manager cache | counter | `mssql_instance`, `database` -`windows_mssql_databases_log_files_size_bytes` | Cumulative size (in kilobytes) of all the transaction log files in the database | gauge | `mssql_instance`, `database` -`windows_mssql_databases_log_files_used_size_bytes` | The cumulative used size of all the log files in the database | gauge | `mssql_instance`, `database` -`windows_mssql_databases_log_flushes` | Total wait time (in milliseconds) to flush the log. On an Always On secondary database, this value indicates the wait time for log records to be hardened to disk | counter | `mssql_instance`, `database` -`windows_mssql_databases_log_flush_waits` | Number of commits per second waiting for the log flush | counter | `mssql_instance`, `database` -`windows_mssql_databases_log_flush_wait_seconds` | Number of commits per second waiting for the log flush | gauge | `mssql_instance`, `database` -`windows_mssql_databases_log_flush_write_seconds` | Time in milliseconds for performing writes of log flushes that were completed in the last second | gauge | `mssql_instance`, `database` -`windows_mssql_databases_log_growths` | Total number of times the transaction log for the database has been expanded | gauge | `mssql_instance`, `database` -`windows_mssql_databases_log_pool_cache_misses` | Number of requests for which the log block was not available in the log pool | counter | `mssql_instance`, `database` -`windows_mssql_databases_log_pool_disk_reads` | Number of disk reads that the log pool issued to fetch log blocks | counter | `mssql_instance`, `database` -`windows_mssql_databases_log_pool_hash_deletes` | Rate of raw hash entry deletes from the Log Pool | counter | `mssql_instance`, `database` -`windows_mssql_databases_log_pool_hash_inserts` | Rate of raw hash entry inserts into the Log Pool | counter | `mssql_instance`, `database` -`windows_mssql_databases_log_pool_invalid_hash_entries` | Rate of hash lookups failing due to being invalid | counter | `mssql_instance`, `database` -`windows_mssql_databases_log_pool_log_scan_pushes` | Rate of Log block pushes by log scans, which may come from disk or memory | counter | `mssql_instance`, `database` -`windows_mssql_databases_log_pool_log_writer_pushes` | Rate of Log block pushes by log writer thread | counter | `mssql_instance`, `database` -`windows_mssql_databases_log_pool_empty_free_pool_pushes` | Rate of Log block push fails due to empty free pool | counter | `mssql_instance`, `database` -`windows_mssql_databases_log_pool_low_memory_pushes` | Rate of Log block push fails due to being low on memory | counter | `mssql_instance`, `database` -`windows_mssql_databases_log_pool_no_free_buffer_pushes` | Rate of Log block push fails due to free buffer unavailable | counter | `mssql_instance`, `database` -`windows_mssql_databases_log_pool_req_behind_trunc` | Log pool cache misses due to block requested being behind truncation LSN | counter | `mssql_instance`, `database` -`windows_mssql_databases_log_pool_requests_old_vlf` | Log Pool requests that were not in the last VLF of the log | counter | `mssql_instance`, `database` -`windows_mssql_databases_log_pool_requests` | The number of log-block requests processed by the log pool | counter | `mssql_instance`, `database` -`windows_mssql_databases_log_pool_total_active_log_bytes` | Current total active log stored in the shared cache buffer manager in bytes | gauge | `mssql_instance`, `database` -`windows_mssql_databases_log_pool_total_shared_pool_bytes` | Current total memory usage of the shared cache buffer manager in bytes | gauge | `mssql_instance`, `database` -`windows_mssql_databases_log_shrinks` | Total number of log shrinks for this database | gauge | `mssql_instance`, `database` -`windows_mssql_databases_log_truncations` | The number of times the transaction log has been truncated (in Simple Recovery Model) | gauge | `mssql_instance`, `database` -`windows_mssql_databases_log_used_percent` | Percentage of space in the log that is in use | gauge | `mssql_instance`, `database` -`windows_mssql_databases_pending_repl_transactions` | Number of transactions in the transaction log of the publication database marked for replication, but not yet delivered to the distribution database | gauge | `mssql_instance`, `database` -`windows_mssql_databases_repl_transactions` | Number of transactions per second read out of the transaction log of the publication database and delivered to the distribution database | counter | `mssql_instance`, `database` -`windows_mssql_databases_shrink_data_movement_bytes` | Amount of data being moved per second by autoshrink operations, or DBCC SHRINKDATABASE or DBCC SHRINKFILE statements | counter | `mssql_instance`, `database` -`windows_mssql_databases_tracked_transactions` | Number of committed transactions recorded in the commit table for the database | counter | `mssql_instance`, `database` -`windows_mssql_databases_transactions` | Number of transactions started for the database per second | counter | `mssql_instance`, `database` -`windows_mssql_databases_write_transactions` | Number of transactions that wrote to the database and committed, in the last second | counter | `mssql_instance`, `database` -`windows_mssql_databases_xtp_controller_dlc_fetch_latency_seconds` | Average latency in microseconds between log blocks entering the Direct Log Consumer and being retrieved by the XTP controller, per second | gauge | `mssql_instance`, `database` -`windows_mssql_databases_xtp_controller_dlc_peak_latency_seconds` | The largest recorded latency, in microseconds, of a fetch from the Direct Log Consumer by the XTP controller | gauge | `mssql_instance`, `database` -`windows_mssql_databases_xtp_controller_log_processed_bytes` | The amount of log bytes processed by the XTP controller thread, per second | counter | `mssql_instance`, `database` -`windows_mssql_databases_xtp_memory_used_bytes` | The amount of memory used by XTP in the database | gauge | `mssql_instance`, `database` -`windows_mssql_genstats_active_temp_tables` | Number of temporary tables/table variables in use | gauge | `mssql_instance` -`windows_mssql_genstats_connection_resets` | Total number of logins started from the connection pool | counter | `mssql_instance` -`windows_mssql_genstats_event_notifications_delayed_drop` | Number of event notifications waiting to be dropped by a system thread | gauge | `mssql_instance` -`windows_mssql_genstats_http_authenticated_requests` | Number of authenticated HTTP requests started per second | gauge | `mssql_instance` -`windows_mssql_genstats_logical_connections` | Number of logical connections to the system | gauge | `mssql_instance` -`windows_mssql_genstats_logins` | Total number of logins started per second. This does not include pooled connections | counter | `mssql_instance` -`windows_mssql_genstats_logouts` | Total number of logout operations started per second | counter | `mssql_instance` -`windows_mssql_genstats_mars_deadlocks` | Number of MARS deadlocks detected | gauge | `mssql_instance` -`windows_mssql_genstats_non_atomic_yields` | Number of non-atomic yields per second | counter | `mssql_instance` -`windows_mssql_genstats_blocked_processes` | Number of currently blocked processes | gauge | `mssql_instance` -`windows_mssql_genstats_soap_empty_requests` | Number of empty SOAP requests started per second | gauge | `mssql_instance` -`windows_mssql_genstats_soap_method_invocations` | Number of SOAP method invocations started per second | gauge | `mssql_instance` -`windows_mssql_genstats_soap_session_initiate_requests` | Number of SOAP Session initiate requests started per second | gauge | `mssql_instance` -`windows_mssql_genstats_soap_session_terminate_requests` | Number of SOAP Session terminate requests started per second | gauge | `mssql_instance` -`windows_mssql_genstats_soapsql_requests` | Number of SOAP SQL requests started per second | gauge | `mssql_instance` -`windows_mssql_genstats_soapwsdl_requests` | Number of SOAP Web Service Description Language requests started per second | gauge | `mssql_instance` -`windows_mssql_genstats_sql_trace_io_provider_lock_waits` | Number of waits for the File IO Provider lock per second | gauge | `mssql_instance` -`windows_mssql_genstats_tempdb_recovery_unit_ids_generated` | Number of duplicate tempdb recovery unit id generated | gauge | `mssql_instance` -`windows_mssql_genstats_tempdb_rowset_ids_generated` | Number of duplicate tempdb rowset id generated | gauge | `mssql_instance` -`windows_mssql_genstats_temp_tables_creations` | Number of temporary tables/table variables created per second | counter | `mssql_instance` -`windows_mssql_genstats_temp_tables_awaiting_destruction` | Number of temporary tables/table variables waiting to be destroyed by the cleanup system thread | gauge | `mssql_instance` -`windows_mssql_genstats_trace_event_notification_queue_size` | Number of trace event notification instances waiting in the internal queue to be sent through Service Broker | gauge | `mssql_instance` -`windows_mssql_genstats_transactions` | Number of transaction enlistments (local, DTC, bound all combined) | gauge | `mssql_instance` -`windows_mssql_genstats_user_connections` | Counts the number of users currently connected to SQL Server | gauge | `mssql_instance` -`windows_mssql_locks_average_wait_seconds` | Average amount of wait time (in milliseconds) for each lock request that resulted in a wait | gauge | `mssql_instance`, `resource` -`windows_mssql_locks_lock_requests` | Number of new locks and lock conversions per second requested from the lock manager | counter | `mssql_instance`, `resource` -`windows_mssql_locks_lock_timeouts` | Number of lock requests per second that timed out, including requests for NOWAIT locks | counter | `mssql_instance`, `resource` -`windows_mssql_locks_lock_timeouts_excluding_NOWAIT` | Number of lock requests per second that timed out, but excluding requests for NOWAIT locks | counter | `mssql_instance`, `resource` -`windows_mssql_locks_lock_waits` | Total wait time (in milliseconds) for locks in the last second | counter | `mssql_instance`, `resource` -`windows_mssql_locks_lock_wait_seconds` | Number of lock requests per second that required the caller to wait | gauge | `mssql_instance`, `resource` -`windows_mssql_locks_deadlocks` | Number of lock requests per second that resulted in a deadlock | counter | `mssql_instance`, `resource` -`windows_mssql_memmgr_connection_memory_bytes` | Specifies the total amount of dynamic memory the server is using for maintaining connections | gauge | `mssql_instance` -`windows_mssql_memmgr_database_cache_memory_bytes` | Specifies the amount of memory the server is currently using for the database pages cache | gauge | `mssql_instance` -`windows_mssql_memmgr_external_benefit_of_memory` | An internal estimation of the performance benefit from adding memory to a specific cache | gauge | `mssql_instance` -`windows_mssql_memmgr_free_memory_bytes` | Specifies the amount of committed memory currently not used by the server | gauge | `mssql_instance` -`windows_mssql_memmgr_granted_workspace_memory_bytes` | Specifies the total amount of memory currently granted to executing processes, such as hash, sort, bulk copy, and index creation operations | gauge | `mssql_instance` -`windows_mssql_memmgr_lock_blocks` | Specifies the current number of lock blocks in use on the server (refreshed periodically). A lock block represents an individual locked resource, such as a table, page, or row | gauge | `mssql_instance` -`windows_mssql_memmgr_allocated_lock_blocks` | Specifies the current number of allocated lock blocks. At server startup, the number of allocated lock blocks plus the number of allocated lock owner blocks depends on the SQL Server Locks configuration option. If more lock blocks are needed, the value increases | gauge | `mssql_instance` -`windows_mssql_memmgr_lock_memory_bytes` | Specifies the total amount of dynamic memory the server is using for locks | gauge | `mssql_instance` -`windows_mssql_memmgr_lock_owner_blocks` | Specifies the current number of allocated lock owner blocks. At server startup, the number of allocated lock owner blocks and the number of allocated lock blocks depend on the SQL Server Locks configuration option. If more lock owner blocks are needed, the value increases dynamically | gauge | `mssql_instance` -`windows_mssql_memmgr_allocated_lock_owner_blocks` | _Not yet documented_ | gauge | `mssql_instance` -`windows_mssql_memmgr_log_pool_memory_bytes` | Total amount of dynamic memory the server is using for Log Pool | gauge | `mssql_instance` -`windows_mssql_memmgr_maximum_workspace_memory_bytes` | Indicates the maximum amount of memory available for executing processes, such as hash, sort, bulk copy, and index creation operations | gauge | `mssql_instance` -`windows_mssql_memmgr_outstanding_memory_grants` | Specifies the total number of processes that have successfully acquired a workspace memory grant | gauge | `mssql_instance` -`windows_mssql_memmgr_pending_memory_grants` | Specifies the total number of processes waiting for a workspace memory grant | gauge | `mssql_instance` -`windows_mssql_memmgr_optimizer_memory_bytes` | Specifies the total amount of dynamic memory the server is using for query optimization | gauge | `mssql_instance` -`windows_mssql_memmgr_reserved_server_memory_bytes` | ndicates the amount of memory the server has reserved for future usage. This counter shows the current unused amount of memory initially granted that is shown in Granted Workspace Memory | gauge | `mssql_instance` -`windows_mssql_memmgr_sql_cache_memory_bytes` | Specifies the total amount of dynamic memory the server is using for the dynamic SQL cache | gauge | `mssql_instance` -`windows_mssql_memmgr_stolen_server_memory_bytes` | Specifies the amount of memory the server is using for purposes other than database pages | gauge | `mssql_instance` -`windows_mssql_memmgr_target_server_memory_bytes` | Indicates the ideal amount of memory the server can consume | gauge | `mssql_instance` -`windows_mssql_memmgr_total_server_memory_bytes` | Specifies the amount of memory the server has committed using the memory manager | gauge | `mssql_instance` -`windows_mssql_sqlstats_auto_parameterization_attempts` | Number of failed auto-parameterization attempts per second. This should be small. Note that auto-parameterizations are also known as simple parameterizations in later versions of SQL Server | counter | `mssql_instance` -`windows_mssql_sqlstats_batch_requests` | _Not yet documented_ | counter | `mssql_instance` -`windows_mssql_sqlstats_failed_auto_parameterization_attempts` | _Not yet documented_ | counter | `mssql_instance` -`windows_mssql_sqlstats_forced_parameterizations` | Number of successful forced parameterizations per second | counter | `mssql_instance` -`windows_mssql_sqlstats_guided_plan_executions` | Number of plan executions per second in which the query plan has been generated by using a plan guide | counter | `mssql_instance` -`windows_mssql_sqlstats_misguided_plan_executions` | Number of plan executions per second in which a plan guide could not be honored during plan generation | counter | `mssql_instance` -`windows_mssql_sqlstats_safe_auto_parameterization_attempts` | Number of safe auto-parameterization attempts per second | counter | `mssql_instance` -`windows_mssql_sqlstats_sql_attentions` | Number of attentions per second | counter | `mssql_instance` -`windows_mssql_sqlstats_sql_compilations` | Number of SQL compilations per second | counter | `mssql_instance` -`windows_mssql_sqlstats_sql_recompilations` | Number of statement recompiles per second | counter | `mssql_instance` -`windows_mssql_sqlstats_unsafe_auto_parameterization_attempts` | Number of unsafe auto-parameterization attempts per second. | counter | `mssql_instance` -`windows_mssql_sql_errors_total` | Information for all errors | counter | `mssql_instance`, `resource` -`windows_mssql_transactions_tempdb_free_space_bytes` | The amount of space (in kilobytes) available in tempdb | gauge | `mssql_instance` -`windows_mssql_transactions_longest_transaction_running_seconds` | The length of time (in seconds) since the start of the transaction that has been active longer than any other current transaction | gauge | `mssql_instance` -`windows_mssql_transactions_nonsnapshot_version_active_total` | The number of currently active transactions that are not using snapshot isolation level and have made data modifications that have generated row versions in the tempdb version store | counter | `mssql_instance` -`windows_mssql_transactions_snapshot_active_total` | The number of currently active transactions using the snapshot isolation level | counter | `mssql_instance` -`windows_mssql_transactions_active` | The number of currently active transactions of all types | gauge | `mssql_instance` -`windows_mssql_transactions_update_conflicts_total` | The percentage of those transactions using the snapshot isolation level that have encountered update conflicts within the last second | counter | `mssql_instance` -`windows_mssql_transactions_update_snapshot_active_total` | The number of currently active transactions using the snapshot isolation level and have modified data | counter | `mssql_instance` -`windows_mssql_transactions_version_cleanup_rate_bytes` | The rate (in kilobytes per second) at which row versions are removed from the snapshot isolation version store in tempdb | gauge | `mssql_instance` -`windows_mssql_transactions_version_generation_rate_bytes` | The rate (in kilobytes per second) at which new row versions are added to the snapshot isolation version store in tempdb | gauge | `mssql_instance` -`windows_mssql_transactions_version_store_size_bytes` | he amount of space (in kilobytes) in tempdb being used to store snapshot isolation level row versions | gauge | `mssql_instance` -`windows_mssql_transactions_version_store_units` | The number of active allocation units in the snapshot isolation version store in tempdb | counter | `mssql_instance` -`windows_mssql_transactions_version_store_creation_units` | The number of allocation units that have been created in the snapshot isolation store since the instance of the Database Engine was started | counter | `mssql_instance` -`windows_mssql_transactions_version_store_truncation_units` | The number of allocation units that have been removed from the snapshot isolation store since the instance of the Database Engine was started | counter | `mssql_instance` -`windows_mssql_waitstats_lock_waits` | Statistics for processes waiting on a lock | gauge | `mssql_instance`, `item` -`windows_mssql_waitstats_memory_grant_queue_waits` | Statistics for processes waiting for memory grant to become available | gauge | `mssql_instance`, `item` -`windows_mssql_waitstats_thread_safe_memory_objects_waits` | Statistics for processes waiting on thread-safe memory allocators | gauge | `mssql_instance`, `item` -`windows_mssql_waitstats_log_write_waits` | Statistics for processes waiting for log buffer to be written | gauge | `mssql_instance`, `item` -`windows_mssql_waitstats_log_buffer_waits` | Statistics for processes waiting for log buffer to be available | gauge | `mssql_instance`, `item` -`windows_mssql_waitstats_network_io_waits` | Statistics relevant to wait on network I/O | gauge | `mssql_instance`, `item` -`windows_mssql_waitstats_page_io_latch_waits` | Statistics relevant to page I/O latches | gauge | `mssql_instance`, `item` -`windows_mssql_waitstats_page_latch_waits` | Statistics relevant to page latches, not including I/O latches | gauge | `mssql_instance`, `item` -`windows_mssql_waitstats_nonpage_latch_waits` | Statistics relevant to non-page latches | gauge | `mssql_instance`, `item` -`windows_mssql_waitstats_wait_for_the_worker_waits` | Statistics relevant to processes waiting for worker to become available | gauge | `mssql_instance`, `item` -`windows_mssql_waitstats_workspace_synchronization_waits` | Statistics relevant to processes synchronizing access to workspace | gauge | `mssql_instance`, `item` -`windows_mssql_waitstats_transaction_ownership_waits` | Statistics relevant to processes synchronizing access to transaction | gauge | `mssql_instance`, `item` +| Name | Description | Type | Labels | +|--------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------|-------------------------------| +| `windows_mssql_info` | Returns infomation about the MSSQL server running on port 1433 | gauge | `version` | +| `windows_mssql_collector_duration_seconds` | The time taken for each sub-collector to return | gauge | `collector`, `mssql_instance` | +| `windows_mssql_collector_success` | 1 if sub-collector succeeded, 0 otherwise | gauge | `collector`, `mssql_instance` | +| `windows_mssql_accessmethods_au_batch_cleanups` | The total number of batches that were completed successfully by the background task that cleans up deferred dropped allocation units | counter | `mssql_instance` | +| `windows_mssql_accessmethods_au_cleanups` | The total number of allocation units that were successfully dropped the background task that cleans up deferred dropped allocation units. Each allocation unit drop requires multiple batches | counter | `mssql_instance` | +| `windows_mssql_accessmethods_by_reference_lob_creates` | The total count of large object (lob) values that were passed by reference. By-reference lobs are used in certain bulk operations to avoid the cost of passing them by value | counter | `mssql_instance` | +| `windows_mssql_accessmethods_by_reference_lob_uses` | The total count of by-reference lob values that were used. By-reference lobs are used in certain bulk operations to avoid the cost of passing them by-value | counter | `mssql_instance` | +| `windows_mssql_accessmethods_lob_read_aheads` | The total count of lob pages on which readahead was issued | counter | `mssql_instance` | +| `windows_mssql_accessmethods_column_value_pulls` | The total count of column values that were pulled in-row from off-row | counter | `mssql_instance` | +| `windows_mssql_accessmethods_column_value_pushes` | The total count of column values that were pushed from in-row to off-row | counter | `mssql_instance` | +| `windows_mssql_accessmethods_deferred_dropped_aus` | The total number of allocation units waiting to be dropped by the background task that cleans up deferred dropped allocation units | gauge | `mssql_instance` | +| `windows_mssql_accessmethods_deferred_dropped_rowsets` | The number of rowsets created as a result of aborted online index build operations that are waiting to be dropped by the background task that cleans up deferred dropped rowsets | gauge | `mssql_instance` | +| `windows_mssql_accessmethods_dropped_rowset_cleanups` | The number of rowsets per second created as a result of aborted online index build operations that were successfully dropped by the background task that cleans up deferred dropped rowsets | counter | `mssql_instance` | +| `windows_mssql_accessmethods_dropped_rowset_skips` | The number of rowsets per second created as a result of aborted online index build operations that were skipped by the background task that cleans up deferred dropped rowsets created | counter | `mssql_instance` | +| `windows_mssql_accessmethods_extent_deallocations` | Number of extents deallocated per second in all databases in this instance of SQL Server | counter | `mssql_instance` | +| `windows_mssql_accessmethods_extent_allocations` | Number of extents allocated per second in all databases in this instance of SQL Server | counter | `mssql_instance` | +| `windows_mssql_accessmethods_au_batch_cleanup_failures` | The number of batches per second that failed and required retry, by the background task that cleans up deferred dropped allocation units. Failure could be due to lack of memory or disk space, hardware failure and other reasons | counter | `mssql_instance` | +| `windows_mssql_accessmethods_leaf_page_cookie_failures` | The number of times that a leaf page cookie could not be used during an index search since changes happened on the leaf page. The cookie is used to speed up index search | counter | `mssql_instance` | +| `windows_mssql_accessmethods_tree_page_cookie_failures` | The number of times that a tree page cookie could not be used during an index search since changes happened on the parent pages of those tree pages. The cookie is used to speed up index search | counter | `mssql_instance` | +| `windows_mssql_accessmethods_forwarded_records` | Number of records per second fetched through forwarded record pointers | counter | `mssql_instance` | +| `windows_mssql_accessmethods_free_space_page_fetches` | Number of pages fetched per second by free space scans. These scans search for free space within pages already allocated to an allocation unit, to satisfy requests to insert or modify record fragments | counter | `mssql_instance` | +| `windows_mssql_accessmethods_free_space_scans` | Number of scans per second that were initiated to search for free space within pages already allocated to an allocation unit to insert or modify record fragment. Each scan may find multiple pages | counter | `mssql_instance` | +| `windows_mssql_accessmethods_full_scans` | Number of unrestricted full scans per second. These can be either base-table or full-index scans | counter | `mssql_instance` | +| `windows_mssql_accessmethods_index_searches` | Number of index searches per second. These are used to start a range scan, reposition a range scan, revalidate a scan point, fetch a single index record, and search down the index to locate where to insert a new row | counter | `mssql_instance` | +| `windows_mssql_accessmethods_insysxact_waits` | Number of times a reader needs to wait for a page because the InSysXact bit is set | counter | `mssql_instance` | +| `windows_mssql_accessmethods_lob_handle_creates` | Count of temporary lobs created | counter | `mssql_instance` | +| `windows_mssql_accessmethods_lob_handle_destroys` | Count of temporary lobs destroyed | counter | `mssql_instance` | +| `windows_mssql_accessmethods_lob_ss_provider_creates` | Count of LOB Storage Service Providers (LobSSP) created. One worktable created per LobSSP | counter | `mssql_instance` | +| `windows_mssql_accessmethods_lob_ss_provider_destroys` | Count of LobSSP destroyed | counter | `mssql_instance` | +| `windows_mssql_accessmethods_lob_ss_provider_truncations` | Count of LobSSP truncated | counter | `mssql_instance` | +| `windows_mssql_accessmethods_mixed_page_allocations` | Number of pages allocated per second from mixed extents. These could be used for storing the IAM pages and the first eight pages that are allocated to an allocation unit | counter | `mssql_instance` | +| `windows_mssql_accessmethods_page_compression_attempts` | Number of pages evaluated for page-level compression. Includes pages that were not compressed because significant savings could be achieved. Includes all objects in the instance of SQL Server | counter | `mssql_instance` | +| `windows_mssql_accessmethods_page_deallocations` | Number of pages deallocated per second in all databases in this instance of SQL Server. These include pages from mixed extents and uniform extents | counter | `mssql_instance` | +| `windows_mssql_accessmethods_page_allocations` | Number of pages allocated per second in all databases in this instance of SQL Server. These include pages allocations from both mixed extents and uniform extents | counter | `mssql_instance` | +| `windows_mssql_accessmethods_page_compressions` | Number of data pages that are compressed by using PAGE compression. Includes all objects in the instance of SQL Server | counter | `mssql_instance` | +| `windows_mssql_accessmethods_page_splits` | Number of page splits per second that occur as the result of overflowing index pages | counter | `mssql_instance` | +| `windows_mssql_accessmethods_probe_scans` | Number of probe scans per second that are used to find at most one single qualified row in an index or base table directly | counter | `mssql_instance` | +| `windows_mssql_accessmethods_range_scans` | Number of qualified range scans through indexes per second | counter | `mssql_instance` | +| `windows_mssql_accessmethods_scan_point_revalidations` | Number of times per second that the scan point had to be revalidated to continue the scan | counter | `mssql_instance` | +| `windows_mssql_accessmethods_ghost_record_skips` | Number of ghosted records per second skipped during scans | counter | `mssql_instance` | +| `windows_mssql_accessmethods_table_lock_escalations` | Number of times locks on a table were escalated to the TABLE or HoBT granularity | counter | `mssql_instance` | +| `windows_mssql_accessmethods_leaf_page_cookie_uses` | Number of times a leaf page cookie is used successfully during an index search since no change happened on the leaf page. The cookie is used to speed up index search | counter | `mssql_instance` | +| `windows_mssql_accessmethods_tree_page_cookie_uses` | Number of times a tree page cookie is used successfully during an index search since no change happened on the parent page of the tree page. The cookie is used to speed up index search | counter | `mssql_instance` | +| `windows_mssql_accessmethods_workfile_creates` | Number of work files created per second. For example, work files could be used to store temporary results for hash joins and hash aggregates | counter | `mssql_instance` | +| `windows_mssql_accessmethods_worktables_creates` | Number of work tables created per second. For example, work tables could be used to store temporary results for query spool, lob variables, XML variables, and cursors | counter | `mssql_instance` | +| `windows_mssql_accessmethods_worktables_from_cache_ratio` | Percentage of work tables created where the initial two pages of the work table were not allocated but were immediately available from the work table cache | counter | `mssql_instance` | +| `windows_mssql_availreplica_received_from_replica_bytes` | Number of bytes received from the availability replica per second. Pings and status updates will generate network traffic even on databases with no user updates | counter | `mssql_instance`, `replica` | +| `windows_mssql_availreplica_sent_to_replica_bytes` | Number of bytes sent to the remote availability replica per second. On the primary replica this is the number of bytes sent to the secondary replica. On the secondary replica this is the number of bytes sent to the primary replica | counter | `mssql_instance`, `replica` | +| `windows_mssql_availreplica_sent_to_transport_bytes` | Actual number of bytes sent per second over the network to the remote availability replica. On the primary replica this is the number of bytes sent to the secondary replica. On the secondary replica this is the number of bytes sent to the primary replica | counter | `mssql_instance`, `replica` | +| `windows_mssql_availreplica_initiated_flow_controls` | Time in milliseconds that log stream messages waited for send flow control, in the last second | counter | `mssql_instance`, `replica` | +| `windows_mssql_availreplica_flow_control_wait_seconds` | Number of times flow-control initiated in the last second. Flow Control Time (ms/sec) divided by Flow Control/sec is the average time per wait | counter | `mssql_instance`, `replica` | +| `windows_mssql_availreplica_receives_from_replica` | Number of Always On messages received from thereplica per second | counter | `mssql_instance`, `replica` | +| `windows_mssql_availreplica_resent_messages` | Number of Always On messages resent in the last second | counter | `mssql_instance`, `replica` | +| `windows_mssql_availreplica_sends_to_replica` | Number of Always On messages sent to this availability replica per second | counter | `mssql_instance`, `replica` | +| `windows_mssql_availreplica_sends_to_transport` | Actual number of Always On messages sent per second over the network to the remote availability replica | counter | `mssql_instance`, `replica` | +| `windows_mssql_bufman_background_writer_pages` | Number of pages flushed to enforce the recovery interval settings | counter | `mssql_instance` | +| `windows_mssql_bufman_buffer_cache_hit_ratio` | Indicates the percentage of pages found in the buffer cache without having to read from disk. The ratio is the total number of cache hits divided by the total number of cache lookups over the last few thousand page accesses | gauge | `mssql_instance` | +| `windows_mssql_bufman_checkpoint_pages` | Indicates the number of pages flushed to disk per second by a checkpoint or other operation that require all dirty pages to be flushed | counter | `mssql_instance` | +| `windows_mssql_bufman_database_pages` | Indicates the number of pages in the buffer pool with database content | gauge | `mssql_instance` | +| `windows_mssql_bufman_extension_allocated_pages` | Total number of non-free cache pages in the buffer pool extension file | gauge | `mssql_instance` | +| `windows_mssql_bufman_extension_free_pages` | Total number of free cache pages in the buffer pool extension file | gauge | `mssql_instance` | +| `windows_mssql_bufman_extension_in_use_as_percentage` | _Not yet documented_ | gauge | `mssql_instance` | +| `windows_mssql_bufman_extension_outstanding_io` | Percentage of the buffer pool extension paging file occupied by buffer manager pages | gauge | `mssql_instance` | +| `windows_mssql_bufman_extension_page_evictions` | Number of pages evicted from the buffer pool extension file per second | counter | `mssql_instance` | +| `windows_mssql_bufman_extension_page_reads` | Number of pages read from the buffer pool extension file per second | counter | `mssql_instance` | +| `windows_mssql_bufman_extension_page_unreferenced_seconds` | Average seconds a page will stay in the buffer pool extension without references to it | gauge | `mssql_instance` | +| `windows_mssql_bufman_extension_page_writes` | Number of pages written to the buffer pool extension file per second | counter | `mssql_instance` | +| `windows_mssql_bufman_free_list_stalls` | Indicates the number of requests per second that had to wait for a free page | counter | `mssql_instance` | +| `windows_mssql_bufman_integral_controller_slope` | The slope that integral controller for the buffer pool last used, times -10 billion | gauge | `mssql_instance` | +| `windows_mssql_bufman_lazywrites` | Indicates the number of buffers written per second by the buffer manager's lazy writer | counter | `mssql_instance` | +| `windows_mssql_bufman_page_life_expectancy_seconds` | Indicates the number of seconds a page will stay in the buffer pool without references | gauge | `mssql_instance` | +| `windows_mssql_bufman_page_lookups` | Indicates the number of requests per second to find a page in the buffer pool | counter | `mssql_instance` | +| `windows_mssql_bufman_page_reads` | Indicates the number of physical database page reads that are issued per second | counter | `mssql_instance` | +| `windows_mssql_bufman_page_writes` | Indicates the number of physical database page writes that are issued per second | counter | `mssql_instance` | +| `windows_mssql_bufman_read_ahead_pages` | Indicates the number of pages read per second in anticipation of use | counter | `mssql_instance` | +| `windows_mssql_bufman_read_ahead_issuing_seconds` | Time (microseconds) spent issuing readahead | counter | `mssql_instance` | +| `windows_mssql_bufman_target_pages` | Ideal number of pages in the buffer pool | gauge | `mssql_instance` | +| `windows_mssql_dbreplica_database_flow_control_wait_seconds` | _Not yet documented_ | gauge | `mssql_instance`, `replica` | +| `windows_mssql_dbreplica_database_initiated_flow_controls` | _Not yet documented_ | counter | `mssql_instance`, `replica` | +| `windows_mssql_dbreplica_received_file_bytes` | _Not yet documented_ | counter | `mssql_instance`, `replica` | +| `windows_mssql_dbreplica_group_commits` | _Not yet documented_ | counter | `mssql_instance`, `replica` | +| `windows_mssql_dbreplica_group_commit_stall_seconds` | _Not yet documented_ | counter | `mssql_instance`, `replica` | +| `windows_mssql_dbreplica_log_apply_pending_queue` | _Not yet documented_ | gauge | `mssql_instance`, `replica` | +| `windows_mssql_dbreplica_log_apply_ready_queue` | _Not yet documented_ | gauge | `mssql_instance`, `replica` | +| `windows_mssql_dbreplica_log_compressed_bytes` | _Not yet documented_ | counter | `mssql_instance`, `replica` | +| `windows_mssql_dbreplica_log_decompressed_bytes` | _Not yet documented_ | counter | `mssql_instance`, `replica` | +| `windows_mssql_dbreplica_log_received_bytes` | _Not yet documented_ | counter | `mssql_instance`, `replica` | +| `windows_mssql_dbreplica_log_compression_cachehits` | _Not yet documented_ | counter | `mssql_instance`, `replica` | +| `windows_mssql_dbreplica_log_compression_cachemisses` | _Not yet documented_ | counter | `mssql_instance`, `replica` | +| `windows_mssql_dbreplica_log_compressions` | _Not yet documented_ | counter | `mssql_instance`, `replica` | +| `windows_mssql_dbreplica_log_decompressions` | _Not yet documented_ | counter | `mssql_instance`, `replica` | +| `windows_mssql_dbreplica_log_remaining_for_undo` | The amount of log, in bytes, remaining to complete the undo phase | gauge | `mssql_instance`, `replica` | +| `windows_mssql_dbreplica_log_send_queue` | Amount of log records in the log files of the primary database, in kilobytes, that haven't been sent to the secondary replica | gauge | `mssql_instance`, `replica` | +| `windows_mssql_dbreplica_mirrored_write_transactions` | Number of transactions that were written to the primary database and then waited to commit until the log was sent to the secondary database, in the last second | counter | `mssql_instance`, `replica` | +| `windows_mssql_dbreplica_recovery_queue_records` | Amount of log records in the log files of the secondary replica that have not been redone | gauge | `mssql_instance`, `replica` | +| `windows_mssql_dbreplica_redo_blocks` | Number of times the redo thread was blocked on locks held by readers of the database | counter | `mssql_instance`, `replica` | +| `windows_mssql_dbreplica_redo_remaining_bytes` | The amount of log, in kilobytes, remaining to be redone to finish the reverting phase | gauge | `mssql_instance`, `replica` | +| `windows_mssql_dbreplica_redone_bytes` | Amount of log records redone on the secondary database in the last second | counter | `mssql_instance`, `replica` | +| `windows_mssql_dbreplica_redones` | _Not yet documented_ | counter | `mssql_instance`, `replica` | +| `windows_mssql_dbreplica_total_log_requiring_undo` | Total kilobytes of log that must be undone | gauge | `mssql_instance`, `replica` | +| `windows_mssql_dbreplica_transaction_delay_seconds` | Delay in waiting for unterminated commit acknowledgment for all the current transactions | gauge | `mssql_instance`, `replica` | +| `windows_mssql_databases_active_transactions` | Number of active transactions for the database | gauge | `mssql_instance`, `database` | +| `windows_mssql_databases_backup_restore_operations` | Read/write throughput for backup and restore operations of a database per second | counter | `mssql_instance`, `database` | +| `windows_mssql_databases_bulk_copy_rows` | Number of rows bulk copied per second | counter | `mssql_instance`, `database` | +| `windows_mssql_databases_bulk_copy_bytes` | Amount of data bulk copied (in kilobytes) per second | counter | `mssql_instance`, `database` | +| `windows_mssql_databases_commit_table_entries` | he size (row count) of the in-memory portion of the commit table for the database | gauge | `mssql_instance`, `database` | +| `windows_mssql_databases_data_files_size_bytes` | Cumulative size (in kilobytes) of all the data files in the database including any automatic growth. Monitoring this counter is useful, for example, for determining the correct size of tempdb | gauge | `mssql_instance`, `database` | +| `windows_mssql_databases_dbcc_logical_scan_bytes` | Number of logical read scan bytes per second for database console commands (DBCC) | counter | `mssql_instance`, `database` | +| `windows_mssql_databases_group_commit_stall_seconds` | Group stall time (microseconds) per second | counter | `mssql_instance`, `database` | +| `windows_mssql_databases_log_flushed_bytes` | Total number of log bytes flushed | counter | `mssql_instance`, `database` | +| `windows_mssql_databases_log_cache_hit_ratio` | Percentage of log cache reads satisfied from the log cache | gauge | `mssql_instance`, `database` | +| `windows_mssql_databases_log_cache_reads` | Reads performed per second through the log manager cache | counter | `mssql_instance`, `database` | +| `windows_mssql_databases_log_files_size_bytes` | Cumulative size (in kilobytes) of all the transaction log files in the database | gauge | `mssql_instance`, `database` | +| `windows_mssql_databases_log_files_used_size_bytes` | The cumulative used size of all the log files in the database | gauge | `mssql_instance`, `database` | +| `windows_mssql_databases_log_flushes` | Total wait time (in milliseconds) to flush the log. On an Always On secondary database, this value indicates the wait time for log records to be hardened to disk | counter | `mssql_instance`, `database` | +| `windows_mssql_databases_log_flush_waits` | Number of commits per second waiting for the log flush | counter | `mssql_instance`, `database` | +| `windows_mssql_databases_log_flush_wait_seconds` | Number of commits per second waiting for the log flush | gauge | `mssql_instance`, `database` | +| `windows_mssql_databases_log_flush_write_seconds` | Time in milliseconds for performing writes of log flushes that were completed in the last second | gauge | `mssql_instance`, `database` | +| `windows_mssql_databases_log_growths` | Total number of times the transaction log for the database has been expanded | gauge | `mssql_instance`, `database` | +| `windows_mssql_databases_log_pool_cache_misses` | Number of requests for which the log block was not available in the log pool | counter | `mssql_instance`, `database` | +| `windows_mssql_databases_log_pool_disk_reads` | Number of disk reads that the log pool issued to fetch log blocks | counter | `mssql_instance`, `database` | +| `windows_mssql_databases_log_pool_hash_deletes` | Rate of raw hash entry deletes from the Log Pool | counter | `mssql_instance`, `database` | +| `windows_mssql_databases_log_pool_hash_inserts` | Rate of raw hash entry inserts into the Log Pool | counter | `mssql_instance`, `database` | +| `windows_mssql_databases_log_pool_invalid_hash_entries` | Rate of hash lookups failing due to being invalid | counter | `mssql_instance`, `database` | +| `windows_mssql_databases_log_pool_log_scan_pushes` | Rate of Log block pushes by log scans, which may come from disk or memory | counter | `mssql_instance`, `database` | +| `windows_mssql_databases_log_pool_log_writer_pushes` | Rate of Log block pushes by log writer thread | counter | `mssql_instance`, `database` | +| `windows_mssql_databases_log_pool_empty_free_pool_pushes` | Rate of Log block push fails due to empty free pool | counter | `mssql_instance`, `database` | +| `windows_mssql_databases_log_pool_low_memory_pushes` | Rate of Log block push fails due to being low on memory | counter | `mssql_instance`, `database` | +| `windows_mssql_databases_log_pool_no_free_buffer_pushes` | Rate of Log block push fails due to free buffer unavailable | counter | `mssql_instance`, `database` | +| `windows_mssql_databases_log_pool_req_behind_trunc` | Log pool cache misses due to block requested being behind truncation LSN | counter | `mssql_instance`, `database` | +| `windows_mssql_databases_log_pool_requests_old_vlf` | Log Pool requests that were not in the last VLF of the log | counter | `mssql_instance`, `database` | +| `windows_mssql_databases_log_pool_requests` | The number of log-block requests processed by the log pool | counter | `mssql_instance`, `database` | +| `windows_mssql_databases_log_pool_total_active_log_bytes` | Current total active log stored in the shared cache buffer manager in bytes | gauge | `mssql_instance`, `database` | +| `windows_mssql_databases_log_pool_total_shared_pool_bytes` | Current total memory usage of the shared cache buffer manager in bytes | gauge | `mssql_instance`, `database` | +| `windows_mssql_databases_log_shrinks` | Total number of log shrinks for this database | gauge | `mssql_instance`, `database` | +| `windows_mssql_databases_log_truncations` | The number of times the transaction log has been truncated (in Simple Recovery Model) | gauge | `mssql_instance`, `database` | +| `windows_mssql_databases_log_used_percent` | Percentage of space in the log that is in use | gauge | `mssql_instance`, `database` | +| `windows_mssql_databases_pending_repl_transactions` | Number of transactions in the transaction log of the publication database marked for replication, but not yet delivered to the distribution database | gauge | `mssql_instance`, `database` | +| `windows_mssql_databases_repl_transactions` | Number of transactions per second read out of the transaction log of the publication database and delivered to the distribution database | counter | `mssql_instance`, `database` | +| `windows_mssql_databases_shrink_data_movement_bytes` | Amount of data being moved per second by autoshrink operations, or DBCC SHRINKDATABASE or DBCC SHRINKFILE statements | counter | `mssql_instance`, `database` | +| `windows_mssql_databases_tracked_transactions` | Number of committed transactions recorded in the commit table for the database | counter | `mssql_instance`, `database` | +| `windows_mssql_databases_transactions` | Number of transactions started for the database per second | counter | `mssql_instance`, `database` | +| `windows_mssql_databases_write_transactions` | Number of transactions that wrote to the database and committed, in the last second | counter | `mssql_instance`, `database` | +| `windows_mssql_databases_xtp_controller_dlc_fetch_latency_seconds` | Average latency in microseconds between log blocks entering the Direct Log Consumer and being retrieved by the XTP controller, per second | gauge | `mssql_instance`, `database` | +| `windows_mssql_databases_xtp_controller_dlc_peak_latency_seconds` | The largest recorded latency, in microseconds, of a fetch from the Direct Log Consumer by the XTP controller | gauge | `mssql_instance`, `database` | +| `windows_mssql_databases_xtp_controller_log_processed_bytes` | The amount of log bytes processed by the XTP controller thread, per second | counter | `mssql_instance`, `database` | +| `windows_mssql_databases_xtp_memory_used_bytes` | The amount of memory used by XTP in the database | gauge | `mssql_instance`, `database` | +| `windows_mssql_genstats_active_temp_tables` | Number of temporary tables/table variables in use | gauge | `mssql_instance` | +| `windows_mssql_genstats_connection_resets` | Total number of logins started from the connection pool | counter | `mssql_instance` | +| `windows_mssql_genstats_event_notifications_delayed_drop` | Number of event notifications waiting to be dropped by a system thread | gauge | `mssql_instance` | +| `windows_mssql_genstats_http_authenticated_requests` | Number of authenticated HTTP requests started per second | gauge | `mssql_instance` | +| `windows_mssql_genstats_logical_connections` | Number of logical connections to the system | gauge | `mssql_instance` | +| `windows_mssql_genstats_logins` | Total number of logins started per second. This does not include pooled connections | counter | `mssql_instance` | +| `windows_mssql_genstats_logouts` | Total number of logout operations started per second | counter | `mssql_instance` | +| `windows_mssql_genstats_mars_deadlocks` | Number of MARS deadlocks detected | gauge | `mssql_instance` | +| `windows_mssql_genstats_non_atomic_yields` | Number of non-atomic yields per second | counter | `mssql_instance` | +| `windows_mssql_genstats_blocked_processes` | Number of currently blocked processes | gauge | `mssql_instance` | +| `windows_mssql_genstats_soap_empty_requests` | Number of empty SOAP requests started per second | gauge | `mssql_instance` | +| `windows_mssql_genstats_soap_method_invocations` | Number of SOAP method invocations started per second | gauge | `mssql_instance` | +| `windows_mssql_genstats_soap_session_initiate_requests` | Number of SOAP Session initiate requests started per second | gauge | `mssql_instance` | +| `windows_mssql_genstats_soap_session_terminate_requests` | Number of SOAP Session terminate requests started per second | gauge | `mssql_instance` | +| `windows_mssql_genstats_soapsql_requests` | Number of SOAP SQL requests started per second | gauge | `mssql_instance` | +| `windows_mssql_genstats_soapwsdl_requests` | Number of SOAP Web Service Description Language requests started per second | gauge | `mssql_instance` | +| `windows_mssql_genstats_sql_trace_io_provider_lock_waits` | Number of waits for the File IO Provider lock per second | gauge | `mssql_instance` | +| `windows_mssql_genstats_tempdb_recovery_unit_ids_generated` | Number of duplicate tempdb recovery unit id generated | gauge | `mssql_instance` | +| `windows_mssql_genstats_tempdb_rowset_ids_generated` | Number of duplicate tempdb rowset id generated | gauge | `mssql_instance` | +| `windows_mssql_genstats_temp_tables_creations` | Number of temporary tables/table variables created per second | counter | `mssql_instance` | +| `windows_mssql_genstats_temp_tables_awaiting_destruction` | Number of temporary tables/table variables waiting to be destroyed by the cleanup system thread | gauge | `mssql_instance` | +| `windows_mssql_genstats_trace_event_notification_queue_size` | Number of trace event notification instances waiting in the internal queue to be sent through Service Broker | gauge | `mssql_instance` | +| `windows_mssql_genstats_transactions` | Number of transaction enlistments (local, DTC, bound all combined) | gauge | `mssql_instance` | +| `windows_mssql_genstats_user_connections` | Counts the number of users currently connected to SQL Server | gauge | `mssql_instance` | +| `windows_mssql_locks_average_wait_seconds` | Average amount of wait time (in milliseconds) for each lock request that resulted in a wait | gauge | `mssql_instance`, `resource` | +| `windows_mssql_locks_lock_requests` | Number of new locks and lock conversions per second requested from the lock manager | counter | `mssql_instance`, `resource` | +| `windows_mssql_locks_lock_timeouts` | Number of lock requests per second that timed out, including requests for NOWAIT locks | counter | `mssql_instance`, `resource` | +| `windows_mssql_locks_lock_timeouts_excluding_NOWAIT` | Number of lock requests per second that timed out, but excluding requests for NOWAIT locks | counter | `mssql_instance`, `resource` | +| `windows_mssql_locks_lock_waits` | Total wait time (in milliseconds) for locks in the last second | counter | `mssql_instance`, `resource` | +| `windows_mssql_locks_lock_wait_seconds` | Number of lock requests per second that required the caller to wait | gauge | `mssql_instance`, `resource` | +| `windows_mssql_locks_deadlocks` | Number of lock requests per second that resulted in a deadlock | counter | `mssql_instance`, `resource` | +| `windows_mssql_memmgr_connection_memory_bytes` | Specifies the total amount of dynamic memory the server is using for maintaining connections | gauge | `mssql_instance` | +| `windows_mssql_memmgr_database_cache_memory_bytes` | Specifies the amount of memory the server is currently using for the database pages cache | gauge | `mssql_instance` | +| `windows_mssql_memmgr_external_benefit_of_memory` | An internal estimation of the performance benefit from adding memory to a specific cache | gauge | `mssql_instance` | +| `windows_mssql_memmgr_free_memory_bytes` | Specifies the amount of committed memory currently not used by the server | gauge | `mssql_instance` | +| `windows_mssql_memmgr_granted_workspace_memory_bytes` | Specifies the total amount of memory currently granted to executing processes, such as hash, sort, bulk copy, and index creation operations | gauge | `mssql_instance` | +| `windows_mssql_memmgr_lock_blocks` | Specifies the current number of lock blocks in use on the server (refreshed periodically). A lock block represents an individual locked resource, such as a table, page, or row | gauge | `mssql_instance` | +| `windows_mssql_memmgr_allocated_lock_blocks` | Specifies the current number of allocated lock blocks. At server startup, the number of allocated lock blocks plus the number of allocated lock owner blocks depends on the SQL Server Locks configuration option. If more lock blocks are needed, the value increases | gauge | `mssql_instance` | +| `windows_mssql_memmgr_lock_memory_bytes` | Specifies the total amount of dynamic memory the server is using for locks | gauge | `mssql_instance` | +| `windows_mssql_memmgr_lock_owner_blocks` | Specifies the current number of allocated lock owner blocks. At server startup, the number of allocated lock owner blocks and the number of allocated lock blocks depend on the SQL Server Locks configuration option. If more lock owner blocks are needed, the value increases dynamically | gauge | `mssql_instance` | +| `windows_mssql_memmgr_allocated_lock_owner_blocks` | _Not yet documented_ | gauge | `mssql_instance` | +| `windows_mssql_memmgr_log_pool_memory_bytes` | Total amount of dynamic memory the server is using for Log Pool | gauge | `mssql_instance` | +| `windows_mssql_memmgr_maximum_workspace_memory_bytes` | Indicates the maximum amount of memory available for executing processes, such as hash, sort, bulk copy, and index creation operations | gauge | `mssql_instance` | +| `windows_mssql_memmgr_outstanding_memory_grants` | Specifies the total number of processes that have successfully acquired a workspace memory grant | gauge | `mssql_instance` | +| `windows_mssql_memmgr_pending_memory_grants` | Specifies the total number of processes waiting for a workspace memory grant | gauge | `mssql_instance` | +| `windows_mssql_memmgr_optimizer_memory_bytes` | Specifies the total amount of dynamic memory the server is using for query optimization | gauge | `mssql_instance` | +| `windows_mssql_memmgr_reserved_server_memory_bytes` | ndicates the amount of memory the server has reserved for future usage. This counter shows the current unused amount of memory initially granted that is shown in Granted Workspace Memory | gauge | `mssql_instance` | +| `windows_mssql_memmgr_sql_cache_memory_bytes` | Specifies the total amount of dynamic memory the server is using for the dynamic SQL cache | gauge | `mssql_instance` | +| `windows_mssql_memmgr_stolen_server_memory_bytes` | Specifies the amount of memory the server is using for purposes other than database pages | gauge | `mssql_instance` | +| `windows_mssql_memmgr_target_server_memory_bytes` | Indicates the ideal amount of memory the server can consume | gauge | `mssql_instance` | +| `windows_mssql_memmgr_total_server_memory_bytes` | Specifies the amount of memory the server has committed using the memory manager | gauge | `mssql_instance` | +| `windows_mssql_sqlstats_auto_parameterization_attempts` | Number of failed auto-parameterization attempts per second. This should be small. Note that auto-parameterizations are also known as simple parameterizations in later versions of SQL Server | counter | `mssql_instance` | +| `windows_mssql_sqlstats_batch_requests` | _Not yet documented_ | counter | `mssql_instance` | +| `windows_mssql_sqlstats_failed_auto_parameterization_attempts` | _Not yet documented_ | counter | `mssql_instance` | +| `windows_mssql_sqlstats_forced_parameterizations` | Number of successful forced parameterizations per second | counter | `mssql_instance` | +| `windows_mssql_sqlstats_guided_plan_executions` | Number of plan executions per second in which the query plan has been generated by using a plan guide | counter | `mssql_instance` | +| `windows_mssql_sqlstats_misguided_plan_executions` | Number of plan executions per second in which a plan guide could not be honored during plan generation | counter | `mssql_instance` | +| `windows_mssql_sqlstats_safe_auto_parameterization_attempts` | Number of safe auto-parameterization attempts per second | counter | `mssql_instance` | +| `windows_mssql_sqlstats_sql_attentions` | Number of attentions per second | counter | `mssql_instance` | +| `windows_mssql_sqlstats_sql_compilations` | Number of SQL compilations per second | counter | `mssql_instance` | +| `windows_mssql_sqlstats_sql_recompilations` | Number of statement recompiles per second | counter | `mssql_instance` | +| `windows_mssql_sqlstats_unsafe_auto_parameterization_attempts` | Number of unsafe auto-parameterization attempts per second. | counter | `mssql_instance` | +| `windows_mssql_sql_errors_total` | Information for all errors | counter | `mssql_instance`, `resource` | +| `windows_mssql_transactions_tempdb_free_space_bytes` | The amount of space (in kilobytes) available in tempdb | gauge | `mssql_instance` | +| `windows_mssql_transactions_longest_transaction_running_seconds` | The length of time (in seconds) since the start of the transaction that has been active longer than any other current transaction | gauge | `mssql_instance` | +| `windows_mssql_transactions_nonsnapshot_version_active_total` | The number of currently active transactions that are not using snapshot isolation level and have made data modifications that have generated row versions in the tempdb version store | counter | `mssql_instance` | +| `windows_mssql_transactions_snapshot_active_total` | The number of currently active transactions using the snapshot isolation level | counter | `mssql_instance` | +| `windows_mssql_transactions_active` | The number of currently active transactions of all types | gauge | `mssql_instance` | +| `windows_mssql_transactions_update_conflicts_total` | The percentage of those transactions using the snapshot isolation level that have encountered update conflicts within the last second | counter | `mssql_instance` | +| `windows_mssql_transactions_update_snapshot_active_total` | The number of currently active transactions using the snapshot isolation level and have modified data | counter | `mssql_instance` | +| `windows_mssql_transactions_version_cleanup_rate_bytes` | The rate (in kilobytes per second) at which row versions are removed from the snapshot isolation version store in tempdb | gauge | `mssql_instance` | +| `windows_mssql_transactions_version_generation_rate_bytes` | The rate (in kilobytes per second) at which new row versions are added to the snapshot isolation version store in tempdb | gauge | `mssql_instance` | +| `windows_mssql_transactions_version_store_size_bytes` | he amount of space (in kilobytes) in tempdb being used to store snapshot isolation level row versions | gauge | `mssql_instance` | +| `windows_mssql_transactions_version_store_units` | The number of active allocation units in the snapshot isolation version store in tempdb | counter | `mssql_instance` | +| `windows_mssql_transactions_version_store_creation_units` | The number of allocation units that have been created in the snapshot isolation store since the instance of the Database Engine was started | counter | `mssql_instance` | +| `windows_mssql_transactions_version_store_truncation_units` | The number of allocation units that have been removed from the snapshot isolation store since the instance of the Database Engine was started | counter | `mssql_instance` | +| `windows_mssql_waitstats_lock_waits` | Statistics for processes waiting on a lock | gauge | `mssql_instance`, `item` | +| `windows_mssql_waitstats_memory_grant_queue_waits` | Statistics for processes waiting for memory grant to become available | gauge | `mssql_instance`, `item` | +| `windows_mssql_waitstats_thread_safe_memory_objects_waits` | Statistics for processes waiting on thread-safe memory allocators | gauge | `mssql_instance`, `item` | +| `windows_mssql_waitstats_log_write_waits` | Statistics for processes waiting for log buffer to be written | gauge | `mssql_instance`, `item` | +| `windows_mssql_waitstats_log_buffer_waits` | Statistics for processes waiting for log buffer to be available | gauge | `mssql_instance`, `item` | +| `windows_mssql_waitstats_network_io_waits` | Statistics relevant to wait on network I/O | gauge | `mssql_instance`, `item` | +| `windows_mssql_waitstats_page_io_latch_waits` | Statistics relevant to page I/O latches | gauge | `mssql_instance`, `item` | +| `windows_mssql_waitstats_page_latch_waits` | Statistics relevant to page latches, not including I/O latches | gauge | `mssql_instance`, `item` | +| `windows_mssql_waitstats_nonpage_latch_waits` | Statistics relevant to non-page latches | gauge | `mssql_instance`, `item` | +| `windows_mssql_waitstats_wait_for_the_worker_waits` | Statistics relevant to processes waiting for worker to become available | gauge | `mssql_instance`, `item` | +| `windows_mssql_waitstats_workspace_synchronization_waits` | Statistics relevant to processes synchronizing access to workspace | gauge | `mssql_instance`, `item` | +| `windows_mssql_waitstats_transaction_ownership_waits` | Statistics relevant to processes synchronizing access to transaction | gauge | `mssql_instance`, `item` | ### Example metric @@ -311,4 +316,4 @@ groups: summary: "SQl EXpress Database size exceeded 10GB" description: "The database size has grown larger than 10GB. Instance: {{ $labels.instance }}" -``` \ No newline at end of file +``` diff --git a/internal/collector/mssql/mssql.go b/internal/collector/mssql/mssql.go index af707d254..f8d44f738 100644 --- a/internal/collector/mssql/mssql.go +++ b/internal/collector/mssql/mssql.go @@ -7,15 +7,20 @@ import ( "fmt" "log/slog" "sort" + "strconv" "strings" "sync" "time" + "unsafe" + "github.com/Microsoft/go-winio/pkg/process" "github.com/alecthomas/kingpin/v2" + "github.com/prometheus-community/windows_exporter/internal/headers/iphlpapi" "github.com/prometheus-community/windows_exporter/internal/mi" "github.com/prometheus-community/windows_exporter/internal/perfdata" "github.com/prometheus-community/windows_exporter/internal/types" "github.com/prometheus/client_golang/prometheus" + "golang.org/x/sys/windows" "golang.org/x/sys/windows/registry" ) @@ -38,6 +43,7 @@ const ( type Config struct { CollectorsEnabled []string `yaml:"collectors_enabled"` + Port uint16 `yaml:"port"` } var ConfigDefaults = Config{ @@ -55,6 +61,7 @@ var ConfigDefaults = Config{ subCollectorTransactions, subCollectorWaitStats, }, + Port: 1433, } // A Collector is a Prometheus Collector for various WMI Win32_PerfRawData_MSSQLSERVER_* metrics. @@ -67,9 +74,13 @@ type Collector struct { collectorFns []func(ch chan<- prometheus.Metric) error closeFns []func() + fileVersion string + productVersion string + // meta mssqlScrapeDurationDesc *prometheus.Desc mssqlScrapeSuccessDesc *prometheus.Desc + mssqlInfoDesc *prometheus.Desc collectorAccessMethods collectorAvailabilityReplica @@ -96,6 +107,10 @@ func New(config *Config) *Collector { config.CollectorsEnabled = ConfigDefaults.CollectorsEnabled } + if config.Port == 0 { + config.Port = ConfigDefaults.Port + } + c := &Collector{ config: *config, } @@ -115,6 +130,11 @@ func NewWithFlags(app *kingpin.Application) *Collector { "Comma-separated list of collectors to use.", ).Default(strings.Join(c.config.CollectorsEnabled, ",")).StringVar(&collectorsEnabled) + app.Flag( + "collector.mssql.port", + "Port of MSSQL server used for windows_mssql_info metric.", + ).Default(strconv.FormatUint(uint64(c.config.Port), 10)).Uint16Var(&c.config.Port) + app.Action(func(*kingpin.ParseContext) error { c.config.CollectorsEnabled = strings.Split(collectorsEnabled, ",") @@ -140,6 +160,17 @@ func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error { c.logger = logger.With(slog.String("collector", Name)) c.mssqlInstances = c.getMSSQLInstances() + fileVersion, productVersion, err := c.getMSSQLServerVersion(c.config.Port) + if err != nil { + logger.Warn("Failed to get MSSQL server version", + slog.Any("err", err), + slog.String("collector", Name), + ) + } + + c.fileVersion = fileVersion + c.productVersion = productVersion + subCollectors := map[string]struct { build func() error collect func(ch chan<- prometheus.Metric) error @@ -209,7 +240,6 @@ func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error { c.collectorFns = make([]func(ch chan<- prometheus.Metric) error, 0, len(c.config.CollectorsEnabled)) c.closeFns = make([]func(), 0, len(c.config.CollectorsEnabled)) - // Result must order, to prevent test failures. sort.Strings(c.config.CollectorsEnabled) @@ -227,6 +257,13 @@ func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error { } // meta + c.mssqlInfoDesc = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "info"), + "mssql server information", + []string{"file_version", "version"}, + nil, + ) + c.mssqlScrapeDurationDesc = prometheus.NewDesc( prometheus.BuildFQName(types.Namespace, Name, "collector_duration_seconds"), "windows_exporter: Duration of an mssql child collection.", @@ -379,3 +416,68 @@ func (c *Collector) collect( return errors.Join(errs...) } + +// getMSSQLServerVersion get the version of the SQL Server instance by +// reading the version information from the process running the SQL Server instance port. +func (c *Collector) getMSSQLServerVersion(port uint16) (string, string, error) { + pid, err := iphlpapi.GetOwnerPIDOfTCPPort(windows.AF_INET, port) + if err != nil { + return "", "", fmt.Errorf("failed to get the PID of the process running on port 1433: %w", err) + } + + hProcess, err := windows.OpenProcess(windows.PROCESS_QUERY_LIMITED_INFORMATION, false, pid) + if err != nil { + return "", "", fmt.Errorf("failed to open the process with PID %d: %w", pid, err) + } + + defer windows.CloseHandle(hProcess) + + processFilePath, err := process.QueryFullProcessImageName(hProcess, process.ImageNameFormatWin32Path) + if err != nil { + return "", "", fmt.Errorf("failed to query the full path of the process with PID %d: %w", pid, err) + } + + // Load the file version information + size, err := windows.GetFileVersionInfoSize(processFilePath, nil) + if err != nil { + return "", "", fmt.Errorf("failed to get the size of the file version information: %w", err) + } + + fileVersionInfo := make([]byte, size) + + err = windows.GetFileVersionInfo(processFilePath, 0, size, unsafe.Pointer(&fileVersionInfo[0])) + if err != nil { + return "", "", fmt.Errorf("failed to get the file version information: %w", err) + } + + var ( + verData *byte + verSize uint32 + ) + + err = windows.VerQueryValue( + unsafe.Pointer(&fileVersionInfo[0]), + `\StringFileInfo\040904b0\ProductVersion`, + unsafe.Pointer(&verData), + &verSize, + ) + if err != nil { + return "", "", fmt.Errorf("failed to query the product version: %w", err) + } + + productVersion := windows.UTF16ToString((*[1 << 16]uint16)(unsafe.Pointer(verData))[:verSize]) + + err = windows.VerQueryValue( + unsafe.Pointer(&fileVersionInfo[0]), + `\StringFileInfo\040904b0\FileVersion`, + unsafe.Pointer(&verData), + &verSize, + ) + if err != nil { + return "", "", fmt.Errorf("failed to query the file version: %w", err) + } + + fileVersion := windows.UTF16ToString((*[1 << 16]uint16)(unsafe.Pointer(verData))[:verSize]) + + return fileVersion, productVersion, nil +} diff --git a/test/main.go b/test/main.go index 3b2026003..10e27d326 100644 --- a/test/main.go +++ b/test/main.go @@ -11,7 +11,7 @@ import ( ) func main() { - pid, err := iphlpapi.GetOwnerPIDOfTCPPort(windows.AF_INET, 135) + pid, err := iphlpapi.GetOwnerPIDOfTCPPort(windows.AF_INET, 1433) if err != nil { panic(err) } @@ -42,7 +42,7 @@ func main() { var verSize uint32 var verData *byte - err = windows.VerQueryValue(unsafe.Pointer(&data[0]), `\StringFileInfo\040904E4\ProductVersion`, unsafe.Pointer(&verData), &verSize) + err = windows.VerQueryValue(unsafe.Pointer(&data[0]), `\StringFileInfo\040904b0\ProductVersion`, unsafe.Pointer(&verData), &verSize) if err != nil { panic(err) } From 78f4266ba46a4419249308bf98f1d8dfe9f9e860 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan-Otto=20Kr=C3=B6pke?= Date: Sat, 16 Nov 2024 21:53:18 +0100 Subject: [PATCH 6/6] mssql: expose server version info MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jan-Otto Kröpke --- docs/collector.mssql.md | 2 +- go.mod | 2 +- internal/collector/mssql/mssql.go | 2 +- internal/headers/iphlpapi/iphlpapi_test.go | 2 + internal/headers/iphlpapi/types.go | 5 +++ test/main.go | 52 ---------------------- 6 files changed, 10 insertions(+), 55 deletions(-) delete mode 100644 test/main.go diff --git a/docs/collector.mssql.md b/docs/collector.mssql.md index d77d61e42..61fc47b32 100644 --- a/docs/collector.mssql.md +++ b/docs/collector.mssql.md @@ -26,7 +26,7 @@ Port of MSSQL server used for `windows_mssql_info` metric. Default is `1433`. | Name | Description | Type | Labels | |--------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------|-------------------------------| -| `windows_mssql_info` | Returns infomation about the MSSQL server running on port 1433 | gauge | `version` | +| `windows_mssql_info` | Returns information about the MSSQL server running on port 1433 | gauge | `version` | | `windows_mssql_collector_duration_seconds` | The time taken for each sub-collector to return | gauge | `collector`, `mssql_instance` | | `windows_mssql_collector_success` | 1 if sub-collector succeeded, 0 otherwise | gauge | `collector`, `mssql_instance` | | `windows_mssql_accessmethods_au_batch_cleanups` | The total number of batches that were completed successfully by the background task that cleans up deferred dropped allocation units | counter | `mssql_instance` | diff --git a/go.mod b/go.mod index 46f82c16e..f6c7c7398 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,7 @@ module github.com/prometheus-community/windows_exporter go 1.23 require ( + github.com/Microsoft/go-winio v0.6.2 github.com/Microsoft/hcsshim v0.12.9 github.com/alecthomas/kingpin/v2 v2.4.0 github.com/bmatcuk/doublestar/v4 v4.7.1 @@ -19,7 +20,6 @@ require ( ) require ( - github.com/Microsoft/go-winio v0.6.2 // indirect github.com/alecthomas/units v0.0.0-20240927000941-0f3dac36c52b // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect diff --git a/internal/collector/mssql/mssql.go b/internal/collector/mssql/mssql.go index f8d44f738..51b2bf359 100644 --- a/internal/collector/mssql/mssql.go +++ b/internal/collector/mssql/mssql.go @@ -430,7 +430,7 @@ func (c *Collector) getMSSQLServerVersion(port uint16) (string, string, error) { return "", "", fmt.Errorf("failed to open the process with PID %d: %w", pid, err) } - defer windows.CloseHandle(hProcess) + defer windows.CloseHandle(hProcess) //nolint:errcheck processFilePath, err := process.QueryFullProcessImageName(hProcess, process.ImageNameFormatWin32Path) if err != nil { diff --git a/internal/headers/iphlpapi/iphlpapi_test.go b/internal/headers/iphlpapi/iphlpapi_test.go index 6ad1c48fb..5867a0d36 100644 --- a/internal/headers/iphlpapi/iphlpapi_test.go +++ b/internal/headers/iphlpapi/iphlpapi_test.go @@ -22,6 +22,8 @@ func TestGetOwnerPIDOfTCPPort(t *testing.T) { t.Parallel() lister, err := net.Listen("tcp", "127.0.0.1:0") + require.NoError(t, err) + t.Cleanup(func() { require.NoError(t, lister.Close()) }) diff --git a/internal/headers/iphlpapi/types.go b/internal/headers/iphlpapi/types.go index 448e00335..d3931cb90 100644 --- a/internal/headers/iphlpapi/types.go +++ b/internal/headers/iphlpapi/types.go @@ -9,6 +9,8 @@ import ( // MIB_TCPROW_OWNER_PID structure for IPv4. // https://learn.microsoft.com/en-us/windows/win32/api/tcpmib/ns-tcpmib-mib_tcprow_owner_pid +// +//nolint:unused type MIB_TCPROW_OWNER_PID struct { dwState MIB_TCP_STATE dwLocalAddr BigEndianUint32 @@ -20,6 +22,8 @@ type MIB_TCPROW_OWNER_PID struct { // MIB_TCP6ROW_OWNER_PID structure for IPv6. // https://learn.microsoft.com/en-us/windows/win32/api/tcpmib/ns-tcpmib-mib_tcp6row_owner_pid +// +//nolint:unused type MIB_TCP6ROW_OWNER_PID struct { ucLocalAddr [16]byte dwLocalScopeId uint32 @@ -85,5 +89,6 @@ type BigEndianUint32 uint32 func (b BigEndianUint32) uint16() uint16 { data := make([]byte, 2) binary.BigEndian.PutUint16(data, uint16(b)) + return binary.LittleEndian.Uint16(data) } diff --git a/test/main.go b/test/main.go deleted file mode 100644 index 10e27d326..000000000 --- a/test/main.go +++ /dev/null @@ -1,52 +0,0 @@ -package main - -import ( - "fmt" - "syscall" - "unsafe" - - "github.com/Microsoft/go-winio/pkg/process" - "github.com/prometheus-community/windows_exporter/internal/headers/iphlpapi" - "golang.org/x/sys/windows" -) - -func main() { - pid, err := iphlpapi.GetOwnerPIDOfTCPPort(windows.AF_INET, 1433) - if err != nil { - panic(err) - } - - hProcess, err := windows.OpenProcess(windows.PROCESS_QUERY_LIMITED_INFORMATION, false, pid) - if err != nil { - panic(err) - } - - cmdLine, err := process.QueryFullProcessImageName(hProcess, process.ImageNameFormatWin32Path) - if err != nil { - panic(err) - } - fmt.Println(cmdLine) - - // Load the file version information - size, err := windows.GetFileVersionInfoSize(cmdLine, nil) - if err != nil { - panic(err) - } - - data := make([]byte, size) - err = windows.GetFileVersionInfo(cmdLine, 0, uint32(len(data)), unsafe.Pointer(&data[0])) - if err != nil { - panic(err) - } - - var verSize uint32 - var verData *byte - - err = windows.VerQueryValue(unsafe.Pointer(&data[0]), `\StringFileInfo\040904b0\ProductVersion`, unsafe.Pointer(&verData), &verSize) - if err != nil { - panic(err) - } - - version := syscall.UTF16ToString((*[1 << 16]uint16)(unsafe.Pointer(verData))[:verSize]) - fmt.Println(version) -}