com.intuit.tank.service.impl.v1.report.SummaryReportRunner.java Source code

Java tutorial

Introduction

Here is the source code for com.intuit.tank.service.impl.v1.report.SummaryReportRunner.java

Source

/**
 * Copyright 2011 Intuit Inc. All Rights Reserved
 */
package com.intuit.tank.service.impl.v1.report;

/*
 * #%L
 * Reporting Rest Service Implementation
 * %%
 * Copyright (C) 2011 - 2015 Intuit Inc.
 * %%
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 * #L%
 */

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.enterprise.event.Event;

import org.apache.commons.math3.stat.descriptive.DescriptiveStatistics;
import org.apache.log4j.Logger;

import com.intuit.tank.api.service.v1.report.ReportService;
import com.intuit.tank.dao.JobInstanceDao;
import com.intuit.tank.dao.PeriodicDataDao;
import com.intuit.tank.dao.SummaryDataDao;
import com.intuit.tank.persistence.databases.BucketDataItem;
import com.intuit.tank.persistence.databases.MetricsCalculator;
import com.intuit.tank.project.JobInstance;
import com.intuit.tank.project.PeriodicData;
import com.intuit.tank.project.PeriodicDataBuilder;
import com.intuit.tank.project.SummaryData;
import com.intuit.tank.project.SummaryDataBuilder;
import com.intuit.tank.reporting.api.ResultsReader;
import com.intuit.tank.reporting.factory.ReportingFactory;
import com.intuit.tank.vm.api.enumerated.JobLifecycleEvent;
import com.intuit.tank.vm.common.util.MethodTimer;
import com.intuit.tank.vm.event.JobEvent;

/**
 * NotificationRunner
 * 
 * @author dangleton
 * 
 */
public class SummaryReportRunner implements Runnable {
    private static final Logger LOG = Logger.getLogger(SummaryReportRunner.class);
    private static final char NEWLINE = '\n';

    private JobEvent jobEvent;
    private Event<JobEvent> jobEventProducer;
    private String rootUrl;

    /**
     * 
     * @param jobEventProducer
     * @param jobEvent
     */
    public SummaryReportRunner(String rootUrl, Event<JobEvent> jobEventProducer, JobEvent jobEvent) {
        this.jobEvent = jobEvent;
        this.jobEventProducer = jobEventProducer;
        this.rootUrl = rootUrl;
    }

    /**
     * @{inheritDoc
     */
    @Override
    public void run() {
        String jobId = jobEvent.getJobId();
        generateSummary(jobEvent.getJobId());
        jobEventProducer
                .fire(new JobEvent(jobId, getSummaryEventMessage(), JobLifecycleEvent.SUMMARY_REPORT_FINISHED));
    }

    /**
     * @return
     */
    private String getSummaryEventMessage() {
        StringBuilder sb = new StringBuilder();
        sb.append("Summary Timing Data Report for job " + jobEvent.getJobId() + " is ready for download.")
                .append(NEWLINE).append(NEWLINE);
        sb.append("The report can be downloaded at ").append(rootUrl).append("/rest")
                .append(ReportService.SERVICE_RELATIVE_PATH).append(ReportService.METHOD_TIMING_SUMMARY_CSV)
                .append('/').append(jobEvent.getJobId());
        return sb.toString();
    }

    /**
     * @param db
     * @param tableName
     */
    public static void generateSummary(String jobIdString) {
        synchronized (jobIdString) {
            LOG.info("generateSummary: job " + jobIdString);
            ResultsReader resultsReader = ReportingFactory.getResultsReader();
            if (resultsReader.hasTimingData(jobIdString)) {
                LOG.info("Generating Summary Report for job " + jobIdString + "...");
                SummaryDataDao dao = new SummaryDataDao();
                int jobId = Integer.parseInt(jobIdString);
                if (dao.findByJobId(jobId).size() == 0) {
                    MethodTimer mt = new MethodTimer(LOG, SummaryReportRunner.class, "generateSummary");
                    MetricsCalculator metricsCalculator = new MetricsCalculator();
                    JobInstance jobInstance = new JobInstanceDao().findById(Integer.valueOf(jobIdString));
                    metricsCalculator.retrieveAndCalculateTimingData(jobIdString,
                            calculateSteadyStateStart(jobInstance), calculateSteadyStateEnd(jobInstance));
                    mt.markAndLog("calculated timing data");
                    Map<String, DescriptiveStatistics> timingData = metricsCalculator.getSummaryResults();
                    if (!timingData.isEmpty()) {
                        try {
                            List<SummaryData> toStore = new ArrayList<SummaryData>();
                            for (Entry<String, DescriptiveStatistics> entry : timingData.entrySet()) {
                                SummaryData data = getSummaryData(jobId, entry.getKey(), entry.getValue());
                                toStore.add(data);
                            }
                            dao.persistCollection(toStore);
                            LOG.info("Finished Summary Report for job " + jobId);
                        } catch (Exception t) {
                            LOG.error("Error adding Summary Items: " + t, t);
                        }
                    }
                    mt.markAndLog("stored " + timingData.size() + " summary data items");
                    // now store buckets
                    Map<String, Map<Date, BucketDataItem>> bucketItems = metricsCalculator.getBucketItems();
                    int countItems = 0;
                    if (!bucketItems.isEmpty()) {
                        PeriodicDataDao periodicDataDao = new PeriodicDataDao();
                        try {
                            List<PeriodicData> toStore = new ArrayList<PeriodicData>();
                            for (Entry<String, Map<Date, BucketDataItem>> entry : bucketItems.entrySet()) {
                                for (BucketDataItem bucketItem : entry.getValue().values()) {
                                    PeriodicData data = getBucketData(jobId, entry.getKey(), bucketItem);
                                    toStore.add(data);
                                    countItems++;
                                }
                            }
                            periodicDataDao.persistCollection(toStore);
                            LOG.info("Finished Summary Report for job " + jobId);
                        } catch (Exception t) {
                            LOG.error("Error adding Summary Items: " + t, t);
                        }
                    }
                    mt.markAndLog("stored " + countItems + " periodic data items");
                    mt.endAndLog();
                }
            } else {
                LOG.info("generateSummary: job " + jobIdString + " has no data.");
            }
            // now delete timing data
            resultsReader.deleteTimingForJob(jobIdString, true);
        }
    }

    private static Date calculateSteadyStateEnd(JobInstance jobInstance) {
        if (jobInstance.getStartTime() != null && jobInstance.getSimulationTime() > 0) {
            return new Date(jobInstance.getStartTime().getTime() + jobInstance.getSimulationTime());
        }
        return null;
    }

    private static Date calculateSteadyStateStart(JobInstance jobInstance) {
        if (jobInstance.getStartTime() != null) {
            return new Date(jobInstance.getStartTime().getTime() + jobInstance.getRampTime());
        }
        return null;
    }

    /**
     * @param jobId
     * @param key
     * @param stats
     * @return
     */
    private static PeriodicData getBucketData(int jobId, String key, BucketDataItem bucketItem) {
        DescriptiveStatistics stats = bucketItem.getStats();
        PeriodicData ret = PeriodicDataBuilder.periodicData().withJobId(jobId).withMax(stats.getMax())
                .withMean(stats.getMean()).withMin(stats.getMin()).withPageId(key)
                .withSampleSize((int) stats.getN()).withPeriod(bucketItem.getPeriod())
                .withTimestamp(bucketItem.getStartTime()).build();
        return ret;
    }

    /**
     * @param key
     * @param value
     * @return
     */
    private static SummaryData getSummaryData(int jobId, String key, DescriptiveStatistics stats) {
        SummaryData ret = SummaryDataBuilder.summaryData().withJobId(jobId)
                .withKurtosis(!Double.isNaN(stats.getKurtosis()) ? stats.getKurtosis() : 0).withMax(stats.getMax())
                .withMean(stats.getMean()).withMin(stats.getMin()).withPageId(key)
                .withPercentile10(stats.getPercentile(10)).withPercentile20(stats.getPercentile(20))
                .withPercentile30(stats.getPercentile(30)).withPercentile40(stats.getPercentile(40))
                .withPercentile50(stats.getPercentile(50)).withPercentile60(stats.getPercentile(60))
                .withPercentile70(stats.getPercentile(70)).withPercentile80(stats.getPercentile(80))
                .withPercentile90(stats.getPercentile(90)).withPercentile95(stats.getPercentile(95))
                .withPercentile99(stats.getPercentile(99)).withSampleSize((int) stats.getN())
                .withSkewness(!Double.isNaN(stats.getSkewness()) ? stats.getSkewness() : 0)
                .withSttDev(!Double.isNaN(stats.getStandardDeviation()) ? stats.getStandardDeviation() : 0)
                .withVarience(!Double.isNaN(stats.getVariance()) ? stats.getVariance() : 0).build();
        return ret;
    }

}