指标属性用于在更上层的指标使用中进行过滤、汇总、统计等高纬度操作。在GoFrame
框架的监控告警组件中,提供了3种属性注入方式:常量属性、变量属性和全局属性。
在OpenTelemetry
中叫做指标属性(attributes
),但在Prometheus
中叫做指标标签(labels
),两者是一个含义。
常量属性
常量属性是固定的一系列属性键值对,可以绑定到Meter
中,也可以直接绑定到指标对象上。如果绑定到Meter
上,那么Meter
下所有创建的指标对象均带有该属性键值对,如果绑定到指标对象上,那么仅会在当前指标上生效。我们来看一个示例:
package main
import (
"context"
"go.opentelemetry.io/otel/exporters/prometheus"
"github.com/gogf/gf/contrib/metric/otelmetric/v2"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gctx"
"github.com/gogf/gf/v2/os/gmetric"
)
const (
instrument = "github.com/gogf/gf/example/metric/basic"
instrumentVersion = "v1.0"
)
var (
meter = gmetric.GetGlobalProvider().Meter(gmetric.MeterOption{
Instrument: instrument,
InstrumentVersion: instrumentVersion,
Attributes: gmetric.Attributes{
gmetric.NewAttribute("meter_const_attr_1", 1),
},
})
counter = meter.MustCounter(
"goframe.metric.demo.counter",
gmetric.MetricOption{
Help: "This is a simple demo for Counter usage",
Unit: "bytes",
Attributes: gmetric.Attributes{
gmetric.NewAttribute("metric_const_attr_1", 1),
},
},
)
observableCounter = meter.MustObservableCounter(
"goframe.metric.demo.observable_counter",
gmetric.MetricOption{
Help: "This is a simple demo for ObservableCounter usage",
Unit: "%",
Attributes: gmetric.Attributes{
gmetric.NewAttribute("metric_const_attr_2", 2),
},
},
)
)
func main() {
var ctx = gctx.New()
// Callback for observable metrics.
meter.MustRegisterCallback(func(ctx context.Context, obs gmetric.Observer) error {
obs.Observe(observableCounter, 10)
return nil
}, observableCounter)
// Prometheus exporter to export metrics as Prometheus format.
exporter, err := prometheus.New(
prometheus.WithoutCounterSuffixes(),
prometheus.WithoutUnits(),
)
if err != nil {
g.Log().Fatal(ctx, err)
}
// OpenTelemetry provider.
provider := otelmetric.MustProvider(
otelmetric.WithReader(exporter),
)
provider.SetAsGlobal()
defer provider.Shutdown(ctx)
// Counter.
counter.Inc(ctx)
counter.Add(ctx, 10)
// HTTP Server for metrics exporting.
otelmetric.StartPrometheusMetricsServer(8000, "/metrics")
}
可以看到,我们通过创建Meter
对象或者Metric
对象时的MeterOption
或MetricOption
参数中的Attributes
属性字段来指定常量属性。
执行后,我们访问 http://127.0.0.1:8000/metrics 看看结果。可以看到绑定到Meter
上的常量属性在两个指标上生效了,但是在各个指标上绑定的常量属性仅在对应的指标上生效了。
变量属性
变量属性是在指标运行时指定的属性键值对,通常只能在运行时才能确定属性的键值对信息,并且键值对可能根据不同的执行场景而发生变化,因此叫做变量属性。
我们来看一个示例:
package main
import (
"context"
"go.opentelemetry.io/otel/exporters/prometheus"
"github.com/gogf/gf/contrib/metric/otelmetric/v2"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gctx"
"github.com/gogf/gf/v2/os/gmetric"
)
const (
instrument = "github.com/gogf/gf/example/metric/basic"
instrumentVersion = "v1.0"
)
var (
meter = gmetric.GetGlobalProvider().Meter(gmetric.MeterOption{
Instrument: instrument,
InstrumentVersion: instrumentVersion,
Attributes: gmetric.Attributes{
gmetric.NewAttribute("meter_const_attr_1", 1),
},
})
counter = meter.MustCounter(
"goframe.metric.demo.counter",
gmetric.MetricOption{
Help: "This is a simple demo for Counter usage",
Unit: "bytes",
Attributes: gmetric.Attributes{
gmetric.NewAttribute("metric_const_attr_1", 1),
},
},
)
observableCounter = meter.MustObservableCounter(
"goframe.metric.demo.observable_counter",
gmetric.MetricOption{
Help: "This is a simple demo for ObservableCounter usage",
Unit: "%",
Attributes: gmetric.Attributes{
gmetric.NewAttribute("metric_const_attr_2", 2),
},
},
)
)
func main() {
var ctx = gctx.New()
// Callback for observable metrics.
meter.MustRegisterCallback(func(ctx context.Context, obs gmetric.Observer) error {
obs.Observe(observableCounter, 10, gmetric.Option{
Attributes: gmetric.Attributes{
gmetric.NewAttribute("dynamic_attr_1", 1),
},
})
return nil
}, observableCounter)
// Prometheus exporter to export metrics as Prometheus format.
exporter, err := prometheus.New(
prometheus.WithoutCounterSuffixes(),
prometheus.WithoutUnits(),
)
if err != nil {
g.Log().Fatal(ctx, err)
}
// OpenTelemetry provider.
provider := otelmetric.MustProvider(
otelmetric.WithReader(exporter),
)
provider.SetAsGlobal()
defer provider.Shutdown(ctx)
// Counter.
counter.Inc(ctx, gmetric.Option{
Attributes: gmetric.Attributes{
gmetric.NewAttribute("dynamic_attr_2", 2),
},
})
counter.Add(ctx, 10, gmetric.Option{
Attributes: gmetric.Attributes{
gmetric.NewAttribute("dynamic_attr_3", 3),
},
})
// HTTP Server for metrics exporting.
otelmetric.StartPrometheusMetricsServer(8000, "/metrics")
}
可以看到,我们在运行通过Option
参数中的Attributes
属性字段来指定指标变量属性,变量属性比较灵活,相同的指标也可以使用不同的变量属性。
同样的,执行后,我们访问 http://127.0.0.1:8000/metrics 看看结果。
全局属性
全局属性是一种更加灵活的指标属性注入方式,可以根据Instrument
信息进行属性自动注入,并且可以根据Instrument
名称的正则匹配来判断是否往该Instrument
下所有的指标注入指标属性信息。
我们来看一个示例:
package main
import (
"context"
"go.opentelemetry.io/otel/exporters/prometheus"
"github.com/gogf/gf/contrib/metric/otelmetric/v2"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gctx"
"github.com/gogf/gf/v2/os/gmetric"
)
const (
instrument = "github.com/gogf/gf/example/metric/basic"
instrumentVersion = "v1.0"
)
var (
meter = gmetric.GetGlobalProvider().Meter(gmetric.MeterOption{
Instrument: instrument,
InstrumentVersion: instrumentVersion,
Attributes: gmetric.Attributes{
gmetric.NewAttribute("meter_const_attr_1", 1),
},
})
counter = meter.MustCounter(
"goframe.metric.demo.counter",
gmetric.MetricOption{
Help: "This is a simple demo for Counter usage",
Unit: "bytes",
Attributes: gmetric.Attributes{
gmetric.NewAttribute("metric_const_attr_1", 1),
},
},
)
observableCounter = meter.MustObservableCounter(
"goframe.metric.demo.observable_counter",
gmetric.MetricOption{
Help: "This is a simple demo for ObservableCounter usage",
Unit: "%",
Attributes: gmetric.Attributes{
gmetric.NewAttribute("metric_const_attr_2", 2),
},
},
)
)
func main() {
var ctx = gctx.New()
gmetric.SetGlobalAttributes(gmetric.Attributes{
gmetric.NewAttribute("global_attr_1", 1),
}, gmetric.SetGlobalAttributesOption{
Instrument: instrument,
InstrumentVersion: instrumentVersion,
InstrumentPattern: "",
})
// Callback for observable metrics.
meter.MustRegisterCallback(func(ctx context.Context, obs gmetric.Observer) error {
obs.Observe(observableCounter, 10, gmetric.Option{
Attributes: gmetric.Attributes{
gmetric.NewAttribute("dynamic_attr_1", 1),
},
})
return nil
}, observableCounter)
// Prometheus exporter to export metrics as Prometheus format.
exporter, err := prometheus.New(
prometheus.WithoutCounterSuffixes(),
prometheus.WithoutUnits(),
)
if err != nil {
g.Log().Fatal(ctx, err)
}
// OpenTelemetry provider.
provider := otelmetric.MustProvider(
otelmetric.WithReader(exporter),
)
provider.SetAsGlobal()
defer provider.Shutdown(ctx)
// Counter.
counter.Inc(ctx, gmetric.Option{
Attributes: gmetric.Attributes{
gmetric.NewAttribute("dynamic_attr_2", 2),
},
})
counter.Add(ctx, 10, gmetric.Option{
Attributes: gmetric.Attributes{
gmetric.NewAttribute("dynamic_attr_3", 3),
},
})
// HTTP Server for metrics exporting.
otelmetric.StartPrometheusMetricsServer(8000, "/metrics")
}
通过gmetric.SetGlobalAttributes
方法设置全局属性,并且根据参数gmetric.SetGlobalAttributesOption
限制影响的指标范围。
同样的,执行后,我们访问 http://127.0.0.1:8000/metrics 看看结果。可以看到,全局属性已经自动添加到了指标中。