Subversion Repositories SmartDukaan

Rev

Rev 34554 | Rev 34567 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

package com.smartdukaan.cron.monitored;

import java.util.Date;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;

import io.micrometer.core.instrument.Counter;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import io.micrometer.core.instrument.MeterRegistry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Aspect to monitor execution of cron jobs via metrics and logging.
 */
@Aspect
@Component
public class CronJobMonitorAspect {

    private static final Logger log = LoggerFactory.getLogger(CronJobMonitorAspect.class);

    @Autowired
    private MeterRegistry meterRegistry;

    private final Map<String, Counter> failureCounters = new ConcurrentHashMap<>();


    /**
     * Intercept any method annotated with @Scheduled (i.e. cron jobs).
     */
    @Around("@annotation(org.springframework.scheduling.annotation.Scheduled)")
    public Object monitorCronJob(ProceedingJoinPoint joinPoint) throws Throwable {
        String methodName = joinPoint.getSignature().toShortString();
        log.info("Cron job {} started", methodName);
        long startTime = System.currentTimeMillis();

        try {
            // Proceed with the scheduled method
            Object result = joinPoint.proceed();
            long elapsed = System.currentTimeMillis() - startTime;

            log.info("Cron job {} completed successfully in {} ms", methodName, elapsed);

            try {
                meterRegistry.counter("custom.cron.success.count", "method", methodName, "status", "success")
                        .increment();
                meterRegistry.timer("custom.cron.execution.time", "method", methodName, "status", "success")
                        .record(elapsed, TimeUnit.MILLISECONDS);
            } catch (Exception e) {
                log.warn("Failed to update success metrics for {}: {}", methodName, e.toString());
            }

            return result;
        } catch (Throwable ex) {
            long elapsed = System.currentTimeMillis() - startTime;
            log.error("Cron job {} failed in {} ms: {}", methodName, elapsed, ex.toString());

            try {
                meterRegistry.counter("custom.cron.failure.count", "method", methodName, "status", "failure")
                        .increment();
                meterRegistry.timer("custom.cron.execution.time", "method", methodName, "status", "failure")
                        .record(elapsed, TimeUnit.MILLISECONDS);
            } catch (Exception e) {
                log.warn("Failed to update failure metrics for {}: {}", methodName, e.toString());
            }
            getFailureCounter(methodName).increment();
            throw ex;
        }
    }

    private Counter getFailureCounter(String methodName) {
        return failureCounters.computeIfAbsent(methodName, name ->
                Counter.builder("cron_execution_failure_count_total")
                        .description("Number of failed executions of scheduled method")
                        .tag("method", name)
                        .register(meterRegistry)
        );
    }
}