aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp/logger/global
diff options
context:
space:
mode:
authorDevtools Arcadia <arcadia-devtools@yandex-team.ru>2022-02-07 18:08:42 +0300
committerDevtools Arcadia <arcadia-devtools@mous.vla.yp-c.yandex.net>2022-02-07 18:08:42 +0300
commit1110808a9d39d4b808aef724c861a2e1a38d2a69 (patch)
treee26c9fed0de5d9873cce7e00bc214573dc2195b7 /library/cpp/logger/global
downloadydb-1110808a9d39d4b808aef724c861a2e1a38d2a69.tar.gz
intermediate changes
ref:cde9a383711a11544ce7e107a78147fb96cc4029
Diffstat (limited to 'library/cpp/logger/global')
-rw-r--r--library/cpp/logger/global/common.cpp36
-rw-r--r--library/cpp/logger/global/common.h149
-rw-r--r--library/cpp/logger/global/global.cpp43
-rw-r--r--library/cpp/logger/global/global.h125
-rw-r--r--library/cpp/logger/global/rty_formater.cpp94
-rw-r--r--library/cpp/logger/global/rty_formater.h61
-rw-r--r--library/cpp/logger/global/rty_formater_ut.cpp31
-rw-r--r--library/cpp/logger/global/ut/ya.make15
-rw-r--r--library/cpp/logger/global/ya.make19
9 files changed, 573 insertions, 0 deletions
diff --git a/library/cpp/logger/global/common.cpp b/library/cpp/logger/global/common.cpp
new file mode 100644
index 00000000000..4fb05c19b4b
--- /dev/null
+++ b/library/cpp/logger/global/common.cpp
@@ -0,0 +1,36 @@
+#include "common.h"
+
+#include <util/generic/yexception.h>
+
+namespace NLoggingImpl {
+ TString GetLocalTimeSSimple() {
+ struct tm tm;
+ return Strftime("%b%d_%H%M%S", Now().LocalTime(&tm));
+ }
+
+ TString PrepareToOpenLog(TString logType, const int logLevel, const bool rotation, const bool startAsDaemon) {
+ Y_ENSURE(logLevel >= 0 && logLevel <= (int)LOG_MAX_PRIORITY, "Incorrect log level");
+
+ if (rotation && TFsPath(logType).Exists()) {
+ TString newPath = Sprintf("%s_%s_%" PRIu64, logType.data(), NLoggingImpl::GetLocalTimeSSimple().data(), static_cast<ui64>(Now().MicroSeconds()));
+ TFsPath(logType).RenameTo(newPath);
+ }
+ if (startAsDaemon && (logType == "console"sv || logType == "cout"sv || logType == "cerr"sv)) {
+ logType = "null";
+ }
+
+ return logType;
+ }
+}
+
+bool TLogFilter::CheckLoggingContext(TLog& log, const TLogRecordContext& context) {
+ return context.Priority <= log.FiltrationLevel();
+}
+
+TSimpleSharedPtr<TLogElement> TLogFilter::StartRecord(TLog& logger, const TLogRecordContext& context, TSimpleSharedPtr<TLogElement> earlier) {
+ if (earlier)
+ return earlier;
+ TSimpleSharedPtr<TLogElement> result(new TLogElement(&logger));
+ *result << context.Priority;
+ return result;
+}
diff --git a/library/cpp/logger/global/common.h b/library/cpp/logger/global/common.h
new file mode 100644
index 00000000000..7dcf650decb
--- /dev/null
+++ b/library/cpp/logger/global/common.h
@@ -0,0 +1,149 @@
+#pragma once
+
+#include <util/datetime/base.h>
+
+#include <util/folder/path.h>
+#include <util/generic/singleton.h>
+#include <util/generic/string.h>
+#include <util/generic/ptr.h>
+#include <util/generic/yexception.h>
+#include <util/string/printf.h>
+#include <util/system/src_location.h>
+
+#include <library/cpp/logger/log.h>
+
+namespace NLoggingImpl {
+ const size_t SingletonPriority = 500;
+}
+
+template <class T>
+T* CreateDefaultLogger() {
+ return nullptr;
+}
+
+namespace NLoggingImpl {
+ template<class T, class TTraits>
+ class TOperatorBase {
+ struct TPtr {
+ TPtr()
+ : Instance(TTraits::CreateDefault())
+ {
+ }
+
+ THolder<T> Instance;
+ };
+
+ public:
+ inline static bool Usage() {
+ return SingletonWithPriority<TPtr, SingletonPriority>()->Instance.Get();
+ }
+
+ inline static T* Get() {
+ return SingletonWithPriority<TPtr, SingletonPriority>()->Instance.Get();
+ }
+
+ inline static void Set(T* v) {
+ SingletonWithPriority<TPtr, SingletonPriority>()->Instance.Reset(v);
+ }
+ };
+
+ template<class T>
+ struct TLoggerTraits {
+ static T* CreateDefault() {
+ return CreateDefaultLogger<T>();
+ }
+ };
+}
+
+template <class T>
+class TLoggerOperator : public NLoggingImpl::TOperatorBase<T, NLoggingImpl::TLoggerTraits<T>> {
+public:
+ inline static TLog& Log() {
+ Y_ASSERT(TLoggerOperator::Usage());
+ return *TLoggerOperator::Get();
+ }
+};
+
+namespace NLoggingImpl {
+
+ TString GetLocalTimeSSimple();
+
+ // Returns correct log type to use
+ TString PrepareToOpenLog(TString logType, int logLevel, bool rotation, bool startAsDaemon);
+
+ template <class TLoggerType>
+ void InitLogImpl(TString logType, const int logLevel, const bool rotation, const bool startAsDaemon) {
+ TLoggerOperator<TLoggerType>::Set(new TLoggerType(PrepareToOpenLog(logType, logLevel, rotation, startAsDaemon), (ELogPriority)logLevel));
+ }
+}
+
+struct TLogRecordContext {
+ constexpr TLogRecordContext(const TSourceLocation& sourceLocation, TStringBuf customMessage, ELogPriority priority)
+ : SourceLocation(sourceLocation)
+ , CustomMessage(customMessage)
+ , Priority(priority)
+ {}
+
+ TSourceLocation SourceLocation;
+ TStringBuf CustomMessage;
+ ELogPriority Priority;
+};
+
+template <class... R>
+struct TLogRecordPreprocessor;
+
+template <>
+struct TLogRecordPreprocessor<> {
+ inline static bool CheckLoggingContext(TLog& /*log*/, const TLogRecordContext& /*context*/) {
+ return true;
+ }
+
+ inline static TSimpleSharedPtr<TLogElement> StartRecord(TLog& log, const TLogRecordContext& context, TSimpleSharedPtr<TLogElement> earlier) {
+ if (earlier)
+ return earlier;
+ TSimpleSharedPtr<TLogElement> result(new TLogElement(&log));
+ *result << context.Priority;
+ return result;
+ }
+};
+
+template <class H, class... R>
+struct TLogRecordPreprocessor<H, R...> {
+ inline static bool CheckLoggingContext(TLog& log, const TLogRecordContext& context) {
+ return H::CheckLoggingContext(log, context) && TLogRecordPreprocessor<R...>::CheckLoggingContext(log, context);
+ }
+
+ inline static TSimpleSharedPtr<TLogElement> StartRecord(TLog& log, const TLogRecordContext& context, TSimpleSharedPtr<TLogElement> earlier) {
+ TSimpleSharedPtr<TLogElement> first = H::StartRecord(log, context, earlier);
+ return TLogRecordPreprocessor<R...>::StartRecord(log, context, first);
+ }
+};
+
+struct TLogFilter {
+ static bool CheckLoggingContext(TLog& log, const TLogRecordContext& context);
+ static TSimpleSharedPtr<TLogElement> StartRecord(TLog& log, const TLogRecordContext& context, TSimpleSharedPtr<TLogElement> earlier);
+};
+
+class TNullLog;
+
+template <class TPreprocessor>
+TSimpleSharedPtr<TLogElement> GetLoggerForce(TLog& log, const TLogRecordContext& context) {
+ if (TSimpleSharedPtr<TLogElement> result = TPreprocessor::StartRecord(log, context, nullptr))
+ return result;
+ return new TLogElement(&TLoggerOperator<TNullLog>::Log());
+}
+
+namespace NPrivateGlobalLogger {
+ struct TEatStream {
+ Y_FORCE_INLINE bool operator|(const IOutputStream&) const {
+ return true;
+ }
+ };
+}
+
+#define LOGGER_GENERIC_LOG_CHECKED(logger, preprocessor, level, message) (*GetLoggerForce<preprocessor>(logger, TLogRecordContext(__LOCATION__, message, level)))
+#define LOGGER_CHECKED_GENERIC_LOG(logger, preprocessor, level, message) \
+ (preprocessor::CheckLoggingContext(logger, TLogRecordContext(__LOCATION__, message, level))) && NPrivateGlobalLogger::TEatStream() | (*(preprocessor::StartRecord(logger, TLogRecordContext(__LOCATION__, message, level), nullptr)))
+
+#define SINGLETON_GENERIC_LOG_CHECKED(type, preprocessor, level, message) LOGGER_GENERIC_LOG_CHECKED(TLoggerOperator<type>::Log(), preprocessor, level, message)
+#define SINGLETON_CHECKED_GENERIC_LOG(type, preprocessor, level, message) LOGGER_CHECKED_GENERIC_LOG(TLoggerOperator<type>::Log(), preprocessor, level, message)
diff --git a/library/cpp/logger/global/global.cpp b/library/cpp/logger/global/global.cpp
new file mode 100644
index 00000000000..9fbd10f6661
--- /dev/null
+++ b/library/cpp/logger/global/global.cpp
@@ -0,0 +1,43 @@
+#include "global.h"
+
+static void DoInitGlobalLog(THolder<TGlobalLog> logger, THolder<ILoggerFormatter> formatter) {
+ TLoggerOperator<TGlobalLog>::Set(logger.Release());
+ if (!formatter) {
+ formatter.Reset(CreateRtyLoggerFormatter());
+ }
+ TLoggerFormatterOperator::Set(formatter.Release());
+}
+
+void DoInitGlobalLog(const TString& logType, const int logLevel, const bool rotation, const bool startAsDaemon, THolder<ILoggerFormatter> formatter, bool threaded) {
+ DoInitGlobalLog(
+ MakeHolder<TGlobalLog>(
+ CreateLogBackend(
+ NLoggingImpl::PrepareToOpenLog(logType, logLevel, rotation, startAsDaemon),
+ (ELogPriority)logLevel,
+ threaded)),
+ std::move(formatter));
+}
+
+void DoInitGlobalLog(THolder<TLogBackend> backend, THolder<ILoggerFormatter> formatter) {
+ DoInitGlobalLog(THolder(new TGlobalLog(std::move(backend))), std::move(formatter));
+}
+
+bool GlobalLogInitialized() {
+ return TLoggerOperator<TGlobalLog>::Usage();
+}
+
+template <>
+TGlobalLog* CreateDefaultLogger<TGlobalLog>() {
+ return new TGlobalLog("console", TLOG_INFO);
+}
+
+template <>
+TNullLog* CreateDefaultLogger<TNullLog>() {
+ return new TNullLog("null");
+}
+
+NPrivateGlobalLogger::TVerifyEvent::~TVerifyEvent() {
+ const TString info = Str();
+ FATAL_LOG << info << Endl;
+ Y_FAIL("%s", info.data());
+}
diff --git a/library/cpp/logger/global/global.h b/library/cpp/logger/global/global.h
new file mode 100644
index 00000000000..cbe71b16ea5
--- /dev/null
+++ b/library/cpp/logger/global/global.h
@@ -0,0 +1,125 @@
+#pragma once
+
+#include "common.h"
+#include "rty_formater.h"
+
+// ATTENTION! MUST CALL DoInitGlobalLog BEFORE USAGE
+
+bool GlobalLogInitialized();
+void DoInitGlobalLog(const TString& logType, const int logLevel, const bool rotation, const bool startAsDaemon, THolder<ILoggerFormatter> formatter = {}, bool threaded = false);
+void DoInitGlobalLog(THolder<TLogBackend> backend, THolder<ILoggerFormatter> formatter = {});
+
+inline void InitGlobalLog2Null() {
+ DoInitGlobalLog("null", TLOG_EMERG, false, false);
+}
+
+inline void InitGlobalLog2Console(int loglevel = TLOG_INFO) {
+ DoInitGlobalLog("console", loglevel, false, false);
+}
+
+class TGlobalLog: public TLog {
+public:
+ TGlobalLog(const TString& logType, ELogPriority priority = LOG_MAX_PRIORITY)
+ : TLog(logType, priority)
+ {
+ }
+
+ TGlobalLog(THolder<TLogBackend> backend)
+ : TLog(std::move(backend))
+ {
+ }
+};
+
+template <>
+TGlobalLog* CreateDefaultLogger<TGlobalLog>();
+
+class TNullLog: public TLog {
+public:
+ TNullLog(const TString& logType, ELogPriority priority = LOG_MAX_PRIORITY)
+ : TLog(logType, priority)
+ {
+ }
+
+ TNullLog(THolder<TLogBackend> backend)
+ : TLog(std::move(backend))
+ {
+ }
+};
+
+template <>
+TNullLog* CreateDefaultLogger<TNullLog>();
+
+template <>
+class TSingletonTraits<TLoggerOperator<TGlobalLog>::TPtr> {
+public:
+ static const size_t Priority = NLoggingImpl::SingletonPriority;
+};
+
+template <>
+class TSingletonTraits<TLoggerOperator<TNullLog>::TPtr> {
+public:
+ static const size_t Priority = NLoggingImpl::SingletonPriority;
+};
+
+#define FATAL_LOG SINGLETON_CHECKED_GENERIC_LOG(TGlobalLog, TRTYLogPreprocessor, TLOG_CRIT, "CRITICAL_INFO")
+#define ALERT_LOG SINGLETON_CHECKED_GENERIC_LOG(TGlobalLog, TRTYLogPreprocessor, TLOG_ALERT, "ALERT")
+#define ERROR_LOG SINGLETON_CHECKED_GENERIC_LOG(TGlobalLog, TRTYLogPreprocessor, TLOG_ERR, "ERROR")
+#define WARNING_LOG SINGLETON_CHECKED_GENERIC_LOG(TGlobalLog, TRTYLogPreprocessor, TLOG_WARNING, "WARNING")
+#define NOTICE_LOG SINGLETON_CHECKED_GENERIC_LOG(TGlobalLog, TRTYLogPreprocessor, TLOG_NOTICE, "NOTICE")
+#define INFO_LOG SINGLETON_CHECKED_GENERIC_LOG(TGlobalLog, TRTYLogPreprocessor, TLOG_INFO, "INFO")
+#define DEBUG_LOG SINGLETON_CHECKED_GENERIC_LOG(TGlobalLog, TRTYLogPreprocessor, TLOG_DEBUG, "DEBUG")
+#define RESOURCES_LOG SINGLETON_CHECKED_GENERIC_LOG(TGlobalLog, TRTYLogPreprocessor, TLOG_RESOURCES, "RESOURCES")
+
+#define TEMPLATE_LOG(logLevel) SINGLETON_CHECKED_GENERIC_LOG(TGlobalLog, TRTYLogPreprocessor, logLevel, ToString(logLevel).data())
+
+#define IS_LOG_ACTIVE(logLevel) (TLoggerOperator<TGlobalLog>::Log().FiltrationLevel() >= logLevel)
+
+#define RTY_MEM_LOG(Action) \
+ { NOTICE_LOG << "RESOURCES On " << Action << ": " << NLoggingImpl::GetSystemResources() << Endl; };
+
+#define VERIFY_WITH_LOG(expr, msg, ...) \
+ do { \
+ if (Y_UNLIKELY(!(expr))) { \
+ FATAL_LOG << Sprintf(msg, ##__VA_ARGS__) << Endl; \
+ Y_VERIFY(false, msg, ##__VA_ARGS__); \
+ }; \
+ } while (0);
+
+namespace NPrivateGlobalLogger {
+ class TVerifyEvent: public TStringStream {
+ public:
+ ~TVerifyEvent();
+ template <class T>
+ inline TVerifyEvent& operator<<(const T& t) {
+ static_cast<IOutputStream&>(*this) << t;
+
+ return *this;
+ }
+ };
+ class TNullStream: public TStringStream {
+ public:
+ ~TNullStream() = default;
+
+ template <class T>
+ inline TNullStream& operator<<(const T& /*t*/) {
+ return *this;
+ }
+ };
+}
+
+#define CHECK_WITH_LOG(expr) \
+ Y_UNLIKELY(!(expr)) && NPrivateGlobalLogger::TEatStream() | NPrivateGlobalLogger::TVerifyEvent() << __LOCATION__ << ": " << #expr << "(verification failed!): "
+
+#if !defined(NDEBUG) && !defined(__GCCXML__)
+#define ASSERT_WITH_LOG(expr) \
+ Y_UNLIKELY(!(expr)) && NPrivateGlobalLogger::TEatStream() | NPrivateGlobalLogger::TVerifyEvent() << __LOCATION__ << ": " << #expr << "(verification failed!): "
+#else
+#define ASSERT_WITH_LOG(expr) \
+ Y_UNLIKELY(false && !(expr)) && NPrivateGlobalLogger::TEatStream() | NPrivateGlobalLogger::TNullStream()
+#endif
+
+#define CHECK_EQ_WITH_LOG(a, b) CHECK_WITH_LOG((a) == (b)) << a << " != " << b;
+#define CHECK_LEQ_WITH_LOG(a, b) CHECK_WITH_LOG((a) <= (b)) << a << " > " << b;
+
+#define FAIL_LOG(msg, ...) VERIFY_WITH_LOG(false, msg, ##__VA_ARGS__)
+#define S_FAIL_LOG CHECK_WITH_LOG(false)
diff --git a/library/cpp/logger/global/rty_formater.cpp b/library/cpp/logger/global/rty_formater.cpp
new file mode 100644
index 00000000000..305f8470c55
--- /dev/null
+++ b/library/cpp/logger/global/rty_formater.cpp
@@ -0,0 +1,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;
+}
diff --git a/library/cpp/logger/global/rty_formater.h b/library/cpp/logger/global/rty_formater.h
new file mode 100644
index 00000000000..6532e1d7695
--- /dev/null
+++ b/library/cpp/logger/global/rty_formater.h
@@ -0,0 +1,61 @@
+#pragma once
+
+#include "common.h"
+
+namespace NMemInfo {
+ struct TMemInfo;
+}
+
+class ILoggerFormatter {
+public:
+ virtual ~ILoggerFormatter() = default;
+
+ virtual void Format(const TLogRecordContext&, TLogElement&) const = 0;
+};
+
+ILoggerFormatter* CreateRtyLoggerFormatter();
+
+namespace NLoggingImpl {
+ class TLocalTimeS {
+ public:
+ TLocalTimeS(TInstant instant = TInstant::Now())
+ : Instant(instant)
+ {
+ }
+
+ TInstant GetInstant() const {
+ return Instant;
+ }
+
+ operator TString() const;
+ TString operator+(TStringBuf right) const;
+
+ private:
+ TInstant Instant;
+ };
+
+ IOutputStream& operator<<(IOutputStream& out, TLocalTimeS localTimeS);
+
+ inline TLocalTimeS GetLocalTimeS() {
+ return TLocalTimeS();
+ }
+
+ TString GetSystemResources();
+ TString PrintSystemResources(const NMemInfo::TMemInfo& info);
+
+ struct TLoggerFormatterTraits {
+ static ILoggerFormatter* CreateDefault() {
+ return CreateRtyLoggerFormatter();
+ }
+ };
+}
+
+class TLoggerFormatterOperator : public NLoggingImpl::TOperatorBase<ILoggerFormatter, NLoggingImpl::TLoggerFormatterTraits> {
+};
+
+struct TRTYMessageFormater {
+ static bool CheckLoggingContext(TLog& logger, const TLogRecordContext& context);
+ static TSimpleSharedPtr<TLogElement> StartRecord(TLog& logger, const TLogRecordContext& context, TSimpleSharedPtr<TLogElement> earlier);
+};
+
+using TRTYLogPreprocessor = TLogRecordPreprocessor<TLogFilter, TRTYMessageFormater>;
diff --git a/library/cpp/logger/global/rty_formater_ut.cpp b/library/cpp/logger/global/rty_formater_ut.cpp
new file mode 100644
index 00000000000..551a97c5bfe
--- /dev/null
+++ b/library/cpp/logger/global/rty_formater_ut.cpp
@@ -0,0 +1,31 @@
+#include "rty_formater.h"
+
+#include <library/cpp/testing/unittest/registar.h>
+
+namespace {
+ const TStringBuf SampleISO8601("2017-07-25T19:26:09.894000+03:00");
+ const TStringBuf SampleRtyLog("2017-07-25 19:26:09.894 +0300");
+}
+
+Y_UNIT_TEST_SUITE(NLoggingImplTest) {
+ Y_UNIT_TEST(TestTLocalTimeSToStream) {
+ NLoggingImpl::TLocalTimeS lt(TInstant::ParseIso8601Deprecated(SampleISO8601));
+ TStringStream ss;
+ ss << lt;
+ UNIT_ASSERT_EQUAL(ss.Str(), SampleRtyLog);
+ }
+ Y_UNIT_TEST(TestTLocalTimeSToString) {
+ NLoggingImpl::TLocalTimeS lt(TInstant::ParseIso8601Deprecated(SampleISO8601));
+ UNIT_ASSERT_EQUAL(TString(lt), SampleRtyLog);
+ }
+ Y_UNIT_TEST(TestTLocalTimeSAddLeft) {
+ NLoggingImpl::TLocalTimeS lt(TInstant::ParseIso8601Deprecated(SampleISO8601));
+ TStringBuf suffix("suffix");
+ UNIT_ASSERT_EQUAL(lt + suffix, TString(SampleRtyLog) + suffix);
+ }
+ Y_UNIT_TEST(TestTLocalTimeSAddRight) {
+ NLoggingImpl::TLocalTimeS lt(TInstant::ParseIso8601Deprecated(SampleISO8601));
+ TString prefix("prefix");
+ UNIT_ASSERT_EQUAL(prefix + lt, prefix + SampleRtyLog);
+ }
+}
diff --git a/library/cpp/logger/global/ut/ya.make b/library/cpp/logger/global/ut/ya.make
new file mode 100644
index 00000000000..8aea38906f5
--- /dev/null
+++ b/library/cpp/logger/global/ut/ya.make
@@ -0,0 +1,15 @@
+UNITTEST()
+
+OWNER(salmin)
+
+PEERDIR(
+ library/cpp/logger/global
+)
+
+SRCDIR(library/cpp/logger/global)
+
+SRCS(
+ rty_formater_ut.cpp
+)
+
+END()
diff --git a/library/cpp/logger/global/ya.make b/library/cpp/logger/global/ya.make
new file mode 100644
index 00000000000..20eb361e728
--- /dev/null
+++ b/library/cpp/logger/global/ya.make
@@ -0,0 +1,19 @@
+LIBRARY()
+
+OWNER(g:geosaas)
+
+PEERDIR(
+ library/cpp/logger
+)
+
+IF (OS_WINDOWS)
+ NO_WERROR()
+ENDIF()
+
+SRCS(
+ common.cpp
+ global.cpp
+ rty_formater.cpp
+)
+
+END()