From 5bc7f009efddb8d3c1942d8b377184b7281f4edd Mon Sep 17 00:00:00 2001 From: Ohjun Kwon Date: Mon, 8 May 2023 21:59:20 +0900 Subject: [PATCH 01/30] Add integration test for scavenger-agent-java --- scavenger-agent-java/build.gradle.kts | 34 ++++++++ .../integrationTest/javaagent/ConfigTest.java | 67 +++++++++++++++ .../AgentIntegrationTestContextProvider.java | 72 ++++++++++++++++ .../integrationTest/support/AgentRunner.java | 85 +++++++++++++++++++ .../util/AgentLogAssertionUtil.java | 31 +++++++ .../java/sample/app/NotServiceClass.java | 11 +++ .../java/sample/app/SampleApp.java | 48 +++++++++++ .../java/sample/app/SampleAspect.java | 31 +++++++ .../java/sample/app/SampleService1.java | 18 ++++ .../java/sample/app/SampleService2.java | 15 ++++ .../sample/app/excluded/NotTrackedClass.java | 15 ++++ .../sample/app/excluded/NotTrackedClass2.java | 11 +++ .../resources/logging.properties | 8 ++ .../integrationTest/resources/scavenger.conf | 6 ++ 14 files changed, 452 insertions(+) create mode 100644 scavenger-agent-java/src/integrationTest/java/integrationTest/javaagent/ConfigTest.java create mode 100644 scavenger-agent-java/src/integrationTest/java/integrationTest/support/AgentIntegrationTestContextProvider.java create mode 100644 scavenger-agent-java/src/integrationTest/java/integrationTest/support/AgentRunner.java create mode 100644 scavenger-agent-java/src/integrationTest/java/integrationTest/util/AgentLogAssertionUtil.java create mode 100644 scavenger-agent-java/src/integrationTest/java/sample/app/NotServiceClass.java create mode 100644 scavenger-agent-java/src/integrationTest/java/sample/app/SampleApp.java create mode 100644 scavenger-agent-java/src/integrationTest/java/sample/app/SampleAspect.java create mode 100644 scavenger-agent-java/src/integrationTest/java/sample/app/SampleService1.java create mode 100644 scavenger-agent-java/src/integrationTest/java/sample/app/SampleService2.java create mode 100644 scavenger-agent-java/src/integrationTest/java/sample/app/excluded/NotTrackedClass.java create mode 100644 scavenger-agent-java/src/integrationTest/java/sample/app/excluded/NotTrackedClass2.java create mode 100644 scavenger-agent-java/src/integrationTest/resources/logging.properties create mode 100644 scavenger-agent-java/src/integrationTest/resources/scavenger.conf diff --git a/scavenger-agent-java/build.gradle.kts b/scavenger-agent-java/build.gradle.kts index 17a98acf..b847f475 100644 --- a/scavenger-agent-java/build.gradle.kts +++ b/scavenger-agent-java/build.gradle.kts @@ -7,6 +7,7 @@ plugins { signing id("com.github.johnrengelman.shadow") version "7.0.0" id("io.freefair.lombok") version "6.6.3" + id("org.unbroken-dome.test-sets") version "4.0.0" } java { @@ -72,6 +73,39 @@ dependencies { testImplementation("org.mockito:mockito-inline:4.3.1") } +testSets { + create("integrationTest") +} + +dependencies { + "integrationTestImplementation"("org.springframework.boot:spring-boot-starter-test:2.5.12") + "integrationTestImplementation"("org.springframework.boot:spring-boot-starter-aop:2.5.12") + "integrationTestImplementation"("com.github.tomakehurst:wiremock:2.27.2") +} + +fun javaPaths(vararg versions: Int) = versions.joinToString(",", + transform = { version: Int -> + "$version:" + javaToolchains.launcherFor { + languageVersion.set(JavaLanguageVersion.of(version)) + }.get().executablePath + }) + +val integrationTestRuntimeClasspath = configurations.named("integrationTestRuntimeClasspath").get().asPath + +tasks.named("integrationTest") { + dependsOn(tasks.shadowJar) + shouldRunAfter(tasks.test) + useJUnitPlatform() + + inputs.files(file("build.gradle.kts")) + inputs.files(tasks.shadowJar.get().outputs.files) + outputs.dir(file("$buildDir/test-results/integrationTest")) + + systemProperty("integrationTest.scavengerAgent", tasks.shadowJar.get().outputs.files.asPath) + systemProperty("integrationTest.classpath", "build/classes/java/integrationTest:$integrationTestRuntimeClasspath") + systemProperty("integrationTest.javaPaths", javaPaths(8, 11, 15, 17)) +} + tasks.withType { filesMatching("internal.properties") { expand(mapOf("scavenger_version" to project.version)) diff --git a/scavenger-agent-java/src/integrationTest/java/integrationTest/javaagent/ConfigTest.java b/scavenger-agent-java/src/integrationTest/java/integrationTest/javaagent/ConfigTest.java new file mode 100644 index 00000000..0a9c8fdf --- /dev/null +++ b/scavenger-agent-java/src/integrationTest/java/integrationTest/javaagent/ConfigTest.java @@ -0,0 +1,67 @@ +package integrationTest.javaagent; + +import static integrationTest.util.AgentLogAssertionUtil.assertDisabled; +import static integrationTest.util.AgentLogAssertionUtil.assertSampleAppOutput; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.containsString; + +import java.util.Properties; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.TestTemplate; +import org.junit.jupiter.api.extension.ExtendWith; + +import integrationTest.support.AgentIntegrationTestContextProvider; +import integrationTest.support.AgentRunner; + +@ExtendWith(AgentIntegrationTestContextProvider.class) +@DisplayName("config test") +public class ConfigTest { + + @TestTemplate + @DisplayName("if no configuration is found") + void noConfig(AgentRunner agentRunner) throws Exception { + // given + agentRunner.setConfigFilePath(""); + + // when + String stdout = agentRunner.call(); + + // then + assertThat(stdout, containsString("Configuration file is not found")); + assertDisabled(stdout); + assertSampleAppOutput(stdout); + } + + @TestTemplate + @DisplayName("if configuration does not exist at the specified location") + void nonExistentConfig(AgentRunner agentRunner) throws Exception { + // given + agentRunner.setConfigFilePath("foobar"); + + // when + String stdout = agentRunner.call(); + + // then + assertThat(stdout, containsString("Specified configuration file is not found")); + assertDisabled(stdout); + assertSampleAppOutput(stdout); + } + + @TestTemplate + @DisplayName("if required field is not set") + void missingRequiredTest(AgentRunner agentRunner) throws Exception { + // given + Properties properties = new Properties(); + properties.setProperty("packages", ""); + agentRunner.setConfig(properties); + + // when + String stdout = agentRunner.call(); + + // then + assertThat(stdout, containsString("mandatory property 'packages' is missing")); + assertDisabled(stdout); + assertSampleAppOutput(stdout); + } +} diff --git a/scavenger-agent-java/src/integrationTest/java/integrationTest/support/AgentIntegrationTestContextProvider.java b/scavenger-agent-java/src/integrationTest/java/integrationTest/support/AgentIntegrationTestContextProvider.java new file mode 100644 index 00000000..cd9ff2c2 --- /dev/null +++ b/scavenger-agent-java/src/integrationTest/java/integrationTest/support/AgentIntegrationTestContextProvider.java @@ -0,0 +1,72 @@ +package integrationTest.support; + +import static org.junit.jupiter.api.Assertions.assertNotNull; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.stream.Stream; + +import org.junit.jupiter.api.extension.Extension; +import org.junit.jupiter.api.extension.ExtensionContext; +import org.junit.jupiter.api.extension.ParameterContext; +import org.junit.jupiter.api.extension.ParameterResolutionException; +import org.junit.jupiter.api.extension.ParameterResolver; +import org.junit.jupiter.api.extension.TestTemplateInvocationContext; +import org.junit.jupiter.api.extension.TestTemplateInvocationContextProvider; + +public class AgentIntegrationTestContextProvider implements TestTemplateInvocationContextProvider { + private static final String scavengerAgentPath = System.getProperty("integrationTest.scavengerAgent"); + private static final String classpath = System.getProperty("integrationTest.classpath"); + private static final String javaPaths = System.getProperty("integrationTest.javaPaths"); + + @Override + public boolean supportsTestTemplate(ExtensionContext context) { + assertNotNull(scavengerAgentPath, "This test must be started from Gradle"); + assertNotNull(classpath, "This test must be started from Gradle"); + assertNotNull(javaPaths, "This test must be started from Gradle"); + return true; + } + + @Override + public Stream provideTestTemplateInvocationContexts(ExtensionContext context) { + return Arrays.stream(javaPaths.split(",")).map(this::invocationContext); + } + + private TestTemplateInvocationContext invocationContext(String javaPathString) { + String[] split = javaPathString.split(":"); + String javaVersion = split[0]; + String javaPath = split[1]; + + return new TestTemplateInvocationContext() { + @Override + public String getDisplayName(int invocationIndex) { + return "Java " + javaVersion; + } + + @Override + public List getAdditionalExtensions() { + return Collections.singletonList(new AgentRunnerParameterResolver(javaPath)); + } + }; + } + + private static class AgentRunnerParameterResolver implements ParameterResolver { + private final String javaPath; + + private AgentRunnerParameterResolver(String javaPath) { + this.javaPath = javaPath; + } + + @Override + public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) throws ParameterResolutionException { + return parameterContext.getParameter().getType() + .equals(AgentRunner.class); + } + + @Override + public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) throws ParameterResolutionException { + return new AgentRunner(javaPath, classpath, scavengerAgentPath); + } + } +} diff --git a/scavenger-agent-java/src/integrationTest/java/integrationTest/support/AgentRunner.java b/scavenger-agent-java/src/integrationTest/java/integrationTest/support/AgentRunner.java new file mode 100644 index 00000000..46e4b21d --- /dev/null +++ b/scavenger-agent-java/src/integrationTest/java/integrationTest/support/AgentRunner.java @@ -0,0 +1,85 @@ +package integrationTest.support; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.List; +import java.util.Properties; +import java.util.concurrent.Callable; +import java.util.stream.Collectors; + +public class AgentRunner implements Callable { + private final String javaPath; + private final String classpath; + private final String agentPath; + + private String configFilePath; + private String cmdLineArgs; + + public AgentRunner(String javaPath, String classpath, String agentPath) { + this.javaPath = javaPath; + this.classpath = classpath; + this.agentPath = agentPath; + } + + public void setConfigFilePath(String configFilePath) { + this.configFilePath = configFilePath; + } + + public void setConfig(Properties properties) { + cmdLineArgs = properties.entrySet().stream() + .map(entry -> entry.getKey() + "=" + entry.getValue()) + .collect(Collectors.joining(";")); + } + + @Override + public String call() throws IOException, InterruptedException, RuntimeException { + List command = buildCommand(); + Process process = new ProcessBuilder().command(command).redirectErrorStream(true).start(); + String output = collectProcessOutput(process.getInputStream()); + int exitCode = process.waitFor(); + if (exitCode != 0) { + throw new RuntimeException(String.format("Could not execute '%s': %s%nExit code=%d", command, output, exitCode)); + } + return output; + } + + private List buildCommand() { + String cp = classpath.endsWith(":") ? classpath.substring(0, classpath.length() - 2) : classpath; + + List command = new ArrayList<>(); + command.add(javaPath); + if (cmdLineArgs != null) { + command.add("-javaagent:" + agentPath + "=" + cmdLineArgs); + } else { + command.add("-javaagent:" + agentPath); + } + command.add("-cp"); + command.add(cp); + command.add("-Djava.util.logging.config.file=src/integrationTest/resources/logging.properties"); + command.add("-Duser.language=en"); + command.add("-Duser.country=US"); + if (configFilePath == null) { + command.add("-Dscavenger.configuration=src/integrationTest/resources/scavenger.conf"); + } else if (!configFilePath.isEmpty()) { + command.add("-Dscavenger.configuration=" + configFilePath); + } + command.add("sample.app.SampleApp"); + System.out.printf("%nLaunching SampleApp with the command: %s%n%n", command); + return command; + } + + private static String collectProcessOutput(InputStream inputStream) throws IOException { + StringBuilder sb = new StringBuilder(); + String line; + BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); + String newLine = ""; + while ((line = reader.readLine()) != null) { + sb.append(newLine).append(line); + newLine = String.format("%n"); + } + return sb.toString(); + } +} diff --git a/scavenger-agent-java/src/integrationTest/java/integrationTest/util/AgentLogAssertionUtil.java b/scavenger-agent-java/src/integrationTest/java/integrationTest/util/AgentLogAssertionUtil.java new file mode 100644 index 00000000..f73dfa31 --- /dev/null +++ b/scavenger-agent-java/src/integrationTest/java/integrationTest/util/AgentLogAssertionUtil.java @@ -0,0 +1,31 @@ +package integrationTest.util; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.matchesPattern; + +import java.util.regex.Pattern; + +public class AgentLogAssertionUtil { + public static void assertSampleAppOutput(String stdout) { + assertThat(stdout, matchesPattern(logPattern("sample.app.SampleApp", "SampleApp starts"))); + assertThat(stdout, matchesPattern(logPattern("sample.app.SampleApp", "2+2=4"))); + assertThat(stdout, + matchesPattern(logPattern("sample.app.SampleAspect", "Before execution(void sample.app.SampleService1.doSomething(int))"))); + assertThat(stdout, matchesPattern(logPattern("sample.app.SampleService1", "Doing something 1"))); + assertThat(stdout, + matchesPattern(logPattern("sample.app.SampleAspect", "Before execution(void sample.app.SampleService2.doSomething(int))"))); + assertThat(stdout, matchesPattern(logPattern("sample.app.SampleService2", "Doing something 2"))); + assertThat(stdout, matchesPattern(logPattern("sample.app.NotServiceClass", "Doing something 4"))); + assertThat(stdout, matchesPattern(logPattern("sample.app.SampleAspect", "After execution(void sample.app.SampleService2.doSomething(int))"))); + assertThat(stdout, matchesPattern(logPattern("sample.app.SampleAspect", "After execution(void sample.app.SampleService1.doSomething(int))"))); + assertThat(stdout, matchesPattern(logPattern("sample.app.SampleApp", "Exit"))); + } + + public static void assertDisabled(String stdout) { + assertThat(stdout, matchesPattern(logPattern("com.navercorp.scavenger.javaagent.ScavengerAgent", "[scavenger] scavenger is disabled"))); + } + + private static Pattern logPattern(String location, String text) { + return Pattern.compile("[\\s\\S]*(INFO|WARNING).*" + Pattern.quote(location) + ".*" + Pattern.quote(text) + "[\\s\\S]*"); + } +} diff --git a/scavenger-agent-java/src/integrationTest/java/sample/app/NotServiceClass.java b/scavenger-agent-java/src/integrationTest/java/sample/app/NotServiceClass.java new file mode 100644 index 00000000..cf19bdd0 --- /dev/null +++ b/scavenger-agent-java/src/integrationTest/java/sample/app/NotServiceClass.java @@ -0,0 +1,11 @@ +package sample.app; + +import lombok.extern.java.Log; + +@Log +public class NotServiceClass { + + public static void doSomething(int p1) { + log.info("Doing something " + p1); + } +} diff --git a/scavenger-agent-java/src/integrationTest/java/sample/app/SampleApp.java b/scavenger-agent-java/src/integrationTest/java/sample/app/SampleApp.java new file mode 100644 index 00000000..202890db --- /dev/null +++ b/scavenger-agent-java/src/integrationTest/java/sample/app/SampleApp.java @@ -0,0 +1,48 @@ +package sample.app; + +import javax.annotation.PostConstruct; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.EnableAspectJAutoProxy; +import org.springframework.stereotype.Controller; + +import lombok.RequiredArgsConstructor; +import lombok.extern.java.Log; + +/** + * @author olle.hallin@crisp.se + */ +@SuppressWarnings("ALL") +@Log +@SpringBootApplication +@EnableAspectJAutoProxy +@RequiredArgsConstructor +@Controller +public class SampleApp { + private final int dummy = 17; + private final SampleService1 sampleService1; + + public static void main(String[] args) throws InterruptedException { + log.info( + String.format( + "%s starts on Java %s", + SampleApp.class.getSimpleName(), System.getProperty("java.version"))); + SpringApplication.run(SampleApp.class, args); + log.info("Exit"); + } + + public int add(int p1, int p2) { + return privateAdd(p1, p2); + } + + private int privateAdd(int p1, int p2) { + return p1 + p2; + } + + @PostConstruct + public void postConstruct() { + log.info("2+2=" + add(2, 2)); + sampleService1.doSomething(1); + } +} diff --git a/scavenger-agent-java/src/integrationTest/java/sample/app/SampleAspect.java b/scavenger-agent-java/src/integrationTest/java/sample/app/SampleAspect.java new file mode 100644 index 00000000..767274a1 --- /dev/null +++ b/scavenger-agent-java/src/integrationTest/java/sample/app/SampleAspect.java @@ -0,0 +1,31 @@ +package sample.app; + +import javax.annotation.PostConstruct; + +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.springframework.stereotype.Component; + +import lombok.extern.java.Log; + +@Component +@Aspect +@Log +public class SampleAspect { + + @PostConstruct + public void logAspectLoaded() { + log.info("Aspect loaded"); + } + + @Around("execution(* sample.app.SampleService*.*(..))") + public Object aroundSampleService(ProceedingJoinPoint pjp) throws Throwable { + log.info("Before " + pjp); + try { + return pjp.proceed(); + } finally { + log.info("After " + pjp); + } + } +} diff --git a/scavenger-agent-java/src/integrationTest/java/sample/app/SampleService1.java b/scavenger-agent-java/src/integrationTest/java/sample/app/SampleService1.java new file mode 100644 index 00000000..5b64f2e0 --- /dev/null +++ b/scavenger-agent-java/src/integrationTest/java/sample/app/SampleService1.java @@ -0,0 +1,18 @@ +package sample.app; + +import org.springframework.stereotype.Service; + +import lombok.RequiredArgsConstructor; +import lombok.extern.java.Log; + +@Service +@RequiredArgsConstructor +@Log +public class SampleService1 { + private final SampleService2 sampleService2; + + public void doSomething(int p1) { + log.info("Doing something " + p1); + sampleService2.doSomething(p1 * 2); + } +} diff --git a/scavenger-agent-java/src/integrationTest/java/sample/app/SampleService2.java b/scavenger-agent-java/src/integrationTest/java/sample/app/SampleService2.java new file mode 100644 index 00000000..7a58ff50 --- /dev/null +++ b/scavenger-agent-java/src/integrationTest/java/sample/app/SampleService2.java @@ -0,0 +1,15 @@ +package sample.app; + +import org.springframework.stereotype.Service; + +import lombok.extern.java.Log; + +@Service +@Log +public class SampleService2 { + + public void doSomething(int p1) { + log.info("Doing something " + p1); + NotServiceClass.doSomething(p1 * 2); + } +} diff --git a/scavenger-agent-java/src/integrationTest/java/sample/app/excluded/NotTrackedClass.java b/scavenger-agent-java/src/integrationTest/java/sample/app/excluded/NotTrackedClass.java new file mode 100644 index 00000000..525ffd16 --- /dev/null +++ b/scavenger-agent-java/src/integrationTest/java/sample/app/excluded/NotTrackedClass.java @@ -0,0 +1,15 @@ +package sample.app.excluded; + +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +public class NotTrackedClass { + + private final NotTrackedClass2 notTrackedClass2; + + @SuppressWarnings("unused") + public void doSomething() { + // doing something + notTrackedClass2.doSomething(); + } +} diff --git a/scavenger-agent-java/src/integrationTest/java/sample/app/excluded/NotTrackedClass2.java b/scavenger-agent-java/src/integrationTest/java/sample/app/excluded/NotTrackedClass2.java new file mode 100644 index 00000000..11b89a03 --- /dev/null +++ b/scavenger-agent-java/src/integrationTest/java/sample/app/excluded/NotTrackedClass2.java @@ -0,0 +1,11 @@ +package sample.app.excluded; + +import org.springframework.stereotype.Service; + +@SuppressWarnings("EmptyMethod") +@Service +public class NotTrackedClass2 { + public void doSomething() { + // doing something + } +} diff --git a/scavenger-agent-java/src/integrationTest/resources/logging.properties b/scavenger-agent-java/src/integrationTest/resources/logging.properties new file mode 100644 index 00000000..1b60939d --- /dev/null +++ b/scavenger-agent-java/src/integrationTest/resources/logging.properties @@ -0,0 +1,8 @@ +handlers=java.util.logging.FileHandler, java.util.logging.ConsoleHandler +java.util.logging.FileHandler.formatter=java.util.logging.SimpleFormatter +java.util.logging.FileHandler.level=ALL +java.util.logging.FileHandler.pattern=build/integrationTest.log +java.util.logging.FileHandler.limit=10000000 +java.util.logging.ConsoleHandler.formatter=java.util.logging.SimpleFormatter +java.util.logging.ConsoleHandler.level=ALL +java.util.logging.SimpleFormatter.format=%1$tF %1$tT [%4$s] %3$s - %5$s%6$s%n diff --git a/scavenger-agent-java/src/integrationTest/resources/scavenger.conf b/scavenger-agent-java/src/integrationTest/resources/scavenger.conf new file mode 100644 index 00000000..1a578222 --- /dev/null +++ b/scavenger-agent-java/src/integrationTest/resources/scavenger.conf @@ -0,0 +1,6 @@ +appName = SampleApp +packages = sample +methodVisibility = protected +excludePackages = sample.app.excluded +codeBase = build/classes/java/integrationTest +debugMode = true From 419c15373a33481815acc887c12f96152f8a6588 Mon Sep 17 00:00:00 2001 From: Ohjun Kwon Date: Tue, 9 May 2023 03:39:16 +0900 Subject: [PATCH 02/30] Remove Java 15 since it is non-LTS release --- scavenger-agent-java/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scavenger-agent-java/build.gradle.kts b/scavenger-agent-java/build.gradle.kts index b847f475..d4836d56 100644 --- a/scavenger-agent-java/build.gradle.kts +++ b/scavenger-agent-java/build.gradle.kts @@ -103,7 +103,7 @@ tasks.named("integrationTest") { systemProperty("integrationTest.scavengerAgent", tasks.shadowJar.get().outputs.files.asPath) systemProperty("integrationTest.classpath", "build/classes/java/integrationTest:$integrationTestRuntimeClasspath") - systemProperty("integrationTest.javaPaths", javaPaths(8, 11, 15, 17)) + systemProperty("integrationTest.javaPaths", javaPaths(8, 11, 17)) } tasks.withType { From 14f33f0ca61737258dfd1be008da6730d0630292 Mon Sep 17 00:00:00 2001 From: Ohjun Kwon Date: Tue, 30 May 2023 21:27:48 +0900 Subject: [PATCH 03/30] Add integration tests for codebase, invocation data publications --- scavenger-agent-java/build.gradle.kts | 1 + .../javaagent/InvocationTest.java | 138 ++++++++++++++++++ .../integrationTest/javaagent/ScanTest.java | 135 +++++++++++++++++ .../util/AgentLogAssertionUtil.java | 29 ++++ 4 files changed, 303 insertions(+) create mode 100644 scavenger-agent-java/src/integrationTest/java/integrationTest/javaagent/InvocationTest.java create mode 100644 scavenger-agent-java/src/integrationTest/java/integrationTest/javaagent/ScanTest.java diff --git a/scavenger-agent-java/build.gradle.kts b/scavenger-agent-java/build.gradle.kts index d4836d56..8c18fa16 100644 --- a/scavenger-agent-java/build.gradle.kts +++ b/scavenger-agent-java/build.gradle.kts @@ -81,6 +81,7 @@ dependencies { "integrationTestImplementation"("org.springframework.boot:spring-boot-starter-test:2.5.12") "integrationTestImplementation"("org.springframework.boot:spring-boot-starter-aop:2.5.12") "integrationTestImplementation"("com.github.tomakehurst:wiremock:2.27.2") + "integrationTestImplementation"("org.grpcmock:grpcmock-junit5:0.9.4") } fun javaPaths(vararg versions: Int) = versions.joinToString(",", diff --git a/scavenger-agent-java/src/integrationTest/java/integrationTest/javaagent/InvocationTest.java b/scavenger-agent-java/src/integrationTest/java/integrationTest/javaagent/InvocationTest.java new file mode 100644 index 00000000..28690682 --- /dev/null +++ b/scavenger-agent-java/src/integrationTest/java/integrationTest/javaagent/InvocationTest.java @@ -0,0 +1,138 @@ +package integrationTest.javaagent; + +import static com.github.tomakehurst.wiremock.client.WireMock.get; +import static com.github.tomakehurst.wiremock.client.WireMock.givenThat; +import static com.github.tomakehurst.wiremock.client.WireMock.okJson; +import static com.navercorp.scavenger.model.Endpoints.Agent.V5_INIT_CONFIG; +import static integrationTest.util.AgentLogAssertionUtil.assertInvoked; +import static integrationTest.util.AgentLogAssertionUtil.assertNotInvoked; +import static integrationTest.util.AgentLogAssertionUtil.assertSampleAppOutput; +import static org.grpcmock.GrpcMock.calledMethod; +import static org.grpcmock.GrpcMock.getGlobalPort; +import static org.grpcmock.GrpcMock.stubFor; +import static org.grpcmock.GrpcMock.unaryMethod; +import static org.grpcmock.GrpcMock.verifyThat; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.util.Optional; +import java.util.Properties; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.grpcmock.GrpcMock; +import org.grpcmock.junit5.GrpcMockExtension; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.TestTemplate; +import org.junit.jupiter.api.extension.ExtendWith; + +import com.github.tomakehurst.wiremock.WireMockServer; +import com.github.tomakehurst.wiremock.client.WireMock; +import com.google.protobuf.util.JsonFormat; +import integrationTest.support.AgentIntegrationTestContextProvider; +import integrationTest.support.AgentRunner; +import io.grpc.ManagedChannel; +import io.grpc.ManagedChannelBuilder; +import sample.app.SampleApp; +import sample.app.SampleAspect; +import sample.app.SampleService1; +import sample.app.excluded.NotTrackedClass; + +import com.navercorp.scavenger.model.GetConfigResponse; +import com.navercorp.scavenger.model.GrpcAgentServiceGrpc; +import com.navercorp.scavenger.model.InitConfigResponse; +import com.navercorp.scavenger.model.PublicationResponse; + +@ExtendWith(AgentIntegrationTestContextProvider.class) +@ExtendWith(GrpcMockExtension.class) +@DisplayName("invocation track test") +public class InvocationTest { + private static WireMockServer wireMockServer; + private static ManagedChannel channel; + + @BeforeAll + static void setUp() { + wireMockServer = new WireMockServer(); + wireMockServer.start(); + WireMock.configureFor(wireMockServer.port()); + + channel = ManagedChannelBuilder.forAddress("localhost", GrpcMock.getGlobalPort()) + .usePlaintext() + .build(); + } + + @AfterAll + static void tearDown() { + Optional.ofNullable(wireMockServer).ifPresent(WireMockServer::shutdown); + Optional.ofNullable(channel).ifPresent(ManagedChannel::shutdownNow); + } + + @TestTemplate + @DisplayName("it tracks correctly") + void track(AgentRunner agentRunner) throws Exception { + // when + String stdout = agentRunner.call(); + + // then + assertSampleAppOutput(stdout); + assertInvoked(stdout, SampleApp.class.getMethod("add", int.class, int.class)); + assertInvoked(stdout, SampleAspect.class.getMethod("logAspectLoaded")); + assertInvoked(stdout, SampleService1.class.getMethod("doSomething", int.class)); + assertNotInvoked(stdout, NotTrackedClass.class.getMethod("doSomething")); + } + + @TestTemplate + @DisplayName("it sends publication correctly") + void send(AgentRunner agentRunner) throws Exception { + // given + Properties properties = new Properties(); + properties.setProperty("schedulerInitialDelayMillis", "0"); + agentRunner.setConfig(properties); + + givenThat( + get(V5_INIT_CONFIG + "?licenseKey=") + .willReturn(okJson(JsonFormat.printer().print( + InitConfigResponse.newBuilder() + .setCollectorUrl("localhost:" + getGlobalPort()) + .build())))); + + stubFor(unaryMethod(GrpcAgentServiceGrpc.getPollConfigMethod()) + .willReturn( + GetConfigResponse.newBuilder() + .setConfigPollIntervalSeconds(1) + .setConfigPollRetryIntervalSeconds(1) + .setCodeBasePublisherCheckIntervalSeconds(1) + .setCodeBasePublisherRetryIntervalSeconds(1) + .setInvocationDataPublisherIntervalSeconds(1) + .setInvocationDataPublisherRetryIntervalSeconds(1) + .build())); + + stubFor(unaryMethod(GrpcAgentServiceGrpc.getSendCodeBasePublicationMethod()) + .willReturn( + PublicationResponse.newBuilder() + .setStatus("OK") + .build())); + stubFor(unaryMethod(GrpcAgentServiceGrpc.getSendInvocationDataPublicationMethod()) + .willReturn( + PublicationResponse.newBuilder() + .setStatus("OK") + .build())); + + // when + String stdout = agentRunner.call(); + + // then + assertSampleAppOutput(stdout); + verifyThat( + calledMethod(GrpcAgentServiceGrpc.getSendInvocationDataPublicationMethod()) + .withStatusOk() + .withRequest(pub -> pub.getEntryCount() == getInvocationsCount(stdout))); + } + + private static int getInvocationsCount(String stdout) { + Matcher matcher = Pattern.compile("\\[scavenger] publishing invocation data: (\\d*) invocations").matcher(stdout); + assertTrue(matcher.find()); + return Integer.parseInt(matcher.group(1)); + } +} diff --git a/scavenger-agent-java/src/integrationTest/java/integrationTest/javaagent/ScanTest.java b/scavenger-agent-java/src/integrationTest/java/integrationTest/javaagent/ScanTest.java new file mode 100644 index 00000000..3c5b235c --- /dev/null +++ b/scavenger-agent-java/src/integrationTest/java/integrationTest/javaagent/ScanTest.java @@ -0,0 +1,135 @@ +package integrationTest.javaagent; + +import static com.github.tomakehurst.wiremock.client.WireMock.get; +import static com.github.tomakehurst.wiremock.client.WireMock.givenThat; +import static com.github.tomakehurst.wiremock.client.WireMock.okJson; +import static com.navercorp.scavenger.model.Endpoints.Agent.V5_INIT_CONFIG; +import static integrationTest.util.AgentLogAssertionUtil.assertNotScanned; +import static integrationTest.util.AgentLogAssertionUtil.assertSampleAppOutput; +import static integrationTest.util.AgentLogAssertionUtil.assertScanned; +import static org.grpcmock.GrpcMock.calledMethod; +import static org.grpcmock.GrpcMock.getGlobalPort; +import static org.grpcmock.GrpcMock.stubFor; +import static org.grpcmock.GrpcMock.unaryMethod; +import static org.grpcmock.GrpcMock.verifyThat; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.util.Optional; +import java.util.Properties; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.grpcmock.GrpcMock; +import org.grpcmock.junit5.GrpcMockExtension; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.TestTemplate; +import org.junit.jupiter.api.extension.ExtendWith; + +import com.github.tomakehurst.wiremock.WireMockServer; +import com.github.tomakehurst.wiremock.client.WireMock; +import com.google.protobuf.util.JsonFormat; +import integrationTest.support.AgentIntegrationTestContextProvider; +import integrationTest.support.AgentRunner; +import io.grpc.ManagedChannel; +import io.grpc.ManagedChannelBuilder; +import sample.app.NotServiceClass; +import sample.app.SampleApp; +import sample.app.SampleService1; +import sample.app.excluded.NotTrackedClass; +import sample.app.excluded.NotTrackedClass2; + +import com.navercorp.scavenger.model.GetConfigResponse; +import com.navercorp.scavenger.model.GrpcAgentServiceGrpc; +import com.navercorp.scavenger.model.InitConfigResponse; +import com.navercorp.scavenger.model.PublicationResponse; + +@ExtendWith(AgentIntegrationTestContextProvider.class) +@ExtendWith(GrpcMockExtension.class) +@DisplayName("codebase scan test") +public class ScanTest { + private static WireMockServer wireMockServer; + private static ManagedChannel channel; + + @BeforeAll + static void setUp() { + wireMockServer = new WireMockServer(); + wireMockServer.start(); + WireMock.configureFor(wireMockServer.port()); + + channel = ManagedChannelBuilder.forAddress("localhost", GrpcMock.getGlobalPort()) + .usePlaintext() + .build(); + } + + @AfterAll + static void tearDown() { + Optional.ofNullable(wireMockServer).ifPresent(WireMockServer::shutdown); + Optional.ofNullable(channel).ifPresent(ManagedChannel::shutdownNow); + } + + @TestTemplate + @DisplayName("it scans correctly") + void scan(AgentRunner agentRunner) throws Exception { + // when + String stdout = agentRunner.call(); + + // then + assertSampleAppOutput(stdout); + assertScanned(stdout, SampleService1.class.getMethod("doSomething", int.class)); + assertScanned(stdout, NotServiceClass.class.getMethod("doSomething", int.class)); + assertScanned(stdout, SampleApp.class.getMethod("main", String[].class)); + assertNotScanned(stdout, NotTrackedClass.class.getMethod("doSomething")); + assertNotScanned(stdout, NotTrackedClass2.class.getMethod("doSomething")); + } + + @TestTemplate + @DisplayName("it sends publication correctly") + void send(AgentRunner agentRunner) throws Exception { + // given + Properties properties = new Properties(); + properties.setProperty("schedulerInitialDelayMillis", "0"); + agentRunner.setConfig(properties); + + givenThat( + get(V5_INIT_CONFIG + "?licenseKey=") + .willReturn(okJson(JsonFormat.printer().print( + InitConfigResponse.newBuilder() + .setCollectorUrl("localhost:" + getGlobalPort()) + .build())))); + + stubFor(unaryMethod(GrpcAgentServiceGrpc.getPollConfigMethod()) + .willReturn( + GetConfigResponse.newBuilder() + .setConfigPollIntervalSeconds(1) + .setConfigPollRetryIntervalSeconds(1) + .setCodeBasePublisherCheckIntervalSeconds(1) + .setCodeBasePublisherRetryIntervalSeconds(1) + .setInvocationDataPublisherIntervalSeconds(1) + .setInvocationDataPublisherRetryIntervalSeconds(1) + .build())); + + stubFor(unaryMethod(GrpcAgentServiceGrpc.getSendCodeBasePublicationMethod()) + .willReturn( + PublicationResponse.newBuilder() + .setStatus("OK") + .build())); + + // when + String stdout = agentRunner.call(); + + // then + assertSampleAppOutput(stdout); + verifyThat( + calledMethod(GrpcAgentServiceGrpc.getSendCodeBasePublicationMethod()) + .withStatusOk() + .withRequest(pub -> pub.getEntryCount() == getMethodsCount(stdout))); + } + + private static int getMethodsCount(String stdout) { + Matcher matcher = Pattern.compile("\\[scavenger] codebase\\(.*\\) scanned in \\d* ms: (\\d*) methods").matcher(stdout); + assertTrue(matcher.find()); + return Integer.parseInt(matcher.group(1)); + } +} diff --git a/scavenger-agent-java/src/integrationTest/java/integrationTest/util/AgentLogAssertionUtil.java b/scavenger-agent-java/src/integrationTest/java/integrationTest/util/AgentLogAssertionUtil.java index f73dfa31..63421654 100644 --- a/scavenger-agent-java/src/integrationTest/java/integrationTest/util/AgentLogAssertionUtil.java +++ b/scavenger-agent-java/src/integrationTest/java/integrationTest/util/AgentLogAssertionUtil.java @@ -2,7 +2,9 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.matchesPattern; +import static org.hamcrest.Matchers.not; +import java.lang.reflect.Method; import java.util.regex.Pattern; public class AgentLogAssertionUtil { @@ -25,7 +27,34 @@ public static void assertDisabled(String stdout) { assertThat(stdout, matchesPattern(logPattern("com.navercorp.scavenger.javaagent.ScavengerAgent", "[scavenger] scavenger is disabled"))); } + public static void assertScanned(String stdout, Method method) { + assertThat(stdout, matchesPattern(scanPattern(method))); + } + + public static void assertNotScanned(String stdout, Method method) { + assertThat(stdout, not(matchesPattern(scanPattern(method)))); + } + + public static void assertInvoked(String stdout, Method method) { + assertThat(stdout, matchesPattern(invokedPattern(method))); + } + + public static void assertNotInvoked(String stdout, Method method) { + assertThat(stdout, not(matchesPattern(invokedPattern(method)))); + } + private static Pattern logPattern(String location, String text) { return Pattern.compile("[\\s\\S]*(INFO|WARNING).*" + Pattern.quote(location) + ".*" + Pattern.quote(text) + "[\\s\\S]*"); } + + private static Pattern scanPattern(Method method) { + String[] split = method.toString().split(" "); + String signature = split[split.length - 1]; + return logPattern("com.navercorp.scavenger.javaagent.collecting.CodeBaseScanner", "[scavenger] " + signature + " is scanned"); + } + + private static Pattern invokedPattern(Method method) { + String signature = method.toString(); + return logPattern("com.navercorp.scavenger.javaagent.collecting.InvocationTracker", "[scavenger] method " + signature + " is invoked"); + } } From 0003c0719e4bb1fe498393e3859164f600290368 Mon Sep 17 00:00:00 2001 From: Ohjun Kwon Date: Tue, 30 May 2023 21:38:58 +0900 Subject: [PATCH 04/30] Assign http port dynamically --- .../java/integrationTest/javaagent/InvocationTest.java | 4 +++- .../java/integrationTest/javaagent/ScanTest.java | 6 +++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/scavenger-agent-java/src/integrationTest/java/integrationTest/javaagent/InvocationTest.java b/scavenger-agent-java/src/integrationTest/java/integrationTest/javaagent/InvocationTest.java index 28690682..436673ac 100644 --- a/scavenger-agent-java/src/integrationTest/java/integrationTest/javaagent/InvocationTest.java +++ b/scavenger-agent-java/src/integrationTest/java/integrationTest/javaagent/InvocationTest.java @@ -29,6 +29,7 @@ import com.github.tomakehurst.wiremock.WireMockServer; import com.github.tomakehurst.wiremock.client.WireMock; +import com.github.tomakehurst.wiremock.core.WireMockConfiguration; import com.google.protobuf.util.JsonFormat; import integrationTest.support.AgentIntegrationTestContextProvider; import integrationTest.support.AgentRunner; @@ -53,7 +54,7 @@ public class InvocationTest { @BeforeAll static void setUp() { - wireMockServer = new WireMockServer(); + wireMockServer = new WireMockServer(new WireMockConfiguration().dynamicPort()); wireMockServer.start(); WireMock.configureFor(wireMockServer.port()); @@ -87,6 +88,7 @@ void track(AgentRunner agentRunner) throws Exception { void send(AgentRunner agentRunner) throws Exception { // given Properties properties = new Properties(); + properties.setProperty("serverUrl", "http://localhost:" + wireMockServer.port()); properties.setProperty("schedulerInitialDelayMillis", "0"); agentRunner.setConfig(properties); diff --git a/scavenger-agent-java/src/integrationTest/java/integrationTest/javaagent/ScanTest.java b/scavenger-agent-java/src/integrationTest/java/integrationTest/javaagent/ScanTest.java index 3c5b235c..f494599d 100644 --- a/scavenger-agent-java/src/integrationTest/java/integrationTest/javaagent/ScanTest.java +++ b/scavenger-agent-java/src/integrationTest/java/integrationTest/javaagent/ScanTest.java @@ -29,13 +29,13 @@ import com.github.tomakehurst.wiremock.WireMockServer; import com.github.tomakehurst.wiremock.client.WireMock; +import com.github.tomakehurst.wiremock.core.WireMockConfiguration; import com.google.protobuf.util.JsonFormat; import integrationTest.support.AgentIntegrationTestContextProvider; import integrationTest.support.AgentRunner; import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; import sample.app.NotServiceClass; -import sample.app.SampleApp; import sample.app.SampleService1; import sample.app.excluded.NotTrackedClass; import sample.app.excluded.NotTrackedClass2; @@ -54,7 +54,7 @@ public class ScanTest { @BeforeAll static void setUp() { - wireMockServer = new WireMockServer(); + wireMockServer = new WireMockServer(new WireMockConfiguration().dynamicPort()); wireMockServer.start(); WireMock.configureFor(wireMockServer.port()); @@ -79,7 +79,6 @@ void scan(AgentRunner agentRunner) throws Exception { assertSampleAppOutput(stdout); assertScanned(stdout, SampleService1.class.getMethod("doSomething", int.class)); assertScanned(stdout, NotServiceClass.class.getMethod("doSomething", int.class)); - assertScanned(stdout, SampleApp.class.getMethod("main", String[].class)); assertNotScanned(stdout, NotTrackedClass.class.getMethod("doSomething")); assertNotScanned(stdout, NotTrackedClass2.class.getMethod("doSomething")); } @@ -90,6 +89,7 @@ void send(AgentRunner agentRunner) throws Exception { // given Properties properties = new Properties(); properties.setProperty("schedulerInitialDelayMillis", "0"); + properties.setProperty("serverUrl", "http://localhost:" + wireMockServer.port()); agentRunner.setConfig(properties); givenThat( From 4be7fbe05062a6a6bff071fe538704ae7f4ee987 Mon Sep 17 00:00:00 2001 From: Ohjun Kwon Date: Mon, 5 Jun 2023 02:59:19 +0900 Subject: [PATCH 05/30] Change variable name: stdout to actual --- .../integrationTest/javaagent/ConfigTest.java | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/scavenger-agent-java/src/integrationTest/java/integrationTest/javaagent/ConfigTest.java b/scavenger-agent-java/src/integrationTest/java/integrationTest/javaagent/ConfigTest.java index 0a9c8fdf..bfcf72ac 100644 --- a/scavenger-agent-java/src/integrationTest/java/integrationTest/javaagent/ConfigTest.java +++ b/scavenger-agent-java/src/integrationTest/java/integrationTest/javaagent/ConfigTest.java @@ -25,12 +25,12 @@ void noConfig(AgentRunner agentRunner) throws Exception { agentRunner.setConfigFilePath(""); // when - String stdout = agentRunner.call(); + String actual = agentRunner.call(); // then - assertThat(stdout, containsString("Configuration file is not found")); - assertDisabled(stdout); - assertSampleAppOutput(stdout); + assertThat(actual, containsString("Configuration file is not found")); + assertDisabled(actual); + assertSampleAppOutput(actual); } @TestTemplate @@ -40,12 +40,12 @@ void nonExistentConfig(AgentRunner agentRunner) throws Exception { agentRunner.setConfigFilePath("foobar"); // when - String stdout = agentRunner.call(); + String actual = agentRunner.call(); // then - assertThat(stdout, containsString("Specified configuration file is not found")); - assertDisabled(stdout); - assertSampleAppOutput(stdout); + assertThat(actual, containsString("Specified configuration file is not found")); + assertDisabled(actual); + assertSampleAppOutput(actual); } @TestTemplate @@ -57,11 +57,11 @@ void missingRequiredTest(AgentRunner agentRunner) throws Exception { agentRunner.setConfig(properties); // when - String stdout = agentRunner.call(); + String actual = agentRunner.call(); // then - assertThat(stdout, containsString("mandatory property 'packages' is missing")); - assertDisabled(stdout); - assertSampleAppOutput(stdout); + assertThat(actual, containsString("mandatory property 'packages' is missing")); + assertDisabled(actual); + assertSampleAppOutput(actual); } } From 08d3010fbf4dcd732fc8c68e73fd18de3d4d9209 Mon Sep 17 00:00:00 2001 From: Ohjun Kwon Date: Mon, 5 Jun 2023 04:38:05 +0900 Subject: [PATCH 06/30] Use assertj instead of hamcrest --- .../integrationTest/javaagent/ConfigTest.java | 9 ++--- .../AgentIntegrationTestContextProvider.java | 8 ++-- .../util/AgentLogAssertionUtil.java | 38 +++++++++---------- 3 files changed, 26 insertions(+), 29 deletions(-) diff --git a/scavenger-agent-java/src/integrationTest/java/integrationTest/javaagent/ConfigTest.java b/scavenger-agent-java/src/integrationTest/java/integrationTest/javaagent/ConfigTest.java index bfcf72ac..bc2c8a8c 100644 --- a/scavenger-agent-java/src/integrationTest/java/integrationTest/javaagent/ConfigTest.java +++ b/scavenger-agent-java/src/integrationTest/java/integrationTest/javaagent/ConfigTest.java @@ -2,8 +2,7 @@ import static integrationTest.util.AgentLogAssertionUtil.assertDisabled; import static integrationTest.util.AgentLogAssertionUtil.assertSampleAppOutput; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.containsString; +import static org.assertj.core.api.Assertions.assertThat; import java.util.Properties; @@ -28,7 +27,7 @@ void noConfig(AgentRunner agentRunner) throws Exception { String actual = agentRunner.call(); // then - assertThat(actual, containsString("Configuration file is not found")); + assertThat(actual).contains("Configuration file is not found"); assertDisabled(actual); assertSampleAppOutput(actual); } @@ -43,7 +42,7 @@ void nonExistentConfig(AgentRunner agentRunner) throws Exception { String actual = agentRunner.call(); // then - assertThat(actual, containsString("Specified configuration file is not found")); + assertThat(actual).contains("Specified configuration file is not found"); assertDisabled(actual); assertSampleAppOutput(actual); } @@ -60,7 +59,7 @@ void missingRequiredTest(AgentRunner agentRunner) throws Exception { String actual = agentRunner.call(); // then - assertThat(actual, containsString("mandatory property 'packages' is missing")); + assertThat(actual).contains("mandatory property 'packages' is missing"); assertDisabled(actual); assertSampleAppOutput(actual); } diff --git a/scavenger-agent-java/src/integrationTest/java/integrationTest/support/AgentIntegrationTestContextProvider.java b/scavenger-agent-java/src/integrationTest/java/integrationTest/support/AgentIntegrationTestContextProvider.java index cd9ff2c2..fb8a706c 100644 --- a/scavenger-agent-java/src/integrationTest/java/integrationTest/support/AgentIntegrationTestContextProvider.java +++ b/scavenger-agent-java/src/integrationTest/java/integrationTest/support/AgentIntegrationTestContextProvider.java @@ -1,6 +1,6 @@ package integrationTest.support; -import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.assertj.core.api.Assertions.assertThat; import java.util.Arrays; import java.util.Collections; @@ -22,9 +22,9 @@ public class AgentIntegrationTestContextProvider implements TestTemplateInvocati @Override public boolean supportsTestTemplate(ExtensionContext context) { - assertNotNull(scavengerAgentPath, "This test must be started from Gradle"); - assertNotNull(classpath, "This test must be started from Gradle"); - assertNotNull(javaPaths, "This test must be started from Gradle"); + assertThat(scavengerAgentPath).as("This test must be started from Gradle").isNotNull(); + assertThat(classpath).as("This test must be started from Gradle").isNotNull(); + assertThat(javaPaths).as("This test must be started from Gradle").isNotNull(); return true; } diff --git a/scavenger-agent-java/src/integrationTest/java/integrationTest/util/AgentLogAssertionUtil.java b/scavenger-agent-java/src/integrationTest/java/integrationTest/util/AgentLogAssertionUtil.java index 63421654..705cc040 100644 --- a/scavenger-agent-java/src/integrationTest/java/integrationTest/util/AgentLogAssertionUtil.java +++ b/scavenger-agent-java/src/integrationTest/java/integrationTest/util/AgentLogAssertionUtil.java @@ -1,46 +1,44 @@ package integrationTest.util; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.matchesPattern; -import static org.hamcrest.Matchers.not; +import static org.assertj.core.api.Assertions.assertThat; import java.lang.reflect.Method; import java.util.regex.Pattern; public class AgentLogAssertionUtil { public static void assertSampleAppOutput(String stdout) { - assertThat(stdout, matchesPattern(logPattern("sample.app.SampleApp", "SampleApp starts"))); - assertThat(stdout, matchesPattern(logPattern("sample.app.SampleApp", "2+2=4"))); - assertThat(stdout, - matchesPattern(logPattern("sample.app.SampleAspect", "Before execution(void sample.app.SampleService1.doSomething(int))"))); - assertThat(stdout, matchesPattern(logPattern("sample.app.SampleService1", "Doing something 1"))); - assertThat(stdout, - matchesPattern(logPattern("sample.app.SampleAspect", "Before execution(void sample.app.SampleService2.doSomething(int))"))); - assertThat(stdout, matchesPattern(logPattern("sample.app.SampleService2", "Doing something 2"))); - assertThat(stdout, matchesPattern(logPattern("sample.app.NotServiceClass", "Doing something 4"))); - assertThat(stdout, matchesPattern(logPattern("sample.app.SampleAspect", "After execution(void sample.app.SampleService2.doSomething(int))"))); - assertThat(stdout, matchesPattern(logPattern("sample.app.SampleAspect", "After execution(void sample.app.SampleService1.doSomething(int))"))); - assertThat(stdout, matchesPattern(logPattern("sample.app.SampleApp", "Exit"))); + assertThat(stdout) + .matches(logPattern("sample.app.SampleApp", "SampleApp starts")) + .matches(logPattern("sample.app.SampleApp", "2+2=4")) + .matches(logPattern("sample.app.SampleAspect", "Before execution(void sample.app.SampleService1.doSomething(int))")) + .matches(logPattern("sample.app.SampleService1", "Doing something 1")) + .matches(logPattern("sample.app.SampleAspect", "Before execution(void sample.app.SampleService2.doSomething(int))")) + .matches(logPattern("sample.app.SampleService2", "Doing something 2")) + .matches(logPattern("sample.app.NotServiceClass", "Doing something 4")) + .matches(logPattern("sample.app.SampleAspect", "After execution(void sample.app.SampleService2.doSomething(int))")) + .matches(logPattern("sample.app.SampleAspect", "After execution(void sample.app.SampleService1.doSomething(int))")) + .matches(logPattern("sample.app.SampleApp", "Exit")); } public static void assertDisabled(String stdout) { - assertThat(stdout, matchesPattern(logPattern("com.navercorp.scavenger.javaagent.ScavengerAgent", "[scavenger] scavenger is disabled"))); + assertThat(stdout) + .matches(logPattern("com.navercorp.scavenger.javaagent.ScavengerAgent", "[scavenger] scavenger is disabled")); } public static void assertScanned(String stdout, Method method) { - assertThat(stdout, matchesPattern(scanPattern(method))); + assertThat(stdout).matches(scanPattern(method)); } public static void assertNotScanned(String stdout, Method method) { - assertThat(stdout, not(matchesPattern(scanPattern(method)))); + assertThat(stdout).doesNotMatch(scanPattern(method)); } public static void assertInvoked(String stdout, Method method) { - assertThat(stdout, matchesPattern(invokedPattern(method))); + assertThat(stdout).matches(invokedPattern(method)); } public static void assertNotInvoked(String stdout, Method method) { - assertThat(stdout, not(matchesPattern(invokedPattern(method)))); + assertThat(stdout).doesNotMatch(invokedPattern(method)); } private static Pattern logPattern(String location, String text) { From 81f851082322f23c4f2d31cafaa411bddc58e8f7 Mon Sep 17 00:00:00 2001 From: Ohjun Kwon Date: Mon, 5 Jun 2023 04:47:49 +0900 Subject: [PATCH 07/30] Use streams --- .../java/integrationTest/support/AgentRunner.java | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/scavenger-agent-java/src/integrationTest/java/integrationTest/support/AgentRunner.java b/scavenger-agent-java/src/integrationTest/java/integrationTest/support/AgentRunner.java index 46e4b21d..ac87278a 100644 --- a/scavenger-agent-java/src/integrationTest/java/integrationTest/support/AgentRunner.java +++ b/scavenger-agent-java/src/integrationTest/java/integrationTest/support/AgentRunner.java @@ -72,14 +72,8 @@ private List buildCommand() { } private static String collectProcessOutput(InputStream inputStream) throws IOException { - StringBuilder sb = new StringBuilder(); - String line; - BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); - String newLine = ""; - while ((line = reader.readLine()) != null) { - sb.append(newLine).append(line); - newLine = String.format("%n"); + try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) { + return reader.lines().collect(Collectors.joining("\n")); } - return sb.toString(); } } From fe07c0fa0198503b576deb9b6af3a69701702650 Mon Sep 17 00:00:00 2001 From: Ohjun Kwon Date: Mon, 5 Jun 2023 04:54:12 +0900 Subject: [PATCH 08/30] Stop using String.format --- .../java/integrationTest/support/AgentRunner.java | 4 ++-- .../src/integrationTest/java/sample/app/SampleApp.java | 5 +---- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/scavenger-agent-java/src/integrationTest/java/integrationTest/support/AgentRunner.java b/scavenger-agent-java/src/integrationTest/java/integrationTest/support/AgentRunner.java index ac87278a..d4a374a3 100644 --- a/scavenger-agent-java/src/integrationTest/java/integrationTest/support/AgentRunner.java +++ b/scavenger-agent-java/src/integrationTest/java/integrationTest/support/AgentRunner.java @@ -41,7 +41,7 @@ public String call() throws IOException, InterruptedException, RuntimeException String output = collectProcessOutput(process.getInputStream()); int exitCode = process.waitFor(); if (exitCode != 0) { - throw new RuntimeException(String.format("Could not execute '%s': %s%nExit code=%d", command, output, exitCode)); + throw new RuntimeException("Could not execute '" + command + "': " + output + "\nExit code=" + exitCode); } return output; } @@ -67,7 +67,7 @@ private List buildCommand() { command.add("-Dscavenger.configuration=" + configFilePath); } command.add("sample.app.SampleApp"); - System.out.printf("%nLaunching SampleApp with the command: %s%n%n", command); + System.out.println("Launching SampleApp with the command: " + command); return command; } diff --git a/scavenger-agent-java/src/integrationTest/java/sample/app/SampleApp.java b/scavenger-agent-java/src/integrationTest/java/sample/app/SampleApp.java index 202890db..dd1f671c 100644 --- a/scavenger-agent-java/src/integrationTest/java/sample/app/SampleApp.java +++ b/scavenger-agent-java/src/integrationTest/java/sample/app/SampleApp.java @@ -24,10 +24,7 @@ public class SampleApp { private final SampleService1 sampleService1; public static void main(String[] args) throws InterruptedException { - log.info( - String.format( - "%s starts on Java %s", - SampleApp.class.getSimpleName(), System.getProperty("java.version"))); + log.info(SampleApp.class.getSimpleName() + " starts on Java " + System.getProperty("java.version")); SpringApplication.run(SampleApp.class, args); log.info("Exit"); } From 23f7752f4d86902ae2579a40bfd691c3cad3b8ee Mon Sep 17 00:00:00 2001 From: Ohjun Kwon Date: Mon, 5 Jun 2023 05:04:54 +0900 Subject: [PATCH 09/30] Move methods to relating class --- .../integrationTest/javaagent/ConfigTest.java | 7 ++-- .../javaagent/InvocationTest.java | 19 +++++++--- .../integrationTest/javaagent/ScanTest.java | 20 +++++++--- .../util/AgentLogAssertionUtil.java | 37 +------------------ 4 files changed, 32 insertions(+), 51 deletions(-) diff --git a/scavenger-agent-java/src/integrationTest/java/integrationTest/javaagent/ConfigTest.java b/scavenger-agent-java/src/integrationTest/java/integrationTest/javaagent/ConfigTest.java index bc2c8a8c..48fe47d1 100644 --- a/scavenger-agent-java/src/integrationTest/java/integrationTest/javaagent/ConfigTest.java +++ b/scavenger-agent-java/src/integrationTest/java/integrationTest/javaagent/ConfigTest.java @@ -1,6 +1,5 @@ package integrationTest.javaagent; -import static integrationTest.util.AgentLogAssertionUtil.assertDisabled; import static integrationTest.util.AgentLogAssertionUtil.assertSampleAppOutput; import static org.assertj.core.api.Assertions.assertThat; @@ -28,7 +27,7 @@ void noConfig(AgentRunner agentRunner) throws Exception { // then assertThat(actual).contains("Configuration file is not found"); - assertDisabled(actual); + assertThat(actual).contains("scavenger is disabled"); assertSampleAppOutput(actual); } @@ -43,7 +42,7 @@ void nonExistentConfig(AgentRunner agentRunner) throws Exception { // then assertThat(actual).contains("Specified configuration file is not found"); - assertDisabled(actual); + assertThat(actual).contains("scavenger is disabled"); assertSampleAppOutput(actual); } @@ -60,7 +59,7 @@ void missingRequiredTest(AgentRunner agentRunner) throws Exception { // then assertThat(actual).contains("mandatory property 'packages' is missing"); - assertDisabled(actual); + assertThat(actual).contains("scavenger is disabled"); assertSampleAppOutput(actual); } } diff --git a/scavenger-agent-java/src/integrationTest/java/integrationTest/javaagent/InvocationTest.java b/scavenger-agent-java/src/integrationTest/java/integrationTest/javaagent/InvocationTest.java index 436673ac..0f16524e 100644 --- a/scavenger-agent-java/src/integrationTest/java/integrationTest/javaagent/InvocationTest.java +++ b/scavenger-agent-java/src/integrationTest/java/integrationTest/javaagent/InvocationTest.java @@ -4,9 +4,8 @@ import static com.github.tomakehurst.wiremock.client.WireMock.givenThat; import static com.github.tomakehurst.wiremock.client.WireMock.okJson; import static com.navercorp.scavenger.model.Endpoints.Agent.V5_INIT_CONFIG; -import static integrationTest.util.AgentLogAssertionUtil.assertInvoked; -import static integrationTest.util.AgentLogAssertionUtil.assertNotInvoked; import static integrationTest.util.AgentLogAssertionUtil.assertSampleAppOutput; +import static org.assertj.core.api.Assertions.assertThat; import static org.grpcmock.GrpcMock.calledMethod; import static org.grpcmock.GrpcMock.getGlobalPort; import static org.grpcmock.GrpcMock.stubFor; @@ -14,6 +13,7 @@ import static org.grpcmock.GrpcMock.verifyThat; import static org.junit.jupiter.api.Assertions.assertTrue; +import java.lang.reflect.Method; import java.util.Optional; import java.util.Properties; import java.util.regex.Matcher; @@ -33,6 +33,7 @@ import com.google.protobuf.util.JsonFormat; import integrationTest.support.AgentIntegrationTestContextProvider; import integrationTest.support.AgentRunner; +import integrationTest.util.AgentLogAssertionUtil; import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; import sample.app.SampleApp; @@ -77,10 +78,10 @@ void track(AgentRunner agentRunner) throws Exception { // then assertSampleAppOutput(stdout); - assertInvoked(stdout, SampleApp.class.getMethod("add", int.class, int.class)); - assertInvoked(stdout, SampleAspect.class.getMethod("logAspectLoaded")); - assertInvoked(stdout, SampleService1.class.getMethod("doSomething", int.class)); - assertNotInvoked(stdout, NotTrackedClass.class.getMethod("doSomething")); + assertThat(stdout).matches(invoked(SampleApp.class.getMethod("add", int.class, int.class))); + assertThat(stdout).matches(invoked(SampleAspect.class.getMethod("logAspectLoaded"))); + assertThat(stdout).matches(invoked(SampleService1.class.getMethod("doSomething", int.class))); + assertThat(stdout).doesNotMatch(invoked(NotTrackedClass.class.getMethod("doSomething"))); } @TestTemplate @@ -132,6 +133,12 @@ void send(AgentRunner agentRunner) throws Exception { .withRequest(pub -> pub.getEntryCount() == getInvocationsCount(stdout))); } + private static Pattern invoked(Method method) { + String signature = method.toString(); + return AgentLogAssertionUtil.logPattern("com.navercorp.scavenger.javaagent.collecting.InvocationTracker", + "[scavenger] method " + signature + " is invoked"); + } + private static int getInvocationsCount(String stdout) { Matcher matcher = Pattern.compile("\\[scavenger] publishing invocation data: (\\d*) invocations").matcher(stdout); assertTrue(matcher.find()); diff --git a/scavenger-agent-java/src/integrationTest/java/integrationTest/javaagent/ScanTest.java b/scavenger-agent-java/src/integrationTest/java/integrationTest/javaagent/ScanTest.java index f494599d..793f1be1 100644 --- a/scavenger-agent-java/src/integrationTest/java/integrationTest/javaagent/ScanTest.java +++ b/scavenger-agent-java/src/integrationTest/java/integrationTest/javaagent/ScanTest.java @@ -4,9 +4,8 @@ import static com.github.tomakehurst.wiremock.client.WireMock.givenThat; import static com.github.tomakehurst.wiremock.client.WireMock.okJson; import static com.navercorp.scavenger.model.Endpoints.Agent.V5_INIT_CONFIG; -import static integrationTest.util.AgentLogAssertionUtil.assertNotScanned; import static integrationTest.util.AgentLogAssertionUtil.assertSampleAppOutput; -import static integrationTest.util.AgentLogAssertionUtil.assertScanned; +import static org.assertj.core.api.Assertions.assertThat; import static org.grpcmock.GrpcMock.calledMethod; import static org.grpcmock.GrpcMock.getGlobalPort; import static org.grpcmock.GrpcMock.stubFor; @@ -14,6 +13,7 @@ import static org.grpcmock.GrpcMock.verifyThat; import static org.junit.jupiter.api.Assertions.assertTrue; +import java.lang.reflect.Method; import java.util.Optional; import java.util.Properties; import java.util.regex.Matcher; @@ -33,6 +33,7 @@ import com.google.protobuf.util.JsonFormat; import integrationTest.support.AgentIntegrationTestContextProvider; import integrationTest.support.AgentRunner; +import integrationTest.util.AgentLogAssertionUtil; import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; import sample.app.NotServiceClass; @@ -77,10 +78,10 @@ void scan(AgentRunner agentRunner) throws Exception { // then assertSampleAppOutput(stdout); - assertScanned(stdout, SampleService1.class.getMethod("doSomething", int.class)); - assertScanned(stdout, NotServiceClass.class.getMethod("doSomething", int.class)); - assertNotScanned(stdout, NotTrackedClass.class.getMethod("doSomething")); - assertNotScanned(stdout, NotTrackedClass2.class.getMethod("doSomething")); + assertThat(stdout).matches(scanned(SampleService1.class.getMethod("doSomething", int.class))); + assertThat(stdout).matches(scanned(NotServiceClass.class.getMethod("doSomething", int.class))); + assertThat(stdout).doesNotMatch(scanned(NotTrackedClass.class.getMethod("doSomething"))); + assertThat(stdout).doesNotMatch(scanned(NotTrackedClass2.class.getMethod("doSomething"))); } @TestTemplate @@ -127,6 +128,13 @@ void send(AgentRunner agentRunner) throws Exception { .withRequest(pub -> pub.getEntryCount() == getMethodsCount(stdout))); } + private static Pattern scanned(Method method) { + String[] split = method.toString().split(" "); + String signature = split[split.length - 1]; + return AgentLogAssertionUtil.logPattern("com.navercorp.scavenger.javaagent.collecting.CodeBaseScanner", + "[scavenger] " + signature + " is scanned"); + } + private static int getMethodsCount(String stdout) { Matcher matcher = Pattern.compile("\\[scavenger] codebase\\(.*\\) scanned in \\d* ms: (\\d*) methods").matcher(stdout); assertTrue(matcher.find()); diff --git a/scavenger-agent-java/src/integrationTest/java/integrationTest/util/AgentLogAssertionUtil.java b/scavenger-agent-java/src/integrationTest/java/integrationTest/util/AgentLogAssertionUtil.java index 705cc040..326a6869 100644 --- a/scavenger-agent-java/src/integrationTest/java/integrationTest/util/AgentLogAssertionUtil.java +++ b/scavenger-agent-java/src/integrationTest/java/integrationTest/util/AgentLogAssertionUtil.java @@ -2,7 +2,6 @@ import static org.assertj.core.api.Assertions.assertThat; -import java.lang.reflect.Method; import java.util.regex.Pattern; public class AgentLogAssertionUtil { @@ -20,39 +19,7 @@ public static void assertSampleAppOutput(String stdout) { .matches(logPattern("sample.app.SampleApp", "Exit")); } - public static void assertDisabled(String stdout) { - assertThat(stdout) - .matches(logPattern("com.navercorp.scavenger.javaagent.ScavengerAgent", "[scavenger] scavenger is disabled")); - } - - public static void assertScanned(String stdout, Method method) { - assertThat(stdout).matches(scanPattern(method)); - } - - public static void assertNotScanned(String stdout, Method method) { - assertThat(stdout).doesNotMatch(scanPattern(method)); - } - - public static void assertInvoked(String stdout, Method method) { - assertThat(stdout).matches(invokedPattern(method)); - } - - public static void assertNotInvoked(String stdout, Method method) { - assertThat(stdout).doesNotMatch(invokedPattern(method)); - } - - private static Pattern logPattern(String location, String text) { - return Pattern.compile("[\\s\\S]*(INFO|WARNING).*" + Pattern.quote(location) + ".*" + Pattern.quote(text) + "[\\s\\S]*"); - } - - private static Pattern scanPattern(Method method) { - String[] split = method.toString().split(" "); - String signature = split[split.length - 1]; - return logPattern("com.navercorp.scavenger.javaagent.collecting.CodeBaseScanner", "[scavenger] " + signature + " is scanned"); - } - - private static Pattern invokedPattern(Method method) { - String signature = method.toString(); - return logPattern("com.navercorp.scavenger.javaagent.collecting.InvocationTracker", "[scavenger] method " + signature + " is invoked"); + public static Pattern logPattern(String location, String text) { + return Pattern.compile("[\\s\\S]*(INFO).*" + Pattern.quote(location) + ".*" + Pattern.quote(text) + "[\\s\\S]*"); } } From e42798c2c90a6fe392a79f72530a48955be56371 Mon Sep 17 00:00:00 2001 From: Ohjun Kwon Date: Mon, 5 Jun 2023 14:10:36 +0900 Subject: [PATCH 10/30] Make tasks.check depends on integrationTest --- scavenger-agent-java/build.gradle.kts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/scavenger-agent-java/build.gradle.kts b/scavenger-agent-java/build.gradle.kts index 8c18fa16..8b5d1c29 100644 --- a/scavenger-agent-java/build.gradle.kts +++ b/scavenger-agent-java/build.gradle.kts @@ -43,6 +43,10 @@ tasks.build { dependsOn(tasks.shadowJar) } +tasks.check { + dependsOn(tasks.named("integrationTest")) +} + tasks.test { useJUnitPlatform() dependsOn(":scavenger-demo:build") From 1f7e8ef78e6591769eeba2ab11c71881f21d9b25 Mon Sep 17 00:00:00 2001 From: Ohjun Kwon Date: Mon, 5 Jun 2023 14:37:17 +0900 Subject: [PATCH 11/30] Reorder gradle tasks --- scavenger-agent-java/build.gradle.kts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/scavenger-agent-java/build.gradle.kts b/scavenger-agent-java/build.gradle.kts index 8b5d1c29..7c77107a 100644 --- a/scavenger-agent-java/build.gradle.kts +++ b/scavenger-agent-java/build.gradle.kts @@ -15,6 +15,8 @@ java { withSourcesJar() } +tasks.jar { enabled = false } + tasks.withType { archiveFileName.set("${project.name}-${project.version}.jar") @@ -39,12 +41,12 @@ tasks.register("relocateShadowJar") { prefix = "sc" } -tasks.build { +tasks.assemble { dependsOn(tasks.shadowJar) } tasks.check { - dependsOn(tasks.named("integrationTest")) + dependsOn("integrationTest") } tasks.test { From 113547bc86142bc0f78bee8a4d3ec46a511c45a6 Mon Sep 17 00:00:00 2001 From: 1004647 Date: Fri, 30 Jun 2023 14:14:48 +0900 Subject: [PATCH 12/30] sweep jvms without agent --- .../navercorp/scavenger/repository/JvmDao.kt | 7 +++ .../scavenger/repository/sql/JvmSql.kt | 13 ++++ .../service/GarbageCollectService.kt | 10 ++++ .../scavenger/repository/JvmDaoTest.kt | 21 +++++++ .../service/GarbageCollectServiceTest.kt | 59 +++++++++++++++++++ 5 files changed, 110 insertions(+) diff --git a/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/repository/JvmDao.kt b/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/repository/JvmDao.kt index 1bd4dc2d..a1a3290c 100644 --- a/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/repository/JvmDao.kt +++ b/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/repository/JvmDao.kt @@ -51,4 +51,11 @@ class JvmDao( .addValue("uuids", uuids) ) } + + fun deleteAllByWithoutAgent(): Int { + return update( + sql.deleteAllByWithoutAgent(), + mapParameterSource() + ) + } } diff --git a/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/repository/sql/JvmSql.kt b/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/repository/sql/JvmSql.kt index fce9fa3f..87d8076b 100644 --- a/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/repository/sql/JvmSql.kt +++ b/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/repository/sql/JvmSql.kt @@ -55,4 +55,17 @@ class JvmSql : SqlGeneratorSupport() { customerId = :customerId AND uuid IN ( :uuids ) """.trimIndent() + + fun deleteAllByWithoutAgent(): String = + """ + DELETE FROM + jvms + WHERE + uuid NOT IN ( + SELECT + jvmUuid + FROM + agent_state + ) + """.trimIndent() } diff --git a/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/service/GarbageCollectService.kt b/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/service/GarbageCollectService.kt index 7d23a797..a71c4eba 100644 --- a/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/service/GarbageCollectService.kt +++ b/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/service/GarbageCollectService.kt @@ -70,6 +70,8 @@ class GarbageCollectService( } logger.info { "[$it] hourly batch took $millis ms" } } + + sweepJvmsWithoutAgent() } /** @@ -91,6 +93,14 @@ class GarbageCollectService( } } + fun sweepJvmsWithoutAgent() { + try { + jvmDao.deleteAllByWithoutAgent() + } catch (e: Exception) { + logger.warn(e) { "error occurred while sweepJvmsWithoutAgent, but ignored. " } + } + } + /** * Remove all agent states which is not active for last expected polling time plus margin */ diff --git a/scavenger-collector/src/test/kotlin/com/navercorp/scavenger/repository/JvmDaoTest.kt b/scavenger-collector/src/test/kotlin/com/navercorp/scavenger/repository/JvmDaoTest.kt index a79c1a82..e8789a6d 100644 --- a/scavenger-collector/src/test/kotlin/com/navercorp/scavenger/repository/JvmDaoTest.kt +++ b/scavenger-collector/src/test/kotlin/com/navercorp/scavenger/repository/JvmDaoTest.kt @@ -6,6 +6,7 @@ import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.test.context.SpringBootTest +import org.springframework.test.context.ActiveProfiles import org.springframework.transaction.annotation.Transactional import java.time.Instant @@ -34,6 +35,20 @@ class JvmDaoTest { hostname = "AL01978856.local", ) + val paramWithoutAgent = JvmUpsertParam( + customerId = 3, + applicationId = applicationId, + applicationVersion = "unspecified", + environmentId = environmentId, + uuid = "9ec4624c-5b81-44fa-82c8-74233095b120", + codeBaseFingerprint = "CodeBaseFingerprint(numClassFiles=0, numJarFiles=1, " + + "sha256=b90e15678202f78cee45fa05cef8cba7c070114e37e81ff9131858c1d9c488c7)", + publishedAt = instant, + createdAt = instant, + hostname = "AL01978856.local", + ) + + sut.upsert(param) sut.upsert(param) } @@ -68,4 +83,10 @@ class JvmDaoTest { sut.deleteGarbagePublishedBefore(2, Instant.now()) assertThat(sut.findByCustomerIdAndUuid(2, "d0dfa3c2-809c-428f-b501-7419196d91c5")).isNull() } + + @Test + fun deleteAllByWithoutAgent() { + sut.deleteAllByWithoutAgent() + assertThat(sut.findByCustomerIdAndUuid(3, "9ec4624c-5b81-44fa-82c8-74233095b120")).isNull() + } } diff --git a/scavenger-collector/src/test/kotlin/com/navercorp/scavenger/service/GarbageCollectServiceTest.kt b/scavenger-collector/src/test/kotlin/com/navercorp/scavenger/service/GarbageCollectServiceTest.kt index fb9a9878..02986b3f 100644 --- a/scavenger-collector/src/test/kotlin/com/navercorp/scavenger/service/GarbageCollectServiceTest.kt +++ b/scavenger-collector/src/test/kotlin/com/navercorp/scavenger/service/GarbageCollectServiceTest.kt @@ -243,4 +243,63 @@ class GarbageCollectServiceTest { .hasSize(3) } } + + @Nested + @DisplayName("if without agent state exists") + inner class WithoutAgentJvms() { + val now = Instant.now() + val ago = now.minus(600 + IntervalService.Companion.GC_DEAD_MARGIN_MINUTES * 60, ChronoUnit.SECONDS) + + @BeforeEach + fun beforeEach() { + // Clean up first + jvmDao.findAllByCustomerId(customerId).forEach { + jvmDao.deleteById(it.id) + } + + jvmDao.insert( + JvmEntity( + customerId = customerId, + applicationId = 1, + environmentId = 1, + uuid = "uuid", + codeBaseFingerprint = null, + createdAt = ago, + publishedAt = ago, + hostname = "hostname", + ) + ) + + jvmDao.insert( + JvmEntity( + customerId = customerId, + applicationId = 1, + environmentId = 1, + uuid = "withoutUUID", + codeBaseFingerprint = null, + createdAt = ago, + publishedAt = ago, + hostname = "hostname", + ) + ) + + agentStateDao.insert( + AgentStateEntity( + customerId = customerId, + jvmUuid = "uuid", + createdAt = ago, + lastPolledAt = ago, + nextPollExpectedAt = ago.plusSeconds(60), + timestamp = ago, + enabled = true, + ) + ) + } + + @Test + fun sweepAgentStatesAndJvms() { + sut.sweepJvmsWithoutAgent() + assertThat(jvmDao.findAllByCustomerId(customerId).size).isEqualTo(1) + } + } } From 5ab9f764f6160fdf1c7b2feceab5f7d71c41d948 Mon Sep 17 00:00:00 2001 From: 1004647 Date: Fri, 30 Jun 2023 14:40:12 +0900 Subject: [PATCH 13/30] Update JvmDaoTest.kt remove unused import --- .../test/kotlin/com/navercorp/scavenger/repository/JvmDaoTest.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/scavenger-collector/src/test/kotlin/com/navercorp/scavenger/repository/JvmDaoTest.kt b/scavenger-collector/src/test/kotlin/com/navercorp/scavenger/repository/JvmDaoTest.kt index e8789a6d..a6035add 100644 --- a/scavenger-collector/src/test/kotlin/com/navercorp/scavenger/repository/JvmDaoTest.kt +++ b/scavenger-collector/src/test/kotlin/com/navercorp/scavenger/repository/JvmDaoTest.kt @@ -6,7 +6,6 @@ import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.test.context.SpringBootTest -import org.springframework.test.context.ActiveProfiles import org.springframework.transaction.annotation.Transactional import java.time.Instant From 59146af24139bdb331c00580bd1f8a92368a6644 Mon Sep 17 00:00:00 2001 From: 1004647 Date: Fri, 30 Jun 2023 14:45:28 +0900 Subject: [PATCH 14/30] Update JvmDaoTest.kt --- .../kotlin/com/navercorp/scavenger/repository/JvmDaoTest.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scavenger-collector/src/test/kotlin/com/navercorp/scavenger/repository/JvmDaoTest.kt b/scavenger-collector/src/test/kotlin/com/navercorp/scavenger/repository/JvmDaoTest.kt index a6035add..0ebbc409 100644 --- a/scavenger-collector/src/test/kotlin/com/navercorp/scavenger/repository/JvmDaoTest.kt +++ b/scavenger-collector/src/test/kotlin/com/navercorp/scavenger/repository/JvmDaoTest.kt @@ -48,7 +48,7 @@ class JvmDaoTest { ) sut.upsert(param) - sut.upsert(param) + sut.upsert(paramWithoutAgent) } @Test From d389f90d41e81859ea374cd5f9c2116ba58b7194 Mon Sep 17 00:00:00 2001 From: 1004647 Date: Mon, 3 Jul 2023 09:34:52 +0900 Subject: [PATCH 15/30] Change logic for sweeping JVMs without agents --- .../com/navercorp/scavenger/repository/JvmDao.kt | 9 +++++++++ .../navercorp/scavenger/repository/sql/JvmSql.kt | 14 ++++++++++++++ .../scavenger/service/GarbageCollectService.kt | 13 ++----------- .../navercorp/scavenger/repository/JvmDaoTest.kt | 7 +++++++ .../scavenger/service/GarbageCollectServiceTest.kt | 6 +++--- 5 files changed, 35 insertions(+), 14 deletions(-) diff --git a/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/repository/JvmDao.kt b/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/repository/JvmDao.kt index a1a3290c..340756a0 100644 --- a/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/repository/JvmDao.kt +++ b/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/repository/JvmDao.kt @@ -58,4 +58,13 @@ class JvmDao( mapParameterSource() ) } + + fun findUuidsByWithoutAgent(customerId: Long): List { + return select( + sql.selectUuidsByWithoutAgent(), + mapParameterSource() + .addValue("customerId", customerId), + String::class.java + ) + } } diff --git a/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/repository/sql/JvmSql.kt b/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/repository/sql/JvmSql.kt index 87d8076b..e902ea02 100644 --- a/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/repository/sql/JvmSql.kt +++ b/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/repository/sql/JvmSql.kt @@ -68,4 +68,18 @@ class JvmSql : SqlGeneratorSupport() { agent_state ) """.trimIndent() + + fun selectUuidsByWithoutAgent(): String = + """ + SELECT uuid FROM + jvms + WHERE + customerId = :customerId + AND uuid NOT IN ( + SELECT + jvmUuid + FROM + agent_state + ) + """.trimIndent() } diff --git a/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/service/GarbageCollectService.kt b/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/service/GarbageCollectService.kt index a71c4eba..807d77a4 100644 --- a/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/service/GarbageCollectService.kt +++ b/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/service/GarbageCollectService.kt @@ -70,8 +70,6 @@ class GarbageCollectService( } logger.info { "[$it] hourly batch took $millis ms" } } - - sweepJvmsWithoutAgent() } /** @@ -93,14 +91,6 @@ class GarbageCollectService( } } - fun sweepJvmsWithoutAgent() { - try { - jvmDao.deleteAllByWithoutAgent() - } catch (e: Exception) { - logger.warn(e) { "error occurred while sweepJvmsWithoutAgent, but ignored. " } - } - } - /** * Remove all agent states which is not active for last expected polling time plus margin */ @@ -111,8 +101,9 @@ class GarbageCollectService( customerId, baseDateTime.minusMillis(intervalService.batchSweepMarginMilliSecond) ) + var jvmUuids = jvmDao.findUuidsByWithoutAgent(customerId) - jvmDao.deleteAllByCustomerIdAndUuids(customerId, agentStates.map { it.jvmUuid }) + jvmDao.deleteAllByCustomerIdAndUuids(customerId, agentStates.map { it.jvmUuid } + jvmUuids) .also { logger.info { "[$customerId] $it jvm is swiped. " } } agentStateDao.deleteAllByCustomerIdAndIds(customerId, agentStates.map { it.id }) .also { logger.info { "[$customerId] $it agent state is swiped. " } } diff --git a/scavenger-collector/src/test/kotlin/com/navercorp/scavenger/repository/JvmDaoTest.kt b/scavenger-collector/src/test/kotlin/com/navercorp/scavenger/repository/JvmDaoTest.kt index 0ebbc409..a843638e 100644 --- a/scavenger-collector/src/test/kotlin/com/navercorp/scavenger/repository/JvmDaoTest.kt +++ b/scavenger-collector/src/test/kotlin/com/navercorp/scavenger/repository/JvmDaoTest.kt @@ -83,6 +83,13 @@ class JvmDaoTest { assertThat(sut.findByCustomerIdAndUuid(2, "d0dfa3c2-809c-428f-b501-7419196d91c5")).isNull() } + @Test + fun selectUuidsByWithoutAgent() { + val jvmUuids = sut.findUuidsByWithoutAgent(3) + assertThat(jvmUuids).isNotEmpty + assertThat(jvmUuids).contains("9ec4624c-5b81-44fa-82c8-74233095b120") + } + @Test fun deleteAllByWithoutAgent() { sut.deleteAllByWithoutAgent() diff --git a/scavenger-collector/src/test/kotlin/com/navercorp/scavenger/service/GarbageCollectServiceTest.kt b/scavenger-collector/src/test/kotlin/com/navercorp/scavenger/service/GarbageCollectServiceTest.kt index 02986b3f..bb8c1ace 100644 --- a/scavenger-collector/src/test/kotlin/com/navercorp/scavenger/service/GarbageCollectServiceTest.kt +++ b/scavenger-collector/src/test/kotlin/com/navercorp/scavenger/service/GarbageCollectServiceTest.kt @@ -246,7 +246,7 @@ class GarbageCollectServiceTest { @Nested @DisplayName("if without agent state exists") - inner class WithoutAgentJvms() { + inner class WithoutAgentJvms { val now = Instant.now() val ago = now.minus(600 + IntervalService.Companion.GC_DEAD_MARGIN_MINUTES * 60, ChronoUnit.SECONDS) @@ -297,8 +297,8 @@ class GarbageCollectServiceTest { } @Test - fun sweepAgentStatesAndJvms() { - sut.sweepJvmsWithoutAgent() + fun sweepAgentStatesAndJvms_removeWithoutAgentJvms() { + sut.sweepAgentStatesAndJvms(customerId, now) assertThat(jvmDao.findAllByCustomerId(customerId).size).isEqualTo(1) } } From e24a230ef7bcab75041aa0b8cfe82a026564e9a1 Mon Sep 17 00:00:00 2001 From: 1004647 Date: Mon, 3 Jul 2023 09:37:53 +0900 Subject: [PATCH 16/30] Delete former method for JVMs without agents --- .../com/navercorp/scavenger/repository/JvmDao.kt | 7 ------- .../navercorp/scavenger/repository/sql/JvmSql.kt | 13 ------------- 2 files changed, 20 deletions(-) diff --git a/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/repository/JvmDao.kt b/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/repository/JvmDao.kt index 340756a0..6438f1f7 100644 --- a/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/repository/JvmDao.kt +++ b/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/repository/JvmDao.kt @@ -52,13 +52,6 @@ class JvmDao( ) } - fun deleteAllByWithoutAgent(): Int { - return update( - sql.deleteAllByWithoutAgent(), - mapParameterSource() - ) - } - fun findUuidsByWithoutAgent(customerId: Long): List { return select( sql.selectUuidsByWithoutAgent(), diff --git a/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/repository/sql/JvmSql.kt b/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/repository/sql/JvmSql.kt index e902ea02..a6d661a1 100644 --- a/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/repository/sql/JvmSql.kt +++ b/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/repository/sql/JvmSql.kt @@ -56,19 +56,6 @@ class JvmSql : SqlGeneratorSupport() { AND uuid IN ( :uuids ) """.trimIndent() - fun deleteAllByWithoutAgent(): String = - """ - DELETE FROM - jvms - WHERE - uuid NOT IN ( - SELECT - jvmUuid - FROM - agent_state - ) - """.trimIndent() - fun selectUuidsByWithoutAgent(): String = """ SELECT uuid FROM From ef5e0860120ac304b2ece1be799be71b21d78cdc Mon Sep 17 00:00:00 2001 From: 1004647 Date: Mon, 3 Jul 2023 13:03:32 +0900 Subject: [PATCH 17/30] Update JvmDaoTest.kt --- .../kotlin/com/navercorp/scavenger/repository/JvmDaoTest.kt | 6 ------ 1 file changed, 6 deletions(-) diff --git a/scavenger-collector/src/test/kotlin/com/navercorp/scavenger/repository/JvmDaoTest.kt b/scavenger-collector/src/test/kotlin/com/navercorp/scavenger/repository/JvmDaoTest.kt index a843638e..6d2c167f 100644 --- a/scavenger-collector/src/test/kotlin/com/navercorp/scavenger/repository/JvmDaoTest.kt +++ b/scavenger-collector/src/test/kotlin/com/navercorp/scavenger/repository/JvmDaoTest.kt @@ -89,10 +89,4 @@ class JvmDaoTest { assertThat(jvmUuids).isNotEmpty assertThat(jvmUuids).contains("9ec4624c-5b81-44fa-82c8-74233095b120") } - - @Test - fun deleteAllByWithoutAgent() { - sut.deleteAllByWithoutAgent() - assertThat(sut.findByCustomerIdAndUuid(3, "9ec4624c-5b81-44fa-82c8-74233095b120")).isNull() - } } From 992359e5aeef175c8d98b0090a73aca7ecbda025 Mon Sep 17 00:00:00 2001 From: taeyeon-kimm Date: Mon, 3 Jul 2023 16:13:00 +0900 Subject: [PATCH 18/30] Clean up code --- .../com/navercorp/scavenger/repository/AgentRepository.kt | 2 +- .../scavenger/repository/ApplicationRepository.kt | 2 +- .../scavenger/repository/EnvironmentRepository.kt | 2 +- .../scavenger/repository/GithubMappingRepository.kt | 2 +- .../scavenger/repository/MethodInvocationRepository.kt | 2 +- .../scavenger/repository/SnapshotApplicationRepository.kt | 4 ++-- .../scavenger/repository/SnapshotEnvironmentRepository.kt | 4 ++-- .../com/navercorp/scavenger/repository/SnapshotNodeDao.kt | 4 ++-- .../navercorp/scavenger/repository/SnapshotRepository.kt | 2 +- .../navercorp/scavenger/repository/sql/SnapshotNodeSql.kt | 2 +- .../com/navercorp/scavenger/service/AgentService.kt | 2 +- .../com/navercorp/scavenger/service/ApplicationService.kt | 6 +++--- .../com/navercorp/scavenger/service/CustomerService.kt | 2 +- .../com/navercorp/scavenger/service/EnvironmentService.kt | 6 +++--- .../navercorp/scavenger/service/GithubMappingService.kt | 2 +- .../navercorp/scavenger/service/SnapshotNodeService.kt | 2 +- .../com/navercorp/scavenger/service/SnapshotService.kt | 8 ++++---- .../navercorp/scavenger/repository/AgentRepositoryTest.kt | 4 ++-- .../scavenger/repository/ApplicationRepositoryTest.kt | 4 ++-- .../scavenger/repository/EnvironmentRepositoryTest.kt | 4 ++-- .../scavenger/repository/GithubMappingRepositoryTest.kt | 6 +++--- .../repository/MethodInvocationRepositoryTest.kt | 4 ++-- .../repository/SnapshotApplicationRepositoryTest.kt | 8 ++++---- .../repository/SnapshotEnvironmentRepositoryTest.kt | 8 ++++---- .../scavenger/repository/SnapshotNodeRepositoryTest.kt | 8 ++++---- .../scavenger/repository/SnapshotRepositoryTest.kt | 4 ++-- .../com/navercorp/scavenger/repository/AgentStateDao.kt | 4 ++-- .../navercorp/scavenger/repository/sql/AgentStateSql.kt | 2 +- .../navercorp/scavenger/service/GarbageCollectService.kt | 4 ++-- 29 files changed, 57 insertions(+), 57 deletions(-) diff --git a/scavenger-api/src/main/kotlin/com/navercorp/scavenger/repository/AgentRepository.kt b/scavenger-api/src/main/kotlin/com/navercorp/scavenger/repository/AgentRepository.kt index 70e8623f..4030965d 100644 --- a/scavenger-api/src/main/kotlin/com/navercorp/scavenger/repository/AgentRepository.kt +++ b/scavenger-api/src/main/kotlin/com/navercorp/scavenger/repository/AgentRepository.kt @@ -30,7 +30,7 @@ interface AgentRepository : DelegatableJdbcRepository { agent_state.customerId = :customerId """ ) - fun findAgentsByCustomerId(@Param("customerId") customerId: Long): List + fun findAllAgentsByCustomerId(@Param("customerId") customerId: Long): List @Modifying @Query("DELETE FROM agent_state WHERE customerId = :customerId") diff --git a/scavenger-api/src/main/kotlin/com/navercorp/scavenger/repository/ApplicationRepository.kt b/scavenger-api/src/main/kotlin/com/navercorp/scavenger/repository/ApplicationRepository.kt index 372ac086..d2406d79 100644 --- a/scavenger-api/src/main/kotlin/com/navercorp/scavenger/repository/ApplicationRepository.kt +++ b/scavenger-api/src/main/kotlin/com/navercorp/scavenger/repository/ApplicationRepository.kt @@ -9,7 +9,7 @@ import org.springframework.stereotype.Repository @Repository interface ApplicationRepository : DelegatableJdbcRepository { - fun findByCustomerId(customerId: Long): List + fun findAllByCustomerId(customerId: Long): List fun findByCustomerIdAndId(customerId: Long, id: Long): ApplicationEntity diff --git a/scavenger-api/src/main/kotlin/com/navercorp/scavenger/repository/EnvironmentRepository.kt b/scavenger-api/src/main/kotlin/com/navercorp/scavenger/repository/EnvironmentRepository.kt index f4db1488..d3d72c1d 100644 --- a/scavenger-api/src/main/kotlin/com/navercorp/scavenger/repository/EnvironmentRepository.kt +++ b/scavenger-api/src/main/kotlin/com/navercorp/scavenger/repository/EnvironmentRepository.kt @@ -9,7 +9,7 @@ import org.springframework.stereotype.Repository @Repository interface EnvironmentRepository : DelegatableJdbcRepository { - fun findByCustomerId(customerId: Long): List + fun findAllByCustomerId(customerId: Long): List fun findByCustomerIdAndId(customerId: Long, id: Long): EnvironmentEntity diff --git a/scavenger-api/src/main/kotlin/com/navercorp/scavenger/repository/GithubMappingRepository.kt b/scavenger-api/src/main/kotlin/com/navercorp/scavenger/repository/GithubMappingRepository.kt index a4655f21..32b167bc 100644 --- a/scavenger-api/src/main/kotlin/com/navercorp/scavenger/repository/GithubMappingRepository.kt +++ b/scavenger-api/src/main/kotlin/com/navercorp/scavenger/repository/GithubMappingRepository.kt @@ -9,7 +9,7 @@ import org.springframework.stereotype.Repository @Repository interface GithubMappingRepository : DelegatableJdbcRepository { - fun findByCustomerId(customerId: Long): List + fun findAllByCustomerId(customerId: Long): List @Modifying @Query("DELETE FROM github_mappings WHERE customerId = :customerId AND id = :id") diff --git a/scavenger-api/src/main/kotlin/com/navercorp/scavenger/repository/MethodInvocationRepository.kt b/scavenger-api/src/main/kotlin/com/navercorp/scavenger/repository/MethodInvocationRepository.kt index 35defcb0..b8f183ca 100644 --- a/scavenger-api/src/main/kotlin/com/navercorp/scavenger/repository/MethodInvocationRepository.kt +++ b/scavenger-api/src/main/kotlin/com/navercorp/scavenger/repository/MethodInvocationRepository.kt @@ -28,7 +28,7 @@ interface MethodInvocationRepository : DelegatableJdbcRepository, @Param("environmentIdList") environmentIdList: List diff --git a/scavenger-api/src/main/kotlin/com/navercorp/scavenger/repository/SnapshotApplicationRepository.kt b/scavenger-api/src/main/kotlin/com/navercorp/scavenger/repository/SnapshotApplicationRepository.kt index 0e47d812..c7482b5f 100644 --- a/scavenger-api/src/main/kotlin/com/navercorp/scavenger/repository/SnapshotApplicationRepository.kt +++ b/scavenger-api/src/main/kotlin/com/navercorp/scavenger/repository/SnapshotApplicationRepository.kt @@ -12,12 +12,12 @@ interface SnapshotApplicationRepository : DelegatableJdbcRepository + fun findAllByCustomerIdAndApplicationId(@Param("customerId") customerId: Long, @Param("applicationId") applicationId: Long): List @Modifying @Query("DELETE FROM snapshot_application WHERE customerId = :customerId AND snapshotId = :snapshotId") fun deleteByCustomerIdAndSnapshotId(customerId: Long, snapshotId: Long) @Query("SELECT snapshotId FROM snapshot_application WHERE customerId = :customerId AND snapshotId = :snapshotId") - fun findByCustomerIdAndSnapshotId(@Param("customerId") customerId: Long, @Param("snapshotId") snapshotId: Long): List + fun findAllByCustomerIdAndSnapshotId(@Param("customerId") customerId: Long, @Param("snapshotId") snapshotId: Long): List } diff --git a/scavenger-api/src/main/kotlin/com/navercorp/scavenger/repository/SnapshotEnvironmentRepository.kt b/scavenger-api/src/main/kotlin/com/navercorp/scavenger/repository/SnapshotEnvironmentRepository.kt index 357ad452..7d6b5bbf 100644 --- a/scavenger-api/src/main/kotlin/com/navercorp/scavenger/repository/SnapshotEnvironmentRepository.kt +++ b/scavenger-api/src/main/kotlin/com/navercorp/scavenger/repository/SnapshotEnvironmentRepository.kt @@ -12,12 +12,12 @@ interface SnapshotEnvironmentRepository : DelegatableJdbcRepository + fun findAllByCustomerIdAndEnvironmentId(@Param("customerId") customerId: Long, @Param("environmentId") environmentId: Long): List @Modifying @Query("DELETE FROM snapshot_environment WHERE customerId = :customerId AND snapshotId = :snapshotId") fun deleteByCustomerIdAndSnapshotId(customerId: Long, snapshotId: Long) @Query("SELECT snapshotId FROM snapshot_environment WHERE customerId = :customerId AND snapshotId = :snapshotId") - fun findByCustomerIdAndSnapshotId(@Param("customerId") customerId: Long, @Param("snapshotId") snapshotId: Long): List + fun findAllByCustomerIdAndSnapshotId(@Param("customerId") customerId: Long, @Param("snapshotId") snapshotId: Long): List } diff --git a/scavenger-api/src/main/kotlin/com/navercorp/scavenger/repository/SnapshotNodeDao.kt b/scavenger-api/src/main/kotlin/com/navercorp/scavenger/repository/SnapshotNodeDao.kt index f6db8b1c..ec55128e 100644 --- a/scavenger-api/src/main/kotlin/com/navercorp/scavenger/repository/SnapshotNodeDao.kt +++ b/scavenger-api/src/main/kotlin/com/navercorp/scavenger/repository/SnapshotNodeDao.kt @@ -19,7 +19,7 @@ class SnapshotNodeDao( snapshotId: Long ): List { return select( - sql.findAllExportSnapshotNode(), + sql.selectAllExportSnapshotNode(), mapParameterSource() .addValue("customerId", customerId) .addValue("snapshotId", snapshotId), @@ -34,7 +34,7 @@ class SnapshotNodeDao( ) } - fun selectAllBySignatureContaining( + fun findAllBySignatureContaining( customerId: Long, snapshotId: Long, signature: String, diff --git a/scavenger-api/src/main/kotlin/com/navercorp/scavenger/repository/SnapshotRepository.kt b/scavenger-api/src/main/kotlin/com/navercorp/scavenger/repository/SnapshotRepository.kt index 07150fa1..95fe508c 100644 --- a/scavenger-api/src/main/kotlin/com/navercorp/scavenger/repository/SnapshotRepository.kt +++ b/scavenger-api/src/main/kotlin/com/navercorp/scavenger/repository/SnapshotRepository.kt @@ -10,7 +10,7 @@ import java.util.Optional @Repository interface SnapshotRepository : DelegatableJdbcRepository { - fun findByCustomerId(customerId: Long): List + fun findAllByCustomerId(customerId: Long): List fun findByCustomerIdAndId(customerId: Long, id: Long): Optional diff --git a/scavenger-api/src/main/kotlin/com/navercorp/scavenger/repository/sql/SnapshotNodeSql.kt b/scavenger-api/src/main/kotlin/com/navercorp/scavenger/repository/sql/SnapshotNodeSql.kt index eb443360..da7b0d91 100644 --- a/scavenger-api/src/main/kotlin/com/navercorp/scavenger/repository/sql/SnapshotNodeSql.kt +++ b/scavenger-api/src/main/kotlin/com/navercorp/scavenger/repository/sql/SnapshotNodeSql.kt @@ -4,7 +4,7 @@ import com.navercorp.spring.data.jdbc.plus.sql.support.SqlGeneratorSupport class SnapshotNodeSql : SqlGeneratorSupport() { - fun findAllExportSnapshotNode(): String = + fun selectAllExportSnapshotNode(): String = """ SELECT snapshots.filterInvokedAtMillis, diff --git a/scavenger-api/src/main/kotlin/com/navercorp/scavenger/service/AgentService.kt b/scavenger-api/src/main/kotlin/com/navercorp/scavenger/service/AgentService.kt index 5ab26d0a..04ef21dd 100644 --- a/scavenger-api/src/main/kotlin/com/navercorp/scavenger/service/AgentService.kt +++ b/scavenger-api/src/main/kotlin/com/navercorp/scavenger/service/AgentService.kt @@ -7,6 +7,6 @@ import org.springframework.stereotype.Service @Service class AgentService(val agentRepository: AgentRepository) { fun getAgents(customerId: Long): List { - return agentRepository.findAgentsByCustomerId(customerId) + return agentRepository.findAllAgentsByCustomerId(customerId) } } diff --git a/scavenger-api/src/main/kotlin/com/navercorp/scavenger/service/ApplicationService.kt b/scavenger-api/src/main/kotlin/com/navercorp/scavenger/service/ApplicationService.kt index 304c612c..caa3aed8 100644 --- a/scavenger-api/src/main/kotlin/com/navercorp/scavenger/service/ApplicationService.kt +++ b/scavenger-api/src/main/kotlin/com/navercorp/scavenger/service/ApplicationService.kt @@ -19,11 +19,11 @@ class ApplicationService( val snapshotService: SnapshotService ) { fun getApplications(customerId: Long): List { - return applicationRepository.findByCustomerId(customerId).map { ApplicationDto.from(it) } + return applicationRepository.findAllByCustomerId(customerId).map { ApplicationDto.from(it) } } fun getApplicationsDetail(customerId: Long): List { - val applications = applicationRepository.findByCustomerId(customerId) + val applications = applicationRepository.findAllByCustomerId(customerId) return applications .map { applicationEntity: ApplicationEntity -> val applicationId = applicationEntity.id @@ -47,7 +47,7 @@ class ApplicationService( checkNotNull(applicationRepository.findByCustomerIdAndId(customerId, applicationId)) { "잘못된 접근" } jvmRepository.deleteByCustomerIdAndApplicationId(customerId, applicationId) invocationRepository.deleteByCustomerIdAndApplicationId(customerId, applicationId) - snapshotApplicationRepository.findByCustomerIdAndApplicationId(customerId, applicationId) + snapshotApplicationRepository.findAllByCustomerIdAndApplicationId(customerId, applicationId) .forEach { snapshotId -> snapshotService.deleteSnapshot(customerId, snapshotId) } applicationRepository.deleteByCustomerIdAndId(customerId, applicationId) } diff --git a/scavenger-api/src/main/kotlin/com/navercorp/scavenger/service/CustomerService.kt b/scavenger-api/src/main/kotlin/com/navercorp/scavenger/service/CustomerService.kt index 824f6424..36a1f746 100644 --- a/scavenger-api/src/main/kotlin/com/navercorp/scavenger/service/CustomerService.kt +++ b/scavenger-api/src/main/kotlin/com/navercorp/scavenger/service/CustomerService.kt @@ -68,7 +68,7 @@ class CustomerService( fun deleteCustomer(groupId: String, userId: String, customerId: Long, remainCustomer: Boolean = true) { val customer = customerRepository.findById(customerId).orElseThrow() if (customer.groupId == groupId) { - snapshotRepository.findByCustomerId(customerId).forEach { + snapshotRepository.findAllByCustomerId(customerId).forEach { snapshotApplicationRepository.deleteByCustomerIdAndSnapshotId(customerId, requireNotNull(it.id)) snapshotEnvironmentRepository.deleteByCustomerIdAndSnapshotId(customerId, it.id) snapshotNodeRepository.deleteAllByCustomerIdAndSnapshotId(customerId, it.id) diff --git a/scavenger-api/src/main/kotlin/com/navercorp/scavenger/service/EnvironmentService.kt b/scavenger-api/src/main/kotlin/com/navercorp/scavenger/service/EnvironmentService.kt index e679891b..d8eca9a3 100644 --- a/scavenger-api/src/main/kotlin/com/navercorp/scavenger/service/EnvironmentService.kt +++ b/scavenger-api/src/main/kotlin/com/navercorp/scavenger/service/EnvironmentService.kt @@ -19,11 +19,11 @@ class EnvironmentService( val snapshotService: SnapshotService ) { fun getEnvironments(customerId: Long): List { - return environmentRepository.findByCustomerId(customerId).map { EnvironmentDto.from(it) } + return environmentRepository.findAllByCustomerId(customerId).map { EnvironmentDto.from(it) } } fun getEnvironmentsDetail(customerId: Long): List { - val environments = environmentRepository.findByCustomerId(customerId) + val environments = environmentRepository.findAllByCustomerId(customerId) return environments .map { environmentEntity: EnvironmentEntity -> val environmentId = environmentEntity.id @@ -47,7 +47,7 @@ class EnvironmentService( checkNotNull(environmentRepository.findByCustomerIdAndId(customerId, environmentId)) { "잘못된 접근" } jvmRepository.deleteByCustomerIdAndEnvironmentId(customerId, environmentId) invocationRepository.deleteByCustomerIdAndEnvironmentId(customerId, environmentId) - snapshotEnvironmentRepository.findByCustomerIdAndEnvironmentId(customerId, environmentId) + snapshotEnvironmentRepository.findAllByCustomerIdAndEnvironmentId(customerId, environmentId) .forEach { snapshotId -> snapshotService.deleteSnapshot(customerId, snapshotId) } environmentRepository.deleteByCustomerIdAndId(customerId, environmentId) } diff --git a/scavenger-api/src/main/kotlin/com/navercorp/scavenger/service/GithubMappingService.kt b/scavenger-api/src/main/kotlin/com/navercorp/scavenger/service/GithubMappingService.kt index 1818098a..066eaa19 100644 --- a/scavenger-api/src/main/kotlin/com/navercorp/scavenger/service/GithubMappingService.kt +++ b/scavenger-api/src/main/kotlin/com/navercorp/scavenger/service/GithubMappingService.kt @@ -9,7 +9,7 @@ import org.springframework.stereotype.Service class GithubMappingService(val githubMappingRepository: GithubMappingRepository) { fun getGithubMappings(customerId: Long): List { - return githubMappingRepository.findByCustomerId(customerId).map { GithubMappingDto.from(it) } + return githubMappingRepository.findAllByCustomerId(customerId).map { GithubMappingDto.from(it) } } fun createGithubMapping(customerId: Long, basePackage: String, url: String): GithubMappingDto { diff --git a/scavenger-api/src/main/kotlin/com/navercorp/scavenger/service/SnapshotNodeService.kt b/scavenger-api/src/main/kotlin/com/navercorp/scavenger/service/SnapshotNodeService.kt index 29b6ad15..985dfca4 100644 --- a/scavenger-api/src/main/kotlin/com/navercorp/scavenger/service/SnapshotNodeService.kt +++ b/scavenger-api/src/main/kotlin/com/navercorp/scavenger/service/SnapshotNodeService.kt @@ -50,7 +50,7 @@ class SnapshotNodeService( signature: String, snapshotNodeId: Long? = null ): List { - return snapshotNodeDao.selectAllBySignatureContaining(customerId, snapshotId, signature, snapshotNodeId) + return snapshotNodeDao.findAllBySignatureContaining(customerId, snapshotId, signature, snapshotNodeId) } private fun filterByPackagesAntMatch( diff --git a/scavenger-api/src/main/kotlin/com/navercorp/scavenger/service/SnapshotService.kt b/scavenger-api/src/main/kotlin/com/navercorp/scavenger/service/SnapshotService.kt index c4dd288e..c1e70344 100644 --- a/scavenger-api/src/main/kotlin/com/navercorp/scavenger/service/SnapshotService.kt +++ b/scavenger-api/src/main/kotlin/com/navercorp/scavenger/service/SnapshotService.kt @@ -31,7 +31,7 @@ class SnapshotService( filterInvokedAtMillis: Long, packages: String ): SnapshotDto { - val methodInvocations = methodInvocationRepository.findMethodInvocations(customerId, applicationIdList, environmentIdList) + val methodInvocations = methodInvocationRepository.findAllMethodInvocations(customerId, applicationIdList, environmentIdList) val snapshotEntity = SnapshotEntity( name = name, customerId = customerId, @@ -58,7 +58,7 @@ class SnapshotService( packages: String ): SnapshotDto { val existing = snapshotDao.findByCustomerIdAndId(customerId, snapshotId).orElseThrow() - val methodInvocations = methodInvocationRepository.findMethodInvocations(existing.customerId, applicationIdList, environmentIdList) + val methodInvocations = methodInvocationRepository.findAllMethodInvocations(existing.customerId, applicationIdList, environmentIdList) val snapshot = existing.copy(packages = packages, name = name, filterInvokedAtMillis = filterInvokedAtMillis) snapshotDao.updateSnapshot(snapshot) @@ -86,7 +86,7 @@ class SnapshotService( val snapshot = snapshotDao.findByCustomerIdAndId(customerId, snapshotId).orElseThrow() val applicationIdList: List = snapshot.applications.map { it.applicationId } val environmentIdList: List = snapshot.environments.map { it.environmentId } - val methodInvocations = methodInvocationRepository.findMethodInvocations(snapshot.customerId, applicationIdList, environmentIdList) + val methodInvocations = methodInvocationRepository.findAllMethodInvocations(snapshot.customerId, applicationIdList, environmentIdList) snapshotNodeService.deleteSnapshotNode(snapshot.customerId, snapshotId) snapshotNodeService.createAndSaveSnapshotNodes(snapshot, methodInvocations) @@ -111,7 +111,7 @@ class SnapshotService( } fun listSnapshots(customerId: Long): List { - return snapshotDao.findByCustomerId(customerId).map { SnapshotDto.from(it) } + return snapshotDao.findAllByCustomerId(customerId).map { SnapshotDto.from(it) } } companion object { diff --git a/scavenger-api/src/test/kotlin/com/navercorp/scavenger/repository/AgentRepositoryTest.kt b/scavenger-api/src/test/kotlin/com/navercorp/scavenger/repository/AgentRepositoryTest.kt index 072da6e9..71ee01a5 100644 --- a/scavenger-api/src/test/kotlin/com/navercorp/scavenger/repository/AgentRepositoryTest.kt +++ b/scavenger-api/src/test/kotlin/com/navercorp/scavenger/repository/AgentRepositoryTest.kt @@ -11,7 +11,7 @@ class AgentRepositoryTest { private lateinit var sut: AgentRepository @Test - fun findAgentsByCustomerId() { - assertThat(sut.findAgentsByCustomerId(1)).isNotNull + fun findAllAgentsByCustomerId() { + assertThat(sut.findAllAgentsByCustomerId(1)).isNotNull } } diff --git a/scavenger-api/src/test/kotlin/com/navercorp/scavenger/repository/ApplicationRepositoryTest.kt b/scavenger-api/src/test/kotlin/com/navercorp/scavenger/repository/ApplicationRepositoryTest.kt index c45f29c5..b9d7cbdc 100644 --- a/scavenger-api/src/test/kotlin/com/navercorp/scavenger/repository/ApplicationRepositoryTest.kt +++ b/scavenger-api/src/test/kotlin/com/navercorp/scavenger/repository/ApplicationRepositoryTest.kt @@ -11,8 +11,8 @@ class ApplicationRepositoryTest { private lateinit var sut: ApplicationRepository @Test - fun findByCustomerId() { - assertThat(sut.findByCustomerId(1)).hasSize(1) + fun findAllByCustomerId() { + assertThat(sut.findAllByCustomerId(1)).hasSize(1) } @Test diff --git a/scavenger-api/src/test/kotlin/com/navercorp/scavenger/repository/EnvironmentRepositoryTest.kt b/scavenger-api/src/test/kotlin/com/navercorp/scavenger/repository/EnvironmentRepositoryTest.kt index bee23298..ea6f0341 100644 --- a/scavenger-api/src/test/kotlin/com/navercorp/scavenger/repository/EnvironmentRepositoryTest.kt +++ b/scavenger-api/src/test/kotlin/com/navercorp/scavenger/repository/EnvironmentRepositoryTest.kt @@ -11,8 +11,8 @@ class EnvironmentRepositoryTest { private lateinit var sut: EnvironmentRepository @Test - fun findByCustomerId() { - assertThat(sut.findByCustomerId(1)).hasSize(1) + fun findAllByCustomerId() { + assertThat(sut.findAllByCustomerId(1)).hasSize(1) } @Test diff --git a/scavenger-api/src/test/kotlin/com/navercorp/scavenger/repository/GithubMappingRepositoryTest.kt b/scavenger-api/src/test/kotlin/com/navercorp/scavenger/repository/GithubMappingRepositoryTest.kt index 436cd982..c1ee1c09 100644 --- a/scavenger-api/src/test/kotlin/com/navercorp/scavenger/repository/GithubMappingRepositoryTest.kt +++ b/scavenger-api/src/test/kotlin/com/navercorp/scavenger/repository/GithubMappingRepositoryTest.kt @@ -12,8 +12,8 @@ class GithubMappingRepositoryTest { private lateinit var sut: GithubMappingRepository @Test - fun findByCustomerId() { - assertThat(sut.findByCustomerId(1)).hasSize(1) + fun findAllByCustomerId() { + assertThat(sut.findAllByCustomerId(1)).hasSize(1) } @Test @@ -21,6 +21,6 @@ class GithubMappingRepositoryTest { fun deleteByCustomerIdAndId() { sut.deleteByCustomerIdAndId(1, 1) - assertThat(sut.findByCustomerId(1)).hasSize(0) + assertThat(sut.findAllByCustomerId(1)).hasSize(0) } } diff --git a/scavenger-api/src/test/kotlin/com/navercorp/scavenger/repository/MethodInvocationRepositoryTest.kt b/scavenger-api/src/test/kotlin/com/navercorp/scavenger/repository/MethodInvocationRepositoryTest.kt index 270e3634..dad92122 100644 --- a/scavenger-api/src/test/kotlin/com/navercorp/scavenger/repository/MethodInvocationRepositoryTest.kt +++ b/scavenger-api/src/test/kotlin/com/navercorp/scavenger/repository/MethodInvocationRepositoryTest.kt @@ -11,7 +11,7 @@ class MethodInvocationRepositoryTest { private lateinit var sut: MethodInvocationRepository @Test - fun findMethodInvocations() { - assertThat(sut.findMethodInvocations(1, listOf(1), listOf(1))).hasSizeGreaterThanOrEqualTo(0) + fun findAllMethodInvocations() { + assertThat(sut.findAllMethodInvocations(1, listOf(1), listOf(1))).hasSizeGreaterThanOrEqualTo(0) } } diff --git a/scavenger-api/src/test/kotlin/com/navercorp/scavenger/repository/SnapshotApplicationRepositoryTest.kt b/scavenger-api/src/test/kotlin/com/navercorp/scavenger/repository/SnapshotApplicationRepositoryTest.kt index 2aa98378..34837bba 100644 --- a/scavenger-api/src/test/kotlin/com/navercorp/scavenger/repository/SnapshotApplicationRepositoryTest.kt +++ b/scavenger-api/src/test/kotlin/com/navercorp/scavenger/repository/SnapshotApplicationRepositoryTest.kt @@ -22,15 +22,15 @@ class SnapshotApplicationRepositoryTest { } @Test - fun findByCustomerIdAndApplicationId() { - assertThat(sut.findByCustomerIdAndApplicationId(customerId, applicationId)).hasSizeGreaterThan(0) + fun findAllByCustomerIdAndApplicationId() { + assertThat(sut.findAllByCustomerIdAndApplicationId(customerId, applicationId)).hasSizeGreaterThan(0) } @Test @Transactional fun deleteByCustomerIdAndSnapshotId() { sut.deleteByCustomerIdAndSnapshotId(customerId, snapshotId) - assertThat(sut.findByCustomerIdAndSnapshotId(customerId, snapshotId)).hasSize(0) + assertThat(sut.findAllByCustomerIdAndSnapshotId(customerId, snapshotId)).hasSize(0) } @Test @@ -42,6 +42,6 @@ class SnapshotApplicationRepositoryTest { ).toSet() sut.insertAll(param) - assertThat(sut.findByCustomerIdAndApplicationId(0, 1)).hasSize(2) + assertThat(sut.findAllByCustomerIdAndApplicationId(0, 1)).hasSize(2) } } diff --git a/scavenger-api/src/test/kotlin/com/navercorp/scavenger/repository/SnapshotEnvironmentRepositoryTest.kt b/scavenger-api/src/test/kotlin/com/navercorp/scavenger/repository/SnapshotEnvironmentRepositoryTest.kt index 4831c02a..eb23a8ae 100644 --- a/scavenger-api/src/test/kotlin/com/navercorp/scavenger/repository/SnapshotEnvironmentRepositoryTest.kt +++ b/scavenger-api/src/test/kotlin/com/navercorp/scavenger/repository/SnapshotEnvironmentRepositoryTest.kt @@ -22,15 +22,15 @@ class SnapshotEnvironmentRepositoryTest { } @Test - fun findByCustomerIdAndApplicationId() { - assertThat(sut.findByCustomerIdAndEnvironmentId(customerId, environmentId)).hasSizeGreaterThan(0) + fun findAllByCustomerIdAndEnvironmentId() { + assertThat(sut.findAllByCustomerIdAndEnvironmentId(customerId, environmentId)).hasSizeGreaterThan(0) } @Test @Transactional fun deleteByCustomerIdAndSnapshotId() { sut.deleteByCustomerIdAndSnapshotId(customerId, snapshotId) - assertThat(sut.findByCustomerIdAndSnapshotId(customerId, snapshotId)).hasSize(0) + assertThat(sut.findAllByCustomerIdAndSnapshotId(customerId, snapshotId)).hasSize(0) } @Test @@ -42,6 +42,6 @@ class SnapshotEnvironmentRepositoryTest { ).toSet() sut.insertAll(param) - assertThat(sut.findByCustomerIdAndEnvironmentId(0, 1)).hasSize(2) + assertThat(sut.findAllByCustomerIdAndEnvironmentId(0, 1)).hasSize(2) } } diff --git a/scavenger-api/src/test/kotlin/com/navercorp/scavenger/repository/SnapshotNodeRepositoryTest.kt b/scavenger-api/src/test/kotlin/com/navercorp/scavenger/repository/SnapshotNodeRepositoryTest.kt index 5da40437..0c329c7c 100644 --- a/scavenger-api/src/test/kotlin/com/navercorp/scavenger/repository/SnapshotNodeRepositoryTest.kt +++ b/scavenger-api/src/test/kotlin/com/navercorp/scavenger/repository/SnapshotNodeRepositoryTest.kt @@ -66,12 +66,12 @@ class SnapshotNodeRepositoryTest { } @Test - fun selectAllBySignatureContaining() { - val result = sut.selectAllBySignatureContaining(customerId, snapshotId, parent) + fun findAllBySignatureContaining() { + val result = sut.findAllBySignatureContaining(customerId, snapshotId, parent) assertThat(result).hasSizeGreaterThan(0) - assertThat(sut.selectAllBySignatureContaining(customerId, snapshotId, parent, result.last().id)).hasSize(0) + assertThat(sut.findAllBySignatureContaining(customerId, snapshotId, parent, result.last().id)).hasSize(0) - assertThat(sut.selectAllBySignatureContaining(customerId, snapshotId, "hello")).hasSize(1) + assertThat(sut.findAllBySignatureContaining(customerId, snapshotId, "hello")).hasSize(1) } } diff --git a/scavenger-api/src/test/kotlin/com/navercorp/scavenger/repository/SnapshotRepositoryTest.kt b/scavenger-api/src/test/kotlin/com/navercorp/scavenger/repository/SnapshotRepositoryTest.kt index 0b95986d..c8a1d80f 100644 --- a/scavenger-api/src/test/kotlin/com/navercorp/scavenger/repository/SnapshotRepositoryTest.kt +++ b/scavenger-api/src/test/kotlin/com/navercorp/scavenger/repository/SnapshotRepositoryTest.kt @@ -11,8 +11,8 @@ class SnapshotRepositoryTest { private lateinit var sut: SnapshotDao @Test - fun findByCustomerId() { - assertThat(sut.findByCustomerId(1)).hasSizeGreaterThan(0) + fun findAllByCustomerId() { + assertThat(sut.findAllByCustomerId(1)).hasSizeGreaterThan(0) } @Test diff --git a/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/repository/AgentStateDao.kt b/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/repository/AgentStateDao.kt index 3babf114..f276ef55 100644 --- a/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/repository/AgentStateDao.kt +++ b/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/repository/AgentStateDao.kt @@ -16,9 +16,9 @@ class AgentStateDao( AgentStateRepository by agentStateRepository { private val sql: AgentStateSql = super.sqls(::AgentStateSql) - fun findGarbageLastPolledAtBefore(customerId: Long, lastPolledAt: Instant): List { + fun findAllGarbageLastPolledAtBefore(customerId: Long, lastPolledAt: Instant): List { return select( - sql.selectGarbageLastPolledAtBefore(), + sql.selectAllGarbageLastPolledAtBefore(), mapParameterSource() .addValue("customerId", customerId) .addValue("lastPolledAt", lastPolledAt), diff --git a/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/repository/sql/AgentStateSql.kt b/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/repository/sql/AgentStateSql.kt index 2c42c87c..fcc40f84 100644 --- a/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/repository/sql/AgentStateSql.kt +++ b/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/repository/sql/AgentStateSql.kt @@ -17,7 +17,7 @@ class AgentStateSql : SqlGeneratorSupport() { AND jvmUuid = :jvmUuid """.trimIndent() - fun selectGarbageLastPolledAtBefore(): String = + fun selectAllGarbageLastPolledAtBefore(): String = """ SELECT ${sql.columns(AgentStateEntity::class.java)} diff --git a/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/service/GarbageCollectService.kt b/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/service/GarbageCollectService.kt index 7d23a797..390fdf8a 100644 --- a/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/service/GarbageCollectService.kt +++ b/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/service/GarbageCollectService.kt @@ -97,7 +97,7 @@ class GarbageCollectService( fun sweepAgentStatesAndJvms(customerId: Long, baseDateTime: Instant) { try { do { - val agentStates = agentStateDao.findGarbageLastPolledAtBefore( + val agentStates = agentStateDao.findAllGarbageLastPolledAtBefore( customerId, baseDateTime.minusMillis(intervalService.batchSweepMarginMilliSecond) ) @@ -117,7 +117,7 @@ class GarbageCollectService( val fingerPrintUsed = jvmDao.findAllByCustomerId(customerId).mapNotNull { it.codeBaseFingerprint }.toSet() val fingerPrintRegistered = codeBaseFingerprintDao.findAllByCustomerId(customerId).map { it.codeBaseFingerprint }.toSet() val sweepSubjects = fingerPrintRegistered - fingerPrintUsed - codeBaseFingerprintDao.deleteAllByCustomerIdAndCodeBaseFingerprintIn(customerId, fingerPrintRegistered - fingerPrintUsed) + codeBaseFingerprintDao.deleteAllByCustomerIdAndCodeBaseFingerprintIn(customerId, sweepSubjects) logger.info { "[$customerId] sweep $sweepSubjects codebaseFingerprint" } } catch (e: Exception) { logger.warn(e) { "[$customerId] error occurred while sweepCodeBaseFingerprints, but ignore. " } From 5f725d5f531c18317f92757c978e488db7105494 Mon Sep 17 00:00:00 2001 From: Suhyeon Sim Date: Mon, 3 Jul 2023 16:16:23 +0900 Subject: [PATCH 19/30] Update scavenger-collector/src/main/kotlin/com/navercorp/scavenger/repository/JvmDao.kt Co-authored-by: taeyeonKim --- .../main/kotlin/com/navercorp/scavenger/repository/JvmDao.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/repository/JvmDao.kt b/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/repository/JvmDao.kt index 6438f1f7..30f42cd0 100644 --- a/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/repository/JvmDao.kt +++ b/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/repository/JvmDao.kt @@ -52,7 +52,7 @@ class JvmDao( ) } - fun findUuidsByWithoutAgent(customerId: Long): List { + fun findAllUuidsByWithoutAgent(customerId: Long): List { return select( sql.selectUuidsByWithoutAgent(), mapParameterSource() From 0f68a2c9cb1354a99d4a5bfb5aef76c8fe9cba30 Mon Sep 17 00:00:00 2001 From: Suhyeon Sim Date: Mon, 3 Jul 2023 16:16:35 +0900 Subject: [PATCH 20/30] Update scavenger-collector/src/main/kotlin/com/navercorp/scavenger/repository/JvmDao.kt Co-authored-by: taeyeonKim --- .../main/kotlin/com/navercorp/scavenger/repository/JvmDao.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/repository/JvmDao.kt b/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/repository/JvmDao.kt index 30f42cd0..920ce771 100644 --- a/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/repository/JvmDao.kt +++ b/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/repository/JvmDao.kt @@ -54,7 +54,7 @@ class JvmDao( fun findAllUuidsByWithoutAgent(customerId: Long): List { return select( - sql.selectUuidsByWithoutAgent(), + sql.selectAllUuidsByWithoutAgent(), mapParameterSource() .addValue("customerId", customerId), String::class.java From dce1a1eb79be8b847f69580e81e0935ee5ea5f8a Mon Sep 17 00:00:00 2001 From: Suhyeon Sim Date: Mon, 3 Jul 2023 16:16:46 +0900 Subject: [PATCH 21/30] Update scavenger-collector/src/main/kotlin/com/navercorp/scavenger/service/GarbageCollectService.kt Co-authored-by: taeyeonKim --- .../com/navercorp/scavenger/service/GarbageCollectService.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/service/GarbageCollectService.kt b/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/service/GarbageCollectService.kt index 807d77a4..0a6cb928 100644 --- a/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/service/GarbageCollectService.kt +++ b/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/service/GarbageCollectService.kt @@ -101,7 +101,7 @@ class GarbageCollectService( customerId, baseDateTime.minusMillis(intervalService.batchSweepMarginMilliSecond) ) - var jvmUuids = jvmDao.findUuidsByWithoutAgent(customerId) + val jvmUuids = jvmDao.findUuidsByWithoutAgent(customerId) jvmDao.deleteAllByCustomerIdAndUuids(customerId, agentStates.map { it.jvmUuid } + jvmUuids) .also { logger.info { "[$customerId] $it jvm is swiped. " } } From 22f2bdf048091e13656f58d2004851300af40679 Mon Sep 17 00:00:00 2001 From: 1004647 Date: Mon, 3 Jul 2023 16:22:46 +0900 Subject: [PATCH 22/30] Applied convention feedback. --- .../kotlin/com/navercorp/scavenger/repository/sql/JvmSql.kt | 2 +- .../com/navercorp/scavenger/service/GarbageCollectService.kt | 2 +- .../kotlin/com/navercorp/scavenger/repository/JvmDaoTest.kt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/repository/sql/JvmSql.kt b/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/repository/sql/JvmSql.kt index a6d661a1..6917fb76 100644 --- a/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/repository/sql/JvmSql.kt +++ b/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/repository/sql/JvmSql.kt @@ -56,7 +56,7 @@ class JvmSql : SqlGeneratorSupport() { AND uuid IN ( :uuids ) """.trimIndent() - fun selectUuidsByWithoutAgent(): String = + fun selectAllUuidsByWithoutAgent(): String = """ SELECT uuid FROM jvms diff --git a/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/service/GarbageCollectService.kt b/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/service/GarbageCollectService.kt index 0a6cb928..9844003f 100644 --- a/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/service/GarbageCollectService.kt +++ b/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/service/GarbageCollectService.kt @@ -101,7 +101,7 @@ class GarbageCollectService( customerId, baseDateTime.minusMillis(intervalService.batchSweepMarginMilliSecond) ) - val jvmUuids = jvmDao.findUuidsByWithoutAgent(customerId) + val jvmUuids = jvmDao.findAllUuidsByWithoutAgent(customerId) jvmDao.deleteAllByCustomerIdAndUuids(customerId, agentStates.map { it.jvmUuid } + jvmUuids) .also { logger.info { "[$customerId] $it jvm is swiped. " } } diff --git a/scavenger-collector/src/test/kotlin/com/navercorp/scavenger/repository/JvmDaoTest.kt b/scavenger-collector/src/test/kotlin/com/navercorp/scavenger/repository/JvmDaoTest.kt index 6d2c167f..a9a776c2 100644 --- a/scavenger-collector/src/test/kotlin/com/navercorp/scavenger/repository/JvmDaoTest.kt +++ b/scavenger-collector/src/test/kotlin/com/navercorp/scavenger/repository/JvmDaoTest.kt @@ -85,7 +85,7 @@ class JvmDaoTest { @Test fun selectUuidsByWithoutAgent() { - val jvmUuids = sut.findUuidsByWithoutAgent(3) + val jvmUuids = sut.findAllUuidsByWithoutAgent(3) assertThat(jvmUuids).isNotEmpty assertThat(jvmUuids).contains("9ec4624c-5b81-44fa-82c8-74233095b120") } From 959a9629c3bb425915a31264bd7d2f316a14c142 Mon Sep 17 00:00:00 2001 From: 1004647 Date: Tue, 4 Jul 2023 10:51:26 +0900 Subject: [PATCH 23/30] Update GarbageCollectService.kt change variable name --- .../com/navercorp/scavenger/service/GarbageCollectService.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/service/GarbageCollectService.kt b/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/service/GarbageCollectService.kt index 9844003f..2ec65a5c 100644 --- a/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/service/GarbageCollectService.kt +++ b/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/service/GarbageCollectService.kt @@ -101,9 +101,9 @@ class GarbageCollectService( customerId, baseDateTime.minusMillis(intervalService.batchSweepMarginMilliSecond) ) - val jvmUuids = jvmDao.findAllUuidsByWithoutAgent(customerId) + val uuidsWithougAgent = jvmDao.findAllUuidsByWithoutAgent(customerId) - jvmDao.deleteAllByCustomerIdAndUuids(customerId, agentStates.map { it.jvmUuid } + jvmUuids) + jvmDao.deleteAllByCustomerIdAndUuids(customerId, agentStates.map { it.jvmUuid } + uuidsWithougAgent) .also { logger.info { "[$customerId] $it jvm is swiped. " } } agentStateDao.deleteAllByCustomerIdAndIds(customerId, agentStates.map { it.id }) .also { logger.info { "[$customerId] $it agent state is swiped. " } } From 78cb31ba56321e8eed26581ec3761ec6abf49949 Mon Sep 17 00:00:00 2001 From: 1004647 Date: Tue, 4 Jul 2023 14:33:09 +0900 Subject: [PATCH 24/30] Update GarbageCollectService typo fix --- .../com/navercorp/scavenger/service/GarbageCollectService.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/service/GarbageCollectService.kt b/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/service/GarbageCollectService.kt index 2ec65a5c..77c8f7ca 100644 --- a/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/service/GarbageCollectService.kt +++ b/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/service/GarbageCollectService.kt @@ -101,9 +101,9 @@ class GarbageCollectService( customerId, baseDateTime.minusMillis(intervalService.batchSweepMarginMilliSecond) ) - val uuidsWithougAgent = jvmDao.findAllUuidsByWithoutAgent(customerId) + val uuidsWithoutAgent = jvmDao.findAllUuidsByWithoutAgent(customerId) - jvmDao.deleteAllByCustomerIdAndUuids(customerId, agentStates.map { it.jvmUuid } + uuidsWithougAgent) + jvmDao.deleteAllByCustomerIdAndUuids(customerId, agentStates.map { it.jvmUuid } + uuidsWithoutAgent) .also { logger.info { "[$customerId] $it jvm is swiped. " } } agentStateDao.deleteAllByCustomerIdAndIds(customerId, agentStates.map { it.id }) .also { logger.info { "[$customerId] $it agent state is swiped. " } } From e0d780ac0e93dc2d4a9bb464888a4ae25199477d Mon Sep 17 00:00:00 2001 From: sohyun-ku Date: Wed, 12 Jul 2023 12:12:24 +0900 Subject: [PATCH 25/30] Add chunk to selectAllUuidsByWithoutAgent --- .../scavenger/repository/sql/JvmSql.kt | 21 ++++++++++--------- .../service/GarbageCollectService.kt | 9 ++++++-- 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/repository/sql/JvmSql.kt b/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/repository/sql/JvmSql.kt index 6917fb76..860f16b3 100644 --- a/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/repository/sql/JvmSql.kt +++ b/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/repository/sql/JvmSql.kt @@ -58,15 +58,16 @@ class JvmSql : SqlGeneratorSupport() { fun selectAllUuidsByWithoutAgent(): String = """ - SELECT uuid FROM - jvms - WHERE - customerId = :customerId - AND uuid NOT IN ( - SELECT - jvmUuid - FROM - agent_state - ) + SELECT uuid FROM + jvms + WHERE + customerId = :customerId + AND uuid NOT IN ( + SELECT + jvmUuid + FROM + agent_state + ) + LIMIT 10000 """.trimIndent() } diff --git a/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/service/GarbageCollectService.kt b/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/service/GarbageCollectService.kt index 44d89955..e2c7bee1 100644 --- a/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/service/GarbageCollectService.kt +++ b/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/service/GarbageCollectService.kt @@ -101,13 +101,18 @@ class GarbageCollectService( customerId, baseDateTime.minusMillis(intervalService.batchSweepMarginMilliSecond) ) - val uuidsWithoutAgent = jvmDao.findAllUuidsByWithoutAgent(customerId) - jvmDao.deleteAllByCustomerIdAndUuids(customerId, agentStates.map { it.jvmUuid } + uuidsWithoutAgent) + jvmDao.deleteAllByCustomerIdAndUuids(customerId, agentStates.map { it.jvmUuid }) .also { logger.info { "[$customerId] $it jvm is swiped. " } } agentStateDao.deleteAllByCustomerIdAndIds(customerId, agentStates.map { it.id }) .also { logger.info { "[$customerId] $it agent state is swiped. " } } } while (agentStates.isNotEmpty()) + + do { + val uuidsWithoutAgent = jvmDao.findAllUuidsByWithoutAgent(customerId) + jvmDao.deleteAllByCustomerIdAndUuids(customerId, uuidsWithoutAgent) + .also { logger.info { "[$customerId] $it jvm without agent is swiped." } } + } while (uuidsWithoutAgent.isNotEmpty()) } catch (e: Exception) { logger.warn(e) { "[$customerId] error occurred while sweepAgentStates, but ignored. " } } From b79a4de3e4900e86904e0cf930f5b3ae922fb659 Mon Sep 17 00:00:00 2001 From: Ohjun Kwon Date: Mon, 7 Aug 2023 15:05:52 +0900 Subject: [PATCH 26/30] Remove unused methods --- .../param/IncompleteMethodInsertParam.kt | 10 ------- .../scavenger/repository/AgentStateDao.kt | 9 ------ .../navercorp/scavenger/repository/JvmDao.kt | 10 ------- .../scavenger/repository/LeadershipDao.kt | 19 ------------- .../scavenger/repository/sql/AgentStateSql.kt | 9 ------ .../scavenger/repository/sql/JvmSql.kt | 12 -------- .../scavenger/repository/sql/LeadershipSql.kt | 28 ------------------- .../scavenger/service/OperationService.kt | 2 +- .../scavenger/repository/AgentStateDaoTest.kt | 10 ------- .../scavenger/repository/JvmDaoTest.kt | 6 ---- 10 files changed, 1 insertion(+), 114 deletions(-) delete mode 100644 scavenger-collector/src/main/kotlin/com/navercorp/scavenger/param/IncompleteMethodInsertParam.kt diff --git a/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/param/IncompleteMethodInsertParam.kt b/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/param/IncompleteMethodInsertParam.kt deleted file mode 100644 index 07cf7607..00000000 --- a/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/param/IncompleteMethodInsertParam.kt +++ /dev/null @@ -1,10 +0,0 @@ -package com.navercorp.scavenger.param - -import java.time.Instant - -class IncompleteMethodInsertParam( - val customerId: Long, - val createdAt: Instant, - val hash: String, - val signatureHash: String, -) diff --git a/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/repository/AgentStateDao.kt b/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/repository/AgentStateDao.kt index f276ef55..835ad8ae 100644 --- a/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/repository/AgentStateDao.kt +++ b/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/repository/AgentStateDao.kt @@ -26,15 +26,6 @@ class AgentStateDao( ) } - fun deleteGarbageLastPolledAtBefore(customerId: Long, lastPolledAt: Instant): Int { - return update( - sql.deleteGarbageLastPolledAtBefore(), - mapParameterSource() - .addValue("customerId", customerId) - .addValue("lastPolledAt", lastPolledAt) - ) - } - @Transactional fun updateTimestampsAndEnabled( customerId: Long, diff --git a/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/repository/JvmDao.kt b/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/repository/JvmDao.kt index 920ce771..9f4dcfe3 100644 --- a/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/repository/JvmDao.kt +++ b/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/repository/JvmDao.kt @@ -6,7 +6,6 @@ import com.navercorp.scavenger.util.getFirstKey import com.navercorp.spring.data.jdbc.plus.sql.provider.EntityJdbcProvider import org.springframework.jdbc.support.GeneratedKeyHolder import org.springframework.stereotype.Repository -import java.time.Instant @Repository class JvmDao( @@ -31,15 +30,6 @@ class JvmDao( } } - fun deleteGarbagePublishedBefore(customerId: Long, publishedBefore: Instant): Int { - return update( - sql.deleteGarbagePublishedBefore(), - mapParameterSource() - .addValue("customerId", customerId) - .addValue("publishedAt", publishedBefore) - ) - } - fun deleteAllByCustomerIdAndUuids(customerId: Long, uuids: List): Int { if (uuids.isEmpty()) { return 0 diff --git a/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/repository/LeadershipDao.kt b/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/repository/LeadershipDao.kt index 0957282b..8baa5af2 100644 --- a/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/repository/LeadershipDao.kt +++ b/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/repository/LeadershipDao.kt @@ -23,15 +23,6 @@ class LeadershipDao( ) } - fun forceLeadership(memberId: String, now: Instant): Int { - return update( - sql.forceLeadership(), - mapParameterSource() - .addValue("memberId", memberId) - .addValue("lastSeenActive", now) - ) - } - fun forceReelection(): Int { return update( sql.forceReelection(), @@ -39,16 +30,6 @@ class LeadershipDao( ) } - fun isLeader(memberId: String): Boolean { - val count = selectSingleValue( - sql.isLeader(), - mapParameterSource() - .addValue("memberId", memberId), - Int::class.java - ) - return count != 0 - } - fun getLeader(): String? { return selectSingleValue( sql.selectLeader(), diff --git a/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/repository/sql/AgentStateSql.kt b/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/repository/sql/AgentStateSql.kt index fcc40f84..efd274fb 100644 --- a/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/repository/sql/AgentStateSql.kt +++ b/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/repository/sql/AgentStateSql.kt @@ -29,15 +29,6 @@ class AgentStateSql : SqlGeneratorSupport() { LIMIT 10000 """.trimIndent() - fun deleteGarbageLastPolledAtBefore(): String = - """ - DELETE FROM - agent_state - WHERE - customerId = :customerId - AND lastPolledAt < :lastPolledAt - """.trimIndent() - fun deleteAllByCustomerIdAndIds(): String = """ DELETE FROM diff --git a/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/repository/sql/JvmSql.kt b/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/repository/sql/JvmSql.kt index 860f16b3..1d3562f1 100644 --- a/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/repository/sql/JvmSql.kt +++ b/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/repository/sql/JvmSql.kt @@ -35,18 +35,6 @@ class JvmSql : SqlGeneratorSupport() { publishedAt = :publishedAt """.trimIndent() - /** - * publishedAt in jvm is same as lastSeenAt - */ - fun deleteGarbagePublishedBefore(): String = - """ - DELETE FROM - jvms - WHERE - customerId = :customerId - AND publishedAt < :publishedAt - """.trimIndent() - fun deleteAllByCustomerIdAndUuids(): String = """ DELETE FROM diff --git a/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/repository/sql/LeadershipSql.kt b/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/repository/sql/LeadershipSql.kt index dc7f3352..6d6fe17a 100644 --- a/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/repository/sql/LeadershipSql.kt +++ b/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/repository/sql/LeadershipSql.kt @@ -23,39 +23,11 @@ class LeadershipSql : SqlGeneratorSupport() { lastSeenActive = CASE WHEN memberId = VALUES(memberId) THEN VALUES(lastSeenActive) ELSE lastSeenActive END """ - fun forceLeadership() = - """ - REPLACE INTO - leadership - ( - anchor, - memberId, - lastSeenActive - ) - VALUES - ( - 1, - :memberId, - :lastSeenActive - ) - """ - fun forceReelection() = """ DELETE FROM leadership """ - fun isLeader() = - """ - SELECT - count(*) AS isLeader - FROM - leadership - WHERE - anchor = 1 - AND memberId = :memberId - """ - fun selectLeader() = """ SELECT diff --git a/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/service/OperationService.kt b/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/service/OperationService.kt index d15241ff..169ac3d9 100644 --- a/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/service/OperationService.kt +++ b/scavenger-collector/src/main/kotlin/com/navercorp/scavenger/service/OperationService.kt @@ -37,7 +37,7 @@ class OperationService( this.operationInfo = operationInfo } } catch (ignored: Exception) { - logger.error(ignored) { "Error occured while dispatching $operationInfoUrl, operation job is skipped" } + logger.error(ignored) { "Error occurred while dispatching $operationInfoUrl, operation job is skipped" } } } diff --git a/scavenger-collector/src/test/kotlin/com/navercorp/scavenger/repository/AgentStateDaoTest.kt b/scavenger-collector/src/test/kotlin/com/navercorp/scavenger/repository/AgentStateDaoTest.kt index ed5baf0c..1325f1a0 100644 --- a/scavenger-collector/src/test/kotlin/com/navercorp/scavenger/repository/AgentStateDaoTest.kt +++ b/scavenger-collector/src/test/kotlin/com/navercorp/scavenger/repository/AgentStateDaoTest.kt @@ -12,16 +12,6 @@ class AgentStateDaoTest { @Autowired private lateinit var sut: AgentStateDao - @Test - @Transactional - fun deleteGarbageLastPolledAtBefore() { - val now = Instant.now() - sut.findAll().map { it.customerId }.forEach { - sut.deleteGarbageLastPolledAtBefore(it, now) - } - assertThat(sut.findAll().filter { it.lastPolledAt <= now }).isEmpty() - } - @Test @Transactional fun updateTimestampsAndEnabled() { diff --git a/scavenger-collector/src/test/kotlin/com/navercorp/scavenger/repository/JvmDaoTest.kt b/scavenger-collector/src/test/kotlin/com/navercorp/scavenger/repository/JvmDaoTest.kt index a9a776c2..e76d2688 100644 --- a/scavenger-collector/src/test/kotlin/com/navercorp/scavenger/repository/JvmDaoTest.kt +++ b/scavenger-collector/src/test/kotlin/com/navercorp/scavenger/repository/JvmDaoTest.kt @@ -77,12 +77,6 @@ class JvmDaoTest { assertThat(sut.findAllByCustomerId(2)).isNotEmpty } - @Test - fun deleteGarbagePublishedBefore() { - sut.deleteGarbagePublishedBefore(2, Instant.now()) - assertThat(sut.findByCustomerIdAndUuid(2, "d0dfa3c2-809c-428f-b501-7419196d91c5")).isNull() - } - @Test fun selectUuidsByWithoutAgent() { val jvmUuids = sut.findAllUuidsByWithoutAgent(3) From d4bad83aecdab5f76ae1058c9a0692a7f42c6434 Mon Sep 17 00:00:00 2001 From: Ohjun Kwon Date: Fri, 18 Aug 2023 19:40:19 +0900 Subject: [PATCH 27/30] Use Gradle JVM toolchain and exclude old agent --- build.gradle.kts | 12 ++++++++++-- scavenger-agent-java/build.gradle.kts | 9 ++++----- scavenger-api/build.gradle.kts | 5 ++++- scavenger-collector/build.gradle.kts | 5 ++++- scavenger-demo-extension/build.gradle.kts | 7 ++++--- scavenger-demo/build.gradle.kts | 7 ++++--- scavenger-entity/build.gradle.kts | 6 ++++++ scavenger-model/build.gradle.kts | 12 +++--------- scavenger-schema/build.gradle.kts | 6 ++++++ 9 files changed, 45 insertions(+), 24 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 4740c723..58a9af81 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -27,8 +27,8 @@ release { version } - pushReleaseVersionBranch.set("release/${ releaseVersion }") - tagTemplate.set("v${ releaseVersion }") + pushReleaseVersionBranch.set("release/${releaseVersion}") + tagTemplate.set("v${releaseVersion}") preTagCommitMessage.set("Release ") newVersionCommitMessage.set("Update next development version after Release") with(git) { @@ -41,3 +41,11 @@ subprojects { useJUnitPlatform() } } + +project(":scavenger-old-agent-java").afterEvaluate { + tasks.all { + onlyIf { + project.hasProperty("oldAgent") + } + } +} diff --git a/scavenger-agent-java/build.gradle.kts b/scavenger-agent-java/build.gradle.kts index 7c77107a..218b7ca1 100644 --- a/scavenger-agent-java/build.gradle.kts +++ b/scavenger-agent-java/build.gradle.kts @@ -11,6 +11,10 @@ plugins { } java { + toolchain { + languageVersion.set(JavaLanguageVersion.of(8)) + } + withJavadocJar() withSourcesJar() } @@ -54,11 +58,6 @@ tasks.test { dependsOn(":scavenger-demo:build") } -tasks.withType { - sourceCompatibility = "8" - targetCompatibility = "8" -} - repositories { mavenCentral() } diff --git a/scavenger-api/build.gradle.kts b/scavenger-api/build.gradle.kts index c35cff3a..f9defe09 100644 --- a/scavenger-api/build.gradle.kts +++ b/scavenger-api/build.gradle.kts @@ -54,10 +54,13 @@ configure { } } +kotlin { + jvmToolchain(11) +} + tasks.withType { kotlinOptions { freeCompilerArgs = listOf("-Xjsr305=strict") - jvmTarget = "11" } } diff --git a/scavenger-collector/build.gradle.kts b/scavenger-collector/build.gradle.kts index a772ffff..161e7f31 100644 --- a/scavenger-collector/build.gradle.kts +++ b/scavenger-collector/build.gradle.kts @@ -68,10 +68,13 @@ configure { } } +kotlin { + jvmToolchain(11) +} + tasks.withType { kotlinOptions { freeCompilerArgs = listOf("-Xjsr305=strict") - jvmTarget = "11" } } diff --git a/scavenger-demo-extension/build.gradle.kts b/scavenger-demo-extension/build.gradle.kts index c03bbb54..57ed8083 100644 --- a/scavenger-demo-extension/build.gradle.kts +++ b/scavenger-demo-extension/build.gradle.kts @@ -5,8 +5,6 @@ plugins { kotlin("plugin.spring") version "1.8.10" } -java.sourceCompatibility = JavaVersion.VERSION_11 - repositories { mavenCentral() } @@ -16,10 +14,13 @@ dependencies { implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8") } +kotlin { + jvmToolchain(11) +} + tasks.withType { kotlinOptions { freeCompilerArgs = listOf("-Xjsr305=strict") - jvmTarget = "11" } } diff --git a/scavenger-demo/build.gradle.kts b/scavenger-demo/build.gradle.kts index 6c3ba5e5..e5ff6c77 100644 --- a/scavenger-demo/build.gradle.kts +++ b/scavenger-demo/build.gradle.kts @@ -7,8 +7,6 @@ plugins { kotlin("plugin.spring") version "1.8.10" } -java.sourceCompatibility = JavaVersion.VERSION_11 - repositories { mavenCentral() } @@ -30,10 +28,13 @@ dependencies { testImplementation("org.springframework.boot:spring-boot-starter-test") } +kotlin { + jvmToolchain(11) +} + tasks.withType { kotlinOptions { freeCompilerArgs = listOf("-Xjsr305=strict") - jvmTarget = "11" } } diff --git a/scavenger-entity/build.gradle.kts b/scavenger-entity/build.gradle.kts index 72d4b3e1..b61bb1df 100644 --- a/scavenger-entity/build.gradle.kts +++ b/scavenger-entity/build.gradle.kts @@ -11,6 +11,12 @@ dependencies { implementation("org.springframework.boot:spring-boot-starter-data-jdbc:2.5.12") } +java { + toolchain { + languageVersion.set(JavaLanguageVersion.of(11)) + } +} + repositories { mavenCentral() } diff --git a/scavenger-model/build.gradle.kts b/scavenger-model/build.gradle.kts index 16c2a623..e366a13d 100644 --- a/scavenger-model/build.gradle.kts +++ b/scavenger-model/build.gradle.kts @@ -1,9 +1,4 @@ -import com.google.protobuf.gradle.builtins -import com.google.protobuf.gradle.generateProtoTasks -import com.google.protobuf.gradle.id -import com.google.protobuf.gradle.plugins -import com.google.protobuf.gradle.protobuf -import com.google.protobuf.gradle.protoc +import com.google.protobuf.gradle.* plugins { java @@ -24,9 +19,8 @@ dependencies { implementation("javax.annotation:javax.annotation-api:1.3.2") } -tasks.withType { - sourceCompatibility = "8" - targetCompatibility = "8" +kotlin { + jvmToolchain(8) } protobuf { diff --git a/scavenger-schema/build.gradle.kts b/scavenger-schema/build.gradle.kts index 3b371f30..6be58306 100644 --- a/scavenger-schema/build.gradle.kts +++ b/scavenger-schema/build.gradle.kts @@ -1,3 +1,9 @@ plugins { java } + +java { + toolchain { + languageVersion.set(JavaLanguageVersion.of(11)) + } +} From 1fa38869c4c334f2bd1824f4d15ef72afb51282d Mon Sep 17 00:00:00 2001 From: Ohjun Kwon Date: Tue, 22 Aug 2023 15:36:33 +0900 Subject: [PATCH 28/30] Refactor codebase scan logic --- .../scavenger/javaagent/ScavengerAgent.java | 31 ++---------- .../javaagent/scheduling/Scheduler.java | 48 +++++++++++-------- .../javaagent/scheduling/SchedulerTest.java | 10 ++-- 3 files changed, 36 insertions(+), 53 deletions(-) diff --git a/scavenger-agent-java/src/main/java/com/navercorp/scavenger/javaagent/ScavengerAgent.java b/scavenger-agent-java/src/main/java/com/navercorp/scavenger/javaagent/ScavengerAgent.java index a11d3897..53220755 100644 --- a/scavenger-agent-java/src/main/java/com/navercorp/scavenger/javaagent/ScavengerAgent.java +++ b/scavenger-agent-java/src/main/java/com/navercorp/scavenger/javaagent/ScavengerAgent.java @@ -39,43 +39,18 @@ public static void premain(String args, Instrumentation inst) { new ScavengerBanner(config).printBanner(System.out); - CodeBase codeBase = null; + Scheduler scheduler = new Scheduler(config); if (!config.isAsyncCodeBaseScanMode()) { - codeBase = scanCodeBase(config); + boolean scanSuccessful = scheduler.scanCodeBase(); - if (codeBase == null) { + if (!scanSuccessful) { log.warning("[scavenger] scavenger is disabled"); return; } } InvocationTracker.installAdvice(inst, config); - - Scheduler scheduler = new Scheduler(config); - if (codeBase != null) { - scheduler.setCodeBasePublication(codeBase.toPublication(config)); - } scheduler.start(); - Runtime.getRuntime().addShutdownHook(new ShutdownHook(scheduler)); } - - static CodeBase scanCodeBase(Config config) { - CodeBase codeBase; - try { - codeBase = new CodeBaseScanner(config).scan(); - } catch (Throwable t) { - log.log(Level.SEVERE, "[scavenger] could not scan codebase", t); - return null; - } - - if (codeBase.getMethods().isEmpty()) { - log.severe("[scavenger] no methods are found"); - return null; - } else if (codeBase.getMethods().size() > 100000) { - log.severe("[scavenger] maximum methods count(100000) exceed: " + codeBase.getMethods().size()); - return null; - } - return codeBase; - } } diff --git a/scavenger-agent-java/src/main/java/com/navercorp/scavenger/javaagent/scheduling/Scheduler.java b/scavenger-agent-java/src/main/java/com/navercorp/scavenger/javaagent/scheduling/Scheduler.java index 78bdb89b..96e250da 100644 --- a/scavenger-agent-java/src/main/java/com/navercorp/scavenger/javaagent/scheduling/Scheduler.java +++ b/scavenger-agent-java/src/main/java/com/navercorp/scavenger/javaagent/scheduling/Scheduler.java @@ -23,29 +23,28 @@ public class Scheduler implements Runnable { private final Config config; private final Publisher publisher; + private final CodeBaseScanner codeBaseScanner; private final ScheduledExecutorService executor; private final SchedulerState pollState; private final SchedulerState codeBasePublisherState; private final SchedulerState invocationDataPublisherState; + private final int forceIntervalSeconds; + private GetConfigResponse dynamicConfig; - @Setter private CodeBasePublication codeBasePublication; private boolean isCodeBasePublished = false; private InvocationDataPublication invocationDataPublication; private String codeBaseFingerprint; - private int forceIntervalSeconds; - @Setter - private CodeBaseScanner codeBaseScanner; public Scheduler(Config config) { - this(config, new Publisher(config)); + this(config, new Publisher(config), new CodeBaseScanner(config)); } - public Scheduler(Config config, Publisher publisher) { + public Scheduler(Config config, Publisher publisher, CodeBaseScanner codeBaseScanner) { this.config = config; - this.codeBaseScanner = new CodeBaseScanner(config); + this.codeBaseScanner = codeBaseScanner; this.publisher = publisher; this.executor = Executors.newScheduledThreadPool( 1, @@ -157,22 +156,11 @@ public void publishCodeBaseIfNeeded() { if (!isCodeBasePublished && codeBasePublisherState.isDueTime() && dynamicConfig != null) { try { if (this.codeBasePublication == null) { - CodeBase codeBase; - try { - codeBase = codeBaseScanner.scan(); - } catch (Throwable e) { - log.log(Level.SEVERE, "[scavenger] code scanning is failed. Stop codebase publishing.", e); - return; - } + boolean scanSuccessful = scanCodeBase(); - if (codeBase.getMethods().isEmpty()) { - log.severe("[scavenger] no methods are found"); - return; - } else if (codeBase.getMethods().size() > 100000) { - log.severe("[scavenger] maximum methods count(100000) exceed: " + codeBase.getMethods().size()); + if (!scanSuccessful) { return; } - this.codeBasePublication = codeBase.toPublication(config); } this.publisher.publishCodeBase(codeBasePublication); @@ -186,6 +174,26 @@ public void publishCodeBaseIfNeeded() { } } + public boolean scanCodeBase() { + CodeBase codeBase; + try { + codeBase = codeBaseScanner.scan(); + } catch (Throwable e) { + log.log(Level.SEVERE, "[scavenger] code scanning is failed. Stop codebase publishing.", e); + return false; + } + + if (codeBase.getMethods().isEmpty()) { + log.severe("[scavenger] no methods are found"); + return false; + } else if (codeBase.getMethods().size() > 100000) { + log.severe("[scavenger] maximum methods count(100000) exceed: " + codeBase.getMethods().size()); + return false; + } + this.codeBasePublication = codeBase.toPublication(config); + return true; + } + public void publishInvocationDataIfNeeded() { if (invocationDataPublisherState.isDueTime() && dynamicConfig != null && isCodeBasePublished) { try { diff --git a/scavenger-agent-java/src/test/java/com/navercorp/scavenger/javaagent/scheduling/SchedulerTest.java b/scavenger-agent-java/src/test/java/com/navercorp/scavenger/javaagent/scheduling/SchedulerTest.java index dd67e166..8e50b0bf 100644 --- a/scavenger-agent-java/src/test/java/com/navercorp/scavenger/javaagent/scheduling/SchedulerTest.java +++ b/scavenger-agent-java/src/test/java/com/navercorp/scavenger/javaagent/scheduling/SchedulerTest.java @@ -80,12 +80,12 @@ private InvocationDataPublication.InvocationDataEntry newInvocationDataEntry(Str @BeforeEach public void setUp() { autoCloseable = MockitoAnnotations.openMocks(this); + when(codeBaseScannerMock.scan()) + .thenReturn( + new CodeBase(Collections.singletonList(Method.createTestMethod()), "fingerprint") + ); - Config config = new Config(new Properties()); - sut = new Scheduler(config, publisher); - - when(codeBaseScannerMock.scan()).thenReturn(new CodeBase(Collections.singletonList(Method.createTestMethod()), "fingerprint")); - sut.setCodeBaseScanner(codeBaseScannerMock); + sut = new Scheduler(new Config(new Properties()), publisher, codeBaseScannerMock); } @AfterEach From a6ce1b1bf1bbf7a9b623fcbde69e88771361fb5a Mon Sep 17 00:00:00 2001 From: Ohjun Kwon Date: Tue, 22 Aug 2023 16:19:12 +0900 Subject: [PATCH 29/30] Expose maxMethodsCount to config --- doc/installation.md | 1 + .../com/navercorp/scavenger/javaagent/model/Config.java | 2 ++ .../scavenger/javaagent/scheduling/Scheduler.java | 7 ++++--- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/doc/installation.md b/doc/installation.md index 36df059d..e6fd8b35 100644 --- a/doc/installation.md +++ b/doc/installation.md @@ -173,6 +173,7 @@ packages=com.navercorp | appVersion | unspecified |
  • Specify the application version. This option does not affect collection. Instead, it is useful if you want to specify which version of the application you are scaning.
  • ex) 1.0.0
  • | | hostname | |
  • Specifies that it should be recorded differently from the existing hostname. This option does not affect ingestion, but can be useful when determining which host the agent ran on.
  • | | debugMode | false |
  • You can check the logs to see which methods are being traced and whether they are being called. Enabling this mode will have a serious impact on the performance of your application, and we do not recommend using it outside of a development environment.
  • | +| maxMethodsCount | 100000 |
  • Sets a maximum limit on the number of methods that can be tracked.
  • | #### Installation diff --git a/scavenger-agent-java/src/main/java/com/navercorp/scavenger/javaagent/model/Config.java b/scavenger-agent-java/src/main/java/com/navercorp/scavenger/javaagent/model/Config.java index a9d5a645..b4cd30e8 100644 --- a/scavenger-agent-java/src/main/java/com/navercorp/scavenger/javaagent/model/Config.java +++ b/scavenger-agent-java/src/main/java/com/navercorp/scavenger/javaagent/model/Config.java @@ -47,6 +47,7 @@ public class Config { private int schedulerInitialDelayMillis = 10_000; private int schedulerIntervalMillis = 10_000; private Integer forceIntervalSeconds; + private Integer maxMethodsCount; private boolean asyncCodeBaseScanMode = false; private boolean legacyCompatibilityMode = false; @@ -80,6 +81,7 @@ public Config(Properties props) { schedulerInitialDelayMillis = getIntValue(props, "schedulerInitialDelayMillis", schedulerInitialDelayMillis); schedulerIntervalMillis = getIntValue(props, "schedulerIntervalMillis", schedulerIntervalMillis); forceIntervalSeconds = getIntValue(props, "forceIntervalSeconds", 0); + maxMethodsCount = getIntValue(props, "maxMethodsCount", 100000); asyncCodeBaseScanMode = getBooleanValue(props, "asyncCodeBaseScanMode", asyncCodeBaseScanMode); legacyCompatibilityMode = getBooleanValue(props, "legacyCompatibilityMode", legacyCompatibilityMode); diff --git a/scavenger-agent-java/src/main/java/com/navercorp/scavenger/javaagent/scheduling/Scheduler.java b/scavenger-agent-java/src/main/java/com/navercorp/scavenger/javaagent/scheduling/Scheduler.java index 96e250da..60d5cf55 100644 --- a/scavenger-agent-java/src/main/java/com/navercorp/scavenger/javaagent/scheduling/Scheduler.java +++ b/scavenger-agent-java/src/main/java/com/navercorp/scavenger/javaagent/scheduling/Scheduler.java @@ -7,7 +7,6 @@ import io.grpc.Status; import io.grpc.StatusRuntimeException; -import lombok.Setter; import lombok.extern.java.Log; import com.navercorp.scavenger.javaagent.collecting.CodeBaseScanner; @@ -31,6 +30,7 @@ public class Scheduler implements Runnable { private final SchedulerState invocationDataPublisherState; private final int forceIntervalSeconds; + private final int maxMethodsCount; private GetConfigResponse dynamicConfig; private CodeBasePublication codeBasePublication; @@ -55,6 +55,7 @@ public Scheduler(Config config, Publisher publisher, CodeBaseScanner codeBaseSca ); this.forceIntervalSeconds = this.config.getForceIntervalSeconds(); + this.maxMethodsCount = this.config.getMaxMethodsCount(); // these intervals will be updated when dynamic config is polled (not likely be used) int intervalSeconds = 600; int retryIntervalSeconds = 600; @@ -186,8 +187,8 @@ public boolean scanCodeBase() { if (codeBase.getMethods().isEmpty()) { log.severe("[scavenger] no methods are found"); return false; - } else if (codeBase.getMethods().size() > 100000) { - log.severe("[scavenger] maximum methods count(100000) exceed: " + codeBase.getMethods().size()); + } else if (codeBase.getMethods().size() > maxMethodsCount) { + log.severe("[scavenger] maximum methods count(" + maxMethodsCount + ") exceed: " + codeBase.getMethods().size()); return false; } this.codeBasePublication = codeBase.toPublication(config); From fbba51ed3d04f1cd02259231aaff896e71a355f8 Mon Sep 17 00:00:00 2001 From: Debugging Sparrow Date: Mon, 28 Aug 2023 09:34:16 +0900 Subject: [PATCH 30/30] Translate the python agent README.md into English (#58) --- README.md | 4 ++- scavenger-agent-python/README.md | 57 ++++++++++++++++++++++---------- 2 files changed, 42 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index e952ec64..3186bdc7 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ Scavenger provides more sophisticated and clear UI and elaborate the instrumenta ### Components -* Scavenger agent +* Scavenger Agent * Collect the code base and regularly send the invocations of the host application to collectors. * Scavenger Collector * Store the data received from the agent in the database. @@ -17,6 +17,8 @@ Scavenger provides more sophisticated and clear UI and elaborate the instrumenta * Provide APs for exploring invocations. * Scavenger Frontend * Provides UI. +* [Scavenger Python Agent (BETA)](https://github.com/naver/scavenger/blob/develop/scavenger-agent-python) + * Python agent of Scavenger Agent described above. # Features diff --git a/scavenger-agent-python/README.md b/scavenger-agent-python/README.md index 2d4dd851..f9feae49 100644 --- a/scavenger-agent-python/README.md +++ b/scavenger-agent-python/README.md @@ -1,42 +1,50 @@ # Scavenger Agent Python (BETA) -*(본 Agent는 베타 버전으로 현재 개발 환경에서만의 사용을 권장하며 상용 환경에서의 사용을 권장하지 않습니다.)* Scavenger Agent의 Python 버전으로, Agent가 아닌 [Server Component](../doc/installation.md)는 사전에 준비되어야 합니다. +*(This Agent is a beta version and is recommended for use only in development environment, not for production environments)* This Agent is a Python +version of Scavenger Agent, and [Server Component](../doc/installation.md) must be prepared in advance. -## 개발 가이드 +## Development Guide -Scavenger Agent Python은 패키지 관리자로 [Poetry](https://python-poetry.org/)를 이용합니다. +Scavenger Agent Python uses [Poetry](https://python-poetry.org/) as a package manager. + +- Install dependencies -- 의존성 설치 ```sh $ poetry install ``` -- 테스트 + +- Test + ```sh $ poetry run python -m unittest ``` -- 빌드 + +- Build + ```sh $ poetry build ``` -자세한 내용은 [Poetry Docs](https://python-poetry.org/docs/)를 참고해주세요. +For more information, please refer to [Poetry Docs](https://python-poetry.org/docs/). -## 에이전트 설치 가이드 +## Installation Guide -### 전제조건 +### Prerequisite `Python >= 3.7` -### 설치 +### Installation ``` $ pip install scavenger-agent-python --save ``` -### 설정 -설정은 설정 파일 `scavenger.conf`을 이용한 방식과 Config Instance를 직접 생성하는 두 가지 방식을 지원합니다. +### Configuration + +Configuration supports two methods: using the configuration file `scavenger.conf` or directly creating a `Config` instance. * Example of `scavenger.conf` + ```py # scavenger.conf apiKey=eb99ff0f-aaaa-bbbb-cccc-5d1ec81f6183 @@ -50,7 +58,9 @@ codebase=. config = Config.load_config() agent = Agent(config) ``` + * Example of `Config()` + ```py config = Config( api_key="eb99ff0f-aaaa-bbbb-cccc-5d1ec81f6183", @@ -63,8 +73,11 @@ config = Config( agent = Agent(config) ``` -### 에이전트 시작 -Scavenger Agent Python은 Scavenger Agent Java와 달리, Agent 시작 코드를 직접 삽입하는 방식으로 동작합니다. 수집을 시작할 함수의 모듈이 import되기 전에 Agent가 동작해야 하므로 *반드시 프로그램의 시작점에 Agent 시작 코드가 삽입되어야 함을 유의하십시오.* +### Agent Start + +Unlike Scavenger Agent Java, Scavenger Agent Python works by directly inserting the agent start code. *Note that the agent start code must be inserted +at the start point of the program*, because the agent must run before the module of the function to be collected is imported. + ```py from scavenger import Agent, Config @@ -76,8 +89,11 @@ agent.start() from ... ``` -### 한계 -* Graceful Shutdown에 대한 구현은 기존 프레임워크와의 충돌 가능성으로 인해 자동으로 지원하지 않습니다. 대신 아래와 같은 `agent.shutdown()` 함수를 지원하므로 직접 등록하여서 사용하여야 합니다. +### Limitations + +* The implementation of Graceful Shutdown is not automatically supported due to potential conflicts with existing frameworks. Instead, + the `agent.shutdown()` function as shown below is provided, so you must register it into your framework shutdown routine by yourself. + ```py def shutdown_gracefully(*args): # Shutdown your application/server first. @@ -87,7 +103,11 @@ def shutdown_gracefully(*args): signal.signal(signal.SIGTERM, shutdown_gracefully) agent.start() ``` -* Scavenger Python Agent는 현재 모듈/클래스의 레퍼런스를 대체하는 방식으로 동작하므로 레퍼런스를 사용하지 않고 함수를 호출하는 경우에는 동작하지 않습니다. 따라서 아래와 같이 Decorator를 이용해 함수의 레퍼런스만 따로 프레임워크에 저장해두는 경우, `def hello_world()`에는 동작하지 않습니다. 이는 추후 함수내 코드를 삽입하는 방식으로 변경되어 지원될 예정입니다. + +* Scavenger Python Agent works by replacing the reference of the current module/class, so it does not work by calling a function without using a + reference. Therefore, if only the function reference is saved in the framework using Decorator as shown below, `def hello_world()` will not work. + This will be changed and supported in the future by inserting code within the function. + ```py from flask import Flask app = Flask(__name__) @@ -96,4 +116,5 @@ app = Flask(__name__) def hello_world(): return 'Hello World!' ``` -* 코드를 직접 읽어서 메서드를 탐색해야 하므로 pyc 파일은 현재 지원되지 않습니다. + +* The direct Instrumentation for pyc files are currently not supported because Python code must be read by the scavenger agent.