/**
* Copyright 2011 Intuit Inc. All Rights Reserved
*/
package com.intuit.tank.persistence.databases;
/*
* #%L
* Reporting database support
* %%
* 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.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.zip.GZIPOutputStream;
import javax.annotation.Nonnull;
import org.apache.commons.io.IOUtils;
import org.apache.commons.math3.stat.descriptive.DescriptiveStatistics;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import com.intuit.tank.reporting.api.PagedTimingResults;
import com.intuit.tank.reporting.api.ResultsReader;
import com.intuit.tank.reporting.factory.ReportingFactory;
import com.intuit.tank.results.TankResult;
import com.intuit.tank.storage.FileData;
import com.intuit.tank.storage.FileStorage;
import com.intuit.tank.storage.FileStorageFactory;
import com.intuit.tank.vm.common.util.MethodTimer;
import com.intuit.tank.vm.common.util.ReportUtil;
import com.intuit.tank.vm.settings.TankConfig;
import com.intuit.tank.vm.settings.TimeUtil;
import au.com.bytecode.opencsv.CSVWriter;
/**
* MetricsCalculator
*
* @author dangleton
*
*/
public class MetricsCalculator {
private static final Logger LOG = LogManager.getLogger(MetricsCalculator.class);
private Map<String, DescriptiveStatistics> summaryResults = new HashMap<String, DescriptiveStatistics>();
private Map<String, Map<Date, BucketDataItem>> bucketItems = new HashMap<String, Map<Date, BucketDataItem>>();
private static final String[] FIELDS = {
DatabaseKeys.TIMESTAMP_KEY.getShortKey(),
DatabaseKeys.JOB_ID_KEY.getShortKey(),
DatabaseKeys.INSTANCE_ID_KEY.getShortKey(),
DatabaseKeys.LOGGING_KEY_KEY.getShortKey(),
DatabaseKeys.STATUS_CODE_KEY.getShortKey(),
DatabaseKeys.RESPONSE_TIME_KEY.getShortKey(),
DatabaseKeys.RESPONSE_SIZE_KEY.getShortKey(),
DatabaseKeys.IS_ERROR_KEY.getShortKey()
};
/**
* @param object2
* @param start
* @{inheritDoc
*/
public void retrieveAndCalculateTimingData(@Nonnull String jobId, Date start, Date end) {
MethodTimer mt = new MethodTimer(LOG, this.getClass(), "retrieveAndCalculateSummaryTimingCsv");
int period = 15;
Writer csvFile = null;
CSVWriter csvWriter = null;
InputStream is = null;
try {
ResultsReader resultsReader = ReportingFactory.getResultsReader();
String fileName = "timing_" + new TankConfig().getInstanceName() + "_" + jobId + ".csv.gz";
File f = File.createTempFile("timing", ".csv.gz");
csvFile = new OutputStreamWriter(new GZIPOutputStream(new FileOutputStream(f)));
csvWriter = new CSVWriter(csvFile);
int count = 0;
Object nextToken = null;
csvWriter.writeNext(FIELDS);
do {
PagedTimingResults results = resultsReader.getPagedTimingResults(jobId, nextToken);
for (TankResult result : results.getResults()) {
count++;
String[] entryArray = getCsvArray(result);
csvWriter.writeNext(entryArray);
if (count % 1000 == 0) {
csvWriter.flush();
}
double d = result.getResponseTime();
if (!skipDate(result.getTimeStamp(), start, end)) {
DescriptiveStatistics statistics = summaryResults.get(result.getRequestName());
if (statistics == null) {
statistics = new DescriptiveStatistics();
summaryResults.put(result.getRequestName(), statistics);
}
statistics.addValue(d);
}
if (result.getTimeStamp() != null) {
Date periodDate = TimeUtil.normalizeToPeriod(period, result.getTimeStamp());
DescriptiveStatistics bucketStats = getBucketStats(result.getRequestName(), period, periodDate);
bucketStats.addValue(d);
}
}
nextToken = results.getNextToken();
} while (nextToken != null);
csvWriter.flush();
csvWriter.close();
csvWriter = null;
IOUtils.closeQuietly(csvFile);
FileStorage fileStorage = FileStorageFactory.getFileStorage(new TankConfig().getTimingDir(), false);
FileData fd = new FileData("",fileName);
is = new FileInputStream(f);
fileStorage.storeFileData(fd, is);
mt.endAndLog();
LOG.info("Processed " + count + " total items for job " + jobId);
} catch (Exception e) {
if (e instanceof RuntimeException) {
throw (RuntimeException) e;
}
throw new RuntimeException(e);
} finally {
if (csvWriter != null) {
try {
csvWriter.close();
} catch (IOException e) {
// swallow
LOG.warn("Error closing csv file: " + e);
}
}
IOUtils.closeQuietly(csvFile);
IOUtils.closeQuietly(is);
}
}
private String[] getCsvArray(TankResult result) {
String[] ret = new String[FIELDS.length];
ret[0] = ReportUtil.getTimestamp(result.getTimeStamp());
ret[1] = result.getJobId();
ret[2] = result.getInstanceId();
ret[3] = result.getRequestName();
ret[3] = Integer.toString(result.getStatusCode());
ret[3] = Integer.toString(result.getResponseTime());
ret[3] = Integer.toString(result.getResponseSize());
ret[3] = Boolean.toString(result.isError());
// DatabaseKeys.IS_ERROR_KEY.getShortKey()
return ret;
}
private boolean skipDate(Date date, Date start, Date end) {
boolean ret = false;
if (start != null && date.before(start)) {
ret = true;
} else if (end != null && date.after(end)) {
ret = true;
}
return ret;
}
/**
* @param loggingKey
* @param periodDate
* @return
*/
private DescriptiveStatistics getBucketStats(String loggingKey, int period, Date periodDate) {
Map<Date, BucketDataItem> map = bucketItems.get(loggingKey);
if (map == null) {
map = new HashMap<Date, BucketDataItem>();
bucketItems.put(loggingKey, map);
}
BucketDataItem bucketDataItem = map.get(periodDate);
if (bucketDataItem == null) {
bucketDataItem = new BucketDataItem(period, periodDate, new DescriptiveStatistics());
map.put(periodDate, bucketDataItem);
}
return bucketDataItem.getStats();
}
/**
* @return the summaryResults
*/
public Map<String, DescriptiveStatistics> getSummaryResults() {
return summaryResults;
}
/**
* @return the bucketItems
*/
public Map<String, Map<Date, BucketDataItem>> getBucketItems() {
return bucketItems;
}
}