Seastar
High performance C++ framework for concurrent servers
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Modules Pages
metrics_api.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
25#include <seastar/util/modules.hh>
26#include <seastar/core/shared_ptr.hh>
27#include <seastar/core/sharded.hh>
28#ifndef SEASTAR_MODULE
29#include <boost/functional/hash.hpp>
30#endif
31
32#include <deque>
33
41namespace seastar {
42namespace metrics {
43namespace impl {
44
45using labels_type = std::map<sstring, sstring>;
46using internalized_labels_ref = lw_shared_ptr<const labels_type>;
47
48}
49}
50}
51
52namespace std {
53
54template<>
55struct hash<seastar::metrics::impl::labels_type> {
56 using argument_type = seastar::metrics::impl::labels_type;
57 using result_type = ::std::size_t;
58 result_type operator()(argument_type const& s) const {
59 result_type h = 0;
60 for (auto&& i : s) {
61 boost::hash_combine(h, std::hash<seastar::sstring>{}(i.second));
62 }
63 return h;
64 }
65};
66
67}
68
69namespace seastar {
70namespace metrics {
71
72SEASTAR_MODULE_EXPORT
73struct relabel_config;
74
75SEASTAR_MODULE_EXPORT
76struct metric_family_config;
88SEASTAR_MODULE_EXPORT
90 size_t metrics_relabeled_due_to_collision;
91};
92
93namespace impl {
94
109public:
110 metric_id() = default;
113 : _group(std::move(group)), _name(
114 std::move(name)), _labels(labels) {
115 }
116 metric_id(metric_id &&) = default;
117 metric_id(const metric_id &) = default;
118
119 metric_id & operator=(metric_id &&) = default;
120 metric_id & operator=(const metric_id &) = default;
121
122 const group_name_type & group_name() const {
123 return _group;
124 }
125 void group_name(const group_name_type & name) {
126 _group = name;
127 }
128 const instance_id_type & instance_id() const {
129 return _labels->at(shard_label.name());
130 }
131 const metric_name_type & name() const {
132 return _name;
133 }
134 const labels_type& labels() const {
135 return *_labels;
136 }
137 internalized_labels_ref internalized_labels() const {
138 return _labels;
139 }
140 void update_labels(internalized_labels_ref labels) {
141 _labels = labels;
142 }
143 sstring full_name() const;
144
145 bool operator<(const metric_id&) const;
146 bool operator==(const metric_id&) const;
147private:
148 auto as_tuple() const {
149 return std::tie(group_name(), instance_id(), name(), labels());
150 }
151 group_name_type _group;
152 metric_name_type _name;
154};
155}
156}
157}
158
159namespace std {
160
161template<>
162struct hash<seastar::metrics::impl::metric_id>
163{
165 typedef ::std::size_t result_type;
166 result_type operator()(argument_type const& s) const
167 {
168 result_type const h1 ( std::hash<seastar::sstring>{}(s.group_name()) );
169 result_type const h2 ( std::hash<seastar::sstring>{}(s.instance_id()) );
170 return h1 ^ (h2 << 1); // or use boost::hash_combine
171 }
172};
173
174}
175
176namespace seastar {
177namespace metrics {
178namespace impl {
179
187 data_type type;
188 metric_type_def inherit_type;
189 description d;
190 sstring name;
191 std::vector<std::string> aggregate_labels;
192};
193
194
199 metric_id id;
200 internalized_labels_ref original_labels;
201 bool enabled;
202 skip_when_empty should_skip_when_empty;
203};
204
207public:
208 explicit internalized_holder(labels_type labels) : _labels(make_lw_shared<labels_type>(std::move(labels))) {
209 }
210
211 explicit internalized_holder(internalized_labels_ref labels) : _labels(std::move(labels)) {
212 }
213
214 internalized_labels_ref labels_ref() const {
215 return _labels;
216 }
217
218 const labels_type& labels() const {
219 return *_labels;
220 }
221
222 size_t has_users() const {
223 // Getting the count wrong isn't a correctness issue but will just make internalization worse
224 return _labels.use_count() > 1;
225 }
226};
227
228inline bool operator<(const internalized_holder& lhs, const labels_type& rhs) {
229 return lhs.labels() < rhs;
230}
231inline bool operator<(const labels_type& lhs, const internalized_holder& rhs) {
232 return lhs < rhs.labels();
233}
234inline bool operator<(const internalized_holder& lhs, const internalized_holder& rhs) {
235 return lhs.labels() < rhs.labels();
236}
237
238
239class impl;
240
241class registered_metric final {
242 metric_info _info;
243 metric_function _f;
244public:
245 registered_metric(metric_id id, metric_function f, bool enabled=true, skip_when_empty skip=skip_when_empty::no);
246 metric_value operator()() const {
247 return _f();
248 }
249
250 bool is_enabled() const {
251 return _info.enabled;
252 }
253
254 void set_enabled(bool b) {
255 _info.enabled = b;
256 }
257 void set_skip_when_empty(skip_when_empty skip) noexcept {
258 _info.should_skip_when_empty = skip;
259 }
260 const metric_id& get_id() const {
261 return _info.id;
262 }
263
264 const metric_info& info() const {
265 return _info;
266 }
267 metric_info& info() {
268 return _info;
269 }
270 const metric_function& get_function() const {
271 return _f;
272 }
273};
274
276using metric_instances = std::map<internalized_holder, register_ref, std::less<>>;
277using metrics_registration = std::vector<register_ref>;
278
280 metrics_registration _registration;
281 shared_ptr<impl> _impl; // keep impl alive while metrics are registered
282public:
285 metric_groups_impl(const metric_groups_impl&) = delete;
287 metric_groups_impl& add_metric(group_name_type name, const metric_definition& md);
288 metric_groups_impl& add_group(group_name_type name, const std::initializer_list<metric_definition>& l);
289 metric_groups_impl& add_group(group_name_type name, const std::vector<metric_definition>& l);
290};
291
293 metric_instances _instances;
294 metric_family_info _info;
295public:
296 using iterator = metric_instances::iterator;
297 using const_iterator = metric_instances::const_iterator;
298
299 metric_family() = default;
300 metric_family(const metric_family&) = default;
301 metric_family(const metric_instances& instances) : _instances(instances) {
302 }
303 metric_family(const metric_instances& instances, const metric_family_info& info) : _instances(instances), _info(info) {
304 }
305 metric_family(metric_instances&& instances, metric_family_info&& info) : _instances(std::move(instances)), _info(std::move(info)) {
306 }
307 metric_family(metric_instances&& instances) : _instances(std::move(instances)) {
308 }
309
310 register_ref& operator[](const internalized_labels_ref& l) {
311 return _instances[internalized_holder(l)];
312 }
313
314 const register_ref& at(const internalized_labels_ref& l) const {
315 return _instances.at(internalized_holder(l));
316 }
317
318 metric_family_info& info() {
319 return _info;
320 }
321
322 const metric_family_info& info() const {
323 return _info;
324 }
325
326 iterator find(const labels_type& l) {
327 return _instances.find(l);
328 }
329
330 const_iterator find(const labels_type& l) const {
331 return _instances.find(l);
332 }
333
334 iterator begin() {
335 return _instances.begin();
336 }
337
338 const_iterator begin() const {
339 return _instances.cbegin();
340 }
341
342 iterator end() {
343 return _instances.end();
344 }
345
346 bool empty() const {
347 return _instances.empty();
348 }
349
350 iterator erase(const_iterator position) {
351 return _instances.erase(position);
352 }
353
354 const_iterator end() const {
355 return _instances.cend();
356 }
357
358 uint32_t size() const {
359 return _instances.size();
360 }
361
362};
363
364using value_map = std::map<sstring, metric_family>;
365
375 // prom backend only needs the label from here but scollectd needs group and
376 // metric name separately. metric_family_info only stores the merged and
377 // filtered name so we have to duplicate it here.
378 metric_id _id;
379 skip_when_empty _should_skip_when_empty;
380public:
381 metric_series_metadata() = default;
382 metric_series_metadata(metric_id id, skip_when_empty should_skip_when_empty)
383 : _id(std::move(id)), _should_skip_when_empty(should_skip_when_empty) {
384 }
385
387 metric_series_metadata& operator=(const metric_series_metadata&) = delete;
388
390 metric_series_metadata& operator=(metric_series_metadata&&) noexcept = default;
391
392 const labels_type& labels() const {
393 return _id.labels();
394 }
395
396 skip_when_empty should_skip_when_empty() const {
397 return _should_skip_when_empty;
398 }
399
400 group_name_type group_name() const {
401 return _id.group_name();
402 }
403
404 group_name_type name() const {
405 return _id.name();
406 }
407};
408
409using metric_metadata_fifo = std::deque<metric_series_metadata>;
410
425 metric_metadata_fifo metrics;
426
427 metric_family_metadata() = default;
429 metric_family_metadata &operator=(metric_family_metadata &&) = default;
430 metric_family_metadata(metric_family_info mf, metric_metadata_fifo metrics)
431 : mf(std::move(mf)), metrics(std::move(metrics)) {}
432};
433
434static_assert(std::is_nothrow_move_assignable_v<metric_family_metadata>);
435
436using value_vector = std::deque<metric_value>;
437using metric_metadata = std::vector<metric_family_metadata>;
438using metric_values = std::deque<value_vector>;
439
442 metric_values values;
443};
444
445struct config {
446 sstring hostname;
447};
448
449using internalized_set = std::set<internalized_holder, std::less<>>;
450
451class impl {
452 value_map _value_map;
453 config _config;
454 bool _dirty = true;
456 std::set<sstring> _labels;
457 std::vector<std::deque<metric_function>> _current_metrics;
458 std::vector<relabel_config> _relabel_configs;
459 std::vector<metric_family_config> _metric_family_configs;
460 internalized_set _internalized_labels;
461public:
462 value_map& get_value_map() {
463 return _value_map;
464 }
465
466 const value_map& get_value_map() const {
467 return _value_map;
468 }
469
470 register_ref 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);
471 internalized_labels_ref internalize_labels(labels_type labels);
472 void remove_registration(const metric_id& id);
473 future<> stop() {
474 return make_ready_future<>();
475 }
476 const config& get_config() const {
477 return _config;
478 }
479 void set_config(const config& c) {
480 _config = c;
481 }
482
484
485 std::vector<std::deque<metric_function>>& functions();
486
487 void update_metrics_if_needed();
488
489 void dirty() {
490 _dirty = true;
491 }
492
493 const std::set<sstring>& get_labels() const noexcept {
494 return _labels;
495 }
496
497 future<metric_relabeling_result> set_relabel_configs(const std::vector<relabel_config>& relabel_configs);
498
499 const std::vector<relabel_config>& get_relabel_configs() const noexcept {
500 return _relabel_configs;
501 }
502 const std::vector<metric_family_config>& get_metric_family_configs() const noexcept {
503 return _metric_family_configs;
504 }
505
506 void set_metric_family_configs(const std::vector<metric_family_config>& metrics_config);
507
508 void update_aggregate(metric_family_info& mf) const noexcept;
509
510private:
511 void gc_internalized_labels();
512 bool apply_relabeling(const relabel_config& rc, metric_info& info);
513};
514
515const value_map& get_value_map();
517
519
520shared_ptr<impl> get_local_impl();
521
522void unregister_metric(const metric_id & id);
523
530std::unique_ptr<metric_groups_def> create_metric_groups();
531
532}
533
540
542};
543
548
594future<metric_relabeling_result> set_relabel_configs(const std::vector<relabel_config>& relabel_configs);
595/*
596 * \brief return the current relabel_configs
597 * This function returns a vector of the current relabel configs
598 */
599const std::vector<relabel_config>& get_relabel_configs();
600
601/*
602 * \brief change the metrics family config
603 *
604 * Family config is a configuration that relates to all metrics with the same name but with different labels.
605 * set_metric_family_configs allows changing that configuration during run time.
606 * Specifically, change the label aggregation based on a metric name.
607 *
608 * The following is an example for setting the aggregate labels for the metric test_gauge_1
609 * and all metrics matching the regex test_gauge1.*:
610 *
611 * std::vector<sm::metric_family_config> fc(2);
612 * fc[0].name = "test_gauge_1";
613 * fc[0].aggregate_labels = { "lb" };
614 * fc[1].regex_name = "test_gauge1.*";
615 * fc[1].aggregate_labels = { "ll", "aa" };
616 * sm::set_metric_family_configs(fc);
617 */
618void set_metric_family_configs(const std::vector<metric_family_config>& metrics_config);
619
620/*
621 * \brief return the current metric_family_config
622 * This function returns a vector of the current metrics family config
623 */
624const std::vector<metric_family_config>& get_metric_family_configs();
625}
626}
Definition: sharded.hh:945
A representation of a possibly not-yet-computed value.
Definition: future.hh:1219
Human-readable description of a metric/group.
Definition: metrics.hh:133
Definition: metrics_api.hh:205
Definition: metrics_api.hh:292
Definition: metrics_api.hh:279
Definition: metrics_api.hh:108
Subset of the per series metadata that is shared via get_values to other shards.
Definition: metrics_api.hh:374
A helper class that used to return metrics value.
Definition: metrics.hh:294
Definition: metrics_api.hh:241
const sstring & name() const
returns the label name
Definition: metrics.hh:248
Definition: metrics_registration.hh:67
Definition: program-options.hh:293
Definition: shared_ptr.hh:507
sstring metric_type_def
Definition: metrics.hh:113
sstring metric_name_type
Definition: metrics.hh:114
sstring instance_id_type
Definition: metrics.hh:115
header for metrics creation.
std::unique_ptr< metric_groups_def > create_metric_groups()
initialize metric group
holds the implementation parts of the metrics layer, do not use directly.
sstring group_name_type
Definition: metrics_registration.hh:64
future configure(const options &opts)
set the metrics configuration
future< metric_relabeling_result > set_relabel_configs(const std::vector< relabel_config > &relabel_configs)
Perform relabeling and operation on metrics dynamically.
result of metric relabeling
Definition: metrics_api.hh:89
Seastar API namespace.
Definition: abort_on_ebadf.hh:26
STL namespace.
Definition: metrics_api.hh:445
holds metadata information of a metric family
Definition: metrics_api.hh:186
holds a metric family metadata
Definition: metrics_api.hh:423
holds metric metadata
Definition: metrics_api.hh:198
Definition: metrics.hh:369
Definition: metrics_api.hh:440
Metrics configuration options.
Definition: metrics_api.hh:535
program_options::value< std::string > metrics_hostname
The hostname used by the metrics.
Definition: metrics_api.hh:539
a relabel_config allows changing metrics labels dynamically
Definition: relabel_config.hh:101