/*******************************************************************************
* Copyright (c) 2006, 2016 Mountainminds GmbH & Co. KG and Contributors
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Marc R. Hoffmann - initial API and implementation
*
******************************************************************************/
package com.mountainminds.eclemma.internal.core;
import java.io.PrintStream;
import java.text.MessageFormat;
import org.eclipse.core.runtime.Platform;
/**
* Access to debug options and tracing facilities for this plug-in.
*/
public final class DebugOptions {
/**
* Interface for optional trace output.
*/
public interface ITracer {
/**
* Determines whether this tracer is enabled. Clients may use this method to
* avoid expensive calculation for debug output.
*
* @return <code>true</code> if the tracer is enabled
*/
public boolean isEnabled();
/**
* Prints the given debug message if the tracer is enabled.
*
* @param message
* text message for trace output
*/
public void trace(String message);
/**
* Prints the given debug message if the tracer is enabled. The parameter
* object will be inserted for the <code>{x}</code> placeholder.
*
* @param message
* text message for trace output
* @param param1
* parameter object for inserting
*/
public void trace(String message, Object param1);
/**
* Prints the given debug message if the tracer is enabled. The parameter
* object wills be inserted for the <code>{x}</code> placeholder.
*
* @param message
* text message for trace output
* @param param1
* first parameter object for inserting
* @param param2
* first parameter object for inserting
*/
public void trace(String message, Object param1, Object param2);
/**
* Prints the given debug message if the tracer is enabled. The parameter
* object wills be inserted for the <code>{x}</code> placeholder.
*
* @param message
* text message for trace output
* @param param1
* first parameter object for inserting
* @param param2
* first parameter object for inserting
* @param param3
* third parameter object for inserting
*/
public void trace(String message, Object param1, Object param2,
Object param3);
/**
* Starts a timer for the calling thread.
*/
public void startTimer();
/**
* Prints out the elapsed time since starting the timer.
*
* @param message
* identification for the timed period
*/
public void stopTimer(String message);
/**
* Start measuring heap memory usage.
*/
public void startMemoryUsage();
/**
* Print out heap memory usage since starting measurement.
*
* @param message
* identification for this memory usage output
*/
public void stopMemoryUsage(String message);
}
private static final ITracer NUL_TRACER = new ITracer() {
public boolean isEnabled() {
return false;
}
public void trace(String message) {
}
public void trace(String message, Object param1) {
}
public void trace(String message, Object param1, Object param2) {
}
public void trace(String message, Object param1, Object param2,
Object param3) {
}
public void startTimer() {
}
public void stopTimer(String message) {
}
public void startMemoryUsage() {
}
public void stopMemoryUsage(String message) {
}
};
private static class PrintStreamTracer implements ITracer {
private final PrintStream out;
private final String channel;
private final ThreadLocal<Long> starttime = new ThreadLocal<Long>();
private final ThreadLocal<Long> heapsize = new ThreadLocal<Long>();
PrintStreamTracer(String channel) {
this(channel, System.out);
}
PrintStreamTracer(String channel, PrintStream out) {
this.channel = channel;
this.out = out;
}
public boolean isEnabled() {
return true;
}
public void trace(String message) {
out.print("["); //$NON-NLS-1$
out.print(channel);
out.print("] "); //$NON-NLS-1$
out.println(message);
}
private void trace(String message, Object[] params) {
trace(MessageFormat.format(message, params));
}
public void trace(String message, Object param1) {
trace(message, new Object[] { param1 });
}
public void trace(String message, Object param1, Object param2) {
trace(message, new Object[] { param1, param2 });
}
public void trace(String message, Object param1, Object param2,
Object param3) {
trace(message, new Object[] { param1, param2, param3 });
}
public void startTimer() {
starttime.set(Long.valueOf(System.currentTimeMillis()));
}
public void stopTimer(String message) {
Long start = (Long) starttime.get();
if (start == null) {
trace("Timer {0} not startet.", message); //$NON-NLS-1$
} else {
long time = System.currentTimeMillis() - start.longValue();
trace("{0} ms for {1}", new Object[] { Long.valueOf(time), message }); //$NON-NLS-1$
}
}
public void startMemoryUsage() {
Runtime rt = Runtime.getRuntime();
heapsize.set(Long.valueOf(rt.totalMemory() - rt.freeMemory()));
}
public void stopMemoryUsage(String message) {
Long start = (Long) heapsize.get();
if (start == null) {
trace("Memory usage for {0} not started.", message); //$NON-NLS-1$
} else {
Runtime rt = Runtime.getRuntime();
long bytes = rt.totalMemory() - rt.freeMemory() - start.longValue();
trace(
"{0} bytes for {1}", new Object[] { Long.valueOf(bytes), message }); //$NON-NLS-1$
}
}
}
private static final String KEYPREFIX_DEBUG = EclEmmaCorePlugin.ID
+ "/debug/"; //$NON-NLS-1$
private static ITracer getTracer(String channel) {
String key = KEYPREFIX_DEBUG + channel;
if (Boolean.valueOf(Platform.getDebugOption(key)).booleanValue()) {
return new PrintStreamTracer(channel);
} else {
return NUL_TRACER;
}
}
public static final ITracer PERFORMANCETRACER = getTracer("performance"); //$NON-NLS-1$
public static final ITracer ANALYSISTRACER = getTracer("analysis"); //$NON-NLS-1$
private DebugOptions() {
// no instances
}
}