MINOR: stick-tables/counters: add http_fail_cnt and http_fail_rate data types

Historically we've been counting lots of client-triggered events in stick
tables to help detect misbehaving ones, but we've been missing the same on
the server side, and there's been repeated requests for being able to count
the server errors per URL in order to precisely monitor the quality of
service or even to avoid routing requests to certain dead services, which
is also called "circuit breaking" nowadays.

This commit introduces http_fail_cnt and http_fail_rate, which work like
http_err_cnt and http_err_rate in that they respectively count events and
their frequency, but they only consider server-side issues such as network
errors, unparsable and truncated responses, and 5xx status codes other
than 501 and 505 (since these ones are usually triggered by the client).
Note that retryable errors are purposely not accounted for, so that only
what the client really sees is considered.

With this it becomes very simple to put some protective measures in place
to perform a redirect or return an excuse page when the error rate goes
beyond a certain threshold for a given URL, and give more chances to the
server to recover from this condition. Typically it could look like this
to bypass a URL causing more than 10 requests per second:

  stick-table type string len 80 size 4k expire 1m store http_fail_rate(1m)
  http-request track-sc0 base       # track host+path, ignore query string
  http-request return status 503 content-type text/html \
      lf-file excuse.html if { sc0_http_fail_rate gt 10 }

A more advanced mechanism using gpt0 could even implement high/low rates
to disable/enable the service.

Reg-test converteers_ref_cnt_never_dec.vtc was updated to test it.
This commit is contained in:
Willy Tarreau 2021-02-10 12:07:15 +01:00
parent e4d247e217
commit 826f3ab5e6
9 changed files with 321 additions and 5 deletions

View File

@ -10838,6 +10838,19 @@ stick-table type {ip | integer | string [len <length>] | binary [len <length>]}
http_err_cnt above for what is accounted as an error). The result is an
integer which can be matched using ACLs.
- http_fail_cnt : HTTP Failure Count. It is a positive 32-bit integer which
counts the absolute number of HTTP response failures induced by servers
which matched this entry. Errors are counted on invalid and truncated
responses, as well as any 5xx response other than 501 or 505. It aims at
being used combined with path or URI to detect service failures.
- http_fail_rate(<period>) : frequency counter (takes 12 bytes). It takes
an integer parameter <period> which indicates in milliseconds the length
of the period over which the average is measured. It reports the average
HTTP response failure rate over that period, in requests per period (see
http_fail_cnt above for what is accounted as a failure). The result is an
integer which can be matched using ACLs.
- bytes_in_cnt : client to server byte count. It is a positive 64-bit
integer which counts the cumulative number of bytes received from clients
which matched this entry. Headers are included in the count. This may be
@ -16162,6 +16175,21 @@ table_http_err_rate(<table>)
period configured in the table. See also the sc_http_err_rate sample fetch
keyword.
table_http_fail_cnt(<table>)
Uses the string representation of the input sample to perform a look up in
the specified table. If the key is not found in the table, integer value zero
is returned. Otherwise the converter returns the cumulative number of HTTP
failures associated with the input sample in the designated table. See also
the sc_http_fail_cnt sample fetch keyword.
table_http_fail_rate(<table>)
Uses the string representation of the input sample to perform a look up in
the specified table. If the key is not found in the table, integer value zero
is returned. Otherwise the average rate of HTTP failures associated with the
input sample in the designated table, measured in amount of failures over the
period configured in the table. See also the sc_http_fail_rate sample fetch
keyword.
table_http_req_cnt(<table>)
Uses the string representation of the input sample to perform a look up in
the specified table. If the key is not found in the table, integer value zero
@ -17166,6 +17194,23 @@ sc2_http_err_rate([<table>]) : integer
includes the both request errors and 4xx error responses. See also
src_http_err_rate.
sc_http_fail_cnt(<ctr>[,<table>]) : integer
sc0_http_fail_cnt([<table>]) : integer
sc1_http_fail_cnt([<table>]) : integer
sc2_http_fail_cnt([<table>]) : integer
Returns the cumulative number of HTTP response failures from the currently
tracked counters. This includes the both response errors and 5xx status codes
other than 501 and 505. See also src_http_fail_cnt.
sc_http_fail_rate(<ctr>[,<table>]) : integer
sc0_http_fail_rate([<table>]) : integer
sc1_http_fail_rate([<table>]) : integer
sc2_http_fail_rate([<table>]) : integer
Returns the average rate of HTTP response failures from the currently tracked
counters, measured in amount of failures over the period configured in the
table. This includes the both response errors and 5xx status codes other than
501 and 505. See also src_http_fail_rate.
sc_http_req_cnt(<ctr>[,<table>]) : integer
sc0_http_req_cnt([<table>]) : integer
sc1_http_req_cnt([<table>]) : integer
@ -17402,6 +17447,21 @@ src_http_err_rate([<table>]) : integer
includes the both request errors and 4xx error responses. If the address is
not found, zero is returned. See also sc/sc0/sc1/sc2_http_err_rate.
src_http_fail_cnt([<table>]) : integer
Returns the cumulative number of HTTP response failures triggered by the
incoming connection's source address in the current proxy's stick-table or in
the designated stick-table. This includes the both repsonse errors and 5xx
status codes other than 501 and 505. See also sc/sc0/sc1/sc2_http_fail_cnt.
If the address is not found, zero is returned.
src_http_fail_rate([<table>]) : integer
Returns the average rate of HTTP response failures triggered by the incoming
connection's source address in the current proxy's stick-table or in the
designated stick-table, measured in amount of failures over the period
configured in the table. This includes the both response errors and 5xx
status codes other than 501 and 505. If the address is not found, zero is
returned. See also sc/sc0/sc1/sc2_http_fail_rate.
src_http_req_cnt([<table>]) : integer
Returns the cumulative number of HTTP requests from the incoming connection's
source address in the current proxy's stick-table or in the designated stick-

View File

@ -97,6 +97,19 @@ static inline void session_inc_http_err_ctr(struct session *sess)
stkctr_inc_http_err_ctr(&sess->stkctr[i]);
}
/* Increase the number of cumulated failed HTTP responses in the tracked
* counters. Only some 5xx responses should be counted here so that we can
* distinguish between server failures and errors triggered by the client
* (i.e. 501 and 505 may be triggered and must be ignored).
*/
static inline void session_inc_http_fail_ctr(struct session *sess)
{
int i;
for (i = 0; i < MAX_SESS_STKCTR; i++)
stkctr_inc_http_fail_ctr(&sess->stkctr[i]);
}
/* Remove the connection from the session list, and destroy the srv_list if it's now empty */
static inline void session_unown_conn(struct session *sess, struct connection *conn)

View File

@ -57,6 +57,9 @@ enum {
STKTABLE_DT_GPC1, /* General Purpose Counter 1 (unsigned 32-bit integer) */
STKTABLE_DT_GPC1_RATE, /* General Purpose Counter 1's event rate */
STKTABLE_DT_SERVER_KEY, /* The server key */
STKTABLE_DT_HTTP_FAIL_CNT, /* cumulated number of HTTP server failures */
STKTABLE_DT_HTTP_FAIL_RATE,/* HTTP server failures rate */
STKTABLE_STATIC_DATA_TYPES,/* number of types above */
/* up to STKTABLE_EXTRA_DATA_TYPES types may be registered here, always
* followed by the number of data types, must always be last.
@ -137,6 +140,8 @@ union stktable_data {
struct freq_ctr_period bytes_in_rate;
unsigned long long bytes_out_cnt;
struct freq_ctr_period bytes_out_rate;
unsigned int http_fail_cnt;
struct freq_ctr_period http_fail_rate;
};
/* known data types */

View File

@ -267,6 +267,38 @@ static inline int stkctr_inc_http_err_ctr(struct stkctr *stkctr)
return 1;
}
/* Increase the number of cumulated failed HTTP responses in the tracked counter
* <stkctr>. It returns 0 if the entry pointer does not exist and nothing is
* performed. Otherwise it returns 1.
*/
static inline int stkctr_inc_http_fail_ctr(struct stkctr *stkctr)
{
struct stksess *ts;
void *ptr1, *ptr2;
ts = stkctr_entry(stkctr);
if (!ts)
return 0;
HA_RWLOCK_WRLOCK(STK_SESS_LOCK, &ts->lock);
ptr1 = stktable_data_ptr(stkctr->table, ts, STKTABLE_DT_HTTP_FAIL_CNT);
if (ptr1)
stktable_data_cast(ptr1, http_fail_cnt)++;
ptr2 = stktable_data_ptr(stkctr->table, ts, STKTABLE_DT_HTTP_FAIL_RATE);
if (ptr2)
update_freq_ctr_period(&stktable_data_cast(ptr2, http_fail_rate),
stkctr->table->data_arg[STKTABLE_DT_HTTP_FAIL_RATE].u, 1);
HA_RWLOCK_WRUNLOCK(STK_SESS_LOCK, &ts->lock);
/* If data was modified, we need to touch to re-schedule sync */
if (ptr1 || ptr2)
stktable_touch_local(stkctr->table, ts, 0);
return 1;
}
/* Increase the number of bytes received in the tracked counter <stkctr>. It
* returns 0 if the entry pointer does not exist and nothing is
* performed. Otherwise it returns 1.

View File

@ -270,6 +270,21 @@ static inline void stream_inc_http_err_ctr(struct stream *s)
}
}
/* Increase the number of cumulated failed HTTP responses in the tracked
* counters. Only some 5xx responses should be counted here so that we can
* distinguish between server failures and errors triggered by the client
* (i.e. 501 and 505 may be triggered and must be ignored).
*/
static inline void stream_inc_http_fail_ctr(struct stream *s)
{
int i;
for (i = 0; i < MAX_SESS_STKCTR; i++) {
if (!stkctr_inc_http_fail_ctr(&s->stkctr[i]))
stkctr_inc_http_fail_ctr(&s->sess->stkctr[i]);
}
}
static inline void __stream_add_srv_conn(struct stream *sess, struct server *srv)
{
sess->srv_conn = srv;

View File

@ -15,6 +15,7 @@
# This should be backported to 1.8
#REGTEST_TYPE=bug
#REQUIRE_VERSION=2.4
varnishtest "stick-tables: Test expirations when used with table_*"
@ -36,7 +37,7 @@ haproxy h1 -conf {
frontend http1
bind "fd@${my_frontend_fd}"
stick-table size 1k expire 1ms type ip store conn_rate(10s),http_req_cnt,http_err_cnt,http_req_rate(10s),http_err_rate(10s),gpc0,gpc0_rate(10s),gpt0
stick-table size 1k expire 1ms type ip store conn_rate(10s),http_req_cnt,http_err_cnt,http_fail_cnt,http_req_rate(10s),http_err_rate(10s),http_fail_rate(10s),gpc0,gpc0_rate(10s),gpt0
http-request track-sc0 req.hdr(X-Forwarded-For)
http-request redirect location https://${s1_addr}:${s1_port}/ if { req.hdr(X-Forwarded-For),table_http_req_cnt(http1) -m int lt 0 }
http-request redirect location https://${s1_addr}:${s1_port}/ if { req.hdr(X-Forwarded-For),table_trackers(http1) -m int lt 0 }
@ -51,6 +52,8 @@ haproxy h1 -conf {
http-request redirect location https://${s1_addr}:${s1_port}/ if { req.hdr(X-Forwarded-For),table_gpc0_rate(http1) -m int lt 0 }
http-request redirect location https://${s1_addr}:${s1_port}/ if { req.hdr(X-Forwarded-For),table_http_err_cnt(http1) -m int lt 0 }
http-request redirect location https://${s1_addr}:${s1_port}/ if { req.hdr(X-Forwarded-For),table_http_err_rate(http1) -m int lt 0 }
http-request redirect location https://${s1_addr}:${s1_port}/ if { req.hdr(X-Forwarded-For),table_http_fail_cnt(http1) -m int lt 0 }
http-request redirect location https://${s1_addr}:${s1_port}/ if { req.hdr(X-Forwarded-For),table_http_fail_rate(http1) -m int lt 0 }
http-request redirect location https://${s1_addr}:${s1_port}/ if { req.hdr(X-Forwarded-For),table_http_req_cnt(http1) -m int lt 0 }
http-request redirect location https://${s1_addr}:${s1_port}/ if { req.hdr(X-Forwarded-For),table_http_req_rate(http1) -m int lt 0 }
http-request redirect location https://${s1_addr}:${s1_port}/ if { req.hdr(X-Forwarded-For),table_kbytes_in(http1) -m int lt 0 }
@ -69,5 +72,5 @@ client c1 -connect ${h1_my_frontend_fd_sock} {
haproxy h1 -cli {
send "show table http1"
expect ~ "table: http1, type: ip, size:1024, used:(0|1\\n0x[0-9a-f]*: key=127\\.0\\.0\\.1 use=0 exp=[0-9]* gpt0=0 gpc0=0 gpc0_rate\\(10000\\)=0 conn_rate\\(10000\\)=1 http_req_cnt=1 http_req_rate\\(10000\\)=1 http_err_cnt=0 http_err_rate\\(10000\\)=0)\\n$"
expect ~ "table: http1, type: ip, size:1024, used:(0|1\\n0x[0-9a-f]*: key=127\\.0\\.0\\.1 use=0 exp=[0-9]* gpt0=0 gpc0=0 gpc0_rate\\(10000\\)=0 conn_rate\\(10000\\)=1 http_req_cnt=1 http_req_rate\\(10000\\)=1 http_err_cnt=0 http_err_rate\\(10000\\)=0 http_fail_cnt=0 http_fail_rate\\(10000\\)=0)\\n$"
} -wait

View File

@ -1777,10 +1777,10 @@ static enum act_return http_action_track_sc(struct act_rule *rule, struct proxy
struct stktable *t;
struct stksess *ts;
struct stktable_key *key;
void *ptr1, *ptr2, *ptr3, *ptr4;
void *ptr1, *ptr2, *ptr3, *ptr4, *ptr5, *ptr6;
int opt;
ptr1 = ptr2 = ptr3 = ptr4 = NULL;
ptr1 = ptr2 = ptr3 = ptr4 = ptr5 = ptr6 = NULL;
opt = ((rule->from == ACT_F_HTTP_REQ) ? SMP_OPT_DIR_REQ : SMP_OPT_DIR_RES) | SMP_OPT_FINAL;
t = rule->arg.trk_ctr.table.t;
@ -1810,7 +1810,13 @@ static enum act_return http_action_track_sc(struct act_rule *rule, struct proxy
ptr4 = stktable_data_ptr(t, ts, STKTABLE_DT_HTTP_ERR_RATE);
}
if (ptr1 || ptr2 || ptr3 || ptr4) {
if (rule->from == ACT_F_HTTP_RES && (unsigned)(s->txn->status - 500) < 100 &&
s->txn->status != 501 && s->txn->status != 505) {
ptr5 = stktable_data_ptr(t, ts, STKTABLE_DT_HTTP_FAIL_CNT);
ptr6 = stktable_data_ptr(t, ts, STKTABLE_DT_HTTP_FAIL_RATE);
}
if (ptr1 || ptr2 || ptr3 || ptr4 || ptr5 || ptr6) {
HA_RWLOCK_WRLOCK(STK_SESS_LOCK, &ts->lock);
if (ptr1)
@ -1823,6 +1829,11 @@ static enum act_return http_action_track_sc(struct act_rule *rule, struct proxy
if (ptr4)
update_freq_ctr_period(&stktable_data_cast(ptr4, http_err_rate),
t->data_arg[STKTABLE_DT_HTTP_ERR_RATE].u, 1);
if (ptr5)
stktable_data_cast(ptr5, http_fail_cnt)++;
if (ptr6)
update_freq_ctr_period(&stktable_data_cast(ptr6, http_fail_rate),
t->data_arg[STKTABLE_DT_HTTP_FAIL_RATE].u, 1);
HA_RWLOCK_WRUNLOCK(STK_SESS_LOCK, &ts->lock);

View File

@ -1418,6 +1418,8 @@ int http_wait_for_response(struct stream *s, struct channel *rep, int an_bit)
}
txn->status = 425;
}
else
stream_inc_http_fail_ctr(s);
s->si[1].flags |= SI_FL_NOLINGER;
http_reply_and_close(s, txn->status, http_error_message(s));
@ -1449,6 +1451,7 @@ int http_wait_for_response(struct stream *s, struct channel *rep, int an_bit)
rep->analysers &= AN_RES_FLT_END;
txn->status = 504;
stream_inc_http_fail_ctr(s);
s->si[1].flags |= SI_FL_NOLINGER;
http_reply_and_close(s, txn->status, http_error_message(s));
@ -1507,6 +1510,7 @@ int http_wait_for_response(struct stream *s, struct channel *rep, int an_bit)
rep->analysers &= AN_RES_FLT_END;
txn->status = 502;
stream_inc_http_fail_ctr(s);
s->si[1].flags |= SI_FL_NOLINGER;
http_reply_and_close(s, txn->status, http_error_message(s));
@ -1614,6 +1618,9 @@ int http_wait_for_response(struct stream *s, struct channel *rep, int an_bit)
if (n == 4)
stream_inc_http_err_ctr(s);
if (n == 5 && txn->status != 501 && txn->status != 505)
stream_inc_http_fail_ctr(s);
if (objt_server(s->target)) {
_HA_ATOMIC_ADD(&__objt_server(s->target)->counters.p.http.rsp[n], 1);
_HA_ATOMIC_ADD(&__objt_server(s->target)->counters.p.http.cum_req, 1);
@ -1784,6 +1791,7 @@ int http_wait_for_response(struct stream *s, struct channel *rep, int an_bit)
return 0;
}
txn->status = 502;
stream_inc_http_fail_ctr(s);
/* fall through */
return_prx_cond:
@ -2081,6 +2089,7 @@ int http_process_res_common(struct stream *s, struct channel *rep, int an_bit, s
return_bad_res:
txn->status = 502;
stream_inc_http_fail_ctr(s);
_HA_ATOMIC_ADD(&s->be->be_counters.failed_resp, 1);
if (objt_server(s->target)) {
_HA_ATOMIC_ADD(&__objt_server(s->target)->counters.failed_resp, 1);
@ -2331,6 +2340,7 @@ int http_response_forward_body(struct stream *s, struct channel *res, int an_bit
_HA_ATOMIC_ADD(&sess->listener->counters->srv_aborts, 1);
if (objt_server(s->target))
_HA_ATOMIC_ADD(&__objt_server(s->target)->counters.srv_aborts, 1);
stream_inc_http_fail_ctr(s);
if (!(s->flags & SF_ERR_MASK))
s->flags |= SF_ERR_SRVCL;
goto return_error;
@ -2363,6 +2373,7 @@ int http_response_forward_body(struct stream *s, struct channel *res, int an_bit
_HA_ATOMIC_ADD(&__objt_server(s->target)->counters.failed_resp, 1);
health_adjust(__objt_server(s->target), HANA_STATUS_HTTP_RSP);
}
stream_inc_http_fail_ctr(s);
if (!(s->flags & SF_ERR_MASK))
s->flags |= SF_ERR_SRVCL;
/* fall through */

View File

@ -1075,6 +1075,8 @@ struct stktable_data_type stktable_data_types[STKTABLE_DATA_TYPES] = {
[STKTABLE_DT_GPC1] = { .name = "gpc1", .std_type = STD_T_UINT },
[STKTABLE_DT_GPC1_RATE] = { .name = "gpc1_rate", .std_type = STD_T_FRQP, .arg_type = ARG_T_DELAY },
[STKTABLE_DT_SERVER_KEY] = { .name = "server_key", .std_type = STD_T_DICT },
[STKTABLE_DT_HTTP_FAIL_CNT] = { .name = "http_fail_cnt", .std_type = STD_T_UINT },
[STKTABLE_DT_HTTP_FAIL_RATE]= { .name = "http_fail_rate", .std_type = STD_T_FRQP, .arg_type = ARG_T_DELAY },
};
/* Registers stick-table extra data type with index <idx>, name <name>, type
@ -1593,6 +1595,79 @@ static int sample_conv_table_http_err_rate(const struct arg *arg_p, struct sampl
return !!ptr;
}
/* Casts sample <smp> to the type of the table specified in arg(0), and looks
* it up into this table. Returns the cumulated number of HTTP response failures
* for the key if the key is present in the table, otherwise zero, so that
* comparisons can be easily performed. If the inspected parameter is not stored
* in the table, <not found> is returned.
*/
static int sample_conv_table_http_fail_cnt(const struct arg *arg_p, struct sample *smp, void *private)
{
struct stktable *t;
struct stktable_key *key;
struct stksess *ts;
void *ptr;
t = arg_p[0].data.t;
key = smp_to_stkey(smp, t);
if (!key)
return 0;
ts = stktable_lookup_key(t, key);
smp->flags = SMP_F_VOL_TEST;
smp->data.type = SMP_T_SINT;
smp->data.u.sint = 0;
if (!ts) /* key not present */
return 1;
ptr = stktable_data_ptr(t, ts, STKTABLE_DT_HTTP_FAIL_CNT);
if (ptr)
smp->data.u.sint = stktable_data_cast(ptr, http_fail_cnt);
stktable_release(t, ts);
return !!ptr;
}
/* Casts sample <smp> to the type of the table specified in arg(0), and looks
* it up into this table. Returns the HTTP response failure rate for the key
* if the key is present in the table, otherwise zero, so that comparisons can
* be easily performed. If the inspected parameter is not stored in the table,
* <not found> is returned.
*/
static int sample_conv_table_http_fail_rate(const struct arg *arg_p, struct sample *smp, void *private)
{
struct stktable *t;
struct stktable_key *key;
struct stksess *ts;
void *ptr;
t = arg_p[0].data.t;
key = smp_to_stkey(smp, t);
if (!key)
return 0;
ts = stktable_lookup_key(t, key);
smp->flags = SMP_F_VOL_TEST;
smp->data.type = SMP_T_SINT;
smp->data.u.sint = 0;
if (!ts) /* key not present */
return 1;
ptr = stktable_data_ptr(t, ts, STKTABLE_DT_HTTP_FAIL_RATE);
if (ptr)
smp->data.u.sint = read_freq_ctr_period(&stktable_data_cast(ptr, http_fail_rate),
t->data_arg[STKTABLE_DT_HTTP_FAIL_RATE].u);
stktable_release(t, ts);
return !!ptr;
}
/* Casts sample <smp> to the type of the table specified in arg(0), and looks
* it up into this table. Returns the cumulated number of HTTP request for the
* key if the key is present in the table, otherwise zero, so that comparisons
@ -3154,6 +3229,85 @@ smp_fetch_sc_http_err_rate(const struct arg *args, struct sample *smp, const cha
return 1;
}
/* set <smp> to the cumulated number of HTTP response failures from the stream's
* tracked frontend counters. Supports being called as "sc[0-9]_http_fail_cnt" or
* "src_http_fail_cnt" only.
*/
static int
smp_fetch_sc_http_fail_cnt(const struct arg *args, struct sample *smp, const char *kw, void *private)
{
struct stkctr tmpstkctr;
struct stkctr *stkctr;
stkctr = smp_fetch_sc_stkctr(smp->sess, smp->strm, args, kw, &tmpstkctr);
if (!stkctr)
return 0;
smp->flags = SMP_F_VOL_TEST;
smp->data.type = SMP_T_SINT;
smp->data.u.sint = 0;
if (stkctr_entry(stkctr) != NULL) {
void *ptr;
ptr = stktable_data_ptr(stkctr->table, stkctr_entry(stkctr), STKTABLE_DT_HTTP_FAIL_CNT);
if (!ptr) {
if (stkctr == &tmpstkctr)
stktable_release(stkctr->table, stkctr_entry(stkctr));
return 0; /* parameter not stored */
}
HA_RWLOCK_RDLOCK(STK_SESS_LOCK, &stkctr_entry(stkctr)->lock);
smp->data.u.sint = stktable_data_cast(ptr, http_fail_cnt);
HA_RWLOCK_RDUNLOCK(STK_SESS_LOCK, &stkctr_entry(stkctr)->lock);
if (stkctr == &tmpstkctr)
stktable_release(stkctr->table, stkctr_entry(stkctr));
}
return 1;
}
/* set <smp> to the HTTP response failure rate from the stream's tracked frontend
* counters. Supports being called as "sc[0-9]_http_fail_rate" or
* "src_http_fail_rate" only.
*/
static int
smp_fetch_sc_http_fail_rate(const struct arg *args, struct sample *smp, const char *kw, void *private)
{
struct stkctr tmpstkctr;
struct stkctr *stkctr;
stkctr = smp_fetch_sc_stkctr(smp->sess, smp->strm, args, kw, &tmpstkctr);
if (!stkctr)
return 0;
smp->flags = SMP_F_VOL_TEST;
smp->data.type = SMP_T_SINT;
smp->data.u.sint = 0;
if (stkctr_entry(stkctr) != NULL) {
void *ptr;
ptr = stktable_data_ptr(stkctr->table, stkctr_entry(stkctr), STKTABLE_DT_HTTP_FAIL_RATE);
if (!ptr) {
if (stkctr == &tmpstkctr)
stktable_release(stkctr->table, stkctr_entry(stkctr));
return 0; /* parameter not stored */
}
HA_RWLOCK_RDLOCK(STK_SESS_LOCK, &stkctr_entry(stkctr)->lock);
smp->data.u.sint = read_freq_ctr_period(&stktable_data_cast(ptr, http_fail_rate),
stkctr->table->data_arg[STKTABLE_DT_HTTP_FAIL_RATE].u);
HA_RWLOCK_RDUNLOCK(STK_SESS_LOCK, &stkctr_entry(stkctr)->lock);
if (stkctr == &tmpstkctr)
stktable_release(stkctr->table, stkctr_entry(stkctr));
}
return 1;
}
/* set <smp> to the number of kbytes received from clients, as found in the
* stream's tracked frontend counters. Supports being called as
* "sc[0-9]_kbytes_in" or "src_kbytes_in" only.
@ -3993,6 +4147,8 @@ static struct sample_fetch_kw_list smp_fetch_keywords = {ILH, {
{ "sc_gpc1_rate", smp_fetch_sc_gpc1_rate, ARG2(1,SINT,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, },
{ "sc_http_err_cnt", smp_fetch_sc_http_err_cnt, ARG2(1,SINT,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, },
{ "sc_http_err_rate", smp_fetch_sc_http_err_rate, ARG2(1,SINT,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, },
{ "sc_http_fail_cnt", smp_fetch_sc_http_fail_cnt, ARG2(1,SINT,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, },
{ "sc_http_fail_rate", smp_fetch_sc_http_fail_rate, ARG2(1,SINT,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, },
{ "sc_http_req_cnt", smp_fetch_sc_http_req_cnt, ARG2(1,SINT,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, },
{ "sc_http_req_rate", smp_fetch_sc_http_req_rate, ARG2(1,SINT,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, },
{ "sc_inc_gpc0", smp_fetch_sc_inc_gpc0, ARG2(1,SINT,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, },
@ -4017,6 +4173,8 @@ static struct sample_fetch_kw_list smp_fetch_keywords = {ILH, {
{ "sc0_gpc1_rate", smp_fetch_sc_gpc1_rate, ARG1(0,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, },
{ "sc0_http_err_cnt", smp_fetch_sc_http_err_cnt, ARG1(0,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, },
{ "sc0_http_err_rate", smp_fetch_sc_http_err_rate, ARG1(0,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, },
{ "sc0_http_fail_cnt", smp_fetch_sc_http_fail_cnt, ARG1(0,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, },
{ "sc0_http_fail_rate", smp_fetch_sc_http_fail_rate, ARG1(0,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, },
{ "sc0_http_req_cnt", smp_fetch_sc_http_req_cnt, ARG1(0,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, },
{ "sc0_http_req_rate", smp_fetch_sc_http_req_rate, ARG1(0,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, },
{ "sc0_inc_gpc0", smp_fetch_sc_inc_gpc0, ARG1(0,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, },
@ -4041,6 +4199,8 @@ static struct sample_fetch_kw_list smp_fetch_keywords = {ILH, {
{ "sc1_gpc1_rate", smp_fetch_sc_gpc1_rate, ARG1(0,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, },
{ "sc1_http_err_cnt", smp_fetch_sc_http_err_cnt, ARG1(0,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, },
{ "sc1_http_err_rate", smp_fetch_sc_http_err_rate, ARG1(0,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, },
{ "sc1_http_fail_cnt", smp_fetch_sc_http_fail_cnt, ARG1(0,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, },
{ "sc1_http_fail_rate", smp_fetch_sc_http_fail_rate, ARG1(0,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, },
{ "sc1_http_req_cnt", smp_fetch_sc_http_req_cnt, ARG1(0,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, },
{ "sc1_http_req_rate", smp_fetch_sc_http_req_rate, ARG1(0,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, },
{ "sc1_inc_gpc0", smp_fetch_sc_inc_gpc0, ARG1(0,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, },
@ -4065,6 +4225,8 @@ static struct sample_fetch_kw_list smp_fetch_keywords = {ILH, {
{ "sc2_gpc1_rate", smp_fetch_sc_gpc1_rate, ARG1(0,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, },
{ "sc2_http_err_cnt", smp_fetch_sc_http_err_cnt, ARG1(0,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, },
{ "sc2_http_err_rate", smp_fetch_sc_http_err_rate, ARG1(0,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, },
{ "sc2_http_fail_cnt", smp_fetch_sc_http_fail_cnt, ARG1(0,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, },
{ "sc2_http_fail_rate", smp_fetch_sc_http_fail_rate, ARG1(0,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, },
{ "sc2_http_req_cnt", smp_fetch_sc_http_req_cnt, ARG1(0,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, },
{ "sc2_http_req_rate", smp_fetch_sc_http_req_rate, ARG1(0,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, },
{ "sc2_inc_gpc0", smp_fetch_sc_inc_gpc0, ARG1(0,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, },
@ -4089,6 +4251,8 @@ static struct sample_fetch_kw_list smp_fetch_keywords = {ILH, {
{ "src_gpc1_rate", smp_fetch_sc_gpc1_rate, ARG1(1,TAB), NULL, SMP_T_SINT, SMP_USE_L4CLI, },
{ "src_http_err_cnt", smp_fetch_sc_http_err_cnt, ARG1(1,TAB), NULL, SMP_T_SINT, SMP_USE_L4CLI, },
{ "src_http_err_rate", smp_fetch_sc_http_err_rate, ARG1(1,TAB), NULL, SMP_T_SINT, SMP_USE_L4CLI, },
{ "src_http_fail_cnt", smp_fetch_sc_http_fail_cnt, ARG1(1,TAB), NULL, SMP_T_SINT, SMP_USE_L4CLI, },
{ "src_http_fail_rate", smp_fetch_sc_http_fail_rate, ARG1(1,TAB), NULL, SMP_T_SINT, SMP_USE_L4CLI, },
{ "src_http_req_cnt", smp_fetch_sc_http_req_cnt, ARG1(1,TAB), NULL, SMP_T_SINT, SMP_USE_L4CLI, },
{ "src_http_req_rate", smp_fetch_sc_http_req_rate, ARG1(1,TAB), NULL, SMP_T_SINT, SMP_USE_L4CLI, },
{ "src_inc_gpc0", smp_fetch_sc_inc_gpc0, ARG1(1,TAB), NULL, SMP_T_SINT, SMP_USE_L4CLI, },
@ -4120,6 +4284,8 @@ static struct sample_conv_kw_list sample_conv_kws = {ILH, {
{ "table_gpc1_rate", sample_conv_table_gpc1_rate, ARG1(1,TAB), NULL, SMP_T_ANY, SMP_T_SINT },
{ "table_http_err_cnt", sample_conv_table_http_err_cnt, ARG1(1,TAB), NULL, SMP_T_ANY, SMP_T_SINT },
{ "table_http_err_rate", sample_conv_table_http_err_rate, ARG1(1,TAB), NULL, SMP_T_ANY, SMP_T_SINT },
{ "table_http_fail_cnt", sample_conv_table_http_fail_cnt, ARG1(1,TAB), NULL, SMP_T_ANY, SMP_T_SINT },
{ "table_http_fail_rate", sample_conv_table_http_fail_rate, ARG1(1,TAB), NULL, SMP_T_ANY, SMP_T_SINT },
{ "table_http_req_cnt", sample_conv_table_http_req_cnt, ARG1(1,TAB), NULL, SMP_T_ANY, SMP_T_SINT },
{ "table_http_req_rate", sample_conv_table_http_req_rate, ARG1(1,TAB), NULL, SMP_T_ANY, SMP_T_SINT },
{ "table_kbytes_in", sample_conv_table_kbytes_in, ARG1(1,TAB), NULL, SMP_T_ANY, SMP_T_SINT },