config_env.go 8.5 KB

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