Skip to content

Instantly share code, notes, and snippets.

Created September 3, 2010 15:57
Show Gist options
  • Save anonymous/564088 to your computer and use it in GitHub Desktop.
Save anonymous/564088 to your computer and use it in GitHub Desktop.
import java.io.File;
import java.io.RandomAccessFile;
import java.lang.reflect.Method;
import java.util.ArrayList;
/**
* A log file tailer is designed to monitor a log file and send notifications
* when new lines are added to the log file. This class has a notification
* strategy similar to a SAX parser: implement the LogFileListener interface,
* create a LogFileTailer to tail your log file, add yourself as a listener, and
* start the LogFileTailer. It is your job to interpret the results, build
* meaningful sets of data, etc. This tailer simply fires notifications
* containing new log file lines, one at a time.
*/
public class LogFileWatcher extends Thread {
/**
* How frequently to check for file changes; defaults to 5 seconds
*/
private long checkFileInterval = 5000;
/**
* The log file to tail
*/
private final File logfile;
/**
* Is the tailer currently tailing?
*/
private boolean watching = false;
/**
* Metchod that determine if error is in log line
*/
private Method hasLogLineErrorMethod = null;
/**
* Collection with lines with errors
*/
private ArrayList<String> errorLines;
/**
* A new line has been added to the tailed log file
*
* @param line
* The new line that has been added to the tailed log file
*/
public void newLogFileLine(String line) {
try {
if ((Boolean) this.hasLogLineErrorMethod.invoke(null, line))
this.errorLines.add(line);
} catch (Exception e) {
// @todo :
System.out.println("Error while invoking hasLogLineErrorMethod()");
}
}
/**
* Creates a new log file tailer
*
* @param file
* The file to tail
* @param interval
* How often to check for updates to the log file (default =
* 5000ms)
* @param checkErrorMethod
* Method that detremines if error in log line ocour
*
*/
public LogFileWatcher(File file, long interval, Method hasLogLineError) {
this.logfile = file;
this.checkFileInterval = interval;
this.hasLogLineErrorMethod = hasLogLineError;
this.errorLines = new ArrayList<String>();
}
public Boolean hasLogError() {
if (this.errorLines.size() > 0)
return true;
return false;
}
public void stopWatching() {
this.watching = false;
}
@Override
public void run() {
// The file pointer keeps track of where we are in the file
long filePointer = this.logfile.length();
try {
// Start tailing
this.watching = true;
RandomAccessFile file = new RandomAccessFile(logfile, "r");
while (this.watching) {
try {
// Compare the length of the file to the file pointer
long fileLength = this.logfile.length();
if (fileLength < filePointer) {
// Log file must have been rotated or deleted;
// reopen the file and reset the file pointer
file = new RandomAccessFile(logfile, "r");
filePointer = 0;
}
if (fileLength > filePointer) {
// There is data to read
file.seek(filePointer);
String line = file.readLine();
while (line != null) {
this.newLogFileLine(line);
line = file.readLine();
}
filePointer = file.getFilePointer();
}
// Sleep for the specified interval
sleep(this.checkFileInterval);
} catch (Exception e) {
}
}
// Close the file that we are tailing
file.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment