value.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452
  1. // Copyright The OpenTelemetry Authors
  2. // SPDX-License-Identifier: Apache-2.0
  3. //go:generate stringer -type=ValueKind -trimprefix=ValueKind
  4. package telemetry
  5. import (
  6. "bytes"
  7. "cmp"
  8. "encoding/base64"
  9. "encoding/json"
  10. "errors"
  11. "fmt"
  12. "io"
  13. "math"
  14. "slices"
  15. "strconv"
  16. "unsafe"
  17. )
  18. // A Value represents a structured value.
  19. // A zero value is valid and represents an empty value.
  20. type Value struct {
  21. // Ensure forward compatibility by explicitly making this not comparable.
  22. noCmp [0]func() //nolint: unused // This is indeed used.
  23. // num holds the value for Int64, Float64, and Bool. It holds the length
  24. // for String, Bytes, Slice, Map.
  25. num uint64
  26. // any holds either the KindBool, KindInt64, KindFloat64, stringptr,
  27. // bytesptr, sliceptr, or mapptr. If KindBool, KindInt64, or KindFloat64
  28. // then the value of Value is in num as described above. Otherwise, it
  29. // contains the value wrapped in the appropriate type.
  30. any any
  31. }
  32. type (
  33. // sliceptr represents a value in Value.any for KindString Values.
  34. stringptr *byte
  35. // bytesptr represents a value in Value.any for KindBytes Values.
  36. bytesptr *byte
  37. // sliceptr represents a value in Value.any for KindSlice Values.
  38. sliceptr *Value
  39. // mapptr represents a value in Value.any for KindMap Values.
  40. mapptr *Attr
  41. )
  42. // ValueKind is the kind of a [Value].
  43. type ValueKind int
  44. // ValueKind values.
  45. const (
  46. ValueKindEmpty ValueKind = iota
  47. ValueKindBool
  48. ValueKindFloat64
  49. ValueKindInt64
  50. ValueKindString
  51. ValueKindBytes
  52. ValueKindSlice
  53. ValueKindMap
  54. )
  55. var valueKindStrings = []string{
  56. "Empty",
  57. "Bool",
  58. "Float64",
  59. "Int64",
  60. "String",
  61. "Bytes",
  62. "Slice",
  63. "Map",
  64. }
  65. func (k ValueKind) String() string {
  66. if k >= 0 && int(k) < len(valueKindStrings) {
  67. return valueKindStrings[k]
  68. }
  69. return "<unknown telemetry.ValueKind>"
  70. }
  71. // StringValue returns a new [Value] for a string.
  72. func StringValue(v string) Value {
  73. return Value{
  74. num: uint64(len(v)),
  75. any: stringptr(unsafe.StringData(v)),
  76. }
  77. }
  78. // IntValue returns a [Value] for an int.
  79. func IntValue(v int) Value { return Int64Value(int64(v)) }
  80. // Int64Value returns a [Value] for an int64.
  81. func Int64Value(v int64) Value {
  82. return Value{num: uint64(v), any: ValueKindInt64}
  83. }
  84. // Float64Value returns a [Value] for a float64.
  85. func Float64Value(v float64) Value {
  86. return Value{num: math.Float64bits(v), any: ValueKindFloat64}
  87. }
  88. // BoolValue returns a [Value] for a bool.
  89. func BoolValue(v bool) Value { //nolint:revive // Not a control flag.
  90. var n uint64
  91. if v {
  92. n = 1
  93. }
  94. return Value{num: n, any: ValueKindBool}
  95. }
  96. // BytesValue returns a [Value] for a byte slice. The passed slice must not be
  97. // changed after it is passed.
  98. func BytesValue(v []byte) Value {
  99. return Value{
  100. num: uint64(len(v)),
  101. any: bytesptr(unsafe.SliceData(v)),
  102. }
  103. }
  104. // SliceValue returns a [Value] for a slice of [Value]. The passed slice must
  105. // not be changed after it is passed.
  106. func SliceValue(vs ...Value) Value {
  107. return Value{
  108. num: uint64(len(vs)),
  109. any: sliceptr(unsafe.SliceData(vs)),
  110. }
  111. }
  112. // MapValue returns a new [Value] for a slice of key-value pairs. The passed
  113. // slice must not be changed after it is passed.
  114. func MapValue(kvs ...Attr) Value {
  115. return Value{
  116. num: uint64(len(kvs)),
  117. any: mapptr(unsafe.SliceData(kvs)),
  118. }
  119. }
  120. // AsString returns the value held by v as a string.
  121. func (v Value) AsString() string {
  122. if sp, ok := v.any.(stringptr); ok {
  123. return unsafe.String(sp, v.num)
  124. }
  125. // TODO: error handle
  126. return ""
  127. }
  128. // asString returns the value held by v as a string. It will panic if the Value
  129. // is not KindString.
  130. func (v Value) asString() string {
  131. return unsafe.String(v.any.(stringptr), v.num)
  132. }
  133. // AsInt64 returns the value held by v as an int64.
  134. func (v Value) AsInt64() int64 {
  135. if v.Kind() != ValueKindInt64 {
  136. // TODO: error handle
  137. return 0
  138. }
  139. return v.asInt64()
  140. }
  141. // asInt64 returns the value held by v as an int64. If v is not of KindInt64,
  142. // this will return garbage.
  143. func (v Value) asInt64() int64 {
  144. // Assumes v.num was a valid int64 (overflow not checked).
  145. return int64(v.num) // nolint: gosec
  146. }
  147. // AsBool returns the value held by v as a bool.
  148. func (v Value) AsBool() bool {
  149. if v.Kind() != ValueKindBool {
  150. // TODO: error handle
  151. return false
  152. }
  153. return v.asBool()
  154. }
  155. // asBool returns the value held by v as a bool. If v is not of KindBool, this
  156. // will return garbage.
  157. func (v Value) asBool() bool { return v.num == 1 }
  158. // AsFloat64 returns the value held by v as a float64.
  159. func (v Value) AsFloat64() float64 {
  160. if v.Kind() != ValueKindFloat64 {
  161. // TODO: error handle
  162. return 0
  163. }
  164. return v.asFloat64()
  165. }
  166. // asFloat64 returns the value held by v as a float64. If v is not of
  167. // KindFloat64, this will return garbage.
  168. func (v Value) asFloat64() float64 { return math.Float64frombits(v.num) }
  169. // AsBytes returns the value held by v as a []byte.
  170. func (v Value) AsBytes() []byte {
  171. if sp, ok := v.any.(bytesptr); ok {
  172. return unsafe.Slice((*byte)(sp), v.num)
  173. }
  174. // TODO: error handle
  175. return nil
  176. }
  177. // asBytes returns the value held by v as a []byte. It will panic if the Value
  178. // is not KindBytes.
  179. func (v Value) asBytes() []byte {
  180. return unsafe.Slice((*byte)(v.any.(bytesptr)), v.num)
  181. }
  182. // AsSlice returns the value held by v as a []Value.
  183. func (v Value) AsSlice() []Value {
  184. if sp, ok := v.any.(sliceptr); ok {
  185. return unsafe.Slice((*Value)(sp), v.num)
  186. }
  187. // TODO: error handle
  188. return nil
  189. }
  190. // asSlice returns the value held by v as a []Value. It will panic if the Value
  191. // is not KindSlice.
  192. func (v Value) asSlice() []Value {
  193. return unsafe.Slice((*Value)(v.any.(sliceptr)), v.num)
  194. }
  195. // AsMap returns the value held by v as a []Attr.
  196. func (v Value) AsMap() []Attr {
  197. if sp, ok := v.any.(mapptr); ok {
  198. return unsafe.Slice((*Attr)(sp), v.num)
  199. }
  200. // TODO: error handle
  201. return nil
  202. }
  203. // asMap returns the value held by v as a []Attr. It will panic if the
  204. // Value is not KindMap.
  205. func (v Value) asMap() []Attr {
  206. return unsafe.Slice((*Attr)(v.any.(mapptr)), v.num)
  207. }
  208. // Kind returns the Kind of v.
  209. func (v Value) Kind() ValueKind {
  210. switch x := v.any.(type) {
  211. case ValueKind:
  212. return x
  213. case stringptr:
  214. return ValueKindString
  215. case bytesptr:
  216. return ValueKindBytes
  217. case sliceptr:
  218. return ValueKindSlice
  219. case mapptr:
  220. return ValueKindMap
  221. default:
  222. return ValueKindEmpty
  223. }
  224. }
  225. // Empty returns if v does not hold any value.
  226. func (v Value) Empty() bool { return v.Kind() == ValueKindEmpty }
  227. // Equal returns if v is equal to w.
  228. func (v Value) Equal(w Value) bool {
  229. k1 := v.Kind()
  230. k2 := w.Kind()
  231. if k1 != k2 {
  232. return false
  233. }
  234. switch k1 {
  235. case ValueKindInt64, ValueKindBool:
  236. return v.num == w.num
  237. case ValueKindString:
  238. return v.asString() == w.asString()
  239. case ValueKindFloat64:
  240. return v.asFloat64() == w.asFloat64()
  241. case ValueKindSlice:
  242. return slices.EqualFunc(v.asSlice(), w.asSlice(), Value.Equal)
  243. case ValueKindMap:
  244. sv := sortMap(v.asMap())
  245. sw := sortMap(w.asMap())
  246. return slices.EqualFunc(sv, sw, Attr.Equal)
  247. case ValueKindBytes:
  248. return bytes.Equal(v.asBytes(), w.asBytes())
  249. case ValueKindEmpty:
  250. return true
  251. default:
  252. // TODO: error handle
  253. return false
  254. }
  255. }
  256. func sortMap(m []Attr) []Attr {
  257. sm := make([]Attr, len(m))
  258. copy(sm, m)
  259. slices.SortFunc(sm, func(a, b Attr) int {
  260. return cmp.Compare(a.Key, b.Key)
  261. })
  262. return sm
  263. }
  264. // String returns Value's value as a string, formatted like [fmt.Sprint].
  265. //
  266. // The returned string is meant for debugging;
  267. // the string representation is not stable.
  268. func (v Value) String() string {
  269. switch v.Kind() {
  270. case ValueKindString:
  271. return v.asString()
  272. case ValueKindInt64:
  273. // Assumes v.num was a valid int64 (overflow not checked).
  274. return strconv.FormatInt(int64(v.num), 10) // nolint: gosec
  275. case ValueKindFloat64:
  276. return strconv.FormatFloat(v.asFloat64(), 'g', -1, 64)
  277. case ValueKindBool:
  278. return strconv.FormatBool(v.asBool())
  279. case ValueKindBytes:
  280. return fmt.Sprint(v.asBytes())
  281. case ValueKindMap:
  282. return fmt.Sprint(v.asMap())
  283. case ValueKindSlice:
  284. return fmt.Sprint(v.asSlice())
  285. case ValueKindEmpty:
  286. return "<nil>"
  287. default:
  288. // Try to handle this as gracefully as possible.
  289. //
  290. // Don't panic here. The goal here is to have developers find this
  291. // first if a slog.Kind is is not handled. It is
  292. // preferable to have user's open issue asking why their attributes
  293. // have a "unhandled: " prefix than say that their code is panicking.
  294. return fmt.Sprintf("<unhandled telemetry.ValueKind: %s>", v.Kind())
  295. }
  296. }
  297. // MarshalJSON encodes v into OTLP formatted JSON.
  298. func (v *Value) MarshalJSON() ([]byte, error) {
  299. switch v.Kind() {
  300. case ValueKindString:
  301. return json.Marshal(struct {
  302. Value string `json:"stringValue"`
  303. }{v.asString()})
  304. case ValueKindInt64:
  305. return json.Marshal(struct {
  306. Value string `json:"intValue"`
  307. }{strconv.FormatInt(int64(v.num), 10)})
  308. case ValueKindFloat64:
  309. return json.Marshal(struct {
  310. Value float64 `json:"doubleValue"`
  311. }{v.asFloat64()})
  312. case ValueKindBool:
  313. return json.Marshal(struct {
  314. Value bool `json:"boolValue"`
  315. }{v.asBool()})
  316. case ValueKindBytes:
  317. return json.Marshal(struct {
  318. Value []byte `json:"bytesValue"`
  319. }{v.asBytes()})
  320. case ValueKindMap:
  321. return json.Marshal(struct {
  322. Value struct {
  323. Values []Attr `json:"values"`
  324. } `json:"kvlistValue"`
  325. }{struct {
  326. Values []Attr `json:"values"`
  327. }{v.asMap()}})
  328. case ValueKindSlice:
  329. return json.Marshal(struct {
  330. Value struct {
  331. Values []Value `json:"values"`
  332. } `json:"arrayValue"`
  333. }{struct {
  334. Values []Value `json:"values"`
  335. }{v.asSlice()}})
  336. case ValueKindEmpty:
  337. return nil, nil
  338. default:
  339. return nil, fmt.Errorf("unknown Value kind: %s", v.Kind().String())
  340. }
  341. }
  342. // UnmarshalJSON decodes the OTLP formatted JSON contained in data into v.
  343. func (v *Value) UnmarshalJSON(data []byte) error {
  344. decoder := json.NewDecoder(bytes.NewReader(data))
  345. t, err := decoder.Token()
  346. if err != nil {
  347. return err
  348. }
  349. if t != json.Delim('{') {
  350. return errors.New("invalid Value type")
  351. }
  352. for decoder.More() {
  353. keyIface, err := decoder.Token()
  354. if err != nil {
  355. if errors.Is(err, io.EOF) {
  356. // Empty.
  357. return nil
  358. }
  359. return err
  360. }
  361. key, ok := keyIface.(string)
  362. if !ok {
  363. return fmt.Errorf("invalid Value key: %#v", keyIface)
  364. }
  365. switch key {
  366. case "stringValue", "string_value":
  367. var val string
  368. err = decoder.Decode(&val)
  369. *v = StringValue(val)
  370. case "boolValue", "bool_value":
  371. var val bool
  372. err = decoder.Decode(&val)
  373. *v = BoolValue(val)
  374. case "intValue", "int_value":
  375. var val protoInt64
  376. err = decoder.Decode(&val)
  377. *v = Int64Value(val.Int64())
  378. case "doubleValue", "double_value":
  379. var val float64
  380. err = decoder.Decode(&val)
  381. *v = Float64Value(val)
  382. case "bytesValue", "bytes_value":
  383. var val64 string
  384. if err := decoder.Decode(&val64); err != nil {
  385. return err
  386. }
  387. var val []byte
  388. val, err = base64.StdEncoding.DecodeString(val64)
  389. *v = BytesValue(val)
  390. case "arrayValue", "array_value":
  391. var val struct{ Values []Value }
  392. err = decoder.Decode(&val)
  393. *v = SliceValue(val.Values...)
  394. case "kvlistValue", "kvlist_value":
  395. var val struct{ Values []Attr }
  396. err = decoder.Decode(&val)
  397. *v = MapValue(val.Values...)
  398. default:
  399. // Skip unknown.
  400. continue
  401. }
  402. // Use first valid. Ignore the rest.
  403. return err
  404. }
  405. // Only unknown fields. Return nil without unmarshaling any value.
  406. return nil
  407. }