errors.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435
  1. #include "errors.h"
  2. #include <library/cpp/yson/node/node_io.h>
  3. #include <library/cpp/yson/node/node_visitor.h>
  4. #include <yt/cpp/mapreduce/interface/error_codes.h>
  5. #include <library/cpp/json/json_reader.h>
  6. #include <library/cpp/yson/writer.h>
  7. #include <util/string/builder.h>
  8. #include <util/stream/str.h>
  9. #include <util/generic/set.h>
  10. namespace NYT {
  11. using namespace NJson;
  12. ////////////////////////////////////////////////////////////////////////////////
  13. static void WriteErrorDescription(const TYtError& error, IOutputStream* out)
  14. {
  15. (*out) << error.GetMessage();
  16. const auto& innerErrorList = error.InnerErrors();
  17. if (!innerErrorList.empty()) {
  18. (*out) << ": ";
  19. WriteErrorDescription(innerErrorList[0], out);
  20. }
  21. }
  22. static void SerializeError(const TYtError& error, NYson::IYsonConsumer* consumer)
  23. {
  24. consumer->OnBeginMap();
  25. {
  26. consumer->OnKeyedItem("code");
  27. consumer->OnInt64Scalar(error.GetCode());
  28. consumer->OnKeyedItem("message");
  29. consumer->OnStringScalar(error.GetMessage());
  30. if (!error.GetAttributes().empty()) {
  31. consumer->OnKeyedItem("attributes");
  32. consumer->OnBeginMap();
  33. {
  34. for (const auto& item : error.GetAttributes()) {
  35. consumer->OnKeyedItem(item.first);
  36. TNodeVisitor(consumer).Visit(item.second);
  37. }
  38. }
  39. consumer->OnEndMap();
  40. }
  41. if (!error.InnerErrors().empty()) {
  42. consumer->OnKeyedItem("inner_errors");
  43. {
  44. consumer->OnBeginList();
  45. for (const auto& innerError : error.InnerErrors()) {
  46. SerializeError(innerError, consumer);
  47. }
  48. consumer->OnEndList();
  49. }
  50. }
  51. }
  52. consumer->OnEndMap();
  53. }
  54. static TString DumpJobInfoForException(const TOperationId& operationId, const TVector<TFailedJobInfo>& failedJobInfoList)
  55. {
  56. ::TStringBuilder output;
  57. // Exceptions have limit to contain 65508 bytes of text, so we also limit stderr text
  58. constexpr size_t MAX_SIZE = 65508 / 2;
  59. size_t written = 0;
  60. for (const auto& failedJobInfo : failedJobInfoList) {
  61. if (written >= MAX_SIZE) {
  62. break;
  63. }
  64. TStringStream nextChunk;
  65. nextChunk << '\n';
  66. nextChunk << "OperationId: " << GetGuidAsString(operationId) << " JobId: " << GetGuidAsString(failedJobInfo.JobId) << '\n';
  67. nextChunk << "Error: " << failedJobInfo.Error.FullDescription() << '\n';
  68. if (!failedJobInfo.Stderr.empty()) {
  69. nextChunk << "Stderr: " << Endl;
  70. size_t tmpWritten = written + nextChunk.Str().size();
  71. if (tmpWritten >= MAX_SIZE) {
  72. break;
  73. }
  74. if (tmpWritten + failedJobInfo.Stderr.size() > MAX_SIZE) {
  75. nextChunk << failedJobInfo.Stderr.substr(failedJobInfo.Stderr.size() - (MAX_SIZE - tmpWritten));
  76. } else {
  77. nextChunk << failedJobInfo.Stderr;
  78. }
  79. }
  80. written += nextChunk.Str().size();
  81. output << nextChunk.Str();
  82. }
  83. return output;
  84. }
  85. ////////////////////////////////////////////////////////////////////////////////
  86. TYtError::TYtError()
  87. : Code_(0)
  88. { }
  89. TYtError::TYtError(const TString& message)
  90. : Code_(NYT::NClusterErrorCodes::Generic)
  91. , Message_(message)
  92. { }
  93. TYtError::TYtError(int code, TString message, TVector<TYtError> innerError, TNode::TMapType attributes)
  94. : Code_(code)
  95. , Message_(message)
  96. , InnerErrors_(innerError)
  97. , Attributes_(attributes)
  98. { }
  99. TYtError::TYtError(const TJsonValue& value)
  100. {
  101. const TJsonValue::TMapType& map = value.GetMap();
  102. TJsonValue::TMapType::const_iterator it = map.find("message");
  103. if (it != map.end()) {
  104. Message_ = it->second.GetString();
  105. }
  106. it = map.find("code");
  107. if (it != map.end()) {
  108. Code_ = static_cast<int>(it->second.GetInteger());
  109. } else {
  110. Code_ = NYT::NClusterErrorCodes::Generic;
  111. }
  112. it = map.find("inner_errors");
  113. if (it != map.end()) {
  114. const TJsonValue::TArray& innerErrors = it->second.GetArray();
  115. for (const auto& innerError : innerErrors) {
  116. InnerErrors_.push_back(TYtError(innerError));
  117. }
  118. }
  119. it = map.find("attributes");
  120. if (it != map.end()) {
  121. auto attributes = NYT::NodeFromJsonValue(it->second);
  122. if (attributes.IsMap()) {
  123. Attributes_ = std::move(attributes.AsMap());
  124. }
  125. }
  126. }
  127. TYtError::TYtError(const TNode& node)
  128. {
  129. const auto& map = node.AsMap();
  130. auto it = map.find("message");
  131. if (it != map.end()) {
  132. Message_ = it->second.AsString();
  133. }
  134. it = map.find("code");
  135. if (it != map.end()) {
  136. Code_ = static_cast<int>(it->second.AsInt64());
  137. } else {
  138. Code_ = NYT::NClusterErrorCodes::Generic;
  139. }
  140. it = map.find("inner_errors");
  141. if (it != map.end()) {
  142. const auto& innerErrors = it->second.AsList();
  143. for (const auto& innerError : innerErrors) {
  144. InnerErrors_.push_back(TYtError(innerError));
  145. }
  146. }
  147. it = map.find("attributes");
  148. if (it != map.end()) {
  149. auto& attributes = it->second;
  150. if (attributes.IsMap()) {
  151. Attributes_ = std::move(attributes.AsMap());
  152. }
  153. }
  154. }
  155. int TYtError::GetCode() const
  156. {
  157. return Code_;
  158. }
  159. const TString& TYtError::GetMessage() const
  160. {
  161. return Message_;
  162. }
  163. const TVector<TYtError>& TYtError::InnerErrors() const
  164. {
  165. return InnerErrors_;
  166. }
  167. void TYtError::ParseFrom(const TString& jsonError)
  168. {
  169. TJsonValue value;
  170. TStringInput input(jsonError);
  171. ReadJsonTree(&input, &value);
  172. *this = TYtError(value);
  173. }
  174. TSet<int> TYtError::GetAllErrorCodes() const
  175. {
  176. TDeque<const TYtError*> queue = {this};
  177. TSet<int> result;
  178. while (!queue.empty()) {
  179. const auto* current = queue.front();
  180. queue.pop_front();
  181. result.insert(current->Code_);
  182. for (const auto& error : current->InnerErrors_) {
  183. queue.push_back(&error);
  184. }
  185. }
  186. return result;
  187. }
  188. bool TYtError::ContainsErrorCode(int code) const
  189. {
  190. if (Code_ == code) {
  191. return true;
  192. }
  193. for (const auto& error : InnerErrors_) {
  194. if (error.ContainsErrorCode(code)) {
  195. return true;
  196. }
  197. }
  198. return false;
  199. }
  200. bool TYtError::ContainsText(const TStringBuf& text) const
  201. {
  202. if (Message_.Contains(text)) {
  203. return true;
  204. }
  205. for (const auto& error : InnerErrors_) {
  206. if (error.ContainsText(text)) {
  207. return true;
  208. }
  209. }
  210. return false;
  211. }
  212. bool TYtError::HasAttributes() const
  213. {
  214. return !Attributes_.empty();
  215. }
  216. const TNode::TMapType& TYtError::GetAttributes() const
  217. {
  218. return Attributes_;
  219. }
  220. TString TYtError::GetYsonText() const
  221. {
  222. TStringStream out;
  223. ::NYson::TYsonWriter writer(&out, NYson::EYsonFormat::Text);
  224. SerializeError(*this, &writer);
  225. return std::move(out.Str());
  226. }
  227. TString TYtError::ShortDescription() const
  228. {
  229. TStringStream out;
  230. WriteErrorDescription(*this, &out);
  231. return std::move(out.Str());
  232. }
  233. TString TYtError::FullDescription() const
  234. {
  235. TStringStream s;
  236. WriteErrorDescription(*this, &s);
  237. s << "; full error: " << GetYsonText();
  238. return s.Str();
  239. }
  240. ////////////////////////////////////////////////////////////////////////////////
  241. TErrorResponse::TErrorResponse(int httpCode, const TString& requestId)
  242. : HttpCode_(httpCode)
  243. , RequestId_(requestId)
  244. { }
  245. bool TErrorResponse::IsOk() const
  246. {
  247. return Error_.GetCode() == 0;
  248. }
  249. void TErrorResponse::SetRawError(const TString& message)
  250. {
  251. Error_ = TYtError(message);
  252. Setup();
  253. }
  254. void TErrorResponse::SetError(TYtError error)
  255. {
  256. Error_ = std::move(error);
  257. Setup();
  258. }
  259. void TErrorResponse::ParseFromJsonError(const TString& jsonError)
  260. {
  261. Error_.ParseFrom(jsonError);
  262. Setup();
  263. }
  264. void TErrorResponse::SetIsFromTrailers(bool isFromTrailers)
  265. {
  266. IsFromTrailers_ = isFromTrailers;
  267. }
  268. int TErrorResponse::GetHttpCode() const
  269. {
  270. return HttpCode_;
  271. }
  272. bool TErrorResponse::IsFromTrailers() const
  273. {
  274. return IsFromTrailers_;
  275. }
  276. bool TErrorResponse::IsTransportError() const
  277. {
  278. return HttpCode_ == 503;
  279. }
  280. TString TErrorResponse::GetRequestId() const
  281. {
  282. return RequestId_;
  283. }
  284. const TYtError& TErrorResponse::GetError() const
  285. {
  286. return Error_;
  287. }
  288. bool TErrorResponse::IsResolveError() const
  289. {
  290. return Error_.ContainsErrorCode(NClusterErrorCodes::NYTree::ResolveError);
  291. }
  292. bool TErrorResponse::IsAccessDenied() const
  293. {
  294. return Error_.ContainsErrorCode(NClusterErrorCodes::NSecurityClient::AuthorizationError);
  295. }
  296. bool TErrorResponse::IsConcurrentTransactionLockConflict() const
  297. {
  298. return Error_.ContainsErrorCode(NClusterErrorCodes::NCypressClient::ConcurrentTransactionLockConflict);
  299. }
  300. bool TErrorResponse::IsRequestRateLimitExceeded() const
  301. {
  302. return Error_.ContainsErrorCode(NClusterErrorCodes::NSecurityClient::RequestQueueSizeLimitExceeded);
  303. }
  304. bool TErrorResponse::IsRequestQueueSizeLimitExceeded() const
  305. {
  306. return Error_.ContainsErrorCode(NClusterErrorCodes::NRpc::RequestQueueSizeLimitExceeded);
  307. }
  308. bool TErrorResponse::IsChunkUnavailable() const
  309. {
  310. return Error_.ContainsErrorCode(NClusterErrorCodes::NChunkClient::ChunkUnavailable);
  311. }
  312. bool TErrorResponse::IsRequestTimedOut() const
  313. {
  314. return Error_.ContainsErrorCode(NClusterErrorCodes::Timeout);
  315. }
  316. bool TErrorResponse::IsNoSuchTransaction() const
  317. {
  318. return Error_.ContainsErrorCode(NClusterErrorCodes::NTransactionClient::NoSuchTransaction);
  319. }
  320. bool TErrorResponse::IsConcurrentOperationsLimitReached() const
  321. {
  322. return Error_.ContainsErrorCode(NClusterErrorCodes::NScheduler::TooManyOperations);
  323. }
  324. void TErrorResponse::Setup()
  325. {
  326. TStringStream s;
  327. *this << Error_.FullDescription();
  328. }
  329. TTransportError::TTransportError(TYtError error)
  330. {
  331. *this << error.FullDescription();
  332. }
  333. ////////////////////////////////////////////////////////////////////////////////
  334. TOperationFailedError::TOperationFailedError(
  335. EState state,
  336. TOperationId id,
  337. TYtError ytError,
  338. TVector<TFailedJobInfo> failedJobInfo)
  339. : State_(state)
  340. , OperationId_(id)
  341. , Error_(std::move(ytError))
  342. , FailedJobInfo_(std::move(failedJobInfo))
  343. {
  344. *this << Error_.FullDescription();
  345. if (!FailedJobInfo_.empty()) {
  346. *this << DumpJobInfoForException(OperationId_, FailedJobInfo_);
  347. }
  348. }
  349. TOperationFailedError::EState TOperationFailedError::GetState() const
  350. {
  351. return State_;
  352. }
  353. TOperationId TOperationFailedError::GetOperationId() const
  354. {
  355. return OperationId_;
  356. }
  357. const TYtError& TOperationFailedError::GetError() const
  358. {
  359. return Error_;
  360. }
  361. const TVector<TFailedJobInfo>& TOperationFailedError::GetFailedJobInfo() const
  362. {
  363. return FailedJobInfo_;
  364. }
  365. } // namespace NYT