You've already forked opentelemetry-go
mirror of
https://github.com/open-telemetry/opentelemetry-go.git
synced 2025-07-15 01:04:25 +02:00
Shrink core.Value (#256)
* shrink the value type went down from 40 bytes to 24 * add missing license blurb * stringify value type * print string value types in stdout exporter * make Value function take a pointer receiver
This commit is contained in:
255
api/core/key.go
255
api/core/key.go
@ -1,5 +1,21 @@
|
|||||||
|
// Copyright 2019, 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
|
package core
|
||||||
|
|
||||||
|
//go:generate stringer -type=ValueType
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
@ -15,20 +31,10 @@ type KeyValue struct {
|
|||||||
type ValueType int
|
type ValueType int
|
||||||
|
|
||||||
type Value struct {
|
type Value struct {
|
||||||
Type ValueType
|
vtype ValueType
|
||||||
Bool bool
|
numeric uint64
|
||||||
Int64 int64
|
stringly string
|
||||||
Uint64 uint64
|
// TODO Lazy value type?
|
||||||
Float64 float64
|
|
||||||
String string
|
|
||||||
|
|
||||||
// Note: this type could be made smaller by using a
|
|
||||||
// core.Number to represent four of these fields, e.g.,
|
|
||||||
// struct {
|
|
||||||
// Type ValueType
|
|
||||||
// String string
|
|
||||||
// Number Number
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -43,116 +49,217 @@ const (
|
|||||||
STRING
|
STRING
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func Bool(v bool) Value {
|
||||||
|
return Value{
|
||||||
|
vtype: BOOL,
|
||||||
|
numeric: boolToRaw(v),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Int64(v int64) Value {
|
||||||
|
return Value{
|
||||||
|
vtype: INT64,
|
||||||
|
numeric: int64ToRaw(v),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Uint64(v uint64) Value {
|
||||||
|
return Value{
|
||||||
|
vtype: UINT64,
|
||||||
|
numeric: uint64ToRaw(v),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Float64(v float64) Value {
|
||||||
|
return Value{
|
||||||
|
vtype: FLOAT64,
|
||||||
|
numeric: float64ToRaw(v),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Int32(v int32) Value {
|
||||||
|
return Value{
|
||||||
|
vtype: INT32,
|
||||||
|
numeric: int32ToRaw(v),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Uint32(v uint32) Value {
|
||||||
|
return Value{
|
||||||
|
vtype: UINT32,
|
||||||
|
numeric: uint32ToRaw(v),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Float32(v float32) Value {
|
||||||
|
return Value{
|
||||||
|
vtype: FLOAT32,
|
||||||
|
numeric: float32ToRaw(v),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func String(v string) Value {
|
||||||
|
return Value{
|
||||||
|
vtype: STRING,
|
||||||
|
stringly: v,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Int(v int) Value {
|
||||||
|
if unsafe.Sizeof(v) == 4 {
|
||||||
|
return Int32(int32(v))
|
||||||
|
}
|
||||||
|
return Int64(int64(v))
|
||||||
|
}
|
||||||
|
|
||||||
|
func Uint(v uint) Value {
|
||||||
|
if unsafe.Sizeof(v) == 4 {
|
||||||
|
return Uint32(uint32(v))
|
||||||
|
}
|
||||||
|
return Uint64(uint64(v))
|
||||||
|
}
|
||||||
|
|
||||||
func (k Key) Bool(v bool) KeyValue {
|
func (k Key) Bool(v bool) KeyValue {
|
||||||
return KeyValue{
|
return KeyValue{
|
||||||
Key: k,
|
Key: k,
|
||||||
Value: Value{
|
Value: Bool(v),
|
||||||
Type: BOOL,
|
|
||||||
Bool: v,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (k Key) Int64(v int64) KeyValue {
|
func (k Key) Int64(v int64) KeyValue {
|
||||||
return KeyValue{
|
return KeyValue{
|
||||||
Key: k,
|
Key: k,
|
||||||
Value: Value{
|
Value: Int64(v),
|
||||||
Type: INT64,
|
|
||||||
Int64: v,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (k Key) Uint64(v uint64) KeyValue {
|
func (k Key) Uint64(v uint64) KeyValue {
|
||||||
return KeyValue{
|
return KeyValue{
|
||||||
Key: k,
|
Key: k,
|
||||||
Value: Value{
|
Value: Uint64(v),
|
||||||
Type: UINT64,
|
|
||||||
Uint64: v,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (k Key) Float64(v float64) KeyValue {
|
func (k Key) Float64(v float64) KeyValue {
|
||||||
return KeyValue{
|
return KeyValue{
|
||||||
Key: k,
|
Key: k,
|
||||||
Value: Value{
|
Value: Float64(v),
|
||||||
Type: FLOAT64,
|
|
||||||
Float64: v,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (k Key) Int32(v int32) KeyValue {
|
func (k Key) Int32(v int32) KeyValue {
|
||||||
return KeyValue{
|
return KeyValue{
|
||||||
Key: k,
|
Key: k,
|
||||||
Value: Value{
|
Value: Int32(v),
|
||||||
Type: INT32,
|
|
||||||
Int64: int64(v),
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (k Key) Uint32(v uint32) KeyValue {
|
func (k Key) Uint32(v uint32) KeyValue {
|
||||||
return KeyValue{
|
return KeyValue{
|
||||||
Key: k,
|
Key: k,
|
||||||
Value: Value{
|
Value: Uint32(v),
|
||||||
Type: UINT32,
|
|
||||||
Uint64: uint64(v),
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (k Key) Float32(v float32) KeyValue {
|
func (k Key) Float32(v float32) KeyValue {
|
||||||
return KeyValue{
|
return KeyValue{
|
||||||
Key: k,
|
Key: k,
|
||||||
Value: Value{
|
Value: Float32(v),
|
||||||
Type: FLOAT32,
|
|
||||||
Float64: float64(v),
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (k Key) String(v string) KeyValue {
|
func (k Key) String(v string) KeyValue {
|
||||||
return KeyValue{
|
return KeyValue{
|
||||||
Key: k,
|
Key: k,
|
||||||
Value: Value{
|
Value: String(v),
|
||||||
Type: STRING,
|
|
||||||
String: v,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (k Key) Int(v int) KeyValue {
|
func (k Key) Int(v int) KeyValue {
|
||||||
if unsafe.Sizeof(v) == 4 {
|
return KeyValue{
|
||||||
return k.Int32(int32(v))
|
Key: k,
|
||||||
|
Value: Int(v),
|
||||||
}
|
}
|
||||||
return k.Int64(int64(v))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (k Key) Uint(v uint) KeyValue {
|
func (k Key) Uint(v uint) KeyValue {
|
||||||
if unsafe.Sizeof(v) == 4 {
|
return KeyValue{
|
||||||
return k.Uint32(uint32(v))
|
Key: k,
|
||||||
|
Value: Uint(v),
|
||||||
}
|
}
|
||||||
return k.Uint64(uint64(v))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (k Key) Defined() bool {
|
func (k Key) Defined() bool {
|
||||||
return len(k) != 0
|
return len(k) != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v Value) Emit() string {
|
func (v *Value) Type() ValueType {
|
||||||
switch v.Type {
|
return v.vtype
|
||||||
case BOOL:
|
}
|
||||||
return fmt.Sprint(v.Bool)
|
|
||||||
case INT32, INT64:
|
func (v *Value) AsBool() bool {
|
||||||
return fmt.Sprint(v.Int64)
|
return rawToBool(v.numeric)
|
||||||
case UINT32, UINT64:
|
}
|
||||||
return fmt.Sprint(v.Uint64)
|
|
||||||
case FLOAT32, FLOAT64:
|
func (v *Value) AsInt32() int32 {
|
||||||
return fmt.Sprint(v.Float64)
|
return rawToInt32(v.numeric)
|
||||||
case STRING:
|
}
|
||||||
return v.String
|
|
||||||
}
|
func (v *Value) AsInt64() int64 {
|
||||||
return "unknown"
|
return rawToInt64(v.numeric)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *Value) AsUint32() uint32 {
|
||||||
|
return rawToUint32(v.numeric)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *Value) AsUint64() uint64 {
|
||||||
|
return rawToUint64(v.numeric)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *Value) AsFloat32() float32 {
|
||||||
|
return rawToFloat32(v.numeric)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *Value) AsFloat64() float64 {
|
||||||
|
return rawToFloat64(v.numeric)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *Value) AsString() string {
|
||||||
|
return v.stringly
|
||||||
|
}
|
||||||
|
|
||||||
|
type unknownValueType struct{}
|
||||||
|
|
||||||
|
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{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *Value) Emit() string {
|
||||||
|
if v.Type() == STRING {
|
||||||
|
return v.stringly
|
||||||
|
}
|
||||||
|
i := v.AsInterface()
|
||||||
|
if _, ok := i.(unknownValueType); ok {
|
||||||
|
return "unknown"
|
||||||
|
}
|
||||||
|
return fmt.Sprint(i)
|
||||||
}
|
}
|
||||||
|
@ -9,265 +9,114 @@ import (
|
|||||||
"go.opentelemetry.io/api/core"
|
"go.opentelemetry.io/api/core"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestBool(t *testing.T) {
|
func TestValue(t *testing.T) {
|
||||||
|
k := core.Key("test")
|
||||||
|
bli := getBitlessInfo(42)
|
||||||
for _, testcase := range []struct {
|
for _, testcase := range []struct {
|
||||||
name string
|
name string
|
||||||
v bool
|
value core.Value
|
||||||
want core.Value
|
wantType core.ValueType
|
||||||
|
wantValue interface{}
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "Key.Bool() correctly returns keys's internal bool value",
|
name: "Key.Bool() correctly returns keys's internal bool value",
|
||||||
v: true,
|
value: k.Bool(true).Value,
|
||||||
want: core.Value{
|
wantType: core.BOOL,
|
||||||
Type: core.BOOL,
|
wantValue: true,
|
||||||
Bool: 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: float64(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.Run(testcase.name, func(t *testing.T) {
|
t.Logf("Running test case %s", testcase.name)
|
||||||
//proto: func (k core.Key) core.Bool(v bool) KeyValue {}
|
if testcase.value.Type() != testcase.wantType {
|
||||||
have := core.Key("").Bool(testcase.v)
|
t.Errorf("wrong value type, got %#v, expected %#v", testcase.value.Type(), testcase.wantType)
|
||||||
if diff := cmp.Diff(testcase.want, have.Value); diff != "" {
|
}
|
||||||
t.Fatal(diff)
|
got := testcase.value.AsInterface()
|
||||||
}
|
if diff := cmp.Diff(testcase.wantValue, got); diff != "" {
|
||||||
})
|
t.Errorf("+got, -want: %s", diff)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestInt64(t *testing.T) {
|
type bitlessInfo struct {
|
||||||
for _, testcase := range []struct {
|
intValue int
|
||||||
name string
|
uintValue uint
|
||||||
v int64
|
signedType core.ValueType
|
||||||
want core.Value
|
unsignedType core.ValueType
|
||||||
}{
|
signedValue interface{}
|
||||||
{
|
unsignedValue interface{}
|
||||||
name: "Key.Int64() correctly returns keys's internal int64 value",
|
|
||||||
v: int64(42),
|
|
||||||
want: core.Value{
|
|
||||||
Type: core.INT64,
|
|
||||||
Int64: int64(42),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
} {
|
|
||||||
t.Run(testcase.name, func(t *testing.T) {
|
|
||||||
//proto: func (k core.Key) Int64(v int64) KeyValue {
|
|
||||||
have := core.Key("").Int64(testcase.v)
|
|
||||||
if diff := cmp.Diff(testcase.want, have.Value); diff != "" {
|
|
||||||
t.Fatal(diff)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestUint64(t *testing.T) {
|
func getBitlessInfo(i int) bitlessInfo {
|
||||||
for _, testcase := range []struct {
|
if unsafe.Sizeof(i) == 4 {
|
||||||
name string
|
return bitlessInfo{
|
||||||
v uint64
|
intValue: i,
|
||||||
want core.Value
|
uintValue: uint(i),
|
||||||
}{
|
signedType: core.INT32,
|
||||||
{
|
unsignedType: core.UINT32,
|
||||||
name: "Key.Uint64() correctly returns keys's internal uint64 value",
|
signedValue: int32(i),
|
||||||
v: uint64(42),
|
unsignedValue: uint32(i),
|
||||||
want: core.Value{
|
}
|
||||||
Type: core.UINT64,
|
|
||||||
Uint64: uint64(42),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
} {
|
|
||||||
t.Run(testcase.name, func(t *testing.T) {
|
|
||||||
//proto: func (k core.Key) Uint64(v uint64) KeyValue {
|
|
||||||
have := core.Key("").Uint64(testcase.v)
|
|
||||||
if diff := cmp.Diff(testcase.want, have.Value); diff != "" {
|
|
||||||
t.Fatal(diff)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
return bitlessInfo{
|
||||||
|
intValue: i,
|
||||||
func TestFloat64(t *testing.T) {
|
uintValue: uint(i),
|
||||||
for _, testcase := range []struct {
|
signedType: core.INT64,
|
||||||
name string
|
unsignedType: core.UINT64,
|
||||||
v float64
|
signedValue: int64(i),
|
||||||
want core.Value
|
unsignedValue: uint64(i),
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "Key.float64() correctly returns keys's internal floa64 value",
|
|
||||||
v: float64(42.1),
|
|
||||||
want: core.Value{
|
|
||||||
Type: core.FLOAT64,
|
|
||||||
Float64: float64(42.1),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
} {
|
|
||||||
t.Run(testcase.name, func(t *testing.T) {
|
|
||||||
//proto: func (k core.Key) Float64(v float64) KeyValue {
|
|
||||||
have := core.Key("").Float64(testcase.v)
|
|
||||||
if diff := cmp.Diff(testcase.want, have.Value); diff != "" {
|
|
||||||
t.Fatal(diff)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestInt32(t *testing.T) {
|
|
||||||
for _, testcase := range []struct {
|
|
||||||
name string
|
|
||||||
v int32
|
|
||||||
want core.Value
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "Key.int32() correctly returns keys's internal int32 value",
|
|
||||||
v: int32(42),
|
|
||||||
want: core.Value{
|
|
||||||
Type: core.INT32,
|
|
||||||
Int64: int64(42),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
} {
|
|
||||||
t.Run(testcase.name, func(t *testing.T) {
|
|
||||||
//proto: func (k core.Key) Int32(v int32) KeyValue {
|
|
||||||
have := core.Key("").Int32(testcase.v)
|
|
||||||
if diff := cmp.Diff(testcase.want, have.Value); diff != "" {
|
|
||||||
t.Fatal(diff)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestUint32(t *testing.T) {
|
|
||||||
for _, testcase := range []struct {
|
|
||||||
name string
|
|
||||||
v uint32
|
|
||||||
want core.Value
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "Key.uint32() correctly returns keys's internal uint32 value",
|
|
||||||
v: uint32(42),
|
|
||||||
want: core.Value{
|
|
||||||
Type: core.UINT32,
|
|
||||||
Uint64: uint64(42),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
} {
|
|
||||||
t.Run(testcase.name, func(t *testing.T) {
|
|
||||||
//proto: func (k core.Key) Uint32(v uint32) KeyValue {
|
|
||||||
have := core.Key("").Uint32(testcase.v)
|
|
||||||
if diff := cmp.Diff(testcase.want, have.Value); diff != "" {
|
|
||||||
t.Fatal(diff)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFloat32(t *testing.T) {
|
|
||||||
for _, testcase := range []struct {
|
|
||||||
name string
|
|
||||||
v float32
|
|
||||||
want core.Value
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "Key.float32() correctly returns keys's internal float32 value",
|
|
||||||
v: float32(42.0),
|
|
||||||
want: core.Value{
|
|
||||||
Type: core.FLOAT32,
|
|
||||||
Float64: float64(42.0),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
} {
|
|
||||||
t.Run(testcase.name, func(t *testing.T) {
|
|
||||||
//proto: func (k core.Key) Float32(v float32) KeyValue {
|
|
||||||
have := core.Key("").Float32(testcase.v)
|
|
||||||
if diff := cmp.Diff(testcase.want, have.Value); diff != "" {
|
|
||||||
t.Fatal(diff)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestString(t *testing.T) {
|
|
||||||
for _, testcase := range []struct {
|
|
||||||
name string
|
|
||||||
v string
|
|
||||||
want core.Value
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "Key.String() correctly returns keys's internal string value",
|
|
||||||
v: "foo",
|
|
||||||
want: core.Value{
|
|
||||||
Type: core.STRING,
|
|
||||||
String: "foo",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
} {
|
|
||||||
t.Run(testcase.name, func(t *testing.T) {
|
|
||||||
//proto: func (k core.Key) String(v string) KeyValue {
|
|
||||||
have := core.Key("").String(testcase.v)
|
|
||||||
if diff := cmp.Diff(testcase.want, have.Value); diff != "" {
|
|
||||||
t.Fatal(diff)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestInt(t *testing.T) {
|
|
||||||
WTYPE := core.INT64
|
|
||||||
if unsafe.Sizeof(int(42)) == 4 {
|
|
||||||
// switch the desired value-type depending on system int byte-size
|
|
||||||
WTYPE = core.INT32
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, testcase := range []struct {
|
|
||||||
name string
|
|
||||||
v int
|
|
||||||
want core.Value
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "Key.Int() correctly returns keys's internal int64 value",
|
|
||||||
v: int(42),
|
|
||||||
want: core.Value{
|
|
||||||
Type: WTYPE,
|
|
||||||
Int64: int64(42),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
} {
|
|
||||||
t.Run(testcase.name, func(t *testing.T) {
|
|
||||||
//proto: func (k core.Key) Int(v int) KeyValue {
|
|
||||||
have := core.Key("").Int(testcase.v)
|
|
||||||
if diff := cmp.Diff(testcase.want, have.Value); diff != "" {
|
|
||||||
t.Fatal(diff)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestUint(t *testing.T) {
|
|
||||||
WTYPE := core.UINT64
|
|
||||||
if unsafe.Sizeof(uint(42)) == 4 {
|
|
||||||
// switch the desired value-type depending on system int byte-size
|
|
||||||
WTYPE = core.UINT32
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, testcase := range []struct {
|
|
||||||
name string
|
|
||||||
v uint
|
|
||||||
want core.Value
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "Key.Uint() correctly returns keys's internal uint64 value",
|
|
||||||
v: uint(42),
|
|
||||||
want: core.Value{
|
|
||||||
Type: WTYPE,
|
|
||||||
Uint64: 42,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
} {
|
|
||||||
t.Run(testcase.name, func(t *testing.T) {
|
|
||||||
//proto: func (k core.Key) Uint(v uint) KeyValue {
|
|
||||||
have := core.Key("").Uint(testcase.v)
|
|
||||||
if diff := cmp.Diff(testcase.want, have.Value); diff != "" {
|
|
||||||
t.Fatal(diff)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -306,66 +155,42 @@ func TestEmit(t *testing.T) {
|
|||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: `test Key.Emit() can emit a string representing self.BOOL`,
|
name: `test Key.Emit() can emit a string representing self.BOOL`,
|
||||||
v: core.Value{
|
v: core.Bool(true),
|
||||||
Type: core.BOOL,
|
|
||||||
Bool: true,
|
|
||||||
},
|
|
||||||
want: "true",
|
want: "true",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: `test Key.Emit() can emit a string representing self.INT32`,
|
name: `test Key.Emit() can emit a string representing self.INT32`,
|
||||||
v: core.Value{
|
v: core.Int32(42),
|
||||||
Type: core.INT32,
|
|
||||||
Int64: 42,
|
|
||||||
},
|
|
||||||
want: "42",
|
want: "42",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: `test Key.Emit() can emit a string representing self.INT64`,
|
name: `test Key.Emit() can emit a string representing self.INT64`,
|
||||||
v: core.Value{
|
v: core.Int64(42),
|
||||||
Type: core.INT64,
|
|
||||||
Int64: 42,
|
|
||||||
},
|
|
||||||
want: "42",
|
want: "42",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: `test Key.Emit() can emit a string representing self.UINT32`,
|
name: `test Key.Emit() can emit a string representing self.UINT32`,
|
||||||
v: core.Value{
|
v: core.Uint32(42),
|
||||||
Type: core.UINT32,
|
|
||||||
Uint64: 42,
|
|
||||||
},
|
|
||||||
want: "42",
|
want: "42",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: `test Key.Emit() can emit a string representing self.UINT64`,
|
name: `test Key.Emit() can emit a string representing self.UINT64`,
|
||||||
v: core.Value{
|
v: core.Uint64(42),
|
||||||
Type: core.UINT64,
|
|
||||||
Uint64: 42,
|
|
||||||
},
|
|
||||||
want: "42",
|
want: "42",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: `test Key.Emit() can emit a string representing self.FLOAT32`,
|
name: `test Key.Emit() can emit a string representing self.FLOAT32`,
|
||||||
v: core.Value{
|
v: core.Float32(42.1),
|
||||||
Type: core.FLOAT32,
|
|
||||||
Float64: 42.1,
|
|
||||||
},
|
|
||||||
want: "42.1",
|
want: "42.1",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: `test Key.Emit() can emit a string representing self.FLOAT64`,
|
name: `test Key.Emit() can emit a string representing self.FLOAT64`,
|
||||||
v: core.Value{
|
v: core.Float64(42.1),
|
||||||
Type: core.FLOAT64,
|
|
||||||
Float64: 42.1,
|
|
||||||
},
|
|
||||||
want: "42.1",
|
want: "42.1",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: `test Key.Emit() can emit a string representing self.STRING`,
|
name: `test Key.Emit() can emit a string representing self.STRING`,
|
||||||
v: core.Value{
|
v: core.String("foo"),
|
||||||
Type: core.STRING,
|
|
||||||
String: "foo",
|
|
||||||
},
|
|
||||||
want: "foo",
|
want: "foo",
|
||||||
},
|
},
|
||||||
} {
|
} {
|
||||||
|
@ -18,9 +18,7 @@ package core
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"unsafe"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// NumberKind describes the data type of the Number.
|
// NumberKind describes the data type of the Number.
|
||||||
@ -495,39 +493,3 @@ func (n Number) compareWithZero(kind NumberKind) int {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func rawToFloat64(r uint64) float64 {
|
|
||||||
return math.Float64frombits(r)
|
|
||||||
}
|
|
||||||
|
|
||||||
func float64ToRaw(f float64) uint64 {
|
|
||||||
return math.Float64bits(f)
|
|
||||||
}
|
|
||||||
|
|
||||||
func rawToInt64(r uint64) int64 {
|
|
||||||
return int64(r)
|
|
||||||
}
|
|
||||||
|
|
||||||
func int64ToRaw(i int64) uint64 {
|
|
||||||
return uint64(i)
|
|
||||||
}
|
|
||||||
|
|
||||||
func rawToUint64(r uint64) uint64 {
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
|
|
||||||
func uint64ToRaw(u uint64) uint64 {
|
|
||||||
return u
|
|
||||||
}
|
|
||||||
|
|
||||||
func rawPtrToFloat64Ptr(r *uint64) *float64 {
|
|
||||||
return (*float64)(unsafe.Pointer(r))
|
|
||||||
}
|
|
||||||
|
|
||||||
func rawPtrToInt64Ptr(r *uint64) *int64 {
|
|
||||||
return (*int64)(unsafe.Pointer(r))
|
|
||||||
}
|
|
||||||
|
|
||||||
func rawPtrToUint64Ptr(r *uint64) *uint64 {
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
|
77
api/core/rawhelpers.go
Normal file
77
api/core/rawhelpers.go
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
package core
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
func boolToRaw(b bool) uint64 {
|
||||||
|
if b {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func rawToBool(r uint64) bool {
|
||||||
|
return r != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func int64ToRaw(i int64) uint64 {
|
||||||
|
return uint64(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
func rawToInt64(r uint64) int64 {
|
||||||
|
return int64(r)
|
||||||
|
}
|
||||||
|
|
||||||
|
func uint64ToRaw(u uint64) uint64 {
|
||||||
|
return u
|
||||||
|
}
|
||||||
|
|
||||||
|
func rawToUint64(r uint64) uint64 {
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
func float64ToRaw(f float64) uint64 {
|
||||||
|
return math.Float64bits(f)
|
||||||
|
}
|
||||||
|
|
||||||
|
func rawToFloat64(r uint64) float64 {
|
||||||
|
return math.Float64frombits(r)
|
||||||
|
}
|
||||||
|
|
||||||
|
func int32ToRaw(i int32) uint64 {
|
||||||
|
return uint64(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
func rawToInt32(r uint64) int32 {
|
||||||
|
return int32(r)
|
||||||
|
}
|
||||||
|
|
||||||
|
func uint32ToRaw(u uint32) uint64 {
|
||||||
|
return uint64(u)
|
||||||
|
}
|
||||||
|
|
||||||
|
func rawToUint32(r uint64) uint32 {
|
||||||
|
return uint32(r)
|
||||||
|
}
|
||||||
|
|
||||||
|
func float32ToRaw(f float32) uint64 {
|
||||||
|
return uint32ToRaw(math.Float32bits(f))
|
||||||
|
}
|
||||||
|
|
||||||
|
func rawToFloat32(r uint64) float32 {
|
||||||
|
return math.Float32frombits(rawToUint32(r))
|
||||||
|
}
|
||||||
|
|
||||||
|
func rawPtrToFloat64Ptr(r *uint64) *float64 {
|
||||||
|
return (*float64)(unsafe.Pointer(r))
|
||||||
|
}
|
||||||
|
|
||||||
|
func rawPtrToInt64Ptr(r *uint64) *int64 {
|
||||||
|
return (*int64)(unsafe.Pointer(r))
|
||||||
|
}
|
||||||
|
|
||||||
|
func rawPtrToUint64Ptr(r *uint64) *uint64 {
|
||||||
|
return r
|
||||||
|
}
|
31
api/core/valuetype_string.go
Normal file
31
api/core/valuetype_string.go
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
// 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]]
|
||||||
|
}
|
@ -70,9 +70,6 @@ func (m Map) Apply(update MapUpdate) Map {
|
|||||||
|
|
||||||
func (m Map) Value(k core.Key) (core.Value, bool) {
|
func (m Map) Value(k core.Key) (core.Value, bool) {
|
||||||
entry, ok := m.m[k]
|
entry, ok := m.m[k]
|
||||||
if !ok {
|
|
||||||
entry.value.Type = core.INVALID
|
|
||||||
}
|
|
||||||
return entry.value, ok
|
return entry.value, ok
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,7 +2,6 @@ package key_test
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
"unsafe"
|
|
||||||
|
|
||||||
"github.com/google/go-cmp/cmp"
|
"github.com/google/go-cmp/cmp"
|
||||||
|
|
||||||
@ -11,7 +10,6 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestKeyValueConstructors(t *testing.T) {
|
func TestKeyValueConstructors(t *testing.T) {
|
||||||
|
|
||||||
tt := []struct {
|
tt := []struct {
|
||||||
name string
|
name string
|
||||||
actual core.KeyValue
|
actual core.KeyValue
|
||||||
@ -21,124 +19,81 @@ func TestKeyValueConstructors(t *testing.T) {
|
|||||||
name: "Bool",
|
name: "Bool",
|
||||||
actual: key.Bool("k1", true),
|
actual: key.Bool("k1", true),
|
||||||
expected: core.KeyValue{
|
expected: core.KeyValue{
|
||||||
Key: "k1",
|
Key: "k1",
|
||||||
Value: core.Value{
|
Value: core.Bool(true),
|
||||||
Type: core.BOOL,
|
|
||||||
Bool: true,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Int64",
|
name: "Int64",
|
||||||
actual: key.Int64("k1", 123),
|
actual: key.Int64("k1", 123),
|
||||||
expected: core.KeyValue{
|
expected: core.KeyValue{
|
||||||
Key: "k1",
|
Key: "k1",
|
||||||
Value: core.Value{
|
Value: core.Int64(123),
|
||||||
Type: core.INT64,
|
|
||||||
Int64: 123,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Uint64",
|
name: "Uint64",
|
||||||
actual: key.Uint64("k1", 1),
|
actual: key.Uint64("k1", 1),
|
||||||
expected: core.KeyValue{
|
expected: core.KeyValue{
|
||||||
Key: "k1",
|
Key: "k1",
|
||||||
Value: core.Value{
|
Value: core.Uint64(1),
|
||||||
Type: core.UINT64,
|
|
||||||
Uint64: 1,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Float64",
|
name: "Float64",
|
||||||
actual: key.Float64("k1", 123.5),
|
actual: key.Float64("k1", 123.5),
|
||||||
expected: core.KeyValue{
|
expected: core.KeyValue{
|
||||||
Key: "k1",
|
Key: "k1",
|
||||||
Value: core.Value{
|
Value: core.Float64(123.5),
|
||||||
Type: core.FLOAT64,
|
|
||||||
Float64: 123.5,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Int32",
|
name: "Int32",
|
||||||
actual: key.Int32("k1", 123),
|
actual: key.Int32("k1", 123),
|
||||||
expected: core.KeyValue{
|
expected: core.KeyValue{
|
||||||
Key: "k1",
|
Key: "k1",
|
||||||
Value: core.Value{
|
Value: core.Int32(123),
|
||||||
Type: core.INT32,
|
|
||||||
Int64: 123,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Uint32",
|
name: "Uint32",
|
||||||
actual: key.Uint32("k1", 123),
|
actual: key.Uint32("k1", 123),
|
||||||
expected: core.KeyValue{
|
expected: core.KeyValue{
|
||||||
Key: "k1",
|
Key: "k1",
|
||||||
Value: core.Value{
|
Value: core.Uint32(123),
|
||||||
Type: core.UINT32,
|
|
||||||
Uint64: 123,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Float32",
|
name: "Float32",
|
||||||
actual: key.Float32("k1", 123.5),
|
actual: key.Float32("k1", 123.5),
|
||||||
expected: core.KeyValue{
|
expected: core.KeyValue{
|
||||||
Key: "k1",
|
Key: "k1",
|
||||||
Value: core.Value{
|
Value: core.Float32(123.5),
|
||||||
Type: core.FLOAT32,
|
|
||||||
Float64: 123.5,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Int",
|
name: "Int",
|
||||||
actual: key.Int("k1", 123),
|
actual: key.Int("k1", 123),
|
||||||
expected: core.KeyValue{
|
expected: core.KeyValue{
|
||||||
Key: "k1",
|
Key: "k1",
|
||||||
Value: core.Value{
|
Value: core.Int(123),
|
||||||
Int64: 123,
|
|
||||||
Type: IntType(123),
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Uint",
|
name: "Uint",
|
||||||
actual: key.Uint("k1", 123),
|
actual: key.Uint("k1", 123),
|
||||||
expected: core.KeyValue{
|
expected: core.KeyValue{
|
||||||
Key: "k1",
|
Key: "k1",
|
||||||
Value: core.Value{
|
Value: core.Uint(123),
|
||||||
Uint64: 123,
|
|
||||||
Type: UintType(123),
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tt {
|
for _, test := range tt {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.name, func(t *testing.T) {
|
||||||
if diff := cmp.Diff(test.actual, test.expected); diff != "" {
|
if diff := cmp.Diff(test.actual, test.expected, cmp.AllowUnexported(core.Value{})); diff != "" {
|
||||||
t.Fatal(diff)
|
t.Fatal(diff)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// IntType returns the core.ValueType depending on system int byte-size
|
|
||||||
func IntType(v int) core.ValueType {
|
|
||||||
if unsafe.Sizeof(v) == 4 {
|
|
||||||
return core.INT32
|
|
||||||
}
|
|
||||||
return core.INT64
|
|
||||||
}
|
|
||||||
|
|
||||||
// UintType returns the core.ValueType depending on system uint byte-size
|
|
||||||
func UintType(v uint) core.ValueType {
|
|
||||||
if unsafe.Sizeof(v) == 4 {
|
|
||||||
return core.UINT32
|
|
||||||
}
|
|
||||||
return core.UINT64
|
|
||||||
}
|
|
||||||
|
@ -223,29 +223,47 @@ func spanDataToThrift(data *export.SpanData) *gen.Span {
|
|||||||
|
|
||||||
func keyValueToTag(kv core.KeyValue) *gen.Tag {
|
func keyValueToTag(kv core.KeyValue) *gen.Tag {
|
||||||
var tag *gen.Tag
|
var tag *gen.Tag
|
||||||
switch kv.Value.Type {
|
switch kv.Value.Type() {
|
||||||
case core.STRING:
|
case core.STRING:
|
||||||
|
s := kv.Value.AsString()
|
||||||
tag = &gen.Tag{
|
tag = &gen.Tag{
|
||||||
Key: string(kv.Key),
|
Key: string(kv.Key),
|
||||||
VStr: &kv.Value.String,
|
VStr: &s,
|
||||||
VType: gen.TagType_STRING,
|
VType: gen.TagType_STRING,
|
||||||
}
|
}
|
||||||
case core.BOOL:
|
case core.BOOL:
|
||||||
|
b := kv.Value.AsBool()
|
||||||
tag = &gen.Tag{
|
tag = &gen.Tag{
|
||||||
Key: string(kv.Key),
|
Key: string(kv.Key),
|
||||||
VBool: &kv.Value.Bool,
|
VBool: &b,
|
||||||
VType: gen.TagType_BOOL,
|
VType: gen.TagType_BOOL,
|
||||||
}
|
}
|
||||||
case core.INT32, core.INT64:
|
case core.INT32:
|
||||||
|
i := int64(kv.Value.AsInt32())
|
||||||
tag = &gen.Tag{
|
tag = &gen.Tag{
|
||||||
Key: string(kv.Key),
|
Key: string(kv.Key),
|
||||||
VLong: &kv.Value.Int64,
|
VLong: &i,
|
||||||
VType: gen.TagType_LONG,
|
VType: gen.TagType_LONG,
|
||||||
}
|
}
|
||||||
case core.FLOAT32, core.FLOAT64:
|
case core.INT64:
|
||||||
|
i := kv.Value.AsInt64()
|
||||||
|
tag = &gen.Tag{
|
||||||
|
Key: string(kv.Key),
|
||||||
|
VLong: &i,
|
||||||
|
VType: gen.TagType_LONG,
|
||||||
|
}
|
||||||
|
case core.FLOAT32:
|
||||||
|
f := float64(kv.Value.AsFloat32())
|
||||||
tag = &gen.Tag{
|
tag = &gen.Tag{
|
||||||
Key: string(kv.Key),
|
Key: string(kv.Key),
|
||||||
VDouble: &kv.Value.Float64,
|
VDouble: &f,
|
||||||
|
VType: gen.TagType_DOUBLE,
|
||||||
|
}
|
||||||
|
case core.FLOAT64:
|
||||||
|
f := kv.Value.AsFloat64()
|
||||||
|
tag = &gen.Tag{
|
||||||
|
Key: string(kv.Key),
|
||||||
|
VDouble: &f,
|
||||||
VType: gen.TagType_DOUBLE,
|
VType: gen.TagType_DOUBLE,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -194,25 +194,25 @@ func copyAttributes(out **tracepb.Span_Attributes, in []core.KeyValue) {
|
|||||||
|
|
||||||
func attributeValue(kv core.KeyValue) *tracepb.AttributeValue {
|
func attributeValue(kv core.KeyValue) *tracepb.AttributeValue {
|
||||||
value := kv.Value
|
value := kv.Value
|
||||||
switch value.Type {
|
switch value.Type() {
|
||||||
case core.BOOL:
|
case core.BOOL:
|
||||||
return &tracepb.AttributeValue{
|
return &tracepb.AttributeValue{
|
||||||
Value: &tracepb.AttributeValue_BoolValue{BoolValue: value.Bool},
|
Value: &tracepb.AttributeValue_BoolValue{BoolValue: value.AsBool()},
|
||||||
}
|
}
|
||||||
case core.INT64:
|
case core.INT64:
|
||||||
return &tracepb.AttributeValue{
|
return &tracepb.AttributeValue{
|
||||||
Value: &tracepb.AttributeValue_IntValue{IntValue: value.Int64},
|
Value: &tracepb.AttributeValue_IntValue{IntValue: value.AsInt64()},
|
||||||
}
|
}
|
||||||
case core.FLOAT64:
|
case core.FLOAT64:
|
||||||
// TODO: set double value if Stackdriver Trace support it in the future.
|
// TODO: set double value if Stackdriver Trace support it in the future.
|
||||||
return &tracepb.AttributeValue{
|
return &tracepb.AttributeValue{
|
||||||
Value: &tracepb.AttributeValue_StringValue{
|
Value: &tracepb.AttributeValue_StringValue{
|
||||||
StringValue: trunc(strconv.FormatFloat(value.Float64, 'f', -1, 64),
|
StringValue: trunc(strconv.FormatFloat(value.AsFloat64(), 'f', -1, 64),
|
||||||
maxAttributeStringValue)},
|
maxAttributeStringValue)},
|
||||||
}
|
}
|
||||||
case core.STRING:
|
case core.STRING:
|
||||||
return &tracepb.AttributeValue{
|
return &tracepb.AttributeValue{
|
||||||
Value: &tracepb.AttributeValue_StringValue{StringValue: trunc(value.String, maxAttributeStringValue)},
|
Value: &tracepb.AttributeValue_StringValue{StringValue: trunc(value.AsString(), maxAttributeStringValue)},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
@ -20,7 +20,12 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"sync"
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"google.golang.org/grpc/codes"
|
||||||
|
|
||||||
|
"go.opentelemetry.io/api/core"
|
||||||
|
apitrace "go.opentelemetry.io/api/trace"
|
||||||
"go.opentelemetry.io/sdk/export"
|
"go.opentelemetry.io/sdk/export"
|
||||||
"go.opentelemetry.io/sdk/trace"
|
"go.opentelemetry.io/sdk/trace"
|
||||||
)
|
)
|
||||||
@ -54,15 +59,72 @@ func (e *Exporter) RegisterSimpleSpanProcessor() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type jsonValue struct {
|
||||||
|
Type string
|
||||||
|
Value interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
type jsonKeyValue struct {
|
||||||
|
Key core.Key
|
||||||
|
Value jsonValue
|
||||||
|
}
|
||||||
|
|
||||||
|
type jsonSpanData struct {
|
||||||
|
SpanContext core.SpanContext
|
||||||
|
ParentSpanID core.SpanID
|
||||||
|
SpanKind apitrace.SpanKind
|
||||||
|
Name string
|
||||||
|
StartTime time.Time
|
||||||
|
EndTime time.Time
|
||||||
|
Attributes []jsonKeyValue
|
||||||
|
MessageEvents []export.Event
|
||||||
|
Links []apitrace.Link
|
||||||
|
Status codes.Code
|
||||||
|
HasRemoteParent bool
|
||||||
|
DroppedAttributeCount int
|
||||||
|
DroppedMessageEventCount int
|
||||||
|
DroppedLinkCount int
|
||||||
|
ChildSpanCount int
|
||||||
|
}
|
||||||
|
|
||||||
|
func marshalSpanData(data *export.SpanData, pretty bool) ([]byte, error) {
|
||||||
|
jsd := jsonSpanData{
|
||||||
|
SpanContext: data.SpanContext,
|
||||||
|
ParentSpanID: data.ParentSpanID,
|
||||||
|
SpanKind: data.SpanKind,
|
||||||
|
Name: data.Name,
|
||||||
|
StartTime: data.StartTime,
|
||||||
|
EndTime: data.EndTime,
|
||||||
|
Attributes: toJSONAttributes(data.Attributes),
|
||||||
|
MessageEvents: data.MessageEvents,
|
||||||
|
Links: data.Links,
|
||||||
|
Status: data.Status,
|
||||||
|
HasRemoteParent: data.HasRemoteParent,
|
||||||
|
DroppedAttributeCount: data.DroppedAttributeCount,
|
||||||
|
DroppedMessageEventCount: data.DroppedMessageEventCount,
|
||||||
|
DroppedLinkCount: data.DroppedLinkCount,
|
||||||
|
ChildSpanCount: data.ChildSpanCount,
|
||||||
|
}
|
||||||
|
|
||||||
|
if pretty {
|
||||||
|
return json.MarshalIndent(jsd, "", "\t")
|
||||||
|
}
|
||||||
|
return json.Marshal(jsd)
|
||||||
|
}
|
||||||
|
|
||||||
|
func toJSONAttributes(attributes []core.KeyValue) []jsonKeyValue {
|
||||||
|
jsonAttrs := make([]jsonKeyValue, len(attributes))
|
||||||
|
for i := 0; i < len(attributes); i++ {
|
||||||
|
jsonAttrs[i].Key = attributes[i].Key
|
||||||
|
jsonAttrs[i].Value.Type = attributes[i].Value.Type().String()
|
||||||
|
jsonAttrs[i].Value.Value = attributes[i].Value.AsInterface()
|
||||||
|
}
|
||||||
|
return jsonAttrs
|
||||||
|
}
|
||||||
|
|
||||||
// ExportSpan writes a SpanData in json format to stdout.
|
// ExportSpan writes a SpanData in json format to stdout.
|
||||||
func (e *Exporter) ExportSpan(ctx context.Context, data *export.SpanData) {
|
func (e *Exporter) ExportSpan(ctx context.Context, data *export.SpanData) {
|
||||||
var jsonSpan []byte
|
jsonSpan, err := marshalSpanData(data, e.pretty)
|
||||||
var err error
|
|
||||||
if e.pretty {
|
|
||||||
jsonSpan, err = json.MarshalIndent(data, "", "\t")
|
|
||||||
} else {
|
|
||||||
jsonSpan, err = json.Marshal(data)
|
|
||||||
}
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// ignore writer failures for now
|
// ignore writer failures for now
|
||||||
_, _ = e.outputWriter.Write([]byte("Error converting spanData to json: " + err.Error()))
|
_, _ = e.outputWriter.Write([]byte("Error converting spanData to json: " + err.Error()))
|
||||||
|
@ -24,6 +24,7 @@ import (
|
|||||||
"google.golang.org/grpc/codes"
|
"google.golang.org/grpc/codes"
|
||||||
|
|
||||||
"go.opentelemetry.io/api/core"
|
"go.opentelemetry.io/api/core"
|
||||||
|
"go.opentelemetry.io/api/key"
|
||||||
"go.opentelemetry.io/api/trace"
|
"go.opentelemetry.io/api/trace"
|
||||||
"go.opentelemetry.io/sdk/export"
|
"go.opentelemetry.io/sdk/export"
|
||||||
)
|
)
|
||||||
@ -54,14 +55,8 @@ func TestExporter_ExportSpan(t *testing.T) {
|
|||||||
StartTime: now,
|
StartTime: now,
|
||||||
EndTime: now,
|
EndTime: now,
|
||||||
Attributes: []core.KeyValue{
|
Attributes: []core.KeyValue{
|
||||||
{
|
key.String("key", keyValue),
|
||||||
Key: core.Key("key"),
|
key.Float64("double", doubleValue),
|
||||||
Value: core.Value{Type: core.STRING, String: keyValue},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Key: core.Key("double"),
|
|
||||||
Value: core.Value{Type: core.FLOAT64, Float64: doubleValue},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
SpanKind: trace.SpanKindInternal,
|
SpanKind: trace.SpanKindInternal,
|
||||||
Status: codes.Unknown,
|
Status: codes.Unknown,
|
||||||
@ -82,11 +77,11 @@ func TestExporter_ExportSpan(t *testing.T) {
|
|||||||
`"Attributes":[` +
|
`"Attributes":[` +
|
||||||
`{` +
|
`{` +
|
||||||
`"Key":"key",` +
|
`"Key":"key",` +
|
||||||
`"Value":{"Type":8,"Bool":false,"Int64":0,"Uint64":0,"Float64":0,"String":"value"}` +
|
`"Value":{"Type":"STRING","Value":"value"}` +
|
||||||
`},` +
|
`},` +
|
||||||
`{` +
|
`{` +
|
||||||
`"Key":"double",` +
|
`"Key":"double",` +
|
||||||
`"Value":{"Type":7,"Bool":false,"Int64":0,"Uint64":0,"Float64":123.456,"String":""}` +
|
`"Value":{"Type":"FLOAT64","Value":123.456}` +
|
||||||
`}` +
|
`}` +
|
||||||
`],` +
|
`],` +
|
||||||
`"MessageEvents":null,` +
|
`"MessageEvents":null,` +
|
||||||
|
@ -361,7 +361,7 @@ func TestExtractValidDistributedContextFromHTTPReq(t *testing.T) {
|
|||||||
totalDiff := ""
|
totalDiff := ""
|
||||||
wantCorCtx.Foreach(func(kv core.KeyValue) bool {
|
wantCorCtx.Foreach(func(kv core.KeyValue) bool {
|
||||||
val, _ := gotCorCtx.Value(kv.Key)
|
val, _ := gotCorCtx.Value(kv.Key)
|
||||||
diff := cmp.Diff(kv, core.KeyValue{Key: kv.Key, Value: val})
|
diff := cmp.Diff(kv, core.KeyValue{Key: kv.Key, Value: val}, cmp.AllowUnexported(core.Value{}))
|
||||||
if diff != "" {
|
if diff != "" {
|
||||||
totalDiff += diff + "\n"
|
totalDiff += diff + "\n"
|
||||||
}
|
}
|
||||||
@ -446,7 +446,7 @@ func TestInjectCorrelationContextToHTTPReq(t *testing.T) {
|
|||||||
"key6=123",
|
"key6=123",
|
||||||
"key7=123",
|
"key7=123",
|
||||||
"key8=123.567",
|
"key8=123.567",
|
||||||
"key9=123.56700134277344",
|
"key9=123.567",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -304,14 +304,13 @@ func TestSetSpanAttributes(t *testing.T) {
|
|||||||
},
|
},
|
||||||
ParentSpanID: sid,
|
ParentSpanID: sid,
|
||||||
Name: "SpanAttribute/span0",
|
Name: "SpanAttribute/span0",
|
||||||
Attributes: []core.KeyValue{{
|
Attributes: []core.KeyValue{
|
||||||
Key: core.Key("key1"),
|
key.String("key1", "value1"),
|
||||||
Value: core.Value{Type: core.STRING, String: "value1"},
|
},
|
||||||
}},
|
|
||||||
SpanKind: "internal",
|
SpanKind: "internal",
|
||||||
HasRemoteParent: true,
|
HasRemoteParent: true,
|
||||||
}
|
}
|
||||||
if diff := cmp.Diff(got, want); diff != "" {
|
if diff := cmpDiff(got, want); diff != "" {
|
||||||
t.Errorf("SetSpanAttributes: -got +want %s", diff)
|
t.Errorf("SetSpanAttributes: -got +want %s", diff)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -339,20 +338,14 @@ func TestSetSpanAttributesOverLimit(t *testing.T) {
|
|||||||
ParentSpanID: sid,
|
ParentSpanID: sid,
|
||||||
Name: "SpanAttributesOverLimit/span0",
|
Name: "SpanAttributesOverLimit/span0",
|
||||||
Attributes: []core.KeyValue{
|
Attributes: []core.KeyValue{
|
||||||
{
|
key.String("key1", "value3"),
|
||||||
Key: core.Key("key1"),
|
key.String("key4", "value4"),
|
||||||
Value: core.Value{Type: core.STRING, String: "value3"},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Key: core.Key("key4"),
|
|
||||||
Value: core.Value{Type: core.STRING, String: "value4"},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
SpanKind: "internal",
|
SpanKind: "internal",
|
||||||
HasRemoteParent: true,
|
HasRemoteParent: true,
|
||||||
DroppedAttributeCount: 1,
|
DroppedAttributeCount: 1,
|
||||||
}
|
}
|
||||||
if diff := cmp.Diff(got, want); diff != "" {
|
if diff := cmpDiff(got, want); diff != "" {
|
||||||
t.Errorf("SetSpanAttributesOverLimit: -got +want %s", diff)
|
t.Errorf("SetSpanAttributesOverLimit: -got +want %s", diff)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -396,7 +389,7 @@ func TestEvents(t *testing.T) {
|
|||||||
},
|
},
|
||||||
SpanKind: "internal",
|
SpanKind: "internal",
|
||||||
}
|
}
|
||||||
if diff := cmp.Diff(got, want, cmp.AllowUnexported(export.Event{})); diff != "" {
|
if diff := cmpDiff(got, want); diff != "" {
|
||||||
t.Errorf("Message Events: -got +want %s", diff)
|
t.Errorf("Message Events: -got +want %s", diff)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -447,7 +440,7 @@ func TestEventsOverLimit(t *testing.T) {
|
|||||||
HasRemoteParent: true,
|
HasRemoteParent: true,
|
||||||
SpanKind: "internal",
|
SpanKind: "internal",
|
||||||
}
|
}
|
||||||
if diff := cmp.Diff(got, want, cmp.AllowUnexported(export.Event{})); diff != "" {
|
if diff := cmpDiff(got, want); diff != "" {
|
||||||
t.Errorf("Message Event over limit: -got +want %s", diff)
|
t.Errorf("Message Event over limit: -got +want %s", diff)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -487,7 +480,7 @@ func TestAddLinks(t *testing.T) {
|
|||||||
},
|
},
|
||||||
SpanKind: "internal",
|
SpanKind: "internal",
|
||||||
}
|
}
|
||||||
if diff := cmp.Diff(got, want, cmp.AllowUnexported(export.Event{})); diff != "" {
|
if diff := cmpDiff(got, want); diff != "" {
|
||||||
t.Errorf("AddLink: -got +want %s", diff)
|
t.Errorf("AddLink: -got +want %s", diff)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -528,7 +521,7 @@ func TestLinks(t *testing.T) {
|
|||||||
},
|
},
|
||||||
SpanKind: "internal",
|
SpanKind: "internal",
|
||||||
}
|
}
|
||||||
if diff := cmp.Diff(got, want, cmp.AllowUnexported(export.Event{})); diff != "" {
|
if diff := cmpDiff(got, want); diff != "" {
|
||||||
t.Errorf("Link: -got +want %s", diff)
|
t.Errorf("Link: -got +want %s", diff)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -571,7 +564,7 @@ func TestLinksOverLimit(t *testing.T) {
|
|||||||
HasRemoteParent: true,
|
HasRemoteParent: true,
|
||||||
SpanKind: "internal",
|
SpanKind: "internal",
|
||||||
}
|
}
|
||||||
if diff := cmp.Diff(got, want, cmp.AllowUnexported(export.Event{})); diff != "" {
|
if diff := cmpDiff(got, want); diff != "" {
|
||||||
t.Errorf("Link over limit: -got +want %s", diff)
|
t.Errorf("Link over limit: -got +want %s", diff)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -620,11 +613,15 @@ func TestSetSpanStatus(t *testing.T) {
|
|||||||
Status: codes.Canceled,
|
Status: codes.Canceled,
|
||||||
HasRemoteParent: true,
|
HasRemoteParent: true,
|
||||||
}
|
}
|
||||||
if diff := cmp.Diff(got, want); diff != "" {
|
if diff := cmpDiff(got, want); diff != "" {
|
||||||
t.Errorf("SetSpanStatus: -got +want %s", diff)
|
t.Errorf("SetSpanStatus: -got +want %s", diff)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func cmpDiff(x, y interface{}) string {
|
||||||
|
return cmp.Diff(x, y, cmp.AllowUnexported(core.Value{}), cmp.AllowUnexported(export.Event{}))
|
||||||
|
}
|
||||||
|
|
||||||
func remoteSpanContext() core.SpanContext {
|
func remoteSpanContext() core.SpanContext {
|
||||||
return core.SpanContext{
|
return core.SpanContext{
|
||||||
TraceID: tid,
|
TraceID: tid,
|
||||||
|
Reference in New Issue
Block a user