Skip to content

Commit

Permalink
implement new runtime metrics
Browse files Browse the repository at this point in the history
  • Loading branch information
dashpole committed Jun 19, 2024
1 parent c7fb822 commit 2282435
Show file tree
Hide file tree
Showing 9 changed files with 498 additions and 77 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
- Add support to configure views when creating MeterProvider using the config package. (#5654)
- Add log support for the autoexport package. (#5733)
- Add support for disabling the old runtime metrics using the `OTEL_GO_X_DEPRECATED_RUNTIME_METRICS=false` environment variable. (#5747)
- Add new runtime metrics to `go.opentelemetry.io/contrib/instrumentation/runtime`, which are still disabled by default. (#5870)

### Fixed

Expand Down
12 changes: 12 additions & 0 deletions instrumentation/runtime/doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,16 @@
// runtime.go.mem.heap_sys (bytes) Bytes of heap memory obtained from the OS
// runtime.go.mem.live_objects - Number of live objects is the number of cumulative Mallocs - Frees
// runtime.uptime (ms) Milliseconds since application was initialized
//
// When the OTEL_GO_X_DEPRECATED_RUNTIME_METRICS environment variable is set to
// false, the metrics produced are:
//
// go.memory.used By Memory used by the Go runtime.
// go.memory.limit By Go runtime memory limit configured by the user, if a limit exists.
// go.memory.allocated By Memory allocated to the heap by the application.
// go.memory.allocations {allocation} Count of allocations to the heap by the application.
// go.memory.gc.goal By Heap size target for the end of the GC cycle.
// go.goroutine.count {goroutine} Count of live goroutines.
// go.processor.limit {thread} The number of OS threads that can execute user-level Go code simultaneously.
// go.config.gogc % Heap size target percentage configured by the user, otherwise 100.
package runtime // import "go.opentelemetry.io/contrib/instrumentation/runtime"
76 changes: 76 additions & 0 deletions instrumentation/runtime/options.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

package runtime // import "go.opentelemetry.io/contrib/instrumentation/runtime"

import (
"time"

"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/metric"
)

// config contains optional settings for reporting runtime metrics.
type config struct {
// MinimumReadMemStatsInterval sets the minimum interval
// between calls to runtime.ReadMemStats(). Negative values
// are ignored.
MinimumReadMemStatsInterval time.Duration

// MeterProvider sets the metric.MeterProvider. If nil, the global
// Provider will be used.
MeterProvider metric.MeterProvider
}

// Option supports configuring optional settings for runtime metrics.
type Option interface {
apply(*config)
}

// DefaultMinimumReadMemStatsInterval is the default minimum interval
// between calls to runtime.ReadMemStats(). Use the
// WithMinimumReadMemStatsInterval() option to modify this setting in
// Start().
const DefaultMinimumReadMemStatsInterval time.Duration = 15 * time.Second

// WithMinimumReadMemStatsInterval sets a minimum interval between calls to
// runtime.ReadMemStats(), which is a relatively expensive call to make
// frequently. This setting is ignored when `d` is negative.
func WithMinimumReadMemStatsInterval(d time.Duration) Option {
return minimumReadMemStatsIntervalOption(d)
}

type minimumReadMemStatsIntervalOption time.Duration

func (o minimumReadMemStatsIntervalOption) apply(c *config) {
if o >= 0 {
c.MinimumReadMemStatsInterval = time.Duration(o)
}
}

// WithMeterProvider sets the Metric implementation to use for
// reporting. If this option is not used, the global metric.MeterProvider
// will be used. `provider` must be non-nil.
func WithMeterProvider(provider metric.MeterProvider) Option {
return metricProviderOption{provider}
}

type metricProviderOption struct{ metric.MeterProvider }

func (o metricProviderOption) apply(c *config) {
if o.MeterProvider != nil {
c.MeterProvider = o.MeterProvider
}
}

// newConfig computes a config from the supplied Options.
func newConfig(opts ...Option) config {
c := config{
MeterProvider: otel.GetMeterProvider(),
MinimumReadMemStatsInterval: DefaultMinimumReadMemStatsInterval,
}
for _, opt := range opts {
opt.apply(&c)
}
return c
}
44 changes: 44 additions & 0 deletions instrumentation/runtime/options_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

package runtime // import "go.opentelemetry.io/contrib/instrumentation/runtime"

import (
"testing"
"time"

"github.com/stretchr/testify/assert"
)

func TestNewConfig(t *testing.T) {
for _, tt := range []struct {
name string
opts []Option
expect config
}{
{
name: "default",
expect: config{MinimumReadMemStatsInterval: 15 * time.Second},
},
{
name: "negative MinimumReadMemStatsInterval ignored",
opts: []Option{WithMinimumReadMemStatsInterval(-1 * time.Second)},
expect: config{MinimumReadMemStatsInterval: 15 * time.Second},
},
{
name: "set MinimumReadMemStatsInterval",
opts: []Option{WithMinimumReadMemStatsInterval(10 * time.Second)},
expect: config{MinimumReadMemStatsInterval: 10 * time.Second},
},
} {
t.Run(tt.name, func(t *testing.T) {
got := newConfig(tt.opts...)
assert.True(t, configEqual(got, tt.expect))
})
}
}

func configEqual(a, b config) bool {
// ignore MeterProvider
return a.MinimumReadMemStatsInterval == b.MinimumReadMemStatsInterval
}

0 comments on commit 2282435

Please sign in to comment.