-
Notifications
You must be signed in to change notification settings - Fork 1.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add metrics Enricher API #1271
Add metrics Enricher API #1271
Changes from 17 commits
468688c
fc0b575
4e641ac
fe2c130
dbe97fe
b297e94
ee0f8fd
21c833f
7b11574
015599a
adf34f1
e6b051e
afa378d
8ea1616
f73d433
208a049
4f91f17
4739df6
85faa2e
b94b328
b3caafa
a22e258
6dab82e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
// Copyright The OpenTelemetry Authors | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
package metric | ||
|
||
// Config contains configuration for an SDK. | ||
type Config struct { | ||
// If provided, MetricsLabelsEnricher is executed each time a metric is recorded | ||
// by the Accumulator's sync instrument implementation | ||
MetricsLabelsEnricher MetricsLabelsEnricher | ||
} | ||
|
||
// Option is the interface that applies the value to a configuration option. | ||
type Option interface { | ||
// Apply sets the Option value of a Config. | ||
Apply(*Config) | ||
} | ||
|
||
func WithMetricsLabelsEnricher(e MetricsLabelsEnricher) Option { | ||
return metricsLabelsEnricherOption(e) | ||
} | ||
|
||
type metricsLabelsEnricherOption MetricsLabelsEnricher | ||
|
||
func (e metricsLabelsEnricherOption) Apply(config *Config) { | ||
config.MetricsLabelsEnricher = MetricsLabelsEnricher(e) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,6 +17,7 @@ package push // import "go.opentelemetry.io/otel/sdk/metric/controller/push" | |
import ( | ||
"time" | ||
|
||
"go.opentelemetry.io/otel/sdk/metric" | ||
"go.opentelemetry.io/otel/sdk/resource" | ||
) | ||
|
||
|
@@ -33,6 +34,10 @@ type Config struct { | |
// integrate, and export) can last before it is canceled. Defaults to | ||
// the controller push period. | ||
Timeout time.Duration | ||
|
||
// MetricsLabelsEnricher is a function that enriches metrics labels based | ||
// on kvs stored in context when metrics are recorded. | ||
MetricsLabelsEnricher metric.MetricsLabelsEnricher | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. (Repeat: open-telemetry/opentelemetry-specification#1207 says we can and should consolidate push and pull controllers, to avoid this repetition.) |
||
} | ||
|
||
// Option is the interface that applies the value to a configuration option. | ||
|
@@ -73,3 +78,13 @@ type timeoutOption time.Duration | |
func (o timeoutOption) Apply(config *Config) { | ||
config.Timeout = time.Duration(o) | ||
} | ||
|
||
func WithMetricsLabelsEnricher(e metric.MetricsLabelsEnricher) Option { | ||
return metricsLabelsEnricherOption(e) | ||
} | ||
|
||
type metricsLabelsEnricherOption metric.MetricsLabelsEnricher | ||
|
||
func (e metricsLabelsEnricherOption) Apply(config *Config) { | ||
config.MetricsLabelsEnricher = metric.MetricsLabelsEnricher(e) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -67,6 +67,9 @@ type ( | |
|
||
// resource is applied to all records in this Accumulator. | ||
resource *resource.Resource | ||
|
||
// metricsLabelsEnricher is applied to all records in this Accumulator | ||
metricsLabelsEnricher MetricsLabelsEnricher | ||
} | ||
|
||
syncInstrument struct { | ||
|
@@ -139,6 +142,10 @@ type ( | |
labels *label.Set | ||
observed export.Aggregator | ||
} | ||
|
||
// MetricsLabelsEnricher can be provided as a config option to enrich metrics labels based on | ||
// the context when the metrics are recorded | ||
MetricsLabelsEnricher func(context.Context, []label.KeyValue) ([]label.KeyValue, error) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @MrAlias Does this make sense?
jmacd marked this conversation as resolved.
Show resolved
Hide resolved
|
||
) | ||
|
||
var ( | ||
|
@@ -291,6 +298,9 @@ func (s *syncInstrument) Bind(kvs []label.KeyValue) api.BoundSyncImpl { | |
} | ||
|
||
func (s *syncInstrument) RecordOne(ctx context.Context, number api.Number, kvs []label.KeyValue) { | ||
if s.meter.metricsLabelsEnricher != nil { | ||
kvs, _ = s.meter.metricsLabelsEnricher(ctx, kvs) | ||
} | ||
h := s.acquireHandle(kvs, nil) | ||
defer h.Unbind() | ||
h.RecordOne(ctx, number) | ||
|
@@ -305,11 +315,17 @@ func (s *syncInstrument) RecordOne(ctx context.Context, number api.Number, kvs [ | |
// processor will call Collect() when it receives a request to scrape | ||
// current metric values. A push-based processor should configure its | ||
// own periodic collection. | ||
func NewAccumulator(processor export.Processor, resource *resource.Resource) *Accumulator { | ||
func NewAccumulator(processor export.Processor, resource *resource.Resource, opts ...Option) *Accumulator { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. See the comment above. I'd be happier to leave this a three-argument function until we have more than one optional setting. |
||
c := &Config{} | ||
for _, opt := range opts { | ||
opt.Apply(c) | ||
} | ||
|
||
return &Accumulator{ | ||
processor: processor, | ||
asyncInstruments: internal.NewAsyncInstrumentState(), | ||
resource: resource, | ||
processor: processor, | ||
asyncInstruments: internal.NewAsyncInstrumentState(), | ||
resource: resource, | ||
metricsLabelsEnricher: c.MetricsLabelsEnricher, | ||
} | ||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FWIW I recently removed a similar struct from this package, arguing that Accumulators are not generally built from options, but from one of the controllers. That's why Resource is an explicit argument, and I would be just as happy if this were an third argument to the function, as opposed to a new option. This would be the first optional setting, and maybe we can introduce a Config struct an Option interface when there are more than one.
FWIW, I'm planning to consolidate the push and pull controllers, which would simplify this PR. See open-telemetry/opentelemetry-specification#1207.