Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for 'auto' value in DD_PROFILING_ENABLED #7264

Merged
merged 1 commit into from
Jul 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import datadog.trace.api.config.UsmConfig;
import datadog.trace.api.gateway.RequestContextSlot;
import datadog.trace.api.gateway.SubscriptionService;
import datadog.trace.api.profiling.ProfilingEnablement;
import datadog.trace.api.scopemanager.ScopeListener;
import datadog.trace.bootstrap.benchmark.StaticEventLogger;
import datadog.trace.bootstrap.instrumentation.api.AgentTracer;
Expand Down Expand Up @@ -1124,6 +1125,11 @@ private static boolean isFeatureEnabled(AgentFeature feature) {
// true unless it's explicitly set to "false"
return !("false".equalsIgnoreCase(featureEnabled) || "0".equals(featureEnabled));
} else {
if (feature == AgentFeature.PROFILING) {
// We need this hack because profiling in SSI can receive 'auto' value in
// the enablement config
return ProfilingEnablement.of(featureEnabled).isActive();
}
// false unless it's explicitly set to "true"
return Boolean.parseBoolean(featureEnabled) || "1".equals(featureEnabled);
}
Expand Down
37 changes: 29 additions & 8 deletions internal-api/src/main/java/datadog/trace/api/Config.java
Original file line number Diff line number Diff line change
Expand Up @@ -495,6 +495,7 @@
import datadog.trace.api.iast.IastDetectionMode;
import datadog.trace.api.iast.telemetry.Verbosity;
import datadog.trace.api.naming.SpanNaming;
import datadog.trace.api.profiling.ProfilingEnablement;
import datadog.trace.bootstrap.config.provider.CapturedEnvironmentConfigSource;
import datadog.trace.bootstrap.config.provider.ConfigProvider;
import datadog.trace.bootstrap.config.provider.SystemPropertiesConfigSource;
Expand Down Expand Up @@ -709,7 +710,7 @@ static class HostNameHolder {
private final String spanSamplingRules;
private final String spanSamplingRulesFile;

private final boolean profilingEnabled;
private final ProfilingEnablement profilingEnabled;
private final boolean profilingAgentless;
private final boolean isDatadogProfilerEnabled;
@Deprecated private final String profilingUrl;
Expand Down Expand Up @@ -1504,9 +1505,12 @@ private Config(final ConfigProvider configProvider, final InstrumenterConfig ins
// on whether
// the profiler was enabled at build time or not.
// Otherwise just do the standard config lookup by key.
// An extra step is needed to properly handle the 'auto' value for profiling enablement via SSI.
profilingEnabled =
configProvider.getBoolean(
ProfilingConfig.PROFILING_ENABLED, instrumenterConfig.isProfilingEnabled());
ProfilingEnablement.of(
configProvider.getString(
ProfilingConfig.PROFILING_ENABLED,
String.valueOf(instrumenterConfig.isProfilingEnabled())));
profilingAgentless =
configProvider.getBoolean(PROFILING_AGENTLESS, PROFILING_AGENTLESS_DEFAULT);
isDatadogProfilerEnabled =
Expand Down Expand Up @@ -1548,10 +1552,27 @@ PROFILING_DATADOG_PROFILER_ENABLED, isDatadogProfilerSafeInCurrentEnvironment())
}

profilingTags = configProvider.getMergedMap(PROFILING_TAGS);
profilingStartDelay =
int profilingStartDelayValue =
configProvider.getInteger(PROFILING_START_DELAY, PROFILING_START_DELAY_DEFAULT);
profilingStartForceFirst =
boolean profilingStartForceFirstValue =
configProvider.getBoolean(PROFILING_START_FORCE_FIRST, PROFILING_START_FORCE_FIRST_DEFAULT);
if (profilingEnabled == ProfilingEnablement.AUTO) {
if (profilingStartDelayValue != PROFILING_START_DELAY_DEFAULT) {
log.info(
"Profiling start delay is set to {}s, but profiling enablement is set to auto. Using the default delay of {}s.",
profilingStartDelayValue,
PROFILING_START_DELAY_DEFAULT);
}
if (profilingStartForceFirstValue != PROFILING_START_FORCE_FIRST_DEFAULT) {
log.info(
"Profiling is requested to start immediately, but profiling enablement is set to auto. Profiling will be started with delay of {}s.",
PROFILING_START_DELAY_DEFAULT);
}
profilingStartDelayValue = PROFILING_START_DELAY_DEFAULT;
profilingStartForceFirstValue = PROFILING_START_FORCE_FIRST_DEFAULT;
}
profilingStartDelay = profilingStartDelayValue;
profilingStartForceFirst = profilingStartForceFirstValue;
profilingUploadPeriod =
configProvider.getInteger(PROFILING_UPLOAD_PERIOD, PROFILING_UPLOAD_PERIOD_DEFAULT);
profilingTemplateOverrideFile = configProvider.getString(PROFILING_TEMPLATE_OVERRIDE_FILE);
Expand Down Expand Up @@ -2664,14 +2685,14 @@ public String getSpanSamplingRulesFile() {

public boolean isProfilingEnabled() {
if (Platform.isNativeImage()) {
if (!instrumenterConfig.isProfilingEnabled() && profilingEnabled) {
if (!instrumenterConfig.isProfilingEnabled() && profilingEnabled.isActive()) {
log.warn(
"Profiling was not enabled during the native image build. "
+ "Please set DD_PROFILING_ENABLED=true in your native image build configuration if you want"
+ "to use profiling.");
}
}
return profilingEnabled && instrumenterConfig.isProfilingEnabled();
return profilingEnabled.isActive() && instrumenterConfig.isProfilingEnabled();
}

public boolean isProfilingTimelineEventsEnabled() {
Expand Down Expand Up @@ -2759,7 +2780,7 @@ public boolean isProfilingRecordExceptionMessage() {
}

public boolean isDatadogProfilerEnabled() {
return profilingEnabled && isDatadogProfilerEnabled;
return isProfilingEnabled() && isDatadogProfilerEnabled;
}

public static boolean isDatadogProfilerEnablementOverridden() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@
import static datadog.trace.util.CollectionUtils.tryMakeImmutableList;
import static datadog.trace.util.CollectionUtils.tryMakeImmutableSet;

import datadog.trace.api.profiling.ProfilingEnablement;
import datadog.trace.bootstrap.config.provider.ConfigProvider;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.lang.reflect.Method;
Expand Down Expand Up @@ -103,7 +104,7 @@ public class InstrumenterConfig {
private final boolean traceEnabled;
private final boolean traceOtelEnabled;
private final boolean logs128bTraceIdEnabled;
private final boolean profilingEnabled;
private final ProfilingEnablement profilingEnabled;
private final boolean ciVisibilityEnabled;
private final ProductActivation appSecActivation;
private final ProductActivation iastActivation;
Expand Down Expand Up @@ -178,7 +179,9 @@ private InstrumenterConfig() {
logs128bTraceIdEnabled =
configProvider.getBoolean(
TRACE_128_BIT_TRACEID_LOGGING_ENABLED, DEFAULT_TRACE_128_BIT_TRACEID_LOGGING_ENABLED);
profilingEnabled = configProvider.getBoolean(PROFILING_ENABLED, PROFILING_ENABLED_DEFAULT);
profilingEnabled =
ProfilingEnablement.of(
configProvider.getString(PROFILING_ENABLED, String.valueOf(PROFILING_ENABLED_DEFAULT)));

if (!Platform.isNativeImageBuilder()) {
ciVisibilityEnabled =
Expand Down Expand Up @@ -301,7 +304,7 @@ public boolean isLogs128bTraceIdEnabled() {
}

public boolean isProfilingEnabled() {
return profilingEnabled;
return profilingEnabled.isActive();
}

public boolean isCiVisibilityEnabled() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package datadog.trace.api.profiling;

public enum ProfilingEnablement {
ENABLED(true),
DISABLED(false),
AUTO(true);

private final boolean active;

ProfilingEnablement(boolean active) {
this.active = active;
}

public boolean isActive() {
return active;
}

public static ProfilingEnablement of(String value) {
if (value == null) {
return DISABLED;
}
switch (value.toLowerCase()) {
case "true":
case "1":
return ENABLED;
case "auto":
return AUTO;
default:
return DISABLED;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,9 @@ import static datadog.trace.api.config.ProfilingConfig.PROFILING_PROXY_PASSWORD
import static datadog.trace.api.config.ProfilingConfig.PROFILING_PROXY_PORT
import static datadog.trace.api.config.ProfilingConfig.PROFILING_PROXY_USERNAME
import static datadog.trace.api.config.ProfilingConfig.PROFILING_START_DELAY
import static datadog.trace.api.config.ProfilingConfig.PROFILING_START_DELAY_DEFAULT
import static datadog.trace.api.config.ProfilingConfig.PROFILING_START_FORCE_FIRST
import static datadog.trace.api.config.ProfilingConfig.PROFILING_START_FORCE_FIRST_DEFAULT
import static datadog.trace.api.config.ProfilingConfig.PROFILING_TAGS
import static datadog.trace.api.config.ProfilingConfig.PROFILING_TEMPLATE_OVERRIDE_FILE
import static datadog.trace.api.config.ProfilingConfig.PROFILING_UPLOAD_COMPRESSION
Expand Down Expand Up @@ -2440,4 +2442,27 @@ class ConfigTest extends DDSpecification {
true | 11 | 11
false | 17 | 0
}

def "check profiling SSI auto-enablement"() {
when:
def prop = new Properties()
prop.setProperty(PROFILING_ENABLED, enablementMode)
prop.setProperty(PROFILING_START_DELAY, "1")
prop.setProperty(PROFILING_START_FORCE_FIRST, "true")

Config config = Config.get(prop)

then:
config.profilingEnabled == expectedEnabled
config.profilingStartDelay == expectedStartDelay
config.profilingStartForceFirst == expectedStartForceFirst

where:
// spotless:off
enablementMode | expectedEnabled | expectedStartDelay | expectedStartForceFirst
"true" | true | 1 | true
"false" | false | 1 | true
"auto" | true | PROFILING_START_DELAY_DEFAULT | PROFILING_START_FORCE_FIRST_DEFAULT
// spotless:on
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package datadog.trace.api.profiling;

import static org.junit.jupiter.api.Assertions.*;

import java.util.stream.Stream;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;

class ProfilingEnablementTest {

@ParameterizedTest
@MethodSource("provideValues")
void of(String value, ProfilingEnablement expected) {
assertEquals(expected, ProfilingEnablement.of(value));
}

private static Stream<Arguments> provideValues() {
return Stream.of(
Arguments.of("true", ProfilingEnablement.ENABLED),
Arguments.of("TRUE", ProfilingEnablement.ENABLED),
Arguments.of("tRuE", ProfilingEnablement.ENABLED),
Arguments.of("1", ProfilingEnablement.ENABLED),
Arguments.of("auto", ProfilingEnablement.AUTO),
Arguments.of("AUTO", ProfilingEnablement.AUTO),
Arguments.of("aUtO", ProfilingEnablement.AUTO),
Arguments.of("false", ProfilingEnablement.DISABLED),
Arguments.of("FALSE", ProfilingEnablement.DISABLED),
Arguments.of("fAlSe", ProfilingEnablement.DISABLED),
Arguments.of("0", ProfilingEnablement.DISABLED),
Arguments.of("anything", ProfilingEnablement.DISABLED),
Arguments.of(null, ProfilingEnablement.DISABLED));
}
}
Loading