/******************************************************************************* * ALMA - Atacama Large Millimeter Array * Copyright (c) ESO - European Southern Observatory, 2011 * (in the framework of the ALMA collaboration). * All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *******************************************************************************/ package alma.acs.profiling.orb; import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.logging.Logger; import java.util.regex.Pattern; import alma.acs.util.IsoDateFormat; import alma.acs.util.StopWatch; /** * Parser for output from {@link AcsORBProfilerImplBase} and also for additional profiler output * to be generated in the future. * @author hsommer */ public class OrbProfilerParser { private final Logger logger; /** * Uses delimiters ' ', ',', '(', ')' and reduces multiple delimiter occurrences. * (Parsing is in total ~15% faster using a precompiled pattern for splitting the lines. Not that it matters, done just out of curiosity.) */ private final Pattern msgSplitPattern = Pattern.compile("[ ,()]+"); /** * @param logger * @param stdoutLogFile * throws IllegalArgumentException if <code>stdoutLogFile</code> is missing or cannot be read. */ public OrbProfilerParser(Logger logger) { this.logger = logger; } /** * Parses the given file and returns the profiler messages extracted from the file as a list for further processing. */ public List<ProfilerMessage> parse(File stdoutLogFile) throws IOException { if (stdoutLogFile == null) { throw new IllegalArgumentException("No data file specified (null)."); } else if (!stdoutLogFile.exists() || !stdoutLogFile.canRead()) { throw new IllegalArgumentException("Data file " + stdoutLogFile.getAbsolutePath() + " does not exist or cannot be read."); } StopWatch sw = new StopWatch(logger); List<ProfilerMessage> messages = new ArrayList<ProfilerMessage>(); BufferedReader reader = new BufferedReader(new FileReader(stdoutLogFile)); String line = null; int lineCount = 0; try { while ((line = reader.readLine()) != null) { lineCount++; ProfilerMessage msg = parseLine(line); if (msg == null) { // System.out.println("Skipping line: " + line); } else { messages.add(msg); } } } finally { reader.close(); } logger.info("Parsed file " + stdoutLogFile.getAbsolutePath() + " in " + sw.getLapTimeMillis() + " ms, found " + lineCount + " lines total, and " + messages.size() + " orb profiler messages."); return messages; } /** * Parses a line of orb profiler stdout output. * Returns a {@link ProfilerMessage} instance if the line could be parsed, <code>null</code> otherwise. */ protected ProfilerMessage parseLine(String line) { String[] words = msgSplitPattern.split(line); ProfilerMessage ret = null; if (words.length >= 4) { // other lines are anyway not matching, prevents ArrayIndexOutOfetc try { if (words[0].equals("connectionThreadPoolSizeChanged")) { // connectionThreadPoolSizeChanged: idleThreads=0, totalThreads=1, maxThreads=1000 } else if (words[0].equals("undeliveredRequest")) { // undeliveredRequest: messageSize=xxx, poaName=yyy, operation=zzz } else if (words[0].equals("requestQueueSizeChanged")) { // requestQueueSizeChanged: requestId=172, poaName=ComponentPOA_DefaultComponentWithBadNulls, queueSize=0, maxQueueLength=100 } else if (words[0].equals("threadPoolSizeChanged")) { // threadPoolSizeChanged: poaName=null, idleThreads=4, totalThreads=5, maxThreads=20 } else if (words[1].equals("requestStarted")) { // 2012-03-20T16:47:58.833 requestStarted(30, dalPOA, get_string, 23) ret = new ProfilerMessage(ProfilerMessage.Type.REQUEST_STARTED); ret.timestamp = IsoDateFormat.parseIsoTimestamp(words[0]).getTime(); ret.requestId = Integer.parseInt(words[2]); ret.poaName = words[3]; ret.operation = words[4]; ret.threadId = Long.parseLong(words[5]); } else if (words[1].equals("requestFinished")) { // 2012-03-20T16:47:58.833 requestFinished(30, dalPOA, get_string, 23) in 0 ms ret = new ProfilerMessage(ProfilerMessage.Type.REQUEST_FINISHED); ret.timestamp = IsoDateFormat.parseIsoTimestamp(words[0]).getTime(); ret.requestId = Integer.parseInt(words[2]); ret.poaName = words[3]; ret.operation = words[4]; ret.threadId = Long.parseLong(words[5]); ret.timeElapsedMillis = Integer.parseInt(words[7]); } } catch (Exception ex) { ex.printStackTrace(); } } return ret; } }