value.go 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  1. // Copyright The OpenTelemetry Authors
  2. // SPDX-License-Identifier: Apache-2.0
  3. package attribute // import "go.opentelemetry.io/otel/attribute"
  4. import (
  5. "encoding/json"
  6. "fmt"
  7. "strconv"
  8. attribute "go.opentelemetry.io/otel/attribute/internal"
  9. )
  10. //go:generate stringer -type=Type
  11. // Type describes the type of the data Value holds.
  12. type Type int // nolint: revive // redefines builtin Type.
  13. // Value represents the value part in key-value pairs.
  14. //
  15. // Note that the zero value is a valid empty value.
  16. type Value struct {
  17. vtype Type
  18. numeric uint64
  19. stringly string
  20. slice any
  21. }
  22. const (
  23. // EMPTY is used for a Value with no value set.
  24. EMPTY Type = iota
  25. // BOOL is a boolean Type Value.
  26. BOOL
  27. // INT64 is a 64-bit signed integral Type Value.
  28. INT64
  29. // FLOAT64 is a 64-bit floating point Type Value.
  30. FLOAT64
  31. // STRING is a string Type Value.
  32. STRING
  33. // BOOLSLICE is a slice of booleans Type Value.
  34. BOOLSLICE
  35. // INT64SLICE is a slice of 64-bit signed integral numbers Type Value.
  36. INT64SLICE
  37. // FLOAT64SLICE is a slice of 64-bit floating point numbers Type Value.
  38. FLOAT64SLICE
  39. // STRINGSLICE is a slice of strings Type Value.
  40. STRINGSLICE
  41. // INVALID is used for a Value with no value set.
  42. //
  43. // Deprecated: Use EMPTY instead as an empty value is a valid value.
  44. INVALID = EMPTY
  45. )
  46. // BoolValue creates a BOOL Value.
  47. func BoolValue(v bool) Value {
  48. return Value{
  49. vtype: BOOL,
  50. numeric: boolToRaw(v),
  51. }
  52. }
  53. // BoolSliceValue creates a BOOLSLICE Value.
  54. func BoolSliceValue(v []bool) Value {
  55. return Value{vtype: BOOLSLICE, slice: attribute.SliceValue(v)}
  56. }
  57. // IntValue creates an INT64 Value.
  58. func IntValue(v int) Value {
  59. return Int64Value(int64(v))
  60. }
  61. // IntSliceValue creates an INT64SLICE Value.
  62. func IntSliceValue(v []int) Value {
  63. val := Value{vtype: INT64SLICE}
  64. // Avoid the common tiny-slice cases from allocating a new slice.
  65. switch len(v) {
  66. case 0:
  67. val.slice = [0]int64{}
  68. case 1:
  69. val.slice = [1]int64{int64(v[0])}
  70. case 2:
  71. val.slice = [2]int64{int64(v[0]), int64(v[1])}
  72. case 3:
  73. val.slice = [3]int64{int64(v[0]), int64(v[1]), int64(v[2])}
  74. default:
  75. // Fallback to a new slice for larger slices.
  76. cp := make([]int64, len(v))
  77. for i, val := range v {
  78. cp[i] = int64(val)
  79. }
  80. val.slice = attribute.SliceValue(cp)
  81. }
  82. return val
  83. }
  84. // Int64Value creates an INT64 Value.
  85. func Int64Value(v int64) Value {
  86. return Value{
  87. vtype: INT64,
  88. numeric: int64ToRaw(v),
  89. }
  90. }
  91. // Int64SliceValue creates an INT64SLICE Value.
  92. func Int64SliceValue(v []int64) Value {
  93. return Value{vtype: INT64SLICE, slice: attribute.SliceValue(v)}
  94. }
  95. // Float64Value creates a FLOAT64 Value.
  96. func Float64Value(v float64) Value {
  97. return Value{
  98. vtype: FLOAT64,
  99. numeric: float64ToRaw(v),
  100. }
  101. }
  102. // Float64SliceValue creates a FLOAT64SLICE Value.
  103. func Float64SliceValue(v []float64) Value {
  104. return Value{vtype: FLOAT64SLICE, slice: attribute.SliceValue(v)}
  105. }
  106. // StringValue creates a STRING Value.
  107. func StringValue(v string) Value {
  108. return Value{
  109. vtype: STRING,
  110. stringly: v,
  111. }
  112. }
  113. // StringSliceValue creates a STRINGSLICE Value.
  114. func StringSliceValue(v []string) Value {
  115. return Value{vtype: STRINGSLICE, slice: attribute.SliceValue(v)}
  116. }
  117. // Type returns a type of the Value.
  118. func (v Value) Type() Type {
  119. return v.vtype
  120. }
  121. // AsBool returns the bool value. Make sure that the Value's type is
  122. // BOOL.
  123. func (v Value) AsBool() bool {
  124. return rawToBool(v.numeric)
  125. }
  126. // AsBoolSlice returns the []bool value. Make sure that the Value's type is
  127. // BOOLSLICE.
  128. func (v Value) AsBoolSlice() []bool {
  129. if v.vtype != BOOLSLICE {
  130. return nil
  131. }
  132. return v.asBoolSlice()
  133. }
  134. func (v Value) asBoolSlice() []bool {
  135. return attribute.AsSlice[bool](v.slice)
  136. }
  137. // AsInt64 returns the int64 value. Make sure that the Value's type is
  138. // INT64.
  139. func (v Value) AsInt64() int64 {
  140. return rawToInt64(v.numeric)
  141. }
  142. // AsInt64Slice returns the []int64 value. Make sure that the Value's type is
  143. // INT64SLICE.
  144. func (v Value) AsInt64Slice() []int64 {
  145. if v.vtype != INT64SLICE {
  146. return nil
  147. }
  148. return v.asInt64Slice()
  149. }
  150. func (v Value) asInt64Slice() []int64 {
  151. return attribute.AsSlice[int64](v.slice)
  152. }
  153. // AsFloat64 returns the float64 value. Make sure that the Value's
  154. // type is FLOAT64.
  155. func (v Value) AsFloat64() float64 {
  156. return rawToFloat64(v.numeric)
  157. }
  158. // AsFloat64Slice returns the []float64 value. Make sure that the Value's type is
  159. // FLOAT64SLICE.
  160. func (v Value) AsFloat64Slice() []float64 {
  161. if v.vtype != FLOAT64SLICE {
  162. return nil
  163. }
  164. return v.asFloat64Slice()
  165. }
  166. func (v Value) asFloat64Slice() []float64 {
  167. return attribute.AsSlice[float64](v.slice)
  168. }
  169. // AsString returns the string value. Make sure that the Value's type
  170. // is STRING.
  171. func (v Value) AsString() string {
  172. return v.stringly
  173. }
  174. // AsStringSlice returns the []string value. Make sure that the Value's type is
  175. // STRINGSLICE.
  176. func (v Value) AsStringSlice() []string {
  177. if v.vtype != STRINGSLICE {
  178. return nil
  179. }
  180. return v.asStringSlice()
  181. }
  182. func (v Value) asStringSlice() []string {
  183. return attribute.AsSlice[string](v.slice)
  184. }
  185. type unknownValueType struct{}
  186. // AsInterface returns Value's data as any.
  187. func (v Value) AsInterface() any {
  188. switch v.Type() {
  189. case BOOL:
  190. return v.AsBool()
  191. case BOOLSLICE:
  192. return v.asBoolSlice()
  193. case INT64:
  194. return v.AsInt64()
  195. case INT64SLICE:
  196. return v.asInt64Slice()
  197. case FLOAT64:
  198. return v.AsFloat64()
  199. case FLOAT64SLICE:
  200. return v.asFloat64Slice()
  201. case STRING:
  202. return v.stringly
  203. case STRINGSLICE:
  204. return v.asStringSlice()
  205. case EMPTY:
  206. return nil
  207. }
  208. return unknownValueType{}
  209. }
  210. // Emit returns a string representation of Value's data.
  211. func (v Value) Emit() string {
  212. switch v.Type() {
  213. case BOOLSLICE:
  214. return fmt.Sprint(v.asBoolSlice())
  215. case BOOL:
  216. return strconv.FormatBool(v.AsBool())
  217. case INT64SLICE:
  218. j, err := json.Marshal(v.asInt64Slice())
  219. if err != nil {
  220. return fmt.Sprintf("invalid: %v", v.asInt64Slice())
  221. }
  222. return string(j)
  223. case INT64:
  224. return strconv.FormatInt(v.AsInt64(), 10)
  225. case FLOAT64SLICE:
  226. j, err := json.Marshal(v.asFloat64Slice())
  227. if err != nil {
  228. return fmt.Sprintf("invalid: %v", v.asFloat64Slice())
  229. }
  230. return string(j)
  231. case FLOAT64:
  232. return fmt.Sprint(v.AsFloat64())
  233. case STRINGSLICE:
  234. j, err := json.Marshal(v.asStringSlice())
  235. if err != nil {
  236. return fmt.Sprintf("invalid: %v", v.asStringSlice())
  237. }
  238. return string(j)
  239. case STRING:
  240. return v.stringly
  241. case EMPTY:
  242. return ""
  243. default:
  244. return "unknown"
  245. }
  246. }
  247. // MarshalJSON returns the JSON encoding of the Value.
  248. func (v Value) MarshalJSON() ([]byte, error) {
  249. var jsonVal struct {
  250. Type string
  251. Value any
  252. }
  253. jsonVal.Type = v.Type().String()
  254. jsonVal.Value = v.AsInterface()
  255. return json.Marshal(jsonVal)
  256. }