/*
* Jopr Management Platform
* Copyright (C) 2005-2009 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.plugins.jbossas5;
import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jboss.managed.api.ManagedComponent;
import org.jboss.managed.api.ManagedOperation;
import org.jboss.managed.api.ManagedProperty;
import org.jboss.metatype.api.values.CompositeValue;
import org.jboss.metatype.api.values.SimpleValue;
import org.rhq.core.domain.configuration.Configuration;
import org.rhq.core.domain.configuration.PropertyList;
import org.rhq.core.domain.configuration.PropertyMap;
import org.rhq.core.domain.configuration.PropertySimple;
import org.rhq.core.domain.measurement.MeasurementReport;
import org.rhq.core.domain.measurement.MeasurementScheduleRequest;
import org.rhq.core.domain.measurement.calltime.CallTimeData;
import org.rhq.core.pluginapi.operation.OperationFacet;
import org.rhq.core.pluginapi.operation.OperationResult;
/**
* An abstract plugin component for managing an EJB bean - has two subclasses - one for EJB2 beans and one for EJB3
* beans.
*
* @author Lukas Krejci
* @author Ian Springer
*/
public abstract class
AbstractEjbBeanComponent extends ManagedComponentComponent implements OperationFacet {
private final Log log = LogFactory.getLog(this.getClass());
private static final String VIEW_INVOCATION_STATS_OPERATION_NAME = "viewInvocationStats";
@Override
public void getValues(MeasurementReport report, Set<MeasurementScheduleRequest> requests) throws Exception {
ManagedComponent managedComponent = getManagedComponent();
Set<MeasurementScheduleRequest> remainingRequests = new LinkedHashSet();
for (MeasurementScheduleRequest request : requests) {
String metricName = request.getName();
try {
if (metricName.equals("methodInvocationTime")) {
// Convert the method stats CompositeValues into nice strongly typed objects.
InvocationStats invocationStats = getInvocationStats(managedComponent);
if (!invocationStats.methodStats.isEmpty()) {
CallTimeData callTimeData = createCallTimeData(request, invocationStats);
report.addData(callTimeData);
resetInvocationStats(managedComponent);
}
} else {
remainingRequests.add(request);
}
} catch (Exception e) {
// Don't let one bad apple spoil the barrel.
log.error("Failed to collect metric '" + metricName + "' for " + getResourceDescription() + ".", e);
}
}
// Let our superclass handle any metrics we didn't collect.
super.getValues(managedComponent, report, remainingRequests);
}
@Override
public OperationResult invokeOperation(String name, Configuration parameters) throws Exception {
OperationResult result;
ManagedComponent managedComponent = getManagedComponent();
if (VIEW_INVOCATION_STATS_OPERATION_NAME.equals(name)) {
result = new OperationResult();
PropertyList methodList = new PropertyList("methods");
result.getComplexResults().put(methodList);
// Convert the invocation stats CompositeValues into a nice strongly typed object.
List<MethodStats> allMethodStats = getInvocationStats(managedComponent).methodStats;
for (MethodStats methodStats : allMethodStats) {
PropertyMap method = new PropertyMap("method", new PropertySimple("methodName", methodStats.name),
new PropertySimple("count", methodStats.count), new PropertySimple("minTime", methodStats.minTime),
new PropertySimple("maxTime", methodStats.maxTime), new PropertySimple("totalTime",
methodStats.totalTime));
methodList.add(method);
}
} else {
result = super.invokeOperation(name, parameters);
}
return result;
}
private InvocationStats getInvocationStats(ManagedComponent managedComponent) {
InvocationStats invocationStats = new InvocationStats();
List<MethodStats> allMethodStats = new ArrayList<MethodStats>();
Configuration pluginConfig = getResourceContext().getPluginConfiguration();
String propName = pluginConfig.getSimple("invocationStatsPropertyName").getStringValue();
ManagedProperty detypedInvokedStatsProp = managedComponent.getProperty(propName);
invocationStats.endTime = System.currentTimeMillis();
CompositeValue detypedInvokeStatsMetaValue = (CompositeValue) detypedInvokedStatsProp.getValue();
CompositeValue allMethodStatsMetaValue = (CompositeValue) detypedInvokeStatsMetaValue.get("methodStats");
Set<String> methodNames = allMethodStatsMetaValue.getMetaType().keySet();
for (String methodName : methodNames) {
CompositeValue methodStatsMetaValue = (CompositeValue) allMethodStatsMetaValue.get(methodName);
MethodStats methodStats = new MethodStats();
methodStats.name = methodName;
methodStats.count = Long.parseLong(((SimpleValue) methodStatsMetaValue.get("count")).getValue().toString());
methodStats.totalTime = Long.parseLong(((SimpleValue) methodStatsMetaValue.get("totalTime")).getValue()
.toString());
methodStats.minTime = Long.parseLong(((SimpleValue) methodStatsMetaValue.get("minTime")).getValue()
.toString());
methodStats.maxTime = Long.parseLong(((SimpleValue) methodStatsMetaValue.get("maxTime")).getValue()
.toString());
allMethodStats.add(methodStats);
}
invocationStats.methodStats = allMethodStats;
SimpleValue lastResetTimeMetaValue = (SimpleValue) ((CompositeValue) detypedInvokedStatsProp.getValue())
.get("lastResetTime");
invocationStats.beginTime = Long.valueOf(lastResetTimeMetaValue.getValue().toString()); // TODO: handle null value?
return invocationStats;
}
private CallTimeData createCallTimeData(MeasurementScheduleRequest schedule, InvocationStats invocationStats)
throws Exception {
CallTimeData callTimeData = new CallTimeData(schedule);
Date beginDate = new Date(invocationStats.beginTime);
Date endDate = new Date(invocationStats.endTime);
for (MethodStats methodStats : invocationStats.methodStats) {
try {
callTimeData.addAggregatedCallData(methodStats.name, beginDate, endDate, methodStats.minTime,
methodStats.maxTime, methodStats.totalTime, methodStats.count);
} catch (IllegalArgumentException iae) {
// if any issue with the data, log them and continue processing the rest of the report
log.error(iae);
}
}
return callTimeData;
}
private void resetInvocationStats(ManagedComponent managedComponent) {
Set<ManagedOperation> operations = managedComponent.getOperations();
for (ManagedOperation operation : operations) {
if (operation.getName().equals("resetInvocationStats")) {
operation.invoke();
break;
}
}
}
class InvocationStats {
List<MethodStats> methodStats;
long beginTime;
long endTime;
}
class MethodStats {
String name;
long count;
long minTime;
long maxTime;
long totalTime;
}
}