@cryptotaxi247 / netdata / commits / 2db34d2af

Fix MSSQL Charts (#20774)

thiagoftsm committed Aug 8, 2025 at 05:17 UTC 2db34d2af56468b009c1bf4de6989fc09298f93c
2 files changed +361 -243
src/collectors/windows.plugin/perflib-mssql-queries.h
+3
@@ -18,6 +18,9 @@
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_TRANSACTIONS_PER_INSTANCE_MASK \
22 + "SELECT counter_name, cntr_value FROM sys.dm_os_performance_counters WHERE (object_name like '%%Buffer Manager%%' or object_name like '%%SQL Statistics%%') AND counter_name IN ('Page reads/sec', 'Page writes/sec', 'Buffer cache hit ratio', 'Checkpoint pages/sec', 'Page life expectancy', 'SQL Compilations/sec', 'SQL Re-Compilations/sec');"
23 +
24 #define NETDATA_QUERY_CHECK_PERM \
25 "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;"
26
src/collectors/windows.plugin/perflib-mssql.c
+358 -243
@@ -37,6 +37,7 @@ struct netdata_mssql_conn {
37 SQLHSTMT databaseListSTMT;
38 SQLHSTMT dataFileSizeSTMT;
39 SQLHSTMT dbTransactionSTMT;
40 + SQLHSTMT dbInstanceTransactionSTMT;
41 SQLHSTMT dbWaitsSTMT;
42 SQLHSTMT dbLocksSTMT;
43
@@ -49,13 +50,13 @@ enum netdata_mssql_metrics {
50 NETDATA_MSSQL_GENERAL_STATS,
51 NETDATA_MSSQL_SQL_ERRORS,
52 NETDATA_MSSQL_MEMORY,
52 - NETDATA_MSSQL_BUFFER_MANAGEMENT,
53 NETDATA_MSSQL_SQL_STATS,
54 NETDATA_MSSQL_ACCESS_METHODS,
55
56 NETDATA_MSSQL_DATABASE,
57 NETDATA_MSSQL_LOCKS,
58 NETDATA_MSSQL_WAITS,
59 + NETDATA_MSSQL_BUFFER_MANAGEMENT,
60
61 NETDATA_MSSQL_METRICS_END
62 };
@@ -109,25 +110,6 @@ struct mssql_instance {
110 RRDSET *st_stats_safe_auto;
111 RRDDIM *rd_stats_safe_auto;
112
112 - RRDSET *st_stats_compilation;
113 - RRDDIM *rd_stats_compilation;
114 -
115 - RRDSET *st_stats_recompiles;
116 - RRDDIM *rd_stats_recompiles;
117 -
118 - RRDSET *st_buff_cache_hits;
119 - RRDDIM *rd_buff_cache_hits;
120 -
121 - RRDSET *st_buff_cache_page_life_expectancy;
122 - RRDDIM *rd_buff_cache_page_life_expectancy;
123 -
124 - RRDSET *st_buff_checkpoint_pages;
125 - RRDDIM *rd_buff_checkpoint_pages;
126 -
127 - RRDSET *st_buff_page_iops;
128 - RRDDIM *rd_buff_page_reads;
129 - RRDDIM *rd_buff_page_writes;
130 -
113 RRDSET *st_access_method_page_splits;
114 RRDDIM *rd_access_method_page_splits;
115
@@ -153,11 +135,6 @@ struct mssql_instance {
135 DICTIONARY *waits;
136
137 COUNTER_DATA MSSQLAccessMethodPageSplits;
156 - COUNTER_DATA MSSQLBufferCacheHits;
157 - COUNTER_DATA MSSQLBufferCheckpointPages;
158 - COUNTER_DATA MSSQLBufferPageLifeExpectancy;
159 - COUNTER_DATA MSSQLBufferPageReads;
160 - COUNTER_DATA MSSQLBufferPageWrites;
138 COUNTER_DATA MSSQLBlockedProcesses;
139 COUNTER_DATA MSSQLUserConnections;
140 COUNTER_DATA MSSQLConnectionMemoryBytes;
@@ -168,8 +145,6 @@ struct mssql_instance {
145 COUNTER_DATA MSSQLStatsAutoParameterization;
146 COUNTER_DATA MSSQLStatsBatchRequests;
147 COUNTER_DATA MSSQLStatSafeAutoParameterization;
171 - COUNTER_DATA MSSQLCompilations;
172 - COUNTER_DATA MSSQLRecompilations;
148 };
149
150 struct mssql_lock_instance {
@@ -191,6 +166,7 @@ struct mssql_db_instance {
166 struct mssql_instance *parent;
167
168 bool collecting_data;
169 + bool collect_instance;
170
171 RRDSET *st_db_data_file_size;
172 RRDSET *st_db_active_transactions;
@@ -203,6 +179,13 @@ struct mssql_db_instance {
179 RRDSET *st_db_deadlock;
180 RRDSET *st_lock_timeouts;
181 RRDSET *st_lock_requests;
182 + RRDSET *st_buff_page_iops;
183 + RRDSET *st_buff_cache_hits;
184 + RRDSET *st_buff_checkpoint_pages;
185 + RRDSET *st_buff_cache_page_life_expectancy;
186 +
187 + RRDSET *st_stats_compilation;
188 + RRDSET *st_stats_recompiles;
189
190 RRDDIM *rd_db_data_file_size;
191 RRDDIM *rd_db_active_transactions;
@@ -215,6 +198,14 @@ struct mssql_db_instance {
198 RRDDIM *rd_db_deadlock;
199 RRDDIM *rd_lock_timeouts;
200 RRDDIM *rd_lock_requests;
201 + RRDDIM *rd_buff_page_reads;
202 + RRDDIM *rd_buff_page_writes;
203 + RRDDIM *rd_buff_cache_hits;
204 + RRDDIM *rd_buff_checkpoint_pages;
205 + RRDDIM *rd_buff_cache_page_life_expectancy;
206 +
207 + RRDDIM *rd_stats_compilation;
208 + RRDDIM *rd_stats_recompiles;
209
210 COUNTER_DATA MSSQLDatabaseDataFileSize;
211
@@ -230,6 +221,16 @@ struct mssql_db_instance {
221 COUNTER_DATA MSSQLDatabaseLockTimeoutsSec;
222 COUNTER_DATA MSSQLDatabaseLockRequestsSec;
223
224 + // Buffer Management (https://learn.microsoft.com/en-us/sql/relational-databases/performance-monitor/sql-server-buffer-manager-object)
225 + COUNTER_DATA MSSQLBufferPageReads;
226 + COUNTER_DATA MSSQLBufferPageWrites;
227 + COUNTER_DATA MSSQLBufferCacheHits;
228 + COUNTER_DATA MSSQLBufferCheckpointPages;
229 + COUNTER_DATA MSSQLBufferPageLifeExpectancy;
230 +
231 + COUNTER_DATA MSSQLCompilations;
232 + COUNTER_DATA MSSQLRecompilations;
233 +
234 uint32_t updated;
235 };
236
@@ -333,6 +334,90 @@ static ULONGLONG netdata_MSSQL_fill_long_value(SQLHSTMT *stmt, const char *mask,
334 return (ULONGLONG)(db_size * MEGA_FACTOR);
335 }
336
337 +#define NETDATA_MSSQL_BUFFER_PAGE_READS_METRIC "Page reads/sec"
338 +#define NETDATA_MSSQL_BUFFER_PAGE_WRITES_METRIC "Page writes/sec"
339 +#define NETDATA_MSSQL_BUFFER_PAGE_CACHE_METRIC "Buffer cache hit ratio"
340 +#define NETDATA_MSSQL_BUFFER_CHECKPOINT_METRIC "Checkpoint pages/sec"
341 +#define NETDATA_MSSQL_BUFFER_PAGE_LIFE_METRIC "Page life expectancy"
342 +
343 +#define NETDATA_MSSQL_STATS_COMPILATIONS_METRIC "SQL Compilations/sec"
344 +#define NETDATA_MSSQL_STATS_RECOMPILATIONS_METRIC "SQL Re-Compilations/sec"
345 +
346 +void dict_mssql_fill_instance_transactions(struct mssql_db_instance *mdi)
347 +{
348 + char object_name[NETDATA_MAX_INSTANCE_OBJECT + 1] = {};
349 + long value = 0;
350 + SQLLEN col_object_len = 0, col_value_len = 0;
351 +
352 + SQLCHAR query[sizeof(NETDATA_QUERY_TRANSACTIONS_PER_INSTANCE_MASK) + NETDATA_MAX_INSTANCE_OBJECT + 1];
353 + snprintfz(
354 + (char *)query,
355 + sizeof(NETDATA_QUERY_TRANSACTIONS_PER_INSTANCE_MASK) + NETDATA_MAX_INSTANCE_OBJECT,
356 + NETDATA_QUERY_TRANSACTIONS_PER_INSTANCE_MASK,
357 + mdi->parent->instanceID);
358 +
359 + SQLRETURN ret = SQLExecDirect(mdi->parent->conn->dbInstanceTransactionSTMT, (SQLCHAR *)query, SQL_NTS);
360 + if (ret != SQL_SUCCESS) {
361 + mdi->collecting_data = false;
362 + netdata_MSSQL_error(
363 + SQL_HANDLE_STMT, mdi->parent->conn->dbInstanceTransactionSTMT, NETDATA_MSSQL_ODBC_QUERY, mdi->parent->instanceID);
364 + goto enditransactions;
365 + }
366 +
367 + ret = SQLBindCol(
368 + mdi->parent->conn->dbInstanceTransactionSTMT, 1, SQL_C_CHAR, object_name, sizeof(object_name), &col_object_len);
369 + if (ret != SQL_SUCCESS) {
370 + netdata_MSSQL_error(
371 + SQL_HANDLE_STMT, mdi->parent->conn->dbInstanceTransactionSTMT, NETDATA_MSSQL_ODBC_PREPARE, mdi->parent->instanceID);
372 + goto enditransactions;
373 + }
374 +
375 + ret = SQLBindCol(mdi->parent->conn->dbInstanceTransactionSTMT, 2, SQL_C_LONG, &value, sizeof(value), &col_value_len);
376 + if (ret != SQL_SUCCESS) {
377 + netdata_MSSQL_error(
378 + SQL_HANDLE_STMT, mdi->parent->conn->dbInstanceTransactionSTMT, NETDATA_MSSQL_ODBC_PREPARE, mdi->parent->instanceID);
379 + goto enditransactions;
380 + }
381 +
382 + do {
383 + ret = SQLFetch(mdi->parent->conn->dbInstanceTransactionSTMT);
384 + switch (ret) {
385 + case SQL_SUCCESS:
386 + case SQL_SUCCESS_WITH_INFO:
387 + break;
388 + case SQL_NO_DATA:
389 + default:
390 + goto enditransactions;
391 + }
392 +
393 + // We cannot use strcmp, because buffer is filled with spaces instead NULL.
394 + if (!strncmp(
395 + object_name, NETDATA_MSSQL_BUFFER_PAGE_READS_METRIC, sizeof(NETDATA_MSSQL_BUFFER_PAGE_READS_METRIC) - 1))
396 + mdi->MSSQLBufferPageReads.current.Data = (ULONGLONG)value;
397 + else if (!strncmp(
398 + object_name, NETDATA_MSSQL_BUFFER_PAGE_WRITES_METRIC, sizeof(NETDATA_MSSQL_BUFFER_PAGE_WRITES_METRIC) - 1))
399 + mdi->MSSQLBufferPageWrites.current.Data = (ULONGLONG)value;
400 + else if (!strncmp(
401 + object_name, NETDATA_MSSQL_BUFFER_PAGE_CACHE_METRIC, sizeof(NETDATA_MSSQL_BUFFER_PAGE_CACHE_METRIC) - 1))
402 + mdi->MSSQLBufferCacheHits.current.Data = (ULONGLONG)value;
403 + else if (!strncmp(
404 + object_name, NETDATA_MSSQL_BUFFER_CHECKPOINT_METRIC, sizeof(NETDATA_MSSQL_BUFFER_CHECKPOINT_METRIC) - 1))
405 + mdi->MSSQLBufferCheckpointPages.current.Data = (ULONGLONG)value;
406 + else if (!strncmp(
407 + object_name, NETDATA_MSSQL_BUFFER_PAGE_LIFE_METRIC, sizeof(NETDATA_MSSQL_BUFFER_PAGE_LIFE_METRIC) - 1))
408 + mdi->MSSQLBufferPageLifeExpectancy.current.Data = (ULONGLONG)value;
409 + else if (!strncmp(
410 + object_name, NETDATA_MSSQL_STATS_COMPILATIONS_METRIC, sizeof(NETDATA_MSSQL_STATS_COMPILATIONS_METRIC) - 1))
411 + mdi->MSSQLCompilations.current.Data = (ULONGLONG)value;
412 + else if (!strncmp(
413 + object_name, NETDATA_MSSQL_STATS_RECOMPILATIONS_METRIC, sizeof(NETDATA_MSSQL_STATS_RECOMPILATIONS_METRIC) - 1))
414 + mdi->MSSQLRecompilations.current.Data = (ULONGLONG)value;
415 + } while (true);
416 +
417 + enditransactions:
418 + netdata_MSSQL_release_results(mdi->parent->conn->dbInstanceTransactionSTMT);
419 +}
420 +
421 #define NETDATA_MSSQL_ACTIVE_TRANSACTIONS_METRIC "Active Transactions"
422 #define NETDATA_MSSQL_TRANSACTION_PER_SEC_METRIC "Transactions/sec"
423 #define NETDATA_MSSQL_WRITE_TRANSACTIONS_METRIC "Write Transactions/sec"
@@ -350,6 +435,9 @@ void dict_mssql_fill_transactions(struct mssql_db_instance *mdi, const char *dbn
435 long value = 0;
436 SQLLEN col_object_len = 0, col_value_len = 0;
437
438 + if (mdi->collect_instance)
439 + dict_mssql_fill_instance_transactions(mdi);
440 +
441 SQLCHAR query[sizeof(NETDATA_QUERY_TRANSACTIONS_MASK) + 2 * NETDATA_MAX_INSTANCE_OBJECT + 1];
442 snprintfz(
443 (char *)query,
@@ -691,6 +779,7 @@ void metdata_mssql_fill_dictionary_from_db(struct mssql_instance *mi)
779 goto enddblist;
780 }
781
782 + int i = 0;
783 do {
784 ret = SQLFetch(mi->conn->databaseListSTMT);
785 if (ret != SQL_SUCCESS && ret != SQL_SUCCESS_WITH_INFO) {
@@ -705,6 +794,10 @@ void metdata_mssql_fill_dictionary_from_db(struct mssql_instance *mi)
794 if (!mdi->parent) {
795 mdi->parent = mi;
796 }
797 +
798 + if (!i) {
799 + mdi->collect_instance = true;
800 + }
801 } while (true);
802
803 enddblist:
@@ -776,6 +869,10 @@ static bool netdata_MSSQL_initialize_conection(struct netdata_mssql_conn *nmc)
869 if (ret != SQL_SUCCESS && ret != SQL_SUCCESS_WITH_INFO)
870 retConn = FALSE;
871
872 + ret = SQLAllocHandle(SQL_HANDLE_STMT, nmc->netdataSQLHDBc, &nmc->dbInstanceTransactionSTMT);
873 + if (ret != SQL_SUCCESS && ret != SQL_SUCCESS_WITH_INFO)
874 + retConn = FALSE;
875 +
876 ret = SQLAllocHandle(SQL_HANDLE_STMT, nmc->netdataSQLHDBc, &nmc->dbLocksSTMT);
877 if (ret != SQL_SUCCESS && ret != SQL_SUCCESS_WITH_INFO)
878 retConn = FALSE;
@@ -847,15 +944,6 @@ static inline void initialize_mssql_keys(struct mssql_instance *mi)
944 mi->MSSQLStatsAutoParameterization.key = "Auto-Param Attempts/sec";
945 mi->MSSQLStatsBatchRequests.key = "Batch Requests/sec";
946 mi->MSSQLStatSafeAutoParameterization.key = "Safe Auto-Params/sec";
850 - mi->MSSQLCompilations.key = "SQL Compilations/sec";
851 - mi->MSSQLRecompilations.key = "SQL Re-Compilations/sec";
852 -
853 - // Buffer Management (https://learn.microsoft.com/en-us/sql/relational-databases/performance-monitor/sql-server-buffer-manager-object)
854 - mi->MSSQLBufferCacheHits.key = "Buffer cache hit ratio";
855 - mi->MSSQLBufferPageLifeExpectancy.key = "Page life expectancy";
856 - mi->MSSQLBufferCheckpointPages.key = "Checkpoint pages/sec";
857 - mi->MSSQLBufferPageReads.key = "Page reads/sec";
858 - mi->MSSQLBufferPageWrites.key = "Page writes/sec";
947
948 // Access Methods (https://learn.microsoft.com/en-us/sql/relational-databases/performance-monitor/sql-server-access-methods-object)
949 mi->MSSQLAccessMethodPageSplits.key = "Page Splits/sec";
@@ -1250,7 +1338,7 @@ static void do_mssql_general_stats(PERF_DATA_BLOCK *pDataBlock, struct mssql_ins
1338 }
1339 }
1340
1253 -static void do_mssql_sql_statistics(PERF_DATA_BLOCK *pDataBlock, struct mssql_instance *mi, int update_every)
1341 +static void do_mssql_statistics_perflib(PERF_DATA_BLOCK *pDataBlock, struct mssql_instance *mi, int update_every)
1342 {
1343 char id[RRD_ID_LENGTH_MAX + 1];
1344
@@ -1350,200 +1438,6 @@ static void do_mssql_sql_statistics(PERF_DATA_BLOCK *pDataBlock, struct mssql_in
1438 (collected_number)mi->MSSQLStatSafeAutoParameterization.current.Data);
1439 rrdset_done(mi->st_stats_safe_auto);
1440 }
1353 -
1354 - if (perflibGetObjectCounter(pDataBlock, pObjectType, &mi->MSSQLCompilations)) {
1355 - if (!mi->st_stats_compilation) {
1356 - snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_sqlstats_sql_compilations", mi->instanceID);
1357 - netdata_fix_chart_name(id);
1358 - mi->st_stats_compilation = rrdset_create_localhost(
1359 - "mssql",
1360 - id,
1361 - NULL,
1362 - "sql activity",
1363 - "mssql.instance_sqlstats_sql_compilations",
1364 - "SQL compilations",
1365 - "compilations/s",
1366 - PLUGIN_WINDOWS_NAME,
1367 - "PerflibMSSQL",
1368 - PRIO_MSSQL_STATS_COMPILATIONS,
1369 - update_every,
1370 - RRDSET_TYPE_LINE);
1371 -
1372 - mi->rd_stats_compilation =
1373 - rrddim_add(mi->st_stats_compilation, "compilations", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
1374 -
1375 - rrdlabels_add(mi->st_stats_compilation->rrdlabels, "mssql_instance", mi->instanceID, RRDLABEL_SRC_AUTO);
1376 - }
1377 -
1378 - rrddim_set_by_pointer(
1379 - mi->st_stats_compilation, mi->rd_stats_compilation, (collected_number)mi->MSSQLCompilations.current.Data);
1380 - rrdset_done(mi->st_stats_compilation);
1381 - }
1382 -
1383 - if (perflibGetObjectCounter(pDataBlock, pObjectType, &mi->MSSQLRecompilations)) {
1384 - if (!mi->st_stats_recompiles) {
1385 - snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_sqlstats_sql_recompilations", mi->instanceID);
1386 - netdata_fix_chart_name(id);
1387 - mi->st_stats_recompiles = rrdset_create_localhost(
1388 - "mssql",
1389 - id,
1390 - NULL,
1391 - "sql activity",
1392 - "mssql.instance_sqlstats_sql_recompilations",
1393 - "SQL re-compilations",
1394 - "recompiles/",
1395 - PLUGIN_WINDOWS_NAME,
1396 - "PerflibMSSQL",
1397 - PRIO_MSSQL_STATS_RECOMPILATIONS,
1398 - update_every,
1399 - RRDSET_TYPE_LINE);
1400 -
1401 - mi->rd_stats_recompiles =
1402 - rrddim_add(mi->st_stats_recompiles, "recompiles", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
1403 -
1404 - rrdlabels_add(mi->st_stats_recompiles->rrdlabels, "mssql_instance", mi->instanceID, RRDLABEL_SRC_AUTO);
1405 - }
1406 -
1407 - rrddim_set_by_pointer(
1408 - mi->st_stats_recompiles, mi->rd_stats_recompiles, (collected_number)mi->MSSQLRecompilations.current.Data);
1409 - rrdset_done(mi->st_stats_recompiles);
1410 - }
1411 -}
1412 -
1413 -static void do_mssql_buffer_management(PERF_DATA_BLOCK *pDataBlock, struct mssql_instance *mi, int update_every)
1414 -{
1415 - char id[RRD_ID_LENGTH_MAX + 1];
1416 -
1417 - PERF_OBJECT_TYPE *pObjectType =
1418 - perflibFindObjectTypeByName(pDataBlock, mi->objectName[NETDATA_MSSQL_BUFFER_MANAGEMENT]);
1419 - if (!pObjectType)
1420 - return;
1421 -
1422 - if (perflibGetObjectCounter(pDataBlock, pObjectType, &mi->MSSQLBufferCacheHits)) {
1423 - if (!mi->st_buff_cache_hits) {
1424 - snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_cache_hit_ratio", mi->instanceID);
1425 - netdata_fix_chart_name(id);
1426 - mi->st_buff_cache_hits = rrdset_create_localhost(
1427 - "mssql",
1428 - id,
1429 - NULL,
1430 - "buffer cache",
1431 - "mssql.instance_cache_hit_ratio",
1432 - "Buffer Cache hit ratio",
1433 - "percentage",
1434 - PLUGIN_WINDOWS_NAME,
1435 - "PerflibMSSQL",
1436 - PRIO_MSSQL_BUFF_CACHE_HIT_RATIO,
1437 - update_every,
1438 - RRDSET_TYPE_LINE);
1439 -
1440 - mi->rd_buff_cache_hits =
1441 - rrddim_add(mi->st_buff_cache_hits, "hit_ratio", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
1442 -
1443 - rrdlabels_add(mi->st_buff_cache_hits->rrdlabels, "mssql_instance", mi->instanceID, RRDLABEL_SRC_AUTO);
1444 - }
1445 -
1446 - rrddim_set_by_pointer(
1447 - mi->st_buff_cache_hits, mi->rd_buff_cache_hits, (collected_number)mi->MSSQLBufferCacheHits.current.Data);
1448 - rrdset_done(mi->st_buff_cache_hits);
1449 - }
1450 -
1451 - if (perflibGetObjectCounter(pDataBlock, pObjectType, &mi->MSSQLBufferCheckpointPages)) {
1452 - if (!mi->st_buff_checkpoint_pages) {
1453 - snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_bufman_checkpoint_pages", mi->instanceID);
1454 - netdata_fix_chart_name(id);
1455 - mi->st_buff_checkpoint_pages = rrdset_create_localhost(
1456 - "mssql",
1457 - id,
1458 - NULL,
1459 - "buffer cache",
1460 - "mssql.instance_bufman_checkpoint_pages",
1461 - "Flushed pages",
1462 - "pages/s",
1463 - PLUGIN_WINDOWS_NAME,
1464 - "PerflibMSSQL",
1465 - PRIO_MSSQL_BUFF_CHECKPOINT_PAGES,
1466 - update_every,
1467 - RRDSET_TYPE_LINE);
1468 -
1469 - mi->rd_buff_checkpoint_pages =
1470 - rrddim_add(mi->st_buff_checkpoint_pages, "log", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
1471 -
1472 - rrdlabels_add(mi->st_buff_checkpoint_pages->rrdlabels, "mssql_instance", mi->instanceID, RRDLABEL_SRC_AUTO);
1473 - }
1474 -
1475 - rrddim_set_by_pointer(
1476 - mi->st_buff_checkpoint_pages,
1477 - mi->rd_buff_checkpoint_pages,
1478 - (collected_number)mi->MSSQLBufferCheckpointPages.current.Data);
1479 - rrdset_done(mi->st_buff_checkpoint_pages);
1480 - }
1481 -
1482 - if (perflibGetObjectCounter(pDataBlock, pObjectType, &mi->MSSQLBufferPageLifeExpectancy)) {
1483 - if (!mi->st_buff_cache_page_life_expectancy) {
1484 - snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_bufman_page_life_expectancy", mi->instanceID);
1485 - netdata_fix_chart_name(id);
1486 - mi->st_buff_cache_page_life_expectancy = rrdset_create_localhost(
1487 - "mssql",
1488 - id,
1489 - NULL,
1490 - "buffer cache",
1491 - "mssql.instance_bufman_page_life_expectancy",
1492 - "Page life expectancy",
1493 - "seconds",
1494 - PLUGIN_WINDOWS_NAME,
1495 - "PerflibMSSQL",
1496 - PRIO_MSSQL_BUFF_PAGE_LIFE_EXPECTANCY,
1497 - update_every,
1498 - RRDSET_TYPE_LINE);
1499 -
1500 - mi->rd_buff_cache_page_life_expectancy = rrddim_add(
1501 - mi->st_buff_cache_page_life_expectancy, "life_expectancy", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
1502 -
1503 - rrdlabels_add(
1504 - mi->st_buff_cache_page_life_expectancy->rrdlabels, "mssql_instance", mi->instanceID, RRDLABEL_SRC_AUTO);
1505 - }
1506 -
1507 - rrddim_set_by_pointer(
1508 - mi->st_buff_cache_page_life_expectancy,
1509 - mi->rd_buff_cache_page_life_expectancy,
1510 - (collected_number)mi->MSSQLBufferPageLifeExpectancy.current.Data);
1511 - rrdset_done(mi->st_buff_cache_page_life_expectancy);
1512 - }
1513 -
1514 - if (perflibGetObjectCounter(pDataBlock, pObjectType, &mi->MSSQLBufferPageReads) &&
1515 - perflibGetObjectCounter(pDataBlock, pObjectType, &mi->MSSQLBufferPageWrites)) {
1516 - if (!mi->st_buff_page_iops) {
1517 - snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_bufman_iops", mi->instanceID);
1518 - netdata_fix_chart_name(id);
1519 - mi->st_buff_page_iops = rrdset_create_localhost(
1520 - "mssql",
1521 - id,
1522 - NULL,
1523 - "buffer cache",
1524 - "mssql.instance_bufman_iops",
1525 - "Number of pages input and output",
1526 - "pages/s",
1527 - PLUGIN_WINDOWS_NAME,
1528 - "PerflibMSSQL",
1529 - PRIO_MSSQL_BUFF_MAN_IOPS,
1530 - update_every,
1531 - RRDSET_TYPE_LINE);
1532 -
1533 - mi->rd_buff_page_reads = rrddim_add(mi->st_buff_page_iops, "read", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
1534 - mi->rd_buff_page_writes =
1535 - rrddim_add(mi->st_buff_page_iops, "written", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
1536 -
1537 - rrdlabels_add(mi->st_buff_page_iops->rrdlabels, "mssql_instance", mi->instanceID, RRDLABEL_SRC_AUTO);
1538 - }
1539 -
1540 - rrddim_set_by_pointer(
1541 - mi->st_buff_page_iops, mi->rd_buff_page_reads, (collected_number)mi->MSSQLBufferPageReads.current.Data);
1542 - rrddim_set_by_pointer(
1543 - mi->st_buff_page_iops, mi->rd_buff_page_writes, (collected_number)mi->MSSQLBufferPageWrites.current.Data);
1544 -
1545 - rrdset_done(mi->st_buff_page_iops);
1546 - }
1441 }
1442
1443 static void do_mssql_access_methods(PERF_DATA_BLOCK *pDataBlock, struct mssql_instance *mi, int update_every)
@@ -1926,6 +1820,224 @@ static void do_mssql_waits(PERF_DATA_BLOCK *pDataBlock, struct mssql_instance *m
1820 dictionary_sorted_walkthrough_read(mi->waits, dict_mssql_waits_charts_cb, mi);
1821 }
1822
1823 +void mssql_buffman_iops_chart(struct mssql_db_instance *mdi, struct mssql_instance *mi)
1824 +{
1825 + if (!mdi->st_buff_page_iops) {
1826 + char id[RRD_ID_LENGTH_MAX + 1];
1827 + snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_bufman_iops", mi->instanceID);
1828 + netdata_fix_chart_name(id);
1829 + mdi->st_buff_page_iops = rrdset_create_localhost(
1830 + "mssql",
1831 + id,
1832 + NULL,
1833 + "buffer cache",
1834 + "mssql.instance_bufman_iops",
1835 + "Number of pages input and output",
1836 + "pages/s",
1837 + PLUGIN_WINDOWS_NAME,
1838 + "PerflibMSSQL",
1839 + PRIO_MSSQL_BUFF_MAN_IOPS,
1840 + mi->update_every,
1841 + RRDSET_TYPE_LINE);
1842 +
1843 + mdi->rd_buff_page_reads = rrddim_add(mdi->st_buff_page_iops, "read", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
1844 + mdi->rd_buff_page_writes =
1845 + rrddim_add(mdi->st_buff_page_iops, "written", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
1846 +
1847 + rrdlabels_add(mdi->st_buff_page_iops->rrdlabels, "mssql_instance", mi->instanceID, RRDLABEL_SRC_AUTO);
1848 + }
1849 +
1850 + rrddim_set_by_pointer(
1851 + mdi->st_buff_page_iops, mdi->rd_buff_page_reads, (collected_number)mdi->MSSQLBufferPageReads.current.Data);
1852 + rrddim_set_by_pointer(
1853 + mdi->st_buff_page_iops, mdi->rd_buff_page_writes, (collected_number)mdi->MSSQLBufferPageWrites.current.Data);
1854 +
1855 + rrdset_done(mdi->st_buff_page_iops);
1856 +}
1857 +
1858 +void mssql_buffman_cache_hit_ratio_chart(struct mssql_db_instance *mdi, struct mssql_instance *mi)
1859 +{
1860 + if (!mdi->st_buff_cache_hits) {
1861 + char id[RRD_ID_LENGTH_MAX + 1];
1862 + snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_cache_hit_ratio", mi->instanceID);
1863 + netdata_fix_chart_name(id);
1864 + mdi->st_buff_cache_hits = rrdset_create_localhost(
1865 + "mssql",
1866 + id,
1867 + NULL,
1868 + "buffer cache",
1869 + "mssql.instance_cache_hit_ratio",
1870 + "Buffer Cache hit ratio",
1871 + "percentage",
1872 + PLUGIN_WINDOWS_NAME,
1873 + "PerflibMSSQL",
1874 + PRIO_MSSQL_BUFF_CACHE_HIT_RATIO,
1875 + mi->update_every,
1876 + RRDSET_TYPE_LINE);
1877 +
1878 + mdi->rd_buff_cache_hits =
1879 + rrddim_add(mdi->st_buff_cache_hits, "hit_ratio", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
1880 +
1881 + rrdlabels_add(mdi->st_buff_cache_hits->rrdlabels, "mssql_instance", mi->instanceID, RRDLABEL_SRC_AUTO);
1882 + }
1883 +
1884 + rrddim_set_by_pointer(
1885 + mdi->st_buff_cache_hits, mdi->rd_buff_cache_hits, (collected_number)mdi->MSSQLBufferCacheHits.current.Data);
1886 + rrdset_done(mdi->st_buff_cache_hits);
1887 +}
1888 +
1889 +void mssql_buffman_checkpoints_pages_chart(struct mssql_db_instance *mdi, struct mssql_instance *mi)
1890 +{
1891 + if (!mdi->st_buff_checkpoint_pages) {
1892 + char id[RRD_ID_LENGTH_MAX + 1];
1893 + snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_bufman_checkpoint_pages", mi->instanceID);
1894 + netdata_fix_chart_name(id);
1895 + mdi->st_buff_checkpoint_pages = rrdset_create_localhost(
1896 + "mssql",
1897 + id,
1898 + NULL,
1899 + "buffer cache",
1900 + "mssql.instance_bufman_checkpoint_pages",
1901 + "Flushed pages",
1902 + "pages/s",
1903 + PLUGIN_WINDOWS_NAME,
1904 + "PerflibMSSQL",
1905 + PRIO_MSSQL_BUFF_CHECKPOINT_PAGES,
1906 + mi->update_every,
1907 + RRDSET_TYPE_LINE);
1908 +
1909 + mdi->rd_buff_checkpoint_pages =
1910 + rrddim_add(mdi->st_buff_checkpoint_pages, "log", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
1911 +
1912 + rrdlabels_add(mdi->st_buff_checkpoint_pages->rrdlabels, "mssql_instance", mi->instanceID, RRDLABEL_SRC_AUTO);
1913 + }
1914 +
1915 + rrddim_set_by_pointer(
1916 + mdi->st_buff_checkpoint_pages,
1917 + mdi->rd_buff_checkpoint_pages,
1918 + (collected_number)mdi->MSSQLBufferCheckpointPages.current.Data);
1919 + rrdset_done(mdi->st_buff_checkpoint_pages);
1920 +}
1921 +
1922 +void mssql_buffman_page_life_expectancy_chart(struct mssql_db_instance *mdi, struct mssql_instance *mi)
1923 +{
1924 + if (!mdi->st_buff_cache_page_life_expectancy) {
1925 + char id[RRD_ID_LENGTH_MAX + 1];
1926 + snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_bufman_page_life_expectancy", mi->instanceID);
1927 + netdata_fix_chart_name(id);
1928 + mdi->st_buff_cache_page_life_expectancy = rrdset_create_localhost(
1929 + "mssql",
1930 + id,
1931 + NULL,
1932 + "buffer cache",
1933 + "mssql.instance_bufman_page_life_expectancy",
1934 + "Page life expectancy",
1935 + "seconds",
1936 + PLUGIN_WINDOWS_NAME,
1937 + "PerflibMSSQL",
1938 + PRIO_MSSQL_BUFF_PAGE_LIFE_EXPECTANCY,
1939 + mi->update_every,
1940 + RRDSET_TYPE_LINE);
1941 +
1942 + mdi->rd_buff_cache_page_life_expectancy = rrddim_add(
1943 + mdi->st_buff_cache_page_life_expectancy, "life_expectancy", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
1944 +
1945 + rrdlabels_add(
1946 + mdi->st_buff_cache_page_life_expectancy->rrdlabels, "mssql_instance", mi->instanceID, RRDLABEL_SRC_AUTO);
1947 + }
1948 +
1949 + rrddim_set_by_pointer(
1950 + mdi->st_buff_cache_page_life_expectancy,
1951 + mdi->rd_buff_cache_page_life_expectancy,
1952 + (collected_number)mdi->MSSQLBufferPageLifeExpectancy.current.Data);
1953 + rrdset_done(mdi->st_buff_cache_page_life_expectancy);
1954 +}
1955 +
1956 +static void netdata_mssql_compilations(struct mssql_db_instance *mdi, struct mssql_instance *mi) {
1957 + if (!mdi->st_stats_compilation) {
1958 + char id[RRD_ID_LENGTH_MAX + 1];
1959 + snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_sqlstats_sql_compilations", mi->instanceID);
1960 + netdata_fix_chart_name(id);
1961 + mdi->st_stats_compilation = rrdset_create_localhost(
1962 + "mssql",
1963 + id,
1964 + NULL,
1965 + "sql activity",
1966 + "mssql.instance_sqlstats_sql_compilations",
1967 + "SQL compilations",
1968 + "compilations/s",
1969 + PLUGIN_WINDOWS_NAME,
1970 + "PerflibMSSQL",
1971 + PRIO_MSSQL_STATS_COMPILATIONS,
1972 + mi->update_every,
1973 + RRDSET_TYPE_LINE);
1974 +
1975 + mdi->rd_stats_compilation =
1976 + rrddim_add(mdi->st_stats_compilation, "compilations", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
1977 +
1978 + rrdlabels_add(mdi->st_stats_compilation->rrdlabels, "mssql_instance", mi->instanceID, RRDLABEL_SRC_AUTO);
1979 + }
1980 +
1981 + rrddim_set_by_pointer(
1982 + mdi->st_stats_compilation, mdi->rd_stats_compilation,
1983 + (collected_number) mdi->MSSQLCompilations.current.Data);
1984 + rrdset_done(mdi->st_stats_compilation);
1985 +}
1986 +
1987 +static void netdata_mssql_recompilations(struct mssql_db_instance *mdi, struct mssql_instance *mi)
1988 +{
1989 + if (!mdi->st_stats_recompiles) {
1990 + char id[RRD_ID_LENGTH_MAX + 1];
1991 + snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_sqlstats_sql_recompilations", mi->instanceID);
1992 + netdata_fix_chart_name(id);
1993 + mdi->st_stats_recompiles = rrdset_create_localhost(
1994 + "mssql",
1995 + id,
1996 + NULL,
1997 + "sql activity",
1998 + "mssql.instance_sqlstats_sql_recompilations",
1999 + "SQL re-compilations",
2000 + "recompiles/",
2001 + PLUGIN_WINDOWS_NAME,
2002 + "PerflibMSSQL",
2003 + PRIO_MSSQL_STATS_RECOMPILATIONS,
2004 + mi->update_every,
2005 + RRDSET_TYPE_LINE);
2006 +
2007 + mdi->rd_stats_recompiles =
2008 + rrddim_add(mdi->st_stats_recompiles, "recompiles", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
2009 +
2010 + rrdlabels_add(mdi->st_stats_recompiles->rrdlabels, "mssql_instance", mi->instanceID, RRDLABEL_SRC_AUTO);
2011 + }
2012 +
2013 + rrddim_set_by_pointer(
2014 + mdi->st_stats_recompiles, mdi->rd_stats_recompiles, (collected_number)mdi->MSSQLRecompilations.current.Data);
2015 + rrdset_done(mdi->st_stats_recompiles);
2016 +}
2017 +
2018 +int dict_mssql_buffman_stats_charts_cb(const DICTIONARY_ITEM *item __maybe_unused, void *value, void *data __maybe_unused)
2019 +{
2020 + struct mssql_db_instance *mdi = value;
2021 + struct mssql_instance *mi = data;
2022 +
2023 + if (unlikely(!mdi->collect_instance))
2024 + return 1;
2025 +
2026 + mssql_buffman_iops_chart(mdi, mi);
2027 + mssql_buffman_cache_hit_ratio_chart(mdi, mi);
2028 + mssql_buffman_checkpoints_pages_chart(mdi, mi);
2029 + mssql_buffman_page_life_expectancy_chart(mdi, mi);
2030 + netdata_mssql_compilations(mdi, mi);
2031 + netdata_mssql_recompilations(mdi, mi);
2032 +
2033 + return 1;
2034 +}
2035 +
2036 +static void do_mssql_bufferman_stats_sql(PERF_DATA_BLOCK *pDataBlock, struct mssql_instance *mi, int update_every)
2037 +{
2038 + dictionary_sorted_walkthrough_read(mi->databases, dict_mssql_buffman_stats_charts_cb, mi);
2039 +}
2040 +
2041 static void mssql_database_backup_restore_chart(struct mssql_db_instance *mdi, const char *db, int update_every)
2042 {
2043 char id[RRD_ID_LENGTH_MAX + 1];
@@ -2374,6 +2486,9 @@ static void do_mssql_databases(PERF_DATA_BLOCK *pDataBlock, struct mssql_instanc
2486 if (!mdi->parent) {
2487 mdi->parent = mi;
2488 }
2489 +
2490 + if (!i)
2491 + mdi->collect_instance = true;
2492 }
2493
2494 end_mssql_databases:
@@ -2536,18 +2651,18 @@ int dict_mssql_charts_cb(const DICTIONARY_ITEM *item __maybe_unused, void *value
2651 int *update_every = data;
2652
2653 static void (*doMSSQL[])(PERF_DATA_BLOCK *, struct mssql_instance *, int) = {
2539 - do_mssql_general_stats,
2540 - do_mssql_errors,
2541 - do_mssql_memory_mgr,
2542 - do_mssql_buffer_management,
2543 - do_mssql_sql_statistics,
2544 - do_mssql_access_methods,
2545 -
2546 - do_mssql_databases,
2547 - do_mssql_locks,
2548 - do_mssql_waits,
2549 -
2550 - NULL};
2654 + do_mssql_general_stats,
2655 + do_mssql_errors,
2656 + do_mssql_memory_mgr,
2657 + do_mssql_statistics_perflib,
2658 + do_mssql_access_methods,
2659 +
2660 + do_mssql_databases,
2661 + do_mssql_locks,
2662 + do_mssql_waits,
2663 + do_mssql_bufferman_stats_sql,
2664 +
2665 + NULL};
2666
2667 DWORD i;
2668 PERF_DATA_BLOCK *pDataBlock;