diff options
| author | deep <[email protected]> | 2025-02-28 14:48:56 +0300 |
|---|---|---|
| committer | deep <[email protected]> | 2025-02-28 15:57:40 +0300 |
| commit | 680ad352dc598780b4945d5420f8168c1665dad2 (patch) | |
| tree | 77fc8d5c7a7b2e360e2df284b3ffeee91543e7f8 /library/cpp/yt/error/error.cpp | |
| parent | bcfc9f25bb1396e151cbbf21b625cda31b01ed08 (diff) | |
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/yt/error/error.cpp')
| -rw-r--r-- | library/cpp/yt/error/error.cpp | 32 |
1 files changed, 30 insertions, 2 deletions
diff --git a/library/cpp/yt/error/error.cpp b/library/cpp/yt/error/error.cpp index 636d7d81fc4..f097697cd6a 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) & |
