|
4 | 4 | import static java.util.Comparator.reverseOrder; |
5 | 5 | import static java.util.Locale.ROOT; |
6 | 6 |
|
7 | | -import com.sun.management.HotSpotDiagnosticMXBean; |
| 7 | +import com.datadoghq.profiler.JVMAccess; |
8 | 8 | import datadog.trace.api.Platform; |
| 9 | +import datadog.trace.api.config.ProfilingConfig; |
| 10 | +import datadog.trace.bootstrap.config.provider.ConfigProvider; |
9 | 11 | import datadog.trace.util.PidHelper; |
10 | 12 | import java.io.BufferedWriter; |
11 | 13 | import java.io.IOException; |
12 | 14 | import java.io.InputStream; |
13 | | -import java.lang.management.ManagementFactory; |
14 | 15 | import java.net.URL; |
15 | 16 | import java.nio.file.Files; |
16 | 17 | import java.nio.file.Path; |
|
20 | 21 | import org.slf4j.Logger; |
21 | 22 | import org.slf4j.LoggerFactory; |
22 | 23 |
|
23 | | -public final class ScriptInitializer { |
24 | | - static final Logger LOG = LoggerFactory.getLogger(ScriptInitializer.class); |
| 24 | +public final class Initializer { |
| 25 | + static final Logger LOG = LoggerFactory.getLogger(Initializer.class); |
25 | 26 | static final String PID_PREFIX = "_pid"; |
26 | 27 | static final String RWXRWXRWX = "rwxrwxrwx"; |
27 | 28 | static final String R_XR_XR_X = "r-xr-xr-x"; |
28 | 29 |
|
29 | 30 | public static void initialize() { |
30 | | - // this is HotSpot specific implementation (eg. will not work for IBM J9) |
31 | | - HotSpotDiagnosticMXBean diagBean = |
32 | | - ManagementFactory.getPlatformMXBean(HotSpotDiagnosticMXBean.class); |
| 31 | + ConfigProvider cfgProvider = ConfigProvider.getInstance(); |
| 32 | + String scratchDir = cfgProvider.getString(ProfilingConfig.PROFILING_DATADOG_PROFILER_SCRATCH); |
33 | 33 |
|
34 | | - initializeCrashUploader(diagBean); |
35 | | - initializeOOMENotifier(diagBean); |
| 34 | + JVMAccess jvmAccess = |
| 35 | + new JVMAccess( |
| 36 | + null, |
| 37 | + scratchDir, |
| 38 | + throwable -> { |
| 39 | + logInitializationError( |
| 40 | + "Unexpected exception while initializing JVMAccess", throwable); |
| 41 | + }); |
| 42 | + |
| 43 | + JVMAccess.Flags flags = jvmAccess.flags(); |
| 44 | + |
| 45 | + initializeCrashUploader(flags); |
| 46 | + initializeOOMENotifier(flags); |
36 | 47 | } |
37 | 48 |
|
38 | 49 | static InputStream getCrashUploaderTemplate() { |
@@ -130,28 +141,75 @@ private static String getBaseName(Path path) { |
130 | 141 | * `dd_crash_uploader.bat` and the script does not exist it will be created and prefilled with |
131 | 142 | * code ensuring the error log upload will be triggered on JVM crash. |
132 | 143 | */ |
133 | | - private static void initializeCrashUploader(HotSpotDiagnosticMXBean diagBean) { |
| 144 | + private static void initializeCrashUploader(JVMAccess.Flags flags) { |
134 | 145 | try { |
135 | | - String onErrorVal = diagBean.getVMOption("OnError").getValue(); |
136 | | - String onErrorFile = diagBean.getVMOption("ErrorFile").getValue(); |
137 | | - CrashUploaderScriptInitializer.initialize(onErrorVal, onErrorFile); |
| 146 | + String onErrorVal = flags.getStringFlag("OnError"); |
| 147 | + String onErrorFile = flags.getStringFlag("ErrorFile"); |
| 148 | + |
| 149 | + String uploadScript = getScript("dd_crash_uploader"); |
| 150 | + if (onErrorVal == null || onErrorVal.isEmpty()) { |
| 151 | + onErrorVal = uploadScript; |
| 152 | + } else if (!onErrorVal.contains("dd_crash_uploader")) { |
| 153 | + // we can chain scripts so let's preserve the original value in addition to our crash |
| 154 | + // uploader |
| 155 | + onErrorVal = uploadScript + "; " + onErrorVal; |
| 156 | + } |
| 157 | + |
| 158 | + // set the JVM flag |
| 159 | + flags.setStringFlag("OnError", onErrorVal); |
| 160 | + if (LOG.isDebugEnabled()) { |
| 161 | + String currentVal = flags.getStringFlag("OnError"); |
| 162 | + if (!currentVal.equals(uploadScript)) { |
| 163 | + LOG.debug("Unable to set OnError flag to {}. Crash-tracking may not work.", currentVal); |
| 164 | + } |
| 165 | + } |
| 166 | + |
| 167 | + CrashUploaderScriptInitializer.initialize(uploadScript, onErrorFile); |
138 | 168 | } catch (Throwable t) { |
139 | 169 | logInitializationError( |
140 | 170 | "Unexpected exception while creating custom crash upload script. Crash tracking will not work properly.", |
141 | 171 | t); |
142 | 172 | } |
143 | 173 | } |
144 | 174 |
|
145 | | - private static void initializeOOMENotifier(HotSpotDiagnosticMXBean diagBean) { |
| 175 | + private static void initializeOOMENotifier(JVMAccess.Flags flags) { |
146 | 176 | try { |
147 | | - String onOutOfMemoryVal = diagBean.getVMOption("OnOutOfMemoryError").getValue(); |
148 | | - OOMENotifierScriptInitializer.initialize(onOutOfMemoryVal); |
| 177 | + String onOutOfMemoryVal = flags.getStringFlag("OnOutOfMemoryError"); |
| 178 | + String notifierScript = getScript("dd_oome_notifier"); |
| 179 | + |
| 180 | + if (onOutOfMemoryVal == null || onOutOfMemoryVal.isEmpty()) { |
| 181 | + onOutOfMemoryVal = notifierScript; |
| 182 | + } else if (!onOutOfMemoryVal.contains("dd_oome_notifier")) { |
| 183 | + // we can chain scripts so let's preserve the original value in addition to our oome tracker |
| 184 | + onOutOfMemoryVal = notifierScript + "; " + onOutOfMemoryVal; |
| 185 | + } |
| 186 | + |
| 187 | + // set the JVM flag |
| 188 | + flags.setStringFlag("OnOutOfMemoryError", onOutOfMemoryVal); |
| 189 | + if (LOG.isDebugEnabled()) { |
| 190 | + String currentVal = flags.getStringFlag("OnOutOfMemoryError"); |
| 191 | + if (!currentVal.equals(onOutOfMemoryVal)) { |
| 192 | + LOG.debug( |
| 193 | + "Unable to set OnOutOfMemoryError flag to {}. OOME tracking may not work.", |
| 194 | + currentVal); |
| 195 | + } |
| 196 | + } |
| 197 | + |
| 198 | + OOMENotifierScriptInitializer.initialize(notifierScript); |
149 | 199 | } catch (Throwable t) { |
150 | 200 | logInitializationError( |
151 | 201 | "Unexpected exception while initializing OOME notifier. OOMEs will not be tracked.", t); |
152 | 202 | } |
153 | 203 | } |
154 | 204 |
|
| 205 | + private static String getScript(String scriptName) { |
| 206 | + return System.getProperty("java.io.tmpdir") + "/" + getScriptFileName(scriptName) + " %p"; |
| 207 | + } |
| 208 | + |
| 209 | + private static String getScriptFileName(String scriptName) { |
| 210 | + return scriptName + "." + (Platform.isWindows() ? "bat" : "sh"); |
| 211 | + } |
| 212 | + |
155 | 213 | private static void logInitializationError(String msg, Throwable t) { |
156 | 214 | if (LOG.isDebugEnabled()) { |
157 | 215 | LOG.warn("{}", msg, t); |
|
0 commit comments