/* * 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; } }