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.

Metrics - Attributes - 图1tip

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:

  1. package main
  2. import (
  3. "context"
  4. "go.opentelemetry.io/otel/exporters/prometheus"
  5. "github.com/gogf/gf/contrib/metric/otelmetric/v2"
  6. "github.com/gogf/gf/v2/frame/g"
  7. "github.com/gogf/gf/v2/os/gctx"
  8. "github.com/gogf/gf/v2/os/gmetric"
  9. )
  10. const (
  11. instrument = "github.com/gogf/gf/example/metric/basic"
  12. instrumentVersion = "v1.0"
  13. )
  14. var (
  15. meter = gmetric.GetGlobalProvider().Meter(gmetric.MeterOption{
  16. Instrument: instrument,
  17. InstrumentVersion: instrumentVersion,
  18. Attributes: gmetric.Attributes{
  19. gmetric.NewAttribute("meter_const_attr_1", 1),
  20. },
  21. })
  22. counter = meter.MustCounter(
  23. "goframe.metric.demo.counter",
  24. gmetric.MetricOption{
  25. Help: "This is a simple demo for Counter usage",
  26. Unit: "bytes",
  27. Attributes: gmetric.Attributes{
  28. gmetric.NewAttribute("metric_const_attr_1", 1),
  29. },
  30. },
  31. )
  32. observableCounter = meter.MustObservableCounter(
  33. "goframe.metric.demo.observable_counter",
  34. gmetric.MetricOption{
  35. Help: "This is a simple demo for ObservableCounter usage",
  36. Unit: "%",
  37. Attributes: gmetric.Attributes{
  38. gmetric.NewAttribute("metric_const_attr_2", 2),
  39. },
  40. },
  41. )
  42. )
  43. func main() {
  44. var ctx = gctx.New()
  45. // Callback for observable metrics.
  46. meter.MustRegisterCallback(func(ctx context.Context, obs gmetric.Observer) error {
  47. obs.Observe(observableCounter, 10)
  48. return nil
  49. }, observableCounter)
  50. // Prometheus exporter to export metrics as Prometheus format.
  51. exporter, err := prometheus.New(
  52. prometheus.WithoutCounterSuffixes(),
  53. prometheus.WithoutUnits(),
  54. )
  55. if err != nil {
  56. g.Log().Fatal(ctx, err)
  57. }
  58. // OpenTelemetry provider.
  59. provider := otelmetric.MustProvider(
  60. otelmetric.WithReader(exporter),
  61. )
  62. provider.SetAsGlobal()
  63. defer provider.Shutdown(ctx)
  64. // Counter.
  65. counter.Inc(ctx)
  66. counter.Add(ctx, 10)
  67. // HTTP Server for metrics exporting.
  68. otelmetric.StartPrometheusMetricsServer(8000, "/metrics")
  69. }

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.

Metrics - Attributes - 图2

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:

  1. package main
  2. import (
  3. "context"
  4. "go.opentelemetry.io/otel/exporters/prometheus"
  5. "github.com/gogf/gf/contrib/metric/otelmetric/v2"
  6. "github.com/gogf/gf/v2/frame/g"
  7. "github.com/gogf/gf/v2/os/gctx"
  8. "github.com/gogf/gf/v2/os/gmetric"
  9. )
  10. const (
  11. instrument = "github.com/gogf/gf/example/metric/basic"
  12. instrumentVersion = "v1.0"
  13. )
  14. var (
  15. meter = gmetric.GetGlobalProvider().Meter(gmetric.MeterOption{
  16. Instrument: instrument,
  17. InstrumentVersion: instrumentVersion,
  18. Attributes: gmetric.Attributes{
  19. gmetric.NewAttribute("meter_const_attr_1", 1),
  20. },
  21. })
  22. counter = meter.MustCounter(
  23. "goframe.metric.demo.counter",
  24. gmetric.MetricOption{
  25. Help: "This is a simple demo for Counter usage",
  26. Unit: "bytes",
  27. Attributes: gmetric.Attributes{
  28. gmetric.NewAttribute("metric_const_attr_1", 1),
  29. },
  30. },
  31. )
  32. observableCounter = meter.MustObservableCounter(
  33. "goframe.metric.demo.observable_counter",
  34. gmetric.MetricOption{
  35. Help: "This is a simple demo for ObservableCounter usage",
  36. Unit: "%",
  37. Attributes: gmetric.Attributes{
  38. gmetric.NewAttribute("metric_const_attr_2", 2),
  39. },
  40. },
  41. )
  42. )
  43. func main() {
  44. var ctx = gctx.New()
  45. // Callback for observable metrics.
  46. meter.MustRegisterCallback(func(ctx context.Context, obs gmetric.Observer) error {
  47. obs.Observe(observableCounter, 10, gmetric.Option{
  48. Attributes: gmetric.Attributes{
  49. gmetric.NewAttribute("dynamic_attr_1", 1),
  50. },
  51. })
  52. return nil
  53. }, observableCounter)
  54. // Prometheus exporter to export metrics as Prometheus format.
  55. exporter, err := prometheus.New(
  56. prometheus.WithoutCounterSuffixes(),
  57. prometheus.WithoutUnits(),
  58. )
  59. if err != nil {
  60. g.Log().Fatal(ctx, err)
  61. }
  62. // OpenTelemetry provider.
  63. provider := otelmetric.MustProvider(
  64. otelmetric.WithReader(exporter),
  65. )
  66. provider.SetAsGlobal()
  67. defer provider.Shutdown(ctx)
  68. // Counter.
  69. counter.Inc(ctx, gmetric.Option{
  70. Attributes: gmetric.Attributes{
  71. gmetric.NewAttribute("dynamic_attr_2", 2),
  72. },
  73. })
  74. counter.Add(ctx, 10, gmetric.Option{
  75. Attributes: gmetric.Attributes{
  76. gmetric.NewAttribute("dynamic_attr_3", 3),
  77. },
  78. })
  79. // HTTP Server for metrics exporting.
  80. otelmetric.StartPrometheusMetricsServer(8000, "/metrics")
  81. }

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.

Metrics - Attributes - 图3

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:

  1. package main
  2. import (
  3. "context"
  4. "go.opentelemetry.io/otel/exporters/prometheus"
  5. "github.com/gogf/gf/contrib/metric/otelmetric/v2"
  6. "github.com/gogf/gf/v2/frame/g"
  7. "github.com/gogf/gf/v2/os/gctx"
  8. "github.com/gogf/gf/v2/os/gmetric"
  9. )
  10. const (
  11. instrument = "github.com/gogf/gf/example/metric/basic"
  12. instrumentVersion = "v1.0"
  13. )
  14. var (
  15. meter = gmetric.GetGlobalProvider().Meter(gmetric.MeterOption{
  16. Instrument: instrument,
  17. InstrumentVersion: instrumentVersion,
  18. Attributes: gmetric.Attributes{
  19. gmetric.NewAttribute("meter_const_attr_1", 1),
  20. },
  21. })
  22. counter = meter.MustCounter(
  23. "goframe.metric.demo.counter",
  24. gmetric.MetricOption{
  25. Help: "This is a simple demo for Counter usage",
  26. Unit: "bytes",
  27. Attributes: gmetric.Attributes{
  28. gmetric.NewAttribute("metric_const_attr_1", 1),
  29. },
  30. },
  31. )
  32. observableCounter = meter.MustObservableCounter(
  33. "goframe.metric.demo.observable_counter",
  34. gmetric.MetricOption{
  35. Help: "This is a simple demo for ObservableCounter usage",
  36. Unit: "%",
  37. Attributes: gmetric.Attributes{
  38. gmetric.NewAttribute("metric_const_attr_2", 2),
  39. },
  40. },
  41. )
  42. )
  43. func main() {
  44. var ctx = gctx.New()
  45. gmetric.SetGlobalAttributes(gmetric.Attributes{
  46. gmetric.NewAttribute("global_attr_1", 1),
  47. }, gmetric.SetGlobalAttributesOption{
  48. Instrument: instrument,
  49. InstrumentVersion: instrumentVersion,
  50. InstrumentPattern: "",
  51. })
  52. // Callback for observable metrics.
  53. meter.MustRegisterCallback(func(ctx context.Context, obs gmetric.Observer) error {
  54. obs.Observe(observableCounter, 10, gmetric.Option{
  55. Attributes: gmetric.Attributes{
  56. gmetric.NewAttribute("dynamic_attr_1", 1),
  57. },
  58. })
  59. return nil
  60. }, observableCounter)
  61. // Prometheus exporter to export metrics as Prometheus format.
  62. exporter, err := prometheus.New(
  63. prometheus.WithoutCounterSuffixes(),
  64. prometheus.WithoutUnits(),
  65. )
  66. if err != nil {
  67. g.Log().Fatal(ctx, err)
  68. }
  69. // OpenTelemetry provider.
  70. provider := otelmetric.MustProvider(
  71. otelmetric.WithReader(exporter),
  72. )
  73. provider.SetAsGlobal()
  74. defer provider.Shutdown(ctx)
  75. // Counter.
  76. counter.Inc(ctx, gmetric.Option{
  77. Attributes: gmetric.Attributes{
  78. gmetric.NewAttribute("dynamic_attr_2", 2),
  79. },
  80. })
  81. counter.Add(ctx, 10, gmetric.Option{
  82. Attributes: gmetric.Attributes{
  83. gmetric.NewAttribute("dynamic_attr_3", 3),
  84. },
  85. })
  86. // HTTP Server for metrics exporting.
  87. otelmetric.StartPrometheusMetricsServer(8000, "/metrics")
  88. }

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.

Metrics - Attributes - 图4