Coverage Report

Created: 2024-11-22 11:49

/root/doris/be/src/util/metrics.h
Line
Count
Source (jump to first uncovered line)
1
// Licensed to the Apache Software Foundation (ASF) under one
2
// or more contributor license agreements.  See the NOTICE file
3
// distributed with this work for additional information
4
// regarding copyright ownership.  The ASF licenses this file
5
// to you under the Apache License, Version 2.0 (the
6
// "License"); you may not use this file except in compliance
7
// with the License.  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
#pragma once
19
20
#include <rapidjson/document.h>
21
#include <rapidjson/rapidjson.h>
22
#include <stddef.h>
23
#include <stdint.h>
24
25
#include <atomic>
26
#include <functional>
27
#include <map>
28
#include <memory>
29
#include <mutex>
30
#include <sstream>
31
#include <string>
32
#include <unordered_map>
33
#include <utility>
34
#include <vector>
35
36
#include "util/core_local.h"
37
#include "util/histogram.h"
38
39
namespace doris {
40
41
namespace rj = RAPIDJSON_NAMESPACE;
42
43
enum class MetricType { COUNTER, GAUGE, HISTOGRAM, SUMMARY, UNTYPED };
44
45
enum class MetricUnit {
46
    NANOSECONDS,
47
    MICROSECONDS,
48
    MILLISECONDS,
49
    SECONDS,
50
    BYTES,
51
    ROWS,
52
    PERCENT,
53
    REQUESTS,
54
    OPERATIONS,
55
    BLOCKS,
56
    ROWSETS,
57
    CONNECTIONS,
58
    PACKETS,
59
    NOUNIT,
60
    FILESYSTEM
61
};
62
63
std::ostream& operator<<(std::ostream& os, MetricType type);
64
const char* unit_name(MetricUnit unit);
65
66
using Labels = std::unordered_map<std::string, std::string>;
67
68
class Metric {
69
public:
70
5.26k
    Metric() {}
71
5.20k
    virtual ~Metric() {}
72
    virtual std::string to_string() const = 0;
73
    virtual std::string to_prometheus(const std::string& display_name, const Labels& entity_labels,
74
                                      const Labels& metric_labels) const;
75
    virtual rj::Value to_json_value(rj::Document::AllocatorType& allocator) const = 0;
76
77
private:
78
    friend class MetricRegistry;
79
};
80
81
// Metric that only can increment
82
template <typename T>
83
class AtomicMetric : public Metric {
84
public:
85
3.31k
    AtomicMetric() : _value(T()) {}
_ZN5doris12AtomicMetricIlEC2Ev
Line
Count
Source
85
3.21k
    AtomicMetric() : _value(T()) {}
_ZN5doris12AtomicMetricImEC2Ev
Line
Count
Source
85
102
    AtomicMetric() : _value(T()) {}
86
3.27k
    virtual ~AtomicMetric() {}
_ZN5doris12AtomicMetricIlED2Ev
Line
Count
Source
86
3.17k
    virtual ~AtomicMetric() {}
_ZN5doris12AtomicMetricImED2Ev
Line
Count
Source
86
102
    virtual ~AtomicMetric() {}
87
88
262
    std::string to_string() const override { return std::to_string(value()); }
_ZNK5doris12AtomicMetricIlE9to_stringB5cxx11Ev
Line
Count
Source
88
243
    std::string to_string() const override { return std::to_string(value()); }
_ZNK5doris12AtomicMetricImE9to_stringB5cxx11Ev
Line
Count
Source
88
19
    std::string to_string() const override { return std::to_string(value()); }
89
90
271
    T value() const { return _value.load(); }
_ZNK5doris12AtomicMetricIlE5valueEv
Line
Count
Source
90
250
    T value() const { return _value.load(); }
_ZNK5doris12AtomicMetricImE5valueEv
Line
Count
Source
90
21
    T value() const { return _value.load(); }
91
92
40.7k
    void increment(const T& delta) { _value.fetch_add(delta); }
_ZN5doris12AtomicMetricIlE9incrementERKl
Line
Count
Source
92
40.7k
    void increment(const T& delta) { _value.fetch_add(delta); }
_ZN5doris12AtomicMetricImE9incrementERKm
Line
Count
Source
92
2
    void increment(const T& delta) { _value.fetch_add(delta); }
93
94
671
    void set_value(const T& value) { _value.store(value); }
_ZN5doris12AtomicMetricIlE9set_valueERKl
Line
Count
Source
94
556
    void set_value(const T& value) { _value.store(value); }
_ZN5doris12AtomicMetricImE9set_valueERKm
Line
Count
Source
94
115
    void set_value(const T& value) { _value.store(value); }
95
96
1
    rj::Value to_json_value(rj::Document::AllocatorType& allocator) const override {
97
1
        return rj::Value(value());
98
1
    }
_ZNK5doris12AtomicMetricIlE13to_json_valueERN9rapidjson19MemoryPoolAllocatorINS2_12CrtAllocatorEEE
Line
Count
Source
96
1
    rj::Value to_json_value(rj::Document::AllocatorType& allocator) const override {
97
1
        return rj::Value(value());
98
1
    }
Unexecuted instantiation: _ZNK5doris12AtomicMetricImE13to_json_valueERN9rapidjson19MemoryPoolAllocatorINS2_12CrtAllocatorEEE
99
100
protected:
101
    std::atomic<T> _value;
102
};
103
104
template <typename T>
105
class LockSimpleMetric : public Metric {
106
public:
107
582
    LockSimpleMetric() : _value(T()) {}
108
570
    virtual ~LockSimpleMetric() {}
109
110
35
    std::string to_string() const override { return std::to_string(value()); }
111
112
39
    T value() const {
113
39
        std::lock_guard<std::mutex> l(_lock);
114
39
        return _value;
115
39
    }
116
117
1
    void increment(const T& delta) {
118
1
        std::lock_guard<std::mutex> l(this->_lock);
119
1
        _value += delta;
120
1
    }
121
122
4
    void set_value(const T& value) {
123
4
        std::lock_guard<std::mutex> l(this->_lock);
124
4
        _value = value;
125
4
    }
126
127
0
    rj::Value to_json_value(rj::Document::AllocatorType& allocator) const override {
128
0
        return rj::Value(value());
129
0
    }
130
131
protected:
132
    // We use std::mutex instead of std::atomic is because atomic don't support
133
    // double's fetch_add
134
    // TODO(zc): If this is atomic is bottleneck, we change to thread local.
135
    // performance: on Intel(R) Xeon(R) CPU E5-2450 int64_t
136
    //  original type: 2ns/op
137
    //  single thread std::mutex: 26ns/op
138
    //  multiple thread(8) std::mutex: 2500ns/op
139
    mutable std::mutex _lock;
140
    T _value;
141
};
142
143
template <typename T>
144
class CoreLocalCounter : public Metric {
145
public:
146
1.35k
    CoreLocalCounter() {}
_ZN5doris16CoreLocalCounterIlEC2Ev
Line
Count
Source
146
1.35k
    CoreLocalCounter() {}
_ZN5doris16CoreLocalCounterImEC2Ev
Line
Count
Source
146
1
    CoreLocalCounter() {}
147
1.35k
    virtual ~CoreLocalCounter() {}
_ZN5doris16CoreLocalCounterIlED2Ev
Line
Count
Source
147
1.35k
    virtual ~CoreLocalCounter() {}
_ZN5doris16CoreLocalCounterImED2Ev
Line
Count
Source
147
1
    virtual ~CoreLocalCounter() {}
148
149
250
    std::string to_string() const override {
150
250
        std::stringstream ss;
151
250
        ss << value();
152
250
        return ss.str();
153
250
    }
_ZNK5doris16CoreLocalCounterIlE9to_stringB5cxx11Ev
Line
Count
Source
149
249
    std::string to_string() const override {
150
249
        std::stringstream ss;
151
249
        ss << value();
152
249
        return ss.str();
153
249
    }
_ZNK5doris16CoreLocalCounterImE9to_stringB5cxx11Ev
Line
Count
Source
149
1
    std::string to_string() const override {
150
1
        std::stringstream ss;
151
1
        ss << value();
152
1
        return ss.str();
153
1
    }
154
155
261
    T value() const {
156
261
        T sum = 0;
157
2.34k
        for (int i = 0; i < _value.size(); ++i) {
158
2.08k
            sum += *_value.access_at_core(i);
159
2.08k
        }
160
261
        return sum;
161
261
    }
_ZNK5doris16CoreLocalCounterIlE5valueEv
Line
Count
Source
155
258
    T value() const {
156
258
        T sum = 0;
157
2.32k
        for (int i = 0; i < _value.size(); ++i) {
158
2.06k
            sum += *_value.access_at_core(i);
159
2.06k
        }
160
258
        return sum;
161
258
    }
_ZNK5doris16CoreLocalCounterImE5valueEv
Line
Count
Source
155
3
    T value() const {
156
3
        T sum = 0;
157
27
        for (int i = 0; i < _value.size(); ++i) {
158
24
            sum += *_value.access_at_core(i);
159
24
        }
160
3
        return sum;
161
3
    }
162
163
87.4k
    void increment(const T& delta) { __sync_fetch_and_add(_value.access(), delta); }
_ZN5doris16CoreLocalCounterIlE9incrementERKl
Line
Count
Source
163
87.4k
    void increment(const T& delta) { __sync_fetch_and_add(_value.access(), delta); }
_ZN5doris16CoreLocalCounterImE9incrementERKm
Line
Count
Source
163
1
    void increment(const T& delta) { __sync_fetch_and_add(_value.access(), delta); }
164
165
5
    void reset() { _value.reset(); }
166
167
5
    rj::Value to_json_value(rj::Document::AllocatorType& allocator) const override {
168
5
        return rj::Value(value());
169
5
    }
_ZNK5doris16CoreLocalCounterIlE13to_json_valueERN9rapidjson19MemoryPoolAllocatorINS2_12CrtAllocatorEEE
Line
Count
Source
167
5
    rj::Value to_json_value(rj::Document::AllocatorType& allocator) const override {
168
5
        return rj::Value(value());
169
5
    }
Unexecuted instantiation: _ZNK5doris16CoreLocalCounterImE13to_json_valueERN9rapidjson19MemoryPoolAllocatorINS2_12CrtAllocatorEEE
170
171
protected:
172
    CoreLocalValue<T> _value;
173
};
174
175
class HistogramMetric : public Metric {
176
public:
177
3
    HistogramMetric() {}
178
3
    virtual ~HistogramMetric() {}
179
180
    HistogramMetric(const HistogramMetric&) = delete;
181
    HistogramMetric& operator=(const HistogramMetric&) = delete;
182
183
    void clear();
184
    bool is_empty() const;
185
    void add(const uint64_t& value);
186
    void merge(const HistogramMetric& other);
187
    void set_histogram(const HistogramStat& stats);
188
189
0
    uint64_t min() const { return _stats.min(); }
190
0
    uint64_t max() const { return _stats.max(); }
191
0
    uint64_t num() const { return _stats.num(); }
192
0
    uint64_t sum() const { return _stats.sum(); }
193
    double median() const;
194
    double percentile(double p) const;
195
    double average() const;
196
    double standard_deviation() const;
197
    std::string to_string() const override;
198
    std::string to_prometheus(const std::string& display_name, const Labels& entity_labels,
199
                              const Labels& metric_labels) const override;
200
    rj::Value to_json_value(rj::Document::AllocatorType& allocator) const override;
201
202
protected:
203
    static std::map<std::string, double> _s_output_percentiles;
204
    mutable std::mutex _lock;
205
    HistogramStat _stats;
206
};
207
208
template <typename T>
209
class AtomicCounter : public AtomicMetric<T> {
210
public:
211
1.53k
    AtomicCounter() {}
212
1.50k
    virtual ~AtomicCounter() {}
213
};
214
215
template <typename T>
216
class AtomicGauge : public AtomicMetric<T> {
217
public:
218
1.78k
    AtomicGauge() : AtomicMetric<T>() {}
_ZN5doris11AtomicGaugeIlEC2Ev
Line
Count
Source
218
1.68k
    AtomicGauge() : AtomicMetric<T>() {}
_ZN5doris11AtomicGaugeImEC2Ev
Line
Count
Source
218
102
    AtomicGauge() : AtomicMetric<T>() {}
219
1.76k
    virtual ~AtomicGauge() {}
_ZN5doris11AtomicGaugeIlED2Ev
Line
Count
Source
219
1.66k
    virtual ~AtomicGauge() {}
_ZN5doris11AtomicGaugeImED2Ev
Line
Count
Source
219
102
    virtual ~AtomicGauge() {}
220
};
221
222
template <typename T>
223
class LockCounter : public LockSimpleMetric<T> {
224
public:
225
1
    LockCounter() : LockSimpleMetric<T>() {}
226
1
    virtual ~LockCounter() {}
227
};
228
229
// This can only used for trival type
230
template <typename T>
231
class LockGauge : public LockSimpleMetric<T> {
232
public:
233
581
    LockGauge() : LockSimpleMetric<T>() {}
234
569
    virtual ~LockGauge() {}
235
};
236
237
using IntCounter = CoreLocalCounter<int64_t>;
238
using IntAtomicCounter = AtomicCounter<int64_t>;
239
using UIntCounter = CoreLocalCounter<uint64_t>;
240
using DoubleCounter = LockCounter<double>;
241
using IntGauge = AtomicGauge<int64_t>;
242
using UIntGauge = AtomicGauge<uint64_t>;
243
using DoubleGauge = LockGauge<double>;
244
245
using Labels = std::unordered_map<std::string, std::string>;
246
struct MetricPrototype {
247
public:
248
    MetricPrototype(MetricType type_, MetricUnit unit_, std::string name_,
249
                    std::string description_ = "", std::string group_name_ = "",
250
                    Labels labels_ = Labels(), bool is_core_metric_ = false)
251
            : is_core_metric(is_core_metric_),
252
              type(type_),
253
              unit(unit_),
254
              name(std::move(name_)),
255
              description(std::move(description_)),
256
              group_name(std::move(group_name_)),
257
347
              labels(std::move(labels_)) {}
258
259
    std::string simple_name() const;
260
    std::string combine_name(const std::string& registry_name) const;
261
    std::string to_prometheus(const std::string& registry_name) const;
262
263
    bool is_core_metric;
264
    MetricType type;
265
    MetricUnit unit;
266
    std::string name;
267
    std::string description;
268
    std::string group_name;
269
    Labels labels;
270
};
271
272
#define DEFINE_METRIC_PROTOTYPE(name, type, unit, desc, group, labels, core) \
273
    ::doris::MetricPrototype METRIC_##name(type, unit, #name, desc, group, labels, core)
274
275
#define DEFINE_COUNTER_METRIC_PROTOTYPE_2ARG(name, unit) \
276
    DEFINE_METRIC_PROTOTYPE(name, MetricType::COUNTER, unit, "", "", Labels(), false)
277
278
#define DEFINE_COUNTER_METRIC_PROTOTYPE_3ARG(name, unit, desc) \
279
    DEFINE_METRIC_PROTOTYPE(name, MetricType::COUNTER, unit, desc, "", Labels(), false)
280
281
#define DEFINE_COUNTER_METRIC_PROTOTYPE_5ARG(name, unit, desc, group, labels) \
282
    DEFINE_METRIC_PROTOTYPE(name, MetricType::COUNTER, unit, desc, #group, labels, false)
283
284
#define DEFINE_GAUGE_METRIC_PROTOTYPE_2ARG(name, unit) \
285
    DEFINE_METRIC_PROTOTYPE(name, MetricType::GAUGE, unit, "", "", Labels(), false)
286
287
#define DEFINE_GAUGE_CORE_METRIC_PROTOTYPE_2ARG(name, unit) \
288
    DEFINE_METRIC_PROTOTYPE(name, MetricType::GAUGE, unit, "", "", Labels(), true)
289
290
#define DEFINE_GAUGE_METRIC_PROTOTYPE_3ARG(name, unit, desc) \
291
    DEFINE_METRIC_PROTOTYPE(name, MetricType::GAUGE, unit, desc, "", Labels(), false)
292
293
#define DEFINE_GAUGE_METRIC_PROTOTYPE_5ARG(name, unit, desc, group, labels) \
294
    DEFINE_METRIC_PROTOTYPE(name, MetricType::GAUGE, unit, desc, #group, labels, false)
295
296
#define DEFINE_HISTOGRAM_METRIC_PROTOTYPE_2ARG(name, unit) \
297
    DEFINE_METRIC_PROTOTYPE(name, MetricType::HISTOGRAM, unit, "", "", Labels(), false)
298
299
#define INT_COUNTER_METRIC_REGISTER(entity, metric) \
300
1.45k
    metric = (IntCounter*)(entity->register_metric<IntCounter>(&METRIC_##metric))
301
302
#define INT_GAUGE_METRIC_REGISTER(entity, metric) \
303
1.79k
    metric = (IntGauge*)(entity->register_metric<IntGauge>(&METRIC_##metric))
304
305
#define INT_DOUBLE_METRIC_REGISTER(entity, metric) \
306
654
    metric = (DoubleGauge*)(entity->register_metric<DoubleGauge>(&METRIC_##metric))
307
308
#define INT_UGAUGE_METRIC_REGISTER(entity, metric) \
309
8
    metric = (UIntGauge*)(entity->register_metric<UIntGauge>(&METRIC_##metric))
310
311
#define INT_ATOMIC_COUNTER_METRIC_REGISTER(entity, metric) \
312
1.67k
    metric = (IntAtomicCounter*)(entity->register_metric<IntAtomicCounter>(&METRIC_##metric))
313
314
#define HISTOGRAM_METRIC_REGISTER(entity, metric) \
315
1
    metric = (HistogramMetric*)(entity->register_metric<HistogramMetric>(&METRIC_##metric))
316
317
#define METRIC_DEREGISTER(entity, metric) entity->deregister_metric(&METRIC_##metric)
318
319
// For 'metrics' in MetricEntity.
320
struct MetricPrototypeHash {
321
7.01k
    size_t operator()(const MetricPrototype* metric_prototype) const {
322
7.01k
        return std::hash<std::string>()(metric_prototype->group_name.empty()
323
7.01k
                                                ? metric_prototype->name
324
7.01k
                                                : metric_prototype->group_name);
325
7.01k
    }
326
};
327
328
struct MetricPrototypeEqualTo {
329
5.41k
    bool operator()(const MetricPrototype* first, const MetricPrototype* second) const {
330
5.41k
        return first->group_name == second->group_name && first->name == second->name;
331
5.41k
    }
332
};
333
334
using MetricMap = std::unordered_map<const MetricPrototype*, Metric*, MetricPrototypeHash,
335
                                     MetricPrototypeEqualTo>;
336
337
enum class MetricEntityType { kServer, kTablet };
338
339
class MetricEntity {
340
public:
341
    MetricEntity(MetricEntityType type, const std::string& name, const Labels& labels)
342
764
            : _type(type), _name(name), _labels(labels) {}
343
758
    ~MetricEntity() {
344
5.10k
        for (auto& metric : _metrics) {
345
5.10k
            delete metric.second;
346
5.10k
        }
347
758
    }
348
349
1.46k
    const std::string& name() const { return _name; }
350
351
    template <typename T>
352
5.99k
    Metric* register_metric(const MetricPrototype* metric_type) {
353
5.99k
        std::lock_guard<std::mutex> l(_lock);
354
5.99k
        auto inserted_metric = _metrics.insert(std::make_pair(metric_type, nullptr));
355
5.99k
        if (inserted_metric.second) {
356
            // If not exist, make a new metric pointer
357
5.25k
            inserted_metric.first->second = new T();
358
5.25k
        }
359
5.99k
        return inserted_metric.first->second;
360
5.99k
    }
_ZN5doris12MetricEntity15register_metricINS_16CoreLocalCounterIlEEEEPNS_6MetricEPKNS_15MetricPrototypeE
Line
Count
Source
352
1.45k
    Metric* register_metric(const MetricPrototype* metric_type) {
353
1.45k
        std::lock_guard<std::mutex> l(_lock);
354
1.45k
        auto inserted_metric = _metrics.insert(std::make_pair(metric_type, nullptr));
355
1.45k
        if (inserted_metric.second) {
356
            // If not exist, make a new metric pointer
357
1.35k
            inserted_metric.first->second = new T();
358
1.35k
        }
359
1.45k
        return inserted_metric.first->second;
360
1.45k
    }
_ZN5doris12MetricEntity15register_metricINS_11AtomicGaugeIlEEEEPNS_6MetricEPKNS_15MetricPrototypeE
Line
Count
Source
352
1.79k
    Metric* register_metric(const MetricPrototype* metric_type) {
353
1.79k
        std::lock_guard<std::mutex> l(_lock);
354
1.79k
        auto inserted_metric = _metrics.insert(std::make_pair(metric_type, nullptr));
355
1.79k
        if (inserted_metric.second) {
356
            // If not exist, make a new metric pointer
357
1.68k
            inserted_metric.first->second = new T();
358
1.68k
        }
359
1.79k
        return inserted_metric.first->second;
360
1.79k
    }
_ZN5doris12MetricEntity15register_metricINS_15HistogramMetricEEEPNS_6MetricEPKNS_15MetricPrototypeE
Line
Count
Source
352
3
    Metric* register_metric(const MetricPrototype* metric_type) {
353
3
        std::lock_guard<std::mutex> l(_lock);
354
3
        auto inserted_metric = _metrics.insert(std::make_pair(metric_type, nullptr));
355
3
        if (inserted_metric.second) {
356
            // If not exist, make a new metric pointer
357
3
            inserted_metric.first->second = new T();
358
3
        }
359
3
        return inserted_metric.first->second;
360
3
    }
_ZN5doris12MetricEntity15register_metricINS_9LockGaugeIdEEEEPNS_6MetricEPKNS_15MetricPrototypeE
Line
Count
Source
352
654
    Metric* register_metric(const MetricPrototype* metric_type) {
353
654
        std::lock_guard<std::mutex> l(_lock);
354
654
        auto inserted_metric = _metrics.insert(std::make_pair(metric_type, nullptr));
355
654
        if (inserted_metric.second) {
356
            // If not exist, make a new metric pointer
357
580
            inserted_metric.first->second = new T();
358
580
        }
359
654
        return inserted_metric.first->second;
360
654
    }
_ZN5doris12MetricEntity15register_metricINS_13AtomicCounterIlEEEEPNS_6MetricEPKNS_15MetricPrototypeE
Line
Count
Source
352
1.67k
    Metric* register_metric(const MetricPrototype* metric_type) {
353
1.67k
        std::lock_guard<std::mutex> l(_lock);
354
1.67k
        auto inserted_metric = _metrics.insert(std::make_pair(metric_type, nullptr));
355
1.67k
        if (inserted_metric.second) {
356
            // If not exist, make a new metric pointer
357
1.52k
            inserted_metric.first->second = new T();
358
1.52k
        }
359
1.67k
        return inserted_metric.first->second;
360
1.67k
    }
_ZN5doris12MetricEntity15register_metricINS_11AtomicGaugeImEEEEPNS_6MetricEPKNS_15MetricPrototypeE
Line
Count
Source
352
405
    Metric* register_metric(const MetricPrototype* metric_type) {
353
405
        std::lock_guard<std::mutex> l(_lock);
354
405
        auto inserted_metric = _metrics.insert(std::make_pair(metric_type, nullptr));
355
405
        if (inserted_metric.second) {
356
            // If not exist, make a new metric pointer
357
101
            inserted_metric.first->second = new T();
358
101
        }
359
405
        return inserted_metric.first->second;
360
405
    }
361
362
    void deregister_metric(const MetricPrototype* metric_type);
363
    Metric* get_metric(const std::string& name, const std::string& group_name = "") const;
364
365
    // Register a hook, this hook will called before get_metric is called
366
    void register_hook(const std::string& name, const std::function<void()>& hook);
367
    void deregister_hook(const std::string& name);
368
    void trigger_hook_unlocked(bool force) const;
369
370
private:
371
    friend class MetricRegistry;
372
    friend struct MetricEntityHash;
373
    friend struct MetricEntityEqualTo;
374
375
    MetricEntityType _type;
376
    std::string _name;
377
    Labels _labels;
378
379
    mutable std::mutex _lock;
380
    MetricMap _metrics;
381
    std::map<std::string, std::function<void()>> _hooks;
382
};
383
384
struct MetricEntityHash {
385
1.46k
    size_t operator()(const std::shared_ptr<MetricEntity> metric_entity) const {
386
1.46k
        return std::hash<std::string>()(metric_entity->name());
387
1.46k
    }
388
};
389
390
struct MetricEntityEqualTo {
391
    bool operator()(const std::shared_ptr<MetricEntity> first,
392
773
                    const std::shared_ptr<MetricEntity> second) const {
393
773
        return first->_type == second->_type && first->_name == second->_name &&
394
773
               first->_labels == second->_labels;
395
773
    }
396
};
397
398
using EntityMetricsByType =
399
        std::unordered_map<const MetricPrototype*, std::vector<std::pair<MetricEntity*, Metric*>>,
400
                           MetricPrototypeHash, MetricPrototypeEqualTo>;
401
402
class MetricRegistry {
403
public:
404
6
    MetricRegistry(const std::string& name) : _name(name) {}
405
    ~MetricRegistry();
406
407
    std::shared_ptr<MetricEntity> register_entity(
408
            const std::string& name, const Labels& labels = {},
409
            MetricEntityType type = MetricEntityType::kServer);
410
    void deregister_entity(const std::shared_ptr<MetricEntity>& entity);
411
    std::shared_ptr<MetricEntity> get_entity(const std::string& name, const Labels& labels = {},
412
                                             MetricEntityType type = MetricEntityType::kServer);
413
414
    void trigger_all_hooks(bool force) const;
415
416
    std::string to_prometheus(bool with_tablet_metrics = false) const;
417
    std::string to_json(bool with_tablet_metrics = false) const;
418
    std::string to_core_string() const;
419
420
private:
421
    const std::string _name;
422
423
    mutable std::mutex _lock;
424
    // MetricEntity -> register count
425
    std::unordered_map<std::shared_ptr<MetricEntity>, int32_t, MetricEntityHash,
426
                       MetricEntityEqualTo>
427
            _entities;
428
};
429
430
} // namespace doris