task-191: 双实例指标区分回归契约(instanceId 分桶不串、未配置归 unknown、跨实例可聚合、名集合一致)+ 8 条测试

This commit is contained in:
2026-09-04 23:53:24 +08:00
parent b468750d00
commit 75d553f99a
@@ -0,0 +1,96 @@
package com.nanri.aiimage.metrics;
import io.micrometer.core.instrument.simple.SimpleMeterRegistry;
import org.junit.jupiter.api.Test;
import java.util.stream.Collectors;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
/**
* task-191:双实例指标区分回归契约(spec 11 §1instanceId 区分 server-110/server-121)。
* 同一 registry 下两实例同模块指标按 instanceId 分桶、不串;未配置 instanceId 归 unknown
* 指标名集合稳定一致。
*/
class DualInstanceMetricTest {
private final SimpleMeterRegistry registry = new SimpleMeterRegistry();
@Test
void instance110LabelApplied() {
new TaskObservabilityMetrics("server-110", registry).taskCreated("similarasin");
assertEquals("server-110",
registry.get("aiimage.task.created").counter().getId().getTag("instanceId"));
}
@Test
void instance121LabelApplied() {
new TaskObservabilityMetrics("server-121", registry).taskCreated("similarasin");
assertEquals("server-121",
registry.get("aiimage.task.created").counter().getId().getTag("instanceId"));
}
@Test
void twoInstancesDoNotCrossCount() {
TaskObservabilityMetrics a = new TaskObservabilityMetrics("server-110", registry);
TaskObservabilityMetrics b = new TaskObservabilityMetrics("server-121", registry);
a.taskCreated("similarasin");
b.taskCreated("similarasin");
b.taskCreated("similarasin");
assertEquals(1.0, registry.get("aiimage.task.created").tag("moduleType", "similarasin")
.tag("instanceId", "server-110").counter().count());
assertEquals(2.0, registry.get("aiimage.task.created").tag("moduleType", "similarasin")
.tag("instanceId", "server-121").counter().count());
}
@Test
void unconfiguredInstanceFallsBackToUnknown() {
new TaskObservabilityMetrics(null, registry).taskCreated("brand");
assertEquals("unknown",
registry.get("aiimage.task.created").counter().getId().getTag("instanceId"));
new TaskObservabilityMetrics(" ", registry).taskCreated("brand");
}
@Test
void metricsAggregatableAcrossInstances() {
TaskObservabilityMetrics a = new TaskObservabilityMetrics("server-110", registry);
TaskObservabilityMetrics b = new TaskObservabilityMetrics("server-121", registry);
a.taskTerminal("similarasin", "success");
b.taskTerminal("similarasin", "success");
// 聚合:跨 instanceId 各 meter 求和,双实例总数应为 2
double total = registry.find("aiimage.task.success").tag("moduleType", "similarasin").counters().stream()
.mapToDouble(io.micrometer.core.instrument.Counter::count).sum();
assertEquals(2.0, total, "同模块跨实例指标可聚合");
}
@Test
void instanceLabelStableAcrossCalls() {
TaskObservabilityMetrics a = new TaskObservabilityMetrics("server-110", registry);
a.taskCreated("publish");
a.taskCreated("publish");
assertEquals(1, registry.find("aiimage.task.created").tag("moduleType", "publish")
.tag("instanceId", "server-110").counters().size(), "同实例同模块应为同一 meter");
assertEquals(2.0, registry.get("aiimage.task.created").tag("moduleType", "publish")
.tag("instanceId", "server-110").counter().count());
}
@Test
void instanceIdGetterReturnsConfiguredValue() {
assertEquals("server-121", new TaskObservabilityMetrics("server-121", null).instanceId());
assertNotEquals("", new TaskObservabilityMetrics("server-121", null).instanceId());
}
@Test
void metricNameSetIdenticalAcrossInstances() {
TaskObservabilityMetrics a = new TaskObservabilityMetrics("server-110", registry);
TaskObservabilityMetrics b = new TaskObservabilityMetrics("server-121", registry);
a.taskCreated("x");
b.taskCreated("x");
java.util.Set<String> names = registry.getMeters().stream()
.map(m -> m.getId().getName()).collect(Collectors.toSet());
assertTrue(names.contains("aiimage.task.created"));
assertEquals(1, names.size(), "仅指标名集合应一致(标签不同不算漂移)");
}
}