EventLoggerUtilsTests.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #include <AzCore/IO/ByteContainerStream.h>
  9. #include <AzCore/Metrics/EventLoggerFactoryImpl.h>
  10. #include <AzCore/Metrics/EventLoggerUtils.h>
  11. #include <AzCore/Metrics/JsonTraceEventLogger.h>
  12. #include <AzCore/std/ranges/ranges_algorithm.h>
  13. #include <AzCore/std/ranges/filter_view.h>
  14. #include <AzCore/UnitTest/TestTypes.h>
  15. namespace UnitTest::EventLoggerUtilsTests
  16. {
  17. class EventLoggerUtilsFixture
  18. : public LeakDetectionFixture
  19. {
  20. public:
  21. EventLoggerUtilsFixture()
  22. {
  23. // Create an event logger factory
  24. m_eventLoggerFactory = AZStd::make_unique<AZ::Metrics::EventLoggerFactoryImpl>();
  25. // Create an byte container stream that allows event logger output to be logged in-memory
  26. auto metricsStream = AZStd::make_unique<AZ::IO::ByteContainerStream<AZStd::string>>(&m_metricsOutput);
  27. // Create the trace event logger that logs to the Google Trace Event format
  28. auto eventLogger = AZStd::make_unique<AZ::Metrics::JsonTraceEventLogger>(AZStd::move(metricsStream));
  29. // Register the Google Trace Event Logger with the Event Logger Factory
  30. EXPECT_TRUE(m_eventLoggerFactory->RegisterEventLogger(m_loggerId, AZStd::move(eventLogger)));
  31. }
  32. protected:
  33. AZStd::string m_metricsOutput;
  34. AZStd::unique_ptr<AZ::Metrics::IEventLoggerFactory> m_eventLoggerFactory;
  35. AZ::Metrics::EventLoggerId m_loggerId{ 1 };
  36. };
  37. TEST_F(EventLoggerUtilsFixture, DirectUtilityFunctions_CanRecordMetricsSuccessfully)
  38. {
  39. constexpr AZ::Metrics::EventLoggerId loggerId{ 1 };
  40. const auto startThreadTime = AZStd::chrono::utc_clock::now();
  41. using EventObjectStorage = AZStd::fixed_vector<AZ::Metrics::EventField, 8>;
  42. EventObjectStorage argsContainer;
  43. argsContainer.emplace_back("string", "Hello World");
  44. AZ::Metrics::DurationArgs durationArgs;
  45. durationArgs.m_name = "Duration Event";
  46. durationArgs.m_cat = "Test";
  47. durationArgs.m_args = argsContainer;
  48. durationArgs.m_id = "0";
  49. auto resultOutcome = AZ::Metrics::RecordDurationEventBegin(loggerId, durationArgs, m_eventLoggerFactory.get());
  50. EXPECT_TRUE(resultOutcome);
  51. resultOutcome = AZ::Metrics::RecordDurationEventEnd(loggerId, durationArgs, m_eventLoggerFactory.get());
  52. EXPECT_TRUE(resultOutcome);
  53. AZ::Metrics::CompleteArgs completeArgs;
  54. completeArgs.m_name = "Complete Event";
  55. completeArgs.m_cat = "Test";
  56. completeArgs.m_args = argsContainer;
  57. completeArgs.m_dur = AZStd::chrono::duration_cast<AZStd::chrono::microseconds>(AZStd::chrono::utc_clock::now() - startThreadTime);
  58. completeArgs.m_id = "0";
  59. resultOutcome = AZ::Metrics::RecordCompleteEvent(loggerId, completeArgs, m_eventLoggerFactory.get());
  60. EXPECT_TRUE(resultOutcome);
  61. AZ::Metrics::InstantArgs instantArgs;
  62. instantArgs.m_name = "Instant Event";
  63. instantArgs.m_cat = "Test";
  64. instantArgs.m_args = argsContainer;
  65. instantArgs.m_id = "0";
  66. instantArgs.m_scope = AZ::Metrics::InstantEventScope::Thread;
  67. resultOutcome = AZ::Metrics::RecordInstantEvent(loggerId, instantArgs, m_eventLoggerFactory.get());
  68. EXPECT_TRUE(resultOutcome);
  69. AZ::Metrics::CounterArgs counterArgs;
  70. counterArgs.m_name = "Counter Event";
  71. counterArgs.m_cat = "Test";
  72. counterArgs.m_args = argsContainer;
  73. counterArgs.m_id = "0";
  74. resultOutcome = AZ::Metrics::RecordCounterEvent(loggerId, counterArgs, m_eventLoggerFactory.get());
  75. EXPECT_TRUE(resultOutcome);
  76. AZ::Metrics::AsyncArgs asyncArgs;
  77. asyncArgs.m_name = "Async Event";
  78. asyncArgs.m_cat = "Test";
  79. asyncArgs.m_args = argsContainer;
  80. asyncArgs.m_id = "0";
  81. asyncArgs.m_scope = "Distinguishing Scope";
  82. resultOutcome = AZ::Metrics::RecordAsyncEventStart(loggerId, asyncArgs, m_eventLoggerFactory.get());
  83. EXPECT_TRUE(resultOutcome);
  84. resultOutcome = AZ::Metrics::RecordAsyncEventInstant(loggerId, asyncArgs, m_eventLoggerFactory.get());
  85. EXPECT_TRUE(resultOutcome);
  86. resultOutcome = AZ::Metrics::RecordAsyncEventEnd(loggerId, asyncArgs, m_eventLoggerFactory.get());
  87. EXPECT_TRUE(resultOutcome);
  88. }
  89. TEST_F(EventLoggerUtilsFixture, RecordEvent_WithEventPhase_CanForwardEventToProperRecordFunction)
  90. {
  91. constexpr AZ::Metrics::EventLoggerId loggerId{ 1 };
  92. constexpr AZ::Metrics::EventLoggerId nonExistantloggerId{ AZStd::numeric_limits<AZ::u32>::max() };
  93. const auto startThreadTime = AZStd::chrono::utc_clock::now();
  94. using EventObjectStorage = AZStd::fixed_vector<AZ::Metrics::EventField, 8>;
  95. EventObjectStorage argsContainer;
  96. argsContainer.emplace_back("string", "Hello World");
  97. AZ::Metrics::DurationArgs durationArgs;
  98. durationArgs.m_name = "Duration Event";
  99. durationArgs.m_cat = "Test";
  100. durationArgs.m_args = argsContainer;
  101. durationArgs.m_id = "0";
  102. AZ::Metrics::CompleteArgs completeArgs;
  103. completeArgs.m_name = "Complete Event";
  104. completeArgs.m_cat = "Test";
  105. completeArgs.m_args = argsContainer;
  106. completeArgs.m_dur = AZStd::chrono::duration_cast<AZStd::chrono::microseconds>(AZStd::chrono::utc_clock::now() - startThreadTime);
  107. completeArgs.m_id = "0";
  108. // Should succeed in recording an event with the proper event phase and events arguments
  109. auto resultOutcome = AZ::Metrics::RecordEvent(loggerId, AZ::Metrics::EventPhase::DurationBegin, durationArgs, m_eventLoggerFactory.get());
  110. EXPECT_TRUE(resultOutcome);
  111. resultOutcome = AZ::Metrics::RecordEvent(loggerId, AZ::Metrics::EventPhase::DurationEnd, durationArgs, m_eventLoggerFactory.get());
  112. EXPECT_TRUE(resultOutcome);
  113. // Should fail due to attempting to query an event logger using a non registered logger id
  114. resultOutcome = AZ::Metrics::RecordEvent(nonExistantloggerId, AZ::Metrics::EventPhase::DurationBegin, durationArgs, m_eventLoggerFactory.get());
  115. EXPECT_FALSE(resultOutcome);
  116. // Should fail due to the Counter event phase type being using a structure of duration args
  117. resultOutcome = AZ::Metrics::RecordEvent(loggerId, AZ::Metrics::EventPhase::Counter, durationArgs, m_eventLoggerFactory.get());
  118. EXPECT_FALSE(resultOutcome);
  119. // Should fail due to the Duration event phase type using a struct of type CompleteArgs
  120. resultOutcome = AZ::Metrics::RecordEvent(loggerId, AZ::Metrics::EventPhase::DurationEnd, completeArgs, m_eventLoggerFactory.get());
  121. EXPECT_FALSE(resultOutcome);
  122. }
  123. TEST_F(EventLoggerUtilsFixture, RecordEvent_WithEventPhase_SupportsAllEventPhasesWithEventArgsStructures)
  124. {
  125. constexpr AZ::Metrics::EventLoggerId loggerId{ 1 };
  126. const auto startThreadTime = AZStd::chrono::utc_clock::now();
  127. using EventObjectStorage = AZStd::fixed_vector<AZ::Metrics::EventField, 8>;
  128. EventObjectStorage argsContainer;
  129. argsContainer.emplace_back("string", "Hello World");
  130. AZ::Metrics::DurationArgs durationArgs;
  131. durationArgs.m_name = "Duration Event";
  132. durationArgs.m_cat = "Test";
  133. durationArgs.m_args = argsContainer;
  134. durationArgs.m_id = "0";
  135. AZ::Metrics::CompleteArgs completeArgs;
  136. completeArgs.m_name = "Complete Event";
  137. completeArgs.m_cat = "Test";
  138. completeArgs.m_args = argsContainer;
  139. completeArgs.m_dur = AZStd::chrono::duration_cast<AZStd::chrono::microseconds>(AZStd::chrono::utc_clock::now() - startThreadTime);
  140. completeArgs.m_id = "0";
  141. AZ::Metrics::InstantArgs instantArgs;
  142. instantArgs.m_name = "Instant Event";
  143. instantArgs.m_cat = "Test";
  144. instantArgs.m_args = argsContainer;
  145. instantArgs.m_id = "0";
  146. instantArgs.m_scope = AZ::Metrics::InstantEventScope::Thread;
  147. AZ::Metrics::CounterArgs counterArgs;
  148. counterArgs.m_name = "Counter Event";
  149. counterArgs.m_cat = "Test";
  150. counterArgs.m_args = argsContainer;
  151. counterArgs.m_id = "0";
  152. AZ::Metrics::AsyncArgs asyncArgs;
  153. asyncArgs.m_name = "Async Event";
  154. asyncArgs.m_cat = "Test";
  155. asyncArgs.m_args = argsContainer;
  156. asyncArgs.m_id = "0";
  157. asyncArgs.m_scope = "Distinguishing Scope";
  158. // Duration phases - Should succeed in recording duration events
  159. auto resultOutcome = AZ::Metrics::RecordEvent(loggerId, AZ::Metrics::EventPhase::DurationBegin, durationArgs, m_eventLoggerFactory.get());
  160. EXPECT_TRUE(resultOutcome);
  161. resultOutcome = AZ::Metrics::RecordEvent(loggerId, AZ::Metrics::EventPhase::DurationEnd, durationArgs, m_eventLoggerFactory.get());
  162. EXPECT_TRUE(resultOutcome);
  163. // Duration phases - Should fail in recording all other events
  164. resultOutcome = AZ::Metrics::RecordEvent(loggerId, AZ::Metrics::EventPhase::DurationBegin, completeArgs, m_eventLoggerFactory.get());
  165. EXPECT_FALSE(resultOutcome);
  166. resultOutcome = AZ::Metrics::RecordEvent(loggerId, AZ::Metrics::EventPhase::DurationBegin, instantArgs, m_eventLoggerFactory.get());
  167. EXPECT_FALSE(resultOutcome);
  168. resultOutcome = AZ::Metrics::RecordEvent(loggerId, AZ::Metrics::EventPhase::DurationBegin, counterArgs, m_eventLoggerFactory.get());
  169. EXPECT_FALSE(resultOutcome);
  170. resultOutcome = AZ::Metrics::RecordEvent(loggerId, AZ::Metrics::EventPhase::DurationBegin, asyncArgs, m_eventLoggerFactory.get());
  171. EXPECT_FALSE(resultOutcome);
  172. resultOutcome = AZ::Metrics::RecordEvent(loggerId, AZ::Metrics::EventPhase::DurationEnd, completeArgs, m_eventLoggerFactory.get());
  173. EXPECT_FALSE(resultOutcome);
  174. resultOutcome = AZ::Metrics::RecordEvent(loggerId, AZ::Metrics::EventPhase::DurationEnd, instantArgs, m_eventLoggerFactory.get());
  175. EXPECT_FALSE(resultOutcome);
  176. resultOutcome = AZ::Metrics::RecordEvent(loggerId, AZ::Metrics::EventPhase::DurationEnd, counterArgs, m_eventLoggerFactory.get());
  177. EXPECT_FALSE(resultOutcome);
  178. resultOutcome = AZ::Metrics::RecordEvent(loggerId, AZ::Metrics::EventPhase::DurationEnd, asyncArgs, m_eventLoggerFactory.get());
  179. EXPECT_FALSE(resultOutcome);
  180. // Complete phase - Should succeed in recording complete events
  181. resultOutcome = AZ::Metrics::RecordEvent(loggerId, AZ::Metrics::EventPhase::Complete, completeArgs, m_eventLoggerFactory.get());
  182. EXPECT_TRUE(resultOutcome);
  183. // Complete phase - Should fail in recording all other events
  184. resultOutcome = AZ::Metrics::RecordEvent(loggerId, AZ::Metrics::EventPhase::Complete, durationArgs, m_eventLoggerFactory.get());
  185. EXPECT_FALSE(resultOutcome);
  186. resultOutcome = AZ::Metrics::RecordEvent(loggerId, AZ::Metrics::EventPhase::Complete, instantArgs, m_eventLoggerFactory.get());
  187. EXPECT_FALSE(resultOutcome);
  188. resultOutcome = AZ::Metrics::RecordEvent(loggerId, AZ::Metrics::EventPhase::Complete, counterArgs, m_eventLoggerFactory.get());
  189. EXPECT_FALSE(resultOutcome);
  190. resultOutcome = AZ::Metrics::RecordEvent(loggerId, AZ::Metrics::EventPhase::Complete, asyncArgs, m_eventLoggerFactory.get());
  191. EXPECT_FALSE(resultOutcome);
  192. // Instant phase - Should succeed in recording instant events
  193. resultOutcome = AZ::Metrics::RecordEvent(loggerId, AZ::Metrics::EventPhase::Instant, instantArgs, m_eventLoggerFactory.get());
  194. EXPECT_TRUE(resultOutcome);
  195. // Instant phase - Should fail in recording all other events
  196. resultOutcome = AZ::Metrics::RecordEvent(loggerId, AZ::Metrics::EventPhase::Instant, durationArgs, m_eventLoggerFactory.get());
  197. EXPECT_FALSE(resultOutcome);
  198. resultOutcome = AZ::Metrics::RecordEvent(loggerId, AZ::Metrics::EventPhase::Instant, completeArgs, m_eventLoggerFactory.get());
  199. EXPECT_FALSE(resultOutcome);
  200. resultOutcome = AZ::Metrics::RecordEvent(loggerId, AZ::Metrics::EventPhase::Instant, counterArgs, m_eventLoggerFactory.get());
  201. EXPECT_FALSE(resultOutcome);
  202. resultOutcome = AZ::Metrics::RecordEvent(loggerId, AZ::Metrics::EventPhase::Instant, asyncArgs, m_eventLoggerFactory.get());
  203. EXPECT_FALSE(resultOutcome);
  204. // Counter phase - Should succeed in recording counter events
  205. resultOutcome = AZ::Metrics::RecordEvent(loggerId, AZ::Metrics::EventPhase::Counter, counterArgs, m_eventLoggerFactory.get());
  206. EXPECT_TRUE(resultOutcome);
  207. // Counter phase - Should fail in recording all other events
  208. resultOutcome = AZ::Metrics::RecordEvent(loggerId, AZ::Metrics::EventPhase::Counter, durationArgs, m_eventLoggerFactory.get());
  209. EXPECT_FALSE(resultOutcome);
  210. resultOutcome = AZ::Metrics::RecordEvent(loggerId, AZ::Metrics::EventPhase::Counter, completeArgs, m_eventLoggerFactory.get());
  211. EXPECT_FALSE(resultOutcome);
  212. resultOutcome = AZ::Metrics::RecordEvent(loggerId, AZ::Metrics::EventPhase::Counter, instantArgs, m_eventLoggerFactory.get());
  213. EXPECT_FALSE(resultOutcome);
  214. resultOutcome = AZ::Metrics::RecordEvent(loggerId, AZ::Metrics::EventPhase::Counter, asyncArgs, m_eventLoggerFactory.get());
  215. EXPECT_FALSE(resultOutcome);
  216. // Async phases - Should succeed in recording async events
  217. resultOutcome = AZ::Metrics::RecordEvent(loggerId, AZ::Metrics::EventPhase::AsyncStart, asyncArgs, m_eventLoggerFactory.get());
  218. EXPECT_TRUE(resultOutcome);
  219. resultOutcome = AZ::Metrics::RecordEvent(loggerId, AZ::Metrics::EventPhase::AsyncInstant, asyncArgs, m_eventLoggerFactory.get());
  220. EXPECT_TRUE(resultOutcome);
  221. resultOutcome = AZ::Metrics::RecordEvent(loggerId, AZ::Metrics::EventPhase::AsyncEnd, asyncArgs, m_eventLoggerFactory.get());
  222. EXPECT_TRUE(resultOutcome);
  223. // Async phases - Should fail in recording all other events
  224. resultOutcome = AZ::Metrics::RecordEvent(loggerId, AZ::Metrics::EventPhase::AsyncStart, durationArgs, m_eventLoggerFactory.get());
  225. EXPECT_FALSE(resultOutcome);
  226. resultOutcome = AZ::Metrics::RecordEvent(loggerId, AZ::Metrics::EventPhase::AsyncStart, completeArgs, m_eventLoggerFactory.get());
  227. EXPECT_FALSE(resultOutcome);
  228. resultOutcome = AZ::Metrics::RecordEvent(loggerId, AZ::Metrics::EventPhase::AsyncStart, instantArgs, m_eventLoggerFactory.get());
  229. EXPECT_FALSE(resultOutcome);
  230. resultOutcome = AZ::Metrics::RecordEvent(loggerId, AZ::Metrics::EventPhase::AsyncStart, counterArgs, m_eventLoggerFactory.get());
  231. EXPECT_FALSE(resultOutcome);
  232. resultOutcome = AZ::Metrics::RecordEvent(loggerId, AZ::Metrics::EventPhase::AsyncInstant, durationArgs, m_eventLoggerFactory.get());
  233. EXPECT_FALSE(resultOutcome);
  234. resultOutcome = AZ::Metrics::RecordEvent(loggerId, AZ::Metrics::EventPhase::AsyncInstant, completeArgs, m_eventLoggerFactory.get());
  235. EXPECT_FALSE(resultOutcome);
  236. resultOutcome = AZ::Metrics::RecordEvent(loggerId, AZ::Metrics::EventPhase::AsyncInstant, instantArgs, m_eventLoggerFactory.get());
  237. EXPECT_FALSE(resultOutcome);
  238. resultOutcome = AZ::Metrics::RecordEvent(loggerId, AZ::Metrics::EventPhase::AsyncInstant, counterArgs, m_eventLoggerFactory.get());
  239. EXPECT_FALSE(resultOutcome);
  240. resultOutcome = AZ::Metrics::RecordEvent(loggerId, AZ::Metrics::EventPhase::AsyncEnd, durationArgs, m_eventLoggerFactory.get());
  241. EXPECT_FALSE(resultOutcome);
  242. resultOutcome = AZ::Metrics::RecordEvent(loggerId, AZ::Metrics::EventPhase::AsyncEnd, completeArgs, m_eventLoggerFactory.get());
  243. EXPECT_FALSE(resultOutcome);
  244. resultOutcome = AZ::Metrics::RecordEvent(loggerId, AZ::Metrics::EventPhase::AsyncEnd, instantArgs, m_eventLoggerFactory.get());
  245. EXPECT_FALSE(resultOutcome);
  246. resultOutcome = AZ::Metrics::RecordEvent(loggerId, AZ::Metrics::EventPhase::AsyncEnd, counterArgs, m_eventLoggerFactory.get());
  247. EXPECT_FALSE(resultOutcome);
  248. }
  249. TEST_F(EventLoggerUtilsFixture, UtilityFunctions_CanLookupGlobalRegisteredEventLoggerFactoryInstance)
  250. {
  251. constexpr AZ::Metrics::EventLoggerId loggerId{ 1 };
  252. using EventObjectStorage = AZStd::fixed_vector<AZ::Metrics::EventField, 8>;
  253. EventObjectStorage argsContainer;
  254. argsContainer.emplace_back("string", "Hello World");
  255. AZ::Metrics::DurationArgs durationArgs;
  256. durationArgs.m_name = "Duration Event";
  257. durationArgs.m_cat = "Test";
  258. durationArgs.m_args = argsContainer;
  259. durationArgs.m_id = "0";
  260. // Recording a duration event using the member event logger factory always should succeed
  261. EXPECT_TRUE(AZ::Metrics::RecordDurationEventBegin(loggerId, durationArgs, m_eventLoggerFactory.get()));
  262. // Since there is not an AZ::Interface registered event logger factory recording should fail the factory argument is not supplied
  263. EXPECT_FALSE(AZ::Metrics::RecordDurationEventBegin(loggerId, durationArgs));
  264. // Register the Event Logger Factory with the AZ::Interface<IEventLoggerFactory>
  265. AZ::Interface<AZ::Metrics::IEventLoggerFactory>::Register(m_eventLoggerFactory.get());
  266. // The registered global AZ::Interface<IEventLoggerFactory> instance should be used in this case
  267. EXPECT_TRUE(AZ::Metrics::RecordDurationEventEnd(loggerId, durationArgs));
  268. // Unregister the Event Logger Factory with the AZ::Interface<IEventLoggerFactory>
  269. AZ::Interface<AZ::Metrics::IEventLoggerFactory>::Unregister(m_eventLoggerFactory.get());
  270. // The AZ::Interface<IEventLogerFactory no longer has a registered instance, the recording of the an event should fail again
  271. AZ::Metrics::CompleteArgs completeArgs;
  272. completeArgs.m_name = "Complete Event";
  273. completeArgs.m_cat = "Test";
  274. completeArgs.m_args = argsContainer;
  275. completeArgs.m_id = "0";
  276. EXPECT_FALSE(AZ::Metrics::RecordCompleteEvent(loggerId, completeArgs));
  277. // Recording should succeed when the member event logger is used though
  278. EXPECT_TRUE(AZ::Metrics::RecordCompleteEvent(loggerId, completeArgs, m_eventLoggerFactory.get()));
  279. }
  280. } // namespace UnitTest::EventLoggerUtilsTests