1// Copyright (c) 2017 Uber Technologies, Inc.
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 jaeger
16
17import (
18	"time"
19
20	"github.com/uber/jaeger-client-go/log"
21)
22
23// SamplerOption is a function that sets some option on the sampler
24type SamplerOption func(options *samplerOptions)
25
26// SamplerOptions is a factory for all available SamplerOption's.
27var SamplerOptions SamplerOptionsFactory
28
29// SamplerOptionsFactory is a factory for all available SamplerOption's.
30// The type acts as a namespace for factory functions. It is public to
31// make the functions discoverable via godoc. Recommended to be used
32// via global SamplerOptions variable.
33type SamplerOptionsFactory struct{}
34
35type samplerOptions struct {
36	metrics                 *Metrics
37	sampler                 SamplerV2
38	logger                  log.DebugLogger
39	samplingServerURL       string
40	samplingRefreshInterval time.Duration
41	samplingFetcher         SamplingStrategyFetcher
42	samplingParser          SamplingStrategyParser
43	updaters                []SamplerUpdater
44	posParams               PerOperationSamplerParams
45}
46
47// Metrics creates a SamplerOption that initializes Metrics on the sampler,
48// which is used to emit statistics.
49func (SamplerOptionsFactory) Metrics(m *Metrics) SamplerOption {
50	return func(o *samplerOptions) {
51		o.metrics = m
52	}
53}
54
55// MaxOperations creates a SamplerOption that sets the maximum number of
56// operations the sampler will keep track of.
57func (SamplerOptionsFactory) MaxOperations(maxOperations int) SamplerOption {
58	return func(o *samplerOptions) {
59		o.posParams.MaxOperations = maxOperations
60	}
61}
62
63// OperationNameLateBinding creates a SamplerOption that sets the respective
64// field in the PerOperationSamplerParams.
65func (SamplerOptionsFactory) OperationNameLateBinding(enable bool) SamplerOption {
66	return func(o *samplerOptions) {
67		o.posParams.OperationNameLateBinding = enable
68	}
69}
70
71// InitialSampler creates a SamplerOption that sets the initial sampler
72// to use before a remote sampler is created and used.
73func (SamplerOptionsFactory) InitialSampler(sampler Sampler) SamplerOption {
74	return func(o *samplerOptions) {
75		o.sampler = samplerV1toV2(sampler)
76	}
77}
78
79// Logger creates a SamplerOption that sets the logger used by the sampler.
80func (SamplerOptionsFactory) Logger(logger Logger) SamplerOption {
81	return func(o *samplerOptions) {
82		o.logger = log.DebugLogAdapter(logger)
83	}
84}
85
86// SamplingServerURL creates a SamplerOption that sets the sampling server url
87// of the local agent that contains the sampling strategies.
88func (SamplerOptionsFactory) SamplingServerURL(samplingServerURL string) SamplerOption {
89	return func(o *samplerOptions) {
90		o.samplingServerURL = samplingServerURL
91	}
92}
93
94// SamplingRefreshInterval creates a SamplerOption that sets how often the
95// sampler will poll local agent for the appropriate sampling strategy.
96func (SamplerOptionsFactory) SamplingRefreshInterval(samplingRefreshInterval time.Duration) SamplerOption {
97	return func(o *samplerOptions) {
98		o.samplingRefreshInterval = samplingRefreshInterval
99	}
100}
101
102// SamplingStrategyFetcher creates a SamplerOption that initializes sampling strategy fetcher.
103func (SamplerOptionsFactory) SamplingStrategyFetcher(fetcher SamplingStrategyFetcher) SamplerOption {
104	return func(o *samplerOptions) {
105		o.samplingFetcher = fetcher
106	}
107}
108
109// SamplingStrategyParser creates a SamplerOption that initializes sampling strategy parser.
110func (SamplerOptionsFactory) SamplingStrategyParser(parser SamplingStrategyParser) SamplerOption {
111	return func(o *samplerOptions) {
112		o.samplingParser = parser
113	}
114}
115
116// Updaters creates a SamplerOption that initializes sampler updaters.
117func (SamplerOptionsFactory) Updaters(updaters ...SamplerUpdater) SamplerOption {
118	return func(o *samplerOptions) {
119		o.updaters = updaters
120	}
121}
122
123func (o *samplerOptions) applyOptionsAndDefaults(opts ...SamplerOption) *samplerOptions {
124	for _, option := range opts {
125		option(o)
126	}
127	if o.sampler == nil {
128		o.sampler = newProbabilisticSampler(0.001)
129	}
130	if o.logger == nil {
131		o.logger = log.NullLogger
132	}
133	if o.samplingServerURL == "" {
134		o.samplingServerURL = DefaultSamplingServerURL
135	}
136	if o.metrics == nil {
137		o.metrics = NewNullMetrics()
138	}
139	if o.samplingRefreshInterval <= 0 {
140		o.samplingRefreshInterval = defaultSamplingRefreshInterval
141	}
142	if o.samplingFetcher == nil {
143		o.samplingFetcher = newHTTPSamplingStrategyFetcher(o.samplingServerURL, o.logger)
144	}
145	if o.samplingParser == nil {
146		o.samplingParser = new(samplingStrategyParser)
147	}
148	if o.updaters == nil {
149		o.updaters = []SamplerUpdater{
150			&AdaptiveSamplerUpdater{
151				MaxOperations:            o.posParams.MaxOperations,
152				OperationNameLateBinding: o.posParams.OperationNameLateBinding,
153			},
154			new(ProbabilisticSamplerUpdater),
155			new(RateLimitingSamplerUpdater),
156		}
157	}
158	return o
159}
160