mirror of
https://github.com/open-telemetry/opentelemetry-go.git
synced 2025-04-07 07:00:13 +02:00
sdk/trace: removing ApplyConfig and Config (#1693)
This patch removes `ApplyConfig` method and `Config` struct from `go.opentelemetry.io/otel/sdk/trace` package. To ensure valid config for TracerProvider, it adds `ensureValidTracerProviderConfig` private function. Jaeger and Zipkin have been used the `Config` directly across package boundaries. Since `Config` is removed, they can't use it. This change, thus, replaces `WithSDK` with `WithSDKOptions`. Resolves #1636, #1705.
This commit is contained in:
parent
1d42be1601
commit
4beb70416e
@ -31,6 +31,8 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
|
||||
- Jaeger exporter populates Jaeger's Span Process from Resource. (#1673)
|
||||
- `"go.opentelemetry.io/otel/sdk/resource".NewWithAttributes` will now drop any invalid attributes passed. (#1703)
|
||||
- `"go.opentelemetry.io/otel/sdk/resource".StringDetector` will now error if the produced attribute is invalid. (#1703)
|
||||
- Changed `WithSDK` to `WithSDKOptions` to accept variadic arguments of `TracerProviderOption` type in `go.opentelemetry.io/otel/exporters/trace/jaeger` package. (#1693)
|
||||
- Changed `WithSDK` to `WithSDKOptions` to accept variadic arguments of `TracerProviderOption` type in `go.opentelemetry.io/otel/exporters/trace/zipkin` package. (#1693)
|
||||
|
||||
### Removed
|
||||
|
||||
@ -41,6 +43,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
|
||||
- Removed `WithConfig` from tracer provider to avoid overriding configuration. (#1633)
|
||||
- Removed `serviceName` parameter from Zipkin exporter and uses resource instead. (#1549)
|
||||
- Removed `jaeger.WithProcess`. (#1673)
|
||||
- Removed `ApplyConfig` method and `Config` struct from tracer provider. (#1693)
|
||||
|
||||
### Fixed
|
||||
|
||||
|
@ -34,14 +34,14 @@ func initTracer() func() {
|
||||
// Create and install Jaeger export pipeline.
|
||||
flush, err := jaeger.InstallNewPipeline(
|
||||
jaeger.WithCollectorEndpoint("http://localhost:14268/api/traces"),
|
||||
jaeger.WithSDK(&sdktrace.Config{
|
||||
DefaultSampler: sdktrace.AlwaysSample(),
|
||||
Resource: resource.NewWithAttributes(
|
||||
jaeger.WithSDKOptions(
|
||||
sdktrace.WithSampler(sdktrace.AlwaysSample()),
|
||||
sdktrace.WithResource(resource.NewWithAttributes(
|
||||
semconv.ServiceNameKey.String("trace-demo"),
|
||||
attribute.String("exporter", "jaeger"),
|
||||
attribute.Float64("float", 312.23),
|
||||
),
|
||||
}),
|
||||
)),
|
||||
),
|
||||
)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
|
@ -43,7 +43,7 @@ func initTracer(url string) func() {
|
||||
exporter, err := zipkin.NewRawExporter(
|
||||
url,
|
||||
zipkin.WithLogger(logger),
|
||||
zipkin.WithSDK(&sdktrace.Config{DefaultSampler: sdktrace.AlwaysSample()}),
|
||||
zipkin.WithSDKOptions(sdktrace.WithSampler(sdktrace.AlwaysSample())),
|
||||
)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
|
@ -52,7 +52,8 @@ type options struct {
|
||||
// BatchMaxCount defines the maximum number of spans sent in one batch
|
||||
BatchMaxCount int
|
||||
|
||||
Config *sdktrace.Config
|
||||
// TracerProviderOptions defines the options for tracer provider of sdk.
|
||||
TracerProviderOptions []sdktrace.TracerProviderOption
|
||||
|
||||
Disabled bool
|
||||
}
|
||||
@ -71,10 +72,10 @@ func WithBatchMaxCount(batchMaxCount int) Option {
|
||||
}
|
||||
}
|
||||
|
||||
// WithSDK sets the SDK config for the exporter pipeline.
|
||||
func WithSDK(config *sdktrace.Config) Option {
|
||||
// WithSDKOptions configures options for tracer provider of sdk.
|
||||
func WithSDKOptions(opts ...sdktrace.TracerProviderOption) Option {
|
||||
return func(o *options) {
|
||||
o.Config = config
|
||||
o.TracerProviderOptions = opts
|
||||
}
|
||||
}
|
||||
|
||||
@ -157,15 +158,7 @@ func NewExportPipeline(endpointOption EndpointOption, opts ...Option) (trace.Tra
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
pOpts := []sdktrace.TracerProviderOption{sdktrace.WithSyncer(exporter)}
|
||||
if exporter.o.Config != nil {
|
||||
pOpts = append(pOpts,
|
||||
sdktrace.WithSampler(exporter.o.Config.DefaultSampler),
|
||||
sdktrace.WithIDGenerator(exporter.o.Config.IDGenerator),
|
||||
sdktrace.WithSpanLimits(exporter.o.Config.SpanLimits),
|
||||
sdktrace.WithResource(exporter.o.Config.Resource),
|
||||
)
|
||||
}
|
||||
pOpts := append(exporter.o.TracerProviderOptions, sdktrace.WithSyncer(exporter))
|
||||
tp := sdktrace.NewTracerProvider(pOpts...)
|
||||
return tp, exporter.Flush, nil
|
||||
}
|
||||
|
@ -17,6 +17,7 @@ package jaeger
|
||||
import (
|
||||
"context"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"os"
|
||||
"sort"
|
||||
"strings"
|
||||
@ -114,9 +115,7 @@ func TestNewExportPipeline(t *testing.T) {
|
||||
name: "always on",
|
||||
endpoint: WithCollectorEndpoint(collectorEndpoint),
|
||||
options: []Option{
|
||||
WithSDK(&sdktrace.Config{
|
||||
DefaultSampler: sdktrace.AlwaysSample(),
|
||||
}),
|
||||
WithSDKOptions(sdktrace.WithSampler(sdktrace.AlwaysSample())),
|
||||
},
|
||||
expectedProviderType: &sdktrace.TracerProvider{},
|
||||
testSpanSampling: true,
|
||||
@ -126,9 +125,7 @@ func TestNewExportPipeline(t *testing.T) {
|
||||
name: "never",
|
||||
endpoint: WithCollectorEndpoint(collectorEndpoint),
|
||||
options: []Option{
|
||||
WithSDK(&sdktrace.Config{
|
||||
DefaultSampler: sdktrace.NeverSample(),
|
||||
}),
|
||||
WithSDKOptions(sdktrace.WithSampler(sdktrace.NeverSample())),
|
||||
},
|
||||
expectedProviderType: &sdktrace.TracerProvider{},
|
||||
testSpanSampling: true,
|
||||
@ -281,11 +278,11 @@ func TestNewRawExporterShouldFailIfCollectorUnset(t *testing.T) {
|
||||
}
|
||||
|
||||
type testCollectorEnpoint struct {
|
||||
spansUploaded []*gen.Span
|
||||
batchesUploaded []*gen.Batch
|
||||
}
|
||||
|
||||
func (c *testCollectorEnpoint) upload(batch *gen.Batch) error {
|
||||
c.spansUploaded = append(c.spansUploaded, batch.Spans...)
|
||||
c.batchesUploaded = append(c.batchesUploaded, batch)
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -297,6 +294,12 @@ func withTestCollectorEndpoint() func() (batchUploader, error) {
|
||||
}
|
||||
}
|
||||
|
||||
func withTestCollectorEndpointInjected(ce *testCollectorEnpoint) func() (batchUploader, error) {
|
||||
return func() (batchUploader, error) {
|
||||
return ce, nil
|
||||
}
|
||||
}
|
||||
|
||||
func TestExporter_ExportSpan(t *testing.T) {
|
||||
const (
|
||||
serviceName = "test-service"
|
||||
@ -306,12 +309,12 @@ func TestExporter_ExportSpan(t *testing.T) {
|
||||
// Create Jaeger Exporter
|
||||
exp, err := NewRawExporter(
|
||||
withTestCollectorEndpoint(),
|
||||
WithSDK(&sdktrace.Config{
|
||||
Resource: resource.NewWithAttributes(
|
||||
WithSDKOptions(
|
||||
sdktrace.WithResource(resource.NewWithAttributes(
|
||||
semconv.ServiceNameKey.String(serviceName),
|
||||
attribute.String(tagKey, tagVal),
|
||||
),
|
||||
}),
|
||||
)),
|
||||
),
|
||||
)
|
||||
|
||||
assert.NoError(t, err)
|
||||
@ -328,7 +331,8 @@ func TestExporter_ExportSpan(t *testing.T) {
|
||||
|
||||
exp.Flush()
|
||||
tc := exp.uploader.(*testCollectorEnpoint)
|
||||
assert.True(t, len(tc.spansUploaded) == 1)
|
||||
assert.True(t, len(tc.batchesUploaded) == 1)
|
||||
assert.True(t, len(tc.batchesUploaded[0].GetSpans()) == 1)
|
||||
}
|
||||
|
||||
func Test_spanSnapshotToThrift(t *testing.T) {
|
||||
@ -886,3 +890,50 @@ func TestProcess(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewExporterPipelineWithOptions(t *testing.T) {
|
||||
envStore, err := ottest.SetEnvVariables(map[string]string{
|
||||
envDisabled: "false",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
defer func() {
|
||||
require.NoError(t, envStore.Restore())
|
||||
}()
|
||||
|
||||
const (
|
||||
serviceName = "test-service"
|
||||
eventCountLimit = 10
|
||||
)
|
||||
|
||||
testCollector := &testCollectorEnpoint{}
|
||||
tp, spanFlush, err := NewExportPipeline(
|
||||
withTestCollectorEndpointInjected(testCollector),
|
||||
WithSDKOptions(
|
||||
sdktrace.WithResource(resource.NewWithAttributes(
|
||||
semconv.ServiceNameKey.String(serviceName),
|
||||
)),
|
||||
sdktrace.WithSpanLimits(sdktrace.SpanLimits{
|
||||
EventCountLimit: eventCountLimit,
|
||||
}),
|
||||
),
|
||||
)
|
||||
assert.NoError(t, err)
|
||||
|
||||
otel.SetTracerProvider(tp)
|
||||
_, span := otel.Tracer("test-tracer").Start(context.Background(), "test-span")
|
||||
for i := 0; i < eventCountLimit*2; i++ {
|
||||
span.AddEvent(fmt.Sprintf("event-%d", i))
|
||||
}
|
||||
span.End()
|
||||
spanFlush()
|
||||
|
||||
assert.True(t, span.SpanContext().IsValid())
|
||||
|
||||
batchesUploaded := testCollector.batchesUploaded
|
||||
assert.True(t, len(batchesUploaded) == 1)
|
||||
uploadedBatch := batchesUploaded[0]
|
||||
assert.Equal(t, serviceName, uploadedBatch.GetProcess().GetServiceName())
|
||||
assert.True(t, len(uploadedBatch.GetSpans()) == 1)
|
||||
uploadedSpan := uploadedBatch.GetSpans()[0]
|
||||
assert.Equal(t, eventCountLimit, len(uploadedSpan.GetLogs()))
|
||||
}
|
||||
|
@ -53,7 +53,7 @@ var (
|
||||
type options struct {
|
||||
client *http.Client
|
||||
logger *log.Logger
|
||||
config *sdktrace.Config
|
||||
tpOpts []sdktrace.TracerProviderOption
|
||||
}
|
||||
|
||||
// Option defines a function that configures the exporter.
|
||||
@ -73,10 +73,10 @@ func WithClient(client *http.Client) Option {
|
||||
}
|
||||
}
|
||||
|
||||
// WithSDK sets the SDK config for the exporter pipeline.
|
||||
func WithSDK(config *sdktrace.Config) Option {
|
||||
return func(o *options) {
|
||||
o.config = config
|
||||
// WithSDKOptions configures options passed to the created TracerProvider.
|
||||
func WithSDKOptions(tpOpts ...sdktrace.TracerProviderOption) Option {
|
||||
return func(opts *options) {
|
||||
opts.tpOpts = tpOpts
|
||||
}
|
||||
}
|
||||
|
||||
@ -116,10 +116,8 @@ func NewExportPipeline(collectorURL string, opts ...Option) (*sdktrace.TracerPro
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tp := sdktrace.NewTracerProvider(sdktrace.WithBatcher(exporter))
|
||||
if exporter.o.config != nil {
|
||||
tp.ApplyConfig(*exporter.o.config)
|
||||
}
|
||||
tpOpts := append(exporter.o.tpOpts, sdktrace.WithBatcher(exporter))
|
||||
tp := sdktrace.NewTracerProvider(tpOpts...)
|
||||
|
||||
return tp, err
|
||||
}
|
||||
|
@ -63,9 +63,7 @@ func TestNewExportPipeline(t *testing.T) {
|
||||
{
|
||||
name: "always on",
|
||||
options: []Option{
|
||||
WithSDK(&sdktrace.Config{
|
||||
DefaultSampler: sdktrace.AlwaysSample(),
|
||||
}),
|
||||
WithSDKOptions(sdktrace.WithSampler(sdktrace.AlwaysSample())),
|
||||
},
|
||||
testSpanSampling: true,
|
||||
spanShouldBeSampled: true,
|
||||
@ -73,9 +71,7 @@ func TestNewExportPipeline(t *testing.T) {
|
||||
{
|
||||
name: "never",
|
||||
options: []Option{
|
||||
WithSDK(&sdktrace.Config{
|
||||
DefaultSampler: sdktrace.NeverSample(),
|
||||
}),
|
||||
WithSDKOptions(sdktrace.WithSampler(sdktrace.NeverSample())),
|
||||
},
|
||||
testSpanSampling: true,
|
||||
spanShouldBeSampled: false,
|
||||
@ -389,3 +385,34 @@ func TestErrorOnExportShutdownExporter(t *testing.T) {
|
||||
assert.NoError(t, exp.Shutdown(context.Background()))
|
||||
assert.NoError(t, exp.ExportSpans(context.Background(), nil))
|
||||
}
|
||||
|
||||
func TestNewExportPipelineWithOptions(t *testing.T) {
|
||||
const eventCountLimit = 10
|
||||
|
||||
collector := startMockZipkinCollector(t)
|
||||
defer collector.Close()
|
||||
|
||||
tp, err := NewExportPipeline(collector.url,
|
||||
WithSDKOptions(
|
||||
sdktrace.WithResource(resource.NewWithAttributes(
|
||||
semconv.ServiceNameKey.String("zipkin-test"),
|
||||
)),
|
||||
sdktrace.WithSpanLimits(sdktrace.SpanLimits{
|
||||
EventCountLimit: eventCountLimit,
|
||||
}),
|
||||
),
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
otel.SetTracerProvider(tp)
|
||||
_, span := otel.Tracer("zipkin-tracer").Start(context.Background(), "test-span")
|
||||
for i := 0; i < eventCountLimit*2; i++ {
|
||||
span.AddEvent(fmt.Sprintf("event-%d", i))
|
||||
}
|
||||
span.End()
|
||||
|
||||
require.NoError(t, tp.Shutdown(context.Background()))
|
||||
require.Equal(t, 1, collector.ModelsLen())
|
||||
model := collector.StealModels()[0]
|
||||
require.Equal(t, len(model.Annotations), eventCountLimit)
|
||||
}
|
||||
|
@ -14,25 +14,6 @@
|
||||
|
||||
package trace // import "go.opentelemetry.io/otel/sdk/trace"
|
||||
|
||||
import (
|
||||
"go.opentelemetry.io/otel/sdk/resource"
|
||||
)
|
||||
|
||||
// Config represents the global tracing configuration.
|
||||
type Config struct {
|
||||
// DefaultSampler is the default sampler used when creating new spans.
|
||||
DefaultSampler Sampler
|
||||
|
||||
// IDGenerator is for internal use only.
|
||||
IDGenerator IDGenerator
|
||||
|
||||
// SpanLimits used to limit the number of attributes, events and links to a span.
|
||||
SpanLimits SpanLimits
|
||||
|
||||
// Resource contains attributes representing an entity that produces telemetry.
|
||||
Resource *resource.Resource
|
||||
}
|
||||
|
||||
// SpanLimits represents the limits of a span.
|
||||
type SpanLimits struct {
|
||||
// AttributeCountLimit is the maximum allowed span attribute count.
|
||||
@ -51,6 +32,24 @@ type SpanLimits struct {
|
||||
AttributePerLinkCountLimit int
|
||||
}
|
||||
|
||||
func (sl *SpanLimits) ensureDefault() {
|
||||
if sl.EventCountLimit <= 0 {
|
||||
sl.EventCountLimit = DefaultEventCountLimit
|
||||
}
|
||||
if sl.AttributeCountLimit <= 0 {
|
||||
sl.AttributeCountLimit = DefaultAttributeCountLimit
|
||||
}
|
||||
if sl.LinkCountLimit <= 0 {
|
||||
sl.LinkCountLimit = DefaultLinkCountLimit
|
||||
}
|
||||
if sl.AttributePerEventCountLimit <= 0 {
|
||||
sl.AttributePerEventCountLimit = DefaultAttributePerEventCountLimit
|
||||
}
|
||||
if sl.AttributePerLinkCountLimit <= 0 {
|
||||
sl.AttributePerLinkCountLimit = DefaultAttributePerLinkCountLimit
|
||||
}
|
||||
}
|
||||
|
||||
const (
|
||||
// DefaultAttributeCountLimit is the default maximum allowed span attribute count.
|
||||
DefaultAttributeCountLimit = 128
|
||||
|
@ -38,7 +38,18 @@ const (
|
||||
// TracerProviderConfig
|
||||
type TracerProviderConfig struct {
|
||||
processors []SpanProcessor
|
||||
config Config
|
||||
|
||||
// sampler is the default sampler used when creating new spans.
|
||||
sampler Sampler
|
||||
|
||||
// idGenerator is used to generate all Span and Trace IDs when needed.
|
||||
idGenerator IDGenerator
|
||||
|
||||
// spanLimits defines the attribute, event, and link limits for spans.
|
||||
spanLimits SpanLimits
|
||||
|
||||
// resource contains attributes representing an entity that produces telemetry.
|
||||
resource *resource.Resource
|
||||
}
|
||||
|
||||
type TracerProviderOption func(*TracerProviderConfig)
|
||||
@ -47,7 +58,10 @@ type TracerProvider struct {
|
||||
mu sync.Mutex
|
||||
namedTracer map[instrumentation.Library]*tracer
|
||||
spanProcessors atomic.Value
|
||||
config atomic.Value // access atomically
|
||||
sampler Sampler
|
||||
idGenerator IDGenerator
|
||||
spanLimits SpanLimits
|
||||
resource *resource.Resource
|
||||
}
|
||||
|
||||
var _ trace.TracerProvider = &TracerProvider{}
|
||||
@ -69,27 +83,20 @@ func NewTracerProvider(opts ...TracerProviderOption) *TracerProvider {
|
||||
opt(o)
|
||||
}
|
||||
|
||||
ensureValidTracerProviderConfig(o)
|
||||
|
||||
tp := &TracerProvider{
|
||||
namedTracer: make(map[instrumentation.Library]*tracer),
|
||||
sampler: o.sampler,
|
||||
idGenerator: o.idGenerator,
|
||||
spanLimits: o.spanLimits,
|
||||
resource: o.resource,
|
||||
}
|
||||
tp.config.Store(&Config{
|
||||
DefaultSampler: ParentBased(AlwaysSample()),
|
||||
IDGenerator: defaultIDGenerator(),
|
||||
SpanLimits: SpanLimits{
|
||||
AttributeCountLimit: DefaultAttributeCountLimit,
|
||||
EventCountLimit: DefaultEventCountLimit,
|
||||
LinkCountLimit: DefaultLinkCountLimit,
|
||||
AttributePerEventCountLimit: DefaultAttributePerEventCountLimit,
|
||||
AttributePerLinkCountLimit: DefaultAttributePerLinkCountLimit,
|
||||
},
|
||||
})
|
||||
|
||||
for _, sp := range o.processors {
|
||||
tp.RegisterSpanProcessor(sp)
|
||||
}
|
||||
|
||||
tp.ApplyConfig(o.config)
|
||||
|
||||
return tp
|
||||
}
|
||||
|
||||
@ -175,40 +182,6 @@ func (p *TracerProvider) UnregisterSpanProcessor(s SpanProcessor) {
|
||||
p.spanProcessors.Store(spss)
|
||||
}
|
||||
|
||||
// ApplyConfig changes the configuration of the provider.
|
||||
// If a field in the configuration is empty or nil then its original value is preserved.
|
||||
func (p *TracerProvider) ApplyConfig(cfg Config) {
|
||||
p.mu.Lock()
|
||||
defer p.mu.Unlock()
|
||||
c := *p.config.Load().(*Config)
|
||||
if cfg.DefaultSampler != nil {
|
||||
c.DefaultSampler = cfg.DefaultSampler
|
||||
}
|
||||
if cfg.IDGenerator != nil {
|
||||
c.IDGenerator = cfg.IDGenerator
|
||||
}
|
||||
if cfg.SpanLimits.EventCountLimit > 0 {
|
||||
c.SpanLimits.EventCountLimit = cfg.SpanLimits.EventCountLimit
|
||||
}
|
||||
if cfg.SpanLimits.AttributeCountLimit > 0 {
|
||||
c.SpanLimits.AttributeCountLimit = cfg.SpanLimits.AttributeCountLimit
|
||||
}
|
||||
if cfg.SpanLimits.LinkCountLimit > 0 {
|
||||
c.SpanLimits.LinkCountLimit = cfg.SpanLimits.LinkCountLimit
|
||||
}
|
||||
if cfg.SpanLimits.AttributePerEventCountLimit > 0 {
|
||||
c.SpanLimits.AttributePerEventCountLimit = cfg.SpanLimits.AttributePerEventCountLimit
|
||||
}
|
||||
if cfg.SpanLimits.AttributePerLinkCountLimit > 0 {
|
||||
c.SpanLimits.AttributePerLinkCountLimit = cfg.SpanLimits.AttributePerLinkCountLimit
|
||||
}
|
||||
c.Resource = cfg.Resource
|
||||
if c.Resource == nil {
|
||||
c.Resource = resource.Default()
|
||||
}
|
||||
p.config.Store(&c)
|
||||
}
|
||||
|
||||
// ForceFlush immediately exports all spans that have not yet been exported for
|
||||
// all the registered span processors.
|
||||
func (p *TracerProvider) ForceFlush(ctx context.Context) error {
|
||||
@ -290,7 +263,9 @@ func WithSpanProcessor(sp SpanProcessor) TracerProviderOption {
|
||||
// resource.Default() Resource by default.
|
||||
func WithResource(r *resource.Resource) TracerProviderOption {
|
||||
return func(opts *TracerProviderConfig) {
|
||||
opts.config.Resource = r
|
||||
if r != nil {
|
||||
opts.resource = r
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -303,7 +278,9 @@ func WithResource(r *resource.Resource) TracerProviderOption {
|
||||
// IDGenerator by default.
|
||||
func WithIDGenerator(g IDGenerator) TracerProviderOption {
|
||||
return func(opts *TracerProviderConfig) {
|
||||
opts.config.IDGenerator = g
|
||||
if g != nil {
|
||||
opts.idGenerator = g
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -316,7 +293,9 @@ func WithIDGenerator(g IDGenerator) TracerProviderOption {
|
||||
// ParentBased(AlwaysSample) Sampler by default.
|
||||
func WithSampler(s Sampler) TracerProviderOption {
|
||||
return func(opts *TracerProviderConfig) {
|
||||
opts.config.DefaultSampler = s
|
||||
if s != nil {
|
||||
opts.sampler = s
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -329,6 +308,20 @@ func WithSampler(s Sampler) TracerProviderOption {
|
||||
// SpanLimits.
|
||||
func WithSpanLimits(sl SpanLimits) TracerProviderOption {
|
||||
return func(opts *TracerProviderConfig) {
|
||||
opts.config.SpanLimits = sl
|
||||
opts.spanLimits = sl
|
||||
}
|
||||
}
|
||||
|
||||
// ensureValidTracerProviderConfig ensures that given TracerProviderConfig is valid.
|
||||
func ensureValidTracerProviderConfig(cfg *TracerProviderConfig) {
|
||||
if cfg.sampler == nil {
|
||||
cfg.sampler = ParentBased(AlwaysSample())
|
||||
}
|
||||
if cfg.idGenerator == nil {
|
||||
cfg.idGenerator = defaultIDGenerator()
|
||||
}
|
||||
cfg.spanLimits.ensureDefault()
|
||||
if cfg.resource == nil {
|
||||
cfg.resource = resource.Default()
|
||||
}
|
||||
}
|
||||
|
@ -521,18 +521,18 @@ func (*span) private() {}
|
||||
func startSpanInternal(ctx context.Context, tr *tracer, name string, parent trace.SpanContext, remoteParent bool, o *trace.SpanConfig) *span {
|
||||
span := &span{}
|
||||
|
||||
cfg := tr.provider.config.Load().(*Config)
|
||||
provider := tr.provider
|
||||
|
||||
var tid trace.TraceID
|
||||
var sid trace.SpanID
|
||||
|
||||
if hasEmptySpanContext(parent) {
|
||||
// Generate both TraceID and SpanID
|
||||
tid, sid = cfg.IDGenerator.NewIDs(ctx)
|
||||
tid, sid = provider.idGenerator.NewIDs(ctx)
|
||||
} else {
|
||||
// TraceID already exists, just generate a SpanID
|
||||
tid = parent.TraceID()
|
||||
sid = cfg.IDGenerator.NewSpanID(ctx, tid)
|
||||
sid = provider.idGenerator.NewSpanID(ctx, tid)
|
||||
}
|
||||
|
||||
span.spanContext = trace.NewSpanContext(trace.SpanContextConfig{
|
||||
@ -542,17 +542,18 @@ func startSpanInternal(ctx context.Context, tr *tracer, name string, parent trac
|
||||
TraceState: parent.TraceState(),
|
||||
})
|
||||
|
||||
span.attributes = newAttributesMap(cfg.SpanLimits.AttributeCountLimit)
|
||||
span.messageEvents = newEvictedQueue(cfg.SpanLimits.EventCountLimit)
|
||||
span.links = newEvictedQueue(cfg.SpanLimits.LinkCountLimit)
|
||||
span.spanLimits = cfg.SpanLimits
|
||||
spanLimits := provider.spanLimits
|
||||
span.attributes = newAttributesMap(spanLimits.AttributeCountLimit)
|
||||
span.messageEvents = newEvictedQueue(spanLimits.EventCountLimit)
|
||||
span.links = newEvictedQueue(spanLimits.LinkCountLimit)
|
||||
span.spanLimits = spanLimits
|
||||
|
||||
data := samplingData{
|
||||
noParent: hasEmptySpanContext(parent),
|
||||
remoteParent: remoteParent,
|
||||
parent: parent,
|
||||
name: name,
|
||||
cfg: cfg,
|
||||
sampler: provider.sampler,
|
||||
span: span,
|
||||
attributes: o.Attributes,
|
||||
links: o.Links,
|
||||
@ -579,7 +580,7 @@ func startSpanInternal(ctx context.Context, tr *tracer, name string, parent trac
|
||||
span.spanKind = trace.ValidateSpanKind(o.SpanKind)
|
||||
span.name = name
|
||||
span.hasRemoteParent = remoteParent
|
||||
span.resource = cfg.Resource
|
||||
span.resource = provider.resource
|
||||
span.instrumentationLibrary = tr.instrumentationLibrary
|
||||
|
||||
span.SetAttributes(samplingResult.Attributes...)
|
||||
@ -598,7 +599,7 @@ type samplingData struct {
|
||||
remoteParent bool
|
||||
parent trace.SpanContext
|
||||
name string
|
||||
cfg *Config
|
||||
sampler Sampler
|
||||
span *span
|
||||
attributes []attribute.KeyValue
|
||||
links []trace.Link
|
||||
@ -606,8 +607,7 @@ type samplingData struct {
|
||||
}
|
||||
|
||||
func makeSamplingDecision(data samplingData) SamplingResult {
|
||||
sampler := data.cfg.DefaultSampler
|
||||
return sampler.ShouldSample(SamplingParameters{
|
||||
return data.sampler.ShouldSample(SamplingParameters{
|
||||
ParentContext: data.parent,
|
||||
TraceID: data.span.spanContext.TraceID(),
|
||||
Name: data.name,
|
||||
|
@ -19,6 +19,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"math"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
@ -1375,11 +1376,10 @@ func TestReadOnlySpan(t *testing.T) {
|
||||
kv := attribute.String("foo", "bar")
|
||||
|
||||
tp := NewTracerProvider(WithResource(resource.NewWithAttributes(kv)))
|
||||
cfg := tp.config.Load().(*Config)
|
||||
tr := tp.Tracer("ReadOnlySpan", trace.WithInstrumentationVersion("3"))
|
||||
|
||||
// Initialize parent context.
|
||||
tID, sID := cfg.IDGenerator.NewIDs(context.Background())
|
||||
tID, sID := tp.idGenerator.NewIDs(context.Background())
|
||||
parent := trace.NewSpanContext(trace.SpanContextConfig{
|
||||
TraceID: tID,
|
||||
SpanID: sID,
|
||||
@ -1389,7 +1389,7 @@ func TestReadOnlySpan(t *testing.T) {
|
||||
ctx := trace.ContextWithRemoteSpanContext(context.Background(), parent)
|
||||
|
||||
// Initialize linked context.
|
||||
tID, sID = cfg.IDGenerator.NewIDs(context.Background())
|
||||
tID, sID = tp.idGenerator.NewIDs(context.Background())
|
||||
linked := trace.NewSpanContext(trace.SpanContextConfig{
|
||||
TraceID: tID,
|
||||
SpanID: sID,
|
||||
@ -1456,11 +1456,10 @@ func TestReadOnlySpan(t *testing.T) {
|
||||
|
||||
func TestReadWriteSpan(t *testing.T) {
|
||||
tp := NewTracerProvider(WithResource(resource.Empty()))
|
||||
cfg := tp.config.Load().(*Config)
|
||||
tr := tp.Tracer("ReadWriteSpan")
|
||||
|
||||
// Initialize parent context.
|
||||
tID, sID := cfg.IDGenerator.NewIDs(context.Background())
|
||||
tID, sID := tp.idGenerator.NewIDs(context.Background())
|
||||
parent := trace.NewSpanContext(trace.SpanContextConfig{
|
||||
TraceID: tID,
|
||||
SpanID: sID,
|
||||
@ -1742,3 +1741,51 @@ func TestSamplerTraceState(t *testing.T) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
type testIDGenerator struct {
|
||||
traceID int
|
||||
spanID int
|
||||
}
|
||||
|
||||
func (gen *testIDGenerator) NewIDs(ctx context.Context) (trace.TraceID, trace.SpanID) {
|
||||
traceIDHex := fmt.Sprintf("%032x", gen.traceID)
|
||||
traceID, _ := trace.TraceIDFromHex(traceIDHex)
|
||||
gen.traceID++
|
||||
|
||||
spanID := gen.NewSpanID(ctx, traceID)
|
||||
return traceID, spanID
|
||||
}
|
||||
|
||||
func (gen *testIDGenerator) NewSpanID(ctx context.Context, traceID trace.TraceID) trace.SpanID {
|
||||
spanIDHex := fmt.Sprintf("%016x", gen.spanID)
|
||||
spanID, _ := trace.SpanIDFromHex(spanIDHex)
|
||||
gen.spanID++
|
||||
return spanID
|
||||
}
|
||||
|
||||
var _ IDGenerator = (*testIDGenerator)(nil)
|
||||
|
||||
func TestWithIDGenerator(t *testing.T) {
|
||||
const (
|
||||
startTraceID = 1
|
||||
startSpanID = 1
|
||||
numSpan = 10
|
||||
)
|
||||
|
||||
gen := &testIDGenerator{traceID: startSpanID, spanID: startSpanID}
|
||||
|
||||
for i := 0; i < numSpan; i++ {
|
||||
te := NewTestExporter()
|
||||
tp := NewTracerProvider(
|
||||
WithSyncer(te),
|
||||
WithIDGenerator(gen),
|
||||
)
|
||||
span := startSpan(tp, "TestWithIDGenerator")
|
||||
got, err := strconv.ParseUint(span.SpanContext().SpanID().String(), 16, 64)
|
||||
require.NoError(t, err)
|
||||
want := uint64(startSpanID + i)
|
||||
assert.Equal(t, got, want)
|
||||
_, err = endSpan(te, span)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user