diff --git a/instrumentation/runtime/options.go b/instrumentation/runtime/options.go index 580dc5dcd53..2e53ba3c9a0 100644 --- a/instrumentation/runtime/options.go +++ b/instrumentation/runtime/options.go @@ -7,6 +7,7 @@ import ( "time" "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/metric" ) @@ -20,6 +21,10 @@ type config struct { // MeterProvider sets the metric.MeterProvider. If nil, the global // Provider will be used. MeterProvider metric.MeterProvider + + // Attributes sets the attributes collection which will be added + // to exported metrics. If nil or empty, then will be ignored. + Attributes []attribute.KeyValue } // Option supports configuring optional settings for runtime metrics. @@ -72,6 +77,21 @@ func (o metricProviderOption) apply(c *config) { } } +// WithAttributes sets the user-defined attributes for each runtime +// metric, which will be reported. If this option is not used, then +// a default metric attributes will be used. +func WithAttributes(attributes ...attribute.KeyValue) Option { + return attributesOption {attributes: attributes} +} + +type attributesOption struct { + attributes []attribute.KeyValue +} + +func (o attributesOption) apply(c *config) { + c.Attributes = o.attributes +} + // newConfig computes a config from the supplied Options. func newConfig(opts ...Option) config { c := config{ diff --git a/instrumentation/runtime/runtime.go b/instrumentation/runtime/runtime.go index 3dc4ad8c5aa..4e4721ea456 100644 --- a/instrumentation/runtime/runtime.go +++ b/instrumentation/runtime/runtime.go @@ -81,6 +81,7 @@ func Start(opts ...Option) error { return err } + defaultMetricOpt := metric.WithAttributes(c.Attributes...) otherMemoryOpt := metric.WithAttributeSet( attribute.NewSet(memoryUsed.AttrMemoryType(goconv.MemoryTypeOther)), ) @@ -95,20 +96,20 @@ func Start(opts ...Option) error { defer lock.Unlock() collector.refresh() stackMemory := collector.getInt(goHeapMemory) - o.ObserveInt64(memoryUsed.Inst(), stackMemory, stackMemoryOpt) + o.ObserveInt64(memoryUsed.Inst(), stackMemory, stackMemoryOpt, defaultMetricOpt) totalMemory := collector.getInt(goTotalMemory) - collector.getInt(goMemoryReleased) otherMemory := totalMemory - stackMemory - o.ObserveInt64(memoryUsed.Inst(), otherMemory, otherMemoryOpt) + o.ObserveInt64(memoryUsed.Inst(), otherMemory, otherMemoryOpt, defaultMetricOpt) // Only observe the limit metric if a limit exists if limit := collector.getInt(goMemoryLimit); limit != math.MaxInt64 { - o.ObserveInt64(memoryLimit.Inst(), limit) + o.ObserveInt64(memoryLimit.Inst(), limit, defaultMetricOpt) } - o.ObserveInt64(memoryAllocated.Inst(), collector.getInt(goMemoryAllocated)) - o.ObserveInt64(memoryAllocations.Inst(), collector.getInt(goMemoryAllocations)) - o.ObserveInt64(memoryGCGoal.Inst(), collector.getInt(goMemoryGoal)) - o.ObserveInt64(goroutineCount.Inst(), collector.getInt(goGoroutines)) - o.ObserveInt64(processorLimit.Inst(), collector.getInt(goMaxProcs)) - o.ObserveInt64(configGogc.Inst(), collector.getInt(goConfigGC)) + o.ObserveInt64(memoryAllocated.Inst(), collector.getInt(goMemoryAllocated), defaultMetricOpt) + o.ObserveInt64(memoryAllocations.Inst(), collector.getInt(goMemoryAllocations), defaultMetricOpt) + o.ObserveInt64(memoryGCGoal.Inst(), collector.getInt(goMemoryGoal), defaultMetricOpt) + o.ObserveInt64(goroutineCount.Inst(), collector.getInt(goGoroutines), defaultMetricOpt) + o.ObserveInt64(processorLimit.Inst(), collector.getInt(goMaxProcs), defaultMetricOpt) + o.ObserveInt64(configGogc.Inst(), collector.getInt(goConfigGC), defaultMetricOpt) return nil }, memoryUsed.Inst(), diff --git a/instrumentation/runtime/runtime_test.go b/instrumentation/runtime/runtime_test.go index c3efb20a0cf..25ee67d1b26 100644 --- a/instrumentation/runtime/runtime_test.go +++ b/instrumentation/runtime/runtime_test.go @@ -65,9 +65,10 @@ func TestRuntimeWithLimit(t *testing.T) { // reset to default defer debug.SetMemoryLimit(math.MaxInt64) + defaultAttribute := attribute.String("test.key", "value") reader := metric.NewManualReader() mp := metric.NewMeterProvider(metric.WithReader(reader)) - err := Start(WithMeterProvider(mp)) + err := Start(WithMeterProvider(mp), WithAttributes(defaultAttribute)) assert.NoError(t, err) rm := metricdata.ResourceMetrics{} err = reader.Collect(t.Context(), &rm) @@ -92,11 +93,13 @@ func TestRuntimeWithLimit(t *testing.T) { { Attributes: attribute.NewSet( goconv.MemoryUsed{}.AttrMemoryType(goconv.MemoryTypeStack), + defaultAttribute, ), }, { Attributes: attribute.NewSet( goconv.MemoryUsed{}.AttrMemoryType(goconv.MemoryTypeOther), + defaultAttribute, ), }, }, @@ -109,7 +112,13 @@ func TestRuntimeWithLimit(t *testing.T) { Data: metricdata.Sum[int64]{ Temporality: metricdata.CumulativeTemporality, IsMonotonic: false, - DataPoints: []metricdata.DataPoint[int64]{{}}, + DataPoints: []metricdata.DataPoint[int64]{ + { + Attributes: attribute.NewSet( + defaultAttribute, + ), + }, + }, }, }, { @@ -119,7 +128,13 @@ func TestRuntimeWithLimit(t *testing.T) { Data: metricdata.Sum[int64]{ Temporality: metricdata.CumulativeTemporality, IsMonotonic: true, - DataPoints: []metricdata.DataPoint[int64]{{}}, + DataPoints: []metricdata.DataPoint[int64]{ + { + Attributes: attribute.NewSet( + defaultAttribute, + ), + }, + }, }, }, { @@ -129,7 +144,13 @@ func TestRuntimeWithLimit(t *testing.T) { Data: metricdata.Sum[int64]{ Temporality: metricdata.CumulativeTemporality, IsMonotonic: true, - DataPoints: []metricdata.DataPoint[int64]{{}}, + DataPoints: []metricdata.DataPoint[int64]{ + { + Attributes: attribute.NewSet( + defaultAttribute, + ), + }, + }, }, }, { @@ -139,7 +160,13 @@ func TestRuntimeWithLimit(t *testing.T) { Data: metricdata.Sum[int64]{ Temporality: metricdata.CumulativeTemporality, IsMonotonic: false, - DataPoints: []metricdata.DataPoint[int64]{{}}, + DataPoints: []metricdata.DataPoint[int64]{ + { + Attributes: attribute.NewSet( + defaultAttribute, + ), + }, + }, }, }, { @@ -149,7 +176,13 @@ func TestRuntimeWithLimit(t *testing.T) { Data: metricdata.Sum[int64]{ Temporality: metricdata.CumulativeTemporality, IsMonotonic: false, - DataPoints: []metricdata.DataPoint[int64]{{}}, + DataPoints: []metricdata.DataPoint[int64]{ + { + Attributes: attribute.NewSet( + defaultAttribute, + ), + }, + }, }, }, { @@ -159,7 +192,13 @@ func TestRuntimeWithLimit(t *testing.T) { Data: metricdata.Sum[int64]{ Temporality: metricdata.CumulativeTemporality, IsMonotonic: false, - DataPoints: []metricdata.DataPoint[int64]{{}}, + DataPoints: []metricdata.DataPoint[int64]{ + { + Attributes: attribute.NewSet( + defaultAttribute, + ), + }, + }, }, }, { @@ -169,7 +208,13 @@ func TestRuntimeWithLimit(t *testing.T) { Data: metricdata.Sum[int64]{ Temporality: metricdata.CumulativeTemporality, IsMonotonic: false, - DataPoints: []metricdata.DataPoint[int64]{{}}, + DataPoints: []metricdata.DataPoint[int64]{ + { + Attributes: attribute.NewSet( + defaultAttribute, + ), + }, + }, }, }, },