master
c 1,289 lines 51.3 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 #include "windows_plugin.h"
4 #include "windows-internals.h"
5
6 struct exchange_proxy {
7 RRDSET *st_exchange_http_proxy_avg_auth_latency;
8 RRDSET *st_exchange_http_proxy_avg_cas_processing_latency;
9 RRDSET *st_exchange_http_proxy_mailbox_proxy_failure;
10 RRDSET *st_exchange_http_proxy_server_location_avg_latency;
11 RRDSET *st_exchange_http_proxy_outstanding_proxy_requests;
12 RRDSET *st_exchange_http_proxy_requests_total;
13
14 RRDDIM *rd_exchange_http_proxy_avg_auth_latency;
15 RRDDIM *rd_exchange_http_proxy_avg_cas_processing_latency;
16 RRDDIM *rd_exchange_http_proxy_mailbox_proxy_failure;
17 RRDDIM *rd_exchange_http_proxy_server_location_avg_latency;
18 RRDDIM *rd_exchange_http_proxy_outstanding_proxy_requests;
19 RRDDIM *rd_exchange_http_proxy_requests_total;
20
21 COUNTER_DATA exchangeProxyAvgAuthLatency;
22 COUNTER_DATA exchangeProxyAvgCasProcessingLatency;
23 COUNTER_DATA exchangeProxyMailboxProxyFailure;
24 COUNTER_DATA exchangeProxyMailboxServerLocator;
25 COUNTER_DATA exchangeProxyOutstandingProxy;
26 COUNTER_DATA exchangeProxyRequestsTotal;
27 };
28
29 struct exchange_workload {
30 RRDSET *st_exchange_workload_active_tasks;
31 RRDSET *st_exchange_workload_complete_tasks;
32 RRDSET *st_exchange_workload_queued_tasks;
33 RRDSET *st_exchange_workload_yielded_tasks;
34 RRDSET *st_exchange_workload_activity_status;
35
36 RRDDIM *rd_exchange_workload_active_tasks;
37 RRDDIM *rd_exchange_workload_complete_tasks;
38 RRDDIM *rd_exchange_workload_queued_tasks;
39 RRDDIM *rd_exchange_workload_yielded_tasks;
40 RRDDIM *rd_exchange_workload_activity_active_status;
41 RRDDIM *rd_exchange_workload_activity_paused_status;
42
43 COUNTER_DATA exchangeWorkloadActiveTasks;
44 COUNTER_DATA exchangeWorkloadCompleteTasks;
45 COUNTER_DATA exchangeWorkloadQueueTasks;
46 COUNTER_DATA exchangeWorkloadYieldedTasks;
47 COUNTER_DATA exchangeWorkloadActivityStatus;
48 };
49
50 struct exchange_queue {
51 RRDSET *st_exchange_queue_active_mailbox;
52 RRDSET *st_exchange_queue_external_active_remote_delivery;
53 RRDSET *st_exchange_queue_internal_active_remote_delivery;
54 RRDSET *st_exchange_queue_unreachable;
55 RRDSET *st_exchange_queue_poison;
56
57 RRDDIM *rd_exchange_queue_active_mailbox;
58 RRDDIM *rd_exchange_queue_external_active_remote_delivery;
59 RRDDIM *rd_exchange_queue_internal_active_remote_delivery;
60 RRDDIM *rd_exchange_queue_unreachable;
61 RRDDIM *rd_exchange_queue_poison;
62
63 COUNTER_DATA exchangeTransportQueuesActiveMailboxDelivery;
64 COUNTER_DATA exchangeTransportQueuesExternalActiveRemoteDelivery;
65 COUNTER_DATA exchangeTransportQueuesInternalActiveRemoteDelivery;
66 COUNTER_DATA exchangeTransportQueuesUnreachable;
67 COUNTER_DATA exchangeTransportQueuesPoison;
68 };
69
70 DICTIONARY *exchange_proxies;
71 DICTIONARY *exchange_workloads;
72 DICTIONARY *exchange_queues;
73
74 static void exchange_proxy_initialize_variables(struct exchange_proxy *ep)
75 {
76 ep->exchangeProxyAvgAuthLatency.key = "Average Authentication Latency";
77 ep->exchangeProxyAvgCasProcessingLatency.key = "Average ClientAccess Server Processing Latency";
78 ep->exchangeProxyMailboxProxyFailure.key = "Mailbox Server Proxy Failure Rate";
79 ep->exchangeProxyMailboxServerLocator.key = "MailboxServerLocator Average Latency (Moving Average)";
80 ep->exchangeProxyOutstandingProxy.key = "Outstanding Proxy Requests";
81 ep->exchangeProxyRequestsTotal.key = "Proxy Requests/Sec";
82 }
83
84 static void
85 dict_exchange_insert_proxy_cb(const DICTIONARY_ITEM *item __maybe_unused, void *value, void *data __maybe_unused)
86 {
87 struct exchange_proxy *ep = value;
88
89 exchange_proxy_initialize_variables(ep);
90 }
91
92 static void exchange_workload_initialize_variables(struct exchange_workload *ew)
93 {
94 ew->exchangeWorkloadActiveTasks.key = "ActiveTasks";
95 ew->exchangeWorkloadCompleteTasks.key = "CompletedTasks";
96 ew->exchangeWorkloadQueueTasks.key = "QueuedTasks";
97 ew->exchangeWorkloadYieldedTasks.key = "YieldedTasks";
98 ew->exchangeWorkloadActivityStatus.key = "Active";
99 }
100
101 static void
102 dict_exchange_insert_workload_cb(const DICTIONARY_ITEM *item __maybe_unused, void *value, void *data __maybe_unused)
103 {
104 struct exchange_workload *ew = value;
105
106 exchange_workload_initialize_variables(ew);
107 }
108
109 static void exchange_queue_initialize_variables(struct exchange_queue *eq)
110 {
111 eq->exchangeTransportQueuesActiveMailboxDelivery.key = "Active Mailbox Delivery Queue Length";
112 eq->exchangeTransportQueuesExternalActiveRemoteDelivery.key = "External Active Remote Delivery Queue Length";
113 eq->exchangeTransportQueuesInternalActiveRemoteDelivery.key = "Internal Active Remote Delivery Queue Length";
114 eq->exchangeTransportQueuesPoison.key = "Poison Queue Length";
115 eq->exchangeTransportQueuesUnreachable.key = "Unreachable Queue Length";
116 }
117
118 static void
119 dict_exchange_insert_queue_cb(const DICTIONARY_ITEM *item __maybe_unused, void *value, void *data __maybe_unused)
120 {
121 struct exchange_queue *eq = value;
122
123 exchange_queue_initialize_variables(eq);
124 }
125
126 static void initialize(void)
127 {
128 exchange_proxies = dictionary_create_advanced(
129 DICT_OPTION_DONT_OVERWRITE_VALUE | DICT_OPTION_FIXED_SIZE, NULL, sizeof(struct exchange_proxy));
130 dictionary_register_insert_callback(exchange_proxies, dict_exchange_insert_proxy_cb, NULL);
131
132 exchange_workloads = dictionary_create_advanced(
133 DICT_OPTION_DONT_OVERWRITE_VALUE | DICT_OPTION_FIXED_SIZE, NULL, sizeof(struct exchange_workload));
134 dictionary_register_insert_callback(exchange_workloads, dict_exchange_insert_workload_cb, NULL);
135
136 exchange_queues = dictionary_create_advanced(
137 DICT_OPTION_DONT_OVERWRITE_VALUE | DICT_OPTION_FIXED_SIZE, NULL, sizeof(struct exchange_queue));
138 dictionary_register_insert_callback(exchange_queues, dict_exchange_insert_queue_cb, NULL);
139 }
140
141 static void netdata_exchange_owa_current_unique_users(COUNTER_DATA *value, int update_every)
142 {
143 static RRDSET *st_exchange_owa_unique_users = NULL;
144 static RRDDIM *rd_exchange_owa_unique_users = NULL;
145
146 if (unlikely(!st_exchange_owa_unique_users)) {
147 st_exchange_owa_unique_users = rrdset_create_localhost(
148 "exchange",
149 "owa_current_unique_users",
150 NULL,
151 "owa",
152 "exchange.owa_current_unique_users",
153 "Unique users currently logged on to Outlook Web App",
154 "users",
155 PLUGIN_WINDOWS_NAME,
156 "PerflibExchange",
157 PRIO_EXCHANGE_OWA_UNIQUE_USERS,
158 update_every,
159 RRDSET_TYPE_LINE);
160
161 rd_exchange_owa_unique_users =
162 rrddim_add(st_exchange_owa_unique_users, "logged-in", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
163 }
164
165 rrddim_set_by_pointer(
166 st_exchange_owa_unique_users, rd_exchange_owa_unique_users, (collected_number)value->current.Data);
167 rrdset_done(st_exchange_owa_unique_users);
168 }
169
170 static void netdata_exchange_owa_request_total(COUNTER_DATA *value, int update_every)
171 {
172 static RRDSET *st_exchange_owa_request_total = NULL;
173 static RRDDIM *rd_exchange_owa_request_total = NULL;
174
175 if (unlikely(!st_exchange_owa_request_total)) {
176 st_exchange_owa_request_total = rrdset_create_localhost(
177 "exchange",
178 "owa_requests_total",
179 NULL,
180 "owa",
181 "exchange.owa_requests_total",
182 "Requests handled by Outlook Web App.",
183 "requests/s",
184 PLUGIN_WINDOWS_NAME,
185 "PerflibExchange",
186 PRIO_EXCHANGE_OWA_REQUESTS_TOTAL,
187 update_every,
188 RRDSET_TYPE_LINE);
189
190 rd_exchange_owa_request_total =
191 rrddim_add(st_exchange_owa_request_total, "handled", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
192 }
193
194 rrddim_set_by_pointer(
195 st_exchange_owa_request_total, rd_exchange_owa_request_total, (collected_number)value->current.Data);
196 rrdset_done(st_exchange_owa_request_total);
197 }
198
199 static void netdata_exchange_owa(PERF_DATA_BLOCK *pDataBlock, PERF_OBJECT_TYPE *pObjectType, int update_every)
200 {
201 static COUNTER_DATA exchangeOWACurrentUniqueUser = {.key = "Current Unique Users"};
202 static COUNTER_DATA exchangeOWARequestsTotal = {.key = "Requests/sec"};
203
204 if (perflibGetObjectCounter(pDataBlock, pObjectType, &exchangeOWACurrentUniqueUser))
205 netdata_exchange_owa_current_unique_users(&exchangeOWACurrentUniqueUser, update_every);
206
207 if (perflibGetObjectCounter(pDataBlock, pObjectType, &exchangeOWARequestsTotal))
208 netdata_exchange_owa_request_total(&exchangeOWARequestsTotal, update_every);
209 }
210
211 static void netdata_exchange_active_ping_cmd(COUNTER_DATA *value, int update_every)
212 {
213 static RRDSET *st_exchange_active_ping_cmds = NULL;
214 static RRDDIM *rd_exchange_active_ping_cmds = NULL;
215
216 if (unlikely(!st_exchange_active_ping_cmds)) {
217 st_exchange_active_ping_cmds = rrdset_create_localhost(
218 "exchange",
219 "activesync_ping_cmds_pending",
220 NULL,
221 "sync",
222 "exchange.activesync_ping_cmds_pending",
223 "Ping commands pending in queue.",
224 "commands",
225 PLUGIN_WINDOWS_NAME,
226 "PerflibExchange",
227 PRIO_EXCHANGE_ACTIVE_SYNC_PING_CMDS_PENDING,
228 update_every,
229 RRDSET_TYPE_LINE);
230
231 rd_exchange_active_ping_cmds =
232 rrddim_add(st_exchange_active_ping_cmds, "pending", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
233 }
234
235 rrddim_set_by_pointer(
236 st_exchange_active_ping_cmds, rd_exchange_active_ping_cmds, (collected_number)value->current.Data);
237 rrdset_done(st_exchange_active_ping_cmds);
238 }
239
240 static void netdata_exchange_active_requests(COUNTER_DATA *value, int update_every)
241 {
242 static RRDSET *st_exchange_received_requests = NULL;
243 static RRDDIM *rd_exchange_received_requests = NULL;
244
245 if (unlikely(!st_exchange_received_requests)) {
246 st_exchange_received_requests = rrdset_create_localhost(
247 "exchange",
248 "activesync_requests",
249 NULL,
250 "sync",
251 "exchange.activesync_requests",
252 "HTTP requests received from ASP.NET.",
253 "requests/s",
254 PLUGIN_WINDOWS_NAME,
255 "PerflibExchange",
256 PRIO_EXCHANGE_ACTIVE_SYNC_REQUESTS,
257 update_every,
258 RRDSET_TYPE_LINE);
259
260 rd_exchange_received_requests =
261 rrddim_add(st_exchange_received_requests, "received", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
262 }
263
264 rrddim_set_by_pointer(
265 st_exchange_received_requests, rd_exchange_received_requests, (collected_number)value->current.Data);
266 rrdset_done(st_exchange_received_requests);
267 }
268
269 static void netdata_exchange_sync_cmds(COUNTER_DATA *value, int update_every)
270 {
271 static RRDSET *st_exchange_sync_cmds = NULL;
272 static RRDDIM *rd_exchange_sync_cmds = NULL;
273
274 if (unlikely(!st_exchange_sync_cmds)) {
275 st_exchange_sync_cmds = rrdset_create_localhost(
276 "exchange",
277 "activesync_sync_cmds",
278 NULL,
279 "sync",
280 "exchange.activesync_sync_cmds",
281 "Sync commands processed.",
282 "commands/s",
283 PLUGIN_WINDOWS_NAME,
284 "PerflibExchange",
285 PRIO_EXCHANGE_ACTIVE_SYNC_CMDS,
286 update_every,
287 RRDSET_TYPE_LINE);
288
289 rd_exchange_sync_cmds = rrddim_add(st_exchange_sync_cmds, "processed", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
290 }
291
292 rrddim_set_by_pointer(st_exchange_sync_cmds, rd_exchange_sync_cmds, (collected_number)value->current.Data);
293 rrdset_done(st_exchange_sync_cmds);
294 }
295
296 static void netdata_exchange_active_sync(PERF_DATA_BLOCK *pDataBlock, PERF_OBJECT_TYPE *pObjectType, int update_every)
297 {
298 static COUNTER_DATA exchangePingCommands = {.key = "Ping Commands Pending"};
299 static COUNTER_DATA exchangeSyncCommands = {.key = "Sync Commands/sec"};
300 static COUNTER_DATA exchangeActiveRequests = {.key = "Requests/sec"};
301
302 if (perflibGetObjectCounter(pDataBlock, pObjectType, &exchangePingCommands))
303 netdata_exchange_active_ping_cmd(&exchangePingCommands, update_every);
304
305 if (perflibGetObjectCounter(pDataBlock, pObjectType, &exchangeSyncCommands))
306 netdata_exchange_sync_cmds(&exchangeSyncCommands, update_every);
307
308 if (perflibGetObjectCounter(pDataBlock, pObjectType, &exchangeActiveRequests))
309 netdata_exchange_active_requests(&exchangeActiveRequests, update_every);
310 }
311
312 static void netdata_exchange_auto_discover(PERF_DATA_BLOCK *pDataBlock, PERF_OBJECT_TYPE *pObjectType, int update_every)
313 {
314 static COUNTER_DATA exchangeAutoDiscoverRequestsTotal = {.key = "Requests/sec"};
315
316 static RRDSET *st_exchange_auto_discover_request_total = NULL;
317 static RRDDIM *rd_exchange_auto_discover_request_total = NULL;
318
319 if (!perflibGetObjectCounter(pDataBlock, pObjectType, &exchangeAutoDiscoverRequestsTotal)) {
320 return;
321 }
322
323 if (unlikely(!st_exchange_auto_discover_request_total)) {
324 st_exchange_auto_discover_request_total = rrdset_create_localhost(
325 "exchange",
326 "autodiscover_requests",
327 NULL,
328 "requests",
329 "exchange.autodiscover_requests",
330 "Autodiscover service requests processed.",
331 "requests/s",
332 PLUGIN_WINDOWS_NAME,
333 "PerflibExchange",
334 PRIO_EXCHANGE_AUTO_DISCOVER_REQUESTS,
335 update_every,
336 RRDSET_TYPE_LINE);
337
338 rd_exchange_auto_discover_request_total =
339 rrddim_add(st_exchange_auto_discover_request_total, "processed", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
340 }
341
342 rrddim_set_by_pointer(
343 st_exchange_auto_discover_request_total,
344 rd_exchange_auto_discover_request_total,
345 (collected_number)exchangeAutoDiscoverRequestsTotal.current.Data);
346 rrdset_done(st_exchange_auto_discover_request_total);
347 }
348
349 static void
350 netdata_exchange_availability_service(PERF_DATA_BLOCK *pDataBlock, PERF_OBJECT_TYPE *pObjectType, int update_every)
351 {
352 static COUNTER_DATA exchangeAvailServiceRequests = {.key = "Availability Requests (sec)"};
353
354 static RRDSET *st_exchange_avail_service_requests = NULL;
355 static RRDDIM *rd_exchange_avail_service_requests = NULL;
356
357 if (!perflibGetObjectCounter(pDataBlock, pObjectType, &exchangeAvailServiceRequests)) {
358 return;
359 }
360
361 if (unlikely(!st_exchange_avail_service_requests)) {
362 st_exchange_avail_service_requests = rrdset_create_localhost(
363 "exchange",
364 "avail_service_requests",
365 NULL,
366 "requests",
367 "exchange.avail_service_requests",
368 "Requests serviced.",
369 "requests/s",
370 PLUGIN_WINDOWS_NAME,
371 "PerflibExchange",
372 PRIO_EXCHANGE_AUTO_AVAILABILITY_SERVICES,
373 update_every,
374 RRDSET_TYPE_LINE);
375
376 rd_exchange_avail_service_requests =
377 rrddim_add(st_exchange_avail_service_requests, "serviced", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
378 }
379
380 rrddim_set_by_pointer(
381 st_exchange_avail_service_requests,
382 rd_exchange_avail_service_requests,
383 (collected_number)exchangeAvailServiceRequests.current.Data);
384 rrdset_done(st_exchange_avail_service_requests);
385 }
386
387 static void netdata_exchange_rpc_avg_latency(COUNTER_DATA *value, int update_every)
388 {
389 static RRDSET *st_exchange_rpc_avg_latency = NULL;
390 static RRDDIM *rd_exchange_rpc_avg_latency = NULL;
391
392 if (unlikely(!st_exchange_rpc_avg_latency)) {
393 st_exchange_rpc_avg_latency = rrdset_create_localhost(
394 "exchange",
395 "rpc_avg_latency",
396 NULL,
397 "rpc",
398 "exchange.rpc_avg_latency",
399 "Average latency.",
400 "seconds",
401 PLUGIN_WINDOWS_NAME,
402 "PerflibExchange",
403 PRIO_EXCHANGE_RPC_AVG_LATENCY,
404 update_every,
405 RRDSET_TYPE_LINE);
406
407 rd_exchange_rpc_avg_latency =
408 rrddim_add(st_exchange_rpc_avg_latency, "latency", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE);
409 }
410
411 rrddim_set_by_pointer(
412 st_exchange_rpc_avg_latency, rd_exchange_rpc_avg_latency, (collected_number)value->current.Data);
413 rrdset_done(st_exchange_rpc_avg_latency);
414 }
415
416 static void netdata_exchange_rpc_requests(COUNTER_DATA *value, int update_every)
417 {
418 static RRDSET *st_exchange_rpc_requests = NULL;
419 static RRDDIM *rd_exchange_rpc_requests = NULL;
420
421 if (unlikely(!st_exchange_rpc_requests)) {
422 st_exchange_rpc_requests = rrdset_create_localhost(
423 "exchange",
424 "rpc_requests_total",
425 NULL,
426 "rpc",
427 "exchange.rpc_requests",
428 "Clients requests currently being processed.",
429 "requests",
430 PLUGIN_WINDOWS_NAME,
431 "PerflibExchange",
432 PRIO_EXCHANGE_RPC_REQUESTS,
433 update_every,
434 RRDSET_TYPE_LINE);
435
436 rd_exchange_rpc_requests =
437 rrddim_add(st_exchange_rpc_requests, "processed", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
438 }
439
440 rrddim_set_by_pointer(st_exchange_rpc_requests, rd_exchange_rpc_requests, (collected_number)value->current.Data);
441 rrdset_done(st_exchange_rpc_requests);
442 }
443
444 static void netdata_exchange_rpc_active_user_count(COUNTER_DATA *value, int update_every)
445 {
446 static RRDSET *st_exchange_active_user_account = NULL;
447 static RRDDIM *rd_exchange_active_user_account = NULL;
448
449 if (unlikely(!st_exchange_active_user_account)) {
450 st_exchange_active_user_account = rrdset_create_localhost(
451 "exchange",
452 "rpc_active_user",
453 NULL,
454 "rpc",
455 "exchange.rpc_active_user",
456 "Active unique users in the last 2 minutes.",
457 "users",
458 PLUGIN_WINDOWS_NAME,
459 "PerflibExchange",
460 PRIO_EXCHANGE_RPC_ACTIVE_USERS_COUNT,
461 update_every,
462 RRDSET_TYPE_LINE);
463
464 rd_exchange_active_user_account =
465 rrddim_add(st_exchange_active_user_account, "active", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
466 }
467
468 rrddim_set_by_pointer(
469 st_exchange_active_user_account, rd_exchange_active_user_account, (collected_number)value->current.Data);
470 rrdset_done(st_exchange_active_user_account);
471 }
472
473 static void netdata_exchange_rpc_connection_count(COUNTER_DATA *value, int update_every)
474 {
475 static RRDSET *st_exchange_rpc_connection_count = NULL;
476 static RRDDIM *rd_exchange_rpc_connection_count = NULL;
477
478 if (unlikely(!st_exchange_rpc_connection_count)) {
479 st_exchange_rpc_connection_count = rrdset_create_localhost(
480 "exchange",
481 "rpc_connection",
482 NULL,
483 "rpc",
484 "exchange.rpc_connection",
485 "Client connections.",
486 "connections",
487 PLUGIN_WINDOWS_NAME,
488 "PerflibExchange",
489 PRIO_EXCHANGE_RPC_CONNECTION_COUNT,
490 update_every,
491 RRDSET_TYPE_LINE);
492
493 rd_exchange_rpc_connection_count =
494 rrddim_add(st_exchange_rpc_connection_count, "connections", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
495 }
496
497 rrddim_set_by_pointer(
498 st_exchange_rpc_connection_count, rd_exchange_rpc_connection_count, (collected_number)value->current.Data);
499 rrdset_done(st_exchange_rpc_connection_count);
500 }
501
502 static void netdata_exchange_rpc_op_per_sec(COUNTER_DATA *value, int update_every)
503 {
504 static RRDSET *st_exchange_rpc_opc_per_sec = NULL;
505 static RRDDIM *rd_exchange_rpc_opc_per_sec = NULL;
506
507 if (unlikely(!st_exchange_rpc_opc_per_sec)) {
508 st_exchange_rpc_opc_per_sec = rrdset_create_localhost(
509 "exchange",
510 "rpc_operations",
511 NULL,
512 "rpc",
513 "exchange.rpc_operations",
514 "RPC operations.",
515 "operations/s",
516 PLUGIN_WINDOWS_NAME,
517 "PerflibExchange",
518 PRIO_EXCHANGE_RPC_OPERATIONS_TOTAL,
519 update_every,
520 RRDSET_TYPE_LINE);
521
522 rd_exchange_rpc_opc_per_sec =
523 rrddim_add(st_exchange_rpc_opc_per_sec, "operations", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
524 }
525
526 rrddim_set_by_pointer(
527 st_exchange_rpc_opc_per_sec, rd_exchange_rpc_opc_per_sec, (collected_number)value->current.Data);
528 rrdset_done(st_exchange_rpc_opc_per_sec);
529 }
530
531 static void netdata_exchange_rpc_user_count(COUNTER_DATA *value, int update_every)
532 {
533 static RRDSET *st_exchange_rpc_user_count = NULL;
534 static RRDDIM *rd_exchange_rpc_user_count = NULL;
535
536 if (unlikely(!st_exchange_rpc_user_count)) {
537 st_exchange_rpc_user_count = rrdset_create_localhost(
538 "exchange",
539 "rpc_user",
540 NULL,
541 "rpc",
542 "exchange.rpc_user_count",
543 "RPC users.",
544 "users",
545 PLUGIN_WINDOWS_NAME,
546 "PerflibExchange",
547 PRIO_EXCHANGE_RPC_USER_COUNT,
548 update_every,
549 RRDSET_TYPE_LINE);
550
551 rd_exchange_rpc_user_count =
552 rrddim_add(st_exchange_rpc_user_count, "users", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
553 }
554
555 rrddim_set_by_pointer(
556 st_exchange_rpc_user_count, rd_exchange_rpc_user_count, (collected_number)value->current.Data);
557 rrdset_done(st_exchange_rpc_user_count);
558 }
559
560 static void netdata_exchange_rpc(PERF_DATA_BLOCK *pDataBlock, PERF_OBJECT_TYPE *pObjectType, int update_every)
561 {
562 static COUNTER_DATA exchangeRPCAveragedLatency = {.key = "RPC Averaged Latency"};
563 static COUNTER_DATA exchangeRPCRequest = {.key = "RPC Requests"};
564 static COUNTER_DATA exchangeRPCActiveUserCount = {.key = "Active User Count"};
565 static COUNTER_DATA exchangeRPCConnectionCount = {.key = "Connection Count"};
566 static COUNTER_DATA exchangeRPCOperationPerSec = {.key = "RPC Operations/sec"};
567 static COUNTER_DATA exchangeRPCUserCount = {.key = "User Count"};
568
569 if (perflibGetObjectCounter(pDataBlock, pObjectType, &exchangeRPCAveragedLatency))
570 netdata_exchange_rpc_avg_latency(&exchangeRPCAveragedLatency, update_every);
571
572 if (perflibGetObjectCounter(pDataBlock, pObjectType, &exchangeRPCRequest))
573 netdata_exchange_rpc_requests(&exchangeRPCRequest, update_every);
574
575 if (perflibGetObjectCounter(pDataBlock, pObjectType, &exchangeRPCActiveUserCount))
576 netdata_exchange_rpc_active_user_count(&exchangeRPCActiveUserCount, update_every);
577
578 if (perflibGetObjectCounter(pDataBlock, pObjectType, &exchangeRPCConnectionCount))
579 netdata_exchange_rpc_connection_count(&exchangeRPCConnectionCount, update_every);
580
581 if (perflibGetObjectCounter(pDataBlock, pObjectType, &exchangeRPCOperationPerSec))
582 netdata_exchange_rpc_op_per_sec(&exchangeRPCOperationPerSec, update_every);
583
584 if (perflibGetObjectCounter(pDataBlock, pObjectType, &exchangeRPCUserCount))
585 netdata_exchange_rpc_user_count(&exchangeRPCUserCount, update_every);
586 }
587
588 static void netdata_exchange_proxy_avg_auth_latency(struct exchange_proxy *ep, char *proxy, int update_every)
589 {
590 if (unlikely(!ep->st_exchange_http_proxy_avg_auth_latency)) {
591 char id[RRD_ID_LENGTH_MAX + 1];
592 snprintfz(id, RRD_ID_LENGTH_MAX, "exchange_proxy_%s_avg_auth_latency", proxy);
593
594 ep->st_exchange_http_proxy_avg_auth_latency = rrdset_create_localhost(
595 "exchange",
596 id,
597 NULL,
598 "proxy",
599 "exchange.http_proxy_avg_auth_latency",
600 "Average time spent authenticating CAS requests.",
601 "seconds",
602 PLUGIN_WINDOWS_NAME,
603 "PerflibExchange",
604 PRIO_EXCHANGE_PROXY_AVG_AUTH_LATENCY,
605 update_every,
606 RRDSET_TYPE_LINE);
607
608 ep->rd_exchange_http_proxy_avg_auth_latency =
609 rrddim_add(ep->st_exchange_http_proxy_avg_auth_latency, "latency", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
610
611 rrdlabels_add(ep->st_exchange_http_proxy_avg_auth_latency->rrdlabels, "http_proxy", proxy, RRDLABEL_SRC_AUTO);
612 }
613
614 rrddim_set_by_pointer(
615 ep->st_exchange_http_proxy_avg_auth_latency,
616 ep->rd_exchange_http_proxy_avg_auth_latency,
617 (collected_number)ep->exchangeProxyAvgAuthLatency.current.Data);
618 rrdset_done(ep->st_exchange_http_proxy_avg_auth_latency);
619 }
620
621 static void netdata_exchange_proxy_avg_cas_processing_latency(struct exchange_proxy *ep, char *proxy, int update_every)
622 {
623 if (unlikely(!ep->st_exchange_http_proxy_avg_cas_processing_latency)) {
624 char id[RRD_ID_LENGTH_MAX + 1];
625 snprintfz(id, RRD_ID_LENGTH_MAX, "exchange_proxy_%s_avg_cas_processing_latency_sec", proxy);
626
627 ep->st_exchange_http_proxy_avg_cas_processing_latency = rrdset_create_localhost(
628 "exchange",
629 id,
630 NULL,
631 "proxy",
632 "exchange.http_proxy_avg_cas_processing_latency_sec",
633 "Average latency (sec) of CAS processing time.",
634 "seconds",
635 PLUGIN_WINDOWS_NAME,
636 "PerflibExchange",
637 PRIO_EXCHANGE_PROXY_AVG_CAS_PROCESSING_LATENCY,
638 update_every,
639 RRDSET_TYPE_LINE);
640
641 ep->rd_exchange_http_proxy_avg_cas_processing_latency = rrddim_add(
642 ep->st_exchange_http_proxy_avg_cas_processing_latency, "latency", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE);
643
644 rrdlabels_add(
645 ep->st_exchange_http_proxy_avg_cas_processing_latency->rrdlabels, "http_proxy", proxy, RRDLABEL_SRC_AUTO);
646 }
647
648 rrddim_set_by_pointer(
649 ep->st_exchange_http_proxy_avg_cas_processing_latency,
650 ep->rd_exchange_http_proxy_avg_cas_processing_latency,
651 (collected_number)ep->exchangeProxyAvgCasProcessingLatency.current.Data);
652 rrdset_done(ep->st_exchange_http_proxy_avg_cas_processing_latency);
653 }
654
655 static void netdata_exchange_proxy_mailbox_proxy_failure(struct exchange_proxy *ep, char *proxy, int update_every)
656 {
657 if (unlikely(!ep->st_exchange_http_proxy_mailbox_proxy_failure)) {
658 char id[RRD_ID_LENGTH_MAX + 1];
659 snprintfz(id, RRD_ID_LENGTH_MAX, "exchange_proxy_%s_mailbox_proxy_failure_rate", proxy);
660
661 ep->st_exchange_http_proxy_mailbox_proxy_failure = rrdset_create_localhost(
662 "exchange",
663 id,
664 NULL,
665 "proxy",
666 "exchange.http_proxy_mailbox_proxy_failure_rate",
667 "Percentage of failures between this CAS and MBX servers.",
668 "percentage",
669 PLUGIN_WINDOWS_NAME,
670 "PerflibExchange",
671 PRIO_EXCHANGE_PROXY_MAILBOX_PROXY_FAILURE,
672 update_every,
673 RRDSET_TYPE_LINE);
674
675 ep->rd_exchange_http_proxy_mailbox_proxy_failure = rrddim_add(
676 ep->st_exchange_http_proxy_mailbox_proxy_failure, "failures", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE);
677
678 rrdlabels_add(
679 ep->st_exchange_http_proxy_mailbox_proxy_failure->rrdlabels, "http_proxy", proxy, RRDLABEL_SRC_AUTO);
680 }
681
682 rrddim_set_by_pointer(
683 ep->st_exchange_http_proxy_mailbox_proxy_failure,
684 ep->rd_exchange_http_proxy_mailbox_proxy_failure,
685 (collected_number)ep->exchangeProxyMailboxProxyFailure.current.Data);
686 rrdset_done(ep->st_exchange_http_proxy_mailbox_proxy_failure);
687 }
688
689 static void netdata_exchange_proxy_mailbox_server_locator(struct exchange_proxy *ep, char *proxy, int update_every)
690 {
691 if (unlikely(!ep->st_exchange_http_proxy_server_location_avg_latency)) {
692 char id[RRD_ID_LENGTH_MAX + 1];
693 snprintfz(id, RRD_ID_LENGTH_MAX, "exchange_proxy_%s_mailbox_server_locator_avg_latency_sec", proxy);
694
695 ep->st_exchange_http_proxy_server_location_avg_latency = rrdset_create_localhost(
696 "exchange",
697 id,
698 NULL,
699 "proxy",
700 "exchange.http_proxy_mailbox_server_locator_avg_latency_sec",
701 "Average latency of MailboxServerLocator web service calls.",
702 "seconds",
703 PLUGIN_WINDOWS_NAME,
704 "PerflibExchange",
705 PRIO_EXCHANGE_PROXY_SERVER_LOCATOR_AVG_LATENCY,
706 update_every,
707 RRDSET_TYPE_LINE);
708
709 ep->rd_exchange_http_proxy_server_location_avg_latency = rrddim_add(
710 ep->st_exchange_http_proxy_server_location_avg_latency, "latency", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE);
711
712 rrdlabels_add(
713 ep->st_exchange_http_proxy_server_location_avg_latency->rrdlabels, "http_proxy", proxy, RRDLABEL_SRC_AUTO);
714 }
715
716 rrddim_set_by_pointer(
717 ep->st_exchange_http_proxy_server_location_avg_latency,
718 ep->rd_exchange_http_proxy_server_location_avg_latency,
719 (collected_number)ep->exchangeProxyMailboxServerLocator.current.Data);
720 rrdset_done(ep->st_exchange_http_proxy_server_location_avg_latency);
721 }
722
723 static void netdata_exchange_proxy_outstanding_proxy(struct exchange_proxy *ep, char *proxy, int update_every)
724 {
725 if (unlikely(!ep->st_exchange_http_proxy_outstanding_proxy_requests)) {
726 char id[RRD_ID_LENGTH_MAX + 1];
727 snprintfz(id, RRD_ID_LENGTH_MAX, "exchange_proxy_%s_outstanding_proxy_requests", proxy);
728
729 ep->st_exchange_http_proxy_outstanding_proxy_requests = rrdset_create_localhost(
730 "exchange",
731 id,
732 NULL,
733 "proxy",
734 "exchange.http_proxy_outstanding_proxy_requests",
735 "Concurrent outstanding proxy requests.",
736 "requests",
737 PLUGIN_WINDOWS_NAME,
738 "PerflibExchange",
739 PRIO_EXCHANGE_PROXY_OUTSTANDING_PROXY_REQUESTS,
740 update_every,
741 RRDSET_TYPE_LINE);
742
743 ep->rd_exchange_http_proxy_outstanding_proxy_requests = rrddim_add(
744 ep->st_exchange_http_proxy_outstanding_proxy_requests, "requests", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
745
746 rrdlabels_add(
747 ep->st_exchange_http_proxy_outstanding_proxy_requests->rrdlabels, "http_proxy", proxy, RRDLABEL_SRC_AUTO);
748 }
749
750 rrddim_set_by_pointer(
751 ep->st_exchange_http_proxy_outstanding_proxy_requests,
752 ep->rd_exchange_http_proxy_outstanding_proxy_requests,
753 (collected_number)ep->exchangeProxyOutstandingProxy.current.Data);
754 rrdset_done(ep->st_exchange_http_proxy_outstanding_proxy_requests);
755 }
756
757 static void netdata_exchange_proxy_request_total(struct exchange_proxy *ep, char *proxy, int update_every)
758 {
759 if (unlikely(!ep->st_exchange_http_proxy_requests_total)) {
760 char id[RRD_ID_LENGTH_MAX + 1];
761 snprintfz(id, RRD_ID_LENGTH_MAX, "exchange_proxy_%s_requests_total", proxy);
762
763 ep->st_exchange_http_proxy_requests_total = rrdset_create_localhost(
764 "exchange",
765 id,
766 NULL,
767 "proxy",
768 "exchange.http_proxy_requests",
769 "Number of proxy requests processed each second.",
770 "requests",
771 PLUGIN_WINDOWS_NAME,
772 "PerflibExchange",
773 PRIO_EXCHANGE_PROXY_REQUESTS_TOTAL,
774 update_every,
775 RRDSET_TYPE_LINE);
776
777 ep->rd_exchange_http_proxy_requests_total =
778 rrddim_add(ep->st_exchange_http_proxy_requests_total, "requests", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
779
780 rrdlabels_add(ep->st_exchange_http_proxy_requests_total->rrdlabels, "http_proxy", proxy, RRDLABEL_SRC_AUTO);
781 }
782
783 rrddim_set_by_pointer(
784 ep->st_exchange_http_proxy_requests_total,
785 ep->rd_exchange_http_proxy_requests_total,
786 (collected_number)ep->exchangeProxyRequestsTotal.current.Data);
787 rrdset_done(ep->st_exchange_http_proxy_requests_total);
788 }
789
790 static void netdata_exchange_proxy(PERF_DATA_BLOCK *pDataBlock, PERF_OBJECT_TYPE *pObjectType, int update_every)
791 {
792 PERF_INSTANCE_DEFINITION *pi = NULL;
793 for (LONG i = 0; i < pObjectType->NumInstances; i++) {
794 pi = perflibForEachInstance(pDataBlock, pObjectType, pi);
795 if (!pi)
796 break;
797
798 if (!getInstanceName(pDataBlock, pObjectType, pi, windows_shared_buffer, sizeof(windows_shared_buffer)))
799 strncpyz(windows_shared_buffer, "[unknown]", sizeof(windows_shared_buffer) - 1);
800
801 if (strcasecmp(windows_shared_buffer, "_Total") == 0)
802 continue;
803
804 struct exchange_proxy *ep = dictionary_set(exchange_proxies, windows_shared_buffer, NULL, sizeof(*ep));
805 if (!ep)
806 continue;
807
808 if (perflibGetObjectCounter(pDataBlock, pObjectType, &ep->exchangeProxyAvgAuthLatency))
809 netdata_exchange_proxy_avg_auth_latency(ep, windows_shared_buffer, update_every);
810
811 if (perflibGetObjectCounter(pDataBlock, pObjectType, &ep->exchangeProxyAvgCasProcessingLatency))
812 netdata_exchange_proxy_avg_cas_processing_latency(ep, windows_shared_buffer, update_every);
813
814 if (perflibGetObjectCounter(pDataBlock, pObjectType, &ep->exchangeProxyMailboxProxyFailure))
815 netdata_exchange_proxy_mailbox_proxy_failure(ep, windows_shared_buffer, update_every);
816
817 if (perflibGetObjectCounter(pDataBlock, pObjectType, &ep->exchangeProxyMailboxServerLocator))
818 netdata_exchange_proxy_mailbox_server_locator(ep, windows_shared_buffer, update_every);
819
820 if (perflibGetObjectCounter(pDataBlock, pObjectType, &ep->exchangeProxyOutstandingProxy))
821 netdata_exchange_proxy_outstanding_proxy(ep, windows_shared_buffer, update_every);
822
823 if (perflibGetObjectCounter(pDataBlock, pObjectType, &ep->exchangeProxyRequestsTotal))
824 netdata_exchange_proxy_request_total(ep, windows_shared_buffer, update_every);
825 }
826 }
827
828 static void netdata_exchange_workload_active_tasks(struct exchange_workload *ew, char *workload, int update_every)
829 {
830 if (unlikely(!ew->st_exchange_workload_active_tasks)) {
831 char id[RRD_ID_LENGTH_MAX + 1];
832 snprintfz(id, RRD_ID_LENGTH_MAX, "exchange_workload_%s_tasks", workload);
833
834 ew->st_exchange_workload_active_tasks = rrdset_create_localhost(
835 "exchange",
836 id,
837 NULL,
838 "workload",
839 "exchange.workload_active_tasks",
840 "Workload active tasks.",
841 "tasks",
842 PLUGIN_WINDOWS_NAME,
843 "PerflibExchange",
844 PRIO_EXCHANGE_WORKLOAD_ACTIVE_TASKS,
845 update_every,
846 RRDSET_TYPE_LINE);
847
848 ew->rd_exchange_workload_active_tasks =
849 rrddim_add(ew->st_exchange_workload_active_tasks, "active", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
850
851 rrdlabels_add(ew->st_exchange_workload_active_tasks->rrdlabels, "workload", workload, RRDLABEL_SRC_AUTO);
852 }
853
854 rrddim_set_by_pointer(
855 ew->st_exchange_workload_active_tasks,
856 ew->rd_exchange_workload_active_tasks,
857 (collected_number)ew->exchangeWorkloadActiveTasks.current.Data);
858 rrdset_done(ew->st_exchange_workload_active_tasks);
859 }
860
861 static void netdata_exchange_workload_completed_tasks(struct exchange_workload *ew, char *workload, int update_every)
862 {
863 if (unlikely(!ew->st_exchange_workload_complete_tasks)) {
864 char id[RRD_ID_LENGTH_MAX + 1];
865 snprintfz(id, RRD_ID_LENGTH_MAX, "exchange_workload_%s_completed_tasks", workload);
866
867 ew->st_exchange_workload_complete_tasks = rrdset_create_localhost(
868 "exchange",
869 id,
870 NULL,
871 "workload",
872 "exchange.workload_completed_tasks",
873 "Workload completed tasks.",
874 "tasks/s",
875 PLUGIN_WINDOWS_NAME,
876 "PerflibExchange",
877 PRIO_EXCHANGE_WORKLOAD_COMPLETE_TASKS,
878 update_every,
879 RRDSET_TYPE_LINE);
880
881 ew->rd_exchange_workload_complete_tasks =
882 rrddim_add(ew->st_exchange_workload_complete_tasks, "completed", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
883
884 rrdlabels_add(ew->st_exchange_workload_complete_tasks->rrdlabels, "workload", workload, RRDLABEL_SRC_AUTO);
885 }
886
887 rrddim_set_by_pointer(
888 ew->st_exchange_workload_complete_tasks,
889 ew->rd_exchange_workload_complete_tasks,
890 (collected_number)ew->exchangeWorkloadCompleteTasks.current.Data);
891 rrdset_done(ew->st_exchange_workload_complete_tasks);
892 }
893
894 static void netdata_exchange_workload_queued_tasks(struct exchange_workload *ew, char *workload, int update_every)
895 {
896 if (unlikely(!ew->st_exchange_workload_queued_tasks)) {
897 char id[RRD_ID_LENGTH_MAX + 1];
898 snprintfz(id, RRD_ID_LENGTH_MAX, "exchange_workload_%s_queued_tasks", workload);
899
900 ew->st_exchange_workload_queued_tasks = rrdset_create_localhost(
901 "exchange",
902 id,
903 NULL,
904 "workload",
905 "exchange.workload_queued_tasks",
906 "Workload queued tasks.",
907 "tasks/s",
908 PLUGIN_WINDOWS_NAME,
909 "PerflibExchange",
910 PRIO_EXCHANGE_WORKLOAD_QUEUE_TASKS,
911 update_every,
912 RRDSET_TYPE_LINE);
913
914 ew->rd_exchange_workload_queued_tasks =
915 rrddim_add(ew->st_exchange_workload_queued_tasks, "queued", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
916
917 rrdlabels_add(ew->st_exchange_workload_queued_tasks->rrdlabels, "workload", workload, RRDLABEL_SRC_AUTO);
918 }
919
920 rrddim_set_by_pointer(
921 ew->st_exchange_workload_queued_tasks,
922 ew->rd_exchange_workload_queued_tasks,
923 (collected_number)ew->exchangeWorkloadQueueTasks.current.Data);
924 rrdset_done(ew->st_exchange_workload_queued_tasks);
925 }
926
927 static void netdata_exchange_workload_yielded_tasks(struct exchange_workload *ew, char *workload, int update_every)
928 {
929 if (unlikely(!ew->st_exchange_workload_yielded_tasks)) {
930 char id[RRD_ID_LENGTH_MAX + 1];
931 snprintfz(id, RRD_ID_LENGTH_MAX, "exchange_workload_%s_yielded_tasks", workload);
932
933 ew->st_exchange_workload_yielded_tasks = rrdset_create_localhost(
934 "exchange",
935 id,
936 NULL,
937 "workload",
938 "exchange.workload_yielded_tasks",
939 "Workload yielded tasks.",
940 "tasks/s",
941 PLUGIN_WINDOWS_NAME,
942 "PerflibExchange",
943 PRIO_EXCHANGE_WORKLOAD_YIELDED_TASKS,
944 update_every,
945 RRDSET_TYPE_LINE);
946
947 ew->rd_exchange_workload_yielded_tasks =
948 rrddim_add(ew->st_exchange_workload_yielded_tasks, "yielded", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
949
950 rrdlabels_add(ew->st_exchange_workload_yielded_tasks->rrdlabels, "workload", workload, RRDLABEL_SRC_AUTO);
951 }
952
953 rrddim_set_by_pointer(
954 ew->st_exchange_workload_yielded_tasks,
955 ew->rd_exchange_workload_yielded_tasks,
956 (collected_number)ew->exchangeWorkloadYieldedTasks.current.Data);
957 rrdset_done(ew->st_exchange_workload_yielded_tasks);
958 }
959
960 static void netdata_exchange_workload_activity_status(struct exchange_workload *ew, char *workload, int update_every)
961 {
962 if (unlikely(!ew->st_exchange_workload_activity_status)) {
963 char id[RRD_ID_LENGTH_MAX + 1];
964 snprintfz(id, RRD_ID_LENGTH_MAX, "exchange_workload_%s_activity_status", workload);
965
966 ew->st_exchange_workload_activity_status = rrdset_create_localhost(
967 "exchange",
968 id,
969 NULL,
970 "workload",
971 "exchange.workload_activity_status",
972 "Workload activity status.",
973 "status",
974 PLUGIN_WINDOWS_NAME,
975 "PerflibExchange",
976 PRIO_EXCHANGE_WORKLOAD_ACTIVITY,
977 update_every,
978 RRDSET_TYPE_LINE);
979
980 ew->rd_exchange_workload_activity_active_status =
981 rrddim_add(ew->st_exchange_workload_activity_status, "active", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
982
983 ew->rd_exchange_workload_activity_paused_status =
984 rrddim_add(ew->st_exchange_workload_activity_status, "paused", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
985
986 rrdlabels_add(ew->st_exchange_workload_activity_status->rrdlabels, "workload", workload, RRDLABEL_SRC_AUTO);
987 }
988
989 bool value = (bool)ew->exchangeWorkloadActivityStatus.current.Data;
990 rrddim_set_by_pointer(
991 ew->st_exchange_workload_activity_status,
992 ew->rd_exchange_workload_activity_active_status,
993 (collected_number)value);
994
995 value = !value;
996 rrddim_set_by_pointer(
997 ew->st_exchange_workload_activity_status,
998 ew->rd_exchange_workload_activity_paused_status,
999 (collected_number)value);
1000 rrdset_done(ew->st_exchange_workload_activity_status);
1001 }
1002
1003 static void netdata_exchange_workload(PERF_DATA_BLOCK *pDataBlock, PERF_OBJECT_TYPE *pObjectType, int update_every)
1004 {
1005 PERF_INSTANCE_DEFINITION *pi = NULL;
1006 for (LONG i = 0; i < pObjectType->NumInstances; i++) {
1007 pi = perflibForEachInstance(pDataBlock, pObjectType, pi);
1008 if (!pi)
1009 break;
1010
1011 if (!getInstanceName(pDataBlock, pObjectType, pi, windows_shared_buffer, sizeof(windows_shared_buffer)))
1012 strncpyz(windows_shared_buffer, "[unknown]", sizeof(windows_shared_buffer) - 1);
1013
1014 if (strcasecmp(windows_shared_buffer, "_Total") == 0)
1015 continue;
1016
1017 struct exchange_workload *ew = dictionary_set(exchange_workloads, windows_shared_buffer, NULL, sizeof(*ew));
1018 if (!ew)
1019 continue;
1020
1021 if (perflibGetObjectCounter(pDataBlock, pObjectType, &ew->exchangeWorkloadActiveTasks))
1022 netdata_exchange_workload_active_tasks(ew, windows_shared_buffer, update_every);
1023
1024 if (perflibGetObjectCounter(pDataBlock, pObjectType, &ew->exchangeWorkloadCompleteTasks))
1025 netdata_exchange_workload_completed_tasks(ew, windows_shared_buffer, update_every);
1026
1027 if (perflibGetObjectCounter(pDataBlock, pObjectType, &ew->exchangeWorkloadQueueTasks))
1028 netdata_exchange_workload_queued_tasks(ew, windows_shared_buffer, update_every);
1029
1030 if (perflibGetObjectCounter(pDataBlock, pObjectType, &ew->exchangeWorkloadYieldedTasks))
1031 netdata_exchange_workload_yielded_tasks(ew, windows_shared_buffer, update_every);
1032
1033 if (perflibGetObjectCounter(pDataBlock, pObjectType, &ew->exchangeWorkloadActivityStatus))
1034 netdata_exchange_workload_activity_status(ew, windows_shared_buffer, update_every);
1035 }
1036 }
1037
1038 static void netdata_exchange_queue_active_mailbox(struct exchange_queue *eq, char *mailbox, int update_every)
1039 {
1040 if (unlikely(!eq->st_exchange_queue_active_mailbox)) {
1041 char id[RRD_ID_LENGTH_MAX + 1];
1042 snprintfz(id, RRD_ID_LENGTH_MAX, "exchange_transport_queues_%s_active_mailbox_delivery", mailbox);
1043
1044 eq->st_exchange_queue_active_mailbox = rrdset_create_localhost(
1045 "exchange",
1046 id,
1047 NULL,
1048 "queue",
1049 "exchange.transport_queues_active_mail_box_delivery",
1050 "Active Mailbox Delivery Queue length.",
1051 "messages",
1052 PLUGIN_WINDOWS_NAME,
1053 "PerflibExchange",
1054 PRIO_EXCHANGE_QUEUE_ACTIVE_MAILBOX_DELIVERY,
1055 update_every,
1056 RRDSET_TYPE_LINE);
1057
1058 eq->rd_exchange_queue_active_mailbox =
1059 rrddim_add(eq->st_exchange_queue_active_mailbox, "active", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
1060
1061 rrdlabels_add(eq->st_exchange_queue_active_mailbox->rrdlabels, "mailbox", mailbox, RRDLABEL_SRC_AUTO);
1062 }
1063
1064 rrddim_set_by_pointer(
1065 eq->st_exchange_queue_active_mailbox,
1066 eq->rd_exchange_queue_active_mailbox,
1067 (collected_number)eq->exchangeTransportQueuesActiveMailboxDelivery.current.Data);
1068 rrdset_done(eq->st_exchange_queue_active_mailbox);
1069 }
1070
1071 static void
1072 netdata_exchange_queue_external_active_remote_delivery(struct exchange_queue *eq, char *mailbox, int update_every)
1073 {
1074 if (unlikely(!eq->st_exchange_queue_external_active_remote_delivery)) {
1075 char id[RRD_ID_LENGTH_MAX + 1];
1076 snprintfz(id, RRD_ID_LENGTH_MAX, "exchange_transport_queues_%s_external_active_remote_delivery", mailbox);
1077
1078 eq->st_exchange_queue_external_active_remote_delivery = rrdset_create_localhost(
1079 "exchange",
1080 id,
1081 NULL,
1082 "queue",
1083 "exchange.transport_queues_external_active_remote_delivery",
1084 "External Active Remote Delivery Queue length.",
1085 "messages",
1086 PLUGIN_WINDOWS_NAME,
1087 "PerflibExchange",
1088 PRIO_EXCHANGE_QUEUE_EXTERNAL_ACTIVE_REMOTE_DELIVERY,
1089 update_every,
1090 RRDSET_TYPE_LINE);
1091
1092 eq->rd_exchange_queue_external_active_remote_delivery = rrddim_add(
1093 eq->st_exchange_queue_external_active_remote_delivery, "active", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
1094
1095 rrdlabels_add(
1096 eq->st_exchange_queue_external_active_remote_delivery->rrdlabels, "mailbox", mailbox, RRDLABEL_SRC_AUTO);
1097 }
1098
1099 rrddim_set_by_pointer(
1100 eq->st_exchange_queue_external_active_remote_delivery,
1101 eq->rd_exchange_queue_external_active_remote_delivery,
1102 (collected_number)eq->exchangeTransportQueuesExternalActiveRemoteDelivery.current.Data);
1103 rrdset_done(eq->st_exchange_queue_external_active_remote_delivery);
1104 }
1105
1106 static void
1107 netdata_exchange_queue_internal_active_remote_delivery(struct exchange_queue *eq, char *mailbox, int update_every)
1108 {
1109 if (unlikely(!eq->st_exchange_queue_internal_active_remote_delivery)) {
1110 char id[RRD_ID_LENGTH_MAX + 1];
1111 snprintfz(id, RRD_ID_LENGTH_MAX, "exchange_transport_queues_%s_internal_active_remote_delivery", mailbox);
1112
1113 eq->st_exchange_queue_internal_active_remote_delivery = rrdset_create_localhost(
1114 "exchange",
1115 id,
1116 NULL,
1117 "queue",
1118 "exchange.transport_queues_internal_active_remote_delivery",
1119 "Internal Active Remote Delivery Queue length.",
1120 "messages",
1121 PLUGIN_WINDOWS_NAME,
1122 "PerflibExchange",
1123 PRIO_EXCHANGE_QUEUE_INTERNAL_ACTIVE_REMOTE_DELIVERY,
1124 update_every,
1125 RRDSET_TYPE_LINE);
1126
1127 eq->rd_exchange_queue_internal_active_remote_delivery = rrddim_add(
1128 eq->st_exchange_queue_internal_active_remote_delivery, "active", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
1129
1130 rrdlabels_add(
1131 eq->st_exchange_queue_internal_active_remote_delivery->rrdlabels, "mailbox", mailbox, RRDLABEL_SRC_AUTO);
1132 }
1133
1134 rrddim_set_by_pointer(
1135 eq->st_exchange_queue_internal_active_remote_delivery,
1136 eq->rd_exchange_queue_internal_active_remote_delivery,
1137 (collected_number)eq->exchangeTransportQueuesInternalActiveRemoteDelivery.current.Data);
1138 rrdset_done(eq->st_exchange_queue_internal_active_remote_delivery);
1139 }
1140
1141 static void netdata_exchange_queue_unreachable(struct exchange_queue *eq, char *mailbox, int update_every)
1142 {
1143 if (unlikely(!eq->st_exchange_queue_unreachable)) {
1144 char id[RRD_ID_LENGTH_MAX + 1];
1145 snprintfz(id, RRD_ID_LENGTH_MAX, "exchange_transport_queues_%s_unreachable", mailbox);
1146
1147 eq->st_exchange_queue_unreachable = rrdset_create_localhost(
1148 "exchange",
1149 id,
1150 NULL,
1151 "queue",
1152 "exchange.transport_queues_unreachable",
1153 "Unreachable Queue length.",
1154 "messages",
1155 PLUGIN_WINDOWS_NAME,
1156 "PerflibExchange",
1157 PRIO_EXCHANGE_QUEUE_UNREACHABLE,
1158 update_every,
1159 RRDSET_TYPE_LINE);
1160
1161 eq->rd_exchange_queue_unreachable =
1162 rrddim_add(eq->st_exchange_queue_unreachable, "unreachable", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
1163
1164 rrdlabels_add(eq->st_exchange_queue_unreachable->rrdlabels, "mailbox", mailbox, RRDLABEL_SRC_AUTO);
1165 }
1166
1167 rrddim_set_by_pointer(
1168 eq->st_exchange_queue_unreachable,
1169 eq->rd_exchange_queue_unreachable,
1170 (collected_number)eq->exchangeTransportQueuesUnreachable.current.Data);
1171 rrdset_done(eq->st_exchange_queue_unreachable);
1172 }
1173
1174 static void netdata_exchange_queue_poison(struct exchange_queue *eq, char *mailbox, int update_every)
1175 {
1176 if (unlikely(!eq->st_exchange_queue_poison)) {
1177 char id[RRD_ID_LENGTH_MAX + 1];
1178 snprintfz(id, RRD_ID_LENGTH_MAX, "exchange_transport_queues_%s_poison", mailbox);
1179
1180 eq->st_exchange_queue_poison = rrdset_create_localhost(
1181 "exchange",
1182 id,
1183 NULL,
1184 "queue",
1185 "exchange.transport_queues_poison",
1186 "Poison Queue Length.",
1187 "messages",
1188 PLUGIN_WINDOWS_NAME,
1189 "PerflibExchange",
1190 PRIO_EXCHANGE_QUEUE_POISON,
1191 update_every,
1192 RRDSET_TYPE_LINE);
1193
1194 eq->rd_exchange_queue_poison =
1195 rrddim_add(eq->st_exchange_queue_poison, "poison", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
1196
1197 rrdlabels_add(eq->st_exchange_queue_poison->rrdlabels, "mailbox", mailbox, RRDLABEL_SRC_AUTO);
1198 }
1199
1200 rrddim_set_by_pointer(
1201 eq->st_exchange_queue_poison,
1202 eq->rd_exchange_queue_poison,
1203 (collected_number)eq->exchangeTransportQueuesPoison.current.Data);
1204 rrdset_done(eq->st_exchange_queue_poison);
1205 }
1206
1207 static void netdata_exchange_queues(PERF_DATA_BLOCK *pDataBlock, PERF_OBJECT_TYPE *pObjectType, int update_every)
1208 {
1209 PERF_INSTANCE_DEFINITION *pi = NULL;
1210 for (LONG i = 0; i < pObjectType->NumInstances; i++) {
1211 pi = perflibForEachInstance(pDataBlock, pObjectType, pi);
1212 if (!pi)
1213 break;
1214
1215 if (!getInstanceName(pDataBlock, pObjectType, pi, windows_shared_buffer, sizeof(windows_shared_buffer)))
1216 strncpyz(windows_shared_buffer, "[unknown]", sizeof(windows_shared_buffer) - 1);
1217
1218 // Remove 'queue' from instance name
1219 char *ptr = strchr(windows_shared_buffer, ' ');
1220 if (ptr)
1221 *ptr = '\0';
1222
1223 if (strcasecmp(windows_shared_buffer, "_Total") == 0 || strcasecmp(windows_shared_buffer, "total") == 0)
1224 continue;
1225
1226 struct exchange_queue *eq = dictionary_set(exchange_queues, windows_shared_buffer, NULL, sizeof(*eq));
1227 if (!eq)
1228 continue;
1229
1230 if (perflibGetObjectCounter(pDataBlock, pObjectType, &eq->exchangeTransportQueuesActiveMailboxDelivery))
1231 netdata_exchange_queue_active_mailbox(eq, windows_shared_buffer, update_every);
1232
1233 if (perflibGetObjectCounter(pDataBlock, pObjectType, &eq->exchangeTransportQueuesExternalActiveRemoteDelivery))
1234 netdata_exchange_queue_external_active_remote_delivery(eq, windows_shared_buffer, update_every);
1235
1236 if (perflibGetObjectCounter(pDataBlock, pObjectType, &eq->exchangeTransportQueuesInternalActiveRemoteDelivery))
1237 netdata_exchange_queue_internal_active_remote_delivery(eq, windows_shared_buffer, update_every);
1238
1239 if (perflibGetObjectCounter(pDataBlock, pObjectType, &eq->exchangeTransportQueuesUnreachable))
1240 netdata_exchange_queue_unreachable(eq, windows_shared_buffer, update_every);
1241
1242 if (perflibGetObjectCounter(pDataBlock, pObjectType, &eq->exchangeTransportQueuesPoison))
1243 netdata_exchange_queue_poison(eq, windows_shared_buffer, update_every);
1244 }
1245 }
1246
1247 struct netdata_exchange_objects {
1248 void (*fnct)(PERF_DATA_BLOCK *, PERF_OBJECT_TYPE *, int);
1249 char *object;
1250 } exchange_obj[] = {
1251 {.fnct = netdata_exchange_owa, .object = "MSExchange OWA"},
1252 {.fnct = netdata_exchange_active_sync, .object = "MSExchange ActiveSync"},
1253 {.fnct = netdata_exchange_auto_discover, .object = "MSExchangeAutodiscover"},
1254 {.fnct = netdata_exchange_availability_service, .object = "MSExchange Availability Service"},
1255 {.fnct = netdata_exchange_rpc, .object = "MSExchange RpcClientAccess"},
1256 {.fnct = netdata_exchange_proxy, .object = "MSExchange HttpProxy"},
1257 {.fnct = netdata_exchange_workload, .object = "MSExchange WorkloadManagement Workloads"},
1258 {.fnct = netdata_exchange_queues, .object = "MSExchangeTransport Queues"},
1259
1260 // This is the end of the loop
1261 {.fnct = NULL, .object = NULL}};
1262
1263 int do_PerflibExchange(int update_every, usec_t dt __maybe_unused)
1264 {
1265 static bool initialized = false;
1266
1267 if (unlikely(!initialized)) {
1268 initialize();
1269 initialized = true;
1270 }
1271
1272 for (int i = 0; exchange_obj[i].fnct; i++) {
1273 DWORD id = RegistryFindIDByName(exchange_obj[i].object);
1274 if (id == PERFLIB_REGISTRY_NAME_NOT_FOUND)
1275 continue;
1276
1277 PERF_DATA_BLOCK *pDataBlock = perflibGetPerformanceData(id);
1278 if (!pDataBlock)
1279 continue;
1280
1281 PERF_OBJECT_TYPE *pObjectType = perflibFindObjectTypeByName(pDataBlock, exchange_obj[i].object);
1282 if (!pObjectType)
1283 continue;
1284
1285 exchange_obj[i].fnct(pDataBlock, pObjectType, update_every);
1286 }
1287
1288 return 0;
1289 }