Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add metrics support #252

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 88 additions & 0 deletions otlpclient/protobuf_common.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package otlpclient

// Implements just enough sugar on the OTel Protocol Buffers span definition
// to support otel-cli and no more.
//
// otel-cli does a few things that are awkward via the opentelemetry-go APIs
// which are restricted for good reasons.

import (
"sort"
"strconv"

commonpb "go.opentelemetry.io/proto/otlp/common/v1"
)

// StringMapAttrsToProtobuf takes a map of string:string, such as that from --attrs
// and returns them in an []*commonpb.KeyValue
func StringMapAttrsToProtobuf(attributes map[string]string) []*commonpb.KeyValue {
out := []*commonpb.KeyValue{}

for k, v := range attributes {
av := new(commonpb.AnyValue)

// try to parse as numbers, and fall through to string
if i, err := strconv.ParseInt(v, 0, 64); err == nil {
av.Value = &commonpb.AnyValue_IntValue{IntValue: i}
} else if f, err := strconv.ParseFloat(v, 64); err == nil {
av.Value = &commonpb.AnyValue_DoubleValue{DoubleValue: f}
} else if b, err := strconv.ParseBool(v); err == nil {
av.Value = &commonpb.AnyValue_BoolValue{BoolValue: b}
} else {
av.Value = &commonpb.AnyValue_StringValue{StringValue: v}
}

akv := commonpb.KeyValue{
Key: k,
Value: av,
}

out = append(out, &akv)
}

return out
}

// AttrValueToString coverts a commonpb.KeyValue attribute to a string.
// Only used by tests for now.
func AttrValueToString(attr *commonpb.KeyValue) string {
v := attr.GetValue()
v.GetIntValue()
if _, ok := v.Value.(*commonpb.AnyValue_StringValue); ok {
return v.GetStringValue()
} else if _, ok := v.Value.(*commonpb.AnyValue_IntValue); ok {
return strconv.FormatInt(v.GetIntValue(), 10)
} else if _, ok := v.Value.(*commonpb.AnyValue_DoubleValue); ok {
return strconv.FormatFloat(v.GetDoubleValue(), byte('f'), -1, 64)
}

return ""
}

// flattenStringMap takes a string map and returns it flattened into a string with
// keys sorted lexically so it should be mostly consistent enough for comparisons
// and printing. Output is k=v,k=v style like attributes input.
func flattenStringMap(mp map[string]string, emptyValue string) string {
if len(mp) == 0 {
return emptyValue
}

var out string
keys := make([]string, len(mp)) // for sorting
var i int
for k := range mp {
keys[i] = k
i++
}
sort.Strings(keys)

for i, k := range keys {
out = out + k + "=" + mp[k]
if i == len(keys)-1 {
break
}
out = out + ","
}

return out
}
55 changes: 55 additions & 0 deletions otlpclient/protobuf_common_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package otlpclient

import (
"testing"
)

func TestCliAttrsToOtel(t *testing.T) {

testAttrs := map[string]string{
"test 1 - string": "isn't testing fun?",
"test 2 - int64": "111111111",
"test 3 - float": "2.4391111",
"test 4 - bool, true": "true",
"test 5 - bool, false": "false",
"test 6 - bool, True": "True",
"test 7 - bool, False": "False",
}

otelAttrs := StringMapAttrsToProtobuf(testAttrs)

// can't count on any ordering from map -> array
for _, attr := range otelAttrs {
key := string(attr.Key)
switch key {
case "test 1 - string":
if attr.Value.GetStringValue() != testAttrs[key] {
t.Errorf("expected value '%s' for key '%s' but got '%s'", testAttrs[key], key, attr.Value.GetStringValue())
}
case "test 2 - int64":
if attr.Value.GetIntValue() != 111111111 {
t.Errorf("expected value '%s' for key '%s' but got %d", testAttrs[key], key, attr.Value.GetIntValue())
}
case "test 3 - float":
if attr.Value.GetDoubleValue() != 2.4391111 {
t.Errorf("expected value '%s' for key '%s' but got %f", testAttrs[key], key, attr.Value.GetDoubleValue())
}
case "test 4 - bool, true":
if attr.Value.GetBoolValue() != true {
t.Errorf("expected value '%s' for key '%s' but got %t", testAttrs[key], key, attr.Value.GetBoolValue())
}
case "test 5 - bool, false":
if attr.Value.GetBoolValue() != false {
t.Errorf("expected value '%s' for key '%s' but got %t", testAttrs[key], key, attr.Value.GetBoolValue())
}
case "test 6 - bool, True":
if attr.Value.GetBoolValue() != true {
t.Errorf("expected value '%s' for key '%s' but got %t", testAttrs[key], key, attr.Value.GetBoolValue())
}
case "test 7 - bool, False":
if attr.Value.GetBoolValue() != false {
t.Errorf("expected value '%s' for key '%s' but got %t", testAttrs[key], key, attr.Value.GetBoolValue())
}
}
}
}
87 changes: 6 additions & 81 deletions otlpclient/protobuf_span.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ package otlpclient
import (
"crypto/rand"
"encoding/hex"
"sort"
"strconv"
"time"

Expand Down Expand Up @@ -155,46 +154,6 @@ func SpanStatusStringToInt(status string) tracepb.Status_StatusCode {
}
}

// StringMapAttrsToProtobuf takes a map of string:string, such as that from --attrs
// and returns them in an []*commonpb.KeyValue
func StringMapAttrsToProtobuf(attributes map[string]string) []*commonpb.KeyValue {
out := []*commonpb.KeyValue{}

for k, v := range attributes {
av := new(commonpb.AnyValue)

// try to parse as numbers, and fall through to string
if i, err := strconv.ParseInt(v, 0, 64); err == nil {
av.Value = &commonpb.AnyValue_IntValue{IntValue: i}
} else if f, err := strconv.ParseFloat(v, 64); err == nil {
av.Value = &commonpb.AnyValue_DoubleValue{DoubleValue: f}
} else if b, err := strconv.ParseBool(v); err == nil {
av.Value = &commonpb.AnyValue_BoolValue{BoolValue: b}
} else {
av.Value = &commonpb.AnyValue_StringValue{StringValue: v}
}

akv := commonpb.KeyValue{
Key: k,
Value: av,
}

out = append(out, &akv)
}

return out
}

// SpanAttributesToStringMap converts the span's attributes to a string map.
// Only used by tests for now.
func SpanAttributesToStringMap(span *tracepb.Span) map[string]string {
out := make(map[string]string)
for _, attr := range span.Attributes {
out[attr.Key] = AttrValueToString(attr)
}
return out
}

// ResourceAttributesToStringMap converts the ResourceSpan's resource attributes to a string map.
// Only used by tests for now.
func ResourceAttributesToStringMap(rss *tracepb.ResourceSpans) map[string]string {
Expand All @@ -209,20 +168,14 @@ func ResourceAttributesToStringMap(rss *tracepb.ResourceSpans) map[string]string
return out
}

// AttrValueToString coverts a commonpb.KeyValue attribute to a string.
// SpanAttributesToStringMap converts the span's attributes to a string map.
// Only used by tests for now.
func AttrValueToString(attr *commonpb.KeyValue) string {
v := attr.GetValue()
v.GetIntValue()
if _, ok := v.Value.(*commonpb.AnyValue_StringValue); ok {
return v.GetStringValue()
} else if _, ok := v.Value.(*commonpb.AnyValue_IntValue); ok {
return strconv.FormatInt(v.GetIntValue(), 10)
} else if _, ok := v.Value.(*commonpb.AnyValue_DoubleValue); ok {
return strconv.FormatFloat(v.GetDoubleValue(), byte('f'), -1, 64)
func SpanAttributesToStringMap(span *tracepb.Span) map[string]string {
out := make(map[string]string)
for _, attr := range span.Attributes {
out[attr.Key] = AttrValueToString(attr)
}

return ""
return out
}

// SpanToStringMap converts a span with some extra data into a stringmap.
Expand Down Expand Up @@ -256,31 +209,3 @@ func TraceparentFromProtobufSpan(span *tracepb.Span, recording bool) traceparent
Initialized: true,
}
}

// flattenStringMap takes a string map and returns it flattened into a string with
// keys sorted lexically so it should be mostly consistent enough for comparisons
// and printing. Output is k=v,k=v style like attributes input.
func flattenStringMap(mp map[string]string, emptyValue string) string {
if len(mp) == 0 {
return emptyValue
}

var out string
keys := make([]string, len(mp)) // for sorting
var i int
for k := range mp {
keys[i] = k
i++
}
sort.Strings(keys)

for i, k := range keys {
out = out + k + "=" + mp[k]
if i == len(keys)-1 {
break
}
out = out + ","
}

return out
}
50 changes: 0 additions & 50 deletions otlpclient/protobuf_span_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -181,53 +181,3 @@ func TestSpanStatusStringToInt(t *testing.T) {
})
}
}

func TestCliAttrsToOtel(t *testing.T) {

testAttrs := map[string]string{
"test 1 - string": "isn't testing fun?",
"test 2 - int64": "111111111",
"test 3 - float": "2.4391111",
"test 4 - bool, true": "true",
"test 5 - bool, false": "false",
"test 6 - bool, True": "True",
"test 7 - bool, False": "False",
}

otelAttrs := StringMapAttrsToProtobuf(testAttrs)

// can't count on any ordering from map -> array
for _, attr := range otelAttrs {
key := string(attr.Key)
switch key {
case "test 1 - string":
if attr.Value.GetStringValue() != testAttrs[key] {
t.Errorf("expected value '%s' for key '%s' but got '%s'", testAttrs[key], key, attr.Value.GetStringValue())
}
case "test 2 - int64":
if attr.Value.GetIntValue() != 111111111 {
t.Errorf("expected value '%s' for key '%s' but got %d", testAttrs[key], key, attr.Value.GetIntValue())
}
case "test 3 - float":
if attr.Value.GetDoubleValue() != 2.4391111 {
t.Errorf("expected value '%s' for key '%s' but got %f", testAttrs[key], key, attr.Value.GetDoubleValue())
}
case "test 4 - bool, true":
if attr.Value.GetBoolValue() != true {
t.Errorf("expected value '%s' for key '%s' but got %t", testAttrs[key], key, attr.Value.GetBoolValue())
}
case "test 5 - bool, false":
if attr.Value.GetBoolValue() != false {
t.Errorf("expected value '%s' for key '%s' but got %t", testAttrs[key], key, attr.Value.GetBoolValue())
}
case "test 6 - bool, True":
if attr.Value.GetBoolValue() != true {
t.Errorf("expected value '%s' for key '%s' but got %t", testAttrs[key], key, attr.Value.GetBoolValue())
}
case "test 7 - bool, False":
if attr.Value.GetBoolValue() != false {
t.Errorf("expected value '%s' for key '%s' but got %t", testAttrs[key], key, attr.Value.GetBoolValue())
}
}
}
}