bvar用法学习

转自:bvar | bRPC

1.介绍

bvar是多线程环境下的计数器类库,方便记录和查看用户程序中的各类数值,它利用了thread local存储减少了cache bouncing。

适用情况:

bvar不能代替所有的计数器,它的本质是把写时的竞争转移到了读:读时需要合并所有写过的线程中的数据,而不可避免地变慢了。当你读写都很频繁或得基于最新值做一些逻辑判断时,你不应该用bvar。适用于写多读少的情况。

2.单维度bvar

https://github.com/apache/brpc/blob/master/docs/cn/bvar_c++.md#bvarpassivestatus

#include <bvar/bvar.h>

namespace foo {
namespace bar {

// bvar::Adder<T>用于累加,下面定义了一个统计read error总数的Adder。
bvar::Adder<int> g_read_error;
// 把bvar::Window套在其他bvar上就可以获得时间窗口内的值。
bvar::Window<bvar::Adder<int> > g_read_error_minute("foo_bar", "read_error", &g_read_error, 60);
//                                                     ^          ^                         ^
//                                                    前缀       监控项名称                  60秒,忽略则为10秒

// bvar::LatencyRecorder是一个复合变量,可以统计:总量、qps、平均延时,延时分位值,最大延时。
bvar::LatencyRecorder g_write_latency("foo_bar", "write");
//                                      ^          ^
//                                     前缀       监控项,别加latency!LatencyRecorder包含多个bvar,它们会加上各自的后缀,比如write_qps, write_latency等等。

// 定义一个统计“已推入task”个数的变量。
bvar::Adder<int> g_task_pushed("foo_bar", "task_pushed");
// 把bvar::PerSecond套在其他bvar上可以获得时间窗口内*平均每秒*的值,这里是每秒内推入task的个数。
bvar::PerSecond<bvar::Adder<int> > g_task_pushed_second("foo_bar", "task_pushed_second", &g_task_pushed);
//       ^                                                                                             ^
//    和Window不同,PerSecond会除以时间窗口的大小.                                   时间窗口是最后一个参数,这里没填,就是默认10秒。

}  // bar
}  // foo

// 使用时的例子
// 碰到read error
foo::bar::g_read_error << 1;

// write_latency是23ms
foo::bar::g_write_latency << 23;

// 推入了1个task
foo::bar::g_task_pushed << 1;
  • Window<>和PerSecond<>都是衍生变量,会自动更新。确认变量名是全局唯一的
  • 不要跨文件定义全局Window或PerSecond。因为存在编译优化,不同cpp的变量并不能确定定义的先后顺序。

为什么要区分前缀和监控项?

前缀可以表示命名空间,形成层级结构,比如你可能有 foo_bar 前缀下的多个不同监控项(如 write、read、update 等),它们共享相同的前缀,但监控项不同。这样在查看指标时,可以很方便地过滤和分组相关的指标。

3.注册到全局表

用户以默认参数建立一个bvar时,这个bvar并未注册到任何全局结构中。况下,bvar纯粹是一个更快的计数器。我们称把一个bvar注册到全局表中的行为为“曝光”,可通过expose函数曝光:

全局曝光后的bvar名字便为name或prefix + name。

// 没太理解,用到时再说吧。

4.PassiveStatus

PassiveStatus 是一个用于动态生成指标值的类。与常规的 bvar 指标(如 bvar::LatencyRecorder 等)不同,PassiveStatus 的值并不是直接由代码逻辑主动设置的,而是通过一个回调函数动态计算和获取的。

例子:

static void get_username(std::ostream& os, void*) {
    char buf[32];
    if (getlogin_r(buf, sizeof(buf)) == 0) {
        buf[sizeof(buf)-1] = '\0';
        os << buf; // 将用户名输出到流中
    } else {
        os << "unknown"; // 如果获取失败,返回 "unknown"
    }
}
PassiveStatus<std::string> g_username("process_username", get_username, NULL);
  • g_username:一个 PassiveStatus 对象,用于暴露当前进程的用户名作为监控指标,指标名称为 process_username。
  • get_username:这是一个回调函数,PassiveStatus 会调用这个函数来生成其值。
    • 使用 getlogin_r 获取当前进程所属的用户名。

每当 PassiveStatus 的值被访问时(例如通过 /vars 页面),get_username 函数都会被调用,以动态生成当前的用户名。

PassiveStatus 通常用于以下场景:动态生成数据、减少存储开销、便捷的指标暴露;

构造函数:

template <typename T>
class PassiveStatus {
public:
    PassiveStatus(const std::string& name, void (*callback)(std::ostream&, void*), void* arg);
    // ...
};
  • name:指定指标的名称,用户可以通过 /vars/<name> 查看对应的值。例如,上述代码中可以通过 /vars/process_username 查看当前用户名。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值