Skip to content

Commit 1ff5f3f

Browse files
authored
Support generics for MultiDimension APIs (#3026)
* Support generics for MVariable api * Update document
1 parent 75341f8 commit 1ff5f3f

12 files changed

Lines changed: 432 additions & 230 deletions

File tree

docs/cn/mbvar_c++.md

Lines changed: 81 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -331,11 +331,13 @@ size_t mbvar_list_exposed(std::vector<std::string>* names) {
331331

332332
多维度统计的实现,主要提供bvar的获取、列举等功能。
333333

334+
为了兼容旧的用法,KeyType默认类型是std::list<std::string>。KeyType必须是(STL或者自定义)容器,value_type必须是std::string。
335+
334336
## constructor
335337

336338
有三个构造函数:
337339
```c++
338-
template <typename T>
340+
template <typename T, typename KeyType = std::list<std::string>>
339341
class MultiDimension : public MVariable {
340342
public:
341343
// 不建议使用
@@ -398,7 +400,7 @@ bvar::MultiDimension<bvar::Adder<int> > g_request_count("foo_bar", "request_coun
398400
399401
## stats
400402
```c++
401-
template <typename T>
403+
template <typename T, typename KeyType = std::list<std::string>>
402404
class MultiDimension : public MVariable {
403405
public:
404406
...
@@ -410,7 +412,15 @@ public:
410412
```
411413

412414
### get_stats
413-
根据指定label获取对应的单维度统计项bvar
415+
根据指定label获取对应的单维度统计项bvar。
416+
417+
get_stats除了支持(默认)std::list<std::string>参数类型,也支持自定义参数类型,满足以下条件:
418+
1. (STL或者自定义)容器。
419+
2. K::value_type支持通过operator std::string()转换为std::string和通过operator butil::StringPiece()转换为butil::StringPiece。
420+
3. K::value_type支持和std::string进行比较。
421+
422+
推荐使用不需要分配内存的容器(例如,std::array、absl::InlinedVector)和不需要拷贝字符串的数据结构(例如,const char*、std::string_view、butil::StringPieces),可以提高性能。
423+
414424
```c++
415425
#include <bvar/bvar.h>
416426
#include <bvar/multi_dimension.h>
@@ -420,7 +430,8 @@ namespace bar {
420430
// 定义一个全局的多维度mbvar变量
421431
bvar::MultiDimension<bvar::Adder<int> > g_request_count("request_count", {"idc", "method", "status"});
422432

423-
int get_request_count(const std::list<std::string>& request_label) {
433+
template <typename K>
434+
int get_request_count(const K& request_label) {
424435
// 获取request_label对应的单维度bvar指针,比如:request_label = {"tc", "get", "200"}
425436
bvar::Adder<int> *request_adder = g_request_count.get_stats(request_label);
426437
// 判断指针非空
@@ -433,6 +444,70 @@ int get_request_count(const std::list<std::string>& request_label) {
433444
return request_adder->get_value();
434445
}
435446

447+
std::list<std::string> request_label_list = {"tc", "get", "200"};
448+
int request_count = get_request_count(request_label_list);
449+
450+
std::vector<std::string_view> request_label_list = {"tc", "get", "200"};
451+
int request_count = get_request_count(request_label_list);
452+
453+
std::vector<butil::StringPiece> request_label_list = {"tc", "get", "200"};
454+
int request_count = get_request_count(request_label_list);
455+
456+
class MyStringView {
457+
public:
458+
MyStringView() : _ptr(NULL), _len(0) {}
459+
MyStringView(const char* str)
460+
: _ptr(str),
461+
_len(str == NULL ? 0 : strlen(str)) {}
462+
#if __cplusplus >= 201703L
463+
MyStringView(const std::string_view& str)
464+
: _ptr(str.data()), _len(str.size()) {}
465+
#endif // __cplusplus >= 201703L
466+
MyStringView(const std::string& str)
467+
: _ptr(str.data()), _len(str.size()) {}
468+
MyStringView(const char* offset, size_t len)
469+
: _ptr(offset), _len(len) {}
470+
471+
const char* data() const { return _ptr; }
472+
size_t size() const { return _len; }
473+
474+
// Converts to `std::basic_string`.
475+
explicit operator std::string() const {
476+
if (NULL == _ptr) {
477+
return {};
478+
}
479+
return {_ptr, size()};
480+
}
481+
482+
// Converts to butil::StringPiece.
483+
explicit operator butil::StringPiece() const {
484+
if (NULL == _ptr) {
485+
return {};
486+
}
487+
return {_ptr, size()};
488+
}
489+
490+
private:
491+
const char* _ptr;
492+
size_t _len;
493+
};
494+
495+
bool operator==(const MyStringView& x, const std::string& y) {
496+
if (x.size() != y.size()) {
497+
return false;
498+
}
499+
return butil::StringPiece::wordmemcmp(x.data(), y.data(), x.size()) == 0;
500+
}
501+
bool operator==(const std::string& x, const MyStringView& y) {
502+
if (x.size() != y.size()) {
503+
return false;
504+
}
505+
return butil::StringPiece::wordmemcmp(x.data(), y.data(), x.size()) == 0;
506+
}
507+
508+
std::vector<MyStringView> request_label_list = {"tc", "get", "200"};
509+
int request_count = get_request_count(request_label_list);
510+
436511
} // namespace bar
437512
} // namespace foo
438513
```
@@ -462,7 +537,7 @@ public:
462537
size_t count_labels() const;
463538
};
464539

465-
template <typename T>
540+
template <typename T, typename KeyType = std::list<std::string>>
466541
class MultiDimension : public MVariable {
467542
public:
468543
...
@@ -536,7 +611,7 @@ size_t count_stats() {
536611

537612
## list
538613
```c++
539-
template <typename T>
614+
template <typename T, typename KeyType = std::list<std::string>>
540615
class MultiDimension : public MVariable {
541616
public:
542617
...

src/brpc/builtin/prometheus_metrics_service.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@ int DumpPrometheusMetricsToIOBuf(butil::IOBuf* output) {
232232

233233
if (bvar::FLAGS_bvar_max_dump_multi_dimension_metric_number > 0) {
234234
PrometheusMetricsDumper dumper_md(&os, g_server_info_prefix);
235-
const int ndump_md = bvar::MVariable::dump_exposed(&dumper_md, NULL);
235+
const int ndump_md = bvar::MVariableBase::dump_exposed(&dumper_md, NULL);
236236
if (ndump_md < 0) {
237237
return -1;
238238
}

src/butil/containers/flat_map.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -199,12 +199,12 @@ class FlatMap {
199199
// Remove |key| and all associated value
200200
// Returns: 1 on erased, 0 otherwise.
201201
template <typename K2, bool Multi = _Multi>
202-
typename std::enable_if<!Multi, size_t >::type
202+
typename std::enable_if<!Multi, size_t>::type
203203
erase(const K2& key, mapped_type* old_value = NULL);
204204
// For `_Multi=true'.
205205
// Returns: num of value on erased, 0 otherwise.
206206
template <typename K2, bool Multi = _Multi>
207-
typename std::enable_if<Multi, size_t >::type
207+
typename std::enable_if<Multi, size_t>::type
208208
erase(const K2& key, std::vector<mapped_type>* old_values = NULL);
209209

210210
// Remove all items. Allocated spaces are NOT returned by system.

src/butil/containers/flat_map_inl.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -592,7 +592,6 @@ typename std::enable_if<!Multi, _T&>::type
592592
FlatMap<_K, _T, _H, _E, _S, _A, _M>::operator[](const key_type& key) {
593593
const size_t index = flatmap_mod(_hashfn(key), _nbucket);
594594
Bucket& first_node = _buckets[index];
595-
// LOG(INFO) << "index=" << index;
596595
if (!first_node.is_valid()) {
597596
++_size;
598597
if (_S) {

src/butil/strings/string_piece.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@
3232

3333
#include <iosfwd>
3434
#include <string>
35+
#if __cplusplus >= 201703L
36+
#include <string_view>
37+
#endif // __cplusplus >= 201703L
3538

3639
#include "butil/base_export.h"
3740
#include "butil/basictypes.h"
@@ -182,6 +185,11 @@ template <typename STRING_TYPE> class BasicStringPiece {
182185
BasicStringPiece(const value_type* str)
183186
: ptr_(str),
184187
length_((str == NULL) ? 0 : STRING_TYPE::traits_type::length(str)) {}
188+
#if __cplusplus >= 201703L
189+
BasicStringPiece(
190+
const std::basic_string_view<value_type, typename STRING_TYPE::traits_type>& str)
191+
: ptr_(str.data()), length_(str.size()) {}
192+
#endif // __cplusplus >= 201703L
185193
BasicStringPiece(const STRING_TYPE& str)
186194
: ptr_(str.data()), length_(str.size()) {}
187195
BasicStringPiece(const value_type* offset, size_type len)
@@ -370,6 +378,14 @@ template <typename STRING_TYPE> class BasicStringPiece {
370378
return internal::substr(*this, pos, n);
371379
}
372380

381+
// Converts to `std::basic_string`.
382+
explicit operator STRING_TYPE() const {
383+
if (NULL == data()) {
384+
return {};
385+
}
386+
return STRING_TYPE(data(), size());
387+
}
388+
373389
protected:
374390
const value_type* ptr_;
375391
size_type length_;

0 commit comments

Comments
 (0)