diff --git a/agent_stats.c b/agent_stats.c index e88d6b3d..4bdafbaa 100644 --- a/agent_stats.c +++ b/agent_stats.c @@ -647,6 +647,15 @@ static void proxy_stats_dump_pstd_stats(ADD_STAT add_stats, "%llu", (long long unsigned int) pstats->err_upstream_write_prep); APPEND_PREFIX_STAT("err_downstream_write_prep", "%llu", (long long unsigned int) pstats->err_downstream_write_prep); + APPEND_PREFIX_STAT("tot_cmd_time", + "%llu", (long long unsigned int) pstats->tot_cmd_time); + APPEND_PREFIX_STAT("tot_cmd_count", + "%llu", (long long unsigned int) pstats->tot_cmd_count); + APPEND_PREFIX_STAT("tot_local_cmd_time", + "%llu", (long long unsigned int) pstats->tot_local_cmd_time); + APPEND_PREFIX_STAT("tot_local_cmd_count", + "%llu", (long long unsigned int) pstats->tot_local_cmd_count); + } static void proxy_stats_dump_stats_cmd(ADD_STAT add_stats, conn *c, @@ -1267,6 +1276,11 @@ static void add_proxy_stats(proxy_stats *agg, proxy_stats *x) { agg->err_oom += x->err_oom; agg->err_upstream_write_prep += x->err_upstream_write_prep; agg->err_downstream_write_prep += x->err_downstream_write_prep; + + agg->tot_cmd_time += x->tot_cmd_time; + agg->tot_cmd_count += x->tot_cmd_count; + agg->tot_local_cmd_time += x->tot_local_cmd_time; + agg->tot_local_cmd_count += x->tot_local_cmd_count; } static void add_stats_cmd(proxy_stats_cmd *agg, @@ -1545,6 +1559,16 @@ void map_pstd_foreach_emit(const void *k, more_stat("err_downstream_write_prep", pstd->stats.err_downstream_write_prep); + more_stat("tot_cmd_time", + pstd->stats.tot_cmd_time); + more_stat("tot_cmd_count", + pstd->stats.tot_cmd_count); + + more_stat("tot_local_cmd_time", + pstd->stats.tot_local_cmd_time); + more_stat("tot_local_cmd_count", + pstd->stats.tot_local_cmd_count); + snprintf(buf_key, sizeof(buf_key), "%s:stats_cmd_", name); emit_proxy_stats_cmd(emit->result, buf_key, "%s_%s_%s", pstd->stats_cmd); } diff --git a/check_moxi_agent.c b/check_moxi_agent.c index e2f698c0..68548722 100644 --- a/check_moxi_agent.c +++ b/check_moxi_agent.c @@ -173,7 +173,11 @@ struct field_description proxy_stats_description[] = { describe_field(struct proxy_stats, tot_optimize_sets), describe_field(struct proxy_stats, err_oom), describe_field(struct proxy_stats, err_upstream_write_prep), - describe_field(struct proxy_stats, err_downstream_write_prep) + describe_field(struct proxy_stats, err_downstream_write_prep), + describe_field(struct proxy_stats, tot_cmd_time), + describe_field(struct proxy_stats, tot_cmd_count), + describe_field(struct proxy_stats, tot_local_cmd_time), + describe_field(struct proxy_stats, tot_local_cmd_count) }; struct field_description proxy_stats_cmd_description[] = { diff --git a/cproxy.c b/cproxy.c index 337fc90e..bdfb1d2b 100644 --- a/cproxy.c +++ b/cproxy.c @@ -2942,10 +2942,33 @@ void cproxy_upstream_state_change(conn *c, enum conn_states next_state) { if (ptd != NULL) { if (c->state == conn_pause) { ptd->stats.stats.tot_upstream_unpaused++; + c->cmd_unpaused = true; } if (next_state == conn_pause) { ptd->stats.stats.tot_upstream_paused++; } + + if (next_state == conn_parse_cmd && c->cmd_arrive_time == 0) { + c->cmd_unpaused = false; + c->hit_local = false; + c->cmd_arrive_time = usec_now(); + } + + if (next_state == conn_closing || next_state == conn_new_cmd) { + uint64_t arrive_time = c->cmd_arrive_time; + if (c->cmd_unpaused && arrive_time != 0) { + uint64_t latency = usec_now() - c->cmd_arrive_time; + + if (c->hit_local) { + ptd->stats.stats.tot_local_cmd_time += latency; + ptd->stats.stats.tot_local_cmd_count++; + } + + ptd->stats.stats.tot_cmd_time += latency; + ptd->stats.stats.tot_cmd_count++; + c->cmd_arrive_time = 0; + } + } } } diff --git a/cproxy.h b/cproxy.h index e5928bd7..27d839c2 100644 --- a/cproxy.h +++ b/cproxy.h @@ -324,6 +324,10 @@ struct proxy_stats { uint64_t err_oom; uint64_t err_upstream_write_prep; uint64_t err_downstream_write_prep; + uint64_t tot_cmd_time; + uint64_t tot_cmd_count; + uint64_t tot_local_cmd_time; + uint64_t tot_local_cmd_count; }; typedef struct { diff --git a/cproxy_protocol_a2b.c b/cproxy_protocol_a2b.c index a00582d1..d2d1c655 100644 --- a/cproxy_protocol_a2b.c +++ b/cproxy_protocol_a2b.c @@ -1217,9 +1217,10 @@ bool cproxy_forward_a2b_simple_downstream(downstream *d, // Handle all other simple commands. // int vbucket = -1; + bool local; conn *c = cproxy_find_downstream_conn_ex(d, key, key_len, - NULL, &vbucket); + &local, &vbucket); if (uc->cmd_curr == PROTOCOL_BINARY_CMD_VERSION) { key = NULL; @@ -1227,6 +1228,9 @@ bool cproxy_forward_a2b_simple_downstream(downstream *d, } if (c != NULL) { + if (local) { + uc->hit_local = true; + } if (cproxy_prep_conn_for_write(c)) { assert(c->state == conn_pause); assert(c->wbuf); @@ -1512,10 +1516,14 @@ bool cproxy_forward_a2b_item_downstream(downstream *d, short cmd, // Assuming we're already connected to downstream. // int vbucket = -1; + bool local; conn *c = cproxy_find_downstream_conn_ex(d, ITEM_key(it), it->nkey, - NULL, &vbucket); + &local, &vbucket); if (c != NULL) { + if (local) { + uc->hit_local = true; + } if (cproxy_prep_conn_for_write(c)) { if (settings.verbose > 2) { moxi_log_write("%d: a2b_item_forward, state: %s\n", diff --git a/cproxy_protocol_b2b.c b/cproxy_protocol_b2b.c index 435bb528..6fc26206 100644 --- a/cproxy_protocol_b2b.c +++ b/cproxy_protocol_b2b.c @@ -164,10 +164,14 @@ bool b2b_forward_item(conn *uc, downstream *d, item *it) { } int vbucket = -1; + bool local; conn *c = cproxy_find_downstream_conn_ex(d, key, keylen, - NULL, &vbucket); + &local, &vbucket); if (c != NULL) { + if (local) { + uc->hit_local = true; + } if (b2b_forward_item_vbucket(uc, d, it, c, vbucket) == true) { d->downstream_used_start = 1; d->downstream_used = 1; diff --git a/cproxy_stats.c b/cproxy_stats.c index 4f24f33b..458ffefb 100644 --- a/cproxy_stats.c +++ b/cproxy_stats.c @@ -440,6 +440,8 @@ void cproxy_reset_stats(proxy_stats *ps) { ps->err_oom = 0; ps->err_upstream_write_prep = 0; ps->err_downstream_write_prep = 0; + ps->tot_cmd_time = 0; + ps->tot_cmd_count = 0; } void cproxy_reset_stats_cmd(proxy_stats_cmd *sc) { diff --git a/mcs.c b/mcs.c index 80314325..4ccdee2b 100644 --- a/mcs.c +++ b/mcs.c @@ -657,15 +657,10 @@ char *mcs_server_st_ident(mcs_server_st *msst, bool is_ascii) { char *buf = is_ascii ? msst->ident_a : msst->ident_b; if (buf[0] == '\0') { - const char *usr = mcs_server_st_usr(msst) != NULL ? - mcs_server_st_usr(msst) : - NULL; + const char *usr = mcs_server_st_usr(msst); + const char *pwd = mcs_server_st_pwd(msst); - const char *pwd = mcs_server_st_pwd(msst) != NULL ? - mcs_server_st_pwd(msst) : - NULL; - - snprintf(buf, MCS_IDENT_SIZE - 1, + snprintf(buf, MCS_IDENT_SIZE, "%s:%d:%s:%s:%d", mcs_server_st_hostname(msst), mcs_server_st_port(msst), diff --git a/memcached.h b/memcached.h index 01d0b862..182283b7 100644 --- a/memcached.h +++ b/memcached.h @@ -486,6 +486,10 @@ struct conn { uint64_t cmd_start_time; // Snapshot of usec_now or msec_current_time. int cmd_retries; + bool hit_local; + bool cmd_unpaused; + uint64_t cmd_arrive_time; + bin_cmd *corked; char *host_ident; // Uniquely identifies a memcached server, including