Skip to content

Commit 8930936

Browse files
committed
Add synchronization to buffer access and add log size limit
1 parent d81d740 commit 8930936

File tree

4 files changed

+61
-34
lines changed

4 files changed

+61
-34
lines changed

shared/src/commonMain/kotlin/org/jetbrains/kotlinconf/AppInit.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ private fun initKoin(
6060
): Koin {
6161
return startKoin {
6262
val appModule = module {
63-
single { BufferedDelegatingLogger() }
63+
single { BufferedDelegatingLogger(get()) }
6464
single<Logger> { get<BufferedDelegatingLogger>() }
6565

6666
single<ApplicationStorage> { MultiplatformSettingsStorage(get(), get()) }
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
package org.jetbrains.kotlinconf.utils
2+
3+
import kotlinx.coroutines.CoroutineScope
4+
import kotlinx.coroutines.launch
5+
import kotlinx.coroutines.sync.Mutex
6+
import kotlinx.coroutines.sync.withLock
7+
8+
/**
9+
* A logger that's constructed during startup and later attached to a real logger.
10+
* Until attached, it buffers log entries in memory. When [attach] is called,
11+
* it forwards the buffered entries to the attached logger in order, and from
12+
* that point on it delegates all calls directly.
13+
*/
14+
class BufferedDelegatingLogger(
15+
private val scope: CoroutineScope,
16+
) : Logger {
17+
private var delegate: Logger? = null
18+
19+
private data class Entry(val tag: String, val lazyMessage: () -> String)
20+
21+
private val mutex = Mutex()
22+
23+
private val buffer = mutableListOf<Entry>()
24+
25+
override fun log(tag: String, lazyMessage: () -> String) {
26+
val current = delegate
27+
if (current != null) {
28+
current.log(tag, lazyMessage)
29+
return
30+
}
31+
32+
scope.launch {
33+
mutex.withLock {
34+
buffer += Entry(tag, lazyMessage)
35+
while (buffer.size > MAX_LOG_MESSAGES_IN_MEMORY) {
36+
buffer.removeAt(0)
37+
}
38+
}
39+
}
40+
}
41+
42+
fun attach(realLogger: Logger) {
43+
require(delegate == null) { "Logger delegate was already set, this should only happen once" }
44+
45+
delegate = realLogger
46+
47+
scope.launch {
48+
mutex.withLock {
49+
buffer.forEach { entry ->
50+
realLogger.log(entry.tag, entry.lazyMessage)
51+
}
52+
buffer.clear()
53+
}
54+
}
55+
}
56+
}

shared/src/commonMain/kotlin/org/jetbrains/kotlinconf/utils/DebugLogger.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ class DebugLogger(private val platformLogger: Logger) : Logger {
1010

1111
override fun log(tag: String, lazyMessage: () -> String) {
1212
logs += "${Clock.System.now()} [${tag}] ${lazyMessage()}"
13+
while (logs.size > MAX_LOG_MESSAGES_IN_MEMORY) {
14+
logs.removeAt(0)
15+
}
1316
platformLogger.log(tag, lazyMessage)
1417
}
1518

shared/src/commonMain/kotlin/org/jetbrains/kotlinconf/utils/Logger.kt

Lines changed: 1 addition & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -21,36 +21,4 @@ class NoopProdLogger : Logger {
2121
}
2222
}
2323

24-
/**
25-
* A logger that's constructed during startup and later attached to a real logger.
26-
* Until attached, it buffers log entries in memory. When [attach] is called,
27-
* it forwards the buffered entries to the attached logger in order, and from
28-
* that point on it delegates all calls directly.
29-
*/
30-
class BufferedDelegatingLogger : Logger {
31-
private var delegate: Logger? = null
32-
33-
private data class Entry(val tag: String, val message: String)
34-
35-
private val buffer = mutableListOf<Entry>()
36-
37-
override fun log(tag: String, lazyMessage: () -> String) {
38-
val current = delegate
39-
if (current != null) {
40-
current.log(tag, lazyMessage)
41-
return
42-
}
43-
44-
buffer += Entry(tag, lazyMessage())
45-
}
46-
47-
fun attach(realLogger: Logger) {
48-
require(delegate == null) { "Logger delegate was already set, this should only happen once" }
49-
50-
buffer.forEach { entry ->
51-
realLogger.log(entry.tag) { entry.message }
52-
}
53-
buffer.clear()
54-
delegate = realLogger
55-
}
56-
}
24+
internal const val MAX_LOG_MESSAGES_IN_MEMORY = 200

0 commit comments

Comments
 (0)