Skip to content

Commit a2d4ae8

Browse files
Full Javadoc
1 parent 5f96878 commit a2d4ae8

11 files changed

Lines changed: 112 additions & 18 deletions

src/main/java/fr/bl/drit/flow/agent/AgentMain.java

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -63,10 +63,22 @@
6363
*/
6464
public class AgentMain {
6565

66+
/**
67+
* When starting the application with the agent.
68+
*
69+
* @param agentArgs Arguments to parse
70+
* @param inst Allows instrumenting Java code
71+
*/
6672
public static void premain(String agentArgs, Instrumentation inst) {
6773
init(agentArgs, inst);
6874
}
6975

76+
/**
77+
* When attaching the agent at runtime.
78+
*
79+
* @param agentArgs Arguments to parse
80+
* @param inst Allows instrumenting Java code
81+
*/
7082
public static void agentmain(String agentArgs, Instrumentation inst) {
7183
init(agentArgs, inst);
7284
}
@@ -153,14 +165,9 @@ private static void init(String agentArgs, Instrumentation inst) {
153165

154166
// === recorder setup ===
155167

156-
try {
157-
Singletons.RECORDER = new ThreadLocalRecorder(factory, outputDir);
158-
} catch (IOException e) {
159-
System.err.println("[flow-agent] Failed to create writer: " + e);
160-
e.printStackTrace();
161-
}
168+
Singletons.RECORDER = new ThreadLocalRecorder(factory, outputDir);
162169

163-
final String finalMappingPath = mappingPath;
170+
final boolean hasMappingPath = mappingPath != null;
164171

165172
// register shutdown hook to close recorder
166173
Runtime.getRuntime()
@@ -170,7 +177,7 @@ private static void init(String agentArgs, Instrumentation inst) {
170177
try {
171178
Singletons.RECORDER.close();
172179

173-
if (finalMappingPath == null) {
180+
if (!hasMappingPath) {
174181
idMapping.dump(outputDir.resolve("ids.properties"));
175182
}
176183

src/main/java/fr/bl/drit/flow/agent/BinaryThreadRecorder.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,10 @@ public class BinaryThreadRecorder implements ThreadRecorder {
159159
/** Pending consecutive exits. */
160160
protected long pendingExits = 0L;
161161

162+
/**
163+
* @param outputDir Path to output directory
164+
* @throws IOException If an I/O error occurs when opening an output stream.
165+
*/
162166
public BinaryThreadRecorder(Path outputDir) throws IOException {
163167
this.fileName = "thread-" + Thread.currentThread().getId() + ".flow";
164168
this.out =
@@ -171,6 +175,9 @@ public BinaryThreadRecorder(Path outputDir) throws IOException {
171175
64 * 1024);
172176
}
173177

178+
/**
179+
* @return The file name this recorder is writing to
180+
*/
174181
public String getFileName() {
175182
return fileName;
176183
}
@@ -186,6 +193,11 @@ public void exit() throws IOException {
186193
pendingExits++;
187194
}
188195

196+
/**
197+
* Flush a pending exit event if there is one.
198+
*
199+
* @throws IOException If an I/O error occurs when writing to file.
200+
*/
189201
protected void flushPendingExits() throws IOException {
190202
if (pendingExits == 0L) {
191203
return;
@@ -204,6 +216,9 @@ protected void flushPendingExits() throws IOException {
204216
* bit 7 : continuation (1 if more bytes follow)
205217
* bits 6-0 : next 7 bits of value
206218
* </code></pre>
219+
*
220+
* @param value The positive integer to encode
221+
* @throws IOException If an I/O error occurs when writing to file.
207222
*/
208223
protected void writeVarInt(long value) throws IOException {
209224
while ((value & M_PAYLOAD_REST) != 0) {
@@ -225,6 +240,10 @@ protected void writeVarInt(long value) throws IOException {
225240
* </code></pre>
226241
*
227242
* Following bytes (if any) are encoded using {@link #writeVarInt(long) writeVarInt}.
243+
*
244+
* @param flag The event flag
245+
* @param value The positive integer to encode
246+
* @throws IOException If an I/O error occurs when writing to file.
228247
*/
229248
protected void writeFlagAndVarInt(int flag, long value) throws IOException {
230249
// Extract lowest 6 bits for first byte

src/main/java/fr/bl/drit/flow/agent/FlowAdvice.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,11 @@
33
import java.io.IOException;
44
import net.bytebuddy.asm.Advice;
55

6-
public class FlowAdvice {
6+
/**
7+
* Contains the enter and exit {@link net.bytebuddy.asm.Advice Advice} methods. Their code is
8+
* inserted at the start and end of instrumented methods, respectively.
9+
*/
10+
public final class FlowAdvice {
711

812
/* (non-Javadoc)
913
Use `inline = false` to avoid `invokedynamic` instructions which are illegal before Java 8.
@@ -14,6 +18,11 @@ public class FlowAdvice {
1418
The exception is then rethrown automatically to let the execution proceed normally.
1519
*/
1620

21+
/**
22+
* Record entering an instrumented method.
23+
*
24+
* @param methodId The ID of the instrumented method
25+
*/
1726
@Advice.OnMethodEnter(inline = false)
1827
public static void enter(@MethodId long methodId) {
1928
try {
@@ -23,6 +32,7 @@ public static void enter(@MethodId long methodId) {
2332
}
2433
}
2534

35+
/** Record exiting an instrumented method. */
2636
@Advice.OnMethodExit(inline = false, onThrowable = Throwable.class)
2737
public static void exit() {
2838
try {

src/main/java/fr/bl/drit/flow/agent/JsonlThreadRecorder.java

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,12 @@
1212
/**
1313
* Call tree JSONL recorder.
1414
*
15-
* <p>Each line is either: - {"e":"enter","method":"<id>"} - {"e":"exit"}
15+
* <p>Each line is either:
16+
*
17+
* <ul>
18+
* <li>A method enter event: {@code {"e":"enter","method":"<id>"}}
19+
* <li>A method exit event: {@code {"e":"exit"}}
20+
* </ul>
1621
*/
1722
public final class JsonlThreadRecorder implements ThreadRecorder {
1823

@@ -21,6 +26,10 @@ public final class JsonlThreadRecorder implements ThreadRecorder {
2126

2227
private final String fileName;
2328

29+
/**
30+
* @param outputDir Path to output directory
31+
* @throws IOException If an I/O error occurs when opening an output stream.
32+
*/
2433
public JsonlThreadRecorder(Path outputDir) throws IOException {
2534
this.fileName = "thread-" + Thread.currentThread().getId() + ".jsonl";
2635
this.out =
@@ -35,6 +44,9 @@ public JsonlThreadRecorder(Path outputDir) throws IOException {
3544
64 * 1024);
3645
}
3746

47+
/**
48+
* @return The file name this recorder is writing to
49+
*/
3850
public String getFileName() {
3951
return fileName;
4052
}

src/main/java/fr/bl/drit/flow/agent/MethodId.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@
55
import java.lang.annotation.RetentionPolicy;
66
import java.lang.annotation.Target;
77

8+
/**
9+
* Used in {@link FlowAdvice#enter(long)} to annotate the parameter that contains the instrumented
10+
* method ID.
11+
*/
812
@Retention(RetentionPolicy.RUNTIME)
913
@Target(ElementType.PARAMETER)
1014
public @interface MethodId {}

src/main/java/fr/bl/drit/flow/agent/MethodIdMapping.java

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ public MethodIdMapping() {
3131
*
3232
* @param input Path to file containing lines of "key=id" generated by {@link #dump(Path)} in a
3333
* previous run.
34-
* @throws IOException
34+
* @throws IOException If an I/O error occurs when opening or reading the file.
3535
*/
3636
public MethodIdMapping(Path input) throws IOException {
3737
this.keyToId = new ConcurrentHashMap<>();
@@ -53,21 +53,40 @@ public MethodIdMapping(Path input) throws IOException {
5353
this.nextId = new AtomicLong(max + 1);
5454
}
5555

56+
/**
57+
* Get or compute a method ID for a given method.
58+
*
59+
* @param key Method signature
60+
* @return Method ID
61+
*/
5662
public long idFor(String key) {
5763
return keyToId.computeIfAbsent(key, k -> nextId.getAndIncrement());
5864
}
5965

66+
/**
67+
* @return Number of methods in the mapping
68+
*/
6069
public int size() {
6170
return keyToId.size();
6271
}
6372

6473
/**
65-
* Dump the mapping to a file, for potential reuse in future runs. Format is lines of "key=id".
74+
* Dump the mapping to a file.
75+
*
76+
* @param output Path to output file
77+
* @throws IOException If an I/O error occurs when opening the file.
6678
*/
6779
public void dump(Path output) throws IOException {
6880
dump(keyToId, output);
6981
}
7082

83+
/**
84+
* Dump the mapping to a file, for potential reuse in future runs. Format is lines of "key=id".
85+
*
86+
* @param mapping Map of signature -> ID
87+
* @param output Path to output file
88+
* @throws IOException If an I/O error occurs when opening or writing the file.
89+
*/
7190
public static void dump(Map<String, Long> mapping, Path output) throws IOException {
7291
try (BufferedWriter w =
7392
Files.newBufferedWriter(

src/main/java/fr/bl/drit/flow/agent/MethodIdRemapper.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -141,12 +141,13 @@ private static Map<String, Long> optimizeMappingByCounts(
141141
}
142142

143143
/**
144-
* Scan existing traces and mapping. Then, optimize the mapping and write it.
144+
* Read existing traces and mapping. Then, optimize the mapping and write it.
145145
*
146146
* @param inputDir directory containing trace files
147147
* @param outputDir directory where optimized mapping will be written
148148
* @return path to optimized mapping file
149-
* @throws IOException
149+
* @throws IOException If an I/O error occurs when reading from {@code inputDir} or writing to
150+
* {@code outputDir}.
150151
*/
151152
public static Path optimize(Path inputDir, Path outputDir) throws IOException {
152153
Path idsFile = inputDir.resolve("ids.properties");

src/main/java/fr/bl/drit/flow/agent/Recorder.java

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,18 @@
55

66
/** Specifies a recorder that is used to record flow data. */
77
public interface Recorder extends Closeable {
8-
/** Emit a method enter event with the given method ID. */
8+
/**
9+
* Emit a method enter event with the given method ID.
10+
*
11+
* @param methodId The ID of the method to trace
12+
* @throws IOException If an I/O error occurs when emitting the event.
13+
*/
914
void enter(long methodId) throws IOException;
1015

11-
/** Emit a method exit event. */
16+
/**
17+
* Emit a method exit event.
18+
*
19+
* @throws IOException If an I/O error occurs when emitting the event.
20+
*/
1221
void exit() throws IOException;
1322
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
package fr.bl.drit.flow.agent;
22

3+
/** Global singletons used by the agent. */
34
public final class Singletons {
45
private Singletons() {}
56

7+
/** The {@link Recorder} of method enter and exit events. */
68
public static Recorder RECORDER;
79
}

src/main/java/fr/bl/drit/flow/agent/ThreadLocalRecorder.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,11 @@ public final class ThreadLocalRecorder implements Recorder {
1111
private final ThreadLocal<ThreadRecorder> local;
1212
private final Queue<ThreadRecorder> all = new ConcurrentLinkedQueue<>();
1313

14-
public ThreadLocalRecorder(ThreadRecorderFactory factory, Path outputDir) throws IOException {
14+
/**
15+
* @param factory Responsible for creating {@link ThreadRecorder}s
16+
* @param outputDir Path to the output directory
17+
*/
18+
public ThreadLocalRecorder(ThreadRecorderFactory factory, Path outputDir) {
1519
this.local =
1620
ThreadLocal.withInitial(
1721
() -> {

0 commit comments

Comments
 (0)