forked from signalfx/tracing-examples
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.go
138 lines (118 loc) · 4.4 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
// This is a simple program that estimates the value of Pi using Leibniz's
// formula. It uses separate goroutines to calculate sections of the estimate
// and then combines them together in the main goroutine.
package main
import (
"fmt"
"io"
"log"
opentracing "github.com/opentracing/opentracing-go"
jaegercfg "github.com/uber/jaeger-client-go/config"
)
// Constants used by the demo application logic
const (
numParts = 3
partTerms = 100000000
)
func main() {
// Create our tracer. This should only have to be done once per
// application.
tracer, tracerCloser, err := createTracer()
if err != nil {
log.Fatal("Could not create Jaeger tracer", err)
}
// Create an initial span that will trace our application run. We are
// calling it "root" but the name can be anything. StartSpan both creates
// and starts the span.
//
// Here we are using the tracer by an explicit reference to it, but in more
// complex applications it will be must easier to rely on the global tracer
// instance, in which case this line would be:
// parentSpan := opentracing.StartSpan("root")
parentSpan := tracer.StartSpan("root")
// Set a tag on the newly created span. This would be more significant if
// the value were dynamic.
parentSpan.SetTag("totalTerms", numParts*partTerms)
results := make(chan float64)
for i := 0; i < numParts; i++ {
part := i
// Do some work in separate goroutines
go func() {
// This creates a child span of the parent span. The parent span
// must be explicitly given. In more complex applications, the
// parent span can be passed around within a context.Context instance
// (see https://github.com/opentracing/opentracing-go#creating-a-span-given-an-existing-go-contextcontext)
sp := tracer.StartSpan("calculatePart", opentracing.ChildOf(parentSpan.Context()))
// We must always explicitly finish a span.
defer sp.Finish()
// Set a tag to uniquely identify goroutines
sp.SetTag("part", part)
termStart := part * partTerms
results <- calculatePart(termStart, termStart+partTerms)
}()
}
partsRemaining := numParts
var piEstimate float64
for partsRemaining > 0 {
select {
case part := <-results:
piEstimate += part * 4.0
partsRemaining--
}
}
fmt.Printf("pi ~= %#v\n", piEstimate)
// Now that our application is done, we must also close the parent span.
parentSpan.Finish()
// It is important to explicitly close the tracer when the application
// shuts down to prevent spans from being lost.
tracerCloser.Close()
}
// This function is used by the application logic and contains no tracing
// code.
func calculatePart(termStart int, termEnd int) float64 {
var partialSum float64
for k := termStart; k < termEnd; k++ {
numerator := 1.0
if k%2 != 0 {
numerator = -1.0
}
partialSum += numerator / float64(((2 * k) + 1))
}
return partialSum
}
func createTracer() (opentracing.Tracer, io.Closer, error) {
// This creates a configuration struct for Jaeger based on environment
// variables. See https://github.com/jaegertracing/jaeger-client-go/blob/master/README.md#environment-variables
// The rest of this setup expects that JAEGER_ENDPOINT and JAEGER_PASSWORD
// have already been set on the application's environment.
cfg, err := jaegercfg.FromEnv()
if err != nil {
// parsing errors might happen here, such as when we get a string where we expect a number
return nil, nil, err
}
// Here we set a default service name for the tracer for this example. This
// would already be set if you set the JAEGER_SERVICE_NAME env var.
if cfg.ServiceName == "" {
cfg.ServiceName = "signalfx-jaeger-go-example"
}
// Here we are configuring span sampling so that all spans are sampled and
// sent. Our standard deployment model sends all spans from the application
// to the Smart Agent and Gateway.
cfg.Sampler = &jaegercfg.SamplerConfig{
Type: "const",
Param: 1,
}
// This creates the Jaeger tracer from the configuration, using our Thrift
// HTTP transport.
tracer, closer, err := cfg.NewTracer()
if err != nil {
return nil, nil, err
}
// Set the tracer as the global tracer in case you want to start a span
// without having a direct reference to the tracer. The use of the global
// tracer actually appears to be the best-practice in Golang but we show an
// explicit invocation of the tracer in the example above to make it more
// obvious what is going on.
opentracing.SetGlobalTracer(tracer)
return tracer, closer, nil
}