Skip to content

Commit

Permalink
fix(sdk): kraken-19 - handle the api activity logs without status code (
Browse files Browse the repository at this point in the history
#148)

* fix(sdk): kraken-19 - handle the api activity logs without status code in stats

* fix(sdk): kraken-19 - fix sonar cloud issue

---------

Co-authored-by: kuangxiang20240501 <[email protected]>
  • Loading branch information
jaroslawmalekcodete and kuangxiang20240501 authored Nov 14, 2024
1 parent be0c700 commit d165a92
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,5 @@
@NoArgsConstructor
public class ErrorBreakdown {
private LocalDate date;
private Map<Integer, Long> errors;
private Map<String, Long> errors;
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
import com.consoleconnect.kraken.operator.controller.dto.statistics.ErrorBreakdown;
import com.consoleconnect.kraken.operator.controller.dto.statistics.MostPopularEndpointStatistics;
import com.consoleconnect.kraken.operator.controller.dto.statistics.RequestStatistics;
import com.consoleconnect.kraken.operator.core.entity.AbstractHttpEntity;
import com.consoleconnect.kraken.operator.core.entity.ApiActivityLogEntity;
import com.consoleconnect.kraken.operator.core.repo.ApiActivityLogRepository;
import com.consoleconnect.kraken.operator.core.request.ApiStatisticsSearchRequest;
Expand Down Expand Up @@ -39,6 +38,7 @@ public class ApiActivityStatisticsService {
public static final String CALL_SEQ_ZERO = "0";
public static final String BUYER = "buyer";
public static final int NUMBER_OF_MOST_POPULAR_ENDPOINT_LIMIT = 7;
public static final String NO_STATUS_CODE = "No Status Code";

private final ApiActivityLogRepository repository;

Expand Down Expand Up @@ -79,20 +79,23 @@ private ApiRequestActivityStatistics createApiRequestActivityStatistics(
var stats =
logsGroupedByDayAndHttpStatus.entrySet().stream()
.map(
dateEntry ->
new RequestStatistics(
dateEntry.getKey().toLocalDate(),
dateEntry.getValue().get(RequestStatus.SUCCESS),
dateEntry.getValue().get(RequestStatus.ERROR)))
dateEntry -> {
Long success = dateEntry.getValue().get(RequestStatus.SUCCESS);
Long error = dateEntry.getValue().get(RequestStatus.ERROR);
return new RequestStatistics(
dateEntry.getKey().toLocalDate(),
(success != null) ? success : 0,
(error != null) ? error : 0);
})
.sorted(Comparator.comparing(RequestStatistics::getDate))
.toList();
return new ApiRequestActivityStatistics(stats);
}

private RequestStatus status(Integer statusCode) {
return (HttpStatus.valueOf(statusCode).is2xxSuccessful())
? RequestStatus.SUCCESS
: RequestStatus.ERROR;
return (statusCode == null || !HttpStatus.valueOf(statusCode).is2xxSuccessful())
? RequestStatus.ERROR
: RequestStatus.SUCCESS;
}

public ErrorApiRequestStatistics loadErrorsStatistics(ApiStatisticsSearchRequest searchRequest) {
Expand All @@ -110,26 +113,35 @@ private List<ApiActivityLogEntity> getApiActivityLogErrorEntities(
if (searchRequest.getBuyerId() != null) {
predicateList.add(criteriaBuilder.equal(root.get(BUYER), searchRequest.getBuyerId()));
}
predicateList.add(criteriaBuilder.greaterThanOrEqualTo(root.get(HTTP_STATUS_CODE), 400));
predicateList.add(criteriaBuilder.lessThan(root.get(HTTP_STATUS_CODE), 600));
var statusIsNull = criteriaBuilder.isNull(root.get(HTTP_STATUS_CODE));
var statusInRange =
criteriaBuilder.and(
criteriaBuilder.greaterThanOrEqualTo(root.get(HTTP_STATUS_CODE), 400),
criteriaBuilder.lessThan(root.get(HTTP_STATUS_CODE), 600));
predicateList.add(criteriaBuilder.or(statusIsNull, statusInRange));

return query.where(predicateList.toArray(new Predicate[0])).getRestriction();
};
return repository.findAll(spec);
}

private Map<ZonedDateTime, Map<Integer, Long>> groupByDayAndStatus(
private Map<ZonedDateTime, Map<String, Long>> groupByDayAndStatus(
ZoneId zoneId, List<ApiActivityLogEntity> logs) {
return logs.stream()
.collect(
Collectors.groupingBy(
entity ->
entity.getCreatedAt().withZoneSameInstant(zoneId).truncatedTo(ChronoUnit.DAYS),
Collectors.groupingBy(
AbstractHttpEntity::getHttpStatusCode, Collectors.counting())));
apiActivityLogEntity ->
(apiActivityLogEntity.getHttpStatusCode() != null)
? apiActivityLogEntity.getHttpStatusCode().toString()
: NO_STATUS_CODE,
Collectors.counting())));
}

private ErrorApiRequestStatistics createErrorApiRequestStatistics(
Map<ZonedDateTime, Map<Integer, Long>> stats) {
Map<ZonedDateTime, Map<String, Long>> stats) {
var data =
stats.entrySet().stream()
.map(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.consoleconnect.kraken.operator.controller.service.statistics;

import static com.consoleconnect.kraken.operator.controller.service.statistics.ApiActivityStatisticsService.NO_STATUS_CODE;
import static org.assertj.core.api.Assertions.assertThat;

import com.consoleconnect.kraken.operator.config.TestApplication;
Expand Down Expand Up @@ -98,6 +99,28 @@ void givenApiActivityLogs_whenLoadRequestStatistics_thenReturnsApiRequestsStatis
assertThat(statsFor2Day.getError()).isEqualTo(12);
}

@Test
void
givenApiActivityLogWithStatusCodeNull_whenLoadRequestStatistics_thenStatusCodeNullShouldBePutItToError() {
// given
var envId = UUID.randomUUID();
var now = ZonedDateTime.parse(NOW_WITH_TIMEZONE);
addApiLogActivity(envId.toString(), createPayloadsWithNullStatus(toUTC(now)));
var searchRequest =
ApiStatisticsSearchRequest.builder()
.env(envId.toString())
.queryStart(now.minusDays(2))
.queryEnd(now)
.build();
// when
var result = sut.loadRequestStatistics(searchRequest);
// then
assertThat(result.getRequestStatistics()).hasSize(1);
var statsFor1Day = result.getRequestStatistics().get(0);
assertThat(statsFor1Day.getError()).isEqualTo(1);
assertThat(statsFor1Day.getSuccess()).isZero();
}

@Test
void givenApiActivityLogs_whenLoadRequestStatisticsByBuyerId_thenReturnsApiRequestsStatistics() {
// given
Expand Down Expand Up @@ -177,8 +200,8 @@ void givenErrorApiActivityLogs_whenLoadErrorsStatistics_thenReturnsErrorStatisti
var errorBreakdown0 = result.getErrorBreakdowns().get(0);
var errorBreakdown1 = result.getErrorBreakdowns().get(1);
assertThat(errorBreakdown0.getDate()).isBefore(errorBreakdown1.getDate());
assertThat(errorBreakdown0.getErrors()).containsEntry(401, 4L).containsEntry(500, 4L);
assertThat(errorBreakdown1.getErrors()).containsEntry(401, 6L).containsEntry(500, 6L);
assertThat(errorBreakdown0.getErrors()).containsEntry("401", 4L).containsEntry("500", 4L);
assertThat(errorBreakdown1.getErrors()).containsEntry("401", 6L).containsEntry("500", 6L);
}

@Test
Expand All @@ -198,8 +221,29 @@ void givenErrorApiActivityLogs_whenLoadErrorsStatisticsByBuyerId_thenReturnsErro
var result = sut.loadErrorsStatistics(searchRequest);
// then
assertThat(result.getErrorBreakdowns()).hasSize(2);
assertThat(result.getErrorBreakdowns().get(0).getErrors()).containsEntry(401, 4L);
assertThat(result.getErrorBreakdowns().get(1).getErrors()).containsEntry(401, 6L);
assertThat(result.getErrorBreakdowns().get(0).getErrors()).containsEntry("401", 4L);
assertThat(result.getErrorBreakdowns().get(1).getErrors()).containsEntry("401", 6L);
}

@Test
void
givenErrorApiActivityLogsWithNoStatusCode_whenLoadErrorsStatistics_thenReturnsErrorStatistics() {
// given
var envId = UUID.randomUUID();
var now = ZonedDateTime.parse(NOW_WITH_TIMEZONE);
addApiLogActivity(envId.toString(), createPayloadsWithNullStatus(toUTC(now)));
var searchRequest =
ApiStatisticsSearchRequest.builder()
.env(envId.toString())
.queryStart(now.minusDays(2))
.queryEnd(now)
.build();
// when
var result = sut.loadErrorsStatistics(searchRequest);
// then
assertThat(result.getErrorBreakdowns()).hasSize(1);
var errorBreakdown0 = result.getErrorBreakdowns().get(0);
assertThat(errorBreakdown0.getErrors()).containsEntry(NO_STATUS_CODE, 1L);
}

@Test
Expand Down Expand Up @@ -415,6 +459,20 @@ private void addApiLogActivity(String envId, List<String> payloads) {
});
}

private List<String> createPayloadsWithNullStatus(ZonedDateTime now) {
return new ArrayList<>(
PayloadBuilder.builder()
.method("GET")
.path0("/mefApi/sonata/product/123")
.path1("/hub/product/123")
.now(now)
.httpStatus(null)
.number(1)
.buyerId(BUYER_ID_1)
.build()
.createPayload());
}

private List<String> createPayloads(ZonedDateTime now) {
var payload = new ArrayList<String>();
payload.addAll(
Expand Down Expand Up @@ -477,7 +535,7 @@ public static class PayloadBuilder {
private String method;
private String path0;
private String path1;
private int httpStatus;
private Integer httpStatus;
private ZonedDateTime now;
private int number;
private String buyerId;
Expand Down

0 comments on commit d165a92

Please sign in to comment.