otlp_file_client_test.cc 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557
  1. // Copyright The OpenTelemetry Authors
  2. // SPDX-License-Identifier: Apache-2.0
  3. #include <gtest/gtest.h>
  4. #include <chrono>
  5. #include <cstdint>
  6. #include <ctime>
  7. #include <fstream>
  8. #include <functional>
  9. #include <iostream>
  10. #include <nlohmann/json.hpp>
  11. #include <sstream>
  12. #include <string>
  13. #include <thread>
  14. #include <unordered_map>
  15. #include <utility>
  16. #include <vector>
  17. // IWYU pragma: no_include <features.h>
  18. #include "opentelemetry/common/timestamp.h"
  19. #include "opentelemetry/exporters/otlp/otlp_file_client.h"
  20. #include "opentelemetry/exporters/otlp/otlp_file_client_options.h"
  21. #include "opentelemetry/exporters/otlp/otlp_file_client_runtime_options.h"
  22. #include "opentelemetry/exporters/otlp/otlp_recordable.h"
  23. #include "opentelemetry/exporters/otlp/otlp_recordable_utils.h"
  24. #include "opentelemetry/nostd/shared_ptr.h"
  25. #include "opentelemetry/nostd/span.h"
  26. #include "opentelemetry/nostd/unique_ptr.h"
  27. #include "opentelemetry/nostd/variant.h"
  28. #include "opentelemetry/sdk/common/exporter_utils.h"
  29. #include "opentelemetry/sdk/instrumentationscope/instrumentation_scope.h"
  30. #include "opentelemetry/sdk/resource/resource.h"
  31. #include "opentelemetry/sdk/trace/recordable.h"
  32. #include "opentelemetry/trace/span_context.h"
  33. #include "opentelemetry/trace/span_id.h"
  34. #include "opentelemetry/trace/span_metadata.h"
  35. #include "opentelemetry/trace/trace_flags.h"
  36. #include "opentelemetry/trace/trace_id.h"
  37. #include "opentelemetry/trace/trace_state.h"
  38. #include "opentelemetry/version.h"
  39. // clang-format off
  40. #include "opentelemetry/exporters/otlp/protobuf_include_prefix.h" // IWYU pragma: keep
  41. #include <google/protobuf/message_lite.h>
  42. #include "opentelemetry/proto/collector/trace/v1/trace_service.pb.h"
  43. #include "opentelemetry/proto/trace/v1/trace.pb.h"
  44. #include "opentelemetry/exporters/otlp/protobuf_include_suffix.h" // IWYU pragma: keep
  45. // clang-format on
  46. using namespace testing;
  47. OPENTELEMETRY_BEGIN_NAMESPACE
  48. namespace exporter
  49. {
  50. namespace otlp
  51. {
  52. namespace resource = opentelemetry::sdk::resource;
  53. class ProtobufGlobalSymbolGuard
  54. {
  55. public:
  56. ProtobufGlobalSymbolGuard() {}
  57. ~ProtobufGlobalSymbolGuard() { google::protobuf::ShutdownProtobufLibrary(); }
  58. };
  59. static std::tm GetLocalTime(std::chrono::system_clock::time_point tp)
  60. {
  61. std::time_t now = std::chrono::system_clock::to_time_t(tp);
  62. #if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L) || defined(__STDC_LIB_EXT1__)
  63. std::tm ret;
  64. localtime_s(&now, &ret);
  65. #elif defined(_MSC_VER) && _MSC_VER >= 1300
  66. std::tm ret;
  67. localtime_s(&ret, &now);
  68. #elif defined(_XOPEN_SOURCE) || defined(_BSD_SOURCE) || defined(_SVID_SOURCE) || \
  69. defined(_POSIX_SOURCE)
  70. std::tm ret;
  71. localtime_r(&now, &ret);
  72. #else
  73. std::tm ret = *localtime(&now);
  74. #endif
  75. return ret;
  76. }
  77. template <class T, size_t N>
  78. static nostd::span<T, N> MakeSpan(T (&array)[N])
  79. {
  80. return nostd::span<T, N>(array);
  81. }
  82. static resource::Resource MakeResource()
  83. {
  84. static ProtobufGlobalSymbolGuard global_symbol_guard;
  85. resource::ResourceAttributes resource_attributes = {{"service.name", "unit_test_service"},
  86. {"tenant.id", "test_user"}};
  87. resource_attributes["bool_value"] = true;
  88. resource_attributes["int32_value"] = static_cast<int32_t>(1);
  89. resource_attributes["uint32_value"] = static_cast<uint32_t>(2);
  90. resource_attributes["int64_value"] = static_cast<int64_t>(0x1100000000LL);
  91. resource_attributes["uint64_value"] = static_cast<uint64_t>(0x1200000000ULL);
  92. resource_attributes["double_value"] = static_cast<double>(3.1);
  93. resource_attributes["vec_bool_value"] = std::vector<bool>{true, false, true};
  94. resource_attributes["vec_int32_value"] = std::vector<int32_t>{1, 2};
  95. resource_attributes["vec_uint32_value"] = std::vector<uint32_t>{3, 4};
  96. resource_attributes["vec_int64_value"] = std::vector<int64_t>{5, 6};
  97. resource_attributes["vec_uint64_value"] = std::vector<uint64_t>{7, 8};
  98. resource_attributes["vec_double_value"] = std::vector<double>{3.2, 3.3};
  99. resource_attributes["vec_string_value"] = std::vector<std::string>{"vector", "string"};
  100. return resource::Resource::Create(resource_attributes);
  101. }
  102. static opentelemetry::nostd::unique_ptr<
  103. opentelemetry::sdk::instrumentationscope::InstrumentationScope>
  104. MakeInstrumentationScope()
  105. {
  106. return opentelemetry::sdk::instrumentationscope::InstrumentationScope::Create(
  107. "otlp_file_client_test", "1.11.0", "https://opentelemetry.io/schemas/1.11.0");
  108. }
  109. static std::unique_ptr<opentelemetry::sdk::trace::Recordable> MakeRecordable(
  110. const resource::Resource &resource,
  111. const opentelemetry::sdk::instrumentationscope::InstrumentationScope &instrumentation_scope)
  112. {
  113. OtlpRecordable *recordable = new OtlpRecordable();
  114. recordable->SetResource(resource);
  115. recordable->SetInstrumentationScope(instrumentation_scope);
  116. recordable->SetName("otlp_file_client_test_span");
  117. recordable->SetSpanKind(opentelemetry::trace::SpanKind::kInternal);
  118. recordable->SetAttribute("test-attribute-key", "test-attribute-value");
  119. recordable->SetDuration(std::chrono::nanoseconds(1234567890));
  120. recordable->SetStartTime(
  121. opentelemetry::common::SystemTimestamp(std::chrono::system_clock::now()));
  122. recordable->SetStatus(opentelemetry::trace::StatusCode::kOk, "success");
  123. {
  124. constexpr uint8_t trace_id_buf[] = {1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8};
  125. constexpr uint8_t span_id_buf[] = {1, 2, 3, 4, 5, 6, 7, 8};
  126. constexpr uint8_t parent_span_id_buf[] = {8, 7, 6, 5, 4, 3, 2, 1};
  127. opentelemetry::trace::TraceId trace_id{trace_id_buf};
  128. opentelemetry::trace::SpanId span_id{span_id_buf};
  129. opentelemetry::trace::SpanId parent_span_id{parent_span_id_buf};
  130. const auto trace_state = opentelemetry::trace::TraceState::GetDefault()->Set("key1", "value");
  131. const opentelemetry::trace::SpanContext span_context{
  132. trace_id, span_id,
  133. opentelemetry::trace::TraceFlags{opentelemetry::trace::TraceFlags::kIsSampled}, true,
  134. trace_state};
  135. recordable->SetIdentity(span_context, parent_span_id);
  136. }
  137. return std::unique_ptr<opentelemetry::sdk::trace::Recordable>(recordable);
  138. }
  139. TEST(OtlpFileClientTest, Shutdown)
  140. {
  141. opentelemetry::proto::collector::trace::v1::ExportTraceServiceRequest request;
  142. auto client = std::unique_ptr<opentelemetry::exporter::otlp::OtlpFileClient>(
  143. new opentelemetry::exporter::otlp::OtlpFileClient(
  144. opentelemetry::exporter::otlp::OtlpFileClientOptions(),
  145. opentelemetry::exporter::otlp::OtlpFileClientRuntimeOptions()));
  146. ASSERT_FALSE(client->IsShutdown());
  147. ASSERT_TRUE(client->Shutdown());
  148. ASSERT_TRUE(client->IsShutdown());
  149. auto result = client->Export(request, 1);
  150. EXPECT_EQ(result, opentelemetry::sdk::common::ExportResult::kFailure);
  151. }
  152. TEST(OtlpFileClientTest, ExportToOstreamTest)
  153. {
  154. auto resource = MakeResource();
  155. auto instrumentation_scope = MakeInstrumentationScope();
  156. std::unique_ptr<opentelemetry::sdk::trace::Recordable> recordable[] = {
  157. MakeRecordable(resource, *instrumentation_scope)};
  158. opentelemetry::proto::collector::trace::v1::ExportTraceServiceRequest request;
  159. OtlpRecordableUtils::PopulateRequest(MakeSpan(recordable), &request);
  160. std::stringstream output_stream;
  161. opentelemetry::exporter::otlp::OtlpFileClientOptions opts;
  162. opentelemetry::exporter::otlp::OtlpFileClientRuntimeOptions rt_opts;
  163. opts.backend_options = std::ref(output_stream);
  164. auto client = std::unique_ptr<opentelemetry::exporter::otlp::OtlpFileClient>(
  165. new opentelemetry::exporter::otlp::OtlpFileClient(std::move(opts), std::move(rt_opts)));
  166. client->Export(request, 1);
  167. {
  168. auto check_json = nlohmann::json::parse(output_stream.str(), nullptr, false);
  169. auto resource_span = *check_json["resourceSpans"].begin();
  170. auto scope_span = *resource_span["scopeSpans"].begin();
  171. auto span = *scope_span["spans"].begin();
  172. auto received_trace_id = span["traceId"].get<std::string>();
  173. EXPECT_EQ(received_trace_id, "01020304050607080102030405060708");
  174. auto received_name = span["name"].get<std::string>();
  175. EXPECT_EQ(received_name, request.resource_spans(0).scope_spans(0).spans(0).name());
  176. auto receivec_attributes = span["attributes"];
  177. int attribute_found = 0;
  178. for (auto iter = receivec_attributes.begin(); iter != receivec_attributes.end(); ++iter)
  179. {
  180. auto key = (*iter)["key"].get<std::string>();
  181. if (key == "test-attribute-key")
  182. {
  183. auto value = (*iter)["value"]["stringValue"];
  184. ++attribute_found;
  185. EXPECT_EQ(value.get<std::string>(), "test-attribute-value");
  186. }
  187. }
  188. EXPECT_EQ(attribute_found, 1);
  189. auto receivec_resource_attributes = resource_span["resource"]["attributes"];
  190. for (auto iter = receivec_resource_attributes.begin();
  191. iter != receivec_resource_attributes.end(); ++iter)
  192. {
  193. auto key = (*iter)["key"].get<std::string>();
  194. if (key == "service.name")
  195. {
  196. auto value = (*iter)["value"]["stringValue"];
  197. ++attribute_found;
  198. EXPECT_EQ(value.get<std::string>(), "unit_test_service");
  199. }
  200. else if (key == "tenant.id")
  201. {
  202. auto value = (*iter)["value"]["stringValue"];
  203. ++attribute_found;
  204. EXPECT_EQ(value.get<std::string>(), "test_user");
  205. }
  206. else if (key == "int32_value")
  207. {
  208. auto value = (*iter)["value"]["intValue"];
  209. ++attribute_found;
  210. if (value.is_number())
  211. {
  212. EXPECT_EQ(value.get<int32_t>(), 1);
  213. }
  214. else
  215. {
  216. EXPECT_EQ(value.get<std::string>(), "1");
  217. }
  218. }
  219. }
  220. EXPECT_EQ(attribute_found, 4);
  221. }
  222. }
  223. TEST(OtlpFileClientTest, ExportToFileSystemRotateIndexTest)
  224. {
  225. auto resource = MakeResource();
  226. auto instrumentation_scope = MakeInstrumentationScope();
  227. std::unique_ptr<opentelemetry::sdk::trace::Recordable> recordable[] = {
  228. MakeRecordable(resource, *instrumentation_scope)};
  229. opentelemetry::proto::collector::trace::v1::ExportTraceServiceRequest request;
  230. OtlpRecordableUtils::PopulateRequest(MakeSpan(recordable), &request);
  231. std::stringstream output_stream;
  232. // Clear old files
  233. {
  234. std::fstream clear_file1("otlp_file_client_test_dir/trace-1.jsonl",
  235. std::ios::out | std::ios::trunc);
  236. std::fstream clear_file2("otlp_file_client_test_dir/trace-2.jsonl",
  237. std::ios::out | std::ios::trunc);
  238. std::fstream clear_file3("otlp_file_client_test_dir/trace-3.jsonl",
  239. std::ios::out | std::ios::trunc);
  240. std::fstream clear_file4("otlp_file_client_test_dir/trace-latest.jsonl",
  241. std::ios::out | std::ios::trunc);
  242. }
  243. opentelemetry::exporter::otlp::OtlpFileClientFileSystemOptions backend_opts;
  244. backend_opts.file_pattern = "otlp_file_client_test_dir/trace-%n.jsonl";
  245. backend_opts.alias_pattern = "otlp_file_client_test_dir/trace-latest.jsonl";
  246. // Smaller than the size of one record, so it will rotate after each record.
  247. backend_opts.file_size = 1500;
  248. backend_opts.rotate_size = 3;
  249. opentelemetry::exporter::otlp::OtlpFileClientOptions opts;
  250. opentelemetry::exporter::otlp::OtlpFileClientRuntimeOptions rt_opts;
  251. opts.backend_options = backend_opts;
  252. auto client = std::unique_ptr<opentelemetry::exporter::otlp::OtlpFileClient>(
  253. new opentelemetry::exporter::otlp::OtlpFileClient(std::move(opts), std::move(rt_opts)));
  254. // Write 5 records with rotatation index 1,2,3,1,2
  255. for (int i = 0; i < 4; ++i)
  256. {
  257. client->Export(request, 1);
  258. }
  259. request.mutable_resource_spans(0)->set_schema_url("https://opentelemetry.io/schemas/1.12.0");
  260. client->Export(request, 1);
  261. client->ForceFlush();
  262. std::unique_ptr<std::ifstream> input_file[5] = {
  263. std::unique_ptr<std::ifstream>(
  264. new std::ifstream("otlp_file_client_test_dir/trace-1.jsonl", std::ios::in)),
  265. std::unique_ptr<std::ifstream>(
  266. new std::ifstream("otlp_file_client_test_dir/trace-2.jsonl", std::ios::in)),
  267. std::unique_ptr<std::ifstream>(
  268. new std::ifstream("otlp_file_client_test_dir/trace-3.jsonl", std::ios::in)),
  269. std::unique_ptr<std::ifstream>(
  270. new std::ifstream("otlp_file_client_test_dir/trace-4.jsonl", std::ios::in)),
  271. std::unique_ptr<std::ifstream>(
  272. new std::ifstream("otlp_file_client_test_dir/trace-latest.jsonl", std::ios::in))};
  273. EXPECT_TRUE(input_file[0]->is_open());
  274. EXPECT_TRUE(input_file[1]->is_open());
  275. EXPECT_TRUE(input_file[2]->is_open());
  276. EXPECT_FALSE(input_file[3]->is_open());
  277. EXPECT_TRUE(input_file[4]->is_open());
  278. std::string jsonl[4];
  279. std::getline(*input_file[0], jsonl[0]);
  280. std::getline(*input_file[1], jsonl[1]);
  281. std::getline(*input_file[2], jsonl[2]);
  282. std::getline(*input_file[4], jsonl[3]);
  283. EXPECT_EQ(jsonl[0], jsonl[2]);
  284. EXPECT_EQ(jsonl[1], jsonl[3]);
  285. {
  286. auto check_json = nlohmann::json::parse(jsonl[0], nullptr, false);
  287. auto resource_span = *check_json["resourceSpans"].begin();
  288. auto scope_span = *resource_span["scopeSpans"].begin();
  289. auto span = *scope_span["spans"].begin();
  290. auto received_trace_id = span["traceId"].get<std::string>();
  291. EXPECT_EQ(received_trace_id, "01020304050607080102030405060708");
  292. auto received_name = span["name"].get<std::string>();
  293. EXPECT_EQ(received_name, request.resource_spans(0).scope_spans(0).spans(0).name());
  294. auto receivec_attributes = span["attributes"];
  295. int attribute_found = 0;
  296. for (auto iter = receivec_attributes.begin(); iter != receivec_attributes.end(); ++iter)
  297. {
  298. auto key = (*iter)["key"].get<std::string>();
  299. if (key == "test-attribute-key")
  300. {
  301. auto value = (*iter)["value"]["stringValue"];
  302. ++attribute_found;
  303. EXPECT_EQ(value.get<std::string>(), "test-attribute-value");
  304. }
  305. }
  306. EXPECT_EQ(attribute_found, 1);
  307. auto receivec_resource_attributes = resource_span["resource"]["attributes"];
  308. for (auto iter = receivec_resource_attributes.begin();
  309. iter != receivec_resource_attributes.end(); ++iter)
  310. {
  311. auto key = (*iter)["key"].get<std::string>();
  312. if (key == "service.name")
  313. {
  314. auto value = (*iter)["value"]["stringValue"];
  315. ++attribute_found;
  316. EXPECT_EQ(value.get<std::string>(), "unit_test_service");
  317. }
  318. else if (key == "tenant.id")
  319. {
  320. auto value = (*iter)["value"]["stringValue"];
  321. ++attribute_found;
  322. EXPECT_EQ(value.get<std::string>(), "test_user");
  323. }
  324. else if (key == "int32_value")
  325. {
  326. auto value = (*iter)["value"]["intValue"];
  327. ++attribute_found;
  328. if (value.is_number())
  329. {
  330. EXPECT_EQ(value.get<int32_t>(), 1);
  331. }
  332. else
  333. {
  334. EXPECT_EQ(value.get<std::string>(), "1");
  335. }
  336. }
  337. }
  338. EXPECT_EQ(attribute_found, 4);
  339. }
  340. }
  341. TEST(OtlpFileClientTest, ExportToFileSystemRotateByTimeTest)
  342. {
  343. auto resource = MakeResource();
  344. auto instrumentation_scope = MakeInstrumentationScope();
  345. std::unique_ptr<opentelemetry::sdk::trace::Recordable> recordable[] = {
  346. MakeRecordable(resource, *instrumentation_scope)};
  347. opentelemetry::proto::collector::trace::v1::ExportTraceServiceRequest request;
  348. OtlpRecordableUtils::PopulateRequest(MakeSpan(recordable), &request);
  349. std::stringstream output_stream;
  350. opentelemetry::exporter::otlp::OtlpFileClientFileSystemOptions backend_opts;
  351. backend_opts.file_pattern = "otlp_file_client_test_dir/trace-%Y-%m-%d-%H-%M-%S.jsonl";
  352. backend_opts.alias_pattern = "";
  353. // Smaller than the size of one record, so it will rotate after each record.
  354. backend_opts.file_size = 1500;
  355. opentelemetry::exporter::otlp::OtlpFileClientOptions opts;
  356. opentelemetry::exporter::otlp::OtlpFileClientRuntimeOptions rt_opts;
  357. opts.backend_options = backend_opts;
  358. auto client = std::unique_ptr<opentelemetry::exporter::otlp::OtlpFileClient>(
  359. new opentelemetry::exporter::otlp::OtlpFileClient(std::move(opts), std::move(rt_opts)));
  360. auto start_time = std::chrono::system_clock::now();
  361. client->Export(request, 1);
  362. std::this_thread::sleep_for(std::chrono::seconds{1});
  363. client->Export(request, 1);
  364. client->ForceFlush();
  365. std::unique_ptr<std::ifstream> input_file[2];
  366. std::size_t found_file_index = 0;
  367. // Try to load the file in 5s, it should finished.
  368. for (int i = 0; i < 5; ++i)
  369. {
  370. char file_path_buf[256] = {0};
  371. std::tm local_tm = GetLocalTime(start_time);
  372. std::strftime(file_path_buf, sizeof(file_path_buf) - 1,
  373. "otlp_file_client_test_dir/trace-%Y-%m-%d-%H-%M-%S.jsonl", &local_tm);
  374. start_time += std::chrono::seconds{1};
  375. input_file[found_file_index] =
  376. std::unique_ptr<std::ifstream>(new std::ifstream(file_path_buf, std::ios::in));
  377. if (input_file[found_file_index]->is_open())
  378. {
  379. ++found_file_index;
  380. }
  381. if (found_file_index >= 2)
  382. {
  383. break;
  384. }
  385. }
  386. ASSERT_EQ(found_file_index, 2);
  387. std::string jsonl[2];
  388. std::getline(*input_file[0], jsonl[0]);
  389. std::getline(*input_file[1], jsonl[1]);
  390. EXPECT_EQ(jsonl[0], jsonl[1]);
  391. {
  392. auto check_json = nlohmann::json::parse(jsonl[0], nullptr, false);
  393. auto resource_span = *check_json["resourceSpans"].begin();
  394. auto scope_span = *resource_span["scopeSpans"].begin();
  395. auto span = *scope_span["spans"].begin();
  396. auto received_trace_id = span["traceId"].get<std::string>();
  397. EXPECT_EQ(received_trace_id, "01020304050607080102030405060708");
  398. auto received_name = span["name"].get<std::string>();
  399. EXPECT_EQ(received_name, request.resource_spans(0).scope_spans(0).spans(0).name());
  400. auto receivec_attributes = span["attributes"];
  401. int attribute_found = 0;
  402. for (auto iter = receivec_attributes.begin(); iter != receivec_attributes.end(); ++iter)
  403. {
  404. auto key = (*iter)["key"].get<std::string>();
  405. if (key == "test-attribute-key")
  406. {
  407. auto value = (*iter)["value"]["stringValue"];
  408. ++attribute_found;
  409. EXPECT_EQ(value.get<std::string>(), "test-attribute-value");
  410. }
  411. }
  412. EXPECT_EQ(attribute_found, 1);
  413. auto receivec_resource_attributes = resource_span["resource"]["attributes"];
  414. for (auto iter = receivec_resource_attributes.begin();
  415. iter != receivec_resource_attributes.end(); ++iter)
  416. {
  417. auto key = (*iter)["key"].get<std::string>();
  418. if (key == "service.name")
  419. {
  420. auto value = (*iter)["value"]["stringValue"];
  421. ++attribute_found;
  422. EXPECT_EQ(value.get<std::string>(), "unit_test_service");
  423. }
  424. else if (key == "tenant.id")
  425. {
  426. auto value = (*iter)["value"]["stringValue"];
  427. ++attribute_found;
  428. EXPECT_EQ(value.get<std::string>(), "test_user");
  429. }
  430. else if (key == "int32_value")
  431. {
  432. auto value = (*iter)["value"]["intValue"];
  433. ++attribute_found;
  434. if (value.is_number())
  435. {
  436. EXPECT_EQ(value.get<int32_t>(), 1);
  437. }
  438. else
  439. {
  440. EXPECT_EQ(value.get<std::string>(), "1");
  441. }
  442. }
  443. }
  444. EXPECT_EQ(attribute_found, 4);
  445. }
  446. }
  447. // Test client configuration options
  448. TEST(OtlpFileClientTest, ConfigTest)
  449. {
  450. {
  451. opentelemetry::exporter::otlp::OtlpFileClientOptions opts;
  452. opentelemetry::exporter::otlp::OtlpFileClientRuntimeOptions rt_opts;
  453. opts.console_debug = true;
  454. opts.backend_options = std::ref(std::cout);
  455. auto client = std::unique_ptr<opentelemetry::exporter::otlp::OtlpFileClient>(
  456. new opentelemetry::exporter::otlp::OtlpFileClient(std::move(opts), std::move(rt_opts)));
  457. ASSERT_TRUE(client->GetOptions().console_debug);
  458. ASSERT_TRUE(opentelemetry::nostd::holds_alternative<std::reference_wrapper<std::ostream>>(
  459. client->GetOptions().backend_options));
  460. }
  461. {
  462. opentelemetry::exporter::otlp::OtlpFileClientFileSystemOptions backend_opts;
  463. backend_opts.file_pattern = "test_file_pattern.jsonl";
  464. opentelemetry::exporter::otlp::OtlpFileClientOptions opts;
  465. opentelemetry::exporter::otlp::OtlpFileClientRuntimeOptions rt_opts;
  466. opts.console_debug = false;
  467. opts.backend_options = backend_opts;
  468. auto client = std::unique_ptr<opentelemetry::exporter::otlp::OtlpFileClient>(
  469. new opentelemetry::exporter::otlp::OtlpFileClient(std::move(opts), std::move(rt_opts)));
  470. ASSERT_FALSE(client->GetOptions().console_debug);
  471. ASSERT_TRUE(opentelemetry::nostd::holds_alternative<
  472. opentelemetry::exporter::otlp::OtlpFileClientFileSystemOptions>(
  473. client->GetOptions().backend_options));
  474. EXPECT_EQ(
  475. opentelemetry::nostd::get<opentelemetry::exporter::otlp::OtlpFileClientFileSystemOptions>(
  476. client->GetOptions().backend_options)
  477. .file_pattern,
  478. "test_file_pattern.jsonl");
  479. }
  480. }
  481. } // namespace otlp
  482. } // namespace exporter
  483. OPENTELEMETRY_END_NAMESPACE