Blame view

include/histogramprovider.h 7.57 KB
b5d9e433   Peter M. Groen   Fixed License Hea...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
  /* ****************************************************************************
   * Copyright 2019 Open Systems Development BV                                 *
   *                                                                            *
   * Permission is hereby granted, free of charge, to any person obtaining a    *
   * copy of this software and associated documentation files (the "Software"), *
   * to deal in the Software without restriction, including without limitation  *
   * the rights to use, copy, modify, merge, publish, distribute, sublicense,   *
   * and/or sell copies of the Software, and to permit persons to whom the      *
   * Software is furnished to do so, subject to the following conditions:       *
   *                                                                            *
   * The above copyright notice and this permission notice shall be included in *
   * all copies or substantial portions of the Software.                        *
   *                                                                            *
   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,   *
   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL    *
   * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING    *
   * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER        *
   * DEALINGS IN THE SOFTWARE.                                                  *
   * ***************************************************************************/
51becbde   Peter M. Groen   Committed the ent...
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
  #ifndef OSDEV_COMPONENTS_MQTT_MEASUREMENT_HISTOGRAMPROVIDER_H
  #define OSDEV_COMPONENTS_MQTT_MEASUREMENT_HISTOGRAMPROVIDER_H
  
  // std
  #include <iostream>
  #include <memory>
  #include <string>
  #include <unordered_map>
  
  #include "compat-c++14.h"
  
  // mlogic::common
  #include "sharedreaderlock.h"
  
  #include "histogram.h"
  
  namespace osdev {
  namespace components {
  namespace mqtt {
  namespace measurement {
  
  /**
   * @brief This class provides the user with Entry class for putting measurements in a histogram.
   * @tparam TContext A tag type that is used to give the HistogramProvider a user defined context.
   * @tparam TValue Defines the value type that the histograms of this provider use.
   * @tparam Buckets The number of buckets to use on creation of a Histogram. The default number of buckets is 10.
   *
   * The TValue type must define the following publically visible members.
   *
   * value_type                - The underlying value type used in the histogram
   * const value_type minValue - The minimum value of the histogram
   * const value_type maxValue - The maximum value of the histogram
   * const char* unit          - The value unit.
   */
  template <typename TContext, typename TValue, std::size_t Buckets = 10>
  class HistogramProvider
  {
  public:
      using HistogramType = Histogram<typename TValue::value_type, Buckets>;
  
      /**
       * @brief Get the HistogramProvider instance.
       */
      static HistogramProvider& instance();
  
      /**
       * @brief Add a value to the histogram identified by id.
       * @param id Identifies the histogram to add the value to.
       * @param value The value to add.
       */
      void addValue(const std::string& id, typename TValue::value_type value);
  
      /**
       * @brief Log the histogram identified by id via the ILogger framework.
       * @param id The histogram to log. If no histogram is found no work is done.
       */
      void log(const std::string& id);
  
      /**
       * @brief Log the histograms via the ILogger framework.
       * @param onlyChanged When set to true only log histograms that have changed. Default is false.
       */
      void logAll(bool onlyChanged = false);
  
      /**
       * @brief Reset all the histograms.
       * @param logBeforeReset Flag that indicates whether the histogram needs to be logged before reset. Default is true.
       * @note Only changed histograms are logged.
       */
      void resetAll(bool logBeforeReset = true);
  
      /**
       * @return The logOnDestroy flag value.
       */
      bool logOnDestroy() const { return m_logOnDestroy; }
  
      /**
       * @brief Set the logOnDestroy flag.
       * @param logOnDest Log on destruction when true, do not log when set to false.
       */
      void setLogOnDestroy(bool logOnDest) { m_logOnDestroy = logOnDest; }
  
  private:
      HistogramProvider();
  
      /**
       * @brief On destruction the provider will log all its histogram information to stdout.
       * Since the destruction will happen as one of the last things in the process, stdout is
       * used for logging.
       */
      ~HistogramProvider();
  
      void log(const HistogramType& hist, bool onlyChanged);
  
      SharedReaderLock m_sharedLock;
      std::unordered_map<std::string, std::unique_ptr<HistogramType>> m_histograms;
      bool m_logOnDestroy; ///< Default is true.
  };
  
  // static
  template <typename TContext, typename TValue, std::size_t Buckets>
  HistogramProvider<TContext, TValue, Buckets>& HistogramProvider<TContext, TValue, Buckets>::instance()
  {
      static HistogramProvider<TContext, TValue, Buckets> s_provider;
      return s_provider;
  }
  
  template <typename TContext, typename TValue, std::size_t Buckets>
  void HistogramProvider<TContext, TValue, Buckets>::addValue(const std::string& id, typename TValue::value_type value)
  {
      OSDEV_COMPONENTS_SHAREDLOCK_SCOPE(m_sharedLock);
      auto it = m_histograms.find(id);
      if (m_histograms.end() == it) {
          OSDEV_COMPONENTS_EXCLUSIVELOCK_SCOPE(m_sharedLock);
          constexpr TValue val;
          it = (m_histograms.emplace(std::make_pair(id, std::make_unique<HistogramType>(id, val.minValue, val.maxValue, val.unit)))).first;
      }
      it->second->setValue(value);
  }
  
  template <typename TContext, typename TValue, std::size_t Buckets>
  void HistogramProvider<TContext, TValue, Buckets>::log(const std::string& id)
  {
      OSDEV_COMPONENTS_SHAREDLOCK_SCOPE(m_sharedLock);
      auto it = m_histograms.find(id);
      if (m_histograms.end() != it) {
          log(*(it->second), false);
      }
  }
  
  template <typename TContext, typename TValue, std::size_t Buckets>
  void HistogramProvider<TContext, TValue, Buckets>::logAll(bool onlyChanged)
  {
      OSDEV_COMPONENTS_SHAREDLOCK_SCOPE(m_sharedLock);
      for (const auto& h : m_histograms) {
          log(*h.second, onlyChanged);
      }
  }
  
  template <typename TContext, typename TValue, std::size_t Buckets>
  void HistogramProvider<TContext, TValue, Buckets>::resetAll(bool logBeforeReset)
  {
      OSDEV_COMPONENTS_SHAREDLOCK_SCOPE(m_sharedLock);
      for (const auto& h : m_histograms) {
          if (logBeforeReset) {
              log(*h.second, true); // only log the histograms that have changed
          }
          h.second->reset();
      }
  }
  
  template <typename TContext, typename TValue, std::size_t Buckets>
  HistogramProvider<TContext, TValue, Buckets>::HistogramProvider()
      : m_sharedLock()
      , m_histograms()
      , m_logOnDestroy(true)
  {
  }
  
  template <typename TContext, typename TValue, std::size_t Buckets>
  HistogramProvider<TContext, TValue, Buckets>::~HistogramProvider()
  {
      if (m_logOnDestroy) {
          for (const auto& h : m_histograms) {
              std::cout << *h.second << std::endl;
          }
      }
  }
  
  template <typename TContext, typename TValue, std::size_t Buckets>
  void HistogramProvider<TContext, TValue, Buckets>::log(const HistogramType& hist, bool onlyChanged)
  {
      if ((onlyChanged && hist.isUpdated()) || !onlyChanged) {
          MLOGIC_COMMON_INFO("HistogramProvider", "%1", hist);
      }
  }
  
  }       // End namespace measurement
  }       // End namespace mqtt
  }       // End namespace components
  }       // End namespace osdev
  
  #endif  // OSDEV_COMPONENTS_MQTT_MEASUREMENT_HISTOGRAMPROVIDER_H