log_ut.cpp 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. #include "log.h"
  2. #include <library/cpp/testing/unittest/registar.h>
  3. #include <library/cpp/actors/testlib/test_runtime.h>
  4. using namespace NMonitoring;
  5. using namespace NActors;
  6. using namespace NActors::NLog;
  7. namespace {
  8. const TString& ServiceToString(int) {
  9. static const TString FAKE{"FAKE"};
  10. return FAKE;
  11. }
  12. TIntrusivePtr<TSettings> DefaultSettings() {
  13. auto loggerId = TActorId{0, "Logger"};
  14. auto s = MakeIntrusive<TSettings>(loggerId, 0, EPriority::PRI_TRACE);
  15. s->SetAllowDrop(false);
  16. s->Append(0, 1, ServiceToString);
  17. return s;
  18. }
  19. TIntrusivePtr<TSettings> DroppingSettings(ui64 timeThresholdMs) {
  20. auto loggerId = TActorId{0, "Logger"};
  21. auto s = MakeIntrusive<TSettings>(
  22. loggerId,
  23. 0,
  24. EPriority::PRI_TRACE,
  25. EPriority::PRI_DEBUG,
  26. (ui32)0,
  27. timeThresholdMs);
  28. s->Append(0, 1, ServiceToString);
  29. return s;
  30. }
  31. class TMockBackend: public TLogBackend {
  32. public:
  33. using TWriteImpl = std::function<void(const TLogRecord&)>;
  34. using TReopenImpl = std::function<void()>;
  35. static void REOPEN_NOP() { }
  36. TMockBackend(TWriteImpl writeImpl, TReopenImpl reopenImpl = REOPEN_NOP)
  37. : WriteImpl_{writeImpl}
  38. , ReopenImpl_{reopenImpl}
  39. {
  40. }
  41. void WriteData(const TLogRecord& r) override {
  42. WriteImpl_(r);
  43. }
  44. void ReopenLog() override { }
  45. void SetWriteImpl(TWriteImpl writeImpl) {
  46. WriteImpl_ = writeImpl;
  47. }
  48. private:
  49. TWriteImpl WriteImpl_;
  50. TReopenImpl ReopenImpl_;
  51. };
  52. void ThrowAlways(const TLogRecord&) {
  53. ythrow yexception();
  54. };
  55. struct TFixture {
  56. TFixture(
  57. TIntrusivePtr<TSettings> settings,
  58. TMockBackend::TWriteImpl writeImpl = ThrowAlways)
  59. {
  60. Runtime.Initialize();
  61. LogBackend.reset(new TMockBackend{writeImpl});
  62. LoggerActor = Runtime.Register(new TLoggerActor{settings, LogBackend, Counters});
  63. Runtime.SetScheduledEventFilter([] (auto&&, auto&&, auto&&, auto) {
  64. return false;
  65. });
  66. }
  67. TFixture(TMockBackend::TWriteImpl writeImpl = ThrowAlways)
  68. : TFixture(DefaultSettings(), writeImpl)
  69. {}
  70. void WriteLog() {
  71. Runtime.Send(new IEventHandle{LoggerActor, {}, new TEvLog(TInstant::Zero(), TLevel{EPrio::Emerg}, 0, "foo")});
  72. }
  73. void WriteLog(TInstant ts) {
  74. Runtime.Send(new IEventHandle{LoggerActor, {}, new TEvLog(ts, TLevel{EPrio::Emerg}, 0, "foo")});
  75. }
  76. void Wakeup() {
  77. Runtime.Send(new IEventHandle{LoggerActor, {}, new TEvents::TEvWakeup});
  78. }
  79. TIntrusivePtr<TDynamicCounters> Counters{MakeIntrusive<TDynamicCounters>()};
  80. std::shared_ptr<TMockBackend> LogBackend;
  81. TActorId LoggerActor;
  82. TTestActorRuntimeBase Runtime;
  83. };
  84. }
  85. Y_UNIT_TEST_SUITE(TLoggerActorTest) {
  86. Y_UNIT_TEST(NoCrashOnWriteFailure) {
  87. TFixture test;
  88. test.WriteLog();
  89. // everything is okay as long as we get here
  90. }
  91. Y_UNIT_TEST(SubsequentWritesAreIgnored) {
  92. size_t count{0};
  93. auto countWrites = [&count] (auto&& r) {
  94. count++;
  95. ThrowAlways(r);
  96. };
  97. TFixture test{countWrites};
  98. test.WriteLog();
  99. UNIT_ASSERT_VALUES_EQUAL(count, 1);
  100. // at this point we should have started dropping messages
  101. for (auto i = 0; i < 5; ++i) {
  102. test.WriteLog();
  103. }
  104. UNIT_ASSERT_VALUES_EQUAL(count, 1);
  105. }
  106. Y_UNIT_TEST(LoggerCanRecover) {
  107. TFixture test;
  108. test.WriteLog();
  109. TVector<TString> messages;
  110. auto acceptWrites = [&] (const TLogRecord& r) {
  111. messages.emplace_back(r.Data, r.Len);
  112. };
  113. auto scheduled = test.Runtime.CaptureScheduledEvents();
  114. UNIT_ASSERT_VALUES_EQUAL(scheduled.size(), 1);
  115. test.LogBackend->SetWriteImpl(acceptWrites);
  116. test.Wakeup();
  117. const auto COUNT = 10;
  118. for (auto i = 0; i < COUNT; ++i) {
  119. test.WriteLog();
  120. }
  121. UNIT_ASSERT_VALUES_EQUAL(messages.size(), COUNT);
  122. }
  123. Y_UNIT_TEST(ShouldObeyTimeThresholdMsWhenOverloaded) {
  124. TFixture test{DroppingSettings(5000)};
  125. TVector<TString> messages;
  126. auto acceptWrites = [&] (const TLogRecord& r) {
  127. messages.emplace_back(r.Data, r.Len);
  128. };
  129. test.LogBackend->SetWriteImpl(acceptWrites);
  130. test.Wakeup();
  131. const auto COUNT = 11;
  132. for (auto i = 0; i < COUNT; ++i) {
  133. test.WriteLog();
  134. }
  135. UNIT_ASSERT_VALUES_EQUAL(messages.size(), COUNT);
  136. test.Runtime.AdvanceCurrentTime(TDuration::Seconds(20));
  137. auto now = test.Runtime.GetCurrentTime();
  138. test.WriteLog(now - TDuration::Seconds(5));
  139. UNIT_ASSERT_VALUES_EQUAL(messages.size(), COUNT + 1);
  140. test.WriteLog(now - TDuration::Seconds(6));
  141. UNIT_ASSERT_VALUES_EQUAL(messages.size(), COUNT + 1);
  142. }
  143. }