CR changes

This commit is contained in:
Nikolay Martynov 2020-03-02 12:22:24 -05:00
parent 2c33f0ace7
commit 6ff723e191
5 changed files with 35 additions and 29 deletions

View File

@ -47,6 +47,10 @@ public class Agent {
public static void start(final Instrumentation inst, final URL bootstrapURL) { public static void start(final Instrumentation inst, final URL bootstrapURL) {
createParentClassloader(bootstrapURL); createParentClassloader(bootstrapURL);
// Profiling agent startup code is written in a way to allow `startProfilingAgent` be called
// multiple times
// If early profiling is enabled then this call will start profiling.
// If early profiling is disabled then later call will do this.
startProfilingAgent(bootstrapURL, true); startProfilingAgent(bootstrapURL, true);
startDatadogAgent(inst, bootstrapURL); startDatadogAgent(inst, bootstrapURL);
@ -279,7 +283,7 @@ public class Agent {
} }
private static synchronized void startProfilingAgent( private static synchronized void startProfilingAgent(
final URL bootstrapURL, final boolean early) { final URL bootstrapURL, final boolean isStartingFirst) {
final ClassLoader contextLoader = Thread.currentThread().getContextClassLoader(); final ClassLoader contextLoader = Thread.currentThread().getContextClassLoader();
try { try {
if (PROFILING_CLASSLOADER == null) { if (PROFILING_CLASSLOADER == null) {
@ -290,7 +294,7 @@ public class Agent {
final Class<?> profilingAgentClass = final Class<?> profilingAgentClass =
PROFILING_CLASSLOADER.loadClass("com.datadog.profiling.agent.ProfilingAgent"); PROFILING_CLASSLOADER.loadClass("com.datadog.profiling.agent.ProfilingAgent");
final Method profilingInstallerMethod = profilingAgentClass.getMethod("run", Boolean.TYPE); final Method profilingInstallerMethod = profilingAgentClass.getMethod("run", Boolean.TYPE);
profilingInstallerMethod.invoke(null, early); profilingInstallerMethod.invoke(null, isStartingFirst);
} catch (final ClassFormatError e) { } catch (final ClassFormatError e) {
/* /*
Profiling is compiled for Java8. Loading it on Java7 results in ClassFormatError Profiling is compiled for Java8. Loading it on Java7 results in ClassFormatError

View File

@ -38,7 +38,7 @@ public final class ProfilingSystem {
private final Duration startupDelay; private final Duration startupDelay;
private final Duration uploadPeriod; private final Duration uploadPeriod;
private final boolean forceEarly; private final boolean isStartingFirst;
private OngoingRecording recording; private OngoingRecording recording;
private boolean started = false; private boolean started = false;
@ -51,6 +51,7 @@ public final class ProfilingSystem {
* @param startupDelay delay before starting jfr * @param startupDelay delay before starting jfr
* @param startupDelayRandomRange randomization range for startup delay * @param startupDelayRandomRange randomization range for startup delay
* @param uploadPeriod how often to upload data * @param uploadPeriod how often to upload data
* @param isStartingFirst starting profiling before other tools
* @throws ConfigurationException if the configuration information was bad. * @throws ConfigurationException if the configuration information was bad.
*/ */
public ProfilingSystem( public ProfilingSystem(
@ -59,7 +60,7 @@ public final class ProfilingSystem {
final Duration startupDelay, final Duration startupDelay,
final Duration startupDelayRandomRange, final Duration startupDelayRandomRange,
final Duration uploadPeriod, final Duration uploadPeriod,
final boolean forceEarly) final boolean isStartingFirst)
throws ConfigurationException { throws ConfigurationException {
this( this(
controller, controller,
@ -67,7 +68,7 @@ public final class ProfilingSystem {
startupDelay, startupDelay,
startupDelayRandomRange, startupDelayRandomRange,
uploadPeriod, uploadPeriod,
forceEarly, isStartingFirst,
Executors.newScheduledThreadPool( Executors.newScheduledThreadPool(
1, new ProfilingThreadFactory("dd-profiler-recording-scheduler")), 1, new ProfilingThreadFactory("dd-profiler-recording-scheduler")),
ThreadLocalRandom.current()); ThreadLocalRandom.current());
@ -79,14 +80,14 @@ public final class ProfilingSystem {
final Duration baseStartupDelay, final Duration baseStartupDelay,
final Duration startupDelayRandomRange, final Duration startupDelayRandomRange,
final Duration uploadPeriod, final Duration uploadPeriod,
final boolean forceEarly, final boolean isStartingFirst,
final ScheduledExecutorService executorService, final ScheduledExecutorService executorService,
final ThreadLocalRandom threadLocalRandom) final ThreadLocalRandom threadLocalRandom)
throws ConfigurationException { throws ConfigurationException {
this.controller = controller; this.controller = controller;
this.dataListener = dataListener; this.dataListener = dataListener;
this.uploadPeriod = uploadPeriod; this.uploadPeriod = uploadPeriod;
this.forceEarly = forceEarly; this.isStartingFirst = isStartingFirst;
this.executorService = executorService; this.executorService = executorService;
if (baseStartupDelay.isNegative()) { if (baseStartupDelay.isNegative()) {
@ -108,12 +109,12 @@ public final class ProfilingSystem {
public final void start() { public final void start() {
log.info( log.info(
"Starting profiling system: startupDelay={}ms, uploadPeriod={}ms, forceEarly={}", "Starting profiling system: startupDelay={}ms, uploadPeriod={}ms, isStartingFirst={}",
startupDelay.toMillis(), startupDelay.toMillis(),
uploadPeriod.toMillis(), uploadPeriod.toMillis(),
forceEarly); isStartingFirst);
if (forceEarly) { if (isStartingFirst) {
startProfilingRecording(); startProfilingRecording();
} else { } else {
// Delay JFR initialization. This code is run from 'premain' and there is a known bug in JVM // Delay JFR initialization. This code is run from 'premain' and there is a known bug in JVM

View File

@ -19,13 +19,14 @@ public class ProfilingAgent {
/** /**
* Main entry point into profiling Note: this must be reentrant because we may want to start * Main entry point into profiling Note: this must be reentrant because we may want to start
* profiling early, and then attempt to start it again at normal time * profiling before any other tool, and then attempt to start it again at normal time
*/ */
public static synchronized void run(final boolean early) throws IllegalArgumentException { public static synchronized void run(final boolean isStartingFirst)
throws IllegalArgumentException {
if (PROFILER == null) { if (PROFILER == null) {
final Config config = Config.get(); final Config config = Config.get();
if (early && !config.isProfilingStartForceEarly()) { if (isStartingFirst && !config.isProfilingStartForceFirst()) {
log.info("Profiling: not starting early"); log.info("Profiling: not starting first");
// early startup is disabled; // early startup is disabled;
return; return;
} }
@ -57,7 +58,7 @@ public class ProfilingAgent {
startupDelay, startupDelay,
startupDelayRandomRange, startupDelayRandomRange,
uploadPeriod, uploadPeriod,
config.isProfilingStartForceEarly()); config.isProfilingStartForceFirst());
PROFILER.start(); PROFILER.start();
log.info("Profiling has started!"); log.info("Profiling has started!");

View File

@ -116,8 +116,8 @@ public class Config {
public static final String PROFILING_START_DELAY = "profiling.start-delay"; public static final String PROFILING_START_DELAY = "profiling.start-delay";
// DANGEROUS! May lead on sigsegv on JVMs before 14 // DANGEROUS! May lead on sigsegv on JVMs before 14
// Not intended for production use // Not intended for production use
public static final String PROFILING_START_FORCE_EARLY = public static final String PROFILING_START_FORCE_FIRST =
"profiling.experimental.start-force-early"; "profiling.experimental.start-force-first";
public static final String PROFILING_UPLOAD_PERIOD = "profiling.upload.period"; public static final String PROFILING_UPLOAD_PERIOD = "profiling.upload.period";
public static final String PROFILING_TEMPLATE_OVERRIDE_FILE = public static final String PROFILING_TEMPLATE_OVERRIDE_FILE =
"profiling.jfr-template-override-file"; "profiling.jfr-template-override-file";
@ -176,7 +176,7 @@ public class Config {
public static final String DEFAULT_PROFILING_URL = public static final String DEFAULT_PROFILING_URL =
"https://intake.profile.datadoghq.com/v1/input"; "https://intake.profile.datadoghq.com/v1/input";
public static final int DEFAULT_PROFILING_START_DELAY = 10; public static final int DEFAULT_PROFILING_START_DELAY = 10;
public static final boolean DEFAULT_PROFILING_START_FORCE_EARLY = false; public static final boolean DEFAULT_PROFILING_START_FORCE_FIRST = false;
public static final int DEFAULT_PROFILING_UPLOAD_PERIOD = 60; // 1 min public static final int DEFAULT_PROFILING_UPLOAD_PERIOD = 60; // 1 min
public static final int DEFAULT_PROFILING_UPLOAD_TIMEOUT = 30; // seconds public static final int DEFAULT_PROFILING_UPLOAD_TIMEOUT = 30; // seconds
public static final String DEFAULT_PROFILING_UPLOAD_COMPRESSION = "on"; public static final String DEFAULT_PROFILING_UPLOAD_COMPRESSION = "on";
@ -273,7 +273,7 @@ public class Config {
@Getter private final String profilingApiKey; @Getter private final String profilingApiKey;
private final Map<String, String> profilingTags; private final Map<String, String> profilingTags;
@Getter private final int profilingStartDelay; @Getter private final int profilingStartDelay;
@Getter private final boolean profilingStartForceEarly; @Getter private final boolean profilingStartForceFirst;
@Getter private final int profilingUploadPeriod; @Getter private final int profilingUploadPeriod;
@Getter private final String profilingTemplateOverrideFile; @Getter private final String profilingTemplateOverrideFile;
@Getter private final int profilingUploadTimeout; @Getter private final int profilingUploadTimeout;
@ -452,9 +452,9 @@ public class Config {
profilingTags = getMapSettingFromEnvironment(PROFILING_TAGS, null); profilingTags = getMapSettingFromEnvironment(PROFILING_TAGS, null);
profilingStartDelay = profilingStartDelay =
getIntegerSettingFromEnvironment(PROFILING_START_DELAY, DEFAULT_PROFILING_START_DELAY); getIntegerSettingFromEnvironment(PROFILING_START_DELAY, DEFAULT_PROFILING_START_DELAY);
profilingStartForceEarly = profilingStartForceFirst =
getBooleanSettingFromEnvironment( getBooleanSettingFromEnvironment(
PROFILING_START_FORCE_EARLY, DEFAULT_PROFILING_START_FORCE_EARLY); PROFILING_START_FORCE_FIRST, DEFAULT_PROFILING_START_FORCE_FIRST);
profilingUploadPeriod = profilingUploadPeriod =
getIntegerSettingFromEnvironment(PROFILING_UPLOAD_PERIOD, DEFAULT_PROFILING_UPLOAD_PERIOD); getIntegerSettingFromEnvironment(PROFILING_UPLOAD_PERIOD, DEFAULT_PROFILING_UPLOAD_PERIOD);
profilingTemplateOverrideFile = profilingTemplateOverrideFile =
@ -614,9 +614,9 @@ public class Config {
profilingTags = getPropertyMapValue(properties, PROFILING_TAGS, parent.profilingTags); profilingTags = getPropertyMapValue(properties, PROFILING_TAGS, parent.profilingTags);
profilingStartDelay = profilingStartDelay =
getPropertyIntegerValue(properties, PROFILING_START_DELAY, parent.profilingStartDelay); getPropertyIntegerValue(properties, PROFILING_START_DELAY, parent.profilingStartDelay);
profilingStartForceEarly = profilingStartForceFirst =
getPropertyBooleanValue( getPropertyBooleanValue(
properties, PROFILING_START_FORCE_EARLY, parent.profilingStartForceEarly); properties, PROFILING_START_FORCE_FIRST, parent.profilingStartForceFirst);
profilingUploadPeriod = profilingUploadPeriod =
getPropertyIntegerValue(properties, PROFILING_UPLOAD_PERIOD, parent.profilingUploadPeriod); getPropertyIntegerValue(properties, PROFILING_UPLOAD_PERIOD, parent.profilingUploadPeriod);
profilingTemplateOverrideFile = profilingTemplateOverrideFile =

View File

@ -41,7 +41,7 @@ import static datadog.trace.api.Config.PROFILING_PROXY_PASSWORD
import static datadog.trace.api.Config.PROFILING_PROXY_PORT import static datadog.trace.api.Config.PROFILING_PROXY_PORT
import static datadog.trace.api.Config.PROFILING_PROXY_USERNAME import static datadog.trace.api.Config.PROFILING_PROXY_USERNAME
import static datadog.trace.api.Config.PROFILING_START_DELAY import static datadog.trace.api.Config.PROFILING_START_DELAY
import static datadog.trace.api.Config.PROFILING_START_FORCE_EARLY import static datadog.trace.api.Config.PROFILING_START_FORCE_FIRST
import static datadog.trace.api.Config.PROFILING_TAGS import static datadog.trace.api.Config.PROFILING_TAGS
import static datadog.trace.api.Config.PROFILING_TEMPLATE_OVERRIDE_FILE import static datadog.trace.api.Config.PROFILING_TEMPLATE_OVERRIDE_FILE
import static datadog.trace.api.Config.PROFILING_UPLOAD_COMPRESSION import static datadog.trace.api.Config.PROFILING_UPLOAD_COMPRESSION
@ -137,7 +137,7 @@ class ConfigTest extends DDSpecification {
config.profilingApiKey == null config.profilingApiKey == null
config.mergedProfilingTags == [(HOST_TAG): config.getHostName(), (RUNTIME_ID_TAG): config.getRuntimeId(), (SERVICE_TAG): config.serviceName, (LANGUAGE_TAG_KEY): LANGUAGE_TAG_VALUE] config.mergedProfilingTags == [(HOST_TAG): config.getHostName(), (RUNTIME_ID_TAG): config.getRuntimeId(), (SERVICE_TAG): config.serviceName, (LANGUAGE_TAG_KEY): LANGUAGE_TAG_VALUE]
config.profilingStartDelay == 10 config.profilingStartDelay == 10
config.profilingStartForceEarly == false config.profilingStartForceFirst == false
config.profilingUploadPeriod == 60 config.profilingUploadPeriod == 60
config.profilingTemplateOverrideFile == null config.profilingTemplateOverrideFile == null
config.profilingUploadTimeout == 30 config.profilingUploadTimeout == 30
@ -202,7 +202,7 @@ class ConfigTest extends DDSpecification {
prop.setProperty(PROFILING_API_KEY, "new api key") prop.setProperty(PROFILING_API_KEY, "new api key")
prop.setProperty(PROFILING_TAGS, "f:6,host:test-host") prop.setProperty(PROFILING_TAGS, "f:6,host:test-host")
prop.setProperty(PROFILING_START_DELAY, "1111") prop.setProperty(PROFILING_START_DELAY, "1111")
prop.setProperty(PROFILING_START_FORCE_EARLY, "true") prop.setProperty(PROFILING_START_FORCE_FIRST, "true")
prop.setProperty(PROFILING_UPLOAD_PERIOD, "1112") prop.setProperty(PROFILING_UPLOAD_PERIOD, "1112")
prop.setProperty(PROFILING_TEMPLATE_OVERRIDE_FILE, "/path") prop.setProperty(PROFILING_TEMPLATE_OVERRIDE_FILE, "/path")
prop.setProperty(PROFILING_UPLOAD_TIMEOUT, "1116") prop.setProperty(PROFILING_UPLOAD_TIMEOUT, "1116")
@ -258,7 +258,7 @@ class ConfigTest extends DDSpecification {
config.profilingApiKey == "new api key" // we can still override via internal properties object config.profilingApiKey == "new api key" // we can still override via internal properties object
config.mergedProfilingTags == [b: "2", f: "6", (HOST_TAG): "test-host", (RUNTIME_ID_TAG): config.getRuntimeId(), (SERVICE_TAG): config.serviceName, (LANGUAGE_TAG_KEY): LANGUAGE_TAG_VALUE] config.mergedProfilingTags == [b: "2", f: "6", (HOST_TAG): "test-host", (RUNTIME_ID_TAG): config.getRuntimeId(), (SERVICE_TAG): config.serviceName, (LANGUAGE_TAG_KEY): LANGUAGE_TAG_VALUE]
config.profilingStartDelay == 1111 config.profilingStartDelay == 1111
config.profilingStartForceEarly == true config.profilingStartForceFirst == true
config.profilingUploadPeriod == 1112 config.profilingUploadPeriod == 1112
config.profilingUploadCompression == "off" config.profilingUploadCompression == "off"
config.profilingTemplateOverrideFile == "/path" config.profilingTemplateOverrideFile == "/path"
@ -314,7 +314,7 @@ class ConfigTest extends DDSpecification {
System.setProperty(PREFIX + PROFILING_API_KEY, "new api key") System.setProperty(PREFIX + PROFILING_API_KEY, "new api key")
System.setProperty(PREFIX + PROFILING_TAGS, "f:6,host:test-host") System.setProperty(PREFIX + PROFILING_TAGS, "f:6,host:test-host")
System.setProperty(PREFIX + PROFILING_START_DELAY, "1111") System.setProperty(PREFIX + PROFILING_START_DELAY, "1111")
System.setProperty(PREFIX + PROFILING_START_FORCE_EARLY, "true") System.setProperty(PREFIX + PROFILING_START_FORCE_FIRST, "true")
System.setProperty(PREFIX + PROFILING_UPLOAD_PERIOD, "1112") System.setProperty(PREFIX + PROFILING_UPLOAD_PERIOD, "1112")
System.setProperty(PREFIX + PROFILING_TEMPLATE_OVERRIDE_FILE, "/path") System.setProperty(PREFIX + PROFILING_TEMPLATE_OVERRIDE_FILE, "/path")
System.setProperty(PREFIX + PROFILING_UPLOAD_TIMEOUT, "1116") System.setProperty(PREFIX + PROFILING_UPLOAD_TIMEOUT, "1116")
@ -370,7 +370,7 @@ class ConfigTest extends DDSpecification {
config.profilingApiKey == null // system properties cannot be used to provide a key config.profilingApiKey == null // system properties cannot be used to provide a key
config.mergedProfilingTags == [b: "2", f: "6", (HOST_TAG): "test-host", (RUNTIME_ID_TAG): config.getRuntimeId(), (SERVICE_TAG): config.serviceName, (LANGUAGE_TAG_KEY): LANGUAGE_TAG_VALUE] config.mergedProfilingTags == [b: "2", f: "6", (HOST_TAG): "test-host", (RUNTIME_ID_TAG): config.getRuntimeId(), (SERVICE_TAG): config.serviceName, (LANGUAGE_TAG_KEY): LANGUAGE_TAG_VALUE]
config.profilingStartDelay == 1111 config.profilingStartDelay == 1111
config.profilingStartForceEarly == true config.profilingStartForceFirst == true
config.profilingUploadPeriod == 1112 config.profilingUploadPeriod == 1112
config.profilingTemplateOverrideFile == "/path" config.profilingTemplateOverrideFile == "/path"
config.profilingUploadTimeout == 1116 config.profilingUploadTimeout == 1116