Skip to content

Commit

Permalink
ADM-953 [frontend][backend]: add timezone to request body and re-calc…
Browse files Browse the repository at this point in the history
…ulate and refactor (#1471)

* ADM-953 [frontend][backend]: add timezone to request body and re-calculate and refactor

* ADM-953 [frontend]: fix e2e test, set chrome default timezone is Asia/Shanghai

* ADM-953 [frontend]: delete the experiment code

* ADM-953 [frontend]: fix sonar issue

* ADM-953 [frontend]: fix comment

* ADM-953 [frontend]: fix comment
  • Loading branch information
zhou-yinyuan authored May 30, 2024
1 parent 22f65b1 commit b9c052d
Show file tree
Hide file tree
Showing 29 changed files with 470 additions and 281 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;

@RestController
@RequiredArgsConstructor
@Tag(name = "Report")
Expand Down Expand Up @@ -68,8 +72,10 @@ public ResponseEntity<CallbackResponse> generateReport(@RequestBody GenerateRepo
log.info("Start to generate report");
reportService.generateReport(request);
String callbackUrl = "/reports/" + request.getCsvTimeStamp() + "?startTime="
+ TimeUtil.convertToChinaSimpleISOFormat(Long.parseLong(request.getStartTime())) + "&endTime="
+ TimeUtil.convertToChinaSimpleISOFormat(Long.parseLong(request.getEndTime()));
+ TimeUtil.convertToUserSimpleISOFormat(Long.parseLong(request.getStartTime()),
request.getTimezoneByZoneId())
+ "&endTime=" + TimeUtil.convertToUserSimpleISOFormat(Long.parseLong(request.getEndTime()),
request.getTimezoneByZoneId());
log.info("Successfully generate report");
return ResponseEntity.status(HttpStatus.ACCEPTED)
.body(CallbackResponse.builder().callbackUrl(callbackUrl).interval(interval).build());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import lombok.Data;
import lombok.NoArgsConstructor;

import java.time.ZoneId;
import java.util.List;

@Data
Expand Down Expand Up @@ -41,6 +42,9 @@ public class GenerateReportRequest {
@NotBlank
private String csvTimeStamp;

@NotBlank
private String timezone;

@JsonIgnore
public List<String> getPipelineMetrics() {
return this.metrics.stream()
Expand Down Expand Up @@ -71,8 +75,9 @@ public List<String> getBoardMetrics() {

@JsonIgnore
public String getTimeRangeAndTimeStamp() {
return TimeUtil.convertToChinaSimpleISOFormat(Long.parseLong(this.startTime)) + "-"
+ TimeUtil.convertToChinaSimpleISOFormat(Long.parseLong(this.endTime)) + "-" + this.csvTimeStamp;
return TimeUtil.convertToUserSimpleISOFormat(Long.parseLong(this.startTime), this.getTimezoneByZoneId()) + "-"
+ TimeUtil.convertToUserSimpleISOFormat(Long.parseLong(this.endTime), this.getTimezoneByZoneId()) + "-"
+ this.csvTimeStamp;

}

Expand Down Expand Up @@ -101,6 +106,7 @@ public GenerateReportRequest toPipelineRequest() {
.codebaseSetting(this.codebaseSetting)
.buildKiteSetting(this.buildKiteSetting)
.csvTimeStamp(this.csvTimeStamp)
.timezone(timezone)
.build();
}

Expand All @@ -114,7 +120,13 @@ public GenerateReportRequest toSourceControlRequest() {
.codebaseSetting(this.codebaseSetting)
.buildKiteSetting(this.buildKiteSetting)
.csvTimeStamp(this.csvTimeStamp)
.timezone(timezone)
.build();
}

@JsonIgnore
public ZoneId getTimezoneByZoneId() {
return ZoneId.of(timezone);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package heartbeat.service.board.jira;

import heartbeat.client.dto.board.jira.JiraCard;
import heartbeat.controller.board.dto.request.RequestJiraBoardColumnSetting;
import heartbeat.controller.board.dto.response.TargetField;
import lombok.Builder;
import lombok.Data;

import java.net.URI;
import java.util.List;

@Data
@Builder
public class JiraBoardInfo {

private List<RequestJiraBoardColumnSetting> boardColumns;

private List<String> users;

private URI baseUrl;

private List<JiraCard> allDoneCards;

private List<TargetField> targetFields;

}
40 changes: 26 additions & 14 deletions backend/src/main/java/heartbeat/service/board/jira/JiraService.java
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.URI;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.Collection;
Expand Down Expand Up @@ -247,7 +248,8 @@ private boolean isIgnoredTargetField(TargetField targetField) {
}

public CardCollection getStoryPointsAndCycleTimeAndReworkInfoForDoneCards(StoryPointsAndCycleTimeRequest request,
List<RequestJiraBoardColumnSetting> boardColumns, List<String> users, String assigneeFilter) {
List<RequestJiraBoardColumnSetting> boardColumns, List<String> users, String assigneeFilter,
ZoneId timezone) {
BoardType boardType = BoardType.fromValue(request.getType());
URI baseUrl = urlGenerator.getUri(request.getSite());
BoardRequestParam boardRequestParam = BoardRequestParam.builder()
Expand All @@ -266,8 +268,14 @@ public CardCollection getStoryPointsAndCycleTimeAndReworkInfoForDoneCards(StoryP
for (RequestJiraBoardColumnSetting boardColumn : boardColumns) {
CardStepsEnum.fromValue(boardColumn.getValue());
}
List<JiraCardDTO> realDoneCards = getRealDoneCards(request, boardColumns, users, baseUrl, allDoneCards,
jiraCardWithFields.getTargetFields(), assigneeFilter);
JiraBoardInfo jiraBoardInfo = JiraBoardInfo.builder()
.boardColumns(boardColumns)
.users(users)
.baseUrl(baseUrl)
.allDoneCards(allDoneCards)
.targetFields(jiraCardWithFields.getTargetFields())
.build();
List<JiraCardDTO> realDoneCards = getRealDoneCards(request, jiraBoardInfo, assigneeFilter, timezone);

double storyPointSum = realDoneCards.stream()
.mapToDouble(card -> card.getBaseInfo().getFields().getStoryPoints())
Expand Down Expand Up @@ -591,9 +599,13 @@ private List<TargetField> getTargetIssueField(Map<String, IssueField> fields) {
.toList();
}

private List<JiraCardDTO> getRealDoneCards(StoryPointsAndCycleTimeRequest request,
List<RequestJiraBoardColumnSetting> boardColumns, List<String> users, URI baseUrl,
List<JiraCard> allDoneCards, List<TargetField> targetFields, String filterMethod) {
private List<JiraCardDTO> getRealDoneCards(StoryPointsAndCycleTimeRequest request, JiraBoardInfo jiraBoardInfo,
String filterMethod, ZoneId timezone) {
List<RequestJiraBoardColumnSetting> boardColumns = jiraBoardInfo.getBoardColumns();
List<String> users = jiraBoardInfo.getUsers();
URI baseUrl = jiraBoardInfo.getBaseUrl();
List<JiraCard> allDoneCards = jiraBoardInfo.getAllDoneCards();
List<TargetField> targetFields = jiraBoardInfo.getTargetFields();

CardCustomFieldKey cardCustomFieldKey = covertCustomFieldKey(targetFields, request.getOverrideFields());
String keyFlagged = cardCustomFieldKey.getFlagged();
Expand All @@ -612,7 +624,7 @@ private List<JiraCardDTO> getRealDoneCards(StoryPointsAndCycleTimeRequest reques
request.getToken());
List<String> assigneeSet = getAssigneeSet(cardHistoryResponseDTO, filterMethod, doneCard);
CycleTimeInfoDTO cycleTimeInfoDTO = getCycleTime(cardHistoryResponseDTO, request.isTreatFlagCardAsBlock(),
keyFlagged, request.getStatus());
keyFlagged, request.getStatus(), timezone);
if (users.stream().anyMatch(assigneeSet::contains)) {
JiraCardDTO jiraCardDTO = JiraCardDTO.builder()
.baseInfo(doneCard)
Expand Down Expand Up @@ -839,13 +851,13 @@ private boolean isRealDoneCardByHistory(CardHistoryResponseDTO jiraCardHistory,
}

private CycleTimeInfoDTO getCycleTime(CardHistoryResponseDTO cardHistoryResponseDTO, Boolean treatFlagCardAsBlock,
String keyFlagged, List<String> realDoneStatus) {
String keyFlagged, List<String> realDoneStatus, ZoneId timezone) {
List<StatusChangedItem> statusChangedArray = putStatusChangeEventsIntoAnArray(cardHistoryResponseDTO,
keyFlagged);
List<CycleTimeInfo> cycleTimeInfos = boardUtil.getCycleTimeInfos(statusChangedArray, realDoneStatus,
treatFlagCardAsBlock);
treatFlagCardAsBlock, timezone);
List<CycleTimeInfo> originCycleTimeInfos = boardUtil.getOriginCycleTimeInfos(statusChangedArray,
treatFlagCardAsBlock);
treatFlagCardAsBlock, timezone);

return CycleTimeInfoDTO.builder()
.cycleTimeInfos(cycleTimeInfos)
Expand Down Expand Up @@ -988,7 +1000,7 @@ private CardCustomFieldKey covertCustomFieldKey(List<TargetField> model, List<Ta
}

public CardCollection getStoryPointsAndCycleTimeForNonDoneCards(StoryPointsAndCycleTimeRequest request,
List<RequestJiraBoardColumnSetting> boardColumns, List<String> users) {
List<RequestJiraBoardColumnSetting> boardColumns, List<String> users, ZoneId timezone) {
URI baseUrl = urlGenerator.getUri(request.getSite());
BoardRequestParam boardRequestParam = BoardRequestParam.builder()
.boardId(request.getBoardId())
Expand All @@ -1008,7 +1020,7 @@ public CardCollection getStoryPointsAndCycleTimeForNonDoneCards(StoryPointsAndCy
}

List<JiraCardDTO> matchedNonCards = getMatchedNonDoneCards(request, boardColumns, users, baseUrl,
jiraCardWithFields.getJiraCards(), jiraCardWithFields.getTargetFields());
jiraCardWithFields.getJiraCards(), jiraCardWithFields.getTargetFields(), timezone);
double storyPointSum = matchedNonCards.stream()
.mapToDouble(card -> card.getBaseInfo().getFields().getStoryPoints())
.sum();
Expand All @@ -1022,7 +1034,7 @@ public CardCollection getStoryPointsAndCycleTimeForNonDoneCards(StoryPointsAndCy

private List<JiraCardDTO> getMatchedNonDoneCards(StoryPointsAndCycleTimeRequest request,
List<RequestJiraBoardColumnSetting> boardColumns, List<String> users, URI baseUrl,
List<JiraCard> allNonDoneCards, List<TargetField> targetFields) {
List<JiraCard> allNonDoneCards, List<TargetField> targetFields, ZoneId timezone) {

List<JiraCardDTO> matchedCards = new ArrayList<>();
CardCustomFieldKey cardCustomFieldKey = covertCustomFieldKey(targetFields, request.getOverrideFields());
Expand All @@ -1032,7 +1044,7 @@ private List<JiraCardDTO> getMatchedNonDoneCards(StoryPointsAndCycleTimeRequest
CardHistoryResponseDTO cardHistoryResponseDTO = getJiraCardHistory(baseUrl, card.getKey(), 0,
request.getToken());
CycleTimeInfoDTO cycleTimeInfoDTO = getCycleTime(cardHistoryResponseDTO, request.isTreatFlagCardAsBlock(),
keyFlagged, request.getStatus());
keyFlagged, request.getStatus(), timezone);

setLastStatusChangeTimeInCard(card, cardHistoryResponseDTO);
List<String> assigneeSet = getAssigneeSetWithDisplayName(baseUrl, card, request.getToken());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -185,9 +185,9 @@ private synchronized ReportResponse generatePipelineReporter(GenerateReportReque

request.getPipelineMetrics().forEach(metric -> {
switch (metric) {
case "deployment frequency" -> reportResponse.setDeploymentFrequency(
deploymentFrequency.calculate(fetchedData.getBuildKiteData().getDeployTimesList(),
Long.parseLong(request.getStartTime()), Long.parseLong(request.getEndTime())));
case "deployment frequency" -> reportResponse.setDeploymentFrequency(deploymentFrequency.calculate(
fetchedData.getBuildKiteData().getDeployTimesList(), Long.parseLong(request.getStartTime()),
Long.parseLong(request.getEndTime()), request.getTimezoneByZoneId()));
case "dev change failure rate" -> reportResponse.setDevChangeFailureRate(
devChangeFailureRate.calculate(fetchedData.getBuildKiteData().getDeployTimesList()));
case "dev mean time to recovery" -> reportResponse.setDevMeanTimeToRecovery(meanToRecoveryCalculator
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,15 +32,16 @@ private CardCollection fetchRealDoneCardCollection(GenerateReportRequest request
StoryPointsAndCycleTimeRequest storyPointsAndCycleTimeRequest = buildStoryPointsAndCycleTimeRequest(
jiraBoardSetting, request.getStartTime(), request.getEndTime());
return jiraService.getStoryPointsAndCycleTimeAndReworkInfoForDoneCards(storyPointsAndCycleTimeRequest,
jiraBoardSetting.getBoardColumns(), jiraBoardSetting.getUsers(), jiraBoardSetting.getAssigneeFilter());
jiraBoardSetting.getBoardColumns(), jiraBoardSetting.getUsers(), jiraBoardSetting.getAssigneeFilter(),
request.getTimezoneByZoneId());
}

private CardCollection fetchNonDoneCardCollection(GenerateReportRequest request) {
JiraBoardSetting jiraBoardSetting = request.getJiraBoardSetting();
StoryPointsAndCycleTimeRequest storyPointsAndCycleTimeRequest = buildStoryPointsAndCycleTimeRequest(
jiraBoardSetting, request.getStartTime(), request.getEndTime());
return jiraService.getStoryPointsAndCycleTimeForNonDoneCards(storyPointsAndCycleTimeRequest,
jiraBoardSetting.getBoardColumns(), jiraBoardSetting.getUsers());
jiraBoardSetting.getBoardColumns(), jiraBoardSetting.getUsers(), request.getTimezoneByZoneId());
}

private static StoryPointsAndCycleTimeRequest buildStoryPointsAndCycleTimeRequest(JiraBoardSetting jiraBoardSetting,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import org.springframework.core.io.InputStreamResource;
import org.springframework.stereotype.Service;

import java.time.ZoneId;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
Expand Down Expand Up @@ -70,8 +71,8 @@ public void generateReport(GenerateReportRequest request) {
CompletableFuture<Void> allFutures = CompletableFuture.allOf(threadList.toArray(new CompletableFuture[0]));
allFutures.thenRun(() -> {
ReportResponse reportResponse = generateReporterService.getComposedReportResponse(request.getCsvTimeStamp(),
convertTimeStampToYYYYMMDD(request.getStartTime()),
convertTimeStampToYYYYMMDD(request.getEndTime()));
convertTimeStampToYYYYMMDD(request.getStartTime(), request.getTimezoneByZoneId()),
convertTimeStampToYYYYMMDD(request.getEndTime(), request.getTimezoneByZoneId()));
if (isNotGenerateMetricError(reportResponse.getReportMetricsError())) {
generateReporterService.generateCSVForMetric(reportResponse, request.getTimeRangeAndTimeStamp());
}
Expand All @@ -80,8 +81,8 @@ public void generateReport(GenerateReportRequest request) {
});
}

private String convertTimeStampToYYYYMMDD(String timeStamp) {
return TimeUtil.convertToChinaSimpleISOFormat(Long.parseLong(timeStamp));
private String convertTimeStampToYYYYMMDD(String timeStamp, ZoneId timezone) {
return TimeUtil.convertToUserSimpleISOFormat(Long.parseLong(timeStamp), timezone);
}

private boolean isNotGenerateMetricError(ReportMetricsError reportMetricsError) {
Expand Down
Loading

0 comments on commit b9c052d

Please sign in to comment.