Skip to content

File monitor_collect.hpp

File List > cubrid > src > monitor > monitor_collect.hpp

Go to the documentation of this file

/*
 * Copyright 2008 Search Solution Corporation
 * Copyright 2016 CUBRID Corporation
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 */

//
// monitor_collect.hpp - interface for collecting statistics
//

#if !defined _MONITOR_COLLECT_HPP_
#define _MONITOR_COLLECT_HPP_

#include "monitor_registration.hpp"
#include "monitor_statistic.hpp"
#include "monitor_transaction.hpp"

namespace cubmonitor
{

  // grouped statistics

  class timer
  {
    public:
      inline timer (void);

      inline void reset (void);
      inline duration time (void);

    private:
      time_point m_timept;
  };


  // name array builder
  //
  // populate on basename and variadic list of prefixes.

  void
  build_name_vector (std::vector<std::string> &names, const char *basename, const char *prefix);

  template <typename ... Args>
  void
  build_name_vector (std::vector<std::string> &names, const char *basename, const char *prefix, Args &&... args)
  {
    names.push_back (std::string (prefix) + basename);
    build_name_vector (names, basename, args...);
  }

  // Multi-statistics
  //
  // Group statistics together to provide detailed information about events

  // Timer statistics - one statistic based on time_rep
  //
  // T is template for time_rep based accumulator statistic
  //
  template <typename T = time_accumulator_statistic>
  class timer_statistic
  {
    public:
      class autotimer
      {
    public:
      autotimer () = delete;
      inline autotimer (timer_statistic &timer_stat, bool active = true);
      inline ~autotimer ();
    private:
      timer_statistic &m_stat;
      bool m_active;
      };

      timer_statistic (void);

      inline void time (const time_rep &d);     // add duration to timer
      inline void time (void);                  // add duration since last time () call to timer

      // fetching interface
      inline void fetch (statistic_value *destination, fetch_mode mode = FETCH_GLOBAL) const;
      inline std::size_t get_statistics_count (void) const;

      // get time
      inline time_rep get_time (fetch_mode mode = FETCH_GLOBAL) const;

      inline void reset_timer ();

    private:
      timer m_timer;          // internal timer
      T m_statistic;          // time statistic
  };
  // explicit instantiations as time_accumulator[_atomic]_statistic with or without transaction sheets
  template class timer_statistic<time_accumulator_statistic>;
  template class timer_statistic<time_accumulator_atomic_statistic>;
  template class timer_statistic<transaction_statistic<time_accumulator_statistic>>;
  template class timer_statistic<transaction_statistic<time_accumulator_atomic_statistic>>;

  // aliases
  using timer_stat = timer_statistic<time_accumulator_statistic>;
  using atomic_timer_stat = timer_statistic<time_accumulator_atomic_statistic>;
  using transaction_timer_stat = timer_statistic<transaction_statistic<time_accumulator_statistic>>;
  using transaction_atomic_timer_stat = timer_statistic<transaction_statistic<time_accumulator_atomic_statistic>>;

  // Counter/timer statistic - two statistics that count and time events
  //
  // A is template for amount_rep based accumulator statistic
  // T is template for time_rep based accumulator statistic
  //
  template <class A = amount_accumulator_statistic, class T = time_accumulator_statistic>
  class counter_timer_statistic
  {
    public:
      // autotimer times and increments statistic on destructor
      class autotimer
      {
    public:
      autotimer () = delete;
      inline autotimer (counter_timer_statistic &cts, bool active = true);
      inline ~autotimer ();
    private:
      counter_timer_statistic &m_stat;
      bool m_active;
      };

      inline counter_timer_statistic (void);

      inline void time_and_increment (const time_rep &d, const amount_rep &a = 1);    // add time and amount
      inline void time_and_increment (const amount_rep &a = 1);                       // add internal time and amount

      inline void reset_timer ();

      // fetch interface
      inline std::size_t get_statistics_count (void) const;
      inline void fetch (statistic_value *destination, fetch_mode mode = FETCH_GLOBAL) const;

      // getters
      inline amount_rep get_count (fetch_mode mode = FETCH_GLOBAL) const;
      inline time_rep get_time (fetch_mode mode = FETCH_GLOBAL) const;
      inline time_rep get_average_time (fetch_mode mode = FETCH_GLOBAL) const;

      // register statistic to monitor
      // three statistics are registers: counter, total time and average time (total / count)
      void register_to_monitor (monitor &mon, const char *basename) const;

    private:
      timer m_timer;                      // internal timer
      A m_amount_statistic;               // amount accumulator
      T m_time_statistic;                 // time accumulator
  };
  // explicit instantiations of counter_timer_statistic with atomic/non-atomic, with/without transactions
  template class counter_timer_statistic<amount_accumulator_statistic, time_accumulator_statistic>;
  template class counter_timer_statistic<amount_accumulator_atomic_statistic, time_accumulator_atomic_statistic>;

  template class counter_timer_statistic<transaction_statistic<amount_accumulator_statistic>,
                     transaction_statistic<time_accumulator_statistic>>;
  template class counter_timer_statistic<transaction_statistic<amount_accumulator_atomic_statistic>,
                     transaction_statistic<time_accumulator_atomic_statistic>>;

  // aliases
  using counter_timer_stat = counter_timer_statistic<>;
  using atomic_counter_timer_stat =
      counter_timer_statistic<amount_accumulator_atomic_statistic, time_accumulator_atomic_statistic>;

  // Counter/timer/max statistic - three statistics that count, time and save events longest duration
  //
  // A is template for amount_rep based accumulator statistic
  // T is template for time_rep based accumulator statistic
  // M is template for time_rep based max statistic
  template <class A = amount_accumulator_statistic, class T = time_accumulator_statistic, class M = time_max_statistic>
  class counter_timer_max_statistic
  {
    public:
      inline counter_timer_max_statistic (void);

      inline void time_and_increment (const time_rep &d, const amount_rep &a = 1);    // add time and amount
      inline void time_and_increment (const amount_rep &a = 1);                       // add internal time and amount

      // fetch interface
      inline std::size_t get_statistics_count (void) const;
      inline void fetch (statistic_value *destination, fetch_mode mode = FETCH_GLOBAL) const;

      // getters
      inline amount_rep get_count (fetch_mode mode = FETCH_GLOBAL) const;
      inline time_rep get_time (fetch_mode mode = FETCH_GLOBAL) const;
      inline time_rep get_average_time (fetch_mode mode = FETCH_GLOBAL) const;
      inline time_rep get_max_time (fetch_mode mode = FETCH_GLOBAL) const;

      // register statistic to monitor
      // three statistics are registers: counter, total time, max per unit time and average time (total / count)
      void register_to_monitor (monitor &mon, const char *basename) const;

    private:
      timer m_timer;
      A m_amount_statistic;
      T m_total_time_statistic;
      M m_max_time_statistic;
  };
  // explicit instantiations
  template class counter_timer_max_statistic<amount_accumulator_statistic, time_accumulator_statistic,
      time_max_statistic>;
  template class counter_timer_max_statistic<amount_accumulator_atomic_statistic, time_accumulator_atomic_statistic,
      time_max_atomic_statistic>;
  template class counter_timer_max_statistic<transaction_statistic<amount_accumulator_statistic>,
      transaction_statistic<time_accumulator_statistic>, transaction_statistic<time_max_statistic>>;
  template class counter_timer_max_statistic<transaction_statistic<amount_accumulator_atomic_statistic>,
      transaction_statistic<time_accumulator_atomic_statistic>, transaction_statistic<time_max_atomic_statistic>>;

  // template and inline implementation

  // timer_statistic

  template <typename T>
  timer_statistic<T>::timer_statistic (void)
    : m_timer ()
    , m_statistic ()
  {
    //
  }

  template <class T>
  void
  timer_statistic<T>::time (const time_rep &d)
  {
    m_statistic.collect (d);
  }

  template <class T>
  void
  timer_statistic<T>::time (void)
  {
    m_statistic.collect (m_timer.time ());    // use internal timer
  }

  template <class T>
  std::size_t
  timer_statistic<T>::get_statistics_count (void) const
  {
    return m_statistic.get_statistics_count ();
  }

  template <class T>
  void
  timer_statistic<T>::fetch (statistic_value *destination, fetch_mode mode /* = FETCH_GLOBAL */) const
  {
    m_statistic.fetch (destination, mode);
  }

  template <class T>
  time_rep
  timer_statistic<T>::get_time (fetch_mode mode /* = FETCH_GLOBAL */) const
  {
    return m_statistic.get_value (mode);
  }

  template <class T>
  void
  timer_statistic<T>::reset_timer ()
  {
    m_timer.reset ();
  }

  template <class T>
  timer_statistic<T>::autotimer::autotimer (timer_statistic &timer_stat, bool active)
    : m_stat (timer_stat)
    , m_active (active)
  {
    if (m_active)
      {
    m_stat.reset_timer ();
      }
  }

  template <class T>
  timer_statistic<T>::autotimer::~autotimer ()
  {
    if (m_active)
      {
    m_stat.time ();
      }
  }

  // counter_timer_statistic

  template <class A, class T>
  counter_timer_statistic<A, T>::counter_timer_statistic (void)
    : m_timer ()
    , m_amount_statistic ()
    , m_time_statistic ()
  {
    //
  }

  template <class A, class T>
  void
  counter_timer_statistic<A, T>::time_and_increment (const time_rep &d, const amount_rep &a /* = 1 */)
  {
    m_amount_statistic.collect (a);
    m_time_statistic.collect (d);
  }

  template <class A, class T>
  void
  counter_timer_statistic<A, T>::time_and_increment (const amount_rep &a /* = 1 */)
  {
    time_and_increment (m_timer.time (), a);      // use internal timer
  }

  template <class A, class T>
  void
  counter_timer_statistic<A, T>::reset_timer ()
  {
    m_timer.reset ();
  }

  template <class A, class T>
  std::size_t
  counter_timer_statistic<A, T>::get_statistics_count (void) const
  {
    return m_amount_statistic.get_statistics_count () + m_time_statistic.get_statistics_count ();
  }

  template <class A, class T>
  void
  counter_timer_statistic<A, T>::fetch (statistic_value *destination, fetch_mode mode /* = FETCH_GLOBAL */) const
  {
    std::size_t index = 0;

    m_amount_statistic.fetch (destination + index, mode);
    index += m_amount_statistic.get_statistics_count ();

    m_time_statistic.fetch (destination + index, mode);
    index += m_time_statistic.get_statistics_count ();

    assert (index == get_statistics_count ());
  }

  template <class A, class T>
  amount_rep
  counter_timer_statistic<A, T>::get_count (fetch_mode mode /* = FETCH_GLOBAL */) const
  {
    return m_amount_statistic.get_value (mode);
  }

  template <class A, class T>
  time_rep
  counter_timer_statistic<A, T>::get_time (fetch_mode mode /* = FETCH_GLOBAL */) const
  {
    return m_time_statistic.get_value (mode);
  }

  template <class A, class T>
  time_rep
  counter_timer_statistic<A, T>::get_average_time (fetch_mode mode /* = FETCH_GLOBAL */) const
  {
    return get_time (mode) / get_count (mode);
  }

  template <class A, class T>
  void
  counter_timer_statistic<A, T>::register_to_monitor (monitor &mon, const char *basename) const
  {
    // we register counter, timer and average

    const char *count_prefix = "Num_";
    const char *total_time_prefix = "Total_time_";
    const char *average_time_prefix = "Avg_time_";
    std::vector<std::string> names;
    build_name_vector (names, basename, count_prefix, total_time_prefix, average_time_prefix);

    std::size_t stat_count = get_statistics_count () + 1;
    assert (stat_count == names.size ());

    auto fetch_func = [&] (statistic_value * destination, fetch_mode mode)
    {
      this->fetch (destination, mode);
      destination[get_statistics_count ()] = statistic_value_cast (this->get_average_time (mode));
    };
    mon.register_statistics (stat_count, fetch_func, names);
  }

  template <class A, class T>
  counter_timer_statistic<A, T>::autotimer::autotimer (counter_timer_statistic &cts, bool active)
    : m_stat (cts)
    , m_active (active)
  {
    if (m_active)
      {
    m_stat.reset_timer ();
      }
  }

  template <class A, class T>
  counter_timer_statistic<A, T>::autotimer::~autotimer ()
  {
    if (m_active)
      {
    // will time duration from construction and increment once
    m_stat.time_and_increment ();
      }
  }

  // counter_timer_max_statistic

  template <class A, class T, class M>
  counter_timer_max_statistic<A, T, M>::counter_timer_max_statistic (void)
    : m_timer ()
    , m_amount_statistic ()
    , m_total_time_statistic ()
    , m_max_time_statistic ()
  {
    //
  }

  template <class A, class T, class M>
  void
  counter_timer_max_statistic<A, T, M>::time_and_increment (const time_rep &d, const amount_rep &a /* = 1 */)
  {
    m_amount_statistic.collect (a);
    m_total_time_statistic.collect (d);
    m_max_time_statistic.collect (d / a);
  }

  template <class A, class T, class M>
  void
  counter_timer_max_statistic<A, T, M>::time_and_increment (const amount_rep &a /* = 1 */)
  {
    time_and_increment (m_timer.time (), a);
  }

  template <class A, class T, class M>
  std::size_t
  counter_timer_max_statistic<A, T, M>::get_statistics_count (void) const
  {
    return m_amount_statistic.get_statistics_count ()
       + m_total_time_statistic.get_statistics_count ()
       + m_max_time_statistic.get_statistics_count ();
  }

  template <class A, class T, class M>
  void
  counter_timer_max_statistic<A, T, M>::fetch (statistic_value *destination,
      fetch_mode mode /* = FETCH_GLOBAL */) const
  {
    std::size_t index = 0;

    m_amount_statistic.fetch (destination + index, mode);
    index += m_amount_statistic.get_statistics_count ();

    m_total_time_statistic.fetch (destination + index, mode);
    index += m_total_time_statistic.get_statistics_count ();

    m_max_time_statistic.fetch (destination + index, mode);
    index += m_max_time_statistic.get_statistics_count ();

    assert (index == get_statistics_count ());
  }

  template <class A, class T, class M>
  amount_rep
  counter_timer_max_statistic<A, T, M>::get_count (fetch_mode mode /* = FETCH_GLOBAL */) const
  {
    return m_amount_statistic.get_value (mode);
  }

  template <class A, class T, class M>
  time_rep
  counter_timer_max_statistic<A, T, M>::get_time (fetch_mode mode /* = FETCH_GLOBAL */) const
  {
    return m_total_time_statistic.get_value (mode);
  }

  template <class A, class T, class M>
  time_rep
  counter_timer_max_statistic<A, T, M>::get_max_time (fetch_mode mode /* = FETCH_GLOBAL */) const
  {
    return m_max_time_statistic.get_value (mode);
  }

  template <class A, class T, class M>
  time_rep
  counter_timer_max_statistic<A, T, M>::get_average_time (fetch_mode mode /* = FETCH_GLOBAL */) const
  {
    return get_time (mode) / get_count (mode);
  }

  template <class A, class T, class M>
  void
  counter_timer_max_statistic<A, T, M>::register_to_monitor (monitor &mon, const char *basename) const
  {
    // we register counter, timer, max and average

    const char *count_prefix = "Num_";
    const char *total_time_prefix = "Total_time_";
    const char *max_time_prefix = "Max_time_";
    const char *average_time_prefix = "Avg_time_";
    std::vector<std::string> names;
    build_name_vector (names, basename, count_prefix, total_time_prefix, max_time_prefix, average_time_prefix);

    std::size_t stat_count = get_statistics_count () + 1;
    assert (stat_count == names.size ());

    auto fetch_func = [&] (statistic_value * destination, fetch_mode mode)
    {
      this->fetch (destination, mode);
      destination[get_statistics_count ()] = statistic_value_cast (this->get_average_time (mode));
    };
    mon.register_statistics (stat_count, fetch_func, names);
  }

  //
  // timer
  //
  timer::timer (void)
    : m_timept (clock_type::now ())
  {
    //
  }

  void
  timer::reset (void)
  {
    m_timept = clock_type::now ();
  }

  duration
  timer::time (void)
  {
    time_point start_pt = m_timept;
    m_timept = clock_type::now ();
    return m_timept - start_pt;
  }

} // namespace cubmonitor

#endif // _MONITOR_COLLECT_HPP_