/**
* Helios, OpenSource Monitoring
* Brought to you by the Helios Development Group
*
* Copyright 2012, Helios Development Group and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*
*/
package org.helios.apmrouter.byteman;
import org.cliffc.high_scale_lib.Counter;
import org.cliffc.high_scale_lib.NonBlockingHashMap;
import org.helios.apmrouter.jmx.JMXHelper;
import org.helios.apmrouter.metric.ICEMetric;
import org.helios.apmrouter.metric.MetricType;
import org.helios.apmrouter.trace.ITracer;
import org.helios.apmrouter.trace.TracerFactory;
import org.helios.apmrouter.util.SimpleLogger;
import org.jboss.byteman.agent.RuleScript;
import org.jboss.byteman.rule.Rule;
import org.jboss.byteman.rule.helper.Helper;
import org.snmp4j.PDU;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.concurrent.TimeUnit;
/**
* <p>Title: APMAgentHelper</p>
* <p>Description: An APM Agent {@link ITracer} implementation exposed as a byteman {@link Helper}, plus a handful of supporting utility constructs.</p>
* <p>Company: Helios Development Group LLC</p>
* @author Whitehead (nwhitehead AT heliosdev DOT org)
* <p><code>org.helios.apmrouter.byteman.APMAgentHelper</code></p>
*/
public class APMAgentHelper extends Helper implements ITracer {
/** The {@link ITracer} instance created when this helper is activated */
protected static ITracer itracer = null;
/** Metrics accumulator */
protected final NonBlockingHashMap<String, Counter> metrics = new NonBlockingHashMap<String, Counter>();
/**
* Creates a new APMAgentHelper
* @param rule The rules the helper is created for
*/
public APMAgentHelper(Rule rule) {
super(rule);
}
/**
* Called when the first instance of this helper class is instantiated for an active rule
*/
public static void activated() {
itracer = TracerFactory.getTracer();
}
/**
* Called when the last rule using this helper class is uninstalled
*/
public static void deactivated() {
/* */
}
/**
* Called when a rule using this helper is installed
* @param rule The rule that this helper was instantiated for
*/
public static void installed(Rule rule) {
RuleScript ruleMBean = rule.getRuleScript();
try {
if(!JMXHelper.getHeliosMBeanServer().isRegistered(ruleMBean.getObjectName())) {
JMXHelper.getHeliosMBeanServer().registerMBean(ruleMBean, ruleMBean.getObjectName());
}
} catch (Exception ex) {
SimpleLogger.warn("Failed to register Rule MBean for [", ruleMBean, "]", ex);
}
}
/**
* Called when a rule using this helper is uninstalled
* @param rule The rule that this helper was instantiated for
*/
public static void uninstalled(Rule rule) {
RuleScript ruleMBean = rule.getRuleScript();
try {
if(JMXHelper.getHeliosMBeanServer().isRegistered(ruleMBean.getObjectName())) {
JMXHelper.getHeliosMBeanServer().unregisterMBean(ruleMBean.getObjectName());
}
} catch (Exception ex) {
SimpleLogger.warn("Failed to unregister Rule MBean for [", ruleMBean, "]", ex);
}
}
/**
* {@inheritDoc}
* @see org.helios.apmrouter.trace.ITracer#getDirectTracer()
*/
@Override
public ITracer getDirectTracer() {
return this;
}
/**
* {@inheritDoc}
* @see org.helios.apmrouter.trace.ITracer#resetStats()
*/
@Override
public void resetStats() {
itracer.resetStats();
}
/**
* {@inheritDoc}
* @see org.helios.apmrouter.trace.ITracer#trace(java.lang.Object, java.lang.CharSequence, org.helios.apmrouter.metric.MetricType, java.lang.CharSequence[])
*/
@Override
public ICEMetric trace(Object value, CharSequence name, MetricType type,
CharSequence... namespace) {
return itracer.trace(value, name, type, namespace);
}
/**
* {@inheritDoc}
* @see org.helios.apmrouter.trace.ITracer#traceDirect(long, java.util.concurrent.TimeUnit, java.lang.Object, java.lang.CharSequence, org.helios.apmrouter.metric.MetricType, java.lang.CharSequence[])
*/
@Override
public ICEMetric traceDirect(long timeout, TimeUnit unit, Object value,
CharSequence name, MetricType type, CharSequence... namespace) {
return itracer.traceDirect(timeout, unit, value, name, type, namespace);
}
/**
* {@inheritDoc}
* @see org.helios.apmrouter.trace.ITracer#traceDirect(java.lang.Object, java.lang.CharSequence, org.helios.apmrouter.metric.MetricType, java.lang.CharSequence[])
*/
@Override
public ICEMetric traceDirect(Object value, CharSequence name,
MetricType type, CharSequence... namespace) {
return itracer.traceDirect(value, name, type, namespace);
}
/**
* {@inheritDoc}
* @see org.helios.apmrouter.trace.ITracer#traceCounter(long, java.lang.CharSequence, java.lang.CharSequence[])
*/
@Override
public ICEMetric traceCounter(long value, CharSequence name,
CharSequence... namespace) {
return itracer.traceCounter(value, name, namespace);
}
/**
* {@inheritDoc}
* @see org.helios.apmrouter.trace.ITracer#traceIncrement(long, java.lang.CharSequence, java.lang.CharSequence[])
*/
@Override
public ICEMetric traceIncrement(long value, CharSequence name,
CharSequence... namespace) {
return itracer.traceIncrement(value, name, namespace);
}
/**
* {@inheritDoc}
* @see org.helios.apmrouter.trace.ITracer#traceIncrement(java.lang.CharSequence, java.lang.CharSequence[])
*/
@Override
public ICEMetric traceIncrement(CharSequence name,
CharSequence... namespace) {
return itracer.traceIncrement(name, namespace);
}
/**
* {@inheritDoc}
* @see org.helios.apmrouter.trace.ITracer#traceIntervalIncrement(long, java.lang.CharSequence, java.lang.CharSequence[])
*/
@Override
public ICEMetric traceIntervalIncrement(long value, CharSequence name,
CharSequence... namespace) {
return itracer.traceIntervalIncrement(value, name, namespace);
}
/**
* {@inheritDoc}
* @see org.helios.apmrouter.trace.ITracer#traceIntervalIncrement(java.lang.CharSequence, java.lang.CharSequence[])
*/
@Override
public ICEMetric traceIntervalIncrement(CharSequence name,
CharSequence... namespace) {
return itracer.traceIntervalIncrement(name, namespace);
}
/**
* {@inheritDoc}
* @see org.helios.apmrouter.trace.ITracer#traceGauge(long, java.lang.CharSequence, java.lang.CharSequence[])
*/
@Override
public ICEMetric traceGauge(long value, CharSequence name,
CharSequence... namespace) {
return itracer.traceGauge(value, name, namespace);
}
/**
* {@inheritDoc}
* @see org.helios.apmrouter.trace.ITracer#traceDeltaGauge(long, java.lang.CharSequence, java.lang.CharSequence[])
*/
@Override
public ICEMetric traceDeltaGauge(long value, CharSequence name,
CharSequence... namespace) {
return itracer.traceDeltaGauge(value, name, namespace);
}
/**
* {@inheritDoc}
* @see org.helios.apmrouter.trace.ITracer#traceDeltaCounter(long, java.lang.CharSequence, java.lang.CharSequence[])
*/
@Override
public ICEMetric traceDeltaCounter(long value, CharSequence name,
CharSequence... namespace) {
return itracer.traceDeltaCounter(value, name, namespace);
}
/**
* {@inheritDoc}
* @see org.helios.apmrouter.trace.ITracer#traceString(java.lang.CharSequence, java.lang.CharSequence, java.lang.CharSequence[])
*/
@Override
public ICEMetric traceString(CharSequence value, CharSequence name,
CharSequence... namespace) {
return itracer.traceString(value, name, namespace);
}
/**
* {@inheritDoc}
* @see org.helios.apmrouter.trace.ITracer#traceError(java.lang.Throwable, java.lang.CharSequence, java.lang.CharSequence[])
*/
@Override
public ICEMetric traceError(Throwable value, CharSequence name,
CharSequence... namespace) {
return itracer.traceError(value, name, namespace);
}
/**
* {@inheritDoc}
* @see org.helios.apmrouter.trace.ITracer#traceBlob(java.io.Serializable, java.lang.CharSequence, java.lang.CharSequence[])
*/
@Override
public ICEMetric traceBlob(Serializable value, CharSequence name,
CharSequence... namespace) {
return itracer.traceBlob(value, name, namespace);
}
/**
* {@inheritDoc}
* @see org.helios.apmrouter.trace.ITracer#traceBlobDirect(java.io.Serializable, java.lang.CharSequence, java.lang.CharSequence[])
*/
@Override
public ICEMetric traceBlobDirect(Serializable value, CharSequence name,
CharSequence... namespace) {
return itracer.traceBlobDirect(value, name, namespace);
}
/**
* {@inheritDoc}
* @see org.helios.apmrouter.trace.ITracer#tracePDU(org.snmp4j.PDU, java.lang.CharSequence, java.lang.CharSequence[])
*/
@Override
public ICEMetric tracePDU(PDU pdu, CharSequence name,
CharSequence... namespace) {
return itracer.tracePDU(pdu, name, namespace);
}
/**
* {@inheritDoc}
* @see org.helios.apmrouter.trace.ITracer#tracePDUDirect(org.snmp4j.PDU, java.lang.CharSequence, java.lang.CharSequence[])
*/
@Override
public ICEMetric tracePDUDirect(PDU pdu, CharSequence name,
CharSequence... namespace) {
return itracer.tracePDUDirect(pdu, name, namespace);
}
/**
* {@inheritDoc}
* @see org.helios.apmrouter.trace.ITracer#getHost()
*/
@Override
public String getHost() {
return itracer.getHost();
}
/**
* {@inheritDoc}
* @see org.helios.apmrouter.trace.ITracer#getAgent()
*/
@Override
public String getAgent() {
return itracer.getAgent();
}
/**
* {@inheritDoc}
* @see org.helios.apmrouter.trace.ITracer#getSentMetrics()
*/
@Override
public long getSentMetrics() {
return itracer.getSentMetrics();
}
/**
* {@inheritDoc}
* @see org.helios.apmrouter.trace.ITracer#getDroppedMetrics()
*/
@Override
public long getDroppedMetrics() {
return itracer.getDroppedMetrics();
}
/**
* {@inheritDoc}
* @see org.helios.apmrouter.trace.ITracer#getQueuedMetrics()
*/
@Override
public long getQueuedMetrics() {
return itracer.getQueuedMetrics();
}
public Object getFieldValue(Object target, String fieldName) {
try {
Field f = null;
try {
f = target.getClass().getDeclaredField(fieldName);
} catch (NoSuchFieldException nox) {
f = target.getClass().getField(fieldName);
}
f.setAccessible(true);
Object value = f.get(Modifier.isStatic(f.getModifiers()) ? null : target);
SimpleLogger.info("Extracted field value [", value, "]");
return value;
} catch (Exception ex) {
SimpleLogger.warn("Failed to get field value for [" , target.getClass().getName() , ".", fieldName, "]", ex);
return null;
}
}
public void logMessage(String msg) {
SimpleLogger.info(msg);
}
/**
* {@inheritDoc}
* @see org.helios.apmrouter.trace.ITracer#trace(java.lang.Object, java.lang.CharSequence, java.lang.Object, java.lang.CharSequence[])
*/
@Override
public ICEMetric trace(Object value, CharSequence name, Object type, CharSequence... namespace) {
try { return trace(value, name, MetricType.valueOf(type), namespace); } catch (Exception ex) { return null; }
}
/**
* {@inheritDoc}
* @see org.helios.apmrouter.trace.ITracer#traceDirect(java.lang.Object, java.lang.CharSequence, java.lang.Object, java.lang.CharSequence[])
*/
@Override
public ICEMetric traceDirect(Object value, CharSequence name, Object type, CharSequence... namespace) {
return traceDirect(value, name, MetricType.valueOf(type), namespace);
}
}