| | |
| | | if (TIME_FIELD_APPE.equalsIgnoreCase(request.getString("timeField"))) { |
| | | timeField = TIME_FIELD_APPE; |
| | | } |
| | | return buildAnalysisResult(list, mode, timeField, request); |
| | | return buildAnalysisResult(list, timeField); |
| | | } |
| | | |
| | | private QueryWrapper<WrkMastLog> buildHistoryLogWrapper(Map<String, Object> param) { |
| | |
| | | wrapper.in("wrk_no", wrkNos); |
| | | } |
| | | |
| | | private Map<String, Object> buildAnalysisResult(List<WrkAnalysis> list, String mode, String timeField, JSONObject request) { |
| | | private Map<String, Object> buildAnalysisResult(List<WrkAnalysis> list, String timeField) { |
| | | Map<String, Object> result = new LinkedHashMap<>(); |
| | | Map<String, Object> summary = new LinkedHashMap<>(); |
| | | summary.put("taskCount", list.size()); |
| | |
| | | summary.put("partialTaskCount", list.stream().filter(item -> METRIC_PARTIAL.equals(item.getMetricCompleteness())).count()); |
| | | result.put("summary", summary); |
| | | result.put("durationCompare", buildDurationCompare(list)); |
| | | result.put("trend", buildTrend(list, mode, timeField, request)); |
| | | result.put("trend", buildTrend(list, timeField)); |
| | | result.put("faultPie", buildFaultPie(list)); |
| | | result.put("faultDuration", buildFaultDuration(list)); |
| | | result.put("detail", buildDetailRows(list)); |
| | |
| | | .collect(Collectors.toList()); |
| | | } |
| | | |
| | | private List<Map<String, Object>> buildTrend(List<WrkAnalysis> list, String mode, String timeField, JSONObject request) { |
| | | private List<Map<String, Object>> buildTrend(List<WrkAnalysis> list, String timeField) { |
| | | List<Map<String, Object>> trend = new ArrayList<>(); |
| | | if (list.isEmpty()) { |
| | | return trend; |
| | | } |
| | | long startMs = Long.MAX_VALUE; |
| | | long endMs = Long.MIN_VALUE; |
| | | if (MODE_TIME.equals(mode)) { |
| | | Long reqStart = parseLong(request.get("startTime")); |
| | | Long reqEnd = parseLong(request.get("endTime")); |
| | | if (reqStart != null && reqEnd != null) { |
| | | startMs = reqStart; |
| | | endMs = reqEnd; |
| | | } |
| | | } |
| | | if (startMs == Long.MAX_VALUE || endMs == Long.MIN_VALUE) { |
| | | for (WrkAnalysis item : list) { |
| | | Date date = resolveBucketTime(item, timeField); |
| | |
| | | if (startMs == Long.MAX_VALUE || endMs == Long.MIN_VALUE) { |
| | | return trend; |
| | | } |
| | | boolean hourly = endMs - startMs <= 72L * 60L * 60L * 1000L; |
| | | SimpleDateFormat keyFormat = new SimpleDateFormat(hourly ? "yyyy-MM-dd HH:00" : "yyyy-MM-dd"); |
| | | TrendBucketType bucketType = resolveTrendBucketType(startMs, endMs); |
| | | SimpleDateFormat keyFormat = new SimpleDateFormat(resolveTrendBucketPattern(bucketType)); |
| | | keyFormat.setTimeZone(TimeZone.getDefault()); |
| | | Map<String, BucketAccumulator> bucketMap = new LinkedHashMap<>(); |
| | | Map<Long, BucketAccumulator> bucketMap = new LinkedHashMap<>(); |
| | | List<WrkAnalysis> sorted = new ArrayList<>(list); |
| | | sorted.sort(Comparator.comparing(item -> resolveBucketTime(item, timeField), Comparator.nullsLast(Date::compareTo))); |
| | | for (WrkAnalysis item : sorted) { |
| | |
| | | if (bucketTime == null) { |
| | | continue; |
| | | } |
| | | String key = keyFormat.format(bucketTime); |
| | | Date bucketStart = truncateBucketTime(bucketTime, bucketType); |
| | | long key = bucketStart.getTime(); |
| | | BucketAccumulator accumulator = bucketMap.computeIfAbsent(key, k -> new BucketAccumulator()); |
| | | accumulator.taskCount++; |
| | | if (item.getTotalDurationMs() != null) { |
| | |
| | | accumulator.craneDurationCount++; |
| | | } |
| | | } |
| | | for (Map.Entry<String, BucketAccumulator> entry : bucketMap.entrySet()) { |
| | | for (Map.Entry<Long, BucketAccumulator> entry : bucketMap.entrySet()) { |
| | | Map<String, Object> item = new LinkedHashMap<>(); |
| | | item.put("bucketLabel", entry.getKey()); |
| | | item.put("bucketLabel", keyFormat.format(new Date(entry.getKey()))); |
| | | item.put("taskCount", entry.getValue().taskCount); |
| | | item.put("avgTotalDurationMs", entry.getValue().totalDurationCount == 0 ? null : entry.getValue().totalDurationMs / entry.getValue().totalDurationCount); |
| | | item.put("avgStationDurationMs", entry.getValue().stationDurationCount == 0 ? null : entry.getValue().stationDurationMs / entry.getValue().stationDurationCount); |
| | |
| | | trend.add(item); |
| | | } |
| | | return trend; |
| | | } |
| | | |
| | | private TrendBucketType resolveTrendBucketType(long startMs, long endMs) { |
| | | long spanMs = Math.max(0L, endMs - startMs); |
| | | if (spanMs <= 6L * 60L * 60L * 1000L) { |
| | | return TrendBucketType.MINUTE; |
| | | } |
| | | if (spanMs <= 72L * 60L * 60L * 1000L) { |
| | | return TrendBucketType.HOUR; |
| | | } |
| | | return TrendBucketType.DAY; |
| | | } |
| | | |
| | | private String resolveTrendBucketPattern(TrendBucketType bucketType) { |
| | | if (bucketType == TrendBucketType.MINUTE) { |
| | | return "yyyy-MM-dd HH:mm"; |
| | | } |
| | | if (bucketType == TrendBucketType.HOUR) { |
| | | return "yyyy-MM-dd HH:00"; |
| | | } |
| | | return "yyyy-MM-dd"; |
| | | } |
| | | |
| | | private Date truncateBucketTime(Date time, TrendBucketType bucketType) { |
| | | Calendar calendar = Calendar.getInstance(); |
| | | calendar.setTime(time); |
| | | if (bucketType == TrendBucketType.DAY) { |
| | | calendar.set(Calendar.HOUR_OF_DAY, 0); |
| | | } |
| | | if (bucketType == TrendBucketType.DAY || bucketType == TrendBucketType.HOUR) { |
| | | calendar.set(Calendar.MINUTE, 0); |
| | | } |
| | | calendar.set(Calendar.SECOND, 0); |
| | | calendar.set(Calendar.MILLISECOND, 0); |
| | | return calendar.getTime(); |
| | | } |
| | | |
| | | private List<Map<String, Object>> buildFaultPie(List<WrkAnalysis> list) { |
| | |
| | | private long craneDurationCount; |
| | | } |
| | | |
| | | private enum TrendBucketType { |
| | | MINUTE, |
| | | HOUR, |
| | | DAY |
| | | } |
| | | |
| | | } |