diff --git a/doc/user/stored-procedures.xml b/doc/user/stored-procedures.xml index 97abfbe30bd823788293976727ded62c8326ad17..209e697f24acc3686ae7cee71015c274fef7564a 100644 --- a/doc/user/stored-procedures.xml +++ b/doc/user/stored-procedures.xml @@ -1441,6 +1441,50 @@ logger = cat - >> tarantool.log </varlistentry> </variablelist> +<variablelist> + <title>Package <code>box.stat</code></title> + <para>This package provides access to request + statistic.</para> + <varlistentry> + <term><emphasis role="lua">box.stat</emphasis></term> + <listitem><bridgehead renderas="sect4">Example</bridgehead><programlisting> +localhost> lua box.stat -- virtual table +--- + - table: 0x41a07a08 +... +localhost> lua box.stat() -- full table (the same) +--- + - table: 0x41a0ebb0 +... +localhost> lua for k, v in pairs(box.stat()) do print(k) end +--- +DELETE +SELECT +REPLACE +CALL +UPDATE +DELETE_1_3 +... +localhost> lua for k, v in pairs(box.stat().DELETE) do print(k, ': ', v) end +--- +total: 23210 +rps: 22 +... +localhost> lua for k, v in pairs(box.stat.DELETE) do print(k, ': ', v) end -- the same +--- +total: 23210 +rps: 22 +... +localhost> lua for k, v in pairs(box.stat.SELECT) do print(k, ': ', v) end +--- +total: 34553330 +rps: 23 +... +localhost> +</programlisting></listitem> + </varlistentry> +</variablelist> + <para> Additional examples can be found in the open source <link xlink:href="https://github.com/mailru/tntlua">Lua stored diff --git a/include/stat.h b/include/stat.h index 8ab4609ad1d2b3903d32976827561ca7a0bb580a..63e0c70ffd4ddea759ef13d7dbe3715e226004f7 100644 --- a/include/stat.h +++ b/include/stat.h @@ -37,4 +37,10 @@ int stat_register(const char **name, size_t count); void stat_collect(int base, int name, i64 value); void stat_print(struct tbuf *buf); +int stat_foreach( + int cb(const char *name, i64 value, int rps, void *udata), + void *data +); + + #endif /* TARANTOOL_STAT_H_INCLUDED */ diff --git a/mod/box/CMakeLists.txt b/mod/box/CMakeLists.txt index 7c99f08466708b6c2275e37fba0162e630c49575..22ccac789e0e0fa10d7ec4311b761239f454e3c6 100644 --- a/mod/box/CMakeLists.txt +++ b/mod/box/CMakeLists.txt @@ -40,4 +40,5 @@ set_source_files_properties(memcached.m tarantool_module("box" tuple.m index.m tree.m space.m port.m request.m txn.m box.m box.lua.c box_lua.m memcached.m memcached-grammar.m + box_lua_stat.m box_lua_uuid.m) diff --git a/mod/box/box_lua.m b/mod/box/box_lua.m index 6565ffc7bcaa024b01b88fa8cd976ca5a14bc261..92685aa24b07bae93398392034f1ce65793c5d01 100644 --- a/mod/box/box_lua.m +++ b/mod/box/box_lua.m @@ -48,7 +48,7 @@ #include "port.h" #include "box_lua_uuid.h" - +#include "box_lua_stat.h" /* contents of box.lua */ extern const char box_lua[]; @@ -1057,6 +1057,7 @@ mod_lua_init(struct lua_State *L) /* Load box.lua */ if (luaL_dostring(L, box_lua)) panic("Error loading box.lua: %s", lua_tostring(L, -1)); + box_lua_stat_init(L); assert(lua_gettop(L) == 0); return L; } diff --git a/mod/box/box_lua_stat.h b/mod/box/box_lua_stat.h new file mode 100644 index 0000000000000000000000000000000000000000..7447e5c70b34ef26a26aa035115c3b96bacd4d4b --- /dev/null +++ b/mod/box/box_lua_stat.h @@ -0,0 +1,36 @@ +#ifndef INCLUDES_TARANTOOL_MOD_BOX_LUA__STAT_H +#define INCLUDES_TARANTOOL_MOD_BOX_LUA__STAT_H +/* + * 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 <COPYRIGHT HOLDER> ``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 + * <COPYRIGHT HOLDER> 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. + */ + +struct lua_State; +void box_lua_stat_init(struct lua_State *L); + +#endif /* INCLUDES_TARANTOOL_MOD_BOX_LUA_STAT_H */ + diff --git a/mod/box/box_lua_stat.m b/mod/box/box_lua_stat.m new file mode 100644 index 0000000000000000000000000000000000000000..387e0a353d349dcce0a507236afb3fc4177d2ec9 --- /dev/null +++ b/mod/box/box_lua_stat.m @@ -0,0 +1,124 @@ +/* + * 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 <COPYRIGHT HOLDER> ``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 + * <COPYRIGHT HOLDER> 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. + */ + + +#include "lua.h" +#include "lauxlib.h" +#include "lualib.h" +#include <string.h> + +#include "box_lua_stat.h" +#include <stat.h> + + +static int _one_stat_item(const char *name, i64 value, int rps, void *udata) { + struct lua_State *L = udata; + + lua_pushstring(L, name); + lua_newtable(L); + + lua_pushstring(L, "rps"); + lua_pushnumber(L, rps); + lua_settable(L, -3); + + lua_pushstring(L, "total"); + lua_pushnumber(L, value); + lua_settable(L, -3); + + lua_settable(L, -3); + + return 0; +} + + +struct _seek_udata { + const char *key; + struct lua_State *L; +}; + +static int _seek_stat_item(const char *name, i64 value, int rps, void *udata) { + + struct _seek_udata *sst = udata; + if (strcmp(name, sst->key) != 0) + return 0; + + lua_newtable(sst->L); + + lua_pushstring(sst->L, "rps"); + lua_pushnumber(sst->L, rps); + lua_settable(sst->L, -3); + + lua_pushstring(sst->L, "total"); + lua_pushnumber(sst->L, value); + lua_settable(sst->L, -3); + + return 1; +} + +static int lbox_stat_index(struct lua_State *L) { + + + struct _seek_udata sst; + sst.key = lua_tolstring(L, -1, NULL); + sst.L = L; + + return stat_foreach(_seek_stat_item, &sst); +} + + +static int lbox_stat_full(struct lua_State *L) { + lua_newtable(L); + + stat_foreach(_one_stat_item, L); + + return 1; +} + +static const struct luaL_reg lbox_stat_meta [] = { + {"__index", lbox_stat_index}, + {"__call", lbox_stat_full}, + {NULL, NULL} +}; + + +void box_lua_stat_init(struct lua_State *L) { + lua_getfield(L, LUA_GLOBALSINDEX, "box"); + + lua_pushstring(L, "stat"); + lua_newtable(L); + + lua_newtable(L); + luaL_register(L, NULL, lbox_stat_meta); + lua_setmetatable(L, -2); + + + lua_settable(L, -3); /* box.stat = created table */ + lua_pop(L, 1); /* cleanup stack */ +} + diff --git a/src/stat.m b/src/stat.m index a1c4cd62e8dfea0a9297b740c0e3d2e375f2a7ef..f26fc0225a01847c966a9dc251a5a45eff791914 100644 --- a/src/stat.m +++ b/src/stat.m @@ -108,6 +108,32 @@ stat_print(struct tbuf *buf) } } +int +stat_foreach( + int cb(const char *name, i64 value, int rps, void *udata), + void *udata +) +{ + if (!cb) + return 0; + for (unsigned i = 0; i <= stats_max; i++) { + if (stats[i].name == NULL) + continue; + + int diff = 0; + for (int j = 0; j < SECS; j++) + diff += stats[i].value[j]; + + diff /= SECS; + + int res = cb(stats[i].name, diff, stats[i].value[SECS], udata); + if (res != 0) + return res; + } + return 0; + +} + void stat_age(ev_timer *timer, int events __attribute__((unused))) { diff --git a/test/box/lua.result b/test/box/lua.result index dacbd56d8f10b4f36a23617c81bac62cb89ee9f5..f029ba682c041acfc827876cba15dd7b876a3128 100644 --- a/test/box/lua.result +++ b/test/box/lua.result @@ -22,6 +22,7 @@ lua for n in pairs(box) do print(' - box.', n) end - box.insert - box.space - box.cfg + - box.stat - box.uuid_hex - box.on_reload_configuration - box.dostring diff --git a/test/box/lua_box_stat.result b/test/box/lua_box_stat.result new file mode 100644 index 0000000000000000000000000000000000000000..6eb010c8160d92b06ea71a18dc37e17c57e56c18 --- /dev/null +++ b/test/box/lua_box_stat.result @@ -0,0 +1,19 @@ +lua for k, v in pairs(box.stat()) do print(k) end +--- +DELETE +SELECT +REPLACE +CALL +UPDATE +DELETE_1_3 +... +lua for k, v in pairs(box.stat().DELETE) do print(k) end +--- +total +rps +... +lua for k, v in pairs(box.stat.DELETE) do print(k) end +--- +total +rps +... diff --git a/test/box/lua_box_stat.test b/test/box/lua_box_stat.test new file mode 100644 index 0000000000000000000000000000000000000000..39c73e0d4f2a479e2d0b6672f2aec25d7b131c1a --- /dev/null +++ b/test/box/lua_box_stat.test @@ -0,0 +1,7 @@ +# encoding: tarantool +import os +import sys + +exec admin "lua for k, v in pairs(box.stat()) do print(k) end" +exec admin "lua for k, v in pairs(box.stat().DELETE) do print(k) end" +exec admin "lua for k, v in pairs(box.stat.DELETE) do print(k) end"