summaryrefslogtreecommitdiffstats
path: root/library/cpp/yt/error/error.cpp
diff options
context:
space:
mode:
authordeep <[email protected]>2025-02-28 14:48:56 +0300
committerdeep <[email protected]>2025-02-28 15:57:40 +0300
commit680ad352dc598780b4945d5420f8168c1665dad2 (patch)
tree77fc8d5c7a7b2e360e2df284b3ffeee91543e7f8 /library/cpp/yt/error/error.cpp
parentbcfc9f25bb1396e151cbbf21b625cda31b01ed08 (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.cpp32
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) &