监控告警-指标属性

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

监控告警-指标属性 - 图1 提示

在 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 上的常量属性在两个指标上生效了,但是在各个指标上绑定的常量属性仅在对应的指标上生效了。

监控告警-指标属性 - 图2

变量属性

变量属性 是在指标运行时指定的属性键值对,通常只能在运行时才能确定属性的键值对信息,并且键值对可能根据不同的执行场景而发生变化,因此叫做变量属性。

我们来看一个示例:

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 看看结果。

监控告警-指标属性 - 图3

全局属性

全局属性 是一种更加灵活的指标属性注入方式,可以根据 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 看看结果。可以看到,全局属性已经自动添加到了指标中。

监控告警-指标属性 - 图4