You've already forked opentelemetry-go
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:
@ -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)
|
||||||
|
@ -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)
|
||||||
|
|
||||||
|
@ -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,
|
||||||
|
@ -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)
|
||||||
|
@ -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)
|
||||||
|
@ -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)
|
||||||
|
}
|
||||||
|
@ -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.
|
||||||
|
@ -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
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
|
@ -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")
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user