From f681b52b46a66743721679e86104533d92b22288 Mon Sep 17 00:00:00 2001 From: Nate Jensen Date: Wed, 11 Jun 2014 17:05:09 -0500 Subject: [PATCH] Omaha #2840 log tool can now save html reports to directory Change-Id: Ifa2d9653d2ee689512f33169028705de98f65682 Former-commit-id: 4aec10e9b7155baa7e4243a4db78ad16440dbba7 --- .../com.raytheon.uf.logsrv/conf/config.xml | 35 ++- .../uf/logsrv/config/LogSrvConfig.java | 31 ++- .../uf/logsrv/quartz/CreateReportJob.java | 228 ++++++++++++++++++ .../uf/logsrv/quartz/CreateSendReportJob.java | 103 -------- .../uf/logsrv/quartz/JobScheduler.java | 7 +- 5 files changed, 282 insertions(+), 122 deletions(-) create mode 100644 javaUtilities/com.raytheon.uf.logsrv/src/com/raytheon/uf/logsrv/quartz/CreateReportJob.java delete mode 100644 javaUtilities/com.raytheon.uf.logsrv/src/com/raytheon/uf/logsrv/quartz/CreateSendReportJob.java diff --git a/javaUtilities/com.raytheon.uf.logsrv/conf/config.xml b/javaUtilities/com.raytheon.uf.logsrv/conf/config.xml index c7f04fdab9..824d3c4798 100644 --- a/javaUtilities/com.raytheon.uf.logsrv/conf/config.xml +++ b/javaUtilities/com.raytheon.uf.logsrv/conf/config.xml @@ -1,26 +1,45 @@ - + + + ec-oma - /common/njensen/logsrv/ - + + + Nathan.Jensen@raytheon.com mk2-msg10.raymail.ray.com 143 - + awipsctl@list.app.ray.com, awipstest@list.app.ray.com, david_j_hladky@raytheon.com + + + - 00:45 diff --git a/javaUtilities/com.raytheon.uf.logsrv/src/com/raytheon/uf/logsrv/config/LogSrvConfig.java b/javaUtilities/com.raytheon.uf.logsrv/src/com/raytheon/uf/logsrv/config/LogSrvConfig.java index 3e4bffca58..dacedffee5 100644 --- a/javaUtilities/com.raytheon.uf.logsrv/src/com/raytheon/uf/logsrv/config/LogSrvConfig.java +++ b/javaUtilities/com.raytheon.uf.logsrv/src/com/raytheon/uf/logsrv/config/LogSrvConfig.java @@ -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 * * * @@ -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!"); } } diff --git a/javaUtilities/com.raytheon.uf.logsrv/src/com/raytheon/uf/logsrv/quartz/CreateReportJob.java b/javaUtilities/com.raytheon.uf.logsrv/src/com/raytheon/uf/logsrv/quartz/CreateReportJob.java new file mode 100644 index 0000000000..6fba3702c0 --- /dev/null +++ b/javaUtilities/com.raytheon.uf.logsrv/src/com/raytheon/uf/logsrv/quartz/CreateReportJob.java @@ -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. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Aug 30, 2013            njensen     Initial creation
+ * Jun 11, 2014 2840       njensen     Added save to dir
+ * 
+ * 
+ * + * @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); + } +} diff --git a/javaUtilities/com.raytheon.uf.logsrv/src/com/raytheon/uf/logsrv/quartz/CreateSendReportJob.java b/javaUtilities/com.raytheon.uf.logsrv/src/com/raytheon/uf/logsrv/quartz/CreateSendReportJob.java deleted file mode 100644 index 0882400b02..0000000000 --- a/javaUtilities/com.raytheon.uf.logsrv/src/com/raytheon/uf/logsrv/quartz/CreateSendReportJob.java +++ /dev/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. - * - *
- * 
- * SOFTWARE HISTORY
- * 
- * Date         Ticket#    Engineer    Description
- * ------------ ---------- ----------- --------------------------
- * Aug 30, 2013            njensen     Initial creation
- * 
- * 
- * - * @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"); - } - } - -} diff --git a/javaUtilities/com.raytheon.uf.logsrv/src/com/raytheon/uf/logsrv/quartz/JobScheduler.java b/javaUtilities/com.raytheon.uf.logsrv/src/com/raytheon/uf/logsrv/quartz/JobScheduler.java index eada4ad713..f356c97cd5 100644 --- a/javaUtilities/com.raytheon.uf.logsrv/src/com/raytheon/uf/logsrv/quartz/JobScheduler.java +++ b/javaUtilities/com.raytheon.uf.logsrv/src/com/raytheon/uf/logsrv/quartz/JobScheduler.java @@ -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 * * * @@ -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 } }