blob: 01921cfeb3a206afe23a1460159e98bdaa360632 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2019 École Polytechnique de Montréal
*
* All rights reserved. This program and the accompanying materials are
* made available under the terms of the Eclipse Public License 2.0 which
* accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*******************************************************************************/
package org.eclipse.tracecompass.incubator.scripting.core.callstack;
import org.eclipse.ease.modules.ScriptParameter;
import org.eclipse.ease.modules.WrapToScript;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.tracecompass.incubator.analysis.core.weighted.tree.AllGroupDescriptor;
import org.eclipse.tracecompass.incubator.analysis.core.weighted.tree.IWeightedTreeGroupDescriptor;
import org.eclipse.tracecompass.incubator.analysis.core.weighted.tree.IWeightedTreeProvider;
import org.eclipse.tracecompass.incubator.analysis.core.weighted.tree.IWeightedTreeSet;
import org.eclipse.tracecompass.incubator.analysis.core.weighted.tree.WeightedTree;
import org.eclipse.tracecompass.incubator.analysis.core.weighted.tree.WeightedTreeGroupBy;
import org.eclipse.tracecompass.incubator.analysis.core.weighted.tree.WeightedTreeUtils;
import org.eclipse.tracecompass.incubator.analysis.core.weighted.tree.diff.DifferentialWeightedTreeProvider;
import org.eclipse.tracecompass.incubator.internal.callstack.core.flamegraph.FlameGraphDataProvider;
import org.eclipse.tracecompass.incubator.internal.scripting.core.data.provider.ScriptingDataProviderManager;
import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
/**
* Provide an API to manipulate callstacks and weighted trees. This modules uses
* objects of class {@link IWeightedTreeProvider} that can be obtained from a
* trace by requesting an analysis that implements the interface.
* <p>
* For example, the following scriptlet would get the LTTng-UST CallStack
* (Incubator) analysis, which implements the weighted tree provider, for the
* active LTTng UST trace. The object can then be used as parameter for the
* methods of this module.
* </p>
*
* <pre>
* trace = getActiveTrace()
* wtProvider = getTraceAnalysis(trace, "org.eclipse.tracecompass.incubator.callstack.core.lttng.ust");
* </pre>
*
* @author Geneviève Bastien
*/
public class CallStackScriptingModule {
/**
* Group the trees of the provider's main treeset, up to the requested
* level. For example, if a treeset's elements are grouped in a hierarchical
* manner with the following element hierarchy:
*
* <pre>
* element 1
* {@literal -->} element 2
* {@literal -->} element 3
* element 4
* {@literal -->} element 5
* </pre>
*
* this method with a level of <code>1</code> would result in a treeset with
* 2 elements: <code>element 1</code> and <code>element 4</code>, each
* containing a merge of the weighted trees of their respective children
* elements.
*
* @param <N>
* The type of objects represented by each node in the tree
* @param <E>
* The type of elements used to group the trees
* @param provider
* The {@link IWeightedTreeProvider} object containing the
* treeset for which to group trees.
* @param level
* The hierarchical level after which the elements' trees will be
* merged together. A value of <code>0</code> would group all the
* weighted trees together in a single element.
* @return The weighted tree set with weighted grouped at the requested
* level.
*/
@WrapToScript
public <@NonNull N, E> IWeightedTreeSet<N, ?, WeightedTree<N>> groupTreesBy(IWeightedTreeProvider<N, E, WeightedTree<N>> provider, int level) {
IWeightedTreeSet<N, E, WeightedTree<N>> treeSet = provider.getTreeSet();
IWeightedTreeGroupDescriptor groupDescriptor = getGroupDescriptor(provider, level);
if (groupDescriptor != null) {
return WeightedTreeGroupBy.groupWeightedTreeBy(groupDescriptor, treeSet, provider);
}
return treeSet;
}
private static <@NonNull N> @Nullable IWeightedTreeGroupDescriptor getGroupDescriptor(IWeightedTreeProvider<N, ?, WeightedTree<N>> provider, int level) {
IWeightedTreeGroupDescriptor groupDescriptor = provider.getGroupDescriptor();
if (level == 0) {
return AllGroupDescriptor.getInstance();
}
int i = 1;
while (groupDescriptor != null && i < level) {
groupDescriptor = groupDescriptor.getNextGroup();
i++;
}
return groupDescriptor;
}
/**
* Differentiates 2 treesets
*
* @param provider
* The original weighted tree provider, whose values will be used
* for the metrics, palettes, etc
* @param first
* The base treeset for comparison
* @param second
* The treeset to compare to
* @param minSignificantValue
* The value as a percentage (between 0 and 100), under which is
* difference should not be highlighted
* @param maxSignificantValue
* The value as a percentage (between 0 and 100), above which the
* difference should be highlighted at the maximal value.
* @param <N>
* The type of data that goes in the trees
* @return The resulting differential weighted tree provider containing the
* result of the difference between the 2 trees
*/
@WrapToScript
public <@NonNull N> @Nullable DifferentialWeightedTreeProvider<N> diffTreeSets(IWeightedTreeProvider<N, ?, WeightedTree<N>> provider,
IWeightedTreeSet<N, @NonNull ?, WeightedTree<N>> first,
IWeightedTreeSet<N, @NonNull ?, WeightedTree<N>> second,
@ScriptParameter(defaultValue = "-1") int minSignificantValue,
@ScriptParameter(defaultValue = "-1") int maxSignificantValue) {
DifferentialWeightedTreeProvider<@NonNull N> diffTrees = WeightedTreeUtils.diffTreeSets(provider, first, second);
if (diffTrees != null && minSignificantValue >= 0) {
diffTrees.setHeatThresholds(minSignificantValue, maxSignificantValue);
}
return diffTrees;
}
/**
* Get a flame graph data provider for a weighted tree provider. The
* weighted tree provider can be the result of the {@link #diffTreeSets}
* method
*
* @param <N>
* The type of data that goes in the trees
* @param <E>
* The type of elements used to group the trees
* @param <T>
* The type of the tree provided
* @param trace
* The trace for which to get the data provider. It is required
* for the data provider base class.
* @param provider
* The weighted tree provider that will provide the data
* @param id
* The ID of the data provider
* @return The resulting flame graph data provider
*/
@SuppressWarnings("restriction")
@WrapToScript
public <@NonNull N, E, @NonNull T extends WeightedTree<N>> FlameGraphDataProvider<N, E, T> getFlameGraphDataProvider(ITmfTrace trace, IWeightedTreeProvider<N, E, T> provider, String id) {
FlameGraphDataProvider<@NonNull N, E, @NonNull T> dataProvider = new FlameGraphDataProvider<>(trace, provider, ScriptingDataProviderManager.PROVIDER_ID + ':' + id);
ScriptingDataProviderManager.getInstance().registerDataProvider(trace, dataProvider);
return dataProvider;
}
}