Skip to content

Commit 836e268

Browse files
heyamstrask
andauthored
Add a startup profiler for debugging (#2085)
* Add StartupProfiler * Fix errorprone * Fix spotless * Invoke before premain Co-authored-by: Trask Stalnaker <[email protected]> * Create dump in applicationinsights folder * Show the full path of the dump * Fix lgtm * Allow sout * Fix lgtm * Supress systemout at the method level * Fix style complain * Address comments * Fix spotless * Address comments * Return when exception occurs * Remove comment Co-authored-by: Trask Stalnaker <[email protected]> * Use getBoolean for system property Co-authored-by: Trask Stalnaker <[email protected]>
1 parent 32709f0 commit 836e268

File tree

2 files changed

+115
-0
lines changed

2 files changed

+115
-0
lines changed

agent/agent/src/main/java/com/microsoft/applicationinsights/agent/Agent.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,11 @@ public static void premain(String agentArgs, Instrumentation inst) {
4040
if (alreadyLoaded) {
4141
return;
4242
}
43+
44+
if (Boolean.getBoolean("applicationinsights.debug.startupProfiling")) {
45+
StartupProfiler.start();
46+
}
47+
4348
OpenTelemetryAgent.premain(agentArgs, inst);
4449
alreadyLoaded = true;
4550
}
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
/*
2+
* ApplicationInsights-Java
3+
* Copyright (c) Microsoft Corporation
4+
* All rights reserved.
5+
*
6+
* MIT License
7+
* Permission is hereby granted, free of charge, to any person obtaining a copy of this
8+
* software and associated documentation files (the ""Software""), to deal in the Software
9+
* without restriction, including without limitation the rights to use, copy, modify, merge,
10+
* publish, distribute, sublicense, and/or sell copies of the Software, and to permit
11+
* persons to whom the Software is furnished to do so, subject to the following conditions:
12+
* The above copyright notice and this permission notice shall be included in all copies or
13+
* substantial portions of the Software.
14+
* THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
15+
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
16+
* PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
17+
* FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
18+
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
19+
* DEALINGS IN THE SOFTWARE.
20+
*/
21+
22+
package com.microsoft.applicationinsights.agent;
23+
24+
import java.io.File;
25+
import java.io.IOException;
26+
import java.io.PrintWriter;
27+
import java.lang.management.ManagementFactory;
28+
import java.lang.management.RuntimeMXBean;
29+
import java.lang.management.ThreadInfo;
30+
import java.lang.management.ThreadMXBean;
31+
import java.nio.charset.Charset;
32+
import java.nio.file.Files;
33+
import java.util.concurrent.Executors;
34+
import java.util.concurrent.TimeUnit;
35+
36+
final class StartupProfiler {
37+
38+
private static final String STACKTRACES = "stacktrace.txt";
39+
40+
@SuppressWarnings("SystemOut")
41+
public static void start() {
42+
String tempDirectory = System.getProperty("java.io.tmpdir");
43+
File folder = new File(tempDirectory, "applicationinsights");
44+
if (!folder.exists()) {
45+
folder.mkdirs();
46+
}
47+
48+
File dumpFile = new File(folder, STACKTRACES);
49+
System.out.println("Writing startup profiler to '" + dumpFile.getPath() + "'");
50+
51+
PrintWriter printWriter = null;
52+
try (PrintWriter out =
53+
new PrintWriter(Files.newBufferedWriter(dumpFile.toPath(), Charset.defaultCharset()))) {
54+
printWriter = new PrintWriter(out);
55+
} catch (IOException e) {
56+
if (printWriter != null) {
57+
printWriter.close();
58+
}
59+
System.out.println("Error occurred when writing dump to " + dumpFile.getPath());
60+
e.printStackTrace();
61+
return;
62+
}
63+
64+
start(printWriter);
65+
}
66+
67+
private static void start(PrintWriter out) {
68+
Executors.newSingleThreadScheduledExecutor()
69+
.scheduleAtFixedRate(new ThreadDump(out), 50, 50, TimeUnit.MILLISECONDS);
70+
}
71+
72+
private StartupProfiler() {}
73+
74+
private static class ThreadDump implements Runnable {
75+
76+
private final PrintWriter out;
77+
78+
private ThreadDump(PrintWriter out) {
79+
this.out = out;
80+
}
81+
82+
@Override
83+
public void run() {
84+
out.println("========================================");
85+
RuntimeMXBean runtimeBean = ManagementFactory.getRuntimeMXBean();
86+
out.println(runtimeBean.getUptime());
87+
out.println();
88+
ThreadMXBean threadBean = ManagementFactory.getThreadMXBean();
89+
ThreadInfo[] threadInfos =
90+
threadBean.getThreadInfo(
91+
threadBean.getAllThreadIds(), threadBean.isObjectMonitorUsageSupported(), false);
92+
long currentThreadId = Thread.currentThread().getId();
93+
for (ThreadInfo threadInfo : threadInfos) {
94+
if (threadInfo.getThreadId() != currentThreadId) {
95+
write(threadInfo);
96+
}
97+
}
98+
out.flush();
99+
}
100+
101+
private void write(ThreadInfo threadInfo) {
102+
out.println(threadInfo.getThreadName() + " #" + threadInfo.getThreadId());
103+
out.println(" java.lang.Thread.State: " + threadInfo.getThreadState());
104+
for (StackTraceElement ste : threadInfo.getStackTrace()) {
105+
out.println(" " + ste);
106+
}
107+
out.println();
108+
}
109+
}
110+
}

0 commit comments

Comments
 (0)