#include "log.h" #include "log_ut.h" #include "context.h" #include "profile.h" #include #include #include #include #include #include #include #include #include #include using namespace NYql; using namespace NLog; Y_UNIT_TEST_SUITE(TLogTest) { Y_UNIT_TEST_ON_EACH_LOG_FORMAT(WrittingWithoutMacro) { TStringStream out; YqlLoggerScope logger(&out, Format, /* isStrict */ false); TString message = "some performance info"; YqlLogger().Write(ELogPriority::TLOG_INFO, message); TString logRow = out.Str(); UNIT_ASSERT_STRING_CONTAINS(logRow, message); } Y_UNIT_TEST_ON_EACH_LOG_FORMAT(WrittingUnknownMetaFlag) { TStringStream out; YqlLoggerScope logger(&out, Format, /* isStrict */ false); TString message = "some performance info"; YqlLogger().Write(ELogPriority::TLOG_INFO, message, {{"unknown", "value"}}); TString logRow = out.Str(); UNIT_ASSERT_STRING_CONTAINS(logRow, message); UNIT_ASSERT_STRING_CONTAINS(logRow, "unknown = value"); } Y_UNIT_TEST_ON_EACH_LOG_FORMAT(Formatting) { TStringStream out; YqlLoggerScope logger(&out, Format); YqlLogger().UpdateProcInfo("my_proc"); TString message = "some performance info"; YQL_LOG(INFO) << message; TLogRow logRow = ParseLogRow(out.Str()); TDuration elapsed(logRow.Time - TInstant::Now()); UNIT_ASSERT(elapsed < TDuration::MilliSeconds(5)); UNIT_ASSERT_EQUAL(logRow.Level, ELevel::INFO); UNIT_ASSERT_STRINGS_EQUAL(logRow.ProcName, "my_proc"); UNIT_ASSERT_EQUAL(logRow.ProcId, GetPID()); UNIT_ASSERT(logRow.ThreadId > 0); UNIT_ASSERT_EQUAL(logRow.Component, EComponent::Default); UNIT_ASSERT_STRINGS_EQUAL( logRow.FileName, TStringBuf(__FILE__).RNextTok(LOCSLASH_C)); UNIT_ASSERT(logRow.LineNumber != 0); UNIT_ASSERT_STRINGS_EQUAL(logRow.Message, message); } Y_UNIT_TEST_ON_EACH_LOG_FORMAT(SpecialCharacters) { TStringStream out; YqlLoggerScope logger(&out, Format); YqlLogger().UpdateProcInfo("\\evil\\"); YQL_LOG(INFO) << "My name is \"YQL\"!"; TLogRow logRow = ParseLogRow(out.Str()); UNIT_ASSERT_STRINGS_EQUAL(logRow.ProcName, "\\evil\\"); UNIT_ASSERT_STRINGS_EQUAL(logRow.Message, "My name is \"YQL\"!"); } Y_UNIT_TEST_ON_EACH_LOG_FORMAT(Levels) { TStringStream out; YqlLoggerScope logger(&out, Format); // default log level INFO YQL_LOG(FATAL) << "fatal message"; YQL_LOG(ERROR) << "error message"; YQL_LOG(WARN) << "warning message"; YQL_LOG(INFO) << "info message"; YQL_LOG(DEBUG) << "debug message"; YQL_LOG(TRACE) << "trace message"; TString fatalStr; TString errorStr; TString warnStr; TString infoStr; TString _; Split(out.Str(), '\n', fatalStr, errorStr, warnStr, infoStr, _); { TLogRow logRow = ParseLogRow(fatalStr); UNIT_ASSERT_EQUAL(logRow.Level, ELevel::FATAL); UNIT_ASSERT_EQUAL(logRow.Component, EComponent::Default); UNIT_ASSERT_STRINGS_EQUAL(logRow.Message, "fatal message"); } { TLogRow logRow = ParseLogRow(errorStr); UNIT_ASSERT_EQUAL(logRow.Level, ELevel::ERROR); UNIT_ASSERT_EQUAL(logRow.Component, EComponent::Default); UNIT_ASSERT_STRINGS_EQUAL(logRow.Message, "error message"); } { TLogRow logRow = ParseLogRow(warnStr); UNIT_ASSERT_EQUAL(logRow.Level, ELevel::WARN); UNIT_ASSERT_EQUAL(logRow.Component, EComponent::Default); UNIT_ASSERT_STRINGS_EQUAL(logRow.Message, "warning message"); } { TLogRow logRow = ParseLogRow(infoStr); UNIT_ASSERT_EQUAL(logRow.Level, ELevel::INFO); UNIT_ASSERT_EQUAL(logRow.Component, EComponent::Default); UNIT_ASSERT_STRINGS_EQUAL(logRow.Message, "info message"); } } Y_UNIT_TEST_ON_EACH_LOG_FORMAT(Components) { TStringStream out; YqlLoggerScope logger(&out, Format); YQL_CLOG(INFO, Default) << "default message"; YQL_CLOG(INFO, Core) << "core message"; YQL_CLOG(INFO, Sql) << "sql message"; YQL_CLOG(INFO, ProviderCommon) << "common message"; YQL_CLOG(INFO, ProviderYt) << "yt message"; YQL_CLOG(INFO, ProviderKikimr) << "kikimr message"; YQL_CLOG(INFO, ProviderRtmr) << "rtmr message"; YQL_CLOG(INFO, Performance) << "performance message"; YQL_CLOG(INFO, Perf) << "perf message"; TString defaultStr; TString coreStr; TString sqlStr; TString commonStr; TString ytStr; TString kikimrStr; TString rtmrStr; TString performanceStr; TString perfStr; TString _; Split(out.Str(), '\n', defaultStr, coreStr, sqlStr, commonStr, ytStr, kikimrStr, rtmrStr, performanceStr, perfStr, _); { TLogRow logRow = ParseLogRow(defaultStr); UNIT_ASSERT_EQUAL(logRow.Level, ELevel::INFO); UNIT_ASSERT_EQUAL(logRow.Component, EComponent::Default); UNIT_ASSERT_STRINGS_EQUAL(logRow.Message, "default message"); } { TLogRow logRow = ParseLogRow(coreStr); UNIT_ASSERT_EQUAL(logRow.Level, ELevel::INFO); UNIT_ASSERT_EQUAL(logRow.Component, EComponent::Core); UNIT_ASSERT_STRINGS_EQUAL(logRow.Message, "core message"); } { TLogRow logRow = ParseLogRow(sqlStr); UNIT_ASSERT_EQUAL(logRow.Level, ELevel::INFO); UNIT_ASSERT_EQUAL(logRow.Component, EComponent::Sql); UNIT_ASSERT_STRINGS_EQUAL(logRow.Message, "sql message"); } { TLogRow logRow = ParseLogRow(commonStr); UNIT_ASSERT_EQUAL(logRow.Level, ELevel::INFO); UNIT_ASSERT_EQUAL(logRow.Component, EComponent::ProviderCommon); UNIT_ASSERT_STRINGS_EQUAL(logRow.Message, "common message"); } { TLogRow logRow = ParseLogRow(ytStr); UNIT_ASSERT_EQUAL(logRow.Level, ELevel::INFO); UNIT_ASSERT_EQUAL(logRow.Component, EComponent::ProviderYt); UNIT_ASSERT_STRINGS_EQUAL(logRow.Message, "yt message"); } { TLogRow logRow = ParseLogRow(kikimrStr); UNIT_ASSERT_EQUAL(logRow.Level, ELevel::INFO); UNIT_ASSERT_EQUAL(logRow.Component, EComponent::ProviderKikimr); UNIT_ASSERT_STRINGS_EQUAL(logRow.Message, "kikimr message"); } { TLogRow logRow = ParseLogRow(rtmrStr); UNIT_ASSERT_EQUAL(logRow.Level, ELevel::INFO); UNIT_ASSERT_EQUAL(logRow.Component, EComponent::ProviderRtmr); UNIT_ASSERT_STRINGS_EQUAL(logRow.Message, "rtmr message"); } { TLogRow logRow = ParseLogRow(performanceStr); UNIT_ASSERT_EQUAL(logRow.Level, ELevel::INFO); UNIT_ASSERT_EQUAL(logRow.Component, EComponent::Performance); UNIT_ASSERT_EQUAL(logRow.Component, EComponent::Perf); UNIT_ASSERT_STRINGS_EQUAL(logRow.Message, "performance message"); } { TLogRow logRow = ParseLogRow(perfStr); UNIT_ASSERT_EQUAL(logRow.Level, ELevel::INFO); UNIT_ASSERT_EQUAL(logRow.Component, EComponent::Perf); UNIT_ASSERT_EQUAL(logRow.Component, EComponent::Performance); UNIT_ASSERT_STRINGS_EQUAL(logRow.Message, "perf message"); } } Y_UNIT_TEST_ON_EACH_LOG_FORMAT(Conditional) { TStringStream out; YqlLoggerScope logger(&out, Format); YQL_LOG_IF(INFO, true) << "default info message"; YQL_LOG_IF(INFO, false) << "must not be logged"; YQL_CLOG_IF(INFO, Perf, true) << "perf info message"; YQL_CLOG_IF(INFO, Perf, false) << "perf info message"; TString defaultStr; TString perfStr; TString _; Split(out.Str(), '\n', defaultStr, perfStr, _); { TLogRow logRow = ParseLogRow(defaultStr); UNIT_ASSERT_EQUAL(logRow.Level, ELevel::INFO); UNIT_ASSERT_EQUAL(logRow.Component, EComponent::Default); UNIT_ASSERT_STRINGS_EQUAL(logRow.Message, "default info message"); } { TLogRow logRow = ParseLogRow(perfStr); UNIT_ASSERT_EQUAL(logRow.Level, ELevel::INFO); UNIT_ASSERT_EQUAL(logRow.Component, EComponent::Perf); UNIT_ASSERT_STRINGS_EQUAL(logRow.Message, "perf info message"); } } Y_UNIT_TEST_ON_EACH_LOG_FORMAT(Contexts) { TStringStream out; YqlLoggerScope logger(&out, Format); UNIT_ASSERT_STRINGS_EQUAL(CurrentLogContextPath().second, ""); YQL_LOG(INFO) << "level0 - begin"; { YQL_LOG_CTX_SCOPE("ctx1"); UNIT_ASSERT_STRINGS_EQUAL(CurrentLogContextPath().second, "ctx1"); YQL_LOG(INFO) << "level1 - begin"; YQL_LOG_CTX_BLOCK(TStringBuf("ctx2")) { UNIT_ASSERT_STRINGS_EQUAL(CurrentLogContextPath().second, "ctx1/ctx2"); YQL_LOG(WARN) << "level2"; } UNIT_ASSERT_STRINGS_EQUAL(CurrentLogContextPath().second, "ctx1"); YQL_LOG(INFO) << "level1 - end"; } UNIT_ASSERT_STRINGS_EQUAL(CurrentLogContextPath().second, ""); YQL_LOG(INFO) << "level0 - end"; TString row1Str; TString row2Str; TString row3Str; TString row4Str; TString row5Str; TString _; Split(out.Str(), '\n', row1Str, row2Str, row3Str, row4Str, row5Str, _); { TLogRow logRow = ParseLogRow(row1Str); UNIT_ASSERT_EQUAL(logRow.Level, ELevel::INFO); UNIT_ASSERT_EQUAL(logRow.Component, EComponent::Default); UNIT_ASSERT_STRINGS_EQUAL(logRow.Message, "level0 - begin"); } { TLogRow logRow = ParseLogRow(row2Str); UNIT_ASSERT_EQUAL(logRow.Level, ELevel::INFO); UNIT_ASSERT_EQUAL(logRow.Component, EComponent::Default); UNIT_ASSERT_STRINGS_EQUAL(logRow.Path, "ctx1"); UNIT_ASSERT_STRINGS_EQUAL(logRow.Message, "level1 - begin"); } { TLogRow logRow = ParseLogRow(row3Str); UNIT_ASSERT_EQUAL(logRow.Level, ELevel::WARN); UNIT_ASSERT_EQUAL(logRow.Component, EComponent::Default); UNIT_ASSERT_STRINGS_EQUAL(logRow.Path, "ctx1/ctx2"); UNIT_ASSERT_STRINGS_EQUAL(logRow.Message, "level2"); } { TLogRow logRow = ParseLogRow(row4Str); UNIT_ASSERT_EQUAL(logRow.Level, ELevel::INFO); UNIT_ASSERT_EQUAL(logRow.Component, EComponent::Default); UNIT_ASSERT_STRINGS_EQUAL(logRow.Path, "ctx1"); UNIT_ASSERT_STRINGS_EQUAL(logRow.Message, "level1 - end"); } { TLogRow logRow = ParseLogRow(row5Str); UNIT_ASSERT_EQUAL(logRow.Level, ELevel::INFO); UNIT_ASSERT_EQUAL(logRow.Component, EComponent::Default); UNIT_ASSERT_STRINGS_EQUAL(logRow.Message, "level0 - end"); } } Y_UNIT_TEST_ON_EACH_LOG_FORMAT(UnknownSessionContexts) { TStringStream out; YqlLoggerScope logger(&out, Format); { YQL_LOG_CTX_ROOT_SCOPE("ctx"); UNIT_ASSERT_STRINGS_EQUAL(CurrentLogContextPath().first, ""); UNIT_ASSERT_STRINGS_EQUAL(CurrentLogContextPath().second, "ctx"); YQL_LOG(INFO) << "level0 - begin"; { YQL_LOG_CTX_ROOT_SESSION_SCOPE(CurrentLogContextPath()); UNIT_ASSERT_STRINGS_EQUAL(CurrentLogContextPath().first, ""); UNIT_ASSERT_STRINGS_EQUAL(CurrentLogContextPath().second, "ctx"); YQL_LOG(INFO) << "level1 - begin"; YQL_LOG_CTX_BLOCK("ctx1") { UNIT_ASSERT_STRINGS_EQUAL(CurrentLogContextPath().first, ""); UNIT_ASSERT_STRINGS_EQUAL(CurrentLogContextPath().second, "ctx/ctx1"); YQL_LOG(WARN) << "level2"; } UNIT_ASSERT_STRINGS_EQUAL(CurrentLogContextPath().first, ""); UNIT_ASSERT_STRINGS_EQUAL(CurrentLogContextPath().second, "ctx"); YQL_LOG(INFO) << "level1 - end"; } UNIT_ASSERT_STRINGS_EQUAL(CurrentLogContextPath().first, ""); UNIT_ASSERT_STRINGS_EQUAL(CurrentLogContextPath().second, "ctx"); YQL_LOG(INFO) << "level0 - end"; } TString row1Str; TString row2Str; TString row3Str; TString row4Str; TString row5Str; TString _; Split(out.Str(), '\n', row1Str, row2Str, row3Str, row4Str, row5Str, _); { TLogRow logRow = ParseLogRow(row1Str); UNIT_ASSERT_EQUAL(logRow.Level, ELevel::INFO); UNIT_ASSERT_EQUAL(logRow.Component, EComponent::Default); UNIT_ASSERT_STRINGS_EQUAL(logRow.Path, "ctx"); UNIT_ASSERT_STRINGS_EQUAL(logRow.Message, "level0 - begin"); } { TLogRow logRow = ParseLogRow(row2Str); UNIT_ASSERT_EQUAL(logRow.Level, ELevel::INFO); UNIT_ASSERT_EQUAL(logRow.Component, EComponent::Default); UNIT_ASSERT_STRINGS_EQUAL(logRow.Path, "ctx"); UNIT_ASSERT_STRINGS_EQUAL(logRow.Message, "level1 - begin"); } { TLogRow logRow = ParseLogRow(row3Str); UNIT_ASSERT_EQUAL(logRow.Level, ELevel::WARN); UNIT_ASSERT_EQUAL(logRow.Component, EComponent::Default); UNIT_ASSERT_STRINGS_EQUAL(logRow.Path, "ctx/ctx1"); UNIT_ASSERT_STRINGS_EQUAL(logRow.Message, "level2"); } { TLogRow logRow = ParseLogRow(row4Str); UNIT_ASSERT_EQUAL(logRow.Level, ELevel::INFO); UNIT_ASSERT_EQUAL(logRow.Component, EComponent::Default); UNIT_ASSERT_STRINGS_EQUAL(logRow.Path, "ctx"); UNIT_ASSERT_STRINGS_EQUAL(logRow.Message, "level1 - end"); } { TLogRow logRow = ParseLogRow(row5Str); UNIT_ASSERT_EQUAL(logRow.Level, ELevel::INFO); UNIT_ASSERT_EQUAL(logRow.Component, EComponent::Default); UNIT_ASSERT_STRINGS_EQUAL(logRow.Path, "ctx"); UNIT_ASSERT_STRINGS_EQUAL(logRow.Message, "level0 - end"); } } Y_UNIT_TEST_ON_EACH_LOG_FORMAT(SessionContexts) { TStringStream out; YqlLoggerScope logger(&out, Format); { YQL_LOG_CTX_ROOT_SESSION_SCOPE("sessionId", "ctx"); UNIT_ASSERT_STRINGS_EQUAL(CurrentLogContextPath().first, "sessionId"); UNIT_ASSERT_STRINGS_EQUAL(CurrentLogContextPath().second, "ctx"); YQL_LOG(INFO) << "level0 - begin"; { YQL_LOG_CTX_ROOT_SESSION_SCOPE(CurrentLogContextPath()); UNIT_ASSERT_STRINGS_EQUAL(CurrentLogContextPath().first, "sessionId"); UNIT_ASSERT_STRINGS_EQUAL(CurrentLogContextPath().second, "ctx"); YQL_LOG(INFO) << "level1 - begin"; YQL_LOG_CTX_BLOCK("ctx1") { UNIT_ASSERT_STRINGS_EQUAL(CurrentLogContextPath().first, "sessionId"); UNIT_ASSERT_STRINGS_EQUAL(CurrentLogContextPath().second, "ctx/ctx1"); YQL_LOG(WARN) << "level2"; } UNIT_ASSERT_STRINGS_EQUAL(CurrentLogContextPath().first, "sessionId"); UNIT_ASSERT_STRINGS_EQUAL(CurrentLogContextPath().second, "ctx"); YQL_LOG(INFO) << "level1 - end"; } UNIT_ASSERT_STRINGS_EQUAL(CurrentLogContextPath().first, "sessionId"); UNIT_ASSERT_STRINGS_EQUAL(CurrentLogContextPath().second, "ctx"); YQL_LOG(INFO) << "level0 - end"; } TString row1Str; TString row2Str; TString row3Str; TString row4Str; TString row5Str; TString _; Split(out.Str(), '\n', row1Str, row2Str, row3Str, row4Str, row5Str, _); { TLogRow logRow = ParseLogRow(row1Str); UNIT_ASSERT_EQUAL(logRow.Level, ELevel::INFO); UNIT_ASSERT_EQUAL(logRow.Component, EComponent::Default); UNIT_ASSERT_STRINGS_EQUAL(logRow.Path, "sessionId/ctx"); UNIT_ASSERT_STRINGS_EQUAL(logRow.Message, "level0 - begin"); } { TLogRow logRow = ParseLogRow(row2Str); UNIT_ASSERT_EQUAL(logRow.Level, ELevel::INFO); UNIT_ASSERT_EQUAL(logRow.Component, EComponent::Default); UNIT_ASSERT_STRINGS_EQUAL(logRow.Path, "sessionId/ctx"); UNIT_ASSERT_STRINGS_EQUAL(logRow.Message, "level1 - begin"); } { TLogRow logRow = ParseLogRow(row3Str); UNIT_ASSERT_EQUAL(logRow.Level, ELevel::WARN); UNIT_ASSERT_EQUAL(logRow.Component, EComponent::Default); UNIT_ASSERT_STRINGS_EQUAL(logRow.Path, "sessionId/ctx/ctx1"); UNIT_ASSERT_STRINGS_EQUAL(logRow.Message, "level2"); } { TLogRow logRow = ParseLogRow(row4Str); UNIT_ASSERT_EQUAL(logRow.Level, ELevel::INFO); UNIT_ASSERT_EQUAL(logRow.Component, EComponent::Default); UNIT_ASSERT_STRINGS_EQUAL(logRow.Path, "sessionId/ctx"); UNIT_ASSERT_STRINGS_EQUAL(logRow.Message, "level1 - end"); } { TLogRow logRow = ParseLogRow(row5Str); UNIT_ASSERT_EQUAL(logRow.Level, ELevel::INFO); UNIT_ASSERT_EQUAL(logRow.Component, EComponent::Default); UNIT_ASSERT_STRINGS_EQUAL(logRow.Path, "sessionId/ctx"); UNIT_ASSERT_STRINGS_EQUAL(logRow.Message, "level0 - end"); } } Y_UNIT_TEST_ON_EACH_LOG_FORMAT(ThrowWithContext) { bool isThrown = false; YQL_LOG_CTX_SCOPE("first"); try { YQL_LOG_CTX_SCOPE("second"); YQL_LOG_CTX_THROW yexception() << "some message"; } catch (const yexception& e) { isThrown = true; UNIT_ASSERT_STRINGS_EQUAL(e.AsStrBuf(), "some message"); TString throwedLogCtx = ThrowedLogContextPath(); TStringBuf file; TStringBuf line; TStringBuf context; TStringBuf(throwedLogCtx).Split(".cpp:", file, line); line.Split(':', line, context); TString expectedFile(__LOCATION__.File); SubstGlobal(expectedFile, LOCSLASH_C, '/'); UNIT_ASSERT_STRINGS_EQUAL(TString(file) + ".cpp", expectedFile); int lineNumber; UNIT_ASSERT(TryFromString(line, lineNumber)); UNIT_ASSERT(lineNumber > 0); UNIT_ASSERT_STRINGS_EQUAL(context, " {first/second} "); // second call without throw returns empty string throwedLogCtx = ThrowedLogContextPath(); UNIT_ASSERT(throwedLogCtx.empty()); } UNIT_ASSERT_C(isThrown, "exception was not thrown"); } Y_UNIT_TEST_ON_EACH_LOG_FORMAT(ContextOverride) { TStringStream out; YqlLoggerScope logger(&out, Format); UNIT_ASSERT_STRINGS_EQUAL(CurrentLogContextPath().second, ""); { YQL_LOG_CTX_SCOPE("ctx1"); UNIT_ASSERT_STRINGS_EQUAL(CurrentLogContextPath().second, "ctx1"); YQL_LOG(INFO) << "level1 - begin"; YQL_LOG_CTX_BLOCK(TStringBuf("ctx2")) { UNIT_ASSERT_STRINGS_EQUAL(CurrentLogContextPath().second, "ctx1/ctx2"); YQL_LOG(WARN) << "level2 - begin"; { YQL_LOG_CTX_ROOT_SCOPE("ctx3"); UNIT_ASSERT_STRINGS_EQUAL(CurrentLogContextPath().second, "ctx3"); YQL_LOG(ERROR) << "level3"; } UNIT_ASSERT_STRINGS_EQUAL(CurrentLogContextPath().second, "ctx1/ctx2"); YQL_LOG(WARN) << "level2 - end"; } UNIT_ASSERT_STRINGS_EQUAL(CurrentLogContextPath().second, "ctx1"); YQL_LOG(INFO) << "level1 - end"; } UNIT_ASSERT_STRINGS_EQUAL(CurrentLogContextPath().second, ""); TString row1Str; TString row2Str; TString row3Str; TString row4Str; TString row5Str; TString _; Split(out.Str(), '\n', row1Str, row2Str, row3Str, row4Str, row5Str, _); { TLogRow logRow = ParseLogRow(row1Str); UNIT_ASSERT_EQUAL(logRow.Level, ELevel::INFO); UNIT_ASSERT_EQUAL(logRow.Component, EComponent::Default); UNIT_ASSERT_STRINGS_EQUAL(logRow.Path, "ctx1"); UNIT_ASSERT_STRINGS_EQUAL(logRow.Message, "level1 - begin"); } { TLogRow logRow = ParseLogRow(row2Str); UNIT_ASSERT_EQUAL(logRow.Level, ELevel::WARN); UNIT_ASSERT_EQUAL(logRow.Component, EComponent::Default); UNIT_ASSERT_STRINGS_EQUAL(logRow.Path, "ctx1/ctx2"); UNIT_ASSERT_STRINGS_EQUAL(logRow.Message, "level2 - begin"); } { TLogRow logRow = ParseLogRow(row3Str); UNIT_ASSERT_EQUAL(logRow.Level, ELevel::ERROR); UNIT_ASSERT_EQUAL(logRow.Component, EComponent::Default); UNIT_ASSERT_STRINGS_EQUAL(logRow.Path, "ctx3"); UNIT_ASSERT_STRINGS_EQUAL(logRow.Message, "level3"); } { TLogRow logRow = ParseLogRow(row4Str); UNIT_ASSERT_EQUAL(logRow.Level, ELevel::WARN); UNIT_ASSERT_EQUAL(logRow.Component, EComponent::Default); UNIT_ASSERT_STRINGS_EQUAL(logRow.Path, "ctx1/ctx2"); UNIT_ASSERT_STRINGS_EQUAL(logRow.Message, "level2 - end"); } { TLogRow logRow = ParseLogRow(row5Str); UNIT_ASSERT_EQUAL(logRow.Level, ELevel::INFO); UNIT_ASSERT_EQUAL(logRow.Component, EComponent::Default); UNIT_ASSERT_STRINGS_EQUAL(logRow.Path, "ctx1"); UNIT_ASSERT_STRINGS_EQUAL(logRow.Message, "level1 - end"); } } Y_UNIT_TEST_ON_EACH_LOG_FORMAT(Profiling) { TStringStream out; YqlLoggerScope logger(&out, Format); { YQL_PROFILE_SCOPE(INFO, "scope1"); } YQL_PROFILE_BLOCK(WARN, "block1") { Sleep(TDuration::MilliSeconds(2)); } YQL_PROFILE_BLOCK(ERROR, "block2") { Sleep(TDuration::MilliSeconds(1200)); } bool isExecuted = false; YQL_PROFILE_BLOCK(TRACE, "block3") { // log will be filtered out isExecuted = true; } UNIT_ASSERT(isExecuted); TString row1Str; TString row2Str; TString row3Str; TString _; Split(out.Str(), '\n', row1Str, row2Str, row3Str, _); { TLogRow logRow = ParseLogRow(row1Str); UNIT_ASSERT_EQUAL(logRow.Level, ELevel::INFO); UNIT_ASSERT_EQUAL(logRow.Component, EComponent::Perf); UNIT_ASSERT_EQUAL(logRow.Component, EComponent::Performance); std::regex re(R"(Execution of \[scope1\] took [0-9\.]+us)"); bool isMatch = std::regex_match(logRow.Message.c_str(), re); UNIT_ASSERT_C(isMatch, "Unexpected message: " << logRow.Message); } { TLogRow logRow = ParseLogRow(row2Str); UNIT_ASSERT_EQUAL(logRow.Level, ELevel::WARN); UNIT_ASSERT_EQUAL(logRow.Component, EComponent::Perf); UNIT_ASSERT_EQUAL(logRow.Component, EComponent::Performance); std::regex re(R"(Execution of \[block1\] took [0-9\.]+ms)"); bool isMatch = std::regex_match(logRow.Message.c_str(), re); UNIT_ASSERT_C(isMatch, "Unexpected message: " << logRow.Message); } { TLogRow logRow = ParseLogRow(row3Str); UNIT_ASSERT_EQUAL(logRow.Level, ELevel::ERROR); UNIT_ASSERT_EQUAL(logRow.Component, EComponent::Perf); UNIT_ASSERT_EQUAL(logRow.Component, EComponent::Performance); std::regex re(R"(Execution of \[block2\] took [0-9\.]+s)"); bool isMatch = std::regex_match(logRow.Message.c_str(), re); UNIT_ASSERT_C(isMatch, "Unexpected message: " << logRow.Message); } } int Func1(int a, char b) { YQL_PROFILE_FUNC(INFO); return a + b; } int Func2(int a, char b) { YQL_PROFILE_FUNCSIG(WARN); return a + b; } Y_UNIT_TEST_ON_EACH_LOG_FORMAT(ProfilingFuncs) { TStringStream out; YqlLoggerScope logger(&out, Format); Func1(1, 2); Func2(1, 2); TString row1Str; TString row2Str; TString _; Split(out.Str(), '\n', row1Str, row2Str, _); { TLogRow logRow = ParseLogRow(row1Str); UNIT_ASSERT_EQUAL(logRow.Level, ELevel::INFO); UNIT_ASSERT_EQUAL(logRow.Component, EComponent::Perf); UNIT_ASSERT_EQUAL(logRow.Component, EComponent::Performance); #ifdef _win_ std::regex re("Execution of \\[[NTestSuiteTLogTest::Func1\\] took [0-9\\.]+us"); #else std::regex re(R"(Execution of \[Func1\] took [0-9\.]+us)"); #endif bool isMatch = std::regex_match(logRow.Message.c_str(), re); UNIT_ASSERT_C(isMatch, "Unexpected message: " << logRow.Message); } { TLogRow logRow = ParseLogRow(row2Str); UNIT_ASSERT_EQUAL(logRow.Level, ELevel::WARN); UNIT_ASSERT_EQUAL(logRow.Component, EComponent::Perf); UNIT_ASSERT_EQUAL(logRow.Component, EComponent::Performance); #ifdef _win_ std::regex re("Execution of \\[int __cdecl NTestSuiteTLogTest::Func2\\(int, char\\)\\] took [0-9\\.]+us"); #else std::regex re(R"(Execution of \[int NTestSuiteTLogTest::Func2\(int, char\)\] took [0-9\.]+us)"); #endif bool isMatch = std::regex_match(logRow.Message.c_str(), re); UNIT_ASSERT_C(isMatch, "Unexpected message: " << logRow.Message); } } Y_UNIT_TEST_ON_EACH_LOG_FORMAT(Limit1) { size_t limit = 0; { TStringStream out; YqlLoggerScope logger(&out, Format); YqlLogger().UpdateProcInfo("proc"); YQL_CLOG(INFO, Core) << "message1"; limit = out.Str().length() * 2 - 7; // Not more than 2 log lines } TStringStream out; YqlLoggerScope logger(&out, Format); YqlLogger().UpdateProcInfo("proc"); YqlLogger().SetMaxLogLimit(limit); YQL_CLOG(INFO, Core) << "message1"; YQL_CLOG(INFO, Core) << "message2"; YQL_CLOG(INFO, Core) << "message3"; TString row1Str; TString row2Str; TString row3Str; TString _; Split(out.Str(), '\n', row1Str, row2Str, row3Str, _); { TLogRow logRow = ParseLogRow(row1Str); UNIT_ASSERT_EQUAL(logRow.Level, ELevel::INFO); UNIT_ASSERT_EQUAL(logRow.Component, EComponent::Core); UNIT_ASSERT_STRINGS_EQUAL(logRow.Message, "message1"); } { TLogRow logRow = ParseLogRow(row2Str); UNIT_ASSERT_EQUAL(logRow.Level, ELevel::INFO); UNIT_ASSERT_EQUAL(logRow.Component, EComponent::Core); UNIT_ASSERT_STRINGS_EQUAL(logRow.Message, "message2"); } { TLogRow logRow = ParseLogRow(row3Str); UNIT_ASSERT_EQUAL(logRow.Level, ELevel::FATAL); UNIT_ASSERT_EQUAL(logRow.Component, EComponent::Default); UNIT_ASSERT_STRINGS_EQUAL(logRow.Message, "Log is truncated by limit"); } } Y_UNIT_TEST_ON_EACH_LOG_FORMAT(Limit2) { size_t limit = 0; { TStringStream out; YqlLoggerScope logger(&out, Format); YqlLogger().UpdateProcInfo("proc"); YQL_CLOG(INFO, Core) << "message1"; limit = out.Str().length() * 2 - 7; // Not more than 2 log lines } TStringStream out; YqlLoggerScope logger(&out, Format); YqlLogger().UpdateProcInfo("proc"); YqlLogger().SetMaxLogLimit(limit); YQL_CLOG(INFO, Core) << "message1"; YQL_CLOG(INFO, Core) << "message2"; YQL_CLOG(WARN, Core) << "message3"; TString row1Str; TString row2Str; TString row3Str; TString row4Str; TString _; Split(out.Str(), '\n', row1Str, row2Str, row3Str, row4Str, _); { TLogRow logRow = ParseLogRow(row1Str); UNIT_ASSERT_EQUAL(logRow.Level, ELevel::INFO); UNIT_ASSERT_EQUAL(logRow.Component, EComponent::Core); UNIT_ASSERT_STRINGS_EQUAL(logRow.Message, "message1"); } { TLogRow logRow = ParseLogRow(row2Str); UNIT_ASSERT_EQUAL(logRow.Level, ELevel::INFO); UNIT_ASSERT_EQUAL(logRow.Component, EComponent::Core); UNIT_ASSERT_STRINGS_EQUAL(logRow.Message, "message2"); } { TLogRow logRow = ParseLogRow(row3Str); UNIT_ASSERT_EQUAL(logRow.Level, ELevel::FATAL); UNIT_ASSERT_EQUAL(logRow.Component, EComponent::Default); UNIT_ASSERT_STRINGS_EQUAL(logRow.Message, "Log is truncated by limit"); } { TLogRow logRow = ParseLogRow(row4Str); UNIT_ASSERT_EQUAL(logRow.Level, ELevel::WARN); UNIT_ASSERT_EQUAL(logRow.Component, EComponent::Core); UNIT_ASSERT_STRINGS_EQUAL(logRow.Message, "message3"); } } } // Y_UNIT_TEST_SUITE(TLogTest)