-
Notifications
You must be signed in to change notification settings - Fork 347
Expand file tree
/
Copy pathTestApplicationHelper.java
More file actions
178 lines (167 loc) · 6.76 KB
/
Copy pathTestApplicationHelper.java
File metadata and controls
178 lines (167 loc) · 6.76 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
package datadog.smoketest.debugger;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.Duration;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.LockSupport;
import java.util.function.Predicate;
public class TestApplicationHelper {
// instrumentation is done by main thread
private static final String INSTRUMENTATION_DONE =
"[%s] DEBUG com.datadog.debugger.agent.DebuggerTransformer - Generating bytecode for class: %s";
private static final String THREAD_MAIN = "main";
private static final String THREAD_REMOTE_CONFIG = "dd-remote-config";
private static final String THREAD_SCHEDULER = "dd-task-scheduler";
private static final String THREAD_STARTUP = "dd-agent-startup-datadog-tracer";
private static final String[] THREAD_NAMES =
new String[] {THREAD_MAIN, THREAD_REMOTE_CONFIG, THREAD_SCHEDULER, THREAD_STARTUP};
private static final String RENTRANSFORMATION_CLASS =
"[dd-remote-config] DEBUG com.datadog.debugger.agent.ConfigurationUpdater - Re-transforming class: %s";
private static final String RETRANSFORMATION_DONE =
"com.datadog.debugger.agent.ConfigurationUpdater - Re-transformation done";
private static final String EXCEPTION_FINGERPRINT_ADDED =
"DEBUG com.datadog.debugger.exception.AbstractExceptionDebugger - Exception Fingerprint ";
private static final long SLEEP_MS = 100;
private static final long TIMEOUT_S = 10;
public static void waitForTransformerInstalled(String logFileName) throws IOException {
waitForSpecificLogLine(
Paths.get(logFileName),
line ->
line.contains(
"DEBUG com.datadog.debugger.agent.ConfigurationUpdater - New transformer installed"),
() -> {},
Duration.ofMillis(SLEEP_MS),
Duration.ofSeconds(TIMEOUT_S));
}
public static void waitForInstrumentation(String logFileName, String className)
throws IOException {
waitForInstrumentation(logFileName, className, null);
}
public static String waitForInstrumentation(String logFileName, String className, String fromLine)
throws IOException {
AtomicBoolean generatingByteCode = new AtomicBoolean();
return waitForSpecificLogLine(
Paths.get(logFileName),
fromLine != null ? line -> line.contains(fromLine) : null,
line -> {
// when instrumentation is done by main thread, we are good to go
if (line.contains(String.format(INSTRUMENTATION_DONE, THREAD_MAIN, className))) {
return true;
}
if (!generatingByteCode.get()) {
// instrumentation is done by background thread, need to wait for end of
// re-transformation
for (String threadName : THREAD_NAMES) {
if (line.contains(String.format(INSTRUMENTATION_DONE, threadName, className))) {
generatingByteCode.set(true);
}
}
} else {
return line.contains(RETRANSFORMATION_DONE);
}
return false;
},
() -> {},
Duration.ofMillis(SLEEP_MS),
Duration.ofSeconds(TIMEOUT_S));
}
public static String waitForReTransformation(
String logFileName, String className, String fromLine) throws IOException {
AtomicBoolean retransforming = new AtomicBoolean();
return waitForSpecificLogLine(
Paths.get(logFileName),
line -> line.contains(fromLine),
line -> {
if (!retransforming.get()) {
retransforming.set(line.contains(String.format(RENTRANSFORMATION_CLASS, className)));
return false;
}
return line.contains(RETRANSFORMATION_DONE);
},
() -> {},
Duration.ofMillis(SLEEP_MS),
Duration.ofSeconds(TIMEOUT_S));
}
public static String waitForExceptionFingerprint(String logFileName) throws IOException {
return waitForSpecificLine(logFileName, EXCEPTION_FINGERPRINT_ADDED, null);
}
public static String waitForSpecificLine(String logFileName, String specificLine, String fromLine)
throws IOException {
return waitForSpecificLogLine(
Paths.get(logFileName),
fromLine != null ? line -> line.contains(fromLine) : null,
line -> line.contains(specificLine),
() -> {},
Duration.ofMillis(SLEEP_MS),
Duration.ofSeconds(TIMEOUT_S));
}
public static void waitForUpload(String logFileName, int expectedUploads) throws IOException {
if (expectedUploads == -1) {
System.out.println("wait for " + TIMEOUT_S + "s");
LockSupport.parkNanos(Duration.ofSeconds(TIMEOUT_S).toNanos());
return;
}
System.out.println("waitForUpload #" + expectedUploads);
AtomicInteger uploadCount = new AtomicInteger(0);
waitForSpecificLogLine(
Paths.get(logFileName),
line -> {
if (line.contains("DEBUG com.datadog.debugger.uploader.BatchUploader - Upload done")) {
int currentUploads = uploadCount.incrementAndGet();
return currentUploads == expectedUploads;
}
return false;
},
() -> uploadCount.set(0),
Duration.ofMillis(SLEEP_MS),
Duration.ofSeconds(TIMEOUT_S));
}
private static String waitForSpecificLogLine(
Path logFilePath,
Predicate<String> lineMatcher,
Runnable init,
Duration sleep,
Duration timeout)
throws IOException {
return waitForSpecificLogLine(logFilePath, null, lineMatcher, init, sleep, timeout);
}
private static String waitForSpecificLogLine(
Path logFilePath,
Predicate<String> fromLineMatcher,
Predicate<String> lineMatcher,
Runnable init,
Duration sleep,
Duration timeout)
throws IOException {
AtomicBoolean result = new AtomicBoolean();
AtomicReference<String> matchedLine = new AtomicReference<>();
long total = sleep.toNanos() == 0 ? 0 : timeout.toNanos() / sleep.toNanos();
int i = 0;
while (i < total && !result.get()) {
System.out.flush();
System.err.flush();
init.run();
AtomicBoolean fromLineMatched = new AtomicBoolean(fromLineMatcher == null);
Files.lines(logFilePath)
.forEach(
line -> {
if (!fromLineMatched.get()) {
fromLineMatched.set(fromLineMatcher.test(line));
} else if (lineMatcher.test(line)) {
matchedLine.set(line);
result.set(true);
}
});
LockSupport.parkNanos(sleep.toNanos());
i++;
}
if (!result.get()) {
throw new IllegalStateException("waitForSpecificLogLine timed out!");
}
return matchedLine.get();
}
}