Reorganize MSSQL collection. (#21290)
thiagoftsm committed
Nov 13, 2025 at 12:21 UTC
959e74ef7aa20a50394a199ad790c253f1a030ab
4 files changed
+3652
-3637
CMakeLists.txt
+2
-1
@@ -1932,12 +1932,12 @@ set(WINDOWS_PLUGIN_FILES
1932
src/collectors/windows.plugin/GetServicesStatus.c
1933
src/collectors/windows.plugin/GetSensors.c
1934
src/collectors/windows.plugin/GetHardwareInfo.c
1935
+ src/collectors/windows.plugin/MonitorSQL.c
1936
src/collectors/windows.plugin/perflib-adcs.c
1937
src/collectors/windows.plugin/perflib-adfs.c
1938
src/collectors/windows.plugin/perflib-rrd.c
1939
src/collectors/windows.plugin/perflib-rrd.h
1940
src/collectors/windows.plugin/perflib-ad.c
1940
- src/collectors/windows.plugin/perflib-mssql.c
1941
src/collectors/windows.plugin/perflib-mssql-queries.h
1942
src/collectors/windows.plugin/perflib-storage.c
1943
src/collectors/windows.plugin/perflib-processor.c
@@ -1945,6 +1945,7 @@ set(WINDOWS_PLUGIN_FILES
1945
src/collectors/windows.plugin/perflib-objects.c
1946
src/collectors/windows.plugin/perflib-network.c
1947
src/collectors/windows.plugin/perflib-netframework.c
1948
+ src/collectors/windows.plugin/perflib-mssql.c
1949
src/collectors/windows.plugin/perflib-memory.c
1950
src/collectors/windows.plugin/perflib-processes.c
1951
src/collectors/windows.plugin/perflib-web-service.c
src/collectors/windows.plugin/MonitorSQL.c
new
+3035
@@ -0,0 +1,3035 @@
1
+// SPDX-License-Identifier: GPL-3.0-or-later
2
+
3
+#include "windows_plugin.h"
4
+#include "windows-internals.h"
5
+
6
+#include "perflib-mssql-queries.h"
7
+
8
+DICTIONARY *conn_options;
9
+
10
+static inline int netdata_mssql_check_result(SQLRETURN ret)
11
+{
12
+ return (ret != SQL_SUCCESS && ret != SQL_SUCCESS_WITH_INFO);
13
+}
14
+
15
+static char *netdata_MSSQL_error_text(enum netdata_mssql_odbc_errors val)
16
+{
17
+ switch (val) {
18
+ case NETDATA_MSSQL_ODBC_NO_ERROR:
19
+ return "NO ERROR";
20
+ case NETDATA_MSSQL_ODBC_CONNECT:
21
+ return "CONNECTION";
22
+ case NETDATA_MSSQL_ODBC_BIND:
23
+ return "BIND PARAMETER";
24
+ case NETDATA_MSSQL_ODBC_PREPARE:
25
+ return "PREPARE PARAMETER";
26
+ case NETDATA_MSSQL_ODBC_QUERY:
27
+ return "QUERY PARAMETER";
28
+ case NETDATA_MSSQL_ODBC_FETCH:
29
+ default:
30
+ return "QUERY FETCH";
31
+ }
32
+}
33
+
34
+static char *netdata_MSSQL_type_text(uint32_t type)
35
+{
36
+ switch (type) {
37
+ case SQL_HANDLE_STMT:
38
+ return "STMT";
39
+ case SQL_HANDLE_DBC:
40
+ default:
41
+ return "DBC";
42
+ }
43
+}
44
+
45
+// Connection and SQL
46
+static void netdata_MSSQL_error(uint32_t type, SQLHANDLE handle, enum netdata_mssql_odbc_errors step, char *instance)
47
+{
48
+ SQLCHAR state[1024];
49
+ SQLCHAR message[1024];
50
+ if (likely(SQL_SUCCESS == SQLGetDiagRec((short)type, handle, 1, state, NULL, message, 1024, NULL))) {
51
+ char *str_step = netdata_MSSQL_error_text(step);
52
+ char *str_type = netdata_MSSQL_type_text(type);
53
+ char *use_instance = (!instance) ? "no instance" : instance;
54
+ nd_log(
55
+ NDLS_COLLECTORS,
56
+ NDLP_INFO,
57
+ "MSSQL server error on %s using the handle %s running %s : %s, %s",
58
+ use_instance,
59
+ str_type,
60
+ str_step,
61
+ message,
62
+ state);
63
+ }
64
+}
65
+
66
+static inline void netdata_MSSQL_release_results(SQLHSTMT *stmt)
67
+{
68
+ SQLCloseCursor(stmt);
69
+}
70
+
71
+static ULONGLONG netdata_MSSQL_fill_long_value(SQLHSTMT *stmt, const char *mask, const char *dbname, char *instance)
72
+{
73
+ long db_size = 0;
74
+ SQLLEN col_data_len = 0;
75
+
76
+ SQLCHAR query[512];
77
+ snprintfz((char *)query, 511, mask, dbname);
78
+
79
+ SQLRETURN ret;
80
+
81
+ ret = SQLExecDirect(stmt, query, SQL_NTS);
82
+ if (likely(netdata_mssql_check_result(ret))) {
83
+ netdata_MSSQL_error(SQL_HANDLE_STMT, stmt, NETDATA_MSSQL_ODBC_QUERY, instance);
84
+ return (ULONGLONG)ULONG_LONG_MAX;
85
+ }
86
+
87
+ ret = SQLBindCol(stmt, 1, SQL_C_LONG, &db_size, sizeof(long), &col_data_len);
88
+ if (likely(netdata_mssql_check_result(ret))) {
89
+ netdata_MSSQL_error(SQL_HANDLE_STMT, stmt, NETDATA_MSSQL_ODBC_PREPARE, instance);
90
+ return (ULONGLONG)ULONG_LONG_MAX;
91
+ }
92
+
93
+ ret = SQLFetch(stmt);
94
+ if (likely(netdata_mssql_check_result(ret))) {
95
+ netdata_MSSQL_error(SQL_HANDLE_STMT, stmt, NETDATA_MSSQL_ODBC_FETCH, instance);
96
+ return (ULONGLONG)ULONG_LONG_MAX;
97
+ }
98
+
99
+ netdata_MSSQL_release_results(stmt);
100
+ return (ULONGLONG)(db_size * MEGA_FACTOR);
101
+}
102
+
103
+#define NETDATA_MSSQL_BUFFER_PAGE_READS_METRIC "Page reads/sec"
104
+#define NETDATA_MSSQL_BUFFER_PAGE_WRITES_METRIC "Page writes/sec"
105
+#define NETDATA_MSSQL_BUFFER_PAGE_CACHE_METRIC "Buffer cache hit ratio"
106
+#define NETDATA_MSSQL_BUFFER_CHECKPOINT_METRIC "Checkpoint pages/sec"
107
+#define NETDATA_MSSQL_BUFFER_PAGE_LIFE_METRIC "Page life expectancy"
108
+#define NETDATA_MSSQL_BUFFER_LAZY_WRITES_METRIC "Lazy writes/sec"
109
+#define NETDATA_MSSQL_BUFFER_PAGE_LOOKUPS_METRIC "Page Lookups/sec"
110
+
111
+#define NETDATA_MSSQL_STATS_COMPILATIONS_METRIC "SQL Compilations/sec"
112
+#define NETDATA_MSSQL_STATS_RECOMPILATIONS_METRIC "SQL Re-Compilations/sec"
113
+
114
+void dict_mssql_fill_instance_transactions(struct mssql_db_instance *mdi)
115
+{
116
+ char object_name[NETDATA_MAX_INSTANCE_OBJECT + 1] = {};
117
+ long value = 0;
118
+ SQLLEN col_object_len = 0, col_value_len = 0;
119
+
120
+ SQLCHAR query[sizeof(NETDATA_QUERY_TRANSACTIONS_PER_INSTANCE_MASK) + NETDATA_MAX_INSTANCE_OBJECT + 1];
121
+ snprintfz(
122
+ (char *)query,
123
+ sizeof(NETDATA_QUERY_TRANSACTIONS_PER_INSTANCE_MASK) + NETDATA_MAX_INSTANCE_OBJECT,
124
+ NETDATA_QUERY_TRANSACTIONS_PER_INSTANCE_MASK,
125
+ mdi->parent->instanceID);
126
+
127
+ SQLRETURN ret = SQLExecDirect(mdi->parent->conn->dbInstanceTransactionSTMT, (SQLCHAR *)query, SQL_NTS);
128
+ if (likely(netdata_mssql_check_result(ret))) {
129
+ mdi->collecting_data = false;
130
+ netdata_MSSQL_error(
131
+ SQL_HANDLE_STMT,
132
+ mdi->parent->conn->dbInstanceTransactionSTMT,
133
+ NETDATA_MSSQL_ODBC_QUERY,
134
+ mdi->parent->instanceID);
135
+ goto enditransactions;
136
+ }
137
+
138
+ ret = SQLBindCol(
139
+ mdi->parent->conn->dbInstanceTransactionSTMT, 1, SQL_C_CHAR, object_name, sizeof(object_name), &col_object_len);
140
+ if (likely(netdata_mssql_check_result(ret))) {
141
+ netdata_MSSQL_error(
142
+ SQL_HANDLE_STMT,
143
+ mdi->parent->conn->dbInstanceTransactionSTMT,
144
+ NETDATA_MSSQL_ODBC_PREPARE,
145
+ mdi->parent->instanceID);
146
+ goto enditransactions;
147
+ }
148
+
149
+ ret =
150
+ SQLBindCol(mdi->parent->conn->dbInstanceTransactionSTMT, 2, SQL_C_LONG, &value, sizeof(value), &col_value_len);
151
+ if (likely(netdata_mssql_check_result(ret))) {
152
+ netdata_MSSQL_error(
153
+ SQL_HANDLE_STMT,
154
+ mdi->parent->conn->dbInstanceTransactionSTMT,
155
+ NETDATA_MSSQL_ODBC_PREPARE,
156
+ mdi->parent->instanceID);
157
+ goto enditransactions;
158
+ }
159
+
160
+ do {
161
+ ret = SQLFetch(mdi->parent->conn->dbInstanceTransactionSTMT);
162
+ switch (ret) {
163
+ case SQL_SUCCESS:
164
+ case SQL_SUCCESS_WITH_INFO:
165
+ break;
166
+ case SQL_NO_DATA:
167
+ default:
168
+ goto enditransactions;
169
+ }
170
+
171
+ // We cannot use strcmp, because buffer is filled with spaces instead NULL.
172
+ if (unlikely(!strncmp(
173
+ object_name, NETDATA_MSSQL_BUFFER_PAGE_READS_METRIC, sizeof(NETDATA_MSSQL_BUFFER_PAGE_READS_METRIC) - 1)))
174
+ mdi->MSSQLBufferPageReads.current.Data = (ULONGLONG)value;
175
+ else if (unlikely(!strncmp(
176
+ object_name,
177
+ NETDATA_MSSQL_BUFFER_PAGE_WRITES_METRIC,
178
+ sizeof(NETDATA_MSSQL_BUFFER_PAGE_WRITES_METRIC) - 1)))
179
+ mdi->MSSQLBufferPageWrites.current.Data = (ULONGLONG)value;
180
+ else if (unlikely(!strncmp(
181
+ object_name,
182
+ NETDATA_MSSQL_BUFFER_PAGE_CACHE_METRIC,
183
+ sizeof(NETDATA_MSSQL_BUFFER_PAGE_CACHE_METRIC) - 1)))
184
+ mdi->MSSQLBufferCacheHits.current.Data = (ULONGLONG)value;
185
+ else if (unlikely(!strncmp(
186
+ object_name,
187
+ NETDATA_MSSQL_BUFFER_CHECKPOINT_METRIC,
188
+ sizeof(NETDATA_MSSQL_BUFFER_CHECKPOINT_METRIC) - 1)))
189
+ mdi->MSSQLBufferCheckpointPages.current.Data = (ULONGLONG)value;
190
+ else if (unlikely(!strncmp(
191
+ object_name,
192
+ NETDATA_MSSQL_BUFFER_PAGE_LIFE_METRIC,
193
+ sizeof(NETDATA_MSSQL_BUFFER_PAGE_LIFE_METRIC) - 1)))
194
+ mdi->MSSQLBufferPageLifeExpectancy.current.Data = (ULONGLONG)value;
195
+ else if (unlikely(!strncmp(
196
+ object_name,
197
+ NETDATA_MSSQL_BUFFER_LAZY_WRITES_METRIC,
198
+ sizeof(NETDATA_MSSQL_BUFFER_LAZY_WRITES_METRIC) - 1)))
199
+ mdi->MSSQLBufferLazyWrite.current.Data = (ULONGLONG)value;
200
+ else if (unlikely(!strncmp(
201
+ object_name,
202
+ NETDATA_MSSQL_BUFFER_PAGE_LOOKUPS_METRIC,
203
+ sizeof(NETDATA_MSSQL_BUFFER_PAGE_LOOKUPS_METRIC) - 1)))
204
+ mdi->MSSQLBufferPageLookups.current.Data = (ULONGLONG)value;
205
+ else if (unlikely(!strncmp(
206
+ object_name,
207
+ NETDATA_MSSQL_STATS_COMPILATIONS_METRIC,
208
+ sizeof(NETDATA_MSSQL_STATS_COMPILATIONS_METRIC) - 1)))
209
+ mdi->MSSQLCompilations.current.Data = (ULONGLONG)value;
210
+ else if (unlikely(!strncmp(
211
+ object_name,
212
+ NETDATA_MSSQL_STATS_RECOMPILATIONS_METRIC,
213
+ sizeof(NETDATA_MSSQL_STATS_RECOMPILATIONS_METRIC) - 1)))
214
+ mdi->MSSQLRecompilations.current.Data = (ULONGLONG)value;
215
+ } while (true);
216
+
217
+enditransactions:
218
+ netdata_MSSQL_release_results(mdi->parent->conn->dbInstanceTransactionSTMT);
219
+}
220
+
221
+#define NETDATA_MSSQL_ACTIVE_TRANSACTIONS_METRIC "Active Transactions"
222
+#define NETDATA_MSSQL_TRANSACTION_PER_SEC_METRIC "Transactions/sec"
223
+#define NETDATA_MSSQL_WRITE_TRANSACTIONS_METRIC "Write Transactions/sec"
224
+#define NETDATA_MSSQL_BACKUP_RESTORE_METRIC "Backup/Restore Throughput/sec"
225
+#define NETDATA_MSSQL_LOG_FLUSHED_METRIC "Log Bytes Flushed/sec"
226
+#define NETDATA_MSSQL_LOG_FLUSHES_METRIC "Log Flushes/sec"
227
+#define NETDATA_MSSQL_NUMBER_DEADLOCKS_METRIC "Number of Deadlocks/sec"
228
+#define NETDATA_MSSQL_LOCK_WAITS_METRIC "Lock Waits/sec"
229
+#define NETDATA_MSSQL_LOCK_TIMEOUTS_METRIC "Lock Timeouts/sec"
230
+#define NETDATA_MSSQL_LOCK_REQUESTS_METRIC "Lock Requests/sec"
231
+
232
+void dict_mssql_fill_transactions(struct mssql_db_instance *mdi, const char *dbname)
233
+{
234
+ char object_name[NETDATA_MAX_INSTANCE_OBJECT + 1] = {};
235
+ long value = 0;
236
+ SQLLEN col_object_len = 0, col_value_len = 0;
237
+
238
+ if (mdi->collect_instance)
239
+ dict_mssql_fill_instance_transactions(mdi);
240
+
241
+ SQLCHAR query[sizeof(NETDATA_QUERY_TRANSACTIONS_MASK) + 2 * NETDATA_MAX_INSTANCE_OBJECT + 1];
242
+ snprintfz(
243
+ (char *)query,
244
+ sizeof(NETDATA_QUERY_TRANSACTIONS_MASK) + 2 * NETDATA_MAX_INSTANCE_OBJECT,
245
+ NETDATA_QUERY_TRANSACTIONS_MASK,
246
+ dbname,
247
+ dbname);
248
+
249
+ SQLRETURN ret = SQLExecDirect(mdi->parent->conn->dbTransactionSTMT, (SQLCHAR *)query, SQL_NTS);
250
+ if (likely(netdata_mssql_check_result(ret))) {
251
+ mdi->collecting_data = false;
252
+ netdata_MSSQL_error(
253
+ SQL_HANDLE_STMT, mdi->parent->conn->dbTransactionSTMT, NETDATA_MSSQL_ODBC_QUERY, mdi->parent->instanceID);
254
+ goto endtransactions;
255
+ }
256
+
257
+ ret = SQLBindCol(
258
+ mdi->parent->conn->dbTransactionSTMT, 1, SQL_C_CHAR, object_name, sizeof(object_name), &col_object_len);
259
+ if (likely(netdata_mssql_check_result(ret))) {
260
+ netdata_MSSQL_error(
261
+ SQL_HANDLE_STMT, mdi->parent->conn->dbTransactionSTMT, NETDATA_MSSQL_ODBC_PREPARE, mdi->parent->instanceID);
262
+ goto endtransactions;
263
+ }
264
+
265
+ ret = SQLBindCol(mdi->parent->conn->dbTransactionSTMT, 2, SQL_C_LONG, &value, sizeof(value), &col_value_len);
266
+ if (likely(netdata_mssql_check_result(ret))) {
267
+ netdata_MSSQL_error(
268
+ SQL_HANDLE_STMT, mdi->parent->conn->dbTransactionSTMT, NETDATA_MSSQL_ODBC_PREPARE, mdi->parent->instanceID);
269
+ goto endtransactions;
270
+ }
271
+
272
+ do {
273
+ ret = SQLFetch(mdi->parent->conn->dbTransactionSTMT);
274
+ switch (ret) {
275
+ case SQL_SUCCESS:
276
+ case SQL_SUCCESS_WITH_INFO:
277
+ break;
278
+ case SQL_NO_DATA:
279
+ default:
280
+ goto endtransactions;
281
+ }
282
+
283
+ // We cannot use strcmp, because buffer is filled with spaces instead NULL.
284
+ if (unlikely(!strncmp(
285
+ object_name,
286
+ NETDATA_MSSQL_ACTIVE_TRANSACTIONS_METRIC,
287
+ sizeof(NETDATA_MSSQL_ACTIVE_TRANSACTIONS_METRIC) - 1)))
288
+ mdi->MSSQLDatabaseActiveTransactions.current.Data = (ULONGLONG)value;
289
+ else if (unlikely(!strncmp(
290
+ object_name,
291
+ NETDATA_MSSQL_TRANSACTION_PER_SEC_METRIC,
292
+ sizeof(NETDATA_MSSQL_TRANSACTION_PER_SEC_METRIC) - 1)))
293
+ mdi->MSSQLDatabaseTransactions.current.Data = (ULONGLONG)value;
294
+ else if (unlikely(!strncmp(
295
+ object_name,
296
+ NETDATA_MSSQL_WRITE_TRANSACTIONS_METRIC,
297
+ sizeof(NETDATA_MSSQL_WRITE_TRANSACTIONS_METRIC) - 1)))
298
+ mdi->MSSQLDatabaseWriteTransactions.current.Data = (ULONGLONG)value;
299
+ else if (unlikely(!strncmp(
300
+ object_name, NETDATA_MSSQL_BACKUP_RESTORE_METRIC, sizeof(NETDATA_MSSQL_BACKUP_RESTORE_METRIC) - 1)))
301
+ mdi->MSSQLDatabaseBackupRestoreOperations.current.Data = (ULONGLONG)value;
302
+ else if (unlikely(!strncmp(object_name, NETDATA_MSSQL_LOG_FLUSHED_METRIC, sizeof(NETDATA_MSSQL_LOG_FLUSHED_METRIC) - 1)))
303
+ mdi->MSSQLDatabaseLogFlushed.current.Data = (ULONGLONG)value;
304
+ else if (unlikely(!strncmp(object_name, NETDATA_MSSQL_LOG_FLUSHES_METRIC, sizeof(NETDATA_MSSQL_LOG_FLUSHES_METRIC) - 1)))
305
+ mdi->MSSQLDatabaseLogFlushes.current.Data = (ULONGLONG)value;
306
+ else if (unlikely(!strncmp(
307
+ object_name,
308
+ NETDATA_MSSQL_NUMBER_DEADLOCKS_METRIC,
309
+ sizeof(NETDATA_MSSQL_NUMBER_DEADLOCKS_METRIC) - 1)))
310
+ mdi->MSSQLDatabaseDeadLockSec.current.Data = (ULONGLONG)value;
311
+ else if (unlikely(!strncmp(object_name, NETDATA_MSSQL_LOCK_WAITS_METRIC, sizeof(NETDATA_MSSQL_LOCK_WAITS_METRIC) - 1)))
312
+ mdi->MSSQLDatabaseLockWaitSec.current.Data = (ULONGLONG)value;
313
+ else if (unlikely(!strncmp(
314
+ object_name, NETDATA_MSSQL_LOCK_TIMEOUTS_METRIC, sizeof(NETDATA_MSSQL_LOCK_TIMEOUTS_METRIC) - 1)))
315
+ mdi->MSSQLDatabaseLockTimeoutsSec.current.Data = (ULONGLONG)value;
316
+ else if (unlikely(!strncmp(
317
+ object_name, NETDATA_MSSQL_LOCK_REQUESTS_METRIC, sizeof(NETDATA_MSSQL_LOCK_REQUESTS_METRIC) - 1)))
318
+ mdi->MSSQLDatabaseLockRequestsSec.current.Data = (ULONGLONG)value;
319
+
320
+ } while (true);
321
+
322
+endtransactions:
323
+ netdata_MSSQL_release_results(mdi->parent->conn->dbTransactionSTMT);
324
+}
325
+
326
+void dict_mssql_fill_locks(struct mssql_db_instance *mdi, const char *dbname)
327
+{
328
+#define NETDATA_MSSQL_MAX_RESOURCE_TYPE (60)
329
+ char resource_type[NETDATA_MSSQL_MAX_RESOURCE_TYPE + 1] = {};
330
+ long value = 0;
331
+ SQLLEN col_object_len = 0, col_value_len = 0;
332
+
333
+ SQLCHAR query[sizeof(NETDATA_QUERY_LOCKS_MASK) + 2 * NETDATA_MAX_INSTANCE_OBJECT + 1];
334
+ snprintfz(
335
+ (char *)query,
336
+ sizeof(NETDATA_QUERY_TRANSACTIONS_MASK) + 2 * NETDATA_MAX_INSTANCE_OBJECT,
337
+ NETDATA_QUERY_LOCKS_MASK,
338
+ dbname,
339
+ dbname);
340
+
341
+ SQLRETURN ret = SQLExecDirect(mdi->parent->conn->dbLocksSTMT, (SQLCHAR *)query, SQL_NTS);
342
+ if (likely(netdata_mssql_check_result(ret))) {
343
+ mdi->collecting_data = false;
344
+ netdata_MSSQL_error(
345
+ SQL_HANDLE_STMT, mdi->parent->conn->dbLocksSTMT, NETDATA_MSSQL_ODBC_QUERY, mdi->parent->instanceID);
346
+ goto endlocks;
347
+ }
348
+
349
+ ret = SQLBindCol(
350
+ mdi->parent->conn->dbLocksSTMT, 1, SQL_C_CHAR, resource_type, sizeof(resource_type), &col_object_len);
351
+ if (likely(netdata_mssql_check_result(ret))) {
352
+ netdata_MSSQL_error(
353
+ SQL_HANDLE_STMT, mdi->parent->conn->dbLocksSTMT, NETDATA_MSSQL_ODBC_PREPARE, mdi->parent->instanceID);
354
+ goto endlocks;
355
+ }
356
+
357
+ ret = SQLBindCol(mdi->parent->conn->dbLocksSTMT, 2, SQL_C_LONG, &value, sizeof(value), &col_value_len);
358
+ if (likely(netdata_mssql_check_result(ret))) {
359
+ netdata_MSSQL_error(
360
+ SQL_HANDLE_STMT, mdi->parent->conn->dbLocksSTMT, NETDATA_MSSQL_ODBC_PREPARE, mdi->parent->instanceID);
361
+ goto endlocks;
362
+ }
363
+
364
+ do {
365
+ ret = SQLFetch(mdi->parent->conn->dbLocksSTMT);
366
+ switch (ret) {
367
+ case SQL_SUCCESS:
368
+ case SQL_SUCCESS_WITH_INFO:
369
+ break;
370
+ case SQL_NO_DATA:
371
+ default:
372
+ goto endlocks;
373
+ }
374
+
375
+ char *space = strchr(resource_type, ' ');
376
+ if (likely(space))
377
+ *space = '\0';
378
+
379
+ struct mssql_lock_instance *mli =
380
+ dictionary_set(mdi->parent->locks_instances, resource_type, NULL, sizeof(*mli));
381
+ if (unlikely(!mli))
382
+ continue;
383
+
384
+ mli->lockWait.current.Data = value;
385
+ } while (true);
386
+
387
+endlocks:
388
+ netdata_MSSQL_release_results(mdi->parent->conn->dbLocksSTMT);
389
+}
390
+
391
+int dict_mssql_fill_waits(struct mssql_instance *mi)
392
+{
393
+ char wait_type[NETDATA_MAX_INSTANCE_OBJECT + 1] = {};
394
+ char wait_category[NETDATA_MAX_INSTANCE_OBJECT + 1] = {};
395
+ SQLBIGINT total_wait = 0;
396
+ SQLBIGINT resource_wait = 0;
397
+ SQLBIGINT signal_wait = 0;
398
+ SQLBIGINT max_wait = 0;
399
+ SQLBIGINT waiting_tasks = 0;
400
+ int success = 0;
401
+ SQLLEN col_wait_type_len = 0, col_total_wait_len = 0, col_resource_wait_len = 0, col_signal_wait_len = 0,
402
+ col_max_wait_len = 0, col_waiting_tasks_len = 0, col_wait_category_len = 0;
403
+
404
+ SQLRETURN ret = SQLExecDirect(mi->conn->dbWaitsSTMT, (SQLCHAR *)NETDATA_QUERY_CHECK_WAITS, SQL_NTS);
405
+ if (likely(netdata_mssql_check_result(ret))) {
406
+ netdata_MSSQL_error(SQL_HANDLE_STMT, mi->conn->dbWaitsSTMT, NETDATA_MSSQL_ODBC_QUERY, mi->instanceID);
407
+ goto endwait;
408
+ }
409
+
410
+ ret = SQLBindCol(mi->conn->dbWaitsSTMT, 1, SQL_C_CHAR, wait_type, sizeof(wait_type), &col_wait_type_len);
411
+ if (likely(netdata_mssql_check_result(ret))) {
412
+ netdata_MSSQL_error(SQL_HANDLE_STMT, mi->conn->dbWaitsSTMT, NETDATA_MSSQL_ODBC_PREPARE, mi->instanceID);
413
+ goto endwait;
414
+ }
415
+
416
+ ret = SQLBindCol(mi->conn->dbWaitsSTMT, 2, SQL_C_LONG, &total_wait, sizeof(total_wait), &col_total_wait_len);
417
+ if (likely(netdata_mssql_check_result(ret))) {
418
+ netdata_MSSQL_error(SQL_HANDLE_STMT, mi->conn->dbWaitsSTMT, NETDATA_MSSQL_ODBC_PREPARE, mi->instanceID);
419
+ goto endwait;
420
+ }
421
+
422
+ ret =
423
+ SQLBindCol(mi->conn->dbWaitsSTMT, 3, SQL_C_LONG, &resource_wait, sizeof(resource_wait), &col_resource_wait_len);
424
+ if (likely(netdata_mssql_check_result(ret))) {
425
+ netdata_MSSQL_error(SQL_HANDLE_STMT, mi->conn->dbWaitsSTMT, NETDATA_MSSQL_ODBC_PREPARE, mi->instanceID);
426
+ goto endwait;
427
+ }
428
+
429
+ ret = SQLBindCol(mi->conn->dbWaitsSTMT, 4, SQL_C_LONG, &signal_wait, sizeof(signal_wait), &col_signal_wait_len);
430
+ if (likely(netdata_mssql_check_result(ret))) {
431
+ netdata_MSSQL_error(SQL_HANDLE_STMT, mi->conn->dbWaitsSTMT, NETDATA_MSSQL_ODBC_PREPARE, mi->instanceID);
432
+ goto endwait;
433
+ }
434
+
435
+ ret = SQLBindCol(mi->conn->dbWaitsSTMT, 5, SQL_C_LONG, &max_wait, sizeof(max_wait), &col_max_wait_len);
436
+ if (likely(netdata_mssql_check_result(ret))) {
437
+ netdata_MSSQL_error(SQL_HANDLE_STMT, mi->conn->dbWaitsSTMT, NETDATA_MSSQL_ODBC_PREPARE, mi->instanceID);
438
+ goto endwait;
439
+ }
440
+
441
+ ret =
442
+ SQLBindCol(mi->conn->dbWaitsSTMT, 6, SQL_C_LONG, &waiting_tasks, sizeof(waiting_tasks), &col_waiting_tasks_len);
443
+ if (likely(netdata_mssql_check_result(ret))) {
444
+ netdata_MSSQL_error(SQL_HANDLE_STMT, mi->conn->dbWaitsSTMT, NETDATA_MSSQL_ODBC_PREPARE, mi->instanceID);
445
+ goto endwait;
446
+ }
447
+
448
+ ret =
449
+ SQLBindCol(mi->conn->dbWaitsSTMT, 7, SQL_C_CHAR, wait_category, sizeof(wait_category), &col_wait_category_len);
450
+ if (likely(netdata_mssql_check_result(ret))) {
451
+ netdata_MSSQL_error(SQL_HANDLE_STMT, mi->conn->dbWaitsSTMT, NETDATA_MSSQL_ODBC_PREPARE, mi->instanceID);
452
+ goto endwait;
453
+ }
454
+
455
+ do {
456
+ ret = SQLFetch(mi->conn->dbWaitsSTMT);
457
+ switch (ret) {
458
+ case SQL_SUCCESS:
459
+ case SQL_SUCCESS_WITH_INFO:
460
+ break;
461
+ case SQL_NO_DATA:
462
+ default:
463
+ success = 1;
464
+ goto endwait;
465
+ }
466
+
467
+ struct mssql_db_waits *mdw = dictionary_set(mi->waits, wait_type, NULL, sizeof(*mdw));
468
+ if (!mdw)
469
+ continue;
470
+
471
+ mdw->MSSQLDatabaseTotalWait.current.Data = (ULONGLONG)total_wait;
472
+ // Variable mdw->MSSQLDatabaseResourceWaitMSec.current.Data stores a mathematical operation
473
+ // that can be negative sometimes. This is the reason we have this if
474
+ if (likely(resource_wait > mdw->MSSQLDatabaseResourceWaitMSec.current.Data))
475
+ mdw->MSSQLDatabaseResourceWaitMSec.current.Data = (ULONGLONG)resource_wait;
476
+ mdw->MSSQLDatabaseSignalWaitMSec.current.Data = (ULONGLONG)signal_wait;
477
+ mdw->MSSQLDatabaseMaxWaitTimeMSec.current.Data = (ULONGLONG)max_wait;
478
+ mdw->MSSQLDatabaseWaitingTasks.current.Data = (ULONGLONG)waiting_tasks;
479
+
480
+ if (unlikely(!mdw->wait_category))
481
+ mdw->wait_category = strdupz(wait_category);
482
+ } while (true);
483
+
484
+endwait:
485
+ netdata_MSSQL_release_results(mi->conn->dbWaitsSTMT);
486
+
487
+ return success;
488
+}
489
+
490
+int netdata_select_db(SQLHDBC hdbc, const char *database)
491
+{
492
+ SQLHSTMT hstmt;
493
+ SQLRETURN ret;
494
+
495
+ ret = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt);
496
+ if (likely(netdata_mssql_check_result(ret))) {
497
+ return -1;
498
+ }
499
+
500
+ char query[512];
501
+ snprintfz(query, sizeof(query), "USE %s", database);
502
+ ret = SQLExecDirect(hstmt, (SQLCHAR *)query, SQL_NTS);
503
+ int result = 0;
504
+ if (likely(netdata_mssql_check_result(ret))) {
505
+ result = -1;
506
+ }
507
+ SQLFreeHandle(SQL_HANDLE_STMT, hstmt);
508
+ return result;
509
+}
510
+
511
+void dict_mssql_fill_replication(struct mssql_db_instance *mdi)
512
+{
513
+ char publisher[NETDATA_MAX_INSTANCE_OBJECT + 1] = {};
514
+ char publisher_db[NETDATA_MAX_INSTANCE_OBJECT + 1] = {};
515
+ char publication[NETDATA_MAX_INSTANCE_OBJECT + 1] = {};
516
+ char key[NETDATA_MAX_INSTANCE_OBJECT * 2 + 2];
517
+ int type = 0, status = 0, warning = 0, avg_latency = 0, retention = 0, subscriptioncount = 0,
518
+ runningdistagentcount = 0, average_runspeedPerf = 0;
519
+ SQLLEN publisher_len = 0, publisherdb_len = 0, publication_len = 0, type_len = 0, status_len = 0, warning_len = 0,
520
+ avg_latency_len = 0, retention_len = 0, subscriptioncount_len = 0, runningagentcount_len = 0,
521
+ average_runspeedperf_len = 0;
522
+
523
+ if (likely(netdata_select_db(mdi->parent->conn->netdataSQLHDBc, NETDATA_REPLICATION_DB))) {
524
+ return;
525
+ }
526
+
527
+ SQLRETURN ret =
528
+ SQLExecDirect(mdi->parent->conn->dbReplicationPublisher, (SQLCHAR *)NETDATA_REPLICATION_MONITOR_QUERY, SQL_NTS);
529
+ if (likely(netdata_mssql_check_result(ret))) {
530
+ mdi->collecting_data = false;
531
+ netdata_MSSQL_error(
532
+ SQL_HANDLE_STMT,
533
+ mdi->parent->conn->dbReplicationPublisher,
534
+ NETDATA_MSSQL_ODBC_QUERY,
535
+ mdi->parent->instanceID);
536
+ goto endreplication;
537
+ }
538
+
539
+ ret = SQLBindCol(
540
+ mdi->parent->conn->dbReplicationPublisher, 1, SQL_C_CHAR, publisher_db, sizeof(publisher_db), &publisherdb_len);
541
+ if (likely(netdata_mssql_check_result(ret))) {
542
+ netdata_MSSQL_error(
543
+ SQL_HANDLE_STMT,
544
+ mdi->parent->conn->dbReplicationPublisher,
545
+ NETDATA_MSSQL_ODBC_PREPARE,
546
+ mdi->parent->instanceID);
547
+ goto endreplication;
548
+ }
549
+
550
+ ret = SQLBindCol(
551
+ mdi->parent->conn->dbReplicationPublisher, 2, SQL_C_CHAR, publication, sizeof(publication), &publication_len);
552
+ if (likely(netdata_mssql_check_result(ret))) {
553
+ netdata_MSSQL_error(
554
+ SQL_HANDLE_STMT,
555
+ mdi->parent->conn->dbReplicationPublisher,
556
+ NETDATA_MSSQL_ODBC_PREPARE,
557
+ mdi->parent->instanceID);
558
+ goto endreplication;
559
+ }
560
+
561
+ ret = SQLBindCol(mdi->parent->conn->dbReplicationPublisher, 4, SQL_C_LONG, &type, sizeof(type), &type_len);
562
+ if (likely(netdata_mssql_check_result(ret))) {
563
+ netdata_MSSQL_error(
564
+ SQL_HANDLE_STMT,
565
+ mdi->parent->conn->dbReplicationPublisher,
566
+ NETDATA_MSSQL_ODBC_PREPARE,
567
+ mdi->parent->instanceID);
568
+ goto endreplication;
569
+ }
570
+
571
+ ret = SQLBindCol(mdi->parent->conn->dbReplicationPublisher, 5, SQL_C_LONG, &status, sizeof(status), &status_len);
572
+ if (likely(netdata_mssql_check_result(ret))) {
573
+ netdata_MSSQL_error(
574
+ SQL_HANDLE_STMT,
575
+ mdi->parent->conn->dbReplicationPublisher,
576
+ NETDATA_MSSQL_ODBC_PREPARE,
577
+ mdi->parent->instanceID);
578
+ goto endreplication;
579
+ }
580
+
581
+ ret = SQLBindCol(mdi->parent->conn->dbReplicationPublisher, 6, SQL_C_LONG, &warning, sizeof(warning), &warning_len);
582
+ if (likely(netdata_mssql_check_result(ret))) {
583
+ netdata_MSSQL_error(
584
+ SQL_HANDLE_STMT,
585
+ mdi->parent->conn->dbReplicationPublisher,
586
+ NETDATA_MSSQL_ODBC_PREPARE,
587
+ mdi->parent->instanceID);
588
+ goto endreplication;
589
+ }
590
+
591
+ ret = SQLBindCol(
592
+ mdi->parent->conn->dbReplicationPublisher, 9, SQL_C_LONG, &avg_latency, sizeof(avg_latency), &avg_latency_len);
593
+ if (likely(netdata_mssql_check_result(ret))) {
594
+ // It is still a NULL value
595
+ avg_latency = 0;
596
+ }
597
+
598
+ ret = SQLBindCol(
599
+ mdi->parent->conn->dbReplicationPublisher, 11, SQL_C_LONG, &retention, sizeof(retention), &retention_len);
600
+ if (likely(netdata_mssql_check_result(ret))) {
601
+ netdata_MSSQL_error(
602
+ SQL_HANDLE_STMT,
603
+ mdi->parent->conn->dbReplicationPublisher,
604
+ NETDATA_MSSQL_ODBC_PREPARE,
605
+ mdi->parent->instanceID);
606
+ goto endreplication;
607
+ }
608
+
609
+ ret = SQLBindCol(
610
+ mdi->parent->conn->dbReplicationPublisher,
611
+ 15,
612
+ SQL_C_LONG,
613
+ &subscriptioncount,
614
+ sizeof(subscriptioncount),
615
+ &subscriptioncount_len);
616
+ if (likely(netdata_mssql_check_result(ret))) {
617
+ netdata_MSSQL_error(
618
+ SQL_HANDLE_STMT,
619
+ mdi->parent->conn->dbReplicationPublisher,
620
+ NETDATA_MSSQL_ODBC_PREPARE,
621
+ mdi->parent->instanceID);
622
+ goto endreplication;
623
+ }
624
+
625
+ ret = SQLBindCol(
626
+ mdi->parent->conn->dbReplicationPublisher,
627
+ 16,
628
+ SQL_C_LONG,
629
+ &runningdistagentcount,
630
+ sizeof(runningdistagentcount),
631
+ &runningagentcount_len);
632
+ if (likely(netdata_mssql_check_result(ret))) {
633
+ netdata_MSSQL_error(
634
+ SQL_HANDLE_STMT,
635
+ mdi->parent->conn->dbReplicationPublisher,
636
+ NETDATA_MSSQL_ODBC_PREPARE,
637
+ mdi->parent->instanceID);
638
+ goto endreplication;
639
+ }
640
+
641
+ ret = SQLBindCol(
642
+ mdi->parent->conn->dbReplicationPublisher,
643
+ 22,
644
+ SQL_C_LONG,
645
+ &average_runspeedPerf,
646
+ sizeof(average_runspeedPerf),
647
+ &average_runspeedperf_len);
648
+ if (likely(netdata_mssql_check_result(ret))) {
649
+ netdata_MSSQL_error(
650
+ SQL_HANDLE_STMT,
651
+ mdi->parent->conn->dbReplicationPublisher,
652
+ NETDATA_MSSQL_ODBC_PREPARE,
653
+ mdi->parent->instanceID);
654
+ goto endreplication;
655
+ }
656
+
657
+ ret = SQLBindCol(
658
+ mdi->parent->conn->dbReplicationPublisher, 24, SQL_C_CHAR, publisher, sizeof(publisher), &publisher_len);
659
+ if (likely(netdata_mssql_check_result(ret))) {
660
+ netdata_MSSQL_error(
661
+ SQL_HANDLE_STMT,
662
+ mdi->parent->conn->dbReplicationPublisher,
663
+ NETDATA_MSSQL_ODBC_PREPARE,
664
+ mdi->parent->instanceID);
665
+ goto endreplication;
666
+ }
667
+
668
+ do {
669
+ ret = SQLFetch(mdi->parent->conn->dbReplicationPublisher);
670
+ switch (ret) {
671
+ case SQL_SUCCESS:
672
+ case SQL_SUCCESS_WITH_INFO:
673
+ break;
674
+ case SQL_NO_DATA:
675
+ default:
676
+ goto endreplication;
677
+ }
678
+
679
+ snprintfz(key, sizeof(key) - 1, "%s:%s", publisher_db, publication);
680
+ struct mssql_publisher_publication *mpp =
681
+ dictionary_set(mdi->parent->publisher_publication, key, NULL, sizeof(*mpp));
682
+
683
+ if (unlikely(!mpp->publisher)) {
684
+ mpp->publisher = strdupz(publisher);
685
+ mpp->parent = mdi->parent;
686
+ }
687
+
688
+ if (unlikely(!mpp->publication))
689
+ mpp->publication = strdupz(publication);
690
+
691
+ if (unlikely(!mpp->db))
692
+ mpp->db = strdupz(publisher_db);
693
+
694
+ mpp->type = type;
695
+ mpp->status = status;
696
+ mpp->warning = warning;
697
+
698
+ mpp->avg_latency = avg_latency;
699
+
700
+ mpp->retention = retention;
701
+
702
+ mpp->subscriptioncount = subscriptioncount;
703
+ mpp->runningdistagentcount = runningdistagentcount;
704
+
705
+ mpp->average_runspeedPerf = average_runspeedPerf;
706
+ } while (true);
707
+
708
+endreplication:
709
+ (void)netdata_select_db(mdi->parent->conn->netdataSQLHDBc, "master");
710
+ netdata_MSSQL_release_results(mdi->parent->conn->dbReplicationPublisher);
711
+}
712
+int dict_mssql_databases_run_queries(const DICTIONARY_ITEM *item __maybe_unused, void *value, void *data __maybe_unused)
713
+{
714
+ struct mssql_db_instance *mdi = value;
715
+ const char *dbname = dictionary_acquired_item_name((DICTIONARY_ITEM *)item);
716
+
717
+ if (unlikely(!mdi->collecting_data || !mdi->parent || !mdi->parent->conn)) {
718
+ goto enddrunquery;
719
+ }
720
+
721
+ // We failed to collect this for the database, so we are not going to try again
722
+ if (unlikely(mdi->MSSQLDatabaseDataFileSize.current.Data != ULONG_LONG_MAX))
723
+ mdi->MSSQLDatabaseDataFileSize.current.Data = netdata_MSSQL_fill_long_value(
724
+ mdi->parent->conn->dataFileSizeSTMT, NETDATA_QUERY_DATA_FILE_SIZE_MASK, dbname, mdi->parent->instanceID);
725
+ else {
726
+ mdi->collecting_data = false;
727
+ goto enddrunquery;
728
+ }
729
+
730
+ dict_mssql_fill_transactions(mdi, dbname);
731
+ dict_mssql_fill_locks(mdi, dbname);
732
+
733
+ if (likely(mdi->running_replication))
734
+ dict_mssql_fill_replication(mdi);
735
+
736
+enddrunquery:
737
+ return 1;
738
+}
739
+
740
+long metdata_mssql_check_permission(struct mssql_instance *mi)
741
+{
742
+ static int next_try = NETDATA_MSSQL_NEXT_TRY - 1;
743
+ long perm = 0;
744
+ SQLLEN col_data_len = 0;
745
+
746
+ if (++next_try != NETDATA_MSSQL_NEXT_TRY)
747
+ return 1;
748
+
749
+ next_try = 0;
750
+
751
+ SQLRETURN ret;
752
+
753
+ ret = SQLExecDirect(mi->conn->checkPermSTMT, (SQLCHAR *)NETDATA_QUERY_CHECK_PERM, SQL_NTS);
754
+ if (likely(netdata_mssql_check_result(ret))) {
755
+ netdata_MSSQL_error(SQL_HANDLE_STMT, mi->conn->checkPermSTMT, NETDATA_MSSQL_ODBC_QUERY, mi->instanceID);
756
+ perm = LONG_MAX;
757
+ goto endperm;
758
+ }
759
+
760
+ ret = SQLBindCol(mi->conn->checkPermSTMT, 1, SQL_C_LONG, &perm, sizeof(perm), &col_data_len);
761
+
762
+ if (likely(netdata_mssql_check_result(ret))) {
763
+ netdata_MSSQL_error(SQL_HANDLE_STMT, mi->conn->checkPermSTMT, NETDATA_MSSQL_ODBC_PREPARE, mi->instanceID);
764
+ perm = LONG_MAX;
765
+ goto endperm;
766
+ }
767
+
768
+ ret = SQLFetch(mi->conn->checkPermSTMT);
769
+ if (likely(netdata_mssql_check_result(ret))) {
770
+ netdata_MSSQL_error(SQL_HANDLE_STMT, mi->conn->checkPermSTMT, NETDATA_MSSQL_ODBC_FETCH, mi->instanceID);
771
+ perm = LONG_MAX;
772
+ goto endperm;
773
+ }
774
+
775
+endperm:
776
+ netdata_MSSQL_release_results(mi->conn->checkPermSTMT);
777
+ return perm;
778
+}
779
+
780
+void metdata_mssql_fill_mssql_status(struct mssql_instance *mi)
781
+{
782
+ char dbname[SQLSERVER_MAX_NAME_LENGTH + 1];
783
+ int readonly = 0;
784
+ BYTE state = 0;
785
+ SQLLEN col_data_len = 0;
786
+
787
+ static int next_try = NETDATA_MSSQL_NEXT_TRY - 1;
788
+
789
+ if (unlikely(++next_try != NETDATA_MSSQL_NEXT_TRY))
790
+ return;
791
+
792
+ next_try = 0;
793
+
794
+ SQLRETURN ret;
795
+
796
+ ret = SQLExecDirect(mi->conn->dbSQLState, (SQLCHAR *)NETDATA_QUERY_DATABASE_STATUS, SQL_NTS);
797
+ if (likely(netdata_mssql_check_result(ret))) {
798
+ netdata_MSSQL_error(SQL_HANDLE_STMT, mi->conn->dbSQLState, NETDATA_MSSQL_ODBC_QUERY, mi->instanceID);
799
+ goto enddbstate;
800
+ }
801
+
802
+ ret = SQLBindCol(mi->conn->dbSQLState, 1, SQL_C_TINYINT, &state, sizeof(state), &col_data_len);
803
+ if (likely(netdata_mssql_check_result(ret))) {
804
+ netdata_MSSQL_error(SQL_HANDLE_STMT, mi->conn->dbSQLState, NETDATA_MSSQL_ODBC_PREPARE, mi->instanceID);
805
+ goto enddbstate;
806
+ }
807
+
808
+ ret = SQLBindCol(mi->conn->dbSQLState, 3, SQL_C_BIT, &readonly, sizeof(readonly), &col_data_len);
809
+ if (likely(netdata_mssql_check_result(ret))) {
810
+ netdata_MSSQL_error(SQL_HANDLE_STMT, mi->conn->dbWaitsSTMT, NETDATA_MSSQL_ODBC_PREPARE, mi->instanceID);
811
+ goto enddbstate;
812
+ }
813
+
814
+ do {
815
+ ret = SQLFetch(mi->conn->dbSQLState);
816
+ if (likely(netdata_mssql_check_result(ret))) {
817
+ goto enddbstate;
818
+ }
819
+
820
+ struct mssql_db_instance *mdi = dictionary_set(mi->databases, dbname, NULL, sizeof(*mdi));
821
+ if (unlikely(!mdi))
822
+ continue;
823
+
824
+ mdi->MSSQLDBState.current.Data = (ULONGLONG)state;
825
+ mdi->MSSQLDBIsReadonly.current.Data = (ULONGLONG)readonly;
826
+ } while (true);
827
+
828
+enddbstate:
829
+ netdata_MSSQL_release_results(mi->conn->dbSQLState);
830
+}
831
+
832
+void metdata_mssql_fill_job_status(struct mssql_instance *mi)
833
+{
834
+ char job[SQLSERVER_MAX_NAME_LENGTH + 1];
835
+ BYTE state = 0;
836
+ SQLLEN col_job_len = 0;
837
+ SQLLEN col_state_len = 0;
838
+
839
+ static int next_try = NETDATA_MSSQL_NEXT_TRY - 1;
840
+
841
+ if (unlikely(++next_try != NETDATA_MSSQL_NEXT_TRY))
842
+ return;
843
+
844
+ next_try = 0;
845
+
846
+ SQLRETURN ret;
847
+
848
+ ret = SQLExecDirect(mi->conn->dbSQLJobs, (SQLCHAR *)NETDATA_QUERY_JOBS_STATUS, SQL_NTS);
849
+ if (likely(netdata_mssql_check_result(ret))) {
850
+ netdata_MSSQL_error(SQL_HANDLE_STMT, mi->conn->dbSQLJobs, NETDATA_MSSQL_ODBC_QUERY, mi->instanceID);
851
+ goto enddbjobs;
852
+ }
853
+
854
+ ret = SQLBindCol(mi->conn->dbSQLJobs, 1, SQL_C_CHAR, job, sizeof(job), &col_job_len);
855
+ if (likely(netdata_mssql_check_result(ret))) {
856
+ netdata_MSSQL_error(SQL_HANDLE_STMT, mi->conn->dbSQLJobs, NETDATA_MSSQL_ODBC_PREPARE, mi->instanceID);
857
+ goto enddbjobs;
858
+ }
859
+
860
+ ret = SQLBindCol(mi->conn->dbSQLJobs, 2, SQL_C_TINYINT, &state, sizeof(state), &col_state_len);
861
+ if (likely(netdata_mssql_check_result(ret))) {
862
+ netdata_MSSQL_error(SQL_HANDLE_STMT, mi->conn->dbSQLJobs, NETDATA_MSSQL_ODBC_PREPARE, mi->instanceID);
863
+ goto enddbjobs;
864
+ }
865
+
866
+ do {
867
+ ret = SQLFetch(mi->conn->dbSQLJobs);
868
+ if (likely(netdata_mssql_check_result(ret))) {
869
+ goto enddbjobs;
870
+ }
871
+
872
+ struct mssql_db_jobs *mdj = dictionary_set(mi->sysjobs, job, NULL, sizeof(*mdj));
873
+ if (unlikely(!mdj))
874
+ continue;
875
+
876
+ mdj->MSSQLJOBState.current.Data = (ULONGLONG)state;
877
+ } while (true);
878
+
879
+enddbjobs:
880
+ netdata_MSSQL_release_results(mi->conn->dbSQLJobs);
881
+}
882
+
883
+void metdata_mssql_fill_dictionary_from_db(struct mssql_instance *mi)
884
+{
885
+ char dbname[SQLSERVER_MAX_NAME_LENGTH + 1];
886
+ SQLLEN col_data_len = 0;
887
+
888
+ static int next_try = NETDATA_MSSQL_NEXT_TRY - 1;
889
+
890
+ if (unlikely(++next_try != NETDATA_MSSQL_NEXT_TRY))
891
+ return;
892
+
893
+ next_try = 0;
894
+
895
+ SQLRETURN ret;
896
+
897
+ ret = SQLExecDirect(mi->conn->databaseListSTMT, (SQLCHAR *)NETDATA_QUERY_LIST_DB, SQL_NTS);
898
+ if (likely(netdata_mssql_check_result(ret))) {
899
+ netdata_MSSQL_error(SQL_HANDLE_STMT, mi->conn->databaseListSTMT, NETDATA_MSSQL_ODBC_QUERY, mi->instanceID);
900
+ goto enddblist;
901
+ }
902
+
903
+ ret = SQLBindCol(mi->conn->databaseListSTMT, 1, SQL_C_CHAR, dbname, sizeof(dbname), &col_data_len);
904
+
905
+ if (likely(netdata_mssql_check_result(ret))) {
906
+ netdata_MSSQL_error(SQL_HANDLE_STMT, mi->conn->databaseListSTMT, NETDATA_MSSQL_ODBC_PREPARE, mi->instanceID);
907
+ goto enddblist;
908
+ }
909
+
910
+ int i = 0;
911
+ do {
912
+ ret = SQLFetch(mi->conn->databaseListSTMT);
913
+ if (likely(netdata_mssql_check_result(ret))) {
914
+ goto enddblist;
915
+ }
916
+
917
+ struct mssql_db_instance *mdi = dictionary_set(mi->databases, dbname, NULL, sizeof(*mdi));
918
+ if (!mdi)
919
+ continue;
920
+
921
+ mdi->updated = 0;
922
+ if (unlikely(!mdi->parent)) {
923
+ mdi->parent = mi;
924
+ }
925
+
926
+ if (mi->conn && !strncmp(dbname, NETDATA_REPLICATION_DB, sizeof(NETDATA_REPLICATION_DB) - 1)) {
927
+ mdi->running_replication = true;
928
+ }
929
+
930
+ if (unlikely(!i)) {
931
+ mdi->collect_instance = true;
932
+ }
933
+ } while (true);
934
+
935
+enddblist:
936
+ netdata_MSSQL_release_results(mi->conn->databaseListSTMT);
937
+}
938
+
939
+static bool netdata_MSSQL_initialize_connection(struct netdata_mssql_conn *nmc)
940
+{
941
+ SQLRETURN ret;
942
+ if (unlikely(!nmc->netdataSQLEnv)) {
943
+ ret = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &nmc->netdataSQLEnv);
944
+ if (likely(netdata_mssql_check_result(ret)))
945
+ return FALSE;
946
+
947
+ ret = SQLSetEnvAttr(nmc->netdataSQLEnv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3, 0);
948
+ if (likely(netdata_mssql_check_result(ret))) {
949
+ return FALSE;
950
+ }
951
+ }
952
+
953
+ ret = SQLAllocHandle(SQL_HANDLE_DBC, nmc->netdataSQLEnv, &nmc->netdataSQLHDBc);
954
+ if (likely(netdata_mssql_check_result(ret))) {
955
+ return FALSE;
956
+ }
957
+
958
+ ret = SQLSetConnectAttr(nmc->netdataSQLHDBc, SQL_LOGIN_TIMEOUT, (SQLPOINTER)5, 0);
959
+ if (likely(netdata_mssql_check_result(ret))) {
960
+ return FALSE;
961
+ }
962
+
963
+ ret = SQLSetConnectAttr(nmc->netdataSQLHDBc, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER)TRUE, 0);
964
+ if (likely(netdata_mssql_check_result(ret))) {
965
+ return FALSE;
966
+ }
967
+
968
+ SQLCHAR ret_conn_str[1024];
969
+ ret = SQLDriverConnect(
970
+ nmc->netdataSQLHDBc, NULL, nmc->connectionString, SQL_NTS, ret_conn_str, 1024, NULL, SQL_DRIVER_NOPROMPT);
971
+
972
+ BOOL retConn;
973
+ switch (ret) {
974
+ case SQL_NO_DATA_FOUND:
975
+ case SQL_INVALID_HANDLE:
976
+ case SQL_ERROR:
977
+ default:
978
+ netdata_MSSQL_error(SQL_HANDLE_DBC, nmc->netdataSQLHDBc, NETDATA_MSSQL_ODBC_CONNECT, NULL);
979
+ retConn = FALSE;
980
+ break;
981
+ case SQL_SUCCESS:
982
+ case SQL_SUCCESS_WITH_INFO:
983
+ retConn = TRUE;
984
+ break;
985
+ }
986
+
987
+ if (likely(retConn)) {
988
+ SQLSetConnectAttr(nmc->netdataSQLHDBc, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER)SQL_AUTOCOMMIT_ON, 0);
989
+
990
+ ret = SQLAllocHandle(SQL_HANDLE_STMT, nmc->netdataSQLHDBc, &nmc->checkPermSTMT);
991
+ if (likely(netdata_mssql_check_result(ret))) {
992
+ retConn = FALSE;
993
+ goto endMSSQLInitializationConnection;
994
+ }
995
+
996
+ ret = SQLAllocHandle(SQL_HANDLE_STMT, nmc->netdataSQLHDBc, &nmc->databaseListSTMT);
997
+ if (likely(netdata_mssql_check_result(ret))) {
998
+ retConn = FALSE;
999
+ goto endMSSQLInitializationConnection;
1000
+ }
1001
+
1002
+ ret = SQLAllocHandle(SQL_HANDLE_STMT, nmc->netdataSQLHDBc, &nmc->dataFileSizeSTMT);
1003
+ if (likely(netdata_mssql_check_result(ret))) {
1004
+ retConn = FALSE;
1005
+ goto endMSSQLInitializationConnection;
1006
+ }
1007
+
1008
+ ret = SQLAllocHandle(SQL_HANDLE_STMT, nmc->netdataSQLHDBc, &nmc->dbTransactionSTMT);
1009
+ if (likely(netdata_mssql_check_result(ret))) {
1010
+ retConn = FALSE;
1011
+ goto endMSSQLInitializationConnection;
1012
+ }
1013
+
1014
+ ret = SQLAllocHandle(SQL_HANDLE_STMT, nmc->netdataSQLHDBc, &nmc->dbInstanceTransactionSTMT);
1015
+ if (likely(netdata_mssql_check_result(ret))) {
1016
+ retConn = FALSE;
1017
+ goto endMSSQLInitializationConnection;
1018
+ }
1019
+
1020
+ ret = SQLAllocHandle(SQL_HANDLE_STMT, nmc->netdataSQLHDBc, &nmc->dbLocksSTMT);
1021
+ if (likely(netdata_mssql_check_result(ret))) {
1022
+ retConn = FALSE;
1023
+ goto endMSSQLInitializationConnection;
1024
+ }
1025
+
1026
+ ret = SQLAllocHandle(SQL_HANDLE_STMT, nmc->netdataSQLHDBc, &nmc->dbWaitsSTMT);
1027
+ if (likely(netdata_mssql_check_result(ret))) {
1028
+ retConn = FALSE;
1029
+ goto endMSSQLInitializationConnection;
1030
+ }
1031
+
1032
+ ret = SQLAllocHandle(SQL_HANDLE_STMT, nmc->netdataSQLHDBc, &nmc->dbSQLState);
1033
+ if (likely(netdata_mssql_check_result(ret))) {
1034
+ retConn = FALSE;
1035
+ goto endMSSQLInitializationConnection;
1036
+ }
1037
+
1038
+ ret = SQLAllocHandle(SQL_HANDLE_STMT, nmc->netdataSQLHDBc, &nmc->dbSQLJobs);
1039
+ if (likely(netdata_mssql_check_result(ret))) {
1040
+ retConn = FALSE;
1041
+ goto endMSSQLInitializationConnection;
1042
+ }
1043
+
1044
+ ret = SQLAllocHandle(SQL_HANDLE_STMT, nmc->netdataSQLHDBc, &nmc->dbReplicationPublisher);
1045
+ if (likely(netdata_mssql_check_result(ret))) {
1046
+ retConn = FALSE;
1047
+ goto endMSSQLInitializationConnection;
1048
+ }
1049
+ }
1050
+
1051
+endMSSQLInitializationConnection:
1052
+ return retConn;
1053
+}
1054
+
1055
+// Dictionary
1056
+static DICTIONARY *mssql_instances = NULL;
1057
+
1058
+static void initialize_mssql_objects(struct mssql_instance *mi, const char *instance)
1059
+{
1060
+ char prefix[NETDATA_MAX_INSTANCE_NAME];
1061
+ if (unlikely(!strcmp(instance, "MSSQLSERVER"))) {
1062
+ strncpyz(prefix, "SQLServer:", sizeof(prefix) - 1);
1063
+ } else if (unlikely(!strcmp(instance, "SQLEXPRESS"))) {
1064
+ strncpyz(prefix, "MSSQL$SQLEXPRESS:", sizeof(prefix) - 1);
1065
+ if (mi->conn)
1066
+ mi->conn->is_sqlexpress = true;
1067
+ } else {
1068
+ char *express = (mi->conn && mi->conn->is_sqlexpress) ? "SQLEXPRESS:" : "";
1069
+ snprintfz(prefix, sizeof(prefix) - 1, "MSSQL$%s%s:", express, instance);
1070
+ }
1071
+
1072
+ size_t length = strlen(prefix);
1073
+ char name[NETDATA_MAX_INSTANCE_OBJECT];
1074
+ snprintfz(name, sizeof(name) - 1, "%s%s", prefix, "General Statistics");
1075
+ mi->objectName[NETDATA_MSSQL_GENERAL_STATS] = strdupz(name);
1076
+
1077
+ strncpyz(&name[length], "SQL Errors", sizeof(name) - length);
1078
+ mi->objectName[NETDATA_MSSQL_SQL_ERRORS] = strdupz(name);
1079
+
1080
+ strncpyz(&name[length], "Databases", sizeof(name) - length);
1081
+ mi->objectName[NETDATA_MSSQL_DATABASE] = strdupz(name);
1082
+
1083
+ strncpyz(&name[length], "SQL Statistics", sizeof(name) - length);
1084
+ mi->objectName[NETDATA_MSSQL_SQL_STATS] = strdupz(name);
1085
+
1086
+ strncpyz(&name[length], "Buffer Manager", sizeof(name) - length);
1087
+ mi->objectName[NETDATA_MSSQL_BUFFER_MANAGEMENT] = strdupz(name);
1088
+
1089
+ strncpyz(&name[length], "SystemJobs", sizeof(name) - length);
1090
+ mi->objectName[NETDATA_MSSQL_JOBS] = strdupz(name);
1091
+
1092
+ strncpyz(&name[length], "Memory Manager", sizeof(name) - length);
1093
+ mi->objectName[NETDATA_MSSQL_MEMORY] = strdupz(name);
1094
+
1095
+ strncpyz(&name[length], "Locks", sizeof(name) - length);
1096
+ mi->objectName[NETDATA_MSSQL_LOCKS] = strdupz(name);
1097
+
1098
+ strncpyz(&name[length], "Wait Statistics", sizeof(name) - length);
1099
+ mi->objectName[NETDATA_MSSQL_WAITS] = strdupz(name);
1100
+
1101
+ strncpyz(&name[length], "Access Methods", sizeof(name) - length);
1102
+ mi->objectName[NETDATA_MSSQL_ACCESS_METHODS] = strdupz(name);
1103
+
1104
+ mi->instanceID = strdupz(instance);
1105
+}
1106
+
1107
+static inline void initialize_mssql_keys(struct mssql_instance *mi)
1108
+{
1109
+ // General Statistics (https://learn.microsoft.com/en-us/sql/relational-databases/performance-monitor/sql-server-general-statistics-object)
1110
+ mi->MSSQLUserConnections.key = "User Connections";
1111
+ mi->MSSQLBlockedProcesses.key = "Processes blocked";
1112
+
1113
+ // SQL Statistics (https://learn.microsoft.com/en-us/sql/relational-databases/performance-monitor/sql-server-sql-statistics-object)
1114
+ mi->MSSQLStatsAutoParameterization.key = "Auto-Param Attempts/sec";
1115
+ mi->MSSQLStatsBatchRequests.key = "Batch Requests/sec";
1116
+ mi->MSSQLStatSafeAutoParameterization.key = "Safe Auto-Params/sec";
1117
+
1118
+ // Access Methods (https://learn.microsoft.com/en-us/sql/relational-databases/performance-monitor/sql-server-access-methods-object)
1119
+ mi->MSSQLAccessMethodPageSplits.key = "Page Splits/sec";
1120
+
1121
+ // Errors (https://learn.microsoft.com/en-us/sql/relational-databases/performance-monitor/sql-server-sql-errors-object)
1122
+ mi->MSSQLSQLErrorsTotal.key = "Errors/sec";
1123
+
1124
+ // Memory Management (https://learn.microsoft.com/en-us/sql/relational-databases/performance-monitor/sql-server-memory-manager-object)
1125
+ mi->MSSQLConnectionMemoryBytes.key = "Connection Memory (KB)";
1126
+ mi->MSSQLExternalBenefitOfMemory.key = "External benefit of memory";
1127
+ mi->MSSQLPendingMemoryGrants.key = "Memory Grants Pending";
1128
+ mi->MSSQLTotalServerMemory.key = "Total Server Memory (KB)";
1129
+}
1130
+
1131
+void dict_mssql_insert_locks_cb(const DICTIONARY_ITEM *item __maybe_unused, void *value, void *data __maybe_unused)
1132
+{
1133
+ const char *resource = dictionary_acquired_item_name((DICTIONARY_ITEM *)item);
1134
+
1135
+ // https://learn.microsoft.com/en-us/sql/relational-databases/performance-monitor/sql-server-locks-object
1136
+ struct mssql_lock_instance *ptr = value;
1137
+ ptr->resourceID = strdupz(resource);
1138
+ ptr->deadLocks.key = "Number of Deadlocks/sec";
1139
+ ptr->lockWait.key = "Lock Waits/sec";
1140
+}
1141
+
1142
+void dict_mssql_insert_wait_cb(const DICTIONARY_ITEM *item __maybe_unused, void *value, void *data __maybe_unused)
1143
+{
1144
+ const char *type = dictionary_acquired_item_name((DICTIONARY_ITEM *)item);
1145
+
1146
+ struct mssql_db_waits *mdw = value;
1147
+
1148
+ mdw->wait_type = strdupz(type);
1149
+ mdw->wait_category = NULL;
1150
+ mdw->rd_total_wait = mdw->rd_max_wait_time_msec = mdw->rd_resource_wait_msec = mdw->rd_signal_wait_msec =
1151
+ mdw->rd_waiting_tasks = NULL;
1152
+}
1153
+
1154
+void dict_mssql_insert_databases_cb(const DICTIONARY_ITEM *item __maybe_unused, void *value, void *data __maybe_unused)
1155
+{
1156
+ struct mssql_db_instance *mdi = value;
1157
+
1158
+ mdi->collecting_data = true;
1159
+}
1160
+
1161
+void dict_mssql_insert_replication_cb(const DICTIONARY_ITEM *item __maybe_unused, void *value, void *data __maybe_unused)
1162
+{
1163
+ UNUSED(value);
1164
+}
1165
+
1166
+void dict_mssql_insert_jobs_cb(const DICTIONARY_ITEM *item __maybe_unused, void *value, void *data __maybe_unused)
1167
+{
1168
+ UNUSED(value);
1169
+}
1170
+
1171
+// Options
1172
+void netdata_mount_mssql_connection_string(struct netdata_mssql_conn *dbInput)
1173
+{
1174
+ SQLCHAR conn[1024];
1175
+ const char *serverAddress;
1176
+ const char *serverAddressArg;
1177
+ if (unlikely(!dbInput)) {
1178
+ return;
1179
+ }
1180
+
1181
+ char auth[512];
1182
+ if (likely(dbInput->server && dbInput->address)) {
1183
+ nd_log(
1184
+ NDLS_COLLECTORS,
1185
+ NDLP_ERR,
1186
+ "Collector is not expecting server and address defined together, please, select one of them.");
1187
+ dbInput->connectionString = NULL;
1188
+ return;
1189
+ }
1190
+
1191
+ if (likely(dbInput->server)) {
1192
+ serverAddress = "Server";
1193
+ serverAddressArg = dbInput->server;
1194
+ } else {
1195
+ serverAddressArg = "Address";
1196
+ serverAddress = dbInput->address;
1197
+ }
1198
+
1199
+ if (likely(dbInput->windows_auth))
1200
+ snprintfz(auth, sizeof(auth) - 1, "Trusted_Connection = yes");
1201
+ else if (unlikely(!dbInput->username || !dbInput->password)) {
1202
+ nd_log(
1203
+ NDLS_COLLECTORS,
1204
+ NDLP_ERR,
1205
+ "You are not using Windows Authentication. Thus, it is necessary to specify user and password.");
1206
+ dbInput->connectionString = NULL;
1207
+ return;
1208
+ } else {
1209
+ snprintfz(auth, sizeof(auth) - 1, "UID=%s;PWD=%s;", dbInput->username, dbInput->password);
1210
+ }
1211
+
1212
+ snprintfz(
1213
+ (char *)conn, sizeof(conn) - 1, "Driver={%s};%s=%s;%s", dbInput->driver, serverAddress, serverAddressArg, auth);
1214
+ dbInput->connectionString = (SQLCHAR *)strdupz((char *)conn);
1215
+}
1216
+
1217
+static void netdata_read_config_options()
1218
+{
1219
+#define NETDATA_MAX_MSSSQL_SECTION_LENGTH (40)
1220
+#define NETDATA_DEFAULT_MSSQL_SECTION "plugin:windows:PerflibMSSQL"
1221
+ uint16_t expected_instances = 1;
1222
+ uint16_t total_instances = 0;
1223
+ for (; total_instances < expected_instances; total_instances++) {
1224
+ char section_name[NETDATA_MAX_MSSSQL_SECTION_LENGTH + 1];
1225
+ char upper_instance[NETDATA_MAX_INSTANCE_OBJECT + 1];
1226
+ strncpyz(section_name, NETDATA_DEFAULT_MSSQL_SECTION, sizeof(NETDATA_DEFAULT_MSSQL_SECTION));
1227
+ if (likely(total_instances)) {
1228
+ snprintfz(§ion_name[sizeof(NETDATA_DEFAULT_MSSQL_SECTION) - 1], 5, "%d", total_instances);
1229
+ }
1230
+ const char *instance = inicfg_get(&netdata_config, section_name, "instance", NULL);
1231
+ int additional_instances = (int)inicfg_get_number(&netdata_config, section_name, "additional instances", 0);
1232
+ if (!instance || strlen(instance) > NETDATA_MAX_INSTANCE_OBJECT) {
1233
+ nd_log(
1234
+ NDLS_COLLECTORS,
1235
+ NDLP_ERR,
1236
+ "You must specify a valid 'instance' name to collect data from database in section %s.",
1237
+ section_name);
1238
+ continue;
1239
+ }
1240
+
1241
+ if (!total_instances && additional_instances) {
1242
+ if (additional_instances > 64) {
1243
+ nd_log(NDLS_COLLECTORS, NDLP_ERR, "Number of instances is bigger than expected (64)");
1244
+ expected_instances = 64;
1245
+ }
1246
+ expected_instances = additional_instances + 1;
1247
+ }
1248
+
1249
+ const char *move = instance;
1250
+ int i;
1251
+ for (i = 0; *move; move++, i++) {
1252
+ upper_instance[i] = toupper(*move);
1253
+ }
1254
+ upper_instance[i] = '\0';
1255
+
1256
+ struct netdata_mssql_conn *dbconn = dictionary_set(conn_options, upper_instance, NULL, sizeof(*dbconn));
1257
+
1258
+ dbconn->instance = strdupz(upper_instance);
1259
+ dbconn->driver = inicfg_get(&netdata_config, section_name, "driver", "SQL Server");
1260
+ dbconn->server = inicfg_get(&netdata_config, section_name, "server", NULL);
1261
+ dbconn->address = inicfg_get(&netdata_config, section_name, "address", NULL);
1262
+ dbconn->username = inicfg_get(&netdata_config, section_name, "uid", NULL);
1263
+ dbconn->password = inicfg_get(&netdata_config, section_name, "pwd", NULL);
1264
+ dbconn->instances = additional_instances;
1265
+ dbconn->windows_auth = inicfg_get_boolean(&netdata_config, section_name, "windows authentication", false);
1266
+ dbconn->is_sqlexpress = inicfg_get_boolean(&netdata_config, section_name, "express", false);
1267
+ dbconn->is_connected = FALSE;
1268
+
1269
+ netdata_mount_mssql_connection_string(dbconn);
1270
+ }
1271
+}
1272
+
1273
+static inline struct netdata_mssql_conn *netdata_mssql_get_conn_option(const char *instance)
1274
+{
1275
+ return (struct netdata_mssql_conn *)dictionary_get(conn_options, instance);
1276
+}
1277
+
1278
+void mssql_fill_initial_instances(struct mssql_instance *mi)
1279
+{
1280
+ // https://learn.microsoft.com/en-us/sql/relational-databases/performance-monitor/sql-server-locks-object?view=sql-server-ver17
1281
+ char *keys[] = {
1282
+ "AllocUnit",
1283
+ "Application",
1284
+ "Database",
1285
+ "Extent",
1286
+ "File",
1287
+ "HoBT",
1288
+ "Key",
1289
+ "Metadata",
1290
+ "OIB",
1291
+ "Object",
1292
+ "Page",
1293
+ "RID",
1294
+ "RowGroup",
1295
+ "Xact",
1296
+ NULL};
1297
+ for (int i = 0; keys[i]; i++) {
1298
+ (void)dictionary_set(mi->locks_instances, keys[i], NULL, sizeof(struct mssql_lock_instance));
1299
+ }
1300
+}
1301
+
1302
+void dict_mssql_insert_cb(const DICTIONARY_ITEM *item __maybe_unused, void *value, void *data __maybe_unused)
1303
+{
1304
+ struct mssql_instance *mi = value;
1305
+ const char *instance = dictionary_acquired_item_name((DICTIONARY_ITEM *)item);
1306
+ bool *create_thread = data;
1307
+
1308
+ if (unlikely(!mi->locks_instances)) {
1309
+ mi->locks_instances = dictionary_create_advanced(
1310
+ DICT_OPTION_DONT_OVERWRITE_VALUE | DICT_OPTION_FIXED_SIZE, NULL, sizeof(struct mssql_lock_instance));
1311
+ dictionary_register_insert_callback(mi->locks_instances, dict_mssql_insert_locks_cb, NULL);
1312
+ mssql_fill_initial_instances(mi);
1313
+ }
1314
+
1315
+ if (unlikely(!mi->databases)) {
1316
+ mi->databases = dictionary_create_advanced(
1317
+ DICT_OPTION_DONT_OVERWRITE_VALUE | DICT_OPTION_FIXED_SIZE, NULL, sizeof(struct mssql_db_instance));
1318
+ dictionary_register_insert_callback(mi->databases, dict_mssql_insert_databases_cb, NULL);
1319
+ }
1320
+
1321
+ if (unlikely(!mi->publisher_publication)) {
1322
+ mi->publisher_publication = dictionary_create_advanced(
1323
+ DICT_OPTION_DONT_OVERWRITE_VALUE | DICT_OPTION_FIXED_SIZE,
1324
+ NULL,
1325
+ sizeof(struct mssql_publisher_publication));
1326
+ dictionary_register_insert_callback(mi->publisher_publication, dict_mssql_insert_replication_cb, NULL);
1327
+ }
1328
+
1329
+ if (unlikely(!mi->sysjobs)) {
1330
+ mi->sysjobs = dictionary_create_advanced(
1331
+ DICT_OPTION_DONT_OVERWRITE_VALUE | DICT_OPTION_FIXED_SIZE, NULL, sizeof(struct mssql_db_jobs));
1332
+ dictionary_register_insert_callback(mi->sysjobs, dict_mssql_insert_jobs_cb, NULL);
1333
+ }
1334
+
1335
+ if (unlikely(!mi->waits)) {
1336
+ mi->waits = dictionary_create_advanced(
1337
+ DICT_OPTION_DONT_OVERWRITE_VALUE | DICT_OPTION_FIXED_SIZE, NULL, sizeof(struct mssql_db_waits));
1338
+ dictionary_register_insert_callback(mi->waits, dict_mssql_insert_wait_cb, NULL);
1339
+ }
1340
+
1341
+ initialize_mssql_objects(mi, instance);
1342
+ initialize_mssql_keys(mi);
1343
+ mi->conn = netdata_mssql_get_conn_option(instance);
1344
+
1345
+ if (likely(mi->conn && mi->conn->connectionString)) {
1346
+ mi->conn->is_connected = netdata_MSSQL_initialize_connection(mi->conn);
1347
+ if (mi->conn->is_connected)
1348
+ *create_thread = true;
1349
+ }
1350
+}
1351
+
1352
+void dict_mssql_insert_conn_option(const DICTIONARY_ITEM *item __maybe_unused, void *value, void *data __maybe_unused)
1353
+{
1354
+ ;
1355
+}
1356
+
1357
+static void mssql_fill_dictionary(int update_every)
1358
+{
1359
+ HKEY hKey;
1360
+ LSTATUS ret = RegOpenKeyExA(
1361
+ HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Microsoft SQL Server\\Instance Names\\SQL", 0, KEY_READ, &hKey);
1362
+ if (ret != ERROR_SUCCESS)
1363
+ return;
1364
+
1365
+ DWORD values = 0;
1366
+
1367
+ ret = RegQueryInfoKey(hKey, NULL, NULL, NULL, NULL, NULL, NULL, &values, NULL, NULL, NULL, NULL);
1368
+ if (likely(ret != ERROR_SUCCESS)) {
1369
+ goto endMSSQLFillDict;
1370
+ }
1371
+
1372
+ if (unlikely(!values)) {
1373
+ ret = ERROR_PATH_NOT_FOUND;
1374
+ goto endMSSQLFillDict;
1375
+ }
1376
+
1377
+// https://learn.microsoft.com/en-us/windows/win32/sysinfo/enumerating-registry-subkeys
1378
+#define REGISTRY_MAX_VALUE 16383
1379
+
1380
+ DWORD i;
1381
+ char avalue[REGISTRY_MAX_VALUE] = {'\0'};
1382
+ for (i = 0; i < values; i++) {
1383
+ avalue[0] = '\0';
1384
+ DWORD length = REGISTRY_MAX_VALUE;
1385
+
1386
+ ret = RegEnumValue(hKey, i, avalue, &length, NULL, NULL, NULL, NULL);
1387
+ if (likely(ret != ERROR_SUCCESS))
1388
+ continue;
1389
+
1390
+ struct mssql_instance *p = dictionary_set(mssql_instances, avalue, NULL, sizeof(*p));
1391
+ p->update_every = update_every;
1392
+ }
1393
+
1394
+endMSSQLFillDict:
1395
+ RegCloseKey(hKey);
1396
+}
1397
+
1398
+int netdata_mssql_reset_value(const DICTIONARY_ITEM *item __maybe_unused, void *value, void *data __maybe_unused)
1399
+{
1400
+ struct mssql_db_instance *mdi = value;
1401
+
1402
+ mdi->collecting_data = false;
1403
+
1404
+ return 1;
1405
+}
1406
+
1407
+int dict_mssql_query_cb(const DICTIONARY_ITEM *item __maybe_unused, void *value, void *data __maybe_unused)
1408
+{
1409
+ struct mssql_instance *mi = value;
1410
+ static long collecting = 1;
1411
+
1412
+ if (likely(mi->conn && mi->conn->is_connected && collecting)) {
1413
+ collecting = metdata_mssql_check_permission(mi);
1414
+ if (!collecting) {
1415
+ nd_log(
1416
+ NDLS_COLLECTORS,
1417
+ NDLP_ERR,
1418
+ "User %s does not have permission to run queries on %s",
1419
+ mi->conn->username,
1420
+ mi->instanceID);
1421
+ } else {
1422
+ metdata_mssql_fill_dictionary_from_db(mi);
1423
+ metdata_mssql_fill_mssql_status(mi);
1424
+ metdata_mssql_fill_job_status(mi);
1425
+ dictionary_sorted_walkthrough_read(mi->databases, dict_mssql_databases_run_queries, NULL);
1426
+ }
1427
+
1428
+ collecting = dict_mssql_fill_waits(mi);
1429
+ } else {
1430
+ dictionary_sorted_walkthrough_read(mi->databases, netdata_mssql_reset_value, NULL);
1431
+ }
1432
+
1433
+ return 1;
1434
+}
1435
+
1436
+static void netdata_mssql_queries(void *ptr __maybe_unused)
1437
+{
1438
+ heartbeat_t hb;
1439
+ heartbeat_init(&hb, USEC_PER_SEC);
1440
+ int update_every = UPDATE_EVERY_MIN;
1441
+
1442
+ while (service_running(SERVICE_COLLECTORS)) {
1443
+ (void)heartbeat_next(&hb);
1444
+
1445
+ if (unlikely(!service_running(SERVICE_COLLECTORS)))
1446
+ break;
1447
+
1448
+ dictionary_sorted_walkthrough_read(mssql_instances, dict_mssql_query_cb, &update_every);
1449
+ }
1450
+}
1451
+
1452
+static ND_THREAD *mssql_queries_thread = NULL;
1453
+
1454
+static int initialize(int update_every)
1455
+{
1456
+ static bool create_thread = false;
1457
+ mssql_instances = dictionary_create_advanced(
1458
+ DICT_OPTION_DONT_OVERWRITE_VALUE | DICT_OPTION_FIXED_SIZE, NULL, sizeof(struct mssql_instance));
1459
+
1460
+ dictionary_register_insert_callback(mssql_instances, dict_mssql_insert_cb, &create_thread);
1461
+
1462
+ conn_options = dictionary_create_advanced(
1463
+ DICT_OPTION_DONT_OVERWRITE_VALUE | DICT_OPTION_FIXED_SIZE, NULL, sizeof(struct netdata_mssql_conn));
1464
+ dictionary_register_insert_callback(conn_options, dict_mssql_insert_conn_option, NULL);
1465
+
1466
+ netdata_read_config_options();
1467
+ mssql_fill_dictionary(update_every);
1468
+
1469
+ if (likely(create_thread)) {
1470
+ mssql_queries_thread =
1471
+ nd_thread_create("mssql_queries", NETDATA_THREAD_OPTION_DEFAULT, netdata_mssql_queries, &update_every);
1472
+ }
1473
+
1474
+ return 0;
1475
+}
1476
+
1477
+void dict_mssql_locks_wait_charts(struct mssql_instance *mi, struct mssql_lock_instance *mli, const char *resource)
1478
+{
1479
+ if (unlikely(!mli->st_lockWait)) {
1480
+ char id[RRD_ID_LENGTH_MAX + 1];
1481
+
1482
+ snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_resource_%s_lock_wait", mi->instanceID, resource);
1483
+ netdata_fix_chart_name(id);
1484
+ mli->st_lockWait = rrdset_create_localhost(
1485
+ "mssql",
1486
+ id,
1487
+ NULL,
1488
+ "locks",
1489
+ "mssql.instance_resource_lock_waits",
1490
+ "Lock requests that required the caller to wait per resource",
1491
+ "locks/s",
1492
+ PLUGIN_WINDOWS_NAME,
1493
+ "PerflibMSSQL",
1494
+ PRIO_MSSQL_LOCKS_WAIT,
1495
+ mi->update_every,
1496
+ RRDSET_TYPE_LINE);
1497
+
1498
+ rrdlabels_add(mli->st_lockWait->rrdlabels, "mssql_instance", mi->instanceID, RRDLABEL_SRC_AUTO);
1499
+ rrdlabels_add(mli->st_lockWait->rrdlabels, "resource", resource, RRDLABEL_SRC_AUTO);
1500
+ mli->rd_lockWait = rrddim_add(mli->st_lockWait, "locks", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
1501
+ }
1502
+
1503
+ rrddim_set_by_pointer(mli->st_lockWait, mli->rd_lockWait, (collected_number)mli->lockWait.current.Data);
1504
+ rrdset_done(mli->st_lockWait);
1505
+}
1506
+
1507
+void dict_mssql_dead_locks_charts(struct mssql_instance *mi, struct mssql_lock_instance *mli, const char *resource)
1508
+{
1509
+ if (unlikely(!mli->st_deadLocks)) {
1510
+ char id[RRD_ID_LENGTH_MAX + 1];
1511
+
1512
+ snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_resource_%s_deadlocks", mi->instanceID, resource);
1513
+ netdata_fix_chart_name(id);
1514
+ mli->st_deadLocks = rrdset_create_localhost(
1515
+ "mssql",
1516
+ id,
1517
+ NULL,
1518
+ "locks",
1519
+ "mssql.instance_resource_deadlocks",
1520
+ "Active lock requests that resulted in deadlock per resource",
1521
+ "deadlocks/s",
1522
+ PLUGIN_WINDOWS_NAME,
1523
+ "PerflibMSSQL",
1524
+ PRIO_MSSQL_LOCKS_DEADLOCK_PER_RESOURCE,
1525
+ mi->update_every,
1526
+ RRDSET_TYPE_LINE);
1527
+
1528
+ rrdlabels_add(mli->st_deadLocks->rrdlabels, "mssql_instance", mi->instanceID, RRDLABEL_SRC_AUTO);
1529
+ rrdlabels_add(mli->st_deadLocks->rrdlabels, "resource", resource, RRDLABEL_SRC_AUTO);
1530
+ mli->rd_deadLocks = rrddim_add(mli->st_deadLocks, "deadlocks", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
1531
+ }
1532
+
1533
+ rrddim_set_by_pointer(mli->st_deadLocks, mli->rd_deadLocks, (collected_number)mli->deadLocks.current.Data);
1534
+ rrdset_done(mli->st_deadLocks);
1535
+}
1536
+
1537
+int dict_mssql_locks_charts_cb(const DICTIONARY_ITEM *item __maybe_unused, void *value, void *data __maybe_unused)
1538
+{
1539
+ const char *dimension = dictionary_acquired_item_name((DICTIONARY_ITEM *)item);
1540
+ struct mssql_lock_instance *mli = value;
1541
+ struct mssql_instance *mi = data;
1542
+
1543
+ dict_mssql_locks_wait_charts(mi, mli, dimension);
1544
+ dict_mssql_dead_locks_charts(mi, mli, dimension);
1545
+
1546
+ return 1;
1547
+}
1548
+
1549
+static void do_mssql_locks(PERF_DATA_BLOCK *pDataBlock, struct mssql_instance *mi, int update_every __maybe_unused)
1550
+{
1551
+ if (unlikely(!pDataBlock))
1552
+ goto end_mssql_locks;
1553
+
1554
+ PERF_OBJECT_TYPE *pObjectType = perflibFindObjectTypeByName(pDataBlock, mi->objectName[NETDATA_MSSQL_LOCKS]);
1555
+ if (likely(pObjectType)) {
1556
+ if (likely(pObjectType->NumInstances)) {
1557
+ PERF_INSTANCE_DEFINITION *pi = NULL;
1558
+ for (LONG i = 0; i < pObjectType->NumInstances; i++) {
1559
+ pi = perflibForEachInstance(pDataBlock, pObjectType, pi);
1560
+ if (unlikely(!pi))
1561
+ break;
1562
+
1563
+ if (unlikely(!getInstanceName(pDataBlock, pObjectType, pi, windows_shared_buffer, sizeof(windows_shared_buffer))))
1564
+ strncpyz(windows_shared_buffer, "[unknown]", sizeof(windows_shared_buffer) - 1);
1565
+
1566
+ if (unlikely(!strcasecmp(windows_shared_buffer, "_Total")))
1567
+ continue;
1568
+
1569
+ struct mssql_lock_instance *mli =
1570
+ dictionary_set(mi->locks_instances, windows_shared_buffer, NULL, sizeof(*mli));
1571
+ if (unlikely(!mli))
1572
+ continue;
1573
+
1574
+ perflibGetInstanceCounter(pDataBlock, pObjectType, pi, &mli->deadLocks);
1575
+ perflibGetInstanceCounter(pDataBlock, pObjectType, pi, &mli->lockWait);
1576
+ }
1577
+ }
1578
+ }
1579
+
1580
+end_mssql_locks:
1581
+ dictionary_sorted_walkthrough_read(mi->locks_instances, dict_mssql_locks_charts_cb, mi);
1582
+}
1583
+
1584
+void mssql_total_wait_charts(struct mssql_instance *mi, struct mssql_db_waits *mdw, const char *type)
1585
+{
1586
+ if (unlikely(!mdw->st_total_wait)) {
1587
+ char id[RRD_ID_LENGTH_MAX + 1];
1588
+
1589
+ snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_%s_total_wait", mi->instanceID, type);
1590
+ netdata_fix_chart_name(id);
1591
+ mdw->st_total_wait = rrdset_create_localhost(
1592
+ "mssql",
1593
+ id,
1594
+ NULL,
1595
+ "locks",
1596
+ "mssql.instance_total_wait_time",
1597
+ "Wait time for each wait type and category",
1598
+ "ms",
1599
+ PLUGIN_WINDOWS_NAME,
1600
+ "PerflibMSSQL",
1601
+ PRIO_MSSQL_WAITS_TOTAL,
1602
+ mi->update_every,
1603
+ RRDSET_TYPE_LINE);
1604
+
1605
+ rrdlabels_add(mdw->st_total_wait->rrdlabels, "mssql_instance", mi->instanceID, RRDLABEL_SRC_AUTO);
1606
+ rrdlabels_add(mdw->st_total_wait->rrdlabels, "wait_type", mdw->wait_type, RRDLABEL_SRC_AUTO);
1607
+ rrdlabels_add(mdw->st_total_wait->rrdlabels, "wait_category", mdw->wait_category, RRDLABEL_SRC_AUTO);
1608
+ mdw->rd_total_wait = rrddim_add(mdw->st_total_wait, "duration", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
1609
+ }
1610
+
1611
+ rrddim_set_by_pointer(
1612
+ mdw->st_total_wait, mdw->rd_total_wait, (collected_number)mdw->MSSQLDatabaseTotalWait.current.Data);
1613
+
1614
+ rrdset_done(mdw->st_total_wait);
1615
+}
1616
+
1617
+void mssql_resource_wait_charts(struct mssql_instance *mi, struct mssql_db_waits *mdw, const char *type)
1618
+{
1619
+ if (unlikely(!mdw->st_resource_wait_msec)) {
1620
+ char id[RRD_ID_LENGTH_MAX + 1];
1621
+
1622
+ snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_%s_resource_wait", mi->instanceID, type);
1623
+ netdata_fix_chart_name(id);
1624
+ mdw->st_resource_wait_msec = rrdset_create_localhost(
1625
+ "mssql",
1626
+ id,
1627
+ NULL,
1628
+ "locks",
1629
+ "mssql.instance_resource_wait_time",
1630
+ "Wait time for threads waiting on specific resource types for each wait type and category",
1631
+ "ms",
1632
+ PLUGIN_WINDOWS_NAME,
1633
+ "PerflibMSSQL",
1634
+ PRIO_MSSQL_RESOURCE_WAIT,
1635
+ mi->update_every,
1636
+ RRDSET_TYPE_LINE);
1637
+
1638
+ rrdlabels_add(mdw->st_resource_wait_msec->rrdlabels, "mssql_instance", mi->instanceID, RRDLABEL_SRC_AUTO);
1639
+ rrdlabels_add(mdw->st_resource_wait_msec->rrdlabels, "wait_type", mdw->wait_type, RRDLABEL_SRC_AUTO);
1640
+ rrdlabels_add(mdw->st_resource_wait_msec->rrdlabels, "wait_category", mdw->wait_category, RRDLABEL_SRC_AUTO);
1641
+ mdw->rd_resource_wait_msec =
1642
+ rrddim_add(mdw->st_resource_wait_msec, "duration", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
1643
+ }
1644
+
1645
+ rrddim_set_by_pointer(
1646
+ mdw->st_resource_wait_msec,
1647
+ mdw->rd_resource_wait_msec,
1648
+ (collected_number)mdw->MSSQLDatabaseResourceWaitMSec.current.Data);
1649
+
1650
+ rrdset_done(mdw->st_resource_wait_msec);
1651
+}
1652
+
1653
+void mssql_signal_wait_charts(struct mssql_instance *mi, struct mssql_db_waits *mdw, const char *type)
1654
+{
1655
+ if (unlikely(!mdw->st_signal_wait_msec)) {
1656
+ char id[RRD_ID_LENGTH_MAX + 1];
1657
+
1658
+ snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_%s_signal_wait", mi->instanceID, type);
1659
+ netdata_fix_chart_name(id);
1660
+ mdw->st_signal_wait_msec = rrdset_create_localhost(
1661
+ "mssql",
1662
+ id,
1663
+ NULL,
1664
+ "locks",
1665
+ "mssql.instance_signal_wait_time",
1666
+ "Delay between thread wakeup signal and actual execution start for each wait type and category",
1667
+ "ms",
1668
+ PLUGIN_WINDOWS_NAME,
1669
+ "PerflibMSSQL",
1670
+ PRIO_MSSQL_SIGNAL_WAIT,
1671
+ mi->update_every,
1672
+ RRDSET_TYPE_LINE);
1673
+
1674
+ rrdlabels_add(mdw->st_signal_wait_msec->rrdlabels, "mssql_instance", mi->instanceID, RRDLABEL_SRC_AUTO);
1675
+ rrdlabels_add(mdw->st_signal_wait_msec->rrdlabels, "wait_type", mdw->wait_type, RRDLABEL_SRC_AUTO);
1676
+ rrdlabels_add(mdw->st_signal_wait_msec->rrdlabels, "wait_category", mdw->wait_category, RRDLABEL_SRC_AUTO);
1677
+ mdw->rd_signal_wait_msec =
1678
+ rrddim_add(mdw->st_signal_wait_msec, "duration", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
1679
+ }
1680
+
1681
+ rrddim_set_by_pointer(
1682
+ mdw->st_signal_wait_msec,
1683
+ mdw->rd_signal_wait_msec,
1684
+ (collected_number)mdw->MSSQLDatabaseSignalWaitMSec.current.Data);
1685
+
1686
+ rrdset_done(mdw->st_signal_wait_msec);
1687
+}
1688
+
1689
+void mssql_max_wait_charts(struct mssql_instance *mi, struct mssql_db_waits *mdw, const char *type)
1690
+{
1691
+ if (unlikely(!mdw->st_max_wait_time_msec)) {
1692
+ char id[RRD_ID_LENGTH_MAX + 1];
1693
+
1694
+ snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_%s_max_wait", mi->instanceID, type);
1695
+ netdata_fix_chart_name(id);
1696
+ mdw->st_max_wait_time_msec = rrdset_create_localhost(
1697
+ "mssql",
1698
+ id,
1699
+ NULL,
1700
+ "locks",
1701
+ "mssql.instance_max_wait_time",
1702
+ "Maximum wait time for each wait type and category",
1703
+ "ms",
1704
+ PLUGIN_WINDOWS_NAME,
1705
+ "PerflibMSSQL",
1706
+ PRIO_MSSQL_MAX_WAIT_TIME,
1707
+ mi->update_every,
1708
+ RRDSET_TYPE_LINE);
1709
+
1710
+ rrdlabels_add(mdw->st_max_wait_time_msec->rrdlabels, "mssql_instance", mi->instanceID, RRDLABEL_SRC_AUTO);
1711
+ rrdlabels_add(mdw->st_max_wait_time_msec->rrdlabels, "wait_type", mdw->wait_type, RRDLABEL_SRC_AUTO);
1712
+ rrdlabels_add(mdw->st_max_wait_time_msec->rrdlabels, "wait_category", mdw->wait_category, RRDLABEL_SRC_AUTO);
1713
+ mdw->rd_max_wait_time_msec =
1714
+ rrddim_add(mdw->st_max_wait_time_msec, "duration", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
1715
+ }
1716
+
1717
+ rrddim_set_by_pointer(
1718
+ mdw->st_max_wait_time_msec,
1719
+ mdw->rd_max_wait_time_msec,
1720
+ (collected_number)mdw->MSSQLDatabaseMaxWaitTimeMSec.current.Data);
1721
+
1722
+ rrdset_done(mdw->st_max_wait_time_msec);
1723
+}
1724
+
1725
+void mssql_waiting_count_charts(struct mssql_instance *mi, struct mssql_db_waits *mdw, const char *type)
1726
+{
1727
+ if (unlikely(!mdw->st_waiting_tasks)) {
1728
+ char id[RRD_ID_LENGTH_MAX + 1];
1729
+
1730
+ snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_%s_waiting_count", mi->instanceID, type);
1731
+ netdata_fix_chart_name(id);
1732
+ mdw->st_waiting_tasks = rrdset_create_localhost(
1733
+ "mssql",
1734
+ id,
1735
+ NULL,
1736
+ "locks",
1737
+ "mssql.instance_waits",
1738
+ "Number of waits for each wait type and category",
1739
+ "waits/s",
1740
+ PLUGIN_WINDOWS_NAME,
1741
+ "PerflibMSSQL",
1742
+ PRIO_MSSQL_WAITING_COUNT,
1743
+ mi->update_every,
1744
+ RRDSET_TYPE_LINE);
1745
+
1746
+ rrdlabels_add(mdw->st_waiting_tasks->rrdlabels, "mssql_instance", mi->instanceID, RRDLABEL_SRC_AUTO);
1747
+ rrdlabels_add(mdw->st_waiting_tasks->rrdlabels, "wait_type", mdw->wait_type, RRDLABEL_SRC_AUTO);
1748
+ rrdlabels_add(mdw->st_waiting_tasks->rrdlabels, "wait_category", mdw->wait_category, RRDLABEL_SRC_AUTO);
1749
+ mdw->rd_waiting_tasks = rrddim_add(mdw->st_waiting_tasks, "waits", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
1750
+ }
1751
+
1752
+ rrddim_set_by_pointer(
1753
+ mdw->st_waiting_tasks, mdw->rd_waiting_tasks, (collected_number)mdw->MSSQLDatabaseWaitingTasks.current.Data);
1754
+
1755
+ rrdset_done(mdw->st_waiting_tasks);
1756
+}
1757
+
1758
+int dict_mssql_waits_charts_cb(const DICTIONARY_ITEM *item __maybe_unused, void *value, void *data __maybe_unused)
1759
+{
1760
+ const char *dimension = dictionary_acquired_item_name((DICTIONARY_ITEM *)item);
1761
+ struct mssql_db_waits *mdw = value;
1762
+ struct mssql_instance *mi = data;
1763
+
1764
+ mssql_total_wait_charts(mi, mdw, dimension);
1765
+ mssql_resource_wait_charts(mi, mdw, dimension);
1766
+ mssql_signal_wait_charts(mi, mdw, dimension);
1767
+ mssql_max_wait_charts(mi, mdw, dimension);
1768
+ mssql_waiting_count_charts(mi, mdw, dimension);
1769
+
1770
+ return 1;
1771
+}
1772
+
1773
+static void do_mssql_waits(PERF_DATA_BLOCK *pDataBlock, struct mssql_instance *mi, int update_every)
1774
+{
1775
+ dictionary_sorted_walkthrough_read(mi->waits, dict_mssql_waits_charts_cb, mi);
1776
+}
1777
+
1778
+void mssql_buffman_iops_chart(struct mssql_db_instance *mdi, struct mssql_instance *mi)
1779
+{
1780
+ if (unlikely(!mdi->st_buff_page_iops)) {
1781
+ char id[RRD_ID_LENGTH_MAX + 1];
1782
+ snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_bufman_iops", mi->instanceID);
1783
+ netdata_fix_chart_name(id);
1784
+ mdi->st_buff_page_iops = rrdset_create_localhost(
1785
+ "mssql",
1786
+ id,
1787
+ NULL,
1788
+ "buffer cache",
1789
+ "mssql.instance_bufman_iops",
1790
+ "Number of pages input and output",
1791
+ "pages/s",
1792
+ PLUGIN_WINDOWS_NAME,
1793
+ "PerflibMSSQL",
1794
+ PRIO_MSSQL_BUFF_MAN_IOPS,
1795
+ mi->update_every,
1796
+ RRDSET_TYPE_LINE);
1797
+
1798
+ mdi->rd_buff_page_reads = rrddim_add(mdi->st_buff_page_iops, "read", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
1799
+ mdi->rd_buff_page_writes =
1800
+ rrddim_add(mdi->st_buff_page_iops, "written", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
1801
+
1802
+ rrdlabels_add(mdi->st_buff_page_iops->rrdlabels, "mssql_instance", mi->instanceID, RRDLABEL_SRC_AUTO);
1803
+ }
1804
+
1805
+ rrddim_set_by_pointer(
1806
+ mdi->st_buff_page_iops, mdi->rd_buff_page_reads, (collected_number)mdi->MSSQLBufferPageReads.current.Data);
1807
+ rrddim_set_by_pointer(
1808
+ mdi->st_buff_page_iops, mdi->rd_buff_page_writes, (collected_number)mdi->MSSQLBufferPageWrites.current.Data);
1809
+
1810
+ rrdset_done(mdi->st_buff_page_iops);
1811
+}
1812
+
1813
+void mssql_buffman_cache_hit_ratio_chart(struct mssql_db_instance *mdi, struct mssql_instance *mi)
1814
+{
1815
+ if (unlikely(!mdi->st_buff_cache_hits)) {
1816
+ char id[RRD_ID_LENGTH_MAX + 1];
1817
+ snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_cache_hit_ratio", mi->instanceID);
1818
+ netdata_fix_chart_name(id);
1819
+ mdi->st_buff_cache_hits = rrdset_create_localhost(
1820
+ "mssql",
1821
+ id,
1822
+ NULL,
1823
+ "buffer cache",
1824
+ "mssql.instance_cache_hit_ratio",
1825
+ "Buffer Cache hit ratio",
1826
+ "percentage",
1827
+ PLUGIN_WINDOWS_NAME,
1828
+ "PerflibMSSQL",
1829
+ PRIO_MSSQL_BUFF_CACHE_HIT_RATIO,
1830
+ mi->update_every,
1831
+ RRDSET_TYPE_LINE);
1832
+
1833
+ mdi->rd_buff_cache_hits = rrddim_add(mdi->st_buff_cache_hits, "hit_ratio", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
1834
+
1835
+ rrdlabels_add(mdi->st_buff_cache_hits->rrdlabels, "mssql_instance", mi->instanceID, RRDLABEL_SRC_AUTO);
1836
+ }
1837
+
1838
+ rrddim_set_by_pointer(
1839
+ mdi->st_buff_cache_hits, mdi->rd_buff_cache_hits, (collected_number)mdi->MSSQLBufferCacheHits.current.Data);
1840
+ rrdset_done(mdi->st_buff_cache_hits);
1841
+}
1842
+
1843
+void mssql_buffman_checkpoints_pages_chart(struct mssql_db_instance *mdi, struct mssql_instance *mi)
1844
+{
1845
+ if (unlikely(!mdi->st_buff_checkpoint_pages)) {
1846
+ char id[RRD_ID_LENGTH_MAX + 1];
1847
+ snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_bufman_checkpoint_pages", mi->instanceID);
1848
+ netdata_fix_chart_name(id);
1849
+ mdi->st_buff_checkpoint_pages = rrdset_create_localhost(
1850
+ "mssql",
1851
+ id,
1852
+ NULL,
1853
+ "buffer cache",
1854
+ "mssql.instance_bufman_checkpoint_pages",
1855
+ "Flushed pages",
1856
+ "pages/s",
1857
+ PLUGIN_WINDOWS_NAME,
1858
+ "PerflibMSSQL",
1859
+ PRIO_MSSQL_BUFF_CHECKPOINT_PAGES,
1860
+ mi->update_every,
1861
+ RRDSET_TYPE_LINE);
1862
+
1863
+ mdi->rd_buff_checkpoint_pages =
1864
+ rrddim_add(mdi->st_buff_checkpoint_pages, "log", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
1865
+
1866
+ rrdlabels_add(mdi->st_buff_checkpoint_pages->rrdlabels, "mssql_instance", mi->instanceID, RRDLABEL_SRC_AUTO);
1867
+ }
1868
+
1869
+ rrddim_set_by_pointer(
1870
+ mdi->st_buff_checkpoint_pages,
1871
+ mdi->rd_buff_checkpoint_pages,
1872
+ (collected_number)mdi->MSSQLBufferCheckpointPages.current.Data);
1873
+ rrdset_done(mdi->st_buff_checkpoint_pages);
1874
+}
1875
+
1876
+void mssql_buffman_page_life_expectancy_chart(struct mssql_db_instance *mdi, struct mssql_instance *mi)
1877
+{
1878
+ if (unlikely(!mdi->st_buff_cache_page_life_expectancy)) {
1879
+ char id[RRD_ID_LENGTH_MAX + 1];
1880
+ snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_bufman_page_life_expectancy", mi->instanceID);
1881
+ netdata_fix_chart_name(id);
1882
+ mdi->st_buff_cache_page_life_expectancy = rrdset_create_localhost(
1883
+ "mssql",
1884
+ id,
1885
+ NULL,
1886
+ "buffer cache",
1887
+ "mssql.instance_bufman_page_life_expectancy",
1888
+ "Page life expectancy",
1889
+ "seconds",
1890
+ PLUGIN_WINDOWS_NAME,
1891
+ "PerflibMSSQL",
1892
+ PRIO_MSSQL_BUFF_PAGE_LIFE_EXPECTANCY,
1893
+ mi->update_every,
1894
+ RRDSET_TYPE_LINE);
1895
+
1896
+ mdi->rd_buff_cache_page_life_expectancy =
1897
+ rrddim_add(mdi->st_buff_cache_page_life_expectancy, "life_expectancy", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
1898
+
1899
+ rrdlabels_add(
1900
+ mdi->st_buff_cache_page_life_expectancy->rrdlabels, "mssql_instance", mi->instanceID, RRDLABEL_SRC_AUTO);
1901
+ }
1902
+
1903
+ rrddim_set_by_pointer(
1904
+ mdi->st_buff_cache_page_life_expectancy,
1905
+ mdi->rd_buff_cache_page_life_expectancy,
1906
+ (collected_number)mdi->MSSQLBufferPageLifeExpectancy.current.Data);
1907
+ rrdset_done(mdi->st_buff_cache_page_life_expectancy);
1908
+}
1909
+
1910
+void mssql_buffman_lazy_write_chart(struct mssql_db_instance *mdi, struct mssql_instance *mi)
1911
+{
1912
+ if (unlikely(!mdi->st_buff_lazy_write)) {
1913
+ char id[RRD_ID_LENGTH_MAX + 1];
1914
+ snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_bufman_lazy_write", mi->instanceID);
1915
+ netdata_fix_chart_name(id);
1916
+ mdi->st_buff_lazy_write = rrdset_create_localhost(
1917
+ "mssql",
1918
+ id,
1919
+ NULL,
1920
+ "buffer cache",
1921
+ "mssql.instance_bufman_lazy_write",
1922
+ "Buffers written by buffer manager's lazy writer",
1923
+ "writes/s",
1924
+ PLUGIN_WINDOWS_NAME,
1925
+ "PerflibMSSQL",
1926
+ PRIO_MSSQL_BUFF_LAZY_WRITE,
1927
+ mi->update_every,
1928
+ RRDSET_TYPE_LINE);
1929
+
1930
+ mdi->rd_buff_lazy_write = rrddim_add(mdi->st_buff_lazy_write, "writes", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
1931
+
1932
+ rrdlabels_add(mdi->st_buff_lazy_write->rrdlabels, "mssql_instance", mi->instanceID, RRDLABEL_SRC_AUTO);
1933
+ }
1934
+
1935
+ rrddim_set_by_pointer(
1936
+ mdi->st_buff_lazy_write, mdi->rd_buff_lazy_write, (collected_number)mdi->MSSQLBufferLazyWrite.current.Data);
1937
+ rrdset_done(mdi->st_buff_lazy_write);
1938
+}
1939
+
1940
+void mssql_buffman_page_lookups_chart(struct mssql_db_instance *mdi, struct mssql_instance *mi)
1941
+{
1942
+ if (unlikely(!mdi->st_buff_page_lookups)) {
1943
+ char id[RRD_ID_LENGTH_MAX + 1];
1944
+ snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_bufman_page_lookups", mi->instanceID);
1945
+ netdata_fix_chart_name(id);
1946
+ mdi->st_buff_page_lookups = rrdset_create_localhost(
1947
+ "mssql",
1948
+ id,
1949
+ NULL,
1950
+ "buffer cache",
1951
+ "mssql.instance_bufman_page_lookups",
1952
+ "Requests to find a page in the buffer pool.",
1953
+ "lookups/s",
1954
+ PLUGIN_WINDOWS_NAME,
1955
+ "PerflibMSSQL",
1956
+ PRIO_MSSQL_BUFF_PAGE_LOOKUPS,
1957
+ mi->update_every,
1958
+ RRDSET_TYPE_LINE);
1959
+
1960
+ mdi->rd_buff_page_lookups =
1961
+ rrddim_add(mdi->st_buff_page_lookups, "lookups", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
1962
+
1963
+ rrdlabels_add(mdi->st_buff_page_lookups->rrdlabels, "mssql_instance", mi->instanceID, RRDLABEL_SRC_AUTO);
1964
+ }
1965
+
1966
+ rrddim_set_by_pointer(
1967
+ mdi->st_buff_page_lookups,
1968
+ mdi->rd_buff_page_lookups,
1969
+ (collected_number)mdi->MSSQLBufferPageLookups.current.Data);
1970
+ rrdset_done(mdi->st_buff_page_lookups);
1971
+}
1972
+
1973
+static void netdata_mssql_compilations(struct mssql_db_instance *mdi, struct mssql_instance *mi)
1974
+{
1975
+ if (unlikely(!mdi->st_stats_compilation)) {
1976
+ char id[RRD_ID_LENGTH_MAX + 1];
1977
+ snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_sqlstats_sql_compilations", mi->instanceID);
1978
+ netdata_fix_chart_name(id);
1979
+ mdi->st_stats_compilation = rrdset_create_localhost(
1980
+ "mssql",
1981
+ id,
1982
+ NULL,
1983
+ "sql activity",
1984
+ "mssql.instance_sqlstats_sql_compilations",
1985
+ "SQL compilations",
1986
+ "compilations/s",
1987
+ PLUGIN_WINDOWS_NAME,
1988
+ "PerflibMSSQL",
1989
+ PRIO_MSSQL_STATS_COMPILATIONS,
1990
+ mi->update_every,
1991
+ RRDSET_TYPE_LINE);
1992
+
1993
+ mdi->rd_stats_compilation =
1994
+ rrddim_add(mdi->st_stats_compilation, "compilations", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
1995
+
1996
+ rrdlabels_add(mdi->st_stats_compilation->rrdlabels, "mssql_instance", mi->instanceID, RRDLABEL_SRC_AUTO);
1997
+ }
1998
+
1999
+ rrddim_set_by_pointer(
2000
+ mdi->st_stats_compilation, mdi->rd_stats_compilation, (collected_number)mdi->MSSQLCompilations.current.Data);
2001
+ rrdset_done(mdi->st_stats_compilation);
2002
+}
2003
+
2004
+static void netdata_mssql_recompilations(struct mssql_db_instance *mdi, struct mssql_instance *mi)
2005
+{
2006
+ if (unlikely(!mdi->st_stats_recompiles)) {
2007
+ char id[RRD_ID_LENGTH_MAX + 1];
2008
+ snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_sqlstats_sql_recompilations", mi->instanceID);
2009
+ netdata_fix_chart_name(id);
2010
+ mdi->st_stats_recompiles = rrdset_create_localhost(
2011
+ "mssql",
2012
+ id,
2013
+ NULL,
2014
+ "sql activity",
2015
+ "mssql.instance_sqlstats_sql_recompilations",
2016
+ "SQL re-compilations",
2017
+ "recompiles/s",
2018
+ PLUGIN_WINDOWS_NAME,
2019
+ "PerflibMSSQL",
2020
+ PRIO_MSSQL_STATS_RECOMPILATIONS,
2021
+ mi->update_every,
2022
+ RRDSET_TYPE_LINE);
2023
+
2024
+ mdi->rd_stats_recompiles =
2025
+ rrddim_add(mdi->st_stats_recompiles, "recompiles", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
2026
+
2027
+ rrdlabels_add(mdi->st_stats_recompiles->rrdlabels, "mssql_instance", mi->instanceID, RRDLABEL_SRC_AUTO);
2028
+ }
2029
+
2030
+ rrddim_set_by_pointer(
2031
+ mdi->st_stats_recompiles, mdi->rd_stats_recompiles, (collected_number)mdi->MSSQLRecompilations.current.Data);
2032
+ rrdset_done(mdi->st_stats_recompiles);
2033
+}
2034
+
2035
+int dict_mssql_buffman_stats_charts_cb(
2036
+ const DICTIONARY_ITEM *item __maybe_unused,
2037
+ void *value,
2038
+ void *data __maybe_unused)
2039
+{
2040
+ struct mssql_db_instance *mdi = value;
2041
+ struct mssql_instance *mi = data;
2042
+
2043
+ if (unlikely(!mdi->collect_instance))
2044
+ return 1;
2045
+
2046
+ mssql_buffman_iops_chart(mdi, mi);
2047
+ mssql_buffman_cache_hit_ratio_chart(mdi, mi);
2048
+ mssql_buffman_checkpoints_pages_chart(mdi, mi);
2049
+ mssql_buffman_page_life_expectancy_chart(mdi, mi);
2050
+ mssql_buffman_lazy_write_chart(mdi, mi);
2051
+ mssql_buffman_page_lookups_chart(mdi, mi);
2052
+
2053
+ netdata_mssql_compilations(mdi, mi);
2054
+ netdata_mssql_recompilations(mdi, mi);
2055
+
2056
+ return 1;
2057
+}
2058
+
2059
+static void do_mssql_bufferman_stats_sql(PERF_DATA_BLOCK *pDataBlock, struct mssql_instance *mi, int update_every)
2060
+{
2061
+ dictionary_sorted_walkthrough_read(mi->databases, dict_mssql_buffman_stats_charts_cb, mi);
2062
+}
2063
+
2064
+static void netdata_mssql_jobs_status(struct mssql_db_jobs *mdj, struct mssql_instance *mi, const char *job)
2065
+{
2066
+ if (unlikely(!mdj->st_status)) {
2067
+ char id[RRD_ID_LENGTH_MAX + 1];
2068
+ snprintfz(id, RRD_ID_LENGTH_MAX, "job_%s_instance_%s_status", job, mi->instanceID);
2069
+ netdata_fix_chart_name(id);
2070
+ mdj->st_status = rrdset_create_localhost(
2071
+ "mssql",
2072
+ id,
2073
+ NULL,
2074
+ "jobs",
2075
+ "mssql.instance_jobs_status",
2076
+ "Jobs running",
2077
+ "status",
2078
+ PLUGIN_WINDOWS_NAME,
2079
+ "PerflibMSSQL",
2080
+ PRIO_MSSQL_DATABASE_JOBS_STATUS,
2081
+ mi->update_every,
2082
+ RRDSET_TYPE_LINE);
2083
+
2084
+ mdj->rd_status_enabled = rrddim_add(mdj->st_status, "enabled", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
2085
+
2086
+ mdj->rd_status_disabled = rrddim_add(mdj->st_status, "disabled", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
2087
+
2088
+ rrdlabels_add(mdj->st_status->rrdlabels, "mssql_instance", mi->instanceID, RRDLABEL_SRC_AUTO);
2089
+ rrdlabels_add(mdj->st_status->rrdlabels, "job_name", job, RRDLABEL_SRC_AUTO);
2090
+ }
2091
+
2092
+ rrddim_set_by_pointer(
2093
+ mdj->st_status, mdj->rd_status_enabled, (collected_number)(mdj->MSSQLJOBState.current.Data == 1));
2094
+ rrddim_set_by_pointer(
2095
+ mdj->st_status, mdj->rd_status_disabled, (collected_number)(mdj->MSSQLJOBState.current.Data == 0));
2096
+ rrdset_done(mdj->st_status);
2097
+}
2098
+
2099
+int dict_mssql_sysjobs_chart_cb(const DICTIONARY_ITEM *item __maybe_unused, void *value, void *data __maybe_unused)
2100
+{
2101
+ const char *job = dictionary_acquired_item_name((DICTIONARY_ITEM *)item);
2102
+ struct mssql_db_jobs *mdj = value;
2103
+ struct mssql_instance *mi = data;
2104
+
2105
+ netdata_mssql_jobs_status(mdj, mi, job);
2106
+}
2107
+
2108
+static void do_mssql_job_status_sql(PERF_DATA_BLOCK *pDataBlock, struct mssql_instance *mi, int update_every)
2109
+{
2110
+ dictionary_sorted_walkthrough_read(mi->sysjobs, dict_mssql_sysjobs_chart_cb, mi);
2111
+}
2112
+
2113
+void dict_mssql_replication_status(struct mssql_publisher_publication *mpp, int update_every)
2114
+{
2115
+ if (unlikely(!mpp->st_publisher_status)) {
2116
+ char id[RRD_ID_LENGTH_MAX + 1];
2117
+
2118
+ snprintfz(
2119
+ id,
2120
+ RRD_ID_LENGTH_MAX,
2121
+ "instance_%s_replication_%s_%s_status",
2122
+ mpp->parent->instanceID,
2123
+ mpp->publication,
2124
+ mpp->db);
2125
+ netdata_fix_chart_name(id);
2126
+ mpp->st_publisher_status = rrdset_create_localhost(
2127
+ "mssql",
2128
+ id,
2129
+ NULL,
2130
+ "replication",
2131
+ "mssql.replication_status",
2132
+ "Current replication status",
2133
+ "status",
2134
+ PLUGIN_WINDOWS_NAME,
2135
+ "PerflibMSSQL",
2136
+ PRIO_MSSQL_REPLICATION_STATUS,
2137
+ update_every,
2138
+ RRDSET_TYPE_LINE);
2139
+
2140
+ rrdlabels_add(
2141
+ mpp->st_publisher_status->rrdlabels, "mssql_instance", mpp->parent->instanceID, RRDLABEL_SRC_AUTO);
2142
+ rrdlabels_add(mpp->st_publisher_status->rrdlabels, "publisher", mpp->publisher, RRDLABEL_SRC_AUTO);
2143
+ rrdlabels_add(mpp->st_publisher_status->rrdlabels, "database", mpp->db, RRDLABEL_SRC_AUTO);
2144
+ rrdlabels_add(mpp->st_publisher_status->rrdlabels, "publication", mpp->publication, RRDLABEL_SRC_AUTO);
2145
+
2146
+ mpp->rd_publisher_status_started =
2147
+ rrddim_add(mpp->st_publisher_status, "started", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
2148
+ mpp->rd_publisher_status_successed =
2149
+ rrddim_add(mpp->st_publisher_status, "succeeded", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
2150
+ mpp->rd_publisher_status_in_progress =
2151
+ rrddim_add(mpp->st_publisher_status, "in_progress", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
2152
+ mpp->rd_publisher_status_idle =
2153
+ rrddim_add(mpp->st_publisher_status, "idle", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
2154
+ mpp->rd_publisher_status_retrying =
2155
+ rrddim_add(mpp->st_publisher_status, "retrying", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
2156
+ mpp->rd_publisher_status_failed =
2157
+ rrddim_add(mpp->st_publisher_status, "failed", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
2158
+ }
2159
+
2160
+ int status = mpp->status;
2161
+ rrddim_set_by_pointer(mpp->st_publisher_status, mpp->rd_publisher_status_started, (collected_number)(status == 1));
2162
+ rrddim_set_by_pointer(
2163
+ mpp->st_publisher_status, mpp->rd_publisher_status_successed, (collected_number)(status == 2));
2164
+ rrddim_set_by_pointer(
2165
+ mpp->st_publisher_status, mpp->rd_publisher_status_in_progress, (collected_number)(status == 3));
2166
+ rrddim_set_by_pointer(mpp->st_publisher_status, mpp->rd_publisher_status_idle, (collected_number)(status == 4));
2167
+ rrddim_set_by_pointer(mpp->st_publisher_status, mpp->rd_publisher_status_retrying, (collected_number)(status == 5));
2168
+ rrddim_set_by_pointer(mpp->st_publisher_status, mpp->rd_publisher_status_failed, (collected_number)(status == 6));
2169
+ rrdset_done(mpp->st_publisher_status);
2170
+}
2171
+
2172
+void dict_mssql_replication_warning(struct mssql_publisher_publication *mpp, int update_every)
2173
+{
2174
+ if (unlikely(!mpp->st_warning)) {
2175
+ char id[RRD_ID_LENGTH_MAX + 1];
2176
+
2177
+ snprintfz(
2178
+ id,
2179
+ RRD_ID_LENGTH_MAX,
2180
+ "instance_%s_replication_%s_%s_warning",
2181
+ mpp->parent->instanceID,
2182
+ mpp->publication,
2183
+ mpp->db);
2184
+ netdata_fix_chart_name(id);
2185
+ mpp->st_warning = rrdset_create_localhost(
2186
+ "mssql",
2187
+ id,
2188
+ NULL,
2189
+ "replication",
2190
+ "mssql.replication_warning",
2191
+ "Maximum threshold warning.",
2192
+ "status",
2193
+ PLUGIN_WINDOWS_NAME,
2194
+ "PerflibMSSQL",
2195
+ PRIO_MSSQL_REPLICATION_WARNING,
2196
+ update_every,
2197
+ RRDSET_TYPE_LINE);
2198
+
2199
+ rrdlabels_add(mpp->st_warning->rrdlabels, "mssql_instance", mpp->parent->instanceID, RRDLABEL_SRC_AUTO);
2200
+ rrdlabels_add(mpp->st_warning->rrdlabels, "publisher", mpp->publisher, RRDLABEL_SRC_AUTO);
2201
+ rrdlabels_add(mpp->st_warning->rrdlabels, "database", mpp->db, RRDLABEL_SRC_AUTO);
2202
+ rrdlabels_add(mpp->st_warning->rrdlabels, "publication", mpp->publication, RRDLABEL_SRC_AUTO);
2203
+
2204
+ mpp->rd_warning_expiration = rrddim_add(mpp->st_warning, "expiration", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
2205
+ mpp->rd_warning_latency = rrddim_add(mpp->st_warning, "latency", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
2206
+ mpp->rd_warning_mergeeexpiration =
2207
+ rrddim_add(mpp->st_warning, "merge expiration", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
2208
+ mpp->rd_warning_mergefastduration =
2209
+ rrddim_add(mpp->st_warning, "fast duration", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
2210
+ mpp->rd_warning_mergelowduration =
2211
+ rrddim_add(mpp->st_warning, "low duration", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
2212
+ mpp->rd_warning_mergefastrunspeed =
2213
+ rrddim_add(mpp->st_warning, "fast run speed", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
2214
+ mpp->rd_warning_mergelowrunspeed =
2215
+ rrddim_add(mpp->st_warning, "low run speed", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
2216
+ }
2217
+
2218
+ int warning = mpp->warning;
2219
+ rrddim_set_by_pointer(
2220
+ mpp->st_warning, mpp->rd_warning_expiration, (collected_number)(warning & MSSQL_REPLICATON_EXPIRATION));
2221
+ rrddim_set_by_pointer(
2222
+ mpp->st_warning, mpp->rd_warning_latency, (collected_number)(warning & MSSQL_REPLICATON_LATENCY));
2223
+ rrddim_set_by_pointer(
2224
+ mpp->st_warning,
2225
+ mpp->rd_warning_mergeeexpiration,
2226
+ (collected_number)(warning & MSSQL_REPLICATON_MERGEEXPIRATION));
2227
+ rrddim_set_by_pointer(
2228
+ mpp->st_warning,
2229
+ mpp->rd_warning_mergefastduration,
2230
+ (collected_number)(warning & MSSQL_REPLICATON_MERGEFASTDURATION));
2231
+ rrddim_set_by_pointer(
2232
+ mpp->st_warning,
2233
+ mpp->rd_warning_mergelowduration,
2234
+ (collected_number)(warning & MSSQL_REPLICATON_MERGELOWDURATION));
2235
+ rrddim_set_by_pointer(
2236
+ mpp->st_warning,
2237
+ mpp->rd_warning_mergefastrunspeed,
2238
+ (collected_number)(warning & MSSQL_REPLICATON_MERGEFASTRUNSPEED));
2239
+ rrddim_set_by_pointer(
2240
+ mpp->st_warning,
2241
+ mpp->rd_warning_mergelowrunspeed,
2242
+ (collected_number)(warning & MSSQL_REPLICATON_MERGELOWRUNSPEED));
2243
+ rrdset_done(mpp->st_warning);
2244
+}
2245
+
2246
+void dict_mssql_replication_avg_latency(struct mssql_publisher_publication *mpp, int update_every)
2247
+{
2248
+ if (unlikely(!mpp->st_avg_latency)) {
2249
+ char id[RRD_ID_LENGTH_MAX + 1];
2250
+
2251
+ snprintfz(
2252
+ id,
2253
+ RRD_ID_LENGTH_MAX,
2254
+ "instance_%s_replication_%s_%s_avg_latency",
2255
+ mpp->parent->instanceID,
2256
+ mpp->publication,
2257
+ mpp->db);
2258
+ netdata_fix_chart_name(id);
2259
+ mpp->st_avg_latency = rrdset_create_localhost(
2260
+ "mssql",
2261
+ id,
2262
+ NULL,
2263
+ "replication",
2264
+ "mssql.replication_avg_latency",
2265
+ "Average latency for a transactional publication.",
2266
+ "seconds",
2267
+ PLUGIN_WINDOWS_NAME,
2268
+ "PerflibMSSQL",
2269
+ PRIO_MSSQL_REPLICATION_AVG_LATENCY,
2270
+ update_every,
2271
+ RRDSET_TYPE_LINE);
2272
+
2273
+ rrdlabels_add(mpp->st_avg_latency->rrdlabels, "mssql_instance", mpp->parent->instanceID, RRDLABEL_SRC_AUTO);
2274
+ rrdlabels_add(mpp->st_avg_latency->rrdlabels, "publisher", mpp->publisher, RRDLABEL_SRC_AUTO);
2275
+ rrdlabels_add(mpp->st_avg_latency->rrdlabels, "database", mpp->db, RRDLABEL_SRC_AUTO);
2276
+ rrdlabels_add(mpp->st_avg_latency->rrdlabels, "publication", mpp->publication, RRDLABEL_SRC_AUTO);
2277
+
2278
+ mpp->rd_avg_latency = rrddim_add(mpp->st_avg_latency, "latency", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
2279
+ }
2280
+
2281
+ rrddim_set_by_pointer(mpp->st_avg_latency, mpp->rd_avg_latency, (collected_number)mpp->avg_latency);
2282
+ rrdset_done(mpp->st_avg_latency);
2283
+}
2284
+
2285
+void dict_mssql_replication_subscription(struct mssql_publisher_publication *mpp, int update_every)
2286
+{
2287
+ if (unlikely(!mpp->st_subscription_count)) {
2288
+ char id[RRD_ID_LENGTH_MAX + 1];
2289
+
2290
+ snprintfz(
2291
+ id,
2292
+ RRD_ID_LENGTH_MAX,
2293
+ "instance_%s_replication_%s_%s_subscription",
2294
+ mpp->parent->instanceID,
2295
+ mpp->publication,
2296
+ mpp->db);
2297
+ netdata_fix_chart_name(id);
2298
+ mpp->st_subscription_count = rrdset_create_localhost(
2299
+ "mssql",
2300
+ id,
2301
+ NULL,
2302
+ "replication",
2303
+ "mssql.replication_subscription",
2304
+ "Number of subscriptions to a publication.",
2305
+ "subscription",
2306
+ PLUGIN_WINDOWS_NAME,
2307
+ "PerflibMSSQL",
2308
+ PRIO_MSSQL_REPLICATION_SUBSCRIPTION_COUNT,
2309
+ update_every,
2310
+ RRDSET_TYPE_LINE);
2311
+
2312
+ rrdlabels_add(
2313
+ mpp->st_subscription_count->rrdlabels, "mssql_instance", mpp->parent->instanceID, RRDLABEL_SRC_AUTO);
2314
+ rrdlabels_add(mpp->st_subscription_count->rrdlabels, "publisher", mpp->publisher, RRDLABEL_SRC_AUTO);
2315
+ rrdlabels_add(mpp->st_subscription_count->rrdlabels, "database", mpp->db, RRDLABEL_SRC_AUTO);
2316
+ rrdlabels_add(mpp->st_subscription_count->rrdlabels, "publication", mpp->publication, RRDLABEL_SRC_AUTO);
2317
+
2318
+ mpp->rd_subscription_count =
2319
+ rrddim_add(mpp->st_subscription_count, "subscription", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
2320
+ }
2321
+
2322
+ rrddim_set_by_pointer(
2323
+ mpp->st_subscription_count, mpp->rd_subscription_count, (collected_number)mpp->subscriptioncount);
2324
+ rrdset_done(mpp->st_subscription_count);
2325
+}
2326
+
2327
+void dict_mssql_replication_dist_agent_running(struct mssql_publisher_publication *mpp, int update_every)
2328
+{
2329
+ if (unlikely(!mpp->st_running_agent)) {
2330
+ char id[RRD_ID_LENGTH_MAX + 1];
2331
+
2332
+ snprintfz(
2333
+ id,
2334
+ RRD_ID_LENGTH_MAX,
2335
+ "instance_%s_replication_%s_%s_agent_running",
2336
+ mpp->parent->instanceID,
2337
+ mpp->publication,
2338
+ mpp->db);
2339
+ netdata_fix_chart_name(id);
2340
+ mpp->st_running_agent = rrdset_create_localhost(
2341
+ "mssql",
2342
+ id,
2343
+ NULL,
2344
+ "replication",
2345
+ "mssql.replication_agent_running",
2346
+ "Distribution agents running.",
2347
+ "agents",
2348
+ PLUGIN_WINDOWS_NAME,
2349
+ "PerflibMSSQL",
2350
+ PRIO_MSSQL_REPLICATION_AGENT_RUNNING,
2351
+ update_every,
2352
+ RRDSET_TYPE_LINE);
2353
+
2354
+ rrdlabels_add(mpp->st_running_agent->rrdlabels, "mssql_instance", mpp->parent->instanceID, RRDLABEL_SRC_AUTO);
2355
+ rrdlabels_add(mpp->st_running_agent->rrdlabels, "publisher", mpp->publisher, RRDLABEL_SRC_AUTO);
2356
+ rrdlabels_add(mpp->st_running_agent->rrdlabels, "database", mpp->db, RRDLABEL_SRC_AUTO);
2357
+ rrdlabels_add(mpp->st_running_agent->rrdlabels, "publication", mpp->publication, RRDLABEL_SRC_AUTO);
2358
+
2359
+ mpp->rd_running_agent = rrddim_add(mpp->st_running_agent, "agents", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
2360
+ }
2361
+
2362
+ rrddim_set_by_pointer(mpp->st_running_agent, mpp->rd_running_agent, (collected_number)mpp->runningdistagentcount);
2363
+ rrdset_done(mpp->st_running_agent);
2364
+}
2365
+
2366
+void dict_mssql_replication_sync_time(struct mssql_publisher_publication *mpp, int update_every)
2367
+{
2368
+ if (unlikely(!mpp->st_synchronization_time)) {
2369
+ char id[RRD_ID_LENGTH_MAX + 1];
2370
+
2371
+ snprintfz(
2372
+ id,
2373
+ RRD_ID_LENGTH_MAX,
2374
+ "instance_%s_replication_%s_%s_synchronization",
2375
+ mpp->parent->instanceID,
2376
+ mpp->publication,
2377
+ mpp->db);
2378
+ netdata_fix_chart_name(id);
2379
+ mpp->st_synchronization_time = rrdset_create_localhost(
2380
+ "mssql",
2381
+ id,
2382
+ NULL,
2383
+ "replication",
2384
+ "mssql.replication_synchronization",
2385
+ "The shortest synchronization.",
2386
+ "seconds",
2387
+ PLUGIN_WINDOWS_NAME,
2388
+ "PerflibMSSQL",
2389
+ PRIO_MSSQL_REPLICATION_SYNC_TIME,
2390
+ update_every,
2391
+ RRDSET_TYPE_LINE);
2392
+
2393
+ rrdlabels_add(
2394
+ mpp->st_synchronization_time->rrdlabels, "mssql_instance", mpp->parent->instanceID, RRDLABEL_SRC_AUTO);
2395
+ rrdlabels_add(mpp->st_synchronization_time->rrdlabels, "publisher", mpp->publisher, RRDLABEL_SRC_AUTO);
2396
+ rrdlabels_add(mpp->st_synchronization_time->rrdlabels, "database", mpp->db, RRDLABEL_SRC_AUTO);
2397
+ rrdlabels_add(mpp->st_synchronization_time->rrdlabels, "publication", mpp->publication, RRDLABEL_SRC_AUTO);
2398
+
2399
+ mpp->rd_synchronization_time =
2400
+ rrddim_add(mpp->st_synchronization_time, "seconds", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
2401
+ }
2402
+
2403
+ rrddim_set_by_pointer(
2404
+ mpp->st_synchronization_time, mpp->rd_synchronization_time, (collected_number)mpp->runningdistagentcount);
2405
+ rrdset_done(mpp->st_synchronization_time);
2406
+}
2407
+
2408
+int dict_mssql_replication_chart_cb(const DICTIONARY_ITEM *item __maybe_unused, void *value, void *data __maybe_unused)
2409
+{
2410
+ struct mssql_publisher_publication *mpp = value;
2411
+ int *update_every = data;
2412
+
2413
+ dict_mssql_replication_status(mpp, *update_every);
2414
+ dict_mssql_replication_warning(mpp, *update_every);
2415
+ dict_mssql_replication_avg_latency(mpp, *update_every);
2416
+ dict_mssql_replication_subscription(mpp, *update_every);
2417
+ dict_mssql_replication_dist_agent_running(mpp, *update_every);
2418
+ dict_mssql_replication_sync_time(mpp, *update_every);
2419
+}
2420
+
2421
+static void do_mssql_replication(struct mssql_instance *mi, int update_every)
2422
+{
2423
+ dictionary_sorted_walkthrough_read(mi->publisher_publication, dict_mssql_replication_chart_cb, &update_every);
2424
+}
2425
+
2426
+static void mssql_database_backup_restore_chart(struct mssql_db_instance *mdi, const char *db, int update_every)
2427
+{
2428
+ char id[RRD_ID_LENGTH_MAX + 1];
2429
+
2430
+ if (unlikely(!mdi->st_db_backup_restore_operations)) {
2431
+ snprintfz(id, RRD_ID_LENGTH_MAX, "db_%s_instance_%s_backup_restore_operations", db, mdi->parent->instanceID);
2432
+ netdata_fix_chart_name(id);
2433
+ mdi->st_db_backup_restore_operations = rrdset_create_localhost(
2434
+ "mssql",
2435
+ id,
2436
+ NULL,
2437
+ "transactions",
2438
+ "mssql.database_backup_restore_operations",
2439
+ "Backup IO per database",
2440
+ "operations/s",
2441
+ PLUGIN_WINDOWS_NAME,
2442
+ "PerflibMSSQL",
2443
+ PRIO_MSSQL_DATABASE_BACKUP_RESTORE_OPERATIONS,
2444
+ update_every,
2445
+ RRDSET_TYPE_LINE);
2446
+
2447
+ rrdlabels_add(
2448
+ mdi->st_db_backup_restore_operations->rrdlabels,
2449
+ "mssql_instance",
2450
+ mdi->parent->instanceID,
2451
+ RRDLABEL_SRC_AUTO);
2452
+ rrdlabels_add(mdi->st_db_backup_restore_operations->rrdlabels, "database", db, RRDLABEL_SRC_AUTO);
2453
+
2454
+ mdi->rd_db_backup_restore_operations =
2455
+ rrddim_add(mdi->st_db_backup_restore_operations, "backup", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
2456
+ }
2457
+
2458
+ rrddim_set_by_pointer(
2459
+ mdi->st_db_backup_restore_operations,
2460
+ mdi->rd_db_backup_restore_operations,
2461
+ (collected_number)mdi->MSSQLDatabaseBackupRestoreOperations.current.Data);
2462
+
2463
+ rrdset_done(mdi->st_db_backup_restore_operations);
2464
+}
2465
+
2466
+static void mssql_database_log_flushes_chart(struct mssql_db_instance *mdi, const char *db, int update_every)
2467
+{
2468
+ char id[RRD_ID_LENGTH_MAX + 1];
2469
+
2470
+ if (unlikely(!mdi->st_db_log_flushes)) {
2471
+ snprintfz(id, RRD_ID_LENGTH_MAX, "db_%s_instance_%s_log_flushes", db, mdi->parent->instanceID);
2472
+ netdata_fix_chart_name(id);
2473
+ mdi->st_db_log_flushes = rrdset_create_localhost(
2474
+ "mssql",
2475
+ id,
2476
+ NULL,
2477
+ "transactions",
2478
+ "mssql.database_log_flushes",
2479
+ "Log flushes",
2480
+ "flushes/s",
2481
+ PLUGIN_WINDOWS_NAME,
2482
+ "PerflibMSSQL",
2483
+ PRIO_MSSQL_DATABASE_LOG_FLUSHES,
2484
+ update_every,
2485
+ RRDSET_TYPE_LINE);
2486
+
2487
+ rrdlabels_add(mdi->st_db_log_flushes->rrdlabels, "mssql_instance", mdi->parent->instanceID, RRDLABEL_SRC_AUTO);
2488
+ rrdlabels_add(mdi->st_db_log_flushes->rrdlabels, "database", db, RRDLABEL_SRC_AUTO);
2489
+ }
2490
+
2491
+ if (unlikely(!mdi->rd_db_log_flushes)) {
2492
+ mdi->rd_db_log_flushes = rrddim_add(mdi->st_db_log_flushes, "flushes", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
2493
+ }
2494
+
2495
+ rrddim_set_by_pointer(
2496
+ mdi->st_db_log_flushes, mdi->rd_db_log_flushes, (collected_number)mdi->MSSQLDatabaseLogFlushes.current.Data);
2497
+
2498
+ rrdset_done(mdi->st_db_log_flushes);
2499
+}
2500
+
2501
+static void mssql_database_log_flushed_chart(struct mssql_db_instance *mdi, const char *db, int update_every)
2502
+{
2503
+ char id[RRD_ID_LENGTH_MAX + 1];
2504
+
2505
+ if (unlikely(!mdi->st_db_log_flushed)) {
2506
+ snprintfz(id, RRD_ID_LENGTH_MAX, "db_%s_instance_%s_log_flushed", db, mdi->parent->instanceID);
2507
+ netdata_fix_chart_name(id);
2508
+ mdi->st_db_log_flushed = rrdset_create_localhost(
2509
+ "mssql",
2510
+ id,
2511
+ NULL,
2512
+ "transactions",
2513
+ "mssql.database_log_flushed",
2514
+ "Log flushed",
2515
+ "bytes/s",
2516
+ PLUGIN_WINDOWS_NAME,
2517
+ "PerflibMSSQL",
2518
+ PRIO_MSSQL_DATABASE_LOG_FLUSHED,
2519
+ update_every,
2520
+ RRDSET_TYPE_LINE);
2521
+
2522
+ rrdlabels_add(mdi->st_db_log_flushed->rrdlabels, "mssql_instance", mdi->parent->instanceID, RRDLABEL_SRC_AUTO);
2523
+ rrdlabels_add(mdi->st_db_log_flushed->rrdlabels, "database", db, RRDLABEL_SRC_AUTO);
2524
+
2525
+ mdi->rd_db_log_flushed = rrddim_add(mdi->st_db_log_flushed, "flushed", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
2526
+ }
2527
+
2528
+ rrddim_set_by_pointer(
2529
+ mdi->st_db_log_flushed, mdi->rd_db_log_flushed, (collected_number)mdi->MSSQLDatabaseLogFlushed.current.Data);
2530
+
2531
+ rrdset_done(mdi->st_db_log_flushed);
2532
+}
2533
+
2534
+static void mssql_transactions_chart(struct mssql_db_instance *mdi, const char *db, int update_every)
2535
+{
2536
+ char id[RRD_ID_LENGTH_MAX + 1];
2537
+
2538
+ if (unlikely(!mdi->st_db_transactions)) {
2539
+ snprintfz(id, RRD_ID_LENGTH_MAX, "db_%s_instance_%s_transactions", db, mdi->parent->instanceID);
2540
+ netdata_fix_chart_name(id);
2541
+ mdi->st_db_transactions = rrdset_create_localhost(
2542
+ "mssql",
2543
+ id,
2544
+ NULL,
2545
+ "transactions",
2546
+ "mssql.database_transactions",
2547
+ "Transactions",
2548
+ "transactions/s",
2549
+ PLUGIN_WINDOWS_NAME,
2550
+ "PerflibMSSQL",
2551
+ PRIO_MSSQL_DATABASE_TRANSACTIONS,
2552
+ update_every,
2553
+ RRDSET_TYPE_LINE);
2554
+
2555
+ rrdlabels_add(mdi->st_db_transactions->rrdlabels, "mssql_instance", mdi->parent->instanceID, RRDLABEL_SRC_AUTO);
2556
+ rrdlabels_add(mdi->st_db_transactions->rrdlabels, "database", db, RRDLABEL_SRC_AUTO);
2557
+
2558
+ mdi->rd_db_transactions =
2559
+ rrddim_add(mdi->st_db_transactions, "transactions", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
2560
+ }
2561
+
2562
+ rrddim_set_by_pointer(
2563
+ mdi->st_db_transactions,
2564
+ mdi->rd_db_transactions,
2565
+ (collected_number)mdi->MSSQLDatabaseTransactions.current.Data);
2566
+
2567
+ rrdset_done(mdi->st_db_transactions);
2568
+}
2569
+
2570
+static void mssql_write_transactions_chart(struct mssql_db_instance *mdi, const char *db, int update_every)
2571
+{
2572
+ char id[RRD_ID_LENGTH_MAX + 1];
2573
+
2574
+ if (unlikely(!mdi->st_db_write_transactions)) {
2575
+ snprintfz(id, RRD_ID_LENGTH_MAX, "db_%s_instance_%s_write_transactions", db, mdi->parent->instanceID);
2576
+ netdata_fix_chart_name(id);
2577
+ mdi->st_db_write_transactions = rrdset_create_localhost(
2578
+ "mssql",
2579
+ id,
2580
+ NULL,
2581
+ "transactions",
2582
+ "mssql.database_write_transactions",
2583
+ "Write transactions",
2584
+ "transactions/s",
2585
+ PLUGIN_WINDOWS_NAME,
2586
+ "PerflibMSSQL",
2587
+ PRIO_MSSQL_DATABASE_WRITE_TRANSACTIONS,
2588
+ update_every,
2589
+ RRDSET_TYPE_LINE);
2590
+
2591
+ rrdlabels_add(
2592
+ mdi->st_db_write_transactions->rrdlabels, "mssql_instance", mdi->parent->instanceID, RRDLABEL_SRC_AUTO);
2593
+ rrdlabels_add(mdi->st_db_write_transactions->rrdlabels, "database", db, RRDLABEL_SRC_AUTO);
2594
+
2595
+ mdi->rd_db_write_transactions =
2596
+ rrddim_add(mdi->st_db_write_transactions, "write", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
2597
+ }
2598
+
2599
+ rrddim_set_by_pointer(
2600
+ mdi->st_db_write_transactions,
2601
+ mdi->rd_db_write_transactions,
2602
+ (collected_number)mdi->MSSQLDatabaseWriteTransactions.current.Data);
2603
+
2604
+ rrdset_done(mdi->st_db_write_transactions);
2605
+}
2606
+
2607
+static void mssql_lockwait_chart(struct mssql_db_instance *mdi, const char *db, int update_every)
2608
+{
2609
+ char id[RRD_ID_LENGTH_MAX + 1];
2610
+
2611
+ if (unlikely(!mdi->st_db_lockwait)) {
2612
+ snprintfz(id, RRD_ID_LENGTH_MAX, "db_%s_instance_%s_lockwait", db, mdi->parent->instanceID);
2613
+ netdata_fix_chart_name(id);
2614
+ mdi->st_db_lockwait = rrdset_create_localhost(
2615
+ "mssql",
2616
+ id,
2617
+ NULL,
2618
+ "locks",
2619
+ "mssql.database_lockwait",
2620
+ "Lock requests that required the caller to wait.",
2621
+ "locks/s",
2622
+ PLUGIN_WINDOWS_NAME,
2623
+ "PerflibMSSQL",
2624
+ PRIO_MSSQL_DATABASE_LOCKWAIT_PER_SECOND,
2625
+ update_every,
2626
+ RRDSET_TYPE_LINE);
2627
+
2628
+ rrdlabels_add(mdi->st_db_lockwait->rrdlabels, "mssql_instance", mdi->parent->instanceID, RRDLABEL_SRC_AUTO);
2629
+ rrdlabels_add(mdi->st_db_lockwait->rrdlabels, "database", db, RRDLABEL_SRC_AUTO);
2630
+
2631
+ mdi->rd_db_lockwait = rrddim_add(mdi->st_db_lockwait, "lock", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
2632
+ }
2633
+
2634
+ rrddim_set_by_pointer(
2635
+ mdi->st_db_lockwait, mdi->rd_db_lockwait, (collected_number)mdi->MSSQLDatabaseLockWaitSec.current.Data);
2636
+
2637
+ rrdset_done(mdi->st_db_lockwait);
2638
+}
2639
+
2640
+static void mssql_deadlock_chart(struct mssql_db_instance *mdi, const char *db, int update_every)
2641
+{
2642
+ char id[RRD_ID_LENGTH_MAX + 1];
2643
+
2644
+ if (unlikely(!mdi->st_db_deadlock)) {
2645
+ snprintfz(id, RRD_ID_LENGTH_MAX, "db_%s_instance_%s_deadlocks", db, mdi->parent->instanceID);
2646
+ netdata_fix_chart_name(id);
2647
+ mdi->st_db_deadlock = rrdset_create_localhost(
2648
+ "mssql",
2649
+ id,
2650
+ NULL,
2651
+ "locks",
2652
+ "mssql.database_deadlocks",
2653
+ "Lock requests that resulted in deadlock.",
2654
+ "deadlocks/s",
2655
+ PLUGIN_WINDOWS_NAME,
2656
+ "PerflibMSSQL",
2657
+ PRIO_MSSQL_DATABASE_DEADLOCKS_PER_SECOND,
2658
+ update_every,
2659
+ RRDSET_TYPE_LINE);
2660
+
2661
+ rrdlabels_add(mdi->st_db_deadlock->rrdlabels, "mssql_instance", mdi->parent->instanceID, RRDLABEL_SRC_AUTO);
2662
+ rrdlabels_add(mdi->st_db_deadlock->rrdlabels, "database", db, RRDLABEL_SRC_AUTO);
2663
+
2664
+ mdi->rd_db_deadlock = rrddim_add(mdi->st_db_deadlock, "deadlocks", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
2665
+ }
2666
+
2667
+ rrddim_set_by_pointer(
2668
+ mdi->st_db_deadlock, mdi->rd_db_deadlock, (collected_number)mdi->MSSQLDatabaseDeadLockSec.current.Data);
2669
+
2670
+ rrdset_done(mdi->st_db_deadlock);
2671
+}
2672
+
2673
+static void mssql_is_readonly_chart(struct mssql_db_instance *mdi, const char *db, int update_every)
2674
+{
2675
+ if (unlikely(!mdi->st_db_readonly)) {
2676
+ char id[RRD_ID_LENGTH_MAX + 1];
2677
+ snprintfz(id, RRD_ID_LENGTH_MAX, "db_%s_instance_%s_readonly", db, mdi->parent->instanceID);
2678
+ netdata_fix_chart_name(id);
2679
+ mdi->st_db_readonly = rrdset_create_localhost(
2680
+ "mssql",
2681
+ id,
2682
+ NULL,
2683
+ "locks",
2684
+ "mssql.database_readonly",
2685
+ "Current database write status.",
2686
+ "status",
2687
+ PLUGIN_WINDOWS_NAME,
2688
+ "PerflibMSSQL",
2689
+ PRIO_MSSQL_DATABASE_READONLY,
2690
+ update_every,
2691
+ RRDSET_TYPE_LINE);
2692
+
2693
+ rrdlabels_add(mdi->st_db_readonly->rrdlabels, "mssql_instance", mdi->parent->instanceID, RRDLABEL_SRC_AUTO);
2694
+ rrdlabels_add(mdi->st_db_readonly->rrdlabels, "database", db, RRDLABEL_SRC_AUTO);
2695
+
2696
+ mdi->rd_db_readonly_yes = rrddim_add(mdi->st_db_readonly, "writable", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
2697
+ mdi->rd_db_readonly_no = rrddim_add(mdi->st_db_readonly, "readonly", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
2698
+ }
2699
+
2700
+ rrddim_set_by_pointer(
2701
+ mdi->st_db_readonly, mdi->rd_db_readonly_no, (collected_number)mdi->MSSQLDBIsReadonly.current.Data);
2702
+
2703
+ collected_number opposite = (mdi->MSSQLDBIsReadonly.current.Data) ? 0 : 1;
2704
+ rrddim_set_by_pointer(mdi->st_db_readonly, mdi->rd_db_readonly_yes, (collected_number)opposite);
2705
+
2706
+ rrdset_done(mdi->st_db_readonly);
2707
+}
2708
+
2709
+static void mssql_db_states_chart(struct mssql_db_instance *mdi, const char *db, int update_every)
2710
+{
2711
+ if (unlikely(!mdi->st_db_state)) {
2712
+ char id[RRD_ID_LENGTH_MAX + 1];
2713
+ snprintfz(id, RRD_ID_LENGTH_MAX, "db_%s_instance_%s_state", db, mdi->parent->instanceID);
2714
+ netdata_fix_chart_name(id);
2715
+ mdi->st_db_state = rrdset_create_localhost(
2716
+ "mssql",
2717
+ id,
2718
+ NULL,
2719
+ "locks",
2720
+ "mssql.database_state",
2721
+ "Current database state.",
2722
+ "status",
2723
+ PLUGIN_WINDOWS_NAME,
2724
+ "PerflibMSSQL",
2725
+ PRIO_MSSQL_DATABASE_STATE,
2726
+ update_every,
2727
+ RRDSET_TYPE_LINE);
2728
+
2729
+ rrdlabels_add(mdi->st_db_state->rrdlabels, "mssql_instance", mdi->parent->instanceID, RRDLABEL_SRC_AUTO);
2730
+ rrdlabels_add(mdi->st_db_state->rrdlabels, "database", db, RRDLABEL_SRC_AUTO);
2731
+
2732
+ mdi->rd_db_state[0] = rrddim_add(mdi->st_db_state, "online", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
2733
+ mdi->rd_db_state[1] = rrddim_add(mdi->st_db_state, "restoring", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
2734
+ mdi->rd_db_state[2] = rrddim_add(mdi->st_db_state, "recovering", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
2735
+ mdi->rd_db_state[3] = rrddim_add(mdi->st_db_state, "recovering_pending", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
2736
+ mdi->rd_db_state[4] = rrddim_add(mdi->st_db_state, "suspect", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
2737
+ mdi->rd_db_state[5] = rrddim_add(mdi->st_db_state, "offline", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
2738
+ }
2739
+}
2740
+
2741
+static void mssql_db_state_chart_loop(struct mssql_db_instance *mdi, const char *db, int update_every)
2742
+{
2743
+ collected_number set_value =
2744
+ (mdi->MSSQLDBState.current.Data < 5) ? (collected_number)mdi->MSSQLDBState.current.Data : 5;
2745
+ mssql_db_states_chart(mdi, db, update_every);
2746
+ for (collected_number i; i < NETDATA_DB_STATES; i++) {
2747
+ rrddim_set_by_pointer(mdi->st_db_state, mdi->rd_db_state[i], i == set_value);
2748
+ }
2749
+ rrdset_done(mdi->st_db_state);
2750
+}
2751
+
2752
+static void mssql_lock_request_chart(struct mssql_db_instance *mdi, const char *db, int update_every)
2753
+{
2754
+ char id[RRD_ID_LENGTH_MAX + 1];
2755
+
2756
+ if (unlikely(!mdi->st_lock_requests)) {
2757
+ snprintfz(id, RRD_ID_LENGTH_MAX, "db_%s_instance_%s_lock_requests", db, mdi->parent->instanceID);
2758
+ netdata_fix_chart_name(id);
2759
+ mdi->st_lock_requests = rrdset_create_localhost(
2760
+ "mssql",
2761
+ id,
2762
+ NULL,
2763
+ "locks",
2764
+ "mssql.database_lock_requests",
2765
+ "Number of new locks and lock conversions requested.",
2766
+ "requests/s",
2767
+ PLUGIN_WINDOWS_NAME,
2768
+ "PerflibMSSQL",
2769
+ PRIO_MSSQL_DATABASE_LOCK_REQUESTS_SEC,
2770
+ update_every,
2771
+ RRDSET_TYPE_LINE);
2772
+
2773
+ rrdlabels_add(mdi->st_lock_requests->rrdlabels, "mssql_instance", mdi->parent->instanceID, RRDLABEL_SRC_AUTO);
2774
+ rrdlabels_add(mdi->st_lock_requests->rrdlabels, "database", db, RRDLABEL_SRC_AUTO);
2775
+
2776
+ mdi->rd_lock_requests = rrddim_add(mdi->st_lock_requests, "requests", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
2777
+ }
2778
+
2779
+ rrddim_set_by_pointer(
2780
+ mdi->st_lock_requests, mdi->rd_lock_requests, (collected_number)mdi->MSSQLDatabaseLockRequestsSec.current.Data);
2781
+
2782
+ rrdset_done(mdi->st_lock_requests);
2783
+}
2784
+
2785
+static void mssql_lock_timeout_chart(struct mssql_db_instance *mdi, const char *db, int update_every)
2786
+{
2787
+ char id[RRD_ID_LENGTH_MAX + 1];
2788
+
2789
+ if (unlikely(!mdi->st_lock_timeouts)) {
2790
+ snprintfz(id, RRD_ID_LENGTH_MAX, "db_%s_instance_%s_lock_timeouts", db, mdi->parent->instanceID);
2791
+ netdata_fix_chart_name(id);
2792
+ mdi->st_lock_timeouts = rrdset_create_localhost(
2793
+ "mssql",
2794
+ id,
2795
+ NULL,
2796
+ "locks",
2797
+ "mssql.database_lock_timeouts",
2798
+ "Lock that timed out.",
2799
+ "timeouts/s",
2800
+ PLUGIN_WINDOWS_NAME,
2801
+ "PerflibMSSQL",
2802
+ PRIO_MSSQL_DATABASE_LOCKS_TIMEOUT_PER_SECOND,
2803
+ update_every,
2804
+ RRDSET_TYPE_LINE);
2805
+
2806
+ rrdlabels_add(mdi->st_lock_timeouts->rrdlabels, "mssql_instance", mdi->parent->instanceID, RRDLABEL_SRC_AUTO);
2807
+ rrdlabels_add(mdi->st_lock_timeouts->rrdlabels, "database", db, RRDLABEL_SRC_AUTO);
2808
+
2809
+ mdi->rd_lock_timeouts = rrddim_add(mdi->st_lock_timeouts, "timeouts", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
2810
+ }
2811
+
2812
+ rrddim_set_by_pointer(
2813
+ mdi->st_lock_timeouts, mdi->rd_lock_timeouts, (collected_number)mdi->MSSQLDatabaseLockTimeoutsSec.current.Data);
2814
+
2815
+ rrdset_done(mdi->st_lock_timeouts);
2816
+}
2817
+
2818
+static void mssql_active_transactions_chart(struct mssql_db_instance *mdi, const char *db, int update_every)
2819
+{
2820
+ char id[RRD_ID_LENGTH_MAX + 1];
2821
+
2822
+ if (unlikely(!mdi->st_db_active_transactions)) {
2823
+ snprintfz(id, RRD_ID_LENGTH_MAX, "db_%s_instance_%s_active_transactions", db, mdi->parent->instanceID);
2824
+ netdata_fix_chart_name(id);
2825
+ mdi->st_db_active_transactions = rrdset_create_localhost(
2826
+ "mssql",
2827
+ id,
2828
+ NULL,
2829
+ "transactions",
2830
+ "mssql.database_active_transactions",
2831
+ "Active transactions per database",
2832
+ "transactions",
2833
+ PLUGIN_WINDOWS_NAME,
2834
+ "PerflibMSSQL",
2835
+ PRIO_MSSQL_DATABASE_ACTIVE_TRANSACTIONS,
2836
+ update_every,
2837
+ RRDSET_TYPE_LINE);
2838
+
2839
+ rrdlabels_add(
2840
+ mdi->st_db_active_transactions->rrdlabels, "mssql_instance", mdi->parent->instanceID, RRDLABEL_SRC_AUTO);
2841
+ rrdlabels_add(mdi->st_db_active_transactions->rrdlabels, "database", db, RRDLABEL_SRC_AUTO);
2842
+
2843
+ mdi->rd_db_active_transactions =
2844
+ rrddim_add(mdi->st_db_active_transactions, "active", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
2845
+ }
2846
+
2847
+ rrddim_set_by_pointer(
2848
+ mdi->st_db_active_transactions,
2849
+ mdi->rd_db_active_transactions,
2850
+ (collected_number)mdi->MSSQLDatabaseActiveTransactions.current.Data);
2851
+
2852
+ rrdset_done(mdi->st_db_active_transactions);
2853
+}
2854
+
2855
+static inline void mssql_data_file_size_chart(struct mssql_db_instance *mdi, const char *db, int update_every)
2856
+{
2857
+ char id[RRD_ID_LENGTH_MAX + 1];
2858
+
2859
+ if (unlikely(!mdi->st_db_data_file_size)) {
2860
+ snprintfz(id, RRD_ID_LENGTH_MAX, "db_%s_instance_%s_data_files_size", db, mdi->parent->instanceID);
2861
+ netdata_fix_chart_name(id);
2862
+ mdi->st_db_data_file_size = rrdset_create_localhost(
2863
+ "mssql",
2864
+ id,
2865
+ NULL,
2866
+ "size",
2867
+ "mssql.database_data_files_size",
2868
+ "Current database size.",
2869
+ "bytes",
2870
+ PLUGIN_WINDOWS_NAME,
2871
+ "PerflibMSSQL",
2872
+ PRIO_MSSQL_DATABASE_DATA_FILE_SIZE,
2873
+ update_every,
2874
+ RRDSET_TYPE_LINE);
2875
+
2876
+ rrdlabels_add(
2877
+ mdi->st_db_data_file_size->rrdlabels, "mssql_instance", mdi->parent->instanceID, RRDLABEL_SRC_AUTO);
2878
+ rrdlabels_add(mdi->st_db_data_file_size->rrdlabels, "database", db, RRDLABEL_SRC_AUTO);
2879
+
2880
+ mdi->rd_db_data_file_size = rrddim_add(mdi->st_db_data_file_size, "size", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
2881
+ }
2882
+
2883
+ collected_number data = mdi->MSSQLDatabaseDataFileSize.current.Data;
2884
+ rrddim_set_by_pointer(mdi->st_db_data_file_size, mdi->rd_db_data_file_size, data);
2885
+
2886
+ rrdset_done(mdi->st_db_data_file_size);
2887
+}
2888
+
2889
+int dict_mssql_databases_charts_cb(const DICTIONARY_ITEM *item __maybe_unused, void *value, void *data __maybe_unused)
2890
+{
2891
+ struct mssql_db_instance *mdi = value;
2892
+ const char *db = dictionary_acquired_item_name((DICTIONARY_ITEM *)item);
2893
+
2894
+ if (unlikely(!mdi->collecting_data)) {
2895
+ goto endchartcb;
2896
+ }
2897
+
2898
+ int *update_every = data;
2899
+
2900
+ void (*transaction_chart[])(struct mssql_db_instance *, const char *, int) = {
2901
+ mssql_data_file_size_chart,
2902
+ mssql_transactions_chart,
2903
+ mssql_database_backup_restore_chart,
2904
+ mssql_database_log_flushed_chart,
2905
+ mssql_database_log_flushes_chart,
2906
+ mssql_active_transactions_chart,
2907
+ mssql_write_transactions_chart,
2908
+ mssql_lockwait_chart,
2909
+ mssql_deadlock_chart,
2910
+ mssql_is_readonly_chart,
2911
+ mssql_db_state_chart_loop,
2912
+ mssql_lock_timeout_chart,
2913
+ mssql_lock_request_chart,
2914
+
2915
+ // Last function pointer must be NULL
2916
+ NULL};
2917
+
2918
+ int i;
2919
+ for (i = 0; transaction_chart[i]; i++) {
2920
+ transaction_chart[i](mdi, db, *update_every);
2921
+ }
2922
+
2923
+endchartcb:
2924
+ return 1;
2925
+}
2926
+
2927
+static void do_mssql_databases(PERF_DATA_BLOCK *pDataBlock, struct mssql_instance *mi, int update_every)
2928
+{
2929
+ if (unlikely(!pDataBlock))
2930
+ goto end_mssql_databases;
2931
+
2932
+ PERF_OBJECT_TYPE *pObjectType = perflibFindObjectTypeByName(pDataBlock, mi->objectName[NETDATA_MSSQL_DATABASE]);
2933
+ if (unlikely(!pObjectType))
2934
+ return;
2935
+
2936
+ PERF_INSTANCE_DEFINITION *pi = NULL;
2937
+ for (LONG i = 0; i < pObjectType->NumInstances; i++) {
2938
+ pi = perflibForEachInstance(pDataBlock, pObjectType, pi);
2939
+ if (unlikely(!pi))
2940
+ break;
2941
+
2942
+ if (unlikely(!getInstanceName(pDataBlock, pObjectType, pi, windows_shared_buffer, sizeof(windows_shared_buffer))))
2943
+ strncpyz(windows_shared_buffer, "[unknown]", sizeof(windows_shared_buffer) - 1);
2944
+
2945
+ if (unlikely(!strcasecmp(windows_shared_buffer, "_Total")))
2946
+ continue;
2947
+
2948
+ struct mssql_db_instance *mdi = dictionary_set(mi->databases, windows_shared_buffer, NULL, sizeof(*mdi));
2949
+ if (unlikely(!mdi))
2950
+ continue;
2951
+
2952
+ if (unlikely(!mdi->parent)) {
2953
+ mdi->parent = mi;
2954
+ }
2955
+
2956
+ if (unlikely(!i))
2957
+ mdi->collect_instance = true;
2958
+ }
2959
+
2960
+end_mssql_databases:
2961
+ dictionary_sorted_walkthrough_read(mi->databases, dict_mssql_databases_charts_cb, &update_every);
2962
+}
2963
+
2964
+int dict_mssql_charts_cb(const DICTIONARY_ITEM *item __maybe_unused, void *value, void *data __maybe_unused)
2965
+{
2966
+ struct mssql_instance *mi = value;
2967
+ int *update_every = data;
2968
+
2969
+ static void (*doMSSQL[])(PERF_DATA_BLOCK *, struct mssql_instance *, int) = {
2970
+ do_mssql_general_stats,
2971
+ do_mssql_errors,
2972
+ do_mssql_memory_mgr,
2973
+ do_mssql_statistics_perflib,
2974
+ do_mssql_access_methods,
2975
+
2976
+ do_mssql_databases,
2977
+ do_mssql_locks,
2978
+ do_mssql_waits,
2979
+ do_mssql_bufferman_stats_sql,
2980
+ do_mssql_job_status_sql,
2981
+
2982
+ NULL};
2983
+
2984
+ DWORD i;
2985
+ PERF_DATA_BLOCK *pDataBlock;
2986
+ static bool collect_perflib[NETDATA_MSSQL_METRICS_END] = {
2987
+ true, true, true, true, true, true, true, true, true, true};
2988
+ for (i = 0; i < NETDATA_MSSQL_ACCESS_METHODS; i++) {
2989
+ if (unlikely(!collect_perflib[i]))
2990
+ continue;
2991
+
2992
+ pDataBlock = netdata_mssql_get_perf_data_block(collect_perflib, mi, i);
2993
+ if (unlikely(!pDataBlock))
2994
+ continue;
2995
+
2996
+ doMSSQL[i](pDataBlock, mi, *update_every);
2997
+ }
2998
+
2999
+ if (unlikely(unlikely(!mi->conn || !mi->conn->is_connected)))
3000
+ return 1;
3001
+
3002
+ for (i = NETDATA_MSSQL_DATABASE; doMSSQL[i]; i++) {
3003
+ pDataBlock = (collect_perflib[i]) ? netdata_mssql_get_perf_data_block(collect_perflib, mi, i) : NULL;
3004
+
3005
+ doMSSQL[i](pDataBlock, mi, *update_every);
3006
+ }
3007
+
3008
+ do_mssql_replication(mi, *update_every);
3009
+
3010
+ return 1;
3011
+}
3012
+
3013
+// Entry point
3014
+
3015
+int do_PerflibMSSQL(int update_every, usec_t dt __maybe_unused)
3016
+{
3017
+ static bool initialized = false;
3018
+
3019
+ if (unlikely(!initialized)) {
3020
+ if (initialize(update_every))
3021
+ return -1;
3022
+
3023
+ initialized = true;
3024
+ }
3025
+
3026
+ dictionary_sorted_walkthrough_read(mssql_instances, dict_mssql_charts_cb, &update_every);
3027
+
3028
+ return 0;
3029
+}
3030
+
3031
+void do_PerflibMSSQL_cleanup()
3032
+{
3033
+ if (likely(nd_thread_join(mssql_queries_thread)))
3034
+ nd_log_daemon(NDLP_ERR, "Failed to join mssql queries thread");
3035
+}
src/collectors/windows.plugin/perflib-mssql-queries.h
+348
@@ -3,6 +3,10 @@
3
#ifndef NETDATA_PERFLIB_MSSQL_QUERIES_H
4
#define NETDATA_PERFLIB_MSSQL_QUERIES_H
5
6
+#include <sqlext.h>
7
+#include <sqltypes.h>
8
+#include <sql.h>
9
+
10
// https://learn.microsoft.com/en-us/sql/relational-databases/system-dynamic-management-views/sys-dm-tran-locks-transact-sql?view=sql-server-ver16
11
#define NETDATA_QUERY_LOCKS_MASK \
12
"SELECT resource_type, count(*) FROM %s.sys.dm_tran_locks WHERE DB_NAME(resource_database_id) = '%s' group by resource_type;"
@@ -631,4 +635,348 @@
635
N'SOS_WORK_DISPATCHER', \
636
'RESERVED_MEMORY_ALLOCATION_EXT') AND ws.[waiting_tasks_count] > 0 AND ws.[wait_time_ms] > 100;"
637
638
+#ifndef MEGA_FACTOR
639
+#define MEGA_FACTOR (1048576) // 1024 * 1024
640
+#endif
641
+// https://learn.microsoft.com/en-us/sql/sql-server/install/instance-configuration?view=sql-server-ver16
642
+#define NETDATA_MAX_INSTANCE_NAME (32)
643
+#define NETDATA_MAX_INSTANCE_OBJECT (128)
644
+// https://learn.microsoft.com/en-us/previous-versions/sql/sql-server-2008-r2/ms191240(v=sql.105)#sysname
645
+#define SQLSERVER_MAX_NAME_LENGTH NETDATA_MAX_INSTANCE_OBJECT
646
+#define NETDATA_MSSQL_NEXT_TRY (60)
647
+
648
+struct netdata_mssql_conn {
649
+ const char *instance;
650
+ const char *driver;
651
+ const char *server;
652
+ const char *address;
653
+ const char *username;
654
+ const char *password;
655
+ int instances;
656
+ bool windows_auth;
657
+ bool is_sqlexpress;
658
+
659
+ SQLCHAR *connectionString;
660
+
661
+ SQLHENV netdataSQLEnv;
662
+ SQLHDBC netdataSQLHDBc;
663
+
664
+ SQLHSTMT checkPermSTMT;
665
+ SQLHSTMT databaseListSTMT;
666
+ SQLHSTMT dataFileSizeSTMT;
667
+ SQLHSTMT dbTransactionSTMT;
668
+ SQLHSTMT dbInstanceTransactionSTMT;
669
+ SQLHSTMT dbWaitsSTMT;
670
+ SQLHSTMT dbLocksSTMT;
671
+ SQLHSTMT dbSQLState;
672
+ SQLHSTMT dbSQLJobs;
673
+ SQLHSTMT dbReplicationPublisher;
674
+
675
+ BOOL is_connected;
676
+};
677
+
678
+enum netdata_mssql_metrics {
679
+ NETDATA_MSSQL_GENERAL_STATS,
680
+ NETDATA_MSSQL_SQL_ERRORS,
681
+ NETDATA_MSSQL_MEMORY,
682
+ NETDATA_MSSQL_SQL_STATS,
683
+ NETDATA_MSSQL_ACCESS_METHODS,
684
+
685
+ NETDATA_MSSQL_DATABASE,
686
+ NETDATA_MSSQL_LOCKS,
687
+ NETDATA_MSSQL_WAITS,
688
+ NETDATA_MSSQL_BUFFER_MANAGEMENT,
689
+ NETDATA_MSSQL_JOBS,
690
+
691
+ NETDATA_MSSQL_METRICS_END
692
+};
693
+
694
+struct mssql_db_waits {
695
+ const char *wait_type;
696
+ const char *wait_category;
697
+
698
+ RRDSET *st_total_wait;
699
+ RRDDIM *rd_total_wait;
700
+
701
+ RRDSET *st_resource_wait_msec;
702
+ RRDDIM *rd_resource_wait_msec;
703
+
704
+ RRDSET *st_signal_wait_msec;
705
+ RRDDIM *rd_signal_wait_msec;
706
+
707
+ RRDSET *st_max_wait_time_msec;
708
+ RRDDIM *rd_max_wait_time_msec;
709
+
710
+ RRDSET *st_waiting_tasks;
711
+ RRDDIM *rd_waiting_tasks;
712
+
713
+ COUNTER_DATA MSSQLDatabaseTotalWait;
714
+ COUNTER_DATA MSSQLDatabaseResourceWaitMSec;
715
+ COUNTER_DATA MSSQLDatabaseSignalWaitMSec;
716
+ COUNTER_DATA MSSQLDatabaseMaxWaitTimeMSec;
717
+ COUNTER_DATA MSSQLDatabaseWaitingTasks;
718
+};
719
+
720
+// https://learn.microsoft.com/en-us/sql/relational-databases/system-stored-procedures/sp-replmonitorhelppublication-transact-sql?view=sql-server-ver17
721
+struct mssql_publisher_publication {
722
+ struct mssql_instance *parent;
723
+
724
+ // Lables
725
+ char *publisher;
726
+ char *publication;
727
+ char *db;
728
+ int type;
729
+
730
+ // Charts
731
+ int status;
732
+ int warning;
733
+
734
+ int avg_latency;
735
+
736
+ int retention;
737
+
738
+ int subscriptioncount;
739
+ int runningdistagentcount;
740
+
741
+ int average_runspeedPerf;
742
+
743
+ RRDSET *st_publisher_status;
744
+ RRDDIM *rd_publisher_status_started;
745
+ RRDDIM *rd_publisher_status_successed;
746
+ RRDDIM *rd_publisher_status_in_progress;
747
+ RRDDIM *rd_publisher_status_idle;
748
+ RRDDIM *rd_publisher_status_retrying;
749
+ RRDDIM *rd_publisher_status_failed;
750
+
751
+ RRDSET *st_warning;
752
+ RRDDIM *rd_warning_expiration;
753
+ RRDDIM *rd_warning_latency;
754
+ RRDDIM *rd_warning_mergeeexpiration;
755
+ RRDDIM *rd_warning_mergefastduration;
756
+ RRDDIM *rd_warning_mergelowduration;
757
+ RRDDIM *rd_warning_mergefastrunspeed;
758
+ RRDDIM *rd_warning_mergelowrunspeed;
759
+
760
+ RRDSET *st_avg_latency;
761
+ RRDDIM *rd_avg_latency;
762
+
763
+ RRDSET *st_retention;
764
+ RRDDIM *rd_retention;
765
+
766
+ RRDSET *st_subscription_count;
767
+ RRDDIM *rd_subscription_count;
768
+
769
+ RRDSET *st_running_agent;
770
+ RRDDIM *rd_running_agent;
771
+
772
+ RRDSET *st_synchronization_time;
773
+ RRDDIM *rd_synchronization_time;
774
+};
775
+
776
+struct mssql_instance {
777
+ char *instanceID;
778
+ int update_every;
779
+
780
+ struct netdata_mssql_conn *conn;
781
+
782
+ char *objectName[NETDATA_MSSQL_METRICS_END];
783
+
784
+ RRDSET *st_user_connections;
785
+ RRDDIM *rd_user_connections;
786
+
787
+ RRDSET *st_process_blocked;
788
+ RRDDIM *rd_process_blocked;
789
+
790
+ RRDSET *st_stats_auto_param;
791
+ RRDDIM *rd_stats_auto_param;
792
+
793
+ RRDSET *st_stats_batch_request;
794
+ RRDDIM *rd_stats_batch_request;
795
+
796
+ RRDSET *st_stats_safe_auto;
797
+ RRDDIM *rd_stats_safe_auto;
798
+
799
+ RRDSET *st_access_method_page_splits;
800
+ RRDDIM *rd_access_method_page_splits;
801
+
802
+ RRDSET *st_sql_errors;
803
+ RRDDIM *rd_sql_errors;
804
+
805
+ DICTIONARY *locks_instances;
806
+
807
+ DICTIONARY *databases;
808
+ DICTIONARY *sysjobs;
809
+ DICTIONARY *publisher_publication;
810
+
811
+ RRDSET *st_conn_memory;
812
+ RRDDIM *rd_conn_memory;
813
+
814
+ RRDSET *st_ext_benefit_mem;
815
+ RRDDIM *rd_ext_benefit_mem;
816
+
817
+ RRDSET *st_pending_mem_grant;
818
+ RRDDIM *rd_pending_mem_grant;
819
+
820
+ RRDSET *st_mem_tot_server;
821
+ RRDDIM *rd_mem_tot_server;
822
+
823
+ DICTIONARY *waits;
824
+
825
+ COUNTER_DATA MSSQLAccessMethodPageSplits;
826
+ COUNTER_DATA MSSQLBlockedProcesses;
827
+ COUNTER_DATA MSSQLUserConnections;
828
+ COUNTER_DATA MSSQLConnectionMemoryBytes;
829
+ COUNTER_DATA MSSQLExternalBenefitOfMemory;
830
+ COUNTER_DATA MSSQLPendingMemoryGrants;
831
+ COUNTER_DATA MSSQLSQLErrorsTotal;
832
+ COUNTER_DATA MSSQLTotalServerMemory;
833
+ COUNTER_DATA MSSQLStatsAutoParameterization;
834
+ COUNTER_DATA MSSQLStatsBatchRequests;
835
+ COUNTER_DATA MSSQLStatSafeAutoParameterization;
836
+};
837
+
838
+struct mssql_lock_instance {
839
+ struct mssql_instance *parent;
840
+
841
+ char *resourceID;
842
+
843
+ COUNTER_DATA lockWait;
844
+ COUNTER_DATA deadLocks;
845
+
846
+ RRDSET *st_deadLocks;
847
+ RRDDIM *rd_lockWait;
848
+
849
+ RRDSET *st_lockWait;
850
+ RRDDIM *rd_deadLocks;
851
+};
852
+
853
+struct mssql_db_jobs {
854
+ bool enabled;
855
+
856
+ RRDSET *st_status;
857
+ RRDDIM *rd_status_enabled;
858
+ RRDDIM *rd_status_disabled;
859
+
860
+ COUNTER_DATA MSSQLJOBState;
861
+};
862
+
863
+struct mssql_db_instance {
864
+ struct mssql_instance *parent;
865
+
866
+ bool collecting_data;
867
+ bool collect_instance;
868
+ bool running_replication;
869
+
870
+ RRDSET *st_db_data_file_size;
871
+ RRDSET *st_db_active_transactions;
872
+ RRDSET *st_db_backup_restore_operations;
873
+ RRDSET *st_db_log_flushed;
874
+ RRDSET *st_db_log_flushes;
875
+ RRDSET *st_db_transactions;
876
+ RRDSET *st_db_write_transactions;
877
+ RRDSET *st_db_lockwait;
878
+ RRDSET *st_db_deadlock;
879
+ RRDSET *st_db_readonly;
880
+ RRDSET *st_db_state;
881
+ RRDSET *st_lock_timeouts;
882
+ RRDSET *st_lock_requests;
883
+ RRDSET *st_buff_page_iops;
884
+ RRDSET *st_buff_cache_hits;
885
+ RRDSET *st_buff_checkpoint_pages;
886
+ RRDSET *st_buff_cache_page_life_expectancy;
887
+ RRDSET *st_buff_lazy_write;
888
+ RRDSET *st_buff_page_lookups;
889
+
890
+ RRDSET *st_stats_compilation;
891
+ RRDSET *st_stats_recompiles;
892
+
893
+ RRDDIM *rd_db_data_file_size;
894
+ RRDDIM *rd_db_active_transactions;
895
+ RRDDIM *rd_db_backup_restore_operations;
896
+ RRDDIM *rd_db_log_flushed;
897
+ RRDDIM *rd_db_log_flushes;
898
+ RRDDIM *rd_db_transactions;
899
+ RRDDIM *rd_db_write_transactions;
900
+ RRDDIM *rd_db_lockwait;
901
+ RRDDIM *rd_db_deadlock;
902
+ RRDDIM *rd_db_readonly_yes;
903
+ RRDDIM *rd_db_readonly_no;
904
+ RRDDIM *rd_db_state[NETDATA_DB_STATES];
905
+ RRDDIM *rd_lock_timeouts;
906
+ RRDDIM *rd_lock_requests;
907
+ RRDDIM *rd_buff_page_reads;
908
+ RRDDIM *rd_buff_page_writes;
909
+ RRDDIM *rd_buff_cache_hits;
910
+ RRDDIM *rd_buff_checkpoint_pages;
911
+ RRDDIM *rd_buff_cache_page_life_expectancy;
912
+ RRDDIM *rd_buff_lazy_write;
913
+ RRDDIM *rd_buff_page_lookups;
914
+
915
+ RRDDIM *rd_stats_compilation;
916
+ RRDDIM *rd_stats_recompiles;
917
+
918
+ COUNTER_DATA MSSQLDatabaseDataFileSize;
919
+
920
+ COUNTER_DATA MSSQLDatabaseActiveTransactions;
921
+ COUNTER_DATA MSSQLDatabaseBackupRestoreOperations;
922
+ COUNTER_DATA MSSQLDatabaseLogFlushed;
923
+ COUNTER_DATA MSSQLDatabaseLogFlushes;
924
+ COUNTER_DATA MSSQLDatabaseTransactions;
925
+ COUNTER_DATA MSSQLDatabaseWriteTransactions;
926
+
927
+ COUNTER_DATA MSSQLDatabaseLockWaitSec;
928
+ COUNTER_DATA MSSQLDatabaseDeadLockSec;
929
+ COUNTER_DATA MSSQLDatabaseLockTimeoutsSec;
930
+ COUNTER_DATA MSSQLDatabaseLockRequestsSec;
931
+
932
+ // Buffer Management (https://learn.microsoft.com/en-us/sql/relational-databases/performance-monitor/sql-server-buffer-manager-object)
933
+ COUNTER_DATA MSSQLBufferPageReads;
934
+ COUNTER_DATA MSSQLBufferPageWrites;
935
+ COUNTER_DATA MSSQLBufferCacheHits;
936
+ COUNTER_DATA MSSQLBufferCheckpointPages;
937
+ COUNTER_DATA MSSQLBufferPageLifeExpectancy;
938
+ COUNTER_DATA MSSQLBufferLazyWrite;
939
+ COUNTER_DATA MSSQLBufferPageLookups;
940
+
941
+ COUNTER_DATA MSSQLCompilations;
942
+ COUNTER_DATA MSSQLRecompilations;
943
+
944
+ COUNTER_DATA MSSQLDBIsReadonly;
945
+ COUNTER_DATA MSSQLDBState;
946
+
947
+ uint32_t updated;
948
+};
949
+
950
+enum netdata_mssql_odbc_errors {
951
+ NETDATA_MSSQL_ODBC_NO_ERROR,
952
+ NETDATA_MSSQL_ODBC_CONNECT,
953
+ NETDATA_MSSQL_ODBC_BIND,
954
+ NETDATA_MSSQL_ODBC_PREPARE,
955
+ NETDATA_MSSQL_ODBC_QUERY,
956
+ NETDATA_MSSQL_ODBC_FETCH
957
+};
958
+
959
+static inline PERF_DATA_BLOCK *
960
+netdata_mssql_get_perf_data_block(bool *collect_perflib, struct mssql_instance *mi, DWORD idx)
961
+{
962
+ DWORD id = RegistryFindIDByName(mi->objectName[idx]);
963
+ if (id == PERFLIB_REGISTRY_NAME_NOT_FOUND) {
964
+ collect_perflib[idx] = false;
965
+ return NULL;
966
+ }
967
+
968
+ PERF_DATA_BLOCK *pDataBlock = perflibGetPerformanceData(id);
969
+ if (!pDataBlock) {
970
+ collect_perflib[idx] = true;
971
+ return NULL;
972
+ }
973
+
974
+ return pDataBlock;
975
+}
976
+
977
+void do_mssql_general_stats(PERF_DATA_BLOCK *pDataBlock, struct mssql_instance *mi, int update_every);
978
+void do_mssql_errors(PERF_DATA_BLOCK *pDataBlock, struct mssql_instance *mi, int update_every);
979
+void do_mssql_memory_mgr(PERF_DATA_BLOCK *pDataBlock, struct mssql_instance *mi, int update_every);
980
+void do_mssql_statistics_perflib(PERF_DATA_BLOCK *pDataBlock, struct mssql_instance *mi, int update_every);
981
+void do_mssql_access_methods(PERF_DATA_BLOCK *pDataBlock, struct mssql_instance *mi, int update_every);
982
#endif
src/collectors/windows.plugin/perflib-mssql.c
+267
-3636
@@ -5,3557 +5,175 @@
5
6
#include "perflib-mssql-queries.h"
7
8
-#include <sqlext.h>
9
-#include <sqltypes.h>
10
-#include <sql.h>
11
-
12
-#define MEGA_FACTOR (1048576) // 1024 * 1024
13
-// https://learn.microsoft.com/en-us/sql/sql-server/install/instance-configuration?view=sql-server-ver16
14
-#define NETDATA_MAX_INSTANCE_NAME (32)
15
-#define NETDATA_MAX_INSTANCE_OBJECT (128)
16
-// https://learn.microsoft.com/en-us/previous-versions/sql/sql-server-2008-r2/ms191240(v=sql.105)#sysname
17
-#define SQLSERVER_MAX_NAME_LENGTH NETDATA_MAX_INSTANCE_OBJECT
18
-#define NETDATA_MSSQL_NEXT_TRY (60)
19
-
20
-struct netdata_mssql_conn {
21
- const char *instance;
22
- const char *driver;
23
- const char *server;
24
- const char *address;
25
- const char *username;
26
- const char *password;
27
- int instances;
28
- bool windows_auth;
29
- bool is_sqlexpress;
30
-
31
- SQLCHAR *connectionString;
32
-
33
- SQLHENV netdataSQLEnv;
34
- SQLHDBC netdataSQLHDBc;
35
-
36
- SQLHSTMT checkPermSTMT;
37
- SQLHSTMT databaseListSTMT;
38
- SQLHSTMT dataFileSizeSTMT;
39
- SQLHSTMT dbTransactionSTMT;
40
- SQLHSTMT dbInstanceTransactionSTMT;
41
- SQLHSTMT dbWaitsSTMT;
42
- SQLHSTMT dbLocksSTMT;
43
- SQLHSTMT dbSQLState;
44
- SQLHSTMT dbSQLJobs;
45
- SQLHSTMT dbReplicationPublisher;
46
-
47
- BOOL is_connected;
48
-};
49
-
50
-DICTIONARY *conn_options;
51
-
52
-enum netdata_mssql_metrics {
53
- NETDATA_MSSQL_GENERAL_STATS,
54
- NETDATA_MSSQL_SQL_ERRORS,
55
- NETDATA_MSSQL_MEMORY,
56
- NETDATA_MSSQL_SQL_STATS,
57
- NETDATA_MSSQL_ACCESS_METHODS,
58
-
59
- NETDATA_MSSQL_DATABASE,
60
- NETDATA_MSSQL_LOCKS,
61
- NETDATA_MSSQL_WAITS,
62
- NETDATA_MSSQL_BUFFER_MANAGEMENT,
63
- NETDATA_MSSQL_JOBS,
64
-
65
- NETDATA_MSSQL_METRICS_END
66
-};
67
-
68
-struct mssql_db_waits {
69
- const char *wait_type;
70
- const char *wait_category;
71
-
72
- RRDSET *st_total_wait;
73
- RRDDIM *rd_total_wait;
74
-
75
- RRDSET *st_resource_wait_msec;
76
- RRDDIM *rd_resource_wait_msec;
77
-
78
- RRDSET *st_signal_wait_msec;
79
- RRDDIM *rd_signal_wait_msec;
80
-
81
- RRDSET *st_max_wait_time_msec;
82
- RRDDIM *rd_max_wait_time_msec;
83
-
84
- RRDSET *st_waiting_tasks;
85
- RRDDIM *rd_waiting_tasks;
86
-
87
- COUNTER_DATA MSSQLDatabaseTotalWait;
88
- COUNTER_DATA MSSQLDatabaseResourceWaitMSec;
89
- COUNTER_DATA MSSQLDatabaseSignalWaitMSec;
90
- COUNTER_DATA MSSQLDatabaseMaxWaitTimeMSec;
91
- COUNTER_DATA MSSQLDatabaseWaitingTasks;
92
-};
93
-
94
-// https://learn.microsoft.com/en-us/sql/relational-databases/system-stored-procedures/sp-replmonitorhelppublication-transact-sql?view=sql-server-ver17
95
-struct mssql_publisher_publication {
96
- struct mssql_instance *parent;
97
-
98
- // Lables
99
- char *publisher;
100
- char *publication;
101
- char *db;
102
- int type;
103
-
104
- // Charts
105
- int status;
106
- int warning;
107
-
108
- int avg_latency;
109
-
110
- int retention;
111
-
112
- int subscriptioncount;
113
- int runningdistagentcount;
114
-
115
- int average_runspeedPerf;
116
-
117
- RRDSET *st_publisher_status;
118
- RRDDIM *rd_publisher_status_started;
119
- RRDDIM *rd_publisher_status_successed;
120
- RRDDIM *rd_publisher_status_in_progress;
121
- RRDDIM *rd_publisher_status_idle;
122
- RRDDIM *rd_publisher_status_retrying;
123
- RRDDIM *rd_publisher_status_failed;
124
-
125
- RRDSET *st_warning;
126
- RRDDIM *rd_warning_expiration;
127
- RRDDIM *rd_warning_latency;
128
- RRDDIM *rd_warning_mergeeexpiration;
129
- RRDDIM *rd_warning_mergefastduration;
130
- RRDDIM *rd_warning_mergelowduration;
131
- RRDDIM *rd_warning_mergefastrunspeed;
132
- RRDDIM *rd_warning_mergelowrunspeed;
133
-
134
- RRDSET *st_avg_latency;
135
- RRDDIM *rd_avg_latency;
136
-
137
- RRDSET *st_retention;
138
- RRDDIM *rd_retention;
139
-
140
- RRDSET *st_subscription_count;
141
- RRDDIM *rd_subscription_count;
142
-
143
- RRDSET *st_running_agent;
144
- RRDDIM *rd_running_agent;
145
-
146
- RRDSET *st_synchronization_time;
147
- RRDDIM *rd_synchronization_time;
148
-};
149
-
150
-struct mssql_instance {
151
- char *instanceID;
152
- int update_every;
153
-
154
- struct netdata_mssql_conn *conn;
155
-
156
- char *objectName[NETDATA_MSSQL_METRICS_END];
157
-
158
- RRDSET *st_user_connections;
159
- RRDDIM *rd_user_connections;
160
-
161
- RRDSET *st_process_blocked;
162
- RRDDIM *rd_process_blocked;
163
-
164
- RRDSET *st_stats_auto_param;
165
- RRDDIM *rd_stats_auto_param;
166
-
167
- RRDSET *st_stats_batch_request;
168
- RRDDIM *rd_stats_batch_request;
169
-
170
- RRDSET *st_stats_safe_auto;
171
- RRDDIM *rd_stats_safe_auto;
172
-
173
- RRDSET *st_access_method_page_splits;
174
- RRDDIM *rd_access_method_page_splits;
175
-
176
- RRDSET *st_sql_errors;
177
- RRDDIM *rd_sql_errors;
178
-
179
- DICTIONARY *locks_instances;
180
-
181
- DICTIONARY *databases;
182
- DICTIONARY *sysjobs;
183
- DICTIONARY *publisher_publication;
184
-
185
- RRDSET *st_conn_memory;
186
- RRDDIM *rd_conn_memory;
187
-
188
- RRDSET *st_ext_benefit_mem;
189
- RRDDIM *rd_ext_benefit_mem;
190
-
191
- RRDSET *st_pending_mem_grant;
192
- RRDDIM *rd_pending_mem_grant;
193
-
194
- RRDSET *st_mem_tot_server;
195
- RRDDIM *rd_mem_tot_server;
196
-
197
- DICTIONARY *waits;
198
-
199
- COUNTER_DATA MSSQLAccessMethodPageSplits;
200
- COUNTER_DATA MSSQLBlockedProcesses;
201
- COUNTER_DATA MSSQLUserConnections;
202
- COUNTER_DATA MSSQLConnectionMemoryBytes;
203
- COUNTER_DATA MSSQLExternalBenefitOfMemory;
204
- COUNTER_DATA MSSQLPendingMemoryGrants;
205
- COUNTER_DATA MSSQLSQLErrorsTotal;
206
- COUNTER_DATA MSSQLTotalServerMemory;
207
- COUNTER_DATA MSSQLStatsAutoParameterization;
208
- COUNTER_DATA MSSQLStatsBatchRequests;
209
- COUNTER_DATA MSSQLStatSafeAutoParameterization;
210
-};
211
-
212
-struct mssql_lock_instance {
213
- struct mssql_instance *parent;
214
-
215
- char *resourceID;
216
-
217
- COUNTER_DATA lockWait;
218
- COUNTER_DATA deadLocks;
219
-
220
- RRDSET *st_deadLocks;
221
- RRDDIM *rd_lockWait;
222
-
223
- RRDSET *st_lockWait;
224
- RRDDIM *rd_deadLocks;
225
-};
226
-
227
-struct mssql_db_jobs {
228
- bool enabled;
229
-
230
- RRDSET *st_status;
231
- RRDDIM *rd_status_enabled;
232
- RRDDIM *rd_status_disabled;
233
-
234
- COUNTER_DATA MSSQLJOBState;
235
-};
236
-
237
-struct mssql_db_instance {
238
- struct mssql_instance *parent;
239
-
240
- bool collecting_data;
241
- bool collect_instance;
242
- bool running_replication;
243
-
244
- RRDSET *st_db_data_file_size;
245
- RRDSET *st_db_active_transactions;
246
- RRDSET *st_db_backup_restore_operations;
247
- RRDSET *st_db_log_flushed;
248
- RRDSET *st_db_log_flushes;
249
- RRDSET *st_db_transactions;
250
- RRDSET *st_db_write_transactions;
251
- RRDSET *st_db_lockwait;
252
- RRDSET *st_db_deadlock;
253
- RRDSET *st_db_readonly;
254
- RRDSET *st_db_state;
255
- RRDSET *st_lock_timeouts;
256
- RRDSET *st_lock_requests;
257
- RRDSET *st_buff_page_iops;
258
- RRDSET *st_buff_cache_hits;
259
- RRDSET *st_buff_checkpoint_pages;
260
- RRDSET *st_buff_cache_page_life_expectancy;
261
- RRDSET *st_buff_lazy_write;
262
- RRDSET *st_buff_page_lookups;
263
-
264
- RRDSET *st_stats_compilation;
265
- RRDSET *st_stats_recompiles;
266
-
267
- RRDDIM *rd_db_data_file_size;
268
- RRDDIM *rd_db_active_transactions;
269
- RRDDIM *rd_db_backup_restore_operations;
270
- RRDDIM *rd_db_log_flushed;
271
- RRDDIM *rd_db_log_flushes;
272
- RRDDIM *rd_db_transactions;
273
- RRDDIM *rd_db_write_transactions;
274
- RRDDIM *rd_db_lockwait;
275
- RRDDIM *rd_db_deadlock;
276
- RRDDIM *rd_db_readonly_yes;
277
- RRDDIM *rd_db_readonly_no;
278
- RRDDIM *rd_db_state[NETDATA_DB_STATES];
279
- RRDDIM *rd_lock_timeouts;
280
- RRDDIM *rd_lock_requests;
281
- RRDDIM *rd_buff_page_reads;
282
- RRDDIM *rd_buff_page_writes;
283
- RRDDIM *rd_buff_cache_hits;
284
- RRDDIM *rd_buff_checkpoint_pages;
285
- RRDDIM *rd_buff_cache_page_life_expectancy;
286
- RRDDIM *rd_buff_lazy_write;
287
- RRDDIM *rd_buff_page_lookups;
288
-
289
- RRDDIM *rd_stats_compilation;
290
- RRDDIM *rd_stats_recompiles;
291
-
292
- COUNTER_DATA MSSQLDatabaseDataFileSize;
293
-
294
- COUNTER_DATA MSSQLDatabaseActiveTransactions;
295
- COUNTER_DATA MSSQLDatabaseBackupRestoreOperations;
296
- COUNTER_DATA MSSQLDatabaseLogFlushed;
297
- COUNTER_DATA MSSQLDatabaseLogFlushes;
298
- COUNTER_DATA MSSQLDatabaseTransactions;
299
- COUNTER_DATA MSSQLDatabaseWriteTransactions;
300
-
301
- COUNTER_DATA MSSQLDatabaseLockWaitSec;
302
- COUNTER_DATA MSSQLDatabaseDeadLockSec;
303
- COUNTER_DATA MSSQLDatabaseLockTimeoutsSec;
304
- COUNTER_DATA MSSQLDatabaseLockRequestsSec;
305
-
306
- // Buffer Management (https://learn.microsoft.com/en-us/sql/relational-databases/performance-monitor/sql-server-buffer-manager-object)
307
- COUNTER_DATA MSSQLBufferPageReads;
308
- COUNTER_DATA MSSQLBufferPageWrites;
309
- COUNTER_DATA MSSQLBufferCacheHits;
310
- COUNTER_DATA MSSQLBufferCheckpointPages;
311
- COUNTER_DATA MSSQLBufferPageLifeExpectancy;
312
- COUNTER_DATA MSSQLBufferLazyWrite;
313
- COUNTER_DATA MSSQLBufferPageLookups;
314
-
315
- COUNTER_DATA MSSQLCompilations;
316
- COUNTER_DATA MSSQLRecompilations;
317
-
318
- COUNTER_DATA MSSQLDBIsReadonly;
319
- COUNTER_DATA MSSQLDBState;
320
-
321
- uint32_t updated;
322
-};
323
-
324
-enum netdata_mssql_odbc_errors {
325
- NETDATA_MSSQL_ODBC_NO_ERROR,
326
- NETDATA_MSSQL_ODBC_CONNECT,
327
- NETDATA_MSSQL_ODBC_BIND,
328
- NETDATA_MSSQL_ODBC_PREPARE,
329
- NETDATA_MSSQL_ODBC_QUERY,
330
- NETDATA_MSSQL_ODBC_FETCH
331
-};
332
-
333
-static inline int netdata_mssql_check_result(SQLRETURN ret)
334
-{
335
- return (ret != SQL_SUCCESS && ret != SQL_SUCCESS_WITH_INFO);
336
-}
337
-
338
-static char *netdata_MSSQL_error_text(enum netdata_mssql_odbc_errors val)
339
-{
340
- switch (val) {
341
- case NETDATA_MSSQL_ODBC_NO_ERROR:
342
- return "NO ERROR";
343
- case NETDATA_MSSQL_ODBC_CONNECT:
344
- return "CONNECTION";
345
- case NETDATA_MSSQL_ODBC_BIND:
346
- return "BIND PARAMETER";
347
- case NETDATA_MSSQL_ODBC_PREPARE:
348
- return "PREPARE PARAMETER";
349
- case NETDATA_MSSQL_ODBC_QUERY:
350
- return "QUERY PARAMETER";
351
- case NETDATA_MSSQL_ODBC_FETCH:
352
- default:
353
- return "QUERY FETCH";
354
- }
355
-}
356
-
357
-static char *netdata_MSSQL_type_text(uint32_t type)
358
-{
359
- switch (type) {
360
- case SQL_HANDLE_STMT:
361
- return "STMT";
362
- case SQL_HANDLE_DBC:
363
- default:
364
- return "DBC";
365
- }
366
-}
367
-
368
-// Connection and SQL
369
-static void netdata_MSSQL_error(uint32_t type, SQLHANDLE handle, enum netdata_mssql_odbc_errors step, char *instance)
370
-{
371
- SQLCHAR state[1024];
372
- SQLCHAR message[1024];
373
- if (SQL_SUCCESS == SQLGetDiagRec((short)type, handle, 1, state, NULL, message, 1024, NULL)) {
374
- char *str_step = netdata_MSSQL_error_text(step);
375
- char *str_type = netdata_MSSQL_type_text(type);
376
- char *use_instance = (!instance) ? "no instance" : instance;
377
- nd_log(
378
- NDLS_COLLECTORS,
379
- NDLP_INFO,
380
- "MSSQL server error on %s using the handle %s running %s : %s, %s",
381
- use_instance,
382
- str_type,
383
- str_step,
384
- message,
385
- state);
386
- }
387
-}
388
-
389
-static inline void netdata_MSSQL_release_results(SQLHSTMT *stmt)
390
-{
391
- SQLCloseCursor(stmt);
392
-}
393
-
394
-static ULONGLONG netdata_MSSQL_fill_long_value(SQLHSTMT *stmt, const char *mask, const char *dbname, char *instance)
395
-{
396
- long db_size = 0;
397
- SQLLEN col_data_len = 0;
398
-
399
- SQLCHAR query[512];
400
- snprintfz((char *)query, 511, mask, dbname);
401
-
402
- SQLRETURN ret;
403
-
404
- ret = SQLExecDirect(stmt, query, SQL_NTS);
405
- if (netdata_mssql_check_result(ret)) {
406
- netdata_MSSQL_error(SQL_HANDLE_STMT, stmt, NETDATA_MSSQL_ODBC_QUERY, instance);
407
- return (ULONGLONG)ULONG_LONG_MAX;
408
- }
409
-
410
- ret = SQLBindCol(stmt, 1, SQL_C_LONG, &db_size, sizeof(long), &col_data_len);
411
- if (netdata_mssql_check_result(ret)) {
412
- netdata_MSSQL_error(SQL_HANDLE_STMT, stmt, NETDATA_MSSQL_ODBC_PREPARE, instance);
413
- return (ULONGLONG)ULONG_LONG_MAX;
414
- }
415
-
416
- ret = SQLFetch(stmt);
417
- if (netdata_mssql_check_result(ret)) {
418
- netdata_MSSQL_error(SQL_HANDLE_STMT, stmt, NETDATA_MSSQL_ODBC_FETCH, instance);
419
- return (ULONGLONG)ULONG_LONG_MAX;
420
- }
421
-
422
- netdata_MSSQL_release_results(stmt);
423
- return (ULONGLONG)(db_size * MEGA_FACTOR);
424
-}
425
-
426
-#define NETDATA_MSSQL_BUFFER_PAGE_READS_METRIC "Page reads/sec"
427
-#define NETDATA_MSSQL_BUFFER_PAGE_WRITES_METRIC "Page writes/sec"
428
-#define NETDATA_MSSQL_BUFFER_PAGE_CACHE_METRIC "Buffer cache hit ratio"
429
-#define NETDATA_MSSQL_BUFFER_CHECKPOINT_METRIC "Checkpoint pages/sec"
430
-#define NETDATA_MSSQL_BUFFER_PAGE_LIFE_METRIC "Page life expectancy"
431
-#define NETDATA_MSSQL_BUFFER_LAZY_WRITES_METRIC "Lazy writes/sec"
432
-#define NETDATA_MSSQL_BUFFER_PAGE_LOOKUPS_METRIC "Page Lookups/sec"
433
-
434
-#define NETDATA_MSSQL_STATS_COMPILATIONS_METRIC "SQL Compilations/sec"
435
-#define NETDATA_MSSQL_STATS_RECOMPILATIONS_METRIC "SQL Re-Compilations/sec"
436
-
437
-void dict_mssql_fill_instance_transactions(struct mssql_db_instance *mdi)
438
-{
439
- char object_name[NETDATA_MAX_INSTANCE_OBJECT + 1] = {};
440
- long value = 0;
441
- SQLLEN col_object_len = 0, col_value_len = 0;
442
-
443
- SQLCHAR query[sizeof(NETDATA_QUERY_TRANSACTIONS_PER_INSTANCE_MASK) + NETDATA_MAX_INSTANCE_OBJECT + 1];
444
- snprintfz(
445
- (char *)query,
446
- sizeof(NETDATA_QUERY_TRANSACTIONS_PER_INSTANCE_MASK) + NETDATA_MAX_INSTANCE_OBJECT,
447
- NETDATA_QUERY_TRANSACTIONS_PER_INSTANCE_MASK,
448
- mdi->parent->instanceID);
449
-
450
- SQLRETURN ret = SQLExecDirect(mdi->parent->conn->dbInstanceTransactionSTMT, (SQLCHAR *)query, SQL_NTS);
451
- if (netdata_mssql_check_result(ret)) {
452
- mdi->collecting_data = false;
453
- netdata_MSSQL_error(
454
- SQL_HANDLE_STMT,
455
- mdi->parent->conn->dbInstanceTransactionSTMT,
456
- NETDATA_MSSQL_ODBC_QUERY,
457
- mdi->parent->instanceID);
458
- goto enditransactions;
459
- }
460
-
461
- ret = SQLBindCol(
462
- mdi->parent->conn->dbInstanceTransactionSTMT, 1, SQL_C_CHAR, object_name, sizeof(object_name), &col_object_len);
463
- if (netdata_mssql_check_result(ret)) {
464
- netdata_MSSQL_error(
465
- SQL_HANDLE_STMT,
466
- mdi->parent->conn->dbInstanceTransactionSTMT,
467
- NETDATA_MSSQL_ODBC_PREPARE,
468
- mdi->parent->instanceID);
469
- goto enditransactions;
470
- }
471
-
472
- ret =
473
- SQLBindCol(mdi->parent->conn->dbInstanceTransactionSTMT, 2, SQL_C_LONG, &value, sizeof(value), &col_value_len);
474
- if (netdata_mssql_check_result(ret)) {
475
- netdata_MSSQL_error(
476
- SQL_HANDLE_STMT,
477
- mdi->parent->conn->dbInstanceTransactionSTMT,
478
- NETDATA_MSSQL_ODBC_PREPARE,
479
- mdi->parent->instanceID);
480
- goto enditransactions;
481
- }
482
-
483
- do {
484
- ret = SQLFetch(mdi->parent->conn->dbInstanceTransactionSTMT);
485
- switch (ret) {
486
- case SQL_SUCCESS:
487
- case SQL_SUCCESS_WITH_INFO:
488
- break;
489
- case SQL_NO_DATA:
490
- default:
491
- goto enditransactions;
492
- }
493
-
494
- // We cannot use strcmp, because buffer is filled with spaces instead NULL.
495
- if (!strncmp(
496
- object_name, NETDATA_MSSQL_BUFFER_PAGE_READS_METRIC, sizeof(NETDATA_MSSQL_BUFFER_PAGE_READS_METRIC) - 1))
497
- mdi->MSSQLBufferPageReads.current.Data = (ULONGLONG)value;
498
- else if (!strncmp(
499
- object_name,
500
- NETDATA_MSSQL_BUFFER_PAGE_WRITES_METRIC,
501
- sizeof(NETDATA_MSSQL_BUFFER_PAGE_WRITES_METRIC) - 1))
502
- mdi->MSSQLBufferPageWrites.current.Data = (ULONGLONG)value;
503
- else if (!strncmp(
504
- object_name,
505
- NETDATA_MSSQL_BUFFER_PAGE_CACHE_METRIC,
506
- sizeof(NETDATA_MSSQL_BUFFER_PAGE_CACHE_METRIC) - 1))
507
- mdi->MSSQLBufferCacheHits.current.Data = (ULONGLONG)value;
508
- else if (!strncmp(
509
- object_name,
510
- NETDATA_MSSQL_BUFFER_CHECKPOINT_METRIC,
511
- sizeof(NETDATA_MSSQL_BUFFER_CHECKPOINT_METRIC) - 1))
512
- mdi->MSSQLBufferCheckpointPages.current.Data = (ULONGLONG)value;
513
- else if (!strncmp(
514
- object_name,
515
- NETDATA_MSSQL_BUFFER_PAGE_LIFE_METRIC,
516
- sizeof(NETDATA_MSSQL_BUFFER_PAGE_LIFE_METRIC) - 1))
517
- mdi->MSSQLBufferPageLifeExpectancy.current.Data = (ULONGLONG)value;
518
- else if (!strncmp(
519
- object_name,
520
- NETDATA_MSSQL_BUFFER_LAZY_WRITES_METRIC,
521
- sizeof(NETDATA_MSSQL_BUFFER_LAZY_WRITES_METRIC) - 1))
522
- mdi->MSSQLBufferLazyWrite.current.Data = (ULONGLONG)value;
523
- else if (!strncmp(
524
- object_name,
525
- NETDATA_MSSQL_BUFFER_PAGE_LOOKUPS_METRIC,
526
- sizeof(NETDATA_MSSQL_BUFFER_PAGE_LOOKUPS_METRIC) - 1))
527
- mdi->MSSQLBufferPageLookups.current.Data = (ULONGLONG)value;
528
- else if (!strncmp(
529
- object_name,
530
- NETDATA_MSSQL_STATS_COMPILATIONS_METRIC,
531
- sizeof(NETDATA_MSSQL_STATS_COMPILATIONS_METRIC) - 1))
532
- mdi->MSSQLCompilations.current.Data = (ULONGLONG)value;
533
- else if (!strncmp(
534
- object_name,
535
- NETDATA_MSSQL_STATS_RECOMPILATIONS_METRIC,
536
- sizeof(NETDATA_MSSQL_STATS_RECOMPILATIONS_METRIC) - 1))
537
- mdi->MSSQLRecompilations.current.Data = (ULONGLONG)value;
538
- } while (true);
539
-
540
-enditransactions:
541
- netdata_MSSQL_release_results(mdi->parent->conn->dbInstanceTransactionSTMT);
542
-}
543
-
544
-#define NETDATA_MSSQL_ACTIVE_TRANSACTIONS_METRIC "Active Transactions"
545
-#define NETDATA_MSSQL_TRANSACTION_PER_SEC_METRIC "Transactions/sec"
546
-#define NETDATA_MSSQL_WRITE_TRANSACTIONS_METRIC "Write Transactions/sec"
547
-#define NETDATA_MSSQL_BACKUP_RESTORE_METRIC "Backup/Restore Throughput/sec"
548
-#define NETDATA_MSSQL_LOG_FLUSHED_METRIC "Log Bytes Flushed/sec"
549
-#define NETDATA_MSSQL_LOG_FLUSHES_METRIC "Log Flushes/sec"
550
-#define NETDATA_MSSQL_NUMBER_DEADLOCKS_METRIC "Number of Deadlocks/sec"
551
-#define NETDATA_MSSQL_LOCK_WAITS_METRIC "Lock Waits/sec"
552
-#define NETDATA_MSSQL_LOCK_TIMEOUTS_METRIC "Lock Timeouts/sec"
553
-#define NETDATA_MSSQL_LOCK_REQUESTS_METRIC "Lock Requests/sec"
554
-
555
-void dict_mssql_fill_transactions(struct mssql_db_instance *mdi, const char *dbname)
556
-{
557
- char object_name[NETDATA_MAX_INSTANCE_OBJECT + 1] = {};
558
- long value = 0;
559
- SQLLEN col_object_len = 0, col_value_len = 0;
560
-
561
- if (mdi->collect_instance)
562
- dict_mssql_fill_instance_transactions(mdi);
563
-
564
- SQLCHAR query[sizeof(NETDATA_QUERY_TRANSACTIONS_MASK) + 2 * NETDATA_MAX_INSTANCE_OBJECT + 1];
565
- snprintfz(
566
- (char *)query,
567
- sizeof(NETDATA_QUERY_TRANSACTIONS_MASK) + 2 * NETDATA_MAX_INSTANCE_OBJECT,
568
- NETDATA_QUERY_TRANSACTIONS_MASK,
569
- dbname,
570
- dbname);
571
-
572
- SQLRETURN ret = SQLExecDirect(mdi->parent->conn->dbTransactionSTMT, (SQLCHAR *)query, SQL_NTS);
573
- if (netdata_mssql_check_result(ret)) {
574
- mdi->collecting_data = false;
575
- netdata_MSSQL_error(
576
- SQL_HANDLE_STMT, mdi->parent->conn->dbTransactionSTMT, NETDATA_MSSQL_ODBC_QUERY, mdi->parent->instanceID);
577
- goto endtransactions;
578
- }
579
-
580
- ret = SQLBindCol(
581
- mdi->parent->conn->dbTransactionSTMT, 1, SQL_C_CHAR, object_name, sizeof(object_name), &col_object_len);
582
- if (netdata_mssql_check_result(ret)) {
583
- netdata_MSSQL_error(
584
- SQL_HANDLE_STMT, mdi->parent->conn->dbTransactionSTMT, NETDATA_MSSQL_ODBC_PREPARE, mdi->parent->instanceID);
585
- goto endtransactions;
586
- }
587
-
588
- ret = SQLBindCol(mdi->parent->conn->dbTransactionSTMT, 2, SQL_C_LONG, &value, sizeof(value), &col_value_len);
589
- if (netdata_mssql_check_result(ret)) {
590
- netdata_MSSQL_error(
591
- SQL_HANDLE_STMT, mdi->parent->conn->dbTransactionSTMT, NETDATA_MSSQL_ODBC_PREPARE, mdi->parent->instanceID);
592
- goto endtransactions;
593
- }
594
-
595
- do {
596
- ret = SQLFetch(mdi->parent->conn->dbTransactionSTMT);
597
- switch (ret) {
598
- case SQL_SUCCESS:
599
- case SQL_SUCCESS_WITH_INFO:
600
- break;
601
- case SQL_NO_DATA:
602
- default:
603
- goto endtransactions;
604
- }
605
-
606
- // We cannot use strcmp, because buffer is filled with spaces instead NULL.
607
- if (!strncmp(
608
- object_name,
609
- NETDATA_MSSQL_ACTIVE_TRANSACTIONS_METRIC,
610
- sizeof(NETDATA_MSSQL_ACTIVE_TRANSACTIONS_METRIC) - 1))
611
- mdi->MSSQLDatabaseActiveTransactions.current.Data = (ULONGLONG)value;
612
- else if (!strncmp(
613
- object_name,
614
- NETDATA_MSSQL_TRANSACTION_PER_SEC_METRIC,
615
- sizeof(NETDATA_MSSQL_TRANSACTION_PER_SEC_METRIC) - 1))
616
- mdi->MSSQLDatabaseTransactions.current.Data = (ULONGLONG)value;
617
- else if (!strncmp(
618
- object_name,
619
- NETDATA_MSSQL_WRITE_TRANSACTIONS_METRIC,
620
- sizeof(NETDATA_MSSQL_WRITE_TRANSACTIONS_METRIC) - 1))
621
- mdi->MSSQLDatabaseWriteTransactions.current.Data = (ULONGLONG)value;
622
- else if (!strncmp(
623
- object_name, NETDATA_MSSQL_BACKUP_RESTORE_METRIC, sizeof(NETDATA_MSSQL_BACKUP_RESTORE_METRIC) - 1))
624
- mdi->MSSQLDatabaseBackupRestoreOperations.current.Data = (ULONGLONG)value;
625
- else if (!strncmp(object_name, NETDATA_MSSQL_LOG_FLUSHED_METRIC, sizeof(NETDATA_MSSQL_LOG_FLUSHED_METRIC) - 1))
626
- mdi->MSSQLDatabaseLogFlushed.current.Data = (ULONGLONG)value;
627
- else if (!strncmp(object_name, NETDATA_MSSQL_LOG_FLUSHES_METRIC, sizeof(NETDATA_MSSQL_LOG_FLUSHES_METRIC) - 1))
628
- mdi->MSSQLDatabaseLogFlushes.current.Data = (ULONGLONG)value;
629
- else if (!strncmp(
630
- object_name,
631
- NETDATA_MSSQL_NUMBER_DEADLOCKS_METRIC,
632
- sizeof(NETDATA_MSSQL_NUMBER_DEADLOCKS_METRIC) - 1))
633
- mdi->MSSQLDatabaseDeadLockSec.current.Data = (ULONGLONG)value;
634
- else if (!strncmp(object_name, NETDATA_MSSQL_LOCK_WAITS_METRIC, sizeof(NETDATA_MSSQL_LOCK_WAITS_METRIC) - 1))
635
- mdi->MSSQLDatabaseLockWaitSec.current.Data = (ULONGLONG)value;
636
- else if (!strncmp(
637
- object_name, NETDATA_MSSQL_LOCK_TIMEOUTS_METRIC, sizeof(NETDATA_MSSQL_LOCK_TIMEOUTS_METRIC) - 1))
638
- mdi->MSSQLDatabaseLockTimeoutsSec.current.Data = (ULONGLONG)value;
639
- else if (!strncmp(
640
- object_name, NETDATA_MSSQL_LOCK_REQUESTS_METRIC, sizeof(NETDATA_MSSQL_LOCK_REQUESTS_METRIC) - 1))
641
- mdi->MSSQLDatabaseLockRequestsSec.current.Data = (ULONGLONG)value;
642
-
643
- } while (true);
644
-
645
-endtransactions:
646
- netdata_MSSQL_release_results(mdi->parent->conn->dbTransactionSTMT);
647
-}
648
-
649
-void dict_mssql_fill_locks(struct mssql_db_instance *mdi, const char *dbname)
650
-{
651
-#define NETDATA_MSSQL_MAX_RESOURCE_TYPE (60)
652
- char resource_type[NETDATA_MSSQL_MAX_RESOURCE_TYPE + 1] = {};
653
- long value = 0;
654
- SQLLEN col_object_len = 0, col_value_len = 0;
655
-
656
- SQLCHAR query[sizeof(NETDATA_QUERY_LOCKS_MASK) + 2 * NETDATA_MAX_INSTANCE_OBJECT + 1];
657
- snprintfz(
658
- (char *)query,
659
- sizeof(NETDATA_QUERY_TRANSACTIONS_MASK) + 2 * NETDATA_MAX_INSTANCE_OBJECT,
660
- NETDATA_QUERY_LOCKS_MASK,
661
- dbname,
662
- dbname);
663
-
664
- SQLRETURN ret = SQLExecDirect(mdi->parent->conn->dbLocksSTMT, (SQLCHAR *)query, SQL_NTS);
665
- if (netdata_mssql_check_result(ret)) {
666
- mdi->collecting_data = false;
667
- netdata_MSSQL_error(
668
- SQL_HANDLE_STMT, mdi->parent->conn->dbLocksSTMT, NETDATA_MSSQL_ODBC_QUERY, mdi->parent->instanceID);
669
- goto endlocks;
670
- }
671
-
672
- ret = SQLBindCol(
673
- mdi->parent->conn->dbLocksSTMT, 1, SQL_C_CHAR, resource_type, sizeof(resource_type), &col_object_len);
674
- if (netdata_mssql_check_result(ret)) {
675
- netdata_MSSQL_error(
676
- SQL_HANDLE_STMT, mdi->parent->conn->dbLocksSTMT, NETDATA_MSSQL_ODBC_PREPARE, mdi->parent->instanceID);
677
- goto endlocks;
678
- }
679
-
680
- ret = SQLBindCol(mdi->parent->conn->dbLocksSTMT, 2, SQL_C_LONG, &value, sizeof(value), &col_value_len);
681
- if (netdata_mssql_check_result(ret)) {
682
- netdata_MSSQL_error(
683
- SQL_HANDLE_STMT, mdi->parent->conn->dbLocksSTMT, NETDATA_MSSQL_ODBC_PREPARE, mdi->parent->instanceID);
684
- goto endlocks;
685
- }
686
-
687
- do {
688
- ret = SQLFetch(mdi->parent->conn->dbLocksSTMT);
689
- switch (ret) {
690
- case SQL_SUCCESS:
691
- case SQL_SUCCESS_WITH_INFO:
692
- break;
693
- case SQL_NO_DATA:
694
- default:
695
- goto endlocks;
696
- }
697
-
698
- char *space = strchr(resource_type, ' ');
699
- if (space)
700
- *space = '\0';
701
-
702
- struct mssql_lock_instance *mli =
703
- dictionary_set(mdi->parent->locks_instances, resource_type, NULL, sizeof(*mli));
704
- if (!mli)
705
- continue;
706
-
707
- mli->lockWait.current.Data = value;
708
- } while (true);
709
-
710
-endlocks:
711
- netdata_MSSQL_release_results(mdi->parent->conn->dbLocksSTMT);
712
-}
713
-
714
-int dict_mssql_fill_waits(struct mssql_instance *mi)
715
-{
716
- char wait_type[NETDATA_MAX_INSTANCE_OBJECT + 1] = {};
717
- char wait_category[NETDATA_MAX_INSTANCE_OBJECT + 1] = {};
718
- SQLBIGINT total_wait = 0;
719
- SQLBIGINT resource_wait = 0;
720
- SQLBIGINT signal_wait = 0;
721
- SQLBIGINT max_wait = 0;
722
- SQLBIGINT waiting_tasks = 0;
723
- int success = 0;
724
- SQLLEN col_wait_type_len = 0, col_total_wait_len = 0, col_resource_wait_len = 0, col_signal_wait_len = 0,
725
- col_max_wait_len = 0, col_waiting_tasks_len = 0, col_wait_category_len = 0;
726
-
727
- SQLRETURN ret = SQLExecDirect(mi->conn->dbWaitsSTMT, (SQLCHAR *)NETDATA_QUERY_CHECK_WAITS, SQL_NTS);
728
- if (netdata_mssql_check_result(ret)) {
729
- netdata_MSSQL_error(SQL_HANDLE_STMT, mi->conn->dbWaitsSTMT, NETDATA_MSSQL_ODBC_QUERY, mi->instanceID);
730
- goto endwait;
731
- }
732
-
733
- ret = SQLBindCol(mi->conn->dbWaitsSTMT, 1, SQL_C_CHAR, wait_type, sizeof(wait_type), &col_wait_type_len);
734
- if (netdata_mssql_check_result(ret)) {
735
- netdata_MSSQL_error(SQL_HANDLE_STMT, mi->conn->dbWaitsSTMT, NETDATA_MSSQL_ODBC_PREPARE, mi->instanceID);
736
- goto endwait;
737
- }
738
-
739
- ret = SQLBindCol(mi->conn->dbWaitsSTMT, 2, SQL_C_LONG, &total_wait, sizeof(total_wait), &col_total_wait_len);
740
- if (netdata_mssql_check_result(ret)) {
741
- netdata_MSSQL_error(SQL_HANDLE_STMT, mi->conn->dbWaitsSTMT, NETDATA_MSSQL_ODBC_PREPARE, mi->instanceID);
742
- goto endwait;
743
- }
744
-
745
- ret =
746
- SQLBindCol(mi->conn->dbWaitsSTMT, 3, SQL_C_LONG, &resource_wait, sizeof(resource_wait), &col_resource_wait_len);
747
- if (netdata_mssql_check_result(ret)) {
748
- netdata_MSSQL_error(SQL_HANDLE_STMT, mi->conn->dbWaitsSTMT, NETDATA_MSSQL_ODBC_PREPARE, mi->instanceID);
749
- goto endwait;
750
- }
751
-
752
- ret = SQLBindCol(mi->conn->dbWaitsSTMT, 4, SQL_C_LONG, &signal_wait, sizeof(signal_wait), &col_signal_wait_len);
753
- if (netdata_mssql_check_result(ret)) {
754
- netdata_MSSQL_error(SQL_HANDLE_STMT, mi->conn->dbWaitsSTMT, NETDATA_MSSQL_ODBC_PREPARE, mi->instanceID);
755
- goto endwait;
756
- }
757
-
758
- ret = SQLBindCol(mi->conn->dbWaitsSTMT, 5, SQL_C_LONG, &max_wait, sizeof(max_wait), &col_max_wait_len);
759
- if (netdata_mssql_check_result(ret)) {
760
- netdata_MSSQL_error(SQL_HANDLE_STMT, mi->conn->dbWaitsSTMT, NETDATA_MSSQL_ODBC_PREPARE, mi->instanceID);
761
- goto endwait;
762
- }
763
-
764
- ret =
765
- SQLBindCol(mi->conn->dbWaitsSTMT, 6, SQL_C_LONG, &waiting_tasks, sizeof(waiting_tasks), &col_waiting_tasks_len);
766
- if (netdata_mssql_check_result(ret)) {
767
- netdata_MSSQL_error(SQL_HANDLE_STMT, mi->conn->dbWaitsSTMT, NETDATA_MSSQL_ODBC_PREPARE, mi->instanceID);
768
- goto endwait;
769
- }
770
-
771
- ret =
772
- SQLBindCol(mi->conn->dbWaitsSTMT, 7, SQL_C_CHAR, wait_category, sizeof(wait_category), &col_wait_category_len);
773
- if (netdata_mssql_check_result(ret)) {
774
- netdata_MSSQL_error(SQL_HANDLE_STMT, mi->conn->dbWaitsSTMT, NETDATA_MSSQL_ODBC_PREPARE, mi->instanceID);
775
- goto endwait;
776
- }
777
-
778
- do {
779
- ret = SQLFetch(mi->conn->dbWaitsSTMT);
780
- switch (ret) {
781
- case SQL_SUCCESS:
782
- case SQL_SUCCESS_WITH_INFO:
783
- break;
784
- case SQL_NO_DATA:
785
- default:
786
- success = 1;
787
- goto endwait;
788
- }
789
-
790
- struct mssql_db_waits *mdw = dictionary_set(mi->waits, wait_type, NULL, sizeof(*mdw));
791
- if (!mdw)
792
- continue;
793
-
794
- mdw->MSSQLDatabaseTotalWait.current.Data = (ULONGLONG)total_wait;
795
- // Variable mdw->MSSQLDatabaseResourceWaitMSec.current.Data stores a mathematical operation
796
- // that can be negative sometimes. This is the reason we have this if
797
- if (resource_wait > mdw->MSSQLDatabaseResourceWaitMSec.current.Data)
798
- mdw->MSSQLDatabaseResourceWaitMSec.current.Data = (ULONGLONG)resource_wait;
799
- mdw->MSSQLDatabaseSignalWaitMSec.current.Data = (ULONGLONG)signal_wait;
800
- mdw->MSSQLDatabaseMaxWaitTimeMSec.current.Data = (ULONGLONG)max_wait;
801
- mdw->MSSQLDatabaseWaitingTasks.current.Data = (ULONGLONG)waiting_tasks;
802
-
803
- if (!mdw->wait_category)
804
- mdw->wait_category = strdupz(wait_category);
805
- } while (true);
806
-
807
-endwait:
808
- netdata_MSSQL_release_results(mi->conn->dbWaitsSTMT);
809
-
810
- return success;
811
-}
812
-
813
-int netdata_select_db(SQLHDBC hdbc, const char *database)
814
-{
815
- SQLHSTMT hstmt;
816
- SQLRETURN ret;
817
-
818
- ret = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt);
819
- if (netdata_mssql_check_result(ret)) {
820
- return -1;
821
- }
822
-
823
- char query[512];
824
- snprintfz(query, sizeof(query), "USE %s", database);
825
- ret = SQLExecDirect(hstmt, (SQLCHAR *)query, SQL_NTS);
826
- int result = 0;
827
- if (netdata_mssql_check_result(ret)) {
828
- result = -1;
829
- }
830
- SQLFreeHandle(SQL_HANDLE_STMT, hstmt);
831
- return result;
832
-}
833
-
834
-void dict_mssql_fill_replication(struct mssql_db_instance *mdi)
835
-{
836
- char publisher[NETDATA_MAX_INSTANCE_OBJECT + 1] = {};
837
- char publisher_db[NETDATA_MAX_INSTANCE_OBJECT + 1] = {};
838
- char publication[NETDATA_MAX_INSTANCE_OBJECT + 1] = {};
839
- char key[NETDATA_MAX_INSTANCE_OBJECT * 2 + 2];
840
- int type = 0, status = 0, warning = 0, avg_latency = 0, retention = 0, subscriptioncount = 0,
841
- runningdistagentcount = 0, average_runspeedPerf = 0;
842
- SQLLEN publisher_len = 0, publisherdb_len = 0, publication_len = 0, type_len = 0, status_len = 0, warning_len = 0,
843
- avg_latency_len = 0, retention_len = 0, subscriptioncount_len = 0, runningagentcount_len = 0,
844
- average_runspeedperf_len = 0;
845
-
846
- if (netdata_select_db(mdi->parent->conn->netdataSQLHDBc, NETDATA_REPLICATION_DB)) {
847
- return;
848
- }
849
-
850
- SQLRETURN ret =
851
- SQLExecDirect(mdi->parent->conn->dbReplicationPublisher, (SQLCHAR *)NETDATA_REPLICATION_MONITOR_QUERY, SQL_NTS);
852
- if (netdata_mssql_check_result(ret)) {
853
- mdi->collecting_data = false;
854
- netdata_MSSQL_error(
855
- SQL_HANDLE_STMT,
856
- mdi->parent->conn->dbReplicationPublisher,
857
- NETDATA_MSSQL_ODBC_QUERY,
858
- mdi->parent->instanceID);
859
- goto endreplication;
860
- }
861
-
862
- ret = SQLBindCol(
863
- mdi->parent->conn->dbReplicationPublisher, 1, SQL_C_CHAR, publisher_db, sizeof(publisher_db), &publisherdb_len);
864
- if (netdata_mssql_check_result(ret)) {
865
- netdata_MSSQL_error(
866
- SQL_HANDLE_STMT,
867
- mdi->parent->conn->dbReplicationPublisher,
868
- NETDATA_MSSQL_ODBC_PREPARE,
869
- mdi->parent->instanceID);
870
- goto endreplication;
871
- }
872
-
873
- ret = SQLBindCol(
874
- mdi->parent->conn->dbReplicationPublisher, 2, SQL_C_CHAR, publication, sizeof(publication), &publication_len);
875
- if (netdata_mssql_check_result(ret)) {
876
- netdata_MSSQL_error(
877
- SQL_HANDLE_STMT,
878
- mdi->parent->conn->dbReplicationPublisher,
879
- NETDATA_MSSQL_ODBC_PREPARE,
880
- mdi->parent->instanceID);
881
- goto endreplication;
882
- }
883
-
884
- ret = SQLBindCol(mdi->parent->conn->dbReplicationPublisher, 4, SQL_C_LONG, &type, sizeof(type), &type_len);
885
- if (netdata_mssql_check_result(ret)) {
886
- netdata_MSSQL_error(
887
- SQL_HANDLE_STMT,
888
- mdi->parent->conn->dbReplicationPublisher,
889
- NETDATA_MSSQL_ODBC_PREPARE,
890
- mdi->parent->instanceID);
891
- goto endreplication;
892
- }
893
-
894
- ret = SQLBindCol(mdi->parent->conn->dbReplicationPublisher, 5, SQL_C_LONG, &status, sizeof(status), &status_len);
895
- if (netdata_mssql_check_result(ret)) {
896
- netdata_MSSQL_error(
897
- SQL_HANDLE_STMT,
898
- mdi->parent->conn->dbReplicationPublisher,
899
- NETDATA_MSSQL_ODBC_PREPARE,
900
- mdi->parent->instanceID);
901
- goto endreplication;
902
- }
903
-
904
- ret = SQLBindCol(mdi->parent->conn->dbReplicationPublisher, 6, SQL_C_LONG, &warning, sizeof(warning), &warning_len);
905
- if (netdata_mssql_check_result(ret)) {
906
- netdata_MSSQL_error(
907
- SQL_HANDLE_STMT,
908
- mdi->parent->conn->dbReplicationPublisher,
909
- NETDATA_MSSQL_ODBC_PREPARE,
910
- mdi->parent->instanceID);
911
- goto endreplication;
912
- }
913
-
914
- ret = SQLBindCol(
915
- mdi->parent->conn->dbReplicationPublisher, 9, SQL_C_LONG, &avg_latency, sizeof(avg_latency), &avg_latency_len);
916
- if (netdata_mssql_check_result(ret)) {
917
- // It is still a NULL value
918
- avg_latency = 0;
919
- }
920
-
921
- ret = SQLBindCol(
922
- mdi->parent->conn->dbReplicationPublisher, 11, SQL_C_LONG, &retention, sizeof(retention), &retention_len);
923
- if (netdata_mssql_check_result(ret)) {
924
- netdata_MSSQL_error(
925
- SQL_HANDLE_STMT,
926
- mdi->parent->conn->dbReplicationPublisher,
927
- NETDATA_MSSQL_ODBC_PREPARE,
928
- mdi->parent->instanceID);
929
- goto endreplication;
930
- }
931
-
932
- ret = SQLBindCol(
933
- mdi->parent->conn->dbReplicationPublisher,
934
- 15,
935
- SQL_C_LONG,
936
- &subscriptioncount,
937
- sizeof(subscriptioncount),
938
- &subscriptioncount_len);
939
- if (netdata_mssql_check_result(ret)) {
940
- netdata_MSSQL_error(
941
- SQL_HANDLE_STMT,
942
- mdi->parent->conn->dbReplicationPublisher,
943
- NETDATA_MSSQL_ODBC_PREPARE,
944
- mdi->parent->instanceID);
945
- goto endreplication;
946
- }
947
-
948
- ret = SQLBindCol(
949
- mdi->parent->conn->dbReplicationPublisher,
950
- 16,
951
- SQL_C_LONG,
952
- &runningdistagentcount,
953
- sizeof(runningdistagentcount),
954
- &runningagentcount_len);
955
- if (netdata_mssql_check_result(ret)) {
956
- netdata_MSSQL_error(
957
- SQL_HANDLE_STMT,
958
- mdi->parent->conn->dbReplicationPublisher,
959
- NETDATA_MSSQL_ODBC_PREPARE,
960
- mdi->parent->instanceID);
961
- goto endreplication;
962
- }
963
-
964
- ret = SQLBindCol(
965
- mdi->parent->conn->dbReplicationPublisher,
966
- 22,
967
- SQL_C_LONG,
968
- &average_runspeedPerf,
969
- sizeof(average_runspeedPerf),
970
- &average_runspeedperf_len);
971
- if (netdata_mssql_check_result(ret)) {
972
- netdata_MSSQL_error(
973
- SQL_HANDLE_STMT,
974
- mdi->parent->conn->dbReplicationPublisher,
975
- NETDATA_MSSQL_ODBC_PREPARE,
976
- mdi->parent->instanceID);
977
- goto endreplication;
978
- }
979
-
980
- ret = SQLBindCol(
981
- mdi->parent->conn->dbReplicationPublisher, 24, SQL_C_CHAR, publisher, sizeof(publisher), &publisher_len);
982
- if (netdata_mssql_check_result(ret)) {
983
- netdata_MSSQL_error(
984
- SQL_HANDLE_STMT,
985
- mdi->parent->conn->dbReplicationPublisher,
986
- NETDATA_MSSQL_ODBC_PREPARE,
987
- mdi->parent->instanceID);
988
- goto endreplication;
989
- }
990
-
991
- do {
992
- ret = SQLFetch(mdi->parent->conn->dbReplicationPublisher);
993
- switch (ret) {
994
- case SQL_SUCCESS:
995
- case SQL_SUCCESS_WITH_INFO:
996
- break;
997
- case SQL_NO_DATA:
998
- default:
999
- goto endreplication;
1000
- }
1001
-
1002
- snprintfz(key, sizeof(key) - 1, "%s:%s", publisher_db, publication);
1003
- struct mssql_publisher_publication *mpp =
1004
- dictionary_set(mdi->parent->publisher_publication, key, NULL, sizeof(*mpp));
1005
-
1006
- if (!mpp->publisher) {
1007
- mpp->publisher = strdupz(publisher);
1008
- mpp->parent = mdi->parent;
1009
- }
1010
-
1011
- if (!mpp->publication)
1012
- mpp->publication = strdupz(publication);
1013
-
1014
- if (!mpp->db)
1015
- mpp->db = strdupz(publisher_db);
1016
-
1017
- mpp->type = type;
1018
- mpp->status = status;
1019
- mpp->warning = warning;
1020
-
1021
- mpp->avg_latency = avg_latency;
1022
-
1023
- mpp->retention = retention;
1024
-
1025
- mpp->subscriptioncount = subscriptioncount;
1026
- mpp->runningdistagentcount = runningdistagentcount;
1027
-
1028
- mpp->average_runspeedPerf = average_runspeedPerf;
1029
- } while (true);
1030
-
1031
-endreplication:
1032
- (void)netdata_select_db(mdi->parent->conn->netdataSQLHDBc, "master");
1033
- netdata_MSSQL_release_results(mdi->parent->conn->dbReplicationPublisher);
1034
-}
1035
-int dict_mssql_databases_run_queries(const DICTIONARY_ITEM *item __maybe_unused, void *value, void *data __maybe_unused)
1036
-{
1037
- struct mssql_db_instance *mdi = value;
1038
- const char *dbname = dictionary_acquired_item_name((DICTIONARY_ITEM *)item);
1039
-
1040
- if (!mdi->collecting_data || !mdi->parent || !mdi->parent->conn) {
1041
- goto enddrunquery;
1042
- }
1043
-
1044
- // We failed to collect this for the database, so we are not going to try again
1045
- if (mdi->MSSQLDatabaseDataFileSize.current.Data != ULONG_LONG_MAX)
1046
- mdi->MSSQLDatabaseDataFileSize.current.Data = netdata_MSSQL_fill_long_value(
1047
- mdi->parent->conn->dataFileSizeSTMT, NETDATA_QUERY_DATA_FILE_SIZE_MASK, dbname, mdi->parent->instanceID);
1048
- else {
1049
- mdi->collecting_data = false;
1050
- goto enddrunquery;
1051
- }
1052
-
1053
- dict_mssql_fill_transactions(mdi, dbname);
1054
- dict_mssql_fill_locks(mdi, dbname);
1055
-
1056
- if (mdi->running_replication)
1057
- dict_mssql_fill_replication(mdi);
1058
-
1059
-enddrunquery:
1060
- return 1;
1061
-}
1062
-
1063
-long metdata_mssql_check_permission(struct mssql_instance *mi)
1064
-{
1065
- static int next_try = NETDATA_MSSQL_NEXT_TRY - 1;
1066
- long perm = 0;
1067
- SQLLEN col_data_len = 0;
1068
-
1069
- if (++next_try != NETDATA_MSSQL_NEXT_TRY)
1070
- return 1;
1071
-
1072
- next_try = 0;
1073
-
1074
- SQLRETURN ret;
1075
-
1076
- ret = SQLExecDirect(mi->conn->checkPermSTMT, (SQLCHAR *)NETDATA_QUERY_CHECK_PERM, SQL_NTS);
1077
- if (netdata_mssql_check_result(ret)) {
1078
- netdata_MSSQL_error(SQL_HANDLE_STMT, mi->conn->checkPermSTMT, NETDATA_MSSQL_ODBC_QUERY, mi->instanceID);
1079
- perm = LONG_MAX;
1080
- goto endperm;
1081
- }
1082
-
1083
- ret = SQLBindCol(mi->conn->checkPermSTMT, 1, SQL_C_LONG, &perm, sizeof(perm), &col_data_len);
1084
-
1085
- if (netdata_mssql_check_result(ret)) {
1086
- netdata_MSSQL_error(SQL_HANDLE_STMT, mi->conn->checkPermSTMT, NETDATA_MSSQL_ODBC_PREPARE, mi->instanceID);
1087
- perm = LONG_MAX;
1088
- goto endperm;
1089
- }
1090
-
1091
- ret = SQLFetch(mi->conn->checkPermSTMT);
1092
- if (netdata_mssql_check_result(ret)) {
1093
- netdata_MSSQL_error(SQL_HANDLE_STMT, mi->conn->checkPermSTMT, NETDATA_MSSQL_ODBC_FETCH, mi->instanceID);
1094
- perm = LONG_MAX;
1095
- goto endperm;
1096
- }
1097
-
1098
-endperm:
1099
- netdata_MSSQL_release_results(mi->conn->checkPermSTMT);
1100
- return perm;
1101
-}
1102
-
1103
-void metdata_mssql_fill_mssql_status(struct mssql_instance *mi)
1104
-{
1105
- char dbname[SQLSERVER_MAX_NAME_LENGTH + 1];
1106
- int readonly = 0;
1107
- BYTE state = 0;
1108
- SQLLEN col_data_len = 0;
1109
-
1110
- static int next_try = NETDATA_MSSQL_NEXT_TRY - 1;
1111
-
1112
- if (++next_try != NETDATA_MSSQL_NEXT_TRY)
1113
- return;
1114
-
1115
- next_try = 0;
1116
-
1117
- SQLRETURN ret;
1118
-
1119
- ret = SQLExecDirect(mi->conn->dbSQLState, (SQLCHAR *)NETDATA_QUERY_DATABASE_STATUS, SQL_NTS);
1120
- if (netdata_mssql_check_result(ret)) {
1121
- netdata_MSSQL_error(SQL_HANDLE_STMT, mi->conn->dbSQLState, NETDATA_MSSQL_ODBC_QUERY, mi->instanceID);
1122
- goto enddbstate;
1123
- }
1124
-
1125
- ret = SQLBindCol(mi->conn->dbSQLState, 1, SQL_C_TINYINT, &state, sizeof(state), &col_data_len);
1126
- if (netdata_mssql_check_result(ret)) {
1127
- netdata_MSSQL_error(SQL_HANDLE_STMT, mi->conn->dbSQLState, NETDATA_MSSQL_ODBC_PREPARE, mi->instanceID);
1128
- goto enddbstate;
1129
- }
1130
-
1131
- ret = SQLBindCol(mi->conn->dbSQLState, 3, SQL_C_BIT, &readonly, sizeof(readonly), &col_data_len);
1132
- if (netdata_mssql_check_result(ret)) {
1133
- netdata_MSSQL_error(SQL_HANDLE_STMT, mi->conn->dbWaitsSTMT, NETDATA_MSSQL_ODBC_PREPARE, mi->instanceID);
1134
- goto enddbstate;
1135
- }
1136
-
1137
- int i = 0;
1138
- do {
1139
- ret = SQLFetch(mi->conn->dbSQLState);
1140
- if (netdata_mssql_check_result(ret)) {
1141
- goto enddbstate;
1142
- }
1143
-
1144
- struct mssql_db_instance *mdi = dictionary_set(mi->databases, dbname, NULL, sizeof(*mdi));
1145
- if (!mdi)
1146
- continue;
1147
-
1148
- mdi->MSSQLDBState.current.Data = (ULONGLONG)state;
1149
- mdi->MSSQLDBIsReadonly.current.Data = (ULONGLONG)readonly;
1150
- } while (true);
1151
-
1152
-enddbstate:
1153
- netdata_MSSQL_release_results(mi->conn->dbSQLState);
1154
-}
1155
-
1156
-void metdata_mssql_fill_job_status(struct mssql_instance *mi)
1157
-{
1158
- char job[SQLSERVER_MAX_NAME_LENGTH + 1];
1159
- BYTE state = 0;
1160
- SQLLEN col_job_len = 0;
1161
- SQLLEN col_state_len = 0;
1162
-
1163
- static int next_try = NETDATA_MSSQL_NEXT_TRY - 1;
1164
-
1165
- if (++next_try != NETDATA_MSSQL_NEXT_TRY)
1166
- return;
1167
-
1168
- next_try = 0;
1169
-
1170
- SQLRETURN ret;
1171
-
1172
- ret = SQLExecDirect(mi->conn->dbSQLJobs, (SQLCHAR *)NETDATA_QUERY_JOBS_STATUS, SQL_NTS);
1173
- if (netdata_mssql_check_result(ret)) {
1174
- netdata_MSSQL_error(SQL_HANDLE_STMT, mi->conn->dbSQLJobs, NETDATA_MSSQL_ODBC_QUERY, mi->instanceID);
1175
- goto enddbjobs;
1176
- }
1177
-
1178
- ret = SQLBindCol(mi->conn->dbSQLJobs, 1, SQL_C_CHAR, job, sizeof(job), &col_job_len);
1179
- if (netdata_mssql_check_result(ret)) {
1180
- netdata_MSSQL_error(SQL_HANDLE_STMT, mi->conn->dbSQLJobs, NETDATA_MSSQL_ODBC_PREPARE, mi->instanceID);
1181
- goto enddbjobs;
1182
- }
1183
-
1184
- ret = SQLBindCol(mi->conn->dbSQLJobs, 2, SQL_C_TINYINT, &state, sizeof(state), &col_state_len);
1185
- if (netdata_mssql_check_result(ret)) {
1186
- netdata_MSSQL_error(SQL_HANDLE_STMT, mi->conn->dbSQLJobs, NETDATA_MSSQL_ODBC_PREPARE, mi->instanceID);
1187
- goto enddbjobs;
1188
- }
1189
-
1190
- do {
1191
- ret = SQLFetch(mi->conn->dbSQLJobs);
1192
- if (netdata_mssql_check_result(ret)) {
1193
- goto enddbjobs;
1194
- }
1195
-
1196
- struct mssql_db_jobs *mdj = dictionary_set(mi->sysjobs, job, NULL, sizeof(*mdj));
1197
- if (!mdj)
1198
- continue;
1199
-
1200
- mdj->MSSQLJOBState.current.Data = (ULONGLONG)state;
1201
- } while (true);
1202
-
1203
-enddbjobs:
1204
- netdata_MSSQL_release_results(mi->conn->dbSQLJobs);
1205
-}
1206
-
1207
-void metdata_mssql_fill_dictionary_from_db(struct mssql_instance *mi)
1208
-{
1209
- char dbname[SQLSERVER_MAX_NAME_LENGTH + 1];
1210
- SQLLEN col_data_len = 0;
1211
-
1212
- static int next_try = NETDATA_MSSQL_NEXT_TRY - 1;
1213
-
1214
- if (++next_try != NETDATA_MSSQL_NEXT_TRY)
1215
- return;
1216
-
1217
- next_try = 0;
1218
-
1219
- SQLRETURN ret;
1220
-
1221
- ret = SQLExecDirect(mi->conn->databaseListSTMT, (SQLCHAR *)NETDATA_QUERY_LIST_DB, SQL_NTS);
1222
- if (netdata_mssql_check_result(ret)) {
1223
- netdata_MSSQL_error(SQL_HANDLE_STMT, mi->conn->databaseListSTMT, NETDATA_MSSQL_ODBC_QUERY, mi->instanceID);
1224
- goto enddblist;
1225
- }
1226
-
1227
- ret = SQLBindCol(mi->conn->databaseListSTMT, 1, SQL_C_CHAR, dbname, sizeof(dbname), &col_data_len);
1228
-
1229
- if (netdata_mssql_check_result(ret)) {
1230
- netdata_MSSQL_error(SQL_HANDLE_STMT, mi->conn->databaseListSTMT, NETDATA_MSSQL_ODBC_PREPARE, mi->instanceID);
1231
- goto enddblist;
1232
- }
1233
-
1234
- int i = 0;
1235
- do {
1236
- ret = SQLFetch(mi->conn->databaseListSTMT);
1237
- if (netdata_mssql_check_result(ret)) {
1238
- goto enddblist;
1239
- }
1240
-
1241
- struct mssql_db_instance *mdi = dictionary_set(mi->databases, dbname, NULL, sizeof(*mdi));
1242
- if (!mdi)
1243
- continue;
1244
-
1245
- mdi->updated = 0;
1246
- if (!mdi->parent) {
1247
- mdi->parent = mi;
1248
- }
1249
-
1250
- if (mi->conn && !strncmp(dbname, NETDATA_REPLICATION_DB, sizeof(NETDATA_REPLICATION_DB) - 1)) {
1251
- mdi->running_replication = true;
1252
- }
1253
-
1254
- if (!i) {
1255
- mdi->collect_instance = true;
1256
- }
1257
- } while (true);
1258
-
1259
-enddblist:
1260
- netdata_MSSQL_release_results(mi->conn->databaseListSTMT);
1261
-}
1262
-
1263
-static bool netdata_MSSQL_initialize_connection(struct netdata_mssql_conn *nmc)
1264
-{
1265
- SQLRETURN ret;
1266
- if (nmc->netdataSQLEnv == NULL) {
1267
- ret = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &nmc->netdataSQLEnv);
1268
- if (netdata_mssql_check_result(ret))
1269
- return FALSE;
1270
-
1271
- ret = SQLSetEnvAttr(nmc->netdataSQLEnv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3, 0);
1272
- if (netdata_mssql_check_result(ret)) {
1273
- return FALSE;
1274
- }
1275
- }
1276
-
1277
- ret = SQLAllocHandle(SQL_HANDLE_DBC, nmc->netdataSQLEnv, &nmc->netdataSQLHDBc);
1278
- if (netdata_mssql_check_result(ret)) {
1279
- return FALSE;
1280
- }
1281
-
1282
- ret = SQLSetConnectAttr(nmc->netdataSQLHDBc, SQL_LOGIN_TIMEOUT, (SQLPOINTER)5, 0);
1283
- if (netdata_mssql_check_result(ret)) {
1284
- return FALSE;
1285
- }
1286
-
1287
- ret = SQLSetConnectAttr(nmc->netdataSQLHDBc, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER)TRUE, 0);
1288
- if (netdata_mssql_check_result(ret)) {
1289
- return FALSE;
1290
- }
1291
-
1292
- SQLCHAR ret_conn_str[1024];
1293
- ret = SQLDriverConnect(
1294
- nmc->netdataSQLHDBc, NULL, nmc->connectionString, SQL_NTS, ret_conn_str, 1024, NULL, SQL_DRIVER_NOPROMPT);
1295
-
1296
- BOOL retConn;
1297
- switch (ret) {
1298
- case SQL_NO_DATA_FOUND:
1299
- case SQL_INVALID_HANDLE:
1300
- case SQL_ERROR:
1301
- default:
1302
- netdata_MSSQL_error(SQL_HANDLE_DBC, nmc->netdataSQLHDBc, NETDATA_MSSQL_ODBC_CONNECT, NULL);
1303
- retConn = FALSE;
1304
- break;
1305
- case SQL_SUCCESS:
1306
- case SQL_SUCCESS_WITH_INFO:
1307
- retConn = TRUE;
1308
- break;
1309
- }
1310
-
1311
- if (retConn) {
1312
- SQLSetConnectAttr(nmc->netdataSQLHDBc, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER)SQL_AUTOCOMMIT_ON, 0);
1313
-
1314
- ret = SQLAllocHandle(SQL_HANDLE_STMT, nmc->netdataSQLHDBc, &nmc->checkPermSTMT);
1315
- if (netdata_mssql_check_result(ret)) {
1316
- retConn = FALSE;
1317
- goto endMSSQLInitializationConnection;
1318
- }
1319
-
1320
- ret = SQLAllocHandle(SQL_HANDLE_STMT, nmc->netdataSQLHDBc, &nmc->databaseListSTMT);
1321
- if (netdata_mssql_check_result(ret)) {
1322
- retConn = FALSE;
1323
- goto endMSSQLInitializationConnection;
1324
- }
1325
-
1326
- ret = SQLAllocHandle(SQL_HANDLE_STMT, nmc->netdataSQLHDBc, &nmc->dataFileSizeSTMT);
1327
- if (netdata_mssql_check_result(ret)) {
1328
- retConn = FALSE;
1329
- goto endMSSQLInitializationConnection;
1330
- }
1331
-
1332
- ret = SQLAllocHandle(SQL_HANDLE_STMT, nmc->netdataSQLHDBc, &nmc->dbTransactionSTMT);
1333
- if (netdata_mssql_check_result(ret)) {
1334
- retConn = FALSE;
1335
- goto endMSSQLInitializationConnection;
1336
- }
1337
-
1338
- ret = SQLAllocHandle(SQL_HANDLE_STMT, nmc->netdataSQLHDBc, &nmc->dbInstanceTransactionSTMT);
1339
- if (netdata_mssql_check_result(ret)) {
1340
- retConn = FALSE;
1341
- goto endMSSQLInitializationConnection;
1342
- }
1343
-
1344
- ret = SQLAllocHandle(SQL_HANDLE_STMT, nmc->netdataSQLHDBc, &nmc->dbLocksSTMT);
1345
- if (netdata_mssql_check_result(ret)) {
1346
- retConn = FALSE;
1347
- goto endMSSQLInitializationConnection;
1348
- }
1349
-
1350
- ret = SQLAllocHandle(SQL_HANDLE_STMT, nmc->netdataSQLHDBc, &nmc->dbWaitsSTMT);
1351
- if (netdata_mssql_check_result(ret)) {
1352
- retConn = FALSE;
1353
- goto endMSSQLInitializationConnection;
1354
- }
1355
-
1356
- ret = SQLAllocHandle(SQL_HANDLE_STMT, nmc->netdataSQLHDBc, &nmc->dbSQLState);
1357
- if (netdata_mssql_check_result(ret)) {
1358
- retConn = FALSE;
1359
- goto endMSSQLInitializationConnection;
1360
- }
1361
-
1362
- ret = SQLAllocHandle(SQL_HANDLE_STMT, nmc->netdataSQLHDBc, &nmc->dbSQLJobs);
1363
- if (netdata_mssql_check_result(ret)) {
1364
- retConn = FALSE;
1365
- goto endMSSQLInitializationConnection;
1366
- }
1367
-
1368
- ret = SQLAllocHandle(SQL_HANDLE_STMT, nmc->netdataSQLHDBc, &nmc->dbReplicationPublisher);
1369
- if (netdata_mssql_check_result(ret)) {
1370
- retConn = FALSE;
1371
- goto endMSSQLInitializationConnection;
1372
- }
1373
- }
1374
-
1375
-endMSSQLInitializationConnection:
1376
- return retConn;
1377
-}
1378
-
1379
-// Dictionary
1380
-static DICTIONARY *mssql_instances = NULL;
1381
-
1382
-static void initialize_mssql_objects(struct mssql_instance *mi, const char *instance)
1383
-{
1384
- char prefix[NETDATA_MAX_INSTANCE_NAME];
1385
- if (!strcmp(instance, "MSSQLSERVER")) {
1386
- strncpyz(prefix, "SQLServer:", sizeof(prefix) - 1);
1387
- } else if (!strcmp(instance, "SQLEXPRESS")) {
1388
- strncpyz(prefix, "MSSQL$SQLEXPRESS:", sizeof(prefix) - 1);
1389
- if (mi->conn)
1390
- mi->conn->is_sqlexpress = true;
1391
- } else {
1392
- char *express = (mi->conn && mi->conn->is_sqlexpress) ? "SQLEXPRESS:" : "";
1393
- snprintfz(prefix, sizeof(prefix) - 1, "MSSQL$%s%s:", express, instance);
1394
- }
1395
-
1396
- size_t length = strlen(prefix);
1397
- char name[NETDATA_MAX_INSTANCE_OBJECT];
1398
- snprintfz(name, sizeof(name) - 1, "%s%s", prefix, "General Statistics");
1399
- mi->objectName[NETDATA_MSSQL_GENERAL_STATS] = strdupz(name);
1400
-
1401
- strncpyz(&name[length], "SQL Errors", sizeof(name) - length);
1402
- mi->objectName[NETDATA_MSSQL_SQL_ERRORS] = strdupz(name);
1403
-
1404
- strncpyz(&name[length], "Databases", sizeof(name) - length);
1405
- mi->objectName[NETDATA_MSSQL_DATABASE] = strdupz(name);
1406
-
1407
- strncpyz(&name[length], "SQL Statistics", sizeof(name) - length);
1408
- mi->objectName[NETDATA_MSSQL_SQL_STATS] = strdupz(name);
1409
-
1410
- strncpyz(&name[length], "Buffer Manager", sizeof(name) - length);
1411
- mi->objectName[NETDATA_MSSQL_BUFFER_MANAGEMENT] = strdupz(name);
1412
-
1413
- strncpyz(&name[length], "SystemJobs", sizeof(name) - length);
1414
- mi->objectName[NETDATA_MSSQL_JOBS] = strdupz(name);
1415
-
1416
- strncpyz(&name[length], "Memory Manager", sizeof(name) - length);
1417
- mi->objectName[NETDATA_MSSQL_MEMORY] = strdupz(name);
1418
-
1419
- strncpyz(&name[length], "Locks", sizeof(name) - length);
1420
- mi->objectName[NETDATA_MSSQL_LOCKS] = strdupz(name);
1421
-
1422
- strncpyz(&name[length], "Wait Statistics", sizeof(name) - length);
1423
- mi->objectName[NETDATA_MSSQL_WAITS] = strdupz(name);
1424
-
1425
- strncpyz(&name[length], "Access Methods", sizeof(name) - length);
1426
- mi->objectName[NETDATA_MSSQL_ACCESS_METHODS] = strdupz(name);
1427
-
1428
- mi->instanceID = strdupz(instance);
1429
-}
1430
-
1431
-static inline void initialize_mssql_keys(struct mssql_instance *mi)
1432
-{
1433
- // General Statistics (https://learn.microsoft.com/en-us/sql/relational-databases/performance-monitor/sql-server-general-statistics-object)
1434
- mi->MSSQLUserConnections.key = "User Connections";
1435
- mi->MSSQLBlockedProcesses.key = "Processes blocked";
1436
-
1437
- // SQL Statistics (https://learn.microsoft.com/en-us/sql/relational-databases/performance-monitor/sql-server-sql-statistics-object)
1438
- mi->MSSQLStatsAutoParameterization.key = "Auto-Param Attempts/sec";
1439
- mi->MSSQLStatsBatchRequests.key = "Batch Requests/sec";
1440
- mi->MSSQLStatSafeAutoParameterization.key = "Safe Auto-Params/sec";
1441
-
1442
- // Access Methods (https://learn.microsoft.com/en-us/sql/relational-databases/performance-monitor/sql-server-access-methods-object)
1443
- mi->MSSQLAccessMethodPageSplits.key = "Page Splits/sec";
1444
-
1445
- // Errors (https://learn.microsoft.com/en-us/sql/relational-databases/performance-monitor/sql-server-sql-errors-object)
1446
- mi->MSSQLSQLErrorsTotal.key = "Errors/sec";
1447
-
1448
- // Memory Management (https://learn.microsoft.com/en-us/sql/relational-databases/performance-monitor/sql-server-memory-manager-object)
1449
- mi->MSSQLConnectionMemoryBytes.key = "Connection Memory (KB)";
1450
- mi->MSSQLExternalBenefitOfMemory.key = "External benefit of memory";
1451
- mi->MSSQLPendingMemoryGrants.key = "Memory Grants Pending";
1452
- mi->MSSQLTotalServerMemory.key = "Total Server Memory (KB)";
1453
-}
1454
-
1455
-void dict_mssql_insert_locks_cb(const DICTIONARY_ITEM *item __maybe_unused, void *value, void *data __maybe_unused)
1456
-{
1457
- const char *resource = dictionary_acquired_item_name((DICTIONARY_ITEM *)item);
1458
-
1459
- // https://learn.microsoft.com/en-us/sql/relational-databases/performance-monitor/sql-server-locks-object
1460
- struct mssql_lock_instance *ptr = value;
1461
- ptr->resourceID = strdupz(resource);
1462
- ptr->deadLocks.key = "Number of Deadlocks/sec";
1463
- ptr->lockWait.key = "Lock Waits/sec";
1464
-}
1465
-
1466
-void dict_mssql_insert_wait_cb(const DICTIONARY_ITEM *item __maybe_unused, void *value, void *data __maybe_unused)
1467
-{
1468
- const char *type = dictionary_acquired_item_name((DICTIONARY_ITEM *)item);
1469
-
1470
- struct mssql_db_waits *mdw = value;
1471
-
1472
- mdw->wait_type = strdupz(type);
1473
- mdw->wait_category = NULL;
1474
- mdw->rd_total_wait = mdw->rd_max_wait_time_msec = mdw->rd_resource_wait_msec = mdw->rd_signal_wait_msec =
1475
- mdw->rd_waiting_tasks = NULL;
1476
-}
1477
-
1478
-void dict_mssql_insert_databases_cb(const DICTIONARY_ITEM *item __maybe_unused, void *value, void *data __maybe_unused)
1479
-{
1480
- struct mssql_db_instance *mdi = value;
1481
-
1482
- mdi->collecting_data = true;
1483
-}
1484
-
1485
-void dict_mssql_insert_replication_cb(const DICTIONARY_ITEM *item __maybe_unused, void *value, void *data __maybe_unused)
1486
-{
1487
- UNUSED(value);
1488
-}
1489
-
1490
-void dict_mssql_insert_jobs_cb(const DICTIONARY_ITEM *item __maybe_unused, void *value, void *data __maybe_unused)
1491
-{
1492
- UNUSED(value);
1493
-}
1494
-
1495
-// Options
1496
-void netdata_mount_mssql_connection_string(struct netdata_mssql_conn *dbInput)
1497
-{
1498
- SQLCHAR conn[1024];
1499
- const char *serverAddress;
1500
- const char *serverAddressArg;
1501
- if (!dbInput) {
1502
- return;
1503
- }
1504
-
1505
- char auth[512];
1506
- if (dbInput->server && dbInput->address) {
1507
- nd_log(
1508
- NDLS_COLLECTORS,
1509
- NDLP_ERR,
1510
- "Collector is not expecting server and address defined together, please, select one of them.");
1511
- dbInput->connectionString = NULL;
1512
- return;
1513
- }
1514
-
1515
- if (dbInput->server) {
1516
- serverAddress = "Server";
1517
- serverAddressArg = dbInput->server;
1518
- } else {
1519
- serverAddressArg = "Address";
1520
- serverAddress = dbInput->address;
1521
- }
1522
-
1523
- if (dbInput->windows_auth)
1524
- snprintfz(auth, sizeof(auth) - 1, "Trusted_Connection = yes");
1525
- else if (!dbInput->username || !dbInput->password) {
1526
- nd_log(
1527
- NDLS_COLLECTORS,
1528
- NDLP_ERR,
1529
- "You are not using Windows Authentication. Thus, it is necessary to specify user and password.");
1530
- dbInput->connectionString = NULL;
1531
- return;
1532
- } else {
1533
- snprintfz(auth, sizeof(auth) - 1, "UID=%s;PWD=%s;", dbInput->username, dbInput->password);
1534
- }
1535
-
1536
- snprintfz(
1537
- (char *)conn, sizeof(conn) - 1, "Driver={%s};%s=%s;%s", dbInput->driver, serverAddress, serverAddressArg, auth);
1538
- dbInput->connectionString = (SQLCHAR *)strdupz((char *)conn);
1539
-}
1540
-
1541
-static void netdata_read_config_options()
1542
-{
1543
-#define NETDATA_MAX_MSSSQL_SECTION_LENGTH (40)
1544
-#define NETDATA_DEFAULT_MSSQL_SECTION "plugin:windows:PerflibMSSQL"
1545
- uint16_t expected_instances = 1;
1546
- uint16_t total_instances = 0;
1547
- for (; total_instances < expected_instances; total_instances++) {
1548
- char section_name[NETDATA_MAX_MSSSQL_SECTION_LENGTH + 1];
1549
- char upper_instance[NETDATA_MAX_INSTANCE_OBJECT + 1];
1550
- strncpyz(section_name, NETDATA_DEFAULT_MSSQL_SECTION, sizeof(NETDATA_DEFAULT_MSSQL_SECTION));
1551
- if (total_instances) {
1552
- snprintfz(§ion_name[sizeof(NETDATA_DEFAULT_MSSQL_SECTION) - 1], 5, "%d", total_instances);
1553
- }
1554
- const char *instance = inicfg_get(&netdata_config, section_name, "instance", NULL);
1555
- int additional_instances = (int)inicfg_get_number(&netdata_config, section_name, "additional instances", 0);
1556
- if (!instance || strlen(instance) > NETDATA_MAX_INSTANCE_OBJECT) {
1557
- nd_log(
1558
- NDLS_COLLECTORS,
1559
- NDLP_ERR,
1560
- "You must specify a valid 'instance' name to collect data from database in section %s.",
1561
- section_name);
1562
- continue;
1563
- }
1564
-
1565
- if (!total_instances && additional_instances) {
1566
- if (additional_instances > 64) {
1567
- nd_log(NDLS_COLLECTORS, NDLP_ERR, "Number of instances is bigger than expected (64)");
1568
- expected_instances = 64;
1569
- }
1570
- expected_instances = additional_instances + 1;
1571
- }
1572
-
1573
- const char *move = instance;
1574
- int i;
1575
- for (i = 0; *move; move++, i++) {
1576
- upper_instance[i] = toupper(*move);
1577
- }
1578
- upper_instance[i] = '\0';
1579
-
1580
- struct netdata_mssql_conn *dbconn = dictionary_set(conn_options, upper_instance, NULL, sizeof(*dbconn));
1581
-
1582
- dbconn->instance = strdupz(upper_instance);
1583
- dbconn->driver = inicfg_get(&netdata_config, section_name, "driver", "SQL Server");
1584
- dbconn->server = inicfg_get(&netdata_config, section_name, "server", NULL);
1585
- dbconn->address = inicfg_get(&netdata_config, section_name, "address", NULL);
1586
- dbconn->username = inicfg_get(&netdata_config, section_name, "uid", NULL);
1587
- dbconn->password = inicfg_get(&netdata_config, section_name, "pwd", NULL);
1588
- dbconn->instances = additional_instances;
1589
- dbconn->windows_auth = inicfg_get_boolean(&netdata_config, section_name, "windows authentication", false);
1590
- dbconn->is_sqlexpress = inicfg_get_boolean(&netdata_config, section_name, "express", false);
1591
- dbconn->is_connected = FALSE;
1592
-
1593
- netdata_mount_mssql_connection_string(dbconn);
1594
- }
1595
-}
1596
-
1597
-static inline struct netdata_mssql_conn *netdata_mssql_get_conn_option(const char *instance)
1598
-{
1599
- return (struct netdata_mssql_conn *)dictionary_get(conn_options, instance);
1600
-}
1601
-
1602
-void mssql_fill_initial_instances(struct mssql_instance *mi)
1603
-{
1604
- // https://learn.microsoft.com/en-us/sql/relational-databases/performance-monitor/sql-server-locks-object?view=sql-server-ver17
1605
- char *keys[] = {
1606
- "AllocUnit",
1607
- "Application",
1608
- "Database",
1609
- "Extent",
1610
- "File",
1611
- "HoBT",
1612
- "Key",
1613
- "Metadata",
1614
- "OIB",
1615
- "Object",
1616
- "Page",
1617
- "RID",
1618
- "RowGroup",
1619
- "Xact",
1620
- NULL};
1621
- for (int i = 0; keys[i]; i++) {
1622
- (void)dictionary_set(mi->locks_instances, keys[i], NULL, sizeof(struct mssql_lock_instance));
1623
- }
1624
-}
1625
-
1626
-void dict_mssql_insert_cb(const DICTIONARY_ITEM *item __maybe_unused, void *value, void *data __maybe_unused)
1627
-{
1628
- struct mssql_instance *mi = value;
1629
- const char *instance = dictionary_acquired_item_name((DICTIONARY_ITEM *)item);
1630
- bool *create_thread = data;
1631
-
1632
- if (!mi->locks_instances) {
1633
- mi->locks_instances = dictionary_create_advanced(
1634
- DICT_OPTION_DONT_OVERWRITE_VALUE | DICT_OPTION_FIXED_SIZE, NULL, sizeof(struct mssql_lock_instance));
1635
- dictionary_register_insert_callback(mi->locks_instances, dict_mssql_insert_locks_cb, NULL);
1636
- mssql_fill_initial_instances(mi);
1637
- }
1638
-
1639
- if (!mi->databases) {
1640
- mi->databases = dictionary_create_advanced(
1641
- DICT_OPTION_DONT_OVERWRITE_VALUE | DICT_OPTION_FIXED_SIZE, NULL, sizeof(struct mssql_db_instance));
1642
- dictionary_register_insert_callback(mi->databases, dict_mssql_insert_databases_cb, NULL);
1643
- }
1644
-
1645
- if (!mi->publisher_publication) {
1646
- mi->publisher_publication = dictionary_create_advanced(
1647
- DICT_OPTION_DONT_OVERWRITE_VALUE | DICT_OPTION_FIXED_SIZE,
1648
- NULL,
1649
- sizeof(struct mssql_publisher_publication));
1650
- dictionary_register_insert_callback(mi->publisher_publication, dict_mssql_insert_replication_cb, NULL);
1651
- }
1652
-
1653
- if (!mi->sysjobs) {
1654
- mi->sysjobs = dictionary_create_advanced(
1655
- DICT_OPTION_DONT_OVERWRITE_VALUE | DICT_OPTION_FIXED_SIZE, NULL, sizeof(struct mssql_db_jobs));
1656
- dictionary_register_insert_callback(mi->sysjobs, dict_mssql_insert_jobs_cb, NULL);
1657
- }
1658
-
1659
- if (!mi->waits) {
1660
- mi->waits = dictionary_create_advanced(
1661
- DICT_OPTION_DONT_OVERWRITE_VALUE | DICT_OPTION_FIXED_SIZE, NULL, sizeof(struct mssql_db_waits));
1662
- dictionary_register_insert_callback(mi->waits, dict_mssql_insert_wait_cb, NULL);
1663
- }
1664
-
1665
- initialize_mssql_objects(mi, instance);
1666
- initialize_mssql_keys(mi);
1667
- mi->conn = netdata_mssql_get_conn_option(instance);
1668
-
1669
- if (mi->conn && mi->conn->connectionString) {
1670
- mi->conn->is_connected = netdata_MSSQL_initialize_connection(mi->conn);
1671
- if (mi->conn->is_connected)
1672
- *create_thread = true;
1673
- }
1674
-}
1675
-
1676
-void dict_mssql_insert_conn_option(const DICTIONARY_ITEM *item __maybe_unused, void *value, void *data __maybe_unused)
1677
-{
1678
- ;
1679
-}
1680
-
1681
-static void mssql_fill_dictionary(int update_every)
1682
-{
1683
- HKEY hKey;
1684
- LSTATUS ret = RegOpenKeyExA(
1685
- HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Microsoft SQL Server\\Instance Names\\SQL", 0, KEY_READ, &hKey);
1686
- if (ret != ERROR_SUCCESS)
1687
- return;
1688
-
1689
- DWORD values = 0;
1690
-
1691
- ret = RegQueryInfoKey(hKey, NULL, NULL, NULL, NULL, NULL, NULL, &values, NULL, NULL, NULL, NULL);
1692
- if (ret != ERROR_SUCCESS) {
1693
- goto endMSSQLFillDict;
1694
- }
1695
-
1696
- if (!values) {
1697
- ret = ERROR_PATH_NOT_FOUND;
1698
- goto endMSSQLFillDict;
1699
- }
1700
-
1701
-// https://learn.microsoft.com/en-us/windows/win32/sysinfo/enumerating-registry-subkeys
1702
-#define REGISTRY_MAX_VALUE 16383
1703
-
1704
- DWORD i;
1705
- char avalue[REGISTRY_MAX_VALUE] = {'\0'};
1706
- for (i = 0; i < values; i++) {
1707
- avalue[0] = '\0';
1708
- DWORD length = REGISTRY_MAX_VALUE;
1709
-
1710
- ret = RegEnumValue(hKey, i, avalue, &length, NULL, NULL, NULL, NULL);
1711
- if (ret != ERROR_SUCCESS)
1712
- continue;
1713
-
1714
- struct mssql_instance *p = dictionary_set(mssql_instances, avalue, NULL, sizeof(*p));
1715
- p->update_every = update_every;
1716
- }
1717
-
1718
-endMSSQLFillDict:
1719
- RegCloseKey(hKey);
1720
-}
1721
-
1722
-int netdata_mssql_reset_value(const DICTIONARY_ITEM *item __maybe_unused, void *value, void *data __maybe_unused)
1723
-{
1724
- struct mssql_db_instance *mdi = value;
1725
-
1726
- mdi->collecting_data = false;
1727
-
1728
- return 1;
1729
-}
1730
-
1731
-int dict_mssql_query_cb(const DICTIONARY_ITEM *item __maybe_unused, void *value, void *data __maybe_unused)
1732
-{
1733
- struct mssql_instance *mi = value;
1734
- static long collecting = 1;
1735
-
1736
- if (mi->conn && mi->conn->is_connected && collecting) {
1737
- collecting = metdata_mssql_check_permission(mi);
1738
- if (!collecting) {
1739
- nd_log(
1740
- NDLS_COLLECTORS,
1741
- NDLP_ERR,
1742
- "User %s does not have permission to run queries on %s",
1743
- mi->conn->username,
1744
- mi->instanceID);
1745
- } else {
1746
- metdata_mssql_fill_dictionary_from_db(mi);
1747
- metdata_mssql_fill_mssql_status(mi);
1748
- metdata_mssql_fill_job_status(mi);
1749
- dictionary_sorted_walkthrough_read(mi->databases, dict_mssql_databases_run_queries, NULL);
1750
- }
1751
-
1752
- collecting = dict_mssql_fill_waits(mi);
1753
- } else {
1754
- dictionary_sorted_walkthrough_read(mi->databases, netdata_mssql_reset_value, NULL);
1755
- }
1756
-
1757
- return 1;
1758
-}
1759
-
1760
-static void netdata_mssql_queries(void *ptr __maybe_unused)
1761
-{
1762
- heartbeat_t hb;
1763
- heartbeat_init(&hb, USEC_PER_SEC);
1764
- int update_every = UPDATE_EVERY_MIN;
1765
-
1766
- while (service_running(SERVICE_COLLECTORS)) {
1767
- (void)heartbeat_next(&hb);
1768
-
1769
- if (unlikely(!service_running(SERVICE_COLLECTORS)))
1770
- break;
1771
-
1772
- dictionary_sorted_walkthrough_read(mssql_instances, dict_mssql_query_cb, &update_every);
1773
- }
1774
-}
1775
-
1776
-static ND_THREAD *mssql_queries_thread = NULL;
1777
-
1778
-static int initialize(int update_every)
1779
-{
1780
- static bool create_thread = false;
1781
- mssql_instances = dictionary_create_advanced(
1782
- DICT_OPTION_DONT_OVERWRITE_VALUE | DICT_OPTION_FIXED_SIZE, NULL, sizeof(struct mssql_instance));
1783
-
1784
- dictionary_register_insert_callback(mssql_instances, dict_mssql_insert_cb, &create_thread);
1785
-
1786
- conn_options = dictionary_create_advanced(
1787
- DICT_OPTION_DONT_OVERWRITE_VALUE | DICT_OPTION_FIXED_SIZE, NULL, sizeof(struct netdata_mssql_conn));
1788
- dictionary_register_insert_callback(conn_options, dict_mssql_insert_conn_option, NULL);
1789
-
1790
- netdata_read_config_options();
1791
- mssql_fill_dictionary(update_every);
1792
-
1793
- if (create_thread)
1794
- mssql_queries_thread =
1795
- nd_thread_create("mssql_queries", NETDATA_THREAD_OPTION_DEFAULT, netdata_mssql_queries, &update_every);
1796
-
1797
- return 0;
1798
-}
1799
-
1800
-static void do_mssql_general_stats(PERF_DATA_BLOCK *pDataBlock, struct mssql_instance *mi, int update_every)
1801
-{
1802
- char id[RRD_ID_LENGTH_MAX + 1];
1803
-
1804
- PERF_OBJECT_TYPE *pObjectType =
1805
- perflibFindObjectTypeByName(pDataBlock, mi->objectName[NETDATA_MSSQL_GENERAL_STATS]);
1806
- if (!pObjectType)
1807
- return;
1808
-
1809
- if (perflibGetObjectCounter(pDataBlock, pObjectType, &mi->MSSQLUserConnections)) {
1810
- if (!mi->st_user_connections) {
1811
- snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_user_connections", mi->instanceID);
1812
- netdata_fix_chart_name(id);
1813
- mi->st_user_connections = rrdset_create_localhost(
1814
- "mssql",
1815
- id,
1816
- NULL,
1817
- "connections",
1818
- "mssql.instance_user_connections",
1819
- "User connections",
1820
- "connections",
1821
- PLUGIN_WINDOWS_NAME,
1822
- "PerflibMSSQL",
1823
- PRIO_MSSQL_USER_CONNECTIONS,
1824
- update_every,
1825
- RRDSET_TYPE_LINE);
1826
-
1827
- mi->rd_user_connections = rrddim_add(mi->st_user_connections, "user", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
1828
-
1829
- rrdlabels_add(mi->st_user_connections->rrdlabels, "mssql_instance", mi->instanceID, RRDLABEL_SRC_AUTO);
1830
- }
1831
-
1832
- rrddim_set_by_pointer(
1833
- mi->st_user_connections, mi->rd_user_connections, (collected_number)mi->MSSQLUserConnections.current.Data);
1834
- rrdset_done(mi->st_user_connections);
1835
- }
1836
-
1837
- if (perflibGetObjectCounter(pDataBlock, pObjectType, &mi->MSSQLBlockedProcesses)) {
1838
- if (!mi->st_process_blocked) {
1839
- snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_blocked_process", mi->instanceID);
1840
- netdata_fix_chart_name(id);
1841
- mi->st_process_blocked = rrdset_create_localhost(
1842
- "mssql",
1843
- id,
1844
- NULL,
1845
- "processes",
1846
- "mssql.instance_blocked_processes",
1847
- "Blocked processes",
1848
- "process",
1849
- PLUGIN_WINDOWS_NAME,
1850
- "PerflibMSSQL",
1851
- PRIO_MSSQL_BLOCKED_PROCESSES,
1852
- update_every,
1853
- RRDSET_TYPE_LINE);
1854
-
1855
- mi->rd_process_blocked = rrddim_add(mi->st_process_blocked, "blocked", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
1856
-
1857
- rrdlabels_add(mi->st_process_blocked->rrdlabels, "mssql_instance", mi->instanceID, RRDLABEL_SRC_AUTO);
1858
- }
1859
-
1860
- rrddim_set_by_pointer(
1861
- mi->st_process_blocked, mi->rd_process_blocked, (collected_number)mi->MSSQLBlockedProcesses.current.Data);
1862
- rrdset_done(mi->st_process_blocked);
1863
- }
1864
-}
1865
-
1866
-static void do_mssql_statistics_perflib(PERF_DATA_BLOCK *pDataBlock, struct mssql_instance *mi, int update_every)
1867
-{
1868
- char id[RRD_ID_LENGTH_MAX + 1];
1869
-
1870
- PERF_OBJECT_TYPE *pObjectType = perflibFindObjectTypeByName(pDataBlock, mi->objectName[NETDATA_MSSQL_SQL_STATS]);
1871
- if (!pObjectType)
1872
- return;
1873
-
1874
- if (perflibGetObjectCounter(pDataBlock, pObjectType, &mi->MSSQLStatsAutoParameterization)) {
1875
- if (!mi->st_stats_auto_param) {
1876
- snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_sqlstats_auto_parameterization_attempts", mi->instanceID);
1877
- netdata_fix_chart_name(id);
1878
- mi->st_stats_auto_param = rrdset_create_localhost(
1879
- "mssql",
1880
- id,
1881
- NULL,
1882
- "sql activity",
1883
- "mssql.instance_sqlstats_auto_parameterization_attempts",
1884
- "Failed auto-parameterization attempts",
1885
- "attempts/s",
1886
- PLUGIN_WINDOWS_NAME,
1887
- "PerflibMSSQL",
1888
- PRIO_MSSQL_STATS_AUTO_PARAMETRIZATION,
1889
- update_every,
1890
- RRDSET_TYPE_LINE);
1891
-
1892
- mi->rd_stats_auto_param =
1893
- rrddim_add(mi->st_stats_auto_param, "failed", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
1894
-
1895
- rrdlabels_add(mi->st_stats_auto_param->rrdlabels, "mssql_instance", mi->instanceID, RRDLABEL_SRC_AUTO);
1896
- }
1897
-
1898
- rrddim_set_by_pointer(
1899
- mi->st_stats_auto_param,
1900
- mi->rd_stats_auto_param,
1901
- (collected_number)mi->MSSQLStatsAutoParameterization.current.Data);
1902
- rrdset_done(mi->st_stats_auto_param);
1903
- }
1904
-
1905
- if (perflibGetObjectCounter(pDataBlock, pObjectType, &mi->MSSQLStatsBatchRequests)) {
1906
- if (!mi->st_stats_batch_request) {
1907
- snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_sqlstats_batch_requests", mi->instanceID);
1908
- netdata_fix_chart_name(id);
1909
- mi->st_stats_batch_request = rrdset_create_localhost(
1910
- "mssql",
1911
- id,
1912
- NULL,
1913
- "sql activity",
1914
- "mssql.instance_sqlstats_batch_requests",
1915
- "Total of batches requests",
1916
- "requests/s",
1917
- PLUGIN_WINDOWS_NAME,
1918
- "PerflibMSSQL",
1919
- PRIO_MSSQL_STATS_BATCH_REQUEST,
1920
- update_every,
1921
- RRDSET_TYPE_LINE);
1922
-
1923
- mi->rd_stats_batch_request =
1924
- rrddim_add(mi->st_stats_batch_request, "batch", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
1925
-
1926
- rrdlabels_add(mi->st_stats_batch_request->rrdlabels, "mssql_instance", mi->instanceID, RRDLABEL_SRC_AUTO);
1927
- }
1928
-
1929
- rrddim_set_by_pointer(
1930
- mi->st_stats_batch_request,
1931
- mi->rd_stats_batch_request,
1932
- (collected_number)mi->MSSQLStatsBatchRequests.current.Data);
1933
- rrdset_done(mi->st_stats_batch_request);
1934
- }
1935
-
1936
- if (perflibGetObjectCounter(pDataBlock, pObjectType, &mi->MSSQLStatSafeAutoParameterization)) {
1937
- if (!mi->st_stats_safe_auto) {
1938
- snprintfz(
1939
- id, RRD_ID_LENGTH_MAX, "instance_%s_sqlstats_safe_auto_parameterization_attempts", mi->instanceID);
1940
- netdata_fix_chart_name(id);
1941
- mi->st_stats_safe_auto = rrdset_create_localhost(
1942
- "mssql",
1943
- id,
1944
- NULL,
1945
- "sql activity",
1946
- "mssql.instance_sqlstats_safe_auto_parameterization_attempts",
1947
- "Safe auto-parameterization attempts",
1948
- "attempts/s",
1949
- PLUGIN_WINDOWS_NAME,
1950
- "PerflibMSSQL",
1951
- PRIO_MSSQL_STATS_SAFE_AUTO_PARAMETRIZATION,
1952
- update_every,
1953
- RRDSET_TYPE_LINE);
1954
-
1955
- mi->rd_stats_safe_auto = rrddim_add(mi->st_stats_safe_auto, "safe", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
1956
-
1957
- rrdlabels_add(mi->st_stats_safe_auto->rrdlabels, "mssql_instance", mi->instanceID, RRDLABEL_SRC_AUTO);
1958
- }
1959
-
1960
- rrddim_set_by_pointer(
1961
- mi->st_stats_safe_auto,
1962
- mi->rd_stats_safe_auto,
1963
- (collected_number)mi->MSSQLStatSafeAutoParameterization.current.Data);
1964
- rrdset_done(mi->st_stats_safe_auto);
1965
- }
1966
-}
1967
-
1968
-static void do_mssql_access_methods(PERF_DATA_BLOCK *pDataBlock, struct mssql_instance *mi, int update_every)
1969
-{
1970
- char id[RRD_ID_LENGTH_MAX + 1];
1971
-
1972
- PERF_OBJECT_TYPE *pObjectType =
1973
- perflibFindObjectTypeByName(pDataBlock, mi->objectName[NETDATA_MSSQL_ACCESS_METHODS]);
1974
- if (!pObjectType)
1975
- return;
1976
-
1977
- if (perflibGetObjectCounter(pDataBlock, pObjectType, &mi->MSSQLAccessMethodPageSplits)) {
1978
- if (!mi->st_access_method_page_splits) {
1979
- snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_accessmethods_page_splits", mi->instanceID);
1980
- netdata_fix_chart_name(id);
1981
- mi->st_access_method_page_splits = rrdset_create_localhost(
1982
- "mssql",
1983
- id,
1984
- NULL,
1985
- "buffer cache",
1986
- "mssql.instance_accessmethods_page_splits",
1987
- "Page splits",
1988
- "splits/s",
1989
- PLUGIN_WINDOWS_NAME,
1990
- "PerflibMSSQL",
1991
- PRIO_MSSQL_BUFF_METHODS_PAGE_SPLIT,
1992
- update_every,
1993
- RRDSET_TYPE_LINE);
1994
-
1995
- mi->rd_access_method_page_splits =
1996
- rrddim_add(mi->st_access_method_page_splits, "page", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
1997
-
1998
- rrdlabels_add(
1999
- mi->st_access_method_page_splits->rrdlabels, "mssql_instance", mi->instanceID, RRDLABEL_SRC_AUTO);
2000
- }
2001
-
2002
- rrddim_set_by_pointer(
2003
- mi->st_access_method_page_splits,
2004
- mi->rd_access_method_page_splits,
2005
- (collected_number)mi->MSSQLAccessMethodPageSplits.current.Data);
2006
- rrdset_done(mi->st_access_method_page_splits);
2007
- }
2008
-}
2009
-
2010
-static void do_mssql_errors(PERF_DATA_BLOCK *pDataBlock, struct mssql_instance *mi, int update_every)
2011
-{
2012
- char id[RRD_ID_LENGTH_MAX + 1];
2013
-
2014
- PERF_OBJECT_TYPE *pObjectType = perflibFindObjectTypeByName(pDataBlock, mi->objectName[NETDATA_MSSQL_SQL_ERRORS]);
2015
- if (!pObjectType)
2016
- return;
2017
-
2018
- if (perflibGetObjectCounter(pDataBlock, pObjectType, &mi->MSSQLSQLErrorsTotal)) {
2019
- if (!mi->st_sql_errors) {
2020
- snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_sql_errors_total", mi->instanceID);
2021
- netdata_fix_chart_name(id);
2022
- mi->st_sql_errors = rrdset_create_localhost(
2023
- "mssql",
2024
- id,
2025
- NULL,
2026
- "errors",
2027
- "mssql.instance_sql_errors",
2028
- "Errors",
2029
- "errors/s",
2030
- PLUGIN_WINDOWS_NAME,
2031
- "PerflibMSSQL",
2032
- PRIO_MSSQL_SQL_ERRORS,
2033
- update_every,
2034
- RRDSET_TYPE_LINE);
2035
-
2036
- mi->rd_sql_errors = rrddim_add(mi->st_sql_errors, "errors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
2037
-
2038
- rrdlabels_add(mi->st_sql_errors->rrdlabels, "mssql_instance", mi->instanceID, RRDLABEL_SRC_AUTO);
2039
- }
2040
-
2041
- rrddim_set_by_pointer(
2042
- mi->st_sql_errors, mi->rd_sql_errors, (collected_number)mi->MSSQLAccessMethodPageSplits.current.Data);
2043
- rrdset_done(mi->st_sql_errors);
2044
- }
2045
-}
2046
-
2047
-void dict_mssql_locks_wait_charts(struct mssql_instance *mi, struct mssql_lock_instance *mli, const char *resource)
2048
-{
2049
- if (!mli->st_lockWait) {
2050
- char id[RRD_ID_LENGTH_MAX + 1];
2051
-
2052
- snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_resource_%s_lock_wait", mi->instanceID, resource);
2053
- netdata_fix_chart_name(id);
2054
- mli->st_lockWait = rrdset_create_localhost(
2055
- "mssql",
2056
- id,
2057
- NULL,
2058
- "locks",
2059
- "mssql.instance_resource_lock_waits",
2060
- "Lock requests that required the caller to wait per resource",
2061
- "locks/s",
2062
- PLUGIN_WINDOWS_NAME,
2063
- "PerflibMSSQL",
2064
- PRIO_MSSQL_LOCKS_WAIT,
2065
- mi->update_every,
2066
- RRDSET_TYPE_LINE);
2067
-
2068
- rrdlabels_add(mli->st_lockWait->rrdlabels, "mssql_instance", mi->instanceID, RRDLABEL_SRC_AUTO);
2069
- rrdlabels_add(mli->st_lockWait->rrdlabels, "resource", resource, RRDLABEL_SRC_AUTO);
2070
- mli->rd_lockWait = rrddim_add(mli->st_lockWait, "locks", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
2071
- }
2072
-
2073
- rrddim_set_by_pointer(mli->st_lockWait, mli->rd_lockWait, (collected_number)mli->lockWait.current.Data);
2074
- rrdset_done(mli->st_lockWait);
2075
-}
2076
-
2077
-void dict_mssql_dead_locks_charts(struct mssql_instance *mi, struct mssql_lock_instance *mli, const char *resource)
2078
-{
2079
- if (!mli->st_deadLocks) {
2080
- char id[RRD_ID_LENGTH_MAX + 1];
2081
-
2082
- snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_resource_%s_deadlocks", mi->instanceID, resource);
2083
- netdata_fix_chart_name(id);
2084
- mli->st_deadLocks = rrdset_create_localhost(
2085
- "mssql",
2086
- id,
2087
- NULL,
2088
- "locks",
2089
- "mssql.instance_resource_deadlocks",
2090
- "Active lock requests that resulted in deadlock per resource",
2091
- "deadlocks/s",
2092
- PLUGIN_WINDOWS_NAME,
2093
- "PerflibMSSQL",
2094
- PRIO_MSSQL_LOCKS_DEADLOCK_PER_RESOURCE,
2095
- mi->update_every,
2096
- RRDSET_TYPE_LINE);
2097
-
2098
- rrdlabels_add(mli->st_deadLocks->rrdlabels, "mssql_instance", mi->instanceID, RRDLABEL_SRC_AUTO);
2099
- rrdlabels_add(mli->st_deadLocks->rrdlabels, "resource", resource, RRDLABEL_SRC_AUTO);
2100
- mli->rd_deadLocks = rrddim_add(mli->st_deadLocks, "deadlocks", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
2101
- }
2102
-
2103
- rrddim_set_by_pointer(mli->st_deadLocks, mli->rd_deadLocks, (collected_number)mli->deadLocks.current.Data);
2104
- rrdset_done(mli->st_deadLocks);
2105
-}
2106
-
2107
-int dict_mssql_locks_charts_cb(const DICTIONARY_ITEM *item __maybe_unused, void *value, void *data __maybe_unused)
2108
-{
2109
- const char *dimension = dictionary_acquired_item_name((DICTIONARY_ITEM *)item);
2110
- struct mssql_lock_instance *mli = value;
2111
- struct mssql_instance *mi = data;
2112
-
2113
- dict_mssql_locks_wait_charts(mi, mli, dimension);
2114
- dict_mssql_dead_locks_charts(mi, mli, dimension);
2115
-
2116
- return 1;
2117
-}
2118
-
2119
-static void do_mssql_locks(PERF_DATA_BLOCK *pDataBlock, struct mssql_instance *mi, int update_every __maybe_unused)
2120
-{
2121
- if (!pDataBlock)
2122
- goto end_mssql_locks;
2123
-
2124
- PERF_OBJECT_TYPE *pObjectType = perflibFindObjectTypeByName(pDataBlock, mi->objectName[NETDATA_MSSQL_LOCKS]);
2125
- if (pObjectType) {
2126
- if (pObjectType->NumInstances) {
2127
- PERF_INSTANCE_DEFINITION *pi = NULL;
2128
- for (LONG i = 0; i < pObjectType->NumInstances; i++) {
2129
- pi = perflibForEachInstance(pDataBlock, pObjectType, pi);
2130
- if (!pi)
2131
- break;
2132
-
2133
- if (!getInstanceName(pDataBlock, pObjectType, pi, windows_shared_buffer, sizeof(windows_shared_buffer)))
2134
- strncpyz(windows_shared_buffer, "[unknown]", sizeof(windows_shared_buffer) - 1);
2135
-
2136
- if (!strcasecmp(windows_shared_buffer, "_Total"))
2137
- continue;
2138
-
2139
- struct mssql_lock_instance *mli =
2140
- dictionary_set(mi->locks_instances, windows_shared_buffer, NULL, sizeof(*mli));
2141
- if (!mli)
2142
- continue;
2143
-
2144
- perflibGetInstanceCounter(pDataBlock, pObjectType, pi, &mli->deadLocks);
2145
- perflibGetInstanceCounter(pDataBlock, pObjectType, pi, &mli->lockWait);
2146
- }
2147
- }
2148
- }
2149
-
2150
-end_mssql_locks:
2151
- dictionary_sorted_walkthrough_read(mi->locks_instances, dict_mssql_locks_charts_cb, mi);
2152
-}
2153
-
2154
-void mssql_total_wait_charts(struct mssql_instance *mi, struct mssql_db_waits *mdw, const char *type)
2155
-{
2156
- if (!mdw->st_total_wait) {
2157
- char id[RRD_ID_LENGTH_MAX + 1];
2158
-
2159
- snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_%s_total_wait", mi->instanceID, type);
2160
- netdata_fix_chart_name(id);
2161
- mdw->st_total_wait = rrdset_create_localhost(
2162
- "mssql",
2163
- id,
2164
- NULL,
2165
- "locks",
2166
- "mssql.instance_total_wait_time",
2167
- "Wait time for each wait type and category",
2168
- "ms",
2169
- PLUGIN_WINDOWS_NAME,
2170
- "PerflibMSSQL",
2171
- PRIO_MSSQL_WAITS_TOTAL,
2172
- mi->update_every,
2173
- RRDSET_TYPE_LINE);
2174
-
2175
- rrdlabels_add(mdw->st_total_wait->rrdlabels, "mssql_instance", mi->instanceID, RRDLABEL_SRC_AUTO);
2176
- rrdlabels_add(mdw->st_total_wait->rrdlabels, "wait_type", mdw->wait_type, RRDLABEL_SRC_AUTO);
2177
- rrdlabels_add(mdw->st_total_wait->rrdlabels, "wait_category", mdw->wait_category, RRDLABEL_SRC_AUTO);
2178
- mdw->rd_total_wait = rrddim_add(mdw->st_total_wait, "duration", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
2179
- }
2180
-
2181
- rrddim_set_by_pointer(
2182
- mdw->st_total_wait, mdw->rd_total_wait, (collected_number)mdw->MSSQLDatabaseTotalWait.current.Data);
2183
-
2184
- rrdset_done(mdw->st_total_wait);
2185
-}
2186
-
2187
-void mssql_resource_wait_charts(struct mssql_instance *mi, struct mssql_db_waits *mdw, const char *type)
2188
-{
2189
- if (!mdw->st_resource_wait_msec) {
2190
- char id[RRD_ID_LENGTH_MAX + 1];
2191
-
2192
- snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_%s_resource_wait", mi->instanceID, type);
2193
- netdata_fix_chart_name(id);
2194
- mdw->st_resource_wait_msec = rrdset_create_localhost(
2195
- "mssql",
2196
- id,
2197
- NULL,
2198
- "locks",
2199
- "mssql.instance_resource_wait_time",
2200
- "Wait time for threads waiting on specific resource types for each wait type and category",
2201
- "ms",
2202
- PLUGIN_WINDOWS_NAME,
2203
- "PerflibMSSQL",
2204
- PRIO_MSSQL_RESOURCE_WAIT,
2205
- mi->update_every,
2206
- RRDSET_TYPE_LINE);
2207
-
2208
- rrdlabels_add(mdw->st_resource_wait_msec->rrdlabels, "mssql_instance", mi->instanceID, RRDLABEL_SRC_AUTO);
2209
- rrdlabels_add(mdw->st_resource_wait_msec->rrdlabels, "wait_type", mdw->wait_type, RRDLABEL_SRC_AUTO);
2210
- rrdlabels_add(mdw->st_resource_wait_msec->rrdlabels, "wait_category", mdw->wait_category, RRDLABEL_SRC_AUTO);
2211
- mdw->rd_resource_wait_msec =
2212
- rrddim_add(mdw->st_resource_wait_msec, "duration", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
2213
- }
2214
-
2215
- rrddim_set_by_pointer(
2216
- mdw->st_resource_wait_msec,
2217
- mdw->rd_resource_wait_msec,
2218
- (collected_number)mdw->MSSQLDatabaseResourceWaitMSec.current.Data);
2219
-
2220
- rrdset_done(mdw->st_resource_wait_msec);
2221
-}
2222
-
2223
-void mssql_signal_wait_charts(struct mssql_instance *mi, struct mssql_db_waits *mdw, const char *type)
2224
-{
2225
- if (!mdw->st_signal_wait_msec) {
2226
- char id[RRD_ID_LENGTH_MAX + 1];
2227
-
2228
- snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_%s_signal_wait", mi->instanceID, type);
2229
- netdata_fix_chart_name(id);
2230
- mdw->st_signal_wait_msec = rrdset_create_localhost(
2231
- "mssql",
2232
- id,
2233
- NULL,
2234
- "locks",
2235
- "mssql.instance_signal_wait_time",
2236
- "Delay between thread wakeup signal and actual execution start for each wait type and category",
2237
- "ms",
2238
- PLUGIN_WINDOWS_NAME,
2239
- "PerflibMSSQL",
2240
- PRIO_MSSQL_SIGNAL_WAIT,
2241
- mi->update_every,
2242
- RRDSET_TYPE_LINE);
2243
-
2244
- rrdlabels_add(mdw->st_signal_wait_msec->rrdlabels, "mssql_instance", mi->instanceID, RRDLABEL_SRC_AUTO);
2245
- rrdlabels_add(mdw->st_signal_wait_msec->rrdlabels, "wait_type", mdw->wait_type, RRDLABEL_SRC_AUTO);
2246
- rrdlabels_add(mdw->st_signal_wait_msec->rrdlabels, "wait_category", mdw->wait_category, RRDLABEL_SRC_AUTO);
2247
- mdw->rd_signal_wait_msec =
2248
- rrddim_add(mdw->st_signal_wait_msec, "duration", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
2249
- }
2250
-
2251
- rrddim_set_by_pointer(
2252
- mdw->st_signal_wait_msec,
2253
- mdw->rd_signal_wait_msec,
2254
- (collected_number)mdw->MSSQLDatabaseSignalWaitMSec.current.Data);
2255
-
2256
- rrdset_done(mdw->st_signal_wait_msec);
2257
-}
2258
-
2259
-void mssql_max_wait_charts(struct mssql_instance *mi, struct mssql_db_waits *mdw, const char *type)
2260
-{
2261
- if (!mdw->st_max_wait_time_msec) {
2262
- char id[RRD_ID_LENGTH_MAX + 1];
2263
-
2264
- snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_%s_max_wait", mi->instanceID, type);
2265
- netdata_fix_chart_name(id);
2266
- mdw->st_max_wait_time_msec = rrdset_create_localhost(
2267
- "mssql",
2268
- id,
2269
- NULL,
2270
- "locks",
2271
- "mssql.instance_max_wait_time",
2272
- "Maximum wait time for each wait type and category",
2273
- "ms",
2274
- PLUGIN_WINDOWS_NAME,
2275
- "PerflibMSSQL",
2276
- PRIO_MSSQL_MAX_WAIT_TIME,
2277
- mi->update_every,
2278
- RRDSET_TYPE_LINE);
2279
-
2280
- rrdlabels_add(mdw->st_max_wait_time_msec->rrdlabels, "mssql_instance", mi->instanceID, RRDLABEL_SRC_AUTO);
2281
- rrdlabels_add(mdw->st_max_wait_time_msec->rrdlabels, "wait_type", mdw->wait_type, RRDLABEL_SRC_AUTO);
2282
- rrdlabels_add(mdw->st_max_wait_time_msec->rrdlabels, "wait_category", mdw->wait_category, RRDLABEL_SRC_AUTO);
2283
- mdw->rd_max_wait_time_msec =
2284
- rrddim_add(mdw->st_max_wait_time_msec, "duration", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
2285
- }
2286
-
2287
- rrddim_set_by_pointer(
2288
- mdw->st_max_wait_time_msec,
2289
- mdw->rd_max_wait_time_msec,
2290
- (collected_number)mdw->MSSQLDatabaseMaxWaitTimeMSec.current.Data);
2291
-
2292
- rrdset_done(mdw->st_max_wait_time_msec);
2293
-}
2294
-
2295
-void mssql_waiting_count_charts(struct mssql_instance *mi, struct mssql_db_waits *mdw, const char *type)
2296
-{
2297
- if (!mdw->st_waiting_tasks) {
2298
- char id[RRD_ID_LENGTH_MAX + 1];
2299
-
2300
- snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_%s_waiting_count", mi->instanceID, type);
2301
- netdata_fix_chart_name(id);
2302
- mdw->st_waiting_tasks = rrdset_create_localhost(
2303
- "mssql",
2304
- id,
2305
- NULL,
2306
- "locks",
2307
- "mssql.instance_waits",
2308
- "Number of waits for each wait type and category",
2309
- "waits/s",
2310
- PLUGIN_WINDOWS_NAME,
2311
- "PerflibMSSQL",
2312
- PRIO_MSSQL_WAITING_COUNT,
2313
- mi->update_every,
2314
- RRDSET_TYPE_LINE);
2315
-
2316
- rrdlabels_add(mdw->st_waiting_tasks->rrdlabels, "mssql_instance", mi->instanceID, RRDLABEL_SRC_AUTO);
2317
- rrdlabels_add(mdw->st_waiting_tasks->rrdlabels, "wait_type", mdw->wait_type, RRDLABEL_SRC_AUTO);
2318
- rrdlabels_add(mdw->st_waiting_tasks->rrdlabels, "wait_category", mdw->wait_category, RRDLABEL_SRC_AUTO);
2319
- mdw->rd_waiting_tasks = rrddim_add(mdw->st_waiting_tasks, "waits", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
2320
- }
2321
-
2322
- rrddim_set_by_pointer(
2323
- mdw->st_waiting_tasks, mdw->rd_waiting_tasks, (collected_number)mdw->MSSQLDatabaseWaitingTasks.current.Data);
2324
-
2325
- rrdset_done(mdw->st_waiting_tasks);
2326
-}
2327
-
2328
-int dict_mssql_waits_charts_cb(const DICTIONARY_ITEM *item __maybe_unused, void *value, void *data __maybe_unused)
2329
-{
2330
- const char *dimension = dictionary_acquired_item_name((DICTIONARY_ITEM *)item);
2331
- struct mssql_db_waits *mdw = value;
2332
- struct mssql_instance *mi = data;
2333
-
2334
- mssql_total_wait_charts(mi, mdw, dimension);
2335
- mssql_resource_wait_charts(mi, mdw, dimension);
2336
- mssql_signal_wait_charts(mi, mdw, dimension);
2337
- mssql_max_wait_charts(mi, mdw, dimension);
2338
- mssql_waiting_count_charts(mi, mdw, dimension);
2339
-
2340
- return 1;
2341
-}
2342
-
2343
-static void do_mssql_waits(PERF_DATA_BLOCK *pDataBlock, struct mssql_instance *mi, int update_every)
2344
-{
2345
- dictionary_sorted_walkthrough_read(mi->waits, dict_mssql_waits_charts_cb, mi);
2346
-}
2347
-
2348
-void mssql_buffman_iops_chart(struct mssql_db_instance *mdi, struct mssql_instance *mi)
2349
-{
2350
- if (!mdi->st_buff_page_iops) {
2351
- char id[RRD_ID_LENGTH_MAX + 1];
2352
- snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_bufman_iops", mi->instanceID);
2353
- netdata_fix_chart_name(id);
2354
- mdi->st_buff_page_iops = rrdset_create_localhost(
2355
- "mssql",
2356
- id,
2357
- NULL,
2358
- "buffer cache",
2359
- "mssql.instance_bufman_iops",
2360
- "Number of pages input and output",
2361
- "pages/s",
2362
- PLUGIN_WINDOWS_NAME,
2363
- "PerflibMSSQL",
2364
- PRIO_MSSQL_BUFF_MAN_IOPS,
2365
- mi->update_every,
2366
- RRDSET_TYPE_LINE);
2367
-
2368
- mdi->rd_buff_page_reads = rrddim_add(mdi->st_buff_page_iops, "read", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
2369
- mdi->rd_buff_page_writes =
2370
- rrddim_add(mdi->st_buff_page_iops, "written", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
2371
-
2372
- rrdlabels_add(mdi->st_buff_page_iops->rrdlabels, "mssql_instance", mi->instanceID, RRDLABEL_SRC_AUTO);
2373
- }
2374
-
2375
- rrddim_set_by_pointer(
2376
- mdi->st_buff_page_iops, mdi->rd_buff_page_reads, (collected_number)mdi->MSSQLBufferPageReads.current.Data);
2377
- rrddim_set_by_pointer(
2378
- mdi->st_buff_page_iops, mdi->rd_buff_page_writes, (collected_number)mdi->MSSQLBufferPageWrites.current.Data);
2379
-
2380
- rrdset_done(mdi->st_buff_page_iops);
2381
-}
2382
-
2383
-void mssql_buffman_cache_hit_ratio_chart(struct mssql_db_instance *mdi, struct mssql_instance *mi)
2384
-{
2385
- if (!mdi->st_buff_cache_hits) {
2386
- char id[RRD_ID_LENGTH_MAX + 1];
2387
- snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_cache_hit_ratio", mi->instanceID);
2388
- netdata_fix_chart_name(id);
2389
- mdi->st_buff_cache_hits = rrdset_create_localhost(
2390
- "mssql",
2391
- id,
2392
- NULL,
2393
- "buffer cache",
2394
- "mssql.instance_cache_hit_ratio",
2395
- "Buffer Cache hit ratio",
2396
- "percentage",
2397
- PLUGIN_WINDOWS_NAME,
2398
- "PerflibMSSQL",
2399
- PRIO_MSSQL_BUFF_CACHE_HIT_RATIO,
2400
- mi->update_every,
2401
- RRDSET_TYPE_LINE);
2402
-
2403
- mdi->rd_buff_cache_hits = rrddim_add(mdi->st_buff_cache_hits, "hit_ratio", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
2404
-
2405
- rrdlabels_add(mdi->st_buff_cache_hits->rrdlabels, "mssql_instance", mi->instanceID, RRDLABEL_SRC_AUTO);
2406
- }
2407
-
2408
- rrddim_set_by_pointer(
2409
- mdi->st_buff_cache_hits, mdi->rd_buff_cache_hits, (collected_number)mdi->MSSQLBufferCacheHits.current.Data);
2410
- rrdset_done(mdi->st_buff_cache_hits);
2411
-}
2412
-
2413
-void mssql_buffman_checkpoints_pages_chart(struct mssql_db_instance *mdi, struct mssql_instance *mi)
2414
-{
2415
- if (!mdi->st_buff_checkpoint_pages) {
2416
- char id[RRD_ID_LENGTH_MAX + 1];
2417
- snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_bufman_checkpoint_pages", mi->instanceID);
2418
- netdata_fix_chart_name(id);
2419
- mdi->st_buff_checkpoint_pages = rrdset_create_localhost(
2420
- "mssql",
2421
- id,
2422
- NULL,
2423
- "buffer cache",
2424
- "mssql.instance_bufman_checkpoint_pages",
2425
- "Flushed pages",
2426
- "pages/s",
2427
- PLUGIN_WINDOWS_NAME,
2428
- "PerflibMSSQL",
2429
- PRIO_MSSQL_BUFF_CHECKPOINT_PAGES,
2430
- mi->update_every,
2431
- RRDSET_TYPE_LINE);
2432
-
2433
- mdi->rd_buff_checkpoint_pages =
2434
- rrddim_add(mdi->st_buff_checkpoint_pages, "log", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
2435
-
2436
- rrdlabels_add(mdi->st_buff_checkpoint_pages->rrdlabels, "mssql_instance", mi->instanceID, RRDLABEL_SRC_AUTO);
2437
- }
2438
-
2439
- rrddim_set_by_pointer(
2440
- mdi->st_buff_checkpoint_pages,
2441
- mdi->rd_buff_checkpoint_pages,
2442
- (collected_number)mdi->MSSQLBufferCheckpointPages.current.Data);
2443
- rrdset_done(mdi->st_buff_checkpoint_pages);
2444
-}
2445
-
2446
-void mssql_buffman_page_life_expectancy_chart(struct mssql_db_instance *mdi, struct mssql_instance *mi)
2447
-{
2448
- if (!mdi->st_buff_cache_page_life_expectancy) {
2449
- char id[RRD_ID_LENGTH_MAX + 1];
2450
- snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_bufman_page_life_expectancy", mi->instanceID);
2451
- netdata_fix_chart_name(id);
2452
- mdi->st_buff_cache_page_life_expectancy = rrdset_create_localhost(
2453
- "mssql",
2454
- id,
2455
- NULL,
2456
- "buffer cache",
2457
- "mssql.instance_bufman_page_life_expectancy",
2458
- "Page life expectancy",
2459
- "seconds",
2460
- PLUGIN_WINDOWS_NAME,
2461
- "PerflibMSSQL",
2462
- PRIO_MSSQL_BUFF_PAGE_LIFE_EXPECTANCY,
2463
- mi->update_every,
2464
- RRDSET_TYPE_LINE);
2465
-
2466
- mdi->rd_buff_cache_page_life_expectancy =
2467
- rrddim_add(mdi->st_buff_cache_page_life_expectancy, "life_expectancy", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
2468
-
2469
- rrdlabels_add(
2470
- mdi->st_buff_cache_page_life_expectancy->rrdlabels, "mssql_instance", mi->instanceID, RRDLABEL_SRC_AUTO);
2471
- }
2472
-
2473
- rrddim_set_by_pointer(
2474
- mdi->st_buff_cache_page_life_expectancy,
2475
- mdi->rd_buff_cache_page_life_expectancy,
2476
- (collected_number)mdi->MSSQLBufferPageLifeExpectancy.current.Data);
2477
- rrdset_done(mdi->st_buff_cache_page_life_expectancy);
2478
-}
2479
-
2480
-void mssql_buffman_lazy_write_chart(struct mssql_db_instance *mdi, struct mssql_instance *mi)
2481
-{
2482
- if (!mdi->st_buff_lazy_write) {
2483
- char id[RRD_ID_LENGTH_MAX + 1];
2484
- snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_bufman_lazy_write", mi->instanceID);
2485
- netdata_fix_chart_name(id);
2486
- mdi->st_buff_lazy_write = rrdset_create_localhost(
2487
- "mssql",
2488
- id,
2489
- NULL,
2490
- "buffer cache",
2491
- "mssql.instance_bufman_lazy_write",
2492
- "Buffers written by buffer manager's lazy writer",
2493
- "writes/s",
2494
- PLUGIN_WINDOWS_NAME,
2495
- "PerflibMSSQL",
2496
- PRIO_MSSQL_BUFF_LAZY_WRITE,
2497
- mi->update_every,
2498
- RRDSET_TYPE_LINE);
2499
-
2500
- mdi->rd_buff_lazy_write = rrddim_add(mdi->st_buff_lazy_write, "writes", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
2501
-
2502
- rrdlabels_add(mdi->st_buff_lazy_write->rrdlabels, "mssql_instance", mi->instanceID, RRDLABEL_SRC_AUTO);
2503
- }
2504
-
2505
- rrddim_set_by_pointer(
2506
- mdi->st_buff_lazy_write, mdi->rd_buff_lazy_write, (collected_number)mdi->MSSQLBufferLazyWrite.current.Data);
2507
- rrdset_done(mdi->st_buff_lazy_write);
2508
-}
2509
-
2510
-void mssql_buffman_page_lookups_chart(struct mssql_db_instance *mdi, struct mssql_instance *mi)
2511
-{
2512
- if (!mdi->st_buff_page_lookups) {
2513
- char id[RRD_ID_LENGTH_MAX + 1];
2514
- snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_bufman_page_lookups", mi->instanceID);
2515
- netdata_fix_chart_name(id);
2516
- mdi->st_buff_page_lookups = rrdset_create_localhost(
2517
- "mssql",
2518
- id,
2519
- NULL,
2520
- "buffer cache",
2521
- "mssql.instance_bufman_page_lookups",
2522
- "Requests to find a page in the buffer pool.",
2523
- "lookups/s",
2524
- PLUGIN_WINDOWS_NAME,
2525
- "PerflibMSSQL",
2526
- PRIO_MSSQL_BUFF_PAGE_LOOKUPS,
2527
- mi->update_every,
2528
- RRDSET_TYPE_LINE);
2529
-
2530
- mdi->rd_buff_page_lookups =
2531
- rrddim_add(mdi->st_buff_page_lookups, "lookups", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
2532
-
2533
- rrdlabels_add(mdi->st_buff_page_lookups->rrdlabels, "mssql_instance", mi->instanceID, RRDLABEL_SRC_AUTO);
2534
- }
2535
-
2536
- rrddim_set_by_pointer(
2537
- mdi->st_buff_page_lookups,
2538
- mdi->rd_buff_page_lookups,
2539
- (collected_number)mdi->MSSQLBufferPageLookups.current.Data);
2540
- rrdset_done(mdi->st_buff_page_lookups);
2541
-}
2542
-
2543
-static void netdata_mssql_compilations(struct mssql_db_instance *mdi, struct mssql_instance *mi)
2544
-{
2545
- if (!mdi->st_stats_compilation) {
2546
- char id[RRD_ID_LENGTH_MAX + 1];
2547
- snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_sqlstats_sql_compilations", mi->instanceID);
2548
- netdata_fix_chart_name(id);
2549
- mdi->st_stats_compilation = rrdset_create_localhost(
2550
- "mssql",
2551
- id,
2552
- NULL,
2553
- "sql activity",
2554
- "mssql.instance_sqlstats_sql_compilations",
2555
- "SQL compilations",
2556
- "compilations/s",
2557
- PLUGIN_WINDOWS_NAME,
2558
- "PerflibMSSQL",
2559
- PRIO_MSSQL_STATS_COMPILATIONS,
2560
- mi->update_every,
2561
- RRDSET_TYPE_LINE);
2562
-
2563
- mdi->rd_stats_compilation =
2564
- rrddim_add(mdi->st_stats_compilation, "compilations", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
2565
-
2566
- rrdlabels_add(mdi->st_stats_compilation->rrdlabels, "mssql_instance", mi->instanceID, RRDLABEL_SRC_AUTO);
2567
- }
2568
-
2569
- rrddim_set_by_pointer(
2570
- mdi->st_stats_compilation, mdi->rd_stats_compilation, (collected_number)mdi->MSSQLCompilations.current.Data);
2571
- rrdset_done(mdi->st_stats_compilation);
2572
-}
2573
-
2574
-static void netdata_mssql_recompilations(struct mssql_db_instance *mdi, struct mssql_instance *mi)
2575
-{
2576
- if (!mdi->st_stats_recompiles) {
2577
- char id[RRD_ID_LENGTH_MAX + 1];
2578
- snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_sqlstats_sql_recompilations", mi->instanceID);
2579
- netdata_fix_chart_name(id);
2580
- mdi->st_stats_recompiles = rrdset_create_localhost(
2581
- "mssql",
2582
- id,
2583
- NULL,
2584
- "sql activity",
2585
- "mssql.instance_sqlstats_sql_recompilations",
2586
- "SQL re-compilations",
2587
- "recompiles/s",
2588
- PLUGIN_WINDOWS_NAME,
2589
- "PerflibMSSQL",
2590
- PRIO_MSSQL_STATS_RECOMPILATIONS,
2591
- mi->update_every,
2592
- RRDSET_TYPE_LINE);
2593
-
2594
- mdi->rd_stats_recompiles =
2595
- rrddim_add(mdi->st_stats_recompiles, "recompiles", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
2596
-
2597
- rrdlabels_add(mdi->st_stats_recompiles->rrdlabels, "mssql_instance", mi->instanceID, RRDLABEL_SRC_AUTO);
2598
- }
2599
-
2600
- rrddim_set_by_pointer(
2601
- mdi->st_stats_recompiles, mdi->rd_stats_recompiles, (collected_number)mdi->MSSQLRecompilations.current.Data);
2602
- rrdset_done(mdi->st_stats_recompiles);
2603
-}
2604
-
2605
-int dict_mssql_buffman_stats_charts_cb(
2606
- const DICTIONARY_ITEM *item __maybe_unused,
2607
- void *value,
2608
- void *data __maybe_unused)
2609
-{
2610
- struct mssql_db_instance *mdi = value;
2611
- struct mssql_instance *mi = data;
2612
-
2613
- if (unlikely(!mdi->collect_instance))
2614
- return 1;
2615
-
2616
- mssql_buffman_iops_chart(mdi, mi);
2617
- mssql_buffman_cache_hit_ratio_chart(mdi, mi);
2618
- mssql_buffman_checkpoints_pages_chart(mdi, mi);
2619
- mssql_buffman_page_life_expectancy_chart(mdi, mi);
2620
- mssql_buffman_lazy_write_chart(mdi, mi);
2621
- mssql_buffman_page_lookups_chart(mdi, mi);
2622
-
2623
- netdata_mssql_compilations(mdi, mi);
2624
- netdata_mssql_recompilations(mdi, mi);
2625
-
2626
- return 1;
2627
-}
2628
-
2629
-static void do_mssql_bufferman_stats_sql(PERF_DATA_BLOCK *pDataBlock, struct mssql_instance *mi, int update_every)
2630
-{
2631
- dictionary_sorted_walkthrough_read(mi->databases, dict_mssql_buffman_stats_charts_cb, mi);
2632
-}
2633
-
2634
-static void netdata_mssql_jobs_status(struct mssql_db_jobs *mdj, struct mssql_instance *mi, const char *job)
2635
-{
2636
- if (!mdj->st_status) {
2637
- char id[RRD_ID_LENGTH_MAX + 1];
2638
- snprintfz(id, RRD_ID_LENGTH_MAX, "job_%s_instance_%s_status", job, mi->instanceID);
2639
- netdata_fix_chart_name(id);
2640
- mdj->st_status = rrdset_create_localhost(
2641
- "mssql",
2642
- id,
2643
- NULL,
2644
- "jobs",
2645
- "mssql.instance_jobs_status",
2646
- "Jobs running",
2647
- "status",
2648
- PLUGIN_WINDOWS_NAME,
2649
- "PerflibMSSQL",
2650
- PRIO_MSSQL_DATABASE_JOBS_STATUS,
2651
- mi->update_every,
2652
- RRDSET_TYPE_LINE);
2653
-
2654
- mdj->rd_status_enabled = rrddim_add(mdj->st_status, "enabled", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
2655
-
2656
- mdj->rd_status_disabled = rrddim_add(mdj->st_status, "disabled", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
2657
-
2658
- rrdlabels_add(mdj->st_status->rrdlabels, "mssql_instance", mi->instanceID, RRDLABEL_SRC_AUTO);
2659
- rrdlabels_add(mdj->st_status->rrdlabels, "job_name", job, RRDLABEL_SRC_AUTO);
2660
- }
2661
-
2662
- rrddim_set_by_pointer(
2663
- mdj->st_status, mdj->rd_status_enabled, (collected_number)(mdj->MSSQLJOBState.current.Data == 1));
2664
- rrddim_set_by_pointer(
2665
- mdj->st_status, mdj->rd_status_disabled, (collected_number)(mdj->MSSQLJOBState.current.Data == 0));
2666
- rrdset_done(mdj->st_status);
2667
-}
2668
-
2669
-int dict_mssql_sysjobs_chart_cb(const DICTIONARY_ITEM *item __maybe_unused, void *value, void *data __maybe_unused)
2670
-{
2671
- const char *job = dictionary_acquired_item_name((DICTIONARY_ITEM *)item);
2672
- struct mssql_db_jobs *mdj = value;
2673
- struct mssql_instance *mi = data;
2674
-
2675
- netdata_mssql_jobs_status(mdj, mi, job);
2676
-}
2677
-
2678
-static void do_mssql_job_status_sql(PERF_DATA_BLOCK *pDataBlock, struct mssql_instance *mi, int update_every)
2679
-{
2680
- dictionary_sorted_walkthrough_read(mi->sysjobs, dict_mssql_sysjobs_chart_cb, mi);
2681
-}
2682
-
2683
-void dict_mssql_replication_status(struct mssql_publisher_publication *mpp, int update_every)
2684
-{
2685
- if (!mpp->st_publisher_status) {
2686
- char id[RRD_ID_LENGTH_MAX + 1];
2687
-
2688
- snprintfz(
2689
- id,
2690
- RRD_ID_LENGTH_MAX,
2691
- "instance_%s_replication_%s_%s_status",
2692
- mpp->parent->instanceID,
2693
- mpp->publication,
2694
- mpp->db);
2695
- netdata_fix_chart_name(id);
2696
- mpp->st_publisher_status = rrdset_create_localhost(
2697
- "mssql",
2698
- id,
2699
- NULL,
2700
- "replication",
2701
- "mssql.replication_status",
2702
- "Current replication status",
2703
- "status",
2704
- PLUGIN_WINDOWS_NAME,
2705
- "PerflibMSSQL",
2706
- PRIO_MSSQL_REPLICATION_STATUS,
2707
- update_every,
2708
- RRDSET_TYPE_LINE);
2709
-
2710
- rrdlabels_add(
2711
- mpp->st_publisher_status->rrdlabels, "mssql_instance", mpp->parent->instanceID, RRDLABEL_SRC_AUTO);
2712
- rrdlabels_add(mpp->st_publisher_status->rrdlabels, "publisher", mpp->publisher, RRDLABEL_SRC_AUTO);
2713
- rrdlabels_add(mpp->st_publisher_status->rrdlabels, "database", mpp->db, RRDLABEL_SRC_AUTO);
2714
- rrdlabels_add(mpp->st_publisher_status->rrdlabels, "publication", mpp->publication, RRDLABEL_SRC_AUTO);
2715
-
2716
- mpp->rd_publisher_status_started =
2717
- rrddim_add(mpp->st_publisher_status, "started", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
2718
- mpp->rd_publisher_status_successed =
2719
- rrddim_add(mpp->st_publisher_status, "succeeded", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
2720
- mpp->rd_publisher_status_in_progress =
2721
- rrddim_add(mpp->st_publisher_status, "in_progress", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
2722
- mpp->rd_publisher_status_idle =
2723
- rrddim_add(mpp->st_publisher_status, "idle", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
2724
- mpp->rd_publisher_status_retrying =
2725
- rrddim_add(mpp->st_publisher_status, "retrying", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
2726
- mpp->rd_publisher_status_failed =
2727
- rrddim_add(mpp->st_publisher_status, "failed", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
2728
- }
2729
-
2730
- int status = mpp->status;
2731
- rrddim_set_by_pointer(mpp->st_publisher_status, mpp->rd_publisher_status_started, (collected_number)(status == 1));
2732
- rrddim_set_by_pointer(
2733
- mpp->st_publisher_status, mpp->rd_publisher_status_successed, (collected_number)(status == 2));
2734
- rrddim_set_by_pointer(
2735
- mpp->st_publisher_status, mpp->rd_publisher_status_in_progress, (collected_number)(status == 3));
2736
- rrddim_set_by_pointer(mpp->st_publisher_status, mpp->rd_publisher_status_idle, (collected_number)(status == 4));
2737
- rrddim_set_by_pointer(mpp->st_publisher_status, mpp->rd_publisher_status_retrying, (collected_number)(status == 5));
2738
- rrddim_set_by_pointer(mpp->st_publisher_status, mpp->rd_publisher_status_failed, (collected_number)(status == 6));
2739
- rrdset_done(mpp->st_publisher_status);
2740
-}
2741
-
2742
-void dict_mssql_replication_warning(struct mssql_publisher_publication *mpp, int update_every)
2743
-{
2744
- if (!mpp->st_warning) {
2745
- char id[RRD_ID_LENGTH_MAX + 1];
2746
-
2747
- snprintfz(
2748
- id,
2749
- RRD_ID_LENGTH_MAX,
2750
- "instance_%s_replication_%s_%s_warning",
2751
- mpp->parent->instanceID,
2752
- mpp->publication,
2753
- mpp->db);
2754
- netdata_fix_chart_name(id);
2755
- mpp->st_warning = rrdset_create_localhost(
2756
- "mssql",
2757
- id,
2758
- NULL,
2759
- "replication",
2760
- "mssql.replication_warning",
2761
- "Maximum threshold warning.",
2762
- "status",
2763
- PLUGIN_WINDOWS_NAME,
2764
- "PerflibMSSQL",
2765
- PRIO_MSSQL_REPLICATION_WARNING,
2766
- update_every,
2767
- RRDSET_TYPE_LINE);
2768
-
2769
- rrdlabels_add(mpp->st_warning->rrdlabels, "mssql_instance", mpp->parent->instanceID, RRDLABEL_SRC_AUTO);
2770
- rrdlabels_add(mpp->st_warning->rrdlabels, "publisher", mpp->publisher, RRDLABEL_SRC_AUTO);
2771
- rrdlabels_add(mpp->st_warning->rrdlabels, "database", mpp->db, RRDLABEL_SRC_AUTO);
2772
- rrdlabels_add(mpp->st_warning->rrdlabels, "publication", mpp->publication, RRDLABEL_SRC_AUTO);
2773
-
2774
- mpp->rd_warning_expiration = rrddim_add(mpp->st_warning, "expiration", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
2775
- mpp->rd_warning_latency = rrddim_add(mpp->st_warning, "latency", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
2776
- mpp->rd_warning_mergeeexpiration =
2777
- rrddim_add(mpp->st_warning, "merge expiration", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
2778
- mpp->rd_warning_mergefastduration =
2779
- rrddim_add(mpp->st_warning, "fast duration", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
2780
- mpp->rd_warning_mergelowduration =
2781
- rrddim_add(mpp->st_warning, "low duration", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
2782
- mpp->rd_warning_mergefastrunspeed =
2783
- rrddim_add(mpp->st_warning, "fast run speed", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
2784
- mpp->rd_warning_mergelowrunspeed =
2785
- rrddim_add(mpp->st_warning, "low run speed", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
2786
- }
2787
-
2788
- int warning = mpp->warning;
2789
- rrddim_set_by_pointer(
2790
- mpp->st_warning, mpp->rd_warning_expiration, (collected_number)(warning & MSSQL_REPLICATON_EXPIRATION));
2791
- rrddim_set_by_pointer(
2792
- mpp->st_warning, mpp->rd_warning_latency, (collected_number)(warning & MSSQL_REPLICATON_LATENCY));
2793
- rrddim_set_by_pointer(
2794
- mpp->st_warning,
2795
- mpp->rd_warning_mergeeexpiration,
2796
- (collected_number)(warning & MSSQL_REPLICATON_MERGEEXPIRATION));
2797
- rrddim_set_by_pointer(
2798
- mpp->st_warning,
2799
- mpp->rd_warning_mergefastduration,
2800
- (collected_number)(warning & MSSQL_REPLICATON_MERGEFASTDURATION));
2801
- rrddim_set_by_pointer(
2802
- mpp->st_warning,
2803
- mpp->rd_warning_mergelowduration,
2804
- (collected_number)(warning & MSSQL_REPLICATON_MERGELOWDURATION));
2805
- rrddim_set_by_pointer(
2806
- mpp->st_warning,
2807
- mpp->rd_warning_mergefastrunspeed,
2808
- (collected_number)(warning & MSSQL_REPLICATON_MERGEFASTRUNSPEED));
2809
- rrddim_set_by_pointer(
2810
- mpp->st_warning,
2811
- mpp->rd_warning_mergelowrunspeed,
2812
- (collected_number)(warning & MSSQL_REPLICATON_MERGELOWRUNSPEED));
2813
- rrdset_done(mpp->st_warning);
2814
-}
2815
-
2816
-void dict_mssql_replication_avg_latency(struct mssql_publisher_publication *mpp, int update_every)
2817
-{
2818
- if (!mpp->st_avg_latency) {
2819
- char id[RRD_ID_LENGTH_MAX + 1];
2820
-
2821
- snprintfz(
2822
- id,
2823
- RRD_ID_LENGTH_MAX,
2824
- "instance_%s_replication_%s_%s_avg_latency",
2825
- mpp->parent->instanceID,
2826
- mpp->publication,
2827
- mpp->db);
2828
- netdata_fix_chart_name(id);
2829
- mpp->st_avg_latency = rrdset_create_localhost(
2830
- "mssql",
2831
- id,
2832
- NULL,
2833
- "replication",
2834
- "mssql.replication_avg_latency",
2835
- "Average latency for a transactional publication.",
2836
- "seconds",
2837
- PLUGIN_WINDOWS_NAME,
2838
- "PerflibMSSQL",
2839
- PRIO_MSSQL_REPLICATION_AVG_LATENCY,
2840
- update_every,
2841
- RRDSET_TYPE_LINE);
2842
-
2843
- rrdlabels_add(mpp->st_avg_latency->rrdlabels, "mssql_instance", mpp->parent->instanceID, RRDLABEL_SRC_AUTO);
2844
- rrdlabels_add(mpp->st_avg_latency->rrdlabels, "publisher", mpp->publisher, RRDLABEL_SRC_AUTO);
2845
- rrdlabels_add(mpp->st_avg_latency->rrdlabels, "database", mpp->db, RRDLABEL_SRC_AUTO);
2846
- rrdlabels_add(mpp->st_avg_latency->rrdlabels, "publication", mpp->publication, RRDLABEL_SRC_AUTO);
2847
-
2848
- mpp->rd_avg_latency = rrddim_add(mpp->st_avg_latency, "latency", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
2849
- }
2850
-
2851
- rrddim_set_by_pointer(mpp->st_avg_latency, mpp->rd_avg_latency, (collected_number)mpp->avg_latency);
2852
- rrdset_done(mpp->st_avg_latency);
2853
-}
2854
-
2855
-void dict_mssql_replication_subscription(struct mssql_publisher_publication *mpp, int update_every)
2856
-{
2857
- if (!mpp->st_subscription_count) {
2858
- char id[RRD_ID_LENGTH_MAX + 1];
2859
-
2860
- snprintfz(
2861
- id,
2862
- RRD_ID_LENGTH_MAX,
2863
- "instance_%s_replication_%s_%s_subscription",
2864
- mpp->parent->instanceID,
2865
- mpp->publication,
2866
- mpp->db);
2867
- netdata_fix_chart_name(id);
2868
- mpp->st_subscription_count = rrdset_create_localhost(
2869
- "mssql",
2870
- id,
2871
- NULL,
2872
- "replication",
2873
- "mssql.replication_subscription",
2874
- "Number of subscriptions to a publication.",
2875
- "subscription",
2876
- PLUGIN_WINDOWS_NAME,
2877
- "PerflibMSSQL",
2878
- PRIO_MSSQL_REPLICATION_SUBSCRIPTION_COUNT,
2879
- update_every,
2880
- RRDSET_TYPE_LINE);
2881
-
2882
- rrdlabels_add(
2883
- mpp->st_subscription_count->rrdlabels, "mssql_instance", mpp->parent->instanceID, RRDLABEL_SRC_AUTO);
2884
- rrdlabels_add(mpp->st_subscription_count->rrdlabels, "publisher", mpp->publisher, RRDLABEL_SRC_AUTO);
2885
- rrdlabels_add(mpp->st_subscription_count->rrdlabels, "database", mpp->db, RRDLABEL_SRC_AUTO);
2886
- rrdlabels_add(mpp->st_subscription_count->rrdlabels, "publication", mpp->publication, RRDLABEL_SRC_AUTO);
2887
-
2888
- mpp->rd_subscription_count =
2889
- rrddim_add(mpp->st_subscription_count, "subscription", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
2890
- }
2891
-
2892
- rrddim_set_by_pointer(
2893
- mpp->st_subscription_count, mpp->rd_subscription_count, (collected_number)mpp->subscriptioncount);
2894
- rrdset_done(mpp->st_subscription_count);
2895
-}
2896
-
2897
-void dict_mssql_replication_dist_agent_running(struct mssql_publisher_publication *mpp, int update_every)
2898
-{
2899
- if (!mpp->st_running_agent) {
2900
- char id[RRD_ID_LENGTH_MAX + 1];
2901
-
2902
- snprintfz(
2903
- id,
2904
- RRD_ID_LENGTH_MAX,
2905
- "instance_%s_replication_%s_%s_agent_running",
2906
- mpp->parent->instanceID,
2907
- mpp->publication,
2908
- mpp->db);
2909
- netdata_fix_chart_name(id);
2910
- mpp->st_running_agent = rrdset_create_localhost(
2911
- "mssql",
2912
- id,
2913
- NULL,
2914
- "replication",
2915
- "mssql.replication_agent_running",
2916
- "Distribution agents running.",
2917
- "agents",
2918
- PLUGIN_WINDOWS_NAME,
2919
- "PerflibMSSQL",
2920
- PRIO_MSSQL_REPLICATION_AGENT_RUNNING,
2921
- update_every,
2922
- RRDSET_TYPE_LINE);
2923
-
2924
- rrdlabels_add(mpp->st_running_agent->rrdlabels, "mssql_instance", mpp->parent->instanceID, RRDLABEL_SRC_AUTO);
2925
- rrdlabels_add(mpp->st_running_agent->rrdlabels, "publisher", mpp->publisher, RRDLABEL_SRC_AUTO);
2926
- rrdlabels_add(mpp->st_running_agent->rrdlabels, "database", mpp->db, RRDLABEL_SRC_AUTO);
2927
- rrdlabels_add(mpp->st_running_agent->rrdlabels, "publication", mpp->publication, RRDLABEL_SRC_AUTO);
2928
-
2929
- mpp->rd_running_agent = rrddim_add(mpp->st_running_agent, "agents", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
2930
- }
2931
-
2932
- rrddim_set_by_pointer(mpp->st_running_agent, mpp->rd_running_agent, (collected_number)mpp->runningdistagentcount);
2933
- rrdset_done(mpp->st_running_agent);
2934
-}
2935
-
2936
-void dict_mssql_replication_sync_time(struct mssql_publisher_publication *mpp, int update_every)
2937
-{
2938
- if (!mpp->st_synchronization_time) {
2939
- char id[RRD_ID_LENGTH_MAX + 1];
2940
-
2941
- snprintfz(
2942
- id,
2943
- RRD_ID_LENGTH_MAX,
2944
- "instance_%s_replication_%s_%s_synchronization",
2945
- mpp->parent->instanceID,
2946
- mpp->publication,
2947
- mpp->db);
2948
- netdata_fix_chart_name(id);
2949
- mpp->st_synchronization_time = rrdset_create_localhost(
2950
- "mssql",
2951
- id,
2952
- NULL,
2953
- "replication",
2954
- "mssql.replication_synchronization",
2955
- "The shortest synchronization.",
2956
- "seconds",
2957
- PLUGIN_WINDOWS_NAME,
2958
- "PerflibMSSQL",
2959
- PRIO_MSSQL_REPLICATION_SYNC_TIME,
2960
- update_every,
2961
- RRDSET_TYPE_LINE);
2962
-
2963
- rrdlabels_add(
2964
- mpp->st_synchronization_time->rrdlabels, "mssql_instance", mpp->parent->instanceID, RRDLABEL_SRC_AUTO);
2965
- rrdlabels_add(mpp->st_synchronization_time->rrdlabels, "publisher", mpp->publisher, RRDLABEL_SRC_AUTO);
2966
- rrdlabels_add(mpp->st_synchronization_time->rrdlabels, "database", mpp->db, RRDLABEL_SRC_AUTO);
2967
- rrdlabels_add(mpp->st_synchronization_time->rrdlabels, "publication", mpp->publication, RRDLABEL_SRC_AUTO);
2968
-
2969
- mpp->rd_synchronization_time =
2970
- rrddim_add(mpp->st_synchronization_time, "seconds", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
2971
- }
2972
-
2973
- rrddim_set_by_pointer(
2974
- mpp->st_synchronization_time, mpp->rd_synchronization_time, (collected_number)mpp->runningdistagentcount);
2975
- rrdset_done(mpp->st_synchronization_time);
2976
-}
2977
-
2978
-int dict_mssql_replication_chart_cb(const DICTIONARY_ITEM *item __maybe_unused, void *value, void *data __maybe_unused)
2979
-{
2980
- struct mssql_publisher_publication *mpp = value;
2981
- int *update_every = data;
2982
-
2983
- dict_mssql_replication_status(mpp, *update_every);
2984
- dict_mssql_replication_warning(mpp, *update_every);
2985
- dict_mssql_replication_avg_latency(mpp, *update_every);
2986
- dict_mssql_replication_subscription(mpp, *update_every);
2987
- dict_mssql_replication_dist_agent_running(mpp, *update_every);
2988
- dict_mssql_replication_sync_time(mpp, *update_every);
2989
-}
2990
-
2991
-static void do_mssql_replication(struct mssql_instance *mi, int update_every)
2992
-{
2993
- dictionary_sorted_walkthrough_read(mi->publisher_publication, dict_mssql_replication_chart_cb, &update_every);
2994
-}
2995
-
2996
-static void mssql_database_backup_restore_chart(struct mssql_db_instance *mdi, const char *db, int update_every)
2997
-{
2998
- char id[RRD_ID_LENGTH_MAX + 1];
2999
-
3000
- if (!mdi->st_db_backup_restore_operations) {
3001
- snprintfz(id, RRD_ID_LENGTH_MAX, "db_%s_instance_%s_backup_restore_operations", db, mdi->parent->instanceID);
3002
- netdata_fix_chart_name(id);
3003
- mdi->st_db_backup_restore_operations = rrdset_create_localhost(
3004
- "mssql",
3005
- id,
3006
- NULL,
3007
- "transactions",
3008
- "mssql.database_backup_restore_operations",
3009
- "Backup IO per database",
3010
- "operations/s",
3011
- PLUGIN_WINDOWS_NAME,
3012
- "PerflibMSSQL",
3013
- PRIO_MSSQL_DATABASE_BACKUP_RESTORE_OPERATIONS,
3014
- update_every,
3015
- RRDSET_TYPE_LINE);
3016
-
3017
- rrdlabels_add(
3018
- mdi->st_db_backup_restore_operations->rrdlabels,
3019
- "mssql_instance",
3020
- mdi->parent->instanceID,
3021
- RRDLABEL_SRC_AUTO);
3022
- rrdlabels_add(mdi->st_db_backup_restore_operations->rrdlabels, "database", db, RRDLABEL_SRC_AUTO);
3023
-
3024
- mdi->rd_db_backup_restore_operations =
3025
- rrddim_add(mdi->st_db_backup_restore_operations, "backup", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
3026
- }
3027
-
3028
- rrddim_set_by_pointer(
3029
- mdi->st_db_backup_restore_operations,
3030
- mdi->rd_db_backup_restore_operations,
3031
- (collected_number)mdi->MSSQLDatabaseBackupRestoreOperations.current.Data);
3032
-
3033
- rrdset_done(mdi->st_db_backup_restore_operations);
3034
-}
3035
-
3036
-static void mssql_database_log_flushes_chart(struct mssql_db_instance *mdi, const char *db, int update_every)
3037
-{
3038
- char id[RRD_ID_LENGTH_MAX + 1];
3039
-
3040
- if (!mdi->st_db_log_flushes) {
3041
- snprintfz(id, RRD_ID_LENGTH_MAX, "db_%s_instance_%s_log_flushes", db, mdi->parent->instanceID);
3042
- netdata_fix_chart_name(id);
3043
- mdi->st_db_log_flushes = rrdset_create_localhost(
3044
- "mssql",
3045
- id,
3046
- NULL,
3047
- "transactions",
3048
- "mssql.database_log_flushes",
3049
- "Log flushes",
3050
- "flushes/s",
3051
- PLUGIN_WINDOWS_NAME,
3052
- "PerflibMSSQL",
3053
- PRIO_MSSQL_DATABASE_LOG_FLUSHES,
3054
- update_every,
3055
- RRDSET_TYPE_LINE);
3056
-
3057
- rrdlabels_add(mdi->st_db_log_flushes->rrdlabels, "mssql_instance", mdi->parent->instanceID, RRDLABEL_SRC_AUTO);
3058
- rrdlabels_add(mdi->st_db_log_flushes->rrdlabels, "database", db, RRDLABEL_SRC_AUTO);
3059
- }
3060
-
3061
- if (!mdi->rd_db_log_flushes) {
3062
- mdi->rd_db_log_flushes = rrddim_add(mdi->st_db_log_flushes, "flushes", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
3063
- }
3064
-
3065
- rrddim_set_by_pointer(
3066
- mdi->st_db_log_flushes, mdi->rd_db_log_flushes, (collected_number)mdi->MSSQLDatabaseLogFlushes.current.Data);
3067
-
3068
- rrdset_done(mdi->st_db_log_flushes);
3069
-}
3070
-
3071
-static void mssql_database_log_flushed_chart(struct mssql_db_instance *mdi, const char *db, int update_every)
3072
-{
3073
- char id[RRD_ID_LENGTH_MAX + 1];
3074
-
3075
- if (!mdi->st_db_log_flushed) {
3076
- snprintfz(id, RRD_ID_LENGTH_MAX, "db_%s_instance_%s_log_flushed", db, mdi->parent->instanceID);
3077
- netdata_fix_chart_name(id);
3078
- mdi->st_db_log_flushed = rrdset_create_localhost(
3079
- "mssql",
3080
- id,
3081
- NULL,
3082
- "transactions",
3083
- "mssql.database_log_flushed",
3084
- "Log flushed",
3085
- "bytes/s",
3086
- PLUGIN_WINDOWS_NAME,
3087
- "PerflibMSSQL",
3088
- PRIO_MSSQL_DATABASE_LOG_FLUSHED,
3089
- update_every,
3090
- RRDSET_TYPE_LINE);
3091
-
3092
- rrdlabels_add(mdi->st_db_log_flushed->rrdlabels, "mssql_instance", mdi->parent->instanceID, RRDLABEL_SRC_AUTO);
3093
- rrdlabels_add(mdi->st_db_log_flushed->rrdlabels, "database", db, RRDLABEL_SRC_AUTO);
3094
-
3095
- mdi->rd_db_log_flushed = rrddim_add(mdi->st_db_log_flushed, "flushed", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
3096
- }
3097
-
3098
- rrddim_set_by_pointer(
3099
- mdi->st_db_log_flushed, mdi->rd_db_log_flushed, (collected_number)mdi->MSSQLDatabaseLogFlushed.current.Data);
3100
-
3101
- rrdset_done(mdi->st_db_log_flushed);
3102
-}
3103
-
3104
-static void mssql_transactions_chart(struct mssql_db_instance *mdi, const char *db, int update_every)
3105
-{
3106
- char id[RRD_ID_LENGTH_MAX + 1];
3107
-
3108
- if (!mdi->st_db_transactions) {
3109
- snprintfz(id, RRD_ID_LENGTH_MAX, "db_%s_instance_%s_transactions", db, mdi->parent->instanceID);
3110
- netdata_fix_chart_name(id);
3111
- mdi->st_db_transactions = rrdset_create_localhost(
3112
- "mssql",
3113
- id,
3114
- NULL,
3115
- "transactions",
3116
- "mssql.database_transactions",
3117
- "Transactions",
3118
- "transactions/s",
3119
- PLUGIN_WINDOWS_NAME,
3120
- "PerflibMSSQL",
3121
- PRIO_MSSQL_DATABASE_TRANSACTIONS,
3122
- update_every,
3123
- RRDSET_TYPE_LINE);
3124
-
3125
- rrdlabels_add(mdi->st_db_transactions->rrdlabels, "mssql_instance", mdi->parent->instanceID, RRDLABEL_SRC_AUTO);
3126
- rrdlabels_add(mdi->st_db_transactions->rrdlabels, "database", db, RRDLABEL_SRC_AUTO);
3127
-
3128
- mdi->rd_db_transactions =
3129
- rrddim_add(mdi->st_db_transactions, "transactions", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
3130
- }
3131
-
3132
- rrddim_set_by_pointer(
3133
- mdi->st_db_transactions,
3134
- mdi->rd_db_transactions,
3135
- (collected_number)mdi->MSSQLDatabaseTransactions.current.Data);
3136
-
3137
- rrdset_done(mdi->st_db_transactions);
3138
-}
3139
-
3140
-static void mssql_write_transactions_chart(struct mssql_db_instance *mdi, const char *db, int update_every)
3141
-{
3142
- char id[RRD_ID_LENGTH_MAX + 1];
3143
-
3144
- if (!mdi->st_db_write_transactions) {
3145
- snprintfz(id, RRD_ID_LENGTH_MAX, "db_%s_instance_%s_write_transactions", db, mdi->parent->instanceID);
3146
- netdata_fix_chart_name(id);
3147
- mdi->st_db_write_transactions = rrdset_create_localhost(
3148
- "mssql",
3149
- id,
3150
- NULL,
3151
- "transactions",
3152
- "mssql.database_write_transactions",
3153
- "Write transactions",
3154
- "transactions/s",
3155
- PLUGIN_WINDOWS_NAME,
3156
- "PerflibMSSQL",
3157
- PRIO_MSSQL_DATABASE_WRITE_TRANSACTIONS,
3158
- update_every,
3159
- RRDSET_TYPE_LINE);
3160
-
3161
- rrdlabels_add(
3162
- mdi->st_db_write_transactions->rrdlabels, "mssql_instance", mdi->parent->instanceID, RRDLABEL_SRC_AUTO);
3163
- rrdlabels_add(mdi->st_db_write_transactions->rrdlabels, "database", db, RRDLABEL_SRC_AUTO);
3164
-
3165
- mdi->rd_db_write_transactions =
3166
- rrddim_add(mdi->st_db_write_transactions, "write", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
3167
- }
3168
-
3169
- rrddim_set_by_pointer(
3170
- mdi->st_db_write_transactions,
3171
- mdi->rd_db_write_transactions,
3172
- (collected_number)mdi->MSSQLDatabaseWriteTransactions.current.Data);
3173
-
3174
- rrdset_done(mdi->st_db_write_transactions);
3175
-}
3176
-
3177
-static void mssql_lockwait_chart(struct mssql_db_instance *mdi, const char *db, int update_every)
3178
-{
3179
- char id[RRD_ID_LENGTH_MAX + 1];
3180
-
3181
- if (!mdi->st_db_lockwait) {
3182
- snprintfz(id, RRD_ID_LENGTH_MAX, "db_%s_instance_%s_lockwait", db, mdi->parent->instanceID);
3183
- netdata_fix_chart_name(id);
3184
- mdi->st_db_lockwait = rrdset_create_localhost(
3185
- "mssql",
3186
- id,
3187
- NULL,
3188
- "locks",
3189
- "mssql.database_lockwait",
3190
- "Lock requests that required the caller to wait.",
3191
- "locks/s",
3192
- PLUGIN_WINDOWS_NAME,
3193
- "PerflibMSSQL",
3194
- PRIO_MSSQL_DATABASE_LOCKWAIT_PER_SECOND,
3195
- update_every,
3196
- RRDSET_TYPE_LINE);
3197
-
3198
- rrdlabels_add(mdi->st_db_lockwait->rrdlabels, "mssql_instance", mdi->parent->instanceID, RRDLABEL_SRC_AUTO);
3199
- rrdlabels_add(mdi->st_db_lockwait->rrdlabels, "database", db, RRDLABEL_SRC_AUTO);
3200
-
3201
- mdi->rd_db_lockwait = rrddim_add(mdi->st_db_lockwait, "lock", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
3202
- }
3203
-
3204
- rrddim_set_by_pointer(
3205
- mdi->st_db_lockwait, mdi->rd_db_lockwait, (collected_number)mdi->MSSQLDatabaseLockWaitSec.current.Data);
3206
-
3207
- rrdset_done(mdi->st_db_lockwait);
3208
-}
3209
-
3210
-static void mssql_deadlock_chart(struct mssql_db_instance *mdi, const char *db, int update_every)
3211
-{
3212
- char id[RRD_ID_LENGTH_MAX + 1];
3213
-
3214
- if (!mdi->st_db_deadlock) {
3215
- snprintfz(id, RRD_ID_LENGTH_MAX, "db_%s_instance_%s_deadlocks", db, mdi->parent->instanceID);
3216
- netdata_fix_chart_name(id);
3217
- mdi->st_db_deadlock = rrdset_create_localhost(
3218
- "mssql",
3219
- id,
3220
- NULL,
3221
- "locks",
3222
- "mssql.database_deadlocks",
3223
- "Lock requests that resulted in deadlock.",
3224
- "deadlocks/s",
3225
- PLUGIN_WINDOWS_NAME,
3226
- "PerflibMSSQL",
3227
- PRIO_MSSQL_DATABASE_DEADLOCKS_PER_SECOND,
3228
- update_every,
3229
- RRDSET_TYPE_LINE);
3230
-
3231
- rrdlabels_add(mdi->st_db_deadlock->rrdlabels, "mssql_instance", mdi->parent->instanceID, RRDLABEL_SRC_AUTO);
3232
- rrdlabels_add(mdi->st_db_deadlock->rrdlabels, "database", db, RRDLABEL_SRC_AUTO);
3233
-
3234
- mdi->rd_db_deadlock = rrddim_add(mdi->st_db_deadlock, "deadlocks", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
3235
- }
3236
-
3237
- rrddim_set_by_pointer(
3238
- mdi->st_db_deadlock, mdi->rd_db_deadlock, (collected_number)mdi->MSSQLDatabaseDeadLockSec.current.Data);
3239
-
3240
- rrdset_done(mdi->st_db_deadlock);
3241
-}
3242
-
3243
-static void mssql_is_readonly_chart(struct mssql_db_instance *mdi, const char *db, int update_every)
3244
-{
3245
- if (!mdi->st_db_readonly) {
3246
- char id[RRD_ID_LENGTH_MAX + 1];
3247
- snprintfz(id, RRD_ID_LENGTH_MAX, "db_%s_instance_%s_readonly", db, mdi->parent->instanceID);
3248
- netdata_fix_chart_name(id);
3249
- mdi->st_db_readonly = rrdset_create_localhost(
3250
- "mssql",
3251
- id,
3252
- NULL,
3253
- "locks",
3254
- "mssql.database_readonly",
3255
- "Current database write status.",
3256
- "status",
3257
- PLUGIN_WINDOWS_NAME,
3258
- "PerflibMSSQL",
3259
- PRIO_MSSQL_DATABASE_READONLY,
3260
- update_every,
3261
- RRDSET_TYPE_LINE);
3262
-
3263
- rrdlabels_add(mdi->st_db_readonly->rrdlabels, "mssql_instance", mdi->parent->instanceID, RRDLABEL_SRC_AUTO);
3264
- rrdlabels_add(mdi->st_db_readonly->rrdlabels, "database", db, RRDLABEL_SRC_AUTO);
3265
-
3266
- mdi->rd_db_readonly_yes = rrddim_add(mdi->st_db_readonly, "writable", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
3267
- mdi->rd_db_readonly_no = rrddim_add(mdi->st_db_readonly, "readonly", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
3268
- }
3269
-
3270
- rrddim_set_by_pointer(
3271
- mdi->st_db_readonly, mdi->rd_db_readonly_no, (collected_number)mdi->MSSQLDBIsReadonly.current.Data);
3272
-
3273
- collected_number opposite = (mdi->MSSQLDBIsReadonly.current.Data) ? 0 : 1;
3274
- rrddim_set_by_pointer(mdi->st_db_readonly, mdi->rd_db_readonly_yes, (collected_number)opposite);
3275
-
3276
- rrdset_done(mdi->st_db_readonly);
3277
-}
3278
-
3279
-static void mssql_db_states_chart(struct mssql_db_instance *mdi, const char *db, int update_every)
3280
-{
3281
- if (!mdi->st_db_state) {
3282
- char id[RRD_ID_LENGTH_MAX + 1];
3283
- snprintfz(id, RRD_ID_LENGTH_MAX, "db_%s_instance_%s_state", db, mdi->parent->instanceID);
3284
- netdata_fix_chart_name(id);
3285
- mdi->st_db_state = rrdset_create_localhost(
3286
- "mssql",
3287
- id,
3288
- NULL,
3289
- "locks",
3290
- "mssql.database_state",
3291
- "Current database state.",
3292
- "status",
3293
- PLUGIN_WINDOWS_NAME,
3294
- "PerflibMSSQL",
3295
- PRIO_MSSQL_DATABASE_STATE,
3296
- update_every,
3297
- RRDSET_TYPE_LINE);
3298
-
3299
- rrdlabels_add(mdi->st_db_state->rrdlabels, "mssql_instance", mdi->parent->instanceID, RRDLABEL_SRC_AUTO);
3300
- rrdlabels_add(mdi->st_db_state->rrdlabels, "database", db, RRDLABEL_SRC_AUTO);
3301
-
3302
- mdi->rd_db_state[0] = rrddim_add(mdi->st_db_state, "online", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
3303
- mdi->rd_db_state[1] = rrddim_add(mdi->st_db_state, "restoring", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
3304
- mdi->rd_db_state[2] = rrddim_add(mdi->st_db_state, "recovering", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
3305
- mdi->rd_db_state[3] = rrddim_add(mdi->st_db_state, "recovering_pending", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
3306
- mdi->rd_db_state[4] = rrddim_add(mdi->st_db_state, "suspect", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
3307
- mdi->rd_db_state[5] = rrddim_add(mdi->st_db_state, "offline", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
3308
- }
3309
-}
3310
-
3311
-static void mssql_db_state_chart_loop(struct mssql_db_instance *mdi, const char *db, int update_every)
3312
-{
3313
- collected_number set_value =
3314
- (mdi->MSSQLDBState.current.Data < 5) ? (collected_number)mdi->MSSQLDBState.current.Data : 5;
3315
- mssql_db_states_chart(mdi, db, update_every);
3316
- for (collected_number i; i < NETDATA_DB_STATES; i++) {
3317
- rrddim_set_by_pointer(mdi->st_db_state, mdi->rd_db_state[i], i == set_value);
3318
- }
3319
- rrdset_done(mdi->st_db_state);
3320
-}
3321
-
3322
-static void mssql_lock_request_chart(struct mssql_db_instance *mdi, const char *db, int update_every)
3323
-{
3324
- char id[RRD_ID_LENGTH_MAX + 1];
3325
-
3326
- if (!mdi->st_lock_requests) {
3327
- snprintfz(id, RRD_ID_LENGTH_MAX, "db_%s_instance_%s_lock_requests", db, mdi->parent->instanceID);
3328
- netdata_fix_chart_name(id);
3329
- mdi->st_lock_requests = rrdset_create_localhost(
3330
- "mssql",
3331
- id,
3332
- NULL,
3333
- "locks",
3334
- "mssql.database_lock_requests",
3335
- "Number of new locks and lock conversions requested.",
3336
- "requests/s",
3337
- PLUGIN_WINDOWS_NAME,
3338
- "PerflibMSSQL",
3339
- PRIO_MSSQL_DATABASE_LOCK_REQUESTS_SEC,
3340
- update_every,
3341
- RRDSET_TYPE_LINE);
3342
-
3343
- rrdlabels_add(mdi->st_lock_requests->rrdlabels, "mssql_instance", mdi->parent->instanceID, RRDLABEL_SRC_AUTO);
3344
- rrdlabels_add(mdi->st_lock_requests->rrdlabels, "database", db, RRDLABEL_SRC_AUTO);
3345
-
3346
- mdi->rd_lock_requests = rrddim_add(mdi->st_lock_requests, "requests", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
3347
- }
3348
-
3349
- rrddim_set_by_pointer(
3350
- mdi->st_lock_requests, mdi->rd_lock_requests, (collected_number)mdi->MSSQLDatabaseLockRequestsSec.current.Data);
3351
-
3352
- rrdset_done(mdi->st_lock_requests);
3353
-}
3354
-
3355
-static void mssql_lock_timeout_chart(struct mssql_db_instance *mdi, const char *db, int update_every)
8
+void do_mssql_access_methods(PERF_DATA_BLOCK *pDataBlock, struct mssql_instance *mi, int update_every)
9
{
10
char id[RRD_ID_LENGTH_MAX + 1];
11
3359
- if (!mdi->st_lock_timeouts) {
3360
- snprintfz(id, RRD_ID_LENGTH_MAX, "db_%s_instance_%s_lock_timeouts", db, mdi->parent->instanceID);
3361
- netdata_fix_chart_name(id);
3362
- mdi->st_lock_timeouts = rrdset_create_localhost(
3363
- "mssql",
3364
- id,
3365
- NULL,
3366
- "locks",
3367
- "mssql.database_lock_timeouts",
3368
- "Lock that timed out.",
3369
- "timeouts/s",
3370
- PLUGIN_WINDOWS_NAME,
3371
- "PerflibMSSQL",
3372
- PRIO_MSSQL_DATABASE_LOCKS_TIMEOUT_PER_SECOND,
3373
- update_every,
3374
- RRDSET_TYPE_LINE);
3375
-
3376
- rrdlabels_add(mdi->st_lock_timeouts->rrdlabels, "mssql_instance", mdi->parent->instanceID, RRDLABEL_SRC_AUTO);
3377
- rrdlabels_add(mdi->st_lock_timeouts->rrdlabels, "database", db, RRDLABEL_SRC_AUTO);
3378
-
3379
- mdi->rd_lock_timeouts = rrddim_add(mdi->st_lock_timeouts, "timeouts", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
3380
- }
3381
-
3382
- rrddim_set_by_pointer(
3383
- mdi->st_lock_timeouts, mdi->rd_lock_timeouts, (collected_number)mdi->MSSQLDatabaseLockTimeoutsSec.current.Data);
3384
-
3385
- rrdset_done(mdi->st_lock_timeouts);
3386
-}
12
+ PERF_OBJECT_TYPE *pObjectType =
13
+ perflibFindObjectTypeByName(pDataBlock, mi->objectName[NETDATA_MSSQL_ACCESS_METHODS]);
14
+ if (unlikely(!pObjectType))
15
+ return;
16
3388
-static void mssql_active_transactions_chart(struct mssql_db_instance *mdi, const char *db, int update_every)
3389
-{
3390
- char id[RRD_ID_LENGTH_MAX + 1];
17
+ if (likely(perflibGetObjectCounter(pDataBlock, pObjectType, &mi->MSSQLAccessMethodPageSplits))) {
18
+ if (unlikely(!mi->st_access_method_page_splits)) {
19
+ snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_accessmethods_page_splits", mi->instanceID);
20
+ netdata_fix_chart_name(id);
21
+ mi->st_access_method_page_splits = rrdset_create_localhost(
22
+ "mssql",
23
+ id,
24
+ NULL,
25
+ "buffer cache",
26
+ "mssql.instance_accessmethods_page_splits",
27
+ "Page splits",
28
+ "splits/s",
29
+ PLUGIN_WINDOWS_NAME,
30
+ "PerflibMSSQL",
31
+ PRIO_MSSQL_BUFF_METHODS_PAGE_SPLIT,
32
+ update_every,
33
+ RRDSET_TYPE_LINE);
34
3392
- if (!mdi->st_db_active_transactions) {
3393
- snprintfz(id, RRD_ID_LENGTH_MAX, "db_%s_instance_%s_active_transactions", db, mdi->parent->instanceID);
3394
- netdata_fix_chart_name(id);
3395
- mdi->st_db_active_transactions = rrdset_create_localhost(
3396
- "mssql",
3397
- id,
3398
- NULL,
3399
- "transactions",
3400
- "mssql.database_active_transactions",
3401
- "Active transactions per database",
3402
- "transactions",
3403
- PLUGIN_WINDOWS_NAME,
3404
- "PerflibMSSQL",
3405
- PRIO_MSSQL_DATABASE_ACTIVE_TRANSACTIONS,
3406
- update_every,
3407
- RRDSET_TYPE_LINE);
35
+ mi->rd_access_method_page_splits =
36
+ rrddim_add(mi->st_access_method_page_splits, "page", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
37
3409
- rrdlabels_add(
3410
- mdi->st_db_active_transactions->rrdlabels, "mssql_instance", mdi->parent->instanceID, RRDLABEL_SRC_AUTO);
3411
- rrdlabels_add(mdi->st_db_active_transactions->rrdlabels, "database", db, RRDLABEL_SRC_AUTO);
38
+ rrdlabels_add(
39
+ mi->st_access_method_page_splits->rrdlabels, "mssql_instance", mi->instanceID, RRDLABEL_SRC_AUTO);
40
+ }
41
3413
- mdi->rd_db_active_transactions =
3414
- rrddim_add(mdi->st_db_active_transactions, "active", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
42
+ rrddim_set_by_pointer(
43
+ mi->st_access_method_page_splits,
44
+ mi->rd_access_method_page_splits,
45
+ (collected_number)mi->MSSQLAccessMethodPageSplits.current.Data);
46
+ rrdset_done(mi->st_access_method_page_splits);
47
}
3416
-
3417
- rrddim_set_by_pointer(
3418
- mdi->st_db_active_transactions,
3419
- mdi->rd_db_active_transactions,
3420
- (collected_number)mdi->MSSQLDatabaseActiveTransactions.current.Data);
3421
-
3422
- rrdset_done(mdi->st_db_active_transactions);
48
}
49
3425
-static inline void mssql_data_file_size_chart(struct mssql_db_instance *mdi, const char *db, int update_every)
50
+void do_mssql_statistics_perflib(PERF_DATA_BLOCK *pDataBlock, struct mssql_instance *mi, int update_every)
51
{
52
char id[RRD_ID_LENGTH_MAX + 1];
53
3429
- if (unlikely(!mdi->st_db_data_file_size)) {
3430
- snprintfz(id, RRD_ID_LENGTH_MAX, "db_%s_instance_%s_data_files_size", db, mdi->parent->instanceID);
3431
- netdata_fix_chart_name(id);
3432
- mdi->st_db_data_file_size = rrdset_create_localhost(
3433
- "mssql",
3434
- id,
3435
- NULL,
3436
- "size",
3437
- "mssql.database_data_files_size",
3438
- "Current database size.",
3439
- "bytes",
3440
- PLUGIN_WINDOWS_NAME,
3441
- "PerflibMSSQL",
3442
- PRIO_MSSQL_DATABASE_DATA_FILE_SIZE,
3443
- update_every,
3444
- RRDSET_TYPE_LINE);
3445
-
3446
- rrdlabels_add(
3447
- mdi->st_db_data_file_size->rrdlabels, "mssql_instance", mdi->parent->instanceID, RRDLABEL_SRC_AUTO);
3448
- rrdlabels_add(mdi->st_db_data_file_size->rrdlabels, "database", db, RRDLABEL_SRC_AUTO);
3449
-
3450
- mdi->rd_db_data_file_size = rrddim_add(mdi->st_db_data_file_size, "size", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
3451
- }
54
+ PERF_OBJECT_TYPE *pObjectType = perflibFindObjectTypeByName(pDataBlock, mi->objectName[NETDATA_MSSQL_SQL_STATS]);
55
+ if (unlikely(!pObjectType))
56
+ return;
57
3453
- collected_number data = mdi->MSSQLDatabaseDataFileSize.current.Data;
3454
- rrddim_set_by_pointer(mdi->st_db_data_file_size, mdi->rd_db_data_file_size, data);
58
+ if (likely(perflibGetObjectCounter(pDataBlock, pObjectType, &mi->MSSQLStatsAutoParameterization))) {
59
+ if (unlikely(!mi->st_stats_auto_param)) {
60
+ snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_sqlstats_auto_parameterization_attempts", mi->instanceID);
61
+ netdata_fix_chart_name(id);
62
+ mi->st_stats_auto_param = rrdset_create_localhost(
63
+ "mssql",
64
+ id,
65
+ NULL,
66
+ "sql activity",
67
+ "mssql.instance_sqlstats_auto_parameterization_attempts",
68
+ "Failed auto-parameterization attempts",
69
+ "attempts/s",
70
+ PLUGIN_WINDOWS_NAME,
71
+ "PerflibMSSQL",
72
+ PRIO_MSSQL_STATS_AUTO_PARAMETRIZATION,
73
+ update_every,
74
+ RRDSET_TYPE_LINE);
75
3456
- rrdset_done(mdi->st_db_data_file_size);
3457
-}
76
+ mi->rd_stats_auto_param =
77
+ rrddim_add(mi->st_stats_auto_param, "failed", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
78
3459
-int dict_mssql_databases_charts_cb(const DICTIONARY_ITEM *item __maybe_unused, void *value, void *data __maybe_unused)
3460
-{
3461
- struct mssql_db_instance *mdi = value;
3462
- const char *db = dictionary_acquired_item_name((DICTIONARY_ITEM *)item);
79
+ rrdlabels_add(mi->st_stats_auto_param->rrdlabels, "mssql_instance", mi->instanceID, RRDLABEL_SRC_AUTO);
80
+ }
81
3464
- if (!mdi->collecting_data) {
3465
- goto endchartcb;
82
+ rrddim_set_by_pointer(
83
+ mi->st_stats_auto_param,
84
+ mi->rd_stats_auto_param,
85
+ (collected_number)mi->MSSQLStatsAutoParameterization.current.Data);
86
+ rrdset_done(mi->st_stats_auto_param);
87
}
88
3468
- int *update_every = data;
89
+ if (likely(perflibGetObjectCounter(pDataBlock, pObjectType, &mi->MSSQLStatsBatchRequests))) {
90
+ if (unlikely(!mi->st_stats_batch_request)) {
91
+ snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_sqlstats_batch_requests", mi->instanceID);
92
+ netdata_fix_chart_name(id);
93
+ mi->st_stats_batch_request = rrdset_create_localhost(
94
+ "mssql",
95
+ id,
96
+ NULL,
97
+ "sql activity",
98
+ "mssql.instance_sqlstats_batch_requests",
99
+ "Total of batches requests",
100
+ "requests/s",
101
+ PLUGIN_WINDOWS_NAME,
102
+ "PerflibMSSQL",
103
+ PRIO_MSSQL_STATS_BATCH_REQUEST,
104
+ update_every,
105
+ RRDSET_TYPE_LINE);
106
3470
- void (*transaction_chart[])(struct mssql_db_instance *, const char *, int) = {
3471
- mssql_data_file_size_chart,
3472
- mssql_transactions_chart,
3473
- mssql_database_backup_restore_chart,
3474
- mssql_database_log_flushed_chart,
3475
- mssql_database_log_flushes_chart,
3476
- mssql_active_transactions_chart,
3477
- mssql_write_transactions_chart,
3478
- mssql_lockwait_chart,
3479
- mssql_deadlock_chart,
3480
- mssql_is_readonly_chart,
3481
- mssql_db_state_chart_loop,
3482
- mssql_lock_timeout_chart,
3483
- mssql_lock_request_chart,
107
+ mi->rd_stats_batch_request =
108
+ rrddim_add(mi->st_stats_batch_request, "batch", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
109
3485
- // Last function pointer must be NULL
3486
- NULL};
110
+ rrdlabels_add(mi->st_stats_batch_request->rrdlabels, "mssql_instance", mi->instanceID, RRDLABEL_SRC_AUTO);
111
+ }
112
3488
- int i;
3489
- for (i = 0; transaction_chart[i]; i++) {
3490
- transaction_chart[i](mdi, db, *update_every);
113
+ rrddim_set_by_pointer(
114
+ mi->st_stats_batch_request,
115
+ mi->rd_stats_batch_request,
116
+ (collected_number)mi->MSSQLStatsBatchRequests.current.Data);
117
+ rrdset_done(mi->st_stats_batch_request);
118
}
119
3493
-endchartcb:
3494
- return 1;
3495
-}
3496
-
3497
-static void do_mssql_databases(PERF_DATA_BLOCK *pDataBlock, struct mssql_instance *mi, int update_every)
3498
-{
3499
- if (!pDataBlock)
3500
- goto end_mssql_databases;
3501
-
3502
- PERF_OBJECT_TYPE *pObjectType = perflibFindObjectTypeByName(pDataBlock, mi->objectName[NETDATA_MSSQL_DATABASE]);
3503
- if (!pObjectType)
3504
- return;
3505
-
3506
- PERF_INSTANCE_DEFINITION *pi = NULL;
3507
- for (LONG i = 0; i < pObjectType->NumInstances; i++) {
3508
- pi = perflibForEachInstance(pDataBlock, pObjectType, pi);
3509
- if (!pi)
3510
- break;
3511
-
3512
- if (!getInstanceName(pDataBlock, pObjectType, pi, windows_shared_buffer, sizeof(windows_shared_buffer)))
3513
- strncpyz(windows_shared_buffer, "[unknown]", sizeof(windows_shared_buffer) - 1);
3514
-
3515
- if (!strcasecmp(windows_shared_buffer, "_Total"))
3516
- continue;
120
+ if (likely(perflibGetObjectCounter(pDataBlock, pObjectType, &mi->MSSQLStatSafeAutoParameterization))) {
121
+ if (unlikely(!mi->st_stats_safe_auto)) {
122
+ snprintfz(
123
+ id, RRD_ID_LENGTH_MAX, "instance_%s_sqlstats_safe_auto_parameterization_attempts", mi->instanceID);
124
+ netdata_fix_chart_name(id);
125
+ mi->st_stats_safe_auto = rrdset_create_localhost(
126
+ "mssql",
127
+ id,
128
+ NULL,
129
+ "sql activity",
130
+ "mssql.instance_sqlstats_safe_auto_parameterization_attempts",
131
+ "Safe auto-parameterization attempts",
132
+ "attempts/s",
133
+ PLUGIN_WINDOWS_NAME,
134
+ "PerflibMSSQL",
135
+ PRIO_MSSQL_STATS_SAFE_AUTO_PARAMETRIZATION,
136
+ update_every,
137
+ RRDSET_TYPE_LINE);
138
3518
- struct mssql_db_instance *mdi = dictionary_set(mi->databases, windows_shared_buffer, NULL, sizeof(*mdi));
3519
- if (!mdi)
3520
- continue;
139
+ mi->rd_stats_safe_auto = rrddim_add(mi->st_stats_safe_auto, "safe", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
140
3522
- if (!mdi->parent) {
3523
- mdi->parent = mi;
141
+ rrdlabels_add(mi->st_stats_safe_auto->rrdlabels, "mssql_instance", mi->instanceID, RRDLABEL_SRC_AUTO);
142
}
143
3526
- if (!i)
3527
- mdi->collect_instance = true;
144
+ rrddim_set_by_pointer(
145
+ mi->st_stats_safe_auto,
146
+ mi->rd_stats_safe_auto,
147
+ (collected_number)mi->MSSQLStatSafeAutoParameterization.current.Data);
148
+ rrdset_done(mi->st_stats_safe_auto);
149
}
3529
-
3530
-end_mssql_databases:
3531
- dictionary_sorted_walkthrough_read(mi->databases, dict_mssql_databases_charts_cb, &update_every);
150
}
151
3534
-static void do_mssql_memory_mgr(PERF_DATA_BLOCK *pDataBlock, struct mssql_instance *mi, int update_every)
152
+void do_mssql_memory_mgr(PERF_DATA_BLOCK *pDataBlock, struct mssql_instance *mi, int update_every)
153
{
154
char id[RRD_ID_LENGTH_MAX + 1];
155
156
PERF_OBJECT_TYPE *pObjectType = perflibFindObjectTypeByName(pDataBlock, mi->objectName[NETDATA_MSSQL_MEMORY]);
3539
- if (!pObjectType)
157
+ if (unlikely(!pObjectType))
158
return;
159
3542
- if (perflibGetObjectCounter(pDataBlock, pObjectType, &mi->MSSQLConnectionMemoryBytes)) {
3543
- if (!mi->st_conn_memory) {
160
+ if (likely(perflibGetObjectCounter(pDataBlock, pObjectType, &mi->MSSQLConnectionMemoryBytes))) {
161
+ if (unlikely(!mi->st_conn_memory)) {
162
snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_memmgr_connection_memory_bytes", mi->instanceID);
163
netdata_fix_chart_name(id);
164
mi->st_conn_memory = rrdset_create_localhost(
3547
- "mssql",
3548
- id,
3549
- NULL,
3550
- "memory",
3551
- "mssql.instance_memmgr_connection_memory_bytes",
3552
- "Amount of dynamic memory to maintain connections",
3553
- "bytes",
3554
- PLUGIN_WINDOWS_NAME,
3555
- "PerflibMSSQL",
3556
- PRIO_MSSQL_MEMMGR_CONNECTION_MEMORY_BYTES,
3557
- update_every,
3558
- RRDSET_TYPE_LINE);
165
+ "mssql",
166
+ id,
167
+ NULL,
168
+ "memory",
169
+ "mssql.instance_memmgr_connection_memory_bytes",
170
+ "Amount of dynamic memory to maintain connections",
171
+ "bytes",
172
+ PLUGIN_WINDOWS_NAME,
173
+ "PerflibMSSQL",
174
+ PRIO_MSSQL_MEMMGR_CONNECTION_MEMORY_BYTES,
175
+ update_every,
176
+ RRDSET_TYPE_LINE);
177
178
mi->rd_conn_memory = rrddim_add(mi->st_conn_memory, "memory", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
179
@@ -3563,29 +181,29 @@ static void do_mssql_memory_mgr(PERF_DATA_BLOCK *pDataBlock, struct mssql_instan
181
}
182
183
rrddim_set_by_pointer(
3566
- mi->st_conn_memory,
3567
- mi->rd_conn_memory,
3568
- (collected_number)(mi->MSSQLConnectionMemoryBytes.current.Data * 1024));
184
+ mi->st_conn_memory,
185
+ mi->rd_conn_memory,
186
+ (collected_number)(mi->MSSQLConnectionMemoryBytes.current.Data * 1024));
187
rrdset_done(mi->st_conn_memory);
188
}
189
3572
- if (perflibGetObjectCounter(pDataBlock, pObjectType, &mi->MSSQLExternalBenefitOfMemory)) {
3573
- if (!mi->st_ext_benefit_mem) {
190
+ if (likely(perflibGetObjectCounter(pDataBlock, pObjectType, &mi->MSSQLExternalBenefitOfMemory))) {
191
+ if (unlikely(!mi->st_ext_benefit_mem)) {
192
snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_memmgr_external_benefit_of_memory", mi->instanceID);
193
netdata_fix_chart_name(id);
194
mi->st_ext_benefit_mem = rrdset_create_localhost(
3577
- "mssql",
3578
- id,
3579
- NULL,
3580
- "memory",
3581
- "mssql.instance_memmgr_external_benefit_of_memory",
3582
- "Performance benefit from adding memory to a specific cache",
3583
- "bytes",
3584
- PLUGIN_WINDOWS_NAME,
3585
- "PerflibMSSQL",
3586
- PRIO_MSSQL_MEMMGR_EXTERNAL_BENEFIT_OF_MEMORY,
3587
- update_every,
3588
- RRDSET_TYPE_LINE);
195
+ "mssql",
196
+ id,
197
+ NULL,
198
+ "memory",
199
+ "mssql.instance_memmgr_external_benefit_of_memory",
200
+ "Performance benefit from adding memory to a specific cache",
201
+ "bytes",
202
+ PLUGIN_WINDOWS_NAME,
203
+ "PerflibMSSQL",
204
+ PRIO_MSSQL_MEMMGR_EXTERNAL_BENEFIT_OF_MEMORY,
205
+ update_every,
206
+ RRDSET_TYPE_LINE);
207
208
mi->rd_ext_benefit_mem = rrddim_add(mi->st_ext_benefit_mem, "benefit", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
209
@@ -3593,61 +211,61 @@ static void do_mssql_memory_mgr(PERF_DATA_BLOCK *pDataBlock, struct mssql_instan
211
}
212
213
rrddim_set_by_pointer(
3596
- mi->st_ext_benefit_mem,
3597
- mi->rd_ext_benefit_mem,
3598
- (collected_number)mi->MSSQLExternalBenefitOfMemory.current.Data);
214
+ mi->st_ext_benefit_mem,
215
+ mi->rd_ext_benefit_mem,
216
+ (collected_number)mi->MSSQLExternalBenefitOfMemory.current.Data);
217
rrdset_done(mi->st_ext_benefit_mem);
218
}
219
3602
- if (perflibGetObjectCounter(pDataBlock, pObjectType, &mi->MSSQLPendingMemoryGrants)) {
3603
- if (!mi->st_pending_mem_grant) {
220
+ if (likely(perflibGetObjectCounter(pDataBlock, pObjectType, &mi->MSSQLPendingMemoryGrants))) {
221
+ if (unlikely(!mi->st_pending_mem_grant)) {
222
snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_memmgr_pending_memory_grants", mi->instanceID);
223
netdata_fix_chart_name(id);
224
mi->st_pending_mem_grant = rrdset_create_localhost(
3607
- "mssql",
3608
- id,
3609
- NULL,
3610
- "memory",
3611
- "mssql.instance_memmgr_pending_memory_grants",
3612
- "Process waiting for memory grant",
3613
- "processes",
3614
- PLUGIN_WINDOWS_NAME,
3615
- "PerflibMSSQL",
3616
- PRIO_MSSQL_MEMMGR_PENDING_MEMORY_GRANTS,
3617
- update_every,
3618
- RRDSET_TYPE_LINE);
225
+ "mssql",
226
+ id,
227
+ NULL,
228
+ "memory",
229
+ "mssql.instance_memmgr_pending_memory_grants",
230
+ "Process waiting for memory grant",
231
+ "processes",
232
+ PLUGIN_WINDOWS_NAME,
233
+ "PerflibMSSQL",
234
+ PRIO_MSSQL_MEMMGR_PENDING_MEMORY_GRANTS,
235
+ update_every,
236
+ RRDSET_TYPE_LINE);
237
238
mi->rd_pending_mem_grant =
3621
- rrddim_add(mi->st_pending_mem_grant, "pending", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
239
+ rrddim_add(mi->st_pending_mem_grant, "pending", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
240
241
rrdlabels_add(mi->st_pending_mem_grant->rrdlabels, "mssql_instance", mi->instanceID, RRDLABEL_SRC_AUTO);
242
}
243
244
rrddim_set_by_pointer(
3627
- mi->st_pending_mem_grant,
3628
- mi->rd_pending_mem_grant,
3629
- (collected_number)mi->MSSQLPendingMemoryGrants.current.Data);
245
+ mi->st_pending_mem_grant,
246
+ mi->rd_pending_mem_grant,
247
+ (collected_number)mi->MSSQLPendingMemoryGrants.current.Data);
248
249
rrdset_done(mi->st_pending_mem_grant);
250
}
251
3634
- if (perflibGetObjectCounter(pDataBlock, pObjectType, &mi->MSSQLTotalServerMemory)) {
3635
- if (!mi->st_mem_tot_server) {
252
+ if (likely(perflibGetObjectCounter(pDataBlock, pObjectType, &mi->MSSQLTotalServerMemory))) {
253
+ if (unlikely(!mi->st_mem_tot_server)) {
254
snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_memmgr_server_memory", mi->instanceID);
255
netdata_fix_chart_name(id);
256
mi->st_mem_tot_server = rrdset_create_localhost(
3639
- "mssql",
3640
- id,
3641
- NULL,
3642
- "memory",
3643
- "mssql.instance_memmgr_server_memory",
3644
- "Memory committed",
3645
- "bytes",
3646
- PLUGIN_WINDOWS_NAME,
3647
- "PerflibMSSQL",
3648
- PRIO_MSSQL_MEMMGR_TOTAL_SERVER,
3649
- update_every,
3650
- RRDSET_TYPE_LINE);
257
+ "mssql",
258
+ id,
259
+ NULL,
260
+ "memory",
261
+ "mssql.instance_memmgr_server_memory",
262
+ "Memory committed",
263
+ "bytes",
264
+ PLUGIN_WINDOWS_NAME,
265
+ "PerflibMSSQL",
266
+ PRIO_MSSQL_MEMMGR_TOTAL_SERVER,
267
+ update_every,
268
+ RRDSET_TYPE_LINE);
269
270
mi->rd_mem_tot_server = rrddim_add(mi->st_mem_tot_server, "memory", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
271
@@ -3655,101 +273,114 @@ static void do_mssql_memory_mgr(PERF_DATA_BLOCK *pDataBlock, struct mssql_instan
273
}
274
275
rrddim_set_by_pointer(
3658
- mi->st_mem_tot_server,
3659
- mi->rd_mem_tot_server,
3660
- (collected_number)(mi->MSSQLTotalServerMemory.current.Data * 1024));
276
+ mi->st_mem_tot_server,
277
+ mi->rd_mem_tot_server,
278
+ (collected_number)(mi->MSSQLTotalServerMemory.current.Data * 1024));
279
280
rrdset_done(mi->st_mem_tot_server);
281
}
282
}
283
3666
-static inline PERF_DATA_BLOCK *
3667
-netdata_mssql_get_perf_data_block(bool *collect_perflib, struct mssql_instance *mi, DWORD idx)
284
+void do_mssql_errors(PERF_DATA_BLOCK *pDataBlock, struct mssql_instance *mi, int update_every)
285
{
3669
- DWORD id = RegistryFindIDByName(mi->objectName[idx]);
3670
- if (id == PERFLIB_REGISTRY_NAME_NOT_FOUND) {
3671
- collect_perflib[idx] = false;
3672
- return NULL;
3673
- }
286
+ char id[RRD_ID_LENGTH_MAX + 1];
287
3675
- PERF_DATA_BLOCK *pDataBlock = perflibGetPerformanceData(id);
3676
- if (!pDataBlock) {
3677
- collect_perflib[idx] = true;
3678
- return NULL;
3679
- }
288
+ PERF_OBJECT_TYPE *pObjectType = perflibFindObjectTypeByName(pDataBlock, mi->objectName[NETDATA_MSSQL_SQL_ERRORS]);
289
+ if (unlikely(!pObjectType))
290
+ return;
291
3681
- return pDataBlock;
3682
-}
292
+ if (likely(perflibGetObjectCounter(pDataBlock, pObjectType, &mi->MSSQLSQLErrorsTotal))) {
293
+ if (unlikely(!mi->st_sql_errors)) {
294
+ snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_sql_errors_total", mi->instanceID);
295
+ netdata_fix_chart_name(id);
296
+ mi->st_sql_errors = rrdset_create_localhost(
297
+ "mssql",
298
+ id,
299
+ NULL,
300
+ "errors",
301
+ "mssql.instance_sql_errors",
302
+ "Errors",
303
+ "errors/s",
304
+ PLUGIN_WINDOWS_NAME,
305
+ "PerflibMSSQL",
306
+ PRIO_MSSQL_SQL_ERRORS,
307
+ update_every,
308
+ RRDSET_TYPE_LINE);
309
3684
-int dict_mssql_charts_cb(const DICTIONARY_ITEM *item __maybe_unused, void *value, void *data __maybe_unused)
3685
-{
3686
- struct mssql_instance *mi = value;
3687
- int *update_every = data;
310
+ mi->rd_sql_errors = rrddim_add(mi->st_sql_errors, "errors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
311
3689
- static void (*doMSSQL[])(PERF_DATA_BLOCK *, struct mssql_instance *, int) = {
3690
- do_mssql_general_stats,
3691
- do_mssql_errors,
3692
- do_mssql_memory_mgr,
3693
- do_mssql_statistics_perflib,
3694
- do_mssql_access_methods,
312
+ rrdlabels_add(mi->st_sql_errors->rrdlabels, "mssql_instance", mi->instanceID, RRDLABEL_SRC_AUTO);
313
+ }
314
3696
- do_mssql_databases,
3697
- do_mssql_locks,
3698
- do_mssql_waits,
3699
- do_mssql_bufferman_stats_sql,
3700
- do_mssql_job_status_sql,
315
+ rrddim_set_by_pointer(
316
+ mi->st_sql_errors, mi->rd_sql_errors, (collected_number)mi->MSSQLAccessMethodPageSplits.current.Data);
317
+ rrdset_done(mi->st_sql_errors);
318
+ }
319
+}
320
3702
- NULL};
321
3704
- DWORD i;
3705
- PERF_DATA_BLOCK *pDataBlock;
3706
- static bool collect_perflib[NETDATA_MSSQL_METRICS_END] = {
3707
- true, true, true, true, true, true, true, true, true, true};
3708
- for (i = 0; i < NETDATA_MSSQL_ACCESS_METHODS; i++) {
3709
- if (!collect_perflib[i])
3710
- continue;
322
+void do_mssql_general_stats(PERF_DATA_BLOCK *pDataBlock, struct mssql_instance *mi, int update_every)
323
+{
324
+ char id[RRD_ID_LENGTH_MAX + 1];
325
3712
- pDataBlock = netdata_mssql_get_perf_data_block(collect_perflib, mi, i);
3713
- if (!pDataBlock)
3714
- continue;
326
+ PERF_OBJECT_TYPE *pObjectType =
327
+ perflibFindObjectTypeByName(pDataBlock, mi->objectName[NETDATA_MSSQL_GENERAL_STATS]);
328
+ if (unlikely(!pObjectType))
329
+ return;
330
3716
- doMSSQL[i](pDataBlock, mi, *update_every);
3717
- }
331
+ if (likely(perflibGetObjectCounter(pDataBlock, pObjectType, &mi->MSSQLUserConnections))) {
332
+ if (unlikely(!mi->st_user_connections)) {
333
+ snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_user_connections", mi->instanceID);
334
+ netdata_fix_chart_name(id);
335
+ mi->st_user_connections = rrdset_create_localhost(
336
+ "mssql",
337
+ id,
338
+ NULL,
339
+ "connections",
340
+ "mssql.instance_user_connections",
341
+ "User connections",
342
+ "connections",
343
+ PLUGIN_WINDOWS_NAME,
344
+ "PerflibMSSQL",
345
+ PRIO_MSSQL_USER_CONNECTIONS,
346
+ update_every,
347
+ RRDSET_TYPE_LINE);
348
3719
- if (unlikely(!mi->conn || !mi->conn->is_connected))
3720
- return 1;
349
+ mi->rd_user_connections = rrddim_add(mi->st_user_connections, "user", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
350
3722
- for (i = NETDATA_MSSQL_DATABASE; doMSSQL[i]; i++) {
3723
- pDataBlock = (collect_perflib[i]) ? netdata_mssql_get_perf_data_block(collect_perflib, mi, i) : NULL;
351
+ rrdlabels_add(mi->st_user_connections->rrdlabels, "mssql_instance", mi->instanceID, RRDLABEL_SRC_AUTO);
352
+ }
353
3725
- doMSSQL[i](pDataBlock, mi, *update_every);
354
+ rrddim_set_by_pointer(
355
+ mi->st_user_connections, mi->rd_user_connections, (collected_number)mi->MSSQLUserConnections.current.Data);
356
+ rrdset_done(mi->st_user_connections);
357
}
358
3728
- do_mssql_replication(mi, *update_every);
3729
-
3730
- return 1;
3731
-}
3732
-
3733
-// Entry point
359
+ if (likely(perflibGetObjectCounter(pDataBlock, pObjectType, &mi->MSSQLBlockedProcesses))) {
360
+ if (unlikely(!mi->st_process_blocked)) {
361
+ snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_blocked_process", mi->instanceID);
362
+ netdata_fix_chart_name(id);
363
+ mi->st_process_blocked = rrdset_create_localhost(
364
+ "mssql",
365
+ id,
366
+ NULL,
367
+ "processes",
368
+ "mssql.instance_blocked_processes",
369
+ "Blocked processes",
370
+ "process",
371
+ PLUGIN_WINDOWS_NAME,
372
+ "PerflibMSSQL",
373
+ PRIO_MSSQL_BLOCKED_PROCESSES,
374
+ update_every,
375
+ RRDSET_TYPE_LINE);
376
3735
-int do_PerflibMSSQL(int update_every, usec_t dt __maybe_unused)
3736
-{
3737
- static bool initialized = false;
377
+ mi->rd_process_blocked = rrddim_add(mi->st_process_blocked, "blocked", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
378
3739
- if (unlikely(!initialized)) {
3740
- if (initialize(update_every))
3741
- return -1;
379
+ rrdlabels_add(mi->st_process_blocked->rrdlabels, "mssql_instance", mi->instanceID, RRDLABEL_SRC_AUTO);
380
+ }
381
3743
- initialized = true;
382
+ rrddim_set_by_pointer(
383
+ mi->st_process_blocked, mi->rd_process_blocked, (collected_number)mi->MSSQLBlockedProcesses.current.Data);
384
+ rrdset_done(mi->st_process_blocked);
385
}
3745
-
3746
- dictionary_sorted_walkthrough_read(mssql_instances, dict_mssql_charts_cb, &update_every);
3747
-
3748
- return 0;
3749
-}
3750
-
3751
-void do_PerflibMSSQL_cleanup()
3752
-{
3753
- if (nd_thread_join(mssql_queries_thread))
3754
- nd_log_daemon(NDLP_ERR, "Failed to join mssql queries thread");
386
}