@cryptotaxi247 / netdata-1 / commits / 90a7ecb11

feat(system-info): improve Windows OS detection and categorization (#20117)

Costa Tsaousis committed Apr 11, 2025 at 10:46 UTC 90a7ecb11a3854a1f4cfd584fcc155f66675ad2c
3 files changed +75 -4
src/daemon/win_system-info.c
+74 -2
@@ -243,6 +243,78 @@ static void netdata_windows_os_kernel_version(char *out, DWORD length, DWORD bui
243 (void)snprintf(out, length, "Windows %u.%u.%u Build: %u", major, minor, build, build);
244 }
245
246 +static char *netdata_windows_get_edition(void)
247 +{
248 + static char edition[256] = {0};
249 +
250 + // Try to read EditionID first, which is more precise
251 + if (netdata_registry_get_string(edition, sizeof(edition)-1, HKEY_LOCAL_MACHINE,
252 + "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion",
253 + "EditionID")) {
254 + return edition;
255 + }
256 +
257 + // If EditionID fails, try ProductName
258 + if (netdata_registry_get_string(edition, sizeof(edition)-1, HKEY_LOCAL_MACHINE,
259 + "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion",
260 + "ProductName")) {
261 + return edition;
262 + }
263 +
264 + // Return unknown if both methods fail
265 + return NETDATA_DEFAULT_SYSTEM_INFO_VALUE_UNKNOWN;
266 +}
267 +
268 +static char *netdata_windows_get_os_id_like(DWORD build)
269 +{
270 + static char id_like[256];
271 + char *edition = netdata_windows_get_edition();
272 + const char *base_id = "";
273 +
274 + if (IsWindowsServer()) {
275 + // Windows Server versions based on build numbers
276 + if (build >= 25000)
277 + base_id = "Windows-Server-2025";
278 + else if (build >= 20348)
279 + base_id = "Windows-Server-2022";
280 + else if (build >= 17763)
281 + base_id = "Windows-Server-2019";
282 + else if (build >= 14393)
283 + base_id = "Windows-Server-2016";
284 + else if (build >= 9600)
285 + base_id = "Windows-Server-2012R2";
286 + else if (build >= 9200)
287 + base_id = "Windows-Server-2012";
288 + else if (build >= 7601)
289 + base_id = "Windows-Server-2008R2";
290 + else
291 + base_id = "Windows-Server";
292 + } else {
293 + // Windows client versions
294 + if (build >= 22000)
295 + base_id = "Windows-11";
296 + else if (build >= 10240)
297 + base_id = "Windows-10";
298 + else if (build >= 9600)
299 + base_id = "Windows-8.1";
300 + else if (build >= 9200)
301 + base_id = "Windows-8";
302 + else if (build >= 7601)
303 + base_id = "Windows-7";
304 + else
305 + base_id = "Windows";
306 + }
307 +
308 + // If we have a valid edition, append it to the ID_LIKE with a dash
309 + if (strcmp(edition, NETDATA_DEFAULT_SYSTEM_INFO_VALUE_UNKNOWN) != 0) {
310 + snprintf(id_like, sizeof(id_like), "%s-%s", base_id, edition);
311 + } else {
312 + strcpy(id_like, base_id);
313 + }
314 +
315 + return id_like;
316 +}
317 +
318 static void netdata_windows_host(struct rrdhost_system_info *systemInfo)
319 {
320 char osVersion[4096];
@@ -253,8 +325,8 @@ static void netdata_windows_host(struct rrdhost_system_info *systemInfo)
325 netdata_windows_discover_os_version(osVersion, 4095, build);
326 (void)rrdhost_system_info_set_by_name(systemInfo, "NETDATA_HOST_OS_ID", osVersion);
327
256 - (void)rrdhost_system_info_set_by_name(
257 - systemInfo, "NETDATA_HOST_OS_ID_LIKE", NETDATA_DEFAULT_SYSTEM_INFO_VALUE_UNKNOWN);
328 + char *id_like = netdata_windows_get_os_id_like(build);
329 + (void)rrdhost_system_info_set_by_name(systemInfo, "NETDATA_HOST_OS_ID_LIKE", id_like);
330
331 (void)rrdhost_system_info_set_by_name(systemInfo, "NETDATA_HOST_OS_VERSION", osVersion);
332 (void)rrdhost_system_info_set_by_name(systemInfo, "NETDATA_HOST_OS_VERSION_ID", osVersion);
src/daemon/win_system-info.h
+1
@@ -9,6 +9,7 @@
9 #define NETDATA_DEFAULT_SYSTEM_INFO_VALUE_UNKNOWN "unknown"
10 #define NETDATA_DEFAULT_SYSTEM_INFO_VALUE_NONE "none"
11 #define NETDATA_DEFAULT_SYSTEM_INFO_VALUE_FALSE "false"
12 +#define NETDATA_WIN_DETECTION_METHOD "windows-api"
13
14 #ifdef OS_WINDOWS
15 #include "windows.h"
src/libnetdata/os/os-windows-wrappers.h
-2
@@ -6,8 +6,6 @@
6 #include "../libnetdata.h"
7
8 #if defined(OS_WINDOWS)
9 -#define NETDATA_WIN_DETECTION_METHOD "Windows API/Registry"
10 -
9 long netdata_registry_get_dword_from_open_key(unsigned int *out, void *lKey, char *name);
10 bool netdata_registry_get_dword(unsigned int *out, void *hKey, char *subKey, char *name);
11