提交 3afe6409 authored 作者: Edwin's avatar Edwin

feat: implement error deduplication in SkyWalkingQueryService for improved error…

feat: implement error deduplication in SkyWalkingQueryService for improved error reporting and trace management
上级 d0af88cf
......@@ -19,8 +19,10 @@ import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.TimeZone;
@Slf4j
......@@ -171,7 +173,8 @@ public class SkyWalkingQueryService {
}
StringBuilder builder = new StringBuilder("【最近报错】");
int index = 1;
for (TraceErrorDetail error : errors) {
for (DedupedError group : dedupeErrors(errors)) {
TraceErrorDetail error = group.representative;
builder.append("\n").append(index++).append(". ");
if (!StringUtil.isBlank(error.getEndpoint())) {
builder.append("接口: ").append(error.getEndpoint());
......@@ -190,13 +193,85 @@ public class SkyWalkingQueryService {
} else if (!StringUtil.isBlank(error.getErrorKind()) || !StringUtil.isBlank(error.getMessage())) {
builder.append("\n 堆栈: (SkyWalking 未采集到 stack,请在业务 Agent 中开启异常栈上报)");
}
if (!StringUtil.isBlank(error.getTraceId())) {
if (group.count > 1) {
builder.append("\n 同类错误: 共 ").append(group.count).append(" 次");
}
if (!group.traceIds.isEmpty()) {
builder.append("\n TraceId: ").append(String.join(", ", group.traceIds));
} else if (!StringUtil.isBlank(error.getTraceId())) {
builder.append("\n TraceId: ").append(error.getTraceId());
}
}
return builder.toString();
}
private List<DedupedError> dedupeErrors(List<TraceErrorDetail> errors) {
Map<String, DedupedError> grouped = new LinkedHashMap<>();
for (TraceErrorDetail error : errors) {
String key = buildErrorSignature(error);
DedupedError existing = grouped.get(key);
if (existing == null) {
grouped.put(key, new DedupedError(error));
continue;
}
existing.count++;
existing.traceIds.add(error.getTraceId());
if (errorDetailScore(error) > errorDetailScore(existing.representative)) {
existing.representative = error;
}
}
return new ArrayList<>(grouped.values());
}
private String buildErrorSignature(TraceErrorDetail error) {
return String.join("|",
safe(error.getEndpoint()),
safe(error.getErrorKind()),
safe(error.getMessage()),
normalizeStackSignature(error.getStack()));
}
private String normalizeStackSignature(String stack) {
if (StringUtil.isBlank(stack)) {
return "";
}
String[] lines = stack.split("\\r?\\n");
StringBuilder builder = new StringBuilder();
int lineCount = 0;
for (String line : lines) {
String trimmed = line.trim();
if (trimmed.isEmpty()) {
continue;
}
if (builder.length() > 0) {
builder.append('\n');
}
builder.append(trimmed);
lineCount++;
if (lineCount >= 3) {
break;
}
}
return builder.toString();
}
private String safe(String value) {
return value == null ? "" : value.trim();
}
private static class DedupedError {
private TraceErrorDetail representative;
private int count = 1;
private final List<String> traceIds = new ArrayList<>();
private DedupedError(TraceErrorDetail representative) {
this.representative = representative;
if (!StringUtil.isBlank(representative.getTraceId())) {
traceIds.add(representative.getTraceId());
}
}
}
private List<TraceErrorDetail> queryErrorTraces(String serviceId, String endpointId) throws Exception {
String[] range = buildDurationRange(skyWalkingProperties.getLookbackMinutes());
String endpointField = StringUtil.isBlank(endpointId)
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论