]> git.proxmox.com Git - ceph.git/blame - ceph/src/seastar/include/seastar/core/metrics_api.hh
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / seastar / include / seastar / core / metrics_api.hh
CommitLineData
11fdf7f2
TL
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#include <seastar/core/metrics.hh>
25#include <unordered_map>
26#include <seastar/core/sharded.hh>
27#include <boost/functional/hash.hpp>
1e59de90 28
11fdf7f2
TL
29/*!
30 * \file metrics_api.hh
1e59de90 31 * \brief header file for metric API layer (like prometheus or collectd)
11fdf7f2
TL
32 *
33 *
34 *
35 */
36namespace seastar {
37namespace metrics {
38namespace impl {
39
40using labels_type = std::map<sstring, sstring>;
41}
42}
43}
44
45namespace std {
46
47template<>
48struct hash<seastar::metrics::impl::labels_type> {
49 using argument_type = seastar::metrics::impl::labels_type;
50 using result_type = ::std::size_t;
51 result_type operator()(argument_type const& s) const {
52 result_type h = 0;
53 for (auto&& i : s) {
54 boost::hash_combine(h, std::hash<seastar::sstring>{}(i.second));
55 }
56 return h;
57 }
58};
59
60}
61
62namespace seastar {
63namespace metrics {
1e59de90
TL
64struct relabel_config;
65
66/*!
67 * \brief result of metric relabeling
68 *
69 * The result of calling set_relabel_configs.
70 *
71 * metrics_relabeled_due_to_collision the number of metrics that caused conflict
72 * and were relabeled to avoid name collision.
73 *
74 * Non zero value indicates there were name collisions.
75 *
76 */
77struct metric_relabeling_result {
78 size_t metrics_relabeled_due_to_collision;
79};
80
11fdf7f2
TL
81namespace impl {
82
83/**
84 * Metrics are collected in groups that belongs to some logical entity.
85 * For example, different measurements of the cpu, will belong to group "cpu".
86 *
87 * Name is the metric name like used_objects or used_bytes
88 *
89 * Inherit type allows customizing one of the basic types (gauge, counter, derive).
90 *
91 * Instance_id is used to differentiate multiple instance of the metrics.
92 * In the seastar environment it is typical to have a metric per shard.
93 *
94 */
95
96class metric_id {
97public:
98 metric_id() = default;
99 metric_id(group_name_type group, metric_name_type name,
100 labels_type labels = {})
101 : _group(std::move(group)), _name(
102 std::move(name)), _labels(labels) {
103 }
104 metric_id(metric_id &&) = default;
105 metric_id(const metric_id &) = default;
106
107 metric_id & operator=(metric_id &&) = default;
108 metric_id & operator=(const metric_id &) = default;
109
110 const group_name_type & group_name() const {
111 return _group;
112 }
113 void group_name(const group_name_type & name) {
114 _group = name;
115 }
116 const instance_id_type & instance_id() const {
117 return _labels.at(shard_label.name());
118 }
119 const metric_name_type & name() const {
120 return _name;
121 }
11fdf7f2
TL
122 const labels_type& labels() const {
123 return _labels;
124 }
1e59de90
TL
125 labels_type& labels() {
126 return _labels;
127 }
11fdf7f2
TL
128 sstring full_name() const;
129
130 bool operator<(const metric_id&) const;
131 bool operator==(const metric_id&) const;
132private:
133 auto as_tuple() const {
f67539c2 134 return std::tie(group_name(), instance_id(), name(), labels());
11fdf7f2
TL
135 }
136 group_name_type _group;
137 metric_name_type _name;
138 labels_type _labels;
139};
140}
141}
142}
143
144namespace std {
145
146template<>
147struct hash<seastar::metrics::impl::metric_id>
148{
149 typedef seastar::metrics::impl::metric_id argument_type;
150 typedef ::std::size_t result_type;
151 result_type operator()(argument_type const& s) const
152 {
153 result_type const h1 ( std::hash<seastar::sstring>{}(s.group_name()) );
154 result_type const h2 ( std::hash<seastar::sstring>{}(s.instance_id()) );
155 return h1 ^ (h2 << 1); // or use boost::hash_combine
156 }
157};
158
159}
160
161namespace seastar {
162namespace metrics {
163namespace impl {
164
165/*!
166 * \brief holds metadata information of a metric family
167 *
168 * Holds the information that is shared between all metrics
169 * that belongs to the same metric_family
170 */
171struct metric_family_info {
172 data_type type;
f67539c2 173 metric_type_def inherit_type;
11fdf7f2
TL
174 description d;
175 sstring name;
1e59de90 176 std::vector<std::string> aggregate_labels;
11fdf7f2
TL
177};
178
179
180/*!
181 * \brief holds metric metadata
182 */
183struct metric_info {
184 metric_id id;
1e59de90 185 labels_type original_labels;
11fdf7f2 186 bool enabled;
1e59de90 187 skip_when_empty should_skip_when_empty;
11fdf7f2
TL
188};
189
190
191using metrics_registration = std::vector<metric_id>;
192
193class metric_groups_impl : public metric_groups_def {
194 metrics_registration _registration;
195public:
196 metric_groups_impl() = default;
197 ~metric_groups_impl();
198 metric_groups_impl(const metric_groups_impl&) = delete;
199 metric_groups_impl(metric_groups_impl&&) = default;
200 metric_groups_impl& add_metric(group_name_type name, const metric_definition& md);
201 metric_groups_impl& add_group(group_name_type name, const std::initializer_list<metric_definition>& l);
202 metric_groups_impl& add_group(group_name_type name, const std::vector<metric_definition>& l);
203};
204
205class impl;
206
207class registered_metric {
208 metric_info _info;
209 metric_function _f;
210 shared_ptr<impl> _impl;
211public:
1e59de90 212 registered_metric(metric_id id, metric_function f, bool enabled=true, skip_when_empty skip=skip_when_empty::no);
11fdf7f2
TL
213 virtual ~registered_metric() {}
214 virtual metric_value operator()() const {
215 return _f();
216 }
217
218 bool is_enabled() const {
219 return _info.enabled;
220 }
221
222 void set_enabled(bool b) {
223 _info.enabled = b;
224 }
1e59de90
TL
225 void set_skip_when_empty(skip_when_empty skip) noexcept {
226 _info.should_skip_when_empty = skip;
227 }
11fdf7f2
TL
228 const metric_id& get_id() const {
229 return _info.id;
230 }
231
232 const metric_info& info() const {
233 return _info;
234 }
1e59de90
TL
235 metric_info& info() {
236 return _info;
237 }
11fdf7f2
TL
238 metric_function& get_function() {
239 return _f;
240 }
241};
242
243using register_ref = shared_ptr<registered_metric>;
244using metric_instances = std::map<labels_type, register_ref>;
245
246class metric_family {
247 metric_instances _instances;
248 metric_family_info _info;
249public:
250 using iterator = metric_instances::iterator;
251 using const_iterator = metric_instances::const_iterator;
252
253 metric_family() = default;
254 metric_family(const metric_family&) = default;
255 metric_family(const metric_instances& instances) : _instances(instances) {
256 }
257 metric_family(const metric_instances& instances, const metric_family_info& info) : _instances(instances), _info(info) {
258 }
259 metric_family(metric_instances&& instances, metric_family_info&& info) : _instances(std::move(instances)), _info(std::move(info)) {
260 }
261 metric_family(metric_instances&& instances) : _instances(std::move(instances)) {
262 }
263
264 register_ref& operator[](const labels_type& l) {
265 return _instances[l];
266 }
267
268 const register_ref& at(const labels_type& l) const {
269 return _instances.at(l);
270 }
271
272 metric_family_info& info() {
273 return _info;
274 }
275
276 const metric_family_info& info() const {
277 return _info;
278 }
279
280 iterator find(const labels_type& l) {
281 return _instances.find(l);
282 }
283
284 const_iterator find(const labels_type& l) const {
285 return _instances.find(l);
286 }
287
288 iterator begin() {
289 return _instances.begin();
290 }
291
292 const_iterator begin() const {
293 return _instances.cbegin();
294 }
295
296 iterator end() {
297 return _instances.end();
298 }
299
300 bool empty() const {
301 return _instances.empty();
302 }
303
304 iterator erase(const_iterator position) {
305 return _instances.erase(position);
306 }
307
308 const_iterator end() const {
309 return _instances.cend();
310 }
311
312 uint32_t size() const {
313 return _instances.size();
314 }
315
316};
317
318using value_map = std::map<sstring, metric_family>;
319
320using metric_metadata_vector = std::vector<metric_info>;
321
322/*!
323 * \brief holds a metric family metadata
324 *
325 * The meta data of a metric family compose of the
326 * metadata of the family, and a vector of the metadata for
327 * each of the metric.
328 */
329struct metric_family_metadata {
330 metric_family_info mf;
331 metric_metadata_vector metrics;
332};
333
334using value_vector = std::vector<metric_value>;
335using metric_metadata = std::vector<metric_family_metadata>;
336using metric_values = std::vector<value_vector>;
337
338struct values_copy {
339 shared_ptr<metric_metadata> metadata;
340 metric_values values;
341};
342
343struct config {
344 sstring hostname;
345};
346
347class impl {
348 value_map _value_map;
349 config _config;
350 bool _dirty = true;
351 shared_ptr<metric_metadata> _metadata;
1e59de90 352 std::set<sstring> _labels;
11fdf7f2 353 std::vector<std::vector<metric_function>> _current_metrics;
1e59de90 354 std::vector<relabel_config> _relabel_configs;
11fdf7f2
TL
355public:
356 value_map& get_value_map() {
357 return _value_map;
358 }
359
360 const value_map& get_value_map() const {
361 return _value_map;
362 }
363
1e59de90 364 void add_registration(const metric_id& id, const metric_type& type, metric_function f, const description& d, bool enabled, skip_when_empty skip, const std::vector<std::string>& aggregate_labels);
11fdf7f2
TL
365 void remove_registration(const metric_id& id);
366 future<> stop() {
367 return make_ready_future<>();
368 }
369 const config& get_config() const {
370 return _config;
371 }
372 void set_config(const config& c) {
373 _config = c;
374 }
375
376 shared_ptr<metric_metadata> metadata();
377
378 std::vector<std::vector<metric_function>>& functions();
379
380 void update_metrics_if_needed();
381
382 void dirty() {
383 _dirty = true;
384 }
1e59de90
TL
385
386 const std::set<sstring>& get_labels() const noexcept {
387 return _labels;
388 }
389
390 future<metric_relabeling_result> set_relabel_configs(const std::vector<relabel_config>& relabel_configs);
391
392 const std::vector<relabel_config>& get_relabel_configs() const noexcept {
393 return _relabel_configs;
394 }
11fdf7f2
TL
395};
396
397const value_map& get_value_map();
398using values_reference = shared_ptr<values_copy>;
399
400foreign_ptr<values_reference> get_values();
401
402shared_ptr<impl> get_local_impl();
403
404void unregister_metric(const metric_id & id);
405
406/*!
407 * \brief initialize metric group
408 *
409 * Create a metric_group_def.
410 * No need to use it directly.
411 */
412std::unique_ptr<metric_groups_def> create_metric_groups();
413
414}
20effc67
TL
415
416/// Metrics configuration options.
417struct options : public program_options::option_group {
418 /// \brief The hostname used by the metrics.
419 ///
420 /// If not set, the local hostname will be used.
421 program_options::value<std::string> metrics_hostname;
422
423 options(program_options::option_group* parent_group);
424};
11fdf7f2
TL
425
426/*!
20effc67 427 * \brief set the metrics configuration
11fdf7f2 428 */
20effc67 429future<> configure(const options& opts);
11fdf7f2 430
1e59de90
TL
431/*!
432 * \brief Perform relabeling and operation on metrics dynamically.
433 *
434 * The function would return true if the changes were applied with no conflict
435 * or false, if there was a conflict in the registration.
436 *
437 * The general logic follows Prometheus metrics_relabel_config configuration.
438 * The relabel rules are applied one after the other.
439 * You can add or change a label. you can enable or disable a metric,
440 * in that case the metrics will not be reported at all.
441 * You can turn on and off the skip_when_empty flag.
442 *
443 * Using the Prometheus convention, the metric name is __name__.
444 * Names cannot be changed.
445 *
446 * Import notes:
447 * - The relabeling always starts from the original set of labels the metric
448 * was created with.
449 * - calling with an empty set will remove the relabel config and will
450 * return all metrics to their original labels
451 * - To prevent a situation that calling this function would crash the system.
452 * in a situation where a conflicting metrics name are entered, an additional label
453 * will be added to the labels with a unique ID.
454 *
455 * A few examples:
456 * To add a level label with a value 1, to the reactor_utilization metric:
457 * std::vector<sm::relabel_config> rl(1);
458 rl[0].source_labels = {"__name__"};
459 rl[0].target_label = "level";
460 rl[0].replacement = "1";
461 rl[0].expr = "reactor_utilization";
462 set_relabel_configs(rl);
463 *
464 * To report only the metrics with the level label equals 1
465 *
466 std::vector<sm::relabel_config> rl(2);
467 rl[0].source_labels = {"__name__"};
468 rl[0].action = sm::relabel_config::relabel_action::drop;
469
470 rl[1].source_labels = {"level"};
471 rl[1].expr = "1";
472 rl[1].action = sm::relabel_config::relabel_action::keep;
473 set_relabel_configs(rl);
474
475 */
476future<metric_relabeling_result> set_relabel_configs(const std::vector<relabel_config>& relabel_configs);
477/*
478 * \brief return the current relabel_configs
479 * This function returns a vector of the current relabel configs
480 */
481const std::vector<relabel_config>& get_relabel_configs();
482
11fdf7f2
TL
483}
484}