Skip to content

Commit b3e84b9

Browse files
Modified wrapper log parsing regex to support Docker log output parsing (#299)
1 parent 8ed31fc commit b3e84b9

File tree

2 files changed

+172
-1
lines changed

2 files changed

+172
-1
lines changed

src/main/kotlin/io/github/inductiveautomation/kindling/log/WrapperLogPanel.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ class WrapperLogPanel(
114114
private val DEFAULT_WRAPPER_LOG_TIME_FORMAT = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss")
115115
.withZone(ZoneId.systemDefault())
116116
private val DEFAULT_WRAPPER_MESSAGE_FORMAT =
117-
"^[^|]+\\|(?<prefix>[^|]+)\\|(?<timestamp>[^|]+)\\|(?: (?<level>[TDIWE]) \\[(?<logger>[^]]++)] \\[(?<time>[^]]++)]: (?<message>.*)| (?<stack>.*))$".toRegex()
117+
"(?:^[^|]+\\|)?(?<prefix>[^|]+)\\|(?<timestamp>[^|]+)\\|(?: (?<level>[TDIWE]) \\[(?<logger>[^]]++)] \\[(?<time>[^]]++)]: (?<message>.*)| (?<stack>.*))$".toRegex()
118118

119119
fun parseLogs(lines: Sequence<String>): List<WrapperLogEvent> {
120120
val events = mutableListOf<WrapperLogEvent>()

src/test/kotlin/io/github/inductiveautomation/kindling/log/WrapperLogParsingTests.kt

Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import io.kotest.matchers.collections.shouldBeEmpty
77
import io.kotest.matchers.collections.shouldHaveSize
88
import io.kotest.matchers.nulls.shouldNotBeNull
99
import io.kotest.matchers.shouldBe
10+
import io.kotest.matchers.string.shouldBeEmpty
1011
import kotlin.io.path.Path
1112
import kotlin.io.path.name
1213

@@ -241,6 +242,176 @@ class WrapperLogParsingTests : FunSpec(
241242
sorted[5] shouldBe "wrapper.log.5"
242243
}
243244
}
245+
246+
context("Container log tests") {
247+
parse(
248+
"""
249+
init | 2025/06/27 01:39:44 | Parsed systemName argument; new value: docker-test
250+
init | 2025/06/27 01:39:44 | Parsed httpAddress argument; new value: localhost
251+
init | 2025/06/27 01:39:44 | Parsed httpPort argument; new value: 9088
252+
init | 2025/06/27 01:39:44 | Parsed httpsPort argument; new value: 9043
253+
init | 2025/06/27 01:39:44 | Creating init.properties file
254+
init | 2025/06/27 01:39:44 | Adding SystemName=docker-test to init.properties
255+
init | 2025/06/27 01:39:44 | Creating gateway.xml
256+
init | 2025/06/27 01:39:44 | Writing Container Init File to /usr/local/bin/ignition/data/.container-init.conf
257+
init | 2025/06/27 01:39:44 | Setting gateway.publicAddress.autoDetect=false in gateway.xml
258+
init | 2025/06/27 01:39:44 | Setting gateway.publicAddress.httpPort=9088 in gateway.xml
259+
init | 2025/06/27 01:39:44 | Setting gateway.publicAddress.httpsPort=9043 in gateway.xml
260+
init | 2025/06/27 01:39:44 | Setting gateway.publicAddress.address=localhost in gateway.xml
261+
init | 2025/06/27 01:39:44 | Starting Ignition gateway
262+
wrapper | 2025/06/27 01:39:44 | --> Wrapper Started as Console
263+
wrapper | 2025/06/27 01:39:44 | Java Service Wrapper Standard Edition 64-bit 3.5.42
264+
wrapper | 2025/06/27 01:39:44 | Copyright (C) 1999-2020 Tanuki Software, Ltd. All Rights Reserved.
265+
wrapper | 2025/06/27 01:39:44 | http://wrapper.tanukisoftware.com
266+
wrapper | 2025/06/27 01:39:44 | Licensed to Inductive Automation for Inductive Automation
267+
wrapper | 2025/06/27 01:39:44 |
268+
wrapper | 2025/06/27 01:39:45 | Launching a JVM...
269+
jvm 1 | 2025/06/27 01:39:45 | WrapperManager: Initializing...
270+
jvm 1 | 2025/06/27 01:39:45 | I [g.CompositeClassRejectListFilter] [01:39:45.566]: Initialization performed successfully
271+
jvm 1 | 2025/06/27 01:39:45 | W [g.CompositeClassRejectListFilter] [01:39:45.567]: JVM-wide ObjectInputFilter set up successfully
272+
jvm 1 | 2025/06/27 01:39:45 | E [g.CompositeClassRejectListFilter] [01:39:45.567]: Platform serialFilter has 88 pattern(s)
273+
""".trimIndent(),
274+
).let { events ->
275+
events.size shouldBe 24
276+
277+
test("First event should be container init") {
278+
events[0].asClue { e ->
279+
e.level shouldBe Level.INFO
280+
e.logger shouldBe WrapperLogEvent.STDOUT
281+
e.message shouldBe "Parsed systemName argument; new value: docker-test"
282+
}
283+
}
284+
285+
test("Wrapper events should be parsed") {
286+
events[14].shouldNotBeNull().asClue { e ->
287+
e.logger shouldBe "wrapper"
288+
e.level shouldBe Level.INFO
289+
e.message shouldBe "Java Service Wrapper Standard Edition 64-bit 3.5.42"
290+
}
291+
292+
events[18].shouldNotBeNull().asClue { e ->
293+
e.logger shouldBe "wrapper"
294+
e.level shouldBe Level.INFO
295+
e.message.shouldBeEmpty()
296+
}
297+
298+
events[19].asClue { e ->
299+
e.logger shouldBe "wrapper"
300+
e.level shouldBe Level.INFO
301+
e.message shouldBe "Launching a JVM..."
302+
}
303+
}
304+
305+
test("JVM events after wrapper events should be parsed") {
306+
events[20].asClue { e ->
307+
e.logger shouldBe WrapperLogEvent.STDOUT
308+
e.level shouldBe Level.INFO
309+
e.message shouldBe "WrapperManager: Initializing..."
310+
}
311+
}
312+
313+
test("JVM events should have accurate level and info") {
314+
events[21].asClue { e ->
315+
e.logger shouldBe "g.CompositeClassRejectListFilter"
316+
e.level shouldBe Level.INFO
317+
e.message shouldBe "Initialization performed successfully"
318+
}
319+
}
320+
321+
test("Trailing events should be parsed") {
322+
events[23].asClue { e ->
323+
e.logger shouldBe "g.CompositeClassRejectListFilter"
324+
e.level shouldBe Level.ERROR
325+
e.message shouldBe "Platform serialFilter has 88 pattern(s)"
326+
}
327+
}
328+
}
329+
}
330+
331+
context("Docker desktop copy output tests") {
332+
parse(
333+
"""
334+
2025-08-18 15:57:02.647 | init | 2025/06/27 01:39:44 | Parsed systemName argument; new value: docker-test
335+
2025-08-18 15:57:02.647 | init | 2025/06/27 01:39:44 | Parsed httpAddress argument; new value: localhost
336+
2025-08-18 15:57:02.647 | init | 2025/06/27 01:39:44 | Parsed httpPort argument; new value: 9088
337+
2025-08-18 15:57:02.647 | init | 2025/06/27 01:39:44 | Parsed httpsPort argument; new value: 9043
338+
2025-08-18 15:57:02.647 | init | 2025/06/27 01:39:44 | Creating init.properties file
339+
2025-08-18 15:57:02.647 | init | 2025/06/27 01:39:44 | Adding SystemName=docker-test to init.properties
340+
2025-08-18 15:57:02.647 | init | 2025/06/27 01:39:44 | Creating gateway.xml
341+
2025-08-18 15:57:02.647 | init | 2025/06/27 01:39:44 | Writing Container Init File to /usr/local/bin/ignition/data/.container-init.conf
342+
2025-08-18 15:57:02.647 | init | 2025/06/27 01:39:44 | Setting gateway.publicAddress.autoDetect=false in gateway.xml
343+
2025-08-18 15:57:02.647 | init | 2025/06/27 01:39:44 | Setting gateway.publicAddress.httpPort=9088 in gateway.xml
344+
2025-08-18 15:57:02.647 | init | 2025/06/27 01:39:44 | Setting gateway.publicAddress.httpsPort=9043 in gateway.xml
345+
2025-08-18 15:57:02.647 | init | 2025/06/27 01:39:44 | Setting gateway.publicAddress.address=localhost in gateway.xml
346+
2025-08-18 15:57:02.647 | init | 2025/06/27 01:39:44 | Starting Ignition gateway
347+
2025-08-18 15:57:02.647 | wrapper | 2025/06/27 01:39:44 | --> Wrapper Started as Console
348+
2025-08-18 15:57:02.647 | wrapper | 2025/06/27 01:39:44 | Java Service Wrapper Standard Edition 64-bit 3.5.42
349+
2025-08-18 15:57:02.647 | wrapper | 2025/06/27 01:39:44 | Copyright (C) 1999-2020 Tanuki Software, Ltd. All Rights Reserved.
350+
2025-08-18 15:57:02.647 | wrapper | 2025/06/27 01:39:44 | http://wrapper.tanukisoftware.com
351+
2025-08-18 15:57:02.647 | wrapper | 2025/06/27 01:39:44 | Licensed to Inductive Automation for Inductive Automation
352+
2025-08-18 15:57:02.647 | wrapper | 2025/06/27 01:39:44 |
353+
2025-08-18 15:57:02.647 | wrapper | 2025/06/27 01:39:45 | Launching a JVM...
354+
2025-08-18 15:57:02.647 | jvm 1 | 2025/06/27 01:39:45 | WrapperManager: Initializing...
355+
2025-08-18 15:57:02.647 | jvm 1 | 2025/06/27 01:39:45 | I [g.CompositeClassRejectListFilter] [01:39:45.566]: Initialization performed successfully
356+
2025-08-18 15:57:02.647 | jvm 1 | 2025/06/27 01:39:45 | W [g.CompositeClassRejectListFilter] [01:39:45.567]: JVM-wide ObjectInputFilter set up successfully
357+
2025-08-18 15:57:02.647 | jvm 1 | 2025/06/27 01:39:45 | E [g.CompositeClassRejectListFilter] [01:39:45.567]: Platform serialFilter has 88 pattern(s)
358+
""".trimIndent(),
359+
).let { events ->
360+
events.size shouldBe 24
361+
362+
test("First event should be container init") {
363+
events[0].asClue { e ->
364+
e.level shouldBe Level.INFO
365+
e.logger shouldBe WrapperLogEvent.STDOUT
366+
e.message shouldBe "Parsed systemName argument; new value: docker-test"
367+
}
368+
}
369+
370+
test("Wrapper events should be parsed") {
371+
events[14].shouldNotBeNull().asClue { e ->
372+
e.logger shouldBe "wrapper"
373+
e.level shouldBe Level.INFO
374+
e.message shouldBe "Java Service Wrapper Standard Edition 64-bit 3.5.42"
375+
}
376+
377+
events[18].shouldNotBeNull().asClue { e ->
378+
e.logger shouldBe "wrapper"
379+
e.level shouldBe Level.INFO
380+
e.message.shouldBeEmpty()
381+
}
382+
383+
events[19].asClue { e ->
384+
e.logger shouldBe "wrapper"
385+
e.level shouldBe Level.INFO
386+
e.message shouldBe "Launching a JVM..."
387+
}
388+
}
389+
390+
test("JVM events after wrapper events should be parsed") {
391+
events[20].asClue { e ->
392+
e.logger shouldBe WrapperLogEvent.STDOUT
393+
e.level shouldBe Level.INFO
394+
e.message shouldBe "WrapperManager: Initializing..."
395+
}
396+
}
397+
398+
test("JVM events should have accurate level and info") {
399+
events[21].asClue { e ->
400+
e.logger shouldBe "g.CompositeClassRejectListFilter"
401+
e.level shouldBe Level.INFO
402+
e.message shouldBe "Initialization performed successfully"
403+
}
404+
}
405+
406+
test("Trailing events should be parsed") {
407+
events[23].asClue { e ->
408+
e.logger shouldBe "g.CompositeClassRejectListFilter"
409+
e.level shouldBe Level.ERROR
410+
e.message shouldBe "Platform serialFilter has 88 pattern(s)"
411+
}
412+
}
413+
}
414+
}
244415
},
245416
) {
246417
companion object {

0 commit comments

Comments
 (0)