Windows Plugin (Sensors) (#20840)
thiagoftsm committed
Aug 20, 2025 at 14:20 UTC
03f8c79250a9411fff8303c02fedb25dbf490b57
6 files changed
+580
-2
CMakeLists.txt
+2
-1
@@ -1951,6 +1951,7 @@ set(WINDOWS_PLUGIN_FILES
1951
src/collectors/windows.plugin/GetSystemCPU.c
1952
src/collectors/windows.plugin/GetPowerSupply.c
1953
src/collectors/windows.plugin/GetServicesStatus.c
1954
+ src/collectors/windows.plugin/GetSensors.c
1955
src/collectors/windows.plugin/perflib-adcs.c
1956
src/collectors/windows.plugin/perflib-adfs.c
1957
src/collectors/windows.plugin/perflib-rrd.c
@@ -2215,7 +2216,7 @@ target_link_libraries(libnetdata PUBLIC
2216
"$<$<BOOL:${ENABLE_MIMALLOC}>:mimalloc-static>"
2217
"$<$<NOT:$<BOOL:${HAVE_BUILTIN_ATOMICS}>>:atomic>"
2218
"$<$<OR:$<BOOL:${OS_LINUX}>,$<BOOL:${OS_FREEBSD}>>:pthread;rt>"
2218
- "$<$<BOOL:${OS_WINDOWS}>:kernel32;advapi32;winmm;rpcrt4;wevtapi;ole32;oleaut32;wbemuuid>"
2219
+ "$<$<BOOL:${OS_WINDOWS}>:kernel32;advapi32;winmm;rpcrt4;wevtapi;ole32;oleaut32;wbemuuid;sensorsapi>"
2220
"$<$<BOOL:${LINK_LIBM}>:m>"
2221
"${SYSTEMD_LDFLAGS}")
2222
src/collectors/all.h
+3
@@ -452,6 +452,9 @@
452
#define NETDATA_CHART_PRIO_CGROUPS_SYSTEMD 19000 // many charts
453
#define NETDATA_CHART_PRIO_CGROUPS_CONTAINERS 40000 // many charts
454
455
+// Sensors
456
+#define NETDATA_CHART_PRIO_SENSORS 70000 // many charts
457
+
458
// STATSD
459
460
#define NETDATA_CHART_PRIO_STATSD_PRIVATE 90000 // many charts
src/collectors/windows.plugin/GetSensors.c
new
+439
@@ -0,0 +1,439 @@
1
+// SPDX-License-Identifier: GPL-3.0-or-later
2
+
3
+#include "windows_plugin.h"
4
+#include "windows-internals.h"
5
+#include "libnetdata/os/windows-wmi/windows-wmi.h"
6
+
7
+#include <windows.h>
8
+#include <wchar.h>
9
+
10
+#include <sensorsapi.h>
11
+#include <sensors.h>
12
+#include <propidl.h>
13
+
14
+static ISensorManager *pSensorManager = NULL;
15
+static ND_THREAD *sensors_thread_update = NULL;
16
+
17
+#define NETDATA_WIN_SENSOR_STATES (6)
18
+
19
+enum netdata_win_sensor_monitored {
20
+ NETDATA_WIN_SENSOR_CELSIUS,
21
+ NETDATA_WIN_SENSOR_POWER_WATTS,
22
+ NETDATA_WIN_SENSOR_CURRENT_AMPS,
23
+ NETDATA_WIN_SENSOR_RELATIVITY_HUMIDITY,
24
+ NETDATA_WIN_SENSOR_LIGHT_LEVEL
25
+};
26
+
27
+REFPROPERTYKEY sensor_keys[] = {
28
+ &SENSOR_DATA_TYPE_TEMPERATURE_CELSIUS,
29
+ &SENSOR_DATA_TYPE_ELECTRICAL_POWER_WATTS,
30
+ &SENSOR_DATA_TYPE_CURRENT_AMPS,
31
+ &SENSOR_DATA_TYPE_RELATIVE_HUMIDITY_PERCENT,
32
+ &SENSOR_DATA_TYPE_LIGHT_LEVEL_LUX,
33
+
34
+ NULL};
35
+
36
+
37
+static struct win_sensor_config {
38
+ const char *title;
39
+ const char *units;
40
+ const char *context;
41
+ const char *family;
42
+
43
+ int priority;
44
+} configs[] = {
45
+ {
46
+ .title = "Sensor Temperature",
47
+ .units = "Cel",
48
+ .context = "system.hw.sensor.temperature.input",
49
+ .family = "Temperature",
50
+ .priority = 70000,
51
+ },
52
+ {
53
+ .title = "Sensor Power",
54
+ .units = "W",
55
+ .context = "system.hw.sensor.power.input",
56
+ .family = "Power",
57
+ .priority = 70006,
58
+ },
59
+ {
60
+ .title = "Sensor Current",
61
+ .units = "A",
62
+ .context = "system.hw.sensor.current.input",
63
+ .family = "Current",
64
+ .priority = 70003,
65
+ },
66
+ {
67
+ .title = "Sensor Humidity",
68
+ .units = "%",
69
+ .context = "system.hw.sensor.humidity.input",
70
+ .family = "Humidity",
71
+ .priority = 70004,
72
+ },
73
+ {
74
+ .title = "Ambient light level",
75
+ .units = "lx",
76
+ .context = "system.hw.sensor.lux.input",
77
+ .family = "illuminance",
78
+ .priority = 70010,
79
+ }
80
+};
81
+
82
+struct sensor_data {
83
+ bool initialized;
84
+ bool first_time;
85
+ bool enabled;
86
+ enum netdata_win_sensor_monitored sensor_data_type;
87
+ struct win_sensor_config *config;
88
+
89
+ const char *type;
90
+ const char *category;
91
+ const char *name;
92
+ const char *manufacturer;
93
+ const char *model;
94
+
95
+ SensorState current_state;
96
+
97
+ RRDSET *st_sensor_state;
98
+ RRDDIM *rd_sensor_state[NETDATA_WIN_SENSOR_STATES];
99
+
100
+ RRDSET *st_sensor_data;
101
+ RRDDIM *rd_sensor_data;
102
+
103
+ collected_number current_data_value;
104
+};
105
+
106
+DICTIONARY *sensors;
107
+
108
+// Microsoft appends additional data
109
+#define ADDTIONAL_UUID_STR_LEN (UUID_STR_LEN + 8)
110
+
111
+static void netdata_clsid_to_char(char *output, const GUID *pguid)
112
+{
113
+ LPWSTR wguid = NULL;
114
+ if (SUCCEEDED(StringFromCLSID(pguid, &wguid)) && wguid) {
115
+ size_t len = wcslen(wguid);
116
+ wcstombs(output, wguid, len);
117
+ CoTaskMemFree(wguid);
118
+ }
119
+}
120
+
121
+static inline char *netdata_convert_guid_to_string(HRESULT hr, GUID *value) {
122
+ if (SUCCEEDED(hr)) {
123
+ char cguid[ADDTIONAL_UUID_STR_LEN];
124
+ netdata_clsid_to_char(cguid, value);
125
+ return strdupz(cguid);
126
+ }
127
+ return NULL;
128
+}
129
+
130
+static inline void netdata_fill_sensor_type(struct sensor_data *s, ISensor *pSensor)
131
+{
132
+ GUID type = {0};
133
+ HRESULT hr = pSensor->lpVtbl->GetType(pSensor, &type);
134
+ s->type = netdata_convert_guid_to_string(hr, &type);
135
+}
136
+
137
+static inline void netdata_fill_sensor_category(struct sensor_data *s, ISensor *pSensor)
138
+{
139
+ GUID category = {0};
140
+ HRESULT hr = pSensor->lpVtbl->GetCategory(pSensor, &category);
141
+ s->category = netdata_convert_guid_to_string(hr, &category);
142
+}
143
+
144
+static inline char *netdata_pvar_to_char(const PROPERTYKEY *key, ISensor *pSensor)
145
+{
146
+ PROPVARIANT pv;
147
+ PropVariantInit(&pv);
148
+ HRESULT hr = pSensor->lpVtbl->GetProperty(pSensor, key, &pv);
149
+ if (SUCCEEDED(hr) && pv.vt == VT_LPWSTR) {
150
+ char value[8192];
151
+ size_t len = wcslen(pv.pwszVal);
152
+ wcstombs(value, pv.pwszVal, len);
153
+ PropVariantClear(&pv);
154
+ return strdupz(value);
155
+ }
156
+ PropVariantClear(&pv);
157
+ return NULL;
158
+}
159
+
160
+static void netdata_initialize_sensor_dict(struct sensor_data *s, ISensor *pSensor)
161
+{
162
+ netdata_fill_sensor_type(s, pSensor);
163
+ netdata_fill_sensor_category(s, pSensor);
164
+ s->name = netdata_pvar_to_char(&SENSOR_PROPERTY_FRIENDLY_NAME, pSensor);
165
+ s->model = netdata_pvar_to_char(&SENSOR_PROPERTY_MODEL, pSensor);
166
+ s->manufacturer = netdata_pvar_to_char(&SENSOR_PROPERTY_MANUFACTURER, pSensor);
167
+}
168
+
169
+static int
170
+netdata_collect_sensor_data(struct sensor_data *s, ISensor *pSensor, REFPROPERTYKEY key)
171
+{
172
+ ISensorDataReport *pReport = NULL;
173
+ PROPVARIANT pv = {};
174
+ HRESULT hr;
175
+
176
+ int defined = 0;
177
+ hr = pSensor->lpVtbl->GetData(pSensor, &pReport);
178
+ if (SUCCEEDED(hr) && pReport) {
179
+ PropVariantInit(&pv);
180
+ hr = pReport->lpVtbl->GetSensorValue(pReport, key, &pv);
181
+ if (SUCCEEDED(hr) && (pv.vt == VT_R4 || pv.vt == VT_R8 || pv.vt == VT_UI4)) {
182
+ switch (pv.vt) {
183
+ case VT_UI4:
184
+ s->current_data_value = (collected_number)(pv.ulVal * 100);
185
+ break;
186
+ case VT_R4:
187
+ s->current_data_value = (collected_number)(pv.fltVal * 100.0);
188
+ break;
189
+ case VT_R8:
190
+ s->current_data_value = (collected_number)(pv.dblVal * 100.0);
191
+ break;
192
+ }
193
+ defined = 1;
194
+ }
195
+ PropVariantClear(&pv);
196
+ pReport->lpVtbl->Release(pReport);
197
+ }
198
+
199
+ return defined;
200
+}
201
+
202
+static void netdata_sensors_get_data(struct sensor_data *s, ISensor *pSensor)
203
+{
204
+ for (int i = 0; sensor_keys[i]; i++) {
205
+ if (netdata_collect_sensor_data(s, pSensor, sensor_keys[i])) {
206
+ s->sensor_data_type = i;
207
+ s->config = &configs[i];
208
+ s->enabled = true;
209
+ break;
210
+ }
211
+ }
212
+
213
+ s->first_time = false;
214
+}
215
+
216
+static void netdata_get_sensors()
217
+{
218
+ ISensorCollection *pSensorCollection = NULL;
219
+ HRESULT hr = pSensorManager->lpVtbl->GetSensorsByCategory(pSensorManager, &SENSOR_CATEGORY_ALL, &pSensorCollection);
220
+ if (FAILED(hr)) {
221
+ return;
222
+ }
223
+
224
+ ULONG count = 0;
225
+ hr = pSensorCollection->lpVtbl->GetCount(pSensorCollection, &count);
226
+ if (FAILED(hr)) {
227
+ return;
228
+ }
229
+
230
+ // the same size of windows_shared_buffer
231
+ char thread_values[8192];
232
+ for (ULONG i = 0; i < count; ++i) {
233
+ ISensor *pSensor = NULL;
234
+ hr = pSensorCollection->lpVtbl->GetAt(pSensorCollection, i, &pSensor);
235
+ if (FAILED(hr) || !pSensor) {
236
+ continue;
237
+ }
238
+
239
+ GUID id = {0};
240
+ hr = pSensor->lpVtbl->GetID(pSensor, &id);
241
+ if (FAILED(hr)) {
242
+ continue;
243
+ }
244
+ netdata_clsid_to_char(thread_values, &id);
245
+
246
+ struct sensor_data *s = dictionary_set(sensors, thread_values, NULL, sizeof(*s));
247
+
248
+ if (unlikely(!s->initialized)) {
249
+ netdata_initialize_sensor_dict(s, pSensor);
250
+ s->initialized = true;
251
+ }
252
+
253
+ s->current_state = SENSOR_STATE_MIN;
254
+ (void)pSensor->lpVtbl->GetState(pSensor, &s->current_state);
255
+
256
+ if (likely(s->first_time))
257
+ netdata_sensors_get_data(s, pSensor);
258
+ else if (likely(s->enabled))
259
+ netdata_collect_sensor_data(s, pSensor, sensor_keys[s->sensor_data_type]);
260
+
261
+ pSensor->lpVtbl->Release(pSensor);
262
+ }
263
+
264
+ pSensorCollection->lpVtbl->Release(pSensorCollection);
265
+}
266
+
267
+static void netdata_sensors_monitor(void *ptr __maybe_unused)
268
+{
269
+ heartbeat_t hb;
270
+ heartbeat_init(&hb, USEC_PER_SEC);
271
+
272
+ while (service_running(SERVICE_COLLECTORS)) {
273
+ (void)heartbeat_next(&hb);
274
+
275
+ if (unlikely(!service_running(SERVICE_COLLECTORS)))
276
+ break;
277
+
278
+ netdata_get_sensors();
279
+ }
280
+}
281
+
282
+void dict_sensor_insert(const DICTIONARY_ITEM *item __maybe_unused, void *value, void *data __maybe_unused)
283
+{
284
+ struct sensor_data *sd = value;
285
+
286
+ sd->first_time = true;
287
+ sd->sensor_data_type = 0;
288
+ sd->config = NULL;
289
+}
290
+
291
+static int initialize(int update_every)
292
+{
293
+ // This is an internal plugin, if we initialize these two times, collector will fail. To avoid this
294
+ // we call InitializeWMI to verify COM interface was already initialized.
295
+ HRESULT hr = InitializeWMI();
296
+ if (hr != S_OK) {
297
+ hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
298
+ if (FAILED(hr)) {
299
+ nd_log(NDLS_COLLECTORS, NDLP_ERR, "Collector cannot initialize COM interface.");
300
+ return -1;
301
+ }
302
+ }
303
+
304
+ hr = CoCreateInstance(
305
+ &CLSID_SensorManager, NULL, CLSCTX_INPROC_SERVER, &IID_ISensorManager, (void **)&pSensorManager);
306
+ if (FAILED(hr)) {
307
+ nd_log(NDLS_COLLECTORS, NDLP_ERR, "Collector cannot initialize sensor API.");
308
+ CoUninitialize();
309
+ return -1;
310
+ }
311
+
312
+ sensors = dictionary_create_advanced(
313
+ DICT_OPTION_DONT_OVERWRITE_VALUE | DICT_OPTION_FIXED_SIZE, NULL, sizeof(struct sensor_data));
314
+ dictionary_register_insert_callback(sensors, dict_sensor_insert, NULL);
315
+
316
+ sensors_thread_update =
317
+ nd_thread_create("sensors_upd", NETDATA_THREAD_OPTION_DEFAULT, netdata_sensors_monitor, &update_every);
318
+
319
+ return 0;
320
+}
321
+
322
+static void mssql_db_states_chart(struct sensor_data *sd, int update_every)
323
+{
324
+ if (!sd->st_sensor_state) {
325
+ char id[RRD_ID_LENGTH_MAX + 1];
326
+ snprintfz(id, RRD_ID_LENGTH_MAX, "%s_state", sd->name);
327
+ netdata_fix_chart_name(id);
328
+ sd->st_sensor_state = rrdset_create_localhost(
329
+ "sensors",
330
+ id,
331
+ NULL,
332
+ "sensors",
333
+ "system.hw.sensor.state",
334
+ "Current sensor state.",
335
+ "status",
336
+ PLUGIN_WINDOWS_NAME,
337
+ "GetSensors",
338
+ 70010,
339
+ update_every,
340
+ RRDSET_TYPE_LINE);
341
+
342
+ rrdlabels_add(sd->st_sensor_state->rrdlabels, "name", sd->name, RRDLABEL_SRC_AUTO);
343
+ rrdlabels_add(sd->st_sensor_state->rrdlabels, "manufacturer", sd->manufacturer, RRDLABEL_SRC_AUTO);
344
+ rrdlabels_add(sd->st_sensor_state->rrdlabels, "model", sd->model, RRDLABEL_SRC_AUTO);
345
+
346
+ sd->rd_sensor_state[0] = rrddim_add(sd->st_sensor_state, "ready", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
347
+ sd->rd_sensor_state[1] = rrddim_add(sd->st_sensor_state, "not_available", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
348
+ sd->rd_sensor_state[2] = rrddim_add(sd->st_sensor_state, "no_data", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
349
+ sd->rd_sensor_state[3] = rrddim_add(sd->st_sensor_state, "initializing", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
350
+ sd->rd_sensor_state[4] = rrddim_add(sd->st_sensor_state, "access_denied", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
351
+ sd->rd_sensor_state[5] = rrddim_add(sd->st_sensor_state, "error", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
352
+ }
353
+}
354
+
355
+static void mssql_sensor_state_chart_loop(struct sensor_data *sd, int update_every)
356
+{
357
+ mssql_db_states_chart(sd, update_every);
358
+ collected_number set_value = (collected_number)sd->current_state;
359
+ for (collected_number i = 0; i < NETDATA_WIN_SENSOR_STATES; i++) {
360
+ rrddim_set_by_pointer(sd->st_sensor_state, sd->rd_sensor_state[i], i == set_value);
361
+ }
362
+ rrdset_done(sd->st_sensor_state);
363
+}
364
+
365
+static void mssql_sensor_data_chart(struct sensor_data *sd, int update_every)
366
+{
367
+ if (!sd->st_sensor_data) {
368
+ char id[RRD_ID_LENGTH_MAX + 1];
369
+ snprintfz(id, RRD_ID_LENGTH_MAX, "sensors.%s_input", sd->name);
370
+ netdata_fix_chart_name(id);
371
+ sd->st_sensor_data = rrdset_create_localhost(
372
+ "sensors",
373
+ id,
374
+ NULL,
375
+ sd->config->family,
376
+ sd->config->context,
377
+ sd->config->title,
378
+ sd->config->units,
379
+ PLUGIN_WINDOWS_NAME,
380
+ "GetSensors",
381
+ sd->config->priority,
382
+ update_every,
383
+ RRDSET_TYPE_LINE);
384
+
385
+ rrdlabels_add(sd->st_sensor_data->rrdlabels, "name", sd->name, RRDLABEL_SRC_AUTO);
386
+ rrdlabels_add(sd->st_sensor_data->rrdlabels, "manufacturer", sd->manufacturer, RRDLABEL_SRC_AUTO);
387
+ rrdlabels_add(sd->st_sensor_data->rrdlabels, "model", sd->model, RRDLABEL_SRC_AUTO);
388
+
389
+ sd->rd_sensor_data = rrddim_add(sd->st_sensor_data, "input", NULL, 1, 100, RRD_ALGORITHM_ABSOLUTE);
390
+ }
391
+
392
+ rrddim_set_by_pointer(sd->st_sensor_data, sd->rd_sensor_data, sd->current_data_value);
393
+ rrdset_done(sd->st_sensor_data);
394
+}
395
+
396
+int dict_sensors_charts_cb(const DICTIONARY_ITEM *item __maybe_unused, void *value, void *data __maybe_unused)
397
+{
398
+ int *update_every = data;
399
+ struct sensor_data *sd = value;
400
+
401
+ if (unlikely(!sd->name))
402
+ return 1;
403
+
404
+ mssql_sensor_state_chart_loop(sd, *update_every);
405
+
406
+ if (unlikely(!sd->enabled))
407
+ return 1;
408
+
409
+ mssql_sensor_data_chart(sd, *update_every);
410
+
411
+ return 1;
412
+}
413
+
414
+int do_GetSensors(int update_every, usec_t dt __maybe_unused)
415
+{
416
+ static bool initialized = false;
417
+ if (unlikely(!initialized)) {
418
+ if (likely(initialize(update_every))) {
419
+ return -1;
420
+ }
421
+
422
+ initialized = true;
423
+ }
424
+
425
+ dictionary_sorted_walkthrough_read(sensors, dict_sensors_charts_cb, &update_every);
426
+ return 0;
427
+}
428
+
429
+void do_Sensors_cleanup()
430
+{
431
+ if (nd_thread_join(sensors_thread_update))
432
+ nd_log_daemon(NDLP_ERR, "Failed to join sensors thread update");
433
+
434
+ if (pSensorManager) {
435
+ pSensorManager->lpVtbl->Release(pSensorManager);
436
+
437
+ CoUninitialize();
438
+ }
439
+}
\ No newline at end of file
src/collectors/windows.plugin/metadata.yaml
+123
@@ -1078,6 +1078,129 @@ modules:
1078
chart_type: line
1079
dimensions:
1080
- name: now
1081
+ - meta:
1082
+ plugin_name: windows.plugin
1083
+ module_name: GetSensors
1084
+ monitored_instance:
1085
+ name: Sensors
1086
+ link: "https://learn.microsoft.com/en-us/windows/win32/sensorsapi/portal"
1087
+ categories:
1088
+ - data-collection.windows-systems
1089
+ icon_filename: "windows.svg"
1090
+ related_resources:
1091
+ integrations:
1092
+ list: []
1093
+ info_provided_to_referring_integrations:
1094
+ description: ""
1095
+ keywords:
1096
+ - Sensors
1097
+ - Windows
1098
+ most_popular: false
1099
+ overview:
1100
+ data_collection:
1101
+ metrics_description: |
1102
+ This collector monitors sensors on Windows systems.
1103
+ method_description: |
1104
+ It uses Sensors API to retrieve available data.
1105
+ supported_platforms:
1106
+ include: ["windows"]
1107
+ exclude: []
1108
+ multi_instance: false
1109
+ additional_permissions:
1110
+ description: ""
1111
+ default_behavior:
1112
+ auto_detection:
1113
+ description: |
1114
+ The collector automatically detects all of the metrics, no further configuration is required.
1115
+ limits:
1116
+ description: ""
1117
+ performance_impact:
1118
+ description: ""
1119
+ setup:
1120
+ prerequisites:
1121
+ list: []
1122
+ configuration:
1123
+ file:
1124
+ section_name: "[plugin:windows:GetSensors]"
1125
+ name: "netdata.conf"
1126
+ description: "The Netdata main configuration file."
1127
+ options:
1128
+ description: ""
1129
+ folding:
1130
+ title: "Config Option"
1131
+ enabled: false
1132
+ list:
1133
+ - name: update every
1134
+ description: Data collection frequency.
1135
+ default_value: 1
1136
+ required: false
1137
+ examples:
1138
+ folding:
1139
+ enabled: false
1140
+ title: ""
1141
+ list: []
1142
+ troubleshooting:
1143
+ problems:
1144
+ list: []
1145
+ alerts: []
1146
+ metrics:
1147
+ folding:
1148
+ title: Metrics
1149
+ enabled: false
1150
+ description: ""
1151
+ availability: []
1152
+ scopes:
1153
+ - name: Sensor
1154
+ description: "These metrics refer to Sensors."
1155
+ labels:
1156
+ - name: name
1157
+ description: Sensor friendly name.
1158
+ - name: manufacturer
1159
+ description: The sensor manufacturer.
1160
+ - name: model
1161
+ description: The sensor model.
1162
+ metrics:
1163
+ - name: system.hw.sensor.temperature
1164
+ description: Sensor Temperature
1165
+ unit: "Cel"
1166
+ chart_type: line
1167
+ dimensions:
1168
+ - name: input
1169
+ - name: system.hw.sensor.power
1170
+ description: Sensor Power
1171
+ unit: "W"
1172
+ chart_type: line
1173
+ dimensions:
1174
+ - name: input
1175
+ - name: system.hw.sensor.current
1176
+ description: Sensor Current
1177
+ unit: "A"
1178
+ chart_type: line
1179
+ dimensions:
1180
+ - name: input
1181
+ - name: system.hw.sensor.humidity
1182
+ description: Sensor Humidity
1183
+ unit: "%"
1184
+ chart_type: line
1185
+ dimensions:
1186
+ - name: input
1187
+ - name: system.hw.sensor.lux
1188
+ description: Ambient light level
1189
+ unit: "lx"
1190
+ chart_type: line
1191
+ dimensions:
1192
+ - name: input
1193
+ - name: system.hw.sensor.state
1194
+ description: Current sensor state.
1195
+ unit: "status"
1196
+ chart_type: line
1197
+ dimensions:
1198
+ - name: ready
1199
+ - name: not_available
1200
+ - name: no_data
1201
+ - name: initializing
1202
+ - name: access_denied
1203
+ - name: error
1204
- meta:
1205
plugin_name: windows.plugin
1206
module_name: PerflibWebService
src/collectors/windows.plugin/windows_plugin.c
+8
@@ -40,6 +40,14 @@ static struct proc_module {
40
.rd = NULL,
41
.thread = NULL,
42
.cleanup = NULL},
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 = "PerflibServices",
52
.dim = "PerflibServices",
53
.enabled = CONFIG_BOOLEAN_YES,
src/collectors/windows.plugin/windows_plugin.h
+5
-1
@@ -25,6 +25,7 @@ int do_GetSystemRAM(int update_every, usec_t dt);
25
int do_GetSystemCPU(int update_every, usec_t dt);
26
int do_GetPowerSupply(int update_every, usec_t dt);
27
int do_GetServicesStatus(int update_every, usec_t dt);
28
+int do_GetSensors(int update_every, usec_t dt);
29
30
// Perflib
31
int do_PerflibStorage(int update_every, usec_t dt);
@@ -36,7 +37,6 @@ int do_PerflibObjects(int update_every, usec_t dt);
37
int do_PerflibThermalZone(int update_every, usec_t dt);
38
int do_PerflibWebService(int update_every, usec_t dt);
39
int do_PerflibMSSQL(int update_every, usec_t dt);
39
-void do_PerflibMSSQL_cleanup();
40
int do_PerflibNetFramework(int update_every, usec_t dt);
41
int do_PerflibAD(int update_every, usec_t dt);
42
int do_PerflibADCS(int update_every, usec_t dt);
@@ -46,6 +46,10 @@ int do_PerflibExchange(int update_every, usec_t dt __maybe_unused);
46
int do_PerflibNUMA(int update_every, usec_t dt __maybe_unused);
47
int do_PerflibASP(int update_every, usec_t dt __maybe_unused);
48
49
+// Cleanup
50
+void do_PerflibMSSQL_cleanup();
51
+void do_Sensors_cleanup();
52
+
53
enum PERFLIB_PRIO {
54
PRIO_WEBSITE_IIS_REQUESTS_RATE = 21000, // PRIO selected, because APPS is using 20YYY
55
PRIO_WEBSITE_IIS_REQUESTS_BY_TYPE_RATE,