diff --git a/doc/admin-guide/monitoring/statistics/core/http-connection.en.rst b/doc/admin-guide/monitoring/statistics/core/http-connection.en.rst index 37cdcb06f77..0baa9dba815 100644 --- a/doc/admin-guide/monitoring/statistics/core/http-connection.en.rst +++ b/doc/admin-guide/monitoring/statistics/core/http-connection.en.rst @@ -256,3 +256,17 @@ HTTP/2 Represents the total number of closed HTTP/2 connections for not reaching the minimum average window increment limit which is configured by :ts:cv:`proxy.config.http2.min_avg_window_update`. + +.. ts:stat:: global proxy.process.http2.max_concurrent_streams_exceeded_in integer + :type: counter + + Represents the number of times an inbound HTTP/2 stream was not created for + reaching the maximum number of concurrent streams per inbound connection + configured by :ts:cv:`proxy.config.http2.max_concurrent_streams_in`. + +.. ts:stat:: global proxy.process.http2.max_concurrent_streams_exceeded_out integer + :type: counter + + Represents the number of times an outbound HTTP/2 stream was not created for + reaching the maximum number of concurrent streams per outbound connection + the client can initiate as specified by the server. diff --git a/proxy/http2/HTTP2.cc b/proxy/http2/HTTP2.cc index 6799425e6e6..8a4ba48e8ce 100644 --- a/proxy/http2/HTTP2.cc +++ b/proxy/http2/HTTP2.cc @@ -84,6 +84,10 @@ static const char *const HTTP2_STAT_MAX_PING_FRAMES_PER_MINUTE_EXCEEDED_NAME = static const char *const HTTP2_STAT_MAX_PRIORITY_FRAMES_PER_MINUTE_EXCEEDED_NAME = "proxy.process.http2.max_priority_frames_per_minute_exceeded"; static const char *const HTTP2_STAT_INSUFFICIENT_AVG_WINDOW_UPDATE_NAME = "proxy.process.http2.insufficient_avg_window_update"; +static const char *const HTTP2_STAT_MAX_CONCURRENT_STREAMS_EXCEEDED_IN_NAME = + "proxy.process.http2.max_concurrent_streams_exceeded_in"; +static const char *const HTTP2_STAT_MAX_CONCURRENT_STREAMS_EXCEEDED_OUT_NAME = + "proxy.process.http2.max_concurrent_streams_exceeded_out"; union byte_pointer { byte_pointer(void *p) : ptr(p) {} @@ -899,6 +903,10 @@ Http2::init() static_cast(HTTP2_STAT_MAX_PRIORITY_FRAMES_PER_MINUTE_EXCEEDED), RecRawStatSyncSum); RecRegisterRawStat(http2_rsb, RECT_PROCESS, HTTP2_STAT_INSUFFICIENT_AVG_WINDOW_UPDATE_NAME, RECD_INT, RECP_PERSISTENT, static_cast(HTTP2_STAT_INSUFFICIENT_AVG_WINDOW_UPDATE), RecRawStatSyncSum); + RecRegisterRawStat(http2_rsb, RECT_PROCESS, HTTP2_STAT_MAX_CONCURRENT_STREAMS_EXCEEDED_IN_NAME, RECD_INT, RECP_PERSISTENT, + static_cast(HTTP2_STAT_MAX_CONCURRENT_STREAMS_EXCEEDED_IN), RecRawStatSyncSum); + RecRegisterRawStat(http2_rsb, RECT_PROCESS, HTTP2_STAT_MAX_CONCURRENT_STREAMS_EXCEEDED_OUT_NAME, RECD_INT, RECP_PERSISTENT, + static_cast(HTTP2_STAT_MAX_CONCURRENT_STREAMS_EXCEEDED_OUT), RecRawStatSyncSum); http2_init(); } diff --git a/proxy/http2/HTTP2.h b/proxy/http2/HTTP2.h index d2eed22ffe3..e5fdc3e1458 100644 --- a/proxy/http2/HTTP2.h +++ b/proxy/http2/HTTP2.h @@ -105,6 +105,8 @@ enum { HTTP2_STAT_MAX_PING_FRAMES_PER_MINUTE_EXCEEDED, HTTP2_STAT_MAX_PRIORITY_FRAMES_PER_MINUTE_EXCEEDED, HTTP2_STAT_INSUFFICIENT_AVG_WINDOW_UPDATE, + HTTP2_STAT_MAX_CONCURRENT_STREAMS_EXCEEDED_IN, + HTTP2_STAT_MAX_CONCURRENT_STREAMS_EXCEEDED_OUT, HTTP2_N_STATS // Terminal counter, NOT A STAT INDEX. }; diff --git a/proxy/http2/Http2ConnectionState.cc b/proxy/http2/Http2ConnectionState.cc index 5e87fd889b7..24b05848555 100644 --- a/proxy/http2/Http2ConnectionState.cc +++ b/proxy/http2/Http2ConnectionState.cc @@ -1322,12 +1322,14 @@ Http2ConnectionState::create_stream(Http2StreamId new_id, Http2Error &error) // stream limit to be exceeded MUST treat this as a stream error. if (client_streamid) { if (client_streams_in_count >= server_settings.get(HTTP2_SETTINGS_MAX_CONCURRENT_STREAMS)) { + HTTP2_INCREMENT_THREAD_DYN_STAT(HTTP2_STAT_MAX_CONCURRENT_STREAMS_EXCEEDED_IN, this_ethread()); error = Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_STREAM, Http2ErrorCode::HTTP2_ERROR_REFUSED_STREAM, "recv headers creating inbound stream beyond max_concurrent limit"); return nullptr; } } else { if (client_streams_out_count >= client_settings.get(HTTP2_SETTINGS_MAX_CONCURRENT_STREAMS)) { + HTTP2_INCREMENT_THREAD_DYN_STAT(HTTP2_STAT_MAX_CONCURRENT_STREAMS_EXCEEDED_OUT, this_ethread()); error = Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_STREAM, Http2ErrorCode::HTTP2_ERROR_REFUSED_STREAM, "recv headers creating outbound stream beyond max_concurrent limit"); return nullptr;