@cryptotaxi247 / netdata-1 / commits / 7fe26f677

Windows Services Monitoring (#19990)

* win_services: Add basis to monitor Windows services * win_services: Add Data Type and chart metadata * win_services: Add collection data * win_services: Remove chart after to confirm with documentation and Windows Exporter data is not more available * win_services: Add new chart * win_services: Adjust algorithm avoiding crashes when accessing a dictionary * win_services: Format file and address codacy * win_services: Disable Services by default * win_services: Add documentation giving information about threads not enabled. * win_services: Split update every of all threads * win_services: Add update every description * improve readme wording * enable services by default * win_services: Removing code. This will be reworked with another PR * win_services: Remove text from documentation, while we do not address this properly. * win_services: Return commit removed from rebase * win_services: Return commit removed from rebase (Part II) --------- Co-authored-by: ilyam8 <ilya@netdata.cloud>

thiagoftsm committed Apr 8, 2025 at 17:00 UTC 7fe26f677833b837a2d46ec399ddf9c23c1b5c24
6 files changed +448 -16
CMakeLists.txt
+1
@@ -1928,6 +1928,7 @@ set(WINDOWS_PLUGIN_FILES
1928 src/collectors/windows.plugin/perflib-memory.c
1929 src/collectors/windows.plugin/perflib-processes.c
1930 src/collectors/windows.plugin/perflib-web-service.c
1931 + src/collectors/windows.plugin/perflib-services.c
1932 src/collectors/windows.plugin/perflib-hyperv.c
1933 )
1934
src/collectors/windows.plugin/README.md new
+39
@@ -0,0 +1,39 @@
1 +# Windows.plugin
2 +
3 +This internal plugin is only available for Microsoft Windows operating systems.
4 +
5 +## The Collector
6 +
7 +This plugin primarily collects metrics from Microsoft Windows [Performance Counters](https://learn.microsoft.com/en-us/windows/win32/perfctrs/performance-counters-what-s-new). All detected metrics are automatically displayed without requiring additional configuration.
8 +
9 +## Configuration File
10 +
11 +The Windows plugin doesn't use a separate configuration file. Instead, configure it through Netdata's main configuration file located at:
12 +`C:\Program Files\Netdata\etc\netdata\netdata.conf`.
13 +
14 +### Enabling or Disabling Collection
15 +
16 +By default, all collector threads are enabled except for `PerflibThermalZone` and `PerflibServices`. You can enable these or disable others by modifying options in the `[plugin:windows]` section of the configuration file.
17 +
18 +To change a setting, remove the comment symbol (`#`) from the beginning of the line and set the value to either `yes` or `no`:
19 +
20 +```text
21 +[plugin:windows]
22 + # GetSystemUptime = yes
23 + # GetSystemRAM = yes
24 + # PerflibProcesses = yes
25 + # PerflibProcessor = yes
26 + # PerflibMemory = yes
27 + # PerflibStorage = yes
28 + # PerflibNetwork = yes
29 + # PerflibObjects = yes
30 + # PerflibHyperV = yes
31 + # PerflibThermalZone = no
32 + # PerflibWebService = yes
33 + # PerflibServices = no
34 + # PerflibNetFramework = yes
35 + # PerflibAD = yes
36 + # PerflibADCS = yes
37 + # PerflibADFS = yes
38 +```
39 +
src/collectors/windows.plugin/metadata.yaml
+93
@@ -2738,3 +2738,96 @@ modules:
2738 chart_type: line
2739 dimensions:
2740 - name: success
2741 + - meta:
2742 + plugin_name: windows.plugin
2743 + module_name: PerflibServices
2744 + monitored_instance:
2745 + name: Windows Services
2746 + link: "https://learn.microsoft.com/en-us/dotnet/framework/windows-services/"
2747 + categories:
2748 + - data-collection.windows-systems
2749 + icon_filename: "windows.svg"
2750 + related_resources:
2751 + integrations:
2752 + list: []
2753 + info_provided_to_referring_integrations:
2754 + description: ""
2755 + keywords:
2756 + - windows
2757 + - microsoft
2758 + - services
2759 + most_popular: false
2760 + overview:
2761 + data_collection:
2762 + metrics_description: |
2763 + This collector monitors Windows Services Status and States.
2764 + method_description: |
2765 + It queries Service Management to get the metrics.
2766 + supported_platforms:
2767 + include: ["windows"]
2768 + exclude: []
2769 + multi_instance: false
2770 + additional_permissions:
2771 + description: ""
2772 + default_behavior:
2773 + auto_detection:
2774 + description: |
2775 + The collector automatically detects all of the metrics, no further configuration is required.
2776 + limits:
2777 + description: ""
2778 + performance_impact:
2779 + description: ""
2780 + setup:
2781 + prerequisites:
2782 + list: []
2783 + configuration:
2784 + file:
2785 + name: "netdata.conf"
2786 + section_name: "[plugin:windows]"
2787 + description: "The Netdata main configuration file"
2788 + options:
2789 + description: ""
2790 + folding:
2791 + title: "Config option"
2792 + enabled: false
2793 + list:
2794 + - name: PerflibServices
2795 + description: An option to enable or disable the data collection.
2796 + default_value: yes
2797 + required: false
2798 + examples:
2799 + folding:
2800 + enabled: true
2801 + title: ""
2802 + list: []
2803 + troubleshooting:
2804 + problems:
2805 + list: []
2806 + alerts: []
2807 + metrics:
2808 + folding:
2809 + title: Metrics
2810 + enabled: false
2811 + description: ""
2812 + availability: []
2813 + scopes:
2814 + - name: Windows Service
2815 + description: "These metrics refer to Windows Services."
2816 + labels:
2817 + - name: service
2818 + description: The service name
2819 + metrics:
2820 + - name: windows.service_state
2821 + description: Service state
2822 + unit: state
2823 + chart_type: line
2824 + dimensions:
2825 + - name: running
2826 + - name: stopped
2827 + - name: start_pending
2828 + - name: stop_pending
2829 + - name: continue_pending
2830 + - name: pause_pending
2831 + - name: paused
2832 + - name: unknown
2833 +
src/collectors/windows.plugin/perflib-services.c new
+232
@@ -0,0 +1,232 @@
1 +// SPDX-License-Identifier: GPL-3.0-or-later
2 +
3 +#include "windows_plugin.h"
4 +#include "windows-internals.h"
5 +
6 +// Service data
7 +struct win_service {
8 + char *service_name;
9 +
10 + RRDSET *st_service_state;
11 + RRDDIM *rd_service_state_running;
12 + RRDDIM *rd_service_state_stopped;
13 + RRDDIM *rd_service_state_start_pending;
14 + RRDDIM *rd_service_state_stop_pending;
15 + RRDDIM *rd_service_state_continue_pending;
16 + RRDDIM *rd_service_state_pause_pending;
17 + RRDDIM *rd_service_state_paused;
18 + RRDDIM *rd_service_state_unknown;
19 +
20 + COUNTER_DATA ServiceState;
21 +};
22 +
23 +static DICTIONARY *win_services = NULL;
24 +
25 +void dict_win_service_insert_cb(const DICTIONARY_ITEM *item, void *value, void *data __maybe_unused)
26 +{
27 + struct win_service *ptr = value;
28 + const char *name = dictionary_acquired_item_name((DICTIONARY_ITEM *)item);
29 +
30 + ptr->service_name = strdupz(name);
31 +}
32 +
33 +static void initialize(void)
34 +{
35 + win_services = dictionary_create_advanced(
36 + DICT_OPTION_DONT_OVERWRITE_VALUE | DICT_OPTION_FIXED_SIZE, NULL, sizeof(struct win_service));
37 +
38 + dictionary_register_insert_callback(win_services, dict_win_service_insert_cb, NULL);
39 +}
40 +
41 +static BOOL fill_dictionary_with_content()
42 +{
43 + static PVOID buffer = NULL;
44 + static DWORD bytes_needed = 0;
45 +
46 + LPENUM_SERVICE_STATUS_PROCESS service, services;
47 + DWORD total_services = 0;
48 + SC_HANDLE ndSCMH = OpenSCManager(NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE | SC_MANAGER_CONNECT);
49 + if (!ndSCMH) {
50 + return FALSE;
51 + }
52 +
53 + // Query to obtain overall information
54 + BOOL ret = EnumServicesStatusEx(
55 + ndSCMH,
56 + SC_ENUM_PROCESS_INFO,
57 + SERVICE_WIN32,
58 + SERVICE_STATE_ALL,
59 + (LPBYTE)buffer,
60 + bytes_needed,
61 + (LPDWORD)&bytes_needed,
62 + (LPDWORD)&total_services,
63 + NULL,
64 + NULL);
65 +
66 + if (GetLastError() == ERROR_MORE_DATA) {
67 + if (!buffer)
68 + buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, bytes_needed);
69 + else
70 + buffer = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, buffer, bytes_needed);
71 + }
72 +
73 + if (!buffer) {
74 + ret = FALSE;
75 + goto endServiceCollection;
76 + }
77 +
78 + if (!ret) {
79 + ret = EnumServicesStatusEx(
80 + ndSCMH,
81 + SC_ENUM_PROCESS_INFO,
82 + SERVICE_WIN32,
83 + SERVICE_STATE_ALL,
84 + (LPBYTE)buffer,
85 + bytes_needed,
86 + (LPDWORD)&bytes_needed,
87 + (LPDWORD)&total_services,
88 + NULL,
89 + NULL);
90 +
91 + if (!ret) {
92 + goto endServiceCollection;
93 + }
94 + }
95 +
96 + services = (LPENUM_SERVICE_STATUS_PROCESS)buffer;
97 +
98 + for (ULONG i = 0; i < total_services; i++) {
99 + service = &services[i];
100 + if (!service->lpServiceName || !*service->lpServiceName)
101 + continue;
102 +
103 + struct win_service *p = dictionary_set(win_services, service->lpServiceName, NULL, sizeof(*p));
104 + if (!p)
105 + continue;
106 +
107 + p->ServiceState.current.Data = service->ServiceStatusProcess.dwCurrentState;
108 + }
109 +
110 + ret = TRUE;
111 +
112 +endServiceCollection:
113 +
114 + CloseServiceHandle(ndSCMH);
115 + return ret;
116 +}
117 +
118 +static RRDDIM *win_service_select_dim(struct win_service *p, uint32_t selector)
119 +{
120 + // Values defined according to https://learn.microsoft.com/en-us/windows/win32/api/winsvc/ns-winsvc-service_status
121 + switch (selector) {
122 + case 1:
123 + return p->rd_service_state_stopped;
124 + case 2:
125 + return p->rd_service_state_start_pending;
126 + case 3:
127 + return p->rd_service_state_stop_pending;
128 + case 4:
129 + return p->rd_service_state_running;
130 + case 5:
131 + return p->rd_service_state_continue_pending;
132 + case 6:
133 + return p->rd_service_state_pause_pending;
134 + case 7:
135 + return p->rd_service_state_paused;
136 + case 8:
137 + default:
138 + return p->rd_service_state_unknown;
139 + }
140 +}
141 +
142 +static int
143 +dict_win_services_charts_cb(const DICTIONARY_ITEM *item __maybe_unused, void *value, void *data __maybe_unused)
144 +{
145 + struct win_service *p = value;
146 + int *update_every = data;
147 +
148 + if (!p->st_service_state) {
149 + char id[RRD_ID_LENGTH_MAX + 1];
150 + snprintfz(id, RRD_ID_LENGTH_MAX, "service_%s_state", p->service_name);
151 + netdata_fix_chart_name(id);
152 + p->st_service_state = rrdset_create_localhost(
153 + "service",
154 + id,
155 + NULL,
156 + "service",
157 + "windows.service_state",
158 + "Service state",
159 + "state",
160 + PLUGIN_WINDOWS_NAME,
161 + "PerflibbService",
162 + PRIO_SERVICE_STATE,
163 + *update_every,
164 + RRDSET_TYPE_LINE);
165 +
166 + p->rd_service_state_running = rrddim_add(p->st_service_state, "running", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
167 +
168 + p->rd_service_state_stopped = rrddim_add(p->st_service_state, "stopped", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
169 +
170 + p->rd_service_state_start_pending =
171 + rrddim_add(p->st_service_state, "start_pending", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
172 +
173 + p->rd_service_state_stop_pending =
174 + rrddim_add(p->st_service_state, "stop_pending", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
175 +
176 + p->rd_service_state_continue_pending =
177 + rrddim_add(p->st_service_state, "continue_pending", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
178 +
179 + p->rd_service_state_pause_pending =
180 + rrddim_add(p->st_service_state, "pause_pending", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
181 +
182 + p->rd_service_state_paused = rrddim_add(p->st_service_state, "paused", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
183 +
184 + p->rd_service_state_unknown = rrddim_add(p->st_service_state, "unknown", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
185 +
186 + rrdlabels_add(p->st_service_state->rrdlabels, "service", p->service_name, RRDLABEL_SRC_AUTO);
187 + }
188 +
189 + if (p->st_service_state) {
190 +#define NETDATA_WINDOWS_SERVICE_STATE_TOTAL_STATES (8)
191 + uint32_t current_state = (uint32_t)p->ServiceState.current.Data;
192 + for (uint32_t i = 1; i <= NETDATA_WINDOWS_SERVICE_STATE_TOTAL_STATES; i++) {
193 + RRDDIM *dim = win_service_select_dim(p, i);
194 + if (!dim)
195 + continue;
196 + uint32_t chart_value = (current_state == i) ? 1 : 0;
197 +
198 + rrddim_set_by_pointer(p->st_service_state, dim, (collected_number)chart_value);
199 + }
200 +
201 + rrdset_done(p->st_service_state);
202 + }
203 +}
204 +
205 +int do_PerflibServices(int update_every, usec_t dt __maybe_unused)
206 +{
207 +#define NETDATA_SERVICE_MAX_TRY (5)
208 + static int limit = 0;
209 + static bool initialized = false;
210 +
211 + if (unlikely(!initialized)) {
212 + initialize();
213 + initialized = true;
214 + }
215 +
216 + if (!fill_dictionary_with_content()) {
217 + if (++limit == NETDATA_SERVICE_MAX_TRY) {
218 + nd_log(
219 + NDLS_COLLECTORS,
220 + NDLP_ERR,
221 + "Disabling thread after %u consecutive tries to open Service Management.",
222 + NETDATA_SERVICE_MAX_TRY);
223 + return -1;
224 + }
225 + return 0;
226 + }
227 +
228 + limit = 0;
229 + dictionary_sorted_walkthrough_read(win_services, dict_win_services_charts_cb, &update_every);
230 +
231 + return 0;
232 +}
src/collectors/windows.plugin/windows_plugin.c
+79 -14
@@ -8,45 +8,104 @@ 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 } win_modules[] = {
15
16 // system metrics
16 - {.name = "GetSystemUptime", .dim = "GetSystemUptime", .enabled = CONFIG_BOOLEAN_YES, .func = do_GetSystemUptime},
17 - {.name = "GetSystemRAM", .dim = "GetSystemRAM", .enabled = CONFIG_BOOLEAN_YES, .func = do_GetSystemRAM},
17 + {.name = "GetSystemUptime",
18 + .dim = "GetSystemUptime",
19 + .enabled = CONFIG_BOOLEAN_YES,
20 + .update_every = UPDATE_EVERY_MIN,
21 + .func = do_GetSystemUptime},
22 + {.name = "GetSystemRAM",
23 + .dim = "GetSystemRAM",
24 + .enabled = CONFIG_BOOLEAN_YES,
25 + .update_every = UPDATE_EVERY_MIN,
26 + .func = do_GetSystemRAM},
27
28 // the same is provided by PerflibProcessor, with more detailed analysis
20 - //{.name = "GetSystemCPU", .dim = "GetSystemCPU", .enabled = CONFIG_BOOLEAN_YES, .func = do_GetSystemCPU},
29 + //{.name = "GetSystemCPU", .dim = "GetSystemCPU", .enabled = CONFIG_BOOLEAN_YES,
30 + // .update_every = UPDATE_EVERY_MIN, .func = do_GetSystemCPU},
31
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 - {.name = "PerflibHyperV", .dim = "PerflibHyperV", .enabled = CONFIG_BOOLEAN_YES, .func = do_PerflibHyperV},
32 + {.name = "PerflibProcesses",
33 + .dim = "PerflibProcesses",
34 + .enabled = CONFIG_BOOLEAN_YES,
35 + .update_every = UPDATE_EVERY_MIN,
36 + .func = do_PerflibProcesses},
37 + {.name = "PerflibProcessor",
38 + .dim = "PerflibProcessor",
39 + .enabled = CONFIG_BOOLEAN_YES,
40 + .update_every = UPDATE_EVERY_MIN,
41 + .func = do_PerflibProcessor},
42 + {.name = "PerflibMemory",
43 + .dim = "PerflibMemory",
44 + .enabled = CONFIG_BOOLEAN_YES,
45 + .update_every = UPDATE_EVERY_MIN,
46 + .func = do_PerflibMemory},
47 + {.name = "PerflibStorage",
48 + .dim = "PerflibStorage",
49 + .enabled = CONFIG_BOOLEAN_YES,
50 + .update_every = UPDATE_EVERY_MIN,
51 + .func = do_PerflibStorage},
52 + {.name = "PerflibNetwork",
53 + .dim = "PerflibNetwork",
54 + .enabled = CONFIG_BOOLEAN_YES,
55 + .update_every = UPDATE_EVERY_MIN,
56 + .func = do_PerflibNetwork},
57 + {.name = "PerflibObjects",
58 + .dim = "PerflibObjects",
59 + .enabled = CONFIG_BOOLEAN_YES,
60 + .update_every = UPDATE_EVERY_MIN,
61 + .func = do_PerflibObjects},
62 + {.name = "PerflibHyperV",
63 + .dim = "PerflibHyperV",
64 + .enabled = CONFIG_BOOLEAN_YES,
65 + .update_every = UPDATE_EVERY_MIN,
66 + .func = do_PerflibHyperV},
67
68 {.name = "PerflibThermalZone",
69 .dim = "PerflibThermalZone",
70 .enabled = CONFIG_BOOLEAN_NO,
71 + .update_every = UPDATE_EVERY_MIN,
72 .func = do_PerflibThermalZone},
73
74 {.name = "PerflibWebService",
75 .dim = "PerflibWebService",
76 .enabled = CONFIG_BOOLEAN_YES,
77 + .update_every = UPDATE_EVERY_MIN,
78 .func = do_PerflibWebService},
79 {.name = "PerflibMSSQL", .dim = "PerflibMSSQL", .enabled = CONFIG_BOOLEAN_YES, .func = do_PerflibMSSQL},
80
81 {.name = "PerflibNetFramework",
82 .dim = "PerflibNetFramework",
83 .enabled = CONFIG_BOOLEAN_YES,
84 + .update_every = UPDATE_EVERY_MIN,
85 .func = do_PerflibNetFramework},
45 - {.name = "PerflibAD", .dim = "PerflibAD", .enabled = CONFIG_BOOLEAN_YES, .func = do_PerflibAD},
86 + {.name = "PerflibAD",
87 + .dim = "PerflibAD",
88 + .enabled = CONFIG_BOOLEAN_YES,
89 + .update_every = UPDATE_EVERY_MIN,
90 + .func = do_PerflibAD},
91 +
92 + {.name = "PerflibADCS",
93 + .dim = "PerflibADCS",
94 + .enabled = CONFIG_BOOLEAN_YES,
95 + .update_every = UPDATE_EVERY_MIN,
96 + .func = do_PerflibADCS},
97
47 - {.name = "PerflibADCS", .dim = "PerflibADCS", .enabled = CONFIG_BOOLEAN_YES, .func = do_PerflibADCS},
98 + {.name = "PerflibADFS",
99 + .dim = "PerflibADFS",
100 + .enabled = CONFIG_BOOLEAN_YES,
101 + .update_every = UPDATE_EVERY_MIN,
102 + .func = do_PerflibADFS},
103
49 - {.name = "PerflibADFS", .dim = "PerflibADFS", .enabled = CONFIG_BOOLEAN_YES, .func = do_PerflibADFS},
104 + {.name = "PerflibServices",
105 + .dim = "PerflibServices",
106 + .enabled = CONFIG_BOOLEAN_NO,
107 + .update_every = 30 * UPDATE_EVERY_MIN,
108 + .func = do_PerflibServices},
109
110 // the terminator of this array
111 {.name = NULL, .dim = NULL, .func = NULL}};
@@ -86,12 +145,18 @@ void *win_plugin_main(void *ptr)
145
146 // check the enabled status for each module
147 int i;
148 + char buf[CONFIG_MAX_NAME + 1];
149 for (i = 0; win_modules[i].name; i++) {
150 struct proc_module *pm = &win_modules[i];
151
152 + snprintfz(buf, CONFIG_MAX_NAME, "plugin:windows:%s", pm->name);
153 +
154 pm->enabled = inicfg_get_boolean(&netdata_config, "plugin:windows", pm->name, pm->enabled);
155 pm->rd = NULL;
156
157 + pm->update_every =
158 + (int)inicfg_get_duration_seconds(&netdata_config, buf, "update every", localhost->rrd_update_every);
159 +
160 worker_register_job_name(i, win_modules[i].dim);
161 }
162
@@ -125,7 +190,7 @@ void *win_plugin_main(void *ptr)
190
191 worker_is_busy(i);
192 lgs[LGS_MODULE_ID] = ND_LOG_FIELD_CB(NDF_MODULE, log_windows_module, pm);
128 - pm->enabled = !pm->func(localhost->rrd_update_every, hb_dt);
193 + pm->enabled = !pm->func(pm->update_every, hb_dt);
194 lgs[LGS_MODULE_ID] = ND_LOG_FIELD_TXT(NDF_MODULE, PLUGIN_WINDOWS_NAME);
195 }
196 }
src/collectors/windows.plugin/windows_plugin.h
+4 -2
@@ -31,6 +31,8 @@ int do_PerflibNetFramework(int update_every, usec_t dt);
31 int do_PerflibAD(int update_every, usec_t dt);
32 int do_PerflibADCS(int update_every, usec_t dt);
33 int do_PerflibADFS(int update_every, usec_t dt);
34 +int do_PerflibHyperV(int update_every, usec_t dt);
35 +int do_PerflibServices(int update_every, usec_t dt);
36
37 enum PERFLIB_PRIO {
38 PRIO_WEBSITE_IIS_REQUESTS_RATE = 21000, // PRIO selected, because APPS is using 20YYY
@@ -132,6 +134,8 @@ enum PERFLIB_PRIO {
134 PRIO_NETFRAMEWORK_CLR_LOCKS_AND_THREADS_RECOGNIZED_THREADS,
135 PRIO_NETFRAMEWORK_CLR_LOCKS_AND_THREADS_CONTENTIONS,
136
137 + PRIO_SERVICE_STATE,
138 +
139 PRIO_AD_OPERATIONS_TOTAL,
140 PRIO_AD_DIROPERATIONS_TOTAL,
141 PRIO_AD_CACHE_LOOKUP_TOTAL,
@@ -194,6 +198,4 @@ enum PERFLIB_PRIO {
198 PRIO_ADFS_WSFED_TOKEN_REQUESTS
199 };
200
197 -int do_PerflibHyperV(int update_every, usec_t dt);
198 -
201 #endif //NETDATA_WINDOWS_PLUGIN_H