Skip to content

Commit 8b77c42

Browse files
committed
tmf: Add raw events data provider
Add TmfRawEventsDataProvider and its factory. Add them to o.e.tc.tmf.core.dataprovider extension point. Signed-off-by: Patrick Tasse <[email protected]>
1 parent c20d8a4 commit 8b77c42

File tree

5 files changed

+294
-3
lines changed

5 files changed

+294
-3
lines changed

tmf/org.eclipse.tracecompass.tmf.core/plugin.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,5 +76,9 @@
7676
class="org.eclipse.tracecompass.internal.provisional.tmf.core.model.events.TmfEventTableDataProviderFactory"
7777
id="org.eclipse.tracecompass.internal.provisional.tmf.core.model.events.TmfEventTableDataProvider">
7878
</dataProviderFactory>
79+
<dataProviderFactory
80+
class="org.eclipse.tracecompass.internal.provisional.tmf.core.model.events.TmfRawEventsDataProviderFactory"
81+
id="org.eclipse.tracecompass.tmf.core.model.events.data">
82+
</dataProviderFactory>
7983
</extension>
8084
</plugin>

tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/internal/provisional/tmf/core/model/events/Messages.java

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/**********************************************************************
2-
* Copyright (c) 2019 Ericsson
2+
* Copyright (c) 2019, 2025 Ericsson
33
*
44
* All rights reserved. This program and the accompanying materials are
55
* made available under the terms of the Eclipse Public License 2.0 which
@@ -14,7 +14,7 @@
1414
import org.eclipse.osgi.util.NLS;
1515

1616
/**
17-
* Message bundle for the new events table messages.
17+
* Message bundle for events data provider messages.
1818
*/
1919
public class Messages extends NLS {
2020
private static final String BUNDLE_NAME = "org.eclipse.tracecompass.internal.provisional.tmf.core.model.events.messages"; //$NON-NLS-1$
@@ -26,6 +26,14 @@ public class Messages extends NLS {
2626
* The events table data provider help text
2727
*/
2828
public static @Nullable String EventsTableDataProviderFactory_DescriptionText;
29+
/**
30+
* The raw event data title
31+
*/
32+
public static @Nullable String RawEventsDataProvider_Title;
33+
/**
34+
* The raw event data provider help text
35+
*/
36+
public static @Nullable String RawEventsDataProviderFactory_DescriptionText;
2937

3038
static {
3139
// initialize resource bundle
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,224 @@
1+
/**********************************************************************
2+
* Copyright (c) 2018, 2025 Ericsson
3+
*
4+
* All rights reserved. This program and the accompanying materials are
5+
* made available under the terms of the Eclipse Public License 2.0 which
6+
* accompanies this distribution, and is available at
7+
* https://www.eclipse.org/legal/epl-2.0/
8+
*
9+
* SPDX-License-Identifier: EPL-2.0
10+
**********************************************************************/
11+
12+
package org.eclipse.tracecompass.internal.provisional.tmf.core.model.events;
13+
14+
import java.util.ArrayList;
15+
import java.util.LinkedHashMap;
16+
import java.util.List;
17+
import java.util.Map;
18+
import java.util.regex.Pattern;
19+
20+
import org.eclipse.core.runtime.IProgressMonitor;
21+
import org.eclipse.jdt.annotation.Nullable;
22+
import org.eclipse.tracecompass.tmf.core.event.ITmfEvent;
23+
import org.eclipse.tracecompass.tmf.core.event.ITmfEventField;
24+
import org.eclipse.tracecompass.tmf.core.event.aspect.TmfBaseAspects;
25+
import org.eclipse.tracecompass.tmf.core.model.AbstractTmfTraceDataProvider;
26+
import org.eclipse.tracecompass.tmf.core.model.CommonStatusMessage;
27+
import org.eclipse.tracecompass.tmf.core.model.object.IObjectDataProvider;
28+
import org.eclipse.tracecompass.tmf.core.model.object.ObjectModel;
29+
import org.eclipse.tracecompass.tmf.core.response.ITmfResponse;
30+
import org.eclipse.tracecompass.tmf.core.response.TmfModelResponse;
31+
import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimestamp;
32+
import org.eclipse.tracecompass.tmf.core.trace.ITmfContext;
33+
import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
34+
35+
import com.google.common.collect.ImmutableMap;
36+
import com.google.common.collect.ImmutableMap.Builder;
37+
38+
/**
39+
* This data provider will return an object representing an array of raw event
40+
* data.
41+
*
42+
* @author Patrick Tasse
43+
*/
44+
public class TmfRawEventsDataProvider extends AbstractTmfTraceDataProvider implements IObjectDataProvider {
45+
46+
/**
47+
* Extension point ID.
48+
*/
49+
public static final String ID = "org.eclipse.tracecompass.tmf.core.model.events.data"; //$NON-NLS-1$
50+
51+
private static final String SELECTION_RANGE = "selection_range"; //$NON-NLS-1$
52+
private static final String START = "start"; //$NON-NLS-1$
53+
private static final String NEXT = "next"; //$NON-NLS-1$
54+
private static final String PREVIOUS = "previous"; //$NON-NLS-1$
55+
private static final String TYPE = "type"; //$NON-NLS-1$
56+
private static final String FIELD = "field"; //$NON-NLS-1$
57+
private static final String COUNT = "count"; //$NON-NLS-1$
58+
59+
/**
60+
* Constructor
61+
*
62+
* @param trace
63+
* A trace on which we are interested to fetch a raw event model
64+
*/
65+
public TmfRawEventsDataProvider(ITmfTrace trace) {
66+
super(trace);
67+
}
68+
69+
@Override
70+
public String getId() {
71+
return ID;
72+
}
73+
74+
@Override
75+
public TmfModelResponse<ObjectModel> fetchData(Map<String, Object> fetchParameters, @Nullable IProgressMonitor monitor) {
76+
ITmfTrace trace = getTrace();
77+
long rank = 0L;
78+
Long prev = null;
79+
Long next = null;
80+
Object selectionRangeObj = fetchParameters.get(SELECTION_RANGE);
81+
Object nextObj = fetchParameters.get(NEXT);
82+
Object previousObj = fetchParameters.get(PREVIOUS);
83+
Object typeObj = fetchParameters.get(TYPE);
84+
Object fieldObj = fetchParameters.get(FIELD);
85+
Object countObj = fetchParameters.get(COUNT);
86+
if (nextObj instanceof Number nextNum) {
87+
rank = nextNum.longValue();
88+
prev = rank;
89+
previousObj = null;
90+
} else if (previousObj instanceof Number previousNum) {
91+
rank = previousNum.longValue();
92+
next = rank;
93+
nextObj = null;
94+
} else if (selectionRangeObj instanceof Map<?,?> selectionRange) {
95+
if (selectionRange.get(START) instanceof Number start) {
96+
rank = trace.seekEvent(TmfTimestamp.fromNanos(start.longValue())).getRank();
97+
}
98+
nextObj = null;
99+
previousObj = null;
100+
}
101+
Pattern eventTypePattern = (typeObj instanceof String type) ? Pattern.compile(type) : null;
102+
Pattern fieldPattern = (fieldObj instanceof String field) ? Pattern.compile(field) : null;
103+
Integer max = null;
104+
if (countObj instanceof Number count) {
105+
max = count.intValue();
106+
}
107+
if (eventTypePattern == null && fieldPattern == null && previousObj instanceof Number) {
108+
// optimize backward request when no filters specified
109+
if (max == null) {
110+
max = (int) rank;
111+
rank = 0L;
112+
} else if (rank >= max) {
113+
rank = rank - max;
114+
} else {
115+
max = (int) rank;
116+
rank = 0L;
117+
}
118+
// clear previousObj to read forwards
119+
previousObj = null;
120+
}
121+
List<Object> object = new ArrayList<>();
122+
ObjectModel model;
123+
if (previousObj instanceof Number) {
124+
// read backward
125+
while (rank > 0 && (max == null || object.size() < max)) {
126+
rank--;
127+
ITmfContext context = trace.seekEvent(rank);
128+
long eventRank = context.getRank();
129+
ITmfEvent event = trace.getNext(context);
130+
if (event == null) {
131+
break;
132+
}
133+
if (eventTypePattern == null || eventTypePattern.matcher(event.getName()).find()) {
134+
Object eventObj = convertEvent(event, eventRank, fieldPattern);
135+
if (eventObj != null) {
136+
object.add(0, eventObj);
137+
}
138+
}
139+
}
140+
model = new ObjectModel(object);
141+
if (rank > 0L) {
142+
model.setPrevious(rank);
143+
}
144+
if (next != null) {
145+
model.setNext(next);
146+
}
147+
} else {
148+
// read forward
149+
ITmfContext context = trace.seekEvent(rank);
150+
while (max == null || object.size() < max) {
151+
long eventRank = context.getRank();
152+
ITmfEvent event = trace.getNext(context);
153+
if (event == null) {
154+
break;
155+
}
156+
if (eventTypePattern == null || eventTypePattern.matcher(event.getName()).find()) {
157+
Object eventObj = convertEvent(event, eventRank, fieldPattern);
158+
if (eventObj != null) {
159+
object.add(eventObj);
160+
}
161+
}
162+
}
163+
model = new ObjectModel(object);
164+
next = context.getRank();
165+
if (trace.getNext(context) != null) {
166+
model.setNext(next);
167+
}
168+
if (prev != null && prev > 0L) {
169+
model.setPrevious(prev);
170+
}
171+
}
172+
return new TmfModelResponse<>(model, ITmfResponse.Status.COMPLETED, CommonStatusMessage.COMPLETED);
173+
}
174+
175+
private static @Nullable Object convertEvent(ITmfEvent event, long rank, @Nullable Pattern fieldPattern) {
176+
Map<String, @Nullable Object> data = new LinkedHashMap<>();
177+
178+
// Add basic event information
179+
data.put("rank", rank); //$NON-NLS-1$
180+
data.put(TmfBaseAspects.getTimestampAspect().getName(), event.getTimestamp().toNanos());
181+
data.put(TmfBaseAspects.getEventTypeAspect().getName(), event.getType().getName());
182+
Object contents = convertEventField(event.getContent(), fieldPattern);
183+
if (fieldPattern != null && contents instanceof Map map) {
184+
if (map.isEmpty()) {
185+
return null;
186+
}
187+
}
188+
data.put(TmfBaseAspects.getContentsAspect().getName(), contents);
189+
return data;
190+
}
191+
192+
private static @Nullable Object convertEventField(@Nullable ITmfEventField field, @Nullable Pattern fieldPattern) {
193+
if (field == null) {
194+
return null;
195+
}
196+
Builder<String, @Nullable Object> builder = ImmutableMap.builder();
197+
for (ITmfEventField subField : field.getFields()) {
198+
if (subField == null) {
199+
continue;
200+
}
201+
String name = subField.getName();
202+
if (fieldPattern == null || fieldPattern.matcher(name).find()) {
203+
Object value = subField.getValue();
204+
if (value instanceof ITmfEventField) {
205+
builder.put(name, convertEventField((ITmfEventField) value, null));
206+
} else {
207+
builder.put(name, value);
208+
}
209+
}
210+
}
211+
Object value = field.getValue();
212+
if (value instanceof ITmfEventField) {
213+
value = convertEventField((ITmfEventField) value, null);
214+
}
215+
ImmutableMap<String, @Nullable Object> fields = builder.build();
216+
if (value == null) {
217+
return fields;
218+
} else if (fields.isEmpty()) {
219+
return value;
220+
} else {
221+
return Map.of("value", value, "fields", fields); //$NON-NLS-1$ //$NON-NLS-2$
222+
}
223+
}
224+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/**********************************************************************
2+
* Copyright (c) 2025 Ericsson
3+
*
4+
* All rights reserved. This program and the accompanying materials are
5+
* made available under the terms of the Eclipse Public License 2.0 which
6+
* accompanies this distribution, and is available at
7+
* https://www.eclipse.org/legal/epl-2.0/
8+
*
9+
* SPDX-License-Identifier: EPL-2.0
10+
**********************************************************************/
11+
12+
package org.eclipse.tracecompass.internal.provisional.tmf.core.model.events;
13+
14+
import java.util.Collection;
15+
import java.util.Collections;
16+
17+
import org.eclipse.jdt.annotation.Nullable;
18+
import org.eclipse.tracecompass.common.core.NonNullUtils;
19+
import org.eclipse.tracecompass.tmf.core.dataprovider.IDataProviderDescriptor;
20+
import org.eclipse.tracecompass.tmf.core.dataprovider.IDataProviderDescriptor.ProviderType;
21+
import org.eclipse.tracecompass.tmf.core.dataprovider.IDataProviderFactory;
22+
import org.eclipse.tracecompass.tmf.core.model.DataProviderCapabilities;
23+
import org.eclipse.tracecompass.tmf.core.model.DataProviderDescriptor;
24+
import org.eclipse.tracecompass.tmf.core.model.ITmfDataProvider;
25+
import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
26+
27+
/**
28+
* {@link TmfRawEventsDataProvider} factory, uses the data provider extension
29+
* point.
30+
*
31+
* @author Patrick Tasse
32+
*/
33+
public class TmfRawEventsDataProviderFactory implements IDataProviderFactory {
34+
35+
private static final IDataProviderDescriptor DESCRIPTOR =
36+
new DataProviderDescriptor.Builder()
37+
.setId(TmfRawEventsDataProvider.ID)
38+
.setName(NonNullUtils.nullToEmptyString(Messages.RawEventsDataProvider_Title))
39+
.setDescription(NonNullUtils.nullToEmptyString(Messages.RawEventsDataProviderFactory_DescriptionText))
40+
.setProviderType(ProviderType.DATA)
41+
.setCapabilities(new DataProviderCapabilities.Builder().setSelectionRange(true).build())
42+
.build();
43+
44+
@Override
45+
public @Nullable ITmfDataProvider createDataProvider(ITmfTrace trace) {
46+
return new TmfRawEventsDataProvider(trace);
47+
}
48+
49+
@Override
50+
public Collection<IDataProviderDescriptor> getDescriptors(ITmfTrace trace) {
51+
return Collections.singleton(DESCRIPTOR);
52+
}
53+
}

tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/internal/provisional/tmf/core/model/events/messages.properties

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
###############################################################################
2-
# Copyright (c) 2019 Ericsson
2+
# Copyright (c) 2019, 2025 Ericsson
33
#
44
# All rights reserved. This program and the accompanying materials
55
# are made available under the terms of the Eclipse Public License 2.0
@@ -11,3 +11,5 @@
1111

1212
EventsTableDataProvider_Title=Events Table
1313
EventsTableDataProviderFactory_DescriptionText=Show the raw events in table form for a given trace
14+
RawEventsDataProvider_Title=Raw Events Data
15+
RawEventsDataProviderFactory_DescriptionText=Show the raw event data in object form for a given trace

0 commit comments

Comments
 (0)