3030package com .google .api .gax .tracing ;
3131
3232import com .google .api .gax .rpc .ApiException ;
33- import com .google .api .gax .rpc .WatchdogTimeoutException ;
3433import com .google .common .base .Strings ;
35- import java .net .ConnectException ;
36- import java .net .SocketTimeoutException ;
37- import java .net .UnknownHostException ;
38- import java .nio .channels .UnresolvedAddressException ;
34+ import com .google .common .collect .ImmutableSet ;
35+ import java .util .Set ;
3936import javax .annotation .Nullable ;
40- import javax .net .ssl .SSLHandshakeException ;
4137
4238public class ErrorTypeUtil {
4339
@@ -58,6 +54,26 @@ public String toString() {
5854 }
5955 }
6056
57+ private static final Set <String > JSON_DECODING_EXCEPTION_CLASS_NAMES =
58+ ImmutableSet .of (
59+ "com.google.gson.JsonSyntaxException" ,
60+ "com.google.gson.JsonParseException" ,
61+ "com.fasterxml.jackson.databind.JsonMappingException" ,
62+ "com.fasterxml.jackson.core.JsonParseException" );
63+
64+ private static final Set <String > AUTHENTICATION_EXCEPTION_CLASS_NAMES =
65+ ImmutableSet .of ("com.google.auth.oauth2.GoogleAuthException" );
66+
67+ private static final Set <String > CLIENT_TIMEOUT_EXCEPTION_CLASS_NAMES =
68+ ImmutableSet .of (
69+ "java.net.SocketTimeoutException" , "com.google.api.gax.rpc.WatchdogTimeoutException" );
70+ private static final Set <String > CLIENT_CONNECTION_EXCEPTIONS =
71+ ImmutableSet .of (
72+ "java.net.ConnectException" ,
73+ "java.net.UnknownHostException" ,
74+ "javax.net.ssl.SSLHandshakeException" ,
75+ "java.nio.channels.UnresolvedAddressException" );
76+
6177 /**
6278 * Extracts a low-cardinality string representing the specific classification of the error to be
6379 * used in the {@link ObservabilityAttributes#ERROR_TYPE_ATTRIBUTE} attribute.
@@ -206,7 +222,7 @@ private static String getClientSideError(Throwable error) {
206222 * @return true if the error is a client timeout, false otherwise.
207223 */
208224 private static boolean isClientTimeout (Throwable e ) {
209- return e instanceof SocketTimeoutException || e instanceof WatchdogTimeoutException ;
225+ return hasErrorNameInCauseChain ( e , CLIENT_TIMEOUT_EXCEPTION_CLASS_NAMES ) ;
210226 }
211227
212228 /**
@@ -217,10 +233,7 @@ private static boolean isClientTimeout(Throwable e) {
217233 * @return true if the error is a client connection error, false otherwise.
218234 */
219235 private static boolean isClientConnectionError (Throwable e ) {
220- return e instanceof ConnectException
221- || e instanceof UnknownHostException
222- || e instanceof SSLHandshakeException
223- || e instanceof UnresolvedAddressException ;
236+ return hasErrorNameInCauseChain (e , CLIENT_CONNECTION_EXCEPTIONS );
224237 }
225238
226239 /**
@@ -231,9 +244,7 @@ private static boolean isClientConnectionError(Throwable e) {
231244 * @return true if the error is a client response decode error, false otherwise.
232245 */
233246 private static boolean isClientResponseDecodeError (Throwable e ) {
234- return e .getClass ().getName ().contains ("Json" )
235- || e .getClass ().getName ().contains ("Gson" )
236- || (e .getCause () != null && e .getCause ().getClass ().getName ().contains ("Gson" ));
247+ return hasErrorNameInCauseChain (e , JSON_DECODING_EXCEPTION_CLASS_NAMES );
237248 }
238249
239250 /**
@@ -255,7 +266,7 @@ private static boolean isClientRedirectError(Throwable e) {
255266 * @return true if the error is a client authentication error, false otherwise.
256267 */
257268 private static boolean isClientAuthenticationError (Throwable e ) {
258- return e . getClass (). getName (). contains ( "GoogleAuthException" );
269+ return hasErrorNameInCauseChain ( e , AUTHENTICATION_EXCEPTION_CLASS_NAMES );
259270 }
260271
261272 /**
@@ -267,7 +278,7 @@ private static boolean isClientAuthenticationError(Throwable e) {
267278 * @return true if the error is a client request body error, false otherwise.
268279 */
269280 private static boolean isRequestBodyError (Throwable e ) {
270- return e . getClass (). getName (). contains ( "RestSerializationException" );
281+ return hasErrorNameInCauseChain ( e , ImmutableSet . of ( "RestSerializationException" ) );
271282 }
272283
273284 /**
@@ -281,4 +292,22 @@ private static boolean isRequestBodyError(Throwable e) {
281292 private static boolean isClientUnknownError (Throwable e ) {
282293 return e .getClass ().getName ().toLowerCase ().contains ("unknown" );
283294 }
295+
296+ /**
297+ * Recursively checks the throwable and its cause chain for any of the specified error name.
298+ *
299+ * @param t The Throwable to check.
300+ * @param errorClassNames A set of fully qualified class names to check against.
301+ * @return true if an error from the set is found in the cause chain, false otherwise.
302+ */
303+ private static boolean hasErrorNameInCauseChain (Throwable t , Set <String > errorClassNames ) {
304+ Throwable current = t ;
305+ while (current != null ) {
306+ if (errorClassNames .contains (current .getClass ().getName ())) {
307+ return true ;
308+ }
309+ current = current .getCause ();
310+ }
311+ return false ;
312+ }
284313}
0 commit comments