Skip to content

Commit d7b3115

Browse files
Make the AsType functions not panic (#3489)
* Make the AsType functions not panic * Adds changelog Signed-off-by: Aaron Clawson <[email protected]> Signed-off-by: Aaron Clawson <[email protected]> Co-authored-by: Chester Cheung <[email protected]>
1 parent 1f5e6ad commit d7b3115

File tree

3 files changed

+85
-8
lines changed

3 files changed

+85
-8
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
5252
- Asynchronous callbacks are only called if they are registered with at least one instrument that does not use drop aggragation. (#3408)
5353
- Do not report empty partial-success responses in the `go.opentelemetry.io/otel/exporters/otlp` exporters. (#3438, #3432)
5454
- Handle partial success responses in `go.opentelemetry.io/otel/exporters/otlp/otlpmetric` exporters. (#3162, #3440)
55+
- Prevents panic when using incorrect `attribute.Value.As[Type]Slice()`. (#3489)
5556

5657
## Removed
5758

attribute/kv_test.go

+48
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import (
1818
"testing"
1919

2020
"github.com/google/go-cmp/cmp"
21+
"github.com/stretchr/testify/assert"
2122

2223
"go.opentelemetry.io/otel/attribute"
2324
)
@@ -132,3 +133,50 @@ func TestKeyValueValid(t *testing.T) {
132133
}
133134
}
134135
}
136+
137+
func TestIncorrectCast(t *testing.T) {
138+
testCases := []struct {
139+
name string
140+
val attribute.Value
141+
}{
142+
{
143+
name: "Float64",
144+
val: attribute.Float64Value(1.0),
145+
},
146+
{
147+
name: "Int64",
148+
val: attribute.Int64Value(2),
149+
},
150+
{
151+
name: "String",
152+
val: attribute.BoolValue(true),
153+
},
154+
{
155+
name: "Float64Slice",
156+
val: attribute.Float64SliceValue([]float64{1.0}),
157+
},
158+
{
159+
name: "Int64Slice",
160+
val: attribute.Int64SliceValue([]int64{2}),
161+
},
162+
{
163+
name: "StringSlice",
164+
val: attribute.BoolSliceValue([]bool{true}),
165+
},
166+
}
167+
for _, tt := range testCases {
168+
t.Run(tt.name, func(t *testing.T) {
169+
assert.NotPanics(t, func() {
170+
tt.val.AsBool()
171+
tt.val.AsBoolSlice()
172+
tt.val.AsFloat64()
173+
tt.val.AsFloat64Slice()
174+
tt.val.AsInt64()
175+
tt.val.AsInt64Slice()
176+
tt.val.AsInterface()
177+
tt.val.AsString()
178+
tt.val.AsStringSlice()
179+
})
180+
})
181+
}
182+
}

attribute/value.go

+36-8
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,13 @@ func (v Value) AsBool() bool {
142142
// AsBoolSlice returns the []bool value. Make sure that the Value's type is
143143
// BOOLSLICE.
144144
func (v Value) AsBoolSlice() []bool {
145+
if v.vtype != BOOLSLICE {
146+
return nil
147+
}
148+
return v.asBoolSlice()
149+
}
150+
151+
func (v Value) asBoolSlice() []bool {
145152
return attribute.AsSlice[bool](v.slice)
146153
}
147154

@@ -154,6 +161,13 @@ func (v Value) AsInt64() int64 {
154161
// AsInt64Slice returns the []int64 value. Make sure that the Value's type is
155162
// INT64SLICE.
156163
func (v Value) AsInt64Slice() []int64 {
164+
if v.vtype != INT64SLICE {
165+
return nil
166+
}
167+
return v.asInt64Slice()
168+
}
169+
170+
func (v Value) asInt64Slice() []int64 {
157171
return attribute.AsSlice[int64](v.slice)
158172
}
159173

@@ -166,6 +180,13 @@ func (v Value) AsFloat64() float64 {
166180
// AsFloat64Slice returns the []float64 value. Make sure that the Value's type is
167181
// FLOAT64SLICE.
168182
func (v Value) AsFloat64Slice() []float64 {
183+
if v.vtype != FLOAT64SLICE {
184+
return nil
185+
}
186+
return v.asFloat64Slice()
187+
}
188+
189+
func (v Value) asFloat64Slice() []float64 {
169190
return attribute.AsSlice[float64](v.slice)
170191
}
171192

@@ -178,6 +199,13 @@ func (v Value) AsString() string {
178199
// AsStringSlice returns the []string value. Make sure that the Value's type is
179200
// STRINGSLICE.
180201
func (v Value) AsStringSlice() []string {
202+
if v.vtype != STRINGSLICE {
203+
return nil
204+
}
205+
return v.asStringSlice()
206+
}
207+
208+
func (v Value) asStringSlice() []string {
181209
return attribute.AsSlice[string](v.slice)
182210
}
183211

@@ -189,19 +217,19 @@ func (v Value) AsInterface() interface{} {
189217
case BOOL:
190218
return v.AsBool()
191219
case BOOLSLICE:
192-
return v.AsBoolSlice()
220+
return v.asBoolSlice()
193221
case INT64:
194222
return v.AsInt64()
195223
case INT64SLICE:
196-
return v.AsInt64Slice()
224+
return v.asInt64Slice()
197225
case FLOAT64:
198226
return v.AsFloat64()
199227
case FLOAT64SLICE:
200-
return v.AsFloat64Slice()
228+
return v.asFloat64Slice()
201229
case STRING:
202230
return v.stringly
203231
case STRINGSLICE:
204-
return v.AsStringSlice()
232+
return v.asStringSlice()
205233
}
206234
return unknownValueType{}
207235
}
@@ -210,19 +238,19 @@ func (v Value) AsInterface() interface{} {
210238
func (v Value) Emit() string {
211239
switch v.Type() {
212240
case BOOLSLICE:
213-
return fmt.Sprint(v.AsBoolSlice())
241+
return fmt.Sprint(v.asBoolSlice())
214242
case BOOL:
215243
return strconv.FormatBool(v.AsBool())
216244
case INT64SLICE:
217-
return fmt.Sprint(v.AsInt64Slice())
245+
return fmt.Sprint(v.asInt64Slice())
218246
case INT64:
219247
return strconv.FormatInt(v.AsInt64(), 10)
220248
case FLOAT64SLICE:
221-
return fmt.Sprint(v.AsFloat64Slice())
249+
return fmt.Sprint(v.asFloat64Slice())
222250
case FLOAT64:
223251
return fmt.Sprint(v.AsFloat64())
224252
case STRINGSLICE:
225-
return fmt.Sprint(v.AsStringSlice())
253+
return fmt.Sprint(v.asStringSlice())
226254
case STRING:
227255
return v.stringly
228256
default:

0 commit comments

Comments
 (0)