diff options
Diffstat (limited to 'src/zenserver/stats')
| -rw-r--r-- | src/zenserver/stats/statsreporter.cpp | 90 | ||||
| -rw-r--r-- | src/zenserver/stats/statsreporter.h | 8 |
2 files changed, 89 insertions, 9 deletions
diff --git a/src/zenserver/stats/statsreporter.cpp b/src/zenserver/stats/statsreporter.cpp index ff055cf18..4898f3ad5 100644 --- a/src/zenserver/stats/statsreporter.cpp +++ b/src/zenserver/stats/statsreporter.cpp @@ -3,12 +3,85 @@ #include "statsreporter.h" #include <zencore/logging.h> +#include <zencore/profiling/counterstrace.h> #include <zencore/trace.h> #include <zennet/statsdclient.h> +ZEN_THIRD_PARTY_INCLUDES_START +#include <EASTL/functional.h> +#include <EASTL/hash_map.h> +ZEN_THIRD_PARTY_INCLUDES_END + +#include <memory> +#include <string> + namespace zen { -StatsReporter::StatsReporter() +// Decorator that forwards every metric call to an inner StatsMetrics (statsd +// in production) and additionally emits a counter trace point so the metric +// shows up in the .utrace stream / `zen trace serve` viewer. +// +// Counter ids are allocated lazily on first sighting of a metric name. The +// name string is owned by the lookup map so the TraceCounter keeps a stable +// pointer to it for late-init re-emission. +class TracingStatsMetrics : public StatsMetrics +{ +public: + void Rebind(StatsMetrics* Inner) { m_Inner = Inner; } + + void Increment(std::string_view Metric) override + { + if (m_Inner) + m_Inner->Increment(Metric); + Counter(Metric).Increment(); + } + + void Decrement(std::string_view Metric) override + { + if (m_Inner) + m_Inner->Decrement(Metric); + Counter(Metric).Decrement(); + } + + void Count(std::string_view Metric, int64_t CountDelta) override + { + if (m_Inner) + m_Inner->Count(Metric, CountDelta); + Counter(Metric).Add(CountDelta); + } + + void Gauge(std::string_view Metric, uint64_t CurrentValue) override + { + if (m_Inner) + m_Inner->Gauge(Metric, CurrentValue); + Counter(Metric).SetAlways(int64_t(CurrentValue)); + } + + void Meter(std::string_view Metric, uint64_t IncrementValue) override + { + if (m_Inner) + m_Inner->Meter(Metric, IncrementValue); + Counter(Metric).Add(int64_t(IncrementValue)); + } + +private: + TraceCounterInt& Counter(std::string_view Metric) + { + if (auto It = m_Counters.find_as(Metric, std::hash<std::string_view>(), eastl::equal_to_2<std::string, std::string_view>()); + It != m_Counters.end()) + { + return *It->second; + } + auto [Inserted, _] = m_Counters.try_emplace(std::string(Metric), nullptr); + Inserted->second = std::make_unique<TraceCounterInt>(Inserted->first.c_str(), TraceCounterDisplayHint::None); + return *Inserted->second; + } + + StatsMetrics* m_Inner = nullptr; + eastl::hash_map<std::string, std::unique_ptr<TraceCounterInt>, std::hash<std::string>, std::equal_to<std::string>> m_Counters; +}; + +StatsReporter::StatsReporter() : m_TracingMetrics(std::make_unique<TracingStatsMetrics>()) { } @@ -52,13 +125,18 @@ void StatsReporter::ReportStats() { RwLock::ExclusiveLockScope _(m_Lock); - if (m_Statsd) + + // Always run providers through the tracing decorator so counter trace + // points fire even when statsd is disabled. The decorator no-ops the + // inner forward when m_Statsd is null. + m_TracingMetrics->Rebind(m_Statsd.get()); + for (StatsProvider* Provider : m_Providers) { - for (StatsProvider* Provider : m_Providers) - { - Provider->ReportMetrics(*m_Statsd); - } + Provider->ReportMetrics(*m_TracingMetrics); + } + if (m_Statsd) + { m_Statsd->Flush(); } } diff --git a/src/zenserver/stats/statsreporter.h b/src/zenserver/stats/statsreporter.h index b4174073c..82219bc14 100644 --- a/src/zenserver/stats/statsreporter.h +++ b/src/zenserver/stats/statsreporter.h @@ -10,6 +10,7 @@ namespace zen { class StatsDaemonClient; +class TracingStatsMetrics; class StatsReporter { @@ -26,9 +27,10 @@ public: void AddProvider(StatsProvider* Provider); private: - RwLock m_Lock; - std::unique_ptr<StatsDaemonClient> m_Statsd; - std::vector<StatsProvider*> m_Providers; + RwLock m_Lock; + std::unique_ptr<StatsDaemonClient> m_Statsd; + std::unique_ptr<TracingStatsMetrics> m_TracingMetrics; // owns counter id table; rebinds to m_Statsd + std::vector<StatsProvider*> m_Providers; }; } // namespace zen |