1
0
mirror of https://github.com/open-telemetry/opentelemetry-go.git synced 2025-01-30 04:40:41 +02:00

Populate Jaeger's Span.Process from Resource (#1673)

* Jaeger exporter now populate Jaeger's Span Process from Resource

* Remove jaeger.WithProcess

* Fix tests

* Change the type of default service name into string

* Add tests

* Update CHANGELOG

* Use the API from `Set` to fetch service name in exporter

* Fix nits

* Add more test cases for jaegerBatchList function

* precommit

Co-authored-by: Anthony Mirabella <a9@aneurysm9.com>
This commit is contained in:
Sam Xie 2021-03-17 00:04:46 +08:00 committed by GitHub
parent 28eaaa9a91
commit 62cbf0f240
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 465 additions and 89 deletions

View File

@ -13,6 +13,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
- Added `Marshaler` config option to `otlphttp` to enable otlp over json or protobufs. (#1586)
- A `ForceFlush` method to the `"go.opentelemetry.io/otel/sdk/trace".TracerProvider` to flush all registered `SpanProcessor`s. (#1608)
- Added `WithDefaultSampler` and `WithSpanLimits` to tracer provider. (#1633)
- Jaeger exporter falls back to `resource.Default`'s `service.name` if the exported Span does not have one. (#1673)
### Changed
@ -25,6 +26,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
- `trace.SpanContext` is now immutable and has no exported fields. (#1573)
- `trace.NewSpanContext()` can be used in conjunction with the `trace.SpanContextConfig` struct to initialize a new `SpanContext` where all values are known.
- Renamed the `LabelSet` method of `"go.opentelemetry.io/otel/sdk/resource".Resource` to `Set`. (#1692)
- Jaeger exporter populates Jaeger's Span Process from Resource. (#1673)
### Removed
@ -33,6 +35,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
These are now returned as a SpanProcessor interface from their respective constructors. (#1638)
- Removed setting status to `Error` while recording an error as a span event in `RecordError`. (#1663)
- Removed `WithConfig` from tracer provider to avoid overriding configuration. (#1633)
- Removed `jaeger.WithProcess`. (#1673)
### Fixed

View File

@ -8,7 +8,6 @@ github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6 h1:ZgQEtGgCBiWRM
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=

View File

@ -21,6 +21,8 @@ import (
"log"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/sdk/resource"
"go.opentelemetry.io/otel/semconv"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/exporters/trace/jaeger"
@ -32,14 +34,14 @@ func initTracer() func() {
// Create and install Jaeger export pipeline.
flush, err := jaeger.InstallNewPipeline(
jaeger.WithCollectorEndpoint("http://localhost:14268/api/traces"),
jaeger.WithProcess(jaeger.Process{
ServiceName: "trace-demo",
Tags: []attribute.KeyValue{
jaeger.WithSDK(&sdktrace.Config{
DefaultSampler: sdktrace.AlwaysSample(),
Resource: resource.NewWithAttributes(
semconv.ServiceNameKey.String("trace-demo"),
attribute.String("exporter", "jaeger"),
attribute.Float64("float", 312.23),
},
),
}),
jaeger.WithSDK(&sdktrace.Config{DefaultSampler: sdktrace.AlwaysSample()}),
)
if err != nil {
log.Fatal(err)
@ -63,6 +65,7 @@ func main() {
func bar(ctx context.Context) {
tr := otel.Tracer("component-bar")
_, span := tr.Start(ctx, "bar")
span.SetAttributes(attribute.Key("testset").String("value"))
defer span.End()
// Do bar...

View File

@ -234,8 +234,8 @@ func TestNewRawExporterWithEnv(t *testing.T) {
assert.NoError(t, err)
assert.Equal(t, false, exp.o.Disabled)
assert.EqualValues(t, serviceName, exp.process.ServiceName)
assert.Len(t, exp.process.Tags, 1)
assert.EqualValues(t, serviceName, exp.o.Process.ServiceName)
assert.Len(t, exp.o.Process.Tags, 1)
require.IsType(t, &collectorUploader{}, exp.uploader)
uploader := exp.uploader.(*collectorUploader)
@ -276,8 +276,8 @@ func TestNewRawExporterWithEnvImplicitly(t *testing.T) {
assert.NoError(t, err)
// NewRawExporter will ignore Disabled env
assert.Equal(t, true, exp.o.Disabled)
assert.EqualValues(t, serviceName, exp.process.ServiceName)
assert.Len(t, exp.process.Tags, 1)
assert.EqualValues(t, serviceName, exp.o.Process.ServiceName)
assert.Len(t, exp.o.Process.Tags, 1)
require.IsType(t, &collectorUploader{}, exp.uploader)
uploader := exp.uploader.(*collectorUploader)

View File

@ -28,13 +28,13 @@ import (
"go.opentelemetry.io/otel/codes"
gen "go.opentelemetry.io/otel/exporters/trace/jaeger/internal/gen-go/jaeger"
export "go.opentelemetry.io/otel/sdk/export/trace"
"go.opentelemetry.io/otel/sdk/resource"
sdktrace "go.opentelemetry.io/otel/sdk/trace"
"go.opentelemetry.io/otel/semconv"
"go.opentelemetry.io/otel/trace"
)
const (
defaultServiceName = "OpenTelemetry"
keyInstrumentationLibraryName = "otel.library.name"
keyInstrumentationLibraryVersion = "otel.library.version"
)
@ -57,13 +57,6 @@ type options struct {
Disabled bool
}
// WithProcess sets the process with the information about the exporting process.
func WithProcess(process Process) Option {
return func(o *options) {
o.Process = process
}
}
// WithBufferMaxCount defines the total number of traces that can be buffered in memory
func WithBufferMaxCount(bufferMaxCount int) Option {
return func(o *options) {
@ -109,27 +102,24 @@ func NewRawExporter(endpointOption EndpointOption, opts ...Option) (*Exporter, e
opt(&o)
}
service := o.Process.ServiceName
if service == "" {
service = defaultServiceName
}
tags := make([]*gen.Tag, 0, len(o.Process.Tags))
for _, tag := range o.Process.Tags {
t := keyValueToTag(tag)
if t != nil {
tags = append(tags, t)
// Fetch default service.name from default resource for backup
var defaultServiceName string
defaultResource := resource.Default()
if value, exists := defaultResource.Set().Value(semconv.ServiceNameKey); exists {
defaultServiceName = value.AsString()
}
if defaultServiceName == "" {
return nil, fmt.Errorf("failed to get service name from default resource")
}
e := &Exporter{
uploader: uploader,
process: &gen.Process{
ServiceName: service,
Tags: tags,
},
o: o,
defaultServiceName: defaultServiceName,
resourceFromProcess: processToResource(o.Process),
}
bundler := bundler.NewBundler((*gen.Span)(nil), func(bundle interface{}) {
if err := e.upload(bundle.([]*gen.Span)); err != nil {
bundler := bundler.NewBundler((*export.SpanSnapshot)(nil), func(bundle interface{}) {
if err := e.upload(bundle.([]*export.SpanSnapshot)); err != nil {
otel.Handle(err)
}
})
@ -205,13 +195,15 @@ type Process struct {
// Exporter is an implementation of an OTel SpanSyncer that uploads spans to
// Jaeger.
type Exporter struct {
process *gen.Process
bundler *bundler.Bundler
uploader batchUploader
o options
stoppedMu sync.RWMutex
stopped bool
defaultServiceName string
resourceFromProcess *resource.Resource
}
var _ export.SpanExporter = (*Exporter)(nil)
@ -227,7 +219,7 @@ func (e *Exporter) ExportSpans(ctx context.Context, ss []*export.SpanSnapshot) e
for _, span := range ss {
// TODO(jbd): Handle oversized bundlers.
err := e.bundler.Add(spanSnapshotToThrift(span), 1)
err := e.bundler.Add(span, 1)
if err != nil {
return fmt.Errorf("failed to bundle %q: %w", span.Name, err)
}
@ -275,17 +267,6 @@ func spanSnapshotToThrift(ss *export.SpanSnapshot) *gen.Span {
}
}
// TODO (jmacd): OTel has a broad "last value wins"
// semantic. Should resources be appended before span
// attributes, above, to allow span attributes to
// overwrite resource attributes?
if ss.Resource != nil {
for iter := ss.Resource.Iter(); iter.Next(); {
if tag := keyValueToTag(iter.Attribute()); tag != nil {
tags = append(tags, tag)
}
}
}
if il := ss.InstrumentationLibrary; il.Name != "" {
tags = append(tags, getStringTag(keyInstrumentationLibraryName, il.Name))
if il.Version != "" {
@ -429,11 +410,94 @@ func (e *Exporter) Flush() {
flush(e)
}
func (e *Exporter) upload(spans []*gen.Span) error {
batch := &gen.Batch{
Spans: spans,
Process: e.process,
func (e *Exporter) upload(spans []*export.SpanSnapshot) error {
batchList := jaegerBatchList(spans, e.defaultServiceName, e.resourceFromProcess)
for _, batch := range batchList {
err := e.uploader.upload(batch)
if err != nil {
return err
}
}
return e.uploader.upload(batch)
return nil
}
// jaegerBatchList transforms a slice of SpanSnapshot into a slice of jaeger
// Batch.
func jaegerBatchList(ssl []*export.SpanSnapshot, defaultServiceName string, resourceFromProcess *resource.Resource) []*gen.Batch {
if len(ssl) == 0 {
return nil
}
batchDict := make(map[attribute.Distinct]*gen.Batch)
for _, ss := range ssl {
if ss == nil {
continue
}
newResource := ss.Resource
if resourceFromProcess != nil {
// The value from process will overwrite the value from span's resources
newResource = resource.Merge(ss.Resource, resourceFromProcess)
}
resourceKey := newResource.Equivalent()
batch, bOK := batchDict[resourceKey]
if !bOK {
batch = &gen.Batch{
Process: process(newResource, defaultServiceName),
Spans: []*gen.Span{},
}
}
batch.Spans = append(batch.Spans, spanSnapshotToThrift(ss))
batchDict[resourceKey] = batch
}
// Transform the categorized map into a slice
batchList := make([]*gen.Batch, 0, len(batchDict))
for _, batch := range batchDict {
batchList = append(batchList, batch)
}
return batchList
}
// process transforms an OTel Resource into a jaeger Process.
func process(res *resource.Resource, defaultServiceName string) *gen.Process {
var process gen.Process
var serviceName attribute.KeyValue
if res != nil {
for iter := res.Iter(); iter.Next(); {
if iter.Attribute().Key == semconv.ServiceNameKey {
serviceName = iter.Attribute()
// Don't convert service.name into tag.
continue
}
if tag := keyValueToTag(iter.Attribute()); tag != nil {
process.Tags = append(process.Tags, tag)
}
}
}
// If no service.name is contained in a Span's Resource,
// that field MUST be populated from the default Resource.
if serviceName.Value.AsString() == "" {
serviceName = semconv.ServiceVersionKey.String(defaultServiceName)
}
process.ServiceName = serviceName.Value.AsString()
return &process
}
func processToResource(process Process) *resource.Resource {
var attrs []attribute.KeyValue
if process.ServiceName != "" {
attrs = append(attrs, semconv.ServiceNameKey.String(process.ServiceName))
}
attrs = append(attrs, process.Tags...)
if len(attrs) == 0 {
return nil
}
return resource.NewWithAttributes(attrs...)
}

View File

@ -19,6 +19,7 @@ import (
"encoding/binary"
"os"
"sort"
"strings"
"testing"
"time"
@ -36,6 +37,7 @@ import (
"go.opentelemetry.io/otel/sdk/instrumentation"
"go.opentelemetry.io/otel/sdk/resource"
sdktrace "go.opentelemetry.io/otel/sdk/trace"
"go.opentelemetry.io/otel/semconv"
"go.opentelemetry.io/otel/trace"
)
@ -185,32 +187,14 @@ func TestNewRawExporter(t *testing.T) {
{
name: "default exporter",
endpoint: WithCollectorEndpoint(collectorEndpoint),
expectedServiceName: defaultServiceName,
expectedServiceName: "unknown_service",
expectedBufferMaxCount: bundler.DefaultBufferedByteLimit,
expectedBatchMaxCount: bundler.DefaultBundleCountThreshold,
},
{
name: "default exporter with agent endpoint",
endpoint: WithAgentEndpoint(agentEndpoint),
expectedServiceName: defaultServiceName,
expectedBufferMaxCount: bundler.DefaultBufferedByteLimit,
expectedBatchMaxCount: bundler.DefaultBundleCountThreshold,
},
{
name: "with process",
endpoint: WithCollectorEndpoint(collectorEndpoint),
options: []Option{
WithProcess(
Process{
ServiceName: "jaeger-test",
Tags: []attribute.KeyValue{
attribute.String("key", "val"),
},
},
),
},
expectedServiceName: "jaeger-test",
expectedTagsLen: 1,
expectedServiceName: "unknown_service",
expectedBufferMaxCount: bundler.DefaultBufferedByteLimit,
expectedBatchMaxCount: bundler.DefaultBundleCountThreshold,
},
@ -218,15 +202,10 @@ func TestNewRawExporter(t *testing.T) {
name: "with buffer and batch max count",
endpoint: WithCollectorEndpoint(collectorEndpoint),
options: []Option{
WithProcess(
Process{
ServiceName: "jaeger-test",
},
),
WithBufferMaxCount(99),
WithBatchMaxCount(99),
},
expectedServiceName: "jaeger-test",
expectedServiceName: "unknown_service",
expectedBufferMaxCount: 99,
expectedBatchMaxCount: 99,
},
@ -240,10 +219,10 @@ func TestNewRawExporter(t *testing.T) {
)
assert.NoError(t, err)
assert.Equal(t, tc.expectedServiceName, exp.process.ServiceName)
assert.Len(t, exp.process.Tags, tc.expectedTagsLen)
assert.Equal(t, tc.expectedBufferMaxCount, exp.bundler.BufferedByteLimit)
assert.Equal(t, tc.expectedBatchMaxCount, exp.bundler.BundleCountThreshold)
assert.NotEmpty(t, exp.defaultServiceName)
assert.True(t, strings.HasPrefix(exp.defaultServiceName, tc.expectedServiceName))
})
}
}
@ -327,11 +306,11 @@ func TestExporter_ExportSpan(t *testing.T) {
// Create Jaeger Exporter
exp, err := NewRawExporter(
withTestCollectorEndpoint(),
WithProcess(Process{
ServiceName: serviceName,
Tags: []attribute.KeyValue{
WithSDK(&sdktrace.Config{
Resource: resource.NewWithAttributes(
semconv.ServiceNameKey.String(serviceName),
attribute.String(tagKey, tagVal),
},
),
}),
)
@ -409,7 +388,6 @@ func Test_spanSnapshotToThrift(t *testing.T) {
StatusCode: codes.Error,
StatusMessage: statusMessage,
SpanKind: trace.SpanKindClient,
Resource: resource.NewWithAttributes(attribute.String("rk1", rv1), attribute.Int64("rk2", rv2)),
InstrumentationLibrary: instrumentation.Library{
Name: instrLibName,
Version: instrLibVersion,
@ -432,8 +410,6 @@ func Test_spanSnapshotToThrift(t *testing.T) {
{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},
{Key: "rk1", VType: gen.TagType_STRING, VStr: &rv1},
{Key: "rk2", VType: gen.TagType_LONG, VLong: &rv2},
},
References: []*gen.SpanRef{
{
@ -516,6 +492,44 @@ func Test_spanSnapshotToThrift(t *testing.T) {
},
},
},
{
name: "resources do not affect the tags",
data: &export.SpanSnapshot{
ParentSpanID: parentSpanID,
SpanContext: trace.NewSpanContext(trace.SpanContextConfig{
TraceID: traceID,
SpanID: spanID,
}),
Name: "/foo",
StartTime: now,
EndTime: now,
Resource: resource.NewWithAttributes(
attribute.String("rk1", rv1),
attribute.Int64("rk2", rv2),
semconv.ServiceNameKey.String("service name"),
),
StatusCode: codes.Unset,
StatusMessage: statusMessage,
SpanKind: trace.SpanKindInternal,
InstrumentationLibrary: instrumentation.Library{
Name: instrLibName,
Version: instrLibVersion,
},
},
want: &gen.Span{
TraceIdLow: 651345242494996240,
TraceIdHigh: 72623859790382856,
SpanId: 72623859790382856,
ParentSpanId: 578437695752307201,
OperationName: "/foo",
StartTime: now.UnixNano() / 1000,
Duration: 0,
Tags: []*gen.Tag{
{Key: "otel.library.name", VType: gen.TagType_STRING, VStr: &instrLibName},
{Key: "otel.library.version", VType: gen.TagType_STRING, VStr: &instrLibVersion},
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
@ -579,3 +593,296 @@ func TestErrorOnExportShutdownExporter(t *testing.T) {
assert.NoError(t, e.Shutdown(context.Background()))
assert.NoError(t, e.ExportSpans(context.Background(), nil))
}
func TestJaegerBatchList(t *testing.T) {
newString := func(value string) *string {
return &value
}
spanKind := "unspecified"
now := time.Now()
testCases := []struct {
name string
spanSnapshotList []*export.SpanSnapshot
defaultServiceName string
resourceFromProcess *resource.Resource
expectedBatchList []*gen.Batch
}{
{
name: "no span shots",
spanSnapshotList: nil,
expectedBatchList: nil,
},
{
name: "span's snapshot contains nil span",
spanSnapshotList: []*export.SpanSnapshot{
{
Name: "s1",
Resource: resource.NewWithAttributes(
semconv.ServiceNameKey.String("name"),
attribute.Key("r1").String("v1"),
),
StartTime: now,
EndTime: now,
},
nil,
},
expectedBatchList: []*gen.Batch{
{
Process: &gen.Process{
ServiceName: "name",
Tags: []*gen.Tag{
{Key: "r1", VType: gen.TagType_STRING, VStr: newString("v1")},
},
},
Spans: []*gen.Span{
{
OperationName: "s1",
Tags: []*gen.Tag{
{Key: "span.kind", VType: gen.TagType_STRING, VStr: &spanKind},
},
StartTime: now.UnixNano() / 1000,
},
},
},
},
},
{
name: "merge spans that have the same resources",
spanSnapshotList: []*export.SpanSnapshot{
{
Name: "s1",
Resource: resource.NewWithAttributes(
semconv.ServiceNameKey.String("name"),
attribute.Key("r1").String("v1"),
),
StartTime: now,
EndTime: now,
},
{
Name: "s2",
Resource: resource.NewWithAttributes(
semconv.ServiceNameKey.String("name"),
attribute.Key("r1").String("v1"),
),
StartTime: now,
EndTime: now,
},
{
Name: "s3",
Resource: resource.NewWithAttributes(
semconv.ServiceNameKey.String("name"),
attribute.Key("r2").String("v2"),
),
StartTime: now,
EndTime: now,
},
},
expectedBatchList: []*gen.Batch{
{
Process: &gen.Process{
ServiceName: "name",
Tags: []*gen.Tag{
{Key: "r1", VType: gen.TagType_STRING, VStr: newString("v1")},
},
},
Spans: []*gen.Span{
{
OperationName: "s1",
Tags: []*gen.Tag{
{Key: "span.kind", VType: gen.TagType_STRING, VStr: &spanKind},
},
StartTime: now.UnixNano() / 1000,
},
{
OperationName: "s2",
Tags: []*gen.Tag{
{Key: "span.kind", VType: gen.TagType_STRING, VStr: &spanKind},
},
StartTime: now.UnixNano() / 1000,
},
},
},
{
Process: &gen.Process{
ServiceName: "name",
Tags: []*gen.Tag{
{Key: "r2", VType: gen.TagType_STRING, VStr: newString("v2")},
},
},
Spans: []*gen.Span{
{
OperationName: "s3",
Tags: []*gen.Tag{
{Key: "span.kind", VType: gen.TagType_STRING, VStr: &spanKind},
},
StartTime: now.UnixNano() / 1000,
},
},
},
},
},
{
name: "merge resources that come from process",
spanSnapshotList: []*export.SpanSnapshot{
{
Name: "s1",
Resource: resource.NewWithAttributes(
semconv.ServiceNameKey.String("name"),
attribute.Key("r1").String("v1"),
attribute.Key("r2").String("v2"),
),
StartTime: now,
EndTime: now,
},
},
resourceFromProcess: resource.NewWithAttributes(
semconv.ServiceNameKey.String("new-name"),
attribute.Key("r1").String("v2"),
),
expectedBatchList: []*gen.Batch{
{
Process: &gen.Process{
ServiceName: "new-name",
Tags: []*gen.Tag{
{Key: "r1", VType: gen.TagType_STRING, VStr: newString("v2")},
{Key: "r2", VType: gen.TagType_STRING, VStr: newString("v2")},
},
},
Spans: []*gen.Span{
{
OperationName: "s1",
Tags: []*gen.Tag{
{Key: "span.kind", VType: gen.TagType_STRING, VStr: &spanKind},
},
StartTime: now.UnixNano() / 1000,
},
},
},
},
},
{
name: "span's snapshot contains no service name but resourceFromProcess does",
spanSnapshotList: []*export.SpanSnapshot{
{
Name: "s1",
Resource: resource.NewWithAttributes(
attribute.Key("r1").String("v1"),
),
StartTime: now,
EndTime: now,
},
nil,
},
resourceFromProcess: resource.NewWithAttributes(
semconv.ServiceNameKey.String("new-name"),
),
expectedBatchList: []*gen.Batch{
{
Process: &gen.Process{
ServiceName: "new-name",
Tags: []*gen.Tag{
{Key: "r1", VType: gen.TagType_STRING, VStr: newString("v1")},
},
},
Spans: []*gen.Span{
{
OperationName: "s1",
Tags: []*gen.Tag{
{Key: "span.kind", VType: gen.TagType_STRING, VStr: &spanKind},
},
StartTime: now.UnixNano() / 1000,
},
},
},
},
},
{
name: "no service name in spans and resourceFromProcess",
spanSnapshotList: []*export.SpanSnapshot{
{
Name: "s1",
Resource: resource.NewWithAttributes(
attribute.Key("r1").String("v1"),
),
StartTime: now,
EndTime: now,
},
nil,
},
defaultServiceName: "default service name",
expectedBatchList: []*gen.Batch{
{
Process: &gen.Process{
ServiceName: "default service name",
Tags: []*gen.Tag{
{Key: "r1", VType: gen.TagType_STRING, VStr: newString("v1")},
},
},
Spans: []*gen.Span{
{
OperationName: "s1",
Tags: []*gen.Tag{
{Key: "span.kind", VType: gen.TagType_STRING, VStr: &spanKind},
},
StartTime: now.UnixNano() / 1000,
},
},
},
},
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
batchList := jaegerBatchList(tc.spanSnapshotList, tc.defaultServiceName, tc.resourceFromProcess)
assert.ElementsMatch(t, tc.expectedBatchList, batchList)
})
}
}
func TestProcess(t *testing.T) {
v1 := "v1"
testCases := []struct {
name string
res *resource.Resource
defaultServiceName string
expectedProcess *gen.Process
}{
{
name: "resources contain service name",
res: resource.NewWithAttributes(
semconv.ServiceNameKey.String("service name"),
attribute.Key("r1").String("v1"),
),
defaultServiceName: "default service name",
expectedProcess: &gen.Process{
ServiceName: "service name",
Tags: []*gen.Tag{
{Key: "r1", VType: gen.TagType_STRING, VStr: &v1},
},
},
},
{
name: "resources don't have service name",
res: resource.NewWithAttributes(attribute.Key("r1").String("v1")),
defaultServiceName: "default service name",
expectedProcess: &gen.Process{
ServiceName: "default service name",
Tags: []*gen.Tag{
{Key: "r1", VType: gen.TagType_STRING, VStr: &v1},
},
},
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
pro := process(tc.res, tc.defaultServiceName)
assert.Equal(t, tc.expectedProcess, pro)
})
}
}