logger_sdk_test.cc 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546
  1. // Copyright The OpenTelemetry Authors
  2. // SPDX-License-Identifier: Apache-2.0
  3. #include <gtest/gtest.h>
  4. #include <stdint.h>
  5. #include <algorithm>
  6. #include <array>
  7. #include <chrono>
  8. #include <functional>
  9. #include <string>
  10. #include <utility>
  11. #include <vector>
  12. #include "opentelemetry/common/attribute_value.h"
  13. #include "opentelemetry/common/timestamp.h"
  14. #include "opentelemetry/logs/event_logger.h"
  15. #include "opentelemetry/logs/event_logger_provider.h"
  16. #include "opentelemetry/logs/log_record.h"
  17. #include "opentelemetry/logs/logger.h"
  18. #include "opentelemetry/logs/logger_provider.h"
  19. #include "opentelemetry/logs/noop.h"
  20. #include "opentelemetry/logs/severity.h"
  21. #include "opentelemetry/nostd/shared_ptr.h"
  22. #include "opentelemetry/nostd/span.h"
  23. #include "opentelemetry/nostd/string_view.h"
  24. #include "opentelemetry/nostd/variant.h"
  25. #include "opentelemetry/sdk/instrumentationscope/instrumentation_scope.h"
  26. #include "opentelemetry/sdk/instrumentationscope/scope_configurator.h"
  27. #include "opentelemetry/sdk/logs/event_logger_provider.h"
  28. #include "opentelemetry/sdk/logs/logger.h"
  29. #include "opentelemetry/sdk/logs/logger_config.h"
  30. #include "opentelemetry/sdk/logs/logger_provider.h"
  31. #include "opentelemetry/sdk/logs/processor.h"
  32. #include "opentelemetry/sdk/logs/recordable.h"
  33. #include "opentelemetry/sdk/resource/resource.h"
  34. #include "opentelemetry/sdk/trace/processor.h"
  35. #include "opentelemetry/sdk/trace/tracer_provider.h"
  36. #include "opentelemetry/sdk/trace/tracer_provider_factory.h"
  37. #include "opentelemetry/trace/scope.h"
  38. #include "opentelemetry/trace/span.h"
  39. #include "opentelemetry/trace/span_context.h"
  40. #include "opentelemetry/trace/span_id.h"
  41. #include "opentelemetry/trace/trace_flags.h"
  42. #include "opentelemetry/trace/trace_id.h"
  43. #include "opentelemetry/trace/tracer.h"
  44. using namespace opentelemetry::sdk::logs;
  45. using namespace opentelemetry::sdk::instrumentationscope;
  46. namespace logs_api = opentelemetry::logs;
  47. namespace nostd = opentelemetry::nostd;
  48. TEST(LoggerSDK, LogToNullProcessor)
  49. {
  50. // Confirm Logger::EmitLogRecord() does not have undefined behavior
  51. // even when there is no processor set
  52. // since it calls Processor::OnEmit()
  53. auto lp = std::shared_ptr<logs_api::LoggerProvider>(new LoggerProvider());
  54. const std::string schema_url{"https://opentelemetry.io/schemas/1.11.0"};
  55. auto logger = lp->GetLogger("logger", "opentelelemtry_library", "", schema_url);
  56. auto sdk_logger = static_cast<opentelemetry::sdk::logs::Logger *>(logger.get());
  57. ASSERT_EQ(sdk_logger->GetInstrumentationScope().GetName(), "opentelelemtry_library");
  58. ASSERT_EQ(sdk_logger->GetInstrumentationScope().GetVersion(), "");
  59. ASSERT_EQ(sdk_logger->GetInstrumentationScope().GetSchemaURL(), schema_url);
  60. // Log a sample log record to a nullptr processor
  61. logger->Debug("Test log");
  62. }
  63. class MockLogRecordable final : public opentelemetry::sdk::logs::Recordable
  64. {
  65. public:
  66. void SetTimestamp(opentelemetry::common::SystemTimestamp) noexcept override {}
  67. void SetObservedTimestamp(
  68. opentelemetry::common::SystemTimestamp observed_timestamp) noexcept override
  69. {
  70. observed_timestamp_ = observed_timestamp;
  71. }
  72. const opentelemetry::common::SystemTimestamp &GetObservedTimestamp() const noexcept
  73. {
  74. return observed_timestamp_;
  75. }
  76. opentelemetry::logs::Severity GetSeverity() const noexcept { return severity_; }
  77. void SetSeverity(opentelemetry::logs::Severity severity) noexcept override
  78. {
  79. severity_ = severity;
  80. }
  81. nostd::string_view GetBody() const noexcept { return body_; }
  82. void SetBody(const opentelemetry::common::AttributeValue &message) noexcept override
  83. {
  84. if (nostd::holds_alternative<const char *>(message))
  85. {
  86. body_ = nostd::get<const char *>(message);
  87. }
  88. else if (nostd::holds_alternative<nostd::string_view>(message))
  89. {
  90. body_ = static_cast<std::string>(nostd::get<nostd::string_view>(message));
  91. }
  92. }
  93. void SetBody(const std::string &message) noexcept { body_ = message; }
  94. void SetEventId(int64_t id, nostd::string_view name) noexcept override
  95. {
  96. event_id_ = id;
  97. log_record_event_name_ = static_cast<std::string>(name);
  98. }
  99. void SetTraceId(const opentelemetry::trace::TraceId &trace_id) noexcept override
  100. {
  101. trace_id_ = trace_id;
  102. }
  103. inline const opentelemetry::trace::TraceId &GetTraceId() const noexcept { return trace_id_; }
  104. void SetSpanId(const opentelemetry::trace::SpanId &span_id) noexcept override
  105. {
  106. span_id_ = span_id;
  107. }
  108. inline const opentelemetry::trace::SpanId &GetSpanId() const noexcept { return span_id_; }
  109. void SetTraceFlags(const opentelemetry::trace::TraceFlags &trace_flags) noexcept override
  110. {
  111. trace_flags_ = trace_flags;
  112. }
  113. inline const opentelemetry::trace::TraceFlags &GetTraceFlags() const noexcept
  114. {
  115. return trace_flags_;
  116. }
  117. void SetAttribute(nostd::string_view key,
  118. const opentelemetry::common::AttributeValue &value) noexcept override
  119. {
  120. if (!nostd::holds_alternative<nostd::string_view>(value))
  121. {
  122. return;
  123. }
  124. if (key == "event.domain")
  125. {
  126. event_domain_ = static_cast<std::string>(nostd::get<nostd::string_view>(value));
  127. }
  128. else if (key == "event.name")
  129. {
  130. event_name_ = static_cast<std::string>(nostd::get<nostd::string_view>(value));
  131. }
  132. }
  133. inline const std::string &GetEventName() const noexcept { return event_name_; }
  134. inline const std::string &GetEventDomain() const noexcept { return event_domain_; }
  135. void SetResource(const opentelemetry::sdk::resource::Resource &) noexcept override {}
  136. void SetInstrumentationScope(
  137. const opentelemetry::sdk::instrumentationscope::InstrumentationScope &) noexcept override
  138. {}
  139. void CopyFrom(const MockLogRecordable &other)
  140. {
  141. severity_ = other.severity_;
  142. body_ = other.body_;
  143. trace_id_ = other.trace_id_;
  144. span_id_ = other.span_id_;
  145. trace_flags_ = other.trace_flags_;
  146. event_name_ = other.event_name_;
  147. event_domain_ = other.event_domain_;
  148. observed_timestamp_ = other.observed_timestamp_;
  149. }
  150. private:
  151. opentelemetry::logs::Severity severity_ = opentelemetry::logs::Severity::kInvalid;
  152. std::string body_;
  153. int64_t event_id_;
  154. std::string log_record_event_name_;
  155. opentelemetry::trace::TraceId trace_id_;
  156. opentelemetry::trace::SpanId span_id_;
  157. opentelemetry::trace::TraceFlags trace_flags_;
  158. std::string event_name_;
  159. std::string event_domain_;
  160. opentelemetry::common::SystemTimestamp observed_timestamp_ =
  161. std::chrono::system_clock::from_time_t(0);
  162. };
  163. class MockProcessor final : public LogRecordProcessor
  164. {
  165. private:
  166. std::shared_ptr<MockLogRecordable> record_received_;
  167. public:
  168. // A processor used for testing that keeps a track of the recordable it received
  169. explicit MockProcessor(std::shared_ptr<MockLogRecordable> record_received) noexcept
  170. : record_received_(std::move(record_received))
  171. {}
  172. std::unique_ptr<opentelemetry::sdk::logs::Recordable> MakeRecordable() noexcept override
  173. {
  174. return std::unique_ptr<opentelemetry::sdk::logs::Recordable>(new MockLogRecordable());
  175. }
  176. // OnEmit stores the record it receives into the shared_ptr recordable passed into its
  177. // constructor
  178. void OnEmit(std::unique_ptr<opentelemetry::sdk::logs::Recordable> &&record) noexcept override
  179. {
  180. // Cast the recordable received into a concrete MockLogRecordable type
  181. auto copy =
  182. std::shared_ptr<MockLogRecordable>(static_cast<MockLogRecordable *>(record.release()));
  183. // Copy over the received log record's severity, name, and body fields over to the recordable
  184. // passed in the constructor
  185. record_received_->CopyFrom(*copy);
  186. }
  187. bool ForceFlush(std::chrono::microseconds /* timeout */) noexcept override { return true; }
  188. bool Shutdown(std::chrono::microseconds /* timeout */) noexcept override { return true; }
  189. };
  190. TEST(LoggerSDK, LogToAProcessor)
  191. {
  192. // Create an API LoggerProvider and logger
  193. auto api_lp = std::shared_ptr<logs_api::LoggerProvider>(new LoggerProvider());
  194. const std::string schema_url{"https://opentelemetry.io/schemas/1.11.0"};
  195. auto logger = api_lp->GetLogger("logger", "opentelelemtry_library", "", schema_url);
  196. // Cast the API LoggerProvider to an SDK Logger Provider and assert that it is still the same
  197. // LoggerProvider by checking that getting a logger with the same name as the previously defined
  198. // logger is the same instance
  199. auto lp = static_cast<LoggerProvider *>(api_lp.get());
  200. auto logger2 = lp->GetLogger("logger", "opentelelemtry_library", "", schema_url);
  201. ASSERT_EQ(logger, logger2);
  202. nostd::shared_ptr<opentelemetry::trace::Span> include_span;
  203. {
  204. std::vector<std::unique_ptr<opentelemetry::sdk::trace::SpanProcessor>> span_processors;
  205. auto trace_provider =
  206. opentelemetry::sdk::trace::TracerProviderFactory::Create(std::move(span_processors));
  207. include_span = trace_provider->GetTracer("logger")->StartSpan("test_logger");
  208. }
  209. opentelemetry::trace::Scope trace_scope{include_span};
  210. auto now = std::chrono::system_clock::now();
  211. auto sdk_logger = static_cast<opentelemetry::sdk::logs::Logger *>(logger.get());
  212. ASSERT_EQ(sdk_logger->GetInstrumentationScope().GetName(), "opentelelemtry_library");
  213. ASSERT_EQ(sdk_logger->GetInstrumentationScope().GetVersion(), "");
  214. ASSERT_EQ(sdk_logger->GetInstrumentationScope().GetSchemaURL(), schema_url);
  215. // Set a processor for the LoggerProvider
  216. auto shared_recordable = std::shared_ptr<MockLogRecordable>(new MockLogRecordable());
  217. lp->AddProcessor(std::unique_ptr<opentelemetry::sdk::logs::LogRecordProcessor>(
  218. new MockProcessor(shared_recordable)));
  219. // Check that the recordable created by the EmitLogRecord() statement is set properly
  220. logger->EmitLogRecord(logs_api::Severity::kWarn, "Log Message");
  221. ASSERT_EQ(shared_recordable->GetSeverity(), logs_api::Severity::kWarn);
  222. ASSERT_EQ(shared_recordable->GetBody(), "Log Message");
  223. ASSERT_EQ(shared_recordable->GetTraceFlags().flags(),
  224. include_span->GetContext().trace_flags().flags());
  225. char trace_id_in_logger[opentelemetry::trace::TraceId::kSize * 2];
  226. char trace_id_in_span[opentelemetry::trace::TraceId::kSize * 2];
  227. char span_id_in_logger[opentelemetry::trace::SpanId::kSize * 2];
  228. char span_id_in_span[opentelemetry::trace::SpanId::kSize * 2];
  229. shared_recordable->GetTraceId().ToLowerBase16(trace_id_in_logger);
  230. include_span->GetContext().trace_id().ToLowerBase16(trace_id_in_span);
  231. shared_recordable->GetSpanId().ToLowerBase16(span_id_in_logger);
  232. include_span->GetContext().span_id().ToLowerBase16(span_id_in_span);
  233. std::string trace_id_text_in_logger{trace_id_in_logger, sizeof(trace_id_in_logger)};
  234. std::string trace_id_text_in_span{trace_id_in_span, sizeof(trace_id_in_span)};
  235. std::string span_id_text_in_logger{span_id_in_logger, sizeof(span_id_in_logger)};
  236. std::string span_id_text_in_span{span_id_in_span, sizeof(span_id_in_span)};
  237. ASSERT_EQ(trace_id_text_in_logger, trace_id_text_in_span);
  238. ASSERT_EQ(span_id_text_in_logger, span_id_text_in_span);
  239. ASSERT_GE(
  240. static_cast<std::chrono::system_clock::time_point>(shared_recordable->GetObservedTimestamp()),
  241. now);
  242. }
  243. TEST(LoggerSDK, LoggerWithDisabledConfig)
  244. {
  245. ScopeConfigurator<LoggerConfig> disabled_all_scopes =
  246. ScopeConfigurator<LoggerConfig>::Builder(LoggerConfig::Disabled()).Build();
  247. // Set a processor for the LoggerProvider
  248. auto shared_recordable = std::shared_ptr<MockLogRecordable>(new MockLogRecordable());
  249. auto log_processor = std::unique_ptr<LogRecordProcessor>(new MockProcessor(shared_recordable));
  250. // Create an API LoggerProvider and logger
  251. const auto resource = opentelemetry::sdk::resource::Resource::Create({});
  252. const std::string schema_url{"https://opentelemetry.io/schemas/1.11.0"};
  253. auto api_lp = std::shared_ptr<logs_api::LoggerProvider>(
  254. new LoggerProvider(std::move(log_processor), resource,
  255. std::make_unique<ScopeConfigurator<LoggerConfig>>(disabled_all_scopes)));
  256. auto logger = api_lp->GetLogger("logger", "opentelelemtry_library", "", schema_url);
  257. auto noop_logger = logs_api::NoopLogger();
  258. // Test Logger functions for the constructed logger
  259. // This logger should behave like a noop logger
  260. ASSERT_EQ(logger->GetName(), noop_logger.GetName());
  261. // Since the logger is disabled, when creating a LogRecord, the observed timestamp will not be
  262. // set in the underlying LogRecordable
  263. auto log_record = logger->CreateLogRecord();
  264. logger->EmitLogRecord(std::move(log_record));
  265. ASSERT_EQ(shared_recordable->GetObservedTimestamp(), std::chrono::system_clock::from_time_t(0));
  266. // Since this logger should behave like a noop logger, no values within the recordable would be
  267. // set.
  268. logger->EmitLogRecord(logs_api::Severity::kWarn, "Log Message");
  269. ASSERT_EQ(shared_recordable->GetBody(), "");
  270. ASSERT_EQ(shared_recordable->GetSeverity(), opentelemetry::logs::Severity::kInvalid);
  271. ASSERT_EQ(shared_recordable->GetObservedTimestamp(), std::chrono::system_clock::from_time_t(0));
  272. }
  273. TEST(LoggerSDK, LoggerWithEnabledConfig)
  274. {
  275. ScopeConfigurator<LoggerConfig> enabled_all_scopes =
  276. ScopeConfigurator<LoggerConfig>::Builder(LoggerConfig::Enabled()).Build();
  277. // Set a processor for the LoggerProvider
  278. auto shared_recordable = std::shared_ptr<MockLogRecordable>(new MockLogRecordable());
  279. auto log_processor = std::unique_ptr<LogRecordProcessor>(new MockProcessor(shared_recordable));
  280. // Create an API LoggerProvider and logger
  281. const auto resource = opentelemetry::sdk::resource::Resource::Create({});
  282. const std::string schema_url{"https://opentelemetry.io/schemas/1.11.0"};
  283. auto api_lp = std::shared_ptr<logs_api::LoggerProvider>(
  284. new LoggerProvider(std::move(log_processor), resource,
  285. std::make_unique<ScopeConfigurator<LoggerConfig>>(enabled_all_scopes)));
  286. auto logger = api_lp->GetLogger("test-logger", "opentelemetry_library", "", schema_url);
  287. // Test Logger functions for the constructed logger
  288. ASSERT_EQ(logger->GetName(), "test-logger");
  289. // Since the logger is enabled, when creating a LogRecord, the observed timestamp will be set
  290. // in the underlying LogRecordable.
  291. auto reference_ts = std::chrono::duration_cast<std::chrono::nanoseconds>(
  292. std::chrono::system_clock::now().time_since_epoch());
  293. auto log_record = logger->CreateLogRecord();
  294. logger->EmitLogRecord(std::move(log_record));
  295. // Since log_record was created after recording reference timestamp, expect that observed
  296. // timestamp is greater
  297. ASSERT_GE(shared_recordable->GetObservedTimestamp().time_since_epoch().count(),
  298. reference_ts.count());
  299. // Since this logger should behave like a valid logger, values within the recordable would be set.
  300. logger->EmitLogRecord(logs_api::Severity::kWarn, "Log Message");
  301. ASSERT_EQ(shared_recordable->GetBody(), "Log Message");
  302. ASSERT_EQ(shared_recordable->GetSeverity(), opentelemetry::logs::Severity::kWarn);
  303. ASSERT_GE(shared_recordable->GetObservedTimestamp().time_since_epoch().count(),
  304. reference_ts.count());
  305. }
  306. static std::unique_ptr<MockLogRecordable> create_mock_log_recordable(
  307. const std::string &body,
  308. opentelemetry::logs::Severity severity)
  309. {
  310. auto mock_log_recordable = std::make_unique<MockLogRecordable>();
  311. mock_log_recordable->SetBody(body);
  312. mock_log_recordable->SetSeverity(severity);
  313. return mock_log_recordable;
  314. }
  315. class CustomLogConfiguratorTestData
  316. {
  317. public:
  318. InstrumentationScope instrumentation_scope_;
  319. MockLogRecordable test_log_recordable_;
  320. MockLogRecordable expected_log_recordable_;
  321. bool expected_disabled_for_scope_;
  322. CustomLogConfiguratorTestData(const InstrumentationScope &instrumentation_scope,
  323. const MockLogRecordable &test_log_recordable,
  324. const MockLogRecordable &expected_log_recordable,
  325. const bool expected_disabled_for_scope)
  326. : instrumentation_scope_(instrumentation_scope),
  327. test_log_recordable_(test_log_recordable),
  328. expected_log_recordable_(expected_log_recordable),
  329. expected_disabled_for_scope_(expected_disabled_for_scope)
  330. {}
  331. };
  332. // constants used in VerifyCustomConfiguratorBehavior test
  333. static auto noop_logger = logs_api::NoopLogger();
  334. const std::string schema{"https://opentelemetry.io/schemas/1.11.0"};
  335. // Generate test case data
  336. // Test Case 1
  337. static auto instrumentation_scope_1 =
  338. *InstrumentationScope::Create("opentelemetry_library", "1.0.0", schema);
  339. static auto test_log_recordable_1 =
  340. create_mock_log_recordable("Log Message", opentelemetry::logs::Severity::kWarn);
  341. static auto expected_log_recordable_1 =
  342. create_mock_log_recordable("Log Message", opentelemetry::logs::Severity::kWarn);
  343. static auto custom_log_configurator_test_data_1 =
  344. CustomLogConfiguratorTestData(instrumentation_scope_1,
  345. *test_log_recordable_1,
  346. *expected_log_recordable_1,
  347. false);
  348. // Test Case 2
  349. static auto instrumentation_scope_2 = *InstrumentationScope::Create("bar_library", "1.0.0", schema);
  350. static auto test_log_recordable_2 =
  351. create_mock_log_recordable("", opentelemetry::logs::Severity::kDebug);
  352. static auto expected_log_recordable_2 =
  353. create_mock_log_recordable("", opentelemetry::logs::Severity::kDebug);
  354. static auto custom_log_configurator_test_data_2 =
  355. CustomLogConfiguratorTestData(instrumentation_scope_2,
  356. *test_log_recordable_2,
  357. *expected_log_recordable_2,
  358. false);
  359. // Test Case 3
  360. static auto instrumentation_scope_3 = *InstrumentationScope::Create("foo_library", "", schema);
  361. static auto test_log_recordable_3 =
  362. create_mock_log_recordable("Info message", opentelemetry::logs::Severity::kInfo);
  363. static auto expected_log_recordable_3 =
  364. create_mock_log_recordable("", opentelemetry::logs::Severity::kInvalid);
  365. static auto custom_log_configurator_test_data_3 =
  366. CustomLogConfiguratorTestData(instrumentation_scope_3,
  367. *test_log_recordable_3,
  368. *expected_log_recordable_3,
  369. true);
  370. // Test Case 4
  371. static auto instrumentation_scope_4 = *InstrumentationScope::Create("allowed_library", "", schema);
  372. static auto test_log_recordable_4 =
  373. create_mock_log_recordable("Scope version missing", opentelemetry::logs::Severity::kInfo);
  374. static auto expected_log_recordable_4 =
  375. create_mock_log_recordable("", opentelemetry::logs::Severity::kInvalid);
  376. static auto custom_log_configurator_test_data_4 =
  377. CustomLogConfiguratorTestData(instrumentation_scope_4,
  378. *test_log_recordable_4,
  379. *expected_log_recordable_4,
  380. true);
  381. // This array could also directly contain the reference types, but that leads to 'uninitialized
  382. // value was created by heap allocation' errors in Valgrind memcheck. This is a bug in Googletest
  383. // library, see https://github.com/google/googletest/issues/3805#issuecomment-1397301790 for more
  384. // details. Using pointers is a workaround to prevent the Valgrind warnings.
  385. constexpr std::array<CustomLogConfiguratorTestData *, 4> log_configurator_test_cases = {
  386. &custom_log_configurator_test_data_1, &custom_log_configurator_test_data_2,
  387. &custom_log_configurator_test_data_3, &custom_log_configurator_test_data_4};
  388. // Test fixture for VerifyCustomConfiguratorBehavior
  389. class CustomLoggerConfiguratorTestFixture
  390. : public ::testing::TestWithParam<CustomLogConfiguratorTestData *>
  391. {};
  392. TEST_P(CustomLoggerConfiguratorTestFixture, VerifyCustomConfiguratorBehavior)
  393. {
  394. // lambda checks if version is present in scope information
  395. auto check_if_version_present = [](const InstrumentationScope &scope_info) {
  396. return !scope_info.GetVersion().empty();
  397. };
  398. // custom scope configurator that only disables loggers for library name "foo_library" or do not
  399. // have version information
  400. auto test_scope_configurator = ScopeConfigurator<LoggerConfig>(
  401. ScopeConfigurator<LoggerConfig>::Builder(LoggerConfig::Disabled())
  402. .AddConditionNameEquals("foo_library", LoggerConfig::Disabled())
  403. .AddCondition(check_if_version_present, LoggerConfig::Enabled())
  404. .Build());
  405. // Get the test case data from fixture
  406. CustomLogConfiguratorTestData *test_case = GetParam();
  407. auto test_instrumentation_scope = test_case->instrumentation_scope_;
  408. auto test_log_recordable = test_case->test_log_recordable_;
  409. // Set a processor for the LoggerProvider
  410. auto shared_recordable_under_test = std::shared_ptr<MockLogRecordable>(new MockLogRecordable());
  411. auto log_processor_test =
  412. std::unique_ptr<LogRecordProcessor>(new MockProcessor(shared_recordable_under_test));
  413. // Create an API LoggerProvider and logger
  414. const auto resource = opentelemetry::sdk::resource::Resource::Create({});
  415. auto api_lp = std::shared_ptr<logs_api::LoggerProvider>(new LoggerProvider(
  416. std::move(log_processor_test), resource,
  417. std::make_unique<ScopeConfigurator<LoggerConfig>>(test_scope_configurator)));
  418. // Create logger and make assertions
  419. auto logger_under_test = api_lp->GetLogger("test-logger", test_instrumentation_scope.GetName(),
  420. test_instrumentation_scope.GetVersion(),
  421. test_instrumentation_scope.GetSchemaURL());
  422. auto reference_ts = std::chrono::duration_cast<std::chrono::nanoseconds>(
  423. std::chrono::system_clock::now().time_since_epoch());
  424. auto log_record = logger_under_test->CreateLogRecord();
  425. logger_under_test->EmitLogRecord(std::move(log_record));
  426. // Test Logger functions for the constructed logger
  427. if (test_case->expected_disabled_for_scope_)
  428. {
  429. ASSERT_EQ(logger_under_test->GetName(), noop_logger.GetName());
  430. ASSERT_EQ(shared_recordable_under_test->GetObservedTimestamp(),
  431. std::chrono::system_clock::from_time_t(0));
  432. }
  433. else
  434. {
  435. ASSERT_EQ(logger_under_test->GetName(), "test-logger");
  436. ASSERT_GE(shared_recordable_under_test->GetObservedTimestamp().time_since_epoch().count(),
  437. reference_ts.count());
  438. }
  439. logger_under_test->EmitLogRecord(test_log_recordable.GetBody(),
  440. test_log_recordable.GetSeverity());
  441. ASSERT_EQ(shared_recordable_under_test->GetBody(), test_case->expected_log_recordable_.GetBody());
  442. ASSERT_EQ(shared_recordable_under_test->GetSeverity(),
  443. test_case->expected_log_recordable_.GetSeverity());
  444. }
  445. INSTANTIATE_TEST_SUITE_P(CustomLogConfiguratorTestData,
  446. CustomLoggerConfiguratorTestFixture,
  447. ::testing::ValuesIn(log_configurator_test_cases));
  448. #if OPENTELEMETRY_ABI_VERSION_NO < 2
  449. TEST(LoggerSDK, EventLog)
  450. {
  451. // Create an API LoggerProvider and logger
  452. auto api_lp = std::shared_ptr<logs_api::LoggerProvider>(new LoggerProvider());
  453. const std::string schema_url{"https://opentelemetry.io/schemas/1.11.0"};
  454. auto logger = api_lp->GetLogger("logger", "opentelelemtry_library", "", schema_url);
  455. auto api_elp = std::shared_ptr<logs_api::EventLoggerProvider>(new EventLoggerProvider());
  456. auto event_logger = api_elp->CreateEventLogger(logger, "otel-cpp.event_domain");
  457. auto sdk_logger = static_cast<opentelemetry::sdk::logs::Logger *>(logger.get());
  458. ASSERT_EQ(sdk_logger->GetInstrumentationScope().GetName(), "opentelelemtry_library");
  459. ASSERT_EQ(sdk_logger->GetInstrumentationScope().GetVersion(), "");
  460. ASSERT_EQ(sdk_logger->GetInstrumentationScope().GetSchemaURL(), schema_url);
  461. // Set a processor for the LoggerProvider
  462. auto shared_recordable = std::shared_ptr<MockLogRecordable>(new MockLogRecordable());
  463. auto sdk_lp = static_cast<LoggerProvider *>(api_lp.get());
  464. sdk_lp->AddProcessor(std::unique_ptr<opentelemetry::sdk::logs::LogRecordProcessor>(
  465. new MockProcessor(shared_recordable)));
  466. // Check that the recordable created by the EmitEvent() statement is set properly
  467. event_logger->EmitEvent("otel-cpp.event_name", logs_api::Severity::kWarn, "Event Log Message");
  468. ASSERT_EQ(shared_recordable->GetSeverity(), logs_api::Severity::kWarn);
  469. ASSERT_EQ(shared_recordable->GetBody(), "Event Log Message");
  470. ASSERT_EQ(shared_recordable->GetEventName(), "otel-cpp.event_name");
  471. ASSERT_EQ(shared_recordable->GetEventDomain(), "otel-cpp.event_domain");
  472. }
  473. #endif