Skip to content

Commit 3f0cf28

Browse files
opentracing: Add flamegraph analysis to opentracing
*The AbstractCalledFunction is updated to maintain a list of children Intervals. Because in Async. Executions the overlapped time of children is calculated twice for self time calculation. So we need to maintain a list of time Intervals of children to compute the intersection of them for Self Time Calculations. Signed-off-by: Fariba Daneshgar <[email protected]>
1 parent cbbd65c commit 3f0cf28

File tree

10 files changed

+755
-2
lines changed

10 files changed

+755
-2
lines changed

callstack/org.eclipse.tracecompass.incubator.callstack.core/src/org/eclipse/tracecompass/incubator/internal/callstack/core/instrumented/callgraph/AbstractCalledFunction.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,5 +181,16 @@ public boolean equals(@Nullable Object obj) {
181181
Objects.equals(fParent, other.getParent()) &&
182182
Objects.equals(getSymbol(), other.getSymbol()));
183183
}
184+
185+
private long getChildIntersection(TmfTimeRange chlInt) {
186+
long intersection = 0;
187+
for (TmfTimeRange childInterval:fChildrenIntervals ) {
188+
TmfTimeRange intersect = chlInt.getIntersection(childInterval);
189+
if (intersect!=null) {
190+
intersection += (intersect.getEndTime().getValue())-(intersect.getStartTime().getValue());
191+
}
192+
}
193+
return intersection;
194+
}
195+
}
184196

185-
}

tracetypes/org.eclipse.tracecompass.incubator.opentracing.core/META-INF/MANIFEST.MF

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,20 @@ Require-Bundle: org.eclipse.core.runtime,
1212
org.eclipse.core.resources,
1313
org.eclipse.tracecompass.common.core,
1414
org.eclipse.tracecompass.tmf.core,
15+
org.eclipse.tracecompass.segmentstore.core;bundle-version="3.1.0",
16+
org.eclipse.tracecompass.incubator.callstack.core;bundle-version="0.1.4",
17+
org.eclipse.tracecompass.analysis.os.linux.core;bundle-version="8.2.0",
18+
org.eclipse.tracecompass.incubator.analysis.core;bundle-version="0.1.1",
19+
org.eclipse.tracecompass.analysis.counters.core;bundle-version="2.2.1",
20+
org.eclipse.tracecompass.analysis.timing.core;bundle-version="5.5.0",
1521
com.google.gson,
1622
com.google.guava,
1723
org.apache.commons.lang3,
1824
org.eclipse.tracecompass.ctf.core,
1925
org.eclipse.tracecompass.jsontrace.core,
20-
org.eclipse.jdt.annotation;bundle-version="[2.0.0,3.0.0)";resolution:=optional
26+
org.eclipse.jdt.annotation;bundle-version="[2.0.0,3.0.0)";resolution:=optional,
27+
org.eclipse.tracecompass.datastore.core;bundle-version="1.3.0",
28+
org.eclipse.tracecompass.incubator.concurrentcallstack.core;bundle-version="0.1.0"
2129
Export-Package: org.eclipse.tracecompass.incubator.internal.opentracing.core;x-friends:="org.eclipse.tracecompass.incubator.opentracing.core.tests",
2230
org.eclipse.tracecompass.incubator.internal.opentracing.core.analysis.spanlife;x-friends:="org.eclipse.tracecompass.incubator.opentracing.core.tests,org.eclipse.tracecompass.incubator.opentracing.ui",
2331
org.eclipse.tracecompass.incubator.internal.opentracing.core.event,

tracetypes/org.eclipse.tracecompass.incubator.opentracing.core/plugin.xml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,18 @@
4040
class="org.eclipse.tracecompass.incubator.internal.opentracing.core.trace.OpenTracingExperiment">
4141
</tracetype>
4242
</module>
43+
<module
44+
analysis_module="org.eclipse.tracecompass.incubator.opentracing.core.analysis.callstack.OpenTracingCallstackAnalysis"
45+
automatic="false"
46+
icon="icons/callstack_view.gif"
47+
id="org.eclipse.tracecompass.incubator.opentracing.analysis.callstack"
48+
name="Open Tracing Callstack">
49+
<tracetype
50+
applies="true"
51+
class="org.eclipse.tracecompass.incubator.internal.opentracing.core.trace.OpenTracingTrace">
52+
</tracetype>
53+
</module>
54+
4355
</extension>
4456
<extension
4557
point="org.eclipse.tracecompass.tmf.core.dataprovider">

tracetypes/org.eclipse.tracecompass.incubator.opentracing.core/src/org/eclipse/tracecompass/incubator/internal/opentracing/core/Activator.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
package org.eclipse.tracecompass.incubator.internal.opentracing.core;
1313

1414
import org.eclipse.tracecompass.common.core.TraceCompassActivator;
15+
import org.eclipse.tracecompass.incubator.concurrentstatesystem.core.SpanCustomValue;
16+
import org.eclipse.tracecompass.internal.provisional.statesystem.core.statevalue.CustomStateValue;
1517

1618
/**
1719
* Activator
@@ -39,6 +41,7 @@ public static TraceCompassActivator getInstance() {
3941

4042
@Override
4143
protected void startActions() {
44+
CustomStateValue.registerCustomFactory(SpanCustomValue.CUSTOM_TYPE_ID, SpanCustomValue.FACTORY);
4245
}
4346

4447
@Override
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,209 @@
1+
package org.eclipse.tracecompass.incubator.opentracing.core.analysis.callstack;
2+
3+
import java.util.Arrays;
4+
import java.util.HashMap;
5+
import java.util.List;
6+
import java.util.Map;
7+
import java.util.Objects;
8+
import java.util.TreeMap;
9+
10+
import org.eclipse.jdt.annotation.NonNull;
11+
import org.eclipse.jdt.annotation.Nullable;
12+
import org.eclipse.tracecompass.incubator.callstack.core.instrumented.statesystem.InstrumentedCallStackAnalysis;
13+
import org.eclipse.tracecompass.incubator.internal.opentracing.core.event.IOpenTracingConstants;
14+
import org.eclipse.tracecompass.statesystem.core.ITmfStateSystemBuilder;
15+
import org.eclipse.tracecompass.statesystem.core.statevalue.TmfStateValue;
16+
import org.eclipse.tracecompass.tmf.core.event.ITmfEvent;
17+
import org.eclipse.tracecompass.tmf.core.event.ITmfEventField;
18+
import org.eclipse.tracecompass.tmf.core.statesystem.AbstractTmfStateProvider;
19+
import org.eclipse.tracecompass.tmf.core.statesystem.ITmfStateProvider;
20+
import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
21+
import org.eclipse.tracecompass.tmf.core.trace.TmfTraceUtils;
22+
23+
/**
24+
* Span Callstack state provider
25+
*
26+
* @author Fateme Faraji Daneshgar
27+
*
28+
*/
29+
public class AsincCallStackStateProvider extends AbstractTmfStateProvider {
30+
31+
/**
32+
* Thread attribute
33+
*
34+
* @since 2.0
35+
*/
36+
public static final String PROCESSES = "Processes"; //$NON-NLS-1$
37+
38+
/**
39+
* Unknown process ID
40+
*
41+
* @since 2.0
42+
*/
43+
public static final int UNKNOWN_PID = -1;
44+
45+
/**
46+
* Unknown name
47+
*
48+
* @since 2.0
49+
*/
50+
public static final String UNKNOWN = "UNKNOWN"; //$NON-NLS-1$
51+
52+
53+
private static final int MAX_STACK_DEPTH = 100000;
54+
55+
private final Map<String, Integer> fStackDepthMap;
56+
private TreeMap<Long, List<Integer>> fPrevEvent;
57+
private int fStateQuark = 3;
58+
59+
/**
60+
* Constructor
61+
*
62+
* @param trace
63+
* the trace to follow
64+
*/
65+
public AsincCallStackStateProvider(@NonNull ITmfTrace trace) {
66+
super(trace, OpenTracingCallstackAnalysis.ID);
67+
// fSpanMap = new HashMap<>();
68+
fStackDepthMap = new HashMap<>();
69+
fPrevEvent = new TreeMap<>();
70+
}
71+
72+
@Override
73+
public int getVersion() {
74+
return 3;
75+
}
76+
77+
@Override
78+
public @NonNull ITmfStateProvider getNewInstance() {
79+
return new AsincCallStackStateProvider(getTrace());
80+
}
81+
82+
@Override
83+
protected void eventHandle(@NonNull ITmfEvent event) {
84+
ITmfStateSystemBuilder ss = getStateSystemBuilder();
85+
if (ss == null) {
86+
return;
87+
}
88+
handleSpan(event,ss);
89+
}
90+
91+
private void handleSpan(ITmfEvent event, ITmfStateSystemBuilder ss) {
92+
long timestamp = event.getTimestamp().toNanos();
93+
if (timestamp == getTrace().getStartTime().toNanos()) {
94+
timestamp++;
95+
}
96+
Long duration = event.getContent().getFieldValue(Long.class, IOpenTracingConstants.DURATION);
97+
if (duration == null) {
98+
return;
99+
}
100+
while (!(fPrevEvent.isEmpty()) && (fPrevEvent.firstKey() < timestamp)) {
101+
long prevTime = fPrevEvent.firstKey();
102+
List<Integer> quarks = Objects.requireNonNull(fPrevEvent.get(fPrevEvent.firstKey()));
103+
ss.modifySpanAttribute(prevTime, (Object) null, quarks.get(0), quarks.get(1));
104+
fPrevEvent.remove(fPrevEvent.firstKey());
105+
}
106+
107+
String processName = event.getContent().getFieldValue(String.class, IOpenTracingConstants.TRACE_ID);
108+
109+
int processId = getProcessId(event);
110+
if (processName == null) {
111+
processName = (processId == UNKNOWN_PID) ? UNKNOWN : Integer.toString(processId);
112+
}
113+
114+
int pq = ss.getQuarkAbsoluteAndAdd(PROCESSES, processName);
115+
ss.updateOngoingState(TmfStateValue.newValueInt(processId), 1);
116+
117+
String Opname = String.valueOf(TmfTraceUtils.resolveAspectOfNameForEvent(event.getTrace(), "Name", event)); //$NON-NLS-1$
118+
String spanId = event.getContent().getFieldValue(String.class, IOpenTracingConstants.SPAN_ID);
119+
String parentId = event.getContent().getFieldValue(String.class, IOpenTracingConstants.REFERENCES + "/CHILD_OF"); //$NON-NLS-1$
120+
121+
int callStackQuark = ss.getQuarkRelativeAndAdd(pq, InstrumentedCallStackAnalysis.CALL_STACK);
122+
int stackDepth = getStackDepth(parentId);
123+
124+
Object functionEntryName = functionEntry(spanId, parentId, Opname);
125+
stackDepth++;
126+
127+
int spanQuark = ss.getQuarkRelativeAndAdd(callStackQuark, String.valueOf(stackDepth));
128+
129+
ss.modifySpanAttribute(timestamp, functionEntryName, fStateQuark, spanQuark);
130+
131+
fStackDepthMap.put(spanId, stackDepth);
132+
133+
List<Integer> quarksList = Arrays.asList(fStateQuark, spanQuark);
134+
fPrevEvent.put(timestamp + duration, quarksList);
135+
fStateQuark++;
136+
137+
}
138+
139+
protected @Nullable String getProcessName(ITmfEvent event) {
140+
141+
Long fieldValue = event.getContent().getFieldValue(Long.class, "trace_id");
142+
if (fieldValue == null) {
143+
fieldValue = event.getContent().getFieldValue(Long.class, "trace_id_low");
144+
}
145+
146+
return fieldValue == null ? "eduroam" : Long.toHexString(fieldValue);
147+
}
148+
149+
protected int getProcessId(ITmfEvent event) {
150+
Long resolve = event.getContent().getFieldValue(Long.class, "trace_id");
151+
return resolve == null ? -1 : resolve.intValue();
152+
}
153+
154+
private int getStackDepth(String parentId) {
155+
Integer stackDepth = fStackDepthMap.get(parentId);
156+
if (stackDepth == null) {
157+
stackDepth = 0;
158+
}
159+
if (stackDepth >= MAX_STACK_DEPTH) {
160+
/*
161+
* Limit stackDepth to 100000, to avoid having Attribute Trees grow
162+
* out of control due to buggy insertions
163+
*/
164+
String message = " Stack limit reached, not pushing"; //$NON-NLS-1$
165+
throw new IllegalStateException(" Quark:" + parentId + message); //$NON-NLS-1$
166+
}
167+
return stackDepth;
168+
169+
}
170+
171+
protected @Nullable Object functionEntry(String spanId, String parentId, String name) {
172+
return new SpanCustomValue(spanId, (parentId == null) ? "0" : parentId, name);
173+
174+
}
175+
176+
protected Map<String, String> MessageHashMapExtractor(ITmfEventField value) {
177+
// split the string to creat key-value pairs
178+
Map<String, String> map = new HashMap<>();
179+
// iterate over the pairs
180+
for (ITmfEventField field : value.getFields()) {
181+
Objects.requireNonNull(field);
182+
map.put(field.getName(), field.getValue().toString().trim());
183+
}
184+
if (map.isEmpty()) {
185+
String valueString = (String) Objects.requireNonNull(value.getValue());
186+
String[] values = valueString.split(",");
187+
for (String tuple : values) {
188+
String[] parts = tuple.split("=");
189+
map.put(parts[0], parts[1].trim());
190+
}
191+
}
192+
return map;
193+
}
194+
195+
@Override
196+
public void done() {
197+
ITmfStateSystemBuilder ss = getStateSystemBuilder();
198+
if (ss == null) {
199+
return;
200+
}
201+
while (!(fPrevEvent.isEmpty())) {
202+
long prevTime = fPrevEvent.firstKey();
203+
List<Integer> quarks = Objects.requireNonNull(fPrevEvent.get(fPrevEvent.firstKey()));
204+
ss.modifySpanAttribute(prevTime, (Object) null, quarks.get(0), quarks.get(1));
205+
fPrevEvent.remove(fPrevEvent.firstKey());
206+
}
207+
}
208+
209+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package org.eclipse.tracecompass.incubator.opentracing.core.analysis.callstack;
2+
3+
import java.util.Collections;
4+
import java.util.Objects;
5+
6+
import org.eclipse.jdt.annotation.NonNull;
7+
import org.eclipse.tracecompass.tmf.core.analysis.requirements.TmfAbstractAnalysisRequirement;
8+
import org.eclipse.tracecompass.tmf.core.statesystem.ITmfStateProvider;
9+
10+
/**
11+
*
12+
*/
13+
public class OpenTracingCallstackAnalysis extends SpanCallStackAnalysis {
14+
/**
15+
* ID
16+
*/
17+
public static final @NonNull String ID = "org.eclipse.tracecompass.incubator.opentracing.analysis.callstack"; //$NON-NLS-1$
18+
19+
20+
@Override
21+
protected ITmfStateProvider createStateProvider() {
22+
return new AsincCallStackStateProvider(Objects.requireNonNull(getTrace()));
23+
}
24+
25+
26+
@Override
27+
public @NonNull Iterable<@NonNull TmfAbstractAnalysisRequirement> getAnalysisRequirements() {
28+
return Collections.emptyList();
29+
}
30+
31+
32+
33+
}

0 commit comments

Comments
 (0)