Monitor Exchange Server (Window.plugin) (#20454)
thiagoftsm committed
Jun 17, 2025 at 14:45 UTC
a2fa5999550ab0fdd8e6e3d543ef93c24a464255
6 files changed
+1593
-1
CMakeLists.txt
+1
@@ -2060,6 +2060,7 @@ set(WINDOWS_PLUGIN_FILES
2060
src/collectors/windows.plugin/perflib-web-service.c
2061
src/collectors/windows.plugin/perflib-services.c
2062
src/collectors/windows.plugin/perflib-hyperv.c
2063
+ src/collectors/windows.plugin/perflib-exchange.c
2064
)
2065
2066
set(PROC_PLUGIN_FILES
src/collectors/windows.plugin/README.md
+1
@@ -31,6 +31,7 @@ To change a setting, remove the comment symbol (`#`) from the beginning of the l
31
# PerflibAD = yes
32
# PerflibADCS = yes
33
# PerflibADFS = yes
34
+ # PerflibExchange = yes
35
```
36
37
## Microsoft SQL Server Integration
src/collectors/windows.plugin/metadata.yaml
+265
@@ -3094,3 +3094,268 @@ modules:
3094
- name: pause_pending
3095
- name: paused
3096
- name: unknown
3097
+ - meta:
3098
+ plugin_name: windows.plugin
3099
+ module_name: PerflibExchange
3100
+ monitored_instance:
3101
+ name: MS Exchange
3102
+ link: "https://www.microsoft.com/en-us/microsoft-365/exchange/email"
3103
+ categories:
3104
+ - data-collection.windows-systems
3105
+ icon_filename: "exchange.svg"
3106
+ related_resources:
3107
+ integrations:
3108
+ list: []
3109
+ info_provided_to_referring_integrations:
3110
+ description: ""
3111
+ keywords:
3112
+ - windows
3113
+ - microsoft
3114
+ - exchange
3115
+ - mail
3116
+ most_popular: false
3117
+ overview:
3118
+ data_collection:
3119
+ metrics_description: |
3120
+ This collector monitors Microsoft Exchange.
3121
+ method_description: |
3122
+ It queries different Exchange objects from Perflib in order to gather the metrics.
3123
+ supported_platforms:
3124
+ include: ["windows"]
3125
+ exclude: []
3126
+ multi_instance: false
3127
+ additional_permissions:
3128
+ description: ""
3129
+ default_behavior:
3130
+ auto_detection:
3131
+ description: |
3132
+ The collector automatically detects all of the metrics, no further configuration is required.
3133
+ limits:
3134
+ description: ""
3135
+ performance_impact:
3136
+ description: ""
3137
+ setup:
3138
+ prerequisites:
3139
+ list: []
3140
+ configuration:
3141
+ file:
3142
+ name: "netdata.conf"
3143
+ section_name: "[plugin:windows]"
3144
+ description: "The Netdata main configuration file"
3145
+ options:
3146
+ description: ""
3147
+ folding:
3148
+ title: "Config option"
3149
+ enabled: false
3150
+ list:
3151
+ - name: PerflibExchange
3152
+ description: An option to enable or disable the data collection.
3153
+ default_value: yes
3154
+ required: false
3155
+ examples:
3156
+ folding:
3157
+ enabled: true
3158
+ title: ""
3159
+ list: []
3160
+ troubleshooting:
3161
+ problems:
3162
+ list: []
3163
+ alerts: []
3164
+ metrics:
3165
+ folding:
3166
+ title: Metrics
3167
+ enabled: false
3168
+ description: ""
3169
+ availability: []
3170
+ scopes:
3171
+ - name: Windows Exchange
3172
+ description: "These metrics refer to Windows Exchange."
3173
+ labels: []
3174
+ metrics:
3175
+ - name: exchange.transport_queues_active_mail_box_delivery
3176
+ description: Active Mailbox Delivery Queue length.
3177
+ unit: messages
3178
+ chart_type: line
3179
+ dimensions:
3180
+ - name: active
3181
+ - name: exchange.transport_queues_external_active_remote_delivery
3182
+ description: External Active Remote Delivery Queue length.
3183
+ unit: messages
3184
+ chart_type: line
3185
+ dimensions:
3186
+ - name: active
3187
+ - name: exchange.transport_queues_internal_active_remote_delivery
3188
+ description: Internal Active Remote Delivery Queue length.
3189
+ unit: messages
3190
+ chart_type: line
3191
+ dimensions:
3192
+ - name: active
3193
+ - name: exchange.transport_queues_unreachable
3194
+ description: Unreachable Queue length.
3195
+ unit: messages
3196
+ chart_type: line
3197
+ dimensions:
3198
+ - name: unreachable
3199
+ - name: exchange.transport_queues_poison
3200
+ description: Poison Queue Length.
3201
+ unit: messages
3202
+ chart_type: line
3203
+ dimensions:
3204
+ - name: unreachable
3205
+ - name: exchange.activesync_ping_cmds_pending
3206
+ description: Ping commands pending in queue.
3207
+ unit: commands
3208
+ chart_type: line
3209
+ dimensions:
3210
+ - name: pending
3211
+ - name: exchange.activesync_requests
3212
+ description: HTTP requests received from ASP.NET.
3213
+ unit: requests/s
3214
+ chart_type: line
3215
+ dimensions:
3216
+ - name: received
3217
+ - name: exchange.activesync_sync_cmds
3218
+ description: Sync commands processed.
3219
+ unit: commands/s
3220
+ chart_type: line
3221
+ dimensions:
3222
+ - name: processed
3223
+ - name: exchange.rpc_active_user_count
3224
+ description: Active unique users in the last 2 minutes.
3225
+ unit: users
3226
+ chart_type: line
3227
+ dimensions:
3228
+ - name: active
3229
+ - name: exchange.rpc_avg_latency
3230
+ description: Average latency.
3231
+ unit: seconds
3232
+ chart_type: line
3233
+ dimensions:
3234
+ - name: latency
3235
+ - name: exchange.rpc_connection_count
3236
+ description: Client connections.
3237
+ unit: connections
3238
+ chart_type: line
3239
+ dimensions:
3240
+ - name: connections
3241
+ - name: exchange.rpc_requests
3242
+ description: Clients requests currently being processed.
3243
+ unit: requests
3244
+ chart_type: line
3245
+ dimensions:
3246
+ - name: processed
3247
+ - name: exchange.rpc_active_user
3248
+ description: Active unique users in the last 2 minutes.
3249
+ unit: users
3250
+ chart_type: line
3251
+ dimensions:
3252
+ - name: users
3253
+ - name: exchange.rpc_connection
3254
+ description: Client connections.
3255
+ unit: connections
3256
+ chart_type: line
3257
+ dimensions:
3258
+ - name: connections
3259
+ - name: exchange.rpc_operations
3260
+ description: RPC operations.
3261
+ unit: operations/s
3262
+ chart_type: line
3263
+ dimensions:
3264
+ - name: operations
3265
+ - name: exchange.rpc_user_count
3266
+ description: RPC users.
3267
+ unit: users
3268
+ chart_type: line
3269
+ dimensions:
3270
+ - name: users
3271
+ - name: exchange.owa_current_unique_users
3272
+ description: Unique users currently logged on to Outlook Web App.
3273
+ unit: users
3274
+ chart_type: line
3275
+ dimensions:
3276
+ - name: logged-in
3277
+ - name: exchange.owa_requests_total
3278
+ description: Requests handled by Outlook Web App.
3279
+ unit: requests/s
3280
+ chart_type: line
3281
+ dimensions:
3282
+ - name: handled
3283
+ - name: exchange.workload_active_tasks
3284
+ description: Workload active tasks.
3285
+ unit: tasks
3286
+ chart_type: line
3287
+ dimensions:
3288
+ - name: active
3289
+ - name: exchange.workload_completed_tasks
3290
+ description: Workload completed tasks.
3291
+ unit: tasks/s
3292
+ chart_type: line
3293
+ dimensions:
3294
+ - name: completed
3295
+ - name: exchange.workload_queued_tasks
3296
+ description: Workload queued tasks.
3297
+ unit: tasks/s
3298
+ chart_type: line
3299
+ dimensions:
3300
+ - name: queued
3301
+ - name: exchange.workload_yielded_tasks
3302
+ description: Workload yielded tasks.
3303
+ unit: tasks/s
3304
+ chart_type: line
3305
+ dimensions:
3306
+ - name: yielded
3307
+ - name: exchange.workload_activity_status
3308
+ description: Workload activity status
3309
+ unit: status
3310
+ chart_type: line
3311
+ dimensions:
3312
+ - name: active
3313
+ - name: paused
3314
+ - name: exchange.http_proxy_avg_auth_latency
3315
+ description: Average time spent authenticating CAS requests.
3316
+ unit: seconds
3317
+ chart_type: line
3318
+ dimensions:
3319
+ - name: latency
3320
+ - name: exchange.http_proxy_avg_cas_processing_latency_sec
3321
+ description: Average latency (sec) of CAS processing time.
3322
+ unit: seconds
3323
+ chart_type: line
3324
+ dimensions:
3325
+ - name: latency
3326
+ - name: exchange.http_proxy_mailbox_proxy_failure_rate
3327
+ description: Percentage of failures between this CAS and MBX servers.
3328
+ unit: seconds
3329
+ chart_type: line
3330
+ dimensions:
3331
+ - name: failures
3332
+ - name: exchange.http_proxy_mailbox_server_locator_avg_latency_sec
3333
+ description: Average latency of MailboxServerLocator web service calls.
3334
+ unit: seconds
3335
+ chart_type: line
3336
+ dimensions:
3337
+ - name: latency
3338
+ - name: exchange.http_proxy_outstanding_proxy_requests
3339
+ description: Concurrent outstanding proxy requests.
3340
+ unit: seconds
3341
+ chart_type: line
3342
+ dimensions:
3343
+ - name: requests
3344
+ - name: exchange.http_proxy_requests
3345
+ description: Number of proxy requests processed each second.
3346
+ unit: seconds
3347
+ chart_type: line
3348
+ dimensions:
3349
+ - name: requests
3350
+ - name: exchange.autodiscover_requests
3351
+ description: Autodiscover service requests processed
3352
+ unit: requests/s
3353
+ chart_type: line
3354
+ dimensions:
3355
+ - name: processed
3356
+ - name: exchange.avail_service_requests
3357
+ description: Requests serviced
3358
+ unit: requests/s
3359
+ chart_type: line
3360
+ dimensions:
3361
+ - name: serviced
src/collectors/windows.plugin/perflib-exchange.c
new
+1286
@@ -0,0 +1,1286 @@
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 exchangeTransportQueuesInternalActiveRemoteDeliery;
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_worload_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->exchangeTransportQueuesInternalActiveRemoteDeliery.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_worload_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_INCREMENTAL);
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(&exchangeRPCRequest, 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_LOCATIOR_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_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, "completed", 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_INCREMENTAL);
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
+ rrdset_done(ew->st_exchange_workload_activity_status);
995
+
996
+ value = !value;
997
+ rrddim_set_by_pointer(
998
+ ew->st_exchange_workload_activity_status,
999
+ ew->rd_exchange_workload_activity_paused_status,
1000
+ (collected_number)value);
1001
+ rrdset_done(ew->st_exchange_workload_activity_status);
1002
+}
1003
+
1004
+static void netdata_exchange_workload(PERF_DATA_BLOCK *pDataBlock, PERF_OBJECT_TYPE *pObjectType, int update_every)
1005
+{
1006
+ PERF_INSTANCE_DEFINITION *pi = NULL;
1007
+ for (LONG i = 0; i < pObjectType->NumInstances; i++) {
1008
+ pi = perflibForEachInstance(pDataBlock, pObjectType, pi);
1009
+ if (!pi)
1010
+ break;
1011
+
1012
+ if (!getInstanceName(pDataBlock, pObjectType, pi, windows_shared_buffer, sizeof(windows_shared_buffer)))
1013
+ strncpyz(windows_shared_buffer, "[unknown]", sizeof(windows_shared_buffer) - 1);
1014
+
1015
+ if (strcasecmp(windows_shared_buffer, "_Total") == 0)
1016
+ continue;
1017
+
1018
+ struct exchange_workload *ew = dictionary_set(exchange_workloads, windows_shared_buffer, NULL, sizeof(*ew));
1019
+ if (!ew)
1020
+ continue;
1021
+
1022
+ if (perflibGetObjectCounter(pDataBlock, pObjectType, &ew->exchangeWorkloadActiveTasks))
1023
+ netdata_exchange_workload_active_tasks(ew, windows_shared_buffer, update_every);
1024
+
1025
+ if (perflibGetObjectCounter(pDataBlock, pObjectType, &ew->exchangeWorkloadCompleteTasks))
1026
+ netdata_exchange_workload_completed_tasks(ew, windows_shared_buffer, update_every);
1027
+
1028
+ if (perflibGetObjectCounter(pDataBlock, pObjectType, &ew->exchangeWorkloadQueueTasks))
1029
+ netdata_exchange_workload_queued_tasks(ew, windows_shared_buffer, update_every);
1030
+
1031
+ if (perflibGetObjectCounter(pDataBlock, pObjectType, &ew->exchangeWorkloadYieldedTasks))
1032
+ netdata_exchange_workload_yielded_tasks(ew, windows_shared_buffer, update_every);
1033
+
1034
+ if (perflibGetObjectCounter(pDataBlock, pObjectType, &ew->exchangeWorkloadActivityStatus))
1035
+ netdata_exchange_workload_activity_status(ew, windows_shared_buffer, update_every);
1036
+ }
1037
+}
1038
+
1039
+static void netdata_exchange_queue_active_mailbox(struct exchange_queue *eq, char *mailbox, int update_every)
1040
+{
1041
+ if (unlikely(!eq->st_exchange_queue_active_mailbox)) {
1042
+ char id[RRD_ID_LENGTH_MAX + 1];
1043
+ snprintfz(id, RRD_ID_LENGTH_MAX, "exchange_transport_queues_%s_active_mailbox_delivery", mailbox);
1044
+
1045
+ eq->st_exchange_queue_active_mailbox = rrdset_create_localhost(
1046
+ "exchange",
1047
+ id,
1048
+ NULL,
1049
+ "queue",
1050
+ "exchange.transport_queues_active_mail_box_delivery",
1051
+ "Active Mailbox Delivery Queue length.",
1052
+ "messages",
1053
+ PLUGIN_WINDOWS_NAME,
1054
+ "PerflibExchange",
1055
+ PRIO_EXCHANGE_QUEUE_ACTIVE_MAILBOX_DELIVERY,
1056
+ update_every,
1057
+ RRDSET_TYPE_LINE);
1058
+
1059
+ eq->rd_exchange_queue_active_mailbox =
1060
+ rrddim_add(eq->st_exchange_queue_active_mailbox, "active", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
1061
+
1062
+ rrdlabels_add(eq->st_exchange_queue_active_mailbox->rrdlabels, "mailbox", mailbox, RRDLABEL_SRC_AUTO);
1063
+ }
1064
+
1065
+ rrddim_set_by_pointer(
1066
+ eq->st_exchange_queue_active_mailbox,
1067
+ eq->rd_exchange_queue_active_mailbox,
1068
+ (collected_number)eq->exchangeTransportQueuesActiveMailboxDelivery.current.Data);
1069
+ rrdset_done(eq->st_exchange_queue_active_mailbox);
1070
+}
1071
+
1072
+static void 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 =
1093
+ rrddim_add(eq->st_exchange_queue_external_active_remote_delivery, "active", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
1094
+
1095
+ rrdlabels_add(eq->st_exchange_queue_external_active_remote_delivery->rrdlabels, "mailbox", mailbox, RRDLABEL_SRC_AUTO);
1096
+ }
1097
+
1098
+ rrddim_set_by_pointer(
1099
+ eq->st_exchange_queue_external_active_remote_delivery,
1100
+ eq->rd_exchange_queue_external_active_remote_delivery,
1101
+ (collected_number)eq->exchangeTransportQueuesExternalActiveRemoteDelivery.current.Data);
1102
+ rrdset_done(eq->st_exchange_queue_external_active_remote_delivery);
1103
+}
1104
+
1105
+static void netdata_exchange_queue_internal_active_remote_delivery(struct exchange_queue *eq, char *mailbox, int update_every)
1106
+{
1107
+ if (unlikely(!eq->st_exchange_queue_internal_active_remote_delivery)) {
1108
+ char id[RRD_ID_LENGTH_MAX + 1];
1109
+ snprintfz(id, RRD_ID_LENGTH_MAX, "exchange_transport_queues_%s_internal_active_remote_delivery", mailbox);
1110
+
1111
+ eq->st_exchange_queue_internal_active_remote_delivery = rrdset_create_localhost(
1112
+ "exchange",
1113
+ id,
1114
+ NULL,
1115
+ "queue",
1116
+ "exchange.transport_queues_internal_active_remote_delivery",
1117
+ "Internal Active Remote Delivery Queue length.",
1118
+ "messages",
1119
+ PLUGIN_WINDOWS_NAME,
1120
+ "PerflibExchange",
1121
+ PRIO_EXCHANGE_QUEUE_INTERNAL_ACTIVE_REMOTE_DELIVERY,
1122
+ update_every,
1123
+ RRDSET_TYPE_LINE);
1124
+
1125
+ eq->rd_exchange_queue_internal_active_remote_delivery =
1126
+ rrddim_add(eq->st_exchange_queue_internal_active_remote_delivery, "active", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
1127
+
1128
+ rrdlabels_add(eq->st_exchange_queue_internal_active_remote_delivery->rrdlabels, "mailbox", mailbox, RRDLABEL_SRC_AUTO);
1129
+ }
1130
+
1131
+ rrddim_set_by_pointer(
1132
+ eq->st_exchange_queue_internal_active_remote_delivery,
1133
+ eq->rd_exchange_queue_internal_active_remote_delivery,
1134
+ (collected_number)eq->exchangeTransportQueuesInternalActiveRemoteDeliery.current.Data);
1135
+ rrdset_done(eq->st_exchange_queue_internal_active_remote_delivery);
1136
+}
1137
+
1138
+static void netdata_exchange_queue_unreachable(struct exchange_queue *eq, char *mailbox, int update_every)
1139
+{
1140
+ if (unlikely(!eq->st_exchange_queue_unreachable)) {
1141
+ char id[RRD_ID_LENGTH_MAX + 1];
1142
+ snprintfz(id, RRD_ID_LENGTH_MAX, "exchange_transport_queues_%s_unreachable", mailbox);
1143
+
1144
+ eq->st_exchange_queue_unreachable = rrdset_create_localhost(
1145
+ "exchange",
1146
+ id,
1147
+ NULL,
1148
+ "queue",
1149
+ "exchange.transport_queues_unreachable",
1150
+ "Unreachable Queue length.",
1151
+ "messages",
1152
+ PLUGIN_WINDOWS_NAME,
1153
+ "PerflibExchange",
1154
+ PRIO_EXCHANGE_QUEUE_UNREACHABLE,
1155
+ update_every,
1156
+ RRDSET_TYPE_LINE);
1157
+
1158
+ eq->rd_exchange_queue_unreachable =
1159
+ rrddim_add(eq->st_exchange_queue_unreachable, "unreachable", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
1160
+
1161
+ rrdlabels_add(eq->st_exchange_queue_unreachable->rrdlabels, "mailbox", mailbox, RRDLABEL_SRC_AUTO);
1162
+ }
1163
+
1164
+ rrddim_set_by_pointer(
1165
+ eq->st_exchange_queue_unreachable,
1166
+ eq->rd_exchange_queue_unreachable,
1167
+ (collected_number)eq->exchangeTransportQueuesUnreachable.current.Data);
1168
+ rrdset_done(eq->st_exchange_queue_unreachable);
1169
+}
1170
+
1171
+static void netdata_exchange_queue_poison(struct exchange_queue *eq, char *mailbox, int update_every)
1172
+{
1173
+ if (unlikely(!eq->st_exchange_queue_poison)) {
1174
+ char id[RRD_ID_LENGTH_MAX + 1];
1175
+ snprintfz(id, RRD_ID_LENGTH_MAX, "exchange_transport_queues_%s_poison", mailbox);
1176
+
1177
+ eq->st_exchange_queue_poison = rrdset_create_localhost(
1178
+ "exchange",
1179
+ id,
1180
+ NULL,
1181
+ "queue",
1182
+ "exchange.transport_queues_poison",
1183
+ "Poison Queue Length.",
1184
+ "messages",
1185
+ PLUGIN_WINDOWS_NAME,
1186
+ "PerflibExchange",
1187
+ PRIO_EXCHANGE_QUEUE_POISON,
1188
+ update_every,
1189
+ RRDSET_TYPE_LINE);
1190
+
1191
+ eq->rd_exchange_queue_poison =
1192
+ rrddim_add(eq->st_exchange_queue_poison, "poison", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
1193
+
1194
+ rrdlabels_add(eq->st_exchange_queue_poison->rrdlabels, "mailbox", mailbox, RRDLABEL_SRC_AUTO);
1195
+ }
1196
+
1197
+ rrddim_set_by_pointer(
1198
+ eq->st_exchange_queue_poison,
1199
+ eq->rd_exchange_queue_poison,
1200
+ (collected_number)eq->exchangeTransportQueuesPoison.current.Data);
1201
+ rrdset_done(eq->st_exchange_queue_poison);
1202
+}
1203
+
1204
+static void netdata_exchange_queues(PERF_DATA_BLOCK *pDataBlock, PERF_OBJECT_TYPE *pObjectType, int update_every)
1205
+{
1206
+ PERF_INSTANCE_DEFINITION *pi = NULL;
1207
+ for (LONG i = 0; i < pObjectType->NumInstances; i++) {
1208
+ pi = perflibForEachInstance(pDataBlock, pObjectType, pi);
1209
+ if (!pi)
1210
+ break;
1211
+
1212
+ if (!getInstanceName(pDataBlock, pObjectType, pi, windows_shared_buffer, sizeof(windows_shared_buffer)))
1213
+ strncpyz(windows_shared_buffer, "[unknown]", sizeof(windows_shared_buffer) - 1);
1214
+
1215
+ // Remove 'queue' from instance name
1216
+ char *ptr = strchr(windows_shared_buffer, ' ');
1217
+ if (ptr)
1218
+ *ptr = '\0';
1219
+
1220
+ if (strcasecmp(windows_shared_buffer, "_Total") == 0 || strcasecmp(windows_shared_buffer, "total") == 0)
1221
+ continue;
1222
+
1223
+ struct exchange_queue *eq = dictionary_set(exchange_queues, windows_shared_buffer, NULL, sizeof(*eq));
1224
+ if (!eq)
1225
+ continue;
1226
+
1227
+ if (perflibGetObjectCounter(pDataBlock, pObjectType, &eq->exchangeTransportQueuesActiveMailboxDelivery))
1228
+ netdata_exchange_queue_active_mailbox(eq, windows_shared_buffer, update_every);
1229
+
1230
+ if (perflibGetObjectCounter(pDataBlock, pObjectType, &eq->exchangeTransportQueuesExternalActiveRemoteDelivery))
1231
+ netdata_exchange_queue_external_active_remote_delivery(eq, windows_shared_buffer, update_every);
1232
+
1233
+ if (perflibGetObjectCounter(pDataBlock, pObjectType, &eq->exchangeTransportQueuesInternalActiveRemoteDeliery))
1234
+ netdata_exchange_queue_internal_active_remote_delivery(eq, windows_shared_buffer, update_every);
1235
+
1236
+ if (perflibGetObjectCounter(pDataBlock, pObjectType, &eq->exchangeTransportQueuesUnreachable))
1237
+ netdata_exchange_queue_unreachable(eq, windows_shared_buffer, update_every);
1238
+
1239
+ if (perflibGetObjectCounter(pDataBlock, pObjectType, &eq->exchangeTransportQueuesPoison))
1240
+ netdata_exchange_queue_poison(eq, windows_shared_buffer, update_every);
1241
+ }
1242
+}
1243
+
1244
+struct netdata_exchange_objects {
1245
+ void (*fnct)(PERF_DATA_BLOCK *, PERF_OBJECT_TYPE *, int);
1246
+ char *object;
1247
+} exchange_obj[] = {
1248
+ {.fnct = netdata_exchange_owa, .object = "MSExchange OWA"},
1249
+ {.fnct = netdata_exchange_active_sync, .object = "MSExchange ActiveSync"},
1250
+ {.fnct = netdata_exchange_auto_discover, .object = "MSExchangeAutodiscover"},
1251
+ {.fnct = netdata_exchange_availability_service, .object = "MSExchange Availability Service"},
1252
+ {.fnct = netdata_exchange_rpc, .object = "MSExchange RpcClientAccess"},
1253
+ {.fnct = netdata_exchange_proxy, .object = "MSExchange HttpProxy"},
1254
+ {.fnct = netdata_exchange_workload, .object = "MSExchange WorkloadManagement Workloads"},
1255
+ {.fnct = netdata_exchange_queues, .object = "MSExchangeTransport Queues"},
1256
+
1257
+ // This is the end of the loop
1258
+ {.fnct = NULL, .object = NULL}};
1259
+
1260
+int do_PerflibExchange(int update_every, usec_t dt __maybe_unused)
1261
+{
1262
+ static bool initialized = false;
1263
+
1264
+ if (unlikely(!initialized)) {
1265
+ initialize();
1266
+ initialized = true;
1267
+ }
1268
+
1269
+ for (int i = 0; exchange_obj[i].fnct; i++) {
1270
+ DWORD id = RegistryFindIDByName(exchange_obj[i].object);
1271
+ if (id == PERFLIB_REGISTRY_NAME_NOT_FOUND)
1272
+ continue;
1273
+
1274
+ PERF_DATA_BLOCK *pDataBlock = perflibGetPerformanceData(id);
1275
+ if (!pDataBlock)
1276
+ continue;
1277
+
1278
+ PERF_OBJECT_TYPE *pObjectType = perflibFindObjectTypeByName(pDataBlock, exchange_obj[i].object);
1279
+ if (!pObjectType)
1280
+ continue;
1281
+
1282
+ exchange_obj[i].fnct(pDataBlock, pObjectType, update_every);
1283
+ }
1284
+
1285
+ return 0;
1286
+}
src/collectors/windows.plugin/windows_plugin.c
+5
@@ -107,6 +107,11 @@ static struct proc_module {
107
.update_every = 30 * UPDATE_EVERY_MIN,
108
.func = do_PerflibServices},
109
110
+ {.name = "PerflibExchange",
111
+ .dim = "PerflibADFS",
112
+ .enabled = CONFIG_BOOLEAN_YES,
113
+ .update_every = UPDATE_EVERY_MIN,
114
+ .func = do_PerflibExchange},
115
// the terminator of this array
116
{.name = NULL, .dim = NULL, .func = NULL}};
117
src/collectors/windows.plugin/windows_plugin.h
+35
-1
@@ -33,6 +33,7 @@ int do_PerflibADCS(int update_every, usec_t dt);
33
int do_PerflibADFS(int update_every, usec_t dt);
34
int do_PerflibHyperV(int update_every, usec_t dt);
35
int do_PerflibServices(int update_every, usec_t dt);
36
+int do_PerflibExchange(int update_every, usec_t dt __maybe_unused);
37
38
enum PERFLIB_PRIO {
39
PRIO_WEBSITE_IIS_REQUESTS_RATE = 21000, // PRIO selected, because APPS is using 20YYY
@@ -220,7 +221,40 @@ enum PERFLIB_PRIO {
221
PRIO_ADFS_SSO_AUTH,
222
PRIO_ADFS_TRUST_TOKEN_SUCCESS,
223
PRIO_ADFS_USER_PASS_AUTH,
223
- PRIO_ADFS_WSFED_TOKEN_REQUESTS
224
+ PRIO_ADFS_WSFED_TOKEN_REQUESTS,
225
+
226
+ PRIO_EXCHANGE_QUEUE_ACTIVE_MAILBOX_DELIVERY,
227
+ PRIO_EXCHANGE_QUEUE_EXTERNAL_ACTIVE_REMOTE_DELIVERY,
228
+ PRIO_EXCHANGE_QUEUE_EXTERNAL_LARGEST_DELIVERY,
229
+ PRIO_EXCHANGE_QUEUE_INTERNAL_ACTIVE_REMOTE_DELIVERY,
230
+ PRIO_EXCHANGE_QUEUE_INTERNAL_LARGEST_DELIVERY,
231
+ PRIO_EXCHANGE_QUEUE_RETRY_MAILBOX_DELIVERY,
232
+ PRIO_EXCHANGE_QUEUE_UNREACHABLE,
233
+ PRIO_EXCHANGE_QUEUE_POISON,
234
+ PRIO_EXCHANGE_ACTIVE_SYNC_PING_CMDS_PENDING,
235
+ PRIO_EXCHANGE_ACTIVE_SYNC_REQUESTS,
236
+ PRIO_EXCHANGE_ACTIVE_SYNC_CMDS,
237
+ PRIO_EXCHANGE_RPC_ACTIVE_USERS_COUNT,
238
+ PRIO_EXCHANGE_RPC_AVG_LATENCY,
239
+ PRIO_EXCHANGE_RPC_CONNECTION_COUNT,
240
+ PRIO_EXCHANGE_RPC_OPERATIONS_TOTAL,
241
+ PRIO_EXCHANGE_RPC_REQUESTS,
242
+ PRIO_EXCHANGE_RPC_USER_COUNT,
243
+ PRIO_EXCHANGE_OWA_REQUESTS_TOTAL,
244
+ PRIO_EXCHANGE_OWA_UNIQUE_USERS,
245
+ PRIO_EXCHANGE_WORKlOAD_ACTIVE_TASKS,
246
+ PRIO_EXCHANGE_WORKlOAD_COMPLETE_TASKS,
247
+ PRIO_EXCHANGE_WORKlOAD_QUEUE_TASKS,
248
+ PRIO_EXCHANGE_WORKlOAD_YIELDED_TASKS,
249
+ PRIO_EXCHANGE_WORKlOAD_ACTIVITY,
250
+ PRIO_EXCHANGE_PROXY_AVG_AUTH_LATENCY,
251
+ PRIO_EXCHANGE_PROXY_AVG_CAS_PROCESSING_LATENCY,
252
+ PRIO_EXCHANGE_PROXY_MAILBOX_PROXY_FAILURE,
253
+ PRIO_EXCHANGE_PROXY_SERVER_LOCATIOR_AVG_LATENCY,
254
+ PRIO_EXCHANGE_PROXY_OUTSTANDING_PROXY_REQUESTS,
255
+ PRIO_EXCHANGE_PROXY_PROXY_REQUESTS_TOTAL,
256
+ PRIO_EXCHANGE_AUTO_DISCOVER_REQUESTS,
257
+ PRIO_EXCHANGE_AUTO_AVAILABILITY_SERVICES
258
};
259
260
#endif //NETDATA_WINDOWS_PLUGIN_H