Make json_event_formatter a gen_event_formatter

Make json_event_formatter a generic event formatter by inheriting from
gen_event_formatter and implementing its methods.

Most of the actual work is still done by resolve_format (previously
resolve_tokens, to avoid confusion with sinsp formatter, as it behaves
slightly differently).

Signed-off-by: Mark Stemm <mark.stemm@gmail.com>
This commit is contained in:
Mark Stemm
2021-08-25 17:02:53 -07:00
committed by poiana
parent 943a37fcf7
commit de4b2fa831
2 changed files with 129 additions and 32 deletions

View File

@@ -1511,31 +1511,53 @@ std::list<gen_event_filter_factory::filter_fieldclass_info> json_event_filter_fa
return ret;
}
json_event_formatter::json_event_formatter(json_event_filter_factory &json_factory, std::string &format):
m_format(format),
m_json_factory(json_factory)
json_event_formatter::json_event_formatter(std::shared_ptr<gen_event_filter_factory> json_factory)
: m_output_format(OF_NORMAL), m_json_factory(json_factory)
{
parse_format();
}
json_event_formatter::~json_event_formatter()
{
}
std::string json_event_formatter::tostring(json_event *ev)
void json_event_formatter::set_format(output_format of, const std::string &format)
{
m_output_format = of;
m_format = format;
parse_format();
}
bool json_event_formatter::tostring_withformat(gen_event *gevt, std::string &output, gen_event_formatter::output_format of)
{
json_event *ev = static_cast<json_event *>(gevt);
std::string ret;
std::list<std::pair<std::string, std::string>> resolved;
resolve_tokens(ev, resolved);
for(auto &res : resolved)
if(of == OF_JSON)
{
ret += res.second;
ret = tojson(ev);
return true;
}
else
{
std::list<std::pair<std::string, std::string>> resolved;
return ret;
resolve_format(ev, resolved);
output = "";
for(auto &res : resolved)
{
output += res.second;
}
return true;
}
}
bool json_event_formatter::tostring(gen_event *gevt, std::string &output)
{
return tostring_withformat(gevt, output, m_output_format);
}
std::string json_event_formatter::tojson(json_event *ev)
@@ -1545,7 +1567,7 @@ std::string json_event_formatter::tojson(json_event *ev)
std::list<std::pair<std::string, std::string>> resolved;
resolve_tokens(ev, resolved);
resolve_format(ev, resolved);
for(auto &res : resolved)
{
@@ -1560,12 +1582,13 @@ std::string json_event_formatter::tojson(json_event *ev)
return ret.dump();
}
std::map<std::string, std::string> json_event_formatter::tomap(json_event *ev)
bool json_event_formatter::get_field_values(gen_event *gevt, std::map<std::string, std::string> &fields)
{
std::map<std::string, std::string> ret;
json_event *ev = static_cast<json_event *>(gevt);
std::list<std::pair<std::string, std::string>> res;
resolve_tokens(ev, res);
resolve_format(ev, res);
for(auto &r : res)
{
@@ -1576,11 +1599,11 @@ std::map<std::string, std::string> json_event_formatter::tomap(json_event *ev)
{
r.second = "<NA>";
}
ret.insert(r);
fields.insert(r);
}
}
return ret;
return true;
}
void json_event_formatter::parse_format()
@@ -1602,7 +1625,7 @@ void json_event_formatter::parse_format()
{
// Skip the %
tformat.erase(0, 1);
json_event_filter_check *chk = (json_event_filter_check *)m_json_factory.new_filtercheck(tformat.c_str());
json_event_filter_check *chk = (json_event_filter_check *)m_json_factory->new_filtercheck(tformat.c_str());
if(!chk)
{
@@ -1638,7 +1661,7 @@ void json_event_formatter::parse_format()
}
}
void json_event_formatter::resolve_tokens(json_event *ev, std::list<std::pair<std::string, std::string>> &resolved)
void json_event_formatter::resolve_format(json_event *ev, std::list<std::pair<std::string, std::string>> &resolved)
{
for(auto tok : m_tokens)
{
@@ -1678,3 +1701,43 @@ void json_event_formatter::resolve_tokens(json_event *ev, std::list<std::pair<st
}
}
}
gen_event_formatter::output_format json_event_formatter::get_output_format()
{
return m_output_format;
}
json_event_formatter_factory::json_event_formatter_factory(std::shared_ptr<gen_event_filter_factory> json_factory)
: m_output_format(gen_event_formatter::OF_NORMAL), m_json_factory(json_factory)
{
}
json_event_formatter_factory::~json_event_formatter_factory()
{
}
void json_event_formatter_factory::set_output_format(gen_event_formatter::output_format of)
{
m_formatters.clear();
m_output_format = of;
}
std::shared_ptr<gen_event_formatter> json_event_formatter_factory::create_formatter(const std::string &format)
{
auto it = m_formatters.find(format);
if (it != m_formatters.end())
{
return it->second;
}
std::shared_ptr<gen_event_formatter> ret;
ret.reset(new json_event_formatter(m_json_factory));
ret->set_format(m_output_format, format);
m_formatters[format] = ret;
return ret;
}

View File

@@ -406,22 +406,34 @@ private:
std::list<json_event_filter_check::check_info> m_info;
};
// Unlike the other classes, this does not inherit from a shared class
// that's used both by json events and sinsp events. It might be
// worthwhile, but it would require a lot of additional work to pull
// up functionality into the generic filtercheck class.
class json_event_formatter
class json_event_formatter : public gen_event_formatter
{
public:
json_event_formatter(json_event_filter_factory &factory, std::string &format);
json_event_formatter(std::shared_ptr<gen_event_filter_factory> factory);
virtual ~json_event_formatter();
std::string tostring(json_event *ev);
std::string tojson(json_event *ev);
std::map<std::string, std::string> tomap(json_event *ev);
void set_format(output_format of, const std::string &format) override;
bool tostring(gen_event *evt, std::string &output) override;
bool tostring_withformat(gen_event *evt, std::string &output, gen_event_formatter::output_format of) override;
bool get_field_values(gen_event *evt, std::map<std::string, std::string> &fields) override;
output_format get_output_format() override;
void resolve_tokens(json_event *ev, std::list<std::pair<std::string, std::string>> &resolved);
std::string tojson(json_event *ev);
// Split the format string into a list of tuples, broken at
// output fields, where each tuple is either a block of text
// from the original format string, or a field value/pair from
// the original format string.
//
// For example, given a format string "some output
// (%proc.name)", this will fill in resolved with 3 tuples:
// - ["", "some output ("]
// - ["proc.name", "nginx"]
// - ["", ")"]
//
// This can be used either to return a resolved output string
// or a map of field name/value pairs.
void resolve_format(json_event *ev, std::list<std::pair<std::string, std::string>> &resolved);
private:
void parse_format();
@@ -441,6 +453,8 @@ private:
std::shared_ptr<json_event_filter_check> check;
};
gen_event_formatter::output_format m_output_format;
// The original format string
std::string m_format;
@@ -449,5 +463,25 @@ private:
std::list<fmt_token> m_tokens;
// All the filterchecks required to resolve tokens in the format string
json_event_filter_factory &m_json_factory;
std::shared_ptr<gen_event_filter_factory> m_json_factory;
};
class json_event_formatter_factory : public gen_event_formatter_factory
{
public:
json_event_formatter_factory(std::shared_ptr<gen_event_filter_factory> factory);
virtual ~json_event_formatter_factory();
void set_output_format(gen_event_formatter::output_format of) override;
std::shared_ptr<gen_event_formatter> create_formatter(const std::string &format) override;
protected:
// Maps from output string to formatter
std::map<std::string, std::shared_ptr<gen_event_formatter>> m_formatters;
gen_event_formatter::output_format m_output_format;
// All the filterchecks required to resolve tokens in the format string
std::shared_ptr<gen_event_filter_factory> m_json_factory;
};