2 Commitit 9b7e73aca3 ... 6b153f10e1

Tekijä SHA1 Viesti Päivämäärä
  Qyanger 6b153f10e1 pro-code 3 kuukautta sitten
  Qyanger 2a7534e943 add-test-data 4 kuukautta sitten

+ 4 - 0
.gitignore

@@ -20,4 +20,8 @@ target/
 # Local I Don't Want to Share
 d4-metrics-90284c04.md
 
+#etc balabala
+myReport/
+img/
+tmp/
 

+ 1 - 1
README.md

@@ -75,7 +75,7 @@ docker run --rm -p 8080:8080 \
   seecoder-analysis-backend:latest
 ```
 
-健康检查:
+## 健康检查:
 
 ```http
 GET /actuator/health

+ 25 - 0
pom.xml

@@ -19,6 +19,7 @@
 
     <properties>
         <java.version>17</java.version>
+        <lombok.version>1.18.38</lombok.version>
     </properties>
 
     <dependencies>
@@ -44,6 +45,12 @@
             <artifactId>spring-boot-configuration-processor</artifactId>
             <optional>true</optional>
         </dependency>
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+            <version>${lombok.version}</version>
+            <optional>true</optional>
+        </dependency>
 
         <dependency>
             <groupId>org.springframework.boot</groupId>
@@ -54,6 +61,24 @@
 
     <build>
         <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <configuration>
+                    <annotationProcessorPaths>
+                        <path>
+                            <groupId>org.projectlombok</groupId>
+                            <artifactId>lombok</artifactId>
+                            <version>${lombok.version}</version>
+                        </path>
+                        <path>
+                            <groupId>org.springframework.boot</groupId>
+                            <artifactId>spring-boot-configuration-processor</artifactId>
+                            <version>${project.parent.version}</version>
+                        </path>
+                    </annotationProcessorPaths>
+                </configuration>
+            </plugin>
             <plugin>
                 <groupId>org.springframework.boot</groupId>
                 <artifactId>spring-boot-maven-plugin</artifactId>

+ 4 - 40
src/main/java/cn/seecoder/analysis/config/D4MetricsProperties.java

@@ -3,9 +3,13 @@ package cn.seecoder.analysis.config;
 import jakarta.validation.constraints.Max;
 import jakarta.validation.constraints.Min;
 import jakarta.validation.constraints.NotBlank;
+import lombok.Getter;
+import lombok.Setter;
 import org.springframework.boot.context.properties.ConfigurationProperties;
 import org.springframework.validation.annotation.Validated;
 
+@Getter
+@Setter
 @Validated
 @ConfigurationProperties(prefix = "d4.metrics")
 public class D4MetricsProperties {
@@ -24,44 +28,4 @@ public class D4MetricsProperties {
     private int maxEventsToScan = 10000;
 
     private Long defaultTaskSlaMs = 86_400_000L;
-
-    public String getIndexPattern() {
-        return indexPattern;
-    }
-
-    public void setIndexPattern(String indexPattern) {
-        this.indexPattern = indexPattern;
-    }
-
-    public int getDefaultRangeDays() {
-        return defaultRangeDays;
-    }
-
-    public void setDefaultRangeDays(int defaultRangeDays) {
-        this.defaultRangeDays = defaultRangeDays;
-    }
-
-    public int getPageSize() {
-        return pageSize;
-    }
-
-    public void setPageSize(int pageSize) {
-        this.pageSize = pageSize;
-    }
-
-    public int getMaxEventsToScan() {
-        return maxEventsToScan;
-    }
-
-    public void setMaxEventsToScan(int maxEventsToScan) {
-        this.maxEventsToScan = maxEventsToScan;
-    }
-
-    public Long getDefaultTaskSlaMs() {
-        return defaultTaskSlaMs;
-    }
-
-    public void setDefaultTaskSlaMs(Long defaultTaskSlaMs) {
-        this.defaultTaskSlaMs = defaultTaskSlaMs;
-    }
 }

+ 7 - 38
src/main/java/cn/seecoder/analysis/d4/LogEvent.java

@@ -2,57 +2,26 @@ package cn.seecoder.analysis.d4;
 
 import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
 import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Getter;
+import lombok.Setter;
 
 import java.util.Map;
 
+@Getter
+@Setter
 @JsonIgnoreProperties(ignoreUnknown = true)
 public class LogEvent {
 
     private String bizName;
 
-    private String businessInfo;
-
-    private String logLevel;
-
-    private String traceId;
-
-    public String getBizName() {
-        return bizName;
-    }
-
-    public void setBizName(String bizName) {
-        this.bizName = bizName;
-    }
-
-    @JsonProperty("business_info")
-    public String getBusinessInfo() {
-        return businessInfo;
-    }
-
     @JsonProperty("business_info")
-    public void setBusinessInfo(String businessInfo) {
-        this.businessInfo = businessInfo;
-    }
-
-    @JsonProperty("log_level")
-    public String getLogLevel() {
-        return logLevel;
-    }
+    private String businessInfo;
 
     @JsonProperty("log_level")
-    public void setLogLevel(String logLevel) {
-        this.logLevel = logLevel;
-    }
-
-    @JsonProperty("trace_id")
-    public String getTraceId() {
-        return traceId;
-    }
+    private String logLevel;
 
     @JsonProperty("trace_id")
-    public void setTraceId(String traceId) {
-        this.traceId = traceId;
-    }
+    private String traceId;
 
     public Map<String, String> parsedBusinessInfo() {
         return BusinessInfoParser.parse(businessInfo);

+ 47 - 0
test-data/README.md

@@ -0,0 +1,47 @@
+# D4 测试日志数据
+
+文件:
+
+- `d4-metrics-sample-logs.txt`
+
+这批日志覆盖以下 D4 事件:
+
+- `D4_TASK_ASSIGNED`
+- `D4_TASK_COMPLETED`
+- `D4_COLLAB_EFFECTIVE`
+- `D4_COLLAB_CONFLICT_CREATED`
+- `D4_COLLAB_CONFLICT_RESOLVED`
+- `D4_COMM_MESSAGE_SENT`
+- `D4_COMM_MESSAGE_RESPONSE`
+
+## 预期统计
+
+如果查询范围覆盖 `2026-03-29T00:00:00Z` 到 `2026-04-01T00:00:00Z`,且不加 `projectId` 过滤:
+
+- 分配任务数:3
+- 完成任务数:4
+- 有效协作次数:4
+- 消息发送数:3
+- 消息响应数:3
+- 冲突创建数:2
+  - 其中有 1 条 `ERROR` 是同一分支合并冲突的排障日志,当前后端会自动排除,不计入指标
+- 冲突解决数:1
+
+如果加 `projectId=50`:
+
+- 分配任务数:2
+- 完成任务数:3
+- 有效协作次数:3
+- 消息发送数:2
+- 消息响应数:2
+- 冲突创建数:2
+  - 后端指标实际计数为 2 条中的 1 条 WARN 分支冲突 + 1 条文件评审返工冲突
+  - 同 trace 的 `ERROR` 排障日志会被排除
+- 冲突解决数:1
+
+## 示例接口
+
+```bash
+curl "http://localhost:8080/api/d4/metrics?from=2026-03-29T00:00:00Z&to=2026-04-01T00:00:00Z"
+curl "http://localhost:8080/api/d4/metrics?from=2026-03-29T00:00:00Z&to=2026-04-01T00:00:00Z&projectId=50"
+```

+ 21 - 0
test-data/d4-metrics-sample-logs.txt

@@ -0,0 +1,21 @@
+2026-03-29 23:15:41.899|SeecoderLog|http-nio-8080-exec-9|INFO|cn.seecoder.web.service.impl.code_review.FileReviewServiceImpl|D4_TASK_ASSIGNED|0a2a00a5177479734188100011|0|taskType=fileReview|taskId=1|projectId=50|creatorId=1008|reviewerCount=1|createdTs=1774797341887
+2026-03-30 00:05:12.310|SeecoderLog|http-nio-8080-exec-3|INFO|cn.seecoder.web.service.impl.code_review.FileReviewServiceImpl|D4_TASK_COMPLETED|0a2a00a5177480031231000012|0|taskType=fileReview|taskId=1|projectId=50|reviewerId=1009|taskDurationMs=29700423|completedTs=1774800312310
+2026-03-30 00:05:12.315|SeecoderLog|http-nio-8080-exec-3|INFO|cn.seecoder.web.service.impl.code_review.FileReviewServiceImpl|D4_COLLAB_EFFECTIVE|0a2a00a5177480031231500013|0|source=fileReviewPass|taskId=1|projectId=50|reviewerId=1009|ts=1774800312315
+2026-03-30 01:07:34.422|SeecoderLog|http-nio-8080-exec-9|INFO|cn.seecoder.web.service.impl.message.MessageServiceImpl|D4_COMM_MESSAGE_SENT|0a2a00b4177480405440900011|0|messageId=201|creatorId=-1|receiverId=1008|linkTo=/project/50/filereviewdetail?fileReviewId=1|ts=1774804054416
+2026-03-30 01:09:02.118|SeecoderLog|http-nio-8080-exec-5|INFO|cn.seecoder.web.service.impl.message.MessageServiceImpl|D4_COMM_MESSAGE_RESPONSE|0a2a00b4177480542118000012|0|messageId=201|creatorId=-1|receiverId=1008|responseMs=87696|readTs=1774804142118
+2026-03-30 09:20:18.500|SeecoderLog|http-nio-8080-exec-7|INFO|cn.seecoder.web.service.impl.code_review.FileReviewServiceImpl|D4_TASK_ASSIGNED|0a2a00a5177483491850000014|0|taskType=fileReview|taskId=2|projectId=50|creatorId=1008|reviewerCount=2|createdTs=1774833618500
+2026-03-30 10:42:03.015|SeecoderLog|http-nio-8080-exec-4|WARN|cn.seecoder.web.service.impl.code_review.FileReviewServiceImpl|D4_COLLAB_CONFLICT_CREATED|0a2a00a5177483983015000015|0|conflictType=fileReviewRework|taskId=2|projectId=50|reviewerId=1010|reason=needRework|ts=1774838523015
+2026-03-30 13:30:46.233|SeecoderLog|http-nio-8080-exec-2|INFO|cn.seecoder.web.service.impl.code_review.FileReviewServiceImpl|D4_TASK_COMPLETED|0a2a00a5177484994623300016|0|taskType=fileReview|taskId=2|projectId=50|reviewerId=1010|taskDurationMs=15027633|completedTs=1774848646233
+2026-03-30 13:30:46.237|SeecoderLog|http-nio-8080-exec-2|INFO|cn.seecoder.web.service.impl.code_review.FileReviewServiceImpl|D4_COLLAB_EFFECTIVE|0a2a00a5177484994623700017|0|source=fileReviewPass|taskId=2|projectId=50|reviewerId=1010|ts=1774848646237
+2026-03-30 13:30:46.241|SeecoderLog|http-nio-8080-exec-2|INFO|cn.seecoder.web.service.impl.code_review.FileReviewServiceImpl|D4_COLLAB_CONFLICT_RESOLVED|0a2a00a5177484994624100018|0|conflictType=fileReviewRework|taskId=2|projectId=50|resolverId=1010|ts=1774848646241
+2026-03-30 14:18:09.808|SeecoderLog|http-nio-8080-exec-6|INFO|cn.seecoder.web.service.impl.message.MessageServiceImpl|D4_COMM_MESSAGE_SENT|0a2a00b4177485278980800019|0|messageId=202|creatorId=1008|receiverId=1010|linkTo=/project/50/filereviewdetail?fileReviewId=2|ts=1774851489808
+2026-03-30 15:03:29.911|SeecoderLog|http-nio-8080-exec-8|INFO|cn.seecoder.web.service.impl.message.MessageServiceImpl|D4_COMM_MESSAGE_RESPONSE|0a2a00b4177485550991100020|0|messageId=202|creatorId=1008|receiverId=1010|responseMs=2720011|readTs=1774854209911
+2026-03-30 16:10:11.021|SeecoderLog|http-nio-8080-exec-1|INFO|cn.seecoder.web.service.impl.code_review.BranchReviewServiceImpl|D4_TASK_COMPLETED|0a2a00c1177485951102100021|0|taskType=branchReview|taskId=301|projectId=50|operatorId=1008|taskDurationMs=5400000|completedTs=1774858211021
+2026-03-30 16:10:11.028|SeecoderLog|http-nio-8080-exec-1|INFO|cn.seecoder.web.service.impl.code_review.BranchReviewServiceImpl|D4_COLLAB_EFFECTIVE|0a2a00c1177485951102800022|0|source=branchReviewMerge|taskId=301|projectId=50|operatorId=1008|ts=1774858211028
+2026-03-30 17:25:44.605|SeecoderLog|http-nio-8080-exec-10|WARN|cn.seecoder.web.service.impl.code_review.BranchReviewServiceImpl|D4_COLLAB_CONFLICT_CREATED|0a2a00c1177486404460500023|0|conflictType=branchMerge|taskId=302|projectId=50|operatorId=1009|reason=SeecoderGitlabException|ts=1774862744605
+2026-03-30 17:25:44.611|SeecoderLog|http-nio-8080-exec-10|ERROR|cn.seecoder.web.service.impl.code_review.BranchReviewServiceImpl|D4_COLLAB_CONFLICT_CREATED|0a2a00c1177486404461100024|0|conflictType=branchMerge|taskId=302|projectId=50|operatorId=1009|reason=SeecoderGitlabException|ts=1774862744611
+2026-03-31 08:02:17.184|SeecoderLog|http-nio-8080-exec-6|INFO|cn.seecoder.web.service.impl.code_review.FileReviewServiceImpl|D4_TASK_ASSIGNED|0a2a00a5177491663718400025|0|taskType=fileReview|taskId=3|projectId=51|creatorId=1011|reviewerCount=1|createdTs=1774915337184
+2026-03-31 09:44:00.002|SeecoderLog|http-nio-8080-exec-6|INFO|cn.seecoder.web.service.impl.code_review.FileReviewServiceImpl|D4_TASK_COMPLETED|0a2a00a5177492274000200026|0|taskType=fileReview|taskId=3|projectId=51|reviewerId=1012|taskDurationMs=6102818|completedTs=1774921440002
+2026-03-31 09:44:00.008|SeecoderLog|http-nio-8080-exec-6|INFO|cn.seecoder.web.service.impl.code_review.FileReviewServiceImpl|D4_COLLAB_EFFECTIVE|0a2a00a5177492274000800027|0|source=fileReviewPass|taskId=3|projectId=51|reviewerId=1012|ts=1774921440008
+2026-03-31 10:05:39.777|SeecoderLog|http-nio-8080-exec-9|INFO|cn.seecoder.web.service.impl.message.MessageServiceImpl|D4_COMM_MESSAGE_SENT|0a2a00b4177492403977700028|0|messageId=203|creatorId=1011|receiverId=1012|linkTo=/project/51/filereviewdetail?fileReviewId=3|ts=1774922739777
+2026-03-31 10:06:10.901|SeecoderLog|http-nio-8080-exec-9|INFO|cn.seecoder.web.service.impl.message.MessageServiceImpl|D4_COMM_MESSAGE_RESPONSE|0a2a00b4177492407090100029|0|messageId=203|creatorId=1011|receiverId=1012|responseMs=31124|readTs=1774922770901