123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437 |
- #include "errors.h"
- #include <library/cpp/yson/node/node_io.h>
- #include <library/cpp/yson/node/node_visitor.h>
- #include <yt/cpp/mapreduce/interface/error_codes.h>
- #include <library/cpp/json/json_reader.h>
- #include <library/cpp/yson/writer.h>
- #include <util/string/builder.h>
- #include <util/stream/str.h>
- #include <util/generic/set.h>
- namespace NYT {
- using namespace NJson;
- ////////////////////////////////////////////////////////////////////
- static void WriteErrorDescription(const TYtError& error, IOutputStream* out)
- {
- (*out) << '\'' << error.GetMessage() << '\'';
- const auto& innerErrorList = error.InnerErrors();
- if (!innerErrorList.empty()) {
- (*out) << " { ";
- bool first = true;
- for (const auto& innerError : innerErrorList) {
- if (first) {
- first = false;
- } else {
- (*out) << " ; ";
- }
- WriteErrorDescription(innerError, out);
- }
- (*out) << " }";
- }
- }
- static void SerializeError(const TYtError& error, NYson::IYsonConsumer* consumer)
- {
- consumer->OnBeginMap();
- {
- consumer->OnKeyedItem("code");
- consumer->OnInt64Scalar(error.GetCode());
- consumer->OnKeyedItem("message");
- consumer->OnStringScalar(error.GetMessage());
- if (!error.GetAttributes().empty()) {
- consumer->OnKeyedItem("attributes");
- consumer->OnBeginMap();
- {
- for (const auto& item : error.GetAttributes()) {
- consumer->OnKeyedItem(item.first);
- TNodeVisitor(consumer).Visit(item.second);
- }
- }
- consumer->OnEndMap();
- }
- if (!error.InnerErrors().empty()) {
- consumer->OnKeyedItem("inner_errors");
- {
- consumer->OnBeginList();
- for (const auto& innerError : error.InnerErrors()) {
- SerializeError(innerError, consumer);
- }
- consumer->OnEndList();
- }
- }
- }
- consumer->OnEndMap();
- }
- static TString DumpJobInfoForException(const TOperationId& operationId, const TVector<TFailedJobInfo>& failedJobInfoList)
- {
- ::TStringBuilder output;
- // Exceptions have limit to contain 65508 bytes of text, so we also limit stderr text
- constexpr size_t MAX_SIZE = 65508 / 2;
- size_t written = 0;
- for (const auto& failedJobInfo : failedJobInfoList) {
- if (written >= MAX_SIZE) {
- break;
- }
- TStringStream nextChunk;
- nextChunk << '\n';
- nextChunk << "OperationId: " << GetGuidAsString(operationId) << " JobId: " << GetGuidAsString(failedJobInfo.JobId) << '\n';
- nextChunk << "Error: " << failedJobInfo.Error.FullDescription() << '\n';
- if (!failedJobInfo.Stderr.empty()) {
- nextChunk << "Stderr: " << Endl;
- size_t tmpWritten = written + nextChunk.Str().size();
- if (tmpWritten >= MAX_SIZE) {
- break;
- }
- if (tmpWritten + failedJobInfo.Stderr.size() > MAX_SIZE) {
- nextChunk << failedJobInfo.Stderr.substr(failedJobInfo.Stderr.size() - (MAX_SIZE - tmpWritten));
- } else {
- nextChunk << failedJobInfo.Stderr;
- }
- }
- written += nextChunk.Str().size();
- output << nextChunk.Str();
- }
- return output;
- }
- ////////////////////////////////////////////////////////////////////
- TYtError::TYtError()
- : Code_(0)
- { }
- TYtError::TYtError(const TString& message)
- : Code_(NYT::NClusterErrorCodes::Generic)
- , Message_(message)
- { }
- TYtError::TYtError(int code, const TString& message)
- : Code_(code)
- , Message_(message)
- { }
- TYtError::TYtError(const TJsonValue& value)
- {
- const TJsonValue::TMapType& map = value.GetMap();
- TJsonValue::TMapType::const_iterator it = map.find("message");
- if (it != map.end()) {
- Message_ = it->second.GetString();
- }
- it = map.find("code");
- if (it != map.end()) {
- Code_ = static_cast<int>(it->second.GetInteger());
- } else {
- Code_ = NYT::NClusterErrorCodes::Generic;
- }
- it = map.find("inner_errors");
- if (it != map.end()) {
- const TJsonValue::TArray& innerErrors = it->second.GetArray();
- for (const auto& innerError : innerErrors) {
- InnerErrors_.push_back(TYtError(innerError));
- }
- }
- it = map.find("attributes");
- if (it != map.end()) {
- auto attributes = NYT::NodeFromJsonValue(it->second);
- if (attributes.IsMap()) {
- Attributes_ = std::move(attributes.AsMap());
- }
- }
- }
- TYtError::TYtError(const TNode& node)
- {
- const auto& map = node.AsMap();
- auto it = map.find("message");
- if (it != map.end()) {
- Message_ = it->second.AsString();
- }
- it = map.find("code");
- if (it != map.end()) {
- Code_ = static_cast<int>(it->second.AsInt64());
- } else {
- Code_ = NYT::NClusterErrorCodes::Generic;
- }
- it = map.find("inner_errors");
- if (it != map.end()) {
- const auto& innerErrors = it->second.AsList();
- for (const auto& innerError : innerErrors) {
- InnerErrors_.push_back(TYtError(innerError));
- }
- }
- it = map.find("attributes");
- if (it != map.end()) {
- auto& attributes = it->second;
- if (attributes.IsMap()) {
- Attributes_ = std::move(attributes.AsMap());
- }
- }
- }
- int TYtError::GetCode() const
- {
- return Code_;
- }
- const TString& TYtError::GetMessage() const
- {
- return Message_;
- }
- const TVector<TYtError>& TYtError::InnerErrors() const
- {
- return InnerErrors_;
- }
- void TYtError::ParseFrom(const TString& jsonError)
- {
- TJsonValue value;
- TStringInput input(jsonError);
- ReadJsonTree(&input, &value);
- *this = TYtError(value);
- }
- TSet<int> TYtError::GetAllErrorCodes() const
- {
- TDeque<const TYtError*> queue = {this};
- TSet<int> result;
- while (!queue.empty()) {
- const auto* current = queue.front();
- queue.pop_front();
- result.insert(current->Code_);
- for (const auto& error : current->InnerErrors_) {
- queue.push_back(&error);
- }
- }
- return result;
- }
- bool TYtError::ContainsErrorCode(int code) const
- {
- if (Code_ == code) {
- return true;
- }
- for (const auto& error : InnerErrors_) {
- if (error.ContainsErrorCode(code)) {
- return true;
- }
- }
- return false;
- }
- bool TYtError::ContainsText(const TStringBuf& text) const
- {
- if (Message_.Contains(text)) {
- return true;
- }
- for (const auto& error : InnerErrors_) {
- if (error.ContainsText(text)) {
- return true;
- }
- }
- return false;
- }
- bool TYtError::HasAttributes() const
- {
- return !Attributes_.empty();
- }
- const TNode::TMapType& TYtError::GetAttributes() const
- {
- return Attributes_;
- }
- TString TYtError::GetYsonText() const
- {
- TStringStream out;
- ::NYson::TYsonWriter writer(&out, NYson::EYsonFormat::Text);
- SerializeError(*this, &writer);
- return std::move(out.Str());
- }
- TString TYtError::ShortDescription() const
- {
- TStringStream out;
- WriteErrorDescription(*this, &out);
- return std::move(out.Str());
- }
- TString TYtError::FullDescription() const
- {
- TStringStream s;
- WriteErrorDescription(*this, &s);
- s << "; full error: " << GetYsonText();
- return s.Str();
- }
- ////////////////////////////////////////////////////////////////////////////////
- TErrorResponse::TErrorResponse(int httpCode, const TString& requestId)
- : HttpCode_(httpCode)
- , RequestId_(requestId)
- { }
- bool TErrorResponse::IsOk() const
- {
- return Error_.GetCode() == 0;
- }
- void TErrorResponse::SetRawError(const TString& message)
- {
- Error_ = TYtError(message);
- Setup();
- }
- void TErrorResponse::SetError(TYtError error)
- {
- Error_ = std::move(error);
- Setup();
- }
- void TErrorResponse::ParseFromJsonError(const TString& jsonError)
- {
- Error_.ParseFrom(jsonError);
- Setup();
- }
- void TErrorResponse::SetIsFromTrailers(bool isFromTrailers)
- {
- IsFromTrailers_ = isFromTrailers;
- }
- int TErrorResponse::GetHttpCode() const
- {
- return HttpCode_;
- }
- bool TErrorResponse::IsFromTrailers() const
- {
- return IsFromTrailers_;
- }
- bool TErrorResponse::IsTransportError() const
- {
- return HttpCode_ == 503;
- }
- TString TErrorResponse::GetRequestId() const
- {
- return RequestId_;
- }
- const TYtError& TErrorResponse::GetError() const
- {
- return Error_;
- }
- bool TErrorResponse::IsResolveError() const
- {
- return Error_.ContainsErrorCode(NClusterErrorCodes::NYTree::ResolveError);
- }
- bool TErrorResponse::IsAccessDenied() const
- {
- return Error_.ContainsErrorCode(NClusterErrorCodes::NSecurityClient::AuthorizationError);
- }
- bool TErrorResponse::IsConcurrentTransactionLockConflict() const
- {
- return Error_.ContainsErrorCode(NClusterErrorCodes::NCypressClient::ConcurrentTransactionLockConflict);
- }
- bool TErrorResponse::IsRequestRateLimitExceeded() const
- {
- return Error_.ContainsErrorCode(NClusterErrorCodes::NSecurityClient::RequestQueueSizeLimitExceeded);
- }
- bool TErrorResponse::IsRequestQueueSizeLimitExceeded() const
- {
- return Error_.ContainsErrorCode(NClusterErrorCodes::NRpc::RequestQueueSizeLimitExceeded);
- }
- bool TErrorResponse::IsChunkUnavailable() const
- {
- return Error_.ContainsErrorCode(NClusterErrorCodes::NChunkClient::ChunkUnavailable);
- }
- bool TErrorResponse::IsRequestTimedOut() const
- {
- return Error_.ContainsErrorCode(NClusterErrorCodes::Timeout);
- }
- bool TErrorResponse::IsNoSuchTransaction() const
- {
- return Error_.ContainsErrorCode(NClusterErrorCodes::NTransactionClient::NoSuchTransaction);
- }
- bool TErrorResponse::IsConcurrentOperationsLimitReached() const
- {
- return Error_.ContainsErrorCode(NClusterErrorCodes::NScheduler::TooManyOperations);
- }
- void TErrorResponse::Setup()
- {
- TStringStream s;
- *this << Error_.FullDescription();
- }
- ////////////////////////////////////////////////////////////////////
- TOperationFailedError::TOperationFailedError(
- EState state,
- TOperationId id,
- TYtError ytError,
- TVector<TFailedJobInfo> failedJobInfo)
- : State_(state)
- , OperationId_(id)
- , Error_(std::move(ytError))
- , FailedJobInfo_(std::move(failedJobInfo))
- {
- *this << Error_.FullDescription();
- if (!FailedJobInfo_.empty()) {
- *this << DumpJobInfoForException(OperationId_, FailedJobInfo_);
- }
- }
- TOperationFailedError::EState TOperationFailedError::GetState() const
- {
- return State_;
- }
- TOperationId TOperationFailedError::GetOperationId() const
- {
- return OperationId_;
- }
- const TYtError& TOperationFailedError::GetError() const
- {
- return Error_;
- }
- const TVector<TFailedJobInfo>& TOperationFailedError::GetFailedJobInfo() const
- {
- return FailedJobInfo_;
- }
- } // namespace NYT
|