/*******************************************************************************
* Copyright (c) 2006-2010 eBay Inc. All Rights Reserved.
* 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
*******************************************************************************/
package org.ebayopensource.turmeric.runtime.common.monitoring;
import java.lang.reflect.Constructor;
import javax.xml.namespace.QName;
import org.ebayopensource.turmeric.runtime.binding.utils.BindingUtils;
import org.ebayopensource.turmeric.runtime.common.exceptions.ErrorDataFactory;
import org.ebayopensource.turmeric.runtime.common.exceptions.ServiceRuntimeException;
import org.ebayopensource.turmeric.runtime.common.monitoring.value.MetricValue;
import org.ebayopensource.turmeric.runtime.common.monitoring.value.MetricValueFactory;
import org.ebayopensource.turmeric.runtime.errorlibrary.ErrorConstants;
/**
* MetricDef is a metric definition. It contains
*
* <UL>
* <LI> A MetricId(metric name, service admin name, and operation name): the
* unique identifier for the metric.
* <LI> A Monitoring Level. The level is used to control whether the metric will
* be logged at runtime based on runtime monitoring level setting.
* <LI> A MetricCategory. The category groups the metric into logically related groups.
* <LI> A MetricValueFactory. The factory to create Initial MetricValue for this metric.
* The framework provides a SimpleMetricValueFactory. This factory calls the given
* MetricValue's single argument constructor to create a new value where the argument
* is a MetricId.
* </UL>
* @author wdeng, ichernyshev
*/
public class MetricDef {
/**
* Indicator for applying to all operations.
*/
public final static String OP_APPLY_TO_ALL = "*";
/**
* Indicator for don't care operations.
*/
public final static String OP_DONT_CARE = null;
/**
* Apply to all services.
*/
public final static QName SVC_APPLY_TO_ALL = new QName("", "*", "");
private final String m_metricName;
private final QName m_serviceName;
private final String m_operationName;
private final MonitoringLevel m_level;
private final MetricCategory m_category;
private final MetricValueFactory m_valueFactory;
private final String m_description;
private int m_hashCode;
/**
* @param metricName The name of a metric
* @param serviceName The name of a service with whom the metric is defined.
* @param operationName The name of an operation with whom the metric is defined.
* @param level The log level of a metric.
* @param category The category of a metric.
* @param valueClass The value class for the metric, this class is used to update the value.
*
*/
public MetricDef(String metricName, QName serviceName, String operationName,
MonitoringLevel level, MetricCategory category, Class<? extends MetricValue> valueClass)
{
this(metricName, serviceName, operationName, level, category,
new SimpleMetricValueFactory(valueClass), null);
}
/**
* @param metricName The name of a metric
* @param serviceName The name of a service with whom the metric is defined.
* @param operationName The name of an operation with whom the metric is defined.
* @param level The log level of a metric.
* @param category The category of a metric.
* @param valueFactory The factory class to create MetricValue objects.
*/
public MetricDef(String metricName, QName serviceName, String operationName,
MonitoringLevel level, MetricCategory category, MetricValueFactory valueFactory)
{
this(metricName, serviceName, operationName, level, category, valueFactory, null);
}
/**
* @param metricName The name of a metric
* @param serviceName The name of a service with whom the metric is defined.
* @param operationName The name of an operation with whom the metric is defined.
* @param level The log level of a metric.
* @param category The category of a metric.
* @param valueClass The value class for the metric, this class is used to update the value.
* @param description The description of a metric.
*/
public MetricDef(String metricName, QName serviceName, String operationName,
MonitoringLevel level, MetricCategory category, Class<? extends MetricValue> valueClass,
String description)
{
this(metricName, serviceName, operationName, level, category,
new SimpleMetricValueFactory(valueClass), description);
}
/**
* @param metricName The name of a metric
* @param serviceName The name of a service with whom the metric is defined.
* @param operationName The name of an operation with whom the metric is defined.
* @param level The log level of a metric.
* @param category The category of a metric.
* @param valueFactory The factory class to create MetricValue objects.
* @param description The description of a metric.
*/
public MetricDef(String metricName, QName serviceName, String operationName,
MonitoringLevel level, MetricCategory category, MetricValueFactory valueFactory,
String description)
{
if (metricName == null || serviceName == null || level == null ||
category == null || valueFactory == null)
{
throw new NullPointerException();
}
m_metricName = metricName;
m_serviceName = serviceName;
m_operationName = operationName;
m_level = level;
m_category = category;
m_valueFactory = valueFactory;
m_description = description;
}
/**
* @return the metric name
*
*/
public final String getMetricName() {
return m_metricName;
}
/**
* @return the admin name of the service the metric is defined for.
*
*/
public final QName getServiceName() {
return m_serviceName;
}
/**
* @return the operation name the metric is defined for.
*
*/
public final String getOperationName() {
return m_operationName;
}
/**
* @return the category of the metric in the definition.
*
*/
public final MetricCategory getCategory() {
return m_category;
}
/**
* @return the monitoring level of the metric in the definition.
*
*/
public final MonitoringLevel getLevel() {
return m_level;
}
/**
* @return the MetricValueFactory of the metric in the definition.
*
*/
public final MetricValueFactory getValueFactory() {
return m_valueFactory;
}
/**
* @return the description of the MetricDef.
*
*/
public final String getDescription() {
return m_description;
}
@Override
public final int hashCode() {
if (m_hashCode == 0) {
m_hashCode = m_metricName.hashCode() ^ m_serviceName.hashCode();
}
return m_hashCode;
}
@Override
public final boolean equals(Object other) {
if (null == other || !(other instanceof MetricDef)) {
return false;
}
MetricDef otherDef = (MetricDef)other;
return m_level == otherDef.m_level &&
m_category == otherDef.m_category &&
isSameId(otherDef) &&
m_valueFactory.isSame(otherDef.m_valueFactory);
}
/**
* Returns true if the caller has the same metric id as the <code>other</code> MetricDef instance.
*
* @param other another MetricDef
* @return True if both MetricDefs have the same id.
*/
public final boolean isSameId(MetricDef other) {
if (null == other) {
return false;
}
return m_metricName.equals(other.m_metricName) &&
m_serviceName.equals(other.m_serviceName) &&
BindingUtils.sameObject(m_operationName, other.m_operationName);
}
@Override
public final String toString() {
return "MetricDef: name=" + m_metricName + ", svc=" + m_serviceName +
", op=" + m_operationName + ", level=" + m_level + ", cat=" + m_category;
}
private static class SimpleMetricValueFactory implements MetricValueFactory {
private final static Class[] METRIC_VALUE_CONSTR_TYPE = new Class[] { MetricId.class };
private final Constructor<? extends MetricValue> m_valueConstructor;
public SimpleMetricValueFactory(Class<? extends MetricValue> valueClass) {
if (valueClass == null) {
throw new NullPointerException();
}
if (!MetricValue.class.isAssignableFrom(valueClass)) {
throw new IllegalArgumentException(valueClass.getName() +
" is not a valid class for MetricValue");
}
try {
m_valueConstructor = valueClass.getConstructor(METRIC_VALUE_CONSTR_TYPE);
} catch (NoSuchMethodException e) {
throw new IllegalArgumentException(valueClass.getName() +
" does not have constructor taking MetricId: " + e.toString(), e);
} catch (SecurityException e) {
throw new IllegalArgumentException("Unable to access constructor for " +
valueClass.getName() + " due to: " + e.toString(), e);
}
}
public boolean isSame(MetricValueFactory other) {
if (!(other instanceof SimpleMetricValueFactory)) {
return false;
}
SimpleMetricValueFactory other2 = (SimpleMetricValueFactory)other;
return other2.m_valueConstructor.getDeclaringClass() == m_valueConstructor.getDeclaringClass();
}
public MetricValue create(MetricId id) {
if (id == null) {
throw new NullPointerException();
}
try {
return m_valueConstructor.newInstance(new Object[] {id});
} catch (Exception e) {
throw new ServiceRuntimeException(ErrorDataFactory.createErrorData(ErrorConstants.SVC_METRICS_CANNOT_INSTANTIATE_VALUE,
ErrorConstants.ERRORDOMAIN, new Object[] {id.toString(), e.toString()}), e);
}
}
}
}