package edu.brown.hstore.util;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.apache.log4j.Logger;
import org.voltdb.utils.EstTime;
import au.com.bytecode.opencsv.CSVWriter;
import edu.brown.hstore.conf.HStoreConf;
import edu.brown.hstore.txns.LocalTransaction;
import edu.brown.logging.LoggerUtil;
import edu.brown.logging.LoggerUtil.LoggerBoolean;
import edu.brown.profilers.ProfileMeasurement;
import edu.brown.profilers.TransactionProfiler;
/**
* Quick utility method to dump out profile information about a txn
* to string arrays so that we can write them to a CSV file
* @author pavlo
*/
public class TransactionProfilerDumper {
private static final Logger LOG = Logger.getLogger(TransactionProfilerDumper.class);
private static final LoggerBoolean debug = new LoggerBoolean();
private static final LoggerBoolean trace = new LoggerBoolean();
static {
LoggerUtil.attachObserver(LOG, debug, trace);
}
private File outputFile;
private final CSVWriter writer;
public TransactionProfilerDumper(File outputFile) {
this.outputFile = outputFile;
try {
FileWriter out = new FileWriter(outputFile);
this.writer = new CSVWriter(out);
} catch (Exception ex) {
LOG.fatal(String.format("Failed to create CSVWriter for '%s'", this.outputFile), ex);
throw new RuntimeException(ex);
}
this.writeHeader();
}
private void flush() {
try {
this.writer.flush();
} catch (Exception ex) {
ex.printStackTrace();
}
}
public synchronized void close() throws IOException {
this.writer.close();
}
public void writeHeader() {
if (debug.val)
LOG.debug(String.format("Writing %s header to '%s'",
this.getClass().getSimpleName(), this.outputFile));
List<Object> row = new ArrayList<Object>();
// Base Information
row.add("TXNID");
row.add("PROCEDURE_NAME");
// Execution Information
row.add("EXEC_DURATION");
row.add("EXEC_STATUS");
row.add("EXEC_BASE_PARTITION");
row.add("EXEC_NUM_PARTITIONS");
row.add("EXEC_SYSPROC");
row.add("EXEC_SPECULATIVE");
row.add("EXEC_MAPREDUCE");
row.add("EXEC_RESTART_COUNTER");
// Query Exec Information
row.add("QUERY_BATCHES");
row.add("QUERY_TOTAL_COUNT");
row.add("QUERY_REMOTE_COUNT");
row.add("QUERY_PREFETCH_COUNT");
// Prediction Information
row.add("PREDICT_NUM_PARTITIONS");
row.add("PREDICT_ABORTABLE");
row.add("PREDICT_READONLY");
// Profiler Information
if (HStoreConf.singleton().site.txn_profiling) {
TransactionProfiler profiler = new TransactionProfiler();
for (ProfileMeasurement pm : profiler.getProfileMeasurements()) {
row.add("PROFILE_" + pm.getName());
}
}
String ret[] = new String[row.size()];
for (int i = 0; i < ret.length; i++) {
ret[i] = row.get(i).toString();
}
this.writer.writeNext(ret);
this.flush();
}
public void writeRow(LocalTransaction ts) {
if (debug.val) LOG.debug("Writing profile information for " + ts);
HStoreConf hstore_conf = HStoreConf.singleton();
List<Object> row = new ArrayList<Object>();
// ---------------------------------------------------------------
// TXN EXEC INFO
// ---------------------------------------------------------------
// TxnId
row.add(ts.getTransactionId());
// Procedure Name
row.add(ts.getProcedure().getName());
// Duration
row.add(EstTime.currentTimeMillis() - ts.getInitiateTime());
// Status
row.add(ts.getStatus());
// Base Partition
row.add(ts.getBasePartition());
// # of Touched Partitions
row.add(ts.getTouchedPartitions().getValueCount());
// Is SysProc
row.add(ts.isSysProc());
// Is Speculative
row.add(ts.isSpeculative());
// Is MapReduce
row.add(ts.isMapReduce());
// Restart Counter
row.add(ts.getRestartCounter());
// ---------------------------------------------------------------
// QUERY INFO
// ---------------------------------------------------------------
if (hstore_conf.site.txn_profiling && ts.profiler != null) {
// # of query batches
row.add(ts.profiler.getBatchCount());
// # of queries
row.add(ts.profiler.getQueryCount());
// # of remote queries
row.add(ts.profiler.getRemoteQueryCount());
// # of prefetch queries
row.add(ts.profiler.getPrefetchQueryCount());
} else {
// # of query batches
row.add(null);
// # of queries
row.add(null);
// # of remote queries
row.add(null);
// # of prefetch queries
row.add(null);
}
// ---------------------------------------------------------------
// PREDICT INFO
// ---------------------------------------------------------------
row.add(ts.getPredictTouchedPartitions().size());
row.add(ts.isPredictAbortable());
row.add(ts.isPredictReadOnly());
if (HStoreConf.singleton().site.txn_profiling &&
ts.profiler != null) {
for (ProfileMeasurement pm : ts.profiler.getProfileMeasurements()) {
row.add(pm.getTotalThinkTimeMS());
}
}
String ret[] = new String[row.size()];
int i = 0;
for (Object obj : row) {
ret[i++] = (obj == null ? "null" : obj.toString());
} // FOR
synchronized (this) {
this.writer.writeNext(ret);
} // SYNCH
}
}