Skip to content

Commit b168173

Browse files
committed
callStack: add Annotations handlers for instant events
implement IOutputAnnotationProvider and override methods add marker data to tooltips Signed-off-by: Yassine Ibhir <[email protected]>
1 parent 7f18609 commit b168173

File tree

4 files changed

+143
-6
lines changed

4 files changed

+143
-6
lines changed

analysis/org.eclipse.tracecompass.analysis.profiling.core/src/org/eclipse/tracecompass/analysis/profiling/core/callstack/CallStackAnalysis.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,13 @@ public abstract class CallStackAnalysis extends TmfStateSystemAnalysisModule imp
5454
*/
5555
public static final String CALL_STACK = "CallStack"; //$NON-NLS-1$
5656

57+
/**
58+
* Annotations string state attribute
59+
*
60+
* @since 2.6
61+
*/
62+
public static final String ANNOTATIONS = "Markers"; //$NON-NLS-1$
63+
5764
private static final String[] DEFAULT_PROCESSES_PATTERN = new String[] { CallStackStateProvider.PROCESSES, "*" }; //$NON-NLS-1$
5865

5966
private static final String[] DEFAULT_THREADS_PATTERN = new String[] { "*" }; //$NON-NLS-1$

analysis/org.eclipse.tracecompass.analysis.profiling.core/src/org/eclipse/tracecompass/analysis/profiling/core/callstack/CallStackStateProvider.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,4 +277,15 @@ public void done() {
277277
/* Override to provide a thread name */
278278
return null;
279279
}
280+
281+
/**
282+
* Add an event as a marker to the Annotations attribute
283+
*
284+
* @param event
285+
* The event to add as a marker
286+
* @since 2.6
287+
*/
288+
protected void addMarker(ITmfEvent event) {
289+
// Do nothing, this is a placeholder for overriding.
290+
}
280291
}

analysis/org.eclipse.tracecompass.analysis.profiling.core/src/org/eclipse/tracecompass/internal/analysis/profiling/core/instrumented/FlameChartDataProvider.java

Lines changed: 117 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
import org.eclipse.tracecompass.analysis.profiling.core.base.FlameWithKernelPalette;
3939
import org.eclipse.tracecompass.analysis.profiling.core.base.ICallStackElement;
4040
import org.eclipse.tracecompass.analysis.profiling.core.callgraph.ICalledFunction;
41+
import org.eclipse.tracecompass.analysis.profiling.core.callstack.CallStackAnalysis;
4142
import org.eclipse.tracecompass.analysis.profiling.core.callstack2.CallStack;
4243
import org.eclipse.tracecompass.analysis.profiling.core.callstack2.CallStackDepth;
4344
import org.eclipse.tracecompass.analysis.profiling.core.callstack2.CallStackSeries;
@@ -48,7 +49,10 @@
4849
import org.eclipse.tracecompass.internal.analysis.profiling.core.instrumented.FlameChartEntryModel.EntryType;
4950
import org.eclipse.tracecompass.internal.analysis.profiling.core.model.ModelManager;
5051
import org.eclipse.tracecompass.internal.analysis.profiling.core.model.ProcessStatusInterval;
52+
import org.eclipse.tracecompass.internal.tmf.core.model.filters.FetchParametersUtils;
5153
import org.eclipse.tracecompass.segmentstore.core.ISegment;
54+
import org.eclipse.tracecompass.statesystem.core.ITmfStateSystem;
55+
import org.eclipse.tracecompass.statesystem.core.exceptions.StateSystemDisposedException;
5256
import org.eclipse.tracecompass.statesystem.core.exceptions.TimeRangeException;
5357
import org.eclipse.tracecompass.statesystem.core.interval.ITmfStateInterval;
5458
import org.eclipse.tracecompass.tmf.core.dataprovider.DataProviderParameterUtils;
@@ -57,6 +61,13 @@
5761
import org.eclipse.tracecompass.tmf.core.model.IOutputStyleProvider;
5862
import org.eclipse.tracecompass.tmf.core.model.OutputElementStyle;
5963
import org.eclipse.tracecompass.tmf.core.model.OutputStyleModel;
64+
import org.eclipse.tracecompass.tmf.core.model.StyleProperties;
65+
import org.eclipse.tracecompass.tmf.core.model.StyleProperties.SymbolType;
66+
import org.eclipse.tracecompass.tmf.core.model.annotations.Annotation;
67+
import org.eclipse.tracecompass.tmf.core.model.annotations.AnnotationCategoriesModel;
68+
import org.eclipse.tracecompass.tmf.core.model.annotations.AnnotationModel;
69+
import org.eclipse.tracecompass.tmf.core.model.annotations.IOutputAnnotationProvider;
70+
import org.eclipse.tracecompass.tmf.core.model.filters.SelectionTimeQueryFilter;
6071
import org.eclipse.tracecompass.tmf.core.model.timegraph.ITimeGraphArrow;
6172
import org.eclipse.tracecompass.tmf.core.model.timegraph.ITimeGraphDataProvider;
6273
import org.eclipse.tracecompass.tmf.core.model.timegraph.ITimeGraphRowModel;
@@ -70,6 +81,7 @@
7081
import org.eclipse.tracecompass.tmf.core.response.ITmfResponse;
7182
import org.eclipse.tracecompass.tmf.core.response.ITmfResponse.Status;
7283
import org.eclipse.tracecompass.tmf.core.response.TmfModelResponse;
84+
import org.eclipse.tracecompass.tmf.core.statesystem.TmfStateSystemAnalysisModule;
7385
import org.eclipse.tracecompass.tmf.core.symbols.ISymbolProvider;
7486
import org.eclipse.tracecompass.tmf.core.symbols.SymbolProviderManager;
7587
import org.eclipse.tracecompass.tmf.core.symbols.SymbolProviderUtils;
@@ -84,6 +96,7 @@
8496
import com.google.common.collect.BiMap;
8597
import com.google.common.collect.HashBiMap;
8698
import com.google.common.collect.ImmutableList;
99+
import com.google.common.collect.ImmutableMap;
87100
import com.google.common.collect.ImmutableList.Builder;
88101
import com.google.common.collect.ImmutableMultimap;
89102
import com.google.common.collect.Multimap;
@@ -95,7 +108,7 @@
95108
*
96109
* @author Geneviève Bastien
97110
*/
98-
public class FlameChartDataProvider extends AbstractTmfTraceDataProvider implements ITimeGraphDataProvider<FlameChartEntryModel>, IOutputStyleProvider {
111+
public class FlameChartDataProvider extends AbstractTmfTraceDataProvider implements ITimeGraphDataProvider<FlameChartEntryModel>, IOutputAnnotationProvider, IOutputStyleProvider {
99112

100113
/**
101114
* Provider ID.
@@ -283,6 +296,34 @@ public TmfModelResponse<Map<String, String>> fetchTooltip(Map<String, Object> fe
283296
if (selectedDepth == null) {
284297
return null;
285298
}
299+
Map<String, String> tooltips = new HashMap<>();
300+
if (fFcProvider instanceof TmfStateSystemAnalysisModule) {
301+
ITmfStateSystem ss = ((TmfStateSystemAnalysisModule) fFcProvider).getStateSystem();
302+
if (ss != null) {
303+
try {
304+
int parentQuark = ss.getParentAttributeQuark(ss.getParentAttributeQuark(selectedDepth.getQuark()));
305+
int annotQuark = ss.optQuarkRelative(parentQuark, CallStackAnalysis.ANNOTATIONS);
306+
if (annotQuark != ITmfStateSystem.INVALID_ATTRIBUTE) {
307+
ITmfStateInterval interval = ss.querySingleState(time, annotQuark);
308+
if (!interval.getStateValue().isNull()) {
309+
String annotValue = interval.getStateValue().unboxStr();
310+
String cleaned = annotValue.replace("{", "").replace("}", "");
311+
String[] pairs = cleaned.split(", ");
312+
for (String pair : pairs) {
313+
String[] keyValue = pair.split("=", 2);
314+
if (keyValue.length == 2) {
315+
tooltips.put(keyValue[0].trim(), keyValue[1].trim());
316+
}
317+
}
318+
}
319+
}
320+
return tooltips;
321+
322+
} catch (StateSystemDisposedException e) {
323+
return null;
324+
}
325+
}
326+
}
286327
Multimap<CallStackDepth, ISegment> csFunctions = fFcProvider.queryCallStacks(Collections.singleton(selectedDepth), Collections.singleton(time));
287328
Collection<ISegment> functions = csFunctions.get(selectedDepth);
288329
if (functions.isEmpty()) {
@@ -293,7 +334,6 @@ public TmfModelResponse<Map<String, String>> fetchTooltip(Map<String, Object> fe
293334
return null;
294335
}
295336
ICalledFunction currentFct = (ICalledFunction) next;
296-
Map<String, String> tooltips = new HashMap<>();
297337
int threadId = currentFct.getThreadId();
298338
if (threadId > 0) {
299339
tooltips.put(String.valueOf(Messages.FlameChartDataProvider_ThreadId), String.valueOf(threadId));
@@ -345,7 +385,8 @@ public TmfModelResponse<TmfTreeModel<FlameChartEntryModel>> fetchTree(Map<String
345385
boolean complete = fcProvider.isComplete();
346386
CallStackSeries callstack = fcProvider.getCallStackSeries();
347387
if (callstack == null) {
348-
// Explicitly tell the client that the analysis is completed to prevent further polling
388+
// Explicitly tell the client that the analysis is completed to
389+
// prevent further polling
349390
if (complete) {
350391
return new TmfModelResponse<>(new TmfTreeModel<>(Collections.emptyList(), Collections.emptyList()), ITmfResponse.Status.COMPLETED, CommonStatusMessage.COMPLETED);
351392
}
@@ -710,4 +751,77 @@ public TmfModelResponse<OutputStyleModel> fetchStyle(Map<String, Object> fetchPa
710751
Map<String, OutputElementStyle> styles = FlameWithKernelPalette.getInstance().getStyles();
711752
return new TmfModelResponse<>(new OutputStyleModel(styles), ITmfResponse.Status.COMPLETED, CommonStatusMessage.COMPLETED);
712753
}
754+
755+
@Override
756+
public TmfModelResponse<AnnotationCategoriesModel> fetchAnnotationCategories(Map<String, Object> fetchParameters, @Nullable IProgressMonitor monitor) {
757+
return new TmfModelResponse<>(new AnnotationCategoriesModel(Collections.singletonList(CallStackAnalysis.ANNOTATIONS)), ITmfResponse.Status.COMPLETED, CommonStatusMessage.COMPLETED);
758+
}
759+
760+
@Override
761+
public TmfModelResponse<AnnotationModel> fetchAnnotations(Map<String, Object> fetchParameters, @Nullable IProgressMonitor monitor) {
762+
763+
if (!(fFcProvider instanceof TmfStateSystemAnalysisModule)) {
764+
return new TmfModelResponse<>(null, ITmfResponse.Status.FAILED, CommonStatusMessage.ANALYSIS_INITIALIZATION_FAILED);
765+
}
766+
767+
TmfStateSystemAnalysisModule csa = (TmfStateSystemAnalysisModule) fFcProvider;
768+
ITmfStateSystem ss = csa.getStateSystem();
769+
if (ss == null) {
770+
return new TmfModelResponse<>(null, ITmfResponse.Status.FAILED, CommonStatusMessage.STATE_SYSTEM_FAILED);
771+
}
772+
773+
SelectionTimeQueryFilter filter = FetchParametersUtils.createSelectionTimeQuery(fetchParameters);
774+
if (filter == null) {
775+
return new TmfModelResponse<>(null, ITmfResponse.Status.COMPLETED, CommonStatusMessage.COMPLETED);
776+
}
777+
778+
Map<Long, FlameChartEntryModel> selectedEntries = getSelectedEntries(fetchParameters);
779+
List<Annotation> annotations = new ArrayList<>();
780+
try {
781+
for (Entry<@NonNull Long, @NonNull FlameChartEntryModel> entry : selectedEntries.entrySet()) {
782+
long csId = entry.getValue().getId();
783+
CallStackDepth cs = fIdToCallstack.get(csId);
784+
if (cs == null) {
785+
continue;
786+
}
787+
int parentQuark = ss.getParentAttributeQuark(ss.getParentAttributeQuark(cs.getQuark()));
788+
int markersQuark = ss.optQuarkRelative(parentQuark, CallStackAnalysis.ANNOTATIONS);
789+
if (markersQuark != ITmfStateSystem.INVALID_ATTRIBUTE) {
790+
List<Long> times = DataProviderParameterUtils.extractTimeRequested(fetchParameters);
791+
for (ITmfStateInterval markerInterval : ss.query2D(Collections.singleton(markersQuark), times)) {
792+
if (!markerInterval.getStateValue().isNull()) {
793+
long startTime = markerInterval.getStartTime();
794+
// Find callstack depth at marker start time
795+
int depth = 0;
796+
for (int i = 1; i <= ss.getNbAttributes(); i++) {
797+
int depthQuark = ss.optQuarkRelative(cs.getQuark(), String.valueOf(i));
798+
if (depthQuark != ITmfStateSystem.INVALID_ATTRIBUTE) {
799+
ITmfStateInterval depthInterval = ss.querySingleState(startTime, depthQuark);
800+
if (!depthInterval.getStateValue().isNull()) {
801+
depth = i;
802+
}
803+
}
804+
}
805+
long entryId = entry.getKey();
806+
long rowId = (depth > 0) ? entryId + depth : entryId;
807+
String annotValue = markerInterval.getStateValue().unboxStr();
808+
String cleaned = annotValue.replace("{", "").replace("}", "");
809+
String[] pairs = cleaned.split(", ");
810+
if (pairs.length > 0) {
811+
OutputElementStyle style = new OutputElementStyle(null, ImmutableMap.of(
812+
StyleProperties.COLOR, "#7D3D31", //$NON-NLS-1$
813+
StyleProperties.HEIGHT, 0.33f,
814+
StyleProperties.SYMBOL_TYPE, SymbolType.DIAMOND));
815+
annotations.add(new Annotation(startTime, 1, rowId, pairs[0], style));
816+
}
817+
}
818+
}
819+
}
820+
}
821+
} catch (StateSystemDisposedException e) {
822+
return new TmfModelResponse<>(null, ITmfResponse.Status.FAILED, e.getMessage());
823+
}
824+
825+
return new TmfModelResponse<>(new AnnotationModel(Collections.singletonMap(CallStackAnalysis.ANNOTATIONS, annotations)), ITmfResponse.Status.COMPLETED, CommonStatusMessage.COMPLETED);
826+
}
713827
}

tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/widgets/timegraph/widgets/TimeGraphControl.java

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2361,9 +2361,14 @@ private void oldDrawMarker(IMarkerEvent marker, GC gc, Rectangle rect, int color
23612361
gc.setAlpha(OPAQUE);
23622362
String label = marker.getLabel();
23632363
if (fLabelsVisible && label != null && marker.getEntry() != null) {
2364-
label = label.substring(0, Math.min(label.indexOf('\n') != -1 ? label.indexOf('\n') : label.length(), MAX_LABEL_LENGTH));
2365-
gc.setForeground(color);
2366-
Utils.drawText(gc, label, rect.x - gc.textExtent(label).x, rect.y, true);
2364+
StyleManager styleManager = getStyleManager();
2365+
OutputElementStyle elementStyle = getElementStyle(marker);
2366+
Object symbolType = (elementStyle != null) ? styleManager.getStyle(elementStyle, StyleProperties.SYMBOL_TYPE) : null;
2367+
if (symbolType == null || symbolType == SymbolType.NONE) {
2368+
label = label.substring(0, Math.min(label.indexOf('\n') != -1 ? label.indexOf('\n') : label.length(), MAX_LABEL_LENGTH));
2369+
gc.setForeground(color);
2370+
Utils.drawText(gc, label, rect.x - gc.textExtent(label).x, rect.y, true);
2371+
}
23672372
}
23682373
}
23692374

0 commit comments

Comments
 (0)