/******************************************************************************* * Copyright (c) 2012, 2014 Ericsson * * 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: * Francois Chouinard - Initial API and implementation *******************************************************************************/ package fr.inria.linuxtools.internal.tmf.core; import java.io.BufferedWriter; import java.io.FileWriter; import java.io.IOException; import org.eclipse.core.runtime.Platform; import fr.inria.linuxtools.tmf.core.component.ITmfComponent; import fr.inria.linuxtools.tmf.core.component.ITmfEventProvider; import fr.inria.linuxtools.tmf.core.event.ITmfEvent; import fr.inria.linuxtools.tmf.core.request.ITmfEventRequest; import fr.inria.linuxtools.tmf.core.signal.TmfSignal; /** * The TMF Core tracer, used to trace TMF internal components. * <p> * The tracing classes are independently controlled (i.e no implicit inclusion) * from the launch configuration's Tracing. The resulting trace is stored in a * distinct file (TmfTrace.log) in a format that can later be analyzed by TMF. * <p> * The tracing classes are: * <ul> * <li><strong>Component</strong>: TMF components life-cycle * <li><strong>Request</strong>: TMF requests life-cycle * <li><strong>Signal</strong>: TMF signals triggering and distribution * <li><strong>Event</strong>: TMF trace events * </ul> * * @version 1.0 * @author Francois Chouinard */ @SuppressWarnings("nls") public class TmfCoreTracer { // ------------------------------------------------------------------------ // Constants // ------------------------------------------------------------------------ private static final String PLUGIN_ID = Activator.PLUGIN_ID; // Tracing keys (in .options) private static final String COMPONENT_TRACE_KEY = PLUGIN_ID + "/component"; private static final String REQUEST_TRACE_KEY = PLUGIN_ID + "/request"; private static final String SIGNAL_TRACE_KEY = PLUGIN_ID + "/signal"; private static final String EVENT_TRACE_KEY = PLUGIN_ID + "/event"; private static final String TRACE_FILE_NAME = "TmfTrace.log"; // ------------------------------------------------------------------------ // Attributes // ------------------------------------------------------------------------ // Classes tracing flags static boolean COMPONENT_CLASS_ENABLED = false; static boolean REQUEST_CLASS_ENABLED = false; static boolean SIGNAL_CLASS_ENABLED = false; static boolean EVENT_CLASS_ENABLED = false; // Trace log file private static BufferedWriter fTraceFile; // ------------------------------------------------------------------------ // Start/stop tracing - controlled by the plug-in // ------------------------------------------------------------------------ /** * Set the tracing flags according to the launch configuration */ public static void init() { String traceKey; boolean isTracing = false; traceKey = Platform.getDebugOption(COMPONENT_TRACE_KEY); if (traceKey != null) { COMPONENT_CLASS_ENABLED = (Boolean.valueOf(traceKey)).booleanValue(); isTracing |= COMPONENT_CLASS_ENABLED; } traceKey = Platform.getDebugOption(REQUEST_TRACE_KEY); if (traceKey != null) { REQUEST_CLASS_ENABLED = (Boolean.valueOf(traceKey)).booleanValue(); isTracing |= REQUEST_CLASS_ENABLED; } traceKey = Platform.getDebugOption(SIGNAL_TRACE_KEY); if (traceKey != null) { SIGNAL_CLASS_ENABLED = (Boolean.valueOf(traceKey)).booleanValue(); isTracing |= SIGNAL_CLASS_ENABLED; } traceKey = Platform.getDebugOption(EVENT_TRACE_KEY); if (traceKey != null) { EVENT_CLASS_ENABLED = (Boolean.valueOf(traceKey)).booleanValue(); isTracing |= EVENT_CLASS_ENABLED; } // Create trace log file if any of the flags was set if (isTracing) { try { fTraceFile = new BufferedWriter(new FileWriter(TRACE_FILE_NAME)); } catch (IOException e) { Activator.logError("Error opening log file " + TRACE_FILE_NAME, e); fTraceFile = null; } } } /** * Close the trace log file */ public static void stop() { if (fTraceFile != null) { try { fTraceFile.close(); fTraceFile = null; } catch (IOException e) { Activator.logError("Error closing log file", e); } } } // ------------------------------------------------------------------------ // Predicates // ------------------------------------------------------------------------ @SuppressWarnings("javadoc") public static boolean isComponentTraced() { return COMPONENT_CLASS_ENABLED; } @SuppressWarnings("javadoc") public static boolean isRequestTraced() { return REQUEST_CLASS_ENABLED; } @SuppressWarnings("javadoc") public static boolean isSignalTraced() { return SIGNAL_CLASS_ENABLED; } @SuppressWarnings("javadoc") public static boolean isEventTraced() { return EVENT_CLASS_ENABLED; } // ------------------------------------------------------------------------ // Tracing methods // ------------------------------------------------------------------------ /** * The central tracing method. Prepends the timestamp and the thread id * to the trace message. * * @param msg the trace message to log */ public static synchronized void trace(String msg) { // Leave when there is no place to write the message. if (fTraceFile == null) { return; } // Set the timestamp (ms resolution) long currentTime = System.currentTimeMillis(); StringBuilder message = new StringBuilder("["); message.append(currentTime / 1000); message.append("."); message.append(String.format("%1$03d", currentTime % 1000)); message.append("] "); // Set the thread id message.append("[TID="); message.append(String.format("%1$03d", Thread.currentThread().getId())); message.append("] "); // Append the trace message message.append(msg); // Write to file try { fTraceFile.write(message.toString()); fTraceFile.newLine(); fTraceFile.flush(); } catch (IOException e) { Activator.logError("Error writing to log file", e); } } // ------------------------------------------------------------------------ // TMF Core specific trace formatters // ------------------------------------------------------------------------ @SuppressWarnings("javadoc") public static void traceComponent(ITmfComponent component, String msg) { if (COMPONENT_CLASS_ENABLED) { String message = ("[CMP] Cmp=" + component.getName() + " " + msg); trace(message); } } @SuppressWarnings("javadoc") public static void traceRequest(ITmfEventRequest request, String msg) { if (REQUEST_CLASS_ENABLED) { String message = ("[REQ] Req=" + request.getRequestId() + " " + msg); trace(message); } } @SuppressWarnings("javadoc") public static void traceSignal(TmfSignal signal, String msg) { if (SIGNAL_CLASS_ENABLED) { String message = ("[SIG] Sig=" + signal.getClass().getSimpleName() + " Target=" + msg); trace(message); } } @SuppressWarnings("javadoc") public static void traceEvent(ITmfEventProvider provider, ITmfEventRequest request, ITmfEvent event) { if (EVENT_CLASS_ENABLED) { String message = ("[EVT] Provider=" + provider.toString() + ", Req=" + request.getRequestId() + ", Event=" + event.getTimestamp()); trace(message); } } }