Skip to content

Commit

Permalink
Merge pull request #111 from naver/develop
Browse files Browse the repository at this point in the history
Release v1.1.2

Reviewed-by: @kojandy @taeyeon-Kim
  • Loading branch information
sohyun-ku authored Jan 10, 2024
2 parents 29acd26 + 482bd0a commit 33fdb60
Show file tree
Hide file tree
Showing 14 changed files with 295 additions and 46 deletions.
2 changes: 1 addition & 1 deletion run-agent.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/bin/bash

./gradlew build -p scavenger-agent-java -x test
./gradlew build -p scavenger-agent-java -x test -x integrationTest
./gradlew build -p scavenger-demo -x test

java -Dscavenger.configuration=./scavenger-demo/scavenger.conf \
Expand Down
11 changes: 5 additions & 6 deletions scavenger-agent-java/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@ java {
withSourcesJar()
}

tasks.jar { enabled = false }

tasks.withType<ShadowJar> {
archiveFileName.set("${project.name}-${project.version}.jar")

Expand Down Expand Up @@ -64,9 +62,9 @@ repositories {

dependencies {
implementation(project(":scavenger-model"))
implementation("net.bytebuddy:byte-buddy:1.12.23")
implementation("org.ow2.asm:asm:9.4")
implementation("org.ow2.asm:asm-tree:9.4")
implementation("net.bytebuddy:byte-buddy:1.14.3")
implementation("org.ow2.asm:asm:9.5")
implementation("org.ow2.asm:asm-tree:9.5")
implementation("com.squareup.okhttp3:okhttp:3.14.9")
implementation("com.google.protobuf:protobuf-java-util:${property("protobufVersion")}")
implementation("io.grpc:grpc-stub:${property("grpcVersion")}")
Expand Down Expand Up @@ -100,6 +98,7 @@ val integrationTestRuntimeClasspath = configurations.named("integrationTestRunti

tasks.named<Test>("integrationTest") {
dependsOn(tasks.shadowJar)
mustRunAfter(tasks.jar)
shouldRunAfter(tasks.test)
useJUnitPlatform()

Expand All @@ -109,7 +108,7 @@ tasks.named<Test>("integrationTest") {

systemProperty("integrationTest.scavengerAgent", tasks.shadowJar.get().outputs.files.asPath)
systemProperty("integrationTest.classpath", "build/classes/java/integrationTest:$integrationTestRuntimeClasspath")
systemProperty("integrationTest.javaPaths", javaPaths(8, 11, 17))
systemProperty("integrationTest.javaPaths", javaPaths(8, 11, 17, 21))
}

tasks.withType<ProcessResources> {
Expand Down
2 changes: 1 addition & 1 deletion scavenger-api/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ dependencies {
implementation("org.liquibase:liquibase-core")
implementation("io.github.microutils:kotlin-logging-jvm:2.1.23")
implementation("net.ttddyy:datasource-proxy:1.7")
implementation("com.github.vertical-blank:sql-formatter:1.0.1")
implementation("com.github.vertical-blank:sql-formatter:2.0.4")
implementation("com.github.doyaaaaaken:kotlin-csv-jvm:1.9.0")
testImplementation("org.springframework.boot:spring-boot-starter-test")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ class SnapshotNodeService(
filteredMethodInvocations.forEach {
updateCountGraph(
current = root,
elements = splitSignature(it),
elements = splitSignatureWithType(it),
isUsed = it.invokedAtMillis > 0 && it.invokedAtMillis >= snapshotEntity.filterInvokedAtMillis,
invokedAtMillis = it.invokedAtMillis
)
Expand Down Expand Up @@ -75,22 +75,23 @@ class SnapshotNodeService(

private fun updateCountGraph(
current: Node,
elements: List<String>,
elements: List<SignatureWithType>,
isUsed: Boolean,
invokedAtMillis: Long
) {
var node = current
elements.forEach {
val signature = it.signature
updateCount(node, isUsed, invokedAtMillis)
if (it !in node.signatureChildMap) {
val delimiter = if (node.type == Node.Type.CLASS && !it.contains("(")) "$" else "."
val nextElementName = if (node.signature.isBlank()) it else "${node.signature}$delimiter$it"
node.signatureChildMap[it] = Node(
if (signature !in node.signatureChildMap) {
val delimiter = if (signature.contains("$")) "" else "."
val nextElementName = if (node.signature.isBlank()) signature else "${node.signature}$delimiter$signature"
node.signatureChildMap[signature] = Node(
signature = nextElementName,
type = getType(node, nextElementName)
type = it.type
)
}
node = node.signatureChildMap.getValue(it)
node = node.signatureChildMap.getValue(signature)
}
updateCount(node, isUsed, invokedAtMillis)
}
Expand All @@ -112,38 +113,38 @@ class SnapshotNodeService(
* "a.b.c.d(e, f)" to ["a", "b", "c", "d(e, f)"]
* "a.b.c.D(e, f)" to ["a", "b", "c", "D", "D(e, f)"]
*/
private fun splitSignature(methodInvocationEntity: MethodInvocationEntity): List<String> {
private fun splitSignatureWithType(methodInvocationEntity: MethodInvocationEntity): List<SignatureWithType> {
val (nameOnlySignature, arguments) = methodInvocationEntity.signature.split("(", limit = 2)

val elements = nameOnlySignature.split(*DELIMITERS)
val elements = nameOnlySignature.split("(?=\\b[.$])".toRegex())
.filterNot { it == "" }
.map { SignatureWithType(it.replace(".", "")) }
.toMutableList()

if (isConstructor(methodInvocationEntity)) {
elements.add(elements.last())
val constructorSignature = elements.last().signature
elements.add(SignatureWithType(constructorSignature.replace("$", "")))
}

elements[elements.size - 1] = "${elements.last()}($arguments" + if (arguments.last() != ')') ")" else ""
return elements
}
val lastElement = elements.removeLast()
elements.add(SignatureWithType("${lastElement.signature}($arguments" + if (arguments.last() != ')') ")" else ""))

private fun isConstructor(methodInvocationEntity: MethodInvocationEntity): Boolean {
return methodInvocationEntity.methodName == "<init>"
}

private fun getType(parent: Node, signature: String): Node.Type {
val isParentTypeClass = parent.type == Node.Type.CLASS
return if (isParentTypeClass && signature.contains("(")) {
Node.Type.METHOD
} else {
val split = signature.split(*DELIMITERS)
val firstOfLast = split.last()[0]
if (firstOfLast.uppercaseChar() == firstOfLast || isParentTypeClass /*Inner Class*/) {
elements.forEachIndexed { index, signatureWithType ->
val signature = signatureWithType.signature
signatureWithType.type = if (signature.contains("(")) {
Node.Type.METHOD
} else if (signature.contains("$") || elements[index + 1].signature.contains("[($]".toRegex())) {
Node.Type.CLASS
} else {
Node.Type.PACKAGE
}
}

return elements
}

private fun isConstructor(methodInvocationEntity: MethodInvocationEntity): Boolean {
return methodInvocationEntity.methodName == "<init>"
}

private fun serializeGraphAddToNodes(
Expand Down Expand Up @@ -179,6 +180,12 @@ class SnapshotNodeService(
)
}

data class SignatureWithType(
val signature: String,
) {
lateinit var type: Node.Type
}

data class Node(
val signature: String,
val type: Type,
Expand All @@ -194,6 +201,5 @@ class SnapshotNodeService(

companion object {
private const val BATCH_CHUNK_SIZE = 1000
private val DELIMITERS = arrayOf(".", "$")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ class ApplicationRepositoryTest {

@Test
fun findAllByCustomerId() {
assertThat(sut.findAllByCustomerId(1)).hasSize(1)
assertThat(sut.findAllByCustomerId(1)).hasSize(2)
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,14 +43,16 @@ class ArmeriaConfiguration(
@Bean
fun armeriaServiceInitializer(tomcatService: TomcatService): ArmeriaServerConfigurator {
return ArmeriaServerConfigurator { serviceBuilder: ServerBuilder ->
val maxMessageSize = maxMessageSize.toBytes().toInt()
serviceBuilder.service("prefix:/", tomcatService)
.service(GrpcService.builder()
.addService(grpcAgentController)
.addExceptionMapping(IllegalArgumentException::class.java, Status.INVALID_ARGUMENT)
.addExceptionMapping(LicenseKeyNotFoundException::class.java, Status.UNAUTHENTICATED)
.maxRequestMessageLength(maxMessageSize.toBytes().toInt())
.maxRequestMessageLength(maxMessageSize)
.build()
)
.maxRequestLength(maxMessageSize.toLong())
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -197,22 +197,22 @@ class GarbageCollectServiceTest {
sut.sweepMethods(customerId, min!!)
assertThat(methodDao.findAllByCustomerId(customerId))
.describedAs("nothing is deleted when the 1 week is not passed since last seen")
.hasSize(5)
.hasSize(34)
assertThat(invocationDao.findAllByCustomerId(customerId))
.describedAs("invocations should be same as before")
.hasSize(invocations.size)
sut.sweepMethods(customerId, min!!.plusSeconds(10))
assertThat(methodDao.findAllByCustomerId(customerId))
.describedAs("marked method is deleted when the more than 1 week is passed after last seen")
.hasSize(3)
.hasSize(32)
val invocationsAfter = invocationDao.findAllByCustomerId(customerId)
assertThat(invocationsAfter)
.describedAs("invocations should be deleted as well")
.hasSizeLessThan(invocations.size)
sut.sweepMethods(customerId, Instant.now())
assertThat(methodDao.findAllByCustomerId(customerId))
.describedAs("nothing more is deleted when no marking is done")
.hasSize(3)
.hasSize(32)
}

@Test
Expand All @@ -225,22 +225,22 @@ class GarbageCollectServiceTest {
sut.sweepMethods(customerId, min!!)
assertThat(methodDao.findAllByCustomerId(customerId))
.describedAs("nothing is deleted when the 1 week is not passed since last seen")
.hasSize(5)
.hasSize(34)
assertThat(invocationDao.findAllByCustomerId(customerId))
.describedAs("invocations should be same as before")
.hasSize(invocations.size)
sut.sweepMethods(customerId, min!!.plusSeconds(10))
assertThat(methodDao.findAllByCustomerId(customerId))
.describedAs("marked method is deleted when the more than 1 week is passed after last seen")
.hasSize(3)
.hasSize(32)
val invocationsAfter = invocationDao.findAllByCustomerId(customerId)
assertThat(invocationsAfter)
.describedAs("invocations should be deleted as well")
.hasSizeLessThan(invocations.size)
sut.sweepMethods(customerId, Instant.now())
assertThat(methodDao.findAllByCustomerId(customerId))
.describedAs("nothing more is deleted when no marking is done")
.hasSize(3)
.hasSize(32)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import com.example.demo.service.BridgeService
import com.example.demo.service.CglibProxyService
import com.example.demo.service.DynamicProxyService
import com.example.demo.service.PojoService
import com.example.demo.service2.TestService
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.RestController

Expand All @@ -14,13 +15,14 @@ class MyController(
private val myService: BridgeService,
private val dynamicProxyService: DynamicProxyService,
private val cglibProxyService: CglibProxyService,
private val asyncService: AsyncService
private val asyncService: AsyncService,
private val testService: TestService
): BaseController() {
@GetMapping("")
fun hello(): String {
dynamicProxyService.aspect()
cglibProxyService.aspect()
return "myservice called ${myService.doSth()} / pojoService called ${PojoService().pojoHello()}"
return "myservice called ${myService.doSth()} / pojoService called ${PojoService().pojoHello()} / myService2 called ${testService.call()}"
}

@GetMapping("/additional")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.example.demo.service2

import com.example.demo.annotation.ScavengerEnabled
import com.example.demo.service.MyInterface
import com.example.demo.service.MyParentService
import org.springframework.stereotype.Service

@ScavengerEnabled
@Service
class TestService : MyParentService(), MyInterface {
fun call(): String {
return "test"
}
}
13 changes: 12 additions & 1 deletion scavenger-frontend/src/components/snapshot/SnapshotDetail.vue
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ export default {
signature = candidate.signature;
} else {
signature = this.snapshotData.children
.find(child => querySignature.startsWith(child.signature)).signature;
.find(child => this.isStartsWithSignature(querySignature, child.signature)).signature;
}
await this.updateSnapshotData(signature);
}
Expand Down Expand Up @@ -328,6 +328,17 @@ export default {
resizeHorizontal(size) {
localStorage.setItem("scavenger.snapshot.horizontal-size", size);
},
isStartsWithSignature(querySignature, signature) {
if (!querySignature.startsWith(signature)) {
return false;
}
if (querySignature === signature) {
return true;
}
return querySignature.substring(signature.length).startsWith(".");
},
},
};
</script>
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
databaseChangeLog:
- include:
file: db/changelog/schema.sql
- include:
file: db/changelog/schema-1.1.2.sql
- include:
file: db/changelog/test-data-set.sql
context: local
- include:
file: db/changelog/test-data-set-1.1.2.sql
context: local
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
--changeset scavenger:3

ALTER TABLE snapshot_nodes MODIFY signature TEXT;
Loading

0 comments on commit 33fdb60

Please sign in to comment.