]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
Merge pull request #932 in SNORT/snort3 from json_formatter to master
authorMichael Altizer (mialtize) <mialtize@cisco.com>
Mon, 26 Jun 2017 16:09:49 +0000 (12:09 -0400)
committerMichael Altizer (mialtize) <mialtize@cisco.com>
Mon, 26 Jun 2017 16:09:49 +0000 (12:09 -0400)
Squashed commit of the following:

commit 81a8d478028d9437122f29bbe2e8cb1c197b800b
Author: Carter Waxman <cwaxman@cisco.com>
Date:   Mon May 16 11:12:56 2016 -0400

    perf_monitor: Add JSON formatter

src/network_inspectors/perf_monitor/CMakeLists.txt
src/network_inspectors/perf_monitor/Makefile.am
src/network_inspectors/perf_monitor/json_formatter.cc [new file with mode: 0644]
src/network_inspectors/perf_monitor/json_formatter.h [new file with mode: 0644]
src/network_inspectors/perf_monitor/perf_formatter.h
src/network_inspectors/perf_monitor/perf_module.cc
src/network_inspectors/perf_monitor/perf_module.h
src/network_inspectors/perf_monitor/perf_monitor.cc
src/network_inspectors/perf_monitor/perf_tracker.cc
src/network_inspectors/perf_monitor/perf_tracker.h

index 5add638e3d3e12b6baee0832a54f65f31161c460..a8093f77c0b3a7c93f75df9a09d0d10294240779 100644 (file)
@@ -14,6 +14,8 @@ add_library ( perf_monitor STATIC
     flow_tracker.h
     flow_ip_tracker.cc
     flow_ip_tracker.h
+    json_formatter.cc
+    json_formatter.h
     perf_formatter.cc
     perf_formatter.h
     perf_module.cc
index 19897c1bb6ccd4d63287b88f56f84938a6aedc64..348fe7ada69ee9d2aa2d11ba47bbc0eb3ef16df1 100644 (file)
@@ -7,6 +7,7 @@ csv_formatter.cc csv_formatter.h \
 cpu_tracker.cc cpu_tracker.h \
 flow_tracker.cc flow_tracker.h \
 flow_ip_tracker.cc flow_ip_tracker.h \
+json_formatter.cc json_formatter.h \
 perf_formatter.cc perf_formatter.h \
 perf_monitor.cc perf_monitor.h \
 perf_module.cc perf_module.h \
diff --git a/src/network_inspectors/perf_monitor/json_formatter.cc b/src/network_inspectors/perf_monitor/json_formatter.cc
new file mode 100644 (file)
index 0000000..078e152
--- /dev/null
@@ -0,0 +1,191 @@
+//--------------------------------------------------------------------------
+// Copyright (C) 2016-2016 Cisco and/or its affiliates. All rights reserved.
+//
+// This program 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.  You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// This program 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 this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//--------------------------------------------------------------------------
+
+// json_formatter.cc author Carter Waxman <cwaxman@cisco.com>
+
+#include "json_formatter.h"
+
+#include <sstream>
+
+#include "utils/stats.h"
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef UNIT_TEST
+#include <cstdio>
+#include <cstring>
+
+#include "catch/catch.hpp"
+#endif
+
+using namespace std;
+
+void JSONFormatter::init_output(FILE* fh)
+{
+    fwrite("[", 1, 1, fh);
+    first_write = true;
+}
+
+void JSONFormatter::write(FILE* fh, time_t cur_time)
+{
+    std::ostringstream ss;
+
+    if( first_write )
+        first_write = false;
+    else
+        ss << ",";
+
+    ss << "{\"timestamp\":" << cur_time;
+
+    for( unsigned i = 0; i < values.size(); i++ )
+    {
+        bool head = false;
+        
+        for( unsigned j = 0; j < values[i].size(); j++ )
+        {
+            switch( types[i][j] )
+            {
+                case FT_PEG_COUNT:
+                    if( *values[i][j].pc != 0 )
+                    {
+                        if( !head ) 
+                        {
+                            ss << ",\"" << section_names[i] << "\":{";
+                            head = true;
+                        }
+                        else
+                            ss << ",";
+                        ss << "\"" << field_names[i][j] << "\":" << *values[i][j].pc;
+                    }
+                    break;
+
+                case FT_STRING:
+                    if( *values[i][j].s )
+                    {
+                        if( !head )
+                        {
+                            ss << ",\"" << section_names[i] << "\":{";
+                            head = true;
+                        }
+                        else
+                            ss << ",";
+                        ss << "\"" << field_names[i][j] << "\":\"" << values[i][j].s << "\"";
+                    }
+                    break;
+
+                case FT_IDX_PEG_COUNT:
+                {
+                    bool vec_head = false;
+
+                    vector<PegCount>* vals = values[i][j].ipc;
+                    for( unsigned k = 0; k < vals->size(); k++ )
+                    {
+                        if( !vals->at(k) )
+                            continue;
+
+                        if( !vec_head )
+                        {
+                            if( !head )
+                            {
+                                ss << ",\"" << section_names[i] << "\":{";
+                                head = true;
+                            }
+                            else
+                                ss << ",";
+
+                            ss << "\"" << field_names[i][j] << "\":{";
+                            vec_head = true;
+                        }
+                        else
+                            ss << ",";
+
+                        ss << "\"" << k << "\":" << vals->at(k);
+                    }
+                    if( vec_head )
+                        ss << "}";
+
+                    break;
+                }
+            }
+        }
+        if ( head )
+            ss << "}";
+    }
+    ss << "}";
+    auto out = ss.str();
+    fwrite(out.c_str(), out.size(), 1, fh);
+    fflush(fh);
+}
+
+void JSONFormatter::finalize_output(FILE* fh)
+{ fwrite("]\n", 2, 1, fh); }
+
+#ifdef UNIT_TEST
+
+string cooked = R"g([{"timestamp":1234567890,"name":{"one":1},"str":{"five":"hellothere"},)g"
+                R"g("vec":{"vector":{"0":50,"2":70}}},{"timestamp":2345678901}])g" "\n";
+
+TEST_CASE("json output", "[JSONFormatter]")
+{
+    PegCount one = 1, two = 0, three = 0;
+    char five[32] = "hellothere";
+    vector<PegCount> kvp;
+
+    FILE* fh = tmpfile();
+    JSONFormatter f("test");
+
+    f.register_section("name");
+    f.register_field("one", &one);
+    f.register_field("two", &two);
+    f.register_section("other");
+    f.register_field("three", &three);
+    f.register_section("str");
+    f.register_field("five", five);
+    f.register_section("vec");
+    f.register_field("vector", &kvp);
+    f.finalize_fields();
+    f.init_output(fh);
+
+    kvp.push_back(50);
+    kvp.push_back(0);
+    kvp.push_back(70);
+    
+    f.write(fh, (time_t)1234567890);
+
+    one = 0;
+    five[0] = '\0';
+    kvp.clear();
+    f.write(fh, (time_t)2345678901);
+    f.finalize_output(fh);
+
+    auto size = ftell(fh);
+    char* fake_file = (char*) malloc(size + 1);
+
+    rewind(fh);
+    fread(fake_file, size, 1, fh);
+    fake_file[size] = '\0';
+
+    CHECK( cooked == fake_file );
+
+    free(fake_file);
+    fclose(fh);
+}
+
+#endif
diff --git a/src/network_inspectors/perf_monitor/json_formatter.h b/src/network_inspectors/perf_monitor/json_formatter.h
new file mode 100644 (file)
index 0000000..17473fe
--- /dev/null
@@ -0,0 +1,46 @@
+//--------------------------------------------------------------------------
+// Copyright (C) 2016-2016 Cisco and/or its affiliates. All rights reserved.
+//
+// This program 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.  You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// This program 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 this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//--------------------------------------------------------------------------
+
+// json_formatter.h author Carter Waxman <cwaxman@cisco.com>
+
+#ifndef JSON_FORMATTER_H
+#define JSON_FORMATTER_H
+
+#include "perf_formatter.h"
+
+class JSONFormatter : public PerfFormatter
+{
+public:
+    using PerfFormatter::PerfFormatter;
+
+    const char* get_extension() override
+    { return ".json"; }
+
+    bool allow_append() override
+    { return false; }
+
+    void init_output(FILE*) override;
+    void write(FILE*, time_t) override;
+    void finalize_output(FILE*) override;
+
+private:
+    bool first_write = true;
+};
+
+#endif
+
index e30bf740fa40b71ac03e458a3ef136031c8d3280..9c136b30b65234e56b9ca19dc205079a10e26adb 100644 (file)
@@ -86,6 +86,7 @@ public:
     virtual void finalize_fields() {}
     virtual void init_output(FILE*) {}
     virtual void write(FILE*, time_t) = 0;
+    virtual void finalize_output(FILE*) {}
 
 protected:
     std::vector<std::vector<FormatterType>> types;
index 6d6575a859dd1f0c6527426152f7a239ef58bdfe..38d5162b1fd25d5bb32c082cc1f857adb3206b07 100644 (file)
@@ -82,7 +82,7 @@ static const Parameter s_params[] =
     { "modules", Parameter::PT_LIST, module_params, nullptr,
       "gather statistics from the specified modules" },
 
-    { "format", Parameter::PT_ENUM, "csv | text" FLATBUFFERS_ENUM, "csv",
+    { "format", Parameter::PT_ENUM, "csv | text | json" FLATBUFFERS_ENUM, "csv",
       "output format for stats" },
 
     { "summary", Parameter::PT_BOOL, nullptr, "false",
index 116263420ab47521d840d64387e68cd683169248..c1319249cc3b027040d6a06ab304131bf407284b 100644 (file)
@@ -43,6 +43,7 @@ enum PerfFormat
 {
     PERF_CSV,
     PERF_TEXT,
+    PERF_JSON,
     PERF_FBS,
     PERF_MOCK
 };
index 91c1f2b0d339e8894e7a6f25b3d1245e2cb1585d..1da7ff6aa11c9689628724dde159457b7c816dfe 100644 (file)
@@ -121,6 +121,9 @@ void PerfMonitor::show(SnortConfig*)
         case PERF_CSV:
             LogMessage("    Output Format:  csv\n");
             break;
+        case PERF_JSON:
+            LogMessage("    Output Format:  json\n");
+            break;
 #ifdef HAVE_FLATBUFFERS
         case PERF_FBS:
             LogMessage("    Output Format:  flatbuffers\n");
@@ -185,7 +188,6 @@ void PerfMonitor::tterm()
             auto back = trackers->back();
             if ( config.perf_flags & PERF_SUMMARY )
                 back->process(true);
-            back->close();
             delete back;
             trackers->pop_back();
         }
index 2ca9fe1cc99a00d2d8f2d3904df73d9ff4019d70..b1c8f4d18b4769b59ded6160ad2c8b5ca020371d 100644 (file)
@@ -37,6 +37,7 @@
 #endif
 
 #include "csv_formatter.h"
+#include "json_formatter.h"
 #include "text_formatter.h"
 
 using namespace std;
@@ -65,6 +66,7 @@ PerfTracker::PerfTracker(PerfConfig* config, bool file, const char* tracker_name
     {
         case PERF_CSV: formatter = new CSVFormatter(tracker_name); break;
         case PERF_TEXT: formatter = new TextFormatter(tracker_name); break;
+        case PERF_JSON: formatter = new JSONFormatter(tracker_name); break;
 #ifdef HAVE_FLATBUFFERS
         case PERF_FBS: formatter = new FbsFormatter(tracker_name); break;
 #endif
@@ -86,8 +88,11 @@ PerfTracker::PerfTracker(PerfConfig* config, bool file, const char* tracker_name
 
 PerfTracker::~PerfTracker()
 {
+    formatter->finalize_output(fh);
     delete formatter;
-    close();
+
+    if (fh && fh != stdout)
+        fclose(fh);
 }
 
 bool PerfTracker::open(bool append)
@@ -151,18 +156,6 @@ bool PerfTracker::open(bool append)
     return true;
 }
 
-bool PerfTracker::close()
-{
-    if (fh && fh != stdout)
-    {
-        if (fclose(fh))
-            return false;
-        fh = nullptr;
-    }
-
-    return true;
-}
-
 // FIXIT-M combine with fileRotate
 // FIXIT-M refactor file naming foo to use std::string
 static bool rotate_file(const char* old_file, FILE* old_fh,
index 12713fc6587910646e1c8c67234cc0d1e799bdf2..07522c165be2daf7a6a2b3e96b8f5907942da9f8 100644 (file)
@@ -55,7 +55,6 @@ public:
     virtual const std::string& get_name() final { return tracker_name; }
 
     virtual bool open(bool append) final;
-    virtual bool close() final;
     virtual bool rotate() final;
     virtual bool auto_rotate() final;