1package trace
2
3import (
4	"context"
5	"fmt"
6
7	"github.com/pomerium/pomerium/internal/log"
8
9	"contrib.go.opencensus.io/exporter/jaeger"
10	"go.opencensus.io/trace"
11)
12
13const (
14	// JaegerTracingProviderName is the name of the tracing provider Jaeger.
15	JaegerTracingProviderName = "jaeger"
16)
17
18// TracingOptions contains the configurations settings for a http server.
19type TracingOptions struct {
20	// Shared
21	Provider string
22	Service  string
23	Debug    bool
24
25	// Jaeger
26
27	// CollectorEndpoint is the full url to the Jaeger HTTP Thrift collector.
28	// For example, http://localhost:14268/api/traces
29	JaegerCollectorEndpoint string `mapstructure:"tracing_jaeger_collector_endpoint"`
30	// AgentEndpoint instructs exporter to send spans to jaeger-agent at this address.
31	// For example, localhost:6831.
32	JaegerAgentEndpoint string `mapstructure:"tracing_jaeger_agent_endpoint"`
33}
34
35// RegisterTracing creates a new trace exporter from TracingOptions.
36func RegisterTracing(opts *TracingOptions) error {
37	var err error
38	switch opts.Provider {
39	case JaegerTracingProviderName:
40		err = registerJaeger(opts)
41	default:
42		return fmt.Errorf("telemetry/trace: provider %s unknown", opts.Provider)
43	}
44	if err != nil {
45		return err
46	}
47	if opts.Debug {
48		log.Debug().Msg("telemetry/trace: debug on, sample everything")
49		trace.ApplyConfig(trace.Config{DefaultSampler: trace.AlwaysSample()})
50	}
51	log.Debug().Interface("Opts", opts).Msg("telemetry/trace: exporter created")
52	return nil
53}
54
55func registerJaeger(opts *TracingOptions) error {
56	jex, err := jaeger.NewExporter(
57		jaeger.Options{
58			AgentEndpoint:     opts.JaegerAgentEndpoint,
59			CollectorEndpoint: opts.JaegerCollectorEndpoint,
60			ServiceName:       opts.Service,
61		})
62	if err != nil {
63		return err
64	}
65	trace.RegisterExporter(jex)
66	return nil
67}
68
69// StartSpan starts a new child span of the current span in the context. If
70// there is no span in the context, creates a new trace and span.
71//
72// Returned context contains the newly created span. You can use it to
73// propagate the returned span in process.
74func StartSpan(ctx context.Context, name string, o ...trace.StartOption) (context.Context, *trace.Span) {
75	return trace.StartSpan(ctx, name, o...)
76}
77