Stats基本使用
在上一篇文章中我们介绍了Metrics
,以及对应的三个具体的Metrics
类型CounterImpl
、GaugeImpl
、HistogramImpl
,而本文将会介绍下,如何去使用这个三个Metrics类型。在Envoy中要定义一组stats
一般会按照下面的步骤来创建。
- 定义一组
stats
#define MY_COOL_STATS(COUNTER, GAUGE, HISTOGRAM) \
COUNTER(counter1) \
GAUGE(gauge1, mode) \
HISTOGRAM(histogram1)
- 将定义好的
stats
放到一个struct
中
struct MyCoolStats {
MY_COOL_STATS(GENERATE_COUNTER_STRUCT, GENERATE_GAUGE_STRUCT,GENERATE_HISTOGRAM_STRUCT)
};
- 初始化
stats
MyCoolStats stats{MY_COOL_STATS(POOL_COUNTER_PREFIX(scope, prefix), POOL_GAUGE_PREFIX(scope, prefix), POOL_HISTOGRAM_PREFIX(scope, prefix))};
- 使用stats
stats.counter1_.inc();
stats.gauge1_.inc();
stats.histogram1.recordValue(xx)
到此为止一组stats
就定义好了,在代码中创建一份实例,然后通过这个实例就可以引用对应的stats来进行统计了。整个stats的创建和使用还是比较简单的,这都要归功于Envoy预先定义好的一组stats macors
。下面我们将进一步分析这些宏的背后到底做了哪些事情。
Stats macros分析
// Fully-qualified for use in external callsites.
#define GENERATE_COUNTER_STRUCT(NAME) Envoy::Stats::Counter& NAME##_;
#define GENERATE_GAUGE_STRUCT(NAME, MODE) Envoy::Stats::Gauge& NAME##_;
#define GENERATE_HISTOGRAM_STRUCT(NAME) Envoy::Stats::Histogram& NAME##_;
GENERATE_*_STRUCT
开头的宏其实就是定义了对应的Metrics
类型的基类引用,这个部分还是很好理解的,MyCoolStats
展开后如下:
struct MyCoolStats {
Envoy::Stats::Counter& counter1_;
Envoy::Stats::Gauge& gauge1_;
Envoy::Stats::Histogram& histogram1_;
};
接着构造MyCoolStats
的时候,通过POOL_*_PREFIX
开头的宏来创建对应的Metrics
类型的实例,其实现如下:
#define FINISH_STAT_DECL_(X) + std::string(#X)),
#define FINISH_STAT_DECL_MODE_(X, MODE) + std::string(#X), Envoy::Stats::Gauge::ImportMode::MODE),
#define POOL_COUNTER_PREFIX(POOL, PREFIX) (POOL).counter(PREFIX FINISH_STAT_DECL_
#define POOL_GAUGE_PREFIX(POOL, PREFIX) (POOL).gauge(PREFIX FINISH_STAT_DECL_MODE_
#define POOL_HISTOGRAM_PREFIX(POOL, PREFIX) (POOL).histogram(PREFIX FINISH_STAT_DECL_
需要传入一个POOL
,这个POOL
在Envoy中指的就是Scope
对象后面的文章会重点来介绍,用来创建不同类型的Metrics
,展开后如下。
MyCoolStats stats{scope.counter(prefix + std::string("counter1")),
scope.gauge(prefix + std::string("gauge1")),
scope.histogram(prefix + std::string("histogram1"))}
如果不需要提供prefix
的话,也可以使用POOL_*
宏,创建不带prefix的Metrics
。 其内部也是调用带有prefix的宏来实现的。
#define POOL_COUNTER(POOL) POOL_COUNTER_PREFIX(POOL, "")
#define POOL_GAUGE(POOL) POOL_GAUGE_PREFIX(POOL, "")
#define POOL_HISTOGRAM(POOL) POOL_HISTOGRAM_PREFIX(POOL, "")