@cryptotaxi247 / netdata-1 / commits / 5f744dd79

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,