aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp/logger/global/rty_formater.cpp
blob: cce0070dcbfe2038f653d3c683d6ed94b5b94211 (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;
}