Skip to content

Commit

Permalink
expand set of translated exemplar attributes
Browse files Browse the repository at this point in the history
  • Loading branch information
dashpole committed Oct 13, 2023
1 parent ed1c628 commit c70c998
Show file tree
Hide file tree
Showing 2 changed files with 278 additions and 82 deletions.
136 changes: 114 additions & 22 deletions bridge/opencensus/internal/ocmetric/metric.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"fmt"
"reflect"
"sort"
"strconv"

ocmetricdata "go.opencensus.io/metric/metricdata"
octrace "go.opencensus.io/trace"
Expand All @@ -28,13 +29,12 @@ import (
)

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

// ConvertMetrics converts metric data from OpenCensus to OpenTelemetry.
Expand Down Expand Up @@ -206,12 +206,7 @@ func convertExemplar(ocExemplar *ocmetricdata.Exemplar) (metricdata.Exemplar[flo
exemplar.SpanID = sc.SpanID[:]
exemplar.TraceID = sc.TraceID[:]
default:
kv := convertKV(k, v)
if !kv.Valid() {
err = errors.Join(err, fmt.Errorf("%w; type: %v", errInvalidExemplarAttachmentValue, reflect.TypeOf(v)))
continue
}
exemplar.FilteredAttributes = append(exemplar.FilteredAttributes, kv)
exemplar.FilteredAttributes = append(exemplar.FilteredAttributes, convertKV(k, v))
}
}
sortable := attribute.Sortable(exemplar.FilteredAttributes)
Expand All @@ -224,28 +219,125 @@ func convertKV(key string, value any) attribute.KeyValue {
switch typedVal := value.(type) {
case bool:
return attribute.Bool(key, typedVal)
case []bool:
return attribute.BoolSlice(key, typedVal)
case int:
return attribute.Int(key, typedVal)
case []int:
return attribute.IntSlice(key, typedVal)
case int8:
return attribute.Int(key, int(typedVal))
case int16:
return attribute.Int(key, int(typedVal))
case int32:
return attribute.Int(key, int(typedVal))
case int64:
return attribute.Int64(key, typedVal)
case []int64:
return attribute.Int64Slice(key, typedVal)
case uint:
return uintKV(key, typedVal)
case uint8:
return uintKV(key, uint(typedVal))
case uint16:
return uintKV(key, uint(typedVal))
case uint32:
return uintKV(key, uint(typedVal))
case uintptr:
return uint64KV(key, uint64(typedVal))
case uint64:
return uint64KV(key, uint64(typedVal))
case float32:
return attribute.Float64(key, float64(typedVal))
case float64:
return attribute.Float64(key, typedVal)
case []float64:
return attribute.Float64Slice(key, typedVal)
case complex64:
return attribute.String(key, complexToString(typedVal))
case complex128:
return attribute.String(key, complexToString(typedVal))
case string:
return attribute.String(key, typedVal)
case []bool:
return attribute.BoolSlice(key, typedVal)
case []int:
return attribute.IntSlice(key, typedVal)
case []int8:
return intSliceKV(key, typedVal)
case []int16:
return intSliceKV(key, typedVal)
case []int32:
return intSliceKV(key, typedVal)
case []int64:
return attribute.Int64Slice(key, typedVal)
case []uint:
return uintSliceKV(key, typedVal)
case []uint8:
return uintSliceKV(key, typedVal)
case []uint16:
return uintSliceKV(key, typedVal)
case []uint32:
return uintSliceKV(key, typedVal)
case []uintptr:
return uintSliceKV(key, typedVal)
case []uint64:
return uintSliceKV(key, typedVal)
case []float32:
floatSlice := make([]float64, len(typedVal))
for i := range typedVal {
floatSlice[i] = float64(typedVal[i])
}
return attribute.Float64Slice(key, floatSlice)
case []float64:
return attribute.Float64Slice(key, typedVal)
case []complex64:
return complexSliceKV(key, typedVal)
case []complex128:
return complexSliceKV(key, typedVal)
case []string:
return attribute.StringSlice(key, typedVal)
case fmt.Stringer:
return attribute.Stringer(key, typedVal)
default:
return attribute.String(key, fmt.Sprintf("unhandled attribute value: %+v", value))
}
}

func intSliceKV[N int8 | int16 | int32](key string, val []N) attribute.KeyValue {
intSlice := make([]int, len(val))
for i := range val {
intSlice[i] = int(val[i])
}
return attribute.IntSlice(key, intSlice)
}

func uintKV(key string, val uint) attribute.KeyValue {
const maxInt = ^uint(0) >> 1
if val > maxInt {
return uint64KV(key, uint64(val))
}
return attribute.Int(key, int(val))
}

func uintSliceKV[N uint | uint8 | uint16 | uint32 | uint64 | uintptr](key string, val []N) attribute.KeyValue {
strSlice := make([]string, len(val))
for i := range val {
strSlice[i] = strconv.FormatUint(uint64(val[i]), 10)
}
return attribute.KeyValue{}
return attribute.StringSlice(key, strSlice)
}

func uint64KV(key string, val uint64) attribute.KeyValue {
const maxInt64 = ^uint64(0) >> 1
if val > maxInt64 {
return attribute.String(key, strconv.FormatUint(val, 10))
}
return attribute.Int64(key, int64(val))
}

func complexSliceKV[N complex64 | complex128](key string, val []N) attribute.KeyValue {
strSlice := make([]string, len(val))
for i := range val {
strSlice[i] = complexToString(val[i])
}
return attribute.StringSlice(key, strSlice)
}

func complexToString[N complex64 | complex128](val N) string {
return strconv.FormatComplex(complex128(val), 'f', -1, 64)
}

// convertAttrs converts from OpenCensus attribute keys and values to an
Expand Down
Loading

0 comments on commit c70c998

Please sign in to comment.