Merge pull request #6 from draios/cleanups

Cleanups
This commit is contained in:
Henri DF 2016-02-24 10:33:11 -08:00
commit ffac848c89
5 changed files with 100 additions and 181 deletions

View File

@ -19,7 +19,6 @@ extern "C" {
#include <config_digwatch.h> #include <config_digwatch.h>
#include "rules.h" #include "rules.h"
#include "formats.h" #include "formats.h"
#include "digwatch.h"
#include "utils.h" #include "utils.h"
@ -35,10 +34,7 @@ static void usage()
" -m <filename>, --main-lua <filename>\n" " -m <filename>, --main-lua <filename>\n"
" Name of lua compiler main file\n" " Name of lua compiler main file\n"
" (default: rules_loader.lua)\n" " (default: rules_loader.lua)\n"
" -M <num_seconds> Stop collecting after <num_seconds> reached.\n"
" -N Don't convert port numbers to names.\n" " -N Don't convert port numbers to names.\n"
" -n <num>, --numevents=<num>\n"
" Stop capturing after <num> events\n"
" -r <readfile>, --read=<readfile>\n" " -r <readfile>, --read=<readfile>\n"
" Read the events from <readfile>.\n" " Read the events from <readfile>.\n"
" --unbuffered Turn off output buffering. This causes every single line\n" " --unbuffered Turn off output buffering. This causes every single line\n"
@ -53,42 +49,20 @@ static void usage()
// //
// Event processing loop // Event processing loop
// //
captureinfo do_inspect(sinsp* inspector, void do_inspect(sinsp* inspector,
uint64_t cnt, digwatch_rules* rules,
int duration_to_tot, digwatch_formats* formats)
digwatch_rules* rules,
digwatch_formats* formats)
{ {
captureinfo retval;
int32_t res; int32_t res;
sinsp_evt* ev; sinsp_evt* ev;
string line; string line;
int duration_start = 0;
sinsp_evt_formatter* formatter; sinsp_evt_formatter* formatter;
// //
// Loop through the events // Loop through the events
// //
duration_start = ((double)clock()) / CLOCKS_PER_SEC;
while(1) while(1)
{ {
if(duration_to_tot > 0)
{
int duration_tot = ((double)clock()) / CLOCKS_PER_SEC - duration_start;
if(duration_tot >= duration_to_tot)
{
break;
}
}
if(retval.m_nevts == cnt)
{
//
// End of capture, either because the user stopped it, or because
// we reached the event count specified with -n.
//
break;
}
res = inspector->next(&ev); res = inspector->next(&ev);
if(res == SCAP_TIMEOUT) if(res == SCAP_TIMEOUT)
@ -109,8 +83,6 @@ captureinfo do_inspect(sinsp* inspector,
throw sinsp_exception(inspector->getlasterr().c_str()); throw sinsp_exception(inspector->getlasterr().c_str());
} }
retval.m_nevts++;
if(!inspector->is_debug_enabled() && if(!inspector->is_debug_enabled() &&
ev->get_category() & EC_INTERNAL) ev->get_category() & EC_INTERNAL)
{ {
@ -118,13 +90,13 @@ captureinfo do_inspect(sinsp* inspector,
} }
formatter = formats->lookup_formatter(ev->get_check_id()); formatter = formats->lookup_formatter(ev->get_check_id());
if (!formatter) if(!formatter)
{ {
throw sinsp_exception("Error: No formatter for event with id %d " + to_string(ev->get_check_id())); throw sinsp_exception("Error: No formatter for event with id %d " + to_string(ev->get_check_id()));
} }
bool has_all = formatter->tostring(ev, &line); bool has_all = formatter->tostring(ev, &line);
if (!has_all) { if(!has_all) {
cout << "(missing fields) "; cout << "(missing fields) ";
} }
cout << line; cout << line;
@ -132,8 +104,6 @@ captureinfo do_inspect(sinsp* inspector,
} }
return retval;
} }
// //
@ -146,10 +116,7 @@ int digwatch_init(int argc, char **argv)
digwatch_rules* rules = NULL; digwatch_rules* rules = NULL;
digwatch_formats* formats = NULL; digwatch_formats* formats = NULL;
int op; int op;
uint64_t cnt = -1;
sinsp_evt::param_fmt event_buffer_format = sinsp_evt::PF_NORMAL; sinsp_evt::param_fmt event_buffer_format = sinsp_evt::PF_NORMAL;
int duration_to_tot = 0;
captureinfo cinfo;
int long_index = 0; int long_index = 0;
string lua_main_filename; string lua_main_filename;
string lua_dir = DIGWATCH_INSTALLATION_DIR; string lua_dir = DIGWATCH_INSTALLATION_DIR;
@ -158,7 +125,6 @@ int digwatch_init(int argc, char **argv)
static struct option long_options[] = static struct option long_options[] =
{ {
{"help", no_argument, 0, 'h' }, {"help", no_argument, 0, 'h' },
{"numevents", required_argument, 0, 'n' },
{"main-lua", required_argument, 0, 'u' }, {"main-lua", required_argument, 0, 'u' },
{"readfile", required_argument, 0, 'r' }, {"readfile", required_argument, 0, 'r' },
{"unbuffered", no_argument, 0, 0 }, {"unbuffered", no_argument, 0, 0 },
@ -174,7 +140,7 @@ int digwatch_init(int argc, char **argv)
// Parse the args // Parse the args
// //
while((op = getopt_long(argc, argv, while((op = getopt_long(argc, argv,
"hm:M:Nn:r:", "hm:Nr:",
long_options, &long_index)) != -1) long_options, &long_index)) != -1)
{ {
switch(op) switch(op)
@ -186,31 +152,9 @@ int digwatch_init(int argc, char **argv)
case 'm': case 'm':
lua_main_filename = optarg; lua_main_filename = optarg;
break; break;
case 'M':
duration_to_tot = atoi(optarg);
if(duration_to_tot <= 0)
{
throw sinsp_exception(string("invalid duration") + optarg);
}
break;
case 'N': case 'N':
inspector->set_hostname_and_port_resolution_mode(false); inspector->set_hostname_and_port_resolution_mode(false);
break; break;
case 'n':
try
{
cnt = sinsp_numparser::parseu64(optarg);
}
catch(...)
{
throw sinsp_exception("can't parse the -n argument, make sure it's a number");
}
if(cnt <= 0)
{
throw sinsp_exception(string("invalid event count ") + optarg);
}
break;
case '?': case '?':
result = EXIT_FAILURE; result = EXIT_FAILURE;
goto exit; goto exit;
@ -243,7 +187,7 @@ int digwatch_init(int argc, char **argv)
#endif #endif
} }
if (rules_file.size() == 0) { if(rules_file.size() == 0) {
usage(); usage();
result = EXIT_FAILURE; result = EXIT_FAILURE;
goto exit; goto exit;
@ -252,13 +196,13 @@ int digwatch_init(int argc, char **argv)
// //
char* env_lua_dir = getenv("DIGWATCH_LUA_DIR"); char* env_lua_dir = getenv("DIGWATCH_LUA_DIR");
if (env_lua_dir) if(env_lua_dir)
{ {
lua_dir = string(env_lua_dir); lua_dir = string(env_lua_dir);
} }
trim(lua_main_filename); trim(lua_main_filename);
if (lua_main_filename.size() == 0) if(lua_main_filename.size() == 0)
{ {
lua_main_filename = lua_dir + DIGWATCH_LUA_MAIN; lua_main_filename = lua_dir + DIGWATCH_LUA_MAIN;
} }
@ -274,11 +218,9 @@ int digwatch_init(int argc, char **argv)
inspector->set_filter(rules->get_filter()); inspector->set_filter(rules->get_filter());
inspector->open(""); inspector->open("");
cinfo = do_inspect(inspector, do_inspect(inspector,
cnt, rules,
duration_to_tot, formats);
rules,
formats);
inspector->close(); inspector->close();
} }

View File

@ -1,41 +0,0 @@
/*
Copyright (C) 2013-2014 Draios inc.
This file is part of sysdig.
sysdig is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License version 2 as
published by the Free Software Foundation.
sysdig is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with sysdig. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#ifdef HAS_CAPTURE
#include "../../driver/driver_config.h"
#endif // HAS_CAPTURE
//
// Capture results
//
class captureinfo
{
public:
captureinfo()
{
m_nevts = 0;
m_time = 0;
}
uint64_t m_nevts;
uint64_t m_time;
};

View File

@ -338,7 +338,7 @@ end
definition uses another macro). definition uses another macro).
--]] --]]
function expand_macros(node, defs, changed) function expand_macros(ast, defs, changed)
function copy(obj) function copy(obj)
if type(obj) ~= 'table' then return obj end if type(obj) ~= 'table' then return obj end
@ -347,110 +347,127 @@ function expand_macros(node, defs, changed)
return res return res
end end
if (node.type == "Rule") then if (ast.type == "Rule") then
macros = expand_macros(node.filter, defs, changed) macros = expand_macros(ast.filter, defs, changed)
elseif node.type == "Filter" then elseif ast.type == "Filter" then
if (node.value.type == "Macro") then if (ast.value.type == "Macro") then
if (defs[node.value.value] == nil) then if (defs[ast.value.value] == nil) then
error("Undefined macro '".. node.value.value .. "' used in filter.") error("Undefined macro '".. ast.value.value .. "' used in filter.")
end end
node.value = copy(defs[node.value.value]) ast.value = copy(defs[ast.value.value])
changed = true changed = true
return changed return changed
end end
return expand_macros(node.value, defs, changed) return expand_macros(ast.value, defs, changed)
elseif node.type == "BinaryBoolOp" then elseif ast.type == "BinaryBoolOp" then
if (node.left.type == "Macro") then if (ast.left.type == "Macro") then
if (defs[node.left.value] == nil) then if (defs[ast.left.value] == nil) then
error("Undefined macro '".. node.left.value .. "' used in filter.") error("Undefined macro '".. ast.left.value .. "' used in filter.")
end end
node.left = copy(defs[node.left.value]) ast.left = copy(defs[ast.left.value])
changed = true changed = true
end end
if (node.right.type == "Macro") then if (ast.right.type == "Macro") then
if (defs[node.right.value] == nil) then if (defs[ast.right.value] == nil) then
error("Undefined macro ".. node.right.value .. "used in filter.") error("Undefined macro ".. ast.right.value .. "used in filter.")
end end
node.right = copy(defs[node.right.value]) ast.right = copy(defs[ast.right.value])
changed = true changed = true
end end
local changed_left = expand_macros(node.left, defs, false) local changed_left = expand_macros(ast.left, defs, false)
local changed_right = expand_macros(node.right, defs, false) local changed_right = expand_macros(ast.right, defs, false)
return changed or changed_left or changed_right return changed or changed_left or changed_right
elseif node.type == "UnaryBoolOp" then elseif ast.type == "UnaryBoolOp" then
if (node.argument.type == "Macro") then if (ast.argument.type == "Macro") then
if (defs[node.argument.value] == nil) then if (defs[ast.argument.value] == nil) then
error("Undefined macro ".. node.argument.value .. "used in filter.") error("Undefined macro ".. ast.argument.value .. "used in filter.")
end end
node.argument = copy(defs[node.argument.value]) ast.argument = copy(defs[ast.argument.value])
changed = true changed = true
end end
return expand_macros(node.argument, defs, changed) return expand_macros(ast.argument, defs, changed)
end end
return changed return changed
end end
function get_macros(node, set) function get_macros(ast, set)
if (node.type == "Macro") then if (ast.type == "Macro") then
set[node.value] = true set[ast.value] = true
return set return set
end end
if node.type == "Filter" then if ast.type == "Filter" then
return get_macros(node.value, set) return get_macros(ast.value, set)
end end
if node.type == "BinaryBoolOp" then if ast.type == "BinaryBoolOp" then
local left = get_macros(node.left, {}) local left = get_macros(ast.left, {})
local right = get_macros(node.right, {}) local right = get_macros(ast.right, {})
for m, _ in pairs(left) do set[m] = true end for m, _ in pairs(left) do set[m] = true end
for m, _ in pairs(right) do set[m] = true end for m, _ in pairs(right) do set[m] = true end
return set return set
end end
if node.type == "UnaryBoolOp" then if ast.type == "UnaryBoolOp" then
return get_macros(node.argument, set) return get_macros(ast.argument, set)
end end
return set return set
end end
function print_ast(node, level) function check_macros(ast)
local t = node.type local macros
if (ast.type == "Rule") then
macros = get_macros(ast.filter, {})
elseif (ast.type == "MacroDef") then
macros = get_macros(ast.value, {})
else
error ("Unexpected type: "..t)
end
for m, _ in pairs(macros) do
if macros[m] == nil then
error ("Undefined macro '"..m.."' used in '"..line.."'")
end
end
end
function print_ast(ast, level)
local t = ast.type
level = level or 0 level = level or 0
local prefix = string.rep(" ", level*2) local prefix = string.rep(" ", level*2)
level = level + 1 level = level + 1
if t == "Rule" then if t == "Rule" then
print_ast(node.filter, level) print_ast(ast.filter, level)
if (node.output) then if (ast.output) then
print(prefix.."| "..node.output.value) print(prefix.."| "..ast.output.value)
end end
elseif t == "Filter" then elseif t == "Filter" then
print_ast(node.value, level) print_ast(ast.value, level)
elseif t == "BinaryBoolOp" or t == "BinaryRelOp" then elseif t == "BinaryBoolOp" or t == "BinaryRelOp" then
print(prefix..node.operator) print(prefix..ast.operator)
print_ast(node.left, level) print_ast(ast.left, level)
print_ast(node.right, level) print_ast(ast.right, level)
elseif t == "UnaryRelOp" or t == "UnaryBoolOp" then elseif t == "UnaryRelOp" or t == "UnaryBoolOp" then
print (prefix..node.operator) print (prefix..ast.operator)
print_ast(node.argument, level) print_ast(ast.argument, level)
elseif t == "List" then elseif t == "List" then
print(prefix.. "List: ") print(prefix.. "List: ")
for i, v in ipairs(node.elements) do for i, v in ipairs(ast.elements) do
print_ast(v, level) print_ast(v, level)
end end
elseif t == "FieldName" or t == "Number" or t == "String" or t == "BareString" or t == "Macro" then elseif t == "FieldName" or t == "Number" or t == "String" or t == "BareString" or t == "Macro" then
print (prefix..t.." "..node.value) print (prefix..t.." "..ast.value)
elseif t == "MacroDef" then elseif t == "MacroDef" then
-- don't print for now -- don't print for now
@ -491,20 +508,8 @@ function compiler.compile_line(line, macro_defs)
return {} return {}
end end
local macros -- check that any macros used have already been defined
if (ast.type == "Rule") then check_macros(ast)
macros = get_macros(ast.filter, {})
elseif (ast.type == "MacroDef") then
macros = get_macros(ast.value, {})
else
error ("Unexpected type: "..t)
end
for m, _ in pairs(macros) do
if macros[m] == nil then
error ("Undefined macro '"..m.."' used in '"..line.."'")
end
end
if (ast.type == "MacroDef") then if (ast.type == "MacroDef") then
-- Parsed line is a macro definition, so update our dictionary of macros and -- Parsed line is a macro definition, so update our dictionary of macros and

View File

@ -7,15 +7,18 @@
local compiler = require "compiler" local compiler = require "compiler"
local function mark_check_nodes(ast, index) --[[
Traverse AST, adding the passed-in 'index' to each node that contains a relational expression
--]]
local function mark_relational_nodes(ast, index)
local t = ast.type local t = ast.type
if t == "BinaryBoolOp" then if t == "BinaryBoolOp" then
mark_check_nodes(ast.left, index) mark_relational_nodes(ast.left, index)
mark_check_nodes(ast.right, index) mark_relational_nodes(ast.right, index)
elseif t == "UnaryBoolOp" then elseif t == "UnaryBoolOp" then
mark_check_nodes(ast.argument, index) mark_relational_nodes(ast.argument, index)
elseif t == "BinaryRelOp" then elseif t == "BinaryRelOp" then
ast.index = index ast.index = index
@ -95,11 +98,20 @@ function load_rule(r)
error ("Unexpected type in load_rule: "..line_ast.type) error ("Unexpected type in load_rule: "..line_ast.type)
end end
-- Register a formatter with the output string from this rule
digwatch.set_formatter(state.n_rules, line_ast.output.value) digwatch.set_formatter(state.n_rules, line_ast.output.value)
mark_check_nodes(line_ast.filter.value, state.n_rules)
-- Store the index of this formatter in each relational expression that
-- this rule contains.
-- This index will eventually be stamped in events passing this rule, and
-- we'll use it later to determine which output to display when we get an
-- event.
mark_relational_nodes(line_ast.filter.value, state.n_rules)
state.n_rules = state.n_rules + 1 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 if (state.filter_ast == nil) then
state.filter_ast = line_ast.filter.value state.filter_ast = line_ast.filter.value
else else

View File

@ -2,13 +2,13 @@
function error_exit_good function error_exit_good
{ {
echo "Error: '$1' did not parse" 1>&2 echo "Error: '$1' did not compiler" 1>&2
exit 1 exit 1
} }
function error_exit_bad function error_exit_bad
{ {
echo "Error: incorrect filter '$1' parsed ok" 1>&2 echo "Error: incorrect filter '$1' compiler ok" 1>&2
exit 1 exit 1
} }
@ -72,6 +72,7 @@ good "a : evt.dir=>"
good "inbound: (syscall.type=listen and evt.dir='>') or (syscall.type=accept and evt.dir='<')" good "inbound: (syscall.type=listen and evt.dir='>') or (syscall.type=accept and evt.dir='<')"
bad "a:" bad "a:"
bad "a : b | bla" bad "a : b | bla"
bad "b and d"
echo echo