decodes.routmon.RoutingMonitor Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of opendcs Show documentation
Show all versions of opendcs Show documentation
A collection of software for aggregatting and processing environmental data such as from NOAA GOES satellites.
The newest version!
/*
* $Id$
*
* $Log$
* Revision 1.1.1.1 2014/05/19 15:28:59 mmaloney
* OPENDCS 6.0 Initial Checkin
*
* Revision 1.2 2013/03/28 17:29:09 mmaloney
* Refactoring for user-customizable decodes properties.
*
* Revision 1.1 2008/04/04 18:21:04 cvs
* Added legacy code to repository
*
* Revision 1.7 2005/02/09 20:15:26 mjmaloney
* dev
*
* Revision 1.6 2005/02/09 20:10:15 mjmaloney
* Added lock mechanism.
*
* Revision 1.5 2005/01/03 18:51:33 mjmaloney
* Added javadocs.
*
* Revision 1.4 2004/05/10 21:30:50 mjmaloney
* Reduce wasted space in report header.
*
* Revision 1.3 2004/05/06 15:29:40 mjmaloney
* Bug fixes in beta 6.1
*
* Revision 1.2 2004/04/29 19:14:49 mjmaloney
* 6.1 release prep
*
* Revision 1.1 2004/04/29 01:10:21 mjmaloney
* Created.
*
*/
package decodes.routmon;
import java.io.*;
import java.util.*;
import java.text.SimpleDateFormat;
import java.net.InetAddress;
import java.net.UnknownHostException;
import ilex.util.Logger;
import ilex.util.PropertiesUtil;
import ilex.util.EnvExpander;
import ilex.util.ServerLock;
import ilex.util.FileServerLock;
import ilex.cmdline.*;
import decodes.util.*;
/**
Main class for the Routing Spec Monitor web application.
*/
public class RoutingMonitor
implements Runnable
{
/** Config param: period between directory scans */
private long scanPeriod;
/** Config param: directory to be scanned */
private Vector directories=new Vector();
/** Config param: directory in which to place output HTML file */
private File outputDir;
/** Config param: directory to be scanned for routing status files. */
private File inputDir;
/** Config param: Name of file to create in the outputDir */
private String htmlFilename;
/** Config param: hostname to use in report header */
private String hostname;
/** Config param: purge routstat files older than this many seconds. */
private long purgetime;
/** Used to format dates in the header of the HTML report. */
private SimpleDateFormat dfHeader;
/** Used to format dates in the columns of the HTML report. */
private SimpleDateFormat dfColumn;
/** Output File object. */
private File htmlFile;
/** monitor object */
RoutingDirMonitor myDirMonitor=new RoutingDirMonitor(this);
/** collection of status objects, one per routing spec. */
private Vector routingSpecStats=new Vector();
/** Prevents multiple instances & provide way to shut down. */
private ServerLock mylock;
/// Command line arguments, set default log name to ./routmon.log
static CmdLineArgs cmdLineArgs = new CmdLineArgs(false, "routmon.log");
static private StringToken host_arg =
new StringToken("h", "host-name", "", TokenOptions.optSwitch, "");
static private StringToken outputDir_arg =
new StringToken("o", "Output Directory","", TokenOptions.optSwitch,
"$DECODES_INSTALL_DIR/routmon");
static private StringToken outputFile_arg =
new StringToken("f", "Output File","", TokenOptions.optSwitch,
"routmon.html");
static private IntegerToken sleepSecs_arg =
new IntegerToken("s", "Sleep Seconds","", TokenOptions.optSwitch, 10);
static private IntegerToken purgeSecs_arg =
new IntegerToken("p", "Purge Seconds","", TokenOptions.optSwitch,
3600*24);
/** -k argument provides the lock file */
static StringToken lockFileArg = new StringToken(
"k", "dcpmon lock file","",TokenOptions.optSwitch,"$HOME/routmon.lock");
static
{
cmdLineArgs.addToken(host_arg);
cmdLineArgs.addToken(outputDir_arg);
cmdLineArgs.addToken(outputFile_arg);
cmdLineArgs.addToken(sleepSecs_arg);
cmdLineArgs.addToken(purgeSecs_arg);
cmdLineArgs.addToken(lockFileArg);
}
/**
* Main method. See command line arguments listed above.
* @param args command line args
*/
public static void main(String[] args)
{
// This parses all args & sets up the logger & debug level.
cmdLineArgs.parseArgs(args);
Logger.instance().info("Just parsed args, minPriority=" + Logger.instance().getMinLogPriority());
Logger.instance().debug1("starting");
// Instantiate my monitor.
RoutingMonitor mymonitor=new RoutingMonitor();
// Put argument values into monitor.
mymonitor.scanPeriod = sleepSecs_arg.getValue();
mymonitor.outputDir =
new File(EnvExpander.expand(outputDir_arg.getValue()));
mymonitor.htmlFilename = outputFile_arg.getValue();
mymonitor.hostname = host_arg.getValue().trim();
if (mymonitor.hostname.length() == 0)
{
try
{
mymonitor.hostname = InetAddress.getLocalHost().getHostName();
}
catch(UnknownHostException ex)
{
Logger.instance().log(Logger.E_WARNING,
"Cannot determine host name -- using 'unknown'");
mymonitor.hostname = "unknown";
}
}
mymonitor.purgetime = purgeSecs_arg.getValue();
// Run the monitor in the main thread.
mymonitor.run();
}
/**
* Application run method reads configuration, starts monitor thread, etc.
*/
public void run()
{
// Get the server lock, & fail if error.
String lockpath = EnvExpander.expand(lockFileArg.getValue());
mylock = new FileServerLock(lockpath);
if (mylock.obtainLock() == false)
{
Logger.instance().log(Logger.E_FATAL,
"Routing Monitor not started: lock file busy");
System.exit(0);
}
mylock.releaseOnExit();
Runtime.getRuntime().addShutdownHook(
new Thread()
{
public void run()
{
Logger.instance().log(Logger.E_INFORMATION,
"Routing Monitor Server exiting " +
(mylock.wasShutdownViaLock() ? "(lock file removed)"
: ""));
}
});
TimeZone utc = TimeZone.getTimeZone("UTC");
dfHeader = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss zzz");
dfHeader.setTimeZone(utc);
dfColumn = new SimpleDateFormat("MM/dd HH:mm:ss");
dfColumn.setTimeZone(utc);
if (!outputDir.isDirectory())
{
outputDir.mkdirs();
if (!outputDir.isDirectory())
{
Logger.instance().log(Logger.E_FATAL,
"Cannot access or create output directory '"
+ outputDir.getPath() + "' -- aborting.");
System.exit(1);
}
}
htmlFile = new File(outputDir, htmlFilename);
// create, configure, & start the dir monitor thread.
myDirMonitor = new RoutingDirMonitor(this);
inputDir = new File(EnvExpander.expand(
DecodesSettings.instance().routingStatusDir));
if (!inputDir.isDirectory())
{
inputDir.mkdirs();
if (!inputDir.isDirectory())
{
Logger.instance().log(Logger.E_FATAL,
"Cannot access or create input directory '"
+ inputDir.getPath() + "' -- aborting.");
System.exit(1);
}
}
myDirMonitor.addDirectory(inputDir);
myDirMonitor.setSleepEveryCycle(true);
myDirMonitor.setSleepInterval(scanPeriod*1000);
myDirMonitor.start();
while(true)
{
try{Thread.sleep(60000);}
catch(Exception e){}
purgeOldStatusRecs();
}
}
/*
* Called from the dir monitor thread with a properties set read from
* a routing-spec's status file.
* Extract the relevant properties & store them in a RoutingSpecStatus
* object in my vector.
*
* @param props the properties representing routing spec status
* @param lastModifyTime last time this rout stat set was changed.
*/
public synchronized void setStatus(Properties props, long lastModifyTime)
throws BadStatusFile
{
/*
Concurrency check: we don't want to try to read a file that isn't
complete. The set must contain start & end times and they must
be equal.
*/
String sts = PropertiesUtil.getIgnoreCase(props, "StartTime");
String ets = PropertiesUtil.getIgnoreCase(props, "EndTime");
if (sts == null || ets == null)
throw new BadStatusFile("Missing start or end time.");
if (!sts.equals(ets))
throw new BadStatusFile("Start time doesn't equal end time.");
String specName = PropertiesUtil.getIgnoreCase(props, "SpecName");
if (specName == null)
throw new BadStatusFile("Missing required 'SpecName' property.");
RoutingSpecStatus myspec = null;
for(int pos=0;pos\n"
+ " Routing Status Monitor \n"
+ " \n"
+ " \n"
+ "\n";
String htmlTitleArea
= "\n"
+ "\n"
+ "\n"
+ "
\n"
+ " \n"
+ "\n"
+ "DECODES Routing Spec Status
\n"
+ "Hostname: " + hostname + "
\n"
+ dfHeader.format(new Date(System.currentTimeMillis())) + "
\n"
+ " \n"
+ "
\n"
+ " \n"
+ " \n"
+ "\n"
+ "
\n"
+ "
\n";
String htmlTableStart
= "\n"
+ "";
String htmlTableHeader
= "\n"
+ "Routing\n"
+ "Spec Name
\n"
+ " \n"
+ "Current\n"
+ "Status
\n"
+ " \n"
+ "Time\n"
+ "Started
\n"
+ " \n"
+ "Last\n"
+ "Msg Rcv'd
\n"
+ " \n"
+ "\n"
+ "Msgs/Errs This Run
\n"
+ " \n"
+ ""
+ "Msgs/Errs Today
\n"
+ " \n"
+ "Current\n"
+ "Server
\n"
+ " \n"
+ "Output\n"
+ "Name
\n"
+ " \n"
+ "OutputFormat
\n"
+ " \n"
+ " \n";
Vector tableRows = new Vector();
Enumeration e = routingSpecStats.elements();
while(e.hasMoreElements())
{
RoutingSpecStatus myspec=(RoutingSpecStatus)e.nextElement();
String row =
""
+ ""
+ myspec.name + "
"
+ "" + myspec.status + " "
+ "" + dfColumn.format(myspec.startTime) + " "
+ "" + dfColumn.format(myspec.lastMsgRecieveTime) + " "
+ "" + myspec.msgsThisRun + " "
+ "" + myspec.msgsToday + " "
+ "" + myspec.currentServer + " "
+ "" + myspec.outputName + " "
+ "" + myspec.outputFormat + " ";
tableRows.add(row);
}
try
{
FileWriter mywriter = new FileWriter(htmlFile);
mywriter.write(htmlHeader);
mywriter.write(htmlTitleArea);
mywriter.write(htmlTableStart);
mywriter.write(htmlTableHeader);
for(Iterator it = tableRows.iterator(); it.hasNext(); )
mywriter.write((String)it.next());
mywriter.write("
\n