logger.cpp 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. #include "logger.h"
  2. #include <library/cpp/yt/assert/assert.h>
  3. #include <library/cpp/yt/cpu_clock/clock.h>
  4. #include <library/cpp/yt/misc/thread_name.h>
  5. #include <util/system/compiler.h>
  6. #include <util/system/thread.h>
  7. namespace NYT::NLogging {
  8. ////////////////////////////////////////////////////////////////////////////////
  9. namespace NDetail {
  10. void OnCriticalLogEvent(
  11. const TLogger& logger,
  12. const TLogEvent& event)
  13. {
  14. if (event.Level == ELogLevel::Fatal ||
  15. event.Level == ELogLevel::Alert && logger.GetAbortOnAlert())
  16. {
  17. fprintf(stderr, "*** Aborting on critical log event\n");
  18. fwrite(event.MessageRef.begin(), 1, event.MessageRef.size(), stderr);
  19. fprintf(stderr, "\n");
  20. YT_ABORT();
  21. }
  22. }
  23. TSharedRef TMessageStringBuilder::Flush()
  24. {
  25. return Buffer_.Slice(0, GetLength());
  26. }
  27. void TMessageStringBuilder::DisablePerThreadCache()
  28. {
  29. Cache_ = nullptr;
  30. CacheDestroyed_ = true;
  31. }
  32. void TMessageStringBuilder::DoReset()
  33. {
  34. Buffer_.Reset();
  35. }
  36. void TMessageStringBuilder::DoReserve(size_t newCapacity)
  37. {
  38. auto oldLength = GetLength();
  39. newCapacity = FastClp2(newCapacity);
  40. auto newChunkSize = std::max(ChunkSize, newCapacity);
  41. // Hold the old buffer until the data is copied.
  42. auto oldBuffer = std::move(Buffer_);
  43. auto* cache = GetCache();
  44. if (Y_LIKELY(cache)) {
  45. auto oldCapacity = End_ - Begin_;
  46. auto deltaCapacity = newCapacity - oldCapacity;
  47. if (End_ == cache->Chunk.Begin() + cache->ChunkOffset &&
  48. cache->ChunkOffset + deltaCapacity <= cache->Chunk.Size())
  49. {
  50. // Resize inplace.
  51. Buffer_ = cache->Chunk.Slice(cache->ChunkOffset - oldCapacity, cache->ChunkOffset + deltaCapacity);
  52. cache->ChunkOffset += deltaCapacity;
  53. End_ = Begin_ + newCapacity;
  54. return;
  55. }
  56. if (Y_UNLIKELY(cache->ChunkOffset + newCapacity > cache->Chunk.Size())) {
  57. cache->Chunk = TSharedMutableRef::Allocate<TMessageBufferTag>(newChunkSize, {.InitializeStorage = false});
  58. cache->ChunkOffset = 0;
  59. }
  60. Buffer_ = cache->Chunk.Slice(cache->ChunkOffset, cache->ChunkOffset + newCapacity);
  61. cache->ChunkOffset += newCapacity;
  62. } else {
  63. Buffer_ = TSharedMutableRef::Allocate<TMessageBufferTag>(newChunkSize, {.InitializeStorage = false});
  64. newCapacity = newChunkSize;
  65. }
  66. if (oldLength > 0) {
  67. ::memcpy(Buffer_.Begin(), Begin_, oldLength);
  68. }
  69. Begin_ = Buffer_.Begin();
  70. End_ = Begin_ + newCapacity;
  71. }
  72. TMessageStringBuilder::TPerThreadCache* TMessageStringBuilder::GetCache()
  73. {
  74. if (Y_LIKELY(Cache_)) {
  75. return Cache_;
  76. }
  77. if (CacheDestroyed_) {
  78. return nullptr;
  79. }
  80. static YT_THREAD_LOCAL(TPerThreadCache) Cache;
  81. Cache_ = &GetTlsRef(Cache);
  82. return Cache_;
  83. }
  84. TMessageStringBuilder::TPerThreadCache::~TPerThreadCache()
  85. {
  86. TMessageStringBuilder::DisablePerThreadCache();
  87. }
  88. YT_THREAD_LOCAL(TMessageStringBuilder::TPerThreadCache*) TMessageStringBuilder::Cache_;
  89. YT_THREAD_LOCAL(bool) TMessageStringBuilder::CacheDestroyed_;
  90. } // namespace NDetail
  91. ////////////////////////////////////////////////////////////////////////////////
  92. Y_WEAK TLoggingContext GetLoggingContext()
  93. {
  94. return {
  95. .Instant = GetCpuInstant(),
  96. .ThreadId = TThread::CurrentThreadId(),
  97. .ThreadName = GetCurrentThreadName(),
  98. };
  99. }
  100. Y_WEAK ILogManager* GetDefaultLogManager()
  101. {
  102. return nullptr;
  103. }
  104. ////////////////////////////////////////////////////////////////////////////////
  105. YT_THREAD_LOCAL(ELogLevel) ThreadMinLogLevel = ELogLevel::Minimum;
  106. void SetThreadMinLogLevel(ELogLevel minLogLevel)
  107. {
  108. ThreadMinLogLevel = minLogLevel;
  109. }
  110. ELogLevel GetThreadMinLogLevel()
  111. {
  112. return ThreadMinLogLevel;
  113. }
  114. ////////////////////////////////////////////////////////////////////////////////
  115. TLogger::TLogger(ILogManager* logManager, TStringBuf categoryName)
  116. : LogManager_(logManager)
  117. , Category_(LogManager_ ? LogManager_->GetCategory(categoryName) : nullptr)
  118. , MinLevel_(LogManager_ ? LoggerDefaultMinLevel : NullLoggerMinLevel)
  119. { }
  120. TLogger::TLogger(TStringBuf categoryName)
  121. : TLogger(GetDefaultLogManager(), categoryName)
  122. { }
  123. TLogger::operator bool() const
  124. {
  125. return LogManager_;
  126. }
  127. const TLoggingCategory* TLogger::GetCategory() const
  128. {
  129. return Category_;
  130. }
  131. bool TLogger::IsLevelEnabledHeavy(ELogLevel level) const
  132. {
  133. // Note that we managed to reach this point, i.e. level >= MinLevel_,
  134. // which implies that MinLevel_ != ELogLevel::Maximum, so this logger was not
  135. // default constructed, thus it has non-trivial category.
  136. YT_ASSERT(Category_);
  137. if (Category_->CurrentVersion != Category_->ActualVersion->load(std::memory_order::relaxed)) {
  138. LogManager_->UpdateCategory(const_cast<TLoggingCategory*>(Category_));
  139. }
  140. return
  141. level >= Category_->MinPlainTextLevel &&
  142. level >= ThreadMinLogLevel;
  143. }
  144. bool TLogger::GetAbortOnAlert() const
  145. {
  146. return LogManager_->GetAbortOnAlert();
  147. }
  148. bool TLogger::IsEssential() const
  149. {
  150. return Essential_;
  151. }
  152. void TLogger::UpdateAnchor(TLoggingAnchor* anchor) const
  153. {
  154. LogManager_->UpdateAnchor(anchor);
  155. }
  156. void TLogger::RegisterStaticAnchor(TLoggingAnchor* anchor, ::TSourceLocation sourceLocation, TStringBuf message) const
  157. {
  158. LogManager_->RegisterStaticAnchor(anchor, sourceLocation, message);
  159. }
  160. void TLogger::Write(TLogEvent&& event) const
  161. {
  162. LogManager_->Enqueue(std::move(event));
  163. }
  164. void TLogger::AddRawTag(const TString& tag)
  165. {
  166. if (!Tag_.empty()) {
  167. Tag_ += ", ";
  168. }
  169. Tag_ += tag;
  170. }
  171. TLogger TLogger::WithRawTag(const TString& tag) const
  172. {
  173. auto result = *this;
  174. result.AddRawTag(tag);
  175. return result;
  176. }
  177. TLogger TLogger::WithEssential(bool essential) const
  178. {
  179. auto result = *this;
  180. result.Essential_ = essential;
  181. return result;
  182. }
  183. TLogger TLogger::WithStructuredValidator(TStructuredValidator validator) const
  184. {
  185. auto result = *this;
  186. result.StructuredValidators_.push_back(std::move(validator));
  187. return result;
  188. }
  189. TLogger TLogger::WithMinLevel(ELogLevel minLevel) const
  190. {
  191. auto result = *this;
  192. if (result) {
  193. result.MinLevel_ = minLevel;
  194. }
  195. return result;
  196. }
  197. const TString& TLogger::GetTag() const
  198. {
  199. return Tag_;
  200. }
  201. const TLogger::TStructuredTags& TLogger::GetStructuredTags() const
  202. {
  203. return StructuredTags_;
  204. }
  205. const TLogger::TStructuredValidators& TLogger::GetStructuredValidators() const
  206. {
  207. return StructuredValidators_;
  208. }
  209. ////////////////////////////////////////////////////////////////////////////////
  210. void LogStructuredEvent(
  211. const TLogger& logger,
  212. NYson::TYsonString message,
  213. ELogLevel level)
  214. {
  215. YT_VERIFY(message.GetType() == NYson::EYsonType::MapFragment);
  216. if (!logger.GetStructuredValidators().empty()) {
  217. auto samplingRate = logger.GetCategory()->StructuredValidationSamplingRate.load();
  218. auto p = RandomNumber<double>();
  219. if (p < samplingRate) {
  220. for (const auto& validator : logger.GetStructuredValidators()) {
  221. validator(message);
  222. }
  223. }
  224. }
  225. auto loggingContext = GetLoggingContext();
  226. auto event = NDetail::CreateLogEvent(
  227. loggingContext,
  228. logger,
  229. level);
  230. event.MessageKind = ELogMessageKind::Structured;
  231. event.MessageRef = message.ToSharedRef();
  232. event.Family = ELogFamily::Structured;
  233. logger.Write(std::move(event));
  234. }
  235. ////////////////////////////////////////////////////////////////////////////////
  236. } // namespace NYT::NLogging