task-189: 指标命名一致性契约(aiimage.* 前缀、全小写点分、全量名快照对齐 spec11 §1、无拼写漂移)+ 8 条测试
This commit is contained in:
+124
@@ -0,0 +1,124 @@
|
||||
package com.nanri.aiimage.metrics;
|
||||
|
||||
import io.micrometer.core.instrument.simple.SimpleMeterRegistry;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
/**
|
||||
* task-189:指标命名一致性契约(spec 11 §1 标准名)。
|
||||
* 全部指标名 aiimage.* 前缀、小写点分、无拼写漂移;recorder 全量指标名快照与 spec 对齐。
|
||||
*/
|
||||
class MetricNamingConsistencyTest {
|
||||
|
||||
private final SimpleMeterRegistry registry = new SimpleMeterRegistry();
|
||||
private final TaskObservabilityMetrics metrics = new TaskObservabilityMetrics("server-110", registry);
|
||||
|
||||
private void createAllMetrics() {
|
||||
metrics.taskCreated("similarasin");
|
||||
metrics.taskRunningDelta("similarasin", 1);
|
||||
metrics.taskTerminal("similarasin", "success");
|
||||
metrics.taskTerminal("similarasin", "failed");
|
||||
metrics.taskTerminal("similarasin", "cancelled");
|
||||
metrics.taskDuration("similarasin", 1L);
|
||||
metrics.taskHeartbeatAge("similarasin", 1L);
|
||||
metrics.fileJobState("similarasin", "pending");
|
||||
metrics.fileJobState("similarasin", "running");
|
||||
metrics.fileJobState("similarasin", "success");
|
||||
metrics.fileJobState("similarasin", "failed");
|
||||
metrics.fileJobState("similarasin", "retry");
|
||||
metrics.fileJobDuration("similarasin", 1L);
|
||||
metrics.upload("similarasin", 1L, 1L, true);
|
||||
metrics.upload("similarasin", 1L, 1L, false);
|
||||
metrics.disk("/tmp/x", 1L, 1L);
|
||||
}
|
||||
|
||||
@Test
|
||||
void allNamesHaveAiimagePrefix() {
|
||||
createAllMetrics();
|
||||
for (String name : names()) {
|
||||
assertTrue(name.startsWith("aiimage."), "指标应带 aiimage. 前缀: " + name);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void allNamesLowercaseDotSegments() {
|
||||
createAllMetrics();
|
||||
for (String name : names()) {
|
||||
assertTrue(name.equals(name.toLowerCase()), "指标名应全小写: " + name);
|
||||
assertTrue(!name.contains(".."), "指标名不应有连续点: " + name);
|
||||
assertTrue(!name.endsWith("."), "指标名不应以点结尾: " + name);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void taskFamilyNamesFrozen() {
|
||||
createAllMetrics();
|
||||
for (String n : List.of("aiimage.task.created", "aiimage.task.running", "aiimage.task.success",
|
||||
"aiimage.task.failed", "aiimage.task.cancelled", "aiimage.task.duration",
|
||||
"aiimage.task.heartbeat.age")) {
|
||||
assertTrue(names().contains(n), "缺少 spec 任务指标名: " + n);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void fileJobFamilyNamesFrozen() {
|
||||
createAllMetrics();
|
||||
for (String n : List.of("aiimage.file-job.pending", "aiimage.file-job.running",
|
||||
"aiimage.file-job.success", "aiimage.file-job.failed", "aiimage.file-job.retry",
|
||||
"aiimage.file-job.duration")) {
|
||||
assertTrue(names().contains(n), "缺少 spec file-job 指标名: " + n);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void noTypoDriftSnapshot() {
|
||||
createAllMetrics();
|
||||
Set<String> names = names();
|
||||
// 与 spec 11 §1 允许集完全一致:不允许出现拼写漂移产生的多余名字
|
||||
Set<String> allowed = Set.of(
|
||||
"aiimage.task.created", "aiimage.task.running", "aiimage.task.success",
|
||||
"aiimage.task.failed", "aiimage.task.cancelled", "aiimage.task.duration",
|
||||
"aiimage.task.heartbeat.age",
|
||||
"aiimage.file-job.pending", "aiimage.file-job.running", "aiimage.file-job.success",
|
||||
"aiimage.file-job.failed", "aiimage.file-job.retry", "aiimage.file-job.duration",
|
||||
"aiimage.upload.duration", "aiimage.upload.size", "aiimage.upload.result",
|
||||
"aiimage.upload.result.success", "aiimage.upload.result.failure",
|
||||
"aiimage.tmpdisk.capacity", "aiimage.tmpdisk.used");
|
||||
Set<String> unexpected = names.stream().filter(n -> !allowed.contains(n)).collect(Collectors.toSet());
|
||||
assertEquals(Set.of(), unexpected, "不应出现 spec 之外的漂移指标名");
|
||||
}
|
||||
|
||||
@Test
|
||||
void snapshotAllMetricsCaptured() {
|
||||
createAllMetrics();
|
||||
assertTrue(names().size() >= 19, "全量指标快照应覆盖任务/文件/上传/磁盘族,实际 " + names().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
void caseConsistentAcrossFamilies() {
|
||||
createAllMetrics();
|
||||
long upperCount = names().stream().filter(n -> n.chars().anyMatch(Character::isUpperCase)).count();
|
||||
assertEquals(0, upperCount, "指标名应统一小写");
|
||||
}
|
||||
|
||||
@Test
|
||||
void metricNamingStableAcrossRepeatedCreation() {
|
||||
createAllMetrics();
|
||||
Set<String> first = names();
|
||||
TaskObservabilityMetrics metrics2 = new TaskObservabilityMetrics("server-121", registry);
|
||||
metrics2.taskCreated("similarasin");
|
||||
Set<String> second = names();
|
||||
assertEquals(first, second, "新增实例不应改变既有指标名集合");
|
||||
}
|
||||
|
||||
private Set<String> names() {
|
||||
return registry.getMeters().stream()
|
||||
.map(m -> m.getId().getName()).collect(Collectors.toSet());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user