2018-05-22 21:43:36 +02:00
|
|
|
// Copyright 2016-2018, Pulumi Corporation.
|
|
|
|
//
|
|
|
|
// 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.
|
|
|
|
|
2017-11-09 02:08:51 +01:00
|
|
|
package cmdutil
|
|
|
|
|
|
|
|
import (
|
|
|
|
"io"
|
|
|
|
"log"
|
2019-09-16 23:16:43 +02:00
|
|
|
"net/url"
|
|
|
|
"os"
|
2017-11-09 02:08:51 +01:00
|
|
|
|
|
|
|
opentracing "github.com/opentracing/opentracing-go"
|
|
|
|
"github.com/pulumi/pulumi/pkg/util/contract"
|
|
|
|
jaeger "github.com/uber/jaeger-client-go"
|
|
|
|
"github.com/uber/jaeger-client-go/transport/zipkin"
|
2019-09-16 23:16:43 +02:00
|
|
|
"sourcegraph.com/sourcegraph/appdash"
|
|
|
|
appdash_opentracing "sourcegraph.com/sourcegraph/appdash/opentracing"
|
2017-11-09 02:08:51 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
// TracingEndpoint is the Zipkin-compatible tracing endpoint where tracing data will be sent.
|
|
|
|
var TracingEndpoint string
|
2019-09-16 23:16:43 +02:00
|
|
|
var TracingToFile bool
|
2018-05-08 03:23:03 +02:00
|
|
|
var TracingRootSpan opentracing.Span
|
2017-11-09 02:08:51 +01:00
|
|
|
|
|
|
|
var traceCloser io.Closer
|
|
|
|
|
2019-09-16 23:16:43 +02:00
|
|
|
type localStore struct {
|
|
|
|
path string
|
|
|
|
store *appdash.MemoryStore
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *localStore) Close() error {
|
|
|
|
f, err := os.Create(s.path)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
defer contract.IgnoreClose(f)
|
|
|
|
return s.store.Write(f)
|
|
|
|
}
|
|
|
|
|
2018-05-07 20:49:15 +02:00
|
|
|
func IsTracingEnabled() bool {
|
|
|
|
return TracingEndpoint != ""
|
|
|
|
}
|
|
|
|
|
2017-11-09 02:08:51 +01:00
|
|
|
// InitTracing initializes tracing
|
2018-05-08 03:23:03 +02:00
|
|
|
func InitTracing(name, rootSpanName, tracingEndpoint string) {
|
2018-05-08 05:17:19 +02:00
|
|
|
// If no tracing endpoint was provided, just return. The default global tracer is already a no-op tracer.
|
|
|
|
if tracingEndpoint == "" {
|
|
|
|
return
|
|
|
|
}
|
2017-11-09 02:08:51 +01:00
|
|
|
|
|
|
|
// Store the tracing endpoint
|
|
|
|
TracingEndpoint = tracingEndpoint
|
|
|
|
|
2019-09-16 23:16:43 +02:00
|
|
|
endpointURL, err := url.Parse(tracingEndpoint)
|
2018-05-08 05:17:19 +02:00
|
|
|
if err != nil {
|
2019-09-16 23:16:43 +02:00
|
|
|
log.Fatalf("invalid tracing endpoint: %v", err)
|
2017-11-09 02:08:51 +01:00
|
|
|
}
|
|
|
|
|
2019-09-16 23:16:43 +02:00
|
|
|
var tracer opentracing.Tracer
|
|
|
|
switch {
|
|
|
|
case endpointURL.Scheme == "file":
|
|
|
|
// If the endpoint is a file:// URL, use a local tracer.
|
|
|
|
TracingToFile = true
|
|
|
|
|
|
|
|
path := endpointURL.Path
|
|
|
|
if path == "" {
|
|
|
|
path = endpointURL.Opaque
|
|
|
|
}
|
|
|
|
if path == "" {
|
|
|
|
log.Fatalf("invalid tracing endpoint: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
store := &localStore{
|
|
|
|
path: path,
|
|
|
|
store: appdash.NewMemoryStore(),
|
|
|
|
}
|
|
|
|
traceCloser = store
|
|
|
|
|
|
|
|
collector := appdash.NewLocalCollector(store.store)
|
|
|
|
tracer = appdash_opentracing.NewTracer(collector)
|
|
|
|
case endpointURL.Scheme == "tcp":
|
|
|
|
// If the endpoint scheme is tcp, use an Appdash endpoint.
|
|
|
|
collector := appdash.NewRemoteCollector(tracingEndpoint)
|
|
|
|
traceCloser = collector
|
|
|
|
tracer = appdash_opentracing.NewTracer(collector)
|
|
|
|
default:
|
|
|
|
// Jaeger tracer can be initialized with a transport that will
|
|
|
|
// report tracing Spans to a Zipkin backend
|
|
|
|
transport, err := zipkin.NewHTTPTransport(
|
|
|
|
tracingEndpoint,
|
|
|
|
zipkin.HTTPBatchSize(1),
|
|
|
|
zipkin.HTTPLogger(jaeger.StdLogger),
|
|
|
|
)
|
|
|
|
if err != nil {
|
|
|
|
log.Fatalf("Cannot initialize HTTP transport: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// create Jaeger tracer
|
|
|
|
t, closer := jaeger.NewTracer(
|
|
|
|
name,
|
|
|
|
jaeger.NewConstSampler(true), // sample all traces
|
|
|
|
jaeger.NewRemoteReporter(transport))
|
|
|
|
|
|
|
|
tracer, traceCloser = t, closer
|
|
|
|
}
|
2017-11-09 02:08:51 +01:00
|
|
|
|
|
|
|
// Set the ambient tracer
|
|
|
|
opentracing.SetGlobalTracer(tracer)
|
2018-05-08 03:23:03 +02:00
|
|
|
|
|
|
|
// If a root span was requested, start it now.
|
|
|
|
if rootSpanName != "" {
|
|
|
|
TracingRootSpan = tracer.StartSpan(rootSpanName)
|
|
|
|
}
|
2017-11-09 02:08:51 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// CloseTracing ensures that all pending spans have been flushed. It should be called before process exit.
|
|
|
|
func CloseTracing() {
|
2018-05-07 20:49:15 +02:00
|
|
|
if !IsTracingEnabled() {
|
2018-05-08 05:17:19 +02:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2018-05-08 03:23:03 +02:00
|
|
|
if TracingRootSpan != nil {
|
|
|
|
TracingRootSpan.Finish()
|
|
|
|
}
|
|
|
|
|
2017-11-09 02:08:51 +01:00
|
|
|
contract.IgnoreClose(traceCloser)
|
|
|
|
}
|