diff options
author | dormando <dormando@rydia.net> | 2023-01-26 15:41:37 -0800 |
---|---|---|
committer | dormando <dormando@rydia.net> | 2023-01-27 19:08:47 -0800 |
commit | 0503e4fb125cee5d8711229ee07e561f9fb36bc3 (patch) | |
tree | 5366192967ff7edffbe1daa387b8711b00018842 /proxy_await.c | |
parent | e56062321515728fdb5b9c80589f51db3357827c (diff) | |
download | memcached-0503e4fb125cee5d8711229ee07e561f9fb36bc3.tar.gz |
proxy: add mcp.await_logerrors()
Logs any backgrounded requests that resulted in an error.
Note that this may be a temporary interface, and could be deprecated in
the future.
Diffstat (limited to 'proxy_await.c')
-rw-r--r-- | proxy_await.c | 50 |
1 files changed, 48 insertions, 2 deletions
diff --git a/proxy_await.c b/proxy_await.c index 4192900..b0a4dee 100644 --- a/proxy_await.c +++ b/proxy_await.c @@ -9,8 +9,10 @@ typedef struct mcp_await_s { int argtable_ref; // need to hold refs to any potential hash selectors int restable_ref; // table of result objects int coro_ref; // reference to parent coroutine + int detail_ref; // reference to detail string. enum mcp_await_e type; bool completed; // have we completed the parent coroutine or not + bool logerr; // create log_req entries for error responses mcp_request_t *rq; mc_resp *resp; // the top level mc_resp to fill in (as if we were an iop) } mcp_await_t; @@ -23,12 +25,13 @@ typedef struct mcp_await_s { // local restable = mcp.await(request, pools, num_wait) // NOTE: need to hold onto the pool objects since those hold backend // references. Here we just keep a reference to the argument table. -int mcplib_await(lua_State *L) { +static int _mcplib_await(lua_State *L, bool logerr) { mcp_request_t *rq = luaL_checkudata(L, 1, "mcp.request"); luaL_checktype(L, 2, LUA_TTABLE); int n = 0; // length of table of pools int wait_for = 0; // 0 means wait for all responses enum mcp_await_e type = AWAIT_GOOD; + int detail_ref = 0; lua_pushnil(L); // init table key while (lua_next(L, 2) != 0) { @@ -41,6 +44,11 @@ int mcplib_await(lua_State *L) { proxy_lua_error(L, "mcp.await arguments must have at least one pool"); } + if (lua_isstring(L, 5)) { + // pops the detail string. + detail_ref = luaL_ref(L, LUA_REGISTRYINDEX); + } + if (lua_isnumber(L, 4)) { type = lua_tointeger(L, 4); lua_pop(L, 1); @@ -86,13 +94,24 @@ int mcplib_await(lua_State *L) { aw->argtable_ref = argtable_ref; aw->rq = rq; aw->req_ref = req_ref; + aw->detail_ref = detail_ref; aw->type = type; + aw->logerr = logerr; P_DEBUG("%s: about to yield [len: %d]\n", __func__, n); lua_pushinteger(L, MCP_YIELD_AWAIT); return lua_yield(L, 2); } +// default await, no logging. +int mcplib_await(lua_State *L) { + return _mcplib_await(L, false); +} + +int mcplib_await_logerrors(lua_State *L) { + return _mcplib_await(L, true); +} + static void mcp_queue_await_io(conn *c, lua_State *Lc, mcp_request_t *rq, int await_ref, bool await_first) { io_queue_t *q = conn_io_queue_get(c, IO_QUEUE_PROXY); @@ -367,7 +386,7 @@ int mcplib_await_return(io_pending_proxy_t *p) { } // note that post-completion, we stop gathering responses into the - // resposne table... because it's already been returned. + // response table... because it's already been returned. // So "valid" can only be true if also !completed if (aw->pending == 0) { if (!aw->completed) { @@ -398,6 +417,30 @@ int mcplib_await_return(io_pending_proxy_t *p) { p->client_resp->elapsed = (end.tv_sec - p->client_resp->start.tv_sec) * 1000000 + (end.tv_usec - p->client_resp->start.tv_usec); + // instructed to generate log_req entries for each failed request, + // this is useful to do here as these can be asynchronous. + // NOTE: this may be a temporary feature. + if (aw->logerr && p->client_resp->status != MCMC_OK && aw->completed) { + size_t dlen = 0; + const char *detail = NULL; + logger *l = p->thread->l; + // only process logs if someone is listening. + if (l->eflags & LOG_PROXYREQS) { + lua_rawgeti(L, LUA_REGISTRYINDEX, aw->req_ref); + mcp_request_t *rq = lua_touserdata(L, -1); + lua_pop(L, 1); // references still held, just clearing stack. + mcp_resp_t *rs = p->client_resp; + + if (aw->detail_ref) { + lua_rawgeti(L, LUA_REGISTRYINDEX, aw->detail_ref); + detail = luaL_tolstring(L, -1, &dlen); + lua_pop(L, 1); + } + + logger_log(l, LOGGER_PROXY_REQ, NULL, rq->pr.request, rq->pr.reqlen, rs->elapsed, rs->resp.type, rs->resp.code, rs->status, detail, dlen, rs->be_name, rs->be_port); + } + } + luaL_unref(L, LUA_REGISTRYINDEX, p->mcpres_ref); } // our await_ref is shared, so we don't need to release it. @@ -430,6 +473,9 @@ int mcplib_await_return(io_pending_proxy_t *p) { luaL_unref(L, LUA_REGISTRYINDEX, aw->argtable_ref); luaL_unref(L, LUA_REGISTRYINDEX, aw->req_ref); luaL_unref(L, LUA_REGISTRYINDEX, p->await_ref); + if (aw->detail_ref) { + luaL_unref(L, LUA_REGISTRYINDEX, aw->detail_ref); + } WSTAT_DECR(p->thread, proxy_await_active, 1); } |