/**
* Copyright 2014 SAP AG
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.spotter.ext.detection.edc;
import java.util.Set;
import java.util.TreeSet;
import org.aim.api.exceptions.InstrumentationException;
import org.aim.api.exceptions.MeasurementException;
import org.aim.api.measurement.dataset.DatasetCollection;
import org.aim.api.measurement.dataset.Parameter;
import org.aim.artifacts.probes.ResponsetimeProbe;
import org.aim.artifacts.probes.SQLQueryProbe;
import org.aim.artifacts.probes.StackTraceProbe;
import org.aim.artifacts.probes.ThreadTracingProbe;
import org.aim.artifacts.scopes.EntryPointScope;
import org.aim.artifacts.scopes.JDBCScope;
import org.aim.description.InstrumentationDescription;
import org.aim.description.builder.InstrumentationDescriptionBuilder;
import org.lpe.common.config.GlobalConfiguration;
import org.lpe.common.extension.IExtension;
import org.lpe.common.util.LpeStringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.spotter.core.ProgressManager;
import org.spotter.core.detection.AbstractDetectionController;
import org.spotter.core.detection.AbstractDetectionExtension;
import org.spotter.core.detection.IDetectionController;
import org.spotter.core.workload.LoadConfig;
import org.spotter.exceptions.WorkloadException;
import org.spotter.ext.detection.edc.strategies.RelativeQueryRTStrategy;
import org.spotter.shared.configuration.ConfigKeys;
import org.spotter.shared.result.model.SpotterResult;
import org.spotter.shared.status.DiagnosisStatus;
public class EDCDetectionController extends AbstractDetectionController {
private static final Logger LOGGER = LoggerFactory.getLogger(EDCDetectionController.class);
public static final String KEY_EXPERIMENT_NAME = "experimentName";
public static final String NAME_SINGLE_USER_EXP = "singleUserExp";
public static final String NAME_MAIN_EXP = "mainExp";
public static final String NAME_STACK_TRACE_EXP = "stackTraceExp";
public static final String NAME_HIERARCHY_EXP = "hierarchyExp";
private IEDCAnalysisStrategy strategy = new RelativeQueryRTStrategy();
private boolean reuser = false;
private double instrumentationGranularity;
public EDCDetectionController(IExtension<IDetectionController> provider) {
super(provider);
}
@Override
public void loadProperties() {
reuser = Boolean.parseBoolean(this.getProblemDetectionConfiguration().getProperty(
AbstractDetectionExtension.REUSE_EXPERIMENTS_FROM_PARENT, "false"));
String sGranularity = getProblemDetectionConfiguration().getProperty(
EDCExtension.INSTRUMENTATION_GRANULARITY_KEY,
String.valueOf(EDCExtension.INSTRUMENTATION_GRANULARITY_DEFAULT));
if (!sGranularity.matches("0|1|0.[0-9]+")) {
instrumentationGranularity = EDCExtension.INSTRUMENTATION_GRANULARITY_DEFAULT;
} else {
instrumentationGranularity = Double.parseDouble(sGranularity);
}
strategy.init(getProblemDetectionConfiguration(), this);
}
@Override
public long getExperimentSeriesDuration() {
if (reuser) {
return 0;
} else {
return Integer.parseInt(LpeStringUtils.getPropertyOrFail(GlobalConfiguration.getInstance().getProperties(),
ConfigKeys.WORKLOAD_MAXUSERS, null)) * 4;
}
}
@Override
public void executeExperiments() throws InstrumentationException, MeasurementException, WorkloadException {
if (!reuser) {
int maxUsers = Integer.parseInt(LpeStringUtils.getPropertyOrFail(GlobalConfiguration.getInstance()
.getProperties(), ConfigKeys.WORKLOAD_MAXUSERS, null));
LOGGER.debug("Hierarchy description:\n" + getServletHierarchyDescription());
instrumentApplication(getServletHierarchyDescription());
runExperiment(this, 1, NAME_HIERARCHY_EXP);
uninstrumentApplication();
LOGGER.debug("Single user description:\n" + getMainInstrumentationDescription(false));
instrumentApplication(getMainInstrumentationDescription(false));
runExperiment(this, 1, NAME_SINGLE_USER_EXP);
uninstrumentApplication();
LOGGER.debug("Mutli user description:\n" + getMainInstrumentationDescription(true));
instrumentApplication(getMainInstrumentationDescription(true));
runExperiment(this, maxUsers, NAME_MAIN_EXP);
uninstrumentApplication();
LOGGER.debug("Stack trace description:\n" + getStackTraceInstrDescription());
instrumentApplication(getStackTraceInstrDescription());
runExperiment(this, 1, NAME_STACK_TRACE_EXP);
uninstrumentApplication();
}
}
@Override
protected SpotterResult analyze(DatasetCollection data) {
strategy.setMeasurementData(data);
return strategy.analyze();
}
private InstrumentationDescription getMainInstrumentationDescription(boolean useGranularity) {
InstrumentationDescriptionBuilder idBuilder = new InstrumentationDescriptionBuilder();
idBuilder.newAPIScopeEntity(EntryPointScope.class.getName()).addProbe(ResponsetimeProbe.MODEL_PROBE)
.addProbe(ThreadTracingProbe.MODEL_PROBE).entityDone();
idBuilder.newAPIScopeEntity(JDBCScope.class.getName()).addProbe(SQLQueryProbe.MODEL_PROBE)
.addProbe(ResponsetimeProbe.MODEL_PROBE).addProbe(ThreadTracingProbe.MODEL_PROBE).entityDone();
if (useGranularity) {
idBuilder.newGlobalRestriction().setGranularity(instrumentationGranularity).restrictionDone();
}
return idBuilder.build();
}
private InstrumentationDescription getStackTraceInstrDescription() {
InstrumentationDescriptionBuilder idBuilder = new InstrumentationDescriptionBuilder();
idBuilder.newAPIScopeEntity(JDBCScope.class.getName()).addProbe(StackTraceProbe.MODEL_PROBE)
.addProbe(SQLQueryProbe.MODEL_PROBE).entityDone();
return idBuilder.build();
}
private InstrumentationDescription getServletHierarchyDescription() {
InstrumentationDescriptionBuilder idBuilder = new InstrumentationDescriptionBuilder();
idBuilder.newAPIScopeEntity(EntryPointScope.class.getName()).addProbe(ResponsetimeProbe.MODEL_PROBE)
.entityDone();
return idBuilder.build();
}
private void runExperiment(IDetectionController detectionController, int numUsers, String experimentName)
throws WorkloadException, MeasurementException {
LOGGER.info("{} detection controller started experiment with {} users ...", detectionController.getProvider()
.getName(), numUsers);
ProgressManager.getInstance().updateProgressStatus(getProblemId(), DiagnosisStatus.EXPERIMENTING_RAMP_UP);
LoadConfig lConfig = new LoadConfig();
lConfig.setNumUsers(numUsers);
lConfig.setRampUpIntervalLength(GlobalConfiguration.getInstance().getPropertyAsInteger(
ConfigKeys.EXPERIMENT_RAMP_UP_INTERVAL_LENGTH));
lConfig.setRampUpUsersPerInterval(GlobalConfiguration.getInstance().getPropertyAsInteger(
ConfigKeys.EXPERIMENT_RAMP_UP_NUM_USERS_PER_INTERVAL));
lConfig.setCoolDownIntervalLength(GlobalConfiguration.getInstance().getPropertyAsInteger(
ConfigKeys.EXPERIMENT_COOL_DOWN_INTERVAL_LENGTH));
lConfig.setCoolDownUsersPerInterval(GlobalConfiguration.getInstance().getPropertyAsInteger(
ConfigKeys.EXPERIMENT_COOL_DOWN_NUM_USERS_PER_INTERVAL));
lConfig.setExperimentDuration(GlobalConfiguration.getInstance().getPropertyAsInteger(
ConfigKeys.EXPERIMENT_DURATION));
if (NAME_STACK_TRACE_EXP.equals(experimentName)) {
lConfig.setExperimentDuration(300);
}
getWorkloadAdapter().startLoad(lConfig);
getWorkloadAdapter().waitForWarmupPhaseTermination();
ProgressManager.getInstance().updateProgressStatus(getProblemId(), DiagnosisStatus.EXPERIMENTING_STABLE_PHASE);
getMeasurementController().enableMonitoring();
getWorkloadAdapter().waitForExperimentPhaseTermination();
ProgressManager.getInstance().updateProgressStatus(getProblemId(), DiagnosisStatus.EXPERIMENTING_COOL_DOWN);
getMeasurementController().disableMonitoring();
getWorkloadAdapter().waitForFinishedLoad();
ProgressManager.getInstance().updateProgressStatus(getProblemId(), DiagnosisStatus.COLLECTING_DATA);
LOGGER.info("Storing data ...");
long dataCollectionStart = System.currentTimeMillis();
Parameter experimentNameParameter = new Parameter(KEY_EXPERIMENT_NAME, experimentName);
Set<Parameter> parameters = new TreeSet<>();
parameters.add(experimentNameParameter);
getResultManager().storeResults(parameters, getMeasurementController());
ProgressManager.getInstance()
.addAdditionalDuration((System.currentTimeMillis() - dataCollectionStart) / SECOND);
LOGGER.info("Data stored!");
}
}