diff options
author | alexvru <alexvru@ydb.tech> | 2022-11-03 10:35:20 +0300 |
---|---|---|
committer | alexvru <alexvru@ydb.tech> | 2022-11-03 10:35:20 +0300 |
commit | 5b229b5f88be3141722b369f4fb13bb933c29a28 (patch) | |
tree | 630d94aab932344b0f1fa4b07a289f83d1f82c1f | |
parent | 3910880160a4aaae4c26adeea4fe525e91856737 (diff) | |
download | ydb-5b229b5f88be3141722b369f4fb13bb933c29a28.tar.gz |
Make stlog a bit better
-rw-r--r-- | ydb/core/keyvalue/keyvalue_storage_read_request.cpp | 14 | ||||
-rw-r--r-- | ydb/core/util/CMakeLists.txt | 2 | ||||
-rw-r--r-- | ydb/core/util/stlog.cpp | 17 | ||||
-rw-r--r-- | ydb/core/util/stlog.h | 244 | ||||
-rw-r--r-- | ydb/core/util/stlog_ut.cpp | 41 | ||||
-rw-r--r-- | ydb/core/util/ut/CMakeLists.darwin.txt | 1 | ||||
-rw-r--r-- | ydb/core/util/ut/CMakeLists.linux-aarch64.txt | 1 | ||||
-rw-r--r-- | ydb/core/util/ut/CMakeLists.linux.txt | 1 |
8 files changed, 243 insertions, 78 deletions
diff --git a/ydb/core/keyvalue/keyvalue_storage_read_request.cpp b/ydb/core/keyvalue/keyvalue_storage_read_request.cpp index 7d463d8736b..d837e194370 100644 --- a/ydb/core/keyvalue/keyvalue_storage_read_request.cpp +++ b/ydb/core/keyvalue/keyvalue_storage_read_request.cpp @@ -8,13 +8,15 @@ namespace NKikimr { namespace NKeyValue { -#define STLOG_WITH_ERROR_DESCRIPTION(VARIABLE, PRIO, COMP, MARKER, TEXT, ...) \ +#define STLOG_WITH_ERROR_DESCRIPTION(VARIABLE, PRIO, COMP, ...) \ do { \ - struct MARKER {}; \ - VARIABLE = (TStringBuilder() << VARIABLE << Endl \ - << ::NKikimr::NStLog::TMessage<MARKER>(__FILE__, __LINE__, #MARKER, TStringBuilder() << TEXT) \ - STLOG_PARAMS(__VA_ARGS__)); \ - STLOG(PRIO, COMP, MARKER, TEXT, __VA_ARGS__); \ + VARIABLE += "\n"; \ + STLOG_STREAM(__stream, 0, __VA_ARGS__); \ + const TString message = __stream.Str(); \ + VARIABLE += message; \ + const auto priority = [&]{ using namespace NActors::NLog; return (PRIO); }(); \ + const auto component = [&]{ using namespace NKikimrServices; using namespace NActorsServices; return (COMP); }(); \ + LOG_LOG_S(*TlsActivationContext, priority, component, message); \ } while(false) \ // STLOG_WITH_ERROR_DESCRIPTION diff --git a/ydb/core/util/CMakeLists.txt b/ydb/core/util/CMakeLists.txt index d473116dd5f..ba1c081f7db 100644 --- a/ydb/core/util/CMakeLists.txt +++ b/ydb/core/util/CMakeLists.txt @@ -19,6 +19,7 @@ target_link_libraries(ydb-core-util PUBLIC cpp-containers-stack_vector cpp-html-escape library-cpp-ipmath + library-cpp-json library-cpp-lwtrace cpp-monlib-dynamic_counters library-cpp-random_provider @@ -41,6 +42,7 @@ target_sources(ydb-core-util PRIVATE ${CMAKE_SOURCE_DIR}/ydb/core/util/memory_tracker.cpp ${CMAKE_SOURCE_DIR}/ydb/core/util/page_map.cpp ${CMAKE_SOURCE_DIR}/ydb/core/util/single_thread_ic_mock.cpp + ${CMAKE_SOURCE_DIR}/ydb/core/util/stlog.cpp ${CMAKE_SOURCE_DIR}/ydb/core/util/testactorsys.cpp ${CMAKE_SOURCE_DIR}/ydb/core/util/text.cpp ${CMAKE_SOURCE_DIR}/ydb/core/util/ulid.cpp diff --git a/ydb/core/util/stlog.cpp b/ydb/core/util/stlog.cpp new file mode 100644 index 00000000000..7c0cea61d18 --- /dev/null +++ b/ydb/core/util/stlog.cpp @@ -0,0 +1,17 @@ +#include "stlog.h" +#include <library/cpp/json/json_reader.h> +#include <google/protobuf/util/json_util.h> + +namespace NKikimr::NStLog { + + void ProtobufToJson(const NProtoBuf::Message& m, NJson::TJsonWriter& json) { + TString s; + google::protobuf::util::MessageToJsonString(m, &s); + if (s) { + json.UnsafeWrite(s); + } else { + json.Write("protobuf deserialization error"); + } + } + +} // NKikimr::NStLog diff --git a/ydb/core/util/stlog.h b/ydb/core/util/stlog.h index dfe8fa79502..c8b14bb4ea0 100644 --- a/ydb/core/util/stlog.h +++ b/ydb/core/util/stlog.h @@ -2,6 +2,7 @@ #include <ydb/core/protos/services.pb.h> #include <library/cpp/actors/core/log.h> +#include <library/cpp/json/json_writer.h> #include <google/protobuf/text_format.h> // special hack for gcc @@ -9,6 +10,10 @@ static struct STLOG_PARAM_T {} STLOG_PARAM; namespace NKikimr::NStLog { + static constexpr bool OutputLogJson = false; + + void ProtobufToJson(const NProtoBuf::Message& m, NJson::TJsonWriter& json); + #define STLOG_EXPAND(X) X #ifdef _MSC_VER @@ -45,46 +50,37 @@ namespace NKikimr::NStLog { #define STLOG_PARAMS_15(KV, ...) STLOG_PARAMS_1(KV) STLOG_EXPAND(STLOG_PARAMS_14(__VA_ARGS__)) #define STLOG_PARAMS_16(KV, ...) STLOG_PARAMS_1(KV) STLOG_EXPAND(STLOG_PARAMS_15(__VA_ARGS__)) -#define STLOGX(CTX, PRIO, COMP, MARKER, TEXT, ...) \ +#define STLOG_STREAM(NAME, JSON_OVERRIDE, MARKER, TEXT, ...) \ + struct MARKER {}; \ + TStringStream NAME; \ + if constexpr (JSON_OVERRIDE ? JSON_OVERRIDE > 0 : ::NKikimr::NStLog::OutputLogJson) { \ + NJson::TJsonWriter __json(&NAME, false); \ + ::NKikimr::NStLog::TMessage<MARKER>(__FILE__, __LINE__, #MARKER)STLOG_PARAMS(__VA_ARGS__).WriteToJson(__json) << TEXT; \ + } else { \ + ::NKikimr::NStLog::TMessage<MARKER>(__FILE__, __LINE__, #MARKER)STLOG_PARAMS(__VA_ARGS__).WriteToStream(NAME) << TEXT; \ + } + +#define STLOGX(CTX, PRIO, COMP, ...) \ do { \ - auto getPrio = [&] { using namespace NActors::NLog; return (PRIO); }; \ - auto getComp = [&] { using namespace NKikimrServices; using namespace NActorsServices; return (COMP); }; \ - auto makeMessage = [&] { \ - struct MARKER {}; \ - using Tag = MARKER; \ - return ::NKikimr::NStLog::TMessage<Tag>(__FILE__, __LINE__, #MARKER, TStringBuilder() << TEXT) \ - STLOG_PARAMS(__VA_ARGS__); \ + auto& ctx = (CTX); \ + const auto priority = [&]{ using namespace NActors::NLog; return (PRIO); }(); \ + const auto component = [&]{ using namespace NKikimrServices; using namespace NActorsServices; return (COMP); }(); \ + if (IS_LOG_PRIORITY_ENABLED(ctx, priority, component)) { \ + STLOG_STREAM(__stream, 0, __VA_ARGS__); \ + ::NActors::MemLogAdapter(ctx, priority, component, __stream.Str()); \ }; \ - LOG_LOG_S((CTX), getPrio(), getComp(), makeMessage()); \ } while (false) -#define STLOG(PRIO, COMP, MARKER, TEXT, ...) \ - do { \ - if (TActivationContext *ctxp = TlsActivationContext) { \ - auto getPrio = [&] { using namespace NActors::NLog; return (PRIO); }; \ - auto getComp = [&] { using namespace NKikimrServices; using namespace NActorsServices; return (COMP); }; \ - auto makeMessage = [&] { \ - struct MARKER {}; \ - using Tag = MARKER; \ - return ::NKikimr::NStLog::TMessage<Tag>(__FILE__, __LINE__, #MARKER, TStringBuilder() << TEXT) \ - STLOG_PARAMS(__VA_ARGS__); \ - }; \ - LOG_LOG_S(*ctxp, getPrio(), getComp(), makeMessage()); \ - } \ - } while (false) +#define STLOG(...) if (TActivationContext *ctxp = TlsActivationContext; !ctxp); else STLOGX(*ctxp, __VA_ARGS__) -#define STLOG_DEBUG_FAIL(COMP, MARKER, TEXT, ...) \ +#define STLOG_DEBUG_FAIL(COMP, ...) \ do { \ if (TActivationContext *ctxp = TlsActivationContext) { \ - auto getComp = [&] { using namespace NKikimrServices; using namespace NActorsServices; return (COMP); }; \ - auto makeMessage = [&] { \ - struct MARKER {}; \ - using Tag = MARKER; \ - return ::NKikimr::NStLog::TMessage<Tag>(__FILE__, __LINE__, #MARKER, TStringBuilder() << TEXT) \ - STLOG_PARAMS(__VA_ARGS__); \ - }; \ - Y_VERIFY_DEBUG_S(false, makeMessage()); \ - LOG_LOG_S(*ctxp, NLog::PRI_CRIT, getComp(), makeMessage()); \ + const auto component = [&]{ using namespace NKikimrServices; using namespace NActorsServices; return (COMP); }(); \ + STLOG_STREAM(__stream, 0, __VA_ARGS__); \ + const TString message = __stream.Str(); \ + Y_VERIFY_DEBUG_S(false, message); \ + LOG_LOG_S(*ctxp, NLog::PRI_CRIT, component, message); \ } \ } while (false) @@ -118,32 +114,36 @@ namespace NKikimr::NStLog { void WriteToStream(IOutputStream& s) const { Base::WriteToStream(s); - s << "# "; - OutputParam(s, Value); + OutputParam(s << "# ", Value); } - private: - template<typename TValue> - static void OutputParam(IOutputStream& s, const std::optional<TValue>& value) { - if (value) { - OutputParam(s, *value); - } else { - s << "<null>"; - } + void WriteToJson(NJson::TJsonWriter& json) const { + Base::WriteToJson(json); + OutputParam(json, Value); } + private: + template<typename Tx> struct TOptionalTraits { static constexpr bool HasOptionalValue = false; }; + template<> struct TOptionalTraits<const char*> { static constexpr bool HasOptionalValue = false; }; + template<> struct TOptionalTraits<char*> { static constexpr bool HasOptionalValue = false; }; + template<typename Tx> struct TOptionalTraits<std::optional<Tx>> { static constexpr bool HasOptionalValue = true; }; + template<typename Tx> struct TOptionalTraits<TMaybe<Tx>> { static constexpr bool HasOptionalValue = true; }; + template<typename Tx> struct TOptionalTraits<Tx*> { static constexpr bool HasOptionalValue = true; }; + template<typename TValue> static void OutputParam(IOutputStream& s, const TValue& value) { - if constexpr (google::protobuf::is_proto_enum<TValue>::value) { - const google::protobuf::EnumDescriptor *e = google::protobuf::GetEnumDescriptor<TValue>(); + using Tx = std::decay_t<TValue>; + + if constexpr (google::protobuf::is_proto_enum<Tx>::value) { + const google::protobuf::EnumDescriptor *e = google::protobuf::GetEnumDescriptor<Tx>(); if (const auto *val = e->FindValueByNumber(value)) { s << val->name(); } else { s << static_cast<int>(value); } - } else if constexpr (std::is_same_v<TValue, bool>) { + } else if constexpr (std::is_same_v<Tx, bool>) { s << (value ? "true" : "false"); - } else if constexpr (std::is_base_of_v<google::protobuf::Message, TValue>) { + } else if constexpr (std::is_base_of_v<google::protobuf::Message, Tx>) { google::protobuf::TextFormat::Printer p; p.SetSingleLineMode(true); TString str; @@ -152,15 +152,15 @@ namespace NKikimr::NStLog { } else { s << "<error>"; } - } else if constexpr (THasToStringMethod<TValue>::value) { + } else if constexpr (THasToStringMethod<Tx>::value) { s << value.ToString(); - } else if constexpr (std::is_pointer_v<TValue> && !std::is_same_v<std::remove_cv_t<std::remove_pointer_t<TValue>>, char>) { + } else if constexpr (TOptionalTraits<Tx>::HasOptionalValue) { if (value) { OutputParam(s, *value); } else { s << "<null>"; } - } else if constexpr (TIsIterable<TValue>::value) { + } else if constexpr (TIsIterable<Tx>::value) { auto begin = std::begin(value); auto end = std::end(value); bool first = true; @@ -178,6 +178,35 @@ namespace NKikimr::NStLog { s << value; } } + + template<typename TValue> + static void OutputParam(NJson::TJsonWriter& json, const TValue& value) { + using Tx = std::decay_t<TValue>; + + if constexpr (std::is_base_of_v<google::protobuf::Message, Tx>) { + ProtobufToJson(value, json); + } else if constexpr (TOptionalTraits<Tx>::HasOptionalValue) { + if (value) { + OutputParam(json, *value); + } else { + json.WriteNull(); + } + } else if constexpr (TIsIterable<Tx>::value) { + json.OpenArray(); + auto begin = std::begin(value); + auto end = std::end(value); + for (; begin != end; ++begin) { + OutputParam(json, *begin); + } + json.CloseArray(); + } else if constexpr (std::is_constructible_v<NJson::TJsonValue, Tx>) { + json.Write(value); + } else { + TStringStream stream; + OutputParam(stream, value); + json.Write(stream.Str()); + } + } }; class TUnboundParam { @@ -196,6 +225,10 @@ namespace NKikimr::NStLog { void WriteToStream(IOutputStream& s) const { s << Name; } + + void WriteToJson(NJson::TJsonWriter& json) const { + json.WriteKey(Name); + } }; template<typename Tag, typename... TParams> @@ -203,53 +236,120 @@ namespace NKikimr::NStLog { const char *File; int Line; const char *Marker; - TString Text; std::tuple<TParams...> Params; static constexpr size_t NumParams = sizeof...(TParams); public: template<typename... TArgs> - TMessage(const char *file, int line, const char *marker, TString text, std::tuple<TParams...>&& params = {}) + TMessage(const char *file, int line, const char *marker, std::tuple<TParams...>&& params = {}) : File(file) , Line(line) , Marker(marker) - , Text(std::move(text)) , Params(std::move(params)) {} template<typename Base, typename T> TMessage<Tag, TParams..., TBoundParam<Base, T>> AppendBoundParam(TBoundParam<Base, T>&& p) { - return {File, Line, Marker, std::move(Text), std::tuple_cat(Params, std::make_tuple(std::move(p)))}; + return {File, Line, Marker, std::tuple_cat(Params, std::make_tuple(std::move(p)))}; } TMessage<Tag, TParams...> AppendBoundParam(const STLOG_PARAM_T&) { return std::move(*this); } - void WriteToStream(IOutputStream& s) const { - const char *p = strrchr(File, '/'); - p = p ? p + 1 : File; - s << "{" << Marker << "@" << p << ":" << Line << "} " << Text; - WriteParams<0>(s, nullptr); + struct TStreamWriter { + const TMessage *Self; + IOutputStream& Stream; + + template<typename T> + TStreamWriter& operator <<(const T& value) { + Stream << value; + return *this; + } + + TStreamWriter(const TMessage *self, IOutputStream& stream) + : Self(self) + , Stream(stream) + { + Self->WriteHeaderToStream(Stream); + } + + ~TStreamWriter() { + Self->WriteParamsToStream(Stream); + } + }; + + TStreamWriter WriteToStream(IOutputStream& s) const { + return {this, s}; + } + + struct TJsonWriter { + const TMessage *Self; + NJson::TJsonWriter& Json; + TStringStream Stream; + + template<typename T> + TJsonWriter& operator <<(const T& value) { + Stream << value; + return *this; + } + + TJsonWriter(const TMessage *self, NJson::TJsonWriter& json) + : Self(self) + , Json(json) + {} + + ~TJsonWriter() { + Json.OpenMap(); + Json.WriteKey("Marker"); + Json.Write(Self->Marker); + Json.WriteKey("File"); + Json.Write(Self->GetFileName()); + Json.WriteKey("Line"); + Json.Write(Self->Line); + Json.WriteKey("Text"); + Json.Write(Stream.Str()); + Self->WriteParamsToJson(Json); + Json.CloseMap(); + } + }; + + TJsonWriter WriteToJson(NJson::TJsonWriter& json) const { + return {this, json}; } private: - template<size_t Index> - void WriteParams(IOutputStream& s, std::enable_if_t<Index != NumParams>*) const { - s << " "; - std::get<Index>(Params).WriteToStream(s); - WriteParams<Index + 1>(s, nullptr); + const char *GetFileName() const { + const char *p = strrchr(File, '/'); + return p ? p + 1 : File; + } + + void WriteHeaderToStream(IOutputStream& s) const { + s << "{" << Marker << "@" << GetFileName() << ":" << Line << "} "; + } + + void WriteParamsToStream(IOutputStream& s) const { + WriteParams<0>(&s); + } + + void WriteParamsToJson(NJson::TJsonWriter& json) const { + WriteParams<0>(&json); + } + + template<size_t Index, typename = std::enable_if_t<Index != NumParams>> + void WriteParams(IOutputStream *s) const { + std::get<Index>(Params).WriteToStream(*s << " "); + WriteParams<Index + 1>(s); + } + + template<size_t Index, typename = std::enable_if_t<Index != NumParams>> + void WriteParams(NJson::TJsonWriter *json) const { + std::get<Index>(Params).WriteToJson(*json); + WriteParams<Index + 1>(json); } - // out-of-range handler template<size_t Index> - void WriteParams(IOutputStream&, ...) const {} + void WriteParams(...) const {} }; } - -template<typename Tag, typename... TParams> -IOutputStream& operator <<(IOutputStream& s, const NKikimr::NStLog::TMessage<Tag, TParams...>& message) { - message.WriteToStream(s); - return s; -} diff --git a/ydb/core/util/stlog_ut.cpp b/ydb/core/util/stlog_ut.cpp new file mode 100644 index 00000000000..be87e2116d7 --- /dev/null +++ b/ydb/core/util/stlog_ut.cpp @@ -0,0 +1,41 @@ +#include "stlog.h" +#include <ydb/core/base/logoblob.h> +#include <ydb/core/protos/base.pb.h> +#include <library/cpp/testing/unittest/registar.h> + +Y_UNIT_TEST_SUITE(StLog) { + + Y_UNIT_TEST(Basic) { + std::optional<int> x1(1); + std::optional<int> y1; + TMaybe<int> x2(2); + TMaybe<int> y2; + int z = 3; + const int *x3 = &z; + const int *y3 = nullptr; + std::vector<int> v{{1, 2, 3}}; + NKikimrProto::EReplyStatus status = NKikimrProto::RACE; + NKikimrProto::TLogoBlobID id; + LogoBlobIDFromLogoBlobID(NKikimr::TLogoBlobID(1, 2, 3, 4, 5, 6), &id); + struct { + TString ToString() const { return "yep"; } + } s; + STLOG_STREAM(stream, -1, MARKER1, "hello, world", (Param1, 1), (Param2, 'c'), (Param3, 1.1f), (Param4, "abcdef"), + (Param5, TString("abcdef")), (Param6, x1), (Param7, x2), (Param8, x3), (Param9, y1), + (Param10, y2), (Param11, y3), (Param12, true), (Param13, v), (Param14, status), (Param15, id), + (Param16, &s)); + UNIT_ASSERT_VALUES_EQUAL(stream.Str(), "{MARKER1@stlog_ut.cpp:26} hello, world Param1# 1 Param2# c Param3# 1.1 " + "Param4# abcdef Param5# abcdef Param6# 1 Param7# 2 Param8# 3 Param9# <null> Param10# <null> Param11# <null> " + "Param12# true Param13# [1 2 3] Param14# RACE Param15# {RawX1: 1 RawX2: 288230376185266176 " + "RawX3: 216172807883587664 } Param16# yep"); + STLOG_STREAM(stream2, 1, MARKER2, "hello, world", (Param1, 1), (Param2, 'c'), (Param3, 1.1f), (Param4, "abcdef"), + (Param5, TString("abcdef")), (Param6, x1), (Param7, x2), (Param8, x3), (Param9, y1), + (Param10, y2), (Param11, y3), (Param12, true), (Param13, v), (Param14, status), (Param15, id), + (Param16, &s)); + UNIT_ASSERT_VALUES_EQUAL(stream2.Str(), R"({"Marker":"MARKER2","File":"stlog_ut.cpp","Line":34,"Text":"hello, world",)" + R"("Param1":1,"Param2":99,"Param3":1.1,"Param4":"abcdef","Param5":"abcdef","Param6":1,"Param7":2,"Param8":3,)" + R"("Param9":null,"Param10":null,"Param11":null,"Param12":true,"Param13":[1,2,3],"Param14":4,"Param15":)" + R"({"RawX1":"1","RawX2":"288230376185266176","RawX3":"216172807883587664"},"Param16":"yep"})"); + } + +} diff --git a/ydb/core/util/ut/CMakeLists.darwin.txt b/ydb/core/util/ut/CMakeLists.darwin.txt index 34fa381ca0f..84db9577ec1 100644 --- a/ydb/core/util/ut/CMakeLists.darwin.txt +++ b/ydb/core/util/ut/CMakeLists.darwin.txt @@ -54,6 +54,7 @@ target_sources(ydb-core-util-ut PRIVATE ${CMAKE_SOURCE_DIR}/ydb/core/util/queue_inplace_ut.cpp ${CMAKE_SOURCE_DIR}/ydb/core/util/queue_oneone_inplace_ut.cpp ${CMAKE_SOURCE_DIR}/ydb/core/util/simple_cache_ut.cpp + ${CMAKE_SOURCE_DIR}/ydb/core/util/stlog_ut.cpp ${CMAKE_SOURCE_DIR}/ydb/core/util/time_series_vec_ut.cpp ${CMAKE_SOURCE_DIR}/ydb/core/util/token_bucket_ut.cpp ${CMAKE_SOURCE_DIR}/ydb/core/util/ulid_ut.cpp diff --git a/ydb/core/util/ut/CMakeLists.linux-aarch64.txt b/ydb/core/util/ut/CMakeLists.linux-aarch64.txt index 175d4481ee4..2aad5d4954f 100644 --- a/ydb/core/util/ut/CMakeLists.linux-aarch64.txt +++ b/ydb/core/util/ut/CMakeLists.linux-aarch64.txt @@ -56,6 +56,7 @@ target_sources(ydb-core-util-ut PRIVATE ${CMAKE_SOURCE_DIR}/ydb/core/util/queue_inplace_ut.cpp ${CMAKE_SOURCE_DIR}/ydb/core/util/queue_oneone_inplace_ut.cpp ${CMAKE_SOURCE_DIR}/ydb/core/util/simple_cache_ut.cpp + ${CMAKE_SOURCE_DIR}/ydb/core/util/stlog_ut.cpp ${CMAKE_SOURCE_DIR}/ydb/core/util/time_series_vec_ut.cpp ${CMAKE_SOURCE_DIR}/ydb/core/util/token_bucket_ut.cpp ${CMAKE_SOURCE_DIR}/ydb/core/util/ulid_ut.cpp diff --git a/ydb/core/util/ut/CMakeLists.linux.txt b/ydb/core/util/ut/CMakeLists.linux.txt index 8e78674cd88..a8d9aff7933 100644 --- a/ydb/core/util/ut/CMakeLists.linux.txt +++ b/ydb/core/util/ut/CMakeLists.linux.txt @@ -58,6 +58,7 @@ target_sources(ydb-core-util-ut PRIVATE ${CMAKE_SOURCE_DIR}/ydb/core/util/queue_inplace_ut.cpp ${CMAKE_SOURCE_DIR}/ydb/core/util/queue_oneone_inplace_ut.cpp ${CMAKE_SOURCE_DIR}/ydb/core/util/simple_cache_ut.cpp + ${CMAKE_SOURCE_DIR}/ydb/core/util/stlog_ut.cpp ${CMAKE_SOURCE_DIR}/ydb/core/util/time_series_vec_ut.cpp ${CMAKE_SOURCE_DIR}/ydb/core/util/token_bucket_ut.cpp ${CMAKE_SOURCE_DIR}/ydb/core/util/ulid_ut.cpp |