Skip to content

Metrics instrumentation version #811

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

Merged
merged 15 commits into from
Jun 12, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion api/global/internal/benchmark_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ func (*benchFixture) CheckpointSet() export.CheckpointSet {
func (*benchFixture) FinishedCollection() {
}

func (fix *benchFixture) Meter(name string) metric.Meter {
func (fix *benchFixture) Meter(_ string, _ ...metric.MeterOption) metric.Meter {
return fix.meter
}

Expand Down
30 changes: 19 additions & 11 deletions api/global/internal/meter.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ import (
// Metric uniqueness checking is implemented by calling the exported
// methods of the api/metric/registry package.

type meterKey struct {
Name, Version string
}

type meterProvider struct {
delegate metric.Provider

Expand All @@ -54,7 +58,7 @@ type meterProvider struct {

// meters maintains a unique entry for every named Meter
// that has been registered through the global instance.
meters map[string]*meterEntry
meters map[meterKey]*meterEntry
}

type meterImpl struct {
Expand Down Expand Up @@ -123,7 +127,7 @@ func (inst *instrument) Descriptor() metric.Descriptor {

func newMeterProvider() *meterProvider {
return &meterProvider{
meters: map[string]*meterEntry{},
meters: map[meterKey]*meterEntry{},
}
}

Expand All @@ -132,38 +136,42 @@ func (p *meterProvider) setDelegate(provider metric.Provider) {
defer p.lock.Unlock()

p.delegate = provider
for name, entry := range p.meters {
entry.impl.setDelegate(name, provider)
for key, entry := range p.meters {
entry.impl.setDelegate(key.Name, key.Version, provider)
}
p.meters = nil
}

func (p *meterProvider) Meter(name string) metric.Meter {
func (p *meterProvider) Meter(instrumentationName string, opts ...metric.MeterOption) metric.Meter {
p.lock.Lock()
defer p.lock.Unlock()

if p.delegate != nil {
return p.delegate.Meter(name)
return p.delegate.Meter(instrumentationName, opts...)
}

entry, ok := p.meters[name]
key := meterKey{
Name: instrumentationName,
Version: metric.ConfigureMeter(opts).InstrumentationVersion,
}
entry, ok := p.meters[key]
if !ok {
entry = &meterEntry{}
entry.unique = registry.NewUniqueInstrumentMeterImpl(&entry.impl)
p.meters[name] = entry
p.meters[key] = entry

}
return metric.WrapMeterImpl(entry.unique, name)
return metric.WrapMeterImpl(entry.unique, key.Name, metric.WithInstrumentationVersion(key.Version))
}

// Meter interface and delegation

func (m *meterImpl) setDelegate(name string, provider metric.Provider) {
func (m *meterImpl) setDelegate(name, version string, provider metric.Provider) {
m.lock.Lock()
defer m.lock.Unlock()

d := new(metric.MeterImpl)
*d = provider.Meter(name).MeterImpl()
*d = provider.Meter(name, metric.WithInstrumentationVersion(version)).MeterImpl()
m.delegate = unsafe.Pointer(d)

for _, inst := range m.syncInsts {
Expand Down
114 changes: 61 additions & 53 deletions api/global/internal/meter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,21 +36,23 @@ import (

// Note: Maybe this should be factored into ../../../internal/metric?
type measured struct {
Name string
LibraryName string
Labels map[kv.Key]value.Value
Number metric.Number
Name string
InstrumentationName string
InstrumentationVersion string
Labels map[kv.Key]value.Value
Number metric.Number
}

func asStructs(batches []metrictest.Batch) []measured {
var r []measured
for _, batch := range batches {
for _, m := range batch.Measurements {
r = append(r, measured{
Name: m.Instrument.Descriptor().Name(),
LibraryName: m.Instrument.Descriptor().LibraryName(),
Labels: asMap(batch.Labels...),
Number: m.Number,
Name: m.Instrument.Descriptor().Name(),
InstrumentationName: m.Instrument.Descriptor().InstrumentationName(),
InstrumentationVersion: m.Instrument.Descriptor().InstrumentationVersion(),
Labels: asMap(batch.Labels...),
Number: m.Number,
})
}
}
Expand All @@ -72,7 +74,7 @@ func TestDirect(t *testing.T) {
internal.ResetForTest()

ctx := context.Background()
meter1 := global.Meter("test1")
meter1 := global.Meter("test1", metric.WithInstrumentationVersion("semver:v1.0.0"))
meter2 := global.Meter("test2")
labels1 := []kv.KeyValue{kv.String("A", "B")}
labels2 := []kv.KeyValue{kv.String("C", "D")}
Expand Down Expand Up @@ -114,46 +116,52 @@ func TestDirect(t *testing.T) {
require.EqualValues(t,
[]measured{
{
Name: "test.counter",
LibraryName: "test1",
Labels: asMap(labels1...),
Number: asInt(1),
Name: "test.counter",
InstrumentationName: "test1",
InstrumentationVersion: "semver:v1.0.0",
Labels: asMap(labels1...),
Number: asInt(1),
},
{
Name: "test.valuerecorder",
LibraryName: "test1",
Labels: asMap(labels1...),
Number: asFloat(3),
Name: "test.valuerecorder",
InstrumentationName: "test1",
InstrumentationVersion: "semver:v1.0.0",
Labels: asMap(labels1...),
Number: asFloat(3),
},
{
Name: "test.second",
LibraryName: "test2",
Labels: asMap(labels3...),
Number: asFloat(3),
Name: "test.second",
InstrumentationName: "test2",
Labels: asMap(labels3...),
Number: asFloat(3),
},
{
Name: "test.valueobserver.float",
LibraryName: "test1",
Labels: asMap(labels1...),
Number: asFloat(1),
Name: "test.valueobserver.float",
InstrumentationName: "test1",
InstrumentationVersion: "semver:v1.0.0",
Labels: asMap(labels1...),
Number: asFloat(1),
},
{
Name: "test.valueobserver.float",
LibraryName: "test1",
Labels: asMap(labels2...),
Number: asFloat(2),
Name: "test.valueobserver.float",
InstrumentationName: "test1",
InstrumentationVersion: "semver:v1.0.0",
Labels: asMap(labels2...),
Number: asFloat(2),
},
{
Name: "test.valueobserver.int",
LibraryName: "test1",
Labels: asMap(labels1...),
Number: asInt(1),
Name: "test.valueobserver.int",
InstrumentationName: "test1",
InstrumentationVersion: "semver:v1.0.0",
Labels: asMap(labels1...),
Number: asInt(1),
},
{
Name: "test.valueobserver.int",
LibraryName: "test1",
Labels: asMap(labels2...),
Number: asInt(2),
Name: "test.valueobserver.int",
InstrumentationName: "test1",
InstrumentationVersion: "semver:v1.0.0",
Labels: asMap(labels2...),
Number: asInt(2),
},
},
measurements,
Expand Down Expand Up @@ -188,16 +196,16 @@ func TestBound(t *testing.T) {
require.EqualValues(t,
[]measured{
{
Name: "test.counter",
LibraryName: "test",
Labels: asMap(labels1...),
Number: asFloat(1),
Name: "test.counter",
InstrumentationName: "test",
Labels: asMap(labels1...),
Number: asFloat(1),
},
{
Name: "test.valuerecorder",
LibraryName: "test",
Labels: asMap(labels1...),
Number: asInt(3),
Name: "test.valuerecorder",
InstrumentationName: "test",
Labels: asMap(labels1...),
Number: asInt(3),
},
},
asStructs(mock.MeasurementBatches))
Expand Down Expand Up @@ -254,7 +262,7 @@ func TestDefaultSDK(t *testing.T) {
pusher.Stop()
out.Close()

require.Equal(t, `{"updates":[{"name":"test.builtin{A=B}","sum":1}]}
require.Equal(t, `{"updates":[{"name":"test.builtin{instrumentation.name=builtin,A=B}","sum":1}]}
`, <-ch)
}

Expand Down Expand Up @@ -284,8 +292,8 @@ type meterWithConstructorError struct {
metric.MeterImpl
}

func (m *meterProviderWithConstructorError) Meter(name string) metric.Meter {
return metric.WrapMeterImpl(&meterWithConstructorError{m.Provider.Meter(name).MeterImpl()}, name)
func (m *meterProviderWithConstructorError) Meter(iName string, opts ...metric.MeterOption) metric.Meter {
return metric.WrapMeterImpl(&meterWithConstructorError{m.Provider.Meter(iName, opts...).MeterImpl()}, iName, opts...)
}

func (m *meterWithConstructorError) NewSyncInstrument(_ metric.Descriptor) (metric.SyncImpl, error) {
Expand Down Expand Up @@ -380,10 +388,10 @@ func TestRecordBatchMock(t *testing.T) {
require.EqualValues(t,
[]measured{
{
Name: "test.counter",
LibraryName: "builtin",
Labels: asMap(),
Number: asInt(1),
Name: "test.counter",
InstrumentationName: "builtin",
Labels: asMap(),
Number: asInt(1),
},
},
asStructs(mock.MeasurementBatches))
Expand Down Expand Up @@ -412,6 +420,6 @@ func TestRecordBatchRealSDK(t *testing.T) {
meter.RecordBatch(context.Background(), nil, counter.Measurement(1))
pusher.Stop()

require.Equal(t, `{"updates":[{"name":"test.counter","sum":1}]}
require.Equal(t, `{"updates":[{"name":"test.counter{instrumentation.name=builtin}","sum":1}]}
`, buf.String())
}
12 changes: 8 additions & 4 deletions api/global/metric.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,16 @@ import (
"go.opentelemetry.io/otel/api/metric"
)

// Meter gets a named Meter interface. If the name is an
// empty string, the provider uses a default name.
// Meter creates an implementation of the Meter interface from the global
// Provider. The instrumentationName must be the name of the library
// providing instrumentation. This name may be the same as the instrumented
// code only if that code provides built-in instrumentation. If the
// instrumentationName is empty, then a implementation defined default name
// will be used instead.
//
// This is short for MeterProvider().Meter(name)
func Meter(name string) metric.Meter {
return MeterProvider().Meter(name)
func Meter(instrumentationName string, opts ...metric.MeterOption) metric.Meter {
return MeterProvider().Meter(instrumentationName, opts...)
}

// MeterProvider returns the registered global meter provider. If
Expand Down
2 changes: 1 addition & 1 deletion api/global/metric_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ type testMeterProvider struct{}

var _ metric.Provider = &testMeterProvider{}

func (*testMeterProvider) Meter(_ string) metric.Meter {
func (*testMeterProvider) Meter(_ string, _ ...metric.MeterOption) metric.Meter {
return metric.Meter{}
}

Expand Down
12 changes: 6 additions & 6 deletions api/metric/api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ var Must = metric.Must
func TestOptions(t *testing.T) {
type testcase struct {
name string
opts []metric.Option
opts []metric.InstrumentOption
desc string
unit unit.Unit
}
Expand All @@ -49,15 +49,15 @@ func TestOptions(t *testing.T) {
},
{
name: "description",
opts: []metric.Option{
opts: []metric.InstrumentOption{
metric.WithDescription("stuff"),
},
desc: "stuff",
unit: "",
},
{
name: "description override",
opts: []metric.Option{
opts: []metric.InstrumentOption{
metric.WithDescription("stuff"),
metric.WithDescription("things"),
},
Expand All @@ -66,15 +66,15 @@ func TestOptions(t *testing.T) {
},
{
name: "unit",
opts: []metric.Option{
opts: []metric.InstrumentOption{
metric.WithUnit("s"),
},
desc: "",
unit: "s",
},
{
name: "unit override",
opts: []metric.Option{
opts: []metric.InstrumentOption{
metric.WithUnit("s"),
metric.WithUnit("h"),
},
Expand All @@ -84,7 +84,7 @@ func TestOptions(t *testing.T) {
}
for idx, tt := range testcases {
t.Logf("Testing counter case %s (%d)", tt.name, idx)
if diff := cmp.Diff(metric.Configure(tt.opts), metric.Config{
if diff := cmp.Diff(metric.ConfigureInstrument(tt.opts), metric.InstrumentConfig{
Description: tt.desc,
Unit: tt.unit,
}); diff != "" {
Expand Down
Loading