/* * RHQ Management Platform * Copyright (C) 2005-2014 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., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ package org.rhq.core.domain.measurement; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.NamedQueries; import javax.persistence.NamedQuery; import javax.persistence.Table; /** * Store for OOB related data * * @author Heiko W. Rupp */ @NamedQueries({ @NamedQuery(name = MeasurementOOB.GET_SCHEDULES_WITH_OOB_AGGREGATE, query = "" // + " SELECT new org.rhq.core.domain.measurement.composite.MeasurementOOBComposite" // + " ( res.name, res.id, res.ancestry, res.resourceType.id, def.displayName, sched.id, o.timestamp, def.id, o.oobFactor, " // + " bal.baselineMin, bal.baselineMax, def.units, parent.name, parent.id) " // + " FROM MeasurementOOB o, MeasurementSchedule sched " // + "LEFT JOIN sched.definition def " // + "LEFT JOIN sched.resource res " // + "LEFT JOIN sched.baseline bal " // + "LEFT JOIN res.parentResource parent " // + " WHERE o.id = sched.id " // + " AND res.inventoryStatus = 'COMMITTED' " // + " AND sched.definition = def " // + " AND sched.resource = res " // + " AND bal.schedule = sched " // + " AND res.id IN ( SELECT rr.id FROM Resource rr " // + " JOIN rr.implicitGroups g JOIN g.roles r JOIN r.subjects s " // + " WHERE s.id = :subjectId ) " // + " AND (UPPER(def.displayName ) LIKE :metricName ESCAPE :escapeChar OR :metricName is null ) " // + " AND (UPPER(res.name) LIKE :resourceName ESCAPE :escapeChar OR :resourceName is null ) " // + " AND (UPPER(parent.name) LIKE :parentName ESCAPE :escapeChar OR :parentName is null ) "), // @NamedQuery(name = MeasurementOOB.GET_SCHEDULES_WITH_OOB_AGGREGATE_ADMIN, query = "" // + " SELECT new org.rhq.core.domain.measurement.composite.MeasurementOOBComposite" // + " ( res.name, res.id, res.ancestry, res.resourceType.id, def.displayName, sched.id, o.timestamp, def.id, o.oobFactor, " // + " bal.baselineMin, bal.baselineMax, def.units, parent.name, parent.id) " // + " FROM MeasurementOOB o, MeasurementSchedule sched " // + "LEFT JOIN sched.definition def " // + "LEFT JOIN sched.resource res " // + "LEFT JOIN sched.baseline bal " // + "LEFT JOIN res.parentResource parent " // + " WHERE o.id = sched.id " // + " AND res.inventoryStatus = 'COMMITTED' " // + " AND sched.definition = def " // + " AND sched.resource = res " // + " AND bal.schedule = sched " // + " AND (UPPER(def.displayName ) LIKE :metricName ESCAPE :escapeChar OR :metricName is null ) " // + " AND (UPPER(res.name) LIKE :resourceName ESCAPE :escapeChar OR :resourceName is null ) " // + " AND (UPPER(parent.name) LIKE :parentName ESCAPE :escapeChar OR :parentName is null ) "), // @NamedQuery(name = MeasurementOOB.GET_SCHEDULES_WITH_OOB_AGGREGATE_COUNT, query = "" // + " SELECT COUNT(sched.id) " // + " FROM MeasurementOOB o, MeasurementSchedule sched " // + "LEFT JOIN sched.definition def " // + "LEFT JOIN sched.resource res " // + "LEFT JOIN res.parentResource parent " // + " WHERE o.id = sched.id " // + " AND res.inventoryStatus = 'COMMITTED' " // + " AND sched.definition = def " // + " AND sched.resource = res " // + " AND (UPPER(def.displayName ) LIKE :metricName OR :metricName is null ) " // + " AND (UPPER(res.name) LIKE :resourceName OR :resourceName is null ) " // + " AND (UPPER(parent.name) LIKE :parentName OR :parentName is null ) "), // @NamedQuery(name = MeasurementOOB.DELETE_OUTDATED, query = "" // + "DELETE FROM MeasurementOOB o " // + " WHERE o.id IN ( SELECT b.schedule.id " // + " FROM MeasurementBaseline b " // + " WHERE b.computeTime > :cutOff )"), // @NamedQuery(name = MeasurementOOB.COUNT_FOR_DATE, query = "" // + "SELECT COUNT(o.timestamp) " // + " FROM MeasurementOOB o " // + " WHERE o.timestamp = :timestamp"), // @NamedQuery(name = MeasurementOOB.DELETE_FOR_SCHEDULE, query = "" // + "DELETE FROM MeasurementOOB o " // + " WHERE o.id = :id"), // @NamedQuery(name = MeasurementOOB.DELETE_FOR_GROUP_AND_DEFINITION, query = "" // + "DELETE FROM MeasurementOOB o " // + " WHERE o.id IN ( SELECT ms.id " // + " FROM MeasurementSchedule ms " // + " JOIN ms.resource res " // + " JOIN res.implicitGroups rg " // + " WHERE rg.id = :groupId " // + " AND ms.definition.id = :definitionId )"), // @NamedQuery(name = MeasurementOOB.DELETE_FOR_RESOURCES, query = "" // + "DELETE FROM MeasurementOOB o " // + " WHERE o.id IN ( SELECT ms.id " // + " FROM MeasurementSchedule ms " // + " WHERE ms.resource.id IN ( :resourceIds ) )"), // @NamedQuery(name = MeasurementOOB.GET_HIGHEST_FACTORS_FOR_RESOURCE, query = "" // + " SELECT new org.rhq.core.domain.measurement.composite.MeasurementOOBComposite" // + " ( res.name, res.id, res.ancestry, res.resourceType.id, def.displayName, sched.id, o.timestamp, def.id, o.oobFactor, " // + " bal.baselineMin , bal.baselineMax, def.units ) " // + " FROM MeasurementOOB o, MeasurementSchedule sched " // + "LEFT JOIN sched.definition def " // + "LEFT JOIN sched.resource res " // + "LEFT JOIN sched.baseline bal " // + " WHERE o.id = sched.id " // + " AND sched.definition = def " // + " AND sched.resource = res " // + " AND bal.schedule = sched " // + " AND :resourceId = res.id "), // @NamedQuery(name = MeasurementOOB.GET_HIGHEST_FACTORS_FOR_GROUP, query = "" // + " SELECT new org.rhq.core.domain.measurement.composite.MeasurementOOBComposite" // + " ( res.name, res.id, res.ancestry, res.resourceType.id, def.displayName, sched.id, o.timestamp, def.id, o.oobFactor, " // + " bal.baselineMin , bal.baselineMax, def.units ) " // + " FROM MeasurementOOB o, MeasurementSchedule sched " // + "LEFT JOIN sched.definition def " // + "LEFT JOIN sched.resource res " // + "LEFT JOIN sched.baseline bal " // + "LEFT JOIN sched.resource.explicitGroups ig " // + " WHERE o.id = sched.id " // + " AND sched.definition = def " // + " AND sched.resource = res " // + " AND bal.schedule = sched " // + " AND :groupId = ig.id ") }) @Entity @Table(name = "RHQ_MEASUREMENT_OOB") public class MeasurementOOB { public static final String GET_SCHEDULES_WITH_OOB_AGGREGATE = "GetSchedulesWithOObAggregate"; public static final String GET_SCHEDULES_WITH_OOB_AGGREGATE_ADMIN = "GetSchedulesWithOObAggregate_admin"; public static final String GET_SCHEDULES_WITH_OOB_AGGREGATE_COUNT = "GetSchedulesWithOObAggregateCount"; /** * @deprecated as of RHQ 4.13, no longer used */ @Deprecated public static final String DELETE_OUTDATED = "DeleteOutdatedOOBs"; public static final String COUNT_FOR_DATE = "CountOOBForDate"; public static final String GET_HIGHEST_FACTORS_FOR_RESOURCE = "GetHighestOOBFactorForResource"; public static final String GET_HIGHEST_FACTORS_FOR_GROUP = "GetHighestOOBFactorForGroup"; public static final String DELETE_FOR_GROUP_AND_DEFINITION = "DeleteOOBForGroupAndDefinition"; public static final String DELETE_FOR_SCHEDULE = "DeleteOOBForSchedule"; public static final String DELETE_FOR_RESOURCES = "DeleteOOBForResurces"; /* * (Jan 16, 2009) - The new OOB system uses a threshold to determine whether a metric is a "problem" or not. * The current threshold is a static value - 0.1 - and does not change based on any characteristic * of the metric data collected. Dynamic metrics, however, can have either naturally narrow or * naturally wide baseline ranges; this makes the static threshold of 0.1 either too sensitive * or not sensitive enough, respectively. The next improvement to the baseline system probably * needs to use a sliding scale for this threshold, to more accurately characterize "problem" * metrics across varying magnitudes of metric baseline deltas. */ public static final String INSERT_QUERY = "" // + "INSERT INTO rhq_measurement_oob_tmp (oob_factor, schedule_id, time_stamp ) \n" // + " ( SELECT max(mx*100) as mxdiff, id, ? \n" // ?1 = begin + " FROM ( SELECT max(((d.maxvalue - b.bl_max) / (b.bl_max - b.bl_min))) AS mx, d.schedule_id as id \n" // + " FROM rhq_measurement_bline b, rhq_measurement_data_num_1h d, rhq_measurement_sched sc, rhq_measurement_def def \n" // + " WHERE b.schedule_id = d.schedule_id \n" // + " AND sc.id = b.schedule_id \n" // + " AND d.value > b.bl_max \n" // + " AND d.time_stamp = ? \n" // ?2 = begin + " AND (b.bl_max - b.bl_min) > 0.1 \n" // + " AND (d.maxvalue - b.bl_max) >0 \n " // + " AND sc.enabled = %TRUE% \n" // + " AND sc.definition = def.id \n" // + " AND def.numeric_type = 0 \n" // Only dynamic metrics + " GROUP BY d.schedule_id \n" // + "UNION ALL \n" // + " SELECT max(((b.bl_min - d.minvalue) / (b.bl_max - b.bl_min))) AS mx, d.schedule_id as id \n" // + " FROM rhq_measurement_bline b, rhq_measurement_data_num_1h d, rhq_measurement_sched sc, rhq_measurement_def def \n" // + " WHERE b.schedule_id = d.schedule_id \n" // + " AND sc.id = b.schedule_id \n" // + " AND d.value < b.bl_max \n" // + " AND d.time_stamp = ? \n" // ?3 = begin + " AND (b.bl_max - b.bl_min) > 0.1 \n" // + " AND (b.bl_min - d.minvalue) >0 \n" // + " AND sc.enabled = %TRUE% \n" // + " AND sc.definition = def.id \n" // + " AND def.numeric_type = 0 \n" // + " GROUP BY d.schedule_id \n" // + " ) data \n" // + "GROUP BY id, mx \n" // + " HAVING mx > 0.05 )"; public static final String UPDATE_MASTER_POSTGRES = "" // + "UPDATE rhq_measurement_oob \n" + " SET oob_factor = rhq_measurement_oob_tmp.oob_factor,time_stamp=rhq_measurement_oob_tmp.time_stamp \n" + " FROM rhq_measurement_oob_tmp \n" + " WHERE rhq_measurement_oob_tmp.oob_factor > rhq_measurement_oob.oob_factor \n" + " AND rhq_measurement_oob_tmp.schedule_id = rhq_measurement_oob.schedule_id "; public static final String MERGE_TABLES_ORACLE = "" // + "MERGE INTO rhq_measurement_oob oob_ \n" // + " USING rhq_measurement_oob_tmp tmp_ \n" // + " ON ( tmp_.schedule_id = oob_.schedule_id ) \n" + " WHEN MATCHED THEN UPDATE SET oob_factor = tmp_.oob_factor, time_stamp = tmp_.time_stamp \n" + " WHEN NOT MATCHED THEN INSERT ( oob_.schedule_id, oob_.time_stamp, oob_.oob_factor ) \n" + " VALUES ( tmp_.schedule_id, tmp_.time_stamp, tmp_.oob_factor )"; /* * H2 syntax doesn't support the more complex SET...FROM...WHERE like Postgres, and although it does support * MERGE it doesn't support the WHEN [NOT] MATCHED syntax; so we'll just delete any and all OOBs that have become * obsolete, and follow that up with a call to INSERT_NEW_ONES, which should give us the same effect as row updates */ public static final String UPDATE_MASTER_GENERIC = "" // + "DELETE FROM rhq_measurement_oob \n" // + " WHERE EXISTS ( SELECT oob_tmp.schedule_id \n" // + " FROM rhq_measurement_oob_tmp oob_tmp \n" // + " WHERE oob_tmp.oob_factor > rhq_measurement_oob.oob_factor \n" // + " AND oob_tmp.schedule_id = rhq_measurement_oob.schedule_id ) "; public static final String INSERT_NEW_ONES = "" // + "INSERT INTO rhq_measurement_oob (oob_factor, schedule_id, time_stamp) \n" + " ( SELECT oob_factor, schedule_id, time_stamp \n" + " FROM rhq_measurement_oob_tmp \n" + " WHERE NOT EXISTS ( SELECT rhq_measurement_oob.schedule_id \n " + " FROM rhq_measurement_oob \n " + " WHERE rhq_measurement_oob.schedule_id = rhq_measurement_oob_tmp.schedule_id ) )"; /** * @deprecated as of RHQ 4.13, no longer used */ @Deprecated public static final String TRUNCATE_TMP_TABLE = "TRUNCATE TABLE rhq_measurement_oob_tmp"; /** * @deprecated as of RHQ 4.13, no longer used */ @Deprecated public static final String SECURITY_ADDITION = "" // + " AND ( res.id IN ( SELECT rr.id FROM Resource rr " // + " JOIN rr.implicitGroups g JOIN g.roles r JOIN r.subjects s " // + " WHERE s.id = :subjectId ) ) "; private static final long serialVersionUID = 1L; @Id @Column(name = "SCHEDULE_ID") int id; @Column(name = "TIME_STAMP") long timestamp; /** * The 'severity' of the violation. Original data is double, but we * don't need that precision here, so use an int to conserve space */ @Column(name = "OOB_FACTOR") private int oobFactor; public MeasurementOOB() { } public int getScheduleId() { return id; } public void setScheduleId(int scheduleId) { id = scheduleId; } public long getTimestamp() { return timestamp; } public void setTimestamp(long timestamp) { this.timestamp = timestamp; } public int getOobFactor() { return oobFactor; } public void setOobFactor(int oobFactor) { this.oobFactor = oobFactor; } @Override public String toString() { final StringBuilder sb = new StringBuilder(); sb.append("MeasurementOOB"); sb.append("{id=").append(id); sb.append(", timestamp=").append(timestamp); sb.append(", oobFactor=").append(oobFactor); sb.append('}'); return sb.toString(); } }