All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.mgmtp.perfload.perfalyzer.PerfAlyzer Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 2013-2015 mgm technology partners GmbH
 *
 * 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 com.mgmtp.perfload.perfalyzer;

import static com.google.common.base.Preconditions.checkState;
import static com.mgmtp.perfload.perfalyzer.util.DirectoryLister.listAllPerfAlyzerFiles;
import static com.mgmtp.perfload.perfalyzer.util.DirectoryLister.listPerfAlyzerFiles;
import static com.mgmtp.perfload.perfalyzer.util.IoUtilities.writeLineToChannel;
import static java.nio.charset.StandardCharsets.UTF_8;
import static java.nio.file.Files.newByteChannel;
import static java.nio.file.StandardOpenOption.CREATE;
import static java.nio.file.StandardOpenOption.WRITE;
import static org.apache.commons.io.FileUtils.copyDirectoryToDirectory;
import static org.apache.commons.io.FileUtils.deleteDirectory;

import java.io.File;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.channels.WritableByteChannel;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import java.util.concurrent.ExecutorService;

import javax.annotation.Nullable;
import javax.inject.Inject;
import javax.inject.Singleton;

import org.apache.commons.lang3.text.StrTokenizer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.beust.jcommander.JCommander;
import com.beust.jcommander.ParameterException;
import com.google.common.base.Stopwatch;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.mgmtp.perfload.perfalyzer.annotations.BinnedDir;
import com.mgmtp.perfload.perfalyzer.annotations.DoBinning;
import com.mgmtp.perfload.perfalyzer.annotations.DoNormalization;
import com.mgmtp.perfload.perfalyzer.annotations.DoReportPreparation;
import com.mgmtp.perfload.perfalyzer.annotations.NormalizedDir;
import com.mgmtp.perfload.perfalyzer.annotations.ReportDir;
import com.mgmtp.perfload.perfalyzer.annotations.ReportPreparationDir;
import com.mgmtp.perfload.perfalyzer.annotations.UnzippedDir;
import com.mgmtp.perfload.perfalyzer.reporting.ReportCreator;
import com.mgmtp.perfload.perfalyzer.reporting.email.EmailReporter;
import com.mgmtp.perfload.perfalyzer.util.Marker;
import com.mgmtp.perfload.perfalyzer.util.PerfAlyzerFile;
import com.mgmtp.perfload.perfalyzer.workflow.WorkflowExecutor;

/**
 * The PerfAlyzer class is the entry point for the application.
 *
 * @author ctchinda
 */
@Singleton
public class PerfAlyzer {

	private static final Logger LOG = LoggerFactory.getLogger(PerfAlyzer.class);

	private final boolean doReportPreparation;
	private final boolean doNormalization;
	private final boolean doBinning;

	private final File unzippedDir;
	private final File normalizedDir;
	private final File binnedDir;
	private final File reportPreparationDir;
	private final File reportDir;

	private final WorkflowExecutor workflowExecutor;
	private final ReportCreator reportCreator;
	private final EmailReporter emailReporter;
	private final List markers;

	@Inject
	public PerfAlyzer(@UnzippedDir final File unzippedDir, @BinnedDir final File binningDir,
			@NormalizedDir final File normalizedDir, @ReportPreparationDir final File reportPreparationDir,
			@ReportDir final File reportDir, @DoNormalization final boolean doNormalization,
			@DoBinning final boolean doBinning, @DoReportPreparation final boolean doReportPreparation,
			final WorkflowExecutor workflowExecutor, final ReportCreator reportCreator,
			@Nullable final EmailReporter emailReporter, final List markers) {

		this.unzippedDir = unzippedDir;
		this.binnedDir = binningDir;
		this.normalizedDir = normalizedDir;
		this.reportPreparationDir = reportPreparationDir;
		this.reportDir = reportDir;

		this.doNormalization = doNormalization;
		this.doBinning = doBinning;
		this.doReportPreparation = doReportPreparation;

		this.workflowExecutor = workflowExecutor;
		this.reportCreator = reportCreator;
		this.emailReporter = emailReporter;

		this.markers = markers;
	}

	public static void main(final String[] args) {
		JCommander jCmd = null;
		try {
			Stopwatch stopwatch = Stopwatch.createStarted();
			LOG.info("Starting perfAlyzer...");

			LOG.info("Arguments:");
			for (String arg : args) {
				LOG.info(arg);
			}
			PerfAlyzerArgs perfAlyzerArgs = new PerfAlyzerArgs();

			jCmd = new JCommander(perfAlyzerArgs);
			jCmd.parse(args);

			Injector injector = Guice.createInjector(new PerfAlyzerModule(perfAlyzerArgs));
			PerfAlyzer perfAlyzer = injector.getInstance(PerfAlyzer.class);
			perfAlyzer.runPerfAlyzer();

			ExecutorService executorService = injector.getInstance(ExecutorService.class);
			executorService.shutdownNow();

			stopwatch.stop();
			LOG.info("Done.");
			LOG.info("Total execution time: {}", stopwatch);
		} catch (ParameterException ex) {
			LOG.error(ex.getMessage());
			StringBuilder sb = new StringBuilder(200);
			jCmd.usage(sb);
			LOG.info(sb.toString());
			System.exit(1);
		} catch (Exception ex) {
			LOG.error(ex.getMessage(), ex);
			System.exit(1);
		}
	}

	public void runPerfAlyzer() throws IOException {
		checkDirs();
		executeWorkflows();
		createReport();
	}

	private void checkDirs() throws IOException {
		if (doNormalization) {
			if (normalizedDir.isDirectory()) {
				LOG.info("Directory '{}' already exists. Deleting it...", normalizedDir);
				deleteDirectory(normalizedDir);
			}
		} else {
			checkState(normalizedDir.isDirectory(),
					"Normalization was turned off, but directory with normalized files does not exist or is not a directory: %s",
					normalizedDir);
		}

		if (doBinning) {
			if (binnedDir.isDirectory()) {
				LOG.info("Directory '{}' already exists. Deleting it...", binnedDir);
				deleteDirectory(binnedDir);
			}
		} else {
			checkState(binnedDir.isDirectory(),
					"Binning was turned off, but directory with binned files does not exist or is not a directory: %s", binnedDir);
		}

		if (doReportPreparation) {
			if (reportPreparationDir.isDirectory()) {
				LOG.info("Directory '{}' already exists. Deleting it...", reportPreparationDir);
				deleteDirectory(reportPreparationDir);
			}
		} else {
			checkState(
					reportPreparationDir.isDirectory(),
					"Report preparation was turned off, but directory with report preparation files does not exist or is not a directory: %s",
					reportPreparationDir);
		}

		if (reportDir.isDirectory()) {
			LOG.info("Directory '{}' already exists. Deleting it...", reportDir);
			deleteDirectory(reportDir);
		}
	}

	private void executeWorkflows() {
		LOG.info("Executing workflows...");

		if (doNormalization) {
			workflowExecutor.executeNormalizationTasks(unzippedDir, normalizedDir);
			extractFilesForMarkers();
		}

		if (doBinning) {
			workflowExecutor.executeBinningTasks(normalizedDir, binnedDir);
		}

		if (doReportPreparation) {
			workflowExecutor.executeReportPreparationTasks(binnedDir, reportPreparationDir);
		}
	}

	private void extractFilesForMarkers() {
		if (!markers.isEmpty()) {
			listPerfAlyzerFiles(normalizedDir)
			.stream()
			.filter(perfAlyzerFile -> {
				// GC logs cannot split up here and need to explicitly handle markers later.
				// Load profiles contains the markers themselves and thus need to be filtered out as well.
				String fileName = perfAlyzerFile.getFile().getName();
				return !fileName.contains("gclog") & !fileName.contains("[loadprofile]");
			} )
			.forEach(perfAlyzerFile -> markers.forEach(marker -> {
				PerfAlyzerFile markerFile = perfAlyzerFile.copy();
				markerFile.setMarker(marker.getName());
				Path destPath = normalizedDir.toPath().resolve(markerFile.getFile().toPath());

				try (WritableByteChannel destChannel = newByteChannel(destPath, CREATE, WRITE)) {
					Path srcPath = normalizedDir.toPath().resolve(perfAlyzerFile.getFile().toPath());
					StrTokenizer tokenizer = StrTokenizer.getCSVInstance();
					tokenizer.setDelimiterChar(';');
					Files.lines(srcPath, UTF_8).filter(line -> {
						try {
							tokenizer.reset(line);
							String timestampString = tokenizer.nextToken();
							long timestamp = Long.parseLong(timestampString);
							return marker.getLeftMillis() <= timestamp && marker.getRightMillis() > timestamp;
						} catch (NumberFormatException ex) {
							LOG.error("Invalid data line: {}", line);
							return false;
						}
					} ).forEach(line -> writeLineToChannel(destChannel, line, UTF_8));
				} catch (IOException e) {
					throw new UncheckedIOException(e);
				}
			} ));
		}
	}

	private void createReport() throws IOException {
		LOG.info("Writing report...");
		reportCreator.createReport(listAllPerfAlyzerFiles(reportPreparationDir));

		// copy assets
		copyDirectoryToDirectory(new File("assets"), reportDir);

		if (emailReporter != null) {
			LOG.info("Creating e-mail report...");
			emailReporter.createAndSendReportMail();
		}
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy