mirror of
https://github.com/open-telemetry/opentelemetry-go.git
synced 2025-03-25 21:28:58 +02:00
Merge branch 'master' into grpctest
This commit is contained in:
commit
56547c988a
@ -12,6 +12,6 @@
|
||||
# https://help.github.com/en/articles/about-code-owners
|
||||
#
|
||||
|
||||
* @tedsuo @jmacd @paivagustavo @krnowak @lizthegrey @MrAlias @Aneurysm9
|
||||
* @jmacd @paivagustavo @lizthegrey @MrAlias @Aneurysm9 @evantorrie
|
||||
|
||||
CODEOWNERS @MrAlias @jmacd
|
||||
|
@ -139,11 +139,10 @@ https://github.com/open-telemetry/opentelemetry-specification/issues/165
|
||||
|
||||
Approvers:
|
||||
|
||||
- [Krzesimir Nowak](https://github.com/krnowak), Kinvolk
|
||||
- [Liz Fong-Jones](https://github.com/lizthegrey), Honeycomb
|
||||
- [Gustavo Silva Paiva](https://github.com/paivagustavo), Stilingue
|
||||
- [Ted Young](https://github.com/tedsuo), LightStep
|
||||
- [Anthony Mirabella](https://github.com/Aneurysm9), Centene
|
||||
- [Evan Torrie](https://github.com/evantorrie), Comcast
|
||||
|
||||
Maintainers:
|
||||
|
||||
|
6
Makefile
6
Makefile
@ -135,7 +135,11 @@ lint: $(TOOLS_DIR)/golangci-lint $(TOOLS_DIR)/misspell
|
||||
done
|
||||
|
||||
generate: $(TOOLS_DIR)/stringer
|
||||
PATH="$(TOOLS_DIR):$${PATH}" go generate ./...
|
||||
set -e; for dir in $(ALL_GO_MOD_DIRS); do \
|
||||
echo "running generators in $${dir}"; \
|
||||
(cd "$${dir}" && \
|
||||
PATH="$(TOOLS_DIR):$${PATH}" go generate ./...); \
|
||||
done
|
||||
|
||||
.PHONY: license-check
|
||||
license-check:
|
||||
|
389
api/core/key.go
389
api/core/key.go
@ -1,389 +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"
|
||||
)
|
||||
|
||||
// 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: boolToRaw(v),
|
||||
}
|
||||
}
|
||||
|
||||
// Int64 creates an INT64 Value.
|
||||
func Int64(v int64) Value {
|
||||
return Value{
|
||||
vtype: INT64,
|
||||
numeric: int64ToRaw(v),
|
||||
}
|
||||
}
|
||||
|
||||
// Uint64 creates a UINT64 Value.
|
||||
func Uint64(v uint64) Value {
|
||||
return Value{
|
||||
vtype: UINT64,
|
||||
numeric: uint64ToRaw(v),
|
||||
}
|
||||
}
|
||||
|
||||
// Float64 creates a FLOAT64 Value.
|
||||
func Float64(v float64) Value {
|
||||
return Value{
|
||||
vtype: FLOAT64,
|
||||
numeric: float64ToRaw(v),
|
||||
}
|
||||
}
|
||||
|
||||
// Int32 creates an INT32 Value.
|
||||
func Int32(v int32) Value {
|
||||
return Value{
|
||||
vtype: INT32,
|
||||
numeric: int32ToRaw(v),
|
||||
}
|
||||
}
|
||||
|
||||
// Uint32 creates a UINT32 Value.
|
||||
func Uint32(v uint32) Value {
|
||||
return Value{
|
||||
vtype: UINT32,
|
||||
numeric: uint32ToRaw(v),
|
||||
}
|
||||
}
|
||||
|
||||
// Float32 creates a FLOAT32 Value.
|
||||
func Float32(v float32) Value {
|
||||
return Value{
|
||||
vtype: FLOAT32,
|
||||
numeric: 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 rawToBool(v.numeric)
|
||||
}
|
||||
|
||||
// AsInt32 returns the int32 value. Make sure that the Value's type is
|
||||
// INT32.
|
||||
func (v Value) AsInt32() int32 {
|
||||
return rawToInt32(v.numeric)
|
||||
}
|
||||
|
||||
// AsInt64 returns the int64 value. Make sure that the Value's type is
|
||||
// INT64.
|
||||
func (v Value) AsInt64() int64 {
|
||||
return rawToInt64(v.numeric)
|
||||
}
|
||||
|
||||
// AsUint32 returns the uint32 value. Make sure that the Value's type
|
||||
// is UINT32.
|
||||
func (v Value) AsUint32() uint32 {
|
||||
return rawToUint32(v.numeric)
|
||||
}
|
||||
|
||||
// AsUint64 returns the uint64 value. Make sure that the Value's type is
|
||||
// UINT64.
|
||||
func (v Value) AsUint64() uint64 {
|
||||
return rawToUint64(v.numeric)
|
||||
}
|
||||
|
||||
// AsFloat32 returns the float32 value. Make sure that the Value's
|
||||
// type is FLOAT32.
|
||||
func (v Value) AsFloat32() float32 {
|
||||
return rawToFloat32(v.numeric)
|
||||
}
|
||||
|
||||
// AsFloat64 returns the float64 value. Make sure that the Value's
|
||||
// type is FLOAT64.
|
||||
func (v Value) AsFloat64() float64 {
|
||||
return 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,12 +19,13 @@ 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"
|
||||
)
|
||||
|
||||
const correlationContextHeader = "Correlation-Context"
|
||||
// Temporary header name until W3C finalizes format.
|
||||
// https://github.com/open-telemetry/opentelemetry-specification/blob/18b2752ebe6c7f0cdd8c7b2bcbdceb0ae3f5ad95/specification/correlationcontext/api.md#header-name
|
||||
const correlationContextHeader = "otcorrelations"
|
||||
|
||||
// CorrelationContext propagates Key:Values in W3C CorrelationContext
|
||||
// format.
|
||||
@ -44,7 +45,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 +69,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 +99,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"),
|
||||
},
|
||||
},
|
||||
}
|
||||
@ -88,7 +89,7 @@ func TestExtractValidDistributedContextFromHTTPReq(t *testing.T) {
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
req, _ := http.NewRequest("GET", "http://example.com", nil)
|
||||
req.Header.Set("Correlation-Context", tt.header)
|
||||
req.Header.Set("otcorrelations", tt.header)
|
||||
|
||||
ctx := context.Background()
|
||||
ctx = propagation.ExtractHTTP(ctx, props, req.Header)
|
||||
@ -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"
|
||||
}
|
||||
@ -132,7 +133,7 @@ func TestExtractInvalidDistributedContextFromHTTPReq(t *testing.T) {
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
req, _ := http.NewRequest("GET", "http://example.com", nil)
|
||||
req.Header.Set("Correlation-Context", tt.header)
|
||||
req.Header.Set("otcorrelations", tt.header)
|
||||
|
||||
ctx := context.Background()
|
||||
ctx = propagation.ExtractHTTP(ctx, props, req.Header)
|
||||
@ -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",
|
||||
@ -201,17 +202,17 @@ func TestInjectCorrelationContextToHTTPReq(t *testing.T) {
|
||||
ctx := correlation.ContextWithMap(context.Background(), correlation.NewMap(correlation.MapUpdate{MultiKV: tt.kvs}))
|
||||
propagation.InjectHTTP(ctx, props, req.Header)
|
||||
|
||||
gotHeader := req.Header.Get("Correlation-Context")
|
||||
gotHeader := req.Header.Get("otcorrelations")
|
||||
wantedLen := len(strings.Join(tt.wantInHeader, ","))
|
||||
if wantedLen != len(gotHeader) {
|
||||
t.Errorf(
|
||||
"%s: Inject Correlation-Context incorrect length %d != %d.", tt.name, tt.wantedLen, len(gotHeader),
|
||||
"%s: Inject otcorrelations incorrect length %d != %d.", tt.name, tt.wantedLen, len(gotHeader),
|
||||
)
|
||||
}
|
||||
for _, inHeader := range tt.wantInHeader {
|
||||
if !strings.Contains(gotHeader, inHeader) {
|
||||
t.Errorf(
|
||||
"%s: Inject Correlation-Context missing part of header: %s in %s", tt.name, inHeader, gotHeader,
|
||||
"%s: Inject otcorrelations missing part of header: %s in %s", tt.name, inHeader, gotHeader,
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -221,7 +222,7 @@ func TestInjectCorrelationContextToHTTPReq(t *testing.T) {
|
||||
|
||||
func TestTraceContextPropagator_GetAllKeys(t *testing.T) {
|
||||
var propagator correlation.CorrelationContext
|
||||
want := []string{"Correlation-Context"}
|
||||
want := []string{"otcorrelations"}
|
||||
got := propagator.GetAllKeys()
|
||||
if diff := cmp.Diff(got, want); diff != "" {
|
||||
t.Errorf("GetAllKeys: -got +want %s", diff)
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -37,7 +37,7 @@ func (*testTraceProvider) Tracer(_ string) trace.Tracer {
|
||||
}
|
||||
|
||||
func (*testMeterProvider) Meter(_ string) metric.Meter {
|
||||
return &metric.NoopMeter{}
|
||||
return metric.Meter{}
|
||||
}
|
||||
|
||||
func TestMultipleGlobalTracerProvider(t *testing.T) {
|
||||
|
@ -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"
|
||||
@ -38,9 +37,9 @@ var Must = metric.Must
|
||||
// benchFixture is copied from sdk/metric/benchmark_test.go.
|
||||
// TODO refactor to share this code.
|
||||
type benchFixture struct {
|
||||
sdk *sdk.SDK
|
||||
meter metric.Meter
|
||||
B *testing.B
|
||||
accumulator *sdk.Accumulator
|
||||
meter metric.Meter
|
||||
B *testing.B
|
||||
}
|
||||
|
||||
var _ metric.Provider = &benchFixture{}
|
||||
@ -51,8 +50,8 @@ func newFixture(b *testing.B) *benchFixture {
|
||||
B: b,
|
||||
}
|
||||
|
||||
bf.sdk = sdk.New(bf)
|
||||
bf.meter = metric.WrapMeterImpl(bf.sdk, "test")
|
||||
bf.accumulator = sdk.NewAccumulator(bf)
|
||||
bf.meter = metric.WrapMeterImpl(bf.accumulator, "test")
|
||||
return bf
|
||||
}
|
||||
|
||||
@ -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"
|
||||
)
|
||||
@ -49,22 +49,27 @@ import (
|
||||
type meterProvider struct {
|
||||
delegate metric.Provider
|
||||
|
||||
lock sync.Mutex
|
||||
meters map[string]*meter
|
||||
// lock protects `delegate` and `meters`.
|
||||
lock sync.Mutex
|
||||
|
||||
// meters maintains a unique entry for every named Meter
|
||||
// that has been registered through the global instance.
|
||||
meters map[string]*meterEntry
|
||||
}
|
||||
|
||||
type meter struct {
|
||||
delegate unsafe.Pointer // (*metric.Meter)
|
||||
|
||||
provider *meterProvider
|
||||
name string
|
||||
type meterImpl struct {
|
||||
delegate unsafe.Pointer // (*metric.MeterImpl)
|
||||
|
||||
lock sync.Mutex
|
||||
registry map[string]metric.InstrumentImpl
|
||||
syncInsts []*syncImpl
|
||||
asyncInsts []*asyncImpl
|
||||
}
|
||||
|
||||
type meterEntry struct {
|
||||
unique metric.MeterImpl
|
||||
impl meterImpl
|
||||
}
|
||||
|
||||
type instrument struct {
|
||||
descriptor metric.Descriptor
|
||||
}
|
||||
@ -73,8 +78,6 @@ type syncImpl struct {
|
||||
delegate unsafe.Pointer // (*metric.SyncImpl)
|
||||
|
||||
instrument
|
||||
|
||||
constructor func(metric.Meter) (metric.SyncImpl, error)
|
||||
}
|
||||
|
||||
type asyncImpl struct {
|
||||
@ -82,7 +85,7 @@ type asyncImpl struct {
|
||||
|
||||
instrument
|
||||
|
||||
constructor func(metric.Meter) (metric.AsyncImpl, error)
|
||||
runner metric.AsyncRunner
|
||||
}
|
||||
|
||||
// SyncImpler is implemented by all of the sync metric
|
||||
@ -101,13 +104,13 @@ type syncHandle struct {
|
||||
delegate unsafe.Pointer // (*metric.HandleImpl)
|
||||
|
||||
inst *syncImpl
|
||||
labels []core.KeyValue
|
||||
labels []kv.KeyValue
|
||||
|
||||
initialize sync.Once
|
||||
}
|
||||
|
||||
var _ metric.Provider = &meterProvider{}
|
||||
var _ metric.Meter = &meter{}
|
||||
var _ metric.MeterImpl = &meterImpl{}
|
||||
var _ metric.InstrumentImpl = &syncImpl{}
|
||||
var _ metric.BoundSyncImpl = &syncHandle{}
|
||||
var _ metric.AsyncImpl = &asyncImpl{}
|
||||
@ -120,7 +123,7 @@ func (inst *instrument) Descriptor() metric.Descriptor {
|
||||
|
||||
func newMeterProvider() *meterProvider {
|
||||
return &meterProvider{
|
||||
meters: map[string]*meter{},
|
||||
meters: map[string]*meterEntry{},
|
||||
}
|
||||
}
|
||||
|
||||
@ -129,8 +132,8 @@ func (p *meterProvider) setDelegate(provider metric.Provider) {
|
||||
defer p.lock.Unlock()
|
||||
|
||||
p.delegate = provider
|
||||
for _, m := range p.meters {
|
||||
m.setDelegate(provider)
|
||||
for name, entry := range p.meters {
|
||||
entry.impl.setDelegate(name, provider)
|
||||
}
|
||||
p.meters = nil
|
||||
}
|
||||
@ -143,29 +146,24 @@ func (p *meterProvider) Meter(name string) metric.Meter {
|
||||
return p.delegate.Meter(name)
|
||||
}
|
||||
|
||||
if exm, ok := p.meters[name]; ok {
|
||||
return exm
|
||||
}
|
||||
entry, ok := p.meters[name]
|
||||
if !ok {
|
||||
entry = &meterEntry{}
|
||||
entry.unique = registry.NewUniqueInstrumentMeterImpl(&entry.impl)
|
||||
p.meters[name] = entry
|
||||
|
||||
m := &meter{
|
||||
provider: p,
|
||||
name: name,
|
||||
registry: map[string]metric.InstrumentImpl{},
|
||||
syncInsts: []*syncImpl{},
|
||||
asyncInsts: []*asyncImpl{},
|
||||
}
|
||||
p.meters[name] = m
|
||||
return m
|
||||
return metric.WrapMeterImpl(entry.unique, name)
|
||||
}
|
||||
|
||||
// Meter interface and delegation
|
||||
|
||||
func (m *meter) setDelegate(provider metric.Provider) {
|
||||
func (m *meterImpl) setDelegate(name string, provider metric.Provider) {
|
||||
m.lock.Lock()
|
||||
defer m.lock.Unlock()
|
||||
|
||||
d := new(metric.Meter)
|
||||
*d = provider.Meter(m.name)
|
||||
d := new(metric.MeterImpl)
|
||||
*d = provider.Meter(name).MeterImpl()
|
||||
m.delegate = unsafe.Pointer(d)
|
||||
|
||||
for _, inst := range m.syncInsts {
|
||||
@ -178,49 +176,30 @@ func (m *meter) setDelegate(provider metric.Provider) {
|
||||
m.asyncInsts = nil
|
||||
}
|
||||
|
||||
func (m *meter) newSync(desc metric.Descriptor, constructor func(metric.Meter) (metric.SyncImpl, error)) (metric.SyncImpl, error) {
|
||||
func (m *meterImpl) NewSyncInstrument(desc metric.Descriptor) (metric.SyncImpl, error) {
|
||||
m.lock.Lock()
|
||||
defer m.lock.Unlock()
|
||||
|
||||
if meterPtr := (*metric.Meter)(atomic.LoadPointer(&m.delegate)); meterPtr != nil {
|
||||
return constructor(*meterPtr)
|
||||
}
|
||||
|
||||
if ex, ok := m.registry[desc.Name()]; ok {
|
||||
if !registry.Compatible(desc, ex.Descriptor()) {
|
||||
return nil, registry.NewMetricKindMismatchError(ex.Descriptor())
|
||||
}
|
||||
return ex.(metric.SyncImpl), nil
|
||||
if meterPtr := (*metric.MeterImpl)(atomic.LoadPointer(&m.delegate)); meterPtr != nil {
|
||||
return (*meterPtr).NewSyncInstrument(desc)
|
||||
}
|
||||
|
||||
inst := &syncImpl{
|
||||
instrument: instrument{
|
||||
descriptor: desc,
|
||||
},
|
||||
constructor: constructor,
|
||||
}
|
||||
m.syncInsts = append(m.syncInsts, inst)
|
||||
m.registry[desc.Name()] = inst
|
||||
return inst, nil
|
||||
}
|
||||
|
||||
func syncCheck(has SyncImpler, err error) (metric.SyncImpl, error) {
|
||||
if has != nil {
|
||||
return has.SyncImpl(), err
|
||||
}
|
||||
if err == nil {
|
||||
err = metric.ErrSDKReturnedNilImpl
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Synchronous delegation
|
||||
|
||||
func (inst *syncImpl) setDelegate(d metric.Meter) {
|
||||
func (inst *syncImpl) setDelegate(d metric.MeterImpl) {
|
||||
implPtr := new(metric.SyncImpl)
|
||||
|
||||
var err error
|
||||
*implPtr, err = inst.constructor(d)
|
||||
*implPtr, err = d.NewSyncInstrument(inst.descriptor)
|
||||
|
||||
if err != nil {
|
||||
// TODO: There is no standard way to deliver this error to the user.
|
||||
@ -240,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)
|
||||
}
|
||||
@ -264,29 +243,25 @@ func (bound *syncHandle) Unbind() {
|
||||
|
||||
// Async delegation
|
||||
|
||||
func (m *meter) newAsync(desc metric.Descriptor, constructor func(metric.Meter) (metric.AsyncImpl, error)) (metric.AsyncImpl, error) {
|
||||
func (m *meterImpl) NewAsyncInstrument(
|
||||
desc metric.Descriptor,
|
||||
runner metric.AsyncRunner,
|
||||
) (metric.AsyncImpl, error) {
|
||||
|
||||
m.lock.Lock()
|
||||
defer m.lock.Unlock()
|
||||
|
||||
if meterPtr := (*metric.Meter)(atomic.LoadPointer(&m.delegate)); meterPtr != nil {
|
||||
return constructor(*meterPtr)
|
||||
}
|
||||
|
||||
if ex, ok := m.registry[desc.Name()]; ok {
|
||||
if !registry.Compatible(desc, ex.Descriptor()) {
|
||||
return nil, registry.NewMetricKindMismatchError(ex.Descriptor())
|
||||
}
|
||||
return ex.(metric.AsyncImpl), nil
|
||||
if meterPtr := (*metric.MeterImpl)(atomic.LoadPointer(&m.delegate)); meterPtr != nil {
|
||||
return (*meterPtr).NewAsyncInstrument(desc, runner)
|
||||
}
|
||||
|
||||
inst := &asyncImpl{
|
||||
instrument: instrument{
|
||||
descriptor: desc,
|
||||
},
|
||||
constructor: constructor,
|
||||
runner: runner,
|
||||
}
|
||||
m.asyncInsts = append(m.asyncInsts, inst)
|
||||
m.registry[desc.Name()] = inst
|
||||
return inst, nil
|
||||
}
|
||||
|
||||
@ -297,21 +272,11 @@ func (obs *asyncImpl) Implementation() interface{} {
|
||||
return obs
|
||||
}
|
||||
|
||||
func asyncCheck(has AsyncImpler, err error) (metric.AsyncImpl, error) {
|
||||
if has != nil {
|
||||
return has.AsyncImpl(), err
|
||||
}
|
||||
if err == nil {
|
||||
err = metric.ErrSDKReturnedNilImpl
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
func (obs *asyncImpl) setDelegate(d metric.Meter) {
|
||||
func (obs *asyncImpl) setDelegate(d metric.MeterImpl) {
|
||||
implPtr := new(metric.AsyncImpl)
|
||||
|
||||
var err error
|
||||
*implPtr, err = obs.constructor(d)
|
||||
*implPtr, err = d.NewAsyncInstrument(obs.descriptor, obs.runner)
|
||||
|
||||
if err != nil {
|
||||
// TODO: There is no standard way to deliver this error to the user.
|
||||
@ -326,13 +291,13 @@ func (obs *asyncImpl) setDelegate(d metric.Meter) {
|
||||
|
||||
// Metric updates
|
||||
|
||||
func (m *meter) RecordBatch(ctx context.Context, labels []core.KeyValue, measurements ...metric.Measurement) {
|
||||
if delegatePtr := (*metric.Meter)(atomic.LoadPointer(&m.delegate)); delegatePtr != nil {
|
||||
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 core.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)
|
||||
}
|
||||
@ -340,7 +305,7 @@ func (inst *syncImpl) RecordOne(ctx context.Context, number core.Number, labels
|
||||
|
||||
// Bound instrument initialization
|
||||
|
||||
func (bound *syncHandle) RecordOne(ctx context.Context, number core.Number) {
|
||||
func (bound *syncHandle) RecordOne(ctx context.Context, number metric.Number) {
|
||||
instPtr := (*metric.SyncImpl)(atomic.LoadPointer(&bound.inst.delegate))
|
||||
if instPtr == nil {
|
||||
return
|
||||
@ -363,64 +328,10 @@ func (bound *syncHandle) RecordOne(ctx context.Context, number core.Number) {
|
||||
(*implPtr).RecordOne(ctx, number)
|
||||
}
|
||||
|
||||
// Constructors
|
||||
|
||||
func (m *meter) withName(opts []metric.Option) []metric.Option {
|
||||
return append(opts, metric.WithLibraryName(m.name))
|
||||
}
|
||||
|
||||
func (m *meter) NewInt64Counter(name string, opts ...metric.Option) (metric.Int64Counter, error) {
|
||||
return metric.WrapInt64CounterInstrument(m.newSync(
|
||||
metric.NewDescriptor(name, metric.CounterKind, core.Int64NumberKind, m.withName(opts)...),
|
||||
func(other metric.Meter) (metric.SyncImpl, error) {
|
||||
return syncCheck(other.NewInt64Counter(name, opts...))
|
||||
}))
|
||||
}
|
||||
|
||||
func (m *meter) NewFloat64Counter(name string, opts ...metric.Option) (metric.Float64Counter, error) {
|
||||
return metric.WrapFloat64CounterInstrument(m.newSync(
|
||||
metric.NewDescriptor(name, metric.CounterKind, core.Float64NumberKind, m.withName(opts)...),
|
||||
func(other metric.Meter) (metric.SyncImpl, error) {
|
||||
return syncCheck(other.NewFloat64Counter(name, opts...))
|
||||
}))
|
||||
}
|
||||
|
||||
func (m *meter) NewInt64Measure(name string, opts ...metric.Option) (metric.Int64Measure, error) {
|
||||
return metric.WrapInt64MeasureInstrument(m.newSync(
|
||||
metric.NewDescriptor(name, metric.MeasureKind, core.Int64NumberKind, m.withName(opts)...),
|
||||
func(other metric.Meter) (metric.SyncImpl, error) {
|
||||
return syncCheck(other.NewInt64Measure(name, opts...))
|
||||
}))
|
||||
}
|
||||
|
||||
func (m *meter) NewFloat64Measure(name string, opts ...metric.Option) (metric.Float64Measure, error) {
|
||||
return metric.WrapFloat64MeasureInstrument(m.newSync(
|
||||
metric.NewDescriptor(name, metric.MeasureKind, core.Float64NumberKind, m.withName(opts)...),
|
||||
func(other metric.Meter) (metric.SyncImpl, error) {
|
||||
return syncCheck(other.NewFloat64Measure(name, opts...))
|
||||
}))
|
||||
}
|
||||
|
||||
func (m *meter) RegisterInt64Observer(name string, callback metric.Int64ObserverCallback, opts ...metric.Option) (metric.Int64Observer, error) {
|
||||
return metric.WrapInt64ObserverInstrument(m.newAsync(
|
||||
metric.NewDescriptor(name, metric.ObserverKind, core.Int64NumberKind, m.withName(opts)...),
|
||||
func(other metric.Meter) (metric.AsyncImpl, error) {
|
||||
return asyncCheck(other.RegisterInt64Observer(name, callback, opts...))
|
||||
}))
|
||||
}
|
||||
|
||||
func (m *meter) RegisterFloat64Observer(name string, callback metric.Float64ObserverCallback, opts ...metric.Option) (metric.Float64Observer, error) {
|
||||
return metric.WrapFloat64ObserverInstrument(m.newAsync(
|
||||
metric.NewDescriptor(name, metric.ObserverKind, core.Float64NumberKind, m.withName(opts)...),
|
||||
func(other metric.Meter) (metric.AsyncImpl, error) {
|
||||
return asyncCheck(other.RegisterFloat64Observer(name, callback, opts...))
|
||||
}))
|
||||
}
|
||||
|
||||
func AtomicFieldOffsets() map[string]uintptr {
|
||||
return map[string]uintptr{
|
||||
"meterProvider.delegate": unsafe.Offsetof(meterProvider{}.delegate),
|
||||
"meter.delegate": unsafe.Offsetof(meter{}.delegate),
|
||||
"meterImpl.delegate": unsafe.Offsetof(meterImpl{}.delegate),
|
||||
"syncImpl.delegate": unsafe.Offsetof(syncImpl{}.delegate),
|
||||
"asyncImpl.delegate": unsafe.Offsetof(asyncImpl{}.delegate),
|
||||
"syncHandle.delegate": unsafe.Offsetof(syncHandle{}.delegate),
|
||||
|
@ -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,8 +38,8 @@ import (
|
||||
type measured struct {
|
||||
Name string
|
||||
LibraryName string
|
||||
Labels map[core.Key]core.Value
|
||||
Number core.Number
|
||||
Labels map[kv.Key]value.Value
|
||||
Number metric.Number
|
||||
}
|
||||
|
||||
func asStructs(batches []metrictest.Batch) []measured {
|
||||
@ -56,16 +57,16 @@ 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
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
var asInt = core.NewInt64Number
|
||||
var asFloat = core.NewFloat64Number
|
||||
var asInt = metric.NewInt64Number
|
||||
var asFloat = metric.NewFloat64Number
|
||||
|
||||
func TestDirect(t *testing.T) {
|
||||
internal.ResetForTest()
|
||||
@ -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...)
|
||||
@ -280,15 +281,15 @@ type meterProviderWithConstructorError struct {
|
||||
}
|
||||
|
||||
type meterWithConstructorError struct {
|
||||
metric.Meter
|
||||
metric.MeterImpl
|
||||
}
|
||||
|
||||
func (m *meterProviderWithConstructorError) Meter(name string) metric.Meter {
|
||||
return &meterWithConstructorError{m.Provider.Meter(name)}
|
||||
return metric.WrapMeterImpl(&meterWithConstructorError{m.Provider.Meter(name).MeterImpl()}, name)
|
||||
}
|
||||
|
||||
func (m *meterWithConstructorError) NewInt64Counter(name string, opts ...metric.Option) (metric.Int64Counter, error) {
|
||||
return metric.Int64Counter{}, errors.New("constructor error")
|
||||
func (m *meterWithConstructorError) NewSyncInstrument(_ metric.Descriptor) (metric.SyncImpl, error) {
|
||||
return metric.NoopSync{}, errors.New("constructor error")
|
||||
}
|
||||
|
||||
func TestErrorInDeferredConstructor(t *testing.T) {
|
||||
|
@ -12,80 +12,80 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package core
|
||||
package internal
|
||||
|
||||
import (
|
||||
"math"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func boolToRaw(b bool) uint64 {
|
||||
func BoolToRaw(b bool) uint64 {
|
||||
if b {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func rawToBool(r uint64) bool {
|
||||
func RawToBool(r uint64) bool {
|
||||
return r != 0
|
||||
}
|
||||
|
||||
func int64ToRaw(i int64) uint64 {
|
||||
func Int64ToRaw(i int64) uint64 {
|
||||
return uint64(i)
|
||||
}
|
||||
|
||||
func rawToInt64(r uint64) int64 {
|
||||
func RawToInt64(r uint64) int64 {
|
||||
return int64(r)
|
||||
}
|
||||
|
||||
func uint64ToRaw(u uint64) uint64 {
|
||||
func Uint64ToRaw(u uint64) uint64 {
|
||||
return u
|
||||
}
|
||||
|
||||
func rawToUint64(r uint64) uint64 {
|
||||
func RawToUint64(r uint64) uint64 {
|
||||
return r
|
||||
}
|
||||
|
||||
func float64ToRaw(f float64) uint64 {
|
||||
func Float64ToRaw(f float64) uint64 {
|
||||
return math.Float64bits(f)
|
||||
}
|
||||
|
||||
func rawToFloat64(r uint64) float64 {
|
||||
func RawToFloat64(r uint64) float64 {
|
||||
return math.Float64frombits(r)
|
||||
}
|
||||
|
||||
func int32ToRaw(i int32) uint64 {
|
||||
func Int32ToRaw(i int32) uint64 {
|
||||
return uint64(i)
|
||||
}
|
||||
|
||||
func rawToInt32(r uint64) int32 {
|
||||
func RawToInt32(r uint64) int32 {
|
||||
return int32(r)
|
||||
}
|
||||
|
||||
func uint32ToRaw(u uint32) uint64 {
|
||||
func Uint32ToRaw(u uint32) uint64 {
|
||||
return uint64(u)
|
||||
}
|
||||
|
||||
func rawToUint32(r uint64) uint32 {
|
||||
func RawToUint32(r uint64) uint32 {
|
||||
return uint32(r)
|
||||
}
|
||||
|
||||
func float32ToRaw(f float32) uint64 {
|
||||
return uint32ToRaw(math.Float32bits(f))
|
||||
func Float32ToRaw(f float32) uint64 {
|
||||
return Uint32ToRaw(math.Float32bits(f))
|
||||
}
|
||||
|
||||
func rawToFloat32(r uint64) float32 {
|
||||
return math.Float32frombits(rawToUint32(r))
|
||||
func RawToFloat32(r uint64) float32 {
|
||||
return math.Float32frombits(RawToUint32(r))
|
||||
}
|
||||
|
||||
func rawPtrToFloat64Ptr(r *uint64) *float64 {
|
||||
func RawPtrToFloat64Ptr(r *uint64) *float64 {
|
||||
return (*float64)(unsafe.Pointer(r))
|
||||
}
|
||||
|
||||
func rawPtrToInt64Ptr(r *uint64) *int64 {
|
||||
func RawPtrToInt64Ptr(r *uint64) *int64 {
|
||||
return (*int64)(unsafe.Pointer(r))
|
||||
}
|
||||
|
||||
func rawPtrToUint64Ptr(r *uint64) *uint64 {
|
||||
func RawPtrToUint64Ptr(r *uint64) *uint64 {
|
||||
return r
|
||||
}
|
@ -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...)
|
||||
|
||||
|
@ -1,210 +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.
|
||||
|
||||
//go:generate stringer -type=Kind
|
||||
|
||||
package metric
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"go.opentelemetry.io/otel/api/core"
|
||||
"go.opentelemetry.io/otel/api/unit"
|
||||
)
|
||||
|
||||
// Provider supports named Meter instances.
|
||||
type Provider interface {
|
||||
// Meter gets a named Meter interface. If the name is an
|
||||
// empty string, the provider uses a default name.
|
||||
Meter(name string) Meter
|
||||
}
|
||||
|
||||
// Config contains some options for metrics of any kind.
|
||||
type Config struct {
|
||||
// Description is an optional field describing the metric
|
||||
// instrument.
|
||||
Description string
|
||||
// Unit is an optional field describing the metric instrument.
|
||||
Unit unit.Unit
|
||||
// LibraryName is the name given to the Meter that created
|
||||
// this instrument. See `Provider`.
|
||||
LibraryName string
|
||||
}
|
||||
|
||||
// Option is an interface for applying metric options.
|
||||
type Option interface {
|
||||
// Apply is used to set the Option value of a Config.
|
||||
Apply(*Config)
|
||||
}
|
||||
|
||||
// Measurement is used for reporting a batch of metric
|
||||
// values. Instances of this type should be created by instruments
|
||||
// (e.g., Int64Counter.Measurement()).
|
||||
type Measurement struct {
|
||||
// number needs to be aligned for 64-bit atomic operations.
|
||||
number core.Number
|
||||
instrument SyncImpl
|
||||
}
|
||||
|
||||
// SyncImpl returns the instrument that created this measurement.
|
||||
// This returns an implementation-level object for use by the SDK,
|
||||
// users should not refer to this.
|
||||
func (m Measurement) SyncImpl() SyncImpl {
|
||||
return m.instrument
|
||||
}
|
||||
|
||||
// Number returns a number recorded in this measurement.
|
||||
func (m Measurement) Number() core.Number {
|
||||
return m.number
|
||||
}
|
||||
|
||||
// Kind describes the kind of instrument.
|
||||
type Kind int8
|
||||
|
||||
const (
|
||||
// MeasureKind indicates a Measure instrument.
|
||||
MeasureKind Kind = iota
|
||||
// ObserverKind indicates an Observer instrument.
|
||||
ObserverKind
|
||||
// CounterKind indicates a Counter instrument.
|
||||
CounterKind
|
||||
)
|
||||
|
||||
// Descriptor contains all the settings that describe an instrument,
|
||||
// including its name, metric kind, number kind, and the configurable
|
||||
// options.
|
||||
type Descriptor struct {
|
||||
name string
|
||||
kind Kind
|
||||
numberKind core.NumberKind
|
||||
config Config
|
||||
}
|
||||
|
||||
// NewDescriptor returns a Descriptor with the given contents.
|
||||
func NewDescriptor(name string, mkind Kind, nkind core.NumberKind, opts ...Option) Descriptor {
|
||||
return Descriptor{
|
||||
name: name,
|
||||
kind: mkind,
|
||||
numberKind: nkind,
|
||||
config: Configure(opts),
|
||||
}
|
||||
}
|
||||
|
||||
// Name returns the metric instrument's name.
|
||||
func (d Descriptor) Name() string {
|
||||
return d.name
|
||||
}
|
||||
|
||||
// MetricKind returns the specific kind of instrument.
|
||||
func (d Descriptor) MetricKind() Kind {
|
||||
return d.kind
|
||||
}
|
||||
|
||||
// Description provides a human-readable description of the metric
|
||||
// instrument.
|
||||
func (d Descriptor) Description() string {
|
||||
return d.config.Description
|
||||
}
|
||||
|
||||
// Unit describes the units of the metric instrument. Unitless
|
||||
// metrics return the empty string.
|
||||
func (d Descriptor) Unit() unit.Unit {
|
||||
return d.config.Unit
|
||||
}
|
||||
|
||||
// NumberKind returns whether this instrument is declared over int64,
|
||||
// float64, or uint64 values.
|
||||
func (d Descriptor) NumberKind() core.NumberKind {
|
||||
return d.numberKind
|
||||
}
|
||||
|
||||
// LibraryName returns the metric instrument's library name, typically
|
||||
// given via a call to Provider.Meter().
|
||||
func (d Descriptor) LibraryName() string {
|
||||
return d.config.LibraryName
|
||||
}
|
||||
|
||||
// Meter is an interface to the metrics portion of the OpenTelemetry SDK.
|
||||
type Meter interface {
|
||||
// RecordBatch atomically records a batch of measurements.
|
||||
RecordBatch(context.Context, []core.KeyValue, ...Measurement)
|
||||
|
||||
// All instrument constructors may return an error for
|
||||
// conditions such as:
|
||||
// `name` is an empty string
|
||||
// `name` was previously registered as a different kind of instrument
|
||||
// for a given named `Meter`.
|
||||
|
||||
// NewInt64Counter creates a new integral counter with a given
|
||||
// name and customized with passed options.
|
||||
NewInt64Counter(name string, opts ...Option) (Int64Counter, error)
|
||||
// NewFloat64Counter creates a new floating point counter with
|
||||
// a given name and customized with passed options.
|
||||
NewFloat64Counter(name string, opts ...Option) (Float64Counter, error)
|
||||
// NewInt64Measure creates a new integral measure with a given
|
||||
// name and customized with passed options.
|
||||
NewInt64Measure(name string, opts ...Option) (Int64Measure, error)
|
||||
// NewFloat64Measure creates a new floating point measure with
|
||||
// a given name and customized with passed options.
|
||||
NewFloat64Measure(name string, opts ...Option) (Float64Measure, error)
|
||||
|
||||
// RegisterInt64Observer creates a new integral observer with a
|
||||
// given name, running a given callback, and customized with passed
|
||||
// options. Callback may be nil.
|
||||
RegisterInt64Observer(name string, callback Int64ObserverCallback, opts ...Option) (Int64Observer, error)
|
||||
// RegisterFloat64Observer creates a new floating point observer
|
||||
// with a given name, running a given callback, and customized with
|
||||
// passed options. Callback may be nil.
|
||||
RegisterFloat64Observer(name string, callback Float64ObserverCallback, opts ...Option) (Float64Observer, error)
|
||||
}
|
||||
|
||||
// WithDescription applies provided description.
|
||||
func WithDescription(desc string) Option {
|
||||
return descriptionOption(desc)
|
||||
}
|
||||
|
||||
type descriptionOption string
|
||||
|
||||
func (d descriptionOption) Apply(config *Config) {
|
||||
config.Description = string(d)
|
||||
}
|
||||
|
||||
// WithUnit applies provided unit.
|
||||
func WithUnit(unit unit.Unit) Option {
|
||||
return unitOption(unit)
|
||||
}
|
||||
|
||||
type unitOption unit.Unit
|
||||
|
||||
func (u unitOption) Apply(config *Config) {
|
||||
config.Unit = unit.Unit(u)
|
||||
}
|
||||
|
||||
// WithLibraryName applies provided library name. This is meant for
|
||||
// use in `Provider` implementations that have not used
|
||||
// `WrapMeterImpl`. Implementations built using `WrapMeterImpl` have
|
||||
// instrument descriptors taken care of through this package.
|
||||
//
|
||||
// This option will have no effect when supplied by the user.
|
||||
// Provider implementations are expected to append this option after
|
||||
// the user-supplied options when building instrument descriptors.
|
||||
func WithLibraryName(name string) Option {
|
||||
return libraryNameOption(name)
|
||||
}
|
||||
|
||||
type libraryNameOption string
|
||||
|
||||
func (r libraryNameOption) Apply(config *Config) {
|
||||
config.LibraryName = string(r)
|
||||
}
|
@ -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,25 +97,25 @@ 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)
|
||||
meter.RecordBatch(ctx, labels, c.Measurement(42))
|
||||
t.Log("Testing float counter")
|
||||
checkBatches(t, ctx, labels, mockSDK, core.Float64NumberKind, c.SyncImpl())
|
||||
checkBatches(t, ctx, labels, mockSDK, metric.Float64NumberKind, c.SyncImpl())
|
||||
}
|
||||
{
|
||||
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)
|
||||
meter.RecordBatch(ctx, labels, c.Measurement(42))
|
||||
t.Log("Testing int counter")
|
||||
checkBatches(t, ctx, labels, mockSDK, core.Int64NumberKind, c.SyncImpl())
|
||||
checkBatches(t, ctx, labels, mockSDK, metric.Int64NumberKind, c.SyncImpl())
|
||||
}
|
||||
}
|
||||
|
||||
@ -125,31 +124,31 @@ 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)
|
||||
meter.RecordBatch(ctx, labels, m.Measurement(42))
|
||||
t.Log("Testing float measure")
|
||||
checkBatches(t, ctx, labels, mockSDK, core.Float64NumberKind, m.SyncImpl())
|
||||
checkBatches(t, ctx, labels, mockSDK, metric.Float64NumberKind, m.SyncImpl())
|
||||
}
|
||||
{
|
||||
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)
|
||||
meter.RecordBatch(ctx, labels, m.Measurement(42))
|
||||
t.Log("Testing int measure")
|
||||
checkBatches(t, ctx, labels, mockSDK, core.Int64NumberKind, m.SyncImpl())
|
||||
checkBatches(t, ctx, labels, mockSDK, metric.Int64NumberKind, m.SyncImpl())
|
||||
}
|
||||
}
|
||||
|
||||
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...)
|
||||
@ -157,21 +156,21 @@ func TestObserver(t *testing.T) {
|
||||
t.Log("Testing float observer")
|
||||
|
||||
mockSDK.RunAsyncInstruments()
|
||||
checkObserverBatch(t, labels, mockSDK, core.Float64NumberKind, o.AsyncImpl())
|
||||
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...)
|
||||
})
|
||||
t.Log("Testing int observer")
|
||||
mockSDK.RunAsyncInstruments()
|
||||
checkObserverBatch(t, labels, mockSDK, core.Int64NumberKind, o.AsyncImpl())
|
||||
checkObserverBatch(t, labels, mockSDK, metric.Int64NumberKind, o.AsyncImpl())
|
||||
}
|
||||
}
|
||||
|
||||
func checkBatches(t *testing.T, ctx context.Context, labels []core.KeyValue, mock *mockTest.MeterImpl, kind core.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 core.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 {
|
||||
@ -233,16 +277,16 @@ func checkObserverBatch(t *testing.T, labels []core.KeyValue, mock *mockTest.Met
|
||||
assert.Equal(t, 0, measurement.Number.CompareNumber(kind, ft))
|
||||
}
|
||||
|
||||
func fortyTwo(t *testing.T, kind core.NumberKind) core.Number {
|
||||
func fortyTwo(t *testing.T, kind metric.NumberKind) metric.Number {
|
||||
t.Helper()
|
||||
switch kind {
|
||||
case core.Int64NumberKind:
|
||||
return core.NewInt64Number(42)
|
||||
case core.Float64NumberKind:
|
||||
return core.NewFloat64Number(42)
|
||||
case metric.Int64NumberKind:
|
||||
return metric.NewInt64Number(42)
|
||||
case metric.Float64NumberKind:
|
||||
return metric.NewFloat64Number(42)
|
||||
}
|
||||
t.Errorf("Invalid value kind %q", kind)
|
||||
return core.NewInt64Number(0)
|
||||
return metric.NewInt64Number(0)
|
||||
}
|
||||
|
||||
type testWrappedMeter struct {
|
||||
@ -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(core.Number, []core.KeyValue))) (metric.AsyncImpl, error) {
|
||||
func (testWrappedMeter) NewAsyncInstrument(_ metric.Descriptor, _ metric.AsyncRunner) (metric.AsyncImpl, error) {
|
||||
return nil, errors.New("Test wrap error")
|
||||
}
|
||||
|
||||
|
177
api/metric/async.go
Normal file
177
api/metric/async.go
Normal file
@ -0,0 +1,177 @@
|
||||
// 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 "go.opentelemetry.io/otel/api/kv"
|
||||
|
||||
// The file is organized as follows:
|
||||
//
|
||||
// - Observation type
|
||||
// - Three kinds of Observer callback (int64, float64, batch)
|
||||
// - Three kinds of Observer result (int64, float64, batch)
|
||||
// - Three kinds of Observe() function (int64, float64, batch)
|
||||
// - Three kinds of AsyncRunner interface (abstract, single, batch)
|
||||
// - Two kinds of Observer constructor (int64, float64)
|
||||
// - Two kinds of Observation() function (int64, float64)
|
||||
// - Various internals
|
||||
|
||||
// Observation is used for reporting an asynchronous batch of metric
|
||||
// values. Instances of this type should be created by asynchronous
|
||||
// instruments (e.g., Int64Observer.Observation()).
|
||||
type Observation struct {
|
||||
// number needs to be aligned for 64-bit atomic operations.
|
||||
number Number
|
||||
instrument AsyncImpl
|
||||
}
|
||||
|
||||
// Int64ObserverCallback is a type of callback that integral
|
||||
// observers run.
|
||||
type Int64ObserverCallback func(Int64ObserverResult)
|
||||
|
||||
// Float64ObserverCallback is a type of callback that floating point
|
||||
// observers run.
|
||||
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)
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
// 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...)
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
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,
|
||||
})
|
||||
}
|
@ -1,116 +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 metric
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"go.opentelemetry.io/otel/api/core"
|
||||
)
|
||||
|
||||
type syncInstrument struct {
|
||||
instrument SyncImpl
|
||||
}
|
||||
|
||||
type syncBoundInstrument struct {
|
||||
boundInstrument BoundSyncImpl
|
||||
}
|
||||
|
||||
type asyncInstrument struct {
|
||||
instrument AsyncImpl
|
||||
}
|
||||
|
||||
var ErrSDKReturnedNilImpl = errors.New("SDK returned a nil implementation")
|
||||
|
||||
func (s syncInstrument) bind(labels []core.KeyValue) syncBoundInstrument {
|
||||
return newSyncBoundInstrument(s.instrument.Bind(labels))
|
||||
}
|
||||
|
||||
func (s syncInstrument) float64Measurement(value float64) Measurement {
|
||||
return newMeasurement(s.instrument, core.NewFloat64Number(value))
|
||||
}
|
||||
|
||||
func (s syncInstrument) int64Measurement(value int64) Measurement {
|
||||
return newMeasurement(s.instrument, core.NewInt64Number(value))
|
||||
}
|
||||
|
||||
func (s syncInstrument) directRecord(ctx context.Context, number core.Number, labels []core.KeyValue) {
|
||||
s.instrument.RecordOne(ctx, number, labels)
|
||||
}
|
||||
|
||||
func (s syncInstrument) SyncImpl() SyncImpl {
|
||||
return s.instrument
|
||||
}
|
||||
|
||||
func (h syncBoundInstrument) directRecord(ctx context.Context, number core.Number) {
|
||||
h.boundInstrument.RecordOne(ctx, number)
|
||||
}
|
||||
|
||||
func (h syncBoundInstrument) Unbind() {
|
||||
h.boundInstrument.Unbind()
|
||||
}
|
||||
|
||||
func (a asyncInstrument) AsyncImpl() AsyncImpl {
|
||||
return a.instrument
|
||||
}
|
||||
|
||||
// checkNewSync receives an SyncImpl and potential
|
||||
// error, and returns the same types, checking for and ensuring that
|
||||
// the returned interface is not nil.
|
||||
func checkNewSync(instrument SyncImpl, err error) (syncInstrument, error) {
|
||||
if instrument == nil {
|
||||
if err == nil {
|
||||
err = ErrSDKReturnedNilImpl
|
||||
}
|
||||
// Note: an alternate behavior would be to synthesize a new name
|
||||
// or group all duplicately-named instruments of a certain type
|
||||
// together and use a tag for the original name, e.g.,
|
||||
// name = 'invalid.counter.int64'
|
||||
// label = 'original-name=duplicate-counter-name'
|
||||
instrument = NoopSync{}
|
||||
}
|
||||
return syncInstrument{
|
||||
instrument: instrument,
|
||||
}, err
|
||||
}
|
||||
|
||||
func newSyncBoundInstrument(boundInstrument BoundSyncImpl) syncBoundInstrument {
|
||||
return syncBoundInstrument{
|
||||
boundInstrument: boundInstrument,
|
||||
}
|
||||
}
|
||||
|
||||
func newMeasurement(instrument SyncImpl, number core.Number) Measurement {
|
||||
return Measurement{
|
||||
instrument: instrument,
|
||||
number: number,
|
||||
}
|
||||
}
|
||||
|
||||
// checkNewAsync receives an AsyncImpl and potential
|
||||
// error, and returns the same types, checking for and ensuring that
|
||||
// the returned interface is not nil.
|
||||
func checkNewAsync(instrument AsyncImpl, err error) (asyncInstrument, error) {
|
||||
if instrument == nil {
|
||||
if err == nil {
|
||||
err = ErrSDKReturnedNilImpl
|
||||
}
|
||||
instrument = NoopAsync{}
|
||||
}
|
||||
return asyncInstrument{
|
||||
instrument: instrument,
|
||||
}, err
|
||||
}
|
84
api/metric/config.go
Normal file
84
api/metric/config.go
Normal file
@ -0,0 +1,84 @@
|
||||
// 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 "go.opentelemetry.io/otel/api/unit"
|
||||
|
||||
// Config contains some options for metrics of any kind.
|
||||
type Config struct {
|
||||
// Description is an optional field describing the metric
|
||||
// instrument.
|
||||
Description string
|
||||
// Unit is an optional field describing the metric instrument.
|
||||
Unit unit.Unit
|
||||
// LibraryName is the name given to the Meter that created
|
||||
// this instrument. See `Provider`.
|
||||
LibraryName string
|
||||
}
|
||||
|
||||
// Option is an interface for applying metric options.
|
||||
type Option interface {
|
||||
// Apply is used to set the Option value of a Config.
|
||||
Apply(*Config)
|
||||
}
|
||||
|
||||
// Configure is a helper that applies all the options to a Config.
|
||||
func Configure(opts []Option) Config {
|
||||
var config Config
|
||||
for _, o := range opts {
|
||||
o.Apply(&config)
|
||||
}
|
||||
return config
|
||||
}
|
||||
|
||||
// WithDescription applies provided description.
|
||||
func WithDescription(desc string) Option {
|
||||
return descriptionOption(desc)
|
||||
}
|
||||
|
||||
type descriptionOption string
|
||||
|
||||
func (d descriptionOption) Apply(config *Config) {
|
||||
config.Description = string(d)
|
||||
}
|
||||
|
||||
// WithUnit applies provided unit.
|
||||
func WithUnit(unit unit.Unit) Option {
|
||||
return unitOption(unit)
|
||||
}
|
||||
|
||||
type unitOption unit.Unit
|
||||
|
||||
func (u unitOption) Apply(config *Config) {
|
||||
config.Unit = unit.Unit(u)
|
||||
}
|
||||
|
||||
// WithLibraryName applies provided library name. This is meant for
|
||||
// use in `Provider` implementations that have not used
|
||||
// `WrapMeterImpl`. Implementations built using `WrapMeterImpl` have
|
||||
// instrument descriptors taken care of through this package.
|
||||
//
|
||||
// This option will have no effect when supplied by the user.
|
||||
// Provider implementations are expected to append this option after
|
||||
// the user-supplied options when building instrument descriptors.
|
||||
func WithLibraryName(name string) Option {
|
||||
return libraryNameOption(name)
|
||||
}
|
||||
|
||||
type libraryNameOption string
|
||||
|
||||
func (r libraryNameOption) Apply(config *Config) {
|
||||
config.LibraryName = string(r)
|
||||
}
|
@ -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,24 +72,24 @@ 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) {
|
||||
c.directRecord(ctx, core.NewFloat64Number(value), labels)
|
||||
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) {
|
||||
c.directRecord(ctx, core.NewInt64Number(value), labels)
|
||||
func (c Int64Counter) Add(ctx context.Context, value int64, labels ...kv.KeyValue) {
|
||||
c.directRecord(ctx, NewInt64Number(value), labels)
|
||||
}
|
||||
|
||||
// Add adds the value to the counter's sum using the labels
|
||||
// previously bound to this counter via Bind()
|
||||
func (b BoundFloat64Counter) Add(ctx context.Context, value float64) {
|
||||
b.directRecord(ctx, core.NewFloat64Number(value))
|
||||
b.directRecord(ctx, NewFloat64Number(value))
|
||||
}
|
||||
|
||||
// Add adds the value to the counter's sum using the labels
|
||||
// previously bound to this counter via Bind()
|
||||
func (b BoundInt64Counter) Add(ctx context.Context, value int64) {
|
||||
b.directRecord(ctx, core.NewInt64Number(value))
|
||||
b.directRecord(ctx, NewInt64Number(value))
|
||||
}
|
||||
|
71
api/metric/descriptor.go
Normal file
71
api/metric/descriptor.go
Normal file
@ -0,0 +1,71 @@
|
||||
// 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 "go.opentelemetry.io/otel/api/unit"
|
||||
|
||||
// Descriptor contains all the settings that describe an instrument,
|
||||
// including its name, metric kind, number kind, and the configurable
|
||||
// options.
|
||||
type Descriptor struct {
|
||||
name string
|
||||
kind Kind
|
||||
numberKind NumberKind
|
||||
config Config
|
||||
}
|
||||
|
||||
// NewDescriptor returns a Descriptor with the given contents.
|
||||
func NewDescriptor(name string, mkind Kind, nkind NumberKind, opts ...Option) Descriptor {
|
||||
return Descriptor{
|
||||
name: name,
|
||||
kind: mkind,
|
||||
numberKind: nkind,
|
||||
config: Configure(opts),
|
||||
}
|
||||
}
|
||||
|
||||
// Name returns the metric instrument's name.
|
||||
func (d Descriptor) Name() string {
|
||||
return d.name
|
||||
}
|
||||
|
||||
// MetricKind returns the specific kind of instrument.
|
||||
func (d Descriptor) MetricKind() Kind {
|
||||
return d.kind
|
||||
}
|
||||
|
||||
// Description provides a human-readable description of the metric
|
||||
// instrument.
|
||||
func (d Descriptor) Description() string {
|
||||
return d.config.Description
|
||||
}
|
||||
|
||||
// Unit describes the units of the metric instrument. Unitless
|
||||
// metrics return the empty string.
|
||||
func (d Descriptor) Unit() unit.Unit {
|
||||
return d.config.Unit
|
||||
}
|
||||
|
||||
// NumberKind returns whether this instrument is declared over int64,
|
||||
// float64, or uint64 values.
|
||||
func (d Descriptor) NumberKind() NumberKind {
|
||||
return d.numberKind
|
||||
}
|
||||
|
||||
// LibraryName returns the metric instrument's library name, typically
|
||||
// given via a call to Provider.Meter().
|
||||
func (d Descriptor) LibraryName() string {
|
||||
return d.config.LibraryName
|
||||
}
|
@ -12,9 +12,18 @@
|
||||
// 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"
|
||||
//go:generate stringer -type=Kind
|
||||
|
||||
package metric
|
||||
|
||||
// Kind describes the kind of instrument.
|
||||
type Kind int8
|
||||
|
||||
const (
|
||||
// MeasureKind indicates a Measure instrument.
|
||||
MeasureKind Kind = iota
|
||||
// ObserverKind indicates an Observer instrument.
|
||||
ObserverKind
|
||||
// CounterKind indicates a Counter instrument.
|
||||
CounterKind
|
||||
)
|
@ -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,25 +73,25 @@ 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) {
|
||||
c.directRecord(ctx, core.NewFloat64Number(value), labels)
|
||||
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) {
|
||||
c.directRecord(ctx, core.NewInt64Number(value), labels)
|
||||
func (c Int64Measure) Record(ctx context.Context, value int64, labels ...kv.KeyValue) {
|
||||
c.directRecord(ctx, NewInt64Number(value), labels)
|
||||
}
|
||||
|
||||
// Record adds a new value to the list of measure's records using the labels
|
||||
// previously bound to the measure via Bind()
|
||||
func (b BoundFloat64Measure) Record(ctx context.Context, value float64) {
|
||||
b.directRecord(ctx, core.NewFloat64Number(value))
|
||||
b.directRecord(ctx, NewFloat64Number(value))
|
||||
}
|
||||
|
||||
// Record adds a new value to the list of measure's records using the labels
|
||||
// previously bound to the measure via Bind()
|
||||
func (b BoundInt64Measure) Record(ctx context.Context, value int64) {
|
||||
b.directRecord(ctx, core.NewInt64Number(value))
|
||||
b.directRecord(ctx, NewInt64Number(value))
|
||||
}
|
||||
|
194
api/metric/meter.go
Normal file
194
api/metric/meter.go
Normal file
@ -0,0 +1,194 @@
|
||||
// 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 (
|
||||
"context"
|
||||
|
||||
"go.opentelemetry.io/otel/api/kv"
|
||||
)
|
||||
|
||||
// The file is organized as follows:
|
||||
//
|
||||
// - Provider interface
|
||||
// - Meter struct
|
||||
// - RecordBatch
|
||||
// - BatchObserver
|
||||
// - Synchronous instrument constructors (2 x int64,float64)
|
||||
// - Asynchronous instrument constructors (1 x int64,float64)
|
||||
// - Batch asynchronous constructors (1 x int64,float64)
|
||||
// - Internals
|
||||
|
||||
// Provider supports named Meter instances.
|
||||
type Provider interface {
|
||||
// Meter gets a named Meter interface. If the name is an
|
||||
// empty string, the provider uses a default name.
|
||||
Meter(name string) Meter
|
||||
}
|
||||
|
||||
// Meter is the OpenTelemetry metric API, based on a `MeterImpl`
|
||||
// implementation and the `Meter` library name.
|
||||
//
|
||||
// An uninitialized Meter is a no-op implementation.
|
||||
type Meter struct {
|
||||
impl MeterImpl
|
||||
libraryName string
|
||||
}
|
||||
|
||||
// RecordBatch atomically records a batch of measurements.
|
||||
func (m Meter) RecordBatch(ctx context.Context, ls []kv.KeyValue, ms ...Measurement) {
|
||||
if m.impl == nil {
|
||||
return
|
||||
}
|
||||
m.impl.RecordBatch(ctx, ls, ms...)
|
||||
}
|
||||
|
||||
// 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),
|
||||
}
|
||||
}
|
||||
|
||||
// NewInt64Counter creates a new integer Counter instrument with the
|
||||
// given name, customized with options. May return an error if the
|
||||
// name is invalid (e.g., empty) or improperly registered (e.g.,
|
||||
// duplicate registration).
|
||||
func (m Meter) NewInt64Counter(name string, options ...Option) (Int64Counter, error) {
|
||||
return wrapInt64CounterInstrument(
|
||||
m.newSync(name, CounterKind, Int64NumberKind, options))
|
||||
}
|
||||
|
||||
// NewFloat64Counter creates a new floating point Counter with the
|
||||
// given name, customized with options. May return an error if the
|
||||
// name is invalid (e.g., empty) or improperly registered (e.g.,
|
||||
// duplicate registration).
|
||||
func (m Meter) NewFloat64Counter(name string, options ...Option) (Float64Counter, error) {
|
||||
return wrapFloat64CounterInstrument(
|
||||
m.newSync(name, CounterKind, Float64NumberKind, options))
|
||||
}
|
||||
|
||||
// NewInt64Measure creates a new integer Measure instrument with the
|
||||
// given name, customized with options. May return an error if the
|
||||
// name is invalid (e.g., empty) or improperly registered (e.g.,
|
||||
// duplicate registration).
|
||||
func (m Meter) NewInt64Measure(name string, opts ...Option) (Int64Measure, error) {
|
||||
return wrapInt64MeasureInstrument(
|
||||
m.newSync(name, MeasureKind, Int64NumberKind, opts))
|
||||
}
|
||||
|
||||
// NewFloat64Measure creates a new floating point Measure with the
|
||||
// given name, customized with options. May return an error if the
|
||||
// name is invalid (e.g., empty) or improperly registered (e.g.,
|
||||
// duplicate registration).
|
||||
func (m Meter) NewFloat64Measure(name string, opts ...Option) (Float64Measure, error) {
|
||||
return wrapFloat64MeasureInstrument(
|
||||
m.newSync(name, MeasureKind, Float64NumberKind, opts))
|
||||
}
|
||||
|
||||
// RegisterInt64Observer creates a new integer Observer instrument
|
||||
// with the given name, running a given 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 (m Meter) RegisterInt64Observer(name string, callback Int64ObserverCallback, opts ...Option) (Int64Observer, error) {
|
||||
if callback == nil {
|
||||
return wrapInt64ObserverInstrument(NoopAsync{}, nil)
|
||||
}
|
||||
return wrapInt64ObserverInstrument(
|
||||
m.newAsync(name, ObserverKind, Int64NumberKind, opts,
|
||||
newInt64AsyncRunner(callback)))
|
||||
}
|
||||
|
||||
// RegisterFloat64Observer creates a new floating point Observer with
|
||||
// the given name, running a given 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 (m Meter) RegisterFloat64Observer(name string, callback Float64ObserverCallback, opts ...Option) (Float64Observer, error) {
|
||||
if callback == nil {
|
||||
return wrapFloat64ObserverInstrument(NoopAsync{}, nil)
|
||||
}
|
||||
return wrapFloat64ObserverInstrument(
|
||||
m.newAsync(name, ObserverKind, Float64NumberKind, opts,
|
||||
newFloat64AsyncRunner(callback)))
|
||||
}
|
||||
|
||||
// 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))
|
||||
}
|
||||
|
||||
// MeterImpl returns the underlying MeterImpl of this Meter.
|
||||
func (m Meter) MeterImpl() MeterImpl {
|
||||
return m.impl
|
||||
}
|
||||
|
||||
// newAsync constructs one new asynchronous instrument.
|
||||
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, runner)
|
||||
}
|
||||
|
||||
// newSync constructs one new synchronous instrument.
|
||||
func (m Meter) newSync(
|
||||
name string,
|
||||
metricKind Kind,
|
||||
numberKind NumberKind,
|
||||
opts []Option,
|
||||
) (
|
||||
SyncImpl,
|
||||
error,
|
||||
) {
|
||||
if m.impl == nil {
|
||||
return NoopSync{}, nil
|
||||
}
|
||||
desc := NewDescriptor(name, metricKind, numberKind, opts...)
|
||||
desc.config.LibraryName = m.libraryName
|
||||
return m.impl.NewSyncInstrument(desc)
|
||||
}
|
@ -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,11 +17,10 @@ package metric
|
||||
import (
|
||||
"context"
|
||||
|
||||
"go.opentelemetry.io/otel/api/core"
|
||||
"go.opentelemetry.io/otel/api/kv"
|
||||
)
|
||||
|
||||
type NoopProvider struct{}
|
||||
type NoopMeter struct{}
|
||||
|
||||
type noopInstrument struct{}
|
||||
type noopBoundInstrument struct{}
|
||||
@ -29,13 +28,12 @@ type NoopSync struct{ noopInstrument }
|
||||
type NoopAsync struct{ noopInstrument }
|
||||
|
||||
var _ Provider = NoopProvider{}
|
||||
var _ Meter = NoopMeter{}
|
||||
var _ SyncImpl = NoopSync{}
|
||||
var _ BoundSyncImpl = noopBoundInstrument{}
|
||||
var _ AsyncImpl = NoopAsync{}
|
||||
|
||||
func (NoopProvider) Meter(name string) Meter {
|
||||
return NoopMeter{}
|
||||
return Meter{}
|
||||
}
|
||||
|
||||
func (noopInstrument) Implementation() interface{} {
|
||||
@ -46,42 +44,15 @@ func (noopInstrument) Descriptor() Descriptor {
|
||||
return Descriptor{}
|
||||
}
|
||||
|
||||
func (noopBoundInstrument) RecordOne(context.Context, core.Number) {
|
||||
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, core.Number, []core.KeyValue) {
|
||||
}
|
||||
|
||||
func (NoopMeter) RecordBatch(context.Context, []core.KeyValue, ...Measurement) {
|
||||
}
|
||||
|
||||
func (NoopMeter) NewInt64Counter(string, ...Option) (Int64Counter, error) {
|
||||
return Int64Counter{syncInstrument{NoopSync{}}}, nil
|
||||
}
|
||||
|
||||
func (NoopMeter) NewFloat64Counter(string, ...Option) (Float64Counter, error) {
|
||||
return Float64Counter{syncInstrument{NoopSync{}}}, nil
|
||||
}
|
||||
|
||||
func (NoopMeter) NewInt64Measure(string, ...Option) (Int64Measure, error) {
|
||||
return Int64Measure{syncInstrument{NoopSync{}}}, nil
|
||||
}
|
||||
|
||||
func (NoopMeter) NewFloat64Measure(string, ...Option) (Float64Measure, error) {
|
||||
return Float64Measure{syncInstrument{NoopSync{}}}, nil
|
||||
}
|
||||
|
||||
func (NoopMeter) RegisterInt64Observer(string, Int64ObserverCallback, ...Option) (Int64Observer, error) {
|
||||
return Int64Observer{asyncInstrument{NoopAsync{}}}, nil
|
||||
}
|
||||
|
||||
func (NoopMeter) RegisterFloat64Observer(string, Float64ObserverCallback, ...Option) (Float64Observer, error) {
|
||||
return Float64Observer{asyncInstrument{NoopAsync{}}}, nil
|
||||
func (NoopSync) RecordOne(context.Context, Number, []kv.KeyValue) {
|
||||
}
|
||||
|
@ -12,7 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package core
|
||||
package metric
|
||||
|
||||
//go:generate stringer -type=NumberKind
|
||||
|
||||
@ -20,6 +20,8 @@ import (
|
||||
"fmt"
|
||||
"math"
|
||||
"sync/atomic"
|
||||
|
||||
"go.opentelemetry.io/otel/api/internal"
|
||||
)
|
||||
|
||||
// NumberKind describes the data type of the Number.
|
||||
@ -92,17 +94,17 @@ func NewNumberFromRaw(r uint64) Number {
|
||||
|
||||
// NewInt64Number creates an integral Number.
|
||||
func NewInt64Number(i int64) Number {
|
||||
return NewNumberFromRaw(int64ToRaw(i))
|
||||
return NewNumberFromRaw(internal.Int64ToRaw(i))
|
||||
}
|
||||
|
||||
// NewFloat64Number creates a floating point Number.
|
||||
func NewFloat64Number(f float64) Number {
|
||||
return NewNumberFromRaw(float64ToRaw(f))
|
||||
return NewNumberFromRaw(internal.Float64ToRaw(f))
|
||||
}
|
||||
|
||||
// NewInt64Number creates an integral Number.
|
||||
func NewUint64Number(u uint64) Number {
|
||||
return NewNumberFromRaw(uint64ToRaw(u))
|
||||
return NewNumberFromRaw(internal.Uint64ToRaw(u))
|
||||
}
|
||||
|
||||
// - as x
|
||||
@ -121,19 +123,19 @@ func (n *Number) AsRaw() uint64 {
|
||||
// AsInt64 assumes that the value contains an int64 and returns it as
|
||||
// such.
|
||||
func (n *Number) AsInt64() int64 {
|
||||
return rawToInt64(n.AsRaw())
|
||||
return internal.RawToInt64(n.AsRaw())
|
||||
}
|
||||
|
||||
// AsFloat64 assumes that the measurement value contains a float64 and
|
||||
// returns it as such.
|
||||
func (n *Number) AsFloat64() float64 {
|
||||
return rawToFloat64(n.AsRaw())
|
||||
return internal.RawToFloat64(n.AsRaw())
|
||||
}
|
||||
|
||||
// AsUint64 assumes that the value contains an uint64 and returns it
|
||||
// as such.
|
||||
func (n *Number) AsUint64() uint64 {
|
||||
return rawToUint64(n.AsRaw())
|
||||
return internal.RawToUint64(n.AsRaw())
|
||||
}
|
||||
|
||||
// - as x atomic
|
||||
@ -158,7 +160,7 @@ func (n *Number) AsInt64Atomic() int64 {
|
||||
// AsFloat64Atomic assumes that the measurement value contains a
|
||||
// float64 and returns it as such atomically.
|
||||
func (n *Number) AsFloat64Atomic() float64 {
|
||||
return rawToFloat64(n.AsRawAtomic())
|
||||
return internal.RawToFloat64(n.AsRawAtomic())
|
||||
}
|
||||
|
||||
// AsUint64Atomic assumes that the number contains a uint64 and
|
||||
@ -178,19 +180,19 @@ func (n *Number) AsRawPtr() *uint64 {
|
||||
// AsInt64Ptr assumes that the number contains an int64 and returns a
|
||||
// pointer to it.
|
||||
func (n *Number) AsInt64Ptr() *int64 {
|
||||
return rawPtrToInt64Ptr(n.AsRawPtr())
|
||||
return internal.RawPtrToInt64Ptr(n.AsRawPtr())
|
||||
}
|
||||
|
||||
// AsFloat64Ptr assumes that the number contains a float64 and returns a
|
||||
// pointer to it.
|
||||
func (n *Number) AsFloat64Ptr() *float64 {
|
||||
return rawPtrToFloat64Ptr(n.AsRawPtr())
|
||||
return internal.RawPtrToFloat64Ptr(n.AsRawPtr())
|
||||
}
|
||||
|
||||
// AsUint64Ptr assumes that the number contains a uint64 and returns a
|
||||
// pointer to it.
|
||||
func (n *Number) AsUint64Ptr() *uint64 {
|
||||
return rawPtrToUint64Ptr(n.AsRawPtr())
|
||||
return internal.RawPtrToUint64Ptr(n.AsRawPtr())
|
||||
}
|
||||
|
||||
// - coerce
|
||||
@ -299,7 +301,7 @@ func (n *Number) SetInt64Atomic(i int64) {
|
||||
// SetFloat64Atomic assumes that the number contains a float64 and
|
||||
// sets it to the passed value atomically.
|
||||
func (n *Number) SetFloat64Atomic(f float64) {
|
||||
atomic.StoreUint64(n.AsRawPtr(), float64ToRaw(f))
|
||||
atomic.StoreUint64(n.AsRawPtr(), internal.Float64ToRaw(f))
|
||||
}
|
||||
|
||||
// SetUint64Atomic assumes that the number contains a uint64 and sets
|
||||
@ -378,7 +380,7 @@ func (n *Number) SwapInt64Atomic(i int64) int64 {
|
||||
// it to the passed value and returns the old float64 value
|
||||
// atomically.
|
||||
func (n *Number) SwapFloat64Atomic(f float64) float64 {
|
||||
return rawToFloat64(atomic.SwapUint64(n.AsRawPtr(), float64ToRaw(f)))
|
||||
return internal.RawToFloat64(atomic.SwapUint64(n.AsRawPtr(), internal.Float64ToRaw(f)))
|
||||
}
|
||||
|
||||
// SwapUint64Atomic assumes that the number contains an uint64, sets
|
||||
@ -496,7 +498,7 @@ func (n *Number) CompareAndSwapInt64(oi, ni int64) bool {
|
||||
// CompareAndSwapFloat64 assumes that this number contains a float64 and
|
||||
// does the atomic CAS operation on it.
|
||||
func (n *Number) CompareAndSwapFloat64(of, nf float64) bool {
|
||||
return atomic.CompareAndSwapUint64(n.AsRawPtr(), float64ToRaw(of), float64ToRaw(nf))
|
||||
return atomic.CompareAndSwapUint64(n.AsRawPtr(), internal.Float64ToRaw(of), internal.Float64ToRaw(nf))
|
||||
}
|
||||
|
||||
// CompareAndSwapUint64 assumes that this number contains a uint64 and
|
@ -12,7 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package core
|
||||
package metric
|
||||
|
||||
import (
|
||||
"testing"
|
@ -1,6 +1,6 @@
|
||||
// Code generated by "stringer -type=NumberKind"; DO NOT EDIT.
|
||||
|
||||
package core
|
||||
package metric
|
||||
|
||||
import "strconv"
|
||||
|
@ -14,28 +14,13 @@
|
||||
|
||||
package metric
|
||||
|
||||
import "go.opentelemetry.io/otel/api/core"
|
||||
|
||||
// Int64ObserverResult is an interface for reporting integral
|
||||
// observations.
|
||||
type Int64ObserverResult interface {
|
||||
Observe(value int64, labels ...core.KeyValue)
|
||||
// BatchObserver represents an Observer callback that can report
|
||||
// observations for multiple instruments.
|
||||
type BatchObserver struct {
|
||||
meter Meter
|
||||
runner AsyncBatchRunner
|
||||
}
|
||||
|
||||
// Float64ObserverResult is an interface for reporting floating point
|
||||
// observations.
|
||||
type Float64ObserverResult interface {
|
||||
Observe(value float64, labels ...core.KeyValue)
|
||||
}
|
||||
|
||||
// Int64ObserverCallback is a type of callback that integral
|
||||
// observers run.
|
||||
type Int64ObserverCallback func(result Int64ObserverResult)
|
||||
|
||||
// Float64ObserverCallback is a type of callback that floating point
|
||||
// observers run.
|
||||
type Float64ObserverCallback func(result Float64ObserverResult)
|
||||
|
||||
// Int64Observer is a metric that captures a set of int64 values at a
|
||||
// point in time.
|
||||
type Int64Observer struct {
|
||||
@ -47,3 +32,25 @@ type Int64Observer struct {
|
||||
type Float64Observer struct {
|
||||
asyncInstrument
|
||||
}
|
||||
|
||||
// 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,
|
||||
}
|
||||
}
|
||||
|
@ -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(core.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
|
||||
}
|
||||
|
93
api/metric/sdkapi.go
Normal file
93
api/metric/sdkapi.go
Normal file
@ -0,0 +1,93 @@
|
||||
// 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 (
|
||||
"context"
|
||||
|
||||
"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, []kv.KeyValue, ...Measurement)
|
||||
|
||||
// NewSyncInstrument returns a newly constructed
|
||||
// synchronous instrument implementation or an error, should
|
||||
// one occur.
|
||||
NewSyncInstrument(descriptor Descriptor) (SyncImpl, error)
|
||||
|
||||
// NewAsyncInstrument returns a newly constructed
|
||||
// asynchronous instrument implementation or an error, should
|
||||
// one occur.
|
||||
NewAsyncInstrument(
|
||||
descriptor Descriptor,
|
||||
runner AsyncRunner,
|
||||
) (AsyncImpl, error)
|
||||
}
|
||||
|
||||
// InstrumentImpl is a common interface for synchronous and
|
||||
// asynchronous instruments.
|
||||
type InstrumentImpl interface {
|
||||
// Implementation returns the underlying implementation of the
|
||||
// instrument, which allows the implementation to gain access
|
||||
// to its own representation especially from a `Measurement`.
|
||||
Implementation() interface{}
|
||||
|
||||
// Descriptor returns a copy of the instrument's Descriptor.
|
||||
Descriptor() Descriptor
|
||||
}
|
||||
|
||||
// SyncImpl is the implementation-level interface to a generic
|
||||
// synchronous instrument (e.g., Measure and Counter instruments).
|
||||
type SyncImpl interface {
|
||||
InstrumentImpl
|
||||
|
||||
// Bind creates an implementation-level bound instrument,
|
||||
// binding a label set with this instrument implementation.
|
||||
Bind(labels []kv.KeyValue) BoundSyncImpl
|
||||
|
||||
// RecordOne captures a single synchronous metric event.
|
||||
RecordOne(ctx context.Context, number Number, labels []kv.KeyValue)
|
||||
}
|
||||
|
||||
// BoundSyncImpl is the implementation-level interface to a
|
||||
// generic bound synchronous instrument
|
||||
type BoundSyncImpl interface {
|
||||
|
||||
// RecordOne captures a single synchronous metric event.
|
||||
RecordOne(ctx context.Context, number Number)
|
||||
|
||||
// Unbind frees the resources associated with this bound instrument. It
|
||||
// does not affect the metric this bound instrument was created through.
|
||||
Unbind()
|
||||
}
|
||||
|
||||
// AsyncImpl is an implementation-level interface to an
|
||||
// asynchronous instrument (e.g., Observer instruments).
|
||||
type AsyncImpl interface {
|
||||
InstrumentImpl
|
||||
}
|
||||
|
||||
// WrapMeterImpl constructs a `Meter` implementation from a
|
||||
// `MeterImpl` implementation.
|
||||
func WrapMeterImpl(impl MeterImpl, libraryName string) Meter {
|
||||
return Meter{
|
||||
impl: impl,
|
||||
libraryName: libraryName,
|
||||
}
|
||||
}
|
@ -1,254 +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 metric
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"go.opentelemetry.io/otel/api/core"
|
||||
)
|
||||
|
||||
// MeterImpl is a convenient interface for SDK and test
|
||||
// implementations that would provide a `Meter` but do not wish to
|
||||
// re-implement the API's type-safe interfaces. Helpers provided in
|
||||
// this package will construct a `Meter` given a `MeterImpl`.
|
||||
type MeterImpl interface {
|
||||
// RecordBatch atomically records a batch of measurements.
|
||||
RecordBatch(context.Context, []core.KeyValue, ...Measurement)
|
||||
|
||||
// NewSyncInstrument returns a newly constructed
|
||||
// synchronous instrument implementation or an error, should
|
||||
// one occur.
|
||||
NewSyncInstrument(descriptor Descriptor) (SyncImpl, error)
|
||||
|
||||
// NewAsyncInstrument returns a newly constructed
|
||||
// asynchronous instrument implementation or an error, should
|
||||
// one occur.
|
||||
NewAsyncInstrument(
|
||||
descriptor Descriptor,
|
||||
callback func(func(core.Number, []core.KeyValue)),
|
||||
) (AsyncImpl, error)
|
||||
}
|
||||
|
||||
// InstrumentImpl is a common interface for synchronous and
|
||||
// asynchronous instruments.
|
||||
type InstrumentImpl interface {
|
||||
// Implementation returns the underlying implementation of the
|
||||
// instrument, which allows the implementation to gain access
|
||||
// to its own representation especially from a `Measurement`.
|
||||
Implementation() interface{}
|
||||
|
||||
// Descriptor returns a copy of the instrument's Descriptor.
|
||||
Descriptor() Descriptor
|
||||
}
|
||||
|
||||
// SyncImpl is the implementation-level interface to a generic
|
||||
// synchronous instrument (e.g., Measure and Counter instruments).
|
||||
type SyncImpl interface {
|
||||
InstrumentImpl
|
||||
|
||||
// Bind creates an implementation-level bound instrument,
|
||||
// binding a label set with this instrument implementation.
|
||||
Bind(labels []core.KeyValue) BoundSyncImpl
|
||||
|
||||
// RecordOne captures a single synchronous metric event.
|
||||
RecordOne(ctx context.Context, number core.Number, labels []core.KeyValue)
|
||||
}
|
||||
|
||||
// BoundSyncImpl is the implementation-level interface to a
|
||||
// generic bound synchronous instrument
|
||||
type BoundSyncImpl interface {
|
||||
|
||||
// RecordOne captures a single synchronous metric event.
|
||||
RecordOne(ctx context.Context, number core.Number)
|
||||
|
||||
// Unbind frees the resources associated with this bound instrument. It
|
||||
// does not affect the metric this bound instrument was created through.
|
||||
Unbind()
|
||||
}
|
||||
|
||||
// AsyncImpl is an implementation-level interface to an
|
||||
// asynchronous instrument (e.g., Observer instruments).
|
||||
type AsyncImpl interface {
|
||||
InstrumentImpl
|
||||
|
||||
// Note: An `Unregister()` API could be supported here.
|
||||
}
|
||||
|
||||
// wrappedMeterImpl implements the `Meter` interface given a
|
||||
// `MeterImpl` implementation.
|
||||
type wrappedMeterImpl struct {
|
||||
impl MeterImpl
|
||||
libraryName string
|
||||
}
|
||||
|
||||
// int64ObserverResult is an adapter for int64-valued asynchronous
|
||||
// callbacks.
|
||||
type int64ObserverResult struct {
|
||||
observe func(core.Number, []core.KeyValue)
|
||||
}
|
||||
|
||||
// float64ObserverResult is an adapter for float64-valued asynchronous
|
||||
// callbacks.
|
||||
type float64ObserverResult struct {
|
||||
observe func(core.Number, []core.KeyValue)
|
||||
}
|
||||
|
||||
var (
|
||||
_ Meter = (*wrappedMeterImpl)(nil)
|
||||
_ Int64ObserverResult = int64ObserverResult{}
|
||||
_ Float64ObserverResult = float64ObserverResult{}
|
||||
)
|
||||
|
||||
// Configure is a helper that applies all the options to a Config.
|
||||
func Configure(opts []Option) Config {
|
||||
var config Config
|
||||
for _, o := range opts {
|
||||
o.Apply(&config)
|
||||
}
|
||||
return config
|
||||
}
|
||||
|
||||
// WrapMeterImpl constructs a `Meter` implementation from a
|
||||
// `MeterImpl` implementation.
|
||||
func WrapMeterImpl(impl MeterImpl, libraryName string) Meter {
|
||||
return &wrappedMeterImpl{
|
||||
impl: impl,
|
||||
libraryName: libraryName,
|
||||
}
|
||||
}
|
||||
|
||||
func (m *wrappedMeterImpl) RecordBatch(ctx context.Context, ls []core.KeyValue, ms ...Measurement) {
|
||||
m.impl.RecordBatch(ctx, ls, ms...)
|
||||
}
|
||||
|
||||
func (m *wrappedMeterImpl) newSync(name string, metricKind Kind, numberKind core.NumberKind, opts []Option) (SyncImpl, error) {
|
||||
desc := NewDescriptor(name, metricKind, numberKind, opts...)
|
||||
desc.config.LibraryName = m.libraryName
|
||||
return m.impl.NewSyncInstrument(desc)
|
||||
}
|
||||
|
||||
func (m *wrappedMeterImpl) NewInt64Counter(name string, opts ...Option) (Int64Counter, error) {
|
||||
return WrapInt64CounterInstrument(
|
||||
m.newSync(name, CounterKind, core.Int64NumberKind, opts))
|
||||
}
|
||||
|
||||
// WrapInt64CounterInstrument returns an `Int64Counter` from a
|
||||
// `SyncImpl`. An error will be generated if the
|
||||
// `SyncImpl` is nil (in which case a No-op is substituted),
|
||||
// otherwise the error passes through.
|
||||
func WrapInt64CounterInstrument(syncInst SyncImpl, err error) (Int64Counter, error) {
|
||||
common, err := checkNewSync(syncInst, err)
|
||||
return Int64Counter{syncInstrument: common}, err
|
||||
}
|
||||
|
||||
func (m *wrappedMeterImpl) NewFloat64Counter(name string, opts ...Option) (Float64Counter, error) {
|
||||
return WrapFloat64CounterInstrument(
|
||||
m.newSync(name, CounterKind, core.Float64NumberKind, opts))
|
||||
}
|
||||
|
||||
// WrapFloat64CounterInstrument returns an `Float64Counter` from a
|
||||
// `SyncImpl`. An error will be generated if the
|
||||
// `SyncImpl` is nil (in which case a No-op is substituted),
|
||||
// otherwise the error passes through.
|
||||
func WrapFloat64CounterInstrument(syncInst SyncImpl, err error) (Float64Counter, error) {
|
||||
common, err := checkNewSync(syncInst, err)
|
||||
return Float64Counter{syncInstrument: common}, err
|
||||
}
|
||||
|
||||
func (m *wrappedMeterImpl) NewInt64Measure(name string, opts ...Option) (Int64Measure, error) {
|
||||
return WrapInt64MeasureInstrument(
|
||||
m.newSync(name, MeasureKind, core.Int64NumberKind, opts))
|
||||
}
|
||||
|
||||
// WrapInt64MeasureInstrument returns an `Int64Measure` from a
|
||||
// `SyncImpl`. An error will be generated if the
|
||||
// `SyncImpl` is nil (in which case a No-op is substituted),
|
||||
// otherwise the error passes through.
|
||||
func WrapInt64MeasureInstrument(syncInst SyncImpl, err error) (Int64Measure, error) {
|
||||
common, err := checkNewSync(syncInst, err)
|
||||
return Int64Measure{syncInstrument: common}, err
|
||||
}
|
||||
|
||||
func (m *wrappedMeterImpl) NewFloat64Measure(name string, opts ...Option) (Float64Measure, error) {
|
||||
return WrapFloat64MeasureInstrument(
|
||||
m.newSync(name, MeasureKind, core.Float64NumberKind, opts))
|
||||
}
|
||||
|
||||
// WrapFloat64MeasureInstrument returns an `Float64Measure` from a
|
||||
// `SyncImpl`. An error will be generated if the
|
||||
// `SyncImpl` is nil (in which case a No-op is substituted),
|
||||
// otherwise the error passes through.
|
||||
func WrapFloat64MeasureInstrument(syncInst SyncImpl, err error) (Float64Measure, error) {
|
||||
common, err := checkNewSync(syncInst, err)
|
||||
return Float64Measure{syncInstrument: common}, err
|
||||
}
|
||||
|
||||
func (m *wrappedMeterImpl) newAsync(name string, mkind Kind, nkind core.NumberKind, opts []Option, callback func(func(core.Number, []core.KeyValue))) (AsyncImpl, error) {
|
||||
desc := NewDescriptor(name, mkind, nkind, opts...)
|
||||
desc.config.LibraryName = m.libraryName
|
||||
return m.impl.NewAsyncInstrument(desc, callback)
|
||||
}
|
||||
|
||||
func (m *wrappedMeterImpl) RegisterInt64Observer(name string, callback Int64ObserverCallback, opts ...Option) (Int64Observer, error) {
|
||||
if callback == nil {
|
||||
return NoopMeter{}.RegisterInt64Observer("", nil)
|
||||
}
|
||||
return WrapInt64ObserverInstrument(
|
||||
m.newAsync(name, ObserverKind, core.Int64NumberKind, opts,
|
||||
func(observe func(core.Number, []core.KeyValue)) {
|
||||
// Note: this memory allocation could be avoided by
|
||||
// using a pointer to this object and mutating it
|
||||
// on each collection interval.
|
||||
callback(int64ObserverResult{observe})
|
||||
}))
|
||||
}
|
||||
|
||||
// WrapInt64ObserverInstrument returns an `Int64Observer` from a
|
||||
// `AsyncImpl`. An error will be generated if the
|
||||
// `AsyncImpl` is nil (in which case a No-op is substituted),
|
||||
// otherwise the error passes through.
|
||||
func WrapInt64ObserverInstrument(asyncInst AsyncImpl, err error) (Int64Observer, error) {
|
||||
common, err := checkNewAsync(asyncInst, err)
|
||||
return Int64Observer{asyncInstrument: common}, err
|
||||
}
|
||||
|
||||
func (m *wrappedMeterImpl) RegisterFloat64Observer(name string, callback Float64ObserverCallback, opts ...Option) (Float64Observer, error) {
|
||||
if callback == nil {
|
||||
return NoopMeter{}.RegisterFloat64Observer("", nil)
|
||||
}
|
||||
return WrapFloat64ObserverInstrument(
|
||||
m.newAsync(name, ObserverKind, core.Float64NumberKind, opts,
|
||||
func(observe func(core.Number, []core.KeyValue)) {
|
||||
callback(float64ObserverResult{observe})
|
||||
}))
|
||||
}
|
||||
|
||||
// WrapFloat64ObserverInstrument returns an `Float64Observer` from a
|
||||
// `AsyncImpl`. An error will be generated if the
|
||||
// `AsyncImpl` is nil (in which case a No-op is substituted),
|
||||
// otherwise the error passes through.
|
||||
func WrapFloat64ObserverInstrument(asyncInst AsyncImpl, err error) (Float64Observer, error) {
|
||||
common, err := checkNewAsync(asyncInst, err)
|
||||
return Float64Observer{asyncInstrument: common}, err
|
||||
}
|
||||
|
||||
func (io int64ObserverResult) Observe(value int64, labels ...core.KeyValue) {
|
||||
io.observe(core.NewInt64Number(value), labels)
|
||||
}
|
||||
|
||||
func (fo float64ObserverResult) Observe(value float64, labels ...core.KeyValue) {
|
||||
fo.observe(core.NewFloat64Number(value), labels)
|
||||
}
|
211
api/metric/sync.go
Normal file
211
api/metric/sync.go
Normal file
@ -0,0 +1,211 @@
|
||||
// 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 (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"go.opentelemetry.io/otel/api/kv"
|
||||
)
|
||||
|
||||
// Measurement is used for reporting a synchronous batch of metric
|
||||
// values. Instances of this type should be created by synchronous
|
||||
// instruments (e.g., Int64Counter.Measurement()).
|
||||
type Measurement struct {
|
||||
// number needs to be aligned for 64-bit atomic operations.
|
||||
number Number
|
||||
instrument SyncImpl
|
||||
}
|
||||
|
||||
// syncInstrument contains a SyncImpl.
|
||||
type syncInstrument struct {
|
||||
instrument SyncImpl
|
||||
}
|
||||
|
||||
// syncBoundInstrument contains a BoundSyncImpl.
|
||||
type syncBoundInstrument struct {
|
||||
boundInstrument BoundSyncImpl
|
||||
}
|
||||
|
||||
// asyncInstrument contains a AsyncImpl.
|
||||
type asyncInstrument struct {
|
||||
instrument AsyncImpl
|
||||
}
|
||||
|
||||
// ErrSDKReturnedNilImpl is used when one of the `MeterImpl` New
|
||||
// methods returns nil.
|
||||
var ErrSDKReturnedNilImpl = errors.New("SDK returned a nil implementation")
|
||||
|
||||
// SyncImpl returns the instrument that created this measurement.
|
||||
// This returns an implementation-level object for use by the SDK,
|
||||
// users should not refer to this.
|
||||
func (m Measurement) SyncImpl() SyncImpl {
|
||||
return m.instrument
|
||||
}
|
||||
|
||||
// Number returns a number recorded in this measurement.
|
||||
func (m Measurement) Number() Number {
|
||||
return m.number
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
// AsyncImpl implements AsyncImpl.
|
||||
func (a asyncInstrument) AsyncImpl() AsyncImpl {
|
||||
return a.instrument
|
||||
}
|
||||
|
||||
// SyncImpl returns the implementation object for synchronous instruments.
|
||||
func (s syncInstrument) SyncImpl() SyncImpl {
|
||||
return s.instrument
|
||||
}
|
||||
|
||||
func (s syncInstrument) bind(labels []kv.KeyValue) syncBoundInstrument {
|
||||
return newSyncBoundInstrument(s.instrument.Bind(labels))
|
||||
}
|
||||
|
||||
func (s syncInstrument) float64Measurement(value float64) Measurement {
|
||||
return newMeasurement(s.instrument, NewFloat64Number(value))
|
||||
}
|
||||
|
||||
func (s syncInstrument) int64Measurement(value int64) Measurement {
|
||||
return newMeasurement(s.instrument, NewInt64Number(value))
|
||||
}
|
||||
|
||||
func (s syncInstrument) directRecord(ctx context.Context, number Number, labels []kv.KeyValue) {
|
||||
s.instrument.RecordOne(ctx, number, labels)
|
||||
}
|
||||
|
||||
func (h syncBoundInstrument) directRecord(ctx context.Context, number Number) {
|
||||
h.boundInstrument.RecordOne(ctx, number)
|
||||
}
|
||||
|
||||
// Unbind calls SyncImpl.Unbind.
|
||||
func (h syncBoundInstrument) Unbind() {
|
||||
h.boundInstrument.Unbind()
|
||||
}
|
||||
|
||||
// checkNewAsync receives an AsyncImpl and potential
|
||||
// error, and returns the same types, checking for and ensuring that
|
||||
// the returned interface is not nil.
|
||||
func checkNewAsync(instrument AsyncImpl, err error) (asyncInstrument, error) {
|
||||
if instrument == nil {
|
||||
if err == nil {
|
||||
err = ErrSDKReturnedNilImpl
|
||||
}
|
||||
instrument = NoopAsync{}
|
||||
}
|
||||
return asyncInstrument{
|
||||
instrument: instrument,
|
||||
}, err
|
||||
}
|
||||
|
||||
// checkNewSync receives an SyncImpl and potential
|
||||
// error, and returns the same types, checking for and ensuring that
|
||||
// the returned interface is not nil.
|
||||
func checkNewSync(instrument SyncImpl, err error) (syncInstrument, error) {
|
||||
if instrument == nil {
|
||||
if err == nil {
|
||||
err = ErrSDKReturnedNilImpl
|
||||
}
|
||||
// Note: an alternate behavior would be to synthesize a new name
|
||||
// or group all duplicately-named instruments of a certain type
|
||||
// together and use a tag for the original name, e.g.,
|
||||
// name = 'invalid.counter.int64'
|
||||
// label = 'original-name=duplicate-counter-name'
|
||||
instrument = NoopSync{}
|
||||
}
|
||||
return syncInstrument{
|
||||
instrument: instrument,
|
||||
}, err
|
||||
}
|
||||
|
||||
func newSyncBoundInstrument(boundInstrument BoundSyncImpl) syncBoundInstrument {
|
||||
return syncBoundInstrument{
|
||||
boundInstrument: boundInstrument,
|
||||
}
|
||||
}
|
||||
|
||||
func newMeasurement(instrument SyncImpl, number Number) Measurement {
|
||||
return Measurement{
|
||||
instrument: instrument,
|
||||
number: number,
|
||||
}
|
||||
}
|
||||
|
||||
// wrapInt64CounterInstrument returns an `Int64Counter` from a
|
||||
// `SyncImpl`. An error will be generated if the
|
||||
// `SyncImpl` is nil (in which case a No-op is substituted),
|
||||
// otherwise the error passes through.
|
||||
func wrapInt64CounterInstrument(syncInst SyncImpl, err error) (Int64Counter, error) {
|
||||
common, err := checkNewSync(syncInst, err)
|
||||
return Int64Counter{syncInstrument: common}, err
|
||||
}
|
||||
|
||||
// wrapFloat64CounterInstrument returns an `Float64Counter` from a
|
||||
// `SyncImpl`. An error will be generated if the
|
||||
// `SyncImpl` is nil (in which case a No-op is substituted),
|
||||
// otherwise the error passes through.
|
||||
func wrapFloat64CounterInstrument(syncInst SyncImpl, err error) (Float64Counter, error) {
|
||||
common, err := checkNewSync(syncInst, err)
|
||||
return Float64Counter{syncInstrument: common}, err
|
||||
}
|
||||
|
||||
// wrapInt64MeasureInstrument returns an `Int64Measure` from a
|
||||
// `SyncImpl`. An error will be generated if the
|
||||
// `SyncImpl` is nil (in which case a No-op is substituted),
|
||||
// otherwise the error passes through.
|
||||
func wrapInt64MeasureInstrument(syncInst SyncImpl, err error) (Int64Measure, error) {
|
||||
common, err := checkNewSync(syncInst, err)
|
||||
return Int64Measure{syncInstrument: common}, err
|
||||
}
|
||||
|
||||
// wrapFloat64MeasureInstrument returns an `Float64Measure` from a
|
||||
// `SyncImpl`. An error will be generated if the
|
||||
// `SyncImpl` is nil (in which case a No-op is substituted),
|
||||
// otherwise the error passes through.
|
||||
func wrapFloat64MeasureInstrument(syncInst SyncImpl, err error) (Float64Measure, error) {
|
||||
common, err := checkNewSync(syncInst, err)
|
||||
return Float64Measure{syncInstrument: common}, err
|
||||
}
|
||||
|
||||
// wrapInt64ObserverInstrument returns an `Int64Observer` from a
|
||||
// `AsyncImpl`. An error will be generated if the
|
||||
// `AsyncImpl` is nil (in which case a No-op is substituted),
|
||||
// otherwise the error passes through.
|
||||
func wrapInt64ObserverInstrument(asyncInst AsyncImpl, err error) (Int64Observer, error) {
|
||||
common, err := checkNewAsync(asyncInst, err)
|
||||
return Int64Observer{asyncInstrument: common}, err
|
||||
}
|
||||
|
||||
// wrapFloat64ObserverInstrument returns an `Float64Observer` from a
|
||||
// `AsyncImpl`. An error will be generated if the
|
||||
// `AsyncImpl` is nil (in which case a No-op is substituted),
|
||||
// otherwise the error passes through.
|
||||
func wrapFloat64ObserverInstrument(asyncInst AsyncImpl, err error) (Float64Observer, error) {
|
||||
common, err := checkNewAsync(asyncInst, err)
|
||||
return Float64Observer{asyncInstrument: common}, err
|
||||
}
|
@ -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
|
||||
)
|
||||
|
@ -20,16 +20,17 @@ import (
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"go.opentelemetry.io/otel/api/metric"
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||
|
||||
"go.opentelemetry.io/otel/api/core"
|
||||
"go.opentelemetry.io/otel/api/global"
|
||||
"go.opentelemetry.io/otel/api/label"
|
||||
export "go.opentelemetry.io/otel/sdk/export/metric"
|
||||
"go.opentelemetry.io/otel/sdk/export/metric/aggregator"
|
||||
"go.opentelemetry.io/otel/sdk/metric/batcher/ungrouped"
|
||||
"go.opentelemetry.io/otel/sdk/metric/controller/push"
|
||||
integrator "go.opentelemetry.io/otel/sdk/metric/integrator/simple"
|
||||
"go.opentelemetry.io/otel/sdk/metric/selector/simple"
|
||||
"go.opentelemetry.io/otel/sdk/resource"
|
||||
)
|
||||
@ -46,7 +47,7 @@ type Exporter struct {
|
||||
onError func(error)
|
||||
|
||||
defaultSummaryQuantiles []float64
|
||||
defaultHistogramBoundaries []core.Number
|
||||
defaultHistogramBoundaries []metric.Number
|
||||
}
|
||||
|
||||
var _ export.Exporter = &Exporter{}
|
||||
@ -78,7 +79,7 @@ type Config struct {
|
||||
|
||||
// DefaultHistogramBoundaries defines the default histogram bucket
|
||||
// boundaries.
|
||||
DefaultHistogramBoundaries []core.Number
|
||||
DefaultHistogramBoundaries []metric.Number
|
||||
|
||||
// OnError is a function that handle errors that may occur while exporting metrics.
|
||||
// TODO: This should be refactored or even removed once we have a better error handling mechanism.
|
||||
@ -144,7 +145,7 @@ func InstallNewPipeline(config Config) (*push.Controller, http.HandlerFunc, erro
|
||||
}
|
||||
|
||||
// NewExportPipeline sets up a complete export pipeline with the recommended setup,
|
||||
// chaining a NewRawExporter into the recommended selectors and batchers.
|
||||
// chaining a NewRawExporter into the recommended selectors and integrators.
|
||||
func NewExportPipeline(config Config, period time.Duration) (*push.Controller, http.HandlerFunc, error) {
|
||||
selector := simple.NewWithHistogramMeasure(config.DefaultHistogramBoundaries)
|
||||
exporter, err := NewRawExporter(config)
|
||||
@ -152,7 +153,7 @@ func NewExportPipeline(config Config, period time.Duration) (*push.Controller, h
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// Prometheus needs to use a stateful batcher since counters (and histogram since they are a collection of Counters)
|
||||
// Prometheus needs to use a stateful integrator since counters (and histogram since they are a collection of Counters)
|
||||
// are cumulative (i.e., monotonically increasing values) and should not be resetted after each export.
|
||||
//
|
||||
// Prometheus uses this approach to be resilient to scrape failures.
|
||||
@ -160,8 +161,8 @@ func NewExportPipeline(config Config, period time.Duration) (*push.Controller, h
|
||||
// it could try again on the next scrape and no data would be lost, only resolution.
|
||||
//
|
||||
// Gauges (or LastValues) and Summaries are an exception to this and have different behaviors.
|
||||
batcher := ungrouped.New(selector, true)
|
||||
pusher := push.New(batcher, exporter, period)
|
||||
integrator := integrator.New(selector, true)
|
||||
pusher := push.New(integrator, exporter, period)
|
||||
pusher.Start()
|
||||
|
||||
return pusher, exporter.ServeHTTP, nil
|
||||
@ -245,7 +246,7 @@ func (c *collector) Collect(ch chan<- prometheus.Metric) {
|
||||
}
|
||||
}
|
||||
|
||||
func (c *collector) exportLastValue(ch chan<- prometheus.Metric, lvagg aggregator.LastValue, kind core.NumberKind, desc *prometheus.Desc, labels []string) error {
|
||||
func (c *collector) exportLastValue(ch chan<- prometheus.Metric, lvagg aggregator.LastValue, kind metric.NumberKind, desc *prometheus.Desc, labels []string) error {
|
||||
lv, _, err := lvagg.LastValue()
|
||||
if err != nil {
|
||||
return fmt.Errorf("error retrieving last value: %w", err)
|
||||
@ -260,7 +261,7 @@ func (c *collector) exportLastValue(ch chan<- prometheus.Metric, lvagg aggregato
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *collector) exportCounter(ch chan<- prometheus.Metric, sum aggregator.Sum, kind core.NumberKind, desc *prometheus.Desc, labels []string) error {
|
||||
func (c *collector) exportCounter(ch chan<- prometheus.Metric, sum aggregator.Sum, kind metric.NumberKind, desc *prometheus.Desc, labels []string) error {
|
||||
v, err := sum.Sum()
|
||||
if err != nil {
|
||||
return fmt.Errorf("error retrieving counter: %w", err)
|
||||
@ -275,13 +276,13 @@ func (c *collector) exportCounter(ch chan<- prometheus.Metric, sum aggregator.Su
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *collector) exportSummary(ch chan<- prometheus.Metric, dist aggregator.Distribution, kind core.NumberKind, desc *prometheus.Desc, labels []string) error {
|
||||
func (c *collector) exportSummary(ch chan<- prometheus.Metric, dist aggregator.Distribution, kind metric.NumberKind, desc *prometheus.Desc, labels []string) error {
|
||||
count, err := dist.Count()
|
||||
if err != nil {
|
||||
return fmt.Errorf("error retrieving count: %w", err)
|
||||
}
|
||||
|
||||
var sum core.Number
|
||||
var sum metric.Number
|
||||
sum, err = dist.Sum()
|
||||
if err != nil {
|
||||
return fmt.Errorf("error retrieving distribution sum: %w", err)
|
||||
@ -302,7 +303,7 @@ func (c *collector) exportSummary(ch chan<- prometheus.Metric, dist aggregator.D
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *collector) exportHistogram(ch chan<- prometheus.Metric, hist aggregator.Histogram, kind core.NumberKind, desc *prometheus.Desc, labels []string) error {
|
||||
func (c *collector) exportHistogram(ch chan<- prometheus.Metric, hist aggregator.Histogram, kind metric.NumberKind, desc *prometheus.Desc, labels []string) error {
|
||||
buckets, err := hist.Histogram()
|
||||
if err != nil {
|
||||
return fmt.Errorf("error retrieving histogram: %w", err)
|
||||
|
@ -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"
|
||||
@ -43,17 +42,17 @@ func TestPrometheusExporter(t *testing.T) {
|
||||
checkpointSet := test.NewCheckpointSet()
|
||||
|
||||
counter := metric.NewDescriptor(
|
||||
"counter", metric.CounterKind, core.Float64NumberKind)
|
||||
"counter", metric.CounterKind, metric.Float64NumberKind)
|
||||
lastValue := metric.NewDescriptor(
|
||||
"lastvalue", metric.ObserverKind, core.Float64NumberKind)
|
||||
"lastvalue", metric.ObserverKind, metric.Float64NumberKind)
|
||||
measure := metric.NewDescriptor(
|
||||
"measure", metric.MeasureKind, core.Float64NumberKind)
|
||||
"measure", metric.MeasureKind, metric.Float64NumberKind)
|
||||
histogramMeasure := metric.NewDescriptor(
|
||||
"histogram_measure", metric.MeasureKind, core.Float64NumberKind)
|
||||
"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...)
|
||||
@ -71,7 +70,7 @@ func TestPrometheusExporter(t *testing.T) {
|
||||
expected = append(expected, `measure_sum{A="B",C="D"} 45`)
|
||||
expected = append(expected, `measure_count{A="B",C="D"} 3`)
|
||||
|
||||
boundaries := []core.Number{core.NewFloat64Number(-0.5), core.NewFloat64Number(1)}
|
||||
boundaries := []metric.Number{metric.NewFloat64Number(-0.5), metric.NewFloat64Number(1)}
|
||||
checkpointSet.AddHistogramMeasure(&histogramMeasure, boundaries, -0.6, labels...)
|
||||
checkpointSet.AddHistogramMeasure(&histogramMeasure, boundaries, -0.4, labels...)
|
||||
checkpointSet.AddHistogramMeasure(&histogramMeasure, boundaries, 0.6, 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...)
|
||||
@ -101,7 +100,7 @@ func TestPrometheusExporter(t *testing.T) {
|
||||
expected = append(expected, `measure_count{A="E",C=""} 1`)
|
||||
expected = append(expected, `measure_sum{A="E",C=""} 19`)
|
||||
|
||||
boundaries = []core.Number{core.NewFloat64Number(0), core.NewFloat64Number(1)}
|
||||
boundaries = []metric.Number{metric.NewFloat64Number(0), metric.NewFloat64Number(1)}
|
||||
checkpointSet.AddHistogramMeasure(&histogramMeasure, boundaries, -0.6, missingLabels...)
|
||||
checkpointSet.AddHistogramMeasure(&histogramMeasure, boundaries, -0.4, missingLabels...)
|
||||
checkpointSet.AddHistogramMeasure(&histogramMeasure, boundaries, -0.1, 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...)
|
||||
|
||||
|
@ -29,8 +29,8 @@ import (
|
||||
|
||||
export "go.opentelemetry.io/otel/sdk/export/metric"
|
||||
"go.opentelemetry.io/otel/sdk/export/metric/aggregator"
|
||||
"go.opentelemetry.io/otel/sdk/metric/batcher/ungrouped"
|
||||
"go.opentelemetry.io/otel/sdk/metric/controller/push"
|
||||
integrator "go.opentelemetry.io/otel/sdk/metric/integrator/simple"
|
||||
"go.opentelemetry.io/otel/sdk/metric/selector/simple"
|
||||
)
|
||||
|
||||
@ -131,15 +131,15 @@ func InstallNewPipeline(config Config, opts ...push.Option) (*push.Controller, e
|
||||
}
|
||||
|
||||
// NewExportPipeline sets up a complete export pipeline with the recommended setup,
|
||||
// chaining a NewRawExporter into the recommended selectors and batchers.
|
||||
// chaining a NewRawExporter into the recommended selectors and integrators.
|
||||
func NewExportPipeline(config Config, period time.Duration, opts ...push.Option) (*push.Controller, error) {
|
||||
selector := simple.NewWithExactMeasure()
|
||||
exporter, err := NewRawExporter(config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
batcher := ungrouped.New(selector, true)
|
||||
pusher := push.New(batcher, exporter, period, opts...)
|
||||
integrator := integrator.New(selector, true)
|
||||
pusher := push.New(integrator, exporter, period, opts...)
|
||||
pusher.Start()
|
||||
|
||||
return pusher, nil
|
||||
|
@ -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"
|
||||
@ -99,9 +98,9 @@ func TestStdoutTimestamp(t *testing.T) {
|
||||
checkpointSet := test.NewCheckpointSet()
|
||||
|
||||
ctx := context.Background()
|
||||
desc := metric.NewDescriptor("test.name", metric.ObserverKind, core.Int64NumberKind)
|
||||
desc := metric.NewDescriptor("test.name", metric.ObserverKind, metric.Int64NumberKind)
|
||||
lvagg := lastvalue.New()
|
||||
aggtest.CheckedUpdate(t, lvagg, core.NewInt64Number(321), &desc)
|
||||
aggtest.CheckedUpdate(t, lvagg, metric.NewInt64Number(321), &desc)
|
||||
lvagg.Checkpoint(ctx, &desc)
|
||||
|
||||
checkpointSet.Add(&desc, lvagg)
|
||||
@ -144,12 +143,12 @@ func TestStdoutCounterFormat(t *testing.T) {
|
||||
|
||||
checkpointSet := test.NewCheckpointSet()
|
||||
|
||||
desc := metric.NewDescriptor("test.name", metric.CounterKind, core.Int64NumberKind)
|
||||
desc := metric.NewDescriptor("test.name", metric.CounterKind, metric.Int64NumberKind)
|
||||
cagg := sum.New()
|
||||
aggtest.CheckedUpdate(fix.t, cagg, core.NewInt64Number(123), &desc)
|
||||
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)
|
||||
|
||||
@ -161,12 +160,12 @@ func TestStdoutLastValueFormat(t *testing.T) {
|
||||
|
||||
checkpointSet := test.NewCheckpointSet()
|
||||
|
||||
desc := metric.NewDescriptor("test.name", metric.ObserverKind, core.Float64NumberKind)
|
||||
desc := metric.NewDescriptor("test.name", metric.ObserverKind, metric.Float64NumberKind)
|
||||
lvagg := lastvalue.New()
|
||||
aggtest.CheckedUpdate(fix.t, lvagg, core.NewFloat64Number(123.456), &desc)
|
||||
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)
|
||||
|
||||
@ -178,13 +177,13 @@ func TestStdoutMinMaxSumCount(t *testing.T) {
|
||||
|
||||
checkpointSet := test.NewCheckpointSet()
|
||||
|
||||
desc := metric.NewDescriptor("test.name", metric.MeasureKind, core.Float64NumberKind)
|
||||
desc := metric.NewDescriptor("test.name", metric.MeasureKind, metric.Float64NumberKind)
|
||||
magg := minmaxsumcount.New(&desc)
|
||||
aggtest.CheckedUpdate(fix.t, magg, core.NewFloat64Number(123.456), &desc)
|
||||
aggtest.CheckedUpdate(fix.t, magg, core.NewFloat64Number(876.543), &desc)
|
||||
aggtest.CheckedUpdate(fix.t, magg, metric.NewFloat64Number(123.456), &desc)
|
||||
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)
|
||||
|
||||
@ -198,16 +197,16 @@ func TestStdoutMeasureFormat(t *testing.T) {
|
||||
|
||||
checkpointSet := test.NewCheckpointSet()
|
||||
|
||||
desc := metric.NewDescriptor("test.name", metric.MeasureKind, core.Float64NumberKind)
|
||||
desc := metric.NewDescriptor("test.name", metric.MeasureKind, metric.Float64NumberKind)
|
||||
magg := array.New()
|
||||
|
||||
for i := 0; i < 1000; i++ {
|
||||
aggtest.CheckedUpdate(fix.t, magg, core.NewFloat64Number(float64(i)+0.5), &desc)
|
||||
aggtest.CheckedUpdate(fix.t, magg, metric.NewFloat64Number(float64(i)+0.5), &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)
|
||||
|
||||
@ -239,7 +238,7 @@ func TestStdoutMeasureFormat(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestStdoutNoData(t *testing.T) {
|
||||
desc := metric.NewDescriptor("test.name", metric.MeasureKind, core.Float64NumberKind)
|
||||
desc := metric.NewDescriptor("test.name", metric.MeasureKind, metric.Float64NumberKind)
|
||||
for name, tc := range map[string]export.Aggregator{
|
||||
"ddsketch": ddsketch.New(ddsketch.NewDefaultConfig(), &desc),
|
||||
"minmaxsumcount": minmaxsumcount.New(&desc),
|
||||
@ -269,11 +268,11 @@ func TestStdoutLastValueNotSet(t *testing.T) {
|
||||
|
||||
checkpointSet := test.NewCheckpointSet()
|
||||
|
||||
desc := metric.NewDescriptor("test.name", metric.ObserverKind, core.Float64NumberKind)
|
||||
desc := metric.NewDescriptor("test.name", metric.ObserverKind, metric.Float64NumberKind)
|
||||
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 {
|
||||
@ -319,9 +318,9 @@ func TestStdoutResource(t *testing.T) {
|
||||
|
||||
checkpointSet := test.NewCheckpointSet()
|
||||
|
||||
desc := metric.NewDescriptor("test.name", metric.ObserverKind, core.Float64NumberKind)
|
||||
desc := metric.NewDescriptor("test.name", metric.ObserverKind, metric.Float64NumberKind)
|
||||
lvagg := lastvalue.New()
|
||||
aggtest.CheckedUpdate(fix.t, lvagg, core.NewFloat64Number(123.456), &desc)
|
||||
aggtest.CheckedUpdate(fix.t, lvagg, metric.NewFloat64Number(123.456), &desc)
|
||||
lvagg.Checkpoint(fix.ctx, &desc)
|
||||
|
||||
checkpointSet.Add(&desc, lvagg, tc.attrs...)
|
||||
|
@ -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{
|
||||
@ -73,30 +73,30 @@ func (p *CheckpointSet) Add(desc *metric.Descriptor, newAgg export.Aggregator, l
|
||||
return newAgg, true
|
||||
}
|
||||
|
||||
func createNumber(desc *metric.Descriptor, v float64) core.Number {
|
||||
if desc.NumberKind() == core.Float64NumberKind {
|
||||
return core.NewFloat64Number(v)
|
||||
func createNumber(desc *metric.Descriptor, v float64) metric.Number {
|
||||
if desc.NumberKind() == metric.Float64NumberKind {
|
||||
return metric.NewFloat64Number(v)
|
||||
}
|
||||
return core.NewInt64Number(int64(v))
|
||||
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 []core.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{
|
||||
{
|
||||
|
@ -27,7 +27,6 @@ import (
|
||||
metricpb "github.com/open-telemetry/opentelemetry-proto/gen/go/metrics/v1"
|
||||
resourcepb "github.com/open-telemetry/opentelemetry-proto/gen/go/resource/v1"
|
||||
|
||||
"go.opentelemetry.io/otel/api/core"
|
||||
"go.opentelemetry.io/otel/api/label"
|
||||
"go.opentelemetry.io/otel/api/metric"
|
||||
export "go.opentelemetry.io/otel/sdk/export/metric"
|
||||
@ -257,12 +256,12 @@ func sum(desc *metric.Descriptor, labels *label.Set, a aggregator.Sum) (*metricp
|
||||
}
|
||||
|
||||
switch n := desc.NumberKind(); n {
|
||||
case core.Int64NumberKind, core.Uint64NumberKind:
|
||||
case metric.Int64NumberKind, metric.Uint64NumberKind:
|
||||
m.MetricDescriptor.Type = metricpb.MetricDescriptor_COUNTER_INT64
|
||||
m.Int64DataPoints = []*metricpb.Int64DataPoint{
|
||||
{Value: sum.CoerceToInt64(n)},
|
||||
}
|
||||
case core.Float64NumberKind:
|
||||
case metric.Float64NumberKind:
|
||||
m.MetricDescriptor.Type = metricpb.MetricDescriptor_COUNTER_DOUBLE
|
||||
m.DoubleDataPoints = []*metricpb.DoubleDataPoint{
|
||||
{Value: sum.CoerceToFloat64(n)},
|
||||
@ -276,7 +275,7 @@ func sum(desc *metric.Descriptor, labels *label.Set, a aggregator.Sum) (*metricp
|
||||
|
||||
// minMaxSumCountValue returns the values of the MinMaxSumCount Aggregator
|
||||
// as discret values.
|
||||
func minMaxSumCountValues(a aggregator.MinMaxSumCount) (min, max, sum core.Number, count int64, err error) {
|
||||
func minMaxSumCountValues(a aggregator.MinMaxSumCount) (min, max, sum metric.Number, count int64, err error) {
|
||||
if min, err = a.Min(); err != nil {
|
||||
return
|
||||
}
|
||||
|
@ -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"},
|
||||
@ -93,9 +92,9 @@ func TestMinMaxSumCountValue(t *testing.T) {
|
||||
mmsc.Checkpoint(context.Background(), &metric.Descriptor{})
|
||||
min, max, sum, count, err := minMaxSumCountValues(mmsc)
|
||||
if assert.NoError(t, err) {
|
||||
assert.Equal(t, min, core.NewInt64Number(1))
|
||||
assert.Equal(t, max, core.NewInt64Number(10))
|
||||
assert.Equal(t, sum, core.NewInt64Number(11))
|
||||
assert.Equal(t, min, metric.NewInt64Number(1))
|
||||
assert.Equal(t, max, metric.NewInt64Number(10))
|
||||
assert.Equal(t, sum, metric.NewInt64Number(11))
|
||||
assert.Equal(t, count, int64(2))
|
||||
}
|
||||
}
|
||||
@ -106,8 +105,8 @@ func TestMinMaxSumCountMetricDescriptor(t *testing.T) {
|
||||
metricKind metric.Kind
|
||||
description string
|
||||
unit unit.Unit
|
||||
numberKind core.NumberKind
|
||||
labels []core.KeyValue
|
||||
numberKind metric.NumberKind
|
||||
labels []kv.KeyValue
|
||||
expected *metricpb.MetricDescriptor
|
||||
}{
|
||||
{
|
||||
@ -115,8 +114,8 @@ func TestMinMaxSumCountMetricDescriptor(t *testing.T) {
|
||||
metric.MeasureKind,
|
||||
"test-a-description",
|
||||
unit.Dimensionless,
|
||||
core.Int64NumberKind,
|
||||
[]core.KeyValue{},
|
||||
metric.Int64NumberKind,
|
||||
[]kv.KeyValue{},
|
||||
&metricpb.MetricDescriptor{
|
||||
Name: "mmsc-test-a",
|
||||
Description: "test-a-description",
|
||||
@ -130,8 +129,8 @@ func TestMinMaxSumCountMetricDescriptor(t *testing.T) {
|
||||
metric.CounterKind, // This shouldn't change anything.
|
||||
"test-b-description",
|
||||
unit.Bytes,
|
||||
core.Float64NumberKind, // This shouldn't change anything.
|
||||
[]core.KeyValue{key.String("A", "1")},
|
||||
metric.Float64NumberKind, // This shouldn't change anything.
|
||||
[]kv.KeyValue{kv.String("A", "1")},
|
||||
&metricpb.MetricDescriptor{
|
||||
Name: "mmsc-test-b",
|
||||
Description: "test-b-description",
|
||||
@ -161,7 +160,7 @@ func TestMinMaxSumCountMetricDescriptor(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestMinMaxSumCountDatapoints(t *testing.T) {
|
||||
desc := metric.NewDescriptor("", metric.MeasureKind, core.Int64NumberKind)
|
||||
desc := metric.NewDescriptor("", metric.MeasureKind, metric.Int64NumberKind)
|
||||
labels := label.NewSet()
|
||||
mmsc := minmaxsumcount.New(&desc)
|
||||
assert.NoError(t, mmsc.Update(context.Background(), 1, &desc))
|
||||
@ -208,8 +207,8 @@ func TestSumMetricDescriptor(t *testing.T) {
|
||||
metricKind metric.Kind
|
||||
description string
|
||||
unit unit.Unit
|
||||
numberKind core.NumberKind
|
||||
labels []core.KeyValue
|
||||
numberKind metric.NumberKind
|
||||
labels []kv.KeyValue
|
||||
expected *metricpb.MetricDescriptor
|
||||
}{
|
||||
{
|
||||
@ -217,8 +216,8 @@ func TestSumMetricDescriptor(t *testing.T) {
|
||||
metric.CounterKind,
|
||||
"test-a-description",
|
||||
unit.Dimensionless,
|
||||
core.Int64NumberKind,
|
||||
[]core.KeyValue{},
|
||||
metric.Int64NumberKind,
|
||||
[]kv.KeyValue{},
|
||||
&metricpb.MetricDescriptor{
|
||||
Name: "sum-test-a",
|
||||
Description: "test-a-description",
|
||||
@ -232,8 +231,8 @@ func TestSumMetricDescriptor(t *testing.T) {
|
||||
metric.MeasureKind, // This shouldn't change anything.
|
||||
"test-b-description",
|
||||
unit.Milliseconds,
|
||||
core.Float64NumberKind,
|
||||
[]core.KeyValue{key.String("A", "1")},
|
||||
metric.Float64NumberKind,
|
||||
[]kv.KeyValue{kv.String("A", "1")},
|
||||
&metricpb.MetricDescriptor{
|
||||
Name: "sum-test-b",
|
||||
Description: "test-b-description",
|
||||
@ -258,10 +257,10 @@ func TestSumMetricDescriptor(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestSumInt64DataPoints(t *testing.T) {
|
||||
desc := metric.NewDescriptor("", metric.MeasureKind, core.Int64NumberKind)
|
||||
desc := metric.NewDescriptor("", metric.MeasureKind, metric.Int64NumberKind)
|
||||
labels := label.NewSet()
|
||||
s := sumAgg.New()
|
||||
assert.NoError(t, s.Update(context.Background(), core.Number(1), &desc))
|
||||
assert.NoError(t, s.Update(context.Background(), metric.Number(1), &desc))
|
||||
s.Checkpoint(context.Background(), &desc)
|
||||
if m, err := sum(&desc, &labels, s); assert.NoError(t, err) {
|
||||
assert.Equal(t, []*metricpb.Int64DataPoint{{Value: 1}}, m.Int64DataPoints)
|
||||
@ -272,10 +271,10 @@ func TestSumInt64DataPoints(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestSumFloat64DataPoints(t *testing.T) {
|
||||
desc := metric.NewDescriptor("", metric.MeasureKind, core.Float64NumberKind)
|
||||
desc := metric.NewDescriptor("", metric.MeasureKind, metric.Float64NumberKind)
|
||||
labels := label.NewSet()
|
||||
s := sumAgg.New()
|
||||
assert.NoError(t, s.Update(context.Background(), core.NewFloat64Number(1), &desc))
|
||||
assert.NoError(t, s.Update(context.Background(), metric.NewFloat64Number(1), &desc))
|
||||
s.Checkpoint(context.Background(), &desc)
|
||||
if m, err := sum(&desc, &labels, s); assert.NoError(t, err) {
|
||||
assert.Equal(t, []*metricpb.Int64DataPoint(nil), m.Int64DataPoints)
|
||||
@ -286,7 +285,7 @@ func TestSumFloat64DataPoints(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestSumErrUnknownValueType(t *testing.T) {
|
||||
desc := metric.NewDescriptor("", metric.MeasureKind, core.NumberKind(-1))
|
||||
desc := metric.NewDescriptor("", metric.MeasureKind, metric.NumberKind(-1))
|
||||
labels := label.NewSet()
|
||||
s := sumAgg.New()
|
||||
_, err := sum(&desc, &labels, s)
|
||||
|
@ -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,14 +26,13 @@ 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"
|
||||
exporttrace "go.opentelemetry.io/otel/sdk/export/trace"
|
||||
"go.opentelemetry.io/otel/sdk/metric/batcher/ungrouped"
|
||||
"go.opentelemetry.io/otel/sdk/metric/controller/push"
|
||||
integrator "go.opentelemetry.io/otel/sdk/metric/integrator/simple"
|
||||
"go.opentelemetry.io/otel/sdk/metric/selector/simple"
|
||||
sdktrace "go.opentelemetry.io/otel/sdk/trace"
|
||||
)
|
||||
@ -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,64 +101,64 @@ 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()
|
||||
}
|
||||
|
||||
selector := simple.NewWithExactMeasure()
|
||||
batcher := ungrouped.New(selector, true)
|
||||
pusher := push.New(batcher, exp, 60*time.Second)
|
||||
integrator := integrator.New(selector, true)
|
||||
pusher := push.New(integrator, exp, 60*time.Second)
|
||||
pusher.Start()
|
||||
|
||||
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
|
||||
nKind core.NumberKind
|
||||
nKind metricapi.NumberKind
|
||||
val int64
|
||||
}
|
||||
instruments := map[string]data{
|
||||
"test-int64-counter": {metric.CounterKind, core.Int64NumberKind, 1},
|
||||
"test-float64-counter": {metric.CounterKind, core.Float64NumberKind, 1},
|
||||
"test-int64-measure": {metric.MeasureKind, core.Int64NumberKind, 2},
|
||||
"test-float64-measure": {metric.MeasureKind, core.Float64NumberKind, 2},
|
||||
"test-int64-observer": {metric.ObserverKind, core.Int64NumberKind, 3},
|
||||
"test-float64-observer": {metric.ObserverKind, core.Float64NumberKind, 3},
|
||||
"test-int64-counter": {metric.CounterKind, metricapi.Int64NumberKind, 1},
|
||||
"test-float64-counter": {metric.CounterKind, metricapi.Float64NumberKind, 1},
|
||||
"test-int64-measure": {metric.MeasureKind, metricapi.Int64NumberKind, 2},
|
||||
"test-float64-measure": {metric.MeasureKind, metricapi.Float64NumberKind, 2},
|
||||
"test-int64-observer": {metric.ObserverKind, metricapi.Int64NumberKind, 3},
|
||||
"test-float64-observer": {metric.ObserverKind, metricapi.Float64NumberKind, 3},
|
||||
}
|
||||
for name, data := range instruments {
|
||||
switch data.iKind {
|
||||
case metric.CounterKind:
|
||||
switch data.nKind {
|
||||
case core.Int64NumberKind:
|
||||
case metricapi.Int64NumberKind:
|
||||
metricapi.Must(meter).NewInt64Counter(name).Add(ctx, data.val, labels...)
|
||||
case core.Float64NumberKind:
|
||||
case metricapi.Float64NumberKind:
|
||||
metricapi.Must(meter).NewFloat64Counter(name).Add(ctx, float64(data.val), labels...)
|
||||
default:
|
||||
assert.Failf(t, "unsupported number testing kind", data.nKind.String())
|
||||
}
|
||||
case metric.MeasureKind:
|
||||
switch data.nKind {
|
||||
case core.Int64NumberKind:
|
||||
case metricapi.Int64NumberKind:
|
||||
metricapi.Must(meter).NewInt64Measure(name).Record(ctx, data.val, labels...)
|
||||
case core.Float64NumberKind:
|
||||
case metricapi.Float64NumberKind:
|
||||
metricapi.Must(meter).NewFloat64Measure(name).Record(ctx, float64(data.val), labels...)
|
||||
default:
|
||||
assert.Failf(t, "unsupported number testing kind", data.nKind.String())
|
||||
}
|
||||
case metric.ObserverKind:
|
||||
switch data.nKind {
|
||||
case core.Int64NumberKind:
|
||||
case metricapi.Int64NumberKind:
|
||||
callback := func(v int64) metricapi.Int64ObserverCallback {
|
||||
return metricapi.Int64ObserverCallback(func(result metricapi.Int64ObserverResult) { result.Observe(v, labels...) })
|
||||
}(data.val)
|
||||
metricapi.Must(meter).RegisterInt64Observer(name, callback)
|
||||
case core.Float64NumberKind:
|
||||
case metricapi.Float64NumberKind:
|
||||
callback := func(v float64) metricapi.Float64ObserverCallback {
|
||||
return metricapi.Float64ObserverCallback(func(result metricapi.Float64ObserverResult) { result.Observe(v, labels...) })
|
||||
}(float64(data.val))
|
||||
@ -234,12 +233,12 @@ func newExporterEndToEndTest(t *testing.T, additionalOpts []otlp.ExporterOption)
|
||||
switch data.iKind {
|
||||
case metric.CounterKind:
|
||||
switch data.nKind {
|
||||
case core.Int64NumberKind:
|
||||
case metricapi.Int64NumberKind:
|
||||
assert.Equal(t, metricpb.MetricDescriptor_COUNTER_INT64.String(), desc.GetType().String())
|
||||
if dp := m.GetInt64DataPoints(); assert.Len(t, dp, 1) {
|
||||
assert.Equal(t, data.val, dp[0].Value, "invalid value for %q", desc.Name)
|
||||
}
|
||||
case core.Float64NumberKind:
|
||||
case metricapi.Float64NumberKind:
|
||||
assert.Equal(t, metricpb.MetricDescriptor_COUNTER_DOUBLE.String(), desc.GetType().String())
|
||||
if dp := m.GetDoubleDataPoints(); assert.Len(t, dp, 1) {
|
||||
assert.Equal(t, float64(data.val), dp[0].Value, "invalid value for %q", desc.Name)
|
||||
|
@ -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"
|
||||
@ -76,18 +75,18 @@ func (m checkpointSet) ForEach(fn func(metricsdk.Record) error) error {
|
||||
type record struct {
|
||||
name string
|
||||
mKind metric.Kind
|
||||
nKind core.NumberKind
|
||||
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",
|
||||
@ -145,7 +144,7 @@ func TestNoGroupingExport(t *testing.T) {
|
||||
{
|
||||
"int64-count",
|
||||
metric.CounterKind,
|
||||
core.Int64NumberKind,
|
||||
metric.Int64NumberKind,
|
||||
nil,
|
||||
nil,
|
||||
append(baseKeyValues, cpuKey.Int(1)),
|
||||
@ -153,7 +152,7 @@ func TestNoGroupingExport(t *testing.T) {
|
||||
{
|
||||
"int64-count",
|
||||
metric.CounterKind,
|
||||
core.Int64NumberKind,
|
||||
metric.Int64NumberKind,
|
||||
nil,
|
||||
nil,
|
||||
append(baseKeyValues, cpuKey.Int(2)),
|
||||
@ -193,7 +192,7 @@ func TestMeasureMetricGroupingExport(t *testing.T) {
|
||||
r := record{
|
||||
"measure",
|
||||
metric.MeasureKind,
|
||||
core.Int64NumberKind,
|
||||
metric.Int64NumberKind,
|
||||
nil,
|
||||
nil,
|
||||
append(baseKeyValues, cpuKey.Int(1)),
|
||||
@ -257,9 +256,9 @@ func TestMeasureMetricGroupingExport(t *testing.T) {
|
||||
}
|
||||
runMetricExportTests(t, []record{r, r}, expected)
|
||||
//changing the number kind should make no difference.
|
||||
r.nKind = core.Uint64NumberKind
|
||||
r.nKind = metric.Uint64NumberKind
|
||||
runMetricExportTests(t, []record{r, r}, expected)
|
||||
r.nKind = core.Float64NumberKind
|
||||
r.nKind = metric.Float64NumberKind
|
||||
runMetricExportTests(t, []record{r, r}, expected)
|
||||
}
|
||||
|
||||
@ -267,7 +266,7 @@ func TestCountInt64MetricGroupingExport(t *testing.T) {
|
||||
r := record{
|
||||
"int64-count",
|
||||
metric.CounterKind,
|
||||
core.Int64NumberKind,
|
||||
metric.Int64NumberKind,
|
||||
nil,
|
||||
nil,
|
||||
append(baseKeyValues, cpuKey.Int(1)),
|
||||
@ -304,7 +303,7 @@ func TestCountUint64MetricGroupingExport(t *testing.T) {
|
||||
r := record{
|
||||
"uint64-count",
|
||||
metric.CounterKind,
|
||||
core.Uint64NumberKind,
|
||||
metric.Uint64NumberKind,
|
||||
nil,
|
||||
nil,
|
||||
append(baseKeyValues, cpuKey.Int(1)),
|
||||
@ -354,7 +353,7 @@ func TestCountFloat64MetricGroupingExport(t *testing.T) {
|
||||
r := record{
|
||||
"float64-count",
|
||||
metric.CounterKind,
|
||||
core.Float64NumberKind,
|
||||
metric.Float64NumberKind,
|
||||
nil,
|
||||
nil,
|
||||
append(baseKeyValues, cpuKey.Int(1)),
|
||||
@ -407,7 +406,7 @@ func TestResourceMetricGroupingExport(t *testing.T) {
|
||||
{
|
||||
"int64-count",
|
||||
metric.CounterKind,
|
||||
core.Int64NumberKind,
|
||||
metric.Int64NumberKind,
|
||||
testInstA,
|
||||
nil,
|
||||
append(baseKeyValues, cpuKey.Int(1)),
|
||||
@ -415,7 +414,7 @@ func TestResourceMetricGroupingExport(t *testing.T) {
|
||||
{
|
||||
"int64-count",
|
||||
metric.CounterKind,
|
||||
core.Int64NumberKind,
|
||||
metric.Int64NumberKind,
|
||||
testInstA,
|
||||
nil,
|
||||
append(baseKeyValues, cpuKey.Int(1)),
|
||||
@ -423,7 +422,7 @@ func TestResourceMetricGroupingExport(t *testing.T) {
|
||||
{
|
||||
"int64-count",
|
||||
metric.CounterKind,
|
||||
core.Int64NumberKind,
|
||||
metric.Int64NumberKind,
|
||||
testInstA,
|
||||
nil,
|
||||
append(baseKeyValues, cpuKey.Int(2)),
|
||||
@ -431,7 +430,7 @@ func TestResourceMetricGroupingExport(t *testing.T) {
|
||||
{
|
||||
"int64-count",
|
||||
metric.CounterKind,
|
||||
core.Int64NumberKind,
|
||||
metric.Int64NumberKind,
|
||||
testInstB,
|
||||
nil,
|
||||
append(baseKeyValues, cpuKey.Int(1)),
|
||||
@ -494,7 +493,7 @@ func TestResourceInstLibMetricGroupingExport(t *testing.T) {
|
||||
{
|
||||
"int64-count",
|
||||
metric.CounterKind,
|
||||
core.Int64NumberKind,
|
||||
metric.Int64NumberKind,
|
||||
testInstA,
|
||||
[]metric.Option{
|
||||
metric.WithLibraryName("couting-lib"),
|
||||
@ -504,7 +503,7 @@ func TestResourceInstLibMetricGroupingExport(t *testing.T) {
|
||||
{
|
||||
"int64-count",
|
||||
metric.CounterKind,
|
||||
core.Int64NumberKind,
|
||||
metric.Int64NumberKind,
|
||||
testInstA,
|
||||
[]metric.Option{
|
||||
metric.WithLibraryName("couting-lib"),
|
||||
@ -514,7 +513,7 @@ func TestResourceInstLibMetricGroupingExport(t *testing.T) {
|
||||
{
|
||||
"int64-count",
|
||||
metric.CounterKind,
|
||||
core.Int64NumberKind,
|
||||
metric.Int64NumberKind,
|
||||
testInstA,
|
||||
[]metric.Option{
|
||||
metric.WithLibraryName("couting-lib"),
|
||||
@ -524,7 +523,7 @@ func TestResourceInstLibMetricGroupingExport(t *testing.T) {
|
||||
{
|
||||
"int64-count",
|
||||
metric.CounterKind,
|
||||
core.Int64NumberKind,
|
||||
metric.Int64NumberKind,
|
||||
testInstA,
|
||||
[]metric.Option{
|
||||
metric.WithLibraryName("summing-lib"),
|
||||
@ -534,7 +533,7 @@ func TestResourceInstLibMetricGroupingExport(t *testing.T) {
|
||||
{
|
||||
"int64-count",
|
||||
metric.CounterKind,
|
||||
core.Int64NumberKind,
|
||||
metric.Int64NumberKind,
|
||||
testInstB,
|
||||
[]metric.Option{
|
||||
metric.WithLibraryName("couting-lib"),
|
||||
@ -644,15 +643,15 @@ func runMetricExportTest(t *testing.T, exp *Exporter, rs []record, expected []me
|
||||
|
||||
ctx := context.Background()
|
||||
switch r.nKind {
|
||||
case core.Uint64NumberKind:
|
||||
require.NoError(t, agg.Update(ctx, core.NewUint64Number(1), &desc))
|
||||
require.NoError(t, agg.Update(ctx, core.NewUint64Number(10), &desc))
|
||||
case core.Int64NumberKind:
|
||||
require.NoError(t, agg.Update(ctx, core.NewInt64Number(1), &desc))
|
||||
require.NoError(t, agg.Update(ctx, core.NewInt64Number(10), &desc))
|
||||
case core.Float64NumberKind:
|
||||
require.NoError(t, agg.Update(ctx, core.NewFloat64Number(1), &desc))
|
||||
require.NoError(t, agg.Update(ctx, core.NewFloat64Number(10), &desc))
|
||||
case metric.Uint64NumberKind:
|
||||
require.NoError(t, agg.Update(ctx, metric.NewUint64Number(1), &desc))
|
||||
require.NoError(t, agg.Update(ctx, metric.NewUint64Number(10), &desc))
|
||||
case metric.Int64NumberKind:
|
||||
require.NoError(t, agg.Update(ctx, metric.NewInt64Number(1), &desc))
|
||||
require.NoError(t, agg.Update(ctx, metric.NewInt64Number(10), &desc))
|
||||
case metric.Float64NumberKind:
|
||||
require.NoError(t, agg.Update(ctx, metric.NewFloat64Number(1), &desc))
|
||||
require.NoError(t, agg.Update(ctx, metric.NewFloat64Number(10), &desc))
|
||||
default:
|
||||
t.Fatalf("invalid number kind: %v", r.nKind)
|
||||
}
|
||||
@ -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,
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user