Tempo: Fix trace kvlist and array transformations (#96388)

* Fix kvlist and array transformations

* Log transformation errors
This commit is contained in:
Andre Pereira 2024-11-15 09:35:41 +00:00 committed by GitHub
parent d8d1886938
commit 65b50b67c4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 103 additions and 13 deletions

View File

@ -1342,6 +1342,42 @@
"value": {
"string_value": "net/http"
}
},
{
"key": "arrayAttribute",
"value": {
"array_value": {
"values": [
{
"string_value": "value1"
},
{
"string_value": "value2"
}
]
}
}
},
{
"key": "kvlistAttribute",
"value": {
"kvlist_value": {
"values": [
{
"key": "key1",
"value": {
"string_value": "value1"
}
},
{
"key": "key2",
"value": {
"string_value": "value2"
}
}
]
}
}
}
],
"status": {}

View File

@ -194,33 +194,79 @@ func resourceToProcess(resource *v1.Resource) (string, []*KeyValue) {
if attribute.Key(attr.Key) == semconv.ServiceNameKey {
serviceName = attr.GetValue().GetStringValue()
}
tags = append(tags, &KeyValue{Key: attr.Key, Value: getAttributeVal(attr.Value)})
val, err := getAttributeVal(attr.Value)
if err != nil {
logger.Debug("error transforming resource to process", "err", err)
}
tags = append(tags, &KeyValue{Key: attr.Key, Value: val})
}
return serviceName, tags
}
func getAttributeVal(attr *commonv11.AnyValue) any {
func getAttributeVal(attr *commonv11.AnyValue) (any, error) {
switch attr.GetValue().(type) {
case *commonv11.AnyValue_StringValue:
return attr.GetStringValue()
return attr.GetStringValue(), nil
case *commonv11.AnyValue_IntValue:
return attr.GetIntValue()
return attr.GetIntValue(), nil
case *commonv11.AnyValue_BoolValue:
return attr.GetBoolValue()
return attr.GetBoolValue(), nil
case *commonv11.AnyValue_DoubleValue:
return attr.GetDoubleValue()
case *commonv11.AnyValue_KvlistValue, *commonv11.AnyValue_ArrayValue:
return attr.GetStringValue()
return attr.GetDoubleValue(), nil
case *commonv11.AnyValue_KvlistValue:
return kvListAsString(attr.GetKvlistValue())
case *commonv11.AnyValue_ArrayValue:
return arrayAsString(attr.GetArrayValue())
default:
return nil
return attr.GetStringValue(), nil
}
}
func arrayAsString(list *commonv11.ArrayValue) (string, error) {
vals := make([]any, len(list.GetValues()))
for i, val := range list.GetValues() {
v, err := getAttributeVal(val)
if err != nil {
return "", fmt.Errorf("failed to get attribute value: %w", err)
}
vals[i] = v
}
res, err := json.Marshal(vals)
if err != nil {
return "", fmt.Errorf("failed to marshal array: %w", err)
}
return string(res), nil
}
func kvListAsString(list *commonv11.KeyValueList) (string, error) {
vals := make(map[string]any, len(list.GetValues()))
for _, val := range list.GetValues() {
v, err := getAttributeVal(val.GetValue())
if err != nil {
return "", fmt.Errorf("failed to get attribute value: %w", err)
}
vals[val.GetKey()] = v
}
res, err := json.Marshal(vals)
if err != nil {
return "", fmt.Errorf("failed to marshal kvlist: %w", err)
}
return string(res), nil
}
func getSpanTags(span *tracev11.Span) []*KeyValue {
tags := make([]*KeyValue, len(span.Attributes))
for i, attr := range span.Attributes {
tags[i] = &KeyValue{Key: attr.Key, Value: getAttributeVal(attr.Value)}
val, err := getAttributeVal(attr.Value)
if err != nil {
logger.Debug("error transforming span tags", "err", err)
}
tags[i] = &KeyValue{Key: attr.Key, Value: val}
}
return tags
}
@ -255,7 +301,11 @@ func spanEventsToLogs(events []*tracev11.Span_Event) []*TraceLog {
event := events[i]
fields := make([]*KeyValue, 0, len(event.Attributes)+1)
for _, attr := range event.Attributes {
fields = append(fields, &KeyValue{Key: attr.Key, Value: getAttributeVal(attr.Value)})
val, err := getAttributeVal(attr.Value)
if err != nil {
logger.Debug("error transforming span events to logs", "err", err)
}
fields = append(fields, &KeyValue{Key: attr.Key, Value: val})
}
logs = append(logs, &TraceLog{
Timestamp: float64(event.TimeUnixNano) / 1_000_000,
@ -285,7 +335,11 @@ func spanLinksToReferences(links []*tracev11.Span_Link) []*TraceReference {
tags := make([]*KeyValue, 0, len(link.Attributes))
for _, attr := range link.Attributes {
tags = append(tags, &KeyValue{Key: attr.Key, Value: getAttributeVal(attr.Value)})
val, err := getAttributeVal(attr.Value)
if err != nil {
logger.Debug("error transforming span links to references", "err", err)
}
tags = append(tags, &KeyValue{Key: attr.Key, Value: val})
}
references = append(references, &TraceReference{

View File

@ -45,7 +45,7 @@ func TestTraceToFrame(t *testing.T) {
require.Equal(t, 1616072924070.497, root["startTime"])
require.Equal(t, 8.421, root["duration"])
require.Equal(t, json.RawMessage("null"), root["logs"])
require.Equal(t, json.RawMessage("[{\"value\":\"const\",\"key\":\"sampler.type\"},{\"value\":true,\"key\":\"sampler.param\"},{\"value\":200,\"key\":\"http.status_code\"},{\"value\":\"GET\",\"key\":\"http.method\"},{\"value\":\"/loki/api/v1/query_range?direction=BACKWARD\\u0026limit=1000\\u0026query=%7Bcompose_project%3D%22devenv%22%7D%20%7C%3D%22trace_id%22\\u0026start=1616070921000000000\\u0026end=1616072722000000000\\u0026step=2\",\"key\":\"http.url\"},{\"value\":\"net/http\",\"key\":\"component\"}]"), root["tags"])
require.Equal(t, json.RawMessage("[{\"value\":\"const\",\"key\":\"sampler.type\"},{\"value\":true,\"key\":\"sampler.param\"},{\"value\":200,\"key\":\"http.status_code\"},{\"value\":\"GET\",\"key\":\"http.method\"},{\"value\":\"/loki/api/v1/query_range?direction=BACKWARD\\u0026limit=1000\\u0026query=%7Bcompose_project%3D%22devenv%22%7D%20%7C%3D%22trace_id%22\\u0026start=1616070921000000000\\u0026end=1616072722000000000\\u0026step=2\",\"key\":\"http.url\"},{\"value\":\"net/http\",\"key\":\"component\"},{\"value\":\"[\\\"value1\\\",\\\"value2\\\"]\",\"key\":\"arrayAttribute\"},{\"value\":\"{\\\"key1\\\":\\\"value1\\\",\\\"key2\\\":\\\"value2\\\"}\",\"key\":\"kvlistAttribute\"}]"), root["tags"])
span := bFrame.FindRowWithValue("spanID", "7198307df9748606")