aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp/logger/global/rty_formater.cpp
blob: c7799280bd81bbd31bdc5dcbab4421e5ccf22774 (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
#include "rty_formater.h"
#include <util/datetime/base.h>
#include <util/datetime/systime.h>
#include <util/stream/str.h>
#include <util/stream/printf.h>
#include <util/system/mem_info.h>
#include <util/system/yassert.h>
#include <inttypes.h>
#include <cstdio>

namespace {
    constexpr size_t LocalTimeSBufferSize = sizeof("2017-07-24 12:20:34.313 +0300");

    size_t PrintLocalTimeS(const TInstant instant, char* const begin, const char* const end) {
        Y_VERIFY(static_cast<size_t>(end - begin) >= LocalTimeSBufferSize);

        struct tm tm;
        instant.LocalTime(&tm);

        // both stftime and sprintf exclude the terminating null byte from the return value
        char* pos = begin; 
        pos += strftime(pos, end - pos, "%Y-%m-%d %H:%M:%S.", &tm);
        pos += sprintf(pos, "%03" PRIu32, instant.MilliSecondsOfSecond());
        pos += strftime(pos, end - pos, " %z", &tm);
        Y_VERIFY(LocalTimeSBufferSize - 1 == pos - begin); // together with Y_VERIFY above this also implies pos<=end
        return (pos - begin);
    }
}

namespace NLoggingImpl {
    IOutputStream& operator<<(IOutputStream& out, TLocalTimeS localTimeS) { 
        char buffer[LocalTimeSBufferSize];
        size_t len = PrintLocalTimeS(localTimeS.GetInstant(), buffer, buffer + sizeof(buffer));
        out.Write(buffer, len);
        return out;
    }

    TLocalTimeS::operator TString() const {
        TString res;
        res.reserve(LocalTimeSBufferSize);
        res.ReserveAndResize(PrintLocalTimeS(Instant, res.begin(), res.begin() + res.capacity()));
        return res;
    }

    TString TLocalTimeS::operator+(const TStringBuf right) const {
        TString res(*this);
        res += right;
        return res;
    }

    TStringBuf StripFileName(TStringBuf string) {
        return string.RNextTok(LOCSLASH_C);
    }

    TString GetSystemResources() {
        NMemInfo::TMemInfo mi = NMemInfo::GetMemInfo();
        return PrintSystemResources(mi);
    }

    TString PrintSystemResources(const NMemInfo::TMemInfo& mi) {
        return Sprintf(" rss=%0.3fMb, vms=%0.3fMb", mi.RSS * 1.0 / (1024 * 1024), mi.VMS * 1.0 / (1024 * 1024));
    }
}

namespace {
    class TRtyLoggerFormatter : public ILoggerFormatter {
    public:
        void Format(const TLogRecordContext& context, TLogElement& elem) const override {
            elem << context.CustomMessage << ": " << NLoggingImpl::GetLocalTimeS() << " "
                 << NLoggingImpl::StripFileName(context.SourceLocation.File) << ":" << context.SourceLocation.Line;
            if (context.Priority > TLOG_RESOURCES && !ExitStarted()) {
                elem << NLoggingImpl::GetSystemResources();
            }
            elem << " ";
        }
    };
}

ILoggerFormatter* CreateRtyLoggerFormatter() {
    return new TRtyLoggerFormatter();
}

bool TRTYMessageFormater::CheckLoggingContext(TLog& /*logger*/, const TLogRecordContext& /*context*/) {
    return true;
}

TSimpleSharedPtr<TLogElement> TRTYMessageFormater::StartRecord(TLog& logger, const TLogRecordContext& context, TSimpleSharedPtr<TLogElement> earlier) {
    if (!earlier) {
        earlier.Reset(new TLogElement(&logger));
    }

    TLoggerFormatterOperator::Get()->Format(context, *earlier);
    return earlier;
}