]> git.proxmox.com Git - ceph.git/blame - ceph/src/common/perf_counters.cc
import 15.2.0 Octopus source
[ceph.git] / ceph / src / common / perf_counters.cc
CommitLineData
7c673cae
FG
1// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2// vim: ts=8 sw=2 smarttab
3/*
4 * Ceph - scalable distributed file system
5 *
6 * Copyright (C) 2011 New Dream Network
7 * Copyright (C) 2017 OVH
8 *
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.
13 *
14 */
15
7c673cae
FG
16#include "common/perf_counters.h"
17#include "common/dout.h"
7c673cae 18#include "common/valgrind.h"
9f95a23c 19#include "include/common_fwd.h"
7c673cae 20
7c673cae
FG
21using std::ostringstream;
22
9f95a23c 23namespace TOPNSPC::common {
11fdf7f2 24PerfCountersCollectionImpl::PerfCountersCollectionImpl()
7c673cae
FG
25{
26}
27
11fdf7f2 28PerfCountersCollectionImpl::~PerfCountersCollectionImpl()
7c673cae
FG
29{
30 clear();
31}
32
11fdf7f2 33void PerfCountersCollectionImpl::add(PerfCounters *l)
7c673cae 34{
7c673cae
FG
35 // make sure the name is unique
36 perf_counters_set_t::iterator i;
37 i = m_loggers.find(l);
38 while (i != m_loggers.end()) {
39 ostringstream ss;
40 ss << l->get_name() << "-" << (void*)l;
41 l->set_name(ss.str());
42 i = m_loggers.find(l);
43 }
44
45 m_loggers.insert(l);
46
47 for (unsigned int i = 0; i < l->m_data.size(); ++i) {
48 PerfCounters::perf_counter_data_any_d &data = l->m_data[i];
49
50 std::string path = l->get_name();
51 path += ".";
52 path += data.name;
53
3efd9988 54 by_path[path] = {&data, l};
7c673cae
FG
55 }
56}
57
11fdf7f2 58void PerfCountersCollectionImpl::remove(PerfCounters *l)
7c673cae 59{
7c673cae
FG
60 for (unsigned int i = 0; i < l->m_data.size(); ++i) {
61 PerfCounters::perf_counter_data_any_d &data = l->m_data[i];
62
63 std::string path = l->get_name();
64 path += ".";
65 path += data.name;
66
67 by_path.erase(path);
68 }
69
70 perf_counters_set_t::iterator i = m_loggers.find(l);
11fdf7f2 71 ceph_assert(i != m_loggers.end());
7c673cae
FG
72 m_loggers.erase(i);
73}
74
11fdf7f2 75void PerfCountersCollectionImpl::clear()
7c673cae 76{
7c673cae
FG
77 perf_counters_set_t::iterator i = m_loggers.begin();
78 perf_counters_set_t::iterator i_end = m_loggers.end();
79 for (; i != i_end; ) {
11fdf7f2 80 delete *i;
7c673cae
FG
81 m_loggers.erase(i++);
82 }
83
84 by_path.clear();
85}
86
11fdf7f2 87bool PerfCountersCollectionImpl::reset(const std::string &name)
7c673cae
FG
88{
89 bool result = false;
7c673cae
FG
90 perf_counters_set_t::iterator i = m_loggers.begin();
91 perf_counters_set_t::iterator i_end = m_loggers.end();
92
93 if (!strcmp(name.c_str(), "all")) {
94 while (i != i_end) {
95 (*i)->reset();
96 ++i;
97 }
98 result = true;
99 } else {
100 while (i != i_end) {
101 if (!name.compare((*i)->get_name())) {
102 (*i)->reset();
103 result = true;
104 break;
105 }
106 ++i;
107 }
108 }
109
110 return result;
111}
112
113
114/**
115 * Serialize current values of performance counters. Optionally
116 * output the schema instead, or filter output to a particular
117 * PerfCounters or particular named counter.
118 *
119 * @param logger name of subsystem logger, e.g. "mds_cache", may be empty
120 * @param counter name of counter within subsystem, e.g. "num_strays",
121 * may be empty.
122 * @param schema if true, output schema instead of current data.
123 * @param histograms if true, dump histogram values,
124 * if false dump all non-histogram counters
125 */
11fdf7f2 126void PerfCountersCollectionImpl::dump_formatted_generic(
7c673cae
FG
127 Formatter *f,
128 bool schema,
129 bool histograms,
130 const std::string &logger,
eafe8130 131 const std::string &counter) const
7c673cae 132{
7c673cae
FG
133 f->open_object_section("perfcounter_collection");
134
135 for (perf_counters_set_t::iterator l = m_loggers.begin();
136 l != m_loggers.end(); ++l) {
137 // Optionally filter on logger name, pass through counter filter
138 if (logger.empty() || (*l)->get_name() == logger) {
139 (*l)->dump_formatted_generic(f, schema, histograms, counter);
140 }
141 }
142 f->close_section();
143}
144
11fdf7f2
TL
145void PerfCountersCollectionImpl::with_counters(std::function<void(
146 const PerfCountersCollectionImpl::CounterMap &)> fn) const
7c673cae 147{
7c673cae
FG
148 fn(by_path);
149}
150
151// ---------------------------
152
153PerfCounters::~PerfCounters()
154{
155}
156
157void PerfCounters::inc(int idx, uint64_t amt)
158{
11fdf7f2 159#ifndef WITH_SEASTAR
7c673cae
FG
160 if (!m_cct->_conf->perf)
161 return;
11fdf7f2 162#endif
7c673cae 163
11fdf7f2
TL
164 ceph_assert(idx > m_lower_bound);
165 ceph_assert(idx < m_upper_bound);
7c673cae
FG
166 perf_counter_data_any_d& data(m_data[idx - m_lower_bound - 1]);
167 if (!(data.type & PERFCOUNTER_U64))
168 return;
169 if (data.type & PERFCOUNTER_LONGRUNAVG) {
31f18b77
FG
170 data.avgcount++;
171 data.u64 += amt;
172 data.avgcount2++;
7c673cae 173 } else {
31f18b77 174 data.u64 += amt;
7c673cae
FG
175 }
176}
177
178void PerfCounters::dec(int idx, uint64_t amt)
179{
11fdf7f2 180#ifndef WITH_SEASTAR
7c673cae
FG
181 if (!m_cct->_conf->perf)
182 return;
11fdf7f2 183#endif
7c673cae 184
11fdf7f2
TL
185 ceph_assert(idx > m_lower_bound);
186 ceph_assert(idx < m_upper_bound);
7c673cae 187 perf_counter_data_any_d& data(m_data[idx - m_lower_bound - 1]);
11fdf7f2 188 ceph_assert(!(data.type & PERFCOUNTER_LONGRUNAVG));
7c673cae
FG
189 if (!(data.type & PERFCOUNTER_U64))
190 return;
31f18b77 191 data.u64 -= amt;
7c673cae
FG
192}
193
194void PerfCounters::set(int idx, uint64_t amt)
195{
11fdf7f2 196#ifndef WITH_SEASTAR
7c673cae
FG
197 if (!m_cct->_conf->perf)
198 return;
11fdf7f2 199#endif
7c673cae 200
11fdf7f2
TL
201 ceph_assert(idx > m_lower_bound);
202 ceph_assert(idx < m_upper_bound);
7c673cae
FG
203 perf_counter_data_any_d& data(m_data[idx - m_lower_bound - 1]);
204 if (!(data.type & PERFCOUNTER_U64))
205 return;
206
207 ANNOTATE_BENIGN_RACE_SIZED(&data.u64, sizeof(data.u64),
208 "perf counter atomic");
209 if (data.type & PERFCOUNTER_LONGRUNAVG) {
31f18b77
FG
210 data.avgcount++;
211 data.u64 = amt;
212 data.avgcount2++;
7c673cae 213 } else {
31f18b77 214 data.u64 = amt;
7c673cae
FG
215 }
216}
217
218uint64_t PerfCounters::get(int idx) const
219{
11fdf7f2 220#ifndef WITH_SEASTAR
7c673cae
FG
221 if (!m_cct->_conf->perf)
222 return 0;
11fdf7f2 223#endif
7c673cae 224
11fdf7f2
TL
225 ceph_assert(idx > m_lower_bound);
226 ceph_assert(idx < m_upper_bound);
7c673cae
FG
227 const perf_counter_data_any_d& data(m_data[idx - m_lower_bound - 1]);
228 if (!(data.type & PERFCOUNTER_U64))
229 return 0;
31f18b77 230 return data.u64;
7c673cae
FG
231}
232
11fdf7f2 233void PerfCounters::tinc(int idx, utime_t amt)
7c673cae 234{
11fdf7f2 235#ifndef WITH_SEASTAR
7c673cae
FG
236 if (!m_cct->_conf->perf)
237 return;
11fdf7f2 238#endif
7c673cae 239
11fdf7f2
TL
240 ceph_assert(idx > m_lower_bound);
241 ceph_assert(idx < m_upper_bound);
7c673cae
FG
242 perf_counter_data_any_d& data(m_data[idx - m_lower_bound - 1]);
243 if (!(data.type & PERFCOUNTER_TIME))
244 return;
245 if (data.type & PERFCOUNTER_LONGRUNAVG) {
31f18b77
FG
246 data.avgcount++;
247 data.u64 += amt.to_nsec();
248 data.avgcount2++;
7c673cae 249 } else {
31f18b77 250 data.u64 += amt.to_nsec();
7c673cae
FG
251 }
252}
253
11fdf7f2 254void PerfCounters::tinc(int idx, ceph::timespan amt)
7c673cae 255{
11fdf7f2 256#ifndef WITH_SEASTAR
7c673cae
FG
257 if (!m_cct->_conf->perf)
258 return;
11fdf7f2 259#endif
7c673cae 260
11fdf7f2
TL
261 ceph_assert(idx > m_lower_bound);
262 ceph_assert(idx < m_upper_bound);
7c673cae
FG
263 perf_counter_data_any_d& data(m_data[idx - m_lower_bound - 1]);
264 if (!(data.type & PERFCOUNTER_TIME))
265 return;
266 if (data.type & PERFCOUNTER_LONGRUNAVG) {
31f18b77
FG
267 data.avgcount++;
268 data.u64 += amt.count();
269 data.avgcount2++;
7c673cae 270 } else {
31f18b77 271 data.u64 += amt.count();
7c673cae
FG
272 }
273}
274
275void PerfCounters::tset(int idx, utime_t amt)
276{
11fdf7f2 277#ifndef WITH_SEASTAR
7c673cae
FG
278 if (!m_cct->_conf->perf)
279 return;
11fdf7f2 280#endif
7c673cae 281
11fdf7f2
TL
282 ceph_assert(idx > m_lower_bound);
283 ceph_assert(idx < m_upper_bound);
7c673cae
FG
284 perf_counter_data_any_d& data(m_data[idx - m_lower_bound - 1]);
285 if (!(data.type & PERFCOUNTER_TIME))
286 return;
31f18b77 287 data.u64 = amt.to_nsec();
7c673cae
FG
288 if (data.type & PERFCOUNTER_LONGRUNAVG)
289 ceph_abort();
290}
291
292utime_t PerfCounters::tget(int idx) const
293{
11fdf7f2 294#ifndef WITH_SEASTAR
7c673cae
FG
295 if (!m_cct->_conf->perf)
296 return utime_t();
11fdf7f2 297#endif
7c673cae 298
11fdf7f2
TL
299 ceph_assert(idx > m_lower_bound);
300 ceph_assert(idx < m_upper_bound);
7c673cae
FG
301 const perf_counter_data_any_d& data(m_data[idx - m_lower_bound - 1]);
302 if (!(data.type & PERFCOUNTER_TIME))
303 return utime_t();
31f18b77 304 uint64_t v = data.u64;
7c673cae
FG
305 return utime_t(v / 1000000000ull, v % 1000000000ull);
306}
307
308void PerfCounters::hinc(int idx, int64_t x, int64_t y)
309{
11fdf7f2 310#ifndef WITH_SEASTAR
7c673cae
FG
311 if (!m_cct->_conf->perf)
312 return;
11fdf7f2 313#endif
7c673cae 314
11fdf7f2
TL
315 ceph_assert(idx > m_lower_bound);
316 ceph_assert(idx < m_upper_bound);
7c673cae
FG
317
318 perf_counter_data_any_d& data(m_data[idx - m_lower_bound - 1]);
11fdf7f2
TL
319 ceph_assert(data.type == (PERFCOUNTER_HISTOGRAM | PERFCOUNTER_COUNTER | PERFCOUNTER_U64));
320 ceph_assert(data.histogram);
7c673cae
FG
321
322 data.histogram->inc(x, y);
323}
324
11fdf7f2 325pair<uint64_t, uint64_t> PerfCounters::get_tavg_ns(int idx) const
7c673cae 326{
11fdf7f2 327#ifndef WITH_SEASTAR
7c673cae
FG
328 if (!m_cct->_conf->perf)
329 return make_pair(0, 0);
11fdf7f2 330#endif
7c673cae 331
11fdf7f2
TL
332 ceph_assert(idx > m_lower_bound);
333 ceph_assert(idx < m_upper_bound);
7c673cae
FG
334 const perf_counter_data_any_d& data(m_data[idx - m_lower_bound - 1]);
335 if (!(data.type & PERFCOUNTER_TIME))
336 return make_pair(0, 0);
337 if (!(data.type & PERFCOUNTER_LONGRUNAVG))
338 return make_pair(0, 0);
339 pair<uint64_t,uint64_t> a = data.read_avg();
11fdf7f2 340 return make_pair(a.second, a.first);
7c673cae
FG
341}
342
343void PerfCounters::reset()
344{
345 perf_counter_data_vec_t::iterator d = m_data.begin();
346 perf_counter_data_vec_t::iterator d_end = m_data.end();
347
348 while (d != d_end) {
349 d->reset();
350 ++d;
351 }
352}
353
354void PerfCounters::dump_formatted_generic(Formatter *f, bool schema,
eafe8130 355 bool histograms, const std::string &counter) const
7c673cae
FG
356{
357 f->open_object_section(m_name.c_str());
358
359 for (perf_counter_data_vec_t::const_iterator d = m_data.begin();
360 d != m_data.end(); ++d) {
361 if (!counter.empty() && counter != d->name) {
362 // Optionally filter on counter name
363 continue;
364 }
365
366 // Switch between normal and histogram view
367 bool is_histogram = (d->type & PERFCOUNTER_HISTOGRAM) != 0;
368 if (is_histogram != histograms) {
369 continue;
370 }
371
372 if (schema) {
373 f->open_object_section(d->name);
31f18b77
FG
374 // we probably should not have exposed this raw field (with bit
375 // values), but existing plugins rely on it so we're stuck with
376 // it.
7c673cae
FG
377 f->dump_int("type", d->type);
378
31f18b77
FG
379 if (d->type & PERFCOUNTER_COUNTER) {
380 f->dump_string("metric_type", "counter");
381 } else {
382 f->dump_string("metric_type", "gauge");
383 }
384
385 if (d->type & PERFCOUNTER_LONGRUNAVG) {
386 if (d->type & PERFCOUNTER_TIME) {
387 f->dump_string("value_type", "real-integer-pair");
388 } else {
389 f->dump_string("value_type", "integer-integer-pair");
390 }
391 } else if (d->type & PERFCOUNTER_HISTOGRAM) {
392 if (d->type & PERFCOUNTER_TIME) {
393 f->dump_string("value_type", "real-2d-histogram");
394 } else {
395 f->dump_string("value_type", "integer-2d-histogram");
396 }
7c673cae 397 } else {
31f18b77
FG
398 if (d->type & PERFCOUNTER_TIME) {
399 f->dump_string("value_type", "real");
400 } else {
401 f->dump_string("value_type", "integer");
402 }
7c673cae
FG
403 }
404
31f18b77 405 f->dump_string("description", d->description ? d->description : "");
7c673cae
FG
406 if (d->nick != NULL) {
407 f->dump_string("nick", d->nick);
408 } else {
409 f->dump_string("nick", "");
410 }
3efd9988 411 f->dump_int("priority", get_adjusted_priority(d->prio));
1adf2230 412
11fdf7f2 413 if (d->unit == UNIT_NONE) {
1adf2230 414 f->dump_string("units", "none");
11fdf7f2 415 } else if (d->unit == UNIT_BYTES) {
1adf2230
AA
416 f->dump_string("units", "bytes");
417 }
7c673cae
FG
418 f->close_section();
419 } else {
420 if (d->type & PERFCOUNTER_LONGRUNAVG) {
421 f->open_object_section(d->name);
422 pair<uint64_t,uint64_t> a = d->read_avg();
423 if (d->type & PERFCOUNTER_U64) {
424 f->dump_unsigned("avgcount", a.second);
425 f->dump_unsigned("sum", a.first);
426 } else if (d->type & PERFCOUNTER_TIME) {
427 f->dump_unsigned("avgcount", a.second);
428 f->dump_format_unquoted("sum", "%" PRId64 ".%09" PRId64,
429 a.first / 1000000000ull,
430 a.first % 1000000000ull);
31f18b77
FG
431 uint64_t count = a.second;
432 uint64_t sum_ns = a.first;
433 if (count) {
434 uint64_t avg_ns = sum_ns / count;
435 f->dump_format_unquoted("avgtime", "%" PRId64 ".%09" PRId64,
436 avg_ns / 1000000000ull,
437 avg_ns % 1000000000ull);
438 } else {
439 f->dump_format_unquoted("avgtime", "%" PRId64 ".%09" PRId64, 0, 0);
440 }
7c673cae
FG
441 } else {
442 ceph_abort();
443 }
444 f->close_section();
445 } else if (d->type & PERFCOUNTER_HISTOGRAM) {
11fdf7f2
TL
446 ceph_assert(d->type == (PERFCOUNTER_HISTOGRAM | PERFCOUNTER_COUNTER | PERFCOUNTER_U64));
447 ceph_assert(d->histogram);
7c673cae
FG
448 f->open_object_section(d->name);
449 d->histogram->dump_formatted(f);
450 f->close_section();
451 } else {
31f18b77 452 uint64_t v = d->u64;
7c673cae
FG
453 if (d->type & PERFCOUNTER_U64) {
454 f->dump_unsigned(d->name, v);
455 } else if (d->type & PERFCOUNTER_TIME) {
456 f->dump_format_unquoted(d->name, "%" PRId64 ".%09" PRId64,
457 v / 1000000000ull,
458 v % 1000000000ull);
459 } else {
460 ceph_abort();
461 }
462 }
463 }
464 }
465 f->close_section();
466}
467
468const std::string &PerfCounters::get_name() const
469{
470 return m_name;
471}
472
473PerfCounters::PerfCounters(CephContext *cct, const std::string &name,
474 int lower_bound, int upper_bound)
475 : m_cct(cct),
476 m_lower_bound(lower_bound),
477 m_upper_bound(upper_bound),
11fdf7f2 478 m_name(name)
9f95a23c 479#if !defined(WITH_SEASTAR) || defined(WITH_ALIEN)
11fdf7f2 480 ,
7c673cae 481 m_lock_name(std::string("PerfCounters::") + name.c_str()),
11fdf7f2
TL
482 m_lock(ceph::make_mutex(m_lock_name))
483#endif
7c673cae
FG
484{
485 m_data.resize(upper_bound - lower_bound - 1);
486}
487
488PerfCountersBuilder::PerfCountersBuilder(CephContext *cct, const std::string &name,
489 int first, int last)
490 : m_perf_counters(new PerfCounters(cct, name, first, last))
491{
492}
493
494PerfCountersBuilder::~PerfCountersBuilder()
495{
496 if (m_perf_counters)
497 delete m_perf_counters;
498 m_perf_counters = NULL;
499}
500
501void PerfCountersBuilder::add_u64_counter(
502 int idx, const char *name,
1adf2230 503 const char *description, const char *nick, int prio, int unit)
7c673cae
FG
504{
505 add_impl(idx, name, description, nick, prio,
1adf2230 506 PERFCOUNTER_U64 | PERFCOUNTER_COUNTER, unit);
7c673cae
FG
507}
508
509void PerfCountersBuilder::add_u64(
510 int idx, const char *name,
1adf2230 511 const char *description, const char *nick, int prio, int unit)
7c673cae 512{
1adf2230 513 add_impl(idx, name, description, nick, prio, PERFCOUNTER_U64, unit);
7c673cae
FG
514}
515
516void PerfCountersBuilder::add_u64_avg(
517 int idx, const char *name,
1adf2230 518 const char *description, const char *nick, int prio, int unit)
7c673cae
FG
519{
520 add_impl(idx, name, description, nick, prio,
1adf2230 521 PERFCOUNTER_U64 | PERFCOUNTER_LONGRUNAVG, unit);
7c673cae
FG
522}
523
524void PerfCountersBuilder::add_time(
525 int idx, const char *name,
526 const char *description, const char *nick, int prio)
527{
528 add_impl(idx, name, description, nick, prio, PERFCOUNTER_TIME);
529}
530
531void PerfCountersBuilder::add_time_avg(
532 int idx, const char *name,
533 const char *description, const char *nick, int prio)
534{
535 add_impl(idx, name, description, nick, prio,
536 PERFCOUNTER_TIME | PERFCOUNTER_LONGRUNAVG);
537}
538
31f18b77 539void PerfCountersBuilder::add_u64_counter_histogram(
7c673cae
FG
540 int idx, const char *name,
541 PerfHistogramCommon::axis_config_d x_axis_config,
542 PerfHistogramCommon::axis_config_d y_axis_config,
1adf2230 543 const char *description, const char *nick, int prio, int unit)
7c673cae
FG
544{
545 add_impl(idx, name, description, nick, prio,
1adf2230 546 PERFCOUNTER_U64 | PERFCOUNTER_HISTOGRAM | PERFCOUNTER_COUNTER, unit,
7c673cae
FG
547 unique_ptr<PerfHistogram<>>{new PerfHistogram<>{x_axis_config, y_axis_config}});
548}
549
550void PerfCountersBuilder::add_impl(
551 int idx, const char *name,
1adf2230 552 const char *description, const char *nick, int prio, int ty, int unit,
7c673cae
FG
553 unique_ptr<PerfHistogram<>> histogram)
554{
11fdf7f2
TL
555 ceph_assert(idx > m_perf_counters->m_lower_bound);
556 ceph_assert(idx < m_perf_counters->m_upper_bound);
7c673cae
FG
557 PerfCounters::perf_counter_data_vec_t &vec(m_perf_counters->m_data);
558 PerfCounters::perf_counter_data_any_d
559 &data(vec[idx - m_perf_counters->m_lower_bound - 1]);
11fdf7f2 560 ceph_assert(data.type == PERFCOUNTER_NONE);
7c673cae
FG
561 data.name = name;
562 data.description = description;
563 // nick must be <= 4 chars
564 if (nick) {
11fdf7f2 565 ceph_assert(strlen(nick) <= 4);
7c673cae
FG
566 }
567 data.nick = nick;
3efd9988 568 data.prio = prio ? prio : prio_default;
7c673cae 569 data.type = (enum perfcounter_type_d)ty;
1adf2230 570 data.unit = (enum unit_t) unit;
7c673cae
FG
571 data.histogram = std::move(histogram);
572}
573
574PerfCounters *PerfCountersBuilder::create_perf_counters()
575{
576 PerfCounters::perf_counter_data_vec_t::const_iterator d = m_perf_counters->m_data.begin();
577 PerfCounters::perf_counter_data_vec_t::const_iterator d_end = m_perf_counters->m_data.end();
31f18b77 578 for (; d != d_end; ++d) {
11fdf7f2
TL
579 ceph_assert(d->type != PERFCOUNTER_NONE);
580 ceph_assert(d->type & (PERFCOUNTER_U64 | PERFCOUNTER_TIME));
31f18b77 581 }
7c673cae
FG
582
583 PerfCounters *ret = m_perf_counters;
584 m_perf_counters = NULL;
585 return ret;
586}
587
9f95a23c 588}