Skip to content

Commit

Permalink
WIP: Named tracer prototype (#227)
Browse files Browse the repository at this point in the history
* named tracer prototype

* rename Manager to Provider.

* fix compile error after merge.

* rename Tracer method to GetTracer

* provider with options.

* update test.

* cleanup make circl-ci

* remove global config.

* some cleanup.

* use provider for bridge

* update propagation test.

* update examples and plugins.

* remove GlobalTracer methods.

* fix review comments.

* some more cleanup.

* remove unnecessary getTracer call in benchmark test.
  • Loading branch information
rghetia authored Oct 22, 2019
1 parent 9b5f5dd commit b04db14
Show file tree
Hide file tree
Showing 36 changed files with 1,064 additions and 410 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ coverage.*
/example/basic/basic
/example/http/client/client
/example/http/server/server
/example/namedtracer/namedtracer
/experimental/streaming/example/basic/basic
11 changes: 6 additions & 5 deletions api/trace/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@ import (
"go.opentelemetry.io/api/distributedcontext"
)

type Provider interface {
// GetTracer creates a named tracer that implements Tracer interface.
// If the name is an empty string then provider uses default name.
GetTracer(name string) Tracer
}

type Tracer interface {
// Start a span.
Start(context.Context, string, ...SpanOption) (context.Context, Span)
Expand Down Expand Up @@ -137,11 +143,6 @@ type Link struct {
Attributes []core.KeyValue
}

// Start starts a new span using registered global tracer.
func Start(ctx context.Context, name string, opts ...SpanOption) (context.Context, Span) {
return GlobalTracer().Start(ctx, name, opts...)
}

// WithStartTime sets the start time of the span to provided time t, when it is started.
// In absensce of this option, wall clock time is used as start time.
// This option is typically used when starting of the span is delayed.
Expand Down
29 changes: 16 additions & 13 deletions api/trace/global.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,21 +16,24 @@ package trace

import "sync/atomic"

// The process global tracer could have process-wide resource
// tags applied directly, or we can have a SetGlobal tracer to
// install a default tracer w/ resources.
var global atomic.Value
type globalProvider struct {
p Provider
}

var globalP atomic.Value

// GlobalTracer return tracer registered with global registry.
// If no tracer is registered then an instance of noop Tracer is returned.
func GlobalTracer() Tracer {
if t := global.Load(); t != nil {
return t.(Tracer)
// GlobalProvider returns trace provider registered with global registry.
// If no trace provider is registered then an instance of NoopTraceProvider is returned.
// Use the trace provider to create a named tracer. E.g.
// tracer := trace.GlobalProvider().GetTracer("example.com/foo")
func GlobalProvider() Provider {
if gp := globalP.Load(); gp != nil {
return gp.(globalProvider).p
}
return NoopTracer{}
return NoopTraceProvider{}
}

// SetGlobalTracer sets provided tracer as a global tracer.
func SetGlobalTracer(t Tracer) {
global.Store(t)
// SetGlobalProvider sets the provider as a global trace provider.
func SetGlobalProvider(m Provider) {
globalP.Store(globalProvider{p: m})
}
39 changes: 21 additions & 18 deletions sdk/trace/examples_test.go → api/trace/global_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,27 +15,30 @@
package trace_test

import (
"context"
"fmt"
"testing"

"go.opentelemetry.io/api/trace"
)

// This example shows how to use trace.Start and (*Span).End to capture
// a function execution in a Span. It assumes that the function
// has a context.Context argument.
func ExampleStart() {
printEvens := func(ctx context.Context) {
_, span := trace.GlobalTracer().Start(ctx, "my/package.Function")
defer span.End()

for i := 0; i < 10; i++ {
if i%2 == 0 {
fmt.Printf("Even!\n")
}
}
}
type TestProvider1 struct {
}

var _ trace.Provider = &TestProvider1{}

func (tp *TestProvider1) GetTracer(name string) trace.Tracer {
return &trace.NoopTracer{}
}

func TestMulitpleGlobalProvider(t *testing.T) {

ctx := context.Background()
printEvens(ctx)
p1 := TestProvider1{}
p2 := trace.NoopTraceProvider{}
trace.SetGlobalProvider(&p1)
trace.SetGlobalProvider(&p2)

got := trace.GlobalProvider()
want := &p2
if got != want {
t.Fatalf("Provider: got %p, want %p\n", got, want)
}
}
16 changes: 6 additions & 10 deletions api/trace/api_test.go → api/trace/noop_trace_provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,11 @@

package trace

import (
"testing"
)
type NoopTraceProvider struct{}

// GlobalTracer return tracer registered with global registry.
// If no tracer is registered then an instance of noop Tracer is returned.
func TestGlobalTracer(t *testing.T) {
tracer := GlobalTracer()
if tracer == nil {
t.Fatalf("Failed to get tracer\n")
}
var _ Provider = NoopTraceProvider{}

// GetTracer returns noop implementation of Tracer.
func (p NoopTraceProvider) GetTracer(name string) Tracer {
return NoopTracer{}
}
2 changes: 1 addition & 1 deletion example/basic/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import (
)

var (
tracer = trace.GlobalTracer()
tracer = trace.GlobalProvider().GetTracer("ex.com/basic")

meter = metric.GlobalMeter() // TODO: should share resources ^^^?

Expand Down
14 changes: 8 additions & 6 deletions example/http-stackdriver/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,6 @@ import (
)

func initTracer() {
// Register SDK as trace provider.
sdktrace.Register()

projectID := os.Getenv("PROJECT_ID")

// Create Stackdriver exporter to be able to retrieve
Expand All @@ -48,15 +45,20 @@ func initTracer() {
if err != nil {
log.Fatal(err)
}
exporter.RegisterSimpleSpanProcessor()

// For the demonstration, use sdktrace.AlwaysSample sampler to sample all traces.
// In a production application, use sdktrace.ProbabilitySampler with a desired probability.
sdktrace.ApplyConfig(sdktrace.Config{DefaultSampler: sdktrace.AlwaysSample()})
tp, err := sdktrace.NewProvider(sdktrace.WithConfig(sdktrace.Config{DefaultSampler: sdktrace.AlwaysSample()}),
sdktrace.WithSyncer(exporter))
if err != nil {
log.Fatal(err)
}
trace.SetGlobalProvider(tp)
}

func main() {
initTracer()
tr := trace.GlobalProvider().GetTracer("stackdriver/example/client")

client := http.DefaultClient
ctx := distributedcontext.NewContext(context.Background(),
Expand All @@ -65,7 +67,7 @@ func main() {

var body []byte

err := trace.GlobalTracer().WithSpan(ctx, "say hello",
err := tr.WithSpan(ctx, "say hello",
func(ctx context.Context) error {
req, _ := http.NewRequest("GET", "http://localhost:7777/hello", nil)

Expand Down
16 changes: 9 additions & 7 deletions example/http-stackdriver/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,6 @@ import (
)

func initTracer() {
sdktrace.Register()

projectID := os.Getenv("PROJECT_ID")

// Create Stackdriver exporter to be able to retrieve
Expand All @@ -40,26 +38,30 @@ func initTracer() {
if err != nil {
log.Fatal(err)
}
if err := exporter.RegisterBatchSpanProcessor(); err != nil {
log.Fatal(err)
}

// For the demonstration, use sdktrace.AlwaysSample sampler to sample all traces.
// In a production application, use sdktrace.ProbabilitySampler with a desired probability.
sdktrace.ApplyConfig(sdktrace.Config{DefaultSampler: sdktrace.AlwaysSample()})
tp, err := sdktrace.NewProvider(sdktrace.WithConfig(sdktrace.Config{DefaultSampler: sdktrace.AlwaysSample()}),
sdktrace.WithSyncer(exporter))
if err != nil {
log.Fatal(err)
}
trace.SetGlobalProvider(tp)
}

func main() {
initTracer()

tr := trace.GlobalProvider().GetTracer("stackdriver/example/server")

helloHandler := func(w http.ResponseWriter, req *http.Request) {
attrs, entries, spanCtx := httptrace.Extract(req.Context(), req)

req = req.WithContext(distributedcontext.WithMap(req.Context(), distributedcontext.NewMap(distributedcontext.MapUpdate{
MultiKV: entries,
})))

ctx, span := trace.GlobalTracer().Start(
ctx, span := tr.Start(
req.Context(),
"hello",
trace.WithAttributes(attrs...),
Expand Down
13 changes: 8 additions & 5 deletions example/http/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,6 @@ import (
)

func initTracer() {
// Register SDK as trace provider.
sdktrace.Register()

// Create stdout exporter to be able to retrieve
// the collected spans.
exporter, err := stdout.NewExporter(stdout.Options{PrettyPrint: true})
Expand All @@ -47,7 +44,12 @@ func initTracer() {

// For the demonstration, use sdktrace.AlwaysSample sampler to sample all traces.
// In a production application, use sdktrace.ProbabilitySampler with a desired probability.
sdktrace.ApplyConfig(sdktrace.Config{DefaultSampler: sdktrace.AlwaysSample()})
tp, err := sdktrace.NewProvider(sdktrace.WithConfig(sdktrace.Config{DefaultSampler: sdktrace.AlwaysSample()}),
sdktrace.WithSyncer(exporter))
if err != nil {
log.Fatal(err)
}
trace.SetGlobalProvider(tp)
}

func main() {
Expand All @@ -60,7 +62,8 @@ func main() {

var body []byte

err := trace.GlobalTracer().WithSpan(ctx, "say hello",
tr := trace.GlobalProvider().GetTracer("example/client")
err := tr.WithSpan(ctx, "say hello",
func(ctx context.Context) error {
req, _ := http.NewRequest("GET", "http://localhost:7777/hello", nil)

Expand Down
12 changes: 8 additions & 4 deletions example/http/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,6 @@ import (
)

func initTracer() {
sdktrace.Register()

// Create stdout exporter to be able to retrieve
// the collected spans.
exporter, err := stdout.NewExporter(stdout.Options{PrettyPrint: true})
Expand All @@ -39,11 +37,17 @@ func initTracer() {

// For the demonstration, use sdktrace.AlwaysSample sampler to sample all traces.
// In a production application, use sdktrace.ProbabilitySampler with a desired probability.
sdktrace.ApplyConfig(sdktrace.Config{DefaultSampler: sdktrace.AlwaysSample()})
tp, err := sdktrace.NewProvider(sdktrace.WithConfig(sdktrace.Config{DefaultSampler: sdktrace.AlwaysSample()}),
sdktrace.WithSyncer(exporter))
if err != nil {
log.Fatal(err)
}
trace.SetGlobalProvider(tp)
}

func main() {
initTracer()
tr := trace.GlobalProvider().GetTracer("example/server")

helloHandler := func(w http.ResponseWriter, req *http.Request) {
attrs, entries, spanCtx := httptrace.Extract(req.Context(), req)
Expand All @@ -52,7 +56,7 @@ func main() {
MultiKV: entries,
})))

ctx, span := trace.GlobalTracer().Start(
ctx, span := tr.Start(
req.Context(),
"hello",
trace.WithAttributes(attrs...),
Expand Down
46 changes: 46 additions & 0 deletions example/namedtracer/foo/foo.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// Copyright 2019, OpenTelemetry 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 foo

import (
"context"

"go.opentelemetry.io/api/key"
"go.opentelemetry.io/api/trace"
)

var (
lemonsKey = key.New("ex.com/lemons")
)

// SubOperation is an example to demonstrate the use of named tracer.
// It creates a named tracer with its package path.
func SubOperation(ctx context.Context) error {

// Using global provider. Alternative is to have application provide a getter
// for its component to get the instance of the provider.
tr := trace.GlobalProvider().GetTracer("example/namedtracer/foo")
return tr.WithSpan(
ctx,
"Sub operation...",
func(ctx context.Context) error {
trace.CurrentSpan(ctx).SetAttribute(lemonsKey.String("five"))

trace.CurrentSpan(ctx).AddEvent(ctx, "Sub span event")

return nil
},
)
}
7 changes: 7 additions & 0 deletions example/namedtracer/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
module go.opentelemetry.io/example/namedtracer

go 1.12

replace go.opentelemetry.io => ../..

require go.opentelemetry.io v0.0.0-00010101000000-000000000000
Loading

0 comments on commit b04db14

Please sign in to comment.