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 attribute // import "go.opentelemetry.io/otel/attribute" 16 17import ( 18 "encoding/json" 19 "fmt" 20 "reflect" 21 "strconv" 22 23 "go.opentelemetry.io/otel/internal" 24) 25 26//go:generate stringer -type=Type 27 28// Type describes the type of the data Value holds. 29type Type int 30 31// Value represents the value part in key-value pairs. 32type Value struct { 33 vtype Type 34 numeric uint64 35 stringly string 36 // TODO Lazy value type? 37 38 array interface{} 39} 40 41const ( 42 // INVALID is used for a Value with no value set. 43 INVALID Type = iota 44 // BOOL is a boolean Type Value. 45 BOOL 46 // INT64 is a 64-bit signed integral Type Value. 47 INT64 48 // FLOAT64 is a 64-bit floating point Type Value. 49 FLOAT64 50 // STRING is a string Type Value. 51 STRING 52 // ARRAY is an array Type Value used to store 1-dimensional slices or 53 // arrays of bool, int, int32, int64, uint, uint32, uint64, float, 54 // float32, float64, or string types. 55 ARRAY 56) 57 58// BoolValue creates a BOOL Value. 59func BoolValue(v bool) Value { 60 return Value{ 61 vtype: BOOL, 62 numeric: internal.BoolToRaw(v), 63 } 64} 65 66// Int64Value creates an INT64 Value. 67func Int64Value(v int64) Value { 68 return Value{ 69 vtype: INT64, 70 numeric: internal.Int64ToRaw(v), 71 } 72} 73 74// Float64Value creates a FLOAT64 Value. 75func Float64Value(v float64) Value { 76 return Value{ 77 vtype: FLOAT64, 78 numeric: internal.Float64ToRaw(v), 79 } 80} 81 82// StringValue creates a STRING Value. 83func StringValue(v string) Value { 84 return Value{ 85 vtype: STRING, 86 stringly: v, 87 } 88} 89 90// IntValue creates an INT64 Value. 91func IntValue(v int) Value { 92 return Int64Value(int64(v)) 93} 94 95// ArrayValue creates an ARRAY value from an array or slice. 96// Only arrays or slices of bool, int, int64, float, float64, or string types are allowed. 97// Specifically, arrays and slices can not contain other arrays, slices, structs, or non-standard 98// types. If the passed value is not an array or slice of these types an 99// INVALID value is returned. 100func ArrayValue(v interface{}) Value { 101 switch reflect.TypeOf(v).Kind() { 102 case reflect.Array, reflect.Slice: 103 // get array type regardless of dimensions 104 typ := reflect.TypeOf(v).Elem() 105 kind := typ.Kind() 106 switch kind { 107 case reflect.Bool, reflect.Int, reflect.Int64, 108 reflect.Float64, reflect.String: 109 val := reflect.ValueOf(v) 110 length := val.Len() 111 frozen := reflect.Indirect(reflect.New(reflect.ArrayOf(length, typ))) 112 reflect.Copy(frozen, val) 113 return Value{ 114 vtype: ARRAY, 115 array: frozen.Interface(), 116 } 117 default: 118 return Value{vtype: INVALID} 119 } 120 } 121 return Value{vtype: INVALID} 122} 123 124// Type returns a type of the Value. 125func (v Value) Type() Type { 126 return v.vtype 127} 128 129// AsBool returns the bool value. Make sure that the Value's type is 130// BOOL. 131func (v Value) AsBool() bool { 132 return internal.RawToBool(v.numeric) 133} 134 135// AsInt64 returns the int64 value. Make sure that the Value's type is 136// INT64. 137func (v Value) AsInt64() int64 { 138 return internal.RawToInt64(v.numeric) 139} 140 141// AsFloat64 returns the float64 value. Make sure that the Value's 142// type is FLOAT64. 143func (v Value) AsFloat64() float64 { 144 return internal.RawToFloat64(v.numeric) 145} 146 147// AsString returns the string value. Make sure that the Value's type 148// is STRING. 149func (v Value) AsString() string { 150 return v.stringly 151} 152 153// AsArray returns the array Value as an interface{}. 154func (v Value) AsArray() interface{} { 155 return v.array 156} 157 158type unknownValueType struct{} 159 160// AsInterface returns Value's data as interface{}. 161func (v Value) AsInterface() interface{} { 162 switch v.Type() { 163 case ARRAY: 164 return v.AsArray() 165 case BOOL: 166 return v.AsBool() 167 case INT64: 168 return v.AsInt64() 169 case FLOAT64: 170 return v.AsFloat64() 171 case STRING: 172 return v.stringly 173 } 174 return unknownValueType{} 175} 176 177// Emit returns a string representation of Value's data. 178func (v Value) Emit() string { 179 switch v.Type() { 180 case ARRAY: 181 return fmt.Sprint(v.array) 182 case BOOL: 183 return strconv.FormatBool(v.AsBool()) 184 case INT64: 185 return strconv.FormatInt(v.AsInt64(), 10) 186 case FLOAT64: 187 return fmt.Sprint(v.AsFloat64()) 188 case STRING: 189 return v.stringly 190 default: 191 return "unknown" 192 } 193} 194 195// MarshalJSON returns the JSON encoding of the Value. 196func (v Value) MarshalJSON() ([]byte, error) { 197 var jsonVal struct { 198 Type string 199 Value interface{} 200 } 201 jsonVal.Type = v.Type().String() 202 jsonVal.Value = v.AsInterface() 203 return json.Marshal(jsonVal) 204} 205