FlashSaleQueueMetrics.java
package com.ecommerce.trade.infrastructure.observability;
import com.ecommerce.trade.infrastructure.persistence.mapper.FlashSaleOrderRequestMapper;
import io.micrometer.core.instrument.Counter;
import io.micrometer.core.instrument.Gauge;
import io.micrometer.core.instrument.MeterRegistry;
import org.springframework.stereotype.Component;
import java.time.Clock;
import java.time.Duration;
import java.time.Instant;
@Component
public class FlashSaleQueueMetrics {
private final FlashSaleOrderRequestMapper requestMapper;
private final Clock clock;
private final Counter succeeded;
private final Counter failed;
public FlashSaleQueueMetrics(
MeterRegistry meterRegistry,
FlashSaleOrderRequestMapper requestMapper,
Clock clock) {
this.requestMapper = requestMapper;
this.clock = clock;
succeeded = completedCounter(meterRegistry, "order_created");
failed = completedCounter(meterRegistry, "failed");
Gauge.builder("ecommerce.flash.sale.processing.pending", requestMapper,
FlashSaleOrderRequestMapper::countProcessing)
.description("Accepted flash-sale requests still awaiting a terminal order result")
.tag("service", "trade-service")
.register(meterRegistry);
Gauge.builder("ecommerce.flash.sale.processing.oldest.age.seconds", this,
FlashSaleQueueMetrics::oldestAgeSeconds)
.description("Age of the oldest accepted flash-sale request awaiting a terminal result")
.tag("service", "trade-service")
.register(meterRegistry);
Gauge.builder("ecommerce.flash.sale.processing.needs.attention", requestMapper,
mapper -> mapper.countByStatus("NEEDS_ATTENTION"))
.description("Flash-sale order requests that exhausted automatic recovery")
.tag("service", "trade-service")
.register(meterRegistry);
}
public void recordCompleted(boolean successful) {
if (successful) {
succeeded.increment();
} else {
failed.increment();
}
}
private double oldestAgeSeconds() {
Instant oldest = requestMapper.selectOldestProcessingCreatedAt();
return oldest == null ? 0 : Math.max(0, Duration.between(oldest, clock.instant()).toMillis() / 1000.0);
}
private Counter completedCounter(MeterRegistry meterRegistry, String result) {
return Counter.builder("ecommerce.flash.sale.processing.completed")
.description("Terminal flash-sale order processing results")
.tag("service", "trade-service")
.tag("result", result)
.register(meterRegistry);
}
}