Skip to content

Commit df68b86

Browse files
committed
expand set of translated exemplar attributes
1 parent 2729fba commit df68b86

File tree

2 files changed

+278
-82
lines changed

2 files changed

+278
-82
lines changed

bridge/opencensus/internal/ocmetric/metric.go

Lines changed: 114 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import (
1919
"fmt"
2020
"reflect"
2121
"sort"
22+
"strconv"
2223

2324
ocmetricdata "go.opencensus.io/metric/metricdata"
2425
octrace "go.opencensus.io/trace"
@@ -28,13 +29,12 @@ import (
2829
)
2930

3031
var (
31-
errAggregationType = errors.New("unsupported OpenCensus aggregation type")
32-
errMismatchedValueTypes = errors.New("wrong value type for data point")
33-
errNegativeDistributionCount = errors.New("distribution count is negative")
34-
errNegativeBucketCount = errors.New("distribution bucket count is negative")
35-
errMismatchedAttributeKeyValues = errors.New("mismatched number of attribute keys and values")
36-
errInvalidExemplarSpanContext = errors.New("span context exemplar attachment does not contain an OpenCensus SpanContext")
37-
errInvalidExemplarAttachmentValue = errors.New("exemplar attachment is not a supported OpenTelemetry attribute type")
32+
errAggregationType = errors.New("unsupported OpenCensus aggregation type")
33+
errMismatchedValueTypes = errors.New("wrong value type for data point")
34+
errNegativeDistributionCount = errors.New("distribution count is negative")
35+
errNegativeBucketCount = errors.New("distribution bucket count is negative")
36+
errMismatchedAttributeKeyValues = errors.New("mismatched number of attribute keys and values")
37+
errInvalidExemplarSpanContext = errors.New("span context exemplar attachment does not contain an OpenCensus SpanContext")
3838
)
3939

4040
// ConvertMetrics converts metric data from OpenCensus to OpenTelemetry.
@@ -206,12 +206,7 @@ func convertExemplar(ocExemplar *ocmetricdata.Exemplar) (metricdata.Exemplar[flo
206206
exemplar.SpanID = sc.SpanID[:]
207207
exemplar.TraceID = sc.TraceID[:]
208208
default:
209-
kv := convertKV(k, v)
210-
if !kv.Valid() {
211-
err = errors.Join(err, fmt.Errorf("%w; type: %v", errInvalidExemplarAttachmentValue, reflect.TypeOf(v)))
212-
continue
213-
}
214-
exemplar.FilteredAttributes = append(exemplar.FilteredAttributes, kv)
209+
exemplar.FilteredAttributes = append(exemplar.FilteredAttributes, convertKV(k, v))
215210
}
216211
}
217212
sortable := attribute.Sortable(exemplar.FilteredAttributes)
@@ -224,28 +219,125 @@ func convertKV(key string, value any) attribute.KeyValue {
224219
switch typedVal := value.(type) {
225220
case bool:
226221
return attribute.Bool(key, typedVal)
227-
case []bool:
228-
return attribute.BoolSlice(key, typedVal)
229222
case int:
230223
return attribute.Int(key, typedVal)
231-
case []int:
232-
return attribute.IntSlice(key, typedVal)
224+
case int8:
225+
return attribute.Int(key, int(typedVal))
226+
case int16:
227+
return attribute.Int(key, int(typedVal))
228+
case int32:
229+
return attribute.Int(key, int(typedVal))
233230
case int64:
234231
return attribute.Int64(key, typedVal)
235-
case []int64:
236-
return attribute.Int64Slice(key, typedVal)
232+
case uint:
233+
return uintKV(key, typedVal)
234+
case uint8:
235+
return uintKV(key, uint(typedVal))
236+
case uint16:
237+
return uintKV(key, uint(typedVal))
238+
case uint32:
239+
return uintKV(key, uint(typedVal))
240+
case uintptr:
241+
return uint64KV(key, uint64(typedVal))
242+
case uint64:
243+
return uint64KV(key, uint64(typedVal))
244+
case float32:
245+
return attribute.Float64(key, float64(typedVal))
237246
case float64:
238247
return attribute.Float64(key, typedVal)
239-
case []float64:
240-
return attribute.Float64Slice(key, typedVal)
248+
case complex64:
249+
return attribute.String(key, complexToString(typedVal))
250+
case complex128:
251+
return attribute.String(key, complexToString(typedVal))
241252
case string:
242253
return attribute.String(key, typedVal)
254+
case []bool:
255+
return attribute.BoolSlice(key, typedVal)
256+
case []int:
257+
return attribute.IntSlice(key, typedVal)
258+
case []int8:
259+
return intSliceKV(key, typedVal)
260+
case []int16:
261+
return intSliceKV(key, typedVal)
262+
case []int32:
263+
return intSliceKV(key, typedVal)
264+
case []int64:
265+
return attribute.Int64Slice(key, typedVal)
266+
case []uint:
267+
return uintSliceKV(key, typedVal)
268+
case []uint8:
269+
return uintSliceKV(key, typedVal)
270+
case []uint16:
271+
return uintSliceKV(key, typedVal)
272+
case []uint32:
273+
return uintSliceKV(key, typedVal)
274+
case []uintptr:
275+
return uintSliceKV(key, typedVal)
276+
case []uint64:
277+
return uintSliceKV(key, typedVal)
278+
case []float32:
279+
floatSlice := make([]float64, len(typedVal))
280+
for i := range typedVal {
281+
floatSlice[i] = float64(typedVal[i])
282+
}
283+
return attribute.Float64Slice(key, floatSlice)
284+
case []float64:
285+
return attribute.Float64Slice(key, typedVal)
286+
case []complex64:
287+
return complexSliceKV(key, typedVal)
288+
case []complex128:
289+
return complexSliceKV(key, typedVal)
243290
case []string:
244291
return attribute.StringSlice(key, typedVal)
245292
case fmt.Stringer:
246293
return attribute.Stringer(key, typedVal)
294+
default:
295+
return attribute.String(key, fmt.Sprintf("unhandled attribute value: %+v", value))
296+
}
297+
}
298+
299+
func intSliceKV[N int8 | int16 | int32](key string, val []N) attribute.KeyValue {
300+
intSlice := make([]int, len(val))
301+
for i := range val {
302+
intSlice[i] = int(val[i])
303+
}
304+
return attribute.IntSlice(key, intSlice)
305+
}
306+
307+
func uintKV(key string, val uint) attribute.KeyValue {
308+
const maxInt = ^uint(0) >> 1
309+
if val > maxInt {
310+
return uint64KV(key, uint64(val))
311+
}
312+
return attribute.Int(key, int(val))
313+
}
314+
315+
func uintSliceKV[N uint | uint8 | uint16 | uint32 | uint64 | uintptr](key string, val []N) attribute.KeyValue {
316+
strSlice := make([]string, len(val))
317+
for i := range val {
318+
strSlice[i] = strconv.FormatUint(uint64(val[i]), 10)
247319
}
248-
return attribute.KeyValue{}
320+
return attribute.StringSlice(key, strSlice)
321+
}
322+
323+
func uint64KV(key string, val uint64) attribute.KeyValue {
324+
const maxInt64 = ^uint64(0) >> 1
325+
if val > maxInt64 {
326+
return attribute.String(key, strconv.FormatUint(val, 10))
327+
}
328+
return attribute.Int64(key, int64(val))
329+
}
330+
331+
func complexSliceKV[N complex64 | complex128](key string, val []N) attribute.KeyValue {
332+
strSlice := make([]string, len(val))
333+
for i := range val {
334+
strSlice[i] = complexToString(val[i])
335+
}
336+
return attribute.StringSlice(key, strSlice)
337+
}
338+
339+
func complexToString[N complex64 | complex128](val N) string {
340+
return strconv.FormatComplex(complex128(val), 'f', -1, 64)
249341
}
250342

251343
// convertAttrs converts from OpenCensus attribute keys and values to an

0 commit comments

Comments
 (0)