Skip to main content
Version: Latest

指标属性用于在更上层的指标使用中进行过滤、汇总、统计等高纬度操作。在 GoFrame 框架的监控告警组件中,提供了3种属性注入方式: 常量属性变量属性全局属性

tip

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 对象时的 MeterOptionMetricOption 参数中的 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 看看结果。可以看到,全局属性已经自动添加到了指标中。