/**
* Helios, OpenSource Monitoring
* Brought to you by the Helios Development Group
*
* Copyright 2007, 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.trace;
import org.helios.apmrouter.jmx.ITracerService;
import org.helios.apmrouter.jmx.JMXHelper;
import org.helios.apmrouter.metric.AgentIdentity;
import org.helios.apmrouter.metric.MetricType;
import org.helios.apmrouter.metric.catalog.ICEMetricCatalog;
import org.helios.apmrouter.sender.ISender;
import org.helios.apmrouter.util.SystemClock;
import org.helios.apmrouter.util.SystemClock.ElapsedTime;
import java.lang.management.ManagementFactory;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicReference;
import static org.helios.apmrouter.util.Methods.nvl;
/**
* <p>Title: TracerFactory</p>
* <p>Description: Creates new {@link ITracer} instances</p>
* <p>Company: Helios Development Group LLC</p>
* @author Whitehead (nwhitehead AT heliosdev DOT org)
* <p><code>org.helios.apmrouter.trace.TracerFactory</code></p>
*/
public class TracerFactory {
/** The default tracer */
private static final ITracer defaultTracer;
/** The current apmrouter sender */
private static final AtomicReference<ISender> sender = new AtomicReference<ISender>();
/** The collection funnel */
private static final CollectionFunnel funnel;
/** The server tracer factory (if we're on the server) */
/** The server tracer */
protected static final ITracerFactory serverTracerFactory;
/** The property name to override the default direct trace confirmation timeout */
public static final String DIRECT_TIMEOUT_PROP = "org.helios.apmrouter.direct.timeout";
/** The default direct trace confirmation timeout */
public static final long DEFAULT_DIRECT_TIMEOUT = 2000;
/** The configured direct timeout */
public static long DIRECT_TIMEOUT = DEFAULT_DIRECT_TIMEOUT;
/** The name of the server tracer factory class */
public static final String SERVER_TRACER_NAME = "org.helios.apmrouter.server.tracing.ServerTracerFactory";
/** A map of created tracers keyed by host/agent */
private static final Map<String, ITracer> tracers = new ConcurrentHashMap<String, ITracer>();
static {
serverTracerFactory = checkForServerTracer();
funnel = serverTracerFactory!=null ? null : CollectionFunnel.getInstance();
defaultTracer = serverTracerFactory!=null ? serverTracerFactory.getTracer() : new TracerImpl(AgentIdentity.ID.getHostName(), AgentIdentity.ID.getAgentName(), funnel);
registerMBean((TracerImpl)defaultTracer);
try {
DIRECT_TIMEOUT = Long.parseLong(System.getProperty(DIRECT_TIMEOUT_PROP, "" + DEFAULT_DIRECT_TIMEOUT));
} catch (Exception e) {
DIRECT_TIMEOUT = DEFAULT_DIRECT_TIMEOUT;
}
if(System.getProperties().containsKey("debug-stop")) {
long time = 60000;
try {
time = Long.parseLong(System.getProperty("debug-stop").trim());
} catch (Exception e) {
time = 60000;
};
int multiplier = 1;
String cmdLine = ManagementFactory.getRuntimeMXBean().getInputArguments().toString();
if(cmdLine.contains("agentlib:jdwp")) {
multiplier = 10*6;
}
final long ftime = time * multiplier;
System.err.println("Args:" + cmdLine);
Thread t = new Thread("DEBUG STOP THREAD") {
public void run() {
SystemClock.sleep(ftime);
System.err.println("\n\t===========================================\n\tDEBUG STOP THREAD EXITING\n\t===========================================\n");
System.exit(-99);
}
};
t.start();
System.err.println("\n\t===========================================\n\tDEBUG STOP THREAD STARTED\n\tTimeout:" + ftime + " ms." + "\n\t===========================================\n");
}
}
/**
* Checks to see if we're running on the server, in which case, we want the in-vm tracer
* @return the in-vm tracer factory or null if it could not be loaded (perhaps because we're not on the server ?)
*/
protected static ITracerFactory checkForServerTracer() {
try {
Class<?> clazz = Class.forName(SERVER_TRACER_NAME);
Method meth = clazz.getDeclaredMethod("getInstance");
ITracerFactory itf = (ITracerFactory)meth.invoke(null);
return itf;
} catch (Exception ex) {
return null;
}
}
/**
* Returns the default tracer instance
* @return the default tracer instance
*/
public static ITracer getTracer() {
return defaultTracer;
}
/**
* Registers the tracer MBean service
* @param defaultTracer the default tracer
*/
static void registerMBean(TracerImpl defaultTracer) {
try {
JMXHelper.registerMBean(ITracerService.OBJECT_NAME, new ITracerService(defaultTracer));
} catch (Exception e) {
System.err.println("Failed to register Tracer MBean. Continuing without.");
}
}
/**
* Returns a tracer instance for the passed host and agent
* @param host The host name to create a tracer for
* @param agent The agent name to create a tracer for
* @param tracerName The tracer name
* @param timeout The tracer timeout in ms.
* @return a tracer instance
*/
public static ITracer getTracer(String host, String agent, String tracerName, long timeout) {
if(serverTracerFactory!=null) return serverTracerFactory.getTracer(host, agent, tracerName, timeout);
String key = nvl(host, "Host Name").trim() + ":" + nvl(agent, "Agent Name").trim();
ITracer tracer = tracers.get(key);
if(tracer==null) {
synchronized(tracers) {
tracer = tracers.get(key);
if(tracer==null) {
tracer = new TracerImpl(host.trim(), agent.trim(), funnel);
tracers.put(key, tracer);
}
}
}
return tracer;
}
public static void mainy(String[] args) {
log("DMC Decode Test");
int LOOPS = 10;
TXContext.rollContext();
SystemClock.startTimer();
for(int i = 0; i < LOOPS; i++) {
getTracer().trace(i, "foo", MetricType.LONG_GAUGE, "bar");
//getTracer().traceString("H#" + i, "W", "G", "H");
//getTracer().traceDirect(5000, TimeUnit.MILLISECONDS, i, "bar", MetricType.LONG, "bar");
}
ElapsedTime et = SystemClock.endTimer();
log("Complete in [" + et + "]\n\tAvg Per Ms:" + et.avgMs(LOOPS) + "\n\tAvg Per Ns:" + et.avgNs(LOOPS));
}
public static void main(String[] args) {
TXContext.rollContext();
MetricType.setCompress(false);
MetricType.setDirect(false);
boolean traceBlob = false;
boolean traceLong = true;
boolean traceString = false;
final int LOOPS = 100000;
final ITracer tracer = getTracer();
log("Basic Tracing Test: [" + tracer.getHost() + "/" + tracer.getAgent() + "]");
for(int x = 0; x < 100; x++) {
for(int i = 0; i < LOOPS; i++) {
if(traceBlob) tracer.traceBlob(new Date(), "foo", "date");
if(traceLong) tracer.traceCounter(i, "foo", "bar");
if(traceString) getTracer().traceString("H#" + i, "W", "G", "H");
}
}
// SystemClock.sleep(CollectionFunnel.getInstance().getTimerPeriod()+1000);
log("Warmup Complete");
log("Starting Untokenized");
// tracer.resetStats();
SystemClock.startTimer();
for(int i = 0; i < LOOPS; i++) {
if(traceBlob) tracer.traceBlob(new Date(), "foo", "date");
if(traceLong) tracer.traceCounter(i, "foo", "bar");
if(traceString) getTracer().traceString("H#" + i, "W", "G", "H");
}
ElapsedTime et = SystemClock.endTimer();
log("FULL:\nSent:" + tracer.getSentMetrics() + "\nDropped:" + tracer.getDroppedMetrics() + "\nElapsed:" + et + "\nAvg Per:" + et.avgNs(LOOPS) + " ns");
/// TOKENIZE
ICEMetricCatalog.getInstance().setToken(tracer.getHost(), tracer.getAgent(), "foo", MetricType.LONG_GAUGE, "bar");
SystemClock.sleep(CollectionFunnel.getInstance().getTimerPeriod()+1000);
log("Starting Tokenized");
tracer.resetStats();
SystemClock.startTimer();
for(int i = 0; i < LOOPS; i++) {
if(traceBlob) tracer.traceBlob(new Date(), "foo", "date");
if(traceLong) tracer.traceCounter(i, "foo", "bar");
if(traceString) getTracer().traceString("H#" + i, "W", "G", "H");
}
et = SystemClock.endTimer();
log("TOKEN:\nSent:" + tracer.getSentMetrics() + "\nDropped:" + tracer.getDroppedMetrics() + "\nElapsed:" + et + "\nAvg Per:" + et.avgNs(LOOPS) + " ns");
SystemClock.sleep(CollectionFunnel.getInstance().getTimerPeriod()+3000);
log("\n\tTotal Sent:" + tracer.getSentMetrics());
log("\tTotal Dropped:" + tracer.getDroppedMetrics());
log("\tTotal Queued:" + tracer.getQueuedMetrics());
log(CollectionFunnel.getInstance().status());
}
public static void log(Object msg) {
System.out.println(msg);
}
}