Omaha #2840 log tool can now save html reports to directory
Change-Id: Ifa2d9653d2ee689512f33169028705de98f65682 Former-commit-id: 4aec10e9b7155baa7e4243a4db78ad16440dbba7
This commit is contained in:
parent
cc957caac6
commit
f681b52b46
5 changed files with 282 additions and 122 deletions
|
@ -1,26 +1,45 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<logSrvConfig>
|
||||
|
||||
<!-- the cluster name, only used for the report email -->
|
||||
<!-- Config file for the log service and how it produces the reports.
|
||||
Depending on what tags are here vs missing/commented out, the log
|
||||
service can
|
||||
a. email the report
|
||||
b. save the report to a specific directory
|
||||
c. both a and b
|
||||
d. neither a and b (rather pointless to run it then)
|
||||
-->
|
||||
|
||||
<!-- the cluster name, required but only used for the report -->
|
||||
<clusterName>ec-oma</clusterName>
|
||||
|
||||
<!-- where to keep track of the errors
|
||||
<!-- Where to keep track of the errors. Required field.
|
||||
how much space you need depends on how many errors the system is throwing
|
||||
-->
|
||||
<databaseDir>/common/njensen/logsrv/</databaseDir>
|
||||
|
||||
<!-- how to send the email report -->
|
||||
<!-- fromAddress, smtpHost, smtpPort, and toAddress are required
|
||||
to send an email. If any of those are commented out then the
|
||||
report will not be emailed.
|
||||
-->
|
||||
|
||||
<!-- How to send the email report -->
|
||||
<fromAddress>Nathan.Jensen@raytheon.com</fromAddress>
|
||||
<smtpHost>mk2-msg10.raymail.ray.com</smtpHost>
|
||||
<smtpPort>143</smtpPort>
|
||||
|
||||
<!-- where to send the email report, a comma-separated list of addresses -->
|
||||
<!-- Where to send the email report, a comma-separated list of addresses -->
|
||||
<toAddress>awipsctl@list.app.ray.com, awipstest@list.app.ray.com, david_j_hladky@raytheon.com</toAddress>
|
||||
|
||||
<!-- Where to save a copy of the report. Note that at present there is
|
||||
no built-in purging of this directory. If this is commented out or
|
||||
missing, the report will not be saved. -->
|
||||
<!--outputDir>/common/njensen/tmp</outputDir-->
|
||||
|
||||
<!-- the time of day to send the report
|
||||
only really matters if you're installing or auto-deploying at a
|
||||
specific time, as you may want to clear out the databaseDir
|
||||
that contains errors from a previous build
|
||||
<!-- The time of day to send and/or save the report. Required to be set.
|
||||
The specific time only really matters if you're installing or
|
||||
auto-deploying at a specific time, as you may want to clear out
|
||||
the databaseDir that contains errors from a previous build/install.
|
||||
-->
|
||||
<timeToSend>00:45</timeToSend>
|
||||
|
||||
|
|
|
@ -26,6 +26,8 @@ import javax.xml.bind.annotation.XmlRootElement;
|
|||
|
||||
import org.apache.commons.lang.Validate;
|
||||
|
||||
import com.raytheon.uf.logsrv.LogService;
|
||||
|
||||
/**
|
||||
* A configuration for the logging service.
|
||||
*
|
||||
|
@ -36,6 +38,7 @@ import org.apache.commons.lang.Validate;
|
|||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Aug 29, 2013 njensen Initial creation
|
||||
* Jun 11, 2014 2840 njensen Added outputDir
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -47,10 +50,10 @@ import org.apache.commons.lang.Validate;
|
|||
@XmlAccessorType(XmlAccessType.NONE)
|
||||
public class LogSrvConfig {
|
||||
|
||||
@XmlElement()
|
||||
@XmlElement(required = true)
|
||||
private String clusterName;
|
||||
|
||||
@XmlElement
|
||||
@XmlElement(required = true)
|
||||
private String databaseDir;
|
||||
|
||||
@XmlElement
|
||||
|
@ -65,9 +68,11 @@ public class LogSrvConfig {
|
|||
@XmlElement
|
||||
private String toAddress;
|
||||
|
||||
@XmlElement
|
||||
@XmlElement(required = true)
|
||||
private String timeToSend;
|
||||
|
||||
private String outputDir;
|
||||
|
||||
public String getFromAddress() {
|
||||
return fromAddress;
|
||||
}
|
||||
|
@ -124,19 +129,27 @@ public class LogSrvConfig {
|
|||
this.databaseDir = databaseDir;
|
||||
}
|
||||
|
||||
public String getOutputDir() {
|
||||
return outputDir;
|
||||
}
|
||||
|
||||
public void setOutputDir(String outputDir) {
|
||||
this.outputDir = outputDir;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates that the config has every value set.
|
||||
*/
|
||||
public void validate() {
|
||||
Validate.notEmpty(clusterName, "Config must include a clusterName");
|
||||
Validate.notEmpty(databaseDir, "Config must include a databaseDir");
|
||||
Validate.notEmpty(fromAddress, "Config must include a fromAddress");
|
||||
Validate.notEmpty(smtpHost, "Config must include an smtpHost");
|
||||
Validate.notEmpty(timeToSend, "Config must include a timeToSend");
|
||||
Validate.notEmpty(toAddress, "Config must include a toAddress");
|
||||
if (smtpPort <= 0) {
|
||||
throw new IllegalArgumentException(
|
||||
"Config must include an smtpPort");
|
||||
if ((outputDir == null)
|
||||
&& (fromAddress == null || toAddress == null
|
||||
|| smtpHost == null || smtpPort == 0)) {
|
||||
LogService
|
||||
.getLogger()
|
||||
.warn("Config appears misconfigured and will not save or email the report!");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,228 @@
|
|||
/**
|
||||
* This software was developed and / or modified by Raytheon Company,
|
||||
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
|
||||
*
|
||||
* U.S. EXPORT CONTROLLED TECHNICAL DATA
|
||||
* This software product contains export-restricted data whose
|
||||
* export/transfer/disclosure is restricted by U.S. law. Dissemination
|
||||
* to non-U.S. persons whether in the United States or abroad requires
|
||||
* an export license or other authorization.
|
||||
*
|
||||
* Contractor Name: Raytheon Company
|
||||
* Contractor Address: 6825 Pine Street, Suite 340
|
||||
* Mail Stop B8
|
||||
* Omaha, NE 68106
|
||||
* 402.291.0100
|
||||
*
|
||||
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
|
||||
* further licensing information.
|
||||
**/
|
||||
package com.raytheon.uf.logsrv.quartz;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
|
||||
import org.quartz.Job;
|
||||
import org.quartz.JobExecutionContext;
|
||||
import org.quartz.JobExecutionException;
|
||||
|
||||
import com.raytheon.uf.logsrv.LogService;
|
||||
import com.raytheon.uf.logsrv.LogServiceException;
|
||||
import com.raytheon.uf.logsrv.config.LogSrvConfig;
|
||||
import com.raytheon.uf.logsrv.derby.DerbyDao;
|
||||
import com.raytheon.uf.logsrv.report.data.LogReportContainer;
|
||||
import com.raytheon.uf.logsrv.report.email.HtmlGenerator;
|
||||
import com.raytheon.uf.logsrv.report.email.ReportEmailer;
|
||||
|
||||
/**
|
||||
* A quartz job that queries the database to build report data, transforms the
|
||||
* report data into HTML, emails and/or saves the HTML, and then purges the
|
||||
* database of all logging events that were included in the report.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Aug 30, 2013 njensen Initial creation
|
||||
* Jun 11, 2014 2840 njensen Added save to dir
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author njensen
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
public class CreateReportJob implements Job {
|
||||
|
||||
private static final SimpleDateFormat SDF = new SimpleDateFormat(
|
||||
"yyyy-MM-dd");
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.quartz.Job#execute(org.quartz.JobExecutionContext)
|
||||
*/
|
||||
@Override
|
||||
public void execute(JobExecutionContext ctx) throws JobExecutionException {
|
||||
LogService.getLogger().info(
|
||||
"Create report job triggered, preparing report");
|
||||
DerbyDao dao = DerbyDao.getInstance();
|
||||
// synchronize on dao to prevent new log entries from being added
|
||||
// while we're querying and then purging
|
||||
synchronized (dao) {
|
||||
LogReportContainer container = null;
|
||||
try {
|
||||
container = dao.buildReport();
|
||||
} catch (LogServiceException e) {
|
||||
LogService.getLogger().error("Error building report", e);
|
||||
throw new JobExecutionException("Error building report", e);
|
||||
}
|
||||
|
||||
String html = HtmlGenerator.generateHtml(container);
|
||||
LogSrvConfig config = (LogSrvConfig) ctx.getJobDetail()
|
||||
.getJobDataMap().get("config");
|
||||
|
||||
boolean emailed = sendEmail(html, config);
|
||||
boolean saved = saveReport(html, config);
|
||||
boolean processed = emailed || saved;
|
||||
|
||||
/*
|
||||
* Only clear out the database if we at least sent or saved the
|
||||
* report.
|
||||
*
|
||||
* TODO If the service keeps erroring off on the report generation,
|
||||
* then in theory the databaseDir could grow out of control forever
|
||||
* until out of disk space. Should somehow set a configurable upper
|
||||
* limit where the derby db cannot go past a certain number of log
|
||||
* messages.
|
||||
*/
|
||||
if (processed) {
|
||||
LogService.getLogger().info(
|
||||
"Purging database of messages that were just reported");
|
||||
try {
|
||||
dao.clearEntries();
|
||||
} catch (LogServiceException e) {
|
||||
LogService.getLogger().error("Error purging database", e);
|
||||
throw new JobExecutionException("Error purging database", e);
|
||||
}
|
||||
LogService.getLogger().info("Database purging complete");
|
||||
} else {
|
||||
LogService
|
||||
.getLogger()
|
||||
.warn("Did not save or send report, therefore skipping purge of database");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the service is configured to send email, and if so sends the
|
||||
* report as configured
|
||||
*
|
||||
* @param report
|
||||
* @param config
|
||||
* @return true if it sent, otherwise false
|
||||
*/
|
||||
protected boolean sendEmail(String report, LogSrvConfig config) {
|
||||
boolean sent = false;
|
||||
if (shouldEmail(config)) {
|
||||
try {
|
||||
ReportEmailer.email(report, config);
|
||||
LogService.getLogger().info(
|
||||
"Report has been sent to: " + config.getToAddress());
|
||||
sent = true;
|
||||
} catch (Exception e) {
|
||||
LogService.getLogger().error("Error emailing report", e);
|
||||
}
|
||||
} else {
|
||||
LogService
|
||||
.getLogger()
|
||||
.info("Skipping email of report"
|
||||
+ ", to enable emailing ensure the log service's config has a fromAddress, toAddress, and smtpHost");
|
||||
}
|
||||
|
||||
return sent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the configuration indicates that the report should be emailed
|
||||
*
|
||||
* @param cfg
|
||||
* @return
|
||||
*/
|
||||
protected boolean shouldEmail(LogSrvConfig cfg) {
|
||||
return (cfg.getFromAddress() != null) && (cfg.getToAddress() != null)
|
||||
&& (cfg.getSmtpHost() != null) && (cfg.getSmtpPort() > 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the service is configured to save the reports, and if so, saves
|
||||
* the report
|
||||
*
|
||||
* @param report
|
||||
* @param config
|
||||
* @return true if it saved, otherwise false
|
||||
*/
|
||||
protected boolean saveReport(String report, LogSrvConfig config) {
|
||||
boolean saved = false;
|
||||
if (shouldSaveReport(config)) {
|
||||
File outputDir = new File(config.getOutputDir());
|
||||
if (!outputDir.exists()) {
|
||||
if (!outputDir.mkdirs()) {
|
||||
LogService.getLogger()
|
||||
.error("Error creating outputDir "
|
||||
+ config.getOutputDir());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
String filename = config.getClusterName() + "_"
|
||||
+ SDF.format(new Date()) + ".html";
|
||||
String filePath = outputDir.getPath() + File.separator + filename;
|
||||
|
||||
FileOutputStream fos = null;
|
||||
try {
|
||||
fos = new FileOutputStream(filePath, false);
|
||||
fos.write(report.getBytes());
|
||||
fos.flush();
|
||||
saved = true;
|
||||
} catch (FileNotFoundException e) {
|
||||
LogService.getLogger().error(
|
||||
"Error opening file output stream " + filePath, e);
|
||||
} catch (IOException e) {
|
||||
LogService.getLogger().error(
|
||||
"Error writing to file " + filePath, e);
|
||||
} finally {
|
||||
if (fos != null) {
|
||||
try {
|
||||
fos.close();
|
||||
} catch (IOException e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
LogService
|
||||
.getLogger()
|
||||
.info("Skipping save of report"
|
||||
+ ", to enable saving reports ensure the log service's config has an outputDir");
|
||||
}
|
||||
|
||||
return saved;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the configuration indicates that the report should be saved
|
||||
*
|
||||
* @param cfg
|
||||
* @return
|
||||
*/
|
||||
protected boolean shouldSaveReport(LogSrvConfig cfg) {
|
||||
return (cfg.getOutputDir() != null);
|
||||
}
|
||||
}
|
|
@ -1,103 +0,0 @@
|
|||
/**
|
||||
* This software was developed and / or modified by Raytheon Company,
|
||||
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
|
||||
*
|
||||
* U.S. EXPORT CONTROLLED TECHNICAL DATA
|
||||
* This software product contains export-restricted data whose
|
||||
* export/transfer/disclosure is restricted by U.S. law. Dissemination
|
||||
* to non-U.S. persons whether in the United States or abroad requires
|
||||
* an export license or other authorization.
|
||||
*
|
||||
* Contractor Name: Raytheon Company
|
||||
* Contractor Address: 6825 Pine Street, Suite 340
|
||||
* Mail Stop B8
|
||||
* Omaha, NE 68106
|
||||
* 402.291.0100
|
||||
*
|
||||
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
|
||||
* further licensing information.
|
||||
**/
|
||||
package com.raytheon.uf.logsrv.quartz;
|
||||
|
||||
import org.quartz.Job;
|
||||
import org.quartz.JobExecutionContext;
|
||||
import org.quartz.JobExecutionException;
|
||||
|
||||
import com.raytheon.uf.logsrv.LogService;
|
||||
import com.raytheon.uf.logsrv.LogServiceException;
|
||||
import com.raytheon.uf.logsrv.config.LogSrvConfig;
|
||||
import com.raytheon.uf.logsrv.derby.DerbyDao;
|
||||
import com.raytheon.uf.logsrv.report.data.LogReportContainer;
|
||||
import com.raytheon.uf.logsrv.report.email.HtmlGenerator;
|
||||
import com.raytheon.uf.logsrv.report.email.ReportEmailer;
|
||||
|
||||
/**
|
||||
* A quartz job that queries the database to build report data, transforms the
|
||||
* report data into HTML, emails the HTML to the configured address, and then
|
||||
* purges the database of all logging events that were included in the report.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Aug 30, 2013 njensen Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author njensen
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
public class CreateSendReportJob implements Job {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.quartz.Job#execute(org.quartz.JobExecutionContext)
|
||||
*/
|
||||
@Override
|
||||
public void execute(JobExecutionContext ctx) throws JobExecutionException {
|
||||
LogService.getLogger().info(
|
||||
"Create report job triggered, preparing to send report");
|
||||
DerbyDao dao = DerbyDao.getInstance();
|
||||
// synchronize on dao to prevent new log entries from being added
|
||||
// while we're querying and then purging
|
||||
synchronized (dao) {
|
||||
LogReportContainer container = null;
|
||||
try {
|
||||
container = dao.buildReport();
|
||||
} catch (LogServiceException e) {
|
||||
LogService.getLogger().error("Error building report", e);
|
||||
throw new JobExecutionException("Error building report", e);
|
||||
}
|
||||
|
||||
String html = HtmlGenerator.generateHtml(container);
|
||||
LogSrvConfig config = (LogSrvConfig) ctx.getJobDetail()
|
||||
.getJobDataMap().get("config");
|
||||
|
||||
try {
|
||||
ReportEmailer.email(html, config);
|
||||
} catch (Exception e) {
|
||||
LogService.getLogger().error("Error emailing report", e);
|
||||
throw new JobExecutionException("Error emailing report", e);
|
||||
}
|
||||
LogService.getLogger().info(
|
||||
"Report has been sent to: " + config.getToAddress());
|
||||
|
||||
// only clear out the database if the analysis report was
|
||||
// successfully emailed
|
||||
LogService.getLogger().info(
|
||||
"Purging database of messages that were just reported");
|
||||
try {
|
||||
dao.clearEntries();
|
||||
} catch (LogServiceException e) {
|
||||
LogService.getLogger().error("Error purging database", e);
|
||||
throw new JobExecutionException("Error purging database", e);
|
||||
}
|
||||
LogService.getLogger().info("Database purging complete");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -41,6 +41,7 @@ import com.raytheon.uf.logsrv.config.LogSrvConfig;
|
|||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Aug 30, 2013 njensen Initial creation
|
||||
* Jun 11, 2014 2840 njensen Renamed create report job
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -56,8 +57,8 @@ public class JobScheduler {
|
|||
Scheduler sched = factory.getScheduler();
|
||||
sched.start();
|
||||
|
||||
JobDetail job = new JobDetail("Create and Send Report Job",
|
||||
CreateSendReportJob.class);
|
||||
JobDetail job = new JobDetail("Create and Send/Save Report Job",
|
||||
CreateReportJob.class);
|
||||
job.getJobDataMap().put("config", config);
|
||||
String[] split = config.getTimeToSend().split(":");
|
||||
int hour = Integer.parseInt(split[0]);
|
||||
|
@ -70,6 +71,8 @@ public class JobScheduler {
|
|||
Trigger countTrigger = TriggerUtils.makeHourlyTrigger();
|
||||
countTrigger.setName("Count Trigger");
|
||||
sched.scheduleJob(countJob, countTrigger);
|
||||
|
||||
// TODO contemplate a purge job for the outputDir
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue