master
c 346 lines 9.96 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 #include "windows_plugin.h"
4
5 char windows_shared_buffer[8192];
6
7 static struct proc_module {
8 const char *name;
9 const char *dim;
10 int enabled;
11 int update_every;
12 int (*func)(int update_every, usec_t dt);
13 RRDDIM *rd;
14 ND_THREAD *thread;
15 void (*cleanup)();
16 } win_modules[] = {
17
18 // system metrics
19 {.name = "GetSystemUptime",
20 .dim = "GetSystemUptime",
21 .enabled = CONFIG_BOOLEAN_YES,
22 .update_every = UPDATE_EVERY_MIN,
23 .func = do_GetSystemUptime,
24 .rd = NULL,
25 .thread = NULL,
26 .cleanup = NULL},
27 {.name = "GetSystemRAM",
28 .dim = "GetSystemRAM",
29 .enabled = CONFIG_BOOLEAN_YES,
30 .update_every = UPDATE_EVERY_MIN,
31 .func = do_GetSystemRAM,
32 .rd = NULL,
33 .thread = NULL,
34 .cleanup = NULL},
35 {.name = "GetPowerSupply",
36 .dim = "GetPowerSupply",
37 .enabled = CONFIG_BOOLEAN_YES,
38 .update_every = UPDATE_EVERY_MIN,
39 .func = do_GetPowerSupply,
40 .rd = NULL,
41 .thread = NULL,
42 .cleanup = do_GetPowerSupply_cleanup},
43 {.name = "GetSensors",
44 .dim = "GetSensors",
45 .enabled = CONFIG_BOOLEAN_YES,
46 .update_every = UPDATE_EVERY_MIN,
47 .func = do_GetSensors,
48 .rd = NULL,
49 .thread = NULL,
50 .cleanup = do_Sensors_cleanup},
51 {.name = "GetHardwareInfo",
52 .dim = "GetHardwareInfo",
53 .enabled = CONFIG_BOOLEAN_YES,
54 .update_every = 10 * UPDATE_EVERY_MIN,
55 .func = do_GetHardwareInfo,
56 .rd = NULL,
57 .thread = NULL,
58 .cleanup = do_GetHardwareInfo_cleanup},
59 {.name = "PerflibServices",
60 .dim = "PerflibServices",
61 .enabled = CONFIG_BOOLEAN_YES,
62 .update_every = 30 * UPDATE_EVERY_MIN,
63 .func = do_GetServicesStatus,
64 .rd = NULL,
65 .thread = NULL,
66 .cleanup = do_GetServicesStatus_cleanup},
67
68 // the same is provided by PerflibProcessor, with more detailed analysis
69 //{.name = "GetSystemCPU", .dim = "GetSystemCPU", .enabled = CONFIG_BOOLEAN_YES,
70 // .update_every = UPDATE_EVERY_MIN, .func = do_GetSystemCPU, .cleanup = do_GetSystemCPU_cleanup},
71
72 {.name = "PerflibProcesses",
73 .dim = "PerflibProcesses",
74 .enabled = CONFIG_BOOLEAN_YES,
75 .update_every = UPDATE_EVERY_MIN,
76 .func = do_PerflibProcesses,
77 .rd = NULL,
78 .thread = NULL,
79 .cleanup = NULL},
80 {.name = "PerflibProcessor",
81 .dim = "PerflibProcessor",
82 .enabled = CONFIG_BOOLEAN_YES,
83 .update_every = UPDATE_EVERY_MIN,
84 .func = do_PerflibProcessor,
85 .rd = NULL,
86 .thread = NULL,
87 .cleanup = NULL},
88 {.name = "PerflibMemory",
89 .dim = "PerflibMemory",
90 .enabled = CONFIG_BOOLEAN_YES,
91 .update_every = UPDATE_EVERY_MIN,
92 .func = do_PerflibMemory,
93 .rd = NULL,
94 .thread = NULL,
95 .cleanup = NULL},
96 {.name = "PerflibStorage",
97 .dim = "PerflibStorage",
98 .enabled = CONFIG_BOOLEAN_YES,
99 .update_every = UPDATE_EVERY_MIN,
100 .func = do_PerflibStorage,
101 .rd = NULL,
102 .thread = NULL,
103 .cleanup = NULL},
104 {.name = "PerflibNetwork",
105 .dim = "PerflibNetwork",
106 .enabled = CONFIG_BOOLEAN_YES,
107 .update_every = UPDATE_EVERY_MIN,
108 .func = do_PerflibNetwork,
109 .rd = NULL,
110 .thread = NULL,
111 .cleanup = NULL},
112 {.name = "PerflibSMB",
113 .dim = "PerflibSMB",
114 .enabled = CONFIG_BOOLEAN_NO,
115 .update_every = UPDATE_EVERY_MIN,
116 .func = do_PerflibSMB,
117 .rd = NULL,
118 .thread = NULL,
119 .cleanup = do_PerflibSMB_cleanup},
120 {.name = "PerflibObjects",
121 .dim = "PerflibObjects",
122 .enabled = CONFIG_BOOLEAN_YES,
123 .update_every = UPDATE_EVERY_MIN,
124 .func = do_PerflibObjects,
125 .rd = NULL,
126 .thread = NULL,
127 .cleanup = NULL},
128 {.name = "PerflibHyperV",
129 .dim = "PerflibHyperV",
130 .enabled = CONFIG_BOOLEAN_YES,
131 .update_every = 5 * UPDATE_EVERY_MIN,
132 .func = do_PerflibHyperV,
133 .rd = NULL,
134 .thread = NULL,
135 .cleanup = NULL},
136 {.name = "PerflibThermalZone",
137 .dim = "PerflibThermalZone",
138 .enabled = CONFIG_BOOLEAN_NO,
139 .update_every = 5 * UPDATE_EVERY_MIN,
140 .func = do_PerflibThermalZone,
141 .rd = NULL,
142 .thread = NULL,
143 .cleanup = NULL},
144 {.name = "PerflibWebService",
145 .dim = "PerflibWebService",
146 .enabled = CONFIG_BOOLEAN_YES,
147 .update_every = UPDATE_EVERY_MIN,
148 .func = do_PerflibWebService,
149 .rd = NULL,
150 .thread = NULL,
151 .cleanup = NULL},
152 {.name = "PerflibNetFramework",
153 .dim = "PerflibNetFramework",
154 .enabled = CONFIG_BOOLEAN_YES,
155 .update_every = UPDATE_EVERY_MIN,
156 .func = do_PerflibNetFramework,
157 .rd = NULL,
158 .thread = NULL,
159 .cleanup = NULL},
160 {.name = "PerflibAD",
161 .dim = "PerflibAD",
162 .enabled = CONFIG_BOOLEAN_YES,
163 .update_every = 10 * UPDATE_EVERY_MIN,
164 .func = do_PerflibAD,
165 .rd = NULL,
166 .thread = NULL,
167 .cleanup = NULL},
168 {.name = "PerflibADCS",
169 .dim = "PerflibADCS",
170 .enabled = CONFIG_BOOLEAN_YES,
171 .update_every = 10 * UPDATE_EVERY_MIN,
172 .func = do_PerflibADCS,
173 .rd = NULL,
174 .thread = NULL,
175 .cleanup = NULL},
176 {.name = "PerflibADFS",
177 .dim = "PerflibADFS",
178 .enabled = CONFIG_BOOLEAN_YES,
179 .update_every = 10 * UPDATE_EVERY_MIN,
180 .func = do_PerflibADFS,
181 .rd = NULL,
182 .thread = NULL,
183 .cleanup = NULL},
184 {.name = "PerflibExchange",
185 .dim = "PerflibExchange",
186 .enabled = CONFIG_BOOLEAN_YES,
187 .update_every = 10 * UPDATE_EVERY_MIN,
188 .func = do_PerflibExchange,
189 .rd = NULL,
190 .thread = NULL,
191 .cleanup = NULL},
192 {.name = "PerflibNUMA",
193 .dim = "PerflibNUMA",
194 .enabled = CONFIG_BOOLEAN_YES,
195 .update_every = UPDATE_EVERY_MIN,
196 .func = do_PerflibNUMA,
197 .rd = NULL,
198 .thread = NULL,
199 .cleanup = NULL},
200 // the terminator of this array
201 {.name = "PerflibASP",
202 .dim = "PerflibASP",
203 .enabled = CONFIG_BOOLEAN_YES,
204 .update_every = UPDATE_EVERY_MIN,
205 .func = do_PerflibASP,
206 .rd = NULL,
207 .thread = NULL,
208 .cleanup = NULL},
209 // the terminator of this array
210 {.name = NULL, .dim = NULL, .func = NULL, .rd = NULL, .thread = NULL, .cleanup = NULL}};
211
212 #if WORKER_UTILIZATION_MAX_JOB_TYPES < 36
213 #error WORKER_UTILIZATION_MAX_JOB_TYPES has to be at least 36
214 #endif
215
216 static void windows_main_cleanup(void *pptr)
217 {
218 struct netdata_static_thread *static_thread = CLEANUP_FUNCTION_GET_PTR(pptr);
219 if (!static_thread)
220 return;
221
222 static_thread->enabled = NETDATA_MAIN_THREAD_EXITING;
223
224 // Cleanup registry resources
225 PerflibNamesRegistryCleanup();
226
227 static_thread->enabled = NETDATA_MAIN_THREAD_EXITED;
228
229 worker_unregister();
230 }
231
232 static bool log_windows_module(BUFFER *wb, void *data)
233 {
234 struct proc_module *pm = data;
235 buffer_sprintf(wb, PLUGIN_WINDOWS_NAME "[%s]", pm->name);
236 return true;
237 }
238
239 static void windows_plugin_thread_worker(void *ptr __maybe_unused)
240 {
241 struct proc_module *mod = ptr;
242 heartbeat_t hb;
243 int update_every = mod->update_every;
244
245 heartbeat_init(&hb, USEC_PER_SEC);
246 usec_t step = USEC_PER_SEC * update_every;
247 usec_t real_step = USEC_PER_SEC;
248
249 usec_t last = now_realtime_usec();
250 while (service_running(SERVICE_COLLECTORS)) {
251 heartbeat_next(&hb);
252 if (real_step < step) {
253 real_step += USEC_PER_SEC;
254 continue;
255 }
256 real_step = USEC_PER_SEC;
257 usec_t now = now_realtime_usec();
258 mod->func(update_every, now - last);
259 last = now;
260 }
261 }
262
263 void win_plugin_main(void *ptr)
264 {
265 worker_register("WIN");
266
267 rrd_collector_started();
268 PerflibNamesRegistryInitialize();
269
270 CLEANUP_FUNCTION_REGISTER(windows_main_cleanup) cleanup_ptr = ptr;
271
272 // check the enabled status for each module
273 int i;
274 char buf[CONFIG_MAX_NAME + 1];
275 int update_every = localhost->rrd_update_every;
276 for (i = 0; win_modules[i].name; i++) {
277 struct proc_module *pm = &win_modules[i];
278 snprintfz(buf, CONFIG_MAX_NAME, "plugin:windows:%s", pm->name);
279
280 pm->enabled = inicfg_get_boolean(&netdata_config, "plugin:windows", pm->name, pm->enabled);
281 pm->rd = NULL;
282
283 pm->update_every = (int)inicfg_get_duration_seconds(
284 &netdata_config, buf, "update every", (update_every != pm->update_every) ? pm->update_every : update_every);
285
286 if (pm->enabled && unlikely(update_every != pm->update_every)) {
287 char tag_name[ND_THREAD_TAG_MAX];
288 snprintfz(tag_name, ND_THREAD_TAG_MAX - 1, "WIN_PLUGIN[%d]", i);
289 pm->thread = nd_thread_create(tag_name, NETDATA_THREAD_OPTION_DEFAULT, windows_plugin_thread_worker, pm);
290 }
291
292 worker_register_job_name(i, win_modules[i].dim);
293 }
294
295 heartbeat_t hb;
296 heartbeat_init(&hb, localhost->rrd_update_every * USEC_PER_SEC);
297
298 #define LGS_MODULE_ID 0
299
300 ND_LOG_STACK lgs[] = {
301 [LGS_MODULE_ID] = ND_LOG_FIELD_TXT(NDF_MODULE, PLUGIN_WINDOWS_NAME),
302 ND_LOG_FIELD_END(),
303 };
304 ND_LOG_STACK_PUSH(lgs);
305
306 while (service_running(SERVICE_COLLECTORS)) {
307 worker_is_idle();
308 usec_t hb_dt = heartbeat_next(&hb);
309
310 if (unlikely(!service_running(SERVICE_COLLECTORS)))
311 break;
312
313 PerflibNamesRegistryUpdate();
314
315 for (i = 0; win_modules[i].name; i++) {
316 if (unlikely(!service_running(SERVICE_COLLECTORS)))
317 break;
318
319 struct proc_module *pm = &win_modules[i];
320 // if we have a thread, we are already running it
321 if (pm->thread)
322 continue;
323
324 if (unlikely(!pm->enabled))
325 continue;
326
327 worker_is_busy(i);
328 lgs[LGS_MODULE_ID] = ND_LOG_FIELD_CB(NDF_MODULE, log_windows_module, pm);
329 pm->enabled = !pm->func(pm->update_every, hb_dt);
330 lgs[LGS_MODULE_ID] = ND_LOG_FIELD_TXT(NDF_MODULE, PLUGIN_WINDOWS_NAME);
331 }
332 }
333
334 // Join threads
335 for (i = 0; win_modules[i].name; i++) {
336 struct proc_module *pm = &win_modules[i];
337
338 if (pm->thread) {
339 nd_thread_join(pm->thread);
340 pm->thread = NULL;
341 }
342
343 if (pm->cleanup)
344 pm->cleanup();
345 }
346 }