@@ -19,6 +19,7 @@ package attribute
1919import (
2020 "encoding/json"
2121 "fmt"
22+ "reflect"
2223 "strconv"
2324)
2425
@@ -30,6 +31,7 @@ type Value struct {
3031 vtype Type
3132 numeric uint64
3233 stringly string
34+ slice any
3335}
3436
3537const (
@@ -43,6 +45,14 @@ const (
4345 FLOAT64
4446 // STRING is a string Type Value.
4547 STRING
48+ // BOOLSLICE is a slice of booleans Type Value.
49+ BOOLSLICE
50+ // INT64SLICE is a slice of 64-bit signed integral numbers Type Value.
51+ INT64SLICE
52+ // FLOAT64SLICE is a slice of 64-bit floating point numbers Type Value.
53+ FLOAT64SLICE
54+ // STRINGSLICE is a slice of strings Type Value.
55+ STRINGSLICE
4656 // UINT64 is a 64-bit unsigned integral Type Value.
4757 //
4858 // This type is intentionally not exposed through the Builder API.
@@ -57,11 +67,30 @@ func BoolValue(v bool) Value {
5767 }
5868}
5969
70+ // BoolSliceValue creates a BOOLSLICE Value.
71+ func BoolSliceValue (v []bool ) Value {
72+ cp := reflect .New (reflect .ArrayOf (len (v ), reflect .TypeFor [bool ]())).Elem ()
73+ reflect .Copy (cp , reflect .ValueOf (v ))
74+ return Value {vtype : BOOLSLICE , slice : cp .Interface ()}
75+ }
76+
6077// IntValue creates an INT64 Value.
6178func IntValue (v int ) Value {
6279 return Int64Value (int64 (v ))
6380}
6481
82+ // IntSliceValue creates an INTSLICE Value.
83+ func IntSliceValue (v []int ) Value {
84+ cp := reflect .New (reflect .ArrayOf (len (v ), reflect .TypeFor [int64 ]()))
85+ for i , val := range v {
86+ cp .Elem ().Index (i ).SetInt (int64 (val ))
87+ }
88+ return Value {
89+ vtype : INT64SLICE ,
90+ slice : cp .Elem ().Interface (),
91+ }
92+ }
93+
6594// Int64Value creates an INT64 Value.
6695func Int64Value (v int64 ) Value {
6796 return Value {
@@ -70,6 +99,13 @@ func Int64Value(v int64) Value {
7099 }
71100}
72101
102+ // Int64SliceValue creates an INT64SLICE Value.
103+ func Int64SliceValue (v []int64 ) Value {
104+ cp := reflect .New (reflect .ArrayOf (len (v ), reflect .TypeFor [int64 ]())).Elem ()
105+ reflect .Copy (cp , reflect .ValueOf (v ))
106+ return Value {vtype : INT64SLICE , slice : cp .Interface ()}
107+ }
108+
73109// Float64Value creates a FLOAT64 Value.
74110func Float64Value (v float64 ) Value {
75111 return Value {
@@ -78,6 +114,13 @@ func Float64Value(v float64) Value {
78114 }
79115}
80116
117+ // Float64SliceValue creates a FLOAT64SLICE Value.
118+ func Float64SliceValue (v []float64 ) Value {
119+ cp := reflect .New (reflect .ArrayOf (len (v ), reflect .TypeFor [float64 ]())).Elem ()
120+ reflect .Copy (cp , reflect .ValueOf (v ))
121+ return Value {vtype : FLOAT64SLICE , slice : cp .Interface ()}
122+ }
123+
81124// StringValue creates a STRING Value.
82125func StringValue (v string ) Value {
83126 return Value {
@@ -86,6 +129,13 @@ func StringValue(v string) Value {
86129 }
87130}
88131
132+ // StringSliceValue creates a STRINGSLICE Value.
133+ func StringSliceValue (v []string ) Value {
134+ cp := reflect .New (reflect .ArrayOf (len (v ), reflect .TypeFor [string ]())).Elem ()
135+ reflect .Copy (cp , reflect .ValueOf (v ))
136+ return Value {vtype : STRINGSLICE , slice : cp .Interface ()}
137+ }
138+
89139// Uint64Value creates a UINT64 Value.
90140//
91141// This constructor is intentionally not exposed through the Builder API.
@@ -107,24 +157,60 @@ func (v Value) AsBool() bool {
107157 return rawToBool (v .numeric )
108158}
109159
160+ // AsBoolSlice returns the []bool value. Make sure that the Value's type is
161+ // BOOLSLICE.
162+ func (v Value ) AsBoolSlice () []bool {
163+ if v .vtype != BOOLSLICE {
164+ return nil
165+ }
166+ return asSlice [bool ](v .slice )
167+ }
168+
110169// AsInt64 returns the int64 value. Make sure that the Value's type is
111170// INT64.
112171func (v Value ) AsInt64 () int64 {
113172 return rawToInt64 (v .numeric )
114173}
115174
175+ // AsInt64Slice returns the []int64 value. Make sure that the Value's type is
176+ // INT64SLICE.
177+ func (v Value ) AsInt64Slice () []int64 {
178+ if v .vtype != INT64SLICE {
179+ return nil
180+ }
181+ return asSlice [int64 ](v .slice )
182+ }
183+
116184// AsFloat64 returns the float64 value. Make sure that the Value's
117185// type is FLOAT64.
118186func (v Value ) AsFloat64 () float64 {
119187 return rawToFloat64 (v .numeric )
120188}
121189
190+ // AsFloat64Slice returns the []float64 value. Make sure that the Value's type is
191+ // FLOAT64SLICE.
192+ func (v Value ) AsFloat64Slice () []float64 {
193+ if v .vtype != FLOAT64SLICE {
194+ return nil
195+ }
196+ return asSlice [float64 ](v .slice )
197+ }
198+
122199// AsString returns the string value. Make sure that the Value's type
123200// is STRING.
124201func (v Value ) AsString () string {
125202 return v .stringly
126203}
127204
205+ // AsStringSlice returns the []string value. Make sure that the Value's type is
206+ // STRINGSLICE.
207+ func (v Value ) AsStringSlice () []string {
208+ if v .vtype != STRINGSLICE {
209+ return nil
210+ }
211+ return asSlice [string ](v .slice )
212+ }
213+
128214// AsUint64 returns the uint64 value. Make sure that the Value's type is
129215// UINT64.
130216func (v Value ) AsUint64 () uint64 {
@@ -138,12 +224,20 @@ func (v Value) AsInterface() interface{} {
138224 switch v .Type () {
139225 case BOOL :
140226 return v .AsBool ()
227+ case BOOLSLICE :
228+ return v .AsBoolSlice ()
141229 case INT64 :
142230 return v .AsInt64 ()
231+ case INT64SLICE :
232+ return v .AsInt64Slice ()
143233 case FLOAT64 :
144234 return v .AsFloat64 ()
235+ case FLOAT64SLICE :
236+ return v .AsFloat64Slice ()
145237 case STRING :
146238 return v .stringly
239+ case STRINGSLICE :
240+ return v .AsStringSlice ()
147241 case UINT64 :
148242 return v .numeric
149243 }
@@ -153,12 +247,20 @@ func (v Value) AsInterface() interface{} {
153247// String returns a string representation of Value's data.
154248func (v Value ) String () string {
155249 switch v .Type () {
250+ case BOOLSLICE :
251+ return fmt .Sprint (v .AsBoolSlice ())
156252 case BOOL :
157253 return strconv .FormatBool (v .AsBool ())
254+ case INT64SLICE :
255+ return fmt .Sprint (v .AsInt64Slice ())
158256 case INT64 :
159257 return strconv .FormatInt (v .AsInt64 (), 10 )
258+ case FLOAT64SLICE :
259+ return fmt .Sprint (v .AsFloat64Slice ())
160260 case FLOAT64 :
161261 return fmt .Sprint (v .AsFloat64 ())
262+ case STRINGSLICE :
263+ return fmt .Sprint (v .AsStringSlice ())
162264 case STRING :
163265 return v .stringly
164266 case UINT64 :
@@ -183,12 +285,20 @@ func (t Type) String() string {
183285 switch t {
184286 case BOOL :
185287 return "bool"
288+ case BOOLSLICE :
289+ return "boolslice"
186290 case INT64 :
187291 return "int64"
292+ case INT64SLICE :
293+ return "int64slice"
188294 case FLOAT64 :
189295 return "float64"
296+ case FLOAT64SLICE :
297+ return "float64slice"
190298 case STRING :
191299 return "string"
300+ case STRINGSLICE :
301+ return "stringslice"
192302 case UINT64 :
193303 return "uint64"
194304 }
@@ -198,10 +308,14 @@ func (t Type) String() string {
198308// mapTypesToStr is a map from attribute.Type to the primitive types the server understands.
199309// https://develop.sentry.dev/sdk/foundations/data-model/attributes/#primitive-types
200310var mapTypesToStr = map [Type ]string {
201- INVALID : "" ,
202- BOOL : "boolean" ,
203- INT64 : "integer" ,
204- FLOAT64 : "double" ,
205- STRING : "string" ,
206- UINT64 : "integer" , // wire format: same "integer" type
311+ INVALID : "" ,
312+ BOOL : "boolean" ,
313+ INT64 : "integer" ,
314+ FLOAT64 : "double" ,
315+ STRING : "string" ,
316+ BOOLSLICE : "array" ,
317+ INT64SLICE : "array" ,
318+ FLOAT64SLICE : "array" ,
319+ STRINGSLICE : "array" ,
320+ UINT64 : "integer" , // wire format: same "integer" type
207321}
0 commit comments