@cryptotaxi247 / netdata-1 / commits / aff889011

Fix MSSQL and improvements (#20032)

thiagoftsm committed Apr 17, 2025 at 18:54 UTC aff889011f29d1c9995cb20d9d879414d21efab2
3 files changed +701 -267
CMakeLists.txt
+1
@@ -3037,6 +3037,7 @@ target_link_libraries(netdata PRIVATE
3037 "$<$<BOOL:${ENABLE_WEBRTC}>:LibDataChannel::LibDataChannelStatic>"
3038 "$<$<BOOL:${ENABLE_H2O}>:h2o>"
3039 "$<$<BOOL:${CURL_FOUND}>:PkgConfig::CURL>"
3040 + "$<$<BOOL:${OS_WINDOWS}>:odbc32>"
3041 )
3042
3043 netdata_add_protobuf(netdata)
src/collectors/windows.plugin/README.md
+157 -6
@@ -5,13 +5,11 @@ This internal plugin is only available for Microsoft Windows operating systems.
5 ## The Collector
6
7 This plugin primarily collects metrics from Microsoft Windows [Performance Counters](https://learn.microsoft.com/en-us/windows/win32/perfctrs/performance-counters-what-s-new). All detected metrics are automatically displayed without requiring additional configuration.
8 +=======
9 +Most of the metrics collected by this plugin originate from Microsoft Windows
10 +[Performance Counters](https://learn.microsoft.com/en-us/windows/win32/perfctrs/performance-counters-what-s-new).
11
9 -## Configuration File
10 -
11 -The Windows plugin doesn't use a separate configuration file. Instead, configure it through Netdata's main configuration file located at:
12 -`C:\Program Files\Netdata\etc\netdata\netdata.conf`.
13 -
14 -### Enabling or Disabling Collection
12 +These metrics are always displayed when detected, requiring no additional configuration.
13
14 By default, all collector threads are enabled except for `PerflibThermalZone` and `PerflibServices`. You can enable these or disable others by modifying options in the `[plugin:windows]` section of the configuration file.
15
@@ -31,9 +29,162 @@ To change a setting, remove the comment symbol (`#`) from the beginning of the l
29 # PerflibThermalZone = no
30 # PerflibWebService = yes
31 # PerflibServices = no
32 + # PerflibMSSQL = yes
33 # PerflibNetFramework = yes
34 # PerflibAD = yes
35 # PerflibADCS = yes
36 # PerflibADFS = yes
37 ```
38
39 +## Configuration
40 +
41 +To collect certain metrics for [Microsoft SQL Server](https://www.microsoft.com/en-us/sql-server),
42 +Netdata needs access to internal server data. To collect this data, you need to configure both your server and Netdata.
43 +
44 +### Windows Defender Firewall with Advanced Security
45 +
46 +To connect to your SQL Server, Netdata uses TCP port 1433 (or any other configured port).
47 +This port is typically blocked by Windows Defender, so you must allow access before proceeding:
48 +
49 +1. Open `Windows Defender Firewall with Advanced Security` as an Adminstrator.
50 +2. Right-click `Inbound Rules` and select `New Rule...`.
51 +3. Select `Port`, then click `Next`.
52 +4. Choose `TCP`, then enter `1433` in the `Specific local ports:`. Click `Next`.
53 +5. Select an appropriate action based on your network policy. For example, `Allow the connection`.
54 + Click `Next`.
55 +6. Choose where the rule will be applied (Domain, Private, or Public).
56 +7. Finally, provide a `Name` and an optional `Description` for the new rule,
57 + then click `Finish`.
58 +
59 +You can use the same rule to allow connections to other instances. To do this,
60 +specify the ports for each instance in the `Port` field separated by commas.
61 +
62 +### Microsoft SQL Server (Configuration)
63 +
64 +After enabling access through the firewall, you will need to configure your SQL Server instance to accept TCP
65 +connections:
66 +
67 +1. Open `SQL Server Configuration Manager`.
68 +2. Expand `SQL Server Network Configuration`.
69 +3. In the console panel, select `Protocols for <instance name>.`.
70 +4. In the details panel, double-click the `TCP` protocol, and set `Yes` for `Enabled`.
71 +5. Go to the `IP Address` tab, locate the section labeled`IPAII`.
72 + - Remove any value from the `TCP Dynamic Ports` field.
73 + - Enter a value in the `TCP Port` field. By default, SQL Server uses `1433`.
74 +6. Finally, select `SQL Server Services`, and restart your SQL Server instance.
75 +
76 +You need to apply this configuration to every instance.
77 +
78 +### Microsoft SQL Server (User)
79 +
80 +If you want to allow connections using SQL Server authentication, you must modify the server configuration:
81 +
82 +1. Open `Microsoft Server Management Studio`.
83 +2. Right-click your server, and select `Properties`.
84 +3. In the left panel, select `Security`.
85 +4. Under `Server authentication`, choose `SQL Server and Windows Authentication mode`.
86 +5. Click `OK`.
87 +6. Finally, right-click your server, and select`Restart`.
88 +
89 +After that, you need to create a user with the `VIEW SERVER STATE` permission to collect data from the server.
90 +Once the user is created, it must also be granted access to the databases.
91 +
92 +```tsql
93 +USE master;
94 +CREATE LOGIN netdata_user WITH PASSWORD = 'netdata';
95 +CREATE USER netdata_user FOR LOGIN netdata_user;
96 +GRANT CONNECT SQL TO netdata_user;
97 +GRANT VIEW SERVER STATE TO netdata_user;
98 +GO
99 +```
100 +
101 +In addition to creating the user, you must enable the
102 +[query store](https://learn.microsoft.com/en-us/sql/relational-databases/performance/monitoring-performance-by-using-the-query-store?view=sql-server-ver16),
103 +on each database you wish to monitor.
104 +
105 +```tsql
106 +DECLARE @dbname NVARCHAR(max)
107 +DECLARE nd_user_cursor CURSOR FOR SELECT name FROM master.dbo.sysdatabases WHERE NAME NOT IN ('master','msdb','tempdb','model')
108 +
109 +OPEN nd_user_cursor
110 +FETCH NEXT FROM nd_user_cursor INTO @dbname WHILE @@FETCH_STATUS = 0
111 +BEGIN
112 + EXECUTE ("USE "+ @dbname+"; CREATE USER netdata_user FOR LOGIN netdata_user; ALTER DATABASE "+@dbname+" SET QUERY_STORE = ON ( QUERY_CAPTURE_MODE = ALL, DATA_FLUSH_INTERVAL_SECONDS = 900 )");
113 + FETCH next FROM nd_user_cursor INTO @dbname;
114 +END
115 +CLOSE nd_user_cursor
116 +DEALLOCATE nd_user_cursor
117 +GO
118 +```
119 +
120 +You need to apply this configuration to every instance.
121 +
122 +### Netdata Configuration
123 +
124 +Now that the user has been created inside your server, update `netdata.conf` by adding the following section:
125 +
126 +```text
127 +[plugin:windows:PerflibMSSQL]
128 + driver = SQL Server
129 + server = 127.0.0.1\\Dev, 1433
130 + #address = [protocol:]Address[,port |\pipe\pipename]
131 + uid = netdata_user
132 + pwd = AReallyStrongPasswordShouldBeInsertedHere
133 + # additional instances = 0
134 + #windows authentication = no
135 +```
136 +
137 +In next table, we give a short description about them:
138 +
139 +| Option | Description |
140 +|--------------------------|-----------------------------------------------------------------------------------|
141 +|`driver` | ODBC driver used to connect to the MSSQL server. |
142 +|`server` | Server address or instance name to connect to. |
143 +|`address` | Similar to `server`. You can also use named pipes if your server supports them. |
144 +|`uid` | User identifier (`uid`) created on your server. |
145 +|`pwd` | Password for the specified user. |
146 +|`additional instances` | Number of additional MSSQL instances to monitor. |
147 +|`windows authentications` | Use Windows credentials to connect to the MSSQL server. |
148 +
149 +For additional information on how to set these parameters, refer to the
150 +[Microsoft Official Documentation](https://learn.microsoft.com/en-us/sql/relational-databases/native-client/applications/using-connection-string-keywords-with-sql-server-native-client?view=sql-server-ver15&viewFallbackFrom=sql-server-ver16)
151 +
152 +#### Additional Instance
153 +
154 +Microsoft SQL Server can host multiple instances. To connect to them, you need to create additional sections in your
155 +`netdata.conf` file, specifying their respective connection options.
156 +
157 +Let’s suppose you have an additional instance named `Production`. To enable Netdata to monitor both the `Production`
158 +and `Dev` instances, you’ll need to add the following configuration section:
159 +
160 +```text
161 +[plugin:windows:PerflibMSSQL1]
162 + driver = SQL Server
163 + server = 127.0.0.1\\Production, 1434
164 + uid = netdata_user
165 + pwd = AnotherReallyStrongPasswordShouldBeInsertedHere
166 +```
167 +
168 +You must also update the main section to indicate how many additional instances you want to monitor:
169 +
170 +```text
171 +[plugin:windows:PerflibMSSQL]
172 + additional instances = 1
173 +```
174 +
175 +Each additional instance section must follow the naming pattern `plugin:windows:PerflibMSSQL`, with a sequential number
176 +from 1 to 65535, based on the number of instances you want to monitor.
177 +
178 +### Errors
179 +
180 +When configuring Netdata to access SQL Server, some errors may occur. You can check your configuration using the
181 +Microsoft Event Viewer by looking for entries that begin with `MSSQL server error using the handle`.
182 +
183 +#### Data source name not found and no default driver
184 +
185 +This error occurs when the driver is not specified correctly. You can check the available drivers by following
186 +these steps:
187 +
188 +- Access `ODBC Data Sources`.
189 +- Go to `Drivers` tab.
190 +- Look for `Name` of the `ODBC` or `SQL Server` driver .
src/collectors/windows.plugin/perflib-mssql.c
+543 -261
@@ -3,12 +3,37 @@
3 #include "windows_plugin.h"
4 #include "windows-internals.h"
5
6 +#include <sqlext.h>
7 +#include <sqltypes.h>
8 +#include <sql.h>
9 +
10 +#define MEGA_FACTOR (1048576) // 1024 * 1024
11 // https://learn.microsoft.com/en-us/sql/sql-server/install/instance-configuration?view=sql-server-ver16
12 #define NETDATA_MAX_INSTANCE_NAME 32
13 #define NETDATA_MAX_INSTANCE_OBJECT 128
14 +// https://learn.microsoft.com/en-us/previous-versions/sql/sql-server-2008-r2/ms191240(v=sql.105)#sysname
15 +#define SQLSERVER_MAX_NAME_LENGTH (128)
16
17 BOOL is_sqlexpress = FALSE;
18
19 +struct netdata_mssql_conn {
20 + const char *driver;
21 + const char *server;
22 + const char *address;
23 + const char *username;
24 + const char *password;
25 + int instances;
26 + bool windows_auth;
27 +
28 + SQLCHAR *connectionString;
29 +
30 + SQLHENV netdataSQLEnv;
31 + SQLHDBC netdataSQLHDBc;
32 + SQLHSTMT dataFileSizeSTMT;
33 +
34 + BOOL is_connected;
35 +};
36 +
37 enum netdata_mssql_metrics {
38 NETDATA_MSSQL_GENERAL_STATS,
39 NETDATA_MSSQL_SQL_ERRORS,
@@ -25,6 +50,8 @@ enum netdata_mssql_metrics {
50 struct mssql_instance {
51 char *instanceID;
52
53 + struct netdata_mssql_conn conn;
54 +
55 char *objectName[NETDATA_MSSQL_METRICS_END];
56
57 RRDSET *st_user_connections;
@@ -116,7 +143,6 @@ struct mssql_lock_instance {
143 };
144
145 enum db_instance_idx {
119 - NETDATA_MSSQL_ENUM_MDI_IDX_FILE_SIZE,
146 NETDATA_MSSQL_ENUM_MDI_IDX_ACTIVE_TRANSACTIONS,
147 NETDATA_MSSQL_ENUM_MDI_IDX_BACKUP_RESTORE_OP,
148 NETDATA_MSSQL_ENUM_MDI_IDX_LOG_FLUSHED,
@@ -157,9 +183,181 @@ struct mssql_db_instance {
183 uint32_t updated;
184 };
185
186 +enum netdata_mssql_odbc_errors {
187 + NETDATA_MSSQL_ODBC_NO_ERROR,
188 + NETDATA_MSSQL_ODBC_CONNECT,
189 + NETDATA_MSSQL_ODBC_BIND,
190 + NETDATA_MSSQL_ODBC_PREPARE,
191 + NETDATA_MSSQL_ODBC_QUERY,
192 + NETDATA_MSSQL_ODBC_FETCH
193 +};
194 +
195 +static char *netdata_MSSQL_error_text(enum netdata_mssql_odbc_errors val)
196 +{
197 + switch (val) {
198 + case NETDATA_MSSQL_ODBC_NO_ERROR:
199 + return "NO ERROR";
200 + case NETDATA_MSSQL_ODBC_CONNECT:
201 + return "CONNECTION";
202 + case NETDATA_MSSQL_ODBC_BIND:
203 + return "BIND PARAMETER";
204 + case NETDATA_MSSQL_ODBC_PREPARE:
205 + return "PREPARE PARAMETER";
206 + case NETDATA_MSSQL_ODBC_QUERY:
207 + return "QUERY PARAMETER";
208 + case NETDATA_MSSQL_ODBC_FETCH:
209 + default:
210 + return "QUERY FETCH";
211 + }
212 +}
213 +
214 +static char *netdata_MSSQL_type_text(uint32_t type)
215 +{
216 + switch (type) {
217 + case SQL_HANDLE_STMT:
218 + return "STMT";
219 + case SQL_HANDLE_DBC:
220 + default:
221 + return "DBC";
222 + }
223 +}
224 +
225 +// Connection and SQL
226 +static void netdata_MSSQL_error(uint32_t type, SQLHANDLE handle, enum netdata_mssql_odbc_errors step)
227 +{
228 + SQLCHAR state[1024];
229 + SQLCHAR message[1024];
230 + if (SQL_SUCCESS == SQLGetDiagRec((short)type, handle, 1, state, NULL, message, 1024, NULL)) {
231 + char *str_step = netdata_MSSQL_error_text(step);
232 + char *str_type = netdata_MSSQL_type_text(type);
233 + nd_log(
234 + NDLS_COLLECTORS,
235 + NDLP_ERR,
236 + "MSSQL server error using the handle %s running %s : %s, %s",
237 + str_type,
238 + str_step,
239 + message,
240 + state);
241 + }
242 +}
243 +
244 +static ULONGLONG netdata_MSSQL_fill_data_file_size_dict(SQLHSTMT *stmt, SQLCHAR *query)
245 +{
246 + static long db_size = 0;
247 + static SQLLEN col_data_len = 0;
248 +
249 + SQLRETURN ret;
250 +
251 + ret = SQLExecDirect(stmt, query, SQL_NTS);
252 + if (ret != SQL_SUCCESS) {
253 + netdata_MSSQL_error(SQL_HANDLE_STMT, stmt, NETDATA_MSSQL_ODBC_QUERY);
254 + return 0;
255 + }
256 +
257 + ret = SQLBindCol(stmt, 1, SQL_C_LONG, &db_size, sizeof(long), &col_data_len);
258 +
259 + if (ret != SQL_SUCCESS) {
260 + netdata_MSSQL_error(SQL_HANDLE_STMT, stmt, NETDATA_MSSQL_ODBC_PREPARE);
261 + return 0;
262 + }
263 +
264 + ret = SQLFetch(stmt);
265 + if (ret != SQL_SUCCESS) {
266 + netdata_MSSQL_error(SQL_HANDLE_STMT, stmt, NETDATA_MSSQL_ODBC_FETCH);
267 + return 0;
268 + }
269 +
270 + return (ULONGLONG)(db_size * MEGA_FACTOR);
271 +}
272 +
273 +ULONGLONG netdata_MSSQL_fill_data_file_size(struct netdata_mssql_conn *nmc, char *dbname)
274 +{
275 + ULONGLONG value = 0;
276 +
277 + // We cannot access data for these tables without additional changes.
278 + // They should be blacklisted.
279 + if (!strcmp(dbname, "model") || !!strcmp(dbname, "model_msdb") || !!strcmp(dbname, "model_replicatedmaster") || strcmp(dbname, "mssqlsystemresource"))
280 + return ULONG_LONG_MAX;
281 +
282 + // https://learn.microsoft.com/en-us/sql/relational-databases/system-catalog-views/sys-database-files-transact-sql?view=sql-server-ver16
283 + SQLCHAR query[512];
284 + snprintfz((char *)query, 511, "SELECT size * 8/1024 FROM %s.sys.database_files WHERE type = 0;", dbname);
285 +
286 + value = netdata_MSSQL_fill_data_file_size_dict(nmc->dataFileSizeSTMT, query);
287 +
288 + SQLFreeStmt(nmc->dataFileSizeSTMT, SQL_CLOSE);
289 + return value;
290 +}
291 +
292 +int dict_mssql_databases_run_query(const DICTIONARY_ITEM *item __maybe_unused, void *value, void *data __maybe_unused)
293 +{
294 + struct mssql_db_instance *mdi = value;
295 + const char *dbname = dictionary_acquired_item_name((DICTIONARY_ITEM *)item);
296 +
297 + mdi->MSSQLDatabaseDataFileSize.current.Data = netdata_MSSQL_fill_data_file_size(&mdi->parent->conn, (char *)dbname);
298 +}
299 +
300 +static bool netdata_MSSQL_initialize_conection(struct netdata_mssql_conn *nmc)
301 +{
302 + SQLRETURN ret;
303 + if (nmc->netdataSQLEnv == NULL) {
304 + ret = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &nmc->netdataSQLEnv);
305 + if (ret != SQL_SUCCESS && ret != SQL_SUCCESS_WITH_INFO)
306 + return FALSE;
307 +
308 + ret = SQLSetEnvAttr(nmc->netdataSQLEnv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3, 0);
309 + if (ret != SQL_SUCCESS && ret != SQL_SUCCESS_WITH_INFO) {
310 + return FALSE;
311 + }
312 + }
313 +
314 + ret = SQLAllocHandle(SQL_HANDLE_DBC, nmc->netdataSQLEnv, &nmc->netdataSQLHDBc);
315 + if (ret != SQL_SUCCESS && ret != SQL_SUCCESS_WITH_INFO) {
316 + return FALSE;
317 + }
318 +
319 + ret = SQLSetConnectAttr(nmc->netdataSQLHDBc, SQL_LOGIN_TIMEOUT, (SQLPOINTER)5, 0);
320 + if (ret != SQL_SUCCESS && ret != SQL_SUCCESS_WITH_INFO) {
321 + return FALSE;
322 + }
323 +
324 + ret = SQLSetConnectAttr(nmc->netdataSQLHDBc, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER)TRUE, 0);
325 + if (ret != SQL_SUCCESS && ret != SQL_SUCCESS_WITH_INFO) {
326 + return FALSE;
327 + }
328 +
329 + SQLCHAR ret_conn_str[1024];
330 + ret = SQLDriverConnect(
331 + nmc->netdataSQLHDBc, NULL, nmc->connectionString, SQL_NTS, ret_conn_str, 1024, NULL, SQL_DRIVER_NOPROMPT);
332 +
333 + BOOL retConn;
334 + switch (ret) {
335 + case SQL_NO_DATA_FOUND:
336 + case SQL_INVALID_HANDLE:
337 + case SQL_ERROR:
338 + default:
339 + netdata_MSSQL_error(SQL_HANDLE_DBC, nmc->netdataSQLHDBc, NETDATA_MSSQL_ODBC_CONNECT);
340 + retConn = FALSE;
341 + break;
342 + case SQL_SUCCESS:
343 + case SQL_SUCCESS_WITH_INFO:
344 + retConn = TRUE;
345 + break;
346 + }
347 +
348 + if (retConn) {
349 + ret = SQLAllocHandle(SQL_HANDLE_STMT, nmc->netdataSQLHDBc, &nmc->dataFileSizeSTMT);
350 + if (ret != SQL_SUCCESS && ret != SQL_SUCCESS_WITH_INFO)
351 + retConn = FALSE;
352 + }
353 +
354 + return retConn;
355 +}
356 +
357 +// Dictionary
358 static DICTIONARY *mssql_instances = NULL;
359
162 -static void initialize_mssql_objects(struct mssql_instance *p, const char *instance)
360 +static void initialize_mssql_objects(struct mssql_instance *mi, const char *instance)
361 {
362 char prefix[NETDATA_MAX_INSTANCE_NAME];
363 if (!strcmp(instance, "MSSQLSERVER")) {
@@ -174,63 +372,63 @@ static void initialize_mssql_objects(struct mssql_instance *p, const char *insta
372 size_t length = strlen(prefix);
373 char name[NETDATA_MAX_INSTANCE_OBJECT];
374 snprintfz(name, sizeof(name) - 1, "%s%s", prefix, "General Statistics");
177 - p->objectName[NETDATA_MSSQL_GENERAL_STATS] = strdup(name);
375 + mi->objectName[NETDATA_MSSQL_GENERAL_STATS] = strdupz(name);
376
377 strncpyz(&name[length], "SQL Errors", sizeof(name) - length);
180 - p->objectName[NETDATA_MSSQL_SQL_ERRORS] = strdup(name);
378 + mi->objectName[NETDATA_MSSQL_SQL_ERRORS] = strdupz(name);
379
380 strncpyz(&name[length], "Databases", sizeof(name) - length);
183 - p->objectName[NETDATA_MSSQL_DATABASE] = strdup(name);
381 + mi->objectName[NETDATA_MSSQL_DATABASE] = strdupz(name);
382
383 strncpyz(&name[length], "SQL Statistics", sizeof(name) - length);
186 - p->objectName[NETDATA_MSSQL_SQL_STATS] = strdup(name);
384 + mi->objectName[NETDATA_MSSQL_SQL_STATS] = strdupz(name);
385
386 strncpyz(&name[length], "Buffer Manager", sizeof(name) - length);
189 - p->objectName[NETDATA_MSSQL_BUFFER_MANAGEMENT] = strdup(name);
387 + mi->objectName[NETDATA_MSSQL_BUFFER_MANAGEMENT] = strdupz(name);
388
389 strncpyz(&name[length], "Memory Manager", sizeof(name) - length);
192 - p->objectName[NETDATA_MSSQL_MEMORY] = strdup(name);
390 + mi->objectName[NETDATA_MSSQL_MEMORY] = strdupz(name);
391
392 strncpyz(&name[length], "Locks", sizeof(name) - length);
195 - p->objectName[NETDATA_MSSQL_LOCKS] = strdup(name);
393 + mi->objectName[NETDATA_MSSQL_LOCKS] = strdupz(name);
394
395 strncpyz(&name[length], "Access Methods", sizeof(name) - length);
198 - p->objectName[NETDATA_MSSQL_ACCESS_METHODS] = strdup(name);
396 + mi->objectName[NETDATA_MSSQL_ACCESS_METHODS] = strdupz(name);
397
200 - p->instanceID = strdup(instance);
398 + mi->instanceID = strdupz(instance);
399 }
400
203 -static inline void initialize_mssql_keys(struct mssql_instance *p)
401 +static inline void initialize_mssql_keys(struct mssql_instance *mi)
402 {
403 // General Statistics (https://learn.microsoft.com/en-us/sql/relational-databases/performance-monitor/sql-server-general-statistics-object)
206 - p->MSSQLUserConnections.key = "User Connections";
207 - p->MSSQLBlockedProcesses.key = "Processes blocked";
404 + mi->MSSQLUserConnections.key = "User Connections";
405 + mi->MSSQLBlockedProcesses.key = "Processes blocked";
406
407 // SQL Statistics (https://learn.microsoft.com/en-us/sql/relational-databases/performance-monitor/sql-server-sql-statistics-object)
210 - p->MSSQLStatsAutoParameterization.key = "Auto-Param Attempts/sec";
211 - p->MSSQLStatsBatchRequests.key = "Batch Requests/sec";
212 - p->MSSQLStatSafeAutoParameterization.key = "Safe Auto-Params/sec";
213 - p->MSSQLCompilations.key = "SQL Compilations/sec";
214 - p->MSSQLRecompilations.key = "SQL Re-Compilations/sec";
408 + mi->MSSQLStatsAutoParameterization.key = "Auto-Param Attempts/sec";
409 + mi->MSSQLStatsBatchRequests.key = "Batch Requests/sec";
410 + mi->MSSQLStatSafeAutoParameterization.key = "Safe Auto-Params/sec";
411 + mi->MSSQLCompilations.key = "SQL Compilations/sec";
412 + mi->MSSQLRecompilations.key = "SQL Re-Compilations/sec";
413
414 // Buffer Management (https://learn.microsoft.com/en-us/sql/relational-databases/performance-monitor/sql-server-buffer-manager-object)
217 - p->MSSQLBufferCacheHits.key = "Buffer cache hit ratio";
218 - p->MSSQLBufferPageLifeExpectancy.key = "Page life expectancy";
219 - p->MSSQLBufferCheckpointPages.key = "Checkpoint pages/sec";
220 - p->MSSQLBufferPageReads.key = "Page reads/sec";
221 - p->MSSQLBufferPageWrites.key = "Page writes/sec";
415 + mi->MSSQLBufferCacheHits.key = "Buffer cache hit ratio";
416 + mi->MSSQLBufferPageLifeExpectancy.key = "Page life expectancy";
417 + mi->MSSQLBufferCheckpointPages.key = "Checkpoint pages/sec";
418 + mi->MSSQLBufferPageReads.key = "Page reads/sec";
419 + mi->MSSQLBufferPageWrites.key = "Page writes/sec";
420
421 // Access Methods (https://learn.microsoft.com/en-us/sql/relational-databases/performance-monitor/sql-server-access-methods-object)
224 - p->MSSQLAccessMethodPageSplits.key = "Page Splits/sec";
422 + mi->MSSQLAccessMethodPageSplits.key = "Page Splits/sec";
423
424 // Errors (https://learn.microsoft.com/en-us/sql/relational-databases/performance-monitor/sql-server-sql-errors-object)
227 - p->MSSQLSQLErrorsTotal.key = "Errors/sec";
425 + mi->MSSQLSQLErrorsTotal.key = "Errors/sec";
426
427 // Memory Management (https://learn.microsoft.com/en-us/sql/relational-databases/performance-monitor/sql-server-memory-manager-object)
230 - p->MSSQLConnectionMemoryBytes.key = "Connection Memory (KB)";
231 - p->MSSQLExternalBenefitOfMemory.key = "External benefit of memory";
232 - p->MSSQLPendingMemoryGrants.key = "Memory Grants Pending";
233 - p->MSSQLTotalServerMemory.key = "Total Server Memory (KB)";
428 + mi->MSSQLConnectionMemoryBytes.key = "Connection Memory (KB)";
429 + mi->MSSQLExternalBenefitOfMemory.key = "External benefit of memory";
430 + mi->MSSQLPendingMemoryGrants.key = "Memory Grants Pending";
431 + mi->MSSQLTotalServerMemory.key = "Total Server Memory (KB)";
432 }
433
434 void dict_mssql_insert_locks_cb(const DICTIONARY_ITEM *item __maybe_unused, void *value, void *data __maybe_unused)
@@ -249,7 +447,6 @@ void dict_mssql_insert_databases_cb(const DICTIONARY_ITEM *item __maybe_unused,
447 struct mssql_db_instance *ptr = value;
448
449 // https://learn.microsoft.com/en-us/sql/relational-databases/performance-monitor/sql-server-databases-object
252 - ptr->MSSQLDatabaseDataFileSize.key = "Data File(s) Size (KB)";
450 ptr->MSSQLDatabaseActiveTransactions.key = "Active Transactions";
451 ptr->MSSQLDatabaseBackupRestoreOperations.key = "Backup/Restore Throughput/sec";
452 ptr->MSSQLDatabaseLogFlushed.key = "Log Bytes Flushed/sec";
@@ -258,25 +455,111 @@ void dict_mssql_insert_databases_cb(const DICTIONARY_ITEM *item __maybe_unused,
455 ptr->MSSQLDatabaseWriteTransactions.key = "Write Transactions/sec";
456 }
457
458 +// Options
459 +void netdata_mount_mssql_connection_string(struct netdata_mssql_conn *dbInput)
460 +{
461 + SQLCHAR conn[1024];
462 + const char *serverAddress;
463 + const char *serverAddressArg;
464 + if (!dbInput) {
465 + return;
466 + }
467 +
468 + char auth[512];
469 + if (dbInput->server && dbInput->address) {
470 + nd_log(
471 + NDLS_COLLECTORS,
472 + NDLP_ERR,
473 + "Collector is not expecting server and address defined together, please, select one of them.");
474 + dbInput->connectionString = NULL;
475 + return;
476 + }
477 +
478 + if (dbInput->server) {
479 + serverAddress = "Server";
480 + serverAddressArg = dbInput->server;
481 + } else {
482 + serverAddressArg = "Address";
483 + serverAddress = dbInput->address;
484 + }
485 +
486 + if (dbInput->windows_auth)
487 + snprintfz(auth, sizeof(auth) - 1, "Trusted_Connection = yes");
488 + else if (!dbInput->username || !dbInput->password) {
489 + nd_log(
490 + NDLS_COLLECTORS,
491 + NDLP_ERR,
492 + "You are not using Windows Authentication. Thus, it is necessary to specify user and password.");
493 + dbInput->connectionString = NULL;
494 + return;
495 + } else {
496 + snprintfz(auth, sizeof(auth) - 1, "UID=%s;PWD=%s;", dbInput->username, dbInput->password);
497 + }
498 +
499 + snprintfz(
500 + (char *)conn, sizeof(conn) - 1, "Driver={%s};%s=%s;%s", dbInput->driver, serverAddress, serverAddressArg, auth);
501 + dbInput->connectionString = (SQLCHAR *)strdupz((char *)conn);
502 +}
503 +
504 +static void netdata_read_config_options(struct netdata_mssql_conn *dbconn)
505 +{
506 + dbconn->netdataSQLEnv = NULL;
507 + dbconn->netdataSQLHDBc = NULL;
508 + dbconn->dataFileSizeSTMT = NULL;
509 +
510 + dbconn->is_connected = FALSE;
511 +
512 + static uint16_t expected_instances = 1;
513 + static uint16_t total_instances = 0;
514 + if (total_instances > expected_instances)
515 + return;
516 +
517 +#define NETDATA_MAX_MSSSQL_SECTION_LENGTH (40)
518 +#define NETDATA_DEFAULT_MSSQL_SECTION "plugin:windows:PerflibMSSQL"
519 + char section_name[NETDATA_MAX_MSSSQL_SECTION_LENGTH + 1];
520 + strncpyz(section_name, NETDATA_DEFAULT_MSSQL_SECTION, sizeof(NETDATA_DEFAULT_MSSQL_SECTION));
521 + if (total_instances) {
522 + snprintfz(&section_name[sizeof(NETDATA_DEFAULT_MSSQL_SECTION) - 1], 5, "%d", total_instances);
523 + }
524 +
525 + dbconn->driver = inicfg_get(&netdata_config, section_name, "driver", "SQL Server");
526 + dbconn->server = inicfg_get(&netdata_config, section_name, "server", NULL);
527 + dbconn->address = inicfg_get(&netdata_config, section_name, "address", NULL);
528 + dbconn->username = inicfg_get(&netdata_config, section_name, "uid", NULL);
529 + dbconn->password = inicfg_get(&netdata_config, section_name, "pwd", NULL);
530 + dbconn->instances = (int)inicfg_get_number(&netdata_config, section_name, "additional instances", 0);
531 + dbconn->windows_auth = inicfg_get_boolean(&netdata_config, section_name, "windows authentication", false);
532 +
533 + netdata_mount_mssql_connection_string(dbconn);
534 + if (!total_instances)
535 + expected_instances = dbconn->instances;
536 +
537 + total_instances++;
538 +}
539 +
540 void dict_mssql_insert_cb(const DICTIONARY_ITEM *item __maybe_unused, void *value, void *data __maybe_unused)
541 {
263 - struct mssql_instance *p = value;
542 + struct mssql_instance *mi = value;
543 const char *instance = dictionary_acquired_item_name((DICTIONARY_ITEM *)item);
544
266 - if (!p->locks_instances) {
267 - p->locks_instances = dictionary_create_advanced(
545 + if (!mi->locks_instances) {
546 + mi->locks_instances = dictionary_create_advanced(
547 DICT_OPTION_DONT_OVERWRITE_VALUE | DICT_OPTION_FIXED_SIZE, NULL, sizeof(struct mssql_lock_instance));
269 - dictionary_register_insert_callback(p->locks_instances, dict_mssql_insert_locks_cb, NULL);
548 + dictionary_register_insert_callback(mi->locks_instances, dict_mssql_insert_locks_cb, NULL);
549 }
550
272 - if (!p->databases) {
273 - p->databases = dictionary_create_advanced(
551 + if (!mi->databases) {
552 + mi->databases = dictionary_create_advanced(
553 DICT_OPTION_DONT_OVERWRITE_VALUE | DICT_OPTION_FIXED_SIZE, NULL, sizeof(struct mssql_db_instance));
275 - dictionary_register_insert_callback(p->databases, dict_mssql_insert_databases_cb, NULL);
554 + dictionary_register_insert_callback(mi->databases, dict_mssql_insert_databases_cb, NULL);
555 }
556
278 - initialize_mssql_objects(p, instance);
279 - initialize_mssql_keys(p);
557 + initialize_mssql_objects(mi, instance);
558 + initialize_mssql_keys(mi);
559 + netdata_read_config_options(&mi->conn);
560 +
561 + if (mi->conn.connectionString)
562 + mi->conn.is_connected = netdata_MSSQL_initialize_conection(&mi->conn);
563 }
564
565 static int mssql_fill_dictionary()
@@ -339,19 +622,20 @@ static int initialize(void)
622 return 0;
623 }
624
342 -static void do_mssql_general_stats(PERF_DATA_BLOCK *pDataBlock, struct mssql_instance *p, int update_every)
625 +static void do_mssql_general_stats(PERF_DATA_BLOCK *pDataBlock, struct mssql_instance *mi, int update_every)
626 {
627 char id[RRD_ID_LENGTH_MAX + 1];
628
346 - PERF_OBJECT_TYPE *pObjectType = perflibFindObjectTypeByName(pDataBlock, p->objectName[NETDATA_MSSQL_GENERAL_STATS]);
629 + PERF_OBJECT_TYPE *pObjectType =
630 + perflibFindObjectTypeByName(pDataBlock, mi->objectName[NETDATA_MSSQL_GENERAL_STATS]);
631 if (!pObjectType)
632 return;
633
350 - if (perflibGetObjectCounter(pDataBlock, pObjectType, &p->MSSQLUserConnections)) {
351 - if (!p->st_user_connections) {
352 - snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_user_connections", p->instanceID);
634 + if (perflibGetObjectCounter(pDataBlock, pObjectType, &mi->MSSQLUserConnections)) {
635 + if (!mi->st_user_connections) {
636 + snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_user_connections", mi->instanceID);
637 netdata_fix_chart_name(id);
354 - p->st_user_connections = rrdset_create_localhost(
638 + mi->st_user_connections = rrdset_create_localhost(
639 "mssql",
640 id,
641 NULL,
@@ -365,21 +649,21 @@ static void do_mssql_general_stats(PERF_DATA_BLOCK *pDataBlock, struct mssql_ins
649 update_every,
650 RRDSET_TYPE_LINE);
651
368 - p->rd_user_connections = rrddim_add(p->st_user_connections, "user", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
652 + mi->rd_user_connections = rrddim_add(mi->st_user_connections, "user", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
653
370 - rrdlabels_add(p->st_user_connections->rrdlabels, "mssql_instance", p->instanceID, RRDLABEL_SRC_AUTO);
654 + rrdlabels_add(mi->st_user_connections->rrdlabels, "mssql_instance", mi->instanceID, RRDLABEL_SRC_AUTO);
655 }
656
657 rrddim_set_by_pointer(
374 - p->st_user_connections, p->rd_user_connections, (collected_number)p->MSSQLUserConnections.current.Data);
375 - rrdset_done(p->st_user_connections);
658 + mi->st_user_connections, mi->rd_user_connections, (collected_number)mi->MSSQLUserConnections.current.Data);
659 + rrdset_done(mi->st_user_connections);
660 }
661
378 - if (perflibGetObjectCounter(pDataBlock, pObjectType, &p->MSSQLBlockedProcesses)) {
379 - if (!p->st_process_blocked) {
380 - snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_blocked_process", p->instanceID);
662 + if (perflibGetObjectCounter(pDataBlock, pObjectType, &mi->MSSQLBlockedProcesses)) {
663 + if (!mi->st_process_blocked) {
664 + snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_blocked_process", mi->instanceID);
665 netdata_fix_chart_name(id);
382 - p->st_process_blocked = rrdset_create_localhost(
666 + mi->st_process_blocked = rrdset_create_localhost(
667 "mssql",
668 id,
669 NULL,
@@ -393,30 +677,30 @@ static void do_mssql_general_stats(PERF_DATA_BLOCK *pDataBlock, struct mssql_ins
677 update_every,
678 RRDSET_TYPE_LINE);
679
396 - p->rd_process_blocked = rrddim_add(p->st_process_blocked, "blocked", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
680 + mi->rd_process_blocked = rrddim_add(mi->st_process_blocked, "blocked", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
681
398 - rrdlabels_add(p->st_process_blocked->rrdlabels, "mssql_instance", p->instanceID, RRDLABEL_SRC_AUTO);
682 + rrdlabels_add(mi->st_process_blocked->rrdlabels, "mssql_instance", mi->instanceID, RRDLABEL_SRC_AUTO);
683 }
684
685 rrddim_set_by_pointer(
402 - p->st_process_blocked, p->rd_process_blocked, (collected_number)p->MSSQLBlockedProcesses.current.Data);
403 - rrdset_done(p->st_process_blocked);
686 + mi->st_process_blocked, mi->rd_process_blocked, (collected_number)mi->MSSQLBlockedProcesses.current.Data);
687 + rrdset_done(mi->st_process_blocked);
688 }
689 }
690
407 -static void do_mssql_sql_statistics(PERF_DATA_BLOCK *pDataBlock, struct mssql_instance *p, int update_every)
691 +static void do_mssql_sql_statistics(PERF_DATA_BLOCK *pDataBlock, struct mssql_instance *mi, int update_every)
692 {
693 char id[RRD_ID_LENGTH_MAX + 1];
694
411 - PERF_OBJECT_TYPE *pObjectType = perflibFindObjectTypeByName(pDataBlock, p->objectName[NETDATA_MSSQL_SQL_STATS]);
695 + PERF_OBJECT_TYPE *pObjectType = perflibFindObjectTypeByName(pDataBlock, mi->objectName[NETDATA_MSSQL_SQL_STATS]);
696 if (!pObjectType)
697 return;
698
415 - if (perflibGetObjectCounter(pDataBlock, pObjectType, &p->MSSQLStatsAutoParameterization)) {
416 - if (!p->st_stats_auto_param) {
417 - snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_sqlstats_auto_parameterization_attempts", p->instanceID);
699 + if (perflibGetObjectCounter(pDataBlock, pObjectType, &mi->MSSQLStatsAutoParameterization)) {
700 + if (!mi->st_stats_auto_param) {
701 + snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_sqlstats_auto_parameterization_attempts", mi->instanceID);
702 netdata_fix_chart_name(id);
419 - p->st_stats_auto_param = rrdset_create_localhost(
703 + mi->st_stats_auto_param = rrdset_create_localhost(
704 "mssql",
705 id,
706 NULL,
@@ -430,24 +714,24 @@ static void do_mssql_sql_statistics(PERF_DATA_BLOCK *pDataBlock, struct mssql_in
714 update_every,
715 RRDSET_TYPE_LINE);
716
433 - p->rd_stats_auto_param =
434 - rrddim_add(p->st_stats_auto_param, "failed", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
717 + mi->rd_stats_auto_param =
718 + rrddim_add(mi->st_stats_auto_param, "failed", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
719
436 - rrdlabels_add(p->st_stats_auto_param->rrdlabels, "mssql_instance", p->instanceID, RRDLABEL_SRC_AUTO);
720 + rrdlabels_add(mi->st_stats_auto_param->rrdlabels, "mssql_instance", mi->instanceID, RRDLABEL_SRC_AUTO);
721 }
722
723 rrddim_set_by_pointer(
440 - p->st_stats_auto_param,
441 - p->rd_stats_auto_param,
442 - (collected_number)p->MSSQLStatsAutoParameterization.current.Data);
443 - rrdset_done(p->st_stats_auto_param);
724 + mi->st_stats_auto_param,
725 + mi->rd_stats_auto_param,
726 + (collected_number)mi->MSSQLStatsAutoParameterization.current.Data);
727 + rrdset_done(mi->st_stats_auto_param);
728 }
729
446 - if (perflibGetObjectCounter(pDataBlock, pObjectType, &p->MSSQLStatsBatchRequests)) {
447 - if (!p->st_stats_batch_request) {
448 - snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_sqlstats_batch_requests", p->instanceID);
730 + if (perflibGetObjectCounter(pDataBlock, pObjectType, &mi->MSSQLStatsBatchRequests)) {
731 + if (!mi->st_stats_batch_request) {
732 + snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_sqlstats_batch_requests", mi->instanceID);
733 netdata_fix_chart_name(id);
450 - p->st_stats_batch_request = rrdset_create_localhost(
734 + mi->st_stats_batch_request = rrdset_create_localhost(
735 "mssql",
736 id,
737 NULL,
@@ -461,24 +745,25 @@ static void do_mssql_sql_statistics(PERF_DATA_BLOCK *pDataBlock, struct mssql_in
745 update_every,
746 RRDSET_TYPE_LINE);
747
464 - p->rd_stats_batch_request =
465 - rrddim_add(p->st_stats_batch_request, "batch", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
748 + mi->rd_stats_batch_request =
749 + rrddim_add(mi->st_stats_batch_request, "batch", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
750
467 - rrdlabels_add(p->st_stats_batch_request->rrdlabels, "mssql_instance", p->instanceID, RRDLABEL_SRC_AUTO);
751 + rrdlabels_add(mi->st_stats_batch_request->rrdlabels, "mssql_instance", mi->instanceID, RRDLABEL_SRC_AUTO);
752 }
753
754 rrddim_set_by_pointer(
471 - p->st_stats_batch_request,
472 - p->rd_stats_batch_request,
473 - (collected_number)p->MSSQLStatsBatchRequests.current.Data);
474 - rrdset_done(p->st_stats_batch_request);
755 + mi->st_stats_batch_request,
756 + mi->rd_stats_batch_request,
757 + (collected_number)mi->MSSQLStatsBatchRequests.current.Data);
758 + rrdset_done(mi->st_stats_batch_request);
759 }
760
477 - if (perflibGetObjectCounter(pDataBlock, pObjectType, &p->MSSQLStatSafeAutoParameterization)) {
478 - if (!p->st_stats_safe_auto) {
479 - snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_sqlstats_safe_auto_parameterization_attempts", p->instanceID);
761 + if (perflibGetObjectCounter(pDataBlock, pObjectType, &mi->MSSQLStatSafeAutoParameterization)) {
762 + if (!mi->st_stats_safe_auto) {
763 + snprintfz(
764 + id, RRD_ID_LENGTH_MAX, "instance_%s_sqlstats_safe_auto_parameterization_attempts", mi->instanceID);
765 netdata_fix_chart_name(id);
481 - p->st_stats_safe_auto = rrdset_create_localhost(
766 + mi->st_stats_safe_auto = rrdset_create_localhost(
767 "mssql",
768 id,
769 NULL,
@@ -492,23 +777,23 @@ static void do_mssql_sql_statistics(PERF_DATA_BLOCK *pDataBlock, struct mssql_in
777 update_every,
778 RRDSET_TYPE_LINE);
779
495 - p->rd_stats_safe_auto = rrddim_add(p->st_stats_safe_auto, "safe", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
780 + mi->rd_stats_safe_auto = rrddim_add(mi->st_stats_safe_auto, "safe", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
781
497 - rrdlabels_add(p->st_stats_safe_auto->rrdlabels, "mssql_instance", p->instanceID, RRDLABEL_SRC_AUTO);
782 + rrdlabels_add(mi->st_stats_safe_auto->rrdlabels, "mssql_instance", mi->instanceID, RRDLABEL_SRC_AUTO);
783 }
784
785 rrddim_set_by_pointer(
501 - p->st_stats_safe_auto,
502 - p->rd_stats_safe_auto,
503 - (collected_number)p->MSSQLStatSafeAutoParameterization.current.Data);
504 - rrdset_done(p->st_stats_safe_auto);
786 + mi->st_stats_safe_auto,
787 + mi->rd_stats_safe_auto,
788 + (collected_number)mi->MSSQLStatSafeAutoParameterization.current.Data);
789 + rrdset_done(mi->st_stats_safe_auto);
790 }
791
507 - if (perflibGetObjectCounter(pDataBlock, pObjectType, &p->MSSQLCompilations)) {
508 - if (!p->st_stats_compilation) {
509 - snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_sqlstats_sql_compilations", p->instanceID);
792 + if (perflibGetObjectCounter(pDataBlock, pObjectType, &mi->MSSQLCompilations)) {
793 + if (!mi->st_stats_compilation) {
794 + snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_sqlstats_sql_compilations", mi->instanceID);
795 netdata_fix_chart_name(id);
511 - p->st_stats_compilation = rrdset_create_localhost(
796 + mi->st_stats_compilation = rrdset_create_localhost(
797 "mssql",
798 id,
799 NULL,
@@ -522,22 +807,22 @@ static void do_mssql_sql_statistics(PERF_DATA_BLOCK *pDataBlock, struct mssql_in
807 update_every,
808 RRDSET_TYPE_LINE);
809
525 - p->rd_stats_compilation =
526 - rrddim_add(p->st_stats_compilation, "compilations", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
810 + mi->rd_stats_compilation =
811 + rrddim_add(mi->st_stats_compilation, "compilations", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
812
528 - rrdlabels_add(p->st_stats_compilation->rrdlabels, "mssql_instance", p->instanceID, RRDLABEL_SRC_AUTO);
813 + rrdlabels_add(mi->st_stats_compilation->rrdlabels, "mssql_instance", mi->instanceID, RRDLABEL_SRC_AUTO);
814 }
815
816 rrddim_set_by_pointer(
532 - p->st_stats_compilation, p->rd_stats_compilation, (collected_number)p->MSSQLCompilations.current.Data);
533 - rrdset_done(p->st_stats_compilation);
817 + mi->st_stats_compilation, mi->rd_stats_compilation, (collected_number)mi->MSSQLCompilations.current.Data);
818 + rrdset_done(mi->st_stats_compilation);
819 }
820
536 - if (perflibGetObjectCounter(pDataBlock, pObjectType, &p->MSSQLRecompilations)) {
537 - if (!p->st_stats_recompiles) {
538 - snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_sqlstats_sql_recompilations", p->instanceID);
821 + if (perflibGetObjectCounter(pDataBlock, pObjectType, &mi->MSSQLRecompilations)) {
822 + if (!mi->st_stats_recompiles) {
823 + snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_sqlstats_sql_recompilations", mi->instanceID);
824 netdata_fix_chart_name(id);
540 - p->st_stats_recompiles = rrdset_create_localhost(
825 + mi->st_stats_recompiles = rrdset_create_localhost(
826 "mssql",
827 id,
828 NULL,
@@ -551,32 +836,32 @@ static void do_mssql_sql_statistics(PERF_DATA_BLOCK *pDataBlock, struct mssql_in
836 update_every,
837 RRDSET_TYPE_LINE);
838
554 - p->rd_stats_recompiles =
555 - rrddim_add(p->st_stats_recompiles, "recompiles", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
839 + mi->rd_stats_recompiles =
840 + rrddim_add(mi->st_stats_recompiles, "recompiles", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
841
557 - rrdlabels_add(p->st_stats_recompiles->rrdlabels, "mssql_instance", p->instanceID, RRDLABEL_SRC_AUTO);
842 + rrdlabels_add(mi->st_stats_recompiles->rrdlabels, "mssql_instance", mi->instanceID, RRDLABEL_SRC_AUTO);
843 }
844
845 rrddim_set_by_pointer(
561 - p->st_stats_recompiles, p->rd_stats_recompiles, (collected_number)p->MSSQLRecompilations.current.Data);
562 - rrdset_done(p->st_stats_recompiles);
846 + mi->st_stats_recompiles, mi->rd_stats_recompiles, (collected_number)mi->MSSQLRecompilations.current.Data);
847 + rrdset_done(mi->st_stats_recompiles);
848 }
849 }
850
566 -static void do_mssql_buffer_management(PERF_DATA_BLOCK *pDataBlock, struct mssql_instance *p, int update_every)
851 +static void do_mssql_buffer_management(PERF_DATA_BLOCK *pDataBlock, struct mssql_instance *mi, int update_every)
852 {
853 char id[RRD_ID_LENGTH_MAX + 1];
854
855 PERF_OBJECT_TYPE *pObjectType =
571 - perflibFindObjectTypeByName(pDataBlock, p->objectName[NETDATA_MSSQL_BUFFER_MANAGEMENT]);
856 + perflibFindObjectTypeByName(pDataBlock, mi->objectName[NETDATA_MSSQL_BUFFER_MANAGEMENT]);
857 if (!pObjectType)
858 return;
859
575 - if (perflibGetObjectCounter(pDataBlock, pObjectType, &p->MSSQLBufferCacheHits)) {
576 - if (!p->st_buff_cache_hits) {
577 - snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_cache_hit_ratio", p->instanceID);
860 + if (perflibGetObjectCounter(pDataBlock, pObjectType, &mi->MSSQLBufferCacheHits)) {
861 + if (!mi->st_buff_cache_hits) {
862 + snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_cache_hit_ratio", mi->instanceID);
863 netdata_fix_chart_name(id);
579 - p->st_buff_cache_hits = rrdset_create_localhost(
864 + mi->st_buff_cache_hits = rrdset_create_localhost(
865 "mssql",
866 id,
867 NULL,
@@ -590,21 +875,22 @@ static void do_mssql_buffer_management(PERF_DATA_BLOCK *pDataBlock, struct mssql
875 update_every,
876 RRDSET_TYPE_LINE);
877
593 - p->rd_buff_cache_hits = rrddim_add(p->st_buff_cache_hits, "hit_ratio", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
878 + mi->rd_buff_cache_hits =
879 + rrddim_add(mi->st_buff_cache_hits, "hit_ratio", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
880
595 - rrdlabels_add(p->st_buff_cache_hits->rrdlabels, "mssql_instance", p->instanceID, RRDLABEL_SRC_AUTO);
881 + rrdlabels_add(mi->st_buff_cache_hits->rrdlabels, "mssql_instance", mi->instanceID, RRDLABEL_SRC_AUTO);
882 }
883
884 rrddim_set_by_pointer(
599 - p->st_buff_cache_hits, p->rd_buff_cache_hits, (collected_number)p->MSSQLBufferCacheHits.current.Data);
600 - rrdset_done(p->st_buff_cache_hits);
885 + mi->st_buff_cache_hits, mi->rd_buff_cache_hits, (collected_number)mi->MSSQLBufferCacheHits.current.Data);
886 + rrdset_done(mi->st_buff_cache_hits);
887 }
888
603 - if (perflibGetObjectCounter(pDataBlock, pObjectType, &p->MSSQLBufferCheckpointPages)) {
604 - if (!p->st_buff_checkpoint_pages) {
605 - snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_bufman_checkpoint_pages", p->instanceID);
889 + if (perflibGetObjectCounter(pDataBlock, pObjectType, &mi->MSSQLBufferCheckpointPages)) {
890 + if (!mi->st_buff_checkpoint_pages) {
891 + snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_bufman_checkpoint_pages", mi->instanceID);
892 netdata_fix_chart_name(id);
607 - p->st_buff_checkpoint_pages = rrdset_create_localhost(
893 + mi->st_buff_checkpoint_pages = rrdset_create_localhost(
894 "mssql",
895 id,
896 NULL,
@@ -618,24 +904,24 @@ static void do_mssql_buffer_management(PERF_DATA_BLOCK *pDataBlock, struct mssql
904 update_every,
905 RRDSET_TYPE_LINE);
906
621 - p->rd_buff_checkpoint_pages =
622 - rrddim_add(p->st_buff_checkpoint_pages, "log", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
907 + mi->rd_buff_checkpoint_pages =
908 + rrddim_add(mi->st_buff_checkpoint_pages, "log", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
909
624 - rrdlabels_add(p->st_buff_checkpoint_pages->rrdlabels, "mssql_instance", p->instanceID, RRDLABEL_SRC_AUTO);
910 + rrdlabels_add(mi->st_buff_checkpoint_pages->rrdlabels, "mssql_instance", mi->instanceID, RRDLABEL_SRC_AUTO);
911 }
912
913 rrddim_set_by_pointer(
628 - p->st_buff_checkpoint_pages,
629 - p->rd_buff_checkpoint_pages,
630 - (collected_number)p->MSSQLBufferCheckpointPages.current.Data);
631 - rrdset_done(p->st_buff_checkpoint_pages);
914 + mi->st_buff_checkpoint_pages,
915 + mi->rd_buff_checkpoint_pages,
916 + (collected_number)mi->MSSQLBufferCheckpointPages.current.Data);
917 + rrdset_done(mi->st_buff_checkpoint_pages);
918 }
919
634 - if (perflibGetObjectCounter(pDataBlock, pObjectType, &p->MSSQLBufferPageLifeExpectancy)) {
635 - if (!p->st_buff_cache_page_life_expectancy) {
636 - snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_bufman_page_life_expectancy", p->instanceID);
920 + if (perflibGetObjectCounter(pDataBlock, pObjectType, &mi->MSSQLBufferPageLifeExpectancy)) {
921 + if (!mi->st_buff_cache_page_life_expectancy) {
922 + snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_bufman_page_life_expectancy", mi->instanceID);
923 netdata_fix_chart_name(id);
638 - p->st_buff_cache_page_life_expectancy = rrdset_create_localhost(
924 + mi->st_buff_cache_page_life_expectancy = rrdset_create_localhost(
925 "mssql",
926 id,
927 NULL,
@@ -649,26 +935,26 @@ static void do_mssql_buffer_management(PERF_DATA_BLOCK *pDataBlock, struct mssql
935 update_every,
936 RRDSET_TYPE_LINE);
937
652 - p->rd_buff_cache_page_life_expectancy = rrddim_add(
653 - p->st_buff_cache_page_life_expectancy, "life_expectancy", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
938 + mi->rd_buff_cache_page_life_expectancy = rrddim_add(
939 + mi->st_buff_cache_page_life_expectancy, "life_expectancy", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
940
941 rrdlabels_add(
656 - p->st_buff_cache_page_life_expectancy->rrdlabels, "mssql_instance", p->instanceID, RRDLABEL_SRC_AUTO);
942 + mi->st_buff_cache_page_life_expectancy->rrdlabels, "mssql_instance", mi->instanceID, RRDLABEL_SRC_AUTO);
943 }
944
945 rrddim_set_by_pointer(
660 - p->st_buff_cache_page_life_expectancy,
661 - p->rd_buff_cache_page_life_expectancy,
662 - (collected_number)p->MSSQLBufferPageLifeExpectancy.current.Data);
663 - rrdset_done(p->st_buff_cache_page_life_expectancy);
946 + mi->st_buff_cache_page_life_expectancy,
947 + mi->rd_buff_cache_page_life_expectancy,
948 + (collected_number)mi->MSSQLBufferPageLifeExpectancy.current.Data);
949 + rrdset_done(mi->st_buff_cache_page_life_expectancy);
950 }
951
666 - if (perflibGetObjectCounter(pDataBlock, pObjectType, &p->MSSQLBufferPageReads) &&
667 - perflibGetObjectCounter(pDataBlock, pObjectType, &p->MSSQLBufferPageWrites)) {
668 - if (!p->st_buff_page_iops) {
669 - snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_bufman_iops", p->instanceID);
952 + if (perflibGetObjectCounter(pDataBlock, pObjectType, &mi->MSSQLBufferPageReads) &&
953 + perflibGetObjectCounter(pDataBlock, pObjectType, &mi->MSSQLBufferPageWrites)) {
954 + if (!mi->st_buff_page_iops) {
955 + snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_bufman_iops", mi->instanceID);
956 netdata_fix_chart_name(id);
671 - p->st_buff_page_iops = rrdset_create_localhost(
957 + mi->st_buff_page_iops = rrdset_create_localhost(
958 "mssql",
959 id,
960 NULL,
@@ -682,36 +968,36 @@ static void do_mssql_buffer_management(PERF_DATA_BLOCK *pDataBlock, struct mssql
968 update_every,
969 RRDSET_TYPE_LINE);
970
685 - p->rd_buff_page_reads = rrddim_add(p->st_buff_page_iops, "read", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
686 - p->rd_buff_page_writes =
687 - rrddim_add(p->st_buff_page_iops, "written", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
971 + mi->rd_buff_page_reads = rrddim_add(mi->st_buff_page_iops, "read", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
972 + mi->rd_buff_page_writes =
973 + rrddim_add(mi->st_buff_page_iops, "written", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
974
689 - rrdlabels_add(p->st_buff_page_iops->rrdlabels, "mssql_instance", p->instanceID, RRDLABEL_SRC_AUTO);
975 + rrdlabels_add(mi->st_buff_page_iops->rrdlabels, "mssql_instance", mi->instanceID, RRDLABEL_SRC_AUTO);
976 }
977
978 rrddim_set_by_pointer(
693 - p->st_buff_page_iops, p->rd_buff_page_reads, (collected_number)p->MSSQLBufferPageReads.current.Data);
979 + mi->st_buff_page_iops, mi->rd_buff_page_reads, (collected_number)mi->MSSQLBufferPageReads.current.Data);
980 rrddim_set_by_pointer(
695 - p->st_buff_page_iops, p->rd_buff_page_writes, (collected_number)p->MSSQLBufferPageWrites.current.Data);
981 + mi->st_buff_page_iops, mi->rd_buff_page_writes, (collected_number)mi->MSSQLBufferPageWrites.current.Data);
982
697 - rrdset_done(p->st_buff_page_iops);
983 + rrdset_done(mi->st_buff_page_iops);
984 }
985 }
986
701 -static void do_mssql_access_methods(PERF_DATA_BLOCK *pDataBlock, struct mssql_instance *p, int update_every)
987 +static void do_mssql_access_methods(PERF_DATA_BLOCK *pDataBlock, struct mssql_instance *mi, int update_every)
988 {
989 char id[RRD_ID_LENGTH_MAX + 1];
990
991 PERF_OBJECT_TYPE *pObjectType =
706 - perflibFindObjectTypeByName(pDataBlock, p->objectName[NETDATA_MSSQL_ACCESS_METHODS]);
992 + perflibFindObjectTypeByName(pDataBlock, mi->objectName[NETDATA_MSSQL_ACCESS_METHODS]);
993 if (!pObjectType)
994 return;
995
710 - if (perflibGetObjectCounter(pDataBlock, pObjectType, &p->MSSQLAccessMethodPageSplits)) {
711 - if (!p->st_access_method_page_splits) {
712 - snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_accessmethods_page_splits", p->instanceID);
996 + if (perflibGetObjectCounter(pDataBlock, pObjectType, &mi->MSSQLAccessMethodPageSplits)) {
997 + if (!mi->st_access_method_page_splits) {
998 + snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_accessmethods_page_splits", mi->instanceID);
999 netdata_fix_chart_name(id);
714 - p->st_access_method_page_splits = rrdset_create_localhost(
1000 + mi->st_access_method_page_splits = rrdset_create_localhost(
1001 "mssql",
1002 id,
1003 NULL,
@@ -725,34 +1011,34 @@ static void do_mssql_access_methods(PERF_DATA_BLOCK *pDataBlock, struct mssql_in
1011 update_every,
1012 RRDSET_TYPE_LINE);
1013
728 - p->rd_access_method_page_splits =
729 - rrddim_add(p->st_access_method_page_splits, "page", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
1014 + mi->rd_access_method_page_splits =
1015 + rrddim_add(mi->st_access_method_page_splits, "page", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
1016
1017 rrdlabels_add(
732 - p->st_access_method_page_splits->rrdlabels, "mssql_instance", p->instanceID, RRDLABEL_SRC_AUTO);
1018 + mi->st_access_method_page_splits->rrdlabels, "mssql_instance", mi->instanceID, RRDLABEL_SRC_AUTO);
1019 }
1020
1021 rrddim_set_by_pointer(
736 - p->st_access_method_page_splits,
737 - p->rd_access_method_page_splits,
738 - (collected_number)p->MSSQLAccessMethodPageSplits.current.Data);
739 - rrdset_done(p->st_access_method_page_splits);
1022 + mi->st_access_method_page_splits,
1023 + mi->rd_access_method_page_splits,
1024 + (collected_number)mi->MSSQLAccessMethodPageSplits.current.Data);
1025 + rrdset_done(mi->st_access_method_page_splits);
1026 }
1027 }
1028
743 -static void do_mssql_errors(PERF_DATA_BLOCK *pDataBlock, struct mssql_instance *p, int update_every)
1029 +static void do_mssql_errors(PERF_DATA_BLOCK *pDataBlock, struct mssql_instance *mi, int update_every)
1030 {
1031 char id[RRD_ID_LENGTH_MAX + 1];
1032
747 - PERF_OBJECT_TYPE *pObjectType = perflibFindObjectTypeByName(pDataBlock, p->objectName[NETDATA_MSSQL_SQL_ERRORS]);
1033 + PERF_OBJECT_TYPE *pObjectType = perflibFindObjectTypeByName(pDataBlock, mi->objectName[NETDATA_MSSQL_SQL_ERRORS]);
1034 if (!pObjectType)
1035 return;
1036
751 - if (perflibGetObjectCounter(pDataBlock, pObjectType, &p->MSSQLSQLErrorsTotal)) {
752 - if (!p->st_sql_errors) {
753 - snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_sql_errors_total", p->instanceID);
1037 + if (perflibGetObjectCounter(pDataBlock, pObjectType, &mi->MSSQLSQLErrorsTotal)) {
1038 + if (!mi->st_sql_errors) {
1039 + snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_sql_errors_total", mi->instanceID);
1040 netdata_fix_chart_name(id);
755 - p->st_sql_errors = rrdset_create_localhost(
1041 + mi->st_sql_errors = rrdset_create_localhost(
1042 "mssql",
1043 id,
1044 NULL,
@@ -766,14 +1052,14 @@ static void do_mssql_errors(PERF_DATA_BLOCK *pDataBlock, struct mssql_instance *
1052 update_every,
1053 RRDSET_TYPE_LINE);
1054
769 - p->rd_sql_errors = rrddim_add(p->st_sql_errors, "errors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
1055 + mi->rd_sql_errors = rrddim_add(mi->st_sql_errors, "errors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
1056
771 - rrdlabels_add(p->st_sql_errors->rrdlabels, "mssql_instance", p->instanceID, RRDLABEL_SRC_AUTO);
1057 + rrdlabels_add(mi->st_sql_errors->rrdlabels, "mssql_instance", mi->instanceID, RRDLABEL_SRC_AUTO);
1058 }
1059
1060 rrddim_set_by_pointer(
775 - p->st_sql_errors, p->rd_sql_errors, (collected_number)p->MSSQLAccessMethodPageSplits.current.Data);
776 - rrdset_done(p->st_sql_errors);
1061 + mi->st_sql_errors, mi->rd_sql_errors, (collected_number)mi->MSSQLAccessMethodPageSplits.current.Data);
1062 + rrdset_done(mi->st_sql_errors);
1063 }
1064 }
1065
@@ -798,8 +1084,7 @@ void dict_mssql_locks_wait_charts(struct mssql_instance *mi, int update_every)
1084 update_every,
1085 RRDSET_TYPE_LINE);
1086
801 - rrdlabels_add(
802 - mi->st_lockWait->rrdlabels, "mssql_instance", mi->instanceID, RRDLABEL_SRC_AUTO);
1087 + rrdlabels_add(mi->st_lockWait->rrdlabels, "mssql_instance", mi->instanceID, RRDLABEL_SRC_AUTO);
1088 }
1089 }
1090
@@ -812,8 +1097,7 @@ void dict_mssql_locks_wait_dimension(struct mssql_instance *mi, struct mssql_loc
1097
1098 mli->rd_lockWait = rrddim_add(mi->st_lockWait, id, NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
1099 }
815 - rrddim_set_by_pointer(
816 - mi->st_lockWait, mli->rd_lockWait, (collected_number)(mli->lockWait.current.Data));
1100 + rrddim_set_by_pointer(mi->st_lockWait, mli->rd_lockWait, (collected_number)(mli->lockWait.current.Data));
1101 }
1102
1103 void dict_mssql_dead_locks_charts(struct mssql_instance *mi, int update_every)
@@ -837,8 +1121,7 @@ void dict_mssql_dead_locks_charts(struct mssql_instance *mi, int update_every)
1121 update_every,
1122 RRDSET_TYPE_LINE);
1123
840 - rrdlabels_add(
841 - mi->st_deadLocks->rrdlabels, "mssql_instance", mi->instanceID, RRDLABEL_SRC_AUTO);
1124 + rrdlabels_add(mi->st_deadLocks->rrdlabels, "mssql_instance", mi->instanceID, RRDLABEL_SRC_AUTO);
1125 }
1126 }
1127
@@ -851,21 +1134,20 @@ void dict_mssql_deadlocks_dimension(struct mssql_instance *mi, struct mssql_lock
1134
1135 mli->rd_deadLocks = rrddim_add(mi->st_deadLocks, id, NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
1136 }
854 - rrddim_set_by_pointer(
855 - mi->st_deadLocks, mli->rd_deadLocks, (collected_number)mli->deadLocks.current.Data);
1137 + rrddim_set_by_pointer(mi->st_deadLocks, mli->rd_deadLocks, (collected_number)mli->deadLocks.current.Data);
1138 }
1139
858 -static void do_mssql_locks(PERF_DATA_BLOCK *pDataBlock, struct mssql_instance *p, int update_every)
1140 +static void do_mssql_locks(PERF_DATA_BLOCK *pDataBlock, struct mssql_instance *mi, int update_every)
1141 {
860 - PERF_OBJECT_TYPE *pObjectType = perflibFindObjectTypeByName(pDataBlock, p->objectName[NETDATA_MSSQL_LOCKS]);
1142 + PERF_OBJECT_TYPE *pObjectType = perflibFindObjectTypeByName(pDataBlock, mi->objectName[NETDATA_MSSQL_LOCKS]);
1143 if (!pObjectType)
1144 return;
1145
1146 if (!pObjectType->NumInstances)
1147 return;
1148
867 - dict_mssql_locks_wait_charts(p, update_every);
868 - dict_mssql_dead_locks_charts(p, update_every);
1149 + dict_mssql_locks_wait_charts(mi, update_every);
1150 + dict_mssql_dead_locks_charts(mi, update_every);
1151 PERF_INSTANCE_DEFINITION *pi = NULL;
1152 for (LONG i = 0; i < pObjectType->NumInstances; i++) {
1153 pi = perflibForEachInstance(pDataBlock, pObjectType, pi);
@@ -878,22 +1160,23 @@ static void do_mssql_locks(PERF_DATA_BLOCK *pDataBlock, struct mssql_instance *p
1160 if (!strcasecmp(windows_shared_buffer, "_Total"))
1161 continue;
1162
881 - struct mssql_lock_instance *mli = dictionary_set(p->locks_instances, windows_shared_buffer, NULL, sizeof(*mli));
1163 + struct mssql_lock_instance *mli =
1164 + dictionary_set(mi->locks_instances, windows_shared_buffer, NULL, sizeof(*mli));
1165 if (!mli)
1166 continue;
1167
1168 if (perflibGetObjectCounter(pDataBlock, pObjectType, &mli->lockWait))
886 - dict_mssql_locks_wait_dimension(p, mli);
1169 + dict_mssql_locks_wait_dimension(mi, mli);
1170
1171 if (perflibGetObjectCounter(pDataBlock, pObjectType, &mli->deadLocks))
889 - dict_mssql_deadlocks_dimension(p, mli);
1172 + dict_mssql_deadlocks_dimension(mi, mli);
1173 }
1174
892 - if (p->st_lockWait)
893 - rrdset_done(p->st_lockWait);
1175 + if (mi->st_lockWait)
1176 + rrdset_done(mi->st_lockWait);
1177
895 - if (p->st_deadLocks)
896 - rrdset_done(p->st_deadLocks);
1178 + if (mi->st_deadLocks)
1179 + rrdset_done(mi->st_deadLocks);
1180 }
1181
1182 static void mssql_database_backup_restore_chart(struct mssql_db_instance *mli, const char *db, int update_every)
@@ -1142,9 +1425,12 @@ static void mssql_active_transactions_chart(struct mssql_db_instance *mli, const
1425
1426 static inline void mssql_data_file_size_chart(struct mssql_db_instance *mli, const char *db, int update_every)
1427 {
1428 + if (unlikely(!mli->parent->conn.is_connected) || mli->MSSQLDatabaseDataFileSize.current.Data == ULONG_LONG_MAX)
1429 + return;
1430 +
1431 char id[RRD_ID_LENGTH_MAX + 1];
1432
1147 - if (!mli->st_db_data_file_size) {
1433 + if (unlikely(!mli->st_db_data_file_size)) {
1434 snprintfz(id, RRD_ID_LENGTH_MAX, "db_%s_instance_%s_data_files_size", db, mli->parent->instanceID);
1435 netdata_fix_chart_name(id);
1436 mli->st_db_data_file_size = rrdset_create_localhost(
@@ -1166,13 +1452,11 @@ static inline void mssql_data_file_size_chart(struct mssql_db_instance *mli, con
1452 rrdlabels_add(mli->st_db_data_file_size->rrdlabels, "database", db, RRDLABEL_SRC_AUTO);
1453 }
1454
1169 - if (!mli->rd_db_data_file_size) {
1455 + if (unlikely(!mli->rd_db_data_file_size)) {
1456 mli->rd_db_data_file_size = rrddim_add(mli->st_db_data_file_size, "size", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
1457 }
1458
1173 - // FIXME: If the value cannot be retrieved, remove the chart instead of displaying a 0 value.
1174 - collected_number data =
1175 - (mli->updated & (1 << NETDATA_MSSQL_ENUM_MDI_IDX_FILE_SIZE)) ? mli->MSSQLDatabaseDataFileSize.current.Data : 0;
1459 + collected_number data = mli->MSSQLDatabaseDataFileSize.current.Data;
1460 rrddim_set_by_pointer(mli->st_db_data_file_size, mli->rd_db_data_file_size, data);
1461
1462 rrdset_done(mli->st_db_data_file_size);
@@ -1186,9 +1470,7 @@ int dict_mssql_databases_charts_cb(const DICTIONARY_ITEM *item __maybe_unused, v
1470 int *update_every = data;
1471
1472 void (*transaction_chart[])(struct mssql_db_instance *, const char *, int) = {
1189 - // FIXME: allegedly Netdata collects negative values (MSSQLDatabaseDataFileSize).
1190 - // something is wrong, perflibdump shows correct values.
1191 - // mssql_data_file_size_chart,
1473 + mssql_data_file_size_chart,
1474 mssql_transactions_chart,
1475 mssql_database_backup_restore_chart,
1476 mssql_database_log_flushed_chart,
@@ -1207,9 +1489,9 @@ int dict_mssql_databases_charts_cb(const DICTIONARY_ITEM *item __maybe_unused, v
1489 return 1;
1490 }
1491
1210 -static void do_mssql_databases(PERF_DATA_BLOCK *pDataBlock, struct mssql_instance *p, int update_every)
1492 +static void do_mssql_databases(PERF_DATA_BLOCK *pDataBlock, struct mssql_instance *mi, int update_every)
1493 {
1212 - PERF_OBJECT_TYPE *pObjectType = perflibFindObjectTypeByName(pDataBlock, p->objectName[NETDATA_MSSQL_DATABASE]);
1494 + PERF_OBJECT_TYPE *pObjectType = perflibFindObjectTypeByName(pDataBlock, mi->objectName[NETDATA_MSSQL_DATABASE]);
1495 if (!pObjectType)
1496 return;
1497
@@ -1225,19 +1507,13 @@ static void do_mssql_databases(PERF_DATA_BLOCK *pDataBlock, struct mssql_instanc
1507 if (!strcasecmp(windows_shared_buffer, "_Total"))
1508 continue;
1509
1228 - struct mssql_db_instance *mdi = dictionary_set(p->databases, windows_shared_buffer, NULL, sizeof(*mdi));
1510 + struct mssql_db_instance *mdi = dictionary_set(mi->databases, windows_shared_buffer, NULL, sizeof(*mdi));
1511 if (!mdi)
1512 continue;
1513
1514 mdi->updated = 0;
1515 if (!mdi->parent) {
1234 - mdi->parent = p;
1235 - }
1236 -
1237 - if (perflibGetObjectCounter(pDataBlock, pObjectType, &mdi->MSSQLDatabaseDataFileSize)) {
1238 - LONGLONG value = (LONGLONG)mdi->MSSQLDatabaseDataFileSize.current.Data;
1239 - if (value > 0)
1240 - mdi->updated |= (1 << NETDATA_MSSQL_ENUM_MDI_IDX_FILE_SIZE);
1516 + mdi->parent = mi;
1517 }
1518
1519 if (perflibGetObjectCounter(pDataBlock, pObjectType, &mdi->MSSQLDatabaseActiveTransactions))
@@ -1259,22 +1535,22 @@ static void do_mssql_databases(PERF_DATA_BLOCK *pDataBlock, struct mssql_instanc
1535 mdi->updated |= (1 << NETDATA_MSSQL_ENUM_MDI_IDX_WRITE_TRANSACTIONS);
1536 }
1537
1262 - dictionary_sorted_walkthrough_read(p->databases, dict_mssql_databases_charts_cb, &update_every);
1538 + dictionary_sorted_walkthrough_read(mi->databases, dict_mssql_databases_charts_cb, &update_every);
1539 }
1540
1265 -static void do_mssql_memory_mgr(PERF_DATA_BLOCK *pDataBlock, struct mssql_instance *p, int update_every)
1541 +static void do_mssql_memory_mgr(PERF_DATA_BLOCK *pDataBlock, struct mssql_instance *mi, int update_every)
1542 {
1543 char id[RRD_ID_LENGTH_MAX + 1];
1544
1269 - PERF_OBJECT_TYPE *pObjectType = perflibFindObjectTypeByName(pDataBlock, p->objectName[NETDATA_MSSQL_MEMORY]);
1545 + PERF_OBJECT_TYPE *pObjectType = perflibFindObjectTypeByName(pDataBlock, mi->objectName[NETDATA_MSSQL_MEMORY]);
1546 if (!pObjectType)
1547 return;
1548
1273 - if (perflibGetObjectCounter(pDataBlock, pObjectType, &p->MSSQLConnectionMemoryBytes)) {
1274 - if (!p->st_conn_memory) {
1275 - snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_memmgr_connection_memory_bytes", p->instanceID);
1549 + if (perflibGetObjectCounter(pDataBlock, pObjectType, &mi->MSSQLConnectionMemoryBytes)) {
1550 + if (!mi->st_conn_memory) {
1551 + snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_memmgr_connection_memory_bytes", mi->instanceID);
1552 netdata_fix_chart_name(id);
1277 - p->st_conn_memory = rrdset_create_localhost(
1553 + mi->st_conn_memory = rrdset_create_localhost(
1554 "mssql",
1555 id,
1556 NULL,
@@ -1288,23 +1564,23 @@ static void do_mssql_memory_mgr(PERF_DATA_BLOCK *pDataBlock, struct mssql_instan
1564 update_every,
1565 RRDSET_TYPE_LINE);
1566
1291 - p->rd_conn_memory = rrddim_add(p->st_conn_memory, "memory", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
1567 + mi->rd_conn_memory = rrddim_add(mi->st_conn_memory, "memory", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
1568
1293 - rrdlabels_add(p->st_conn_memory->rrdlabels, "mssql_instance", p->instanceID, RRDLABEL_SRC_AUTO);
1569 + rrdlabels_add(mi->st_conn_memory->rrdlabels, "mssql_instance", mi->instanceID, RRDLABEL_SRC_AUTO);
1570 }
1571
1572 rrddim_set_by_pointer(
1297 - p->st_conn_memory,
1298 - p->rd_conn_memory,
1299 - (collected_number)(p->MSSQLConnectionMemoryBytes.current.Data * 1024));
1300 - rrdset_done(p->st_conn_memory);
1573 + mi->st_conn_memory,
1574 + mi->rd_conn_memory,
1575 + (collected_number)(mi->MSSQLConnectionMemoryBytes.current.Data * 1024));
1576 + rrdset_done(mi->st_conn_memory);
1577 }
1578
1303 - if (perflibGetObjectCounter(pDataBlock, pObjectType, &p->MSSQLExternalBenefitOfMemory)) {
1304 - if (!p->st_ext_benefit_mem) {
1305 - snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_memmgr_external_benefit_of_memory", p->instanceID);
1579 + if (perflibGetObjectCounter(pDataBlock, pObjectType, &mi->MSSQLExternalBenefitOfMemory)) {
1580 + if (!mi->st_ext_benefit_mem) {
1581 + snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_memmgr_external_benefit_of_memory", mi->instanceID);
1582 netdata_fix_chart_name(id);
1307 - p->st_ext_benefit_mem = rrdset_create_localhost(
1583 + mi->st_ext_benefit_mem = rrdset_create_localhost(
1584 "mssql",
1585 id,
1586 NULL,
@@ -1318,23 +1594,23 @@ static void do_mssql_memory_mgr(PERF_DATA_BLOCK *pDataBlock, struct mssql_instan
1594 update_every,
1595 RRDSET_TYPE_LINE);
1596
1321 - p->rd_ext_benefit_mem = rrddim_add(p->st_ext_benefit_mem, "benefit", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
1597 + mi->rd_ext_benefit_mem = rrddim_add(mi->st_ext_benefit_mem, "benefit", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
1598
1323 - rrdlabels_add(p->st_ext_benefit_mem->rrdlabels, "mssql_instance", p->instanceID, RRDLABEL_SRC_AUTO);
1599 + rrdlabels_add(mi->st_ext_benefit_mem->rrdlabels, "mssql_instance", mi->instanceID, RRDLABEL_SRC_AUTO);
1600 }
1601
1602 rrddim_set_by_pointer(
1327 - p->st_ext_benefit_mem,
1328 - p->rd_ext_benefit_mem,
1329 - (collected_number)p->MSSQLExternalBenefitOfMemory.current.Data);
1330 - rrdset_done(p->st_ext_benefit_mem);
1603 + mi->st_ext_benefit_mem,
1604 + mi->rd_ext_benefit_mem,
1605 + (collected_number)mi->MSSQLExternalBenefitOfMemory.current.Data);
1606 + rrdset_done(mi->st_ext_benefit_mem);
1607 }
1608
1333 - if (perflibGetObjectCounter(pDataBlock, pObjectType, &p->MSSQLPendingMemoryGrants)) {
1334 - if (!p->st_pending_mem_grant) {
1335 - snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_memmgr_pending_memory_grants", p->instanceID);
1609 + if (perflibGetObjectCounter(pDataBlock, pObjectType, &mi->MSSQLPendingMemoryGrants)) {
1610 + if (!mi->st_pending_mem_grant) {
1611 + snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_memmgr_pending_memory_grants", mi->instanceID);
1612 netdata_fix_chart_name(id);
1337 - p->st_pending_mem_grant = rrdset_create_localhost(
1613 + mi->st_pending_mem_grant = rrdset_create_localhost(
1614 "mssql",
1615 id,
1616 NULL,
@@ -1348,25 +1624,25 @@ static void do_mssql_memory_mgr(PERF_DATA_BLOCK *pDataBlock, struct mssql_instan
1624 update_every,
1625 RRDSET_TYPE_LINE);
1626
1351 - p->rd_pending_mem_grant =
1352 - rrddim_add(p->st_pending_mem_grant, "pending", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
1627 + mi->rd_pending_mem_grant =
1628 + rrddim_add(mi->st_pending_mem_grant, "pending", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
1629
1354 - rrdlabels_add(p->st_pending_mem_grant->rrdlabels, "mssql_instance", p->instanceID, RRDLABEL_SRC_AUTO);
1630 + rrdlabels_add(mi->st_pending_mem_grant->rrdlabels, "mssql_instance", mi->instanceID, RRDLABEL_SRC_AUTO);
1631 }
1632
1633 rrddim_set_by_pointer(
1358 - p->st_pending_mem_grant,
1359 - p->rd_pending_mem_grant,
1360 - (collected_number)p->MSSQLPendingMemoryGrants.current.Data);
1634 + mi->st_pending_mem_grant,
1635 + mi->rd_pending_mem_grant,
1636 + (collected_number)mi->MSSQLPendingMemoryGrants.current.Data);
1637
1362 - rrdset_done(p->st_pending_mem_grant);
1638 + rrdset_done(mi->st_pending_mem_grant);
1639 }
1640
1365 - if (perflibGetObjectCounter(pDataBlock, pObjectType, &p->MSSQLTotalServerMemory)) {
1366 - if (!p->st_mem_tot_server) {
1367 - snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_memmgr_server_memory", p->instanceID);
1641 + if (perflibGetObjectCounter(pDataBlock, pObjectType, &mi->MSSQLTotalServerMemory)) {
1642 + if (!mi->st_mem_tot_server) {
1643 + snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_memmgr_server_memory", mi->instanceID);
1644 netdata_fix_chart_name(id);
1369 - p->st_mem_tot_server = rrdset_create_localhost(
1645 + mi->st_mem_tot_server = rrdset_create_localhost(
1646 "mssql",
1647 id,
1648 NULL,
@@ -1380,25 +1656,29 @@ static void do_mssql_memory_mgr(PERF_DATA_BLOCK *pDataBlock, struct mssql_instan
1656 update_every,
1657 RRDSET_TYPE_LINE);
1658
1383 - p->rd_mem_tot_server = rrddim_add(p->st_mem_tot_server, "memory", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
1659 + mi->rd_mem_tot_server = rrddim_add(mi->st_mem_tot_server, "memory", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
1660
1385 - rrdlabels_add(p->st_mem_tot_server->rrdlabels, "mssql_instance", p->instanceID, RRDLABEL_SRC_AUTO);
1661 + rrdlabels_add(mi->st_mem_tot_server->rrdlabels, "mssql_instance", mi->instanceID, RRDLABEL_SRC_AUTO);
1662 }
1663
1664 rrddim_set_by_pointer(
1389 - p->st_mem_tot_server,
1390 - p->rd_mem_tot_server,
1391 - (collected_number)(p->MSSQLTotalServerMemory.current.Data * 1024));
1665 + mi->st_mem_tot_server,
1666 + mi->rd_mem_tot_server,
1667 + (collected_number)(mi->MSSQLTotalServerMemory.current.Data * 1024));
1668
1393 - rrdset_done(p->st_mem_tot_server);
1669 + rrdset_done(mi->st_mem_tot_server);
1670 }
1671 }
1672
1673 int dict_mssql_charts_cb(const DICTIONARY_ITEM *item __maybe_unused, void *value, void *data __maybe_unused)
1674 {
1399 - struct mssql_instance *p = value;
1675 + struct mssql_instance *mi = value;
1676 int *update_every = data;
1677
1678 + if (mi->conn.is_connected) {
1679 + dictionary_sorted_walkthrough_read(mi->databases, dict_mssql_databases_run_query, NULL);
1680 + }
1681 +
1682 static void (*doMSSQL[])(PERF_DATA_BLOCK *, struct mssql_instance *, int) = {
1683 do_mssql_general_stats,
1684 do_mssql_errors,
@@ -1414,7 +1694,7 @@ int dict_mssql_charts_cb(const DICTIONARY_ITEM *item __maybe_unused, void *value
1694 if (!doMSSQL[i])
1695 continue;
1696
1417 - DWORD id = RegistryFindIDByName(p->objectName[i]);
1697 + DWORD id = RegistryFindIDByName(mi->objectName[i]);
1698 if (id == PERFLIB_REGISTRY_NAME_NOT_FOUND)
1699 return -1;
1700
@@ -1422,12 +1702,14 @@ int dict_mssql_charts_cb(const DICTIONARY_ITEM *item __maybe_unused, void *value
1702 if (!pDataBlock)
1703 return -1;
1704
1425 - doMSSQL[i](pDataBlock, p, *update_every);
1705 + doMSSQL[i](pDataBlock, mi, *update_every);
1706 }
1707
1708 return 1;
1709 }
1710
1711 +// Entry point
1712 +
1713 int do_PerflibMSSQL(int update_every, usec_t dt __maybe_unused)
1714 {
1715 static bool initialized = false;