Skip to content

Commit

Permalink
Add InstrumentationLibrary info to Zipkin/Jaeger exporters
Browse files Browse the repository at this point in the history
  • Loading branch information
evantorrie committed Sep 2, 2020
1 parent 440c4bd commit df86b7c
Show file tree
Hide file tree
Showing 5 changed files with 156 additions and 8 deletions.
12 changes: 8 additions & 4 deletions exporters/trace/jaeger/jaeger.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,12 @@ import (
sdktrace "go.opentelemetry.io/otel/sdk/trace"
)

const defaultServiceName = "OpenTelemetry"
const (
defaultServiceName = "OpenTelemetry"

keyInstrumentationLibraryName = "otel.instrumentation_library.name"
keyInstrumentationLibraryVersion = "otel.instrumentation_library.version"
)

type Option func(*options)

Expand Down Expand Up @@ -228,11 +233,10 @@ func spanDataToThrift(data *export.SpanData) *gen.Span {
}
}
}

if il := data.InstrumentationLibrary; il.Name != "" {
tags = append(tags, getStringTag("instrumentation.name", il.Name))
tags = append(tags, getStringTag(keyInstrumentationLibraryName, il.Name))
if il.Version != "" {
tags = append(tags, getStringTag("instrumentation.version", il.Version))
tags = append(tags, getStringTag(keyInstrumentationLibraryVersion, il.Version))
}
}

Expand Down
4 changes: 2 additions & 2 deletions exporters/trace/jaeger/jaeger_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -430,8 +430,8 @@ func Test_spanDataToThrift(t *testing.T) {
{Key: "key", VType: gen.TagType_STRING, VStr: &keyValue},
{Key: "uint", VType: gen.TagType_LONG, VLong: &uintValue},
{Key: "error", VType: gen.TagType_BOOL, VBool: &boolTrue},
{Key: "instrumentation.name", VType: gen.TagType_STRING, VStr: &instrLibName},
{Key: "instrumentation.version", VType: gen.TagType_STRING, VStr: &instrLibVersion},
{Key: "otel.instrumentation_library.name", VType: gen.TagType_STRING, VStr: &instrLibName},
{Key: "otel.instrumentation_library.version", VType: gen.TagType_STRING, VStr: &instrLibVersion},
{Key: "status.code", VType: gen.TagType_LONG, VLong: &statusCodeValue},
{Key: "status.message", VType: gen.TagType_STRING, VStr: &statusMessage},
{Key: "span.kind", VType: gen.TagType_STRING, VStr: &spanKind},
Expand Down
1 change: 1 addition & 0 deletions exporters/trace/zipkin/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ replace (
)

require (
github.com/google/go-cmp v0.5.2
github.com/openzipkin/zipkin-go v0.2.3
github.com/stretchr/testify v1.6.1
go.opentelemetry.io/otel v0.11.0
Expand Down
23 changes: 21 additions & 2 deletions exporters/trace/zipkin/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ import (
export "go.opentelemetry.io/otel/sdk/export/trace"
)

const (
keyInstrumentationLibraryName = "otel.instrumentation_library.name"
keyInstrumentationLibraryVersion = "otel.instrumentation_library.version"
)

func toZipkinSpanModels(batch []*export.SpanData, serviceName string) []zkmodel.SpanModel {
models := make([]zkmodel.SpanModel, 0, len(batch))
for _, data := range batch {
Expand Down Expand Up @@ -132,9 +137,16 @@ func attributesToJSONMapString(attributes []label.KeyValue) string {
return (string)(jsonBytes)
}

// extraZipkinTags are those that may be added to every outgoing span
var extraZipkinTags = []string{
"ot.status_code",
"ot.status_description",
keyInstrumentationLibraryName,
keyInstrumentationLibraryVersion,
}

func toZipkinTags(data *export.SpanData) map[string]string {
// +2 for status code and for status message
m := make(map[string]string, len(data.Attributes)+2)
m := make(map[string]string, len(data.Attributes)+len(extraZipkinTags))
for _, kv := range data.Attributes {
m[(string)(kv.Key)] = kv.Value.Emit()
}
Expand All @@ -143,5 +155,12 @@ func toZipkinTags(data *export.SpanData) map[string]string {
}
m["ot.status_code"] = data.StatusCode.String()
m["ot.status_description"] = data.StatusMessage

if il := data.InstrumentationLibrary; il.Name != "" {
m[keyInstrumentationLibraryName] = il.Name
if il.Version != "" {
m[keyInstrumentationLibraryVersion] = il.Version
}
}
return m
}
124 changes: 124 additions & 0 deletions exporters/trace/zipkin/model_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,20 @@
package zipkin

import (
"fmt"
"strconv"
"testing"
"time"

"github.com/google/go-cmp/cmp"
zkmodel "github.com/openzipkin/zipkin-go/model"
"github.com/stretchr/testify/require"
"google.golang.org/grpc/codes"

"go.opentelemetry.io/otel/api/trace"
"go.opentelemetry.io/otel/label"
export "go.opentelemetry.io/otel/sdk/export/trace"
"go.opentelemetry.io/otel/sdk/instrumentation"
)

func TestModelConversion(t *testing.T) {
Expand Down Expand Up @@ -656,3 +660,123 @@ func zkmodelIDPtr(n uint64) *zkmodel.ID {
id := zkmodel.ID(n)
return &id
}

func Test_toZipkinTags(t *testing.T) {
keyValue := "value"
doubleValue := 123.456
uintValue := int64(123)
statusMessage := "this is a problem"
instrLibName := "instrumentation-library"
instrLibVersion := "semver:1.0.0"

tests := []struct {
name string
data *export.SpanData
want map[string]string
}{
{
name: "attributes",
data: &export.SpanData{
Attributes: []label.KeyValue{
label.String("key", keyValue),
label.Float64("double", doubleValue),
label.Uint64("uint", uint64(uintValue)),
label.Bool("ok", true),
},
},
want: map[string]string{
"double": fmt.Sprint(doubleValue),
"key": keyValue,
"ok": "true",
"uint": strconv.FormatInt(uintValue, 10),
"ot.status_code": codes.OK.String(),
"ot.status_description": "",
},
},
{
name: "no attributes",
data: &export.SpanData{},
want: map[string]string{
"ot.status_code": codes.OK.String(),
"ot.status_description": "",
},
},
{
name: "omit-noerror",
data: &export.SpanData{
Attributes: []label.KeyValue{
label.Bool("error", false),
},
},
want: map[string]string{
"ot.status_code": codes.OK.String(),
"ot.status_description": "",
},
},
{
name: "statusCode",
data: &export.SpanData{
Attributes: []label.KeyValue{
label.String("key", keyValue),
label.Bool("error", true),
},
StatusCode: codes.Unknown,
StatusMessage: statusMessage,
},
want: map[string]string{
"error": "true",
"key": keyValue,
"ot.status_code": codes.Unknown.String(),
"ot.status_description": statusMessage,
},
},
{
name: "instrLib-empty",
data: &export.SpanData{
InstrumentationLibrary: instrumentation.Library{},
},
want: map[string]string{
"ot.status_code": codes.OK.String(),
"ot.status_description": "",
},
},
{
name: "instrLib-noversion",
data: &export.SpanData{
Attributes: []label.KeyValue{},
InstrumentationLibrary: instrumentation.Library{
Name: instrLibName,
},
},
want: map[string]string{
"otel.instrumentation_library.name": instrLibName,
"ot.status_code": codes.OK.String(),
"ot.status_description": "",
},
},
{
name: "instrLib-with-version",
data: &export.SpanData{
Attributes: []label.KeyValue{},
InstrumentationLibrary: instrumentation.Library{
Name: instrLibName,
Version: instrLibVersion,
},
},
want: map[string]string{
"otel.instrumentation_library.name": instrLibName,
"otel.instrumentation_library.version": instrLibVersion,
"ot.status_code": codes.OK.String(),
"ot.status_description": "",
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := toZipkinTags(tt.data)
if diff := cmp.Diff(got, tt.want); diff != "" {
t.Errorf("Diff%v", diff)
}
})
}
}

0 comments on commit df86b7c

Please sign in to comment.