Skip to content

Commit e5efccf

Browse files
author
Steve Salas
committed
Merges dev/llc into master
2 parents ddf3e0e + b4a80b0 commit e5efccf

File tree

892 files changed

+136966
-1959
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

892 files changed

+136966
-1959
lines changed

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,6 @@ outputs/
1414
/distrib/dependencies/
1515
/fetch-cache
1616

17-
*.log
17+
*.log
18+
19+
dotnet-symbol-service-last-commit

agent/src/main/java/com/codedx/codepulse/agent/agent/DefaultTraceAgent.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
import com.codedx.codepulse.agent.message.MessageSenderManager;
3838
import com.codedx.codepulse.agent.message.PooledBufferService;
3939
import com.codedx.codepulse.agent.protocol.ProtocolVersion;
40-
import com.codedx.codepulse.agent.protocol.ProtocolVersion2;
40+
import com.codedx.codepulse.agent.protocol.ProtocolVersion3;
4141
import com.codedx.codepulse.agent.trace.TraceDataCollector;
4242
import com.codedx.codepulse.agent.util.ShutdownHook;
4343
import com.codedx.codepulse.agent.util.SocketFactory;
@@ -65,7 +65,7 @@ public class DefaultTraceAgent implements TraceAgent
6565
private RuntimeAgentConfigurationV1 config;
6666

6767
private final Semaphore startMutex = new Semaphore(0);
68-
private final ProtocolVersion protocol = new ProtocolVersion2();
68+
private final ProtocolVersion protocol = new ProtocolVersion3();
6969
private MinlogListener logger = null;
7070
private ClassIdentifier classIdentifier = new ClassIdentifier();
7171
private MethodIdentifier methodIdentifier = new MethodIdentifier();

agent/src/main/java/com/codedx/codepulse/agent/data/MessageDealerTraceDataCollector.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,4 +60,17 @@ public void methodExit(int methodId, boolean exThrown)
6060
ErrorHandler.handleError("error sending method exit", e);
6161
}
6262
}
63+
64+
@Override
65+
public void recordLineLevelTrace(int methodId, int startLine, int endLine, java.util.BitSet lineMap)
66+
{
67+
try
68+
{
69+
messageDealer.recordLineLevelTrace(methodId, startLine, endLine, lineMap);
70+
}
71+
catch (Exception e)
72+
{
73+
ErrorHandler.handleError("error recording line level trace", e);
74+
}
75+
}
6376
}

agent/src/main/java/com/codedx/codepulse/agent/message/MessageDealer.java

Lines changed: 114 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,17 @@
1818
package com.codedx.codepulse.agent.message;
1919

2020
import java.io.IOException;
21+
import java.util.BitSet;
22+
import java.util.HashSet;
2123
import java.util.concurrent.ConcurrentHashMap;
2224
import java.util.concurrent.ConcurrentMap;
2325
import java.util.concurrent.atomic.AtomicInteger;
2426

27+
import com.codedx.bytefrog.instrumentation.LineLevelMapper;
2528
import com.codedx.bytefrog.instrumentation.id.*;
2629

2730
import com.codedx.codepulse.agent.common.message.MessageProtocol;
31+
import com.codedx.codepulse.agent.common.message.NotSupportedException;
2832
import com.codedx.codepulse.agent.common.queue.DataBufferOutputStream;
2933

3034
/**
@@ -33,9 +37,8 @@
3337
* {@link BufferService}, then sent via the same BufferService. For events that
3438
* require mapped ids for the current thread and method signature, those ids
3539
* (along with the appropriate secondary "map" events) will be automatically
36-
* generated by an internal {@link MethodId} and {@link ThreadId}. The time of
37-
* MessageFactory's construction will be saved, and used to calculate the
38-
* "relative timestamp" for each event that requires one.
40+
* generated. The time of MessageFactory's construction will be saved, and used
41+
* to calculate the "relative timestamp" for each event that requires one.
3942
*
4043
* @author dylanh
4144
*/
@@ -45,12 +48,13 @@ public class MessageDealer
4548
private final BufferService bufferService;
4649

4750
private final long startTime = System.currentTimeMillis();
48-
private final ExceptionId exceptionIdMapper = new ExceptionId();
4951
private final ThreadId threadIdMapper = new ThreadId();
5052
private final Sequencer sequencer = new Sequencer();
5153

5254
private final MethodIdAdapter methodIdAdapter;
5355

56+
private static final int unavailableSourceLocationId = -1;
57+
5458
/**
5559
*
5660
* @param messageProtocol
@@ -85,45 +89,14 @@ public int getCurrentSequence()
8589
// ===============================
8690

8791
/**
88-
* MAP EXCEPTION (EVENT) MESSAGE
89-
*
90-
* @param exception
91-
* @param id
92-
* @throws IOException
93-
* @throws FailedToObtainBufferException
94-
* @throws FailedToSendBufferException
95-
*/
96-
public void sendMapException(String exception, int id) throws IOException,
97-
FailedToObtainBufferException, FailedToSendBufferException
98-
{
99-
DataBufferOutputStream buffer = bufferService.obtainBuffer();
100-
if (buffer != null)
101-
{
102-
boolean wrote = false;
103-
try
104-
{
105-
messageProtocol.writeMapException(buffer, id, exception);
106-
wrote = true;
107-
}
108-
finally
109-
{
110-
if (!wrote)
111-
buffer.reset();
112-
bufferService.sendBuffer(buffer);
113-
}
114-
}
115-
}
116-
117-
/**
118-
* MAP THREAD NAME (EVENT) MESSAGE
92+
* METHOD ENTRY (EVENT) MESSAGE
11993
*
120-
* @param name
121-
* @param id
94+
* @param methodId
12295
* @throws IOException
12396
* @throws FailedToObtainBufferException
12497
* @throws FailedToSendBufferException
12598
*/
126-
public void sendMapThreadName(String name, int id) throws IOException,
99+
public void sendMethodEntry(int methodId) throws IOException,
127100
FailedToObtainBufferException, FailedToSendBufferException
128101
{
129102
DataBufferOutputStream buffer = bufferService.obtainBuffer();
@@ -132,7 +105,11 @@ public void sendMapThreadName(String name, int id) throws IOException,
132105
boolean wrote = false;
133106
try
134107
{
135-
messageProtocol.writeMapThreadName(buffer, id, getTimeOffset(), name);
108+
int timestamp = getTimeOffset();
109+
int threadId = threadIdMapper.getCurrent();
110+
methodIdAdapter.mark(methodId, buffer);
111+
messageProtocol.writeMethodEntry(buffer, timestamp, sequencer.getSequence(),
112+
methodId, threadId);
136113
wrote = true;
137114
}
138115
finally
@@ -145,14 +122,15 @@ public void sendMapThreadName(String name, int id) throws IOException,
145122
}
146123

147124
/**
148-
* METHOD ENTRY (EVENT) MESSAGE
125+
* METHOD EXIT (EVENT) MESSAGE
149126
*
150127
* @param methodId
128+
* @param exThrown
151129
* @throws IOException
152130
* @throws FailedToObtainBufferException
153131
* @throws FailedToSendBufferException
154132
*/
155-
public void sendMethodEntry(int methodId) throws IOException,
133+
public void sendMethodExit(int methodId, boolean exThrown) throws IOException,
156134
FailedToObtainBufferException, FailedToSendBufferException
157135
{
158136
DataBufferOutputStream buffer = bufferService.obtainBuffer();
@@ -164,8 +142,8 @@ public void sendMethodEntry(int methodId) throws IOException,
164142
int timestamp = getTimeOffset();
165143
int threadId = threadIdMapper.getCurrent();
166144
methodIdAdapter.mark(methodId, buffer);
167-
messageProtocol.writeMethodEntry(buffer, timestamp, sequencer.getSequence(),
168-
methodId, threadId);
145+
messageProtocol.writeMethodExit(buffer, timestamp, sequencer.getSequence(),
146+
methodId, exThrown, threadId);
169147
wrote = true;
170148
}
171149
finally
@@ -177,17 +155,8 @@ public void sendMethodEntry(int methodId) throws IOException,
177155
}
178156
}
179157

180-
/**
181-
* METHOD EXIT (EVENT) MESSAGE
182-
*
183-
* @param methodId
184-
* @param exThrown
185-
* @throws IOException
186-
* @throws FailedToObtainBufferException
187-
* @throws FailedToSendBufferException
188-
*/
189-
public void sendMethodExit(int methodId, boolean exThrown) throws IOException,
190-
FailedToObtainBufferException, FailedToSendBufferException
158+
public void recordLineLevelTrace(int methodId, int startLine, int endLine, java.util.BitSet lineMap) throws IOException,
159+
FailedToObtainBufferException, FailedToSendBufferException, NotSupportedException
191160
{
192161
DataBufferOutputStream buffer = bufferService.obtainBuffer();
193162
if (buffer != null)
@@ -196,10 +165,14 @@ public void sendMethodExit(int methodId, boolean exThrown) throws IOException,
196165
try
197166
{
198167
int timestamp = getTimeOffset();
168+
199169
int threadId = threadIdMapper.getCurrent();
200-
methodIdAdapter.mark(methodId, buffer);
201-
messageProtocol.writeMethodExit(buffer, timestamp, sequencer.getSequence(),
202-
methodId, exThrown, threadId);
170+
for (int i = lineMap.nextSetBit(0); i >= 0; i = lineMap.nextSetBit(i+1)) {
171+
int sourceLocationId = methodIdAdapter.markSourceLocation(methodId, startLine+i, startLine+i, buffer);
172+
if (sourceLocationId != unavailableSourceLocationId) {
173+
messageProtocol.writeMethodVisit(buffer, timestamp, sequencer.getSequence(), methodId, sourceLocationId, threadId);
174+
}
175+
}
203176
wrote = true;
204177
}
205178
finally
@@ -218,12 +191,95 @@ private class MethodIdAdapter
218191

219192
private final ConcurrentMap<Integer, Boolean> observedIds = new ConcurrentHashMap<Integer, Boolean>();
220193

194+
private final ConcurrentMap<Integer, Integer> sourceLocationCounts = new ConcurrentHashMap<>();
195+
196+
private final AtomicInteger nextSourceLocationId = new AtomicInteger();
197+
protected final ConcurrentHashMap<String, Integer> sourceLocationMap = new ConcurrentHashMap<>();
198+
221199
public MethodIdAdapter(ClassIdentifier classIdentifier, MethodIdentifier methodIdentifier)
222200
{
223201
this.classIdentifier = classIdentifier;
224202
this.methodIdentifier = methodIdentifier;
225203
}
226204

205+
public int markSourceLocation(int methodId, int startLine, int endLine, DataBufferOutputStream buffer)
206+
throws IOException, NotSupportedException, FailedToObtainBufferException, FailedToSendBufferException {
207+
208+
mark(methodId, buffer);
209+
210+
String key = String.format("%d-%d-%d", methodId, startLine, endLine);
211+
Integer id = sourceLocationMap.get(key);
212+
if (id != null)
213+
{
214+
return id;
215+
}
216+
217+
int classId = methodIdentifier.get(methodId).getClassId();
218+
219+
ClassIdentifier.ClassInformation classInformation = classIdentifier.get(classId);
220+
LineLevelMapper llm = classInformation.getLineLevelMapper();
221+
if (llm != null) {
222+
223+
Boolean sourceLocationCountsMessageSent = sourceLocationCounts.containsKey(classId);
224+
if (!sourceLocationCountsMessageSent) {
225+
HashSet<String> mappedLocations = new HashSet<>();
226+
227+
BitSet lineNumbers = classInformation.getLineNumbers();
228+
for (int l = lineNumbers.nextSetBit(0); l >= 0; l = lineNumbers.nextSetBit(l + 1)) {
229+
BitSet b = new BitSet();
230+
b.set(0);
231+
LineLevelMapper.MappedCoverage mappedCoverage[] = llm.map(l, b);
232+
if (mappedCoverage != null) {
233+
StringBuilder s = new StringBuilder();
234+
for (LineLevelMapper.MappedCoverage mappedCoverageItem : mappedCoverage) {
235+
for (int q = mappedCoverageItem.lines.nextSetBit(0); q >= 0; q = mappedCoverageItem.lines.nextSetBit(q + 1)) {
236+
s.append(mappedCoverageItem.startLine + q);
237+
s.append("; ");
238+
}
239+
}
240+
mappedLocations.add(s.toString());
241+
}
242+
}
243+
244+
int mappingsCount = mappedLocations.size();
245+
messageProtocol.writeSourceLocationCount(buffer, methodId, mappingsCount);
246+
sourceLocationCounts.put(classId, mappingsCount);
247+
}
248+
249+
BitSet bitSet = new BitSet();
250+
bitSet.set(0, endLine - startLine + 1);
251+
252+
LineLevelMapper.MappedCoverage mappedCoverage[] = llm.map(startLine, bitSet);
253+
if (mappedCoverage == null) {
254+
return unavailableSourceLocationId;
255+
}
256+
257+
int newStartLine = Integer.MAX_VALUE;
258+
int newEndLine = Integer.MIN_VALUE;
259+
for (LineLevelMapper.MappedCoverage mappedCoverageItem: mappedCoverage){
260+
for (int l = mappedCoverageItem.lines.nextSetBit(0); l >= 0; l = mappedCoverageItem.lines.nextSetBit(l + 1)) {
261+
newStartLine = l < newStartLine ? l : newStartLine;
262+
newEndLine = l > newEndLine ? l : newEndLine;
263+
}
264+
}
265+
266+
// adjust for zero-based line offset
267+
startLine = newStartLine + 1;
268+
endLine = newEndLine + 1;
269+
}
270+
271+
Integer newId = nextSourceLocationId.getAndIncrement();
272+
id = sourceLocationMap.putIfAbsent(key, newId);
273+
274+
if (id == null)
275+
{
276+
short ignored = -1;
277+
messageProtocol.writeMapSourceLocation(buffer, newId, methodId, startLine, endLine, ignored, ignored);
278+
return newId;
279+
}
280+
return id;
281+
}
282+
227283
public void mark(int methodId, DataBufferOutputStream buffer) throws IOException, FailedToObtainBufferException, FailedToSendBufferException
228284
{
229285
Boolean seen = observedIds.putIfAbsent(methodId, true);
@@ -239,27 +295,6 @@ public void mark(int methodId, DataBufferOutputStream buffer) throws IOException
239295
}
240296
}
241297

242-
private class ExceptionId
243-
{
244-
private final AtomicInteger idGen = new AtomicInteger(1);
245-
private final ConcurrentMap<String, Integer> ids = new ConcurrentHashMap<String, Integer>();
246-
247-
public int getId(String exception) throws IOException, FailedToObtainBufferException,
248-
FailedToSendBufferException
249-
{
250-
Integer id = ids.putIfAbsent(exception, 0);
251-
if (id == null || id == 0)
252-
{
253-
id = idGen.getAndIncrement();
254-
if (ids.replace(exception, 0, id))
255-
{
256-
sendMapException(exception, id);
257-
}
258-
}
259-
return ids.get(exception);
260-
}
261-
}
262-
263298
/**
264299
* Creates a monotonically-incrementing unique id for each thread. The id
265300
* for the currently-running thread is available via {@link #getCurrent()}
@@ -310,9 +345,7 @@ protected String initialValue()
310345
};
311346

312347
/**
313-
* Get the unique id of the currently-running thread. When necessary,
314-
* this method will automatically send a MapMethodName message to the
315-
* message queue.
348+
* Get the unique id of the currently-running thread.
316349
*
317350
* @return The unique id for the currently-running thread.
318351
* @throws InterruptedException
@@ -323,14 +356,12 @@ protected String initialValue()
323356
public int getCurrent() throws IOException, FailedToObtainBufferException,
324357
FailedToSendBufferException
325358
{
326-
boolean updated = false;
327359
int id = threadId.get();
328360

329361
// check if the id is "new"
330362
if (!threadHasId.get())
331363
{
332364
threadHasId.set(true);
333-
updated = true;
334365
}
335366

336367
// check if the name has changed
@@ -344,14 +375,8 @@ public int getCurrent() throws IOException, FailedToObtainBufferException,
344375
if (!nowName.equals(oldName))
345376
{
346377
threadName.set(nowName);
347-
updated = true;
348378
}
349379

350-
// when updated, send a MapThreadName message
351-
if (updated)
352-
{
353-
sendMapThreadName(nowName, id);
354-
}
355380
return id;
356381
}
357382
}

0 commit comments

Comments
 (0)