|
19 | 19 |
|
20 | 20 | import com.google.api.client.googleapis.json.GoogleJsonResponseException; |
21 | 21 | import com.google.api.client.http.HttpResponseException; |
| 22 | +import com.google.api.gax.rpc.ApiException; |
22 | 23 | import com.google.common.base.Strings; |
23 | 24 | import com.google.common.base.Throwables; |
24 | 25 | import io.cdap.cdap.api.exception.ErrorCategory; |
@@ -69,21 +70,49 @@ public static ProgramFailureException getProgramFailureException(HttpResponseExc |
69 | 70 | ErrorCodeType.HTTP, statusCode.toString(), externalDocumentationLink, e); |
70 | 71 | } |
71 | 72 |
|
| 73 | + /** |
| 74 | + * Get a ProgramFailureException with the given error |
| 75 | + * information from {@link ApiException}. |
| 76 | + * |
| 77 | + * @param e The ApiException to get the error information from. |
| 78 | + * @return A ProgramFailureException with the given error information. |
| 79 | + */ |
| 80 | + public static ProgramFailureException getProgramFailureException(ApiException e, String externalDocUrl, |
| 81 | + @Nullable ErrorContext errorContext) { |
| 82 | + Integer statusCode = e.getStatusCode().getCode().getHttpStatusCode(); |
| 83 | + ErrorUtils.ActionErrorPair pair = ErrorUtils.getActionErrorByStatusCode(statusCode); |
| 84 | + String errorReason = String.format("%s %s. %s. For more details, see %s", statusCode, e.getMessage(), |
| 85 | + pair.getCorrectiveAction(), externalDocUrl); |
| 86 | + String errorMessage = e.getMessage(); |
| 87 | + return ErrorUtils.getProgramFailureException(new ErrorCategory(ErrorCategory.ErrorCategoryEnum.PLUGIN), errorReason, |
| 88 | + errorContext != null ? |
| 89 | + String.format(GCPErrorDetailsProvider.ERROR_MESSAGE_FORMAT, errorContext.getPhase(), e.getClass().getName(), |
| 90 | + errorMessage) : String.format("%s: %s", e.getClass().getName(), errorMessage), pair.getErrorType(), true, |
| 91 | + ErrorCodeType.HTTP, statusCode.toString(), externalDocUrl, e); |
| 92 | + } |
| 93 | + |
72 | 94 | public static ProgramFailureException getHttpResponseExceptionDetailsFromChain(Throwable e, String errorReason, |
73 | 95 | ErrorType errorType, |
74 | 96 | boolean dependency, |
75 | 97 | String externalDocUrl) { |
76 | 98 | List<Throwable> causalChain = Throwables.getCausalChain(e); |
| 99 | + // Check for ProgramFailureException (avoid unnecessary re-wrapping) |
77 | 100 | for (Throwable t : causalChain) { |
78 | 101 | if (t instanceof ProgramFailureException) { |
79 | | - // Avoid double wrap |
80 | 102 | return (ProgramFailureException) t; |
81 | 103 | } |
| 104 | + } |
| 105 | + // Reverse iterate to prioritize HttpResponseException over ApiException |
| 106 | + for (int i = causalChain.size() - 1; i >= 0; i--) { |
| 107 | + Throwable t = causalChain.get(i); |
82 | 108 | if (t instanceof HttpResponseException) { |
83 | 109 | return getProgramFailureException((HttpResponseException) t, externalDocUrl, null); |
84 | 110 | } |
| 111 | + if (t instanceof ApiException) { |
| 112 | + return getProgramFailureException((ApiException) t, externalDocUrl, null); |
| 113 | + } |
85 | 114 | } |
86 | | - // If no HttpResponseException found in the causal chain, return generic program failure exception |
| 115 | + // If no HttpResponseException or ApiException found in the causal chain, return generic program failure exception |
87 | 116 | return ErrorUtils.getProgramFailureException(new ErrorCategory(ErrorCategory.ErrorCategoryEnum.PLUGIN), errorReason, |
88 | 117 | String.format("%s %s: %s", errorReason, e.getClass().getName(), e.getMessage()), errorType, dependency, e); |
89 | 118 | } |
|
0 commit comments