]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
smbprofile: Count failed requests
authorVolker Lendecke <vl@samba.org>
Tue, 9 Jan 2024 15:12:20 +0000 (16:12 +0100)
committerGünther Deschner <gd@samba.org>
Fri, 11 Apr 2025 18:46:40 +0000 (18:46 +0000)
Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
Reviewed-by: Guenther Deschner <gd@samba.org>
source3/include/smbprofile.h
source3/profile/profile_read.c
source3/smbd/smb2_server.c
source3/utils/smb_prometheus_endpoint.c
source3/utils/status_profile.c

index 3354770efe72f1d94bf6a55f4ce4f841edcb2c3e..9692ebadef1f88465805fa005e816dfe223ea022 100644 (file)
@@ -24,6 +24,8 @@
 #include "replace.h"
 #include <tdb.h>
 #include "lib/util/time.h"
+#include "libcli/smb/smb2_constants.h"
+#include "libcli/util/ntstatus.h"
 
 struct smbd_server_connection;
 struct tevent_context;
@@ -293,6 +295,7 @@ struct smbprofile_stats_bytes_async {
 
 struct smbprofile_stats_iobytes {
        uint64_t count;         /* number of events */
+       uint64_t failed_count;  /* number of unsuccessful events */
        uint64_t time;          /* microseconds */
        uint64_t buckets[10];   /* 1,2,4,...256,Inf msecs */
        uint64_t idle;          /* idle time compared to 'time' microseconds */
@@ -459,10 +462,11 @@ struct profile_stats {
        _SMBPROFILE_TIMER_ASYNC_SET_IDLE(_async)
 #define SMBPROFILE_IOBYTES_ASYNC_SET_BUSY(_async) \
        _SMBPROFILE_TIMER_ASYNC_SET_BUSY(_async)
-#define SMBPROFILE_IOBYTES_ASYNC_END(_async, _outbytes) do { \
+#define SMBPROFILE_IOBYTES_ASYNC_END(_async, _outbytes, _opcode, _status) do { \
        if ((_async).stats != NULL) { \
                (_async).stats->outbytes += (_outbytes); \
                _SMBPROFILE_TIMER_ASYNC_END(_async); \
+               smbprofile_update_failed_count((_async.stats), (_opcode), (_status)); \
                smbprofile_update_hist((_async).stats, profile_timestamp() - (_async).start); \
                (_async) = (struct smbprofile_stats_iobytes_async) {}; \
                smbprofile_dump_schedule(); \
@@ -513,6 +517,37 @@ static inline bool smbprofile_active(void)
        return smbprofile_state.config.do_count;
 }
 
+static inline void smbprofile_update_failed_count(
+       struct smbprofile_stats_iobytes *s,
+       uint16_t opcode,
+       NTSTATUS status)
+{
+       bool ok = NT_STATUS_IS_OK(status);
+
+       switch (opcode) {
+       case SMB2_OP_SESSSETUP:
+               if (NT_STATUS_EQUAL(status,
+                                   NT_STATUS_MORE_PROCESSING_REQUIRED)) {
+                       ok = true;
+               }
+               break;
+       case SMB2_OP_QUERY_DIRECTORY:
+               if (NT_STATUS_EQUAL(status, NT_STATUS_NO_MORE_FILES)) {
+                       ok = true;
+               }
+               break;
+       case SMB2_OP_NOTIFY:
+               if (NT_STATUS_EQUAL(status, NT_STATUS_CANCELLED)) {
+                       ok = true;
+               }
+               break;
+       }
+
+       if (!ok) {
+               s->failed_count += 1;
+       }
+}
+
 static inline void smbprofile_update_hist(struct smbprofile_stats_iobytes *s,
                                          uint64_t microsecs)
 {
@@ -626,7 +661,7 @@ static inline uint64_t profile_timestamp(void)
 #define SMBPROFILE_IOBYTES_ASYNC_START(_name, _area, _async, _inbytes)
 #define SMBPROFILE_IOBYTES_ASYNC_SET_IDLE(_async)
 #define SMBPROFILE_IOBYTES_ASYNC_SET_BUSY(_async)
-#define SMBPROFILE_IOBYTES_ASYNC_END(_async, _outbytes)
+#define SMBPROFILE_IOBYTES_ASYNC_END(_async, _outbytes, _opcode, _status)
 
 #define DO_PROFILE_INC(x)
 #define START_PROFILE(x)
index 3c4e6ebcfa3541cda22e1167ab6d1667534ad271..c4b99b80e923b96c78d4ab555d7f201656a3a422 100644 (file)
@@ -63,6 +63,8 @@ void smbprofile_stats_accumulate(struct profile_stats *acc,
        do {                                               \
                acc->values.name##_stats.count +=          \
                        add->values.name##_stats.count;    \
+               acc->values.name##_stats.failed_count +=   \
+                       add->values.name##_stats.failed_count; \
                acc->values.name##_stats.time +=           \
                        add->values.name##_stats.time;     \
                acc->values.name##_stats.buckets[0] +=     \
index 59f4a4aad5ba471624d88e1a4406de64e942dda1..5c3b7b90dc91aa1dc7f9bcca0f521be01fd9f5c2 100644 (file)
@@ -3561,7 +3561,10 @@ skipped_signing:
                SMBPROFILE_IOBYTES_ASYNC_START(smb2_cancel, profile_p,
                                               req->profile, _INBYTES(req));
                return_value = smbd_smb2_request_process_cancel(req);
-               SMBPROFILE_IOBYTES_ASYNC_END(req->profile, 0);
+               SMBPROFILE_IOBYTES_ASYNC_END(req->profile,
+                                            0,
+                                            SMB2_OP_CANCEL,
+                                            NT_STATUS_OK);
 
                /*
                 * We don't need the request anymore cancel requests never
@@ -3746,8 +3749,11 @@ static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
        }
        TALLOC_FREE(req->last_sign_key);
 
-       SMBPROFILE_IOBYTES_ASYNC_END(req->profile,
-               iov_buflen(outhdr, SMBD_SMB2_NUM_IOV_PER_REQ-1));
+       SMBPROFILE_IOBYTES_ASYNC_END(
+               req->profile,
+               iov_buflen(outhdr, SMBD_SMB2_NUM_IOV_PER_REQ - 1),
+               PULL_LE_U16(outhdr->iov_base, SMB2_HDR_OPCODE),
+               NT_STATUS(IVAL(outhdr->iov_base, SMB2_HDR_STATUS)));
 
        req->current_idx += SMBD_SMB2_NUM_IOV_PER_REQ;
 
index 2fa1da9c6b2b2b15c5b11f3528a4bdaf5d8cd429..3959a8511cc566c52560d65c2c9a3c672fd262ec 100644 (file)
@@ -28,10 +28,10 @@ struct export_state {
        struct evbuffer *buf;
        bool sent_help_cpu_seconds : 1;
        bool sent_help_smb1_request_total : 1;
-       bool sent_help_smb2_request_total : 1;
        bool sent_help_smb2_request_inbytes : 1;
        bool sent_help_smb2_request_outbytes : 1;
        bool sent_help_smb2_request_hist : 1;
+       bool sent_help_smb2_request_failed : 1;
 };
 
 static void export_count(const char *name,
@@ -202,6 +202,32 @@ static void export_iobytes_buckets(const char *name,
        }
 }
 
+static void export_iobytes_failed(const char *name,
+                                 const struct smbprofile_stats_iobytes *val,
+                                 struct export_state *state)
+{
+       bool is_smb2;
+
+       is_smb2 = (strncmp(name, "smb2_", 5) == 0);
+       if (is_smb2) {
+               if (!state->sent_help_smb2_request_failed) {
+                       evbuffer_add_printf(
+                               state->buf,
+                               "# HELP smb_smb2_request_failed Number "
+                               "of failed SMB2 requests\n"
+                               "# TYPE smb_smb2_request_failed counter\n");
+                       state->sent_help_smb2_request_failed = true;
+               }
+
+               evbuffer_add_printf(
+                       state->buf,
+                       "smb_smb2_request_failed { operation=\"%s\" } "
+                       "%" PRIu64 "\n",
+                       name + 5,
+                       val->failed_count);
+       }
+}
+
 static void metrics_handler(struct evhttp_request *req, void *arg)
 {
        struct export_state state = {.buf = NULL};
@@ -389,6 +415,31 @@ static void metrics_handler(struct evhttp_request *req, void *arg)
 #undef SMBPROFILE_STATS_BYTES
 #undef SMBPROFILE_STATS_IOBYTES
 #undef SMBPROFILE_STATS_SECTION_END
+#undef SMBPROFILE_STATS_END
+
+#define SMBPROFILE_STATS_START
+#define SMBPROFILE_STATS_SECTION_START(name, display)
+#define SMBPROFILE_STATS_COUNT(name)
+#define SMBPROFILE_STATS_TIME(name)
+#define SMBPROFILE_STATS_BASIC(name)
+#define SMBPROFILE_STATS_BYTES(name)
+#define SMBPROFILE_STATS_IOBYTES(name)                            \
+       do {                                                      \
+               export_iobytes_failed(#name,                      \
+                                     &stats.values.name##_stats, \
+                                     &state);                    \
+       } while (0);
+#define SMBPROFILE_STATS_SECTION_END
+#define SMBPROFILE_STATS_END
+       SMBPROFILE_STATS_ALL_SECTIONS
+#undef SMBPROFILE_STATS_START
+#undef SMBPROFILE_STATS_SECTION_START
+#undef SMBPROFILE_STATS_COUNT
+#undef SMBPROFILE_STATS_TIME
+#undef SMBPROFILE_STATS_BASIC
+#undef SMBPROFILE_STATS_BYTES
+#undef SMBPROFILE_STATS_IOBYTES
+#undef SMBPROFILE_STATS_SECTION_END
 #undef SMBPROFILE_STATS_END
 
        evhttp_send_reply(req, HTTP_OK, "OK", state.buf);
index 082bc5cb61eec576a7c751dbbb144c6be93c4b12..299731b48136bed8ccbb1152cc920ad1d4817055 100644 (file)
@@ -125,6 +125,7 @@ bool status_profile_dump(bool verbose,
 } while(0);
 #define SMBPROFILE_STATS_IOBYTES(name) do { \
        __PRINT_FIELD_LINE(#name, name##_stats,  count); \
+       __PRINT_FIELD_LINE(#name, name##_stats,  failed_count); \
        __PRINT_FIELD_LINE(#name, name##_stats,  time); \
        print_buckets(state, #name, &stats.values.name##_stats); \
        __PRINT_FIELD_LINE(#name, name##_stats,  idle); \