From aaced060bfbd4232a39b9cd510bf50f83d947c9a Mon Sep 17 00:00:00 2001 From: Vinnie Falco Date: Sat, 1 Feb 2014 20:14:38 -0800 Subject: [PATCH] Add basic_seconds_clock, insight::Groups --- Builds/VisualStudio2012/beast.vcxproj | 23 ++ Builds/VisualStudio2012/beast.vcxproj.filters | 24 ++ Builds/VisualStudio2013/beast.vcxproj | 4 + Builds/VisualStudio2013/beast.vcxproj.filters | 12 + beast/Chrono.h | 1 + beast/Insight.h | 2 + beast/chrono/Chrono.cpp | 1 + beast/chrono/abstract_clock.h | 2 +- beast/chrono/basic_seconds_clock.h | 237 ++++++++++++++++++ beast/chrono/impl/basic_seconds_clock.cpp | 47 ++++ beast/insight/Base.h | 38 +++ beast/insight/BaseImpl.h | 40 +++ beast/insight/Collector.h | 36 +++ beast/insight/Counter.h | 23 +- beast/insight/CounterImpl.h | 8 +- beast/insight/Event.h | 8 +- beast/insight/EventImpl.h | 6 +- beast/insight/Gauge.h | 23 +- beast/insight/GaugeImpl.h | 9 +- beast/insight/Group.h | 43 ++++ beast/insight/Groups.h | 55 ++++ beast/insight/Hook.h | 11 +- beast/insight/HookImpl.h | 6 +- beast/insight/Insight.cpp | 2 + beast/insight/Meter.h | 26 +- beast/insight/MeterImpl.h | 9 +- beast/insight/impl/Group.cpp | 28 +++ beast/insight/impl/Groups.cpp | 144 +++++++++++ beast/insight/impl/Metric.cpp | 8 + beast/insight/impl/NullCollector.cpp | 12 - beast/insight/impl/StatsDCollector.cpp | 27 -- 31 files changed, 809 insertions(+), 106 deletions(-) create mode 100644 beast/chrono/basic_seconds_clock.h create mode 100644 beast/chrono/impl/basic_seconds_clock.cpp create mode 100644 beast/insight/Base.h create mode 100644 beast/insight/BaseImpl.h create mode 100644 beast/insight/Group.h create mode 100644 beast/insight/Groups.h create mode 100644 beast/insight/impl/Group.cpp create mode 100644 beast/insight/impl/Groups.cpp diff --git a/Builds/VisualStudio2012/beast.vcxproj b/Builds/VisualStudio2012/beast.vcxproj index ec1388eac9..0bb02c5cb8 100644 --- a/Builds/VisualStudio2012/beast.vcxproj +++ b/Builds/VisualStudio2012/beast.vcxproj @@ -97,6 +97,7 @@ + @@ -131,6 +132,8 @@ + + @@ -138,6 +141,8 @@ + + @@ -408,6 +413,12 @@ + + true + true + true + true + true true @@ -524,6 +535,18 @@ true true + + true + true + true + true + + + true + true + true + true + true true diff --git a/Builds/VisualStudio2012/beast.vcxproj.filters b/Builds/VisualStudio2012/beast.vcxproj.filters index 5bd137834e..6c9f7d5d51 100644 --- a/Builds/VisualStudio2012/beast.vcxproj.filters +++ b/Builds/VisualStudio2012/beast.vcxproj.filters @@ -1242,6 +1242,21 @@ beast\chrono + + beast\chrono + + + beast\insight + + + beast\insight + + + beast\insight + + + beast\insight + @@ -1802,6 +1817,15 @@ beast\crypto\impl + + beast\chrono\impl + + + beast\insight\impl + + + beast\insight\impl + diff --git a/Builds/VisualStudio2013/beast.vcxproj b/Builds/VisualStudio2013/beast.vcxproj index ba9d4f9e62..f4b93cdcb6 100644 --- a/Builds/VisualStudio2013/beast.vcxproj +++ b/Builds/VisualStudio2013/beast.vcxproj @@ -131,6 +131,8 @@ + + @@ -138,6 +140,8 @@ + + diff --git a/Builds/VisualStudio2013/beast.vcxproj.filters b/Builds/VisualStudio2013/beast.vcxproj.filters index 2d7cc5e900..9a1c036675 100644 --- a/Builds/VisualStudio2013/beast.vcxproj.filters +++ b/Builds/VisualStudio2013/beast.vcxproj.filters @@ -1242,6 +1242,18 @@ beast\chrono + + beast\insight + + + beast\insight + + + beast\insight + + + beast\insight + diff --git a/beast/Chrono.h b/beast/Chrono.h index 3d9c46a8f9..cc41b72f58 100644 --- a/beast/Chrono.h +++ b/beast/Chrono.h @@ -21,6 +21,7 @@ #define BEAST_CHRONO_H_INCLUDED #include "chrono/abstract_clock.h" +#include "chrono/basic_seconds_clock.h" #include "chrono/chrono_io.h" #include "chrono/chrono_util.h" #include "chrono/manual_clock.h" diff --git a/beast/Insight.h b/beast/Insight.h index 20efda393b..2ec5b42ed1 100644 --- a/beast/Insight.h +++ b/beast/Insight.h @@ -26,6 +26,8 @@ #include "insight/EventImpl.h" #include "insight/Gauge.h" #include "insight/GaugeImpl.h" +#include "insight/Group.h" +#include "insight/Groups.h" #include "insight/Hook.h" #include "insight/HookImpl.h" #include "insight/Collector.h" diff --git a/beast/chrono/Chrono.cpp b/beast/chrono/Chrono.cpp index dc50936e04..28f92f8ccd 100644 --- a/beast/chrono/Chrono.cpp +++ b/beast/chrono/Chrono.cpp @@ -24,6 +24,7 @@ #include "impl/abstract_clock.cpp" #include "impl/chrono_io.cpp" +#include "impl/basic_seconds_clock.cpp" #include "impl/CPUMeter.cpp" #include "impl/RelativeTime.cpp" diff --git a/beast/chrono/abstract_clock.h b/beast/chrono/abstract_clock.h index c47c1bd1fe..d150d267ce 100644 --- a/beast/chrono/abstract_clock.h +++ b/beast/chrono/abstract_clock.h @@ -121,7 +121,7 @@ template struct abstract_clock_wrapper : public basic_abstract_clock_wrapper { - // generic conversion displays the duration + // generic conversion displays the duration std::string to_string (typename basic_abstract_clock_wrapper < TrivialClock, Duration>::time_point const& tp) { diff --git a/beast/chrono/basic_seconds_clock.h b/beast/chrono/basic_seconds_clock.h new file mode 100644 index 0000000000..2e15fdcc42 --- /dev/null +++ b/beast/chrono/basic_seconds_clock.h @@ -0,0 +1,237 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef BEAST_CHRONO_BASIC_SECONDS_CLOCK_H_INCLUDED +#define BEAST_CHRONO_BASIC_SECONDS_CLOCK_H_INCLUDED + +#include +#include + +#ifndef BEAST_BASIC_SECONDS_CLOCK_BOOST_WORKAROUND +# ifdef _MSC_VER +// Visual Studio 2012, 2013 have a bug in std::thread that +// causes a hang on exit, in the library function atexit() +# if BEAST_USE_BOOST_FEATURES +# define BEAST_BASIC_SECONDS_CLOCK_BOOST_WORKAROUND 1 +# else +# define BEAST_BASIC_SECONDS_CLOCK_BOOST_WORKAROUND 0 +# endif +# else +# define BEAST_BASIC_SECONDS_CLOCK_BOOST_WORKAROUND 0 +# endif +#endif + +#if BEAST_BASIC_SECONDS_CLOCK_BOOST_WORKAROUND +# include +# if BOOST_VERSION >= 105500 +# include +# include +# include +# include +# else +# error "Boost version 1.55.0 or later is required" +# endif +#else +# include +# include +# include +#endif + +#include "../chrono/chrono_util.h" + +namespace beast { + +namespace detail { + +class seconds_clock_worker +{ +public: + virtual void sample () = 0; +}; + +//------------------------------------------------------------------------------ + +// Updates the clocks +class seconds_clock_thread +{ +public: +#if BEAST_BASIC_SECONDS_CLOCK_BOOST_WORKAROUND + typedef boost::mutex mutex; + typedef boost::condition_variable cond_var; + typedef boost::lock_guard lock_guard; + typedef boost::unique_lock unique_lock; + typedef boost::chrono::steady_clock clock_type; + typedef boost::chrono::seconds seconds; + typedef boost::thread thread; +#else + typedef std::mutex mutex; + typedef std::condition_variable cond_var; + typedef std::lock_guard lock_guard; + typedef std::unique_lock unique_lock; + typedef std::chrono::steady_clock clock_type; + typedef std::chrono::seconds seconds; + typedef std::thread thread; +#endif + typedef std::vector workers; + + bool m_stop; + mutex m_mutex; + cond_var m_cond; + workers m_workers; + thread m_thread; + + seconds_clock_thread () + : m_stop (false) + { + m_thread = thread (std::bind( + &seconds_clock_thread::run, this)); + } + + ~seconds_clock_thread () + { + { + lock_guard lock (m_mutex); + m_stop = true; + } + m_cond.notify_all(); + m_thread.join (); + } + + void add (seconds_clock_worker& w) + { + lock_guard lock (m_mutex); + m_workers.push_back (&w); + } + + void remove (seconds_clock_worker& w) + { + lock_guard lock (m_mutex); + m_workers.erase (std::find ( + m_workers.begin (), m_workers.end(), &w)); + } + + void run () + { + unique_lock lock (m_mutex);; + + for (;;) + { + for (auto iter : m_workers) + iter->sample(); + + clock_type::time_point const when ( + floor ( + clock_type::now().time_since_epoch()) + + seconds (1)); + + if (m_cond.wait_until (lock, when, [this]{ return m_stop; })) + return; + } + } + + static seconds_clock_thread& instance () + { + static seconds_clock_thread singleton; + return singleton; + } +}; + +} + +//------------------------------------------------------------------------------ + +/** A clock whose minimum resolution is one second. + The purpose of this class is to optimize the performance of the now() + member function call. It uses a dedicated thread that wakes up at least + once per second to sample the requested trivial clock. + @tparam TrivialClock The clock to sample. +*/ +template +class basic_seconds_clock +{ +public: + typedef std::chrono::seconds resolution; + typedef typename resolution::rep rep; + typedef typename resolution::period period; + typedef std::chrono::duration duration; + typedef std::chrono::time_point time_point; + + static bool const is_steady = TrivialClock::is_steady; + + static time_point now () + { + // Make sure the thread is constructed before the + // worker otherwise we will crash during destruction + // of objects with static storage duration. + struct initializer + { + initializer () + { + detail::seconds_clock_thread::instance(); + } + }; + static initializer init; + + struct worker : detail::seconds_clock_worker + { + typedef std::mutex mutex; + typedef std::lock_guard lock_guard; + + time_point m_now; + mutex m_mutex; + + static time_point get_now () + { + return time_point (floor ( + TrivialClock::now().time_since_epoch())); + } + + worker () + : m_now (get_now ()) + { + detail::seconds_clock_thread::instance().add (*this); + } + + ~worker () + { + detail::seconds_clock_thread::instance().remove (*this); + } + + time_point now() + { + lock_guard lock (m_mutex); + return m_now; + } + + void sample () + { + lock_guard lock (m_mutex); + m_now = get_now (); + } + }; + + static worker w; + + return w.now (); + } +}; + +} + +#endif diff --git a/beast/chrono/impl/basic_seconds_clock.cpp b/beast/chrono/impl/basic_seconds_clock.cpp new file mode 100644 index 0000000000..fcbdd17ee0 --- /dev/null +++ b/beast/chrono/impl/basic_seconds_clock.cpp @@ -0,0 +1,47 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#include "../basic_seconds_clock.h" + +#include "../../Config.h" +#include "../../../modules/beast_core/beast_core.h" // for UnitTest + +namespace beast { + +class basic_seconds_clock_Tests : public UnitTest +{ +public: + void runTest () + { + beginTestCase ("now"); + + auto const now (basic_seconds_clock < + std::chrono::steady_clock>::now ()); + + pass (); + } + + basic_seconds_clock_Tests() : UnitTest("basic_seconds_clock", "beast") + { + } +}; + +static basic_seconds_clock_Tests basic_seconds_clock_tests; + +} diff --git a/beast/insight/Base.h b/beast/insight/Base.h new file mode 100644 index 0000000000..f885d5fa92 --- /dev/null +++ b/beast/insight/Base.h @@ -0,0 +1,38 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef BEAST_INSIGHT_BASE_H_INCLUDED +#define BEAST_INSIGHT_BASE_H_INCLUDED + +#include + +namespace beast { +namespace insight { + +/** Base for all metrics and hooks. */ +class Base +{ +public: + virtual ~Base () = 0; +}; + +} +} + +#endif diff --git a/beast/insight/BaseImpl.h b/beast/insight/BaseImpl.h new file mode 100644 index 0000000000..86953efe0d --- /dev/null +++ b/beast/insight/BaseImpl.h @@ -0,0 +1,40 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef BEAST_INSIGHT_BASEIMPL_H_INCLUDED +#define BEAST_INSIGHT_BASEIMPL_H_INCLUDED + +#include + +namespace beast { +namespace insight { + +/** Base for all metrics and hook implementations. */ +class BaseImpl +{ +public: + typedef std::shared_ptr ptr; + + virtual ~BaseImpl () = 0; +}; + +} +} + +#endif diff --git a/beast/insight/Collector.h b/beast/insight/Collector.h index 5595d88c05..74bb8998a9 100644 --- a/beast/insight/Collector.h +++ b/beast/insight/Collector.h @@ -73,22 +73,58 @@ public: /** Create a counter with the specified name. @see Counter */ + /** @{ */ virtual Counter make_counter (std::string const& name) = 0; + + Counter make_counter (std::string const& prefix, std::string const& name) + { + if (prefix.empty ()) + return make_counter (name); + return make_counter (prefix + "." + name); + } + /** @} */ /** Create an event with the specified name. @see Event */ + /** @{ */ virtual Event make_event (std::string const& name) = 0; + Event make_event (std::string const& prefix, std::string const& name) + { + if (prefix.empty ()) + return make_event (name); + return make_event (prefix + "." + name); + } + /** @} */ + /** Create a gauge with the specified name. @see Gauge */ + /** @{ */ virtual Gauge make_gauge (std::string const& name) = 0; + Gauge make_gauge (std::string const& prefix, std::string const& name) + { + if (prefix.empty ()) + return make_gauge (name); + return make_gauge (prefix + "." + name); + } + /** @} */ + /** Create a meter with the specified name. @see Meter */ + /** @{ */ virtual Meter make_meter (std::string const& name) = 0; + + Meter make_meter (std::string const& prefix, std::string const& name) + { + if (prefix.empty ()) + return make_meter (name); + return make_meter (prefix + "." + name); + } + /** @} */ }; } diff --git a/beast/insight/Counter.h b/beast/insight/Counter.h index 4e78013384..9f27128b66 100644 --- a/beast/insight/Counter.h +++ b/beast/insight/Counter.h @@ -22,6 +22,7 @@ #include +#include "Base.h" #include "CounterImpl.h" namespace beast { @@ -35,7 +36,7 @@ namespace insight { This is a lightweight reference wrapper which is cheap to copy and assign. When the last reference goes away, the metric is no longer collected. */ -class Counter +class Counter : public Base { public: typedef CounterImpl::value_type value_type; @@ -57,21 +58,6 @@ public: { } - /** Set a handler for polling. - If a handler is set, it will be called once per collection interval. - This may be used to implement polling style collection instead of - push style. - - Handler will be called with this signature: - void Handler (Counter const&); - */ - template - void set_handler (Handler handler) const - { - if (m_impl) - m_impl->set_handler (handler); - } - /** Increment the counter. */ /** @{ */ void increment (value_type amount) const @@ -99,6 +85,11 @@ public: { increment (-1); return *this; } /** @} */ + std::shared_ptr const& impl () const + { + return m_impl; + } + private: std::shared_ptr m_impl; }; diff --git a/beast/insight/CounterImpl.h b/beast/insight/CounterImpl.h index f6c0b6e0db..c1a0254be3 100644 --- a/beast/insight/CounterImpl.h +++ b/beast/insight/CounterImpl.h @@ -22,20 +22,22 @@ #include +#include "BaseImpl.h" + namespace beast { namespace insight { class Counter; -class CounterImpl : public std::enable_shared_from_this +class CounterImpl + : public std::enable_shared_from_this + , public BaseImpl { public: typedef int64 value_type; - typedef std::function HandlerType; virtual ~CounterImpl () = 0; virtual void increment (value_type amount) = 0; - virtual void set_handler (HandlerType const& handler) = 0; }; } diff --git a/beast/insight/Event.h b/beast/insight/Event.h index fac4be70e6..0bcf6df590 100644 --- a/beast/insight/Event.h +++ b/beast/insight/Event.h @@ -23,6 +23,7 @@ #include #include +#include "Base.h" #include "EventImpl.h" #include "../chrono/chrono_util.h" @@ -39,7 +40,7 @@ namespace insight { This is a lightweight reference wrapper which is cheap to copy and assign. When the last reference goes away, the metric is no longer collected. */ -class Event +class Event : public Base { public: typedef EventImpl::value_type value_type; @@ -67,6 +68,11 @@ public: m_impl->notify (ceil (value)); } + std::shared_ptr const& impl () const + { + return m_impl; + } + private: std::shared_ptr m_impl; }; diff --git a/beast/insight/EventImpl.h b/beast/insight/EventImpl.h index 567a1def2b..d2d684e555 100644 --- a/beast/insight/EventImpl.h +++ b/beast/insight/EventImpl.h @@ -22,12 +22,16 @@ #include +#include "BaseImpl.h" + namespace beast { namespace insight { class Event; -class EventImpl : public std::enable_shared_from_this +class EventImpl + : public std::enable_shared_from_this + , public BaseImpl { public: typedef std::chrono::milliseconds value_type; diff --git a/beast/insight/Gauge.h b/beast/insight/Gauge.h index 70fff9b05d..22875214f9 100644 --- a/beast/insight/Gauge.h +++ b/beast/insight/Gauge.h @@ -22,6 +22,7 @@ #include +#include "Base.h" #include "GaugeImpl.h" namespace beast { @@ -36,7 +37,7 @@ namespace insight { This is a lightweight reference wrapper which is cheap to copy and assign. When the last reference goes away, the metric is no longer collected. */ -class Gauge +class Gauge : public Base { public: typedef GaugeImpl::value_type value_type; @@ -59,21 +60,6 @@ public: { } - /** Set a handler for polling. - If a handler is set, it will be called once per collection interval. - This may be used to implement polling style collection instead of - push style. - - Handler will be called with this signature: - void Handler (Gauge const&); - */ - template - void set_handler (Handler handler) const - { - if (m_impl) - m_impl->set_handler (handler); - } - /** Set the value on the gauge. A Collector implementation should combine multiple calls to value changes into a single change if the calls occur within a single @@ -117,6 +103,11 @@ public: { increment (-1); return *this; } /** @} */ + std::shared_ptr const& impl () const + { + return m_impl; + } + private: std::shared_ptr m_impl; }; diff --git a/beast/insight/GaugeImpl.h b/beast/insight/GaugeImpl.h index e816e6ce7e..1f5794e958 100644 --- a/beast/insight/GaugeImpl.h +++ b/beast/insight/GaugeImpl.h @@ -20,25 +20,26 @@ #ifndef BEAST_INSIGHT_GAUGEIMPL_H_INCLUDED #define BEAST_INSIGHT_GAUGEIMPL_H_INCLUDED -#include #include +#include "BaseImpl.h" + namespace beast { namespace insight { class Gauge; -class GaugeImpl : public std::enable_shared_from_this +class GaugeImpl + : public std::enable_shared_from_this + , public BaseImpl { public: typedef uint64 value_type; typedef int64 difference_type; - typedef std::function HandlerType; virtual ~GaugeImpl () = 0; virtual void set (value_type value) = 0; virtual void increment (difference_type amount) = 0; - virtual void set_handler (HandlerType const& handler) = 0; }; } diff --git a/beast/insight/Group.h b/beast/insight/Group.h new file mode 100644 index 0000000000..273472914e --- /dev/null +++ b/beast/insight/Group.h @@ -0,0 +1,43 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef BEAST_INSIGHT_GROUP_H_INCLUDED +#define BEAST_INSIGHT_GROUP_H_INCLUDED + +#include + +#include "Collector.h" + +namespace beast { +namespace insight { + +/** A collector front-end that manages a group of metrics. */ +class Group : public Collector +{ +public: + typedef std::shared_ptr ptr; + + /** Returns the name of this group, for diagnostics. */ + virtual std::string const& name () const = 0; +}; + +} +} + +#endif diff --git a/beast/insight/Groups.h b/beast/insight/Groups.h new file mode 100644 index 0000000000..6138938205 --- /dev/null +++ b/beast/insight/Groups.h @@ -0,0 +1,55 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef BEAST_INSIGHT_GROUPS_H_INCLUDED +#define BEAST_INSIGHT_GROUPS_H_INCLUDED + +#include +#include + +#include "Collector.h" +#include "Group.h" + +namespace beast { +namespace insight { + +/** A container for managing a set of metric groups. */ +class Groups +{ +public: + virtual ~Groups() = 0; + + /** Find or create a new collector with a given name. */ + /** @{ */ + virtual Group::ptr const& get (std::string const& name) = 0; + + Group::ptr const& operator[] (std::string const& name) + { + return get (name); + } + /** @} */ +}; + +/** Create a group container that uses the specified collector. */ +std::unique_ptr make_Groups (Collector::ptr const& collector); + +} +} + +#endif diff --git a/beast/insight/Hook.h b/beast/insight/Hook.h index a529c0e1be..783477a4e7 100644 --- a/beast/insight/Hook.h +++ b/beast/insight/Hook.h @@ -20,15 +20,16 @@ #ifndef BEAST_INSIGHT_HOOK_H_INCLUDED #define BEAST_INSIGHT_HOOK_H_INCLUDED -#include "HookImpl.h" - #include +#include "Base.h" +#include "HookImpl.h" + namespace beast { namespace insight { /** A reference to a handler for performing polled collection. */ -class Hook +class Hook : public Base { public: /** Create a null hook. @@ -44,7 +45,11 @@ public: */ explicit Hook (std::shared_ptr const& impl) : m_impl (impl) + { } + + std::shared_ptr const& impl () const { + return m_impl; } private: diff --git a/beast/insight/HookImpl.h b/beast/insight/HookImpl.h index 6c8cda2a0e..84b2b3e7f2 100644 --- a/beast/insight/HookImpl.h +++ b/beast/insight/HookImpl.h @@ -23,10 +23,14 @@ #include #include +#include "BaseImpl.h" + namespace beast { namespace insight { -class HookImpl : public std::enable_shared_from_this +class HookImpl + : public std::enable_shared_from_this + , public BaseImpl { public: typedef std::function HandlerType; diff --git a/beast/insight/Insight.cpp b/beast/insight/Insight.cpp index 1426d5073d..eaf1faaea6 100644 --- a/beast/insight/Insight.cpp +++ b/beast/insight/Insight.cpp @@ -26,6 +26,8 @@ #include "../Insight.h" #include "impl/Collector.cpp" +#include "impl/Group.cpp" +#include "impl/Groups.cpp" #include "impl/Hook.cpp" #include "impl/Metric.cpp" #include "impl/NullCollector.cpp" diff --git a/beast/insight/Meter.h b/beast/insight/Meter.h index 2743e9c2cd..2cf3d38efe 100644 --- a/beast/insight/Meter.h +++ b/beast/insight/Meter.h @@ -20,10 +20,11 @@ #ifndef BEAST_INSIGHT_METER_H_INCLUDED #define BEAST_INSIGHT_METER_H_INCLUDED -#include "MeterImpl.h" - #include +#include "Base.h" +#include "MeterImpl.h" + namespace beast { namespace insight { @@ -34,7 +35,7 @@ namespace insight { This is a lightweight reference wrapper which is cheap to copy and assign. When the last reference goes away, the metric is no longer collected. */ -class Meter +class Meter : public Base { public: typedef MeterImpl::value_type value_type; @@ -54,20 +55,6 @@ public: : m_impl (impl) { } - /** Set a handler for polling. - If a handler is set, it will be called once per collection interval. - This may be used to implement polling style collection instead of - push style. - - Handler will be called with this signature: - void Handler (Meter const&); - */ - template - void set_handler (Handler handler) const - { - m_impl->set_handler (handler); - } - /** Increment the meter. */ /** @{ */ void increment (value_type amount) const @@ -95,6 +82,11 @@ public: } /** @} */ + std::shared_ptr const& impl () const + { + return m_impl; + } + private: std::shared_ptr m_impl; }; diff --git a/beast/insight/MeterImpl.h b/beast/insight/MeterImpl.h index ca3fffaa55..21dae58a0c 100644 --- a/beast/insight/MeterImpl.h +++ b/beast/insight/MeterImpl.h @@ -20,23 +20,24 @@ #ifndef BEAST_INSIGHT_METERIMPL_H_INCLUDED #define BEAST_INSIGHT_METERIMPL_H_INCLUDED -#include #include +#include "BaseImpl.h" + namespace beast { namespace insight { class Meter; -class MeterImpl : public std::enable_shared_from_this +class MeterImpl + : public std::enable_shared_from_this + , public BaseImpl { public: typedef uint64 value_type; - typedef std::function HandlerType; virtual ~MeterImpl () = 0; virtual void increment (value_type amount) = 0; - virtual void set_handler (HandlerType const& handler) = 0; }; } diff --git a/beast/insight/impl/Group.cpp b/beast/insight/impl/Group.cpp new file mode 100644 index 0000000000..a80baa47b1 --- /dev/null +++ b/beast/insight/impl/Group.cpp @@ -0,0 +1,28 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +namespace beast { +namespace insight { + +namespace detail { + +} + +} +} diff --git a/beast/insight/impl/Groups.cpp b/beast/insight/impl/Groups.cpp new file mode 100644 index 0000000000..186cb87bbd --- /dev/null +++ b/beast/insight/impl/Groups.cpp @@ -0,0 +1,144 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#include + +#include "../../make_unique.h" + +namespace beast { +namespace insight { + +namespace detail { + +class GroupImp + : public std::enable_shared_from_this + , public Group +{ +public: + typedef std::vector > Items; + + std::string const m_name; + Collector::ptr m_collector; + Items m_items; + + GroupImp (std::string const& name_, + Collector::ptr const& collector) + : m_name (name_) + , m_collector (collector) + { + } + + ~GroupImp () + { + } + + std::string const& name () const + { + return m_name; + } + + std::string make_name (std::string const& name) + { + return m_name + "." + name; + } + + Hook make_hook (HookImpl::HandlerType const& handler) + { + Hook hook (m_collector->make_hook (handler)); + m_items.emplace_back (hook.impl ()); + return hook; + } + + Counter make_counter (std::string const& name) + { + Counter counter (m_collector->make_counter (make_name (name))); + m_items.emplace_back (counter.impl ()); + return counter; + } + + Event make_event (std::string const& name) + { + Event event (m_collector->make_event (make_name (name))); + m_items.emplace_back (event.impl ()); + return event; + } + + Gauge make_gauge (std::string const& name) + { + Gauge gauge (m_collector->make_gauge (make_name (name))); + m_items.emplace_back (gauge.impl ()); + return gauge; + } + + Meter make_meter (std::string const& name) + { + Meter meter (m_collector->make_meter (make_name (name))); + m_items.emplace_back (meter.impl ()); + return meter; + } + +private: + GroupImp& operator= (GroupImp const&); +}; + +//------------------------------------------------------------------------------ + +class GroupsImp : public Groups +{ +public: + typedef std::unordered_map > Items; + + Collector::ptr m_collector; + Items m_items; + + GroupsImp (Collector::ptr const& collector) + : m_collector (collector) + { + } + + ~GroupsImp () + { + } + + Group::ptr const& get (std::string const& name) + { + std::pair result ( + m_items.emplace (name, Group::ptr ())); + Group::ptr& group (result.first->second); + if (result.second) + group = std::make_shared (name, m_collector); + return group; + } +}; + +} + +//------------------------------------------------------------------------------ + +Groups::~Groups () +{ +} + +std::unique_ptr make_Groups (Collector::ptr const& collector) +{ + return std::make_unique (collector); +} + +} +} diff --git a/beast/insight/impl/Metric.cpp b/beast/insight/impl/Metric.cpp index f40cd493bb..22a7bd0496 100644 --- a/beast/insight/impl/Metric.cpp +++ b/beast/insight/impl/Metric.cpp @@ -20,6 +20,14 @@ namespace beast { namespace insight { +Base::~Base () +{ +} + +BaseImpl::~BaseImpl () +{ +} + CounterImpl::~CounterImpl () { } diff --git a/beast/insight/impl/NullCollector.cpp b/beast/insight/impl/NullCollector.cpp index 97b242c322..cf7229de1e 100644 --- a/beast/insight/impl/NullCollector.cpp +++ b/beast/insight/impl/NullCollector.cpp @@ -37,10 +37,6 @@ public: { } - void set_handler (HandlerType const&) - { - } - private: NullCounterImpl& operator= (NullCounterImpl const&); }; @@ -71,10 +67,6 @@ public: { } - void set_handler (HandlerType const&) - { - } - private: NullGaugeImpl& operator= (NullGaugeImpl const&); }; @@ -88,10 +80,6 @@ public: { } - void set_handler (HandlerType const&) - { - } - private: NullMeterImpl& operator= (NullMeterImpl const&); }; diff --git a/beast/insight/impl/StatsDCollector.cpp b/beast/insight/impl/StatsDCollector.cpp index b99f52fc5b..744b3b2704 100644 --- a/beast/insight/impl/StatsDCollector.cpp +++ b/beast/insight/impl/StatsDCollector.cpp @@ -85,7 +85,6 @@ public: ~StatsDCounterImpl (); void increment (CounterImpl::value_type amount); - void set_handler (HandlerType const& handler); void flush (); void do_increment (CounterImpl::value_type amount); @@ -98,7 +97,6 @@ private: std::string m_name; CounterImpl::value_type m_value; bool m_dirty; - HandlerType m_handler; }; //------------------------------------------------------------------------------ @@ -138,7 +136,6 @@ public: void set (GaugeImpl::value_type value); void increment (GaugeImpl::difference_type amount); - void set_handler (HandlerType const& handler); void flush (); void do_set (GaugeImpl::value_type value); @@ -153,7 +150,6 @@ private: GaugeImpl::value_type m_last_value; GaugeImpl::value_type m_value; bool m_dirty; - HandlerType m_handler; }; //------------------------------------------------------------------------------ @@ -169,7 +165,6 @@ public: ~StatsDMeterImpl (); void increment (MeterImpl::value_type amount); - void set_handler (HandlerType const& handler); void flush (); void do_increment (MeterImpl::value_type amount); @@ -182,7 +177,6 @@ private: std::string m_name; MeterImpl::value_type m_value; bool m_dirty; - HandlerType m_handler; }; //------------------------------------------------------------------------------ @@ -480,11 +474,6 @@ void StatsDCounterImpl::increment (CounterImpl::value_type amount) shared_from_this ()), amount)); } -void StatsDCounterImpl::set_handler (HandlerType const& handler) -{ - m_handler = handler; -} - void StatsDCounterImpl::flush () { if (m_dirty) @@ -509,8 +498,6 @@ void StatsDCounterImpl::do_increment (CounterImpl::value_type amount) void StatsDCounterImpl::do_process () { - if (m_handler) - m_handler (Counter (shared_from_this ())); flush (); } @@ -580,11 +567,6 @@ void StatsDGaugeImpl::increment (GaugeImpl::difference_type amount) shared_from_this ()), amount)); } -void StatsDGaugeImpl::set_handler (HandlerType const& handler) -{ - m_handler = handler; -} - void StatsDGaugeImpl::flush () { if (m_dirty) @@ -636,8 +618,6 @@ void StatsDGaugeImpl::do_increment (GaugeImpl::difference_type amount) void StatsDGaugeImpl::do_process () { - if (m_handler) - m_handler (Gauge (shared_from_this ())); flush (); } @@ -666,11 +646,6 @@ void StatsDMeterImpl::increment (MeterImpl::value_type amount) shared_from_this ()), amount)); } -void StatsDMeterImpl::set_handler (HandlerType const& handler) -{ - m_handler = handler; -} - void StatsDMeterImpl::flush () { if (m_dirty) @@ -695,8 +670,6 @@ void StatsDMeterImpl::do_increment (MeterImpl::value_type amount) void StatsDMeterImpl::do_process () { - if (m_handler) - m_handler (Meter (shared_from_this ())); flush (); }