@cryptotaxi247 / netdata-1 / commits / 767229d29

Add hyper-v metrics (#18697)

* Add hyper-v metrics * Address review comments Code cleanup * Cleanup adjust labels charts

Stelios Fragkakis committed Nov 4, 2024 at 13:55 UTC 767229d296ecec5d2c14e7725c85de3dfaf87380
6 files changed +1540 -2
CMakeLists.txt
+1
@@ -1526,6 +1526,7 @@ set(WINDOWS_PLUGIN_FILES
1526 src/collectors/windows.plugin/perflib-memory.c
1527 src/collectors/windows.plugin/perflib-processes.c
1528 src/collectors/windows.plugin/perflib-web-service.c
1529 + src/collectors/windows.plugin/perflib-hyperv.c
1530 )
1531
1532 set(PROC_PLUGIN_FILES
src/collectors/all.h
+1 -1
@@ -56,7 +56,7 @@
56 #define NETDATA_CHART_PRIO_SYSTEM_PACKETS 7001 // freebsd only
57 #define NETDATA_CHART_PRIO_WINDOWS_THREADS 8001 // Windows only
58 #define NETDATA_CHART_PRIO_WINDOWS_THERMAL_ZONES 8002 // Windows only
59 -
59 +#define NETDATA_CHART_PRIO_WINDOWS_HYPERV 9000 // Windows only
60
61 // CPU per core
62
src/collectors/windows.plugin/perflib-hyperv.c new
+1534
@@ -0,0 +1,1534 @@
1 +// SPDX-License-Identifier: GPL-3.0-or-later
2 +
3 +#include "windows_plugin.h"
4 +#include "windows-internals.h"
5 +
6 +#define _COMMON_PLUGIN_NAME "windows.plugin"
7 +#define _COMMON_PLUGIN_MODULE_NAME "PerflibHyperV"
8 +#include "../common-contexts/common-contexts.h"
9 +
10 +#define HYPERV "hyperv"
11 +
12 +static long chart_priority = NETDATA_CHART_PRIO_WINDOWS_HYPERV;
13 +
14 +static void get_and_sanitize_instance_value(
15 + PERF_DATA_BLOCK *pDataBlock,
16 + PERF_OBJECT_TYPE *pObjectType,
17 + PERF_INSTANCE_DEFINITION *pi,
18 + char *buffer,
19 + size_t buffer_size)
20 +{
21 + // char wstr[8192];
22 + if (!getInstanceName(pDataBlock, pObjectType, pi, buffer, sizeof(buffer_size))) {
23 + strncpyz(buffer, "[unknown]", buffer_size - 1);
24 + // return;
25 + }
26 + // rrdlabels_sanitize_value(buffer, wstr, buffer_size);
27 +}
28 +
29 +#define DICT_PERF_OPTION (DICT_OPTION_DONT_OVERWRITE_VALUE | DICT_OPTION_FIXED_SIZE)
30 +
31 +#define DEFINE_RD(counter_name) RRDDIM *rd_##counter_name
32 +
33 +#define GET_INSTANCE_COUNTER(counter) \
34 + do { \
35 + perflibGetInstanceCounter(pDataBlock, pObjectType, pi, &p->counter); \
36 + } while (0)
37 +
38 +#define GET_OBJECT_COUNTER(counter) \
39 + do { \
40 + perflibGetObjectCounter(pDataBlock, pObjectType, &p->counter); \
41 + } while (0)
42 +
43 +#define SETP_DIM_VALUE(st, field) \
44 + do { \
45 + rrddim_set_by_pointer(p->st, p->rd_##field, (collected_number)p->field.current.Data); \
46 + } while (0)
47 +
48 +typedef bool (*perf_func_collect)(PERF_DATA_BLOCK *pDataBlock, int update_every, void *data);
49 +
50 +typedef struct {
51 + const char *registry_name;
52 + perf_func_collect function_collect;
53 + dict_cb_insert_t dict_insert_cb;
54 + size_t dict_size;
55 + DICTIONARY *instance;
56 +} hyperv_perf_item;
57 +
58 +struct hypervisor_memory {
59 + bool collected_metadata;
60 + bool charts_created;
61 +
62 + RRDSET *st_pressure;
63 + RRDSET *st_vm_memory_physical;
64 + RRDSET *st_vm_memory_physical_guest_visible;
65 +
66 + DEFINE_RD(CurrentPressure);
67 + DEFINE_RD(PhysicalMemory);
68 + DEFINE_RD(GuestVisiblePhysicalMemory);
69 + DEFINE_RD(GuestAvailableMemory);
70 +
71 + COUNTER_DATA CurrentPressure;
72 + COUNTER_DATA PhysicalMemory;
73 + COUNTER_DATA GuestVisiblePhysicalMemory;
74 + COUNTER_DATA GuestAvailableMemory;
75 +};
76 +
77 +void initialize_hyperv_memory_keys(struct hypervisor_memory *p) {
78 + p->CurrentPressure.key = "Current Pressure";
79 + p->PhysicalMemory.key = "Physical Memory";
80 + p->GuestVisiblePhysicalMemory.key = "Guest Visible Physical Memory";
81 + p->GuestAvailableMemory.key = "Guest Available Memory";
82 +}
83 +
84 +
85 +void dict_hyperv_memory_insert_cb(const DICTIONARY_ITEM *item __maybe_unused, void *value, void *data __maybe_unused) {
86 + struct hypervisor_memory *p = value;
87 + initialize_hyperv_memory_keys(p);
88 +}
89 +
90 +struct hypervisor_partition {
91 + bool collected_metadata;
92 + bool charts_created;
93 +
94 + RRDSET *st_vm_vid_physical_pages_allocated;
95 + RRDSET *st_vm_vid_remote_physical_pages;
96 +
97 + DEFINE_RD(PhysicalPagesAllocated);
98 + DEFINE_RD(RemotePhysicalPages);
99 +
100 + COUNTER_DATA PhysicalPagesAllocated;
101 + COUNTER_DATA RemotePhysicalPages;
102 +
103 +};
104 +
105 +void initialize_hyperv_partition_keys(struct hypervisor_partition *p)
106 +{
107 + p->PhysicalPagesAllocated.key = "Physical Pages Allocated";
108 + p->RemotePhysicalPages.key = "Remote Physical Pages";
109 +}
110 +
111 +void dict_hyperv_partition_insert_cb(const DICTIONARY_ITEM *item __maybe_unused, void *value, void *data __maybe_unused) {
112 + struct hypervisor_partition *p = value;
113 + initialize_hyperv_partition_keys(p);
114 +}
115 +
116 +static bool do_hyperv_memory(PERF_DATA_BLOCK *pDataBlock, int update_every, void *data)
117 +{
118 + hyperv_perf_item *item = data;
119 +
120 + PERF_OBJECT_TYPE *pObjectType = perflibFindObjectTypeByName(pDataBlock, item->registry_name);
121 + if (!pObjectType)
122 + return false;
123 +
124 + PERF_INSTANCE_DEFINITION *pi = NULL;
125 + for(LONG i = 0; i < pObjectType->NumInstances ; i++) {
126 + pi = perflibForEachInstance(pDataBlock, pObjectType, pi);
127 + if (!pi)
128 + break;
129 +
130 + get_and_sanitize_instance_value(pDataBlock, pObjectType, pi, windows_shared_buffer, sizeof(windows_shared_buffer));
131 +
132 + struct hypervisor_memory *p = dictionary_set(item->instance, windows_shared_buffer, NULL, sizeof(*p));
133 +
134 + if(!p->collected_metadata) {
135 + p->collected_metadata = true;
136 + }
137 +
138 + GET_INSTANCE_COUNTER(CurrentPressure);
139 + GET_INSTANCE_COUNTER(PhysicalMemory);
140 + GET_INSTANCE_COUNTER(GuestVisiblePhysicalMemory);
141 + GET_INSTANCE_COUNTER(GuestAvailableMemory);
142 +
143 + if (!p->charts_created) {
144 + p->charts_created = true;
145 + if(!p->st_vm_memory_physical) {
146 + p->st_vm_memory_physical = rrdset_create_localhost(
147 + "vm_memory_physical",
148 + windows_shared_buffer,
149 + NULL,
150 + HYPERV,
151 + HYPERV".vm_memory_physical",
152 + "VM assigned memory",
153 + "bytes",
154 + _COMMON_PLUGIN_NAME,
155 + _COMMON_PLUGIN_MODULE_NAME,
156 + chart_priority++,
157 + update_every,
158 + RRDSET_TYPE_LINE);
159 +
160 + p->st_vm_memory_physical_guest_visible = rrdset_create_localhost(
161 + "vm_memory_physical_guest_visible",
162 + windows_shared_buffer,
163 + NULL,
164 + HYPERV,
165 + HYPERV".vm_memory_physical_guest_visible",
166 + "VM guest visible memory",
167 + "bytes",
168 + _COMMON_PLUGIN_NAME,
169 + _COMMON_PLUGIN_MODULE_NAME,
170 + chart_priority++,
171 + update_every,
172 + RRDSET_TYPE_LINE);
173 +
174 + p->st_pressure = rrdset_create_localhost(
175 + "vm_memory_pressure_current",
176 + windows_shared_buffer,
177 + NULL,
178 + HYPERV,
179 + HYPERV".vm_memory_pressure_current",
180 + "VM Memory Pressure",
181 + "percentage",
182 + _COMMON_PLUGIN_NAME,
183 + _COMMON_PLUGIN_MODULE_NAME,
184 + chart_priority++,
185 + update_every,
186 + RRDSET_TYPE_LINE);
187 +
188 + p->rd_CurrentPressure = rrddim_add(p->st_pressure, "pressure", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
189 + p->rd_PhysicalMemory = rrddim_add(p->st_vm_memory_physical, "assigned_memory", NULL, 1024 * 1024, 1, RRD_ALGORITHM_ABSOLUTE);
190 + p->rd_GuestVisiblePhysicalMemory = rrddim_add(p->st_vm_memory_physical_guest_visible, "visible_memory", NULL, 1024 * 1024, 1, RRD_ALGORITHM_ABSOLUTE);
191 + p->rd_GuestAvailableMemory = rrddim_add(p->st_vm_memory_physical_guest_visible, "available_memory", NULL, 1024 * 1024, 1, RRD_ALGORITHM_ABSOLUTE);
192 +
193 + rrdlabels_add(p->st_vm_memory_physical->rrdlabels, "vm_name", windows_shared_buffer, RRDLABEL_SRC_AUTO);
194 + rrdlabels_add(p->st_pressure->rrdlabels, "vm_name", windows_shared_buffer, RRDLABEL_SRC_AUTO);
195 + rrdlabels_add(p->st_vm_memory_physical_guest_visible->rrdlabels, "vm_name", windows_shared_buffer, RRDLABEL_SRC_AUTO);
196 + }
197 + }
198 +
199 + SETP_DIM_VALUE(st_pressure, CurrentPressure);
200 + SETP_DIM_VALUE(st_vm_memory_physical, PhysicalMemory);
201 + SETP_DIM_VALUE(st_vm_memory_physical_guest_visible, GuestVisiblePhysicalMemory);
202 + SETP_DIM_VALUE(st_vm_memory_physical_guest_visible, GuestAvailableMemory);
203 +
204 + rrdset_done(p->st_pressure);
205 + rrdset_done(p->st_vm_memory_physical);
206 + rrdset_done(p->st_vm_memory_physical_guest_visible);
207 + }
208 +
209 + return true;
210 +}
211 +
212 +static bool do_hyperv_vid_partition(PERF_DATA_BLOCK *pDataBlock, int update_every, void *data)
213 +{
214 + hyperv_perf_item *item = data;
215 + PERF_OBJECT_TYPE *pObjectType = perflibFindObjectTypeByName(pDataBlock, item->registry_name);
216 + if (!pObjectType)
217 + return false;
218 +
219 + PERF_INSTANCE_DEFINITION *pi = NULL;
220 + for(LONG i = 0; i < pObjectType->NumInstances ; i++) {
221 + pi = perflibForEachInstance(pDataBlock, pObjectType, pi);
222 + if (!pi)
223 + break;
224 +
225 + get_and_sanitize_instance_value(pDataBlock, pObjectType, pi, windows_shared_buffer, sizeof(windows_shared_buffer));
226 +
227 + struct hypervisor_partition *p = dictionary_set(item->instance, windows_shared_buffer, NULL, sizeof(*p));
228 +
229 + if(!p->collected_metadata) {
230 +
231 + p->collected_metadata = true;
232 + }
233 +
234 + if(strcasecmp(windows_shared_buffer, "_Total") == 0)
235 + continue;
236 +
237 + GET_INSTANCE_COUNTER(RemotePhysicalPages);
238 + GET_INSTANCE_COUNTER(PhysicalPagesAllocated);
239 +
240 + if (!p->charts_created) {
241 + p->charts_created = true;
242 +
243 + p->st_vm_vid_physical_pages_allocated = rrdset_create_localhost(
244 + "vm_vid_physical_pages_allocated",
245 + windows_shared_buffer,
246 + NULL,
247 + HYPERV,
248 + HYPERV ".vm_vid_physical_pages_allocated",
249 + "VM physical pages allocated",
250 + "pages",
251 + _COMMON_PLUGIN_NAME,
252 + _COMMON_PLUGIN_MODULE_NAME,
253 + chart_priority++,
254 + update_every,
255 + RRDSET_TYPE_LINE);
256 +
257 + p->st_vm_vid_remote_physical_pages = rrdset_create_localhost(
258 + "vm_vid_remote_physical_pages",
259 + windows_shared_buffer,
260 + NULL,
261 + HYPERV,
262 + HYPERV ".vm_vid_remote_physical_pages",
263 + "VM physical pages not allocated from the preferred NUMA node",
264 + "pages",
265 + _COMMON_PLUGIN_NAME,
266 + _COMMON_PLUGIN_MODULE_NAME,
267 + chart_priority++,
268 + update_every,
269 + RRDSET_TYPE_LINE);
270 +
271 + p->rd_PhysicalPagesAllocated = rrddim_add(p->st_vm_vid_physical_pages_allocated, "allocated", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
272 + p->rd_RemotePhysicalPages = rrddim_add(p->st_vm_vid_remote_physical_pages, "remote_physical", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
273 +
274 + rrdlabels_add(p->st_vm_vid_physical_pages_allocated->rrdlabels, "vm_name", windows_shared_buffer, RRDLABEL_SRC_AUTO);
275 + rrdlabels_add(p->st_vm_vid_remote_physical_pages->rrdlabels, "vm_name", windows_shared_buffer, RRDLABEL_SRC_AUTO);
276 + }
277 +
278 + SETP_DIM_VALUE(st_vm_vid_remote_physical_pages, RemotePhysicalPages);
279 + SETP_DIM_VALUE(st_vm_vid_physical_pages_allocated, PhysicalPagesAllocated);
280 +
281 + rrdset_done(p->st_vm_vid_physical_pages_allocated);
282 + rrdset_done(p->st_vm_vid_remote_physical_pages);
283 + }
284 +
285 + return true;
286 +}
287 +
288 +// Define structure for Hyper-V Virtual Machine Health Summary
289 +static struct hypervisor_health_summary {
290 + bool collected_metadata;
291 + bool charts_created;
292 +
293 + RRDSET *st_health;
294 +
295 + DEFINE_RD(HealthCritical);
296 + DEFINE_RD(HealthOk);
297 +
298 + COUNTER_DATA HealthCritical;
299 + COUNTER_DATA HealthOk;
300 +} health_summary = {
301 + .collected_metadata = false,
302 + .st_health = NULL,
303 + .HealthCritical.key = "Health Critical",
304 + .HealthOk.key = "Health Ok"};
305 +
306 +// Function to handle "Hyper-V Virtual Machine Health Summary"
307 +static bool do_hyperv_health_summary(PERF_DATA_BLOCK *pDataBlock, int update_every, void *data)
308 +{
309 + hyperv_perf_item *item = data;
310 +
311 + PERF_OBJECT_TYPE *pObjectType = perflibFindObjectTypeByName(pDataBlock, item->registry_name);
312 + if (!pObjectType)
313 + return false;
314 +
315 + struct hypervisor_health_summary *p = &health_summary;
316 +
317 + GET_OBJECT_COUNTER(HealthCritical);
318 + GET_OBJECT_COUNTER(HealthOk);
319 +
320 + if (!p->charts_created) {
321 + p->charts_created = true;
322 + p->st_health = rrdset_create_localhost(
323 + "vms_health",
324 + windows_shared_buffer,
325 + NULL,
326 + HYPERV,
327 + HYPERV ".vms_health",
328 + "Virtual machines health status",
329 + "vms",
330 + _COMMON_PLUGIN_NAME,
331 + _COMMON_PLUGIN_MODULE_NAME,
332 + chart_priority++,
333 + update_every,
334 + RRDSET_TYPE_STACKED);
335 +
336 + p->rd_HealthCritical = rrddim_add(p->st_health, "critical", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
337 + p->rd_HealthOk = rrddim_add(p->st_health, "ok", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
338 +
339 + rrdlabels_add(p->st_health->rrdlabels, "vm_name", windows_shared_buffer, RRDLABEL_SRC_AUTO);
340 + }
341 +
342 + SETP_DIM_VALUE(st_health, HealthCritical);
343 + SETP_DIM_VALUE(st_health, HealthOk);
344 +
345 + rrdset_done(p->st_health);
346 + return true;
347 +}
348 +
349 +// Define structure for Hyper-V Root Partition Metrics (Device and GPA Space Pages)
350 +struct hypervisor_root_partition {
351 + bool collected_metadata;
352 + bool charts_created;
353 +
354 + RRDSET *st_device_space_pages;
355 + RRDSET *st_gpa_space_pages;
356 + RRDSET *st_gpa_space_modifications;
357 + RRDSET *st_attached_devices;
358 + RRDSET *st_deposited_pages;
359 +
360 + RRDSET *st_DeviceDMAErrors;
361 + RRDSET *st_DeviceInterruptErrors;
362 + RRDSET *st_DeviceInterruptThrottleEvents;
363 + RRDSET *st_IOΤLBFlushesSec;
364 + RRDSET *st_AddressSpaces;
365 + RRDSET *st_VirtualTLBPages;
366 + RRDSET *st_VirtualTLBFlushEntiresSec;
367 +
368 + DEFINE_RD(DeviceSpacePages4K);
369 + DEFINE_RD(DeviceSpacePages2M);
370 + DEFINE_RD(DeviceSpacePages1G);
371 + DEFINE_RD(GPASpacePages4K);
372 + DEFINE_RD(GPASpacePages2M);
373 + DEFINE_RD(GPASpacePages1G);
374 + DEFINE_RD(GPASpaceModifications);
375 +
376 + DEFINE_RD(AttachedDevices);
377 + DEFINE_RD(DepositedPages);
378 +
379 + DEFINE_RD(DeviceDMAErrors);
380 + DEFINE_RD(DeviceInterruptErrors);
381 + DEFINE_RD(DeviceInterruptThrottleEvents);
382 + DEFINE_RD(IOΤLBFlushesSec);
383 + DEFINE_RD(AddressSpaces);
384 + DEFINE_RD(VirtualTLBPages);
385 + DEFINE_RD(VirtualTLBFlushEntiresSec);
386 +
387 + COUNTER_DATA DeviceSpacePages4K;
388 + COUNTER_DATA DeviceSpacePages2M;
389 + COUNTER_DATA DeviceSpacePages1G;
390 + COUNTER_DATA GPASpacePages4K;
391 + COUNTER_DATA GPASpacePages2M;
392 + COUNTER_DATA GPASpacePages1G;
393 + COUNTER_DATA GPASpaceModifications;
394 + COUNTER_DATA AttachedDevices;
395 + COUNTER_DATA DepositedPages;
396 + COUNTER_DATA DeviceDMAErrors;
397 + COUNTER_DATA DeviceInterruptErrors;
398 + COUNTER_DATA DeviceInterruptThrottleEvents;
399 + COUNTER_DATA IOΤLBFlushesSec;
400 + COUNTER_DATA AddressSpaces;
401 + COUNTER_DATA VirtualTLBPages;
402 + COUNTER_DATA VirtualTLBFlushEntiresSec;
403 +};
404 +
405 +// Initialize the keys for the root partition metrics
406 +void initialize_hyperv_root_partition_keys(struct hypervisor_root_partition *p) {
407 + p->DeviceSpacePages4K.key = "4K device pages";
408 + p->DeviceSpacePages2M.key = "2M device pages";
409 + p->DeviceSpacePages1G.key = "1G device pages";
410 +
411 + p->GPASpacePages4K.key = "4K GPA pages";
412 + p->GPASpacePages2M.key = "2M GPA pages";
413 + p->GPASpacePages1G.key = "1G GPA pages";
414 +
415 + p->GPASpaceModifications.key = "GPA Space Modifications/sec";
416 + p->AttachedDevices.key = "Attached Devices";
417 + p->DepositedPages.key = "Deposited Pages";
418 +
419 + p->DeviceDMAErrors.key = "Device DMA Errors";
420 + p->DeviceInterruptErrors.key = "Device Interrupt Errors";
421 + p->DeviceInterruptThrottleEvents.key = "Device Interrupt Throttle Events";
422 + p->IOΤLBFlushesSec.key = "I/O TLB Flushes/sec";
423 + p->AddressSpaces.key = "Address Spaces";
424 + p->VirtualTLBPages.key = "Virtual TLB Pages";
425 + p->VirtualTLBFlushEntiresSec.key = "Virtual TLB Flush Entires/sec";
426 +}
427 +
428 +// Callback function for inserting root partition metrics into the dictionary
429 +void dict_hyperv_root_partition_insert_cb(const DICTIONARY_ITEM *item __maybe_unused, void *value, void *data __maybe_unused) {
430 + struct hypervisor_root_partition *p = value;
431 + initialize_hyperv_root_partition_keys(p);
432 +}
433 +
434 +// Function to handle "Hyper-V Hypervisor Root Partition" metrics (Device Space and GPA Space)
435 +static bool do_hyperv_root_partition(PERF_DATA_BLOCK *pDataBlock, int update_every, void *data)
436 +{
437 + hyperv_perf_item *item = data;
438 +
439 + PERF_OBJECT_TYPE *pObjectType = perflibFindObjectTypeByName(pDataBlock, item->registry_name);
440 + if (!pObjectType)
441 + return false;
442 +
443 + PERF_INSTANCE_DEFINITION *pi = NULL;
444 + for (LONG i = 0; i < pObjectType->NumInstances; i++) {
445 + pi = perflibForEachInstance(pDataBlock, pObjectType, pi);
446 + if (!pi)
447 + break;
448 +
449 + get_and_sanitize_instance_value(pDataBlock, pObjectType, pi, windows_shared_buffer, sizeof(windows_shared_buffer));
450 +
451 + if(strcasecmp(windows_shared_buffer, "_Total") == 0)
452 + continue;
453 +
454 + struct hypervisor_root_partition *p = dictionary_set(item->instance, windows_shared_buffer, NULL, sizeof(*p));
455 +
456 + if (!p->collected_metadata) {
457 + p->collected_metadata = true;
458 + }
459 +
460 + // Fetch counters
461 + GET_INSTANCE_COUNTER(DeviceSpacePages4K);
462 + GET_INSTANCE_COUNTER(DeviceSpacePages2M);
463 + GET_INSTANCE_COUNTER(DeviceSpacePages1G);
464 + GET_INSTANCE_COUNTER(GPASpacePages4K);
465 + GET_INSTANCE_COUNTER(GPASpacePages2M);
466 + GET_INSTANCE_COUNTER(GPASpacePages1G);
467 + GET_INSTANCE_COUNTER(GPASpaceModifications);
468 + GET_INSTANCE_COUNTER(AttachedDevices);
469 + GET_INSTANCE_COUNTER(DepositedPages);
470 +
471 + GET_INSTANCE_COUNTER(DeviceDMAErrors);
472 + GET_INSTANCE_COUNTER(DeviceInterruptErrors);
473 + GET_INSTANCE_COUNTER(DeviceInterruptThrottleEvents);
474 + GET_INSTANCE_COUNTER(IOΤLBFlushesSec);
475 + GET_INSTANCE_COUNTER(AddressSpaces);
476 + GET_INSTANCE_COUNTER(VirtualTLBPages);
477 + GET_INSTANCE_COUNTER(VirtualTLBFlushEntiresSec);
478 +
479 +
480 + // Create charts
481 + if (!p->charts_created) {
482 + p->charts_created = true;
483 + p->st_device_space_pages = rrdset_create_localhost(
484 + "root_partition_device_space_pages",
485 + windows_shared_buffer,
486 + NULL,
487 + HYPERV,
488 + HYPERV ".root_partition_device_space_pages",
489 + "Root partition device space pages",
490 + "pages",
491 + _COMMON_PLUGIN_NAME,
492 + _COMMON_PLUGIN_MODULE_NAME,
493 + chart_priority++,
494 + update_every,
495 + RRDSET_TYPE_LINE);
496 +
497 + p->rd_DeviceSpacePages4K = rrddim_add(p->st_device_space_pages, "4K", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
498 + p->rd_DeviceSpacePages2M = rrddim_add(p->st_device_space_pages, "2M", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
499 + p->rd_DeviceSpacePages1G = rrddim_add(p->st_device_space_pages, "1G", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
500 + rrdlabels_add(p->st_device_space_pages->rrdlabels, "vm_name", windows_shared_buffer, RRDLABEL_SRC_AUTO);
501 +
502 + p->st_gpa_space_pages = rrdset_create_localhost(
503 + "root_partition_gpa_space_pages",
504 + windows_shared_buffer,
505 + NULL,
506 + HYPERV,
507 + HYPERV ".root_partition_gpa_space_pages",
508 + "Root partition GPA space pages",
509 + "pages",
510 + _COMMON_PLUGIN_NAME,
511 + _COMMON_PLUGIN_MODULE_NAME,
512 + chart_priority++,
513 + update_every,
514 + RRDSET_TYPE_LINE);
515 +
516 + p->rd_GPASpacePages4K = rrddim_add(p->st_gpa_space_pages, "4K", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
517 + p->rd_GPASpacePages2M = rrddim_add(p->st_gpa_space_pages, "2M", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
518 + p->rd_GPASpacePages1G = rrddim_add(p->st_gpa_space_pages, "1G", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
519 + rrdlabels_add(p->st_gpa_space_pages->rrdlabels, "vm_name", windows_shared_buffer, RRDLABEL_SRC_AUTO);
520 +
521 + p->st_gpa_space_modifications = rrdset_create_localhost(
522 + "root_partition_gpa_space_modifications",
523 + windows_shared_buffer,
524 + NULL,
525 + HYPERV,
526 + HYPERV ".root_partition_gpa_space_modifications",
527 + "Root partition GPA space modifications",
528 + "modifications/s",
529 + _COMMON_PLUGIN_NAME,
530 + _COMMON_PLUGIN_MODULE_NAME,
531 + chart_priority++,
532 + update_every,
533 + RRDSET_TYPE_LINE);
534 +
535 + p->rd_GPASpaceModifications =
536 + rrddim_add(p->st_gpa_space_modifications, "gpa", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
537 + rrdlabels_add(p->st_gpa_space_modifications->rrdlabels, "vm_name", windows_shared_buffer, RRDLABEL_SRC_AUTO);
538 +
539 + p->st_attached_devices = rrdset_create_localhost(
540 + "root_partition_attached_devices",
541 + windows_shared_buffer,
542 + NULL,
543 + HYPERV,
544 + HYPERV ".root_partition_attached_devices",
545 + "Root partition attached devices",
546 + "devices",
547 + _COMMON_PLUGIN_NAME,
548 + _COMMON_PLUGIN_MODULE_NAME,
549 + chart_priority++,
550 + update_every,
551 + RRDSET_TYPE_LINE);
552 +
553 + p->rd_AttachedDevices = rrddim_add(p->st_attached_devices, "attached", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
554 + rrdlabels_add(p->st_attached_devices->rrdlabels, "vm_name", windows_shared_buffer, RRDLABEL_SRC_AUTO);
555 +
556 + p->st_deposited_pages = rrdset_create_localhost(
557 + "root_partition_deposited_pages",
558 + windows_shared_buffer,
559 + NULL,
560 + HYPERV,
561 + HYPERV ".root_partition_deposited_pages",
562 + "Root partition deposited pages",
563 + "pages",
564 + _COMMON_PLUGIN_NAME,
565 + _COMMON_PLUGIN_MODULE_NAME,
566 + chart_priority++,
567 + update_every,
568 + RRDSET_TYPE_LINE);
569 +
570 + p->rd_DepositedPages = rrddim_add(p->st_deposited_pages, "gpa", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
571 + rrdlabels_add(p->st_deposited_pages->rrdlabels, "vm_name", windows_shared_buffer, RRDLABEL_SRC_AUTO);
572 +
573 + p->st_DeviceDMAErrors = rrdset_create_localhost(
574 + "root_partition_device_dma_errors",
575 + windows_shared_buffer,
576 + NULL,
577 + HYPERV,
578 + HYPERV ".root_partition_device_dma_errors",
579 + "Root partition illegal DMA requests",
580 + "requests",
581 + _COMMON_PLUGIN_NAME,
582 + _COMMON_PLUGIN_MODULE_NAME,
583 + chart_priority++,
584 + update_every,
585 + RRDSET_TYPE_LINE);
586 +
587 + p->rd_DeviceDMAErrors =
588 + rrddim_add(p->st_DeviceDMAErrors, "illegal_dma", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
589 + rrdlabels_add(p->st_DeviceDMAErrors->rrdlabels, "vm_name", windows_shared_buffer, RRDLABEL_SRC_AUTO);
590 +
591 + p->st_DeviceInterruptErrors = rrdset_create_localhost(
592 + "root_partition_device_interrupt_errors",
593 + windows_shared_buffer,
594 + NULL,
595 + HYPERV,
596 + HYPERV ".root_partition_device_interrupt_errors",
597 + "Root partition illegal interrupt requestss",
598 + "requests",
599 + _COMMON_PLUGIN_NAME,
600 + _COMMON_PLUGIN_MODULE_NAME,
601 + chart_priority++,
602 + update_every,
603 + RRDSET_TYPE_LINE);
604 +
605 + p->rd_DeviceInterruptErrors =
606 + rrddim_add(p->st_DeviceInterruptErrors, "illegal_interrupt", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
607 + rrdlabels_add(p->st_DeviceInterruptErrors->rrdlabels, "vm_name", windows_shared_buffer, RRDLABEL_SRC_AUTO);
608 +
609 + p->st_DeviceInterruptThrottleEvents = rrdset_create_localhost(
610 + "root_partition_device_interrupt_throttle_events",
611 + windows_shared_buffer,
612 + NULL,
613 + HYPERV,
614 + HYPERV ".root_partition_device_interrupt_throttle_events",
615 + "Root partition throttled interrupts",
616 + "events",
617 + _COMMON_PLUGIN_NAME,
618 + _COMMON_PLUGIN_MODULE_NAME,
619 + chart_priority++,
620 + update_every,
621 + RRDSET_TYPE_LINE);
622 +
623 + p->rd_DeviceInterruptThrottleEvents =
624 + rrddim_add(p->st_DeviceInterruptThrottleEvents, "throttling", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
625 + rrdlabels_add(
626 + p->st_DeviceInterruptThrottleEvents->rrdlabels, "vm_name", windows_shared_buffer, RRDLABEL_SRC_AUTO);
627 +
628 + p->st_IOΤLBFlushesSec = rrdset_create_localhost(
629 + "root_partition_io_tlb_flush",
630 + windows_shared_buffer,
631 + NULL,
632 + HYPERV,
633 + HYPERV ".root_partition_io_tlb_flush",
634 + "Root partition flushes of I/O TLBs",
635 + "flushes/s",
636 + _COMMON_PLUGIN_NAME,
637 + _COMMON_PLUGIN_MODULE_NAME,
638 + chart_priority++,
639 + update_every,
640 + RRDSET_TYPE_LINE);
641 +
642 + p->rd_IOΤLBFlushesSec = rrddim_add(p->st_IOΤLBFlushesSec, "gpa", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
643 + rrdlabels_add(p->st_IOΤLBFlushesSec->rrdlabels, "vm_name", windows_shared_buffer, RRDLABEL_SRC_AUTO);
644 +
645 + p->st_AddressSpaces = rrdset_create_localhost(
646 + "root_partition_address_space",
647 + windows_shared_buffer,
648 + NULL,
649 + HYPERV,
650 + HYPERV ".root_partition_address_space",
651 + "Root partition address spaces in the virtual TLB",
652 + "address spaces",
653 + _COMMON_PLUGIN_NAME,
654 + _COMMON_PLUGIN_MODULE_NAME,
655 + chart_priority++,
656 + update_every,
657 + RRDSET_TYPE_LINE);
658 +
659 + p->rd_AddressSpaces = rrddim_add(p->st_AddressSpaces, "address_spaces", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
660 + rrdlabels_add(p->st_AddressSpaces->rrdlabels, "vm_name", windows_shared_buffer, RRDLABEL_SRC_AUTO);
661 +
662 + p->st_VirtualTLBPages = rrdset_create_localhost(
663 + "root_partition_virtual_tlb_pages",
664 + windows_shared_buffer,
665 + NULL,
666 + HYPERV,
667 + HYPERV ".root_partition_virtual_tlb_pages",
668 + "Root partition pages used by the virtual TLB",
669 + "pages",
670 + _COMMON_PLUGIN_NAME,
671 + _COMMON_PLUGIN_MODULE_NAME,
672 + chart_priority++,
673 + update_every,
674 + RRDSET_TYPE_LINE);
675 +
676 + p->rd_VirtualTLBPages = rrddim_add(p->st_VirtualTLBPages, "used", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
677 + rrdlabels_add(p->st_VirtualTLBPages->rrdlabels, "vm_name", windows_shared_buffer, RRDLABEL_SRC_AUTO);
678 +
679 + p->st_VirtualTLBFlushEntiresSec = rrdset_create_localhost(
680 + "root_partition_virtual_tlb_flush_entries",
681 + windows_shared_buffer,
682 + NULL,
683 + HYPERV,
684 + HYPERV ".root_partition_virtual_tlb_flush_entries",
685 + "Root partition flushes of the entire virtual TLB",
686 + "flushes/s",
687 + _COMMON_PLUGIN_NAME,
688 + _COMMON_PLUGIN_MODULE_NAME,
689 + chart_priority++,
690 + update_every,
691 + RRDSET_TYPE_LINE);
692 +
693 + p->rd_VirtualTLBFlushEntiresSec =
694 + rrddim_add(p->st_VirtualTLBFlushEntiresSec, "flushes", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
695 + rrdlabels_add(p->st_VirtualTLBFlushEntiresSec->rrdlabels, "vm_name", windows_shared_buffer, RRDLABEL_SRC_AUTO);
696 + }
697 +
698 + // Set the data for each dimension
699 +
700 + SETP_DIM_VALUE(st_device_space_pages,DeviceSpacePages4K);
701 + SETP_DIM_VALUE(st_device_space_pages,DeviceSpacePages2M);
702 + SETP_DIM_VALUE(st_device_space_pages,DeviceSpacePages1G);
703 +
704 + SETP_DIM_VALUE(st_gpa_space_pages, GPASpacePages4K);
705 + SETP_DIM_VALUE(st_gpa_space_pages, GPASpacePages2M);
706 + SETP_DIM_VALUE(st_gpa_space_pages, GPASpacePages1G);
707 +
708 + SETP_DIM_VALUE(st_gpa_space_modifications, GPASpaceModifications);
709 +
710 + SETP_DIM_VALUE(st_attached_devices, AttachedDevices);
711 + SETP_DIM_VALUE(st_deposited_pages, DepositedPages);
712 +
713 + SETP_DIM_VALUE(st_DeviceDMAErrors, DeviceDMAErrors);
714 + SETP_DIM_VALUE(st_DeviceInterruptErrors, DeviceInterruptErrors);
715 + SETP_DIM_VALUE(st_DeviceInterruptThrottleEvents, DeviceInterruptThrottleEvents);
716 + SETP_DIM_VALUE(st_IOΤLBFlushesSec, IOΤLBFlushesSec);
717 + SETP_DIM_VALUE(st_AddressSpaces, AddressSpaces);
718 + SETP_DIM_VALUE(st_VirtualTLBPages, VirtualTLBPages);
719 + SETP_DIM_VALUE(st_VirtualTLBFlushEntiresSec, VirtualTLBFlushEntiresSec);
720 +
721 + // Mark the charts as done
722 + rrdset_done(p->st_device_space_pages);
723 + rrdset_done(p->st_gpa_space_pages);
724 + rrdset_done(p->st_gpa_space_modifications);
725 + rrdset_done(p->st_attached_devices);
726 + rrdset_done(p->st_deposited_pages);
727 + rrdset_done(p->st_DeviceInterruptErrors);
728 + rrdset_done(p->st_DeviceInterruptThrottleEvents);
729 + rrdset_done(p->st_IOΤLBFlushesSec);
730 + rrdset_done(p->st_AddressSpaces);
731 + rrdset_done(p->st_DeviceDMAErrors);
732 + rrdset_done(p->st_VirtualTLBPages);
733 + rrdset_done(p->st_VirtualTLBFlushEntiresSec);
734 + }
735 +
736 + return true;
737 +}
738 +
739 +// Storage DEVICE
740 +
741 +struct hypervisor_storage_device {
742 + bool collected_metadata;
743 + bool charts_created;
744 +
745 + RRDSET *st_operations;
746 + DEFINE_RD(ReadOperationsSec);
747 + DEFINE_RD(WriteOperationsSec);
748 +
749 + RRDSET *st_bytes;
750 + DEFINE_RD(ReadBytesSec);
751 + DEFINE_RD(WriteBytesSec);
752 +
753 + RRDSET *st_errors;
754 + DEFINE_RD(ErrorCount);
755 +
756 + COUNTER_DATA ReadOperationsSec;
757 + COUNTER_DATA WriteOperationsSec;
758 +
759 + COUNTER_DATA ReadBytesSec;
760 + COUNTER_DATA WriteBytesSec;
761 + COUNTER_DATA ErrorCount;
762 +};
763 +
764 +
765 +// Initialize the keys for the root partition metrics
766 +void initialize_hyperv_storage_device_keys(struct hypervisor_storage_device *p) {
767 + p->ReadOperationsSec.key = "Read Operations/Sec";
768 + p->WriteOperationsSec.key = "Write Operations/Sec";
769 +
770 + p->ReadBytesSec.key = "Read Bytes/sec";
771 + p->WriteBytesSec.key = "Write Bytes/sec";
772 + p->ErrorCount.key = "Error Count";
773 +}
774 +
775 +// Callback function for inserting root partition metrics into the dictionary
776 +void dict_hyperv_storage_device_insert_cb(const DICTIONARY_ITEM *item __maybe_unused, void *value, void *data __maybe_unused) {
777 + struct hypervisor_storage_device *p = value;
778 + initialize_hyperv_storage_device_keys(p);
779 +}
780 +
781 +static bool do_hyperv_storage_device(PERF_DATA_BLOCK *pDataBlock, int update_every, void *data)
782 +{
783 + hyperv_perf_item *item = data;
784 +
785 + PERF_OBJECT_TYPE *pObjectType = perflibFindObjectTypeByName(pDataBlock, item->registry_name);
786 + if (!pObjectType)
787 + return false;
788 +
789 +
790 + PERF_INSTANCE_DEFINITION *pi = NULL;
791 + for (LONG i = 0; i < pObjectType->NumInstances; i++) {
792 + pi = perflibForEachInstance(pDataBlock, pObjectType, pi);
793 + if (!pi)
794 + break;
795 +
796 + get_and_sanitize_instance_value(pDataBlock, pObjectType, pi, windows_shared_buffer, sizeof(windows_shared_buffer));
797 +
798 + if(strcasecmp(windows_shared_buffer, "_Total") == 0)
799 + continue;
800 +
801 + struct hypervisor_storage_device *p = dictionary_set(item->instance, windows_shared_buffer, NULL, sizeof(*p));
802 +
803 + if (!p->collected_metadata) {
804 + p->collected_metadata = true;
805 + }
806 +
807 + // Fetch counters
808 + GET_INSTANCE_COUNTER(ReadOperationsSec);
809 + GET_INSTANCE_COUNTER(WriteOperationsSec);
810 +
811 + GET_INSTANCE_COUNTER(ReadBytesSec);
812 + GET_INSTANCE_COUNTER(WriteBytesSec);
813 + GET_INSTANCE_COUNTER(ErrorCount);
814 +
815 + if (!p->charts_created) {
816 + p->charts_created = true;
817 + if (!p->st_operations) {
818 + p->st_operations = rrdset_create_localhost(
819 + "vm_storage_device_operations",
820 + windows_shared_buffer,
821 + NULL,
822 + HYPERV,
823 + HYPERV".vm_storage_device_operations",
824 + "VM storage device IOPS",
825 + "operations/sec",
826 + _COMMON_PLUGIN_NAME,
827 + _COMMON_PLUGIN_MODULE_NAME,
828 + chart_priority++,
829 + update_every,
830 + RRDSET_TYPE_LINE);
831 +
832 + p->rd_ReadOperationsSec = rrddim_add(p->st_operations, "read", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
833 + p->rd_WriteOperationsSec = rrddim_add(p->st_operations, "write", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
834 +
835 + rrdlabels_add(p->st_operations->rrdlabels, "vm_storage_device", windows_shared_buffer, RRDLABEL_SRC_AUTO);
836 + }
837 +
838 + if (!p->st_bytes) {
839 + p->st_bytes = rrdset_create_localhost(
840 + "vm_storage_device_bytes",
841 + windows_shared_buffer,
842 + NULL,
843 + HYPERV,
844 + HYPERV".vm_storage_device_bytes",
845 + "VM storage device IO",
846 + "bytes/sec",
847 + _COMMON_PLUGIN_NAME,
848 + _COMMON_PLUGIN_MODULE_NAME,
849 + chart_priority++,
850 + update_every,
851 + RRDSET_TYPE_AREA);
852 +
853 + p->rd_ReadBytesSec = rrddim_add(p->st_bytes, "read", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
854 + p->rd_WriteBytesSec = rrddim_add(p->st_bytes, "write", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
855 +
856 + rrdlabels_add(p->st_bytes->rrdlabels, "vm_storage_device", windows_shared_buffer, RRDLABEL_SRC_AUTO);
857 + }
858 +
859 + if (!p->st_errors) {
860 + p->st_errors = rrdset_create_localhost(
861 + "vm_storage_device_errors",
862 + windows_shared_buffer,
863 + NULL,
864 + HYPERV,
865 + HYPERV".vm_storage_device_errors",
866 + "VM storage device errors",
867 + "errors/sec",
868 + _COMMON_PLUGIN_NAME,
869 + _COMMON_PLUGIN_MODULE_NAME,
870 + chart_priority++,
871 + update_every,
872 + RRDSET_TYPE_LINE);
873 +
874 + p->rd_ErrorCount = rrddim_add(p->st_errors, "errors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
875 +
876 + rrdlabels_add(p->st_errors->rrdlabels, "vm_storage_device", windows_shared_buffer, RRDLABEL_SRC_AUTO);
877 + }
878 + }
879 +
880 + SETP_DIM_VALUE(st_operations,ReadOperationsSec);
881 + SETP_DIM_VALUE(st_operations,WriteOperationsSec);
882 +
883 + SETP_DIM_VALUE(st_bytes,ReadBytesSec);
884 + SETP_DIM_VALUE(st_bytes,WriteBytesSec);
885 +
886 + SETP_DIM_VALUE(st_errors,ErrorCount);
887 +
888 + // Mark the charts as done
889 + rrdset_done(p->st_operations);
890 + rrdset_done(p->st_bytes);
891 + rrdset_done(p->st_errors);
892 + }
893 +
894 + return true;
895 +}
896 +
897 +struct hypervisor_switch {
898 + bool collected_metadata;
899 + bool charts_created;
900 +
901 + RRDSET *st_bytes;
902 + DEFINE_RD(BytesSentSec);
903 + DEFINE_RD(BytesReceivedSec);
904 +
905 + RRDSET *st_packets;
906 + DEFINE_RD(PacketsSentSec);
907 + DEFINE_RD(PacketsReceivedSec);
908 +
909 + RRDSET *st_directed_packets;
910 + DEFINE_RD(DirectedPacketsSentSec);
911 + DEFINE_RD(DirectedPacketsReceivedSec);
912 +
913 + RRDSET *st_broadcast_packets;
914 + DEFINE_RD(BroadcastPacketsSentSec);
915 + DEFINE_RD(BroadcastPacketsReceivedSec);
916 +
917 + RRDSET *st_multicast_packets;
918 + DEFINE_RD(MulticastPacketsSentSec);
919 + DEFINE_RD(MulticastPacketsReceivedSec);
920 +
921 + RRDSET *st_dropped_packets;
922 + DEFINE_RD(DroppedPacketsOutgoingSec);
923 + DEFINE_RD(DroppedPacketsIncomingSec);
924 +
925 + RRDSET *st_ext_dropped_packets;
926 + DEFINE_RD(ExtensionsDroppedPacketsOutgoingSec);
927 + DEFINE_RD(ExtensionsDroppedPacketsIncomingSec);
928 +
929 + RRDSET *st_flooded;
930 + DEFINE_RD(PacketsFlooded);
931 +
932 + RRDSET *st_learned_mac;
933 + DEFINE_RD(LearnedMacAddresses);
934 +
935 + RRDSET *st_purged_mac;
936 + DEFINE_RD(PurgedMacAddresses);
937 +
938 + COUNTER_DATA BytesSentSec;
939 + COUNTER_DATA BytesReceivedSec;
940 +
941 + COUNTER_DATA PacketsSentSec;
942 + COUNTER_DATA PacketsReceivedSec;
943 +
944 + COUNTER_DATA DirectedPacketsSentSec;
945 + COUNTER_DATA DirectedPacketsReceivedSec;
946 +
947 + COUNTER_DATA BroadcastPacketsSentSec;
948 + COUNTER_DATA BroadcastPacketsReceivedSec;
949 +
950 + COUNTER_DATA MulticastPacketsSentSec;
951 + COUNTER_DATA MulticastPacketsReceivedSec;
952 +
953 + COUNTER_DATA DroppedPacketsOutgoingSec;
954 + COUNTER_DATA DroppedPacketsIncomingSec;
955 +
956 + COUNTER_DATA ExtensionsDroppedPacketsOutgoingSec;
957 + COUNTER_DATA ExtensionsDroppedPacketsIncomingSec;
958 +
959 + COUNTER_DATA PacketsFlooded;
960 +
961 + COUNTER_DATA LearnedMacAddresses;
962 +
963 + COUNTER_DATA PurgedMacAddresses;
964 +};
965 +
966 +// Initialize the keys for the root partition metrics
967 +void initialize_hyperv_switch_keys(struct hypervisor_switch *p)
968 +{
969 + p->BytesSentSec.key = "Bytes Sent/sec";
970 + p->BytesReceivedSec.key = "Bytes Received/sec";
971 + p->PacketsSentSec.key = "Packets Sent/sec";
972 + p->PacketsReceivedSec.key = "Packets Received/sec";
973 +
974 + p->DirectedPacketsSentSec.key = "Directed Packets Sent/sec";
975 + p->DirectedPacketsReceivedSec.key = "Directed Packets Received/sec";
976 + p->BroadcastPacketsSentSec.key = "Broadcast Packets Sent/sec";
977 + p->BroadcastPacketsReceivedSec.key = "Broadcast Packets Received/sec";
978 + p->MulticastPacketsSentSec.key = "Multicast Packets Sent/sec";
979 + p->MulticastPacketsReceivedSec.key = "Multicast Packets Received/sec";
980 + p->DroppedPacketsOutgoingSec.key = "Dropped Packets Outgoing/sec";
981 + p->DroppedPacketsIncomingSec.key = "Dropped Packets Incoming/sec";
982 + p->ExtensionsDroppedPacketsOutgoingSec.key = "Extensions Dropped Packets Outgoing/sec";
983 + p->ExtensionsDroppedPacketsIncomingSec.key = "Extensions Dropped Packets Incoming/sec";
984 + p->PacketsFlooded.key = "Packets Flooded";
985 + p->LearnedMacAddresses.key = "Learned Mac Addresses";
986 + p->PurgedMacAddresses.key = "Purged Mac Addresses";
987 +}
988 +
989 +void dict_hyperv_switch_insert_cb(const DICTIONARY_ITEM *item __maybe_unused, void *value, void *data __maybe_unused)
990 +{
991 + struct hypervisor_switch *p = value;
992 + initialize_hyperv_switch_keys(p);
993 +}
994 +
995 +static bool do_hyperv_switch(PERF_DATA_BLOCK *pDataBlock, int update_every, void *data)
996 +{
997 + hyperv_perf_item *item = data;
998 +
999 + PERF_OBJECT_TYPE *pObjectType = perflibFindObjectTypeByName(pDataBlock, item->registry_name);
1000 + if (!pObjectType)
1001 + return false;
1002 +
1003 + PERF_INSTANCE_DEFINITION *pi = NULL;
1004 + for (LONG i = 0; i < pObjectType->NumInstances; i++) {
1005 + static bool charts_created = false;
1006 + pi = perflibForEachInstance(pDataBlock, pObjectType, pi);
1007 + if (!pi)
1008 + break;
1009 +
1010 + get_and_sanitize_instance_value(
1011 + pDataBlock, pObjectType, pi, windows_shared_buffer, sizeof(windows_shared_buffer));
1012 +
1013 + if(strcasecmp(windows_shared_buffer, "_Total") == 0)
1014 + continue;
1015 +
1016 + struct hypervisor_switch *p = dictionary_set(item->instance, windows_shared_buffer, NULL, sizeof(*p));
1017 +
1018 + if (!p->collected_metadata) {
1019 + p->collected_metadata = true;
1020 + }
1021 +
1022 + GET_INSTANCE_COUNTER(BytesReceivedSec);
1023 + GET_INSTANCE_COUNTER(BytesSentSec);
1024 +
1025 + GET_INSTANCE_COUNTER(PacketsReceivedSec);
1026 + GET_INSTANCE_COUNTER(PacketsSentSec);
1027 +
1028 + GET_INSTANCE_COUNTER(DirectedPacketsSentSec);
1029 + GET_INSTANCE_COUNTER(DirectedPacketsReceivedSec);
1030 +
1031 + GET_INSTANCE_COUNTER(BroadcastPacketsSentSec);
1032 + GET_INSTANCE_COUNTER(BroadcastPacketsReceivedSec);
1033 +
1034 + GET_INSTANCE_COUNTER(MulticastPacketsSentSec);
1035 + GET_INSTANCE_COUNTER(MulticastPacketsReceivedSec);
1036 +
1037 + GET_INSTANCE_COUNTER(DroppedPacketsOutgoingSec);
1038 + GET_INSTANCE_COUNTER(DroppedPacketsIncomingSec);
1039 +
1040 + GET_INSTANCE_COUNTER(ExtensionsDroppedPacketsOutgoingSec);
1041 + GET_INSTANCE_COUNTER(ExtensionsDroppedPacketsIncomingSec);
1042 +
1043 + GET_INSTANCE_COUNTER(PacketsFlooded);
1044 +
1045 + GET_INSTANCE_COUNTER(LearnedMacAddresses);
1046 +
1047 + GET_INSTANCE_COUNTER(PurgedMacAddresses);
1048 +
1049 + if (!p->charts_created) {
1050 + p->charts_created = true;
1051 +
1052 + p->st_bytes = rrdset_create_localhost(
1053 + "vswitch_bytes",
1054 + windows_shared_buffer,
1055 + NULL,
1056 + HYPERV,
1057 + HYPERV ".vswitch_bytes",
1058 + "Virtual switch traffic",
1059 + "bytes/sec",
1060 + _COMMON_PLUGIN_NAME,
1061 + _COMMON_PLUGIN_MODULE_NAME,
1062 + chart_priority++,
1063 + update_every,
1064 + RRDSET_TYPE_LINE);
1065 +
1066 + p->rd_BytesReceivedSec = rrddim_add(p->st_bytes, "received", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
1067 + p->rd_BytesSentSec = rrddim_add(p->st_bytes, "sent", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
1068 + rrdlabels_add(p->st_bytes->rrdlabels, "vswitch", windows_shared_buffer, RRDLABEL_SRC_AUTO);
1069 +
1070 + p->st_packets = rrdset_create_localhost(
1071 + "vswitch_packets",
1072 + windows_shared_buffer,
1073 + NULL,
1074 + HYPERV,
1075 + HYPERV ".vswitch_packets",
1076 + "Virtual switch packets",
1077 + "packets/sec",
1078 + _COMMON_PLUGIN_NAME,
1079 + _COMMON_PLUGIN_MODULE_NAME,
1080 + chart_priority++,
1081 + update_every,
1082 + RRDSET_TYPE_LINE);
1083 +
1084 + p->rd_PacketsReceivedSec = rrddim_add(p->st_packets, "received", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
1085 + p->rd_PacketsSentSec = rrddim_add(p->st_packets, "sent", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
1086 + rrdlabels_add(p->st_packets->rrdlabels, "vswitch", windows_shared_buffer, RRDLABEL_SRC_AUTO);
1087 +
1088 + p->st_directed_packets = rrdset_create_localhost(
1089 + "vswitch_directed_packets",
1090 + windows_shared_buffer,
1091 + NULL,
1092 + HYPERV,
1093 + HYPERV ".vswitch_directed_packets",
1094 + "Virtual switch directed packets",
1095 + "packets/sec",
1096 + _COMMON_PLUGIN_NAME,
1097 + _COMMON_PLUGIN_MODULE_NAME,
1098 + chart_priority++,
1099 + update_every,
1100 + RRDSET_TYPE_LINE);
1101 +
1102 + p->rd_DirectedPacketsReceivedSec =
1103 + rrddim_add(p->st_directed_packets, "received", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
1104 + p->rd_DirectedPacketsSentSec =
1105 + rrddim_add(p->st_directed_packets, "sent", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
1106 + rrdlabels_add(p->st_directed_packets->rrdlabels, "vswitch", windows_shared_buffer, RRDLABEL_SRC_AUTO);
1107 +
1108 + p->st_broadcast_packets = rrdset_create_localhost(
1109 + "vswitch_broadcast_packets",
1110 + windows_shared_buffer,
1111 + NULL,
1112 + HYPERV,
1113 + HYPERV ".vswitch_broadcast_packets",
1114 + "Virtual switch broadcast packets",
1115 + "packets/sec",
1116 + _COMMON_PLUGIN_NAME,
1117 + _COMMON_PLUGIN_MODULE_NAME,
1118 + chart_priority++,
1119 + update_every,
1120 + RRDSET_TYPE_LINE);
1121 +
1122 + p->rd_BroadcastPacketsReceivedSec =
1123 + rrddim_add(p->st_broadcast_packets, "received", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
1124 + p->rd_BroadcastPacketsSentSec =
1125 + rrddim_add(p->st_broadcast_packets, "sent", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
1126 + rrdlabels_add(p->st_broadcast_packets->rrdlabels, "vswitch", windows_shared_buffer, RRDLABEL_SRC_AUTO);
1127 +
1128 + p->st_multicast_packets = rrdset_create_localhost(
1129 + "vswitch_multicast_packets",
1130 + windows_shared_buffer,
1131 + NULL,
1132 + HYPERV,
1133 + HYPERV ".vswitch_multicast_packets",
1134 + "Virtual switch multicast packets",
1135 + "packets/sec",
1136 + _COMMON_PLUGIN_NAME,
1137 + _COMMON_PLUGIN_MODULE_NAME,
1138 + chart_priority++,
1139 + update_every,
1140 + RRDSET_TYPE_LINE);
1141 +
1142 + p->rd_MulticastPacketsReceivedSec =
1143 + rrddim_add(p->st_multicast_packets, "received", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
1144 + p->rd_MulticastPacketsSentSec =
1145 + rrddim_add(p->st_multicast_packets, "sent", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
1146 + rrdlabels_add(p->st_multicast_packets->rrdlabels, "vswitch", windows_shared_buffer, RRDLABEL_SRC_AUTO);
1147 +
1148 + p->st_dropped_packets = rrdset_create_localhost(
1149 + "vswitch_dropped_packets",
1150 + windows_shared_buffer,
1151 + NULL,
1152 + HYPERV,
1153 + HYPERV ".vswitch_dropped_packets",
1154 + "Virtual switch dropped packets",
1155 + "drops/sec",
1156 + _COMMON_PLUGIN_NAME,
1157 + _COMMON_PLUGIN_MODULE_NAME,
1158 + chart_priority++,
1159 + update_every,
1160 + RRDSET_TYPE_LINE);
1161 +
1162 + p->rd_DroppedPacketsIncomingSec =
1163 + rrddim_add(p->st_dropped_packets, "incoming", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
1164 + p->rd_DroppedPacketsOutgoingSec =
1165 + rrddim_add(p->st_dropped_packets, "outgoing", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
1166 + rrdlabels_add(p->st_dropped_packets->rrdlabels, "vswitch", windows_shared_buffer, RRDLABEL_SRC_AUTO);
1167 +
1168 + p->st_ext_dropped_packets = rrdset_create_localhost(
1169 + "vswitch_extensions_dropped_packets",
1170 + windows_shared_buffer,
1171 + NULL,
1172 + HYPERV,
1173 + HYPERV ".vswitch_extensions_dropped_packets",
1174 + "Virtual switch extensions dropped packets",
1175 + "drops/sec",
1176 + _COMMON_PLUGIN_NAME,
1177 + _COMMON_PLUGIN_MODULE_NAME,
1178 + chart_priority++,
1179 + update_every,
1180 + RRDSET_TYPE_LINE);
1181 +
1182 + p->rd_ExtensionsDroppedPacketsIncomingSec =
1183 + rrddim_add(p->st_ext_dropped_packets, "incoming", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
1184 + p->rd_ExtensionsDroppedPacketsOutgoingSec =
1185 + rrddim_add(p->st_ext_dropped_packets, "outgoing", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
1186 + rrdlabels_add(p->st_ext_dropped_packets->rrdlabels, "vswitch", windows_shared_buffer, RRDLABEL_SRC_AUTO);
1187 +
1188 + p->st_flooded = rrdset_create_localhost(
1189 + "vswitch_packets_flooded",
1190 + windows_shared_buffer,
1191 + NULL,
1192 + HYPERV,
1193 + HYPERV ".vswitch_packets_flooded",
1194 + "Virtual switch flooded packets",
1195 + "packets/sec",
1196 + _COMMON_PLUGIN_NAME,
1197 + _COMMON_PLUGIN_MODULE_NAME,
1198 + chart_priority++,
1199 + update_every,
1200 + RRDSET_TYPE_LINE);
1201 +
1202 + p->rd_PacketsFlooded = rrddim_add(p->st_flooded, "flooded", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
1203 + rrdlabels_add(p->st_flooded->rrdlabels, "vswitch", windows_shared_buffer, RRDLABEL_SRC_AUTO);
1204 +
1205 + p->st_learned_mac = rrdset_create_localhost(
1206 + "vswitch_learned_mac_addresses",
1207 + windows_shared_buffer,
1208 + NULL,
1209 + HYPERV,
1210 + HYPERV ".vswitch_learned_mac_addresses",
1211 + "Virtual switch learned MAC addresses",
1212 + "mac addresses/sec",
1213 + _COMMON_PLUGIN_NAME,
1214 + _COMMON_PLUGIN_MODULE_NAME,
1215 + chart_priority++,
1216 + update_every,
1217 + RRDSET_TYPE_LINE);
1218 +
1219 + p->rd_LearnedMacAddresses = rrddim_add(p->st_learned_mac, "learned", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
1220 + rrdlabels_add(p->st_learned_mac->rrdlabels, "vswitch", windows_shared_buffer, RRDLABEL_SRC_AUTO);
1221 +
1222 + p->st_purged_mac = rrdset_create_localhost(
1223 + "vswitch_purged_mac_addresses",
1224 + windows_shared_buffer,
1225 + NULL,
1226 + HYPERV,
1227 + HYPERV ".vswitch_purged_mac_addresses",
1228 + "Virtual switch purged MAC addresses",
1229 + "mac addresses/sec",
1230 + _COMMON_PLUGIN_NAME,
1231 + _COMMON_PLUGIN_MODULE_NAME,
1232 + chart_priority++,
1233 + update_every,
1234 + RRDSET_TYPE_LINE);
1235 +
1236 + p->rd_PurgedMacAddresses = rrddim_add(p->st_purged_mac, "purged", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
1237 + rrdlabels_add(p->st_purged_mac->rrdlabels, "vswitch", windows_shared_buffer, RRDLABEL_SRC_AUTO);
1238 + }
1239 +
1240 + SETP_DIM_VALUE(st_packets, PacketsReceivedSec);
1241 + SETP_DIM_VALUE(st_packets, PacketsSentSec);
1242 +
1243 + SETP_DIM_VALUE(st_bytes, BytesReceivedSec);
1244 + SETP_DIM_VALUE(st_bytes, BytesSentSec);
1245 +
1246 + SETP_DIM_VALUE(st_directed_packets, DirectedPacketsSentSec);
1247 + SETP_DIM_VALUE(st_directed_packets, DirectedPacketsReceivedSec);
1248 +
1249 + SETP_DIM_VALUE(st_broadcast_packets, BroadcastPacketsSentSec);
1250 + SETP_DIM_VALUE(st_broadcast_packets, BroadcastPacketsReceivedSec);
1251 +
1252 + SETP_DIM_VALUE(st_multicast_packets, MulticastPacketsSentSec);
1253 + SETP_DIM_VALUE(st_multicast_packets, MulticastPacketsReceivedSec);
1254 +
1255 + SETP_DIM_VALUE(st_dropped_packets, DroppedPacketsOutgoingSec);
1256 + SETP_DIM_VALUE(st_dropped_packets, DroppedPacketsIncomingSec);
1257 +
1258 + SETP_DIM_VALUE(st_ext_dropped_packets, ExtensionsDroppedPacketsOutgoingSec);
1259 + SETP_DIM_VALUE(st_ext_dropped_packets, ExtensionsDroppedPacketsIncomingSec);
1260 +
1261 + SETP_DIM_VALUE(st_flooded, PacketsFlooded);
1262 + SETP_DIM_VALUE(st_learned_mac, LearnedMacAddresses);
1263 + SETP_DIM_VALUE(st_purged_mac, PurgedMacAddresses);
1264 +
1265 + // Mark the charts as done
1266 + rrdset_done(p->st_packets);
1267 + rrdset_done(p->st_bytes);
1268 +
1269 + rrdset_done(p->st_directed_packets);
1270 + rrdset_done(p->st_broadcast_packets);
1271 + rrdset_done(p->st_multicast_packets);
1272 + rrdset_done(p->st_dropped_packets);
1273 + rrdset_done(p->st_ext_dropped_packets);
1274 + rrdset_done(p->st_flooded);
1275 + rrdset_done(p->st_learned_mac);
1276 + rrdset_done(p->st_purged_mac);
1277 +
1278 + }
1279 + return true;
1280 +}
1281 +
1282 +
1283 +struct hypervisor_network_adapter {
1284 + bool collected_metadata;
1285 + bool charts_created;
1286 +
1287 + RRDSET *st_packets;
1288 + DEFINE_RD(DroppedPacketsOutgoingSec);
1289 + DEFINE_RD(DroppedPacketsIncomingSec);
1290 +
1291 + COUNTER_DATA DroppedPacketsOutgoingSec;
1292 + COUNTER_DATA DroppedPacketsIncomingSec;
1293 +};
1294 +
1295 +// Initialize the keys for the root partition metrics
1296 +void initialize_hyperv_network_adapter_keys(struct hypervisor_network_adapter *p)
1297 +{
1298 + p->DroppedPacketsOutgoingSec.key = "Dropped Packets Outgoing/sec";
1299 + p->DroppedPacketsIncomingSec.key = "Dropped Packets Incoming/sec";
1300 +}
1301 +
1302 +void dict_hyperv_network_adapter_insert_cb(const DICTIONARY_ITEM *item __maybe_unused, void *value, void *data __maybe_unused)
1303 +{
1304 + struct hypervisor_network_adapter *p = value;
1305 + initialize_hyperv_network_adapter_keys(p);
1306 +}
1307 +
1308 +static bool do_hyperv_network_adapter(PERF_DATA_BLOCK *pDataBlock, int update_every, void *data)
1309 +{
1310 + hyperv_perf_item *item = data;
1311 +
1312 + PERF_OBJECT_TYPE *pObjectType = perflibFindObjectTypeByName(pDataBlock, item->registry_name);
1313 + if (!pObjectType)
1314 + return false;
1315 +
1316 + PERF_INSTANCE_DEFINITION *pi = NULL;
1317 + for (LONG i = 0; i < pObjectType->NumInstances; i++) {
1318 + pi = perflibForEachInstance(pDataBlock, pObjectType, pi);
1319 + if (!pi)
1320 + break;
1321 +
1322 + get_and_sanitize_instance_value(pDataBlock, pObjectType, pi, windows_shared_buffer, sizeof(windows_shared_buffer));
1323 +
1324 + if(strcasecmp(windows_shared_buffer, "_Total") == 0)
1325 + continue;
1326 +
1327 + struct hypervisor_network_adapter *p = dictionary_set(item->instance, windows_shared_buffer, NULL, sizeof(*p));
1328 +
1329 + if (!p->collected_metadata) {
1330 + p->collected_metadata = true;
1331 + }
1332 +
1333 + GET_INSTANCE_COUNTER(DroppedPacketsIncomingSec);
1334 + GET_INSTANCE_COUNTER(DroppedPacketsOutgoingSec);
1335 +
1336 + if (!p->charts_created) {
1337 + p->charts_created = true;
1338 + p->st_packets = rrdset_create_localhost(
1339 + "vm_net_interface_packets_dropped",
1340 + windows_shared_buffer,
1341 + NULL,
1342 + HYPERV,
1343 + HYPERV".vm_net_interface_packets_dropped",
1344 + "VM interface packets dropped",
1345 + "drops/sec",
1346 + _COMMON_PLUGIN_NAME,
1347 + _COMMON_PLUGIN_MODULE_NAME,
1348 + chart_priority++,
1349 + update_every,
1350 + RRDSET_TYPE_LINE);
1351 +
1352 + p->rd_DroppedPacketsIncomingSec = rrddim_add(p->st_packets, "incoming", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
1353 + p->rd_DroppedPacketsOutgoingSec = rrddim_add(p->st_packets, "outgoing", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
1354 +
1355 + rrdlabels_add(p->st_packets->rrdlabels, "vm_net_interface", windows_shared_buffer, RRDLABEL_SRC_AUTO);
1356 + }
1357 +
1358 + SETP_DIM_VALUE(st_packets, DroppedPacketsIncomingSec);
1359 + SETP_DIM_VALUE(st_packets, DroppedPacketsOutgoingSec);
1360 +
1361 + rrdset_done(p->st_packets);
1362 + }
1363 + return true;
1364 +}
1365 +
1366 +
1367 +// Hypervisor Virtual Processor
1368 +struct hypervisor_processor {
1369 + bool collected_metadata;
1370 + bool charts_created;
1371 +
1372 + RRDSET *st_HypervisorProcessor;
1373 +
1374 + DEFINE_RD(GuestRunTime);
1375 + DEFINE_RD(HypervisorRunTime);
1376 + DEFINE_RD(RemoteRunTime);
1377 +
1378 + COUNTER_DATA GuestRunTime;
1379 + COUNTER_DATA HypervisorRunTime;
1380 + COUNTER_DATA RemoteRunTime;
1381 +};
1382 +
1383 +
1384 +void initialize_hyperv_processor_keys(struct hypervisor_processor *p)
1385 +{
1386 + p->GuestRunTime.key = "% Guest Run Time";
1387 + p->HypervisorRunTime.key = "% Hypervisor Run Time";
1388 + p->RemoteRunTime.key = "% Remote Run Time";
1389 +}
1390 +
1391 +void dict_hyperv_processor_insert_cb(const DICTIONARY_ITEM *item __maybe_unused, void *value, void *data __maybe_unused)
1392 +{
1393 + struct hypervisor_processor *p = value;
1394 + initialize_hyperv_processor_keys(p);
1395 +}
1396 +
1397 +static bool do_hyperv_processor(PERF_DATA_BLOCK *pDataBlock, int update_every, void *data)
1398 +{
1399 + hyperv_perf_item *item = data;
1400 +
1401 + PERF_OBJECT_TYPE *pObjectType = perflibFindObjectTypeByName(pDataBlock, item->registry_name);
1402 + if (!pObjectType)
1403 + return false;
1404 +
1405 + PERF_INSTANCE_DEFINITION *pi = NULL;
1406 + for (LONG i = 0; i < pObjectType->NumInstances; i++) {
1407 + pi = perflibForEachInstance(pDataBlock, pObjectType, pi);
1408 + if (!pi)
1409 + break;
1410 +
1411 + get_and_sanitize_instance_value(pDataBlock, pObjectType, pi, windows_shared_buffer, sizeof(windows_shared_buffer));
1412 +
1413 + if(strcasecmp(windows_shared_buffer, "_Total") == 0)
1414 + continue;
1415 +
1416 + struct hypervisor_processor *p = dictionary_set(item->instance, windows_shared_buffer, NULL, sizeof(*p));
1417 +
1418 + if (!p->collected_metadata) {
1419 + p->collected_metadata = true;
1420 + }
1421 +
1422 + GET_INSTANCE_COUNTER(GuestRunTime);
1423 + GET_INSTANCE_COUNTER(HypervisorRunTime);
1424 + GET_INSTANCE_COUNTER(RemoteRunTime);
1425 +
1426 + if (!p->charts_created) {
1427 + p->charts_created = true;
1428 + p->st_HypervisorProcessor = rrdset_create_localhost(
1429 + "vm_cpu_usage",
1430 + windows_shared_buffer,
1431 + NULL,
1432 + HYPERV,
1433 + HYPERV ".vm_cpu_usage",
1434 + "VM CPU usage (100% = 1 core)",
1435 + "percentage",
1436 + _COMMON_PLUGIN_NAME,
1437 + _COMMON_PLUGIN_MODULE_NAME,
1438 + chart_priority++,
1439 + update_every,
1440 + RRDSET_TYPE_STACKED);
1441 +
1442 + p->rd_GuestRunTime =
1443 + rrddim_add(p->st_HypervisorProcessor, "guest", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
1444 + p->rd_HypervisorRunTime =
1445 + rrddim_add(p->st_HypervisorProcessor, "hypervisor", NULL, -1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
1446 + p->rd_RemoteRunTime =
1447 + rrddim_add(p->st_HypervisorProcessor, "remote", NULL, -1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
1448 +
1449 + rrdlabels_add(p->st_HypervisorProcessor->rrdlabels, "vm_name", windows_shared_buffer, RRDLABEL_SRC_AUTO);
1450 + }
1451 +
1452 + SETP_DIM_VALUE(st_HypervisorProcessor, GuestRunTime);
1453 + SETP_DIM_VALUE(st_HypervisorProcessor, HypervisorRunTime);
1454 + SETP_DIM_VALUE(st_HypervisorProcessor, RemoteRunTime);
1455 +
1456 + rrdset_done(p->st_HypervisorProcessor);
1457 + }
1458 + return true;
1459 +}
1460 +
1461 +hyperv_perf_item hyperv_perf_list[] = {
1462 + {.registry_name = "Hyper-V Dynamic Memory VM",
1463 + .function_collect = do_hyperv_memory,
1464 + .dict_insert_cb = dict_hyperv_memory_insert_cb,
1465 + .dict_size = sizeof(struct hypervisor_memory)},
1466 +
1467 + {.registry_name = "Hyper-V VM Vid Partition",
1468 + .function_collect = do_hyperv_vid_partition,
1469 + .dict_insert_cb = dict_hyperv_partition_insert_cb,
1470 + .dict_size = sizeof(struct hypervisor_partition)},
1471 +
1472 + {
1473 + .registry_name = "Hyper-V Virtual Machine Health Summary",
1474 + .function_collect = do_hyperv_health_summary,
1475 + },
1476 +
1477 + {
1478 + .registry_name = "Hyper-V Hypervisor Root Partition",
1479 + .function_collect = do_hyperv_root_partition,
1480 + .dict_insert_cb = dict_hyperv_root_partition_insert_cb,
1481 + .dict_size = sizeof(struct hypervisor_root_partition),
1482 + },
1483 +
1484 + {.registry_name = "Hyper-V Virtual Storage Device",
1485 + .function_collect = do_hyperv_storage_device,
1486 + .dict_insert_cb = dict_hyperv_storage_device_insert_cb,
1487 + .dict_size = sizeof(struct hypervisor_storage_device)},
1488 +
1489 + {.registry_name = "Hyper-V Virtual Switch",
1490 + .function_collect = do_hyperv_switch,
1491 + .dict_insert_cb = dict_hyperv_switch_insert_cb,
1492 + .dict_size = sizeof(struct hypervisor_switch)},
1493 +
1494 + {.registry_name = "Hyper-V Virtual Network Adapter",
1495 + .function_collect = do_hyperv_network_adapter,
1496 + .dict_insert_cb = dict_hyperv_network_adapter_insert_cb,
1497 + .dict_size = sizeof(struct hypervisor_network_adapter)},
1498 +
1499 + {.registry_name = "Hyper-V Hypervisor Virtual Processor",
1500 + .function_collect = do_hyperv_processor,
1501 + .dict_insert_cb = dict_hyperv_processor_insert_cb,
1502 + .dict_size = sizeof(struct hypervisor_processor)},
1503 +
1504 + {.registry_name = NULL, .function_collect = NULL}};
1505 +
1506 +int do_PerflibHyperV(int update_every, usec_t dt __maybe_unused) {
1507 + static bool initialized = false;
1508 +
1509 + if (unlikely(!initialized)) {
1510 + for (int i = 0; hyperv_perf_list[i].registry_name != NULL; i++) {
1511 + hyperv_perf_item *item = &hyperv_perf_list[i];
1512 + if (item->dict_insert_cb) {
1513 + item->instance = dictionary_create_advanced(DICT_PERF_OPTION, NULL, item->dict_size);
1514 + dictionary_register_insert_callback(item->instance, item->dict_insert_cb, NULL);
1515 + }
1516 + }
1517 + initialized = true;
1518 + }
1519 +
1520 + for (int i = 0; hyperv_perf_list[i].registry_name != NULL; i++) {
1521 + // Find the registry ID using the registry name
1522 + DWORD id = RegistryFindIDByName(hyperv_perf_list[i].registry_name);
1523 + if (id == PERFLIB_REGISTRY_NAME_NOT_FOUND)
1524 + continue;
1525 +
1526 + // Get the performance data using the registry ID
1527 + PERF_DATA_BLOCK *pDataBlock = perflibGetPerformanceData(id);
1528 + if (!pDataBlock)
1529 + continue;
1530 +
1531 + hyperv_perf_list[i].function_collect(pDataBlock, update_every, &hyperv_perf_list[i]);
1532 + }
1533 + return 0;
1534 +}
src/collectors/windows.plugin/windows_plugin.c
+1
@@ -25,6 +25,7 @@ static struct proc_module {
25 {.name = "PerflibStorage", .dim = "PerflibStorage", .enabled = CONFIG_BOOLEAN_YES, .func = do_PerflibStorage},
26 {.name = "PerflibNetwork", .dim = "PerflibNetwork", .enabled = CONFIG_BOOLEAN_YES, .func = do_PerflibNetwork},
27 {.name = "PerflibObjects", .dim = "PerflibObjects", .enabled = CONFIG_BOOLEAN_YES, .func = do_PerflibObjects},
28 + {.name = "PerflibHyperV", .dim = "PerflibHyperV", .enabled = CONFIG_BOOLEAN_YES, .func = do_PerflibHyperV},
29
30 {.name = "PerflibThermalZone", .dim = "PerflibThermalZone", .enabled = CONFIG_BOOLEAN_NO, .func = do_PerflibThermalZone},
31
src/collectors/windows.plugin/windows_plugin.h
+2 -1
@@ -99,5 +99,6 @@ enum PERFLIB_PRIO {
99 PRIO_NETFRAMEWORK_CLR_LOADING_CLASS_LOAD_FAILURE
100 };
101
102 -#endif //NETDATA_WINDOWS_PLUGIN_H
102 +int do_PerflibHyperV(int update_every, usec_t dt);
103
104 +#endif //NETDATA_WINDOWS_PLUGIN_H
src/database/rrdlabels.h
+1
@@ -75,6 +75,7 @@ pattern_array_add_key_simple_pattern(struct pattern_array *pa, const char *key,
75 void pattern_array_free(struct pattern_array *pa);
76
77 int rrdlabels_unittest(void);
78 +size_t rrdlabels_sanitize_name(char *dst, const char *src, size_t dst_size);
79
80 // unfortunately this break when defined in exporting_engine.h
81 bool exporting_labels_filter_callback(const char *name, const char *value, RRDLABEL_SRC ls, void *data);