aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp/actors/core/log_buffer.cpp
blob: 8c80f1d054bbac5159e208b01464d35b0e5fa359 (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
#include "log_buffer.h"

#include <util/system/yassert.h>
#include <algorithm>

using namespace NActors::NLog;

namespace NActors {
TLogBuffer::TLogBuffer(ILoggerMetrics &metrics, const NLog::TSettings &settings)
    : Metrics(metrics)
    , Settings(settings)
{}

size_t TLogBuffer::GetLogCostInBytes(NLog::TEvLog *log) const {
    return LOG_STRUCTURE_BYTES + log->Line.length();
}

ui16 TLogBuffer::GetPrioIndex(NLog::EPrio prio) {
    return Min(ui16(prio), ui16(LOG_PRIORITIES_NUMBER - 1));
}

TIntrusiveList<NLog::TEvLog, NLog::TEvLogBufferLevelListTag> &TLogBuffer::GetPrioLogs(NLog::EPrio prio) {
    return PrioLogsList[GetPrioIndex(prio)];
}

void TLogBuffer::AddLog(NLog::TEvLog *log) {
    NLog::EPrio prio = log->Level.ToPrio();
    if (!CheckSize(log) && prio > NLog::EPrio::Emerg) { // always keep logs with prio Emerg = 0
        HandleIgnoredLog(log);
        return;
    }

    SizeBytes += GetLogCostInBytes(log);
    Logs.PushBack(log);
    GetPrioLogs(prio).PushBack(log);
}

NLog::TEvLog* TLogBuffer::Pop() {
    NLog::TEvLog* log = Logs.PopFront();
    static_cast<TIntrusiveListItem<TEvLog, TEvLogBufferLevelListTag>&>(*log).Unlink();

    SizeBytes -= GetLogCostInBytes(log);

    return log;
}

bool TLogBuffer::IsEmpty() const {
    return Logs.Empty();
}

bool TLogBuffer::CheckLogIgnoring() const {
    return IgnoredCount > 0;
}

bool TLogBuffer::CheckSize(NLog::TEvLog *log) {
    size_t startSizeBytes = SizeBytes;

    size_t logSize = GetLogCostInBytes(log);
    if (SizeBytes + logSize <= Settings.BufferSizeLimitBytes) {
        return true;
    }

    ui16 scanHighestPrio = Max((ui16)1, GetPrioIndex(log->Level.ToPrio())); // always keep logs with prio Emerg = 0
    for (ui16 scanPrio = LOG_PRIORITIES_NUMBER - 1; scanPrio >= scanHighestPrio; scanPrio--) {
        TIntrusiveList<NLog::TEvLog, NLog::TEvLogBufferLevelListTag> &scanLogs = PrioLogsList[scanPrio];
        while (!scanLogs.Empty()) {
            NLog::TEvLog* log = scanLogs.PopFront();
            SizeBytes -= GetLogCostInBytes(log);
            HandleIgnoredLog(log);
            
            if (SizeBytes + logSize <= Settings.BufferSizeLimitBytes) {
                return true;
            }
        }
    }

    if (startSizeBytes > SizeBytes) {
        return true;
    }

    return false;
}

void TLogBuffer::HandleIgnoredLog(NLog::TEvLog *log) {
    ui16 logPrio = GetPrioIndex(log->Level.ToPrio());
    Metrics.IncIgnoredMsgs();
    if (IgnoredHighestPrio > logPrio) {
        IgnoredHighestPrio = logPrio;
    }
    IgnoredCount++;
    delete log;
}

ui64 TLogBuffer::GetIgnoredCount() {
    return IgnoredCount;
}

NLog::EPrio TLogBuffer::GetIgnoredHighestPrio() {
    NLog::EPrio prio = static_cast<NLog::EPrio>(IgnoredHighestPrio);
    return prio;
}

void TLogBuffer::ClearIgnoredCount() {
    IgnoredHighestPrio = LOG_PRIORITIES_NUMBER - 1;
    IgnoredCount = 0;
}

}