MEDIUM: stats: Be able to access a specific field into a stats module

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.
This commit is contained in:
Christopher Faulet 2024-01-29 16:35:19 +01:00
parent fd366a106b
commit 3246f863d6
8 changed files with 460 additions and 127 deletions

View File

@ -511,7 +511,7 @@ struct stats_module {
const char *name; const char *name;
/* functor used to generate the stats module using counters provided through data parameter */ /* 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 */ struct name_desc *stats; /* name/description of stats provided by the module */
void *counters; /* initial values of allocated counters */ void *counters; /* initial values of allocated counters */

View File

@ -128,40 +128,114 @@ static struct h3_counters {
long long qpack_decoder_stream_error; /* total number of QPACK_DECODER_STREAM_ERROR errors received */ long long qpack_decoder_stream_error; /* total number of QPACK_DECODER_STREAM_ERROR errors received */
} h3_counters; } 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; struct h3_counters *counters = data;
unsigned int current_field = (selected_field != NULL ? *selected_field : 0);
/* h3 frame type counters */ for (; current_field < H3_STATS_COUNT; current_field++) {
stats[H3_ST_DATA] = mkf_u64(FN_COUNTER, counters->h3_data); struct field metric = { 0 };
stats[H3_ST_HEADERS] = mkf_u64(FN_COUNTER, counters->h3_headers);
stats[H3_ST_CANCEL_PUSH] = mkf_u64(FN_COUNTER, counters->h3_cancel_push); switch (current_field) {
stats[H3_ST_PUSH_PROMISE] = mkf_u64(FN_COUNTER, counters->h3_push_promise); /* h3 frame type counters */
stats[H3_ST_MAX_PUSH_ID] = mkf_u64(FN_COUNTER, counters->h3_max_push_id); case H3_ST_DATA:
stats[H3_ST_GOAWAY] = mkf_u64(FN_COUNTER, counters->h3_goaway); metric = mkf_u64(FN_COUNTER, counters->h3_data);
stats[H3_ST_SETTINGS] = mkf_u64(FN_COUNTER, counters->h3_settings); break;
/* h3 error counters */ case H3_ST_HEADERS:
stats[H3_ST_H3_NO_ERROR] = mkf_u64(FN_COUNTER, counters->h3_no_error); metric = mkf_u64(FN_COUNTER, counters->h3_headers);
stats[H3_ST_H3_GENERAL_PROTOCOL_ERROR] = mkf_u64(FN_COUNTER, counters->h3_general_protocol_error); break;
stats[H3_ST_H3_INTERNAL_ERROR] = mkf_u64(FN_COUNTER, counters->h3_internal_error); case H3_ST_CANCEL_PUSH:
stats[H3_ST_H3_STREAM_CREATION_ERROR] = mkf_u64(FN_COUNTER, counters->h3_stream_creation_error); metric = mkf_u64(FN_COUNTER, counters->h3_cancel_push);
stats[H3_ST_H3_CLOSED_CRITICAL_STREAM] = mkf_u64(FN_COUNTER, counters->h3_closed_critical_stream); break;
stats[H3_ST_H3_FRAME_UNEXPECTED] = mkf_u64(FN_COUNTER, counters->h3_frame_unexpected); case H3_ST_PUSH_PROMISE:
stats[H3_ST_H3_FRAME_ERROR] = mkf_u64(FN_COUNTER, counters->h3_frame_error); metric = mkf_u64(FN_COUNTER, counters->h3_push_promise);
stats[H3_ST_H3_EXCESSIVE_LOAD] = mkf_u64(FN_COUNTER, counters->h3_excessive_load); break;
stats[H3_ST_H3_ID_ERROR] = mkf_u64(FN_COUNTER, counters->h3_id_error); case H3_ST_MAX_PUSH_ID:
stats[H3_ST_H3_SETTINGS_ERROR] = mkf_u64(FN_COUNTER, counters->h3_settings_error); metric = mkf_u64(FN_COUNTER, counters->h3_max_push_id);
stats[H3_ST_H3_MISSING_SETTINGS] = mkf_u64(FN_COUNTER, counters->h3_missing_settings); break;
stats[H3_ST_H3_REQUEST_REJECTED] = mkf_u64(FN_COUNTER, counters->h3_request_rejected); case H3_ST_GOAWAY:
stats[H3_ST_H3_REQUEST_CANCELLED] = mkf_u64(FN_COUNTER, counters->h3_request_cancelled); metric = mkf_u64(FN_COUNTER, counters->h3_goaway);
stats[H3_ST_H3_REQUEST_INCOMPLETE] = mkf_u64(FN_COUNTER, counters->h3_request_incomplete); break;
stats[H3_ST_H3_MESSAGE_ERROR] = mkf_u64(FN_COUNTER, counters->h3_message_error); case H3_ST_SETTINGS:
stats[H3_ST_H3_CONNECT_ERROR] = mkf_u64(FN_COUNTER, counters->h3_connect_error); metric = mkf_u64(FN_COUNTER, counters->h3_settings);
stats[H3_ST_H3_VERSION_FALLBACK] = mkf_u64(FN_COUNTER, counters->h3_version_fallback); break;
/* QPACK error counters */
stats[H3_ST_QPACK_DECOMPRESSION_FAILED] = mkf_u64(FN_COUNTER, counters->qpack_decompression_failed); /* h3 error counters */
stats[H3_ST_QPACK_ENCODER_STREAM_ERROR] = mkf_u64(FN_COUNTER, counters->qpack_encoder_stream_error); case H3_ST_H3_NO_ERROR:
stats[H3_ST_QPACK_DECODER_STREAM_ERROR] = mkf_u64(FN_COUNTER, counters->qpack_decoder_stream_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 = { struct stats_module h3_stats_module = {

View File

@ -264,21 +264,54 @@ static struct h1_counters {
#endif #endif
} h1_counters; } 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; 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); for (; current_field < H1_STATS_COUNT; current_field++) {
stats[H1_ST_OPEN_STREAM] = mkf_u64(FN_GAUGE, counters->open_streams); struct field metric = { 0 };
stats[H1_ST_TOTAL_CONN] = mkf_u64(FN_COUNTER, counters->total_conns);
stats[H1_ST_TOTAL_STREAM] = mkf_u64(FN_COUNTER, counters->total_streams);
stats[H1_ST_BYTES_IN] = mkf_u64(FN_COUNTER, counters->bytes_in); switch (current_field) {
stats[H1_ST_BYTES_OUT] = mkf_u64(FN_COUNTER, counters->bytes_out); 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) #if defined(USE_LINUX_SPLICE)
stats[H1_ST_SPLICED_BYTES_IN] = mkf_u64(FN_COUNTER, counters->spliced_bytes_in); case H1_ST_SPLICED_BYTES_IN:
stats[H1_ST_SPLICED_BYTES_OUT] = mkf_u64(FN_COUNTER, counters->spliced_bytes_out); 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 #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 = { static struct stats_module h1_stats_module = {

View File

@ -355,25 +355,67 @@ static struct h2_counters {
long long total_streams; /* total number of streams */ long long total_streams; /* total number of streams */
} h2_counters; } 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; 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); for (; current_field < H2_STATS_COUNT; current_field++) {
stats[H2_ST_DATA_RCVD] = mkf_u64(FN_COUNTER, counters->data_rcvd); struct field metric = { 0 };
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); switch (current_field) {
stats[H2_ST_STRM_PROTO_ERR] = mkf_u64(FN_COUNTER, counters->strm_proto_err); case H2_ST_HEADERS_RCVD:
stats[H2_ST_RST_STREAM_RESP] = mkf_u64(FN_COUNTER, counters->rst_stream_resp); metric = mkf_u64(FN_COUNTER, counters->headers_rcvd);
stats[H2_ST_GOAWAY_RESP] = mkf_u64(FN_COUNTER, counters->goaway_resp); break;
case H2_ST_DATA_RCVD:
stats[H2_ST_OPEN_CONN] = mkf_u64(FN_GAUGE, counters->open_conns); metric = mkf_u64(FN_COUNTER, counters->data_rcvd);
stats[H2_ST_OPEN_STREAM] = mkf_u64(FN_GAUGE, counters->open_streams); break;
stats[H2_ST_TOTAL_CONN] = mkf_u64(FN_COUNTER, counters->total_conns); case H2_ST_SETTINGS_RCVD:
stats[H2_ST_TOTAL_STREAM] = mkf_u64(FN_COUNTER, counters->total_streams); 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 = { static struct stats_module h2_stats_module = {

View File

@ -90,53 +90,154 @@ static struct name_desc quic_stats[] = {
struct quic_counters quic_counters; 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; 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); for (; current_field < QUIC_STATS_COUNT; current_field++) {
stats[QUIC_ST_DROPPED_PACKET] = mkf_u64(FN_COUNTER, counters->dropped_pkt); struct field metric = { 0 };
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); switch (current_field) {
stats[QUIC_ST_SOCKET_FULL] = mkf_u64(FN_COUNTER, counters->socket_full); case QUIC_ST_RXBUF_FULL:
stats[QUIC_ST_SENDTO_ERR] = mkf_u64(FN_COUNTER, counters->sendto_err); metric = mkf_u64(FN_COUNTER, counters->rxbuf_full);
stats[QUIC_ST_SENDTO_ERR_UNKNWN] = mkf_u64(FN_COUNTER, counters->sendto_err_unknown); break;
stats[QUIC_ST_SENT_PACKET] = mkf_u64(FN_COUNTER, counters->sent_pkt); case QUIC_ST_DROPPED_PACKET:
stats[QUIC_ST_LOST_PACKET] = mkf_u64(FN_COUNTER, counters->lost_pkt); metric = mkf_u64(FN_COUNTER, counters->dropped_pkt);
stats[QUIC_ST_TOO_SHORT_INITIAL_DGRAM] = mkf_u64(FN_COUNTER, counters->too_short_initial_dgram); break;
stats[QUIC_ST_RETRY_SENT] = mkf_u64(FN_COUNTER, counters->retry_sent); case QUIC_ST_DROPPED_PACKET_BUFOVERRUN:
stats[QUIC_ST_RETRY_VALIDATED] = mkf_u64(FN_COUNTER, counters->retry_validated); metric = mkf_u64(FN_COUNTER, counters->dropped_pkt_bufoverrun);
stats[QUIC_ST_RETRY_ERRORS] = mkf_u64(FN_COUNTER, counters->retry_error); break;
stats[QUIC_ST_HALF_OPEN_CONN] = mkf_u64(FN_GAUGE, counters->half_open_conn); case QUIC_ST_DROPPED_PARSING:
stats[QUIC_ST_HDSHK_FAIL] = mkf_u64(FN_COUNTER, counters->hdshk_fail); metric = mkf_u64(FN_COUNTER, counters->dropped_parsing);
stats[QUIC_ST_STATELESS_RESET_SENT] = mkf_u64(FN_COUNTER, counters->stateless_reset_sent); break;
/* Special events of interest */ case QUIC_ST_SOCKET_FULL:
stats[QUIC_ST_CONN_MIGRATION_DONE] = mkf_u64(FN_COUNTER, counters->conn_migration_done); metric = mkf_u64(FN_COUNTER, counters->socket_full);
/* Transport errors */ break;
stats[QUIC_ST_TRANSP_ERR_NO_ERROR] = mkf_u64(FN_COUNTER, counters->quic_transp_err_no_error); case QUIC_ST_SENDTO_ERR:
stats[QUIC_ST_TRANSP_ERR_INTERNAL_ERROR] = mkf_u64(FN_COUNTER, counters->quic_transp_err_internal_error); metric = mkf_u64(FN_COUNTER, counters->sendto_err);
stats[QUIC_ST_TRANSP_ERR_CONNECTION_REFUSED] = mkf_u64(FN_COUNTER, counters->quic_transp_err_connection_refused); break;
stats[QUIC_ST_TRANSP_ERR_FLOW_CONTROL_ERROR] = mkf_u64(FN_COUNTER, counters->quic_transp_err_flow_control_error); case QUIC_ST_SENDTO_ERR_UNKNWN:
stats[QUIC_ST_TRANSP_ERR_STREAM_LIMIT_ERROR] = mkf_u64(FN_COUNTER, counters->quic_transp_err_stream_limit_error); metric = mkf_u64(FN_COUNTER, counters->sendto_err_unknown);
stats[QUIC_ST_TRANSP_ERR_STREAM_STATE_ERROR] = mkf_u64(FN_COUNTER, counters->quic_transp_err_stream_state_error); break;
stats[QUIC_ST_TRANSP_ERR_FINAL_SIZE_ERROR] = mkf_u64(FN_COUNTER, counters->quic_transp_err_final_size_error); case QUIC_ST_SENT_PACKET:
stats[QUIC_ST_TRANSP_ERR_FRAME_ENCODING_ERROR] = mkf_u64(FN_COUNTER, counters->quic_transp_err_frame_encoding_error); metric = mkf_u64(FN_COUNTER, counters->sent_pkt);
stats[QUIC_ST_TRANSP_ERR_TRANSPORT_PARAMETER_ERROR] = mkf_u64(FN_COUNTER, counters->quic_transp_err_transport_parameter_error); break;
stats[QUIC_ST_TRANSP_ERR_CONNECTION_ID_LIMIT_ERROR] = mkf_u64(FN_COUNTER, counters->quic_transp_err_connection_id_limit); case QUIC_ST_LOST_PACKET:
stats[QUIC_ST_TRANSP_ERR_PROTOCOL_VIOLATION] = mkf_u64(FN_COUNTER, counters->quic_transp_err_protocol_violation); metric = mkf_u64(FN_COUNTER, counters->lost_pkt);
stats[QUIC_ST_TRANSP_ERR_INVALID_TOKEN] = mkf_u64(FN_COUNTER, counters->quic_transp_err_invalid_token); break;
stats[QUIC_ST_TRANSP_ERR_APPLICATION_ERROR] = mkf_u64(FN_COUNTER, counters->quic_transp_err_application_error); case QUIC_ST_TOO_SHORT_INITIAL_DGRAM:
stats[QUIC_ST_TRANSP_ERR_CRYPTO_BUFFER_EXCEEDED] = mkf_u64(FN_COUNTER, counters->quic_transp_err_crypto_buffer_exceeded); metric = mkf_u64(FN_COUNTER, counters->too_short_initial_dgram);
stats[QUIC_ST_TRANSP_ERR_KEY_UPDATE_ERROR] = mkf_u64(FN_COUNTER, counters->quic_transp_err_key_update_error); break;
stats[QUIC_ST_TRANSP_ERR_AEAD_LIMIT_REACHED] = mkf_u64(FN_COUNTER, counters->quic_transp_err_aead_limit_reached); case QUIC_ST_RETRY_SENT:
stats[QUIC_ST_TRANSP_ERR_NO_VIABLE_PATH] = mkf_u64(FN_COUNTER, counters->quic_transp_err_no_viable_path); metric = mkf_u64(FN_COUNTER, counters->retry_sent);
stats[QUIC_ST_TRANSP_ERR_CRYPTO_ERROR] = mkf_u64(FN_COUNTER, counters->quic_transp_err_crypto_error); break;
stats[QUIC_ST_TRANSP_ERR_UNKNOWN_ERROR] = mkf_u64(FN_COUNTER, counters->quic_transp_err_unknown_error); case QUIC_ST_RETRY_VALIDATED:
/* Streams related counters */ metric = mkf_u64(FN_COUNTER, counters->retry_validated);
stats[QUIC_ST_DATA_BLOCKED] = mkf_u64(FN_COUNTER, counters->data_blocked); break;
stats[QUIC_ST_STREAM_DATA_BLOCKED] = mkf_u64(FN_COUNTER, counters->stream_data_blocked); case QUIC_ST_RETRY_ERRORS:
stats[QUIC_ST_STREAMS_BLOCKED_BIDI] = mkf_u64(FN_COUNTER, counters->streams_blocked_bidi); metric = mkf_u64(FN_COUNTER, counters->retry_error);
stats[QUIC_ST_STREAMS_BLOCKED_UNI] = mkf_u64(FN_COUNTER, counters->streams_blocked_uni); 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 = { struct stats_module quic_stats_module = {

View File

@ -114,26 +114,79 @@ static struct name_desc resolv_stats[] = {
static struct dns_counters dns_counters; 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; struct dns_counters *counters = d;
stats[RSLV_STAT_ID] = mkf_str(FO_CONFIG, counters->id); unsigned int current_field = (selected_field != NULL ? *selected_field : 0);
stats[RSLV_STAT_PID] = mkf_str(FO_CONFIG, counters->pid);
stats[RSLV_STAT_SENT] = mkf_u64(FN_GAUGE, counters->sent); for (; current_field < RSLV_STAT_END; current_field++) {
stats[RSLV_STAT_SND_ERROR] = mkf_u64(FN_GAUGE, counters->snd_error); struct field metric = { 0 };
stats[RSLV_STAT_VALID] = mkf_u64(FN_GAUGE, counters->app.resolver.valid);
stats[RSLV_STAT_UPDATE] = mkf_u64(FN_GAUGE, counters->app.resolver.update); switch (current_field) {
stats[RSLV_STAT_CNAME] = mkf_u64(FN_GAUGE, counters->app.resolver.cname); case RSLV_STAT_ID:
stats[RSLV_STAT_CNAME_ERROR] = mkf_u64(FN_GAUGE, counters->app.resolver.cname_error); metric = mkf_str(FO_CONFIG, counters->id);
stats[RSLV_STAT_ANY_ERR] = mkf_u64(FN_GAUGE, counters->app.resolver.any_err); break;
stats[RSLV_STAT_NX] = mkf_u64(FN_GAUGE, counters->app.resolver.nx); case RSLV_STAT_PID:
stats[RSLV_STAT_TIMEOUT] = mkf_u64(FN_GAUGE, counters->app.resolver.timeout); metric = mkf_str(FO_CONFIG, counters->pid);
stats[RSLV_STAT_REFUSED] = mkf_u64(FN_GAUGE, counters->app.resolver.refused); break;
stats[RSLV_STAT_OTHER] = mkf_u64(FN_GAUGE, counters->app.resolver.other); case RSLV_STAT_SENT:
stats[RSLV_STAT_INVALID] = mkf_u64(FN_GAUGE, counters->app.resolver.invalid); metric = mkf_u64(FN_GAUGE, counters->sent);
stats[RSLV_STAT_TOO_BIG] = mkf_u64(FN_GAUGE, counters->app.resolver.too_big); break;
stats[RSLV_STAT_TRUNCATED] = mkf_u64(FN_GAUGE, counters->app.resolver.truncated); case RSLV_STAT_SND_ERROR:
stats[RSLV_STAT_OUTDATED] = mkf_u64(FN_GAUGE, counters->app.resolver.outdated); 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 = { 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) { list_for_each_entry(mod, stat_modules, list) {
struct counters_node *counters = EXTRA_COUNTERS_GET(ns->extra_counters, mod); 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; idx += mod->stats_count;
} }

View File

@ -172,13 +172,37 @@ static struct ssl_counters {
long long failed_handshake; long long failed_handshake;
} ssl_counters; } 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; 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); for (; current_field < SSL_ST_STATS_COUNT; current_field++) {
stats[SSL_ST_REUSED_SESS] = mkf_u64(FN_COUNTER, counters->reused_sess); struct field metric = { 0 };
stats[SSL_ST_FAILED_HANDSHAKE] = mkf_u64(FN_COUNTER, counters->failed_handshake);
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 = { static struct stats_module ssl_stats_module = {

View 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); 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; 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); 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; 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); 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; 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); 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; stats_count += mod->stats_count;
} }
@ -5332,6 +5336,7 @@ void stats_register_module(struct stats_module *m)
stat_count[domain] += m->stats_count; stat_count[domain] += m->stats_count;
} }
static int allocate_stats_px_postcheck(void) static int allocate_stats_px_postcheck(void)
{ {
struct stats_module *mod; struct stats_module *mod;