Skip to content

Commit 82fc652

Browse files
tmf.core: Add event type children to histogram data provider
- Add individual event type histogram support to HistogramDataProvider - Track event type IDs in fEventTypeIds map - Extend fetchTree() to include event type children from statistics - Extend fetchXY() to handle event type histogram requests - Add getEventTypeHistogram() method for per-type density data - Change EventDensityViewer to use AREA chart style This allows users to view histogram density per event type in addition to total and lost events. note: this commit was made with the assistance of Claude Sonnet 4 [Added] lines in histogram Change-Id: I142886fe9fa8e154ef2825a5a01c4f51a48385ea Signed-off-by: Matthew Khouzam <[email protected]>
1 parent 7f18609 commit 82fc652

File tree

4 files changed

+96
-5
lines changed
  • ctf/org.eclipse.tracecompass.tmf.ctf.core.tests/src/org/eclipse/tracecompass/tmf/core/tests/histogram/dataprovider
  • tmf
    • org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/internal/tmf/core/histogram
    • org.eclipse.tracecompass.tmf.ui.swtbot.tests/src/org/eclipse/tracecompass/tmf/ui/swtbot/tests/views/eventdensity
    • org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/viewers/eventdensity

4 files changed

+96
-5
lines changed

ctf/org.eclipse.tracecompass.tmf.ctf.core.tests/src/org/eclipse/tracecompass/tmf/core/tests/histogram/dataprovider/HistogramDataProviderTest.java

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
import java.util.List;
1919
import java.util.Map;
20+
import java.util.Map.Entry;
2021

2122
import org.eclipse.core.runtime.Status;
2223
import org.eclipse.jdt.annotation.NonNull;
@@ -108,7 +109,10 @@ public void testHelloLost() throws TmfAnalysisException {
108109
ITmfResponse.Status.COMPLETED, treeResponse.getStatus());
109110
TmfTreeModel<@NonNull TmfTreeDataModel> treeModel = treeResponse.getModel();
110111
assertNotNull(treeModel);
111-
assertEquals(EXPECTED_FULL_PATHS, getFullPaths(treeModel.getEntries()));
112+
List<String> entries = getFullPaths(treeModel.getEntries());
113+
for (String path : EXPECTED_FULL_PATHS) {
114+
assertTrue(entries.contains(path));
115+
}
112116

113117
for (TmfTreeDataModel entry : treeModel.getEntries()) {
114118
if (!entry.getName().equals(TRACE_NAME)) {
@@ -124,7 +128,10 @@ public void testHelloLost() throws TmfAnalysisException {
124128
ITmfResponse.Status.COMPLETED, xyResponse.getStatus());
125129
ITmfXyModel xyModel = xyResponse.getModel();
126130
assertNotNull(xyModel);
127-
assertEquals(EXPECTED_YDATA, Maps.uniqueIndex(xyModel.getSeriesData(), ISeriesModel::getId));
131+
Map<Long, @NonNull ISeriesModel> data = Maps.uniqueIndex(xyModel.getSeriesData(), ISeriesModel::getId);
132+
for (Entry<Long, ISeriesModel> yEntry : EXPECTED_YDATA.entrySet()) {
133+
assertEquals(data.get(yEntry.getKey()), yEntry.getValue());
134+
}
128135
} finally {
129136
module.dispose();
130137
CtfTmfTestTraceUtils.dispose(CtfTestTrace.HELLO_LOST);

tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/internal/tmf/core/histogram/HistogramDataProvider.java

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import java.util.Collection;
1717
import java.util.Collections;
1818
import java.util.Comparator;
19+
import java.util.HashMap;
1920
import java.util.Iterator;
2021
import java.util.List;
2122
import java.util.Map;
@@ -74,6 +75,7 @@ public class HistogramDataProvider extends AbstractTmfTraceDataProvider implemen
7475
private final long fTraceId = TRACE_IDS.getAndIncrement();
7576
private final long fTotalId = TRACE_IDS.getAndIncrement();
7677
private final long fLostId = TRACE_IDS.getAndIncrement();
78+
private final Map<String, Long> fEventTypeIds = new HashMap<>();
7779

7880
/**
7981
* Constructor
@@ -101,6 +103,21 @@ public TmfModelResponse<TmfTreeModel<TmfTreeDataModel>> fetchTree(Map<String, Ob
101103
if (eventsSs.optQuarkAbsolute(Attributes.LOST_EVENTS) != ITmfStateSystem.INVALID_ATTRIBUTE) {
102104
builder.add(new TmfXyTreeDataModel(fLostId, fTraceId, Collections.singletonList(Objects.requireNonNull(Messages.HistogramDataProvider_Lost)), true, null, true));
103105
}
106+
107+
// Add event type children
108+
int eventTypesQuark = eventsSs.optQuarkAbsolute(Attributes.EVENT_TYPES);
109+
if (eventTypesQuark != ITmfStateSystem.INVALID_ATTRIBUTE) {
110+
List<Integer> eventTypeQuarks = eventsSs.getSubAttributes(eventTypesQuark, false);
111+
for (Integer quark : eventTypeQuarks) {
112+
String eventTypeName = eventsSs.getAttributeName(quark);
113+
if (!"Lost event".equals(eventTypeName)) { //$NON-NLS-1$
114+
long eventTypeId = TRACE_IDS.getAndIncrement();
115+
fEventTypeIds.put(eventTypeName, eventTypeId);
116+
builder.add(new TmfXyTreeDataModel(eventTypeId, fTraceId, Collections.singletonList(eventTypeName), true, null, true));
117+
}
118+
}
119+
}
120+
104121
if (eventsSs.waitUntilBuilt(0)) {
105122
TmfModelResponse<TmfTreeModel<TmfTreeDataModel>> response = new TmfModelResponse<>(new TmfTreeModel<>(Collections.emptyList(), builder.build()), ITmfResponse.Status.COMPLETED, CommonStatusMessage.COMPLETED);
106123
fCached = response;
@@ -145,6 +162,21 @@ public TmfModelResponse<TmfTreeModel<TmfTreeDataModel>> fetchTree(Map<String, Ob
145162
return TmfXyResponseFactory.createFailedResponse(CommonStatusMessage.STATE_SYSTEM_FAILED);
146163
}
147164
}
165+
166+
// Handle event type requests
167+
if (eventsSs != null) {
168+
for (Map.Entry<String, Long> entry : fEventTypeIds.entrySet()) {
169+
if (selected.contains(entry.getValue())) {
170+
try {
171+
YModel series = getEventTypeHistogram(eventsSs, entry.getKey(), entry.getValue(), xValues);
172+
builder.add(series);
173+
} catch (StateSystemDisposedException e) {
174+
return TmfXyResponseFactory.createFailedResponse(CommonStatusMessage.STATE_SYSTEM_FAILED);
175+
}
176+
}
177+
}
178+
}
179+
148180
boolean completed = eventsSs != null ? eventsSs.waitUntilBuilt(0) || eventsSs.getCurrentEndTime() >= filter.getEnd() : false;
149181

150182
return TmfXyResponseFactory.create(TITLE, xValues, builder.build(), completed);
@@ -212,6 +244,58 @@ private YModel getLostEvents(ITmfStateSystem ss, long[] times) throws StateSyste
212244
return new YModel(fLostId, lostName, leY);
213245
}
214246

247+
private YModel getEventTypeHistogram(ITmfStateSystem eventsSs, String eventTypeName, long eventTypeId, long[] times) throws StateSystemDisposedException {
248+
int eventTypeQuark = eventsSs.optQuarkAbsolute(Attributes.EVENT_TYPES, eventTypeName);
249+
if (eventTypeQuark == ITmfStateSystem.INVALID_ATTRIBUTE) {
250+
return new YModel(eventTypeId, getTrace().getName() + '/' + eventTypeName, new double[times.length]);
251+
}
252+
253+
List<Long> timesList = new ArrayList<>();
254+
for (long time : times) {
255+
timesList.add(time);
256+
}
257+
258+
List<Long> values = new ArrayList<>();
259+
try {
260+
List<ITmfStateInterval> rawValues = new ArrayList<>();
261+
262+
Iterable<ITmfStateInterval> intervals = eventsSs.query2D(Collections.singletonList(eventTypeQuark), timesList);
263+
for (ITmfStateInterval interval : intervals) {
264+
rawValues.add(interval);
265+
}
266+
rawValues.sort(new Comparator<ITmfStateInterval>() {
267+
@Override
268+
public int compare(ITmfStateInterval arg0, ITmfStateInterval arg1) {
269+
return Long.compare(arg0.getStartTime(), arg1.getStartTime());
270+
}
271+
});
272+
long prevValue = rawValues.get(0).getValueLong();
273+
for (ITmfStateInterval interval : rawValues) {
274+
Object value = interval.getValue();
275+
long currentValue = (value instanceof Number) ? ((Number) value).longValue() : 0;
276+
values.add(currentValue - prevValue);
277+
prevValue = currentValue;
278+
}
279+
} catch (StateSystemDisposedException e) {
280+
// Return empty data if state system is disposed
281+
for (int i = 0; i < times.length; i++) {
282+
values.add(0L);
283+
}
284+
}
285+
286+
// Pad with zeros if needed
287+
while (values.size() < times.length) {
288+
values.add(0L);
289+
}
290+
291+
double[] y = new double[times.length];
292+
for (int i = 0; i < Math.min(times.length, values.size()); i++) {
293+
y[i] = values.get(i).doubleValue();
294+
}
295+
296+
return new YModel(eventTypeId, getTrace().getName() + '/' + eventTypeName, y);
297+
}
298+
215299
private class LostEventInterval {
216300
private final long fStartTime;
217301
private final long fEndTime;

tmf/org.eclipse.tracecompass.tmf.ui.swtbot.tests/src/org/eclipse/tracecompass/tmf/ui/swtbot/tests/views/eventdensity/EventDensityViewTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,9 @@ public void testManipulatingTreeViewer() {
6666

6767
// Uncheck a leaf of the tree
6868
totalItem.uncheck();
69-
assertFalse(root.isChecked());
69+
assertTrue(root.isChecked());
7070
assertFalse(totalItem.isChecked());
71-
WaitUtils.waitUntil(c -> c.getSeriesSet().getSeries().length == 0, chart,
71+
WaitUtils.waitUntil(c -> c.getSeriesSet().getSeries().length >= 1, chart,
7272
"A data series has not been removed.");
7373
}
7474

tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/viewers/eventdensity/EventDensityViewer.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,6 @@ public EventDensityViewer(Composite parent, TmfXYChartSettings settings) {
5656

5757
@Override
5858
public @NonNull OutputElementStyle getSeriesStyle(@NonNull Long seriesId) {
59-
return getPresentationProvider().getSeriesStyle(seriesId, StyleProperties.SeriesType.BAR, DEFAULT_SERIES_WIDTH);
59+
return getPresentationProvider().getSeriesStyle(seriesId, StyleProperties.SeriesType.AREA, DEFAULT_SERIES_WIDTH);
6060
}
6161
}

0 commit comments

Comments
 (0)