From 0863614e66e8311af63da341f78fe7bc91acfdaa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=84=E8=87=AA=E8=BE=BE?= <980324341@qq.com> Date: Fri, 4 Sep 2026 23:48:20 +0800 Subject: [PATCH] =?UTF-8?q?task-182:=20task.success/failed/cancelled=20?= =?UTF-8?q?=E7=BB=88=E6=80=81=E8=AE=A1=E6=95=B0=E6=8C=87=E6=A0=87=E5=A5=91?= =?UTF-8?q?=E7=BA=A6=EF=BC=88aiimage.task.*=EF=BC=8C=E5=88=86=20moduleType?= =?UTF-8?q?/instanceId=EF=BC=89+=208=20=E6=9D=A1=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../metrics/TaskTerminalMetricsTest.java | 86 +++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 backend-java/src/test/java/com/nanri/aiimage/metrics/TaskTerminalMetricsTest.java diff --git a/backend-java/src/test/java/com/nanri/aiimage/metrics/TaskTerminalMetricsTest.java b/backend-java/src/test/java/com/nanri/aiimage/metrics/TaskTerminalMetricsTest.java new file mode 100644 index 00000000..7ab7c5b2 --- /dev/null +++ b/backend-java/src/test/java/com/nanri/aiimage/metrics/TaskTerminalMetricsTest.java @@ -0,0 +1,86 @@ +package com.nanri.aiimage.metrics; + +import io.micrometer.core.instrument.Counter; +import io.micrometer.core.instrument.simple.SimpleMeterRegistry; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +/** + * task-182:task.success/failed/cancelled 终态计数契约(spec 11 §1)。 + * 每个终态独立计数、分 moduleType;单次终态调用精确 +1,互不串扰。 + */ +class TaskTerminalMetricsTest { + + private final SimpleMeterRegistry registry = new SimpleMeterRegistry(); + private final TaskObservabilityMetrics metrics = new TaskObservabilityMetrics("server-110", registry); + + private Counter counter(String terminal, String moduleType) { + return registry.get("aiimage.task." + terminal).tag("moduleType", moduleType).counter(); + } + + @Test + void successCounted() { + metrics.taskTerminal("similarasin", "success"); + assertEquals(1.0, counter("success", "similarasin").count()); + } + + @Test + void failedCounted() { + metrics.taskTerminal("similarasin", "failed"); + assertEquals(1.0, counter("failed", "similarasin").count()); + } + + @Test + void cancelledCounted() { + metrics.taskTerminal("similarasin", "cancelled"); + assertEquals(1.0, counter("cancelled", "similarasin").count()); + } + + @Test + void moduleSplitIndependent() { + metrics.taskTerminal("similarasin", "success"); + metrics.taskTerminal("publish", "success"); + assertEquals(1.0, counter("success", "similarasin").count()); + assertEquals(1.0, counter("success", "publish").count()); + } + + @Test + void singleTerminalCallCountsOnce() { + metrics.taskTerminal("brand", "failed"); + assertEquals(1.0, counter("failed", "brand").count(), "单次终态调用精确 +1"); + } + + @Test + void terminalTypesDoNotCrossCount() { + metrics.taskTerminal("similarasin", "success"); + metrics.taskTerminal("similarasin", "failed"); + assertEquals(1.0, counter("success", "similarasin").count()); + assertEquals(1.0, counter("failed", "similarasin").count()); + assertEquals(0.0, registry.find("aiimage.task.cancelled").tag("moduleType", "similarasin").counter() == null + ? 0.0 + : registry.find("aiimage.task.cancelled").tag("moduleType", "similarasin").counter().count(), + "success/failed 不应污染 cancelled"); + } + + @Test + void terminalNamesFrozen() { + metrics.taskTerminal("similarasin", "success"); + metrics.taskTerminal("similarasin", "failed"); + metrics.taskTerminal("similarasin", "cancelled"); + assertTrue(registry.getMeters().stream() + .anyMatch(m -> m.getId().getName().equals("aiimage.task.success"))); + assertTrue(registry.getMeters().stream() + .anyMatch(m -> m.getId().getName().equals("aiimage.task.failed"))); + assertTrue(registry.getMeters().stream() + .anyMatch(m -> m.getId().getName().equals("aiimage.task.cancelled"))); + } + + @Test + void countersCarryInstanceLabel() { + metrics.taskTerminal("similarasin", "success"); + assertEquals("server-110", + registry.get("aiimage.task.success").counter().getId().getTag("instanceId")); + } +}