View Javadoc
1   /*
2    * Copyright 2006-2010 the original author or authors.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.springframework.batch.admin.jmx;
17  
18  import javax.management.ObjectName;
19  import javax.management.monitor.GaugeMonitor;
20  import javax.management.monitor.MonitorMBean;
21  
22  import org.springframework.beans.factory.FactoryBean;
23  import org.springframework.beans.factory.InitializingBean;
24  import org.springframework.util.Assert;
25  
26  /**
27   * Monitors executions of a given step and sends JMX notifications if it takes
28   * too long. The monitor is a {@link MonitorMBean} so it can be automatically
29   * exposed to an existing MBeanServer using Spring JMX. JMX clients subscribe to
30   * notifications and receive them whenever the thresholds are crossed.
31   * 
32   * @author Dave Syer
33   * 
34   */
35  public class StepExecutionServiceLevelMonitor implements FactoryBean<GaugeMonitor>, InitializingBean {
36  
37  	private String defaultDomain = BatchMBeanExporter.DEFAULT_DOMAIN;
38  
39  	private String stepName;
40  
41  	private String jobName;
42  
43  	private int upperThreshold = 0;
44  
45  	private int lowerThreshold = 0;
46  
47  	private boolean autoStart = true;
48  
49  	private String observedAttribute = "LatestDuration";
50  
51  	/**
52  	 * The name of the attribute to monitor on the step. Defaults to
53  	 * <code>LatestDuration</code>. This can be changed at runtime, but note
54  	 * that if the type of the observed metric changes (e.g. from double to
55  	 * integer) then the thresholds will also have to be changed so their type
56  	 * matches.
57  	 * 
58  	 * @param observedAttribute the observed attribute to set
59  	 */
60  	public void setObservedAttribute(String observedAttribute) {
61  		this.observedAttribute = observedAttribute;
62  	}
63  
64  	/**
65  	 * Should the monitor start immediately or wait to be started manually?
66  	 * 
67  	 * @param autoStart the auto start flag to set
68  	 */
69  	public void setAutoStart(boolean autoStart) {
70  		this.autoStart = autoStart;
71  	}
72  
73  	/**
74  	 * The domain name to use in constructing object names for the monitored
75  	 * step. Default to <code>org.springframework.batch</code> (same as
76  	 * {@link BatchMBeanExporter}).
77  	 * 
78  	 * @param defaultDomain the default domain to set
79  	 */
80  	public void setDefaultDomain(String defaultDomain) {
81  		this.defaultDomain = defaultDomain;
82  	}
83  
84  	/**
85  	 * @param stepName the stepName to set
86  	 */
87  	public void setStepName(String stepName) {
88  		this.stepName = stepName;
89  	}
90  
91  	/**
92  	 * @param jobName the jobName to set
93  	 */
94  	public void setJobName(String jobName) {
95  		this.jobName = jobName;
96  	}
97  
98  	/**
99  	 * Upper threshold for observed attribute. Mandatory with no default.
100 	 * 
101 	 * @param upperThreshold the upper threshold to set
102 	 */
103 	public void setUpperThreshold(int upperThreshold) {
104 		this.upperThreshold = upperThreshold;
105 	}
106 
107 	/**
108 	 * Optional lower threshold. Defaults to 80% of the upper threshold.
109 	 * 
110 	 * @param lowerThreshold the lower threshold to set
111 	 */
112 	public void setLowerThreshold(int lowerThreshold) {
113 		this.lowerThreshold = lowerThreshold;
114 	}
115 
116 	public GaugeMonitor getObject() throws Exception {
117 		GaugeMonitor monitor = new GaugeMonitor();
118 		monitor.setNotifyHigh(true);
119 		monitor.addObservedObject(new ObjectName(String.format("%s:type=JobExecution,name=%s,step=%s", defaultDomain,
120 				jobName, stepName)));
121 		monitor.setObservedAttribute(observedAttribute);
122 		if (observedAttribute.endsWith("Duration")) {
123 			monitor.setThresholds(new Double(upperThreshold), new Double(lowerThreshold));
124 		}
125 		else {
126 			monitor.setThresholds(new Integer(upperThreshold), new Integer(lowerThreshold));
127 		}
128 		if (autoStart) {
129 			monitor.start();
130 		}
131 		return monitor;
132 	}
133 
134 	public Class<?> getObjectType() {
135 		return GaugeMonitor.class;
136 	}
137 
138 	public boolean isSingleton() {
139 		return true;
140 	}
141 
142 	public void afterPropertiesSet() throws Exception {
143 		Assert.state(jobName != null, "A Job name must be provided");
144 		Assert.state(stepName != null, "A Step name must be provided");
145 		Assert.state(upperThreshold > 0, "A threshold must be provided");
146 		Assert.state(lowerThreshold < upperThreshold, "A threshold must be provided");
147 		if (lowerThreshold == 0) {
148 			lowerThreshold = upperThreshold * 8 / 10;
149 		}
150 	}
151 
152 }