Logging to MySQL with ExperimentLogger

Introduction

Logging the right experimental data is a tedious task. You do not only have to consider how much data to collect, but also in what format to store the data. The ExperimentLogger class is designed to make it easy to log different variables with different data types straight to a (My)SQL database. Below you will find information on how the class is constructed and on how to put it to full use.

The ExperimentLogger class

To use the ExperimentLogger class, you do the following:

  1. Instantiate an ExperimentLogger object, like so
    Instantiate the ExperimentLogger object
    try {
      elogger = new ExperimentLogger("DBtablename", "jdbc:mysql://localhost/test", "root", "");
    } catch (Exception sqle) {
      log4jlogger.error("Error instantiating elogger.");
    }
    
  2. Pass the log(Object ... fields) method of the ExperimentLogger object any number of arguments. For instance:
    elogger.log(System.currentTimeMillis(), "a string", 4, gs.getGameId(), "another string");
    

The ExperimentLogger will then check whether the database table exists or not. There are two scenarios:

  1. The table does not exist.
    The ExperimentLogger will create a new table with as many columns as the number of arguments passed to the log method and then continue to log the objects to the table.
  2. The table exists.
    The ExperimentLogger wil check whether the number of columns equals the number of objects passed to the log method and check whether the data types of the objects match the data types in the columns (in order). If either check fails, an Exception is thrown. Otherwise, it will continue to log.

A note on conversion

The ExperimentLogger's log(Object ... fields) method will take any object as a parameter and will then convert the Java data type to a SQL datatype on the basis of the outcome of a sequence of instanceof statements. For instance, an int Object returns true to instanceof Integer and will therefore be logged as an INTEGER SQL data type; a String will be logged as a VARCHAR(255).

Using a Wrapper class

By using a wrapper class, you can predefine a sequence of variables that will be logged with each log statement.

An example of a log method in a Wrapper class
public void log(String logStatement){

  ArrayList logList = new ArrayList();
        
  logList.add(System.currentTimeMillis());
  logList.add(gs.getGameId());
  logList.add(logStatement);

  for (PlayerStatus player : gs.getPlayers()) {
    logList.add(player.getPin());
    logList.add(player.getPerGameId());
    logList.add(player.getChips());
    logList.add(player.getPosition());
  }

  Object[] logArray = logList.toArray();

  elogger.log(logArray);
}

By calling this log method, your log statement will be recorded, together with a time stamp and the gameId as well as the pin, perGameId, chip sets and positions of each player at that moment. To create your own Wrapper class, all you need is a constructor that instantiates the ExperimentLogger and a log method like the above.

public ExampleExperimentLoggerWrapper(ServerGameStatus gs, String table) {
  this.gs = gs;
  try {
    elogger = new ExperimentLogger(table, "jdbc:mysql://localhost/test", "root", "");
  } catch (Exception sqle) {
    log4jlogger.error("Error instantiating elogger.");
  }

}

In your configuration file, you now simply instantiate an instance of the Wrapper class and call the Wrapper's log method to log to MySQL.

ExampleExperimentLoggerWrapper logger = new ExampleExperimentLoggerWrapper(gs, "example");
logger.log("This is an example log statement");

For more information...

For more examples of how to use a Wrapper class, please take a look at edu.harvard.eecs.airg.coloredtrails.shared.ExampleExperimentLoggerWrapper.java.