diff --git a/userspace/digwatch/digwatch.cpp b/userspace/digwatch/digwatch.cpp index 4e438cae..fd0c47d9 100644 --- a/userspace/digwatch/digwatch.cpp +++ b/userspace/digwatch/digwatch.cpp @@ -45,18 +45,19 @@ static void usage() ); } +string lua_on_event = "on_event"; // // Event processing loop // void do_inspect(sinsp* inspector, digwatch_rules* rules, - digwatch_formats* formats) + digwatch_formats* formats, + lua_State* ls) { int32_t res; sinsp_evt* ev; string line; - sinsp_evt_formatter* formatter; // // Loop through the events @@ -89,20 +90,24 @@ void do_inspect(sinsp* inspector, continue; } - formatter = formats->lookup_formatter(ev->get_check_id()); - if(!formatter) + lua_getglobal(ls, lua_on_event.c_str()); + + if(lua_isfunction(ls, -1)) { - throw sinsp_exception("Error: No formatter for event with id %d " + to_string(ev->get_check_id())); + lua_pushlightuserdata(ls, ev); + lua_pushnumber(ls, ev->get_check_id()); + + if(lua_pcall(ls, 2, 0, 0) != 0) + { + const char* lerr = lua_tostring(ls, -1); + string err = "Error installing rules: " + string(lerr); + throw sinsp_exception(err); + } } - - bool has_all = formatter->tostring(ev, &line); - if(!has_all) { - cout << "(missing fields) "; + else + { + throw sinsp_exception("No function " + lua_on_event + " found in lua compiler module"); } - cout << line; - cout << endl; - - } } @@ -219,7 +224,8 @@ int digwatch_init(int argc, char **argv) do_inspect(inspector, rules, - formats); + formats, + ls); inspector->close(); } diff --git a/userspace/digwatch/formats.cpp b/userspace/digwatch/formats.cpp index 531c54e5..b7f2c9d8 100644 --- a/userspace/digwatch/formats.cpp +++ b/userspace/digwatch/formats.cpp @@ -6,12 +6,12 @@ extern "C" { #include "lauxlib.h" } -std::map g_format_map; sinsp* g_inspector; const static struct luaL_reg ll_digwatch [] = { - {"set_formatter", &digwatch_formats::set_formatter}, + {"formatter", &digwatch_formats::formatter}, + {"format_event", &digwatch_formats::format_event}, {NULL,NULL} }; @@ -24,20 +24,12 @@ digwatch_formats::digwatch_formats(sinsp* inspector, lua_State *ls) luaL_openlib(m_ls, "digwatch", ll_digwatch, 0); } -int digwatch_formats::set_formatter (lua_State *ls) { - uint32_t index = luaL_checkinteger(ls, 1); - string format = luaL_checkstring(ls, 2); - +int digwatch_formats::formatter(lua_State *ls) { + string format = luaL_checkstring(ls, 1); + sinsp_evt_formatter* formatter; try { - if(format == "" || format == "default") - { - g_format_map[index] = new sinsp_evt_formatter(g_inspector, DEFAULT_OUTPUT_STR); - } - else - { - g_format_map[index] = new sinsp_evt_formatter(g_inspector, format); - } + formatter = new sinsp_evt_formatter(g_inspector, format); } catch(sinsp_exception& e) { @@ -46,12 +38,24 @@ int digwatch_formats::set_formatter (lua_State *ls) { throw sinsp_exception("set_formatter error"); } - return 0; + lua_pushlightuserdata(ls, formatter); + + return 1; } -sinsp_evt_formatter* digwatch_formats::lookup_formatter(uint32_t index) -{ - return g_format_map[index]; +int digwatch_formats::format_event (lua_State *ls) { + string line; + + if (!lua_islightuserdata(ls, -1) || !lua_islightuserdata(ls, -2)) { + string err = "invalid arguments passed to format_event() "; + throw sinsp_exception("format_event error"); + } + sinsp_evt* evt = (sinsp_evt*)lua_topointer(ls, 1); + sinsp_evt_formatter* formatter = (sinsp_evt_formatter*)lua_topointer(ls, 2); + + formatter->tostring(evt, &line); + + lua_pushstring(ls, line.c_str()); + return 1; } - diff --git a/userspace/digwatch/formats.h b/userspace/digwatch/formats.h index 7cb84c61..913c461c 100644 --- a/userspace/digwatch/formats.h +++ b/userspace/digwatch/formats.h @@ -10,9 +10,11 @@ class digwatch_formats public: digwatch_formats(sinsp* inspector, lua_State *ls); - // set_formatter(index, format_string) - static int set_formatter(lua_State *ls); - sinsp_evt_formatter* lookup_formatter(uint32_t index); + // formatter = digwatch.formatter(format_string) + static int formatter(lua_State *ls); + + // formatted_string = digwatch.format_event(evt, formatter) + static int format_event(lua_State *ls); private: lua_State* m_ls; diff --git a/userspace/digwatch/lua/compiler.lua b/userspace/digwatch/lua/compiler.lua index aadd33bc..f9fa99b1 100644 --- a/userspace/digwatch/lua/compiler.lua +++ b/userspace/digwatch/lua/compiler.lua @@ -173,7 +173,7 @@ end local function rule(filter, output) if not output then - output = outputformat("") + output = outputformat(nil) end return {type = "Rule", filter = filter, output = output} end diff --git a/userspace/digwatch/lua/rule_loader.lua b/userspace/digwatch/lua/rule_loader.lua index a7963d9f..d0291133 100644 --- a/userspace/digwatch/lua/rule_loader.lua +++ b/userspace/digwatch/lua/rule_loader.lua @@ -5,6 +5,8 @@ --]] +local DEFAULT_OUTPUT_FORMAT = "%evt.num %evt.time %evt.cpu %proc.name (%thread.tid) %evt.dir %evt.type %evt.args" + local compiler = require "compiler" --[[ @@ -72,7 +74,7 @@ local state to the line-oriented compiler. --]] local function init() - return {macros={}, filter_ast=nil, n_rules=0} + return {macros={}, filter_ast=nil, n_rules=0, outputs={}} end @@ -90,8 +92,16 @@ function load_rule(r) error ("Unexpected type in load_rule: "..line_ast.type) end - -- Register a formatter with the output string from this rule - digwatch.set_formatter(state.n_rules, line_ast.output.value) + state.n_rules = state.n_rules + 1 + + local format + if line_ast.output.value==nil then + format = DEFAULT_OUTPUT_FORMAT + else + format = line_ast.output.value + end + + state.outputs[state.n_rules] = digwatch.formatter(format) -- Store the index of this formatter in each relational expression that -- this rule contains. @@ -100,8 +110,6 @@ function load_rule(r) -- event. mark_relational_nodes(line_ast.filter.value, state.n_rules) - state.n_rules = state.n_rules + 1 - -- Rule ASTs are merged together into one big AST, with "OR" between each -- rule. if (state.filter_ast == nil) then @@ -114,3 +122,8 @@ end function on_done() install_filter(state.filter_ast) end + +function on_event(evt, rule_id) + print(digwatch.format_event(evt, state.outputs[rule_id])) +end +