Add MSSQL Wait statistics (windows.plugin) (#20307)
Co-authored-by: ilyam8 <ilya@netdata.cloud>
thiagoftsm committed
Jun 11, 2025 at 09:59 UTC
5f744dd79e8468d2602893a7453f4bd538fbd1fd
5 files changed
+1151
-97
CMakeLists.txt
+1
@@ -2048,6 +2048,7 @@ set(WINDOWS_PLUGIN_FILES
2048
src/collectors/windows.plugin/perflib-rrd.h
2049
src/collectors/windows.plugin/perflib-ad.c
2050
src/collectors/windows.plugin/perflib-mssql.c
2051
+ src/collectors/windows.plugin/perflib-mssql-queries.h
2052
src/collectors/windows.plugin/perflib-storage.c
2053
src/collectors/windows.plugin/perflib-processor.c
2054
src/collectors/windows.plugin/perflib-thermalzone.c
src/collectors/windows.plugin/metadata.yaml
+63
-41
@@ -1705,7 +1705,8 @@ modules:
1705
default_behavior:
1706
auto_detection:
1707
description: |
1708
- The collector automatically discovers and monitors standard SQL Server metrics without additional setup. However, for transaction-level metrics, you must:
1708
+ The collector automatically discovers and monitors standard SQL Server metrics without additional setup. However, for transaction-level metrics,
1709
+ the size of all the data files, and the wait stats in the database you must:
1710
1711
- Complete the "Configure SQL Server for Monitoring" steps in the Setup -> Prerequisites section.
1712
- Configure a database connection (see Setup → Configuration → Examples).
@@ -1721,7 +1722,7 @@ modules:
1722
For **each SQL Server** instance you want to monitor, complete the following steps:
1723
1724
1. **Create Monitoring User**
1724
-
1725
+
1726
Create an SQL Server user with the necessary permissions to collect monitoring data:
1727
1728
```tsql
@@ -1732,9 +1733,9 @@ modules:
1733
GRANT VIEW SERVER STATE TO netdata_user;
1734
GO
1735
```
1735
-
1736
+
1737
2. **Enable Query Store**
1737
-
1738
+
1739
Enable the [Query Store](https://learn.microsoft.com/en-us/sql/relational-databases/performance/monitoring-performance-by-using-the-query-store?view=sql-server-ver16) and grant access to the monitoring user on all relevant databases:
1740
1741
```tsql
@@ -1962,50 +1963,72 @@ modules:
1963
chart_type: line
1964
dimensions:
1965
- name: benefit
1966
+ - name: mssql.instance_blocked_processes
1967
+ description: Blocked processes
1968
+ unit: processes
1969
+ chart_type: line
1970
+ dimensions:
1971
+ - name: blocked
1972
+ - name: MSSQL Resource Locks
1973
+ description: "Monitors SQL Server resource locks by type. SQL Server uses locks to manage concurrent access to database resources during transactions, preventing conflicts when multiple users access the same data simultaneously. This metric tracks locks on different [resource types](https://learn.microsoft.com/en-us/sql/relational-databases/performance-monitor/sql-server-locks-object?view=sql-server-ver17) like rows, pages, tables, and databases."
1974
+ labels:
1975
+ - name: mssql_instance
1976
+ description: The SQL Server instance name (e.g., 'MSSQLSERVER' for default instance or named instance like 'INSTANCE01').
1977
+ - name: resource
1978
+ description: "The specific resource type being locked (e.g., 'Database', 'Table', 'Page', 'Row', 'Key', 'Extent', 'RID', 'Application', 'Metadata', 'Allocation_Unit')."
1979
+ metrics:
1980
- name: mssql.instance_resource_deadlocks
1981
description: Active lock requests that resulted in deadlock per resource
1967
- unit: deadlocks/s
1982
+ unit: deadlock/s
1983
chart_type: line
1984
dimensions:
1970
- - name: alloc_unit
1971
- - name: application
1972
- - name: database
1973
- - name: extent
1974
- - name: file
1975
- - name: hobt
1976
- - name: key
1977
- - name: metadata
1978
- - name: oib
1979
- - name: object
1980
- - name: page
1981
- - name: rid
1982
- - name: row_group
1983
- - name: xact
1984
- - name: mssql.instance_resource_lock_wait
1985
- description: Active lock requests that required the caller to wait
1986
- unit: locks/s
1985
+ - name: locks
1986
+ - name: mssql.instance_resource_lock_waits
1987
+ description: Lock requests that required the caller to wait per resource
1988
+ unit: lock/s
1989
chart_type: line
1990
dimensions:
1989
- - name: alloc_unit
1990
- - name: application
1991
- - name: database
1992
- - name: extent
1993
- - name: file
1994
- - name: hobt
1995
- - name: key
1996
- - name: metadata
1997
- - name: oib
1998
- - name: object
1999
- - name: page
2000
- - name: rid
2001
- - name: row_group
2002
- - name: xact
2003
- - name: mssql.instance_blocked_processes
2004
- description: Blocked processes
2005
- unit: processes
1991
+ - name: locks
1992
+ - name: MSSQL Waits
1993
+ description: "These metrics refer to the Microsoft SQL Server instances defined on the host and their associated wait events."
1994
+ labels:
1995
+ - name: mssql_instance
1996
+ description: The instance name.
1997
+ - name: wait_type
1998
+ description: A wait defined in https://learn.microsoft.com/en-us/sql/relational-databases/system-dynamic-management-views/sys-dm-os-wait-stats-transact-sql?view=sql-server-ver16#WaitTypes.
1999
+ - name: wait_category
2000
+ description: "Wait categories are groupings of specific wait types that indicate the reason a SQL Server worker is waiting."
2001
+ metrics:
2002
+ - name: mssql.instance_total_wait_time
2003
+ description: Wait time for each wait type and category
2004
+ unit: ms
2005
chart_type: line
2006
dimensions:
2008
- - name: blocked
2007
+ - name: duration
2008
+ - name: mssql.instance_resource_wait_time
2009
+ description: Wait time for threads waiting on specific resource types for each wait type and category
2010
+ unit: ms
2011
+ chart_type: line
2012
+ dimensions:
2013
+ - name: duration
2014
+ - name: mssql.instance_signal_wait_time
2015
+ description: Delay between thread wakeup signal and actual execution start for each wait type and category
2016
+ unit: ms
2017
+ chart_type: line
2018
+ dimensions:
2019
+ - name: duration
2020
+ - name: mssql.instance_max_wait_time
2021
+ description: Maximum wait time for each wait type and category
2022
+ unit: ms
2023
+ chart_type: line
2024
+ dimensions:
2025
+ - name: duration
2026
+ - name: mssql.instance_waits
2027
+ description: Number of waits for each wait type and category
2028
+ unit: waits/s
2029
+ chart_type: line
2030
+ dimensions:
2031
+ - name: waits
2032
- name: Database
2033
description: "These metrics refer to Microsoft SQL Server databases."
2034
labels:
@@ -3071,4 +3094,3 @@ modules:
3094
- name: pause_pending
3095
- name: paused
3096
- name: unknown
3074
-
src/collectors/windows.plugin/perflib-mssql-queries.h
new
+622
@@ -0,0 +1,622 @@
1
+// SPDX-License-Identifier: GPL-3.0-or-later
2
+
3
+#ifndef NETDATA_PERFLIB_MSSQL_QUERIES_H
4
+#define NETDATA_PERFLIB_MSSQL_QUERIES_H
5
+
6
+// https://learn.microsoft.com/en-us/sql/relational-databases/system-dynamic-management-views/sys-dm-tran-locks-transact-sql?view=sql-server-ver16
7
+#define NETDATA_QUERY_LOCKS_MASK \
8
+ "SELECT resource_type, count(*) FROM %s.sys.dm_tran_locks WHERE DB_NAME(resource_database_id) = '%s' group by resource_type;"
9
+
10
+#define NETDATA_QUERY_LIST_DB "SELECT name FROM sys.databases;"
11
+
12
+// https://learn.microsoft.com/en-us/sql/relational-databases/system-catalog-views/sys-database-files-transact-sql?view=sql-server-ver16
13
+#define NETDATA_QUERY_DATA_FILE_SIZE_MASK "SELECT size * 8/1024 FROM %s.sys.database_files WHERE type = 0;"
14
+
15
+// https://learn.microsoft.com/en-us/sql/relational-databases/system-compatibility-views/sys-sysprocesses-transact-sql?view=sql-server-ver16
16
+// SQL SERVER BEFORE 2008 DOES NOT HAVE DATA IN THIS TABLE
17
+// https://github.com/influxdata/telegraf/blob/081dfa26e80d8764fb7f9aac5230e81584b62b56/plugins/inputs/sqlserver/sqlqueriesV2.go#L1259
18
+#define NETDATA_QUERY_TRANSACTIONS_MASK \
19
+ "SELECT counter_name, cntr_value FROM %s.sys.dm_os_performance_counters WHERE instance_name = '%s' AND counter_name IN ('Active Transactions', 'Transactions/sec', 'Write Transactions/sec', 'Backup/Restore Throughput/sec', 'Log Bytes Flushed/sec', 'Log Flushes/sec', 'Number of Deadlocks/sec', 'Lock Waits/sec', 'Lock Timeouts/sec', 'Lock Requests/sec');"
20
+
21
+#define NETDATA_QUERY_CHECK_PERM \
22
+ "SELECT CASE WHEN IS_SRVROLEMEMBER('sysadmin') = 1 OR HAS_PERMS_BY_NAME(null, null, 'VIEW SERVER STATE') = 1 THEN 1 ELSE 0 END AS has_permission;"
23
+
24
+// https://learn.microsoft.com/en-us/sql/relational-databases/system-dynamic-management-views/sys-dm-os-wait-stats-transact-sql?view=sql-server-ver16
25
+#define NETDATA_QUERY_CHECK_WAITS \
26
+ "SELECT \
27
+ ws.[wait_type], ws.[wait_time_ms], ws.[wait_time_ms] - ws.[signal_wait_time_ms] AS[resource_wait_ms], \
28
+ ws.[signal_wait_time_ms], ws.[max_wait_time_ms], ws.[waiting_tasks_count], \
29
+ ISNULL(wc.[wait_category], 'OTHER') AS[wait_category] FROM sys.dm_os_wait_stats AS ws WITH(NOLOCK) \
30
+ LEFT OUTER JOIN( \
31
+ VALUES('ASYNC_IO_COMPLETION', 'Other Disk IO'), \
32
+ ('ASYNC_NETWORK_IO', 'Network IO'), \
33
+ ('BACKUPIO', 'Other Disk IO'), \
34
+ ('BROKER_CONNECTION_RECEIVE_TASK', 'Service Broker'), \
35
+ ('BROKER_DISPATCHER', 'Service Broker'), \
36
+ ('BROKER_ENDPOINT_STATE_MUTEX', 'Service Broker'), \
37
+ ('BROKER_EVENTHANDLER', 'Service Broker'), \
38
+ ('BROKER_FORWARDER', 'Service Broker'), \
39
+ ('BROKER_INIT', 'Service Broker'), \
40
+ ('BROKER_MASTERSTART', 'Service Broker'), \
41
+ ('BROKER_RECEIVE_WAITFOR', 'User Wait'), \
42
+ ('BROKER_REGISTERALLENDPOINTS', 'Service Broker'), \
43
+ ('BROKER_SERVICE', 'Service Broker'), \
44
+ ('BROKER_SHUTDOWN', 'Service Broker'), \
45
+ ('BROKER_START', 'Service Broker'), \
46
+ ('BROKER_TASK_SHUTDOWN', 'Service Broker'), \
47
+ ('BROKER_TASK_STOP', 'Service Broker'), \
48
+ ('BROKER_TASK_SUBMIT', 'Service Broker'), \
49
+ ('BROKER_TO_FLUSH', 'Service Broker'), \
50
+ ('BROKER_TRANSMISSION_OBJECT', 'Service Broker'), \
51
+ ('BROKER_TRANSMISSION_TABLE', 'Service Broker'), \
52
+ ('BROKER_TRANSMISSION_WORK', 'Service Broker'), \
53
+ ('BROKER_TRANSMITTER', 'Service Broker'), \
54
+ ('CHECKPOINT_QUEUE', 'Idle'), \
55
+ ('CHKPT', 'Tran Log IO'), \
56
+ ('CLR_AUTO_EVENT', 'SQL CLR'), \
57
+ ('CLR_CRST', 'SQL CLR'), \
58
+ ('CLR_JOIN', 'SQL CLR'), \
59
+ ('CLR_MANUAL_EVENT', 'SQL CLR'), \
60
+ ('CLR_MEMORY_SPY', 'SQL CLR'), \
61
+ ('CLR_MONITOR', 'SQL CLR'), \
62
+ ('CLR_RWLOCK_READER', 'SQL CLR'), \
63
+ ('CLR_RWLOCK_WRITER', 'SQL CLR'), \
64
+ ('CLR_SEMAPHORE', 'SQL CLR'), \
65
+ ('CLR_TASK_START', 'SQL CLR'), \
66
+ ('CLRHOST_STATE_ACCESS', 'SQL CLR'), \
67
+ ('CMEMPARTITIONED', 'Memory'), \
68
+ ('CMEMTHREAD', 'Memory'), \
69
+ ('CXPACKET', 'Parallelism'), \
70
+ ('CXCONSUMER', 'Parallelism'), \
71
+ ('DBMIRROR_DBM_EVENT', 'Mirroring'), \
72
+ ('DBMIRROR_DBM_MUTEX', 'Mirroring'), \
73
+ ('DBMIRROR_EVENTS_QUEUE', 'Mirroring'), \
74
+ ('DBMIRROR_SEND', 'Mirroring'), \
75
+ ('DBMIRROR_WORKER_QUEUE', 'Mirroring'), \
76
+ ('DBMIRRORING_CMD', 'Mirroring'), \
77
+ ('DTC', 'Transaction'), \
78
+ ('DTC_ABORT_REQUEST', 'Transaction'), \
79
+ ('DTC_RESOLVE', 'Transaction'), \
80
+ ('DTC_STATE', 'Transaction'), \
81
+ ('DTC_TMDOWN_REQUEST', 'Transaction'), \
82
+ ('DTC_WAITFOR_OUTCOME', 'Transaction'), \
83
+ ('DTCNEW_ENLIST', 'Transaction'), \
84
+ ('DTCNEW_PREPARE', 'Transaction'), \
85
+ ('DTCNEW_RECOVERY', 'Transaction'), \
86
+ ('DTCNEW_TM', 'Transaction'), \
87
+ ('DTCNEW_TRANSACTION_ENLISTMENT', 'Transaction'), \
88
+ ('DTCPNTSYNC', 'Transaction'), \
89
+ ('EE_PMOLOCK', 'Memory'), \
90
+ ('EXCHANGE', 'Parallelism'), \
91
+ ('EXTERNAL_SCRIPT_NETWORK_IOF', 'Network IO'), \
92
+ ('FCB_REPLICA_READ', 'Replication'), \
93
+ ('FCB_REPLICA_WRITE', 'Replication'), \
94
+ ('FT_COMPROWSET_RWLOCK', 'Full Text Search'), \
95
+ ('FT_IFTS_RWLOCK', 'Full Text Search'), \
96
+ ('FT_IFTS_SCHEDULER_IDLE_WAIT', 'Idle'), \
97
+ ('FT_IFTSHC_MUTEX', 'Full Text Search'), \
98
+ ('FT_IFTSISM_MUTEX', 'Full Text Search'), \
99
+ ('FT_MASTER_MERGE', 'Full Text Search'), \
100
+ ('FT_MASTER_MERGE_COORDINATOR', 'Full Text Search'), \
101
+ ('FT_METADATA_MUTEX', 'Full Text Search'), \
102
+ ('FT_PROPERTYLIST_CACHE', 'Full Text Search'), \
103
+ ('FT_RESTART_CRAWL', 'Full Text Search'), \
104
+ ('FULLTEXT GATHERER', 'Full Text Search'), \
105
+ ('HADR_AG_MUTEX', 'Replication'), \
106
+ ('HADR_AR_CRITICAL_SECTION_ENTRY', 'Replication'), \
107
+ ('HADR_AR_MANAGER_MUTEX', 'Replication'), \
108
+ ('HADR_AR_UNLOAD_COMPLETED', 'Replication'), \
109
+ ('HADR_ARCONTROLLER_NOTIFICATIONS_SUBSCRIBER_LIST', 'Replication'), \
110
+ ('HADR_BACKUP_BULK_LOCK', 'Replication'), \
111
+ ('HADR_BACKUP_QUEUE', 'Replication'), \
112
+ ('HADR_CLUSAPI_CALL', 'Replication'), \
113
+ ('HADR_COMPRESSED_CACHE_SYNC', 'Replication'), \
114
+ ('HADR_CONNECTIVITY_INFO', 'Replication'), \
115
+ ('HADR_DATABASE_FLOW_CONTROL', 'Replication'), \
116
+ ('HADR_DATABASE_VERSIONING_STATE', 'Replication'), \
117
+ ('HADR_DATABASE_WAIT_FOR_RECOVERY', 'Replication'), \
118
+ ('HADR_DATABASE_WAIT_FOR_RESTART', 'Replication'), \
119
+ ('HADR_DATABASE_WAIT_FOR_TRANSITION_TO_VERSIONING', 'Replication'), \
120
+ ('HADR_DB_COMMAND', 'Replication'), \
121
+ ('HADR_DB_OP_COMPLETION_SYNC', 'Replication'), \
122
+ ('HADR_DB_OP_START_SYNC', 'Replication'), \
123
+ ('HADR_DBR_SUBSCRIBER', 'Replication'), \
124
+ ('HADR_DBR_SUBSCRIBER_FILTER_LIST', 'Replication'), \
125
+ ('HADR_DBSEEDING', 'Replication'), \
126
+ ('HADR_DBSEEDING_LIST', 'Replication'), \
127
+ ('HADR_DBSTATECHANGE_SYNC', 'Replication'), \
128
+ ('HADR_FABRIC_CALLBACK', 'Replication'), \
129
+ ('HADR_FILESTREAM_BLOCK_FLUSH', 'Replication'), \
130
+ ('HADR_FILESTREAM_FILE_CLOSE', 'Replication'), \
131
+ ('HADR_FILESTREAM_FILE_REQUEST', 'Replication'), \
132
+ ('HADR_FILESTREAM_IOMGR', 'Replication'), \
133
+ ('HADR_FILESTREAM_IOMGR_IOCOMPLETION', 'Replication'), \
134
+ ('HADR_FILESTREAM_MANAGER', 'Replication'), \
135
+ ('HADR_FILESTREAM_PREPROC', 'Replication'), \
136
+ ('HADR_GROUP_COMMIT', 'Replication'), \
137
+ ('HADR_LOGCAPTURE_SYNC', 'Replication'), \
138
+ ('HADR_LOGCAPTURE_WAIT', 'Replication'), \
139
+ ('HADR_LOGPROGRESS_SYNC', 'Replication'), \
140
+ ('HADR_NOTIFICATION_DEQUEUE', 'Replication'), \
141
+ ('HADR_NOTIFICATION_WORKER_EXCLUSIVE_ACCESS', 'Replication'), \
142
+ ('HADR_NOTIFICATION_WORKER_STARTUP_SYNC', 'Replication'), \
143
+ ('HADR_NOTIFICATION_WORKER_TERMINATION_SYNC', 'Replication'), \
144
+ ('HADR_PARTNER_SYNC', 'Replication'), \
145
+ ('HADR_READ_ALL_NETWORKS', 'Replication'), \
146
+ ('HADR_RECOVERY_WAIT_FOR_CONNECTION', 'Replication'), \
147
+ ('HADR_RECOVERY_WAIT_FOR_UNDO', 'Replication'), \
148
+ ('HADR_REPLICAINFO_SYNC', 'Replication'), \
149
+ ('HADR_SEEDING_CANCELLATION', 'Replication'), \
150
+ ('HADR_SEEDING_FILE_LIST', 'Replication'), \
151
+ ('HADR_SEEDING_LIMIT_BACKUPS', 'Replication'), \
152
+ ('HADR_SEEDING_SYNC_COMPLETION', 'Replication'), \
153
+ ('HADR_SEEDING_TIMEOUT_TASK', 'Replication'), \
154
+ ('HADR_SEEDING_WAIT_FOR_COMPLETION', 'Replication'), \
155
+ ('HADR_SYNC_COMMIT', 'Replication'), \
156
+ ('HADR_SYNCHRONIZING_THROTTLE', 'Replication'), \
157
+ ('HADR_TDS_LISTENER_SYNC', 'Replication'), \
158
+ ('HADR_TDS_LISTENER_SYNC_PROCESSING', 'Replication'), \
159
+ ('HADR_THROTTLE_LOG_RATE_GOVERNOR', 'Log Rate Governor'), \
160
+ ('HADR_TIMER_TASK', 'Replication'), \
161
+ ('HADR_TRANSPORT_DBRLIST', 'Replication'), \
162
+ ('HADR_TRANSPORT_FLOW_CONTROL', 'Replication'), \
163
+ ('HADR_TRANSPORT_SESSION', 'Replication'), \
164
+ ('HADR_WORK_POOL', 'Replication'), \
165
+ ('HADR_WORK_QUEUE', 'Replication'), \
166
+ ('HADR_XRF_STACK_ACCESS', 'Replication'), \
167
+ ('INSTANCE_LOG_RATE_GOVERNOR', 'Log Rate Governor'), \
168
+ ('IO_COMPLETION', 'Other Disk IO'), \
169
+ ('IO_QUEUE_LIMIT', 'Other Disk IO'), \
170
+ ('IO_RETRY', 'Other Disk IO'), \
171
+ ('LATCH_DT', 'Latch'), \
172
+ ('LATCH_EX', 'Latch'), \
173
+ ('LATCH_KP', 'Latch'), \
174
+ ('LATCH_NL', 'Latch'), \
175
+ ('LATCH_SH', 'Latch'), \
176
+ ('LATCH_UP', 'Latch'), \
177
+ ('LAZYWRITER_SLEEP', 'Idle'), \
178
+ ('LCK_M_BU', 'Lock'), \
179
+ ('LCK_M_BU_ABORT_BLOCKERS', 'Lock'), \
180
+ ('LCK_M_BU_LOW_PRIORITY', 'Lock'), \
181
+ ('LCK_M_IS', 'Lock'), \
182
+ ('LCK_M_IS_ABORT_BLOCKERS', 'Lock'), \
183
+ ('LCK_M_IS_LOW_PRIORITY', 'Lock'), \
184
+ ('LCK_M_IU', 'Lock'), \
185
+ ('LCK_M_IU_ABORT_BLOCKERS', 'Lock'), \
186
+ ('LCK_M_IU_LOW_PRIORITY', 'Lock'), \
187
+ ('LCK_M_IX', 'Lock'), \
188
+ ('LCK_M_IX_ABORT_BLOCKERS', 'Lock'), \
189
+ ('LCK_M_IX_LOW_PRIORITY', 'Lock'), \
190
+ ('LCK_M_RIn_NL', 'Lock'), \
191
+ ('LCK_M_RIn_NL_ABORT_BLOCKERS', 'Lock'), \
192
+ ('LCK_M_RIn_NL_LOW_PRIORITY', 'Lock'), \
193
+ ('LCK_M_RIn_S', 'Lock'), \
194
+ ('LCK_M_RIn_S_ABORT_BLOCKERS', 'Lock'), \
195
+ ('LCK_M_RIn_S_LOW_PRIORITY', 'Lock'), \
196
+ ('LCK_M_RIn_U', 'Lock'), \
197
+ ('LCK_M_RIn_U_ABORT_BLOCKERS', 'Lock'), \
198
+ ('LCK_M_RIn_U_LOW_PRIORITY', 'Lock'), \
199
+ ('LCK_M_RIn_X', 'Lock'), \
200
+ ('LCK_M_RIn_X_ABORT_BLOCKERS', 'Lock'), \
201
+ ('LCK_M_RIn_X_LOW_PRIORITY', 'Lock'), \
202
+ ('LCK_M_RS_S', 'Lock'), \
203
+ ('LCK_M_RS_S_ABORT_BLOCKERS', 'Lock'), \
204
+ ('LCK_M_RS_S_LOW_PRIORITY', 'Lock'), \
205
+ ('LCK_M_RS_U', 'Lock'), \
206
+ ('LCK_M_RS_U_ABORT_BLOCKERS', 'Lock'), \
207
+ ('LCK_M_RS_U_LOW_PRIORITY', 'Lock'), \
208
+ ('LCK_M_RX_S', 'Lock'), \
209
+ ('LCK_M_RX_S_ABORT_BLOCKERS', 'Lock'), \
210
+ ('LCK_M_RX_S_LOW_PRIORITY', 'Lock'), \
211
+ ('LCK_M_RX_U', 'Lock'), \
212
+ ('LCK_M_RX_U_ABORT_BLOCKERS', 'Lock'), \
213
+ ('LCK_M_RX_U_LOW_PRIORITY', 'Lock'), \
214
+ ('LCK_M_RX_X', 'Lock'), \
215
+ ('LCK_M_RX_X_ABORT_BLOCKERS', 'Lock'), \
216
+ ('LCK_M_RX_X_LOW_PRIORITY', 'Lock'), \
217
+ ('LCK_M_S', 'Lock'), \
218
+ ('LCK_M_S_ABORT_BLOCKERS', 'Lock'), \
219
+ ('LCK_M_S_LOW_PRIORITY', 'Lock'), \
220
+ ('LCK_M_SCH_M', 'Lock'), \
221
+ ('LCK_M_SCH_M_ABORT_BLOCKERS', 'Lock'), \
222
+ ('LCK_M_SCH_M_LOW_PRIORITY', 'Lock'), \
223
+ ('LCK_M_SCH_S', 'Lock'), \
224
+ ('LCK_M_SCH_S_ABORT_BLOCKERS', 'Lock'), \
225
+ ('LCK_M_SCH_S_LOW_PRIORITY', 'Lock'), \
226
+ ('LCK_M_SIU', 'Lock'), \
227
+ ('LCK_M_SIU_ABORT_BLOCKERS', 'Lock'), \
228
+ ('LCK_M_SIU_LOW_PRIORITY', 'Lock'), \
229
+ ('LCK_M_SIX', 'Lock'), \
230
+ ('LCK_M_SIX_ABORT_BLOCKERS', 'Lock'), \
231
+ ('LCK_M_SIX_LOW_PRIORITY', 'Lock'), \
232
+ ('LCK_M_U', 'Lock'), \
233
+ ('LCK_M_U_ABORT_BLOCKERS', 'Lock'), \
234
+ ('LCK_M_U_LOW_PRIORITY', 'Lock'), \
235
+ ('LCK_M_UIX', 'Lock'), \
236
+ ('LCK_M_UIX_ABORT_BLOCKERS', 'Lock'), \
237
+ ('LCK_M_UIX_LOW_PRIORITY', 'Lock'), \
238
+ ('LCK_M_X', 'Lock'), \
239
+ ('LCK_M_X_ABORT_BLOCKERS', 'Lock'), \
240
+ ('LCK_M_X_LOW_PRIORITY', 'Lock'), \
241
+ ('LOGBUFFER', 'Tran Log IO'), \
242
+ ('LOGMGR', 'Tran Log IO'), \
243
+ ('LOGMGR_FLUSH', 'Tran Log IO'), \
244
+ ('LOGMGR_PMM_LOG', 'Tran Log IO'), \
245
+ ('LOGMGR_QUEUE', 'Idle'), \
246
+ ('LOGMGR_RESERVE_APPEND', 'Tran Log IO'), \
247
+ ('MEMORY_ALLOCATION_EXT', 'Memory'), \
248
+ ('MEMORY_GRANT_UPDATE', 'Memory'), \
249
+ ('MSQL_XACT_MGR_MUTEX', 'Transaction'), \
250
+ ('MSQL_XACT_MUTEX', 'Transaction'), \
251
+ ('MSSEARCH', 'Full Text Search'), \
252
+ ('NET_WAITFOR_PACKET', 'Network IO'), \
253
+ ('ONDEMAND_TASK_QUEUE', 'Idle'), \
254
+ ('PAGEIOLATCH_DT', 'Buffer IO'), \
255
+ ('PAGEIOLATCH_EX', 'Buffer IO'), \
256
+ ('PAGEIOLATCH_KP', 'Buffer IO'), \
257
+ ('PAGEIOLATCH_NL', 'Buffer IO'), \
258
+ ('PAGEIOLATCH_SH', 'Buffer IO'), \
259
+ ('PAGEIOLATCH_UP', 'Buffer IO'), \
260
+ ('PAGELATCH_DT', 'Buffer Latch'), \
261
+ ('PAGELATCH_EX', 'Buffer Latch'), \
262
+ ('PAGELATCH_KP', 'Buffer Latch'), \
263
+ ('PAGELATCH_NL', 'Buffer Latch'), \
264
+ ('PAGELATCH_SH', 'Buffer Latch'), \
265
+ ('PAGELATCH_UP', 'Buffer Latch'), \
266
+ ('POOL_LOG_RATE_GOVERNOR', 'Log Rate Governor'), \
267
+ ('PREEMPTIVE_ABR', 'Preemptive'), \
268
+ ('PREEMPTIVE_CLOSEBACKUPMEDIA', 'Preemptive'), \
269
+ ('PREEMPTIVE_CLOSEBACKUPTAPE', 'Preemptive'), \
270
+ ('PREEMPTIVE_CLOSEBACKUPVDIDEVICE', 'Preemptive'), \
271
+ ('PREEMPTIVE_CLUSAPI_CLUSTERRESOURCECONTROL', 'Preemptive'), \
272
+ ('PREEMPTIVE_COM_COCREATEINSTANCE', 'Preemptive'), \
273
+ ('PREEMPTIVE_COM_COGETCLASSOBJECT', 'Preemptive'), \
274
+ ('PREEMPTIVE_COM_CREATEACCESSOR', 'Preemptive'), \
275
+ ('PREEMPTIVE_COM_DELETEROWS', 'Preemptive'), \
276
+ ('PREEMPTIVE_COM_GETCOMMANDTEXT', 'Preemptive'), \
277
+ ('PREEMPTIVE_COM_GETDATA', 'Preemptive'), \
278
+ ('PREEMPTIVE_COM_GETNEXTROWS', 'Preemptive'), \
279
+ ('PREEMPTIVE_COM_GETRESULT', 'Preemptive'), \
280
+ ('PREEMPTIVE_COM_GETROWSBYBOOKMARK', 'Preemptive'), \
281
+ ('PREEMPTIVE_COM_LBFLUSH', 'Preemptive'), \
282
+ ('PREEMPTIVE_COM_LBLOCKREGION', 'Preemptive'), \
283
+ ('PREEMPTIVE_COM_LBREADAT', 'Preemptive'), \
284
+ ('PREEMPTIVE_COM_LBSETSIZE', 'Preemptive'), \
285
+ ('PREEMPTIVE_COM_LBSTAT', 'Preemptive'), \
286
+ ('PREEMPTIVE_COM_LBUNLOCKREGION', 'Preemptive'), \
287
+ ('PREEMPTIVE_COM_LBWRITEAT', 'Preemptive'), \
288
+ ('PREEMPTIVE_COM_QUERYINTERFACE', 'Preemptive'), \
289
+ ('PREEMPTIVE_COM_RELEASE', 'Preemptive'), \
290
+ ('PREEMPTIVE_COM_RELEASEACCESSOR', 'Preemptive'), \
291
+ ('PREEMPTIVE_COM_RELEASEROWS', 'Preemptive'), \
292
+ ('PREEMPTIVE_COM_RELEASESESSION', 'Preemptive'), \
293
+ ('PREEMPTIVE_COM_RESTARTPOSITION', 'Preemptive'), \
294
+ ('PREEMPTIVE_COM_SEQSTRMREAD', 'Preemptive'), \
295
+ ('PREEMPTIVE_COM_SEQSTRMREADANDWRITE', 'Preemptive'), \
296
+ ('PREEMPTIVE_COM_SETDATAFAILURE', 'Preemptive'), \
297
+ ('PREEMPTIVE_COM_SETPARAMETERINFO', 'Preemptive'), \
298
+ ('PREEMPTIVE_COM_SETPARAMETERPROPERTIES', 'Preemptive'), \
299
+ ('PREEMPTIVE_COM_STRMLOCKREGION', 'Preemptive'), \
300
+ ('PREEMPTIVE_COM_STRMSEEKANDREAD', 'Preemptive'), \
301
+ ('PREEMPTIVE_COM_STRMSEEKANDWRITE', 'Preemptive'), \
302
+ ('PREEMPTIVE_COM_STRMSETSIZE', 'Preemptive'), \
303
+ ('PREEMPTIVE_COM_STRMSTAT', 'Preemptive'), \
304
+ ('PREEMPTIVE_COM_STRMUNLOCKREGION', 'Preemptive'), \
305
+ ('PREEMPTIVE_CONSOLEWRITE', 'Preemptive'), \
306
+ ('PREEMPTIVE_CREATEPARAM', 'Preemptive'), \
307
+ ('PREEMPTIVE_DEBUG', 'Preemptive'), \
308
+ ('PREEMPTIVE_DFSADDLINK', 'Preemptive'), \
309
+ ('PREEMPTIVE_DFSLINKEXISTCHECK', 'Preemptive'), \
310
+ ('PREEMPTIVE_DFSLINKHEALTHCHECK', 'Preemptive'), \
311
+ ('PREEMPTIVE_DFSREMOVELINK', 'Preemptive'), \
312
+ ('PREEMPTIVE_DFSREMOVEROOT', 'Preemptive'), \
313
+ ('PREEMPTIVE_DFSROOTFOLDERCHECK', 'Preemptive'), \
314
+ ('PREEMPTIVE_DFSROOTINIT', 'Preemptive'), \
315
+ ('PREEMPTIVE_DFSROOTSHARECHECK', 'Preemptive'), \
316
+ ('PREEMPTIVE_DTC_ABORT', 'Preemptive'), \
317
+ ('PREEMPTIVE_DTC_ABORTREQUESTDONE', 'Preemptive'), \
318
+ ('PREEMPTIVE_DTC_BEGINTRANSACTION', 'Preemptive'), \
319
+ ('PREEMPTIVE_DTC_COMMITREQUESTDONE', 'Preemptive'), \
320
+ ('PREEMPTIVE_DTC_ENLIST', 'Preemptive'), \
321
+ ('PREEMPTIVE_DTC_PREPAREREQUESTDONE', 'Preemptive'), \
322
+ ('PREEMPTIVE_FILESIZEGET', 'Preemptive'), \
323
+ ('PREEMPTIVE_FSAOLEDB_ABORTTRANSACTION', 'Preemptive'), \
324
+ ('PREEMPTIVE_FSAOLEDB_COMMITTRANSACTION', 'Preemptive'), \
325
+ ('PREEMPTIVE_FSAOLEDB_STARTTRANSACTION', 'Preemptive'), \
326
+ ('PREEMPTIVE_FSRECOVER_UNCONDITIONALUNDO', 'Preemptive'), \
327
+ ('PREEMPTIVE_GETRMINFO', 'Preemptive'), \
328
+ ('PREEMPTIVE_HADR_LEASE_MECHANISM', 'Preemptive'), \
329
+ ('PREEMPTIVE_HTTP_EVENT_WAIT', 'Preemptive'), \
330
+ ('PREEMPTIVE_HTTP_REQUEST', 'Preemptive'), \
331
+ ('PREEMPTIVE_LOCKMONITOR', 'Preemptive'), \
332
+ ('PREEMPTIVE_MSS_RELEASE', 'Preemptive'), \
333
+ ('PREEMPTIVE_ODBCOPS', 'Preemptive'), \
334
+ ('PREEMPTIVE_OLE_UNINIT', 'Preemptive'), \
335
+ ('PREEMPTIVE_OLEDB_ABORTORCOMMITTRAN', 'Preemptive'), \
336
+ ('PREEMPTIVE_OLEDB_ABORTTRAN', 'Preemptive'), \
337
+ ('PREEMPTIVE_OLEDB_GETDATASOURCE', 'Preemptive'), \
338
+ ('PREEMPTIVE_OLEDB_GETLITERALINFO', 'Preemptive'), \
339
+ ('PREEMPTIVE_OLEDB_GETPROPERTIES', 'Preemptive'), \
340
+ ('PREEMPTIVE_OLEDB_GETPROPERTYINFO', 'Preemptive'), \
341
+ ('PREEMPTIVE_OLEDB_GETSCHEMALOCK', 'Preemptive'), \
342
+ ('PREEMPTIVE_OLEDB_JOINTRANSACTION', 'Preemptive'), \
343
+ ('PREEMPTIVE_OLEDB_RELEASE', 'Preemptive'), \
344
+ ('PREEMPTIVE_OLEDB_SETPROPERTIES', 'Preemptive'), \
345
+ ('PREEMPTIVE_OLEDBOPS', 'Preemptive'), \
346
+ ('PREEMPTIVE_OS_ACCEPTSECURITYCONTEXT', 'Preemptive'), \
347
+ ('PREEMPTIVE_OS_ACQUIRECREDENTIALSHANDLE', 'Preemptive'), \
348
+ ('PREEMPTIVE_OS_AUTHENTICATIONOPS', 'Preemptive'), \
349
+ ('PREEMPTIVE_OS_AUTHORIZATIONOPS', 'Preemptive'), \
350
+ ('PREEMPTIVE_OS_AUTHZGETINFORMATIONFROMCONTEXT', 'Preemptive'), \
351
+ ('PREEMPTIVE_OS_AUTHZINITIALIZECONTEXTFROMSID', 'Preemptive'), \
352
+ ('PREEMPTIVE_OS_AUTHZINITIALIZERESOURCEMANAGER', 'Preemptive'), \
353
+ ('PREEMPTIVE_OS_BACKUPREAD', 'Preemptive'), \
354
+ ('PREEMPTIVE_OS_CLOSEHANDLE', 'Preemptive'), \
355
+ ('PREEMPTIVE_OS_CLUSTEROPS', 'Preemptive'), \
356
+ ('PREEMPTIVE_OS_COMOPS', 'Preemptive'), \
357
+ ('PREEMPTIVE_OS_COMPLETEAUTHTOKEN', 'Preemptive'), \
358
+ ('PREEMPTIVE_OS_COPYFILE', 'Preemptive'), \
359
+ ('PREEMPTIVE_OS_CREATEDIRECTORY', 'Preemptive'), \
360
+ ('PREEMPTIVE_OS_CREATEFILE', 'Preemptive'), \
361
+ ('PREEMPTIVE_OS_CRYPTACQUIRECONTEXT', 'Preemptive'), \
362
+ ('PREEMPTIVE_OS_CRYPTIMPORTKEY', 'Preemptive'), \
363
+ ('PREEMPTIVE_OS_CRYPTOPS', 'Preemptive'), \
364
+ ('PREEMPTIVE_OS_DECRYPTMESSAGE', 'Preemptive'), \
365
+ ('PREEMPTIVE_OS_DELETEFILE', 'Preemptive'), \
366
+ ('PREEMPTIVE_OS_DELETESECURITYCONTEXT', 'Preemptive'), \
367
+ ('PREEMPTIVE_OS_DEVICEIOCONTROL', 'Preemptive'), \
368
+ ('PREEMPTIVE_OS_DEVICEOPS', 'Preemptive'), \
369
+ ('PREEMPTIVE_OS_DIRSVC_NETWORKOPS', 'Preemptive'), \
370
+ ('PREEMPTIVE_OS_DISCONNECTNAMEDPIPE', 'Preemptive'), \
371
+ ('PREEMPTIVE_OS_DOMAINSERVICESOPS', 'Preemptive'), \
372
+ ('PREEMPTIVE_OS_DSGETDCNAME', 'Preemptive'), \
373
+ ('PREEMPTIVE_OS_DTCOPS', 'Preemptive'), \
374
+ ('PREEMPTIVE_OS_ENCRYPTMESSAGE', 'Preemptive'), \
375
+ ('PREEMPTIVE_OS_FILEOPS', 'Preemptive'), \
376
+ ('PREEMPTIVE_OS_FINDFILE', 'Preemptive'), \
377
+ ('PREEMPTIVE_OS_FLUSHFILEBUFFERS', 'Preemptive'), \
378
+ ('PREEMPTIVE_OS_FORMATMESSAGE', 'Preemptive'), \
379
+ ('PREEMPTIVE_OS_FREECREDENTIALSHANDLE', 'Preemptive'), \
380
+ ('PREEMPTIVE_OS_FREELIBRARY', 'Preemptive'), \
381
+ ('PREEMPTIVE_OS_GENERICOPS', 'Preemptive'), \
382
+ ('PREEMPTIVE_OS_GETADDRINFO', 'Preemptive'), \
383
+ ('PREEMPTIVE_OS_GETCOMPRESSEDFILESIZE', 'Preemptive'), \
384
+ ('PREEMPTIVE_OS_GETDISKFREESPACE', 'Preemptive'), \
385
+ ('PREEMPTIVE_OS_GETFILEATTRIBUTES', 'Preemptive'), \
386
+ ('PREEMPTIVE_OS_GETFILESIZE', 'Preemptive'), \
387
+ ('PREEMPTIVE_OS_GETFINALFILEPATHBYHANDLE', 'Preemptive'), \
388
+ ('PREEMPTIVE_OS_GETLONGPATHNAME', 'Preemptive'), \
389
+ ('PREEMPTIVE_OS_GETPROCADDRESS', 'Preemptive'), \
390
+ ('PREEMPTIVE_OS_GETVOLUMENAMEFORVOLUMEMOUNTPOINT', 'Preemptive'), \
391
+ ('PREEMPTIVE_OS_GETVOLUMEPATHNAME', 'Preemptive'), \
392
+ ('PREEMPTIVE_OS_INITIALIZESECURITYCONTEXT', 'Preemptive'), \
393
+ ('PREEMPTIVE_OS_LIBRARYOPS', 'Preemptive'), \
394
+ ('PREEMPTIVE_OS_LOADLIBRARY', 'Preemptive'), \
395
+ ('PREEMPTIVE_OS_LOGONUSER', 'Preemptive'), \
396
+ ('PREEMPTIVE_OS_LOOKUPACCOUNTSID', 'Preemptive'), \
397
+ ('PREEMPTIVE_OS_MESSAGEQUEUEOPS', 'Preemptive'), \
398
+ ('PREEMPTIVE_OS_MOVEFILE', 'Preemptive'), \
399
+ ('PREEMPTIVE_OS_NETGROUPGETUSERS', 'Preemptive'), \
400
+ ('PREEMPTIVE_OS_NETLOCALGROUPGETMEMBERS', 'Preemptive'), \
401
+ ('PREEMPTIVE_OS_NETUSERGETGROUPS', 'Preemptive'), \
402
+ ('PREEMPTIVE_OS_NETUSERGETLOCALGROUPS', 'Preemptive'), \
403
+ ('PREEMPTIVE_OS_NETUSERMODALSGET', 'Preemptive'), \
404
+ ('PREEMPTIVE_OS_NETVALIDATEPASSWORDPOLICY', 'Preemptive'), \
405
+ ('PREEMPTIVE_OS_NETVALIDATEPASSWORDPOLICYFREE', 'Preemptive'), \
406
+ ('PREEMPTIVE_OS_OPENDIRECTORY', 'Preemptive'), \
407
+ ('PREEMPTIVE_OS_PDH_WMI_INIT', 'Preemptive'), \
408
+ ('PREEMPTIVE_OS_PIPEOPS', 'Preemptive'), \
409
+ ('PREEMPTIVE_OS_PROCESSOPS', 'Preemptive'), \
410
+ ('PREEMPTIVE_OS_QUERYCONTEXTATTRIBUTES', 'Preemptive'), \
411
+ ('PREEMPTIVE_OS_QUERYREGISTRY', 'Preemptive'), \
412
+ ('PREEMPTIVE_OS_QUERYSECURITYCONTEXTTOKEN', 'Preemptive'), \
413
+ ('PREEMPTIVE_OS_REMOVEDIRECTORY', 'Preemptive'), \
414
+ ('PREEMPTIVE_OS_REPORTEVENT', 'Preemptive'), \
415
+ ('PREEMPTIVE_OS_REVERTTOSELF', 'Preemptive'), \
416
+ ('PREEMPTIVE_OS_RSFXDEVICEOPS', 'Preemptive'), \
417
+ ('PREEMPTIVE_OS_SECURITYOPS', 'Preemptive'), \
418
+ ('PREEMPTIVE_OS_SERVICEOPS', 'Preemptive'), \
419
+ ('PREEMPTIVE_OS_SETENDOFFILE', 'Preemptive'), \
420
+ ('PREEMPTIVE_OS_SETFILEPOINTER', 'Preemptive'), \
421
+ ('PREEMPTIVE_OS_SETFILEVALIDDATA', 'Preemptive'), \
422
+ ('PREEMPTIVE_OS_SETNAMEDSECURITYINFO', 'Preemptive'), \
423
+ ('PREEMPTIVE_OS_SQLCLROPS', 'Preemptive'), \
424
+ ('PREEMPTIVE_OS_SQMLAUNCH', 'Preemptive'), \
425
+ ('PREEMPTIVE_OS_VERIFYSIGNATURE', 'Preemptive'), \
426
+ ('PREEMPTIVE_OS_VERIFYTRUST', 'Preemptive'), \
427
+ ('PREEMPTIVE_OS_VSSOPS', 'Preemptive'), \
428
+ ('PREEMPTIVE_OS_WAITFORSINGLEOBJECT', 'Preemptive'), \
429
+ ('PREEMPTIVE_OS_WINSOCKOPS', 'Preemptive'), \
430
+ ('PREEMPTIVE_OS_WRITEFILE', 'Preemptive'), \
431
+ ('PREEMPTIVE_OS_WRITEFILEGATHER', 'Preemptive'), \
432
+ ('PREEMPTIVE_OS_WSASETLASTERROR', 'Preemptive'), \
433
+ ('PREEMPTIVE_REENLIST', 'Preemptive'), \
434
+ ('PREEMPTIVE_RESIZELOG', 'Preemptive'), \
435
+ ('PREEMPTIVE_ROLLFORWARDREDO', 'Preemptive'), \
436
+ ('PREEMPTIVE_ROLLFORWARDUNDO', 'Preemptive'), \
437
+ ('PREEMPTIVE_SB_STOPENDPOINT', 'Preemptive'), \
438
+ ('PREEMPTIVE_SERVER_STARTUP', 'Preemptive'), \
439
+ ('PREEMPTIVE_SETRMINFO', 'Preemptive'), \
440
+ ('PREEMPTIVE_SHAREDMEM_GETDATA', 'Preemptive'), \
441
+ ('PREEMPTIVE_SNIOPEN', 'Preemptive'), \
442
+ ('PREEMPTIVE_SOSHOST', 'Preemptive'), \
443
+ ('PREEMPTIVE_SOSTESTING', 'Preemptive'), \
444
+ ('PREEMPTIVE_SP_SERVER_DIAGNOSTICS', 'Preemptive'), \
445
+ ('PREEMPTIVE_STARTRM', 'Preemptive'), \
446
+ ('PREEMPTIVE_STREAMFCB_CHECKPOINT', 'Preemptive'), \
447
+ ('PREEMPTIVE_STREAMFCB_RECOVER', 'Preemptive'), \
448
+ ('PREEMPTIVE_STRESSDRIVER', 'Preemptive'), \
449
+ ('PREEMPTIVE_TESTING', 'Preemptive'), \
450
+ ('PREEMPTIVE_TRANSIMPORT', 'Preemptive'), \
451
+ ('PREEMPTIVE_UNMARSHALPROPAGATIONTOKEN', 'Preemptive'), \
452
+ ('PREEMPTIVE_VSS_CREATESNAPSHOT', 'Preemptive'), \
453
+ ('PREEMPTIVE_VSS_CREATEVOLUMESNAPSHOT', 'Preemptive'), \
454
+ ('PREEMPTIVE_XE_CALLBACKEXECUTE', 'Preemptive'), \
455
+ ('PREEMPTIVE_XE_CX_FILE_OPEN', 'Preemptive'), \
456
+ ('PREEMPTIVE_XE_CX_HTTP_CALL', 'Preemptive'), \
457
+ ('PREEMPTIVE_XE_DISPATCHER', 'Preemptive'), \
458
+ ('PREEMPTIVE_XE_ENGINEINIT', 'Preemptive'), \
459
+ ('PREEMPTIVE_XE_GETTARGETSTATE', 'Preemptive'), \
460
+ ('PREEMPTIVE_XE_SESSIONCOMMIT', 'Preemptive'), \
461
+ ('PREEMPTIVE_XE_TARGETFINALIZE', 'Preemptive'), \
462
+ ('PREEMPTIVE_XE_TARGETINIT', 'Preemptive'), \
463
+ ('PREEMPTIVE_XE_TIMERRUN', 'Preemptive'), \
464
+ ('PREEMPTIVE_XETESTING', 'Preemptive'), \
465
+ ('PWAIT_HADR_ACTION_COMPLETED', 'Replication'), \
466
+ ('PWAIT_HADR_CHANGE_NOTIFIER_TERMINATION_SYNC', 'Replication'), \
467
+ ('PWAIT_HADR_CLUSTER_INTEGRATION', 'Replication'), \
468
+ ('PWAIT_HADR_FAILOVER_COMPLETED', 'Replication'), \
469
+ ('PWAIT_HADR_JOIN', 'Replication'), \
470
+ ('PWAIT_HADR_OFFLINE_COMPLETED', 'Replication'), \
471
+ ('PWAIT_HADR_ONLINE_COMPLETED', 'Replication'), \
472
+ ('PWAIT_HADR_POST_ONLINE_COMPLETED', 'Replication'), \
473
+ ('PWAIT_HADR_SERVER_READY_CONNECTIONS', 'Replication'), \
474
+ ('PWAIT_HADR_WORKITEM_COMPLETED', 'Replication'), \
475
+ ('PWAIT_HADRSIM', 'Replication'), \
476
+ ('PWAIT_RESOURCE_SEMAPHORE_FT_PARALLEL_QUERY_SYNC', 'Full Text Search'), \
477
+ ('QUERY_TRACEOUT', 'Tracing'), \
478
+ ('REPL_CACHE_ACCESS', 'Replication'), \
479
+ ('REPL_HISTORYCACHE_ACCESS', 'Replication'), \
480
+ ('REPL_SCHEMA_ACCESS', 'Replication'), \
481
+ ('REPL_TRANFSINFO_ACCESS', 'Replication'), \
482
+ ('REPL_TRANHASHTABLE_ACCESS', 'Replication'), \
483
+ ('REPL_TRANTEXTINFO_ACCESS', 'Replication'), \
484
+ ('REPLICA_WRITES', 'Replication'), \
485
+ ('REQUEST_FOR_DEADLOCK_SEARCH', 'Idle'), \
486
+ ('RESERVED_MEMORY_ALLOCATION_EXT', 'Memory'), \
487
+ ('RESOURCE_SEMAPHORE', 'Memory'), \
488
+ ('RESOURCE_SEMAPHORE_QUERY_COMPILE', 'Compilation'), \
489
+ ('SLEEP_BPOOL_FLUSH', 'Idle'), \
490
+ ('SLEEP_BUFFERPOOL_HELPLW', 'Idle'), \
491
+ ('SLEEP_DBSTARTUP', 'Idle'), \
492
+ ('SLEEP_DCOMSTARTUP', 'Idle'), \
493
+ ('SLEEP_MASTERDBREADY', 'Idle'), \
494
+ ('SLEEP_MASTERMDREADY', 'Idle'), \
495
+ ('SLEEP_MASTERUPGRADED', 'Idle'), \
496
+ ('SLEEP_MEMORYPOOL_ALLOCATEPAGES', 'Idle'), \
497
+ ('SLEEP_MSDBSTARTUP', 'Idle'), \
498
+ ('SLEEP_RETRY_VIRTUALALLOC', 'Idle'), \
499
+ ('SLEEP_SYSTEMTASK', 'Idle'), \
500
+ ('SLEEP_TASK', 'Idle'), \
501
+ ('SLEEP_TEMPDBSTARTUP', 'Idle'), \
502
+ ('SLEEP_WORKSPACE_ALLOCATEPAGE', 'Idle'), \
503
+ ('SOS_SCHEDULER_YIELD', 'CPU'), \
504
+ ('SQLCLR_APPDOMAIN', 'SQL CLR'), \
505
+ ('SQLCLR_ASSEMBLY', 'SQL CLR'), \
506
+ ('SQLCLR_DEADLOCK_DETECTION', 'SQL CLR'), \
507
+ ('SQLCLR_QUANTUM_PUNISHMENT', 'SQL CLR'), \
508
+ ('SQLTRACE_BUFFER_FLUSH', 'Idle'), \
509
+ ('SQLTRACE_FILE_BUFFER', 'Tracing'), \
510
+ ('SQLTRACE_FILE_READ_IO_COMPLETION', 'Tracing'), \
511
+ ('SQLTRACE_FILE_WRITE_IO_COMPLETION', 'Tracing'), \
512
+ ('SQLTRACE_INCREMENTAL_FLUSH_SLEEP', 'Idle'), \
513
+ ('SQLTRACE_PENDING_BUFFER_WRITERS', 'Tracing'), \
514
+ ('SQLTRACE_SHUTDOWN', 'Tracing'), \
515
+ ('SQLTRACE_WAIT_ENTRIES', 'Idle'), \
516
+ ('THREADPOOL', 'Worker Thread'), \
517
+ ('TRACE_EVTNOTIF', 'Tracing'), \
518
+ ('TRACEWRITE', 'Tracing'), \
519
+ ('TRAN_MARKLATCH_DT', 'Transaction'), \
520
+ ('TRAN_MARKLATCH_EX', 'Transaction'), \
521
+ ('TRAN_MARKLATCH_KP', 'Transaction'), \
522
+ ('TRAN_MARKLATCH_NL', 'Transaction'), \
523
+ ('TRAN_MARKLATCH_SH', 'Transaction'), \
524
+ ('TRAN_MARKLATCH_UP', 'Transaction'), \
525
+ ('TRANSACTION_MUTEX', 'Transaction'), \
526
+ ('WAIT_FOR_RESULTS', 'User Wait'), \
527
+ ('WAITFOR', 'User Wait'), \
528
+ ('WRITE_COMPLETION', 'Other Disk IO'), \
529
+ ('WRITELOG', 'Tran Log IO'), \
530
+ ('XACT_OWN_TRANSACTION', 'Transaction'), \
531
+ ('XACT_RECLAIM_SESSION', 'Transaction'), \
532
+ ('XACTLOCKINFO', 'Transaction'), \
533
+ ('XACTWORKSPACE_MUTEX', 'Transaction'), \
534
+ ('XE_DISPATCHER_WAIT', 'Idle'), \
535
+ ('XE_TIMER_EVENT', 'Idle')) AS wc([wait_type], [wait_category]) ON ws.[wait_type] = \
536
+ wc.[wait_type] WHERE ws \
537
+ .[wait_type] NOT IN( \
538
+ N'BROKER_EVENTHANDLER', \
539
+ N'BROKER_RECEIVE_WAITFOR', \
540
+ N'BROKER_TASK_STOP', \
541
+ N'BROKER_TO_FLUSH', \
542
+ N'BROKER_TRANSMITTER', \
543
+ N'CHECKPOINT_QUEUE', \
544
+ N'CHKPT', \
545
+ N'CLR_AUTO_EVENT', \
546
+ N'CLR_MANUAL_EVENT', \
547
+ N'CLR_SEMAPHORE', \
548
+ N'DBMIRROR_DBM_EVENT', \
549
+ N'DBMIRROR_EVENTS_QUEUE', \
550
+ N'DBMIRROR_WORKER_QUEUE', \
551
+ N'DBMIRRORING_CMD', \
552
+ N'DIRTY_PAGE_POLL', \
553
+ N'DISPATCHER_QUEUE_SEMAPHORE', \
554
+ N'EXECSYNC', \
555
+ N'FSAGENT', \
556
+ N'FT_IFTS_SCHEDULER_IDLE_WAIT', \
557
+ N'FT_IFTSHC_MUTEX', \
558
+ N'HADR_CLUSAPI_CALL', \
559
+ N'HADR_FILESTREAM_IOMGR_IOCOMPLETION', \
560
+ N'HADR_LOGCAPTURE_WAIT', \
561
+ N'HADR_NOTIFICATION_DEQUEUE', \
562
+ N'HADR_TIMER_TASK', \
563
+ N'HADR_WORK_QUEUE', \
564
+ N'KSOURCE_WAKEUP', \
565
+ N'LAZYWRITER_SLEEP', \
566
+ N'LOGMGR_QUEUE', \
567
+ N'MEMORY_ALLOCATION_EXT', \
568
+ N'ONDEMAND_TASK_QUEUE', \
569
+ N'PARALLEL_REDO_WORKER_WAIT_WORK', \
570
+ N'PREEMPTIVE_HADR_LEASE_MECHANISM', \
571
+ N'PREEMPTIVE_SP_SERVER_DIAGNOSTICS', \
572
+ N'PREEMPTIVE_OS_LIBRARYOPS', \
573
+ N'PREEMPTIVE_OS_COMOPS', \
574
+ N'PREEMPTIVE_OS_CRYPTOPS', \
575
+ N'PREEMPTIVE_OS_PIPEOPS', \
576
+ 'PREEMPTIVE_OS_GENERICOPS', \
577
+ N'PREEMPTIVE_OS_VERIFYTRUST', \
578
+ N'PREEMPTIVE_OS_DEVICEOPS', \
579
+ N'PREEMPTIVE_XE_CALLBACKEXECUTE', \
580
+ N'PREEMPTIVE_XE_DISPATCHER', \
581
+ N'PREEMPTIVE_XE_GETTARGETSTATE', \
582
+ N'PREEMPTIVE_XE_SESSIONCOMMIT', \
583
+ N'PREEMPTIVE_XE_TARGETINIT', \
584
+ N'PREEMPTIVE_XE_TARGETFINALIZE', \
585
+ N'PWAIT_ALL_COMPONENTS_INITIALIZED', \
586
+ N'PWAIT_DIRECTLOGCONSUMER_GETNEXT', \
587
+ N'QDS_PERSIST_TASK_MAIN_LOOP_SLEEP', \
588
+ N'QDS_ASYNC_QUEUE', \
589
+ N'QDS_CLEANUP_STALE_QUERIES_TASK_MAIN_LOOP_SLEEP', \
590
+ N'REQUEST_FOR_DEADLOCK_SEARCH', \
591
+ N'RESOURCE_QUEUE', \
592
+ N'SERVER_IDLE_CHECK', \
593
+ N'SLEEP_BPOOL_FLUSH', \
594
+ N'SLEEP_DBSTARTUP', \
595
+ N'SLEEP_DCOMSTARTUP', \
596
+ N'SLEEP_MASTERDBREADY', \
597
+ N'SLEEP_MASTERMDREADY', \
598
+ N'SLEEP_MASTERUPGRADED', \
599
+ N'SLEEP_MSDBSTARTUP', \
600
+ N'SLEEP_SYSTEMTASK', \
601
+ N'SLEEP_TASK', \
602
+ N'SLEEP_TEMPDBSTARTUP', \
603
+ N'SNI_HTTP_ACCEPT', \
604
+ N'SP_SERVER_DIAGNOSTICS_SLEEP', \
605
+ N'SQLTRACE_BUFFER_FLUSH', \
606
+ N'SQLTRACE_INCREMENTAL_FLUSH_SLEEP', \
607
+ N'SQLTRACE_WAIT_ENTRIES', \
608
+ N'WAIT_FOR_RESULTS', \
609
+ N'WAITFOR', \
610
+ N'WAITFOR_TASKSHUTDOWN', \
611
+ N'WAIT_XTP_HOST_WAIT', \
612
+ N'WAIT_XTP_OFFLINE_CKPT_NEW_LOG', \
613
+ N'WAIT_XTP_CKPT_CLOSE', \
614
+ N'XE_BUFFERMGR_ALLPROCESSED_EVENT', \
615
+ N'XE_DISPATCHER_JOIN', \
616
+ N'XE_DISPATCHER_WAIT', \
617
+ N'XE_LIVE_TARGET_TVF', \
618
+ N'XE_TIMER_EVENT', \
619
+ N'SOS_WORK_DISPATCHER', \
620
+ 'RESERVED_MEMORY_ALLOCATION_EXT') AND ws.[waiting_tasks_count] > 0 AND ws.[wait_time_ms] > 100;"
621
+
622
+#endif
src/collectors/windows.plugin/perflib-mssql.c
+459
-56
@@ -3,6 +3,8 @@
3
#include "windows_plugin.h"
4
#include "windows-internals.h"
5
6
+#include "perflib-mssql-queries.h"
7
+
8
#include <sqlext.h>
9
#include <sqltypes.h>
10
#include <sql.h>
@@ -36,6 +38,7 @@ struct netdata_mssql_conn {
38
SQLHSTMT databaseListSTMT;
39
SQLHSTMT dataFileSizeSTMT;
40
SQLHSTMT dbTransactionSTMT;
41
+ SQLHSTMT dbWaitsSTMT;
42
SQLHSTMT dbLocksSTMT;
43
44
BOOL is_connected;
@@ -46,6 +49,7 @@ enum netdata_mssql_metrics {
49
NETDATA_MSSQL_SQL_ERRORS,
50
NETDATA_MSSQL_DATABASE,
51
NETDATA_MSSQL_LOCKS,
52
+ NETDATA_MSSQL_WAITS,
53
NETDATA_MSSQL_MEMORY,
54
NETDATA_MSSQL_BUFFER_MANAGEMENT,
55
NETDATA_MSSQL_SQL_STATS,
@@ -54,8 +58,35 @@ enum netdata_mssql_metrics {
58
NETDATA_MSSQL_METRICS_END
59
};
60
61
+struct mssql_db_waits {
62
+ const char *wait_type;
63
+ const char *wait_category;
64
+
65
+ RRDSET *st_total_wait;
66
+ RRDDIM *rd_total_wait;
67
+
68
+ RRDSET *st_resource_wait_msec;
69
+ RRDDIM *rd_resource_wait_msec;
70
+
71
+ RRDSET *st_signal_wait_msec;
72
+ RRDDIM *rd_signal_wait_msec;
73
+
74
+ RRDSET *st_max_wait_time_msec;
75
+ RRDDIM *rd_max_wait_time_msec;
76
+
77
+ RRDSET *st_waiting_tasks;
78
+ RRDDIM *rd_waiting_tasks;
79
+
80
+ COUNTER_DATA MSSQLDatabaseTotalWait;
81
+ COUNTER_DATA MSSQLDatabaseResourceWaitMSec;
82
+ COUNTER_DATA MSSQLDatabaseSignalWaitMSec;
83
+ COUNTER_DATA MSSQLDatabaseMaxWaitTimeMSec;
84
+ COUNTER_DATA MSSQLDatabaseWaitingTasks;
85
+};
86
+
87
struct mssql_instance {
88
char *instanceID;
89
+ int update_every;
90
91
struct netdata_mssql_conn conn;
92
@@ -102,8 +133,6 @@ struct mssql_instance {
133
RRDDIM *rd_sql_errors;
134
135
DICTIONARY *locks_instances;
105
- RRDSET *st_deadLocks;
106
- RRDSET *st_lockWait;
136
137
DICTIONARY *databases;
138
@@ -119,6 +148,8 @@ struct mssql_instance {
148
RRDSET *st_mem_tot_server;
149
RRDDIM *rd_mem_tot_server;
150
151
+ DICTIONARY *waits;
152
+
153
COUNTER_DATA MSSQLAccessMethodPageSplits;
154
COUNTER_DATA MSSQLBufferCacheHits;
155
COUNTER_DATA MSSQLBufferCheckpointPages;
@@ -147,7 +178,10 @@ struct mssql_lock_instance {
178
COUNTER_DATA lockWait;
179
COUNTER_DATA deadLocks;
180
181
+ RRDSET *st_deadLocks;
182
RRDDIM *rd_lockWait;
183
+
184
+ RRDSET *st_lockWait;
185
RRDDIM *rd_deadLocks;
186
};
187
@@ -257,7 +291,8 @@ static void netdata_MSSQL_error(uint32_t type, SQLHANDLE handle, enum netdata_ms
291
}
292
}
293
260
-static inline void netdata_MSSQL_release_results(SQLHSTMT *stmt) {
294
+static inline void netdata_MSSQL_release_results(SQLHSTMT *stmt)
295
+{
296
SQLFreeStmt(stmt, SQL_CLOSE);
297
SQLFreeStmt(stmt, SQL_UNBIND);
298
SQLFreeStmt(stmt, SQL_RESET_PARAMS);
@@ -296,17 +331,6 @@ static ULONGLONG netdata_MSSQL_fill_long_value(SQLHSTMT *stmt, const char *mask,
331
return (ULONGLONG)(db_size * MEGA_FACTOR);
332
}
333
299
-#define NETDATA_QUERY_LIST_DB "SELECT name FROM sys.databases;"
300
-
301
-// https://learn.microsoft.com/en-us/sql/relational-databases/system-catalog-views/sys-database-files-transact-sql?view=sql-server-ver16
302
-#define NETDATA_QUERY_DATA_FILE_SIZE_MASK "SELECT size * 8/1024 FROM %s.sys.database_files WHERE type = 0;"
303
-
304
-// https://learn.microsoft.com/en-us/sql/relational-databases/system-compatibility-views/sys-sysprocesses-transact-sql?view=sql-server-ver16
305
-// SQL SERVER BEFORE 2008 DOES NOT HAVE DATA IN THIS TABLE
306
-// https://github.com/influxdata/telegraf/blob/081dfa26e80d8764fb7f9aac5230e81584b62b56/plugins/inputs/sqlserver/sqlqueriesV2.go#L1259
307
-#define NETDATA_QUERY_TRANSACTIONS_MASK \
308
- "select counter_name, cntr_value from %s.sys.dm_os_performance_counters where instance_name = '%s' and counter_name in ('Active Transactions', 'Transactions/sec', 'Write Transactions/sec', 'Backup/Restore Throughput/sec', 'Log Bytes Flushed/sec', 'Log Flushes/sec', 'Number of Deadlocks/sec', 'Lock Waits/sec', 'Lock Timeouts/sec', 'Lock Requests/sec');"
309
-
334
#define NETDATA_MSSQL_ACTIVE_TRANSACTIONS_METRIC "Active Transactions"
335
#define NETDATA_MSSQL_TRANSACTION_PER_SEC_METRIC "Transactions/sec"
336
#define NETDATA_MSSQL_WRITE_TRANSACTIONS_METRIC "Write Transactions/sec"
@@ -409,14 +433,11 @@ endtransactions:
433
netdata_MSSQL_release_results(mdi->parent->conn.dbTransactionSTMT);
434
}
435
412
-// https://learn.microsoft.com/en-us/sql/relational-databases/system-dynamic-management-views/sys-dm-tran-locks-transact-sql?view=sql-server-ver16
413
-#define NETDATA_QUERY_LOCKS_MASK \
414
- "SELECT resource_type, count(*) FROM %s.sys.dm_tran_locks WHERE DB_NAME(resource_database_id) = '%s' group by resource_type;"
436
void dict_mssql_fill_locks(struct mssql_db_instance *mdi, const char *dbname)
437
{
438
#define NETDATA_MSSQL_MAX_RESOURCE_TYPE (60)
418
- char resource_type[NETDATA_MSSQL_MAX_RESOURCE_TYPE + 1];
419
- long value;
439
+ char resource_type[NETDATA_MSSQL_MAX_RESOURCE_TYPE + 1] = {};
440
+ long value = 0;
441
SQLLEN col_object_len = 0, col_value_len = 0;
442
443
SQLCHAR query[sizeof(NETDATA_QUERY_LOCKS_MASK) + 2 * NETDATA_MAX_INSTANCE_OBJECT + 1];
@@ -469,12 +490,112 @@ void dict_mssql_fill_locks(struct mssql_db_instance *mdi, const char *dbname)
490
dictionary_set(mdi->parent->locks_instances, resource_type, NULL, sizeof(*mli));
491
if (!mli)
492
continue;
493
+
494
+ mli->lockWait.current.Data = value;
495
} while (true);
496
497
endlocks:
498
netdata_MSSQL_release_results(mdi->parent->conn.dbLocksSTMT);
499
}
500
501
+int dict_mssql_fill_waits(struct mssql_instance *mi)
502
+{
503
+ char wait_type[NETDATA_MAX_INSTANCE_OBJECT + 1] = {};
504
+ char wait_category[NETDATA_MAX_INSTANCE_OBJECT + 1] = {};
505
+ SQLBIGINT total_wait = 0;
506
+ SQLBIGINT resource_wait = 0;
507
+ SQLBIGINT signal_wait = 0;
508
+ SQLBIGINT max_wait = 0;
509
+ SQLBIGINT waiting_tasks = 0;
510
+ int success = 0;
511
+ SQLLEN col_wait_type_len = 0, col_total_wait_len = 0, col_resource_wait_len = 0, col_signal_wait_len = 0,
512
+ col_max_wait_len = 0, col_waiting_tasks_len = 0, col_wait_category_len = 0;
513
+
514
+ SQLRETURN ret = SQLExecDirect(mi->conn.dbWaitsSTMT, (SQLCHAR *)NETDATA_QUERY_CHECK_WAITS, SQL_NTS);
515
+ if (ret != SQL_SUCCESS) {
516
+ netdata_MSSQL_error(SQL_HANDLE_STMT, mi->conn.dbWaitsSTMT, NETDATA_MSSQL_ODBC_QUERY, mi->instanceID);
517
+ goto endwait;
518
+ }
519
+
520
+ ret = SQLBindCol(mi->conn.dbWaitsSTMT, 1, SQL_C_CHAR, wait_type, sizeof(wait_type), &col_wait_type_len);
521
+ if (ret != SQL_SUCCESS) {
522
+ netdata_MSSQL_error(SQL_HANDLE_STMT, mi->conn.dbWaitsSTMT, NETDATA_MSSQL_ODBC_PREPARE, mi->instanceID);
523
+ goto endwait;
524
+ }
525
+
526
+ ret = SQLBindCol(mi->conn.dbWaitsSTMT, 2, SQL_C_LONG, &total_wait, sizeof(total_wait), &col_total_wait_len);
527
+ if (ret != SQL_SUCCESS) {
528
+ netdata_MSSQL_error(SQL_HANDLE_STMT, mi->conn.dbWaitsSTMT, NETDATA_MSSQL_ODBC_PREPARE, mi->instanceID);
529
+ goto endwait;
530
+ }
531
+
532
+ ret =
533
+ SQLBindCol(mi->conn.dbWaitsSTMT, 3, SQL_C_LONG, &resource_wait, sizeof(resource_wait), &col_resource_wait_len);
534
+ if (ret != SQL_SUCCESS) {
535
+ netdata_MSSQL_error(SQL_HANDLE_STMT, mi->conn.dbWaitsSTMT, NETDATA_MSSQL_ODBC_PREPARE, mi->instanceID);
536
+ goto endwait;
537
+ }
538
+
539
+ ret = SQLBindCol(mi->conn.dbWaitsSTMT, 4, SQL_C_LONG, &signal_wait, sizeof(signal_wait), &col_signal_wait_len);
540
+ if (ret != SQL_SUCCESS) {
541
+ netdata_MSSQL_error(SQL_HANDLE_STMT, mi->conn.dbWaitsSTMT, NETDATA_MSSQL_ODBC_PREPARE, mi->instanceID);
542
+ goto endwait;
543
+ }
544
+
545
+ ret = SQLBindCol(mi->conn.dbWaitsSTMT, 5, SQL_C_LONG, &max_wait, sizeof(max_wait), &col_max_wait_len);
546
+ if (ret != SQL_SUCCESS) {
547
+ netdata_MSSQL_error(SQL_HANDLE_STMT, mi->conn.dbWaitsSTMT, NETDATA_MSSQL_ODBC_PREPARE, mi->instanceID);
548
+ goto endwait;
549
+ }
550
+
551
+ ret =
552
+ SQLBindCol(mi->conn.dbWaitsSTMT, 6, SQL_C_LONG, &waiting_tasks, sizeof(waiting_tasks), &col_waiting_tasks_len);
553
+ if (ret != SQL_SUCCESS) {
554
+ netdata_MSSQL_error(SQL_HANDLE_STMT, mi->conn.dbWaitsSTMT, NETDATA_MSSQL_ODBC_PREPARE, mi->instanceID);
555
+ goto endwait;
556
+ }
557
+
558
+ ret = SQLBindCol(mi->conn.dbWaitsSTMT, 7, SQL_C_CHAR, wait_category, sizeof(wait_category), &col_wait_category_len);
559
+ if (ret != SQL_SUCCESS) {
560
+ netdata_MSSQL_error(SQL_HANDLE_STMT, mi->conn.dbWaitsSTMT, NETDATA_MSSQL_ODBC_PREPARE, mi->instanceID);
561
+ goto endwait;
562
+ }
563
+
564
+ do {
565
+ ret = SQLFetch(mi->conn.dbWaitsSTMT);
566
+ switch (ret) {
567
+ case SQL_SUCCESS:
568
+ case SQL_SUCCESS_WITH_INFO:
569
+ break;
570
+ case SQL_NO_DATA:
571
+ default:
572
+ success = 1;
573
+ goto endwait;
574
+ }
575
+
576
+ struct mssql_db_waits *mdw = dictionary_set(mi->waits, wait_type, NULL, sizeof(*mdw));
577
+ if (!mdw)
578
+ continue;
579
+
580
+ mdw->MSSQLDatabaseTotalWait.current.Data = (ULONGLONG)total_wait;
581
+ // Variable mdw->MSSQLDatabaseResourceWaitMSec.current.Data stores a mathematical operation
582
+ // that can be negative sometimes. This is the reason we have this if
583
+ if (resource_wait > mdw->MSSQLDatabaseResourceWaitMSec.current.Data)
584
+ mdw->MSSQLDatabaseResourceWaitMSec.current.Data = (ULONGLONG)resource_wait;
585
+ mdw->MSSQLDatabaseSignalWaitMSec.current.Data = (ULONGLONG)signal_wait;
586
+ mdw->MSSQLDatabaseMaxWaitTimeMSec.current.Data = (ULONGLONG)max_wait;
587
+ mdw->MSSQLDatabaseWaitingTasks.current.Data = (ULONGLONG)waiting_tasks;
588
+
589
+ if (!mdw->wait_category)
590
+ mdw->wait_category = strdupz(wait_category);
591
+ } while (true);
592
+
593
+endwait:
594
+ netdata_MSSQL_release_results(mi->conn.dbWaitsSTMT);
595
+
596
+ return success;
597
+}
598
+
599
int dict_mssql_databases_run_queries(const DICTIONARY_ITEM *item __maybe_unused, void *value, void *data __maybe_unused)
600
{
601
struct mssql_db_instance *mdi = value;
@@ -500,8 +621,6 @@ enddrunquery:
621
return 1;
622
}
623
503
-#define NETDATA_QUERY_CHECK_PERM \
504
- "SELECT CASE WHEN IS_SRVROLEMEMBER('sysadmin') = 1 OR HAS_PERMS_BY_NAME(null, null, 'VIEW SERVER STATE') = 1 THEN 1 ELSE 0 END AS has_permission;"
624
long metdata_mssql_check_permission(struct mssql_instance *mi)
625
{
626
static int next_try = NETDATA_MSSQL_NEXT_TRY - 1;
@@ -657,6 +776,10 @@ static bool netdata_MSSQL_initialize_conection(struct netdata_mssql_conn *nmc)
776
ret = SQLAllocHandle(SQL_HANDLE_STMT, nmc->netdataSQLHDBc, &nmc->dbLocksSTMT);
777
if (ret != SQL_SUCCESS && ret != SQL_SUCCESS_WITH_INFO)
778
retConn = FALSE;
779
+
780
+ ret = SQLAllocHandle(SQL_HANDLE_STMT, nmc->netdataSQLHDBc, &nmc->dbWaitsSTMT);
781
+ if (ret != SQL_SUCCESS && ret != SQL_SUCCESS_WITH_INFO)
782
+ retConn = FALSE;
783
}
784
785
return retConn;
@@ -700,6 +823,9 @@ static void initialize_mssql_objects(struct mssql_instance *mi, const char *inst
823
strncpyz(&name[length], "Locks", sizeof(name) - length);
824
mi->objectName[NETDATA_MSSQL_LOCKS] = strdupz(name);
825
826
+ strncpyz(&name[length], "Wait Statistics", sizeof(name) - length);
827
+ mi->objectName[NETDATA_MSSQL_WAITS] = strdupz(name);
828
+
829
strncpyz(&name[length], "Access Methods", sizeof(name) - length);
830
mi->objectName[NETDATA_MSSQL_ACCESS_METHODS] = strdupz(name);
831
@@ -746,6 +872,20 @@ void dict_mssql_insert_locks_cb(const DICTIONARY_ITEM *item __maybe_unused, void
872
// https://learn.microsoft.com/en-us/sql/relational-databases/performance-monitor/sql-server-locks-object
873
struct mssql_lock_instance *ptr = value;
874
ptr->resourceID = strdupz(resource);
875
+ ptr->deadLocks.key = "Number of Deadlocks/sec";
876
+ ptr->lockWait.key = "Lock Waits/sec";
877
+}
878
+
879
+void dict_mssql_insert_wait_cb(const DICTIONARY_ITEM *item __maybe_unused, void *value, void *data __maybe_unused)
880
+{
881
+ const char *type = dictionary_acquired_item_name((DICTIONARY_ITEM *)item);
882
+
883
+ struct mssql_db_waits *mdw = value;
884
+
885
+ mdw->wait_type = strdupz(type);
886
+ mdw->wait_category = NULL;
887
+ mdw->rd_total_wait = mdw->rd_max_wait_time_msec = mdw->rd_resource_wait_msec = mdw->rd_signal_wait_msec =
888
+ mdw->rd_waiting_tasks = NULL;
889
}
890
891
void dict_mssql_insert_databases_cb(const DICTIONARY_ITEM *item __maybe_unused, void *value, void *data __maybe_unused)
@@ -809,6 +949,7 @@ static void netdata_read_config_options(struct netdata_mssql_conn *dbconn)
949
dbconn->databaseListSTMT = NULL;
950
dbconn->dataFileSizeSTMT = NULL;
951
dbconn->dbTransactionSTMT = NULL;
952
+ dbconn->dbWaitsSTMT = NULL;
953
dbconn->dbLocksSTMT = NULL;
954
955
dbconn->is_connected = FALSE;
@@ -841,6 +982,30 @@ static void netdata_read_config_options(struct netdata_mssql_conn *dbconn)
982
total_instances++;
983
}
984
985
+void mssql_fill_initial_instances(struct mssql_instance *mi)
986
+{
987
+ // https://learn.microsoft.com/en-us/sql/relational-databases/performance-monitor/sql-server-locks-object?view=sql-server-ver17
988
+ char *keys[] = {
989
+ "AllocUnit",
990
+ "Application",
991
+ "Database",
992
+ "Extent",
993
+ "File",
994
+ "HoBT",
995
+ "Key",
996
+ "Metadata",
997
+ "OIB",
998
+ "Object",
999
+ "Page",
1000
+ "RID",
1001
+ "RowGroup",
1002
+ "Xact",
1003
+ NULL};
1004
+ for (int i = 0; keys[i]; i++) {
1005
+ (void)dictionary_set(mi->locks_instances, keys[i], NULL, sizeof(struct mssql_lock_instance));
1006
+ }
1007
+}
1008
+
1009
void dict_mssql_insert_cb(const DICTIONARY_ITEM *item __maybe_unused, void *value, void *data __maybe_unused)
1010
{
1011
struct mssql_instance *mi = value;
@@ -851,6 +1016,7 @@ void dict_mssql_insert_cb(const DICTIONARY_ITEM *item __maybe_unused, void *valu
1016
mi->locks_instances = dictionary_create_advanced(
1017
DICT_OPTION_DONT_OVERWRITE_VALUE | DICT_OPTION_FIXED_SIZE, NULL, sizeof(struct mssql_lock_instance));
1018
dictionary_register_insert_callback(mi->locks_instances, dict_mssql_insert_locks_cb, NULL);
1019
+ mssql_fill_initial_instances(mi);
1020
}
1021
1022
if (!mi->databases) {
@@ -859,6 +1025,12 @@ void dict_mssql_insert_cb(const DICTIONARY_ITEM *item __maybe_unused, void *valu
1025
dictionary_register_insert_callback(mi->databases, dict_mssql_insert_databases_cb, NULL);
1026
}
1027
1028
+ if (!mi->waits) {
1029
+ mi->waits = dictionary_create_advanced(
1030
+ DICT_OPTION_DONT_OVERWRITE_VALUE | DICT_OPTION_FIXED_SIZE, NULL, sizeof(struct mssql_db_waits));
1031
+ dictionary_register_insert_callback(mi->waits, dict_mssql_insert_wait_cb, NULL);
1032
+ }
1033
+
1034
initialize_mssql_objects(mi, instance);
1035
initialize_mssql_keys(mi);
1036
netdata_read_config_options(&mi->conn);
@@ -870,7 +1042,7 @@ void dict_mssql_insert_cb(const DICTIONARY_ITEM *item __maybe_unused, void *valu
1042
}
1043
}
1044
873
-static int mssql_fill_dictionary()
1045
+static int mssql_fill_dictionary(int update_every)
1046
{
1047
HKEY hKey;
1048
LSTATUS ret = RegOpenKeyExA(
@@ -908,6 +1080,7 @@ static int mssql_fill_dictionary()
1080
}
1081
1082
struct mssql_instance *p = dictionary_set(mssql_instances, avalue, NULL, sizeof(*p));
1083
+ p->update_every = update_every;
1084
}
1085
1086
endMSSQLFillDict:
@@ -928,11 +1101,11 @@ int netdata_mssql_reset_value(const DICTIONARY_ITEM *item __maybe_unused, void *
1101
int dict_mssql_query_cb(const DICTIONARY_ITEM *item __maybe_unused, void *value, void *data __maybe_unused)
1102
{
1103
struct mssql_instance *mi = value;
931
- static long have_perm = 1;
1104
+ static long collecting = 1;
1105
933
- if (mi->conn.is_connected && have_perm) {
934
- have_perm = metdata_mssql_check_permission(mi);
935
- if (!have_perm) {
1106
+ if (mi->conn.is_connected && collecting) {
1107
+ collecting = metdata_mssql_check_permission(mi);
1108
+ if (!collecting) {
1109
nd_log(
1110
NDLS_COLLECTORS,
1111
NDLP_ERR,
@@ -943,6 +1116,8 @@ int dict_mssql_query_cb(const DICTIONARY_ITEM *item __maybe_unused, void *value,
1116
metdata_mssql_fill_dictionary_from_db(mi);
1117
dictionary_sorted_walkthrough_read(mi->databases, dict_mssql_databases_run_queries, NULL);
1118
}
1119
+
1120
+ collecting = dict_mssql_fill_waits(mi);
1121
} else {
1122
dictionary_sorted_walkthrough_read(mi->databases, netdata_mssql_reset_value, NULL);
1123
}
@@ -976,14 +1151,13 @@ static int initialize(int update_every)
1151
1152
dictionary_register_insert_callback(mssql_instances, dict_mssql_insert_cb, &create_thread);
1153
979
- if (mssql_fill_dictionary()) {
1154
+ if (mssql_fill_dictionary(update_every)) {
1155
return -1;
1156
}
1157
1158
if (create_thread)
984
- mssql_query_thread = nd_thread_create("mssql_queries",
985
- NETDATA_THREAD_OPTION_DEFAULT,
986
- netdata_mssql_queries, &update_every);
1159
+ mssql_query_thread =
1160
+ nd_thread_create("mssql_queries", NETDATA_THREAD_OPTION_DEFAULT, netdata_mssql_queries, &update_every);
1161
1162
return 0;
1163
}
@@ -1429,73 +1603,301 @@ static void do_mssql_errors(PERF_DATA_BLOCK *pDataBlock, struct mssql_instance *
1603
}
1604
}
1605
1432
-void dict_mssql_locks_wait_charts(struct mssql_instance *mi, int update_every)
1606
+void dict_mssql_locks_wait_charts(struct mssql_instance *mi, struct mssql_lock_instance *mli, const char *resource)
1607
{
1434
- if (!mi->st_lockWait) {
1608
+ if (!mli->st_lockWait) {
1609
char id[RRD_ID_LENGTH_MAX + 1];
1610
1437
- snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_resource_lock_wait", mi->instanceID);
1611
+ snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_resource_%s_lock_wait", mi->instanceID, resource);
1612
netdata_fix_chart_name(id);
1439
- mi->st_lockWait = rrdset_create_localhost(
1613
+ mli->st_lockWait = rrdset_create_localhost(
1614
"mssql",
1615
id,
1616
NULL,
1617
"locks",
1444
- "mssql.instance_resource_lock_wait",
1445
- "Lock requests that required the caller to wait per resource.",
1618
+ "mssql.instance_resource_lock_waits",
1619
+ "Lock requests that required the caller to wait per resource",
1620
"locks/s",
1621
PLUGIN_WINDOWS_NAME,
1622
"PerflibMSSQL",
1623
PRIO_MSSQL_LOCKS_WAIT,
1450
- update_every,
1624
+ mi->update_every,
1625
RRDSET_TYPE_LINE);
1626
1453
- rrdlabels_add(mi->st_lockWait->rrdlabels, "mssql_instance", mi->instanceID, RRDLABEL_SRC_AUTO);
1627
+ rrdlabels_add(mli->st_lockWait->rrdlabels, "mssql_instance", mi->instanceID, RRDLABEL_SRC_AUTO);
1628
+ rrdlabels_add(mli->st_lockWait->rrdlabels, "resource", resource, RRDLABEL_SRC_AUTO);
1629
+ mli->rd_lockWait = rrddim_add(mli->st_lockWait, "locks", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
1630
}
1631
+
1632
+ rrddim_set_by_pointer(mli->st_lockWait, mli->rd_lockWait, (collected_number)mli->lockWait.current.Data);
1633
+ rrdset_done(mli->st_lockWait);
1634
}
1635
1457
-void dict_mssql_dead_locks_charts(struct mssql_instance *mi, int update_every)
1636
+void dict_mssql_dead_locks_charts(struct mssql_instance *mi, struct mssql_lock_instance *mli, const char *resource)
1637
{
1459
- if (!mi->st_deadLocks) {
1638
+ if (!mli->st_deadLocks) {
1639
char id[RRD_ID_LENGTH_MAX + 1];
1640
1462
- snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_resource_deadlocks", mi->instanceID);
1641
+ snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_resource_%s_deadlocks", mi->instanceID, resource);
1642
netdata_fix_chart_name(id);
1464
- mi->st_deadLocks = rrdset_create_localhost(
1643
+ mli->st_deadLocks = rrdset_create_localhost(
1644
"mssql",
1645
id,
1646
NULL,
1647
"locks",
1648
"mssql.instance_resource_deadlocks",
1470
- "Active lock requests that resulted in deadlock per resource.",
1649
+ "Active lock requests that resulted in deadlock per resource",
1650
"deadlocks/s",
1651
PLUGIN_WINDOWS_NAME,
1652
"PerflibMSSQL",
1653
PRIO_MSSQL_LOCKS_DEADLOCK_PER_RESOURCE,
1475
- update_every,
1654
+ mi->update_every,
1655
RRDSET_TYPE_LINE);
1656
1478
- rrdlabels_add(mi->st_deadLocks->rrdlabels, "mssql_instance", mi->instanceID, RRDLABEL_SRC_AUTO);
1657
+ rrdlabels_add(mli->st_deadLocks->rrdlabels, "mssql_instance", mi->instanceID, RRDLABEL_SRC_AUTO);
1658
+ rrdlabels_add(mli->st_deadLocks->rrdlabels, "resource", resource, RRDLABEL_SRC_AUTO);
1659
+ mli->rd_deadLocks = rrddim_add(mli->st_deadLocks, "deadlocks", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
1660
}
1661
+
1662
+ rrddim_set_by_pointer(mli->st_deadLocks, mli->rd_deadLocks, (collected_number)mli->deadLocks.current.Data);
1663
+ rrdset_done(mli->st_deadLocks);
1664
+}
1665
+
1666
+int dict_mssql_locks_charts_cb(const DICTIONARY_ITEM *item __maybe_unused, void *value, void *data __maybe_unused)
1667
+{
1668
+ const char *dimension = dictionary_acquired_item_name((DICTIONARY_ITEM *)item);
1669
+ struct mssql_lock_instance *mli = value;
1670
+ struct mssql_instance *mi = data;
1671
+
1672
+ dict_mssql_locks_wait_charts(mi, mli, dimension);
1673
+ dict_mssql_dead_locks_charts(mi, mli, dimension);
1674
+
1675
+ return 1;
1676
}
1677
1482
-static void do_mssql_locks(PERF_DATA_BLOCK *pDataBlock, struct mssql_instance *mi, int update_every)
1678
+static void do_mssql_locks(PERF_DATA_BLOCK *pDataBlock, struct mssql_instance *mi, int update_every __maybe_unused)
1679
{
1680
PERF_OBJECT_TYPE *pObjectType = perflibFindObjectTypeByName(pDataBlock, mi->objectName[NETDATA_MSSQL_LOCKS]);
1485
- if (!pObjectType)
1486
- return;
1681
+ if (pObjectType) {
1682
+ if (pObjectType->NumInstances) {
1683
+ PERF_INSTANCE_DEFINITION *pi = NULL;
1684
+ for (LONG i = 0; i < pObjectType->NumInstances; i++) {
1685
+ pi = perflibForEachInstance(pDataBlock, pObjectType, pi);
1686
+ if (!pi)
1687
+ break;
1688
+
1689
+ if (!getInstanceName(pDataBlock, pObjectType, pi, windows_shared_buffer, sizeof(windows_shared_buffer)))
1690
+ strncpyz(windows_shared_buffer, "[unknown]", sizeof(windows_shared_buffer) - 1);
1691
+
1692
+ if (!strcasecmp(windows_shared_buffer, "_Total"))
1693
+ continue;
1694
+
1695
+ struct mssql_lock_instance *mli =
1696
+ dictionary_set(mi->locks_instances, windows_shared_buffer, NULL, sizeof(*mli));
1697
+ if (!mli)
1698
+ continue;
1699
+
1700
+ perflibGetInstanceCounter(pDataBlock, pObjectType, pi, &mli->deadLocks);
1701
+ perflibGetInstanceCounter(pDataBlock, pObjectType, pi, &mli->lockWait);
1702
+ }
1703
+ }
1704
+ }
1705
1488
- if (!pObjectType->NumInstances)
1489
- return;
1706
+ dictionary_sorted_walkthrough_read(mi->locks_instances, dict_mssql_locks_charts_cb, mi);
1707
+}
1708
+
1709
+void mssql_total_wait_charts(struct mssql_instance *mi, struct mssql_db_waits *mdw, const char *type)
1710
+{
1711
+ if (!mdw->st_total_wait) {
1712
+ char id[RRD_ID_LENGTH_MAX + 1];
1713
+
1714
+ snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_%s_total_wait", mi->instanceID, type);
1715
+ netdata_fix_chart_name(id);
1716
+ mdw->st_total_wait = rrdset_create_localhost(
1717
+ "mssql",
1718
+ id,
1719
+ NULL,
1720
+ "locks",
1721
+ "mssql.instance_total_wait_time",
1722
+ "Wait time for each wait type and category",
1723
+ "ms",
1724
+ PLUGIN_WINDOWS_NAME,
1725
+ "PerflibMSSQL",
1726
+ PRIO_MSSQL_WAITS_TOTAL,
1727
+ mi->update_every,
1728
+ RRDSET_TYPE_LINE);
1729
+
1730
+ rrdlabels_add(mdw->st_total_wait->rrdlabels, "mssql_instance", mi->instanceID, RRDLABEL_SRC_AUTO);
1731
+ rrdlabels_add(mdw->st_total_wait->rrdlabels, "wait_type", mdw->wait_type, RRDLABEL_SRC_AUTO);
1732
+ rrdlabels_add(mdw->st_total_wait->rrdlabels, "wait_category", mdw->wait_category, RRDLABEL_SRC_AUTO);
1733
+ mdw->rd_total_wait = rrddim_add(mdw->st_total_wait, "duration", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
1734
+ }
1735
+
1736
+ rrddim_set_by_pointer(
1737
+ mdw->st_total_wait, mdw->rd_total_wait, (collected_number)mdw->MSSQLDatabaseTotalWait.current.Data);
1738
+
1739
+ rrdset_done(mdw->st_total_wait);
1740
+}
1741
+
1742
+void mssql_resource_wait_charts(struct mssql_instance *mi, struct mssql_db_waits *mdw, const char *type)
1743
+{
1744
+ if (!mdw->st_resource_wait_msec) {
1745
+ char id[RRD_ID_LENGTH_MAX + 1];
1746
+
1747
+ snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_%s_resource_wait", mi->instanceID, type);
1748
+ netdata_fix_chart_name(id);
1749
+ mdw->st_resource_wait_msec = rrdset_create_localhost(
1750
+ "mssql",
1751
+ id,
1752
+ NULL,
1753
+ "locks",
1754
+ "mssql.instance_resource_wait_time",
1755
+ "Wait time for threads waiting on specific resource types for each wait type and category",
1756
+ "ms",
1757
+ PLUGIN_WINDOWS_NAME,
1758
+ "PerflibMSSQL",
1759
+ PRIO_MSSQL_RESOURCE_WAIT,
1760
+ mi->update_every,
1761
+ RRDSET_TYPE_LINE);
1762
+
1763
+ rrdlabels_add(mdw->st_resource_wait_msec->rrdlabels, "mssql_instance", mi->instanceID, RRDLABEL_SRC_AUTO);
1764
+ rrdlabels_add(mdw->st_resource_wait_msec->rrdlabels, "wait_type", mdw->wait_type, RRDLABEL_SRC_AUTO);
1765
+ rrdlabels_add(mdw->st_resource_wait_msec->rrdlabels, "wait_category", mdw->wait_category, RRDLABEL_SRC_AUTO);
1766
+ mdw->rd_resource_wait_msec =
1767
+ rrddim_add(mdw->st_resource_wait_msec, "duration", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
1768
+ }
1769
+
1770
+ rrddim_set_by_pointer(
1771
+ mdw->st_resource_wait_msec,
1772
+ mdw->rd_resource_wait_msec,
1773
+ (collected_number)mdw->MSSQLDatabaseResourceWaitMSec.current.Data);
1774
+
1775
+ rrdset_done(mdw->st_resource_wait_msec);
1776
+}
1777
+
1778
+void mssql_signal_wait_charts(struct mssql_instance *mi, struct mssql_db_waits *mdw, const char *type)
1779
+{
1780
+ if (!mdw->st_signal_wait_msec) {
1781
+ char id[RRD_ID_LENGTH_MAX + 1];
1782
+
1783
+ snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_%s_signal_wait", mi->instanceID, type);
1784
+ netdata_fix_chart_name(id);
1785
+ mdw->st_signal_wait_msec = rrdset_create_localhost(
1786
+ "mssql",
1787
+ id,
1788
+ NULL,
1789
+ "locks",
1790
+ "mssql.instance_signal_wait_time",
1791
+ "Delay between thread wakeup signal and actual execution start for each wait type and category",
1792
+ "ms",
1793
+ PLUGIN_WINDOWS_NAME,
1794
+ "PerflibMSSQL",
1795
+ PRIO_MSSQL_SIGNAL_WAIT,
1796
+ mi->update_every,
1797
+ RRDSET_TYPE_LINE);
1798
+
1799
+ rrdlabels_add(mdw->st_signal_wait_msec->rrdlabels, "mssql_instance", mi->instanceID, RRDLABEL_SRC_AUTO);
1800
+ rrdlabels_add(mdw->st_signal_wait_msec->rrdlabels, "wait_type", mdw->wait_type, RRDLABEL_SRC_AUTO);
1801
+ rrdlabels_add(mdw->st_signal_wait_msec->rrdlabels, "wait_category", mdw->wait_category, RRDLABEL_SRC_AUTO);
1802
+ mdw->rd_signal_wait_msec =
1803
+ rrddim_add(mdw->st_signal_wait_msec, "duration", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
1804
+ }
1805
+
1806
+ rrddim_set_by_pointer(
1807
+ mdw->st_signal_wait_msec,
1808
+ mdw->rd_signal_wait_msec,
1809
+ (collected_number)mdw->MSSQLDatabaseSignalWaitMSec.current.Data);
1810
+
1811
+ rrdset_done(mdw->st_signal_wait_msec);
1812
+}
1813
+
1814
+void mssql_max_wait_charts(struct mssql_instance *mi, struct mssql_db_waits *mdw, const char *type)
1815
+{
1816
+ if (!mdw->st_max_wait_time_msec) {
1817
+ char id[RRD_ID_LENGTH_MAX + 1];
1818
+
1819
+ snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_%s_max_wait", mi->instanceID, type);
1820
+ netdata_fix_chart_name(id);
1821
+ mdw->st_max_wait_time_msec = rrdset_create_localhost(
1822
+ "mssql",
1823
+ id,
1824
+ NULL,
1825
+ "locks",
1826
+ "mssql.instance_max_wait_time",
1827
+ "Maximum wait time for each wait type and category",
1828
+ "ms",
1829
+ PLUGIN_WINDOWS_NAME,
1830
+ "PerflibMSSQL",
1831
+ PRIO_MSSQL_MAX_WAIT_TIME,
1832
+ mi->update_every,
1833
+ RRDSET_TYPE_LINE);
1834
+
1835
+ rrdlabels_add(mdw->st_max_wait_time_msec->rrdlabels, "mssql_instance", mi->instanceID, RRDLABEL_SRC_AUTO);
1836
+ rrdlabels_add(mdw->st_max_wait_time_msec->rrdlabels, "wait_type", mdw->wait_type, RRDLABEL_SRC_AUTO);
1837
+ rrdlabels_add(mdw->st_max_wait_time_msec->rrdlabels, "wait_category", mdw->wait_category, RRDLABEL_SRC_AUTO);
1838
+ mdw->rd_max_wait_time_msec =
1839
+ rrddim_add(mdw->st_max_wait_time_msec, "duration", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
1840
+ }
1841
+
1842
+ rrddim_set_by_pointer(
1843
+ mdw->st_max_wait_time_msec,
1844
+ mdw->rd_max_wait_time_msec,
1845
+ (collected_number)mdw->MSSQLDatabaseMaxWaitTimeMSec.current.Data);
1846
+
1847
+ rrdset_done(mdw->st_max_wait_time_msec);
1848
+}
1849
+
1850
+void mssql_waiting_count_charts(struct mssql_instance *mi, struct mssql_db_waits *mdw, const char *type)
1851
+{
1852
+ if (!mdw->st_waiting_tasks) {
1853
+ char id[RRD_ID_LENGTH_MAX + 1];
1854
+
1855
+ snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_%s_waiting_count", mi->instanceID, type);
1856
+ netdata_fix_chart_name(id);
1857
+ mdw->st_waiting_tasks = rrdset_create_localhost(
1858
+ "mssql",
1859
+ id,
1860
+ NULL,
1861
+ "locks",
1862
+ "mssql.instance_waits",
1863
+ "Number of waits for each wait type and category",
1864
+ "waits/s",
1865
+ PLUGIN_WINDOWS_NAME,
1866
+ "PerflibMSSQL",
1867
+ PRIO_MSSQL_WAITING_COUNT,
1868
+ mi->update_every,
1869
+ RRDSET_TYPE_LINE);
1870
+
1871
+ rrdlabels_add(mdw->st_waiting_tasks->rrdlabels, "mssql_instance", mi->instanceID, RRDLABEL_SRC_AUTO);
1872
+ rrdlabels_add(mdw->st_waiting_tasks->rrdlabels, "wait_type", mdw->wait_type, RRDLABEL_SRC_AUTO);
1873
+ rrdlabels_add(mdw->st_waiting_tasks->rrdlabels, "wait_category", mdw->wait_category, RRDLABEL_SRC_AUTO);
1874
+ mdw->rd_waiting_tasks = rrddim_add(mdw->st_waiting_tasks, "waits", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
1875
+ }
1876
+
1877
+ rrddim_set_by_pointer(
1878
+ mdw->st_waiting_tasks, mdw->rd_waiting_tasks, (collected_number)mdw->MSSQLDatabaseWaitingTasks.current.Data);
1879
+
1880
+ rrdset_done(mdw->st_waiting_tasks);
1881
+}
1882
+
1883
+int dict_mssql_waits_charts_cb(const DICTIONARY_ITEM *item __maybe_unused, void *value, void *data __maybe_unused)
1884
+{
1885
+ const char *dimension = dictionary_acquired_item_name((DICTIONARY_ITEM *)item);
1886
+ struct mssql_db_waits *mdw = value;
1887
+ struct mssql_instance *mi = data;
1888
1491
- dict_mssql_locks_wait_charts(mi, update_every);
1492
- dict_mssql_dead_locks_charts(mi, update_every);
1889
+ mssql_total_wait_charts(mi, mdw, dimension);
1890
+ mssql_resource_wait_charts(mi, mdw, dimension);
1891
+ mssql_signal_wait_charts(mi, mdw, dimension);
1892
+ mssql_max_wait_charts(mi, mdw, dimension);
1893
+ mssql_waiting_count_charts(mi, mdw, dimension);
1894
1494
- if (mi->st_lockWait)
1495
- rrdset_done(mi->st_lockWait);
1895
+ return 1;
1896
+}
1897
1497
- if (mi->st_deadLocks)
1498
- rrdset_done(mi->st_deadLocks);
1898
+static void do_mssql_waits(PERF_DATA_BLOCK *pDataBlock, struct mssql_instance *mi, int update_every)
1899
+{
1900
+ dictionary_sorted_walkthrough_read(mi->waits, dict_mssql_waits_charts_cb, mi);
1901
}
1902
1903
static void mssql_database_backup_restore_chart(struct mssql_db_instance *mdi, const char *db, int update_every)
@@ -2123,6 +2525,7 @@ int dict_mssql_charts_cb(const DICTIONARY_ITEM *item __maybe_unused, void *value
2525
do_mssql_errors,
2526
do_mssql_databases,
2527
do_mssql_locks,
2528
+ do_mssql_waits,
2529
do_mssql_memory_mgr,
2530
do_mssql_buffer_management,
2531
do_mssql_sql_statistics,
src/collectors/windows.plugin/windows_plugin.h
+6
@@ -112,6 +112,12 @@ enum PERFLIB_PRIO {
112
PRIO_MSSQL_LOCKS_WAIT,
113
PRIO_MSSQL_LOCKS_DEADLOCK_PER_RESOURCE,
114
115
+ PRIO_MSSQL_WAITS_TOTAL,
116
+ PRIO_MSSQL_RESOURCE_WAIT,
117
+ PRIO_MSSQL_SIGNAL_WAIT,
118
+ PRIO_MSSQL_MAX_WAIT_TIME,
119
+ PRIO_MSSQL_WAITING_COUNT,
120
+
121
PRIO_MSSQL_SQL_ERRORS,
122
123
PRIO_NETFRAMEWORK_CLR_EXCEPTION_THROWN,