Skip to content

Commit 9d4439f

Browse files
authored
cmdutil: Add OTEL contrib runtime instrumentation (#213)
## Rationale We want the option to collect Golang runtime metrics out of the box with `heroku/x/cmdutil`. Here we introduce a new environment variable `OTEL_ENABLE_RUNTIME_METRICS` that when set to `true` will start the collection of runtime metrics and their reporting through the OTEL pipeline. ## Changes * Add dependency `go.opentelemetry.io/contrib/instrumentation/[email protected]` * Add config `OTEL_ENABLE_RUNTIME_METRICS`, defaulting to `false` * Add option function to enable runtime metrics collection * Update semconv version to `go.opentelemetry.io/otel/semconv/v1.25.0` ## Meta [W-15906716](https://gus.lightning.force.com/a07EE00001sy18ZYAQ)
1 parent 1f1acb1 commit 9d4439f

File tree

7 files changed

+82
-38
lines changed

7 files changed

+82
-38
lines changed

cmdutil/metrics/otel/config.go

+5-4
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,11 @@ import (
99
// Config is a reusable configuration struct that contains the necessary
1010
// environment variables to setup an metrics.Provider
1111
type Config struct {
12-
Enabled bool `env:"ENABLE_OTEL_COLLECTION"`
13-
CollectorURL *url.URL `env:"OTEL_COLLECTOR_URL"`
14-
MetricsDestinations []string `env:"OTEL_METRICS_DESTINATIONS,default=honeycomb;argus"`
15-
Honeycomb honeycomb.Config
12+
Enabled bool `env:"ENABLE_OTEL_COLLECTION"`
13+
EnableRuntimeMetrics bool `env:"OTEL_ENABLE_RUNTIME_METRICS,default=false"`
14+
CollectorURL *url.URL `env:"OTEL_COLLECTOR_URL"`
15+
MetricsDestinations []string `env:"OTEL_METRICS_DESTINATIONS,default=honeycomb;argus"`
16+
Honeycomb honeycomb.Config
1617

1718
// EndpointURL maps to the official opentelemetry environment variable for configuring the endpoint
1819
EndpointURL *url.URL `env:"OTEL_EXPORTER_OTLP_ENDPOINT"`

cmdutil/metrics/otel/otel.go

+7
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,9 @@ func MustProvider(ctx context.Context, logger logrus.FieldLogger, cfg Config, se
5353

5454
// ensure we use the http exporter
5555
otel.WithHTTPEndpointExporter(endpoint.String()),
56+
57+
// optionally enable Golang runtime metrics collection
58+
otel.WithRuntimeInstrumentation(cfg.EnableRuntimeMetrics),
5659
}
5760
allOpts = append(allOpts, opts...)
5861

@@ -61,5 +64,9 @@ func MustProvider(ctx context.Context, logger logrus.FieldLogger, cfg Config, se
6164
logger.Fatal(err)
6265
}
6366

67+
if err := otelProvider.(*otel.Provider).Start(); err != nil {
68+
logger.Fatal(err)
69+
}
70+
6471
return otelProvider
6572
}

go-kit/metrics/provider/otel/options.go

+24
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,19 @@ func WithCollectPeriod(collectPeriod time.Duration) Option {
5252
}
5353
}
5454

55+
// DefaultTemporalitySelector uses delta temporality for all instrument kinds, except
56+
// UpDown counters it uses cumulative temporality.
57+
func DefaultTemporalitySelector(ik metric.InstrumentKind) metricdata.Temporality {
58+
switch ik {
59+
case
60+
metric.InstrumentKindUpDownCounter,
61+
metric.InstrumentKindObservableUpDownCounter:
62+
return metricdata.CumulativeTemporality
63+
default:
64+
return metricdata.DeltaTemporality
65+
}
66+
}
67+
5568
func CumulativeTemporalitySelector(_ metric.InstrumentKind) metricdata.Temporality {
5669
return metricdata.CumulativeTemporality
5770
}
@@ -60,6 +73,10 @@ func DeltaTemporalitySelector(_ metric.InstrumentKind) metricdata.Temporality {
6073
return metricdata.DeltaTemporality
6174
}
6275

76+
func WithDefaultTemporality() Option {
77+
return WithTemporalitySelector(DefaultTemporalitySelector)
78+
}
79+
6380
func WithCumulativeTemporality() Option {
6481
return WithTemporalitySelector(CumulativeTemporalitySelector)
6582
}
@@ -177,3 +194,10 @@ func WithExporterFunc(fn exporterFactory) Option {
177194
return nil
178195
}
179196
}
197+
198+
func WithRuntimeInstrumentation(b bool) Option {
199+
return func(c *config) error {
200+
c.enableRuntimeMetrics = b
201+
return nil
202+
}
203+
}

go-kit/metrics/provider/otel/provider.go

+17-8
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"sync"
77
"time"
88

9+
"go.opentelemetry.io/contrib/instrumentation/runtime"
910
"go.opentelemetry.io/otel/sdk/metric"
1011
"go.opentelemetry.io/otel/sdk/resource"
1112

@@ -20,13 +21,14 @@ const (
2021
var DefaultReaderInterval = time.Minute
2122

2223
type config struct {
23-
ctx context.Context // used for init and shutdown of the otlp exporter and other bits of this Provider
24-
serviceResource *resource.Resource
25-
prefix string
26-
collectPeriod time.Duration
27-
temporalitySelector metric.TemporalitySelector
28-
aggregationSelector metric.AggregationSelector
29-
exporterFactory exporterFactory
24+
ctx context.Context // used for init and shutdown of the otlp exporter and other bits of this Provider
25+
serviceResource *resource.Resource
26+
prefix string
27+
collectPeriod time.Duration
28+
temporalitySelector metric.TemporalitySelector
29+
aggregationSelector metric.AggregationSelector
30+
exporterFactory exporterFactory
31+
enableRuntimeMetrics bool
3032
}
3133

3234
// Provider initializes a global otlp meter provider that can collect metrics and
@@ -128,7 +130,14 @@ func New(ctx context.Context, serviceName string, opts ...Option) (xmetrics.Prov
128130

129131
// Start starts the provider's controller and exporter.
130132
func (p *Provider) Start() error {
131-
return nil
133+
var err error
134+
if p.cfg.enableRuntimeMetrics {
135+
err = runtime.Start(
136+
runtime.WithMeterProvider(p.meterProvider),
137+
runtime.WithMinimumReadMemStatsInterval(p.cfg.collectPeriod),
138+
)
139+
}
140+
return err
132141
}
133142

134143
// Stop shuts down the provider's controller and exporter.

go-kit/metrics/provider/otel/resource.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import (
66
"go.opentelemetry.io/otel/attribute"
77
"go.opentelemetry.io/otel/sdk/resource"
88

9-
semconv "go.opentelemetry.io/otel/semconv/v1.21.0"
9+
semconv "go.opentelemetry.io/otel/semconv/v1.25.0"
1010
)
1111

1212
// Service level resource attributes

go.mod

+8-7
Original file line numberDiff line numberDiff line change
@@ -40,15 +40,14 @@ require (
4040
github.com/unrolled/secure v1.0.1
4141
github.com/urfave/cli v1.21.0
4242
go.opencensus.io v0.22.1
43-
go.opentelemetry.io/otel v1.19.0
43+
go.opentelemetry.io/otel v1.27.0
4444
go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.42.0 // indirect
4545
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.42.0
4646
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.42.0
47-
go.opentelemetry.io/otel/metric v1.19.0
48-
go.opentelemetry.io/otel/sdk v1.19.0
47+
go.opentelemetry.io/otel/metric v1.27.0
4948
golang.org/x/crypto v0.21.0
5049
golang.org/x/sync v0.3.0
51-
golang.org/x/sys v0.18.0 // indirect
50+
golang.org/x/sys v0.20.0 // indirect
5251
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c
5352
google.golang.org/grpc v1.59.0
5453
google.golang.org/grpc/examples v0.0.0-20210916203835-567da6b86340
@@ -58,19 +57,21 @@ require (
5857
)
5958

6059
require (
61-
go.opentelemetry.io/otel/sdk/metric v1.19.0
60+
go.opentelemetry.io/contrib/instrumentation/runtime v0.45.0
61+
go.opentelemetry.io/otel/sdk v1.27.0
62+
go.opentelemetry.io/otel/sdk/metric v1.27.0
6263
golang.org/x/text v0.14.0
6364
)
6465

6566
require (
6667
github.com/cenkalti/backoff/v4 v4.2.1 // indirect
6768
github.com/census-instrumentation/opencensus-proto v0.4.1 // indirect
68-
github.com/go-logr/logr v1.2.4 // indirect
69+
github.com/go-logr/logr v1.4.1 // indirect
6970
github.com/go-logr/stdr v1.2.2 // indirect
7071
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6 // indirect
7172
github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.0 // indirect
7273
github.com/konsorten/go-windows-terminal-sequences v1.0.3 // indirect
73-
go.opentelemetry.io/otel/trace v1.19.0 // indirect
74+
go.opentelemetry.io/otel/trace v1.27.0 // indirect
7475
go.opentelemetry.io/proto/otlp v1.0.0 // indirect
7576
golang.org/x/net v0.23.0 // indirect
7677
golang.org/x/oauth2 v0.12.0 // indirect

go.sum

+20-18
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,8 @@ github.com/go-kit/kit v0.9.0 h1:wDJmvq38kDhkVxi50ni9ykkdUr1PKgqKOoi01fa0Mdk=
5555
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
5656
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
5757
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
58-
github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ=
59-
github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
58+
github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ=
59+
github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
6060
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
6161
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
6262
github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
@@ -101,8 +101,8 @@ github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw
101101
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
102102
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
103103
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
104-
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
105-
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
104+
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
105+
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
106106
github.com/google/gops v0.3.22 h1:lyvhDxfPLHAOR2xIYwjPhN387qHxyU21Sk9sz/GhmhQ=
107107
github.com/google/gops v0.3.22/go.mod h1:7diIdLsqpCihPSX3fQagksT/Ku/y4RL9LHTlKyEUDl8=
108108
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
@@ -191,8 +191,8 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P
191191
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
192192
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
193193
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
194-
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
195-
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
194+
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
195+
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
196196
github.com/tklauser/go-sysconf v0.3.9/go.mod h1:11DU/5sG7UexIrp/O6g35hrWzu0JxlwQ3LSFUzyeuhs=
197197
github.com/tklauser/numcpus v0.3.0/go.mod h1:yFGUr7TUHQRAhyqBcEg0Ge34zDBAsIvJJcyE6boqnA8=
198198
github.com/unrolled/secure v1.0.1 h1:PZ79/VmnyIrDWRAUp9lWSwmckdf8H0v9djiqZxAb8Tc=
@@ -207,22 +207,24 @@ go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
207207
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
208208
go.opencensus.io v0.22.1 h1:8dP3SGL7MPB94crU3bEPplMPe83FI4EouesJUeFHv50=
209209
go.opencensus.io v0.22.1/go.mod h1:Ap50jQcDJrx6rB6VgeeFPtuPIf3wMRvRfrfYDO6+BmA=
210-
go.opentelemetry.io/otel v1.19.0 h1:MuS/TNf4/j4IXsZuJegVzI1cwut7Qc00344rgH7p8bs=
211-
go.opentelemetry.io/otel v1.19.0/go.mod h1:i0QyjOq3UPoTzff0PJB2N66fb4S0+rSbSB15/oyH9fY=
210+
go.opentelemetry.io/contrib/instrumentation/runtime v0.45.0 h1:2JydY5UiDpqvj2p7sO9bgHuhTy4hgTZ0ymehdq/Ob0Q=
211+
go.opentelemetry.io/contrib/instrumentation/runtime v0.45.0/go.mod h1:ch3a5QxOqVWxas4CzjCFFOOQe+7HgAXC/N1oVxS9DK4=
212+
go.opentelemetry.io/otel v1.27.0 h1:9BZoF3yMK/O1AafMiQTVu0YDj5Ea4hPhxCs7sGva+cg=
213+
go.opentelemetry.io/otel v1.27.0/go.mod h1:DMpAK8fzYRzs+bi3rS5REupisuqTheUlSZJ1WnZaPAQ=
212214
go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.42.0 h1:ZtfnDL+tUrs1F0Pzfwbg2d59Gru9NCH3bgSHBM6LDwU=
213215
go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.42.0/go.mod h1:hG4Fj/y8TR/tlEDREo8tWstl9fO9gcFkn4xrx0Io8xU=
214216
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.42.0 h1:NmnYCiR0qNufkldjVvyQfZTHSdzeHoZ41zggMsdMcLM=
215217
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.42.0/go.mod h1:UVAO61+umUsHLtYb8KXXRoHtxUkdOPkYidzW3gipRLQ=
216218
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.42.0 h1:wNMDy/LVGLj2h3p6zg4d0gypKfWKSWI14E1C4smOgl8=
217219
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.42.0/go.mod h1:YfbDdXAAkemWJK3H/DshvlrxqFB2rtW4rY6ky/3x/H0=
218-
go.opentelemetry.io/otel/metric v1.19.0 h1:aTzpGtV0ar9wlV4Sna9sdJyII5jTVJEvKETPiOKwvpE=
219-
go.opentelemetry.io/otel/metric v1.19.0/go.mod h1:L5rUsV9kM1IxCj1MmSdS+JQAcVm319EUrDVLrt7jqt8=
220-
go.opentelemetry.io/otel/sdk v1.19.0 h1:6USY6zH+L8uMH8L3t1enZPR3WFEmSTADlqldyHtJi3o=
221-
go.opentelemetry.io/otel/sdk v1.19.0/go.mod h1:NedEbbS4w3C6zElbLdPJKOpJQOrGUJ+GfzpjUvI0v1A=
222-
go.opentelemetry.io/otel/sdk/metric v1.19.0 h1:EJoTO5qysMsYCa+w4UghwFV/ptQgqSL/8Ni+hx+8i1k=
223-
go.opentelemetry.io/otel/sdk/metric v1.19.0/go.mod h1:XjG0jQyFJrv2PbMvwND7LwCEhsJzCzV5210euduKcKY=
224-
go.opentelemetry.io/otel/trace v1.19.0 h1:DFVQmlVbfVeOuBRrwdtaehRrWiL1JoVs9CPIQ1Dzxpg=
225-
go.opentelemetry.io/otel/trace v1.19.0/go.mod h1:mfaSyvGyEJEI0nyV2I4qhNQnbBOUUmYZpYojqMnX2vo=
220+
go.opentelemetry.io/otel/metric v1.27.0 h1:hvj3vdEKyeCi4YaYfNjv2NUje8FqKqUY8IlF0FxV/ik=
221+
go.opentelemetry.io/otel/metric v1.27.0/go.mod h1:mVFgmRlhljgBiuk/MP/oKylr4hs85GZAylncepAX/ak=
222+
go.opentelemetry.io/otel/sdk v1.27.0 h1:mlk+/Y1gLPLn84U4tI8d3GNJmGT/eXe3ZuOXN9kTWmI=
223+
go.opentelemetry.io/otel/sdk v1.27.0/go.mod h1:Ha9vbLwJE6W86YstIywK2xFfPjbWlCuwPtMkKdz/Y4A=
224+
go.opentelemetry.io/otel/sdk/metric v1.27.0 h1:5uGNOlpXi+Hbo/DRoI31BSb1v+OGcpv2NemcCrOL8gI=
225+
go.opentelemetry.io/otel/sdk/metric v1.27.0/go.mod h1:we7jJVrYN2kh3mVBlswtPU22K0SA+769l93J6bsyvqw=
226+
go.opentelemetry.io/otel/trace v1.27.0 h1:IqYb813p7cmbHk0a5y6pD5JPakbVfftRXABGt5/Rscw=
227+
go.opentelemetry.io/otel/trace v1.27.0/go.mod h1:6RiD1hkAprV4/q+yd2ln1HG9GoPx39SuvvstaLBl+l4=
226228
go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I=
227229
go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM=
228230
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
@@ -290,8 +292,8 @@ golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7w
290292
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
291293
golang.org/x/sys v0.0.0-20210816074244-15123e1e1f71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
292294
golang.org/x/sys v0.0.0-20210902050250-f475640dd07b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
293-
golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
294-
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
295+
golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
296+
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
295297
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
296298
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
297299
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=

0 commit comments

Comments
 (0)