From b255cfa987c1c9b7fab46d5dd1c6f23d889bc1e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juraci=20Paix=C3=A3o=20Kr=C3=B6hling?= Date: Tue, 27 Mar 2018 15:58:53 +0200 Subject: [PATCH] Added support for client configuration via env vars MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds support for configuring the tracer based on environment variables, similar to what is currently supported by the Java client. Closes #206 Signed-off-by: Juraci Paixão Kröhling --- README.md | 22 +++++ config/config.go | 56 +++++++++-- config/config_env.go | 205 +++++++++++++++++++++++++++++++++++++++++ config/config_test.go | 193 ++++++++++++++++++++++++++++++++++++++ config/example_test.go | 44 +++++++++ constants.go | 6 ++ transport_udp.go | 5 +- 7 files changed, 520 insertions(+), 11 deletions(-) create mode 100644 config/config_env.go diff --git a/README.md b/README.md index 3d232d08..ef6f1646 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,28 @@ make install See tracer initialization examples in [godoc](https://godoc.org/github.com/uber/jaeger-client-go/config#pkg-examples) and [config/example_test.go](./config/example_test.go). +### Environment variables + +The tracer can be initialized with values coming from environment variables. None of the env vars are required +and all of them can be overriden via direct setting of the property on the configuration object. + +Property| Description +--- | --- +JAEGER_SERVICE_NAME | The service name +JAEGER_AGENT_HOST | The hostname for communicating with agent via UDP +JAEGER_AGENT_PORT | The port for communicating with agent via UDP +JAEGER_REPORTER_LOG_SPANS | Whether the reporter should also log the spans +JAEGER_REPORTER_MAX_QUEUE_SIZE | The reporter's maximum queue size +JAEGER_REPORTER_FLUSH_INTERVAL | The reporter's flush interval (ms) +JAEGER_SAMPLER_TYPE | The sampler type +JAEGER_SAMPLER_PARAM | The sampler parameter (number) +JAEGER_SAMPLER_MANAGER_HOST_PORT | The host name and port when using the remote controlled sampler +JAEGER_SAMPLER_MAX_OPERATIONS | The maximum number of operations that the sampler will keep track of +JAEGER_SAMPLER_REFRESH_INTERVAL | How often the remotely controlled sampler will poll jaeger-agent for the appropriate sampling strategy +JAEGER_TAGS | A comma separated list of `name = value` tracer level tags, which get added to all reported spans. The value can also refer to an environment variable using the format `${envVarName:default}`, where the `:default` is optional, and identifies a value to be used if the environment variable cannot be found +JAEGER_DISABLED | Whether the tracer is disabled or not. If true, the default `opentracing.NoopTracer` is used. +JAEGER_RPC_METRICS | Whether to store RPC metrics + ### Closing the tracer via `io.Closer` The constructor function for Jaeger Tracer returns the tracer itself and an `io.Closer` instance. diff --git a/config/config.go b/config/config.go index 3ff21384..ec65dff0 100644 --- a/config/config.go +++ b/config/config.go @@ -32,17 +32,29 @@ const defaultSamplingProbability = 0.001 // Configuration configures and creates Jaeger Tracer type Configuration struct { - Disabled bool `yaml:"disabled"` + // ServiceName specifies the service name to use on the tracer. + // Can be provided via environment variable named JAEGER_SERVICE_NAME + ServiceName string `yaml:"serviceName"` + + // Disabled can be provided via environment variable named JAEGER_DISABLED + Disabled bool `yaml:"disabled"` + + // RPCMetrics can be provided via environment variable named JAEGER_RPC_METRICS + RPCMetrics bool `yaml:"rpc_metrics"` + + // Tags can be provided via environment variable named JAEGER_TAGS + Tags []opentracing.Tag `yaml:"tags"` + Sampler *SamplerConfig `yaml:"sampler"` Reporter *ReporterConfig `yaml:"reporter"` Headers *jaeger.HeadersConfig `yaml:"headers"` - RPCMetrics bool `yaml:"rpc_metrics"` BaggageRestrictions *BaggageRestrictionsConfig `yaml:"baggage_restrictions"` } // SamplerConfig allows initializing a non-default sampler. All fields are optional. type SamplerConfig struct { // Type specifies the type of the sampler: const, probabilistic, rateLimiting, or remote + // Can be set by exporting an environment variable named JAEGER_SAMPLER_TYPE Type string `yaml:"type"` // Param is a value passed to the sampler. @@ -52,19 +64,23 @@ type SamplerConfig struct { // - for "rateLimiting" sampler, the number of spans per second // - for "remote" sampler, param is the same as for "probabilistic" // and indicates the initial sampling rate before the actual one - // is received from the mothership + // is received from the mothership. + // Can be set by exporting an environment variable named JAEGER_SAMPLER_PARAM Param float64 `yaml:"param"` // SamplingServerURL is the address of jaeger-agent's HTTP sampling server + // Can be set by exporting an environment variable named JAEGER_SAMPLER_MANAGER_HOST_PORT SamplingServerURL string `yaml:"samplingServerURL"` // MaxOperations is the maximum number of operations that the sampler // will keep track of. If an operation is not tracked, a default probabilistic // sampler will be used rather than the per operation specific sampler. + // Can be set by exporting an environment variable named JAEGER_SAMPLER_MAX_OPERATIONS MaxOperations int `yaml:"maxOperations"` // SamplingRefreshInterval controls how often the remotely controlled sampler will poll // jaeger-agent for the appropriate sampling strategy. + // Can be set by exporting an environment variable named JAEGER_SAMPLER_REFRESH_INTERVAL SamplingRefreshInterval time.Duration `yaml:"samplingRefreshInterval"` } @@ -73,18 +89,22 @@ type ReporterConfig struct { // QueueSize controls how many spans the reporter can keep in memory before it starts dropping // new spans. The queue is continuously drained by a background go-routine, as fast as spans // can be sent out of process. + // Can be set by exporting an environment variable named JAEGER_REPORTER_MAX_QUEUE_SIZE QueueSize int `yaml:"queueSize"` // BufferFlushInterval controls how often the buffer is force-flushed, even if it's not full. // It is generally not useful, as it only matters for very low traffic services. + // Can be set by exporting an environment variable named JAEGER_REPORTER_FLUSH_INTERVAL BufferFlushInterval time.Duration // LogSpans, when true, enables LoggingReporter that runs in parallel with the main reporter // and logs all submitted spans. Main Configuration.Logger must be initialized in the code // for this option to have any effect. + // Can be set by exporting an environment variable named JAEGER_REPORTER_LOG_SPANS LogSpans bool `yaml:"logSpans"` // LocalAgentHostPort instructs reporter to send spans to jaeger-agent at this address + // Can be set by exporting an environment variable named JAEGER_AGENT_HOST / JAEGER_AGENT_PORT LocalAgentHostPort string `yaml:"localAgentHostPort"` } @@ -111,13 +131,29 @@ func (*nullCloser) Close() error { return nil } // New creates a new Jaeger Tracer, and a closer func that can be used to flush buffers // before shutdown. +// Deprecated: use NewTracer() function func (c Configuration) New( serviceName string, options ...Option, ) (opentracing.Tracer, io.Closer, error) { - if serviceName == "" { + if serviceName == "" && c.ServiceName == "" { return nil, nil, errors.New("no service name provided") } + + if serviceName != "" { + c.ServiceName = serviceName + } + + return c.NewTracer(options...) +} + +// NewTracer returns a new tracer based on the current configuration, using the given options, +// and a closer func that can be used to flush buffers before shutdown. +func (c *Configuration) NewTracer(options ...Option) (opentracing.Tracer, io.Closer, error) { + if c.ServiceName == "" { + return nil, nil, errors.New("no service name provided") + } + if c.Disabled { return &opentracing.NoopTracer{}, &nullCloser{}, nil } @@ -143,7 +179,7 @@ func (c Configuration) New( sampler := opts.sampler if sampler == nil { - s, err := c.Sampler.NewSampler(serviceName, tracerMetrics) + s, err := c.Sampler.NewSampler(c.ServiceName, tracerMetrics) if err != nil { return nil, nil, err } @@ -152,7 +188,7 @@ func (c Configuration) New( reporter := opts.reporter if reporter == nil { - r, err := c.Reporter.NewReporter(serviceName, tracerMetrics, opts.logger) + r, err := c.Reporter.NewReporter(c.ServiceName, tracerMetrics, opts.logger) if err != nil { return nil, nil, err } @@ -171,6 +207,10 @@ func (c Configuration) New( tracerOptions = append(tracerOptions, jaeger.TracerOptions.Tag(tag.Key, tag.Value)) } + for _, tag := range c.Tags { + tracerOptions = append(tracerOptions, jaeger.TracerOptions.Tag(tag.Key, tag.Value)) + } + for _, obs := range opts.observers { tracerOptions = append(tracerOptions, jaeger.TracerOptions.Observer(obs)) } @@ -189,7 +229,7 @@ func (c Configuration) New( if c.BaggageRestrictions != nil { mgr := remote.NewRestrictionManager( - serviceName, + c.ServiceName, remote.Options.Metrics(tracerMetrics), remote.Options.Logger(opts.logger), remote.Options.HostPort(c.BaggageRestrictions.HostPort), @@ -202,7 +242,7 @@ func (c Configuration) New( } tracer, closer := jaeger.NewTracer( - serviceName, + c.ServiceName, sampler, reporter, tracerOptions..., diff --git a/config/config_env.go b/config/config_env.go new file mode 100644 index 00000000..96f170c5 --- /dev/null +++ b/config/config_env.go @@ -0,0 +1,205 @@ +// Copyright (c) 2018 The Jaeger Authors. +// +// 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. + +package config + +import ( + "fmt" + "os" + "strconv" + "strings" + "time" + + opentracing "github.com/opentracing/opentracing-go" + "github.com/pkg/errors" + + "github.com/uber/jaeger-client-go" +) + +const ( + // environment variable names + envServiceName = "JAEGER_SERVICE_NAME" + envDisabled = "JAEGER_DISABLED" + envRPCMetrics = "JAEGER_RPC_METRICS" + envTags = "JAEGER_TAGS" + envSamplerType = "JAEGER_SAMPLER_TYPE" + envSamplerParam = "JAEGER_SAMPLER_PARAM" + envSamplerManagerHostPort = "JAEGER_SAMPLER_MANAGER_HOST_PORT" + envSamplerMaxOperations = "JAEGER_SAMPLER_MAX_OPERATIONS" + envSamplerRefreshInterval = "JAEGER_SAMPLER_REFRESH_INTERVAL" + envReporterMaxQueueSize = "JAEGER_REPORTER_MAX_QUEUE_SIZE" + envReporterFlushInterval = "JAEGER_REPORTER_FLUSH_INTERVAL" + envReporterLogSpans = "JAEGER_REPORTER_LOG_SPANS" + envAgentHost = "JAEGER_AGENT_HOST" + envAgentPort = "JAEGER_AGENT_PORT" +) + +// FromEnv uses environment variables to set the tracer's Configuration +func FromEnv() (*Configuration, error) { + c := &Configuration{} + + if e := os.Getenv(envServiceName); e != "" { + c.ServiceName = e + } + + if e := os.Getenv(envRPCMetrics); e != "" { + if value, err := strconv.ParseBool(e); err == nil { + c.RPCMetrics = value + } else { + return nil, errors.Wrapf(err, "cannot parse env var %s=%s", envRPCMetrics, e) + } + } + + if e := os.Getenv(envDisabled); e != "" { + if value, err := strconv.ParseBool(e); err == nil { + c.Disabled = value + } else { + return nil, errors.Wrapf(err, "cannot parse env var %s=%s", envDisabled, e) + } + } + + if e := os.Getenv(envTags); e != "" { + c.Tags = parseTags(e) + } + + if s, err := samplerConfigFromEnv(); err == nil { + c.Sampler = s + } else { + return nil, errors.Wrap(err, "cannot obtain sampler config from env") + } + + if r, err := reporterConfigFromEnv(); err == nil { + c.Reporter = r + } else { + return nil, errors.Wrap(err, "cannot obtain reporter config from env") + } + + return c, nil +} + +// samplerConfigFromEnv creates a new SamplerConfig based on the environment variables +func samplerConfigFromEnv() (*SamplerConfig, error) { + sc := &SamplerConfig{} + + if e := os.Getenv(envSamplerType); e != "" { + sc.Type = e + } + + if e := os.Getenv(envSamplerParam); e != "" { + if value, err := strconv.ParseFloat(e, 64); err == nil { + sc.Param = value + } else { + return nil, errors.Wrapf(err, "cannot parse env var %s=%s", envSamplerParam, e) + } + } + + if e := os.Getenv(envSamplerManagerHostPort); e != "" { + sc.SamplingServerURL = e + } + + if e := os.Getenv(envSamplerMaxOperations); e != "" { + if value, err := strconv.ParseInt(e, 10, 0); err == nil { + sc.MaxOperations = int(value) + } else { + return nil, errors.Wrapf(err, "cannot parse env var %s=%s", envSamplerMaxOperations, e) + } + } + + if e := os.Getenv(envSamplerRefreshInterval); e != "" { + if value, err := time.ParseDuration(e); err == nil { + sc.SamplingRefreshInterval = value + } else { + return nil, errors.Wrapf(err, "cannot parse env var %s=%s", envSamplerRefreshInterval, e) + } + } + + return sc, nil +} + +// reporterConfigFromEnv creates a new ReporterConfig based on the environment variables +func reporterConfigFromEnv() (*ReporterConfig, error) { + rc := &ReporterConfig{} + + if e := os.Getenv(envReporterMaxQueueSize); e != "" { + if value, err := strconv.ParseInt(e, 10, 0); err == nil { + rc.QueueSize = int(value) + } else { + return nil, errors.Wrapf(err, "cannot parse env var %s=%s", envReporterMaxQueueSize, e) + } + } + + if e := os.Getenv(envReporterFlushInterval); e != "" { + if value, err := time.ParseDuration(e); err == nil { + rc.BufferFlushInterval = value + } else { + return nil, errors.Wrapf(err, "cannot parse env var %s=%s", envReporterFlushInterval, e) + } + } + + if e := os.Getenv(envReporterLogSpans); e != "" { + if value, err := strconv.ParseBool(e); err == nil { + rc.LogSpans = value + } else { + return nil, errors.Wrapf(err, "cannot parse env var %s=%s", envReporterLogSpans, e) + } + } + + host := jaeger.DefaultUDPSpanServerHost + if e := os.Getenv(envAgentHost); e != "" { + host = e + } + + port := jaeger.DefaultUDPSpanServerPort + if e := os.Getenv(envAgentPort); e != "" { + if value, err := strconv.ParseInt(e, 10, 0); err == nil { + port = int(value) + } else { + return nil, errors.Wrapf(err, "cannot parse env var %s=%s", envAgentPort, e) + } + } + + // the side effect of this is that we are building the default value, even if none of the env vars + // were not explicitly passed + rc.LocalAgentHostPort = fmt.Sprintf("%s:%d", host, port) + + return rc, nil +} + +// parseTags parses the given string into a collection of Tags. +// Spec for this value: +// - comma separated list of key=value +// - value can be specified using the notation ${envVar:defaultValue}, where `envVar` +// is an environment variable and `defaultValue` is the value to use in case the env var is not set +func parseTags(sTags string) []opentracing.Tag { + pairs := strings.Split(sTags, ",") + tags := make([]opentracing.Tag, 0) + for _, p := range pairs { + kv := strings.SplitN(p, "=", 2) + k, v := strings.TrimSpace(kv[0]), strings.TrimSpace(kv[1]) + + if strings.HasPrefix(v, "${") && strings.HasSuffix(v, "}") { + ed := strings.SplitN(v[2:len(v)-1], ":", 2) + e, d := ed[0], ed[1] + v = os.Getenv(e) + if v == "" && d != "" { + v = d + } + } + + tag := opentracing.Tag{Key: k, Value: v} + tags = append(tags, tag) + } + + return tags +} diff --git a/config/config_test.go b/config/config_test.go index d25a793d..41e82646 100644 --- a/config/config_test.go +++ b/config/config_test.go @@ -15,6 +15,8 @@ package config import ( + "fmt" + "os" "testing" "time" @@ -70,6 +72,155 @@ func TestDefaultSampler(t *testing.T) { require.Error(t, err) } +func TestServiceNameFromEnv(t *testing.T) { + os.Setenv(envServiceName, "my-service") + + cfg, err := FromEnv() + assert.NoError(t, err) + + _, c, err := cfg.New("") + defer c.Close() + assert.NoError(t, err) + os.Unsetenv(envServiceName) +} + +func TestFromEnv(t *testing.T) { + os.Setenv(envServiceName, "my-service") + os.Setenv(envDisabled, "false") + os.Setenv(envRPCMetrics, "true") + os.Setenv(envTags, "KEY=VALUE") + + cfg, err := FromEnv() + assert.NoError(t, err) + assert.Equal(t, "my-service", cfg.ServiceName) + assert.Equal(t, false, cfg.Disabled) + assert.Equal(t, true, cfg.RPCMetrics) + assert.Equal(t, "KEY", cfg.Tags[0].Key) + assert.Equal(t, "VALUE", cfg.Tags[0].Value) + + os.Unsetenv(envServiceName) + os.Unsetenv(envDisabled) + os.Unsetenv(envRPCMetrics) +} + +func TestNoServiceNameFromEnv(t *testing.T) { + os.Unsetenv(envServiceName) + + cfg, err := FromEnv() + assert.NoError(t, err) + + _, _, err = cfg.New("") + assert.Error(t, err) +} + +func TestSamplerConfigFromEnv(t *testing.T) { + // prepare + os.Setenv(envSamplerType, "const") + os.Setenv(envSamplerParam, "1") + os.Setenv(envSamplerManagerHostPort, "http://themaster") + os.Setenv(envSamplerMaxOperations, "10") + os.Setenv(envSamplerRefreshInterval, "1m1s") // 61 seconds + + // test + cfg, err := FromEnv() + assert.NoError(t, err) + + // verify + assert.Equal(t, "const", cfg.Sampler.Type) + assert.Equal(t, float64(1), cfg.Sampler.Param) + assert.Equal(t, "http://themaster", cfg.Sampler.SamplingServerURL) + assert.Equal(t, int(10), cfg.Sampler.MaxOperations) + assert.Equal(t, 61000000000, int(cfg.Sampler.SamplingRefreshInterval)) + + // cleanup + os.Unsetenv(envSamplerType) + os.Unsetenv(envSamplerParam) + os.Unsetenv(envSamplerManagerHostPort) + os.Unsetenv(envSamplerMaxOperations) + os.Unsetenv(envSamplerRefreshInterval) +} + +func TestReporterConfigFromEnv(t *testing.T) { + // prepare + os.Setenv(envReporterMaxQueueSize, "10") + os.Setenv(envReporterFlushInterval, "1m1s") // 61 seconds + os.Setenv(envReporterLogSpans, "true") + os.Setenv(envAgentHost, "nonlocalhost") + os.Setenv(envAgentPort, "6832") + + // test + cfg, err := FromEnv() + assert.NoError(t, err) + + // verify + assert.Equal(t, int(10), cfg.Reporter.QueueSize) + assert.Equal(t, 61000000000, int(cfg.Reporter.BufferFlushInterval)) + assert.Equal(t, true, cfg.Reporter.LogSpans) + assert.Equal(t, "nonlocalhost:6832", cfg.Reporter.LocalAgentHostPort) + + // cleanup + os.Unsetenv(envReporterMaxQueueSize) + os.Unsetenv(envReporterFlushInterval) + os.Unsetenv(envReporterLogSpans) + os.Unsetenv(envAgentHost) + os.Unsetenv(envAgentPort) +} + +func TestParsingErrorsFromEnv(t *testing.T) { + os.Setenv(envAgentHost, "localhost") // we require this in order to test the parsing of the port + + tests := []struct { + envVar string + value string + }{ + { + envVar: envRPCMetrics, + value: "NOT_A_BOOLEAN", + }, + { + envVar: envDisabled, + value: "NOT_A_BOOLEAN", + }, + { + envVar: envSamplerParam, + value: "NOT_A_FLOAT", + }, + { + envVar: envSamplerMaxOperations, + value: "NOT_AN_INT", + }, + { + envVar: envSamplerRefreshInterval, + value: "NOT_A_DURATION", + }, + { + envVar: envReporterMaxQueueSize, + value: "NOT_AN_INT", + }, + { + envVar: envReporterFlushInterval, + value: "NOT_A_DURATION", + }, + { + envVar: envReporterLogSpans, + value: "NOT_A_BOOLEAN", + }, + { + envVar: envAgentPort, + value: "NOT_AN_INT", + }, + } + + for _, test := range tests { + os.Setenv(test.envVar, test.value) + _, err := FromEnv() + require.Error(t, err) + assert.Contains(t, err.Error(), fmt.Sprintf("cannot parse env var %s=%s", test.envVar, test.value)) + os.Unsetenv(test.envVar) + } + +} + func TestInvalidSamplerType(t *testing.T) { cfg := &SamplerConfig{MaxOperations: 10} s, err := cfg.NewSampler("x", jaeger.NewNullMetrics()) @@ -302,3 +453,45 @@ func TestConfigWithSampler(t *testing.T) { require.Equal(t, traceID, sampler.lastTraceID) require.Equal(t, "test", sampler.lastOperation) } + +func TestNewTracer(t *testing.T) { + cfg := &Configuration{ServiceName: "my-service"} + _, closer, err := cfg.NewTracer(Metrics(metrics.NullFactory), Logger(log.NullLogger)) + defer closer.Close() + + assert.NoError(t, err) +} + +func TestNewTracerWithoutServiceName(t *testing.T) { + cfg := &Configuration{} + _, _, err := cfg.NewTracer(Metrics(metrics.NullFactory), Logger(log.NullLogger)) + assert.Contains(t, err.Error(), "no service name provided") +} + +func TestParseTags(t *testing.T) { + os.Setenv("existing", "not-default") + tags := "key=value,k1=${nonExisting:default}, k2=${withSpace:default},k3=${existing:default}" + ts := parseTags(tags) + assert.Equal(t, 4, len(ts)) + + assert.Equal(t, "key", ts[0].Key) + assert.Equal(t, "value", ts[0].Value) + + assert.Equal(t, "k1", ts[1].Key) + assert.Equal(t, "default", ts[1].Value) + + assert.Equal(t, "k2", ts[2].Key) + assert.Equal(t, "default", ts[2].Value) + + assert.Equal(t, "k3", ts[3].Key) + assert.Equal(t, "not-default", ts[3].Value) + + os.Unsetenv("existing") +} + +func TestServiceNameViaConfiguration(t *testing.T) { + cfg := &Configuration{ServiceName: "my-service"} + _, closer, err := cfg.New("") + assert.NoError(t, err) + defer closer.Close() +} diff --git a/config/example_test.go b/config/example_test.go index befaae8d..28644226 100644 --- a/config/example_test.go +++ b/config/example_test.go @@ -16,7 +16,9 @@ package config_test import ( "log" + "os" + opentracing "github.com/opentracing/opentracing-go" "github.com/uber/jaeger-lib/metrics" "github.com/uber/jaeger-client-go" @@ -82,3 +84,45 @@ func ExampleConfiguration_InitGlobalTracer_production() { // continue main() } + +func ExampleConfiguration_EnvironmentVariables() { + cfg, err := jaegercfg.FromEnv() + if err != nil { + // parsing errors might happen here, such as when we get a string where we expect a number + log.Printf("Could not initialize jaeger tracer: %s", err.Error()) + return + } + + tracer, closer, err := cfg.NewTracer() + if err != nil { + log.Printf("Could not initialize jaeger tracer: %s", err.Error()) + return + } + defer closer.Close() + + opentracing.SetGlobalTracer(tracer) + // continue main() +} + +func ExampleConfiguration_Override_EnvironmentVariables() { + os.Setenv("JAEGER_SERVICE_NAME", "not-effective") + + cfg, err := jaegercfg.FromEnv() + if err != nil { + // parsing errors might happen here, such as when we get a string where we expect a number + log.Printf("Could not initialize jaeger tracer: %s", err.Error()) + return + } + + cfg.ServiceName = "this-will-be-the-service-name" + + tracer, closer, err := cfg.NewTracer() + if err != nil { + log.Printf("Could not initialize jaeger tracer: %s", err.Error()) + return + } + defer closer.Close() + + opentracing.SetGlobalTracer(tracer) + // continue main() +} diff --git a/constants.go b/constants.go index ff931269..2485107f 100644 --- a/constants.go +++ b/constants.go @@ -73,4 +73,10 @@ const ( // SamplerTypeLowerBound is the type of sampler that samples // at least a fixed number of traces per second. SamplerTypeLowerBound = "lowerbound" + + // DefaultUDPSpanServerHost is the default host to send the spans to, via UDP + DefaultUDPSpanServerHost = "localhost" + + // DefaultUDPSpanServerPort is the default port to send the spans to, via UDP + DefaultUDPSpanServerPort = 6831 ) diff --git a/transport_udp.go b/transport_udp.go index cb83cdf9..709e4b88 100644 --- a/transport_udp.go +++ b/transport_udp.go @@ -16,6 +16,7 @@ package jaeger import ( "errors" + "fmt" "github.com/apache/thrift/lib/go/thrift" @@ -31,8 +32,6 @@ import ( // in the batch, because the length of the list is encoded as varint32, as well as SeqId. const emitBatchOverhead = 30 -const defaultUDPSpanServerHostPort = "localhost:6831" - var errSpanTooLarge = errors.New("Span is too large") type udpSender struct { @@ -50,7 +49,7 @@ type udpSender struct { // NewUDPTransport creates a reporter that submits spans to jaeger-agent func NewUDPTransport(hostPort string, maxPacketSize int) (Transport, error) { if len(hostPort) == 0 { - hostPort = defaultUDPSpanServerHostPort + hostPort = fmt.Sprintf("%s:%d", DefaultUDPSpanServerHost, DefaultUDPSpanServerPort) } if maxPacketSize == 0 { maxPacketSize = utils.UDPPacketMaxLength