@cryptotaxi247 / netdata-1 / commits / 0ecefab68

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 }