5 namespace opentracing
{
6 BEGIN_OPENTRACING_ABI_NAMESPACE
9 static uint64_t GenerateId() {
10 static thread_local
std::mt19937_64 rand_source
{std::random_device()()};
11 return static_cast<uint64_t>(rand_source());
14 static std::tuple
<SystemTime
, SteadyTime
> ComputeStartTimestamps(
15 const SystemTime
& start_system_timestamp
,
16 const SteadyTime
& start_steady_timestamp
) {
17 // If neither the system nor steady timestamps are set, get the tme from the
18 // respective clocks; otherwise, use the set timestamp to initialize the
20 if (start_system_timestamp
== SystemTime() &&
21 start_steady_timestamp
== SteadyTime()) {
22 return std::tuple
<SystemTime
, SteadyTime
>{SystemClock::now(),
25 if (start_system_timestamp
== SystemTime()) {
26 return std::tuple
<SystemTime
, SteadyTime
>{
27 opentracing::convert_time_point
<SystemClock
>(start_steady_timestamp
),
28 start_steady_timestamp
};
30 if (start_steady_timestamp
== SteadyTime()) {
31 return std::tuple
<SystemTime
, SteadyTime
>{
32 start_system_timestamp
,
33 opentracing::convert_time_point
<SteadyClock
>(start_system_timestamp
)};
35 return std::tuple
<SystemTime
, SteadyTime
>{start_system_timestamp
,
36 start_steady_timestamp
};
39 static bool SetSpanReference(
40 const std::pair
<SpanReferenceType
, const SpanContext
*>& reference
,
41 std::map
<std::string
, std::string
>& baggage
,
42 SpanReferenceData
& reference_data
) {
43 reference_data
.reference_type
= reference
.first
;
44 if (reference
.second
== nullptr) {
47 auto referenced_context
=
48 dynamic_cast<const MockSpanContext
*>(reference
.second
);
49 if (referenced_context
== nullptr) {
52 reference_data
.trace_id
= referenced_context
->trace_id();
53 reference_data
.span_id
= referenced_context
->span_id();
55 referenced_context
->ForeachBaggageItem(
56 [&baggage
](const std::string
& key
, const std::string
& value
) {
64 MockSpan::MockSpan(std::shared_ptr
<const Tracer
>&& tracer
, Recorder
* recorder
,
65 string_view operation_name
, const StartSpanOptions
& options
)
66 : tracer_
{std::move(tracer
)}, recorder_
{recorder
} {
67 data_
.operation_name
= operation_name
;
69 // Set start timestamps
70 std::tie(data_
.start_timestamp
, start_steady_
) = ComputeStartTimestamps(
71 options
.start_system_timestamp
, options
.start_steady_timestamp
);
74 SpanContextData span_context_data
;
75 for (auto& reference
: options
.references
) {
76 SpanReferenceData reference_data
;
77 if (!SetSpanReference(reference
, span_context_data
.baggage
,
81 data_
.references
.push_back(reference_data
);
85 for (auto& tag
: options
.tags
) {
86 data_
.tags
[tag
.first
] = tag
.second
;
90 span_context_data
.trace_id
=
91 data_
.references
.empty() ? GenerateId() : data_
.references
[0].trace_id
;
92 span_context_data
.span_id
= GenerateId();
93 span_context_
= MockSpanContext
{std::move(span_context_data
)};
96 MockSpan::~MockSpan() {
102 void MockSpan::FinishWithOptions(const FinishSpanOptions
& options
) noexcept
{
103 // Ensure the span is only finished once.
104 if (is_finished_
.exchange(true)) {
108 data_
.logs
.reserve(data_
.logs
.size() + options
.log_records
.size());
109 for (auto& log_record
: options
.log_records
) {
110 data_
.logs
.push_back(log_record
);
113 auto finish_timestamp
= options
.finish_steady_timestamp
;
114 if (finish_timestamp
== SteadyTime
{}) {
115 finish_timestamp
= SteadyClock::now();
118 data_
.duration
= finish_timestamp
- start_steady_
;
120 span_context_
.CopyData(data_
.span_context
);
122 if (recorder_
!= nullptr) {
123 recorder_
->RecordSpan(std::move(data_
));
127 void MockSpan::SetOperationName(string_view name
) noexcept
try {
128 std::lock_guard
<std::mutex
> lock_guard
{mutex_
};
129 data_
.operation_name
= name
;
130 } catch (const std::exception
& e
) {
132 fprintf(stderr
, "Failed to set operation name: %s\n", e
.what());
135 void MockSpan::SetTag(string_view key
,
136 const opentracing::Value
& value
) noexcept
try {
137 std::lock_guard
<std::mutex
> lock_guard
{mutex_
};
138 data_
.tags
[key
] = value
;
139 } catch (const std::exception
& e
) {
140 // Ignore upon error.
141 fprintf(stderr
, "Failed to set tag: %s\n", e
.what());
145 std::initializer_list
<std::pair
<string_view
, Value
>> fields
) noexcept
{
146 Log(SystemClock::now(), fields
);
150 SystemTime timestamp
,
151 std::initializer_list
<std::pair
<string_view
, Value
>> fields
) noexcept
try {
152 LogRecord log_record
;
153 log_record
.timestamp
= timestamp
;
154 log_record
.fields
.reserve(fields
.size());
155 for (auto& field
: fields
) {
156 log_record
.fields
.emplace_back(field
.first
, field
.second
);
158 std::lock_guard
<std::mutex
> lock_guard
{mutex_
};
159 data_
.logs
.emplace_back(std::move(log_record
));
160 } catch (const std::exception
& e
) {
161 // Drop log record upon error.
162 fprintf(stderr
, "Failed to log: %s\n", e
.what());
166 SystemTime timestamp
,
167 const std::vector
<std::pair
<string_view
, Value
>>& fields
) noexcept
try {
168 LogRecord log_record
;
169 log_record
.timestamp
= timestamp
;
170 log_record
.fields
.reserve(fields
.size());
171 for (auto& field
: fields
) {
172 log_record
.fields
.emplace_back(field
.first
, field
.second
);
174 std::lock_guard
<std::mutex
> lock_guard
{mutex_
};
175 data_
.logs
.emplace_back(std::move(log_record
));
176 } catch (const std::exception
& e
) {
177 // Drop log record upon error.
178 fprintf(stderr
, "Failed to log: %s\n", e
.what());
181 void MockSpan::SetBaggageItem(string_view restricted_key
,
182 string_view value
) noexcept
try {
183 std::lock_guard
<std::mutex
> lock_guard
{span_context_
.baggage_mutex_
};
184 span_context_
.data_
.baggage
.emplace(restricted_key
, value
);
185 } catch (const std::exception
& e
) {
186 // Drop baggage item upon error.
187 fprintf(stderr
, "Failed to set baggage item: %s\n", e
.what());
190 std::string
MockSpan::BaggageItem(string_view restricted_key
) const
192 std::lock_guard
<std::mutex
> lock_guard
{span_context_
.baggage_mutex_
};
193 auto lookup
= span_context_
.data_
.baggage
.find(restricted_key
);
194 if (lookup
!= span_context_
.data_
.baggage
.end()) {
195 return lookup
->second
;
198 } catch (const std::exception
& e
) {
199 // Return empty string upon error.
200 fprintf(stderr
, "Failed to retrieve baggage item: %s\n", e
.what());
204 } // namespace mocktracer
205 END_OPENTRACING_ABI_NAMESPACE
206 } // namespace opentracing