]>
Commit | Line | Data |
---|---|---|
f67539c2 TL |
1 | /* |
2 | * Copyright (c) 2017 Uber Technologies, Inc. | |
3 | * | |
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | * you may not use this file except in compliance with the License. | |
6 | * You may obtain a copy of the License at | |
7 | * | |
8 | * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | * | |
10 | * Unless required by applicable law or agreed to in writing, software | |
11 | * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | * See the License for the specific language governing permissions and | |
14 | * limitations under the License. | |
15 | */ | |
16 | ||
17 | #ifndef JAEGERTRACING_TRACER_H | |
18 | #define JAEGERTRACING_TRACER_H | |
19 | ||
20 | #include <chrono> | |
21 | #include <memory> | |
22 | #include <random> | |
23 | #include <vector> | |
24 | ||
25 | #include <opentracing/noop.h> | |
26 | #include <opentracing/tracer.h> | |
27 | ||
28 | #include "jaegertracing/Compilers.h" | |
29 | #include "jaegertracing/Config.h" | |
30 | #include "jaegertracing/Constants.h" | |
31 | #include "jaegertracing/Logging.h" | |
32 | #include "jaegertracing/Span.h" | |
33 | #include "jaegertracing/Tag.h" | |
34 | #include "jaegertracing/baggage/BaggageSetter.h" | |
35 | #include "jaegertracing/baggage/RestrictionManager.h" | |
36 | #include "jaegertracing/metrics/Metrics.h" | |
37 | #include "jaegertracing/metrics/NullStatsFactory.h" | |
38 | #include "jaegertracing/net/IPAddress.h" | |
39 | #include "jaegertracing/platform/Hostname.h" | |
40 | #include "jaegertracing/propagation/Propagator.h" | |
41 | #include "jaegertracing/reporters/Reporter.h" | |
42 | #include "jaegertracing/samplers/Sampler.h" | |
43 | #include "jaegertracing/utils/ErrorUtil.h" | |
44 | ||
45 | namespace jaegertracing { | |
46 | ||
47 | class Tracer : public opentracing::Tracer, | |
48 | public std::enable_shared_from_this<Tracer> { | |
49 | public: | |
50 | using SteadyClock = Span::SteadyClock; | |
51 | using SystemClock = Span::SystemClock; | |
52 | using string_view = opentracing::string_view; | |
53 | ||
54 | static constexpr auto kGen128BitOption = 1; | |
55 | ||
56 | static std::shared_ptr<opentracing::Tracer> make(const Config& config) | |
57 | { | |
58 | return make(config.serviceName(), | |
59 | config, | |
60 | std::shared_ptr<logging::Logger>(logging::nullLogger())); | |
61 | } | |
62 | ||
63 | static std::shared_ptr<opentracing::Tracer> | |
64 | make(const std::string& serviceName, const Config& config) | |
65 | { | |
66 | return make(serviceName, | |
67 | config, | |
68 | std::shared_ptr<logging::Logger>(logging::nullLogger())); | |
69 | } | |
70 | ||
71 | static std::shared_ptr<opentracing::Tracer> | |
72 | make(const std::string& serviceName, | |
73 | const Config& config, | |
74 | const std::shared_ptr<logging::Logger>& logger) | |
75 | { | |
76 | metrics::NullStatsFactory factory; | |
77 | return make(serviceName, config, logger, factory); | |
78 | } | |
79 | static std::shared_ptr<opentracing::Tracer> | |
80 | make(const std::string& serviceName, | |
81 | const Config& config, | |
82 | const std::shared_ptr<logging::Logger>& logger, | |
83 | metrics::StatsFactory& statsFactory) | |
84 | { | |
85 | return make(serviceName, config, logger, statsFactory, 0); | |
86 | } | |
87 | static std::shared_ptr<opentracing::Tracer> | |
88 | make(const std::string& serviceName, | |
89 | const Config& config, | |
90 | const std::shared_ptr<logging::Logger>& logger, | |
91 | metrics::StatsFactory& statsFactory, | |
92 | int options); | |
93 | ||
94 | ~Tracer() { Close(); } | |
95 | ||
96 | std::unique_ptr<opentracing::Span> | |
97 | StartSpanWithOptions(string_view operationName, | |
98 | const opentracing::StartSpanOptions& options) const | |
99 | noexcept override; | |
100 | ||
101 | opentracing::expected<void> Inject(const opentracing::SpanContext& ctx, | |
102 | std::ostream& writer) const override | |
103 | { | |
104 | const auto* jaegerCtx = dynamic_cast<const SpanContext*>(&ctx); | |
105 | if (!jaegerCtx) { | |
106 | return opentracing::make_expected_from_error<void>( | |
107 | opentracing::invalid_span_context_error); | |
108 | } | |
109 | _binaryPropagator.inject(*jaegerCtx, writer); | |
110 | return opentracing::make_expected(); | |
111 | } | |
112 | ||
113 | opentracing::expected<void> | |
114 | Inject(const opentracing::SpanContext& ctx, | |
115 | const opentracing::TextMapWriter& writer) const override | |
116 | { | |
117 | const auto* jaegerCtx = dynamic_cast<const SpanContext*>(&ctx); | |
118 | if (!jaegerCtx) { | |
119 | return opentracing::make_expected_from_error<void>( | |
120 | opentracing::invalid_span_context_error); | |
121 | } | |
122 | _textPropagator.inject(*jaegerCtx, writer); | |
123 | return opentracing::make_expected(); | |
124 | } | |
125 | ||
126 | opentracing::expected<void> | |
127 | Inject(const opentracing::SpanContext& ctx, | |
128 | const opentracing::HTTPHeadersWriter& writer) const override | |
129 | { | |
130 | const auto* jaegerCtx = dynamic_cast<const SpanContext*>(&ctx); | |
131 | if (!jaegerCtx) { | |
132 | return opentracing::make_expected_from_error<void>( | |
133 | opentracing::invalid_span_context_error); | |
134 | } | |
135 | _httpHeaderPropagator.inject(*jaegerCtx, writer); | |
136 | return opentracing::make_expected(); | |
137 | } | |
138 | ||
139 | opentracing::expected<std::unique_ptr<opentracing::SpanContext>> | |
140 | Extract(std::istream& reader) const override | |
141 | { | |
142 | const auto spanContext = _binaryPropagator.extract(reader); | |
143 | if (spanContext == SpanContext()) { | |
144 | return std::unique_ptr<opentracing::SpanContext>(); | |
145 | } | |
146 | return std::unique_ptr<opentracing::SpanContext>( | |
147 | new SpanContext(spanContext)); | |
148 | } | |
149 | ||
150 | opentracing::expected<std::unique_ptr<opentracing::SpanContext>> | |
151 | Extract(const opentracing::TextMapReader& reader) const override | |
152 | { | |
153 | const auto spanContext = _textPropagator.extract(reader); | |
154 | if (spanContext == SpanContext()) { | |
155 | return std::unique_ptr<opentracing::SpanContext>(); | |
156 | } | |
157 | return std::unique_ptr<opentracing::SpanContext>( | |
158 | new SpanContext(spanContext)); | |
159 | } | |
160 | ||
161 | opentracing::expected<std::unique_ptr<opentracing::SpanContext>> | |
162 | Extract(const opentracing::HTTPHeadersReader& reader) const override | |
163 | { | |
164 | const auto spanContext = _httpHeaderPropagator.extract(reader); | |
165 | if (spanContext == SpanContext()) { | |
166 | return std::unique_ptr<opentracing::SpanContext>(); | |
167 | } | |
168 | return std::unique_ptr<opentracing::SpanContext>( | |
169 | new SpanContext(spanContext)); | |
170 | } | |
171 | ||
172 | void Close() noexcept override | |
173 | { | |
174 | try { | |
175 | _reporter->close(); | |
176 | _sampler->close(); | |
177 | _restrictionManager->close(); | |
178 | } catch (...) { | |
179 | utils::ErrorUtil::logError(*_logger, | |
180 | "Error occurred in Tracer::Close"); | |
181 | } | |
182 | } | |
183 | ||
184 | void close() noexcept { Close(); } | |
185 | ||
186 | const std::string& serviceName() const { return _serviceName; } | |
187 | ||
188 | const std::vector<Tag>& tags() const { return _tags; } | |
189 | ||
190 | const baggage::BaggageSetter& baggageSetter() const | |
191 | { | |
192 | return _baggageSetter; | |
193 | } | |
194 | ||
195 | void reportSpan(const Span& span) const | |
196 | { | |
197 | _metrics->spansFinished().inc(1); | |
198 | if (span.context().isSampled()) { | |
199 | _reporter->report(span); | |
200 | } | |
201 | } | |
202 | ||
203 | private: | |
204 | Tracer(const std::string& serviceName, | |
205 | const std::shared_ptr<samplers::Sampler>& sampler, | |
206 | const std::shared_ptr<reporters::Reporter>& reporter, | |
207 | const std::shared_ptr<logging::Logger>& logger, | |
208 | const std::shared_ptr<metrics::Metrics>& metrics, | |
209 | const propagation::HeadersConfig& headersConfig, | |
210 | const std::vector<Tag>& tags, | |
211 | int options) | |
212 | : _serviceName(serviceName) | |
213 | , _hostIPv4(net::IPAddress::localIP(AF_INET)) | |
214 | , _sampler(sampler) | |
215 | , _reporter(reporter) | |
216 | , _metrics(metrics) | |
217 | , _logger(logger) | |
218 | , _randomNumberGenerator() | |
219 | , _textPropagator(headersConfig, _metrics) | |
220 | , _httpHeaderPropagator(headersConfig, _metrics) | |
221 | , _binaryPropagator(_metrics) | |
222 | , _tags() | |
223 | , _restrictionManager(new baggage::DefaultRestrictionManager(0)) | |
224 | , _baggageSetter(*_restrictionManager, *_metrics) | |
225 | , _options(options) | |
226 | { | |
227 | _tags.push_back(Tag(kJaegerClientVersionTagKey, kJaegerClientVersion)); | |
228 | ||
229 | try { | |
230 | _tags.push_back(Tag(kTracerHostnameTagKey, platform::hostname())); | |
231 | } catch (const std::system_error&) { | |
232 | // Ignore hostname error. | |
233 | } | |
234 | ||
235 | if (_hostIPv4 == net::IPAddress()) { | |
236 | _logger->error("Unable to determine this host's IP address"); | |
237 | } | |
238 | else { | |
239 | _tags.push_back(Tag(kTracerIPTagKey, _hostIPv4.host())); | |
240 | } | |
241 | ||
242 | std::copy(tags.cbegin(), tags.cend(), std::back_inserter(_tags)); | |
243 | ||
244 | std::random_device device; | |
245 | _randomNumberGenerator.seed(device()); | |
246 | } | |
247 | ||
248 | uint64_t randomID() const | |
249 | { | |
250 | std::lock_guard<std::mutex> lock(_randomMutex); | |
251 | auto value = _randomNumberGenerator(); | |
252 | while (value == 0) { | |
253 | value = _randomNumberGenerator(); | |
254 | } | |
255 | return value; | |
256 | } | |
257 | ||
258 | using OpenTracingTag = std::pair<std::string, opentracing::Value>; | |
259 | ||
260 | std::unique_ptr<Span> | |
261 | startSpanInternal(const SpanContext& context, | |
262 | const std::string& operationName, | |
263 | const SystemClock::time_point& startTimeSystem, | |
264 | const SteadyClock::time_point& startTimeSteady, | |
265 | const std::vector<Tag>& internalTags, | |
266 | const std::vector<OpenTracingTag>& tags, | |
267 | bool newTrace, | |
268 | const std::vector<Reference>& references) const; | |
269 | ||
270 | using OpenTracingRef = std::pair<opentracing::SpanReferenceType, | |
271 | const opentracing::SpanContext*>; | |
272 | ||
273 | struct AnalyzedReferences { | |
274 | AnalyzedReferences() | |
275 | : _parent(nullptr) | |
276 | , _self(nullptr) | |
277 | , _references() | |
278 | { | |
279 | } | |
280 | ||
281 | const SpanContext* _parent; | |
282 | const SpanContext* _self; | |
283 | std::vector<Reference> _references; | |
284 | }; | |
285 | ||
286 | AnalyzedReferences | |
287 | analyzeReferences(const std::vector<OpenTracingRef>& references) const; | |
288 | ||
289 | std::string _serviceName; | |
290 | net::IPAddress _hostIPv4; | |
291 | std::shared_ptr<samplers::Sampler> _sampler; | |
292 | std::shared_ptr<reporters::Reporter> _reporter; | |
293 | std::shared_ptr<metrics::Metrics> _metrics; | |
294 | std::shared_ptr<logging::Logger> _logger; | |
295 | mutable std::mt19937_64 _randomNumberGenerator; | |
296 | mutable std::mutex _randomMutex; | |
297 | propagation::TextMapPropagator _textPropagator; | |
298 | propagation::HTTPHeaderPropagator _httpHeaderPropagator; | |
299 | propagation::BinaryPropagator _binaryPropagator; | |
300 | std::vector<Tag> _tags; | |
301 | std::unique_ptr<baggage::RestrictionManager> _restrictionManager; | |
302 | baggage::BaggageSetter _baggageSetter; | |
303 | int _options; | |
304 | }; | |
305 | ||
306 | ||
307 | // jaegertracing::SelfRef() returns an opentracing::SpanReference which can be passed to Tracer::StartSpan | |
308 | // to influence the SpanContext of the newly created span. Specifically, the new span inherits the traceID | |
309 | // and spanID from the passed SELF reference. It can be used to pass externally generated IDs to the tracer, | |
310 | // with the purpose of recording spans from data generated elsewhere (e.g. from logs), or by augmenting the | |
311 | // data of the existing span (Jaeger backend will merge multiple instances of the spans with the same IDs). | |
312 | // Must be the lone reference, can be used only for root spans | |
313 | opentracing::SpanReference SelfRef(const opentracing::SpanContext* span_context) noexcept; | |
314 | ||
315 | } // namespace jaegertracing | |
316 | ||
317 | #endif // JAEGERTRACING_TRACER_H |