]> granicus.if.org Git - icinga2/commitdiff
livestatus: add basic aggregator support
authorMichael Friedrich <michael.friedrich@netways.de>
Thu, 11 Jul 2013 13:52:01 +0000 (15:52 +0200)
committerMichael Friedrich <michael.friedrich@netways.de>
Thu, 11 Jul 2013 14:08:53 +0000 (16:08 +0200)
refs #4398

components/livestatus/Makefile.am
components/livestatus/aggregator.cpp [new file with mode: 0644]
components/livestatus/aggregator.h [new file with mode: 0644]
components/livestatus/countaggregator.cpp [new file with mode: 0644]
components/livestatus/countaggregator.h [new file with mode: 0644]
components/livestatus/query.cpp
components/livestatus/query.h

index 67c1ed41d1bd62f002885b144c6a45f4cf1439fa..3699921c6f3b12853d3d4f0432e4d3a5eaf74524 100644 (file)
@@ -10,6 +10,8 @@ EXTRA_DIST = \
        $(top_builddir)/tools/mkembedconfig/mkembedconfig $< $@
 
 liblivestatus_la_SOURCES = \
+       aggregator.cpp \
+       aggregator.h \
        attributefilter.cpp \
        attributefilter.h \
        andfilter.cpp \
@@ -28,6 +30,8 @@ liblivestatus_la_SOURCES = \
        contactgroupstable.h \
        contactstable.cpp \
        contactstable.h \
+       countaggregator.cpp \
+       countaggregator.h \
        downtimestable.cpp \
        downtimestable.h \
        filter.cpp \
diff --git a/components/livestatus/aggregator.cpp b/components/livestatus/aggregator.cpp
new file mode 100644 (file)
index 0000000..06c286f
--- /dev/null
@@ -0,0 +1,35 @@
+/******************************************************************************
+ * Icinga 2                                                                   *
+ * Copyright (C) 2012 Icinga Development Team (http://www.icinga.org/)        *
+ *                                                                            *
+ * This program is free software; you can redistribute it and/or              *
+ * modify it under the terms of the GNU General Public License                *
+ * as published by the Free Software Foundation; either version 2             *
+ * of the License, or (at your option) any later version.                     *
+ *                                                                            *
+ * 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 St, Fifth Floor, Boston, MA 02110-1301, USA.             *
+ ******************************************************************************/
+
+#include "livestatus/aggregator.h"
+
+using namespace livestatus;
+
+Aggregator::Aggregator(void)
+{ }
+
+void Aggregator::SetFilter(const Filter::Ptr& filter)
+{
+       m_Filter = filter;
+}
+
+Filter::Ptr Aggregator::GetFilter(void) const
+{
+       return m_Filter;
+}
diff --git a/components/livestatus/aggregator.h b/components/livestatus/aggregator.h
new file mode 100644 (file)
index 0000000..803134a
--- /dev/null
@@ -0,0 +1,52 @@
+/******************************************************************************
+ * Icinga 2                                                                   *
+ * Copyright (C) 2012 Icinga Development Team (http://www.icinga.org/)        *
+ *                                                                            *
+ * This program is free software; you can redistribute it and/or              *
+ * modify it under the terms of the GNU General Public License                *
+ * as published by the Free Software Foundation; either version 2             *
+ * of the License, or (at your option) any later version.                     *
+ *                                                                            *
+ * 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 St, Fifth Floor, Boston, MA 02110-1301, USA.             *
+ ******************************************************************************/
+
+#ifndef AGGREGATOR_H
+#define AGGREGATOR_H
+
+#include "livestatus/table.h"
+#include "livestatus/filter.h"
+
+namespace livestatus
+{
+
+/**
+ * @ingroup livestatus
+ */
+class Aggregator : public Object
+{
+public:
+       DECLARE_PTR_TYPEDEFS(Aggregator);
+
+       virtual void Apply(const Table::Ptr& table, const Value& row) = 0;
+       virtual double GetResult(void) const = 0;
+       void SetFilter(const Filter::Ptr& filter);
+
+protected:
+       Aggregator(void);
+       
+       Filter::Ptr GetFilter(void) const;
+       
+private:
+       Filter::Ptr m_Filter;
+};
+
+}
+
+#endif /* AGGREGATOR_H */
diff --git a/components/livestatus/countaggregator.cpp b/components/livestatus/countaggregator.cpp
new file mode 100644 (file)
index 0000000..54df567
--- /dev/null
@@ -0,0 +1,37 @@
+/******************************************************************************
+ * Icinga 2                                                                   *
+ * Copyright (C) 2012 Icinga Development Team (http://www.icinga.org/)        *
+ *                                                                            *
+ * This program is free software; you can redistribute it and/or              *
+ * modify it under the terms of the GNU General Public License                *
+ * as published by the Free Software Foundation; either version 2             *
+ * of the License, or (at your option) any later version.                     *
+ *                                                                            *
+ * 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 St, Fifth Floor, Boston, MA 02110-1301, USA.             *
+ ******************************************************************************/
+
+#include "livestatus/countaggregator.h"
+
+using namespace livestatus;
+
+CountAggregator::CountAggregator(void)
+    : m_Count(0)
+{ }
+
+void CountAggregator::Apply(const Table::Ptr& table, const Value& row)
+{
+       if (GetFilter()->Apply(table, row))
+               m_Count++;
+}
+
+double CountAggregator::GetResult(void) const
+{
+       return m_Count;
+}
diff --git a/components/livestatus/countaggregator.h b/components/livestatus/countaggregator.h
new file mode 100644 (file)
index 0000000..aea0858
--- /dev/null
@@ -0,0 +1,48 @@
+/******************************************************************************
+ * Icinga 2                                                                   *
+ * Copyright (C) 2012 Icinga Development Team (http://www.icinga.org/)        *
+ *                                                                            *
+ * This program is free software; you can redistribute it and/or              *
+ * modify it under the terms of the GNU General Public License                *
+ * as published by the Free Software Foundation; either version 2             *
+ * of the License, or (at your option) any later version.                     *
+ *                                                                            *
+ * 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 St, Fifth Floor, Boston, MA 02110-1301, USA.             *
+ ******************************************************************************/
+
+#ifndef COUNTAGGREGATOR_H
+#define COUNTAGGREGATOR_H
+
+#include "livestatus/table.h"
+#include "livestatus/aggregator.h"
+
+namespace livestatus
+{
+
+/**
+ * @ingroup livestatus
+ */
+class CountAggregator : public Aggregator
+{
+public:
+       DECLARE_PTR_TYPEDEFS(CountAggregator);
+
+       CountAggregator(void);
+
+       virtual void Apply(const Table::Ptr& table, const Value& row);
+       virtual double GetResult(void) const;
+       
+private:
+       int m_Count;
+};
+
+}
+
+#endif /* COUNTAGGREGATOR_H */
index 8793601582c6991bc9753a21592a08b368942169..02ce92f4ec02cc75d740346d00f50c25f3b93cf2 100644 (file)
@@ -18,6 +18,7 @@
  ******************************************************************************/
 
 #include "livestatus/query.h"
+#include "livestatus/countaggregator.h"
 #include "livestatus/attributefilter.h"
 #include "livestatus/negatefilter.h"
 #include "livestatus/orfilter.h"
@@ -63,6 +64,7 @@ Query::Query(const std::vector<String>& lines)
        }
 
        std::deque<Filter::Ptr> filters, stats;
+       std::deque<Aggregator::Ptr> aggregators;
 
        for (unsigned int i = 1; i < lines.size(); i++) {
                line = lines[i];
@@ -80,43 +82,24 @@ Query::Query(const std::vector<String>& lines)
                else if (header == "ColumnHeaders")
                        m_ColumnHeaders = (params == "on");
                else if (header == "Filter" || header == "Stats") {
-                       std::vector<String> tokens;
-                       boost::algorithm::split(tokens, params, boost::is_any_of(" "));
 
-                       if (tokens.size() == 2)
-                               tokens.push_back("");
-
-                       if (tokens.size() < 3) {
+                       Filter::Ptr filter = ParseFilter(params);
+                       
+                       if (!filter) {
                                m_Verb = "ERROR";
                                m_ErrorCode = 452;
-                               m_ErrorMessage = "Expected 3 parameters in the filter specification.";
+                               m_ErrorMessage = "Invalid filter specification.";
                                return;
                        }
 
-                       String op = tokens[1];
-                       bool negate = false;
-
-                       if (op == "!=") {
-                               op = "=";
-                               negate = true;
-                       } else if (op == "!~") {
-                               op = "~";
-                               negate = true;
-                       } else if (op == "!=~") {
-                               op = "=~";
-                               negate = true;
-                       } else if (op == "!~~") {
-                               op = "~~";
-                               negate = true;
-                       }
-
-                       Filter::Ptr filter = boost::make_shared<AttributeFilter>(tokens[0], op, tokens[2]);
-
-                       if (negate)
-                               filter = boost::make_shared<NegateFilter>(filter);
-
                        std::deque<Filter::Ptr>& deq = (header == "Filter") ? filters : stats;
                        deq.push_back(filter);
+                       
+                       if (deq == stats) {
+                               Aggregator::Ptr aggregator = boost::make_shared<CountAggregator>();
+                               aggregator->SetFilter(filter);
+                               aggregators.push_back(aggregator);
+                       }
                } else if (header == "Or" || header == "And") {
                        std::deque<Filter::Ptr>& deq = (header == "Or" || header == "And") ? filters : stats;
 
@@ -155,6 +138,11 @@ Query::Query(const std::vector<String>& lines)
                        filters.pop_back();
 
                        deq.push_back(boost::make_shared<NegateFilter>(filter));
+                       
+                       if (deq == stats) {
+                               Aggregator::Ptr aggregator = aggregators.back();
+                               aggregator->SetFilter(filter);
+                       }
                }
        }
 
@@ -166,7 +154,43 @@ Query::Query(const std::vector<String>& lines)
        }
 
        m_Filter = top_filter;
-       m_Stats.swap(stats);
+       m_Aggregators.swap(aggregators);
+}
+
+Filter::Ptr Query::ParseFilter(const String& params)
+{
+       std::vector<String> tokens;
+       boost::algorithm::split(tokens, params, boost::is_any_of(" "));
+
+       if (tokens.size() == 2)
+               tokens.push_back("");
+
+       if (tokens.size() < 3)
+               return Filter::Ptr();
+
+       String op = tokens[1];
+       bool negate = false;
+
+       if (op == "!=") {
+               op = "=";
+               negate = true;
+       } else if (op == "!~") {
+               op = "~";
+               negate = true;
+       } else if (op == "!=~") {
+               op = "=~";
+               negate = true;
+       } else if (op == "!~~") {
+               op = "~~";
+               negate = true;
+       }
+
+       Filter::Ptr filter = boost::make_shared<AttributeFilter>(tokens[0], op, tokens[2]);
+
+       if (negate)
+               filter = boost::make_shared<NegateFilter>(filter);
+
+       return filter;
 }
 
 void Query::PrintResultSet(std::ostream& fp, const std::vector<String>& columns, const Array::Ptr& rs)
@@ -231,7 +255,7 @@ void Query::ExecuteGetHelper(const Stream::Ptr& stream)
 
        Array::Ptr rs = boost::make_shared<Array>();
 
-       if (m_Stats.empty()) {
+       if (m_Aggregators.empty()) {
                BOOST_FOREACH(const Value& object, objects) {
                        Array::Ptr row = boost::make_shared<Array>();
 
@@ -244,20 +268,20 @@ void Query::ExecuteGetHelper(const Stream::Ptr& stream)
                        rs->Add(row);
                }
        } else {
-               std::vector<int> stats(m_Stats.size(), 0);
-
-               BOOST_FOREACH(const Value& object, objects) {
-                       int index = 0;
-                       BOOST_FOREACH(const Filter::Ptr filter, m_Stats) {
-                               if (filter->Apply(table, object))
-                                       stats[index]++;
+               std::vector<double> stats(m_Aggregators.size(), 0);
 
-                               index++;
+               int index = 0;
+               BOOST_FOREACH(const Aggregator::Ptr aggregator, m_Aggregators) {
+                       BOOST_FOREACH(const Value& object, objects) {
+                               aggregator->Apply(table, object);
                        }
+                       
+                       stats[index] = aggregator->GetResult();
+                       index++;
                }
 
                Array::Ptr row = boost::make_shared<Array>();
-               for (int i = 0; i < m_Stats.size(); i++)
+               for (int i = 0; i < m_Aggregators.size(); i++)
                        row->Add(stats[i]);
 
                rs->Add(row);
index 270aa6abee1467b311ffcac0862e805a83f1fad1..16ce7efe7d9d9aa3c43643c822b7d074c87680e2 100644 (file)
@@ -21,6 +21,7 @@
 #define QUERY_H
 
 #include "livestatus/filter.h"
+#include "livestatus/aggregator.h"
 #include "base/object.h"
 #include "base/array.h"
 #include "base/stream.h"
@@ -53,7 +54,7 @@ private:
        std::vector<String> m_Columns;
 
        Filter::Ptr m_Filter;
-       std::deque<Filter::Ptr> m_Stats;
+       std::deque<Aggregator::Ptr> m_Aggregators;
 
        String m_OutputFormat;
        bool m_ColumnHeaders;
@@ -76,6 +77,8 @@ private:
 
        void SendResponse(const Stream::Ptr& stream, int code, const String& data);
        void PrintFixed16(const Stream::Ptr& stream, int code, const String& data);
+       
+       static Filter::Ptr ParseFilter(const String& params);
 };
 
 }