diff --git a/core-api/src/main/java/com/optimizely/ab/odp/parser/impl/GsonParser.java b/core-api/src/main/java/com/optimizely/ab/odp/parser/impl/GsonParser.java index b27d65078..70136536f 100644 --- a/core-api/src/main/java/com/optimizely/ab/odp/parser/impl/GsonParser.java +++ b/core-api/src/main/java/com/optimizely/ab/odp/parser/impl/GsonParser.java @@ -1,5 +1,5 @@ /** - * Copyright 2022, Optimizely Inc. and contributors + * Copyright 2022-2023, Optimizely Inc. and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -34,15 +34,16 @@ public List parseQualifiedSegments(String responseJson) { JsonObject root = JsonParser.parseString(responseJson).getAsJsonObject(); if (root.has("errors")) { - JsonArray errors = root.getAsJsonArray("errors"); - StringBuilder logMessage = new StringBuilder(); - for (int i = 0; i < errors.size(); i++) { - if (i > 0) { - logMessage.append(", "); + JsonArray errors = root.getAsJsonArray("errors"); + JsonObject extensions = errors.get(0).getAsJsonObject().get("extensions").getAsJsonObject(); + if (extensions != null) { + if (extensions.has("code") && extensions.get("code").getAsString().equals("INVALID_IDENTIFIER_EXCEPTION")) { + logger.warn("Audience segments fetch failed (invalid identifier)"); + } else { + String errorMessage = extensions.get("classification") == null ? "decode error" : extensions.get("classification").getAsString(); + logger.error("Audience segments fetch failed (" + errorMessage + ")"); } - logMessage.append(errors.get(i).getAsJsonObject().get("message").getAsString()); } - logger.error(logMessage.toString()); return null; } diff --git a/core-api/src/main/java/com/optimizely/ab/odp/parser/impl/JacksonParser.java b/core-api/src/main/java/com/optimizely/ab/odp/parser/impl/JacksonParser.java index f1a38eca7..b9a2b668f 100644 --- a/core-api/src/main/java/com/optimizely/ab/odp/parser/impl/JacksonParser.java +++ b/core-api/src/main/java/com/optimizely/ab/odp/parser/impl/JacksonParser.java @@ -1,5 +1,5 @@ /** - * Copyright 2022, Optimizely Inc. and contributors + * Copyright 2022-2023, Optimizely Inc. and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -39,14 +39,15 @@ public List parseQualifiedSegments(String responseJson) { if (root.has("errors")) { JsonNode errors = root.path("errors"); - StringBuilder logMessage = new StringBuilder(); - for (int i = 0; i < errors.size(); i++) { - if (i > 0) { - logMessage.append(", "); + JsonNode extensions = errors.get(0).path("extensions"); + if (extensions != null) { + if (extensions.has("code") && extensions.path("code").asText().equals("INVALID_IDENTIFIER_EXCEPTION")) { + logger.warn("Audience segments fetch failed (invalid identifier)"); + } else { + String errorMessage = extensions.has("classification") ? extensions.path("classification").asText() : "decode error"; + logger.error("Audience segments fetch failed (" + errorMessage + ")"); } - logMessage.append(errors.get(i).path("message")); } - logger.error(logMessage.toString()); return null; } diff --git a/core-api/src/main/java/com/optimizely/ab/odp/parser/impl/JsonParser.java b/core-api/src/main/java/com/optimizely/ab/odp/parser/impl/JsonParser.java index fcae748a4..e0e23c366 100644 --- a/core-api/src/main/java/com/optimizely/ab/odp/parser/impl/JsonParser.java +++ b/core-api/src/main/java/com/optimizely/ab/odp/parser/impl/JsonParser.java @@ -1,5 +1,5 @@ /** - * Copyright 2022, Optimizely Inc. and contributors + * Copyright 2022-2023, Optimizely Inc. and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -35,15 +35,17 @@ public List parseQualifiedSegments(String responseJson) { JSONObject root = new JSONObject(responseJson); if (root.has("errors")) { - JSONArray errors = root.getJSONArray("errors"); - StringBuilder logMessage = new StringBuilder(); - for (int i = 0; i < errors.length(); i++) { - if (i > 0) { - logMessage.append(", "); + JSONArray errors = root.getJSONArray("errors"); + JSONObject extensions = errors.getJSONObject(0).getJSONObject("extensions"); + if (extensions != null) { + if (extensions.has("code") && extensions.getString("code").equals("INVALID_IDENTIFIER_EXCEPTION")) { + logger.warn("Audience segments fetch failed (invalid identifier)"); + } else { + String errorMessage = extensions.has("classification") ? + extensions.getString("classification") : "decode error"; + logger.error("Audience segments fetch failed (" + errorMessage + ")"); } - logMessage.append(errors.getJSONObject(i).getString("message")); } - logger.error(logMessage.toString()); return null; } diff --git a/core-api/src/main/java/com/optimizely/ab/odp/parser/impl/JsonSimpleParser.java b/core-api/src/main/java/com/optimizely/ab/odp/parser/impl/JsonSimpleParser.java index 1bee81b0a..de444e3c2 100644 --- a/core-api/src/main/java/com/optimizely/ab/odp/parser/impl/JsonSimpleParser.java +++ b/core-api/src/main/java/com/optimizely/ab/odp/parser/impl/JsonSimpleParser.java @@ -1,5 +1,5 @@ /** - * Copyright 2022, Optimizely Inc. and contributors + * Copyright 2022-2023, Optimizely Inc. and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -36,17 +36,17 @@ public List parseQualifiedSegments(String responseJson) { JSONObject root = null; try { root = (JSONObject) parser.parse(responseJson); - if (root.containsKey("errors")) { JSONArray errors = (JSONArray) root.get("errors"); - StringBuilder logMessage = new StringBuilder(); - for (int i = 0; i < errors.size(); i++) { - if (i > 0) { - logMessage.append(", "); + JSONObject extensions = (JSONObject) ((JSONObject) errors.get(0)).get("extensions"); + if (extensions != null) { + if (extensions.containsKey("code") && extensions.get("code").equals("INVALID_IDENTIFIER_EXCEPTION")) { + logger.warn("Audience segments fetch failed (invalid identifier)"); + } else { + String errorMessage = extensions.get("classification") == null ? "decode error" : (String) extensions.get("classification"); + logger.error("Audience segments fetch failed (" + errorMessage + ")"); } - logMessage.append((String)((JSONObject) errors.get(i)).get("message")); } - logger.error(logMessage.toString()); return null; } diff --git a/core-api/src/test/java/com/optimizely/ab/odp/parser/ResponseJsonParserTest.java b/core-api/src/test/java/com/optimizely/ab/odp/parser/ResponseJsonParserTest.java index 1acd5cf15..454ab1718 100644 --- a/core-api/src/test/java/com/optimizely/ab/odp/parser/ResponseJsonParserTest.java +++ b/core-api/src/test/java/com/optimizely/ab/odp/parser/ResponseJsonParserTest.java @@ -1,5 +1,5 @@ /** - * Copyright 2022, Optimizely Inc. and contributors + * Copyright 2022-2023, Optimizely Inc. and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -84,9 +84,34 @@ public void returnNullWhenJsonIsMalformed() { @Test public void returnNullAndLogCorrectErrorWhenErrorResponseIsReturned() { - String responseToParse = "{\"errors\":[{\"message\":\"Exception while fetching data (/customer) : java.lang.RuntimeException: could not resolve _fs_user_id = wrong_id\",\"locations\":[{\"line\":2,\"column\":3}],\"path\":[\"customer\"],\"extensions\":{\"classification\":\"InvalidIdentifierException\"}}],\"data\":{\"customer\":null}}"; + String responseToParse = "{\"errors\":[{\"message\":\"Exception while fetching data (/customer) : java.lang.RuntimeException: could not resolve _fs_user_id = wrong_id\",\"locations\":[{\"line\":2,\"column\":3}],\"path\":[\"customer\"],\"extensions\":{\"code\":\"INVALID_IDENTIFIER_EXCEPTION\", \"classification\":\"DataFetchingException\"}}],\"data\":{\"customer\":null}}"; List parsedSegments = jsonParser.parseQualifiedSegments(responseToParse); - logbackVerifier.expectMessage(Level.ERROR, "Exception while fetching data (/customer) : java.lang.RuntimeException: could not resolve _fs_user_id = wrong_id"); + logbackVerifier.expectMessage(Level.WARN, "Audience segments fetch failed (invalid identifier)"); assertEquals(null, parsedSegments); } + + @Test + public void returnNullAndLogNoErrorWhenErrorResponseIsReturnedButCodeKeyIsNotPresent() { + String responseToParse = "{\"errors\":[{\"message\":\"Exception while fetching data (/customer) : java.lang.RuntimeException: could not resolve _fs_user_id = wrong_id\",\"locations\":[{\"line\":2,\"column\":3}],\"path\":[\"customer\"],\"extensions\":{\"classification\":\"DataFetchingException\"}}],\"data\":{\"customer\":null}}"; + List parsedSegments = jsonParser.parseQualifiedSegments(responseToParse); + logbackVerifier.expectMessage(Level.ERROR, "Audience segments fetch failed (DataFetchingException)"); + assertEquals(null, parsedSegments); + } + + @Test + public void returnNullAndLogCorrectErrorWhenErrorResponseIsReturnedButCodeValueIsNotInvalidIdentifierException() { + String responseToParse = "{\"errors\":[{\"message\":\"Exception while fetching data (/customer) : java.lang.RuntimeException: could not resolve _fs_user_id = wrong_id\",\"locations\":[{\"line\":2,\"column\":3}],\"path\":[\"customer\"],\"extensions\":{\"code\":\"OTHER_EXCEPTIONS\", \"classification\":\"DataFetchingException\"}}],\"data\":{\"customer\":null}}"; + List parsedSegments = jsonParser.parseQualifiedSegments(responseToParse); + logbackVerifier.expectMessage(Level.ERROR, "Audience segments fetch failed (DataFetchingException)"); + assertEquals(null, parsedSegments); + } + + @Test + public void returnNullAndLogCorrectErrorWhenErrorResponseIsReturnedButCodeValueIsNotInvalidIdentifierExceptionNullClassification() { + String responseToParse = "{\"errors\":[{\"message\":\"Exception while fetching data (/customer) : java.lang.RuntimeException: could not resolve _fs_user_id = wrong_id\",\"locations\":[{\"line\":2,\"column\":3}],\"path\":[\"customer\"],\"extensions\":{\"code\":\"OTHER_EXCEPTIONS\"}}],\"data\":{\"customer\":null}}"; + List parsedSegments = jsonParser.parseQualifiedSegments(responseToParse); + logbackVerifier.expectMessage(Level.ERROR, "Audience segments fetch failed (decode error)"); + assertEquals(null, parsedSegments); + } + } diff --git a/core-httpclient-impl/src/main/java/com/optimizely/ab/odp/DefaultODPApiManager.java b/core-httpclient-impl/src/main/java/com/optimizely/ab/odp/DefaultODPApiManager.java index 040709d39..3a7ae3291 100644 --- a/core-httpclient-impl/src/main/java/com/optimizely/ab/odp/DefaultODPApiManager.java +++ b/core-httpclient-impl/src/main/java/com/optimizely/ab/odp/DefaultODPApiManager.java @@ -137,7 +137,8 @@ String getSegmentsStringForRequest(Set segmentsList) { "customer" ], "extensions": { - "classification": "InvalidIdentifierException" + "code": "INVALID_IDENTIFIER_EXCEPTION", + "classification": "DataFetchingException" } } ],