log.h 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369
  1. #pragma once
  2. #include "defs.h"
  3. #include "log_iface.h"
  4. #include "log_settings.h"
  5. #include "actorsystem.h"
  6. #include "events.h"
  7. #include "event_local.h"
  8. #include "hfunc.h"
  9. #include "mon.h"
  10. #include <util/generic/vector.h>
  11. #include <util/string/printf.h>
  12. #include <util/string/builder.h>
  13. #include <library/cpp/logger/all.h>
  14. #include <library/cpp/monlib/dynamic_counters/counters.h>
  15. #include <library/cpp/monlib/metrics/metric_registry.h>
  16. #include <library/cpp/json/writer/json.h>
  17. #include <library/cpp/svnversion/svnversion.h>
  18. #include <library/cpp/actors/memory_log/memlog.h>
  19. // TODO: limit number of messages per second
  20. // TODO: make TLogComponentLevelRequest/Response network messages
  21. #define IS_LOG_PRIORITY_ENABLED(actorCtxOrSystem, priority, component) \
  22. (static_cast<::NActors::NLog::TSettings*>((actorCtxOrSystem).LoggerSettings()) && \
  23. static_cast<::NActors::NLog::TSettings*>((actorCtxOrSystem).LoggerSettings())->Satisfies( \
  24. static_cast<::NActors::NLog::EPriority>(priority), \
  25. static_cast<::NActors::NLog::EComponent>(component), \
  26. 0ull) \
  27. )
  28. #define LOG_LOG_SAMPLED_BY(actorCtxOrSystem, priority, component, sampleBy, ...) \
  29. do { \
  30. ::NActors::NLog::TSettings* mSettings = static_cast<::NActors::NLog::TSettings*>((actorCtxOrSystem).LoggerSettings()); \
  31. ::NActors::NLog::EPriority mPriority = static_cast<::NActors::NLog::EPriority>(priority); \
  32. ::NActors::NLog::EComponent mComponent = static_cast<::NActors::NLog::EComponent>(component); \
  33. if (mSettings && mSettings->Satisfies(mPriority, mComponent, sampleBy)) { \
  34. ::NActors::MemLogAdapter( \
  35. actorCtxOrSystem, priority, component, __VA_ARGS__); \
  36. } \
  37. } while (0) /**/
  38. #define LOG_LOG_S_SAMPLED_BY(actorCtxOrSystem, priority, component, sampleBy, stream) \
  39. LOG_LOG_SAMPLED_BY(actorCtxOrSystem, priority, component, sampleBy, "%s", [&]() { \
  40. TStringBuilder logStringBuilder; \
  41. logStringBuilder << stream; \
  42. return static_cast<TString>(logStringBuilder); \
  43. }().data())
  44. #define LOG_LOG(actorCtxOrSystem, priority, component, ...) LOG_LOG_SAMPLED_BY(actorCtxOrSystem, priority, component, 0ull, __VA_ARGS__)
  45. #define LOG_LOG_S(actorCtxOrSystem, priority, component, stream) LOG_LOG_S_SAMPLED_BY(actorCtxOrSystem, priority, component, 0ull, stream)
  46. // use these macros for logging via actor system or actor context
  47. #define LOG_EMERG(actorCtxOrSystem, component, ...) LOG_LOG(actorCtxOrSystem, NActors::NLog::PRI_EMERG, component, __VA_ARGS__)
  48. #define LOG_ALERT(actorCtxOrSystem, component, ...) LOG_LOG(actorCtxOrSystem, NActors::NLog::PRI_ALERT, component, __VA_ARGS__)
  49. #define LOG_CRIT(actorCtxOrSystem, component, ...) LOG_LOG(actorCtxOrSystem, NActors::NLog::PRI_CRIT, component, __VA_ARGS__)
  50. #define LOG_ERROR(actorCtxOrSystem, component, ...) LOG_LOG(actorCtxOrSystem, NActors::NLog::PRI_ERROR, component, __VA_ARGS__)
  51. #define LOG_WARN(actorCtxOrSystem, component, ...) LOG_LOG(actorCtxOrSystem, NActors::NLog::PRI_WARN, component, __VA_ARGS__)
  52. #define LOG_NOTICE(actorCtxOrSystem, component, ...) LOG_LOG(actorCtxOrSystem, NActors::NLog::PRI_NOTICE, component, __VA_ARGS__)
  53. #define LOG_INFO(actorCtxOrSystem, component, ...) LOG_LOG(actorCtxOrSystem, NActors::NLog::PRI_INFO, component, __VA_ARGS__)
  54. #define LOG_DEBUG(actorCtxOrSystem, component, ...) LOG_LOG(actorCtxOrSystem, NActors::NLog::PRI_DEBUG, component, __VA_ARGS__)
  55. #define LOG_TRACE(actorCtxOrSystem, component, ...) LOG_LOG(actorCtxOrSystem, NActors::NLog::PRI_TRACE, component, __VA_ARGS__)
  56. #define LOG_EMERG_S(actorCtxOrSystem, component, stream) LOG_LOG_S(actorCtxOrSystem, NActors::NLog::PRI_EMERG, component, stream)
  57. #define LOG_ALERT_S(actorCtxOrSystem, component, stream) LOG_LOG_S(actorCtxOrSystem, NActors::NLog::PRI_ALERT, component, stream)
  58. #define LOG_CRIT_S(actorCtxOrSystem, component, stream) LOG_LOG_S(actorCtxOrSystem, NActors::NLog::PRI_CRIT, component, stream)
  59. #define LOG_ERROR_S(actorCtxOrSystem, component, stream) LOG_LOG_S(actorCtxOrSystem, NActors::NLog::PRI_ERROR, component, stream)
  60. #define LOG_WARN_S(actorCtxOrSystem, component, stream) LOG_LOG_S(actorCtxOrSystem, NActors::NLog::PRI_WARN, component, stream)
  61. #define LOG_NOTICE_S(actorCtxOrSystem, component, stream) LOG_LOG_S(actorCtxOrSystem, NActors::NLog::PRI_NOTICE, component, stream)
  62. #define LOG_INFO_S(actorCtxOrSystem, component, stream) LOG_LOG_S(actorCtxOrSystem, NActors::NLog::PRI_INFO, component, stream)
  63. #define LOG_DEBUG_S(actorCtxOrSystem, component, stream) LOG_LOG_S(actorCtxOrSystem, NActors::NLog::PRI_DEBUG, component, stream)
  64. #define LOG_TRACE_S(actorCtxOrSystem, component, stream) LOG_LOG_S(actorCtxOrSystem, NActors::NLog::PRI_TRACE, component, stream)
  65. #define LOG_EMERG_SAMPLED_BY(actorCtxOrSystem, component, sampleBy, ...) LOG_LOG_SAMPLED_BY(actorCtxOrSystem, NActors::NLog::PRI_EMERG, component, sampleBy, __VA_ARGS__)
  66. #define LOG_ALERT_SAMPLED_BY(actorCtxOrSystem, component, sampleBy, ...) LOG_LOG_SAMPLED_BY(actorCtxOrSystem, NActors::NLog::PRI_ALERT, component, sampleBy, __VA_ARGS__)
  67. #define LOG_CRIT_SAMPLED_BY(actorCtxOrSystem, component, sampleBy, ...) LOG_LOG_SAMPLED_BY(actorCtxOrSystem, NActors::NLog::PRI_CRIT, component, sampleBy, __VA_ARGS__)
  68. #define LOG_ERROR_SAMPLED_BY(actorCtxOrSystem, component, sampleBy, ...) LOG_LOG_SAMPLED_BY(actorCtxOrSystem, NActors::NLog::PRI_ERROR, component, sampleBy, __VA_ARGS__)
  69. #define LOG_WARN_SAMPLED_BY(actorCtxOrSystem, component, sampleBy, ...) LOG_LOG_SAMPLED_BY(actorCtxOrSystem, NActors::NLog::PRI_WARN, component, sampleBy, __VA_ARGS__)
  70. #define LOG_NOTICE_SAMPLED_BY(actorCtxOrSystem, component, sampleBy, ...) LOG_LOG_SAMPLED_BY(actorCtxOrSystem, NActors::NLog::PRI_NOTICE, component, sampleBy, __VA_ARGS__)
  71. #define LOG_INFO_SAMPLED_BY(actorCtxOrSystem, component, sampleBy, ...) LOG_LOG_SAMPLED_BY(actorCtxOrSystem, NActors::NLog::PRI_INFO, component, sampleBy, __VA_ARGS__)
  72. #define LOG_DEBUG_SAMPLED_BY(actorCtxOrSystem, component, sampleBy, ...) LOG_LOG_SAMPLED_BY(actorCtxOrSystem, NActors::NLog::PRI_DEBUG, component, sampleBy, __VA_ARGS__)
  73. #define LOG_TRACE_SAMPLED_BY(actorCtxOrSystem, component, sampleBy, ...) LOG_LOG_SAMPLED_BY(actorCtxOrSystem, NActors::NLog::PRI_TRACE, component, sampleBy, __VA_ARGS__)
  74. #define LOG_EMERG_S_SAMPLED_BY(actorCtxOrSystem, component, sampleBy, stream) LOG_LOG_S_SAMPLED_BY(actorCtxOrSystem, NActors::NLog::PRI_EMERG, component, sampleBy, stream)
  75. #define LOG_ALERT_S_SAMPLED_BY(actorCtxOrSystem, component, sampleBy, stream) LOG_LOG_S_SAMPLED_BY(actorCtxOrSystem, NActors::NLog::PRI_ALERT, component, sampleBy, stream)
  76. #define LOG_CRIT_S_SAMPLED_BY(actorCtxOrSystem, component, sampleBy, stream) LOG_LOG_S_SAMPLED_BY(actorCtxOrSystem, NActors::NLog::PRI_CRIT, component, sampleBy, stream)
  77. #define LOG_ERROR_S_SAMPLED_BY(actorCtxOrSystem, component, sampleBy, stream) LOG_LOG_S_SAMPLED_BY(actorCtxOrSystem, NActors::NLog::PRI_ERROR, component, sampleBy, stream)
  78. #define LOG_WARN_S_SAMPLED_BY(actorCtxOrSystem, component, sampleBy, stream) LOG_LOG_S_SAMPLED_BY(actorCtxOrSystem, NActors::NLog::PRI_WARN, component, sampleBy, stream)
  79. #define LOG_NOTICE_S_SAMPLED_BY(actorCtxOrSystem, component, sampleBy, stream) LOG_LOG_S_SAMPLED_BY(actorCtxOrSystem, NActors::NLog::PRI_NOTICE, component, sampleBy, stream)
  80. #define LOG_INFO_S_SAMPLED_BY(actorCtxOrSystem, component, sampleBy, stream) LOG_LOG_S_SAMPLED_BY(actorCtxOrSystem, NActors::NLog::PRI_INFO, component, sampleBy, stream)
  81. #define LOG_DEBUG_S_SAMPLED_BY(actorCtxOrSystem, component, sampleBy, stream) LOG_LOG_S_SAMPLED_BY(actorCtxOrSystem, NActors::NLog::PRI_DEBUG, component, sampleBy, stream)
  82. #define LOG_TRACE_S_SAMPLED_BY(actorCtxOrSystem, component, sampleBy, stream) LOG_LOG_S_SAMPLED_BY(actorCtxOrSystem, NActors::NLog::PRI_TRACE, component, sampleBy, stream)
  83. // Log Throttling
  84. #define LOG_LOG_THROTTLE(throttler, actorCtxOrSystem, priority, component, ...) \
  85. do { \
  86. if ((throttler).Kick()) { \
  87. LOG_LOG(actorCtxOrSystem, priority, component, __VA_ARGS__); \
  88. } \
  89. } while (0) /**/
  90. #define TRACE_EVENT(component) \
  91. const auto& currentTracer = component; \
  92. if (ev->HasEvent()) { \
  93. LOG_TRACE(*TlsActivationContext, currentTracer, "%s, received event# %" PRIu32 ", Sender %s, Recipient %s: %s", \
  94. __FUNCTION__, ev->Type, ev->Sender.ToString().data(), SelfId().ToString().data(), ev->GetBase()->ToString().substr(0, 1000).data()); \
  95. } else { \
  96. LOG_TRACE(*TlsActivationContext, currentTracer, "%s, received event# %" PRIu32 ", Sender %s, Recipient %s", \
  97. __FUNCTION__, ev->Type, ev->Sender.ToString().data(), ev->Recipient.ToString().data()); \
  98. }
  99. #define TRACE_EVENT_TYPE(eventType) LOG_TRACE(*TlsActivationContext, currentTracer, "%s, processing event %s", __FUNCTION__, eventType)
  100. class TLog;
  101. class TLogBackend;
  102. namespace NActors {
  103. class TLoggerActor;
  104. ////////////////////////////////////////////////////////////////////////////////
  105. // SET LOG LEVEL FOR A COMPONENT
  106. ////////////////////////////////////////////////////////////////////////////////
  107. class TLogComponentLevelRequest: public TEventLocal<TLogComponentLevelRequest, int(NLog::EEv::LevelReq)> {
  108. public:
  109. // set given priority for the component
  110. TLogComponentLevelRequest(NLog::EPriority priority, NLog::EComponent component)
  111. : Priority(priority)
  112. , Component(component)
  113. {
  114. }
  115. // set given priority for all components
  116. TLogComponentLevelRequest(NLog::EPriority priority)
  117. : Priority(priority)
  118. , Component(NLog::InvalidComponent)
  119. {
  120. }
  121. protected:
  122. NLog::EPriority Priority;
  123. NLog::EComponent Component;
  124. friend class TLoggerActor;
  125. };
  126. class TLogComponentLevelResponse: public TEventLocal<TLogComponentLevelResponse, int(NLog::EEv::LevelResp)> {
  127. public:
  128. TLogComponentLevelResponse(int code, const TString& explanation)
  129. : Code(code)
  130. , Explanation(explanation)
  131. {
  132. }
  133. int GetCode() const {
  134. return Code;
  135. }
  136. const TString& GetExplanation() const {
  137. return Explanation;
  138. }
  139. protected:
  140. int Code;
  141. TString Explanation;
  142. };
  143. class TLogIgnored: public TEventLocal<TLogIgnored, int(NLog::EEv::Ignored)> {
  144. public:
  145. TLogIgnored() {
  146. }
  147. };
  148. ////////////////////////////////////////////////////////////////////////////////
  149. // LOGGER ACTOR
  150. ////////////////////////////////////////////////////////////////////////////////
  151. class ILoggerMetrics {
  152. public:
  153. virtual ~ILoggerMetrics() = default;
  154. virtual void IncActorMsgs() = 0;
  155. virtual void IncDirectMsgs() = 0;
  156. virtual void IncLevelRequests() = 0;
  157. virtual void IncIgnoredMsgs() = 0;
  158. virtual void IncAlertMsgs() = 0;
  159. virtual void IncEmergMsgs() = 0;
  160. virtual void IncDroppedMsgs() = 0;
  161. virtual void GetOutputHtml(IOutputStream&) = 0;
  162. };
  163. class TLoggerActor: public TActor<TLoggerActor> {
  164. public:
  165. static constexpr IActor::EActivityType ActorActivityType() {
  166. return IActor::LOG_ACTOR;
  167. }
  168. TLoggerActor(TIntrusivePtr<NLog::TSettings> settings,
  169. TAutoPtr<TLogBackend> logBackend,
  170. TIntrusivePtr<NMonitoring::TDynamicCounters> counters);
  171. TLoggerActor(TIntrusivePtr<NLog::TSettings> settings,
  172. std::shared_ptr<TLogBackend> logBackend,
  173. TIntrusivePtr<NMonitoring::TDynamicCounters> counters);
  174. TLoggerActor(TIntrusivePtr<NLog::TSettings> settings,
  175. TAutoPtr<TLogBackend> logBackend,
  176. std::shared_ptr<NMonitoring::TMetricRegistry> metrics);
  177. TLoggerActor(TIntrusivePtr<NLog::TSettings> settings,
  178. std::shared_ptr<TLogBackend> logBackend,
  179. std::shared_ptr<NMonitoring::TMetricRegistry> metrics);
  180. ~TLoggerActor();
  181. void StateFunc(TAutoPtr<IEventHandle>& ev, const TActorContext& ctx) {
  182. switch (ev->GetTypeRewrite()) {
  183. HFunc(TLogIgnored, HandleIgnoredEvent);
  184. HFunc(NLog::TEvLog, HandleLogEvent);
  185. HFunc(TLogComponentLevelRequest, HandleLogComponentLevelRequest);
  186. HFunc(NMon::TEvHttpInfo, HandleMonInfo);
  187. }
  188. }
  189. STFUNC(StateDefunct) {
  190. switch (ev->GetTypeRewrite()) {
  191. cFunc(TLogIgnored::EventType, HandleIgnoredEventDrop);
  192. hFunc(NLog::TEvLog, HandleLogEventDrop);
  193. HFunc(TLogComponentLevelRequest, HandleLogComponentLevelRequest);
  194. HFunc(NMon::TEvHttpInfo, HandleMonInfo);
  195. cFunc(TEvents::TEvWakeup::EventType, HandleWakeup);
  196. }
  197. }
  198. // Directly call logger instead of sending a message
  199. void Log(TInstant time, NLog::EPriority priority, NLog::EComponent component, const char* c, ...);
  200. static void Throttle(const NLog::TSettings& settings);
  201. private:
  202. TIntrusivePtr<NLog::TSettings> Settings;
  203. std::shared_ptr<TLogBackend> LogBackend;
  204. ui64 IgnoredCount = 0;
  205. ui64 PassedCount = 0;
  206. static TAtomic IsOverflow;
  207. TDuration WakeupInterval{TDuration::Seconds(5)};
  208. std::unique_ptr<ILoggerMetrics> Metrics;
  209. void BecomeDefunct();
  210. void HandleIgnoredEvent(TLogIgnored::TPtr& ev, const NActors::TActorContext& ctx);
  211. void HandleIgnoredEventDrop();
  212. void HandleLogEvent(NLog::TEvLog::TPtr& ev, const TActorContext& ctx);
  213. void HandleLogEventDrop(const NLog::TEvLog::TPtr& ev);
  214. void HandleLogComponentLevelRequest(TLogComponentLevelRequest::TPtr& ev, const TActorContext& ctx);
  215. void HandleMonInfo(NMon::TEvHttpInfo::TPtr& ev, const TActorContext& ctx);
  216. void HandleWakeup();
  217. [[nodiscard]] bool OutputRecord(TInstant time, NLog::EPrio priority, NLog::EComponent component, const TString& formatted) noexcept;
  218. void RenderComponentPriorities(IOutputStream& str);
  219. void LogIgnoredCount(TInstant now);
  220. void WriteMessageStat(const NLog::TEvLog& ev);
  221. static const char* FormatLocalTimestamp(TInstant time, char* buf);
  222. };
  223. ////////////////////////////////////////////////////////////////////////////////
  224. // LOG THROTTLING
  225. // TTrivialLogThrottler -- log a message every 'period' duration
  226. // Use case:
  227. // TTrivialLogThrottler throttler(TDuration::Minutes(1));
  228. // ....
  229. // LOG_LOG_THROTTLE(throttler, ctx, NActors::NLog::PRI_ERROR, SOME, "Error");
  230. ////////////////////////////////////////////////////////////////////////////////
  231. class TTrivialLogThrottler {
  232. public:
  233. TTrivialLogThrottler(TDuration period)
  234. : Period(period)
  235. {
  236. }
  237. // return value:
  238. // true -- write to log
  239. // false -- don't write to log, throttle
  240. bool Kick() {
  241. auto now = TInstant::Now();
  242. if (now >= (LastWrite + Period)) {
  243. LastWrite = now;
  244. return true;
  245. } else {
  246. return false;
  247. }
  248. }
  249. private:
  250. TInstant LastWrite;
  251. TDuration Period;
  252. };
  253. ////////////////////////////////////////////////////////////////////////////////
  254. // SYSLOG BACKEND
  255. ////////////////////////////////////////////////////////////////////////////////
  256. TAutoPtr<TLogBackend> CreateSysLogBackend(const TString& ident,
  257. bool logPError, bool logCons);
  258. TAutoPtr<TLogBackend> CreateStderrBackend();
  259. TAutoPtr<TLogBackend> CreateFileBackend(const TString& fileName);
  260. TAutoPtr<TLogBackend> CreateNullBackend();
  261. TAutoPtr<TLogBackend> CreateCompositeLogBackend(TVector<TAutoPtr<TLogBackend>>&& underlyingBackends);
  262. /////////////////////////////////////////////////////////////////////
  263. // Logging adaptors for memory log and logging into filesystem
  264. /////////////////////////////////////////////////////////////////////
  265. namespace NDetail {
  266. inline void Y_PRINTF_FORMAT(2, 3) PrintfV(TString& dst, const char* format, ...) {
  267. va_list params;
  268. va_start(params, format);
  269. vsprintf(dst, format, params);
  270. va_end(params);
  271. }
  272. inline void PrintfV(TString& dst, const char* format, va_list params) {
  273. vsprintf(dst, format, params);
  274. }
  275. } // namespace NDetail
  276. template <typename TCtx>
  277. inline void DeliverLogMessage(TCtx& ctx, NLog::EPriority mPriority, NLog::EComponent mComponent, TString &&str)
  278. {
  279. const NLog::TSettings *mSettings = ctx.LoggerSettings();
  280. TLoggerActor::Throttle(*mSettings);
  281. ctx.Send(new IEventHandle(mSettings->LoggerActorId, TActorId(), new NLog::TEvLog(mPriority, mComponent, std::move(str))));
  282. }
  283. template <typename TCtx, typename... TArgs>
  284. inline void MemLogAdapter(
  285. TCtx& actorCtxOrSystem,
  286. NLog::EPriority mPriority,
  287. NLog::EComponent mComponent,
  288. const char* format, TArgs&&... params) {
  289. TString Formatted;
  290. if constexpr (sizeof... (params) > 0) {
  291. NDetail::PrintfV(Formatted, format, std::forward<TArgs>(params)...);
  292. } else {
  293. NDetail::PrintfV(Formatted, "%s", format);
  294. }
  295. MemLogWrite(Formatted.data(), Formatted.size(), true);
  296. DeliverLogMessage(actorCtxOrSystem, mPriority, mComponent, std::move(Formatted));
  297. }
  298. template <typename TCtx>
  299. Y_WRAPPER inline void MemLogAdapter(
  300. TCtx& actorCtxOrSystem,
  301. NLog::EPriority mPriority,
  302. NLog::EComponent mComponent,
  303. const TString& str) {
  304. MemLogWrite(str.data(), str.size(), true);
  305. DeliverLogMessage(actorCtxOrSystem, mPriority, mComponent, TString(str));
  306. }
  307. template <typename TCtx>
  308. Y_WRAPPER inline void MemLogAdapter(
  309. TCtx& actorCtxOrSystem,
  310. NLog::EPriority mPriority,
  311. NLog::EComponent mComponent,
  312. TString&& str) {
  313. MemLogWrite(str.data(), str.size(), true);
  314. DeliverLogMessage(actorCtxOrSystem, mPriority, mComponent, std::move(str));
  315. }
  316. }