blob: a729bd8fe6007ecae8aae3aaeaa9f2be9e2b34a4 [file] [log] [blame]
Takahiro Suzukid7bf8202020-12-17 20:21:59 +09001// Copyright (c) 2018 The Jaeger Authors.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package config
16
17import (
18 "fmt"
19 "net/url"
20 "os"
21 "strconv"
22 "strings"
23 "time"
24
25 "github.com/opentracing/opentracing-go"
26 "github.com/pkg/errors"
27
28 "github.com/uber/jaeger-client-go"
29)
30
31const (
32 // environment variable names
33 envServiceName = "JAEGER_SERVICE_NAME"
34 envDisabled = "JAEGER_DISABLED"
35 envRPCMetrics = "JAEGER_RPC_METRICS"
36 envTags = "JAEGER_TAGS"
37 envSamplerType = "JAEGER_SAMPLER_TYPE"
38 envSamplerParam = "JAEGER_SAMPLER_PARAM"
39 envSamplerManagerHostPort = "JAEGER_SAMPLER_MANAGER_HOST_PORT"
40 envSamplerMaxOperations = "JAEGER_SAMPLER_MAX_OPERATIONS"
41 envSamplerRefreshInterval = "JAEGER_SAMPLER_REFRESH_INTERVAL"
42 envReporterMaxQueueSize = "JAEGER_REPORTER_MAX_QUEUE_SIZE"
43 envReporterFlushInterval = "JAEGER_REPORTER_FLUSH_INTERVAL"
44 envReporterLogSpans = "JAEGER_REPORTER_LOG_SPANS"
45 envEndpoint = "JAEGER_ENDPOINT"
46 envUser = "JAEGER_USER"
47 envPassword = "JAEGER_PASSWORD"
48 envAgentHost = "JAEGER_AGENT_HOST"
49 envAgentPort = "JAEGER_AGENT_PORT"
50)
51
52// FromEnv uses environment variables to set the tracer's Configuration
53func FromEnv() (*Configuration, error) {
54 c := &Configuration{}
55 return c.FromEnv()
56}
57
58// FromEnv uses environment variables and overrides existing tracer's Configuration
59func (c *Configuration) FromEnv() (*Configuration, error) {
60 if e := os.Getenv(envServiceName); e != "" {
61 c.ServiceName = e
62 }
63
64 if e := os.Getenv(envRPCMetrics); e != "" {
65 if value, err := strconv.ParseBool(e); err == nil {
66 c.RPCMetrics = value
67 } else {
68 return nil, errors.Wrapf(err, "cannot parse env var %s=%s", envRPCMetrics, e)
69 }
70 }
71
72 if e := os.Getenv(envDisabled); e != "" {
73 if value, err := strconv.ParseBool(e); err == nil {
74 c.Disabled = value
75 } else {
76 return nil, errors.Wrapf(err, "cannot parse env var %s=%s", envDisabled, e)
77 }
78 }
79
80 if e := os.Getenv(envTags); e != "" {
81 c.Tags = parseTags(e)
82 }
83
84 if c.Sampler == nil {
85 c.Sampler = &SamplerConfig{}
86 }
87
88 if s, err := c.Sampler.samplerConfigFromEnv(); err == nil {
89 c.Sampler = s
90 } else {
91 return nil, errors.Wrap(err, "cannot obtain sampler config from env")
92 }
93
94 if c.Reporter == nil {
95 c.Reporter = &ReporterConfig{}
96 }
97
98 if r, err := c.Reporter.reporterConfigFromEnv(); err == nil {
99 c.Reporter = r
100 } else {
101 return nil, errors.Wrap(err, "cannot obtain reporter config from env")
102 }
103
104 return c, nil
105}
106
107// samplerConfigFromEnv creates a new SamplerConfig based on the environment variables
108func (sc *SamplerConfig) samplerConfigFromEnv() (*SamplerConfig, error) {
109 if e := os.Getenv(envSamplerType); e != "" {
110 sc.Type = e
111 }
112
113 if e := os.Getenv(envSamplerParam); e != "" {
114 if value, err := strconv.ParseFloat(e, 64); err == nil {
115 sc.Param = value
116 } else {
117 return nil, errors.Wrapf(err, "cannot parse env var %s=%s", envSamplerParam, e)
118 }
119 }
120
121 if e := os.Getenv(envSamplerManagerHostPort); e != "" {
122 sc.SamplingServerURL = e
123 } else if e := os.Getenv(envAgentHost); e != "" {
124 // Fallback if we know the agent host - try the sampling endpoint there
125 sc.SamplingServerURL = fmt.Sprintf("http://%s:%d/sampling", e, jaeger.DefaultSamplingServerPort)
126 }
127
128 if e := os.Getenv(envSamplerMaxOperations); e != "" {
129 if value, err := strconv.ParseInt(e, 10, 0); err == nil {
130 sc.MaxOperations = int(value)
131 } else {
132 return nil, errors.Wrapf(err, "cannot parse env var %s=%s", envSamplerMaxOperations, e)
133 }
134 }
135
136 if e := os.Getenv(envSamplerRefreshInterval); e != "" {
137 if value, err := time.ParseDuration(e); err == nil {
138 sc.SamplingRefreshInterval = value
139 } else {
140 return nil, errors.Wrapf(err, "cannot parse env var %s=%s", envSamplerRefreshInterval, e)
141 }
142 }
143
144 return sc, nil
145}
146
147// reporterConfigFromEnv creates a new ReporterConfig based on the environment variables
148func (rc *ReporterConfig) reporterConfigFromEnv() (*ReporterConfig, error) {
149 if e := os.Getenv(envReporterMaxQueueSize); e != "" {
150 if value, err := strconv.ParseInt(e, 10, 0); err == nil {
151 rc.QueueSize = int(value)
152 } else {
153 return nil, errors.Wrapf(err, "cannot parse env var %s=%s", envReporterMaxQueueSize, e)
154 }
155 }
156
157 if e := os.Getenv(envReporterFlushInterval); e != "" {
158 if value, err := time.ParseDuration(e); err == nil {
159 rc.BufferFlushInterval = value
160 } else {
161 return nil, errors.Wrapf(err, "cannot parse env var %s=%s", envReporterFlushInterval, e)
162 }
163 }
164
165 if e := os.Getenv(envReporterLogSpans); e != "" {
166 if value, err := strconv.ParseBool(e); err == nil {
167 rc.LogSpans = value
168 } else {
169 return nil, errors.Wrapf(err, "cannot parse env var %s=%s", envReporterLogSpans, e)
170 }
171 }
172
173 if e := os.Getenv(envEndpoint); e != "" {
174 u, err := url.ParseRequestURI(e)
175 if err != nil {
176 return nil, errors.Wrapf(err, "cannot parse env var %s=%s", envEndpoint, e)
177 }
178 rc.CollectorEndpoint = u.String()
179 user := os.Getenv(envUser)
180 pswd := os.Getenv(envPassword)
181 if user != "" && pswd == "" || user == "" && pswd != "" {
182 return nil, errors.Errorf("you must set %s and %s env vars together", envUser, envPassword)
183 }
184 rc.User = user
185 rc.Password = pswd
186 } else {
187 host := jaeger.DefaultUDPSpanServerHost
188 if e := os.Getenv(envAgentHost); e != "" {
189 host = e
190 }
191
192 port := jaeger.DefaultUDPSpanServerPort
193 if e := os.Getenv(envAgentPort); e != "" {
194 if value, err := strconv.ParseInt(e, 10, 0); err == nil {
195 port = int(value)
196 } else {
197 return nil, errors.Wrapf(err, "cannot parse env var %s=%s", envAgentPort, e)
198 }
199 }
200 rc.LocalAgentHostPort = fmt.Sprintf("%s:%d", host, port)
201 }
202
203 return rc, nil
204}
205
206// parseTags parses the given string into a collection of Tags.
207// Spec for this value:
208// - comma separated list of key=value
209// - value can be specified using the notation ${envVar:defaultValue}, where `envVar`
210// is an environment variable and `defaultValue` is the value to use in case the env var is not set
211func parseTags(sTags string) []opentracing.Tag {
212 pairs := strings.Split(sTags, ",")
213 tags := make([]opentracing.Tag, 0)
214 for _, p := range pairs {
215 kv := strings.SplitN(p, "=", 2)
216 k, v := strings.TrimSpace(kv[0]), strings.TrimSpace(kv[1])
217
218 if strings.HasPrefix(v, "${") && strings.HasSuffix(v, "}") {
219 ed := strings.SplitN(v[2:len(v)-1], ":", 2)
220 e, d := ed[0], ed[1]
221 v = os.Getenv(e)
222 if v == "" && d != "" {
223 v = d
224 }
225 }
226
227 tag := opentracing.Tag{Key: k, Value: v}
228 tags = append(tags, tag)
229 }
230
231 return tags
232}