Source:
<code>private String searchJiraAPI(final PluginTask task, int startAt, int maxResults) { try { return retryExecutor().withRetryLimit(task.getRetryLimit()) .withInitialRetryWait(task.getInitialRetryIntervalMillis()) .withMaxRetryWait(task.getMaximumRetryIntervalMillis()) .runInterruptible(new Retryable<String>() { @Override public String call() throws Exception { return authorizeAndRequestWithGet(task, JiraUtil.buildSearchUrl(task, startAt, maxResults)); } @Override public boolean isRetryableException(Exception exception) { if (exception instanceof JiraException) { int statusCode = ((JiraException) exception).getStatusCode(); if (statusCode / 100 == 4 && statusCode != HttpStatus.SC_UNAUTHORIZED && statusCode != 429) { return false; } return true; } return false; } @Override public void onRetry(Exception exception, int retryCount, int retryLimit, int retryWait) throws RetryGiveupException { if (exception instanceof JiraException) { String message = String .format("Retrying %d/%d after %d seconds. HTTP status code: %s", retryCount, retryLimit, retryWait / 1000, ((JiraException) exception).getStatusCode()); LOGGER.warn(message); } else { String message = String .format("Retrying %d/%d after %d seconds. Message: %s", retryCount, retryLimit, retryWait / 1000, exception.getMessage()); LOGGER.warn(message, exception); } } @Override public void onGiveup(Exception firstException, Exception lastException) throws RetryGiveupException { <START> LOGGER.warn("Retry Limits Completed"); <END> } }); } catch (RetryGiveupException | InterruptedException e) { throw new RuntimeException(e); } }</code><technical_language>Code style: wording, "Completed" sounds a bit misleading, imo "Retry Limit Exceeded" easier understand logs</technical_language>

Target:
private String searchJiraAPI(final PluginTask task, int startAt, int maxResults) { try { return retryExecutor().withRetryLimit(task.getRetryLimit()) .withInitialRetryWait(task.getInitialRetryIntervalMillis()) .withMaxRetryWait(task.getMaximumRetryIntervalMillis()) .runInterruptible(new Retryable<String>() { @Override public String call() throws Exception { return authorizeAndRequest(task, JiraUtil.buildSearchUrl(task.getUri()), createSearchIssuesBody(task, startAt, maxResults)); } @Override public boolean isRetryableException(Exception exception) { if (exception instanceof JiraException) { int statusCode = ((JiraException) exception).getStatusCode(); return statusCode / 100 != 4 || statusCode == HttpStatus.SC_UNAUTHORIZED || statusCode == 429; } return false; } @Override public void onRetry(Exception exception, int retryCount, int retryLimit, int retryWait) throws RetryGiveupException { if (exception instanceof JiraException) { String message = String .format("Retrying %d/%d after %d seconds. HTTP status code: %s", retryCount, retryLimit, retryWait / 1000, ((JiraException) exception).getStatusCode()); LOGGER.warn(message); } else { String message = String .format("Retrying %d/%d after %d seconds. Message: %s", retryCount, retryLimit, retryWait / 1000, exception.getMessage()); LOGGER.warn(message, exception); } } @Override public void onGiveup(Exception firstException, Exception lastException) throws RetryGiveupException { LOGGER.warn("Retry Limit Exceeded"); } }); } catch (RetryGiveupException | InterruptedException e) { if (e instanceof RetryGiveupException && e.getCause() != null && e.getCause() instanceof JiraException) { throw new ConfigException(e.getCause().getMessage()); } throw new ConfigException(e); } }