value.go 4.8 KB

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