Coverage Report

Created: 2024-11-18 10:37

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