diff --git a/src/Conn.h b/src/Conn.h index cc66313d58..b88ad3c7a3 100644 --- a/src/Conn.h +++ b/src/Conn.h @@ -132,6 +132,17 @@ public: analyzer::Analyzer* FindAnalyzer(const char* name); // find first in tree. TransportProto ConnTransport() const { return proto; } + std::string TransportIdentifier() const override + { + if ( proto == TRANSPORT_TCP ) + return "tcp"; + else if ( proto == TRANSPORT_UDP ) + return "udp"; + else if ( proto == TRANSPORT_ICMP ) + return "icmp"; + else + return "unknown"; + } // FIXME: Now this is in Analyzer and should eventually be removed here. // diff --git a/src/Session.h b/src/Session.h index 6cda3e2150..8e8d13cb82 100644 --- a/src/Session.h +++ b/src/Session.h @@ -191,6 +191,12 @@ public: */ void DeleteTimer(double t); + /** + * Returns a string representation of the transport protocol referenced by the + * session. This is used by SessionManager for statistics. + */ + virtual std::string TransportIdentifier() const = 0; + protected: friend class detail::SessionTimer; @@ -239,7 +245,6 @@ protected: unsigned int is_active:1; unsigned int record_packets:1, record_contents:1; unsigned int record_current_packet:1, record_current_content:1; - }; namespace detail { diff --git a/src/SessionManager.cc b/src/SessionManager.cc index f6543ed5cd..d16944705a 100644 --- a/src/SessionManager.cc +++ b/src/SessionManager.cc @@ -36,13 +36,6 @@ zeek::SessionManager*& zeek::sessions = zeek::session_mgr; namespace zeek { -SessionManager::SessionManager() - : stats(telemetry_mgr->GaugeFamily("zeek", "session_stats", - {"tcp", "udp", "icmp"}, - "Zeek Session Stats", "1", false)) - { - } - SessionManager::~SessionManager() { Clear(); @@ -361,17 +354,9 @@ void SessionManager::Remove(Session* s) if ( session_map.erase(key) == 0 ) reporter->InternalWarning("connection missing"); else - switch ( c->ConnTransport() ) { - case TRANSPORT_TCP: - stats.GetOrAdd({{"tcp", "num_conns"}}).Dec(); - break; - case TRANSPORT_UDP: - stats.GetOrAdd({{"udp", "num_conns"}}).Dec(); - break; - case TRANSPORT_ICMP: - stats.GetOrAdd({{"icmp", "num_conns"}}).Dec(); - break; - case TRANSPORT_UNKNOWN: break; + { + if ( auto* stat_block = stats.GetCounters(c->TransportIdentifier()) ) + stat_block->num.Dec(); } s->ClearKey(); @@ -425,17 +410,20 @@ void SessionManager::Clear() void SessionManager::GetStats(SessionStats& s) { - s.max_TCP_conns = stats.GetOrAdd({{"tcp", "max_conns"}}).Value(); - s.num_TCP_conns = stats.GetOrAdd({{"tcp", "num_conns"}}).Value(); - s.cumulative_TCP_conns = stats.GetOrAdd({{"tcp", "cumulative_conns"}}).Value(); + auto* tcp_stats = stats.GetCounters("tcp"); + s.max_TCP_conns = tcp_stats->max; + s.num_TCP_conns = tcp_stats->num.Value(); + s.cumulative_TCP_conns = tcp_stats->total.Value(); - s.max_UDP_conns = stats.GetOrAdd({{"udp", "max_conns"}}).Value(); - s.num_UDP_conns = stats.GetOrAdd({{"udp", "num_conns"}}).Value(); - s.cumulative_UDP_conns = stats.GetOrAdd({{"udp", "cumulative_conns"}}).Value(); + auto* udp_stats = stats.GetCounters("udp"); + s.max_UDP_conns = udp_stats->max; + s.num_UDP_conns = udp_stats->num.Value(); + s.cumulative_UDP_conns = udp_stats->total.Value(); - s.max_ICMP_conns = stats.GetOrAdd({{"icmp", "max_conns"}}).Value(); - s.num_ICMP_conns = stats.GetOrAdd({{"icmp", "num_conns"}}).Value(); - s.cumulative_ICMP_conns = stats.GetOrAdd({{"icmp", "cumulative_conns"}}).Value(); + auto* icmp_stats = stats.GetCounters("icmp"); + s.max_ICMP_conns = icmp_stats->max; + s.num_ICMP_conns = icmp_stats->num.Value(); + s.cumulative_ICMP_conns = icmp_stats->total.Value(); s.num_fragments = detail::fragment_mgr->Size(); s.max_fragments = detail::fragment_mgr->MaxFragments(); @@ -649,31 +637,15 @@ void SessionManager::InsertSession(detail::SessionKey key, Session* session) key.CopyData(); session_map.insert_or_assign(std::move(key), session); - std::string protocol; - switch ( static_cast(session)->ConnTransport() ) - { - case TRANSPORT_TCP: - protocol = "tcp"; - break; - case TRANSPORT_UDP: - protocol = "udp"; - break; - case TRANSPORT_ICMP: - protocol = "icmp"; - break; - default: - break; - } + std::string protocol = session->TransportIdentifier(); - if ( ! protocol.empty() ) + if ( auto* stat_block = stats.GetCounters(protocol) ) { - auto max = stats.GetOrAdd({{protocol, "max_conns"}}); - auto num = stats.GetOrAdd({{protocol, "num_conns"}}); - num.Inc(); + stat_block->num.Inc(); + stat_block->total.Inc(); - stats.GetOrAdd({{protocol, "cumulative_conns"}}).Inc(); - if ( num.Value() > max.Value() ) - max.Inc(); + if ( stat_block->num.Value() > stat_block->max ) + stat_block->max++; } } diff --git a/src/SessionManager.h b/src/SessionManager.h index 4d8591c863..b6f05dca53 100644 --- a/src/SessionManager.h +++ b/src/SessionManager.h @@ -9,7 +9,7 @@ #include "zeek/Frag.h" #include "zeek/NetVar.h" #include "zeek/analyzer/protocol/tcp/Stats.h" -#include "zeek/telemetry/Gauge.h" +#include "zeek/telemetry/Manager.h" #include "zeek/Hash.h" #include "zeek/Session.h" @@ -42,7 +42,7 @@ struct SessionStats { class SessionManager final { public: - SessionManager(); + SessionManager() = default; ~SessionManager(); void Done(); // call to drain events before destructing @@ -141,6 +141,59 @@ public: private: + class StatBlocks { + + public: + + struct Block { + telemetry::IntGauge num; + telemetry::IntCounter total; + size_t max = 0; + + Block(telemetry::IntGaugeFamily num_family, + telemetry::IntCounterFamily total_family, + std::string protocol) : num(num_family.GetOrAdd({{"protocol", protocol}})), + total(total_family.GetOrAdd({{"protocol", protocol}})) + { + } + }; + + using BlockMap = std::map; + + BlockMap::iterator InitCounters(std::string protocol) + { + telemetry::IntGaugeFamily num_family = telemetry_mgr->GaugeFamily( + "zeek", "open-sessions", {"protocol"}, "Active Zeek Sessions"); + telemetry::IntCounterFamily total_family = telemetry_mgr->CounterFamily( + "zeek", "sessions", {"protocol"}, + "Total number of sessions", "1", true); + + auto [it, inserted] = entries.insert( + {protocol, Block{num_family, total_family, protocol}}); + + if ( inserted ) + return it; + + return entries.end(); + } + + Block* GetCounters(std::string protocol) + { + auto it = entries.find(protocol); + if ( it == entries.end() ) + it = InitCounters(protocol); + + if ( it != entries.end() ) + return &(it->second); + + return nullptr; + } + + private: + + BlockMap entries; + }; + using SessionMap = std::map; Connection* NewConn(const detail::ConnIDKey& k, double t, const ConnID* id, @@ -177,7 +230,7 @@ private: void InsertSession(detail::SessionKey key, Session* session); SessionMap session_map; - telemetry::IntGaugeFamily stats; + StatBlocks stats; }; // Manager for the currently active sessions.