master
c 108 lines 3.38 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 #include "windows_plugin.h"
4 #include "windows-internals.h"
5
6 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 {
15 p->thermalZoneTemperature.key = "Temperature";
16 }
17
18 void dict_thermal_zone_insert_cb(const DICTIONARY_ITEM *item __maybe_unused, void *value, void *data __maybe_unused)
19 {
20 struct thermal_zone *p = value;
21 initialize_thermal_zone_keys(p);
22 }
23
24 static DICTIONARY *thermal_zones = NULL;
25
26 static void initialize(void)
27 {
28 thermal_zones = dictionary_create_advanced(
29 DICT_OPTION_DONT_OVERWRITE_VALUE | DICT_OPTION_FIXED_SIZE, NULL, sizeof(struct thermal_zone));
30
31 dictionary_register_insert_callback(thermal_zones, dict_thermal_zone_insert_cb, NULL);
32 }
33
34 static bool do_thermal_zones(PERF_DATA_BLOCK *pDataBlock, int update_every)
35 {
36 PERF_OBJECT_TYPE *pObjectType = perflibFindObjectTypeByName(pDataBlock, "Thermal Zone Information");
37 if (!pObjectType)
38 return false;
39
40 PERF_INSTANCE_DEFINITION *pi = NULL;
41 for (LONG i = 0; i < pObjectType->NumInstances; i++) {
42 pi = perflibForEachInstance(pDataBlock, pObjectType, pi);
43 if (!pi)
44 break;
45
46 if (!getInstanceName(pDataBlock, pObjectType, pi, windows_shared_buffer, sizeof(windows_shared_buffer)))
47 strncpyz(windows_shared_buffer, "[unknown]", sizeof(windows_shared_buffer) - 1);
48
49 struct thermal_zone *p = dictionary_set(thermal_zones, windows_shared_buffer, NULL, sizeof(*p));
50
51 perflibGetInstanceCounter(pDataBlock, pObjectType, pi, &p->thermalZoneTemperature);
52
53 // https://learn.microsoft.com/en-us/windows-hardware/design/device-experiences/design-guide
54 if (!p->st) {
55 char id[RRD_ID_LENGTH_MAX + 1];
56 snprintfz(id, RRD_ID_LENGTH_MAX, "thermalzone_%s_temperature", windows_shared_buffer);
57 netdata_fix_chart_name(id);
58 p->st = rrdset_create_localhost(
59 "system",
60 id,
61 NULL,
62 "thermalzone",
63 "system.thermalzone_temperature",
64 "Thermal zone temperature",
65 "Celsius",
66 PLUGIN_WINDOWS_NAME,
67 "ThermalZone",
68 NETDATA_CHART_PRIO_WINDOWS_THERMAL_ZONES,
69 update_every,
70 RRDSET_TYPE_LINE);
71
72 p->rd = rrddim_add(p->st, id, "temperature", 1, 1, RRD_ALGORITHM_ABSOLUTE);
73
74 rrdlabels_add(p->st->rrdlabels, "thermalzone", windows_shared_buffer, RRDLABEL_SRC_AUTO);
75 }
76
77 // Convert to Celsius before to plot
78 NETDATA_DOUBLE kTemperature = (NETDATA_DOUBLE)p->thermalZoneTemperature.current.Data;
79 kTemperature -= 273.15;
80
81 rrddim_set_by_pointer(p->st, p->rd, (collected_number)kTemperature);
82 rrdset_done(p->st);
83 }
84
85 return true;
86 }
87
88 int do_PerflibThermalZone(int update_every, usec_t dt __maybe_unused)
89 {
90 static bool initialized = false;
91
92 if (unlikely(!initialized)) {
93 initialize();
94 initialized = true;
95 }
96
97 DWORD id = RegistryFindIDByName("Thermal Zone Information");
98 if (id == PERFLIB_REGISTRY_NAME_NOT_FOUND)
99 return -1;
100
101 PERF_DATA_BLOCK *pDataBlock = perflibGetPerformanceData(id);
102 if (!pDataBlock)
103 return -1;
104
105 do_thermal_zones(pDataBlock, update_every);
106
107 return 0;
108 }