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