Windows Plugin Metrics (Thermal and Memory) (#18494)
thiagoftsm committed
Sep 12, 2024 at 17:44 UTC
d78db40901a258e27e91338aa57e668b7b79267b
6 files changed
+277
-11
CMakeLists.txt
+1
@@ -1426,6 +1426,7 @@ set(WINDOWS_PLUGIN_FILES
1426
src/collectors/windows.plugin/perflib-dump.c
1427
src/collectors/windows.plugin/perflib-storage.c
1428
src/collectors/windows.plugin/perflib-processor.c
1429
+ src/collectors/windows.plugin/perflib-thermalzone.c
1430
src/collectors/windows.plugin/perflib-objects.c
1431
src/collectors/windows.plugin/perflib-network.c
1432
src/collectors/windows.plugin/perflib-memory.c
src/collectors/all.h
+3
@@ -55,6 +55,7 @@
55
#define NETDATA_CHART_PRIO_SYSTEM_IPC_SHARED_MEM_CALLS 1207
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
60
61
// CPU per core
@@ -76,7 +77,9 @@
77
#define NETDATA_CHART_PRIO_MEM_SYSTEM_COMMITTED 1030
78
#define NETDATA_CHART_PRIO_MEM_SWAP 1035
79
#define NETDATA_CHART_PRIO_MEM_SWAP_CALLS 1037
80
+#define NETDATA_CHART_PRIO_MEM_SWAP_PAGES 1037 // Windows only
81
#define NETDATA_CHART_PRIO_MEM_SWAPIO 1038
82
+#define NETDATA_CHART_PRIO_MEM_SYSTEM_POOL 1039 // Windows only
83
#define NETDATA_CHART_PRIO_MEM_ZSWAP 1036
84
#define NETDATA_CHART_PRIO_MEM_ZSWAPIO 1037
85
#define NETDATA_CHART_PRIO_MEM_ZSWAP_COMPRESS_RATIO 1038
src/collectors/windows.plugin/perflib-memory.c
+155
-1
@@ -7,8 +7,158 @@
7
#define _COMMON_PLUGIN_MODULE_NAME "PerflibMemory"
8
#include "../common-contexts/common-contexts.h"
9
10
+struct swap {
11
+ RRDSET *operations;
12
+ RRDDIM *rd_op_read;
13
+ RRDDIM *rd_op_write;
14
+
15
+ RRDSET *pages;
16
+ RRDDIM *rd_page_read;
17
+ RRDDIM *rd_page_write;
18
+
19
+ COUNTER_DATA pageReadsTotal;
20
+ COUNTER_DATA pageWritesTotal;
21
+ COUNTER_DATA pageInputTotal;
22
+ COUNTER_DATA pageOutputTotal;
23
+};
24
+
25
+struct system_pool {
26
+ RRDSET *pool;
27
+ RRDDIM *rd_paged;
28
+ RRDDIM *rd_nonpaged;
29
+
30
+ COUNTER_DATA pagedData;
31
+ COUNTER_DATA nonPagedData;
32
+};
33
+
34
+struct swap localSwap = { 0 };
35
+struct system_pool localPool = { 0 };
36
+
37
+void initialize_swap_keys(struct swap *p) {
38
+ // SWAP Operations
39
+ p->pageReadsTotal.key = "Page Reads/sec";
40
+ p->pageWritesTotal.key = "Page Writes/s";
41
+
42
+ // Swap Pages
43
+ p->pageInputTotal.key = "Pages Input/sec";
44
+ p->pageOutputTotal.key = "Pages Output/s";
45
+}
46
+
47
+void initialize_pool_keys(struct system_pool *p) {
48
+ p->pagedData.key = "Pool Paged Bytes";
49
+ p->nonPagedData.key = "Pool Nonpaged Bytes";
50
+}
51
+
52
static void initialize(void) {
11
- ;
53
+ initialize_swap_keys(&localSwap);
54
+ initialize_pool_keys(&localPool);
55
+}
56
+
57
+static void do_memory_swap(PERF_DATA_BLOCK *pDataBlock, PERF_OBJECT_TYPE *pObjectType, int update_every)
58
+{
59
+ perflibGetObjectCounter(pDataBlock, pObjectType, &localSwap.pageReadsTotal);
60
+ perflibGetObjectCounter(pDataBlock, pObjectType, &localSwap.pageWritesTotal);
61
+ perflibGetObjectCounter(pDataBlock, pObjectType, &localSwap.pageInputTotal);
62
+ perflibGetObjectCounter(pDataBlock, pObjectType, &localSwap.pageOutputTotal);
63
+
64
+ if (!localSwap.operations) {
65
+ localSwap.operations = rrdset_create_localhost(
66
+ "mem"
67
+ , "swap_operations", NULL
68
+ , "swap"
69
+ , "mem.swap_iops"
70
+
71
+ , "Swap Operations"
72
+ , "operations/s"
73
+ , PLUGIN_WINDOWS_NAME
74
+ , "PerflibMemory"
75
+ , NETDATA_CHART_PRIO_MEM_SWAPIO
76
+ , update_every
77
+ , RRDSET_TYPE_STACKED
78
+ );
79
+
80
+ localSwap.rd_op_read = rrddim_add(localSwap.operations, "read", NULL,
81
+ 1, 1, RRD_ALGORITHM_INCREMENTAL);
82
+ localSwap.rd_op_write = rrddim_add(localSwap.operations, "write", NULL,
83
+ 1, -1, RRD_ALGORITHM_INCREMENTAL);
84
+ }
85
+
86
+ rrddim_set_by_pointer(localSwap.operations,
87
+ localSwap.rd_op_read,
88
+ (collected_number)localSwap.pageReadsTotal.current.Data);
89
+
90
+ rrddim_set_by_pointer(localSwap.operations,
91
+ localSwap.rd_op_write,
92
+ (collected_number)localSwap.pageWritesTotal.current.Data);
93
+ rrdset_done(localSwap.operations);
94
+
95
+ if (!localSwap.pages) {
96
+ localSwap.pages = rrdset_create_localhost(
97
+ "mem"
98
+ , "swap_pages", NULL
99
+ , "swap"
100
+ , "mem.swap_pages_io"
101
+
102
+ , "Swap Pages"
103
+ , "pages/s"
104
+ , PLUGIN_WINDOWS_NAME
105
+ , "PerflibMemory"
106
+ , NETDATA_CHART_PRIO_MEM_SWAP_PAGES
107
+ , update_every
108
+ , RRDSET_TYPE_STACKED
109
+ );
110
+
111
+ localSwap.rd_page_read = rrddim_add(localSwap.pages, "read", NULL,
112
+ 1, 1, RRD_ALGORITHM_INCREMENTAL);
113
+ localSwap.rd_page_write = rrddim_add(localSwap.pages, "write", NULL,
114
+ 1, -1, RRD_ALGORITHM_INCREMENTAL);
115
+ }
116
+
117
+ rrddim_set_by_pointer(localSwap.pages,
118
+ localSwap.rd_page_read,
119
+ (collected_number)localSwap.pageInputTotal.current.Data);
120
+
121
+ rrddim_set_by_pointer(localSwap.pages,
122
+ localSwap.rd_page_write,
123
+ (collected_number)localSwap.pageOutputTotal.current.Data);
124
+ rrdset_done(localSwap.pages);
125
+}
126
+
127
+static void do_memory_system_pool(PERF_DATA_BLOCK *pDataBlock, PERF_OBJECT_TYPE *pObjectType, int update_every)
128
+{
129
+ perflibGetObjectCounter(pDataBlock, pObjectType, &localPool.nonPagedData);
130
+ perflibGetObjectCounter(pDataBlock, pObjectType, &localPool.pagedData);
131
+
132
+ if (!localPool.pool) {
133
+ localPool.pool = rrdset_create_localhost(
134
+ "mem"
135
+ , "system_pool", NULL
136
+ , "mem"
137
+ , "mem.system_pool_size"
138
+
139
+ , "System Memory Pool"
140
+ , "bytes"
141
+ , PLUGIN_WINDOWS_NAME
142
+ , "PerflibMemory"
143
+ , NETDATA_CHART_PRIO_MEM_SYSTEM_POOL
144
+ , update_every
145
+ , RRDSET_TYPE_STACKED
146
+ );
147
+
148
+ localPool.rd_paged = rrddim_add(localPool.pool, "paged", NULL,
149
+ 1, 1, RRD_ALGORITHM_ABSOLUTE);
150
+ localPool.rd_nonpaged = rrddim_add(localPool.pool, "pool-paged", NULL,
151
+ 1, 1, RRD_ALGORITHM_ABSOLUTE);
152
+ }
153
+
154
+ rrddim_set_by_pointer(localPool.pool,
155
+ localPool.rd_paged,
156
+ (collected_number)localPool.pagedData.current.Data);
157
+
158
+ rrddim_set_by_pointer(localPool.pool,
159
+ localPool.rd_nonpaged,
160
+ (collected_number)localPool.nonPagedData.current.Data);
161
+ rrdset_done(localPool.pool);
162
}
163
164
static bool do_memory(PERF_DATA_BLOCK *pDataBlock, int update_every) {
@@ -41,6 +191,10 @@ static bool do_memory(PERF_DATA_BLOCK *pDataBlock, int update_every) {
191
192
common_mem_available(available_bytes, update_every);
193
194
+ do_memory_swap(pDataBlock, pObjectType, update_every);
195
+
196
+ do_memory_system_pool(pDataBlock, pObjectType, update_every);
197
+
198
return true;
199
}
200
src/collectors/windows.plugin/perflib-thermalzone.c
new
+105
@@ -0,0 +1,105 @@
1
+// SPDX-License-Identifier: GPL-3.0-or-later
2
+
3
+#include "windows_plugin.h"
4
+#include "windows-internals.h"
5
+
6
+typedef struct thermal_zone {
7
+ RRDSET *st;
8
+ RRDDIM *rd;
9
+
10
+ COUNTER_DATA thermalZoneTemperature;
11
+};
12
+
13
+static inline void initialize_thermal_zone_keys(struct thermal_zone *p) {
14
+ p->thermalZoneTemperature.key = "Temperature";
15
+}
16
+
17
+void dict_thermal_zone_insert_cb(const DICTIONARY_ITEM *item __maybe_unused, void *value, void *data __maybe_unused) {
18
+ struct thermal_zone *p = value;
19
+ initialize_thermal_zone_keys(p);
20
+}
21
+
22
+static DICTIONARY *thermal_zones = NULL;
23
+
24
+static void initialize(void) {
25
+ thermal_zones = dictionary_create_advanced(DICT_OPTION_DONT_OVERWRITE_VALUE |
26
+ DICT_OPTION_FIXED_SIZE, NULL, sizeof(struct thermal_zone));
27
+
28
+ dictionary_register_insert_callback(thermal_zones, dict_thermal_zone_insert_cb, NULL);
29
+}
30
+
31
+static bool do_thermal_zones(PERF_DATA_BLOCK *pDataBlock, int update_every) {
32
+ PERF_OBJECT_TYPE *pObjectType = perflibFindObjectTypeByName(pDataBlock, "Thermal Zone Information");
33
+ if(!pObjectType) return false;
34
+
35
+ PERF_INSTANCE_DEFINITION *pi = NULL;
36
+ for(LONG i = 0; i < pObjectType->NumInstances ; i++) {
37
+ pi = perflibForEachInstance(pDataBlock, pObjectType, pi);
38
+ if(!pi) break;
39
+
40
+ if(!getInstanceName(pDataBlock, pObjectType, pi, windows_shared_buffer, sizeof(windows_shared_buffer)))
41
+ strncpyz(windows_shared_buffer, "[unknown]", sizeof(windows_shared_buffer) - 1);
42
+
43
+ netdata_fix_chart_name(windows_shared_buffer);
44
+ struct thermal_zone *p = dictionary_set(thermal_zones, windows_shared_buffer, NULL, sizeof(*p));
45
+
46
+ perflibGetInstanceCounter(pDataBlock, pObjectType, pi, &p->thermalZoneTemperature);
47
+
48
+ // https://learn.microsoft.com/en-us/windows-hardware/design/device-experiences/design-guide
49
+ if(!p->st) {
50
+ char id[RRD_ID_LENGTH_MAX + 1];
51
+ snprintfz(id, RRD_ID_LENGTH_MAX, "thermalzone_%s_temperature", windows_shared_buffer);
52
+ p->st = rrdset_create_localhost(
53
+ "system"
54
+ , id, NULL
55
+ , "thermalzone"
56
+ , "system.thermalzone_temperature"
57
+ , "Thermal zone temperature"
58
+ , "Celsius"
59
+ , PLUGIN_WINDOWS_NAME
60
+ , "ThermalZone"
61
+ , NETDATA_CHART_PRIO_WINDOWS_THERMAL_ZONES
62
+ , update_every
63
+ , RRDSET_TYPE_LINE
64
+ );
65
+
66
+ p->rd = rrddim_add(p->st,
67
+ id,
68
+ "temperature",
69
+ 1,
70
+ 1,
71
+ RRD_ALGORITHM_ABSOLUTE);
72
+
73
+ rrdlabels_add(p->st->rrdlabels, "thermalzone", windows_shared_buffer, RRDLABEL_SRC_AUTO);
74
+ }
75
+
76
+ // Convert to Celsius before to plot
77
+ NETDATA_DOUBLE kTemperature = (NETDATA_DOUBLE)p->thermalZoneTemperature.current.Data;
78
+ kTemperature -= 273.15;
79
+
80
+ rrddim_set_by_pointer(p->st, p->rd, (collected_number)kTemperature);
81
+ rrdset_done(p->st);
82
+ }
83
+
84
+ return true;
85
+}
86
+
87
+int do_PerflibThermalZone(int update_every, usec_t dt __maybe_unused) {
88
+ static bool initialized = false;
89
+
90
+ if(unlikely(!initialized)) {
91
+ initialize();
92
+ initialized = true;
93
+ }
94
+
95
+ DWORD id = RegistryFindIDByName("Thermal Zone Information");
96
+ if(id == PERFLIB_REGISTRY_NAME_NOT_FOUND)
97
+ return -1;
98
+
99
+ PERF_DATA_BLOCK *pDataBlock = perflibGetPerformanceData(id);
100
+ if(!pDataBlock) return -1;
101
+
102
+ do_thermal_zones(pDataBlock, update_every);
103
+
104
+ return 0;
105
+}
src/collectors/windows.plugin/windows_plugin.c
+12
-10
@@ -13,18 +13,20 @@ static struct proc_module {
13
} win_modules[] = {
14
15
// system metrics
16
- {.name = "GetSystemUptime", .dim = "GetSystemUptime", .func = do_GetSystemUptime},
17
- {.name = "GetSystemRAM", .dim = "GetSystemRAM", .func = do_GetSystemRAM},
16
+ {.name = "GetSystemUptime", .dim = "GetSystemUptime", .enabled = CONFIG_BOOLEAN_YES, .func = do_GetSystemUptime},
17
+ {.name = "GetSystemRAM", .dim = "GetSystemRAM", .enabled = CONFIG_BOOLEAN_YES, .func = do_GetSystemRAM},
18
19
// the same is provided by PerflibProcessor, with more detailed analysis
20
- //{.name = "GetSystemCPU", .dim = "GetSystemCPU", .func = do_GetSystemCPU},
20
+ //{.name = "GetSystemCPU", .dim = "GetSystemCPU", .enabled = CONFIG_BOOLEAN_YES, .func = do_GetSystemCPU},
21
22
- {.name = "PerflibProcesses", .dim = "PerflibProcesses", .func = do_PerflibProcesses},
23
- {.name = "PerflibProcessor", .dim = "PerflibProcessor", .func = do_PerflibProcessor},
24
- {.name = "PerflibMemory", .dim = "PerflibMemory", .func = do_PerflibMemory},
25
- {.name = "PerflibStorage", .dim = "PerflibStorage", .func = do_PerflibStorage},
26
- {.name = "PerflibNetwork", .dim = "PerflibNetwork", .func = do_PerflibNetwork},
27
- {.name = "PerflibObjects", .dim = "PerflibObjects", .func = do_PerflibObjects},
22
+ {.name = "PerflibProcesses", .dim = "PerflibProcesses", .enabled = CONFIG_BOOLEAN_YES, .func = do_PerflibProcesses},
23
+ {.name = "PerflibProcessor", .dim = "PerflibProcessor", .enabled = CONFIG_BOOLEAN_YES, .func = do_PerflibProcessor},
24
+ {.name = "PerflibMemory", .dim = "PerflibMemory", .enabled = CONFIG_BOOLEAN_YES, .func = do_PerflibMemory},
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
+
29
+ {.name = "PerflibThermalZone", .dim = "PerflibThermalZone", .enabled = CONFIG_BOOLEAN_NO, .func = do_PerflibThermalZone},
30
31
// the terminator of this array
32
{.name = NULL, .dim = NULL, .func = NULL}
@@ -66,7 +68,7 @@ void *win_plugin_main(void *ptr) {
68
for(i = 0; win_modules[i].name; i++) {
69
struct proc_module *pm = &win_modules[i];
70
69
- pm->enabled = config_get_boolean("plugin:windows", pm->name, CONFIG_BOOLEAN_YES);
71
+ pm->enabled = config_get_boolean("plugin:windows", pm->name, pm->enabled);
72
pm->rd = NULL;
73
74
worker_register_job_name(i, win_modules[i].dim);
src/collectors/windows.plugin/windows_plugin.h
+1
@@ -24,6 +24,7 @@ int do_PerflibProcesses(int update_every, usec_t dt);
24
int do_PerflibProcessor(int update_every, usec_t dt);
25
int do_PerflibMemory(int update_every, usec_t dt);
26
int do_PerflibObjects(int update_every, usec_t dt);
27
+int do_PerflibThermalZone(int update_every, usec_t dt);
28
29
#include "perflib.h"
30