123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369 |
- #pragma once
- #include "defs.h"
- #include "log_iface.h"
- #include "log_settings.h"
- #include "actorsystem.h"
- #include "events.h"
- #include "event_local.h"
- #include "hfunc.h"
- #include "mon.h"
- #include <util/generic/vector.h>
- #include <util/string/printf.h>
- #include <util/string/builder.h>
- #include <library/cpp/logger/all.h>
- #include <library/cpp/monlib/dynamic_counters/counters.h>
- #include <library/cpp/monlib/metrics/metric_registry.h>
- #include <library/cpp/json/writer/json.h>
- #include <library/cpp/svnversion/svnversion.h>
- #include <library/cpp/actors/memory_log/memlog.h>
- // TODO: limit number of messages per second
- // TODO: make TLogComponentLevelRequest/Response network messages
- #define IS_LOG_PRIORITY_ENABLED(actorCtxOrSystem, priority, component) \
- (static_cast<::NActors::NLog::TSettings*>((actorCtxOrSystem).LoggerSettings()) && \
- static_cast<::NActors::NLog::TSettings*>((actorCtxOrSystem).LoggerSettings())->Satisfies( \
- static_cast<::NActors::NLog::EPriority>(priority), \
- static_cast<::NActors::NLog::EComponent>(component), \
- 0ull) \
- )
- #define LOG_LOG_SAMPLED_BY(actorCtxOrSystem, priority, component, sampleBy, ...) \
- do { \
- ::NActors::NLog::TSettings* mSettings = static_cast<::NActors::NLog::TSettings*>((actorCtxOrSystem).LoggerSettings()); \
- ::NActors::NLog::EPriority mPriority = static_cast<::NActors::NLog::EPriority>(priority); \
- ::NActors::NLog::EComponent mComponent = static_cast<::NActors::NLog::EComponent>(component); \
- if (mSettings && mSettings->Satisfies(mPriority, mComponent, sampleBy)) { \
- ::NActors::MemLogAdapter( \
- actorCtxOrSystem, priority, component, __VA_ARGS__); \
- } \
- } while (0) /**/
- #define LOG_LOG_S_SAMPLED_BY(actorCtxOrSystem, priority, component, sampleBy, stream) \
- LOG_LOG_SAMPLED_BY(actorCtxOrSystem, priority, component, sampleBy, "%s", [&]() { \
- TStringBuilder logStringBuilder; \
- logStringBuilder << stream; \
- return static_cast<TString>(logStringBuilder); \
- }().data())
- #define LOG_LOG(actorCtxOrSystem, priority, component, ...) LOG_LOG_SAMPLED_BY(actorCtxOrSystem, priority, component, 0ull, __VA_ARGS__)
- #define LOG_LOG_S(actorCtxOrSystem, priority, component, stream) LOG_LOG_S_SAMPLED_BY(actorCtxOrSystem, priority, component, 0ull, stream)
- // use these macros for logging via actor system or actor context
- #define LOG_EMERG(actorCtxOrSystem, component, ...) LOG_LOG(actorCtxOrSystem, NActors::NLog::PRI_EMERG, component, __VA_ARGS__)
- #define LOG_ALERT(actorCtxOrSystem, component, ...) LOG_LOG(actorCtxOrSystem, NActors::NLog::PRI_ALERT, component, __VA_ARGS__)
- #define LOG_CRIT(actorCtxOrSystem, component, ...) LOG_LOG(actorCtxOrSystem, NActors::NLog::PRI_CRIT, component, __VA_ARGS__)
- #define LOG_ERROR(actorCtxOrSystem, component, ...) LOG_LOG(actorCtxOrSystem, NActors::NLog::PRI_ERROR, component, __VA_ARGS__)
- #define LOG_WARN(actorCtxOrSystem, component, ...) LOG_LOG(actorCtxOrSystem, NActors::NLog::PRI_WARN, component, __VA_ARGS__)
- #define LOG_NOTICE(actorCtxOrSystem, component, ...) LOG_LOG(actorCtxOrSystem, NActors::NLog::PRI_NOTICE, component, __VA_ARGS__)
- #define LOG_INFO(actorCtxOrSystem, component, ...) LOG_LOG(actorCtxOrSystem, NActors::NLog::PRI_INFO, component, __VA_ARGS__)
- #define LOG_DEBUG(actorCtxOrSystem, component, ...) LOG_LOG(actorCtxOrSystem, NActors::NLog::PRI_DEBUG, component, __VA_ARGS__)
- #define LOG_TRACE(actorCtxOrSystem, component, ...) LOG_LOG(actorCtxOrSystem, NActors::NLog::PRI_TRACE, component, __VA_ARGS__)
- #define LOG_EMERG_S(actorCtxOrSystem, component, stream) LOG_LOG_S(actorCtxOrSystem, NActors::NLog::PRI_EMERG, component, stream)
- #define LOG_ALERT_S(actorCtxOrSystem, component, stream) LOG_LOG_S(actorCtxOrSystem, NActors::NLog::PRI_ALERT, component, stream)
- #define LOG_CRIT_S(actorCtxOrSystem, component, stream) LOG_LOG_S(actorCtxOrSystem, NActors::NLog::PRI_CRIT, component, stream)
- #define LOG_ERROR_S(actorCtxOrSystem, component, stream) LOG_LOG_S(actorCtxOrSystem, NActors::NLog::PRI_ERROR, component, stream)
- #define LOG_WARN_S(actorCtxOrSystem, component, stream) LOG_LOG_S(actorCtxOrSystem, NActors::NLog::PRI_WARN, component, stream)
- #define LOG_NOTICE_S(actorCtxOrSystem, component, stream) LOG_LOG_S(actorCtxOrSystem, NActors::NLog::PRI_NOTICE, component, stream)
- #define LOG_INFO_S(actorCtxOrSystem, component, stream) LOG_LOG_S(actorCtxOrSystem, NActors::NLog::PRI_INFO, component, stream)
- #define LOG_DEBUG_S(actorCtxOrSystem, component, stream) LOG_LOG_S(actorCtxOrSystem, NActors::NLog::PRI_DEBUG, component, stream)
- #define LOG_TRACE_S(actorCtxOrSystem, component, stream) LOG_LOG_S(actorCtxOrSystem, NActors::NLog::PRI_TRACE, component, stream)
- #define LOG_EMERG_SAMPLED_BY(actorCtxOrSystem, component, sampleBy, ...) LOG_LOG_SAMPLED_BY(actorCtxOrSystem, NActors::NLog::PRI_EMERG, component, sampleBy, __VA_ARGS__)
- #define LOG_ALERT_SAMPLED_BY(actorCtxOrSystem, component, sampleBy, ...) LOG_LOG_SAMPLED_BY(actorCtxOrSystem, NActors::NLog::PRI_ALERT, component, sampleBy, __VA_ARGS__)
- #define LOG_CRIT_SAMPLED_BY(actorCtxOrSystem, component, sampleBy, ...) LOG_LOG_SAMPLED_BY(actorCtxOrSystem, NActors::NLog::PRI_CRIT, component, sampleBy, __VA_ARGS__)
- #define LOG_ERROR_SAMPLED_BY(actorCtxOrSystem, component, sampleBy, ...) LOG_LOG_SAMPLED_BY(actorCtxOrSystem, NActors::NLog::PRI_ERROR, component, sampleBy, __VA_ARGS__)
- #define LOG_WARN_SAMPLED_BY(actorCtxOrSystem, component, sampleBy, ...) LOG_LOG_SAMPLED_BY(actorCtxOrSystem, NActors::NLog::PRI_WARN, component, sampleBy, __VA_ARGS__)
- #define LOG_NOTICE_SAMPLED_BY(actorCtxOrSystem, component, sampleBy, ...) LOG_LOG_SAMPLED_BY(actorCtxOrSystem, NActors::NLog::PRI_NOTICE, component, sampleBy, __VA_ARGS__)
- #define LOG_INFO_SAMPLED_BY(actorCtxOrSystem, component, sampleBy, ...) LOG_LOG_SAMPLED_BY(actorCtxOrSystem, NActors::NLog::PRI_INFO, component, sampleBy, __VA_ARGS__)
- #define LOG_DEBUG_SAMPLED_BY(actorCtxOrSystem, component, sampleBy, ...) LOG_LOG_SAMPLED_BY(actorCtxOrSystem, NActors::NLog::PRI_DEBUG, component, sampleBy, __VA_ARGS__)
- #define LOG_TRACE_SAMPLED_BY(actorCtxOrSystem, component, sampleBy, ...) LOG_LOG_SAMPLED_BY(actorCtxOrSystem, NActors::NLog::PRI_TRACE, component, sampleBy, __VA_ARGS__)
- #define LOG_EMERG_S_SAMPLED_BY(actorCtxOrSystem, component, sampleBy, stream) LOG_LOG_S_SAMPLED_BY(actorCtxOrSystem, NActors::NLog::PRI_EMERG, component, sampleBy, stream)
- #define LOG_ALERT_S_SAMPLED_BY(actorCtxOrSystem, component, sampleBy, stream) LOG_LOG_S_SAMPLED_BY(actorCtxOrSystem, NActors::NLog::PRI_ALERT, component, sampleBy, stream)
- #define LOG_CRIT_S_SAMPLED_BY(actorCtxOrSystem, component, sampleBy, stream) LOG_LOG_S_SAMPLED_BY(actorCtxOrSystem, NActors::NLog::PRI_CRIT, component, sampleBy, stream)
- #define LOG_ERROR_S_SAMPLED_BY(actorCtxOrSystem, component, sampleBy, stream) LOG_LOG_S_SAMPLED_BY(actorCtxOrSystem, NActors::NLog::PRI_ERROR, component, sampleBy, stream)
- #define LOG_WARN_S_SAMPLED_BY(actorCtxOrSystem, component, sampleBy, stream) LOG_LOG_S_SAMPLED_BY(actorCtxOrSystem, NActors::NLog::PRI_WARN, component, sampleBy, stream)
- #define LOG_NOTICE_S_SAMPLED_BY(actorCtxOrSystem, component, sampleBy, stream) LOG_LOG_S_SAMPLED_BY(actorCtxOrSystem, NActors::NLog::PRI_NOTICE, component, sampleBy, stream)
- #define LOG_INFO_S_SAMPLED_BY(actorCtxOrSystem, component, sampleBy, stream) LOG_LOG_S_SAMPLED_BY(actorCtxOrSystem, NActors::NLog::PRI_INFO, component, sampleBy, stream)
- #define LOG_DEBUG_S_SAMPLED_BY(actorCtxOrSystem, component, sampleBy, stream) LOG_LOG_S_SAMPLED_BY(actorCtxOrSystem, NActors::NLog::PRI_DEBUG, component, sampleBy, stream)
- #define LOG_TRACE_S_SAMPLED_BY(actorCtxOrSystem, component, sampleBy, stream) LOG_LOG_S_SAMPLED_BY(actorCtxOrSystem, NActors::NLog::PRI_TRACE, component, sampleBy, stream)
- // Log Throttling
- #define LOG_LOG_THROTTLE(throttler, actorCtxOrSystem, priority, component, ...) \
- do { \
- if ((throttler).Kick()) { \
- LOG_LOG(actorCtxOrSystem, priority, component, __VA_ARGS__); \
- } \
- } while (0) /**/
- #define TRACE_EVENT(component) \
- const auto& currentTracer = component; \
- if (ev->HasEvent()) { \
- LOG_TRACE(*TlsActivationContext, currentTracer, "%s, received event# %" PRIu32 ", Sender %s, Recipient %s: %s", \
- __FUNCTION__, ev->Type, ev->Sender.ToString().data(), SelfId().ToString().data(), ev->GetBase()->ToString().substr(0, 1000).data()); \
- } else { \
- LOG_TRACE(*TlsActivationContext, currentTracer, "%s, received event# %" PRIu32 ", Sender %s, Recipient %s", \
- __FUNCTION__, ev->Type, ev->Sender.ToString().data(), ev->Recipient.ToString().data()); \
- }
- #define TRACE_EVENT_TYPE(eventType) LOG_TRACE(*TlsActivationContext, currentTracer, "%s, processing event %s", __FUNCTION__, eventType)
- class TLog;
- class TLogBackend;
- namespace NActors {
- class TLoggerActor;
- ////////////////////////////////////////////////////////////////////////////////
- // SET LOG LEVEL FOR A COMPONENT
- ////////////////////////////////////////////////////////////////////////////////
- class TLogComponentLevelRequest: public TEventLocal<TLogComponentLevelRequest, int(NLog::EEv::LevelReq)> {
- public:
- // set given priority for the component
- TLogComponentLevelRequest(NLog::EPriority priority, NLog::EComponent component)
- : Priority(priority)
- , Component(component)
- {
- }
- // set given priority for all components
- TLogComponentLevelRequest(NLog::EPriority priority)
- : Priority(priority)
- , Component(NLog::InvalidComponent)
- {
- }
- protected:
- NLog::EPriority Priority;
- NLog::EComponent Component;
- friend class TLoggerActor;
- };
- class TLogComponentLevelResponse: public TEventLocal<TLogComponentLevelResponse, int(NLog::EEv::LevelResp)> {
- public:
- TLogComponentLevelResponse(int code, const TString& explanation)
- : Code(code)
- , Explanation(explanation)
- {
- }
- int GetCode() const {
- return Code;
- }
- const TString& GetExplanation() const {
- return Explanation;
- }
- protected:
- int Code;
- TString Explanation;
- };
- class TLogIgnored: public TEventLocal<TLogIgnored, int(NLog::EEv::Ignored)> {
- public:
- TLogIgnored() {
- }
- };
- ////////////////////////////////////////////////////////////////////////////////
- // LOGGER ACTOR
- ////////////////////////////////////////////////////////////////////////////////
- class ILoggerMetrics {
- public:
- virtual ~ILoggerMetrics() = default;
- virtual void IncActorMsgs() = 0;
- virtual void IncDirectMsgs() = 0;
- virtual void IncLevelRequests() = 0;
- virtual void IncIgnoredMsgs() = 0;
- virtual void IncAlertMsgs() = 0;
- virtual void IncEmergMsgs() = 0;
- virtual void IncDroppedMsgs() = 0;
- virtual void GetOutputHtml(IOutputStream&) = 0;
- };
- class TLoggerActor: public TActor<TLoggerActor> {
- public:
- static constexpr IActor::EActivityType ActorActivityType() {
- return IActor::LOG_ACTOR;
- }
- TLoggerActor(TIntrusivePtr<NLog::TSettings> settings,
- TAutoPtr<TLogBackend> logBackend,
- TIntrusivePtr<NMonitoring::TDynamicCounters> counters);
- TLoggerActor(TIntrusivePtr<NLog::TSettings> settings,
- std::shared_ptr<TLogBackend> logBackend,
- TIntrusivePtr<NMonitoring::TDynamicCounters> counters);
- TLoggerActor(TIntrusivePtr<NLog::TSettings> settings,
- TAutoPtr<TLogBackend> logBackend,
- std::shared_ptr<NMonitoring::TMetricRegistry> metrics);
- TLoggerActor(TIntrusivePtr<NLog::TSettings> settings,
- std::shared_ptr<TLogBackend> logBackend,
- std::shared_ptr<NMonitoring::TMetricRegistry> metrics);
- ~TLoggerActor();
- void StateFunc(TAutoPtr<IEventHandle>& ev, const TActorContext& ctx) {
- switch (ev->GetTypeRewrite()) {
- HFunc(TLogIgnored, HandleIgnoredEvent);
- HFunc(NLog::TEvLog, HandleLogEvent);
- HFunc(TLogComponentLevelRequest, HandleLogComponentLevelRequest);
- HFunc(NMon::TEvHttpInfo, HandleMonInfo);
- }
- }
- STFUNC(StateDefunct) {
- switch (ev->GetTypeRewrite()) {
- cFunc(TLogIgnored::EventType, HandleIgnoredEventDrop);
- hFunc(NLog::TEvLog, HandleLogEventDrop);
- HFunc(TLogComponentLevelRequest, HandleLogComponentLevelRequest);
- HFunc(NMon::TEvHttpInfo, HandleMonInfo);
- cFunc(TEvents::TEvWakeup::EventType, HandleWakeup);
- }
- }
- // Directly call logger instead of sending a message
- void Log(TInstant time, NLog::EPriority priority, NLog::EComponent component, const char* c, ...);
- static void Throttle(const NLog::TSettings& settings);
- private:
- TIntrusivePtr<NLog::TSettings> Settings;
- std::shared_ptr<TLogBackend> LogBackend;
- ui64 IgnoredCount = 0;
- ui64 PassedCount = 0;
- static TAtomic IsOverflow;
- TDuration WakeupInterval{TDuration::Seconds(5)};
- std::unique_ptr<ILoggerMetrics> Metrics;
- void BecomeDefunct();
- void HandleIgnoredEvent(TLogIgnored::TPtr& ev, const NActors::TActorContext& ctx);
- void HandleIgnoredEventDrop();
- void HandleLogEvent(NLog::TEvLog::TPtr& ev, const TActorContext& ctx);
- void HandleLogEventDrop(const NLog::TEvLog::TPtr& ev);
- void HandleLogComponentLevelRequest(TLogComponentLevelRequest::TPtr& ev, const TActorContext& ctx);
- void HandleMonInfo(NMon::TEvHttpInfo::TPtr& ev, const TActorContext& ctx);
- void HandleWakeup();
- [[nodiscard]] bool OutputRecord(TInstant time, NLog::EPrio priority, NLog::EComponent component, const TString& formatted) noexcept;
- void RenderComponentPriorities(IOutputStream& str);
- void LogIgnoredCount(TInstant now);
- void WriteMessageStat(const NLog::TEvLog& ev);
- static const char* FormatLocalTimestamp(TInstant time, char* buf);
- };
- ////////////////////////////////////////////////////////////////////////////////
- // LOG THROTTLING
- // TTrivialLogThrottler -- log a message every 'period' duration
- // Use case:
- // TTrivialLogThrottler throttler(TDuration::Minutes(1));
- // ....
- // LOG_LOG_THROTTLE(throttler, ctx, NActors::NLog::PRI_ERROR, SOME, "Error");
- ////////////////////////////////////////////////////////////////////////////////
- class TTrivialLogThrottler {
- public:
- TTrivialLogThrottler(TDuration period)
- : Period(period)
- {
- }
- // return value:
- // true -- write to log
- // false -- don't write to log, throttle
- bool Kick() {
- auto now = TInstant::Now();
- if (now >= (LastWrite + Period)) {
- LastWrite = now;
- return true;
- } else {
- return false;
- }
- }
- private:
- TInstant LastWrite;
- TDuration Period;
- };
- ////////////////////////////////////////////////////////////////////////////////
- // SYSLOG BACKEND
- ////////////////////////////////////////////////////////////////////////////////
- TAutoPtr<TLogBackend> CreateSysLogBackend(const TString& ident,
- bool logPError, bool logCons);
- TAutoPtr<TLogBackend> CreateStderrBackend();
- TAutoPtr<TLogBackend> CreateFileBackend(const TString& fileName);
- TAutoPtr<TLogBackend> CreateNullBackend();
- TAutoPtr<TLogBackend> CreateCompositeLogBackend(TVector<TAutoPtr<TLogBackend>>&& underlyingBackends);
- /////////////////////////////////////////////////////////////////////
- // Logging adaptors for memory log and logging into filesystem
- /////////////////////////////////////////////////////////////////////
- namespace NDetail {
- inline void Y_PRINTF_FORMAT(2, 3) PrintfV(TString& dst, const char* format, ...) {
- va_list params;
- va_start(params, format);
- vsprintf(dst, format, params);
- va_end(params);
- }
- inline void PrintfV(TString& dst, const char* format, va_list params) {
- vsprintf(dst, format, params);
- }
- } // namespace NDetail
- template <typename TCtx>
- inline void DeliverLogMessage(TCtx& ctx, NLog::EPriority mPriority, NLog::EComponent mComponent, TString &&str)
- {
- const NLog::TSettings *mSettings = ctx.LoggerSettings();
- TLoggerActor::Throttle(*mSettings);
- ctx.Send(new IEventHandle(mSettings->LoggerActorId, TActorId(), new NLog::TEvLog(mPriority, mComponent, std::move(str))));
- }
- template <typename TCtx, typename... TArgs>
- inline void MemLogAdapter(
- TCtx& actorCtxOrSystem,
- NLog::EPriority mPriority,
- NLog::EComponent mComponent,
- const char* format, TArgs&&... params) {
- TString Formatted;
- if constexpr (sizeof... (params) > 0) {
- NDetail::PrintfV(Formatted, format, std::forward<TArgs>(params)...);
- } else {
- NDetail::PrintfV(Formatted, "%s", format);
- }
- MemLogWrite(Formatted.data(), Formatted.size(), true);
- DeliverLogMessage(actorCtxOrSystem, mPriority, mComponent, std::move(Formatted));
- }
- template <typename TCtx>
- Y_WRAPPER inline void MemLogAdapter(
- TCtx& actorCtxOrSystem,
- NLog::EPriority mPriority,
- NLog::EComponent mComponent,
- const TString& str) {
- MemLogWrite(str.data(), str.size(), true);
- DeliverLogMessage(actorCtxOrSystem, mPriority, mComponent, TString(str));
- }
- template <typename TCtx>
- Y_WRAPPER inline void MemLogAdapter(
- TCtx& actorCtxOrSystem,
- NLog::EPriority mPriority,
- NLog::EComponent mComponent,
- TString&& str) {
- MemLogWrite(str.data(), str.size(), true);
- DeliverLogMessage(actorCtxOrSystem, mPriority, mComponent, std::move(str));
- }
- }
|