Update MSSQL collection (windows.plugin) (#21426)
thiagoftsm committed
Dec 11, 2025 at 12:27 UTC
0ecefab68ec0d00314f5c097c16e7b87514dcfb9
4 files changed
+101
-33
src/collectors/windows.plugin/MonitorSQL.c
+87
-1
@@ -1018,6 +1018,42 @@ enduserconn:
1018
netdata_MSSQL_release_results(mi->conn->dbSQLConnections);
1019
}
1020
1021
+static void netdata_mssql_fill_blocked_processes_query(struct mssql_instance *mi)
1022
+{
1023
+ if (unlikely(!mi || !mi->conn || mi->conn->dbSQLBlockedProcesses == SQL_NULL_HSTMT))
1024
+ return;
1025
+
1026
+ long blocked_processes = 0;
1027
+ SQLLEN col_len = 0;
1028
+ mi->MSSQLBlockedProcesses.current.Data = 0;
1029
+
1030
+ SQLRETURN ret = SQLExecDirect(mi->conn->dbSQLBlockedProcesses, (SQLCHAR *)NETDATA_QUERY_BLOCKED_PROCESSES, SQL_NTS);
1031
+ if (likely(netdata_mssql_check_result(ret))) {
1032
+ netdata_MSSQL_error(SQL_HANDLE_STMT, mi->conn->dbSQLBlockedProcesses, NETDATA_MSSQL_ODBC_QUERY, mi->instanceID);
1033
+ goto end_blocked_processes;
1034
+ }
1035
+
1036
+ ret = SQLBindCol(
1037
+ mi->conn->dbSQLBlockedProcesses,
1038
+ 1,
1039
+ SQL_C_LONG,
1040
+ &blocked_processes,
1041
+ sizeof(blocked_processes),
1042
+ &col_len);
1043
+ if (likely(netdata_mssql_check_result(ret))) {
1044
+ netdata_MSSQL_error(SQL_HANDLE_STMT, mi->conn->dbSQLBlockedProcesses, NETDATA_MSSQL_ODBC_PREPARE, mi->instanceID);
1045
+ goto end_blocked_processes;
1046
+ }
1047
+
1048
+ ret = SQLFetch(mi->conn->dbSQLBlockedProcesses);
1049
+ if (likely(netdata_mssql_check_result(ret)))
1050
+ goto end_blocked_processes;
1051
+
1052
+ mi->MSSQLBlockedProcesses.current.Data = blocked_processes;
1053
+end_blocked_processes:
1054
+ netdata_MSSQL_release_results(mi->conn->dbSQLBlockedProcesses);
1055
+}
1056
+
1057
void netdata_mssql_fill_dictionary_from_db(struct mssql_instance *mi)
1058
{
1059
char dbname[SQLSERVER_MAX_NAME_LENGTH + 1];
@@ -1188,6 +1224,12 @@ static bool netdata_MSSQL_initialize_connection(struct netdata_mssql_conn *nmc)
1224
goto endMSSQLInitializationConnection;
1225
}
1226
1227
+ ret = SQLAllocHandle(SQL_HANDLE_STMT, nmc->netdataSQLHDBc, &nmc->dbSQLBlockedProcesses);
1228
+ if (likely(netdata_mssql_check_result(ret))) {
1229
+ retConn = FALSE;
1230
+ goto endMSSQLInitializationConnection;
1231
+ }
1232
+
1233
ret = SQLAllocHandle(SQL_HANDLE_STMT, nmc->netdataSQLHDBc, &nmc->dbReplicationPublisher);
1234
if (likely(netdata_mssql_check_result(ret))) {
1235
retConn = FALSE;
@@ -1422,6 +1464,8 @@ static void netdata_read_config_options()
1464
dbconn->collect_data_size = inicfg_get_boolean(&netdata_config, section_name, "collect database size", true);
1465
dbconn->collect_user_connections =
1466
inicfg_get_boolean(&netdata_config, section_name, "collect user connections", true);
1467
+ dbconn->collect_blocked_processes = inicfg_get_boolean(
1468
+ &netdata_config, section_name, "collect blocked processes", true);
1469
dbconn->is_connected = FALSE;
1470
1471
netdata_mount_mssql_connection_string(dbconn);
@@ -1581,6 +1625,8 @@ int dict_mssql_query_cb(const DICTIONARY_ITEM *item __maybe_unused, void *value,
1625
netdata_mssql_fill_mssql_status(mi);
1626
netdata_mssql_fill_job_status(mi);
1627
netdata_mssql_fill_user_connection(mi);
1628
+ if (likely(mi->conn->collect_blocked_processes))
1629
+ netdata_mssql_fill_blocked_processes_query(mi);
1630
dictionary_sorted_walkthrough_read(mi->databases, dict_mssql_databases_run_queries, NULL);
1631
}
1632
@@ -1633,6 +1679,45 @@ static int initialize(int update_every)
1679
return 0;
1680
}
1681
1682
+// Charts
1683
+void netdata_mssql_blocked_processes_chart(struct mssql_instance *mi, int update_every)
1684
+{
1685
+ if (unlikely(!mi->st_process_blocked)) {
1686
+ char id[RRD_ID_LENGTH_MAX + 1];
1687
+ snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_blocked_process", mi->instanceID);
1688
+ netdata_fix_chart_name(id);
1689
+ mi->st_process_blocked = rrdset_create_localhost(
1690
+ "mssql",
1691
+ id,
1692
+ NULL,
1693
+ "processes",
1694
+ "mssql.instance_blocked_processes",
1695
+ "Blocked processes",
1696
+ "process",
1697
+ PLUGIN_WINDOWS_NAME,
1698
+ "PerflibMSSQL",
1699
+ PRIO_MSSQL_BLOCKED_PROCESSES,
1700
+ update_every,
1701
+ RRDSET_TYPE_LINE);
1702
+
1703
+ mi->rd_process_blocked = rrddim_add(mi->st_process_blocked, "blocked", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
1704
+
1705
+ rrdlabels_add(mi->st_process_blocked->rrdlabels, "mssql_instance", mi->instanceID, RRDLABEL_SRC_AUTO);
1706
+ }
1707
+
1708
+ rrddim_set_by_pointer(
1709
+ mi->st_process_blocked, mi->rd_process_blocked, (collected_number)mi->MSSQLBlockedProcesses.current.Data);
1710
+ rrdset_done(mi->st_process_blocked);
1711
+}
1712
+
1713
+static void do_mssql_blocked_processes(PERF_DATA_BLOCK *pDataBlock __maybe_unused, struct mssql_instance *mi, int update_every)
1714
+{
1715
+ if (unlikely(!mi || !mi->conn || !mi->conn->collect_blocked_processes))
1716
+ return;
1717
+
1718
+ netdata_mssql_blocked_processes_chart(mi, update_every);
1719
+}
1720
+
1721
void dict_mssql_locks_wait_charts(struct mssql_instance *mi, struct mssql_lock_instance *mli, const char *resource)
1722
{
1723
if (unlikely(!mli->st_lockWait)) {
@@ -3159,13 +3244,14 @@ int dict_mssql_charts_cb(const DICTIONARY_ITEM *item __maybe_unused, void *value
3244
do_mssql_bufferman_stats_sql,
3245
do_mssql_job_status_sql,
3246
do_mssql_user_connection,
3247
+ do_mssql_blocked_processes,
3248
3249
NULL};
3250
3251
DWORD i;
3252
PERF_DATA_BLOCK *pDataBlock;
3253
static bool collect_perflib[NETDATA_MSSQL_METRICS_END] = {
3168
- true, true, true, true, true, true, true, true, true, true, false};
3254
+ true, true, true, true, true, true, true, true, true, true, false, false};
3255
for (i = 0; i < NETDATA_MSSQL_ACCESS_METHODS; i++) {
3256
if (unlikely(!collect_perflib[i]))
3257
continue;
src/collectors/windows.plugin/metadata.yaml
+4
@@ -2285,6 +2285,10 @@ modules:
2285
description: Run queries to collect information from the server's connection.
2286
default_value: yes
2287
required: false
2288
+ - name: collect blocked processes
2289
+ description: Run queries to collect information from the server's blocked processes.
2290
+ default_value: yes
2291
+ required: false
2292
examples:
2293
folding:
2294
enabled: true
src/collectors/windows.plugin/perflib-mssql-queries.h
+7
@@ -39,6 +39,9 @@
39
40
#define NETDATA_QUERY_CONNECTIONS "SELECT COUNT(*), is_user_process FROM sys.dm_exec_sessions GROUP BY is_user_process;"
41
42
+#define NETDATA_QUERY_BLOCKED_PROCESSES \
43
+ "SELECT COUNT(DISTINCT session_id) AS blocked_sessions FROM sys.dm_exec_requests WHERE blocking_session_id <> 0;"
44
+
45
// https://learn.microsoft.com/en-us/sql/relational-databases/system-dynamic-management-views/sys-dm-os-wait-stats-transact-sql?view=sql-server-ver16
46
#define NETDATA_QUERY_CHECK_WAITS \
47
"SELECT \
@@ -673,6 +676,7 @@ struct netdata_mssql_conn {
676
SQLHSTMT dbSQLState;
677
SQLHSTMT dbSQLJobs;
678
SQLHSTMT dbSQLConnections;
679
+ SQLHSTMT dbSQLBlockedProcesses;
680
SQLHSTMT dbReplicationPublisher;
681
682
BOOL collect_transactions;
@@ -683,6 +687,7 @@ struct netdata_mssql_conn {
687
BOOL collect_buffer;
688
BOOL collect_data_size;
689
BOOL collect_user_connections;
690
+ BOOL collect_blocked_processes;
691
692
BOOL is_connected;
693
};
@@ -700,6 +705,7 @@ enum netdata_mssql_metrics {
705
NETDATA_MSSQL_BUFFER_MANAGEMENT,
706
NETDATA_MSSQL_JOBS,
707
NETDATA_USER_CONNECTIONS,
708
+ NETDATA_BLOCKED_PROCESS,
709
710
NETDATA_MSSQL_METRICS_END
711
};
@@ -998,4 +1004,5 @@ extern void do_mssql_statistics_perflib(PERF_DATA_BLOCK *pDataBlock, struct mssq
1004
extern void do_mssql_access_methods(PERF_DATA_BLOCK *pDataBlock, struct mssql_instance *mi, int update_every);
1005
extern void do_mssql_user_connections(struct mssql_instance *mi, int update_every);
1006
extern void do_mssql_sessions_connections(struct mssql_instance *mi, int update_every);
1007
+extern void netdata_mssql_blocked_processes_chart(struct mssql_instance *mi, int update_every);
1008
#endif
src/collectors/windows.plugin/perflib-mssql.c
+3
-32
@@ -415,36 +415,6 @@ void do_mssql_sessions_connections(struct mssql_instance *mi, int update_every)
415
rrdset_done(mi->st_session_connections);
416
}
417
418
-void do_mssql_blocked_processes(struct mssql_instance *mi, int update_every)
419
-{
420
- if (unlikely(!mi->st_process_blocked)) {
421
- char id[RRD_ID_LENGTH_MAX + 1];
422
- snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_blocked_process", mi->instanceID);
423
- netdata_fix_chart_name(id);
424
- mi->st_process_blocked = rrdset_create_localhost(
425
- "mssql",
426
- id,
427
- NULL,
428
- "processes",
429
- "mssql.instance_blocked_processes",
430
- "Blocked processes",
431
- "process",
432
- PLUGIN_WINDOWS_NAME,
433
- "PerflibMSSQL",
434
- PRIO_MSSQL_BLOCKED_PROCESSES,
435
- update_every,
436
- RRDSET_TYPE_LINE);
437
-
438
- mi->rd_process_blocked = rrddim_add(mi->st_process_blocked, "blocked", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
439
-
440
- rrdlabels_add(mi->st_process_blocked->rrdlabels, "mssql_instance", mi->instanceID, RRDLABEL_SRC_AUTO);
441
- }
442
-
443
- rrddim_set_by_pointer(
444
- mi->st_process_blocked, mi->rd_process_blocked, (collected_number)mi->MSSQLBlockedProcesses.current.Data);
445
- rrdset_done(mi->st_process_blocked);
446
-}
447
-
418
void do_mssql_general_stats(PERF_DATA_BLOCK *pDataBlock, struct mssql_instance *mi, int update_every)
419
{
420
PERF_OBJECT_TYPE *pObjectType =
@@ -458,7 +428,8 @@ void do_mssql_general_stats(PERF_DATA_BLOCK *pDataBlock, struct mssql_instance *
428
}
429
}
430
461
- if (likely(perflibGetObjectCounter(pDataBlock, pObjectType, &mi->MSSQLBlockedProcesses))) {
462
- do_mssql_blocked_processes(mi, update_every);
431
+ if (unlikely(!mi || !mi->conn || !mi->conn->collect_blocked_processes) &&
432
+ likely(perflibGetObjectCounter(pDataBlock, pObjectType, &mi->MSSQLBlockedProcesses))) {
433
+ netdata_mssql_blocked_processes_chart(mi, update_every);
434
}
435
}