@cryptotaxi247 / netdata / commits / d3f74d66f

SMB Protocol (Windows.plugin) (#22236)

thiagoftsm committed May 1, 2026 at 13:41 UTC d3f74d66f137014fb8aafd7d49a0c80d808ae4d7
5 files changed +453 -1
CMakeLists.txt
+1
@@ -2068,6 +2068,7 @@ set(WINDOWS_PLUGIN_FILES
2068 src/collectors/windows.plugin/perflib-thermalzone.c
2069 src/collectors/windows.plugin/perflib-objects.c
2070 src/collectors/windows.plugin/perflib-network.c
2071 + src/collectors/windows.plugin/perflib-smb.c
2072 src/collectors/windows.plugin/perflib-netframework.c
2073 src/collectors/windows.plugin/perflib-memory.c
2074 src/collectors/windows.plugin/perflib-processes.c
src/collectors/windows.plugin/metadata.yaml
+128
@@ -879,6 +879,134 @@ modules:
879 chart_type: line
880 dimensions:
881 - name: connections
882 + - meta:
883 + plugin_name: windows.plugin
884 + module_name: PerflibSMB
885 + monitored_instance:
886 + name: SMB Server Shares
887 + link: "https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-smb/"
888 + categories:
889 + - data-collection.storage
890 + icon_filename: "windows.svg"
891 + related_resources:
892 + integrations:
893 + list: []
894 + info_provided_to_referring_integrations:
895 + description: ""
896 + keywords:
897 + - windows
898 + - microsoft
899 + - smb
900 + - share
901 + - file sharing
902 + overview:
903 + data_collection:
904 + metrics_description: |
905 + Monitor SMB server share activity and throughput counters on Windows systems.
906 + method_description: |
907 + It queries the 'SMB Server Shares' object from Perflib in order to gather the metrics.
908 + supported_platforms:
909 + include: ["windows"]
910 + exclude: []
911 + multi_instance: false
912 + additional_permissions:
913 + description: ""
914 + default_behavior:
915 + auto_detection:
916 + description: |
917 + This collector is disabled by default. When enabled, it automatically detects all available SMB share instances and metrics.
918 + limits:
919 + description: ""
920 + performance_impact:
921 + description: ""
922 + setup:
923 + prerequisites:
924 + list: []
925 + configuration:
926 + file:
927 + name: "netdata.conf"
928 + section_name: "[plugin:windows:PerflibSMB]"
929 + description: "The Netdata main configuration file"
930 + options:
931 + description: ""
932 + folding:
933 + title: "Config option"
934 + enabled: false
935 + list:
936 + - name: update every
937 + description: Data collection frequency.
938 + default_value: 1
939 + required: false
940 + examples:
941 + folding:
942 + enabled: true
943 + title: ""
944 + list: []
945 + troubleshooting:
946 + problems:
947 + list: []
948 + alerts: []
949 + metrics:
950 + folding:
951 + title: Metrics
952 + enabled: false
953 + description: ""
954 + availability: []
955 + scopes:
956 + - name: SMB Share
957 + description: "These metrics refer to SMB shares."
958 + labels:
959 + - name: share
960 + description: SMB share name as exposed by the Windows SMB Server Shares performance object.
961 + metrics:
962 + - name: smb.server_shares_current_open_file_count
963 + description: Current total count of open files on the SMB share.
964 + unit: "files"
965 + chart_type: line
966 + dimensions:
967 + - name: open
968 + - name: smb.server_shares_tree_connect_count
969 + description: Count of user connections to the SMB share.
970 + unit: "connections"
971 + chart_type: line
972 + dimensions:
973 + - name: connections
974 + - name: smb.server_shares_received_bytes
975 + description: Received bytes on the SMB share.
976 + unit: "bytes/s"
977 + chart_type: line
978 + dimensions:
979 + - name: received
980 + - name: smb.server_shares_write_requests
981 + description: Write requests on the SMB share.
982 + unit: "requests/s"
983 + chart_type: line
984 + dimensions:
985 + - name: writes
986 + - name: smb.server_shares_read_requests
987 + description: Read requests on the SMB share.
988 + unit: "requests/s"
989 + chart_type: line
990 + dimensions:
991 + - name: reads
992 + - name: smb.server_shares_metadata_requests
993 + description: Metadata requests on the SMB share.
994 + unit: "requests/s"
995 + chart_type: line
996 + dimensions:
997 + - name: metadata
998 + - name: smb.server_shares_sent_bytes
999 + description: Sent bytes on the SMB share.
1000 + unit: "bytes/s"
1001 + chart_type: line
1002 + dimensions:
1003 + - name: sent
1004 + - name: smb.server_shares_files_opened
1005 + description: Files opened on the SMB share.
1006 + unit: "files/s"
1007 + chart_type: line
1008 + dimensions:
1009 + - name: opened
1010 - meta:
1011 plugin_name: windows.plugin
1012 module_name: PerflibObjects
src/collectors/windows.plugin/perflib-smb.c new
+304
@@ -0,0 +1,304 @@
1 +// SPDX-License-Identifier: GPL-3.0-or-later
2 +
3 +#include "windows_plugin.h"
4 +#include "windows-internals.h"
5 +
6 +struct smb_share {
7 + usec_t last_collected;
8 +
9 + RRDSET *st_current_open_file_count;
10 + RRDSET *st_tree_connect_count;
11 + RRDSET *st_received_bytes;
12 + RRDSET *st_write_requests;
13 + RRDSET *st_read_requests;
14 + RRDSET *st_metadata_requests;
15 + RRDSET *st_sent_bytes;
16 + RRDSET *st_files_opened;
17 +
18 + RRDDIM *rd_current_open_file_count;
19 + RRDDIM *rd_tree_connect_count;
20 + RRDDIM *rd_received_bytes;
21 + RRDDIM *rd_write_requests;
22 + RRDDIM *rd_read_requests;
23 + RRDDIM *rd_metadata_requests;
24 + RRDDIM *rd_sent_bytes;
25 + RRDDIM *rd_files_opened;
26 +
27 + COUNTER_DATA currentOpenFileCount;
28 + COUNTER_DATA treeConnectCount;
29 + COUNTER_DATA receivedBytes;
30 + COUNTER_DATA writeRequests;
31 + COUNTER_DATA readRequests;
32 + COUNTER_DATA metadataRequests;
33 + COUNTER_DATA sentBytes;
34 + COUNTER_DATA filesOpened;
35 +};
36 +
37 +static DICTIONARY *smb_shares = NULL;
38 +
39 +static void smb_share_initialize(struct smb_share *share)
40 +{
41 + share->currentOpenFileCount.key = "Current Open File Count";
42 + share->treeConnectCount.key = "Tree Connect Count";
43 + share->receivedBytes.key = "Received Bytes/sec";
44 + share->writeRequests.key = "Write Requests/sec";
45 + share->readRequests.key = "Read Requests/sec";
46 + share->metadataRequests.key = "Metadata Requests/sec";
47 + share->sentBytes.key = "Sent Bytes/sec";
48 + share->filesOpened.key = "Files Opened/sec";
49 +}
50 +
51 +static void smb_share_cleanup(struct smb_share *share)
52 +{
53 + rrdset_is_obsolete___safe_from_collector_thread(share->st_current_open_file_count);
54 + rrdset_is_obsolete___safe_from_collector_thread(share->st_tree_connect_count);
55 + rrdset_is_obsolete___safe_from_collector_thread(share->st_received_bytes);
56 + rrdset_is_obsolete___safe_from_collector_thread(share->st_write_requests);
57 + rrdset_is_obsolete___safe_from_collector_thread(share->st_read_requests);
58 + rrdset_is_obsolete___safe_from_collector_thread(share->st_metadata_requests);
59 + rrdset_is_obsolete___safe_from_collector_thread(share->st_sent_bytes);
60 + rrdset_is_obsolete___safe_from_collector_thread(share->st_files_opened);
61 +}
62 +
63 +static void dict_smb_share_insert_cb(const DICTIONARY_ITEM *item __maybe_unused, void *value, void *data __maybe_unused)
64 +{
65 + struct smb_share *share = value;
66 +
67 + smb_share_initialize(share);
68 +}
69 +
70 +static void dict_smb_share_delete_cb(const DICTIONARY_ITEM *item __maybe_unused, void *value, void *data __maybe_unused)
71 +{
72 + struct smb_share *share = value;
73 +
74 + smb_share_cleanup(share);
75 +}
76 +
77 +static void initialize(void)
78 +{
79 + smb_shares = dictionary_create_advanced(
80 + DICT_OPTION_DONT_OVERWRITE_VALUE | DICT_OPTION_FIXED_SIZE, NULL, sizeof(struct smb_share));
81 +
82 + dictionary_register_insert_callback(smb_shares, dict_smb_share_insert_cb, NULL);
83 + dictionary_register_delete_callback(smb_shares, dict_smb_share_delete_cb, NULL);
84 +}
85 +
86 +static void smb_share_chart(
87 + RRDSET **st,
88 + RRDDIM **rd,
89 + COUNTER_DATA *counter,
90 + int update_every,
91 + const char *share,
92 + const char *id_suffix,
93 + const char *context,
94 + const char *title,
95 + const char *units,
96 + int priority,
97 + const char *dimension)
98 +{
99 + if (!counter->updated)
100 + return;
101 +
102 + if (unlikely(!*st)) {
103 + char id[RRD_ID_LENGTH_MAX + 1];
104 + snprintfz(id, sizeof(id), "smb_share_%s_%s", share, id_suffix);
105 + netdata_fix_chart_name(id);
106 +
107 + *st = rrdset_create_localhost(
108 + "smb",
109 + id,
110 + NULL,
111 + "shares",
112 + context,
113 + title,
114 + units,
115 + PLUGIN_WINDOWS_NAME,
116 + "PerflibSMB",
117 + priority,
118 + update_every,
119 + RRDSET_TYPE_LINE);
120 +
121 + *rd = perflib_rrddim_add(*st, dimension, NULL, 1, 1, counter);
122 + rrdlabels_add((*st)->rrdlabels, "share", share, RRDLABEL_SRC_AUTO);
123 + }
124 +
125 + perflib_rrddim_set_by_pointer(*st, *rd, counter);
126 + rrdset_done(*st);
127 +}
128 +
129 +static bool do_smb_server_shares(PERF_DATA_BLOCK *pDataBlock, int update_every)
130 +{
131 + PERF_OBJECT_TYPE *pObjectType = perflibFindObjectTypeByName(pDataBlock, "SMB Server Shares");
132 + if (!pObjectType)
133 + return false;
134 +
135 + usec_t now_ut = now_monotonic_usec();
136 +
137 + PERF_INSTANCE_DEFINITION *pi = NULL;
138 + for (LONG i = 0; i < pObjectType->NumInstances; i++) {
139 + pi = perflibForEachInstance(pDataBlock, pObjectType, pi);
140 + if (!pi)
141 + break;
142 +
143 + if (!getInstanceName(pDataBlock, pObjectType, pi, windows_shared_buffer, sizeof(windows_shared_buffer)))
144 + strncpyz(windows_shared_buffer, "[unknown]", sizeof(windows_shared_buffer) - 1);
145 +
146 + struct smb_share *share = dictionary_set(smb_shares, windows_shared_buffer, NULL, sizeof(*share));
147 + share->last_collected = now_ut;
148 +
149 + perflibGetInstanceCounter(pDataBlock, pObjectType, pi, &share->currentOpenFileCount);
150 + perflibGetInstanceCounter(pDataBlock, pObjectType, pi, &share->treeConnectCount);
151 + perflibGetInstanceCounter(pDataBlock, pObjectType, pi, &share->receivedBytes);
152 + perflibGetInstanceCounter(pDataBlock, pObjectType, pi, &share->writeRequests);
153 + perflibGetInstanceCounter(pDataBlock, pObjectType, pi, &share->readRequests);
154 + perflibGetInstanceCounter(pDataBlock, pObjectType, pi, &share->metadataRequests);
155 + perflibGetInstanceCounter(pDataBlock, pObjectType, pi, &share->sentBytes);
156 + perflibGetInstanceCounter(pDataBlock, pObjectType, pi, &share->filesOpened);
157 +
158 + smb_share_chart(
159 + &share->st_current_open_file_count,
160 + &share->rd_current_open_file_count,
161 + &share->currentOpenFileCount,
162 + update_every,
163 + windows_shared_buffer,
164 + "current_open_file_count",
165 + "smb.server_shares_current_open_file_count",
166 + "Current open file count on the SMB share",
167 + "files",
168 + PRIO_SMB_SERVER_SHARES_CURRENT_OPEN_FILE_COUNT,
169 + "open");
170 +
171 + smb_share_chart(
172 + &share->st_tree_connect_count,
173 + &share->rd_tree_connect_count,
174 + &share->treeConnectCount,
175 + update_every,
176 + windows_shared_buffer,
177 + "tree_connect_count",
178 + "smb.server_shares_tree_connect_count",
179 + "Tree connect count on the SMB share",
180 + "connections",
181 + PRIO_SMB_SERVER_SHARES_TREE_CONNECT_COUNT,
182 + "connections");
183 +
184 + smb_share_chart(
185 + &share->st_received_bytes,
186 + &share->rd_received_bytes,
187 + &share->receivedBytes,
188 + update_every,
189 + windows_shared_buffer,
190 + "received_bytes",
191 + "smb.server_shares_received_bytes",
192 + "Received bytes on the SMB share",
193 + "bytes/s",
194 + PRIO_SMB_SERVER_SHARES_RECEIVED_BYTES,
195 + "received");
196 +
197 + smb_share_chart(
198 + &share->st_write_requests,
199 + &share->rd_write_requests,
200 + &share->writeRequests,
201 + update_every,
202 + windows_shared_buffer,
203 + "write_requests",
204 + "smb.server_shares_write_requests",
205 + "Write requests on the SMB share",
206 + "requests/s",
207 + PRIO_SMB_SERVER_SHARES_WRITE_REQUESTS,
208 + "writes");
209 +
210 + smb_share_chart(
211 + &share->st_read_requests,
212 + &share->rd_read_requests,
213 + &share->readRequests,
214 + update_every,
215 + windows_shared_buffer,
216 + "read_requests",
217 + "smb.server_shares_read_requests",
218 + "Read requests on the SMB share",
219 + "requests/s",
220 + PRIO_SMB_SERVER_SHARES_READ_REQUESTS,
221 + "reads");
222 +
223 + smb_share_chart(
224 + &share->st_metadata_requests,
225 + &share->rd_metadata_requests,
226 + &share->metadataRequests,
227 + update_every,
228 + windows_shared_buffer,
229 + "metadata_requests",
230 + "smb.server_shares_metadata_requests",
231 + "Metadata requests on the SMB share",
232 + "requests/s",
233 + PRIO_SMB_SERVER_SHARES_METADATA_REQUESTS,
234 + "metadata");
235 +
236 + smb_share_chart(
237 + &share->st_sent_bytes,
238 + &share->rd_sent_bytes,
239 + &share->sentBytes,
240 + update_every,
241 + windows_shared_buffer,
242 + "sent_bytes",
243 + "smb.server_shares_sent_bytes",
244 + "Sent bytes on the SMB share",
245 + "bytes/s",
246 + PRIO_SMB_SERVER_SHARES_SENT_BYTES,
247 + "sent");
248 +
249 + smb_share_chart(
250 + &share->st_files_opened,
251 + &share->rd_files_opened,
252 + &share->filesOpened,
253 + update_every,
254 + windows_shared_buffer,
255 + "files_opened",
256 + "smb.server_shares_files_opened",
257 + "Files opened on the SMB share",
258 + "files/s",
259 + PRIO_SMB_SERVER_SHARES_FILES_OPENED,
260 + "opened");
261 + }
262 +
263 + // delete entries not seen in this collection cycle
264 + {
265 + struct smb_share *share;
266 + dfe_start_write(smb_shares, share)
267 + {
268 + if (share->last_collected < now_ut)
269 + dictionary_del(smb_shares, share_dfe.name);
270 + }
271 + dfe_done(share);
272 + dictionary_garbage_collect(smb_shares);
273 + }
274 +
275 + return true;
276 +}
277 +
278 +void do_PerflibSMB_cleanup(void)
279 +{
280 + dictionary_destroy(smb_shares);
281 + smb_shares = NULL;
282 +}
283 +
284 +int do_PerflibSMB(int update_every, usec_t dt __maybe_unused)
285 +{
286 + static bool initialized = false;
287 +
288 + if (unlikely(!initialized)) {
289 + initialize();
290 + initialized = true;
291 + }
292 +
293 + DWORD id = RegistryFindIDByName("SMB Server Shares");
294 + if (id == PERFLIB_REGISTRY_NAME_NOT_FOUND)
295 + return -1;
296 +
297 + PERF_DATA_BLOCK *pDataBlock = perflibGetPerformanceData(id);
298 + if (!pDataBlock)
299 + return -1;
300 +
301 + do_smb_server_shares(pDataBlock, update_every);
302 +
303 + return 0;
304 +}
src/collectors/windows.plugin/windows_plugin.c
+8
@@ -109,6 +109,14 @@ static struct proc_module {
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,
src/collectors/windows.plugin/windows_plugin.h
+12 -1
@@ -49,6 +49,7 @@ int do_PerflibHyperV(int update_every, usec_t dt);
49 int do_PerflibExchange(int update_every, usec_t dt __maybe_unused);
50 int do_PerflibNUMA(int update_every, usec_t dt __maybe_unused);
51 int do_PerflibASP(int update_every, usec_t dt __maybe_unused);
52 +int do_PerflibSMB(int update_every, usec_t dt __maybe_unused);
53
54 // Cleanup
55 void do_GetHardwareInfo_cleanup();
@@ -56,6 +57,7 @@ void do_Sensors_cleanup();
57 void do_GetServicesStatus_cleanup();
58 void do_GetSystemCPU_cleanup();
59 void do_GetPowerSupply_cleanup();
60 +void do_PerflibSMB_cleanup();
61
62 enum PERFLIB_PRIO {
63 PRIO_WEBSITE_IIS_REQUESTS_RATE = 21000, // PRIO selected, because APPS is using 20YYY
@@ -349,7 +351,16 @@ enum PERFLIB_PRIO {
351 PRIO_ASPNET_MEMBERSHIP_AUTHENTICATION_SUCCESS,
352 PRIO_ASPNET_MEMBERSHIP_AUTHENTICATION_FAILURE,
353 PRIO_ASPNET_FORM_AUTHENTICATION_SUCCESS,
352 - PRIO_ASPNET_FORM_AUTHENTICATION_FAILURE
354 + PRIO_ASPNET_FORM_AUTHENTICATION_FAILURE,
355 +
356 + PRIO_SMB_SERVER_SHARES_CURRENT_OPEN_FILE_COUNT,
357 + PRIO_SMB_SERVER_SHARES_TREE_CONNECT_COUNT,
358 + PRIO_SMB_SERVER_SHARES_RECEIVED_BYTES,
359 + PRIO_SMB_SERVER_SHARES_WRITE_REQUESTS,
360 + PRIO_SMB_SERVER_SHARES_READ_REQUESTS,
361 + PRIO_SMB_SERVER_SHARES_METADATA_REQUESTS,
362 + PRIO_SMB_SERVER_SHARES_SENT_BYTES,
363 + PRIO_SMB_SERVER_SHARES_FILES_OPENED
364 };
365
366 #endif //NETDATA_WINDOWS_PLUGIN_H