Skip to content

Commit

Permalink
Fix APM tracer libraries verification (#444)
Browse files Browse the repository at this point in the history
  • Loading branch information
nikita-tkachenko-datadog authored Aug 20, 2024
1 parent c7ac69a commit dc96660
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,27 @@ public Map<String, String> configure(Run<?, ?> run, Computer computer, Node node
return Collections.emptyMap();
}

TopLevelItem topLevelItem = getTopLevelItem(run);
FilePath workspacePath = node.getWorkspaceFor(topLevelItem);
if (workspacePath == null) {
listener.error("[datadog] Cannot find workspace path for " + topLevelItem + " on " + node);
return Collections.emptyMap();
}

String nodeHostname = DatadogUtilities.getNodeHostname(envs, computer);
Collection<TracerLanguage> languages = tracerConfig.getLanguages();
for (ConfigureTracerAction action : run.getActions(ConfigureTracerAction.class)) {
if (nodeHostname != null && nodeHostname.equals(action.nodeHostname) && action.languages.containsAll(languages)) {
return action.variables;
boolean previousConfigurationValid = true;
for (TracerLanguage language : action.languages) {
TracerConfigurator tracerConfigurator = configurators.get(language);
if (tracerConfigurator != null) {
previousConfigurationValid &= tracerConfigurator.isConfigurationValid(node, workspacePath);
}
}
if (previousConfigurationValid) {
return action.variables;
}
}
}

Expand All @@ -62,13 +78,6 @@ public Map<String, String> configure(Run<?, ?> run, Computer computer, Node node
return Collections.emptyMap();
}

TopLevelItem topLevelItem = getTopLevelItem(run);
FilePath workspacePath = node.getWorkspaceFor(topLevelItem);
if (workspacePath == null) {
listener.error("[datadog] Cannot find workspace path for " + topLevelItem + " on " + node);
return Collections.emptyMap();
}

Map<String, String> variables = new HashMap<>(getCommonEnvVariables(datadogConfig, tracerConfig));
for (TracerLanguage language : languages) {
TracerConfigurator tracerConfigurator = configurators.get(language);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import hudson.model.TaskListener;
import hudson.util.Secret;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
Expand All @@ -14,14 +15,16 @@
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.logging.Level;
import java.util.logging.Logger;
import jenkins.model.Jenkins;
import org.datadog.jenkins.plugins.datadog.DatadogUtilities;
import org.datadog.jenkins.plugins.datadog.apm.signature.SignatureVerifier;
import org.datadog.jenkins.plugins.datadog.clients.HttpClient;

final class JavaConfigurator implements TracerConfigurator {

private static final Logger LOGGER = Logger.getLogger(DatadogTracerConfigurator.class.getName());
private static final Logger LOGGER = Logger.getLogger(JavaConfigurator.class.getName());

private static final String TRACER_DISTRIBUTION_URL_ENV_VAR = "DATADOG_JENKINS_PLUGIN_TRACER_DISTRIBUTION_URL";
private static final String DEFAULT_TRACER_DISTRIBUTION_URL = "https://dtdg.co/latest-java-tracer";
Expand All @@ -43,10 +46,7 @@ public Map<String, String> configure(DatadogTracerJobProperty<?> tracerConfig, N
}

private FilePath downloadTracer(DatadogTracerJobProperty<?> tracerConfig, FilePath workspacePath, Node node, TaskListener listener) throws Exception {
FilePath datadogFolder = workspacePath.child(".datadog");
datadogFolder.mkdirs();

FilePath datadogTracerFile = datadogFolder.child(TRACER_FILE_NAME);
FilePath datadogTracerFile = getDatadogTracerFile(workspacePath);
long minutesSinceModification = TimeUnit.MILLISECONDS.toMinutes(System.currentTimeMillis() - datadogTracerFile.lastModified());
if (minutesSinceModification < getTracerJarCacheTtlMinutes(tracerConfig)) {
listener.getLogger().println("[datadog] Configuring DD Java tracer: using existing tracer available at " + datadogTracerFile);
Expand Down Expand Up @@ -86,6 +86,12 @@ private FilePath downloadTracer(DatadogTracerJobProperty<?> tracerConfig, FilePa
return datadogTracerFile.absolutize();
}

private static FilePath getDatadogTracerFile(FilePath workspacePath) throws IOException, InterruptedException {
FilePath datadogFolder = workspacePath.child(".datadog");
datadogFolder.mkdirs();
return datadogFolder.child(TRACER_FILE_NAME);
}

private int getTracerJarCacheTtlMinutes(DatadogTracerJobProperty<?> tracerConfig) {
return getSetting(tracerConfig, TRACER_JAR_CACHE_TTL_ENV_VAR, DEFAULT_TRACER_JAR_CACHE_TTL_MINUTES, Integer::parseInt);
}
Expand Down Expand Up @@ -212,4 +218,15 @@ private static String getProxyConfiguration(DatadogTracerJobProperty<?> tracerCo
}
return proxyOptions.length() > 0 ? proxyOptions.toString() : null;
}

@Override
public boolean isConfigurationValid(Node node, FilePath workspacePath) {
try {
FilePath datadogTracerFile = getDatadogTracerFile(workspacePath);
return datadogTracerFile.exists();
} catch (Exception e) {
DatadogUtilities.logException(LOGGER, Level.FINE, "Could not verify Java tracer file existence", e);
return false;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,19 @@
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.datadog.jenkins.plugins.datadog.DatadogUtilities;

final class JavascriptConfigurator implements TracerConfigurator {

private static final Logger LOGGER = Logger.getLogger(JavascriptConfigurator.class.getName());

private static final int GET_NPM_VERSION_TIMEOUT_MILLIS = 30_000;
private static final int INSTALL_TRACER_TIMEOUT_MILLIS = 300_000;

private static final String RELATIVE_TRACER_PATH = "lib/node_modules/dd-trace";

@Override
public Map<String, String> configure(DatadogTracerJobProperty<?> tracerConfig, Node node, FilePath workspacePath, Map<String, String> envs, TaskListener listener) throws Exception {
String nodeVersion = workspacePath.act(new ShellCommandCallable(Collections.emptyMap(), GET_NPM_VERSION_TIMEOUT_MILLIS, "npm", "-v"));
Expand All @@ -29,12 +36,24 @@ public Map<String, String> configure(DatadogTracerJobProperty<?> tracerConfig, N
// we install dd-trace as a "global" package
// (otherwise, doing SCM checkout might rollback the changes to package.json, and any subsequent `npm install` calls will result in removing the package)
String installTracerOutput = workspacePath.act(new ShellCommandCallable(environment, INSTALL_TRACER_TIMEOUT_MILLIS, "npm", "install", "-g", "dd-trace"));
Path tracerPath = absoluteDatadogPath.resolve("lib/node_modules/dd-trace");
Path tracerPath = absoluteDatadogPath.resolve(RELATIVE_TRACER_PATH);
listener.getLogger().println("[datadog] Configuring DD JS tracer: tracer installed in " + tracerPath + " on " + node + "; output: " + installTracerOutput);

Map<String, String> variables = new HashMap<>();
variables.put("DD_TRACE_PATH", tracerPath.toString());
variables.put("NODE_OPTIONS", PropertyUtils.prepend(envs, "NODE_OPTIONS", String.format("-r %s/ci/init", tracerPath)));
return variables;
}

@Override
public boolean isConfigurationValid(Node node, FilePath workspacePath) {
try {
FilePath datadogPath = workspacePath.child(".datadog");
FilePath tracerPath = datadogPath.child(RELATIVE_TRACER_PATH);
return tracerPath.exists();
} catch (Exception e) {
DatadogUtilities.logException(LOGGER, Level.FINE, "Could not verify JS tracer file existence", e);
return false;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,14 @@
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.datadog.jenkins.plugins.datadog.DatadogUtilities;

final class PythonConfigurator implements TracerConfigurator {

private static final Logger LOGGER = Logger.getLogger(PythonConfigurator.class.getName());

private static final int GET_PIP_VERSION_TIMEOUT_MILLIS = 30_000;
private static final int INSTALL_TRACER_TIMEOUT_MILLIS = 300_000;
private static final int SHOW_TRACER_PACKAGE_DETAILS_TIMEOUT_MILLIS = 300_000;
Expand Down Expand Up @@ -39,4 +44,15 @@ private static String getTracerLocation(FilePath workspacePath) throws IOExcepti
}
throw new IllegalStateException("Could not determine tracer location in " + workspacePath + "; command output is: " + getTracerLocationOutput);
}

@Override
public boolean isConfigurationValid(Node node, FilePath workspacePath) {
try {
String tracerLocation = getTracerLocation(workspacePath);
return workspacePath.child(tracerLocation).exists();
} catch (Exception e) {
DatadogUtilities.logException(LOGGER, Level.FINE, "Could not verify Python tracer file existence", e);
return false;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,11 @@ Map<String, String> configure(DatadogTracerJobProperty<?> tracerConfig,
FilePath workspacePath,
Map<String, String> envs,
TaskListener listener) throws Exception;

/**
* Is used to check whether configuration is valid or needs to be re-applied.
*/
default boolean isConfigurationValid(Node node, FilePath workspacePath) {
return true;
}
}

0 comments on commit dc96660

Please sign in to comment.