import io.micrometer.core.instrument.Counter; import io.micrometer.core.instrument.Gauge; import io.micrometer.core.instrument.MeterRegistry; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.HashOperations; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; import java.util.Map; @Service public class StatusDelayMonitorService { private static final String HASH_NAME = "registros_pendentes"; private static final long LIMITE_ATRASO_MS = 3_600_000; // 1 hora private final Counter atrasoCounter; private final HashOperations hashOps; @Autowired public StatusDelayMonitorService(RedisTemplate redisTemplate, MeterRegistry meterRegistry) { this.hashOps = redisTemplate.opsForHash(); this.atrasoCounter = Counter.builder("registro.atrasos") .description("Eventos que excederam tempo máximo aguardando status B") .register(meterRegistry); // Gauge que retorna o tamanho diretamente do Redis, sem variável intermediária Gauge.builder("registros.pendentes", this, s -> s.getPendentesCount()) .description("Quantidade de registros pendentes em tempo real aguardando status B") .register(meterRegistry); } // 1. Registrar chegada com status A public void onStatusA(String registroId) { hashOps.put(HASH_NAME, registroId, String.valueOf(System.currentTimeMillis())); } // 2. Remover ao chegar status B public void onStatusB(String registroId) { hashOps.delete(HASH_NAME, registroId); } // 3. Verificação periódica de atrasos @Scheduled(fixedRate = 60_000) public void verificarAtrasos() { long now = System.currentTimeMillis(); Map registros = hashOps.entries(HASH_NAME); for (Map.Entry entry : registros.entrySet()) { String id = entry.getKey(); long timestamp = Long.parseLong(entry.getValue()); if ((now - timestamp) > LIMITE_ATRASO_MS) { // Esta métrica será utilizada pelo sistema de monitoramento para disparar alarmes de atraso. atrasoCounter.increment(); // Opcional: hashOps.delete(HASH_NAME, id); } } } // Micrometer chama este método para atualizar a Gauge public int getPendentesCount() { return (int) hashOps.size(HASH_NAME); } }