diff options
author | deep <deep@yandex-team.com> | 2025-02-28 14:48:56 +0300 |
---|---|---|
committer | deep <deep@yandex-team.com> | 2025-02-28 15:57:40 +0300 |
commit | 680ad352dc598780b4945d5420f8168c1665dad2 (patch) | |
tree | 77fc8d5c7a7b2e360e2df284b3ffeee91543e7f8 /library/cpp | |
parent | bcfc9f25bb1396e151cbbf21b625cda31b01ed08 (diff) | |
download | ydb-680ad352dc598780b4945d5420f8168c1665dad2.tar.gz |
YTORM-1292 Error enrichment via dependency injection
Идея такая: хочу подкладывать атрибуты в ошибки, не протаскивая их через стек (как в orm/server/objects) и не прогоняя все ошибки через специальные методы (как в orm/library/attributes). Для этого завожу fiber-local структурку с ленивым выведением строчек. Поскольку TError и TFls живут в разных мирах, пришлось сделать отдельный трамплин для совсем генеричной доработки ошибок в момент создания.
Игнат посоветовал глянуть на Codicil. Там очень похоже, но нет key/value, поэтому похитил только название. Вообще, можно унифицировать, если есть запрос.
commit_hash:203ec7abe5e8c8484e66d55f16192485db776806
Diffstat (limited to 'library/cpp')
-rw-r--r-- | library/cpp/yt/error/error.cpp | 32 | ||||
-rw-r--r-- | library/cpp/yt/error/error.h | 10 |
2 files changed, 40 insertions, 2 deletions
diff --git a/library/cpp/yt/error/error.cpp b/library/cpp/yt/error/error.cpp index 636d7d81fc..f097697cd6 100644 --- a/library/cpp/yt/error/error.cpp +++ b/library/cpp/yt/error/error.cpp @@ -29,6 +29,8 @@ void FormatValue(TStringBuilderBase* builder, TErrorCode code, TStringBuf spec) constexpr TStringBuf ErrorMessageTruncatedSuffix = "...<message truncated>"; +TError::TEnricher TError::Enricher_; + //////////////////////////////////////////////////////////////////////////////// class TError::TImpl @@ -275,15 +277,20 @@ TError::TErrorOr(const std::exception& ex) *this = TError(NYT::EErrorCode::Generic, TRuntimeFormat{ex.what()}); } YT_VERIFY(!IsOK()); + Enrich(); } TError::TErrorOr(std::string message, TDisableFormat) : Impl_(std::make_unique<TImpl>(std::move(message))) -{ } +{ + Enrich(); +} TError::TErrorOr(TErrorCode code, std::string message, TDisableFormat) : Impl_(std::make_unique<TImpl>(code, std::move(message))) -{ } +{ + Enrich(); +} TError& TError::operator = (const TError& other) { @@ -632,6 +639,20 @@ std::optional<TError> TError::FindMatching(const THashSet<TErrorCode>& codes) co }); } +void TError::RegisterEnricher(TEnricher enricher) +{ + // NB: This daisy-chaining strategy is optimal when there's O(1) callbacks. Convert to a vector + // if the number grows. + if (Enricher_) { + Enricher_ = [first = std::move(Enricher_), second = std::move(enricher)] (TError& error) { + first(error); + second(error); + }; + } else { + Enricher_ = std::move(enricher); + } +} + TError::TErrorOr(std::unique_ptr<TImpl> impl) : Impl_(std::move(impl)) { } @@ -643,6 +664,13 @@ void TError::MakeMutable() } } +void TError::Enrich() +{ + if (Enricher_) { + Enricher_(*this); + } +} + //////////////////////////////////////////////////////////////////////////////// TError& TError::operator <<= (const TErrorAttribute& attribute) & diff --git a/library/cpp/yt/error/error.h b/library/cpp/yt/error/error.h index 8b459d0beb..92f19bc398 100644 --- a/library/cpp/yt/error/error.h +++ b/library/cpp/yt/error/error.h @@ -219,6 +219,13 @@ public: template <CErrorNestable TValue> TError operator << (const std::optional<TValue>& rhs) const &; + // The |enricher| is called during TError construction and before TErrorOr<> construction. Meant + // to enrich the error, e.g. by setting generic attributes. The |RegisterEnricher| method is not + // threadsafe and is meant to be called from single-threaded bootstrapping code. Multiple + // enrichers are supported and will be called in order of registration. + using TEnricher = std::function<void(TError&)>; + static void RegisterEnricher(TEnricher enricher); + private: class TImpl; std::unique_ptr<TImpl> Impl_; @@ -226,8 +233,11 @@ private: explicit TErrorOr(std::unique_ptr<TImpl> impl); void MakeMutable(); + void Enrich(); friend class TErrorAttributes; + + static TEnricher Enricher_; }; //////////////////////////////////////////////////////////////////////////////// |