Merge "Issue # 1292 Migrate the common and edex projects required for stats from the 5-Data_Delivery branch to the development branch in the AWIPS2_baseline repository: edexOsgi/com.raytheon.uf.common.event edexOsgi/com.raytheon.uf.common.stats edexOsgi/com.raytheon.uf.edex.event.feature edexOsgi/com.raytheon.uf.edex.event edexOsgi/com.raytheon.uf.edex.stats" into development

Former-commit-id: 41472f07d2 [formerly 173813c954] [formerly 41472f07d2 [formerly 173813c954] [formerly 41c8c88a03 [formerly f67e7970061c9bc4dde3b4175dcb9b45d204ff34]]]
Former-commit-id: 41c8c88a03
Former-commit-id: 15ae8a5add [formerly bd49530415]
Former-commit-id: 1f07aee476
This commit is contained in:
Lee Venable 2012-10-26 15:25:52 -05:00 committed by Gerrit Code Review
commit 88b4c01882
62 changed files with 3015 additions and 1 deletions

View file

@ -23,6 +23,13 @@
install-size="0"
version="0.0.0"/>
<plugin
id="com.google.guava"
download-size="0"
install-size="0"
version="0.0.0"
unpack="false"/>
<plugin
id="javax.jms"
download-size="0"

View file

@ -74,6 +74,10 @@
<param name="feature"
value="com.raytheon.uf.edex.ost.feature" />
</antcall>
<antcall target="build">
<param name="feature"
value="com.raytheon.uf.edex.event.feature" />
</antcall>
<antcall target="build">
<param name="feature"
value="com.raytheon.uf.edex.npp.feature" />

View file

@ -96,6 +96,10 @@
id="com.raytheon.uf.edex.ost.feature"
version="0.0.0"/>
<includes
id="com.raytheon.uf.edex.event.feature"
version="0.0.0"/>
<includes
id="com.raytheon.uf.edex.npp.feature"
version="0.0.0"/>

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry kind="src" path="src"/>
<classpathentry kind="output" path="bin"/>
</classpath>

View file

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>com.raytheon.uf.common.event</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.ManifestBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.SchemaBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.pde.PluginNature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

View file

@ -0,0 +1,8 @@
#Thu Jun 14 10:58:39 CDT 2012
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
org.eclipse.jdt.core.compiler.compliance=1.6
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.source=1.6

View file

@ -0,0 +1,12 @@
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Event
Bundle-SymbolicName: com.raytheon.uf.common.event
Bundle-Version: 1.0.0.qualifier
Bundle-Vendor: RAYTHEON
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Require-Bundle: com.raytheon.uf.common.serialization;bundle-version="1.12.1174",
com.raytheon.uf.common.serialization.comm;bundle-version="1.12.1174",
javax.persistence;bundle-version="1.0.0",
com.raytheon.uf.common.dataplugin;bundle-version="1.12.1174"
Export-Package: com.raytheon.uf.common.event

View file

@ -0,0 +1,4 @@
source.. = src/
output.. = bin/
bin.includes = META-INF/,\
.

View file

@ -0,0 +1,8 @@
<project basedir="." default="deploy" name="com.raytheon.uf.common.event">
<available file="../build.edex" property="build.dir.location" value="../build.edex"/>
<available file="../../../../../build.edex" property="build.dir.location" value="../../../../../build.edex"/>
<import file="${build.dir.location}/basebuilds/component_deploy_base.xml" />
</project>

View file

@ -0,0 +1,49 @@
package com.raytheon.uf.common.event;
import java.io.Serializable;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import javax.persistence.Column;
import com.raytheon.uf.common.serialization.ISerializableObject;
import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement;
public abstract class Event implements Serializable, ISerializableObject {
private static final long serialVersionUID = 1L;
@Column
@DynamicSerializeElement
protected Calendar date;
@Column
@DynamicSerializeElement
protected String id;
public Event() {
date = Calendar.getInstance();
}
public Calendar getDate() {
return date;
}
public void setDate(Calendar date) {
this.date = date;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String toString() {
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-d hh:mm:ss");
return formatter.format(date.getTime()) + " Id: " + id;
}
}

View file

@ -0,0 +1,68 @@
/**
* 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.common.event;
import com.raytheon.uf.common.serialization.annotations.DynamicSerialize;
import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement;
/**
* TODO Add Description
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Oct 25, 2012 #1292 bgonzale Initial creation
*
* </pre>
*
* @author bgonzale
* @version 1.0
*/
@DynamicSerialize
public class ProcessEvent extends Event {
private static final long serialVersionUID = 1L;
@DynamicSerializeElement
private final String message;
public ProcessEvent(String message) {
super();
this.message = message;
}
@Override
public String toString() {
return super.toString() + " : " + getMessage();
}
/**
* @return the message
*/
public String getMessage() {
return message;
}
}

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry kind="src" path="src"/>
<classpathentry kind="output" path="bin"/>
</classpath>

View file

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>com.raytheon.uf.common.stats</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.ManifestBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.SchemaBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.pde.PluginNature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

View file

@ -0,0 +1,8 @@
#Mon Aug 06 10:54:57 CDT 2012
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
org.eclipse.jdt.core.compiler.compliance=1.6
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.source=1.6

View file

@ -0,0 +1,13 @@
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Stats
Bundle-SymbolicName: com.raytheon.uf.common.stats
Bundle-Version: 1.0.0.qualifier
Bundle-Vendor: RAYTHEON
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Export-Package: com.raytheon.uf.common.stats
Require-Bundle: com.raytheon.uf.common.time;bundle-version="1.12.1174",
com.raytheon.uf.common.serialization;bundle-version="1.12.1174",
com.raytheon.uf.common.serialization.comm;bundle-version="1.12.1174",
javax.persistence;bundle-version="1.0.0",
com.raytheon.uf.common.dataplugin;bundle-version="1.12.1174"

View file

@ -0,0 +1,2 @@
com.raytheon.uf.common.stats.StatsRecord
com.raytheon.uf.common.stats.AggregateRecord

View file

@ -0,0 +1,4 @@
source.. = src/
output.. = bin/
bin.includes = META-INF/,\
.

View file

@ -0,0 +1,189 @@
/**
* 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.common.stats;
import java.util.Calendar;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
import com.raytheon.uf.common.dataplugin.persist.PersistableDataObject;
import com.raytheon.uf.common.serialization.annotations.DynamicSerialize;
import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement;
/**
* Record class for an aggregate result.
*
* <pre>
*
* SOFTWARE HISTORY
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Aug 21, 2012 jsanchez Initial creation
*
* </pre>
*
* @author jsanchez
* @version 1.0
*/
@Entity
@Table(name = "aggregate", schema = "events")
@XmlRootElement
@XmlAccessorType(XmlAccessType.NONE)
@DynamicSerialize
public class AggregateRecord extends PersistableDataObject {
@GeneratedValue(strategy = GenerationType.AUTO)
@Id
@DynamicSerializeElement
private Integer id;
@Column(nullable = false)
@DynamicSerializeElement
private Calendar startDate;
@Column(nullable = false)
@DynamicSerializeElement
private Calendar endDate;
@Column(nullable = false)
@DynamicSerializeElement
private String eventType;
@DynamicSerializeElement
private String grouping;
@Column(nullable = false)
@DynamicSerializeElement
private String field;
@DynamicSerializeElement
private double max;
@DynamicSerializeElement
private double min;
@DynamicSerializeElement
private double sum;
@DynamicSerializeElement
private double count;
public AggregateRecord() {
}
public AggregateRecord(String eventType, Calendar startDate,
Calendar endDate, String groupings, String field) {
this.eventType = eventType;
this.startDate = startDate;
this.endDate = endDate;
this.grouping = groupings;
this.field = field;
}
public Calendar getStartDate() {
return startDate;
}
public void setStartDate(Calendar startDate) {
this.startDate = startDate;
}
public Calendar getEndDate() {
return endDate;
}
public void setEndDate(Calendar endDate) {
this.endDate = endDate;
}
public String getEventType() {
return eventType;
}
public void setEventType(String eventType) {
this.eventType = eventType;
}
public String getGrouping() {
return grouping;
}
public void setGrouping(String grouping) {
this.grouping = grouping;
}
public String getField() {
return field;
}
public void setField(String field) {
this.field = field;
}
public double getMax() {
return max;
}
public void setMax(double max) {
this.max = max;
}
public double getMin() {
return min;
}
public void setMin(double min) {
this.min = min;
}
public double getSum() {
return sum;
}
public void setSum(double sum) {
this.sum = sum;
}
public double getCount() {
return count;
}
public void setCount(double count) {
this.count = count;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
}

View file

@ -0,0 +1,88 @@
/**
* 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.common.stats;
import com.raytheon.uf.common.serialization.annotations.DynamicSerialize;
import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement;
import com.raytheon.uf.common.serialization.comm.IServerRequest;
import com.raytheon.uf.common.time.TimeRange;
/**
* Request results from the metadata.aggregate table.
*
* SOFTWARE HISTORY
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Aug 21, 2012 jsanchez Initial creation
*
* @author jsanchez
*
*/
@DynamicSerialize
public class AggregatedStatsRequest implements IServerRequest {
@DynamicSerializeElement
private TimeRange timeRange;
@DynamicSerializeElement
private String eventType;
@DynamicSerializeElement
private String[] grouping;
@DynamicSerializeElement
private String field;
public AggregatedStatsRequest() {
}
public TimeRange getTimeRange() {
return timeRange;
}
public void setTimeRange(TimeRange timeRange) {
this.timeRange = timeRange;
}
public String getEventType() {
return eventType;
}
public void setEventType(String eventType) {
this.eventType = eventType;
}
public String[] getGrouping() {
return grouping;
}
public void setGrouping(String[] grouping) {
this.grouping = grouping;
}
public String getField() {
return field;
}
public void setField(String field) {
this.field = field;
}
}

View file

@ -0,0 +1,107 @@
/**
* 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.common.stats;
import com.raytheon.uf.common.serialization.ISerializableObject;
import com.raytheon.uf.common.serialization.annotations.DynamicSerialize;
import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement;
import com.raytheon.uf.common.time.TimeRange;
/**
* Response from the handler of the results in the metadata.aggregate table.
*
* SOFTWARE HISTORY
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Aug 21, 2012 jsanchez Initial creation
*
* @author jsanchez
*
*/
@DynamicSerialize
public class AggregatedStatsResponse implements ISerializableObject {
@DynamicSerializeElement
private TimeRange timeRange;
@DynamicSerializeElement
private String eventType;
@DynamicSerializeElement
private String[] grouping;
@DynamicSerializeElement
private String field;
@DynamicSerializeElement
private AggregateRecord[] records;
public AggregatedStatsResponse() {
}
public AggregatedStatsResponse(TimeRange timeRange, String eventType,
String[] grouping, String field) {
this.timeRange = timeRange;
this.eventType = eventType;
this.grouping = grouping;
this.field = field;
}
public TimeRange getTimeRange() {
return timeRange;
}
public String getEventType() {
return eventType;
}
public void setEventType(String eventType) {
this.eventType = eventType;
}
public String[] getGrouping() {
return grouping;
}
public void setGrouping(String[] grouping) {
this.grouping = grouping;
}
public String getField() {
return field;
}
public void setField(String field) {
this.field = field;
}
public void setTimeRange(TimeRange timeRange) {
this.timeRange = timeRange;
}
public AggregateRecord[] getRecords() {
return records;
}
public void setRecords(AggregateRecord[] records) {
this.records = records;
}
}

View file

@ -0,0 +1,108 @@
/**
* 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.common.stats;
import java.util.Calendar;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
import com.raytheon.uf.common.dataplugin.persist.PersistableDataObject;
import com.raytheon.uf.common.serialization.annotations.DynamicSerialize;
import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement;
/**
* Record class for stats waiting to be stored in the appropriate bucket.
*
* <pre>
*
* SOFTWARE HISTORY
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Aug 21, 2012 jsanchez Initial creation
*
* </pre>
*
* @author jsanchez
*
*/
@Entity
@Table(name = "stats", schema = "events")
@XmlRootElement
@XmlAccessorType(XmlAccessType.NONE)
@DynamicSerialize
public class StatsRecord extends PersistableDataObject {
@GeneratedValue(strategy = GenerationType.AUTO)
@Id
@DynamicSerializeElement
private Integer id;
@Column(nullable = false)
@DynamicSerializeElement
private Calendar date;
@Column(nullable = false)
@DynamicSerializeElement
private String eventType;
@Column(nullable = false)
@DynamicSerializeElement
private byte[] event;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Calendar getDate() {
return date;
}
public void setDate(Calendar date) {
this.date = date;
}
public String getEventType() {
return eventType;
}
public void setEventType(String eventType) {
this.eventType = eventType;
}
public byte[] getEvent() {
return event;
}
public void setEvent(byte[] event) {
this.event = event;
}
}

View file

@ -293,6 +293,13 @@
install-size="0"
version="0.0.0"/>
<plugin
id="com.google.guava"
download-size="0"
install-size="0"
version="0.0.0"
unpack="false"/>
<plugin
id="org.apache.commons.cli"
download-size="0"

View file

@ -1143,4 +1143,13 @@ public class CoreDao extends HibernateDaoSupport {
return getSessionFactory().getClassMetadata(daoClass);
}
}
public void deleteAll(final List<?> objs) {
txTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
public void doInTransactionWithoutResult(TransactionStatus status) {
getHibernateTemplate().deleteAll(objs);
}
});
}
}

View file

@ -17,6 +17,8 @@ Require-Bundle: org.apache.camel;bundle-version="1.0.0",
javax.servlet
Export-Package: com.raytheon.uf.edex.esb.camel,
com.raytheon.uf.edex.esb.camel.directvm
Import-Package: com.raytheon.uf.common.message,
Import-Package: com.raytheon.uf.common.event,
com.raytheon.uf.common.message,
com.raytheon.uf.edex.database.cluster,
com.raytheon.uf.edex.event,
javax.persistence

View file

@ -29,9 +29,11 @@ import org.apache.camel.Header;
import org.apache.camel.Headers;
import com.raytheon.uf.common.dataplugin.PluginDataObject;
import com.raytheon.uf.common.event.ProcessEvent;
import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.status.UFStatus.Priority;
import com.raytheon.uf.edex.event.EventBus;
/**
* Provides logging and deletion services for camel
@ -111,6 +113,9 @@ public class ProcessUtil {
}
sb.append(" (sec)");
}
EventBus.getInstance().publish(new ProcessEvent(sb.toString()));
// Make sure we have something to log.
if (sb.length() > 0) {
handler.handle(Priority.INFO, sb.toString());

View file

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>com.raytheon.uf.edex.event.feature</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.pde.FeatureBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.pde.FeatureNature</nature>
</natures>
</projectDescription>

View file

@ -0,0 +1 @@
bin.includes = feature.xml

View file

@ -0,0 +1,48 @@
<?xml version="1.0" encoding="UTF-8"?>
<feature
id="com.raytheon.uf.edex.event.feature"
label="EDEX Event Feature"
version="1.0.0.qualifier"
provider-name="RAYTHEON">
<description url="http://www.example.com/description">
[Enter Feature Description here.]
</description>
<copyright url="http://www.example.com/copyright">
[Enter Copyright Description here.]
</copyright>
<license url="http://www.example.com/license">
[Enter License Description here.]
</license>
<plugin
id="com.raytheon.uf.common.event"
download-size="0"
install-size="0"
version="0.0.0"
unpack="false"/>
<plugin
id="com.raytheon.uf.edex.event"
download-size="0"
install-size="0"
version="0.0.0"
unpack="false"/>
<plugin
id="com.raytheon.uf.common.stats"
download-size="0"
install-size="0"
version="0.0.0"
unpack="false"/>
<plugin
id="com.raytheon.uf.edex.stats"
download-size="0"
install-size="0"
version="0.0.0"
unpack="false"/>
</feature>

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry kind="src" path="src"/>
<classpathentry kind="output" path="bin"/>
</classpath>

View file

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>com.raytheon.uf.edex.event</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.ManifestBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.SchemaBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.pde.PluginNature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

View file

@ -0,0 +1,8 @@
#Thu Jun 14 11:22:23 CDT 2012
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
org.eclipse.jdt.core.compiler.compliance=1.6
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.source=1.6

View file

@ -0,0 +1,22 @@
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Event
Bundle-SymbolicName: com.raytheon.uf.edex.event
Bundle-Version: 1.0.0.qualifier
Bundle-Vendor: RAYTHEON
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Require-Bundle: com.google.guava;bundle-version="1.0.0",
com.raytheon.uf.common.status;bundle-version="1.12.1174",
com.raytheon.uf.edex.core;bundle-version="1.12.1174",
com.raytheon.uf.common.event;bundle-version="1.0.0",
org.apache.commons.logging;bundle-version="1.1.1",
com.raytheon.uf.common.time;bundle-version="1.12.1174",
com.raytheon.uf.common.serialization;bundle-version="1.12.1174",
com.raytheon.uf.edex.database;bundle-version="1.0.0",
com.raytheon.uf.common.dataquery;bundle-version="1.0.0",
org.springframework;bundle-version="2.5.6",
com.raytheon.uf.common.localization;bundle-version="1.12.1174",
com.raytheon.uf.common.serialization.comm;bundle-version="1.12.1174",
com.raytheon.uf.common.dataplugin;bundle-version="1.12.1174",
org.junit
Export-Package: com.raytheon.uf.edex.event

View file

@ -0,0 +1,5 @@
source.. = src/
output.. = bin/
bin.includes = META-INF/,\
.,\
res/

View file

@ -0,0 +1,7 @@
<project basedir="." default="deploy" name="com.raytheon.uf.edex.event">
<available file="../build.edex" property="build.dir.location" value="../build.edex"/>
<available file="../../../../../build.edex" property="build.dir.location" value="../../../../../build.edex"/>
<import file="${build.dir.location}/basebuilds/component_deploy_base.xml" />
</project>

View file

@ -0,0 +1,29 @@
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:amq="http://activemq.apache.org/schema/core"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://activemq.apache.org/schema/core http://activemq.apache.org/schema/core/activemq-core.xsd
http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">
<bean id="eventBusThreadCount" class="java.lang.String">
<constructor-arg type="java.lang.String" value="15" />
</bean>
<bean id="logHandler" class="com.raytheon.uf.edex.event.handler.LogHandler"/>
<bean id="jms-notify" class="org.apache.camel.component.jms.JmsComponent">
<constructor-arg ref="jmsIngestNotifyConfig" />
<property name="taskExecutor" ref="notifyThreadPool" />
</bean>
<bean id="jmsIngestNotifyConfig" class="org.apache.camel.component.jms.JmsConfiguration"
factory-bean="jmsConfig" factory-method="copy">
</bean>
<bean id="notifyThreadPool"
class="com.raytheon.uf.edex.esb.camel.spring.JmsThreadPoolTaskExecutor">
<property name="corePoolSize" value="1" />
<property name="maxPoolSize" value="1" />
</bean>
</beans>

View file

@ -0,0 +1,86 @@
package com.raytheon.uf.edex.event;
import java.util.concurrent.Executors;
import com.google.common.eventbus.AsyncEventBus;
import com.raytheon.uf.common.event.Event;
import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.edex.core.EDEXUtil;
/**
*
* The EventBus.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Oct 11, 2012 1261 djohnson Add SW history, create constants for fields,
* add unregister.
*
* </pre>
*
* @author djohnson
* @version 1.0
*/
public class EventBus {
private static final IUFStatusHandler statusHandler = UFStatus
.getHandler(EventBus.class);
private static final EventBus instance = new EventBus();
private static final AsyncEventBus asyncEventBus;
static {
int threadCount = 15;
try {
threadCount = Integer.parseInt((String) EDEXUtil
.getESBComponent("eventBusThreadCount"));
} catch (Exception e) {
statusHandler.error(
"Unable to set thread pool size from spring; defaulting size to "
+ threadCount + ".",
e);
}
asyncEventBus = new AsyncEventBus(
Executors.newFixedThreadPool(threadCount));
}
/**
* Returns the same instance of the data delivery event bus
*
* @return
*/
public static EventBus getInstance() {
return instance;
}
/**
* Register an object with the event bus.
*
* @param subscriber
*/
public void register(Object subscriber) {
asyncEventBus.register(subscriber);
}
/**
* Publishes events for all subscribers to receive
*
* @param event
*/
public void publish(Event event) {
asyncEventBus.post(event);
}
/**
* Unregister an object with the event bus.
*
* @param instance2
*/
public void unregister(Object subscriber) {
asyncEventBus.unregister(subscriber);
}
}

View file

@ -0,0 +1,52 @@
package com.raytheon.uf.edex.event.handler;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.google.common.eventbus.AllowConcurrentEvents;
import com.google.common.eventbus.Subscribe;
import com.raytheon.uf.common.event.Event;
import com.raytheon.uf.edex.event.EventBus;
/**
*
* Logs ALL events published on the event bus
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Mar 1, 2012 jsanchez Initial creation
*
* </pre>
*
* @author jsanchez
* @version 1.0
*/
public class LogHandler {
private final Log logger;
private static EventBus eventBus = EventBus.getInstance();
/**
* Creates a new object
*/
public LogHandler() {
eventBus.register(this);
logger = LogFactory.getLog("Event");
}
/**
* Listens for any DataDeliveryEvent object published on the event bus
*
* @param event
*/
@Subscribe
@AllowConcurrentEvents
public void eventListener(Event event) {
logger.info(event.toString());
}
}

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry kind="src" path="src"/>
<classpathentry kind="output" path="bin"/>
</classpath>

View file

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>com.raytheon.uf.edex.stats</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.ManifestBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.SchemaBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.pde.PluginNature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

View file

@ -0,0 +1,8 @@
#Mon Jun 18 16:45:16 CDT 2012
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
org.eclipse.jdt.core.compiler.compliance=1.6
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.source=1.6

View file

@ -0,0 +1,22 @@
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Stats
Bundle-SymbolicName: com.raytheon.uf.edex.stats
Bundle-Version: 1.0.0.qualifier
Bundle-Vendor: RAYTHEON
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Require-Bundle: com.raytheon.uf.common.serialization;bundle-version="1.12.1174",
com.raytheon.uf.edex.event;bundle-version="1.0.0",
com.raytheon.uf.common.event;bundle-version="1.0.0",
com.google.guava;bundle-version="1.0.0",
com.raytheon.uf.edex.database;bundle-version="1.0.0",
com.raytheon.uf.common.localization;bundle-version="1.12.1174",
com.raytheon.uf.common.dataquery;bundle-version="1.0.0",
com.raytheon.uf.common.time;bundle-version="1.12.1174",
com.raytheon.uf.common.serialization.comm;bundle-version="1.12.1174",
com.raytheon.uf.common.stats;bundle-version="1.0.0",
com.raytheon.uf.common.dataplugin;bundle-version="1.12.1174",
org.springframework;bundle-version="2.5.6",
com.raytheon.uf.edex.core;bundle-version="1.12.1174",
com.raytheon.uf.common.status;bundle-version="1.12.1174",
org.apache.commons.collections;bundle-version="3.2.0"

View file

@ -0,0 +1,5 @@
source.. = src/
output.. = bin/
bin.includes = META-INF/,\
.,\
res/

View file

@ -0,0 +1,42 @@
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:amq="http://activemq.apache.org/schema/core"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">
<bean id="statsPurge"
class="com.raytheon.uf.edex.stats.StatsPurge"
depends-on="statsRegister"/>
<bean id="statsHandler"
class="com.raytheon.uf.edex.stats.handler.StatsHandler"
depends-on="eventBusThreadCount"/>
<bean id="aggregateManager" class="com.raytheon.uf.edex.stats.AggregateManager">
<constructor-arg value="${stats.period}"/>
<constructor-arg value="${stats.scanInterval}"/>
</bean>
<bean id="edexStatsRegistered" factory-bean="contextManager"
factory-method="register" depends-on="persistCamelRegistered">
<constructor-arg ref="edexStats-camel"/>
</bean>
<camelContext id="edexStats-camel"
xmlns="http://camel.apache.org/schema/spring"
errorHandlerRef="errorHandler"
autoStartup="false">
<route id="statsTableScan">
<from uri="timer://scanStats?period=15m" />
<doTry>
<bean ref="statsPurge" method="purgeAggregates"/>
<bean ref="aggregateManager" method="scan"/>
<doCatch>
<exception>java.lang.Throwable</exception>
<to uri="log:stats?level=ERROR&amp;showBody=false&amp;showCaughtException=true&amp;showStackTrace=true"/>
</doCatch>
</doTry>
</route>
</camelContext>
</beans>

View file

@ -0,0 +1,18 @@
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:amq="http://activemq.apache.org/schema/core" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://activemq.apache.org/schema/core http://activemq.apache.org/schema/core/activemq-core.xsd
http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">
<bean id="statsDatabaseProperties" class="com.raytheon.uf.edex.database.DatabasePluginProperties">
<property name="pluginName" value="stats" />
<property name="pluginFQN" value="com.raytheon.uf.common.stats" />
<property name="database" value="metadata" />
</bean>
<bean id="statsRegister" factory-bean="dbPluginRegistry" factory-method="register">
<constructor-arg value="stats"/>
<constructor-arg ref="statsDatabaseProperties"/>
</bean>
</beans>

View file

@ -0,0 +1,19 @@
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:amq="http://activemq.apache.org/schema/core"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">
<!-- Need to set up connect between cave and edex
1) The possible combinations to populate drop downs etc
2) Bucketizing so that Cave requests data in 15 minute buckets,
you would need to do the aggregation (still undecided on if this is a cave or edex feature).
-->
<bean id="aggregatedStatsHandler" class="com.raytheon.uf.edex.stats.handler.AggregatedStatsHandler"/>
<bean factory-bean="handlerRegistry" factory-method="register">
<constructor-arg value="com.raytheon.uf.common.stats.AggregatedStatsRequest"/>
<constructor-arg ref="aggregatedStatsHandler"/>
</bean>
</beans>

View file

@ -0,0 +1,4 @@
# scan interval of stats table in minutes
stats.scanInterval=15
# bucket interval or period of when to aggregate in minutes
stats.period=2

View file

@ -0,0 +1,4 @@
# scan interval of stats table in minutes
stats.scanInterval=15
# bucket interval or period of when to aggregate in minutes
stats.period=2

View file

@ -0,0 +1,485 @@
/**
* 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.edex.stats;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TimeZone;
import com.raytheon.uf.common.event.Event;
import com.raytheon.uf.common.serialization.SerializationException;
import com.raytheon.uf.common.serialization.SerializationUtil;
import com.raytheon.uf.common.stats.AggregateRecord;
import com.raytheon.uf.common.stats.StatsRecord;
import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.time.TimeRange;
import com.raytheon.uf.edex.database.dao.CoreDao;
import com.raytheon.uf.edex.database.dao.DaoConfig;
import com.raytheon.uf.edex.stats.dao.StatsDao;
import com.raytheon.uf.edex.stats.handler.StatsHandler;
import com.raytheon.uf.edex.stats.util.ConfigLoader;
import com.raytheon.uf.edex.stats.xml.Aggregate;
import com.raytheon.uf.edex.stats.xml.Item;
import com.raytheon.uf.edex.stats.xml.StatsConfig;
/**
* Aggregates stat records based on the statsConfig files and stores them after
* a configured period.
*
* *
*
* <pre>
*
* SOFTWARE HISTORY
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Aug 21, 2012 jsanchez Stored the aggregate buckets in the db.
*
* </pre>
*
* @author jsanchez
*
*/
public class AggregateManager {
private static final transient IUFStatusHandler statusHandler = UFStatus
.getHandler(AggregateManager.class);
private class TimeRangeKey extends TimeRange {
public TimeRangeKey(Calendar cal1, Calendar cal2) {
super(cal1, cal2);
}
@Override
public boolean equals(Object o) {
if (o != null && o instanceof TimeRange) {
TimeRange other = (TimeRange) o;
return (this.getStart().equals(other.getStart()) && this
.getEnd().equals(other.getEnd()));
}
return false;
}
@Override
public int hashCode() {
return 1;
}
public String toString() {
return super.toString();
}
}
/** In minutes */
private int bucketInterval;
/** In minutes */
private int scanInterval;
/** default value */
private static final int defaultBucketInterval = 5;
/** default value */
private static final int defaultScanInterval = 15;
/** loads localized copies of the statsConfig */
private ConfigLoader configLoader;
private CoreDao aggregateRecordDao = new CoreDao(DaoConfig.forClass(
"metadata", AggregateRecord.class));
public AggregateManager(String bucketInterval, String scanInterval)
throws Exception {
this.configLoader = new ConfigLoader();
validateIntervals(bucketInterval, scanInterval);
configLoader.load();
StatsHandler.setValidEventTypes(configLoader.getConfigurations());
}
/**
* Tests if the bucket interval and the scan interval are valid values. If
* values are invalid then values will be set to default values.
*
* @param bucketInt
* @param scanInt
* @return
*/
private void validateIntervals(String bucketInt, String scanInt) {
try {
bucketInterval = Integer.parseInt(bucketInt);
} catch (NumberFormatException e) {
bucketInterval = defaultBucketInterval;
statusHandler.info("'" + bucketInt
+ "' is not a valid bucket interval value. Setting to '"
+ defaultBucketInterval + "'");
}
try {
scanInterval = Integer.parseInt(scanInt);
} catch (NumberFormatException e) {
scanInterval = defaultScanInterval;
statusHandler.info("'" + scanInt
+ "' is not a valid scan interval value. Setting to '"
+ defaultScanInterval + "'");
}
if (scanInterval < bucketInterval) {
scanInterval = defaultBucketInterval;
bucketInterval = defaultBucketInterval;
statusHandler
.info("The bucket interval can not be greater than the scan interval. Setting scan interval to '"
+ defaultBucketInterval
+ "' and bucket interval to '"
+ bucketInterval
+ "'");
}
int incrementsWithinHour = bucketInterval;
// checks if period is larger than 60 minutes
if (bucketInterval > 60) {
incrementsWithinHour = bucketInterval % 60;
}
if (60 % incrementsWithinHour != 0) {
bucketInterval = defaultBucketInterval;
statusHandler
.info("The bucket interval must go into an hour evenly. Setting bucket interval to '"
+ bucketInterval + "'");
}
}
/**
* Scans the stats table to be stored in buckets and aggregate if necessary.
*/
public void scan() throws Exception {
StatsDao statsRecordDao = new StatsDao();
Map<String, Map<TimeRangeKey, List<StatsRecord>>> aggregateBuckets = new HashMap<String, Map<TimeRangeKey, List<StatsRecord>>>();
// retrieves records and sorts in buckets
retrieveStatRecords(statsRecordDao, aggregateBuckets);
// loops through map to aggregate buckets
for (StatsConfig statsConfig : configLoader.getConfigurations()) {
String eventType = statsConfig.getEventType();
Map<TimeRangeKey, List<StatsRecord>> map = aggregateBuckets
.get(eventType);
// map should never be null, since it will be set in the 'sort'
// method.
for (Iterator<Map.Entry<TimeRangeKey, List<StatsRecord>>> iter = map.entrySet().iterator(); iter.hasNext(); ) {
Entry<TimeRangeKey, List<StatsRecord>> element = iter.next();
TimeRangeKey tr = element.getKey();
List<StatsRecord> records = element.getValue();
if (!records.isEmpty()) {
List<Event> data = extractEvents(records);
aggregate(statsConfig, tr, data);
try {
statsRecordDao.deleteAll(records);
} catch (Exception e) {
statusHandler.error("Error deleting stat records", e);
}
}
iter.remove();
}
}
}
/**
* Retrieve StatRecords from the metadata.event.stats table. This method
* does not retrieve records of the current bucket.
*/
private void retrieveStatRecords(StatsDao statsRecordDao,
Map<String, Map<TimeRangeKey, List<StatsRecord>>> aggregateBuckets)
throws Exception {
Calendar current = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
for (StatsConfig statsConfig : configLoader.getConfigurations()) {
String eventType = statsConfig.getEventType();
// Does not retrieve stat records of current bucket.
// this method should always return a valid array.
StatsRecord[] records = statsRecordDao.retrieveRecords(
getBucketStartTime(current), eventType);
sort(eventType, records, aggregateBuckets);
}
}
/**
* Stores the results into proper aggregate buckets. This method assumes
* that the records are in date order.
*
* @param events
*/
private void sort(String eventType, StatsRecord[] records,
Map<String, Map<TimeRangeKey, List<StatsRecord>>> aggregateBuckets)
throws Exception {
Map<TimeRangeKey, List<StatsRecord>> map = aggregateBuckets
.get(eventType);
if (map == null) {
map = new HashMap<TimeRangeKey, List<StatsRecord>>();
aggregateBuckets.put(eventType, map);
}
TimeRangeKey timeRange = null;
for (StatsRecord record : records) {
if (timeRange == null
|| !timeRange.contains(record.getDate().getTime())) {
// Create bucket based on stats record date
timeRange = createTimeRangeKey(record.getDate());
}
List<StatsRecord> bucketList = map.get(timeRange);
if (bucketList == null) {
bucketList = new ArrayList<StatsRecord>();
map.put(timeRange, bucketList);
}
bucketList.add(record);
}
}
/**
* Creates a time range from a date and the bucket interval. The time range
* start time that will be the date rounded to the next bucket interval. The
* time range end time will be the start time plus the bucket interval.
*
* @param date
* @return
*/
private TimeRangeKey createTimeRangeKey(Calendar date) {
Calendar start = getBucketStartTime(date);
Calendar end = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
end.setTimeInMillis(start.getTimeInMillis());
end.add(Calendar.MINUTE, bucketInterval);
TimeRangeKey timeRangeKey = new TimeRangeKey(start, end);
return timeRangeKey;
}
/**
* Calculates the start time that will be the date rounded to the next
* bucket interval
*
* @param date
* @return
*/
private Calendar getBucketStartTime(Calendar date) {
int currentMinutes = date.get(Calendar.MINUTE);
int incrementsWithinHour = bucketInterval;
// checks if period is larger than 60 minutes
if (bucketInterval > 60) {
incrementsWithinHour = bucketInterval % 60;
}
int mod = currentMinutes % incrementsWithinHour;
Calendar start = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
start.setTimeInMillis(date.getTimeInMillis());
start.add(Calendar.MINUTE, -mod);
start.set(Calendar.SECOND, 0);
start.set(Calendar.MILLISECOND, 0);
return start;
}
/**
* Extracts the events from the stats records.
*
* @param records
* @return
*/
private List<Event> extractEvents(List<StatsRecord> records) {
List<Event> eventsList = new ArrayList<Event>(records.size());
for (StatsRecord record : records) {
try {
Event event = (Event) SerializationUtil
.transformFromThrift(record.getEvent());
eventsList.add(event);
} catch (SerializationException e) {
statusHandler
.error("Error trying to transform event. Aggregation may be inaccurate. ",
e);
}
}
return eventsList;
}
/**
* Performs the aggregation based on the statsConfig file.
*
* @param key
* @param data
*/
private void aggregate(StatsConfig statsConfig, TimeRange timeRange,
List<Event> data) {
Calendar start = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
start.setTime(timeRange.getStart());
Calendar end = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
end.setTime(timeRange.getEnd());
// collect grouping names from stats config
List<String> groupByColumns = new ArrayList<String>();
for (Item item : statsConfig.getGroupBy().getAttributes()) {
String column = item.getName();
groupByColumns.add(column);
}
// breaks data into groups
Map<String, List<Event>> map = divideIntoGroups(data, groupByColumns);
// perform aggregate functions on the grouped data
for (String groupKey : map.keySet()) {
List<Event> groupData = map.get(groupKey);
for (Aggregate aggregate : statsConfig.getAggregates()) {
String field = aggregate.getField();
try {
double[] values = new double[groupData.size()];
String methodName = getterMethodName(field);
for (int i = 0; i < groupData.size(); i++) {
Object obj = groupData.get(i);
Class<?> clazz = obj.getClass();
Method m = clazz.getMethod(methodName, new Class<?>[0]);
Number number = (Number) m.invoke(obj, new Object[0]);
values[i] = number.doubleValue();
}
double count = values.length;
double max = 0;
double min = Double.MAX_VALUE;
double sum = 0;
for (int i = 0; i < values.length; i++) {
sum += values[i];
if (values[i] > max) {
max = values[i];
}
if (values[i] < min) {
min = values[i];
}
}
AggregateRecord record = new AggregateRecord(
statsConfig.getEventType(), start, end, groupKey,
field);
record.setSum(sum);
record.setMin(min);
record.setMax(max);
record.setCount(count);
aggregateRecordDao.persist(record);
} catch (Exception e) {
statusHandler.error("Unable to aggregate '" + field + "'",
e);
}
}
}
}
/**
* Breaks the list of data into groups based on groupByColumns. The key is a
* concatenation of the column values (i.e. datatype.username). This method
* can group data to n-number of levels.
*
* @param data
* @param groupByColumns
* @return
*/
private Map<String, List<Event>> divideIntoGroups(List<Event> data,
List<String> groupByColumns) {
Map<String, List<Event>> map = new HashMap<String, List<Event>>();
map.put("", data);
for (String column : groupByColumns) {
List<Map<String, List<Event>>> listOfMaps = new ArrayList<Map<String, List<Event>>>();
for (String parent : map.keySet()) {
List<Event> list = map.get(parent);
listOfMaps.add(group(list, column, parent));
}
map.clear();
// replace map with grouped data
for (Map<String, List<Event>> m : listOfMaps) {
for (String k : m.keySet()) {
map.put(k, m.get(k));
}
}
}
return map;
}
/**
* Helper method to group data to one level.
*
* @param data
* @param column
* @param parent
* @return
*/
private Map<String, List<Event>> group(List<Event> data, String column,
String parent) {
Map<String, List<Event>> map = new HashMap<String, List<Event>>();
String methodName = getterMethodName(column);
for (Event rec : data) {
try {
Class<?> clazz = rec.getClass();
Method m = clazz.getMethod(methodName, new Class<?>[0]);
String value = column + ":"
+ String.valueOf(m.invoke(rec, new Object[0]));
if (parent.length() > 0) {
value = parent + "-" + value;
}
List<Event> list = map.get(value);
if (list == null) {
list = new ArrayList<Event>();
}
list.add(rec);
map.put(value, list);
} catch (Exception e) {
statusHandler.error("Error creating groups", e);
}
}
return map;
}
/**
* Returns the name of the getter method for the parameter
*
* @param parameter
* @return
*/
private String getterMethodName(String parameter) {
return "get" + parameter.substring(0, 1).toUpperCase()
+ parameter.substring(1);
}
}

View file

@ -0,0 +1,180 @@
/**
* 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.edex.stats;
import java.io.File;
import java.util.Calendar;
import java.util.List;
import java.util.TimeZone;
import javax.xml.bind.JAXBException;
import com.raytheon.uf.common.dataquery.db.QueryParam.QueryOperand;
import com.raytheon.uf.common.localization.PathManagerFactory;
import com.raytheon.uf.common.serialization.SerializationException;
import com.raytheon.uf.common.serialization.SerializationUtil;
import com.raytheon.uf.common.stats.AggregateRecord;
import com.raytheon.uf.common.stats.StatsRecord;
import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.edex.database.DataAccessLayerException;
import com.raytheon.uf.edex.database.dao.CoreDao;
import com.raytheon.uf.edex.database.dao.DaoConfig;
import com.raytheon.uf.edex.database.purge.PurgeRule;
import com.raytheon.uf.edex.database.purge.PurgeRuleSet;
import com.raytheon.uf.edex.database.query.DatabaseQuery;
import com.raytheon.uf.edex.stats.util.Archiver;
/**
* Purges the stats table of expired/unused stat records. Purges the aggregate
* table and write it to disk.
*
* *
*
* <pre>
*
* SOFTWARE HISTORY
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Aug 21, 2012 jsanchez Initial creation.
*
* </pre>
*
* @author jsanchez
*
*/
public class StatsPurge {
private static final transient IUFStatusHandler statusHandler = UFStatus
.getHandler(StatsPurge.class);
private Archiver archiver;
private CoreDao aggregateRecordDao = new CoreDao(DaoConfig.forClass(
"metadata", AggregateRecord.class));
private CoreDao statsRecordDao = new CoreDao(DaoConfig.forClass("metadata",
StatsRecord.class));
private PurgeRuleSet aggregatePurgeRules;
private PurgeRuleSet statsPurgeRules;
public StatsPurge() {
aggregatePurgeRules = readPurgeRules("aggregatePurgeRules.xml");
statsPurgeRules = readPurgeRules("statsPurgeRules.xml");
try {
archiver = new Archiver();
purgeStats();
} catch (JAXBException e) {
statusHandler
.error("Error starting up archiver. Aggregates will not be archived. ",
e);
} catch (DataAccessLayerException e) {
statusHandler
.error("Error purging stats on start up. Stats will not be purged. ",
e);
}
}
/**
* Reads the purge files.
*/
private PurgeRuleSet readPurgeRules(String xml) {
PurgeRuleSet purgeRules = null;
try {
File file = PathManagerFactory.getPathManager().getStaticFile(
"purge/" + xml);
if (file != null) {
try {
purgeRules = (PurgeRuleSet) SerializationUtil
.jaxbUnmarshalFromXmlFile(file);
} catch (SerializationException e) {
statusHandler.error("Error deserializing purge rule " + xml
+ "!");
}
} else {
statusHandler.error(xml
+ " rule not defined!! Data will not be purged.");
}
} catch (Exception e) {
statusHandler.error("Error reading purge file " + xml, e);
}
return purgeRules;
}
/**
* Purges records from the stats table if they are older than the expiration
* time.
*/
private void purgeStats() throws DataAccessLayerException {
if (statsPurgeRules != null) {
Calendar expiration = Calendar.getInstance(TimeZone
.getTimeZone("GMT"));
DatabaseQuery deleteStmt = new DatabaseQuery(StatsRecord.class);
for (PurgeRule rule : statsPurgeRules.getRules()) {
if (rule.isPeriodSpecified()) {
long ms = rule.getPeriodInMillis();
int minutes = new Long(ms / (1000 * 60)).intValue();
expiration.add(Calendar.MINUTE, -minutes);
deleteStmt.addQueryParam("date", expiration,
QueryOperand.LESSTHAN);
statsRecordDao.deleteByCriteria(deleteStmt);
}
}
}
}
/**
* Purges records from the aggregate table and writes them to disk.
*/
public void purgeAggregates() throws JAXBException,
DataAccessLayerException {
if (aggregatePurgeRules != null) {
Calendar expiration = Calendar.getInstance(TimeZone
.getTimeZone("GMT"));
DatabaseQuery query = new DatabaseQuery(AggregateRecord.class);
for (PurgeRule rule : aggregatePurgeRules.getRules()) {
if (rule.isPeriodSpecified()) {
long ms = rule.getPeriodInMillis();
int minutes = new Long(ms / (1000 * 60)).intValue();
expiration.add(Calendar.MINUTE, -minutes);
query.addQueryParam("endDate", expiration,
QueryOperand.LESSTHAN);
List<?> objects = aggregateRecordDao.queryByCriteria(query);
if (!objects.isEmpty()) {
AggregateRecord[] aggregateRecords = new AggregateRecord[objects
.size()];
for (int i = 0; i < aggregateRecords.length; i++) {
aggregateRecords[i] = (AggregateRecord) objects
.get(i);
}
archiver.writeToDisk(aggregateRecords);
aggregateRecordDao.deleteAll(objects);
}
}
}
}
}
}

View file

@ -0,0 +1,57 @@
package com.raytheon.uf.edex.stats.dao;
import java.util.Calendar;
import java.util.List;
import com.raytheon.uf.common.dataquery.db.QueryParam.QueryOperand;
import com.raytheon.uf.common.stats.StatsRecord;
import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.edex.database.DataAccessLayerException;
import com.raytheon.uf.edex.database.dao.CoreDao;
import com.raytheon.uf.edex.database.dao.DaoConfig;
import com.raytheon.uf.edex.database.query.DatabaseQuery;
public class StatsDao extends CoreDao {
private static final transient IUFStatusHandler statusHandler = UFStatus
.getHandler(StatsDao.class);
/**
* Creates a new data access object
*/
public StatsDao() {
super(DaoConfig.forClass("metadata", StatsRecord.class));
}
/**
* Retrieves stat records that has a date before the limit.
*
* @param limit
* @param eventType
* @return an array of stat records. If an error occurs, then an array of
* size 0 will be returned.
* @throws DataAccessLayerException
*/
public StatsRecord[] retrieveRecords(Calendar limit, String eventType) {
DatabaseQuery query = new DatabaseQuery(StatsRecord.class);
query.addQueryParam("eventType", eventType, QueryOperand.EQUALS);
query.addQueryParam("date", limit, QueryOperand.LESSTHAN);
query.setMaxResults(1000);
// TODO Need to make StatsDao to keep track to determine next 1000
// results.
StatsRecord[] records = null;
try {
List<?> objects = queryByCriteria(query);
records = new StatsRecord[objects.size()];
for (int i = 0; i < records.length; i++) {
records[i] = (StatsRecord) objects.get(i);
}
} catch (DataAccessLayerException e) {
records = new StatsRecord[0];
statusHandler.error("Error querying the stats table", e);
}
return records;
}
}

View file

@ -0,0 +1,98 @@
/**
* 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.edex.stats.handler;
import java.util.List;
import com.raytheon.uf.common.dataquery.db.QueryParam.QueryOperand;
import com.raytheon.uf.common.serialization.comm.IRequestHandler;
import com.raytheon.uf.common.stats.AggregateRecord;
import com.raytheon.uf.common.stats.AggregatedStatsRequest;
import com.raytheon.uf.common.stats.AggregatedStatsResponse;
import com.raytheon.uf.edex.database.dao.CoreDao;
import com.raytheon.uf.edex.database.dao.DaoConfig;
import com.raytheon.uf.edex.database.query.DatabaseQuery;
/**
* Handles an AggregateStatsRequest and queries the metadata.aggregate table and
* return the results in an AggregateStatsResponse
*
* * <pre>
*
* SOFTWARE HISTORY
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Aug 21, 2012 jsanchez Initial creation.
*
* </pre>
*
* @author jsanchez
*
*/
public class AggregatedStatsHandler implements
IRequestHandler<AggregatedStatsRequest> {
private CoreDao dao = new CoreDao(DaoConfig.forClass("metadata",
AggregateRecord.class));
@Override
public AggregatedStatsResponse handleRequest(AggregatedStatsRequest request)
throws Exception {
DatabaseQuery query = new DatabaseQuery(AggregateRecord.class.getName());
// TODO Add a time range implementation
if (request.getEventType() != null) {
query.addQueryParam("eventType", request.getEventType(),
QueryOperand.EQUALS);
}
if (request.getGrouping() != null) {
StringBuffer grouping = new StringBuffer();
for (String group : request.getGrouping()) {
if (grouping.length() > 0) {
grouping.append("-");
}
grouping.append(group);
}
query.addQueryParam("grouping", grouping, QueryOperand.EQUALS);
}
if (request.getField() != null) {
query.addQueryParam("field", request.getField(),
QueryOperand.EQUALS);
}
List<?> results = dao.queryByCriteria(query);
AggregateRecord[] records = new AggregateRecord[results.size()];
for (int i = 0; i < results.size(); i++) {
if (results.get(i) instanceof AggregateRecord) {
records[i] = (AggregateRecord) results.get(i);
}
}
AggregatedStatsResponse response = new AggregatedStatsResponse(
request.getTimeRange(), request.getEventType(),
request.getGrouping(), request.getField());
response.setRecords(records);
return response;
}
}

View file

@ -0,0 +1,95 @@
/**
* 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.edex.stats.handler;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import com.google.common.eventbus.AllowConcurrentEvents;
import com.google.common.eventbus.Subscribe;
import com.raytheon.uf.common.event.Event;
import com.raytheon.uf.common.serialization.SerializationException;
import com.raytheon.uf.common.serialization.SerializationUtil;
import com.raytheon.uf.common.stats.StatsRecord;
import com.raytheon.uf.edex.database.dao.CoreDao;
import com.raytheon.uf.edex.database.dao.DaoConfig;
import com.raytheon.uf.edex.event.EventBus;
import com.raytheon.uf.edex.stats.xml.StatsConfig;
/**
* Subscribes to the event bus and stores them in the appropriate stats table
*
*
* <pre>
*
* SOFTWARE HISTORY
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Aug 21, 2012 jsanchez Removed instance variable of event bus.
*
* </pre>
*
* @author jsanchez
*
*/
public class StatsHandler {
private CoreDao dao = new CoreDao(DaoConfig.forClass("metadata",
StatsRecord.class));
// TODO Make unmodifiable
private static Set<String> validEventTypes = new HashSet<String>();
/**
* Registers StatsHandler with the event bus
*/
public StatsHandler() {
EventBus.getInstance().register(this);
}
@Subscribe
@AllowConcurrentEvents
public void eventListener(Event event) {
String clazz = String.valueOf(event.getClass().getName());
if (validEventTypes.contains(clazz)) {
try {
byte[] bytes = SerializationUtil.transformToThrift(event);
StatsRecord record = new StatsRecord();
record.setDate(event.getDate());
record.setEventType(clazz);
record.setEvent(bytes);
dao.persist(record);
} catch (SerializationException e) {
e.printStackTrace();
}
}
}
public static void setValidEventTypes(List<StatsConfig> configurations) {
validEventTypes = new HashSet<String>();
for (StatsConfig config : configurations) {
validEventTypes.add(config.getEventType());
}
}
}

View file

@ -0,0 +1,260 @@
/**
* 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.edex.stats.util;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import com.raytheon.uf.common.localization.IPathManager;
import com.raytheon.uf.common.localization.LocalizationContext;
import com.raytheon.uf.common.localization.LocalizationContext.LocalizationLevel;
import com.raytheon.uf.common.localization.LocalizationContext.LocalizationType;
import com.raytheon.uf.common.localization.LocalizationFile;
import com.raytheon.uf.common.localization.PathManagerFactory;
import com.raytheon.uf.common.stats.AggregateRecord;
import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.time.TimeRange;
import com.raytheon.uf.edex.stats.xml.Aggregate;
import com.raytheon.uf.edex.stats.xml.GroupBy;
import com.raytheon.uf.edex.stats.xml.Item;
import com.raytheon.uf.edex.stats.xml.Statistics;
/**
* Archives the data in the aggregate_bucket table to an xml file.
*
* <pre>
*
* SOFTWARE HISTORY
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Aug 21, 2012 jsanchez Initial creation.
*
* </pre>
*
* @author jsanchez
*
*/
public class Archiver {
private static final transient IUFStatusHandler statusHandler = UFStatus
.getHandler(Archiver.class);
private class StatisticsKey {
public String eventType;
public String grouping;
public TimeRange timeRange;
@Override
public boolean equals(Object o) {
if (o != null && o instanceof StatisticsKey) {
StatisticsKey other = (StatisticsKey) o;
return (this.eventType.equals(other.eventType)
&& this.timeRange.getStart().equals(
other.timeRange.getStart()) && this.timeRange
.getEnd().equals(other.timeRange.getEnd()));
}
return false;
}
@Override
public int hashCode() {
return 1;
}
}
/** Marshaller object */
private Marshaller marshaller;
/** JAXB context */
private JAXBContext jax;
private IPathManager pm = PathManagerFactory.getPathManager();
private LocalizationContext context = pm.getContext(
LocalizationType.COMMON_STATIC, LocalizationLevel.SITE);
private SimpleDateFormat dateFormatter = new SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss");
private SimpleDateFormat fileDateFormatter = new SimpleDateFormat(
"yyyyMMdd_HHmm");
public Archiver() throws JAXBException {
jax = JAXBContext.newInstance(new Class[] { Statistics.class });
this.marshaller = jax.createMarshaller();
}
/**
* Writes the statistics xml to disk.
*
* @param statistics
* @throws JAXBException
*/
public void writeToDisk(String filename, Statistics statistics)
throws JAXBException {
LocalizationFile siteLocalization = pm.getLocalizationFile(context,
filename);
marshaller.marshal(statistics, siteLocalization.getFile());
}
/**
* Writes the aggregate records to disk.
*
* @param aggregateRecords
* @throws JAXBException
*/
public void writeToDisk(AggregateRecord[] aggregateRecords) {
Map<StatisticsKey, List<AggregateRecord>> statisticsMap = new HashMap<StatisticsKey, List<AggregateRecord>>();
for (AggregateRecord record : aggregateRecords) {
StatisticsKey key = new StatisticsKey();
key.eventType = record.getEventType();
key.grouping = record.getGrouping();
key.timeRange = new TimeRange(record.getStartDate(),
record.getEndDate());
List<AggregateRecord> aggregateRecordList = statisticsMap.get(key);
if (aggregateRecordList == null) {
aggregateRecordList = new ArrayList<AggregateRecord>();
statisticsMap.put(key, aggregateRecordList);
}
aggregateRecordList.add(record);
}
for (StatisticsKey key : statisticsMap.keySet()) {
Statistics statistics = new Statistics();
statistics.setEventType(key.eventType);
statistics.setStart(dateFormatter.format(key.timeRange.getStart()));
statistics.setEnd(dateFormatter.format(key.timeRange.getEnd()));
statistics.setGroupBy(createGroupBy(key.grouping));
statistics.setAggregates(createAggregates(statisticsMap.get(key)));
String filename = createFilename(key.timeRange, statistics);
try {
writeToDisk(filename, statistics);
} catch (JAXBException e) {
statusHandler.error("Unable to write statistics file "
+ filename, e);
}
}
}
/**
* Creates a filename in the format
* /stats/aggregates/groupBy{0}/groupby{1}...
* /group{n}/eventType.start-end.dat
*
* @param items
* @return
*/
private String createFilename(TimeRange tr, Statistics statistics) {
StringBuffer sb = new StringBuffer("stats/aggregates");
for (Item item : statistics.getGroupBy().getAttributes()) {
sb.append("/" + item.getResult());
}
sb.append("/" + statistics.getEventType() + "."
+ fileDateFormatter.format(tr.getStart()) + "-"
+ fileDateFormatter.format(tr.getEnd()) + ".dat");
return sb.toString();
}
/**
* Transforms the grouping string from the record into a GroupBy object.
*
* @param recordGroupBy
* @return
*/
private GroupBy createGroupBy(String recordGroupBy) {
GroupBy groupBy = new GroupBy();
String[] groups = recordGroupBy.split("-");
Item[] attributes = new Item[groups.length];
for (int i = 0; i < groups.length; i++) {
String[] g = groups[i].split(":");
String name = g[0];
String result = g[1];
Item item = new Item();
item.setName(name);
item.setResult(result);
attributes[i] = item;
}
groupBy.setAttributes(attributes);
return groupBy;
}
/**
* Transforms the records into Aggregate objects
*
* @param aggregateRecordList
* @return
*/
private Aggregate[] createAggregates(
List<AggregateRecord> aggregateRecordList) {
Aggregate[] aggregates = new Aggregate[aggregateRecordList.size()];
for (int i = 0; i < aggregates.length; i++) {
AggregateRecord record = aggregateRecordList.get(i);
Aggregate aggregate = new Aggregate();
aggregate.setField(record.getField());
Item sumItem = new Item();
sumItem.setName("sum");
sumItem.setResult(String.valueOf(record.getSum()));
Item minItem = new Item();
minItem.setName("min");
minItem.setResult(String.valueOf(record.getMin()));
Item maxItem = new Item();
sumItem.setName("max");
sumItem.setResult(String.valueOf(record.getMax()));
Item countItem = new Item();
minItem.setName("count");
minItem.setResult(String.valueOf(record.getCount()));
aggregate.setFunctions(new Item[] { sumItem, minItem, maxItem,
countItem });
aggregates[i] = aggregate;
}
return aggregates;
}
}

View file

@ -0,0 +1,158 @@
/**
* 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.edex.stats.util;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import com.raytheon.uf.common.localization.IPathManager;
import com.raytheon.uf.common.localization.LocalizationContext;
import com.raytheon.uf.common.localization.LocalizationContext.LocalizationType;
import com.raytheon.uf.common.localization.LocalizationFile;
import com.raytheon.uf.common.localization.PathManagerFactory;
import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.edex.stats.xml.Aggregate;
import com.raytheon.uf.edex.stats.xml.Statistics;
import com.raytheon.uf.edex.stats.xml.StatsConfig;
/**
* Loads statsConfig files from localization.
*
* <pre>
*
* SOFTWARE HISTORY
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Aug 21, 2012 jsanchez Updated error handling and validated config files.
*
* </pre>
*
* @author jsanchez
*
*/
public class ConfigLoader {
private static final transient IUFStatusHandler statusHandler = UFStatus
.getHandler(ConfigLoader.class);
private JAXBContext jax;
/** Unmarshaller object */
private Unmarshaller unmarshaller;
/** Marshaller object */
private Marshaller marshaller;
private IPathManager pm = PathManagerFactory.getPathManager();
private List<StatsConfig> configurations;
private final String STATS_DIR = "stats";
/**
* Constructor. Performs an initial statsCon
*/
public ConfigLoader() throws JAXBException {
jax = JAXBContext.newInstance(new Class[] { StatsConfig.class,
Statistics.class });
unmarshaller = jax.createUnmarshaller();
this.marshaller = jax.createMarshaller();
this.marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
this.configurations = new ArrayList<StatsConfig>();
}
/**
* Loads the statsConfig files in the STATS_DIR directory.
*/
public void load() throws Exception {
LocalizationContext[] searchContext = pm
.getLocalSearchHierarchy(LocalizationType.EDEX_STATIC);
LocalizationFile[] localizationFiles = null;
for (LocalizationContext ctx : searchContext) {
localizationFiles = pm.listFiles(ctx, STATS_DIR, null, false, true);
if (localizationFiles != null && localizationFiles.length > 0) {
break;
}
}
if (localizationFiles != null && localizationFiles.length > 0) {
configurations.clear();
for (LocalizationFile localizationFile : localizationFiles) {
if (localizationFile.getFile() != null
&& localizationFile.getFile().exists()) {
StatsConfig config = (StatsConfig) unmarshaller
.unmarshal(localizationFile.getFile());
config = validateAggregates(config);
configurations.add(config);
}
}
}
}
/**
* Removes the aggregate if its not a numerical parameter.
*
* @param config
*/
private StatsConfig validateAggregates(StatsConfig config)
throws ClassNotFoundException {
Class<?> clazz = Class.forName(config.getEventType());
List<Aggregate> aggregates = new ArrayList<Aggregate>();
for (Aggregate aggregate : config.getAggregates()) {
String aggregateField = aggregate.getField();
try {
Field field = clazz.getDeclaredField(aggregateField);
if (!field.getType().isPrimitive()) {
statusHandler
.info("'"
+ aggregateField
+ "' not a primitive type. Aggregate being removed. ");
}
aggregates.add(aggregate);
} catch (NoSuchFieldException e) {
statusHandler.info("'" + aggregateField
+ "' not a valid field. Aggregate being removed. ");
}
}
config.setAggregates(aggregates.toArray(new Aggregate[aggregates.size()]));
return config;
}
/**
* Returns a list of all statsConfig files.
*
* @return
*/
public List<StatsConfig> getConfigurations() {
return configurations;
}
}

View file

@ -0,0 +1,74 @@
/**
* 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.edex.stats.xml;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import com.raytheon.uf.common.serialization.annotations.DynamicSerialize;
import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement;
/**
*
*
* <pre>
*
* SOFTWARE HISTORY
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Aug 21, 2012 jsanchez Made serializable.
*
* </pre>
*
* @author jsanchez
*
*/
@DynamicSerialize
@XmlAccessorType(XmlAccessType.NONE)
public class Aggregate {
/** the field to perform the function on. */
@XmlAttribute
@DynamicSerializeElement
private String field;
/** the name of the statistic function */
@XmlElement(name = "function")
@DynamicSerializeElement
private Item[] functions;
public String getField() {
return field;
}
public void setField(String field) {
this.field = field;
}
public Item[] getFunctions() {
return functions;
}
public void setFunctions(Item[] functions) {
this.functions = functions;
}
}

View file

@ -0,0 +1,59 @@
/**
* 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.edex.stats.xml;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import com.raytheon.uf.common.serialization.annotations.DynamicSerialize;
import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement;
/**
*
*
* <pre>
*
* SOFTWARE HISTORY
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Aug 21, 2012 jsanchez Made serializable.
*
* </pre>
*
* @author jsanchez
*
*/
@DynamicSerialize
@XmlAccessorType(XmlAccessType.NONE)
public class GroupBy {
@XmlElement(name = "attribute")
@DynamicSerializeElement
private Item[] attributes;
public Item[] getAttributes() {
return attributes;
}
public void setAttributes(Item[] attributes) {
this.attributes = attributes;
}
}

View file

@ -0,0 +1,71 @@
/**
* 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.edex.stats.xml;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import com.raytheon.uf.common.serialization.annotations.DynamicSerialize;
import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement;
/**
*
*
* <pre>
*
* SOFTWARE HISTORY
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Aug 21, 2012 jsanchez Made serializable.
*
* </pre>
*
* @author jsanchez
*
*/
@DynamicSerialize
@XmlAccessorType(XmlAccessType.NONE)
public class Item {
@XmlAttribute
@DynamicSerializeElement
private String name;
@XmlAttribute
@DynamicSerializeElement
private String result;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getResult() {
return result;
}
public void setResult(String result) {
this.result = result;
}
}

View file

@ -0,0 +1,119 @@
/**
* 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.edex.stats.xml;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import com.raytheon.uf.common.serialization.ISerializableObject;
/**
*
*
* <pre>
*
* SOFTWARE HISTORY
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Aug 21, 2012 jsanchez Made serializable.
*
* </pre>
*
* @author jsanchez
*
*/
@XmlRootElement(name = "statistics")
@XmlAccessorType(XmlAccessType.NONE)
public class Statistics implements ISerializableObject {
/** the start time of the period YYYY-MM-DD HH:MM:SS */
@XmlAttribute
private String start;
/** the end time of the period YYYY-MM-DD HH:MM:SS */
@XmlAttribute
private String end;
/** the event type that will be monitored */
@XmlElement(name = "eventType")
private String eventType;
@XmlElement(name = "groupBy")
private GroupBy groupBy;
@XmlElement(name = "aggregate")
private Aggregate[] aggregates;
/**
* default constructor
*/
public Statistics() {
}
public Statistics(StatsConfig config) {
this.eventType = config.getEventType();
this.groupBy = config.getGroupBy();
this.aggregates = config.getAggregates();
}
public String getEventType() {
return eventType;
}
public void setEventType(String eventType) {
this.eventType = eventType;
}
public GroupBy getGroupBy() {
return groupBy;
}
public void setGroupBy(GroupBy groupBy) {
this.groupBy = groupBy;
}
public Aggregate[] getAggregates() {
return aggregates;
}
public void setAggregates(Aggregate[] aggregates) {
this.aggregates = aggregates;
}
public String getStart() {
return start;
}
public void setStart(String start) {
this.start = start;
}
public String getEnd() {
return end;
}
public void setEnd(String end) {
this.end = end;
}
}

View file

@ -0,0 +1,85 @@
/**
* 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.edex.stats.xml;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import com.raytheon.uf.common.serialization.ISerializableObject;
import com.raytheon.uf.common.serialization.annotations.DynamicSerialize;
import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement;
/**
* The config file that will be used to set the specific parameters that
* statistic files can be aggregated against.
*
* SOFTWARE HISTORY
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Aug 21, 2012 jsanchez Made serializable.
*
* @author jsanchez
*
*/
@DynamicSerialize
@XmlRootElement(name = "statsConfig")
@XmlAccessorType(XmlAccessType.NONE)
public class StatsConfig implements ISerializableObject {
/** the event type that will be monitored */
@XmlElement(name = "eventType")
@DynamicSerializeElement
private String eventType;
@XmlElement(name = "groupBy")
@DynamicSerializeElement
private GroupBy groupBy;
@XmlElement(name = "aggregate")
@DynamicSerializeElement
private Aggregate[] aggregates;
public String getEventType() {
return eventType;
}
public void setEventType(String eventType) {
this.eventType = eventType;
}
public GroupBy getGroupBy() {
return groupBy;
}
public void setGroupBy(GroupBy groupBy) {
this.groupBy = groupBy;
}
public Aggregate[] getAggregates() {
return aggregates;
}
public void setAggregates(Aggregate[] aggregates) {
this.aggregates = aggregates;
}
}

View file

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<purgeRuleSet xmlns:ns2="group">
<rule>
<id>
<pluginName>aggregate</pluginName>
<key>default</key>
</id>
<period>30-00:00:00</period>
</rule>
</purgeRuleSet>

View file

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<purgeRuleSet xmlns:ns2="group">
<rule>
<id>
<pluginName>stats</pluginName>
<key>default</key>
</id>
<period>00-24:00:00</period>
</rule>
</purgeRuleSet>

View file

@ -0,0 +1,10 @@
<statsConfig>
<!-- Event Type should be fully qualified name of stat event -->
<eventType>com.raytheon.uf.common.event.ProcessEvent</eventType>
<groupBy>
<attribute name="plugin"/>
<attribute name="owner"/>
</groupBy>
<aggregate field="numFailed"/>
<aggregate field="numComplete"/>
</statsConfig>