Skip to content

Commit 83159d0

Browse files
authored
Merge pull request #407 from enigbe/2024-11-configurable-logging-system
undefined
2 parents 0558d91 + e509cf8 commit 83159d0

File tree

27 files changed

+561
-240
lines changed

27 files changed

+561
-240
lines changed

Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ libc = "0.2"
8080
uniffi = { version = "0.27.3", features = ["build"], optional = true }
8181
serde = { version = "1.0.210", default-features = false, features = ["std", "derive"] }
8282
serde_json = { version = "1.0.128", default-features = false, features = ["std"] }
83+
log = { version = "0.4.22", default-features = false, features = ["std"]}
8384

8485
vss-client = "0.3"
8586
prost = { version = "0.11.6", default-features = false}

bindings/kotlin/ldk-node-android/lib/src/androidTest/kotlin/org/lightningdevkit/ldknode/AndroidLibTest.kt

+5-10
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,16 @@
33
*/
44
package org.lightningdevkit.ldknode
55

6-
import kotlin.UInt
7-
import kotlin.test.Test
8-
import kotlin.test.assertEquals
6+
import androidx.test.ext.junit.runners.AndroidJUnit4
97
import kotlin.io.path.createTempDirectory
8+
import kotlin.test.Test
109
import org.junit.runner.RunWith
11-
import org.lightningdevkit.ldknode.*;
12-
import android.content.Context.MODE_PRIVATE
13-
import androidx.test.core.app.ApplicationProvider
14-
import androidx.test.ext.junit.runners.AndroidJUnit4
10+
import org.lightningdevkit.ldknode.*
1511

1612
@RunWith(AndroidJUnit4::class)
1713
class AndroidLibTest {
18-
@Test fun node_start_stop() {
14+
@Test
15+
fun node_start_stop() {
1916
val tmpDir1 = createTempDirectory("ldk_node").toString()
2017
println("Random dir 1: $tmpDir1")
2118
val tmpDir2 = createTempDirectory("ldk_node").toString()
@@ -28,13 +25,11 @@ class AndroidLibTest {
2825
config1.storageDirPath = tmpDir1
2926
config1.listeningAddresses = listOf(listenAddress1)
3027
config1.network = Network.REGTEST
31-
config1.logLevel = LogLevel.TRACE
3228

3329
val config2 = defaultConfig()
3430
config2.storageDirPath = tmpDir2
3531
config2.listeningAddresses = listOf(listenAddress2)
3632
config2.network = Network.REGTEST
37-
config2.logLevel = LogLevel.TRACE
3833

3934
val builder1 = Builder.fromConfig(config1)
4035
val builder2 = Builder.fromConfig(config2)

bindings/kotlin/ldk-node-jvm/lib/src/test/kotlin/org/lightningdevkit/ldknode/LibraryTest.kt

+64-2
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import java.net.http.HttpRequest
99
import java.net.http.HttpResponse
1010
import kotlin.io.path.createTempDirectory
1111
import kotlin.test.assertEquals
12+
import kotlin.test.assertTrue
1213

1314
fun runCommandAndWait(vararg cmd: String): String {
1415
println("Running command \"${cmd.joinToString(" ")}\"")
@@ -92,6 +93,60 @@ fun waitForBlock(esploraEndpoint: String, blockHash: String) {
9293
}
9394
}
9495

96+
class CustomLogWriter(private var currentLogLevel: LogLevel = LogLevel.INFO) :
97+
LogWriter {
98+
enum class LogLevel {
99+
ERROR, WARN, INFO, DEBUG, TRACE, GOSSIP
100+
}
101+
102+
private val logMessages = mutableListOf<String>()
103+
104+
fun setLogLevel(level: LogLevel) {
105+
currentLogLevel = level
106+
}
107+
108+
fun getLogMessages(): List<String> {
109+
return logMessages.toList()
110+
}
111+
112+
override fun log(record: LogRecord) {
113+
val recordLevel =
114+
when (record.level.toString().lowercase()) {
115+
"error" -> LogLevel.ERROR
116+
"warn" -> LogLevel.WARN
117+
"info" -> LogLevel.INFO
118+
"debug" -> LogLevel.DEBUG
119+
"trace" -> LogLevel.TRACE
120+
"gossip" -> LogLevel.GOSSIP
121+
else -> LogLevel.INFO
122+
}
123+
124+
if (isLevelEnabled(recordLevel)) {
125+
val logMessage = formatRecord(record)
126+
logMessages.add(logMessage)
127+
println("$logMessage")
128+
}
129+
}
130+
131+
private fun formatRecord(record: LogRecord): String {
132+
val timestamp =
133+
java.time.LocalDateTime.now()
134+
.format(java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))
135+
return String.format(
136+
"%s %-6s [%s:%s] %s\n",
137+
timestamp,
138+
record.level,
139+
record.modulePath,
140+
record.line,
141+
record.args
142+
)
143+
}
144+
145+
private fun isLevelEnabled(level: LogLevel): Boolean {
146+
return level.ordinal <= currentLogLevel.ordinal
147+
}
148+
}
149+
95150
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
96151
class LibraryTest {
97152

@@ -106,6 +161,9 @@ class LibraryTest {
106161
}
107162

108163
@Test fun fullCycle() {
164+
val logWriter1 = CustomLogWriter(CustomLogWriter.LogLevel.GOSSIP)
165+
val logWriter2 = CustomLogWriter(CustomLogWriter.LogLevel.GOSSIP)
166+
109167
val tmpDir1 = createTempDirectory("ldk_node").toString()
110168
println("Random dir 1: $tmpDir1")
111169
val tmpDir2 = createTempDirectory("ldk_node").toString()
@@ -118,21 +176,22 @@ class LibraryTest {
118176
config1.storageDirPath = tmpDir1
119177
config1.listeningAddresses = listOf(listenAddress1)
120178
config1.network = Network.REGTEST
121-
config1.logLevel = LogLevel.TRACE
122179

123180
println("Config 1: $config1")
124181

125182
val config2 = defaultConfig()
126183
config2.storageDirPath = tmpDir2
127184
config2.listeningAddresses = listOf(listenAddress2)
128185
config2.network = Network.REGTEST
129-
config2.logLevel = LogLevel.TRACE
130186
println("Config 2: $config2")
131187

132188
val builder1 = Builder.fromConfig(config1)
133189
builder1.setChainSourceEsplora(esploraEndpoint, null)
190+
builder1.setCustomLogger(logWriter1)
191+
134192
val builder2 = Builder.fromConfig(config2)
135193
builder2.setChainSourceEsplora(esploraEndpoint, null)
194+
builder2.setCustomLogger(logWriter2)
136195

137196
val node1 = builder1.build()
138197
val node2 = builder2.build()
@@ -265,6 +324,9 @@ class LibraryTest {
265324
assert(spendableBalance1AfterClose < 100000u)
266325
assertEquals(102500uL, spendableBalance2AfterClose)
267326

327+
assertTrue(logWriter1.getLogMessages().isNotEmpty())
328+
assertTrue(logWriter2.getLogMessages().isNotEmpty())
329+
268330
node1.stop()
269331
node2.stop()
270332
}

bindings/ldk_node.udl

+24-11
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,11 @@ namespace ldk_node {
55

66
dictionary Config {
77
string storage_dir_path;
8-
string? log_file_path;
98
Network network;
109
sequence<SocketAddress>? listening_addresses;
1110
NodeAlias? node_alias;
1211
sequence<PublicKey> trusted_peers_0conf;
1312
u64 probing_liquidity_limit_multiplier;
14-
LogLevel log_level;
1513
AnchorChannelsConfig? anchor_channels_config;
1614
SendingParameters? sending_parameters;
1715
};
@@ -27,6 +25,27 @@ dictionary EsploraSyncConfig {
2725
u64 fee_rate_cache_update_interval_secs;
2826
};
2927

28+
enum LogLevel {
29+
"Gossip",
30+
"Trace",
31+
"Debug",
32+
"Info",
33+
"Warn",
34+
"Error",
35+
};
36+
37+
dictionary LogRecord {
38+
LogLevel level;
39+
string args;
40+
string module_path;
41+
u32 line;
42+
};
43+
44+
[Trait, WithForeign]
45+
interface LogWriter {
46+
void log(LogRecord record);
47+
};
48+
3049
interface Builder {
3150
constructor();
3251
[Name=from_config]
@@ -41,6 +60,9 @@ interface Builder {
4160
void set_gossip_source_rgs(string rgs_server_url);
4261
void set_liquidity_source_lsps2(SocketAddress address, PublicKey node_id, string? token);
4362
void set_storage_dir_path(string storage_dir_path);
63+
void set_filesystem_logger(string? log_file_path, LogLevel? log_level);
64+
void set_log_facade_logger(LogLevel log_level);
65+
void set_custom_logger(LogWriter log_writer);
4466
void set_network(Network network);
4567
[Throws=BuildError]
4668
void set_listening_addresses(sequence<SocketAddress> listening_addresses);
@@ -535,15 +557,6 @@ interface MaxDustHTLCExposure {
535557
FeeRateMultiplier ( u64 multiplier );
536558
};
537559

538-
enum LogLevel {
539-
"Gossip",
540-
"Trace",
541-
"Debug",
542-
"Info",
543-
"Warn",
544-
"Error",
545-
};
546-
547560
interface NetworkGraph {
548561
sequence<u64> list_channels();
549562
ChannelInfo? channel(u64 short_channel_id);

0 commit comments

Comments
 (0)