modules/core/domain/src/main/java/org/rhq/core/domain/cloud/StorageNodeLoadComposite.java
| 56 ++---
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/storage/StorageNodeDatasource.java
| 37 +--
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerBean.java
| 104 ++++++----
modules/enterprise/server/plugins/alertdef-rhq/src/main/java/org/rhq/enterprise/server/plugins/alertdef/AlertDefinitionServerPluginComponent.java
| 66 ++++++
modules/plugins/cassandra/src/main/java/org/rhq/plugins/cassandra/StorageServiceComponent.java
| 65 +++---
modules/plugins/cassandra/src/main/resources/META-INF/rhq-plugin.xml
| 9
6 files changed, 232 insertions(+), 105 deletions(-)
New commits:
commit c19b6ea19c342474b0cc43733fc8eec5ae1c955f
Author: Stefan Negrea <snegrea(a)redhat.com>
Date: Thu Jul 4 02:47:49 2013 -0500
Update the way the percentage disk space use is calculated. It is now based on the
aggregate usage of all the partitions that have data files. Also, this is based on the
total disk use, not just Cassandra. Added an alert based on this metric.
Added a new metric to the storage node composite that aggregates all the metrics that
refer to storage related to Cassandra: data files, commit logs, row cache, and key cache.
This will be used for CLI an web only, it will not be a plugin metric.
Updated the plugin descriptor to collect metrics related to disk space usage.
Minor other code refactorings and updates.
diff --git
a/modules/core/domain/src/main/java/org/rhq/core/domain/cloud/StorageNodeLoadComposite.java
b/modules/core/domain/src/main/java/org/rhq/core/domain/cloud/StorageNodeLoadComposite.java
index 379eba6..0913f1d 100644
---
a/modules/core/domain/src/main/java/org/rhq/core/domain/cloud/StorageNodeLoadComposite.java
+++
b/modules/core/domain/src/main/java/org/rhq/core/domain/cloud/StorageNodeLoadComposite.java
@@ -36,19 +36,20 @@ public class StorageNodeLoadComposite implements Serializable {
private StorageNode storageNode;
private long beginTime;
private long endTime;
-
+
private MeasurementAggregateWithUnits heapCommitted;
private MeasurementAggregateWithUnits heapUsed;
private MeasurementAggregateWithUnits heapPercentageUsed;
private MeasurementAggregateWithUnits load;
- private MeasurementAggregateWithUnits diskSpacePercentageUsed;
- private MeasurementAggregate tokens;
+ private MeasurementAggregateWithUnits partitionDiskUsedPercentage;
+ private MeasurementAggregateWithUnits dataDiskUsed;
+ private MeasurementAggregate tokens;
private MeasurementAggregateWithUnits actuallyOwns;
public StorageNodeLoadComposite() {
// GWT needs this
}
-
+
public StorageNodeLoadComposite(StorageNode storageNode, long beginTime, long
endTime) {
this.storageNode = storageNode;
this.beginTime = beginTime;
@@ -114,15 +115,26 @@ public class StorageNodeLoadComposite implements Serializable {
}
/**
- * @return A computed metric for the space used on disk by all SSTables of all column
families expressed as a
- * percentage.
+ * @return A computed metric for the percentage of disk space used on the partition
that contains the SSTables.
+ * If multiple data locations are configured then the partition with the
highest utilization will be reported.
*/
- public MeasurementAggregateWithUnits getDiskSpacePercentageUsed() {
- return diskSpacePercentageUsed;
+ public MeasurementAggregateWithUnits getPartitionDiskUsedPercentage() {
+ return partitionDiskUsedPercentage;
}
- public void setDiskSpacePercentageUsed(MeasurementAggregateWithUnits
diskSpacePercentageUsed) {
- this.diskSpacePercentageUsed = diskSpacePercentageUsed;
+ public void setPartitionDiskUsedPercentage(MeasurementAggregateWithUnits
partitionDiskUsedPercentage) {
+ this.partitionDiskUsedPercentage = partitionDiskUsedPercentage;
+ }
+
+ /**
+ * @return A computed metric for the space used on disk by all data files, commit
logs, and saved caches.
+ */
+ public MeasurementAggregateWithUnits getDataDiskUsed() {
+ return dataDiskUsed;
+ }
+
+ public void setDataDiskUsed(MeasurementAggregateWithUnits dataDiskUsed) {
+ this.dataDiskUsed = dataDiskUsed;
}
/**
@@ -161,38 +173,32 @@ public class StorageNodeLoadComposite implements Serializable {
this.actuallyOwns = actuallyOwns;
}
+ /* (non-Javadoc)
+ * @see java.lang.Object#toString()
+ */
public String toString() {
StringBuilder builder = new StringBuilder();
- // gwt doesn't support String.format
-// builder.append("average values for last ");
-// builder.append((endtime - begintime) / (1000 * 60 * 60));
-// builder.append(" hours");
-// builder.append("\naddress load tokens owns
(effective)\n");
-// builder.append(string.format("%15s", storagenode.getaddress()));
-// builder.append(string.format("%11s",
load.getaggregate().getavg())).append(" ").append(load.getunits().getname());
-// builder.append(string.format("%8s", tokens.getavg()));
-// builder.append(string.format("%16s", actuallyowns.getavg()));
-
builder.append("storageNode.addresss=").append(storageNode.getAddress()).append(",
");
builder.append("beginTime=").append(beginTime).append(", ");
builder.append("heapCommitted=").append(heapCommitted).append(",
");
builder.append("heapUsed=").append(heapUsed).append(", ");
builder.append("heapPercentageUsed=").append(heapPercentageUsed).append(",
");
builder.append("load=").append(load).append(", ");
-
builder.append("diskSpacePercentageUsed=").append(diskSpacePercentageUsed).append(",
");
+
builder.append("partitionDiskUsedPercentage=").append(partitionDiskUsedPercentage).append(",
");
+ builder.append("dataDiskUsed=").append(dataDiskUsed).append(",
");
builder.append("tokens=").append(tokens).append(", ");
builder.append("actuallyOwns=").append(actuallyOwns);
return builder.toString();
}
-
+
public static class MeasurementAggregateWithUnits implements Serializable {
private static final long serialVersionUID = 1L;
-
+
private MeasurementAggregate aggregate;
private MeasurementUnits units;
private String formattedValue;
-
+
public MeasurementAggregateWithUnits() {
// GWT needs this
}
@@ -209,7 +215,7 @@ public class StorageNodeLoadComposite implements Serializable {
public MeasurementUnits getUnits() {
return units;
}
-
+
public void setFormattedValue(String formattedValue) {
this.formattedValue = formattedValue;
}
diff --git
a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/storage/StorageNodeDatasource.java
b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/storage/StorageNodeDatasource.java
index f267602..7d413fd 100644
---
a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/storage/StorageNodeDatasource.java
+++
b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/storage/StorageNodeDatasource.java
@@ -61,7 +61,7 @@ import org.rhq.enterprise.server.measurement.util.MeasurementUtils;
/**
* Datasource for @see StorageNode.
- *
+ *
* @author Jirka Kremser
*/
public class StorageNodeDatasource extends RPCDataSource<StorageNode,
StorageNodeCriteria> {
@@ -104,7 +104,7 @@ public class StorageNodeDatasource extends
RPCDataSource<StorageNode, StorageNod
ListGridField createdTimeField = FIELD_CTIME.getListGridField("120");
TimestampCellFormatter.prepareDateField(createdTimeField);
fields.add(createdTimeField);
-
+
ListGridField lastUpdateTimeField =
FIELD_MTIME.getListGridField("120");
TimestampCellFormatter.prepareDateField(lastUpdateTimeField);
fields.add(lastUpdateTimeField);
@@ -142,7 +142,7 @@ public class StorageNodeDatasource extends
RPCDataSource<StorageNode, StorageNod
*/
@Override
protected PageControl getPageControl(DSRequest request) {
- // Initialize paging.
+ // Initialize paging.
PageControl pageControl = new PageControl(0, getDataPageSize());
// Initialize sorting.
@@ -197,7 +197,7 @@ public class StorageNodeDatasource extends
RPCDataSource<StorageNode, StorageNod
return criteria;
}
-
+
public static class StorageNodeLoadCompositeDatasource extends
RPCDataSource<StorageNodeLoadComposite, StorageNodeCriteria> {
public static final String HEAP_PERCENTAGE_KEY = "heapPercentage";
public static final String DISK_SPACE_PERCENTAGE_KEY =
"diskSpacePercentage";
@@ -205,12 +205,12 @@ public class StorageNodeDatasource extends
RPCDataSource<StorageNode, StorageNod
public static StorageNodeLoadCompositeDatasource getInstance(int id) {
// if (instance == null) {
-// instance =
+ // instance =
return new StorageNodeLoadCompositeDatasource(id);
// }
// return instance;
}
-
+
public StorageNodeLoadCompositeDatasource(int id) {
super();
this.id = id;
@@ -235,7 +235,7 @@ public class StorageNodeDatasource extends
RPCDataSource<StorageNode, StorageNod
fields.add(idField);
return fields;
}
-
+
public List<ListGridField> getListGridFields() {
List<ListGridField> fields = new ArrayList<ListGridField>();
ListGridField idField = FIELD_ID.getListGridField();
@@ -259,8 +259,7 @@ public class StorageNodeDatasource extends
RPCDataSource<StorageNode, StorageNod
fields.add(hoverField);
return fields;
}
-
-
+
@Override
protected void executeFetch(final DSRequest request, final DSResponse response,
StorageNodeCriteria criteria) {
// Integer id = getFilter(request, FIELD_ID.propertyName(), Integer.class);
@@ -286,7 +285,6 @@ public class StorageNodeDatasource extends
RPCDataSource<StorageNode, StorageNod
private ListGridRecord[] makeListGridRecords(StorageNodeLoadComposite
loadComposite) {
List<ListGridRecord> recordsList = new
ArrayList<ListGridRecord>(6);
- @SuppressWarnings("unchecked")
List<List<Object>> loadFields = Arrays
.<List<Object>> asList(
Arrays.<Object> asList(loadComposite.getHeapCommitted(),
"Heap Maximum",
@@ -298,10 +296,16 @@ public class StorageNodeDatasource extends
RPCDataSource<StorageNode, StorageNod
"This value is calculated by dividing Heap Used by Heap
Maximum.", HEAP_PERCENTAGE_KEY),
Arrays.<Object> asList(loadComposite.getLoad(),
"Load", "Data stored on the node", "load"),
Arrays.<Object> asList(
- loadComposite.getDiskSpacePercentageUsed(),
+ loadComposite.getPartitionDiskUsedPercentage(),
"Disk Space Percent Used",
- "How much of diskspace is already used. This takes into
account the installation path, where Cassandra was installed.",
- DISK_SPACE_PERCENTAGE_KEY), Arrays.<Object>
asList(loadComposite.getActuallyOwns(),
+ "Percentage of total disk space used for the partition that
contains the data files.If multiple data locations are specified then this will report the
average utilization accross all the partitions.",
+ DISK_SPACE_PERCENTAGE_KEY),
+ Arrays.<Object> asList(
+ loadComposite.getDataDiskUsed(),
+ "Total Disk Space Used",
+ "Total space used on disk by all data files, commit logs,
and saved caches.",
+ "totaldisk"),
+ Arrays.<Object> asList(loadComposite.getActuallyOwns(),
"Ownership", "Refers to the percentage of keys
that a node owns.", "ownership"));
for (List<Object> aggregateWithUnitsList : loadFields) {
if (aggregateWithUnitsList.get(0) != null) {
@@ -346,14 +350,13 @@ public class StorageNodeDatasource extends
RPCDataSource<StorageNode, StorageNod
record.setAttribute("hover", hover);
return record;
}
-
-
+
@Override
protected StorageNodeCriteria getFetchCriteria(DSRequest request) {
return new StorageNodeCriteria();
// throw new
UnsupportedOperationException("StorageNodeDatasource.StorageNodeLoadCompositeDatasource.getFetchCriteria()");
}
-
+
@Override
public StorageNodeLoadComposite copyValues(Record from) {
throw new
UnsupportedOperationException("StorageNodeDatasource.StorageNodeLoadCompositeDatasource.copyValues(Record
from)");
@@ -363,6 +366,6 @@ public class StorageNodeDatasource extends
RPCDataSource<StorageNode, StorageNod
public ListGridRecord copyValues(StorageNodeLoadComposite from) {
throw new
UnsupportedOperationException("StorageNodeDatasource.StorageNodeLoadCompositeDatasource.copyValues(StorageNodeLoadComposite
from)");
}
-
+
}
}
diff --git
a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerBean.java
b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerBean.java
index b21946a..b76d054 100644
---
a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerBean.java
+++
b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerBean.java
@@ -332,71 +332,96 @@ public class StorageNodeManagerBean implements
StorageNodeManagerLocal, StorageN
@Override
@RequiredPermission(Permission.MANAGE_SETTINGS)
public StorageNodeLoadComposite getLoad(Subject subject, StorageNode node, long
beginTime, long endTime) {
- StorageNodeLoadComposite result = new StorageNodeLoadComposite(node, beginTime,
endTime);
- final String tokensMetric = "Tokens", ownershipMetric =
"Ownership", loadMetric = "Load", diskUsedPercentageMetric =
"Calculated.DiskSpaceUsedPercentage";
- final String heapCommittedMetric = "{HeapMemoryUsage.committed}",
heapUsedMetric = "{HeapMemoryUsage.used}", heapUsedPercentageMetric =
"Calculated.HeapUsagePercentage";
-
int resourceId = getResourceIdFromStorageNode(node);
+ Map<String, Integer> scheduleIdsMap = new HashMap<String,
Integer>();
// get the schedule ids for Storage Service resource
+ final String tokensMetric = "Tokens", ownershipMetric =
"Ownership", diskUsedPercentageMetric =
"Calculated.PartitionDiskUsedPercentage";
+ final String loadMetric = "Load", keyCacheSize =
"KeyCacheSize", rowCacheSize = "RowCacheSize", totalCommitLogSize =
"TotalCommitlogSize";
TypedQuery<Object[]> query = entityManager.<Object[]>
createNamedQuery(
StorageNode.QUERY_FIND_SCHEDULE_IDS_BY_PARENT_RESOURCE_ID_AND_MEASUREMENT_DEFINITION_NAMES,
Object[].class);
query.setParameter("parrentId",
resourceId).setParameter("metricNames",
- Arrays.asList(tokensMetric, ownershipMetric, loadMetric,
diskUsedPercentageMetric));
- List<Object[]> scheduleIds = query.getResultList();
- Map<String, Integer> scheduleIdsMap = new HashMap<String,
Integer>(4);
- for (Object[] pair : scheduleIds) {
+ Arrays.asList(tokensMetric, ownershipMetric, diskUsedPercentageMetric,
loadMetric, keyCacheSize,
+ rowCacheSize, totalCommitLogSize));
+ for (Object[] pair : query.getResultList()) {
scheduleIdsMap.put((String) pair[0], (Integer) pair[1]);
}
// get the schedule ids for Memory Subsystem resource
+ final String heapCommittedMetric = "{HeapMemoryUsage.committed}",
heapUsedMetric = "{HeapMemoryUsage.used}", heapUsedPercentageMetric =
"Calculated.HeapUsagePercentage";
query = entityManager.<Object[]> createNamedQuery(
StorageNode.QUERY_FIND_SCHEDULE_IDS_BY_GRANDPARENT_RESOURCE_ID_AND_MEASUREMENT_DEFINITION_NAMES,
Object[].class);
query.setParameter("grandparrentId",
resourceId).setParameter("metricNames",
Arrays.asList(heapCommittedMetric, heapUsedMetric,
heapUsedPercentageMetric));
- scheduleIds = query.getResultList();
- for (Object[] pair : scheduleIds) {
+ for (Object[] pair : query.getResultList()) {
scheduleIdsMap.put((String) pair[0], (Integer) pair[1]);
}
+
+ StorageNodeLoadComposite result = new StorageNodeLoadComposite(node, beginTime,
endTime);
+ MeasurementAggregate totalDiskUsedaggregate = new MeasurementAggregate(0d, 0d,
0d);
+ Integer scheduleId = null;
+
// find the aggregates and enrich the result instance
if (!scheduleIdsMap.isEmpty()) {
- if (scheduleIdsMap.get(tokensMetric) != null) {
- MeasurementAggregate tokensAggregate =
measurementManager.getAggregate(subject,
- scheduleIdsMap.get(tokensMetric), beginTime, endTime);
+ if ((scheduleId = scheduleIdsMap.get(tokensMetric)) != null) {
+ MeasurementAggregate tokensAggregate =
measurementManager.getAggregate(subject, scheduleId, beginTime,
+ endTime);
result.setTokens(tokensAggregate);
}
- if (scheduleIdsMap.get(ownershipMetric) != null) {
+ if ((scheduleId = scheduleIdsMap.get(ownershipMetric)) != null) {
StorageNodeLoadComposite.MeasurementAggregateWithUnits
ownershipAggregateWithUnits = getMeasurementAggregateWithUnits(
- subject, scheduleIdsMap.get(ownershipMetric),
MeasurementUnits.PERCENTAGE, beginTime, endTime);
+ subject, scheduleId, MeasurementUnits.PERCENTAGE, beginTime,
endTime);
result.setActuallyOwns(ownershipAggregateWithUnits);
}
- if (scheduleIdsMap.get(loadMetric) != null) {
+ if ((scheduleId = scheduleIdsMap.get(diskUsedPercentageMetric)) != null) {
+ StorageNodeLoadComposite.MeasurementAggregateWithUnits
diskUsedPercentageAggregateWithUnits = getMeasurementAggregateWithUnits(
+ subject, scheduleId, MeasurementUnits.PERCENTAGE, beginTime,
endTime);
+
result.setPartitionDiskUsedPercentage(diskUsedPercentageAggregateWithUnits);
+ }
+
+ if ((scheduleId = scheduleIdsMap.get(loadMetric)) != null) {
StorageNodeLoadComposite.MeasurementAggregateWithUnits
loadAggregateWithUnits = getMeasurementAggregateWithUnits(
- subject, scheduleIdsMap.get(loadMetric), MeasurementUnits.BYTES,
beginTime, endTime);
+ subject, scheduleId, MeasurementUnits.BYTES, beginTime, endTime);
result.setLoad(loadAggregateWithUnits);
+
+ updateAggregateTotal(totalDiskUsedaggregate,
loadAggregateWithUnits.getAggregate());
}
- if (scheduleIdsMap.get(diskUsedPercentageMetric) != null) {
- StorageNodeLoadComposite.MeasurementAggregateWithUnits
diskUsedPercentageAggregateWithUnits = getMeasurementAggregateWithUnits(
- subject, scheduleIdsMap.get(diskUsedPercentageMetric),
MeasurementUnits.PERCENTAGE, beginTime,
- endTime);
- result.setDiskSpacePercentageUsed(diskUsedPercentageAggregateWithUnits);
+ if ((scheduleId = scheduleIdsMap.get(keyCacheSize)) != null) {
+ updateAggregateTotal(totalDiskUsedaggregate,
+ measurementManager.getAggregate(subject, scheduleId, beginTime,
endTime));
+ }
+ if ((scheduleId = scheduleIdsMap.get(rowCacheSize)) != null) {
+ updateAggregateTotal(totalDiskUsedaggregate,
+ measurementManager.getAggregate(subject, scheduleId, beginTime,
endTime));
+ }
+ if ((scheduleId = scheduleIdsMap.get(totalCommitLogSize)) != null) {
+ updateAggregateTotal(totalDiskUsedaggregate,
+ measurementManager.getAggregate(subject, scheduleId, beginTime,
endTime));
+ }
+
+ if (totalDiskUsedaggregate.getMax() > 0) {
+ StorageNodeLoadComposite.MeasurementAggregateWithUnits
totalDiskUsedAggregateWithUnits = new
StorageNodeLoadComposite.MeasurementAggregateWithUnits(
+ totalDiskUsedaggregate, MeasurementUnits.BYTES);
+
totalDiskUsedAggregateWithUnits.setFormattedValue(getSummaryString(totalDiskUsedaggregate,
+ MeasurementUnits.BYTES));
+ result.setDataDiskUsed(totalDiskUsedAggregateWithUnits);
}
- if (scheduleIdsMap.get(heapCommittedMetric) != null) {
+ if ((scheduleId = scheduleIdsMap.get(heapCommittedMetric)) != null) {
StorageNodeLoadComposite.MeasurementAggregateWithUnits
heapCommittedAggregateWithUnits = getMeasurementAggregateWithUnits(
- subject, scheduleIdsMap.get(heapCommittedMetric),
MeasurementUnits.BYTES, beginTime, endTime);
+ subject, scheduleId, MeasurementUnits.BYTES, beginTime, endTime);
result.setHeapCommitted(heapCommittedAggregateWithUnits);
}
- if (scheduleIdsMap.get(heapUsedMetric) != null) {
+ if ((scheduleId = scheduleIdsMap.get(heapUsedMetric)) != null) {
StorageNodeLoadComposite.MeasurementAggregateWithUnits
heapUsedAggregateWithUnits = getMeasurementAggregateWithUnits(
- subject, scheduleIdsMap.get(heapUsedMetric), MeasurementUnits.BYTES,
beginTime, endTime);
+ subject, scheduleId, MeasurementUnits.BYTES, beginTime, endTime);
result.setHeapUsed(heapUsedAggregateWithUnits);
}
- if (scheduleIdsMap.get(heapUsedPercentageMetric) != null) {
+ if ((scheduleId = scheduleIdsMap.get(heapUsedPercentageMetric)) != null) {
StorageNodeLoadComposite.MeasurementAggregateWithUnits
heapUsedPercentageAggregateWithUnits = getMeasurementAggregateWithUnits(
- subject, scheduleIdsMap.get(heapUsedPercentageMetric),
MeasurementUnits.PERCENTAGE, beginTime,
+ subject, scheduleId, MeasurementUnits.PERCENTAGE, beginTime,
endTime);
result.setHeapPercentageUsed(heapUsedPercentageAggregateWithUnits);
}
@@ -405,13 +430,28 @@ public class StorageNodeManagerBean implements
StorageNodeManagerLocal, StorageN
return result;
}
+ /**
+ * @param accumulator
+ * @param input
+ */
+ private void updateAggregateTotal(MeasurementAggregate accumulator,
MeasurementAggregate input) {
+ if (accumulator != null && input != null
+ && input.getMax() != null &&
!Double.isNaN(input.getMax())
+ && input.getMin() != null &&
!Double.isNaN(input.getMin())
+ && input.getAvg() != null &&
!Double.isNaN(input.getAvg())) {
+ accumulator.setAvg(accumulator.getAvg() + input.getAvg());
+ accumulator.setMax(accumulator.getMax() + input.getMax());
+ accumulator.setMin(accumulator.getMin() + input.getMin());
+ }
+ }
+
@Override
public List<StorageNode> getStorageNodes() {
TypedQuery<StorageNode> query = entityManager.<StorageNode>
createNamedQuery(StorageNode.QUERY_FIND_ALL,
StorageNode.class);
return query.getResultList();
}
-
+
@Override
@RequiredPermission(Permission.MANAGE_SETTINGS)
public PageList<StorageNode> findStorageNodesByCriteria(Subject subject,
StorageNodeCriteria criteria) {
@@ -432,7 +472,7 @@ public class StorageNodeManagerBean implements
StorageNodeManagerLocal, StorageN
Server server = serverManager.getServer();
// setting the server mode to maintenance
topologyManager.updateServerMode(subject, new Integer[] { server.getId() },
Server.OperationMode.MAINTENANCE);
-
+
Configuration parameters = new Configuration();
parameters.setSimpleValue("snapshotName",
String.valueOf(System.currentTimeMillis()));
// scheduling the operation
@@ -543,7 +583,7 @@ public class StorageNodeManagerBean implements
StorageNodeManagerLocal, StorageN
}
}
}
-
+
private StorageNodeLoadComposite.MeasurementAggregateWithUnits
getMeasurementAggregateWithUnits(Subject subject,
int schedId, MeasurementUnits units, long beginTime, long endTime) {
MeasurementAggregate measurementAggregate =
measurementManager.getAggregate(subject, schedId, beginTime,
@@ -553,7 +593,7 @@ public class StorageNodeManagerBean implements
StorageNodeManagerLocal, StorageN
measurementAggregateWithUnits.setFormattedValue(getSummaryString(measurementAggregate,
units));
return measurementAggregateWithUnits;
}
-
+
private int getResourceIdFromStorageNode(StorageNode storageNode) {
int resourceId;
if (storageNode.getResource() == null) {
diff --git
a/modules/enterprise/server/plugins/alertdef-rhq/src/main/java/org/rhq/enterprise/server/plugins/alertdef/AlertDefinitionServerPluginComponent.java
b/modules/enterprise/server/plugins/alertdef-rhq/src/main/java/org/rhq/enterprise/server/plugins/alertdef/AlertDefinitionServerPluginComponent.java
index 566dfe2..1cff654 100644
---
a/modules/enterprise/server/plugins/alertdef-rhq/src/main/java/org/rhq/enterprise/server/plugins/alertdef/AlertDefinitionServerPluginComponent.java
+++
b/modules/enterprise/server/plugins/alertdef-rhq/src/main/java/org/rhq/enterprise/server/plugins/alertdef/AlertDefinitionServerPluginComponent.java
@@ -54,15 +54,19 @@ import org.rhq.enterprise.server.util.LookupUtil;
/**
* An alert definition server-side plugin component that the server uses to inject
"factory-installed" alert definitions.
- *
+ *
* @author Jay Shaughnessy
*/
public class AlertDefinitionServerPluginComponent implements ServerPluginComponent,
ControlFacet {
private final Log log =
LogFactory.getLog(AlertDefinitionServerPluginComponent.class);
+ private static final String PARTITION_DISK_USED_PERCENTAGE_METRIC_NAME =
"Calculated.PartitionDiskUsedPercentage";
+ private static final String DATA_FILE_LOCATIONS_NAME =
"AllDataFileLocations";
+
static private final List<InjectedTemplate> injectedTemplates;
static private final InjectedTemplate storageNodeHighHeapTemplate;
+ static private final InjectedTemplate storageNodeHighDiskUsageTemplate;
static {
storageNodeHighHeapTemplate = new InjectedTemplate(
@@ -71,8 +75,15 @@ public class AlertDefinitionServerPluginComponent implements
ServerPluginCompone
"StorageNodeHighHeapTemplate", //
"An alert template to notify users of excessive heap use by an RHQ
Storage Node. When fired please see documentation for the proper corrective
action.");
+ storageNodeHighDiskUsageTemplate = new InjectedTemplate(
+ "RHQStorage", //
+ "StorageService", //
+ "StorageNodeHighDiskUsageTemplate", //
+ "An alert template to notify users of excessive heap use by an RHQ
Storage Node. When fired please see documentation for the proper corrective
action.");
+
injectedTemplates = new ArrayList<InjectedTemplate>();
injectedTemplates.add(storageNodeHighHeapTemplate);
+ injectedTemplates.add(storageNodeHighDiskUsageTemplate);
}
private ServerPluginContext context;
@@ -213,6 +224,8 @@ public class AlertDefinitionServerPluginComponent implements
ServerPluginCompone
if (storageNodeHighHeapTemplate.equals(injectedAlertDef)) {
newAlertDefId = injectStorageNodeHighHeapTemplate(resourceType);
+ } else if (storageNodeHighDiskUsageTemplate.equals(injectedAlertDef)) {
+ newAlertDefId = injectStorageNodeHighDiskUsageTemplate(resourceType);
}
adc.addFilterId(newAlertDefId);
@@ -273,6 +286,57 @@ public class AlertDefinitionServerPluginComponent implements
ServerPluginCompone
return newTemplateId;
}
+ private int injectStorageNodeHighDiskUsageTemplate(ResourceType resourceType) {
+ AlertTemplateManagerLocal alertTemplateManager =
LookupUtil.getAlertTemplateManager();
+ SubjectManagerLocal subjectManager = LookupUtil.getSubjectManager();
+
+ AlertDefinition newTemplate = new AlertDefinition();
+ newTemplate.setName(storageNodeHighDiskUsageTemplate.getName());
+ newTemplate.setResourceType(resourceType);
+ newTemplate.setPriority(AlertPriority.MEDIUM);
+ newTemplate.setConditionExpression(BooleanExpression.ANY);
+ newTemplate.setRecoveryId(0);
+ newTemplate.setEnabled(true);
+
+ AlertCondition ac = new AlertCondition();
+ ac.setCategory(AlertConditionCategory.THRESHOLD);
+ ac.setComparator(">");
+ ac.setThreshold(0.75D);
+
+ List<Integer> measurementDefinitionIds = new ArrayList<Integer>(1);
+ for (MeasurementDefinition d : resourceType.getMetricDefinitions()) {
+ if (PARTITION_DISK_USED_PERCENTAGE_METRIC_NAME.equals(d.getName())) {
+ measurementDefinitionIds.add(d.getId());
+ ac.setMeasurementDefinition(d);
+ ac.setName(d.getDisplayName());
+ } else if (DATA_FILE_LOCATIONS_NAME.equals(d.getName())) {
+ measurementDefinitionIds.add(d.getId());
+ }
+ }
+ assert null != ac.getMeasurementDefinition() : "Did not find expected
measurement definition "
+ + PARTITION_DISK_USED_PERCENTAGE_METRIC_NAME + " for "
+ + resourceType;
+ newTemplate.addCondition(ac);
+
+ AlertDampening dampener = new
AlertDampening(AlertDampening.Category.PARTIAL_COUNT);
+ dampener.setPeriod(15);
+ dampener.setPeriodUnits(TimeUnits.MINUTES);
+ dampener.setValue(10);
+ newTemplate.setAlertDampening(dampener);
+
+ int newTemplateId =
alertTemplateManager.createAlertTemplate(subjectManager.getOverlord(), newTemplate,
+ resourceType.getId());
+
+ // additionally, we want to ensure that the metric is enabled and collecting at a
more frequent interval than
+ // is set by default.
+ MeasurementScheduleManagerLocal measurementManager =
LookupUtil.getMeasurementScheduleManager();
+
measurementManager.updateDefaultCollectionIntervalAndEnablementForMeasurementDefinitions(
+ subjectManager.getOverlord(),
ArrayUtils.toPrimitive(measurementDefinitionIds.toArray(new Integer[2])),
+ 60000L, true, true);
+
+ return newTemplateId;
+ }
+
private static class InjectedTemplate {
static public final String FIELD_PLUGIN_NAME = "plugin";
static public final String FIELD_RESOURCE_TYPE_NAME = "type";
diff --git
a/modules/plugins/cassandra/src/main/java/org/rhq/plugins/cassandra/StorageServiceComponent.java
b/modules/plugins/cassandra/src/main/java/org/rhq/plugins/cassandra/StorageServiceComponent.java
index b2987be..7281f9b 100644
---
a/modules/plugins/cassandra/src/main/java/org/rhq/plugins/cassandra/StorageServiceComponent.java
+++
b/modules/plugins/cassandra/src/main/java/org/rhq/plugins/cassandra/StorageServiceComponent.java
@@ -29,9 +29,10 @@ import static org.rhq.core.domain.measurement.AvailabilityType.DOWN;
import static org.rhq.core.domain.measurement.AvailabilityType.UNKNOWN;
import static org.rhq.core.domain.measurement.AvailabilityType.UP;
-import java.io.File;
import java.net.InetAddress;
import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -48,19 +49,20 @@ import org.rhq.core.domain.measurement.MeasurementReport;
import org.rhq.core.domain.measurement.MeasurementScheduleRequest;
import org.rhq.core.pluginapi.inventory.ResourceContext;
import org.rhq.core.pluginapi.operation.OperationResult;
+import org.rhq.core.system.FileSystemInfo;
import org.rhq.plugins.jmx.JMXComponent;
/**
* @author John Sanda
*/
public class StorageServiceComponent extends ComplexConfigurationResourceComponent {
-
+
private static final String OWNERSHIP_METRIC_NAME = "Ownership";
- private static final String DISK_USED_METRIC_NAME =
"Calculated.DiskSpaceUsedPercentage";
+ private static final String PARTITION_DISK_USED_PERCENTAGE_METRIC_NAME =
"Calculated.PartitionDiskUsedPercentage";
private static final String DATA_FILE_LOCATIONS_NAME =
"AllDataFileLocations";
private Log log = LogFactory.getLog(StorageServiceComponent.class);
private InetAddress host;
-
+
@Override
public void start(ResourceContext<JMXComponent<?>> context) {
super.start(context);
@@ -73,7 +75,7 @@ public class StorageServiceComponent extends
ComplexConfigurationResourceCompone
e);
}
}
-
+
@Override
public AvailabilityType getAvailability() {
ResourceContext<?> context = getResourceContext();
@@ -148,7 +150,7 @@ public class StorageServiceComponent extends
ComplexConfigurationResourceCompone
return new OperationResult();
}
-
+
@Override
protected void getValues(MeasurementReport report,
Set<MeasurementScheduleRequest> requests, EmsBean bean) {
super.getValues(report, requests, bean);
@@ -175,32 +177,43 @@ public class StorageServiceComponent extends
ComplexConfigurationResourceCompone
report.addData(new MeasurementDataNumeric(request,
value.doubleValue()));
}
break;
- } else if (DISK_USED_METRIC_NAME.equals(request.getName())) {
+ } else if
(PARTITION_DISK_USED_PERCENTAGE_METRIC_NAME.equals(request.getName())) {
EmsAttribute attribute = bean.getAttribute(DATA_FILE_LOCATIONS_NAME);
Object valueObject = attribute.refresh();
if (valueObject instanceof String[]) {
- String[] paths = (String[]) valueObject;
- double max = 0;
- for (String path : paths) {
- double taken = getUsage(path);
- if (taken > max) {
- max = taken;
- }
- }
- if (max > 0.0001d) {
- report.addData(new MeasurementDataNumeric(request, max));
- }
+ //Please visit for details:
https://issues.apache.org/jira/browse/CASSANDRA-2749
+ //The average usage of all partitions with the data will be
reported.
+ //Cassandra selects the partition with most free space for SStable
flush and compaction.
+ report.addData(new MeasurementDataNumeric(request,
+ getPartitionDiskUsedPercentage((String[]) valueObject)));
}
}
}
}
-
- private double getUsage(String path) {
- File f = new File(path);
- return ((double)f.getTotalSpace() - f.getUsableSpace()) / f.getTotalSpace();
- }
-
- public static boolean kindOfIP(final String addr) {
- return addr.matches("^\\d{1,3}\\.\\d{1,3\\.\\d{1,3\\.\\d{1,3$"); // ||
addr.indexOf(":") >= 0) or IPv6
+
+ private double getPartitionDiskUsedPercentage(String[] paths) {
+ List<String> visitedMountPoints = new ArrayList<String>();
+ long totalDiskSpace = 0;
+ long totalUsedDiskSpace = 0;
+
+ for (String path : paths) {
+ try {
+ FileSystemInfo fileSystemInfo =
this.getResourceContext().getSystemInformation().getFileSystem(path);
+ if (!visitedMountPoints.contains(fileSystemInfo.getMountPoint())) {
+ visitedMountPoints.add(fileSystemInfo.getMountPoint());
+ totalDiskSpace += fileSystemInfo.getFileSystemUsage().getTotal();
+ totalUsedDiskSpace += fileSystemInfo.getFileSystemUsage().getUsed();
+ }
+ } catch (Exception e) {
+ log.error("Unable to determine file system usage information for
data file location " + path, e);
+ }
+ }
+
+ if (totalDiskSpace != 0) {
+ double rawPercentage = ((double) totalUsedDiskSpace) / ((double)
totalDiskSpace);
+ return Math.round(rawPercentage * 100.0) / 100.0;
+ }
+
+ return 0;
}
}
diff --git a/modules/plugins/cassandra/src/main/resources/META-INF/rhq-plugin.xml
b/modules/plugins/cassandra/src/main/resources/META-INF/rhq-plugin.xml
index ebaef94..cac0a8d 100644
--- a/modules/plugins/cassandra/src/main/resources/META-INF/rhq-plugin.xml
+++ b/modules/plugins/cassandra/src/main/resources/META-INF/rhq-plugin.xml
@@ -183,7 +183,8 @@
</operation>
<metric property="CurrentGenerationNumber" dataType="trait"
displayType="summary" description="Current generation number"/>
- <metric property="Calculated.DiskSpaceUsedPercentage"
dataType="measurement" units="percentage"
displayType="summary" description="How much of diskspace is already used.
This takes into account the installation path, where Cassandra was installed."/>
+ <metric property="Calculated.PartitionDiskUsedPercentage"
dataType="measurement" units="percentage"
displayType="summary" description="Percentage of total disk space used for
the partition that contains the data files.
+
If multiple data locations are specified then
this will report the average utilization accross all the partitions."/>
<metric property="ExceptionCount" measurementType="trendsup"
dataType="measurement" displayType="summary"
description="Exception Count"/>
<metric property="Initialized" dataType="trait"
displayType="summary" description="Initialized"/>
<metric property="Joined" dataType="trait"
displayType="summary" description="Joined"/>
@@ -272,7 +273,7 @@
<c:simple-property name="nameTemplate" readOnly="true"
type="string" default="Commit Log" />
</plugin-configuration>
- <metric property="TotalCommitlogSize"
measurementType="trendsup" dataType="measurement"
displayType="summary" description="Size of all commit log
segments"/>
+ <metric property="TotalCommitlogSize"
measurementType="dynamic" displayType="summary" description="Size
of all commit log segments"/>
<metric property="PendingTasks" measurementType="dynamic"
displayType="summary" description="Number of tasks waiting to be
executed"/>
<metric property="CompletedTasks" measurementType="trendsup"
displayType="summary" description="Number of completed tasks"/>
</service>
@@ -393,8 +394,8 @@
<metric property="KeyCacheCapacityInBytes"
measurementType="dynamic" displayType="summary" description="Key
cache capacity in bytes"/>
<metric property="RowCacheCapacityInBytes"
measurementType="dynamic" displayType="summary" description="Row
cache capacity in bytes"/>
- <metric property="KeyCacheSize" measurementType="dynamic"
displayType="detail" description="Key cache size"/>
- <metric property="RowCacheSize" measurementType="dynamic"
displayType="detail" description="Row cache size"/>
+ <metric property="KeyCacheSize" measurementType="dynamic"
displayType="summary" description="Key cache size"/>
+ <metric property="RowCacheSize" measurementType="dynamic"
displayType="summary" description="Row cache size"/>
<resource-configuration>
<c:simple-property name="KeyCacheCapacityInMB" type="long"
required="true" displayName="Key Cache Capacity In MB"
description="Key cache capacity in MB"/>