aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp/unified_agent_client/logger.h
blob: d83cba92dedeb6c90cbc1f3912f7a51b85814a15 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
#pragma once

#include <library/cpp/unified_agent_client/f_maybe.h>
#include <library/cpp/unified_agent_client/throttling.h>

#include <library/cpp/logger/log.h>
#include <library/cpp/monlib/dynamic_counters/counters.h>

#include <util/generic/string.h>
#include <util/string/join.h>
#include <util/string/printf.h>
#include <util/system/file.h>

#include <atomic>

#define YLOG(logPriority, message, logger)                                        \
    do {                                                                          \
        const auto __logPriority = logPriority;                                   \
        if (auto* log = logger.Accept(__logPriority, false); log != nullptr) {    \
            logger.Log(*log, __logPriority, message);                             \
        }                                                                         \
    } while (false)

#define YLOG_EMERG(msg)         YLOG(TLOG_EMERG, msg, Logger)
#define YLOG_ALERT(msg)         YLOG(TLOG_ALERT, msg, Logger)
#define YLOG_CRIT(msg)          YLOG(TLOG_CRIT, msg, Logger)
#define YLOG_ERR(msg)           YLOG(TLOG_ERR, msg, Logger)
#define YLOG_WARNING(msg)       YLOG(TLOG_WARNING, msg, Logger)
#define YLOG_NOTICE(msg)        YLOG(TLOG_NOTICE, msg, Logger)
#define YLOG_INFO(msg)          YLOG(TLOG_INFO, msg, Logger)
#define YLOG_DEBUG(msg)         YLOG(TLOG_DEBUG, msg, Logger)
#define YLOG_RESOURCES(msg)     YLOG(TLOG_RESOURCES , msg, Logger)

#define YLOG_FATAL(msg)            \
    YLOG(TLOG_CRIT, msg, Logger);  \
    _Exit(1);

namespace NUnifiedAgent {
    class TScopeLogger;

    class TLogger {
    public:
        TLogger(TLog& log, TFMaybe<size_t> rateLimitBytes);

        void StartTracing(ELogPriority logPriority) noexcept;

        void FinishTracing() noexcept;

        inline TScopeLogger Child(const TString& v, NMonitoring::TDeprecatedCounter* errors = nullptr);

        inline void SetErrorsCounter(NMonitoring::TDeprecatedCounter* counter) noexcept {
            Errors = counter;
        }

        inline void SetDroppedBytesCounter(NMonitoring::TDeprecatedCounter* counter) noexcept {
            DroppedBytes = counter;
        }

        inline bool HasRateLimit() const noexcept {
            return Throttler != nullptr;
        }

        friend class TScopeLogger;

    private:
        void Log(TLog& log, ELogPriority logPriority, const TStringBuf message, const TString& scope) const;

        inline TLog* Accept(ELogPriority logPriority, NMonitoring::TDeprecatedCounter* errors) const noexcept {
            if ((logPriority <= TLOG_ERR) && (errors != nullptr)) {
                ++(*errors);
            }
            auto* result = CurrentLogContext_.load(std::memory_order_acquire);
            return result != nullptr && static_cast<int>(logPriority) <= static_cast<int>(result->Priority)
                   ? &result->Log
                   : nullptr;
        }

    private:
        struct TLogContext {
            TLog Log;
            ELogPriority Priority;
        };

        class TThrottlerWithLock {
        public:
            explicit TThrottlerWithLock(size_t rateLimitBytes);

            bool TryConsume(double tokens);

        private:
            TThrottler Throttler;
            TAdaptiveLock Lock;
        };

    private:
        void SetCurrentLogContext(TLogContext& logContext);

        TLogContext& GetOrCreateTracingLogContext(ELogPriority logPriority);

        void SetTracing(TLogContext& logContext, const char* action);

    private:
        TLogContext DefaultLogContext;
        TVector<THolder<TLogContext>> TracingLogContexts;
        std::atomic<TLogContext*> CurrentLogContext_;
        NMonitoring::TDeprecatedCounter* Errors;
        NMonitoring::TDeprecatedCounter* DroppedBytes;
        const THolder<TThrottlerWithLock> Throttler;
        TAdaptiveLock Lock;
    };

    class TScopeLogger {
    public:
        TScopeLogger();

        inline void Log(TLog& log, ELogPriority logPriority, const TStringBuf message) const {
            if (Logger) {
                Logger->Log(log, logPriority, message, Scope);
            }
        }

        inline TLog* Accept(ELogPriority logPriority, bool silent) const noexcept {
            return Logger ? Logger->Accept(logPriority, silent ? nullptr : Errors) : nullptr;
        }

        inline TScopeLogger Child(const TString& v, NMonitoring::TDeprecatedCounter* errors = nullptr) {
            return Logger
                ? Logger->Child(Join('/', Scope, v), errors == nullptr ? Errors : errors)
                : TScopeLogger();
        }

        inline TLogger* Unwrap() noexcept {
            return Logger;
        }

        friend class TLogger;

    private:
        TScopeLogger(TLogger* logger,
                     const TString& scope,
                     NMonitoring::TDeprecatedCounter* errors);

    private:
        TLogger* Logger;
        TString Scope;
        NMonitoring::TDeprecatedCounter* Errors;
    };

    inline TScopeLogger TLogger::Child(const TString& v, NMonitoring::TDeprecatedCounter* errors) {
        return TScopeLogger(this, v, errors == nullptr ? Errors : errors);
    }

    inline ELogPriority ToLogPriority(int level) noexcept {
        const auto result = ClampVal(level, 0, static_cast<int>(TLOG_RESOURCES));
        return static_cast<ELogPriority>(result);
    }
}