content: package de.chandre.quartz.spring.listener;
  
  import javax.annotation.PostConstruct;
  
  import org.quartz.JobExecutionContext;
  import org.quartz.Trigger;
  import org.quartz.Trigger.CompletedExecutionInstruction;
  import org.quartz.listeners.TriggerListenerSupport;
  import org.springframework.beans.factory.annotation.Autowired;
  import org.springframework.boot.actuate.metrics.CounterService;
  import org.springframework.boot.actuate.metrics.GaugeService;
  import org.springframework.util.StringUtils;
  
  import de.chandre.quartz.spring.QuartzSchedulerProperties.Metrics;
  
  /**
   * Quartz metrics listener for Spring Boot actuator.<br>
   * requires a CounterService and GaugeService to be configured.
   * 
   * @author André
   * @since 1.0.5
   *
   */
  public class TriggerMetricsListener extends TriggerListenerSupport {
  
  	public static final String SEPARATOR = ".";
  
  	public static final String METRIC_PREFIX = "quartz" + SEPARATOR;
  
  	public static final String METRIC_INFIX_TYPE_JOB = "job" + SEPARATOR;
  	public static final String METRIC_INFIX_TYPE_TRIGGER = "trigger" + SEPARATOR;
  
  	public static final String METRIC_SUFFIX_START = SEPARATOR + "fired";
  	public static final String METRIC_SUFFIX_COMPLETE = SEPARATOR + "completed";
  	public static final String METRIC_SUFFIX_MISFIRE = SEPARATOR + "misfired";
  
  	private Metrics metricSettings;
  	private String name;
  
  	@Autowired(required = false)
  	private CounterService counterService;
  
  	@Autowired(required = false)
  	private GaugeService gaugeService;
  
  	public TriggerMetricsListener(Metrics metrics, String name) {
  		this.metricSettings = metrics;
  		this.name = StringUtils.isEmpty(name) ? getClass().getSimpleName() : name;
  	}
  
  	public boolean isActive() {
  		return this.metricSettings.isEnabled() && (this.counterService != null || this.gaugeService != null);
  	}
  
  	@PostConstruct
  	public void init() {
  		getLog().info(this.getClass().getName() + " is " + (isActive() ? "active" : "deactivated"));
  	}
  
  	@Override
  	public String getName() {
  		return this.name;
  	}
  
  	protected void mesure(String suffix, Trigger trigger, JobExecutionContext context,
  			CompletedExecutionInstruction triggerInstructionCode) {
  		if (null == this.counterService && null == this.gaugeService) {
  			return;
  		}
  		getLog().trace("exposing metrics");
  
  		String jobKey = METRIC_PREFIX + METRIC_INFIX_TYPE_JOB + trigger.getJobKey().getGroup() + SEPARATOR
  				+ trigger.getJobKey().getName() + suffix;
  		String triggerKey = METRIC_PREFIX + METRIC_INFIX_TYPE_TRIGGER + trigger.getKey().getGroup() + SEPARATOR
  				+ trigger.getKey().getName() + suffix;
  
  		if (null != this.counterService) {
  			if (this.metricSettings.isEnableJobGroupCounter()) {
  				// count job group
  				this.counterService.increment(METRIC_PREFIX + METRIC_INFIX_TYPE_JOB + trigger.getJobKey().getGroup() + suffix);
  			}
  			if (this.metricSettings.isEnableJobCounter()) {
  				// count job group and job name
  				this.counterService.increment(jobKey);
  			}
  			if (this.metricSettings.isEnableTriggerCounter()) {
  				// count trigger group and trigger name
  				this.counterService.increment(triggerKey);
  			}
  			
  			// count finish code
  			if (this.metricSettings.isEnableExecutionInstructionCounter() && null != triggerInstructionCode) {
  				if (this.metricSettings.isEnableTriggerCounter()) {
  					this.counterService.increment(triggerKey + SEPARATOR + triggerInstructionCode.name());
  				}
  				if (this.metricSettings.isEnableJobCounter()) {
  					// if a job has more than one trigger .
  					this.counterService.increment(jobKey + SEPARATOR + triggerInstructionCode.name());
  				}
  			}
  		}
  
  		if (null != context && null != this.gaugeService) {
  			if (context.getJobRunTime() != -1) {
  				if (this.metricSettings.isEnableTriggerGauges()) {
  					gaugeService.submit(triggerKey, Long.valueOf(context.getJobRunTime()).doubleValue());
  				}
  				if (this.metricSettings.isEnableJobGauges()) {
  					// if a job has more than one trigger .
  					gaugeService.submit(jobKey, Long.valueOf(context.getJobRunTime()).doubleValue());
  				}
  			}
  		}
  
  	}
  
  	@Override
  	public void triggerFired(Trigger trigger, JobExecutionContext context) {
  		mesure(METRIC_SUFFIX_START, trigger, context, null);
  	}
  
  	@Override
  	public void triggerMisfired(Trigger trigger) {
  		mesure(METRIC_SUFFIX_MISFIRE, trigger, null, null);
  	}
  
  	@Override
  	public void triggerComplete(Trigger trigger, JobExecutionContext context,
  			CompletedExecutionInstruction triggerInstructionCode) {
  		mesure(METRIC_SUFFIX_COMPLETE, trigger, context, triggerInstructionCode);
  	}
  
  }
  