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