modules/core/domain/src/main/java/org/rhq/core/domain/alert/AlertCondition.java | 8 modules/core/domain/src/main/java/org/rhq/core/domain/alert/AlertConditionCategory.java | 5 modules/core/domain/src/main/java/org/rhq/core/domain/alert/AlertConditionOperator.java | 88 ++++ modules/core/domain/src/main/java/org/rhq/core/domain/alert/composite/AlertConditionAvailabilityCategoryComposite.java | 48 +- modules/core/domain/src/main/java/org/rhq/core/domain/measurement/AvailabilityType.java | 4 modules/core/domain/src/main/java/org/rhq/core/domain/measurement/ResourceAvailability.java | 8 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/AlertFormatUtility.java | 41 + modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/NewConditionEditor.java | 208 ++++++---- modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/startup/StartupServlet.java | 8 modules/enterprise/server/ear/pom.xml | 10 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertConditionManagerBean.java | 11 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertManagerBean.java | 54 ++ modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/AlertConditionCacheManagerBean.java | 7 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/AlertConditionCacheManagerLocal.java | 9 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/internal/AbstractConditionCache.java | 10 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/internal/AgentConditionCache.java | 6 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/internal/AlertConditionCacheCoordinator.java | 17 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/internal/AlertConditionCacheUtils.java | 111 +++-- modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/internal/GlobalConditionCache.java | 104 ++++- modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/mbean/AlertConditionCacheMonitor.java | 25 + modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/mbean/AlertConditionCacheMonitorMBean.java | 10 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/model/AbstractCacheElement.java | 2 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/model/AbstractEnumCacheElement.java | 2 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/model/AlertConditionOperator.java | 78 --- modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/model/AvailabilityCacheElement.java | 57 ++ modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/model/AvailabilityDurationCacheElement.java | 170 ++++++++ modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/model/AvailabilityDurationComposite.java | 66 +++ modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/model/CallTimeDataCacheElement.java | 1 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/model/DriftCacheElement.java | 1 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/model/EventCacheElement.java | 1 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/model/MeasurementBaselineCacheElement.java | 2 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/model/MeasurementNumericCacheElement.java | 2 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/model/MeasurementRangeNumericCacheElement.java | 2 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/model/MeasurementTraitCacheElement.java | 2 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/model/NumericDoubleCacheElement.java | 2 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/model/ResourceConfigurationCacheElement.java | 1 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/model/ResourceOperationCacheElement.java | 1 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/model/StringCacheElement.java | 2 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/AvailabilityManagerBean.java | 6 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/scheduler/EnhancedScheduler.java | 27 + modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/scheduler/EnhancedSchedulerImpl.java | 44 +- modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/scheduler/SchedulerBean.java | 13 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/scheduler/jobs/AlertAvailabilityDurationJob.java | 88 ++++ modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/alert/engine/model/MeasurementRangeNumericCacheElementTest.java | 2 44 files changed, 1073 insertions(+), 291 deletions(-)
New commits: commit e3d4a8b0347708511feab76a8650318ebbeb8548 Author: Jay Shaughnessy jshaughn@redhat.com Date: Thu Feb 9 11:28:59 2012 -0500
Removing unused named query.
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/measurement/ResourceAvailability.java b/modules/core/domain/src/main/java/org/rhq/core/domain/measurement/ResourceAvailability.java index 263dfa2..89d689f 100644 --- a/modules/core/domain/src/main/java/org/rhq/core/domain/measurement/ResourceAvailability.java +++ b/modules/core/domain/src/main/java/org/rhq/core/domain/measurement/ResourceAvailability.java @@ -65,13 +65,6 @@ import org.rhq.core.domain.resource.Resource; + " FROM Resource res " // + " WHERE res.agent.id = :agentId " // + " AND res.parentResource IS NOT NULL )"), - @NamedQuery(name = ResourceAvailability.INSERT_BY_RESOURCE_IDS, query = "" // - + " INSERT INTO ResourceAvailability ( resourceId ) " // - + " SELECT res.id " // - + " FROM Resource res " // - + " LEFT JOIN res.currentAvailability avail " // - + " WHERE res.id IN ( :resourceIds ) " // - + " AND avail IS NULL "), /* * Platform plugins always return up for availability. Platforms are * only down if the check-suspect-agent's backfiller sets them down. @@ -96,7 +89,6 @@ public class ResourceAvailability implements Serializable { public static final String QUERY_FIND_BY_RESOURCE_ID = "ResourceAvailability.findByResourceId"; public static final String UPDATE_CHILD_BY_AGENT_ID = "ResourceAvailability.updateChildByAgentId"; public static final String UPDATE_PLATFORM_BY_AGENT_ID = "ResourceAvailability.updatePlatformByAgentId"; - public static final String INSERT_BY_RESOURCE_IDS = "ResourceAvailability.insertByResourceIds"; public static final String QUERY_IS_AGENT_BACKFILLED = "ResourceAvailability.isAgentBackfilled";
@SuppressWarnings("unused")
commit 6e3e98398e8fbb8367a971434ab81231a29160e7 Author: Jay Shaughnessy jshaughn@redhat.com Date: Thu Feb 9 11:28:30 2012 -0500
[Bug 789039 - unwanted jars being pulled into rhq ear lib directory] Changes to the rhq-server-client-api deps caused unwanted libs to be pulled into rhq.ear.
Added dep exclusions in the ear pom to keep out the unwanted transitive deps.
diff --git a/modules/enterprise/server/ear/pom.xml b/modules/enterprise/server/ear/pom.xml index 941c88a..429f446 100644 --- a/modules/enterprise/server/ear/pom.xml +++ b/modules/enterprise/server/ear/pom.xml @@ -100,6 +100,16 @@ <groupId>org.rhq</groupId> <artifactId>rhq-server-client-api</artifactId> <version>${project.version}</version> + <exclusions> + <exclusion> + <groupId>org.rhq</groupId> + <artifactId>rhq-container-lib</artifactId> + </exclusion> + <exclusion> + <groupId>org.rhq</groupId> + <artifactId>rhq-enterprise-server</artifactId> + </exclusion> + </exclusions> </dependency>
<!-- 3rd Party Deps -->
commit 73e27be61bea1cb76a5ffa9b76c9410be3783dcd Author: Jay Shaughnessy jshaughn@redhat.com Date: Thu Feb 9 11:19:08 2012 -0500
Add Availability Duration Alerting This is a new alert category. The idea of adding dampening support (to the inherently stateless) avail checking seemed unintuitive and also very complex. And actually, this isn't really dampening, which deals with repeated condition evaluation. This is more a deferred condition evaluation. So, instead, I basically added a new type of alerting, instead of Availability Change alerts, these are Availability Duration alerts. Semantically it means fire an alert if the avail changes to A *and* stays at A for M minutes. - Stopped trying to force fit avail conditions into CHANGE_TO/FROM operators. Adding dedicated AlertConditionOperators provides more flexibility and removes a few hacks in the avail alerting code. - Added DISABLED avail type - Worked in alerting for UNKNOWN, DISABLED, and added NOT_UP for convenience - Added necessary gui hooks (still needs I18N) - Added new Triggered job (AlertAvailabilityDurationJob) for scheduling the deferred avail type checking. - A lot of the touched files result from moving AlertConditionOperator from server jar to domain jar. This made the operator values available to coregui for some conditional formatting. Most *CacheElement file changes were due to this refactor. TODO: - I18N
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/alert/AlertCondition.java b/modules/core/domain/src/main/java/org/rhq/core/domain/alert/AlertCondition.java index fb98c5b..064400c 100644 --- a/modules/core/domain/src/main/java/org/rhq/core/domain/alert/AlertCondition.java +++ b/modules/core/domain/src/main/java/org/rhq/core/domain/alert/AlertCondition.java @@ -47,7 +47,6 @@ import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlTransient;
-import org.rhq.core.domain.measurement.AvailabilityType; import org.rhq.core.domain.measurement.MeasurementDefinition; import org.rhq.core.domain.operation.OperationRequestStatus;
@@ -57,7 +56,7 @@ import org.rhq.core.domain.operation.OperationRequestStatus; * @author Joseph Marques */ @Entity -@NamedQueries( { +@NamedQueries({ @NamedQuery(name = "AlertCondition.findByTriggerId", query = "SELECT a FROM AlertCondition AS a WHERE a.triggerId = :tid"), @NamedQuery(name = "AlertCondition.findAll", query = "SELECT a FROM AlertCondition AS a"), @NamedQuery(name = AlertCondition.QUERY_DELETE_BY_RESOURCES, query = "DELETE FROM AlertCondition ac WHERE ac.alertDefinition IN ( SELECT ad FROM AlertDefinition ad WHERE ad.resource.id IN ( :resourceIds ) )"), @@ -167,7 +166,7 @@ import org.rhq.core.domain.operation.OperationRequestStatus; + " AND ( res.agent.id = :agentId OR :agentId IS NULL ) " // + " AND ad.enabled = TRUE " // + " AND ad.deleted = FALSE " // - + " AND ac.category = 'AVAILABILITY' " // + + " AND ac.category = :category " // + "ORDER BY ac.id"), // @NamedQuery(name = AlertCondition.QUERY_BY_CATEGORY_CONTROL, query = "" // + " SELECT new org.rhq.core.domain.alert.composite.AlertConditionControlCategoryComposite " // @@ -489,7 +488,8 @@ public class AlertCondition implements Serializable {
/** * The option string is optional and its semantics differ based on the category of this condition: - * AVAILABILITY: the {@link AvailabilityType} to trigger off of (DOWN or UP) + * AVAILABILITY: n/a + * AVAIL_DURATION: the duration, in minutes * THRESHOLD: for calltime metric conditions, one of "MIN, "MAX", "AVG" - all others are n/a * BASELINE: one of "min", "max" or "mean" - indicates what the threshold is compared to (min/max/avg baseline value) * CHANGE: for calltime metric conditions, one of "MIN, "MAX", "AVG" - all others are n/a diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/alert/AlertConditionCategory.java b/modules/core/domain/src/main/java/org/rhq/core/domain/alert/AlertConditionCategory.java index bb7a563..59d2c2b 100644 --- a/modules/core/domain/src/main/java/org/rhq/core/domain/alert/AlertConditionCategory.java +++ b/modules/core/domain/src/main/java/org/rhq/core/domain/alert/AlertConditionCategory.java @@ -23,7 +23,7 @@ package org.rhq.core.domain.alert;
public enum AlertConditionCategory { - AVAILABILITY("Resource Availability"), // + AVAILABILITY("Resource Availability"), // i.e. AVAILABILITY_CHANGE THRESHOLD("Measurement Threshold"), // BASELINE("Measurement Baseline"), // CHANGE("Measurement Value Change"), // @@ -33,7 +33,8 @@ public enum AlertConditionCategory { RESOURCE_CONFIG("Resource Configuration Property Value Change"), // EVENT("Log Event"), // DRIFT("Drift Detected"), // - RANGE("Measurement Value Range"); + RANGE("Measurement Value Range"), // + AVAIL_DURATION("Resource Availability for Duration");
/* * legacyOrder exists to support code that still uses the old EventConstants.TYPE_* attributes, which was one-based diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/alert/AlertConditionOperator.java b/modules/core/domain/src/main/java/org/rhq/core/domain/alert/AlertConditionOperator.java new file mode 100644 index 0000000..a9221a6 --- /dev/null +++ b/modules/core/domain/src/main/java/org/rhq/core/domain/alert/AlertConditionOperator.java @@ -0,0 +1,88 @@ +/* + * RHQ Management Platform + * Copyright (C) 2005-2012 Red Hat, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +package org.rhq.core.domain.alert; + +/** + * @author Joseph Marques + * @author Jay Shaughnessy + */ + +public enum AlertConditionOperator { + /* + * absolute value comparison operators + */ + LESS_THAN_OR_EQUAL_TO(Type.STATEFUL), // + LESS_THAN(Type.STATEFUL), // + EQUALS(Type.STATEFUL), // + REGEX(Type.STATELESS), // more flexible form of EQUALS + GREATER_THAN(Type.STATEFUL), // + GREATER_THAN_OR_EQUAL_TO(Type.STATEFUL), // + + /* + * operator based on state deltas + */ + CHANGES(Type.STATELESS), // state value changes in any way + CHANGES_TO(Type.STATELESS), // becomes one specific state value + CHANGES_FROM(Type.STATELESS), // leaves one specific state value + + AVAIL_GOES_DOWN(Type.STATELESS), // avail becomes DOWN from anything else + AVAIL_GOES_DISABLED(Type.STATELESS), // avail becomes DISABLED from anything else + AVAIL_GOES_UNKNOWN(Type.STATELESS), // avail becomes UNKNOWN from anything else + AVAIL_GOES_NOT_UP(Type.STATELESS), // convenience for avail becomes DOWN | DISABLED | UNKNOWN from UP + AVAIL_GOES_UP(Type.STATELESS), // avail becomes UP from anything else + + AVAIL_DURATION_DOWN(Type.STATELESS), // avail DOWN for X minutes + AVAIL_DURATION_NOT_UP(Type.STATELESS); // convenience for avail DOWN | UNKNOWN | DISABLED for X minutes + + private Type defaultType; + + /** + * For the most part, the operator itself denotes whether it makes comparisons against a sliding scale or not. + * However, this doesn't hold in every conceivable scenario. Thus, the defaultType will support 95% of the use + * cases, and the AbstractCacheElement's getOperatorType will have a chance to override this. + */ + AlertConditionOperator(Type defaultType) { + this.defaultType = defaultType; + } + + public Type getDefaultType() { + return defaultType; + } + + public enum Type { + /* + * stateful is used to support a sliding scale of values, usually a number line; once the stateful operator's + * condition threshold is met, stateful cache elements are disabled until the threshold is crossed once again + * into the expected range; + */ + STATEFUL, + + /* + * stateless can be used for anything stateful can, but will never be disabled in the cache; so, if you're + * worried about being able to suppress sliding-scale conditions once a threshold is meet, mark your operator + * as stateful + */ + STATELESS, + + /* + * CacheElement doesn't support the Operator if getOperatorSupportsType(Operator) is overridden to return NONE + */ + NONE; + } +} \ No newline at end of file diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/alert/composite/AlertConditionAvailabilityCategoryComposite.java b/modules/core/domain/src/main/java/org/rhq/core/domain/alert/composite/AlertConditionAvailabilityCategoryComposite.java index be52414..fd4ccb4 100644 --- a/modules/core/domain/src/main/java/org/rhq/core/domain/alert/composite/AlertConditionAvailabilityCategoryComposite.java +++ b/modules/core/domain/src/main/java/org/rhq/core/domain/alert/composite/AlertConditionAvailabilityCategoryComposite.java @@ -1,31 +1,34 @@ - /* - * RHQ Management Platform - * Copyright (C) 2005-2008 Red Hat, Inc. - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License, version 2, as - * published by the Free Software Foundation, and/or the GNU Lesser - * General Public License, version 2.1, also as published by the Free - * Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License and the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License - * and the GNU Lesser General Public License along with this program; - * if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ +/* + * RHQ Management Platform + * Copyright (C) 2005-2008 Red Hat, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2, as + * published by the Free Software Foundation, and/or the GNU Lesser + * General Public License, version 2.1, also as published by the Free + * Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License and the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License + * and the GNU Lesser General Public License along with this program; + * if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ package org.rhq.core.domain.alert.composite;
import org.rhq.core.domain.alert.AlertCondition; import org.rhq.core.domain.measurement.AvailabilityType;
/** + * This composite serves both AVAILABILITY and AVAIL_DURATION alert categories as they both + * require the same information from the composite. + * * @author Joseph Marques */ public class AlertConditionAvailabilityCategoryComposite extends AbstractAlertConditionCategoryComposite { @@ -35,6 +38,7 @@ public class AlertConditionAvailabilityCategoryComposite extends AbstractAlertCo
public AlertConditionAvailabilityCategoryComposite(AlertCondition condition, Integer resourceId, AvailabilityType availabilityType) { + super(condition); this.resourceId = resourceId; this.availabilityType = availabilityType; diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/measurement/AvailabilityType.java b/modules/core/domain/src/main/java/org/rhq/core/domain/measurement/AvailabilityType.java index 667ace5..27abf17 100644 --- a/modules/core/domain/src/main/java/org/rhq/core/domain/measurement/AvailabilityType.java +++ b/modules/core/domain/src/main/java/org/rhq/core/domain/measurement/AvailabilityType.java @@ -36,7 +36,9 @@ public enum AvailabilityType { /** Resource is up */ UP, /** Resource avail can't be determined. Typically meaning the agent is down */ - UNKNOWN; + UNKNOWN, + /** Resource is reporting but administratively disabled. Put another way, it is expectedly down */ + DISABLED;
/** * A Java bean style getter to allow us to access the enum name from JSPs or Facelets (e.g. diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/AlertFormatUtility.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/AlertFormatUtility.java index 4e15bd9..34882fb 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/AlertFormatUtility.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/AlertFormatUtility.java @@ -25,6 +25,7 @@ package org.rhq.enterprise.gui.coregui.client.alert; import org.rhq.core.domain.alert.Alert; import org.rhq.core.domain.alert.AlertCondition; import org.rhq.core.domain.alert.AlertConditionCategory; +import org.rhq.core.domain.alert.AlertConditionOperator; import org.rhq.core.domain.alert.AlertDefinition; import org.rhq.core.domain.measurement.MeasurementUnits; import org.rhq.enterprise.gui.coregui.client.CoreGUI; @@ -50,14 +51,44 @@ public class AlertFormatUtility { AlertConditionCategory category = condition.getCategory(); switch (category) { case AVAILABILITY: { - str.append(MSG.view_alert_common_tab_conditions_type_availability()); + // TODO I18N + str.append("Availability Change To"); str.append(" ["); - if ("up".equalsIgnoreCase(condition.getOption())) { - str.append(MSG.view_alert_common_tab_conditions_type_availability_up()); - } else { - str.append(MSG.view_alert_common_tab_conditions_type_availability_down()); + AlertConditionOperator operator = AlertConditionOperator.valueOf(condition.getName().toUpperCase()); + switch (operator) { + case AVAIL_GOES_DISABLED: + case AVAIL_GOES_DOWN: + case AVAIL_GOES_UNKNOWN: + case AVAIL_GOES_UP: + case AVAIL_GOES_NOT_UP: + str.append(operator); + break; + default: + str.append("*ERROR*"); } str.append("]"); + + break; + } + case AVAIL_DURATION: { + // TODO I18N + str.append("Availability Duration ["); + AlertConditionOperator operator = AlertConditionOperator.valueOf(condition.getName().toUpperCase()); + switch (operator) { + case AVAIL_DURATION_DOWN: + case AVAIL_DURATION_NOT_UP: + str.append(operator); + break; + default: + str.append("*ERROR*"); + } + str.append(" For "); + + String value = condition.getOption(); + String formatted = MeasurementConverterClient.format(value, MeasurementUnits.MINUTES); + str.append(formatted); + str.append("]"); + break; } case THRESHOLD: { diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/NewConditionEditor.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/NewConditionEditor.java index 20b2003..75c05de 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/NewConditionEditor.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/NewConditionEditor.java @@ -47,9 +47,9 @@ import com.smartgwt.client.widgets.form.fields.events.ClickHandler;
import org.rhq.core.domain.alert.AlertCondition; import org.rhq.core.domain.alert.AlertConditionCategory; +import org.rhq.core.domain.alert.AlertConditionOperator; import org.rhq.core.domain.alert.BooleanExpression; import org.rhq.core.domain.event.EventSeverity; -import org.rhq.core.domain.measurement.AvailabilityType; import org.rhq.core.domain.measurement.DataType; import org.rhq.core.domain.measurement.MeasurementDefinition; import org.rhq.core.domain.measurement.MeasurementUnits; @@ -75,6 +75,8 @@ public class NewConditionEditor extends LocatableDynamicForm { private static final String ALERT_CONDITION_CATEGORY_CALLTIME_THRESHOLD = "calltime-threshold";
private static final String AVAILABILITY_ITEMNAME = "availability"; + private static final String AVAILABILITY_DURATION_ITEMNAME = "availabilityDuration"; + private static final String AVAILABILITY_DURATION_VAL_ITEMNAME = "availabilityDurationVal"; private static final String THRESHOLD_METRIC_ITEMNAME = "thresholdMetric"; private static final String THRESHOLD_COMPARATOR_ITEMNAME = "thresholdComparator"; private static final String THRESHOLD_ABSVALUE_ITEMNAME = "metricAbsoluteValue"; @@ -170,46 +172,48 @@ public class NewConditionEditor extends LocatableDynamicForm {
setMargin(20);
- conditionTypeSelectItem = new SelectItem("conditionType", MSG - .view_alert_definition_condition_editor_option_label()); + conditionTypeSelectItem = new SelectItem("conditionType", + MSG.view_alert_definition_condition_editor_option_label()); LinkedHashMap<String, String> condTypes = new LinkedHashMap<String, String>(7); - condTypes.put(AlertConditionCategory.AVAILABILITY.name(), MSG - .view_alert_definition_condition_editor_option_availability()); + condTypes.put(AlertConditionCategory.AVAILABILITY.name(), + MSG.view_alert_definition_condition_editor_option_availability()); + // TODO I18N + condTypes.put(AlertConditionCategory.AVAIL_DURATION.name(), "Availability Duration"); if (supportsMetrics) { - condTypes.put(AlertConditionCategory.THRESHOLD.name(), MSG - .view_alert_definition_condition_editor_option_metric_threshold()); - condTypes.put(AlertConditionCategory.BASELINE.name(), MSG - .view_alert_definition_condition_editor_option_metric_baseline()); - condTypes.put(AlertConditionCategory.CHANGE.name(), MSG - .view_alert_definition_condition_editor_option_metric_change()); - condTypes.put(AlertConditionCategory.RANGE.name(), MSG - .view_alert_definition_condition_editor_option_metric_range()); + condTypes.put(AlertConditionCategory.THRESHOLD.name(), + MSG.view_alert_definition_condition_editor_option_metric_threshold()); + condTypes.put(AlertConditionCategory.BASELINE.name(), + MSG.view_alert_definition_condition_editor_option_metric_baseline()); + condTypes.put(AlertConditionCategory.CHANGE.name(), + MSG.view_alert_definition_condition_editor_option_metric_change()); + condTypes.put(AlertConditionCategory.RANGE.name(), + MSG.view_alert_definition_condition_editor_option_metric_range()); } if (supportsCalltimeMetrics) { - condTypes.put(ALERT_CONDITION_CATEGORY_CALLTIME_THRESHOLD, MSG - .view_alert_definition_condition_editor_option_metric_calltime_threshold()); - condTypes.put(ALERT_CONDITION_CATEGORY_CALLTIME_CHANGE, MSG - .view_alert_definition_condition_editor_option_metric_calltime_change()); + condTypes.put(ALERT_CONDITION_CATEGORY_CALLTIME_THRESHOLD, + MSG.view_alert_definition_condition_editor_option_metric_calltime_threshold()); + condTypes.put(ALERT_CONDITION_CATEGORY_CALLTIME_CHANGE, + MSG.view_alert_definition_condition_editor_option_metric_calltime_change()); } if (supportsTraits) { - condTypes.put(AlertConditionCategory.TRAIT.name(), MSG - .view_alert_definition_condition_editor_option_metric_trait_change()); + condTypes.put(AlertConditionCategory.TRAIT.name(), + MSG.view_alert_definition_condition_editor_option_metric_trait_change()); } if (supportsOperations) { - condTypes.put(AlertConditionCategory.CONTROL.name(), MSG - .view_alert_definition_condition_editor_option_operation()); + condTypes.put(AlertConditionCategory.CONTROL.name(), + MSG.view_alert_definition_condition_editor_option_operation()); } if (supportsResourceConfig) { - condTypes.put(AlertConditionCategory.RESOURCE_CONFIG.name(), MSG - .view_alert_definition_condition_editor_option_resource_configuration()); + condTypes.put(AlertConditionCategory.RESOURCE_CONFIG.name(), + MSG.view_alert_definition_condition_editor_option_resource_configuration()); } if (supportsEvents) { - condTypes.put(AlertConditionCategory.EVENT.name(), MSG - .view_alert_definition_condition_editor_option_event()); + condTypes.put(AlertConditionCategory.EVENT.name(), + MSG.view_alert_definition_condition_editor_option_event()); } if (supportsDrift) { - condTypes.put(AlertConditionCategory.DRIFT.name(), MSG - .view_alert_definition_condition_editor_option_drift()); + condTypes.put(AlertConditionCategory.DRIFT.name(), + MSG.view_alert_definition_condition_editor_option_drift()); } conditionTypeSelectItem.setValueMap(condTypes); conditionTypeSelectItem.setDefaultValue(AlertConditionCategory.AVAILABILITY.name()); @@ -253,6 +257,7 @@ public class NewConditionEditor extends LocatableDynamicForm { formItems.add(conditionTypeSelectItem); formItems.add(spacer1); formItems.addAll(buildAvailabilityChangeFormItems()); + formItems.addAll(buildAvailabilityDurationFormItems()); if (supportsMetrics) { formItems.addAll(buildMetricThresholdFormItems()); formItems.addAll(buildMetricRangeFormItems()); @@ -329,10 +334,19 @@ public class NewConditionEditor extends LocatableDynamicForm {
switch (category) { case AVAILABILITY: { - newCondition.setName(null); + newCondition.setName(getValueAsString(AVAILABILITY_ITEMNAME)); + newCondition.setComparator(null); + newCondition.setThreshold(null); + newCondition.setOption(null); + newCondition.setMeasurementDefinition(null); + break; + } + + case AVAIL_DURATION: { + newCondition.setName(getValueAsString(AVAILABILITY_DURATION_ITEMNAME)); newCondition.setComparator(null); newCondition.setThreshold(null); - newCondition.setOption(getValueAsString(AVAILABILITY_ITEMNAME)); + newCondition.setOption(getValueAsString(AVAILABILITY_DURATION_VAL_ITEMNAME)); newCondition.setMeasurementDefinition(null); break; } @@ -483,8 +497,8 @@ public class NewConditionEditor extends LocatableDynamicForm { if (metricDropDownMenu != null) { formItems.add(metricDropDownMenu); formItems.add(buildComparatorDropDownMenu(THRESHOLD_COMPARATOR_ITEMNAME, ifFunc)); - TextItem absoluteValue = new TextItem(THRESHOLD_ABSVALUE_ITEMNAME, MSG - .view_alert_definition_condition_editor_metric_threshold_value()); + TextItem absoluteValue = new TextItem(THRESHOLD_ABSVALUE_ITEMNAME, + MSG.view_alert_definition_condition_editor_metric_threshold_value()); absoluteValue.setWrapTitle(false); absoluteValue.setRequired(true); absoluteValue.setTooltip(MSG.view_alert_definition_condition_editor_metric_threshold_value_tooltip()); @@ -516,8 +530,8 @@ public class NewConditionEditor extends LocatableDynamicForm { if (metricDropDownMenu != null) { formItems.add(metricDropDownMenu); formItems.add(buildRangeComparatorDropDownMenu(RANGE_COMPARATOR_ITEMNAME, ifFunc)); - TextItem absoluteLowValue = new TextItem(RANGE_LO_ABSVALUE_ITEMNAME, MSG - .view_alert_definition_condition_editor_metric_range_lovalue()); + TextItem absoluteLowValue = new TextItem(RANGE_LO_ABSVALUE_ITEMNAME, + MSG.view_alert_definition_condition_editor_metric_range_lovalue()); absoluteLowValue.setWrapTitle(false); absoluteLowValue.setRequired(true); absoluteLowValue.setTooltip(MSG.view_alert_definition_condition_editor_metric_range_lovalue_tooltip()); @@ -528,8 +542,8 @@ public class NewConditionEditor extends LocatableDynamicForm { absoluteLowValue.setShowIfCondition(ifFunc); formItems.add(absoluteLowValue);
- TextItem absoluteHighValue = new TextItem(RANGE_HI_ABSVALUE_ITEMNAME, MSG - .view_alert_definition_condition_editor_metric_range_hivalue()); + TextItem absoluteHighValue = new TextItem(RANGE_HI_ABSVALUE_ITEMNAME, + MSG.view_alert_definition_condition_editor_metric_range_hivalue()); absoluteHighValue.setWrapTitle(false); absoluteHighValue.setRequired(true); absoluteHighValue.setTooltip(MSG.view_alert_definition_condition_editor_metric_range_hivalue_tooltip()); @@ -563,8 +577,8 @@ public class NewConditionEditor extends LocatableDynamicForm { formItems.add(metricDropDownMenu); formItems.add(buildComparatorDropDownMenu(BASELINE_COMPARATOR_ITEMNAME, ifFunc));
- TextItem baselinePercentage = new TextItem(BASELINE_PERCENTAGE_ITEMNAME, MSG - .view_alert_definition_condition_editor_metric_baseline_percentage()); + TextItem baselinePercentage = new TextItem(BASELINE_PERCENTAGE_ITEMNAME, + MSG.view_alert_definition_condition_editor_metric_baseline_percentage()); baselinePercentage.setWrapTitle(false); baselinePercentage.setRequired(true); baselinePercentage.setTooltip(MSG @@ -575,8 +589,8 @@ public class NewConditionEditor extends LocatableDynamicForm { baselinePercentage.setValidators(new NumberWithUnitsValidator(MeasurementUnits.PERCENTAGE)); formItems.add(baselinePercentage);
- SelectItem baselineSelection = new SelectItem(BASELINE_SELECTION_ITEMNAME, MSG - .view_alert_definition_condition_editor_metric_baseline_value()); + SelectItem baselineSelection = new SelectItem(BASELINE_SELECTION_ITEMNAME, + MSG.view_alert_definition_condition_editor_metric_baseline_value()); LinkedHashMap<String, String> baselines = new LinkedHashMap<String, String>(3); baselines.put("min", MSG.view_alert_definition_condition_editor_common_min()); // TODO can we have the current value of the min baseline baselines.put("mean", MSG.view_alert_definition_condition_editor_common_avg()); // TODO can we have the current value of the avg baseline @@ -630,8 +644,8 @@ public class NewConditionEditor extends LocatableDynamicForm { SelectItem metricDropDownMenu = buildCalltimeMetricDropDownMenu(CALLTIME_THRESHOLD_METRIC_ITEMNAME, ifFunc); formItems.add(metricDropDownMenu);
- SelectItem minMaxAvgSelection = new SelectItem(CALLTIME_THRESHOLD_MINMAXAVG_ITEMNAME, MSG - .view_alert_definition_condition_editor_metric_calltime_common_limit()); + SelectItem minMaxAvgSelection = new SelectItem(CALLTIME_THRESHOLD_MINMAXAVG_ITEMNAME, + MSG.view_alert_definition_condition_editor_metric_calltime_common_limit()); LinkedHashMap<String, String> limits = new LinkedHashMap<String, String>(3); limits.put("MIN", MSG.view_alert_definition_condition_editor_common_min()); limits.put("AVG", MSG.view_alert_definition_condition_editor_common_avg()); @@ -648,8 +662,8 @@ public class NewConditionEditor extends LocatableDynamicForm { formItems.add(minMaxAvgSelection);
formItems.add(buildComparatorDropDownMenu(CALLTIME_THRESHOLD_COMPARATOR_ITEMNAME, ifFunc)); - TextItem absoluteValue = new TextItem(CALLTIME_THRESHOLD_ABSVALUE_ITEMNAME, MSG - .view_alert_definition_condition_editor_metric_calltime_threshold_value()); + TextItem absoluteValue = new TextItem(CALLTIME_THRESHOLD_ABSVALUE_ITEMNAME, + MSG.view_alert_definition_condition_editor_metric_calltime_threshold_value()); absoluteValue.setWrapTitle(false); absoluteValue.setRequired(true); absoluteValue.setTooltip(MSG.view_alert_definition_condition_editor_metric_calltime_threshold_value_tooltip()); @@ -660,8 +674,8 @@ public class NewConditionEditor extends LocatableDynamicForm { metricDropDownMenu)); formItems.add(absoluteValue);
- TextItem regex = new TextItem(CALLTIME_THRESHOLD_REGEX_ITEMNAME, MSG - .view_alert_definition_condition_editor_metric_calltime_common_regex()); + TextItem regex = new TextItem(CALLTIME_THRESHOLD_REGEX_ITEMNAME, + MSG.view_alert_definition_condition_editor_metric_calltime_common_regex()); regex.setRequired(false); regex.setTooltip(MSG.view_alert_definition_condition_editor_metric_calltime_common_regex_tooltip()); regex.setHoverWidth(200); @@ -683,8 +697,8 @@ public class NewConditionEditor extends LocatableDynamicForm {
formItems.add(buildCalltimeMetricDropDownMenu(CALLTIME_CHANGE_METRIC_ITEMNAME, ifFunc));
- SelectItem minMaxAvgSelection = new SelectItem(CALLTIME_CHANGE_MINMAXAVG_ITEMNAME, MSG - .view_alert_definition_condition_editor_metric_calltime_common_limit()); + SelectItem minMaxAvgSelection = new SelectItem(CALLTIME_CHANGE_MINMAXAVG_ITEMNAME, + MSG.view_alert_definition_condition_editor_metric_calltime_common_limit()); LinkedHashMap<String, String> limits = new LinkedHashMap<String, String>(3); limits.put("MIN", MSG.view_alert_definition_condition_editor_common_min()); limits.put("AVG", MSG.view_alert_definition_condition_editor_common_avg()); @@ -702,8 +716,8 @@ public class NewConditionEditor extends LocatableDynamicForm {
formItems.add(buildCalltimeComparatorDropDownMenu(CALLTIME_CHANGE_COMPARATOR_ITEMNAME, ifFunc));
- TextItem percentage = new TextItem(CALLTIME_CHANGE_PERCENTAGE_ITEMNAME, MSG - .view_alert_definition_condition_editor_metric_calltime_change_percentage()); + TextItem percentage = new TextItem(CALLTIME_CHANGE_PERCENTAGE_ITEMNAME, + MSG.view_alert_definition_condition_editor_metric_calltime_change_percentage()); percentage.setWrapTitle(false); percentage.setRequired(true); percentage.setTooltip(MSG.view_alert_definition_condition_editor_metric_calltime_change_percentage_tooltip()); @@ -713,8 +727,8 @@ public class NewConditionEditor extends LocatableDynamicForm { percentage.setValidators(new NumberWithUnitsValidator(MeasurementUnits.PERCENTAGE)); formItems.add(percentage);
- TextItem regex = new TextItem(CALLTIME_CHANGE_REGEX_ITEMNAME, MSG - .view_alert_definition_condition_editor_metric_calltime_common_regex()); + TextItem regex = new TextItem(CALLTIME_CHANGE_REGEX_ITEMNAME, + MSG.view_alert_definition_condition_editor_metric_calltime_common_regex()); regex.setRequired(false); regex.setTooltip(MSG.view_alert_definition_condition_editor_metric_calltime_common_regex_tooltip()); regex.setHoverWidth(200); @@ -741,8 +755,8 @@ public class NewConditionEditor extends LocatableDynamicForm { } }
- SelectItem traitSelection = new SelectItem(TRAIT_METRIC_ITEMNAME, MSG - .view_alert_definition_condition_editor_metric_trait_change_value()); + SelectItem traitSelection = new SelectItem(TRAIT_METRIC_ITEMNAME, + MSG.view_alert_definition_condition_editor_metric_trait_change_value()); traitSelection.setValueMap(traitsMap); traitSelection.setDefaultValue(traitsMap.keySet().iterator().next()); // just use the first one traitSelection.setWidth("*"); @@ -762,19 +776,61 @@ public class NewConditionEditor extends LocatableDynamicForm { StaticTextItem helpItem = buildHelpTextItem("availabilityHelp", helpStr, ifFunc); formItems.add(helpItem);
- SelectItem selection = new SelectItem(AVAILABILITY_ITEMNAME, MSG - .view_alert_definition_condition_editor_avilability_value()); + SelectItem selection = new SelectItem(AVAILABILITY_ITEMNAME, + MSG.view_alert_definition_condition_editor_avilability_value()); LinkedHashMap<String, String> avails = new LinkedHashMap<String, String>(2); - avails.put(AvailabilityType.UP.name(), MSG.view_alert_definition_condition_editor_avilability_option_up()); - avails.put(AvailabilityType.DOWN.name(), MSG.view_alert_definition_condition_editor_avilability_option_down()); + avails.put(AlertConditionOperator.AVAIL_GOES_DOWN.name(), AlertConditionOperator.AVAIL_GOES_DOWN.toString()); + avails.put(AlertConditionOperator.AVAIL_GOES_DISABLED.name(), + AlertConditionOperator.AVAIL_GOES_DISABLED.toString()); + avails.put(AlertConditionOperator.AVAIL_GOES_UNKNOWN.name(), + AlertConditionOperator.AVAIL_GOES_UNKNOWN.toString()); + avails + .put(AlertConditionOperator.AVAIL_GOES_NOT_UP.name(), AlertConditionOperator.AVAIL_GOES_NOT_UP.toString()); + avails.put(AlertConditionOperator.AVAIL_GOES_UP.name(), AlertConditionOperator.AVAIL_GOES_UP.toString()); selection.setValueMap(avails); - selection.setDefaultValue(AvailabilityType.DOWN.name()); + selection.setDefaultValue(AlertConditionOperator.AVAIL_GOES_DOWN.name()); selection.setShowIfCondition(ifFunc);
formItems.add(selection); return formItems; }
+ private ArrayList<FormItem> buildAvailabilityDurationFormItems() { + ArrayList<FormItem> formItems = new ArrayList<FormItem>(); + + ShowIfCategoryFunction ifFunc = new ShowIfCategoryFunction(AlertConditionCategory.AVAIL_DURATION); + + // TODO I18N + //String helpStr = MSG.view_alert_definition_condition_editor_avilability_tooltip(); + String helpStr = "Trigger alert if resource stays in specified avail state for specified duration. This should be no less than several minutes to give the agent a chance to detect and report the change in availability."; + StaticTextItem helpItem = buildHelpTextItem("availabilityHelp", helpStr, ifFunc); + formItems.add(helpItem); + + SelectItem selection = new SelectItem(AVAILABILITY_DURATION_ITEMNAME, "Availability Duration"); + LinkedHashMap<String, String> avails = new LinkedHashMap<String, String>(2); + avails.put(AlertConditionOperator.AVAIL_DURATION_DOWN.name(), + AlertConditionOperator.AVAIL_DURATION_DOWN.toString()); + avails.put(AlertConditionOperator.AVAIL_DURATION_NOT_UP.name(), + AlertConditionOperator.AVAIL_DURATION_NOT_UP.toString()); + selection.setValueMap(avails); + selection.setDefaultValue(AlertConditionOperator.AVAIL_DURATION_DOWN.name()); + selection.setShowIfCondition(ifFunc); + formItems.add(selection); + + TextItem durationValue = new TextItem(AVAILABILITY_DURATION_VAL_ITEMNAME, "Duration"); + durationValue.setWrapTitle(false); + durationValue.setRequired(true); + durationValue + .setTooltip("The number of minutes the resource must be at the given availability before the condition is met."); + durationValue.setHoverWidth(200); + durationValue.setValidateOnChange(true); + durationValue.setValidators(new NumberWithUnitsValidator(MeasurementUnits.MINUTES)); + durationValue.setShowIfCondition(ifFunc); + formItems.add(durationValue); + + return formItems; + } + private ArrayList<FormItem> buildOperationFormItems() { ArrayList<FormItem> formItems = new ArrayList<FormItem>();
@@ -821,8 +877,8 @@ public class NewConditionEditor extends LocatableDynamicForm { StaticTextItem helpItem = buildHelpTextItem("eventHelp", helpStr, ifFunc); formItems.add(helpItem);
- SelectItem eventSeveritySelection = new SelectItem(EVENT_SEVERITY_ITEMNAME, MSG - .view_alert_definition_condition_editor_event_severity()); + SelectItem eventSeveritySelection = new SelectItem(EVENT_SEVERITY_ITEMNAME, + MSG.view_alert_definition_condition_editor_event_severity()); LinkedHashMap<String, String> severities = new LinkedHashMap<String, String>(5); severities.put(EventSeverity.DEBUG.name(), MSG.common_severity_debug()); severities.put(EventSeverity.INFO.name(), MSG.common_severity_info()); @@ -835,8 +891,8 @@ public class NewConditionEditor extends LocatableDynamicForm { eventSeveritySelection.setShowIfCondition(ifFunc); formItems.add(eventSeveritySelection);
- TextItem eventRegex = new TextItem(EVENT_REGEX_ITEMNAME, MSG - .view_alert_definition_condition_editor_event_regex()); + TextItem eventRegex = new TextItem(EVENT_REGEX_ITEMNAME, + MSG.view_alert_definition_condition_editor_event_regex()); eventRegex.setRequired(false); eventRegex.setTooltip(MSG.view_alert_definition_condition_editor_event_regex_tooltip()); eventRegex.setHoverWidth(200); @@ -868,8 +924,8 @@ public class NewConditionEditor extends LocatableDynamicForm { StaticTextItem helpItem = buildHelpTextItem("driftHelp", helpStr, ifFunc); formItems.add(helpItem);
- TextItem driftDefNameRegex = new TextItem(DRIFT_DEFNAME_REGEX_ITEMNAME, MSG - .view_alert_definition_condition_editor_drift_configname_regex()); + TextItem driftDefNameRegex = new TextItem(DRIFT_DEFNAME_REGEX_ITEMNAME, + MSG.view_alert_definition_condition_editor_drift_configname_regex()); driftDefNameRegex.setRequired(false); driftDefNameRegex.setTooltip(MSG.view_alert_definition_condition_editor_drift_configname_regex_tooltip()); driftDefNameRegex.setHoverWidth(200); @@ -877,8 +933,8 @@ public class NewConditionEditor extends LocatableDynamicForm { driftDefNameRegex.setShowIfCondition(ifFunc); formItems.add(driftDefNameRegex);
- TextItem driftPathNameRegex = new TextItem(DRIFT_PATHNAME_REGEX_ITEMNAME, MSG - .view_alert_definition_condition_editor_drift_pathname_regex()); + TextItem driftPathNameRegex = new TextItem(DRIFT_PATHNAME_REGEX_ITEMNAME, + MSG.view_alert_definition_condition_editor_drift_pathname_regex()); driftPathNameRegex.setRequired(false); driftPathNameRegex.setTooltip(MSG.view_alert_definition_condition_editor_drift_pathname_regex_tooltip()); driftPathNameRegex.setHoverWidth(200); @@ -927,8 +983,8 @@ public class NewConditionEditor extends LocatableDynamicForm { return null; // all metrics should be hidden }
- SelectItem metricSelection = new SelectItem(itemName, MSG - .view_alert_definition_condition_editor_metric_threshold_name()); + SelectItem metricSelection = new SelectItem(itemName, + MSG.view_alert_definition_condition_editor_metric_threshold_name()); metricSelection.setValueMap(metricsMap); metricSelection.setDefaultValue(metricsMap.keySet().iterator().next()); // just use the first one metricSelection.setWidth("*"); @@ -946,8 +1002,8 @@ public class NewConditionEditor extends LocatableDynamicForm { } }
- SelectItem metricSelection = new SelectItem(itemName, MSG - .view_alert_definition_condition_editor_metric_calltime_common_name()); + SelectItem metricSelection = new SelectItem(itemName, + MSG.view_alert_definition_condition_editor_metric_calltime_common_name()); metricSelection.setValueMap(metricsMap); metricSelection.setDefaultValue(metricsMap.keySet().iterator().next()); // just use the first one metricSelection.setWidth("*"); @@ -966,8 +1022,8 @@ public class NewConditionEditor extends LocatableDynamicForm { comparators.put(">", "> (" + MSG.view_alert_definition_condition_editor_metric_threshold_comparator_greater() + ")");
- SelectItem comparatorSelection = new SelectItem(itemName, MSG - .view_alert_definition_condition_editor_metric_threshold_comparator()); + SelectItem comparatorSelection = new SelectItem(itemName, + MSG.view_alert_definition_condition_editor_metric_threshold_comparator()); comparatorSelection.setValueMap(comparators); comparatorSelection.setDefaultValue("<"); comparatorSelection @@ -984,8 +1040,8 @@ public class NewConditionEditor extends LocatableDynamicForm { comparators.put("CH", MSG.view_alert_definition_condition_editor_metric_calltime_common_comparator_changes()); comparators.put("HI", MSG.view_alert_definition_condition_editor_metric_calltime_common_comparator_grows());
- SelectItem comparatorSelection = new SelectItem(itemName, MSG - .view_alert_definition_condition_editor_metric_calltime_common_comparator()); + SelectItem comparatorSelection = new SelectItem(itemName, + MSG.view_alert_definition_condition_editor_metric_calltime_common_comparator()); comparatorSelection.setValueMap(comparators); comparatorSelection.setDefaultValue("CH"); comparatorSelection.setTooltip(MSG @@ -1003,8 +1059,8 @@ public class NewConditionEditor extends LocatableDynamicForm { comparators.put("<=", MSG.view_alert_definition_condition_editor_metric_range_comparator_inside_inclusive()); comparators.put(">=", MSG.view_alert_definition_condition_editor_metric_range_comparator_outside_inclusive());
- SelectItem comparatorSelection = new SelectItem(itemName, MSG - .view_alert_definition_condition_editor_metric_range_comparator()); + SelectItem comparatorSelection = new SelectItem(itemName, + MSG.view_alert_definition_condition_editor_metric_range_comparator()); comparatorSelection.setValueMap(comparators); comparatorSelection.setDefaultValue("<"); comparatorSelection.setTooltip(MSG.view_alert_definition_condition_editor_metric_range_comparator_tooltip()); diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/startup/StartupServlet.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/startup/StartupServlet.java index 606eefe..8b94c7b 100644 --- a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/startup/StartupServlet.java +++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/startup/StartupServlet.java @@ -67,6 +67,7 @@ import org.rhq.enterprise.server.plugin.pc.MasterServerPluginContainer; import org.rhq.enterprise.server.plugin.pc.ServerPluginServiceManagement; import org.rhq.enterprise.server.resource.ResourceTypeManagerLocal; import org.rhq.enterprise.server.scheduler.SchedulerLocal; +import org.rhq.enterprise.server.scheduler.jobs.AlertAvailabilityDurationJob; import org.rhq.enterprise.server.scheduler.jobs.AsyncResourceDeleteJob; import org.rhq.enterprise.server.scheduler.jobs.CheckForSuspectedAgentsJob; import org.rhq.enterprise.server.scheduler.jobs.CheckForTimedOutConfigUpdatesJob; @@ -528,6 +529,13 @@ public class StartupServlet extends HttpServlet { log.error("Cannot schedule server plugin jobs.", e); }
+ // Alerting Availability Duration Job (create only, nothing actually scheduled here) + try { + scheduler.scheduleTriggeredJob(AlertAvailabilityDurationJob.class, false, null); + } catch (Exception e) { + log.error("Cannot create alert availability duration job.", e); + } + return; }
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertConditionManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertConditionManagerBean.java index 2f8a8bd..fa38154 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertConditionManagerBean.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertConditionManagerBean.java @@ -100,6 +100,10 @@ public class AlertConditionManagerBean implements AlertConditionManagerLocal { } else if (category == AlertConditionCategory.AVAILABILITY) { queryName = AlertCondition.QUERY_BY_CATEGORY_AVAILABILITY;
+ } else if (category == AlertConditionCategory.AVAIL_DURATION) { + // The duration category can use the same availability composite query, just needs a parameter set + queryName = AlertCondition.QUERY_BY_CATEGORY_AVAILABILITY; + } else if (category == AlertConditionCategory.CONTROL) { queryName = AlertCondition.QUERY_BY_CATEGORY_CONTROL;
@@ -127,7 +131,12 @@ public class AlertConditionManagerBean implements AlertConditionManagerLocal { PersistenceUtility.setDataPage(query, pageControl); Query queryCount = entityManager.createNamedQuery(countQueryName);
- // only the default parameterized count query needs a parameter + // The following query is used in two places, and needs the category set to get different results + if (queryName == AlertCondition.QUERY_BY_CATEGORY_AVAILABILITY) { + query.setParameter("category", category); + } + + // the default parameterized count query needs a parameter if (countQueryName == AlertCondition.QUERY_BY_CATEGORY_COUNT_PARAMETERIZED) { queryCount.setParameter("category", category); } diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertManagerBean.java index a8ab5a7..0475e82 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertManagerBean.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertManagerBean.java @@ -43,8 +43,8 @@ import javax.sql.DataSource;
import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; - import org.hibernate.ejb.QueryImpl; + import org.jboss.annotation.IgnoreDependency; import org.jboss.annotation.ejb.TransactionTimeout;
@@ -52,6 +52,7 @@ import org.rhq.core.domain.alert.Alert; import org.rhq.core.domain.alert.AlertCondition; import org.rhq.core.domain.alert.AlertConditionCategory; import org.rhq.core.domain.alert.AlertConditionLog; +import org.rhq.core.domain.alert.AlertConditionOperator; import org.rhq.core.domain.alert.AlertDefinition; import org.rhq.core.domain.alert.notification.AlertNotification; import org.rhq.core.domain.alert.notification.AlertNotificationLog; @@ -60,6 +61,7 @@ import org.rhq.core.domain.alert.notification.SenderResult; import org.rhq.core.domain.auth.Subject; import org.rhq.core.domain.authz.Permission; import org.rhq.core.domain.common.EntityContext; +import org.rhq.core.domain.common.composite.SystemSetting; import org.rhq.core.domain.criteria.AlertCriteria; import org.rhq.core.domain.measurement.MeasurementUnits; import org.rhq.core.domain.operation.OperationDefinition; @@ -807,8 +809,9 @@ public class AlertManagerBean implements AlertManagerLocal, AlertManagerRemote { dateFormat = new SimpleDateFormat("yy/MM/dd HH:mm:ss z"); else dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss z"); - builder.append(AlertI18NFactory.getMessage(format, conditionCounter, prettyPrintAlertCondition(aLog - .getCondition(), shortVersion), dateFormat.format(new Date(aLog.getCtime())), formattedValue)); + builder.append(AlertI18NFactory.getMessage(format, conditionCounter, + prettyPrintAlertCondition(aLog.getCondition(), shortVersion), + dateFormat.format(new Date(aLog.getCtime())), formattedValue)); conditionCounter++; }
@@ -821,6 +824,26 @@ public class AlertManagerBean implements AlertManagerLocal, AlertManagerRemote { AlertConditionCategory category = condition.getCategory(); switch (category) { case AVAILABILITY: { + // TODO I18N + str.append("Availability Change To"); + str.append(" ["); + AlertConditionOperator operator = AlertConditionOperator.valueOf(condition.getName().toUpperCase()); + switch (operator) { + case AVAIL_GOES_DISABLED: + case AVAIL_GOES_DOWN: + case AVAIL_GOES_UNKNOWN: + case AVAIL_GOES_UP: + case AVAIL_GOES_NOT_UP: + str.append(operator); + break; + default: + str.append("*ERROR*"); + } + str.append("]"); + + break; + + /* if ("up".equalsIgnoreCase(condition.getOption())) { if (shortVersion) { str.append(AlertI18NFactory.getMessage(AlertI18NResourceKeys.ALERT_AVAILABILITY_UP_SHORT)); @@ -834,9 +857,31 @@ public class AlertManagerBean implements AlertManagerLocal, AlertManagerRemote { str.append(AlertI18NFactory.getMessage(AlertI18NResourceKeys.ALERT_AVAILABILITY_DOWN)); } } + */ + } + + case AVAIL_DURATION: { + // TODO I18N + str.append("Availability Duration "); + AlertConditionOperator operator = AlertConditionOperator.valueOf(condition.getName().toUpperCase()); + switch (operator) { + case AVAIL_DURATION_DOWN: + case AVAIL_DURATION_NOT_UP: + str.append(operator); + break; + default: + str.append("*ERROR*"); + } + str.append("] ["); + + double value = condition.getThreshold(); + String formatted = MeasurementConverter.format(value, MeasurementUnits.MILLISECONDS, true); + str.append(formatted); + str.append("]");
break; } + case THRESHOLD: { double value = condition.getThreshold(); MeasurementUnits units = condition.getMeasurementDefinition().getUnits(); @@ -1151,8 +1196,7 @@ public class AlertManagerBean implements AlertManagerLocal, AlertManagerRemote { public String prettyPrintAlertURL(Alert alert) { StringBuilder builder = new StringBuilder();
- String baseUrl = systemManager.getSystemConfiguration(subjectManager.getOverlord()).getProperty( - RHQConstants.BaseURL); + String baseUrl = systemManager.getSystemSettings(subjectManager.getOverlord()).get(SystemSetting.BASE_URL); builder.append(baseUrl); if (!baseUrl.endsWith("/")) { builder.append("/"); diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/AlertConditionCacheManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/AlertConditionCacheManagerBean.java index 57cf70d..1d37cd3 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/AlertConditionCacheManagerBean.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/AlertConditionCacheManagerBean.java @@ -37,6 +37,7 @@ import org.rhq.core.domain.measurement.calltime.CallTimeData; import org.rhq.core.domain.operation.OperationHistory; import org.rhq.core.domain.resource.Agent; import org.rhq.enterprise.server.alert.engine.internal.AlertConditionCacheCoordinator; +import org.rhq.enterprise.server.alert.engine.model.AvailabilityDurationComposite; import org.rhq.enterprise.server.cloud.instance.ServerManagerLocal; import org.rhq.enterprise.server.plugin.pc.drift.DriftChangeSetSummary;
@@ -77,6 +78,12 @@ public class AlertConditionCacheManagerBean implements AlertConditionCacheManage return stats; }
+ public AlertConditionCacheStats checkConditions(AvailabilityDurationComposite... composites) { + AlertConditionCacheStats stats; + stats = AlertConditionCacheCoordinator.getInstance().checkConditions(composites); + return stats; + } + public AlertConditionCacheStats checkConditions(EventSource source, Event... events) { AlertConditionCacheStats stats; stats = AlertConditionCacheCoordinator.getInstance().checkConditions(source, events); diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/AlertConditionCacheManagerLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/AlertConditionCacheManagerLocal.java index 1eed43d..e1d0306 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/AlertConditionCacheManagerLocal.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/AlertConditionCacheManagerLocal.java @@ -31,6 +31,7 @@ import org.rhq.core.domain.measurement.Availability; import org.rhq.core.domain.measurement.MeasurementData; import org.rhq.core.domain.measurement.calltime.CallTimeData; import org.rhq.core.domain.operation.OperationHistory; +import org.rhq.enterprise.server.alert.engine.model.AvailabilityDurationComposite; import org.rhq.enterprise.server.plugin.pc.drift.DriftChangeSetSummary;
/** @@ -81,6 +82,14 @@ public interface AlertConditionCacheManagerLocal { AlertConditionCacheStats checkConditions(Availability... availability);
/** + * Availability duration checking is unlike Availability. Since Availability is RLE it does not give us + * the ability to perform avail duration, this mechnism does. + * + * @return the number of conditions that were true against this argument + */ + AlertConditionCacheStats checkConditions(AvailabilityDurationComposite... availabilityDurationComposites); + + /** * An EventReport is full of Event objects. Each of these could potentially match against one of the cache's * conditions. So, each must be checked against it, to see whether it fires against any of the conditions. * diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/internal/AbstractConditionCache.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/internal/AbstractConditionCache.java index 9199701..9266cda 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/internal/AbstractConditionCache.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/internal/AbstractConditionCache.java @@ -25,10 +25,10 @@ import java.util.Map; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory;
+import org.rhq.core.domain.alert.AlertConditionOperator; import org.rhq.enterprise.server.alert.engine.AlertConditionCacheStats; import org.rhq.enterprise.server.alert.engine.jms.CachedConditionProducerLocal; import org.rhq.enterprise.server.alert.engine.model.AbstractCacheElement; -import org.rhq.enterprise.server.alert.engine.model.AlertConditionOperator; import org.rhq.enterprise.server.util.LookupUtil;
/** @@ -66,8 +66,8 @@ abstract class AbstractConditionCache { */ cacheElement.setActive(true); // no harm to always set active (though, technically, STATELESS operators don't need it) cachedConditionProducer.sendActivateAlertConditionMessage( - cacheElement.getAlertConditionTriggerId(), timestamp, cacheElement - .convertValueToString(providedValue), extraParams); + cacheElement.getAlertConditionTriggerId(), timestamp, + cacheElement.convertValueToString(providedValue), extraParams);
stats.matched++; } catch (Exception e) { @@ -85,8 +85,8 @@ abstract class AbstractConditionCache {
try { // send negative message - cachedConditionProducer.sendDeactivateAlertConditionMessage(cacheElement - .getAlertConditionTriggerId(), timestamp); + cachedConditionProducer.sendDeactivateAlertConditionMessage( + cacheElement.getAlertConditionTriggerId(), timestamp); } catch (Exception e) { log.error("Error sending deactivation message for cache element '" + cacheElement + "': " + e.getMessage()); diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/internal/AgentConditionCache.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/internal/AgentConditionCache.java index be48af0..f23574b 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/internal/AgentConditionCache.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/internal/AgentConditionCache.java @@ -29,6 +29,7 @@ import java.util.concurrent.TimeUnit;
import org.rhq.core.domain.alert.AlertCondition; import org.rhq.core.domain.alert.AlertConditionCategory; +import org.rhq.core.domain.alert.AlertConditionOperator; import org.rhq.core.domain.alert.composite.AbstractAlertConditionCategoryComposite; import org.rhq.core.domain.alert.composite.AlertConditionBaselineCategoryComposite; import org.rhq.core.domain.alert.composite.AlertConditionChangesCategoryComposite; @@ -54,7 +55,6 @@ import org.rhq.enterprise.server.alert.AlertConditionManagerLocal; import org.rhq.enterprise.server.alert.engine.AlertConditionCacheStats; import org.rhq.enterprise.server.alert.engine.internal.AlertConditionCacheCoordinator.Cache; import org.rhq.enterprise.server.alert.engine.mbean.AlertConditionCacheMonitor; -import org.rhq.enterprise.server.alert.engine.model.AlertConditionOperator; import org.rhq.enterprise.server.alert.engine.model.CallTimeDataCacheElement; import org.rhq.enterprise.server.alert.engine.model.CallTimeDataCacheElement.CallTimeElementValue; import org.rhq.enterprise.server.alert.engine.model.DriftCacheElement; @@ -176,8 +176,8 @@ class AgentConditionCache extends AbstractConditionCache { int alertConditionId = alertCondition.getId(); // auto-unboxing is safe here because as the PK it's guaranteed to be non-null
AlertConditionCategory alertConditionCategory = alertCondition.getCategory(); - AlertConditionOperator alertConditionOperator = AlertConditionCacheUtils.getAlertConditionOperator( - alertConditionCategory, alertCondition.getComparator(), alertCondition.getOption()); + AlertConditionOperator alertConditionOperator = AlertConditionCacheUtils + .getAlertConditionOperator(alertCondition);
if (DataType.CALLTIME == composite.getDataType()) { // call-time cases start here if (alertConditionCategory == AlertConditionCategory.CHANGE) { diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/internal/AlertConditionCacheCoordinator.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/internal/AlertConditionCacheCoordinator.java index db4b0b9..59c0fb6 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/internal/AlertConditionCacheCoordinator.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/internal/AlertConditionCacheCoordinator.java @@ -38,6 +38,7 @@ import org.rhq.core.domain.measurement.calltime.CallTimeData; import org.rhq.core.domain.operation.OperationHistory; import org.rhq.enterprise.server.alert.engine.AlertConditionCacheStats; import org.rhq.enterprise.server.alert.engine.model.AbstractCacheElement; +import org.rhq.enterprise.server.alert.engine.model.AvailabilityDurationComposite; import org.rhq.enterprise.server.cloud.StatusManagerLocal; import org.rhq.enterprise.server.core.AgentManagerLocal; import org.rhq.enterprise.server.plugin.pc.drift.DriftChangeSetSummary; @@ -68,7 +69,8 @@ public final class AlertConditionCacheCoordinator { AvailabilityCache(Type.Global), // EventsCache(Type.Agent), // ResourceConfigurationCache(Type.Global), // - DriftCache(Type.Agent); + DriftCache(Type.Agent), // + AvailabilityDurationCache(Type.Global); //
public enum Type { Global, // @@ -342,6 +344,19 @@ public final class AlertConditionCacheCoordinator { return stats; }
+ public AlertConditionCacheStats checkConditions(AvailabilityDurationComposite... composites) { + AlertConditionCacheStats stats = null; + try { + stats = globalCache.checkConditions(composites); + } catch (Throwable t) { + log.error("Error during checkConditions", t); // don't let any exceptions bubble up to the calling SLSB layer + } + if (stats == null) { + stats = new AlertConditionCacheStats(); + } + return stats; + } + private Integer getAgentId(DriftChangeSetSummary driftChangeSetSummary) { try { int resourceId = driftChangeSetSummary.getResourceId(); diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/internal/AlertConditionCacheUtils.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/internal/AlertConditionCacheUtils.java index b20f1a8..f6eb3e9 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/internal/AlertConditionCacheUtils.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/internal/AlertConditionCacheUtils.java @@ -24,10 +24,10 @@ import java.util.Map; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory;
+import org.rhq.core.domain.alert.AlertCondition; import org.rhq.core.domain.alert.AlertConditionCategory; -import org.rhq.core.domain.measurement.AvailabilityType; +import org.rhq.core.domain.alert.AlertConditionOperator; import org.rhq.enterprise.server.alert.engine.model.AbstractCacheElement; -import org.rhq.enterprise.server.alert.engine.model.AlertConditionOperator; import org.rhq.enterprise.server.alert.engine.model.UnsupportedAlertConditionOperatorException;
/** @@ -37,74 +37,89 @@ class AlertConditionCacheUtils {
private static final Log log = LogFactory.getLog(AlertConditionCacheCoordinator.class);
- public static AlertConditionOperator getAlertConditionOperator(AlertConditionCategory category, String comparator, - String conditionOption) { - if (category == AlertConditionCategory.CONTROL) { + public static AlertConditionOperator getAlertConditionOperator(AlertCondition alertCondition) { + + AlertConditionCategory category = alertCondition.getCategory(); + String name = alertCondition.getName(); + String comparator = alertCondition.getComparator(); + + switch (category) { + case CONTROL: // the UI currently only supports one operator for control return AlertConditionOperator.EQUALS; - }
- if (category == AlertConditionCategory.EVENT) { + case EVENT: // the UI currently only supports one operator for events return AlertConditionOperator.GREATER_THAN_OR_EQUAL_TO; + + case DRIFT: + // any drift that is detected infers a change to its previous state + return AlertConditionOperator.CHANGES; + + case RESOURCE_CONFIG: + case CHANGE: + case TRAIT: + // the model currently supports CHANGE as a category type instead of a comparator + return AlertConditionOperator.CHANGES; + + case AVAILABILITY: { + AlertConditionOperator operator = AlertConditionOperator.valueOf(name.toUpperCase()); + + switch (operator) { + case AVAIL_GOES_DISABLED: + case AVAIL_GOES_DOWN: + case AVAIL_GOES_UNKNOWN: + case AVAIL_GOES_UP: + case AVAIL_GOES_NOT_UP: + return operator; + + default: + throw new UnsupportedAlertConditionOperatorException( + "Invalid alertConditionValue for AVAILABILITY category:" + operator); + } + } + + case AVAIL_DURATION: { + AlertConditionOperator operator = AlertConditionOperator.valueOf(name.toUpperCase()); + + switch (operator) { + case AVAIL_DURATION_DOWN: + case AVAIL_DURATION_NOT_UP: + return operator; + + default: + throw new UnsupportedAlertConditionOperatorException( + "Invalid alertConditionValue for AVAILABILITY_DURATION category:" + operator); + } }
- if (category == AlertConditionCategory.RANGE) { + case RANGE: // range can support <= and >=, which we look for here. It can also support < and >, which is checked down below further. // note that RANGE does not support =, so we throw an exception if caller tries that if (comparator.equals("<=")) { return AlertConditionOperator.LESS_THAN_OR_EQUAL_TO; + } else if (comparator.equals(">=")) { return AlertConditionOperator.GREATER_THAN_OR_EQUAL_TO; + } else if (comparator.equals("=")) { throw new UnsupportedAlertConditionOperatorException("Comparator [" + comparator + "] " + "is not supported for category: " + category.name()); } - }
- if (category == AlertConditionCategory.DRIFT) { - // any drift that is detected infers a change to its previous state - return AlertConditionOperator.CHANGES; - } + default:
- if (category == AlertConditionCategory.RESOURCE_CONFIG || category == AlertConditionCategory.CHANGE - || category == AlertConditionCategory.TRAIT) { - // the model currently supports CHANGE as a category type instead of a comparator - return AlertConditionOperator.CHANGES; - } - - if (category == AlertConditionCategory.AVAILABILITY) { - AvailabilityType conditionOptionType = AvailabilityType.valueOf(conditionOption.toUpperCase()); - if (conditionOptionType == AvailabilityType.DOWN) { - /* - * UI phrases this as "Goes DOWN", but we're going to store the cache element as CHANGES_FROM:UP - * - * This way, it'll work when the agent's goes suspect and null is persisted for AvailabilityType - */ - return AlertConditionOperator.CHANGES_FROM; - } else if (conditionOptionType == AvailabilityType.UP) { - /* - * UI phrases this as "Goes UP", but we're going to store the cache element as CHANGES_TO:UP - * - * This way, it'll work when the agent's comes back from being suspect, where it had null for its - * AvailabilityType - */ - return AlertConditionOperator.CHANGES_TO; + if (comparator.equals("<")) { + return AlertConditionOperator.LESS_THAN; + } else if (comparator.equals(">")) { + return AlertConditionOperator.GREATER_THAN; + } else if (comparator.equals("=")) { + return AlertConditionOperator.EQUALS; } else { - throw new UnsupportedAlertConditionOperatorException("Invalid alertCondition for AVAILABILITY category"); + throw new UnsupportedAlertConditionOperatorException("Comparator [" + comparator + "] " + + "is not supported for category: " + category.name()); } } - - if (comparator.equals("<")) { - return AlertConditionOperator.LESS_THAN; - } else if (comparator.equals(">")) { - return AlertConditionOperator.GREATER_THAN; - } else if (comparator.equals("=")) { - return AlertConditionOperator.EQUALS; - } else { - throw new UnsupportedAlertConditionOperatorException("Comparator [" + comparator + "] " - + "is not supported for category: " + category.name()); - } }
public static String getCacheElementErrorString(int conditionId, AlertConditionOperator operator, Object option, diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/internal/GlobalConditionCache.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/internal/GlobalConditionCache.java index 5f9ecdb..98f9463 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/internal/GlobalConditionCache.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/internal/GlobalConditionCache.java @@ -18,6 +18,7 @@ */ package org.rhq.enterprise.server.alert.engine.internal;
+import java.util.ArrayList; import java.util.EnumSet; import java.util.HashMap; import java.util.List; @@ -25,6 +26,7 @@ import java.util.Map;
import org.rhq.core.domain.alert.AlertCondition; import org.rhq.core.domain.alert.AlertConditionCategory; +import org.rhq.core.domain.alert.AlertConditionOperator; import org.rhq.core.domain.alert.composite.AbstractAlertConditionCategoryComposite; import org.rhq.core.domain.alert.composite.AlertConditionAvailabilityCategoryComposite; import org.rhq.core.domain.alert.composite.AlertConditionControlCategoryComposite; @@ -44,8 +46,9 @@ import org.rhq.enterprise.server.alert.AlertConditionManagerLocal; import org.rhq.enterprise.server.alert.engine.AlertConditionCacheStats; import org.rhq.enterprise.server.alert.engine.internal.AlertConditionCacheCoordinator.Cache; import org.rhq.enterprise.server.alert.engine.mbean.AlertConditionCacheMonitor; -import org.rhq.enterprise.server.alert.engine.model.AlertConditionOperator; import org.rhq.enterprise.server.alert.engine.model.AvailabilityCacheElement; +import org.rhq.enterprise.server.alert.engine.model.AvailabilityDurationCacheElement; +import org.rhq.enterprise.server.alert.engine.model.AvailabilityDurationComposite; import org.rhq.enterprise.server.alert.engine.model.InvalidCacheElementException; import org.rhq.enterprise.server.alert.engine.model.ResourceConfigurationCacheElement; import org.rhq.enterprise.server.alert.engine.model.ResourceOperationCacheElement; @@ -59,6 +62,7 @@ class GlobalConditionCache extends AbstractConditionCache {
private Map<Integer, Map<Integer, List<ResourceOperationCacheElement>>> resourceOperationCache; // key: resource ID, inner key: operation def ID private Map<Integer, List<AvailabilityCacheElement>> availabilityCache; // key: resource ID + private Map<Integer, List<AvailabilityDurationCacheElement>> availabilityDurationCache; // key: resource ID private Map<Integer, List<ResourceConfigurationCacheElement>> resourceConfigurationCache; // key: resource ID
private AlertConditionManagerLocal alertConditionManager; @@ -69,6 +73,7 @@ class GlobalConditionCache extends AbstractConditionCache {
resourceOperationCache = new HashMap<Integer, Map<Integer, List<ResourceOperationCacheElement>>>(); availabilityCache = new HashMap<Integer, List<AvailabilityCacheElement>>(); + availabilityDurationCache = new HashMap<Integer, List<AvailabilityDurationCacheElement>>(); resourceConfigurationCache = new HashMap<Integer, List<ResourceConfigurationCacheElement>>();
alertConditionManager = LookupUtil.getAlertConditionManager(); @@ -89,7 +94,8 @@ class GlobalConditionCache extends AbstractConditionCache { Subject overlord = subjectManager.getOverlord();
EnumSet<AlertConditionCategory> supportedCategories = EnumSet.of(AlertConditionCategory.AVAILABILITY, - AlertConditionCategory.CONTROL, AlertConditionCategory.RESOURCE_CONFIG); + AlertConditionCategory.AVAIL_DURATION, AlertConditionCategory.CONTROL, + AlertConditionCategory.RESOURCE_CONFIG);
for (AlertConditionCategory nextCategory : supportedCategories) { // page thru all alert definitions @@ -137,22 +143,15 @@ class GlobalConditionCache extends AbstractConditionCache { int alertConditionId = alertCondition.getId(); // auto-unboxing is safe here because as the PK it's guaranteed to be non-null
AlertConditionCategory alertConditionCategory = alertCondition.getCategory(); - AlertConditionOperator alertConditionOperator = AlertConditionCacheUtils.getAlertConditionOperator( - alertConditionCategory, alertCondition.getComparator(), alertCondition.getOption()); + AlertConditionOperator alertConditionOperator = AlertConditionCacheUtils + .getAlertConditionOperator(alertCondition);
if (alertConditionCategory == AlertConditionCategory.AVAILABILITY) { - /* - * This is a hack, because we're not respecting the persist alertCondition option, we're instead overriding - * it with AvailabilityType.UP to satisfy the desired semantics. - * - * TODO: jmarques - should associate a specific operator with availability UI selections to make biz - * processing more consistent with the model - */ AlertConditionAvailabilityCategoryComposite availabilityComposite = (AlertConditionAvailabilityCategoryComposite) composite;
try { AvailabilityCacheElement cacheElement = new AvailabilityCacheElement(alertConditionOperator, - AvailabilityType.UP, availabilityComposite.getAvailabilityType(), alertConditionId); + availabilityComposite.getAvailabilityType(), alertConditionId); addTo("availabilityCache", availabilityCache, availabilityComposite.getResourceId(), cacheElement, alertConditionId, stats); } catch (InvalidCacheElementException icee) { @@ -160,6 +159,20 @@ class GlobalConditionCache extends AbstractConditionCache { + AlertConditionCacheUtils.getCacheElementErrorString(alertConditionId, alertConditionOperator, availabilityComposite.getAvailabilityType(), AvailabilityType.UP)); } + } else if (alertConditionCategory == AlertConditionCategory.AVAIL_DURATION) { + AlertConditionAvailabilityCategoryComposite availabilityComposite = (AlertConditionAvailabilityCategoryComposite) composite; + + try { + AvailabilityDurationCacheElement cacheElement = new AvailabilityDurationCacheElement( + alertConditionOperator, alertCondition.getOption(), availabilityComposite.getAvailabilityType(), + alertConditionId); + addTo("availabilityDurationCache", availabilityDurationCache, availabilityComposite.getResourceId(), + cacheElement, alertConditionId, stats); + } catch (InvalidCacheElementException icee) { + log.info("Failed to create AvailabilityCacheElement with parameters: " + + AlertConditionCacheUtils.getCacheElementErrorString(alertConditionId, alertConditionOperator, + availabilityComposite.getAvailabilityType(), alertConditionOperator.toString())); + } } else if (alertConditionCategory == AlertConditionCategory.CONTROL) { AlertConditionControlCategoryComposite controlComposite = (AlertConditionControlCategoryComposite) composite; String option = alertCondition.getOption(); @@ -170,8 +183,8 @@ class GlobalConditionCache extends AbstractConditionCache { operationRequestStatus, alertConditionId);
// auto-boxing always safe - addToResourceOperationCache(controlComposite.getResourceId(), controlComposite - .getOperationDefinitionId(), cacheElement, alertConditionId, stats); + addToResourceOperationCache(controlComposite.getResourceId(), + controlComposite.getOperationDefinitionId(), cacheElement, alertConditionId, stats); } catch (InvalidCacheElementException icee) { log.info("Failed to create ResourceOperationCacheElement with parameters: " + AlertConditionCacheUtils.getCacheElementErrorString(alertConditionId, alertConditionOperator, @@ -190,8 +203,8 @@ class GlobalConditionCache extends AbstractConditionCache { null, null)); }
- addTo("resourceConfigurationCache", resourceConfigurationCache, resourceConfigurationComposite - .getResourceId(), cacheElement, alertConditionId, stats); + addTo("resourceConfigurationCache", resourceConfigurationCache, + resourceConfigurationComposite.getResourceId(), cacheElement, alertConditionId, stats); } }
@@ -265,6 +278,14 @@ class GlobalConditionCache extends AbstractConditionCache { List<AvailabilityCacheElement> cacheElements = lookupAvailabilityCacheElements(resource.getId());
processCacheElements(cacheElements, availabilityType, availability.getStartTime().getTime(), stats); + + // Avail Duration conditions are evaluated in two parts: + // 1) First, an avail change to the that starts the clock ticking. + // 2) Second, after the duration period, check to see if the avail state is still the same. + // Here we check for part 1, see if we need to start duration processing for the avail change + List<AvailabilityDurationCacheElement> durationCacheElements = lookupAvailabilityDurationCacheElements(resource + .getId()); + AvailabilityDurationCacheElement.checkCacheElements(durationCacheElements, resource, availabilityType); }
AlertConditionCacheMonitor.getMBean().incrementAvailabilityCacheElementMatches(stats.matched); @@ -278,6 +299,51 @@ class GlobalConditionCache extends AbstractConditionCache { return stats; }
+ // Avail Duration conditions are evaluated in two parts: + // 1) First, an avail change to the that starts the clock ticking. + // 2) Second, after the duration period, check to see if the avail state is still the same. + // Here we check for part 2, finish processing of the condition whose duration job finished and + // determined the avail state to be satisfied. Now hook in to the alerting chassis... + public AlertConditionCacheStats checkConditions(AvailabilityDurationComposite... composites) { + if ((null == composites) || (composites.length == 0)) { + return new AlertConditionCacheStats(); + } + + AlertConditionCacheStats stats = new AlertConditionCacheStats(); + try { + for (AvailabilityDurationComposite composite : composites) { + + List<AvailabilityDurationCacheElement> cacheElements = lookupAvailabilityDurationCacheElements(composite + .getResourceId()); + + // This method differs from the other <code>checkConditions<code> methods in that it is only + // interested in a single condition for each composite, the one for which the duration job completed. + if (!(null == cacheElements || cacheElements.isEmpty())) { + for (AvailabilityDurationCacheElement cacheElement : cacheElements) { + if (composite.getConditionId() == cacheElement.getAlertConditionTriggerId()) { + List<AvailabilityDurationCacheElement> cacheElementAsList = new ArrayList<AvailabilityDurationCacheElement>( + 1); + cacheElementAsList.add(cacheElement); + + processCacheElements(cacheElementAsList, composite.getAvailabilityType(), + System.currentTimeMillis(), stats); + break; + } + } + } + } + + AlertConditionCacheMonitor.getMBean().incrementAvailabilityDurationCacheElementMatches(stats.matched); + AlertConditionCacheMonitor.getMBean().incrementAvailabilityDurationProcessingTime(stats.getAge()); + if (log.isDebugEnabled()) + log.debug("Check AvailabilityDuration[size=" + composites.length + "] - " + stats); + } catch (Throwable t) { + // don't let any exceptions bubble up to the calling SLSB layer + log.error("Error during global cache processing: ", t); + } + return stats; + } + private boolean addToResourceOperationCache(Integer resourceId, Integer operationDefinitionId, ResourceOperationCacheElement cacheElement, Integer alertConditionId, AlertConditionCacheStats stats) { // resourceOperationCache = new HashMap< Integer, Map< Integer, List < ResourceOperationCacheElement > > >(); @@ -309,6 +375,10 @@ class GlobalConditionCache extends AbstractConditionCache { return availabilityCache.get(resourceId); // yup, might be null }
+ private List<AvailabilityDurationCacheElement> lookupAvailabilityDurationCacheElements(int resourceId) { + return availabilityDurationCache.get(resourceId); // yup, might be null + } + private List<ResourceConfigurationCacheElement> lookupResourceConfigurationCacheElements(int resourceId) { return resourceConfigurationCache.get(resourceId); // yup, might be null } @@ -317,6 +387,8 @@ class GlobalConditionCache extends AbstractConditionCache { public int getCacheSize(Cache cache) { if (cache == AlertConditionCacheCoordinator.Cache.AvailabilityCache) { return AlertConditionCacheUtils.getMapListCount(availabilityCache); + } else if (cache == AlertConditionCacheCoordinator.Cache.AvailabilityDurationCache) { + return AlertConditionCacheUtils.getMapListCount(availabilityDurationCache); } else if (cache == AlertConditionCacheCoordinator.Cache.ResourceConfigurationCache) { return AlertConditionCacheUtils.getMapListCount(resourceConfigurationCache); } else if (cache == AlertConditionCacheCoordinator.Cache.ResourceOperationCache) { diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/mbean/AlertConditionCacheMonitor.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/mbean/AlertConditionCacheMonitor.java index 8e3be19..812e2a6 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/mbean/AlertConditionCacheMonitor.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/mbean/AlertConditionCacheMonitor.java @@ -38,6 +38,7 @@ import org.rhq.enterprise.server.util.LookupUtil; public class AlertConditionCacheMonitor implements AlertConditionCacheMonitorMBean, MBeanRegistration {
public AtomicInteger availabilityCacheElementMatches = new AtomicInteger(); + public AtomicInteger availabilityDurationCacheElementMatches = new AtomicInteger(); public AtomicInteger eventCacheElementMatches = new AtomicInteger(); public AtomicInteger measurementCacheElementMatches = new AtomicInteger(); public AtomicInteger resourceConfigurationCacheElementMatches = new AtomicInteger(); @@ -47,6 +48,7 @@ public class AlertConditionCacheMonitor implements AlertConditionCacheMonitorMBe public AtomicInteger totalCacheElementMatches = new AtomicInteger();
public AtomicLong availabilityProcessingTime = new AtomicLong(); + public AtomicLong availabilityDurationProcessingTime = new AtomicLong(); public AtomicLong eventProcessingTime = new AtomicLong(); public AtomicLong measurementProcessingTime = new AtomicLong(); public AtomicLong resourceConfigurationProcessingTime = new AtomicLong(); @@ -79,6 +81,11 @@ public class AlertConditionCacheMonitor implements AlertConditionCacheMonitorMBe AlertConditionCacheCoordinator.Cache.AvailabilityCache); }
+ public int getAvailabilityDurationCacheElementCount() { + return AlertConditionCacheCoordinator.getInstance().getCacheSize( + AlertConditionCacheCoordinator.Cache.AvailabilityDurationCache); + } + public int getEventCacheElementCount() { return AlertConditionCacheCoordinator.getInstance().getCacheSize( AlertConditionCacheCoordinator.Cache.EventsCache); @@ -131,6 +138,10 @@ public class AlertConditionCacheMonitor implements AlertConditionCacheMonitorMBe return availabilityCacheElementMatches.get(); }
+ public int getAvailabilityDurationCacheElementMatches() { + return availabilityDurationCacheElementMatches.get(); + } + public int getEventCacheElementMatches() { return eventCacheElementMatches.get(); } @@ -164,6 +175,11 @@ public class AlertConditionCacheMonitor implements AlertConditionCacheMonitorMBe totalCacheElementMatches.addAndGet(matches); }
+ public void incrementAvailabilityDurationCacheElementMatches(int matches) { + availabilityDurationCacheElementMatches.addAndGet(matches); + totalCacheElementMatches.addAndGet(matches); + } + public void incrementEventCacheElementMatches(int matches) { eventCacheElementMatches.addAndGet(matches); totalCacheElementMatches.addAndGet(matches); @@ -198,6 +214,10 @@ public class AlertConditionCacheMonitor implements AlertConditionCacheMonitorMBe return availabilityProcessingTime.get(); }
+ public long getAvailabilityDurationProcessingTime() { + return availabilityDurationProcessingTime.get(); + } + public long getEventProcessingTime() { return eventProcessingTime.get(); } @@ -227,6 +247,11 @@ public class AlertConditionCacheMonitor implements AlertConditionCacheMonitorMBe totalProcessingTime.addAndGet(moreMillis); }
+ public void incrementAvailabilityDurationProcessingTime(long moreMillis) { + availabilityDurationProcessingTime.addAndGet(moreMillis); + totalProcessingTime.addAndGet(moreMillis); + } + public void incrementEventProcessingTime(long moreMillis) { eventProcessingTime.addAndGet(moreMillis); totalProcessingTime.addAndGet(moreMillis); diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/mbean/AlertConditionCacheMonitorMBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/mbean/AlertConditionCacheMonitorMBean.java index 328d4f2..dbe3116 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/mbean/AlertConditionCacheMonitorMBean.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/mbean/AlertConditionCacheMonitorMBean.java @@ -34,6 +34,8 @@ public interface AlertConditionCacheMonitorMBean {
public long getAvailabilityProcessingTime();
+ public long getAvailabilityDurationProcessingTime(); + public long getMeasurementProcessingTime();
public long getEventProcessingTime(); @@ -46,6 +48,8 @@ public interface AlertConditionCacheMonitorMBean {
public void incrementAvailabilityProcessingTime(long moreMillis);
+ public void incrementAvailabilityDurationProcessingTime(long moreMillis); + public void incrementMeasurementProcessingTime(long moreMillis);
public void incrementEventProcessingTime(long moreMillis); @@ -65,6 +69,8 @@ public interface AlertConditionCacheMonitorMBean {
public int getAvailabilityCacheElementCount();
+ public int getAvailabilityDurationCacheElementCount(); + public int getMeasurementCacheElementCount();
public int getEventCacheElementCount(); @@ -86,6 +92,8 @@ public interface AlertConditionCacheMonitorMBean {
public int getAvailabilityCacheElementMatches();
+ public int getAvailabilityDurationCacheElementMatches(); + public int getMeasurementCacheElementMatches();
public int getEventCacheElementMatches(); @@ -100,6 +108,8 @@ public interface AlertConditionCacheMonitorMBean {
public void incrementAvailabilityCacheElementMatches(int matches);
+ public void incrementAvailabilityDurationCacheElementMatches(int matches); + public void incrementMeasurementCacheElementMatches(int matches);
public void incrementEventCacheElementMatches(int matches); diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/model/AbstractCacheElement.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/model/AbstractCacheElement.java index e09ddae..31f406c 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/model/AbstractCacheElement.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/model/AbstractCacheElement.java @@ -21,6 +21,8 @@ package org.rhq.enterprise.server.alert.engine.model; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory;
+import org.rhq.core.domain.alert.AlertConditionOperator; + /** * @author Joseph Marques */ diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/model/AbstractEnumCacheElement.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/model/AbstractEnumCacheElement.java index ed68b0b..088542c 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/model/AbstractEnumCacheElement.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/model/AbstractEnumCacheElement.java @@ -18,6 +18,8 @@ */ package org.rhq.enterprise.server.alert.engine.model;
+import org.rhq.core.domain.alert.AlertConditionOperator; + /** * @author Joseph Marques */ diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/model/AlertConditionOperator.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/model/AlertConditionOperator.java deleted file mode 100644 index bd5aabc..0000000 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/model/AlertConditionOperator.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * RHQ Management Platform - * Copyright (C) 2005-2008 Red Hat, Inc. - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -package org.rhq.enterprise.server.alert.engine.model; - -/** - * @author Joseph Marques - */ - -public enum AlertConditionOperator { - /* - * absolute value comparison operators - */ - LESS_THAN_OR_EQUAL_TO(Type.STATEFUL), // - LESS_THAN(Type.STATEFUL), // - EQUALS(Type.STATEFUL), // - REGEX(Type.STATELESS), // more flexible form of EQUALS - GREATER_THAN(Type.STATEFUL), // - GREATER_THAN_OR_EQUAL_TO(Type.STATEFUL), // - - /* - * operator based on state deltas - */ - CHANGES(Type.STATELESS), // state value changes in any way - CHANGES_TO(Type.STATELESS), // becomes one specific state value - CHANGES_FROM(Type.STATELESS); // leaves one specific state value - - private Type defaultType; - - /** - * For the most part, the operator itself denotes whether it makes comparisons against a sliding scale or not. - * However, this doesn't hold in every conceivable scenario. Thus, the defaultType will support 95% of the use - * cases, and the AbstractCacheElement's getOperatorType will have a chance to override this. - */ - AlertConditionOperator(Type defaultType) { - this.defaultType = defaultType; - } - - public Type getDefaultType() { - return defaultType; - } - - public enum Type { - /* - * stateful is used to support a sliding scale of values, usually a number line; once the stateful operator's - * condition threshold is met, stateful cache elements are disabled until the threshold is crossed once again - * into the expected range; - */ - STATEFUL, - - /* - * stateless can be used for anything stateful can, but will never be disabled in the cache; so, if you're - * worried about being able to suppress sliding-scale conditions once a threshold is meet, mark your operator - * as stateful - */ - STATELESS, - - /* - * CacheElement doesn't support the Operator if getOperatorSupportsType(Operator) is overridden to return NONE - */ - NONE; - } -} \ No newline at end of file diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/model/AvailabilityCacheElement.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/model/AvailabilityCacheElement.java index bee581c..5e55502 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/model/AvailabilityCacheElement.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/model/AvailabilityCacheElement.java @@ -18,6 +18,7 @@ */ package org.rhq.enterprise.server.alert.engine.model;
+import org.rhq.core.domain.alert.AlertConditionOperator; import org.rhq.core.domain.measurement.AvailabilityType;
/** @@ -25,8 +26,58 @@ import org.rhq.core.domain.measurement.AvailabilityType; */
public final class AvailabilityCacheElement extends AbstractEnumCacheElement<AvailabilityType> { - public AvailabilityCacheElement(AlertConditionOperator operator, AvailabilityType operatorOption, - AvailabilityType value, int conditionTriggerId) { - super(operator, operatorOption, value, conditionTriggerId); + + public AvailabilityCacheElement(AlertConditionOperator operator, AvailabilityType value, int conditionTriggerId) { + + super(operator, null, value, conditionTriggerId); + } + + @Override + public boolean matches(AvailabilityType providedValue, Object... extraParams) { + if (null == providedValue) { + return false; + } + + boolean result = false; + + switch (alertConditionOperator) { + case AVAIL_GOES_DOWN: + result = (AvailabilityType.DOWN == providedValue && AvailabilityType.DOWN != alertConditionValue); + break; + case AVAIL_GOES_NOT_UP: + result = (AvailabilityType.UP != providedValue && AvailabilityType.UP == alertConditionValue); + break; + case AVAIL_GOES_UP: + result = (AvailabilityType.UP == providedValue && AvailabilityType.UP != alertConditionValue); + break; + case AVAIL_GOES_DISABLED: + result = (AvailabilityType.DISABLED == providedValue && AvailabilityType.DISABLED != alertConditionValue); + break; + case AVAIL_GOES_UNKNOWN: + result = (AvailabilityType.UNKNOWN == providedValue && AvailabilityType.UNKNOWN != alertConditionValue); + break; + } + + alertConditionValue = providedValue; + + return result; + } + + @Override + public AlertConditionOperator.Type getOperatorSupportsType(AlertConditionOperator operator) { + switch (operator) { + case AVAIL_GOES_DOWN: + case AVAIL_GOES_NOT_UP: + case AVAIL_GOES_UP: + case AVAIL_GOES_DISABLED: + case AVAIL_GOES_UNKNOWN: + case AVAIL_DURATION_DOWN: + case AVAIL_DURATION_NOT_UP: + + return operator.getDefaultType(); + + default: + return AlertConditionOperator.Type.NONE; + } } } \ No newline at end of file diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/model/AvailabilityDurationCacheElement.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/model/AvailabilityDurationCacheElement.java new file mode 100644 index 0000000..beeafbd --- /dev/null +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/model/AvailabilityDurationCacheElement.java @@ -0,0 +1,170 @@ +/* + * RHQ Management Platform + * Copyright 2012, Red Hat Middleware LLC, and individual contributors + * as indicated by the @author tags. See the copyright.txt file in the + * distribution for a full listing of individual contributors. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +package org.rhq.enterprise.server.alert.engine.model; + +import java.text.DateFormat; +import java.util.Date; +import java.util.List; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.quartz.JobDataMap; +import org.quartz.SimpleTrigger; +import org.quartz.Trigger; + +import org.rhq.core.domain.alert.AlertConditionOperator; +import org.rhq.core.domain.measurement.AvailabilityType; +import org.rhq.core.domain.resource.Resource; +import org.rhq.enterprise.server.scheduler.jobs.AlertAvailabilityDurationJob; +import org.rhq.enterprise.server.util.LookupUtil; + +/** + * @author Jay Shaughnessy + */ + +public final class AvailabilityDurationCacheElement extends AbstractEnumCacheElement<AvailabilityType> { + + /** + * @param operator + * @param operatorOption the duration, in minutes (as String) + * @param value + * @param conditionTriggerId this is actually the alertConditionId, renamed here. + */ + public AvailabilityDurationCacheElement(AlertConditionOperator operator, String operatorOption, + AvailabilityType value, int conditionTriggerId) { + + super(operator, operatorOption, value, conditionTriggerId); + } + + /** + * Here we check to see if an availability change for a resource should initiate an avail duration check. For + * each relevant avail duration condition for the resource schedule a job to check the avail state after the + * condition's duration. + * + * @param cacheElements + * @param resource + * @param providedValue + */ + public static void checkCacheElements(List<AvailabilityDurationCacheElement> cacheElements, Resource resource, + AvailabilityType providedValue) { + if (null == cacheElements) { + return; // nothing to do + } + + for (AvailabilityDurationCacheElement cacheElement : cacheElements) { + switch (cacheElement.getAlertConditionOperator()) { + case AVAIL_DURATION_DOWN: + if (AvailabilityType.DOWN == providedValue + && AvailabilityType.DOWN != cacheElement.getAlertConditionValue()) { + + scheduleAvailabilityDurationCheck(cacheElement, resource); + } + break; + case AVAIL_DURATION_NOT_UP: + if (AvailabilityType.UP != providedValue + && AvailabilityType.UP == cacheElement.getAlertConditionValue()) { + + scheduleAvailabilityDurationCheck(cacheElement, resource); + } + break; + } + + cacheElement.setAlertConditionValue(providedValue); + } + } + + /** + * Each avail duration check is performed by triggering an execution of {@link AlertAvailabilityDurationJob}. + * Note that each of the scheduled jobs is relevant to only 1 condition evaluation. + * + * @param cacheElement + * @param resource + */ + private static void scheduleAvailabilityDurationCheck(AvailabilityDurationCacheElement cacheElement, + Resource resource) { + + Log log = LogFactory.getLog(AvailabilityDurationCacheElement.class.getName()); + String jobName = AlertAvailabilityDurationJob.class.getName(); + String jobGroupName = AlertAvailabilityDurationJob.class.getName(); + String operator = cacheElement.getAlertConditionOperator().name(); + String triggerName = operator + "-" + resource.getId(); + String duration = (String) cacheElement.getAlertConditionOperatorOption(); + Date jobTime = new Date(System.currentTimeMillis() + (Long.valueOf(duration).longValue() * 60 * 1000)); + + if (log.isDebugEnabled()) { + log.debug("Scheduling availability duration job for [" + DateFormat.getDateTimeInstance().format(jobTime) + + "]"); + } + + JobDataMap jobDataMap = new JobDataMap(); + // the condition id is needed to ensure we limit the future avail checking to the one relevant alert condition + jobDataMap.put(AlertAvailabilityDurationJob.DATAMAP_CONDITION_ID, + String.valueOf(cacheElement.getAlertConditionTriggerId())); + jobDataMap.put(AlertAvailabilityDurationJob.DATAMAP_RESOURCE_ID, String.valueOf(resource.getId())); + jobDataMap.put(AlertAvailabilityDurationJob.DATAMAP_OPERATOR, operator); + jobDataMap.put(AlertAvailabilityDurationJob.DATAMAP_DURATION, duration); + + Trigger trigger = new SimpleTrigger(triggerName, jobGroupName, jobTime); + trigger.setJobName(jobName); + trigger.setJobGroup(jobGroupName); + trigger.setJobDataMap(jobDataMap); + try { + LookupUtil.getSchedulerBean().scheduleJob(trigger); + } catch (Throwable t) { + log.warn( + "Unable to schedule availability duration job for [" + resource + "] with JobData [" + + jobDataMap.values() + "]", t); + } + } + + @Override + public boolean matches(AvailabilityType providedValue, Object... extraParams) { + if (null == providedValue) { + return false; + } + + boolean result = false; + + switch (alertConditionOperator) { + case AVAIL_DURATION_DOWN: + result = (AvailabilityType.DOWN == providedValue); + break; + case AVAIL_DURATION_NOT_UP: + result = (AvailabilityType.UP != providedValue); + break; + } + + alertConditionValue = providedValue; + + return result; + } + + @Override + public AlertConditionOperator.Type getOperatorSupportsType(AlertConditionOperator operator) { + switch (operator) { + case AVAIL_DURATION_DOWN: + case AVAIL_DURATION_NOT_UP: + return operator.getDefaultType(); + + default: + return AlertConditionOperator.Type.NONE; + } + } +} diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/model/AvailabilityDurationComposite.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/model/AvailabilityDurationComposite.java new file mode 100644 index 0000000..43b4f81 --- /dev/null +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/model/AvailabilityDurationComposite.java @@ -0,0 +1,66 @@ +/* + * RHQ Management Platform + * Copyright 2012, Red Hat Middleware LLC, and individual contributors + * as indicated by the @author tags. See the copyright.txt file in the + * distribution for a full listing of individual contributors. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +package org.rhq.enterprise.server.alert.engine.model; + +import org.rhq.core.domain.alert.AlertConditionOperator; +import org.rhq.core.domain.measurement.AvailabilityType; + +/** + * @author Jay Shaughnessy + */ +public class AvailabilityDurationComposite { + private int conditionId; + private AlertConditionOperator operator; + private int resourceId; + private AvailabilityType availabilityType; + private long duration; + + public AvailabilityDurationComposite(int conditionId, AlertConditionOperator operator, int resourceId, + AvailabilityType availabilityType, long duration) { + super(); + this.conditionId = conditionId; + this.operator = operator; + this.resourceId = resourceId; + this.availabilityType = availabilityType; + this.duration = duration; + } + + public int getConditionId() { + return conditionId; + } + + public AlertConditionOperator getOperator() { + return operator; + } + + public int getResourceId() { + return resourceId; + } + + public AvailabilityType getAvailabilityType() { + return availabilityType; + } + + public long getDuration() { + return duration; + } + +} diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/model/CallTimeDataCacheElement.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/model/CallTimeDataCacheElement.java index d013af5..bc2f573 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/model/CallTimeDataCacheElement.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/model/CallTimeDataCacheElement.java @@ -4,6 +4,7 @@ import java.text.DateFormat; import java.util.concurrent.ConcurrentHashMap; import java.util.regex.Pattern;
+import org.rhq.core.domain.alert.AlertConditionOperator; import org.rhq.core.domain.measurement.calltime.CallTimeDataValue;
/** diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/model/DriftCacheElement.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/model/DriftCacheElement.java index 90dd613..8bbbaf7 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/model/DriftCacheElement.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/model/DriftCacheElement.java @@ -20,6 +20,7 @@ package org.rhq.enterprise.server.alert.engine.model;
import java.util.regex.Pattern;
+import org.rhq.core.domain.alert.AlertConditionOperator; import org.rhq.core.domain.drift.DriftChangeSetCategory; import org.rhq.enterprise.server.plugin.pc.drift.DriftChangeSetSummary;
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/model/EventCacheElement.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/model/EventCacheElement.java index bbbc006..755ff20 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/model/EventCacheElement.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/model/EventCacheElement.java @@ -20,6 +20,7 @@ package org.rhq.enterprise.server.alert.engine.model;
import java.util.regex.Pattern;
+import org.rhq.core.domain.alert.AlertConditionOperator; import org.rhq.core.domain.event.EventSeverity;
/** diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/model/MeasurementBaselineCacheElement.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/model/MeasurementBaselineCacheElement.java index 429a693..43903d5 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/model/MeasurementBaselineCacheElement.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/model/MeasurementBaselineCacheElement.java @@ -18,6 +18,8 @@ */ package org.rhq.enterprise.server.alert.engine.model;
+import org.rhq.core.domain.alert.AlertConditionOperator; + /** * @author Joseph Marques */ diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/model/MeasurementNumericCacheElement.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/model/MeasurementNumericCacheElement.java index 0b66ba8..d9ab523 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/model/MeasurementNumericCacheElement.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/model/MeasurementNumericCacheElement.java @@ -18,6 +18,8 @@ */ package org.rhq.enterprise.server.alert.engine.model;
+import org.rhq.core.domain.alert.AlertConditionOperator; + /** * @author Joseph Marques */ diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/model/MeasurementRangeNumericCacheElement.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/model/MeasurementRangeNumericCacheElement.java index c5439e0..1d5ae34 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/model/MeasurementRangeNumericCacheElement.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/model/MeasurementRangeNumericCacheElement.java @@ -18,6 +18,8 @@ */ package org.rhq.enterprise.server.alert.engine.model;
+import org.rhq.core.domain.alert.AlertConditionOperator; + public class MeasurementRangeNumericCacheElement extends MeasurementNumericCacheElement {
public MeasurementRangeNumericCacheElement(AlertConditionOperator operator, Double loValue, Double hiValue, diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/model/MeasurementTraitCacheElement.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/model/MeasurementTraitCacheElement.java index 1632eca..a30b3d7 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/model/MeasurementTraitCacheElement.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/model/MeasurementTraitCacheElement.java @@ -18,6 +18,8 @@ */ package org.rhq.enterprise.server.alert.engine.model;
+import org.rhq.core.domain.alert.AlertConditionOperator; + /** * @author Joseph Marques */ diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/model/NumericDoubleCacheElement.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/model/NumericDoubleCacheElement.java index bee3fe1..d0ef1ab 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/model/NumericDoubleCacheElement.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/model/NumericDoubleCacheElement.java @@ -18,6 +18,8 @@ */ package org.rhq.enterprise.server.alert.engine.model;
+import org.rhq.core.domain.alert.AlertConditionOperator; + /** * @author Joseph Marques */ diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/model/ResourceConfigurationCacheElement.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/model/ResourceConfigurationCacheElement.java index 1e72046..d05960a 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/model/ResourceConfigurationCacheElement.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/model/ResourceConfigurationCacheElement.java @@ -18,6 +18,7 @@ */ package org.rhq.enterprise.server.alert.engine.model;
+import org.rhq.core.domain.alert.AlertConditionOperator; import org.rhq.core.domain.configuration.Configuration;
/** diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/model/ResourceOperationCacheElement.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/model/ResourceOperationCacheElement.java index 878d9e1..d0d8ee6 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/model/ResourceOperationCacheElement.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/model/ResourceOperationCacheElement.java @@ -18,6 +18,7 @@ */ package org.rhq.enterprise.server.alert.engine.model;
+import org.rhq.core.domain.alert.AlertConditionOperator; import org.rhq.core.domain.operation.OperationRequestStatus;
/** diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/model/StringCacheElement.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/model/StringCacheElement.java index a570318..30e464c 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/model/StringCacheElement.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/engine/model/StringCacheElement.java @@ -20,6 +20,8 @@ package org.rhq.enterprise.server.alert.engine.model;
import java.util.regex.Pattern;
+import org.rhq.core.domain.alert.AlertConditionOperator; + /** * @author Joseph Marques */ diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/AvailabilityManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/AvailabilityManagerBean.java index 2c8d376..07dc3bf 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/AvailabilityManagerBean.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/AvailabilityManagerBean.java @@ -611,7 +611,7 @@ public class AvailabilityManagerBean implements AvailabilityManagerLocal, Availa
resourceAvailabilityManager.updateAgentResourcesLatestAvailability(agentId, childAvailType, false);
- // To handle backfilling process, which will mark them down + // To handle backfilling process, which will mark them unknown notifyAlertConditionCacheManager("setAllAgentResourceAvailabilities", newAvailabilities.toArray(new Availability[newAvailabilities.size()]));
@@ -796,6 +796,8 @@ public class AvailabilityManagerBean implements AvailabilityManagerLocal, Availa private void notifyAlertConditionCacheManager(String callingMethod, Availability... availabilities) { AlertConditionCacheStats stats = alertConditionCacheManager.checkConditions(availabilities);
- log.debug(callingMethod + ": " + stats.toString()); + if (log.isDebugEnabled()) { + log.debug(callingMethod + ": " + stats.toString()); + } } } \ No newline at end of file diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/scheduler/EnhancedScheduler.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/scheduler/EnhancedScheduler.java index b10f627..bd8e3a1 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/scheduler/EnhancedScheduler.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/scheduler/EnhancedScheduler.java @@ -22,6 +22,7 @@ import org.quartz.Job; import org.quartz.JobDataMap; import org.quartz.Scheduler; import org.quartz.SchedulerException; +import org.quartz.Trigger;
/** * An enhanced scheduler interface that provides the normal scheduler API with some additional convenience methods. @@ -153,4 +154,30 @@ public interface EnhancedScheduler extends Scheduler { */ public void scheduleSimpleCronJob(Class<? extends Job> jobClass, boolean rescheduleIfExists, boolean isVolatile, String cronString) throws SchedulerException; + + /** + * Schedules the job with the given triggger. If the trigger is null then the durable job is simply created, + * if necessary, and will await future triggers. + * + * <p>This is a convienence method for adding a trigger to a job. There is no job-level {@link JobDataMap} but + * each trigger may contain a trigger-specific {@link JobDataMap}.</p> + * + * <p>This method delegates to {@link #addJob(org.quartz.JobDetail, boolean)} where the <code> + * name</code> is the name of the given class (<code>jobClass.getName()</code>) and <code>replace</code> is + * false. If <code>trigger</code> is not null, then + * {@link Scheduler#scheduleJob(org.quartz.JobDetail, org.quartz.Trigger)} will be called to schedule the job.</p> + * + * @param jobClass the class of the job that will be executed when the trigger fires + * @param trigger an optional trigger for firing the job + * + * @throws SchedulerException + * + * @see SchedulerServiceMBean#addJob(org.quartz.JobDetail, boolean) + * @param isVolatile if <code>false</code>, the job will be persisted to the database; if <code> + * true</code>, when the scheduler is shutdown, the job's schedule is lost + * @see SchedulerServiceMBean#scheduleJob(org.quartz.JobDetail, org.quartz.Trigger) + */ + void scheduleTriggeredJob(Class<? extends Job> jobClass, boolean isVolatile, Trigger trigger) + throws SchedulerException; + } \ No newline at end of file diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/scheduler/EnhancedSchedulerImpl.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/scheduler/EnhancedSchedulerImpl.java index 47168e6..2dd1083 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/scheduler/EnhancedSchedulerImpl.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/scheduler/EnhancedSchedulerImpl.java @@ -46,6 +46,7 @@ import org.quartz.spi.JobFactory; * Wraps a Quartz scheduler and provides some enhanced scheduler methods. */ public class EnhancedSchedulerImpl implements EnhancedScheduler { + @SuppressWarnings("unused") private static final long serialVersionUID = 1L; private final Log log = LogFactory.getLog(EnhancedSchedulerImpl.class.getName()); private final Scheduler scheduler; @@ -64,11 +65,12 @@ public class EnhancedSchedulerImpl implements EnhancedScheduler { // either remove it so we can reschedule it or keep it (based on rescheduleIfExists). JobDetail existingJob = getExistingJob(name, groupName, rescheduleIfExists); if (existingJob != null) { - if (rescheduleIfExists) { + if (rescheduleIfExists) { log.debug("Looks like repeating job [" + name + ':' + groupName + "] is already scheduled - removing it so it can be rescheduled..."); if (!this.scheduler.deleteJob(name, groupName)) { - throw new SchedulerException("Failed to delete repeating job [" + existingJob + "] in order to reschedule it."); + throw new SchedulerException("Failed to delete repeating job [" + existingJob + + "] in order to reschedule it."); } } else { log.debug("Looks like repeating job [" + name + ':' + groupName @@ -97,11 +99,11 @@ public class EnhancedSchedulerImpl implements EnhancedScheduler { // either remove it so we can reschedule it or keep it (based on rescheduleIfExists). JobDetail existingJob = getExistingJob(name, groupName, rescheduleIfExists); if (existingJob != null) { - if (rescheduleIfExists) { + if (rescheduleIfExists) { log.debug("Looks like cron job [" + name + ':' + groupName + "] is already scheduled - removing it so it can be rescheduled..."); - deleteJob(name, groupName, existingJob); - } else { + deleteJob(name, groupName, existingJob); + } else { log.debug("Looks like cron job [" + name + ':' + groupName + "] is already scheduled - leaving the original job as-is."); return; @@ -452,7 +454,7 @@ public class EnhancedSchedulerImpl implements EnhancedScheduler { deleteJob(name, groupName, null); } catch (SchedulerException e1) { log.error("Failed to delete job [" + name + ":" + groupName + "] with invalid job class (as per " - + cause + ")", e1); + + cause + ")", e1); } } else { log.error("Error while attempting to lookup job [" + name + ":" + groupName + "].", e); @@ -470,14 +472,14 @@ public class EnhancedSchedulerImpl implements EnhancedScheduler { }
private JobDetail createJobDetail(String name, String groupName, Class<? extends Job> jobClass, boolean isVolatile, - JobDataMap jobData) { + JobDataMap jobData) { JobDetail job = new JobDetail(name, groupName, jobClass, isVolatile, false, false); job.setJobDataMap(jobData); return job; }
private SimpleTrigger createSimpleTrigger(String name, String groupName, boolean isVolatile, long initialDelay, - long interval) { + long interval) { Date start = new Date(System.currentTimeMillis() + initialDelay); SimpleTrigger trigger = new SimpleTrigger(name, groupName, start, null, SimpleTrigger.REPEAT_INDEFINITELY, interval); @@ -486,7 +488,7 @@ public class EnhancedSchedulerImpl implements EnhancedScheduler { }
private CronTrigger createCronTrigger(String name, String groupName, boolean isVolatile, String cronString) - throws SchedulerException { + throws SchedulerException { CronTrigger trigger; try { trigger = new CronTrigger(name, groupName, name, groupName, cronString); @@ -496,4 +498,28 @@ public class EnhancedSchedulerImpl implements EnhancedScheduler { trigger.setVolatility(isVolatile); return trigger; } + + @Override + public void scheduleTriggeredJob(Class<? extends Job> jobClass, boolean isVolatile, Trigger trigger) + throws SchedulerException { + + String name = jobClass.getName(); + String groupName = name; + + // See if the job exists, if not, add it. + JobDetail existingJob = getExistingJob(name, groupName, false); + if (null == existingJob) { + JobDetail job = new JobDetail(name, groupName, jobClass, isVolatile, true, false); + this.scheduler.addJob(job, false); + } + + if (null != trigger) { + if (null == existingJob) { + existingJob = getExistingJob(name, groupName, false); + } + this.scheduler.scheduleJob(existingJob, trigger); + } + + return; + } } \ No newline at end of file diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/scheduler/SchedulerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/scheduler/SchedulerBean.java index da52c2c..baf3663 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/scheduler/SchedulerBean.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/scheduler/SchedulerBean.java @@ -50,6 +50,7 @@ import org.jboss.mx.util.MBeanServerLocator; */ @Stateless public class SchedulerBean implements SchedulerLocal { + @SuppressWarnings("unused") private static final long serialVersionUID = 1L; private final Log log = LogFactory.getLog(SchedulerBean.class.getName());
@@ -63,8 +64,8 @@ public class SchedulerBean implements SchedulerLocal { */ private SchedulerServiceMBean getSchedulerService() throws SchedulerException { try { - return (SchedulerServiceMBean) MBeanServerInvocationHandler.newProxyInstance(MBeanServerLocator - .locateJBoss(), SCHEDULER_MBEAN_NAME, SchedulerServiceMBean.class, false); + return (SchedulerServiceMBean) MBeanServerInvocationHandler.newProxyInstance( + MBeanServerLocator.locateJBoss(), SCHEDULER_MBEAN_NAME, SchedulerServiceMBean.class, false); } catch (Exception e) { throw new SchedulerException("Failed to get a proxy to the scheduler service MBean", e); } @@ -450,4 +451,12 @@ public class SchedulerBean implements SchedulerLocal { public void startDelayed(int delay) throws SchedulerException { getSchedulerService().startDelayed(delay); } + + @Override + public void scheduleTriggeredJob(Class<? extends Job> jobClass, boolean isVolatile, Trigger trigger) + throws SchedulerException { + + new EnhancedSchedulerImpl(getSchedulerService()).scheduleTriggeredJob(jobClass, isVolatile, trigger); + return; + } } \ No newline at end of file diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/scheduler/jobs/AlertAvailabilityDurationJob.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/scheduler/jobs/AlertAvailabilityDurationJob.java new file mode 100644 index 0000000..4998d01 --- /dev/null +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/scheduler/jobs/AlertAvailabilityDurationJob.java @@ -0,0 +1,88 @@ +/* + * RHQ Management Platform + * Copyright 2012, Red Hat Middleware LLC, and individual contributors + * as indicated by the @author tags. See the copyright.txt file in the + * distribution for a full listing of individual contributors. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +package org.rhq.enterprise.server.scheduler.jobs; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.quartz.JobDataMap; +import org.quartz.JobExecutionContext; +import org.quartz.JobExecutionException; + +import org.rhq.core.domain.alert.AlertConditionOperator; +import org.rhq.core.domain.measurement.AvailabilityType; +import org.rhq.core.domain.measurement.ResourceAvailability; +import org.rhq.enterprise.server.alert.engine.AlertConditionCacheStats; +import org.rhq.enterprise.server.alert.engine.model.AvailabilityDurationComposite; +import org.rhq.enterprise.server.util.LookupUtil; + +/** + * @author Jay Shaughnessy + */ +public class AlertAvailabilityDurationJob extends AbstractStatefulJob { + private static final Log LOG = LogFactory.getLog(AlertAvailabilityDurationJob.class); + + public static final String DATAMAP_CONDITION_ID = "alertConditionId"; + public static final String DATAMAP_DURATION = "duration"; + public static final String DATAMAP_OPERATOR = "alertConditionOperator"; + public static final String DATAMAP_RESOURCE_ID = "resourceId"; + + @Override + public void executeJobCode(JobExecutionContext context) throws JobExecutionException { + JobDataMap jobDataMap = context.getTrigger().getJobDataMap(); + int conditionId = Integer.valueOf(jobDataMap.getString(DATAMAP_CONDITION_ID)); + int resourceId = Integer.valueOf(jobDataMap.getString(DATAMAP_RESOURCE_ID)); + long duration = Long.valueOf(jobDataMap.getString(DATAMAP_DURATION)); + AlertConditionOperator operator = AlertConditionOperator.valueOf(jobDataMap.getString(DATAMAP_OPERATOR)); + + // get the current resource availability + ResourceAvailability resourceAvail = LookupUtil.getResourceAvailabilityManager().getLatestAvailability( + resourceId); + AvailabilityType availType = resourceAvail.getAvailabilityType(); + + // Question? Do we care whether the avail type has been the same for the entire duration (meaning we would need + // to go and find the most recent Availability record)? Or do we only care if it is currently at the avail + // type that matters? For now we'll go with the latter approach and ignore whether the avail actually + // changed during the specified duration. + + boolean checkConditions = false; + switch (operator) { + case AVAIL_DURATION_DOWN: + checkConditions = (AvailabilityType.DOWN == availType); + break; + case AVAIL_DURATION_NOT_UP: + checkConditions = (AvailabilityType.UP != availType); + break; + } + + // the call to checkConditions will probably result in an alert, as the actual condition satisfaction was + // just done. but we need to actually hook into the alerting chassis to ensure any other conditions are + // still satisfied and to make sure all the alert processing is performed. + if (checkConditions) { + AvailabilityDurationComposite composite = new AvailabilityDurationComposite(conditionId, operator, + resourceId, availType, duration); + AlertConditionCacheStats stats = LookupUtil.getAlertConditionCacheManager().checkConditions(composite); + + if (LOG.isDebugEnabled()) { + LOG.debug("AlertAvailabilityDurationJob: " + stats.toString()); + } + } + } +} diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/alert/engine/model/MeasurementRangeNumericCacheElementTest.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/alert/engine/model/MeasurementRangeNumericCacheElementTest.java index 075b510..eb01b1c 100644 --- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/alert/engine/model/MeasurementRangeNumericCacheElementTest.java +++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/alert/engine/model/MeasurementRangeNumericCacheElementTest.java @@ -21,6 +21,8 @@ package org.rhq.enterprise.server.alert.engine.model;
import org.testng.annotations.Test;
+import org.rhq.core.domain.alert.AlertConditionOperator; + /** * there are two ways we can check the value compared to the range, each with either inclusivness or exclusivness. * inclusive means if value equals either the lo or hi, it is considered inside the range.