errors.cpp 11 KB

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