Metric attributes are used for filtering, aggregation, statistical, and other high-level operations in higher-level metric usage. In the monitoring alerts component of the GoFrame
framework, three types of attribute injection methods are provided: constant attributes, variable attributes, and global attributes.
In OpenTelemetry
, they are called metric attributes (attributes
), but in Prometheus
, they are called metric labels (labels
), both meaning the same.
Constant Attributes
Constant attributes are a set of fixed attribute key-value pairs that can be bound to a Meter
or directly to a metric object. If bound to a Meter
, all metric objects created under the Meter
carry this attribute key-value pair. If bound to a metric object, it will only be effective on the current metric. Let's look at an example:
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")
}
As you can see, we specify constant attributes through the Attributes
attribute field in the MeterOption
or MetricOption
parameters when creating a Meter
object or a Metric
object.
Once executed, we visit http://127.0.0.1:8000/metrics to see the results. The constant attributes bound to the Meter
took effect on both metrics, but the constant attributes bound to each metric only took effect on the corresponding metric.
Variable Attributes
Variable attributes are attribute key-value pairs specified at runtime, usually determined only at runtime, and might vary based on different execution scenarios, hence called variable attributes.
Let's look at an example:
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")
}
As shown, we specify metric variable attributes at runtime through the Attributes
attribute field in the Option
parameter. Variable attributes are quite flexible, and the same metric can use different variable attributes.
Similarly, after execution, we visit http://127.0.0.1:8000/metrics to see the results.
Global Attributes
Global attributes are a more flexible metric attribute injection method, which can be automatically injected based on Instrument
information and can determine whether to inject metric attributes into all metrics under a given Instrument
based on regex matches of the Instrument
name.
Let's look at an example:
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")
}
Set global attributes through the gmetric.SetGlobalAttributes
method, and restrict the affected metric range based on the parameter gmetric.SetGlobalAttributesOption
.
Similarly, after execution, visit http://127.0.0.1:8000/metrics to see the results. You can see that the global attributes have been automatically added to the metrics.