Newer
Older
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
package tracing
import (
"encoding/json"
"errors"
"io/ioutil"
"log"
"net/http"
"os"
"path/filepath"
"sync"
openzipkin "github.com/openzipkin/zipkin-go"
zipkinHTTP "github.com/openzipkin/zipkin-go/reporter/http"
"go.opencensus.io/exporter/zipkin"
"go.opencensus.io/plugin/ochttp"
"go.opencensus.io/trace"
)
var (
// Enabled reports whether tracing is globally enabled or not.
Enabled bool
// The active tracing configuration, if Enabled is true.
config tracingConfig
initOnce sync.Once
)
const globalTracingConfigPath = "/etc/tracing/client.conf"
type tracingConfig struct {
ReportURL string `json:"report_url"`
}
// Read the global tracing configuration file. Its location is
// hardcoded, but it can be overriden using the TRACING_CONFIG
// environment variable.
func readTracingConfig() error {
// Read and decode configuration.
cfgPath := globalTracingConfigPath
if s := os.Getenv("TRACING_CONFIG"); s != "" {
cfgPath = s
}
data, err := ioutil.ReadFile(cfgPath)
if err != nil {
return err
}
if err := json.Unmarshal(data, &config); err != nil {
log.Printf("warning: error in tracing configuration: %v, tracing disabled", err)
return err
}
if config.ReportURL == "" {
log.Printf("warning: tracing configuration contains no report_url, tracing disabled")
return errors.New("no report_url")
}
return nil
}
// Compute the service name for Zipkin: this is usually the program
// name (without path), but it can be overriden by the TRACING_SERVICE
// environment variable.
func getServiceName() string {
if s := os.Getenv("TRACING_SERVICE"); s != "" {
return s
}
return filepath.Base(os.Args[0])
}
// Initialize tracing. Tracing will be enabled if the system-wide
// tracing configuration file is present and valid. Explicitly set
// TRACING_ENABLE=0 in the environment to disable tracing.
//
// We need to check the configuration as soon as possible, because
// it's likely that client transports are created before HTTP servers,
// and we need to wrap them with opencensus at creation time.
func init() {
// Kill switch from environment.
if s := os.Getenv("TRACING_ENABLE"); s == "0" {
return
}
if err := readTracingConfig(); err != nil {
return
}
Enabled = true
}
func initTracing(endpointAddr string) {
initOnce.Do(func() {
localEndpoint, err := openzipkin.NewEndpoint(getServiceName(), endpointAddr)
if err != nil {
log.Printf("warning: error creating tracing endpoint: %v, tracing disabled", err)
return
}
reporter := zipkinHTTP.NewReporter(config.ReportURL)
ze := zipkin.NewExporter(reporter, localEndpoint)
trace.RegisterExporter(ze)
trace.ApplyConfig(trace.Config{DefaultSampler: trace.AlwaysSample()})
log.Printf("tracing enabled (report_url %s)", config.ReportURL)
Enabled = true
})
}
// WrapTransport optionally wraps a http.RoundTripper with OpenCensus
// tracing functionality, if it is globally enabled.
func WrapTransport(t http.RoundTripper) http.RoundTripper {
if Enabled {
t = &ochttp.Transport{Base: t}
}
return t
}
// WrapHandler wraps a http.Handler with OpenCensus tracing
// functionality, if globally enabled.
func WrapHandler(h http.Handler, endpointAddr string) http.Handler {
if Enabled {
initTracing(endpointAddr)
h = &ochttp.Handler{Handler: h}
}
return h
}