diff --git a/include/haproxy/stats-t.h b/include/haproxy/stats-t.h index 34a4cc256..d3abf9ca2 100644 --- a/include/haproxy/stats-t.h +++ b/include/haproxy/stats-t.h @@ -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 */ diff --git a/src/h3_stats.c b/src/h3_stats.c index c96093f2c..830aa88a3 100644 --- a/src/h3_stats.c +++ b/src/h3_stats.c @@ -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 = { diff --git a/src/mux_h1.c b/src/mux_h1.c index c324c2fb9..b810ca625 100644 --- a/src/mux_h1.c +++ b/src/mux_h1.c @@ -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 = { diff --git a/src/mux_h2.c b/src/mux_h2.c index a38d75b90..bb1cbb87e 100644 --- a/src/mux_h2.c +++ b/src/mux_h2.c @@ -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); + for (; current_field < H2_STATS_COUNT; current_field++) { + struct field metric = { 0 }; - 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); + 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 = { diff --git a/src/quic_stats.c b/src/quic_stats.c index 3657f308c..80887c4fe 100644 --- a/src/quic_stats.c +++ b/src/quic_stats.c @@ -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 = { diff --git a/src/resolvers.c b/src/resolvers.c index 96af44a0c..9657156c1 100644 --- a/src/resolvers.c +++ b/src/resolvers.c @@ -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; } diff --git a/src/ssl_sock.c b/src/ssl_sock.c index 92e78e80b..56872a100 100644 --- a/src/ssl_sock.c +++ b/src/ssl_sock.c @@ -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 = { diff --git a/src/stats.c b/src/stats.c index 554799974..6ef8fec5a 100644 --- a/src/stats.c +++ b/src/stats.c @@ -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;