rework digwatch event output handling

the high-level change is that events matching a rule are now send into a
lua "on_event" function for handling, rather than doing the handling
down in c++.

more specifics:

before, the lua "load_rule" function registered formatters with
associated IDs with the c++ side, which later used this state to
reconcile events with formats and print output accordingly.

now, no such state is kept on the c++ side. the lua "load_rule" function
maintains the id->formatters map, and uses it to print outputs when it
receives events.

this change simplifies the existing flow and will also make the forthcoming
implementation of function outputs far simpler than it would have been
in the current setup.
This commit is contained in:
Henri DF
2016-02-28 21:06:29 -08:00
parent f71de57a90
commit 1c04ed7874
5 changed files with 67 additions and 42 deletions

View File

@@ -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();
}

View File

@@ -6,12 +6,12 @@ extern "C" {
#include "lauxlib.h"
}
std::map<uint32_t, sinsp_evt_formatter*> 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;
}

View File

@@ -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;

View File

@@ -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

View File

@@ -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