package ch.ethz.syslab.telesto.profile;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import ch.ethz.syslab.telesto.common.util.Log;
import ch.ethz.syslab.telesto.common.util.StringUtil;
/**
* A simple implementation of a log for benchmarking tasks that uses a {@link BufferedWriter}. All entries written must
* not contain any tabular characters <code>\t</code> other than those intended for value separation or the resulting
* log file may be corrupted for reading and analysis.
*
* <p>
* Note that this implementation does not throw any exception but directly logs them to its logger. This ensures that no
* {@link IOException}s have to be handled by any users of this service.
*
*/
public class BenchmarkLog {
private static Log LOGGER = new Log(BenchmarkLog.class);
private static final String DELIMITER = "\t";
private static final String EXTENSION = ".log";
private static String FOLDER = "log";
private String name;
private File logFile;
private BufferedWriter logWriter;
public BenchmarkLog(String name) {
this.name = name;
openLogFile();
}
/**
* Set ExecutionId for the current execution that is used as the folder name for all logFiles written by instances
* of {@link BenchmarkLog}. This does not throw an exception if the name is not valid. Only further instantiation of
* this class lead to the expected {@link IOException}s.
*
* @param id
* A valid foldername for the current system
*/
public static void setExecutionId(String id) {
FOLDER = id;
}
/**
* creates the logFile and opens it for writing. Also ensures that the directory hierarchy is present and generates
* it otherwise.
*/
protected void openLogFile() {
logFile = new File(FOLDER, name + EXTENSION);
if (logFile.exists()) {
LOGGER.warning("Log File %s already exists at location %s!", name, logFile.getAbsolutePath());
}
logFile.getParentFile().mkdirs();
try {
logFile.createNewFile();
logWriter = new BufferedWriter(new FileWriter(logFile));
} catch (IOException e) {
LOGGER.severe(e, "Failed to create log file %s", logFile);
}
}
/**
* Adds the given entry to a new line of the log file.
*
* @param entry
*/
public void addEntry(Object... entries) {
try {
logWriter.write(StringUtil.joinString(DELIMITER, entries) + "\n");
} catch (IOException e) {
LOGGER.severe(e, "Failed to write to log file %s", logFile);
}
}
/**
* Adds the given entry prepended by the current system timestamp to a new line of the log file.
*
* @param entries
*/
public void addTimedEntry(Object... entries) {
long time = System.currentTimeMillis();
if (entries != null && entries.length > 0) {
entries[0] = StringUtil.joinString(DELIMITER, time, entries[0]);
addEntry(entries);
} else {
addEntry(time);
}
}
/**
* close the underlying log file. Internally uses {@link Writer#close()}.
*
* @throws IOException
*/
public void closeFile() {
try {
logWriter.close();
} catch (IOException e) {
LOGGER.severe(e, "Failed to close log file %s", logFile);
}
}
/**
* Ensure that the logWriter is closed and all content is written to the file.
*/
@Override
protected void finalize() throws Throwable {
closeFile();
}
public void flush() {
try {
logWriter.flush();
} catch (IOException e) {
LOGGER.warning(e, "Failed to flush log file %s", logFile);
}
}
}