diff --git a/cfgmgr/Makefile.am b/cfgmgr/Makefile.am index 69cefc8052c..dc2a467aa70 100644 --- a/cfgmgr/Makefile.am +++ b/cfgmgr/Makefile.am @@ -3,7 +3,7 @@ CFLAGS_SAI = -I /usr/include/sai LIBNL_CFLAGS = -I/usr/include/libnl3 LIBNL_LIBS = -lnl-genl-3 -lnl-route-3 -lnl-3 SAIMETA_LIBS = -lsaimeta -lsaimetadata -lzmq -COMMON_LIBS = -lswsscommon +COMMON_LIBS = -lswsscommon -lpthread bin_PROGRAMS = vlanmgrd teammgrd portmgrd intfmgrd buffermgrd vrfmgrd nbrmgrd vxlanmgrd sflowmgrd natmgrd coppmgrd tunnelmgrd macsecmgrd @@ -26,67 +26,67 @@ else DBGFLAGS = -g endif -vlanmgrd_SOURCES = vlanmgrd.cpp vlanmgr.cpp $(top_srcdir)/orchagent/orch.cpp $(top_srcdir)/orchagent/request_parser.cpp $(top_srcdir)/orchagent/response_publisher.cpp shellcmd.h +vlanmgrd_SOURCES = vlanmgrd.cpp vlanmgr.cpp $(top_srcdir)/orchagent/orch.cpp $(top_srcdir)/orchagent/orchstats.cpp $(top_srcdir)/orchagent/request_parser.cpp $(top_srcdir)/orchagent/response_publisher.cpp shellcmd.h vlanmgrd_CFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) $(CFLAGS_SAI) $(CFLAGS_ASAN) vlanmgrd_CPPFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) $(CFLAGS_SAI) $(CFLAGS_ASAN) vlanmgrd_LDADD = $(LDFLAGS_ASAN) $(COMMON_LIBS) $(SAIMETA_LIBS) -teammgrd_SOURCES = teammgrd.cpp teammgr.cpp $(top_srcdir)/orchagent/orch.cpp $(top_srcdir)/orchagent/request_parser.cpp $(top_srcdir)/orchagent/response_publisher.cpp shellcmd.h +teammgrd_SOURCES = teammgrd.cpp teammgr.cpp $(top_srcdir)/orchagent/orch.cpp $(top_srcdir)/orchagent/orchstats.cpp $(top_srcdir)/orchagent/request_parser.cpp $(top_srcdir)/orchagent/response_publisher.cpp shellcmd.h teammgrd_CFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) $(CFLAGS_SAI) $(CFLAGS_ASAN) teammgrd_CPPFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) $(CFLAGS_SAI) $(CFLAGS_ASAN) teammgrd_LDADD = $(LDFLAGS_ASAN) $(COMMON_LIBS) $(SAIMETA_LIBS) -portmgrd_SOURCES = portmgrd.cpp portmgr.cpp $(top_srcdir)/orchagent/orch.cpp $(top_srcdir)/orchagent/request_parser.cpp $(top_srcdir)/orchagent/response_publisher.cpp shellcmd.h +portmgrd_SOURCES = portmgrd.cpp portmgr.cpp $(top_srcdir)/orchagent/orch.cpp $(top_srcdir)/orchagent/orchstats.cpp $(top_srcdir)/orchagent/request_parser.cpp $(top_srcdir)/orchagent/response_publisher.cpp shellcmd.h portmgrd_CFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) $(CFLAGS_SAI) $(CFLAGS_ASAN) portmgrd_CPPFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) $(CFLAGS_SAI) $(CFLAGS_ASAN) portmgrd_LDADD = $(LDFLAGS_ASAN) $(COMMON_LIBS) $(SAIMETA_LIBS) -intfmgrd_SOURCES = intfmgrd.cpp intfmgr.cpp $(top_srcdir)/orchagent/orch.cpp $(top_srcdir)/orchagent/request_parser.cpp $(top_srcdir)/lib/subintf.cpp $(top_srcdir)/orchagent/response_publisher.cpp shellcmd.h +intfmgrd_SOURCES = intfmgrd.cpp intfmgr.cpp $(top_srcdir)/orchagent/orch.cpp $(top_srcdir)/orchagent/request_parser.cpp $(top_srcdir)/orchagent/orchstats.cpp $(top_srcdir)/lib/subintf.cpp $(top_srcdir)/orchagent/response_publisher.cpp shellcmd.h intfmgrd_CFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) $(CFLAGS_SAI) $(CFLAGS_ASAN) intfmgrd_CPPFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) $(CFLAGS_SAI) $(CFLAGS_ASAN) intfmgrd_LDADD = $(LDFLAGS_ASAN) $(COMMON_LIBS) $(SAIMETA_LIBS) -buffermgrd_SOURCES = buffermgrd.cpp buffermgr.cpp buffermgrdyn.cpp $(top_srcdir)/orchagent/orch.cpp $(top_srcdir)/orchagent/request_parser.cpp $(top_srcdir)/orchagent/response_publisher.cpp shellcmd.h +buffermgrd_SOURCES = buffermgrd.cpp buffermgr.cpp buffermgrdyn.cpp $(top_srcdir)/orchagent/orch.cpp $(top_srcdir)/orchagent/orchstats.cpp $(top_srcdir)/orchagent/request_parser.cpp $(top_srcdir)/orchagent/response_publisher.cpp shellcmd.h buffermgrd_CFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) $(CFLAGS_SAI) $(CFLAGS_ASAN) buffermgrd_CPPFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) $(CFLAGS_SAI) $(CFLAGS_ASAN) buffermgrd_LDADD = $(LDFLAGS_ASAN) $(COMMON_LIBS) $(SAIMETA_LIBS) -vrfmgrd_SOURCES = vrfmgrd.cpp vrfmgr.cpp $(top_srcdir)/orchagent/orch.cpp $(top_srcdir)/orchagent/request_parser.cpp $(top_srcdir)/orchagent/response_publisher.cpp shellcmd.h +vrfmgrd_SOURCES = vrfmgrd.cpp vrfmgr.cpp $(top_srcdir)/orchagent/orch.cpp $(top_srcdir)/orchagent/orchstats.cpp $(top_srcdir)/orchagent/request_parser.cpp $(top_srcdir)/orchagent/response_publisher.cpp shellcmd.h vrfmgrd_CFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) $(CFLAGS_SAI) $(CFLAGS_ASAN) vrfmgrd_CPPFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) $(CFLAGS_SAI) $(CFLAGS_ASAN) vrfmgrd_LDADD = $(LDFLAGS_ASAN) $(COMMON_LIBS) $(SAIMETA_LIBS) -nbrmgrd_SOURCES = nbrmgrd.cpp nbrmgr.cpp $(top_srcdir)/orchagent/orch.cpp $(top_srcdir)/orchagent/request_parser.cpp $(top_srcdir)/orchagent/response_publisher.cpp shellcmd.h +nbrmgrd_SOURCES = nbrmgrd.cpp nbrmgr.cpp $(top_srcdir)/orchagent/orch.cpp $(top_srcdir)/orchagent/orchstats.cpp $(top_srcdir)/orchagent/request_parser.cpp $(top_srcdir)/orchagent/response_publisher.cpp shellcmd.h nbrmgrd_CFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) $(CFLAGS_SAI) $(LIBNL_CFLAGS) $(CFLAGS_ASAN) nbrmgrd_CPPFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) $(CFLAGS_SAI) $(LIBNL_CPPFLAGS) $(CFLAGS_ASAN) nbrmgrd_LDADD = $(LDFLAGS_ASAN) $(COMMON_LIBS) $(SAIMETA_LIBS) $(LIBNL_LIBS) -vxlanmgrd_SOURCES = vxlanmgrd.cpp vxlanmgr.cpp $(top_srcdir)/orchagent/orch.cpp $(top_srcdir)/orchagent/request_parser.cpp $(top_srcdir)/orchagent/response_publisher.cpp shellcmd.h +vxlanmgrd_SOURCES = vxlanmgrd.cpp vxlanmgr.cpp $(top_srcdir)/orchagent/orch.cpp $(top_srcdir)/orchagent/orchstats.cpp $(top_srcdir)/orchagent/request_parser.cpp $(top_srcdir)/orchagent/response_publisher.cpp shellcmd.h vxlanmgrd_CFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) $(CFLAGS_SAI) $(CFLAGS_ASAN) vxlanmgrd_CPPFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) $(CFLAGS_SAI) $(CFLAGS_ASAN) vxlanmgrd_LDADD = $(LDFLAGS_ASAN) $(COMMON_LIBS) $(SAIMETA_LIBS) -sflowmgrd_SOURCES = sflowmgrd.cpp sflowmgr.cpp $(top_srcdir)/orchagent/orch.cpp $(top_srcdir)/orchagent/request_parser.cpp $(top_srcdir)/orchagent/response_publisher.cpp shellcmd.h +sflowmgrd_SOURCES = sflowmgrd.cpp sflowmgr.cpp $(top_srcdir)/orchagent/orch.cpp $(top_srcdir)/orchagent/orchstats.cpp $(top_srcdir)/orchagent/request_parser.cpp $(top_srcdir)/orchagent/response_publisher.cpp shellcmd.h sflowmgrd_CFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) $(CFLAGS_SAI) $(CFLAGS_ASAN) sflowmgrd_CPPFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) $(CFLAGS_SAI) $(CFLAGS_ASAN) sflowmgrd_LDADD = $(LDFLAGS_ASAN) $(COMMON_LIBS) $(SAIMETA_LIBS) -natmgrd_SOURCES = natmgrd.cpp natmgr.cpp $(top_srcdir)/orchagent/orch.cpp $(top_srcdir)/orchagent/request_parser.cpp $(top_srcdir)/orchagent/response_publisher.cpp shellcmd.h +natmgrd_SOURCES = natmgrd.cpp natmgr.cpp $(top_srcdir)/orchagent/orch.cpp $(top_srcdir)/orchagent/orchstats.cpp $(top_srcdir)/orchagent/request_parser.cpp $(top_srcdir)/orchagent/response_publisher.cpp shellcmd.h natmgrd_CFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) $(CFLAGS_SAI) $(CFLAGS_ASAN) natmgrd_CPPFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) $(CFLAGS_SAI) $(CFLAGS_ASAN) natmgrd_LDADD = $(LDFLAGS_ASAN) $(COMMON_LIBS) $(SAIMETA_LIBS) -coppmgrd_SOURCES = coppmgrd.cpp coppmgr.cpp $(top_srcdir)/orchagent/orch.cpp $(top_srcdir)/orchagent/request_parser.cpp $(top_srcdir)/orchagent/response_publisher.cpp shellcmd.h +coppmgrd_SOURCES = coppmgrd.cpp coppmgr.cpp $(top_srcdir)/orchagent/orch.cpp $(top_srcdir)/orchagent/orchstats.cpp $(top_srcdir)/orchagent/request_parser.cpp $(top_srcdir)/orchagent/response_publisher.cpp shellcmd.h coppmgrd_CFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) $(CFLAGS_SAI) $(CFLAGS_ASAN) coppmgrd_CPPFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) $(CFLAGS_SAI) $(CFLAGS_ASAN) coppmgrd_LDADD = $(LDFLAGS_ASAN) $(COMMON_LIBS) $(SAIMETA_LIBS) -tunnelmgrd_SOURCES = tunnelmgrd.cpp tunnelmgr.cpp $(top_srcdir)/orchagent/orch.cpp $(top_srcdir)/orchagent/request_parser.cpp $(top_srcdir)/orchagent/response_publisher.cpp shellcmd.h +tunnelmgrd_SOURCES = tunnelmgrd.cpp tunnelmgr.cpp $(top_srcdir)/orchagent/orch.cpp $(top_srcdir)/orchagent/orchstats.cpp $(top_srcdir)/orchagent/request_parser.cpp $(top_srcdir)/orchagent/response_publisher.cpp shellcmd.h tunnelmgrd_CFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) $(CFLAGS_SAI) $(CFLAGS_ASAN) tunnelmgrd_CPPFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) $(CFLAGS_SAI) $(CFLAGS_ASAN) tunnelmgrd_LDADD = $(LDFLAGS_ASAN) $(COMMON_LIBS) $(SAIMETA_LIBS) -macsecmgrd_SOURCES = macsecmgrd.cpp macsecmgr.cpp $(top_srcdir)/orchagent/orch.cpp $(top_srcdir)/orchagent/request_parser.cpp $(top_srcdir)/orchagent/response_publisher.cpp shellcmd.h +macsecmgrd_SOURCES = macsecmgrd.cpp macsecmgr.cpp $(top_srcdir)/orchagent/orch.cpp $(top_srcdir)/orchagent/orchstats.cpp $(top_srcdir)/orchagent/request_parser.cpp $(top_srcdir)/orchagent/response_publisher.cpp shellcmd.h macsecmgrd_CFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) $(CFLAGS_SAI) $(CFLAGS_ASAN) macsecmgrd_CPPFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) $(CFLAGS_SAI) $(CFLAGS_ASAN) macsecmgrd_LDADD = $(LDFLAGS_ASAN) $(COMMON_LIBS) $(SAIMETA_LIBS) diff --git a/orchagent/Makefile.am b/orchagent/Makefile.am index 5e3cd741ccc..5ed4159e384 100644 --- a/orchagent/Makefile.am +++ b/orchagent/Makefile.am @@ -47,6 +47,7 @@ orchagent_SOURCES = \ $(top_srcdir)/lib/subintf.cpp \ orchdaemon.cpp \ orch.cpp \ + orchstats.cpp \ notifications.cpp \ nhgorch.cpp \ nhgbase.cpp \ diff --git a/orchagent/orch.cpp b/orchagent/orch.cpp index 5690d85dd41..3bb1e78a8b2 100644 --- a/orchagent/orch.cpp +++ b/orchagent/orch.cpp @@ -6,6 +6,7 @@ #include #include "timestamp.h" #include "orch.h" +#include "orchstats.h" #include "subscriberstatetable.h" #include "portsorch.h" @@ -84,6 +85,8 @@ void Consumer::addToSync(const KeyOpFieldsValuesTuple &entry) Orch::recordTuple(*this, entry); } + OrchStats::getInstance()->recordIncomingTask(*this, entry); + /* * m_toSync is a multimap which will allow one key with multiple values, * Also, the order of the key-value pairs whose keys compare equivalent diff --git a/orchagent/orchstats.cpp b/orchagent/orchstats.cpp new file mode 100644 index 00000000000..ddad11874a0 --- /dev/null +++ b/orchagent/orchstats.cpp @@ -0,0 +1,114 @@ +#include "orchstats.h" + +using namespace std; +using namespace swss; + +#define ORCH_STATS_TABLE "ORCH_STATS_TABLE" + +OrchStats* OrchStats::getInstance() +{ + static OrchStats instance; + return &instance; +} + +OrchStats::OrchStats(uint32_t interval) : + m_interval(interval) +{ + SWSS_LOG_ENTER(); + + m_run_thread = true; + m_counter_db = make_shared("COUNTERS_DB", 0); + m_counter_table = make_unique(m_counter_db.get(), ORCH_STATS_TABLE); + + m_background_thread = make_unique(&OrchStats::recordStatsThread, this); +} + +OrchStats::~OrchStats() +{ + SWSS_LOG_ENTER(); + + m_run_thread = false; + m_background_thread->join(); +} + +void OrchStats::recordIncomingTask(Consumer &consumer, const KeyOpFieldsValuesTuple &tuple) +{ + SWSS_LOG_ENTER(); + + auto table_name = consumer.getTableName(); + auto op = kfvOp(tuple); + + auto& stats = getTableStats(table_name); + if (op == SET_COMMAND) + { + stats.m_set++; + } + else + { + stats.m_del++; + } + stats.m_version++; +} + +OrchStats::Stats &OrchStats::getTableStats(const std::string &table_name) +{ + SWSS_LOG_ENTER(); + + auto it = m_table_stats_map.find(table_name); + if (it == m_table_stats_map.end()) + { + lock_guard lock(m_mutex); + it = m_table_stats_map.emplace( + std::piecewise_construct, + std::forward_as_tuple(table_name), + std::forward_as_tuple()).first; + } + return it->second; +} + +void OrchStats::dumpStats(const OrchStats::Stats& stats, vector &dump) +{ + SWSS_LOG_ENTER(); + + dump.clear(); + + dump.emplace_back("SET", to_string(stats.m_set)); + dump.emplace_back("DEL", to_string(stats.m_del)); +} + +void OrchStats::recordStatsThread() +{ + SWSS_LOG_ENTER(); + + std::unordered_map dump_version; + + while (m_run_thread) + { + vector stats_names; + vector> stats_values; + { + lock_guard lock(m_mutex); + for (const auto& table_stats : m_table_stats_map) + { + auto ver = dump_version.find(table_stats.first); + if (ver == dump_version.end()) + { + ver = dump_version.emplace(table_stats.first, 0).first; + } + else if (ver->second == table_stats.second.m_version) + { + continue; + } + ver->second = table_stats.second.m_version; + stats_names.emplace_back(table_stats.first); + stats_values.emplace_back(); + dumpStats(table_stats.second, stats_values.back()); + } + } + for (size_t i = 0; i < stats_names.size(); i++) + { + m_counter_table->set(stats_names[i], stats_values[i]); + } + this_thread::sleep_for(chrono::seconds(m_interval)); + } +} diff --git a/orchagent/orchstats.h b/orchagent/orchstats.h new file mode 100644 index 00000000000..4b06f0558dc --- /dev/null +++ b/orchagent/orchstats.h @@ -0,0 +1,45 @@ +#pragma once + +#include +#include +#include +#include + +#include "orch.h" + + +class OrchStats +{ +public: + static OrchStats* getInstance(); + ~OrchStats(); + + void recordIncomingTask(Consumer &consumer, const swss::KeyOpFieldsValuesTuple &tuple); +private: + + struct Stats + { + std::atomic m_version; + std::atomic m_set; + std::atomic m_del; + Stats() : m_version(0), m_set(0), m_del(0) {} + }; + + using StatsTable = std::unordered_map; + using DumpCounters = std::vector; + + bool m_run_thread; + std::uint32_t m_interval; + std::unique_ptr m_background_thread; + std::mutex m_mutex; + + std::shared_ptr m_counter_db; + std::unique_ptr m_counter_table; + + StatsTable m_table_stats_map; + + OrchStats(std::uint32_t interval = 1); + Stats &getTableStats(const std::string &table_name); + void dumpStats(const Stats& stats, std::vector &dump); + void recordStatsThread(); +}; \ No newline at end of file diff --git a/orchagent/p4orch/tests/Makefile.am b/orchagent/p4orch/tests/Makefile.am index d759033c68a..ff736af4962 100644 --- a/orchagent/p4orch/tests/Makefile.am +++ b/orchagent/p4orch/tests/Makefile.am @@ -23,6 +23,7 @@ CFLAGS_TSAN = -fsanitize=thread CFLAGS_USAN = -fsanitize=undefined p4orch_tests_SOURCES = $(ORCHAGENT_DIR)/orch.cpp \ + $(top_srcdir)/orchagent/orchstats.cpp \ $(ORCHAGENT_DIR)/vrforch.cpp \ $(ORCHAGENT_DIR)/vxlanorch.cpp \ $(ORCHAGENT_DIR)/copporch.cpp \ diff --git a/tests/mock_tests/Makefile.am b/tests/mock_tests/Makefile.am index fb3bb4d00e7..5f200238b36 100644 --- a/tests/mock_tests/Makefile.am +++ b/tests/mock_tests/Makefile.am @@ -56,6 +56,7 @@ tests_SOURCES = aclorch_ut.cpp \ $(top_srcdir)/lib/subintf.cpp \ $(top_srcdir)/orchagent/orchdaemon.cpp \ $(top_srcdir)/orchagent/orch.cpp \ + $(top_srcdir)/orchagent/orchstats.cpp \ $(top_srcdir)/orchagent/notifications.cpp \ $(top_srcdir)/orchagent/routeorch.cpp \ $(top_srcdir)/orchagent/mplsrouteorch.cpp \ @@ -159,6 +160,7 @@ tests_intfmgrd_SOURCES = intfmgrd/intfmgr_ut.cpp \ $(top_srcdir)/cfgmgr/intfmgr.cpp \ $(top_srcdir)/lib/subintf.cpp \ $(top_srcdir)/orchagent/orch.cpp \ + $(top_srcdir)/orchagent/orchstats.cpp \ $(top_srcdir)/orchagent/request_parser.cpp \ mock_orchagent_main.cpp \ mock_dbconnector.cpp \ diff --git a/tests/test_orchstats.py b/tests/test_orchstats.py new file mode 100644 index 00000000000..ac03629faa9 --- /dev/null +++ b/tests/test_orchstats.py @@ -0,0 +1,6 @@ +from swsscommon import swsscommon + +def test_orchstats(): + db = swsscommon.DBConnector("COUNTERS_DB", 0) + tb=swsscommon.Table(db, "ORCH_STATS_TABLE") + assert(tb.get("PORT")[0])