指标属性用于在更上层的指标使用中进行过滤、汇总、统计等高纬度操作。在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对象时的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 看看结果。可以看到,全局属性已经自动添加到了指标中。


Content Menu

  • No labels