Seastar
High performance C++ framework for concurrent servers
metrics.hh
Go to the documentation of this file.
1/*
2 * This file is open source software, licensed to you under the terms
3 * of the Apache License, Version 2.0 (the "License"). See the NOTICE file
4 * distributed with this work for additional information regarding copyright
5 * ownership. You may not use this file except in compliance with the License.
6 *
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing,
12 * software distributed under the License is distributed on an
13 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 * KIND, either express or implied. See the License for the
15 * specific language governing permissions and limitations
16 * under the License.
17 */
18/*
19 * Copyright (C) 2016 ScyllaDB.
20 */
21
22#pragma once
23
24#ifndef SEASTAR_MODULE
25#include <functional>
26#include <limits>
27#include <map>
28#include <type_traits>
29#include <variant>
30#include <fmt/format.h>
31#endif
32#include <seastar/core/sstring.hh>
33#include <seastar/core/shared_ptr.hh>
35#include <seastar/core/metrics_types.hh>
36#include <seastar/util/std-compat.hh>
37#include <seastar/util/bool_class.hh>
38#include <seastar/util/modules.hh>
39
51namespace seastar {
52
98namespace metrics {
99
100SEASTAR_MODULE_EXPORT_BEGIN
101
102class double_registration : public std::runtime_error {
103public:
104 double_registration(std::string what);
105};
106
113using metric_type_def = sstring;
114using metric_name_type = sstring;
115using instance_id_type = sstring;
117
134public:
135 description(sstring s = sstring()) : _s(std::move(s))
136 {}
137 const sstring& str() const {
138 return _s;
139 }
140private:
141 sstring _s;
142};
143
162 sstring _key;
163 sstring _value;
164public:
177 template<typename T>
178 label_instance(const sstring& key, T v) : _key(key), _value(fmt::to_string(v)){}
179
183 const sstring key() const {
184 return _key;
185 }
186
190 const sstring value() const {
191 return _value;
192 }
193 bool operator<(const label_instance&) const;
194 bool operator==(const label_instance&) const;
195 bool operator!=(const label_instance&) const;
196};
197
198
216class label {
217 sstring key;
218public:
219 using instance = label_instance;
225 explicit label(const sstring& key) : key(key) {
226 }
227
240 template<typename T>
241 instance operator()(T value) const {
242 return label_instance(key, std::forward<T>(value));
243 }
244
248 const sstring& name() const {
249 return key;
250 }
251};
252SEASTAR_MODULE_EXPORT_END
253
261namespace impl {
262
263// The value binding data types
264enum class data_type : uint8_t {
265 COUNTER,
266 REAL_COUNTER,
267 GAUGE,
268 HISTOGRAM,
269 SUMMARY,
270};
271
272template <bool callable, typename T>
274 using type = T;
275};
276
277template <typename T>
279 using type = std::invoke_result_t<T>;
280};
281
282template <typename T>
285 static constexpr bool is_integral = std::is_integral_v<typename real_traits::type>;
286 static constexpr data_type type = is_integral ? data_type::COUNTER : data_type::REAL_COUNTER;
287};
288
295public:
296 std::variant<double, histogram> u;
297 data_type _type;
298 data_type type() const {
299 return _type;
300 }
301
302 double d() const {
303 return std::get<double>(u);
304 }
305
306 uint64_t ui() const {
307 auto d = std::get<double>(u);
308 if (d >= 0 && d <= double(std::numeric_limits<long>::max())) {
309 return lround(d);
310 } else {
311 // double value is out of range or NaN or Inf
312 ulong_conversion_error(d);
313 return 0;
314 }
315 }
316
317 int64_t i() const {
318 auto d = std::get<double>(u);
319 if (d >= double(std::numeric_limits<long>::min()) && d <= double(std::numeric_limits<long>::max())) {
320 return lround(d);
321 } else {
322 // double value is out of range or NaN or Inf
323 ulong_conversion_error(d);
324 return 0;
325 }
326 }
327
329 : _type(data_type::GAUGE) {
330 }
331
332 metric_value(histogram&& h, data_type t = data_type::HISTOGRAM) :
333 u(std::move(h)), _type(t) {
334 }
335 metric_value(const histogram& h, data_type t = data_type::HISTOGRAM) :
336 u(h), _type(t) {
337 }
338
339 metric_value(double d, data_type t)
340 : u(d), _type(t) {
341 }
342
343 metric_value& operator+=(const metric_value& c) {
344 *this = *this + c;
345 return *this;
346 }
347
348 metric_value operator+(const metric_value& c);
349 const histogram& get_histogram() const {
350 return std::get<histogram>(u);
351 }
352
359 bool is_empty() const noexcept {
360 return ((_type == data_type::HISTOGRAM || _type == data_type::SUMMARY) && get_histogram().sample_count == 0) ||
361 ((_type == data_type::COUNTER || _type == data_type::REAL_COUNTER) && d() == 0);
362 }
363private:
364 static void ulong_conversion_error(double d);
365};
366
367using metric_function = std::function<metric_value()>;
368
370 data_type base_type;
371 metric_type_def type_name;
372};
373
375 metric_name_type name;
376 metric_type type;
377 metric_function f;
378 description d;
379 bool enabled = true;
380 skip_when_empty _skip_when_empty = skip_when_empty::no;
381 std::vector<std::string> aggregate_labels;
382 std::map<sstring, sstring> labels;
383 metric_definition_impl& operator ()(bool enabled);
384 metric_definition_impl& operator ()(const label_instance& label);
385 metric_definition_impl& operator ()(skip_when_empty skip) noexcept;
386 metric_definition_impl& aggregate(const std::vector<label>& labels) noexcept;
387 metric_definition_impl& set_skip_when_empty(bool skip=true) noexcept;
388 metric_definition_impl& set_type(const sstring& type_name);
390 metric_name_type name,
391 metric_type type,
392 metric_function f,
393 description d,
394 std::vector<label_instance> labels,
395 std::vector<label> aggregate_labels = {});
396};
397
399public:
400 metric_groups_def() = default;
401 virtual ~metric_groups_def() = default;
402 metric_groups_def(const metric_groups_def&) = delete;
404 virtual metric_groups_def& add_metric(group_name_type name, const metric_definition& md) = 0;
405 virtual metric_groups_def& add_group(group_name_type name, const std::initializer_list<metric_definition>& l) = 0;
406 virtual metric_groups_def& add_group(group_name_type name, const std::vector<metric_definition>& l) = 0;
407};
408
409instance_id_type shard();
410
411template<typename T, typename = std::enable_if_t<std::is_invocable_v<T>>>
412metric_function make_function(T val, data_type dt) {
413 return [dt, val = std::move(val)] {
414 return metric_value(val(), dt);
415 };
416}
417
418template<typename T, typename = std::enable_if_t<!std::is_invocable_v<T>>>
419metric_function make_function(T& val, data_type dt) {
420 return [dt, &val] {
421 return metric_value(val, dt);
422 };
423}
424}
425
426extern const bool metric_disabled;
427
428extern label shard_label;
429
430/*
431 * The metrics definition are defined to be compatible with collectd metrics defintion.
432 * Typically you should used gauge or derived.
433 */
434
435
441template<typename T>
443 T&& val, description d = description(), std::vector<label_instance> labels = {}) {
444 return {name, {impl::data_type::GAUGE, "gauge"}, make_function(std::forward<T>(val), impl::data_type::GAUGE), d, labels};
445}
446
452template<typename T>
454 description d, T&& val) {
455 return {name, {impl::data_type::GAUGE, "gauge"}, make_function(std::forward<T>(val), impl::data_type::GAUGE), d, {}};
456}
457
463template<typename T>
465 description d, std::vector<label_instance> labels, T&& val) {
466 return {name, {impl::data_type::GAUGE, "gauge"}, make_function(std::forward<T>(val), impl::data_type::GAUGE), d, labels};
467}
468
469
478template<typename T>
479[[deprecated("Use make_counter()")]]
481 T&& val, description d = description(), std::vector<label_instance> labels = {}) {
482 return make_counter(std::move(name), std::forward<T>(val), std::move(d), std::move(labels));
483}
484
485
494template<typename T>
495[[deprecated("Use make_counter()")]]
497 T&& val) {
498 return make_counter(std::move(name), std::forward<T>(val), std::move(d), {});
499}
500
501
510template<typename T>
511[[deprecated("Use make_counter()")]]
512impl::metric_definition_impl make_derive(metric_name_type name, description d, std::vector<label_instance> labels,
513 T&& val) {
514 return make_counter(std::move(name), std::forward<T>(val), std::move(d), std::move(labels));
515}
516
517
527template<typename T>
529 T&& val, description d = description(), std::vector<label_instance> labels = {}) {
530 auto type = impl::counter_type_traits<std::remove_reference_t<T>>::type;
531 return {name, {type, "counter"}, make_function(std::forward<T>(val), type), d, labels};
532}
533
543template<typename T>
545 return make_counter(std::move(name), std::forward<T>(val), std::move(d), {});
546}
547
557template<typename T>
558impl::metric_definition_impl make_counter(metric_name_type name, description d, std::vector<label_instance> labels, T&& val) {
559 return make_counter(std::move(name), std::forward<T>(val), std::move(d), std::move(labels));
560}
561
568template<typename T>
569[[deprecated("Use make_counter()")]]
571 T&& val, description d = description(), std::vector<label_instance> labels = {}) {
572 return make_counter(std::move(name), std::forward<T>(val), std::move(d), std::move(labels));
573}
574
581template<typename T>
583 T&& val, description d = description(), std::vector<label_instance> labels = {}) {
584 return {name, {impl::data_type::HISTOGRAM, "histogram"}, make_function(std::forward<T>(val), impl::data_type::HISTOGRAM), d, labels};
585}
586
593template<typename T>
595 description d, std::vector<label_instance> labels, T&& val) {
596 return {name, {impl::data_type::HISTOGRAM, "histogram"}, make_function(std::forward<T>(val), impl::data_type::HISTOGRAM), d, labels};
597}
598
599
606template<typename T>
608 description d, T&& val) {
609 return {name, {impl::data_type::HISTOGRAM, "histogram"}, make_function(std::forward<T>(val), impl::data_type::HISTOGRAM), d, {}};
610}
611
618template<typename T>
620 description d, T&& val) {
621 return {name, {impl::data_type::SUMMARY, "summary"}, make_function(std::forward<T>(val), impl::data_type::SUMMARY), d, {}};
622}
623
624
632template<typename T>
634 T&& val, description d = description(), std::vector<label_instance> labels = {},
635 instance_id_type = impl::shard()) {
636 return make_counter(name, std::forward<T>(val), d, labels).set_type("total_bytes");
637}
638
646template<typename T>
648 T&& val, description d = description(), std::vector<label_instance> labels = {},
649 instance_id_type = impl::shard()) {
650 return make_gauge(name, std::forward<T>(val), d, labels).set_type("bytes");
651}
652
653
660template<typename T>
662 T&& val, description d = description(), std::vector<label_instance> labels = {},
663 instance_id_type = impl::shard()) {
664 return make_gauge(name, std::forward<T>(val), d, labels).set_type("queue_length");
665}
666
667
674template<typename T>
676 T&& val, description d = description(), std::vector<label_instance> labels = {},
677 instance_id_type = impl::shard()) {
678 return make_counter(name, std::forward<T>(val), d, labels).set_type("total_operations");
679}
680
682}
683}
Human-readable description of a metric/group.
Definition: metrics.hh:133
Definition: metrics.hh:102
A helper class that used to return metrics value.
Definition: metrics.hh:294
bool is_empty() const noexcept
return true if this metric was never used
Definition: metrics.hh:359
Label a metrics.
Definition: metrics.hh:161
const sstring key() const
returns the label key
Definition: metrics.hh:183
label_instance(const sstring &key, T v)
create a label_instance label instance consists of key and value. The key is an sstring....
Definition: metrics.hh:178
const sstring value() const
returns the label value
Definition: metrics.hh:190
Class that creates label instances.
Definition: metrics.hh:216
instance operator()(T value) const
creating a label instance
Definition: metrics.hh:241
label(const sstring &key)
creating a label key is the label name, it will be the key for all label_instance that will be create...
Definition: metrics.hh:225
const sstring & name() const
returns the label name
Definition: metrics.hh:248
Definition: metrics_registration.hh:67
impl::metric_definition_impl make_queue_length(metric_name_type name, T &&val, description d=description(), std::vector< label_instance > labels={}, instance_id_type=impl::shard())
create a queue_length metric.
Definition: metrics.hh:661
sstring metric_type_def
Definition: metrics.hh:113
sstring metric_name_type
Definition: metrics.hh:114
impl::metric_definition_impl make_total_operations(metric_name_type name, T &&val, description d=description(), std::vector< label_instance > labels={}, instance_id_type=impl::shard())
create a total operation metric.
Definition: metrics.hh:675
sstring instance_id_type
Definition: metrics.hh:115
impl::metric_definition_impl make_total_bytes(metric_name_type name, T &&val, description d=description(), std::vector< label_instance > labels={}, instance_id_type=impl::shard())
create a total_bytes metric.
Definition: metrics.hh:633
impl::metric_definition_impl make_derive(metric_name_type name, T &&val, description d=description(), std::vector< label_instance > labels={})
Derive are used when a rate is more interesting than the value.
Definition: metrics.hh:480
impl::metric_definition_impl make_current_bytes(metric_name_type name, T &&val, description d=description(), std::vector< label_instance > labels={}, instance_id_type=impl::shard())
create a current_bytes metric.
Definition: metrics.hh:647
impl::metric_definition_impl make_summary(metric_name_type name, description d, T &&val)
create a summary metric.
Definition: metrics.hh:619
impl::metric_definition_impl make_gauge(metric_name_type name, T &&val, description d=description(), std::vector< label_instance > labels={})
Gauge are a general purpose metric.
Definition: metrics.hh:442
impl::metric_definition_impl make_absolute(metric_name_type name, T &&val, description d=description(), std::vector< label_instance > labels={})
create an absolute metric.
Definition: metrics.hh:570
impl::metric_definition_impl make_counter(metric_name_type name, T &&val, description d=description(), std::vector< label_instance > labels={})
create a counter metric
Definition: metrics.hh:528
impl::metric_definition_impl make_histogram(metric_name_type name, T &&val, description d=description(), std::vector< label_instance > labels={})
create a histogram metric.
Definition: metrics.hh:582
holds the metric_groups definition needed by class that reports metrics
holds the implementation parts of the metrics layer, do not use directly.
sstring group_name_type
Definition: metrics_registration.hh:64
Seastar API namespace.
Definition: abort_on_ebadf.hh:26
Histogram data type.
Definition: metrics_types.hh:69
Definition: metrics.hh:369