logger.cpp 7.5 KB

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