tracer_shim_test.cc 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344
  1. /*
  2. * Copyright The OpenTelemetry Authors
  3. * SPDX-License-Identifier: Apache-2.0
  4. */
  5. #include <gtest/gtest.h>
  6. #include <stdint.h>
  7. #include <iostream>
  8. #include <string>
  9. #include <system_error>
  10. #include <unordered_map>
  11. #include <utility>
  12. #include <vector>
  13. #include "opentracing/expected/expected.hpp"
  14. #include "opentracing/noop.h"
  15. #include "opentracing/propagation.h"
  16. #include "opentracing/span.h"
  17. #include "opentracing/tracer.h"
  18. #include "opentracing/util.h"
  19. #include "opentracing/value.h"
  20. #include "opentelemetry/baggage/baggage.h"
  21. #include "opentelemetry/common/key_value_iterable.h"
  22. #include "opentelemetry/context/propagation/text_map_propagator.h"
  23. #include "opentelemetry/nostd/shared_ptr.h"
  24. #include "opentelemetry/nostd/span.h"
  25. #include "opentelemetry/nostd/string_view.h"
  26. #include "opentelemetry/opentracingshim/shim_utils.h"
  27. #include "opentelemetry/opentracingshim/span_context_shim.h"
  28. #include "opentelemetry/opentracingshim/tracer_shim.h"
  29. #include "opentelemetry/trace/default_span.h"
  30. #include "opentelemetry/trace/provider.h"
  31. #include "opentelemetry/trace/span.h"
  32. #include "opentelemetry/trace/span_context.h"
  33. #include "opentelemetry/trace/span_context_kv_iterable.h"
  34. #include "opentelemetry/trace/span_id.h"
  35. #include "opentelemetry/trace/span_metadata.h"
  36. #include "opentelemetry/trace/span_startoptions.h"
  37. #include "opentelemetry/trace/trace_flags.h"
  38. #include "opentelemetry/trace/trace_id.h"
  39. #include "opentelemetry/trace/tracer.h"
  40. #include "opentelemetry/trace/tracer_provider.h"
  41. #include "shim_mocks.h"
  42. namespace trace_api = opentelemetry::trace;
  43. namespace nostd = opentelemetry::nostd;
  44. namespace context = opentelemetry::context;
  45. namespace baggage = opentelemetry::baggage;
  46. namespace shim = opentelemetry::opentracingshim;
  47. class TracerShimTest : public testing::Test
  48. {
  49. public:
  50. std::shared_ptr<opentracing::Tracer> tracer_shim;
  51. MockPropagator *text_map_format;
  52. MockPropagator *http_headers_format;
  53. protected:
  54. virtual void SetUp() override
  55. {
  56. using context::propagation::TextMapPropagator;
  57. text_map_format = new MockPropagator();
  58. http_headers_format = new MockPropagator();
  59. tracer_shim = shim::TracerShim::createTracerShim(
  60. trace_api::Provider::GetTracerProvider(),
  61. {.text_map = nostd::shared_ptr<TextMapPropagator>(text_map_format),
  62. .http_headers = nostd::shared_ptr<TextMapPropagator>(http_headers_format)});
  63. }
  64. virtual void TearDown() override { tracer_shim.reset(); }
  65. };
  66. TEST_F(TracerShimTest, TracerName)
  67. {
  68. auto mock_provider_ptr = new MockTracerProvider();
  69. nostd::shared_ptr<trace_api::TracerProvider> provider(mock_provider_ptr);
  70. ASSERT_NE(shim::TracerShim::createTracerShim(provider), nullptr);
  71. ASSERT_EQ(mock_provider_ptr->library_name_, "opentracing-shim");
  72. }
  73. TEST_F(TracerShimTest, SpanReferenceToCreatingTracer)
  74. {
  75. auto span_shim = tracer_shim->StartSpan("a");
  76. ASSERT_NE(span_shim, nullptr);
  77. ASSERT_EQ(&span_shim->tracer(), tracer_shim.get());
  78. }
  79. TEST_F(TracerShimTest, SpanParentChildRelationship)
  80. {
  81. auto span_shim1 = tracer_shim->StartSpan("a");
  82. auto span_shim2 = tracer_shim->StartSpan("b", {opentracing::ChildOf(&span_shim1->context())});
  83. ASSERT_NE(span_shim1, nullptr);
  84. ASSERT_NE(span_shim2, nullptr);
  85. ASSERT_NE(span_shim1, span_shim2);
  86. ASSERT_EQ(span_shim1->context().ToSpanID(), span_shim2->context().ToSpanID());
  87. ASSERT_EQ(span_shim1->context().ToTraceID(), span_shim2->context().ToTraceID());
  88. auto span_context_shim1 = static_cast<const shim::SpanContextShim *>(&span_shim1->context());
  89. auto span_context_shim2 = static_cast<const shim::SpanContextShim *>(&span_shim2->context());
  90. ASSERT_TRUE(span_context_shim1 != nullptr);
  91. ASSERT_TRUE(span_context_shim2 != nullptr);
  92. ASSERT_EQ(span_context_shim1->context(), span_context_shim2->context());
  93. }
  94. TEST_F(TracerShimTest, TracerGloballyRegistered)
  95. {
  96. ASSERT_FALSE(opentracing::Tracer::IsGlobalTracerRegistered());
  97. ASSERT_NE(opentracing::Tracer::InitGlobal(tracer_shim), nullptr);
  98. ASSERT_TRUE(opentracing::Tracer::IsGlobalTracerRegistered());
  99. }
  100. TEST_F(TracerShimTest, Close)
  101. {
  102. tracer_shim->Close();
  103. auto span_shim = tracer_shim->StartSpan("a");
  104. ASSERT_TRUE(span_shim == nullptr);
  105. }
  106. TEST_F(TracerShimTest, SpanHandleErrorTagAtCreation)
  107. {
  108. auto mock_provider_ptr = new MockTracerProvider();
  109. nostd::shared_ptr<trace_api::TracerProvider> provider(mock_provider_ptr);
  110. auto tracer_shim = shim::TracerShim::createTracerShim(provider);
  111. auto span_shim = tracer_shim->StartSpanWithOptions("test", {});
  112. ASSERT_TRUE(span_shim != nullptr);
  113. ASSERT_TRUE(mock_provider_ptr->tracer_ != nullptr);
  114. ASSERT_TRUE(mock_provider_ptr->tracer_->span_ != nullptr);
  115. ASSERT_EQ(mock_provider_ptr->tracer_->span_->name_, "test");
  116. ASSERT_EQ(mock_provider_ptr->tracer_->span_->status_.first, trace_api::StatusCode::kUnset);
  117. auto span_shim1 = tracer_shim->StartSpanWithOptions("test1", {.tags = {{"event", "normal"}}});
  118. ASSERT_TRUE(span_shim1 != nullptr);
  119. ASSERT_EQ(mock_provider_ptr->tracer_->span_->name_, "test1");
  120. ASSERT_EQ(mock_provider_ptr->tracer_->span_->status_.first, trace_api::StatusCode::kUnset);
  121. auto span_shim2 = tracer_shim->StartSpanWithOptions("test2", {.tags = {{"error", true}}});
  122. ASSERT_TRUE(span_shim2 != nullptr);
  123. ASSERT_EQ(mock_provider_ptr->tracer_->span_->name_, "test2");
  124. ASSERT_EQ(mock_provider_ptr->tracer_->span_->status_.first, trace_api::StatusCode::kError);
  125. auto span_shim3 = tracer_shim->StartSpanWithOptions("test3", {.tags = {{"error", "false"}}});
  126. ASSERT_TRUE(span_shim3 != nullptr);
  127. ASSERT_EQ(mock_provider_ptr->tracer_->span_->name_, "test3");
  128. ASSERT_EQ(mock_provider_ptr->tracer_->span_->status_.first, trace_api::StatusCode::kOk);
  129. }
  130. TEST_F(TracerShimTest, InjectInvalidCarrier)
  131. {
  132. auto span_shim = tracer_shim->StartSpan("a");
  133. auto result = tracer_shim->Inject(span_shim->context(), std::cout);
  134. ASSERT_TRUE(opentracing::are_errors_equal(result.error(), opentracing::invalid_carrier_error));
  135. }
  136. TEST_F(TracerShimTest, InjectNullContext)
  137. {
  138. std::unordered_map<std::string, std::string> text_map;
  139. auto noop_tracer = opentracing::MakeNoopTracer();
  140. auto span = noop_tracer->StartSpan("a");
  141. auto result = tracer_shim->Inject(span->context(), TextMapCarrier{text_map});
  142. ASSERT_TRUE(
  143. opentracing::are_errors_equal(result.error(), opentracing::invalid_span_context_error));
  144. ASSERT_TRUE(text_map.empty());
  145. }
  146. TEST_F(TracerShimTest, InjectTextMap)
  147. {
  148. ASSERT_FALSE(text_map_format->is_injected);
  149. ASSERT_FALSE(http_headers_format->is_injected);
  150. std::unordered_map<std::string, std::string> text_map;
  151. auto span_shim = tracer_shim->StartSpan("a");
  152. tracer_shim->Inject(span_shim->context(), TextMapCarrier{text_map});
  153. ASSERT_TRUE(text_map_format->is_injected);
  154. ASSERT_FALSE(http_headers_format->is_injected);
  155. }
  156. TEST_F(TracerShimTest, InjectHttpsHeaders)
  157. {
  158. ASSERT_FALSE(text_map_format->is_injected);
  159. ASSERT_FALSE(http_headers_format->is_injected);
  160. std::unordered_map<std::string, std::string> text_map;
  161. auto span_shim = tracer_shim->StartSpan("a");
  162. tracer_shim->Inject(span_shim->context(), HTTPHeadersCarrier{text_map});
  163. ASSERT_FALSE(text_map_format->is_injected);
  164. ASSERT_TRUE(http_headers_format->is_injected);
  165. }
  166. TEST_F(TracerShimTest, ExtractInvalidCarrier)
  167. {
  168. auto result = tracer_shim->Extract(std::cin);
  169. ASSERT_TRUE(opentracing::are_errors_equal(result.error(), opentracing::invalid_carrier_error));
  170. }
  171. TEST_F(TracerShimTest, ExtractNullContext)
  172. {
  173. std::unordered_map<std::string, std::string> text_map;
  174. auto result = tracer_shim->Extract(TextMapCarrier{text_map});
  175. ASSERT_EQ(result.value(), nullptr);
  176. }
  177. TEST_F(TracerShimTest, ExtractTextMap)
  178. {
  179. ASSERT_FALSE(text_map_format->is_extracted);
  180. ASSERT_FALSE(http_headers_format->is_extracted);
  181. std::unordered_map<std::string, std::string> text_map;
  182. auto result = tracer_shim->Extract(TextMapCarrier{text_map});
  183. ASSERT_EQ(result.value(), nullptr);
  184. ASSERT_TRUE(text_map_format->is_extracted);
  185. ASSERT_FALSE(http_headers_format->is_extracted);
  186. }
  187. TEST_F(TracerShimTest, ExtractHttpsHeaders)
  188. {
  189. ASSERT_FALSE(text_map_format->is_extracted);
  190. ASSERT_FALSE(http_headers_format->is_extracted);
  191. std::unordered_map<std::string, std::string> text_map;
  192. auto result = tracer_shim->Extract(HTTPHeadersCarrier{text_map});
  193. ASSERT_EQ(result.value(), nullptr);
  194. ASSERT_FALSE(text_map_format->is_extracted);
  195. ASSERT_TRUE(http_headers_format->is_extracted);
  196. }
  197. TEST_F(TracerShimTest, ExtractOnlyBaggage)
  198. {
  199. std::unordered_map<std::string, std::string> text_map;
  200. auto span_shim = tracer_shim->StartSpan("a");
  201. span_shim->SetBaggageItem("foo", "bar");
  202. ASSERT_EQ(span_shim->BaggageItem("foo"), "bar");
  203. tracer_shim->Inject(span_shim->context(), TextMapCarrier{text_map});
  204. auto span_context = tracer_shim->Extract(TextMapCarrier{text_map});
  205. ASSERT_TRUE(span_context.value() != nullptr);
  206. auto span_context_shim = static_cast<shim::SpanContextShim *>(span_context.value().get());
  207. ASSERT_TRUE(span_context_shim != nullptr);
  208. ASSERT_FALSE(span_context_shim->context().IsValid());
  209. ASSERT_FALSE(span_context_shim->context().IsSampled());
  210. ASSERT_FALSE(shim::utils::isBaggageEmpty(span_context_shim->baggage()));
  211. std::string value;
  212. ASSERT_TRUE(span_context_shim->BaggageItem("foo", value));
  213. ASSERT_EQ(value, "bar");
  214. }
  215. class TracerWithSpanContext : public trace_api::Tracer
  216. {
  217. public:
  218. nostd::shared_ptr<trace_api::Span> StartSpan(
  219. nostd::string_view name,
  220. const common::KeyValueIterable & /* attributes */,
  221. const trace_api::SpanContextKeyValueIterable & /* links */,
  222. const trace_api::StartSpanOptions & /* options */) noexcept override
  223. {
  224. constexpr uint8_t trace_id_buf[] = {1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8};
  225. trace_api::TraceId trace_id(trace_id_buf);
  226. constexpr uint8_t span_id_buf[] = {1, 2, 3, 4, 5, 6, 7, 8};
  227. trace_api::SpanId span_id(span_id_buf);
  228. auto span_context = trace_api::SpanContext(trace_id, span_id, GetTraceFlags(), false);
  229. nostd::shared_ptr<trace_api::Span> result(new trace_api::DefaultSpan(span_context));
  230. return result;
  231. }
  232. void ForceFlushWithMicroseconds(uint64_t /* timeout */) noexcept override {}
  233. void CloseWithMicroseconds(uint64_t /* timeout */) noexcept override {}
  234. static trace_api::TraceFlags GetTraceFlags()
  235. {
  236. return trace_api::TraceFlags(trace_api::TraceFlags::kIsSampled);
  237. }
  238. };
  239. class TracerWithSpanContextProvider : public trace_api::TracerProvider
  240. {
  241. public:
  242. static nostd::shared_ptr<trace_api::TracerProvider> Create()
  243. {
  244. nostd::shared_ptr<trace_api::TracerProvider> result(new TracerWithSpanContextProvider());
  245. return result;
  246. }
  247. #if OPENTELEMETRY_ABI_VERSION_NO >= 2
  248. nostd::shared_ptr<trace_api::Tracer> GetTracer(
  249. nostd::string_view /* name */,
  250. nostd::string_view /* version */,
  251. nostd::string_view /* schema_url */,
  252. const common::KeyValueIterable * /* attributes */) noexcept override
  253. {
  254. nostd::shared_ptr<trace_api::Tracer> result(new TracerWithSpanContext());
  255. return result;
  256. }
  257. #else
  258. nostd::shared_ptr<trace_api::Tracer> GetTracer(
  259. nostd::string_view /* name */,
  260. nostd::string_view /* version */,
  261. nostd::string_view /* schema_url */) noexcept override
  262. {
  263. nostd::shared_ptr<trace_api::Tracer> result(new TracerWithSpanContext());
  264. return result;
  265. }
  266. #endif
  267. };
  268. TEST_F(TracerShimTest, InjectSpanKey)
  269. {
  270. using context::propagation::TextMapPropagator;
  271. auto local_text_map_format = new MockPropagator();
  272. auto local_http_headers_format = new MockPropagator();
  273. ASSERT_FALSE(local_text_map_format->is_injected);
  274. ASSERT_FALSE(local_http_headers_format->is_injected);
  275. nostd::shared_ptr<trace_api::TracerProvider> tracer_provider =
  276. TracerWithSpanContextProvider::Create();
  277. auto local_tracer_shim = shim::TracerShim::createTracerShim(
  278. tracer_provider,
  279. {.text_map = nostd::shared_ptr<TextMapPropagator>(local_text_map_format),
  280. .http_headers = nostd::shared_ptr<TextMapPropagator>(local_http_headers_format)});
  281. std::unordered_map<std::string, std::string> text_map;
  282. auto span_shim = local_tracer_shim->StartSpan("a");
  283. local_tracer_shim->Inject(span_shim->context(), TextMapCarrier{text_map});
  284. ASSERT_TRUE(local_text_map_format->is_injected);
  285. ASSERT_FALSE(local_http_headers_format->is_injected);
  286. ASSERT_EQ(span_shim->context().ToTraceID(), text_map[MockPropagator::kTraceIdKey]);
  287. ASSERT_EQ(span_shim->context().ToSpanID(), text_map[MockPropagator::kSpanIdKey]);
  288. char flag_buffer[2];
  289. TracerWithSpanContext::GetTraceFlags().ToLowerBase16(flag_buffer);
  290. ASSERT_EQ(std::string(flag_buffer, 2), text_map[MockPropagator::kTraceFlagsKey]);
  291. }