aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp
diff options
context:
space:
mode:
authordeep <deep@yandex-team.com>2025-02-28 14:48:56 +0300
committerdeep <deep@yandex-team.com>2025-02-28 15:57:40 +0300
commit680ad352dc598780b4945d5420f8168c1665dad2 (patch)
tree77fc8d5c7a7b2e360e2df284b3ffeee91543e7f8 /library/cpp
parentbcfc9f25bb1396e151cbbf21b625cda31b01ed08 (diff)
downloadydb-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.cpp32
-rw-r--r--library/cpp/yt/error/error.h10
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_;
};
////////////////////////////////////////////////////////////////////////////////