]> git.proxmox.com Git - ceph.git/blame - ceph/src/jaegertracing/jaeger-client-cpp/src/jaegertracing/Tracer.h
update source to Ceph Pacific 16.2.2
[ceph.git] / ceph / src / jaegertracing / jaeger-client-cpp / src / jaegertracing / Tracer.h
CommitLineData
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
45namespace jaegertracing {
46
47class 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
313opentracing::SpanReference SelfRef(const opentracing::SpanContext* span_context) noexcept;
314
315} // namespace jaegertracing
316
317#endif // JAEGERTRACING_TRACER_H