Merge pull request #10 from draios/support-function-outputs

Support function outputs
This commit is contained in:
Henri DF 2016-02-29 20:38:45 -08:00
commit 3feaa86db0
5 changed files with 99 additions and 49 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;
}
}
@ -111,7 +116,7 @@ void do_inspect(sinsp* inspector,
//
int digwatch_init(int argc, char **argv)
{
int result;
int result = EXIT_SUCCESS;
sinsp* inspector = NULL;
digwatch_rules* rules = NULL;
digwatch_formats* formats = NULL;
@ -120,7 +125,7 @@ int digwatch_init(int argc, char **argv)
int long_index = 0;
string lua_main_filename;
string lua_dir = DIGWATCH_INSTALLATION_DIR;
lua_State* ls;
lua_State* ls = NULL;
static struct option long_options[] =
{
@ -147,7 +152,6 @@ int digwatch_init(int argc, char **argv)
{
case 'h':
usage();
result = EXIT_SUCCESS;
goto exit;
case 'm':
lua_main_filename = optarg;
@ -220,7 +224,8 @@ int digwatch_init(int argc, char **argv)
do_inspect(inspector,
rules,
formats);
formats,
ls);
inspector->close();
}
@ -242,7 +247,10 @@ exit:
delete inspector;
}
lua_close(ls);
if(ls)
{
lua_close(ls);
}
return result;
}

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,13 @@ 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 +39,25 @@ 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)
int digwatch_formats::format_event (lua_State *ls)
{
return g_format_map[index];
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

@ -167,13 +167,13 @@ local function outputformat (format)
return {type = "OutputFormat", value = format}
end
local function functioncall (name, args)
return {type = "FunctionCall", name = name, arguments = args}
local function functioncall (str, mname, fname, args)
return {type = "FunctionCall", mname = mname, fname = fname, arguments = args, source = str}
end
local function rule(filter, output)
if not output then
output = outputformat("")
output = outputformat(nil)
end
return {type = "Rule", filter = filter, output = output}
end
@ -217,7 +217,7 @@ local G = {
MacroDef = (C(V"Macro") * V"Skip" * V"Colon" * (V"Filter"));
FuncArgs = symb("(") * list(V"Value", symb(",")) * symb(")");
Output = ((V"Name" * V"FuncArgs") / functioncall) + P(1)^0 / outputformat;
Output = (C(V"Name" * P(".") * V"Name" * V"FuncArgs") / functioncall) + P(1)^0 / outputformat;
-- Terminals
Value = terminal "Number" + terminal "String" + terminal "BareString";
@ -462,7 +462,7 @@ function print_ast(ast, level)
print(ast.value)
elseif t == "FunctionCall" then
print(ast.name .. "(" )
print(ast.mname..ast.fname .. "(" )
print_ast(ast.arguments)
print(")")

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,10 +74,31 @@ 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
function set_output(output_ast)
if(output_ast.type == "OutputFormat") then
local format
if output_ast.value==nil then
format = DEFAULT_OUTPUT_FORMAT
else
format = output_ast.value
end
state.outputs[state.n_rules] = {type="format", formatter=digwatch.formatter(format)}
elseif (output_ast.type == "FunctionCall") then
require(output_ast.mname)
state.outputs[state.n_rules] = {type="function", mname = output_ast.mname, source=output_ast.source}
else
error ("Unexpected type in set_output: ".. output_ast.type)
end
end
function load_rule(r)
if (state == nil) then
state = init()
@ -90,8 +113,9 @@ 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
set_output(line_ast.output)
-- Store the index of this formatter in each relational expression that
-- this rule contains.
@ -100,8 +124,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 +136,15 @@ end
function on_done()
install_filter(state.filter_ast)
end
evt = nil
function on_event(evt_, rule_id)
if state.outputs[rule_id].type == "format" then
print(digwatch.format_event(evt, state.outputs[rule_id].formatter))
elseif state.outputs[rule_id].type == "function" then
local reqmod = "local "..state.outputs[rule_id].mname.." = require('" ..state.outputs[rule_id].mname .. "')";
evt = evt_
assert(loadstring(reqmod .. "; print(type(evt));" ..state.outputs[rule_id].source))()
end
end