value.go 11 KB

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