2020-05-23 17:43:57 +02:00
|
|
|
package serv
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"net/http"
|
|
|
|
"strconv"
|
|
|
|
"sync"
|
|
|
|
|
|
|
|
"contrib.go.opencensus.io/exporter/aws"
|
|
|
|
"contrib.go.opencensus.io/exporter/prometheus"
|
|
|
|
"contrib.go.opencensus.io/exporter/stackdriver"
|
|
|
|
|
|
|
|
"contrib.go.opencensus.io/exporter/zipkin"
|
|
|
|
"contrib.go.opencensus.io/integrations/ocsql"
|
|
|
|
stdzipkin "github.com/openzipkin/zipkin-go"
|
|
|
|
httpreporter "github.com/openzipkin/zipkin-go/reporter/http"
|
|
|
|
"go.opencensus.io/stats/view"
|
|
|
|
"go.opencensus.io/trace"
|
|
|
|
"go.opencensus.io/zpages"
|
|
|
|
)
|
|
|
|
|
|
|
|
func enableObservability(mux *http.ServeMux) (func(), error) {
|
|
|
|
// Enable OpenCensus zPages
|
|
|
|
if conf.Telemetry.Debug {
|
|
|
|
zpages.Handle(mux, "/telemetry")
|
|
|
|
}
|
|
|
|
|
|
|
|
// Enable ocsql metrics with OpenCensus
|
|
|
|
ocsql.RegisterAllViews()
|
|
|
|
|
|
|
|
var mex view.Exporter
|
|
|
|
var tex trace.Exporter
|
|
|
|
|
|
|
|
var mCloseFn, tCloseFn func()
|
|
|
|
var err error
|
|
|
|
|
|
|
|
// Set up the metrics exporter
|
|
|
|
switch conf.Telemetry.Metrics.Exporter {
|
|
|
|
case "prometheus":
|
|
|
|
ep := "/metrics"
|
|
|
|
|
|
|
|
if conf.Telemetry.Metrics.Endpoint != "" {
|
|
|
|
ep = conf.Telemetry.Metrics.Endpoint
|
|
|
|
}
|
|
|
|
|
|
|
|
ex, err1 := prometheus.NewExporter(prometheus.Options{Namespace: conf.Telemetry.Metrics.Namespace})
|
|
|
|
if err == nil {
|
|
|
|
mux.Handle(ep, ex)
|
|
|
|
log.Printf("INF Prometheus exporter listening on: %s", ep)
|
|
|
|
}
|
|
|
|
mex, err = view.Exporter(ex), err1
|
|
|
|
|
|
|
|
case "stackdriver":
|
|
|
|
mex, err = stackdriver.NewExporter(stackdriver.Options{ProjectID: conf.Telemetry.Metrics.Key})
|
|
|
|
if err == nil {
|
|
|
|
log.Println("INF Google Stackdriver exporter initialized")
|
|
|
|
}
|
|
|
|
|
|
|
|
case "":
|
2020-05-23 22:37:15 +02:00
|
|
|
log.Println("WRN OpenCensus: no metrics exporter defined")
|
2020-05-23 17:43:57 +02:00
|
|
|
|
|
|
|
default:
|
|
|
|
err = fmt.Errorf("invalid metrics exporter")
|
|
|
|
}
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("ERR OpenCensus: %s: %v", conf.Telemetry.Metrics, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if mex != nil {
|
|
|
|
// Register the exporter
|
|
|
|
view.RegisterExporter(mex)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set up the tracing exporter
|
|
|
|
switch conf.Telemetry.Tracing.Exporter {
|
|
|
|
case "xray", "aws":
|
|
|
|
ex, err1 := aws.NewExporter(aws.WithVersion("latest"))
|
|
|
|
if err == nil {
|
|
|
|
tCloseFn = func() { ex.Flush() }
|
|
|
|
log.Println("INF Amazon X-Ray exporter initialized")
|
|
|
|
}
|
|
|
|
tex, err = trace.Exporter(ex), err1
|
|
|
|
|
|
|
|
case "zipkin":
|
|
|
|
// The local endpoint stores the name and address of the local service
|
|
|
|
lep, err := stdzipkin.NewEndpoint(conf.AppName, conf.hostPort)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
// The Zipkin reporter takes collected spans from the app and reports them to the backend
|
|
|
|
// http://localhost:9411/api/v2/spans is the default for the Zipkin Span v2
|
|
|
|
re := httpreporter.NewReporter(conf.Telemetry.Tracing.Endpoint)
|
|
|
|
tCloseFn = func() { re.Close() }
|
|
|
|
tex = zipkin.NewExporter(re, lep)
|
|
|
|
|
|
|
|
case "":
|
2020-05-23 22:37:15 +02:00
|
|
|
log.Println("WRN OpenCensus: no traceing exporter defined")
|
2020-05-23 17:43:57 +02:00
|
|
|
|
|
|
|
default:
|
|
|
|
err = fmt.Errorf("invalid tracing exporter")
|
|
|
|
}
|
|
|
|
|
|
|
|
if err != nil {
|
2020-05-24 08:24:24 +02:00
|
|
|
return nil, fmt.Errorf("ERR OpenCensus: %s: %v",
|
|
|
|
conf.Telemetry.Tracing.Exporter,
|
|
|
|
err)
|
2020-05-23 17:43:57 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if tex != nil {
|
|
|
|
trace.RegisterExporter(tex)
|
|
|
|
sample := conf.Telemetry.Tracing.Sample
|
|
|
|
|
|
|
|
if sample == "always" {
|
|
|
|
trace.ApplyConfig(trace.Config{DefaultSampler: trace.AlwaysSample()})
|
|
|
|
|
|
|
|
} else {
|
|
|
|
prob := 0.5
|
|
|
|
if v, err := strconv.ParseFloat(sample, 10); err == nil {
|
|
|
|
prob = v
|
|
|
|
}
|
|
|
|
trace.ApplyConfig(trace.Config{DefaultSampler: trace.ProbabilitySampler(prob)})
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
var closeOnce sync.Once
|
|
|
|
|
|
|
|
return func() {
|
|
|
|
// Flush and shutdown the Zipkin HTTP reporter
|
|
|
|
closeOnce.Do(func() {
|
|
|
|
if mCloseFn != nil {
|
|
|
|
mCloseFn()
|
|
|
|
}
|
|
|
|
if tCloseFn != nil {
|
|
|
|
tCloseFn()
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}, err
|
|
|
|
}
|