[master] 6f2e1bc Request handling byte accounting
Martin Blix Grydeland
martin at varnish-software.com
Mon Mar 31 11:28:00 CEST 2014
commit 6f2e1bcd343a7a745ac01aa61e8ce0e66b3bb6cc
Author: Martin Blix Grydeland <martin at varnish-software.com>
Date: Fri Mar 28 11:25:38 2014 +0100
Request handling byte accounting
Counters show bytes received/transmitted, split between header and
body bytes.
SLT_ReqAcct logs per request counter values.
diff --git a/bin/varnishd/cache/cache.h b/bin/varnishd/cache/cache.h
index b793467..de7d895 100644
--- a/bin/varnishd/cache/cache.h
+++ b/bin/varnishd/cache/cache.h
@@ -228,9 +228,9 @@ struct http_conn {
/*--------------------------------------------------------------------*/
-struct acct {
+struct acct_req {
#define ACCT(foo) uint64_t foo;
-#include "tbl/acct_fields.h"
+#include "tbl/acct_fields_req.h"
#undef ACCT
};
@@ -654,9 +654,9 @@ struct req {
double d_ttl;
unsigned char wantbody;
- uint64_t req_bodybytes;
+ uint64_t req_bodybytes; /* Parsed req bodybytes */
- uint64_t resp_bodybytes;
+ uint64_t resp_hdrbytes; /* Scheduled resp hdrbytes */
uint16_t err_code;
const char *err_reason;
@@ -716,7 +716,7 @@ struct req {
struct vsl_log vsl[1];
/* Temporary accounting */
- struct acct acct_req;
+ struct acct_req acct;
/* Synth content in vcl_error */
struct vsb *synth_body;
@@ -847,6 +847,7 @@ int HTTP1_CacheReqBody(struct req *req, ssize_t maxsize);
int HTTP1_IterateReqBody(struct req *req, req_body_iter_f *func, void *priv);
/* cache_http1_deliver.c */
+unsigned V1D_FlushReleaseAcct(struct req *req);
void V1D_Deliver(struct req *);
void V1D_Deliver_Synth(struct req *req);
@@ -892,6 +893,7 @@ VDP_pop(struct req *req, vdp_bytes *func)
/* cache_req_fsm.c [CNT] */
enum req_fsm_nxt CNT_Request(struct worker *, struct req *);
+void CNT_AcctLogCharge(struct dstat *, struct req *);
/* cache_cli.c [CLI] */
void CLI_Init(void);
@@ -1099,14 +1101,13 @@ void WRW_Chunked(const struct worker *w);
void WRW_EndChunk(const struct worker *w);
void WRW_Reserve(struct worker *w, int *fd, struct vsl_log *, double t0);
unsigned WRW_Flush(const struct worker *w);
-unsigned WRW_FlushRelease(struct worker *w);
+unsigned WRW_FlushRelease(struct worker *w, ssize_t *pacc);
unsigned WRW_Write(const struct worker *w, const void *ptr, int len);
unsigned WRW_WriteH(const struct worker *w, const txt *hh, const char *suf);
/* cache_session.c [SES] */
void SES_Close(struct sess *sp, enum sess_close reason);
void SES_Delete(struct sess *sp, enum sess_close reason, double now);
-void SES_Charge(struct worker *, struct req *);
struct sesspool *SES_NewPool(struct pool *pp, unsigned pool_no);
void SES_DeletePool(struct sesspool *sp);
int SES_ScheduleReq(struct req *);
diff --git a/bin/varnishd/cache/cache_cli.c b/bin/varnishd/cache/cache_cli.c
index 8aa022b..ca9da16 100644
--- a/bin/varnishd/cache/cache_cli.c
+++ b/bin/varnishd/cache/cache_cli.c
@@ -126,7 +126,7 @@ cli_debug_sizeof(struct cli *cli, const char * const *av, void *priv)
SZOF(struct ws);
SZOF(struct http);
SZOF(struct http_conn);
- SZOF(struct acct);
+ SZOF(struct acct_req);
SZOF(struct worker);
SZOF(struct wrk_accept);
SZOF(struct storage);
diff --git a/bin/varnishd/cache/cache_esi_deliver.c b/bin/varnishd/cache/cache_esi_deliver.c
index b1c3362..dbbe7b1 100644
--- a/bin/varnishd/cache/cache_esi_deliver.c
+++ b/bin/varnishd/cache/cache_esi_deliver.c
@@ -55,7 +55,7 @@ ved_include(struct req *preq, const char *src, const char *host)
if (preq->esi_level >= cache_param->max_esi_depth)
return;
- (void)WRW_FlushRelease(wrk);
+ (void)V1D_FlushReleaseAcct(preq);
/* Take a workspace snapshot */
wrk_ws_wm = WS_Snapshot(wrk->aws); /* XXX ? */
@@ -120,9 +120,17 @@ ved_include(struct req *preq, const char *src, const char *host)
AZ(req->wrk);
(void)usleep(10000);
}
+ AN(WRW_IsReleased(wrk));
- /* Make sure the VSL id has been released */
- AZ(req->vsl->wid);
+ /* Flush and release the log */
+ AN(req->vsl->wid);
+ VSLb(req->vsl, SLT_End, "%s", "");
+ VSL_Flush(req->vsl, 0);
+ req->vsl->wid = 0;
+
+ /* Charge the transmitted body byte counts to the parent request */
+ preq->acct.resp_bodybytes += req->acct.resp_bodybytes;
+ req->acct.resp_bodybytes = 0;
/* Reset the workspace */
WS_Reset(wrk->aws, wrk_ws_wm); /* XXX ? */
diff --git a/bin/varnishd/cache/cache_hash.c b/bin/varnishd/cache/cache_hash.c
index 6cb2de8..1530937 100644
--- a/bin/varnishd/cache/cache_hash.c
+++ b/bin/varnishd/cache/cache_hash.c
@@ -501,7 +501,6 @@ HSH_Lookup(struct req *req, struct objcore **ocp, struct objcore **bocp,
}
wrk->stats.busy_sleep++;
- SES_Charge(wrk, req);
/*
* The objhead reference transfers to the sess, we get it
* back when the sess comes off the waiting list and
diff --git a/bin/varnishd/cache/cache_http1_deliver.c b/bin/varnishd/cache/cache_http1_deliver.c
index e82ed31..5e99668 100644
--- a/bin/varnishd/cache/cache_http1_deliver.c
+++ b/bin/varnishd/cache/cache_http1_deliver.c
@@ -46,8 +46,6 @@ v1d_bytes(struct req *req, enum vdp_action act, const void *ptr, ssize_t len)
if (len > 0)
wl = WRW_Write(req->wrk, ptr, len);
- if (wl > 0)
- req->acct_req.bodybytes += wl;
if (act > VDP_NULL && WRW_Flush(req->wrk))
return (-1);
if (len != wl)
@@ -193,6 +191,33 @@ v1d_WriteDirObj(struct req *req)
return (ois);
}
+/*--------------------------------------------------------------------
+ * V1D_FlushReleaseAcct()
+ * Call WRW_FlushRelease on the worker and update the requests
+ * byte accounting with the number of bytes transmitted
+ *
+ * Returns the return value from WRW_FlushRelease()
+ */
+unsigned
+V1D_FlushReleaseAcct(struct req *req)
+{
+ unsigned u;
+ ssize_t txcnt = 0, hdrbytes;
+
+ CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
+ CHECK_OBJ_NOTNULL(req->wrk, WORKER_MAGIC);
+ u = WRW_FlushRelease(req->wrk, &txcnt);
+ if (req->acct.resp_hdrbytes < req->resp_hdrbytes) {
+ hdrbytes = req->resp_hdrbytes - req->acct.resp_hdrbytes;
+ if (hdrbytes > txcnt)
+ hdrbytes = txcnt;
+ } else
+ hdrbytes = 0;
+ req->acct.resp_hdrbytes += hdrbytes;
+ req->acct.resp_bodybytes += txcnt - hdrbytes;
+ return (u);
+}
+
void
V1D_Deliver(struct req *req)
{
@@ -288,7 +313,7 @@ V1D_Deliver(struct req *req)
* Send HTTP protocol header, unless interior ESI object
*/
if (!(req->res_mode & RES_ESI_CHILD))
- req->acct_req.hdrbytes += HTTP1_Write(req->wrk, req->resp, 1);
+ req->resp_hdrbytes += HTTP1_Write(req->wrk, req->resp, 1);
if (req->res_mode & RES_CHUNKED)
WRW_Chunked(req->wrk);
@@ -320,7 +345,7 @@ V1D_Deliver(struct req *req)
!(req->res_mode & RES_ESI_CHILD))
WRW_EndChunk(req->wrk);
- if ((WRW_FlushRelease(req->wrk) || ois != OIS_DONE) && req->sp->fd >= 0)
+ if ((V1D_FlushReleaseAcct(req) || ois != OIS_DONE) && req->sp->fd >= 0)
SES_Close(req->sp, SC_REM_CLOSE);
}
@@ -395,7 +420,7 @@ V1D_Deliver_Synth(struct req *req)
* Send HTTP protocol header, unless interior ESI object
*/
if (!(req->res_mode & RES_ESI_CHILD))
- req->acct_req.hdrbytes += HTTP1_Write(req->wrk, req->resp, 1);
+ req->resp_hdrbytes += HTTP1_Write(req->wrk, req->resp, 1);
if (req->res_mode & RES_CHUNKED)
WRW_Chunked(req->wrk);
@@ -418,6 +443,6 @@ V1D_Deliver_Synth(struct req *req)
if (req->res_mode & RES_CHUNKED && !(req->res_mode & RES_ESI_CHILD))
WRW_EndChunk(req->wrk);
- if (WRW_FlushRelease(req->wrk) && req->sp->fd >= 0)
+ if (V1D_FlushReleaseAcct(req) && req->sp->fd >= 0)
SES_Close(req->sp, SC_REM_CLOSE);
}
diff --git a/bin/varnishd/cache/cache_http1_fetch.c b/bin/varnishd/cache/cache_http1_fetch.c
index 317bfcb..82dcab6 100644
--- a/bin/varnishd/cache/cache_http1_fetch.c
+++ b/bin/varnishd/cache/cache_http1_fetch.c
@@ -330,7 +330,7 @@ V1F_fetch_hdr(struct worker *wrk, struct busyobj *bo, struct req *req)
}
}
- if (WRW_FlushRelease(wrk) || i != 0) {
+ if (WRW_FlushRelease(wrk, NULL) || i != 0) {
VSLb(bo->vsl, SLT_FetchError, "backend write error: %d (%s)",
errno, strerror(errno));
VSLb_ts_busyobj(bo, "Bereq", W_TIM_real(wrk));
diff --git a/bin/varnishd/cache/cache_http1_fsm.c b/bin/varnishd/cache/cache_http1_fsm.c
index 37ed35a..a46534c 100644
--- a/bin/varnishd/cache/cache_http1_fsm.c
+++ b/bin/varnishd/cache/cache_http1_fsm.c
@@ -126,6 +126,7 @@ http1_wait(struct sess *sp, struct worker *wrk, struct req *req)
VSLb_ts_req(req, "Start", now);
VSLb_ts_req(req, "Req", now);
req->t_req = req->t_prev;
+ req->acct.req_hdrbytes += Tlen(req->htc->rxbuf);
return (REQ_FSM_MORE);
} else if (hs == HTTP1_ERROR_EOF) {
why = SC_REM_CLOSE;
@@ -161,6 +162,8 @@ http1_wait(struct sess *sp, struct worker *wrk, struct req *req)
}
}
}
+ req->acct.req_hdrbytes += Tlen(req->htc->rxbuf);
+ CNT_AcctLogCharge(&wrk->stats, req);
SES_ReleaseReq(req);
assert(why != SC_NULL);
SES_Delete(sp, why, now);
@@ -200,20 +203,28 @@ http1_cleanup(struct sess *sp, struct worker *wrk, struct req *req)
req->vcl = NULL;
}
+ /* Charge and log byte counters */
+ AN(req->vsl->wid);
+ CNT_AcctLogCharge(&wrk->stats, req);
+ req->req_bodybytes = 0;
+ req->resp_hdrbytes = 0;
+
+ /* Nuke the VXID. http1_dissect() will allocate a new one when
+ necessary */
+ VSLb(req->vsl, SLT_End, "%s", "");
+ VSL_Flush(req->vsl, 0);
+ req->vsl->wid = 0;
+
if (!isnan(req->t_prev) && req->t_prev > 0.)
sp->t_idle = req->t_prev;
else
sp->t_idle = W_TIM_real(wrk);
- VSL_Flush(req->vsl, 0);
req->t_first = NAN;
req->t_prev = NAN;
req->t_req = NAN;
req->req_body_status = REQ_BODY_INIT;
- // req->req_bodybytes = 0;
- req->resp_bodybytes = 0;
-
req->hash_always_miss = 0;
req->hash_ignore_busy = 0;
@@ -235,10 +246,17 @@ http1_cleanup(struct sess *sp, struct worker *wrk, struct req *req)
WS_Reset(wrk->aws, NULL);
if (HTTP1_Reinit(req->htc) == HTTP1_COMPLETE) {
+ AZ(req->vsl->wid);
+ req->vsl->wid = VXID_Get(&wrk->vxid_pool) | VSL_CLIENTMARKER;
+ VSLb(req->vsl, SLT_Begin, "req %u rxreq",
+ req->sp->vxid & VSL_IDENTMASK);
+ VSL(SLT_Link, req->sp->vxid, "req %u rxreq",
+ req->vsl->wid & VSL_IDENTMASK);
VSLb_ts_req(req, "Start", sp->t_idle);
VSLb_ts_req(req, "Req", sp->t_idle);
req->t_req = req->t_prev;
wrk->stats.sess_pipeline++;
+ req->acct.req_hdrbytes += Tlen(req->htc->rxbuf);
return (SESS_DONE_RET_START);
} else {
if (Tlen(req->htc->rxbuf))
@@ -285,6 +303,7 @@ http1_dissect(struct worker *wrk, struct req *req)
const char *r_411 = "HTTP/1.1 411 Length Required\r\n\r\n";
const char *r_417 = "HTTP/1.1 417 Expectation Failed\r\n\r\n";
char *p;
+ ssize_t r;
CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
@@ -314,7 +333,9 @@ http1_dissect(struct worker *wrk, struct req *req)
/* If we could not even parse the request, just close */
if (req->err_code != 0) {
wrk->stats.client_req_400++;
- (void)write(req->sp->fd, r_400, strlen(r_400));
+ r = write(req->sp->fd, r_400, strlen(r_400));
+ if (r > 0)
+ req->acct.resp_hdrbytes += r;
SES_Close(req->sp, SC_RX_JUNK);
return (REQ_FSM_DONE);
}
@@ -326,7 +347,9 @@ http1_dissect(struct worker *wrk, struct req *req)
if (req->req_body_status == REQ_BODY_FAIL) {
wrk->stats.client_req_411++;
- (void)write(req->sp->fd, r_411, strlen(r_411));
+ r = write(req->sp->fd, r_411, strlen(r_411));
+ if (r > 0)
+ req->acct.resp_hdrbytes += r;
SES_Close(req->sp, SC_RX_JUNK);
return (REQ_FSM_DONE);
}
@@ -335,21 +358,25 @@ http1_dissect(struct worker *wrk, struct req *req)
if (strcasecmp(p, "100-continue")) {
wrk->stats.client_req_417++;
req->err_code = 417;
- (void)write(req->sp->fd, r_417, strlen(r_417));
+ r = write(req->sp->fd, r_417, strlen(r_417));
+ if (r > 0)
+ req->resp_hdrbytes += r;
SES_Close(req->sp, SC_RX_JUNK);
return (REQ_FSM_DONE);
}
- if (strlen(r_100) != write(req->sp->fd, r_100, strlen(r_100))) {
- // XXX: stats counter ?
+ r = write(req->sp->fd, r_100, strlen(r_100));
+ if (r > 0)
+ req->acct.resp_hdrbytes += r;
+ if (r != strlen(r_100)) {
SES_Close(req->sp, SC_REM_CLOSE);
return (REQ_FSM_DONE);
}
}
wrk->stats.client_req++;
+ wrk->stats.s_req++;
AZ(req->err_code);
- req->acct_req.req++;
req->ws_req = WS_Snapshot(req->ws);
req->doclose = http_DoConnection(req->http);
@@ -475,6 +502,7 @@ http1_iter_req_body(struct req *req, void *buf, ssize_t len)
}
req->h1.bytes_done += len;
req->h1.bytes_yet = req->req_bodybytes - req->h1.bytes_done;
+ req->acct.req_bodybytes += len;
return (len);
}
diff --git a/bin/varnishd/cache/cache_pipe.c b/bin/varnishd/cache/cache_pipe.c
index 1a0a44f..7d77096 100644
--- a/bin/varnishd/cache/cache_pipe.c
+++ b/bin/varnishd/cache/cache_pipe.c
@@ -66,6 +66,7 @@ PipeRequest(struct req *req, struct busyobj *bo)
struct worker *wrk;
struct pollfd fds[2];
int i;
+ ssize_t txcnt;
CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
CHECK_OBJ_NOTNULL(req->sp, SESS_MAGIC);
@@ -80,14 +81,13 @@ PipeRequest(struct req *req, struct busyobj *bo)
(void)VTCP_blocking(vc->fd);
WRW_Reserve(wrk, &vc->fd, bo->vsl, req->t_req);
- req->acct_req.hdrbytes += HTTP1_Write(wrk, bo->bereq, 0);
+ (void)HTTP1_Write(wrk, bo->bereq, 0);
if (req->htc->pipeline.b != NULL)
- req->acct_req.bodybytes +=
- WRW_Write(wrk, req->htc->pipeline.b,
+ (void)WRW_Write(wrk, req->htc->pipeline.b,
Tlen(req->htc->pipeline));
- i = WRW_FlushRelease(wrk);
+ i = WRW_FlushRelease(wrk, &txcnt);
VSLb_ts_req(req, "Pipe", W_TIM_real(wrk));
diff --git a/bin/varnishd/cache/cache_req_fsm.c b/bin/varnishd/cache/cache_req_fsm.c
index 090e0b6..8888226 100644
--- a/bin/varnishd/cache/cache_req_fsm.c
+++ b/bin/varnishd/cache/cache_req_fsm.c
@@ -200,7 +200,7 @@ cnt_synth(struct worker *wrk, struct req *req)
CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
- req->acct_req.synth++;
+ wrk->stats.s_synth++;
HTTP_Setup(req->resp, req->ws, req->vsl, SLT_RespMethod);
h = req->resp;
@@ -281,7 +281,7 @@ cnt_fetch(struct worker *wrk, struct req *req)
CHECK_OBJ_NOTNULL(req->objcore, OBJCORE_MAGIC);
AZ(req->obj);
- req->acct_req.fetch++;
+ wrk->stats.s_fetch++;
(void)HTTP1_DiscardReqBody(req);
if (req->objcore->flags & OC_F_FAILED) {
@@ -554,7 +554,7 @@ cnt_pass(struct worker *wrk, struct req *req)
req->req_step = R_STP_RESTART;
break;
case VCL_RET_FETCH:
- req->acct_req.pass++;
+ wrk->stats.s_pass++;
req->objcore = HSH_Private(wrk);
CHECK_OBJ_NOTNULL(req->objcore, OBJCORE_MAGIC);
VBF_Fetch(wrk, req, req->objcore, NULL, VBF_PASS);
@@ -593,7 +593,7 @@ cnt_pipe(struct worker *wrk, struct req *req)
CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
CHECK_OBJ_NOTNULL(req->vcl, VCL_CONF_MAGIC);
- req->acct_req.pipe++;
+ wrk->stats.s_pipe++;
bo = VBO_GetBusyObj(wrk, req);
HTTP_Setup(bo->bereq, bo->ws, bo->vsl, SLT_BereqMethod);
http_FilterReq(bo->bereq, req->http, 0); // XXX: 0 ?
@@ -897,33 +897,43 @@ CNT_Request(struct worker *wrk, struct req *req)
}
if (nxt == REQ_FSM_DONE) {
/* XXX: Workaround for pipe */
- if (req->sp->fd >= 0) {
- VSLb(req->vsl, SLT_Length, "%ju",
- (uintmax_t)req->resp_bodybytes);
- }
while (!VTAILQ_EMPTY(&req->body)) {
st = VTAILQ_FIRST(&req->body);
VTAILQ_REMOVE(&req->body, st, list);
STV_free(st);
}
-
- /* done == 2 was charged by cache_hash.c */
- SES_Charge(wrk, req);
-
- /*
- * Nuke the VXID, cache_http1_fsm.c::http1_dissect() will
- * allocate a new one when necessary.
- */
- VSLb(req->vsl, SLT_End, "%s", "");
- req->vsl->wid = 0;
- req->wrk = NULL;
}
-
+ req->wrk = NULL;
assert(WRW_IsReleased(wrk));
return (nxt);
}
+void
+CNT_AcctLogCharge(struct dstat *ds, struct req *req)
+{
+ struct acct_req *a;
+
+ AN(ds);
+ CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
+
+ a = &req->acct;
+
+ VSLb(req->vsl, SLT_ReqAcct, "%ju %ju %ju %ju %ju %ju",
+ (uintmax_t)a->req_hdrbytes,
+ (uintmax_t)a->req_bodybytes,
+ (uintmax_t)(a->req_hdrbytes + a->req_bodybytes),
+ (uintmax_t)a->resp_hdrbytes,
+ (uintmax_t)a->resp_bodybytes,
+ (uintmax_t)(a->resp_hdrbytes + a->resp_bodybytes));
+
+#define ACCT(foo) \
+ ds->s_##foo += a->foo; \
+ a->foo = 0;
+#include "tbl/acct_fields_req.h"
+#undef ACCT
+}
+
/*
DOT }
*/
diff --git a/bin/varnishd/cache/cache_session.c b/bin/varnishd/cache/cache_session.c
index 8059c83..0c5d2f9 100644
--- a/bin/varnishd/cache/cache_session.c
+++ b/bin/varnishd/cache/cache_session.c
@@ -62,31 +62,6 @@ struct sesspool {
};
/*--------------------------------------------------------------------
- * Charge statistics from worker to request and session.
- */
-
-void
-SES_Charge(struct worker *wrk, struct req *req)
-{
- struct sess *sp;
- struct acct *a;
-
- CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
- CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
- sp = req->sp;
- CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
-
- a = &req->acct_req;
- req->resp_bodybytes += a->bodybytes;
-
-#define ACCT(foo) \
- wrk->stats.s_##foo += a->foo; \
- a->foo = 0;
-#include "tbl/acct_fields.h"
-#undef ACCT
-}
-
-/*--------------------------------------------------------------------
* Get a new session, preferably by recycling an already ready one
*
* Layout is:
@@ -395,6 +370,9 @@ SES_GetReq(struct worker *wrk, struct sess *sp)
WS_Init(req->ws, "req", p, e - p);
+ req->req_bodybytes = 0;
+ req->resp_hdrbytes = 0;
+
req->t_first = NAN;
req->t_prev = NAN;
req->t_req = NAN;
@@ -411,10 +389,14 @@ SES_ReleaseReq(struct req *req)
struct sesspool *pp;
CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
- AZ(req->vcl);
-#define ACCT(foo) AZ(req->acct_req.foo);
-#include "tbl/acct_fields.h"
+
+ /* Make sure the request counters have all been zeroed */
+#define ACCT(foo) \
+ AZ(req->acct.foo);
+#include "tbl/acct_fields_req.h"
#undef ACCT
+
+ AZ(req->vcl);
sp = req->sp;
CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
pp = sp->sesspool;
diff --git a/bin/varnishd/cache/cache_wrw.c b/bin/varnishd/cache/cache_wrw.c
index adf2f11..a418ea0 100644
--- a/bin/varnishd/cache/cache_wrw.c
+++ b/bin/varnishd/cache/cache_wrw.c
@@ -58,6 +58,7 @@ struct wrw {
unsigned ciov; /* Chunked header marker */
double t0;
struct vsl_log *vsl;
+ ssize_t cnt; /* Flushed byte count */
};
/*--------------------------------------------------------------------
@@ -101,7 +102,7 @@ WRW_Reserve(struct worker *wrk, int *fd, struct vsl_log *vsl, double t0)
}
static void
-WRW_Release(struct worker *wrk)
+wrw_release(struct worker *wrk, ssize_t *pacc)
{
struct wrw *wrw;
@@ -109,6 +110,8 @@ WRW_Release(struct worker *wrk)
wrw = wrk->wrw;
wrk->wrw = NULL;
CHECK_OBJ_NOTNULL(wrw, WRW_MAGIC);
+ if (pacc != NULL)
+ *pacc += wrw->cnt;
WS_Release(wrk->aws, 0);
WS_Reset(wrk->aws, NULL);
}
@@ -171,6 +174,8 @@ WRW_Flush(const struct worker *wrk)
}
i = writev(*wrw->wfd, wrw->iov, wrw->niov);
+ if (i > 0)
+ wrw->cnt += i;
while (i != wrw->liov && i > 0) {
/* Remove sent data from start of I/O vector,
* then retry; we hit a timeout, but some data
@@ -195,6 +200,8 @@ WRW_Flush(const struct worker *wrk)
wrw_prune(wrw, i);
i = writev(*wrw->wfd, wrw->iov, wrw->niov);
+ if (i > 0)
+ wrw->cnt += i;
}
if (i <= 0) {
wrw->werr++;
@@ -212,14 +219,14 @@ WRW_Flush(const struct worker *wrk)
}
unsigned
-WRW_FlushRelease(struct worker *wrk)
+WRW_FlushRelease(struct worker *wrk, ssize_t *pacc)
{
unsigned u;
CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
AN(wrk->wrw->wfd);
u = WRW_Flush(wrk);
- WRW_Release(wrk);
+ wrw_release(wrk, pacc);
return (u);
}
diff --git a/bin/varnishtest/tests/l00002.vtc b/bin/varnishtest/tests/l00002.vtc
new file mode 100644
index 0000000..0106324
--- /dev/null
+++ b/bin/varnishtest/tests/l00002.vtc
@@ -0,0 +1,108 @@
+varnishtest "Test request byte counters"
+
+server s1 {
+ rxreq
+ expect req.url == "/1"
+ txresp -bodylen 1000
+
+ rxreq
+ expect req.url == "/2"
+ txresp -bodylen 2000
+} -start
+
+varnish v1 -vcl+backend {
+ sub vcl_deliver {
+ unset resp.http.date;
+ unset resp.http.age;
+ unset resp.http.via;
+ unset resp.http.x-varnish;
+ }
+} -start
+
+# Request (1001):
+# GET /1 HTTP/1.1\r\n 17 bytes
+# Content-Length: 4\r\n 19 bytes
+# \r\n 2 bytes
+# Total: 38 bytes
+# Response:
+# HTTP/1.1 200 Ok\r\n 17 bytes
+# Content-Length: 1000\r\n 22 bytes
+# Connection: keep-alive\r\n 24 bytes
+# Accept-Ranges: bytes\r\n 22 bytes
+# \r\n 2 bytes
+# Total: 87 bytes
+
+# Request (1003):
+# GET /2 HTTP/1.1\r\n 17 bytes
+# \r\n 2 bytes
+# Total: 19 bytes
+# Response:
+# HTTP/1.1 200 Ok\r\n 17 bytes
+# Content-Length: 2000\r\n 22 bytes
+# Connection: keep-alive\r\n 24 bytes
+# Accept-Ranges: bytes\r\n 22 bytes
+# \r\n 2 bytes
+# Total: 87 bytes
+
+# Request (1005):
+# GET /2 HTTP/1.1\r\n 17 bytes
+# \r\n 2 bytes
+# Total: 19 bytes
+# Response:
+# HTTP/1.1 200 Ok\r\n 17 bytes
+# Content-Length: 2000\r\n 22 bytes
+# Connection: keep-alive\r\n 24 bytes
+# Accept-Ranges: bytes\r\n 22 bytes
+# \r\n 2 bytes
+# Total: 87 bytes
+
+# Request (1006):
+# GET\r\n 5 bytes
+# \r\n 2 bytes
+# Total: 7 bytes
+# Response:
+# HTTP/1.1 400 Bad Request\r\n 26 bytes
+# \r\n 2 bytes
+# Total: 28 bytes
+logexpect l1 -v v1 -g request {
+ expect 0 1001 Begin "^req .* rxreq"
+ expect * = ReqAcct "^38 4 42 87 1000 1087$"
+ expect 0 = End
+ expect 0 1002 Begin "^bereq "
+ expect * = End
+ expect 0 1003 Begin "^req .* rxreq"
+ expect * = ReqAcct "^19 0 19 87 2000 2087$"
+ expect 0 = End
+ expect 0 1004 Begin "^bereq"
+ expect * = End
+ expect 0 1005 Begin "^req .* rxreq"
+ expect * = ReqAcct "^19 0 19 87 2000 2087$"
+ expect 0 = End
+ expect 0 1006 Begin "^req .* rxreq"
+ expect * = ReqAcct "^7 0 7 28 0 28$"
+ expect 0 = End
+} -start
+
+# Request 1001
+client c1 {
+ txreq -url "/1" -body "asdf"
+ rxresp
+ expect resp.status == 200
+
+ send "GET /2 HTTP/1.1\r\n\r\nGET /2 HTTP/1.1\r\n\r\n"
+ rxresp
+ expect resp.status == 200
+ rxresp
+ expect resp.status == 200
+
+ send "GET\r\n\r\n"
+ rxresp
+ expect resp.status == 400
+} -run
+
+logexpect l1 -wait
+
+varnish v1 -expect s_req_hdrbytes == 83
+varnish v1 -expect s_req_bodybytes == 4
+varnish v1 -expect s_resp_hdrbytes == 289
+varnish v1 -expect s_resp_bodybytes == 5000
diff --git a/include/Makefile.am b/include/Makefile.am
index 3813836..e996fc0 100644
--- a/include/Makefile.am
+++ b/include/Makefile.am
@@ -2,7 +2,7 @@
# API headers
nobase_pkginclude_HEADERS = \
- tbl/acct_fields.h \
+ tbl/acct_fields_req.h \
tbl/backend_poll.h \
tbl/ban_vars.h \
tbl/bo_flags.h \
diff --git a/include/tbl/acct_fields.h b/include/tbl/acct_fields.h
deleted file mode 100644
index ac205a7..0000000
--- a/include/tbl/acct_fields.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*-
- * Copyright (c) 2008 Verdens Gang AS
- * Copyright (c) 2008-2009 Varnish Software AS
- * All rights reserved.
- *
- * Author: Poul-Henning Kamp <phk at phk.freebsd.dk>
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * These are the stats we keep track of per session.
- * SES_Charge() sums them into wrk->stats
- * NB: Remember to mark those in vsc_fields.h to be included in struct dstat.
- */
-
-ACCT(req)
-ACCT(pipe)
-ACCT(pass)
-ACCT(fetch)
-ACCT(synth)
-ACCT(hdrbytes)
-ACCT(bodybytes)
diff --git a/include/tbl/acct_fields_req.h b/include/tbl/acct_fields_req.h
new file mode 100644
index 0000000..a1759f5
--- /dev/null
+++ b/include/tbl/acct_fields_req.h
@@ -0,0 +1,36 @@
+/*-
+ * Copyright (c) 2008 Verdens Gang AS
+ * Copyright (c) 2008-2014 Varnish Software AS
+ * All rights reserved.
+ *
+ * Author: Poul-Henning Kamp <phk at phk.freebsd.dk>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * These are the stats we keep track of per request.
+ * NB: Remember to mark those in vsc_fields.h to be included in struct dstat.
+ */
+
+ACCT(req_hdrbytes)
+ACCT(req_bodybytes)
+ACCT(resp_hdrbytes)
+ACCT(resp_bodybytes)
diff --git a/include/tbl/vsc_f_main.h b/include/tbl/vsc_f_main.h
index 3874ec1..859a2eb 100644
--- a/include/tbl/vsc_f_main.h
+++ b/include/tbl/vsc_f_main.h
@@ -384,13 +384,21 @@ VSC_F(s_synth, uint64_t, 1, 'a', info,
"Total synth",
""
)
-VSC_F(s_hdrbytes, uint64_t, 1, 'a', info,
- "Total header bytes",
- ""
+VSC_F(s_req_hdrbytes, uint64_t, 1, 'a', info,
+ "Request header bytes",
+ "Total request header bytes received"
)
-VSC_F(s_bodybytes, uint64_t, 1, 'a', info,
- "Total body bytes",
- ""
+VSC_F(s_req_bodybytes, uint64_t, 1, 'a', info,
+ "Request body bytes",
+ "Total request body bytes received"
+)
+VSC_F(s_resp_hdrbytes, uint64_t, 1, 'a', info,
+ "Response header bytes",
+ "Total response header bytes transmitted"
+)
+VSC_F(s_resp_bodybytes, uint64_t, 1, 'a', info,
+ "Reponse body bytes",
+ "Total response body bytes transmitted"
)
VSC_F(sess_closed, uint64_t, 1, 'a', info,
diff --git a/include/tbl/vsl_tags.h b/include/tbl/vsl_tags.h
index 10a3a15..252b859 100644
--- a/include/tbl/vsl_tags.h
+++ b/include/tbl/vsl_tags.h
@@ -474,4 +474,18 @@ SLTM(Timestamp, 0, "Timing information",
"\n"
)
+SLTM(ReqAcct, 0, "Request handling byte counts",
+ "Contains byte counts for the request handling.\n\n"
+ "The format is::\n\n"
+ "\t%d %d %d %d %d %d\n"
+ "\t| | | | | |\n"
+ "\t| | | | | +- Total bytes transmitted\n"
+ "\t| | | | +---- Body bytes transmitted\n"
+ "\t| | | +------- Header bytes transmitted\n"
+ "\t| | +---------- Total bytes received\n"
+ "\t| +------------- Body bytes received\n"
+ "\t+---------------- Header bytes received\n"
+ "\n"
+)
+
#undef NODEF_NOTICE
More information about the varnish-commit
mailing list