/* * JMeter Report Server * Copyright (C) 2010 eXcentia * dev@sonar.codehaus.org * * This program 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 3 of the License, or (at your option) any later version. * * This program 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 program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 */ package es.excentia.jmeter.report.server.report; import java.util.HashMap; import java.util.Map; import es.excentia.jmeter.report.client.serialization.StreamReader; import es.excentia.jmeter.report.server.service.ReaderService; import es.excentia.jmeter.report.server.service.ServiceFactory; import es.excentia.jmeter.report.server.testresults.SampleMix; import es.excentia.jmeter.report.server.testresults.xmlbeans.HttpSample; import es.excentia.jmeter.report.server.testresults.xmlbeans.Sample; @SuppressWarnings("unchecked") public class Report { /** * Dos fases: En la primera pasada obtendremos la media y la mayoría de los * datos y en la segunda obtendremos las desviaciones típicas */ int actualPhaseIndex; int getActualPhaseIndex() { return actualPhaseIndex; } public static final int FIRST_PHASE = 0; public static final int SECOND_PHASE = 1; public static final int SCOPE_REQUEST_GLOBAL = 1; public static final int SCOPE_TRANS_GLOBAL = 2; public static final int SCOPE_TRANS_TYPE = 3; public static final int SCOPE_ALL = 4; protected ReaderService readerService = ServiceFactory.get(ReaderService.class); OkUserAccessCounter okUserAccessCounter; public long getNumUsersLogged() { return okUserAccessCounter.getDistictUsersCount(); } Duration testDuration; public long getTestDuration() { return testDuration.getDuration(); } public double getTestDurationInMinutes() { return testDuration.getDurationInMinutes(); } String actualTransName; String getActualTransName() { return actualTransName; } Map<String, Class<?>> requestGlobalDataClasses = new HashMap<String, Class<?>>(); Map<String, Class<?>> transGlobalDataClasses = new HashMap<String, Class<?>>(); Map<String, Class<?>> transTypeDataClasses = new HashMap<String, Class<?>>(); Map<String, ReportData>[] requestGlobalData = new Map[2]; Map<String, ReportData>[] transGlobalData = new Map[2]; Map<String, Map<String, ReportData>>[] transTypeData = new Map[2]; public <T extends ReportData> void addData(Class<T> clazz, int scope) { if (scope == SCOPE_ALL) { requestGlobalDataClasses.put(clazz.getSimpleName(), clazz); transGlobalDataClasses.put(clazz.getSimpleName(), clazz); transTypeDataClasses.put(clazz.getSimpleName(), clazz); return; } switch (scope) { case SCOPE_TRANS_GLOBAL: transGlobalDataClasses.put(clazz.getSimpleName(), clazz); break; case SCOPE_TRANS_TYPE: transTypeDataClasses.put(clazz.getSimpleName(), clazz); break; // case SCOPE_REQUEST_GLOBAL: default: requestGlobalDataClasses.put(clazz.getSimpleName(), clazz); break; } } public <T extends ReportData> T getDataRequestGlobal(Class<T> clazz) { int phase = getPhasesByClass(clazz)[0]; return (T) requestGlobalData[phase].get(clazz.getSimpleName()); } public <T extends ReportData> T getDataTransGlobal(Class<T> clazz) { int phase = getPhasesByClass(clazz)[0]; return (T) transGlobalData[phase].get(clazz.getSimpleName()); } public <T extends ReportData> Map<String, T> getDataTransType(Class<T> clazz) { int phase = getPhasesByClass(clazz)[0]; return (Map<String, T>) transTypeData[phase].get(clazz.getSimpleName()); } public void init() { actualPhaseIndex = 0; actualTransName = null; okUserAccessCounter = (OkUserAccessCounter) createSummaryData(OkUserAccessCounter.class); testDuration = (Duration) createSummaryData(Duration.class); for (int phase = 0; phase < 2; phase++) { requestGlobalData[phase] = new HashMap<String, ReportData>(); transGlobalData[phase] = new HashMap<String, ReportData>(); transTypeData[phase] = new HashMap<String, Map<String, ReportData>>(); } for (String dataName : requestGlobalDataClasses.keySet()) { Class<?> dataClass = requestGlobalDataClasses.get(dataName); int phases[] = getPhasesByClass(dataClass); ReportData data = createSummaryData(dataClass); for (int phase : phases) { requestGlobalData[phase].put(dataName, data); } } for (String dataName : transGlobalDataClasses.keySet()) { Class<?> dataClass = transGlobalDataClasses.get(dataName); int phases[] = getPhasesByClass(dataClass); ReportData data = createSummaryData(dataClass); for (int phase : phases) { transGlobalData[phase].put(dataName, data); } } for (String dataName : transTypeDataClasses.keySet()) { Class<?> dataClass = transTypeDataClasses.get(dataName); int phases[] = getPhasesByClass(dataClass); Map<String, ReportData> transDataMap = new HashMap<String, ReportData>(); for (int phase : phases) { transTypeData[phase].put(dataName, transDataMap); } } } public void extract(String config) { init(); StreamReader<SampleMix> reader; for (int phase = FIRST_PHASE; phase <= SECOND_PHASE; phase++) { reader = readerService.getSampleMixReaderByTestConfig(config); SampleMix sampleMix = reader.read(); while (sampleMix != null) { // Analizamos requests for (HttpSample request : sampleMix.getHttpSamples()) { if (phase == FIRST_PHASE) { testDuration.addMeasure(request); okUserAccessCounter.addMeasure(request); } for (String dataName : requestGlobalData[phase].keySet()) { ReportData data = requestGlobalData[phase].get(dataName); data.addMeasure(request); } } // Analizamos transacciones for (Sample trans : sampleMix.getTransactions()) { actualTransName = trans.getLb(); for (String dataName : transGlobalData[phase].keySet()) { ReportData data = transGlobalData[phase].get(dataName); data.addMeasure(trans); } for (String dataName : transTypeData[phase].keySet()) { Map<String, ReportData> transDataMap = transTypeData[phase] .get(dataName); ReportData data = transDataMap.get(actualTransName); if (data == null) { Class<?> summaryDataClass = transTypeDataClasses.get(dataName); data = createSummaryData(summaryDataClass); transDataMap.put(actualTransName, data); } data.addMeasure(trans); } } actualTransName = null; sampleMix = reader.read(); } actualPhaseIndex++; } } protected ReportData createSummaryData(Class<?> summaryDataClass) { ReportData data; try { data = (ReportData) summaryDataClass.getConstructors()[0].newInstance(new Object[] {}); } catch (Exception e) { throw new ReportException(e); } data.setSummary(this); return data; } protected int[] getPhasesByClass(Class<?> dataClass) { if (Average.class.isAssignableFrom(dataClass)) { return new int[] { FIRST_PHASE, SECOND_PHASE }; } else { return new int[] { FIRST_PHASE }; } } @Override public String toString() { StringBuffer buff = new StringBuffer(); buff.append("\n** Request Global Scope **"); for (int phase = 0; phase < 2; phase++) { buff.append('\n'); buff.append(requestGlobalData[phase].toString()); } buff.append("\n\n** Transaction Global Scope **"); for (int phase = 0; phase < 2; phase++) { buff.append('\n'); buff.append(transGlobalData[phase].toString()); } buff.append("\n\n** Transaction Type Scope **"); for (int phase = 0; phase < 2; phase++) { buff.append('\n'); buff.append(transTypeData[phase].toString()); } buff.append('\n'); return buff.toString(); } }