Cloud Bits: Beyond Pings – Checks for Cloud-Native Reliability

a close up of a computer screen with a line of ecg

Understanding the problem

Health-checks vs deep-checks

Seeing things in action

Using Spring Boot

    public Health health() {
        try {
            paymentRepository.count();
            return Health.up()
                .withDetail("database", "PostgreSQL connection healthy")
                .withDetail("service", "Payment service operational")
                .build();
        } catch (Exception e) {
            return Health.down()
                .withDetail("database", "PostgreSQL connection failed")
                .withDetail("Error", e.getMessage())
                .withDetail("service", "Payment service not operational")
                .build();
        }
    }
public Health health() {
        try {
            // First, verify Payment Service deep check
            PaymentDeepCheckResponse paymentDeepCheckResponse = restClient.get()
                .uri(paymentDeepCheckUrl)
                .retrieve()
                .body(PaymentDeepCheckResponse.class);
            if (!"UP".equals(Objects.requireNonNull(paymentDeepCheckResponse).status())) {
                return Health.down()
                    .withDetail("paymentDeepCheck", "Payment Service deep check reported DOWN status")
                    .withDetail("service", "Order service deep check failed")
                    .build();
            }
            // Perform a deep check by creating a test order
            UUID testOrderId = orderService.createOrder(
                testPrefix + UUID.randomUUID(),
                100.0,
                UUID.randomUUID());
            return Health.up()
                .withDetail("id for test order", testOrderId.toString())
                .withDetail("service", "Order service deep check passed")
                .withDetail("paymentDeepCheck", paymentDeepCheckResponse.details.service)
                .build();
        } catch (Exception e) {
            return Health.down()
                .withDetail("deepCheck", "Failed to create test order")
                .withDetail("Error", e.getMessage())
                .withDetail("service", "Order service deep check failed")
                .build();
        }
    }
management:
  endpoints:
    web:
      exposure:
        include: health
  endpoint:
    health:
      show-details: always
      group:
        liveness:
          include: orderServiceHealth
          show-details: always
        deep:
          include: orderServiceDeepCheck
          show-details: always

Using Kubernetes

readinessProbe:
  httpGet:
    port: 8001
    path: /actuator/health/orderServiceDeepCheck
  initialDelaySeconds: 30 # Initial wait period
  periodSeconds: 10 # Interval between checks
livenessProbe:
  httpGet:
    port: 8001
    path: /actuator/health/orderServiceHealth
  initialDelaySeconds: 60
  periodSeconds: 30
public class FaultInjectionFilter extends OncePerRequestFilter {

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
        throws ServletException, IOException {
        response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
        response.setContentType(APPLICATION_JSON_VALUE);
        response.getWriter().write("{\"status\":\"FAILURE\",\"failureReason\":\"Injected failure\"}");
    }
}

Leave a Reply

Your email address will not be published. Required fields are marked *