blob: 9ef8b028415dcfe5649afc9d1c600acc57b9db3b [file] [log] [blame]
/*
* Copyright 2001-2008 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.apache.juddi.api.impl;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
import javax.management.Attribute;
import javax.management.AttributeList;
import javax.management.AttributeNotFoundException;
import javax.management.DynamicMBean;
import javax.management.InstanceAlreadyExistsException;
import javax.management.InvalidAttributeValueException;
import javax.management.MBeanAttributeInfo;
import javax.management.MBeanException;
import javax.management.MBeanInfo;
import javax.management.MBeanOperationInfo;
import javax.management.MBeanRegistrationException;
import javax.management.MBeanServer;
import javax.management.MBeanServerFactory;
import javax.management.MalformedObjectNameException;
import javax.management.NotCompliantMBeanException;
import javax.management.ObjectName;
import javax.management.ReflectionException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.juddi.api.util.QueryStatus;
import org.apache.juddi.api.util.UDDIQuery;
/**
* This class provides MBean functionality that offers metrics on UDDI service method invocations
* and various management functions (documented by Alex O'Ree)
* @author Tom Cunningham
*/
public class UDDIServiceCounter implements DynamicMBean, Serializable {
private static Log log = LogFactory.getLog(UDDIServiceCounter.class);
private Hashtable <String, LongHolder> queryProcessingTime;
private Hashtable <String, IntHolder> totalQueryCounter;
private Hashtable <String, IntHolder> successQueryCounter;
private Hashtable <String, IntHolder> faultQueryCounter;
private ObjectName listObjectName = null;
private int totalApiCounter;
private int successApiCounter;
private int faultApiCounter;
private static final String PROCESSING_TIME = "processing time";
private static final String TOTAL_QUERIES = "total queries";
private static final String SUCCESSFUL_QUERIES = "successful queries";
private static final String FAILED_QUERIES = "failed queries";
private static final String TOTAL_API_QUERIES = "Total API Queries";
private static final String SUCCESSFUL_API_QUERIES = "Successful API Queries";
private static final String FAILED_API_QUERIES = "Failed API Queries";
public static final String RESET_COUNTER = "resetCounts";
public void initList(Class klass, List<String> queries) {
try {
listObjectName = new ObjectName("apache.juddi:" + "counter=" + klass.getName());
} catch (MalformedObjectNameException mone) {
log.error(mone);
}
queryProcessingTime = new Hashtable<String,LongHolder>();
totalQueryCounter = new Hashtable<String, IntHolder>();
successQueryCounter = new Hashtable<String, IntHolder>();
faultQueryCounter = new Hashtable<String, IntHolder>();
for (String query : queries) {
queryProcessingTime.put(query + " " + PROCESSING_TIME, new LongHolder());
totalQueryCounter.put(query + " " + TOTAL_QUERIES, new IntHolder());
successQueryCounter.put(query + " " + SUCCESSFUL_QUERIES, new IntHolder());
faultQueryCounter.put(query + " " + FAILED_QUERIES, new IntHolder());
}
totalApiCounter = 0;
successApiCounter = 0;
faultApiCounter = 0;
}
protected void registerMBean() {
MBeanServer mbeanServer = null;
mbeanServer = getServer();
if (mbeanServer == null) {
try {
// mbeanServer = MBeanServerLocator.locateJBoss();
} catch (IllegalStateException ise) {
// If we can't find a JBoss MBeanServer, just return
// Needed for unit tests
return;
}
}
try {
if (! mbeanServer.isRegistered(listObjectName))
mbeanServer.registerMBean(this, listObjectName);
} catch (InstanceAlreadyExistsException e) {
log.warn("", e);
} catch (MBeanRegistrationException e) {
log.warn("", e);
} catch (NotCompliantMBeanException e) {
log.warn("", e);
}
}
private MBeanServer getServer() {
MBeanServer mbserver = null;
ArrayList mbservers = MBeanServerFactory.findMBeanServer(null);
if (mbservers.size() > 0) {
mbserver = (MBeanServer) mbservers.get(0);
}
if (mbserver != null) {
log.info("Found MBean server");
} else {
mbserver = MBeanServerFactory.createMBeanServer();
}
return mbserver;
}
public void resetCounts() {
for (String key : queryProcessingTime.keySet()) {
queryProcessingTime.put(key, new LongHolder());
}
for (String key : totalQueryCounter.keySet()) {
totalQueryCounter.put(key, new IntHolder());
}
for (String key : successQueryCounter.keySet()) {
successQueryCounter.put(key, new IntHolder());
}
for (String key : faultQueryCounter.keySet()) {
faultQueryCounter.put(key, new IntHolder());
}
totalApiCounter = 0;
successApiCounter = 0;
faultApiCounter = 0;
}
/**
* This updates the performance metrics for a given service.
*
* Note, as of jUDDI 3.2, procTime MUST be in milliseconds. Prior to 3.2 used nanoseconds
* @param queryObject the item that was executed
* @param queryStatus success or fail status
* @param procTime Expects time in milliseconds
*/
public synchronized void update(UDDIQuery queryObject, QueryStatus queryStatus,
long procTime) {
//log.info("Updating " + queryObject.getQuery() + " time " + procTime);
String query = queryObject.getQuery();
LongHolder totalProcTime = queryProcessingTime.get(query + " " + PROCESSING_TIME);
if (totalProcTime != null) {
totalProcTime.value += procTime;
totalApiCounter++;
} else {
throw new RuntimeException("Exception in Update : " + queryObject.getQuery()
+ " time " + procTime + " queryprocessingtime.size() + "
+ queryProcessingTime.size());
}
IntHolder queryCounter = totalQueryCounter.get(query + " " + TOTAL_QUERIES);
if (queryCounter != null) {
queryCounter.value++;
} else {
throw new RuntimeException("Exception in Update : " + queryObject.getQuery()
+ " time " + procTime + " totalQueryCounter.size() + "
+ totalQueryCounter.size());
}
if (queryStatus == QueryStatus.SUCCESS) {
IntHolder successQuery = successQueryCounter.get(query + " " + SUCCESSFUL_QUERIES);
if (successQuery != null) {
successQuery.value++;
successApiCounter++;
} else {
throw new RuntimeException("Exception in Update : " + queryObject.getQuery()
+ " time " + procTime + " successQueryCounter.size() "
+ successQueryCounter.size());
}
} else if (queryStatus == queryStatus.FAILED) {
IntHolder faultQuery = faultQueryCounter.get(query + " " + FAILED_QUERIES);
if (faultQuery != null) {
faultQuery.value++;
faultApiCounter++;
} else {
throw new RuntimeException("Exception in Update : " + queryObject.getQuery()
+ " time " + procTime + " faultQueryCounter.size() "
+ faultQueryCounter.size());
}
}
}
@Override
public Object getAttribute(String attribute)
throws AttributeNotFoundException, MBeanException,
ReflectionException {
if (queryProcessingTime.containsKey(attribute)) {
return queryProcessingTime.get(attribute);
} else if (totalQueryCounter.containsKey(attribute)) {
return totalQueryCounter.get(attribute);
} else if (successQueryCounter.containsKey(attribute)) {
return successQueryCounter.get(attribute);
} else if (faultQueryCounter.containsKey(attribute)) {
return faultQueryCounter.get(attribute);
} else if (attribute.equals(TOTAL_API_QUERIES)) {
return totalApiCounter;
} else if (attribute.equals(SUCCESSFUL_API_QUERIES)) {
return successApiCounter;
} else if (attribute.equals(FAILED_API_QUERIES)) {
return faultApiCounter;
}
return null;
}
@Override
public void setAttribute(Attribute attribute)
throws AttributeNotFoundException, InvalidAttributeValueException,
MBeanException, ReflectionException {
}
@Override
public AttributeList getAttributes(String[] attributes) {
AttributeList attributeList = new AttributeList();
attributeList.add(new Attribute(TOTAL_API_QUERIES, totalApiCounter));
attributeList.add(new Attribute(SUCCESSFUL_API_QUERIES, successApiCounter));
attributeList.add(new Attribute(FAILED_API_QUERIES, faultApiCounter));
for (String key : queryProcessingTime.keySet()) {
Attribute at = new Attribute(key, queryProcessingTime.get(key).toString());
attributeList.add(at);
}
for (String key : totalQueryCounter.keySet()) {
Attribute at = new Attribute(key, totalQueryCounter.get(key).toString());
attributeList.add(at);
}
for (String key : successQueryCounter.keySet()) {
Attribute at = new Attribute(key, successQueryCounter.get(key).toString());
attributeList.add(at);
}
for (String key : faultQueryCounter.keySet()) {
Attribute at = new Attribute(key, faultQueryCounter.get(key).toString());
attributeList.add(at);
}
return attributeList;
}
@Override
public AttributeList setAttributes(AttributeList attributes) {
return null;
}
@Override
public Object invoke(String actionName, Object[] params, String[] signature)
throws MBeanException, ReflectionException {
if (actionName.equalsIgnoreCase(RESET_COUNTER)) {
resetCounts();
return "Invoking the " + actionName + " on the lifecycle.";
} else {
throw new ReflectionException(new NoSuchMethodException(actionName));
}
}
@Override
public MBeanInfo getMBeanInfo() {
// the extra 3 added are for totalApiQueries, faultApiQueries, and
// successfulApiQueries
int count = queryProcessingTime.size() + totalQueryCounter.size() +
successQueryCounter.size() + faultQueryCounter.size() + 3;
MBeanAttributeInfo[] attrs = new MBeanAttributeInfo[count];
int counter = 0;
attrs[counter] = new MBeanAttributeInfo(
TOTAL_API_QUERIES, "java.lang.Integer", "Property " + TOTAL_API_QUERIES,
true, false, false);
counter++;
attrs[counter] = new MBeanAttributeInfo(
SUCCESSFUL_API_QUERIES, "java.lang.Integer", "Property " + SUCCESSFUL_API_QUERIES,
true, false, false);
counter++;
attrs[counter] = new MBeanAttributeInfo(
FAILED_API_QUERIES, "java.lang.Integer", "Property " + FAILED_API_QUERIES,
true, false, false);
counter++;
for (String key : queryProcessingTime.keySet()) {
attrs[counter] = new MBeanAttributeInfo(
key, "java.lang.Double", "Property " + key, true, false, false);
counter++;
}
for (String key : totalQueryCounter.keySet()) {
attrs[counter] = new MBeanAttributeInfo(
key, "java.lang.Integer", "Property " + key, true, false, false);
counter++;
}
for (String key : successQueryCounter.keySet()) {
attrs[counter] = new MBeanAttributeInfo(
key, "java.lang.Integer", "Property " + key, true, false, false);
counter++;
}
for (String key : faultQueryCounter.keySet()) {
attrs[counter] = new MBeanAttributeInfo(
key, "java.lang.Integer", "Property " + key, true, false, false);
counter++;
}
MBeanOperationInfo[] opers = {
new MBeanOperationInfo(
RESET_COUNTER, "Reset the counter",
null, "void", MBeanOperationInfo.ACTION)
};
return new MBeanInfo(this.getClass().getName(), "Service Counter MBean",
attrs, null, opers, null);
}
private static final class IntHolder implements Serializable
{
int value ;
@Override
public String toString() {
return Integer.toString(value);
}
}
private static final class LongHolder implements Serializable
{
long value ;
@Override
public String toString() {
return Long.toString(value);
}
}
}