|
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 | + // // this is HotSpot specific implementation (eg. will not work for IBM J9) |
| 46 | + // HotSpotDiagnosticMXBean diagBean = |
| 47 | + // ManagementFactory.getPlatformMXBean(HotSpotDiagnosticMXBean.class); |
| 48 | + |
| 49 | + initializeCrashUploader(flags); |
| 50 | + initializeOOMENotifier(flags); |
36 | 51 | } |
37 | 52 |
|
38 | 53 | static InputStream getCrashUploaderTemplate() { |
@@ -130,28 +145,75 @@ private static String getBaseName(Path path) { |
130 | 145 | * `dd_crash_uploader.bat` and the script does not exist it will be created and prefilled with |
131 | 146 | * code ensuring the error log upload will be triggered on JVM crash. |
132 | 147 | */ |
133 | | - private static void initializeCrashUploader(HotSpotDiagnosticMXBean diagBean) { |
| 148 | + private static void initializeCrashUploader(JVMAccess.Flags flags) { |
134 | 149 | try { |
135 | | - String onErrorVal = diagBean.getVMOption("OnError").getValue(); |
136 | | - String onErrorFile = diagBean.getVMOption("ErrorFile").getValue(); |
137 | | - CrashUploaderScriptInitializer.initialize(onErrorVal, onErrorFile); |
| 150 | + String onErrorVal = flags.getStringFlag("OnError"); |
| 151 | + String onErrorFile = flags.getStringFlag("ErrorFile"); |
| 152 | + |
| 153 | + String uploadScript = getScript("dd_crash_uploader"); |
| 154 | + if (onErrorVal == null || onErrorVal.isEmpty()) { |
| 155 | + onErrorVal = uploadScript; |
| 156 | + } else if (!onErrorVal.contains("dd_crash_uploader")) { |
| 157 | + // we can chain scripts so let's preserve the original value in addition to our crash |
| 158 | + // uploader |
| 159 | + onErrorVal = uploadScript + "; " + onErrorVal; |
| 160 | + } |
| 161 | + |
| 162 | + // set the JVM flag |
| 163 | + flags.setStringFlag("OnError", onErrorVal); |
| 164 | + if (LOG.isDebugEnabled()) { |
| 165 | + String currentVal = flags.getStringFlag("OnError"); |
| 166 | + if (!currentVal.equals(uploadScript)) { |
| 167 | + LOG.debug("Unable to set OnError flag to {}. Crash-tracking may not work.", currentVal); |
| 168 | + } |
| 169 | + } |
| 170 | + |
| 171 | + CrashUploaderScriptInitializer.initialize(uploadScript, onErrorFile); |
138 | 172 | } catch (Throwable t) { |
139 | 173 | logInitializationError( |
140 | 174 | "Unexpected exception while creating custom crash upload script. Crash tracking will not work properly.", |
141 | 175 | t); |
142 | 176 | } |
143 | 177 | } |
144 | 178 |
|
145 | | - private static void initializeOOMENotifier(HotSpotDiagnosticMXBean diagBean) { |
| 179 | + private static void initializeOOMENotifier(JVMAccess.Flags flags) { |
146 | 180 | try { |
147 | | - String onOutOfMemoryVal = diagBean.getVMOption("OnOutOfMemoryError").getValue(); |
148 | | - OOMENotifierScriptInitializer.initialize(onOutOfMemoryVal); |
| 181 | + String onOutOfMemoryVal = flags.getStringFlag("OnOutOfMemoryError"); |
| 182 | + String notifierScript = getScript("dd_oome_notifier"); |
| 183 | + |
| 184 | + if (onOutOfMemoryVal == null || onOutOfMemoryVal.isEmpty()) { |
| 185 | + onOutOfMemoryVal = notifierScript; |
| 186 | + } else if (!onOutOfMemoryVal.contains("dd_oome_notifier")) { |
| 187 | + // we can chain scripts so let's preserve the original value in addition to our oome tracker |
| 188 | + onOutOfMemoryVal = notifierScript + "; " + onOutOfMemoryVal; |
| 189 | + } |
| 190 | + |
| 191 | + // set the JVM flag |
| 192 | + flags.setStringFlag("OnOutOfMemoryError", onOutOfMemoryVal); |
| 193 | + if (LOG.isDebugEnabled()) { |
| 194 | + String currentVal = flags.getStringFlag("OnOutOfMemoryError"); |
| 195 | + if (!currentVal.equals(onOutOfMemoryVal)) { |
| 196 | + LOG.debug( |
| 197 | + "Unable to set OnOutOfMemoryError flag to {}. OOME tracking may not work.", |
| 198 | + currentVal); |
| 199 | + } |
| 200 | + } |
| 201 | + |
| 202 | + OOMENotifierScriptInitializer.initialize(notifierScript); |
149 | 203 | } catch (Throwable t) { |
150 | 204 | logInitializationError( |
151 | 205 | "Unexpected exception while initializing OOME notifier. OOMEs will not be tracked.", t); |
152 | 206 | } |
153 | 207 | } |
154 | 208 |
|
| 209 | + private static String getScript(String scriptName) { |
| 210 | + return System.getProperty("java.io.tmpdir") + "/" + getScriptFileName(scriptName) + " %p"; |
| 211 | + } |
| 212 | + |
| 213 | + private static String getScriptFileName(String scriptName) { |
| 214 | + return scriptName + "." + (Platform.isWindows() ? "bat" : "sh"); |
| 215 | + } |
| 216 | + |
155 | 217 | private static void logInitializationError(String msg, Throwable t) { |
156 | 218 | if (LOG.isDebugEnabled()) { |
157 | 219 | LOG.warn("{}", msg, t); |
|
0 commit comments