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;