1
0
mirror of https://github.com/open-telemetry/opentelemetry-go.git synced 2024-12-10 09:50:58 +02:00
This commit is contained in:
Stefan Prisca 2020-05-14 11:11:55 +02:00
commit 2c718982df
119 changed files with 2425 additions and 1890 deletions

View File

@ -1,20 +0,0 @@
// 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.
// This package provides basic types used in OpenTelemetry - keys,
// values, numbers and span contexts.
//
// See the api/key package for convenience functions for creating keys
// and key-value pairs.
package core // import "go.opentelemetry.io/otel/api/core"

View File

@ -1,391 +0,0 @@
// 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 core
//go:generate stringer -type=ValueType
import (
"encoding/json"
"fmt"
"strconv"
"unsafe"
"go.opentelemetry.io/otel/api/internal"
)
// Key represents the key part in key-value pairs. It's a string. The
// allowed character set in the key depends on the use of the key.
type Key string
// KeyValue holds a key and value pair.
type KeyValue struct {
Key Key
Value Value
}
// ValueType describes the type of the data Value holds.
type ValueType int
// Value represents the value part in key-value pairs.
type Value struct {
vtype ValueType
numeric uint64
stringly string
// TODO Lazy value type?
}
const (
INVALID ValueType = iota // No value.
BOOL // Boolean value, use AsBool() to get it.
INT32 // 32 bit signed integral value, use AsInt32() to get it.
INT64 // 64 bit signed integral value, use AsInt64() to get it.
UINT32 // 32 bit unsigned integral value, use AsUint32() to get it.
UINT64 // 64 bit unsigned integral value, use AsUint64() to get it.
FLOAT32 // 32 bit floating point value, use AsFloat32() to get it.
FLOAT64 // 64 bit floating point value, use AsFloat64() to get it.
STRING // String value, use AsString() to get it.
)
// Bool creates a BOOL Value.
func Bool(v bool) Value {
return Value{
vtype: BOOL,
numeric: internal.BoolToRaw(v),
}
}
// Int64 creates an INT64 Value.
func Int64(v int64) Value {
return Value{
vtype: INT64,
numeric: internal.Int64ToRaw(v),
}
}
// Uint64 creates a UINT64 Value.
func Uint64(v uint64) Value {
return Value{
vtype: UINT64,
numeric: internal.Uint64ToRaw(v),
}
}
// Float64 creates a FLOAT64 Value.
func Float64(v float64) Value {
return Value{
vtype: FLOAT64,
numeric: internal.Float64ToRaw(v),
}
}
// Int32 creates an INT32 Value.
func Int32(v int32) Value {
return Value{
vtype: INT32,
numeric: internal.Int32ToRaw(v),
}
}
// Uint32 creates a UINT32 Value.
func Uint32(v uint32) Value {
return Value{
vtype: UINT32,
numeric: internal.Uint32ToRaw(v),
}
}
// Float32 creates a FLOAT32 Value.
func Float32(v float32) Value {
return Value{
vtype: FLOAT32,
numeric: internal.Float32ToRaw(v),
}
}
// String creates a STRING Value.
func String(v string) Value {
return Value{
vtype: STRING,
stringly: v,
}
}
// Int creates either an INT32 or an INT64 Value, depending on whether
// the int type is 32 or 64 bits wide.
func Int(v int) Value {
if unsafe.Sizeof(v) == 4 {
return Int32(int32(v))
}
return Int64(int64(v))
}
// Uint creates either a UINT32 or a UINT64 Value, depending on
// whether the uint type is 32 or 64 bits wide.
func Uint(v uint) Value {
if unsafe.Sizeof(v) == 4 {
return Uint32(uint32(v))
}
return Uint64(uint64(v))
}
// Bool creates a KeyValue instance with a BOOL Value.
//
// If creating both key and a bool value at the same time, then
// instead of calling core.Key(name).Bool(value) consider using a
// convenience function provided by the api/key package -
// key.Bool(name, value).
func (k Key) Bool(v bool) KeyValue {
return KeyValue{
Key: k,
Value: Bool(v),
}
}
// Int64 creates a KeyValue instance with an INT64 Value.
//
// If creating both key and an int64 value at the same time, then
// instead of calling core.Key(name).Int64(value) consider using a
// convenience function provided by the api/key package -
// key.Int64(name, value).
func (k Key) Int64(v int64) KeyValue {
return KeyValue{
Key: k,
Value: Int64(v),
}
}
// Uint64 creates a KeyValue instance with a UINT64 Value.
//
// If creating both key and a uint64 value at the same time, then
// instead of calling core.Key(name).Uint64(value) consider using a
// convenience function provided by the api/key package -
// key.Uint64(name, value).
func (k Key) Uint64(v uint64) KeyValue {
return KeyValue{
Key: k,
Value: Uint64(v),
}
}
// Float64 creates a KeyValue instance with a FLOAT64 Value.
//
// If creating both key and a float64 value at the same time, then
// instead of calling core.Key(name).Float64(value) consider using a
// convenience function provided by the api/key package -
// key.Float64(name, value).
func (k Key) Float64(v float64) KeyValue {
return KeyValue{
Key: k,
Value: Float64(v),
}
}
// Int32 creates a KeyValue instance with an INT32 Value.
//
// If creating both key and an int32 value at the same time, then
// instead of calling core.Key(name).Int32(value) consider using a
// convenience function provided by the api/key package -
// key.Int32(name, value).
func (k Key) Int32(v int32) KeyValue {
return KeyValue{
Key: k,
Value: Int32(v),
}
}
// Uint32 creates a KeyValue instance with a UINT32 Value.
//
// If creating both key and a uint32 value at the same time, then
// instead of calling core.Key(name).Uint32(value) consider using a
// convenience function provided by the api/key package -
// key.Uint32(name, value).
func (k Key) Uint32(v uint32) KeyValue {
return KeyValue{
Key: k,
Value: Uint32(v),
}
}
// Float32 creates a KeyValue instance with a FLOAT32 Value.
//
// If creating both key and a float32 value at the same time, then
// instead of calling core.Key(name).Float32(value) consider using a
// convenience function provided by the api/key package -
// key.Float32(name, value).
func (k Key) Float32(v float32) KeyValue {
return KeyValue{
Key: k,
Value: Float32(v),
}
}
// String creates a KeyValue instance with a STRING Value.
//
// If creating both key and a string value at the same time, then
// instead of calling core.Key(name).String(value) consider using a
// convenience function provided by the api/key package -
// key.String(name, value).
func (k Key) String(v string) KeyValue {
return KeyValue{
Key: k,
Value: String(v),
}
}
// Int creates a KeyValue instance with either an INT32 or an INT64
// Value, depending on whether the int type is 32 or 64 bits wide.
//
// If creating both key and an int value at the same time, then
// instead of calling core.Key(name).Int(value) consider using a
// convenience function provided by the api/key package -
// key.Int(name, value).
func (k Key) Int(v int) KeyValue {
return KeyValue{
Key: k,
Value: Int(v),
}
}
// Uint creates a KeyValue instance with either a UINT32 or a UINT64
// Value, depending on whether the uint type is 32 or 64 bits wide.
//
// If creating both key and a uint value at the same time, then
// instead of calling core.Key(name).Uint(value) consider using a
// convenience function provided by the api/key package -
// key.Uint(name, value).
func (k Key) Uint(v uint) KeyValue {
return KeyValue{
Key: k,
Value: Uint(v),
}
}
// Defined returns true for non-empty keys.
func (k Key) Defined() bool {
return len(k) != 0
}
// Type returns a type of the Value.
func (v Value) Type() ValueType {
return v.vtype
}
// AsBool returns the bool value. Make sure that the Value's type is
// BOOL.
func (v Value) AsBool() bool {
return internal.RawToBool(v.numeric)
}
// AsInt32 returns the int32 value. Make sure that the Value's type is
// INT32.
func (v Value) AsInt32() int32 {
return internal.RawToInt32(v.numeric)
}
// AsInt64 returns the int64 value. Make sure that the Value's type is
// INT64.
func (v Value) AsInt64() int64 {
return internal.RawToInt64(v.numeric)
}
// AsUint32 returns the uint32 value. Make sure that the Value's type
// is UINT32.
func (v Value) AsUint32() uint32 {
return internal.RawToUint32(v.numeric)
}
// AsUint64 returns the uint64 value. Make sure that the Value's type is
// UINT64.
func (v Value) AsUint64() uint64 {
return internal.RawToUint64(v.numeric)
}
// AsFloat32 returns the float32 value. Make sure that the Value's
// type is FLOAT32.
func (v Value) AsFloat32() float32 {
return internal.RawToFloat32(v.numeric)
}
// AsFloat64 returns the float64 value. Make sure that the Value's
// type is FLOAT64.
func (v Value) AsFloat64() float64 {
return internal.RawToFloat64(v.numeric)
}
// AsString returns the string value. Make sure that the Value's type
// is STRING.
func (v Value) AsString() string {
return v.stringly
}
type unknownValueType struct{}
// AsInterface returns Value's data as interface{}.
func (v Value) AsInterface() interface{} {
switch v.Type() {
case BOOL:
return v.AsBool()
case INT32:
return v.AsInt32()
case INT64:
return v.AsInt64()
case UINT32:
return v.AsUint32()
case UINT64:
return v.AsUint64()
case FLOAT32:
return v.AsFloat32()
case FLOAT64:
return v.AsFloat64()
case STRING:
return v.stringly
}
return unknownValueType{}
}
// Emit returns a string representation of Value's data.
func (v Value) Emit() string {
switch v.Type() {
case BOOL:
return strconv.FormatBool(v.AsBool())
case INT32:
return strconv.FormatInt(int64(v.AsInt32()), 10)
case INT64:
return strconv.FormatInt(v.AsInt64(), 10)
case UINT32:
return strconv.FormatUint(uint64(v.AsUint32()), 10)
case UINT64:
return strconv.FormatUint(v.AsUint64(), 10)
case FLOAT32:
return fmt.Sprint(v.AsFloat32())
case FLOAT64:
return fmt.Sprint(v.AsFloat64())
case STRING:
return v.stringly
default:
return "unknown"
}
}
// MarshalJSON returns the JSON encoding of the Value.
func (v Value) MarshalJSON() ([]byte, error) {
var jsonVal struct {
Type string
Value interface{}
}
jsonVal.Type = v.Type().String()
jsonVal.Value = v.AsInterface()
return json.Marshal(jsonVal)
}

View File

@ -1,275 +0,0 @@
// 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 core_test
import (
"encoding/json"
"testing"
"unsafe"
"github.com/google/go-cmp/cmp"
"github.com/stretchr/testify/require"
"go.opentelemetry.io/otel/api/core"
"go.opentelemetry.io/otel/api/key"
)
func TestValue(t *testing.T) {
k := core.Key("test")
bli := getBitlessInfo(42)
for _, testcase := range []struct {
name string
value core.Value
wantType core.ValueType
wantValue interface{}
}{
{
name: "Key.Bool() correctly returns keys's internal bool value",
value: k.Bool(true).Value,
wantType: core.BOOL,
wantValue: true,
},
{
name: "Key.Int64() correctly returns keys's internal int64 value",
value: k.Int64(42).Value,
wantType: core.INT64,
wantValue: int64(42),
},
{
name: "Key.Uint64() correctly returns keys's internal uint64 value",
value: k.Uint64(42).Value,
wantType: core.UINT64,
wantValue: uint64(42),
},
{
name: "Key.Float64() correctly returns keys's internal float64 value",
value: k.Float64(42.1).Value,
wantType: core.FLOAT64,
wantValue: 42.1,
},
{
name: "Key.Int32() correctly returns keys's internal int32 value",
value: k.Int32(42).Value,
wantType: core.INT32,
wantValue: int32(42),
},
{
name: "Key.Uint32() correctly returns keys's internal uint32 value",
value: k.Uint32(42).Value,
wantType: core.UINT32,
wantValue: uint32(42),
},
{
name: "Key.Float32() correctly returns keys's internal float32 value",
value: k.Float32(42.1).Value,
wantType: core.FLOAT32,
wantValue: float32(42.1),
},
{
name: "Key.String() correctly returns keys's internal string value",
value: k.String("foo").Value,
wantType: core.STRING,
wantValue: "foo",
},
{
name: "Key.Int() correctly returns keys's internal signed integral value",
value: k.Int(bli.intValue).Value,
wantType: bli.signedType,
wantValue: bli.signedValue,
},
{
name: "Key.Uint() correctly returns keys's internal unsigned integral value",
value: k.Uint(bli.uintValue).Value,
wantType: bli.unsignedType,
wantValue: bli.unsignedValue,
},
} {
t.Logf("Running test case %s", testcase.name)
if testcase.value.Type() != testcase.wantType {
t.Errorf("wrong value type, got %#v, expected %#v", testcase.value.Type(), testcase.wantType)
}
got := testcase.value.AsInterface()
if diff := cmp.Diff(testcase.wantValue, got); diff != "" {
t.Errorf("+got, -want: %s", diff)
}
}
}
type bitlessInfo struct {
intValue int
uintValue uint
signedType core.ValueType
unsignedType core.ValueType
signedValue interface{}
unsignedValue interface{}
}
func getBitlessInfo(i int) bitlessInfo {
if unsafe.Sizeof(i) == 4 {
return bitlessInfo{
intValue: i,
uintValue: uint(i),
signedType: core.INT32,
unsignedType: core.UINT32,
signedValue: int32(i),
unsignedValue: uint32(i),
}
}
return bitlessInfo{
intValue: i,
uintValue: uint(i),
signedType: core.INT64,
unsignedType: core.UINT64,
signedValue: int64(i),
unsignedValue: uint64(i),
}
}
func TestDefined(t *testing.T) {
for _, testcase := range []struct {
name string
k core.Key
want bool
}{
{
name: "Key.Defined() returns true when len(v.Name) != 0",
k: core.Key("foo"),
want: true,
},
{
name: "Key.Defined() returns false when len(v.Name) == 0",
k: core.Key(""),
want: false,
},
} {
t.Run(testcase.name, func(t *testing.T) {
//func (k core.Key) Defined() bool {
have := testcase.k.Defined()
if have != testcase.want {
t.Errorf("Want: %v, but have: %v", testcase.want, have)
}
})
}
}
func TestJSONValue(t *testing.T) {
var kvs interface{} = [2]core.KeyValue{
key.String("A", "B"),
key.Int64("C", 1),
}
data, err := json.Marshal(kvs)
require.NoError(t, err)
require.Equal(t,
`[{"Key":"A","Value":{"Type":"STRING","Value":"B"}},{"Key":"C","Value":{"Type":"INT64","Value":1}}]`,
string(data))
}
func TestEmit(t *testing.T) {
for _, testcase := range []struct {
name string
v core.Value
want string
}{
{
name: `test Key.Emit() can emit a string representing self.BOOL`,
v: core.Bool(true),
want: "true",
},
{
name: `test Key.Emit() can emit a string representing self.INT32`,
v: core.Int32(42),
want: "42",
},
{
name: `test Key.Emit() can emit a string representing self.INT64`,
v: core.Int64(42),
want: "42",
},
{
name: `test Key.Emit() can emit a string representing self.UINT32`,
v: core.Uint32(42),
want: "42",
},
{
name: `test Key.Emit() can emit a string representing self.UINT64`,
v: core.Uint64(42),
want: "42",
},
{
name: `test Key.Emit() can emit a string representing self.FLOAT32`,
v: core.Float32(42.1),
want: "42.1",
},
{
name: `test Key.Emit() can emit a string representing self.FLOAT64`,
v: core.Float64(42.1),
want: "42.1",
},
{
name: `test Key.Emit() can emit a string representing self.STRING`,
v: core.String("foo"),
want: "foo",
},
} {
t.Run(testcase.name, func(t *testing.T) {
//proto: func (v core.Value) Emit() string {
have := testcase.v.Emit()
if have != testcase.want {
t.Errorf("Want: %s, but have: %s", testcase.want, have)
}
})
}
}
func BenchmarkEmitBool(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
n := core.Bool(i%2 == 0)
_ = n.Emit()
}
}
func BenchmarkEmitInt64(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
n := core.Int64(int64(i))
_ = n.Emit()
}
}
func BenchmarkEmitUInt64(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
n := core.Uint64(uint64(i))
_ = n.Emit()
}
}
func BenchmarkEmitFloat64(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
n := core.Float64(float64(i))
_ = n.Emit()
}
}
func BenchmarkEmitFloat32(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
n := core.Float32(float32(i))
_ = n.Emit()
}
}

View File

@ -1,31 +0,0 @@
// Code generated by "stringer -type=ValueType"; DO NOT EDIT.
package core
import "strconv"
func _() {
// An "invalid array index" compiler error signifies that the constant values have changed.
// Re-run the stringer command to generate them again.
var x [1]struct{}
_ = x[INVALID-0]
_ = x[BOOL-1]
_ = x[INT32-2]
_ = x[INT64-3]
_ = x[UINT32-4]
_ = x[UINT64-5]
_ = x[FLOAT32-6]
_ = x[FLOAT64-7]
_ = x[STRING-8]
}
const _ValueType_name = "INVALIDBOOLINT32INT64UINT32UINT64FLOAT32FLOAT64STRING"
var _ValueType_index = [...]uint8{0, 7, 11, 16, 21, 27, 33, 40, 47, 53}
func (i ValueType) String() string {
if i < 0 || i >= ValueType(len(_ValueType_index)-1) {
return "ValueType(" + strconv.FormatInt(int64(i), 10) + ")"
}
return _ValueType_name[_ValueType_index[i]:_ValueType_index[i+1]]
}

View File

@ -17,7 +17,7 @@ package correlation
import (
"context"
"go.opentelemetry.io/otel/api/core"
"go.opentelemetry.io/otel/api/kv"
)
type correlationsType struct{}
@ -150,7 +150,7 @@ func ContextWithMap(ctx context.Context, m Map) context.Context {
// NewContext returns a context with the map from passed context
// updated with the passed key-value pairs.
func NewContext(ctx context.Context, keyvalues ...core.KeyValue) context.Context {
func NewContext(ctx context.Context, keyvalues ...kv.KeyValue) context.Context {
return ContextWithMap(ctx, MapFromContext(ctx).Apply(MapUpdate{
MultiKV: keyvalues,
}))

View File

@ -19,8 +19,7 @@ import (
"net/url"
"strings"
"go.opentelemetry.io/otel/api/core"
"go.opentelemetry.io/otel/api/key"
"go.opentelemetry.io/otel/api/kv"
"go.opentelemetry.io/otel/api/propagation"
)
@ -44,7 +43,7 @@ func (CorrelationContext) Inject(ctx context.Context, supplier propagation.HTTPS
correlationCtx := MapFromContext(ctx)
firstIter := true
var headerValueBuilder strings.Builder
correlationCtx.Foreach(func(kv core.KeyValue) bool {
correlationCtx.Foreach(func(kv kv.KeyValue) bool {
if !firstIter {
headerValueBuilder.WriteRune(',')
}
@ -68,7 +67,7 @@ func (CorrelationContext) Extract(ctx context.Context, supplier propagation.HTTP
}
contextValues := strings.Split(correlationContext, ",")
keyValues := make([]core.KeyValue, 0, len(contextValues))
keyValues := make([]kv.KeyValue, 0, len(contextValues))
for _, contextValue := range contextValues {
valueAndProps := strings.Split(contextValue, ";")
if len(valueAndProps) < 1 {
@ -98,7 +97,7 @@ func (CorrelationContext) Extract(ctx context.Context, supplier propagation.HTTP
trimmedValueWithProps.WriteString(prop)
}
keyValues = append(keyValues, key.New(trimmedName).String(trimmedValueWithProps.String()))
keyValues = append(keyValues, kv.Key(trimmedName).String(trimmedValueWithProps.String()))
}
return ContextWithMap(ctx, NewMap(MapUpdate{
MultiKV: keyValues,

View File

@ -20,11 +20,12 @@ import (
"strings"
"testing"
"go.opentelemetry.io/otel/api/kv/value"
"github.com/google/go-cmp/cmp"
"go.opentelemetry.io/otel/api/core"
"go.opentelemetry.io/otel/api/correlation"
"go.opentelemetry.io/otel/api/key"
"go.opentelemetry.io/otel/api/kv"
"go.opentelemetry.io/otel/api/propagation"
)
@ -33,54 +34,54 @@ func TestExtractValidDistributedContextFromHTTPReq(t *testing.T) {
tests := []struct {
name string
header string
wantKVs []core.KeyValue
wantKVs []kv.KeyValue
}{
{
name: "valid w3cHeader",
header: "key1=val1,key2=val2",
wantKVs: []core.KeyValue{
key.New("key1").String("val1"),
key.New("key2").String("val2"),
wantKVs: []kv.KeyValue{
kv.Key("key1").String("val1"),
kv.Key("key2").String("val2"),
},
},
{
name: "valid w3cHeader with spaces",
header: "key1 = val1, key2 =val2 ",
wantKVs: []core.KeyValue{
key.New("key1").String("val1"),
key.New("key2").String("val2"),
wantKVs: []kv.KeyValue{
kv.Key("key1").String("val1"),
kv.Key("key2").String("val2"),
},
},
{
name: "valid w3cHeader with properties",
header: "key1=val1,key2=val2;prop=1",
wantKVs: []core.KeyValue{
key.New("key1").String("val1"),
key.New("key2").String("val2;prop=1"),
wantKVs: []kv.KeyValue{
kv.Key("key1").String("val1"),
kv.Key("key2").String("val2;prop=1"),
},
},
{
name: "valid header with url-escaped comma",
header: "key1=val1,key2=val2%2Cval3",
wantKVs: []core.KeyValue{
key.New("key1").String("val1"),
key.New("key2").String("val2,val3"),
wantKVs: []kv.KeyValue{
kv.Key("key1").String("val1"),
kv.Key("key2").String("val2,val3"),
},
},
{
name: "valid header with an invalid header",
header: "key1=val1,key2=val2,a,val3",
wantKVs: []core.KeyValue{
key.New("key1").String("val1"),
key.New("key2").String("val2"),
wantKVs: []kv.KeyValue{
kv.Key("key1").String("val1"),
kv.Key("key2").String("val2"),
},
},
{
name: "valid header with no value",
header: "key1=,key2=val2",
wantKVs: []core.KeyValue{
key.New("key1").String(""),
key.New("key2").String("val2"),
wantKVs: []kv.KeyValue{
kv.Key("key1").String(""),
kv.Key("key2").String("val2"),
},
},
}
@ -102,9 +103,9 @@ func TestExtractValidDistributedContextFromHTTPReq(t *testing.T) {
)
}
totalDiff := ""
wantCorCtx.Foreach(func(kv core.KeyValue) bool {
val, _ := gotCorCtx.Value(kv.Key)
diff := cmp.Diff(kv, core.KeyValue{Key: kv.Key, Value: val}, cmp.AllowUnexported(core.Value{}))
wantCorCtx.Foreach(func(keyValue kv.KeyValue) bool {
val, _ := gotCorCtx.Value(keyValue.Key)
diff := cmp.Diff(keyValue, kv.KeyValue{Key: keyValue.Key, Value: val}, cmp.AllowUnexported(value.Value{}))
if diff != "" {
totalDiff += diff + "\n"
}
@ -149,38 +150,38 @@ func TestInjectCorrelationContextToHTTPReq(t *testing.T) {
props := propagation.New(propagation.WithInjectors(propagator))
tests := []struct {
name string
kvs []core.KeyValue
kvs []kv.KeyValue
wantInHeader []string
wantedLen int
}{
{
name: "two simple values",
kvs: []core.KeyValue{
key.New("key1").String("val1"),
key.New("key2").String("val2"),
kvs: []kv.KeyValue{
kv.Key("key1").String("val1"),
kv.Key("key2").String("val2"),
},
wantInHeader: []string{"key1=val1", "key2=val2"},
},
{
name: "two values with escaped chars",
kvs: []core.KeyValue{
key.New("key1").String("val1,val2"),
key.New("key2").String("val3=4"),
kvs: []kv.KeyValue{
kv.Key("key1").String("val1,val2"),
kv.Key("key2").String("val3=4"),
},
wantInHeader: []string{"key1=val1%2Cval2", "key2=val3%3D4"},
},
{
name: "values of non-string types",
kvs: []core.KeyValue{
key.New("key1").Bool(true),
key.New("key2").Int(123),
key.New("key3").Int64(123),
key.New("key4").Int32(123),
key.New("key5").Uint(123),
key.New("key6").Uint32(123),
key.New("key7").Uint64(123),
key.New("key8").Float64(123.567),
key.New("key9").Float32(123.567),
kvs: []kv.KeyValue{
kv.Key("key1").Bool(true),
kv.Key("key2").Int(123),
kv.Key("key3").Int64(123),
kv.Key("key4").Int32(123),
kv.Key("key5").Uint(123),
kv.Key("key6").Uint32(123),
kv.Key("key7").Uint64(123),
kv.Key("key8").Float64(123.567),
kv.Key("key9").Float32(123.567),
},
wantInHeader: []string{
"key1=true",

View File

@ -15,11 +15,12 @@
package correlation
import (
"go.opentelemetry.io/otel/api/core"
"go.opentelemetry.io/otel/api/kv"
"go.opentelemetry.io/otel/api/kv/value"
)
type rawMap map[core.Key]core.Value
type keySet map[core.Key]struct{}
type rawMap map[kv.Key]value.Value
type keySet map[kv.Key]struct{}
// Map is an immutable storage for correlations.
type Map struct {
@ -32,18 +33,18 @@ type MapUpdate struct {
// DropSingleK contains a single key to be dropped from
// correlations. Use this to avoid an overhead of a slice
// allocation if there is only one key to drop.
DropSingleK core.Key
DropSingleK kv.Key
// DropMultiK contains all the keys to be dropped from
// correlations.
DropMultiK []core.Key
DropMultiK []kv.Key
// SingleKV contains a single key-value pair to be added to
// correlations. Use this to avoid an overhead of a slice
// allocation if there is only one key-value pair to add.
SingleKV core.KeyValue
SingleKV kv.KeyValue
// MultiKV contains all the key-value pairs to be added to
// correlations.
MultiKV []core.KeyValue
MultiKV []kv.KeyValue
}
func newMap(raw rawMap) Map {
@ -101,7 +102,7 @@ func getModificationSets(update MapUpdate) (delSet, addSet keySet) {
deletionsCount++
}
if deletionsCount > 0 {
delSet = make(map[core.Key]struct{}, deletionsCount)
delSet = make(map[kv.Key]struct{}, deletionsCount)
for _, k := range update.DropMultiK {
delSet[k] = struct{}{}
}
@ -115,7 +116,7 @@ func getModificationSets(update MapUpdate) (delSet, addSet keySet) {
additionsCount++
}
if additionsCount > 0 {
addSet = make(map[core.Key]struct{}, additionsCount)
addSet = make(map[kv.Key]struct{}, additionsCount)
for _, k := range update.MultiKV {
addSet[k.Key] = struct{}{}
}
@ -146,14 +147,14 @@ func getNewMapSize(m rawMap, delSet, addSet keySet) int {
// Value gets a value from correlations map and returns a boolean
// value indicating whether the key exist in the map.
func (m Map) Value(k core.Key) (core.Value, bool) {
func (m Map) Value(k kv.Key) (value.Value, bool) {
value, ok := m.m[k]
return value, ok
}
// HasValue returns a boolean value indicating whether the key exist
// in the map.
func (m Map) HasValue(k core.Key) bool {
func (m Map) HasValue(k kv.Key) bool {
_, has := m.Value(k)
return has
}
@ -166,9 +167,9 @@ func (m Map) Len() int {
// Foreach calls a passed callback once on each key-value pair until
// all the key-value pairs of the map were iterated or the callback
// returns false, whichever happens first.
func (m Map) Foreach(f func(kv core.KeyValue) bool) {
func (m Map) Foreach(f func(kv kv.KeyValue) bool) {
for k, v := range m.m {
if !f(core.KeyValue{
if !f(kv.KeyValue{
Key: k,
Value: v,
}) {

View File

@ -18,15 +18,16 @@ import (
"fmt"
"testing"
"go.opentelemetry.io/otel/api/core"
"go.opentelemetry.io/otel/api/key"
"go.opentelemetry.io/otel/api/kv/value"
"go.opentelemetry.io/otel/api/kv"
)
type testCase struct {
name string
value MapUpdate
init []int
wantKVs []core.KeyValue
wantKVs []kv.KeyValue
}
func TestMap(t *testing.T) {
@ -47,7 +48,7 @@ func TestMap(t *testing.T) {
}
}
// test Foreach()
got.Foreach(func(kv core.KeyValue) bool {
got.Foreach(func(kv kv.KeyValue) bool {
for _, want := range testcase.wantKVs {
if kv == want {
return false
@ -85,193 +86,193 @@ func TestSizeComputation(t *testing.T) {
func getTestCases() []testCase {
return []testCase{
{
name: "New map with MultiKV",
value: MapUpdate{MultiKV: []core.KeyValue{
key.Int64("key1", 1),
key.String("key2", "val2")},
name: "map with MultiKV",
value: MapUpdate{MultiKV: []kv.KeyValue{
kv.Int64("key1", 1),
kv.String("key2", "val2")},
},
init: []int{},
wantKVs: []core.KeyValue{
key.Int64("key1", 1),
key.String("key2", "val2"),
wantKVs: []kv.KeyValue{
kv.Int64("key1", 1),
kv.String("key2", "val2"),
},
},
{
name: "New map with SingleKV",
value: MapUpdate{SingleKV: key.String("key1", "val1")},
name: "map with SingleKV",
value: MapUpdate{SingleKV: kv.String("key1", "val1")},
init: []int{},
wantKVs: []core.KeyValue{
key.String("key1", "val1"),
wantKVs: []kv.KeyValue{
kv.String("key1", "val1"),
},
},
{
name: "New map with both add fields",
value: MapUpdate{SingleKV: key.Int64("key1", 3),
MultiKV: []core.KeyValue{
key.String("key1", ""),
key.String("key2", "val2")},
name: "map with both add fields",
value: MapUpdate{SingleKV: kv.Int64("key1", 3),
MultiKV: []kv.KeyValue{
kv.String("key1", ""),
kv.String("key2", "val2")},
},
init: []int{},
wantKVs: []core.KeyValue{
key.String("key1", ""),
key.String("key2", "val2"),
wantKVs: []kv.KeyValue{
kv.String("key1", ""),
kv.String("key2", "val2"),
},
},
{
name: "New map with empty MapUpdate",
name: "map with empty MapUpdate",
value: MapUpdate{},
init: []int{},
wantKVs: []core.KeyValue{},
wantKVs: []kv.KeyValue{},
},
{
name: "New map with DropSingleK",
value: MapUpdate{DropSingleK: core.Key("key1")},
name: "map with DropSingleK",
value: MapUpdate{DropSingleK: kv.Key("key1")},
init: []int{},
wantKVs: []core.KeyValue{},
wantKVs: []kv.KeyValue{},
},
{
name: "New map with DropMultiK",
value: MapUpdate{DropMultiK: []core.Key{
core.Key("key1"), core.Key("key2"),
name: "map with DropMultiK",
value: MapUpdate{DropMultiK: []kv.Key{
kv.Key("key1"), kv.Key("key2"),
}},
init: []int{},
wantKVs: []core.KeyValue{},
wantKVs: []kv.KeyValue{},
},
{
name: "New map with both drop fields",
name: "map with both drop fields",
value: MapUpdate{
DropSingleK: core.Key("key1"),
DropMultiK: []core.Key{
core.Key("key1"),
core.Key("key2"),
DropSingleK: kv.Key("key1"),
DropMultiK: []kv.Key{
kv.Key("key1"),
kv.Key("key2"),
},
},
init: []int{},
wantKVs: []core.KeyValue{},
wantKVs: []kv.KeyValue{},
},
{
name: "New map with all fields",
name: "map with all fields",
value: MapUpdate{
DropSingleK: core.Key("key1"),
DropMultiK: []core.Key{
core.Key("key1"),
core.Key("key2"),
DropSingleK: kv.Key("key1"),
DropMultiK: []kv.Key{
kv.Key("key1"),
kv.Key("key2"),
},
SingleKV: key.String("key4", "val4"),
MultiKV: []core.KeyValue{
key.String("key1", ""),
key.String("key2", "val2"),
key.String("key3", "val3"),
SingleKV: kv.String("key4", "val4"),
MultiKV: []kv.KeyValue{
kv.String("key1", ""),
kv.String("key2", "val2"),
kv.String("key3", "val3"),
},
},
init: []int{},
wantKVs: []core.KeyValue{
key.String("key1", ""),
key.String("key2", "val2"),
key.String("key3", "val3"),
key.String("key4", "val4"),
wantKVs: []kv.KeyValue{
kv.String("key1", ""),
kv.String("key2", "val2"),
kv.String("key3", "val3"),
kv.String("key4", "val4"),
},
},
{
name: "Existing map with MultiKV",
value: MapUpdate{MultiKV: []core.KeyValue{
key.Int64("key1", 1),
key.String("key2", "val2")},
value: MapUpdate{MultiKV: []kv.KeyValue{
kv.Int64("key1", 1),
kv.String("key2", "val2")},
},
init: []int{5},
wantKVs: []core.KeyValue{
key.Int64("key1", 1),
key.String("key2", "val2"),
key.Int("key5", 5),
wantKVs: []kv.KeyValue{
kv.Int64("key1", 1),
kv.String("key2", "val2"),
kv.Int("key5", 5),
},
},
{
name: "Existing map with SingleKV",
value: MapUpdate{SingleKV: key.String("key1", "val1")},
value: MapUpdate{SingleKV: kv.String("key1", "val1")},
init: []int{5},
wantKVs: []core.KeyValue{
key.String("key1", "val1"),
key.Int("key5", 5),
wantKVs: []kv.KeyValue{
kv.String("key1", "val1"),
kv.Int("key5", 5),
},
},
{
name: "Existing map with both add fields",
value: MapUpdate{SingleKV: key.Int64("key1", 3),
MultiKV: []core.KeyValue{
key.String("key1", ""),
key.String("key2", "val2")},
value: MapUpdate{SingleKV: kv.Int64("key1", 3),
MultiKV: []kv.KeyValue{
kv.String("key1", ""),
kv.String("key2", "val2")},
},
init: []int{5},
wantKVs: []core.KeyValue{
key.String("key1", ""),
key.String("key2", "val2"),
key.Int("key5", 5),
wantKVs: []kv.KeyValue{
kv.String("key1", ""),
kv.String("key2", "val2"),
kv.Int("key5", 5),
},
},
{
name: "Existing map with empty MapUpdate",
value: MapUpdate{},
init: []int{5},
wantKVs: []core.KeyValue{
key.Int("key5", 5),
wantKVs: []kv.KeyValue{
kv.Int("key5", 5),
},
},
{
name: "Existing map with DropSingleK",
value: MapUpdate{DropSingleK: core.Key("key1")},
value: MapUpdate{DropSingleK: kv.Key("key1")},
init: []int{1, 5},
wantKVs: []core.KeyValue{
key.Int("key5", 5),
wantKVs: []kv.KeyValue{
kv.Int("key5", 5),
},
},
{
name: "Existing map with DropMultiK",
value: MapUpdate{DropMultiK: []core.Key{
core.Key("key1"), core.Key("key2"),
value: MapUpdate{DropMultiK: []kv.Key{
kv.Key("key1"), kv.Key("key2"),
}},
init: []int{1, 5},
wantKVs: []core.KeyValue{
key.Int("key5", 5),
wantKVs: []kv.KeyValue{
kv.Int("key5", 5),
},
},
{
name: "Existing map with both drop fields",
value: MapUpdate{
DropSingleK: core.Key("key1"),
DropMultiK: []core.Key{
core.Key("key1"),
core.Key("key2"),
DropSingleK: kv.Key("key1"),
DropMultiK: []kv.Key{
kv.Key("key1"),
kv.Key("key2"),
},
},
init: []int{1, 2, 5},
wantKVs: []core.KeyValue{
key.Int("key5", 5),
wantKVs: []kv.KeyValue{
kv.Int("key5", 5),
},
},
{
name: "Existing map with all the fields",
value: MapUpdate{
DropSingleK: core.Key("key1"),
DropMultiK: []core.Key{
core.Key("key1"),
core.Key("key2"),
core.Key("key5"),
core.Key("key6"),
DropSingleK: kv.Key("key1"),
DropMultiK: []kv.Key{
kv.Key("key1"),
kv.Key("key2"),
kv.Key("key5"),
kv.Key("key6"),
},
SingleKV: key.String("key4", "val4"),
MultiKV: []core.KeyValue{
key.String("key1", ""),
key.String("key2", "val2"),
key.String("key3", "val3"),
SingleKV: kv.String("key4", "val4"),
MultiKV: []kv.KeyValue{
kv.String("key1", ""),
kv.String("key2", "val2"),
kv.String("key3", "val3"),
},
},
init: []int{5, 6, 7},
wantKVs: []core.KeyValue{
key.String("key1", ""),
key.String("key2", "val2"),
key.String("key3", "val3"),
key.String("key4", "val4"),
key.Int("key7", 7),
wantKVs: []kv.KeyValue{
kv.String("key1", ""),
kv.String("key2", "val2"),
kv.String("key3", "val3"),
kv.String("key4", "val4"),
kv.Int("key7", 7),
},
},
}
@ -280,7 +281,7 @@ func getTestCases() []testCase {
func makeTestMap(ints []int) Map {
r := make(rawMap, len(ints))
for _, v := range ints {
r[core.Key(fmt.Sprintf("key%d", v))] = core.Int(v)
r[kv.Key(fmt.Sprintf("key%d", v))] = value.Int(v)
}
return newMap(r)
}

View File

@ -19,10 +19,9 @@ import (
"strings"
"testing"
"go.opentelemetry.io/otel/api/core"
"go.opentelemetry.io/otel/api/global"
"go.opentelemetry.io/otel/api/global/internal"
"go.opentelemetry.io/otel/api/key"
"go.opentelemetry.io/otel/api/kv"
"go.opentelemetry.io/otel/api/metric"
"go.opentelemetry.io/otel/api/trace"
export "go.opentelemetry.io/otel/sdk/export/metric"
@ -91,7 +90,7 @@ func BenchmarkGlobalInt64CounterAddNoSDK(b *testing.B) {
internal.ResetForTest()
ctx := context.Background()
sdk := global.Meter("test")
labs := []core.KeyValue{key.String("A", "B")}
labs := []kv.KeyValue{kv.String("A", "B")}
cnt := Must(sdk).NewInt64Counter("int64.counter")
b.ResetTimer()
@ -110,7 +109,7 @@ func BenchmarkGlobalInt64CounterAddWithSDK(b *testing.B) {
global.SetMeterProvider(fix)
labs := []core.KeyValue{key.String("A", "B")}
labs := []kv.KeyValue{kv.String("A", "B")}
cnt := Must(sdk).NewInt64Counter("int64.counter")
b.ResetTimer()

View File

@ -20,7 +20,7 @@ import (
"sync/atomic"
"unsafe"
"go.opentelemetry.io/otel/api/core"
"go.opentelemetry.io/otel/api/kv"
"go.opentelemetry.io/otel/api/metric"
"go.opentelemetry.io/otel/api/metric/registry"
)
@ -85,7 +85,7 @@ type asyncImpl struct {
instrument
callback func(func(metric.Number, []core.KeyValue))
runner metric.AsyncRunner
}
// SyncImpler is implemented by all of the sync metric
@ -104,7 +104,7 @@ type syncHandle struct {
delegate unsafe.Pointer // (*metric.HandleImpl)
inst *syncImpl
labels []core.KeyValue
labels []kv.KeyValue
initialize sync.Once
}
@ -219,7 +219,7 @@ func (inst *syncImpl) Implementation() interface{} {
return inst
}
func (inst *syncImpl) Bind(labels []core.KeyValue) metric.BoundSyncImpl {
func (inst *syncImpl) Bind(labels []kv.KeyValue) metric.BoundSyncImpl {
if implPtr := (*metric.SyncImpl)(atomic.LoadPointer(&inst.delegate)); implPtr != nil {
return (*implPtr).Bind(labels)
}
@ -245,21 +245,21 @@ func (bound *syncHandle) Unbind() {
func (m *meterImpl) NewAsyncInstrument(
desc metric.Descriptor,
callback func(func(metric.Number, []core.KeyValue)),
runner metric.AsyncRunner,
) (metric.AsyncImpl, error) {
m.lock.Lock()
defer m.lock.Unlock()
if meterPtr := (*metric.MeterImpl)(atomic.LoadPointer(&m.delegate)); meterPtr != nil {
return (*meterPtr).NewAsyncInstrument(desc, callback)
return (*meterPtr).NewAsyncInstrument(desc, runner)
}
inst := &asyncImpl{
instrument: instrument{
descriptor: desc,
},
callback: callback,
runner: runner,
}
m.asyncInsts = append(m.asyncInsts, inst)
return inst, nil
@ -276,7 +276,7 @@ func (obs *asyncImpl) setDelegate(d metric.MeterImpl) {
implPtr := new(metric.AsyncImpl)
var err error
*implPtr, err = d.NewAsyncInstrument(obs.descriptor, obs.callback)
*implPtr, err = d.NewAsyncInstrument(obs.descriptor, obs.runner)
if err != nil {
// TODO: There is no standard way to deliver this error to the user.
@ -291,13 +291,13 @@ func (obs *asyncImpl) setDelegate(d metric.MeterImpl) {
// Metric updates
func (m *meterImpl) RecordBatch(ctx context.Context, labels []core.KeyValue, measurements ...metric.Measurement) {
func (m *meterImpl) RecordBatch(ctx context.Context, labels []kv.KeyValue, measurements ...metric.Measurement) {
if delegatePtr := (*metric.MeterImpl)(atomic.LoadPointer(&m.delegate)); delegatePtr != nil {
(*delegatePtr).RecordBatch(ctx, labels, measurements...)
}
}
func (inst *syncImpl) RecordOne(ctx context.Context, number metric.Number, labels []core.KeyValue) {
func (inst *syncImpl) RecordOne(ctx context.Context, number metric.Number, labels []kv.KeyValue) {
if instPtr := (*metric.SyncImpl)(atomic.LoadPointer(&inst.delegate)); instPtr != nil {
(*instPtr).RecordOne(ctx, number, labels)
}

View File

@ -22,12 +22,13 @@ import (
"io/ioutil"
"testing"
"go.opentelemetry.io/otel/api/kv/value"
"github.com/stretchr/testify/require"
"go.opentelemetry.io/otel/api/core"
"go.opentelemetry.io/otel/api/global"
"go.opentelemetry.io/otel/api/global/internal"
"go.opentelemetry.io/otel/api/key"
"go.opentelemetry.io/otel/api/kv"
"go.opentelemetry.io/otel/api/metric"
"go.opentelemetry.io/otel/exporters/metric/stdout"
metrictest "go.opentelemetry.io/otel/internal/metric"
@ -37,7 +38,7 @@ import (
type measured struct {
Name string
LibraryName string
Labels map[core.Key]core.Value
Labels map[kv.Key]value.Value
Number metric.Number
}
@ -56,8 +57,8 @@ func asStructs(batches []metrictest.Batch) []measured {
return r
}
func asMap(kvs ...core.KeyValue) map[core.Key]core.Value {
m := map[core.Key]core.Value{}
func asMap(kvs ...kv.KeyValue) map[kv.Key]value.Value {
m := map[kv.Key]value.Value{}
for _, kv := range kvs {
m[kv.Key] = kv.Value
}
@ -73,9 +74,9 @@ func TestDirect(t *testing.T) {
ctx := context.Background()
meter1 := global.Meter("test1")
meter2 := global.Meter("test2")
labels1 := []core.KeyValue{key.String("A", "B")}
labels2 := []core.KeyValue{key.String("C", "D")}
labels3 := []core.KeyValue{key.String("E", "F")}
labels1 := []kv.KeyValue{kv.String("A", "B")}
labels2 := []kv.KeyValue{kv.String("C", "D")}
labels3 := []kv.KeyValue{kv.String("E", "F")}
counter := Must(meter1).NewInt64Counter("test.counter")
counter.Add(ctx, 1, labels1...)
@ -166,7 +167,7 @@ func TestBound(t *testing.T) {
// vs. the above, to cover all the instruments.
ctx := context.Background()
glob := global.Meter("test")
labels1 := []core.KeyValue{key.String("A", "B")}
labels1 := []kv.KeyValue{kv.String("A", "B")}
counter := Must(glob).NewFloat64Counter("test.counter")
boundC := counter.Bind(labels1...)
@ -210,7 +211,7 @@ func TestUnbind(t *testing.T) {
internal.ResetForTest()
glob := global.Meter("test")
labels1 := []core.KeyValue{key.String("A", "B")}
labels1 := []kv.KeyValue{kv.String("A", "B")}
counter := Must(glob).NewFloat64Counter("test.counter")
boundC := counter.Bind(labels1...)
@ -227,7 +228,7 @@ func TestDefaultSDK(t *testing.T) {
ctx := context.Background()
meter1 := global.Meter("builtin")
labels1 := []core.KeyValue{key.String("A", "B")}
labels1 := []kv.KeyValue{kv.String("A", "B")}
counter := Must(meter1).NewInt64Counter("test.builtin")
counter.Add(ctx, 1, labels1...)

View File

@ -12,14 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
package key_test
package kv_test
import (
"context"
"testing"
"go.opentelemetry.io/otel/api/kv"
"go.opentelemetry.io/otel/api/global"
"go.opentelemetry.io/otel/api/key"
"go.opentelemetry.io/otel/api/trace"
sdktrace "go.opentelemetry.io/otel/sdk/trace"
)
@ -35,7 +36,7 @@ func getSpan() trace.Span {
func BenchmarkKeyInfer(b *testing.B) {
for i := 0; i < b.N; i++ {
key.Infer("Attr", int(256))
kv.Infer("Attr", int(256))
}
}
@ -46,7 +47,7 @@ func BenchmarkMultiNoKeyInference(b *testing.B) {
b.ResetTimer()
for i := 0; i < b.N; i++ {
sp.SetAttributes(key.Int("Attr", 1))
sp.SetAttributes(kv.Int("Attr", 1))
}
}
@ -57,7 +58,7 @@ func BenchmarkMultiWithKeyInference(b *testing.B) {
b.ResetTimer()
for i := 0; i < b.N; i++ {
sp.SetAttributes(key.Infer("Attr", 1))
sp.SetAttributes(kv.Infer("Attr", 1))
}
}

View File

@ -12,6 +12,5 @@
// See the License for the specific language governing permissions and
// limitations under the License.
// This package provides convenience functions for creating keys and
// key-value pairs.
package key // import "go.opentelemetry.io/otel/api/key"
// package kv provides basic key and value types.
package kv // import "go.opentelemetry.io/otel/api/kv"

160
api/kv/key.go Normal file
View File

@ -0,0 +1,160 @@
// 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 kv
import (
"go.opentelemetry.io/otel/api/kv/value"
)
// Key represents the key part in key-value pairs. It's a string. The
// allowed character set in the key depends on the use of the key.
type Key string
// Bool creates a KeyValue instance with a BOOL Value.
//
// If creating both key and a bool value at the same time, then
// instead of calling kv.Key(name).Bool(value) consider using a
// convenience function provided by the api/key package -
// key.Bool(name, value).
func (k Key) Bool(v bool) KeyValue {
return KeyValue{
Key: k,
Value: value.Bool(v),
}
}
// Int64 creates a KeyValue instance with an INT64 Value.
//
// If creating both key and an int64 value at the same time, then
// instead of calling kv.Key(name).Int64(value) consider using a
// convenience function provided by the api/key package -
// key.Int64(name, value).
func (k Key) Int64(v int64) KeyValue {
return KeyValue{
Key: k,
Value: value.Int64(v),
}
}
// Uint64 creates a KeyValue instance with a UINT64 Value.
//
// If creating both key and a uint64 value at the same time, then
// instead of calling kv.Key(name).Uint64(value) consider using a
// convenience function provided by the api/key package -
// key.Uint64(name, value).
func (k Key) Uint64(v uint64) KeyValue {
return KeyValue{
Key: k,
Value: value.Uint64(v),
}
}
// Float64 creates a KeyValue instance with a FLOAT64 Value.
//
// If creating both key and a float64 value at the same time, then
// instead of calling kv.Key(name).Float64(value) consider using a
// convenience function provided by the api/key package -
// key.Float64(name, value).
func (k Key) Float64(v float64) KeyValue {
return KeyValue{
Key: k,
Value: value.Float64(v),
}
}
// Int32 creates a KeyValue instance with an INT32 Value.
//
// If creating both key and an int32 value at the same time, then
// instead of calling kv.Key(name).Int32(value) consider using a
// convenience function provided by the api/key package -
// key.Int32(name, value).
func (k Key) Int32(v int32) KeyValue {
return KeyValue{
Key: k,
Value: value.Int32(v),
}
}
// Uint32 creates a KeyValue instance with a UINT32 Value.
//
// If creating both key and a uint32 value at the same time, then
// instead of calling kv.Key(name).Uint32(value) consider using a
// convenience function provided by the api/key package -
// key.Uint32(name, value).
func (k Key) Uint32(v uint32) KeyValue {
return KeyValue{
Key: k,
Value: value.Uint32(v),
}
}
// Float32 creates a KeyValue instance with a FLOAT32 Value.
//
// If creating both key and a float32 value at the same time, then
// instead of calling kv.Key(name).Float32(value) consider using a
// convenience function provided by the api/key package -
// key.Float32(name, value).
func (k Key) Float32(v float32) KeyValue {
return KeyValue{
Key: k,
Value: value.Float32(v),
}
}
// String creates a KeyValue instance with a STRING Value.
//
// If creating both key and a string value at the same time, then
// instead of calling kv.Key(name).String(value) consider using a
// convenience function provided by the api/key package -
// key.String(name, value).
func (k Key) String(v string) KeyValue {
return KeyValue{
Key: k,
Value: value.String(v),
}
}
// Int creates a KeyValue instance with either an INT32 or an INT64
// Value, depending on whether the int type is 32 or 64 bits wide.
//
// If creating both key and an int value at the same time, then
// instead of calling kv.Key(name).Int(value) consider using a
// convenience function provided by the api/key package -
// key.Int(name, value).
func (k Key) Int(v int) KeyValue {
return KeyValue{
Key: k,
Value: value.Int(v),
}
}
// Uint creates a KeyValue instance with either a UINT32 or a UINT64
// Value, depending on whether the uint type is 32 or 64 bits wide.
//
// If creating both key and a uint value at the same time, then
// instead of calling kv.Key(name).Uint(value) consider using a
// convenience function provided by the api/key package -
// key.Uint(name, value).
func (k Key) Uint(v uint) KeyValue {
return KeyValue{
Key: k,
Value: value.Uint(v),
}
}
// Defined returns true for non-empty keys.
func (k Key) Defined() bool {
return len(k) != 0
}

163
api/kv/key_test.go Normal file
View File

@ -0,0 +1,163 @@
// 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 kv_test
import (
"encoding/json"
"testing"
"go.opentelemetry.io/otel/api/kv"
"github.com/stretchr/testify/require"
"go.opentelemetry.io/otel/api/kv/value"
)
func TestDefined(t *testing.T) {
for _, testcase := range []struct {
name string
k kv.Key
want bool
}{
{
name: "Key.Defined() returns true when len(v.Name) != 0",
k: kv.Key("foo"),
want: true,
},
{
name: "Key.Defined() returns false when len(v.Name) == 0",
k: kv.Key(""),
want: false,
},
} {
t.Run(testcase.name, func(t *testing.T) {
//func (k kv.Key) Defined() bool {
have := testcase.k.Defined()
if have != testcase.want {
t.Errorf("Want: %v, but have: %v", testcase.want, have)
}
})
}
}
func TestJSONValue(t *testing.T) {
var kvs interface{} = [2]kv.KeyValue{
kv.String("A", "B"),
kv.Int64("C", 1),
}
data, err := json.Marshal(kvs)
require.NoError(t, err)
require.Equal(t,
`[{"Key":"A","Value":{"Type":"STRING","Value":"B"}},{"Key":"C","Value":{"Type":"INT64","Value":1}}]`,
string(data))
}
func TestEmit(t *testing.T) {
for _, testcase := range []struct {
name string
v value.Value
want string
}{
{
name: `test Key.Emit() can emit a string representing self.BOOL`,
v: value.Bool(true),
want: "true",
},
{
name: `test Key.Emit() can emit a string representing self.INT32`,
v: value.Int32(42),
want: "42",
},
{
name: `test Key.Emit() can emit a string representing self.INT64`,
v: value.Int64(42),
want: "42",
},
{
name: `test Key.Emit() can emit a string representing self.UINT32`,
v: value.Uint32(42),
want: "42",
},
{
name: `test Key.Emit() can emit a string representing self.UINT64`,
v: value.Uint64(42),
want: "42",
},
{
name: `test Key.Emit() can emit a string representing self.FLOAT32`,
v: value.Float32(42.1),
want: "42.1",
},
{
name: `test Key.Emit() can emit a string representing self.FLOAT64`,
v: value.Float64(42.1),
want: "42.1",
},
{
name: `test Key.Emit() can emit a string representing self.STRING`,
v: value.String("foo"),
want: "foo",
},
} {
t.Run(testcase.name, func(t *testing.T) {
//proto: func (v kv.Value) Emit() string {
have := testcase.v.Emit()
if have != testcase.want {
t.Errorf("Want: %s, but have: %s", testcase.want, have)
}
})
}
}
func BenchmarkEmitBool(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
n := value.Bool(i%2 == 0)
_ = n.Emit()
}
}
func BenchmarkEmitInt64(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
n := value.Int64(int64(i))
_ = n.Emit()
}
}
func BenchmarkEmitUInt64(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
n := value.Uint64(uint64(i))
_ = n.Emit()
}
}
func BenchmarkEmitFloat64(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
n := value.Float64(float64(i))
_ = n.Emit()
}
}
func BenchmarkEmitFloat32(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
n := value.Float32(float32(i))
_ = n.Emit()
}
}

View File

@ -12,91 +12,92 @@
// See the License for the specific language governing permissions and
// limitations under the License.
package key
package kv
import (
"fmt"
"reflect"
"go.opentelemetry.io/otel/api/core"
"go.opentelemetry.io/otel/api/kv/value"
)
// New creates a new key with a passed name.
func New(name string) core.Key {
return core.Key(name)
// KeyValue holds a key and value pair.
type KeyValue struct {
Key Key
Value value.Value
}
// Bool creates a new key-value pair with a passed name and a bool
// value.
func Bool(k string, v bool) core.KeyValue {
return New(k).Bool(v)
func Bool(k string, v bool) KeyValue {
return Key(k).Bool(v)
}
// Int64 creates a new key-value pair with a passed name and an int64
// value.
func Int64(k string, v int64) core.KeyValue {
return New(k).Int64(v)
func Int64(k string, v int64) KeyValue {
return Key(k).Int64(v)
}
// Uint64 creates a new key-value pair with a passed name and a uint64
// value.
func Uint64(k string, v uint64) core.KeyValue {
return New(k).Uint64(v)
func Uint64(k string, v uint64) KeyValue {
return Key(k).Uint64(v)
}
// Float64 creates a new key-value pair with a passed name and a float64
// value.
func Float64(k string, v float64) core.KeyValue {
return New(k).Float64(v)
func Float64(k string, v float64) KeyValue {
return Key(k).Float64(v)
}
// Int32 creates a new key-value pair with a passed name and an int32
// value.
func Int32(k string, v int32) core.KeyValue {
return New(k).Int32(v)
func Int32(k string, v int32) KeyValue {
return Key(k).Int32(v)
}
// Uint32 creates a new key-value pair with a passed name and a uint32
// value.
func Uint32(k string, v uint32) core.KeyValue {
return New(k).Uint32(v)
func Uint32(k string, v uint32) KeyValue {
return Key(k).Uint32(v)
}
// Float32 creates a new key-value pair with a passed name and a float32
// value.
func Float32(k string, v float32) core.KeyValue {
return New(k).Float32(v)
func Float32(k string, v float32) KeyValue {
return Key(k).Float32(v)
}
// String creates a new key-value pair with a passed name and a string
// value.
func String(k, v string) core.KeyValue {
return New(k).String(v)
func String(k, v string) KeyValue {
return Key(k).String(v)
}
// Stringer creates a new key-value pair with a passed name and a string
// value generated by the passed Stringer interface.
func Stringer(k string, v fmt.Stringer) core.KeyValue {
return New(k).String(v.String())
func Stringer(k string, v fmt.Stringer) KeyValue {
return Key(k).String(v.String())
}
// Int creates a new key-value pair instance with a passed name and
// either an int32 or an int64 value, depending on whether the int
// type is 32 or 64 bits wide.
func Int(k string, v int) core.KeyValue {
return New(k).Int(v)
func Int(k string, v int) KeyValue {
return Key(k).Int(v)
}
// Uint creates a new key-value pair instance with a passed name and
// either an uint32 or an uint64 value, depending on whether the uint
// type is 32 or 64 bits wide.
func Uint(k string, v uint) core.KeyValue {
return New(k).Uint(v)
func Uint(k string, v uint) KeyValue {
return Key(k).Uint(v)
}
// Infer creates a new key-value pair instance with a passed name and
// automatic type inference. This is slower, and not type-safe.
func Infer(k string, value interface{}) core.KeyValue {
func Infer(k string, value interface{}) KeyValue {
if value == nil {
return String(k, "<nil>")
}

View File

@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
package key_test
package kv_test
import (
"strings"
@ -20,101 +20,101 @@ import (
"github.com/google/go-cmp/cmp"
"go.opentelemetry.io/otel/api/core"
"go.opentelemetry.io/otel/api/key"
"go.opentelemetry.io/otel/api/kv"
"go.opentelemetry.io/otel/api/kv/value"
)
func TestKeyValueConstructors(t *testing.T) {
tt := []struct {
name string
actual core.KeyValue
expected core.KeyValue
actual kv.KeyValue
expected kv.KeyValue
}{
{
name: "Bool",
actual: key.Bool("k1", true),
expected: core.KeyValue{
actual: kv.Bool("k1", true),
expected: kv.KeyValue{
Key: "k1",
Value: core.Bool(true),
Value: value.Bool(true),
},
},
{
name: "Int64",
actual: key.Int64("k1", 123),
expected: core.KeyValue{
actual: kv.Int64("k1", 123),
expected: kv.KeyValue{
Key: "k1",
Value: core.Int64(123),
Value: value.Int64(123),
},
},
{
name: "Uint64",
actual: key.Uint64("k1", 1),
expected: core.KeyValue{
actual: kv.Uint64("k1", 1),
expected: kv.KeyValue{
Key: "k1",
Value: core.Uint64(1),
Value: value.Uint64(1),
},
},
{
name: "Float64",
actual: key.Float64("k1", 123.5),
expected: core.KeyValue{
actual: kv.Float64("k1", 123.5),
expected: kv.KeyValue{
Key: "k1",
Value: core.Float64(123.5),
Value: value.Float64(123.5),
},
},
{
name: "Int32",
actual: key.Int32("k1", 123),
expected: core.KeyValue{
actual: kv.Int32("k1", 123),
expected: kv.KeyValue{
Key: "k1",
Value: core.Int32(123),
Value: value.Int32(123),
},
},
{
name: "Uint32",
actual: key.Uint32("k1", 123),
expected: core.KeyValue{
actual: kv.Uint32("k1", 123),
expected: kv.KeyValue{
Key: "k1",
Value: core.Uint32(123),
Value: value.Uint32(123),
},
},
{
name: "Float32",
actual: key.Float32("k1", 123.5),
expected: core.KeyValue{
actual: kv.Float32("k1", 123.5),
expected: kv.KeyValue{
Key: "k1",
Value: core.Float32(123.5),
Value: value.Float32(123.5),
},
},
{
name: "String",
actual: key.String("k1", "123.5"),
expected: core.KeyValue{
actual: kv.String("k1", "123.5"),
expected: kv.KeyValue{
Key: "k1",
Value: core.String("123.5"),
Value: value.String("123.5"),
},
},
{
name: "Int",
actual: key.Int("k1", 123),
expected: core.KeyValue{
actual: kv.Int("k1", 123),
expected: kv.KeyValue{
Key: "k1",
Value: core.Int(123),
Value: value.Int(123),
},
},
{
name: "Uint",
actual: key.Uint("k1", 123),
expected: core.KeyValue{
actual: kv.Uint("k1", 123),
expected: kv.KeyValue{
Key: "k1",
Value: core.Uint(123),
Value: value.Uint(123),
},
},
}
for _, test := range tt {
t.Run(test.name, func(t *testing.T) {
if diff := cmp.Diff(test.actual, test.expected, cmp.AllowUnexported(core.Value{})); diff != "" {
if diff := cmp.Diff(test.actual, test.expected, cmp.AllowUnexported(value.Value{})); diff != "" {
t.Fatal(diff)
}
})
@ -127,76 +127,76 @@ func TestInfer(t *testing.T) {
for _, testcase := range []struct {
key string
value interface{}
wantType core.ValueType
wantType value.Type
wantValue interface{}
}{
{
key: "bool type inferred",
value: true,
wantType: core.BOOL,
wantType: value.BOOL,
wantValue: true,
},
{
key: "int64 type inferred",
value: int64(42),
wantType: core.INT64,
wantType: value.INT64,
wantValue: int64(42),
},
{
key: "uint64 type inferred",
value: uint64(42),
wantType: core.UINT64,
wantType: value.UINT64,
wantValue: uint64(42),
},
{
key: "float64 type inferred",
value: float64(42.1),
wantType: core.FLOAT64,
wantType: value.FLOAT64,
wantValue: 42.1,
},
{
key: "int32 type inferred",
value: int32(42),
wantType: core.INT32,
wantType: value.INT32,
wantValue: int32(42),
},
{
key: "uint32 type inferred",
value: uint32(42),
wantType: core.UINT32,
wantType: value.UINT32,
wantValue: uint32(42),
},
{
key: "float32 type inferred",
value: float32(42.1),
wantType: core.FLOAT32,
wantType: value.FLOAT32,
wantValue: float32(42.1),
},
{
key: "string type inferred",
value: "foo",
wantType: core.STRING,
wantType: value.STRING,
wantValue: "foo",
},
{
key: "stringer type inferred",
value: builder,
wantType: core.STRING,
wantType: value.STRING,
wantValue: "foo",
},
{
key: "unknown value serialized as %v",
value: nil,
wantType: core.STRING,
wantType: value.STRING,
wantValue: "<nil>",
},
} {
t.Logf("Running test case %s", testcase.key)
kv := key.Infer(testcase.key, testcase.value)
if kv.Value.Type() != testcase.wantType {
t.Errorf("wrong value type, got %#v, expected %#v", kv.Value.Type(), testcase.wantType)
keyValue := kv.Infer(testcase.key, testcase.value)
if keyValue.Value.Type() != testcase.wantType {
t.Errorf("wrong value type, got %#v, expected %#v", keyValue.Value.Type(), testcase.wantType)
}
got := kv.Value.AsInterface()
got := keyValue.Value.AsInterface()
if diff := cmp.Diff(testcase.wantValue, got); diff != "" {
t.Errorf("+got, -want: %s", diff)
}

View File

@ -0,0 +1,31 @@
// Code generated by "stringer -type=Type"; DO NOT EDIT.
package value
import "strconv"
func _() {
// An "invalid array index" compiler error signifies that the constant values have changed.
// Re-run the stringer command to generate them again.
var x [1]struct{}
_ = x[INVALID-0]
_ = x[BOOL-1]
_ = x[INT32-2]
_ = x[INT64-3]
_ = x[UINT32-4]
_ = x[UINT64-5]
_ = x[FLOAT32-6]
_ = x[FLOAT64-7]
_ = x[STRING-8]
}
const _Type_name = "INVALIDBOOLINT32INT64UINT32UINT64FLOAT32FLOAT64STRING"
var _Type_index = [...]uint8{0, 7, 11, 16, 21, 27, 33, 40, 47, 53}
func (i Type) String() string {
if i < 0 || i >= Type(len(_Type_index)-1) {
return "Type(" + strconv.FormatInt(int64(i), 10) + ")"
}
return _Type_name[_Type_index[i]:_Type_index[i+1]]
}

244
api/kv/value/value.go Normal file
View File

@ -0,0 +1,244 @@
// 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 value
import (
"encoding/json"
"fmt"
"strconv"
"unsafe"
"go.opentelemetry.io/otel/api/internal"
)
//go:generate stringer -type=Type
// Type describes the type of the data Value holds.
type Type int
// Value represents the value part in key-value pairs.
type Value struct {
vtype Type
numeric uint64
stringly string
// TODO Lazy value type?
}
const (
INVALID Type = iota // No value.
BOOL // Boolean value, use AsBool() to get it.
INT32 // 32 bit signed integral value, use AsInt32() to get it.
INT64 // 64 bit signed integral value, use AsInt64() to get it.
UINT32 // 32 bit unsigned integral value, use AsUint32() to get it.
UINT64 // 64 bit unsigned integral value, use AsUint64() to get it.
FLOAT32 // 32 bit floating point value, use AsFloat32() to get it.
FLOAT64 // 64 bit floating point value, use AsFloat64() to get it.
STRING // String value, use AsString() to get it.
)
// Bool creates a BOOL Value.
func Bool(v bool) Value {
return Value{
vtype: BOOL,
numeric: internal.BoolToRaw(v),
}
}
// Int64 creates an INT64 Value.
func Int64(v int64) Value {
return Value{
vtype: INT64,
numeric: internal.Int64ToRaw(v),
}
}
// Uint64 creates a UINT64 Value.
func Uint64(v uint64) Value {
return Value{
vtype: UINT64,
numeric: internal.Uint64ToRaw(v),
}
}
// Float64 creates a FLOAT64 Value.
func Float64(v float64) Value {
return Value{
vtype: FLOAT64,
numeric: internal.Float64ToRaw(v),
}
}
// Int32 creates an INT32 Value.
func Int32(v int32) Value {
return Value{
vtype: INT32,
numeric: internal.Int32ToRaw(v),
}
}
// Uint32 creates a UINT32 Value.
func Uint32(v uint32) Value {
return Value{
vtype: UINT32,
numeric: internal.Uint32ToRaw(v),
}
}
// Float32 creates a FLOAT32 Value.
func Float32(v float32) Value {
return Value{
vtype: FLOAT32,
numeric: internal.Float32ToRaw(v),
}
}
// String creates a STRING Value.
func String(v string) Value {
return Value{
vtype: STRING,
stringly: v,
}
}
// Int creates either an INT32 or an INT64 Value, depending on whether
// the int type is 32 or 64 bits wide.
func Int(v int) Value {
if unsafe.Sizeof(v) == 4 {
return Int32(int32(v))
}
return Int64(int64(v))
}
// Uint creates either a UINT32 or a UINT64 Value, depending on
// whether the uint type is 32 or 64 bits wide.
func Uint(v uint) Value {
if unsafe.Sizeof(v) == 4 {
return Uint32(uint32(v))
}
return Uint64(uint64(v))
}
// Type returns a type of the Value.
func (v Value) Type() Type {
return v.vtype
}
// AsBool returns the bool value. Make sure that the Value's type is
// BOOL.
func (v Value) AsBool() bool {
return internal.RawToBool(v.numeric)
}
// AsInt32 returns the int32 value. Make sure that the Value's type is
// INT32.
func (v Value) AsInt32() int32 {
return internal.RawToInt32(v.numeric)
}
// AsInt64 returns the int64 value. Make sure that the Value's type is
// INT64.
func (v Value) AsInt64() int64 {
return internal.RawToInt64(v.numeric)
}
// AsUint32 returns the uint32 value. Make sure that the Value's type
// is UINT32.
func (v Value) AsUint32() uint32 {
return internal.RawToUint32(v.numeric)
}
// AsUint64 returns the uint64 value. Make sure that the Value's type is
// UINT64.
func (v Value) AsUint64() uint64 {
return internal.RawToUint64(v.numeric)
}
// AsFloat32 returns the float32 value. Make sure that the Value's
// type is FLOAT32.
func (v Value) AsFloat32() float32 {
return internal.RawToFloat32(v.numeric)
}
// AsFloat64 returns the float64 value. Make sure that the Value's
// type is FLOAT64.
func (v Value) AsFloat64() float64 {
return internal.RawToFloat64(v.numeric)
}
// AsString returns the string value. Make sure that the Value's type
// is STRING.
func (v Value) AsString() string {
return v.stringly
}
type unknownValueType struct{}
// AsInterface returns Value's data as interface{}.
func (v Value) AsInterface() interface{} {
switch v.Type() {
case BOOL:
return v.AsBool()
case INT32:
return v.AsInt32()
case INT64:
return v.AsInt64()
case UINT32:
return v.AsUint32()
case UINT64:
return v.AsUint64()
case FLOAT32:
return v.AsFloat32()
case FLOAT64:
return v.AsFloat64()
case STRING:
return v.stringly
}
return unknownValueType{}
}
// Emit returns a string representation of Value's data.
func (v Value) Emit() string {
switch v.Type() {
case BOOL:
return strconv.FormatBool(v.AsBool())
case INT32:
return strconv.FormatInt(int64(v.AsInt32()), 10)
case INT64:
return strconv.FormatInt(v.AsInt64(), 10)
case UINT32:
return strconv.FormatUint(uint64(v.AsUint32()), 10)
case UINT64:
return strconv.FormatUint(v.AsUint64(), 10)
case FLOAT32:
return fmt.Sprint(v.AsFloat32())
case FLOAT64:
return fmt.Sprint(v.AsFloat64())
case STRING:
return v.stringly
default:
return "unknown"
}
}
// MarshalJSON returns the JSON encoding of the Value.
func (v Value) MarshalJSON() ([]byte, error) {
var jsonVal struct {
Type string
Value interface{}
}
jsonVal.Type = v.Type().String()
jsonVal.Value = v.AsInterface()
return json.Marshal(jsonVal)
}

137
api/kv/value/value_test.go Normal file
View File

@ -0,0 +1,137 @@
// 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 value_test
import (
"testing"
"unsafe"
"go.opentelemetry.io/otel/api/kv"
"github.com/google/go-cmp/cmp"
"go.opentelemetry.io/otel/api/kv/value"
)
func TestValue(t *testing.T) {
k := kv.Key("test")
bli := getBitlessInfo(42)
for _, testcase := range []struct {
name string
value value.Value
wantType value.Type
wantValue interface{}
}{
{
name: "Key.Bool() correctly returns keys's internal bool value",
value: k.Bool(true).Value,
wantType: value.BOOL,
wantValue: true,
},
{
name: "Key.Int64() correctly returns keys's internal int64 value",
value: k.Int64(42).Value,
wantType: value.INT64,
wantValue: int64(42),
},
{
name: "Key.Uint64() correctly returns keys's internal uint64 value",
value: k.Uint64(42).Value,
wantType: value.UINT64,
wantValue: uint64(42),
},
{
name: "Key.Float64() correctly returns keys's internal float64 value",
value: k.Float64(42.1).Value,
wantType: value.FLOAT64,
wantValue: 42.1,
},
{
name: "Key.Int32() correctly returns keys's internal int32 value",
value: k.Int32(42).Value,
wantType: value.INT32,
wantValue: int32(42),
},
{
name: "Key.Uint32() correctly returns keys's internal uint32 value",
value: k.Uint32(42).Value,
wantType: value.UINT32,
wantValue: uint32(42),
},
{
name: "Key.Float32() correctly returns keys's internal float32 value",
value: k.Float32(42.1).Value,
wantType: value.FLOAT32,
wantValue: float32(42.1),
},
{
name: "Key.String() correctly returns keys's internal string value",
value: k.String("foo").Value,
wantType: value.STRING,
wantValue: "foo",
},
{
name: "Key.Int() correctly returns keys's internal signed integral value",
value: k.Int(bli.intValue).Value,
wantType: bli.signedType,
wantValue: bli.signedValue,
},
{
name: "Key.Uint() correctly returns keys's internal unsigned integral value",
value: k.Uint(bli.uintValue).Value,
wantType: bli.unsignedType,
wantValue: bli.unsignedValue,
},
} {
t.Logf("Running test case %s", testcase.name)
if testcase.value.Type() != testcase.wantType {
t.Errorf("wrong value type, got %#v, expected %#v", testcase.value.Type(), testcase.wantType)
}
got := testcase.value.AsInterface()
if diff := cmp.Diff(testcase.wantValue, got); diff != "" {
t.Errorf("+got, -want: %s", diff)
}
}
}
type bitlessInfo struct {
intValue int
uintValue uint
signedType value.Type
unsignedType value.Type
signedValue interface{}
unsignedValue interface{}
}
func getBitlessInfo(i int) bitlessInfo {
if unsafe.Sizeof(i) == 4 {
return bitlessInfo{
intValue: i,
uintValue: uint(i),
signedType: value.INT32,
unsignedType: value.UINT32,
signedValue: int32(i),
unsignedValue: uint32(i),
}
}
return bitlessInfo{
intValue: i,
uintValue: uint(i),
signedType: value.INT64,
unsignedType: value.UINT64,
signedValue: int64(i),
unsignedValue: uint64(i),
}
}

View File

@ -19,7 +19,7 @@ import (
"sync"
"sync/atomic"
"go.opentelemetry.io/otel/api/core"
"go.opentelemetry.io/otel/api/kv/value"
)
type (
@ -111,18 +111,18 @@ func (d *defaultLabelEncoder) Encode(iter Iterator) string {
buf.Reset()
for iter.Next() {
i, kv := iter.IndexedLabel()
i, keyValue := iter.IndexedLabel()
if i > 0 {
_, _ = buf.WriteRune(',')
}
copyAndEscape(buf, string(kv.Key))
copyAndEscape(buf, string(keyValue.Key))
_, _ = buf.WriteRune('=')
if kv.Value.Type() == core.STRING {
copyAndEscape(buf, kv.Value.AsString())
if keyValue.Value.Type() == value.STRING {
copyAndEscape(buf, keyValue.Value.AsString())
} else {
_, _ = buf.WriteString(kv.Value.Emit())
_, _ = buf.WriteString(keyValue.Value.Emit())
}
}
return buf.String()

View File

@ -15,7 +15,7 @@
package label
import (
"go.opentelemetry.io/otel/api/core"
"go.opentelemetry.io/otel/api/kv"
)
// Iterator allows iterating over the set of labels in order,
@ -32,26 +32,26 @@ func (i *Iterator) Next() bool {
return i.idx < i.Len()
}
// Label returns current core.KeyValue. Must be called only after Next returns
// Label returns current kv.KeyValue. Must be called only after Next returns
// true.
func (i *Iterator) Label() core.KeyValue {
func (i *Iterator) Label() kv.KeyValue {
kv, _ := i.storage.Get(i.idx)
return kv
}
// Attribute is a synonym for Label().
func (i *Iterator) Attribute() core.KeyValue {
func (i *Iterator) Attribute() kv.KeyValue {
return i.Label()
}
// IndexedLabel returns current index and label. Must be called only
// after Next returns true.
func (i *Iterator) IndexedLabel() (int, core.KeyValue) {
func (i *Iterator) IndexedLabel() (int, kv.KeyValue) {
return i.idx, i.Label()
}
// IndexedAttribute is a synonym for IndexedLabel().
func (i *Iterator) IndexedAttribute() (int, core.KeyValue) {
func (i *Iterator) IndexedAttribute() (int, kv.KeyValue) {
return i.IndexedLabel()
}
@ -63,13 +63,13 @@ func (i *Iterator) Len() int {
// ToSlice is a convenience function that creates a slice of labels
// from the passed iterator. The iterator is set up to start from the
// beginning before creating the slice.
func (i *Iterator) ToSlice() []core.KeyValue {
func (i *Iterator) ToSlice() []kv.KeyValue {
l := i.Len()
if l == 0 {
return nil
}
i.idx = -1
slice := make([]core.KeyValue, 0, l)
slice := make([]kv.KeyValue, 0, l)
for i.Next() {
slice = append(slice, i.Label())
}

View File

@ -17,15 +17,16 @@ package label_test
import (
"testing"
"go.opentelemetry.io/otel/api/kv"
"github.com/stretchr/testify/require"
"go.opentelemetry.io/otel/api/key"
"go.opentelemetry.io/otel/api/label"
)
func TestIterator(t *testing.T) {
one := key.String("one", "1")
two := key.Int("two", 2)
one := kv.String("one", "1")
two := kv.Int("two", 2)
lbl := label.NewSet(one, two)
iter := lbl.Iter()
require.Equal(t, 2, iter.Len())

View File

@ -20,7 +20,9 @@ import (
"sort"
"sync"
"go.opentelemetry.io/otel/api/core"
"go.opentelemetry.io/otel/api/kv/value"
"go.opentelemetry.io/otel/api/kv"
)
type (
@ -43,7 +45,7 @@ type (
encoded [maxConcurrentEncoders]string
}
// Distinct wraps a variable-size array of `core.KeyValue`,
// Distinct wraps a variable-size array of `kv.KeyValue`,
// constructed with keys in sorted order. This can be used as
// a map key or for equality checking between Sets.
Distinct struct {
@ -51,22 +53,22 @@ type (
}
// Sortable implements `sort.Interface`, used for sorting
// `core.KeyValue`. This is an exported type to support a
// `kv.KeyValue`. This is an exported type to support a
// memory optimization. A pointer to one of these is needed
// for the call to `sort.Stable()`, which the caller may
// provide in order to avoid an allocation. See
// `NewSetWithSortable()`.
Sortable []core.KeyValue
Sortable []kv.KeyValue
)
var (
// keyValueType is used in `computeDistinctReflect`.
keyValueType = reflect.TypeOf(core.KeyValue{})
keyValueType = reflect.TypeOf(kv.KeyValue{})
// emptySet is returned for empty label sets.
emptySet = &Set{
equivalent: Distinct{
iface: [0]core.KeyValue{},
iface: [0]kv.KeyValue{},
},
}
)
@ -96,44 +98,44 @@ func (l *Set) Len() int {
}
// Get returns the KeyValue at ordered position `idx` in this set.
func (l *Set) Get(idx int) (core.KeyValue, bool) {
func (l *Set) Get(idx int) (kv.KeyValue, bool) {
if l == nil {
return core.KeyValue{}, false
return kv.KeyValue{}, false
}
value := l.equivalent.reflect()
if idx >= 0 && idx < value.Len() {
// Note: The Go compiler successfully avoids an allocation for
// the interface{} conversion here:
return value.Index(idx).Interface().(core.KeyValue), true
return value.Index(idx).Interface().(kv.KeyValue), true
}
return core.KeyValue{}, false
return kv.KeyValue{}, false
}
// Value returns the value of a specified key in this set.
func (l *Set) Value(k core.Key) (core.Value, bool) {
func (l *Set) Value(k kv.Key) (value.Value, bool) {
if l == nil {
return core.Value{}, false
return value.Value{}, false
}
value := l.equivalent.reflect()
vlen := value.Len()
rValue := l.equivalent.reflect()
vlen := rValue.Len()
idx := sort.Search(vlen, func(idx int) bool {
return value.Index(idx).Interface().(core.KeyValue).Key >= k
return rValue.Index(idx).Interface().(kv.KeyValue).Key >= k
})
if idx >= vlen {
return core.Value{}, false
return value.Value{}, false
}
kv := value.Index(idx).Interface().(core.KeyValue)
if k == kv.Key {
return kv.Value, true
keyValue := rValue.Index(idx).Interface().(kv.KeyValue)
if k == keyValue.Key {
return keyValue.Value, true
}
return core.Value{}, false
return value.Value{}, false
}
// HasValue tests whether a key is defined in this set.
func (l *Set) HasValue(k core.Key) bool {
func (l *Set) HasValue(k kv.Key) bool {
if l == nil {
return false
}
@ -151,7 +153,7 @@ func (l *Set) Iter() Iterator {
// ToSlice returns the set of labels belonging to this set, sorted,
// where keys appear no more than once.
func (l *Set) ToSlice() []core.KeyValue {
func (l *Set) ToSlice() []kv.KeyValue {
iter := l.Iter()
return iter.ToSlice()
}
@ -226,7 +228,7 @@ func (l *Set) Encoded(encoder Encoder) string {
//
// Except for empty sets, this method adds an additional allocation
// compared with a call to `NewSetWithSortable`.
func NewSet(kvs ...core.KeyValue) Set {
func NewSet(kvs ...kv.KeyValue) Set {
// Check for empty set.
if len(kvs) == 0 {
return Set{
@ -258,7 +260,7 @@ func NewSet(kvs ...core.KeyValue) Set {
//
// The result maintains a cache of encoded labels, by label.EncoderID.
// This value should not be copied after its first use.
func NewSetWithSortable(kvs []core.KeyValue, tmp *Sortable) Set {
func NewSetWithSortable(kvs []kv.KeyValue, tmp *Sortable) Set {
// Check for empty set.
if len(kvs) == 0 {
return Set{
@ -299,7 +301,7 @@ func NewSetWithSortable(kvs []core.KeyValue, tmp *Sortable) Set {
// computeDistinct returns a `Distinct` using either the fixed- or
// reflect-oriented code path, depending on the size of the input.
// The input slice is assumed to already be sorted and de-duplicated.
func computeDistinct(kvs []core.KeyValue) Distinct {
func computeDistinct(kvs []kv.KeyValue) Distinct {
iface := computeDistinctFixed(kvs)
if iface == nil {
iface = computeDistinctReflect(kvs)
@ -311,46 +313,46 @@ func computeDistinct(kvs []core.KeyValue) Distinct {
// computeDistinctFixed computes a `Distinct` for small slices. It
// returns nil if the input is too large for this code path.
func computeDistinctFixed(kvs []core.KeyValue) interface{} {
func computeDistinctFixed(kvs []kv.KeyValue) interface{} {
switch len(kvs) {
case 1:
ptr := new([1]core.KeyValue)
ptr := new([1]kv.KeyValue)
copy((*ptr)[:], kvs)
return *ptr
case 2:
ptr := new([2]core.KeyValue)
ptr := new([2]kv.KeyValue)
copy((*ptr)[:], kvs)
return *ptr
case 3:
ptr := new([3]core.KeyValue)
ptr := new([3]kv.KeyValue)
copy((*ptr)[:], kvs)
return *ptr
case 4:
ptr := new([4]core.KeyValue)
ptr := new([4]kv.KeyValue)
copy((*ptr)[:], kvs)
return *ptr
case 5:
ptr := new([5]core.KeyValue)
ptr := new([5]kv.KeyValue)
copy((*ptr)[:], kvs)
return *ptr
case 6:
ptr := new([6]core.KeyValue)
ptr := new([6]kv.KeyValue)
copy((*ptr)[:], kvs)
return *ptr
case 7:
ptr := new([7]core.KeyValue)
ptr := new([7]kv.KeyValue)
copy((*ptr)[:], kvs)
return *ptr
case 8:
ptr := new([8]core.KeyValue)
ptr := new([8]kv.KeyValue)
copy((*ptr)[:], kvs)
return *ptr
case 9:
ptr := new([9]core.KeyValue)
ptr := new([9]kv.KeyValue)
copy((*ptr)[:], kvs)
return *ptr
case 10:
ptr := new([10]core.KeyValue)
ptr := new([10]kv.KeyValue)
copy((*ptr)[:], kvs)
return *ptr
default:
@ -360,10 +362,10 @@ func computeDistinctFixed(kvs []core.KeyValue) interface{} {
// computeDistinctReflect computes a `Distinct` using reflection,
// works for any size input.
func computeDistinctReflect(kvs []core.KeyValue) interface{} {
func computeDistinctReflect(kvs []kv.KeyValue) interface{} {
at := reflect.New(reflect.ArrayOf(len(kvs), keyValueType)).Elem()
for i, kv := range kvs {
*(at.Index(i).Addr().Interface().(*core.KeyValue)) = kv
for i, keyValue := range kvs {
*(at.Index(i).Addr().Interface().(*kv.KeyValue)) = keyValue
}
return at.Interface()
}

View File

@ -17,19 +17,18 @@ package label_test
import (
"testing"
"go.opentelemetry.io/otel/api/core"
"go.opentelemetry.io/otel/api/key"
"go.opentelemetry.io/otel/api/kv"
"go.opentelemetry.io/otel/api/label"
"github.com/stretchr/testify/require"
)
type testCase struct {
kvs []core.KeyValue
kvs []kv.KeyValue
encoding string
}
func expect(enc string, kvs ...core.KeyValue) testCase {
func expect(enc string, kvs ...kv.KeyValue) testCase {
return testCase{
kvs: kvs,
encoding: enc,
@ -38,16 +37,16 @@ func expect(enc string, kvs ...core.KeyValue) testCase {
func TestSetDedup(t *testing.T) {
cases := []testCase{
expect("A=B", key.String("A", "2"), key.String("A", "B")),
expect("A=B", key.String("A", "2"), key.Int("A", 1), key.String("A", "B")),
expect("A=B", key.String("A", "B"), key.String("A", "C"), key.String("A", "D"), key.String("A", "B")),
expect("A=B", kv.String("A", "2"), kv.String("A", "B")),
expect("A=B", kv.String("A", "2"), kv.Int("A", 1), kv.String("A", "B")),
expect("A=B", kv.String("A", "B"), kv.String("A", "C"), kv.String("A", "D"), kv.String("A", "B")),
expect("A=B,C=D", key.String("A", "1"), key.String("C", "D"), key.String("A", "B")),
expect("A=B,C=D", key.String("A", "2"), key.String("A", "B"), key.String("C", "D")),
expect("A=B,C=D", key.Float64("C", 1.2), key.String("A", "2"), key.String("A", "B"), key.String("C", "D")),
expect("A=B,C=D", key.String("C", "D"), key.String("A", "B"), key.String("A", "C"), key.String("A", "D"), key.String("A", "B")),
expect("A=B,C=D", key.String("A", "B"), key.String("C", "D"), key.String("A", "C"), key.String("A", "D"), key.String("A", "B")),
expect("A=B,C=D", key.String("A", "B"), key.String("A", "C"), key.String("A", "D"), key.String("A", "B"), key.String("C", "D")),
expect("A=B,C=D", kv.String("A", "1"), kv.String("C", "D"), kv.String("A", "B")),
expect("A=B,C=D", kv.String("A", "2"), kv.String("A", "B"), kv.String("C", "D")),
expect("A=B,C=D", kv.Float64("C", 1.2), kv.String("A", "2"), kv.String("A", "B"), kv.String("C", "D")),
expect("A=B,C=D", kv.String("C", "D"), kv.String("A", "B"), kv.String("A", "C"), kv.String("A", "D"), kv.String("A", "B")),
expect("A=B,C=D", kv.String("A", "B"), kv.String("C", "D"), kv.String("A", "C"), kv.String("A", "D"), kv.String("A", "B")),
expect("A=B,C=D", kv.String("A", "B"), kv.String("A", "C"), kv.String("A", "D"), kv.String("A", "B"), kv.String("C", "D")),
}
enc := label.DefaultEncoder()
@ -55,7 +54,7 @@ func TestSetDedup(t *testing.T) {
d2s := map[label.Distinct][]string{}
for _, tc := range cases {
cpy := make([]core.KeyValue, len(tc.kvs))
cpy := make([]kv.KeyValue, len(tc.kvs))
copy(cpy, tc.kvs)
sl := label.NewSet(cpy...)

View File

@ -19,7 +19,7 @@ package metric
import (
"context"
"go.opentelemetry.io/otel/api/core"
"go.opentelemetry.io/otel/api/kv"
"go.opentelemetry.io/otel/api/unit"
)
@ -145,7 +145,7 @@ type Meter struct {
}
// RecordBatch atomically records a batch of measurements.
func (m Meter) RecordBatch(ctx context.Context, ls []core.KeyValue, ms ...Measurement) {
func (m Meter) RecordBatch(ctx context.Context, ls []kv.KeyValue, ms ...Measurement) {
if m.impl == nil {
return
}
@ -198,9 +198,7 @@ func (m Meter) RegisterInt64Observer(name string, callback Int64ObserverCallback
}
return wrapInt64ObserverInstrument(
m.newAsync(name, ObserverKind, Int64NumberKind, opts,
func(observe func(Number, []core.KeyValue)) {
callback(Int64ObserverResult{observe})
}))
newInt64AsyncRunner(callback)))
}
// RegisterFloat64Observer creates a new floating point Observer with
@ -213,21 +211,16 @@ func (m Meter) RegisterFloat64Observer(name string, callback Float64ObserverCall
}
return wrapFloat64ObserverInstrument(
m.newAsync(name, ObserverKind, Float64NumberKind, opts,
func(observe func(Number, []core.KeyValue)) {
callback(Float64ObserverResult{observe})
}))
newFloat64AsyncRunner(callback)))
}
// Observe captures a single integer value from the associated
// instrument callback, with the given labels.
func (io Int64ObserverResult) Observe(value int64, labels ...core.KeyValue) {
io.observe(NewInt64Number(value), labels)
}
// Observe captures a single floating point value from the associated
// instrument callback, with the given labels.
func (fo Float64ObserverResult) Observe(value float64, labels ...core.KeyValue) {
fo.observe(NewFloat64Number(value), labels)
// NewBatchObserver creates a new BatchObserver that supports
// making batches of observations for multiple instruments.
func (m Meter) NewBatchObserver(callback BatchObserverCallback) BatchObserver {
return BatchObserver{
meter: m,
runner: newBatchAsyncRunner(callback),
}
}
// WithDescription applies provided description.

View File

@ -20,8 +20,7 @@ import (
"fmt"
"testing"
"go.opentelemetry.io/otel/api/core"
"go.opentelemetry.io/otel/api/key"
"go.opentelemetry.io/otel/api/kv"
"go.opentelemetry.io/otel/api/metric"
"go.opentelemetry.io/otel/api/unit"
mockTest "go.opentelemetry.io/otel/internal/metric"
@ -98,7 +97,7 @@ func TestCounter(t *testing.T) {
mockSDK, meter := mockTest.NewMeter()
c := Must(meter).NewFloat64Counter("test.counter.float")
ctx := context.Background()
labels := []core.KeyValue{key.String("A", "B")}
labels := []kv.KeyValue{kv.String("A", "B")}
c.Add(ctx, 42, labels...)
boundInstrument := c.Bind(labels...)
boundInstrument.Add(ctx, 42)
@ -110,7 +109,7 @@ func TestCounter(t *testing.T) {
mockSDK, meter := mockTest.NewMeter()
c := Must(meter).NewInt64Counter("test.counter.int")
ctx := context.Background()
labels := []core.KeyValue{key.String("A", "B"), key.String("C", "D")}
labels := []kv.KeyValue{kv.String("A", "B"), kv.String("C", "D")}
c.Add(ctx, 42, labels...)
boundInstrument := c.Bind(labels...)
boundInstrument.Add(ctx, 42)
@ -125,7 +124,7 @@ func TestMeasure(t *testing.T) {
mockSDK, meter := mockTest.NewMeter()
m := Must(meter).NewFloat64Measure("test.measure.float")
ctx := context.Background()
labels := []core.KeyValue{}
labels := []kv.KeyValue{}
m.Record(ctx, 42, labels...)
boundInstrument := m.Bind(labels...)
boundInstrument.Record(ctx, 42)
@ -137,7 +136,7 @@ func TestMeasure(t *testing.T) {
mockSDK, meter := mockTest.NewMeter()
m := Must(meter).NewInt64Measure("test.measure.int")
ctx := context.Background()
labels := []core.KeyValue{key.Int("I", 1)}
labels := []kv.KeyValue{kv.Int("I", 1)}
m.Record(ctx, 42, labels...)
boundInstrument := m.Bind(labels...)
boundInstrument.Record(ctx, 42)
@ -149,7 +148,7 @@ func TestMeasure(t *testing.T) {
func TestObserver(t *testing.T) {
{
labels := []core.KeyValue{key.String("O", "P")}
labels := []kv.KeyValue{kv.String("O", "P")}
mockSDK, meter := mockTest.NewMeter()
o := Must(meter).RegisterFloat64Observer("test.observer.float", func(result metric.Float64ObserverResult) {
result.Observe(42, labels...)
@ -160,7 +159,7 @@ func TestObserver(t *testing.T) {
checkObserverBatch(t, labels, mockSDK, metric.Float64NumberKind, o.AsyncImpl())
}
{
labels := []core.KeyValue{}
labels := []kv.KeyValue{}
mockSDK, meter := mockTest.NewMeter()
o := Must(meter).RegisterInt64Observer("test.observer.int", func(result metric.Int64ObserverResult) {
result.Observe(42, labels...)
@ -171,7 +170,7 @@ func TestObserver(t *testing.T) {
}
}
func checkBatches(t *testing.T, ctx context.Context, labels []core.KeyValue, mock *mockTest.MeterImpl, kind metric.NumberKind, instrument metric.InstrumentImpl) {
func checkBatches(t *testing.T, ctx context.Context, labels []kv.KeyValue, mock *mockTest.MeterImpl, kind metric.NumberKind, instrument metric.InstrumentImpl) {
t.Helper()
if len(mock.MeasurementBatches) != 3 {
t.Errorf("Expected 3 recorded measurement batches, got %d", len(mock.MeasurementBatches))
@ -211,7 +210,52 @@ func checkBatches(t *testing.T, ctx context.Context, labels []core.KeyValue, moc
}
}
func checkObserverBatch(t *testing.T, labels []core.KeyValue, mock *mockTest.MeterImpl, kind metric.NumberKind, observer metric.AsyncImpl) {
func TestBatchObserver(t *testing.T) {
mockSDK, meter := mockTest.NewMeter()
var obs1 metric.Int64Observer
var obs2 metric.Float64Observer
labels := []kv.KeyValue{
kv.String("A", "B"),
kv.String("C", "D"),
}
cb := Must(meter).NewBatchObserver(
func(result metric.BatchObserverResult) {
result.Observe(labels,
obs1.Observation(42),
obs2.Observation(42.0),
)
},
)
obs1 = cb.RegisterInt64Observer("test.observer.int")
obs2 = cb.RegisterFloat64Observer("test.observer.float")
mockSDK.RunAsyncInstruments()
require.Len(t, mockSDK.MeasurementBatches, 1)
impl1 := obs1.AsyncImpl().Implementation().(*mockTest.Async)
impl2 := obs2.AsyncImpl().Implementation().(*mockTest.Async)
require.NotNil(t, impl1)
require.NotNil(t, impl2)
got := mockSDK.MeasurementBatches[0]
require.Equal(t, labels, got.Labels)
require.Len(t, got.Measurements, 2)
m1 := got.Measurements[0]
require.Equal(t, impl1, m1.Instrument.Implementation().(*mockTest.Async))
require.Equal(t, 0, m1.Number.CompareNumber(metric.Int64NumberKind, fortyTwo(t, metric.Int64NumberKind)))
m2 := got.Measurements[1]
require.Equal(t, impl2, m2.Instrument.Implementation().(*mockTest.Async))
require.Equal(t, 0, m2.Number.CompareNumber(metric.Float64NumberKind, fortyTwo(t, metric.Float64NumberKind)))
}
func checkObserverBatch(t *testing.T, labels []kv.KeyValue, mock *mockTest.MeterImpl, kind metric.NumberKind, observer metric.AsyncImpl) {
t.Helper()
assert.Len(t, mock.MeasurementBatches, 1)
if len(mock.MeasurementBatches) < 1 {
@ -250,14 +294,14 @@ type testWrappedMeter struct {
var _ metric.MeterImpl = testWrappedMeter{}
func (testWrappedMeter) RecordBatch(context.Context, []core.KeyValue, ...metric.Measurement) {
func (testWrappedMeter) RecordBatch(context.Context, []kv.KeyValue, ...metric.Measurement) {
}
func (testWrappedMeter) NewSyncInstrument(_ metric.Descriptor) (metric.SyncImpl, error) {
return nil, nil
}
func (testWrappedMeter) NewAsyncInstrument(_ metric.Descriptor, _ func(func(metric.Number, []core.KeyValue))) (metric.AsyncImpl, error) {
func (testWrappedMeter) NewAsyncInstrument(_ metric.Descriptor, _ metric.AsyncRunner) (metric.AsyncImpl, error) {
return nil, errors.New("Test wrap error")
}

View File

@ -18,7 +18,7 @@ import (
"context"
"errors"
"go.opentelemetry.io/otel/api/core"
"go.opentelemetry.io/otel/api/kv"
)
type syncInstrument struct {
@ -35,7 +35,7 @@ type asyncInstrument struct {
var ErrSDKReturnedNilImpl = errors.New("SDK returned a nil implementation")
func (s syncInstrument) bind(labels []core.KeyValue) syncBoundInstrument {
func (s syncInstrument) bind(labels []kv.KeyValue) syncBoundInstrument {
return newSyncBoundInstrument(s.instrument.Bind(labels))
}
@ -47,7 +47,7 @@ func (s syncInstrument) int64Measurement(value int64) Measurement {
return newMeasurement(s.instrument, NewInt64Number(value))
}
func (s syncInstrument) directRecord(ctx context.Context, number Number, labels []core.KeyValue) {
func (s syncInstrument) directRecord(ctx context.Context, number Number, labels []kv.KeyValue) {
s.instrument.RecordOne(ctx, number, labels)
}

View File

@ -17,7 +17,7 @@ package metric
import (
"context"
"go.opentelemetry.io/otel/api/core"
"go.opentelemetry.io/otel/api/kv"
)
// Float64Counter is a metric that accumulates float64 values.
@ -46,14 +46,14 @@ type BoundInt64Counter struct {
// Bind creates a bound instrument for this counter. The labels are
// associated with values recorded via subsequent calls to Record.
func (c Float64Counter) Bind(labels ...core.KeyValue) (h BoundFloat64Counter) {
func (c Float64Counter) Bind(labels ...kv.KeyValue) (h BoundFloat64Counter) {
h.syncBoundInstrument = c.bind(labels)
return
}
// Bind creates a bound instrument for this counter. The labels are
// associated with values recorded via subsequent calls to Record.
func (c Int64Counter) Bind(labels ...core.KeyValue) (h BoundInt64Counter) {
func (c Int64Counter) Bind(labels ...kv.KeyValue) (h BoundInt64Counter) {
h.syncBoundInstrument = c.bind(labels)
return
}
@ -72,13 +72,13 @@ func (c Int64Counter) Measurement(value int64) Measurement {
// Add adds the value to the counter's sum. The labels should contain
// the keys and values to be associated with this value.
func (c Float64Counter) Add(ctx context.Context, value float64, labels ...core.KeyValue) {
func (c Float64Counter) Add(ctx context.Context, value float64, labels ...kv.KeyValue) {
c.directRecord(ctx, NewFloat64Number(value), labels)
}
// Add adds the value to the counter's sum. The labels should contain
// the keys and values to be associated with this value.
func (c Int64Counter) Add(ctx context.Context, value int64, labels ...core.KeyValue) {
func (c Int64Counter) Add(ctx context.Context, value int64, labels ...kv.KeyValue) {
c.directRecord(ctx, NewInt64Number(value), labels)
}

View File

@ -17,7 +17,7 @@ package metric
import (
"context"
"go.opentelemetry.io/otel/api/core"
"go.opentelemetry.io/otel/api/kv"
)
// Float64Measure is a metric that records float64 values.
@ -46,14 +46,14 @@ type BoundInt64Measure struct {
// Bind creates a bound instrument for this measure. The labels are
// associated with values recorded via subsequent calls to Record.
func (c Float64Measure) Bind(labels ...core.KeyValue) (h BoundFloat64Measure) {
func (c Float64Measure) Bind(labels ...kv.KeyValue) (h BoundFloat64Measure) {
h.syncBoundInstrument = c.bind(labels)
return
}
// Bind creates a bound instrument for this measure. The labels are
// associated with values recorded via subsequent calls to Record.
func (c Int64Measure) Bind(labels ...core.KeyValue) (h BoundInt64Measure) {
func (c Int64Measure) Bind(labels ...kv.KeyValue) (h BoundInt64Measure) {
h.syncBoundInstrument = c.bind(labels)
return
}
@ -73,14 +73,14 @@ func (c Int64Measure) Measurement(value int64) Measurement {
// Record adds a new value to the list of measure's records. The
// labels should contain the keys and values to be associated with
// this value.
func (c Float64Measure) Record(ctx context.Context, value float64, labels ...core.KeyValue) {
func (c Float64Measure) Record(ctx context.Context, value float64, labels ...kv.KeyValue) {
c.directRecord(ctx, NewFloat64Number(value), labels)
}
// Record adds a new value to the list of measure's records. The
// labels should contain the keys and values to be associated with
// this value.
func (c Int64Measure) Record(ctx context.Context, value int64, labels ...core.KeyValue) {
func (c Int64Measure) Record(ctx context.Context, value int64, labels ...kv.KeyValue) {
c.directRecord(ctx, NewInt64Number(value), labels)
}

View File

@ -20,6 +20,12 @@ type MeterMust struct {
meter Meter
}
// BatchObserverMust is a wrapper for BatchObserver that panics when
// any instrument constructor encounters an error.
type BatchObserverMust struct {
batch BatchObserver
}
// Must constructs a MeterMust implementation from a Meter, allowing
// the application to panic when any instrument constructor yields an
// error.
@ -86,3 +92,31 @@ func (mm MeterMust) RegisterFloat64Observer(name string, callback Float64Observe
return inst
}
}
// NewBatchObserver returns a wrapper around BatchObserver that panics
// when any instrument constructor returns an error.
func (mm MeterMust) NewBatchObserver(callback BatchObserverCallback) BatchObserverMust {
return BatchObserverMust{
batch: mm.meter.NewBatchObserver(callback),
}
}
// RegisterInt64Observer calls `BatchObserver.RegisterInt64Observer` and
// returns the instrument, panicking if it encounters an error.
func (bm BatchObserverMust) RegisterInt64Observer(name string, oos ...Option) Int64Observer {
if inst, err := bm.batch.RegisterInt64Observer(name, oos...); err != nil {
panic(err)
} else {
return inst
}
}
// RegisterFloat64Observer calls `BatchObserver.RegisterFloat64Observer` and
// returns the instrument, panicking if it encounters an error.
func (bm BatchObserverMust) RegisterFloat64Observer(name string, oos ...Option) Float64Observer {
if inst, err := bm.batch.RegisterFloat64Observer(name, oos...); err != nil {
panic(err)
} else {
return inst
}
}

View File

@ -17,7 +17,7 @@ package metric
import (
"context"
"go.opentelemetry.io/otel/api/core"
"go.opentelemetry.io/otel/api/kv"
)
type NoopProvider struct{}
@ -50,9 +50,9 @@ func (noopBoundInstrument) RecordOne(context.Context, Number) {
func (noopBoundInstrument) Unbind() {
}
func (NoopSync) Bind([]core.KeyValue) BoundSyncImpl {
func (NoopSync) Bind([]kv.KeyValue) BoundSyncImpl {
return noopBoundInstrument{}
}
func (NoopSync) RecordOne(context.Context, Number, []core.KeyValue) {
func (NoopSync) RecordOne(context.Context, Number, []kv.KeyValue) {
}

View File

@ -14,13 +14,20 @@
package metric
import "go.opentelemetry.io/otel/api/kv"
// Int64ObserverCallback is a type of callback that integral
// observers run.
type Int64ObserverCallback func(result Int64ObserverResult)
type Int64ObserverCallback func(Int64ObserverResult)
// Float64ObserverCallback is a type of callback that floating point
// observers run.
type Float64ObserverCallback func(result Float64ObserverResult)
type Float64ObserverCallback func(Float64ObserverResult)
// BatchObserverCallback is a callback argument for use with any
// Observer instrument that will be reported as a batch of
// observations.
type BatchObserverCallback func(BatchObserverResult)
// Int64Observer is a metric that captures a set of int64 values at a
// point in time.
@ -33,3 +40,205 @@ type Int64Observer struct {
type Float64Observer struct {
asyncInstrument
}
// BatchObserver represents an Observer callback that can report
// observations for multiple instruments.
type BatchObserver struct {
meter Meter
runner AsyncBatchRunner
}
// Int64ObserverResult is passed to an observer callback to capture
// observations for one asynchronous integer metric instrument.
type Int64ObserverResult struct {
instrument AsyncImpl
function func([]kv.KeyValue, ...Observation)
}
// Float64ObserverResult is passed to an observer callback to capture
// observations for one asynchronous floating point metric instrument.
type Float64ObserverResult struct {
instrument AsyncImpl
function func([]kv.KeyValue, ...Observation)
}
// BatchObserverResult is passed to a batch observer callback to
// capture observations for multiple asynchronous instruments.
type BatchObserverResult struct {
function func([]kv.KeyValue, ...Observation)
}
// AsyncRunner is expected to convert into an AsyncSingleRunner or an
// AsyncBatchRunner. SDKs will encounter an error if the AsyncRunner
// does not satisfy one of these interfaces.
type AsyncRunner interface {
// anyRunner() is a non-exported method with no functional use
// other than to make this a non-empty interface.
anyRunner()
}
// AsyncSingleRunner is an interface implemented by single-observer
// callbacks.
type AsyncSingleRunner interface {
// Run accepts a single instrument and function for capturing
// observations of that instrument. Each call to the function
// receives one captured observation. (The function accepts
// multiple observations so the same implementation can be
// used for batch runners.)
Run(single AsyncImpl, capture func([]kv.KeyValue, ...Observation))
AsyncRunner
}
// AsyncBatchRunner is an interface implemented by batch-observer
// callbacks.
type AsyncBatchRunner interface {
// Run accepts a function for capturing observations of
// multiple instruments.
Run(capture func([]kv.KeyValue, ...Observation))
AsyncRunner
}
// Observe captures a single integer value from the associated
// instrument callback, with the given labels.
func (ir Int64ObserverResult) Observe(value int64, labels ...kv.KeyValue) {
ir.function(labels, Observation{
instrument: ir.instrument,
number: NewInt64Number(value),
})
}
// Observe captures a single floating point value from the associated
// instrument callback, with the given labels.
func (fr Float64ObserverResult) Observe(value float64, labels ...kv.KeyValue) {
fr.function(labels, Observation{
instrument: fr.instrument,
number: NewFloat64Number(value),
})
}
// Observe captures a multiple observations from the associated batch
// instrument callback, with the given labels.
func (br BatchObserverResult) Observe(labels []kv.KeyValue, obs ...Observation) {
br.function(labels, obs...)
}
// Observation is used for reporting a batch of metric
// values. Instances of this type should be created by Observer
// instruments (e.g., Int64Observer.Observation()).
type Observation struct {
// number needs to be aligned for 64-bit atomic operations.
number Number
instrument AsyncImpl
}
// AsyncImpl returns the instrument that created this observation.
// This returns an implementation-level object for use by the SDK,
// users should not refer to this.
func (m Observation) AsyncImpl() AsyncImpl {
return m.instrument
}
// Number returns a number recorded in this observation.
func (m Observation) Number() Number {
return m.number
}
// RegisterInt64Observer creates a new integer Observer instrument
// with the given name, running in a batch callback, and customized with
// options. May return an error if the name is invalid (e.g., empty)
// or improperly registered (e.g., duplicate registration).
func (b BatchObserver) RegisterInt64Observer(name string, opts ...Option) (Int64Observer, error) {
if b.runner == nil {
return wrapInt64ObserverInstrument(NoopAsync{}, nil)
}
return wrapInt64ObserverInstrument(
b.meter.newAsync(name, ObserverKind, Int64NumberKind, opts, b.runner))
}
// RegisterFloat64Observer creates a new floating point Observer with
// the given name, running in a batch callback, and customized with
// options. May return an error if the name is invalid (e.g., empty)
// or improperly registered (e.g., duplicate registration).
func (b BatchObserver) RegisterFloat64Observer(name string, opts ...Option) (Float64Observer, error) {
if b.runner == nil {
return wrapFloat64ObserverInstrument(NoopAsync{}, nil)
}
return wrapFloat64ObserverInstrument(
b.meter.newAsync(name, ObserverKind, Float64NumberKind, opts,
b.runner))
}
// Observation returns an Observation, a BatchObserverCallback
// argument, for an asynchronous integer instrument.
// This returns an implementation-level object for use by the SDK,
// users should not refer to this.
func (i Int64Observer) Observation(v int64) Observation {
return Observation{
number: NewInt64Number(v),
instrument: i.instrument,
}
}
// Observation returns an Observation, a BatchObserverCallback
// argument, for an asynchronous integer instrument.
// This returns an implementation-level object for use by the SDK,
// users should not refer to this.
func (f Float64Observer) Observation(v float64) Observation {
return Observation{
number: NewFloat64Number(v),
instrument: f.instrument,
}
}
var _ AsyncSingleRunner = (*Int64ObserverCallback)(nil)
var _ AsyncSingleRunner = (*Float64ObserverCallback)(nil)
var _ AsyncBatchRunner = (*BatchObserverCallback)(nil)
// newInt64AsyncRunner returns a single-observer callback for integer Observer instruments.
func newInt64AsyncRunner(c Int64ObserverCallback) AsyncSingleRunner {
return &c
}
// newFloat64AsyncRunner returns a single-observer callback for floating point Observer instruments.
func newFloat64AsyncRunner(c Float64ObserverCallback) AsyncSingleRunner {
return &c
}
// newBatchAsyncRunner returns a batch-observer callback use with multiple Observer instruments.
func newBatchAsyncRunner(c BatchObserverCallback) AsyncBatchRunner {
return &c
}
// anyRunner implements AsyncRunner.
func (*Int64ObserverCallback) anyRunner() {}
// anyRunner implements AsyncRunner.
func (*Float64ObserverCallback) anyRunner() {}
// anyRunner implements AsyncRunner.
func (*BatchObserverCallback) anyRunner() {}
// Run implements AsyncSingleRunner.
func (i *Int64ObserverCallback) Run(impl AsyncImpl, function func([]kv.KeyValue, ...Observation)) {
(*i)(Int64ObserverResult{
instrument: impl,
function: function,
})
}
// Run implements AsyncSingleRunner.
func (f *Float64ObserverCallback) Run(impl AsyncImpl, function func([]kv.KeyValue, ...Observation)) {
(*f)(Float64ObserverResult{
instrument: impl,
function: function,
})
}
// Run implements AsyncBatchRunner.
func (b *BatchObserverCallback) Run(function func([]kv.KeyValue, ...Observation)) {
(*b)(BatchObserverResult{
function: function,
})
}

View File

@ -19,7 +19,7 @@ import (
"fmt"
"sync"
"go.opentelemetry.io/otel/api/core"
"go.opentelemetry.io/otel/api/kv"
"go.opentelemetry.io/otel/api/metric"
)
@ -32,6 +32,8 @@ type uniqueInstrumentMeterImpl struct {
state map[key]metric.InstrumentImpl
}
var _ metric.MeterImpl = (*uniqueInstrumentMeterImpl)(nil)
type key struct {
name string
libraryName string
@ -42,8 +44,6 @@ type key struct {
var ErrMetricKindMismatch = fmt.Errorf(
"A metric was already registered by this name with another kind or number type")
var _ metric.MeterImpl = (*uniqueInstrumentMeterImpl)(nil)
// NewUniqueInstrumentMeterImpl returns a wrapped metric.MeterImpl with
// the addition of uniqueness checking.
func NewUniqueInstrumentMeterImpl(impl metric.MeterImpl) metric.MeterImpl {
@ -54,7 +54,7 @@ func NewUniqueInstrumentMeterImpl(impl metric.MeterImpl) metric.MeterImpl {
}
// RecordBatch implements metric.MeterImpl.
func (u *uniqueInstrumentMeterImpl) RecordBatch(ctx context.Context, labels []core.KeyValue, ms ...metric.Measurement) {
func (u *uniqueInstrumentMeterImpl) RecordBatch(ctx context.Context, labels []kv.KeyValue, ms ...metric.Measurement) {
u.impl.RecordBatch(ctx, labels, ms...)
}
@ -125,7 +125,7 @@ func (u *uniqueInstrumentMeterImpl) NewSyncInstrument(descriptor metric.Descript
// NewAsyncInstrument implements metric.MeterImpl.
func (u *uniqueInstrumentMeterImpl) NewAsyncInstrument(
descriptor metric.Descriptor,
callback func(func(metric.Number, []core.KeyValue)),
runner metric.AsyncRunner,
) (metric.AsyncImpl, error) {
u.lock.Lock()
defer u.lock.Unlock()
@ -138,7 +138,7 @@ func (u *uniqueInstrumentMeterImpl) NewAsyncInstrument(
return impl.(metric.AsyncImpl), nil
}
asyncInst, err := u.impl.NewAsyncInstrument(descriptor, callback)
asyncInst, err := u.impl.NewAsyncInstrument(descriptor, runner)
if err != nil {
return nil, err
}

View File

@ -17,14 +17,14 @@ package metric
import (
"context"
"go.opentelemetry.io/otel/api/core"
"go.opentelemetry.io/otel/api/kv"
)
// MeterImpl is the interface an SDK must implement to supply a Meter
// implementation.
type MeterImpl interface {
// RecordBatch atomically records a batch of measurements.
RecordBatch(context.Context, []core.KeyValue, ...Measurement)
RecordBatch(context.Context, []kv.KeyValue, ...Measurement)
// NewSyncInstrument returns a newly constructed
// synchronous instrument implementation or an error, should
@ -36,7 +36,7 @@ type MeterImpl interface {
// one occur.
NewAsyncInstrument(
descriptor Descriptor,
callback func(func(Number, []core.KeyValue)),
runner AsyncRunner,
) (AsyncImpl, error)
}
@ -59,10 +59,10 @@ type SyncImpl interface {
// Bind creates an implementation-level bound instrument,
// binding a label set with this instrument implementation.
Bind(labels []core.KeyValue) BoundSyncImpl
Bind(labels []kv.KeyValue) BoundSyncImpl
// RecordOne captures a single synchronous metric event.
RecordOne(ctx context.Context, number Number, labels []core.KeyValue)
RecordOne(ctx context.Context, number Number, labels []kv.KeyValue)
}
// BoundSyncImpl is the implementation-level interface to a
@ -83,18 +83,6 @@ type AsyncImpl interface {
InstrumentImpl
}
// Int64ObserverResult is passed to an observer callback to capture
// observations for one asynchronous integer metric instrument.
type Int64ObserverResult struct {
observe func(Number, []core.KeyValue)
}
// Float64ObserverResult is passed to an observer callback to capture
// observations for one asynchronous floating point metric instrument.
type Float64ObserverResult struct {
observe func(Number, []core.KeyValue)
}
// Configure is a helper that applies all the options to a Config.
func Configure(opts []Option) Config {
var config Config
@ -165,13 +153,13 @@ func wrapFloat64MeasureInstrument(syncInst SyncImpl, err error) (Float64Measure,
}
// newAsync constructs one new asynchronous instrument.
func (m Meter) newAsync(name string, mkind Kind, nkind NumberKind, opts []Option, callback func(func(Number, []core.KeyValue))) (AsyncImpl, error) {
func (m Meter) newAsync(name string, mkind Kind, nkind NumberKind, opts []Option, runner AsyncRunner) (AsyncImpl, error) {
if m.impl == nil {
return NoopAsync{}, nil
}
desc := NewDescriptor(name, mkind, nkind, opts...)
desc.config.LibraryName = m.libraryName
return m.impl.NewAsyncInstrument(desc, callback)
return m.impl.NewAsyncInstrument(desc, runner)
}
// wrapInt64ObserverInstrument returns an `Int64Observer` from a

View File

@ -21,9 +21,10 @@ import (
"testing"
"time"
"go.opentelemetry.io/otel/api/kv"
"google.golang.org/grpc/codes"
"go.opentelemetry.io/otel/api/key"
"go.opentelemetry.io/otel/api/trace"
"go.opentelemetry.io/otel/internal/matchers"
)
@ -329,7 +330,7 @@ func (h *Harness) testSpan(tracerFactory func() trace.Tracer) {
span.SetName("new name")
},
"#SetAttributes": func(span trace.Span) {
span.SetAttributes(key.String("key1", "value"), key.Int("key2", 123))
span.SetAttributes(kv.String("key1", "value"), kv.Int("key2", 123))
},
}
var mechanisms = map[string]func() trace.Span{

View File

@ -15,7 +15,7 @@
package trace
import (
"go.opentelemetry.io/otel/api/core"
"go.opentelemetry.io/otel/api/kv"
)
const (
@ -36,7 +36,7 @@ func (ns alwaysOffSampler) ShouldSample(
_ SpanID,
_ string,
_ SpanKind,
_ []core.KeyValue,
_ []kv.KeyValue,
_ []Link,
) Decision {
return alwaysOffSamplerDecision

View File

@ -19,12 +19,12 @@ import (
"github.com/google/go-cmp/cmp"
"go.opentelemetry.io/otel/api/core"
"go.opentelemetry.io/otel/api/kv"
)
func TestNeverSamperShouldSample(t *testing.T) {
gotD := AlwaysOffSampler().ShouldSample(
SpanContext{}, false, ID{}, SpanID{}, "span", SpanKindClient, []core.KeyValue{}, []Link{})
SpanContext{}, false, ID{}, SpanID{}, "span", SpanKindClient, []kv.KeyValue{}, []Link{})
wantD := Decision{Sampled: false}
if diff := cmp.Diff(wantD, gotD); diff != "" {
t.Errorf("Decision: +got, -want%v", diff)

View File

@ -15,7 +15,7 @@
package trace
import (
"go.opentelemetry.io/otel/api/core"
"go.opentelemetry.io/otel/api/kv"
)
const (
@ -36,7 +36,7 @@ func (as alwaysOnSampler) ShouldSample(
_ SpanID,
_ string,
_ SpanKind,
_ []core.KeyValue,
_ []kv.KeyValue,
_ []Link,
) Decision {
return alwaysOnSamplerDecision

View File

@ -19,12 +19,12 @@ import (
"github.com/google/go-cmp/cmp"
"go.opentelemetry.io/otel/api/core"
"go.opentelemetry.io/otel/api/kv"
)
func TestAlwaysOnSamplerShouldSample(t *testing.T) {
gotD := AlwaysOnSampler().ShouldSample(
SpanContext{}, false, ID{}, SpanID{}, "span", SpanKindClient, []core.KeyValue{}, []Link{})
SpanContext{}, false, ID{}, SpanID{}, "span", SpanKindClient, []kv.KeyValue{}, []Link{})
wantD := Decision{Sampled: true}
if diff := cmp.Diff(wantD, gotD); diff != "" {
t.Errorf("Decision: +got, -want%v", diff)

View File

@ -20,7 +20,7 @@ import (
"google.golang.org/grpc/codes"
"go.opentelemetry.io/otel/api/core"
"go.opentelemetry.io/otel/api/kv"
)
type Provider interface {
@ -92,10 +92,10 @@ type Span interface {
End(options ...EndOption)
// AddEvent adds an event to the span.
AddEvent(ctx context.Context, name string, attrs ...core.KeyValue)
AddEvent(ctx context.Context, name string, attrs ...kv.KeyValue)
// AddEventWithTimestamp adds an event with a custom timestamp
// to the span.
AddEventWithTimestamp(ctx context.Context, timestamp time.Time, name string, attrs ...core.KeyValue)
AddEventWithTimestamp(ctx context.Context, timestamp time.Time, name string, attrs ...kv.KeyValue)
// IsRecording returns true if the span is active and recording events is enabled.
IsRecording() bool
@ -120,7 +120,7 @@ type Span interface {
SetName(name string)
// Set span attributes
SetAttributes(...core.KeyValue)
SetAttributes(...kv.KeyValue)
// Set singular span attribute, with type inference.
SetAttribute(string, interface{})
@ -132,7 +132,7 @@ type StartOption func(*StartConfig)
// StartConfig provides options to set properties of span at the time of starting
// a new span.
type StartConfig struct {
Attributes []core.KeyValue
Attributes []kv.KeyValue
StartTime time.Time
Links []Link
Record bool
@ -153,7 +153,7 @@ type StartConfig struct {
// be correlated.
type Link struct {
SpanContext
Attributes []core.KeyValue
Attributes []kv.KeyValue
}
// SpanKind represents the role of a Span inside a Trace. Often, this defines how a Span
@ -221,7 +221,7 @@ func WithStartTime(t time.Time) StartOption {
// WithAttributes sets attributes to span. These attributes provides additional
// data about the span.
// Multiple `WithAttributes` options appends the attributes preserving the order.
func WithAttributes(attrs ...core.KeyValue) StartOption {
func WithAttributes(attrs ...kv.KeyValue) StartOption {
return func(c *StartConfig) {
c.Attributes = append(c.Attributes, attrs...)
}
@ -248,7 +248,7 @@ func WithNewRoot() StartOption {
}
// LinkedTo allows instantiating a Span with initial Links.
func LinkedTo(sc SpanContext, attrs ...core.KeyValue) StartOption {
func LinkedTo(sc SpanContext, attrs ...kv.KeyValue) StartOption {
return func(c *StartConfig) {
c.Links = append(c.Links, Link{sc, attrs})
}

View File

@ -21,7 +21,7 @@ import (
"google.golang.org/grpc/codes"
"go.opentelemetry.io/otel/api/core"
"go.opentelemetry.io/otel/api/kv"
"go.opentelemetry.io/otel/api/trace"
)
@ -94,7 +94,7 @@ func (mockSpan) SetError(v bool) {
}
// SetAttributes does nothing.
func (mockSpan) SetAttributes(attributes ...core.KeyValue) {
func (mockSpan) SetAttributes(attributes ...kv.KeyValue) {
}
// SetAttribute does nothing.
@ -115,9 +115,9 @@ func (mockSpan) Tracer() trace.Tracer {
}
// Event does nothing.
func (mockSpan) AddEvent(ctx context.Context, name string, attrs ...core.KeyValue) {
func (mockSpan) AddEvent(ctx context.Context, name string, attrs ...kv.KeyValue) {
}
// AddEventWithTimestamp does nothing.
func (mockSpan) AddEventWithTimestamp(ctx context.Context, timestamp time.Time, name string, attrs ...core.KeyValue) {
func (mockSpan) AddEventWithTimestamp(ctx context.Context, timestamp time.Time, name string, attrs ...kv.KeyValue) {
}

View File

@ -20,7 +20,7 @@ import (
"google.golang.org/grpc/codes"
"go.opentelemetry.io/otel/api/core"
"go.opentelemetry.io/otel/api/kv"
)
type NoopSpan struct {
@ -47,7 +47,7 @@ func (NoopSpan) SetError(v bool) {
}
// SetAttributes does nothing.
func (NoopSpan) SetAttributes(attributes ...core.KeyValue) {
func (NoopSpan) SetAttributes(attributes ...kv.KeyValue) {
}
// SetAttribute does nothing.
@ -68,11 +68,11 @@ func (NoopSpan) Tracer() Tracer {
}
// AddEvent does nothing.
func (NoopSpan) AddEvent(ctx context.Context, name string, attrs ...core.KeyValue) {
func (NoopSpan) AddEvent(ctx context.Context, name string, attrs ...kv.KeyValue) {
}
// AddEventWithTimestamp does nothing.
func (NoopSpan) AddEventWithTimestamp(ctx context.Context, timestamp time.Time, name string, attrs ...core.KeyValue) {
func (NoopSpan) AddEventWithTimestamp(ctx context.Context, timestamp time.Time, name string, attrs ...kv.KeyValue) {
}
// SetName does nothing.

View File

@ -14,7 +14,7 @@
package trace
import "go.opentelemetry.io/otel/api/core"
import "go.opentelemetry.io/otel/api/kv"
type Sampler interface {
// ShouldSample returns a Decision that contains a decision whether to sample
@ -27,7 +27,7 @@ type Sampler interface {
spanID SpanID,
spanName string,
spanKind SpanKind,
attributes []core.KeyValue,
attributes []kv.KeyValue,
links []Link,
) Decision
@ -43,5 +43,5 @@ type Decision struct {
// Attributes provides insight into Sample r's decision process.
// It could be empty slice or nil if no attributes are recorded by the sampler.
Attributes []core.KeyValue
Attributes []kv.KeyValue
}

View File

@ -17,12 +17,14 @@ package testtrace
import (
"time"
"go.opentelemetry.io/otel/api/core"
"go.opentelemetry.io/otel/api/kv"
"go.opentelemetry.io/otel/api/kv/value"
)
// Event encapsulates the properties of calls to AddEvent or AddEventWithTimestamp.
type Event struct {
Timestamp time.Time
Name string
Attributes map[core.Key]core.Value
Attributes map[kv.Key]value.Value
}

View File

@ -21,16 +21,17 @@ import (
"sync"
"time"
"go.opentelemetry.io/otel/api/kv/value"
"google.golang.org/grpc/codes"
"go.opentelemetry.io/otel/api/core"
"go.opentelemetry.io/otel/api/key"
"go.opentelemetry.io/otel/api/kv"
"go.opentelemetry.io/otel/api/trace"
)
const (
errorTypeKey = core.Key("error.type")
errorMessageKey = core.Key("error.message")
errorTypeKey = kv.Key("error.type")
errorMessageKey = kv.Key("error.message")
errorEventName = "error"
)
@ -47,9 +48,9 @@ type Span struct {
endTime time.Time
statusCode codes.Code
statusMessage string
attributes map[core.Key]core.Value
attributes map[kv.Key]value.Value
events []Event
links map[trace.SpanContext][]core.KeyValue
links map[trace.SpanContext][]kv.KeyValue
}
func (s *Span) Tracer() trace.Tracer {
@ -109,11 +110,11 @@ func (s *Span) RecordError(ctx context.Context, err error, opts ...trace.ErrorOp
)
}
func (s *Span) AddEvent(ctx context.Context, name string, attrs ...core.KeyValue) {
func (s *Span) AddEvent(ctx context.Context, name string, attrs ...kv.KeyValue) {
s.AddEventWithTimestamp(ctx, time.Now(), name, attrs...)
}
func (s *Span) AddEventWithTimestamp(ctx context.Context, timestamp time.Time, name string, attrs ...core.KeyValue) {
func (s *Span) AddEventWithTimestamp(ctx context.Context, timestamp time.Time, name string, attrs ...kv.KeyValue) {
s.lock.Lock()
defer s.lock.Unlock()
@ -121,7 +122,7 @@ func (s *Span) AddEventWithTimestamp(ctx context.Context, timestamp time.Time, n
return
}
attributes := make(map[core.Key]core.Value)
attributes := make(map[kv.Key]value.Value)
for _, attr := range attrs {
attributes[attr.Key] = attr.Value
@ -165,7 +166,7 @@ func (s *Span) SetName(name string) {
s.name = name
}
func (s *Span) SetAttributes(attrs ...core.KeyValue) {
func (s *Span) SetAttributes(attrs ...kv.KeyValue) {
s.lock.Lock()
defer s.lock.Unlock()
@ -179,7 +180,7 @@ func (s *Span) SetAttributes(attrs ...core.KeyValue) {
}
func (s *Span) SetAttribute(k string, v interface{}) {
s.SetAttributes(key.Infer(k, v))
s.SetAttributes(kv.Infer(k, v))
}
// Name returns the name most recently set on the Span, either at or after creation time.
@ -198,11 +199,11 @@ func (s *Span) ParentSpanID() trace.SpanID {
// Attributes returns the attributes set on the Span, either at or after creation time.
// If the same attribute key was set multiple times, the last call will be used.
// Attributes cannot be changed after End has been called on the Span.
func (s *Span) Attributes() map[core.Key]core.Value {
func (s *Span) Attributes() map[kv.Key]value.Value {
s.lock.RLock()
defer s.lock.RUnlock()
attributes := make(map[core.Key]core.Value)
attributes := make(map[kv.Key]value.Value)
for k, v := range s.attributes {
attributes[k] = v
@ -219,11 +220,11 @@ func (s *Span) Events() []Event {
// Links returns the links set on the Span at creation time.
// If multiple links for the same SpanContext were set, the last link will be used.
func (s *Span) Links() map[trace.SpanContext][]core.KeyValue {
links := make(map[trace.SpanContext][]core.KeyValue)
func (s *Span) Links() map[trace.SpanContext][]kv.KeyValue {
links := make(map[trace.SpanContext][]kv.KeyValue)
for sc, attributes := range s.links {
links[sc] = append([]core.KeyValue{}, attributes...)
links[sc] = append([]kv.KeyValue{}, attributes...)
}
return links

View File

@ -22,10 +22,11 @@ import (
"testing"
"time"
"go.opentelemetry.io/otel/api/kv/value"
"google.golang.org/grpc/codes"
"go.opentelemetry.io/otel/api/core"
"go.opentelemetry.io/otel/api/key"
"go.opentelemetry.io/otel/api/kv"
"go.opentelemetry.io/otel/api/trace"
"go.opentelemetry.io/otel/api/trace/testtrace"
"go.opentelemetry.io/otel/internal/matchers"
@ -160,9 +161,9 @@ func TestSpan(t *testing.T) {
expectedEvents := []testtrace.Event{{
Timestamp: testTime,
Name: "error",
Attributes: map[core.Key]core.Value{
core.Key("error.type"): core.String(s.typ),
core.Key("error.message"): core.String(s.msg),
Attributes: map[kv.Key]value.Value{
kv.Key("error.type"): value.String(s.typ),
kv.Key("error.message"): value.String(s.msg),
},
}}
e.Expect(subject.Events()).ToEqual(expectedEvents)
@ -191,9 +192,9 @@ func TestSpan(t *testing.T) {
expectedEvents := []testtrace.Event{{
Timestamp: testTime,
Name: "error",
Attributes: map[core.Key]core.Value{
core.Key("error.type"): core.String("go.opentelemetry.io/otel/internal/testing.TestError"),
core.Key("error.message"): core.String(errMsg),
Attributes: map[kv.Key]value.Value{
kv.Key("error.type"): value.String("go.opentelemetry.io/otel/internal/testing.TestError"),
kv.Key("error.message"): value.String(errMsg),
},
}}
e.Expect(subject.Events()).ToEqual(expectedEvents)
@ -326,7 +327,7 @@ func TestSpan(t *testing.T) {
subject, ok := span.(*testtrace.Span)
e.Expect(ok).ToBeTrue()
e.Expect(subject.Attributes()).ToEqual(map[core.Key]core.Value{})
e.Expect(subject.Attributes()).ToEqual(map[kv.Key]value.Value{})
})
t.Run("returns the most recently set attributes", func(t *testing.T) {
@ -340,9 +341,9 @@ func TestSpan(t *testing.T) {
subject, ok := span.(*testtrace.Span)
e.Expect(ok).ToBeTrue()
attr1 := key.String("key1", "value1")
attr2 := key.String("key2", "value2")
attr3 := key.String("key3", "value3")
attr1 := kv.String("key1", "value1")
attr2 := kv.String("key2", "value2")
attr3 := kv.String("key3", "value3")
unexpectedAttr := attr2.Key.String("unexpected")
subject.SetAttributes(attr1, unexpectedAttr, attr3)
@ -366,7 +367,7 @@ func TestSpan(t *testing.T) {
subject, ok := span.(*testtrace.Span)
e.Expect(ok).ToBeTrue()
expectedAttr := key.String("key", "value")
expectedAttr := kv.String("key", "value")
subject.SetAttributes(expectedAttr)
subject.End()
@ -396,7 +397,7 @@ func TestSpan(t *testing.T) {
go func() {
defer wg.Done()
subject.SetAttributes(key.String("key", "value"))
subject.SetAttributes(kv.String("key", "value"))
}()
go func() {
@ -452,9 +453,9 @@ func TestSpan(t *testing.T) {
e.Expect(ok).ToBeTrue()
event1Name := "event1"
event1Attributes := []core.KeyValue{
key.String("event1Attr1", "foo"),
key.String("event1Attr2", "bar"),
event1Attributes := []kv.KeyValue{
kv.String("event1Attr1", "foo"),
kv.String("event1Attr2", "bar"),
}
event1Start := time.Now()
@ -463,8 +464,8 @@ func TestSpan(t *testing.T) {
event2Timestamp := time.Now().AddDate(5, 0, 0)
event2Name := "event1"
event2Attributes := []core.KeyValue{
key.String("event2Attr", "abc"),
event2Attributes := []kv.KeyValue{
kv.String("event2Attr", "abc"),
}
subject.AddEventWithTimestamp(context.Background(), event2Timestamp, event2Name, event2Attributes...)

View File

@ -19,7 +19,9 @@ import (
"sync"
"time"
"go.opentelemetry.io/otel/api/core"
"go.opentelemetry.io/otel/api/kv/value"
"go.opentelemetry.io/otel/api/kv"
"go.opentelemetry.io/otel/api/trace"
"go.opentelemetry.io/otel/internal/trace/parent"
@ -80,8 +82,8 @@ func (t *Tracer) Start(ctx context.Context, name string, opts ...trace.StartOpti
SpanID: spanID,
},
parentSpanID: parentSpanID,
attributes: make(map[core.Key]core.Value),
links: make(map[trace.SpanContext][]core.KeyValue),
attributes: make(map[kv.Key]value.Value),
links: make(map[trace.SpanContext][]kv.KeyValue),
}
span.SetName(name)

View File

@ -20,8 +20,7 @@ import (
"testing"
"time"
"go.opentelemetry.io/otel/api/core"
"go.opentelemetry.io/otel/api/key"
"go.opentelemetry.io/otel/api/kv"
"go.opentelemetry.io/otel/api/testharness"
"go.opentelemetry.io/otel/api/trace"
"go.opentelemetry.io/otel/api/trace/testtrace"
@ -61,8 +60,8 @@ func TestTracer(t *testing.T) {
e := matchers.NewExpecter(t)
attr1 := key.String("a", "1")
attr2 := key.String("b", "2")
attr1 := kv.String("a", "1")
attr2 := kv.String("b", "2")
subject := testtrace.NewTracer()
_, span := subject.Start(context.Background(), "test", trace.WithAttributes(attr1, attr2))
@ -194,14 +193,14 @@ func TestTracer(t *testing.T) {
expectedLinks := []trace.Link{
{
SpanContext: parentSpanContext,
Attributes: []core.KeyValue{
key.String("ignored-on-demand", "current"),
Attributes: []kv.KeyValue{
kv.String("ignored-on-demand", "current"),
},
},
{
SpanContext: remoteParentSpanContext,
Attributes: []core.KeyValue{
key.String("ignored-on-demand", "remote"),
Attributes: []kv.KeyValue{
kv.String("ignored-on-demand", "remote"),
},
},
}
@ -226,16 +225,16 @@ func TestTracer(t *testing.T) {
_, span := subject.Start(context.Background(), "link1")
link1 := trace.Link{
SpanContext: span.SpanContext(),
Attributes: []core.KeyValue{
key.String("a", "1"),
Attributes: []kv.KeyValue{
kv.String("a", "1"),
},
}
_, span = subject.Start(context.Background(), "link2")
link2 := trace.Link{
SpanContext: span.SpanContext(),
Attributes: []core.KeyValue{
key.String("b", "2"),
Attributes: []kv.KeyValue{
kv.String("b", "2"),
},
}
@ -268,8 +267,8 @@ func TestTracer(t *testing.T) {
e := matchers.NewExpecter(t)
attr1 := key.String("a", "1")
attr2 := key.String("b", "2")
attr1 := kv.String("a", "1")
attr2 := kv.String("b", "2")
subject := testtrace.NewTracer()
var span trace.Span

View File

@ -27,10 +27,9 @@ import (
otext "github.com/opentracing/opentracing-go/ext"
otlog "github.com/opentracing/opentracing-go/log"
otelcore "go.opentelemetry.io/otel/api/core"
otelcorrelation "go.opentelemetry.io/otel/api/correlation"
otelglobal "go.opentelemetry.io/otel/api/global"
otelkey "go.opentelemetry.io/otel/api/key"
otelcore "go.opentelemetry.io/otel/api/kv"
otelpropagation "go.opentelemetry.io/otel/api/propagation"
oteltrace "go.opentelemetry.io/otel/api/trace"
otelparent "go.opentelemetry.io/otel/internal/trace/parent"
@ -67,12 +66,12 @@ func (c *bridgeSpanContext) ForeachBaggageItem(handler func(k, v string) bool) {
func (c *bridgeSpanContext) setBaggageItem(restrictedKey, value string) {
crk := http.CanonicalHeaderKey(restrictedKey)
c.baggageItems = c.baggageItems.Apply(otelcorrelation.MapUpdate{SingleKV: otelkey.New(crk).String(value)})
c.baggageItems = c.baggageItems.Apply(otelcorrelation.MapUpdate{SingleKV: otelcore.Key(crk).String(value)})
}
func (c *bridgeSpanContext) baggageItem(restrictedKey string) string {
crk := http.CanonicalHeaderKey(restrictedKey)
val, _ := c.baggageItems.Value(otelkey.New(crk))
val, _ := c.baggageItems.Value(otelcore.Key(crk))
return val.Emit()
}
@ -373,7 +372,7 @@ func (t *BridgeTracer) correlationGetHook(ctx context.Context, m otelcorrelation
}
kv := make([]otelcore.KeyValue, 0, len(items))
for k, v := range items {
kv = append(kv, otelkey.String(k, v))
kv = append(kv, otelcore.String(k, v))
}
return m.Apply(otelcorrelation.MapUpdate{MultiKV: kv})
}
@ -559,7 +558,7 @@ func otSpanReferenceToOtelLink(bridgeSC *bridgeSpanContext, refType ot.SpanRefer
func otSpanReferenceTypeToOtelLinkAttributes(refType ot.SpanReferenceType) []otelcore.KeyValue {
return []otelcore.KeyValue{
otelkey.String("ot-span-reference-type", otSpanReferenceTypeToString(refType)),
otelcore.String("ot-span-reference-type", otSpanReferenceTypeToString(refType)),
}
}

View File

@ -23,9 +23,8 @@ import (
"google.golang.org/grpc/codes"
otelcore "go.opentelemetry.io/otel/api/core"
otelcorrelation "go.opentelemetry.io/otel/api/correlation"
otelkey "go.opentelemetry.io/otel/api/key"
otelcore "go.opentelemetry.io/otel/api/kv"
oteltrace "go.opentelemetry.io/otel/api/trace"
otelparent "go.opentelemetry.io/otel/internal/trace/parent"
@ -33,12 +32,12 @@ import (
)
var (
ComponentKey = otelkey.New("component")
ServiceKey = otelkey.New("service")
StatusCodeKey = otelkey.New("status.code")
StatusMessageKey = otelkey.New("status.message")
ErrorKey = otelkey.New("error")
NameKey = otelkey.New("name")
ComponentKey = otelcore.Key("component")
ServiceKey = otelcore.Key("service")
StatusCodeKey = otelcore.Key("status.code")
StatusMessageKey = otelcore.Key("status.message")
ErrorKey = otelcore.Key("error")
NameKey = otelcore.Key("name")
)
type MockContextKeyValue struct {
@ -240,7 +239,7 @@ func (s *MockSpan) SetAttributes(attributes ...otelcore.KeyValue) {
}
func (s *MockSpan) SetAttribute(k string, v interface{}) {
s.SetAttributes(otelkey.Infer(k, v))
s.SetAttributes(otelcore.Infer(k, v))
}
func (s *MockSpan) applyUpdate(update otelcorrelation.MapUpdate) {
@ -289,8 +288,8 @@ func (s *MockSpan) RecordError(ctx context.Context, err error, opts ...oteltrace
}
s.AddEventWithTimestamp(ctx, cfg.Timestamp, "error",
otelkey.String("error.type", reflect.TypeOf(err).String()),
otelkey.String("error.message", err.Error()),
otelcore.String("error.type", reflect.TypeOf(err).String()),
otelcore.String("error.message", err.Error()),
)
}

View File

@ -21,10 +21,9 @@ import (
ot "github.com/opentracing/opentracing-go"
otelcore "go.opentelemetry.io/otel/api/core"
otelcorrelation "go.opentelemetry.io/otel/api/correlation"
otelglobal "go.opentelemetry.io/otel/api/global"
otelkey "go.opentelemetry.io/otel/api/key"
otelcore "go.opentelemetry.io/otel/api/kv"
oteltrace "go.opentelemetry.io/otel/api/trace"
"go.opentelemetry.io/otel/bridge/opentracing/internal"
@ -590,7 +589,7 @@ func (bio *baggageInteroperationTest) addAndRecordBaggage(t *testing.T, ctx cont
value := bio.baggageItems[idx].value
otSpan.SetBaggageItem(otKey, value)
ctx = otelcorrelation.NewContext(ctx, otelkey.String(otelKey, value))
ctx = otelcorrelation.NewContext(ctx, otelcore.String(otelKey, value))
otRecording := make(map[string]string)
otSpan.Context().ForeachBaggageItem(func(key, value string) bool {

View File

@ -4,4 +4,4 @@ go 1.13
replace go.opentelemetry.io/otel => ../..
require go.opentelemetry.io/otel v0.4.3
require go.opentelemetry.io/otel v0.5.0

View File

@ -18,10 +18,9 @@ import (
"context"
"log"
"go.opentelemetry.io/otel/api/core"
"go.opentelemetry.io/otel/api/correlation"
"go.opentelemetry.io/otel/api/global"
"go.opentelemetry.io/otel/api/key"
"go.opentelemetry.io/otel/api/kv"
"go.opentelemetry.io/otel/api/metric"
"go.opentelemetry.io/otel/api/trace"
metricstdout "go.opentelemetry.io/otel/exporters/metric/stdout"
@ -31,10 +30,10 @@ import (
)
var (
fooKey = key.New("ex.com/foo")
barKey = key.New("ex.com/bar")
lemonsKey = key.New("ex.com/lemons")
anotherKey = key.New("ex.com/another")
fooKey = kv.Key("ex.com/foo")
barKey = kv.Key("ex.com/bar")
lemonsKey = kv.Key("ex.com/lemons")
anotherKey = kv.Key("ex.com/another")
)
// initTracer creates and registers trace provider instance.
@ -47,7 +46,7 @@ func initTracer() {
}
tp, err := sdktrace.NewProvider(sdktrace.WithSyncer(exp),
sdktrace.WithConfig(sdktrace.Config{DefaultSampler: sdktrace.AlwaysSample()}),
sdktrace.WithResourceAttributes(key.String("rk1", "rv11"), key.Int64("rk2", 5)))
sdktrace.WithResourceAttributes(kv.String("rk1", "rv11"), kv.Int64("rk2", 5)))
if err != nil {
log.Panicf("failed to initialize trace provider %v", err)
}
@ -72,7 +71,7 @@ func main() {
tracer := global.Tracer("ex.com/basic")
meter := global.Meter("ex.com/basic")
commonLabels := []core.KeyValue{lemonsKey.Int(10), key.String("A", "1"), key.String("B", "2"), key.String("C", "3")}
commonLabels := []kv.KeyValue{lemonsKey.Int(10), kv.String("A", "1"), kv.String("B", "2"), kv.String("C", "3")}
oneMetricCB := func(result metric.Float64ObserverResult) {
result.Observe(1, commonLabels...)
@ -95,7 +94,7 @@ func main() {
err := tracer.WithSpan(ctx, "operation", func(ctx context.Context) error {
trace.SpanFromContext(ctx).AddEvent(ctx, "Nice operation!", key.New("bogons").Int(100))
trace.SpanFromContext(ctx).AddEvent(ctx, "Nice operation!", kv.Key("bogons").Int(100))
trace.SpanFromContext(ctx).SetAttributes(anotherKey.String("yes"))

View File

@ -6,7 +6,7 @@ replace go.opentelemetry.io/otel => ../..
require (
github.com/golang/protobuf v1.3.2
go.opentelemetry.io/otel v0.4.3
go.opentelemetry.io/otel v0.5.0
golang.org/x/net v0.0.0-20190311183353-d8887717615a
google.golang.org/grpc v1.27.1
)

View File

@ -21,12 +21,13 @@ import (
"io/ioutil"
"log"
"go.opentelemetry.io/otel/api/kv"
"net/http"
"time"
"go.opentelemetry.io/otel/api/correlation"
"go.opentelemetry.io/otel/api/global"
"go.opentelemetry.io/otel/api/key"
"go.opentelemetry.io/otel/exporters/trace/stdout"
"go.opentelemetry.io/otel/plugin/httptrace"
sdktrace "go.opentelemetry.io/otel/sdk/trace"
@ -57,7 +58,7 @@ func main() {
client := http.DefaultClient
ctx := correlation.NewContext(context.Background(),
key.String("username", "donuts"),
kv.String("username", "donuts"),
)
var body []byte

View File

@ -4,4 +4,4 @@ go 1.13
replace go.opentelemetry.io/otel => ../..
require go.opentelemetry.io/otel v0.4.3
require go.opentelemetry.io/otel v0.5.0

View File

@ -8,6 +8,6 @@ replace (
)
require (
go.opentelemetry.io/otel v0.4.3
go.opentelemetry.io/otel/exporters/trace/jaeger v0.4.3
go.opentelemetry.io/otel v0.5.0
go.opentelemetry.io/otel/exporters/trace/jaeger v0.5.0
)

View File

@ -20,9 +20,8 @@ import (
"context"
"log"
"go.opentelemetry.io/otel/api/core"
"go.opentelemetry.io/otel/api/global"
"go.opentelemetry.io/otel/api/key"
"go.opentelemetry.io/otel/api/kv"
"go.opentelemetry.io/otel/exporters/trace/jaeger"
sdktrace "go.opentelemetry.io/otel/sdk/trace"
@ -35,9 +34,9 @@ func initTracer() func() {
jaeger.WithCollectorEndpoint("http://localhost:14268/api/traces"),
jaeger.WithProcess(jaeger.Process{
ServiceName: "trace-demo",
Tags: []core.KeyValue{
key.String("exporter", "jaeger"),
key.Float64("float", 312.23),
Tags: []kv.KeyValue{
kv.String("exporter", "jaeger"),
kv.Float64("float", 312.23),
},
}),
jaeger.RegisterAsGlobal(),

View File

@ -18,12 +18,12 @@ import (
"context"
"go.opentelemetry.io/otel/api/global"
"go.opentelemetry.io/otel/api/key"
"go.opentelemetry.io/otel/api/kv"
"go.opentelemetry.io/otel/api/trace"
)
var (
lemonsKey = key.New("ex.com/lemons")
lemonsKey = kv.Key("ex.com/lemons")
)
// SubOperation is an example to demonstrate the use of named tracer.

View File

@ -4,4 +4,4 @@ go 1.13
replace go.opentelemetry.io/otel => ../..
require go.opentelemetry.io/otel v0.4.3
require go.opentelemetry.io/otel v0.5.0

View File

@ -18,9 +18,10 @@ import (
"context"
"log"
"go.opentelemetry.io/otel/api/kv"
"go.opentelemetry.io/otel/api/correlation"
"go.opentelemetry.io/otel/api/global"
"go.opentelemetry.io/otel/api/key"
"go.opentelemetry.io/otel/api/trace"
"go.opentelemetry.io/otel/example/namedtracer/foo"
"go.opentelemetry.io/otel/exporters/trace/stdout"
@ -28,9 +29,9 @@ import (
)
var (
fooKey = key.New("ex.com/foo")
barKey = key.New("ex.com/bar")
anotherKey = key.New("ex.com/another")
fooKey = kv.Key("ex.com/foo")
barKey = kv.Key("ex.com/bar")
anotherKey = kv.Key("ex.com/another")
)
var tp *sdktrace.Provider
@ -66,7 +67,7 @@ func main() {
err := tracer.WithSpan(ctx, "operation", func(ctx context.Context) error {
trace.SpanFromContext(ctx).AddEvent(ctx, "Nice operation!", key.New("bogons").Int(100))
trace.SpanFromContext(ctx).AddEvent(ctx, "Nice operation!", kv.Key("bogons").Int(100))
trace.SpanFromContext(ctx).SetAttributes(anotherKey.String("yes"))

View File

@ -8,6 +8,6 @@ replace (
)
require (
go.opentelemetry.io/otel v0.4.3
go.opentelemetry.io/otel/exporters/metric/prometheus v0.4.3
go.opentelemetry.io/otel v0.5.0
go.opentelemetry.io/otel/exporters/metric/prometheus v0.5.0
)

View File

@ -21,16 +21,15 @@ import (
"sync"
"time"
"go.opentelemetry.io/otel/api/core"
"go.opentelemetry.io/otel/api/global"
"go.opentelemetry.io/otel/api/key"
"go.opentelemetry.io/otel/api/kv"
"go.opentelemetry.io/otel/api/metric"
"go.opentelemetry.io/otel/exporters/metric/prometheus"
"go.opentelemetry.io/otel/sdk/metric/controller/push"
)
var (
lemonsKey = key.New("ex.com/lemons")
lemonsKey = kv.Key("ex.com/lemons")
)
func initMeter() *push.Controller {
@ -52,7 +51,7 @@ func main() {
meter := global.Meter("ex.com/basic")
observerLock := new(sync.RWMutex)
observerValueToReport := new(float64)
observerLabelsToReport := new([]core.KeyValue)
observerLabelsToReport := new([]kv.KeyValue)
cb := func(result metric.Float64ObserverResult) {
(*observerLock).RLock()
value := *observerValueToReport
@ -67,8 +66,8 @@ func main() {
measureTwo := metric.Must(meter).NewFloat64Measure("ex.com.two")
measureThree := metric.Must(meter).NewFloat64Counter("ex.com.three")
commonLabels := []core.KeyValue{lemonsKey.Int(10), key.String("A", "1"), key.String("B", "2"), key.String("C", "3")}
notSoCommonLabels := []core.KeyValue{lemonsKey.Int(13)}
commonLabels := []kv.KeyValue{lemonsKey.Int(10), kv.String("A", "1"), kv.String("B", "2"), kv.String("C", "3")}
notSoCommonLabels := []kv.KeyValue{lemonsKey.Int(13)}
ctx := context.Background()

View File

@ -8,6 +8,6 @@ replace (
)
require (
go.opentelemetry.io/otel v0.4.3
go.opentelemetry.io/otel/exporters/trace/zipkin v0.4.3
go.opentelemetry.io/otel v0.5.0
go.opentelemetry.io/otel/exporters/trace/zipkin v0.5.0
)

View File

@ -9,6 +9,6 @@ require (
github.com/prometheus/client_golang v1.5.0
github.com/prometheus/procfs v0.0.10 // indirect
github.com/stretchr/testify v1.4.0
go.opentelemetry.io/otel v0.4.3
go.opentelemetry.io/otel v0.5.0
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527 // indirect
)

View File

@ -24,8 +24,7 @@ import (
"github.com/stretchr/testify/require"
"go.opentelemetry.io/otel/api/core"
"go.opentelemetry.io/otel/api/key"
"go.opentelemetry.io/otel/api/kv"
"go.opentelemetry.io/otel/api/metric"
"go.opentelemetry.io/otel/exporters/metric/prometheus"
"go.opentelemetry.io/otel/exporters/metric/test"
@ -51,9 +50,9 @@ func TestPrometheusExporter(t *testing.T) {
histogramMeasure := metric.NewDescriptor(
"histogram_measure", metric.MeasureKind, metric.Float64NumberKind)
labels := []core.KeyValue{
key.New("A").String("B"),
key.New("C").String("D"),
labels := []kv.KeyValue{
kv.Key("A").String("B"),
kv.Key("C").String("D"),
}
checkpointSet.AddCounter(&counter, 15.3, labels...)
@ -83,9 +82,9 @@ func TestPrometheusExporter(t *testing.T) {
expected = append(expected, `histogram_measure_count{A="B",C="D"} 4`)
expected = append(expected, `histogram_measure_sum{A="B",C="D"} 19.6`)
missingLabels := []core.KeyValue{
key.New("A").String("E"),
key.New("C").String(""),
missingLabels := []kv.KeyValue{
kv.Key("A").String("E"),
kv.Key("C").String(""),
}
checkpointSet.AddCounter(&counter, 12, missingLabels...)

View File

@ -19,8 +19,7 @@ import (
"log"
"time"
"go.opentelemetry.io/otel/api/core"
"go.opentelemetry.io/otel/api/key"
"go.opentelemetry.io/otel/api/kv"
"go.opentelemetry.io/otel/api/metric"
"go.opentelemetry.io/otel/exporters/metric/stdout"
)
@ -38,12 +37,12 @@ func ExampleNewExportPipeline() {
ctx := context.Background()
key := key.New("key")
key := kv.Key("key")
meter := pusher.Meter("example")
// Create and update a single counter:
counter := metric.Must(meter).NewInt64Counter("a.counter")
labels := []core.KeyValue{key.String("value")}
labels := []kv.KeyValue{key.String("value")}
counter.Add(ctx, 100, labels...)

View File

@ -24,8 +24,7 @@ import (
"github.com/stretchr/testify/require"
"go.opentelemetry.io/otel/api/core"
"go.opentelemetry.io/otel/api/key"
"go.opentelemetry.io/otel/api/kv"
"go.opentelemetry.io/otel/api/metric"
"go.opentelemetry.io/otel/exporters/metric/stdout"
"go.opentelemetry.io/otel/exporters/metric/test"
@ -149,7 +148,7 @@ func TestStdoutCounterFormat(t *testing.T) {
aggtest.CheckedUpdate(fix.t, cagg, metric.NewInt64Number(123), &desc)
cagg.Checkpoint(fix.ctx, &desc)
checkpointSet.Add(&desc, cagg, key.String("A", "B"), key.String("C", "D"))
checkpointSet.Add(&desc, cagg, kv.String("A", "B"), kv.String("C", "D"))
fix.Export(checkpointSet)
@ -166,7 +165,7 @@ func TestStdoutLastValueFormat(t *testing.T) {
aggtest.CheckedUpdate(fix.t, lvagg, metric.NewFloat64Number(123.456), &desc)
lvagg.Checkpoint(fix.ctx, &desc)
checkpointSet.Add(&desc, lvagg, key.String("A", "B"), key.String("C", "D"))
checkpointSet.Add(&desc, lvagg, kv.String("A", "B"), kv.String("C", "D"))
fix.Export(checkpointSet)
@ -184,7 +183,7 @@ func TestStdoutMinMaxSumCount(t *testing.T) {
aggtest.CheckedUpdate(fix.t, magg, metric.NewFloat64Number(876.543), &desc)
magg.Checkpoint(fix.ctx, &desc)
checkpointSet.Add(&desc, magg, key.String("A", "B"), key.String("C", "D"))
checkpointSet.Add(&desc, magg, kv.String("A", "B"), kv.String("C", "D"))
fix.Export(checkpointSet)
@ -207,7 +206,7 @@ func TestStdoutMeasureFormat(t *testing.T) {
magg.Checkpoint(fix.ctx, &desc)
checkpointSet.Add(&desc, magg, key.String("A", "B"), key.String("C", "D"))
checkpointSet.Add(&desc, magg, kv.String("A", "B"), kv.String("C", "D"))
fix.Export(checkpointSet)
@ -273,7 +272,7 @@ func TestStdoutLastValueNotSet(t *testing.T) {
lvagg := lastvalue.New()
lvagg.Checkpoint(fix.ctx, &desc)
checkpointSet.Add(&desc, lvagg, key.String("A", "B"), key.String("C", "D"))
checkpointSet.Add(&desc, lvagg, kv.String("A", "B"), kv.String("C", "D"))
fix.Export(checkpointSet)
@ -284,9 +283,9 @@ func TestStdoutResource(t *testing.T) {
type testCase struct {
expect string
res *resource.Resource
attrs []core.KeyValue
attrs []kv.KeyValue
}
newCase := func(expect string, res *resource.Resource, attrs ...core.KeyValue) testCase {
newCase := func(expect string, res *resource.Resource, attrs ...kv.KeyValue) testCase {
return testCase{
expect: expect,
res: res,
@ -295,23 +294,23 @@ func TestStdoutResource(t *testing.T) {
}
testCases := []testCase{
newCase("R1=V1,R2=V2,A=B,C=D",
resource.New(key.String("R1", "V1"), key.String("R2", "V2")),
key.String("A", "B"),
key.String("C", "D")),
resource.New(kv.String("R1", "V1"), kv.String("R2", "V2")),
kv.String("A", "B"),
kv.String("C", "D")),
newCase("R1=V1,R2=V2",
resource.New(key.String("R1", "V1"), key.String("R2", "V2")),
resource.New(kv.String("R1", "V1"), kv.String("R2", "V2")),
),
newCase("A=B,C=D",
nil,
key.String("A", "B"),
key.String("C", "D"),
kv.String("A", "B"),
kv.String("C", "D"),
),
// We explicitly do not de-duplicate between resources
// and metric labels in this exporter.
newCase("R1=V1,R2=V2,R1=V3,R2=V4",
resource.New(key.String("R1", "V1"), key.String("R2", "V2")),
key.String("R1", "V3"),
key.String("R2", "V4")),
resource.New(kv.String("R1", "V1"), kv.String("R2", "V2")),
kv.String("R1", "V3"),
kv.String("R2", "V4")),
}
for _, tc := range testCases {

View File

@ -18,7 +18,7 @@ import (
"context"
"errors"
"go.opentelemetry.io/otel/api/core"
"go.opentelemetry.io/otel/api/kv"
"go.opentelemetry.io/otel/api/label"
"go.opentelemetry.io/otel/api/metric"
export "go.opentelemetry.io/otel/sdk/export/metric"
@ -56,7 +56,7 @@ func (p *CheckpointSet) Reset() {
//
// If there is an existing record with the same descriptor and labels,
// the stored aggregator will be returned and should be merged.
func (p *CheckpointSet) Add(desc *metric.Descriptor, newAgg export.Aggregator, labels ...core.KeyValue) (agg export.Aggregator, added bool) {
func (p *CheckpointSet) Add(desc *metric.Descriptor, newAgg export.Aggregator, labels ...kv.KeyValue) (agg export.Aggregator, added bool) {
elabels := label.NewSet(labels...)
key := mapkey{
@ -80,23 +80,23 @@ func createNumber(desc *metric.Descriptor, v float64) metric.Number {
return metric.NewInt64Number(int64(v))
}
func (p *CheckpointSet) AddLastValue(desc *metric.Descriptor, v float64, labels ...core.KeyValue) {
func (p *CheckpointSet) AddLastValue(desc *metric.Descriptor, v float64, labels ...kv.KeyValue) {
p.updateAggregator(desc, lastvalue.New(), v, labels...)
}
func (p *CheckpointSet) AddCounter(desc *metric.Descriptor, v float64, labels ...core.KeyValue) {
func (p *CheckpointSet) AddCounter(desc *metric.Descriptor, v float64, labels ...kv.KeyValue) {
p.updateAggregator(desc, sum.New(), v, labels...)
}
func (p *CheckpointSet) AddMeasure(desc *metric.Descriptor, v float64, labels ...core.KeyValue) {
func (p *CheckpointSet) AddMeasure(desc *metric.Descriptor, v float64, labels ...kv.KeyValue) {
p.updateAggregator(desc, array.New(), v, labels...)
}
func (p *CheckpointSet) AddHistogramMeasure(desc *metric.Descriptor, boundaries []metric.Number, v float64, labels ...core.KeyValue) {
func (p *CheckpointSet) AddHistogramMeasure(desc *metric.Descriptor, boundaries []metric.Number, v float64, labels ...kv.KeyValue) {
p.updateAggregator(desc, histogram.New(desc, boundaries), v, labels...)
}
func (p *CheckpointSet) updateAggregator(desc *metric.Descriptor, newAgg export.Aggregator, v float64, labels ...core.KeyValue) {
func (p *CheckpointSet) updateAggregator(desc *metric.Descriptor, newAgg export.Aggregator, v float64, labels ...kv.KeyValue) {
ctx := context.Background()
// Updates and checkpoint the new aggregator
_ = newAgg.Update(ctx, createNumber(desc, v), desc)

View File

@ -9,7 +9,7 @@ require (
github.com/grpc-ecosystem/grpc-gateway v1.14.3 // indirect
github.com/open-telemetry/opentelemetry-proto v0.3.0
github.com/stretchr/testify v1.4.0
go.opentelemetry.io/otel v0.4.3
go.opentelemetry.io/otel v0.5.0
golang.org/x/text v0.3.2 // indirect
google.golang.org/grpc v1.27.1
)

View File

@ -17,12 +17,14 @@ package transform
import (
commonpb "github.com/open-telemetry/opentelemetry-proto/gen/go/common/v1"
"go.opentelemetry.io/otel/api/core"
"go.opentelemetry.io/otel/api/kv/value"
"go.opentelemetry.io/otel/api/kv"
"go.opentelemetry.io/otel/sdk/resource"
)
// Attributes transforms a slice of KeyValues into a slice of OTLP attribute key-values.
func Attributes(attrs []core.KeyValue) []*commonpb.AttributeKeyValue {
func Attributes(attrs []kv.KeyValue) []*commonpb.AttributeKeyValue {
if len(attrs) == 0 {
return nil
}
@ -48,33 +50,33 @@ func ResourceAttributes(resource *resource.Resource) []*commonpb.AttributeKeyVal
return out
}
func toAttribute(v core.KeyValue) *commonpb.AttributeKeyValue {
func toAttribute(v kv.KeyValue) *commonpb.AttributeKeyValue {
switch v.Value.Type() {
case core.BOOL:
case value.BOOL:
return &commonpb.AttributeKeyValue{
Key: string(v.Key),
Type: commonpb.AttributeKeyValue_BOOL,
BoolValue: v.Value.AsBool(),
}
case core.INT64, core.INT32, core.UINT32, core.UINT64:
case value.INT64, value.INT32, value.UINT32, value.UINT64:
return &commonpb.AttributeKeyValue{
Key: string(v.Key),
Type: commonpb.AttributeKeyValue_INT,
IntValue: v.Value.AsInt64(),
}
case core.FLOAT32:
case value.FLOAT32:
return &commonpb.AttributeKeyValue{
Key: string(v.Key),
Type: commonpb.AttributeKeyValue_DOUBLE,
DoubleValue: float64(v.Value.AsFloat32()),
}
case core.FLOAT64:
case value.FLOAT64:
return &commonpb.AttributeKeyValue{
Key: string(v.Key),
Type: commonpb.AttributeKeyValue_DOUBLE,
DoubleValue: v.Value.AsFloat64(),
}
case core.STRING:
case value.STRING:
return &commonpb.AttributeKeyValue{
Key: string(v.Key),
Type: commonpb.AttributeKeyValue_STRING,

View File

@ -20,28 +20,27 @@ import (
commonpb "github.com/open-telemetry/opentelemetry-proto/gen/go/common/v1"
"github.com/stretchr/testify/assert"
"go.opentelemetry.io/otel/api/core"
"go.opentelemetry.io/otel/api/key"
"go.opentelemetry.io/otel/api/kv"
)
func TestAttributes(t *testing.T) {
for _, test := range []struct {
attrs []core.KeyValue
attrs []kv.KeyValue
expected []*commonpb.AttributeKeyValue
}{
{nil, nil},
{
[]core.KeyValue{
key.Int("int to int", 123),
key.Uint("uint to int", 1234),
key.Int32("int32 to int", 12345),
key.Uint32("uint32 to int", 123456),
key.Int64("int64 to int64", 1234567),
key.Uint64("uint64 to int64", 12345678),
key.Float32("float32 to double", 3.14),
key.Float32("float64 to double", 1.61),
key.String("string to string", "string"),
key.Bool("bool to bool", true),
[]kv.KeyValue{
kv.Int("int to int", 123),
kv.Uint("uint to int", 1234),
kv.Int32("int32 to int", 12345),
kv.Uint32("uint32 to int", 123456),
kv.Int64("int64 to int64", 1234567),
kv.Uint64("uint64 to int64", 12345678),
kv.Float32("float32 to double", 3.14),
kv.Float32("float64 to double", 1.61),
kv.String("string to string", "string"),
kv.Bool("bool to bool", true),
},
[]*commonpb.AttributeKeyValue{
{

View File

@ -23,8 +23,7 @@ import (
metricpb "github.com/open-telemetry/opentelemetry-proto/gen/go/metrics/v1"
"github.com/stretchr/testify/assert"
"go.opentelemetry.io/otel/api/core"
"go.opentelemetry.io/otel/api/key"
"go.opentelemetry.io/otel/api/kv"
"go.opentelemetry.io/otel/api/label"
"go.opentelemetry.io/otel/api/metric"
"go.opentelemetry.io/otel/api/unit"
@ -35,7 +34,7 @@ import (
func TestStringKeyValues(t *testing.T) {
tests := []struct {
kvs []core.KeyValue
kvs []kv.KeyValue
expected []*commonpb.StringKeyValue
}{
{
@ -43,21 +42,21 @@ func TestStringKeyValues(t *testing.T) {
nil,
},
{
[]core.KeyValue{},
[]kv.KeyValue{},
nil,
},
{
[]core.KeyValue{
key.Bool("true", true),
key.Int64("one", 1),
key.Uint64("two", 2),
key.Float64("three", 3),
key.Int32("four", 4),
key.Uint32("five", 5),
key.Float32("six", 6),
key.Int("seven", 7),
key.Uint("eight", 8),
key.String("the", "final word"),
[]kv.KeyValue{
kv.Bool("true", true),
kv.Int64("one", 1),
kv.Uint64("two", 2),
kv.Float64("three", 3),
kv.Int32("four", 4),
kv.Uint32("five", 5),
kv.Float32("six", 6),
kv.Int("seven", 7),
kv.Uint("eight", 8),
kv.String("the", "final word"),
},
[]*commonpb.StringKeyValue{
{Key: "eight", Value: "8"},
@ -107,7 +106,7 @@ func TestMinMaxSumCountMetricDescriptor(t *testing.T) {
description string
unit unit.Unit
numberKind metric.NumberKind
labels []core.KeyValue
labels []kv.KeyValue
expected *metricpb.MetricDescriptor
}{
{
@ -116,7 +115,7 @@ func TestMinMaxSumCountMetricDescriptor(t *testing.T) {
"test-a-description",
unit.Dimensionless,
metric.Int64NumberKind,
[]core.KeyValue{},
[]kv.KeyValue{},
&metricpb.MetricDescriptor{
Name: "mmsc-test-a",
Description: "test-a-description",
@ -131,7 +130,7 @@ func TestMinMaxSumCountMetricDescriptor(t *testing.T) {
"test-b-description",
unit.Bytes,
metric.Float64NumberKind, // This shouldn't change anything.
[]core.KeyValue{key.String("A", "1")},
[]kv.KeyValue{kv.String("A", "1")},
&metricpb.MetricDescriptor{
Name: "mmsc-test-b",
Description: "test-b-description",
@ -209,7 +208,7 @@ func TestSumMetricDescriptor(t *testing.T) {
description string
unit unit.Unit
numberKind metric.NumberKind
labels []core.KeyValue
labels []kv.KeyValue
expected *metricpb.MetricDescriptor
}{
{
@ -218,7 +217,7 @@ func TestSumMetricDescriptor(t *testing.T) {
"test-a-description",
unit.Dimensionless,
metric.Int64NumberKind,
[]core.KeyValue{},
[]kv.KeyValue{},
&metricpb.MetricDescriptor{
Name: "sum-test-a",
Description: "test-a-description",
@ -233,7 +232,7 @@ func TestSumMetricDescriptor(t *testing.T) {
"test-b-description",
unit.Milliseconds,
metric.Float64NumberKind,
[]core.KeyValue{key.String("A", "1")},
[]kv.KeyValue{kv.String("A", "1")},
&metricpb.MetricDescriptor{
Name: "sum-test-b",
Description: "test-b-description",

View File

@ -19,8 +19,7 @@ import (
"github.com/stretchr/testify/assert"
"go.opentelemetry.io/otel/api/core"
"go.opentelemetry.io/otel/api/key"
"go.opentelemetry.io/otel/api/kv"
"go.opentelemetry.io/otel/sdk/resource"
)
@ -39,7 +38,7 @@ func TestEmptyResource(t *testing.T) {
*/
func TestResourceAttributes(t *testing.T) {
attrs := []core.KeyValue{key.Int("one", 1), key.Int("two", 2)}
attrs := []kv.KeyValue{kv.Int("one", 1), kv.Int("two", 2)}
got := Resource(resource.New(attrs...)).GetAttributes()
if !assert.Len(t, attrs, 2) {

View File

@ -25,8 +25,7 @@ import (
"github.com/stretchr/testify/assert"
"google.golang.org/grpc/codes"
"go.opentelemetry.io/otel/api/core"
"go.opentelemetry.io/otel/api/key"
"go.opentelemetry.io/otel/api/kv"
apitrace "go.opentelemetry.io/otel/api/trace"
export "go.opentelemetry.io/otel/sdk/export/trace"
"go.opentelemetry.io/otel/sdk/resource"
@ -75,12 +74,12 @@ func TestEmptySpanEvent(t *testing.T) {
}
func TestSpanEvent(t *testing.T) {
attrs := []core.KeyValue{key.Int("one", 1), key.Int("two", 2)}
attrs := []kv.KeyValue{kv.Int("one", 1), kv.Int("two", 2)}
now := time.Now()
got := spanEvents([]export.Event{
{
Name: "test 1",
Attributes: []core.KeyValue{},
Attributes: []kv.KeyValue{},
Time: now,
},
{
@ -119,7 +118,7 @@ func TestEmptyLinks(t *testing.T) {
}
func TestLinks(t *testing.T) {
attrs := []core.KeyValue{key.Int("one", 1), key.Int("two", 2)}
attrs := []kv.KeyValue{kv.Int("one", 1), kv.Int("two", 2)}
l := []apitrace.Link{
{},
{
@ -281,13 +280,13 @@ func TestSpanData(t *testing.T) {
EndTime: endTime,
MessageEvents: []export.Event{
{Time: startTime,
Attributes: []core.KeyValue{
key.Uint64("CompressedByteSize", 512),
Attributes: []kv.KeyValue{
kv.Uint64("CompressedByteSize", 512),
},
},
{Time: endTime,
Attributes: []core.KeyValue{
key.String("MessageEventType", "Recv"),
Attributes: []kv.KeyValue{
kv.String("MessageEventType", "Recv"),
},
},
},
@ -298,8 +297,8 @@ func TestSpanData(t *testing.T) {
SpanID: apitrace.SpanID{0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7},
TraceFlags: 0,
},
Attributes: []core.KeyValue{
key.String("LinkType", "Parent"),
Attributes: []kv.KeyValue{
kv.String("LinkType", "Parent"),
},
},
{
@ -308,21 +307,21 @@ func TestSpanData(t *testing.T) {
SpanID: apitrace.SpanID{0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7},
TraceFlags: 0,
},
Attributes: []core.KeyValue{
key.String("LinkType", "Child"),
Attributes: []kv.KeyValue{
kv.String("LinkType", "Child"),
},
},
},
StatusCode: codes.Internal,
StatusMessage: "utterly unrecognized",
HasRemoteParent: true,
Attributes: []core.KeyValue{
key.Int64("timeout_ns", 12e9),
Attributes: []kv.KeyValue{
kv.Int64("timeout_ns", 12e9),
},
DroppedAttributeCount: 1,
DroppedMessageEventCount: 2,
DroppedLinkCount: 3,
Resource: resource.New(key.String("rk1", "rv1"), key.Int64("rk2", 5)),
Resource: resource.New(kv.String("rk1", "rv1"), kv.Int64("rk2", 5)),
}
// Not checking resource as the underlying map of our Resource makes

View File

@ -26,8 +26,7 @@ import (
metricpb "github.com/open-telemetry/opentelemetry-proto/gen/go/metrics/v1"
"go.opentelemetry.io/otel/api/core"
"go.opentelemetry.io/otel/api/key"
"go.opentelemetry.io/otel/api/kv"
"go.opentelemetry.io/otel/api/metric"
metricapi "go.opentelemetry.io/otel/api/metric"
"go.opentelemetry.io/otel/exporters/otlp"
@ -87,13 +86,13 @@ func newExporterEndToEndTest(t *testing.T, additionalOpts []otlp.ExporterOption)
),
}
tp1, err := sdktrace.NewProvider(append(pOpts,
sdktrace.WithResourceAttributes(key.String("rk1", "rv11)"),
key.Int64("rk2", 5)))...)
sdktrace.WithResourceAttributes(kv.String("rk1", "rv11)"),
kv.Int64("rk2", 5)))...)
assert.NoError(t, err)
tp2, err := sdktrace.NewProvider(append(pOpts,
sdktrace.WithResourceAttributes(key.String("rk1", "rv12)"),
key.Float32("rk3", 6.5)))...)
sdktrace.WithResourceAttributes(kv.String("rk1", "rv12)"),
kv.Float32("rk3", 6.5)))...)
assert.NoError(t, err)
tr1 := tp1.Tracer("test-tracer1")
@ -102,11 +101,11 @@ func newExporterEndToEndTest(t *testing.T, additionalOpts []otlp.ExporterOption)
m := 4
for i := 0; i < m; i++ {
_, span := tr1.Start(context.Background(), "AlwaysSample")
span.SetAttributes(key.Int64("i", int64(i)))
span.SetAttributes(kv.Int64("i", int64(i)))
span.End()
_, span = tr2.Start(context.Background(), "AlwaysSample")
span.SetAttributes(key.Int64("i", int64(i)))
span.SetAttributes(kv.Int64("i", int64(i)))
span.End()
}
@ -117,7 +116,7 @@ func newExporterEndToEndTest(t *testing.T, additionalOpts []otlp.ExporterOption)
ctx := context.Background()
meter := pusher.Meter("test-meter")
labels := []core.KeyValue{key.Bool("test", true)}
labels := []kv.KeyValue{kv.Bool("test", true)}
type data struct {
iKind metric.Kind

View File

@ -25,8 +25,7 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.opentelemetry.io/otel/api/core"
"go.opentelemetry.io/otel/api/key"
"go.opentelemetry.io/otel/api/kv"
"go.opentelemetry.io/otel/api/label"
"go.opentelemetry.io/otel/api/metric"
metricsdk "go.opentelemetry.io/otel/sdk/export/metric"
@ -79,15 +78,15 @@ type record struct {
nKind metric.NumberKind
resource *resource.Resource
opts []metric.Option
labels []core.KeyValue
labels []kv.KeyValue
}
var (
baseKeyValues = []core.KeyValue{key.String("host", "test.com")}
cpuKey = core.Key("CPU")
baseKeyValues = []kv.KeyValue{kv.String("host", "test.com")}
cpuKey = kv.Key("CPU")
testInstA = resource.New(key.String("instance", "tester-a"))
testInstB = resource.New(key.String("instance", "tester-b"))
testInstA = resource.New(kv.String("instance", "tester-a"))
testInstB = resource.New(kv.String("instance", "tester-b"))
cpu1MD = &metricpb.MetricDescriptor{
Name: "int64-count",
@ -714,7 +713,7 @@ func TestEmptyMetricExport(t *testing.T) {
exp.metricExporter = msc
exp.started = true
resource := resource.New(key.String("R", "S"))
resource := resource.New(kv.String("R", "S"))
for _, test := range []struct {
records []metricsdk.Record

View File

@ -27,8 +27,7 @@ import (
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"go.opentelemetry.io/otel/api/core"
"go.opentelemetry.io/otel/api/key"
"go.opentelemetry.io/otel/api/kv"
apitrace "go.opentelemetry.io/otel/api/trace"
tracesdk "go.opentelemetry.io/otel/sdk/export/trace"
"go.opentelemetry.io/otel/sdk/resource"
@ -90,13 +89,13 @@ func TestExportSpans(t *testing.T) {
Name: "parent process",
StartTime: startTime,
EndTime: endTime,
Attributes: []core.KeyValue{
key.String("user", "alice"),
key.Bool("authenticated", true),
Attributes: []kv.KeyValue{
kv.String("user", "alice"),
kv.Bool("authenticated", true),
},
StatusCode: codes.OK,
StatusMessage: "Ok",
Resource: resource.New(key.String("instance", "tester-a")),
Resource: resource.New(kv.String("instance", "tester-a")),
},
{
SpanContext: apitrace.SpanContext{
@ -109,13 +108,13 @@ func TestExportSpans(t *testing.T) {
Name: "internal process",
StartTime: startTime,
EndTime: endTime,
Attributes: []core.KeyValue{
key.String("user", "alice"),
key.Bool("authenticated", true),
Attributes: []kv.KeyValue{
kv.String("user", "alice"),
kv.Bool("authenticated", true),
},
StatusCode: codes.OK,
StatusMessage: "Ok",
Resource: resource.New(key.String("instance", "tester-a")),
Resource: resource.New(kv.String("instance", "tester-a")),
},
{
SpanContext: apitrace.SpanContext{
@ -127,13 +126,13 @@ func TestExportSpans(t *testing.T) {
Name: "parent process",
StartTime: startTime,
EndTime: endTime,
Attributes: []core.KeyValue{
key.String("user", "bob"),
key.Bool("authenticated", false),
Attributes: []kv.KeyValue{
kv.String("user", "bob"),
kv.Bool("authenticated", false),
},
StatusCode: codes.Unauthenticated,
StatusMessage: "Unauthenticated",
Resource: resource.New(key.String("instance", "tester-b")),
Resource: resource.New(kv.String("instance", "tester-b")),
},
},
[]tracepb.ResourceSpans{

View File

@ -8,7 +8,7 @@ require (
github.com/apache/thrift v0.13.0
github.com/google/go-cmp v0.4.0
github.com/stretchr/testify v1.4.0
go.opentelemetry.io/otel v0.4.3
go.opentelemetry.io/otel v0.5.0
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e // indirect
google.golang.org/api v0.20.0
google.golang.org/grpc v1.27.1

View File

@ -19,11 +19,13 @@ import (
"encoding/binary"
"log"
"go.opentelemetry.io/otel/api/kv/value"
"google.golang.org/api/support/bundler"
"google.golang.org/grpc/codes"
"go.opentelemetry.io/otel/api/core"
"go.opentelemetry.io/otel/api/global"
"go.opentelemetry.io/otel/api/kv"
gen "go.opentelemetry.io/otel/exporters/trace/jaeger/internal/gen-go/jaeger"
export "go.opentelemetry.io/otel/sdk/export/trace"
sdktrace "go.opentelemetry.io/otel/sdk/trace"
@ -176,7 +178,7 @@ type Process struct {
ServiceName string
// Tags are added to Jaeger Process exports
Tags []core.KeyValue
Tags []kv.KeyValue
}
// Exporter is an implementation of trace.SpanSyncer that uploads spans to Jaeger.
@ -271,48 +273,48 @@ func spanDataToThrift(data *export.SpanData) *gen.Span {
}
}
func keyValueToTag(kv core.KeyValue) *gen.Tag {
func keyValueToTag(keyValue kv.KeyValue) *gen.Tag {
var tag *gen.Tag
switch kv.Value.Type() {
case core.STRING:
s := kv.Value.AsString()
switch keyValue.Value.Type() {
case value.STRING:
s := keyValue.Value.AsString()
tag = &gen.Tag{
Key: string(kv.Key),
Key: string(keyValue.Key),
VStr: &s,
VType: gen.TagType_STRING,
}
case core.BOOL:
b := kv.Value.AsBool()
case value.BOOL:
b := keyValue.Value.AsBool()
tag = &gen.Tag{
Key: string(kv.Key),
Key: string(keyValue.Key),
VBool: &b,
VType: gen.TagType_BOOL,
}
case core.INT32:
i := int64(kv.Value.AsInt32())
case value.INT32:
i := int64(keyValue.Value.AsInt32())
tag = &gen.Tag{
Key: string(kv.Key),
Key: string(keyValue.Key),
VLong: &i,
VType: gen.TagType_LONG,
}
case core.INT64:
i := kv.Value.AsInt64()
case value.INT64:
i := keyValue.Value.AsInt64()
tag = &gen.Tag{
Key: string(kv.Key),
Key: string(keyValue.Key),
VLong: &i,
VType: gen.TagType_LONG,
}
case core.FLOAT32:
f := float64(kv.Value.AsFloat32())
case value.FLOAT32:
f := float64(keyValue.Value.AsFloat32())
tag = &gen.Tag{
Key: string(kv.Key),
Key: string(keyValue.Key),
VDouble: &f,
VType: gen.TagType_DOUBLE,
}
case core.FLOAT64:
f := kv.Value.AsFloat64()
case value.FLOAT64:
f := keyValue.Value.AsFloat64()
tag = &gen.Tag{
Key: string(kv.Key),
Key: string(keyValue.Key),
VDouble: &f,
VType: gen.TagType_DOUBLE,
}

View File

@ -25,9 +25,8 @@ import (
"github.com/stretchr/testify/assert"
"google.golang.org/grpc/codes"
"go.opentelemetry.io/otel/api/core"
"go.opentelemetry.io/otel/api/global"
"go.opentelemetry.io/otel/api/key"
"go.opentelemetry.io/otel/api/kv"
apitrace "go.opentelemetry.io/otel/api/trace"
gen "go.opentelemetry.io/otel/exporters/trace/jaeger/internal/gen-go/jaeger"
export "go.opentelemetry.io/otel/sdk/export/trace"
@ -94,8 +93,8 @@ func TestNewRawExporter(t *testing.T) {
WithCollectorEndpoint(collectorEndpoint),
WithProcess(Process{
ServiceName: serviceName,
Tags: []core.KeyValue{
key.String(tagKey, tagVal),
Tags: []kv.KeyValue{
kv.String(tagKey, tagVal),
},
}),
)
@ -141,8 +140,8 @@ func TestExporter_ExportSpan(t *testing.T) {
withTestCollectorEndpoint(),
WithProcess(Process{
ServiceName: serviceName,
Tags: []core.KeyValue{
key.String(tagKey, tagVal),
Tags: []kv.KeyValue{
kv.String(tagKey, tagVal),
},
}),
)
@ -230,19 +229,19 @@ func Test_spanDataToThrift(t *testing.T) {
},
},
},
Attributes: []core.KeyValue{
key.String("key", keyValue),
key.Float64("double", doubleValue),
Attributes: []kv.KeyValue{
kv.String("key", keyValue),
kv.Float64("double", doubleValue),
// Jaeger doesn't handle Uint tags, this should be ignored.
key.Uint64("ignored", 123),
kv.Uint64("ignored", 123),
},
MessageEvents: []export.Event{
{Name: eventNameValue, Attributes: []core.KeyValue{key.String("k1", keyValue)}, Time: now},
{Name: eventNameValue, Attributes: []kv.KeyValue{kv.String("k1", keyValue)}, Time: now},
},
StatusCode: codes.Unknown,
StatusMessage: statusMessage,
SpanKind: apitrace.SpanKindClient,
Resource: resource.New(key.String("rk1", rv1), key.Int64("rk2", rv2)),
Resource: resource.New(kv.String("rk1", rv1), kv.Int64("rk2", rv2)),
},
want: &gen.Span{
TraceIdLow: 651345242494996240,

View File

@ -23,8 +23,7 @@ import (
"google.golang.org/grpc/codes"
"go.opentelemetry.io/otel/api/core"
"go.opentelemetry.io/otel/api/key"
"go.opentelemetry.io/otel/api/kv"
"go.opentelemetry.io/otel/api/trace"
export "go.opentelemetry.io/otel/sdk/export/trace"
"go.opentelemetry.io/otel/sdk/resource"
@ -44,7 +43,7 @@ func TestExporter_ExportSpan(t *testing.T) {
spanID, _ := trace.SpanIDFromHex("0102030405060708")
keyValue := "value"
doubleValue := 123.456
resource := resource.New(key.String("rk1", "rv11"))
resource := resource.New(kv.String("rk1", "rv11"))
testSpan := &export.SpanData{
SpanContext: trace.SpanContext{
@ -54,13 +53,13 @@ func TestExporter_ExportSpan(t *testing.T) {
Name: "/foo",
StartTime: now,
EndTime: now,
Attributes: []core.KeyValue{
key.String("key", keyValue),
key.Float64("double", doubleValue),
Attributes: []kv.KeyValue{
kv.String("key", keyValue),
kv.Float64("double", doubleValue),
},
MessageEvents: []export.Event{
{Name: "foo", Attributes: []core.KeyValue{key.String("key", keyValue)}, Time: now},
{Name: "bar", Attributes: []core.KeyValue{key.Float64("double", doubleValue)}, Time: now},
{Name: "foo", Attributes: []kv.KeyValue{kv.String("key", keyValue)}, Time: now},
{Name: "bar", Attributes: []kv.KeyValue{kv.Float64("double", doubleValue)}, Time: now},
},
SpanKind: trace.SpanKindInternal,
StatusCode: codes.Unknown,

View File

@ -7,6 +7,6 @@ replace go.opentelemetry.io/otel => ../../..
require (
github.com/openzipkin/zipkin-go v0.2.2
github.com/stretchr/testify v1.4.0
go.opentelemetry.io/otel v0.4.3
go.opentelemetry.io/otel v0.5.0
google.golang.org/grpc v1.27.1
)

View File

@ -21,7 +21,7 @@ import (
zkmodel "github.com/openzipkin/zipkin-go/model"
"go.opentelemetry.io/otel/api/core"
"go.opentelemetry.io/otel/api/kv"
"go.opentelemetry.io/otel/api/trace"
export "go.opentelemetry.io/otel/sdk/export/trace"
)
@ -122,7 +122,7 @@ func toZipkinAnnotations(events []export.Event) []zkmodel.Annotation {
return annotations
}
func attributesToJSONMapString(attributes []core.KeyValue) string {
func attributesToJSONMapString(attributes []kv.KeyValue) string {
m := make(map[string]interface{}, len(attributes))
for _, attribute := range attributes {
m[(string)(attribute.Key)] = attribute.Value.AsInterface()

View File

@ -22,8 +22,7 @@ import (
"github.com/stretchr/testify/require"
"google.golang.org/grpc/codes"
"go.opentelemetry.io/otel/api/core"
"go.opentelemetry.io/otel/api/key"
"go.opentelemetry.io/otel/api/kv"
"go.opentelemetry.io/otel/api/trace"
export "go.opentelemetry.io/otel/sdk/export/trace"
)
@ -41,16 +40,16 @@ func TestModelConversion(t *testing.T) {
Name: "foo",
StartTime: time.Date(2020, time.March, 11, 19, 24, 0, 0, time.UTC),
EndTime: time.Date(2020, time.March, 11, 19, 25, 0, 0, time.UTC),
Attributes: []core.KeyValue{
key.Uint64("attr1", 42),
key.String("attr2", "bar"),
Attributes: []kv.KeyValue{
kv.Uint64("attr1", 42),
kv.String("attr2", "bar"),
},
MessageEvents: []export.Event{
{
Time: time.Date(2020, time.March, 11, 19, 24, 30, 0, time.UTC),
Name: "ev1",
Attributes: []core.KeyValue{
key.Uint64("eventattr1", 123),
Attributes: []kv.KeyValue{
kv.Uint64("eventattr1", 123),
},
},
{
@ -74,16 +73,16 @@ func TestModelConversion(t *testing.T) {
Name: "foo",
StartTime: time.Date(2020, time.March, 11, 19, 24, 0, 0, time.UTC),
EndTime: time.Date(2020, time.March, 11, 19, 25, 0, 0, time.UTC),
Attributes: []core.KeyValue{
key.Uint64("attr1", 42),
key.String("attr2", "bar"),
Attributes: []kv.KeyValue{
kv.Uint64("attr1", 42),
kv.String("attr2", "bar"),
},
MessageEvents: []export.Event{
{
Time: time.Date(2020, time.March, 11, 19, 24, 30, 0, time.UTC),
Name: "ev1",
Attributes: []core.KeyValue{
key.Uint64("eventattr1", 123),
Attributes: []kv.KeyValue{
kv.Uint64("eventattr1", 123),
},
},
{
@ -106,16 +105,16 @@ func TestModelConversion(t *testing.T) {
Name: "foo",
StartTime: time.Date(2020, time.March, 11, 19, 24, 0, 0, time.UTC),
EndTime: time.Date(2020, time.March, 11, 19, 25, 0, 0, time.UTC),
Attributes: []core.KeyValue{
key.Uint64("attr1", 42),
key.String("attr2", "bar"),
Attributes: []kv.KeyValue{
kv.Uint64("attr1", 42),
kv.String("attr2", "bar"),
},
MessageEvents: []export.Event{
{
Time: time.Date(2020, time.March, 11, 19, 24, 30, 0, time.UTC),
Name: "ev1",
Attributes: []core.KeyValue{
key.Uint64("eventattr1", 123),
Attributes: []kv.KeyValue{
kv.Uint64("eventattr1", 123),
},
},
{
@ -138,16 +137,16 @@ func TestModelConversion(t *testing.T) {
Name: "foo",
StartTime: time.Date(2020, time.March, 11, 19, 24, 0, 0, time.UTC),
EndTime: time.Date(2020, time.March, 11, 19, 25, 0, 0, time.UTC),
Attributes: []core.KeyValue{
key.Uint64("attr1", 42),
key.String("attr2", "bar"),
Attributes: []kv.KeyValue{
kv.Uint64("attr1", 42),
kv.String("attr2", "bar"),
},
MessageEvents: []export.Event{
{
Time: time.Date(2020, time.March, 11, 19, 24, 30, 0, time.UTC),
Name: "ev1",
Attributes: []core.KeyValue{
key.Uint64("eventattr1", 123),
Attributes: []kv.KeyValue{
kv.Uint64("eventattr1", 123),
},
},
{
@ -170,16 +169,16 @@ func TestModelConversion(t *testing.T) {
Name: "foo",
StartTime: time.Date(2020, time.March, 11, 19, 24, 0, 0, time.UTC),
EndTime: time.Date(2020, time.March, 11, 19, 25, 0, 0, time.UTC),
Attributes: []core.KeyValue{
key.Uint64("attr1", 42),
key.String("attr2", "bar"),
Attributes: []kv.KeyValue{
kv.Uint64("attr1", 42),
kv.String("attr2", "bar"),
},
MessageEvents: []export.Event{
{
Time: time.Date(2020, time.March, 11, 19, 24, 30, 0, time.UTC),
Name: "ev1",
Attributes: []core.KeyValue{
key.Uint64("eventattr1", 123),
Attributes: []kv.KeyValue{
kv.Uint64("eventattr1", 123),
},
},
{
@ -202,16 +201,16 @@ func TestModelConversion(t *testing.T) {
Name: "foo",
StartTime: time.Date(2020, time.March, 11, 19, 24, 0, 0, time.UTC),
EndTime: time.Date(2020, time.March, 11, 19, 25, 0, 0, time.UTC),
Attributes: []core.KeyValue{
key.Uint64("attr1", 42),
key.String("attr2", "bar"),
Attributes: []kv.KeyValue{
kv.Uint64("attr1", 42),
kv.String("attr2", "bar"),
},
MessageEvents: []export.Event{
{
Time: time.Date(2020, time.March, 11, 19, 24, 30, 0, time.UTC),
Name: "ev1",
Attributes: []core.KeyValue{
key.Uint64("eventattr1", 123),
Attributes: []kv.KeyValue{
kv.Uint64("eventattr1", 123),
},
},
{
@ -234,16 +233,16 @@ func TestModelConversion(t *testing.T) {
Name: "foo",
StartTime: time.Date(2020, time.March, 11, 19, 24, 0, 0, time.UTC),
EndTime: time.Date(2020, time.March, 11, 19, 25, 0, 0, time.UTC),
Attributes: []core.KeyValue{
key.Uint64("attr1", 42),
key.String("attr2", "bar"),
Attributes: []kv.KeyValue{
kv.Uint64("attr1", 42),
kv.String("attr2", "bar"),
},
MessageEvents: []export.Event{
{
Time: time.Date(2020, time.March, 11, 19, 24, 30, 0, time.UTC),
Name: "ev1",
Attributes: []core.KeyValue{
key.Uint64("eventattr1", 123),
Attributes: []kv.KeyValue{
kv.Uint64("eventattr1", 123),
},
},
{
@ -266,9 +265,9 @@ func TestModelConversion(t *testing.T) {
Name: "foo",
StartTime: time.Date(2020, time.March, 11, 19, 24, 0, 0, time.UTC),
EndTime: time.Date(2020, time.March, 11, 19, 25, 0, 0, time.UTC),
Attributes: []core.KeyValue{
key.Uint64("attr1", 42),
key.String("attr2", "bar"),
Attributes: []kv.KeyValue{
kv.Uint64("attr1", 42),
kv.String("attr2", "bar"),
},
MessageEvents: nil,
StatusCode: codes.NotFound,
@ -285,15 +284,15 @@ func TestModelConversion(t *testing.T) {
Name: "foo",
StartTime: time.Date(2020, time.March, 11, 19, 24, 0, 0, time.UTC),
EndTime: time.Date(2020, time.March, 11, 19, 25, 0, 0, time.UTC),
Attributes: []core.KeyValue{
key.String("error", "false"),
Attributes: []kv.KeyValue{
kv.String("error", "false"),
},
MessageEvents: []export.Event{
{
Time: time.Date(2020, time.March, 11, 19, 24, 30, 0, time.UTC),
Name: "ev1",
Attributes: []core.KeyValue{
key.Uint64("eventattr1", 123),
Attributes: []kv.KeyValue{
kv.Uint64("eventattr1", 123),
},
},
{

160
internal/metric/async.go Normal file
View File

@ -0,0 +1,160 @@
// 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
import (
"errors"
"fmt"
"os"
"sync"
"go.opentelemetry.io/otel/api/kv"
"go.opentelemetry.io/otel/api/metric"
)
var ErrInvalidAsyncRunner = errors.New("unknown async runner type")
// AsyncCollector is an interface used between the MeterImpl and the
// AsyncInstrumentState helper below. This interface is implemented by
// the SDK to provide support for running observer callbacks.
type AsyncCollector interface {
// CollectAsync passes a batch of observations to the MeterImpl.
CollectAsync([]kv.KeyValue, ...metric.Observation)
}
// AsyncInstrumentState manages an ordered set of asynchronous
// instruments and the distinct runners, taking into account batch
// observer callbacks.
type AsyncInstrumentState struct {
lock sync.Mutex
// errorHandler will be called in case of an invalid
// metric.AsyncRunner, i.e., one that does not implement
// either the single-or batch-runner interfaces.
errorHandler func(error)
errorOnce sync.Once
// runnerMap keeps the set of runners that will run each
// collection interval. Singletons are entered with a real
// instrument each, batch observers are entered with a nil
// instrument, ensuring that when a singleton callback is used
// repeatedly, it is excuted repeatedly in the interval, while
// when a batch callback is used repeatedly, it only executes
// once per interval.
runnerMap map[asyncRunnerPair]struct{}
// runners maintains the set of runners in the order they were
// registered.
runners []asyncRunnerPair
// instruments maintains the set of instruments in the order
// they were registered.
instruments []metric.AsyncImpl
}
// asyncRunnerPair is a map entry for Observer callback runners.
type asyncRunnerPair struct {
// runner is used as a map key here. The API ensures
// that all callbacks are pointers for this reason.
runner metric.AsyncRunner
// inst refers to a non-nil instrument when `runner` is a
// AsyncSingleRunner.
inst metric.AsyncImpl
}
// NewAsyncInstrumentState returns a new *AsyncInstrumentState, for
// use by MeterImpl to manage running the set of observer callbacks in
// the correct order.
//
// errorHandler is used to print an error condition. If errorHandler
// nil, the default error handler will be used that prints to
// os.Stderr. Only the first error is passed to the handler, after
// which errors are skipped.
func NewAsyncInstrumentState(errorHandler func(error)) *AsyncInstrumentState {
if errorHandler == nil {
errorHandler = func(err error) {
fmt.Fprintln(os.Stderr, "Metrics Async state error:", err)
}
}
return &AsyncInstrumentState{
errorHandler: errorHandler,
runnerMap: map[asyncRunnerPair]struct{}{},
}
}
// Instruments returns the asynchronous instruments managed by this
// object, the set that should be checkpointed after observers are
// run.
func (a *AsyncInstrumentState) Instruments() []metric.AsyncImpl {
a.lock.Lock()
defer a.lock.Unlock()
return a.instruments
}
// Register adds a new asynchronous instrument to by managed by this
// object. This should be called during NewAsyncInstrument() and
// assumes that errors (e.g., duplicate registration) have already
// been checked.
func (a *AsyncInstrumentState) Register(inst metric.AsyncImpl, runner metric.AsyncRunner) {
a.lock.Lock()
defer a.lock.Unlock()
a.instruments = append(a.instruments, inst)
// asyncRunnerPair reflects this callback in the asyncRunners
// list. If this is a batch runner, the instrument is nil.
// If this is a single-Observer runner, the instrument is
// included. This ensures that batch callbacks are called
// once and single callbacks are called once per instrument.
rp := asyncRunnerPair{
runner: runner,
}
if _, ok := runner.(metric.AsyncSingleRunner); ok {
rp.inst = inst
}
if _, ok := a.runnerMap[rp]; !ok {
a.runnerMap[rp] = struct{}{}
a.runners = append(a.runners, rp)
}
}
// Run executes the complete set of observer callbacks.
func (a *AsyncInstrumentState) Run(collector AsyncCollector) {
a.lock.Lock()
runners := a.runners
a.lock.Unlock()
for _, rp := range runners {
// The runner must be a single or batch runner, no
// other implementations are possible because the
// interface has un-exported methods.
if singleRunner, ok := rp.runner.(metric.AsyncSingleRunner); ok {
singleRunner.Run(rp.inst, collector.CollectAsync)
continue
}
if multiRunner, ok := rp.runner.(metric.AsyncBatchRunner); ok {
multiRunner.Run(collector.CollectAsync)
continue
}
a.errorOnce.Do(func() {
a.errorHandler(fmt.Errorf("%w: type %T (reported once)", ErrInvalidAsyncRunner, rp))
})
}
}

View File

@ -18,7 +18,7 @@ import (
"context"
"sync"
"go.opentelemetry.io/otel/api/core"
"go.opentelemetry.io/otel/api/kv"
"go.opentelemetry.io/otel/api/metric"
apimetric "go.opentelemetry.io/otel/api/metric"
"go.opentelemetry.io/otel/api/metric/registry"
@ -27,14 +27,14 @@ import (
type (
Handle struct {
Instrument *Sync
Labels []core.KeyValue
Labels []kv.KeyValue
}
Batch struct {
// Measurement needs to be aligned for 64-bit atomic operations.
Measurements []Measurement
Ctx context.Context
Labels []core.KeyValue
Labels []kv.KeyValue
LibraryName string
}
@ -46,8 +46,11 @@ type (
}
MeterImpl struct {
lock sync.Mutex
MeasurementBatches []Batch
AsyncInstruments []*Async
asyncInstruments *AsyncInstrumentState
}
Measurement struct {
@ -64,7 +67,7 @@ type (
Async struct {
Instrument
callback func(func(apimetric.Number, []core.KeyValue))
runner apimetric.AsyncRunner
}
Sync struct {
@ -91,14 +94,14 @@ func (s *Sync) Implementation() interface{} {
return s
}
func (s *Sync) Bind(labels []core.KeyValue) apimetric.BoundSyncImpl {
func (s *Sync) Bind(labels []kv.KeyValue) apimetric.BoundSyncImpl {
return &Handle{
Instrument: s,
Labels: labels,
}
}
func (s *Sync) RecordOne(ctx context.Context, number apimetric.Number, labels []core.KeyValue) {
func (s *Sync) RecordOne(ctx context.Context, number apimetric.Number, labels []kv.KeyValue) {
s.meter.doRecordSingle(ctx, labels, s, number)
}
@ -109,15 +112,17 @@ func (h *Handle) RecordOne(ctx context.Context, number apimetric.Number) {
func (h *Handle) Unbind() {
}
func (m *MeterImpl) doRecordSingle(ctx context.Context, labels []core.KeyValue, instrument apimetric.InstrumentImpl, number apimetric.Number) {
m.recordMockBatch(ctx, labels, Measurement{
func (m *MeterImpl) doRecordSingle(ctx context.Context, labels []kv.KeyValue, instrument apimetric.InstrumentImpl, number apimetric.Number) {
m.collect(ctx, labels, []Measurement{{
Instrument: instrument,
Number: number,
})
}})
}
func NewProvider() (*MeterImpl, apimetric.Provider) {
impl := &MeterImpl{}
impl := &MeterImpl{
asyncInstruments: NewAsyncInstrumentState(nil),
}
p := &MeterProvider{
impl: impl,
unique: registry.NewUniqueInstrumentMeterImpl(impl),
@ -144,6 +149,9 @@ func NewMeter() (*MeterImpl, apimetric.Meter) {
}
func (m *MeterImpl) NewSyncInstrument(descriptor metric.Descriptor) (apimetric.SyncImpl, error) {
m.lock.Lock()
defer m.lock.Unlock()
return &Sync{
Instrument{
descriptor: descriptor,
@ -152,19 +160,22 @@ func (m *MeterImpl) NewSyncInstrument(descriptor metric.Descriptor) (apimetric.S
}, nil
}
func (m *MeterImpl) NewAsyncInstrument(descriptor metric.Descriptor, callback func(func(apimetric.Number, []core.KeyValue))) (apimetric.AsyncImpl, error) {
func (m *MeterImpl) NewAsyncInstrument(descriptor metric.Descriptor, runner metric.AsyncRunner) (apimetric.AsyncImpl, error) {
m.lock.Lock()
defer m.lock.Unlock()
a := &Async{
Instrument: Instrument{
descriptor: descriptor,
meter: m,
},
callback: callback,
runner: runner,
}
m.AsyncInstruments = append(m.AsyncInstruments, a)
m.asyncInstruments.Register(a, runner)
return a, nil
}
func (m *MeterImpl) RecordBatch(ctx context.Context, labels []core.KeyValue, measurements ...apimetric.Measurement) {
func (m *MeterImpl) RecordBatch(ctx context.Context, labels []kv.KeyValue, measurements ...apimetric.Measurement) {
mm := make([]Measurement, len(measurements))
for i := 0; i < len(measurements); i++ {
m := measurements[i]
@ -173,10 +184,25 @@ func (m *MeterImpl) RecordBatch(ctx context.Context, labels []core.KeyValue, mea
Number: m.Number(),
}
}
m.recordMockBatch(ctx, labels, mm...)
m.collect(ctx, labels, mm)
}
func (m *MeterImpl) recordMockBatch(ctx context.Context, labels []core.KeyValue, measurements ...Measurement) {
func (m *MeterImpl) CollectAsync(labels []kv.KeyValue, obs ...metric.Observation) {
mm := make([]Measurement, len(obs))
for i := 0; i < len(obs); i++ {
o := obs[i]
mm[i] = Measurement{
Instrument: o.AsyncImpl(),
Number: o.Number(),
}
}
m.collect(context.Background(), labels, mm)
}
func (m *MeterImpl) collect(ctx context.Context, labels []kv.KeyValue, measurements []Measurement) {
m.lock.Lock()
defer m.lock.Unlock()
m.MeasurementBatches = append(m.MeasurementBatches, Batch{
Ctx: ctx,
Labels: labels,
@ -185,9 +211,5 @@ func (m *MeterImpl) recordMockBatch(ctx context.Context, labels []core.KeyValue,
}
func (m *MeterImpl) RunAsyncInstruments() {
for _, observer := range m.AsyncInstruments {
observer.callback(func(n apimetric.Number, labels []core.KeyValue) {
m.doRecordSingle(context.Background(), labels, observer, n)
})
}
m.asyncInstruments.Run(m)
}

View File

@ -20,7 +20,7 @@ import (
"google.golang.org/grpc/codes"
"go.opentelemetry.io/otel/api/core"
"go.opentelemetry.io/otel/api/kv"
apitrace "go.opentelemetry.io/otel/api/trace"
)
@ -33,8 +33,8 @@ type MockSpan struct {
var _ apitrace.Span = (*MockSpan)(nil)
// SpanContext returns associated core.SpanContext. If the receiver is nil it returns
// an empty core.SpanContext
// SpanContext returns associated kv.SpanContext. If the receiver is nil it returns
// an empty kv.SpanContext
func (ms *MockSpan) SpanContext() apitrace.SpanContext {
if ms == nil {
return apitrace.EmptySpanContext()
@ -56,7 +56,7 @@ func (ms *MockSpan) SetError(v bool) {
}
// SetAttributes does nothing.
func (ms *MockSpan) SetAttributes(attributes ...core.KeyValue) {
func (ms *MockSpan) SetAttributes(attributes ...kv.KeyValue) {
}
// SetAttribute does nothing.
@ -82,9 +82,9 @@ func (ms *MockSpan) Tracer() apitrace.Tracer {
}
// AddEvent does nothing.
func (ms *MockSpan) AddEvent(ctx context.Context, name string, attrs ...core.KeyValue) {
func (ms *MockSpan) AddEvent(ctx context.Context, name string, attrs ...kv.KeyValue) {
}
// AddEvent does nothing.
func (ms *MockSpan) AddEventWithTimestamp(ctx context.Context, timestamp time.Time, name string, attrs ...core.KeyValue) {
func (ms *MockSpan) AddEventWithTimestamp(ctx context.Context, timestamp time.Time, name string, attrs ...kv.KeyValue) {
}

View File

@ -17,8 +17,7 @@ package parent
import (
"context"
"go.opentelemetry.io/otel/api/core"
"go.opentelemetry.io/otel/api/key"
"go.opentelemetry.io/otel/api/kv"
"go.opentelemetry.io/otel/api/trace"
)
@ -47,8 +46,8 @@ func addLinkIfValid(links []trace.Link, sc trace.SpanContext, kind string) []tra
}
return append(links, trace.Link{
SpanContext: sc,
Attributes: []core.KeyValue{
key.String("ignored-on-demand", kind),
Attributes: []kv.KeyValue{
kv.String("ignored-on-demand", kind),
},
})
}

View File

@ -19,9 +19,9 @@ import (
"google.golang.org/grpc/metadata"
"go.opentelemetry.io/otel/api/core"
"go.opentelemetry.io/otel/api/correlation"
"go.opentelemetry.io/otel/api/global"
"go.opentelemetry.io/otel/api/kv"
"go.opentelemetry.io/otel/api/propagation"
"go.opentelemetry.io/otel/api/trace"
)
@ -54,14 +54,14 @@ func Inject(ctx context.Context, metadata *metadata.MD) {
// Extract returns the correlation context and span context that
// another service encoded in the gRPC metadata object with Inject.
// This function is meant to be used on incoming requests.
func Extract(ctx context.Context, metadata *metadata.MD) ([]core.KeyValue, trace.SpanContext) {
func Extract(ctx context.Context, metadata *metadata.MD) ([]kv.KeyValue, trace.SpanContext) {
ctx = propagation.ExtractHTTP(ctx, global.Propagators(), &metadataSupplier{
metadata: metadata,
})
spanContext := trace.RemoteSpanContextFromContext(ctx)
var correlationCtxKVs []core.KeyValue
correlation.MapFromContext(ctx).Foreach(func(kv core.KeyValue) bool {
var correlationCtxKVs []kv.KeyValue
correlation.MapFromContext(ctx).Foreach(func(kv kv.KeyValue) bool {
correlationCtxKVs = append(correlationCtxKVs, kv)
return true
})

View File

@ -28,20 +28,19 @@ import (
"google.golang.org/grpc/peer"
"google.golang.org/grpc/status"
"go.opentelemetry.io/otel/api/core"
"go.opentelemetry.io/otel/api/correlation"
"go.opentelemetry.io/otel/api/key"
"go.opentelemetry.io/otel/api/kv"
"go.opentelemetry.io/otel/api/trace"
)
var (
rpcServiceKey = key.New("rpc.service")
netPeerIPKey = key.New("net.peer.ip")
netPeerPortKey = key.New("net.peer.port")
rpcServiceKey = kv.Key("rpc.service")
netPeerIPKey = kv.Key("net.peer.ip")
netPeerPortKey = kv.Key("net.peer.port")
messageTypeKey = key.New("message.type")
messageIDKey = key.New("message.id")
messageUncompressedSizeKey = key.New("message.uncompressed_size")
messageTypeKey = kv.Key("message.type")
messageIDKey = kv.Key("message.id")
messageUncompressedSizeKey = kv.Key("message.uncompressed_size")
)
const (
@ -399,28 +398,28 @@ func StreamServerInterceptor(tracer trace.Tracer) grpc.StreamServerInterceptor {
}
}
func peerInfoFromTarget(target string) []core.KeyValue {
func peerInfoFromTarget(target string) []kv.KeyValue {
host, port, err := net.SplitHostPort(target)
if err != nil {
return []core.KeyValue{}
return []kv.KeyValue{}
}
if host == "" {
host = "127.0.0.1"
}
return []core.KeyValue{
return []kv.KeyValue{
netPeerIPKey.String(host),
netPeerPortKey.String(port),
}
}
func peerInfoFromContext(ctx context.Context) []core.KeyValue {
func peerInfoFromContext(ctx context.Context) []kv.KeyValue {
p, ok := peer.FromContext(ctx)
if !ok {
return []core.KeyValue{}
return []kv.KeyValue{}
}
return peerInfoFromTarget(p.Addr.String())

View File

@ -24,17 +24,16 @@ import (
"google.golang.org/grpc/codes"
"go.opentelemetry.io/otel/api/core"
"go.opentelemetry.io/otel/api/global"
"go.opentelemetry.io/otel/api/key"
"go.opentelemetry.io/otel/api/kv"
"go.opentelemetry.io/otel/api/trace"
)
var (
HTTPStatus = key.New("http.status")
HTTPHeaderMIME = key.New("http.mime")
HTTPRemoteAddr = key.New("http.remote")
HTTPLocalAddr = key.New("http.local")
HTTPStatus = kv.Key("http.status")
HTTPHeaderMIME = kv.Key("http.mime")
HTTPRemoteAddr = kv.Key("http.remote")
HTTPLocalAddr = kv.Key("http.local")
)
var (
@ -90,7 +89,7 @@ func NewClientTrace(ctx context.Context) *httptrace.ClientTrace {
}
}
func (ct *clientTracer) start(hook, spanName string, attrs ...core.KeyValue) {
func (ct *clientTracer) start(hook, spanName string, attrs ...kv.KeyValue) {
ct.mtx.Lock()
defer ct.mtx.Unlock()
@ -110,7 +109,7 @@ func (ct *clientTracer) start(hook, spanName string, attrs ...core.KeyValue) {
}
}
func (ct *clientTracer) end(hook string, err error, attrs ...core.KeyValue) {
func (ct *clientTracer) end(hook string, err error, attrs ...kv.KeyValue) {
ct.mtx.Lock()
defer ct.mtx.Unlock()
if ctx, ok := ct.activeHooks[hook]; ok {
@ -198,7 +197,7 @@ func (ct *clientTracer) wroteHeaderField(k string, v []string) {
if ct.span("http.headers") == nil {
ct.start("http.headers", "http.headers")
}
ct.root.SetAttributes(key.String("http."+strings.ToLower(k), sliceToString(v)))
ct.root.SetAttributes(kv.String("http."+strings.ToLower(k), sliceToString(v)))
}
func (ct *clientTracer) wroteHeaders() {

View File

@ -23,9 +23,8 @@ import (
"github.com/google/go-cmp/cmp"
"go.opentelemetry.io/otel/api/core"
"go.opentelemetry.io/otel/api/global"
"go.opentelemetry.io/otel/api/key"
"go.opentelemetry.io/otel/api/kv"
"go.opentelemetry.io/otel/plugin/httptrace"
export "go.opentelemetry.io/otel/sdk/export/trace"
sdktrace "go.opentelemetry.io/otel/sdk/trace"
@ -102,19 +101,19 @@ func TestHTTPRequestWithClientTrace(t *testing.T) {
testLen := []struct {
name string
attributes []core.KeyValue
attributes []kv.KeyValue
parent string
}{
{
name: "http.connect",
attributes: []core.KeyValue{key.String("http.remote", address.String())},
attributes: []kv.KeyValue{kv.String("http.remote", address.String())},
parent: "http.getconn",
},
{
name: "http.getconn",
attributes: []core.KeyValue{
key.String("http.remote", address.String()),
key.String("http.host", address.String()),
attributes: []kv.KeyValue{
kv.String("http.remote", address.String()),
kv.String("http.host", address.String()),
},
parent: "test",
},
@ -141,18 +140,18 @@ func TestHTTPRequestWithClientTrace(t *testing.T) {
}
}
actualAttrs := make(map[core.Key]string)
actualAttrs := make(map[kv.Key]string)
for _, attr := range span.Attributes {
actualAttrs[attr.Key] = attr.Value.Emit()
}
expectedAttrs := make(map[core.Key]string)
expectedAttrs := make(map[kv.Key]string)
for _, attr := range tl.attributes {
expectedAttrs[attr.Key] = attr.Value.Emit()
}
if tl.name == "http.getconn" {
local := key.New("http.local")
local := kv.Key("http.local")
// http.local attribute is not deterministic, just make sure it exists for `getconn`.
if _, ok := actualAttrs[local]; ok {
delete(actualAttrs, local)

View File

@ -18,30 +18,29 @@ import (
"context"
"net/http"
"go.opentelemetry.io/otel/api/core"
"go.opentelemetry.io/otel/api/correlation"
"go.opentelemetry.io/otel/api/global"
"go.opentelemetry.io/otel/api/key"
"go.opentelemetry.io/otel/api/kv"
"go.opentelemetry.io/otel/api/propagation"
"go.opentelemetry.io/otel/api/trace"
)
var (
HostKey = key.New("http.host")
URLKey = key.New("http.url")
HostKey = kv.Key("http.host")
URLKey = kv.Key("http.url")
)
// Returns the Attributes, Context Entries, and SpanContext that were encoded by Inject.
func Extract(ctx context.Context, req *http.Request) ([]core.KeyValue, []core.KeyValue, trace.SpanContext) {
func Extract(ctx context.Context, req *http.Request) ([]kv.KeyValue, []kv.KeyValue, trace.SpanContext) {
ctx = propagation.ExtractHTTP(ctx, global.Propagators(), req.Header)
attrs := []core.KeyValue{
attrs := []kv.KeyValue{
URLKey.String(req.URL.String()),
// Etc.
}
var correlationCtxKVs []core.KeyValue
correlation.MapFromContext(ctx).Foreach(func(kv core.KeyValue) bool {
var correlationCtxKVs []kv.KeyValue
correlation.MapFromContext(ctx).Foreach(func(kv kv.KeyValue) bool {
correlationCtxKVs = append(correlationCtxKVs, kv)
return true
})

View File

@ -17,24 +17,25 @@ package othttp
import (
"net/http"
"go.opentelemetry.io/otel/api/core"
"go.opentelemetry.io/otel/api/kv"
"go.opentelemetry.io/otel/api/trace"
)
// Attribute keys that can be added to a span.
const (
HostKey = core.Key("http.host") // the HTTP host (http.Request.Host)
MethodKey = core.Key("http.method") // the HTTP method (http.Request.Method)
PathKey = core.Key("http.path") // the HTTP path (http.Request.URL.Path)
URLKey = core.Key("http.url") // the HTTP URL (http.Request.URL.String())
UserAgentKey = core.Key("http.user_agent") // the HTTP user agent (http.Request.UserAgent())
RouteKey = core.Key("http.route") // the HTTP route (ex: /users/:id)
RemoteAddrKey = core.Key("http.remote_addr") // the network address of the client that sent the HTTP request (http.Request.RemoteAddr)
StatusCodeKey = core.Key("http.status_code") // if set, the HTTP status
ReadBytesKey = core.Key("http.read_bytes") // if anything was read from the request body, the total number of bytes read
ReadErrorKey = core.Key("http.read_error") // If an error occurred while reading a request, the string of the error (io.EOF is not recorded)
WroteBytesKey = core.Key("http.wrote_bytes") // if anything was written to the response writer, the total number of bytes written
WriteErrorKey = core.Key("http.write_error") // if an error occurred while writing a reply, the string of the error (io.EOF is not recorded)
HostKey = kv.Key("http.host") // the HTTP host (http.Request.Host)
MethodKey = kv.Key("http.method") // the HTTP method (http.Request.Method)
PathKey = kv.Key("http.path") // the HTTP path (http.Request.URL.Path)
URLKey = kv.Key("http.url") // the HTTP URL (http.Request.URL.String())
UserAgentKey = kv.Key("http.user_agent") // the HTTP user agent (http.Request.UserAgent())
RouteKey = kv.Key("http.route") // the HTTP route (ex: /users/:id)
RemoteAddrKey = kv.Key("http.remote_addr") // the network address of the client that sent the HTTP request (http.Request.RemoteAddr)
StatusCodeKey = kv.Key("http.status_code") // if set, the HTTP status
ReadBytesKey = kv.Key("http.read_bytes") // if anything was read from the request body, the total number of bytes read
ReadErrorKey = kv.Key("http.read_error") // If an error occurred while reading a request, the string of the error (io.EOF is not recorded)
WroteBytesKey = kv.Key("http.wrote_bytes") // if anything was written to the response writer, the total number of bytes written
WriteErrorKey = kv.Key("http.write_error") // if an error occurred while writing a reply, the string of the error (io.EOF is not recorded)
)
// Filter is a predicate used to determine whether a given http.request should

View File

@ -18,8 +18,8 @@ import (
"io"
"net/http"
"go.opentelemetry.io/otel/api/core"
"go.opentelemetry.io/otel/api/global"
"go.opentelemetry.io/otel/api/kv"
"go.opentelemetry.io/otel/api/propagation"
"go.opentelemetry.io/otel/api/trace"
)
@ -29,7 +29,7 @@ var _ http.Handler = &Handler{}
// Handler is http middleware that corresponds to the http.Handler interface and
// is designed to wrap a http.Mux (or equivalent), while individual routes on
// the mux are wrapped with WithRouteTag. A Handler will add various attributes
// to the span using the core.Keys defined in this package.
// to the span using the kv.Keys defined in this package.
type Handler struct {
operation string
handler http.Handler
@ -121,7 +121,7 @@ func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
}
func setAfterServeAttributes(span trace.Span, read, wrote, statusCode int64, rerr, werr error) {
kv := make([]core.KeyValue, 0, 5)
kv := make([]kv.KeyValue, 0, 5)
// TODO: Consider adding an event after each read and write, possibly as an
// option (defaulting to off), so as to not create needlessly verbose spans.
if read > 0 {

View File

@ -22,8 +22,9 @@ import (
"net/http"
"strings"
"go.opentelemetry.io/otel/api/kv"
"go.opentelemetry.io/otel/api/global"
"go.opentelemetry.io/otel/api/key"
"go.opentelemetry.io/otel/api/trace"
"go.opentelemetry.io/otel/exporters/trace/stdout"
"go.opentelemetry.io/otel/plugin/othttp"
@ -65,7 +66,7 @@ func ExampleNewHandler() {
case "":
err = fmt.Errorf("expected /hello/:name in %q", s)
default:
trace.SpanFromContext(ctx).SetAttributes(key.String("name", pp[1]))
trace.SpanFromContext(ctx).SetAttributes(kv.String("name", pp[1]))
}
return pp[1], err
}

View File

@ -17,19 +17,18 @@ package metric
import (
"testing"
"go.opentelemetry.io/otel/api/core"
"go.opentelemetry.io/otel/api/key"
"go.opentelemetry.io/otel/api/kv"
"go.opentelemetry.io/otel/api/label"
"github.com/stretchr/testify/require"
)
var testSlice = []core.KeyValue{
key.String("bar", "baz"),
key.Int("foo", 42),
var testSlice = []kv.KeyValue{
kv.String("bar", "baz"),
kv.Int("foo", 42),
}
func newIter(slice []core.KeyValue) label.Iterator {
func newIter(slice []kv.KeyValue) label.Iterator {
labels := label.NewSet(slice...)
return labels.Iter()
}
@ -39,17 +38,17 @@ func TestLabelIterator(t *testing.T) {
require.Equal(t, 2, iter.Len())
require.True(t, iter.Next())
require.Equal(t, key.String("bar", "baz"), iter.Label())
require.Equal(t, kv.String("bar", "baz"), iter.Label())
idx, label := iter.IndexedLabel()
require.Equal(t, 0, idx)
require.Equal(t, key.String("bar", "baz"), label)
require.Equal(t, kv.String("bar", "baz"), label)
require.Equal(t, 2, iter.Len())
require.True(t, iter.Next())
require.Equal(t, key.Int("foo", 42), iter.Label())
require.Equal(t, kv.Int("foo", 42), iter.Label())
idx, label = iter.IndexedLabel()
require.Equal(t, 1, idx)
require.Equal(t, key.Int("foo", 42), label)
require.Equal(t, kv.Int("foo", 42), label)
require.Equal(t, 2, iter.Len())
require.False(t, iter.Next())

Some files were not shown because too many files have changed in this diff Show More