From 64c2db41afc0b45998040936b792d5dda6de074a Mon Sep 17 00:00:00 2001 From: Girish Date: Wed, 21 Aug 2024 00:53:00 +0530 Subject: [PATCH 1/4] DTS-38567: Log Management | As a user I can access the data fetch errors --- .../advanced-settings.component.html | 6 +++ .../jira/listener/JobListenerKanban.java | 4 +- .../jira/listener/JobListenerScrum.java | 27 +++++----- .../jira/util/JiraProcessorUtil.java | 53 ++++++++++++++++++- 4 files changed, 73 insertions(+), 17 deletions(-) diff --git a/UI/src/app/config/advanced-settings/advanced-settings.component.html b/UI/src/app/config/advanced-settings/advanced-settings.component.html index 83f6e90c54..d8c821a473 100644 --- a/UI/src/app/config/advanced-settings/advanced-settings.component.html +++ b/UI/src/app/config/advanced-settings/advanced-settings.component.html @@ -70,6 +70,7 @@ Processor Name + Connection Name Last Executed On Status @@ -82,11 +83,16 @@ {{ processor.toolName === 'Azure' ? 'Azure Board' : processor.toolName }} + + {{ processor.connectionName }} + {{ showExecutionDate(processor.toolName) }} + + procExecTraceLogs = processorExecutionTraceLogRepo .findByProcessorNameAndBasicProjectConfigIdIn(JiraConstants.JIRA, Collections.singletonList(projectId)); if (CollectionUtils.isNotEmpty(procExecTraceLogs)) { for (ProcessorExecutionTraceLog processorExecutionTraceLog : procExecTraceLogs) { - checkDeltaIssues(processorExecutionTraceLog,status); + checkDeltaIssues(processorExecutionTraceLog, status); processorExecutionTraceLog.setExecutionEndedAt(System.currentTimeMillis()); processorExecutionTraceLog.setExecutionSuccess(status); if (stepFailureException != null && processorExecutionTraceLog.isProgressStats()) { - String failureMessage = "An error occurred. Please check logs."; - processorExecutionTraceLog.setErrorMessage(failureMessage); + processorExecutionTraceLog.setErrorMessage(generateLogMessage(stepFailureException)); processorExecutionTraceLog.setFailureLog(stepFailureException.getMessage()); } } diff --git a/processors/jira/src/main/java/com/publicissapient/kpidashboard/jira/util/JiraProcessorUtil.java b/processors/jira/src/main/java/com/publicissapient/kpidashboard/jira/util/JiraProcessorUtil.java index 9c1b62f3c7..b06e7b83d7 100644 --- a/processors/jira/src/main/java/com/publicissapient/kpidashboard/jira/util/JiraProcessorUtil.java +++ b/processors/jira/src/main/java/com/publicissapient/kpidashboard/jira/util/JiraProcessorUtil.java @@ -27,7 +27,10 @@ import java.util.ArrayList; import java.util.List; import java.util.Optional; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import com.publicissapient.kpidashboard.common.exceptions.ClientErrorMessageEnum; import org.apache.commons.lang3.StringUtils; import org.codehaus.jettison.json.JSONException; import org.joda.time.DateTime; @@ -53,7 +56,8 @@ @Slf4j public class JiraProcessorUtil { - private JiraProcessorUtil(){} + private JiraProcessorUtil() { + } // not static because not thread safe private static final String SPRINT_SPLIT = "(?=,\\w+=)"; @@ -68,6 +72,19 @@ private JiraProcessorUtil(){} private static final String ACTIVATEDDATE = "activatedDate"; private static final String GOAL = "goal"; private static final String BOARDID = "boardId"; + private static final Pattern EXCEPTION_WITH_MESSAGE_PATTERN = Pattern + .compile("^(\\w+(?:\\.\\w+)*Exception):\\s*(.+)$"); + + private static final Pattern EXCEPTION_WITH_STATUS_CODE_PATTERN = Pattern + .compile("(\\w+(?:\\.\\w+)*Exception)\\{[^}]*statusCode=Optional\\.of\\((\\d+)\\)"); + + private static final Pattern ERROR_COLLECTION_PATTERN = Pattern + .compile("\\[ErrorCollection\\{status=(\\d+), errors=\\{.*\\}, errorMessages=\\[.*\\]\\}\\]"); + + private static final Pattern ERROR_WITH_STATUS_CODE_PATTERN = Pattern.compile("Error:\\s*(\\d+)\\s*-\\s*(.*)"); + + private static final String UNAUTHORIZED = "Sorry, you are not authorized to access the requested resource."; + private static final String OTHER_CLIENT_ERRORS = "An unexpected error has occurred. Please contact the KnowHow Support for assistance."; /** * This method return UTF-8 decoded string response @@ -354,4 +371,38 @@ public static ProcessorExecutionTraceLog saveChunkProgressInTrace( return processorExecutionTraceLog; } + public static String generateLogMessage(Throwable exception) { + String exceptionMessage = exception.getMessage(); + + String logMessage = matchPattern(exceptionMessage, EXCEPTION_WITH_STATUS_CODE_PATTERN, true); + if (logMessage != null) + return logMessage; + + logMessage = matchPattern(exceptionMessage, EXCEPTION_WITH_MESSAGE_PATTERN, false); + if (logMessage != null) + return logMessage; + + logMessage = matchPattern(exceptionMessage, ERROR_COLLECTION_PATTERN, true); + if (logMessage != null) + return logMessage; + + logMessage = matchPattern(exceptionMessage, ERROR_WITH_STATUS_CODE_PATTERN, true); + if (logMessage != null) + return logMessage; + + return "No matching exception pattern found"; + } + + private static String matchPattern(String exceptionMessage, Pattern pattern, boolean hasStatusCode) { + Matcher matcher = pattern.matcher(exceptionMessage); + if (matcher.find()) { + if (hasStatusCode) { + int statusCode = Integer.parseInt(matcher.group(1)); + return (statusCode >= 400 && statusCode < 500) ? UNAUTHORIZED : OTHER_CLIENT_ERRORS; + } else { + return OTHER_CLIENT_ERRORS; + } + } + return null; + } } From 859c543781ee425abc9533d5be4626ceef54e90c Mon Sep 17 00:00:00 2001 From: Girish Date: Wed, 21 Aug 2024 00:53:00 +0530 Subject: [PATCH 2/4] DTS-38567: Log Management | As a user I can access the data fetch errors --- .../advanced-settings.component.html | 6 +++ .../jira/listener/JobListenerKanban.java | 24 ++++----- .../jira/listener/JobListenerScrum.java | 27 +++++----- .../jira/util/JiraProcessorUtil.java | 53 ++++++++++++++++++- 4 files changed, 83 insertions(+), 27 deletions(-) diff --git a/UI/src/app/config/advanced-settings/advanced-settings.component.html b/UI/src/app/config/advanced-settings/advanced-settings.component.html index 83f6e90c54..d8c821a473 100644 --- a/UI/src/app/config/advanced-settings/advanced-settings.component.html +++ b/UI/src/app/config/advanced-settings/advanced-settings.component.html @@ -70,6 +70,7 @@ Processor Name + Connection Name Last Executed On Status @@ -82,11 +83,16 @@ {{ processor.toolName === 'Azure' ? 'Azure Board' : processor.toolName }} + + {{ processor.connectionName }} + {{ showExecutionDate(processor.toolName) }} + + procExecTraceLogs = processorExecutionTraceLogRepo .findByProcessorNameAndBasicProjectConfigIdIn(JiraConstants.JIRA, Collections.singletonList(projectId)); if (CollectionUtils.isNotEmpty(procExecTraceLogs)) { for (ProcessorExecutionTraceLog processorExecutionTraceLog : procExecTraceLogs) { - checkDeltaIssues(processorExecutionTraceLog,status); + checkDeltaIssues(processorExecutionTraceLog, status); processorExecutionTraceLog.setExecutionEndedAt(System.currentTimeMillis()); processorExecutionTraceLog.setExecutionSuccess(status); if (stepFailureException != null && processorExecutionTraceLog.isProgressStats()) { - String failureMessage = "An error occurred. Please check logs."; - processorExecutionTraceLog.setErrorMessage(failureMessage); + processorExecutionTraceLog.setErrorMessage(generateLogMessage(stepFailureException)); processorExecutionTraceLog.setFailureLog(stepFailureException.getMessage()); } } diff --git a/processors/jira/src/main/java/com/publicissapient/kpidashboard/jira/util/JiraProcessorUtil.java b/processors/jira/src/main/java/com/publicissapient/kpidashboard/jira/util/JiraProcessorUtil.java index 9c1b62f3c7..b06e7b83d7 100644 --- a/processors/jira/src/main/java/com/publicissapient/kpidashboard/jira/util/JiraProcessorUtil.java +++ b/processors/jira/src/main/java/com/publicissapient/kpidashboard/jira/util/JiraProcessorUtil.java @@ -27,7 +27,10 @@ import java.util.ArrayList; import java.util.List; import java.util.Optional; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import com.publicissapient.kpidashboard.common.exceptions.ClientErrorMessageEnum; import org.apache.commons.lang3.StringUtils; import org.codehaus.jettison.json.JSONException; import org.joda.time.DateTime; @@ -53,7 +56,8 @@ @Slf4j public class JiraProcessorUtil { - private JiraProcessorUtil(){} + private JiraProcessorUtil() { + } // not static because not thread safe private static final String SPRINT_SPLIT = "(?=,\\w+=)"; @@ -68,6 +72,19 @@ private JiraProcessorUtil(){} private static final String ACTIVATEDDATE = "activatedDate"; private static final String GOAL = "goal"; private static final String BOARDID = "boardId"; + private static final Pattern EXCEPTION_WITH_MESSAGE_PATTERN = Pattern + .compile("^(\\w+(?:\\.\\w+)*Exception):\\s*(.+)$"); + + private static final Pattern EXCEPTION_WITH_STATUS_CODE_PATTERN = Pattern + .compile("(\\w+(?:\\.\\w+)*Exception)\\{[^}]*statusCode=Optional\\.of\\((\\d+)\\)"); + + private static final Pattern ERROR_COLLECTION_PATTERN = Pattern + .compile("\\[ErrorCollection\\{status=(\\d+), errors=\\{.*\\}, errorMessages=\\[.*\\]\\}\\]"); + + private static final Pattern ERROR_WITH_STATUS_CODE_PATTERN = Pattern.compile("Error:\\s*(\\d+)\\s*-\\s*(.*)"); + + private static final String UNAUTHORIZED = "Sorry, you are not authorized to access the requested resource."; + private static final String OTHER_CLIENT_ERRORS = "An unexpected error has occurred. Please contact the KnowHow Support for assistance."; /** * This method return UTF-8 decoded string response @@ -354,4 +371,38 @@ public static ProcessorExecutionTraceLog saveChunkProgressInTrace( return processorExecutionTraceLog; } + public static String generateLogMessage(Throwable exception) { + String exceptionMessage = exception.getMessage(); + + String logMessage = matchPattern(exceptionMessage, EXCEPTION_WITH_STATUS_CODE_PATTERN, true); + if (logMessage != null) + return logMessage; + + logMessage = matchPattern(exceptionMessage, EXCEPTION_WITH_MESSAGE_PATTERN, false); + if (logMessage != null) + return logMessage; + + logMessage = matchPattern(exceptionMessage, ERROR_COLLECTION_PATTERN, true); + if (logMessage != null) + return logMessage; + + logMessage = matchPattern(exceptionMessage, ERROR_WITH_STATUS_CODE_PATTERN, true); + if (logMessage != null) + return logMessage; + + return "No matching exception pattern found"; + } + + private static String matchPattern(String exceptionMessage, Pattern pattern, boolean hasStatusCode) { + Matcher matcher = pattern.matcher(exceptionMessage); + if (matcher.find()) { + if (hasStatusCode) { + int statusCode = Integer.parseInt(matcher.group(1)); + return (statusCode >= 400 && statusCode < 500) ? UNAUTHORIZED : OTHER_CLIENT_ERRORS; + } else { + return OTHER_CLIENT_ERRORS; + } + } + return null; + } } From bfc902a8a36912757a71e14e450fd52279be9dad Mon Sep 17 00:00:00 2001 From: Girish Date: Wed, 21 Aug 2024 11:14:58 +0530 Subject: [PATCH 3/4] DTS-38567:Addressed review comments --- .../jira/util/JiraProcessorUtilTest.java | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/processors/jira/src/test/java/com/publicissapient/kpidashboard/jira/util/JiraProcessorUtilTest.java b/processors/jira/src/test/java/com/publicissapient/kpidashboard/jira/util/JiraProcessorUtilTest.java index e26a17618f..0f350f75d0 100644 --- a/processors/jira/src/test/java/com/publicissapient/kpidashboard/jira/util/JiraProcessorUtilTest.java +++ b/processors/jira/src/test/java/com/publicissapient/kpidashboard/jira/util/JiraProcessorUtilTest.java @@ -234,4 +234,32 @@ public void testSaveChunkProgressInTrace_BothNotNull() { assertEquals("Process Issues 0 to 0 out of 0", progressStatusList.get(0).getStepName()); assertEquals(BatchStatus.COMPLETED.toString(), progressStatusList.get(0).getStatus()); } + @Test + public void testGenerateLogMessage_withExceptionMessage() { + Throwable exception = new Throwable("java.lang.NullPointerException: null"); + String expectedMessage = "An unexpected error has occurred. Please contact the KnowHow Support for assistance."; + String actualMessage = JiraProcessorUtil.generateLogMessage(exception); + assertEquals(expectedMessage, actualMessage); + } + @Test + public void testGenerateLogMessage_withErrorCollection() { + Throwable exception = new Throwable("org.codehaus.jettison.json.JSONException: A JSONObject text must begin with '{'"); + String expectedMessage = "An unexpected error has occurred. Please contact the KnowHow Support for assistance."; + String actualMessage = JiraProcessorUtil.generateLogMessage(exception); + assertEquals(expectedMessage, actualMessage); + } + @Test + public void testGenerateLogMessage_withErrorStatusCode() { + Throwable exception = new Throwable("[ErrorCollection{status=401, errors={}, errorMessages=[]}]"); + String expectedMessage = "Sorry, you are not authorized to access the requested resource."; + String actualMessage = JiraProcessorUtil.generateLogMessage(exception); + assertEquals(expectedMessage, actualMessage); + } + @Test + public void testGenerateLogMessage_noMatchingPattern() { + Throwable exception = new Throwable("Some random exception message"); + String expectedMessage = "No matching exception pattern found"; + String actualMessage = JiraProcessorUtil.generateLogMessage(exception); + assertEquals(expectedMessage, actualMessage); + } } \ No newline at end of file From 09af26460e612115d3bc332f04cb42a3fe4e6a21 Mon Sep 17 00:00:00 2001 From: Girish Date: Wed, 21 Aug 2024 13:37:53 +0530 Subject: [PATCH 4/4] DTS-38567:Addressed review comments for status check --- .../jira/util/JiraProcessorUtil.java | 17 ++++++++++++++--- .../jira/util/JiraProcessorUtilTest.java | 16 +++++++++++++++- 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/processors/jira/src/main/java/com/publicissapient/kpidashboard/jira/util/JiraProcessorUtil.java b/processors/jira/src/main/java/com/publicissapient/kpidashboard/jira/util/JiraProcessorUtil.java index b06e7b83d7..71cf06207b 100644 --- a/processors/jira/src/main/java/com/publicissapient/kpidashboard/jira/util/JiraProcessorUtil.java +++ b/processors/jira/src/main/java/com/publicissapient/kpidashboard/jira/util/JiraProcessorUtil.java @@ -84,7 +84,9 @@ private JiraProcessorUtil() { private static final Pattern ERROR_WITH_STATUS_CODE_PATTERN = Pattern.compile("Error:\\s*(\\d+)\\s*-\\s*(.*)"); private static final String UNAUTHORIZED = "Sorry, you are not authorized to access the requested resource."; + private static final String TO_MANY_REQUEST = "Too many request try after sometime."; private static final String OTHER_CLIENT_ERRORS = "An unexpected error has occurred. Please contact the KnowHow Support for assistance."; + private static final String FORBIDDEN="Forbidden, check your credentials."; /** * This method return UTF-8 decoded string response @@ -398,11 +400,20 @@ private static String matchPattern(String exceptionMessage, Pattern pattern, boo if (matcher.find()) { if (hasStatusCode) { int statusCode = Integer.parseInt(matcher.group(1)); - return (statusCode >= 400 && statusCode < 500) ? UNAUTHORIZED : OTHER_CLIENT_ERRORS; - } else { - return OTHER_CLIENT_ERRORS; + switch (statusCode) { + case 401: + return UNAUTHORIZED; + case 429: + return TO_MANY_REQUEST; + case 403: + return FORBIDDEN; + default: + return OTHER_CLIENT_ERRORS; + } } + return OTHER_CLIENT_ERRORS; } return null; } + } diff --git a/processors/jira/src/test/java/com/publicissapient/kpidashboard/jira/util/JiraProcessorUtilTest.java b/processors/jira/src/test/java/com/publicissapient/kpidashboard/jira/util/JiraProcessorUtilTest.java index 0f350f75d0..f2db81b856 100644 --- a/processors/jira/src/test/java/com/publicissapient/kpidashboard/jira/util/JiraProcessorUtilTest.java +++ b/processors/jira/src/test/java/com/publicissapient/kpidashboard/jira/util/JiraProcessorUtilTest.java @@ -249,13 +249,27 @@ public void testGenerateLogMessage_withErrorCollection() { assertEquals(expectedMessage, actualMessage); } @Test - public void testGenerateLogMessage_withErrorStatusCode() { + public void testGenerateLogMessage_withErrorStatusCode401() { Throwable exception = new Throwable("[ErrorCollection{status=401, errors={}, errorMessages=[]}]"); String expectedMessage = "Sorry, you are not authorized to access the requested resource."; String actualMessage = JiraProcessorUtil.generateLogMessage(exception); assertEquals(expectedMessage, actualMessage); } @Test + public void testGenerateLogMessage_withErrorStatusCode403() { + Throwable exception = new Throwable("[ErrorCollection{status=403, errors={}, errorMessages=[]}]"); + String expectedMessage = "Forbidden, check your credentials."; + String actualMessage = JiraProcessorUtil.generateLogMessage(exception); + assertEquals(expectedMessage, actualMessage); + } + @Test + public void testGenerateLogMessage_withErrorStatusCode429() { + Throwable exception = new Throwable("[ErrorCollection{status=429, errors={}, errorMessages=[]}]"); + String expectedMessage = "Too many request try after sometime."; + String actualMessage = JiraProcessorUtil.generateLogMessage(exception); + assertEquals(expectedMessage, actualMessage); + } + @Test public void testGenerateLogMessage_noMatchingPattern() { Throwable exception = new Throwable("Some random exception message"); String expectedMessage = "No matching exception pattern found";