From de4b2fa8313423af9a503e749ef3f6c5a08f8aff Mon Sep 17 00:00:00 2001 From: Mark Stemm Date: Wed, 25 Aug 2021 17:02:53 -0700 Subject: [PATCH] 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 --- userspace/engine/json_evt.cpp | 103 +++++++++++++++++++++++++++------- userspace/engine/json_evt.h | 58 +++++++++++++++---- 2 files changed, 129 insertions(+), 32 deletions(-) diff --git a/userspace/engine/json_evt.cpp b/userspace/engine/json_evt.cpp index 97917d9b..6ea1c327 100644 --- a/userspace/engine/json_evt.cpp +++ b/userspace/engine/json_evt.cpp @@ -1511,31 +1511,53 @@ std::list 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 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(gevt); + std::string ret; - std::list> resolved; - - resolve_tokens(ev, resolved); - - for(auto &res : resolved) + if(of == OF_JSON) { - ret += res.second; + ret = tojson(ev); + return true; } + else + { + std::list> 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> 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 json_event_formatter::tomap(json_event *ev) +bool json_event_formatter::get_field_values(gen_event *gevt, std::map &fields) { - std::map ret; + json_event *ev = static_cast(gevt); + std::list> res; - resolve_tokens(ev, res); + resolve_format(ev, res); for(auto &r : res) { @@ -1576,11 +1599,11 @@ std::map json_event_formatter::tomap(json_event *ev) { r.second = ""; } - 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> &resolved) +void json_event_formatter::resolve_format(json_event *ev, std::list> &resolved) { for(auto tok : m_tokens) { @@ -1678,3 +1701,43 @@ void json_event_formatter::resolve_tokens(json_event *ev, std::list 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 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 ret; + + ret.reset(new json_event_formatter(m_json_factory)); + + ret->set_format(m_output_format, format); + m_formatters[format] = ret; + + return ret; +} diff --git a/userspace/engine/json_evt.h b/userspace/engine/json_evt.h index 457e9ca2..e4c1a321 100644 --- a/userspace/engine/json_evt.h +++ b/userspace/engine/json_evt.h @@ -406,22 +406,34 @@ private: std::list 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 factory); virtual ~json_event_formatter(); - std::string tostring(json_event *ev); - std::string tojson(json_event *ev); - std::map 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 &fields) override; + output_format get_output_format() override; - void resolve_tokens(json_event *ev, std::list> &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> &resolved); private: void parse_format(); @@ -441,6 +453,8 @@ private: std::shared_ptr check; }; + gen_event_formatter::output_format m_output_format; + // The original format string std::string m_format; @@ -449,5 +463,25 @@ private: std::list m_tokens; // All the filterchecks required to resolve tokens in the format string - json_event_filter_factory &m_json_factory; + std::shared_ptr m_json_factory; +}; + +class json_event_formatter_factory : public gen_event_formatter_factory +{ +public: + json_event_formatter_factory(std::shared_ptr factory); + virtual ~json_event_formatter_factory(); + + void set_output_format(gen_event_formatter::output_format of) override; + + std::shared_ptr create_formatter(const std::string &format) override; + +protected: + // Maps from output string to formatter + std::map> m_formatters; + + gen_event_formatter::output_format m_output_format; + + // All the filterchecks required to resolve tokens in the format string + std::shared_ptr m_json_factory; };