MEDIUM: streams: support looking up stkctr in the session

In order to support sessions tracking counters, we first ensure that there
is no overlap between streams' stkctr and sessions', and we allow an
automatic lookup into the session's counters when the stream doesn't
have a counter or when the stream doesn't exist during an access via
a sample fetch. The functions used to update the stream counters only
update them and not the session counters however.
This commit is contained in:
Willy Tarreau 2015-04-04 16:29:12 +02:00
parent 7698c9080a
commit 8b7f8688ee
2 changed files with 69 additions and 41 deletions

View File

@ -178,41 +178,50 @@ static void inline stream_inc_http_req_ctr(struct stream *s)
int i; int i;
for (i = 0; i < MAX_SESS_STKCTR; i++) { for (i = 0; i < MAX_SESS_STKCTR; i++) {
if (!stkctr_entry(&s->stkctr[i])) struct stkctr *stkctr = &s->stkctr[i];
continue;
ptr = stktable_data_ptr(s->stkctr[i].table, stkctr_entry(&s->stkctr[i]), STKTABLE_DT_HTTP_REQ_CNT); if (!stkctr_entry(stkctr)) {
stkctr = &s->sess->stkctr[i];
if (!stkctr_entry(stkctr))
continue;
}
ptr = stktable_data_ptr(stkctr->table, stkctr_entry(stkctr), STKTABLE_DT_HTTP_REQ_CNT);
if (ptr) if (ptr)
stktable_data_cast(ptr, http_req_cnt)++; stktable_data_cast(ptr, http_req_cnt)++;
ptr = stktable_data_ptr(s->stkctr[i].table, stkctr_entry(&s->stkctr[i]), STKTABLE_DT_HTTP_REQ_RATE); ptr = stktable_data_ptr(stkctr->table, stkctr_entry(stkctr), STKTABLE_DT_HTTP_REQ_RATE);
if (ptr) if (ptr)
update_freq_ctr_period(&stktable_data_cast(ptr, http_req_rate), update_freq_ctr_period(&stktable_data_cast(ptr, http_req_rate),
s->stkctr[i].table->data_arg[STKTABLE_DT_HTTP_REQ_RATE].u, 1); stkctr->table->data_arg[STKTABLE_DT_HTTP_REQ_RATE].u, 1);
} }
} }
/* Increase the number of cumulated HTTP requests in the backend's tracked counters */ /* Increase the number of cumulated HTTP requests in the backend's tracked
* counters. We don't look up the session since it cannot happen in the bakcend.
*/
static void inline stream_inc_be_http_req_ctr(struct stream *s) static void inline stream_inc_be_http_req_ctr(struct stream *s)
{ {
void *ptr; void *ptr;
int i; int i;
for (i = 0; i < MAX_SESS_STKCTR; i++) { for (i = 0; i < MAX_SESS_STKCTR; i++) {
if (!stkctr_entry(&s->stkctr[i])) struct stkctr *stkctr = &s->stkctr[i];
if (!stkctr_entry(stkctr))
continue; continue;
if (!(stkctr_flags(&s->stkctr[i]) & STKCTR_TRACK_BACKEND)) if (!(stkctr_flags(&s->stkctr[i]) & STKCTR_TRACK_BACKEND))
continue; continue;
ptr = stktable_data_ptr(s->stkctr[i].table, stkctr_entry(&s->stkctr[i]), STKTABLE_DT_HTTP_REQ_CNT); ptr = stktable_data_ptr(stkctr->table, stkctr_entry(stkctr), STKTABLE_DT_HTTP_REQ_CNT);
if (ptr) if (ptr)
stktable_data_cast(ptr, http_req_cnt)++; stktable_data_cast(ptr, http_req_cnt)++;
ptr = stktable_data_ptr(s->stkctr[i].table, stkctr_entry(&s->stkctr[i]), STKTABLE_DT_HTTP_REQ_RATE); ptr = stktable_data_ptr(stkctr->table, stkctr_entry(stkctr), STKTABLE_DT_HTTP_REQ_RATE);
if (ptr) if (ptr)
update_freq_ctr_period(&stktable_data_cast(ptr, http_req_rate), update_freq_ctr_period(&stktable_data_cast(ptr, http_req_rate),
s->stkctr[i].table->data_arg[STKTABLE_DT_HTTP_REQ_RATE].u, 1); stkctr->table->data_arg[STKTABLE_DT_HTTP_REQ_RATE].u, 1);
} }
} }
@ -228,17 +237,22 @@ static void inline stream_inc_http_err_ctr(struct stream *s)
int i; int i;
for (i = 0; i < MAX_SESS_STKCTR; i++) { for (i = 0; i < MAX_SESS_STKCTR; i++) {
if (!stkctr_entry(&s->stkctr[i])) struct stkctr *stkctr = &s->stkctr[i];
continue;
ptr = stktable_data_ptr(s->stkctr[i].table, stkctr_entry(&s->stkctr[i]), STKTABLE_DT_HTTP_ERR_CNT); if (!stkctr_entry(stkctr)) {
stkctr = &s->sess->stkctr[i];
if (!stkctr_entry(stkctr))
continue;
}
ptr = stktable_data_ptr(stkctr->table, stkctr_entry(stkctr), STKTABLE_DT_HTTP_ERR_CNT);
if (ptr) if (ptr)
stktable_data_cast(ptr, http_err_cnt)++; stktable_data_cast(ptr, http_err_cnt)++;
ptr = stktable_data_ptr(s->stkctr[i].table, stkctr_entry(&s->stkctr[i]), STKTABLE_DT_HTTP_ERR_RATE); ptr = stktable_data_ptr(stkctr->table, stkctr_entry(stkctr), STKTABLE_DT_HTTP_ERR_RATE);
if (ptr) if (ptr)
update_freq_ctr_period(&stktable_data_cast(ptr, http_err_rate), update_freq_ctr_period(&stktable_data_cast(ptr, http_err_rate),
s->stkctr[i].table->data_arg[STKTABLE_DT_HTTP_ERR_RATE].u, 1); stkctr->table->data_arg[STKTABLE_DT_HTTP_ERR_RATE].u, 1);
} }
} }

View File

@ -454,18 +454,19 @@ int stream_complete(struct stream *s)
for (i = 0; i < MAX_SESS_STKCTR; i++) { for (i = 0; i < MAX_SESS_STKCTR; i++) {
void *ptr; void *ptr;
struct stkctr *stkctr = &sess->stkctr[i];
if (!stkctr_entry(&s->stkctr[i])) if (!stkctr_entry(stkctr))
continue; continue;
ptr = stktable_data_ptr(s->stkctr[i].table, stkctr_entry(&s->stkctr[i]), STKTABLE_DT_SESS_CNT); ptr = stktable_data_ptr(stkctr->table, stkctr_entry(stkctr), STKTABLE_DT_SESS_CNT);
if (ptr) if (ptr)
stktable_data_cast(ptr, sess_cnt)++; stktable_data_cast(ptr, sess_cnt)++;
ptr = stktable_data_ptr(s->stkctr[i].table, stkctr_entry(&s->stkctr[i]), STKTABLE_DT_SESS_RATE); ptr = stktable_data_ptr(stkctr->table, stkctr_entry(stkctr), STKTABLE_DT_SESS_RATE);
if (ptr) if (ptr)
update_freq_ctr_period(&stktable_data_cast(ptr, sess_rate), update_freq_ctr_period(&stktable_data_cast(ptr, sess_rate),
s->stkctr[i].table->data_arg[STKTABLE_DT_SESS_RATE].u, 1); stkctr->table->data_arg[STKTABLE_DT_SESS_RATE].u, 1);
} }
/* this part should be common with other protocols */ /* this part should be common with other protocols */
@ -807,21 +808,22 @@ void stream_process_counters(struct stream *s)
sess->listener->counters->bytes_in += bytes; sess->listener->counters->bytes_in += bytes;
for (i = 0; i < MAX_SESS_STKCTR; i++) { for (i = 0; i < MAX_SESS_STKCTR; i++) {
if (!stkctr_entry(&s->stkctr[i])) struct stkctr *stkctr = &s->stkctr[i];
continue;
ptr = stktable_data_ptr(s->stkctr[i].table, if (!stkctr_entry(stkctr)) {
stkctr_entry(&s->stkctr[i]), stkctr = &sess->stkctr[i];
STKTABLE_DT_BYTES_IN_CNT); if (!stkctr_entry(stkctr))
continue;
}
ptr = stktable_data_ptr(stkctr->table, stkctr_entry(stkctr), STKTABLE_DT_BYTES_IN_CNT);
if (ptr) if (ptr)
stktable_data_cast(ptr, bytes_in_cnt) += bytes; stktable_data_cast(ptr, bytes_in_cnt) += bytes;
ptr = stktable_data_ptr(s->stkctr[i].table, ptr = stktable_data_ptr(stkctr->table, stkctr_entry(stkctr), STKTABLE_DT_BYTES_IN_RATE);
stkctr_entry(&s->stkctr[i]),
STKTABLE_DT_BYTES_IN_RATE);
if (ptr) if (ptr)
update_freq_ctr_period(&stktable_data_cast(ptr, bytes_in_rate), update_freq_ctr_period(&stktable_data_cast(ptr, bytes_in_rate),
s->stkctr[i].table->data_arg[STKTABLE_DT_BYTES_IN_RATE].u, bytes); stkctr->table->data_arg[STKTABLE_DT_BYTES_IN_RATE].u, bytes);
} }
} }
@ -839,21 +841,22 @@ void stream_process_counters(struct stream *s)
sess->listener->counters->bytes_out += bytes; sess->listener->counters->bytes_out += bytes;
for (i = 0; i < MAX_SESS_STKCTR; i++) { for (i = 0; i < MAX_SESS_STKCTR; i++) {
if (!stkctr_entry(&s->stkctr[i])) struct stkctr *stkctr = &s->stkctr[i];
continue;
ptr = stktable_data_ptr(s->stkctr[i].table, if (!stkctr_entry(stkctr)) {
stkctr_entry(&s->stkctr[i]), stkctr = &sess->stkctr[i];
STKTABLE_DT_BYTES_OUT_CNT); if (!stkctr_entry(stkctr))
continue;
}
ptr = stktable_data_ptr(stkctr->table, stkctr_entry(stkctr), STKTABLE_DT_BYTES_OUT_CNT);
if (ptr) if (ptr)
stktable_data_cast(ptr, bytes_out_cnt) += bytes; stktable_data_cast(ptr, bytes_out_cnt) += bytes;
ptr = stktable_data_ptr(s->stkctr[i].table, ptr = stktable_data_ptr(stkctr->table, stkctr_entry(stkctr), STKTABLE_DT_BYTES_OUT_RATE);
stkctr_entry(&s->stkctr[i]),
STKTABLE_DT_BYTES_OUT_RATE);
if (ptr) if (ptr)
update_freq_ctr_period(&stktable_data_cast(ptr, bytes_out_rate), update_freq_ctr_period(&stktable_data_cast(ptr, bytes_out_rate),
s->stkctr[i].table->data_arg[STKTABLE_DT_BYTES_OUT_RATE].u, bytes); stkctr->table->data_arg[STKTABLE_DT_BYTES_OUT_RATE].u, bytes);
} }
} }
} }
@ -2890,12 +2893,14 @@ void stream_shutdown(struct stream *stream, int why)
* passed. When present, the currently tracked key is then looked up * passed. When present, the currently tracked key is then looked up
* in the specified table instead of the current table. The purpose is * in the specified table instead of the current table. The purpose is
* to be able to convery multiple values per key (eg: have gpc0 from * to be able to convery multiple values per key (eg: have gpc0 from
* multiple tables). * multiple tables). <strm> is allowed to be NULL, in which case only
* the session will be consulted.
*/ */
struct stkctr * struct stkctr *
smp_fetch_sc_stkctr(struct session *sess, struct stream *strm, const struct arg *args, const char *kw) smp_fetch_sc_stkctr(struct session *sess, struct stream *strm, const struct arg *args, const char *kw)
{ {
static struct stkctr stkctr; static struct stkctr stkctr;
struct stkctr *stkptr;
struct stksess *stksess; struct stksess *stksess;
unsigned int num = kw[2] - '0'; unsigned int num = kw[2] - '0';
int arg = 0; int arg = 0;
@ -2924,9 +2929,18 @@ smp_fetch_sc_stkctr(struct session *sess, struct stream *strm, const struct arg
/* Here, <num> contains the counter number from 0 to 9 for /* Here, <num> contains the counter number from 0 to 9 for
* the sc[0-9]_ form, or even higher using sc_(num) if needed. * the sc[0-9]_ form, or even higher using sc_(num) if needed.
* args[arg] is the first optional argument. * args[arg] is the first optional argument. We first lookup the
* ctr form the stream, then from the session if it was not there.
*/ */
stksess = stkctr_entry(&strm->stkctr[num]);
stkptr = &strm->stkctr[num];
if (!strm || !stkctr_entry(stkptr)) {
stkptr = &sess->stkctr[num];
if (!stkctr_entry(stkptr))
return NULL;
}
stksess = stkctr_entry(stkptr);
if (!stksess) if (!stksess)
return NULL; return NULL;
@ -2936,7 +2950,7 @@ smp_fetch_sc_stkctr(struct session *sess, struct stream *strm, const struct arg
stkctr_set_entry(&stkctr, stktable_lookup(stkctr.table, stksess)); stkctr_set_entry(&stkctr, stktable_lookup(stkctr.table, stksess));
return &stkctr; return &stkctr;
} }
return &strm->stkctr[num]; return stkptr;
} }
/* set return a boolean indicating if the requested stream counter is /* set return a boolean indicating if the requested stream counter is