package de.codecentric.batch.metrics;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
import org.springframework.boot.actuate.metrics.GaugeService;
import org.springframework.util.ClassUtils;
import org.springframework.util.StopWatch;

import de.codecentric.batch.listener.LoggingListener;

/**
 * Central aspect-configuration to profile Spring Batch Jobs with AspectJ and Spring Boot Metrics.
 * 
 * @author Dennis Schulte
 */
@Aspect
public class BatchMetricsAspects {

	private static final Logger LOG = LoggerFactory.getLogger(BatchMetricsAspects.class);

	private GaugeService gaugeService;

	public BatchMetricsAspects(GaugeService gaugeService) {
		this.gaugeService = gaugeService;
	}

	@Around("execution(* org.springframework.batch.item.ItemReader.read(..))")
	public Object profileReadMethods(ProceedingJoinPoint pjp) throws Throwable {
		StopWatch stopWatch = startStopWatch();
		try {
			return pjp.proceed();
		} finally {
			gaugeService.submit(MetricsListener.GAUGE_PREFIX + getJobIdentifier() + "." + ClassUtils.getShortName(pjp.getTarget().getClass())+ ".read",
					getTotalTimeMillis(stopWatch));
		}
	}

	@Around("execution(* org.springframework.batch.item.ItemProcessor.process(..))")
	public Object profileProcessMethods(ProceedingJoinPoint pjp) throws Throwable {
		StopWatch stopWatch = startStopWatch();
		try {
			return pjp.proceed();
		} finally {
			gaugeService.submit(MetricsListener.GAUGE_PREFIX + getJobIdentifier() + "." + ClassUtils.getShortName(pjp.getTarget().getClass())+ ".process",
					getTotalTimeMillis(stopWatch));
		}
	}

	@Around("execution(* org.springframework.batch.item.ItemWriter.write(..))")
	public Object profileWriteMethods(ProceedingJoinPoint pjp) throws Throwable {
		StopWatch stopWatch = startStopWatch();
		try {
			return pjp.proceed();
		} finally {
			gaugeService.submit(MetricsListener.GAUGE_PREFIX + getJobIdentifier() + "." + ClassUtils.getShortName(pjp.getTarget().getClass())+ ".write",
					getTotalTimeMillis(stopWatch));
		}
	}

	private long getTotalTimeMillis(StopWatch stopWatch) {
		stopWatch.stop();
		long duration = stopWatch.getTotalTimeMillis();
		return duration;
	}

	private StopWatch startStopWatch() {
		StopWatch stopWatch = new StopWatch();
		stopWatch.start();
		return stopWatch;
	}

	private String getJobIdentifier() {
		String jobName = MDC.get(LoggingListener.JOB_EXECUTION_IDENTIFIER);
		if (jobName == null) {
			LOG.warn("Jobname could not be read from MDC.");
			jobName = "unknown";
		}
		return jobName;
	}
}
@@ -1178,35 +1178,36 @@
 UGE_PREFIX + get
-Job
+Step
 Identifier() + %22
@@ -1630,35 +1630,36 @@
 UGE_PREFIX + get
-Job
+Step
 Identifier() + %22
@@ -2082,27 +2082,28 @@
 PREFIX + get
-Job
+Step
 Identifier()
@@ -2528,19 +2528,20 @@
 ring get
-Job
+Step
 Identifi
@@ -2557,23 +2557,30 @@
 %09String 
-jobName
+stepIdentifier
  = MDC.g
@@ -2602,11 +2602,12 @@
 ner.
-JOB
+STEP
 _EXE
@@ -2633,23 +2633,30 @@
 %0D%0A%09%09if (
-jobName
+stepIdentifier
  == null
@@ -2677,15 +2677,23 @@
 rn(%22
-Jobname
+Step identifier
  cou
@@ -2724,23 +2724,30 @@
 %22);%0D%0A%09%09%09
-jobName
+stepIdentifier
  = %22unkn
@@ -2771,15 +2771,22 @@
 urn 
-jobName
+stepIdentifier
 ;%0D%0A%09

fix to apply to the new MetricListener code