]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: stats: Be able to access a specific field into a stats module
authorChristopher Faulet <cfaulet@haproxy.com>
Mon, 29 Jan 2024 15:35:19 +0000 (16:35 +0100)
committerChristopher Faulet <cfaulet@haproxy.com>
Thu, 1 Feb 2024 11:00:53 +0000 (12:00 +0100)
It is now possible to selectively retrieve extra counters from stats
modules. H1, H2, QUIC and H3 fill_stats() callback functions are updated to
return a specific counter.

include/haproxy/stats-t.h
src/h3_stats.c
src/mux_h1.c
src/mux_h2.c
src/quic_stats.c
src/resolvers.c
src/ssl_sock.c
src/stats.c

index 34a4cc256aca0d42ca96257397bf7c7ffa832673..d3abf9ca2f2e0af468fb250c7d81ea20fe370b4a 100644 (file)
@@ -511,7 +511,7 @@ struct stats_module {
        const char *name;
 
        /* functor used to generate the stats module using counters provided through data parameter */
-       void (*fill_stats)(void *data, struct field *);
+       int (*fill_stats)(void *data, struct field *, unsigned int *);
 
        struct name_desc *stats; /* name/description of stats provided by the module */
        void *counters;          /* initial values of allocated counters */
index c96093f2c3017b096d3f1be4963f5691a6f4c5f3..830aa88a3acea1db6e77f6d95f81dbaecbf458a6 100644 (file)
@@ -128,40 +128,114 @@ static struct h3_counters {
        long long qpack_decoder_stream_error; /* total number of QPACK_DECODER_STREAM_ERROR errors received */
 } h3_counters;
 
-static void h3_fill_stats(void *data, struct field *stats)
+static int h3_fill_stats(void *data, struct field *stats, unsigned int *selected_field)
 {
        struct h3_counters *counters = data;
+       unsigned int current_field = (selected_field != NULL ? *selected_field : 0);
 
-       /* h3 frame type counters */
-       stats[H3_ST_DATA]         = mkf_u64(FN_COUNTER, counters->h3_data);
-       stats[H3_ST_HEADERS]      = mkf_u64(FN_COUNTER, counters->h3_headers);
-       stats[H3_ST_CANCEL_PUSH]  = mkf_u64(FN_COUNTER, counters->h3_cancel_push);
-       stats[H3_ST_PUSH_PROMISE] = mkf_u64(FN_COUNTER, counters->h3_push_promise);
-       stats[H3_ST_MAX_PUSH_ID]  = mkf_u64(FN_COUNTER, counters->h3_max_push_id);
-       stats[H3_ST_GOAWAY]       = mkf_u64(FN_COUNTER, counters->h3_goaway);
-       stats[H3_ST_SETTINGS]     = mkf_u64(FN_COUNTER, counters->h3_settings);
-       /* h3 error counters */
-       stats[H3_ST_H3_NO_ERROR]               = mkf_u64(FN_COUNTER, counters->h3_no_error);
-       stats[H3_ST_H3_GENERAL_PROTOCOL_ERROR] = mkf_u64(FN_COUNTER, counters->h3_general_protocol_error);
-       stats[H3_ST_H3_INTERNAL_ERROR]         = mkf_u64(FN_COUNTER, counters->h3_internal_error);
-       stats[H3_ST_H3_STREAM_CREATION_ERROR]  = mkf_u64(FN_COUNTER, counters->h3_stream_creation_error);
-       stats[H3_ST_H3_CLOSED_CRITICAL_STREAM] = mkf_u64(FN_COUNTER, counters->h3_closed_critical_stream);
-       stats[H3_ST_H3_FRAME_UNEXPECTED]       = mkf_u64(FN_COUNTER, counters->h3_frame_unexpected);
-       stats[H3_ST_H3_FRAME_ERROR]            = mkf_u64(FN_COUNTER, counters->h3_frame_error);
-       stats[H3_ST_H3_EXCESSIVE_LOAD]         = mkf_u64(FN_COUNTER, counters->h3_excessive_load);
-       stats[H3_ST_H3_ID_ERROR]               = mkf_u64(FN_COUNTER, counters->h3_id_error);
-       stats[H3_ST_H3_SETTINGS_ERROR]         = mkf_u64(FN_COUNTER, counters->h3_settings_error);
-       stats[H3_ST_H3_MISSING_SETTINGS]       = mkf_u64(FN_COUNTER, counters->h3_missing_settings);
-       stats[H3_ST_H3_REQUEST_REJECTED]       = mkf_u64(FN_COUNTER, counters->h3_request_rejected);
-       stats[H3_ST_H3_REQUEST_CANCELLED]      = mkf_u64(FN_COUNTER, counters->h3_request_cancelled);
-       stats[H3_ST_H3_REQUEST_INCOMPLETE]     = mkf_u64(FN_COUNTER, counters->h3_request_incomplete);
-       stats[H3_ST_H3_MESSAGE_ERROR]          = mkf_u64(FN_COUNTER, counters->h3_message_error);
-       stats[H3_ST_H3_CONNECT_ERROR]          = mkf_u64(FN_COUNTER, counters->h3_connect_error);
-       stats[H3_ST_H3_VERSION_FALLBACK]       = mkf_u64(FN_COUNTER, counters->h3_version_fallback);
-       /* QPACK error counters */
-       stats[H3_ST_QPACK_DECOMPRESSION_FAILED] = mkf_u64(FN_COUNTER, counters->qpack_decompression_failed);
-       stats[H3_ST_QPACK_ENCODER_STREAM_ERROR] = mkf_u64(FN_COUNTER, counters->qpack_encoder_stream_error);
-       stats[H3_ST_QPACK_DECODER_STREAM_ERROR] = mkf_u64(FN_COUNTER, counters->qpack_decoder_stream_error);
+       for (; current_field < H3_STATS_COUNT; current_field++) {
+               struct field metric = { 0 };
+
+               switch (current_field) {
+               /* h3 frame type counters */
+               case H3_ST_DATA:
+                       metric = mkf_u64(FN_COUNTER, counters->h3_data);
+                       break;
+               case H3_ST_HEADERS:
+                       metric = mkf_u64(FN_COUNTER, counters->h3_headers);
+                       break;
+               case H3_ST_CANCEL_PUSH:
+                       metric = mkf_u64(FN_COUNTER, counters->h3_cancel_push);
+                       break;
+               case H3_ST_PUSH_PROMISE:
+                       metric = mkf_u64(FN_COUNTER, counters->h3_push_promise);
+                       break;
+               case H3_ST_MAX_PUSH_ID:
+                       metric = mkf_u64(FN_COUNTER, counters->h3_max_push_id);
+                       break;
+               case H3_ST_GOAWAY:
+                       metric = mkf_u64(FN_COUNTER, counters->h3_goaway);
+                       break;
+               case H3_ST_SETTINGS:
+                       metric = mkf_u64(FN_COUNTER, counters->h3_settings);
+                       break;
+
+               /* h3 error counters */
+               case H3_ST_H3_NO_ERROR:
+                       metric = mkf_u64(FN_COUNTER, counters->h3_no_error);
+                       break;
+               case H3_ST_H3_GENERAL_PROTOCOL_ERROR:
+                       metric = mkf_u64(FN_COUNTER, counters->h3_general_protocol_error);
+                       break;
+               case H3_ST_H3_INTERNAL_ERROR:
+                       metric = mkf_u64(FN_COUNTER, counters->h3_internal_error);
+                       break;
+               case H3_ST_H3_STREAM_CREATION_ERROR:
+                       metric = mkf_u64(FN_COUNTER, counters->h3_stream_creation_error);
+                       break;
+               case H3_ST_H3_CLOSED_CRITICAL_STREAM:
+                       metric = mkf_u64(FN_COUNTER, counters->h3_closed_critical_stream);
+                       break;
+               case H3_ST_H3_FRAME_UNEXPECTED:
+                       metric = mkf_u64(FN_COUNTER, counters->h3_frame_unexpected);
+                       break;
+               case H3_ST_H3_FRAME_ERROR:
+                       metric = mkf_u64(FN_COUNTER, counters->h3_frame_error);
+                       break;
+               case H3_ST_H3_EXCESSIVE_LOAD:
+                       metric = mkf_u64(FN_COUNTER, counters->h3_excessive_load);
+                       break;
+               case H3_ST_H3_ID_ERROR:
+                       metric = mkf_u64(FN_COUNTER, counters->h3_id_error);
+                       break;
+               case H3_ST_H3_SETTINGS_ERROR:
+                       metric = mkf_u64(FN_COUNTER, counters->h3_settings_error);
+                       break;
+               case H3_ST_H3_MISSING_SETTINGS:
+                       metric = mkf_u64(FN_COUNTER, counters->h3_missing_settings);
+                       break;
+               case H3_ST_H3_REQUEST_REJECTED:
+                       metric = mkf_u64(FN_COUNTER, counters->h3_request_rejected);
+                       break;
+               case H3_ST_H3_REQUEST_CANCELLED:
+                       metric = mkf_u64(FN_COUNTER, counters->h3_request_cancelled);
+                       break;
+               case H3_ST_H3_REQUEST_INCOMPLETE:
+                       metric = mkf_u64(FN_COUNTER, counters->h3_request_incomplete);
+                       break;
+               case H3_ST_H3_MESSAGE_ERROR:
+                       metric = mkf_u64(FN_COUNTER, counters->h3_message_error);
+                       break;
+               case H3_ST_H3_CONNECT_ERROR:
+                       metric = mkf_u64(FN_COUNTER, counters->h3_connect_error);
+                       break;
+               case H3_ST_H3_VERSION_FALLBACK:
+                       metric = mkf_u64(FN_COUNTER, counters->h3_version_fallback);
+                       break;
+
+               /* QPACK error counters */
+               case H3_ST_QPACK_DECOMPRESSION_FAILED:
+                       metric = mkf_u64(FN_COUNTER, counters->qpack_decompression_failed);
+                       break;
+               case H3_ST_QPACK_ENCODER_STREAM_ERROR:
+                       metric = mkf_u64(FN_COUNTER, counters->qpack_encoder_stream_error);
+                       break;
+               case H3_ST_QPACK_DECODER_STREAM_ERROR:
+                       metric = mkf_u64(FN_COUNTER, counters->qpack_decoder_stream_error);
+                       break;
+               default:
+                       /* not used for frontends. If a specific metric
+                        * is requested, return an error. Otherwise continue.
+                        */
+                       if (selected_field != NULL)
+                               return 0;
+                       continue;
+               }
+               stats[current_field] = metric;
+               if (selected_field != NULL)
+                       break;
+       }
+       return 1;
 }
 
 struct stats_module h3_stats_module = {
index c324c2fb967e33eb8dd6163ca698ced65880a9e6..b810ca6251bb7573cf1c8fe519e43e657f12ba62 100644 (file)
@@ -264,21 +264,54 @@ static struct h1_counters {
 #endif
 } h1_counters;
 
-static void h1_fill_stats(void *data, struct field *stats)
+static int h1_fill_stats(void *data, struct field *stats, unsigned int *selected_field)
 {
        struct h1_counters *counters = data;
+       unsigned int current_field = (selected_field != NULL ? *selected_field : 0);
 
-       stats[H1_ST_OPEN_CONN]        = mkf_u64(FN_GAUGE,   counters->open_conns);
-       stats[H1_ST_OPEN_STREAM]      = mkf_u64(FN_GAUGE,   counters->open_streams);
-       stats[H1_ST_TOTAL_CONN]       = mkf_u64(FN_COUNTER, counters->total_conns);
-       stats[H1_ST_TOTAL_STREAM]     = mkf_u64(FN_COUNTER, counters->total_streams);
+       for (; current_field < H1_STATS_COUNT; current_field++) {
+               struct field metric = { 0 };
 
-       stats[H1_ST_BYTES_IN]          = mkf_u64(FN_COUNTER, counters->bytes_in);
-       stats[H1_ST_BYTES_OUT]         = mkf_u64(FN_COUNTER, counters->bytes_out);
+               switch (current_field) {
+               case H1_ST_OPEN_CONN:
+                       metric = mkf_u64(FN_GAUGE,   counters->open_conns);
+                       break;
+               case H1_ST_OPEN_STREAM:
+                       metric = mkf_u64(FN_GAUGE,   counters->open_streams);
+                       break;
+               case H1_ST_TOTAL_CONN:
+                       metric = mkf_u64(FN_COUNTER, counters->total_conns);
+                       break;
+               case H1_ST_TOTAL_STREAM:
+                       metric = mkf_u64(FN_COUNTER, counters->total_streams);
+                       break;
+               case H1_ST_BYTES_IN:
+                       metric = mkf_u64(FN_COUNTER, counters->bytes_in);
+                       break;
+               case H1_ST_BYTES_OUT:
+                       metric = mkf_u64(FN_COUNTER, counters->bytes_out);
+                       break;
 #if defined(USE_LINUX_SPLICE)
-       stats[H1_ST_SPLICED_BYTES_IN]  = mkf_u64(FN_COUNTER, counters->spliced_bytes_in);
-       stats[H1_ST_SPLICED_BYTES_OUT] = mkf_u64(FN_COUNTER, counters->spliced_bytes_out);
+               case H1_ST_SPLICED_BYTES_IN:
+                       metric = mkf_u64(FN_COUNTER, counters->spliced_bytes_in);
+                       break;
+               case H1_ST_SPLICED_BYTES_OUT:
+                       metric = mkf_u64(FN_COUNTER, counters->spliced_bytes_out);
+                       break;
 #endif
+               default:
+                       /* not used for frontends. If a specific metric
+                        * is requested, return an error. Otherwise continue.
+                        */
+                       if (selected_field != NULL)
+                               return 0;
+                       continue;
+               }
+               stats[current_field] = metric;
+               if (selected_field != NULL)
+                       break;
+       }
+       return 1;
 }
 
 static struct stats_module h1_stats_module = {
index a38d75b901efb062d8645fde74db4ea3a70981be..bb1cbb87ed458a7ff17de151900182325d13b9e1 100644 (file)
@@ -355,25 +355,67 @@ static struct h2_counters {
        long long total_streams; /* total number of streams */
 } h2_counters;
 
-static void h2_fill_stats(void *data, struct field *stats)
+static int h2_fill_stats(void *data, struct field *stats, unsigned int *selected_field)
 {
        struct h2_counters *counters = data;
+       unsigned int current_field = (selected_field != NULL ? *selected_field : 0);
 
-       stats[H2_ST_HEADERS_RCVD]    = mkf_u64(FN_COUNTER, counters->headers_rcvd);
-       stats[H2_ST_DATA_RCVD]       = mkf_u64(FN_COUNTER, counters->data_rcvd);
-       stats[H2_ST_SETTINGS_RCVD]   = mkf_u64(FN_COUNTER, counters->settings_rcvd);
-       stats[H2_ST_RST_STREAM_RCVD] = mkf_u64(FN_COUNTER, counters->rst_stream_rcvd);
-       stats[H2_ST_GOAWAY_RCVD]     = mkf_u64(FN_COUNTER, counters->goaway_rcvd);
-
-       stats[H2_ST_CONN_PROTO_ERR]  = mkf_u64(FN_COUNTER, counters->conn_proto_err);
-       stats[H2_ST_STRM_PROTO_ERR]  = mkf_u64(FN_COUNTER, counters->strm_proto_err);
-       stats[H2_ST_RST_STREAM_RESP] = mkf_u64(FN_COUNTER, counters->rst_stream_resp);
-       stats[H2_ST_GOAWAY_RESP]     = mkf_u64(FN_COUNTER, counters->goaway_resp);
-
-       stats[H2_ST_OPEN_CONN]    = mkf_u64(FN_GAUGE,   counters->open_conns);
-       stats[H2_ST_OPEN_STREAM]  = mkf_u64(FN_GAUGE,   counters->open_streams);
-       stats[H2_ST_TOTAL_CONN]   = mkf_u64(FN_COUNTER, counters->total_conns);
-       stats[H2_ST_TOTAL_STREAM] = mkf_u64(FN_COUNTER, counters->total_streams);
+       for (; current_field < H2_STATS_COUNT; current_field++) {
+               struct field metric = { 0 };
+
+               switch (current_field) {
+               case H2_ST_HEADERS_RCVD:
+                       metric = mkf_u64(FN_COUNTER, counters->headers_rcvd);
+                       break;
+               case H2_ST_DATA_RCVD:
+                       metric = mkf_u64(FN_COUNTER, counters->data_rcvd);
+                       break;
+               case H2_ST_SETTINGS_RCVD:
+                       metric = mkf_u64(FN_COUNTER, counters->settings_rcvd);
+                       break;
+               case H2_ST_RST_STREAM_RCVD:
+                       metric = mkf_u64(FN_COUNTER, counters->rst_stream_rcvd);
+                       break;
+               case H2_ST_GOAWAY_RCVD:
+                       metric = mkf_u64(FN_COUNTER, counters->goaway_rcvd);
+                       break;
+               case H2_ST_CONN_PROTO_ERR:
+                       metric = mkf_u64(FN_COUNTER, counters->conn_proto_err);
+                       break;
+               case H2_ST_STRM_PROTO_ERR:
+                       metric = mkf_u64(FN_COUNTER, counters->strm_proto_err);
+                       break;
+               case H2_ST_RST_STREAM_RESP:
+                       metric = mkf_u64(FN_COUNTER, counters->rst_stream_resp);
+                       break;
+               case H2_ST_GOAWAY_RESP:
+                       metric = mkf_u64(FN_COUNTER, counters->goaway_resp);
+                       break;
+               case H2_ST_OPEN_CONN:
+                       metric = mkf_u64(FN_GAUGE,   counters->open_conns);
+                       break;
+               case H2_ST_OPEN_STREAM:
+                       metric = mkf_u64(FN_GAUGE,   counters->open_streams);
+                       break;
+               case H2_ST_TOTAL_CONN:
+                       metric = mkf_u64(FN_COUNTER, counters->total_conns);
+                       break;
+               case H2_ST_TOTAL_STREAM:
+                       metric = mkf_u64(FN_COUNTER, counters->total_streams);
+                       break;
+               default:
+                       /* not used for frontends. If a specific metric
+                        * is requested, return an error. Otherwise continue.
+                        */
+                       if (selected_field != NULL)
+                               return 0;
+                       continue;
+               }
+               stats[current_field] = metric;
+               if (selected_field != NULL)
+                       break;
+       }
+       return 1;
 }
 
 static struct stats_module h2_stats_module = {
index 3657f308c461daee3e701ae71013d84a7545718e..80887c4fefec64e0b421a9e6bfbfb38da9409dba 100644 (file)
@@ -90,53 +90,154 @@ static struct name_desc quic_stats[] = {
 
 struct quic_counters quic_counters;
 
-static void quic_fill_stats(void *data, struct field *stats)
+static int quic_fill_stats(void *data, struct field *stats, unsigned int *selected_field)
 {
        struct quic_counters *counters = data;
+       unsigned int current_field = (selected_field != NULL ? *selected_field : 0);
 
-       stats[QUIC_ST_RXBUF_FULL]        = mkf_u64(FN_COUNTER, counters->rxbuf_full);
-       stats[QUIC_ST_DROPPED_PACKET]    = mkf_u64(FN_COUNTER, counters->dropped_pkt);
-       stats[QUIC_ST_DROPPED_PACKET_BUFOVERRUN] = mkf_u64(FN_COUNTER, counters->dropped_pkt_bufoverrun);
-       stats[QUIC_ST_DROPPED_PARSING]   = mkf_u64(FN_COUNTER, counters->dropped_parsing);
-       stats[QUIC_ST_SOCKET_FULL]       = mkf_u64(FN_COUNTER, counters->socket_full);
-       stats[QUIC_ST_SENDTO_ERR]        = mkf_u64(FN_COUNTER, counters->sendto_err);
-       stats[QUIC_ST_SENDTO_ERR_UNKNWN] = mkf_u64(FN_COUNTER, counters->sendto_err_unknown);
-       stats[QUIC_ST_SENT_PACKET]       = mkf_u64(FN_COUNTER, counters->sent_pkt);
-       stats[QUIC_ST_LOST_PACKET]       = mkf_u64(FN_COUNTER, counters->lost_pkt);
-       stats[QUIC_ST_TOO_SHORT_INITIAL_DGRAM] = mkf_u64(FN_COUNTER, counters->too_short_initial_dgram);
-       stats[QUIC_ST_RETRY_SENT]        = mkf_u64(FN_COUNTER, counters->retry_sent);
-       stats[QUIC_ST_RETRY_VALIDATED]   = mkf_u64(FN_COUNTER, counters->retry_validated);
-       stats[QUIC_ST_RETRY_ERRORS]      = mkf_u64(FN_COUNTER, counters->retry_error);
-       stats[QUIC_ST_HALF_OPEN_CONN]    = mkf_u64(FN_GAUGE, counters->half_open_conn);
-       stats[QUIC_ST_HDSHK_FAIL]        = mkf_u64(FN_COUNTER, counters->hdshk_fail);
-       stats[QUIC_ST_STATELESS_RESET_SENT] = mkf_u64(FN_COUNTER, counters->stateless_reset_sent);
-       /* Special events of interest */
-       stats[QUIC_ST_CONN_MIGRATION_DONE] = mkf_u64(FN_COUNTER, counters->conn_migration_done);
-       /* Transport errors */
-       stats[QUIC_ST_TRANSP_ERR_NO_ERROR]           = mkf_u64(FN_COUNTER, counters->quic_transp_err_no_error);
-       stats[QUIC_ST_TRANSP_ERR_INTERNAL_ERROR]     = mkf_u64(FN_COUNTER, counters->quic_transp_err_internal_error);
-       stats[QUIC_ST_TRANSP_ERR_CONNECTION_REFUSED] = mkf_u64(FN_COUNTER, counters->quic_transp_err_connection_refused);
-       stats[QUIC_ST_TRANSP_ERR_FLOW_CONTROL_ERROR] = mkf_u64(FN_COUNTER, counters->quic_transp_err_flow_control_error);
-       stats[QUIC_ST_TRANSP_ERR_STREAM_LIMIT_ERROR] = mkf_u64(FN_COUNTER, counters->quic_transp_err_stream_limit_error);
-       stats[QUIC_ST_TRANSP_ERR_STREAM_STATE_ERROR] = mkf_u64(FN_COUNTER, counters->quic_transp_err_stream_state_error);
-       stats[QUIC_ST_TRANSP_ERR_FINAL_SIZE_ERROR]   = mkf_u64(FN_COUNTER, counters->quic_transp_err_final_size_error);
-       stats[QUIC_ST_TRANSP_ERR_FRAME_ENCODING_ERROR]      = mkf_u64(FN_COUNTER, counters->quic_transp_err_frame_encoding_error);
-       stats[QUIC_ST_TRANSP_ERR_TRANSPORT_PARAMETER_ERROR] = mkf_u64(FN_COUNTER, counters->quic_transp_err_transport_parameter_error);
-       stats[QUIC_ST_TRANSP_ERR_CONNECTION_ID_LIMIT_ERROR] = mkf_u64(FN_COUNTER, counters->quic_transp_err_connection_id_limit);
-       stats[QUIC_ST_TRANSP_ERR_PROTOCOL_VIOLATION]     = mkf_u64(FN_COUNTER, counters->quic_transp_err_protocol_violation);
-       stats[QUIC_ST_TRANSP_ERR_INVALID_TOKEN]          = mkf_u64(FN_COUNTER, counters->quic_transp_err_invalid_token);
-       stats[QUIC_ST_TRANSP_ERR_APPLICATION_ERROR]      = mkf_u64(FN_COUNTER, counters->quic_transp_err_application_error);
-       stats[QUIC_ST_TRANSP_ERR_CRYPTO_BUFFER_EXCEEDED] = mkf_u64(FN_COUNTER, counters->quic_transp_err_crypto_buffer_exceeded);
-       stats[QUIC_ST_TRANSP_ERR_KEY_UPDATE_ERROR]       = mkf_u64(FN_COUNTER, counters->quic_transp_err_key_update_error);
-       stats[QUIC_ST_TRANSP_ERR_AEAD_LIMIT_REACHED]     = mkf_u64(FN_COUNTER, counters->quic_transp_err_aead_limit_reached);
-       stats[QUIC_ST_TRANSP_ERR_NO_VIABLE_PATH]         = mkf_u64(FN_COUNTER, counters->quic_transp_err_no_viable_path);
-       stats[QUIC_ST_TRANSP_ERR_CRYPTO_ERROR]           = mkf_u64(FN_COUNTER, counters->quic_transp_err_crypto_error);
-       stats[QUIC_ST_TRANSP_ERR_UNKNOWN_ERROR]          = mkf_u64(FN_COUNTER, counters->quic_transp_err_unknown_error);
-       /* Streams related counters */
-       stats[QUIC_ST_DATA_BLOCKED]              = mkf_u64(FN_COUNTER, counters->data_blocked);
-       stats[QUIC_ST_STREAM_DATA_BLOCKED]       = mkf_u64(FN_COUNTER, counters->stream_data_blocked);
-       stats[QUIC_ST_STREAMS_BLOCKED_BIDI]      = mkf_u64(FN_COUNTER, counters->streams_blocked_bidi);
-       stats[QUIC_ST_STREAMS_BLOCKED_UNI]       = mkf_u64(FN_COUNTER, counters->streams_blocked_uni);
+       for (; current_field < QUIC_STATS_COUNT; current_field++) {
+               struct field metric = { 0 };
+
+               switch (current_field) {
+               case QUIC_ST_RXBUF_FULL:
+                       metric = mkf_u64(FN_COUNTER, counters->rxbuf_full);
+                       break;
+               case QUIC_ST_DROPPED_PACKET:
+                       metric = mkf_u64(FN_COUNTER, counters->dropped_pkt);
+                       break;
+               case QUIC_ST_DROPPED_PACKET_BUFOVERRUN:
+                       metric = mkf_u64(FN_COUNTER, counters->dropped_pkt_bufoverrun);
+                       break;
+               case QUIC_ST_DROPPED_PARSING:
+                       metric = mkf_u64(FN_COUNTER, counters->dropped_parsing);
+                       break;
+               case QUIC_ST_SOCKET_FULL:
+                       metric = mkf_u64(FN_COUNTER, counters->socket_full);
+                       break;
+               case QUIC_ST_SENDTO_ERR:
+                       metric = mkf_u64(FN_COUNTER, counters->sendto_err);
+                       break;
+               case QUIC_ST_SENDTO_ERR_UNKNWN:
+                       metric = mkf_u64(FN_COUNTER, counters->sendto_err_unknown);
+                       break;
+               case QUIC_ST_SENT_PACKET:
+                       metric = mkf_u64(FN_COUNTER, counters->sent_pkt);
+                       break;
+               case QUIC_ST_LOST_PACKET:
+                       metric = mkf_u64(FN_COUNTER, counters->lost_pkt);
+                       break;
+               case QUIC_ST_TOO_SHORT_INITIAL_DGRAM:
+                       metric = mkf_u64(FN_COUNTER, counters->too_short_initial_dgram);
+                       break;
+               case QUIC_ST_RETRY_SENT:
+                       metric = mkf_u64(FN_COUNTER, counters->retry_sent);
+                       break;
+               case QUIC_ST_RETRY_VALIDATED:
+                       metric = mkf_u64(FN_COUNTER, counters->retry_validated);
+                       break;
+               case QUIC_ST_RETRY_ERRORS:
+                       metric = mkf_u64(FN_COUNTER, counters->retry_error);
+                       break;
+               case QUIC_ST_HALF_OPEN_CONN:
+                       metric = mkf_u64(FN_GAUGE, counters->half_open_conn);
+                       break;
+               case QUIC_ST_HDSHK_FAIL:
+                       metric = mkf_u64(FN_COUNTER, counters->hdshk_fail);
+                       break;
+               case QUIC_ST_STATELESS_RESET_SENT:
+                       metric = mkf_u64(FN_COUNTER, counters->stateless_reset_sent);
+                       break;
+
+               /* Special events of interest */
+               case QUIC_ST_CONN_MIGRATION_DONE:
+                       metric = mkf_u64(FN_COUNTER, counters->conn_migration_done);
+                       break;
+
+               /* Transport errors */
+               case QUIC_ST_TRANSP_ERR_NO_ERROR:
+                       metric = mkf_u64(FN_COUNTER, counters->quic_transp_err_no_error);
+                       break;
+               case QUIC_ST_TRANSP_ERR_INTERNAL_ERROR:
+                       metric = mkf_u64(FN_COUNTER, counters->quic_transp_err_internal_error);
+                       break;
+               case QUIC_ST_TRANSP_ERR_CONNECTION_REFUSED:
+                       metric = mkf_u64(FN_COUNTER, counters->quic_transp_err_connection_refused);
+                       break;
+               case QUIC_ST_TRANSP_ERR_FLOW_CONTROL_ERROR:
+                       metric = mkf_u64(FN_COUNTER, counters->quic_transp_err_flow_control_error);
+                       break;
+               case QUIC_ST_TRANSP_ERR_STREAM_LIMIT_ERROR:
+                       metric = mkf_u64(FN_COUNTER, counters->quic_transp_err_stream_limit_error);
+                       break;
+               case QUIC_ST_TRANSP_ERR_STREAM_STATE_ERROR:
+                       metric = mkf_u64(FN_COUNTER, counters->quic_transp_err_stream_state_error);
+                       break;
+               case QUIC_ST_TRANSP_ERR_FINAL_SIZE_ERROR:
+                       metric = mkf_u64(FN_COUNTER, counters->quic_transp_err_final_size_error);
+                       break;
+               case QUIC_ST_TRANSP_ERR_FRAME_ENCODING_ERROR:
+                       metric = mkf_u64(FN_COUNTER, counters->quic_transp_err_frame_encoding_error);
+                       break;
+               case QUIC_ST_TRANSP_ERR_TRANSPORT_PARAMETER_ERROR:
+                       metric = mkf_u64(FN_COUNTER, counters->quic_transp_err_transport_parameter_error);
+                       break;
+               case QUIC_ST_TRANSP_ERR_CONNECTION_ID_LIMIT_ERROR:
+                       metric = mkf_u64(FN_COUNTER, counters->quic_transp_err_connection_id_limit);
+                       break;
+               case QUIC_ST_TRANSP_ERR_PROTOCOL_VIOLATION:
+                       metric = mkf_u64(FN_COUNTER, counters->quic_transp_err_protocol_violation);
+                       break;
+               case QUIC_ST_TRANSP_ERR_INVALID_TOKEN:
+                       metric = mkf_u64(FN_COUNTER, counters->quic_transp_err_invalid_token);
+                       break;
+               case QUIC_ST_TRANSP_ERR_APPLICATION_ERROR:
+                       metric = mkf_u64(FN_COUNTER, counters->quic_transp_err_application_error);
+                       break;
+               case QUIC_ST_TRANSP_ERR_CRYPTO_BUFFER_EXCEEDED:
+                       metric = mkf_u64(FN_COUNTER, counters->quic_transp_err_crypto_buffer_exceeded);
+                       break;
+               case QUIC_ST_TRANSP_ERR_KEY_UPDATE_ERROR:
+                       metric = mkf_u64(FN_COUNTER, counters->quic_transp_err_key_update_error);
+                       break;
+               case QUIC_ST_TRANSP_ERR_AEAD_LIMIT_REACHED:
+                       metric = mkf_u64(FN_COUNTER, counters->quic_transp_err_aead_limit_reached);
+                       break;
+               case QUIC_ST_TRANSP_ERR_NO_VIABLE_PATH:
+                       metric = mkf_u64(FN_COUNTER, counters->quic_transp_err_no_viable_path);
+                       break;
+               case QUIC_ST_TRANSP_ERR_CRYPTO_ERROR:
+                       metric = mkf_u64(FN_COUNTER, counters->quic_transp_err_crypto_error);
+                       break;
+               case QUIC_ST_TRANSP_ERR_UNKNOWN_ERROR:
+                       metric = mkf_u64(FN_COUNTER, counters->quic_transp_err_unknown_error);
+                       break;
+
+               /* Streams related counters */
+               case QUIC_ST_DATA_BLOCKED:
+                       metric = mkf_u64(FN_COUNTER, counters->data_blocked);
+                       break;
+               case QUIC_ST_STREAM_DATA_BLOCKED:
+                       metric = mkf_u64(FN_COUNTER, counters->stream_data_blocked);
+                       break;
+               case QUIC_ST_STREAMS_BLOCKED_BIDI:
+                       metric = mkf_u64(FN_COUNTER, counters->streams_blocked_bidi);
+                       break;
+               case QUIC_ST_STREAMS_BLOCKED_UNI:
+                       metric = mkf_u64(FN_COUNTER, counters->streams_blocked_uni);
+                       break;
+               default:
+                       /* not used for frontends. If a specific metric
+                        * is requested, return an error. Otherwise continue.
+                        */
+                       if (selected_field != NULL)
+                               return 0;
+                       continue;
+               }
+               stats[current_field] = metric;
+               if (selected_field != NULL)
+                       break;
+       }
+       return 1;
 }
 
 struct stats_module quic_stats_module = {
index 96af44a0c90c98c69f924d95b62b69de4f0205dc..9657156c10c3d9eaad0e236b97fa8d39dcb1086d 100644 (file)
@@ -114,26 +114,79 @@ static struct name_desc resolv_stats[] = {
 
 static struct dns_counters dns_counters;
 
-static void resolv_fill_stats(void *d, struct field *stats)
+static int resolv_fill_stats(void *d, struct field *stats, unsigned int *selected_field)
 {
        struct dns_counters *counters = d;
-       stats[RSLV_STAT_ID]          = mkf_str(FO_CONFIG, counters->id);
-       stats[RSLV_STAT_PID]         = mkf_str(FO_CONFIG, counters->pid);
-       stats[RSLV_STAT_SENT]        = mkf_u64(FN_GAUGE, counters->sent);
-       stats[RSLV_STAT_SND_ERROR]   = mkf_u64(FN_GAUGE, counters->snd_error);
-       stats[RSLV_STAT_VALID]       = mkf_u64(FN_GAUGE, counters->app.resolver.valid);
-       stats[RSLV_STAT_UPDATE]      = mkf_u64(FN_GAUGE, counters->app.resolver.update);
-       stats[RSLV_STAT_CNAME]       = mkf_u64(FN_GAUGE, counters->app.resolver.cname);
-       stats[RSLV_STAT_CNAME_ERROR] = mkf_u64(FN_GAUGE, counters->app.resolver.cname_error);
-       stats[RSLV_STAT_ANY_ERR]     = mkf_u64(FN_GAUGE, counters->app.resolver.any_err);
-       stats[RSLV_STAT_NX]          = mkf_u64(FN_GAUGE, counters->app.resolver.nx);
-       stats[RSLV_STAT_TIMEOUT]     = mkf_u64(FN_GAUGE, counters->app.resolver.timeout);
-       stats[RSLV_STAT_REFUSED]     = mkf_u64(FN_GAUGE, counters->app.resolver.refused);
-       stats[RSLV_STAT_OTHER]       = mkf_u64(FN_GAUGE, counters->app.resolver.other);
-       stats[RSLV_STAT_INVALID]     = mkf_u64(FN_GAUGE, counters->app.resolver.invalid);
-       stats[RSLV_STAT_TOO_BIG]     = mkf_u64(FN_GAUGE, counters->app.resolver.too_big);
-       stats[RSLV_STAT_TRUNCATED]   = mkf_u64(FN_GAUGE, counters->app.resolver.truncated);
-       stats[RSLV_STAT_OUTDATED]    = mkf_u64(FN_GAUGE, counters->app.resolver.outdated);
+       unsigned int current_field = (selected_field != NULL ? *selected_field : 0);
+
+       for (; current_field < RSLV_STAT_END; current_field++) {
+               struct field metric = { 0 };
+
+               switch (current_field) {
+               case RSLV_STAT_ID:
+                       metric = mkf_str(FO_CONFIG, counters->id);
+                       break;
+               case RSLV_STAT_PID:
+                       metric = mkf_str(FO_CONFIG, counters->pid);
+                       break;
+               case RSLV_STAT_SENT:
+                       metric = mkf_u64(FN_GAUGE, counters->sent);
+                       break;
+               case RSLV_STAT_SND_ERROR:
+                       metric = mkf_u64(FN_GAUGE, counters->snd_error);
+                       break;
+               case RSLV_STAT_VALID:
+                       metric = mkf_u64(FN_GAUGE, counters->app.resolver.valid);
+                       break;
+               case RSLV_STAT_UPDATE:
+                       metric = mkf_u64(FN_GAUGE, counters->app.resolver.update);
+                       break;
+               case RSLV_STAT_CNAME:
+                       metric = mkf_u64(FN_GAUGE, counters->app.resolver.cname);
+                       break;
+               case RSLV_STAT_CNAME_ERROR:
+                       metric = mkf_u64(FN_GAUGE, counters->app.resolver.cname_error);
+                       break;
+               case RSLV_STAT_ANY_ERR:
+                       metric = mkf_u64(FN_GAUGE, counters->app.resolver.any_err);
+                       break;
+               case RSLV_STAT_NX:
+                       metric = mkf_u64(FN_GAUGE, counters->app.resolver.nx);
+                       break;
+               case RSLV_STAT_TIMEOUT:
+                       metric = mkf_u64(FN_GAUGE, counters->app.resolver.timeout);
+                       break;
+               case RSLV_STAT_REFUSED:
+                       metric = mkf_u64(FN_GAUGE, counters->app.resolver.refused);
+                       break;
+               case RSLV_STAT_OTHER:
+                       metric = mkf_u64(FN_GAUGE, counters->app.resolver.other);
+                       break;
+               case RSLV_STAT_INVALID:
+                       metric = mkf_u64(FN_GAUGE, counters->app.resolver.invalid);
+                       break;
+               case RSLV_STAT_TOO_BIG:
+                       metric = mkf_u64(FN_GAUGE, counters->app.resolver.too_big);
+                       break;
+               case RSLV_STAT_TRUNCATED:
+                       metric = mkf_u64(FN_GAUGE, counters->app.resolver.truncated);
+                       break;
+               case RSLV_STAT_OUTDATED:
+                       metric = mkf_u64(FN_GAUGE, counters->app.resolver.outdated);
+                       break;
+               default:
+                       /* not used for frontends. If a specific metric
+                        * is requested, return an error. Otherwise continue.
+                        */
+                       if (selected_field != NULL)
+                               return 0;
+                       continue;
+               }
+               stats[current_field] = metric;
+               if (selected_field != NULL)
+                       break;
+       }
+       return 1;
 }
 
 static struct stats_module rslv_stats_module = {
@@ -2711,7 +2764,8 @@ static int stats_dump_resolv_to_buffer(struct stconn *sc,
        list_for_each_entry(mod, stat_modules, list) {
                struct counters_node *counters = EXTRA_COUNTERS_GET(ns->extra_counters, mod);
 
-               mod->fill_stats(counters, stats + idx);
+               if (!mod->fill_stats(counters, stats + idx, NULL))
+                       continue;
                idx += mod->stats_count;
        }
 
index 92e78e80b023cf6d04a0f655365c27eac7720e31..56872a10077582b6a018898b527a3673adaac8f4 100644 (file)
@@ -172,13 +172,37 @@ static struct ssl_counters {
        long long failed_handshake;
 } ssl_counters;
 
-static void ssl_fill_stats(void *data, struct field *stats)
+static int ssl_fill_stats(void *data, struct field *stats, unsigned int *selected_field)
 {
        struct ssl_counters *counters = data;
+       unsigned int current_field = (selected_field != NULL ? *selected_field : 0);
 
-       stats[SSL_ST_SESS]             = mkf_u64(FN_COUNTER, counters->sess);
-       stats[SSL_ST_REUSED_SESS]      = mkf_u64(FN_COUNTER, counters->reused_sess);
-       stats[SSL_ST_FAILED_HANDSHAKE] = mkf_u64(FN_COUNTER, counters->failed_handshake);
+       for (; current_field < SSL_ST_STATS_COUNT; current_field++) {
+               struct field metric = { 0 };
+
+               switch (current_field) {
+               case SSL_ST_SESS:
+                       metric = mkf_u64(FN_COUNTER, counters->sess);
+                       break;
+               case SSL_ST_REUSED_SESS:
+                       metric = mkf_u64(FN_COUNTER, counters->reused_sess);
+                       break;
+               case SSL_ST_FAILED_HANDSHAKE:
+                       metric = mkf_u64(FN_COUNTER, counters->failed_handshake);
+                       break;
+               default:
+                       /* not used for frontends. If a specific metric
+                        * is requested, return an error. Otherwise continue.
+                        */
+                       if (selected_field != NULL)
+                               return 0;
+                       continue;
+               }
+               stats[current_field] = metric;
+               if (selected_field != NULL)
+                       break;
+       }
+       return 1;
 }
 
 static struct stats_module ssl_stats_module = {
index 5547999747be91be3964a8299c1a66bfaa22da6e..6ef8fec5ad45b07e483d617e128f87b0737e3250 100644 (file)
@@ -1952,7 +1952,8 @@ static int stats_dump_fe_stats(struct stconn *sc, struct proxy *px)
                }
 
                counters = EXTRA_COUNTERS_GET(px->extra_counters_fe, mod);
-               mod->fill_stats(counters, stats + stats_count);
+               if (!mod->fill_stats(counters, stats + stats_count, NULL))
+                       continue;
                stats_count += mod->stats_count;
        }
 
@@ -2119,7 +2120,8 @@ static int stats_dump_li_stats(struct stconn *sc, struct proxy *px, struct liste
                }
 
                counters = EXTRA_COUNTERS_GET(l->extra_counters, mod);
-               mod->fill_stats(counters, stats + stats_count);
+               if (!mod->fill_stats(counters, stats + stats_count, NULL))
+                       continue;
                stats_count += mod->stats_count;
        }
 
@@ -2637,7 +2639,8 @@ static int stats_dump_sv_stats(struct stconn *sc, struct proxy *px, struct serve
                }
 
                counters = EXTRA_COUNTERS_GET(sv->extra_counters, mod);
-               mod->fill_stats(counters, stats + stats_count);
+               if (!mod->fill_stats(counters, stats + stats_count, NULL))
+                       continue;
                stats_count += mod->stats_count;
        }
 
@@ -2973,7 +2976,8 @@ static int stats_dump_be_stats(struct stconn *sc, struct proxy *px)
                }
 
                counters = EXTRA_COUNTERS_GET(px->extra_counters_be, mod);
-               mod->fill_stats(counters, stats + stats_count);
+               if (!mod->fill_stats(counters, stats + stats_count, NULL))
+                       continue;
                stats_count += mod->stats_count;
        }
 
@@ -5332,6 +5336,7 @@ void stats_register_module(struct stats_module *m)
        stat_count[domain] += m->stats_count;
 }
 
+
 static int allocate_stats_px_postcheck(void)
 {
        struct stats_module *mod;