value.go 11 KB

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