PageRenderTime 50ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 1ms

/gmonitor/gmonitor-core/src/main/java/com/zdingke/gmonitor/trans/TestMetricTrans.java

https://gitlab.com/zhengdingke/gmonitor
Java | 508 lines | 439 code | 59 blank | 10 comment | 72 complexity | 6b3d2fa3f923d94740cb2a402e17c4c3 MD5 | raw file
  1. package com.zdingke.gmonitor.trans;
  2. import java.io.File;
  3. import java.io.FileInputStream;
  4. import java.io.InputStream;
  5. import java.util.ArrayList;
  6. import java.util.Date;
  7. import java.util.HashMap;
  8. import java.util.Iterator;
  9. import java.util.List;
  10. import java.util.Map;
  11. import org.apache.commons.cli.CommandLine;
  12. import org.apache.commons.cli.CommandLineParser;
  13. import org.apache.commons.cli.GnuParser;
  14. import org.apache.commons.cli.HelpFormatter;
  15. import org.apache.commons.cli.Option;
  16. import org.apache.commons.cli.Options;
  17. import org.apache.commons.cli.ParseException;
  18. import org.apache.commons.io.FilenameUtils;
  19. import org.apache.commons.lang.RandomStringUtils;
  20. import org.apache.commons.logging.Log;
  21. import org.apache.commons.logging.LogFactory;
  22. import org.apache.commons.pool.KeyedObjectPool;
  23. import org.apache.commons.pool.impl.GenericKeyedObjectPool;
  24. import org.codehaus.jackson.map.ObjectMapper;
  25. import org.quartz.CronExpression;
  26. import org.quartz.CronTrigger;
  27. import org.quartz.JobDataMap;
  28. import org.quartz.JobDetail;
  29. import org.quartz.Scheduler;
  30. import org.quartz.SchedulerException;
  31. import org.quartz.Trigger;
  32. import org.quartz.TriggerUtils;
  33. import org.quartz.impl.StdSchedulerFactory;
  34. import com.alibaba.fastjson.JSON;
  35. import com.googlecode.jmxtrans.JmxTransformer;
  36. import com.googlecode.jmxtrans.OutputWriter;
  37. import com.googlecode.jmxtrans.jmx.ManagedGenericKeyedObjectPool;
  38. import com.googlecode.jmxtrans.jobs.ServerJob;
  39. import com.googlecode.jmxtrans.model.JmxProcess;
  40. import com.googlecode.jmxtrans.model.Query;
  41. import com.googlecode.jmxtrans.model.Server;
  42. import com.googlecode.jmxtrans.util.JmxUtils;
  43. import com.googlecode.jmxtrans.util.LifecycleException;
  44. import com.googlecode.jmxtrans.util.OptionsException;
  45. import com.googlecode.jmxtrans.util.ValidationException;
  46. import com.googlecode.jmxtrans.util.WatchDir;
  47. import com.googlecode.jmxtrans.util.WatchedCallback;
  48. import com.zdingke.gmonitor.utils.MetricJsonCreateUtil;
  49. public class TestMetricTrans implements WatchedCallback {
  50. private static final Log log = LogFactory.getLog(TestMetricTrans.class);
  51. private String quartPropertiesFile;
  52. private int runPeriod;
  53. private File jsonDirOrFile;
  54. private boolean runEndlessly;
  55. private Scheduler serverScheduler;
  56. private WatchDir watcher;
  57. private Map<String, KeyedObjectPool> poolMap;
  58. private Map<String, ManagedGenericKeyedObjectPool> poolMBeans;
  59. private List<Server> masterServersList;
  60. private Thread shutdownHook;
  61. private volatile boolean isRunning;
  62. public TestMetricTrans() {
  63. this.quartPropertiesFile = null;
  64. this.runPeriod = 60;
  65. this.runEndlessly = false;
  66. this.masterServersList = new ArrayList();
  67. this.shutdownHook = new ShutdownHook();
  68. this.isRunning = false;
  69. }
  70. public static void main(String[] args) throws Exception {
  71. TestMetricTrans transformer = new TestMetricTrans();
  72. transformer.doMain(args);
  73. }
  74. private void doMain(String[] args) throws Exception {
  75. if (!parseOptions(args)) {
  76. return;
  77. }
  78. // ManagedJmxTransformerProcess mbean = new
  79. // ManagedJmxTransformerProcess();
  80. // JmxUtils.registerJMX(mbean);
  81. start();
  82. try {
  83. for (;;) {
  84. Thread.sleep(5L);
  85. }
  86. } catch (Exception e) {
  87. // JmxUtils.unregisterJMX(mbean);
  88. }
  89. }
  90. public synchronized void start() throws LifecycleException {
  91. if (this.isRunning) {
  92. throw new LifecycleException("Process already started");
  93. }
  94. log.info("Starting Jmxtrans on : " + this.jsonDirOrFile.toString());
  95. try {
  96. startupScheduler();
  97. startupWatchdir();
  98. // setupObjectPooling();
  99. //
  100. // startupSystem();
  101. } catch (Exception e) {
  102. log.error(e.getMessage(), e);
  103. throw new LifecycleException(e);
  104. }
  105. Runtime.getRuntime().addShutdownHook(this.shutdownHook);
  106. this.isRunning = true;
  107. }
  108. public synchronized void stop() throws LifecycleException {
  109. if (!this.isRunning) {
  110. throw new LifecycleException("Process already stoped");
  111. }
  112. try {
  113. log.info("Stopping Jmxtrans");
  114. if (this.shutdownHook != null) {
  115. Runtime.getRuntime().removeShutdownHook(this.shutdownHook);
  116. }
  117. stopServices();
  118. this.isRunning = false;
  119. } catch (LifecycleException e) {
  120. log.error(e.getMessage(), e);
  121. throw new LifecycleException(e);
  122. }
  123. }
  124. private synchronized void stopServices() throws LifecycleException {
  125. try {
  126. if (this.serverScheduler != null) {
  127. this.serverScheduler.shutdown(true);
  128. log.debug("Shutdown server scheduler");
  129. try {
  130. Thread.sleep(1500L);
  131. } catch (InterruptedException e) {
  132. log.error(e.getMessage(), e);
  133. }
  134. this.serverScheduler = null;
  135. }
  136. if (this.watcher != null) {
  137. this.watcher.stopService();
  138. this.watcher = null;
  139. log.debug("Shutdown watch service");
  140. }
  141. // for (String key : this.poolMap.keySet()) {
  142. // JmxUtils.unregisterJMX((ManagedObject) this.poolMBeans.get(key));
  143. // }
  144. this.poolMBeans = null;
  145. for (Map.Entry<String, KeyedObjectPool> entry : this.poolMap.entrySet()) {
  146. try {
  147. entry.getValue().close();
  148. log.debug("Closed object pool factory: " + entry.getKey());
  149. } catch (Exception ex) {
  150. log.error("Error closing object pool factory: " + entry.getKey());
  151. }
  152. }
  153. this.poolMap = null;
  154. Iterator i$;
  155. Query query;
  156. for (Server server : this.masterServersList) {
  157. for (i$ = server.getQueries().iterator(); i$.hasNext();) {
  158. query = (Query) i$.next();
  159. for (OutputWriter writer : query.getOutputWriters()) {
  160. try {
  161. writer.stop();
  162. log.debug("Stopped writer: " + writer.getClass().getSimpleName() + " for query: " + query);
  163. } catch (LifecycleException ex) {
  164. log.error("Error stopping writer: " + writer.getClass().getSimpleName() + " for query: " + query);
  165. }
  166. }
  167. }
  168. }
  169. this.masterServersList.clear();
  170. } catch (Exception e) {
  171. log.error(e.getMessage(), e);
  172. throw new LifecycleException(e);
  173. }
  174. }
  175. private void startupWatchdir() throws Exception {
  176. File dirToWatch = null;
  177. System.out.println(getJsonDirOrFile().toString());
  178. if (getJsonDirOrFile().isFile()) {
  179. dirToWatch = new File(FilenameUtils.getFullPath(getJsonDirOrFile().getAbsolutePath()));
  180. } else {
  181. dirToWatch = getJsonDirOrFile();
  182. }
  183. this.watcher = new WatchDir(dirToWatch, this);
  184. this.watcher.start();
  185. }
  186. private void startupScheduler() throws Exception {
  187. StdSchedulerFactory serverSchedFact = new StdSchedulerFactory();
  188. InputStream stream = null;
  189. if (this.quartPropertiesFile == null) {
  190. stream = JmxTransformer.class.getResourceAsStream("/quartz.server.properties");
  191. } else {
  192. stream = new FileInputStream(this.quartPropertiesFile);
  193. }
  194. serverSchedFact.initialize(stream);
  195. this.serverScheduler = serverSchedFact.getScheduler();
  196. this.serverScheduler.start();
  197. }
  198. public void executeStandalone(JmxProcess process) throws Exception {
  199. this.masterServersList = process.getServers();
  200. startupScheduler();
  201. setupObjectPooling();
  202. processServersIntoJobs(this.serverScheduler);
  203. Thread.sleep(10000L);
  204. }
  205. private void startupSystem() throws LifecycleException {
  206. processFilesIntoServers(getJsonFiles());
  207. processServersIntoJobs(this.serverScheduler);
  208. }
  209. protected void setupObjectPooling() throws Exception {
  210. if (this.poolMap == null) {
  211. this.poolMap = JmxUtils.getDefaultPoolMap();
  212. this.poolMBeans = new HashMap();
  213. for (String key : this.poolMap.keySet()) {
  214. ManagedGenericKeyedObjectPool mbean = new ManagedGenericKeyedObjectPool((GenericKeyedObjectPool) this.poolMap.get(key));
  215. mbean.setPoolName(key);
  216. JmxUtils.registerJMX(mbean);
  217. this.poolMBeans.put(key, mbean);
  218. }
  219. }
  220. }
  221. private void validateSetup(List<Query> queries) throws ValidationException {
  222. for (Query q : queries) {
  223. validateSetup(q);
  224. }
  225. }
  226. private void validateSetup(Query query) throws ValidationException {
  227. List<OutputWriter> writers = query.getOutputWriters();
  228. if (writers != null) {
  229. for (OutputWriter w : writers) {
  230. w.validateSetup(query);
  231. }
  232. }
  233. }
  234. private void processFilesIntoServers(List<File> jsonFiles) throws LifecycleException {
  235. MetricJsonCreateUtil.getAllModuleJsonObj(getJsonDirOrFile().getPath().toString()).stream().forEach(m -> {
  236. System.out.println(JSON.toJSONString(m, true));
  237. ObjectMapper mapper = new ObjectMapper();
  238. JmxProcess process = null;
  239. try {
  240. process = mapper.readValue(JSON.toJSONString(m), JmxProcess.class);
  241. } catch (Exception e) {
  242. log.error(e.getMessage(), e);
  243. }
  244. JmxUtils.mergeServerLists(this.masterServersList, process.getServers());
  245. });
  246. }
  247. private void processServersIntoJobs(Scheduler scheduler) throws LifecycleException {
  248. System.out.println("server.size:" + this.masterServersList.size());
  249. for (Server server : this.masterServersList) {
  250. try {
  251. for (Query query : server.getQueries()) {
  252. query.setServer(server);
  253. for (OutputWriter writer : query.getOutputWriters()) {
  254. writer.setObjectPoolMap(this.poolMap);
  255. writer.start();
  256. }
  257. }
  258. validateSetup(server.getQueries());
  259. scheduleJob(scheduler, server);
  260. } catch (java.text.ParseException ex) {
  261. throw new LifecycleException("Error parsing cron expression: " + server.getCronExpression(), ex);
  262. } catch (SchedulerException ex) {
  263. throw new LifecycleException("Error scheduling job for server: " + server, ex);
  264. } catch (ValidationException ex) {
  265. throw new LifecycleException("Error validating json setup for query", ex);
  266. }
  267. }
  268. }
  269. private void scheduleJob(Scheduler scheduler, Server server) throws java.text.ParseException, SchedulerException {
  270. String name = server.getHost() + ":" + server.getPort() + "-" + System.currentTimeMillis() + "-" + RandomStringUtils.randomNumeric(10);
  271. JobDetail jd = new JobDetail(name, "ServerJob", ServerJob.class);
  272. JobDataMap map = new JobDataMap();
  273. map.put(Server.class.getName(), server);
  274. map.put(Server.JMX_CONNECTION_FACTORY_POOL, this.poolMap.get(Server.JMX_CONNECTION_FACTORY_POOL));
  275. jd.setJobDataMap(map);
  276. Trigger trigger = null;
  277. if ((server.getCronExpression() != null) && (CronExpression.isValidExpression(server.getCronExpression()))) {
  278. trigger = new CronTrigger();
  279. ((CronTrigger) trigger).setCronExpression(server.getCronExpression());
  280. ((CronTrigger) trigger).setName(server.getHost() + ":" + server.getPort() + "-" + Long.valueOf(System.currentTimeMillis()).toString());
  281. ((CronTrigger) trigger).setStartTime(new Date());
  282. } else {
  283. Trigger minuteTrigger = TriggerUtils.makeSecondlyTrigger(this.runPeriod);
  284. minuteTrigger.setName(server.getHost() + ":" + server.getPort() + "-" + Long.valueOf(System.currentTimeMillis()).toString());
  285. minuteTrigger.setStartTime(new Date());
  286. trigger = minuteTrigger;
  287. }
  288. scheduler.scheduleJob(jd, trigger);
  289. if (log.isDebugEnabled()) {
  290. log.debug("Scheduled job: " + jd.getName() + " for server: " + server);
  291. }
  292. }
  293. private void deleteAllJobs(Scheduler scheduler) throws Exception {
  294. List<JobDetail> allJobs = new ArrayList();
  295. String[] jobGroups = scheduler.getJobGroupNames();
  296. for (String jobGroup : jobGroups) {
  297. String[] jobNames = scheduler.getJobNames(jobGroup);
  298. for (String jobName : jobNames) {
  299. allJobs.add(scheduler.getJobDetail(jobName, jobGroup));
  300. }
  301. }
  302. for (JobDetail jd : allJobs) {
  303. scheduler.deleteJob(jd.getName(), jd.getGroup());
  304. if (log.isDebugEnabled()) {
  305. log.debug("Deleted scheduled job: " + jd.getName() + " group: " + jd.getGroup());
  306. }
  307. }
  308. }
  309. public void setRunEndlessly(boolean runEndlessly) {
  310. this.runEndlessly = runEndlessly;
  311. }
  312. public boolean isRunEndlessly() {
  313. return this.runEndlessly;
  314. }
  315. private boolean parseOptions(String[] args) throws OptionsException, ParseException {
  316. CommandLineParser parser = new GnuParser();
  317. CommandLine cl = parser.parse(getOptions(), args);
  318. Option[] options = cl.getOptions();
  319. boolean result = true;
  320. for (Option option : options) {
  321. if (option.getOpt().equals("j")) {
  322. File tmp = new File(option.getValue());
  323. if ((!tmp.exists()) && (!tmp.isDirectory())) {
  324. throw new OptionsException("Path to json directory is invalid: " + tmp);
  325. }
  326. setJsonDirOrFile(tmp);
  327. } else if (option.getOpt().equals("f")) {
  328. File tmp = new File(option.getValue());
  329. if ((!tmp.exists()) && (!tmp.isFile())) {
  330. throw new OptionsException("Path to json file is invalid: " + tmp);
  331. }
  332. setJsonDirOrFile(tmp);
  333. } else if (option.getOpt().equals("e")) {
  334. setRunEndlessly(true);
  335. } else if (option.getOpt().equals("q")) {
  336. setQuartPropertiesFile(option.getValue());
  337. File file = new File(option.getValue());
  338. if (!file.exists()) {
  339. throw new OptionsException("Could not find path to the quartz properties file: " + file.getAbsolutePath());
  340. }
  341. } else if (option.getOpt().equals("s")) {
  342. setRunPeriod(Integer.valueOf(option.getValue()).intValue());
  343. } else if (option.getOpt().equals("h")) {
  344. HelpFormatter formatter = new HelpFormatter();
  345. formatter.printHelp("java -jar jmxtrans-all.jar", getOptions());
  346. result = false;
  347. }
  348. }
  349. if ((result == true) && (getJsonDirOrFile() == null)) {
  350. throw new OptionsException("Please specify either the -f or -j option.");
  351. }
  352. return result;
  353. }
  354. public Options getOptions() {
  355. Options options = new Options();
  356. options.addOption("j", true, "Directory where json configuration is stored. Default is .");
  357. options.addOption("f", true, "A single json file to execute.");
  358. options.addOption("e", false, "Run endlessly. Default false.");
  359. options.addOption("q", true, "Path to quartz configuration file.");
  360. options.addOption("s", true, "Seconds between server job runs (not defined with cron). Default: 60");
  361. options.addOption("h", false, "Help");
  362. return options;
  363. }
  364. public String getQuartPropertiesFile() {
  365. return this.quartPropertiesFile;
  366. }
  367. public void setQuartPropertiesFile(String quartPropertiesFile) {
  368. this.quartPropertiesFile = quartPropertiesFile;
  369. }
  370. public int getRunPeriod() {
  371. return this.runPeriod;
  372. }
  373. public void setRunPeriod(int runPeriod) {
  374. this.runPeriod = runPeriod;
  375. }
  376. public void setJsonDirOrFile(File jsonDirOrFile) {
  377. this.jsonDirOrFile = jsonDirOrFile;
  378. }
  379. public File getJsonDirOrFile() {
  380. return this.jsonDirOrFile;
  381. }
  382. private List<File> getJsonFiles() {
  383. File[] files = null;
  384. if ((getJsonDirOrFile() != null) && (getJsonDirOrFile().isFile())) {
  385. files = new File[1];
  386. files[0] = getJsonDirOrFile();
  387. } else {
  388. files = getJsonDirOrFile().listFiles();
  389. }
  390. List<File> result = new ArrayList();
  391. for (File file : files) {
  392. if (isJsonFile(file)) {
  393. result.add(file);
  394. }
  395. }
  396. return result;
  397. }
  398. private boolean isJsonFile(File file) {
  399. if (getJsonDirOrFile().isFile()) {
  400. return file.equals(getJsonDirOrFile());
  401. }
  402. return file.getName().endsWith(".json");
  403. }
  404. @Override
  405. public void fileModified(File file) throws Exception {
  406. System.out.println(file.getAbsolutePath().toString());
  407. if (isJsonFile(file)) {
  408. Thread.sleep(1000L);
  409. if (log.isDebugEnabled()) {
  410. log.debug("File modified: " + file);
  411. }
  412. deleteAllJobs(this.serverScheduler);
  413. startupSystem();
  414. }
  415. }
  416. @Override
  417. public void fileDeleted(File file) throws Exception {
  418. if (isJsonFile(file)) {
  419. Thread.sleep(1000L);
  420. if (log.isDebugEnabled()) {
  421. log.debug("File deleted: " + file);
  422. }
  423. deleteAllJobs(this.serverScheduler);
  424. startupSystem();
  425. }
  426. }
  427. @Override
  428. public void fileAdded(File file) throws Exception {
  429. if (isJsonFile(file)) {
  430. Thread.sleep(1000L);
  431. if (log.isDebugEnabled()) {
  432. log.debug("File added: " + file);
  433. }
  434. startupSystem();
  435. }
  436. }
  437. protected class ShutdownHook extends Thread {
  438. protected ShutdownHook() {
  439. }
  440. @Override
  441. public void run() {
  442. try {
  443. TestMetricTrans.this.stopServices();
  444. } catch (LifecycleException e) {
  445. TestMetricTrans.log.error("Error shutdown hook", e);
  446. }
  447. }
  448. }
  449. }