1
0
mirror of https://github.com/open-telemetry/opentelemetry-go.git synced 2025-07-13 01:00:22 +02:00

Create resource.Default() with required attributes/default values (#1507)

* Create resource.Default() with required attributes/default values

Add metric controller and tracer provider tests for resources

* Updated CHANGELOG

* PR comments

+ some small CHANGELOG PR addition, rewording
+ change default resource servicename to `unknown_service:go` (this
matches the Java codebase which uses `unknown_service:java`)
This commit is contained in:
ET
2021-02-15 12:28:37 -08:00
committed by GitHub
parent 76f9342277
commit 8fae0a644a
10 changed files with 204 additions and 45 deletions

View File

@ -8,11 +8,15 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
## [Unreleased] ## [Unreleased]
### Added
- Added `resource.Default()` for use with meter and tracer providers. (#1507)
## [0.17.0] - 2020-02-12 ## [0.17.0] - 2020-02-12
### Changed ### Changed
- Rename project default branch from `master` to `main`. - Rename project default branch from `master` to `main`. (#1505)
- Reverse order in which `Resource` attributes are merged, per change in spec. (#1501) - Reverse order in which `Resource` attributes are merged, per change in spec. (#1501)
- Add tooling to maintain "replace" directives in go.mod files automatically. (#1528) - Add tooling to maintain "replace" directives in go.mod files automatically. (#1528)
- Create new modules: otel/metric, otel/trace, otel/oteltest, otel/sdk/export/metric, otel/sdk/metric (#1528) - Create new modules: otel/metric, otel/trace, otel/oteltest, otel/sdk/export/metric, otel/sdk/metric (#1528)

View File

@ -117,6 +117,7 @@ func TestPrometheusStatefulness(t *testing.T) {
exporter, err := prometheus.NewExportPipeline( exporter, err := prometheus.NewExportPipeline(
prometheus.Config{}, prometheus.Config{},
controller.WithCollectPeriod(0), controller.WithCollectPeriod(0),
controller.WithResource(resource.Empty()),
) )
require.NoError(t, err) require.NoError(t, err)

View File

@ -26,6 +26,7 @@ import (
export "go.opentelemetry.io/otel/sdk/export/metric" export "go.opentelemetry.io/otel/sdk/export/metric"
sdk "go.opentelemetry.io/otel/sdk/metric" sdk "go.opentelemetry.io/otel/sdk/metric"
controllerTime "go.opentelemetry.io/otel/sdk/metric/controller/time" controllerTime "go.opentelemetry.io/otel/sdk/metric/controller/time"
"go.opentelemetry.io/otel/sdk/resource"
) )
// DefaultPeriod is used for: // DefaultPeriod is used for:
@ -85,6 +86,9 @@ func New(checkpointer export.Checkpointer, opts ...Option) *Controller {
for _, opt := range opts { for _, opt := range opts {
opt.Apply(c) opt.Apply(c)
} }
if c.Resource == nil {
c.Resource = resource.Default()
}
impl := sdk.NewAccumulator( impl := sdk.NewAccumulator(
checkpointer, checkpointer,

View File

@ -17,6 +17,7 @@ package basic_test
import ( import (
"context" "context"
"errors" "errors"
"fmt"
"testing" "testing"
"time" "time"
@ -30,6 +31,7 @@ import (
"go.opentelemetry.io/otel/sdk/metric/controller/controllertest" "go.opentelemetry.io/otel/sdk/metric/controller/controllertest"
processor "go.opentelemetry.io/otel/sdk/metric/processor/basic" processor "go.opentelemetry.io/otel/sdk/metric/processor/basic"
"go.opentelemetry.io/otel/sdk/metric/processor/processortest" "go.opentelemetry.io/otel/sdk/metric/processor/processortest"
"go.opentelemetry.io/otel/sdk/resource"
) )
func getMap(t *testing.T, cont *controller.Controller) map[string]float64 { func getMap(t *testing.T, cont *controller.Controller) map[string]float64 {
@ -55,6 +57,58 @@ func checkTestContext(t *testing.T, ctx context.Context) {
require.Equal(t, "B", ctx.Value(testContextKey("A"))) require.Equal(t, "B", ctx.Value(testContextKey("A")))
} }
func TestControllerUsesResource(t *testing.T) {
cases := []struct {
name string
options []controller.Option
wanted string
}{
{
name: "explicitly empty resource",
options: []controller.Option{controller.WithResource(resource.Empty())},
wanted: ""},
{
name: "uses default if no resource option",
options: nil,
wanted: resource.Default().Encoded(label.DefaultEncoder())},
{
name: "explicit resource",
options: []controller.Option{controller.WithResource(resource.NewWithAttributes(label.String("R", "S")))},
wanted: "R=S"},
{
name: "last resource wins",
options: []controller.Option{
controller.WithResource(resource.Default()),
controller.WithResource(resource.NewWithAttributes(label.String("R", "S"))),
},
wanted: "R=S",
},
}
for _, c := range cases {
t.Run(fmt.Sprintf("case-%s", c.name), func(t *testing.T) {
cont := controller.New(
processor.New(
processortest.AggregatorSelector(),
export.CumulativeExportKindSelector(),
),
c.options...,
)
prov := cont.MeterProvider()
ctr := metric.Must(prov.Meter("named")).NewFloat64Counter("calls.sum")
ctr.Add(context.Background(), 1.)
// Collect once
require.NoError(t, cont.Collect(context.Background()))
expect := map[string]float64{
"calls.sum//" + c.wanted: 1.,
}
require.EqualValues(t, expect, getMap(t, cont))
})
}
}
func TestStartNoExporter(t *testing.T) { func TestStartNoExporter(t *testing.T) {
cont := controller.New( cont := controller.New(
processor.New( processor.New(
@ -62,6 +116,7 @@ func TestStartNoExporter(t *testing.T) {
export.CumulativeExportKindSelector(), export.CumulativeExportKindSelector(),
), ),
controller.WithCollectPeriod(time.Second), controller.WithCollectPeriod(time.Second),
controller.WithResource(resource.Empty()),
) )
mock := controllertest.NewMockClock() mock := controllertest.NewMockClock()
cont.SetClock(mock) cont.SetClock(mock)
@ -132,6 +187,7 @@ func TestObserverCanceled(t *testing.T) {
), ),
controller.WithCollectPeriod(0), controller.WithCollectPeriod(0),
controller.WithCollectTimeout(time.Millisecond), controller.WithCollectTimeout(time.Millisecond),
controller.WithResource(resource.Empty()),
) )
prov := cont.MeterProvider() prov := cont.MeterProvider()
@ -163,6 +219,7 @@ func TestObserverContext(t *testing.T) {
export.CumulativeExportKindSelector(), export.CumulativeExportKindSelector(),
), ),
controller.WithCollectTimeout(0), controller.WithCollectTimeout(0),
controller.WithResource(resource.Empty()),
) )
prov := cont.MeterProvider() prov := cont.MeterProvider()
@ -228,6 +285,7 @@ func TestExportTimeout(t *testing.T) {
controller.WithCollectPeriod(time.Second), controller.WithCollectPeriod(time.Second),
controller.WithPushTimeout(time.Millisecond), controller.WithPushTimeout(time.Millisecond),
controller.WithPusher(exporter), controller.WithPusher(exporter),
controller.WithResource(resource.Empty()),
) )
mock := controllertest.NewMockClock() mock := controllertest.NewMockClock()
cont.SetClock(mock) cont.SetClock(mock)
@ -283,6 +341,7 @@ func TestCollectAfterStopThenStartAgain(t *testing.T) {
), ),
controller.WithCollectPeriod(time.Second), controller.WithCollectPeriod(time.Second),
controller.WithPusher(exp), controller.WithPusher(exp),
controller.WithResource(resource.Empty()),
) )
mock := controllertest.NewMockClock() mock := controllertest.NewMockClock()
cont.SetClock(mock) cont.SetClock(mock)

View File

@ -29,6 +29,7 @@ import (
"go.opentelemetry.io/otel/sdk/metric/controller/controllertest" "go.opentelemetry.io/otel/sdk/metric/controller/controllertest"
processor "go.opentelemetry.io/otel/sdk/metric/processor/basic" processor "go.opentelemetry.io/otel/sdk/metric/processor/basic"
"go.opentelemetry.io/otel/sdk/metric/processor/processortest" "go.opentelemetry.io/otel/sdk/metric/processor/processortest"
"go.opentelemetry.io/otel/sdk/resource"
) )
func TestPullNoCollect(t *testing.T) { func TestPullNoCollect(t *testing.T) {
@ -39,6 +40,7 @@ func TestPullNoCollect(t *testing.T) {
processor.WithMemory(true), processor.WithMemory(true),
), ),
controller.WithCollectPeriod(0), controller.WithCollectPeriod(0),
controller.WithResource(resource.Empty()),
) )
ctx := context.Background() ctx := context.Background()
@ -74,6 +76,7 @@ func TestPullWithCollect(t *testing.T) {
processor.WithMemory(true), processor.WithMemory(true),
), ),
controller.WithCollectPeriod(time.Second), controller.WithCollectPeriod(time.Second),
controller.WithResource(resource.Empty()),
) )
mock := controllertest.NewMockClock() mock := controllertest.NewMockClock()
puller.SetClock(mock) puller.SetClock(mock)

View File

@ -18,6 +18,7 @@ import (
"context" "context"
"fmt" "fmt"
"os" "os"
"path/filepath"
"go.opentelemetry.io/otel" "go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/label" "go.opentelemetry.io/otel/label"
@ -43,12 +44,15 @@ type (
K label.Key K label.Key
F func() (string, error) F func() (string, error)
} }
defaultServiceNameDetector struct{}
) )
var ( var (
_ Detector = TelemetrySDK{} _ Detector = TelemetrySDK{}
_ Detector = Host{} _ Detector = Host{}
_ Detector = stringDetector{} _ Detector = stringDetector{}
_ Detector = defaultServiceNameDetector{}
) )
// Detect returns a *Resource that describes the OpenTelemetry SDK used. // Detect returns a *Resource that describes the OpenTelemetry SDK used.
@ -79,3 +83,17 @@ func (sd stringDetector) Detect(ctx context.Context) (*Resource, error) {
} }
return NewWithAttributes(sd.K.String(value)), nil return NewWithAttributes(sd.K.String(value)), nil
} }
// Detect implements Detector
func (defaultServiceNameDetector) Detect(ctx context.Context) (*Resource, error) {
return StringDetector(
semconv.ServiceNameKey,
func() (string, error) {
executable, err := os.Executable()
if err != nil {
return "unknown_service:go", nil
}
return "unknown_service:" + filepath.Base(executable), nil
},
).Detect(ctx)
}

View File

@ -15,6 +15,10 @@
package resource // import "go.opentelemetry.io/otel/sdk/resource" package resource // import "go.opentelemetry.io/otel/sdk/resource"
import ( import (
"context"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/label" "go.opentelemetry.io/otel/label"
) )
@ -29,7 +33,16 @@ type Resource struct {
labels label.Set labels label.Set
} }
var emptyResource Resource var (
emptyResource Resource
defaultResource *Resource = func(r *Resource, err error) *Resource {
if err != nil {
otel.Handle(err)
}
return r
}(Detect(context.Background(), defaultServiceNameDetector{}, TelemetrySDK{}))
)
// NewWithAttributes creates a resource from a set of attributes. If there are // NewWithAttributes creates a resource from a set of attributes. If there are
// duplicate keys present in the list of attributes, then the last // duplicate keys present in the list of attributes, then the last
@ -113,6 +126,12 @@ func Empty() *Resource {
return &emptyResource return &emptyResource
} }
// Default returns an instance of Resource with a default
// "service.name" and OpenTelemetrySDK attributes
func Default() *Resource {
return defaultResource
}
// Equivalent returns an object that can be compared for equality // Equivalent returns an object that can be compared for equality
// between two resources. This value is suitable for use as a key in // between two resources. This value is suitable for use as a key in
// a map. // a map.

View File

@ -17,13 +17,16 @@ package resource_test
import ( import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"strings"
"testing" "testing"
"github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/label" "go.opentelemetry.io/otel/label"
"go.opentelemetry.io/otel/sdk/resource" "go.opentelemetry.io/otel/sdk/resource"
"go.opentelemetry.io/otel/semconv"
) )
var ( var (
@ -162,6 +165,21 @@ func TestMerge(t *testing.T) {
} }
} }
func TestDefault(t *testing.T) {
res := resource.Default()
require.False(t, res.Equal(resource.Empty()))
require.True(t, res.LabelSet().HasValue(semconv.ServiceNameKey))
serviceName, _ := res.LabelSet().Value(semconv.ServiceNameKey)
require.True(t, strings.HasPrefix(serviceName.AsString(), "unknown_service:"))
require.Greaterf(t, len(serviceName.AsString()), len("unknown_service:"),
"default service.name should include executable name")
require.Contains(t, res.Attributes(), semconv.TelemetrySDKLanguageGo)
require.Contains(t, res.Attributes(), semconv.TelemetrySDKVersionKey.String(otel.Version()))
require.Contains(t, res.Attributes(), semconv.TelemetrySDKNameKey.String("opentelemetry"))
}
func TestString(t *testing.T) { func TestString(t *testing.T) {
for _, test := range []struct { for _, test := range []struct {
kvs []label.KeyValue kvs []label.KeyValue

View File

@ -179,8 +179,9 @@ func (p *TracerProvider) ApplyConfig(cfg Config) {
if cfg.MaxLinksPerSpan > 0 { if cfg.MaxLinksPerSpan > 0 {
c.MaxLinksPerSpan = cfg.MaxLinksPerSpan c.MaxLinksPerSpan = cfg.MaxLinksPerSpan
} }
if cfg.Resource != nil { c.Resource = cfg.Resource
c.Resource = cfg.Resource if c.Resource == nil {
c.Resource = resource.Default()
} }
p.config.Store(&c) p.config.Store(&c)
} }

View File

@ -354,7 +354,7 @@ func TestStartSpanWithParent(t *testing.T) {
func TestSetSpanAttributesOnStart(t *testing.T) { func TestSetSpanAttributesOnStart(t *testing.T) {
te := NewTestExporter() te := NewTestExporter()
tp := NewTracerProvider(WithSyncer(te)) tp := NewTracerProvider(WithSyncer(te), WithResource(resource.Empty()))
span := startSpan(tp, span := startSpan(tp,
"StartSpanAttribute", "StartSpanAttribute",
trace.WithAttributes(label.String("key1", "value1")), trace.WithAttributes(label.String("key1", "value1")),
@ -387,7 +387,7 @@ func TestSetSpanAttributesOnStart(t *testing.T) {
func TestSetSpanAttributes(t *testing.T) { func TestSetSpanAttributes(t *testing.T) {
te := NewTestExporter() te := NewTestExporter()
tp := NewTracerProvider(WithSyncer(te)) tp := NewTracerProvider(WithSyncer(te), WithResource(resource.Empty()))
span := startSpan(tp, "SpanAttribute") span := startSpan(tp, "SpanAttribute")
span.SetAttributes(label.String("key1", "value1")) span.SetAttributes(label.String("key1", "value1"))
got, err := endSpan(te, span) got, err := endSpan(te, span)
@ -419,7 +419,7 @@ func TestSetSpanAttributes(t *testing.T) {
func TestSamplerAttributesLocalChildSpan(t *testing.T) { func TestSamplerAttributesLocalChildSpan(t *testing.T) {
sampler := &testSampler{prefix: "span", t: t} sampler := &testSampler{prefix: "span", t: t}
te := NewTestExporter() te := NewTestExporter()
tp := NewTracerProvider(WithConfig(Config{DefaultSampler: sampler}), WithSyncer(te)) tp := NewTracerProvider(WithConfig(Config{DefaultSampler: sampler}), WithSyncer(te), WithResource(resource.Empty()))
ctx := context.Background() ctx := context.Background()
ctx, span := startLocalSpan(tp, ctx, "SpanOne", "span0") ctx, span := startLocalSpan(tp, ctx, "SpanOne", "span0")
@ -483,7 +483,7 @@ func TestSamplerAttributesLocalChildSpan(t *testing.T) {
func TestSetSpanAttributesOverLimit(t *testing.T) { func TestSetSpanAttributesOverLimit(t *testing.T) {
te := NewTestExporter() te := NewTestExporter()
cfg := Config{MaxAttributesPerSpan: 2} cfg := Config{MaxAttributesPerSpan: 2}
tp := NewTracerProvider(WithConfig(cfg), WithSyncer(te)) tp := NewTracerProvider(WithConfig(cfg), WithSyncer(te), WithResource(resource.Empty()))
span := startSpan(tp, "SpanAttributesOverLimit") span := startSpan(tp, "SpanAttributesOverLimit")
span.SetAttributes( span.SetAttributes(
@ -520,7 +520,7 @@ func TestSetSpanAttributesOverLimit(t *testing.T) {
func TestEvents(t *testing.T) { func TestEvents(t *testing.T) {
te := NewTestExporter() te := NewTestExporter()
tp := NewTracerProvider(WithSyncer(te)) tp := NewTracerProvider(WithSyncer(te), WithResource(resource.Empty()))
span := startSpan(tp, "Events") span := startSpan(tp, "Events")
k1v1 := label.String("key1", "value1") k1v1 := label.String("key1", "value1")
@ -566,7 +566,7 @@ func TestEvents(t *testing.T) {
func TestEventsOverLimit(t *testing.T) { func TestEventsOverLimit(t *testing.T) {
te := NewTestExporter() te := NewTestExporter()
cfg := Config{MaxEventsPerSpan: 2} cfg := Config{MaxEventsPerSpan: 2}
tp := NewTracerProvider(WithConfig(cfg), WithSyncer(te)) tp := NewTracerProvider(WithConfig(cfg), WithSyncer(te), WithResource(resource.Empty()))
span := startSpan(tp, "EventsOverLimit") span := startSpan(tp, "EventsOverLimit")
k1v1 := label.String("key1", "value1") k1v1 := label.String("key1", "value1")
@ -617,7 +617,7 @@ func TestEventsOverLimit(t *testing.T) {
func TestLinks(t *testing.T) { func TestLinks(t *testing.T) {
te := NewTestExporter() te := NewTestExporter()
tp := NewTracerProvider(WithSyncer(te)) tp := NewTracerProvider(WithSyncer(te), WithResource(resource.Empty()))
k1v1 := label.String("key1", "value1") k1v1 := label.String("key1", "value1")
k2v2 := label.String("key2", "value2") k2v2 := label.String("key2", "value2")
@ -662,7 +662,7 @@ func TestLinksOverLimit(t *testing.T) {
sc2 := trace.SpanContext{TraceID: trace.TraceID([16]byte{1, 1}), SpanID: trace.SpanID{3}} sc2 := trace.SpanContext{TraceID: trace.TraceID([16]byte{1, 1}), SpanID: trace.SpanID{3}}
sc3 := trace.SpanContext{TraceID: trace.TraceID([16]byte{1, 1}), SpanID: trace.SpanID{3}} sc3 := trace.SpanContext{TraceID: trace.TraceID([16]byte{1, 1}), SpanID: trace.SpanID{3}}
tp := NewTracerProvider(WithConfig(cfg), WithSyncer(te)) tp := NewTracerProvider(WithConfig(cfg), WithSyncer(te), WithResource(resource.Empty()))
span := startSpan(tp, "LinksOverLimit", span := startSpan(tp, "LinksOverLimit",
trace.WithLinks( trace.WithLinks(
@ -703,7 +703,7 @@ func TestLinksOverLimit(t *testing.T) {
func TestSetSpanName(t *testing.T) { func TestSetSpanName(t *testing.T) {
te := NewTestExporter() te := NewTestExporter()
tp := NewTracerProvider(WithSyncer(te)) tp := NewTracerProvider(WithSyncer(te), WithResource(resource.Empty()))
ctx := context.Background() ctx := context.Background()
want := "SpanName-1" want := "SpanName-1"
@ -725,7 +725,7 @@ func TestSetSpanName(t *testing.T) {
func TestSetSpanStatus(t *testing.T) { func TestSetSpanStatus(t *testing.T) {
te := NewTestExporter() te := NewTestExporter()
tp := NewTracerProvider(WithSyncer(te)) tp := NewTracerProvider(WithSyncer(te), WithResource(resource.Empty()))
span := startSpan(tp, "SpanStatus") span := startSpan(tp, "SpanStatus")
span.SetStatus(codes.Error, "Error") span.SetStatus(codes.Error, "Error")
@ -1083,7 +1083,7 @@ func TestRecordError(t *testing.T) {
for _, s := range scenarios { for _, s := range scenarios {
te := NewTestExporter() te := NewTestExporter()
tp := NewTracerProvider(WithSyncer(te)) tp := NewTracerProvider(WithSyncer(te), WithResource(resource.Empty()))
span := startSpan(tp, "RecordError") span := startSpan(tp, "RecordError")
errTime := time.Now() errTime := time.Now()
@ -1124,7 +1124,7 @@ func TestRecordError(t *testing.T) {
func TestRecordErrorNil(t *testing.T) { func TestRecordErrorNil(t *testing.T) {
te := NewTestExporter() te := NewTestExporter()
tp := NewTracerProvider(WithSyncer(te)) tp := NewTracerProvider(WithSyncer(te), WithResource(resource.Empty()))
span := startSpan(tp, "RecordErrorNil") span := startSpan(tp, "RecordErrorNil")
span.RecordError(nil) span.RecordError(nil)
@ -1154,7 +1154,7 @@ func TestRecordErrorNil(t *testing.T) {
func TestWithSpanKind(t *testing.T) { func TestWithSpanKind(t *testing.T) {
te := NewTestExporter() te := NewTestExporter()
tp := NewTracerProvider(WithSyncer(te), WithConfig(Config{DefaultSampler: AlwaysSample()})) tp := NewTracerProvider(WithSyncer(te), WithConfig(Config{DefaultSampler: AlwaysSample()}), WithResource(resource.Empty()))
tr := tp.Tracer("withSpanKind") tr := tp.Tracer("withSpanKind")
_, span := tr.Start(context.Background(), "WithoutSpanKind") _, span := tr.Start(context.Background(), "WithoutSpanKind")
@ -1191,40 +1191,72 @@ func TestWithSpanKind(t *testing.T) {
} }
func TestWithResource(t *testing.T) { func TestWithResource(t *testing.T) {
te := NewTestExporter() cases := []struct {
tp := NewTracerProvider(WithSyncer(te), name string
WithConfig(Config{DefaultSampler: AlwaysSample()}), options []TracerProviderOption
WithResource(resource.NewWithAttributes(label.String("rk1", "rv1"), label.Int64("rk2", 5)))) want *resource.Resource
span := startSpan(tp, "WithResource") msg string
span.SetAttributes(label.String("key1", "value1")) }{
got, err := endSpan(te, span) {
if err != nil { name: "explicitly empty resource",
t.Error(err.Error()) options: []TracerProviderOption{WithResource(resource.Empty())},
} want: resource.Empty(),
want := &export.SpanSnapshot{
SpanContext: trace.SpanContext{
TraceID: tid,
TraceFlags: 0x1,
}, },
ParentSpanID: sid, {
Name: "span0", name: "uses default if no resource option",
Attributes: []label.KeyValue{ options: []TracerProviderOption{},
label.String("key1", "value1"), want: resource.Default(),
},
{
name: "explicit resource",
options: []TracerProviderOption{WithResource(resource.NewWithAttributes(label.String("rk1", "rv1"), label.Int64("rk2", 5)))},
want: resource.NewWithAttributes(label.String("rk1", "rv1"), label.Int64("rk2", 5)),
},
{
name: "last resource wins",
options: []TracerProviderOption{
WithResource(resource.NewWithAttributes(label.String("rk1", "vk1"), label.Int64("rk2", 5))),
WithResource(resource.NewWithAttributes(label.String("rk3", "rv3"), label.Int64("rk4", 10)))},
want: resource.NewWithAttributes(label.String("rk3", "rv3"), label.Int64("rk4", 10)),
}, },
SpanKind: trace.SpanKindInternal,
HasRemoteParent: true,
Resource: resource.NewWithAttributes(label.String("rk1", "rv1"), label.Int64("rk2", 5)),
InstrumentationLibrary: instrumentation.Library{Name: "WithResource"},
} }
if diff := cmpDiff(got, want); diff != "" { for _, tc := range cases {
t.Errorf("WithResource:\n -got +want %s", diff) tc := tc
t.Run(tc.name, func(t *testing.T) {
te := NewTestExporter()
defaultOptions := []TracerProviderOption{WithSyncer(te), WithConfig(Config{DefaultSampler: AlwaysSample()})}
tp := NewTracerProvider(append(defaultOptions, tc.options...)...)
span := startSpan(tp, "WithResource")
span.SetAttributes(label.String("key1", "value1"))
got, err := endSpan(te, span)
if err != nil {
t.Error(err.Error())
}
want := &export.SpanSnapshot{
SpanContext: trace.SpanContext{
TraceID: tid,
TraceFlags: 0x1,
},
ParentSpanID: sid,
Name: "span0",
Attributes: []label.KeyValue{
label.String("key1", "value1"),
},
SpanKind: trace.SpanKindInternal,
HasRemoteParent: true,
Resource: tc.want,
InstrumentationLibrary: instrumentation.Library{Name: "WithResource"},
}
if diff := cmpDiff(got, want); diff != "" {
t.Errorf("WithResource:\n -got +want %s", diff)
}
})
} }
} }
func TestWithInstrumentationVersion(t *testing.T) { func TestWithInstrumentationVersion(t *testing.T) {
te := NewTestExporter() te := NewTestExporter()
tp := NewTracerProvider(WithSyncer(te)) tp := NewTracerProvider(WithSyncer(te), WithResource(resource.Empty()))
ctx := context.Background() ctx := context.Background()
ctx = trace.ContextWithRemoteSpanContext(ctx, remoteSpanContext()) ctx = trace.ContextWithRemoteSpanContext(ctx, remoteSpanContext())
@ -1258,7 +1290,7 @@ func TestWithInstrumentationVersion(t *testing.T) {
func TestSpanCapturesPanic(t *testing.T) { func TestSpanCapturesPanic(t *testing.T) {
te := NewTestExporter() te := NewTestExporter()
tp := NewTracerProvider(WithSyncer(te)) tp := NewTracerProvider(WithSyncer(te), WithResource(resource.Empty()))
_, span := tp.Tracer("CatchPanic").Start( _, span := tp.Tracer("CatchPanic").Start(
context.Background(), context.Background(),
"span", "span",
@ -1363,7 +1395,7 @@ func TestReadOnlySpan(t *testing.T) {
} }
func TestReadWriteSpan(t *testing.T) { func TestReadWriteSpan(t *testing.T) {
tp := NewTracerProvider() tp := NewTracerProvider(WithResource(resource.Empty()))
cfg := tp.config.Load().(*Config) cfg := tp.config.Load().(*Config)
tr := tp.Tracer("ReadWriteSpan") tr := tp.Tracer("ReadWriteSpan")