Skip to content

Commit

Permalink
proxy: mcp.server_stats(subcmd)
Browse files Browse the repository at this point in the history
Allow accessing server stats from the configuration thread (useful for
crons, checking start args, etc). Does not support cachedump or detail.

Returns a table of the results. The results are thus unordered.
  • Loading branch information
dormando committed Apr 11, 2024
1 parent 6537dcd commit 07fd8dc
Show file tree
Hide file tree
Showing 9 changed files with 159 additions and 18 deletions.
4 changes: 2 additions & 2 deletions memcached.c
Original file line number Diff line number Diff line change
Expand Up @@ -1796,7 +1796,7 @@ void append_stat(const char *name, ADD_STAT add_stats, conn *c,
}

/* return server specific stats only */
void server_stats(ADD_STAT add_stats, conn *c) {
void server_stats(ADD_STAT add_stats, void *c) {
pid_t pid = getpid();
rel_time_t now = current_time;

Expand Down Expand Up @@ -1861,7 +1861,7 @@ void server_stats(ADD_STAT add_stats, conn *c) {
APPEND_STAT("get_expired", "%llu", (unsigned long long)thread_stats.get_expired);
APPEND_STAT("get_flushed", "%llu", (unsigned long long)thread_stats.get_flushed);
#ifdef EXTSTORE
if (c->thread->storage) {
if (ext_storage) {
APPEND_STAT("get_extstore", "%llu", (unsigned long long)thread_stats.get_extstore);
APPEND_STAT("get_aborted_extstore", "%llu", (unsigned long long)thread_stats.get_aborted_extstore);
APPEND_STAT("get_oom_extstore", "%llu", (unsigned long long)thread_stats.get_oom_extstore);
Expand Down
2 changes: 1 addition & 1 deletion memcached.h
Original file line number Diff line number Diff line change
Expand Up @@ -1063,7 +1063,7 @@ void conn_set_state(conn *c, enum conn_states state);
void out_of_memory(conn *c, char *ascii_error);
void out_errstring(conn *c, const char *str);
void write_and_free(conn *c, char *buf, int bytes);
void server_stats(ADD_STAT add_stats, conn *c);
void server_stats(ADD_STAT add_stats, void *c);
void append_stats(const char *key, const uint16_t klen,
const char *val, const uint32_t vlen,
const void *cookie);
Expand Down
8 changes: 4 additions & 4 deletions proto_proxy.c
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ bool proxy_bufmem_checkadd(LIBEVENT_THREAD *t, int len) {
}

// see also: process_extstore_stats()
void proxy_stats(void *arg, ADD_STAT add_stats, conn *c) {
void proxy_stats(void *arg, ADD_STAT add_stats, void *c) {
if (arg == NULL) {
return;
}
Expand All @@ -137,7 +137,7 @@ void proxy_stats(void *arg, ADD_STAT add_stats, conn *c) {
STAT_UL(ctx);
}

void process_proxy_stats(void *arg, ADD_STAT add_stats, conn *c) {
void process_proxy_stats(void *arg, ADD_STAT add_stats, void *c) {
char key_str[STAT_KEY_LEN];
struct proxy_int_stats istats = {0};
uint64_t req_limit = 0;
Expand Down Expand Up @@ -225,7 +225,7 @@ void process_proxy_stats(void *arg, ADD_STAT add_stats, conn *c) {
APPEND_STAT("cmd_replace", "%llu", (unsigned long long)istats.counters[CMD_REPLACE]);
}

void process_proxy_funcstats(void *arg, ADD_STAT add_stats, conn *c) {
void process_proxy_funcstats(void *arg, ADD_STAT add_stats, void *c) {
char key_str[STAT_KEY_LEN];
if (!arg) {
return;
Expand Down Expand Up @@ -261,7 +261,7 @@ void process_proxy_funcstats(void *arg, ADD_STAT add_stats, conn *c) {
pthread_mutex_unlock(&ctx->sharedvm_lock);
}

void process_proxy_bestats(void *arg, ADD_STAT add_stats, conn *c) {
void process_proxy_bestats(void *arg, ADD_STAT add_stats, void *c) {
char key_str[STAT_KEY_LEN];
if (!arg) {
return;
Expand Down
8 changes: 4 additions & 4 deletions proto_proxy.h
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
#ifndef PROTO_PROXY_H
#define PROTO_PROXY_H

void proxy_stats(void *arg, ADD_STAT add_stats, conn *c);
void process_proxy_stats(void *arg, ADD_STAT add_stats, conn *c);
void process_proxy_funcstats(void *arg, ADD_STAT add_stats, conn *c);
void process_proxy_bestats(void *arg, ADD_STAT add_stats, conn *c);
void proxy_stats(void *arg, ADD_STAT add_stats, void *c);
void process_proxy_stats(void *arg, ADD_STAT add_stats, void *c);
void process_proxy_funcstats(void *arg, ADD_STAT add_stats, void *c);
void process_proxy_bestats(void *arg, ADD_STAT add_stats, void *c);

/* proxy mode handlers */
int try_read_command_proxy(conn *c);
Expand Down
68 changes: 68 additions & 0 deletions proxy_lua.c
Original file line number Diff line number Diff line change
@@ -1,12 +1,79 @@
/* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */

#include "proxy.h"
#include "storage.h" // for stats call

// func prototype example:
// static int fname (lua_State *L)
// normal library open:
// int luaopen_mcp(lua_State *L) { }

struct _mcplib_statctx_s {
lua_State *L;
};

static void _mcplib_append_stats(const char *key, const uint16_t klen,
const char *val, const uint32_t vlen,
const void *cookie) {
if (klen == 0 && vlen > 0) {
return;
}
if (klen == 0 && vlen == 0) {
// END isn't necessary for the lua API since we're using a table.
return;
}

// cookie -> struct
const struct _mcplib_statctx_s *c = cookie;
lua_State *L = c->L;
// table should always be on the top.
lua_pushlstring(L, key, klen);
lua_pushlstring(L, val, vlen);
lua_rawset(L, -3);
}

// reimplementation of proto_text.c:process_stat()
static int mcplib_server_stats(lua_State *L) {
int argc = lua_gettop(L);
proxy_ctx_t *ctx = PROXY_GET_CTX(L);
lua_newtable(L); // the table to return.
struct _mcplib_statctx_s c = {
L,
};

if (argc == 0) {
server_stats(&_mcplib_append_stats, &c);
get_stats(NULL, 0, &_mcplib_append_stats, &c);
} else {
const char *cmd = luaL_checkstring(L, 1);
if (strcmp(cmd, "settings") == 0) {
process_stat_settings(&_mcplib_append_stats, &c);
} else if (strcmp(cmd, "conns") == 0) {
process_stats_conns(&_mcplib_append_stats, &c);
#ifdef EXTSTORE
} else if (strcmp(cmd, "extstore") == 0) {
process_extstore_stats(&_mcplib_append_stats, &c);
#endif
} else if (strcmp(cmd, "proxy") == 0) {
process_proxy_stats(ctx, &_mcplib_append_stats, &c);
} else if (strcmp(cmd, "proxyfuncs") == 0) {
process_proxy_funcstats(ctx, &_mcplib_append_stats, &c);
} else if (strcmp(cmd, "proxybe") == 0) {
process_proxy_bestats(ctx, &_mcplib_append_stats, &c);
} else {
if (get_stats(cmd, strlen(cmd), &_mcplib_append_stats, &c)) {
// all good.
} else {
// unknown command.
proxy_lua_error(L, "unknown subcommand passed to server_stats");
}
}
}

// return the table.
return 1;
}

static lua_Integer _mcplib_backend_get_waittime(lua_Number secondsf) {
lua_Integer secondsi = (lua_Integer) secondsf;
lua_Number subseconds = secondsf - secondsi;
Expand Down Expand Up @@ -1615,6 +1682,7 @@ int proxy_register_libs(void *ctx, LIBEVENT_THREAD *t, void *state) {
{"buffer_memory_limit", mcplib_buffer_memory_limit},
{"schedule_config_reload", mcplib_schedule_config_reload},
{"register_cron", mcplib_register_cron},
{"server_stats", mcplib_server_stats},
{NULL, NULL}
};

Expand Down
10 changes: 5 additions & 5 deletions storage.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ void storage_delete(void *e, item *it) {
// but feels a little off being defined here.
// At very least maybe "process_storage_stats" in line with making this more
// of a generic wrapper module.
void process_extstore_stats(ADD_STAT add_stats, conn *c) {
void process_extstore_stats(ADD_STAT add_stats, void *c) {
int i;
char key_str[STAT_KEY_LEN];
char val_str[STAT_VAL_LEN];
Expand All @@ -83,7 +83,7 @@ void process_extstore_stats(ADD_STAT add_stats, conn *c) {

assert(add_stats);

void *storage = c->thread->storage;
void *storage = ext_storage;
if (storage == NULL) {
return;
}
Expand All @@ -106,17 +106,17 @@ void process_extstore_stats(ADD_STAT add_stats, conn *c) {
}

// Additional storage stats for the main stats output.
void storage_stats(ADD_STAT add_stats, conn *c) {
void storage_stats(ADD_STAT add_stats, void *c) {
struct extstore_stats st;
if (c->thread->storage) {
if (ext_storage) {
STATS_LOCK();
APPEND_STAT("extstore_compact_lost", "%llu", (unsigned long long)stats.extstore_compact_lost);
APPEND_STAT("extstore_compact_rescues", "%llu", (unsigned long long)stats.extstore_compact_rescues);
APPEND_STAT("extstore_compact_resc_cold", "%llu", (unsigned long long)stats.extstore_compact_resc_cold);
APPEND_STAT("extstore_compact_resc_old", "%llu", (unsigned long long)stats.extstore_compact_resc_old);
APPEND_STAT("extstore_compact_skipped", "%llu", (unsigned long long)stats.extstore_compact_skipped);
STATS_UNLOCK();
extstore_get_stats(c->thread->storage, &st);
extstore_get_stats(ext_storage, &st);
APPEND_STAT("extstore_page_allocs", "%llu", (unsigned long long)st.page_allocs);
APPEND_STAT("extstore_page_evictions", "%llu", (unsigned long long)st.page_evictions);
APPEND_STAT("extstore_page_reclaims", "%llu", (unsigned long long)st.page_reclaims);
Expand Down
4 changes: 2 additions & 2 deletions storage.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ void storage_delete(void *e, item *it);
#endif

// API.
void storage_stats(ADD_STAT add_stats, conn *c);
void process_extstore_stats(ADD_STAT add_stats, conn *c);
void storage_stats(ADD_STAT add_stats, void *c);
void process_extstore_stats(ADD_STAT add_stats, void *c);
bool storage_validate_item(void *e, item *it);
int storage_get_item(conn *c, item *it, mc_resp *resp);

Expand Down
48 changes: 48 additions & 0 deletions t/proxyintstats.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
function dump_stats(s)
print("STATS DUMP")
for k, v in pairs(s) do
print("key/val:", k, v)
end
print("END STATS DUMP")
end

function mcp_config_pools()
--[[mcp.register_cron("stats", { every = 2, func = function()
local s = mcp.server_stats("slabs")
dump_stats(s)
end })]]--

local s
s = mcp.server_stats()
dump_stats(s)

s = mcp.server_stats("settings")
dump_stats(s)

s = mcp.server_stats("conns")
dump_stats(s)

s = mcp.server_stats("extstore")
dump_stats(s)

s = mcp.server_stats("proxy")
dump_stats(s)

s = mcp.server_stats("proxyfuncs")
dump_stats(s)

s = mcp.server_stats("proxybe")
dump_stats(s)

s = mcp.server_stats("items")
dump_stats(s)

s = mcp.server_stats("slabs")
dump_stats(s)
end

function mcp_config_routes(c)
mcp.attach(mcp.CMD_ANY_STORAGE, function(r)
return mcp.internal(r)
end)
end
25 changes: 25 additions & 0 deletions t/proxyintstats.t
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#!/usr/bin/env perl

use strict;
use warnings;
use Test::More;
use FindBin qw($Bin);
use lib "$Bin/lib";
use Carp qw(croak);
use MemcachedTest;
use IO::Socket qw(AF_INET SOCK_STREAM);
use IO::Select;
use Data::Dumper qw/Dumper/;

if (!supports_proxy()) {
plan skip_all => 'proxy not enabled';
exit 0;
}

my $p_srv = new_memcached('-o proxy_config=./t/proxyintstats.lua -t 1');
my $ps = $p_srv->sock;
$ps->autoflush(1);

pass("didn't crash");

done_testing();

0 comments on commit 07fd8dc

Please sign in to comment.