diff --git a/examples/http/helloworld_client/main.go b/examples/http/helloworld_client/main.go index 9a2a67e90..362c126cd 100644 --- a/examples/http/helloworld_client/main.go +++ b/examples/http/helloworld_client/main.go @@ -35,7 +35,7 @@ func main() { trace.RegisterExporter(exporter) // Always trace for this demo. - trace.SetDefaultSampler(trace.AlwaysSample()) + trace.SetConfig(trace.Config{DefaultSampler: trace.AlwaysSample()}) // Report stats at every second. view.SetReportingPeriod(1 * time.Second) diff --git a/examples/http/helloworld_server/main.go b/examples/http/helloworld_server/main.go index dbeb438ca..592a7e769 100644 --- a/examples/http/helloworld_server/main.go +++ b/examples/http/helloworld_server/main.go @@ -37,7 +37,7 @@ func main() { trace.RegisterExporter(exporter) // Always trace for this demo. - trace.SetDefaultSampler(trace.AlwaysSample()) + trace.SetConfig(trace.Config{DefaultSampler: trace.AlwaysSample()}) // Report stats at every second. view.SetReportingPeriod(1 * time.Second) diff --git a/exporter/jaeger/example/main.go b/exporter/jaeger/example/main.go index c07d9840f..4dcfd1297 100644 --- a/exporter/jaeger/example/main.go +++ b/exporter/jaeger/example/main.go @@ -39,7 +39,7 @@ func main() { trace.RegisterExporter(exporter) // For demoing purposes, always sample. - trace.SetDefaultSampler(trace.AlwaysSample()) + trace.SetConfig(trace.Config{DefaultSampler: trace.AlwaysSample()}) ctx, span := trace.StartSpan(ctx, "/foo") bar(ctx) diff --git a/exporter/stackdriver/stackdriver_test.go b/exporter/stackdriver/stackdriver_test.go index 59b91303b..29db01b22 100644 --- a/exporter/stackdriver/stackdriver_test.go +++ b/exporter/stackdriver/stackdriver_test.go @@ -47,7 +47,7 @@ func TestExport(t *testing.T) { view.RegisterExporter(exporter) defer view.UnregisterExporter(exporter) - trace.SetDefaultSampler(trace.AlwaysSample()) + trace.SetConfig(trace.Config{DefaultSampler: trace.AlwaysSample()}) span := trace.NewSpan("custom-span", nil, trace.StartOptions{}) time.Sleep(10 * time.Millisecond) @@ -100,7 +100,7 @@ func TestGRPC(t *testing.T) { view.RegisterExporter(exporter) defer view.UnregisterExporter(exporter) - trace.SetDefaultSampler(trace.AlwaysSample()) + trace.SetConfig(trace.Config{DefaultSampler: trace.AlwaysSample()}) client, done := testpb.NewTestClient(t) defer done() diff --git a/exporter/stackdriver/trace_test.go b/exporter/stackdriver/trace_test.go index 9175af62e..4a20a28a4 100644 --- a/exporter/stackdriver/trace_test.go +++ b/exporter/stackdriver/trace_test.go @@ -35,7 +35,7 @@ func TestBundling(t *testing.T) { } trace.RegisterExporter(exporter) - trace.SetDefaultSampler(trace.AlwaysSample()) + trace.SetConfig(trace.Config{DefaultSampler: trace.AlwaysSample()}) for i := 0; i < 35; i++ { _, span := trace.StartSpan(context.Background(), "span") span.End() diff --git a/exporter/zipkin/example/main.go b/exporter/zipkin/example/main.go index f82631a12..b0da404d2 100644 --- a/exporter/zipkin/example/main.go +++ b/exporter/zipkin/example/main.go @@ -42,7 +42,7 @@ func main() { trace.RegisterExporter(exporter) // For example purposes, sample every trace. - trace.SetDefaultSampler(trace.AlwaysSample()) + trace.SetConfig(trace.Config{DefaultSampler: trace.AlwaysSample()}) ctx := context.Background() foo(ctx) diff --git a/plugin/ocgrpc/trace_test.go b/plugin/ocgrpc/trace_test.go index 7cd1b2e52..7a7ef1174 100644 --- a/plugin/ocgrpc/trace_test.go +++ b/plugin/ocgrpc/trace_test.go @@ -33,7 +33,7 @@ func (t *testExporter) ExportSpan(s *trace.SpanData) { } func TestStreaming(t *testing.T) { - trace.SetDefaultSampler(trace.AlwaysSample()) + trace.SetConfig(trace.Config{DefaultSampler: trace.AlwaysSample()}) te := testExporter{make(chan *trace.SpanData)} trace.RegisterExporter(&te) defer trace.UnregisterExporter(&te) @@ -76,7 +76,7 @@ func TestStreaming(t *testing.T) { } func TestStreamingFail(t *testing.T) { - trace.SetDefaultSampler(trace.AlwaysSample()) + trace.SetConfig(trace.Config{DefaultSampler: trace.AlwaysSample()}) te := testExporter{make(chan *trace.SpanData)} trace.RegisterExporter(&te) defer trace.UnregisterExporter(&te) @@ -117,7 +117,7 @@ func TestStreamingFail(t *testing.T) { } func TestSingle(t *testing.T) { - trace.SetDefaultSampler(trace.AlwaysSample()) + trace.SetConfig(trace.Config{DefaultSampler: trace.AlwaysSample()}) te := testExporter{make(chan *trace.SpanData)} trace.RegisterExporter(&te) defer trace.UnregisterExporter(&te) @@ -150,7 +150,7 @@ func TestServerSpanDuration(t *testing.T) { trace.RegisterExporter(&te) defer trace.UnregisterExporter(&te) - trace.SetDefaultSampler(trace.AlwaysSample()) + trace.SetConfig(trace.Config{DefaultSampler: trace.AlwaysSample()}) ctx := context.Background() const sleep = 100 * time.Millisecond @@ -174,7 +174,7 @@ loop: } func TestSingleFail(t *testing.T) { - trace.SetDefaultSampler(trace.AlwaysSample()) + trace.SetConfig(trace.Config{DefaultSampler: trace.AlwaysSample()}) te := testExporter{make(chan *trace.SpanData)} trace.RegisterExporter(&te) defer trace.UnregisterExporter(&te) diff --git a/plugin/ochttp/propagation_test.go b/plugin/ochttp/propagation_test.go index 8c09efa11..0fcd3d918 100644 --- a/plugin/ochttp/propagation_test.go +++ b/plugin/ochttp/propagation_test.go @@ -36,7 +36,7 @@ func TestRoundTripAllFormats(t *testing.T) { } ctx := context.Background() - trace.SetDefaultSampler(trace.AlwaysSample()) + trace.SetConfig(trace.Config{DefaultSampler: trace.AlwaysSample()}) ctx, span := trace.StartSpan(ctx, "test") sc := span.SpanContext() wantStr := fmt.Sprintf("trace_id=%x, span_id=%x, options=%d", sc.TraceID, sc.SpanID, sc.TraceOptions) diff --git a/plugin/ochttp/trace_test.go b/plugin/ochttp/trace_test.go index cfad50c3c..12d65e0ef 100644 --- a/plugin/ochttp/trace_test.go +++ b/plugin/ochttp/trace_test.go @@ -172,7 +172,7 @@ func (c *collector) ExportSpan(s *trace.SpanData) { } func TestEndToEnd(t *testing.T) { - trace.SetDefaultSampler(trace.AlwaysSample()) + trace.SetConfig(trace.Config{DefaultSampler: trace.AlwaysSample()}) tc := []struct { name string diff --git a/trace/benchmark_test.go b/trace/benchmark_test.go index 8c6cc5abb..e7e5a6ff6 100644 --- a/trace/benchmark_test.go +++ b/trace/benchmark_test.go @@ -94,12 +94,12 @@ func BenchmarkSpanID_DotString(b *testing.B) { func traceBenchmark(b *testing.B, fn func(*testing.B)) { b.Run("AlwaysSample", func(b *testing.B) { b.ReportAllocs() - SetDefaultSampler(AlwaysSample()) + SetConfig(Config{DefaultSampler: AlwaysSample()}) fn(b) }) b.Run("NeverSample", func(b *testing.B) { b.ReportAllocs() - SetDefaultSampler(NeverSample()) + SetConfig(Config{DefaultSampler: NeverSample()}) fn(b) }) } diff --git a/trace/config.go b/trace/config.go new file mode 100644 index 000000000..c1c2dc962 --- /dev/null +++ b/trace/config.go @@ -0,0 +1,36 @@ +// Copyright 2018, OpenCensus Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package trace + +func init() { + config.DefaultSampler = ProbabilitySampler(defaultSamplingProbability) +} + +// Config represents the global tracing configuration. +type Config struct { + // DefaultSampler is the default sampler used when creating new spans. + DefaultSampler Sampler +} + +// SetConfig sets the global tracing configuration. +func SetConfig(cfg Config) { + if cfg.DefaultSampler == nil { + cfg.DefaultSampler = newDefaultSampler() + } + mu.Lock() + // TODO(jbd): Reduce the global contention on config. + config = cfg + mu.Unlock() +} diff --git a/trace/doc.go b/trace/doc.go index 5c94e9d89..ea5693c3a 100644 --- a/trace/doc.go +++ b/trace/doc.go @@ -28,10 +28,10 @@ one of the provided exporters or write your own. trace.RegisterExporter(anExporter) By default, traces will be sampled relatively rarely. To change the sampling -frequency for your entire program, call SetDefaultSampler. Use a ProbabilitySampler +frequency for your entire program, call SetConfig. Use a ProbabilitySampler to sample a subset of traces, or use AlwaysSample to collect a trace on every run: - trace.SetDefaultSampler(trace.AlwaysSample()) + trace.SetConfig(trace.Config{DefaultSampler: trace.AlwaysSample()}) Adding Spans to a Trace diff --git a/trace/sampling.go b/trace/sampling.go index 8ff8db967..97bf9e62c 100644 --- a/trace/sampling.go +++ b/trace/sampling.go @@ -20,22 +20,14 @@ import ( const defaultSamplingProbability = 1e-4 -func init() { - defaultSampler = ProbabilitySampler(defaultSamplingProbability) -} - func newDefaultSampler() Sampler { return ProbabilitySampler(defaultSamplingProbability) } // SetDefaultSampler sets the default sampler used when creating new spans. +// +// Deprecated: Use SetConfig. func SetDefaultSampler(sampler Sampler) { - if sampler == nil { - sampler = newDefaultSampler() - } - mu.Lock() - defaultSampler = sampler - mu.Unlock() } // Sampler decides whether a trace should be sampled and exported. diff --git a/trace/trace.go b/trace/trace.go index 0340b6a83..cb79d957c 100644 --- a/trace/trace.go +++ b/trace/trace.go @@ -114,7 +114,7 @@ type StartOptions struct { // If not provided, then the behavior differs based on whether // the parent of this Span is remote, local, or there is no parent. // In the case of a remote parent or no parent, the - // default sampler (see SetDefaultSampler) will be consulted. Otherwise, + // default sampler (see Config) will be consulted. Otherwise, // when there is a non-remote parent, no new sampling decision will be made: // we will preserve the sampling of the parent. Sampler Sampler @@ -158,11 +158,12 @@ func startSpanInternal(name string, hasParent bool, parent SpanContext, remotePa span := &Span{} span.spanContext = parent mu.Lock() + // TODO(jbd): Reduce the contention. if !hasParent { span.spanContext.TraceID = newTraceIDLocked() } span.spanContext.SpanID = newSpanIDLocked() - sampler := defaultSampler + sampler := config.DefaultSampler mu.Unlock() if !hasParent || remoteParent || o.Sampler != nil { @@ -405,12 +406,12 @@ func (s *Span) String() string { } var ( - mu sync.Mutex // protects the variables below - traceIDRand *rand.Rand - traceIDAdd [2]uint64 - nextSpanID uint64 - spanIDInc uint64 - defaultSampler Sampler + mu sync.Mutex // protects the variables below + traceIDRand *rand.Rand + traceIDAdd [2]uint64 + nextSpanID uint64 + spanIDInc uint64 + config Config ) func init() { diff --git a/trace/trace_test.go b/trace/trace_test.go index 862b2c939..a68c5b1fd 100644 --- a/trace/trace_test.go +++ b/trace/trace_test.go @@ -29,7 +29,7 @@ var ( func init() { // no random sampling, but sample children of sampled spans. - SetDefaultSampler(ProbabilitySampler(0)) + SetConfig(Config{DefaultSampler: ProbabilitySampler(0)}) } func TestStrings(t *testing.T) { @@ -154,7 +154,7 @@ func TestSampling(t *testing.T) { AlwaysSample(), ProbabilitySampler(0), } { - SetDefaultSampler(defaultSampler) + SetConfig(Config{DefaultSampler: defaultSampler}) sampler := NeverSample() if test.parentTraceOptions == 1 { sampler = AlwaysSample() @@ -174,7 +174,7 @@ func TestSampling(t *testing.T) { } } } - SetDefaultSampler(ProbabilitySampler(0)) // reset the default sampler. + SetConfig(Config{DefaultSampler: ProbabilitySampler(0)}) // reset the default sampler. } func TestProbabilitySampler(t *testing.T) {