mirror of
https://github.com/open-telemetry/opentelemetry-go.git
synced 2024-12-10 09:50:58 +02:00
Merge branch 'master' of https://github.com/open-telemetry/opentelemetry-go into sp-master
This commit is contained in:
commit
2c718982df
@ -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"
|
391
api/core/key.go
391
api/core/key.go
@ -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)
|
||||
}
|
@ -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()
|
||||
}
|
||||
}
|
@ -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]]
|
||||
}
|
@ -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,
|
||||
}))
|
||||
|
@ -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,
|
||||
|
@ -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",
|
||||
|
@ -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,
|
||||
}) {
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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()
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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...)
|
||||
|
@ -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))
|
||||
}
|
||||
}
|
||||
|
@ -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
160
api/kv/key.go
Normal 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
163
api/kv/key_test.go
Normal 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()
|
||||
}
|
||||
}
|
@ -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>")
|
||||
}
|
@ -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)
|
||||
}
|
31
api/kv/value/type_string.go
Normal file
31
api/kv/value/type_string.go
Normal 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
244
api/kv/value/value.go
Normal 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
137
api/kv/value/value_test.go
Normal 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),
|
||||
}
|
||||
}
|
@ -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()
|
||||
|
@ -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())
|
||||
}
|
||||
|
@ -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())
|
||||
|
@ -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()
|
||||
}
|
||||
|
@ -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...)
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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")
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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) {
|
||||
}
|
||||
|
@ -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,
|
||||
})
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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{
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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})
|
||||
}
|
||||
|
@ -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) {
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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...)
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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)),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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()),
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
|
@ -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"))
|
||||
|
||||
|
@ -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
|
||||
)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
)
|
||||
|
@ -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(),
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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"))
|
||||
|
||||
|
@ -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
|
||||
)
|
||||
|
@ -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()
|
||||
|
||||
|
@ -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
|
||||
)
|
||||
|
@ -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
|
||||
)
|
||||
|
@ -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...)
|
||||
|
@ -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...)
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
)
|
||||
|
@ -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,
|
||||
|
@ -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{
|
||||
{
|
||||
|
@ -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",
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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{
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
)
|
||||
|
@ -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()
|
||||
|
@ -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
160
internal/metric/async.go
Normal 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))
|
||||
})
|
||||
}
|
||||
}
|
@ -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)
|
||||
}
|
||||
|
@ -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) {
|
||||
}
|
||||
|
@ -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),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
@ -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
|
||||
})
|
||||
|
@ -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())
|
||||
|
@ -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() {
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
})
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user