This commit is contained in:
2026-08-25 14:46:06 +08:00
parent 5abc7543ae
commit f325d57fc1
106 changed files with 3682 additions and 450 deletions
@@ -0,0 +1,54 @@
package com.baiyue.eventbridge.metrics;
import com.baiyue.common.event.EventTypes;
import com.baiyue.eventbridge.mapper.BridgeInboxMapper;
import io.micrometer.core.instrument.simple.SimpleMeterRegistry;
import org.junit.jupiter.api.Test;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
class EventBridgeInboxMetricsSamplerTest {
@Test
void samplesDatabaseOnceAndServesCachedLowCardinalityGauges() {
BridgeInboxMapper mapper = mock(BridgeInboxMapper.class);
SimpleMeterRegistry registry = new SimpleMeterRegistry();
InboxMetricsSnapshot known = snapshot("OVERSEAS", EventTypes.FIRST_LEG_LOADING_PLAN_COMPLETED,
7, 121.5, 2);
InboxMetricsSnapshot unknown = snapshot("region-123", "dynamic-event-123", 3, 900.0, 1);
when(mapper.observabilitySnapshots()).thenReturn(List.of(known, unknown));
EventBridgeInboxMetricsSampler sampler = new EventBridgeInboxMetricsSampler(mapper, registry);
sampler.sample();
verify(mapper).observabilitySnapshots();
assertThat(gauge(registry, EventBridgeInboxMetricsSampler.BACKLOG_METRIC,
"OVERSEAS", EventTypes.FIRST_LEG_LOADING_PLAN_COMPLETED)).isEqualTo(7.0);
assertThat(gauge(registry, EventBridgeInboxMetricsSampler.OLDEST_AGE_METRIC,
"OVERSEAS", EventTypes.FIRST_LEG_LOADING_PLAN_COMPLETED)).isEqualTo(121.5);
assertThat(gauge(registry, EventBridgeInboxMetricsSampler.DEAD_METRIC,
"OTHER", "OTHER")).isEqualTo(1.0);
verifyNoMoreInteractions(mapper);
}
private InboxMetricsSnapshot snapshot(String region, String eventType, long backlog,
double oldestAge, long dead) {
InboxMetricsSnapshot snapshot = new InboxMetricsSnapshot();
snapshot.setTargetRegion(region);
snapshot.setEventType(eventType);
snapshot.setBacklogCount(backlog);
snapshot.setOldestPendingAgeSeconds(oldestAge);
snapshot.setDeadCount(dead);
return snapshot;
}
private double gauge(SimpleMeterRegistry registry, String name, String region, String eventType) {
return registry.get(name).tags("target_region", region, "event_type", eventType).gauge().value();
}
}
@@ -0,0 +1,58 @@
package com.baiyue.eventbridge.metrics;
import com.baiyue.eventbridge.domain.BridgeInbox;
import io.micrometer.core.instrument.simple.SimpleMeterRegistry;
import io.micrometer.core.instrument.MeterRegistry;
import org.junit.jupiter.api.Test;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatCode;
import static org.mockito.Mockito.mock;
class EventBridgeMetricsTest {
@Test
void collapsesUnboundedRegionAndEventTypeLabelsToOther() {
SimpleMeterRegistry registry = new SimpleMeterRegistry();
EventBridgeMetrics metrics = new EventBridgeMetrics(registry);
BridgeInbox event = new BridgeInbox();
event.setTargetRegion("customer-controlled-region");
event.setEventType("dynamic-event-123456");
metrics.recordTransport(event, EventBridgeMetrics.TransportResult.RETRY);
assertThat(registry.get(EventBridgeMetrics.TRANSPORT_METRIC)
.tags("target_region", "OTHER", "event_type", "OTHER", "result", "RETRY")
.counter().count()).isEqualTo(1.0);
assertThat(registry.getMeters()).allSatisfy(meter -> assertThat(meter.getId().getTags())
.noneMatch(tag -> tag.getValue().contains("dynamic-event")));
assertThat(EventBridgeMetrics.eventType(null)).isEqualTo("OTHER");
}
@Test
void everyFrozenEventTypeHasABoundedTagValue() {
assertThat(Arrays.stream(com.baiyue.common.event.EventTypes.class.getFields())
.filter(field -> Modifier.isStatic(field.getModifiers()) && field.getType() == String.class)
.map(field -> {
try {
return (String) field.get(null);
} catch (IllegalAccessException exception) {
throw new AssertionError(exception);
}
})).allMatch(value -> EventBridgeMetrics.eventType(value).equals(value));
}
@Test
void metricsFailureDoesNotChangeTransportControlFlow() {
EventBridgeMetrics metrics = new EventBridgeMetrics(mock(MeterRegistry.class));
BridgeInbox event = new BridgeInbox();
event.setTargetRegion("CN");
event.setEventType(com.baiyue.common.event.EventTypes.OVERSEAS_CONTAINER_UNLOADED);
assertThatCode(() -> metrics.recordTransport(event, EventBridgeMetrics.TransportResult.RETRY))
.doesNotThrowAnyException();
}
}
@@ -0,0 +1,41 @@
package com.baiyue.eventbridge.metrics;
import com.baiyue.eventbridge.mapper.BridgeInboxMapper;
import org.apache.ibatis.annotations.Select;
import org.junit.jupiter.api.Test;
import java.nio.file.Files;
import java.nio.file.Path;
import static org.assertj.core.api.Assertions.assertThat;
class EventBridgeObservabilityContractTest {
@Test
void aggregationIsScheduledCacheInputAndUsesExistingStatusIndexBasis() throws Exception {
Select annotation = BridgeInboxMapper.class.getMethod("observabilitySnapshots")
.getAnnotation(Select.class);
String query = String.join(" ", annotation.value()).replaceAll("\\s+", " ");
String schema = Files.readString(Path.of("src/main/resources/db/event-bridge.sql"));
assertThat(query)
.contains("WHERE status IN ('RECEIVED','RETRY','PROCESSING','DEAD')")
.contains("GROUP BY target_region, event_type")
.doesNotContain("event_id AS", "customer_id AS", "last_error AS");
assertThat(schema).contains(
"KEY idx_bridge_inbox_consume (status, next_retry_at, lease_until)");
}
@Test
void developmentSloAndAlertThresholdsAreFrozenWithoutDeploymentClaim() throws Exception {
String contract = Files.readString(Path.of("docs/development-observability-slo.md"));
assertThat(contract)
.contains("99% 的新接收跨区事件在 60 秒内")
.contains("99.9% 的新接收跨区事件在 15 分钟内")
.contains("result=\"DEAD\"", "> 120", "> 900")
.contains("不表示任何环境已经部署")
.contains("idx_bridge_inbox_consume(status, next_retry_at, lease_until)")
.doesNotContain("customer_id\"", "event_id\"");
}
}