logger-inl.h 8.3 KB

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