logger-inl.h 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305
  1. #ifndef LOGGER_INL_H_
  2. #error "Direct inclusion of this file is not allowed, include logger.h"
  3. // For the sake of sane code completion.
  4. #include "logger.h"
  5. #endif
  6. #undef LOGGER_INL_H_
  7. #include <library/cpp/yt/yson_string/convert.h>
  8. #include <library/cpp/yt/yson_string/string.h>
  9. #include <library/cpp/yt/misc/tls.h>
  10. namespace NYT::NLogging {
  11. ////////////////////////////////////////////////////////////////////////////////
  12. inline bool TLogger::IsAnchorUpToDate(const TLoggingAnchor& position) const
  13. {
  14. return
  15. !Category_ ||
  16. position.CurrentVersion == Category_->ActualVersion->load(std::memory_order::relaxed);
  17. }
  18. template <class... TArgs>
  19. void TLogger::AddTag(const char* format, TArgs&&... args)
  20. {
  21. AddRawTag(Format(format, std::forward<TArgs>(args)...));
  22. }
  23. template <class TType>
  24. void TLogger::AddStructuredTag(TStringBuf key, TType value)
  25. {
  26. StructuredTags_.emplace_back(key, NYson::ConvertToYsonString(value));
  27. }
  28. template <class... TArgs>
  29. TLogger TLogger::WithTag(const char* format, TArgs&&... args) const
  30. {
  31. auto result = *this;
  32. result.AddTag(format, std::forward<TArgs>(args)...);
  33. return result;
  34. }
  35. template <class TType>
  36. TLogger TLogger::WithStructuredTag(TStringBuf key, TType value) const
  37. {
  38. auto result = *this;
  39. result.AddStructuredTag(key, value);
  40. return result;
  41. }
  42. Y_FORCE_INLINE bool TLogger::IsLevelEnabled(ELogLevel level) const
  43. {
  44. // This is the first check which is intended to be inlined next to
  45. // logging invocation point. Check below is almost zero-cost due
  46. // to branch prediction (which requires inlining for proper work).
  47. if (level < MinLevel_) {
  48. return false;
  49. }
  50. // Next check is heavier and requires full log manager definition which
  51. // is undesirable in -inl.h header file. This is why we extract it
  52. // to a separate method which is implemented in cpp file.
  53. return IsLevelEnabledHeavy(level);
  54. }
  55. ////////////////////////////////////////////////////////////////////////////////
  56. namespace NDetail {
  57. struct TMessageStringBuilderContext
  58. {
  59. TSharedMutableRef Chunk;
  60. };
  61. struct TMessageBufferTag
  62. { };
  63. class TMessageStringBuilder
  64. : public TStringBuilderBase
  65. {
  66. public:
  67. TSharedRef Flush();
  68. // For testing only.
  69. static void DisablePerThreadCache();
  70. protected:
  71. void DoReset() override;
  72. void DoReserve(size_t newLength) override;
  73. private:
  74. struct TPerThreadCache
  75. {
  76. ~TPerThreadCache();
  77. TSharedMutableRef Chunk;
  78. size_t ChunkOffset = 0;
  79. };
  80. TSharedMutableRef Buffer_;
  81. static YT_THREAD_LOCAL(TPerThreadCache*) Cache_;
  82. static YT_THREAD_LOCAL(bool) CacheDestroyed_;
  83. static TPerThreadCache* GetCache();
  84. static constexpr size_t ChunkSize = 128_KB - 64;
  85. };
  86. inline bool HasMessageTags(
  87. const TLoggingContext& loggingContext,
  88. const TLogger& logger)
  89. {
  90. if (logger.GetTag()) {
  91. return true;
  92. }
  93. if (loggingContext.TraceLoggingTag) {
  94. return true;
  95. }
  96. return false;
  97. }
  98. inline void AppendMessageTags(
  99. TStringBuilderBase* builder,
  100. const TLoggingContext& loggingContext,
  101. const TLogger& logger)
  102. {
  103. bool printComma = false;
  104. if (const auto& loggerTag = logger.GetTag()) {
  105. builder->AppendString(loggerTag);
  106. printComma = true;
  107. }
  108. if (auto traceLoggingTag = loggingContext.TraceLoggingTag) {
  109. if (printComma) {
  110. builder->AppendString(TStringBuf(", "));
  111. }
  112. builder->AppendString(traceLoggingTag);
  113. }
  114. }
  115. inline void AppendLogMessage(
  116. TStringBuilderBase* builder,
  117. const TLoggingContext& loggingContext,
  118. const TLogger& logger,
  119. TRef message)
  120. {
  121. if (HasMessageTags(loggingContext, logger)) {
  122. if (message.Size() >= 1 && message[message.Size() - 1] == ')') {
  123. builder->AppendString(TStringBuf(message.Begin(), message.Size() - 1));
  124. builder->AppendString(TStringBuf(", "));
  125. } else {
  126. builder->AppendString(TStringBuf(message.Begin(), message.Size()));
  127. builder->AppendString(TStringBuf(" ("));
  128. }
  129. AppendMessageTags(builder, loggingContext, logger);
  130. builder->AppendChar(')');
  131. } else {
  132. builder->AppendString(TStringBuf(message.Begin(), message.Size()));
  133. }
  134. }
  135. template <class... TArgs>
  136. void AppendLogMessageWithFormat(
  137. TStringBuilderBase* builder,
  138. const TLoggingContext& loggingContext,
  139. const TLogger& logger,
  140. TStringBuf format,
  141. TArgs&&... args)
  142. {
  143. if (HasMessageTags(loggingContext, logger)) {
  144. if (format.size() >= 2 && format[format.size() - 1] == ')') {
  145. builder->AppendFormat(format.substr(0, format.size() - 1), std::forward<TArgs>(args)...);
  146. builder->AppendString(TStringBuf(", "));
  147. } else {
  148. builder->AppendFormat(format, std::forward<TArgs>(args)...);
  149. builder->AppendString(TStringBuf(" ("));
  150. }
  151. AppendMessageTags(builder, loggingContext, logger);
  152. builder->AppendChar(')');
  153. } else {
  154. builder->AppendFormat(format, std::forward<TArgs>(args)...);
  155. }
  156. }
  157. struct TLogMessage
  158. {
  159. TSharedRef MessageRef;
  160. TStringBuf Anchor;
  161. };
  162. template <size_t Length, class... TArgs>
  163. TLogMessage BuildLogMessage(
  164. const TLoggingContext& loggingContext,
  165. const TLogger& logger,
  166. const char (&format)[Length],
  167. TArgs&&... args)
  168. {
  169. TMessageStringBuilder builder;
  170. AppendLogMessageWithFormat(&builder, loggingContext, logger, format, std::forward<TArgs>(args)...);
  171. return {builder.Flush(), format};
  172. }
  173. template <class T>
  174. TLogMessage BuildLogMessage(
  175. const TLoggingContext& loggingContext,
  176. const TLogger& logger,
  177. const T& obj)
  178. {
  179. TMessageStringBuilder builder;
  180. FormatValue(&builder, obj, TStringBuf());
  181. if (HasMessageTags(loggingContext, logger)) {
  182. builder.AppendString(TStringBuf(" ("));
  183. AppendMessageTags(&builder, loggingContext, logger);
  184. builder.AppendChar(')');
  185. }
  186. return {builder.Flush(), TStringBuf()};
  187. }
  188. inline TLogMessage BuildLogMessage(
  189. const TLoggingContext& loggingContext,
  190. const TLogger& logger,
  191. TStringBuf message)
  192. {
  193. TMessageStringBuilder builder;
  194. builder.AppendString(message);
  195. if (HasMessageTags(loggingContext, logger)) {
  196. builder.AppendString(TStringBuf(" ("));
  197. AppendMessageTags(&builder, loggingContext, logger);
  198. builder.AppendChar(')');
  199. }
  200. return {builder.Flush(), message};
  201. }
  202. template <size_t Length>
  203. TLogMessage BuildLogMessage(
  204. const TLoggingContext& loggingContext,
  205. const TLogger& logger,
  206. const char (&message)[Length])
  207. {
  208. return BuildLogMessage(
  209. loggingContext,
  210. logger,
  211. TStringBuf(message));
  212. }
  213. inline TLogMessage BuildLogMessage(
  214. const TLoggingContext& loggingContext,
  215. const TLogger& logger,
  216. TSharedRef&& message)
  217. {
  218. if (HasMessageTags(loggingContext, logger)) {
  219. TMessageStringBuilder builder;
  220. AppendLogMessage(&builder, loggingContext, logger, message);
  221. return {builder.Flush(), TStringBuf()};
  222. } else {
  223. return {std::move(message), TStringBuf()};
  224. }
  225. }
  226. inline TLogEvent CreateLogEvent(
  227. const TLoggingContext& loggingContext,
  228. const TLogger& logger,
  229. ELogLevel level)
  230. {
  231. TLogEvent event;
  232. event.Instant = loggingContext.Instant;
  233. event.Category = logger.GetCategory();
  234. event.Essential = logger.IsEssential();
  235. event.Level = level;
  236. event.ThreadId = loggingContext.ThreadId;
  237. event.ThreadName = loggingContext.ThreadName;
  238. event.FiberId = loggingContext.FiberId;
  239. event.TraceId = loggingContext.TraceId;
  240. event.RequestId = loggingContext.RequestId;
  241. return event;
  242. }
  243. void OnCriticalLogEvent(
  244. const TLogger& logger,
  245. const TLogEvent& event);
  246. inline void LogEventImpl(
  247. const TLoggingContext& loggingContext,
  248. const TLogger& logger,
  249. ELogLevel level,
  250. ::TSourceLocation sourceLocation,
  251. TSharedRef message)
  252. {
  253. auto event = CreateLogEvent(loggingContext, logger, level);
  254. event.MessageKind = ELogMessageKind::Unstructured;
  255. event.MessageRef = std::move(message);
  256. event.Family = ELogFamily::PlainText;
  257. event.SourceFile = sourceLocation.File;
  258. event.SourceLine = sourceLocation.Line;
  259. logger.Write(std::move(event));
  260. if (Y_UNLIKELY(event.Level >= ELogLevel::Alert)) {
  261. OnCriticalLogEvent(logger, event);
  262. }
  263. }
  264. } // namespace NDetail
  265. ////////////////////////////////////////////////////////////////////////////////
  266. } // namespace NYT::NLogging