Metrics的源码学习
1 - exporter.go的源码学习
Dapr metrics package中的 exporter.go文件的源码分析,包括结构体定义、方法实现。当前只支持 Prometheus。
Exporter定义和实现
Exporter 接口定义
Exporter 接口定义:
// Exporter is the interface for metrics exporters
type Exporter interface {
// Init initializes metrics exporter
Init() error
// Options returns Exporter options
Options() *Options
}
exporter 结构体定义
exporter 结构体定义:
// exporter is the base struct
type exporter struct {
namespace string
options *Options
logger logger.Logger
}
构建 exporter
// NewExporter creates new MetricsExporter instance
func NewExporter(namespace string) Exporter {
// TODO: support multiple exporters
return &promMetricsExporter{
&exporter{
namespace: namespace,
options: defaultMetricOptions(),
logger: logger.NewLogger("dapr.metrics"),
},
nil,
}
}
当前只支持 promMetrics 的 Exporter。
接口方法Options()的实现
Options() 方法简单返回 m.options:
// Options returns current metric exporter options
func (m *exporter) Options() *Options {
return m.options
}
具体的赋值在 defaultMetricOptions().
Prometheus Exporter的实现
promMetricsExporter 结构体定义
// promMetricsExporter is prometheus metric exporter
type promMetricsExporter struct {
*exporter
ocExporter *ocprom.Exporter
}
内嵌 exporter (相当于继承),还有一个 ocprom.Exporter 字段。
接口方法 Init() 的实现
初始化 opencensus 的 exporter:
// Init initializes opencensus exporter
func (m *promMetricsExporter) Init() error {
if !m.exporter.Options().MetricsEnabled {
return nil
}
// Add default health metrics for process
// 添加默认的 health metrics: 进程信息,和 go 信息
registry := prom.NewRegistry()
registry.MustRegister(prom.NewProcessCollector(prom.ProcessCollectorOpts{}))
registry.MustRegister(prom.NewGoCollector())
var err error
m.ocExporter, err = ocprom.NewExporter(ocprom.Options{
Namespace: m.namespace,
Registry: registry,
})
if err != nil {
return errors.Errorf("failed to create Prometheus exporter: %v", err)
}
// register exporter to view
view.RegisterExporter(m.ocExporter)
// start metrics server
return m.startMetricServer()
}
startMetricServer() 方法的实现
启动 MetricServer, 监听端口来自 options 的 MetricsPort,监听路径为 defaultMetricsPath:
const (
defaultMetricsPath = "/"
)
// startMetricServer starts metrics server
func (m *promMetricsExporter) startMetricServer() error {
if !m.exporter.Options().MetricsEnabled {
// skip if metrics is not enabled
return nil
}
addr := fmt.Sprintf(":%d", m.options.MetricsPort())
if m.ocExporter == nil {
return errors.New("exporter was not initialized")
}
m.exporter.logger.Infof("metrics server started on %s%s", addr, defaultMetricsPath)
go func() {
mux := http.NewServeMux()
mux.Handle(defaultMetricsPath, m.ocExporter)
if err := http.ListenAndServe(addr, mux); err != nil {
m.exporter.logger.Fatalf("failed to start metrics server: %v", err)
}
}()
return nil
}
2 - options.go的源码学习
Dapr metrics package中的 options.go文件的源码学习
代码实现
Options 结构体定义
// Options defines the sets of options for Dapr logging
type Options struct {
// OutputLevel is the level of logging
MetricsEnabled bool
metricsPort string
}
默认值
metrics 默认端口 9090, 默认启用 metrics:
const (
defaultMetricsPort = "9090"
defaultMetricsEnabled = true
)
func defaultMetricOptions() *Options {
return &Options{
metricsPort: defaultMetricsPort,
MetricsEnabled: defaultMetricsEnabled,
}
}
MetricsPort() 方法实现
MetricsPort() 方法用于获取 metrics 端口,如果配置错误,则使用默认端口 9090:
// MetricsPort gets metrics port.
func (o *Options) MetricsPort() uint64 {
port, err := strconv.ParseUint(o.metricsPort, 10, 64)
if err != nil {
// Use default metrics port as a fallback
port, _ = strconv.ParseUint(defaultMetricsPort, 10, 64)
}
return port
}
解析命令行标记的方法
AttachCmdFlags() 方法
AttachCmdFlags() 方法解析 metrics-port 和 enable-metrics 两个命令行标记:
// AttachCmdFlags attaches metrics options to command flags
func (o *Options) AttachCmdFlags(
stringVar func(p *string, name string, value string, usage string),
boolVar func(p *bool, name string, value bool, usage string)) {
stringVar(
&o.metricsPort,
"metrics-port",
defaultMetricsPort,
"The port for the metrics server")
boolVar(
&o.MetricsEnabled,
"enable-metrics",
defaultMetricsEnabled,
"Enable prometheus metric")
}
AttachCmdFlag() 方法
AttachCmdFlag() 方法只解析 metrics-port 命令行标记(不解析 enable-metrics ) :
// AttachCmdFlag attaches single metrics option to command flags
func (o *Options) AttachCmdFlag(
stringVar func(p *string, name string, value string, usage string)) {
stringVar(
&o.metricsPort,
"metrics-port",
defaultMetricsPort,
"The port for the metrics server")
}
使用场景
只解析 metrics-port 命令行标记 的 AttachCmdFlag() 方法在 dapr runtime 启动时被调用(也只被这一个地方调用):
metricsExporter := metrics.NewExporter(metrics.DefaultMetricNamespace)
// attaching only metrics-port option
metricsExporter.Options().AttachCmdFlag(flag.StringVar)
而解析 metrics-port 和 enable-metrics 两个命令行标记的 AttachCmdFlags() 方法被 injector / operator / placement / sentry 调用:
func init() {
metricsExporter := metrics.NewExporter(metrics.DefaultMetricNamespace)
metricsExporter.Options().AttachCmdFlags(flag.StringVar, flag.BoolVar)
}