From a0c93fa1c1e05bdf9aebd831c67347e0219cbd66 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Mon, 10 Aug 2026 18:50:48 +0900 Subject: [PATCH 1/5] test(analytics): define terminal conversion success rate --- .../viewer/api/KpiSnapshotResponseTest.java | 37 ++++++++++++++++++- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/src/test/java/com/clearfolio/viewer/api/KpiSnapshotResponseTest.java b/src/test/java/com/clearfolio/viewer/api/KpiSnapshotResponseTest.java index 1e2dd385c..eba5afc20 100644 --- a/src/test/java/com/clearfolio/viewer/api/KpiSnapshotResponseTest.java +++ b/src/test/java/com/clearfolio/viewer/api/KpiSnapshotResponseTest.java @@ -29,11 +29,44 @@ void fromSkipsPreviewTimingWhenSucceededJobsDoNotHaveCompleteTimestamps() { assertNull(response.p95TimeToPreviewMs()); } + @Test + void conversionSuccessRateUsesOnlyTerminalOutcomes() { + KpiSnapshotResponse response = KpiSnapshotResponse.from(List.of( + job(ConversionJobStatus.SUCCEEDED), + job(ConversionJobStatus.SUCCEEDED), + job(ConversionJobStatus.FAILED), + job(ConversionJobStatus.SUBMITTED), + job(ConversionJobStatus.PROCESSING) + )); + + assertEquals(5, response.totalJobs()); + assertEquals(1, response.submittedJobs()); + assertEquals(1, response.processingJobs()); + assertEquals(2, response.succeededJobs()); + assertEquals(1, response.failedJobs()); + assertEquals(2.0 / 3.0, response.conversionSuccessRate(), 1.0e-12); + } + + @Test + void conversionSuccessRateIsZeroUntilOneJobReachesATerminalOutcome() { + KpiSnapshotResponse response = KpiSnapshotResponse.from(List.of( + job(ConversionJobStatus.SUBMITTED), + job(ConversionJobStatus.PROCESSING) + )); + + assertEquals(0.0, response.conversionSuccessRate()); + } + private ConversionJob succeededJob(Instant startedAt, Instant completedAt) { - ConversionJob job = mock(ConversionJob.class); - when(job.getStatus()).thenReturn(ConversionJobStatus.SUCCEEDED); + ConversionJob job = job(ConversionJobStatus.SUCCEEDED); when(job.getStartedAt()).thenReturn(startedAt); when(job.getCompletedAt()).thenReturn(completedAt); + return job; + } + + private ConversionJob job(ConversionJobStatus status) { + ConversionJob job = mock(ConversionJob.class); + when(job.getStatus()).thenReturn(status); when(job.isDeadLettered()).thenReturn(false); return job; } From c27845fc29fa0d0fa3078ee72f7844867c54bf12 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Mon, 10 Aug 2026 18:59:48 +0900 Subject: [PATCH 2/5] fix(analytics): exclude in-flight jobs from success denominator --- .../java/com/clearfolio/viewer/api/KpiSnapshotResponse.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/clearfolio/viewer/api/KpiSnapshotResponse.java b/src/main/java/com/clearfolio/viewer/api/KpiSnapshotResponse.java index a9a29b76a..fe0e4f5eb 100644 --- a/src/main/java/com/clearfolio/viewer/api/KpiSnapshotResponse.java +++ b/src/main/java/com/clearfolio/viewer/api/KpiSnapshotResponse.java @@ -17,7 +17,7 @@ * @param succeededJobs jobs with a ready preview artifact * @param failedJobs jobs in failed state * @param deadLetteredJobs failed jobs that exhausted retry handling - * @param conversionSuccessRate succeeded jobs divided by total jobs + * @param conversionSuccessRate succeeded jobs divided by terminal succeeded/failed jobs * @param p95TimeToPreviewMs p95 processing time for succeeded jobs with timestamps */ public record KpiSnapshotResponse( @@ -64,7 +64,8 @@ public static KpiSnapshotResponse from(List jobs) { } int total = jobs.size(); - double successRate = total == 0 ? 0.0 : (double) succeeded / total; + int terminal = succeeded + failed; + double successRate = terminal == 0 ? 0.0 : (double) succeeded / terminal; return new KpiSnapshotResponse( total, submitted, From 1fa3875ffac2392ce795ad6f0e05b16388c7eef1 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Mon, 10 Aug 2026 19:05:00 +0900 Subject: [PATCH 3/5] test(analytics): align controller KPI expectation with terminal outcomes --- .../clearfolio/viewer/controller/AnalyticsControllerTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/com/clearfolio/viewer/controller/AnalyticsControllerTest.java b/src/test/java/com/clearfolio/viewer/controller/AnalyticsControllerTest.java index 7752589e0..da895f917 100644 --- a/src/test/java/com/clearfolio/viewer/controller/AnalyticsControllerTest.java +++ b/src/test/java/com/clearfolio/viewer/controller/AnalyticsControllerTest.java @@ -84,7 +84,7 @@ void kpiSnapshotSummarizesCurrentJobStates() { .jsonPath("$.succeededJobs").isEqualTo(1) .jsonPath("$.failedJobs").isEqualTo(1) .jsonPath("$.deadLetteredJobs").isEqualTo(1) - .jsonPath("$.conversionSuccessRate").value(value -> assertEquals(0.25, (Double) value)) + .jsonPath("$.conversionSuccessRate").value(value -> assertEquals(0.5, (Double) value)) .jsonPath("$.p95TimeToPreviewMs").value(value -> { assertNotNull(value); assertTrue(((Number) value).longValue() >= 0L); From c568532a4a0f11376aa0149c2e8a7e335deff554 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Mon, 10 Aug 2026 19:07:38 +0900 Subject: [PATCH 4/5] docs(analytics): define terminal conversion success rate --- .../java/com/clearfolio/viewer/analytics/KpiSnapshotRecord.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/clearfolio/viewer/analytics/KpiSnapshotRecord.java b/src/main/java/com/clearfolio/viewer/analytics/KpiSnapshotRecord.java index 65e44d4a9..5a91a33ef 100644 --- a/src/main/java/com/clearfolio/viewer/analytics/KpiSnapshotRecord.java +++ b/src/main/java/com/clearfolio/viewer/analytics/KpiSnapshotRecord.java @@ -14,7 +14,7 @@ * @param succeededJobs succeeded jobs in the snapshot * @param failedJobs failed jobs in the snapshot * @param deadLetteredJobs dead-lettered jobs in the snapshot - * @param conversionSuccessRate succeeded jobs divided by total jobs + * @param conversionSuccessRate succeeded jobs divided by terminal succeeded/failed jobs * @param p95TimeToPreviewMs p95 time to preview, when available */ public record KpiSnapshotRecord( From 99e7c79142ce8e10ad0ef6880ab6d4fa8826c113 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Mon, 10 Aug 2026 19:08:27 +0900 Subject: [PATCH 5/5] docs(analytics): align exported KPI success semantics --- .../com/clearfolio/viewer/api/KpiSnapshotExportResponse.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/clearfolio/viewer/api/KpiSnapshotExportResponse.java b/src/main/java/com/clearfolio/viewer/api/KpiSnapshotExportResponse.java index 82babf93a..b5c40a295 100644 --- a/src/main/java/com/clearfolio/viewer/api/KpiSnapshotExportResponse.java +++ b/src/main/java/com/clearfolio/viewer/api/KpiSnapshotExportResponse.java @@ -15,7 +15,7 @@ * @param succeededJobs succeeded jobs in the exported snapshot * @param failedJobs failed jobs in the exported snapshot * @param deadLetteredJobs dead-lettered jobs in the exported snapshot - * @param conversionSuccessRate succeeded jobs divided by total jobs + * @param conversionSuccessRate succeeded jobs divided by terminal succeeded/failed jobs * @param p95TimeToPreviewMs p95 time to preview, when available */ public record KpiSnapshotExportResponse(