github.com/Jeffail/benthos/v3@v3.65.0/lib/tracer/jaeger.go (about)

     1  package tracer
     2  
     3  import (
     4  	"fmt"
     5  	"io"
     6  	"strings"
     7  	"time"
     8  
     9  	"github.com/Jeffail/benthos/v3/internal/docs"
    10  	"github.com/opentracing/opentracing-go"
    11  	"github.com/uber/jaeger-client-go"
    12  	jaegercfg "github.com/uber/jaeger-client-go/config"
    13  )
    14  
    15  //------------------------------------------------------------------------------
    16  
    17  func init() {
    18  	Constructors[TypeJaeger] = TypeSpec{
    19  		constructor: NewJaeger,
    20  		Summary: `
    21  Send tracing events to a [Jaeger](https://www.jaegertracing.io/) agent or collector.`,
    22  		FieldSpecs: docs.FieldSpecs{
    23  			docs.FieldCommon("agent_address", "The address of a Jaeger agent to send tracing events to.", "jaeger-agent:6831"),
    24  			docs.FieldCommon("collector_url", "The URL of a Jaeger collector to send tracing events to. If set, this will override `agent_address`.",
    25  				"https://jaeger-collector:14268/api/traces").AtVersion("3.38.0"),
    26  			docs.FieldCommon("service_name", "A name to provide for this service."),
    27  			docs.FieldCommon("sampler_type", "The sampler type to use.").HasAnnotatedOptions(
    28  				"const", "A constant decision for all traces, either 1 or 0.",
    29  				"probabilistic", "The sampler makes a random sampling decision with the probability of sampling equal to the value of sampler param.",
    30  				"ratelimiting", "The sampler uses a leaky bucket rate limiter to ensure that traces are sampled with a certain constant rate.",
    31  				"remote", "The sampler consults Jaeger agent for the appropriate sampling strategy to use in the current service.",
    32  			),
    33  			docs.FieldAdvanced("sampler_manager_address", "An optional address of a sampler manager."),
    34  			docs.FieldFloat("sampler_param", "A parameter to use for sampling. This field is unused for some sampling types.").Advanced(),
    35  			docs.FieldString("tags", "A map of tags to add to tracing spans.").Map().Advanced(),
    36  			docs.FieldCommon("flush_interval", "The period of time between each flush of tracing spans."),
    37  		},
    38  	}
    39  }
    40  
    41  //------------------------------------------------------------------------------
    42  
    43  // JaegerConfig is config for the Jaeger metrics type.
    44  type JaegerConfig struct {
    45  	AgentAddress          string            `json:"agent_address" yaml:"agent_address"`
    46  	CollectorURL          string            `json:"collector_url" yaml:"collector_url"`
    47  	ServiceName           string            `json:"service_name" yaml:"service_name"`
    48  	SamplerType           string            `json:"sampler_type" yaml:"sampler_type"`
    49  	SamplerManagerAddress string            `json:"sampler_manager_address" yaml:"sampler_manager_address"`
    50  	SamplerParam          float64           `json:"sampler_param" yaml:"sampler_param"`
    51  	Tags                  map[string]string `json:"tags" yaml:"tags"`
    52  	FlushInterval         string            `json:"flush_interval" yaml:"flush_interval"`
    53  }
    54  
    55  // NewJaegerConfig creates an JaegerConfig struct with default values.
    56  func NewJaegerConfig() JaegerConfig {
    57  	return JaegerConfig{
    58  		AgentAddress:          "localhost:6831",
    59  		ServiceName:           "benthos",
    60  		SamplerType:           "const",
    61  		SamplerManagerAddress: "",
    62  		SamplerParam:          1.0,
    63  		Tags:                  map[string]string{},
    64  		FlushInterval:         "",
    65  	}
    66  }
    67  
    68  //------------------------------------------------------------------------------
    69  
    70  // Jaeger is a tracer with the capability to push spans to a Jaeger instance.
    71  type Jaeger struct {
    72  	closer io.Closer
    73  }
    74  
    75  // NewJaeger creates and returns a new Jaeger object.
    76  func NewJaeger(config Config, opts ...func(Type)) (Type, error) {
    77  	j := &Jaeger{}
    78  
    79  	for _, opt := range opts {
    80  		opt(j)
    81  	}
    82  
    83  	var sampler *jaegercfg.SamplerConfig
    84  	if sType := config.Jaeger.SamplerType; len(sType) > 0 {
    85  		sampler = &jaegercfg.SamplerConfig{
    86  			Param:             config.Jaeger.SamplerParam,
    87  			SamplingServerURL: config.Jaeger.SamplerManagerAddress,
    88  		}
    89  		switch strings.ToLower(sType) {
    90  		case "const":
    91  			sampler.Type = jaeger.SamplerTypeConst
    92  		case "probabilistic":
    93  			sampler.Type = jaeger.SamplerTypeProbabilistic
    94  		case "ratelimiting":
    95  			sampler.Type = jaeger.SamplerTypeRateLimiting
    96  		case "remote":
    97  			sampler.Type = jaeger.SamplerTypeRemote
    98  		default:
    99  			return nil, fmt.Errorf("unrecognised sampler type: %v", sType)
   100  		}
   101  	}
   102  
   103  	cfg := jaegercfg.Configuration{
   104  		ServiceName: config.Jaeger.ServiceName,
   105  		Sampler:     sampler,
   106  	}
   107  
   108  	if tags := config.Jaeger.Tags; len(tags) > 0 {
   109  		var jTags []opentracing.Tag
   110  		for k, v := range config.Jaeger.Tags {
   111  			jTags = append(jTags, opentracing.Tag{
   112  				Key:   k,
   113  				Value: v,
   114  			})
   115  		}
   116  		cfg.Tags = jTags
   117  	}
   118  
   119  	reporterConf := &jaegercfg.ReporterConfig{}
   120  
   121  	if i := config.Jaeger.FlushInterval; len(i) > 0 {
   122  		flushInterval, err := time.ParseDuration(i)
   123  		if err != nil {
   124  			return nil, fmt.Errorf("failed to parse flush interval '%s': %v", i, err)
   125  		}
   126  		reporterConf.BufferFlushInterval = flushInterval
   127  		cfg.Reporter = reporterConf
   128  	}
   129  
   130  	if i := config.Jaeger.AgentAddress; len(i) > 0 {
   131  		reporterConf.LocalAgentHostPort = i
   132  		cfg.Reporter = reporterConf
   133  	}
   134  
   135  	if i := config.Jaeger.CollectorURL; len(i) > 0 {
   136  		reporterConf.CollectorEndpoint = i
   137  	}
   138  
   139  	tracer, closer, err := cfg.NewTracer()
   140  	if err != nil {
   141  		return nil, err
   142  	}
   143  	opentracing.SetGlobalTracer(tracer)
   144  	j.closer = closer
   145  
   146  	return j, nil
   147  }
   148  
   149  //------------------------------------------------------------------------------
   150  
   151  // Close stops the tracer.
   152  func (j *Jaeger) Close() error {
   153  	if j.closer != nil {
   154  		j.closer.Close()
   155  		j.closer = nil
   156  	}
   157  	return nil
   158  }
   159  
   160  //------------------------------------------------------------------------------