1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 * Ceph - scalable distributed file system
6 * Copyright (C) 2011 New Dream Network
7 * Copyright (C) 2017 OVH
9 * This is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License version 2.1, as published by the Free Software
12 * Foundation. See file COPYING.
17 #ifndef CEPH_COMMON_PERF_COUNTERS_H
18 #define CEPH_COMMON_PERF_COUNTERS_H
20 #include "common/config_obs.h"
21 #include "common/perf_histogram.h"
22 #include "common/Mutex.h"
23 #include "include/utime.h"
25 #include "common/config_obs.h"
26 #include "common/Mutex.h"
27 #include "common/ceph_time.h"
35 class PerfCountersBuilder
;
37 enum perfcounter_type_d
: uint8_t
40 PERFCOUNTER_TIME
= 0x1,
41 PERFCOUNTER_U64
= 0x2,
42 PERFCOUNTER_LONGRUNAVG
= 0x4,
43 PERFCOUNTER_COUNTER
= 0x8,
44 PERFCOUNTER_HISTOGRAM
= 0x10,
49 * A PerfCounters object is usually associated with a single subsystem.
50 * It contains counters which we modify to track performance and throughput
53 * PerfCounters can track several different types of values:
54 * 1) integer values & counters
55 * 2) floating-point values & counters
56 * 3) floating-point averages
57 * 4) 2D histograms of quantized value pairs
59 * The difference between values, counters and histograms is in how they are initialized
60 * and accessed. For a counter, use the inc(counter, amount) function (note
61 * that amount defaults to 1 if you don't set it). For a value, use the
62 * set(index, value) function. For histogram use the hinc(value1, value2) function.
63 * (For time, use the tinc and tset variants.)
65 * If for some reason you would like to reset your counters, you can do so using
66 * the set functions even if they are counters, and you can also
67 * increment your values if for some reason you wish to.
69 * For the time average, it returns the current value and
70 * the "avgcount" member when read off. avgcount is incremented when you call
71 * tinc. Calling tset on an average is an error and will assert out.
76 /** Represents a PerfCounters data element. */
77 struct perf_counter_data_any_d
{
78 perf_counter_data_any_d()
82 type(PERFCOUNTER_NONE
),
87 perf_counter_data_any_d(const perf_counter_data_any_d
& other
)
89 description(other
.description
),
92 u64(other
.u64
.read()) {
93 pair
<uint64_t,uint64_t> a
= other
.read_avg();
95 avgcount
.set(a
.second
);
96 avgcount2
.set(a
.second
);
97 if (other
.histogram
) {
98 histogram
.reset(new PerfHistogram
<>(*other
.histogram
));
103 const char *description
;
106 enum perfcounter_type_d type
;
109 atomic64_t avgcount2
;
110 std::unique_ptr
<PerfHistogram
<>> histogram
;
114 if (type
!= PERFCOUNTER_U64
) {
124 // read <sum, count> safely by making sure the post- and pre-count
125 // are identical; in other words the whole loop needs to be run
126 // without any intervening calls to inc, set, or tinc.
127 pair
<uint64_t,uint64_t> read_avg() const {
130 count
= avgcount2
.read();
132 } while (avgcount
.read() != count
);
133 return make_pair(sum
, count
);
137 template <typename T
>
139 pair
<uint64_t, T
> last
;
140 pair
<uint64_t, T
> cur
;
141 avg_tracker() : last(0, 0), cur(0, 0) {}
143 if (cur
.first
== last
.first
)
145 cur
.second
/ cur
.first
:
146 0; // no change, report avg over all time
147 return (cur
.second
- last
.second
) / (cur
.first
- last
.first
);
149 void consume_next(const pair
<uint64_t, T
> &next
) {
157 void inc(int idx
, uint64_t v
= 1);
158 void dec(int idx
, uint64_t v
= 1);
159 void set(int idx
, uint64_t v
);
160 uint64_t get(int idx
) const;
162 void tset(int idx
, utime_t v
);
163 void tinc(int idx
, utime_t v
, uint32_t avgcount
= 1);
164 void tinc(int idx
, ceph::timespan v
, uint32_t avgcount
= 1);
165 utime_t
tget(int idx
) const;
167 void hinc(int idx
, int64_t x
, int64_t y
);
170 void dump_formatted(ceph::Formatter
*f
, bool schema
,
171 const std::string
&counter
= "") {
172 dump_formatted_generic(f
, schema
, false, counter
);
174 void dump_formatted_histograms(ceph::Formatter
*f
, bool schema
,
175 const std::string
&counter
= "") {
176 dump_formatted_generic(f
, schema
, true, counter
);
178 pair
<uint64_t, uint64_t> get_tavg_ms(int idx
) const;
180 const std::string
& get_name() const;
181 void set_name(std::string s
) {
185 /// adjust priority values by some value
186 void set_prio_adjust(int p
) {
191 PerfCounters(CephContext
*cct
, const std::string
&name
,
192 int lower_bound
, int upper_bound
);
193 PerfCounters(const PerfCounters
&rhs
);
194 PerfCounters
& operator=(const PerfCounters
&rhs
);
195 void dump_formatted_generic(ceph::Formatter
*f
, bool schema
, bool histograms
,
196 const std::string
&counter
= "");
198 typedef std::vector
<perf_counter_data_any_d
> perf_counter_data_vec_t
;
204 const std::string m_lock_name
;
208 /** Protects m_data */
209 mutable Mutex m_lock
;
211 perf_counter_data_vec_t m_data
;
213 friend class PerfCountersBuilder
;
214 friend class PerfCountersCollection
;
217 class SortPerfCountersByName
{
219 bool operator()(const PerfCounters
* lhs
, const PerfCounters
* rhs
) const {
220 return (lhs
->get_name() < rhs
->get_name());
224 typedef std::set
<PerfCounters
*, SortPerfCountersByName
> perf_counters_set_t
;
227 * PerfCountersCollection manages PerfCounters objects for a Ceph process.
229 class PerfCountersCollection
232 PerfCountersCollection(CephContext
*cct
);
233 ~PerfCountersCollection();
234 void add(class PerfCounters
*l
);
235 void remove(class PerfCounters
*l
);
237 bool reset(const std::string
&name
);
239 void dump_formatted(ceph::Formatter
*f
, bool schema
,
240 const std::string
&logger
= "",
241 const std::string
&counter
= "") {
242 dump_formatted_generic(f
, schema
, false, logger
, counter
);
245 void dump_formatted_histograms(ceph::Formatter
*f
, bool schema
,
246 const std::string
&logger
= "",
247 const std::string
&counter
= "") {
248 dump_formatted_generic(f
, schema
, true, logger
, counter
);
251 typedef std::map
<std::string
,
252 PerfCounters::perf_counter_data_any_d
*> CounterMap
;
254 void with_counters(std::function
<void(const CounterMap
&)>) const;
257 void dump_formatted_generic(ceph::Formatter
*f
, bool schema
, bool histograms
,
258 const std::string
&logger
= "",
259 const std::string
&counter
= "");
263 /** Protects m_loggers */
264 mutable Mutex m_lock
;
266 perf_counters_set_t m_loggers
;
268 std::map
<std::string
, PerfCounters::perf_counter_data_any_d
*> by_path
;
270 friend class PerfCountersCollectionTest
;
273 /* Class for constructing a PerfCounters object.
275 * This class performs some validation that the parameters we have supplied are
276 * correct in create_perf_counters().
278 * In the future, we will probably get rid of the first/last arguments, since
279 * PerfCountersBuilder can deduce them itself.
281 class PerfCountersBuilder
284 PerfCountersBuilder(CephContext
*cct
, const std::string
&name
,
285 int first
, int last
);
286 ~PerfCountersBuilder();
288 // prio values: higher is better, and higher values get included in
289 // 'ceph daemonperf' (and similar) results.
292 PRIO_INTERESTING
= 8,
294 PRIO_UNINTERESTING
= 2,
297 void add_u64(int key
, const char *name
,
298 const char *description
=NULL
, const char *nick
= NULL
,
300 void add_u64_counter(int key
, const char *name
,
301 const char *description
=NULL
,
302 const char *nick
= NULL
,
304 void add_u64_avg(int key
, const char *name
,
305 const char *description
=NULL
,
306 const char *nick
= NULL
,
308 void add_time(int key
, const char *name
,
309 const char *description
=NULL
,
310 const char *nick
= NULL
,
312 void add_time_avg(int key
, const char *name
,
313 const char *description
=NULL
,
314 const char *nick
= NULL
,
316 void add_histogram(int key
, const char* name
,
317 PerfHistogramCommon::axis_config_d x_axis_config
,
318 PerfHistogramCommon::axis_config_d y_axis_config
,
319 const char *description
=NULL
,
320 const char* nick
= NULL
,
322 PerfCounters
* create_perf_counters();
324 PerfCountersBuilder(const PerfCountersBuilder
&rhs
);
325 PerfCountersBuilder
& operator=(const PerfCountersBuilder
&rhs
);
326 void add_impl(int idx
, const char *name
,
327 const char *description
, const char *nick
, int prio
, int ty
,
328 unique_ptr
<PerfHistogram
<>> histogram
= nullptr);
330 PerfCounters
*m_perf_counters
;