View Javadoc

1   /*******************************************************************************
2    * Copyright (c) 2007, 2014 Massimiliano Ziccardi
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 it.jnrpe.plugin.mysql;
17  
18  import it.jnrpe.ICommandLine;
19  import it.jnrpe.Status;
20  import it.jnrpe.plugins.Metric;
21  import it.jnrpe.plugins.MetricGatheringException;
22  import it.jnrpe.plugins.PluginBase;
23  import it.jnrpe.utils.BadThresholdException;
24  import it.jnrpe.utils.thresholds.ThresholdsEvaluatorBuilder;
25  
26  import java.math.BigDecimal;
27  import java.sql.Connection;
28  import java.sql.ResultSet;
29  import java.sql.SQLException;
30  import java.sql.Statement;
31  import java.util.ArrayList;
32  import java.util.Collection;
33  import java.util.HashMap;
34  import java.util.List;
35  import java.util.Map;
36  
37  /**
38   * This plugin tests connections to a MySql server.
39   * 
40   * @author Frederico Campos
41   */
42  public class CheckMysql extends PluginBase {
43  
44  	/**
45  	 * Configures the threshold evaluator. This plugin supports both the legacy
46  	 * threshold format and the new format specification.
47  	 * 
48  	 * @param thrb
49  	 *            - the evaluator to be configured
50  	 * @param cl
51  	 *            - the received command line
52  	 * @throws BadThresholdException
53  	 *             - if the threshold can't be parsed
54  	 */
55  	@Override
56  	public final void configureThresholdEvaluatorBuilder(
57  			final ThresholdsEvaluatorBuilder thrb, final ICommandLine cl)
58  			throws BadThresholdException {
59  		if (cl.hasOption("th")) {
60  			super.configureThresholdEvaluatorBuilder(thrb, cl);
61  		} else {
62  			thrb.withLegacyThreshold("time", null,
63  					cl.getOptionValue("warning"), cl.getOptionValue("critical"))
64  					.withLegacyThreshold("secondsBehindMaster", null,
65  							cl.getOptionValue("warning"),
66  							cl.getOptionValue("critical"));
67  		}
68  	}
69  
70  	/**
71  	 * Execute and gather metrics.
72  	 * 
73  	 * @param cl
74  	 *            - The command line parameters
75  	 * @throws MetricGatheringException
76  	 *             - If any error occurs during metric gathering process
77  	 * @return the gathered metrics
78  	 */
79  	@Override
80  	public final Collection<Metric> gatherMetrics(final ICommandLine cl)
81  			throws MetricGatheringException {
82  		List<Metric> metrics = new ArrayList<Metric>();
83  		Mysql mysql = new Mysql(cl);
84  		long start = System.currentTimeMillis();
85  		long elapsed = 0L;
86  		Connection conn = null;
87  		try {
88  			conn = mysql.getConnection();
89  			elapsed = (System.currentTimeMillis() - start) / 1000L;
90  		} catch (ClassNotFoundException e) {
91  			log.error("Mysql driver library not found into the classpath: "
92  					+ "download and put it in the same directory "
93  					+ "of this plugin");
94  			throw new MetricGatheringException(
95  					"Error accessing the MySQL server "
96  							+ "- JDBC driver not installed", Status.CRITICAL, e);
97  		} catch (Exception e) {
98  			log.error("Error accessing the MySQL server", e);
99  			throw new MetricGatheringException(
100 					"Error accessing the MySQL server - " + e.getMessage(),
101 					Status.CRITICAL, e);
102 		}
103 
104 		if (cl.hasOption("check-slave")) {
105 			metrics.add(checkSlave(cl, mysql, conn));
106 		} else {
107 			metrics.add(new Metric("time", "Connection took " + elapsed
108 					+ " secs. ", new BigDecimal(elapsed), new BigDecimal(0),
109 					null));
110 		}
111 		mysql.closeConnection(conn);
112 		return metrics;
113 	}
114 
115 	/**
116 	 * Check the status of mysql slave thread.
117 	 * 
118 	 * @param cl
119 	 *            The command line
120 	 * @param mysql
121 	 *            MySQL connection mgr object
122 	 * @param conn
123 	 *            The SQL connection
124 	 * @return ReturnValue -
125 	 * @throws MetricGatheringException
126 	 *             -
127 	 */
128 	private Metric checkSlave(final ICommandLine cl, final Mysql mysql,
129 			final Connection conn) throws MetricGatheringException {
130 		Metric metric = null;
131 		try {
132 			Map<String, Integer> status = getSlaveStatus(conn);
133 			if (status.isEmpty()) {
134 				mysql.closeConnection(conn);
135 				throw new MetricGatheringException(
136 						"CHECK_MYSQL - WARNING: No slaves defined. ",
137 						Status.CRITICAL, null);
138 			}
139 
140 			// check if slave is running
141 			int slaveIoRunning = status.get("Slave_IO_Running");
142 			int slaveSqlRunning = status.get("Slave_SQL_Running");
143 			int secondsBehindMaster = status.get("Seconds_Behind_Master");
144 
145 			if (slaveIoRunning == 0 || slaveSqlRunning == 0) {
146 				mysql.closeConnection(conn);
147 				throw new MetricGatheringException(
148 						"CHECK_MYSQL - CRITICAL: Slave status unavailable. ",
149 						Status.CRITICAL, null);
150 			}
151 			String slaveResult = "Slave IO: " + slaveIoRunning + " Slave SQL: "
152 					+ slaveSqlRunning + " Seconds Behind Master: "
153 					+ secondsBehindMaster;
154 
155 			metric = new Metric("secondsBehindMaster", slaveResult,
156 					new BigDecimal(secondsBehindMaster), null, null);
157 		} catch (SQLException e) {
158 			log.warn(
159 					"Error executing the CheckMysql plugin: " + e.getMessage(),
160 					e);
161 			throw new MetricGatheringException(
162 					"CHECK_MYSQL - CRITICAL: Unable to check slave status:  - "
163 							+ e.getMessage(), Status.CRITICAL, e);
164 		}
165 
166 		return metric;
167 
168 	}
169 
170 	/**
171 	 * Get slave statuses.
172 	 * 
173 	 * @param conn
174 	 *            The database connection
175 	 * @return The slave status info
176 	 * @throws SQLException
177 	 *             -
178 	 */
179 	private Map<String, Integer> getSlaveStatus(final Connection conn)
180 			throws SQLException {
181 		Map<String, Integer> map = new HashMap<String, Integer>();
182 		String query = "show slave status;";
183 		Statement statement = null;
184 		ResultSet rs = null;
185 		try {
186 			if (conn != null) {
187 				statement = conn.createStatement();
188 				rs = statement.executeQuery(query);
189 				while (rs.next()) {
190 					map.put("Slave_IO_Running", rs.getInt("Slave_IO_Running"));
191 					map.put("Slave_SQL_Running", rs.getInt("Slave_SQL_Running"));
192 					map.put("Seconds_Behind_Master",
193 							rs.getInt("Seconds_Behind_Master"));
194 				}
195 			}
196 		} finally {
197 			if (statement != null) {
198 				statement.close();
199 			}
200 		}
201 		return map;
202 	}
203 
204 	@Override
205 	protected final String getPluginName() {
206 		return "CHECK_MYSQL";
207 	}
208 }