Scripting

This plugin adds support for scripting in Trace Compass. It uses the Eclipse EASE project as the scripting framework. It supports python, javascript, ruby, groovy, among others.

The following image shows the Trace Compass EASE environment, with some comments on the various available scripting languages

 Engines and modules

Install Trace Compass with EASE support

To use Trace Compass Scripting modules, one needs to have the latest development snapshot of Trace Compass, or at least the stable 5.0 release.

The full installation procedure depends on the language one wishes to use for scripting. Here follows the details.

Javascript

For Javascript, the feature is available through the Tools -> Add-ons... under the Analyses category. You can search for the Trace Compass Scripting Javascript (Incubation) feature and click ``Finish``.

 Javascript feature

It will automatically install the required Trace Compass Scripting (Incubation) feature and all related features to edit and execute javascript with EASE.

After Trace Compass restart, the feature will be available.

Others

For any other language, there is some additional steps to install the full support.

First, you need to install the Trace Compass Scripting (Incubation) feature of Trace Compass through the Tools -> Add-ons.

 Scripting feature

Then, for each language, one needs to install 2 components:

Here is the EASE page describing the supported engines/editors

To install the EASE language support, go to the Help -> Install New Software... menu. From the list of available update site, select the ease update site. It should be already available after installing the Trace Compass feature. In case it is not, you can add it using the following link http://download.eclipse.org/ease/update/release.

 Install New Software

Then under the EASE Language Support category, select the appropriate feature. There are some duplicates, you should look at the Version of the feature, it should be the latest one (0.6.0.x). For instance, to add python support, you need to select the EASE Py4J Support (Incubation). Then complete the installation.

 Py4J Feature Installation

If an editor is not installed, the script files will be opened in an external text editor instead of in Trace Compass. That may be sufficient for small scripts, but having code completion, etc can be handy too. Follow the links in the the supported engines/editors page for the appropriate engine and follow the instructions to install its editor in Eclipse. They are external tools and sometimes, IDEs of their own, so they might add a lot of content and dependencies to Trace Compass.

Create and execute a script

Trace Compass scripts are not associated with a trace or trace type, do not integrate well with the analysis framework, so you will not see any scripted views under a trace. A script needs to be run manually for each trace and it will run on the currently active trace.

Anywhere in Trace Compass workspace, you can create a script file. For example, right-click on a project, the select New -> File and name it <some-file-name>.js.

The file should now open in a javascript editor in Trace Compass. You can write your script in that file. The next sections describes the API to Trace Compass and show an example script.

 Javascript editor

To run the script, make sure the trace you want to run it on is active, then, right-click on the script and select Run As -> EASE Script.

 Run EASE Script

Debug script and results

You can also run the script in debug mode ( Debug As -> EASE Script). Also, any print statement in the script will be displayed in the Console that opens when the script is run.

The Trace Compass branch downloaded above changed the State System Explorer so that it can open state system files directly, without requiring them to be linked to an analysis. The state system created by the script can thus be explored using that view.

Trace Compass Scripting API and examples

Here's an example javascript script for Trace Compass. It is the equivalent of Active Thread analysis in Trace Compass, ie saves the currently running process on each CPU.

// load Trace Compass modules
loadModule('/TraceCompass/Analysis');
loadModule('/TraceCompass/DataProvider');
loadModule('/TraceCompass/View');

// Create an analysis named activetid.js.
var analysis = getAnalysis("activetid.js");

if (analysis == null) {
	print("Trace is null");
	exit();
}

// Get the analysis's state system so we can fill it, false indicates to create a new state system even if one already exists, true would re-use an existing state system
var ss = analysis.getStateSystem(false);

// The analysis itself is in this function
function runAnalysis() {
	// Get the event iterator for the trace
	var iter = analysis.getEventIterator();

	var event = null;
	// Parse all events
	while (iter.hasNext()) {

		event = iter.next();

		// Do something when the event is a sched_switch
		if (event.getName() == "sched_switch") {
			// This function is a wrapper to get the value of field CPU in the event, or return null if the field is not present
			cpu = getFieldValue(event, "CPU");
			tid = getFieldValue(event, "next_tid");
			if ((cpu != null) && (tid != null)) {
				// Write the tid to the state system, for the attribute corresponding to the cpu
				quark = ss.getQuarkAbsoluteAndAdd(cpu);
				// modify the value, tid is a long, so "" + tid make sure it's a string for display purposes
				ss.modifyAttribute(event.getTimestamp().toNanos(), "" + tid, quark);
			}
		}

	}
	// Done parsing the events, close the state system at the time of the last event, it needs to be done manually otherwise the state system will still be waiting for values and will not be considered finished building
	if (event != null) {
		ss.closeHistory(event.getTimestamp().toNanos());
	}
}

// This condition verifies if the state system is completed. For instance, if it had been built in a previous run of the script, it wouldn't run again.
if (!ss.waitUntilBuilt(0)) {
	// State system not built, run the analysis
	runAnalysis();
}

function getEntries(filter) {
	quarks = ss.getQuarks("*");
	// Prepare the CPU names and sort them
	var cpus = [];
	for (i = 0; i < quarks.size(); i++) {
		quark = quarks.get(i);
		cpus.push(ss.getAttributeName(quark));
	}
	cpus.sort(function(a,b){return Number(a) - Number(b)});
	var entries = [];
	for (i = 0; i < cpus.length; i++) {
		cpu = cpus[i];
		quark = ss.getQuarkAbsolute(cpu);
		entries.push(createEntry({'quark' : quark, 'name' : "CPU " + cpu}));
	}
	return entries;
}

// Get a time graph provider from this analysis, displaying all attributes (which are the cpus here)
provider = createTimeGraphProvider(analysis, {'path' : '*'});
if (provider != null) {
	// Open a time graph view displaying this provider
	openTimeGraphView(provider);
}

print("Done");

Other script examples can be found in the git tree of the Trace Compass Incubator here https://git.eclipse.org/c/tracecompass.incubator/org.eclipse.tracecompass.incubator.git/tree/analyses/org.eclipse.tracecompass.incubator.scripting.core.tests/testfiles/scripts