diff --git a/boot/src/test/kotlin/integration/breakpoint/MaxObjectDepthControlTest.kt b/boot/src/test/kotlin/integration/breakpoint/MaxObjectDepthControlTest.kt index 967e3922..d2f69c23 100644 --- a/boot/src/test/kotlin/integration/breakpoint/MaxObjectDepthControlTest.kt +++ b/boot/src/test/kotlin/integration/breakpoint/MaxObjectDepthControlTest.kt @@ -39,10 +39,11 @@ class MaxObjectDepthControlTest : ProbeIntegrationTest() { private fun doTest() { val deepObject1 = DeepObject1() val deepObject11 = DeepObject1() + val deeperObject1 = DeeperObject1() } @Test - fun testVariableControl() = runBlocking { + fun `max depth variable control`(): Unit = runBlocking { val testContext = VertxTestContext() val consumer = vertx.eventBus().localConsumer(toLiveInstrumentSubscriberAddress("system")) consumer.handler { @@ -51,7 +52,57 @@ class MaxObjectDepthControlTest : ProbeIntegrationTest() { if (event.eventType == LiveInstrumentEventType.BREAKPOINT_HIT) { val item = LiveBreakpointHit(JsonObject(event.data)) val vars = item.stackTrace.first().variables - assertEquals(3, vars.size) + assertEquals(4, vars.size) + + //deeperObject1 is full depth + var deeperObject1 = (vars.first { it.name == "deeperObject1" }.value as JsonArray) + .first() as JsonObject + deeperObject1 = deeperObject1.getJsonArray("value").first() as JsonObject + deeperObject1 = deeperObject1.getJsonArray("value").first() as JsonObject + deeperObject1 = deeperObject1.getJsonArray("value").first() as JsonObject + deeperObject1 = deeperObject1.getJsonArray("value").first() as JsonObject + deeperObject1 = deeperObject1.getJsonArray("value").first() as JsonObject + deeperObject1 = deeperObject1.getJsonArray("value").first() as JsonObject + assertEquals(0, deeperObject1.getJsonArray("value").size()) + + consumer.unregister() + testContext.completeNow() + } + } + }.completionHandler().await() + + assertNotNull( + instrumentService.addLiveInstrument( + LiveBreakpoint( + variableControl = LiveVariableControl( + maxObjectDepth = 8 + ), + location = LiveSourceLocation(MaxObjectDepthControlTest::class.qualifiedName!!, 43), + applyImmediately = true + ) + ).await() + ) + + //trigger breakpoint + doTest() + + errorOnTimeout(testContext) + + //clean up + consumer.unregister() + } + + @Test + fun `max depth variable control by name`(): Unit = runBlocking { + val testContext = VertxTestContext() + val consumer = vertx.eventBus().localConsumer(toLiveInstrumentSubscriberAddress("system")) + consumer.handler { + testContext.verify { + val event = LiveInstrumentEvent(it.body()) + if (event.eventType == LiveInstrumentEventType.BREAKPOINT_HIT) { + val item = LiveBreakpointHit(JsonObject(event.data)) + val vars = item.stackTrace.first().variables + assertEquals(4, vars.size) //deepObject1 is not full depth var deepObject1 = (vars.first { it.name == "deepObject1" }.value as JsonArray) @@ -90,7 +141,7 @@ class MaxObjectDepthControlTest : ProbeIntegrationTest() { ) ) ), - location = LiveSourceLocation(MaxObjectDepthControlTest::class.qualifiedName!!, 41), + location = LiveSourceLocation(MaxObjectDepthControlTest::class.qualifiedName!!, 43), applyImmediately = true ) ).await() @@ -127,4 +178,35 @@ class MaxObjectDepthControlTest : ProbeIntegrationTest() { } } } + + class DeeperObject1 { + val deeperObject2 = DeeperObject2() + + class DeeperObject2 { + val deeperObject3 = DeeperObject3() + + class DeeperObject3 { + val deeperObject4 = DeeperObject4() + + class DeeperObject4 { + val deeperObject5 = DeeperObject5() + + class DeeperObject5 { + val deeperObject6 = DeeperObject6() + + class DeeperObject6 { + val deeperObject7 = DeeperObject7() + + class DeeperObject7 { + val deeperObject8 = DeeperObject8() + + class DeeperObject8 { + } + } + } + } + } + } + } + } } diff --git a/services/src/main/kotlin/spp/probe/services/common/serialize/CappedTypeAdapterFactory.kt b/services/src/main/kotlin/spp/probe/services/common/serialize/CappedTypeAdapterFactory.kt index 18c7d98c..db2e92fb 100644 --- a/services/src/main/kotlin/spp/probe/services/common/serialize/CappedTypeAdapterFactory.kt +++ b/services/src/main/kotlin/spp/probe/services/common/serialize/CappedTypeAdapterFactory.kt @@ -330,11 +330,16 @@ class CappedTypeAdapterFactory : TypeAdapterFactory { } fun getDefaultMaxDepth(): Int { + //check live breakpoint config (only default max depth) + ModelSerializer.INSTANCE.rootBreakpoint.get()?.variableControl?.let { + it.maxObjectDepth?.let { return it } + } + return ProbeConfiguration.variableControl.getInteger("max_object_depth") } fun getCustomMaxDepth(variableName: String?, value: Any): Int { - //check live breakpoint config + //check live breakpoint config (minus default max depth) ModelSerializer.INSTANCE.rootBreakpoint.get()?.variableControl?.let { if (variableName != null) { it.variableNameConfig[variableName]?.let { @@ -344,7 +349,6 @@ class CappedTypeAdapterFactory : TypeAdapterFactory { it.variableTypeConfig[getTypeName(value)]?.let { it.maxObjectDepth?.let { return it } } - it.maxObjectDepth?.let { return it } } //check spp-probe.yml config