1// Copyright The OpenTelemetry Authors 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15package label // import "go.opentelemetry.io/otel/label" 16 17import ( 18 "encoding/json" 19 "fmt" 20 "reflect" 21 "strconv" 22 "unsafe" 23 24 "go.opentelemetry.io/otel/internal" 25) 26 27//go:generate stringer -type=Type 28 29// Type describes the type of the data Value holds. 30type Type int 31 32// Value represents the value part in key-value pairs. 33type Value struct { 34 vtype Type 35 numeric uint64 36 stringly string 37 // TODO Lazy value type? 38 39 array interface{} 40} 41 42const ( 43 // INVALID is used for a Value with no value set. 44 INVALID Type = iota 45 // BOOL is a boolean Type Value. 46 BOOL 47 // INT32 is a 32-bit signed integral Type Value. 48 INT32 49 // INT64 is a 64-bit signed integral Type Value. 50 INT64 51 // UINT32 is a 32-bit unsigned integral Type Value. 52 UINT32 53 // UINT64 is a 64-bit unsigned integral Type Value. 54 UINT64 55 // FLOAT32 is a 32-bit floating point Type Value. 56 FLOAT32 57 // FLOAT64 is a 64-bit floating point Type Value. 58 FLOAT64 59 // STRING is a string Type Value. 60 STRING 61 // ARRAY is an array Type Value used to store 1-dimensional slices or 62 // arrays of bool, int, int32, int64, uint, uint32, uint64, float, 63 // float32, float64, or string types. 64 ARRAY 65) 66 67// BoolValue creates a BOOL Value. 68func BoolValue(v bool) Value { 69 return Value{ 70 vtype: BOOL, 71 numeric: internal.BoolToRaw(v), 72 } 73} 74 75// Int64Value creates an INT64 Value. 76func Int64Value(v int64) Value { 77 return Value{ 78 vtype: INT64, 79 numeric: internal.Int64ToRaw(v), 80 } 81} 82 83// Uint64Value creates a UINT64 Value. 84func Uint64Value(v uint64) Value { 85 return Value{ 86 vtype: UINT64, 87 numeric: internal.Uint64ToRaw(v), 88 } 89} 90 91// Float64Value creates a FLOAT64 Value. 92func Float64Value(v float64) Value { 93 return Value{ 94 vtype: FLOAT64, 95 numeric: internal.Float64ToRaw(v), 96 } 97} 98 99// Int32Value creates an INT32 Value. 100func Int32Value(v int32) Value { 101 return Value{ 102 vtype: INT32, 103 numeric: internal.Int32ToRaw(v), 104 } 105} 106 107// Uint32Value creates a UINT32 Value. 108func Uint32Value(v uint32) Value { 109 return Value{ 110 vtype: UINT32, 111 numeric: internal.Uint32ToRaw(v), 112 } 113} 114 115// Float32Value creates a FLOAT32 Value. 116func Float32Value(v float32) Value { 117 return Value{ 118 vtype: FLOAT32, 119 numeric: internal.Float32ToRaw(v), 120 } 121} 122 123// StringValue creates a STRING Value. 124func StringValue(v string) Value { 125 return Value{ 126 vtype: STRING, 127 stringly: v, 128 } 129} 130 131// IntValue creates either an INT32 or an INT64 Value, depending on whether 132// the int type is 32 or 64 bits wide. 133func IntValue(v int) Value { 134 if unsafe.Sizeof(v) == 4 { 135 return Int32Value(int32(v)) 136 } 137 return Int64Value(int64(v)) 138} 139 140// UintValue creates either a UINT32 or a UINT64 Value, depending on whether 141// the uint type is 32 or 64 bits wide. 142func UintValue(v uint) Value { 143 if unsafe.Sizeof(v) == 4 { 144 return Uint32Value(uint32(v)) 145 } 146 return Uint64Value(uint64(v)) 147} 148 149// ArrayValue creates an ARRAY value from an array or slice. 150// Only arrays or slices of bool, int, int32, int64, uint, uint32, uint64, 151// float, float32, float64, or string types are allowed. Specifically, arrays 152// and slices can not contain other arrays, slices, structs, or non-standard 153// types. If the passed value is not an array or slice of these types an 154// INVALID value is returned. 155func ArrayValue(v interface{}) Value { 156 switch reflect.TypeOf(v).Kind() { 157 case reflect.Array, reflect.Slice: 158 // get array type regardless of dimensions 159 typ := reflect.TypeOf(v).Elem() 160 kind := typ.Kind() 161 switch kind { 162 case reflect.Bool, reflect.Int, reflect.Int32, reflect.Int64, 163 reflect.Float32, reflect.Float64, reflect.String, 164 reflect.Uint, reflect.Uint32, reflect.Uint64: 165 val := reflect.ValueOf(v) 166 length := val.Len() 167 frozen := reflect.Indirect(reflect.New(reflect.ArrayOf(length, typ))) 168 reflect.Copy(frozen, val) 169 return Value{ 170 vtype: ARRAY, 171 array: frozen.Interface(), 172 } 173 default: 174 return Value{vtype: INVALID} 175 } 176 } 177 return Value{vtype: INVALID} 178} 179 180// Type returns a type of the Value. 181func (v Value) Type() Type { 182 return v.vtype 183} 184 185// AsBool returns the bool value. Make sure that the Value's type is 186// BOOL. 187func (v Value) AsBool() bool { 188 return internal.RawToBool(v.numeric) 189} 190 191// AsInt32 returns the int32 value. Make sure that the Value's type is 192// INT32. 193func (v Value) AsInt32() int32 { 194 return internal.RawToInt32(v.numeric) 195} 196 197// AsInt64 returns the int64 value. Make sure that the Value's type is 198// INT64. 199func (v Value) AsInt64() int64 { 200 return internal.RawToInt64(v.numeric) 201} 202 203// AsUint32 returns the uint32 value. Make sure that the Value's type 204// is UINT32. 205func (v Value) AsUint32() uint32 { 206 return internal.RawToUint32(v.numeric) 207} 208 209// AsUint64 returns the uint64 value. Make sure that the Value's type is 210// UINT64. 211func (v Value) AsUint64() uint64 { 212 return internal.RawToUint64(v.numeric) 213} 214 215// AsFloat32 returns the float32 value. Make sure that the Value's 216// type is FLOAT32. 217func (v Value) AsFloat32() float32 { 218 return internal.RawToFloat32(v.numeric) 219} 220 221// AsFloat64 returns the float64 value. Make sure that the Value's 222// type is FLOAT64. 223func (v Value) AsFloat64() float64 { 224 return internal.RawToFloat64(v.numeric) 225} 226 227// AsString returns the string value. Make sure that the Value's type 228// is STRING. 229func (v Value) AsString() string { 230 return v.stringly 231} 232 233// AsArray returns the array Value as an interface{}. 234func (v Value) AsArray() interface{} { 235 return v.array 236} 237 238type unknownValueType struct{} 239 240// AsInterface returns Value's data as interface{}. 241func (v Value) AsInterface() interface{} { 242 switch v.Type() { 243 case ARRAY: 244 return v.AsArray() 245 case BOOL: 246 return v.AsBool() 247 case INT32: 248 return v.AsInt32() 249 case INT64: 250 return v.AsInt64() 251 case UINT32: 252 return v.AsUint32() 253 case UINT64: 254 return v.AsUint64() 255 case FLOAT32: 256 return v.AsFloat32() 257 case FLOAT64: 258 return v.AsFloat64() 259 case STRING: 260 return v.stringly 261 } 262 return unknownValueType{} 263} 264 265// Emit returns a string representation of Value's data. 266func (v Value) Emit() string { 267 switch v.Type() { 268 case ARRAY: 269 return fmt.Sprint(v.array) 270 case BOOL: 271 return strconv.FormatBool(v.AsBool()) 272 case INT32: 273 return strconv.FormatInt(int64(v.AsInt32()), 10) 274 case INT64: 275 return strconv.FormatInt(v.AsInt64(), 10) 276 case UINT32: 277 return strconv.FormatUint(uint64(v.AsUint32()), 10) 278 case UINT64: 279 return strconv.FormatUint(v.AsUint64(), 10) 280 case FLOAT32: 281 return fmt.Sprint(v.AsFloat32()) 282 case FLOAT64: 283 return fmt.Sprint(v.AsFloat64()) 284 case STRING: 285 return v.stringly 286 default: 287 return "unknown" 288 } 289} 290 291// MarshalJSON returns the JSON encoding of the Value. 292func (v Value) MarshalJSON() ([]byte, error) { 293 var jsonVal struct { 294 Type string 295 Value interface{} 296 } 297 jsonVal.Type = v.Type().String() 298 jsonVal.Value = v.AsInterface() 299 return json.Marshal(jsonVal) 300} 301