|
|
@@ -14,6 +14,7 @@ import org.springframework.stereotype.Service;
|
|
|
import java.time.Duration;
|
|
|
import java.time.LocalDateTime;
|
|
|
import java.util.*;
|
|
|
+import java.util.concurrent.ConcurrentHashMap;
|
|
|
import java.util.stream.Collectors;
|
|
|
|
|
|
@Service
|
|
|
@@ -30,6 +31,7 @@ public class D4MetricsService {
|
|
|
);
|
|
|
private static final int D4_QUERY_PAGE_SIZE = 1000;
|
|
|
private static final long DEFAULT_D4_SLA_THRESHOLD_MS = 24L * 60L * 60L * 1000L;
|
|
|
+ private static final String BUSINESS_INFO_SEPARATOR = "\\|";
|
|
|
|
|
|
public D4Metrics calculateD4Metrics(LocalDateTime startTime, LocalDateTime endTime) {
|
|
|
log.info("Calculating D4 metrics from {} to {}", startTime, endTime);
|
|
|
@@ -156,16 +158,18 @@ public class D4MetricsService {
|
|
|
|
|
|
private Map<String, Double> calculateCompletionRateByTaskType(List<LogEntry> assignedLogs, List<LogEntry> completedLogs) {
|
|
|
Map<String, Long> assignedByType = assignedLogs.stream()
|
|
|
- .filter(log -> log.getContext() != null && log.getContext().containsKey("taskType"))
|
|
|
+ .map(log -> getContextString(log, "taskType"))
|
|
|
+ .filter(Objects::nonNull)
|
|
|
.collect(Collectors.groupingBy(
|
|
|
- log -> (String) log.getContext().get("taskType"),
|
|
|
+ taskType -> taskType,
|
|
|
Collectors.counting()
|
|
|
));
|
|
|
|
|
|
Map<String, Long> completedByType = completedLogs.stream()
|
|
|
- .filter(log -> log.getContext() != null && log.getContext().containsKey("taskType"))
|
|
|
+ .map(log -> getContextString(log, "taskType"))
|
|
|
+ .filter(Objects::nonNull)
|
|
|
.collect(Collectors.groupingBy(
|
|
|
- log -> (String) log.getContext().get("taskType"),
|
|
|
+ taskType -> taskType,
|
|
|
Collectors.counting()
|
|
|
));
|
|
|
|
|
|
@@ -183,16 +187,18 @@ public class D4MetricsService {
|
|
|
|
|
|
private Map<String, Double> calculateCompletionRateByProject(List<LogEntry> assignedLogs, List<LogEntry> completedLogs) {
|
|
|
Map<String, Long> assignedByProject = assignedLogs.stream()
|
|
|
- .filter(log -> log.getContext() != null && log.getContext().containsKey("projectId"))
|
|
|
+ .map(log -> getContextString(log, "projectId"))
|
|
|
+ .filter(Objects::nonNull)
|
|
|
.collect(Collectors.groupingBy(
|
|
|
- log -> String.valueOf(log.getContext().get("projectId")),
|
|
|
+ projectId -> projectId,
|
|
|
Collectors.counting()
|
|
|
));
|
|
|
|
|
|
Map<String, Long> completedByProject = completedLogs.stream()
|
|
|
- .filter(log -> log.getContext() != null && log.getContext().containsKey("projectId"))
|
|
|
+ .map(log -> getContextString(log, "projectId"))
|
|
|
+ .filter(Objects::nonNull)
|
|
|
.collect(Collectors.groupingBy(
|
|
|
- log -> String.valueOf(log.getContext().get("projectId")),
|
|
|
+ projectId -> projectId,
|
|
|
Collectors.counting()
|
|
|
));
|
|
|
|
|
|
@@ -258,18 +264,20 @@ public class D4MetricsService {
|
|
|
|
|
|
private Map<String, Long> calculateCollaborationsBySource(List<LogEntry> collabLogs) {
|
|
|
return collabLogs.stream()
|
|
|
- .filter(log -> log.getContext() != null && log.getContext().containsKey("source"))
|
|
|
+ .map(log -> getContextString(log, "source"))
|
|
|
+ .filter(Objects::nonNull)
|
|
|
.collect(Collectors.groupingBy(
|
|
|
- log -> (String) log.getContext().get("source"),
|
|
|
+ source -> source,
|
|
|
Collectors.counting()
|
|
|
));
|
|
|
}
|
|
|
|
|
|
private Map<String, Long> calculateConflictsByType(List<LogEntry> conflictLogs) {
|
|
|
return conflictLogs.stream()
|
|
|
- .filter(log -> log.getContext() != null && log.getContext().containsKey("conflictType"))
|
|
|
+ .map(log -> getContextString(log, "conflictType"))
|
|
|
+ .filter(Objects::nonNull)
|
|
|
.collect(Collectors.groupingBy(
|
|
|
- log -> String.valueOf(log.getContext().get("conflictType")),
|
|
|
+ conflictType -> conflictType,
|
|
|
Collectors.counting()
|
|
|
));
|
|
|
}
|
|
|
@@ -371,18 +379,12 @@ public class D4MetricsService {
|
|
|
}
|
|
|
|
|
|
private String getContextString(LogEntry logEntry, String key) {
|
|
|
- if (logEntry == null || logEntry.getContext() == null) {
|
|
|
- return null;
|
|
|
- }
|
|
|
- Object value = logEntry.getContext().get(key);
|
|
|
+ Object value = getContextValue(logEntry, key);
|
|
|
return value != null ? String.valueOf(value) : null;
|
|
|
}
|
|
|
|
|
|
private Long getContextLong(LogEntry logEntry, String key) {
|
|
|
- if (logEntry == null || logEntry.getContext() == null) {
|
|
|
- return null;
|
|
|
- }
|
|
|
- Object value = logEntry.getContext().get(key);
|
|
|
+ Object value = getContextValue(logEntry, key);
|
|
|
if (value == null) {
|
|
|
return null;
|
|
|
}
|
|
|
@@ -404,4 +406,48 @@ public class D4MetricsService {
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ private Object getContextValue(LogEntry logEntry, String key) {
|
|
|
+ if (logEntry == null || key == null) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ Map<String, Object> context = logEntry.getContext();
|
|
|
+ if (context != null && context.containsKey(key)) {
|
|
|
+ return context.get(key);
|
|
|
+ }
|
|
|
+ Map<String, Object> parsed = parseBusinessInfo(logEntry);
|
|
|
+ return parsed.get(key);
|
|
|
+ }
|
|
|
+
|
|
|
+ private Map<String, Object> parseBusinessInfo(LogEntry logEntry) {
|
|
|
+ if (logEntry == null || logEntry.getBusinessInfo() == null || logEntry.getBusinessInfo().isBlank()) {
|
|
|
+ return Collections.emptyMap();
|
|
|
+ }
|
|
|
+
|
|
|
+ if (logEntry.getContext() == null) {
|
|
|
+ logEntry.setContext(new ConcurrentHashMap<>());
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!logEntry.getContext().isEmpty()) {
|
|
|
+ return logEntry.getContext();
|
|
|
+ }
|
|
|
+
|
|
|
+ String[] pairs = logEntry.getBusinessInfo().split(BUSINESS_INFO_SEPARATOR);
|
|
|
+ for (String pair : pairs) {
|
|
|
+ if (pair == null || pair.isBlank()) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ int splitIndex = pair.indexOf('=');
|
|
|
+ if (splitIndex <= 0 || splitIndex == pair.length() - 1) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ String key = pair.substring(0, splitIndex).trim();
|
|
|
+ String value = pair.substring(splitIndex + 1).trim();
|
|
|
+ if (!key.isEmpty() && !value.isEmpty() && !"null".equalsIgnoreCase(value)) {
|
|
|
+ logEntry.getContext().put(key, value);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return logEntry.getContext();
|
|
|
+ }
|
|
|
}
|