Skip to content

Commit e63af7f

Browse files
committed
fix: reduce code complexity
1 parent 4269ccd commit e63af7f

1 file changed

Lines changed: 108 additions & 44 deletions

File tree

gax-java/gax/src/main/java/com/google/api/gax/tracing/ObservabilityUtils.java

Lines changed: 108 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,12 @@
3131

3232
import com.google.api.gax.rpc.ApiException;
3333
import com.google.api.gax.rpc.StatusCode;
34+
import com.google.common.base.Strings;
3435
import io.opentelemetry.api.common.Attributes;
3536
import io.opentelemetry.api.common.AttributesBuilder;
37+
import java.util.Arrays;
38+
import java.util.Collections;
39+
import java.util.List;
3640
import java.util.Map;
3741
import java.util.concurrent.CancellationException;
3842
import javax.annotation.Nullable;
@@ -56,6 +60,38 @@ public String toString() {
5660
}
5761
}
5862

63+
private static final List<Class<? extends Throwable>> CLIENT_TIMEOUT_CLASSES =
64+
Arrays.asList(
65+
java.util.concurrent.TimeoutException.class, java.net.SocketTimeoutException.class);
66+
private static final List<String> CLIENT_TIMEOUT_NAMES =
67+
Collections.singletonList("WatchdogTimeoutException");
68+
69+
private static final List<Class<? extends Throwable>> CLIENT_CONNECTION_ERROR_CLASSES =
70+
Arrays.asList(
71+
java.net.ConnectException.class,
72+
java.net.UnknownHostException.class,
73+
java.nio.channels.UnresolvedAddressException.class);
74+
private static final List<String> CLIENT_CONNECTION_ERROR_NAMES =
75+
Collections.singletonList("ConnectException");
76+
77+
private static final List<String> CLIENT_AUTH_ERROR_SUBSTRINGS =
78+
Arrays.asList("CredentialsException", "AuthenticationException");
79+
80+
private static final List<String> CLIENT_RESPONSE_DECODE_ERROR_SUBSTRINGS =
81+
Arrays.asList("ProtocolBufferParsingException", "DecodeException");
82+
83+
private static final List<String> CLIENT_REDIRECT_ERROR_SUBSTRINGS =
84+
Collections.singletonList("RedirectException");
85+
86+
private static final List<String> CLIENT_REQUEST_BODY_ERROR_SUBSTRINGS =
87+
Collections.singletonList("RequestBodyException");
88+
89+
private static final List<String> CLIENT_REQUEST_ERROR_SUBSTRINGS =
90+
Collections.singletonList("RequestException");
91+
92+
private static final List<String> CLIENT_UNKNOWN_ERROR_SUBSTRINGS =
93+
Collections.singletonList("UnknownClientException");
94+
5995
/**
6096
* Extracts a low-cardinality string representing the specific classification of the error to be
6197
* used in the {@link ObservabilityAttributes#ERROR_TYPE_ATTRIBUTE} attribute.
@@ -107,76 +143,104 @@ static String extractErrorType(@Nullable Throwable error) {
107143
}
108144

109145
if (error instanceof ApiException) {
110-
ApiException apiException = (ApiException) error;
111-
112-
// 1. Check for ErrorInfo.reason
113-
String reason = apiException.getReason();
114-
if (reason != null && !reason.isEmpty()) {
115-
return reason;
146+
String errorType = extractFromApiException((ApiException) error);
147+
if (errorType != null) {
148+
return errorType;
116149
}
150+
}
117151

118-
// 2. Specific Server Error Code
119-
if (apiException.getStatusCode() != null) {
120-
Object transportCode = apiException.getStatusCode().getTransportCode();
121-
if (transportCode instanceof Integer) {
122-
// HTTP Status Code
123-
return String.valueOf(transportCode);
124-
} else if (apiException.getStatusCode().getCode() != null) {
125-
// gRPC Status Code name
126-
return apiException.getStatusCode().getCode().name();
127-
}
128-
}
152+
String clientError = getClientSideError(error);
153+
if (clientError != null) {
154+
return clientError;
129155
}
130156

131-
// 3. Client-Side Network/Operational Errors
157+
// 4. Language-specific error type fallback
132158
String exceptionName = error.getClass().getSimpleName();
159+
if (exceptionName != null && !exceptionName.isEmpty()) {
160+
return exceptionName;
161+
}
133162

134-
if (error instanceof java.util.concurrent.TimeoutException
135-
|| error instanceof java.net.SocketTimeoutException
136-
|| exceptionName.equals("WatchdogTimeoutException")) {
137-
return ErrorType.CLIENT_TIMEOUT.toString();
163+
// 5. Internal Fallback
164+
return ErrorType.INTERNAL.toString();
165+
}
166+
167+
@Nullable
168+
private static String extractFromApiException(ApiException apiException) {
169+
// 1. Check for ErrorInfo.reason
170+
String reason = apiException.getReason();
171+
if (!Strings.isNullOrEmpty(reason)) {
172+
return reason;
173+
}
174+
175+
// 2. Specific Server Error Code
176+
if (apiException.getStatusCode() != null) {
177+
Object transportCode = apiException.getStatusCode().getTransportCode();
178+
if (transportCode instanceof Integer) {
179+
// HTTP Status Code
180+
return String.valueOf(transportCode);
181+
} else if (apiException.getStatusCode().getCode() != null) {
182+
// gRPC Status Code name
183+
return apiException.getStatusCode().getCode().name();
184+
}
138185
}
186+
return null;
187+
}
139188

140-
if (error instanceof java.net.ConnectException
141-
|| error instanceof java.net.UnknownHostException
142-
|| error instanceof java.nio.channels.UnresolvedAddressException
143-
|| exceptionName.equals("ConnectException")) {
189+
@Nullable
190+
private static String getClientSideError(Throwable error) {
191+
if (isInstanceof(error, CLIENT_TIMEOUT_CLASSES)) {
192+
return ErrorType.CLIENT_TIMEOUT.toString();
193+
}
194+
if (isInstanceof(error, CLIENT_CONNECTION_ERROR_CLASSES)) {
144195
return ErrorType.CLIENT_CONNECTION_ERROR.toString();
145196
}
146197

147-
if (exceptionName.contains("CredentialsException")
148-
|| exceptionName.contains("AuthenticationException")) {
198+
String exceptionName = error.getClass().getSimpleName();
199+
200+
if (CLIENT_TIMEOUT_NAMES.contains(exceptionName)) {
201+
return ErrorType.CLIENT_TIMEOUT.toString();
202+
}
203+
if (CLIENT_CONNECTION_ERROR_NAMES.contains(exceptionName)) {
204+
return ErrorType.CLIENT_CONNECTION_ERROR.toString();
205+
}
206+
if (nameContains(exceptionName, CLIENT_AUTH_ERROR_SUBSTRINGS)) {
149207
return ErrorType.CLIENT_AUTHENTICATION_ERROR.toString();
150208
}
151-
152-
if (exceptionName.contains("ProtocolBufferParsingException")
153-
|| exceptionName.contains("DecodeException")) {
209+
if (nameContains(exceptionName, CLIENT_RESPONSE_DECODE_ERROR_SUBSTRINGS)) {
154210
return ErrorType.CLIENT_RESPONSE_DECODE_ERROR.toString();
155211
}
156-
157-
if (exceptionName.contains("RedirectException")) {
212+
if (nameContains(exceptionName, CLIENT_REDIRECT_ERROR_SUBSTRINGS)) {
158213
return ErrorType.CLIENT_REDIRECT_ERROR.toString();
159214
}
160-
161-
if (exceptionName.contains("RequestBodyException")) {
215+
if (nameContains(exceptionName, CLIENT_REQUEST_BODY_ERROR_SUBSTRINGS)) {
162216
return ErrorType.CLIENT_REQUEST_BODY_ERROR.toString();
163217
}
164-
165-
if (exceptionName.contains("RequestException")) {
218+
if (nameContains(exceptionName, CLIENT_REQUEST_ERROR_SUBSTRINGS)) {
166219
return ErrorType.CLIENT_REQUEST_ERROR.toString();
167220
}
168-
169-
if (exceptionName.contains("UnknownClientException")) {
221+
if (nameContains(exceptionName, CLIENT_UNKNOWN_ERROR_SUBSTRINGS)) {
170222
return ErrorType.CLIENT_UNKNOWN_ERROR.toString();
171223
}
172224

173-
// 4. Language-specific error type fallback
174-
if (exceptionName != null && !exceptionName.isEmpty()) {
175-
return exceptionName;
225+
return null;
226+
}
227+
228+
private static boolean isInstanceof(Throwable error, List<Class<? extends Throwable>> classes) {
229+
for (Class<? extends Throwable> clazz : classes) {
230+
if (clazz.isInstance(error)) {
231+
return true;
232+
}
176233
}
234+
return false;
235+
}
177236

178-
// 5. Internal Fallback
179-
return ErrorType.INTERNAL.toString();
237+
private static boolean nameContains(String name, List<String> substrings) {
238+
for (String sub : substrings) {
239+
if (name.contains(sub)) {
240+
return true;
241+
}
242+
}
243+
return false;
180244
}
181245

182246
/** Function to extract the status of the error as a string */

0 commit comments

Comments
 (0)