|
| 1 | +/** |
| 2 | +* Module: IDGstatsMon.java |
| 3 | +* |
| 4 | +* Written by Ray Wilson |
| 5 | +* |
| 6 | +* Description: Parse CLI output files and put the data into a csv file. This file |
| 7 | +* can then be imported into your favorite spreadsheet and graphed. |
| 8 | +* |
| 9 | +* A very small performance increase in this application can be achieved by |
| 10 | +* commenting out all of the "if(DEBUG)" statements. |
| 11 | +* |
| 12 | +* CSV format: |
| 13 | +* date-time, Memory%, cpu10s, cpu1m, cpu10m, cpu1h, cpu1d, tps10s, tps1m, tps10m, tps1h, tps1d |
| 14 | +* |
| 15 | +* Notes: date-time - is taken from the timestamp in the source data file. |
| 16 | +* Memory - is read once for each file processed. (because that is how the CLI script works) |
| 17 | +* CPU data - is read once for each file processed. |
| 18 | +* TPS data - is the SUM of all gateways in all domains that are reported in the CLI script |
| 19 | +* |
| 20 | +* Version 1.0 |
| 21 | +* |
| 22 | +* History: |
| 23 | +* 2016-04-02 v1.0 Created. |
| 24 | +* |
| 25 | +* Copyright (C) 2016 Paul Ray Wilson |
| 26 | +* |
| 27 | +* This program is free software: you can redistribute it and/or modify |
| 28 | +* it under the terms of the GNU General Public License as published by |
| 29 | +* the Free Software Foundation, either version 3 of the License, or |
| 30 | +* (at your option) any later version. |
| 31 | +* |
| 32 | +* This program is distributed in the hope that it will be useful, |
| 33 | +* but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 34 | +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 35 | +* GNU General Public License for more details. |
| 36 | +* |
| 37 | +* You should have received a copy of the GNU General Public License |
| 38 | +* along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 39 | +* |
| 40 | +*/ |
| 41 | + |
| 42 | +import java.io.*; |
| 43 | +import java.util.*; |
| 44 | +import java.io.File; |
| 45 | + |
| 46 | +public class IDGstatsMon { |
| 47 | + public static boolean DEBUG = false; |
| 48 | + public static int runInterval = 10; |
| 49 | + public static String dataDir = ""; |
| 50 | + public static String procDir = ""; |
| 51 | + public static String resultDir = ""; |
| 52 | + public static String baseName = ""; |
| 53 | + |
| 54 | + /** main() |
| 55 | + * |
| 56 | + * This is the "main" method that checks for command line arguments and |
| 57 | + * for starting the doWork method below where all the actual work will happen |
| 58 | + * |
| 59 | + */ |
| 60 | + public static void main(String arg[]) throws Exception { |
| 61 | + |
| 62 | + boolean argsValid = checkArgs(arg); // Check command line arugments |
| 63 | + |
| 64 | + if (!argsValid) { |
| 65 | + System.out.println("\n==============================================================================="); |
| 66 | + System.out.println(" "); |
| 67 | + System.out.println("Usage: java IDGstatsMon runInterval dataDir procDir resultDir filename"); |
| 68 | + System.out.println(" Where:"); |
| 69 | + System.out.println(" runInterval = Number of seconds between checking the folder for new data files, must be > 0"); |
| 70 | + System.out.println(" dataDir = Relative or Absolute path to the directory for data files"); |
| 71 | + System.out.println(" procDir = Relative or Absolute path to the directory for processed data files"); |
| 72 | + System.out.println(" resultDir = Relative or Absolute path to the directory for the output .csv file"); |
| 73 | + System.out.println(" filename = The base name of the data files to be collected"); |
| 74 | + System.out.println(" "); |
| 75 | + System.out.println("Example > java IDGstatsMon 30 /Users/uid/MonitorResult/_data/ /Users/uid/MonitorResult/_processed/ /Users/uid/MonitorResult/ IDGv720-1"); |
| 76 | + System.out.println("Example > java IDGstatsMon 30 ./_data/ ./_processed/ ./_result/ IDGv720-1"); |
| 77 | + System.out.println("Example > java IDGstatsMon 30 _data/ _processed/ _result/ IDGv720-1"); |
| 78 | + System.out.println(" "); |
| 79 | + System.out.println("===============================================================================\n"); |
| 80 | + System.exit(0); |
| 81 | + } else { |
| 82 | + try { |
| 83 | + |
| 84 | + // Validate the command line arguments. |
| 85 | + runInterval = Integer.parseInt(arg[0]); |
| 86 | + dataDir = arg[1]; |
| 87 | + procDir = arg[2]; |
| 88 | + resultDir = arg[3]; |
| 89 | + baseName = arg[4]; |
| 90 | + |
| 91 | + String result = doWork(); |
| 92 | + System.out.println(result); |
| 93 | + |
| 94 | + } catch (Exception e) { |
| 95 | + System.err.println(e.getMessage()); |
| 96 | + System.exit(0); |
| 97 | + } |
| 98 | + } |
| 99 | + } |
| 100 | + |
| 101 | + /** doWork() |
| 102 | + * |
| 103 | + * This method scan the folder for matching files and get the data our of them, |
| 104 | + * then update a data file and move the file to the processed folder. It will |
| 105 | + * then wait for some period of time before checking the folder again. |
| 106 | + * assumptions: |
| 107 | + * - 1) the out put files are name "something"+time-stamp+".out" |
| 108 | + * - 2) they are all in one folder, porinted to with myPath. |
| 109 | + * - 3) there are sub-folders in this folder called "processed" and "result_data" |
| 110 | + * - processed is for the files once the data has been extracted |
| 111 | + * the extension ".done" is added to the file and it is moved ot this folder |
| 112 | + * - result_data is where the .csv file is stored and updated. |
| 113 | + * |
| 114 | + * return - String - The results of the echo opperation. |
| 115 | + */ |
| 116 | + public static String doWork () { |
| 117 | + if(DEBUG) {System.out.println("DEBUG :: Entering doWork");} |
| 118 | + boolean runMe = true; |
| 119 | + String outputFilename = resultDir+baseName+".csv"; |
| 120 | + File fout = new File(outputFilename); |
| 121 | + String processedFolder = procDir; |
| 122 | + try { |
| 123 | + while (runMe) { |
| 124 | + |
| 125 | + // Create the output file if it does not exist. |
| 126 | + if(!fout.exists()){ |
| 127 | + fout.createNewFile(); |
| 128 | + if(DEBUG){System.out.println("DEBUG :: Creating output file - " + outputFilename);} |
| 129 | + } |
| 130 | + // |
| 131 | + // Output file handle |
| 132 | + // |
| 133 | + BufferedWriter out = new BufferedWriter(new FileWriter(outputFilename,true)); |
| 134 | + out.write("Date-Time,Mem %,CPU-10s,CPU-1m,CPU-10m,CPU-1h,CPU-1d,TPS-10s,TPS-1m,TPS-10m,TPS-1h,TPS-1d\n"); |
| 135 | + |
| 136 | + // |
| 137 | + // Create a list of files in the folder pointed to by the path on the command line. |
| 138 | + // |
| 139 | + String thisfile; |
| 140 | + File folderToScan = new File(dataDir); |
| 141 | + File[] listOfFiles = folderToScan.listFiles(); |
| 142 | + if(DEBUG) {System.out.println("DEBUG :: Found "+listOfFiles.length+" Files");} |
| 143 | + if(DEBUG){ |
| 144 | + System.out.println("DEBUG :: Processing File List:"); |
| 145 | + for(int j=0;j<listOfFiles.length;j++){ |
| 146 | + System.out.println("DEBUG :: File ["+j+"] = "+listOfFiles[j]); |
| 147 | + } |
| 148 | + } |
| 149 | + |
| 150 | + // |
| 151 | + // Scan through the list of files looking for the ones that match our filename from |
| 152 | + // the command line (as well as an extension that I added that is hard coded) |
| 153 | + // |
| 154 | + for (int i = 0; i < listOfFiles.length; i++) { |
| 155 | + if (listOfFiles[i].isFile()) { |
| 156 | + thisfile = listOfFiles[i].getName(); |
| 157 | + |
| 158 | + // |
| 159 | + // File selection - the starts with comes from the filename you enter on the command |
| 160 | + // line, and the ends with is just what I used for a filename. Everything in the middle |
| 161 | + // is assumed to be some sort of time stamp or something. |
| 162 | + // |
| 163 | + if (thisfile.startsWith(baseName) && thisfile.endsWith(".out")) { |
| 164 | + File fin = new File(dataDir+thisfile); |
| 165 | + String dateTimeStamp = ""; |
| 166 | + if(DEBUG) {System.out.println("DEBUG :: Processing file "+listOfFiles[i]);} |
| 167 | + |
| 168 | + try{ |
| 169 | + String csvString = ""; |
| 170 | + int memPct = 0; |
| 171 | + int[] cpuStats = {0,0,0,0,0}; |
| 172 | + int[] tpsStats = {0,0,0,0,0}; |
| 173 | + |
| 174 | + // |
| 175 | + // Input file handle |
| 176 | + // |
| 177 | + BufferedReader in = new BufferedReader(new FileReader(fin)); |
| 178 | + |
| 179 | + // |
| 180 | + // start processesing the file, read a line, for our use the first line is a |
| 181 | + // date-time stamp. After that we scan down the file looking the lines with lots |
| 182 | + // of dashed, the data follows that line. We process the data then start looking |
| 183 | + // for more dashes, if we find some we process that as well, otherwise it will |
| 184 | + // process until EOF. |
| 185 | + |
| 186 | + String thisLine = in.readLine(); /// |
| 187 | + dateTimeStamp = thisLine; /// These lines are specific to the files I'm using |
| 188 | + thisLine = in.readLine(); /// |
| 189 | + |
| 190 | + // |
| 191 | + // Process the rest of the file |
| 192 | + // |
| 193 | + while (thisLine != null) { |
| 194 | + |
| 195 | + if (thisLine.contains("Memory") && thisLine.contains("Usage")) { |
| 196 | + memPct = getMemStats(thisLine); |
| 197 | + if(DEBUG) {System.out.println("Memory Data gathered");} |
| 198 | + } |
| 199 | + else if (thisLine.contains("cpu") && thisLine.contains("usage")) { |
| 200 | + cpuStats = getCpuStats(thisLine, cpuStats); |
| 201 | + if(DEBUG) {System.out.println("CPU Data gathered");} |
| 202 | + } |
| 203 | + else if (thisLine.contains("---")) { // Line with all the --- before the stats we want |
| 204 | + thisLine = in.readLine(); |
| 205 | + while (thisLine.trim().length() > 0) { // Blank line after the stats we want |
| 206 | + tpsStats = getTpsStats(thisLine, tpsStats); |
| 207 | + thisLine = in.readLine(); |
| 208 | + } |
| 209 | + if(DEBUG) {System.out.println("TPS Data gathered");} |
| 210 | + } |
| 211 | + thisLine = in.readLine(); |
| 212 | + } |
| 213 | + // |
| 214 | + // Build the string for the csv output file |
| 215 | + // |
| 216 | + String cpuString = cpuStats[0]+", "+cpuStats[1]+", "+ |
| 217 | + cpuStats[2]+", "+cpuStats[3]+", "+cpuStats[4]; |
| 218 | + |
| 219 | + String tpsString = tpsStats[0]+", "+tpsStats[1]+", "+ |
| 220 | + tpsStats[2]+", "+tpsStats[3]+", "+tpsStats[4]; |
| 221 | + |
| 222 | + csvString = dateTimeStamp+", "+ |
| 223 | + memPct+", "+ |
| 224 | + cpuString+", "+ |
| 225 | + tpsString; |
| 226 | + // |
| 227 | + // Update the results .csv file |
| 228 | + // |
| 229 | + out.write(csvString + "\n"); |
| 230 | + in.close(); |
| 231 | + // |
| 232 | + // Move and rename the datafile to the processed folder with the |
| 233 | + // extension of .done |
| 234 | + // |
| 235 | + fin.renameTo(new File(processedFolder+thisfile+".done")); |
| 236 | + } catch (Exception e) { |
| 237 | + System.out.println("\nA Error Occured with file processing"); |
| 238 | + e.printStackTrace(); |
| 239 | + runMe=false; |
| 240 | + out.close(); |
| 241 | + } |
| 242 | + } |
| 243 | + } |
| 244 | + } |
| 245 | + // |
| 246 | + // Wait timer for running continuously. |
| 247 | + // The timer is set at the top of the class with the runInterval argument. |
| 248 | + // |
| 249 | + try { |
| 250 | + Thread.sleep(runInterval*1000); |
| 251 | + } catch(InterruptedException ex) { |
| 252 | + Thread.currentThread().interrupt(); |
| 253 | + } |
| 254 | + |
| 255 | + // |
| 256 | + // Run once! This is mostly for DEBUGging, when the statement does not execute this will |
| 257 | + // become more of a deamon like process in it's behavior. Rescanning the folder every |
| 258 | + // "runInterval" seconds until it is killed. |
| 259 | + // |
| 260 | + if(DEBUG) { runMe=false; } |
| 261 | + out.close(); |
| 262 | + } |
| 263 | + |
| 264 | + } catch (Exception e) { |
| 265 | + System.out.println("\nA Error Occured"); |
| 266 | + e.printStackTrace(); |
| 267 | + } |
| 268 | + return("Done"); |
| 269 | + } |
| 270 | + |
| 271 | + /** checkArgs() |
| 272 | + * |
| 273 | + * This is method validates the command line arguments as best as we can. |
| 274 | + * |
| 275 | + * param - arg[] |
| 276 | + * |
| 277 | + * return - boolean - true of no errors detected else false. |
| 278 | + */ |
| 279 | + public static boolean checkArgs(String[] arg){ |
| 280 | + boolean valid = true; |
| 281 | + if(DEBUG){ for(int i=0;i<arg.length;i++){ System.out.println("DEBUG :: arg "+i+" -"+arg[i]+"-"); }} |
| 282 | + |
| 283 | + // Check Interval time |
| 284 | + if(Integer.parseInt(arg[0]) < 1) { valid = false; System.out.println("EEROR :: runInterval -"+arg[0]+"- is not valid"); } |
| 285 | + |
| 286 | + // Check for the data directory |
| 287 | + File dDir = new File(arg[1]); |
| 288 | + if(!dDir.exists()){ valid = false; System.out.println("EEROR :: dataDir -"+arg[1]+"- is not valid"); } |
| 289 | + |
| 290 | + // Check for the processed directory |
| 291 | + File pDir = new File(arg[2]); |
| 292 | + if(!pDir.exists()){ valid = false; System.out.println("EEROR :: procDir -"+arg[2]+"- is not valid"); } |
| 293 | + |
| 294 | + // Check for the result directory |
| 295 | + File rDir = new File(arg[3]); |
| 296 | + if(!rDir.exists()){ valid = false; System.out.println("EEROR :: resultDir -"+arg[3]+"- is not valid"); } |
| 297 | + |
| 298 | + // Check for a basename |
| 299 | + if(!(arg[4].length() > 0)) { valid = false; System.out.println("EEROR :: basename -"+arg[4]+"- is not valid"); } |
| 300 | + |
| 301 | + return valid; |
| 302 | + } |
| 303 | + |
| 304 | + /** getMemStats() |
| 305 | + * |
| 306 | + * This is method that gets the Memory stats from the string of data |
| 307 | + * |
| 308 | + * param - String containing a record to parse. |
| 309 | + * |
| 310 | + * return - int - value for the % of memory being used. |
| 311 | + */ |
| 312 | + public static int getMemStats(String record){ |
| 313 | + String[] toks = record.split("\\s+"); |
| 314 | + if(DEBUG) { System.out.print("DEBUG :: "); for(int i=0;i<toks.length;i++){ System.out.print(" -"+toks[i]+"-"); } System.out.print("\n");} |
| 315 | + return Integer.parseInt(toks[3]); |
| 316 | + } |
| 317 | + |
| 318 | + /** getCpuStats() |
| 319 | + * |
| 320 | + * This is method that gets the CPU stats from the string of data |
| 321 | + * |
| 322 | + * param - String containing a record to parse. |
| 323 | + * - int array for storing the values of the CPU data |
| 324 | + * |
| 325 | + * return - int[] - with the CPU data for this record. |
| 326 | + */ |
| 327 | + public static int[] getCpuStats(String record, int[] cpuStats){ |
| 328 | + String[] toks = record.split("\\s+"); |
| 329 | + if(DEBUG) { System.out.print("DEBUG :: "); for(int i=0;i<toks.length;i++){ System.out.print(" -"+toks[i]+"-"); } System.out.print("\n");} |
| 330 | + cpuStats[0] = Integer.parseInt(toks[3]); |
| 331 | + cpuStats[1] = Integer.parseInt(toks[4]); |
| 332 | + cpuStats[2] = Integer.parseInt(toks[5]); |
| 333 | + cpuStats[3] = Integer.parseInt(toks[6]); |
| 334 | + cpuStats[4] = Integer.parseInt(toks[7]); |
| 335 | + return cpuStats; |
| 336 | + } |
| 337 | + |
| 338 | + /** getTpsStats() |
| 339 | + * |
| 340 | + * This is method that gets the TPS stats from the string of data |
| 341 | + * |
| 342 | + * param - String containing a record to parse. |
| 343 | + * - int array for storing the values of the TPS data |
| 344 | + * |
| 345 | + * return - int[] - with the TPS data for this record. |
| 346 | + */ |
| 347 | + public static int[] getTpsStats(String record, int[] tpsStats){ |
| 348 | + String[] toks = record.split("\\s+"); |
| 349 | + if(DEBUG) { System.out.print("DEBUG :: "); for(int i=0;i<toks.length;i++){ System.out.print(" -"+toks[i]+"-"); } System.out.print("\n");} tpsStats[0] = tpsStats[0]+Integer.parseInt(toks[3]); |
| 350 | + tpsStats[1] = tpsStats[1]+Integer.parseInt(toks[4]); |
| 351 | + tpsStats[2] = tpsStats[2]+Integer.parseInt(toks[5]); |
| 352 | + tpsStats[3] = tpsStats[3]+Integer.parseInt(toks[6]); |
| 353 | + tpsStats[4] = tpsStats[4]+Integer.parseInt(toks[7]); |
| 354 | + return tpsStats; |
| 355 | + } |
| 356 | + |
| 357 | +} |
0 commit comments