fork download
  1. #include <iostream>
  2. #include <string>
  3. #include <sstream>
  4. #include <array>
  5. #include <algorithm>
  6. #include <string>
  7. #include <cstdlib>
  8. #include <cctype>
  9. #include <vector>
  10. using namespace std;
  11.  
  12. std::string NormalizeError(std::string err_msg) {
  13. // ------------------------------------------------------------------------
  14. // log with header, {} indicates optional
  15. //-------------------------------------------------------------------------
  16. // [timestamp] file_name:line_number: {check_msg:} {error_type:} {message0}
  17. // {message1}
  18. // Stack trace:
  19. // {stack trace 0}
  20. // {stack trace 1}
  21. //-------------------------------------------------------------------------
  22. // Normalzied version
  23. //-------------------------------------------------------------------------
  24. // error_type: check_msg message0
  25. // {message1}
  26. // Stack trace:
  27. // File file_name, line lineno
  28. // {stack trace 0}
  29. // {stack trace 1}
  30. //-------------------------------------------------------------------------
  31. int line_number = 0;
  32. std::istringstream is(err_msg);
  33. std::string line, file_name, error_type, check_msg;
  34.  
  35. // Parse log header and set the fields,
  36. // Return true if it the log is in correct format,
  37. // return false if something is wrong.
  38. auto parse_log_header = [&]() {
  39. // skip timestamp
  40. if (is.peek() != '[') {
  41. getline(is, line);
  42. return true;
  43. }
  44. if (!(is >> line)) return false;
  45. // get filename
  46. while (is.peek() == ' ') is.get();
  47. if (!getline(is, file_name, ':')) return false;
  48. // get line number
  49. if (!(is >> line_number)) return false;
  50. // get rest of the message.
  51. while (is.peek() == ' ' || is.peek() == ':') is.get();
  52. if (!getline(is, line)) return false;
  53. // detect check message, rewrite to remote extra :
  54. if (line.compare(0, 13, "Check failed:") == 0) {
  55. size_t end_pos = line.find(':', 13);
  56. if (end_pos == std::string::npos) return false;
  57. check_msg = line.substr(0, end_pos + 1) + ' ';
  58. line = line.substr(end_pos + 1);
  59. }
  60. return true;
  61. };
  62. // if not in correct format, do not do any rewrite.
  63. if (!parse_log_header()) return err_msg;
  64. // Parse error type.
  65. {
  66. size_t start_pos = 0, end_pos;
  67. for (; start_pos < line.length() && line[start_pos] == ' '; ++start_pos) {}
  68. for (end_pos = start_pos; end_pos < line.length(); ++end_pos) {
  69. char ch = line[end_pos];
  70. if (ch == ':') {
  71. error_type = line.substr(start_pos, end_pos - start_pos);
  72. break;
  73. }
  74. // [A-Z0-9a-z_.]
  75. if (!std::isalpha(ch) && !std::isdigit(ch) && ch != '_' && ch != '.') break;
  76. }
  77. if (error_type.length() != 0) {
  78. // if we successfully detected error_type: trim the following space.
  79. for (start_pos = end_pos + 1;
  80. start_pos < line.length() && line[start_pos] == ' '; ++start_pos) {}
  81. line = line.substr(start_pos);
  82. } else {
  83. // did not detect error_type, use default value.
  84. line = line.substr(start_pos);
  85. error_type = "TVMError";
  86. }
  87. }
  88. // Seperate out stack trace.
  89. std::ostringstream os;
  90. os << error_type << ": " << check_msg << line << '\n';
  91.  
  92. bool trace_mode = true;
  93. std::vector<std::string> stack_trace;
  94. while (getline(is, line)) {
  95. if (trace_mode) {
  96. if (line.compare(0, 2, " ") == 0) {
  97. stack_trace.push_back(line);
  98. } else {
  99. trace_mode = false;
  100. // remove EOL trailing stacktrace.
  101. if (line.length() == 0) continue;
  102. }
  103. }
  104. if (!trace_mode) {
  105. if (line.compare(0, 11, "Stack trace") == 0) {
  106. trace_mode = true;
  107. } else {
  108. os << line << '\n';
  109. }
  110. }
  111. }
  112. if (stack_trace.size() != 0 || file_name.length() != 0) {
  113. os << "Stack trace:\n";
  114. if (file_name.length() != 0) {
  115. os << " File \"" << file_name << "\", line " << line_number << "\n";
  116. }
  117. // Print out stack traces, optionally trim the c++ traces
  118. // about the frontends (as they will be provided by the frontends).
  119. bool ffi_boundary = false;
  120. for (const auto& line : stack_trace) {
  121. // Heuristic to detect python ffi.
  122. if (line.find("libffi.so") != std::string::npos ||
  123. line.find("core.cpython") != std::string::npos) {
  124. ffi_boundary = true;
  125. }
  126. // If the backtrace is not c++ backtrace with the prefix " [bt]",
  127. // then we can stop trimming.
  128. if (ffi_boundary && line.compare(0, 6, " [bt]") != 0) {
  129. ffi_boundary = false;
  130. }
  131. if (!ffi_boundary) {
  132. os << line << '\n';
  133. }
  134. // The line after TVMFuncCall cound be in FFI.
  135. if (line.find("(TVMFuncCall") != std::string::npos) {
  136. ffi_boundary = true;
  137. }
  138. }
  139. }
  140. return os.str();
  141. }
  142.  
  143. int main() {
  144. cout << NormalizeError("[23:21:56] C:srctvm-winsrcnodereflection.cc:109: AttributeError: Schedule object has no attributed code_hash");
  145. return 0;
  146. }
Success #stdin #stdout 0s 4460KB
stdin
Standard input is empty
stdout
[23:21:56] C:srctvm-winsrcnodereflection.cc:109: AttributeError: Schedule object has no attributed code_hash