diff --git a/BUILDING.md b/BUILDING.md index 1859c8dcce0..10b49764979 100644 --- a/BUILDING.md +++ b/BUILDING.md @@ -10,7 +10,7 @@ This documentation is dedicated to developers to setup their environment, and bu ## Development environment quick check -As a preliminary step, you can quickly check that your development environment is properly set up to build the project running `./setup.sh` from the project root: +To check that your development environment is properly set up to build the project, you will eventually run `./setup.sh` from the project root and should have its output look something like this: ```bash $ ./setup.sh diff --git a/communication/src/main/java/datadog/communication/BackendApiFactory.java b/communication/src/main/java/datadog/communication/BackendApiFactory.java index 296d22cb36f..f60eaa7e215 100644 --- a/communication/src/main/java/datadog/communication/BackendApiFactory.java +++ b/communication/src/main/java/datadog/communication/BackendApiFactory.java @@ -34,8 +34,13 @@ public BackendApiFactory(Config config, SharedCommunicationObjects sharedCommuni "Agentless mode is enabled and api key is not set. Please set application key"); } String traceId = config.getIdGenerationStrategy().generateTraceId().toString(); - long timeoutMillis = config.getCiVisibilityBackendApiTimeoutMillis(); - return new IntakeApi(agentlessUrl, apiKey, traceId, timeoutMillis, retryPolicyFactory, true); + return new IntakeApi( + agentlessUrl, + apiKey, + traceId, + retryPolicyFactory, + sharedCommunicationObjects.okHttpClient, + true); } DDAgentFeaturesDiscovery featuresDiscovery = diff --git a/communication/src/main/java/datadog/communication/IntakeApi.java b/communication/src/main/java/datadog/communication/IntakeApi.java index ff29dc89124..3f1fe9df67f 100644 --- a/communication/src/main/java/datadog/communication/IntakeApi.java +++ b/communication/src/main/java/datadog/communication/IntakeApi.java @@ -37,16 +37,15 @@ public IntakeApi( HttpUrl hostUrl, String apiKey, String traceId, - long timeoutMillis, HttpRetryPolicy.Factory retryPolicyFactory, + OkHttpClient httpClient, boolean responseCompression) { this.hostUrl = hostUrl; this.apiKey = apiKey; this.traceId = traceId; this.retryPolicyFactory = retryPolicyFactory; this.responseCompression = responseCompression; - - httpClient = OkHttpUtils.buildHttpClient(hostUrl, timeoutMillis); + this.httpClient = httpClient; } @Override diff --git a/communication/src/main/java/datadog/communication/ddagent/SharedCommunicationObjects.java b/communication/src/main/java/datadog/communication/ddagent/SharedCommunicationObjects.java index 8c02098fe81..14de312dadc 100644 --- a/communication/src/main/java/datadog/communication/ddagent/SharedCommunicationObjects.java +++ b/communication/src/main/java/datadog/communication/ddagent/SharedCommunicationObjects.java @@ -36,11 +36,21 @@ public void createRemaining(Config config) { } } if (okHttpClient == null) { - String unixDomainSocket = SocketUtils.discoverApmSocket(config); - String namedPipe = config.getAgentNamedPipe(); + String unixDomainSocket; + String namedPipe; + HttpUrl url; + if (!config.isCiVisibilityAgentlessEnabled()) { + unixDomainSocket = SocketUtils.discoverApmSocket(config); + namedPipe = config.getAgentNamedPipe(); + url = agentUrl; + } else { + unixDomainSocket = null; + namedPipe = null; + url = null; + } okHttpClient = OkHttpUtils.buildHttpClient( - agentUrl, unixDomainSocket, namedPipe, getHttpClientTimeout(config)); + url, unixDomainSocket, namedPipe, getHttpClientTimeout(config)); } } diff --git a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/CiVisibilityServices.java b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/CiVisibilityServices.java index 93e1271316b..31fd0ff0cfd 100644 --- a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/CiVisibilityServices.java +++ b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/CiVisibilityServices.java @@ -1,12 +1,20 @@ package datadog.trace.civisibility; +import com.squareup.moshi.JsonAdapter; +import com.squareup.moshi.Moshi; +import com.squareup.moshi.Types; import datadog.communication.BackendApi; import datadog.communication.BackendApiFactory; import datadog.communication.ddagent.SharedCommunicationObjects; +import datadog.communication.http.HttpRetryPolicy; +import datadog.communication.http.OkHttpUtils; import datadog.trace.api.Config; import datadog.trace.api.civisibility.telemetry.CiVisibilityMetricCollector; import datadog.trace.api.git.GitInfoProvider; import datadog.trace.civisibility.ci.CIProviderInfoFactory; +import datadog.trace.civisibility.ci.env.CiEnvironment; +import datadog.trace.civisibility.ci.env.CiEnvironmentImpl; +import datadog.trace.civisibility.ci.env.CompositeCiEnvironment; import datadog.trace.civisibility.config.CachingJvmInfoFactory; import datadog.trace.civisibility.config.JvmInfoFactory; import datadog.trace.civisibility.config.JvmInfoFactoryImpl; @@ -19,19 +27,22 @@ import datadog.trace.civisibility.source.ByteCodeMethodLinesResolver; import datadog.trace.civisibility.source.CompilerAidedMethodLinesResolver; import datadog.trace.civisibility.source.MethodLinesResolver; -import datadog.trace.civisibility.source.index.CachingRepoIndexBuilderFactory; -import datadog.trace.civisibility.source.index.ConventionBasedResourceResolver; -import datadog.trace.civisibility.source.index.PackageResolver; -import datadog.trace.civisibility.source.index.PackageResolverImpl; -import datadog.trace.civisibility.source.index.RepoIndexFetcher; -import datadog.trace.civisibility.source.index.RepoIndexProvider; -import datadog.trace.civisibility.source.index.ResourceResolver; +import datadog.trace.civisibility.source.index.*; import datadog.trace.civisibility.utils.ProcessHierarchyUtils; +import java.lang.reflect.Type; import java.net.InetSocketAddress; import java.nio.file.FileSystem; import java.nio.file.FileSystems; import java.nio.file.Path; +import java.util.Collections; +import java.util.Map; import javax.annotation.Nullable; +import okhttp3.HttpUrl; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import org.jetbrains.annotations.NotNull; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * Services that do not need repository root location to be instantiated. Can be shared between @@ -39,8 +50,12 @@ */ public class CiVisibilityServices { + private static final Logger logger = LoggerFactory.getLogger(CiVisibilityServices.class); + private static final String GIT_FOLDER_NAME = ".git"; + static final String DD_ENV_VARS_PROVIDER_KEY_HEADER = "DD-Env-Vars-Provider-Key"; + final Config config; final CiVisibilityMetricCollector metricCollector; final BackendApi backendApi; @@ -63,13 +78,15 @@ public class CiVisibilityServices { new BackendApiFactory(config, sco).createBackendApi(BackendApiFactory.Intake.API); this.jvmInfoFactory = new CachingJvmInfoFactory(config, new JvmInfoFactoryImpl()); this.gitClientFactory = new GitClient.Factory(config, metricCollector); - this.ciProviderInfoFactory = new CIProviderInfoFactory(config); + + CiEnvironment environment = buildCiEnvironment(config, sco); + this.ciProviderInfoFactory = new CIProviderInfoFactory(config, environment); this.methodLinesResolver = new BestEffortMethodLinesResolver( new CompilerAidedMethodLinesResolver(), new ByteCodeMethodLinesResolver()); this.gitInfoProvider = gitInfoProvider; - gitInfoProvider.registerGitInfoBuilder(new CIProviderGitInfoBuilder()); + gitInfoProvider.registerGitInfoBuilder(new CIProviderGitInfoBuilder(config, environment)); gitInfoProvider.registerGitInfoBuilder( new CILocalGitInfoBuilder(gitClientFactory, GIT_FOLDER_NAME)); gitInfoProvider.registerGitInfoBuilder(new GitClientGitInfoBuilder(config, gitClientFactory)); @@ -94,6 +111,55 @@ public class CiVisibilityServices { } } + @NotNull + private static CiEnvironment buildCiEnvironment(Config config, SharedCommunicationObjects sco) { + String remoteEnvVarsProviderUrl = config.getCiVisibilityRemoteEnvVarsProviderUrl(); + if (remoteEnvVarsProviderUrl != null) { + String remoteEnvVarsProviderKey = config.getCiVisibilityRemoteEnvVarsProviderKey(); + CiEnvironment remoteEnvironment = + new CiEnvironmentImpl( + getRemoteEnvironment( + remoteEnvVarsProviderUrl, remoteEnvVarsProviderKey, sco.okHttpClient)); + CiEnvironment localEnvironment = new CiEnvironmentImpl(System.getenv()); + return new CompositeCiEnvironment(remoteEnvironment, localEnvironment); + } else { + return new CiEnvironmentImpl(System.getenv()); + } + } + + static Map getRemoteEnvironment(String url, String key, OkHttpClient httpClient) { + HttpRetryPolicy.Factory retryPolicyFactory = new HttpRetryPolicy.Factory(5, 100, 2.0, true); + + HttpUrl httpUrl = HttpUrl.get(url); + Request request = + new Request.Builder() + .url(httpUrl) + .header(DD_ENV_VARS_PROVIDER_KEY_HEADER, key) + .get() + .build(); + try (okhttp3.Response response = + OkHttpUtils.sendWithRetries(httpClient, retryPolicyFactory, request)) { + + if (response.isSuccessful()) { + Moshi moshi = new Moshi.Builder().build(); + Type type = Types.newParameterizedType(Map.class, String.class, String.class); + JsonAdapter> adapter = moshi.adapter(type); + return adapter.fromJson(response.body().source()); + } else { + logger.warn( + "Could not get remote CI environment (HTTP code " + + response.code() + + ")" + + (response.body() != null ? ": " + response.body().string() : "")); + return Collections.emptyMap(); + } + + } catch (Exception e) { + logger.warn("Could not get remote CI environment", e); + return Collections.emptyMap(); + } + } + CiVisibilityRepoServices repoServices(Path path) { return new CiVisibilityRepoServices(this, path); } diff --git a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/AppVeyorInfo.java b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/AppVeyorInfo.java index 80315deb1d8..d5e97d581b3 100644 --- a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/AppVeyorInfo.java +++ b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/AppVeyorInfo.java @@ -8,6 +8,7 @@ import datadog.trace.api.git.CommitInfo; import datadog.trace.api.git.GitInfo; import datadog.trace.api.git.PersonInfo; +import datadog.trace.civisibility.ci.env.CiEnvironment; class AppVeyorInfo implements CIProviderInfo { @@ -31,13 +32,19 @@ class AppVeyorInfo implements CIProviderInfo { public static final String APPVEYOR_REPO_COMMIT_AUTHOR_EMAIL = "APPVEYOR_REPO_COMMIT_AUTHOR_EMAIL"; + private final CiEnvironment environment; + + AppVeyorInfo(CiEnvironment environment) { + this.environment = environment; + } + @Override public GitInfo buildCIGitInfo() { - final String repoProvider = System.getenv(APPVEYOR_REPO_PROVIDER); - final String messageSubject = System.getenv(APPVEYOR_REPO_COMMIT_MESSAGE_SUBJECT); - final String messageBody = System.getenv(APPVEYOR_REPO_COMMIT_MESSAGE_BODY); + final String repoProvider = environment.get(APPVEYOR_REPO_PROVIDER); + final String messageSubject = environment.get(APPVEYOR_REPO_COMMIT_MESSAGE_SUBJECT); + final String messageBody = environment.get(APPVEYOR_REPO_COMMIT_MESSAGE_BODY); return new GitInfo( - buildGitRepositoryUrl(repoProvider, System.getenv(APPVEYOR_REPO_NAME)), + buildGitRepositoryUrl(repoProvider, environment.get(APPVEYOR_REPO_NAME)), buildGitBranch(repoProvider), buildGitTag(repoProvider), new CommitInfo( @@ -60,23 +67,23 @@ private static String getCommitMessage(String messageSubject, String messageBody @Override public CIInfo buildCIInfo() { final String url = - buildPipelineUrl(System.getenv(APPVEYOR_REPO_NAME), System.getenv(APPVEYOR_BUILD_ID)); - return CIInfo.builder() + buildPipelineUrl(environment.get(APPVEYOR_REPO_NAME), environment.get(APPVEYOR_BUILD_ID)); + return CIInfo.builder(environment) .ciProviderName(APPVEYOR_PROVIDER_NAME) - .ciPipelineId(System.getenv(APPVEYOR_BUILD_ID)) - .ciPipelineName(System.getenv(APPVEYOR_REPO_NAME)) - .ciPipelineNumber(System.getenv(APPVEYOR_PIPELINE_NUMBER)) + .ciPipelineId(environment.get(APPVEYOR_BUILD_ID)) + .ciPipelineName(environment.get(APPVEYOR_REPO_NAME)) + .ciPipelineNumber(environment.get(APPVEYOR_PIPELINE_NUMBER)) .ciPipelineUrl(url) .ciJobUrl(url) - .ciWorkspace(expandTilde(System.getenv(APPVEYOR_WORKSPACE_PATH))) + .ciWorkspace(expandTilde(environment.get(APPVEYOR_WORKSPACE_PATH))) .build(); } private String buildGitBranch(final String repoProvider) { if ("github".equals(repoProvider)) { - String branch = System.getenv(APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH); + String branch = environment.get(APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH); if (branch == null || branch.isEmpty()) { - branch = System.getenv(APPVEYOR_REPO_BRANCH); + branch = environment.get(APPVEYOR_REPO_BRANCH); } return normalizeBranch(branch); } @@ -85,14 +92,14 @@ private String buildGitBranch(final String repoProvider) { private String buildGitTag(final String repoProvider) { if ("github".equals(repoProvider)) { - return normalizeTag(System.getenv(APPVEYOR_REPO_TAG_NAME)); + return normalizeTag(environment.get(APPVEYOR_REPO_TAG_NAME)); } return null; } private String buildGitCommit() { - if ("github".equals(System.getenv(APPVEYOR_REPO_PROVIDER))) { - return System.getenv(APPVEYOR_REPO_COMMIT); + if ("github".equals(environment.get(APPVEYOR_REPO_PROVIDER))) { + return environment.get(APPVEYOR_REPO_COMMIT); } return null; } @@ -110,8 +117,8 @@ private String buildPipelineUrl(final String repoName, final String buildId) { private PersonInfo buildGitCommitAuthor() { return new PersonInfo( - System.getenv(APPVEYOR_REPO_COMMIT_AUTHOR_NAME), - System.getenv(APPVEYOR_REPO_COMMIT_AUTHOR_EMAIL)); + environment.get(APPVEYOR_REPO_COMMIT_AUTHOR_NAME), + environment.get(APPVEYOR_REPO_COMMIT_AUTHOR_EMAIL)); } @Override diff --git a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/AwsCodePipelineInfo.java b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/AwsCodePipelineInfo.java index fcae8d11248..72d672e0528 100644 --- a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/AwsCodePipelineInfo.java +++ b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/AwsCodePipelineInfo.java @@ -2,6 +2,7 @@ import datadog.trace.api.civisibility.telemetry.tag.Provider; import datadog.trace.api.git.GitInfo; +import datadog.trace.civisibility.ci.env.CiEnvironment; class AwsCodePipelineInfo implements CIProviderInfo { @@ -11,6 +12,12 @@ class AwsCodePipelineInfo implements CIProviderInfo { public static final String AWS_CODEPIPELINE_ACTION_EXECUTION_ID = "DD_ACTION_EXECUTION_ID"; public static final String AWS_CODEPIPELINE_ARN = "CODEBUILD_BUILD_ARN"; + private final CiEnvironment environment; + + AwsCodePipelineInfo(CiEnvironment environment) { + this.environment = environment; + } + @Override public GitInfo buildCIGitInfo() { return GitInfo.NOOP; @@ -18,9 +25,9 @@ public GitInfo buildCIGitInfo() { @Override public CIInfo buildCIInfo() { - return CIInfo.builder() + return CIInfo.builder(environment) .ciProviderName(AWS_CODEPIPELINE_PROVIDER_NAME) - .ciPipelineId(System.getenv(AWS_CODEPIPELINE_EXECUTION_ID)) + .ciPipelineId(environment.get(AWS_CODEPIPELINE_EXECUTION_ID)) .ciEnvVars( AWS_CODEPIPELINE_EXECUTION_ID, AWS_CODEPIPELINE_ACTION_EXECUTION_ID, diff --git a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/AzurePipelinesInfo.java b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/AzurePipelinesInfo.java index 65cabf1d603..708a6bea6be 100644 --- a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/AzurePipelinesInfo.java +++ b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/AzurePipelinesInfo.java @@ -10,6 +10,7 @@ import datadog.trace.api.git.CommitInfo; import datadog.trace.api.git.GitInfo; import datadog.trace.api.git.PersonInfo; +import datadog.trace.civisibility.ci.env.CiEnvironment; class AzurePipelinesInfo implements CIProviderInfo { @@ -39,6 +40,12 @@ class AzurePipelinesInfo implements CIProviderInfo { public static final String AZURE_BUILD_REQUESTED_FOR_ID = "BUILD_REQUESTEDFORID"; public static final String AZURE_BUILD_REQUESTED_FOR_EMAIL = "BUILD_REQUESTEDFOREMAIL"; + private final CiEnvironment environment; + + AzurePipelinesInfo(CiEnvironment environment) { + this.environment = environment; + } + @Override public GitInfo buildCIGitInfo() { return new GitInfo( @@ -49,27 +56,27 @@ public GitInfo buildCIGitInfo() { buildGitCommit(), buildGitCommitAuthor(), PersonInfo.NOOP, - System.getenv(AZURE_BUILD_SOURCEVERSION_MESSAGE))); + environment.get(AZURE_BUILD_SOURCEVERSION_MESSAGE))); } @Override public CIInfo buildCIInfo() { - final String uri = System.getenv(AZURE_SYSTEM_TEAMFOUNDATIONSERVERURI); - final String project = System.getenv(AZURE_SYSTEM_TEAMPROJECTID); - final String buildId = System.getenv(AZURE_BUILD_BUILDID); - final String jobId = System.getenv(AZURE_SYSTEM_JOBID); - final String taskId = System.getenv(AZURE_SYSTEM_TASKINSTANCEID); + final String uri = environment.get(AZURE_SYSTEM_TEAMFOUNDATIONSERVERURI); + final String project = environment.get(AZURE_SYSTEM_TEAMPROJECTID); + final String buildId = environment.get(AZURE_BUILD_BUILDID); + final String jobId = environment.get(AZURE_SYSTEM_JOBID); + final String taskId = environment.get(AZURE_SYSTEM_TASKINSTANCEID); - return CIInfo.builder() + return CIInfo.builder(environment) .ciProviderName(AZURE_PROVIDER_NAME) - .ciPipelineId(System.getenv(AZURE_BUILD_BUILDID)) - .ciPipelineName(System.getenv(AZURE_PIPELINE_NAME)) + .ciPipelineId(environment.get(AZURE_BUILD_BUILDID)) + .ciPipelineName(environment.get(AZURE_PIPELINE_NAME)) .ciPipelineNumber(buildId) .ciPipelineUrl(buildCiPipelineUrl(uri, project, buildId)) - .ciStageName(System.getenv(AZURE_SYSTEM_STAGEDISPLAYNAME)) - .ciJobName(System.getenv(AZURE_SYSTEM_JOBDISPLAYNAME)) + .ciStageName(environment.get(AZURE_SYSTEM_STAGEDISPLAYNAME)) + .ciJobName(environment.get(AZURE_SYSTEM_JOBDISPLAYNAME)) .ciJobUrl(buildCiJobUrl(uri, project, buildId, jobId, taskId)) - .ciWorkspace(expandTilde(System.getenv(AZURE_WORKSPACE_PATH))) + .ciWorkspace(expandTilde(environment.get(AZURE_WORKSPACE_PATH))) .ciEnvVars(AZURE_SYSTEM_TEAMPROJECTID, AZURE_BUILD_BUILDID, AZURE_SYSTEM_JOBID) .build(); } @@ -92,26 +99,26 @@ private String buildGitTag() { } } - private static String getGitBranchOrTag() { - String gitBranchOrTag = System.getenv(AZURE_SYSTEM_PULLREQUEST_SOURCEBRANCH); + private String getGitBranchOrTag() { + String gitBranchOrTag = environment.get(AZURE_SYSTEM_PULLREQUEST_SOURCEBRANCH); if (gitBranchOrTag == null || gitBranchOrTag.isEmpty()) { - gitBranchOrTag = System.getenv(AZURE_BUILD_SOURCEBRANCH); + gitBranchOrTag = environment.get(AZURE_BUILD_SOURCEBRANCH); } return gitBranchOrTag; } private String buildGitCommit() { - String commit = System.getenv(AZURE_SYSTEM_PULLREQUEST_SOURCECOMMITID); + String commit = environment.get(AZURE_SYSTEM_PULLREQUEST_SOURCECOMMITID); if (commit == null || commit.isEmpty()) { - commit = System.getenv(AZURE_BUILD_SOURCEVERSION); + commit = environment.get(AZURE_BUILD_SOURCEVERSION); } return commit; } private String buildGitRepositoryUrl() { - String repoUrl = System.getenv(AZURE_SYSTEM_PULLREQUEST_SOURCEREPOSITORYURI); + String repoUrl = environment.get(AZURE_SYSTEM_PULLREQUEST_SOURCEREPOSITORYURI); if (repoUrl == null || repoUrl.isEmpty()) { - repoUrl = System.getenv(AZURE_BUILD_REPOSITORY_URI); + repoUrl = environment.get(AZURE_BUILD_REPOSITORY_URI); } return filterSensitiveInfo(repoUrl); } @@ -132,8 +139,8 @@ private String buildCiPipelineUrl(final String uri, final String project, final private PersonInfo buildGitCommitAuthor() { return new PersonInfo( - System.getenv(AZURE_BUILD_REQUESTED_FOR_ID), - System.getenv(AZURE_BUILD_REQUESTED_FOR_EMAIL)); + environment.get(AZURE_BUILD_REQUESTED_FOR_ID), + environment.get(AZURE_BUILD_REQUESTED_FOR_EMAIL)); } @Override diff --git a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/BitBucketInfo.java b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/BitBucketInfo.java index 80c1e705dc5..63b9eace1e5 100644 --- a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/BitBucketInfo.java +++ b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/BitBucketInfo.java @@ -8,6 +8,7 @@ import datadog.trace.api.civisibility.telemetry.tag.Provider; import datadog.trace.api.git.CommitInfo; import datadog.trace.api.git.GitInfo; +import datadog.trace.civisibility.ci.env.CiEnvironment; import datadog.trace.util.Strings; class BitBucketInfo implements CIProviderInfo { @@ -25,21 +26,27 @@ class BitBucketInfo implements CIProviderInfo { public static final String BITBUCKET_GIT_BRANCH = "BITBUCKET_BRANCH"; public static final String BITBUCKET_GIT_TAG = "BITBUCKET_TAG"; + private final CiEnvironment environment; + + BitBucketInfo(CiEnvironment environment) { + this.environment = environment; + } + @Override public GitInfo buildCIGitInfo() { return new GitInfo( getRepositoryURL(), - normalizeBranch(System.getenv(BITBUCKET_GIT_BRANCH)), - normalizeTag(System.getenv(BITBUCKET_GIT_TAG)), - new CommitInfo(System.getenv(BITBUCKET_GIT_COMMIT))); + normalizeBranch(environment.get(BITBUCKET_GIT_BRANCH)), + normalizeTag(environment.get(BITBUCKET_GIT_TAG)), + new CommitInfo(environment.get(BITBUCKET_GIT_COMMIT))); } - private static String getRepositoryURL() { - String gitRepoUrl = System.getenv(BITBUCKET_GIT_REPOSITORY_URL); + private String getRepositoryURL() { + String gitRepoUrl = environment.get(BITBUCKET_GIT_REPOSITORY_URL); if (Strings.isNotBlank(gitRepoUrl)) { return filterSensitiveInfo(gitRepoUrl); } - String httpsRepoUrl = System.getenv(BITBUCKET_HTTPS_REPOSITORY_URL); + String httpsRepoUrl = environment.get(BITBUCKET_HTTPS_REPOSITORY_URL); if (Strings.isNotBlank(httpsRepoUrl)) { return filterSensitiveInfo(httpsRepoUrl); } @@ -48,18 +55,18 @@ private static String getRepositoryURL() { @Override public CIInfo buildCIInfo() { - final String repo = System.getenv(BITBUCKET_REPO_FULL_NAME); - final String number = System.getenv(BITBUCKET_BUILD_NUMBER); + final String repo = environment.get(BITBUCKET_REPO_FULL_NAME); + final String number = environment.get(BITBUCKET_BUILD_NUMBER); final String url = buildPipelineUrl(repo, number); - return CIInfo.builder() + return CIInfo.builder(environment) .ciProviderName(BITBUCKET_PROVIDER_NAME) .ciPipelineId(buildPipelineId()) .ciPipelineName(repo) .ciPipelineNumber(number) .ciPipelineUrl(url) .ciJobUrl(url) - .ciWorkspace(expandTilde(System.getenv(BITBUCKET_WORKSPACE_PATH))) + .ciWorkspace(expandTilde(environment.get(BITBUCKET_WORKSPACE_PATH))) .build(); } @@ -69,7 +76,7 @@ private String buildPipelineUrl(final String repo, final String number) { } private String buildPipelineId() { - String id = System.getenv(BITBUCKET_PIPELINE_ID); + String id = environment.get(BITBUCKET_PIPELINE_ID); if (id != null) { id = Strings.replace(id, "{", ""); id = Strings.replace(id, "}", ""); diff --git a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/BitriseInfo.java b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/BitriseInfo.java index 7428fe5ff24..b5af995835a 100644 --- a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/BitriseInfo.java +++ b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/BitriseInfo.java @@ -9,6 +9,7 @@ import datadog.trace.api.git.CommitInfo; import datadog.trace.api.git.GitInfo; import datadog.trace.api.git.PersonInfo; +import datadog.trace.civisibility.ci.env.CiEnvironment; class BitriseInfo implements CIProviderInfo { @@ -30,40 +31,47 @@ class BitriseInfo implements CIProviderInfo { public static final String BITRISE_GIT_COMMITER_NAME = "GIT_CLONE_COMMIT_COMMITER_NAME"; public static final String BITRISE_GIT_COMMITER_EMAIL = "GIT_CLONE_COMMIT_COMMITER_EMAIL"; + private final CiEnvironment environment; + + BitriseInfo(CiEnvironment environment) { + this.environment = environment; + } + @Override public GitInfo buildCIGitInfo() { return new GitInfo( - filterSensitiveInfo(System.getenv(BITRISE_GIT_REPOSITORY_URL)), - normalizeBranch(System.getenv(BITRISE_GIT_BRANCH)), - normalizeTag(System.getenv(BITRISE_GIT_TAG)), + filterSensitiveInfo(environment.get(BITRISE_GIT_REPOSITORY_URL)), + normalizeBranch(environment.get(BITRISE_GIT_BRANCH)), + normalizeTag(environment.get(BITRISE_GIT_TAG)), new CommitInfo( buildGitCommit(), new PersonInfo( - System.getenv(BITRISE_GIT_AUTHOR_NAME), System.getenv(BITRISE_GIT_AUTHOR_EMAIL)), + environment.get(BITRISE_GIT_AUTHOR_NAME), + environment.get(BITRISE_GIT_AUTHOR_EMAIL)), new PersonInfo( - System.getenv(BITRISE_GIT_COMMITER_NAME), - System.getenv(BITRISE_GIT_COMMITER_EMAIL)), - System.getenv(BITRISE_GIT_MESSAGE))); + environment.get(BITRISE_GIT_COMMITER_NAME), + environment.get(BITRISE_GIT_COMMITER_EMAIL)), + environment.get(BITRISE_GIT_MESSAGE))); } @Override public CIInfo buildCIInfo() { - return CIInfo.builder() + return CIInfo.builder(environment) .ciProviderName(BITRISE_PROVIDER_NAME) - .ciPipelineId(System.getenv(BITRISE_PIPELINE_ID)) - .ciPipelineName(System.getenv(BITRISE_PIPELINE_NAME)) - .ciPipelineNumber(System.getenv(BITRISE_PIPELINE_NUMBER)) - .ciPipelineUrl(System.getenv(BITRISE_PIPELINE_URL)) - .ciWorkspace(expandTilde(System.getenv(BITRISE_WORKSPACE_PATH))) + .ciPipelineId(environment.get(BITRISE_PIPELINE_ID)) + .ciPipelineName(environment.get(BITRISE_PIPELINE_NAME)) + .ciPipelineNumber(environment.get(BITRISE_PIPELINE_NUMBER)) + .ciPipelineUrl(environment.get(BITRISE_PIPELINE_URL)) + .ciWorkspace(expandTilde(environment.get(BITRISE_WORKSPACE_PATH))) .build(); } private String buildGitCommit() { - final String fromCommit = System.getenv(BITRISE_GIT_PR_COMMIT); + final String fromCommit = environment.get(BITRISE_GIT_PR_COMMIT); if (fromCommit != null && !fromCommit.isEmpty()) { return fromCommit; } else { - return System.getenv(BITRISE_GIT_COMMIT); + return environment.get(BITRISE_GIT_COMMIT); } } diff --git a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/BuddyInfo.java b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/BuddyInfo.java index 2315f806f2f..8118c9c22c8 100644 --- a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/BuddyInfo.java +++ b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/BuddyInfo.java @@ -8,6 +8,7 @@ import datadog.trace.api.git.CommitInfo; import datadog.trace.api.git.GitInfo; import datadog.trace.api.git.PersonInfo; +import datadog.trace.civisibility.ci.env.CiEnvironment; class BuddyInfo implements CIProviderInfo { @@ -26,33 +27,39 @@ class BuddyInfo implements CIProviderInfo { public static final String BUDDY_GIT_COMMIT_AUTHOR = "BUDDY_EXECUTION_REVISION_COMMITTER_NAME"; public static final String BUDDY_GIT_COMMIT_EMAIL = "BUDDY_EXECUTION_REVISION_COMMITTER_EMAIL"; + private final CiEnvironment environment; + + BuddyInfo(CiEnvironment environment) { + this.environment = environment; + } + @Override public GitInfo buildCIGitInfo() { return new GitInfo( - filterSensitiveInfo(System.getenv(BUDDY_GIT_REPOSITORY_URL)), - normalizeBranch(System.getenv(BUDDY_GIT_BRANCH)), - normalizeTag(System.getenv(BUDDY_GIT_TAG)), + filterSensitiveInfo(environment.get(BUDDY_GIT_REPOSITORY_URL)), + normalizeBranch(environment.get(BUDDY_GIT_BRANCH)), + normalizeTag(environment.get(BUDDY_GIT_TAG)), new CommitInfo( - System.getenv(BUDDY_GIT_COMMIT), + environment.get(BUDDY_GIT_COMMIT), PersonInfo.NOOP, buildGitCommiter(), - System.getenv(BUDDY_GIT_COMMIT_MESSAGE))); + environment.get(BUDDY_GIT_COMMIT_MESSAGE))); } @Override public CIInfo buildCIInfo() { - String pipelineNumber = System.getenv(BUDDY_PIPELINE_EXECUTION_ID); - return CIInfo.builder() + String pipelineNumber = environment.get(BUDDY_PIPELINE_EXECUTION_ID); + return CIInfo.builder(environment) .ciProviderName(BUDDY_PROVIDER_NAME) .ciPipelineId(getPipelineId(pipelineNumber)) - .ciPipelineName(System.getenv(BUDDY_PIPELINE_NAME)) + .ciPipelineName(environment.get(BUDDY_PIPELINE_NAME)) .ciPipelineNumber(pipelineNumber) - .ciPipelineUrl(System.getenv(BUDDY_PIPELINE_EXECUTION_URL)) + .ciPipelineUrl(environment.get(BUDDY_PIPELINE_EXECUTION_URL)) .build(); } - private static String getPipelineId(String pipelineNumber) { - String pipelineId = System.getenv(BUDDY_PIPELINE_ID); + private String getPipelineId(String pipelineNumber) { + String pipelineId = environment.get(BUDDY_PIPELINE_ID); if (pipelineId == null) { return pipelineNumber; } @@ -64,7 +71,7 @@ private static String getPipelineId(String pipelineNumber) { private PersonInfo buildGitCommiter() { return new PersonInfo( - System.getenv(BUDDY_GIT_COMMIT_AUTHOR), System.getenv(BUDDY_GIT_COMMIT_EMAIL)); + environment.get(BUDDY_GIT_COMMIT_AUTHOR), environment.get(BUDDY_GIT_COMMIT_EMAIL)); } @Override diff --git a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/BuildkiteInfo.java b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/BuildkiteInfo.java index 72ba40ee611..4aa2a6781b9 100644 --- a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/BuildkiteInfo.java +++ b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/BuildkiteInfo.java @@ -10,6 +10,7 @@ import datadog.trace.api.git.CommitInfo; import datadog.trace.api.git.GitInfo; import datadog.trace.api.git.PersonInfo; +import datadog.trace.civisibility.ci.env.CiEnvironment; import java.util.ArrayList; import java.util.List; import java.util.Locale; @@ -36,32 +37,38 @@ class BuildkiteInfo implements CIProviderInfo { public static final String BUILDKITE_AGENT_ID = "BUILDKITE_AGENT_ID"; private static final String BUILDKITE_CI_NODE_LABEL_PREFIX = "BUILDKITE_AGENT_META_DATA_"; + private final CiEnvironment environment; + + BuildkiteInfo(CiEnvironment environment) { + this.environment = environment; + } + @Override public GitInfo buildCIGitInfo() { return new GitInfo( - filterSensitiveInfo(System.getenv(BUILDKITE_GIT_REPOSITORY_URL)), - normalizeBranch(System.getenv(BUILDKITE_GIT_BRANCH)), - normalizeTag(System.getenv(BUILDKITE_GIT_TAG)), + filterSensitiveInfo(environment.get(BUILDKITE_GIT_REPOSITORY_URL)), + normalizeBranch(environment.get(BUILDKITE_GIT_BRANCH)), + normalizeTag(environment.get(BUILDKITE_GIT_TAG)), new CommitInfo( - System.getenv(BUILDKITE_GIT_COMMIT), + environment.get(BUILDKITE_GIT_COMMIT), buildGitCommitAuthor(), PersonInfo.NOOP, - System.getenv(BUILDKITE_GIT_MESSAGE))); + environment.get(BUILDKITE_GIT_MESSAGE))); } @Override public CIInfo buildCIInfo() { - final String ciPipelineUrl = System.getenv(BUILDKITE_BUILD_URL); + final String ciPipelineUrl = environment.get(BUILDKITE_BUILD_URL); - return CIInfo.builder() + return CIInfo.builder(environment) .ciProviderName(BUILDKITE_PROVIDER_NAME) - .ciPipelineId(System.getenv(BUILDKITE_PIPELINE_ID)) - .ciPipelineName(System.getenv(BUILDKITE_PIPELINE_NAME)) - .ciPipelineNumber(System.getenv(BUILDKITE_PIPELINE_NUMBER)) + .ciPipelineId(environment.get(BUILDKITE_PIPELINE_ID)) + .ciPipelineName(environment.get(BUILDKITE_PIPELINE_NAME)) + .ciPipelineNumber(environment.get(BUILDKITE_PIPELINE_NUMBER)) .ciPipelineUrl(ciPipelineUrl) - .ciJobUrl(String.format("%s#%s", ciPipelineUrl, System.getenv(BUILDKITE_JOB_ID))) - .ciWorkspace(expandTilde(System.getenv(BUILDKITE_WORKSPACE_PATH))) - .ciNodeName(System.getenv(BUILDKITE_AGENT_ID)) + .ciJobUrl(String.format("%s#%s", ciPipelineUrl, environment.get(BUILDKITE_JOB_ID))) + .ciWorkspace(expandTilde(environment.get(BUILDKITE_WORKSPACE_PATH))) + .ciNodeName(environment.get(BUILDKITE_AGENT_ID)) .ciNodeLabels(buildCiNodeLabels()) .ciEnvVars(BUILDKITE_PIPELINE_ID, BUILDKITE_JOB_ID) .build(); @@ -69,7 +76,7 @@ public CIInfo buildCIInfo() { private String buildCiNodeLabels() { List labels = new ArrayList<>(); - for (Map.Entry e : System.getenv().entrySet()) { + for (Map.Entry e : environment.get().entrySet()) { String envVar = e.getKey(); if (envVar.startsWith(BUILDKITE_CI_NODE_LABEL_PREFIX)) { String labelKey = @@ -83,7 +90,7 @@ private String buildCiNodeLabels() { private PersonInfo buildGitCommitAuthor() { return new PersonInfo( - System.getenv(BUILDKITE_GIT_AUTHOR_NAME), System.getenv(BUILDKITE_GIT_AUTHOR_EMAIL)); + environment.get(BUILDKITE_GIT_AUTHOR_NAME), environment.get(BUILDKITE_GIT_AUTHOR_EMAIL)); } @Override diff --git a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/CIInfo.java b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/CIInfo.java index 3c7ffc31825..9fb2bbfb81f 100644 --- a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/CIInfo.java +++ b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/CIInfo.java @@ -2,6 +2,7 @@ import static datadog.trace.api.git.GitUtils.filterSensitiveInfo; +import datadog.trace.civisibility.ci.env.CiEnvironment; import datadog.trace.civisibility.utils.FileUtils; import java.io.File; import java.util.HashMap; @@ -11,11 +12,13 @@ public class CIInfo { public static final CIInfo NOOP = new CIInfo(); - public static Builder builder() { - return new Builder(); + public static Builder builder(CiEnvironment environment) { + return new Builder(environment); } public static final class Builder { + private final CiEnvironment environment; + private String ciProviderName; private String ciPipelineId; private String ciPipelineName; @@ -30,6 +33,10 @@ public static final class Builder { private Map ciEnvVars; private Map additionalTags; + public Builder(CiEnvironment environment) { + this.environment = environment; + } + public Builder ciProviderName(String ciProviderName) { this.ciProviderName = ciProviderName; return this; @@ -92,7 +99,7 @@ public Builder ciEnvVars(String... ciEnvVarKeysArray) { ciEnvVars = new HashMap<>(); for (String ciEnvVarKey : ciEnvVarKeysArray) { - final String envVarVal = filterSensitiveInfo(System.getenv(ciEnvVarKey)); + final String envVarVal = filterSensitiveInfo(environment.get(ciEnvVarKey)); if (envVarVal != null && !envVarVal.isEmpty()) { ciEnvVars.put(ciEnvVarKey, envVarVal); } diff --git a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/CIProviderInfoFactory.java b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/CIProviderInfoFactory.java index 37a651678b7..df6dd218a88 100644 --- a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/CIProviderInfoFactory.java +++ b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/CIProviderInfoFactory.java @@ -1,61 +1,64 @@ package datadog.trace.civisibility.ci; import datadog.trace.api.Config; +import datadog.trace.civisibility.ci.env.CiEnvironment; import java.nio.file.Path; public class CIProviderInfoFactory { private final String targetFolder; private final Config config; + private final CiEnvironment environment; - public CIProviderInfoFactory(Config config) { - this(config, ".git"); + public CIProviderInfoFactory(Config config, CiEnvironment environment) { + this(config, ".git", environment); } - CIProviderInfoFactory(Config config, String targetFolder) { + CIProviderInfoFactory(Config config, String targetFolder, CiEnvironment environment) { this.targetFolder = targetFolder; this.config = config; + this.environment = environment; } public CIProviderInfo createCIProviderInfo(Path currentPath) { if (!config.isCiVisibilityCiProviderIntegrationEnabled()) { - return new UnknownCIInfo(targetFolder, currentPath); + return new UnknownCIInfo(environment, targetFolder, currentPath); } // CI and Git information is obtained // from different environment variables // depending on which CI server is running the build. - if (System.getenv(JenkinsInfo.JENKINS) != null) { - return new JenkinsInfo(); - } else if (System.getenv(GitLabInfo.GITLAB) != null) { - return new GitLabInfo(); - } else if (System.getenv(TravisInfo.TRAVIS) != null) { - return new TravisInfo(); - } else if (System.getenv(CircleCIInfo.CIRCLECI) != null) { - return new CircleCIInfo(); - } else if (System.getenv(AppVeyorInfo.APPVEYOR) != null) { - return new AppVeyorInfo(); - } else if (System.getenv(AzurePipelinesInfo.AZURE) != null) { - return new AzurePipelinesInfo(); - } else if (System.getenv(BitBucketInfo.BITBUCKET) != null) { - return new BitBucketInfo(); - } else if (System.getenv(GithubActionsInfo.GHACTIONS) != null) { - return new GithubActionsInfo(); - } else if (System.getenv(BuildkiteInfo.BUILDKITE) != null) { - return new BuildkiteInfo(); - } else if (System.getenv(BitriseInfo.BITRISE) != null) { - return new BitriseInfo(); - } else if (System.getenv(BuddyInfo.BUDDY) != null) { - return new BuddyInfo(); - } else if (System.getenv(CodefreshInfo.CODEFRESH) != null) { - return new CodefreshInfo(); - } else if (System.getenv(TeamcityInfo.TEAMCITY) != null) { - return new TeamcityInfo(); - } else if (System.getenv(AwsCodePipelineInfo.AWS_CODEPIPELINE) != null - && System.getenv(AwsCodePipelineInfo.AWS_CODEPIPELINE).startsWith("codepipeline")) { - return new AwsCodePipelineInfo(); + if (environment.get(JenkinsInfo.JENKINS) != null) { + return new JenkinsInfo(environment); + } else if (environment.get(GitLabInfo.GITLAB) != null) { + return new GitLabInfo(environment); + } else if (environment.get(TravisInfo.TRAVIS) != null) { + return new TravisInfo(environment); + } else if (environment.get(CircleCIInfo.CIRCLECI) != null) { + return new CircleCIInfo(environment); + } else if (environment.get(AppVeyorInfo.APPVEYOR) != null) { + return new AppVeyorInfo(environment); + } else if (environment.get(AzurePipelinesInfo.AZURE) != null) { + return new AzurePipelinesInfo(environment); + } else if (environment.get(BitBucketInfo.BITBUCKET) != null) { + return new BitBucketInfo(environment); + } else if (environment.get(GithubActionsInfo.GHACTIONS) != null) { + return new GithubActionsInfo(environment); + } else if (environment.get(BuildkiteInfo.BUILDKITE) != null) { + return new BuildkiteInfo(environment); + } else if (environment.get(BitriseInfo.BITRISE) != null) { + return new BitriseInfo(environment); + } else if (environment.get(BuddyInfo.BUDDY) != null) { + return new BuddyInfo(environment); + } else if (environment.get(CodefreshInfo.CODEFRESH) != null) { + return new CodefreshInfo(environment); + } else if (environment.get(TeamcityInfo.TEAMCITY) != null) { + return new TeamcityInfo(environment); + } else if (environment.get(AwsCodePipelineInfo.AWS_CODEPIPELINE) != null + && environment.get(AwsCodePipelineInfo.AWS_CODEPIPELINE).startsWith("codepipeline")) { + return new AwsCodePipelineInfo(environment); } else { - return new UnknownCIInfo(targetFolder, currentPath); + return new UnknownCIInfo(environment, targetFolder, currentPath); } } } diff --git a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/CircleCIInfo.java b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/CircleCIInfo.java index 690bcac6f38..f18fab7c949 100644 --- a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/CircleCIInfo.java +++ b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/CircleCIInfo.java @@ -8,6 +8,7 @@ import datadog.trace.api.civisibility.telemetry.tag.Provider; import datadog.trace.api.git.CommitInfo; import datadog.trace.api.git.GitInfo; +import datadog.trace.civisibility.ci.env.CiEnvironment; class CircleCIInfo implements CIProviderInfo { @@ -25,26 +26,32 @@ class CircleCIInfo implements CIProviderInfo { public static final String CIRCLECI_GIT_TAG = "CIRCLE_TAG"; public static final String CIRCLECI_JOB_NAME = "CIRCLE_JOB"; + private final CiEnvironment environment; + + CircleCIInfo(CiEnvironment environment) { + this.environment = environment; + } + @Override public GitInfo buildCIGitInfo() { return new GitInfo( - filterSensitiveInfo(System.getenv(CIRCLECI_GIT_REPOSITORY_URL)), - normalizeBranch(System.getenv(CIRCLECI_GIT_BRANCH)), - normalizeTag(System.getenv(CIRCLECI_GIT_TAG)), - new CommitInfo(System.getenv(CIRCLECI_GIT_COMMIT))); + filterSensitiveInfo(environment.get(CIRCLECI_GIT_REPOSITORY_URL)), + normalizeBranch(environment.get(CIRCLECI_GIT_BRANCH)), + normalizeTag(environment.get(CIRCLECI_GIT_TAG)), + new CommitInfo(environment.get(CIRCLECI_GIT_COMMIT))); } @Override public CIInfo buildCIInfo() { - final String pipelineId = System.getenv(CIRCLECI_PIPELINE_ID); - return CIInfo.builder() + final String pipelineId = environment.get(CIRCLECI_PIPELINE_ID); + return CIInfo.builder(environment) .ciProviderName(CIRCLECI_PROVIDER_NAME) .ciPipelineId(pipelineId) - .ciPipelineName(System.getenv(CIRCLECI_PIPELINE_NAME)) + .ciPipelineName(environment.get(CIRCLECI_PIPELINE_NAME)) .ciPipelineUrl(buildPipelineUrl(pipelineId)) - .ciJobName(System.getenv(CIRCLECI_JOB_NAME)) - .ciJobUrl(System.getenv(CIRCLECI_BUILD_URL)) - .ciWorkspace(expandTilde(System.getenv(CIRCLECI_WORKSPACE_PATH))) + .ciJobName(environment.get(CIRCLECI_JOB_NAME)) + .ciJobUrl(environment.get(CIRCLECI_BUILD_URL)) + .ciWorkspace(expandTilde(environment.get(CIRCLECI_WORKSPACE_PATH))) .ciEnvVars(CIRCLECI_PIPELINE_ID, CIRCLECI_BUILD_NUM) .build(); } diff --git a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/CodefreshInfo.java b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/CodefreshInfo.java index a639ff53ca9..5dcdbe1abcb 100644 --- a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/CodefreshInfo.java +++ b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/CodefreshInfo.java @@ -8,6 +8,7 @@ import datadog.trace.api.git.CommitInfo; import datadog.trace.api.git.GitInfo; import datadog.trace.api.git.PersonInfo; +import datadog.trace.civisibility.ci.env.CiEnvironment; public class CodefreshInfo implements CIProviderInfo { public static final String CODEFRESH = "CF_BUILD_ID"; @@ -20,6 +21,12 @@ public class CodefreshInfo implements CIProviderInfo { private static final String CF_COMMIT_MESSAGE = "CF_COMMIT_MESSAGE"; private static final String CF_COMMIT_AUTHOR = "CF_COMMIT_AUTHOR"; + private final CiEnvironment environment; + + CodefreshInfo(CiEnvironment environment) { + this.environment = environment; + } + @Override public GitInfo buildCIGitInfo() { return new GitInfo( @@ -27,10 +34,10 @@ public GitInfo buildCIGitInfo() { buildGitBranch(), buildGitTag(), new CommitInfo( - System.getenv(CF_REVISION), - new PersonInfo(System.getenv(CF_COMMIT_AUTHOR), null), + environment.get(CF_REVISION), + new PersonInfo(environment.get(CF_COMMIT_AUTHOR), null), PersonInfo.NOOP, - System.getenv(CF_COMMIT_MESSAGE))); + environment.get(CF_COMMIT_MESSAGE))); } private String buildGitBranch() { @@ -51,18 +58,18 @@ private String buildGitTag() { } } - private static String getGitBranchOrTag() { - return System.getenv(CF_BRANCH); + private String getGitBranchOrTag() { + return environment.get(CF_BRANCH); } @Override public CIInfo buildCIInfo() { - return CIInfo.builder() + return CIInfo.builder(environment) .ciProviderName(CODEFRESH_PROVIDER_NAME) - .ciPipelineId(System.getenv(CODEFRESH)) - .ciPipelineName(System.getenv(CF_PIPELINE_NAME)) - .ciPipelineUrl(System.getenv(CF_BUILD_URL)) - .ciJobName(System.getenv(CF_STEP_NAME)) + .ciPipelineId(environment.get(CODEFRESH)) + .ciPipelineName(environment.get(CF_PIPELINE_NAME)) + .ciPipelineUrl(environment.get(CF_BUILD_URL)) + .ciJobName(environment.get(CF_STEP_NAME)) .ciEnvVars(CODEFRESH) .build(); } diff --git a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/GitLabInfo.java b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/GitLabInfo.java index ba31b498ef7..ce99e955371 100644 --- a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/GitLabInfo.java +++ b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/GitLabInfo.java @@ -10,6 +10,7 @@ import datadog.trace.api.git.GitInfo; import datadog.trace.api.git.GitUtils; import datadog.trace.api.git.PersonInfo; +import datadog.trace.civisibility.ci.env.CiEnvironment; import de.thetaphi.forbiddenapis.SuppressForbidden; @SuppressForbidden @@ -38,46 +39,52 @@ class GitLabInfo implements CIProviderInfo { public static final String GITLAB_CI_RUNNER_ID = "CI_RUNNER_ID"; public static final String GITLAB_CI_RUNNER_TAGS = "CI_RUNNER_TAGS"; + private final CiEnvironment environment; + + GitLabInfo(CiEnvironment environment) { + this.environment = environment; + } + @Override public GitInfo buildCIGitInfo() { return new GitInfo( - filterSensitiveInfo(System.getenv(GITLAB_GIT_REPOSITORY_URL)), - normalizeBranch(System.getenv(GITLAB_GIT_BRANCH)), - normalizeTag(System.getenv(GITLAB_GIT_TAG)), + filterSensitiveInfo(environment.get(GITLAB_GIT_REPOSITORY_URL)), + normalizeBranch(environment.get(GITLAB_GIT_BRANCH)), + normalizeTag(environment.get(GITLAB_GIT_TAG)), new CommitInfo( - System.getenv(GITLAB_GIT_COMMIT), + environment.get(GITLAB_GIT_COMMIT), buildGitCommitAuthor(), PersonInfo.NOOP, - System.getenv(GITLAB_GIT_COMMIT_MESSAGE))); + environment.get(GITLAB_GIT_COMMIT_MESSAGE))); } @Override public CIInfo buildCIInfo() { - return CIInfo.builder() + return CIInfo.builder(environment) .ciProviderName(GITLAB_PROVIDER_NAME) - .ciPipelineId(System.getenv(GITLAB_PIPELINE_ID)) - .ciPipelineName(System.getenv(GITLAB_PIPELINE_NAME)) - .ciPipelineNumber(System.getenv(GITLAB_PIPELINE_NUMBER)) - .ciPipelineUrl(System.getenv(GITLAB_PIPELINE_URL)) - .ciStageName(System.getenv(GITLAB_STAGE_NAME)) - .ciJobName(System.getenv(GITLAB_JOB_NAME)) - .ciJobUrl(System.getenv(GITLAB_JOB_URL)) - .ciWorkspace(expandTilde(System.getenv(GITLAB_WORKSPACE_PATH))) - .ciNodeName(System.getenv(GITLAB_CI_RUNNER_ID)) - .ciNodeLabels(System.getenv(GITLAB_CI_RUNNER_TAGS)) + .ciPipelineId(environment.get(GITLAB_PIPELINE_ID)) + .ciPipelineName(environment.get(GITLAB_PIPELINE_NAME)) + .ciPipelineNumber(environment.get(GITLAB_PIPELINE_NUMBER)) + .ciPipelineUrl(environment.get(GITLAB_PIPELINE_URL)) + .ciStageName(environment.get(GITLAB_STAGE_NAME)) + .ciJobName(environment.get(GITLAB_JOB_NAME)) + .ciJobUrl(environment.get(GITLAB_JOB_URL)) + .ciWorkspace(expandTilde(environment.get(GITLAB_WORKSPACE_PATH))) + .ciNodeName(environment.get(GITLAB_CI_RUNNER_ID)) + .ciNodeLabels(environment.get(GITLAB_CI_RUNNER_TAGS)) .ciEnvVars(GITLAB_PROJECT_URL, GITLAB_PIPELINE_ID, GITLAB_JOB_ID) .build(); } private PersonInfo buildGitCommitAuthor() { - final String gitAuthor = System.getenv(GITLAB_GIT_COMMIT_AUTHOR); + final String gitAuthor = environment.get(GITLAB_GIT_COMMIT_AUTHOR); if (gitAuthor == null || gitAuthor.isEmpty()) { return PersonInfo.NOOP; } final PersonInfo personInfo = GitUtils.splitAuthorAndEmail(gitAuthor); return new PersonInfo( - personInfo.getName(), personInfo.getEmail(), System.getenv(GITLAB_GIT_COMMIT_TIMESTAMP)); + personInfo.getName(), personInfo.getEmail(), environment.get(GITLAB_GIT_COMMIT_TIMESTAMP)); } @Override diff --git a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/GithubActionsInfo.java b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/GithubActionsInfo.java index 6260c2e3070..ee38ed4aefc 100644 --- a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/GithubActionsInfo.java +++ b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/GithubActionsInfo.java @@ -12,6 +12,7 @@ import datadog.trace.api.civisibility.telemetry.tag.Provider; import datadog.trace.api.git.CommitInfo; import datadog.trace.api.git.GitInfo; +import datadog.trace.civisibility.ci.env.CiEnvironment; import datadog.trace.util.Strings; import java.nio.charset.StandardCharsets; import java.nio.file.Files; @@ -47,50 +48,57 @@ class GithubActionsInfo implements CIProviderInfo { public static final String GIT_PULL_REQUEST_BASE_BRANCH_SHA = "git.pull_request.base_branch_sha"; public static final String GIT_COMMIT_HEAD_SHA = "git.commit.head_sha"; + private final CiEnvironment environment; + + GithubActionsInfo(CiEnvironment environment) { + this.environment = environment; + } + @Override public GitInfo buildCIGitInfo() { return new GitInfo( buildGitRepositoryUrl( - filterSensitiveInfo(System.getenv(GHACTIONS_URL)), System.getenv(GHACTIONS_REPOSITORY)), + filterSensitiveInfo(environment.get(GHACTIONS_URL)), + environment.get(GHACTIONS_REPOSITORY)), buildGitBranch(), buildGitTag(), - new CommitInfo(System.getenv(GHACTIONS_SHA))); + new CommitInfo(environment.get(GHACTIONS_SHA))); } @Override public CIInfo buildCIInfo() { final String pipelineUrl = buildPipelineUrl( - filterSensitiveInfo(System.getenv(GHACTIONS_URL)), - System.getenv(GHACTIONS_REPOSITORY), - System.getenv(GHACTIONS_PIPELINE_ID), - System.getenv(GHACTIONS_PIPELINE_RETRY)); + filterSensitiveInfo(environment.get(GHACTIONS_URL)), + environment.get(GHACTIONS_REPOSITORY), + environment.get(GHACTIONS_PIPELINE_ID), + environment.get(GHACTIONS_PIPELINE_RETRY)); final String jobUrl = buildJobUrl( - filterSensitiveInfo(System.getenv(GHACTIONS_URL)), - System.getenv(GHACTIONS_REPOSITORY), - System.getenv(GHACTIONS_SHA)); + filterSensitiveInfo(environment.get(GHACTIONS_URL)), + environment.get(GHACTIONS_REPOSITORY), + environment.get(GHACTIONS_SHA)); - CIInfo.Builder builder = CIInfo.builder(); + CIInfo.Builder builder = CIInfo.builder(environment); setAdditionalTagsIfApplicable(builder); return builder .ciProviderName(GHACTIONS_PROVIDER_NAME) - .ciPipelineId(System.getenv(GHACTIONS_PIPELINE_ID)) - .ciPipelineName(System.getenv(GHACTIONS_PIPELINE_NAME)) - .ciPipelineNumber(System.getenv(GHACTIONS_PIPELINE_NUMBER)) + .ciPipelineId(environment.get(GHACTIONS_PIPELINE_ID)) + .ciPipelineName(environment.get(GHACTIONS_PIPELINE_NAME)) + .ciPipelineNumber(environment.get(GHACTIONS_PIPELINE_NUMBER)) .ciPipelineUrl(pipelineUrl) - .ciJobName(System.getenv(GHACTIONS_JOB)) + .ciJobName(environment.get(GHACTIONS_JOB)) .ciJobUrl(jobUrl) - .ciWorkspace(expandTilde(System.getenv(GHACTIONS_WORKSPACE_PATH))) + .ciWorkspace(expandTilde(environment.get(GHACTIONS_WORKSPACE_PATH))) .ciEnvVars( GHACTIONS_URL, GHACTIONS_REPOSITORY, GHACTIONS_PIPELINE_ID, GHACTIONS_PIPELINE_RETRY) .build(); } - private static void setAdditionalTagsIfApplicable(CIInfo.Builder builder) { - String baseRef = System.getenv(GITHUB_BASE_REF); + private void setAdditionalTagsIfApplicable(CIInfo.Builder builder) { + String baseRef = environment.get(GITHUB_BASE_REF); if (!Strings.isNotBlank(baseRef)) { return; } @@ -99,7 +107,7 @@ private static void setAdditionalTagsIfApplicable(CIInfo.Builder builder) { Map additionalTags = new HashMap<>(); additionalTags.put(GIT_PULL_REQUEST_BASE_BRANCH, baseRef); - Path eventPath = Paths.get(System.getenv(GITHUB_EVENT_PATH)); + Path eventPath = Paths.get(environment.get(GITHUB_EVENT_PATH)); String event = new String(Files.readAllBytes(eventPath), StandardCharsets.UTF_8); Moshi moshi = new Moshi.Builder().build(); @@ -147,10 +155,10 @@ private String buildGitTag() { } } - private static String getGitBranchOrTag() { - String gitBranchOrTag = System.getenv(GHACTIONS_HEAD_REF); + private String getGitBranchOrTag() { + String gitBranchOrTag = environment.get(GHACTIONS_HEAD_REF); if (gitBranchOrTag == null || gitBranchOrTag.isEmpty()) { - gitBranchOrTag = System.getenv(GHACTIONS_REF); + gitBranchOrTag = environment.get(GHACTIONS_REF); } return gitBranchOrTag; } diff --git a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/JenkinsInfo.java b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/JenkinsInfo.java index a4d65533428..bb3d56f81e3 100644 --- a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/JenkinsInfo.java +++ b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/JenkinsInfo.java @@ -9,6 +9,7 @@ import datadog.trace.api.civisibility.telemetry.tag.Provider; import datadog.trace.api.git.CommitInfo; import datadog.trace.api.git.GitInfo; +import datadog.trace.civisibility.ci.env.CiEnvironment; import datadog.trace.util.Strings; import de.thetaphi.forbiddenapis.SuppressForbidden; import java.util.Arrays; @@ -37,34 +38,40 @@ class JenkinsInfo implements CIProviderInfo { public static final String JENKINS_NODE_NAME = "NODE_NAME"; public static final String JENKINS_NODE_LABELS = "NODE_LABELS"; + private final CiEnvironment environment; + + JenkinsInfo(CiEnvironment environment) { + this.environment = environment; + } + @Override public GitInfo buildCIGitInfo() { return new GitInfo( filterSensitiveInfo(buildGitRepositoryUrl()), buildGitBranch(), buildGitTag(), - new CommitInfo(System.getenv(JENKINS_GIT_COMMIT))); + new CommitInfo(environment.get(JENKINS_GIT_COMMIT))); } @Override public CIInfo buildCIInfo() { final String gitBranch = buildGitBranch(); - return CIInfo.builder() + return CIInfo.builder(environment) .ciProviderName(JENKINS_PROVIDER_NAME) - .ciPipelineId(System.getenv(JENKINS_PIPELINE_ID)) + .ciPipelineId(environment.get(JENKINS_PIPELINE_ID)) .ciPipelineName(buildCiPipelineName(gitBranch)) - .ciPipelineNumber(System.getenv(JENKINS_PIPELINE_NUMBER)) - .ciPipelineUrl(System.getenv(JENKINS_PIPELINE_URL)) - .ciWorkspace(expandTilde(System.getenv(JENKINS_WORKSPACE_PATH))) - .ciNodeName(System.getenv(JENKINS_NODE_NAME)) + .ciPipelineNumber(environment.get(JENKINS_PIPELINE_NUMBER)) + .ciPipelineUrl(environment.get(JENKINS_PIPELINE_URL)) + .ciWorkspace(expandTilde(environment.get(JENKINS_WORKSPACE_PATH))) + .ciNodeName(environment.get(JENKINS_NODE_NAME)) .ciNodeLabels(buildCiNodeLabels()) .ciEnvVars(JENKINS_DD_CUSTOM_TRACE_ID) .build(); } private String buildCiNodeLabels() { - String labels = System.getenv(JENKINS_NODE_LABELS); + String labels = environment.get(JENKINS_NODE_LABELS); if (labels == null || labels.isEmpty()) { return labels; } @@ -73,13 +80,13 @@ private String buildCiNodeLabels() { } private String buildGitRepositoryUrl() { - return System.getenv(JENKINS_GIT_REPOSITORY_URL) != null - ? System.getenv(JENKINS_GIT_REPOSITORY_URL) - : System.getenv(JENKINS_GIT_REPOSITORY_URL_ALT); + return environment.get(JENKINS_GIT_REPOSITORY_URL) != null + ? environment.get(JENKINS_GIT_REPOSITORY_URL) + : environment.get(JENKINS_GIT_REPOSITORY_URL_ALT); } private String buildGitBranch() { - final String gitBranchOrTag = System.getenv(JENKINS_GIT_BRANCH); + final String gitBranchOrTag = environment.get(JENKINS_GIT_BRANCH); if (!isTagReference(gitBranchOrTag)) { return normalizeBranch(gitBranchOrTag); } else { @@ -88,7 +95,7 @@ private String buildGitBranch() { } private String buildGitTag() { - final String gitBranchOrTag = System.getenv(JENKINS_GIT_BRANCH); + final String gitBranchOrTag = environment.get(JENKINS_GIT_BRANCH); if (isTagReference(gitBranchOrTag)) { return normalizeTag(gitBranchOrTag); } else { @@ -97,7 +104,7 @@ private String buildGitTag() { } private String buildCiPipelineName(final String branch) { - final String jobName = System.getenv(JENKINS_PIPELINE_NAME); + final String jobName = environment.get(JENKINS_PIPELINE_NAME); return filterJenkinsJobName(jobName, branch); } diff --git a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/TeamcityInfo.java b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/TeamcityInfo.java index ed2a0f2de20..996576f134a 100644 --- a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/TeamcityInfo.java +++ b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/TeamcityInfo.java @@ -3,6 +3,7 @@ import datadog.trace.api.civisibility.telemetry.tag.Provider; import datadog.trace.api.git.CommitInfo; import datadog.trace.api.git.GitInfo; +import datadog.trace.civisibility.ci.env.CiEnvironment; public class TeamcityInfo implements CIProviderInfo { public static final String TEAMCITY = "TEAMCITY_VERSION"; @@ -10,6 +11,12 @@ public class TeamcityInfo implements CIProviderInfo { private static final String TEAMCITY_BUILDCONF_NAME = "TEAMCITY_BUILDCONF_NAME"; private static final String BUILD_URL = "BUILD_URL"; + private final CiEnvironment environment; + + TeamcityInfo(CiEnvironment environment) { + this.environment = environment; + } + @Override public GitInfo buildCIGitInfo() { return new GitInfo(null, null, null, new CommitInfo(null)); @@ -17,10 +24,10 @@ public GitInfo buildCIGitInfo() { @Override public CIInfo buildCIInfo() { - return CIInfo.builder() + return CIInfo.builder(environment) .ciProviderName(TEAMCITY_PROVIDER_NAME) - .ciJobName(System.getenv(TEAMCITY_BUILDCONF_NAME)) - .ciJobUrl(System.getenv(BUILD_URL)) + .ciJobName(environment.get(TEAMCITY_BUILDCONF_NAME)) + .ciJobUrl(environment.get(BUILD_URL)) .build(); } diff --git a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/TravisInfo.java b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/TravisInfo.java index 830f9056291..8bcad157624 100644 --- a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/TravisInfo.java +++ b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/TravisInfo.java @@ -8,6 +8,7 @@ import datadog.trace.api.git.CommitInfo; import datadog.trace.api.git.GitInfo; import datadog.trace.api.git.PersonInfo; +import datadog.trace.civisibility.ci.env.CiEnvironment; class TravisInfo implements CIProviderInfo { @@ -27,46 +28,51 @@ class TravisInfo implements CIProviderInfo { public static final String TRAVIS_GIT_TAG = "TRAVIS_TAG"; public static final String TRAVIS_GIT_COMMIT_MESSAGE = "TRAVIS_COMMIT_MESSAGE"; + private final CiEnvironment environment; + + TravisInfo(CiEnvironment environment) { + this.environment = environment; + } + @Override public GitInfo buildCIGitInfo() { - return new GitInfo( buildGitRepositoryUrl(), buildGitBranch(), - normalizeTag(System.getenv(TRAVIS_GIT_TAG)), + normalizeTag(environment.get(TRAVIS_GIT_TAG)), new CommitInfo( - System.getenv(TRAVIS_GIT_COMMIT), + environment.get(TRAVIS_GIT_COMMIT), PersonInfo.NOOP, PersonInfo.NOOP, - System.getenv(TRAVIS_GIT_COMMIT_MESSAGE))); + environment.get(TRAVIS_GIT_COMMIT_MESSAGE))); } @Override public CIInfo buildCIInfo() { - return CIInfo.builder() + return CIInfo.builder(environment) .ciProviderName(TRAVIS_PROVIDER_NAME) - .ciPipelineId(System.getenv(TRAVIS_PIPELINE_ID)) + .ciPipelineId(environment.get(TRAVIS_PIPELINE_ID)) .ciPipelineName(buildCiPipelineName()) - .ciPipelineNumber(System.getenv(TRAVIS_PIPELINE_NUMBER)) - .ciPipelineUrl(System.getenv(TRAVIS_PIPELINE_URL)) - .ciJobUrl(System.getenv(TRAVIS_JOB_URL)) - .ciWorkspace(expandTilde(System.getenv(TRAVIS_WORKSPACE_PATH))) + .ciPipelineNumber(environment.get(TRAVIS_PIPELINE_NUMBER)) + .ciPipelineUrl(environment.get(TRAVIS_PIPELINE_URL)) + .ciJobUrl(environment.get(TRAVIS_JOB_URL)) + .ciWorkspace(expandTilde(environment.get(TRAVIS_WORKSPACE_PATH))) .build(); } private String buildGitBranch() { - final String fromBranch = System.getenv(TRAVIS_GIT_PR_BRANCH); + final String fromBranch = environment.get(TRAVIS_GIT_PR_BRANCH); if (fromBranch != null && !fromBranch.isEmpty()) { return normalizeBranch(fromBranch); } else { - return normalizeBranch(System.getenv(TRAVIS_GIT_BRANCH)); + return normalizeBranch(environment.get(TRAVIS_GIT_BRANCH)); } } private String buildGitRepositoryUrl() { - String repoSlug = System.getenv(TRAVIS_PR_REPOSITORY_SLUG); + String repoSlug = environment.get(TRAVIS_PR_REPOSITORY_SLUG); if (repoSlug == null || repoSlug.isEmpty()) { - repoSlug = System.getenv(TRAVIS_REPOSITORY_SLUG); + repoSlug = environment.get(TRAVIS_REPOSITORY_SLUG); } if (repoSlug == null || repoSlug.isEmpty()) { @@ -76,9 +82,9 @@ private String buildGitRepositoryUrl() { } private String buildCiPipelineName() { - String repoSlug = System.getenv(TRAVIS_PR_REPOSITORY_SLUG); + String repoSlug = environment.get(TRAVIS_PR_REPOSITORY_SLUG); if (repoSlug == null || repoSlug.isEmpty()) { - repoSlug = System.getenv(TRAVIS_REPOSITORY_SLUG); + repoSlug = environment.get(TRAVIS_REPOSITORY_SLUG); } return repoSlug; } diff --git a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/UnknownCIInfo.java b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/UnknownCIInfo.java index 02dfed2bd4a..72ddbb4017c 100644 --- a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/UnknownCIInfo.java +++ b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/UnknownCIInfo.java @@ -4,6 +4,7 @@ import datadog.trace.api.civisibility.telemetry.tag.Provider; import datadog.trace.api.git.GitInfo; +import datadog.trace.civisibility.ci.env.CiEnvironment; import java.nio.file.Path; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -28,14 +29,12 @@ class UnknownCIInfo implements CIProviderInfo { public static final String UNKNOWN_PROVIDER_NAME = "unknown"; + private final CiEnvironment environment; private final String targetFolder; private final Path currentPath; - UnknownCIInfo(Path currentPath) { - this(".git", currentPath); - } - - UnknownCIInfo(String targetFolder, Path currentPath) { + UnknownCIInfo(CiEnvironment environment, String targetFolder, Path currentPath) { + this.environment = environment; this.targetFolder = targetFolder; this.currentPath = currentPath; } @@ -58,7 +57,7 @@ public CIInfo buildCIInfo() { LOGGER.debug("Could not get real path for workspace folder {}", workspace, e); } - return CIInfo.builder().ciWorkspace(workspace.toAbsolutePath().toString()).build(); + return CIInfo.builder(environment).ciWorkspace(workspace.toAbsolutePath().toString()).build(); } protected String getTargetFolder() { diff --git a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/env/CiEnvironment.java b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/env/CiEnvironment.java new file mode 100644 index 00000000000..f649701e382 --- /dev/null +++ b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/env/CiEnvironment.java @@ -0,0 +1,10 @@ +package datadog.trace.civisibility.ci.env; + +import java.util.Map; + +public interface CiEnvironment { + + String get(String name); + + Map get(); +} diff --git a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/env/CiEnvironmentImpl.java b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/env/CiEnvironmentImpl.java new file mode 100644 index 00000000000..0030df98768 --- /dev/null +++ b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/env/CiEnvironmentImpl.java @@ -0,0 +1,22 @@ +package datadog.trace.civisibility.ci.env; + +import java.util.Map; + +public class CiEnvironmentImpl implements CiEnvironment { + + private final Map env; + + public CiEnvironmentImpl(Map env) { + this.env = env; + } + + @Override + public String get(String name) { + return env.get(name); + } + + @Override + public Map get() { + return env; + } +} diff --git a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/env/CompositeCiEnvironment.java b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/env/CompositeCiEnvironment.java new file mode 100644 index 00000000000..2a723606d76 --- /dev/null +++ b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/ci/env/CompositeCiEnvironment.java @@ -0,0 +1,35 @@ +package datadog.trace.civisibility.ci.env; + +import java.util.HashMap; +import java.util.Map; + +public class CompositeCiEnvironment implements CiEnvironment { + + private final CiEnvironment[] delegates; + + public CompositeCiEnvironment(CiEnvironment... delegates) { + this.delegates = delegates; + } + + @Override + public String get(String name) { + for (CiEnvironment delegate : delegates) { + String value = delegate.get(name); + if (value != null) { + return value; + } + } + return null; + } + + @Override + public Map get() { + Map combinedEnvironment = new HashMap<>(); + for (int i = delegates.length - 1; i >= 0; i--) { + // iterating over delegates in reverse order, + // since delegates with lower indices have higher priority + combinedEnvironment.putAll(delegates[i].get()); + } + return combinedEnvironment; + } +} diff --git a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/git/CIProviderGitInfoBuilder.java b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/git/CIProviderGitInfoBuilder.java index 7a138f2f10e..b4a6d6f0d30 100644 --- a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/git/CIProviderGitInfoBuilder.java +++ b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/git/CIProviderGitInfoBuilder.java @@ -5,15 +5,25 @@ import datadog.trace.api.git.GitInfoBuilder; import datadog.trace.civisibility.ci.CIProviderInfo; import datadog.trace.civisibility.ci.CIProviderInfoFactory; +import datadog.trace.civisibility.ci.env.CiEnvironment; import java.nio.file.Path; import java.nio.file.Paths; import javax.annotation.Nullable; public class CIProviderGitInfoBuilder implements GitInfoBuilder { + + private final Config config; + private final CiEnvironment environment; + + public CIProviderGitInfoBuilder(Config config, CiEnvironment environment) { + this.config = config; + this.environment = environment; + } + @Override public GitInfo build(@Nullable String repositoryPath) { Path currentPath = repositoryPath != null ? Paths.get(repositoryPath) : null; - CIProviderInfoFactory ciProviderInfoFactory = new CIProviderInfoFactory(Config.get()); + CIProviderInfoFactory ciProviderInfoFactory = new CIProviderInfoFactory(config, environment); CIProviderInfo ciProviderInfo = ciProviderInfoFactory.createCIProviderInfo(currentPath); return ciProviderInfo.buildCIGitInfo(); } diff --git a/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/CiVisibilityServicesTest.groovy b/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/CiVisibilityServicesTest.groovy new file mode 100644 index 00000000000..8e7cbf71a5a --- /dev/null +++ b/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/CiVisibilityServicesTest.groovy @@ -0,0 +1,33 @@ +package datadog.trace.civisibility + +import datadog.trace.agent.test.server.http.TestHttpServer +import datadog.trace.agent.test.utils.OkHttpUtils +import spock.lang.Specification + +import static datadog.trace.agent.test.server.http.TestHttpServer.httpServer + +class CiVisibilityServicesTest extends Specification { + + def "test get remote environment"() { + given: + def key = "the-key" + + TestHttpServer remoteEnvironmentServer = httpServer { + handlers { + prefix("/") { + if (request.getHeader(CiVisibilityServices.DD_ENV_VARS_PROVIDER_KEY_HEADER) == key) { + response.status(200).send(""" { "a": 1, "b": "2" } """) + } else { + response.status(404).send() + } + } + } + } + + expect: + CiVisibilityServices.getRemoteEnvironment(remoteEnvironmentServer.address.toString(), key, OkHttpUtils.client()) == ["a": "1", "b": "2"] + + cleanup: + remoteEnvironmentServer.stop() + } +} diff --git a/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/ci/CIProviderInfoFactoryTest.groovy b/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/ci/CIProviderInfoFactoryTest.groovy index 62d9ec6108b..08b21a8d318 100644 --- a/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/ci/CIProviderInfoFactoryTest.groovy +++ b/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/ci/CIProviderInfoFactoryTest.groovy @@ -1,6 +1,7 @@ package datadog.trace.civisibility.ci import datadog.trace.api.Config +import datadog.trace.civisibility.ci.env.CiEnvironmentImpl import org.junit.Rule import org.junit.contrib.java.lang.system.EnvironmentVariables import org.junit.contrib.java.lang.system.RestoreSystemProperties @@ -38,7 +39,7 @@ class CIProviderInfoFactoryTest extends Specification { environmentVariables.set(ciKeySelector, "true") when: - def ciProviderInfoFactory = new CIProviderInfoFactory(Config.get()) + def ciProviderInfoFactory = new CIProviderInfoFactory(Config.get(), new CiEnvironmentImpl(System.getenv())) def ciProviderInfo = ciProviderInfoFactory.createCIProviderInfo(Paths.get("").toAbsolutePath()) then: diff --git a/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/ci/CITagsProviderTest.groovy b/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/ci/CITagsProviderTest.groovy index 616f7ea18db..e51a2224f3a 100644 --- a/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/ci/CITagsProviderTest.groovy +++ b/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/ci/CITagsProviderTest.groovy @@ -5,6 +5,7 @@ import datadog.trace.api.git.GitInfo import datadog.trace.api.git.GitInfoProvider import datadog.trace.api.git.UserSuppliedGitInfoBuilder import datadog.trace.bootstrap.instrumentation.api.Tags +import datadog.trace.civisibility.ci.env.CiEnvironmentImpl import datadog.trace.civisibility.git.CILocalGitInfoBuilder import datadog.trace.civisibility.git.CIProviderGitInfoBuilder import datadog.trace.civisibility.git.tree.GitClient @@ -46,7 +47,7 @@ abstract class CITagsProviderTest extends Specification { } when: - CIProviderInfoFactory ciProviderInfoFactory = new CIProviderInfoFactory(Config.get(), GIT_FOLDER_FOR_TESTS) + CIProviderInfoFactory ciProviderInfoFactory = new CIProviderInfoFactory(Config.get(), GIT_FOLDER_FOR_TESTS, new CiEnvironmentImpl(System.getenv())) def ciProviderInfo = ciProviderInfoFactory.createCIProviderInfo(getWorkspacePath()) def ciInfo = ciProviderInfo.buildCIInfo() def ciTagsProvider = ciTagsProvider() @@ -71,7 +72,7 @@ abstract class CITagsProviderTest extends Specification { environmentVariables.set(GitInfo.DD_GIT_COMMIT_SHA, "1234567890123456789012345678901234567890") when: - CIProviderInfoFactory ciProviderInfoFactory = new CIProviderInfoFactory(Config.get(), GIT_FOLDER_FOR_TESTS) + CIProviderInfoFactory ciProviderInfoFactory = new CIProviderInfoFactory(Config.get(), GIT_FOLDER_FOR_TESTS, new CiEnvironmentImpl(System.getenv())) def ciProviderInfo = ciProviderInfoFactory.createCIProviderInfo(getWorkspacePath()) def ciInfo = ciProviderInfo.buildCIInfo() def ciTagsProvider = ciTagsProvider() @@ -90,7 +91,7 @@ abstract class CITagsProviderTest extends Specification { environmentVariables.set(GitInfo.DD_GIT_REPOSITORY_URL, "local supplied repo url") when: - CIProviderInfoFactory ciProviderInfoFactory = new CIProviderInfoFactory(Config.get(), GIT_FOLDER_FOR_TESTS) + CIProviderInfoFactory ciProviderInfoFactory = new CIProviderInfoFactory(Config.get(), GIT_FOLDER_FOR_TESTS, new CiEnvironmentImpl(System.getenv())) def ciProviderInfo = ciProviderInfoFactory.createCIProviderInfo(getWorkspacePath()) def ciInfo = ciProviderInfo.buildCIInfo() def ciTagsProvider = ciTagsProvider() @@ -107,7 +108,7 @@ abstract class CITagsProviderTest extends Specification { } when: - CIProviderInfoFactory ciProviderInfoFactory = new CIProviderInfoFactory(Config.get(), GIT_FOLDER_FOR_TESTS) + CIProviderInfoFactory ciProviderInfoFactory = new CIProviderInfoFactory(Config.get(), GIT_FOLDER_FOR_TESTS, new CiEnvironmentImpl(System.getenv())) def ciProviderInfo = ciProviderInfoFactory.createCIProviderInfo(getWorkspacePath()) def ciInfo = ciProviderInfo.buildCIInfo() def ciTagsProvider = ciTagsProvider() @@ -139,7 +140,7 @@ abstract class CITagsProviderTest extends Specification { then: if (isCi()) { - CIProviderInfoFactory ciProviderInfoFactory = new CIProviderInfoFactory(Config.get(), GIT_FOLDER_FOR_TESTS) + CIProviderInfoFactory ciProviderInfoFactory = new CIProviderInfoFactory(Config.get(), GIT_FOLDER_FOR_TESTS, new CiEnvironmentImpl(System.getenv())) def ciProviderInfo = ciProviderInfoFactory.createCIProviderInfo(getWorkspacePath()) def ciInfo = ciProviderInfo.buildCIInfo() def tags = ciTagsProvider.getCiTags(ciInfo) @@ -173,7 +174,7 @@ abstract class CITagsProviderTest extends Specification { GitInfoProvider gitInfoProvider = new GitInfoProvider() gitInfoProvider.registerGitInfoBuilder(new UserSuppliedGitInfoBuilder()) - gitInfoProvider.registerGitInfoBuilder(new CIProviderGitInfoBuilder()) + gitInfoProvider.registerGitInfoBuilder(new CIProviderGitInfoBuilder(Config.get(), new CiEnvironmentImpl(System.getenv()))) gitInfoProvider.registerGitInfoBuilder(new CILocalGitInfoBuilder(gitClientFactory, GIT_FOLDER_FOR_TESTS)) return new CITagsProvider(gitInfoProvider) } diff --git a/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/ci/GithubActionsInfoTest.groovy b/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/ci/GithubActionsInfoTest.groovy index 784e5e3d529..c54503cb0a7 100644 --- a/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/ci/GithubActionsInfoTest.groovy +++ b/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/ci/GithubActionsInfoTest.groovy @@ -1,5 +1,6 @@ package datadog.trace.civisibility.ci +import datadog.trace.civisibility.ci.env.CiEnvironmentImpl import java.nio.file.Paths @@ -36,7 +37,7 @@ class GithubActionsInfoTest extends CITagsProviderTest { environmentVariables.set(GithubActionsInfo.GITHUB_EVENT_PATH, githubEventPath.toString()) when: - def cIInfo = new GithubActionsInfo().buildCIInfo() + def cIInfo = new GithubActionsInfo(new CiEnvironmentImpl(System.getenv())).buildCIInfo() then: cIInfo.getAdditionalTags() == [ diff --git a/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/ci/UnknownCIInfoTest.groovy b/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/ci/UnknownCIInfoTest.groovy index 333f554c8d4..77d1dda2f7b 100644 --- a/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/ci/UnknownCIInfoTest.groovy +++ b/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/ci/UnknownCIInfoTest.groovy @@ -4,6 +4,7 @@ import datadog.trace.api.Config import datadog.trace.api.git.GitInfoProvider import datadog.trace.api.git.UserSuppliedGitInfoBuilder import datadog.trace.bootstrap.instrumentation.api.Tags +import datadog.trace.civisibility.ci.env.CiEnvironmentImpl import datadog.trace.civisibility.git.CILocalGitInfoBuilder import datadog.trace.civisibility.git.CIProviderGitInfoBuilder import datadog.trace.civisibility.git.tree.GitClient @@ -44,7 +45,7 @@ class UnknownCIInfoTest extends CITagsProviderTest { ] when: - CIProviderInfoFactory ciProviderInfoFactory = new CIProviderInfoFactory(Config.get(), GIT_FOLDER_FOR_TESTS) + CIProviderInfoFactory ciProviderInfoFactory = new CIProviderInfoFactory(Config.get(), GIT_FOLDER_FOR_TESTS, new CiEnvironmentImpl(System.getenv())) def ciProviderInfo = ciProviderInfoFactory.createCIProviderInfo(workspaceForTests) def ciInfo = ciProviderInfo.buildCIInfo() def ciTagsProvider = ciTagsProvider() @@ -61,9 +62,9 @@ class UnknownCIInfoTest extends CITagsProviderTest { GitInfoProvider gitInfoProvider = new GitInfoProvider() gitInfoProvider.registerGitInfoBuilder(new UserSuppliedGitInfoBuilder()) - gitInfoProvider.registerGitInfoBuilder(new CIProviderGitInfoBuilder()) + gitInfoProvider.registerGitInfoBuilder(new CIProviderGitInfoBuilder(Config.get(), new CiEnvironmentImpl(System.getenv()))) gitInfoProvider.registerGitInfoBuilder(new CILocalGitInfoBuilder(gitClientFactory, "this-target-folder-does-not-exist")) - CIProviderInfoFactory ciProviderInfoFactory = new CIProviderInfoFactory(Config.get(), "this-target-folder-does-not-exist") + CIProviderInfoFactory ciProviderInfoFactory = new CIProviderInfoFactory(Config.get(), "this-target-folder-does-not-exist", new CiEnvironmentImpl(System.getenv())) def ciProviderInfo = ciProviderInfoFactory.createCIProviderInfo(workspaceForTests) def ciInfo = ciProviderInfo.buildCIInfo() diff --git a/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/ci/env/CiEnvironmentImplTest.groovy b/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/ci/env/CiEnvironmentImplTest.groovy new file mode 100644 index 00000000000..fa8f664cb7c --- /dev/null +++ b/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/ci/env/CiEnvironmentImplTest.groovy @@ -0,0 +1,25 @@ +package datadog.trace.civisibility.ci.env + + +import spock.lang.Specification + +class CiEnvironmentImplTest extends Specification { + + def "test returns an environment variable"() { + setup: + def environmentVariables = ["MY_ENV_VAR": "MY_VALUE"] + def environment = new CiEnvironmentImpl(environmentVariables) + + expect: + environment.get("MY_ENV_VAR") == "MY_VALUE" + } + + def "test returns all environment variables"() { + setup: + def environmentVariables = ["MY_ENV_VAR": "MY_VALUE", "MY_OTHER_ENV_VAR": "MY_OTHER_VALUE"] + def environment = new CiEnvironmentImpl(environmentVariables) + + expect: + environment.get() == ["MY_ENV_VAR": "MY_VALUE", "MY_OTHER_ENV_VAR": "MY_OTHER_VALUE"] + } +} diff --git a/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/ci/env/CompositeCiEnvironmentTest.groovy b/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/ci/env/CompositeCiEnvironmentTest.groovy new file mode 100644 index 00000000000..1f28d0f5859 --- /dev/null +++ b/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/ci/env/CompositeCiEnvironmentTest.groovy @@ -0,0 +1,41 @@ +package datadog.trace.civisibility.ci.env + + +import spock.lang.Specification + +class CompositeCiEnvironmentTest extends Specification { + + def "test uses delegate"() { + setup: + def environmentVariables = ["MY_ENV_VAR": "MY_VALUE", "MY_OTHER_ENV_VAR": "MY_OTHER_VALUE"] + def delegate = new CiEnvironmentImpl(environmentVariables) + def environment = new CompositeCiEnvironment(delegate) + + expect: + environment.get("MY_ENV_VAR") == "MY_VALUE" + environment.get() == ["MY_ENV_VAR": "MY_VALUE", "MY_OTHER_ENV_VAR": "MY_OTHER_VALUE"] + } + + def "test uses multiple delegates"() { + setup: + def delegateA = new CiEnvironmentImpl(["A": "1", "AA": "2"]) + def delegateB = new CiEnvironmentImpl(["B": "3", "BB": "4"]) + def environment = new CompositeCiEnvironment(delegateA, delegateB) + + expect: + environment.get("A") == "1" + environment.get("B") == "3" + environment.get() == ["A": "1", "AA": "2", "B": "3", "BB": "4"] + } + + def "test delegates priority"() { + setup: + def delegateA = new CiEnvironmentImpl(["A": "1", "B": "2"]) + def delegateB = new CiEnvironmentImpl(["B": "3", "C": "4"]) + def environment = new CompositeCiEnvironment(delegateA, delegateB) + + expect: + environment.get("B") == "2" + environment.get() == ["A": "1", "B": "2", "C": "4"] + } +} diff --git a/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/config/ConfigurationApiImplTest.groovy b/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/config/ConfigurationApiImplTest.groovy index f56830ff3dc..b630e86fab9 100644 --- a/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/config/ConfigurationApiImplTest.groovy +++ b/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/config/ConfigurationApiImplTest.groovy @@ -395,7 +395,6 @@ class ConfigurationApiImplTest extends Specification { String apiKey = "api-key" String traceId = "a-trace-id" - long timeoutMillis = 1000 HttpRetryPolicy retryPolicy = Stub(HttpRetryPolicy) retryPolicy.shouldRetry(_) >> false @@ -403,7 +402,8 @@ class ConfigurationApiImplTest extends Specification { HttpRetryPolicy.Factory retryPolicyFactory = Stub(HttpRetryPolicy.Factory) retryPolicyFactory.create() >> retryPolicy - return new IntakeApi(intakeUrl, apiKey, traceId, timeoutMillis, retryPolicyFactory, responseCompression) + OkHttpClient client = OkHttpUtils.buildHttpClient(intakeUrl, REQUEST_TIMEOUT_MILLIS) + return new IntakeApi(intakeUrl, apiKey, traceId, retryPolicyFactory, client, responseCompression) } private static TracerEnvironment givenTracerEnvironment() { diff --git a/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/git/CIProviderGitInfoBuilderTest.groovy b/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/git/CIProviderGitInfoBuilderTest.groovy index 1ad5ad74617..1177e64183b 100644 --- a/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/git/CIProviderGitInfoBuilderTest.groovy +++ b/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/git/CIProviderGitInfoBuilderTest.groovy @@ -1,6 +1,7 @@ package datadog.trace.civisibility.git - +import datadog.trace.api.Config +import datadog.trace.civisibility.ci.env.CiEnvironmentImpl import org.junit.Rule import org.junit.contrib.java.lang.system.EnvironmentVariables import spock.lang.Specification @@ -19,7 +20,7 @@ class CIProviderGitInfoBuilderTest extends Specification { def "test builds empty git info in an unknown repository"() { setup: - def builder = new CIProviderGitInfoBuilder() + def builder = new CIProviderGitInfoBuilder(Config.get(), new CiEnvironmentImpl(System.getenv())) when: def gitInfo = builder.build(null) diff --git a/dd-java-agent/agent-debugger/src/main/java/com/datadog/debugger/instrumentation/CapturedContextInstrumentor.java b/dd-java-agent/agent-debugger/src/main/java/com/datadog/debugger/instrumentation/CapturedContextInstrumentor.java index af0bb92b2a8..dda1265b201 100644 --- a/dd-java-agent/agent-debugger/src/main/java/com/datadog/debugger/instrumentation/CapturedContextInstrumentor.java +++ b/dd-java-agent/agent-debugger/src/main/java/com/datadog/debugger/instrumentation/CapturedContextInstrumentor.java @@ -476,6 +476,7 @@ private Collection initAndHoistLocalVars(InsnList insnList) { } checkHoistableLocalVar(localVar, localVarsByName, localVarsBySlot, hoistableVarByName); } + removeDuplicatesFromArgs(hoistableVarByName, localVarsBySlotArray); // hoist vars List results = new ArrayList<>(); for (Map.Entry> entry : hoistableVarByName.entrySet()) { @@ -512,6 +513,19 @@ private Collection initAndHoistLocalVars(InsnList insnList) { return results; } + private void removeDuplicatesFromArgs( + Map> hoistableVarByName, + LocalVariableNode[] localVarsBySlotArray) { + for (int idx = 0; idx < argOffset; idx++) { + LocalVariableNode localVar = localVarsBySlotArray[idx]; + if (localVar == null) { + continue; + } + // we are removing local variables that are arguments + hoistableVarByName.remove(localVar.name); + } + } + private LabelNode findLatestLabel(InsnList instructions, Set endLabels) { for (AbstractInsnNode insn = instructions.getLast(); insn != null; insn = insn.getPrevious()) { if (insn instanceof LabelNode && endLabels.contains(insn)) { @@ -762,8 +776,8 @@ private void collectArguments(InsnList insnList, Snapshot.Kind kind) { int slot = isStatic ? 0 : 1; for (Type argType : argTypes) { String currentArgName = null; - if (slot < localVarsBySlot.length) { - LocalVariableNode localVarNode = localVarsBySlot[slot]; + if (slot < localVarsBySlotArray.length) { + LocalVariableNode localVarNode = localVarsBySlotArray[slot]; currentArgName = localVarNode != null ? localVarNode.name : null; } if (currentArgName == null) { diff --git a/dd-java-agent/agent-debugger/src/main/java/com/datadog/debugger/instrumentation/Instrumentor.java b/dd-java-agent/agent-debugger/src/main/java/com/datadog/debugger/instrumentation/Instrumentor.java index 0f81bf033d6..d16e2fda812 100644 --- a/dd-java-agent/agent-debugger/src/main/java/com/datadog/debugger/instrumentation/Instrumentor.java +++ b/dd-java-agent/agent-debugger/src/main/java/com/datadog/debugger/instrumentation/Instrumentor.java @@ -45,7 +45,7 @@ public abstract class Instrumentor { protected final LabelNode methodEnterLabel; protected int localVarBaseOffset; protected int argOffset; - protected final LocalVariableNode[] localVarsBySlot; + protected final LocalVariableNode[] localVarsBySlotArray; protected LabelNode returnHandlerLabel; protected final List finallyBlocks = new ArrayList<>(); @@ -68,7 +68,7 @@ public Instrumentor( for (Type t : argTypes) { argOffset += t.getSize(); } - localVarsBySlot = extractLocalVariables(argTypes); + localVarsBySlotArray = extractLocalVariables(argTypes); } public abstract InstrumentationResult.Status instrument(); diff --git a/dd-java-agent/agent-debugger/src/main/java/com/datadog/debugger/instrumentation/MetricInstrumentor.java b/dd-java-agent/agent-debugger/src/main/java/com/datadog/debugger/instrumentation/MetricInstrumentor.java index 1905d451f49..11c46673318 100644 --- a/dd-java-agent/agent-debugger/src/main/java/com/datadog/debugger/instrumentation/MetricInstrumentor.java +++ b/dd-java-agent/agent-debugger/src/main/java/com/datadog/debugger/instrumentation/MetricInstrumentor.java @@ -697,8 +697,8 @@ private ASMHelper.Type tryRetrieveArgument(String head, InsnList insnList) { int slot = instrumentor.isStatic ? 0 : 1; for (Type argType : argTypes) { String currentArgName = null; - if (instrumentor.localVarsBySlot.length > 0) { - LocalVariableNode localVarNode = instrumentor.localVarsBySlot[slot]; + if (instrumentor.localVarsBySlotArray.length > 0) { + LocalVariableNode localVarNode = instrumentor.localVarsBySlotArray[slot]; currentArgName = localVarNode != null ? localVarNode.name : null; } if (currentArgName == null) { diff --git a/dd-java-agent/agent-debugger/src/main/java/com/datadog/debugger/probe/CodeOriginProbe.java b/dd-java-agent/agent-debugger/src/main/java/com/datadog/debugger/probe/CodeOriginProbe.java index 6c6eeba5233..1f0c774a11b 100644 --- a/dd-java-agent/agent-debugger/src/main/java/com/datadog/debugger/probe/CodeOriginProbe.java +++ b/dd-java-agent/agent-debugger/src/main/java/com/datadog/debugger/probe/CodeOriginProbe.java @@ -1,7 +1,6 @@ package com.datadog.debugger.probe; import static com.datadog.debugger.codeorigin.DebuggerConfiguration.isDebuggerEnabled; -import static datadog.trace.api.DDTags.DD_CODE_ORIGIN_SNAPSHOT_ID; import static datadog.trace.api.DDTags.DD_STACK_CODE_ORIGIN_FRAME; import static datadog.trace.api.DDTags.DD_STACK_CODE_ORIGIN_TYPE; import static java.lang.String.format; @@ -13,7 +12,6 @@ import com.datadog.debugger.instrumentation.InstrumentationResult; import com.datadog.debugger.sink.Snapshot; import com.datadog.debugger.util.ClassNameFiltering; -import datadog.trace.api.DDTags; import datadog.trace.bootstrap.debugger.CapturedContext; import datadog.trace.bootstrap.debugger.MethodLocation; import datadog.trace.bootstrap.debugger.ProbeId; @@ -91,28 +89,9 @@ public void commit( private void applySpanOriginTags(AgentSpan span, String snapshotId) { List entries = getUserStackFrames(); - recordCodeOrigin(span, entries, snapshotId); recordStackFrames(span, entries, snapshotId); } - private void recordCodeOrigin( - AgentSpan span, List entries, String snapshotId) { - if (entrySpanProbe && !entries.isEmpty()) { - StackTraceElement entry = entries.get(0); - List list = asList(span, span.getLocalRootSpan()); - for (AgentSpan s : list) { - s.setTag(DDTags.DD_CODE_ORIGIN_FILE, toFileName(entry.getClassName())); - s.setTag(DDTags.DD_CODE_ORIGIN_METHOD, entry.getMethodName()); - s.setTag(DDTags.DD_CODE_ORIGIN_LINE, entry.getLineNumber()); - s.setTag(DDTags.DD_CODE_ORIGIN_TYPE, entry.getClassName()); - s.setTag(DDTags.DD_CODE_ORIGIN_METHOD_SIGNATURE, signature); - if (snapshotId != null) { - s.setTag(DD_CODE_ORIGIN_SNAPSHOT_ID, snapshotId); - } - } - } - } - private void recordStackFrames( AgentSpan span, List entries, String snapshotId) { List agentSpans = @@ -127,6 +106,9 @@ private void recordStackFrames( s.setTag(format(DD_STACK_CODE_ORIGIN_FRAME, i, "method"), info.getMethodName()); s.setTag(format(DD_STACK_CODE_ORIGIN_FRAME, i, "line"), info.getLineNumber()); s.setTag(format(DD_STACK_CODE_ORIGIN_FRAME, i, "type"), info.getClassName()); + if (i == 0 && signature != null) { + s.setTag(format(DD_STACK_CODE_ORIGIN_FRAME, i, "signature"), signature); + } if (i == 0 && snapshotId != null) { s.setTag(format(DD_STACK_CODE_ORIGIN_FRAME, i, "snapshot_id"), snapshotId); } diff --git a/dd-java-agent/agent-debugger/src/test/java/com/datadog/debugger/origin/CodeOriginTest.java b/dd-java-agent/agent-debugger/src/test/java/com/datadog/debugger/origin/CodeOriginTest.java index 76d2ab934fa..a76a202644b 100644 --- a/dd-java-agent/agent-debugger/src/test/java/com/datadog/debugger/origin/CodeOriginTest.java +++ b/dd-java-agent/agent-debugger/src/test/java/com/datadog/debugger/origin/CodeOriginTest.java @@ -32,7 +32,6 @@ import com.datadog.debugger.util.TestTraceInterceptor; import datadog.trace.agent.tooling.TracerInstaller; import datadog.trace.api.Config; -import datadog.trace.api.DDTags; import datadog.trace.api.InstrumenterConfig; import datadog.trace.api.interceptor.MutableSpan; import datadog.trace.bootstrap.debugger.DebuggerContext; @@ -191,20 +190,16 @@ private void waitForInstrumentation() { private static void checkEntrySpanTags(MutableSpan span, boolean includeSnapshot) { String keys = format("Existing keys for %s: %s", span.getOperationName(), ldKeys(span)); - assertKeyPresent(span, DDTags.DD_CODE_ORIGIN_FILE); - assertKeyPresent(span, DDTags.DD_CODE_ORIGIN_LINE); - assertKeyPresent(span, DDTags.DD_CODE_ORIGIN_METHOD); - assertKeyPresent(span, DDTags.DD_CODE_ORIGIN_METHOD_SIGNATURE); assertEquals(span.getTag(DD_STACK_CODE_ORIGIN_TYPE), "entry", keys); assertKeyPresent(span, DD_STACK_CODE_ORIGIN_TYPE); assertKeyPresent(span, format(DD_STACK_CODE_ORIGIN_FRAME, 0, "file")); assertKeyPresent(span, format(DD_STACK_CODE_ORIGIN_FRAME, 0, "line")); assertKeyPresent(span, format(DD_STACK_CODE_ORIGIN_FRAME, 0, "method")); + assertKeyPresent(span, format(DD_STACK_CODE_ORIGIN_FRAME, 0, "signature")); assertKeyPresent(span, format(DD_STACK_CODE_ORIGIN_FRAME, 0, "type")); if (includeSnapshot) { - assertKeyPresent(span, DDTags.DD_CODE_ORIGIN_SNAPSHOT_ID); assertKeyPresent(span, format(DD_STACK_CODE_ORIGIN_FRAME, 0, "snapshot_id")); } } @@ -229,12 +224,6 @@ private static void checkExitSpanTags(MutableSpan span, boolean includeSnapshot) String keys = format("Existing keys for %s: %s", span.getOperationName(), new TreeSet<>(ldKeys(span))); - assertKeyNotPresent(span, DDTags.DD_CODE_ORIGIN_FILE); - assertKeyNotPresent(span, DDTags.DD_CODE_ORIGIN_LINE); - assertKeyNotPresent(span, DDTags.DD_CODE_ORIGIN_METHOD); - assertKeyNotPresent(span, DDTags.DD_CODE_ORIGIN_METHOD_SIGNATURE); - assertKeyNotPresent(span, DDTags.DD_CODE_ORIGIN_SNAPSHOT_ID); - assertKeyPresent(span, DD_STACK_CODE_ORIGIN_TYPE); assertKeyPresent(span, format(DD_STACK_CODE_ORIGIN_FRAME, 0, "file")); assertKeyPresent(span, format(DD_STACK_CODE_ORIGIN_FRAME, 0, "line")); diff --git a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/InstrumenterModule.java b/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/InstrumenterModule.java index f1afd39e2f7..253eacc8331 100644 --- a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/InstrumenterModule.java +++ b/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/InstrumenterModule.java @@ -249,9 +249,14 @@ public List typeInstrumentations() { @Override public boolean isApplicable(Set enabledSystems) { - return enabledSystems.contains(TargetSystem.IAST) - || (isOptOutEnabled() - && InstrumenterConfig.get().getAppSecActivation() == ProductActivation.FULLY_ENABLED); + if (enabledSystems.contains(TargetSystem.IAST)) { + return true; + } + final InstrumenterConfig cfg = InstrumenterConfig.get(); + if (!isOptOutEnabled() || cfg.isIastFullyDisabled()) { + return false; + } + return cfg.getAppSecActivation() == ProductActivation.FULLY_ENABLED; } /** diff --git a/dd-java-agent/appsec/src/main/java/com/datadog/appsec/user/AppSecEventTrackerImpl.java b/dd-java-agent/appsec/src/main/java/com/datadog/appsec/user/AppSecEventTrackerImpl.java index 039312c7c93..e7cf336fa11 100644 --- a/dd-java-agent/appsec/src/main/java/com/datadog/appsec/user/AppSecEventTrackerImpl.java +++ b/dd-java-agent/appsec/src/main/java/com/datadog/appsec/user/AppSecEventTrackerImpl.java @@ -96,6 +96,15 @@ public void onLoginFailureEvent( } } + @Override + public void onUserEvent(UserIdCollectionMode mode, String userId) { + TraceSegment segment = beforeEvent(mode, userId); + if (segment == null) { + return; + } + onUserId(mode, segment, userId, EVENTS.userId()); + } + @Override public void onCustomEvent( final UserIdCollectionMode mode, final String eventName, final Map metadata) { diff --git a/dd-java-agent/appsec/src/test/groovy/com/datadog/appsec/user/AppSecEventTrackerSpecification.groovy b/dd-java-agent/appsec/src/test/groovy/com/datadog/appsec/user/AppSecEventTrackerSpecification.groovy index 8ec0447c9e6..f38200fff1b 100644 --- a/dd-java-agent/appsec/src/test/groovy/com/datadog/appsec/user/AppSecEventTrackerSpecification.groovy +++ b/dd-java-agent/appsec/src/test/groovy/com/datadog/appsec/user/AppSecEventTrackerSpecification.groovy @@ -237,6 +237,25 @@ class AppSecEventTrackerSpecification extends DDSpecification { 'ident' | 'identification' | 'user doesn\'t exist' | USER_ID } + def "test onUserEvent (#mode)"() { + setup: + final collectionMode = UserIdCollectionMode.fromString(mode, null) + + when: + tracker.onUserEvent(collectionMode, USER_ID) + + then: + 1 * traceSegment.getTagTop('_dd.appsec.user.collection_mode') >> null + 1 * userCallback.apply(_ as RequestContext, collectionMode, expectedUserId) >> NoopFlow.INSTANCE + 0 * _ + + where: + mode | modeTag | expectedUserId + 'anon' | 'anonymization' | ANONYMIZED_USER_ID + 'ident' | 'identification' | USER_ID + } + + def "test onUserNotFound (#mode)"() { setup: final collectionMode = UserIdCollectionMode.fromString(mode, null) diff --git a/dd-java-agent/instrumentation/akka-http-10.0/build.gradle b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/build.gradle similarity index 99% rename from dd-java-agent/instrumentation/akka-http-10.0/build.gradle rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/build.gradle index a77f0330348..ed0efec6969 100644 --- a/dd-java-agent/instrumentation/akka-http-10.0/build.gradle +++ b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/build.gradle @@ -120,7 +120,7 @@ dependencies { iastTestCompileOnly group: 'de.thetaphi', name: 'forbiddenapis', version: '3.4' iastTestRuntimeOnly project(':dd-java-agent:instrumentation:jackson-core') iastTestRuntimeOnly project(':dd-java-agent:instrumentation:iast-instrumenter') - iastTestRuntimeOnly project(':dd-java-agent:instrumentation:akka-http-10.2-iast') + iastTestRuntimeOnly project(':dd-java-agent:instrumentation:akka-http:akka-http-10.2-iast') // There are some internal API changes in 10.1 that we would like to test separately for version101TestImplementation libs.scala212 diff --git a/dd-java-agent/instrumentation/akka-http-10.0/gradle.lockfile b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/gradle.lockfile similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/gradle.lockfile rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/gradle.lockfile diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/baseTest/groovy/AkkaHttpClientInstrumentationTest.groovy b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/baseTest/groovy/AkkaHttpClientInstrumentationTest.groovy similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/baseTest/groovy/AkkaHttpClientInstrumentationTest.groovy rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/baseTest/groovy/AkkaHttpClientInstrumentationTest.groovy diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/baseTest/groovy/AkkaHttpServerInstrumentationTest.groovy b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/baseTest/groovy/AkkaHttpServerInstrumentationTest.groovy similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/baseTest/groovy/AkkaHttpServerInstrumentationTest.groovy rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/baseTest/groovy/AkkaHttpServerInstrumentationTest.groovy diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/baseTest/resources/application.conf b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/baseTest/resources/application.conf similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/baseTest/resources/application.conf rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/baseTest/resources/application.conf diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/baseTest/scala/AkkaHttpTestWebServer.scala b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/baseTest/scala/AkkaHttpTestWebServer.scala similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/baseTest/scala/AkkaHttpTestWebServer.scala rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/baseTest/scala/AkkaHttpTestWebServer.scala diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/iastTest/groovy/datadog/trace/instrumentation/akkahttp/iast/AkkaIastTestWebServer.groovy b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/iastTest/groovy/datadog/trace/instrumentation/akkahttp/iast/AkkaIastTestWebServer.groovy similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/iastTest/groovy/datadog/trace/instrumentation/akkahttp/iast/AkkaIastTestWebServer.groovy rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/iastTest/groovy/datadog/trace/instrumentation/akkahttp/iast/AkkaIastTestWebServer.groovy diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/iastTest/groovy/datadog/trace/instrumentation/akkahttp/iast/IastAkkaTest.groovy b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/iastTest/groovy/datadog/trace/instrumentation/akkahttp/iast/IastAkkaTest.groovy similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/iastTest/groovy/datadog/trace/instrumentation/akkahttp/iast/IastAkkaTest.groovy rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/iastTest/groovy/datadog/trace/instrumentation/akkahttp/iast/IastAkkaTest.groovy diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/iastTest/groovy/foo/bar/WithInstrumentedCallSites.groovy b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/iastTest/groovy/foo/bar/WithInstrumentedCallSites.groovy similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/iastTest/groovy/foo/bar/WithInstrumentedCallSites.groovy rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/iastTest/groovy/foo/bar/WithInstrumentedCallSites.groovy diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/lagomTest/groovy/LagomTest.groovy b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/lagomTest/groovy/LagomTest.groovy similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/lagomTest/groovy/LagomTest.groovy rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/lagomTest/groovy/LagomTest.groovy diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/lagomTest/java/EchoService.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/lagomTest/java/EchoService.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/lagomTest/java/EchoService.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/lagomTest/java/EchoService.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/lagomTest/java/EchoServiceImpl.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/lagomTest/java/EchoServiceImpl.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/lagomTest/java/EchoServiceImpl.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/lagomTest/java/EchoServiceImpl.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/lagomTest/java/ServiceTestModule.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/lagomTest/java/ServiceTestModule.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/lagomTest/java/ServiceTestModule.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/lagomTest/java/ServiceTestModule.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/lagomTest/resources/application.conf b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/lagomTest/resources/application.conf similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/lagomTest/resources/application.conf rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/lagomTest/resources/application.conf diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/latestDepTest/groovy/AkkaHttp102ServerInstrumentationTests.groovy b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/latestDepTest/groovy/AkkaHttp102ServerInstrumentationTests.groovy similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/latestDepTest/groovy/AkkaHttp102ServerInstrumentationTests.groovy rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/latestDepTest/groovy/AkkaHttp102ServerInstrumentationTests.groovy diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/latestDepTest/scala/AkkaHttp102TestWebServer.scala b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/latestDepTest/scala/AkkaHttp102TestWebServer.scala similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/latestDepTest/scala/AkkaHttp102TestWebServer.scala rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/latestDepTest/scala/AkkaHttp102TestWebServer.scala diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/AkkaHttp2ServerInstrumentation.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/AkkaHttp2ServerInstrumentation.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/AkkaHttp2ServerInstrumentation.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/AkkaHttp2ServerInstrumentation.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/AkkaHttpClientDecorator.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/AkkaHttpClientDecorator.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/AkkaHttpClientDecorator.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/AkkaHttpClientDecorator.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/AkkaHttpClientHelpers.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/AkkaHttpClientHelpers.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/AkkaHttpClientHelpers.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/AkkaHttpClientHelpers.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/AkkaHttpServerDecorator.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/AkkaHttpServerDecorator.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/AkkaHttpServerDecorator.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/AkkaHttpServerDecorator.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/AkkaHttpServerHeaders.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/AkkaHttpServerHeaders.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/AkkaHttpServerHeaders.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/AkkaHttpServerHeaders.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/AkkaHttpServerInstrumentation.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/AkkaHttpServerInstrumentation.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/AkkaHttpServerInstrumentation.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/AkkaHttpServerInstrumentation.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/AkkaHttpSingleRequestInstrumentation.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/AkkaHttpSingleRequestInstrumentation.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/AkkaHttpSingleRequestInstrumentation.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/AkkaHttpSingleRequestInstrumentation.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/AkkaPoolMasterActorInstrumentation.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/AkkaPoolMasterActorInstrumentation.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/AkkaPoolMasterActorInstrumentation.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/AkkaPoolMasterActorInstrumentation.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/DatadogAsyncHandlerWrapper.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/DatadogAsyncHandlerWrapper.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/DatadogAsyncHandlerWrapper.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/DatadogAsyncHandlerWrapper.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/DatadogServerRequestResponseFlowWrapper.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/DatadogServerRequestResponseFlowWrapper.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/DatadogServerRequestResponseFlowWrapper.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/DatadogServerRequestResponseFlowWrapper.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/DatadogWrapperHelper.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/DatadogWrapperHelper.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/DatadogWrapperHelper.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/DatadogWrapperHelper.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/DefaultExceptionHandlerInstrumentation.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/DefaultExceptionHandlerInstrumentation.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/DefaultExceptionHandlerInstrumentation.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/DefaultExceptionHandlerInstrumentation.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/MarkSpanAsErroredPF.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/MarkSpanAsErroredPF.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/MarkSpanAsErroredPF.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/MarkSpanAsErroredPF.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/RecoverFromBlockedExceptionPF.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/RecoverFromBlockedExceptionPF.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/RecoverFromBlockedExceptionPF.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/RecoverFromBlockedExceptionPF.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/UriAdapter.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/UriAdapter.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/UriAdapter.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/UriAdapter.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/AkkaBlockResponseFunction.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/AkkaBlockResponseFunction.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/AkkaBlockResponseFunction.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/AkkaBlockResponseFunction.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/BlockingResponseHelper.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/BlockingResponseHelper.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/BlockingResponseHelper.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/BlockingResponseHelper.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/Bug4304Instrumentation.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/Bug4304Instrumentation.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/Bug4304Instrumentation.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/Bug4304Instrumentation.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/ConfigProvideRemoteAddressHeaderInstrumentation.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/ConfigProvideRemoteAddressHeaderInstrumentation.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/ConfigProvideRemoteAddressHeaderInstrumentation.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/ConfigProvideRemoteAddressHeaderInstrumentation.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/FormDataToStrictInstrumentation.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/FormDataToStrictInstrumentation.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/FormDataToStrictInstrumentation.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/FormDataToStrictInstrumentation.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/JacksonUnmarshallerInstrumentation.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/JacksonUnmarshallerInstrumentation.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/JacksonUnmarshallerInstrumentation.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/JacksonUnmarshallerInstrumentation.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/MultipartUnmarshallersInstrumentation.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/MultipartUnmarshallersInstrumentation.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/MultipartUnmarshallersInstrumentation.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/MultipartUnmarshallersInstrumentation.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/PredefinedFromEntityUnmarshallersInstrumentation.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/PredefinedFromEntityUnmarshallersInstrumentation.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/PredefinedFromEntityUnmarshallersInstrumentation.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/PredefinedFromEntityUnmarshallersInstrumentation.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/ScalaListCollector.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/ScalaListCollector.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/ScalaListCollector.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/ScalaListCollector.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/ScalaListCollectorMuzzleReferences.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/ScalaListCollectorMuzzleReferences.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/ScalaListCollectorMuzzleReferences.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/ScalaListCollectorMuzzleReferences.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/SprayUnmarshallerInstrumentation.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/SprayUnmarshallerInstrumentation.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/SprayUnmarshallerInstrumentation.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/SprayUnmarshallerInstrumentation.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/StrictFormCompanionInstrumentation.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/StrictFormCompanionInstrumentation.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/StrictFormCompanionInstrumentation.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/StrictFormCompanionInstrumentation.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/UnmarshallerHelpers.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/UnmarshallerHelpers.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/UnmarshallerHelpers.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/appsec/UnmarshallerHelpers.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/CookieDirectivesInstrumentation.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/CookieDirectivesInstrumentation.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/CookieDirectivesInstrumentation.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/CookieDirectivesInstrumentation.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/CookieHeaderInstrumentation.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/CookieHeaderInstrumentation.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/CookieHeaderInstrumentation.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/CookieHeaderInstrumentation.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/ExtractDirectivesInstrumentation.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/ExtractDirectivesInstrumentation.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/ExtractDirectivesInstrumentation.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/ExtractDirectivesInstrumentation.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/FormDataInstrumentation.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/FormDataInstrumentation.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/FormDataInstrumentation.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/FormDataInstrumentation.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/FormFieldDirectivesInstrumentation.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/FormFieldDirectivesInstrumentation.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/FormFieldDirectivesInstrumentation.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/FormFieldDirectivesInstrumentation.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/HeaderNameCallSite.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/HeaderNameCallSite.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/HeaderNameCallSite.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/HeaderNameCallSite.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/HttpHeaderSubclassesInstrumentation.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/HttpHeaderSubclassesInstrumentation.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/HttpHeaderSubclassesInstrumentation.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/HttpHeaderSubclassesInstrumentation.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/HttpRequestInstrumentation.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/HttpRequestInstrumentation.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/HttpRequestInstrumentation.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/HttpRequestInstrumentation.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/MakeTaintableInstrumentation.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/MakeTaintableInstrumentation.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/MakeTaintableInstrumentation.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/MakeTaintableInstrumentation.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/MarshallingDirectivesInstrumentation.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/MarshallingDirectivesInstrumentation.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/MarshallingDirectivesInstrumentation.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/MarshallingDirectivesInstrumentation.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/ParameterDirectivesInstrumentation.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/ParameterDirectivesInstrumentation.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/ParameterDirectivesInstrumentation.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/ParameterDirectivesInstrumentation.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/PathMatcherInstrumentation.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/PathMatcherInstrumentation.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/PathMatcherInstrumentation.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/PathMatcherInstrumentation.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/RequestContextInstrumentation.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/RequestContextInstrumentation.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/RequestContextInstrumentation.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/RequestContextInstrumentation.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/TraitMethodMatchers.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/TraitMethodMatchers.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/TraitMethodMatchers.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/TraitMethodMatchers.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/UnmarshallerInstrumentation.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/UnmarshallerInstrumentation.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/UnmarshallerInstrumentation.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/UnmarshallerInstrumentation.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/UriInstrumentation.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/UriInstrumentation.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/UriInstrumentation.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/UriInstrumentation.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/ScalaToJava.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/ScalaToJava.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/ScalaToJava.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/ScalaToJava.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/TaintCookieFunction.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/TaintCookieFunction.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/TaintCookieFunction.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/TaintCookieFunction.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/TaintFutureHelper.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/TaintFutureHelper.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/TaintFutureHelper.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/TaintFutureHelper.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/TaintMapFunction.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/TaintMapFunction.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/TaintMapFunction.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/TaintMapFunction.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/TaintMultiMapFunction.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/TaintMultiMapFunction.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/TaintMultiMapFunction.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/TaintMultiMapFunction.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/TaintOptionalCookieFunction.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/TaintOptionalCookieFunction.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/TaintOptionalCookieFunction.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/TaintOptionalCookieFunction.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/TaintRequestContextFunction.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/TaintRequestContextFunction.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/TaintRequestContextFunction.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/TaintRequestContextFunction.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/TaintRequestFunction.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/TaintRequestFunction.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/TaintRequestFunction.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/TaintRequestFunction.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/TaintSeqFunction.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/TaintSeqFunction.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/TaintSeqFunction.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/TaintSeqFunction.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/TaintSingleParameterFunction.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/TaintSingleParameterFunction.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/TaintSingleParameterFunction.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/TaintSingleParameterFunction.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/TaintUnmarshaller.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/TaintUnmarshaller.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/TaintUnmarshaller.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/TaintUnmarshaller.java diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/TaintUriFunction.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/TaintUriFunction.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/TaintUriFunction.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/iast/helpers/TaintUriFunction.java diff --git a/dd-java-agent/instrumentation/akka-http-10.2-iast/build.gradle b/dd-java-agent/instrumentation/akka-http/akka-http-10.2-iast/build.gradle similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.2-iast/build.gradle rename to dd-java-agent/instrumentation/akka-http/akka-http-10.2-iast/build.gradle diff --git a/dd-java-agent/instrumentation/akka-http-10.2-iast/gradle.lockfile b/dd-java-agent/instrumentation/akka-http/akka-http-10.2-iast/gradle.lockfile similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.2-iast/gradle.lockfile rename to dd-java-agent/instrumentation/akka-http/akka-http-10.2-iast/gradle.lockfile diff --git a/dd-java-agent/instrumentation/akka-http-10.2-iast/src/main/java/datadog/trace/instrumentation/akkahttp102/iast/FormFieldDirectivesImplInstrumentation.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.2-iast/src/main/java/datadog/trace/instrumentation/akkahttp102/iast/FormFieldDirectivesImplInstrumentation.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.2-iast/src/main/java/datadog/trace/instrumentation/akkahttp102/iast/FormFieldDirectivesImplInstrumentation.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.2-iast/src/main/java/datadog/trace/instrumentation/akkahttp102/iast/FormFieldDirectivesImplInstrumentation.java diff --git a/dd-java-agent/instrumentation/akka-http-10.2-iast/src/main/java/datadog/trace/instrumentation/akkahttp102/iast/ParameterDirectivesImplInstrumentation.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.2-iast/src/main/java/datadog/trace/instrumentation/akkahttp102/iast/ParameterDirectivesImplInstrumentation.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.2-iast/src/main/java/datadog/trace/instrumentation/akkahttp102/iast/ParameterDirectivesImplInstrumentation.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.2-iast/src/main/java/datadog/trace/instrumentation/akkahttp102/iast/ParameterDirectivesImplInstrumentation.java diff --git a/dd-java-agent/instrumentation/akka-http-10.2-iast/src/main/java/datadog/trace/instrumentation/akkahttp102/iast/helpers/TaintParametersFunction.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.2-iast/src/main/java/datadog/trace/instrumentation/akkahttp102/iast/helpers/TaintParametersFunction.java similarity index 100% rename from dd-java-agent/instrumentation/akka-http-10.2-iast/src/main/java/datadog/trace/instrumentation/akkahttp102/iast/helpers/TaintParametersFunction.java rename to dd-java-agent/instrumentation/akka-http/akka-http-10.2-iast/src/main/java/datadog/trace/instrumentation/akkahttp102/iast/helpers/TaintParametersFunction.java diff --git a/dd-java-agent/instrumentation/akka-http/akka-http-10.6/build.gradle b/dd-java-agent/instrumentation/akka-http/akka-http-10.6/build.gradle new file mode 100644 index 00000000000..0c6522331c3 --- /dev/null +++ b/dd-java-agent/instrumentation/akka-http/akka-http-10.6/build.gradle @@ -0,0 +1,80 @@ +// Set properties before any plugins get loaded +ext { + minJavaVersionForTests = JavaVersion.VERSION_11 +} + +apply from: "$rootDir/gradle/java.gradle" +apply plugin: 'scala' +apply plugin: 'call-site-instrumentation' + + +muzzle { + pass { + group = 'com.typesafe.akka' + module = 'akka-http_2.13' + versions = "[10.6.0,)" + javaVersion = "11" + extraDependency 'com.typesafe.akka:akka-stream_2.13:2.9.0' + extraRepository('akka', 'https://repo.akka.io/maven') + assertInverse = true + } + +} + +repositories { + maven { + url "https://repo.akka.io/maven" + } +} + +addTestSuiteForDir('latestDepTest', 'test') + +[compileMain_java11Java, compileTestScala, compileLatestDepTestScala].each { + it.configure { + setJavaVersion(it, 11) + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + } +} + +compileTestGroovy { + javaLauncher = getJavaLauncherFor(11) + dependsOn compileTestScala + classpath += files(compileTestScala.destinationDirectory) +} + +compileLatestDepTestGroovy { + javaLauncher = getJavaLauncherFor(11) + dependsOn compileLatestDepTestScala + classpath += files(compileLatestDepTestScala.destinationDirectory) +} + +dependencies { + main_java11CompileOnly libs.scala213 + main_java11CompileOnly group: 'com.typesafe.akka', name: 'akka-http_2.13', version: '10.6.0' + main_java11CompileOnly group: 'com.typesafe.akka', name: 'akka-actor_2.13', version: '2.9.0' + + //testImplementation group: 'com.squareup.okhttp3', name: 'okhttp', version: '3.6.0' + testImplementation group: 'com.typesafe.akka', name: 'akka-http_2.13', version: '10.6.0' + testImplementation group: 'com.typesafe.akka', name: 'akka-stream_2.13', version: '2.9.0' + testImplementation group: 'com.typesafe.akka', name: 'akka-http-jackson_2.13', version: '10.6.0' + testImplementation group: 'com.typesafe.akka', name: 'akka-http-spray-json_2.13', version: '10.6.0' + testImplementation libs.scala213 + testImplementation project(':dd-java-agent:instrumentation:trace-annotation') + testImplementation project(':dd-java-agent:instrumentation:akka-concurrent') + testImplementation project(':dd-java-agent:instrumentation:scala-concurrent') + testImplementation project(':dd-java-agent:instrumentation:akka-http:akka-http-10.0') + testImplementation project(':dd-java-agent:instrumentation:scala-promise:scala-promise-2.13') + + latestDepTestImplementation group: 'com.typesafe.akka', name: 'akka-http_2.13', version: '+' + latestDepTestImplementation group: 'com.typesafe.akka', name: 'akka-stream_2.13', version: '+' + latestDepTestImplementation group: 'com.typesafe.akka', name: 'akka-pki_2.13', version: '+' + latestDepTestImplementation group: 'com.typesafe.akka', name: 'akka-protobuf-v3_2.13', version: '+' + latestDepTestImplementation group: 'com.typesafe.akka', name: 'akka-http-jackson_2.13', version: '+' + latestDepTestImplementation group: 'com.typesafe.akka', name: 'akka-http-spray-json_2.13', version: '+' + latestDepTestImplementation group: 'org.scala-lang.modules', name: 'scala-java8-compat_2.13', version: '1.0.+' +} + +configurations.getByName("latestDepTestRuntimeClasspath").resolutionStrategy { + it.force libs.slf4j +} diff --git a/dd-java-agent/instrumentation/akka-http/akka-http-10.6/src/main/java/datadog/trace/instrumentation/akkahttp106/AkkaHttpSingleRequestInstrumentation.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.6/src/main/java/datadog/trace/instrumentation/akkahttp106/AkkaHttpSingleRequestInstrumentation.java new file mode 100644 index 00000000000..688a9f06475 --- /dev/null +++ b/dd-java-agent/instrumentation/akka-http/akka-http-10.6/src/main/java/datadog/trace/instrumentation/akkahttp106/AkkaHttpSingleRequestInstrumentation.java @@ -0,0 +1,39 @@ +package datadog.trace.instrumentation.akkahttp106; + +import static datadog.trace.agent.tooling.bytebuddy.matcher.NameMatchers.named; +import static net.bytebuddy.matcher.ElementMatchers.takesArgument; + +import com.google.auto.service.AutoService; +import datadog.trace.agent.tooling.Instrumenter; +import datadog.trace.agent.tooling.InstrumenterModule; + +@AutoService(InstrumenterModule.class) +public final class AkkaHttpSingleRequestInstrumentation extends InstrumenterModule.Tracing + implements Instrumenter.ForSingleType { + public AkkaHttpSingleRequestInstrumentation() { + super("akka-http", "akka-http-client"); + } + + @Override + public String instrumentedType() { + return "akka.http.scaladsl.HttpExt"; + } + + @Override + public String[] helperClassNames() { + return new String[] { + packageName + ".AkkaHttpClientHelpers", + packageName + ".AkkaHttpClientHelpers$OnCompleteHandler", + packageName + ".AkkaHttpClientHelpers$AkkaHttpHeaders", + packageName + ".AkkaHttpClientHelpers$HasSpanHeader", + packageName + ".AkkaHttpClientDecorator", + }; + } + + @Override + public void methodAdvice(MethodTransformer transformer) { + transformer.applyAdvice( + named("singleRequest").and(takesArgument(0, named("akka.http.scaladsl.model.HttpRequest"))), + packageName + ".SingleRequestAdvice"); + } +} diff --git a/dd-java-agent/instrumentation/akka-http/akka-http-10.6/src/main/java11/datadog/trace/instrumentation/akkahttp106/AkkaHttpClientDecorator.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.6/src/main/java11/datadog/trace/instrumentation/akkahttp106/AkkaHttpClientDecorator.java new file mode 100644 index 00000000000..35f5b54e734 --- /dev/null +++ b/dd-java-agent/instrumentation/akka-http/akka-http-10.6/src/main/java11/datadog/trace/instrumentation/akkahttp106/AkkaHttpClientDecorator.java @@ -0,0 +1,52 @@ +package datadog.trace.instrumentation.akkahttp106; + +import akka.http.javadsl.model.HttpHeader; +import akka.http.scaladsl.model.HttpRequest; +import akka.http.scaladsl.model.HttpResponse; +import datadog.trace.bootstrap.instrumentation.api.URIUtils; +import datadog.trace.bootstrap.instrumentation.api.UTF8BytesString; +import datadog.trace.bootstrap.instrumentation.decorator.HttpClientDecorator; +import java.net.URI; +import java.net.URISyntaxException; + +public class AkkaHttpClientDecorator extends HttpClientDecorator { + public static final CharSequence AKKA_HTTP_CLIENT = UTF8BytesString.create("akka-http-client"); + public static final AkkaHttpClientDecorator DECORATE = new AkkaHttpClientDecorator(); + public static final CharSequence AKKA_CLIENT_REQUEST = + UTF8BytesString.create(DECORATE.operationName()); + + @Override + protected String[] instrumentationNames() { + return new String[] {"akka-http", "akka-http-client"}; + } + + @Override + protected CharSequence component() { + return AKKA_HTTP_CLIENT; + } + + @Override + protected String method(final HttpRequest httpRequest) { + return httpRequest.method().value(); + } + + @Override + protected URI url(final HttpRequest httpRequest) throws URISyntaxException { + return URIUtils.safeParse(httpRequest.uri().toString()); + } + + @Override + protected int status(final HttpResponse httpResponse) { + return httpResponse.status().intValue(); + } + + @Override + protected String getRequestHeader(HttpRequest request, String headerName) { + return request.getHeader(headerName).map(HttpHeader::value).orElse(null); + } + + @Override + protected String getResponseHeader(HttpResponse response, String headerName) { + return response.getHeader(headerName).map(HttpHeader::value).orElse(null); + } +} diff --git a/dd-java-agent/instrumentation/akka-http/akka-http-10.6/src/main/java11/datadog/trace/instrumentation/akkahttp106/AkkaHttpClientHelpers.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.6/src/main/java11/datadog/trace/instrumentation/akkahttp106/AkkaHttpClientHelpers.java new file mode 100644 index 00000000000..b9e0fc65042 --- /dev/null +++ b/dd-java-agent/instrumentation/akka-http/akka-http-10.6/src/main/java11/datadog/trace/instrumentation/akkahttp106/AkkaHttpClientHelpers.java @@ -0,0 +1,83 @@ +package datadog.trace.instrumentation.akkahttp106; + +import akka.http.javadsl.model.headers.RawHeader; +import akka.http.scaladsl.model.HttpRequest; +import akka.http.scaladsl.model.HttpResponse; +import akka.http.scaladsl.model.headers.CustomHeader; +import datadog.trace.bootstrap.instrumentation.api.AgentPropagation; +import datadog.trace.bootstrap.instrumentation.api.AgentSpan; +import scala.runtime.AbstractFunction1; +import scala.util.Try; + +public final class AkkaHttpClientHelpers { + public static class OnCompleteHandler extends AbstractFunction1, Void> { + private final AgentSpan span; + + public OnCompleteHandler(final AgentSpan span) { + this.span = span; + } + + @Override + public Void apply(final Try result) { + if (result.isSuccess()) { + AkkaHttpClientDecorator.DECORATE.onResponse(span, result.get()); + } else { + AkkaHttpClientDecorator.DECORATE.onError(span, result.failed().get()); + } + AkkaHttpClientDecorator.DECORATE.beforeFinish(span); + span.finish(); + return null; + } + } + + public static class AkkaHttpHeaders implements AgentPropagation.Setter { + private HttpRequest request; + // Did this request have a span when the AkkaHttpHeaders object was created? + private boolean hadSpan; + + public AkkaHttpHeaders(final HttpRequest request) { + hadSpan = request != null && request.getHeader("x-datadog-request-has-span").isPresent(); + if (hadSpan || request == null) { + this.request = request; + } else { + this.request = (HttpRequest) request.addHeader(new HasSpanHeader()); + } + } + + public boolean hadSpan() { + return hadSpan; + } + + @Override + public void set(final HttpRequest carrier, final String key, final String value) { + request = (HttpRequest) request.addHeader(RawHeader.create(key, value)); + } + + public HttpRequest getRequest() { + return request; + } + } + + // Custom header to mark that this request has a span associated with it + public static class HasSpanHeader extends CustomHeader { + @Override + public String name() { + return "x-datadog-request-has-span"; + } + + @Override + public String value() { + return "true"; + } + + @Override + public boolean renderInRequests() { + return false; + } + + @Override + public boolean renderInResponses() { + return false; + } + } +} diff --git a/dd-java-agent/instrumentation/akka-http/akka-http-10.6/src/main/java11/datadog/trace/instrumentation/akkahttp106/SingleRequestAdvice.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.6/src/main/java11/datadog/trace/instrumentation/akkahttp106/SingleRequestAdvice.java new file mode 100644 index 00000000000..8e987bc8ec8 --- /dev/null +++ b/dd-java-agent/instrumentation/akka-http/akka-http-10.6/src/main/java11/datadog/trace/instrumentation/akkahttp106/SingleRequestAdvice.java @@ -0,0 +1,63 @@ +package datadog.trace.instrumentation.akkahttp106; + +import static datadog.trace.bootstrap.instrumentation.api.AgentTracer.activateSpan; +import static datadog.trace.bootstrap.instrumentation.api.AgentTracer.propagate; +import static datadog.trace.bootstrap.instrumentation.api.AgentTracer.startSpan; + +import akka.http.scaladsl.HttpExt; +import akka.http.scaladsl.model.HttpRequest; +import akka.http.scaladsl.model.HttpResponse; +import datadog.trace.bootstrap.instrumentation.api.AgentScope; +import datadog.trace.bootstrap.instrumentation.api.AgentSpan; +import datadog.trace.bootstrap.instrumentation.decorator.HttpClientDecorator; +import net.bytebuddy.asm.Advice; +import scala.concurrent.Future; + +public class SingleRequestAdvice { + @Advice.OnMethodEnter(suppress = Throwable.class) + public static AgentScope methodEnter( + @Advice.Argument(value = 0, readOnly = false) HttpRequest request) { + final AkkaHttpClientHelpers.AkkaHttpHeaders headers = + new AkkaHttpClientHelpers.AkkaHttpHeaders(request); + if (headers.hadSpan()) { + return null; + } + + final AgentSpan span = startSpan(AkkaHttpClientDecorator.AKKA_CLIENT_REQUEST); + AkkaHttpClientDecorator.DECORATE.afterStart(span); + AkkaHttpClientDecorator.DECORATE.onRequest(span, request); + + if (request != null) { + propagate().inject(span, request, headers); + propagate() + .injectPathwayContext( + span, request, headers, HttpClientDecorator.CLIENT_PATHWAY_EDGE_TAGS); + // Request is immutable, so we have to assign new value once we update headers + request = headers.getRequest(); + } + return activateSpan(span); + } + + @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) + public static void methodExit( + @Advice.This final HttpExt thiz, + @Advice.Return final Future responseFuture, + @Advice.Enter final AgentScope scope, + @Advice.Thrown final Throwable throwable) { + if (scope == null) { + return; + } + + final AgentSpan span = scope.span(); + + if (throwable == null) { + responseFuture.onComplete( + new AkkaHttpClientHelpers.OnCompleteHandler(span), thiz.system().dispatcher()); + } else { + AkkaHttpClientDecorator.DECORATE.onError(span, throwable); + AkkaHttpClientDecorator.DECORATE.beforeFinish(span); + span.finish(); + } + scope.close(); + } +} diff --git a/dd-java-agent/instrumentation/akka-http/akka-http-10.6/src/test/groovy/AkkaHttp102ServerInstrumentationTests.groovy b/dd-java-agent/instrumentation/akka-http/akka-http-10.6/src/test/groovy/AkkaHttp102ServerInstrumentationTests.groovy new file mode 100644 index 00000000000..a8c4134f9f5 --- /dev/null +++ b/dd-java-agent/instrumentation/akka-http/akka-http-10.6/src/test/groovy/AkkaHttp102ServerInstrumentationTests.groovy @@ -0,0 +1,55 @@ +import datadog.trace.agent.test.base.HttpServer + +class AkkaHttp102ServerInstrumentationBindFlowTest extends AkkaHttpServerInstrumentationTest { + @Override + HttpServer server() { + return new AkkaHttpTestWebServer(AkkaHttp102TestWebServer.ServerBuilderBindFlow()) + } + + @Override + boolean redirectHasBody() { + return true + } +} + +class AkkaHttp102ServerInstrumentationBindTest extends AkkaHttpServerInstrumentationTest { + @Override + HttpServer server() { + return new AkkaHttpTestWebServer(AkkaHttp102TestWebServer.ServerBuilderBind()) + } +} + +class AkkaHttp102ServerInstrumentationBindSyncTest extends AkkaHttpServerInstrumentationTest { + @Override + HttpServer server() { + return new AkkaHttpTestWebServer(AkkaHttp102TestWebServer.ServerBuilderBindSync()) + } + + // we test body endpoints only on the async tests + @Override + boolean testRequestBody() { + false + } + + @Override + boolean testBodyMultipart() { + false + } + + @Override + boolean testBodyJson() { + false + } + + @Override + boolean testBodyUrlencoded() { + false + } +} + +class AkkaHttp102ServerInstrumentationBindAsyncHttp2Test extends AkkaHttpServerInstrumentationTest { + @Override + HttpServer server() { + return new AkkaHttpTestWebServer(AkkaHttp102TestWebServer.ServerBuilderBindHttp2()) + } +} diff --git a/dd-java-agent/instrumentation/akka-http/akka-http-10.6/src/test/groovy/AkkaHttpClientInstrumentationTest.groovy b/dd-java-agent/instrumentation/akka-http/akka-http-10.6/src/test/groovy/AkkaHttpClientInstrumentationTest.groovy new file mode 100644 index 00000000000..7d4513b5570 --- /dev/null +++ b/dd-java-agent/instrumentation/akka-http/akka-http-10.6/src/test/groovy/AkkaHttpClientInstrumentationTest.groovy @@ -0,0 +1,151 @@ +import akka.actor.ActorSystem +import akka.http.javadsl.Http +import akka.http.javadsl.model.HttpMethods +import akka.http.javadsl.model.HttpRequest +import akka.http.javadsl.model.HttpResponse +import akka.http.javadsl.model.headers.RawHeader +import akka.http.scaladsl.settings.ConnectionPoolSettings +import datadog.trace.agent.test.base.HttpClientTest +import datadog.trace.agent.test.naming.TestingGenericHttpNamingConventions +import datadog.trace.api.DDSpanTypes +import datadog.trace.bootstrap.instrumentation.api.Tags +import datadog.trace.instrumentation.akkahttp106.AkkaHttpClientDecorator +import scala.compat.java8.FutureConverters +import scala.concurrent.Future +import spock.lang.Shared +import spock.lang.Timeout + +import java.util.concurrent.CompletionStage + +@Timeout(5) +abstract class AkkaHttpClientInstrumentationTest extends HttpClientTest { + @Shared + ActorSystem system = ActorSystem.create() + + abstract CompletionStage doRequest(HttpRequest request) + + @Override + int doRequest(String method, URI uri, Map headers, String body, Closure callback) { + def request = HttpRequest.create(uri.toString()) + .withMethod(HttpMethods.lookup(method).get()) + .addHeaders(headers.collect { RawHeader.create(it.key, it.value) }) + + def response + try { + response = doRequest(request) + .whenComplete { result, error -> + callback?.call() + } + .toCompletableFuture() + .get() + } finally { + // Since the spans are completed in an async callback, we need to wait here + blockUntilChildSpansFinished(1) + } + return response.status().intValue() + } + + @Override + CharSequence component() { + return AkkaHttpClientDecorator.DECORATE.component() + } + + @Override + boolean testRedirects() { + false + } + + @Override + boolean testRemoteConnection() { + // Not sure how to properly set timeouts... + return false + } + + def "singleRequest exception trace"() { + when: + Http.get(system).singleRequest(null) + + then: + def exception = thrown NullPointerException + assertTraces(1) { + trace(1) { + span { + parent() + operationName operation() + resourceName operation() // resource name is not set so defaults to operationName + spanType DDSpanTypes.HTTP_CLIENT + errored true + tags { + "$Tags.COMPONENT" "akka-http-client" + "$Tags.SPAN_KIND" Tags.SPAN_KIND_CLIENT + errorTags(exception) + defaultTags(false, false) + } + } + } + } + } +} + + +abstract class AkkaHttpJavaClientInstrumentationTest extends AkkaHttpClientInstrumentationTest { + @Override + CompletionStage doRequest(HttpRequest request) { + return Http.get(system).singleRequest(request) + } +} + + +abstract class AkkaHttpScalaClientInstrumentationTest extends AkkaHttpClientInstrumentationTest { + @Override + CompletionStage doRequest(HttpRequest request) { + def http = akka.http.scaladsl.Http.apply(system) + def sRequest = (akka.http.scaladsl.model.HttpRequest) request + Future f = http.singleRequest(sRequest, http.defaultClientHttpsContext(), + (ConnectionPoolSettings) ConnectionPoolSettings.apply(system), system.log()) + return FutureConverters.toJava(f) + } +} + +class AkkaHttpJavaClientInstrumentationV0Test extends AkkaHttpJavaClientInstrumentationTest { + + @Override + int version() { + return 0 + } + + @Override + String service() { + return null + } + + @Override + String operation() { + return "akka-http.client.request" + } +} + +class AkkaHttpJavaClientInstrumentationV1ForkedTest extends AkkaHttpJavaClientInstrumentationTest implements TestingGenericHttpNamingConventions.ClientV1 { +} + +class AkkaHttpScalaClientInstrumentationV0Test extends AkkaHttpScalaClientInstrumentationTest { + + @Override + int version() { + return 0 + } + + @Override + String service() { + return null + } + + @Override + String operation() { + return "akka-http.client.request" + } +} + +class AkkaHttpScalaClientInstrumentationV1ForkedTest extends AkkaHttpScalaClientInstrumentationTest implements TestingGenericHttpNamingConventions.ClientV1{ + +} diff --git a/dd-java-agent/instrumentation/akka-http/akka-http-10.6/src/test/groovy/AkkaHttpServerInstrumentationTest.groovy b/dd-java-agent/instrumentation/akka-http/akka-http-10.6/src/test/groovy/AkkaHttpServerInstrumentationTest.groovy new file mode 100644 index 00000000000..397de4f2613 --- /dev/null +++ b/dd-java-agent/instrumentation/akka-http/akka-http-10.6/src/test/groovy/AkkaHttpServerInstrumentationTest.groovy @@ -0,0 +1,319 @@ +import static datadog.trace.agent.test.base.HttpServerTest.ServerEndpoint.BODY_JSON +import static datadog.trace.agent.test.base.HttpServerTest.ServerEndpoint.BODY_MULTIPART +import static datadog.trace.agent.test.base.HttpServerTest.ServerEndpoint.SUCCESS +import static org.junit.Assume.assumeTrue + +import datadog.trace.agent.test.base.HttpServer +import datadog.trace.agent.test.base.HttpServerTest +import datadog.trace.agent.test.naming.TestingGenericHttpNamingConventions +import datadog.trace.agent.test.utils.ThreadUtils +import datadog.trace.instrumentation.akkahttp.AkkaHttpServerDecorator +import okhttp3.HttpUrl +import okhttp3.MultipartBody +import okhttp3.Request +import okhttp3.RequestBody +import okhttp3.Response +import spock.lang.Shared + +import java.util.concurrent.atomic.AtomicInteger + +abstract class AkkaHttpServerInstrumentationTest extends HttpServerTest { + + @Override + String component() { + return AkkaHttpServerDecorator.DECORATE.component() + } + + @Override + String expectedOperationName() { + return "akka-http.request" + } + + @Override + boolean testExceptionBody() { + false + } + + @Override + boolean hasExtraErrorInformation() { + return true + } + + @Override + protected boolean enabledFinishTimingChecks() { + true + } + + @Override + boolean changesAll404s() { + true + } + + @Override + boolean testBlocking() { + true + } + + @Override + boolean testBlockingOnResponse() { + true + } + + @Override + boolean testRequestBody() { + true + } + + @Override + boolean testBodyUrlencoded() { + true + } + + @Override + boolean testBodyMultipart() { + true + } + + @Override + boolean testBodyJson() { + true + } + + @Override + boolean isRequestBodyNoStreaming() { + true + } + + @Override + boolean testBadUrl() { + false + } + + @Shared + def totalInvocations = 200 + + @Shared + AtomicInteger counter = new AtomicInteger(0) + + void doAndValidateRequest(int id) { + def type = id & 1 ? "p" : "f" + String url = address.resolve("/injected-id/${type}ing/$id") + def traceId = totalInvocations + id + def request = new Request.Builder().url(url).get().header("x-datadog-trace-id", traceId.toString()).build() + def response = client.newCall(request).execute() + def responseBodyStr = response.body().string() + assert responseBodyStr == "${type}ong $id -> $traceId" + assert response.code() == 200 + } + + def "propagate trace id when we ping akka-http concurrently"() { + expect: + ThreadUtils.runConcurrently(10, totalInvocations, { + def id = counter.incrementAndGet() + doAndValidateRequest(id) + }) + + and: + TEST_WRITER.waitForTraces(totalInvocations) + } + + def 'test instrumentation gateway multipart request body — strict variant'() { + setup: + assumeTrue(testBodyMultipart()) + def body = new MultipartBody.Builder() + .setType(MultipartBody.FORM) + .addFormDataPart('a', 'x') + .build() + + def url = HttpUrl.get(BODY_MULTIPART.resolve(address)).newBuilder() + .encodedQuery('variant=strictUnmarshaller') + .build() + def request = new Request.Builder() + .url(url) + .method('POST', body) + .build() + def response = client.newCall(request).execute() + if (isDataStreamsEnabled()) { + TEST_DATA_STREAMS_WRITER.waitForGroups(1) + } + + expect: + response.body().charStream().text == '[a:[x]]' + + when: + TEST_WRITER.waitForTraces(1) + + then: + TEST_WRITER.get(0).any { + it.getTag('request.body.converted') == '[a:[x]]' + } + } + + def 'test instrumentation gateway json request body — spray variant'() { + assumeTrue(testBodyJson()) + + setup: + def url = HttpUrl.get(BODY_JSON.resolve(address)).newBuilder() + .encodedQuery('variant=spray') + .build() + def request = new Request.Builder() + .url(url) + .method('POST', RequestBody.create(okhttp3.MediaType.get('application/json'), '{"a":"x"}\n')) + .build() + def response = client.newCall(request).execute() + if (isDataStreamsEnabled()) { + TEST_DATA_STREAMS_WRITER.waitForGroups(1) + } + + expect: + response.body().charStream().text == '{"a":"x"}' + + when: + TEST_WRITER.waitForTraces(1) + + then: + TEST_WRITER.get(0).any { + it.getTag('request.body.converted') == '[a:[x]]' + } + } + + void 'content length and type are provided to IG on strict responses'() { + setup: + Request request = request(SUCCESS, 'GET', null) + .header(IG_EXTRA_SPAN_NAME_HEADER, 'ig-span') + .header(IG_ASK_FOR_RESPONSE_HEADER_TAGS_HEADER, 'true') + .build() + Response response = client.newCall(request).execute() + if (isDataStreamsEnabled()) { + TEST_DATA_STREAMS_WRITER.waitForGroups(1) + } + + expect: + response.body().charStream().text == SUCCESS.body + + when: + TEST_WRITER.waitForTraces(1) + def tags = TEST_WRITER.get(0).find { it.spanName == 'ig-span' }.tags + + then: + tags['response.header.content-type'] != null + tags['response.header.content-length'] == SUCCESS.body.length() as String + } +} + +abstract class AkkaHttpServerInstrumentationSyncTest extends AkkaHttpServerInstrumentationTest { + @Override + HttpServer server() { + return new AkkaHttpTestWebServer(AkkaHttpTestWebServer.BindAndHandleSync()) + } + + @Override + String expectedOperationName() { + return operation() + } + + // we test body endpoints only on the async tests + @Override + boolean testRequestBody() { + false + } + + @Override + boolean testBodyMultipart() { + false + } + + @Override + boolean testBodyJson() { + false + } + + @Override + boolean testBodyUrlencoded() { + false + } +} + +class AkkaHttpServerInstrumentationSyncV0Test extends AkkaHttpServerInstrumentationSyncTest { + @Override + int version() { + return 0 + } + + @Override + String service() { + return null + } + + @Override + String operation() { + return "akka-http.request" + } +} + +class AkkaHttpServerInstrumentationSyncV1ForkedTest extends AkkaHttpServerInstrumentationSyncTest implements TestingGenericHttpNamingConventions.ServerV1 { +} + +class AkkaHttpServerInstrumentationAsyncTest extends AkkaHttpServerInstrumentationTest { + @Override + HttpServer server() { + return new AkkaHttpTestWebServer(AkkaHttpTestWebServer.BindAndHandleAsync()) + } +} + +class AkkaHttpServerInstrumentationBindAndHandleTest extends AkkaHttpServerInstrumentationTest { + + @Override + HttpServer server() { + AkkaHttpTestWebServer server = new AkkaHttpTestWebServer(AkkaHttpTestWebServer.BindAndHandle()) + server + } + + @Override + boolean redirectHasBody() { + return true + } + + @Override + boolean testBodyMultipart() { + true + } + + @Override + boolean testBodyUrlencoded() { + true + } +} + +class AkkaHttpServerInstrumentationBindAndHandleAsyncWithRouteAsyncHandlerTest extends AkkaHttpServerInstrumentationTest { + String akkaHttpVersion + + @Override + HttpServer server() { + AkkaHttpTestWebServer server = new AkkaHttpTestWebServer(AkkaHttpTestWebServer.BindAndHandleAsyncWithRouteAsyncHandler()) + akkaHttpVersion = server.system().settings().config().getString('akka.http.version') + server + } + + @Override + boolean redirectHasBody() { + return true + } + + @Override + boolean testBodyMultipart() { + true + } + + @Override + boolean testBodyUrlencoded() { + true + } +} + +class AkkaHttpServerInstrumentationAsyncHttp2Test extends AkkaHttpServerInstrumentationTest { + @Override + HttpServer server() { + return new AkkaHttpTestWebServer(AkkaHttpTestWebServer.BindAndHandleAsyncHttp2()) + } +} diff --git a/dd-java-agent/instrumentation/akka-http/akka-http-10.6/src/test/resources/application.conf b/dd-java-agent/instrumentation/akka-http/akka-http-10.6/src/test/resources/application.conf new file mode 100644 index 00000000000..7e7db624120 --- /dev/null +++ b/dd-java-agent/instrumentation/akka-http/akka-http-10.6/src/test/resources/application.conf @@ -0,0 +1,6 @@ +akka.http { + host-connection-pool { + // Limit maximum http backoff for tests + max-connection-backoff = 100ms + } +} diff --git a/dd-java-agent/instrumentation/akka-http/akka-http-10.6/src/test/scala/AkkaHttp102TestWebServer.scala b/dd-java-agent/instrumentation/akka-http/akka-http-10.6/src/test/scala/AkkaHttp102TestWebServer.scala new file mode 100644 index 00000000000..da4f15e839d --- /dev/null +++ b/dd-java-agent/instrumentation/akka-http/akka-http-10.6/src/test/scala/AkkaHttp102TestWebServer.scala @@ -0,0 +1,67 @@ +import AkkaHttpTestWebServer.Binder +import akka.actor.ActorSystem +import akka.http.scaladsl.Http +import akka.http.scaladsl.Http.ServerBinding +import akka.http.scaladsl.server.Route +import akka.stream.Materializer + +import scala.concurrent.Future + +object AkkaHttp102TestWebServer { + val ServerBuilderBindFlow: Binder = new Binder { + override def name: String = "server-builder-bind-flow" + override def bind(port: Int)( + implicit system: ActorSystem, + materializer: Materializer + ): Future[ServerBinding] = { + import materializer.executionContext + Http() + .newServerAt("localhost", port) + .withMaterializer(materializer) + .bindFlow(AkkaHttpTestWebServer.route) + } + } + + val ServerBuilderBind: Binder = new Binder { + override def name: String = "server-builder-bind" + override def bind(port: Int)( + implicit system: ActorSystem, + materializer: Materializer + ): Future[ServerBinding] = { + import materializer.executionContext + Http() + .newServerAt("localhost", port) + .withMaterializer(materializer) + .bind(AkkaHttpTestWebServer.asyncHandler) + } + } + + val ServerBuilderBindSync: Binder = new Binder { + override def name: String = "server-builder-bind-sync" + override def bind(port: Int)( + implicit system: ActorSystem, + materializer: Materializer + ): Future[ServerBinding] = { + import materializer.executionContext + Http() + .newServerAt("localhost", port) + .withMaterializer(materializer) + .bindSync(AkkaHttpTestWebServer.syncHandler) + } + } + + val ServerBuilderBindHttp2: Binder = new Binder { + override def name: String = "server-builder-bind-http2" + override def bind(port: Int)( + implicit system: ActorSystem, + materializer: Materializer + ): Future[ServerBinding] = { + import materializer.executionContext + Http() + .newServerAt("localhost", port) + .withMaterializer(materializer) + .adaptSettings(AkkaHttpTestWebServer.enableHttp2) + .bind(AkkaHttpTestWebServer.asyncHandler) + } + } +} diff --git a/dd-java-agent/instrumentation/akka-http/akka-http-10.6/src/test/scala/AkkaHttpTestWebServer.scala b/dd-java-agent/instrumentation/akka-http/akka-http-10.6/src/test/scala/AkkaHttpTestWebServer.scala new file mode 100644 index 00000000000..af0bc91b428 --- /dev/null +++ b/dd-java-agent/instrumentation/akka-http/akka-http-10.6/src/test/scala/AkkaHttpTestWebServer.scala @@ -0,0 +1,503 @@ +import AkkaHttpTestWebServer.Binder +import akka.actor.ActorSystem +import akka.http.javadsl.marshallers.jackson.Jackson +import akka.http.scaladsl.Http.ServerBinding +import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport +import akka.http.scaladsl.model.HttpEntity.apply +import akka.http.scaladsl.model.HttpMethods.{GET, POST} +import akka.http.scaladsl.model.Multipart.FormData +import akka.http.scaladsl.model.Multipart.FormData.BodyPart +import akka.http.scaladsl.model._ +import akka.http.scaladsl.model.headers.RawHeader +import akka.http.scaladsl.server.Directives._ +import akka.http.scaladsl.server._ +import akka.http.scaladsl.settings.ServerSettings +import akka.http.scaladsl.unmarshalling.PredefinedFromEntityUnmarshallers.defaultUrlEncodedFormDataUnmarshaller +import akka.http.scaladsl.unmarshalling.Unmarshaller.messageUnmarshallerFromEntityUnmarshaller +import akka.http.scaladsl.unmarshalling.{FromEntityUnmarshaller, MultipartUnmarshallers, Unmarshal, Unmarshaller} +import akka.http.scaladsl.util.FastFuture.EnhancedFuture +import akka.http.scaladsl.{Http, model} +import akka.stream.{ActorMaterializer, Materializer} +import com.typesafe.config.{Config, ConfigFactory, ConfigValueFactory} +import datadog.appsec.api.blocking.{Blocking, BlockingException} +import datadog.trace.agent.test.base.HttpServerTest.ServerEndpoint._ +import datadog.trace.agent.test.base.{HttpServer, HttpServerTest} +import datadog.trace.agent.test.utils.TraceUtils +import datadog.trace.bootstrap.instrumentation.api.AgentTracer +import datadog.trace.bootstrap.instrumentation.api.AgentTracer.activeSpan +import groovy.lang.Closure +import spray.json.{JsObject, JsString, JsValue, RootJsonFormat, deserializationError} + +import java.net.URI +import scala.concurrent.duration._ +import scala.concurrent.{Await, ExecutionContext, Future} +import scala.language.postfixOps +import scala.util.control.NonFatal + +class AkkaHttpTestWebServer(binder: Binder) extends HttpServer { + implicit val system: ActorSystem = { + val name = s"${binder.name}" + binder.config match { + case None => ActorSystem(name) + case Some(config) => ActorSystem(name, config) + } + } + implicit val materializer: ActorMaterializer = ActorMaterializer() + private var port: Int = 0 + private var portBinding: Future[ServerBinding] = _ + + override def start(): Unit = { + portBinding = Await.ready(binder.bind(0), 10 seconds) + port = portBinding.value.get.get.localAddress.getPort + } + + override def stop(): Unit = { + import materializer.executionContext + portBinding + .flatMap(_.unbind()) + .onComplete(_ => system.terminate()) + } + + override def address(): URI = { + new URI("http://localhost:" + port + "/") + } +} + +object AkkaHttpTestWebServer { + + trait Binder { + def name: String + + def config: Option[Config] = None + + def bind(port: Int)( + implicit system: ActorSystem, + materializer: Materializer + ): Future[ServerBinding] + } + + val BindAndHandle: Binder = new Binder { + override def name: String = "bind-and-handle" + + override def bind(port: Int)( + implicit system: ActorSystem, + materializer: Materializer + ): Future[ServerBinding] = { + import materializer.executionContext + Http().bindAndHandle(route, "localhost", port) + } + } + + val BindAndHandleAsyncWithRouteAsyncHandler: Binder = new Binder { + override def name: String = "bind-and-handle-async-with-route-async-handler" + + override def config: Option[Config] = Some( + ConfigFactory.load() + .withValue("akka.http.server.request-timeout", ConfigValueFactory.fromAnyRef("300 s")) + .withValue("akka.http.server.idle-timeout", ConfigValueFactory.fromAnyRef("300 s")) + ) + + override def bind(port: Int)( + implicit system: ActorSystem, + materializer: Materializer + ): Future[ServerBinding] = { + import materializer.executionContext + Http().bindAndHandleAsync(Route.asyncHandler(route), "localhost", port) + } + } + + val BindAndHandleSync: Binder = new Binder { + override def name: String = "bind-and-handle-sync" + + override def bind(port: Int)( + implicit system: ActorSystem, + materializer: Materializer + ): Future[ServerBinding] = { + Http().bindAndHandleSync(syncHandler, "localhost", port) + } + } + + val BindAndHandleAsync: Binder = new Binder { + override def name: String = "bind-and-handle-async" + + override def bind(port: Int)( + implicit system: ActorSystem, + materializer: Materializer + ): Future[ServerBinding] = { + import materializer.executionContext + Http().bindAndHandleAsync(asyncHandler, "localhost", port) + } + } + + val BindAndHandleAsyncHttp2: Binder = new Binder { + override def name: String = "bind-and-handle-async-http2" + + override def bind(port: Int)( + implicit system: ActorSystem, + materializer: Materializer + ): Future[ServerBinding] = { + import materializer.executionContext + val serverSettings = enableHttp2(ServerSettings(system)) + Http().bindAndHandleAsync( + asyncHandler, + "localhost", + port, + settings = serverSettings + ) + } + } + + // This part defines the routes using the Scala routing DSL + // ---------------------------------------------------------------------- // + private val exceptionHandler = ExceptionHandler { + case e : Exception if !e.isInstanceOf[BlockingException] => + val span = activeSpan() + TraceUtils.handleException(span, e) + complete( + HttpResponse(status = EXCEPTION.getStatus, entity = e.getMessage) + ) + } + + // Since the akka-http route DSL produces a Route that is evaluated for every + // incoming request, we need to wrap the HttpServerTest.controller call and exception + // handling in a custom Directive + private def withController: Directive0 = Directive[Unit] { inner => ctx => + def handleException: PartialFunction[Throwable, Future[RouteResult]] = + exceptionHandler andThen (_(ctx.withAcceptAll)) + + val uri = ctx.request.uri + val endpoint = HttpServerTest.ServerEndpoint.forPath(uri.path.toString()) + HttpServerTest.controller( + endpoint, + new Closure[Future[RouteResult]](()) { + def doCall(): Future[RouteResult] = { + try inner(())(ctx).fast + .recoverWith(handleException)(ctx.executionContext) + catch { + case NonFatal(e) => + handleException + .applyOrElse[Throwable, Future[RouteResult]](e, throw _) + } + } + } + ) + } + + private val defaultHeader = + RawHeader(HttpServerTest.getIG_RESPONSE_HEADER, HttpServerTest.getIG_RESPONSE_HEADER_VALUE) + + // force a rejection due to BlockingException to throw so that the error + // can be recorded in the span + private val blockingRejectionHandler: RejectionHandler = RejectionHandler.newBuilder() + .handle({ + case MalformedRequestContentRejection(_, cause: BlockingException) => + throw cause + }).result() + + def route(implicit ec: ExecutionContext): Route = withController { + handleRejections(blockingRejectionHandler) { + respondWithDefaultHeader(defaultHeader) { + get { + path(SUCCESS.relativePath) { + complete( + HttpResponse(status = SUCCESS.getStatus, entity = SUCCESS.getBody) + ) + } ~ path(FORWARDED.relativePath) { + headerValueByName("x-forwarded-for") { address => + complete( + HttpResponse(status = FORWARDED.getStatus, entity = address) + ) + } + } ~ path( + QUERY_PARAM.relativePath | QUERY_ENCODED_BOTH.relativePath | QUERY_ENCODED_QUERY.relativePath + ) { + parameter("some") { query => + complete( + HttpResponse( + status = QUERY_PARAM.getStatus, + entity = s"some=$query" + ) + ) + } + } ~ path(REDIRECT.relativePath) { + redirect(Uri(REDIRECT.getBody), StatusCodes.Found) + } ~ path(USER_BLOCK.relativePath) { + Blocking.forUser("user-to-block").blockIfMatch() + complete( + HttpResponse(status = SUCCESS.getStatus, entity = "Should not be reached") + ) + } ~ path(ERROR.relativePath) { + complete(HttpResponse(status = ERROR.getStatus, entity = ERROR.getBody)) + } ~ path(EXCEPTION.relativePath) { + throw new Exception(EXCEPTION.getBody) + } ~ pathPrefix("injected-id") { + path("ping" / IntNumber) { id => + val traceId = AgentTracer.activeSpan().getTraceId + complete(s"pong $id -> $traceId") + } ~ path("fing" / IntNumber) { id => + // force the response to happen on another thread or in another context + onSuccess(Future { + Thread.sleep(10) + id + }) { fid => + val traceId = AgentTracer.activeSpan().getTraceId + complete(s"fong $fid -> $traceId") + } + } + } ~ path(USER_BLOCK.relativePath()) { + Blocking.forUser("user-to-block").blockIfMatch() + complete(HttpResponse(status = 200, entity = "should never be reached")) + } + } ~ post { + path(CREATED.relativePath()) { + entity(as[String]) { s => + complete( + HttpResponse( + status = CREATED.getStatus, + entity = s"created: $s" + ) + ) + } + } ~ + path(BODY_URLENCODED.relativePath()) { + formFieldMultiMap { m => + complete( + HttpResponse( + status = BODY_URLENCODED.getStatus, + entity = m.toStringAsGroovy + ) + ) + } + } ~ + path(BODY_JSON.relativePath()) { + parameter(Symbol("variant") ?) { + case Some("spray") => + entity(Unmarshaller.messageUnmarshallerFromEntityUnmarshaller(sprayMapUnmarshaller)) { m => + complete( + HttpResponse( + status = BODY_JSON.getStatus, + entity = SprayMapFormat.write(m).compactPrint + ) + ) + } + case _ => // jackson + entity(Unmarshaller.messageUnmarshallerFromEntityUnmarshaller(jacksonMapUnmarshaller)) { m => + complete( + HttpResponse( + status = BODY_JSON.getStatus, + entity = SprayMapFormat.write(m).compactPrint + ) + ) + } + } + } ~ + path(BODY_MULTIPART.relativePath()) { + parameter(Symbol("variant") ?) { + case Some("strictUnmarshaller") => + entity(as[Multipart.FormData.Strict]) { formData => + val m = formData.strictParts + .groupBy(_.name) + .mapValues( + _.map((bp: BodyPart.Strict) => + bp.entity.data.utf8String + ).toList + ) + complete( + HttpResponse( + status = BODY_MULTIPART.getStatus, + entity = m.toStringAsGroovy + ) + ) + } + case _ => + formFieldMultiMap { m => + complete( + HttpResponse( + status = BODY_MULTIPART.getStatus, + entity = m.toStringAsGroovy + ) + ) + } + } + } + } + } + } + } + + // This part defines the sync and async handler functions + // ---------------------------------------------------------------------- // + + val syncHandler: HttpRequest => HttpResponse = { + case HttpRequest(GET, uri: Uri, _, _, _) => + val path = uri.path.toString() + val endpoint = HttpServerTest.ServerEndpoint.forPath(path) + HttpServerTest + .controller( + endpoint, + new Closure[HttpResponse](()) { + def doCall(): HttpResponse = { + val resp = HttpResponse(status = endpoint.getStatus) + endpoint match { + case SUCCESS => resp.withEntity(endpoint.getBody) + case FORWARDED => resp.withEntity(endpoint.getBody) // cheating + case QUERY_PARAM | QUERY_ENCODED_BOTH | QUERY_ENCODED_QUERY => + resp.withEntity(uri.queryString().orNull) + case REDIRECT => + resp.withHeaders(headers.Location(endpoint.getBody)) + case ERROR => resp.withEntity(endpoint.getBody) + case EXCEPTION => throw new Exception(endpoint.getBody) + case USER_BLOCK => { + Blocking.forUser("user-to-block").blockIfMatch() + // should never be output: + resp.withEntity("should never be reached") + } + case _ => + if (path.startsWith("/injected-id/")) { + val groups = path.split('/') + if (groups.length == 4) { // The path starts with a / and has 3 segments + val traceId = AgentTracer.activeSpan().getTraceId + val id = groups(3).toInt + groups(2) match { + case "ping" => + return HttpResponse(entity = s"pong $id -> $traceId") + case "fing" => + return HttpResponse(entity = s"fong $id -> $traceId") + case _ => + } + } + } + HttpResponse(status = NOT_FOUND.getStatus) + .withEntity(NOT_FOUND.getBody) + } + } + } + ) + .withDefaultHeaders(defaultHeader) + } + + def asyncHandler( + implicit ec: ExecutionContext, + mat: Materializer + ): HttpRequest => Future[HttpResponse] = { + case request@HttpRequest(POST, uri, _, entity, _) => + val path = request.uri.path.toString + val endpoint = HttpServerTest.ServerEndpoint.forPath(path) + + endpoint match { + case CREATED => + Unmarshal(entity).to[String].map { bodyStr => + HttpResponse(status = CREATED.getStatus) + .withEntity(s"${CREATED.getBody}: $bodyStr") + } + case BODY_MULTIPART => + uri.query().get("variant") match { + case Some("strictUnmarshaller") => + val eventualStrict = Unmarshal(entity).to[FormData.Strict] + eventualStrict.map { s => + HttpResponse(status = BODY_MULTIPART.getStatus) + .withEntity(s.toStringAsGroovy) + } + case _ => + val fd = Unmarshal(entity).to[Multipart.FormData] + val eventualStrict = fd.flatMap(_.toStrict(500 millis)) + eventualStrict.map { s => + HttpResponse(status = BODY_MULTIPART.getStatus) + .withEntity(s.toStringAsGroovy) + } + } + case BODY_URLENCODED => + val eventualData = Unmarshal(entity).to[model.FormData] + eventualData.map { d => + HttpResponse(status = BODY_URLENCODED.getStatus) + .withEntity(d.toStringAsGroovy) + } + case BODY_JSON => + val unmarshaller = uri.query().get("variant") match { + case Some("spray") => sprayMapUnmarshaller + case _ => jacksonMapUnmarshaller + } + val eventualData = Unmarshal(entity).to[Map[String, String]](unmarshaller, ec, mat) + eventualData.map { d => + HttpResponse(status = BODY_URLENCODED.getStatus) + .withEntity(SprayMapFormat.write(d).compactPrint) + } + case _ => Future.successful(HttpResponse(404)) + } + case request => Future { + syncHandler(request) + } + } + + def enableHttp2(serverSettings: ServerSettings): ServerSettings = { + val previewServerSettings = + serverSettings.previewServerSettings.withEnableHttp2(true) + serverSettings.withPreviewServerSettings(previewServerSettings) + } + + implicit class MapExtensions[A](m: Iterable[(String, A)]) { + def toStringAsGroovy: String = { + def valueToString(value: Object) : String = value match { + case seq: Seq[_] => seq.map(x => valueToString(x.asInstanceOf[Object])).mkString("[", ",", "]") + case other => other.toString + } + + m.map { case (key, value) => s"$key:${valueToString(value.asInstanceOf[Object])}" } + .mkString("[", ",", "]") + } + } + + implicit class MultipartFormDataStrictExtensions(strict: Multipart.FormData.Strict) { + def toStringAsGroovy: String = + strict.strictParts + .groupBy(_.name) + .mapValues( + _.map((bp: BodyPart.Strict) => + bp.entity.data.utf8String + ).toList + ).toStringAsGroovy + } + + implicit class FormDataExtensions(formData: model.FormData) { + def toStringAsGroovy: String = formData.fields.toMultiMap.toStringAsGroovy + } + + implicit def strictMultipartFormDataUnmarshaller: FromEntityUnmarshaller[Multipart.FormData.Strict] = { + val toStrictUnmarshaller = Unmarshaller.withMaterializer[HttpEntity, HttpEntity.Strict] { + implicit ec => + implicit mat => + entity => + entity.toStrict(1000.millis) + } + val toFormDataUnmarshaller = MultipartUnmarshallers.multipartFormDataUnmarshaller + val downcastUnmarshaller = Unmarshaller.strict[Multipart.FormData, Multipart.FormData.Strict] { + case strict: Multipart.FormData.Strict => strict + case _ => throw new RuntimeException("Expected Strict form data at this point") + } + + toStrictUnmarshaller.andThen(toFormDataUnmarshaller).andThen(downcastUnmarshaller) + } + + val jacksonMapUnmarshaller: FromEntityUnmarshaller[Map[String,String]] = { + Jackson.unmarshaller(classOf[java.util.Map[String, String]]).asScala.map( + javaMap => { + import scala.collection.JavaConverters._ + javaMap.asScala.toMap + } + ) + } + + object SprayMapFormat extends RootJsonFormat[Map[String, String]] { + def write(map: Map[String, String]): JsObject = JsObject(map.mapValues(JsString(_)).toMap) + + def read(value: JsValue): Map[String, String] = value match { + case JsObject(fields) => fields.collect { + case (k, JsString(v)) => k -> v + } + case _ => deserializationError("Expected a JSON object") + } + } + + val sprayMapUnmarshaller: FromEntityUnmarshaller[Map[String, String]] = + SprayJsonSupport.sprayJsonUnmarshaller[Map[String, String]](SprayMapFormat) +} diff --git a/dd-java-agent/instrumentation/akka-http/build.gradle b/dd-java-agent/instrumentation/akka-http/build.gradle new file mode 100644 index 00000000000..5e69c67bd78 --- /dev/null +++ b/dd-java-agent/instrumentation/akka-http/build.gradle @@ -0,0 +1 @@ +apply from: "$rootDir/gradle/java.gradle" diff --git a/dd-java-agent/instrumentation/aws-java-sns-1.0/build.gradle b/dd-java-agent/instrumentation/aws-java-sns-1.0/build.gradle index 480ea864e22..0e64612a3a6 100644 --- a/dd-java-agent/instrumentation/aws-java-sns-1.0/build.gradle +++ b/dd-java-agent/instrumentation/aws-java-sns-1.0/build.gradle @@ -22,7 +22,7 @@ dependencies { // SQS is used to act as the "Subscriber" of the SNS topic. // There's a problem with sqs sdk v1 with localstack+testcontainers testing. so use sdk v2 for sqs testImplementation 'software.amazon.awssdk:sqs:2.25.40' - testImplementation 'org.testcontainers:localstack:1.19.7' + testImplementation group: 'org.testcontainers', name: 'localstack', version: libs.versions.testcontainers.get() latestDepTestImplementation group: 'com.amazonaws', name: 'aws-java-sdk-sns', version: '+' } diff --git a/dd-java-agent/instrumentation/aws-java-sns-2.0/build.gradle b/dd-java-agent/instrumentation/aws-java-sns-2.0/build.gradle index 41099604996..90db2451631 100644 --- a/dd-java-agent/instrumentation/aws-java-sns-2.0/build.gradle +++ b/dd-java-agent/instrumentation/aws-java-sns-2.0/build.gradle @@ -21,7 +21,7 @@ dependencies { testImplementation 'software.amazon.awssdk:sns:2.25.40' // SQS is used to act as the "Subscriber" of the SNS topic. testImplementation 'software.amazon.awssdk:sqs:2.25.40' - testImplementation 'org.testcontainers:localstack:1.19.7' + testImplementation group: 'org.testcontainers', name: 'localstack', version: libs.versions.testcontainers.get() latestDepTestImplementation group: 'software.amazon.awssdk', name: 'sns', version: '+' } diff --git a/dd-java-agent/instrumentation/datastax-cassandra-3.8/build.gradle b/dd-java-agent/instrumentation/datastax-cassandra-3.8/build.gradle index 33649d5ea20..0e2e9efba6c 100644 --- a/dd-java-agent/instrumentation/datastax-cassandra-3.8/build.gradle +++ b/dd-java-agent/instrumentation/datastax-cassandra-3.8/build.gradle @@ -28,7 +28,7 @@ dependencies { testImplementation group: 'com.datastax.cassandra', name: 'cassandra-driver-core', version: '3.8.0' testImplementation group: 'com.github.jbellis', name: 'jamm', version: '0.3.3' - testImplementation ('org.testcontainers:cassandra:1.17.6') { + testImplementation (group: 'org.testcontainers', name: 'cassandra', version: libs.versions.testcontainers.get()) { exclude group: 'com.datastax.cassandra', module: 'cassandra-driver-core' } diff --git a/dd-java-agent/instrumentation/datastax-cassandra-3/build.gradle b/dd-java-agent/instrumentation/datastax-cassandra-3/build.gradle index 54392ca26cc..b91ca20d229 100644 --- a/dd-java-agent/instrumentation/datastax-cassandra-3/build.gradle +++ b/dd-java-agent/instrumentation/datastax-cassandra-3/build.gradle @@ -52,7 +52,7 @@ dependencies { testImplementation group: 'com.datastax.cassandra', name: 'cassandra-driver-core', version: '3.2.0' testImplementation group: 'com.github.jbellis', name: 'jamm', version: '0.3.3' - testImplementation ('org.testcontainers:cassandra:1.17.6') { + testImplementation (group: 'org.testcontainers', name: 'cassandra', version: libs.versions.testcontainers.get()) { exclude group: 'com.datastax.cassandra', module: 'cassandra-driver-core' } diff --git a/dd-java-agent/instrumentation/datastax-cassandra-4/build.gradle b/dd-java-agent/instrumentation/datastax-cassandra-4/build.gradle index 47cf694eacb..68ef75a7956 100644 --- a/dd-java-agent/instrumentation/datastax-cassandra-4/build.gradle +++ b/dd-java-agent/instrumentation/datastax-cassandra-4/build.gradle @@ -22,7 +22,7 @@ dependencies { // ProgrammaticConfig, required to set the timeout, wasn't added until 4.0.1 testImplementation group: 'com.datastax.oss', name: 'java-driver-core', version: '4.0.1' - testImplementation group: 'org.testcontainers', name: 'cassandra', version: '1.17.6' + testImplementation group: 'org.testcontainers', name: 'cassandra', version: libs.versions.testcontainers.get() // Force 0.3.3 because 0.3.0 has a version parsing bug that fails on jdk 15 testImplementation group: 'com.github.jbellis', name: "jamm", version: '0.3.3' diff --git a/dd-java-agent/instrumentation/java-lang/src/test/groovy/datadog/trace/instrumentation/java/lang/StringBuilderCallSiteTest.groovy b/dd-java-agent/instrumentation/java-lang/src/test/groovy/datadog/trace/instrumentation/java/lang/StringBuilderCallSiteTest.groovy index f8a25369ebb..109262fab2f 100644 --- a/dd-java-agent/instrumentation/java-lang/src/test/groovy/datadog/trace/instrumentation/java/lang/StringBuilderCallSiteTest.groovy +++ b/dd-java-agent/instrumentation/java-lang/src/test/groovy/datadog/trace/instrumentation/java/lang/StringBuilderCallSiteTest.groovy @@ -57,7 +57,7 @@ class StringBuilderCallSiteTest extends AgentTestRunner { if (param.class == String) { 1 * iastModule.onStringBuilderAppend(target, (String) param) } else { - 1 * iastModule.onStringBuilderAppend(target, param.toString()) + 1 * iastModule.onStringBuilderAppend(target, { it -> it.toString() == param.toString() } ) } _ * TEST_PROFILING_CONTEXT_INTEGRATION._ 0 * _ diff --git a/dd-java-agent/instrumentation/jdbc/build.gradle b/dd-java-agent/instrumentation/jdbc/build.gradle index 06c92d54486..ae412741974 100644 --- a/dd-java-agent/instrumentation/jdbc/build.gradle +++ b/dd-java-agent/instrumentation/jdbc/build.gradle @@ -38,7 +38,7 @@ dependencies { testImplementation group: 'org.testcontainers', name:'mysql', version: libs.versions.testcontainers.get() testImplementation group: 'org.testcontainers', name:'postgresql', version: libs.versions.testcontainers.get() - testImplementation group: 'org.testcontainers', name:'mssqlserver', version: '1.19.8' + testImplementation group: 'org.testcontainers', name:'mssqlserver', version: libs.versions.testcontainers.get() testRuntimeOnly project(':dd-java-agent:instrumentation:iast-instrumenter') diff --git a/dd-java-agent/instrumentation/owasp-esapi-2/src/test/groovy/datadog/trace/instrumentation/owasp/esapi/EncoderCallSiteTest.groovy b/dd-java-agent/instrumentation/owasp-esapi-2/src/test/groovy/datadog/trace/instrumentation/owasp/esapi/EncoderCallSiteTest.groovy index 800b7653a77..c90ad8e96bc 100644 --- a/dd-java-agent/instrumentation/owasp-esapi-2/src/test/groovy/datadog/trace/instrumentation/owasp/esapi/EncoderCallSiteTest.groovy +++ b/dd-java-agent/instrumentation/owasp-esapi-2/src/test/groovy/datadog/trace/instrumentation/owasp/esapi/EncoderCallSiteTest.groovy @@ -25,7 +25,7 @@ class EncoderCallSiteTest extends AgentTestRunner { testSuite.&"$method".call(args) then: - 1 * module.taintObjectIfTainted(_, _, false, mark) + 1 * module.taintStringIfTainted(_, _, false, mark) 0 * module._ where: diff --git a/dd-java-agent/instrumentation/play-2.4/build.gradle b/dd-java-agent/instrumentation/play-2.4/build.gradle index 3abd49b8e70..b2ab0d7cd28 100644 --- a/dd-java-agent/instrumentation/play-2.4/build.gradle +++ b/dd-java-agent/instrumentation/play-2.4/build.gradle @@ -77,7 +77,7 @@ dependencies { testRuntimeOnly project(':dd-java-agent:instrumentation:netty-4.0') testRuntimeOnly project(':dd-java-agent:instrumentation:netty-4.1') - testRuntimeOnly project(':dd-java-agent:instrumentation:akka-http-10.0') + testRuntimeOnly project(':dd-java-agent:instrumentation:akka-http:akka-http-10.0') testRuntimeOnly project(':dd-java-agent:instrumentation:akka-concurrent') testRuntimeOnly project(':dd-java-agent:instrumentation:akka-init') testRuntimeOnly project(':dd-java-agent:instrumentation:scala-concurrent') diff --git a/dd-java-agent/instrumentation/play-2.6/build.gradle b/dd-java-agent/instrumentation/play-2.6/build.gradle index 09d8571e64f..a13487d0063 100644 --- a/dd-java-agent/instrumentation/play-2.6/build.gradle +++ b/dd-java-agent/instrumentation/play-2.6/build.gradle @@ -104,7 +104,7 @@ dependencies { testRuntimeOnly project(':dd-java-agent:instrumentation:netty-4.0') testRuntimeOnly project(':dd-java-agent:instrumentation:netty-4.1') - testRuntimeOnly project(':dd-java-agent:instrumentation:akka-http-10.0') + testRuntimeOnly project(':dd-java-agent:instrumentation:akka-http:akka-http-10.0') testRuntimeOnly project(':dd-java-agent:instrumentation:akka-concurrent') testRuntimeOnly project(':dd-java-agent:instrumentation:akka-init') testRuntimeOnly project(':dd-java-agent:instrumentation:scala-concurrent') diff --git a/dd-java-agent/instrumentation/play-ws-1/build.gradle b/dd-java-agent/instrumentation/play-ws-1/build.gradle index da201cc0f5b..e1dc92d0a5d 100644 --- a/dd-java-agent/instrumentation/play-ws-1/build.gradle +++ b/dd-java-agent/instrumentation/play-ws-1/build.gradle @@ -33,7 +33,7 @@ dependencies { // These are to ensure cross compatibility testImplementation project(':dd-java-agent:instrumentation:netty-4.0') testImplementation project(':dd-java-agent:instrumentation:netty-4.1') - testImplementation project(':dd-java-agent:instrumentation:akka-http-10.0') + testImplementation project(':dd-java-agent:instrumentation:akka-http:akka-http-10.0') testImplementation project(':dd-java-agent:instrumentation:akka-concurrent') testImplementation project(':dd-java-agent:instrumentation:akka-init') testImplementation project(':dd-java-agent:instrumentation:scala-concurrent') diff --git a/dd-java-agent/instrumentation/play-ws-2.1/build.gradle b/dd-java-agent/instrumentation/play-ws-2.1/build.gradle index 2efa8ec9bbc..9181efa9426 100644 --- a/dd-java-agent/instrumentation/play-ws-2.1/build.gradle +++ b/dd-java-agent/instrumentation/play-ws-2.1/build.gradle @@ -39,7 +39,7 @@ dependencies { // These are to ensure cross compatibility testImplementation project(':dd-java-agent:instrumentation:netty-4.0') testImplementation project(':dd-java-agent:instrumentation:netty-4.1') - testImplementation project(':dd-java-agent:instrumentation:akka-http-10.0') + testImplementation project(':dd-java-agent:instrumentation:akka-http:akka-http-10.0') testImplementation project(':dd-java-agent:instrumentation:akka-concurrent') testImplementation project(':dd-java-agent:instrumentation:akka-init') testImplementation project(':dd-java-agent:instrumentation:scala-concurrent') diff --git a/dd-java-agent/instrumentation/play-ws-2/build.gradle b/dd-java-agent/instrumentation/play-ws-2/build.gradle index 3d7a3db1f1a..3591769e47c 100644 --- a/dd-java-agent/instrumentation/play-ws-2/build.gradle +++ b/dd-java-agent/instrumentation/play-ws-2/build.gradle @@ -38,7 +38,7 @@ dependencies { // These are to ensure cross compatibility testImplementation project(':dd-java-agent:instrumentation:netty-4.0') testImplementation project(':dd-java-agent:instrumentation:netty-4.1') - testImplementation project(':dd-java-agent:instrumentation:akka-http-10.0') + testImplementation project(':dd-java-agent:instrumentation:akka-http:akka-http-10.0') testImplementation project(':dd-java-agent:instrumentation:akka-concurrent') testImplementation project(':dd-java-agent:instrumentation:akka-init') testImplementation project(':dd-java-agent:instrumentation:scala-concurrent') diff --git a/dd-java-agent/instrumentation/spring-security-5/build.gradle b/dd-java-agent/instrumentation/spring-security-5/build.gradle index dd425272adc..51bc36007cf 100644 --- a/dd-java-agent/instrumentation/spring-security-5/build.gradle +++ b/dd-java-agent/instrumentation/spring-security-5/build.gradle @@ -3,39 +3,27 @@ muzzle { group = 'org.springframework.security' module = 'spring-security-core' versions = "[5.5.0,)" - // assertInverse = true } } -ext { - minJavaVersionForTests = JavaVersion.VERSION_17 -} - apply from: "$rootDir/gradle/java.gradle" +addTestSuiteForDir('latestDepTest', 'test') -[compileMain_java17Java, compileTestJava].each { - it.configure { - setJavaVersion(it, 17) - sourceCompatibility = JavaVersion.VERSION_1_8 - targetCompatibility = JavaVersion.VERSION_1_8 - } -} - -compileTestGroovy { - javaLauncher = getJavaLauncherFor(17) -} +final springSecurityVersion = '5.8.2' +final springBootVersion = '2.6.0' dependencies { - main_java17CompileOnly group: 'org.springframework.security', name: 'spring-security-core', version: '5.5.0' - compileOnly group: 'org.springframework.security', name: 'spring-security-core', version: '5.5.0' - - testImplementation group: 'org.springframework.boot', name: 'spring-boot-starter-test', version: '3.0.0' - testImplementation group: 'org.springframework.boot', name: 'spring-boot-starter-web', version: '3.0.0' - testImplementation group: 'org.springframework.boot', name: 'spring-boot-starter-security', version: '3.0.0' - testImplementation 'org.springframework.boot:spring-boot-starter-jdbc:3.0.0' + compileOnly group: 'org.springframework.security', name: 'spring-security-core', version: springSecurityVersion testImplementation testFixtures(project(':dd-java-agent:appsec')) - testImplementation project(':dd-java-agent:instrumentation:tomcat-appsec-6') - testImplementation project(':dd-java-agent:instrumentation:tomcat-5.5') - testImplementation 'com.h2database:h2:2.1.212' + testImplementation group: 'org.springframework.boot', name: 'spring-boot-starter-test', version: springBootVersion + testImplementation group: 'org.springframework.boot', name: 'spring-boot-starter-web', version: springBootVersion + testImplementation group: 'org.springframework.boot', name: 'spring-boot-starter-security', version: springBootVersion + + latestDepTestImplementation group: 'org.springframework.boot', name: 'spring-boot-starter-test', version: '2.+' + latestDepTestImplementation group: 'org.springframework.boot', name: 'spring-boot-starter-web', version: '2.+' + latestDepTestImplementation group: 'org.springframework.boot', name: 'spring-boot-starter-security', version: '2.+' + + testRuntimeOnly project(':dd-java-agent:instrumentation:tomcat-appsec-6') + testRuntimeOnly project(':dd-java-agent:instrumentation:tomcat-5.5') } diff --git a/dd-java-agent/instrumentation/spring-security-5/gradle.lockfile b/dd-java-agent/instrumentation/spring-security-5/gradle.lockfile index 8dd9809b3b3..c4422c4872b 100644 --- a/dd-java-agent/instrumentation/spring-security-5/gradle.lockfile +++ b/dd-java-agent/instrumentation/spring-security-5/gradle.lockfile @@ -1,219 +1,258 @@ # This is a Gradle generated file for dependency locking. # Manual edits can break the build and are not advised. # This file is expected to be part of source control. -cafe.cryptography:curve25519-elisabeth:0.1.0=instrumentPluginClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath -cafe.cryptography:ed25519-elisabeth:0.1.0=instrumentPluginClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath -ch.qos.logback:logback-classic:1.4.5=testCompileClasspath,testRuntimeClasspath -ch.qos.logback:logback-core:1.4.5=testCompileClasspath,testRuntimeClasspath -com.beust:jcommander:1.78=testRuntimeClasspath -com.blogspot.mydailyjava:weak-lock-free:0.17=compileClasspath,instrumentPluginClasspath,main_java17CompileClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -com.datadoghq.okhttp3:okhttp:3.12.15=compileClasspath,instrumentPluginClasspath,main_java17CompileClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -com.datadoghq.okio:okio:1.17.6=compileClasspath,instrumentPluginClasspath,main_java17CompileClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -com.datadoghq:dd-javac-plugin-client:0.1.7=compileClasspath,instrumentPluginClasspath,main_java17CompileClasspath,main_java17RuntimeClasspath,muzzleBootstrap,muzzleTooling,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -com.datadoghq:java-dogstatsd-client:4.4.0=instrumentPluginClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath -com.datadoghq:sketches-java:0.8.3=instrumentPluginClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath -com.fasterxml.jackson.core:jackson-annotations:2.14.1=testCompileClasspath,testRuntimeClasspath -com.fasterxml.jackson.core:jackson-core:2.14.1=testCompileClasspath,testRuntimeClasspath -com.fasterxml.jackson.core:jackson-databind:2.14.1=testCompileClasspath,testRuntimeClasspath -com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.14.1=testCompileClasspath,testRuntimeClasspath -com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.14.1=testCompileClasspath,testRuntimeClasspath -com.fasterxml.jackson.module:jackson-module-parameter-names:2.14.1=testCompileClasspath,testRuntimeClasspath -com.fasterxml.jackson:jackson-bom:2.14.1=testCompileClasspath,testRuntimeClasspath -com.github.javaparser:javaparser-core:3.25.1=testCompileClasspath,testRuntimeClasspath -com.github.jnr:jffi:1.3.13=instrumentPluginClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath -com.github.jnr:jnr-a64asm:1.0.0=instrumentPluginClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath -com.github.jnr:jnr-constants:0.10.4=instrumentPluginClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath -com.github.jnr:jnr-enxio:0.32.17=instrumentPluginClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath -com.github.jnr:jnr-ffi:2.2.16=instrumentPluginClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath -com.github.jnr:jnr-posix:3.1.19=instrumentPluginClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath -com.github.jnr:jnr-unixsocket:0.38.22=instrumentPluginClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath -com.github.jnr:jnr-x86asm:1.0.2=instrumentPluginClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath -com.github.spotbugs:spotbugs-annotations:4.2.0=compileClasspath,testCompileClasspath,testRuntimeClasspath +cafe.cryptography:curve25519-elisabeth:0.1.0=instrumentPluginClasspath,latestDepTestRuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath +cafe.cryptography:ed25519-elisabeth:0.1.0=instrumentPluginClasspath,latestDepTestRuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath +ch.qos.logback:logback-classic:1.2.12=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +ch.qos.logback:logback-classic:1.2.7=testCompileClasspath,testRuntimeClasspath +ch.qos.logback:logback-core:1.2.12=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +ch.qos.logback:logback-core:1.2.7=testCompileClasspath,testRuntimeClasspath +com.beust:jcommander:1.78=latestDepTestRuntimeClasspath,testRuntimeClasspath +com.blogspot.mydailyjava:weak-lock-free:0.17=compileClasspath,instrumentPluginClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,muzzleTooling,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +com.datadoghq.okhttp3:okhttp:3.12.15=compileClasspath,instrumentPluginClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,muzzleTooling,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +com.datadoghq.okio:okio:1.17.6=compileClasspath,instrumentPluginClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,muzzleTooling,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +com.datadoghq:dd-javac-plugin-client:0.1.7=compileClasspath,instrumentPluginClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,muzzleBootstrap,muzzleTooling,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +com.datadoghq:java-dogstatsd-client:4.4.0=instrumentPluginClasspath,latestDepTestRuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath +com.datadoghq:sketches-java:0.8.3=instrumentPluginClasspath,latestDepTestRuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath +com.fasterxml.jackson.core:jackson-annotations:2.13.0=testCompileClasspath,testRuntimeClasspath +com.fasterxml.jackson.core:jackson-annotations:2.13.5=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +com.fasterxml.jackson.core:jackson-core:2.13.0=testCompileClasspath,testRuntimeClasspath +com.fasterxml.jackson.core:jackson-core:2.13.5=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +com.fasterxml.jackson.core:jackson-databind:2.13.0=testCompileClasspath,testRuntimeClasspath +com.fasterxml.jackson.core:jackson-databind:2.13.5=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.13.0=testCompileClasspath,testRuntimeClasspath +com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.13.5=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.13.0=testCompileClasspath,testRuntimeClasspath +com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.13.5=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +com.fasterxml.jackson.module:jackson-module-parameter-names:2.13.0=testCompileClasspath,testRuntimeClasspath +com.fasterxml.jackson.module:jackson-module-parameter-names:2.13.5=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +com.fasterxml.jackson:jackson-bom:2.13.5=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +com.github.javaparser:javaparser-core:3.25.1=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +com.github.jnr:jffi:1.3.13=instrumentPluginClasspath,latestDepTestRuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath +com.github.jnr:jnr-a64asm:1.0.0=instrumentPluginClasspath,latestDepTestRuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath +com.github.jnr:jnr-constants:0.10.4=instrumentPluginClasspath,latestDepTestRuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath +com.github.jnr:jnr-enxio:0.32.17=instrumentPluginClasspath,latestDepTestRuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath +com.github.jnr:jnr-ffi:2.2.16=instrumentPluginClasspath,latestDepTestRuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath +com.github.jnr:jnr-posix:3.1.19=instrumentPluginClasspath,latestDepTestRuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath +com.github.jnr:jnr-unixsocket:0.38.22=instrumentPluginClasspath,latestDepTestRuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath +com.github.jnr:jnr-x86asm:1.0.2=instrumentPluginClasspath,latestDepTestRuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath +com.github.spotbugs:spotbugs-annotations:4.2.0=compileClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath com.github.spotbugs:spotbugs-annotations:4.7.3=spotbugs com.github.spotbugs:spotbugs:4.7.3=spotbugs -com.github.stefanbirkner:system-rules:1.19.0=testCompileClasspath,testRuntimeClasspath -com.google.auto.service:auto-service-annotations:1.0-rc7=annotationProcessor,compileClasspath,testAnnotationProcessor,testCompileClasspath -com.google.auto.service:auto-service:1.0-rc7=annotationProcessor,testAnnotationProcessor -com.google.auto:auto-common:0.10=annotationProcessor,testAnnotationProcessor -com.google.code.findbugs:jsr305:3.0.2=annotationProcessor,compileClasspath,spotbugs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath +com.github.stefanbirkner:system-rules:1.19.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +com.google.auto.service:auto-service-annotations:1.0-rc7=annotationProcessor,compileClasspath,latestDepTestAnnotationProcessor,latestDepTestCompileClasspath,testAnnotationProcessor,testCompileClasspath +com.google.auto.service:auto-service:1.0-rc7=annotationProcessor,latestDepTestAnnotationProcessor,testAnnotationProcessor +com.google.auto:auto-common:0.10=annotationProcessor,latestDepTestAnnotationProcessor,testAnnotationProcessor +com.google.code.findbugs:jsr305:3.0.2=annotationProcessor,compileClasspath,latestDepTestAnnotationProcessor,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,spotbugs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath com.google.code.gson:gson:2.9.1=spotbugs -com.google.errorprone:error_prone_annotations:2.2.0=annotationProcessor,testAnnotationProcessor -com.google.guava:failureaccess:1.0.1=annotationProcessor,testAnnotationProcessor -com.google.guava:guava:20.0=testCompileClasspath,testRuntimeClasspath -com.google.guava:guava:27.0.1-jre=annotationProcessor,testAnnotationProcessor -com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava=annotationProcessor,testAnnotationProcessor -com.google.j2objc:j2objc-annotations:1.1=annotationProcessor,testAnnotationProcessor -com.google.re2j:re2j:1.7=instrumentPluginClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath -com.h2database:h2:2.1.212=testCompileClasspath,testRuntimeClasspath -com.jayway.jsonpath:json-path:2.7.0=testCompileClasspath,testRuntimeClasspath -com.squareup.moshi:moshi:1.11.0=compileClasspath,instrumentPluginClasspath,main_java17CompileClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -com.squareup.okhttp3:logging-interceptor:3.12.12=testCompileClasspath,testRuntimeClasspath -com.squareup.okhttp3:okhttp:3.12.12=testCompileClasspath,testRuntimeClasspath -com.squareup.okio:okio:1.17.5=compileClasspath,instrumentPluginClasspath,main_java17CompileClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -com.thoughtworks.qdox:qdox:1.12.1=testRuntimeClasspath -com.vaadin.external.google:android-json:0.0.20131108.vaadin1=testCompileClasspath,testRuntimeClasspath -com.zaxxer:HikariCP:5.0.1=testCompileClasspath,testRuntimeClasspath +com.google.errorprone:error_prone_annotations:2.2.0=annotationProcessor,latestDepTestAnnotationProcessor,testAnnotationProcessor +com.google.guava:failureaccess:1.0.1=annotationProcessor,latestDepTestAnnotationProcessor,testAnnotationProcessor +com.google.guava:guava:20.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +com.google.guava:guava:27.0.1-jre=annotationProcessor,latestDepTestAnnotationProcessor,testAnnotationProcessor +com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava=annotationProcessor,latestDepTestAnnotationProcessor,testAnnotationProcessor +com.google.j2objc:j2objc-annotations:1.1=annotationProcessor,latestDepTestAnnotationProcessor,testAnnotationProcessor +com.google.re2j:re2j:1.7=instrumentPluginClasspath,latestDepTestRuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath +com.jayway.jsonpath:json-path:2.6.0=testCompileClasspath,testRuntimeClasspath +com.jayway.jsonpath:json-path:2.7.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +com.squareup.moshi:moshi:1.11.0=compileClasspath,instrumentPluginClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,muzzleTooling,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +com.squareup.okhttp3:logging-interceptor:3.12.12=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +com.squareup.okhttp3:okhttp:3.12.12=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +com.squareup.okio:okio:1.17.5=compileClasspath,instrumentPluginClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,muzzleTooling,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +com.thoughtworks.qdox:qdox:1.12.1=latestDepTestRuntimeClasspath,testRuntimeClasspath +com.vaadin.external.google:android-json:0.0.20131108.vaadin1=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath commons-codec:commons-codec:1.15=spotbugs -commons-fileupload:commons-fileupload:1.5=testCompileClasspath,testRuntimeClasspath -commons-io:commons-io:2.11.0=testCompileClasspath,testRuntimeClasspath +commons-fileupload:commons-fileupload:1.5=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +commons-io:commons-io:2.11.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath de.thetaphi:forbiddenapis:3.1=compileClasspath -info.picocli:picocli:4.6.3=testRuntimeClasspath -io.micrometer:micrometer-commons:1.10.1=testCompileClasspath,testRuntimeClasspath -io.micrometer:micrometer-observation:1.10.1=testCompileClasspath,testRuntimeClasspath -io.sqreen:libsqreen:11.0.1=testRuntimeClasspath -jakarta.activation:jakarta.activation-api:2.1.0=testCompileClasspath,testRuntimeClasspath -jakarta.annotation:jakarta.annotation-api:2.1.1=testCompileClasspath,testRuntimeClasspath -jakarta.xml.bind:jakarta.xml.bind-api:4.0.0=testCompileClasspath,testRuntimeClasspath -javax.servlet:javax.servlet-api:3.1.0=testCompileClasspath,testRuntimeClasspath +info.picocli:picocli:4.6.3=latestDepTestRuntimeClasspath,testRuntimeClasspath +io.sqreen:libsqreen:11.0.0=latestDepTestRuntimeClasspath,testRuntimeClasspath +jakarta.activation:jakarta.activation-api:1.2.2=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +jakarta.annotation:jakarta.annotation-api:1.3.5=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +jakarta.xml.bind:jakarta.xml.bind-api:2.3.3=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +javax.servlet:javax.servlet-api:3.1.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath jaxen:jaxen:1.2.0=spotbugs -jline:jline:2.14.6=testRuntimeClasspath -junit:junit-dep:4.11=testCompileClasspath,testRuntimeClasspath -junit:junit:4.13.2=testCompileClasspath,testRuntimeClasspath -net.bytebuddy:byte-buddy-agent:1.14.18=compileClasspath,instrumentPluginClasspath,main_java17CompileClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -net.bytebuddy:byte-buddy:1.14.18=compileClasspath,instrumentPluginClasspath,main_java17CompileClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -net.java.dev.jna:jna-platform:5.8.0=instrumentPluginClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath -net.java.dev.jna:jna:5.8.0=instrumentPluginClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath -net.jcip:jcip-annotations:1.0=compileClasspath,spotbugs,testCompileClasspath,testRuntimeClasspath -net.minidev:accessors-smart:2.4.7=testCompileClasspath,testRuntimeClasspath -net.minidev:json-smart:2.4.7=testCompileClasspath,testRuntimeClasspath +jline:jline:2.14.6=latestDepTestRuntimeClasspath,testRuntimeClasspath +junit:junit-dep:4.11=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +junit:junit:4.13.2=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +net.bytebuddy:byte-buddy-agent:1.14.18=compileClasspath,instrumentPluginClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,muzzleTooling,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +net.bytebuddy:byte-buddy:1.14.18=compileClasspath,instrumentPluginClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,muzzleTooling,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +net.java.dev.jna:jna-platform:5.8.0=instrumentPluginClasspath,latestDepTestRuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath +net.java.dev.jna:jna:5.8.0=instrumentPluginClasspath,latestDepTestRuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath +net.jcip:jcip-annotations:1.0=compileClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,spotbugs,testCompileClasspath,testRuntimeClasspath +net.minidev:accessors-smart:2.4.7=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +net.minidev:json-smart:2.4.7=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath net.sf.saxon:Saxon-HE:11.4=spotbugs -org.apache.ant:ant-antlr:1.10.12=testRuntimeClasspath +org.apache.ant:ant-antlr:1.10.12=latestDepTestRuntimeClasspath,testRuntimeClasspath org.apache.ant:ant-antlr:1.9.15=codenarc -org.apache.ant:ant-junit:1.10.12=testRuntimeClasspath +org.apache.ant:ant-junit:1.10.12=latestDepTestRuntimeClasspath,testRuntimeClasspath org.apache.ant:ant-junit:1.9.15=codenarc -org.apache.ant:ant-launcher:1.10.12=testRuntimeClasspath -org.apache.ant:ant:1.10.12=testCompileClasspath,testRuntimeClasspath +org.apache.ant:ant-launcher:1.10.12=latestDepTestRuntimeClasspath,testRuntimeClasspath +org.apache.ant:ant:1.10.12=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath org.apache.bcel:bcel:6.5.0=spotbugs org.apache.commons:commons-lang3:3.12.0=spotbugs org.apache.commons:commons-text:1.10.0=spotbugs org.apache.httpcomponents.client5:httpclient5:5.1.3=spotbugs org.apache.httpcomponents.core5:httpcore5-h2:5.1.3=spotbugs org.apache.httpcomponents.core5:httpcore5:5.1.3=spotbugs -org.apache.logging.log4j:log4j-api:2.19.0=spotbugs,testCompileClasspath,testRuntimeClasspath +org.apache.logging.log4j:log4j-api:2.14.1=testCompileClasspath,testRuntimeClasspath +org.apache.logging.log4j:log4j-api:2.17.2=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.apache.logging.log4j:log4j-api:2.19.0=spotbugs org.apache.logging.log4j:log4j-core:2.19.0=spotbugs -org.apache.logging.log4j:log4j-to-slf4j:2.19.0=testCompileClasspath,testRuntimeClasspath -org.apache.tomcat.embed:tomcat-embed-core:10.1.1=testCompileClasspath,testRuntimeClasspath -org.apache.tomcat.embed:tomcat-embed-el:10.1.1=testCompileClasspath,testRuntimeClasspath -org.apache.tomcat.embed:tomcat-embed-websocket:10.1.1=testCompileClasspath,testRuntimeClasspath -org.apiguardian:apiguardian-api:1.1.2=testCompileClasspath -org.assertj:assertj-core:3.23.1=testCompileClasspath,testRuntimeClasspath -org.checkerframework:checker-qual:2.5.2=annotationProcessor,testAnnotationProcessor -org.codehaus.groovy:groovy-all:3.0.17=testCompileClasspath,testRuntimeClasspath +org.apache.logging.log4j:log4j-to-slf4j:2.14.1=testCompileClasspath,testRuntimeClasspath +org.apache.logging.log4j:log4j-to-slf4j:2.17.2=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.apache.tomcat.embed:tomcat-embed-core:9.0.55=testCompileClasspath,testRuntimeClasspath +org.apache.tomcat.embed:tomcat-embed-core:9.0.83=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.apache.tomcat.embed:tomcat-embed-el:9.0.55=testCompileClasspath,testRuntimeClasspath +org.apache.tomcat.embed:tomcat-embed-el:9.0.83=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.apache.tomcat.embed:tomcat-embed-websocket:9.0.55=testCompileClasspath,testRuntimeClasspath +org.apache.tomcat.embed:tomcat-embed-websocket:9.0.83=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.apiguardian:apiguardian-api:1.1.2=latestDepTestCompileClasspath,testCompileClasspath +org.assertj:assertj-core:3.21.0=testCompileClasspath,testRuntimeClasspath +org.assertj:assertj-core:3.22.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.checkerframework:checker-qual:2.5.2=annotationProcessor,latestDepTestAnnotationProcessor,testAnnotationProcessor +org.codehaus.groovy:groovy-all:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath org.codehaus.groovy:groovy-ant:2.5.14=codenarc -org.codehaus.groovy:groovy-ant:3.0.17=testCompileClasspath,testRuntimeClasspath -org.codehaus.groovy:groovy-astbuilder:3.0.17=testCompileClasspath,testRuntimeClasspath -org.codehaus.groovy:groovy-cli-picocli:3.0.17=testCompileClasspath,testRuntimeClasspath -org.codehaus.groovy:groovy-console:3.0.17=testCompileClasspath,testRuntimeClasspath -org.codehaus.groovy:groovy-datetime:3.0.17=testCompileClasspath,testRuntimeClasspath -org.codehaus.groovy:groovy-docgenerator:3.0.17=testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-ant:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-astbuilder:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-cli-picocli:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-console:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-datetime:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-docgenerator:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath org.codehaus.groovy:groovy-groovydoc:2.5.14=codenarc -org.codehaus.groovy:groovy-groovydoc:3.0.17=testCompileClasspath,testRuntimeClasspath -org.codehaus.groovy:groovy-groovysh:3.0.17=testCompileClasspath,testRuntimeClasspath -org.codehaus.groovy:groovy-jmx:3.0.17=testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-groovydoc:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-groovysh:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-jmx:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath org.codehaus.groovy:groovy-json:2.5.14=codenarc -org.codehaus.groovy:groovy-json:3.0.17=testCompileClasspath,testRuntimeClasspath -org.codehaus.groovy:groovy-jsr223:3.0.17=testCompileClasspath,testRuntimeClasspath -org.codehaus.groovy:groovy-macro:3.0.17=testCompileClasspath,testRuntimeClasspath -org.codehaus.groovy:groovy-nio:3.0.17=testCompileClasspath,testRuntimeClasspath -org.codehaus.groovy:groovy-servlet:3.0.17=testCompileClasspath,testRuntimeClasspath -org.codehaus.groovy:groovy-sql:3.0.17=testCompileClasspath,testRuntimeClasspath -org.codehaus.groovy:groovy-swing:3.0.17=testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-json:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-jsr223:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-macro:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-nio:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-servlet:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-sql:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-swing:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath org.codehaus.groovy:groovy-templates:2.5.14=codenarc -org.codehaus.groovy:groovy-templates:3.0.17=testCompileClasspath,testRuntimeClasspath -org.codehaus.groovy:groovy-test-junit5:3.0.17=testCompileClasspath,testRuntimeClasspath -org.codehaus.groovy:groovy-test:3.0.17=testCompileClasspath,testRuntimeClasspath -org.codehaus.groovy:groovy-testng:3.0.17=testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-templates:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-test-junit5:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-test:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-testng:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath org.codehaus.groovy:groovy-xml:2.5.14=codenarc -org.codehaus.groovy:groovy-xml:3.0.17=testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-xml:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath org.codehaus.groovy:groovy:2.5.14=codenarc -org.codehaus.groovy:groovy:3.0.17=testCompileClasspath,testRuntimeClasspath -org.codehaus.mojo:animal-sniffer-annotations:1.17=annotationProcessor,testAnnotationProcessor +org.codehaus.groovy:groovy:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.mojo:animal-sniffer-annotations:1.17=annotationProcessor,latestDepTestAnnotationProcessor,testAnnotationProcessor org.codenarc:CodeNarc:2.2.0=codenarc org.dom4j:dom4j:2.1.3=spotbugs -org.eclipse.jetty:jetty-http:9.2.30.v20200428=testCompileClasspath,testRuntimeClasspath -org.eclipse.jetty:jetty-io:9.2.30.v20200428=testCompileClasspath,testRuntimeClasspath -org.eclipse.jetty:jetty-server:9.2.30.v20200428=testCompileClasspath,testRuntimeClasspath -org.eclipse.jetty:jetty-util:9.2.30.v20200428=testCompileClasspath,testRuntimeClasspath +org.eclipse.jetty:jetty-http:9.2.30.v20200428=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.eclipse.jetty:jetty-io:9.2.30.v20200428=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.eclipse.jetty:jetty-server:9.2.30.v20200428=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.eclipse.jetty:jetty-util:9.2.30.v20200428=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath org.gmetrics:GMetrics:1.1=codenarc -org.hamcrest:hamcrest-core:1.3=testCompileClasspath,testRuntimeClasspath -org.hamcrest:hamcrest:2.2=testCompileClasspath,testRuntimeClasspath -org.jctools:jctools-core:3.3.0=instrumentPluginClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath -org.junit.jupiter:junit-jupiter-api:5.9.2=testCompileClasspath,testRuntimeClasspath -org.junit.jupiter:junit-jupiter-engine:5.9.2=testRuntimeClasspath -org.junit.jupiter:junit-jupiter-params:5.9.2=testCompileClasspath,testRuntimeClasspath -org.junit.jupiter:junit-jupiter:5.9.2=testCompileClasspath,testRuntimeClasspath -org.junit.platform:junit-platform-commons:1.9.2=testCompileClasspath,testRuntimeClasspath -org.junit.platform:junit-platform-engine:1.9.2=testCompileClasspath,testRuntimeClasspath -org.junit.platform:junit-platform-launcher:1.9.2=testRuntimeClasspath -org.junit.platform:junit-platform-runner:1.9.2=testRuntimeClasspath -org.junit.platform:junit-platform-suite-api:1.9.2=testRuntimeClasspath -org.junit.platform:junit-platform-suite-commons:1.9.2=testRuntimeClasspath -org.junit:junit-bom:5.9.1=spotbugs -org.junit:junit-bom:5.9.2=testCompileClasspath,testRuntimeClasspath -org.mockito:mockito-core:4.8.1=testCompileClasspath,testRuntimeClasspath -org.mockito:mockito-junit-jupiter:4.8.1=testCompileClasspath,testRuntimeClasspath -org.objenesis:objenesis:3.3=testCompileClasspath,testRuntimeClasspath -org.opentest4j:opentest4j:1.2.0=testCompileClasspath,testRuntimeClasspath -org.ow2.asm:asm-analysis:9.2=instrumentPluginClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath +org.hamcrest:hamcrest-core:1.3=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.hamcrest:hamcrest:2.2=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.jctools:jctools-core:3.3.0=instrumentPluginClasspath,latestDepTestRuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath +org.junit.jupiter:junit-jupiter-api:5.9.2=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.junit.jupiter:junit-jupiter-engine:5.9.2=latestDepTestRuntimeClasspath,testRuntimeClasspath +org.junit.jupiter:junit-jupiter-params:5.9.2=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.junit.jupiter:junit-jupiter:5.9.2=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.junit.platform:junit-platform-commons:1.9.2=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.junit.platform:junit-platform-engine:1.9.2=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.junit.platform:junit-platform-launcher:1.9.2=latestDepTestRuntimeClasspath,testRuntimeClasspath +org.junit.platform:junit-platform-runner:1.9.2=latestDepTestRuntimeClasspath,testRuntimeClasspath +org.junit.platform:junit-platform-suite-api:1.9.2=latestDepTestRuntimeClasspath,testRuntimeClasspath +org.junit.platform:junit-platform-suite-commons:1.9.2=latestDepTestRuntimeClasspath,testRuntimeClasspath +org.junit:junit-bom:5.9.2=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.mockito:mockito-core:4.0.0=testCompileClasspath,testRuntimeClasspath +org.mockito:mockito-core:4.5.1=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.mockito:mockito-junit-jupiter:4.0.0=testCompileClasspath,testRuntimeClasspath +org.mockito:mockito-junit-jupiter:4.5.1=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.objenesis:objenesis:3.3=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.opentest4j:opentest4j:1.2.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.ow2.asm:asm-analysis:9.2=instrumentPluginClasspath,latestDepTestRuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath org.ow2.asm:asm-analysis:9.4=spotbugs -org.ow2.asm:asm-commons:9.2=instrumentPluginClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath +org.ow2.asm:asm-commons:9.2=instrumentPluginClasspath,latestDepTestRuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath org.ow2.asm:asm-commons:9.4=spotbugs -org.ow2.asm:asm-tree:9.2=instrumentPluginClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath +org.ow2.asm:asm-tree:9.2=instrumentPluginClasspath,latestDepTestRuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath org.ow2.asm:asm-tree:9.4=spotbugs -org.ow2.asm:asm-util:9.2=instrumentPluginClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath +org.ow2.asm:asm-util:9.2=instrumentPluginClasspath,latestDepTestRuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath org.ow2.asm:asm-util:9.4=spotbugs -org.ow2.asm:asm:9.1=testCompileClasspath -org.ow2.asm:asm:9.2=instrumentPluginClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath +org.ow2.asm:asm:9.1=latestDepTestCompileClasspath,testCompileClasspath +org.ow2.asm:asm:9.2=instrumentPluginClasspath,latestDepTestRuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath org.ow2.asm:asm:9.4=spotbugs -org.skyscreamer:jsonassert:1.5.1=testCompileClasspath,testRuntimeClasspath -org.slf4j:jcl-over-slf4j:1.7.30=testCompileClasspath,testRuntimeClasspath -org.slf4j:jul-to-slf4j:2.0.4=testCompileClasspath,testRuntimeClasspath -org.slf4j:log4j-over-slf4j:1.7.30=testCompileClasspath,testRuntimeClasspath -org.slf4j:slf4j-api:1.7.30=compileClasspath,instrumentPluginClasspath,main_java17CompileClasspath,main_java17RuntimeClasspath,muzzleBootstrap,muzzleTooling,runtimeClasspath +org.skyscreamer:jsonassert:1.5.0=testCompileClasspath,testRuntimeClasspath +org.skyscreamer:jsonassert:1.5.1=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.slf4j:jcl-over-slf4j:1.7.30=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.slf4j:jul-to-slf4j:1.7.32=testCompileClasspath,testRuntimeClasspath +org.slf4j:jul-to-slf4j:1.7.36=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.slf4j:log4j-over-slf4j:1.7.30=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.slf4j:slf4j-api:1.7.30=compileClasspath,instrumentPluginClasspath,muzzleBootstrap,muzzleTooling,runtimeClasspath +org.slf4j:slf4j-api:1.7.32=testCompileClasspath,testRuntimeClasspath +org.slf4j:slf4j-api:1.7.36=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath org.slf4j:slf4j-api:2.0.0=spotbugs,spotbugsSlf4j -org.slf4j:slf4j-api:2.0.4=testCompileClasspath,testRuntimeClasspath org.slf4j:slf4j-simple:2.0.0=spotbugsSlf4j -org.spockframework:spock-core:2.2-groovy-3.0=testCompileClasspath,testRuntimeClasspath -org.spockframework:spock-junit4:2.2-groovy-3.0=testCompileClasspath,testRuntimeClasspath -org.springframework.boot:spring-boot-autoconfigure:3.0.0=testCompileClasspath,testRuntimeClasspath -org.springframework.boot:spring-boot-starter-jdbc:3.0.0=testCompileClasspath,testRuntimeClasspath -org.springframework.boot:spring-boot-starter-json:3.0.0=testCompileClasspath,testRuntimeClasspath -org.springframework.boot:spring-boot-starter-logging:3.0.0=testCompileClasspath,testRuntimeClasspath -org.springframework.boot:spring-boot-starter-security:3.0.0=testCompileClasspath,testRuntimeClasspath -org.springframework.boot:spring-boot-starter-test:3.0.0=testCompileClasspath,testRuntimeClasspath -org.springframework.boot:spring-boot-starter-tomcat:3.0.0=testCompileClasspath,testRuntimeClasspath -org.springframework.boot:spring-boot-starter-web:3.0.0=testCompileClasspath,testRuntimeClasspath -org.springframework.boot:spring-boot-starter:3.0.0=testCompileClasspath,testRuntimeClasspath -org.springframework.boot:spring-boot-test-autoconfigure:3.0.0=testCompileClasspath,testRuntimeClasspath -org.springframework.boot:spring-boot-test:3.0.0=testCompileClasspath,testRuntimeClasspath -org.springframework.boot:spring-boot:3.0.0=testCompileClasspath,testRuntimeClasspath -org.springframework.security:spring-security-config:6.0.0=testCompileClasspath,testRuntimeClasspath -org.springframework.security:spring-security-core:5.5.0=compileClasspath,main_java17CompileClasspath -org.springframework.security:spring-security-core:6.0.0=testCompileClasspath,testRuntimeClasspath -org.springframework.security:spring-security-crypto:5.5.0=compileClasspath,main_java17CompileClasspath -org.springframework.security:spring-security-crypto:6.0.0=testCompileClasspath,testRuntimeClasspath -org.springframework.security:spring-security-web:6.0.0=testCompileClasspath,testRuntimeClasspath -org.springframework:spring-aop:5.3.7=compileClasspath,main_java17CompileClasspath -org.springframework:spring-aop:6.0.2=testCompileClasspath,testRuntimeClasspath -org.springframework:spring-beans:5.3.7=compileClasspath,main_java17CompileClasspath -org.springframework:spring-beans:6.0.2=testCompileClasspath,testRuntimeClasspath -org.springframework:spring-context:5.3.7=compileClasspath,main_java17CompileClasspath -org.springframework:spring-context:6.0.2=testCompileClasspath,testRuntimeClasspath -org.springframework:spring-core:5.3.7=compileClasspath,main_java17CompileClasspath -org.springframework:spring-core:6.0.2=testCompileClasspath,testRuntimeClasspath -org.springframework:spring-expression:5.3.7=compileClasspath,main_java17CompileClasspath -org.springframework:spring-expression:6.0.2=testCompileClasspath,testRuntimeClasspath -org.springframework:spring-jcl:5.3.7=compileClasspath,main_java17CompileClasspath -org.springframework:spring-jcl:6.0.2=testCompileClasspath,testRuntimeClasspath -org.springframework:spring-jdbc:6.0.2=testCompileClasspath,testRuntimeClasspath -org.springframework:spring-test:6.0.2=testCompileClasspath,testRuntimeClasspath -org.springframework:spring-tx:6.0.2=testCompileClasspath,testRuntimeClasspath -org.springframework:spring-web:6.0.2=testCompileClasspath,testRuntimeClasspath -org.springframework:spring-webmvc:6.0.2=testCompileClasspath,testRuntimeClasspath -org.testng:testng:7.5=testRuntimeClasspath -org.webjars:jquery:3.5.1=testRuntimeClasspath +org.spockframework:spock-core:2.2-groovy-3.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.spockframework:spock-junit4:2.2-groovy-3.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.springframework.boot:spring-boot-autoconfigure:2.6.0=testCompileClasspath,testRuntimeClasspath +org.springframework.boot:spring-boot-autoconfigure:2.7.18=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.springframework.boot:spring-boot-starter-json:2.6.0=testCompileClasspath,testRuntimeClasspath +org.springframework.boot:spring-boot-starter-json:2.7.18=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.springframework.boot:spring-boot-starter-logging:2.6.0=testCompileClasspath,testRuntimeClasspath +org.springframework.boot:spring-boot-starter-logging:2.7.18=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.springframework.boot:spring-boot-starter-security:2.6.0=testCompileClasspath,testRuntimeClasspath +org.springframework.boot:spring-boot-starter-security:2.7.18=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.springframework.boot:spring-boot-starter-test:2.6.0=testCompileClasspath,testRuntimeClasspath +org.springframework.boot:spring-boot-starter-test:2.7.18=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.springframework.boot:spring-boot-starter-tomcat:2.6.0=testCompileClasspath,testRuntimeClasspath +org.springframework.boot:spring-boot-starter-tomcat:2.7.18=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.springframework.boot:spring-boot-starter-web:2.6.0=testCompileClasspath,testRuntimeClasspath +org.springframework.boot:spring-boot-starter-web:2.7.18=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.springframework.boot:spring-boot-starter:2.6.0=testCompileClasspath,testRuntimeClasspath +org.springframework.boot:spring-boot-starter:2.7.18=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.springframework.boot:spring-boot-test-autoconfigure:2.6.0=testCompileClasspath,testRuntimeClasspath +org.springframework.boot:spring-boot-test-autoconfigure:2.7.18=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.springframework.boot:spring-boot-test:2.6.0=testCompileClasspath,testRuntimeClasspath +org.springframework.boot:spring-boot-test:2.7.18=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.springframework.boot:spring-boot:2.6.0=testCompileClasspath,testRuntimeClasspath +org.springframework.boot:spring-boot:2.7.18=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.springframework.security:spring-security-config:5.6.0=testCompileClasspath,testRuntimeClasspath +org.springframework.security:spring-security-config:5.7.11=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.springframework.security:spring-security-core:5.6.0=testCompileClasspath,testRuntimeClasspath +org.springframework.security:spring-security-core:5.7.11=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.springframework.security:spring-security-core:5.8.2=compileClasspath +org.springframework.security:spring-security-crypto:5.6.0=testCompileClasspath,testRuntimeClasspath +org.springframework.security:spring-security-crypto:5.7.11=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.springframework.security:spring-security-crypto:5.8.2=compileClasspath +org.springframework.security:spring-security-web:5.6.0=testCompileClasspath,testRuntimeClasspath +org.springframework.security:spring-security-web:5.7.11=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.springframework:spring-aop:5.3.13=testCompileClasspath,testRuntimeClasspath +org.springframework:spring-aop:5.3.25=compileClasspath +org.springframework:spring-aop:5.3.31=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.springframework:spring-beans:5.3.13=testCompileClasspath,testRuntimeClasspath +org.springframework:spring-beans:5.3.25=compileClasspath +org.springframework:spring-beans:5.3.31=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.springframework:spring-context:5.3.13=testCompileClasspath,testRuntimeClasspath +org.springframework:spring-context:5.3.25=compileClasspath +org.springframework:spring-context:5.3.31=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.springframework:spring-core:5.3.13=testCompileClasspath,testRuntimeClasspath +org.springframework:spring-core:5.3.25=compileClasspath +org.springframework:spring-core:5.3.31=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.springframework:spring-expression:5.3.13=testCompileClasspath,testRuntimeClasspath +org.springframework:spring-expression:5.3.25=compileClasspath +org.springframework:spring-expression:5.3.31=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.springframework:spring-jcl:5.3.13=testCompileClasspath,testRuntimeClasspath +org.springframework:spring-jcl:5.3.25=compileClasspath +org.springframework:spring-jcl:5.3.31=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.springframework:spring-test:5.3.13=testCompileClasspath,testRuntimeClasspath +org.springframework:spring-test:5.3.31=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.springframework:spring-web:5.3.13=testCompileClasspath,testRuntimeClasspath +org.springframework:spring-web:5.3.31=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.springframework:spring-webmvc:5.3.13=testCompileClasspath,testRuntimeClasspath +org.springframework:spring-webmvc:5.3.31=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.testng:testng:7.5=latestDepTestRuntimeClasspath,testRuntimeClasspath +org.webjars:jquery:3.5.1=latestDepTestRuntimeClasspath,testRuntimeClasspath org.xmlresolver:xmlresolver:4.4.3=spotbugs -org.xmlunit:xmlunit-core:2.9.0=testCompileClasspath,testRuntimeClasspath -org.yaml:snakeyaml:1.33=testCompileClasspath,testRuntimeClasspath +org.xmlunit:xmlunit-core:2.8.3=testCompileClasspath,testRuntimeClasspath +org.xmlunit:xmlunit-core:2.9.1=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.yaml:snakeyaml:1.29=testCompileClasspath,testRuntimeClasspath +org.yaml:snakeyaml:1.30=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath xml-apis:xml-apis:1.4.01=spotbugs -empty=main_java17AnnotationProcessor,spotbugsPlugins +empty=spotbugsPlugins diff --git a/dd-java-agent/instrumentation/spring-security-5/src/main/java/datadog/trace/instrumentation/springsecurity5/AppSecDeferredContext.java b/dd-java-agent/instrumentation/spring-security-5/src/main/java/datadog/trace/instrumentation/springsecurity5/AppSecDeferredContext.java new file mode 100644 index 00000000000..bfdea675ef9 --- /dev/null +++ b/dd-java-agent/instrumentation/spring-security-5/src/main/java/datadog/trace/instrumentation/springsecurity5/AppSecDeferredContext.java @@ -0,0 +1,22 @@ +package datadog.trace.instrumentation.springsecurity5; + +import java.util.function.Supplier; +import org.springframework.security.core.context.SecurityContext; + +public class AppSecDeferredContext implements Supplier { + + private final Supplier delegate; + + public AppSecDeferredContext(final Supplier delegate) { + this.delegate = delegate; + } + + @Override + public SecurityContext get() { + SecurityContext context = delegate.get(); + if (context != null) { + SpringSecurityUserEventDecorator.DECORATE.onUser(context.getAuthentication()); + } + return context; + } +} diff --git a/dd-java-agent/instrumentation/spring-security-5/src/main/java/datadog/trace/instrumentation/springsecurity5/AuthenticationProviderInstrumentation.java b/dd-java-agent/instrumentation/spring-security-5/src/main/java/datadog/trace/instrumentation/springsecurity5/AuthenticationProviderInstrumentation.java index 2eedc42e624..77d1e3b4531 100644 --- a/dd-java-agent/instrumentation/spring-security-5/src/main/java/datadog/trace/instrumentation/springsecurity5/AuthenticationProviderInstrumentation.java +++ b/dd-java-agent/instrumentation/spring-security-5/src/main/java/datadog/trace/instrumentation/springsecurity5/AuthenticationProviderInstrumentation.java @@ -10,8 +10,12 @@ import com.google.auto.service.AutoService; import datadog.trace.agent.tooling.Instrumenter; import datadog.trace.agent.tooling.InstrumenterModule; +import datadog.trace.bootstrap.ActiveSubsystems; +import net.bytebuddy.asm.Advice; import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.matcher.ElementMatcher; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.AuthenticationException; @AutoService(InstrumenterModule.class) public class AuthenticationProviderInstrumentation extends InstrumenterModule.AppSec @@ -46,6 +50,19 @@ public void methodAdvice(MethodTransformer transformer) { .and(takesArgument(0, named("org.springframework.security.core.Authentication"))) .and(returns(named("org.springframework.security.core.Authentication"))) .and(isPublic()), - packageName + ".AuthenticationProviderAdvice"); + getClass().getName() + "$AuthenticationProviderAdvice"); + } + + public static class AuthenticationProviderAdvice { + + @Advice.OnMethodExit(onThrowable = AuthenticationException.class, suppress = Throwable.class) + public static void onExit( + @Advice.Argument(value = 0, readOnly = false) Authentication authentication, + @Advice.Return final Authentication result, + @Advice.Thrown final AuthenticationException throwable) { + if (ActiveSubsystems.APPSEC_ACTIVE) { + SpringSecurityUserEventDecorator.DECORATE.onLogin(authentication, throwable, result); + } + } } } diff --git a/dd-java-agent/instrumentation/spring-security-5/src/main/java/datadog/trace/instrumentation/springsecurity5/SecurityContextHolderInstrumentation.java b/dd-java-agent/instrumentation/spring-security-5/src/main/java/datadog/trace/instrumentation/springsecurity5/SecurityContextHolderInstrumentation.java new file mode 100644 index 00000000000..31cc383c28a --- /dev/null +++ b/dd-java-agent/instrumentation/spring-security-5/src/main/java/datadog/trace/instrumentation/springsecurity5/SecurityContextHolderInstrumentation.java @@ -0,0 +1,90 @@ +package datadog.trace.instrumentation.springsecurity5; + +import static datadog.trace.agent.tooling.bytebuddy.matcher.HierarchyMatchers.implementsInterface; +import static datadog.trace.agent.tooling.bytebuddy.matcher.NameMatchers.named; +import static net.bytebuddy.matcher.ElementMatchers.isMethod; +import static net.bytebuddy.matcher.ElementMatchers.isPublic; +import static net.bytebuddy.matcher.ElementMatchers.takesArgument; +import static net.bytebuddy.matcher.ElementMatchers.takesArguments; + +import com.google.auto.service.AutoService; +import datadog.trace.agent.tooling.Instrumenter; +import datadog.trace.agent.tooling.InstrumenterModule; +import datadog.trace.bootstrap.ActiveSubsystems; +import java.util.function.Supplier; +import net.bytebuddy.asm.Advice; +import net.bytebuddy.description.type.TypeDescription; +import net.bytebuddy.matcher.ElementMatcher; +import org.springframework.security.core.context.SecurityContext; + +@AutoService(InstrumenterModule.class) +public class SecurityContextHolderInstrumentation extends InstrumenterModule.AppSec + implements Instrumenter.ForTypeHierarchy { + + public SecurityContextHolderInstrumentation() { + super("spring-security"); + } + + @Override + public String hierarchyMarkerType() { + return "org.springframework.security.core.context.SecurityContextHolderStrategy"; + } + + @Override + public ElementMatcher hierarchyMatcher() { + return implementsInterface(named(hierarchyMarkerType())); + } + + @Override + public String[] helperClassNames() { + return new String[] { + "datadog.trace.instrumentation.springsecurity5.SpringSecurityUserEventDecorator", + "datadog.trace.instrumentation.springsecurity5.AppSecDeferredContext" + }; + } + + @Override + public void methodAdvice(MethodTransformer transformer) { + transformer.applyAdvice( + isMethod() + .and(named("setContext")) + .and(takesArguments(1)) + .and( + takesArgument( + 0, named("org.springframework.security.core.context.SecurityContext"))) + .and(isPublic()), + getClass().getName() + "$SetSecurityContextAdvice"); + transformer.applyAdvice( + isMethod().and(named("setDeferredContext")).and(takesArguments(1)).and(isPublic()), + getClass().getName() + "$SetDeferredSecurityContextAdvice"); + } + + public static class SetSecurityContextAdvice { + + @Advice.OnMethodEnter(suppress = Throwable.class) + public static void onEnter(@Advice.Argument(0) final SecurityContext context) { + if (context == null) { + return; + } + if (!ActiveSubsystems.APPSEC_ACTIVE) { + return; + } + SpringSecurityUserEventDecorator.DECORATE.onUser(context.getAuthentication()); + } + } + + public static class SetDeferredSecurityContextAdvice { + + @Advice.OnMethodEnter(suppress = Throwable.class) + public static void onEnter( + @Advice.Argument(value = 0, readOnly = false) Supplier deferred) { + if (deferred == null) { + return; + } + if (!ActiveSubsystems.APPSEC_ACTIVE) { + return; + } + deferred = new AppSecDeferredContext(deferred); + } + } +} diff --git a/dd-java-agent/instrumentation/spring-security-5/src/main/java17/datadog/trace/instrumentation/springsecurity5/SpringSecurityUserEventDecorator.java b/dd-java-agent/instrumentation/spring-security-5/src/main/java/datadog/trace/instrumentation/springsecurity5/SpringSecurityUserEventDecorator.java similarity index 91% rename from dd-java-agent/instrumentation/spring-security-5/src/main/java17/datadog/trace/instrumentation/springsecurity5/SpringSecurityUserEventDecorator.java rename to dd-java-agent/instrumentation/spring-security-5/src/main/java/datadog/trace/instrumentation/springsecurity5/SpringSecurityUserEventDecorator.java index 175470b5ea8..25c20548ec0 100644 --- a/dd-java-agent/instrumentation/spring-security-5/src/main/java17/datadog/trace/instrumentation/springsecurity5/SpringSecurityUserEventDecorator.java +++ b/dd-java-agent/instrumentation/spring-security-5/src/main/java/datadog/trace/instrumentation/springsecurity5/SpringSecurityUserEventDecorator.java @@ -111,6 +111,25 @@ public void onLogin(Authentication authentication, Throwable throwable, Authenti } } + public void onUser(final Authentication authentication) { + if (authentication == null) { + return; + } + + final AppSecEventTracker tracker = AppSecEventTracker.getEventTracker(); + if (tracker == null) { + return; + } + + if (shouldSkipAuthentication(authentication)) { + return; + } + + UserIdCollectionMode mode = UserIdCollectionMode.get(); + String userId = authentication.getName(); + tracker.onUserEvent(mode, userId); + } + private static boolean shouldSkipAuthentication(final Authentication authentication) { if (authentication instanceof UsernamePasswordAuthenticationToken) { return false; diff --git a/dd-java-agent/instrumentation/spring-security-5/src/main/java/datadog/trace/instrumentation/springsecurity5/UserDetailsManagerInstrumentation.java b/dd-java-agent/instrumentation/spring-security-5/src/main/java/datadog/trace/instrumentation/springsecurity5/UserDetailsManagerInstrumentation.java index 1545edd41e0..cdbefae8760 100644 --- a/dd-java-agent/instrumentation/spring-security-5/src/main/java/datadog/trace/instrumentation/springsecurity5/UserDetailsManagerInstrumentation.java +++ b/dd-java-agent/instrumentation/spring-security-5/src/main/java/datadog/trace/instrumentation/springsecurity5/UserDetailsManagerInstrumentation.java @@ -9,8 +9,11 @@ import com.google.auto.service.AutoService; import datadog.trace.agent.tooling.Instrumenter; import datadog.trace.agent.tooling.InstrumenterModule; +import datadog.trace.bootstrap.ActiveSubsystems; +import net.bytebuddy.asm.Advice; import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.matcher.ElementMatcher; +import org.springframework.security.core.userdetails.UserDetails; @AutoService(InstrumenterModule.class) public class UserDetailsManagerInstrumentation extends InstrumenterModule.AppSec @@ -46,6 +49,18 @@ public void methodAdvice(MethodTransformer transformer) { takesArgument( 0, named("org.springframework.security.core.userdetails.UserDetails"))) .and(isPublic()), - packageName + ".UserDetailsManagerAdvice"); + getClass().getName() + "$UserDetailsManagerAdvice"); + } + + public static class UserDetailsManagerAdvice { + + @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) + public static void onExit( + @Advice.Argument(value = 0, readOnly = false) UserDetails user, + @Advice.Thrown Throwable throwable) { + if (ActiveSubsystems.APPSEC_ACTIVE) { + SpringSecurityUserEventDecorator.DECORATE.onSignup(user, throwable); + } + } } } diff --git a/dd-java-agent/instrumentation/spring-security-5/src/main/java/datadog/trace/instrumentation/springsecurity5/UsernameNotFoundExceptionInstrumentation.java b/dd-java-agent/instrumentation/spring-security-5/src/main/java/datadog/trace/instrumentation/springsecurity5/UsernameNotFoundExceptionInstrumentation.java index a2bf67c779a..38cd80fc061 100644 --- a/dd-java-agent/instrumentation/spring-security-5/src/main/java/datadog/trace/instrumentation/springsecurity5/UsernameNotFoundExceptionInstrumentation.java +++ b/dd-java-agent/instrumentation/spring-security-5/src/main/java/datadog/trace/instrumentation/springsecurity5/UsernameNotFoundExceptionInstrumentation.java @@ -9,6 +9,7 @@ import com.google.auto.service.AutoService; import datadog.trace.agent.tooling.Instrumenter; import datadog.trace.agent.tooling.InstrumenterModule; +import net.bytebuddy.asm.Advice; import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.matcher.ElementMatcher; @@ -41,6 +42,14 @@ public String[] helperClassNames() { public void methodAdvice(MethodTransformer transformer) { transformer.applyAdvice( isConstructor().and(takesArgument(0, named("java.lang.String"))).and(isPublic()), - packageName + ".UsernameNotFoundExceptionAdvice"); + getClass().getName() + "$UsernameNotFoundExceptionAdvice"); + } + + public static class UsernameNotFoundExceptionAdvice { + + @Advice.OnMethodEnter(suppress = Throwable.class) + public static void onEnter() { + SpringSecurityUserEventDecorator.DECORATE.onUserNotFound(); + } } } diff --git a/dd-java-agent/instrumentation/spring-security-5/src/main/java17/datadog/trace/instrumentation/springsecurity5/AuthenticationProviderAdvice.java b/dd-java-agent/instrumentation/spring-security-5/src/main/java17/datadog/trace/instrumentation/springsecurity5/AuthenticationProviderAdvice.java deleted file mode 100644 index 9afaa255ff0..00000000000 --- a/dd-java-agent/instrumentation/spring-security-5/src/main/java17/datadog/trace/instrumentation/springsecurity5/AuthenticationProviderAdvice.java +++ /dev/null @@ -1,19 +0,0 @@ -package datadog.trace.instrumentation.springsecurity5; - -import datadog.trace.bootstrap.ActiveSubsystems; -import net.bytebuddy.asm.Advice; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.AuthenticationException; - -public class AuthenticationProviderAdvice { - - @Advice.OnMethodExit(onThrowable = AuthenticationException.class, suppress = Throwable.class) - public static void onExit( - @Advice.Argument(value = 0, readOnly = false) Authentication authentication, - @Advice.Return final Authentication result, - @Advice.Thrown final AuthenticationException throwable) { - if (ActiveSubsystems.APPSEC_ACTIVE) { - SpringSecurityUserEventDecorator.DECORATE.onLogin(authentication, throwable, result); - } - } -} diff --git a/dd-java-agent/instrumentation/spring-security-5/src/main/java17/datadog/trace/instrumentation/springsecurity5/UserDetailsManagerAdvice.java b/dd-java-agent/instrumentation/spring-security-5/src/main/java17/datadog/trace/instrumentation/springsecurity5/UserDetailsManagerAdvice.java deleted file mode 100644 index fe36885e437..00000000000 --- a/dd-java-agent/instrumentation/spring-security-5/src/main/java17/datadog/trace/instrumentation/springsecurity5/UserDetailsManagerAdvice.java +++ /dev/null @@ -1,17 +0,0 @@ -package datadog.trace.instrumentation.springsecurity5; - -import datadog.trace.bootstrap.ActiveSubsystems; -import net.bytebuddy.asm.Advice; -import org.springframework.security.core.userdetails.UserDetails; - -public class UserDetailsManagerAdvice { - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void onExit( - @Advice.Argument(value = 0, readOnly = false) UserDetails user, - @Advice.Thrown Throwable throwable) { - if (ActiveSubsystems.APPSEC_ACTIVE) { - SpringSecurityUserEventDecorator.DECORATE.onSignup(user, throwable); - } - } -} diff --git a/dd-java-agent/instrumentation/spring-security-5/src/main/java17/datadog/trace/instrumentation/springsecurity5/UsernameNotFoundExceptionAdvice.java b/dd-java-agent/instrumentation/spring-security-5/src/main/java17/datadog/trace/instrumentation/springsecurity5/UsernameNotFoundExceptionAdvice.java deleted file mode 100644 index f3d24b75ea0..00000000000 --- a/dd-java-agent/instrumentation/spring-security-5/src/main/java17/datadog/trace/instrumentation/springsecurity5/UsernameNotFoundExceptionAdvice.java +++ /dev/null @@ -1,11 +0,0 @@ -package datadog.trace.instrumentation.springsecurity5; - -import net.bytebuddy.asm.Advice; - -public class UsernameNotFoundExceptionAdvice { - - @Advice.OnMethodEnter(suppress = Throwable.class) - public static void onEnter() { - SpringSecurityUserEventDecorator.DECORATE.onUserNotFound(); - } -} diff --git a/dd-java-agent/instrumentation/spring-security-5/src/test/groovy/datadog/trace/instrumentation/springsecurity5/SecurityConfig.groovy b/dd-java-agent/instrumentation/spring-security-5/src/test/groovy/datadog/trace/instrumentation/springsecurity5/SecurityConfig.groovy index e865ef18e5c..d5ce025ad32 100644 --- a/dd-java-agent/instrumentation/spring-security-5/src/test/groovy/datadog/trace/instrumentation/springsecurity5/SecurityConfig.groovy +++ b/dd-java-agent/instrumentation/spring-security-5/src/test/groovy/datadog/trace/instrumentation/springsecurity5/SecurityConfig.groovy @@ -2,20 +2,18 @@ package datadog.trace.instrumentation.springsecurity5 import custom.CustomAuthenticationFilter import custom.CustomAuthenticationProvider -import org.springframework.boot.jdbc.DataSourceBuilder import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.security.authentication.AuthenticationManager import org.springframework.security.config.annotation.web.builders.HttpSecurity import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer -import org.springframework.security.provisioning.JdbcUserDetailsManager +import org.springframework.security.core.userdetails.UserDetails +import org.springframework.security.provisioning.InMemoryUserDetailsManager import org.springframework.security.provisioning.UserDetailsManager import org.springframework.security.web.SecurityFilterChain import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter -import javax.sql.DataSource - import static datadog.trace.instrumentation.springsecurity5.SecurityConfig.CustomDsl.customDsl @Configuration @@ -26,28 +24,25 @@ class SecurityConfig { SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http.apply(customDsl()) http - .authorizeHttpRequests( - (requests) -> requests - .requestMatchers("/", "/success", "/register", "/login", "/custom").permitAll() - .anyRequest().authenticated()) .csrf().disable() .formLogin((form) -> form.loginPage("/login").permitAll()) + .authorizeRequests() + .antMatchers("/", "/success", "/register", "/login", "/custom").permitAll() + .anyRequest().authenticated() return http.build() } - @Bean - DataSource getDataSource() { - DataSourceBuilder dataSourceBuilder = DataSourceBuilder.create() - dataSourceBuilder.driverClassName("org.h2.Driver") - dataSourceBuilder.url("jdbc:h2:mem:authDB;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE;INIT=RUNSCRIPT FROM 'classpath:schema.sql';") - dataSourceBuilder.username("SA") - dataSourceBuilder.password("") - return dataSourceBuilder.build() - } - @Bean UserDetailsManager userDetailsService() { - return new JdbcUserDetailsManager(dataSource) + return new InMemoryUserDetailsManager() { + @Override + void createUser(UserDetails user) { + if (user.username == 'cant_create_me') { + throw new IllegalArgumentException('cannot create user') + } + super.createUser(user) + } + } } static class CustomDsl extends AbstractHttpConfigurer { diff --git a/dd-java-agent/instrumentation/spring-security-5/src/test/groovy/datadog/trace/instrumentation/springsecurity5/SpringBootBasedTest.groovy b/dd-java-agent/instrumentation/spring-security-5/src/test/groovy/datadog/trace/instrumentation/springsecurity5/SpringBootBasedTest.groovy index a9262731ef3..96f9c21836c 100644 --- a/dd-java-agent/instrumentation/spring-security-5/src/test/groovy/datadog/trace/instrumentation/springsecurity5/SpringBootBasedTest.groovy +++ b/dd-java-agent/instrumentation/spring-security-5/src/test/groovy/datadog/trace/instrumentation/springsecurity5/SpringBootBasedTest.groovy @@ -15,10 +15,13 @@ import org.springframework.boot.web.servlet.context.ServletWebServerApplicationC import org.springframework.context.ConfigurableApplicationContext import spock.lang.Shared -import static datadog.trace.instrumentation.springsecurity5.TestEndpoint.LOGIN +import static datadog.trace.agent.test.utils.OkHttpUtils.clientBuilder +import static datadog.trace.agent.test.utils.OkHttpUtils.cookieJar import static datadog.trace.agent.test.utils.TraceUtils.runUnderTrace import static datadog.trace.instrumentation.springsecurity5.TestEndpoint.CUSTOM +import static datadog.trace.instrumentation.springsecurity5.TestEndpoint.LOGIN import static datadog.trace.instrumentation.springsecurity5.TestEndpoint.REGISTER +import static datadog.trace.instrumentation.springsecurity5.TestEndpoint.SUCCESS import static datadog.trace.instrumentation.springsecurity5.TestEndpoint.UNKNOWN import static datadog.trace.instrumentation.springsecurity5.TestEndpoint.NOT_FOUND @@ -213,7 +216,7 @@ class SpringBootBasedTest extends AppSecHttpServerTest - (1..length).collect { Character.valueOf((char) (random.nextInt(26) + (char)'a')) } - }.join() + void 'test user event'() { + setup: + def client = clientBuilder().cookieJar(cookieJar()).followRedirects(false).build() + def formBody = new FormBody.Builder() + .add("username", "admin") + .add("password", "admin") + .build() + + def loginRequest = request(LOGIN, "POST", formBody).build() + def loginResponse = client.newCall(loginRequest).execute() + assert loginResponse.code() == LOGIN.status + assert loginResponse.body().string() == LOGIN.body + TEST_WRITER.waitForTraces(1) + TEST_WRITER.start() // clear all traces + + when: + def request = request(SUCCESS, "GET", null).build() + def response = client.newCall(request).execute() + TEST_WRITER.waitForTraces(1) + def span = TEST_WRITER.flatten().first() as DDSpan + + then: + response.code() == SUCCESS.status + response.body().string() == SUCCESS.body + span.getResourceName().toString() == 'GET /success' + !span.getTags().isEmpty() + span.getTag("usr.id") == 'admin' + span.getTag("_dd.appsec.user.collection_mode") == 'ident' } } diff --git a/dd-java-agent/instrumentation/spring-security-5/src/test/groovy/datadog/trace/instrumentation/springsecurity5/TestEndpoint.groovy b/dd-java-agent/instrumentation/spring-security-5/src/test/groovy/datadog/trace/instrumentation/springsecurity5/TestEndpoint.groovy index bb6d223a7a7..3a558355471 100644 --- a/dd-java-agent/instrumentation/spring-security-5/src/test/groovy/datadog/trace/instrumentation/springsecurity5/TestEndpoint.groovy +++ b/dd-java-agent/instrumentation/spring-security-5/src/test/groovy/datadog/trace/instrumentation/springsecurity5/TestEndpoint.groovy @@ -6,6 +6,7 @@ enum TestEndpoint { NOT_FOUND("not-found", 404, "not found"), UNKNOWN("", 451, null), // This needs to have a valid status code CUSTOM("custom", 302, ""), + SUCCESS("success", 200, ""), private final String path private final String rawPath diff --git a/dd-java-agent/instrumentation/spring-security-5/src/test/java/custom/CustomAuthenticationFilter.java b/dd-java-agent/instrumentation/spring-security-5/src/test/java/custom/CustomAuthenticationFilter.java index b3ec62a572b..f63ccdc574d 100644 --- a/dd-java-agent/instrumentation/spring-security-5/src/test/java/custom/CustomAuthenticationFilter.java +++ b/dd-java-agent/instrumentation/spring-security-5/src/test/java/custom/CustomAuthenticationFilter.java @@ -1,9 +1,9 @@ package custom; -import jakarta.servlet.ServletException; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; diff --git a/dd-java-agent/instrumentation/spring-security-5/src/test/resources/schema.sql b/dd-java-agent/instrumentation/spring-security-5/src/test/resources/schema.sql deleted file mode 100644 index f7a9a7728ca..00000000000 --- a/dd-java-agent/instrumentation/spring-security-5/src/test/resources/schema.sql +++ /dev/null @@ -1,30 +0,0 @@ -create table IF NOT EXISTS users( - username varchar_ignorecase(50) not null primary key, - password varchar_ignorecase(500) not null, - enabled boolean not null -); - -create table IF NOT EXISTS authorities ( - username varchar_ignorecase(50) not null, - authority varchar_ignorecase(50) not null, - constraint fk_authorities_users foreign key(username) references users(username) -); -create unique index IF NOT EXISTS ix_auth_username on authorities (username,authority); - -create table IF NOT EXISTS groups ( - id bigint generated by default as identity(start with 0) primary key, - group_name varchar_ignorecase(50) not null -); - -create table IF NOT EXISTS group_authorities ( - group_id bigint not null, - authority varchar(50) not null, - constraint fk_group_authorities_group foreign key(group_id) references groups(id) -); - -create table IF NOT EXISTS group_members ( - id bigint generated by default as identity(start with 0) primary key, - username varchar(50) not null, - group_id bigint not null, - constraint fk_group_members_group foreign key(group_id) references groups(id) -); \ No newline at end of file diff --git a/dd-java-agent/instrumentation/spring-security-6/build.gradle b/dd-java-agent/instrumentation/spring-security-6/build.gradle new file mode 100644 index 00000000000..e746ed3f9c5 --- /dev/null +++ b/dd-java-agent/instrumentation/spring-security-6/build.gradle @@ -0,0 +1,32 @@ +ext { + minJavaVersionForTests = JavaVersion.VERSION_17 +} + +apply from: "$rootDir/gradle/java.gradle" +addTestSuiteForDir('latestDepTest', 'test') + +final springBootVersion = '3.0.0' + +tasks.withType(AbstractCompile).configureEach { + setJavaVersion(it, 17) +} + +tasks.withType(GroovyCompile).configureEach { + javaLauncher = getJavaLauncherFor(17) +} + +dependencies { + + testImplementation testFixtures(project(':dd-java-agent:appsec')) + testImplementation project(':dd-java-agent:instrumentation:spring-security-5') + testImplementation group: 'org.springframework.boot', name: 'spring-boot-starter-test', version: springBootVersion + testImplementation group: 'org.springframework.boot', name: 'spring-boot-starter-web', version: springBootVersion + testImplementation group: 'org.springframework.boot', name: 'spring-boot-starter-security', version: springBootVersion + + latestDepTestImplementation group: 'org.springframework.boot', name: 'spring-boot-starter-test', version: '+' + latestDepTestImplementation group: 'org.springframework.boot', name: 'spring-boot-starter-web', version: '+' + latestDepTestImplementation group: 'org.springframework.boot', name: 'spring-boot-starter-security', version: '+' + + testRuntimeOnly project(':dd-java-agent:instrumentation:tomcat-appsec-6') + testRuntimeOnly project(':dd-java-agent:instrumentation:tomcat-5.5') +} diff --git a/dd-java-agent/instrumentation/spring-security-6/gradle.lockfile b/dd-java-agent/instrumentation/spring-security-6/gradle.lockfile new file mode 100644 index 00000000000..0f542362a9c --- /dev/null +++ b/dd-java-agent/instrumentation/spring-security-6/gradle.lockfile @@ -0,0 +1,272 @@ +# This is a Gradle generated file for dependency locking. +# Manual edits can break the build and are not advised. +# This file is expected to be part of source control. +cafe.cryptography:curve25519-elisabeth:0.1.0=instrumentPluginClasspath,latestDepTestRuntimeClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath +cafe.cryptography:ed25519-elisabeth:0.1.0=instrumentPluginClasspath,latestDepTestRuntimeClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath +ch.qos.logback:logback-classic:1.4.5=testCompileClasspath,testRuntimeClasspath +ch.qos.logback:logback-classic:1.5.7=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +ch.qos.logback:logback-core:1.4.5=testCompileClasspath,testRuntimeClasspath +ch.qos.logback:logback-core:1.5.7=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +com.beust:jcommander:1.78=latestDepTestRuntimeClasspath,testRuntimeClasspath +com.blogspot.mydailyjava:weak-lock-free:0.17=compileClasspath,instrumentPluginClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,main_java17CompileClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +com.datadoghq.okhttp3:okhttp:3.12.15=compileClasspath,instrumentPluginClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,main_java17CompileClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +com.datadoghq.okio:okio:1.17.6=compileClasspath,instrumentPluginClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,main_java17CompileClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +com.datadoghq:dd-javac-plugin-client:0.1.7=compileClasspath,instrumentPluginClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,main_java17CompileClasspath,main_java17RuntimeClasspath,muzzleBootstrap,muzzleTooling,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +com.datadoghq:java-dogstatsd-client:4.4.0=instrumentPluginClasspath,latestDepTestRuntimeClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath +com.datadoghq:sketches-java:0.8.3=instrumentPluginClasspath,latestDepTestRuntimeClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath +com.fasterxml.jackson.core:jackson-annotations:2.14.1=testCompileClasspath,testRuntimeClasspath +com.fasterxml.jackson.core:jackson-annotations:2.17.2=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +com.fasterxml.jackson.core:jackson-core:2.14.1=testCompileClasspath,testRuntimeClasspath +com.fasterxml.jackson.core:jackson-core:2.17.2=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +com.fasterxml.jackson.core:jackson-databind:2.14.1=testCompileClasspath,testRuntimeClasspath +com.fasterxml.jackson.core:jackson-databind:2.17.2=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.14.1=testCompileClasspath,testRuntimeClasspath +com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.17.2=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.14.1=testCompileClasspath,testRuntimeClasspath +com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.17.2=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +com.fasterxml.jackson.module:jackson-module-parameter-names:2.14.1=testCompileClasspath,testRuntimeClasspath +com.fasterxml.jackson.module:jackson-module-parameter-names:2.17.2=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +com.fasterxml.jackson:jackson-bom:2.14.1=testCompileClasspath,testRuntimeClasspath +com.fasterxml.jackson:jackson-bom:2.17.2=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +com.github.javaparser:javaparser-core:3.25.1=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +com.github.jnr:jffi:1.3.13=instrumentPluginClasspath,latestDepTestRuntimeClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath +com.github.jnr:jnr-a64asm:1.0.0=instrumentPluginClasspath,latestDepTestRuntimeClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath +com.github.jnr:jnr-constants:0.10.4=instrumentPluginClasspath,latestDepTestRuntimeClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath +com.github.jnr:jnr-enxio:0.32.17=instrumentPluginClasspath,latestDepTestRuntimeClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath +com.github.jnr:jnr-ffi:2.2.16=instrumentPluginClasspath,latestDepTestRuntimeClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath +com.github.jnr:jnr-posix:3.1.19=instrumentPluginClasspath,latestDepTestRuntimeClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath +com.github.jnr:jnr-unixsocket:0.38.22=instrumentPluginClasspath,latestDepTestRuntimeClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath +com.github.jnr:jnr-x86asm:1.0.2=instrumentPluginClasspath,latestDepTestRuntimeClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath +com.github.spotbugs:spotbugs-annotations:4.2.0=compileClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +com.github.spotbugs:spotbugs-annotations:4.7.3=spotbugs +com.github.spotbugs:spotbugs:4.7.3=spotbugs +com.github.stefanbirkner:system-rules:1.19.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +com.google.auto.service:auto-service-annotations:1.0-rc7=annotationProcessor,compileClasspath,latestDepTestAnnotationProcessor,latestDepTestCompileClasspath,testAnnotationProcessor,testCompileClasspath +com.google.auto.service:auto-service:1.0-rc7=annotationProcessor,latestDepTestAnnotationProcessor,testAnnotationProcessor +com.google.auto:auto-common:0.10=annotationProcessor,latestDepTestAnnotationProcessor,testAnnotationProcessor +com.google.code.findbugs:jsr305:3.0.2=annotationProcessor,compileClasspath,latestDepTestAnnotationProcessor,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,spotbugs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath +com.google.code.gson:gson:2.9.1=spotbugs +com.google.errorprone:error_prone_annotations:2.2.0=annotationProcessor,latestDepTestAnnotationProcessor,testAnnotationProcessor +com.google.guava:failureaccess:1.0.1=annotationProcessor,latestDepTestAnnotationProcessor,testAnnotationProcessor +com.google.guava:guava:20.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +com.google.guava:guava:27.0.1-jre=annotationProcessor,latestDepTestAnnotationProcessor,testAnnotationProcessor +com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava=annotationProcessor,latestDepTestAnnotationProcessor,testAnnotationProcessor +com.google.j2objc:j2objc-annotations:1.1=annotationProcessor,latestDepTestAnnotationProcessor,testAnnotationProcessor +com.google.re2j:re2j:1.7=instrumentPluginClasspath,latestDepTestRuntimeClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath +com.jayway.jsonpath:json-path:2.7.0=testCompileClasspath,testRuntimeClasspath +com.jayway.jsonpath:json-path:2.9.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +com.squareup.moshi:moshi:1.11.0=compileClasspath,instrumentPluginClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,main_java17CompileClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +com.squareup.okhttp3:logging-interceptor:3.12.12=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +com.squareup.okhttp3:okhttp:3.12.12=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +com.squareup.okio:okio:1.17.5=compileClasspath,instrumentPluginClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,main_java17CompileClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +com.thoughtworks.qdox:qdox:1.12.1=latestDepTestRuntimeClasspath,testRuntimeClasspath +com.vaadin.external.google:android-json:0.0.20131108.vaadin1=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +commons-codec:commons-codec:1.15=spotbugs +commons-fileupload:commons-fileupload:1.5=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +commons-io:commons-io:2.11.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +de.thetaphi:forbiddenapis:3.1=compileClasspath +info.picocli:picocli:4.6.3=latestDepTestRuntimeClasspath,testRuntimeClasspath +io.micrometer:micrometer-commons:1.10.1=testCompileClasspath,testRuntimeClasspath +io.micrometer:micrometer-commons:1.12.9=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +io.micrometer:micrometer-observation:1.10.1=testCompileClasspath,testRuntimeClasspath +io.micrometer:micrometer-observation:1.12.9=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +io.sqreen:libsqreen:11.0.0=latestDepTestRuntimeClasspath,testRuntimeClasspath +jakarta.activation:jakarta.activation-api:2.1.0=testCompileClasspath,testRuntimeClasspath +jakarta.activation:jakarta.activation-api:2.1.3=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +jakarta.annotation:jakarta.annotation-api:2.1.1=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +jakarta.xml.bind:jakarta.xml.bind-api:4.0.0=testCompileClasspath,testRuntimeClasspath +jakarta.xml.bind:jakarta.xml.bind-api:4.0.2=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +javax.servlet:javax.servlet-api:3.1.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +jaxen:jaxen:1.2.0=spotbugs +jline:jline:2.14.6=latestDepTestRuntimeClasspath,testRuntimeClasspath +junit:junit-dep:4.11=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +junit:junit:4.13.2=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +net.bytebuddy:byte-buddy-agent:1.14.18=compileClasspath,instrumentPluginClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,main_java17CompileClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +net.bytebuddy:byte-buddy:1.14.18=compileClasspath,instrumentPluginClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,main_java17CompileClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +net.java.dev.jna:jna-platform:5.8.0=instrumentPluginClasspath,latestDepTestRuntimeClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath +net.java.dev.jna:jna:5.8.0=instrumentPluginClasspath,latestDepTestRuntimeClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath +net.jcip:jcip-annotations:1.0=compileClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,spotbugs,testCompileClasspath,testRuntimeClasspath +net.minidev:accessors-smart:2.4.7=testCompileClasspath,testRuntimeClasspath +net.minidev:accessors-smart:2.5.1=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +net.minidev:json-smart:2.4.7=testCompileClasspath,testRuntimeClasspath +net.minidev:json-smart:2.5.1=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +net.sf.saxon:Saxon-HE:11.4=spotbugs +org.apache.ant:ant-antlr:1.10.12=latestDepTestRuntimeClasspath,testRuntimeClasspath +org.apache.ant:ant-antlr:1.9.15=codenarc +org.apache.ant:ant-junit:1.10.12=latestDepTestRuntimeClasspath,testRuntimeClasspath +org.apache.ant:ant-junit:1.9.15=codenarc +org.apache.ant:ant-launcher:1.10.12=latestDepTestRuntimeClasspath,testRuntimeClasspath +org.apache.ant:ant:1.10.12=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.apache.bcel:bcel:6.5.0=spotbugs +org.apache.commons:commons-lang3:3.12.0=spotbugs +org.apache.commons:commons-text:1.10.0=spotbugs +org.apache.httpcomponents.client5:httpclient5:5.1.3=spotbugs +org.apache.httpcomponents.core5:httpcore5-h2:5.1.3=spotbugs +org.apache.httpcomponents.core5:httpcore5:5.1.3=spotbugs +org.apache.logging.log4j:log4j-api:2.19.0=spotbugs,testCompileClasspath,testRuntimeClasspath +org.apache.logging.log4j:log4j-api:2.23.1=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.apache.logging.log4j:log4j-core:2.19.0=spotbugs +org.apache.logging.log4j:log4j-to-slf4j:2.19.0=testCompileClasspath,testRuntimeClasspath +org.apache.logging.log4j:log4j-to-slf4j:2.23.1=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.apache.tomcat.embed:tomcat-embed-core:10.1.1=testCompileClasspath,testRuntimeClasspath +org.apache.tomcat.embed:tomcat-embed-core:10.1.28=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.apache.tomcat.embed:tomcat-embed-el:10.1.1=testCompileClasspath,testRuntimeClasspath +org.apache.tomcat.embed:tomcat-embed-el:10.1.28=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.apache.tomcat.embed:tomcat-embed-websocket:10.1.1=testCompileClasspath,testRuntimeClasspath +org.apache.tomcat.embed:tomcat-embed-websocket:10.1.28=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.apiguardian:apiguardian-api:1.1.2=latestDepTestCompileClasspath,testCompileClasspath +org.assertj:assertj-core:3.23.1=testCompileClasspath,testRuntimeClasspath +org.assertj:assertj-core:3.25.3=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.awaitility:awaitility:4.2.2=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.checkerframework:checker-qual:2.5.2=annotationProcessor,latestDepTestAnnotationProcessor,testAnnotationProcessor +org.codehaus.groovy:groovy-all:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-ant:2.5.14=codenarc +org.codehaus.groovy:groovy-ant:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-astbuilder:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-cli-picocli:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-console:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-datetime:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-docgenerator:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-groovydoc:2.5.14=codenarc +org.codehaus.groovy:groovy-groovydoc:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-groovysh:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-jmx:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-json:2.5.14=codenarc +org.codehaus.groovy:groovy-json:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-jsr223:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-macro:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-nio:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-servlet:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-sql:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-swing:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-templates:2.5.14=codenarc +org.codehaus.groovy:groovy-templates:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-test-junit5:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-test:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-testng:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-xml:2.5.14=codenarc +org.codehaus.groovy:groovy-xml:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy:2.5.14=codenarc +org.codehaus.groovy:groovy:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.mojo:animal-sniffer-annotations:1.17=annotationProcessor,latestDepTestAnnotationProcessor,testAnnotationProcessor +org.codenarc:CodeNarc:2.2.0=codenarc +org.dom4j:dom4j:2.1.3=spotbugs +org.eclipse.jetty:jetty-http:9.2.30.v20200428=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.eclipse.jetty:jetty-io:9.2.30.v20200428=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.eclipse.jetty:jetty-server:9.2.30.v20200428=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.eclipse.jetty:jetty-util:9.2.30.v20200428=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.gmetrics:GMetrics:1.1=codenarc +org.hamcrest:hamcrest-core:1.3=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.hamcrest:hamcrest:2.2=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.jctools:jctools-core:3.3.0=instrumentPluginClasspath,latestDepTestRuntimeClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath +org.junit.jupiter:junit-jupiter-api:5.10.3=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.junit.jupiter:junit-jupiter-api:5.9.2=testCompileClasspath,testRuntimeClasspath +org.junit.jupiter:junit-jupiter-engine:5.10.3=latestDepTestRuntimeClasspath +org.junit.jupiter:junit-jupiter-engine:5.9.2=testRuntimeClasspath +org.junit.jupiter:junit-jupiter-params:5.10.3=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.junit.jupiter:junit-jupiter-params:5.9.2=testCompileClasspath,testRuntimeClasspath +org.junit.jupiter:junit-jupiter:5.10.3=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.junit.jupiter:junit-jupiter:5.9.2=testCompileClasspath,testRuntimeClasspath +org.junit.platform:junit-platform-commons:1.10.3=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.junit.platform:junit-platform-commons:1.9.2=testCompileClasspath,testRuntimeClasspath +org.junit.platform:junit-platform-engine:1.10.3=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.junit.platform:junit-platform-engine:1.9.2=testCompileClasspath,testRuntimeClasspath +org.junit.platform:junit-platform-launcher:1.10.3=latestDepTestRuntimeClasspath +org.junit.platform:junit-platform-launcher:1.9.2=testRuntimeClasspath +org.junit.platform:junit-platform-runner:1.10.3=latestDepTestRuntimeClasspath +org.junit.platform:junit-platform-runner:1.9.2=testRuntimeClasspath +org.junit.platform:junit-platform-suite-api:1.10.3=latestDepTestRuntimeClasspath +org.junit.platform:junit-platform-suite-api:1.9.2=testRuntimeClasspath +org.junit.platform:junit-platform-suite-commons:1.10.3=latestDepTestRuntimeClasspath +org.junit.platform:junit-platform-suite-commons:1.9.2=testRuntimeClasspath +org.junit:junit-bom:5.10.3=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.junit:junit-bom:5.9.2=testCompileClasspath,testRuntimeClasspath +org.mockito:mockito-core:4.8.1=testCompileClasspath,testRuntimeClasspath +org.mockito:mockito-core:5.11.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.mockito:mockito-junit-jupiter:4.8.1=testCompileClasspath,testRuntimeClasspath +org.mockito:mockito-junit-jupiter:5.11.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.objenesis:objenesis:3.3=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.opentest4j:opentest4j:1.2.0=testCompileClasspath,testRuntimeClasspath +org.opentest4j:opentest4j:1.3.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.ow2.asm:asm-analysis:9.2=instrumentPluginClasspath,latestDepTestRuntimeClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath +org.ow2.asm:asm-analysis:9.4=spotbugs +org.ow2.asm:asm-commons:9.2=instrumentPluginClasspath,latestDepTestRuntimeClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath +org.ow2.asm:asm-commons:9.4=spotbugs +org.ow2.asm:asm-tree:9.2=instrumentPluginClasspath,latestDepTestRuntimeClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath +org.ow2.asm:asm-tree:9.4=spotbugs +org.ow2.asm:asm-util:9.2=instrumentPluginClasspath,latestDepTestRuntimeClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath +org.ow2.asm:asm-util:9.4=spotbugs +org.ow2.asm:asm:9.1=testCompileClasspath +org.ow2.asm:asm:9.2=instrumentPluginClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath +org.ow2.asm:asm:9.4=spotbugs +org.ow2.asm:asm:9.6=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.skyscreamer:jsonassert:1.5.1=testCompileClasspath,testRuntimeClasspath +org.skyscreamer:jsonassert:1.5.3=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.slf4j:jcl-over-slf4j:1.7.30=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.slf4j:jul-to-slf4j:2.0.16=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.slf4j:jul-to-slf4j:2.0.4=testCompileClasspath,testRuntimeClasspath +org.slf4j:log4j-over-slf4j:1.7.30=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.slf4j:slf4j-api:1.7.30=compileClasspath,instrumentPluginClasspath,main_java17CompileClasspath,main_java17RuntimeClasspath,muzzleBootstrap,muzzleTooling,runtimeClasspath +org.slf4j:slf4j-api:2.0.0=spotbugs,spotbugsSlf4j +org.slf4j:slf4j-api:2.0.16=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.slf4j:slf4j-api:2.0.4=testCompileClasspath,testRuntimeClasspath +org.slf4j:slf4j-simple:2.0.0=spotbugsSlf4j +org.spockframework:spock-core:2.2-groovy-3.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.spockframework:spock-junit4:2.2-groovy-3.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.springframework.boot:spring-boot-autoconfigure:3.0.0=testCompileClasspath,testRuntimeClasspath +org.springframework.boot:spring-boot-autoconfigure:3.3.3=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.springframework.boot:spring-boot-starter-json:3.0.0=testCompileClasspath,testRuntimeClasspath +org.springframework.boot:spring-boot-starter-json:3.3.3=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.springframework.boot:spring-boot-starter-logging:3.0.0=testCompileClasspath,testRuntimeClasspath +org.springframework.boot:spring-boot-starter-logging:3.3.3=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.springframework.boot:spring-boot-starter-security:3.0.0=testCompileClasspath,testRuntimeClasspath +org.springframework.boot:spring-boot-starter-security:3.3.3=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.springframework.boot:spring-boot-starter-test:3.0.0=testCompileClasspath,testRuntimeClasspath +org.springframework.boot:spring-boot-starter-test:3.3.3=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.springframework.boot:spring-boot-starter-tomcat:3.0.0=testCompileClasspath,testRuntimeClasspath +org.springframework.boot:spring-boot-starter-tomcat:3.3.3=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.springframework.boot:spring-boot-starter-web:3.0.0=testCompileClasspath,testRuntimeClasspath +org.springframework.boot:spring-boot-starter-web:3.3.3=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.springframework.boot:spring-boot-starter:3.0.0=testCompileClasspath,testRuntimeClasspath +org.springframework.boot:spring-boot-starter:3.3.3=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.springframework.boot:spring-boot-test-autoconfigure:3.0.0=testCompileClasspath,testRuntimeClasspath +org.springframework.boot:spring-boot-test-autoconfigure:3.3.3=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.springframework.boot:spring-boot-test:3.0.0=testCompileClasspath,testRuntimeClasspath +org.springframework.boot:spring-boot-test:3.3.3=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.springframework.boot:spring-boot:3.0.0=testCompileClasspath,testRuntimeClasspath +org.springframework.boot:spring-boot:3.3.3=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.springframework.security:spring-security-config:6.0.0=testCompileClasspath,testRuntimeClasspath +org.springframework.security:spring-security-config:6.3.3=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.springframework.security:spring-security-core:6.0.0=testCompileClasspath,testRuntimeClasspath +org.springframework.security:spring-security-core:6.3.3=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.springframework.security:spring-security-crypto:6.0.0=testCompileClasspath,testRuntimeClasspath +org.springframework.security:spring-security-crypto:6.3.3=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.springframework.security:spring-security-web:6.0.0=testCompileClasspath,testRuntimeClasspath +org.springframework.security:spring-security-web:6.3.3=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.springframework:spring-aop:6.0.2=testCompileClasspath,testRuntimeClasspath +org.springframework:spring-aop:6.1.12=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.springframework:spring-beans:6.0.2=testCompileClasspath,testRuntimeClasspath +org.springframework:spring-beans:6.1.12=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.springframework:spring-context:6.0.2=testCompileClasspath,testRuntimeClasspath +org.springframework:spring-context:6.1.12=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.springframework:spring-core:6.0.2=testCompileClasspath,testRuntimeClasspath +org.springframework:spring-core:6.1.12=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.springframework:spring-expression:6.0.2=testCompileClasspath,testRuntimeClasspath +org.springframework:spring-expression:6.1.12=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.springframework:spring-jcl:6.0.2=testCompileClasspath,testRuntimeClasspath +org.springframework:spring-jcl:6.1.12=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.springframework:spring-test:6.0.2=testCompileClasspath,testRuntimeClasspath +org.springframework:spring-test:6.1.12=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.springframework:spring-web:6.0.2=testCompileClasspath,testRuntimeClasspath +org.springframework:spring-web:6.1.12=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.springframework:spring-webmvc:6.0.2=testCompileClasspath,testRuntimeClasspath +org.springframework:spring-webmvc:6.1.12=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.testng:testng:7.5=latestDepTestRuntimeClasspath,testRuntimeClasspath +org.webjars:jquery:3.5.1=latestDepTestRuntimeClasspath,testRuntimeClasspath +org.xmlresolver:xmlresolver:4.4.3=spotbugs +org.xmlunit:xmlunit-core:2.9.0=testCompileClasspath,testRuntimeClasspath +org.xmlunit:xmlunit-core:2.9.1=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.yaml:snakeyaml:1.33=testCompileClasspath,testRuntimeClasspath +org.yaml:snakeyaml:2.2=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +xml-apis:xml-apis:1.4.01=spotbugs +empty=main_java17AnnotationProcessor,spotbugsPlugins diff --git a/dd-java-agent/instrumentation/spring-security-6/src/test/groovy/datadog/trace/instrumentation/springsecurity6/AppConfig.groovy b/dd-java-agent/instrumentation/spring-security-6/src/test/groovy/datadog/trace/instrumentation/springsecurity6/AppConfig.groovy new file mode 100644 index 00000000000..c33b48693a4 --- /dev/null +++ b/dd-java-agent/instrumentation/spring-security-6/src/test/groovy/datadog/trace/instrumentation/springsecurity6/AppConfig.groovy @@ -0,0 +1,11 @@ +package datadog.trace.instrumentation.springsecurity6 + +import org.springframework.boot.autoconfigure.SpringBootApplication +import org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer + +// Component scan defeats the purpose of configuring with specific classes +@SpringBootApplication(exclude = [ErrorMvcAutoConfiguration]) +class AppConfig implements WebMvcConfigurer { + +} diff --git a/dd-java-agent/instrumentation/spring-security-6/src/test/groovy/datadog/trace/instrumentation/springsecurity6/SecurityConfig.groovy b/dd-java-agent/instrumentation/spring-security-6/src/test/groovy/datadog/trace/instrumentation/springsecurity6/SecurityConfig.groovy new file mode 100644 index 00000000000..623698699b7 --- /dev/null +++ b/dd-java-agent/instrumentation/spring-security-6/src/test/groovy/datadog/trace/instrumentation/springsecurity6/SecurityConfig.groovy @@ -0,0 +1,58 @@ +package datadog.trace.instrumentation.springsecurity6 + +import custom.CustomAuthenticationFilter +import custom.CustomAuthenticationProvider +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import org.springframework.security.authentication.AuthenticationManager +import org.springframework.security.config.annotation.web.builders.HttpSecurity +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity +import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer +import org.springframework.security.core.userdetails.UserDetails +import org.springframework.security.provisioning.InMemoryUserDetailsManager +import org.springframework.security.provisioning.UserDetailsManager +import org.springframework.security.web.SecurityFilterChain +import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter + +@Configuration +@EnableWebSecurity +class SecurityConfig { + + @Bean + SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { + http.apply(CustomDsl.customDsl()) + http + .csrf().disable() + .formLogin((form) -> form.loginPage("/login").permitAll()) + .authorizeHttpRequests() + .requestMatchers("/", "/success", "/register", "/login", "/custom").permitAll() + .anyRequest().authenticated() + return http.build() + } + + @Bean + UserDetailsManager userDetailsService() { + return new InMemoryUserDetailsManager() { + @Override + void createUser(UserDetails user) { + if (user.username == 'cant_create_me') { + throw new IllegalArgumentException('cannot create user') + } + super.createUser(user) + } + } + } + + static class CustomDsl extends AbstractHttpConfigurer { + @Override + void configure(HttpSecurity http) throws Exception { + AuthenticationManager authenticationManager = http.getSharedObject(AuthenticationManager) + http.authenticationProvider(new CustomAuthenticationProvider()) + http.addFilterBefore(new CustomAuthenticationFilter(authenticationManager), UsernamePasswordAuthenticationFilter) + } + + static CustomDsl customDsl() { + return new CustomDsl() + } + } +} diff --git a/dd-java-agent/instrumentation/spring-security-6/src/test/groovy/datadog/trace/instrumentation/springsecurity6/SpringBootBasedTest.groovy b/dd-java-agent/instrumentation/spring-security-6/src/test/groovy/datadog/trace/instrumentation/springsecurity6/SpringBootBasedTest.groovy new file mode 100644 index 00000000000..0dca21ff574 --- /dev/null +++ b/dd-java-agent/instrumentation/spring-security-6/src/test/groovy/datadog/trace/instrumentation/springsecurity6/SpringBootBasedTest.groovy @@ -0,0 +1,291 @@ +package datadog.trace.instrumentation.springsecurity6 + +import ch.qos.logback.classic.Logger +import ch.qos.logback.core.Appender +import com.datadog.appsec.AppSecHttpServerTest +import datadog.trace.agent.test.base.HttpServer +import datadog.trace.api.config.AppSecConfig +import datadog.trace.core.DDSpan +import datadog.trace.instrumentation.springsecurity5.SpringSecurityUserEventDecorator +import okhttp3.FormBody +import okhttp3.HttpUrl +import okhttp3.Request +import okhttp3.RequestBody +import org.springframework.boot.SpringApplication +import org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext +import org.springframework.context.ConfigurableApplicationContext +import spock.lang.Shared + +import static datadog.trace.agent.test.utils.OkHttpUtils.clientBuilder +import static datadog.trace.agent.test.utils.OkHttpUtils.cookieJar +import static datadog.trace.agent.test.utils.TraceUtils.runUnderTrace +import static datadog.trace.instrumentation.springsecurity6.TestEndpoint.CUSTOM +import static datadog.trace.instrumentation.springsecurity6.TestEndpoint.LOGIN +import static datadog.trace.instrumentation.springsecurity6.TestEndpoint.NOT_FOUND +import static datadog.trace.instrumentation.springsecurity6.TestEndpoint.REGISTER +import static datadog.trace.instrumentation.springsecurity6.TestEndpoint.SUCCESS +import static datadog.trace.instrumentation.springsecurity6.TestEndpoint.UNKNOWN + +class SpringBootBasedTest extends AppSecHttpServerTest { + + @Shared + def context + + SpringApplication application() { + return new SpringApplication(AppConfig, UserController, SecurityConfig) + } + + class SpringBootServer implements HttpServer { + def port = 0 + final app = application() + + @Override + void start() { + app.setDefaultProperties(["server.port": 0, "server.context-path": "/"]) + context = app.run() + port = (context as ServletWebServerApplicationContext).webServer.port + assert port > 0 + } + + @Override + void stop() { + context.close() + } + + @Override + URI address() { + return new URI("http://localhost:$port/") + } + + @Override + String toString() { + return this.class.name + } + } + + @Override + HttpServer server() { + return new SpringBootServer() + } + + + @Override + int version() { + return 0 + } + + @Override + String service() { + return null + } + + @Override + String operation() { + return null + } + + @Override + protected void configurePreAgent() { + super.configurePreAgent() + injectSysConfig(AppSecConfig.APPSEC_AUTO_USER_INSTRUMENTATION_MODE, 'identification') + } + + Request.Builder request(TestEndpoint uri, String method, RequestBody body) { + def url = HttpUrl.get(uri.resolve(address)).newBuilder() + .encodedQuery(uri.rawQuery) + .fragment(uri.fragment) + .build() + return new Request.Builder() + .url(url) + //.addHeader('user-agent', 'Arachni/v1') + .method(method, body) + } + + static T controller(TestEndpoint endpoint, Closure closure) { + if (endpoint == NOT_FOUND || endpoint == UNKNOWN) { + return closure() + } + return runUnderTrace("controller", closure) + } + + + def "test signup event"() { + setup: + RequestBody formBody = new FormBody.Builder() + .add("username", "admin") + .add("password", "admin") + .build() + + def request = request(REGISTER, "POST", formBody).build() + + when: + def response = client.newCall(request).execute() + TEST_WRITER.waitForTraces(1) + DDSpan span = TEST_WRITER.flatten().first() + + then: + response.code() == REGISTER.status + response.body().string() == REGISTER.body + !span.getTags().isEmpty() + span.getTag("appsec.events.users.signup.track") == true + span.getTag("_dd.appsec.events.users.signup.auto.mode") == 'identification' + span.getTag("usr.id") == 'admin' + span.getTag("appsec.events.users.signup")['enabled'] == 'true' + span.getTag("appsec.events.users.signup")['authorities'] == 'ROLE_USER' + } + + + def "test failed login with non existing user"() { + setup: + RequestBody formBody = new FormBody.Builder() + .add("username", "not_existing_user") + .add("password", "some_password") + .build() + + def request = request(LOGIN, "POST", formBody).build() + + when: + def response = client.newCall(request).execute() + TEST_WRITER.waitForTraces(1) + DDSpan span = TEST_WRITER.flatten().first() + + then: + response.code() == LOGIN.status + response.body().string() == LOGIN.body + !span.getTags().isEmpty() + span.getTag("appsec.events.users.login.failure.track") == true + span.getTag("_dd.appsec.events.users.login.failure.auto.mode") == 'identification' + span.getTag("appsec.events.users.login.failure.usr.exists") == false + span.getTag("appsec.events.users.login.failure.usr.id") == 'not_existing_user' + } + + + def "test failed login with existing user but wrong password"() { + setup: + RequestBody formBody = new FormBody.Builder() + .add("username", "admin") + .add("password", "wrong_password").build() + + def request = request(LOGIN, "POST", formBody).build() + + when: + def response = client.newCall(request).execute() + TEST_WRITER.waitForTraces(1) + DDSpan span = TEST_WRITER.flatten().first() + + then: + response.code() == LOGIN.status + response.body().string() == LOGIN.body + !span.getTags().isEmpty() + span.getTag("appsec.events.users.login.failure.track") == true + span.getTag("_dd.appsec.events.users.login.failure.auto.mode") == 'identification' + // TODO: Ideally should be `false` but we have no reliable method to detect it it is just absent. See APPSEC-12765. + span.getTag("appsec.events.users.login.failure.usr.exists") == null + span.getTag("appsec.events.users.login.failure.usr.id") == 'admin' + } + + + def "test success login"() { + setup: + RequestBody formBody = new FormBody.Builder() + .add("username", "admin") + .add("password", "admin") + .build() + + def request = request(LOGIN, "POST", formBody).build() + + when: + def response = client.newCall(request).execute() + TEST_WRITER.waitForTraces(1) + DDSpan span = TEST_WRITER.flatten().first() + + then: + response.code() == LOGIN.status + response.body().string() == LOGIN.body + !span.getTags().isEmpty() + span.getTag("appsec.events.users.login.success.track") == true + span.getTag("_dd.appsec.events.users.login.success.auto.mode") == 'identification' + span.getTag("usr.id") == 'admin' + span.getTag("appsec.events.users.login.success")['credentialsNonExpired'] == 'true' + span.getTag("appsec.events.users.login.success")['accountNonExpired'] == 'true' + span.getTag("appsec.events.users.login.success")['enabled'] == 'true' + span.getTag("appsec.events.users.login.success")['authorities'] == 'ROLE_USER' + span.getTag("appsec.events.users.login.success")['accountNonLocked'] == 'true' + } + + void 'test failed signup'() { + setup: + final formBody = new FormBody.Builder() + .add('username', 'cant_create_me') + .add('password', 'cant_create_me') + .build() + + final request = request(REGISTER, 'POST', formBody).build() + + when: + final response = client.newCall(request).execute() + TEST_WRITER.waitForTraces(1) + final span = TEST_WRITER.flatten().first() as DDSpan + + then: + response.code() == 500 + span.getTags().findAll { it.key.startsWith('appsec.events.users.signup') }.isEmpty() + } + + void 'test skipped authentication'() { + setup: + final appender = Mock(Appender) + final logger = SpringSecurityUserEventDecorator.LOGGER as Logger + logger.addAppender(appender) + + and: + final requestCount = 3 + final request = request(CUSTOM, "GET", null).addHeader('X-Custom-User', 'batman').build() + + when: + final response = (1..requestCount).collect { client.newCall(request).execute() }.first() + TEST_WRITER.waitForTraces(3) + final span = TEST_WRITER.flatten().first() as DDSpan + logger.detachAppender(appender) // cant add cleanup + + then: + response.code() == CUSTOM.status + span.context().resourceName.contains(CUSTOM.path) + span.getTags().findAll { key, value -> key.startsWith('appsec.events.users.login')}.isEmpty() + // single call to the appender + 1 * appender.doAppend(_) >> { + assert it[0].toString().contains('Skipped authentication, auth=org.springframework.security.authentication.AbstractAuthenticationToken') + } + 0 * appender._ + } + + void 'test user event'() { + setup: + def client = clientBuilder().cookieJar(cookieJar()).followRedirects(false).build() + def formBody = new FormBody.Builder() + .add("username", "admin") + .add("password", "admin") + .build() + + def loginRequest = request(LOGIN, "POST", formBody).build() + def loginResponse = client.newCall(loginRequest).execute() + assert loginResponse.code() == LOGIN.status + assert loginResponse.body().string() == LOGIN.body + TEST_WRITER.waitForTraces(1) + TEST_WRITER.start() // clear all traces + + when: + def request = request(SUCCESS, "GET", null).build() + def response = client.newCall(request).execute() + TEST_WRITER.waitForTraces(1) + def span = TEST_WRITER.flatten().first() as DDSpan + + then: + response.code() == SUCCESS.status + response.body().string() == SUCCESS.body + span.getResourceName().toString() == 'GET /success' + !span.getTags().isEmpty() + span.getTag("usr.id") == 'admin' + span.getTag("_dd.appsec.user.collection_mode") == 'ident' + } +} diff --git a/dd-java-agent/instrumentation/spring-security-6/src/test/groovy/datadog/trace/instrumentation/springsecurity6/TestEndpoint.groovy b/dd-java-agent/instrumentation/spring-security-6/src/test/groovy/datadog/trace/instrumentation/springsecurity6/TestEndpoint.groovy new file mode 100644 index 00000000000..ab0c1528b26 --- /dev/null +++ b/dd-java-agent/instrumentation/spring-security-6/src/test/groovy/datadog/trace/instrumentation/springsecurity6/TestEndpoint.groovy @@ -0,0 +1,50 @@ +package datadog.trace.instrumentation.springsecurity6 + +enum TestEndpoint { + LOGIN("login", 302, ""), + REGISTER("register", 200, ""), + NOT_FOUND("not-found", 404, "not found"), + UNKNOWN("", 451, null), // This needs to have a valid status code + CUSTOM("custom", 302, ""), + SUCCESS("success", 200, ""), + + private final String path + private final String rawPath + final String query + final String rawQuery + final String fragment + final int status + final String body + + TestEndpoint(String uri, int status, String body) { + def uriObj = URI.create(uri) + this.path = uriObj.path + this.rawPath = uriObj.rawPath + this.query = uriObj.query + this.rawQuery = uriObj.rawQuery + this.fragment = uriObj.fragment + this.status = status + this.body = body + } + + String getPath() { + return "/$path" + } + + String relativePath() { + return path + } + + String getRawPath() { + return "/$rawPath" + } + + String relativeRawPath() { + return rawPath + } + + URI resolve(URI address) { + // must be relative path to allow for servlet context + return address.resolve(relativeRawPath()) + } +} diff --git a/dd-java-agent/instrumentation/spring-security-6/src/test/groovy/datadog/trace/instrumentation/springsecurity6/UserController.groovy b/dd-java-agent/instrumentation/spring-security-6/src/test/groovy/datadog/trace/instrumentation/springsecurity6/UserController.groovy new file mode 100644 index 00000000000..03b29f7c271 --- /dev/null +++ b/dd-java-agent/instrumentation/spring-security-6/src/test/groovy/datadog/trace/instrumentation/springsecurity6/UserController.groovy @@ -0,0 +1,45 @@ +package datadog.trace.instrumentation.springsecurity6 + + +import org.springframework.security.core.userdetails.User +import org.springframework.security.provisioning.UserDetailsManager +import org.springframework.stereotype.Controller +import org.springframework.ui.Model +import org.springframework.web.bind.annotation.PostMapping +import org.springframework.web.bind.annotation.RequestMapping +import org.springframework.web.bind.annotation.RequestParam +import org.springframework.web.bind.annotation.ResponseBody + +import static datadog.trace.instrumentation.springsecurity6.TestEndpoint.REGISTER +import static datadog.trace.instrumentation.springsecurity6.TestEndpoint.SUCCESS + +@Controller +class UserController { + + private final UserDetailsManager userDetailsManager + + UserController(UserDetailsManager userDetailsManager) { + this.userDetailsManager = userDetailsManager + } + + @RequestMapping("/success") + @ResponseBody + String success() { + SpringBootBasedTest.controller(SUCCESS) { + SUCCESS.body + } + } + + @PostMapping("/register") + @ResponseBody + void register( + @RequestParam("username") String username, + @RequestParam("password") String password, + Model model) { + SpringBootBasedTest.controller(REGISTER) { + userDetailsManager.createUser( + User.withUsername(username).password("{noop}" + password).roles("USER").build()) + model.addAttribute("username", username) + } + } +} diff --git a/dd-java-agent/instrumentation/spring-security-6/src/test/java/custom/CustomAuthenticationFilter.java b/dd-java-agent/instrumentation/spring-security-6/src/test/java/custom/CustomAuthenticationFilter.java new file mode 100644 index 00000000000..b3ec62a572b --- /dev/null +++ b/dd-java-agent/instrumentation/spring-security-6/src/test/java/custom/CustomAuthenticationFilter.java @@ -0,0 +1,33 @@ +package custom; + +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import java.io.IOException; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter; + +public class CustomAuthenticationFilter extends AbstractAuthenticationProcessingFilter { + + private static final String HEADER_NAME = "X-Custom-User"; + + private final AuthenticationManager authenticationManager; + + public CustomAuthenticationFilter(final AuthenticationManager authenticationManager) { + super("/custom"); + this.authenticationManager = authenticationManager; + } + + @Override + public Authentication attemptAuthentication( + HttpServletRequest request, HttpServletResponse response) + throws AuthenticationException, IOException, ServletException { + final String user = request.getHeader(HEADER_NAME); + if (user == null) { + return null; + } + return authenticationManager.authenticate(new CustomAuthenticationToken(user)); + } +} diff --git a/dd-java-agent/instrumentation/spring-security-6/src/test/java/custom/CustomAuthenticationProvider.java b/dd-java-agent/instrumentation/spring-security-6/src/test/java/custom/CustomAuthenticationProvider.java new file mode 100644 index 00000000000..ac9b8706ab9 --- /dev/null +++ b/dd-java-agent/instrumentation/spring-security-6/src/test/java/custom/CustomAuthenticationProvider.java @@ -0,0 +1,18 @@ +package custom; + +import org.springframework.security.authentication.AuthenticationProvider; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.AuthenticationException; + +public class CustomAuthenticationProvider implements AuthenticationProvider { + + @Override + public Authentication authenticate(Authentication authentication) throws AuthenticationException { + return authentication; + } + + @Override + public boolean supports(Class authentication) { + return CustomAuthenticationToken.class.isAssignableFrom(authentication); + } +} diff --git a/dd-java-agent/instrumentation/spring-security-6/src/test/java/custom/CustomAuthenticationToken.java b/dd-java-agent/instrumentation/spring-security-6/src/test/java/custom/CustomAuthenticationToken.java new file mode 100644 index 00000000000..b85fdc4ad99 --- /dev/null +++ b/dd-java-agent/instrumentation/spring-security-6/src/test/java/custom/CustomAuthenticationToken.java @@ -0,0 +1,24 @@ +package custom; + +import java.util.Collections; +import org.springframework.security.authentication.AbstractAuthenticationToken; + +public class CustomAuthenticationToken extends AbstractAuthenticationToken { + + private final String user; + + public CustomAuthenticationToken(String user) { + super(Collections.emptyList()); + this.user = user; + } + + @Override + public Object getCredentials() { + return user; + } + + @Override + public Object getPrincipal() { + return user; + } +} diff --git a/dd-java-agent/instrumentation/tomcat-appsec-7/src/test/groovy/datadog/trace/instrumentation/tomcat7/ErrorReportValueInstrumentationTest.groovy b/dd-java-agent/instrumentation/tomcat-appsec-7/src/test/groovy/datadog/trace/instrumentation/tomcat7/ErrorReportValueInstrumentationForkedTest.groovy similarity index 80% rename from dd-java-agent/instrumentation/tomcat-appsec-7/src/test/groovy/datadog/trace/instrumentation/tomcat7/ErrorReportValueInstrumentationTest.groovy rename to dd-java-agent/instrumentation/tomcat-appsec-7/src/test/groovy/datadog/trace/instrumentation/tomcat7/ErrorReportValueInstrumentationForkedTest.groovy index 3cc5ec706c8..9d176479d73 100644 --- a/dd-java-agent/instrumentation/tomcat-appsec-7/src/test/groovy/datadog/trace/instrumentation/tomcat7/ErrorReportValueInstrumentationTest.groovy +++ b/dd-java-agent/instrumentation/tomcat-appsec-7/src/test/groovy/datadog/trace/instrumentation/tomcat7/ErrorReportValueInstrumentationForkedTest.groovy @@ -7,7 +7,7 @@ import org.apache.catalina.connector.Request import org.apache.catalina.connector.Response import org.apache.catalina.valves.ErrorReportValve -class ErrorReportValueInstrumentationTest extends AgentTestRunner { +class ErrorReportValueInstrumentationForkedTest extends AgentTestRunner { void 'test vulnerability detection'() { given: @@ -37,7 +37,7 @@ class ErrorReportValueInstrumentationTest extends AgentTestRunner { } } -class AppSecErrorReportValueInstrumentationTest extends ErrorReportValueInstrumentationTest { +class AppSecErrorReportValueInstrumentationForkedTest extends ErrorReportValueInstrumentationForkedTest { @Override protected void configurePreAgent() { @@ -51,7 +51,7 @@ class AppSecErrorReportValueInstrumentationTest extends ErrorReportValueInstrume } } -class IastErrorReportValueInstrumentationTest extends ErrorReportValueInstrumentationTest { +class IastErrorReportValueInstrumentationForkedTest extends ErrorReportValueInstrumentationForkedTest { @Override protected void configurePreAgent() { @@ -65,7 +65,7 @@ class IastErrorReportValueInstrumentationTest extends ErrorReportValueInstrument } } -class IastDisabledErrorReportValueInstrumentationTest extends ErrorReportValueInstrumentationTest { +class IastDisabledErrorReportValueInstrumentationForkedTest extends ErrorReportValueInstrumentationForkedTest { @Override protected void configurePreAgent() { diff --git a/dd-java-agent/testing/src/main/groovy/datadog/trace/agent/test/SpockRunner.java b/dd-java-agent/testing/src/main/groovy/datadog/trace/agent/test/SpockRunner.java index 2e1703aa4d5..bb2f9ab0b3c 100644 --- a/dd-java-agent/testing/src/main/groovy/datadog/trace/agent/test/SpockRunner.java +++ b/dd-java-agent/testing/src/main/groovy/datadog/trace/agent/test/SpockRunner.java @@ -9,13 +9,18 @@ import java.lang.reflect.Method; import java.util.Arrays; import java.util.HashSet; +import java.util.List; import java.util.Set; import java.util.TreeSet; import java.util.jar.JarFile; import net.bytebuddy.agent.ByteBuddyAgent; import net.bytebuddy.dynamic.ClassFileLocator; import org.junit.platform.runner.JUnitPlatform; +import org.junit.runner.notification.Failure; +import org.junit.runner.notification.RunListener; import org.junit.runner.notification.RunNotifier; +import org.spockframework.mock.IMockInvocation; +import org.spockframework.mock.TooManyInvocationsError; /** * Runs a spock test in an agent-friendly way. @@ -129,10 +134,13 @@ private static Class shadowTestClass(final Class clazz) { @Override public void run(final RunNotifier notifier) { final ClassLoader contextLoader = Thread.currentThread().getContextClassLoader(); + final RunListener listener = new TooManyInvocationsErrorListener(); try { Thread.currentThread().setContextClassLoader(customLoader); + notifier.addFirstListener(listener); super.run(notifier); } finally { + notifier.removeListener(listener); Thread.currentThread().setContextClassLoader(contextLoader); } } @@ -222,4 +230,51 @@ protected Class loadClass(final String name, final boolean resolve) } } } + + /** + * This class tries to fix {@link TooManyInvocationsError} exceptions when the assertion error is + * caught by a mock triggering a stack overflow while composing the failure message. + */ + @SuppressWarnings("ResultOfMethodCallIgnored") + @RunListener.ThreadSafe + private static class TooManyInvocationsErrorListener extends RunListener { + + @Override + public void testFailure(final Failure failure) throws Exception { + if (failure.getException() instanceof TooManyInvocationsError) { + final TooManyInvocationsError assertion = (TooManyInvocationsError) failure.getException(); + try { + // try to trigger an error (e.g. stack overflow) + assertion.getMessage(); + } catch (final Throwable e) { + fixTooManyInvocationsError(assertion); + } + } + } + + private void fixTooManyInvocationsError(final TooManyInvocationsError error) { + final List accepted = error.getAcceptedInvocations(); + for (final IMockInvocation invocation : accepted) { + try { + invocation.toString(); + } catch (final Throwable t) { + final List arguments = invocation.getArguments(); + for (int i = 0; i < arguments.size(); i++) { + final Object arg = arguments.get(i); + if (arg instanceof AssertionError) { + final AssertionError updatedAssertion = + new AssertionError( + "'" + + arg.getClass().getName() + + "' hidden due to '" + + t.getClass().getName() + + "'", + t); + invocation.getArguments().set(i, updatedAssertion); + } + } + } + } + } + } } diff --git a/dd-java-agent/testing/src/main/groovy/datadog/trace/agent/test/asserts/TagsAssert.groovy b/dd-java-agent/testing/src/main/groovy/datadog/trace/agent/test/asserts/TagsAssert.groovy index b66fcd730bc..0693ddfda56 100644 --- a/dd-java-agent/testing/src/main/groovy/datadog/trace/agent/test/asserts/TagsAssert.groovy +++ b/dd-java-agent/testing/src/main/groovy/datadog/trace/agent/test/asserts/TagsAssert.groovy @@ -62,10 +62,6 @@ class TagsAssert { assertedTags.add(DDTags.PROFILING_ENABLED) assertedTags.add(DDTags.PROFILING_CONTEXT_ENGINE) assertedTags.add(DDTags.BASE_SERVICE) - assertedTags.add(DDTags.DD_CODE_ORIGIN_FILE) - assertedTags.add(DDTags.DD_CODE_ORIGIN_METHOD) - assertedTags.add(DDTags.DD_CODE_ORIGIN_LINE) - assertedTags.add(DDTags.DD_CODE_ORIGIN_METHOD_SIGNATURE) assertedTags.add(DDTags.DSM_ENABLED) assertedTags.add(DDTags.DJM_ENABLED) assertedTags.add(DDTags.PARENT_ID) diff --git a/dd-java-agent/testing/src/test/groovy/TooManyInvocationsErrorListenerTest.groovy b/dd-java-agent/testing/src/test/groovy/TooManyInvocationsErrorListenerTest.groovy new file mode 100644 index 00000000000..265a63e8fc0 --- /dev/null +++ b/dd-java-agent/testing/src/test/groovy/TooManyInvocationsErrorListenerTest.groovy @@ -0,0 +1,38 @@ +import datadog.trace.agent.test.AgentTestRunner +import datadog.trace.agent.test.SpockRunner +import org.junit.runner.Description +import org.junit.runner.notification.Failure +import org.spockframework.mock.IMockInteraction +import org.spockframework.mock.IMockMethod +import org.spockframework.mock.IMockObject +import org.spockframework.mock.IResponseGenerator +import org.spockframework.mock.TooManyInvocationsError +import org.spockframework.mock.runtime.MockInvocation + +class TooManyInvocationsErrorListenerTest extends AgentTestRunner { + + @SuppressWarnings('GroovyAccessibility') + void 'test that listener modifies failure'() { + setup: + final error = new TooManyInvocationsError(Stub(IMockInteraction), []) + error.acceptedInvocations.add(new MockInvocation(Stub(IMockObject), + Stub(IMockMethod), + [error], + Stub(IResponseGenerator))) + final failure = new Failure(new Description(TooManyInvocationsErrorListenerTest, 'test'), error) + + when: + failure.getMessage() + + then: + thrown(StackOverflowError) + + when: + final listener = new SpockRunner.TooManyInvocationsErrorListener() + listener.testFailure(failure) + failure.getMessage() + + then: + noExceptionThrown() + } +} diff --git a/dd-smoke-tests/debugger-integration-tests/src/test/java/datadog/smoketest/TracerDebuggerIntegrationTest.java b/dd-smoke-tests/debugger-integration-tests/src/test/java/datadog/smoketest/TracerDebuggerIntegrationTest.java index 4b1884dd4b9..4361a8e5573 100644 --- a/dd-smoke-tests/debugger-integration-tests/src/test/java/datadog/smoketest/TracerDebuggerIntegrationTest.java +++ b/dd-smoke-tests/debugger-integration-tests/src/test/java/datadog/smoketest/TracerDebuggerIntegrationTest.java @@ -4,6 +4,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertTrue; import com.datadog.debugger.agent.JsonSnapshotSerializer; @@ -99,6 +100,8 @@ void testTracerSameMethod() throws Exception { Snapshot snapshot = request.getDebugger().getSnapshot(); assertEquals(PROBE_ID.getId(), snapshot.getProbe().getId()); assertEquals(42, snapshot.getCaptures().getEntry().getArguments().get("argInt").getValue()); + // no locals captured + assertNull(snapshot.getCaptures().getEntry().getLocals()); assertTrue(Pattern.matches("[0-9a-f]+", request.getTraceId())); assertTrue(Pattern.matches("\\d+", request.getSpanId())); } diff --git a/dd-trace-api/src/main/java/datadog/trace/api/DDTags.java b/dd-trace-api/src/main/java/datadog/trace/api/DDTags.java index 58506822388..bafad0a3f6f 100644 --- a/dd-trace-api/src/main/java/datadog/trace/api/DDTags.java +++ b/dd-trace-api/src/main/java/datadog/trace/api/DDTags.java @@ -3,20 +3,12 @@ public class DDTags { private static final String DD_LD_PREFIX = "_dd.ld."; - public static final String DD_STACK_CODE_ORIGIN_PREFIX = "_dd.stack.code_origin."; + public static final String DD_STACK_CODE_ORIGIN_PREFIX = DD_LD_PREFIX + "code_origin."; public static final String DD_STACK_CODE_ORIGIN_TYPE = DD_STACK_CODE_ORIGIN_PREFIX + "type"; - // _dd.stack.code_origin.frame.%d.file|line|method|type|snapshot_id + // _dd.ld.code_origin.frames.%d.file|line|method|type|snapshot_id public static final String DD_STACK_CODE_ORIGIN_FRAME = - DD_STACK_CODE_ORIGIN_PREFIX + "frame.%d.%s"; - - public static final String DD_CODE_ORIGIN_FILE = DD_LD_PREFIX + "code_origin.file"; - public static final String DD_CODE_ORIGIN_METHOD = DD_LD_PREFIX + "code_origin.method"; - public static final String DD_CODE_ORIGIN_METHOD_SIGNATURE = - DD_LD_PREFIX + "code_origin.signature"; - public static final String DD_CODE_ORIGIN_LINE = DD_LD_PREFIX + "code_origin.line"; - public static final String DD_CODE_ORIGIN_SNAPSHOT_ID = DD_LD_PREFIX + "code_origin.snapshot_id"; - public static final String DD_CODE_ORIGIN_TYPE = DD_LD_PREFIX + "code_origin.type"; + DD_STACK_CODE_ORIGIN_PREFIX + "frames.%d.%s"; public static final String SPAN_TYPE = "span.type"; public static final String SERVICE_NAME = "service.name"; diff --git a/dd-trace-api/src/main/java/datadog/trace/api/config/CiVisibilityConfig.java b/dd-trace-api/src/main/java/datadog/trace/api/config/CiVisibilityConfig.java index 248bf228ab1..a929649e703 100644 --- a/dd-trace-api/src/main/java/datadog/trace/api/config/CiVisibilityConfig.java +++ b/dd-trace-api/src/main/java/datadog/trace/api/config/CiVisibilityConfig.java @@ -69,6 +69,10 @@ public final class CiVisibilityConfig { "civisibility.rum.flush.wait.millis"; public static final String CIVISIBILITY_AUTO_INSTRUMENTATION_PROVIDER = "civisibility.auto.instrumentation.provider"; + public static final String CIVISIBILITY_REMOTE_ENV_VARS_PROVIDER_URL = + "civisibility.remote.env.vars.provider.url"; + public static final String CIVISIBILITY_REMOTE_ENV_VARS_PROVIDER_KEY = + "civisibility.remote.env.vars.provider.key"; /* COVERAGE SETTINGS */ public static final String CIVISIBILITY_CODE_COVERAGE_ENABLED = diff --git a/dd-trace-core/src/main/java/datadog/trace/common/writer/WriterFactory.java b/dd-trace-core/src/main/java/datadog/trace/common/writer/WriterFactory.java index b4af03b90e7..ef73a0b6fb7 100644 --- a/dd-trace-core/src/main/java/datadog/trace/common/writer/WriterFactory.java +++ b/dd-trace-core/src/main/java/datadog/trace/common/writer/WriterFactory.java @@ -188,6 +188,7 @@ private static RemoteApi createDDIntakeRemoteApi( } return DDIntakeApi.builder() .hostUrl(hostUrl) + .httpClient(commObjects.okHttpClient) .apiKey(config.getApiKey()) .trackType(trackType) .build(); diff --git a/dd-trace-core/src/main/java/datadog/trace/common/writer/ddintake/DDIntakeApi.java b/dd-trace-core/src/main/java/datadog/trace/common/writer/ddintake/DDIntakeApi.java index 165d1a951ab..7abad42d2f1 100644 --- a/dd-trace-core/src/main/java/datadog/trace/common/writer/ddintake/DDIntakeApi.java +++ b/dd-trace-core/src/main/java/datadog/trace/common/writer/ddintake/DDIntakeApi.java @@ -77,7 +77,7 @@ public DDIntakeApiBuilder hostUrl(final HttpUrl hostUrl) { return this; } - DDIntakeApiBuilder httpClient(final OkHttpClient httpClient) { + public DDIntakeApiBuilder httpClient(final OkHttpClient httpClient) { this.httpClient = httpClient; return this; } diff --git a/dd-trace-core/src/main/java/datadog/trace/core/CoreTracer.java b/dd-trace-core/src/main/java/datadog/trace/core/CoreTracer.java index 8da026f224f..6cacd7037ff 100644 --- a/dd-trace-core/src/main/java/datadog/trace/core/CoreTracer.java +++ b/dd-trace-core/src/main/java/datadog/trace/core/CoreTracer.java @@ -956,7 +956,7 @@ public AgentSpan blackholeSpan() { @Override public AgentSpan.Context notifyExtensionStart(Object event) { - return LambdaHandler.notifyStartInvocation(event, propagationTagsFactory); + return LambdaHandler.notifyStartInvocation(this, event); } @Override diff --git a/dd-trace-core/src/main/java/datadog/trace/lambda/LambdaHandler.java b/dd-trace-core/src/main/java/datadog/trace/lambda/LambdaHandler.java index 1d298169207..e11dbb8c29e 100644 --- a/dd-trace-core/src/main/java/datadog/trace/lambda/LambdaHandler.java +++ b/dd-trace-core/src/main/java/datadog/trace/lambda/LambdaHandler.java @@ -1,17 +1,13 @@ package datadog.trace.lambda; -import static datadog.trace.api.TracePropagationStyle.DATADOG; import static java.util.concurrent.TimeUnit.SECONDS; import com.squareup.moshi.JsonAdapter; import com.squareup.moshi.Moshi; import datadog.trace.api.DDSpanId; import datadog.trace.api.DDTags; -import datadog.trace.api.DDTraceId; -import datadog.trace.api.sampling.PrioritySampling; import datadog.trace.bootstrap.instrumentation.api.AgentSpan; -import datadog.trace.core.propagation.ExtractedContext; -import datadog.trace.core.propagation.PropagationTags; +import datadog.trace.core.CoreTracer; import java.io.ByteArrayInputStream; import java.nio.charset.StandardCharsets; import java.util.Base64; @@ -44,7 +40,6 @@ public class LambdaHandler { private static final String DATADOG_INVOCATION_ERROR_MSG = "x-datadog-invocation-error-msg"; private static final String DATADOG_INVOCATION_ERROR_TYPE = "x-datadog-invocation-error-type"; private static final String DATADOG_INVOCATION_ERROR_STACK = "x-datadog-invocation-error-stack"; - private static final String DATADOG_TAGS_KEY = "x-datadog-tags"; private static final String START_INVOCATION = "/lambda/start-invocation"; private static final String END_INVOCATION = "/lambda/end-invocation"; @@ -73,8 +68,7 @@ public class LambdaHandler { private static String EXTENSION_BASE_URL = "http://127.0.0.1:8124"; - public static AgentSpan.Context notifyStartInvocation( - Object event, PropagationTags.Factory propagationTagsFactory) { + public static AgentSpan.Context notifyStartInvocation(CoreTracer tracer, Object event) { RequestBody body = RequestBody.create(jsonMediaType, writeValueAsString(event)); try (Response response = HTTP_CLIENT @@ -86,33 +80,16 @@ public static AgentSpan.Context notifyStartInvocation( .build()) .execute()) { if (response.isSuccessful()) { - final String traceID = response.headers().get(DATADOG_TRACE_ID); - final String priority = response.headers().get(DATADOG_SAMPLING_PRIORITY); - if (null != traceID && null != priority) { - int samplingPriority = PrioritySampling.UNSET; - try { - samplingPriority = Integer.parseInt(priority); - } catch (final NumberFormatException ignored) { - log.warn("could not read the sampling priority, defaulting to UNSET"); - } - log.debug( - "notifyStartInvocation success, found traceID = {} and samplingPriority = {}", - traceID, - samplingPriority); - PropagationTags propagationTags = - propagationTagsFactory.fromHeaderValue( - PropagationTags.HeaderType.DATADOG, response.headers().get(DATADOG_TAGS_KEY)); - return new ExtractedContext( - DDTraceId.from(traceID), - DDSpanId.ZERO, - samplingPriority, - null, - propagationTags, - DATADOG); - } else { - log.debug( - "could not find traceID or sampling priority in notifyStartInvocation, not injecting the context"); - } + + return tracer + .propagate() + .extract( + response.headers(), + (carrier, classifier) -> { + for (String headerName : carrier.names()) { + classifier.accept(headerName, carrier.get(headerName)); + } + }); } } catch (Throwable ignored) { log.error("could not reach the extension"); @@ -121,7 +98,6 @@ public static AgentSpan.Context notifyStartInvocation( } public static boolean notifyEndInvocation(AgentSpan span, Object result, boolean isError) { - if (null == span || null == span.getSamplingPriority()) { log.error( "could not notify the extension as the lambda span is null or no sampling priority has been found"); diff --git a/dd-trace-core/src/test/groovy/datadog/trace/lambda/LambdaHandlerTest.groovy b/dd-trace-core/src/test/groovy/datadog/trace/lambda/LambdaHandlerTest.groovy index bf2dc097f19..716dec06ddf 100644 --- a/dd-trace-core/src/test/groovy/datadog/trace/lambda/LambdaHandlerTest.groovy +++ b/dd-trace-core/src/test/groovy/datadog/trace/lambda/LambdaHandlerTest.groovy @@ -1,10 +1,9 @@ package datadog.trace.lambda -import datadog.trace.api.Config import datadog.trace.api.DDSpanId import datadog.trace.api.DDTags import datadog.trace.api.DDTraceId -import datadog.trace.core.propagation.PropagationTags +import datadog.trace.core.CoreTracer import datadog.trace.core.test.DDCoreSpecification import datadog.trace.core.DDSpan import com.amazonaws.services.lambda.runtime.events.SQSEvent @@ -30,8 +29,7 @@ class LambdaHandlerTest extends DDCoreSpecification { def "test start invocation success"() { given: - Config config = Mock(Config) - config.getxDatadogTagsMaxLength() >> 512 + CoreTracer ct = tracerBuilder().build() def server = httpServer { handlers { @@ -47,7 +45,7 @@ class LambdaHandlerTest extends DDCoreSpecification { LambdaHandler.setExtensionBaseUrl(server.address.toString()) when: - def objTest = LambdaHandler.notifyStartInvocation(obj, PropagationTags.factory(config)) + def objTest = LambdaHandler.notifyStartInvocation(ct, obj) then: objTest.getTraceId().toString() == traceId @@ -55,16 +53,50 @@ class LambdaHandlerTest extends DDCoreSpecification { cleanup: server.close() + ct.close() where: traceId | samplingPriority | obj "1234" | 2 | new TestObject() } + def "test start invocation with 128 bit trace ID"() { + given: + CoreTracer ct = tracerBuilder().build() + + def server = httpServer { + handlers { + post("/lambda/start-invocation") { + response + .status(200) + .addHeader("x-datadog-trace-id", "5744042798732701615") + .addHeader("x-datadog-sampling-priority", "2") + .addHeader("x-datadog-tags", "_dd.p.tid=1914fe7789eb32be") + .send() + } + } + } + LambdaHandler.setExtensionBaseUrl(server.address.toString()) + + when: + def objTest = LambdaHandler.notifyStartInvocation(ct, obj) + + then: + objTest.getTraceId().toHexString() == traceId + objTest.getSamplingPriority() == samplingPriority + + cleanup: + server.close() + ct.close() + + where: + traceId | samplingPriority | obj + "1914fe7789eb32be4fb6f07e011a6faf" | 2 | new TestObject() + } + def "test start invocation failure"() { given: - Config config = Mock(Config) - config.getxDatadogTagsMaxLength() >> 512 + CoreTracer ct = tracerBuilder().build() def server = httpServer { handlers { @@ -78,13 +110,14 @@ class LambdaHandlerTest extends DDCoreSpecification { LambdaHandler.setExtensionBaseUrl(server.address.toString()) when: - def objTest = LambdaHandler.notifyStartInvocation(obj, PropagationTags.factory(config)) + def objTest = LambdaHandler.notifyStartInvocation(ct, obj) then: objTest == expected cleanup: server.close() + ct.close() where: expected | obj diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 1f4d82334cc..810474ad645 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -26,10 +26,10 @@ commons = "3.2" mockito = '4.4.0' jctools = '3.3.0' moshi = '1.11.0' -testcontainers = '1.19.3' +testcontainers = '1.20.1' jmc = "8.1.0" autoservice = "1.0-rc7" -ddprof = "1.14.0" +ddprof = "1.15.0" asm = "9.7" cafe_crypto = "0.1.0" lz4 = "1.7.1" diff --git a/internal-api/src/main/java/datadog/trace/api/Config.java b/internal-api/src/main/java/datadog/trace/api/Config.java index c461a36806f..75b95385375 100644 --- a/internal-api/src/main/java/datadog/trace/api/Config.java +++ b/internal-api/src/main/java/datadog/trace/api/Config.java @@ -1,500 +1,22 @@ package datadog.trace.api; -import static datadog.trace.api.ConfigDefaults.DEFAULT_AGENT_HOST; -import static datadog.trace.api.ConfigDefaults.DEFAULT_AGENT_TIMEOUT; -import static datadog.trace.api.ConfigDefaults.DEFAULT_AGENT_WRITER_TYPE; -import static datadog.trace.api.ConfigDefaults.DEFAULT_ANALYTICS_SAMPLE_RATE; -import static datadog.trace.api.ConfigDefaults.DEFAULT_API_SECURITY_ENABLED; -import static datadog.trace.api.ConfigDefaults.DEFAULT_API_SECURITY_REQUEST_SAMPLE_RATE; -import static datadog.trace.api.ConfigDefaults.DEFAULT_APPSEC_MAX_STACK_TRACES; -import static datadog.trace.api.ConfigDefaults.DEFAULT_APPSEC_MAX_STACK_TRACE_DEPTH; -import static datadog.trace.api.ConfigDefaults.DEFAULT_APPSEC_RASP_ENABLED; -import static datadog.trace.api.ConfigDefaults.DEFAULT_APPSEC_REPORTING_INBAND; -import static datadog.trace.api.ConfigDefaults.DEFAULT_APPSEC_STACK_TRACE_ENABLED; -import static datadog.trace.api.ConfigDefaults.DEFAULT_APPSEC_TRACE_RATE_LIMIT; -import static datadog.trace.api.ConfigDefaults.DEFAULT_APPSEC_WAF_METRICS; -import static datadog.trace.api.ConfigDefaults.DEFAULT_APPSEC_WAF_TIMEOUT; -import static datadog.trace.api.ConfigDefaults.DEFAULT_CIVISIBILITY_AGENTLESS_ENABLED; -import static datadog.trace.api.ConfigDefaults.DEFAULT_CIVISIBILITY_AUTO_CONFIGURATION_ENABLED; -import static datadog.trace.api.ConfigDefaults.DEFAULT_CIVISIBILITY_BACKEND_API_TIMEOUT_MILLIS; -import static datadog.trace.api.ConfigDefaults.DEFAULT_CIVISIBILITY_BUILD_INSTRUMENTATION_ENABLED; -import static datadog.trace.api.ConfigDefaults.DEFAULT_CIVISIBILITY_COMPILER_PLUGIN_AUTO_CONFIGURATION_ENABLED; -import static datadog.trace.api.ConfigDefaults.DEFAULT_CIVISIBILITY_COMPILER_PLUGIN_VERSION; -import static datadog.trace.api.ConfigDefaults.DEFAULT_CIVISIBILITY_GIT_COMMAND_TIMEOUT_MILLIS; -import static datadog.trace.api.ConfigDefaults.DEFAULT_CIVISIBILITY_GIT_REMOTE_NAME; -import static datadog.trace.api.ConfigDefaults.DEFAULT_CIVISIBILITY_GIT_UNSHALLOW_ENABLED; -import static datadog.trace.api.ConfigDefaults.DEFAULT_CIVISIBILITY_GIT_UPLOAD_ENABLED; -import static datadog.trace.api.ConfigDefaults.DEFAULT_CIVISIBILITY_GIT_UPLOAD_TIMEOUT_MILLIS; -import static datadog.trace.api.ConfigDefaults.DEFAULT_CIVISIBILITY_JACOCO_PLUGIN_EXCLUDES; -import static datadog.trace.api.ConfigDefaults.DEFAULT_CIVISIBILITY_JACOCO_PLUGIN_VERSION; -import static datadog.trace.api.ConfigDefaults.DEFAULT_CIVISIBILITY_RESOURCE_FOLDER_NAMES; -import static datadog.trace.api.ConfigDefaults.DEFAULT_CIVISIBILITY_SIGNAL_SERVER_HOST; -import static datadog.trace.api.ConfigDefaults.DEFAULT_CIVISIBILITY_SIGNAL_SERVER_PORT; -import static datadog.trace.api.ConfigDefaults.DEFAULT_CIVISIBILITY_SOURCE_DATA_ENABLED; -import static datadog.trace.api.ConfigDefaults.DEFAULT_CLIENT_IP_ENABLED; -import static datadog.trace.api.ConfigDefaults.DEFAULT_CLOCK_SYNC_PERIOD; -import static datadog.trace.api.ConfigDefaults.DEFAULT_COUCHBASE_INTERNAL_SPANS_ENABLED; -import static datadog.trace.api.ConfigDefaults.DEFAULT_CWS_ENABLED; -import static datadog.trace.api.ConfigDefaults.DEFAULT_CWS_TLS_REFRESH; -import static datadog.trace.api.ConfigDefaults.DEFAULT_DATA_JOBS_ENABLED; -import static datadog.trace.api.ConfigDefaults.DEFAULT_DATA_STREAMS_BUCKET_DURATION; -import static datadog.trace.api.ConfigDefaults.DEFAULT_DATA_STREAMS_ENABLED; -import static datadog.trace.api.ConfigDefaults.DEFAULT_DB_CLIENT_HOST_SPLIT_BY_HOST; -import static datadog.trace.api.ConfigDefaults.DEFAULT_DB_CLIENT_HOST_SPLIT_BY_INSTANCE; -import static datadog.trace.api.ConfigDefaults.DEFAULT_DB_CLIENT_HOST_SPLIT_BY_INSTANCE_TYPE_SUFFIX; -import static datadog.trace.api.ConfigDefaults.DEFAULT_DB_DBM_PROPAGATION_MODE_MODE; -import static datadog.trace.api.ConfigDefaults.DEFAULT_DEBUGGER_CAPTURE_TIMEOUT; -import static datadog.trace.api.ConfigDefaults.DEFAULT_DEBUGGER_CLASSFILE_DUMP_ENABLED; -import static datadog.trace.api.ConfigDefaults.DEFAULT_DEBUGGER_CODE_ORIGIN_ENABLED; -import static datadog.trace.api.ConfigDefaults.DEFAULT_DEBUGGER_DIAGNOSTICS_INTERVAL; -import static datadog.trace.api.ConfigDefaults.DEFAULT_DEBUGGER_ENABLED; -import static datadog.trace.api.ConfigDefaults.DEFAULT_DEBUGGER_EXCEPTION_CAPTURE_INTERMEDIATE_SPANS_ENABLED; -import static datadog.trace.api.ConfigDefaults.DEFAULT_DEBUGGER_EXCEPTION_CAPTURE_INTERVAL_SECONDS; -import static datadog.trace.api.ConfigDefaults.DEFAULT_DEBUGGER_EXCEPTION_ENABLED; -import static datadog.trace.api.ConfigDefaults.DEFAULT_DEBUGGER_EXCEPTION_MAX_CAPTURED_FRAMES; -import static datadog.trace.api.ConfigDefaults.DEFAULT_DEBUGGER_EXCEPTION_ONLY_LOCAL_ROOT; -import static datadog.trace.api.ConfigDefaults.DEFAULT_DEBUGGER_INSTRUMENT_THE_WORLD; -import static datadog.trace.api.ConfigDefaults.DEFAULT_DEBUGGER_MAX_EXCEPTION_PER_SECOND; -import static datadog.trace.api.ConfigDefaults.DEFAULT_DEBUGGER_MAX_PAYLOAD_SIZE; -import static datadog.trace.api.ConfigDefaults.DEFAULT_DEBUGGER_METRICS_ENABLED; -import static datadog.trace.api.ConfigDefaults.DEFAULT_DEBUGGER_POLL_INTERVAL; -import static datadog.trace.api.ConfigDefaults.DEFAULT_DEBUGGER_SYMBOL_ENABLED; -import static datadog.trace.api.ConfigDefaults.DEFAULT_DEBUGGER_SYMBOL_FLUSH_THRESHOLD; -import static datadog.trace.api.ConfigDefaults.DEFAULT_DEBUGGER_SYMBOL_FORCE_UPLOAD; -import static datadog.trace.api.ConfigDefaults.DEFAULT_DEBUGGER_UPLOAD_BATCH_SIZE; -import static datadog.trace.api.ConfigDefaults.DEFAULT_DEBUGGER_UPLOAD_FLUSH_INTERVAL; -import static datadog.trace.api.ConfigDefaults.DEFAULT_DEBUGGER_UPLOAD_TIMEOUT; -import static datadog.trace.api.ConfigDefaults.DEFAULT_DEBUGGER_VERIFY_BYTECODE; -import static datadog.trace.api.ConfigDefaults.DEFAULT_DOGSTATSD_START_DELAY; -import static datadog.trace.api.ConfigDefaults.DEFAULT_ELASTICSEARCH_BODY_AND_PARAMS_ENABLED; -import static datadog.trace.api.ConfigDefaults.DEFAULT_ELASTICSEARCH_BODY_ENABLED; -import static datadog.trace.api.ConfigDefaults.DEFAULT_ELASTICSEARCH_PARAMS_ENABLED; -import static datadog.trace.api.ConfigDefaults.DEFAULT_GRPC_CLIENT_ERROR_STATUSES; -import static datadog.trace.api.ConfigDefaults.DEFAULT_GRPC_SERVER_ERROR_STATUSES; -import static datadog.trace.api.ConfigDefaults.DEFAULT_HEALTH_METRICS_ENABLED; -import static datadog.trace.api.ConfigDefaults.DEFAULT_HTTP_CLIENT_ERROR_STATUSES; -import static datadog.trace.api.ConfigDefaults.DEFAULT_HTTP_CLIENT_SPLIT_BY_DOMAIN; -import static datadog.trace.api.ConfigDefaults.DEFAULT_HTTP_CLIENT_TAG_QUERY_STRING; -import static datadog.trace.api.ConfigDefaults.DEFAULT_HTTP_SERVER_ERROR_STATUSES; -import static datadog.trace.api.ConfigDefaults.DEFAULT_HTTP_SERVER_ROUTE_BASED_NAMING; -import static datadog.trace.api.ConfigDefaults.DEFAULT_HTTP_SERVER_TAG_QUERY_STRING; -import static datadog.trace.api.ConfigDefaults.DEFAULT_IAST_ANONYMOUS_CLASSES_ENABLED; -import static datadog.trace.api.ConfigDefaults.DEFAULT_IAST_DEBUG_ENABLED; -import static datadog.trace.api.ConfigDefaults.DEFAULT_IAST_HARDCODED_SECRET_ENABLED; -import static datadog.trace.api.ConfigDefaults.DEFAULT_IAST_REDACTION_ENABLED; -import static datadog.trace.api.ConfigDefaults.DEFAULT_IAST_REDACTION_NAME_PATTERN; -import static datadog.trace.api.ConfigDefaults.DEFAULT_IAST_REDACTION_VALUE_PATTERN; -import static datadog.trace.api.ConfigDefaults.DEFAULT_IAST_STACKTRACE_LEAK_SUPPRESS; -import static datadog.trace.api.ConfigDefaults.DEFAULT_IAST_TRUNCATION_MAX_VALUE_LENGTH; -import static datadog.trace.api.ConfigDefaults.DEFAULT_IAST_WEAK_CIPHER_ALGORITHMS; -import static datadog.trace.api.ConfigDefaults.DEFAULT_IAST_WEAK_HASH_ALGORITHMS; -import static datadog.trace.api.ConfigDefaults.DEFAULT_JMX_FETCH_ENABLED; -import static datadog.trace.api.ConfigDefaults.DEFAULT_JMX_FETCH_MULTIPLE_RUNTIME_SERVICES_ENABLED; -import static datadog.trace.api.ConfigDefaults.DEFAULT_JMX_FETCH_MULTIPLE_RUNTIME_SERVICES_LIMIT; -import static datadog.trace.api.ConfigDefaults.DEFAULT_LOGS_INJECTION_ENABLED; -import static datadog.trace.api.ConfigDefaults.DEFAULT_PARTIAL_FLUSH_MIN_SPANS; -import static datadog.trace.api.ConfigDefaults.DEFAULT_PERF_METRICS_ENABLED; -import static datadog.trace.api.ConfigDefaults.DEFAULT_PRIORITY_SAMPLING_ENABLED; -import static datadog.trace.api.ConfigDefaults.DEFAULT_PRIORITY_SAMPLING_FORCE; -import static datadog.trace.api.ConfigDefaults.DEFAULT_PROPAGATION_EXTRACT_LOG_HEADER_NAMES_ENABLED; -import static datadog.trace.api.ConfigDefaults.DEFAULT_PROPAGATION_STYLE; -import static datadog.trace.api.ConfigDefaults.DEFAULT_REMOTE_CONFIG_ENABLED; -import static datadog.trace.api.ConfigDefaults.DEFAULT_REMOTE_CONFIG_INTEGRITY_CHECK_ENABLED; -import static datadog.trace.api.ConfigDefaults.DEFAULT_REMOTE_CONFIG_MAX_EXTRA_SERVICES; -import static datadog.trace.api.ConfigDefaults.DEFAULT_REMOTE_CONFIG_MAX_PAYLOAD_SIZE; -import static datadog.trace.api.ConfigDefaults.DEFAULT_REMOTE_CONFIG_POLL_INTERVAL_SECONDS; -import static datadog.trace.api.ConfigDefaults.DEFAULT_REMOTE_CONFIG_TARGETS_KEY; -import static datadog.trace.api.ConfigDefaults.DEFAULT_REMOTE_CONFIG_TARGETS_KEY_ID; -import static datadog.trace.api.ConfigDefaults.DEFAULT_SCOPE_DEPTH_LIMIT; -import static datadog.trace.api.ConfigDefaults.DEFAULT_SCOPE_ITERATION_KEEP_ALIVE; -import static datadog.trace.api.ConfigDefaults.DEFAULT_SECURE_RANDOM; -import static datadog.trace.api.ConfigDefaults.DEFAULT_SERVICE_NAME; -import static datadog.trace.api.ConfigDefaults.DEFAULT_SERVLET_ROOT_CONTEXT_SERVICE_NAME; -import static datadog.trace.api.ConfigDefaults.DEFAULT_SITE; -import static datadog.trace.api.ConfigDefaults.DEFAULT_STARTUP_LOGS_ENABLED; -import static datadog.trace.api.ConfigDefaults.DEFAULT_TELEMETRY_DEPENDENCY_COLLECTION_ENABLED; -import static datadog.trace.api.ConfigDefaults.DEFAULT_TELEMETRY_DEPENDENCY_RESOLUTION_QUEUE_SIZE; -import static datadog.trace.api.ConfigDefaults.DEFAULT_TELEMETRY_EXTENDED_HEARTBEAT_INTERVAL; -import static datadog.trace.api.ConfigDefaults.DEFAULT_TELEMETRY_HEARTBEAT_INTERVAL; -import static datadog.trace.api.ConfigDefaults.DEFAULT_TELEMETRY_LOG_COLLECTION_ENABLED; -import static datadog.trace.api.ConfigDefaults.DEFAULT_TELEMETRY_METRICS_INTERVAL; -import static datadog.trace.api.ConfigDefaults.DEFAULT_TRACE_128_BIT_TRACEID_GENERATION_ENABLED; -import static datadog.trace.api.ConfigDefaults.DEFAULT_TRACE_AGENT_PORT; -import static datadog.trace.api.ConfigDefaults.DEFAULT_TRACE_AGENT_V05_ENABLED; -import static datadog.trace.api.ConfigDefaults.DEFAULT_TRACE_ANALYTICS_ENABLED; -import static datadog.trace.api.ConfigDefaults.DEFAULT_TRACE_HTTP_RESOURCE_REMOVE_TRAILING_SLASH; -import static datadog.trace.api.ConfigDefaults.DEFAULT_TRACE_LONG_RUNNING_FLUSH_INTERVAL; -import static datadog.trace.api.ConfigDefaults.DEFAULT_TRACE_LONG_RUNNING_INITIAL_FLUSH_INTERVAL; -import static datadog.trace.api.ConfigDefaults.DEFAULT_TRACE_PROPAGATION_EXTRACT_FIRST; -import static datadog.trace.api.ConfigDefaults.DEFAULT_TRACE_PROPAGATION_STYLE; -import static datadog.trace.api.ConfigDefaults.DEFAULT_TRACE_RATE_LIMIT; -import static datadog.trace.api.ConfigDefaults.DEFAULT_TRACE_REPORT_HOSTNAME; -import static datadog.trace.api.ConfigDefaults.DEFAULT_TRACE_RESOLVER_ENABLED; -import static datadog.trace.api.ConfigDefaults.DEFAULT_TRACE_X_DATADOG_TAGS_MAX_LENGTH; -import static datadog.trace.api.ConfigDefaults.DEFAULT_WRITER_BAGGAGE_INJECT; -import static datadog.trace.api.DDTags.APM_ENABLED; -import static datadog.trace.api.DDTags.HOST_TAG; -import static datadog.trace.api.DDTags.INTERNAL_HOST_NAME; -import static datadog.trace.api.DDTags.LANGUAGE_TAG_KEY; -import static datadog.trace.api.DDTags.LANGUAGE_TAG_VALUE; -import static datadog.trace.api.DDTags.PID_TAG; +import static datadog.trace.api.ConfigDefaults.*; +import static datadog.trace.api.DDTags.*; import static datadog.trace.api.DDTags.PROFILING_ENABLED; -import static datadog.trace.api.DDTags.RUNTIME_ID_TAG; -import static datadog.trace.api.DDTags.RUNTIME_VERSION_TAG; -import static datadog.trace.api.DDTags.SCHEMA_VERSION_TAG_KEY; -import static datadog.trace.api.DDTags.SERVICE; -import static datadog.trace.api.DDTags.SERVICE_TAG; -import static datadog.trace.api.config.AppSecConfig.API_SECURITY_ENABLED; -import static datadog.trace.api.config.AppSecConfig.API_SECURITY_ENABLED_EXPERIMENTAL; -import static datadog.trace.api.config.AppSecConfig.API_SECURITY_REQUEST_SAMPLE_RATE; -import static datadog.trace.api.config.AppSecConfig.APPSEC_AUTOMATED_USER_EVENTS_TRACKING; -import static datadog.trace.api.config.AppSecConfig.APPSEC_AUTO_USER_INSTRUMENTATION_MODE; -import static datadog.trace.api.config.AppSecConfig.APPSEC_HTTP_BLOCKED_TEMPLATE_HTML; -import static datadog.trace.api.config.AppSecConfig.APPSEC_HTTP_BLOCKED_TEMPLATE_JSON; -import static datadog.trace.api.config.AppSecConfig.APPSEC_IP_ADDR_HEADER; -import static datadog.trace.api.config.AppSecConfig.APPSEC_MAX_STACK_TRACES; -import static datadog.trace.api.config.AppSecConfig.APPSEC_MAX_STACK_TRACE_DEPTH; -import static datadog.trace.api.config.AppSecConfig.APPSEC_OBFUSCATION_PARAMETER_KEY_REGEXP; -import static datadog.trace.api.config.AppSecConfig.APPSEC_OBFUSCATION_PARAMETER_VALUE_REGEXP; -import static datadog.trace.api.config.AppSecConfig.APPSEC_RASP_ENABLED; -import static datadog.trace.api.config.AppSecConfig.APPSEC_REPORTING_INBAND; -import static datadog.trace.api.config.AppSecConfig.APPSEC_REPORT_TIMEOUT_SEC; -import static datadog.trace.api.config.AppSecConfig.APPSEC_RULES_FILE; -import static datadog.trace.api.config.AppSecConfig.APPSEC_SCA_ENABLED; -import static datadog.trace.api.config.AppSecConfig.APPSEC_STACK_TRACE_ENABLED; -import static datadog.trace.api.config.AppSecConfig.APPSEC_STANDALONE_ENABLED; -import static datadog.trace.api.config.AppSecConfig.APPSEC_TRACE_RATE_LIMIT; -import static datadog.trace.api.config.AppSecConfig.APPSEC_WAF_METRICS; -import static datadog.trace.api.config.AppSecConfig.APPSEC_WAF_TIMEOUT; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_ADDITIONAL_CHILD_PROCESS_JVM_ARGS; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_AGENTLESS_ENABLED; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_AGENTLESS_URL; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_AGENT_JAR_URI; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_AUTO_CONFIGURATION_ENABLED; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_AUTO_INSTRUMENTATION_PROVIDER; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_BACKEND_API_TIMEOUT_MILLIS; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_BUILD_INSTRUMENTATION_ENABLED; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_CIPROVIDER_INTEGRATION_ENABLED; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_CODE_COVERAGE_ENABLED; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_CODE_COVERAGE_EXCLUDES; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_CODE_COVERAGE_INCLUDES; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_CODE_COVERAGE_LINES_ENABLED; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_CODE_COVERAGE_REPORT_DUMP_DIR; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_CODE_COVERAGE_ROOT_PACKAGES_LIMIT; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_COMPILER_PLUGIN_AUTO_CONFIGURATION_ENABLED; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_COMPILER_PLUGIN_VERSION; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_DEBUG_PORT; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_EARLY_FLAKE_DETECTION_ENABLED; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_EARLY_FLAKE_DETECTION_LOWER_LIMIT; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_EXECUTION_SETTINGS_CACHE_SIZE; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_FLAKY_RETRY_COUNT; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_FLAKY_RETRY_ENABLED; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_FLAKY_RETRY_ONLY_KNOWN_FLAKES; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_GIT_COMMAND_TIMEOUT_MILLIS; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_GIT_REMOTE_NAME; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_GIT_UNSHALLOW_DEFER; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_GIT_UNSHALLOW_ENABLED; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_GIT_UPLOAD_ENABLED; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_GIT_UPLOAD_TIMEOUT_MILLIS; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_GRADLE_SOURCE_SETS; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_INJECTED_TRACER_VERSION; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_ITR_ENABLED; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_JACOCO_PLUGIN_VERSION; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_JVM_INFO_CACHE_SIZE; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_MODULE_ID; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_MODULE_NAME; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_REPO_INDEX_SHARING_ENABLED; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_RESOURCE_FOLDER_NAMES; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_RUM_FLUSH_WAIT_MILLIS; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_SESSION_ID; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_SIGNAL_CLIENT_TIMEOUT_MILLIS; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_SIGNAL_SERVER_HOST; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_SIGNAL_SERVER_PORT; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_SOURCE_DATA_ENABLED; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_TELEMETRY_ENABLED; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_TEST_COMMAND; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_TEST_SKIPPING_ENABLED; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_TOTAL_FLAKY_RETRY_COUNT; -import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_TRACE_SANITATION_ENABLED; -import static datadog.trace.api.config.CiVisibilityConfig.TEST_SESSION_NAME; -import static datadog.trace.api.config.CrashTrackingConfig.CRASH_TRACKING_AGENTLESS; -import static datadog.trace.api.config.CrashTrackingConfig.CRASH_TRACKING_AGENTLESS_DEFAULT; -import static datadog.trace.api.config.CrashTrackingConfig.CRASH_TRACKING_TAGS; +import static datadog.trace.api.config.AppSecConfig.*; +import static datadog.trace.api.config.CiVisibilityConfig.*; +import static datadog.trace.api.config.CrashTrackingConfig.*; import static datadog.trace.api.config.CwsConfig.CWS_ENABLED; import static datadog.trace.api.config.CwsConfig.CWS_TLS_REFRESH; -import static datadog.trace.api.config.DebuggerConfig.DEBUGGER_CAPTURE_TIMEOUT; -import static datadog.trace.api.config.DebuggerConfig.DEBUGGER_CLASSFILE_DUMP_ENABLED; -import static datadog.trace.api.config.DebuggerConfig.DEBUGGER_CODE_ORIGIN_ENABLED; -import static datadog.trace.api.config.DebuggerConfig.DEBUGGER_DIAGNOSTICS_INTERVAL; -import static datadog.trace.api.config.DebuggerConfig.DEBUGGER_ENABLED; -import static datadog.trace.api.config.DebuggerConfig.DEBUGGER_EXCEPTION_CAPTURE_INTERMEDIATE_SPANS_ENABLED; -import static datadog.trace.api.config.DebuggerConfig.DEBUGGER_EXCEPTION_CAPTURE_INTERVAL_SECONDS; -import static datadog.trace.api.config.DebuggerConfig.DEBUGGER_EXCEPTION_CAPTURE_MAX_FRAMES; -import static datadog.trace.api.config.DebuggerConfig.DEBUGGER_EXCEPTION_ENABLED; -import static datadog.trace.api.config.DebuggerConfig.DEBUGGER_EXCEPTION_MAX_CAPTURED_FRAMES; -import static datadog.trace.api.config.DebuggerConfig.DEBUGGER_EXCEPTION_ONLY_LOCAL_ROOT; -import static datadog.trace.api.config.DebuggerConfig.DEBUGGER_EXCLUDE_FILES; -import static datadog.trace.api.config.DebuggerConfig.DEBUGGER_INSTRUMENT_THE_WORLD; -import static datadog.trace.api.config.DebuggerConfig.DEBUGGER_MAX_EXCEPTION_PER_SECOND; -import static datadog.trace.api.config.DebuggerConfig.DEBUGGER_MAX_PAYLOAD_SIZE; -import static datadog.trace.api.config.DebuggerConfig.DEBUGGER_METRICS_ENABLED; -import static datadog.trace.api.config.DebuggerConfig.DEBUGGER_POLL_INTERVAL; -import static datadog.trace.api.config.DebuggerConfig.DEBUGGER_PROBE_FILE_LOCATION; -import static datadog.trace.api.config.DebuggerConfig.DEBUGGER_REDACTED_IDENTIFIERS; -import static datadog.trace.api.config.DebuggerConfig.DEBUGGER_REDACTED_TYPES; -import static datadog.trace.api.config.DebuggerConfig.DEBUGGER_REDACTION_EXCLUDED_IDENTIFIERS; -import static datadog.trace.api.config.DebuggerConfig.DEBUGGER_SYMBOL_ENABLED; -import static datadog.trace.api.config.DebuggerConfig.DEBUGGER_SYMBOL_FLUSH_THRESHOLD; -import static datadog.trace.api.config.DebuggerConfig.DEBUGGER_SYMBOL_FORCE_UPLOAD; -import static datadog.trace.api.config.DebuggerConfig.DEBUGGER_SYMBOL_INCLUDES; -import static datadog.trace.api.config.DebuggerConfig.DEBUGGER_UPLOAD_BATCH_SIZE; -import static datadog.trace.api.config.DebuggerConfig.DEBUGGER_UPLOAD_FLUSH_INTERVAL; -import static datadog.trace.api.config.DebuggerConfig.DEBUGGER_UPLOAD_TIMEOUT; -import static datadog.trace.api.config.DebuggerConfig.DEBUGGER_VERIFY_BYTECODE; -import static datadog.trace.api.config.DebuggerConfig.EXCEPTION_REPLAY_ENABLED; -import static datadog.trace.api.config.DebuggerConfig.THIRD_PARTY_EXCLUDES; -import static datadog.trace.api.config.DebuggerConfig.THIRD_PARTY_INCLUDES; -import static datadog.trace.api.config.GeneralConfig.API_KEY; -import static datadog.trace.api.config.GeneralConfig.API_KEY_FILE; -import static datadog.trace.api.config.GeneralConfig.APPLICATION_KEY; -import static datadog.trace.api.config.GeneralConfig.APPLICATION_KEY_FILE; -import static datadog.trace.api.config.GeneralConfig.AZURE_APP_SERVICES; -import static datadog.trace.api.config.GeneralConfig.DATA_JOBS_COMMAND_PATTERN; -import static datadog.trace.api.config.GeneralConfig.DATA_JOBS_ENABLED; -import static datadog.trace.api.config.GeneralConfig.DATA_STREAMS_BUCKET_DURATION_SECONDS; -import static datadog.trace.api.config.GeneralConfig.DATA_STREAMS_ENABLED; -import static datadog.trace.api.config.GeneralConfig.DOGSTATSD_ARGS; -import static datadog.trace.api.config.GeneralConfig.DOGSTATSD_HOST; -import static datadog.trace.api.config.GeneralConfig.DOGSTATSD_NAMED_PIPE; -import static datadog.trace.api.config.GeneralConfig.DOGSTATSD_PATH; -import static datadog.trace.api.config.GeneralConfig.DOGSTATSD_PORT; -import static datadog.trace.api.config.GeneralConfig.DOGSTATSD_START_DELAY; -import static datadog.trace.api.config.GeneralConfig.ENV; -import static datadog.trace.api.config.GeneralConfig.GLOBAL_TAGS; -import static datadog.trace.api.config.GeneralConfig.HEALTH_METRICS_ENABLED; -import static datadog.trace.api.config.GeneralConfig.HEALTH_METRICS_STATSD_HOST; -import static datadog.trace.api.config.GeneralConfig.HEALTH_METRICS_STATSD_PORT; -import static datadog.trace.api.config.GeneralConfig.LOG_LEVEL; -import static datadog.trace.api.config.GeneralConfig.PERF_METRICS_ENABLED; -import static datadog.trace.api.config.GeneralConfig.PRIMARY_TAG; -import static datadog.trace.api.config.GeneralConfig.RUNTIME_ID_ENABLED; -import static datadog.trace.api.config.GeneralConfig.RUNTIME_METRICS_ENABLED; +import static datadog.trace.api.config.DebuggerConfig.*; +import static datadog.trace.api.config.GeneralConfig.*; import static datadog.trace.api.config.GeneralConfig.SERVICE_NAME; -import static datadog.trace.api.config.GeneralConfig.SITE; -import static datadog.trace.api.config.GeneralConfig.STARTUP_LOGS_ENABLED; -import static datadog.trace.api.config.GeneralConfig.STATSD_CLIENT_QUEUE_SIZE; -import static datadog.trace.api.config.GeneralConfig.STATSD_CLIENT_SOCKET_BUFFER; -import static datadog.trace.api.config.GeneralConfig.STATSD_CLIENT_SOCKET_TIMEOUT; -import static datadog.trace.api.config.GeneralConfig.TAGS; -import static datadog.trace.api.config.GeneralConfig.TELEMETRY_DEPENDENCY_COLLECTION_ENABLED; -import static datadog.trace.api.config.GeneralConfig.TELEMETRY_DEPENDENCY_RESOLUTION_QUEUE_SIZE; -import static datadog.trace.api.config.GeneralConfig.TELEMETRY_EXTENDED_HEARTBEAT_INTERVAL; -import static datadog.trace.api.config.GeneralConfig.TELEMETRY_HEARTBEAT_INTERVAL; -import static datadog.trace.api.config.GeneralConfig.TELEMETRY_LOG_COLLECTION_ENABLED; -import static datadog.trace.api.config.GeneralConfig.TELEMETRY_METRICS_INTERVAL; -import static datadog.trace.api.config.GeneralConfig.TRACER_METRICS_BUFFERING_ENABLED; -import static datadog.trace.api.config.GeneralConfig.TRACER_METRICS_ENABLED; -import static datadog.trace.api.config.GeneralConfig.TRACER_METRICS_IGNORED_RESOURCES; -import static datadog.trace.api.config.GeneralConfig.TRACER_METRICS_MAX_AGGREGATES; -import static datadog.trace.api.config.GeneralConfig.TRACER_METRICS_MAX_PENDING; -import static datadog.trace.api.config.GeneralConfig.TRACE_DEBUG; -import static datadog.trace.api.config.GeneralConfig.TRACE_TAGS; -import static datadog.trace.api.config.GeneralConfig.TRACE_TRIAGE; -import static datadog.trace.api.config.GeneralConfig.TRIAGE_REPORT_DIR; -import static datadog.trace.api.config.GeneralConfig.TRIAGE_REPORT_TRIGGER; -import static datadog.trace.api.config.GeneralConfig.VERSION; -import static datadog.trace.api.config.IastConfig.IAST_ANONYMOUS_CLASSES_ENABLED; -import static datadog.trace.api.config.IastConfig.IAST_CONTEXT_MODE; -import static datadog.trace.api.config.IastConfig.IAST_DEBUG_ENABLED; -import static datadog.trace.api.config.IastConfig.IAST_DETECTION_MODE; -import static datadog.trace.api.config.IastConfig.IAST_HARDCODED_SECRET_ENABLED; -import static datadog.trace.api.config.IastConfig.IAST_REDACTION_ENABLED; -import static datadog.trace.api.config.IastConfig.IAST_REDACTION_NAME_PATTERN; -import static datadog.trace.api.config.IastConfig.IAST_REDACTION_VALUE_PATTERN; -import static datadog.trace.api.config.IastConfig.IAST_SOURCE_MAPPING_ENABLED; -import static datadog.trace.api.config.IastConfig.IAST_SOURCE_MAPPING_MAX_SIZE; -import static datadog.trace.api.config.IastConfig.IAST_STACKTRACE_LEAK_SUPPRESS; -import static datadog.trace.api.config.IastConfig.IAST_TELEMETRY_VERBOSITY; -import static datadog.trace.api.config.IastConfig.IAST_TRUNCATION_MAX_VALUE_LENGTH; -import static datadog.trace.api.config.IastConfig.IAST_WEAK_CIPHER_ALGORITHMS; -import static datadog.trace.api.config.IastConfig.IAST_WEAK_HASH_ALGORITHMS; -import static datadog.trace.api.config.JmxFetchConfig.JMX_FETCH_CHECK_PERIOD; -import static datadog.trace.api.config.JmxFetchConfig.JMX_FETCH_CONFIG; -import static datadog.trace.api.config.JmxFetchConfig.JMX_FETCH_CONFIG_DIR; -import static datadog.trace.api.config.JmxFetchConfig.JMX_FETCH_ENABLED; -import static datadog.trace.api.config.JmxFetchConfig.JMX_FETCH_INITIAL_REFRESH_BEANS_PERIOD; -import static datadog.trace.api.config.JmxFetchConfig.JMX_FETCH_METRICS_CONFIGS; -import static datadog.trace.api.config.JmxFetchConfig.JMX_FETCH_MULTIPLE_RUNTIME_SERVICES_ENABLED; -import static datadog.trace.api.config.JmxFetchConfig.JMX_FETCH_MULTIPLE_RUNTIME_SERVICES_LIMIT; -import static datadog.trace.api.config.JmxFetchConfig.JMX_FETCH_REFRESH_BEANS_PERIOD; -import static datadog.trace.api.config.JmxFetchConfig.JMX_FETCH_START_DELAY; -import static datadog.trace.api.config.JmxFetchConfig.JMX_FETCH_STATSD_HOST; -import static datadog.trace.api.config.JmxFetchConfig.JMX_FETCH_STATSD_PORT; -import static datadog.trace.api.config.JmxFetchConfig.JMX_TAGS; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_AGENTLESS; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_AGENTLESS_DEFAULT; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_API_KEY_FILE_OLD; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_API_KEY_FILE_VERY_OLD; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_API_KEY_OLD; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_API_KEY_VERY_OLD; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_BACKPRESSURE_SAMPLE_LIMIT_DEFAULT; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_BACKPRESSURE_SAMPLING_ENABLED; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_BACKPRESSURE_SAMPLING_ENABLED_DEFAULT; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_DATADOG_PROFILER_ENABLED; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_DIRECT_ALLOCATION_SAMPLE_LIMIT; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_DIRECT_ALLOCATION_SAMPLE_LIMIT_DEFAULT; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_EXCEPTION_HISTOGRAM_MAX_COLLECTION_SIZE; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_EXCEPTION_HISTOGRAM_MAX_COLLECTION_SIZE_DEFAULT; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_EXCEPTION_HISTOGRAM_TOP_ITEMS; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_EXCEPTION_HISTOGRAM_TOP_ITEMS_DEFAULT; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_EXCEPTION_RECORD_MESSAGE; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_EXCEPTION_RECORD_MESSAGE_DEFAULT; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_EXCEPTION_SAMPLE_LIMIT; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_EXCEPTION_SAMPLE_LIMIT_DEFAULT; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_EXCLUDE_AGENT_THREADS; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_PROXY_HOST; -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_PORT_DEFAULT; -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; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_UPLOAD_COMPRESSION_DEFAULT; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_UPLOAD_PERIOD; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_UPLOAD_PERIOD_DEFAULT; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_UPLOAD_SUMMARY_ON_413; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_UPLOAD_SUMMARY_ON_413_DEFAULT; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_UPLOAD_TIMEOUT; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_UPLOAD_TIMEOUT_DEFAULT; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_URL; -import static datadog.trace.api.config.RemoteConfigConfig.REMOTE_CONFIGURATION_ENABLED; -import static datadog.trace.api.config.RemoteConfigConfig.REMOTE_CONFIG_ENABLED; -import static datadog.trace.api.config.RemoteConfigConfig.REMOTE_CONFIG_INTEGRITY_CHECK_ENABLED; -import static datadog.trace.api.config.RemoteConfigConfig.REMOTE_CONFIG_MAX_EXTRA_SERVICES; -import static datadog.trace.api.config.RemoteConfigConfig.REMOTE_CONFIG_MAX_PAYLOAD_SIZE; -import static datadog.trace.api.config.RemoteConfigConfig.REMOTE_CONFIG_POLL_INTERVAL_SECONDS; -import static datadog.trace.api.config.RemoteConfigConfig.REMOTE_CONFIG_TARGETS_KEY; -import static datadog.trace.api.config.RemoteConfigConfig.REMOTE_CONFIG_TARGETS_KEY_ID; -import static datadog.trace.api.config.RemoteConfigConfig.REMOTE_CONFIG_URL; -import static datadog.trace.api.config.TraceInstrumentationConfig.AXIS_PROMOTE_RESOURCE_NAME; -import static datadog.trace.api.config.TraceInstrumentationConfig.COUCHBASE_INTERNAL_SPANS_ENABLED; -import static datadog.trace.api.config.TraceInstrumentationConfig.DB_CLIENT_HOST_SPLIT_BY_HOST; -import static datadog.trace.api.config.TraceInstrumentationConfig.DB_CLIENT_HOST_SPLIT_BY_INSTANCE; -import static datadog.trace.api.config.TraceInstrumentationConfig.DB_CLIENT_HOST_SPLIT_BY_INSTANCE_TYPE_SUFFIX; -import static datadog.trace.api.config.TraceInstrumentationConfig.DB_DBM_PROPAGATION_MODE_MODE; -import static datadog.trace.api.config.TraceInstrumentationConfig.ELASTICSEARCH_BODY_AND_PARAMS_ENABLED; -import static datadog.trace.api.config.TraceInstrumentationConfig.ELASTICSEARCH_BODY_ENABLED; -import static datadog.trace.api.config.TraceInstrumentationConfig.ELASTICSEARCH_PARAMS_ENABLED; -import static datadog.trace.api.config.TraceInstrumentationConfig.GOOGLE_PUBSUB_IGNORED_GRPC_METHODS; -import static datadog.trace.api.config.TraceInstrumentationConfig.GRPC_CLIENT_ERROR_STATUSES; -import static datadog.trace.api.config.TraceInstrumentationConfig.GRPC_IGNORED_INBOUND_METHODS; -import static datadog.trace.api.config.TraceInstrumentationConfig.GRPC_IGNORED_OUTBOUND_METHODS; -import static datadog.trace.api.config.TraceInstrumentationConfig.GRPC_SERVER_ERROR_STATUSES; -import static datadog.trace.api.config.TraceInstrumentationConfig.GRPC_SERVER_TRIM_PACKAGE_RESOURCE; -import static datadog.trace.api.config.TraceInstrumentationConfig.HTTP_CLIENT_HOST_SPLIT_BY_DOMAIN; -import static datadog.trace.api.config.TraceInstrumentationConfig.HTTP_CLIENT_TAG_HEADERS; -import static datadog.trace.api.config.TraceInstrumentationConfig.HTTP_CLIENT_TAG_QUERY_STRING; -import static datadog.trace.api.config.TraceInstrumentationConfig.HTTP_SERVER_DECODED_RESOURCE_PRESERVE_SPACES; -import static datadog.trace.api.config.TraceInstrumentationConfig.HTTP_SERVER_RAW_QUERY_STRING; -import static datadog.trace.api.config.TraceInstrumentationConfig.HTTP_SERVER_RAW_RESOURCE; -import static datadog.trace.api.config.TraceInstrumentationConfig.HTTP_SERVER_ROUTE_BASED_NAMING; -import static datadog.trace.api.config.TraceInstrumentationConfig.HTTP_SERVER_TAG_QUERY_STRING; -import static datadog.trace.api.config.TraceInstrumentationConfig.HYSTRIX_MEASURED_ENABLED; -import static datadog.trace.api.config.TraceInstrumentationConfig.HYSTRIX_TAGS_ENABLED; -import static datadog.trace.api.config.TraceInstrumentationConfig.IGNITE_CACHE_INCLUDE_KEYS; -import static datadog.trace.api.config.TraceInstrumentationConfig.INTEGRATION_SYNAPSE_LEGACY_OPERATION_NAME; -import static datadog.trace.api.config.TraceInstrumentationConfig.JAX_RS_EXCEPTION_AS_ERROR_ENABLED; -import static datadog.trace.api.config.TraceInstrumentationConfig.JMS_PROPAGATION_DISABLED_QUEUES; -import static datadog.trace.api.config.TraceInstrumentationConfig.JMS_PROPAGATION_DISABLED_TOPICS; -import static datadog.trace.api.config.TraceInstrumentationConfig.JMS_UNACKNOWLEDGED_MAX_AGE; -import static datadog.trace.api.config.TraceInstrumentationConfig.KAFKA_CLIENT_BASE64_DECODING_ENABLED; -import static datadog.trace.api.config.TraceInstrumentationConfig.KAFKA_CLIENT_PROPAGATION_DISABLED_TOPICS; -import static datadog.trace.api.config.TraceInstrumentationConfig.LOGS_INJECTION; -import static datadog.trace.api.config.TraceInstrumentationConfig.LOGS_INJECTION_ENABLED; -import static datadog.trace.api.config.TraceInstrumentationConfig.MESSAGE_BROKER_SPLIT_BY_DESTINATION; -import static datadog.trace.api.config.TraceInstrumentationConfig.OBFUSCATION_QUERY_STRING_REGEXP; -import static datadog.trace.api.config.TraceInstrumentationConfig.PLAY_REPORT_HTTP_STATUS; -import static datadog.trace.api.config.TraceInstrumentationConfig.RABBIT_INCLUDE_ROUTINGKEY_IN_RESOURCE; -import static datadog.trace.api.config.TraceInstrumentationConfig.RABBIT_PROPAGATION_DISABLED_EXCHANGES; -import static datadog.trace.api.config.TraceInstrumentationConfig.RABBIT_PROPAGATION_DISABLED_QUEUES; -import static datadog.trace.api.config.TraceInstrumentationConfig.SERVLET_ASYNC_TIMEOUT_ERROR; -import static datadog.trace.api.config.TraceInstrumentationConfig.SERVLET_PRINCIPAL_ENABLED; -import static datadog.trace.api.config.TraceInstrumentationConfig.SERVLET_ROOT_CONTEXT_SERVICE_NAME; -import static datadog.trace.api.config.TraceInstrumentationConfig.SPARK_APP_NAME_AS_SERVICE; -import static datadog.trace.api.config.TraceInstrumentationConfig.SPARK_TASK_HISTOGRAM_ENABLED; -import static datadog.trace.api.config.TraceInstrumentationConfig.SPRING_DATA_REPOSITORY_INTERFACE_RESOURCE_NAME; -import static datadog.trace.api.config.TracerConfig.AGENT_HOST; -import static datadog.trace.api.config.TracerConfig.AGENT_NAMED_PIPE; -import static datadog.trace.api.config.TracerConfig.AGENT_PORT_LEGACY; -import static datadog.trace.api.config.TracerConfig.AGENT_TIMEOUT; -import static datadog.trace.api.config.TracerConfig.AGENT_UNIX_DOMAIN_SOCKET; -import static datadog.trace.api.config.TracerConfig.BAGGAGE_MAPPING; -import static datadog.trace.api.config.TracerConfig.CLIENT_IP_ENABLED; -import static datadog.trace.api.config.TracerConfig.CLOCK_SYNC_PERIOD; -import static datadog.trace.api.config.TracerConfig.ENABLE_TRACE_AGENT_V05; -import static datadog.trace.api.config.TracerConfig.HEADER_TAGS; -import static datadog.trace.api.config.TracerConfig.HTTP_CLIENT_ERROR_STATUSES; -import static datadog.trace.api.config.TracerConfig.HTTP_SERVER_ERROR_STATUSES; -import static datadog.trace.api.config.TracerConfig.ID_GENERATION_STRATEGY; -import static datadog.trace.api.config.TracerConfig.PARTIAL_FLUSH_ENABLED; -import static datadog.trace.api.config.TracerConfig.PARTIAL_FLUSH_MIN_SPANS; -import static datadog.trace.api.config.TracerConfig.PRIORITY_SAMPLING; -import static datadog.trace.api.config.TracerConfig.PRIORITY_SAMPLING_FORCE; -import static datadog.trace.api.config.TracerConfig.PROPAGATION_EXTRACT_LOG_HEADER_NAMES_ENABLED; -import static datadog.trace.api.config.TracerConfig.PROPAGATION_STYLE_EXTRACT; -import static datadog.trace.api.config.TracerConfig.PROPAGATION_STYLE_INJECT; -import static datadog.trace.api.config.TracerConfig.PROXY_NO_PROXY; -import static datadog.trace.api.config.TracerConfig.REQUEST_HEADER_TAGS; -import static datadog.trace.api.config.TracerConfig.REQUEST_HEADER_TAGS_COMMA_ALLOWED; -import static datadog.trace.api.config.TracerConfig.RESPONSE_HEADER_TAGS; -import static datadog.trace.api.config.TracerConfig.SCOPE_DEPTH_LIMIT; -import static datadog.trace.api.config.TracerConfig.SCOPE_INHERIT_ASYNC_PROPAGATION; -import static datadog.trace.api.config.TracerConfig.SCOPE_ITERATION_KEEP_ALIVE; -import static datadog.trace.api.config.TracerConfig.SCOPE_STRICT_MODE; -import static datadog.trace.api.config.TracerConfig.SECURE_RANDOM; -import static datadog.trace.api.config.TracerConfig.SERVICE_MAPPING; -import static datadog.trace.api.config.TracerConfig.SPAN_SAMPLING_RULES; -import static datadog.trace.api.config.TracerConfig.SPAN_SAMPLING_RULES_FILE; -import static datadog.trace.api.config.TracerConfig.SPAN_TAGS; -import static datadog.trace.api.config.TracerConfig.SPLIT_BY_TAGS; -import static datadog.trace.api.config.TracerConfig.TRACE_128_BIT_TRACEID_GENERATION_ENABLED; -import static datadog.trace.api.config.TracerConfig.TRACE_AGENT_ARGS; -import static datadog.trace.api.config.TracerConfig.TRACE_AGENT_PATH; -import static datadog.trace.api.config.TracerConfig.TRACE_AGENT_PORT; -import static datadog.trace.api.config.TracerConfig.TRACE_AGENT_URL; -import static datadog.trace.api.config.TracerConfig.TRACE_ANALYTICS_ENABLED; -import static datadog.trace.api.config.TracerConfig.TRACE_CLIENT_IP_HEADER; -import static datadog.trace.api.config.TracerConfig.TRACE_CLIENT_IP_RESOLVER_ENABLED; -import static datadog.trace.api.config.TracerConfig.TRACE_GIT_METADATA_ENABLED; -import static datadog.trace.api.config.TracerConfig.TRACE_HTTP_CLIENT_PATH_RESOURCE_NAME_MAPPING; -import static datadog.trace.api.config.TracerConfig.TRACE_HTTP_RESOURCE_REMOVE_TRAILING_SLASH; -import static datadog.trace.api.config.TracerConfig.TRACE_HTTP_SERVER_PATH_RESOURCE_NAME_MAPPING; -import static datadog.trace.api.config.TracerConfig.TRACE_PEER_SERVICE_COMPONENT_OVERRIDES; -import static datadog.trace.api.config.TracerConfig.TRACE_PEER_SERVICE_DEFAULTS_ENABLED; -import static datadog.trace.api.config.TracerConfig.TRACE_PEER_SERVICE_MAPPING; -import static datadog.trace.api.config.TracerConfig.TRACE_POST_PROCESSING_TIMEOUT; -import static datadog.trace.api.config.TracerConfig.TRACE_PROPAGATION_EXTRACT_FIRST; -import static datadog.trace.api.config.TracerConfig.TRACE_PROPAGATION_STYLE; -import static datadog.trace.api.config.TracerConfig.TRACE_PROPAGATION_STYLE_EXTRACT; -import static datadog.trace.api.config.TracerConfig.TRACE_PROPAGATION_STYLE_INJECT; -import static datadog.trace.api.config.TracerConfig.TRACE_RATE_LIMIT; -import static datadog.trace.api.config.TracerConfig.TRACE_REMOVE_INTEGRATION_SERVICE_NAMES_ENABLED; -import static datadog.trace.api.config.TracerConfig.TRACE_REPORT_HOSTNAME; -import static datadog.trace.api.config.TracerConfig.TRACE_RESOLVER_ENABLED; -import static datadog.trace.api.config.TracerConfig.TRACE_SAMPLE_RATE; -import static datadog.trace.api.config.TracerConfig.TRACE_SAMPLING_OPERATION_RULES; -import static datadog.trace.api.config.TracerConfig.TRACE_SAMPLING_RULES; -import static datadog.trace.api.config.TracerConfig.TRACE_SAMPLING_SERVICE_RULES; -import static datadog.trace.api.config.TracerConfig.TRACE_SPAN_ATTRIBUTE_SCHEMA; -import static datadog.trace.api.config.TracerConfig.TRACE_STRICT_WRITES_ENABLED; -import static datadog.trace.api.config.TracerConfig.TRACE_X_DATADOG_TAGS_MAX_LENGTH; -import static datadog.trace.api.config.TracerConfig.WRITER_BAGGAGE_INJECT; -import static datadog.trace.api.config.TracerConfig.WRITER_TYPE; +import static datadog.trace.api.config.IastConfig.*; +import static datadog.trace.api.config.JmxFetchConfig.*; +import static datadog.trace.api.config.ProfilingConfig.*; +import static datadog.trace.api.config.RemoteConfigConfig.*; +import static datadog.trace.api.config.TraceInstrumentationConfig.*; +import static datadog.trace.api.config.TracerConfig.*; import static datadog.trace.api.iast.IastDetectionMode.DEFAULT; import static datadog.trace.api.telemetry.LogCollector.SEND_TELEMETRY; import static datadog.trace.util.CollectionUtils.tryMakeImmutableList; @@ -523,30 +45,13 @@ import java.io.File; import java.io.IOException; import java.io.InputStreamReader; -import java.net.InetAddress; -import java.net.MalformedURLException; -import java.net.URI; -import java.net.URISyntaxException; -import java.net.URL; -import java.net.UnknownHostException; +import java.net.*; import java.nio.charset.StandardCharsets; import java.nio.file.FileSystems; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.BitSet; -import java.util.Collections; -import java.util.HashMap; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Properties; -import java.util.Set; -import java.util.SortedSet; -import java.util.UUID; +import java.util.*; import java.util.concurrent.TimeUnit; import java.util.function.Function; import java.util.function.Supplier; @@ -853,6 +358,8 @@ public static String getHostName() { private final boolean ciVisibilityTelemetryEnabled; private final long ciVisibilityRumFlushWaitMillis; private final boolean ciVisibilityAutoInjected; + private final String ciVisibilityRemoteEnvVarsProviderUrl; + private final String ciVisibilityRemoteEnvVarsProviderKey; private final boolean remoteConfigEnabled; private final boolean remoteConfigIntegrityCheckEnabled; @@ -1928,6 +1435,10 @@ PROFILING_DATADOG_PROFILER_ENABLED, isDatadogProfilerSafeInCurrentEnvironment()) configProvider.getLong(CIVISIBILITY_RUM_FLUSH_WAIT_MILLIS, 500); ciVisibilityAutoInjected = Strings.isNotBlank(configProvider.getString(CIVISIBILITY_AUTO_INSTRUMENTATION_PROVIDER)); + ciVisibilityRemoteEnvVarsProviderUrl = + configProvider.getString(CIVISIBILITY_REMOTE_ENV_VARS_PROVIDER_URL); + ciVisibilityRemoteEnvVarsProviderKey = + configProvider.getString(CIVISIBILITY_REMOTE_ENV_VARS_PROVIDER_KEY); remoteConfigEnabled = configProvider.getBoolean( @@ -3291,6 +2802,14 @@ public boolean isCiVisibilityAutoInjected() { return ciVisibilityAutoInjected; } + public String getCiVisibilityRemoteEnvVarsProviderUrl() { + return ciVisibilityRemoteEnvVarsProviderUrl; + } + + public String getCiVisibilityRemoteEnvVarsProviderKey() { + return ciVisibilityRemoteEnvVarsProviderKey; + } + public String getAppSecRulesFile() { return appSecRulesFile; } diff --git a/internal-api/src/main/java/datadog/trace/api/InstrumenterConfig.java b/internal-api/src/main/java/datadog/trace/api/InstrumenterConfig.java index f0aa03e83f8..78152292a48 100644 --- a/internal-api/src/main/java/datadog/trace/api/InstrumenterConfig.java +++ b/internal-api/src/main/java/datadog/trace/api/InstrumenterConfig.java @@ -108,6 +108,7 @@ public class InstrumenterConfig { private final boolean ciVisibilityEnabled; private final ProductActivation appSecActivation; private final ProductActivation iastActivation; + private final boolean iastFullyDisabled; private final boolean usmEnabled; private final boolean telemetryEnabled; @@ -194,6 +195,8 @@ private InstrumenterConfig() { iastActivation = ProductActivation.fromString( configProvider.getStringNotEmpty(IAST_ENABLED, DEFAULT_IAST_ENABLED)); + final Boolean iastEnabled = configProvider.getBoolean(IAST_ENABLED); + iastFullyDisabled = iastEnabled != null && !iastEnabled; usmEnabled = configProvider.getBoolean(USM_ENABLED, DEFAULT_USM_ENABLED); telemetryEnabled = configProvider.getBoolean(TELEMETRY_ENABLED, DEFAULT_TELEMETRY_ENABLED); } else { @@ -201,6 +204,7 @@ private InstrumenterConfig() { ciVisibilityEnabled = false; appSecActivation = ProductActivation.FULLY_DISABLED; iastActivation = ProductActivation.FULLY_DISABLED; + iastFullyDisabled = true; telemetryEnabled = false; usmEnabled = false; } @@ -321,6 +325,10 @@ public ProductActivation getIastActivation() { return iastActivation; } + public boolean isIastFullyDisabled() { + return iastFullyDisabled; + } + public boolean isUsmEnabled() { return usmEnabled; } diff --git a/internal-api/src/main/java/datadog/trace/api/appsec/AppSecEventTracker.java b/internal-api/src/main/java/datadog/trace/api/appsec/AppSecEventTracker.java index 204c53a3736..c4e84ae317e 100644 --- a/internal-api/src/main/java/datadog/trace/api/appsec/AppSecEventTracker.java +++ b/internal-api/src/main/java/datadog/trace/api/appsec/AppSecEventTracker.java @@ -47,6 +47,8 @@ public abstract void onLoginSuccessEvent( public abstract void onLoginFailureEvent( UserIdCollectionMode mode, String userId, Boolean exists, Map metadata); + public abstract void onUserEvent(UserIdCollectionMode mode, String userId); + public abstract void onCustomEvent( UserIdCollectionMode mode, String eventName, Map metadata); } diff --git a/settings.gradle b/settings.gradle index d332a3df27d..a48738f63c6 100644 --- a/settings.gradle +++ b/settings.gradle @@ -168,8 +168,10 @@ include ':dd-smoke-tests:iast-util' // instrumentation: include ':dd-java-agent:instrumentation:aerospike-4' include ':dd-java-agent:instrumentation:akka-concurrent' -include ':dd-java-agent:instrumentation:akka-http-10.0' -include ':dd-java-agent:instrumentation:akka-http-10.2-iast' +include ':dd-java-agent:instrumentation:akka-http' +include ':dd-java-agent:instrumentation:akka-http:akka-http-10.0' +include ':dd-java-agent:instrumentation:akka-http:akka-http-10.2-iast' +include ':dd-java-agent:instrumentation:akka-http:akka-http-10.6' include ':dd-java-agent:instrumentation:akka-init' include ':dd-java-agent:instrumentation:apache-httpasyncclient-4' include ':dd-java-agent:instrumentation:apache-httpclient-4' @@ -433,6 +435,7 @@ include ':dd-java-agent:instrumentation:spring-messaging-4' include ':dd-java-agent:instrumentation:spring-rabbit' include ':dd-java-agent:instrumentation:spring-scheduling-3.1' include ':dd-java-agent:instrumentation:spring-security-5' +include ':dd-java-agent:instrumentation:spring-security-6' include ':dd-java-agent:instrumentation:spring-webflux-5' include ':dd-java-agent:instrumentation:spring-webflux-6' include ':dd-java-agent:instrumentation:spring-webmvc-3.1' diff --git a/setup.sh b/setup.sh index 077421fd6fd..de097ead030 100755 --- a/setup.sh +++ b/setup.sh @@ -59,7 +59,7 @@ function look-for-hook() { elif [ -e "$HOOKS_PATH/$HOOK_NAME" ] && [ "$(get-file-hash $HOOKS_PATH/$HOOK_NAME)" == "$HOOK_CHECKSUM" ]; then echo "✅ $HOOK_NAME hook is installed in git hooks path." else - echo "🟨 $HOOK_NAME hook was not found (optional but recommanded)." + echo "🟨 $HOOK_NAME hook was not found (optional but recommended)." fi }