package alma.acs.manager.logparser;
import static org.junit.Assert.assertEquals;
import java.io.File;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.math.stat.descriptive.DescriptiveStatistics;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import alma.acs.algorithms.DataBinner;
import alma.acs.algorithms.DataBinner.BinnedTimeValues;
import alma.acs.algorithms.DataBinner.TimeValue;
import alma.acs.logging.testsupport.JUnit4StandaloneTestBase;
import alma.acs.manager.logparser.ManagerStdoutParser.ComponentRequest;
import alma.acs.manager.logparser.ManagerStdoutParser.ComponentRequestKey;
import alma.acs.util.IsoDateFormat;
/**
* Test for manager stdout log parser.
* This test can be modified to analyze other manager output data for debugging.
*/
public class ManagerStdoutParserTest extends JUnit4StandaloneTestBase
{
@Before
public void setUp() throws Exception {
super.setUp();
logger.info("--------- " + testMethodName + " ---------");
}
@After
public void tearDown() throws Exception {
super.tearDown();
}
@Test
public void testParseLine() throws Exception {
ManagerStdoutParser parser = new ManagerStdoutParser(logger);
Map<ComponentRequestKey, List<ComponentRequest>> pendingRequests = new HashMap<ComponentRequestKey, List<ComponentRequest>>();
List<ComponentRequest> finishedRequests = new ArrayList<ComponentRequest>();
parser.parseLine("2011-09-30T21:34:20.084 INFO [Manager] 'Python Client' requested component 'curl:///CONTROL/DV15/Mount'.", pendingRequests, finishedRequests);
parser.parseLine("2011-09-30T21:38:20.008 FINE [Manager] 'CCLSimpleClient' requested non-sticky component 'curl:///CONTROL/DA43/WVR'.", pendingRequests, finishedRequests);
assertEquals(2, pendingRequests.keySet().size());
assertEquals(0, finishedRequests.size());
parser.parseLine("2011-09-30T21:34:20.085 INFO [Manager] Component 'curl:///CONTROL/DV15/Mount' provided to 'Python Client'.", pendingRequests, finishedRequests);
assertEquals(1, pendingRequests.keySet().size());
assertEquals(1, finishedRequests.size());
ComponentRequest request = finishedRequests.get(0);
assertEquals("Python Client", request.key.clientName);
assertEquals("curl:///CONTROL/DV15/Mount", request.key.curl);
assertEquals("2011-09-30T21:34:20.084", toISO(request.timeRequested));
assertEquals("2011-09-30T21:34:20.085", toISO(request.timeProvided));
logger.info("Got ComponentRequest as expected: " + request);
pendingRequests.clear();
finishedRequests.clear();
// Unmatched 'provided to', should also log a WARNING which we currently don't check here
parser.parseLine("2011-09-30T21:34:20.085 INFO [Manager] Component 'curl:///CONTROL/DV15/Mount' provided to 'Python Client'.", pendingRequests, finishedRequests);
assertEquals(0, pendingRequests.keySet().size());
assertEquals(0, finishedRequests.size());
}
@Test
public void testParseManagerOutput() throws Exception, ParseException {
String fileName = "sampleOutput/acsManager_2012-03-20_16.48.20.642";
ManagerStdoutParser parser = new ManagerStdoutParser(logger);
List<ComponentRequest> requests = parser.parse(new File(fileName));
// to select only logs between these two timestamps
long t0 = IsoDateFormat.parseIsoTimestamp("2011-11-13T20:47:17.328").getTime();
long t1 = IsoDateFormat.parseIsoTimestamp("2011-11-13T21:29:48.314").getTime();
List<TimeValue<ComponentRequest>> data = new ArrayList<TimeValue<ComponentRequest>>();
for (ComponentRequest r : requests) {
// if (r.timeRequested >= t0 && r.timeRequested <= t1) {
data.add(new TimeValue<ComponentRequest>(r.timeRequested, r));
System.out.println(toISO(r.timeRequested) + ", " + (r.timeProvided-r.timeRequested) + ", " + r.key.curl.substring(8) + ", " + r.key.clientName);
// }
}
Collections.sort(data);
DecimalFormat df = new DecimalFormat();
df.setMaximumFractionDigits(2);
int binIntervalSec = 5;
DataBinner binner = new DataBinner();
List<BinnedTimeValues<ComponentRequest>> binned = binner.binTimedData(data, binIntervalSec * 1000);
// System.out.println("Time interval\t#Requests by 'Python Client'/" + binIntervalSec +
// "s\t#Requests by other clients/" + binIntervalSec + "s" + "\t" + "Average response time/ms");
System.out.println("Time interval\t#Requests/" + binIntervalSec +
"s interval\tAverage response time/ms");
for (BinnedTimeValues<ComponentRequest> binnedTimeValues : binned) {
long timeCurrentBin = binnedTimeValues.timeMillis;
List<TimeValue<ComponentRequest>> valuesCurrentBin = binnedTimeValues.binnedData;
int numCallsPythonClient = 0;
int numCallsOtherClients = 0;
DescriptiveStatistics callTimeStats = new DescriptiveStatistics();
for (TimeValue<ComponentRequest> timeValue : valuesCurrentBin) {
ComponentRequest r = timeValue.value;
if (r.key.clientName.equals("Python Client")) {
numCallsPythonClient++;
}
else {
numCallsOtherClients++;
}
callTimeStats.addValue(r.timeProvided - r.timeRequested); // duration in ms
}
System.out.println(toISO(timeCurrentBin) + "\t" + (numCallsPythonClient+numCallsOtherClients) + "\t" + df.format(callTimeStats.getMean()));
}
}
private String toISO(long time) {
return IsoDateFormat.formatDate(new Date(time));
}
}