From 0ba57509a038dc0161b11b1be1aef2b360bd006b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vlado=20Paji=C4=87?= Date: Wed, 29 Jul 2026 18:36:02 +0200 Subject: [PATCH 01/19] logs filter --- CMakeLists.txt | 17 +++++++++++++ flake.lock | 8 +++--- flake.nix | 2 +- src/plugin.cpp | 18 +++++++++++++ src/plugin.h | 12 +++++++++ tutorial/docs/tutorial_0_introduction.md | 25 +++++++++++++++++-- tutorial/docs/tutorial_10_peerstore.md | 7 ++++++ tutorial/docs/tutorial_11_circuit_relay.md | 7 ++++++ tutorial/docs/tutorial_1_node_lifecycle.md | 7 ++++++ tutorial/docs/tutorial_2_custom_config.md | 7 ++++++ tutorial/docs/tutorial_3_connecting_peers.md | 7 ++++++ tutorial/docs/tutorial_4_custom_protocol.md | 7 ++++++ tutorial/docs/tutorial_5_kademlia_basics.md | 7 ++++++ .../docs/tutorial_6_kademlia_providers.md | 6 +++++ tutorial/docs/tutorial_7_gossipsub_polling.md | 7 ++++++ .../tutorial_8_gossipsub_event_callback.md | 7 ++++++ tutorial/docs/tutorial_9_service_discovery.md | 7 ++++++ tutorial/tutorial_0_introduction.cpp | 25 +++++++++++++++++-- tutorial/tutorial_10_peerstore.cpp | 7 ++++++ tutorial/tutorial_11_circuit_relay.cpp | 7 ++++++ tutorial/tutorial_1_node_lifecycle.cpp | 7 ++++++ tutorial/tutorial_2_custom_config.cpp | 7 ++++++ tutorial/tutorial_3_connecting_peers.cpp | 7 ++++++ tutorial/tutorial_4_custom_protocol.cpp | 7 ++++++ tutorial/tutorial_5_kademlia_basics.cpp | 7 ++++++ tutorial/tutorial_6_kademlia_providers.cpp | 6 +++++ tutorial/tutorial_7_gossipsub_polling.cpp | 7 ++++++ .../tutorial_8_gossipsub_event_callback.cpp | 7 ++++++ tutorial/tutorial_9_service_discovery.cpp | 7 ++++++ 29 files changed, 250 insertions(+), 9 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c4e7871..2449b1d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,8 @@ cmake_minimum_required(VERSION 3.14) project(Libp2pModulePlugin LANGUAGES CXX) +include(CheckCXXSourceCompiles) + if(DEFINED ENV{LOGOS_MODULE_BUILDER_ROOT}) include($ENV{LOGOS_MODULE_BUILDER_ROOT}/cmake/LogosModule.cmake) else() @@ -31,4 +33,19 @@ logos_module( tinycbor ) +set(CMAKE_REQUIRED_INCLUDES ${LIBP2P_INCLUDE_DIR}) +check_cxx_source_compiles(" + #include + int main() { + auto fn = &libp2p_ctx_set_log_level; + (void)fn; + return 0; + } +" HAVE_LIBP2P_CTX_SET_LOG_LEVEL) + +if(HAVE_LIBP2P_CTX_SET_LOG_LEVEL) + target_compile_definitions(libp2p_module_module_plugin + PRIVATE HAVE_LIBP2P_CTX_SET_LOG_LEVEL) +endif() + add_subdirectory(tutorial) diff --git a/flake.lock b/flake.lock index e5c2506..2d40250 100644 --- a/flake.lock +++ b/flake.lock @@ -148,16 +148,16 @@ "nixpkgs": "nixpkgs" }, "locked": { - "lastModified": 1785247914, - "narHash": "sha256-W15T9ugMOkwjlySOpDxqK8UzCz4eCFMCcVRLGfbsQT0=", + "lastModified": 1785335110, + "narHash": "sha256-CRPBSjLcKjfoSdP8zFVKr+Rhi1ylXWRZ7wJJt736Slk=", "owner": "vacp2p", "repo": "nim-libp2p", - "rev": "4116b2ff373232c95eb173834f7a8a881bb4828a", + "rev": "a70c615c287a94e1134f45c05c18c338c7a3bc8f", "type": "github" }, "original": { "owner": "vacp2p", - "ref": "fix/cbind/nim-ffi-bump", + "ref": "master", "repo": "nim-libp2p", "type": "github" } diff --git a/flake.nix b/flake.nix index e373867..4ecfb7e 100644 --- a/flake.nix +++ b/flake.nix @@ -3,7 +3,7 @@ inputs = { logos-module-builder.url = "github:logos-co/logos-module-builder"; - libp2p.url = "github:vacp2p/nim-libp2p/fix/cbind/nim-ffi-bump"; + libp2p.url = "github:vacp2p/nim-libp2p/master"; openmetrics-module = { url = "github:logos-co/openmetrics-module"; diff --git a/src/plugin.cpp b/src/plugin.cpp index 86d9536..4380e35 100644 --- a/src/plugin.cpp +++ b/src/plugin.cpp @@ -213,6 +213,24 @@ StdLogosResult Libp2pModuleImpl::createNode(const std::string& config) { return createContext(); } +StdLogosResult Libp2pModuleImpl::setLogLevel(LogLevel level) { +#ifdef HAVE_LIBP2P_CTX_SET_LOG_LEVEL + if (!ctx) { + auto created = createContext(); + if (!created.success) return created; + } + return callSync("Failed to set log level", [&](SyncPromise* p) { + return libp2p_ctx_set_log_level(ctx, static_cast(level), + &Libp2pModuleImpl::cbBool, p); + }); +#else + // Older generated cbind headers do not expose runtime log filtering. + // Keep this a no-op so callers can use one source path across cbind revs. + (void)level; + return {true, {}, ""}; +#endif +} + void Libp2pModuleImpl::destroyContext() { if (!ctx) { return; diff --git a/src/plugin.h b/src/plugin.h index 4b68f76..3922764 100644 --- a/src/plugin.h +++ b/src/plugin.h @@ -53,6 +53,17 @@ struct SyncResult { LibP2PCtx* newCtx = nullptr; }; +enum class LogLevel : int64_t { + None = 0, + Trace = 1, + Debug = 2, + Info = 3, + Notice = 4, + Warn = 5, + Error = 6, + Fatal = 7, +}; + using SyncPromise = std::promise; // Resolves and reclaims a heap SyncPromise. Every libp2p callback owns its @@ -126,6 +137,7 @@ class Libp2pModuleImpl { StdLogosResult createNode(const std::string& config); StdLogosResult getNodeInfo(const std::string& field); + StdLogosResult setLogLevel(LogLevel level); StdLogosResult start(); StdLogosResult stop(); diff --git a/tutorial/docs/tutorial_0_introduction.md b/tutorial/docs/tutorial_0_introduction.md index 8ac9cd2..1409a53 100644 --- a/tutorial/docs/tutorial_0_introduction.md +++ b/tutorial/docs/tutorial_0_introduction.md @@ -40,8 +40,22 @@ These programs are examples, not long-running services. When a required operation fails, they print a useful error message to `stderr` and return `1`. Successful tutorials print progress to `stdout` and return `0`. -The `stdout` stream can be noisy because logs from the wrapped C binding -are also included. This is tracked in [issue #79](https://github.com/logos-co/logos-libp2p-module/issues/79). +## Controlling libp2p Logs + +The wrapped libp2p binding can emit runtime logs. Tutorials disable those +logs by default so `stdout` only shows the tutorial's own progress messages. +Use `setLogLevel()` with `LogLevel::None` to disable logs, or choose another +level such as `LogLevel::Info`, `LogLevel::Debug`, or `LogLevel::Trace` when +you need more detail while debugging: + +```cpp +StdLogosResult logRes = node.setLogLevel(LogLevel::None); +if (!logRes.success) { + fprintf(stderr, "Failed to disable libp2p logs: %s\n", + logRes.error.c_str()); + return 1; +} +``` ## Convert JSON Values Explicitly @@ -88,6 +102,13 @@ Even the first real operation returns a result. Check it before moving on. ```cpp Libp2pModuleImpl node; + StdLogosResult logRes = node.setLogLevel(LogLevel::None); + if (!logRes.success) { + fprintf(stderr, "Failed to disable libp2p logs: %s\n", + logRes.error.c_str()); + return 1; + } + StdLogosResult startRes = node.start(); if (!startRes.success) { fprintf(stderr, "Failed to start node: %s\n", diff --git a/tutorial/docs/tutorial_10_peerstore.md b/tutorial/docs/tutorial_10_peerstore.md index bf8a838..6733d5a 100644 --- a/tutorial/docs/tutorial_10_peerstore.md +++ b/tutorial/docs/tutorial_10_peerstore.md @@ -44,6 +44,13 @@ contains real peer data after a connection is established. Libp2pModuleImpl node(opts); Libp2pModuleImpl remote(remoteOpts); + StdLogosResult logRes = node.setLogLevel(LogLevel::None); + if (!logRes.success) { + fprintf(stderr, "Failed to disable libp2p logs: %s\n", + logRes.error.c_str()); + return 1; + } + StdLogosResult startRes = node.start(); if (!startRes.success) { fprintf(stderr, "Node failed to start: %s\n", diff --git a/tutorial/docs/tutorial_11_circuit_relay.md b/tutorial/docs/tutorial_11_circuit_relay.md index d837656..de88620 100644 --- a/tutorial/docs/tutorial_11_circuit_relay.md +++ b/tutorial/docs/tutorial_11_circuit_relay.md @@ -76,6 +76,13 @@ The Client connects to the Relay before dialing the Destination. Libp2pModuleImpl dest(optsDest); Libp2pModuleImpl client(optsClient); + StdLogosResult logRes = relay.setLogLevel(LogLevel::None); + if (!logRes.success) { + fprintf(stderr, "Failed to disable libp2p logs: %s\n", + logRes.error.c_str()); + return 1; + } + printf("Starting nodes...\n"); StdLogosResult relayStartRes = relay.start(); diff --git a/tutorial/docs/tutorial_1_node_lifecycle.md b/tutorial/docs/tutorial_1_node_lifecycle.md index 236a042..698bc5b 100644 --- a/tutorial/docs/tutorial_1_node_lifecycle.md +++ b/tutorial/docs/tutorial_1_node_lifecycle.md @@ -34,6 +34,13 @@ int main() // By default it listens on 127.0.0.1 with a random port (tcp/0). Libp2pModuleImpl node; + StdLogosResult logRes = node.setLogLevel(LogLevel::None); + if (!logRes.success) { + fprintf(stderr, "Failed to disable libp2p logs: %s\n", + logRes.error.c_str()); + return 1; + } + printf("Node object created (not yet started)\n"); ``` diff --git a/tutorial/docs/tutorial_2_custom_config.md b/tutorial/docs/tutorial_2_custom_config.md index 7ee8dba..78d5680 100644 --- a/tutorial/docs/tutorial_2_custom_config.md +++ b/tutorial/docs/tutorial_2_custom_config.md @@ -65,6 +65,13 @@ The most explicit way to configure a node is by constructing Libp2pModuleImpl node(options); + StdLogosResult logRes = node.setLogLevel(LogLevel::None); + if (!logRes.success) { + fprintf(stderr, "Failed to disable libp2p logs: %s\n", + logRes.error.c_str()); + return 1; + } + StdLogosResult startRes = node.start(); if (!startRes.success) { fprintf(stderr, "Failed to start node: %s\n", diff --git a/tutorial/docs/tutorial_3_connecting_peers.md b/tutorial/docs/tutorial_3_connecting_peers.md index 6f183a9..a0aeef6 100644 --- a/tutorial/docs/tutorial_3_connecting_peers.md +++ b/tutorial/docs/tutorial_3_connecting_peers.md @@ -63,6 +63,13 @@ For simplicity, both mount the built-in `/ipfs/ping/1.0.0` protocol Libp2pModuleImpl nodeA(optsA); Libp2pModuleImpl nodeB(optsB); + StdLogosResult logRes = nodeA.setLogLevel(LogLevel::None); + if (!logRes.success) { + fprintf(stderr, "Failed to disable libp2p logs: %s\n", + logRes.error.c_str()); + return 1; + } + StdLogosResult startARes = nodeA.start(); if (!startARes.success) { fprintf(stderr, "Node A failed to start: %s\n", diff --git a/tutorial/docs/tutorial_4_custom_protocol.md b/tutorial/docs/tutorial_4_custom_protocol.md index 6fed133..914552b 100644 --- a/tutorial/docs/tutorial_4_custom_protocol.md +++ b/tutorial/docs/tutorial_4_custom_protocol.md @@ -69,6 +69,13 @@ int main() Libp2pModuleImpl nodeA(optsA); Libp2pModuleImpl nodeB(optsB); + StdLogosResult logRes = nodeA.setLogLevel(LogLevel::None); + if (!logRes.success) { + fprintf(stderr, "Failed to disable libp2p logs: %s\n", + logRes.error.c_str()); + return 1; + } + StdLogosResult startARes = nodeA.start(); if (!startARes.success) { fprintf(stderr, "Node A failed: %s\n", startARes.error.c_str()); diff --git a/tutorial/docs/tutorial_5_kademlia_basics.md b/tutorial/docs/tutorial_5_kademlia_basics.md index a1d5aa0..e3c577f 100644 --- a/tutorial/docs/tutorial_5_kademlia_basics.md +++ b/tutorial/docs/tutorial_5_kademlia_basics.md @@ -56,6 +56,13 @@ real network, one node would be a well-known bootstrap peer. // Node A is the bootstrap — no special config needed, just its address. Libp2pModuleImpl nodeA(optsA); + StdLogosResult logRes = nodeA.setLogLevel(LogLevel::None); + if (!logRes.success) { + fprintf(stderr, "Failed to disable libp2p logs: %s\n", + logRes.error.c_str()); + return 1; + } + printf("Starting Node A (bootstrap)...\n"); StdLogosResult startARes = nodeA.start(); if (!startARes.success) { diff --git a/tutorial/docs/tutorial_6_kademlia_providers.md b/tutorial/docs/tutorial_6_kademlia_providers.md index 1ded98e..813fe29 100644 --- a/tutorial/docs/tutorial_6_kademlia_providers.md +++ b/tutorial/docs/tutorial_6_kademlia_providers.md @@ -45,6 +45,12 @@ int main() optsA.mountKad = true; Libp2pModuleImpl nodeA(optsA); + StdLogosResult logRes = nodeA.setLogLevel(LogLevel::None); + if (!logRes.success) { + fprintf(stderr, "Failed to disable libp2p logs: %s\n", + logRes.error.c_str()); + return 1; + } StdLogosResult startARes = nodeA.start(); if (!startARes.success) { diff --git a/tutorial/docs/tutorial_7_gossipsub_polling.md b/tutorial/docs/tutorial_7_gossipsub_polling.md index 6b329dd..2742562 100644 --- a/tutorial/docs/tutorial_7_gossipsub_polling.md +++ b/tutorial/docs/tutorial_7_gossipsub_polling.md @@ -54,6 +54,13 @@ We keep it explicit here for clarity. Libp2pModuleImpl nodeA(optsA); Libp2pModuleImpl nodeB(optsB); + StdLogosResult logRes = nodeA.setLogLevel(LogLevel::None); + if (!logRes.success) { + fprintf(stderr, "Failed to disable libp2p logs: %s\n", + logRes.error.c_str()); + return 1; + } + StdLogosResult startARes = nodeA.start(); if (!startARes.success) { fprintf(stderr, "Node A failed: %s\n", startARes.error.c_str()); diff --git a/tutorial/docs/tutorial_8_gossipsub_event_callback.md b/tutorial/docs/tutorial_8_gossipsub_event_callback.md index c59ca0e..c197d51 100644 --- a/tutorial/docs/tutorial_8_gossipsub_event_callback.md +++ b/tutorial/docs/tutorial_8_gossipsub_event_callback.md @@ -50,6 +50,13 @@ int main() Libp2pModuleImpl nodeA(optsA); Libp2pModuleImpl nodeB(optsB); + StdLogosResult logRes = nodeA.setLogLevel(LogLevel::None); + if (!logRes.success) { + fprintf(stderr, "Failed to disable libp2p logs: %s\n", + logRes.error.c_str()); + return 1; + } + StdLogosResult startARes = nodeA.start(); if (!startARes.success) { fprintf(stderr, "Node A failed: %s\n", startARes.error.c_str()); diff --git a/tutorial/docs/tutorial_9_service_discovery.md b/tutorial/docs/tutorial_9_service_discovery.md index a3fd4e4..e6c4293 100644 --- a/tutorial/docs/tutorial_9_service_discovery.md +++ b/tutorial/docs/tutorial_9_service_discovery.md @@ -48,6 +48,13 @@ It relays service advertisements and lookup queries. optsBootstrap.mountServiceDiscovery = true; Libp2pModuleImpl bootstrap(optsBootstrap); + StdLogosResult logRes = bootstrap.setLogLevel(LogLevel::None); + if (!logRes.success) { + fprintf(stderr, "Failed to disable libp2p logs: %s\n", + logRes.error.c_str()); + return 1; + } + StdLogosResult bootstrapStartRes = bootstrap.start(); if (!bootstrapStartRes.success) { fprintf(stderr, "Bootstrap failed: %s\n", diff --git a/tutorial/tutorial_0_introduction.cpp b/tutorial/tutorial_0_introduction.cpp index 433215f..6e62f96 100644 --- a/tutorial/tutorial_0_introduction.cpp +++ b/tutorial/tutorial_0_introduction.cpp @@ -40,8 +40,22 @@ /// operation fails, they print a useful error message to `stderr` and return /// `1`. Successful tutorials print progress to `stdout` and return `0`. /// -/// The `stdout` stream can be noisy because logs from the wrapped C binding -/// are also included. This is tracked in [issue #79](https://github.com/logos-co/logos-libp2p-module/issues/79). +/// ## Controlling libp2p Logs +/// +/// The wrapped libp2p binding can emit runtime logs. Tutorials disable those +/// logs by default so `stdout` only shows the tutorial's own progress messages. +/// Use `setLogLevel()` with `LogLevel::None` to disable logs, or choose another +/// level such as `LogLevel::Info`, `LogLevel::Debug`, or `LogLevel::Trace` when +/// you need more detail while debugging: +/// +/// ```cpp +/// StdLogosResult logRes = node.setLogLevel(LogLevel::None); +/// if (!logRes.success) { +/// fprintf(stderr, "Failed to disable libp2p logs: %s\n", +/// logRes.error.c_str()); +/// return 1; +/// } +/// ``` /// /// ## Convert JSON Values Explicitly /// @@ -84,6 +98,13 @@ int main() /// Even the first real operation returns a result. Check it before moving on. Libp2pModuleImpl node; + StdLogosResult logRes = node.setLogLevel(LogLevel::None); + if (!logRes.success) { + fprintf(stderr, "Failed to disable libp2p logs: %s\n", + logRes.error.c_str()); + return 1; + } + StdLogosResult startRes = node.start(); if (!startRes.success) { fprintf(stderr, "Failed to start node: %s\n", diff --git a/tutorial/tutorial_10_peerstore.cpp b/tutorial/tutorial_10_peerstore.cpp index 99a9848..2dc1152 100644 --- a/tutorial/tutorial_10_peerstore.cpp +++ b/tutorial/tutorial_10_peerstore.cpp @@ -40,6 +40,13 @@ int main() Libp2pModuleImpl node(opts); Libp2pModuleImpl remote(remoteOpts); + StdLogosResult logRes = node.setLogLevel(LogLevel::None); + if (!logRes.success) { + fprintf(stderr, "Failed to disable libp2p logs: %s\n", + logRes.error.c_str()); + return 1; + } + StdLogosResult startRes = node.start(); if (!startRes.success) { fprintf(stderr, "Node failed to start: %s\n", diff --git a/tutorial/tutorial_11_circuit_relay.cpp b/tutorial/tutorial_11_circuit_relay.cpp index 436d4ca..28d67fc 100644 --- a/tutorial/tutorial_11_circuit_relay.cpp +++ b/tutorial/tutorial_11_circuit_relay.cpp @@ -72,6 +72,13 @@ int main() Libp2pModuleImpl dest(optsDest); Libp2pModuleImpl client(optsClient); + StdLogosResult logRes = relay.setLogLevel(LogLevel::None); + if (!logRes.success) { + fprintf(stderr, "Failed to disable libp2p logs: %s\n", + logRes.error.c_str()); + return 1; + } + printf("Starting nodes...\n"); StdLogosResult relayStartRes = relay.start(); diff --git a/tutorial/tutorial_1_node_lifecycle.cpp b/tutorial/tutorial_1_node_lifecycle.cpp index f4d4618..f63fc13 100644 --- a/tutorial/tutorial_1_node_lifecycle.cpp +++ b/tutorial/tutorial_1_node_lifecycle.cpp @@ -30,6 +30,13 @@ int main() // By default it listens on 127.0.0.1 with a random port (tcp/0). Libp2pModuleImpl node; + StdLogosResult logRes = node.setLogLevel(LogLevel::None); + if (!logRes.success) { + fprintf(stderr, "Failed to disable libp2p logs: %s\n", + logRes.error.c_str()); + return 1; + } + printf("Node object created (not yet started)\n"); /// ## Step 2: Start the node diff --git a/tutorial/tutorial_2_custom_config.cpp b/tutorial/tutorial_2_custom_config.cpp index 925c9cc..6be0495 100644 --- a/tutorial/tutorial_2_custom_config.cpp +++ b/tutorial/tutorial_2_custom_config.cpp @@ -61,6 +61,13 @@ int main() Libp2pModuleImpl node(options); + StdLogosResult logRes = node.setLogLevel(LogLevel::None); + if (!logRes.success) { + fprintf(stderr, "Failed to disable libp2p logs: %s\n", + logRes.error.c_str()); + return 1; + } + StdLogosResult startRes = node.start(); if (!startRes.success) { fprintf(stderr, "Failed to start node: %s\n", diff --git a/tutorial/tutorial_3_connecting_peers.cpp b/tutorial/tutorial_3_connecting_peers.cpp index f975ba7..9846207 100644 --- a/tutorial/tutorial_3_connecting_peers.cpp +++ b/tutorial/tutorial_3_connecting_peers.cpp @@ -59,6 +59,13 @@ int main() Libp2pModuleImpl nodeA(optsA); Libp2pModuleImpl nodeB(optsB); + StdLogosResult logRes = nodeA.setLogLevel(LogLevel::None); + if (!logRes.success) { + fprintf(stderr, "Failed to disable libp2p logs: %s\n", + logRes.error.c_str()); + return 1; + } + StdLogosResult startARes = nodeA.start(); if (!startARes.success) { fprintf(stderr, "Node A failed to start: %s\n", diff --git a/tutorial/tutorial_4_custom_protocol.cpp b/tutorial/tutorial_4_custom_protocol.cpp index d14fe2f..42c73ab 100644 --- a/tutorial/tutorial_4_custom_protocol.cpp +++ b/tutorial/tutorial_4_custom_protocol.cpp @@ -62,6 +62,13 @@ int main() Libp2pModuleImpl nodeA(optsA); Libp2pModuleImpl nodeB(optsB); + StdLogosResult logRes = nodeA.setLogLevel(LogLevel::None); + if (!logRes.success) { + fprintf(stderr, "Failed to disable libp2p logs: %s\n", + logRes.error.c_str()); + return 1; + } + StdLogosResult startARes = nodeA.start(); if (!startARes.success) { fprintf(stderr, "Node A failed: %s\n", startARes.error.c_str()); diff --git a/tutorial/tutorial_5_kademlia_basics.cpp b/tutorial/tutorial_5_kademlia_basics.cpp index 0606a3e..8c4458d 100644 --- a/tutorial/tutorial_5_kademlia_basics.cpp +++ b/tutorial/tutorial_5_kademlia_basics.cpp @@ -52,6 +52,13 @@ int main() // Node A is the bootstrap — no special config needed, just its address. Libp2pModuleImpl nodeA(optsA); + StdLogosResult logRes = nodeA.setLogLevel(LogLevel::None); + if (!logRes.success) { + fprintf(stderr, "Failed to disable libp2p logs: %s\n", + logRes.error.c_str()); + return 1; + } + printf("Starting Node A (bootstrap)...\n"); StdLogosResult startARes = nodeA.start(); if (!startARes.success) { diff --git a/tutorial/tutorial_6_kademlia_providers.cpp b/tutorial/tutorial_6_kademlia_providers.cpp index c73fc5e..db5ce2e 100644 --- a/tutorial/tutorial_6_kademlia_providers.cpp +++ b/tutorial/tutorial_6_kademlia_providers.cpp @@ -41,6 +41,12 @@ int main() optsA.mountKad = true; Libp2pModuleImpl nodeA(optsA); + StdLogosResult logRes = nodeA.setLogLevel(LogLevel::None); + if (!logRes.success) { + fprintf(stderr, "Failed to disable libp2p logs: %s\n", + logRes.error.c_str()); + return 1; + } StdLogosResult startARes = nodeA.start(); if (!startARes.success) { diff --git a/tutorial/tutorial_7_gossipsub_polling.cpp b/tutorial/tutorial_7_gossipsub_polling.cpp index a44a6cf..fa768e8 100644 --- a/tutorial/tutorial_7_gossipsub_polling.cpp +++ b/tutorial/tutorial_7_gossipsub_polling.cpp @@ -50,6 +50,13 @@ int main() Libp2pModuleImpl nodeA(optsA); Libp2pModuleImpl nodeB(optsB); + StdLogosResult logRes = nodeA.setLogLevel(LogLevel::None); + if (!logRes.success) { + fprintf(stderr, "Failed to disable libp2p logs: %s\n", + logRes.error.c_str()); + return 1; + } + StdLogosResult startARes = nodeA.start(); if (!startARes.success) { fprintf(stderr, "Node A failed: %s\n", startARes.error.c_str()); diff --git a/tutorial/tutorial_8_gossipsub_event_callback.cpp b/tutorial/tutorial_8_gossipsub_event_callback.cpp index 679471e..12607e0 100644 --- a/tutorial/tutorial_8_gossipsub_event_callback.cpp +++ b/tutorial/tutorial_8_gossipsub_event_callback.cpp @@ -46,6 +46,13 @@ int main() Libp2pModuleImpl nodeA(optsA); Libp2pModuleImpl nodeB(optsB); + StdLogosResult logRes = nodeA.setLogLevel(LogLevel::None); + if (!logRes.success) { + fprintf(stderr, "Failed to disable libp2p logs: %s\n", + logRes.error.c_str()); + return 1; + } + StdLogosResult startARes = nodeA.start(); if (!startARes.success) { fprintf(stderr, "Node A failed: %s\n", startARes.error.c_str()); diff --git a/tutorial/tutorial_9_service_discovery.cpp b/tutorial/tutorial_9_service_discovery.cpp index f506fb8..72a2506 100644 --- a/tutorial/tutorial_9_service_discovery.cpp +++ b/tutorial/tutorial_9_service_discovery.cpp @@ -44,6 +44,13 @@ int main() optsBootstrap.mountServiceDiscovery = true; Libp2pModuleImpl bootstrap(optsBootstrap); + StdLogosResult logRes = bootstrap.setLogLevel(LogLevel::None); + if (!logRes.success) { + fprintf(stderr, "Failed to disable libp2p logs: %s\n", + logRes.error.c_str()); + return 1; + } + StdLogosResult bootstrapStartRes = bootstrap.start(); if (!bootstrapStartRes.success) { fprintf(stderr, "Bootstrap failed: %s\n", From ff8fc9a52acf08ae0ef19971d189bf68154bd8a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vlado=20Paji=C4=87?= Date: Wed, 29 Jul 2026 19:08:20 +0200 Subject: [PATCH 02/19] fix --- flake.nix | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/flake.nix b/flake.nix index 4ecfb7e..f77798a 100644 --- a/flake.nix +++ b/flake.nix @@ -17,9 +17,28 @@ outputs = inputs@{ logos-module-builder, ... }: let + nixpkgs = logos-module-builder.inputs.nixpkgs; + systems = [ "aarch64-darwin" "x86_64-darwin" "aarch64-linux" "x86_64-linux" ]; + + forEachSystem = f: builtins.listToAttrs (map (system: { + name = system; + value = f system; + }) systems); + + libp2pRuntimeFiltering = { + packages = forEachSystem (system: { + cbind = inputs.libp2p.packages.${system}.cbind.overrideAttrs (old: { + buildPhase = builtins.replaceStrings + [ "--threads:on --opt:size --noMain --mm:refc --d:metrics" ] + [ "--threads:on --opt:size --noMain --mm:refc --d:metrics -d:chronicles_runtime_filtering=on" ] + old.buildPhase; + }); + }); + }; + externalLibInputs = { libp2p = { - input = inputs.libp2p; + input = libp2pRuntimeFiltering; packages.default = "cbind"; }; }; @@ -34,14 +53,6 @@ }; }; - nixpkgs = logos-module-builder.inputs.nixpkgs; - systems = [ "aarch64-darwin" "x86_64-darwin" "aarch64-linux" "x86_64-linux" ]; - - forEachSystem = f: builtins.listToAttrs (map (system: { - name = system; - value = f system; - }) systems); - # Pre-resolved store paths for the two .lgx bundles the e2e installs. e2eEnv = system: { LIBP2P_LGX_DIR = "${module.packages.${system}.lgx}"; From 8a20153910804f3c64520b1908cde6a34681cc29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vlado=20Paji=C4=87?= Date: Wed, 29 Jul 2026 19:27:55 +0200 Subject: [PATCH 03/19] log lvl is always here --- CMakeLists.txt | 17 ----------------- src/plugin.cpp | 7 ------- 2 files changed, 24 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2449b1d..c4e7871 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,8 +1,6 @@ cmake_minimum_required(VERSION 3.14) project(Libp2pModulePlugin LANGUAGES CXX) -include(CheckCXXSourceCompiles) - if(DEFINED ENV{LOGOS_MODULE_BUILDER_ROOT}) include($ENV{LOGOS_MODULE_BUILDER_ROOT}/cmake/LogosModule.cmake) else() @@ -33,19 +31,4 @@ logos_module( tinycbor ) -set(CMAKE_REQUIRED_INCLUDES ${LIBP2P_INCLUDE_DIR}) -check_cxx_source_compiles(" - #include - int main() { - auto fn = &libp2p_ctx_set_log_level; - (void)fn; - return 0; - } -" HAVE_LIBP2P_CTX_SET_LOG_LEVEL) - -if(HAVE_LIBP2P_CTX_SET_LOG_LEVEL) - target_compile_definitions(libp2p_module_module_plugin - PRIVATE HAVE_LIBP2P_CTX_SET_LOG_LEVEL) -endif() - add_subdirectory(tutorial) diff --git a/src/plugin.cpp b/src/plugin.cpp index 4380e35..8f9d99a 100644 --- a/src/plugin.cpp +++ b/src/plugin.cpp @@ -214,7 +214,6 @@ StdLogosResult Libp2pModuleImpl::createNode(const std::string& config) { } StdLogosResult Libp2pModuleImpl::setLogLevel(LogLevel level) { -#ifdef HAVE_LIBP2P_CTX_SET_LOG_LEVEL if (!ctx) { auto created = createContext(); if (!created.success) return created; @@ -223,12 +222,6 @@ StdLogosResult Libp2pModuleImpl::setLogLevel(LogLevel level) { return libp2p_ctx_set_log_level(ctx, static_cast(level), &Libp2pModuleImpl::cbBool, p); }); -#else - // Older generated cbind headers do not expose runtime log filtering. - // Keep this a no-op so callers can use one source path across cbind revs. - (void)level; - return {true, {}, ""}; -#endif } void Libp2pModuleImpl::destroyContext() { From bfd8117caf444cdb86d6b582e84309906bfe7e2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vlado=20Paji=C4=87?= Date: Wed, 29 Jul 2026 19:40:29 +0200 Subject: [PATCH 04/19] update --- src/plugin.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/plugin.h b/src/plugin.h index 3922764..7db680e 100644 --- a/src/plugin.h +++ b/src/plugin.h @@ -54,14 +54,14 @@ struct SyncResult { }; enum class LogLevel : int64_t { - None = 0, - Trace = 1, - Debug = 2, - Info = 3, - Notice = 4, - Warn = 5, - Error = 6, - Fatal = 7, + None = LOG_LEVEL_NONE, + Trace = LOG_LEVEL_TRACE, + Debug = LOG_LEVEL_DEBUG, + Info = LOG_LEVEL_INFO, + Notice = LOG_LEVEL_NOTICE, + Warn = LOG_LEVEL_WARN, + Error = LOG_LEVEL_ERROR, + Fatal = LOG_LEVEL_FATAL, }; using SyncPromise = std::promise; From aa2443efb370782d59d8375d0fec5ba25552b0a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vlado=20Paji=C4=87?= Date: Thu, 30 Jul 2026 11:29:28 +0200 Subject: [PATCH 05/19] update --- src/plugin.cpp | 8 ++--- tutorial/tutorial_0_introduction.cpp | 29 ++++++++++--------- tutorial/tutorial_10_peerstore.cpp | 10 ++----- tutorial/tutorial_11_circuit_relay.cpp | 8 ++--- tutorial/tutorial_1_node_lifecycle.cpp | 18 ++++++------ tutorial/tutorial_2_custom_config.cpp | 11 +++---- tutorial/tutorial_3_connecting_peers.cpp | 8 ++--- tutorial/tutorial_4_custom_protocol.cpp | 11 ++----- tutorial/tutorial_5_kademlia_basics.cpp | 10 ++----- tutorial/tutorial_6_kademlia_providers.cpp | 8 ++--- tutorial/tutorial_7_gossipsub_polling.cpp | 10 ++----- .../tutorial_8_gossipsub_event_callback.cpp | 10 ++----- tutorial/tutorial_9_service_discovery.cpp | 8 ++--- 13 files changed, 54 insertions(+), 95 deletions(-) diff --git a/src/plugin.cpp b/src/plugin.cpp index 8f9d99a..309e416 100644 --- a/src/plugin.cpp +++ b/src/plugin.cpp @@ -214,13 +214,9 @@ StdLogosResult Libp2pModuleImpl::createNode(const std::string& config) { } StdLogosResult Libp2pModuleImpl::setLogLevel(LogLevel level) { - if (!ctx) { - auto created = createContext(); - if (!created.success) return created; - } return callSync("Failed to set log level", [&](SyncPromise* p) { - return libp2p_ctx_set_log_level(ctx, static_cast(level), - &Libp2pModuleImpl::cbBool, p); + return libp2p_static_set_log_level(static_cast(level), + &Libp2pModuleImpl::cbBool, p); }); } diff --git a/tutorial/tutorial_0_introduction.cpp b/tutorial/tutorial_0_introduction.cpp index 6e62f96..0361791 100644 --- a/tutorial/tutorial_0_introduction.cpp +++ b/tutorial/tutorial_0_introduction.cpp @@ -42,16 +42,16 @@ /// /// ## Controlling libp2p Logs /// -/// The wrapped libp2p binding can emit runtime logs. Tutorials disable those -/// logs by default so `stdout` only shows the tutorial's own progress messages. -/// Use `setLogLevel()` with `LogLevel::None` to disable logs, or choose another -/// level such as `LogLevel::Info`, `LogLevel::Debug`, or `LogLevel::Trace` when -/// you need more detail while debugging: +/// The wrapped libp2p binding can emit runtime logs. Tutorials set the log +/// level to `LogLevel::Fatal` by default so `stdout` only shows the tutorial's +/// own progress messages during normal runs. Choose another level such as +/// `LogLevel::Info`, `LogLevel::Debug`, or `LogLevel::Trace` when you need more +/// detail while debugging: /// /// ```cpp -/// StdLogosResult logRes = node.setLogLevel(LogLevel::None); +/// StdLogosResult logRes = node.setLogLevel(LogLevel::Fatal); /// if (!logRes.success) { -/// fprintf(stderr, "Failed to disable libp2p logs: %s\n", +/// fprintf(stderr, "Failed to set libp2p log level: %s\n", /// logRes.error.c_str()); /// return 1; /// } @@ -93,18 +93,21 @@ int main() { printf("=== Tutorial 0: Introduction and Common Patterns ===\n\n"); -/// ## Step 1: Create and start a node -/// -/// Even the first real operation returns a result. Check it before moving on. - Libp2pModuleImpl node; - - StdLogosResult logRes = node.setLogLevel(LogLevel::None); + // Silence logs from wrapped library. It is always advised to check result, + // but in future tutorials will avoid it in order to simplify code. + StdLogosResult logRes = setLogLevel(LogLevel::Fatal); if (!logRes.success) { fprintf(stderr, "Failed to disable libp2p logs: %s\n", logRes.error.c_str()); return 1; } +/// ## Step 1: Create and start a node +/// +/// Even the first real operation returns a result. Check it before moving on. + Libp2pModuleImpl node; + + StdLogosResult startRes = node.start(); if (!startRes.success) { fprintf(stderr, "Failed to start node: %s\n", diff --git a/tutorial/tutorial_10_peerstore.cpp b/tutorial/tutorial_10_peerstore.cpp index 2dc1152..7a18d20 100644 --- a/tutorial/tutorial_10_peerstore.cpp +++ b/tutorial/tutorial_10_peerstore.cpp @@ -26,6 +26,8 @@ int main() { printf("=== Tutorial 10: Peer Store Management ===\n\n"); + setLogLevel(LogLevel::Fatal); + /// ## Step 1: Create two nodes /// /// The peer store is automatically available on any started node. @@ -39,13 +41,7 @@ int main() Libp2pModuleImpl node(opts); Libp2pModuleImpl remote(remoteOpts); - - StdLogosResult logRes = node.setLogLevel(LogLevel::None); - if (!logRes.success) { - fprintf(stderr, "Failed to disable libp2p logs: %s\n", - logRes.error.c_str()); - return 1; - } + StdLogosResult startRes = node.start(); if (!startRes.success) { diff --git a/tutorial/tutorial_11_circuit_relay.cpp b/tutorial/tutorial_11_circuit_relay.cpp index 28d67fc..358643c 100644 --- a/tutorial/tutorial_11_circuit_relay.cpp +++ b/tutorial/tutorial_11_circuit_relay.cpp @@ -44,6 +44,8 @@ int main() { printf("=== Tutorial 11: Circuit Relay ===\n\n"); + setLogLevel(LogLevel::Fatal); + /// ## Step 1: Create three nodes /// /// - **Relay** (port 9890): publicly reachable, `circuitRelay: true` @@ -72,12 +74,6 @@ int main() Libp2pModuleImpl dest(optsDest); Libp2pModuleImpl client(optsClient); - StdLogosResult logRes = relay.setLogLevel(LogLevel::None); - if (!logRes.success) { - fprintf(stderr, "Failed to disable libp2p logs: %s\n", - logRes.error.c_str()); - return 1; - } printf("Starting nodes...\n"); diff --git a/tutorial/tutorial_1_node_lifecycle.cpp b/tutorial/tutorial_1_node_lifecycle.cpp index f63fc13..0208211 100644 --- a/tutorial/tutorial_1_node_lifecycle.cpp +++ b/tutorial/tutorial_1_node_lifecycle.cpp @@ -22,21 +22,19 @@ #include #include "plugin.h" -/// The main class we work with is `Libp2pModuleImpl`. Let's create one with -/// default options: int main() { + printf("=== Tutorial 1: Creating and Starting a libp2p Node ===\n\n"); + + setLogLevel(LogLevel::Fatal); + +/// The main class we work with is `Libp2pModuleImpl`. Let's create one with +/// default options: + // Create a libp2p node with default configuration. // By default it listens on 127.0.0.1 with a random port (tcp/0). Libp2pModuleImpl node; - StdLogosResult logRes = node.setLogLevel(LogLevel::None); - if (!logRes.success) { - fprintf(stderr, "Failed to disable libp2p logs: %s\n", - logRes.error.c_str()); - return 1; - } - printf("Node object created (not yet started)\n"); /// ## Step 2: Start the node @@ -102,6 +100,8 @@ int main() node.stop(); printf("Node stopped\n"); + printf("\n=== Tutorial 1 Complete ===\n"); + return 0; } diff --git a/tutorial/tutorial_2_custom_config.cpp b/tutorial/tutorial_2_custom_config.cpp index 6be0495..736722d 100644 --- a/tutorial/tutorial_2_custom_config.cpp +++ b/tutorial/tutorial_2_custom_config.cpp @@ -34,6 +34,10 @@ int main() { + printf("=== Tutorial 2: Custom Node Configuration ===\n\n"); + + setLogLevel(LogLevel::Fatal); + /// ## Method 1: Configure via C++ struct /// /// The most explicit way to configure a node is by constructing @@ -61,13 +65,6 @@ int main() Libp2pModuleImpl node(options); - StdLogosResult logRes = node.setLogLevel(LogLevel::None); - if (!logRes.success) { - fprintf(stderr, "Failed to disable libp2p logs: %s\n", - logRes.error.c_str()); - return 1; - } - StdLogosResult startRes = node.start(); if (!startRes.success) { fprintf(stderr, "Failed to start node: %s\n", diff --git a/tutorial/tutorial_3_connecting_peers.cpp b/tutorial/tutorial_3_connecting_peers.cpp index 9846207..0bc505f 100644 --- a/tutorial/tutorial_3_connecting_peers.cpp +++ b/tutorial/tutorial_3_connecting_peers.cpp @@ -43,6 +43,8 @@ int main() { printf("=== Tutorial 3: Connecting Peers ===\n\n"); + setLogLevel(LogLevel::Fatal); + /// ## Step 1: Create and start two nodes /// /// We create two nodes. Node A listens on port 9190, Node B on port 9191. @@ -59,12 +61,6 @@ int main() Libp2pModuleImpl nodeA(optsA); Libp2pModuleImpl nodeB(optsB); - StdLogosResult logRes = nodeA.setLogLevel(LogLevel::None); - if (!logRes.success) { - fprintf(stderr, "Failed to disable libp2p logs: %s\n", - logRes.error.c_str()); - return 1; - } StdLogosResult startARes = nodeA.start(); if (!startARes.success) { diff --git a/tutorial/tutorial_4_custom_protocol.cpp b/tutorial/tutorial_4_custom_protocol.cpp index 42c73ab..200d1c0 100644 --- a/tutorial/tutorial_4_custom_protocol.cpp +++ b/tutorial/tutorial_4_custom_protocol.cpp @@ -54,6 +54,8 @@ int main() { printf("=== Tutorial 4: Custom Protocol Handlers ===\n\n"); + setLogLevel(LogLevel::Fatal); + /// ## Step 1: Create and start two nodes Libp2pModuleOptions optsA, optsB; optsA.addrs = {"/ip4/127.0.0.1/tcp/9290"}; @@ -61,14 +63,7 @@ int main() Libp2pModuleImpl nodeA(optsA); Libp2pModuleImpl nodeB(optsB); - - StdLogosResult logRes = nodeA.setLogLevel(LogLevel::None); - if (!logRes.success) { - fprintf(stderr, "Failed to disable libp2p logs: %s\n", - logRes.error.c_str()); - return 1; - } - + StdLogosResult startARes = nodeA.start(); if (!startARes.success) { fprintf(stderr, "Node A failed: %s\n", startARes.error.c_str()); diff --git a/tutorial/tutorial_5_kademlia_basics.cpp b/tutorial/tutorial_5_kademlia_basics.cpp index 8c4458d..a396685 100644 --- a/tutorial/tutorial_5_kademlia_basics.cpp +++ b/tutorial/tutorial_5_kademlia_basics.cpp @@ -39,6 +39,8 @@ int main() { printf("=== Tutorial 5: Kademlia DHT Basics ===\n\n"); + setLogLevel(LogLevel::Fatal); + /// ## Step 1: Create two nodes /// /// We need at least two nodes to demonstrate DHT operations. In a @@ -52,12 +54,6 @@ int main() // Node A is the bootstrap — no special config needed, just its address. Libp2pModuleImpl nodeA(optsA); - StdLogosResult logRes = nodeA.setLogLevel(LogLevel::None); - if (!logRes.success) { - fprintf(stderr, "Failed to disable libp2p logs: %s\n", - logRes.error.c_str()); - return 1; - } printf("Starting Node A (bootstrap)...\n"); StdLogosResult startARes = nodeA.start(); @@ -87,7 +83,7 @@ int main() optsB.mountKad = true; optsB.bootstrapNodes = {{peerIdA, addrsA}}; - Libp2pModuleImpl nodeB(optsB); + Libp2pModuleImpl nodeB(optsB); printf("Starting Node B (with Node A as bootstrap)...\n"); StdLogosResult startBRes = nodeB.start(); if (!startBRes.success) { diff --git a/tutorial/tutorial_6_kademlia_providers.cpp b/tutorial/tutorial_6_kademlia_providers.cpp index db5ce2e..98cd59a 100644 --- a/tutorial/tutorial_6_kademlia_providers.cpp +++ b/tutorial/tutorial_6_kademlia_providers.cpp @@ -34,6 +34,8 @@ int main() { printf("=== Tutorial 6: Kademlia Provider Records ===\n\n"); + + setLogLevel(LogLevel::Fatal); /// ## Step 1: Create two peers Libp2pModuleOptions optsA, optsB; @@ -41,12 +43,6 @@ int main() optsA.mountKad = true; Libp2pModuleImpl nodeA(optsA); - StdLogosResult logRes = nodeA.setLogLevel(LogLevel::None); - if (!logRes.success) { - fprintf(stderr, "Failed to disable libp2p logs: %s\n", - logRes.error.c_str()); - return 1; - } StdLogosResult startARes = nodeA.start(); if (!startARes.success) { diff --git a/tutorial/tutorial_7_gossipsub_polling.cpp b/tutorial/tutorial_7_gossipsub_polling.cpp index fa768e8..add3842 100644 --- a/tutorial/tutorial_7_gossipsub_polling.cpp +++ b/tutorial/tutorial_7_gossipsub_polling.cpp @@ -36,6 +36,8 @@ int main() { printf("=== Tutorial 7: GossipSub - Polling for Messages ===\n\n"); + setLogLevel(LogLevel::Fatal); + /// ## Step 1: Create two nodes with GossipSub enabled /// /// GossipSub is enabled by default (`mountGossipsub: true`). @@ -49,13 +51,7 @@ int main() Libp2pModuleImpl nodeA(optsA); Libp2pModuleImpl nodeB(optsB); - - StdLogosResult logRes = nodeA.setLogLevel(LogLevel::None); - if (!logRes.success) { - fprintf(stderr, "Failed to disable libp2p logs: %s\n", - logRes.error.c_str()); - return 1; - } + StdLogosResult startARes = nodeA.start(); if (!startARes.success) { diff --git a/tutorial/tutorial_8_gossipsub_event_callback.cpp b/tutorial/tutorial_8_gossipsub_event_callback.cpp index 12607e0..f7a2300 100644 --- a/tutorial/tutorial_8_gossipsub_event_callback.cpp +++ b/tutorial/tutorial_8_gossipsub_event_callback.cpp @@ -35,6 +35,8 @@ int main() { printf("=== Tutorial 8: GossipSub - Event Callback Messages ===\n\n"); + setLogLevel(LogLevel::Fatal); + /// ## Step 1: Create two nodes with GossipSub enabled Libp2pModuleOptions optsA, optsB; optsA.addrs = {"/ip4/127.0.0.1/tcp/9600"}; @@ -45,13 +47,7 @@ int main() Libp2pModuleImpl nodeA(optsA); Libp2pModuleImpl nodeB(optsB); - - StdLogosResult logRes = nodeA.setLogLevel(LogLevel::None); - if (!logRes.success) { - fprintf(stderr, "Failed to disable libp2p logs: %s\n", - logRes.error.c_str()); - return 1; - } + StdLogosResult startARes = nodeA.start(); if (!startARes.success) { diff --git a/tutorial/tutorial_9_service_discovery.cpp b/tutorial/tutorial_9_service_discovery.cpp index 72a2506..1f6c6a7 100644 --- a/tutorial/tutorial_9_service_discovery.cpp +++ b/tutorial/tutorial_9_service_discovery.cpp @@ -35,6 +35,8 @@ int main() { printf("=== Tutorial 9: Service Discovery ===\n\n"); + setLogLevel(LogLevel::Fatal); + /// ## Step 1: Create a bootstrap node /// /// The bootstrap is a well-known node that all peers connect to. @@ -44,12 +46,6 @@ int main() optsBootstrap.mountServiceDiscovery = true; Libp2pModuleImpl bootstrap(optsBootstrap); - StdLogosResult logRes = bootstrap.setLogLevel(LogLevel::None); - if (!logRes.success) { - fprintf(stderr, "Failed to disable libp2p logs: %s\n", - logRes.error.c_str()); - return 1; - } StdLogosResult bootstrapStartRes = bootstrap.start(); if (!bootstrapStartRes.success) { From 26712bf0214ee23454d4508529fe1dd6e1f25a2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vlado=20Paji=C4=87?= Date: Thu, 30 Jul 2026 12:02:52 +0200 Subject: [PATCH 06/19] comsetics --- flake.nix | 4 ++-- tutorial/tutorial_0_introduction.cpp | 5 ++--- tutorial/tutorial_10_peerstore.cpp | 3 +-- tutorial/tutorial_11_circuit_relay.cpp | 3 +-- tutorial/tutorial_1_node_lifecycle.cpp | 2 +- tutorial/tutorial_2_custom_config.cpp | 2 +- tutorial/tutorial_3_connecting_peers.cpp | 3 +-- tutorial/tutorial_4_custom_protocol.cpp | 4 ++-- tutorial/tutorial_5_kademlia_basics.cpp | 5 ++--- tutorial/tutorial_6_kademlia_providers.cpp | 2 +- tutorial/tutorial_7_gossipsub_polling.cpp | 3 +-- tutorial/tutorial_8_gossipsub_event_callback.cpp | 3 +-- tutorial/tutorial_9_service_discovery.cpp | 3 +-- 13 files changed, 17 insertions(+), 25 deletions(-) diff --git a/flake.nix b/flake.nix index f77798a..01abfac 100644 --- a/flake.nix +++ b/flake.nix @@ -25,7 +25,7 @@ value = f system; }) systems); - libp2pRuntimeFiltering = { + libp2pInputs = { packages = forEachSystem (system: { cbind = inputs.libp2p.packages.${system}.cbind.overrideAttrs (old: { buildPhase = builtins.replaceStrings @@ -38,7 +38,7 @@ externalLibInputs = { libp2p = { - input = libp2pRuntimeFiltering; + input = libp2pInputs; packages.default = "cbind"; }; }; diff --git a/tutorial/tutorial_0_introduction.cpp b/tutorial/tutorial_0_introduction.cpp index 0361791..5fcc98e 100644 --- a/tutorial/tutorial_0_introduction.cpp +++ b/tutorial/tutorial_0_introduction.cpp @@ -49,7 +49,7 @@ /// detail while debugging: /// /// ```cpp -/// StdLogosResult logRes = node.setLogLevel(LogLevel::Fatal); +/// StdLogosResult logRes = node.setLogLevel(LogLevel::Debug); /// if (!logRes.success) { /// fprintf(stderr, "Failed to set libp2p log level: %s\n", /// logRes.error.c_str()); @@ -95,7 +95,7 @@ int main() // Silence logs from wrapped library. It is always advised to check result, // but in future tutorials will avoid it in order to simplify code. - StdLogosResult logRes = setLogLevel(LogLevel::Fatal); + StdLogosResult logRes = setLogLevel(LogLevel::None); if (!logRes.success) { fprintf(stderr, "Failed to disable libp2p logs: %s\n", logRes.error.c_str()); @@ -107,7 +107,6 @@ int main() /// Even the first real operation returns a result. Check it before moving on. Libp2pModuleImpl node; - StdLogosResult startRes = node.start(); if (!startRes.success) { fprintf(stderr, "Failed to start node: %s\n", diff --git a/tutorial/tutorial_10_peerstore.cpp b/tutorial/tutorial_10_peerstore.cpp index 7a18d20..3109bea 100644 --- a/tutorial/tutorial_10_peerstore.cpp +++ b/tutorial/tutorial_10_peerstore.cpp @@ -26,7 +26,7 @@ int main() { printf("=== Tutorial 10: Peer Store Management ===\n\n"); - setLogLevel(LogLevel::Fatal); + setLogLevel(LogLevel::None); /// ## Step 1: Create two nodes /// @@ -41,7 +41,6 @@ int main() Libp2pModuleImpl node(opts); Libp2pModuleImpl remote(remoteOpts); - StdLogosResult startRes = node.start(); if (!startRes.success) { diff --git a/tutorial/tutorial_11_circuit_relay.cpp b/tutorial/tutorial_11_circuit_relay.cpp index 358643c..8ea55f1 100644 --- a/tutorial/tutorial_11_circuit_relay.cpp +++ b/tutorial/tutorial_11_circuit_relay.cpp @@ -44,7 +44,7 @@ int main() { printf("=== Tutorial 11: Circuit Relay ===\n\n"); - setLogLevel(LogLevel::Fatal); + setLogLevel(LogLevel::None); /// ## Step 1: Create three nodes /// @@ -74,7 +74,6 @@ int main() Libp2pModuleImpl dest(optsDest); Libp2pModuleImpl client(optsClient); - printf("Starting nodes...\n"); StdLogosResult relayStartRes = relay.start(); diff --git a/tutorial/tutorial_1_node_lifecycle.cpp b/tutorial/tutorial_1_node_lifecycle.cpp index 0208211..1d05628 100644 --- a/tutorial/tutorial_1_node_lifecycle.cpp +++ b/tutorial/tutorial_1_node_lifecycle.cpp @@ -26,7 +26,7 @@ int main() { printf("=== Tutorial 1: Creating and Starting a libp2p Node ===\n\n"); - setLogLevel(LogLevel::Fatal); + setLogLevel(LogLevel::None); /// The main class we work with is `Libp2pModuleImpl`. Let's create one with /// default options: diff --git a/tutorial/tutorial_2_custom_config.cpp b/tutorial/tutorial_2_custom_config.cpp index 736722d..fe164a3 100644 --- a/tutorial/tutorial_2_custom_config.cpp +++ b/tutorial/tutorial_2_custom_config.cpp @@ -36,7 +36,7 @@ int main() { printf("=== Tutorial 2: Custom Node Configuration ===\n\n"); - setLogLevel(LogLevel::Fatal); + setLogLevel(LogLevel::None); /// ## Method 1: Configure via C++ struct /// diff --git a/tutorial/tutorial_3_connecting_peers.cpp b/tutorial/tutorial_3_connecting_peers.cpp index 0bc505f..433e055 100644 --- a/tutorial/tutorial_3_connecting_peers.cpp +++ b/tutorial/tutorial_3_connecting_peers.cpp @@ -43,7 +43,7 @@ int main() { printf("=== Tutorial 3: Connecting Peers ===\n\n"); - setLogLevel(LogLevel::Fatal); + setLogLevel(LogLevel::None); /// ## Step 1: Create and start two nodes /// @@ -61,7 +61,6 @@ int main() Libp2pModuleImpl nodeA(optsA); Libp2pModuleImpl nodeB(optsB); - StdLogosResult startARes = nodeA.start(); if (!startARes.success) { fprintf(stderr, "Node A failed to start: %s\n", diff --git a/tutorial/tutorial_4_custom_protocol.cpp b/tutorial/tutorial_4_custom_protocol.cpp index 200d1c0..3a2393e 100644 --- a/tutorial/tutorial_4_custom_protocol.cpp +++ b/tutorial/tutorial_4_custom_protocol.cpp @@ -54,7 +54,7 @@ int main() { printf("=== Tutorial 4: Custom Protocol Handlers ===\n\n"); - setLogLevel(LogLevel::Fatal); + setLogLevel(LogLevel::None); /// ## Step 1: Create and start two nodes Libp2pModuleOptions optsA, optsB; @@ -63,7 +63,7 @@ int main() Libp2pModuleImpl nodeA(optsA); Libp2pModuleImpl nodeB(optsB); - + StdLogosResult startARes = nodeA.start(); if (!startARes.success) { fprintf(stderr, "Node A failed: %s\n", startARes.error.c_str()); diff --git a/tutorial/tutorial_5_kademlia_basics.cpp b/tutorial/tutorial_5_kademlia_basics.cpp index a396685..722fc1e 100644 --- a/tutorial/tutorial_5_kademlia_basics.cpp +++ b/tutorial/tutorial_5_kademlia_basics.cpp @@ -39,7 +39,7 @@ int main() { printf("=== Tutorial 5: Kademlia DHT Basics ===\n\n"); - setLogLevel(LogLevel::Fatal); + setLogLevel(LogLevel::None); /// ## Step 1: Create two nodes /// @@ -54,7 +54,6 @@ int main() // Node A is the bootstrap — no special config needed, just its address. Libp2pModuleImpl nodeA(optsA); - printf("Starting Node A (bootstrap)...\n"); StdLogosResult startARes = nodeA.start(); if (!startARes.success) { @@ -83,7 +82,7 @@ int main() optsB.mountKad = true; optsB.bootstrapNodes = {{peerIdA, addrsA}}; - Libp2pModuleImpl nodeB(optsB); + Libp2pModuleImpl nodeB(optsB); printf("Starting Node B (with Node A as bootstrap)...\n"); StdLogosResult startBRes = nodeB.start(); if (!startBRes.success) { diff --git a/tutorial/tutorial_6_kademlia_providers.cpp b/tutorial/tutorial_6_kademlia_providers.cpp index 98cd59a..82d3dd9 100644 --- a/tutorial/tutorial_6_kademlia_providers.cpp +++ b/tutorial/tutorial_6_kademlia_providers.cpp @@ -35,7 +35,7 @@ int main() { printf("=== Tutorial 6: Kademlia Provider Records ===\n\n"); - setLogLevel(LogLevel::Fatal); + setLogLevel(LogLevel::None); /// ## Step 1: Create two peers Libp2pModuleOptions optsA, optsB; diff --git a/tutorial/tutorial_7_gossipsub_polling.cpp b/tutorial/tutorial_7_gossipsub_polling.cpp index add3842..d17e444 100644 --- a/tutorial/tutorial_7_gossipsub_polling.cpp +++ b/tutorial/tutorial_7_gossipsub_polling.cpp @@ -36,7 +36,7 @@ int main() { printf("=== Tutorial 7: GossipSub - Polling for Messages ===\n\n"); - setLogLevel(LogLevel::Fatal); + setLogLevel(LogLevel::None); /// ## Step 1: Create two nodes with GossipSub enabled /// @@ -51,7 +51,6 @@ int main() Libp2pModuleImpl nodeA(optsA); Libp2pModuleImpl nodeB(optsB); - StdLogosResult startARes = nodeA.start(); if (!startARes.success) { diff --git a/tutorial/tutorial_8_gossipsub_event_callback.cpp b/tutorial/tutorial_8_gossipsub_event_callback.cpp index f7a2300..60790c7 100644 --- a/tutorial/tutorial_8_gossipsub_event_callback.cpp +++ b/tutorial/tutorial_8_gossipsub_event_callback.cpp @@ -35,7 +35,7 @@ int main() { printf("=== Tutorial 8: GossipSub - Event Callback Messages ===\n\n"); - setLogLevel(LogLevel::Fatal); + setLogLevel(LogLevel::None); /// ## Step 1: Create two nodes with GossipSub enabled Libp2pModuleOptions optsA, optsB; @@ -47,7 +47,6 @@ int main() Libp2pModuleImpl nodeA(optsA); Libp2pModuleImpl nodeB(optsB); - StdLogosResult startARes = nodeA.start(); if (!startARes.success) { diff --git a/tutorial/tutorial_9_service_discovery.cpp b/tutorial/tutorial_9_service_discovery.cpp index 1f6c6a7..55e9e41 100644 --- a/tutorial/tutorial_9_service_discovery.cpp +++ b/tutorial/tutorial_9_service_discovery.cpp @@ -35,7 +35,7 @@ int main() { printf("=== Tutorial 9: Service Discovery ===\n\n"); - setLogLevel(LogLevel::Fatal); + setLogLevel(LogLevel::None); /// ## Step 1: Create a bootstrap node /// @@ -46,7 +46,6 @@ int main() optsBootstrap.mountServiceDiscovery = true; Libp2pModuleImpl bootstrap(optsBootstrap); - StdLogosResult bootstrapStartRes = bootstrap.start(); if (!bootstrapStartRes.success) { fprintf(stderr, "Bootstrap failed: %s\n", From e2bd8970725a631f681b9d28cfe0b0e8d61a9f5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vlado=20Paji=C4=87?= Date: Thu, 30 Jul 2026 12:07:28 +0200 Subject: [PATCH 07/19] exercies --- tutorial/tutorial_0_introduction.cpp | 18 +++++++++++++++-- tutorial/tutorial_2_custom_config.cpp | 28 +++++++++++++-------------- 2 files changed, 30 insertions(+), 16 deletions(-) diff --git a/tutorial/tutorial_0_introduction.cpp b/tutorial/tutorial_0_introduction.cpp index 5fcc98e..b1f7073 100644 --- a/tutorial/tutorial_0_introduction.cpp +++ b/tutorial/tutorial_0_introduction.cpp @@ -43,13 +43,13 @@ /// ## Controlling libp2p Logs /// /// The wrapped libp2p binding can emit runtime logs. Tutorials set the log -/// level to `LogLevel::Fatal` by default so `stdout` only shows the tutorial's +/// level to `LogLevel::None` by default so `stdout` only shows the tutorial's /// own progress messages during normal runs. Choose another level such as /// `LogLevel::Info`, `LogLevel::Debug`, or `LogLevel::Trace` when you need more /// detail while debugging: /// /// ```cpp -/// StdLogosResult logRes = node.setLogLevel(LogLevel::Debug); +/// StdLogosResult logRes = node.setLogLevel(LogLevel::None); /// if (!logRes.success) { /// fprintf(stderr, "Failed to set libp2p log level: %s\n", /// logRes.error.c_str()); @@ -189,3 +189,17 @@ int main() /// ```bash /// nix --extra-experimental-features 'nix-command flakes' develop --command ./tutorial/build_tutorials.sh /// ``` + +/// ## Exercise: Enable libp2p debug logs +/// +/// Change this tutorial's log level from `LogLevel::None` to +/// `LogLevel::Debug`: +/// +/// ```cpp +/// StdLogosResult logRes = setLogLevel(LogLevel::Debug); +/// ``` +/// +/// Compile the tutorial binaries again, using the same command from above. +/// +/// Run tutorial 0 again. You should now see libp2p debug logs in `stdout` +/// alongside the tutorial's own progress messages. diff --git a/tutorial/tutorial_2_custom_config.cpp b/tutorial/tutorial_2_custom_config.cpp index fe164a3..3d923f7 100644 --- a/tutorial/tutorial_2_custom_config.cpp +++ b/tutorial/tutorial_2_custom_config.cpp @@ -148,6 +148,20 @@ int main() return 0; } +/// ## Summary +/// +/// In this tutorial you learned: +/// - How to configure a node with a fixed port +/// - How to control connection limits +/// - How to pass options via C++ struct or JSON +/// - How to verify the node's actual bound addresses + +/// ## Run tutorial +/// +/// ```bash +/// ./build/tutorial/tutorial_2_custom_config +/// ``` + /// ## Exercise: Try different configurations /// /// Experiment with these variations: @@ -163,17 +177,3 @@ int main() /// "/ip4/0.0.0.0/tcp/9094" /// }; /// ``` - -/// ## Summary -/// -/// In this tutorial you learned: -/// - How to configure a node with a fixed port -/// - How to control connection limits -/// - How to pass options via C++ struct or JSON -/// - How to verify the node's actual bound addresses - -/// ## Run tutorial -/// -/// ```bash -/// ./build/tutorial/tutorial_2_custom_config -/// ``` From 0b39b2795070dc6614edec8e9455a70cdb24c973 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vlado=20Paji=C4=87?= Date: Thu, 30 Jul 2026 12:11:20 +0200 Subject: [PATCH 08/19] add note --- tutorial/tutorial_0_introduction.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tutorial/tutorial_0_introduction.cpp b/tutorial/tutorial_0_introduction.cpp index b1f7073..8fc6f17 100644 --- a/tutorial/tutorial_0_introduction.cpp +++ b/tutorial/tutorial_0_introduction.cpp @@ -48,6 +48,12 @@ /// `LogLevel::Info`, `LogLevel::Debug`, or `LogLevel::Trace` when you need more /// detail while debugging: /// +/// In your own application, `LogLevel::Error` or `LogLevel::Fatal` is often a +/// useful default. It keeps normal output quiet while still surfacing conditions +/// that may indicate libp2p is misbehaving or that your integration code needs an +/// adjustment. Some error logs describe remote-peer behavior, retries, or +/// recoverable internal state, so they may not require any action from your side. +/// /// ```cpp /// StdLogosResult logRes = node.setLogLevel(LogLevel::None); /// if (!logRes.success) { From 49036f6e50a4995abc99128e5c006e34283db98c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vlado=20Paji=C4=87?= Date: Thu, 30 Jul 2026 12:11:45 +0200 Subject: [PATCH 09/19] refresh --- tutorial/docs/tutorial_0_introduction.md | 48 ++++++++++++++----- tutorial/docs/tutorial_10_peerstore.md | 9 +--- tutorial/docs/tutorial_11_circuit_relay.md | 9 +--- tutorial/docs/tutorial_1_node_lifecycle.md | 18 +++---- tutorial/docs/tutorial_2_custom_config.md | 39 +++++++-------- tutorial/docs/tutorial_3_connecting_peers.md | 9 +--- tutorial/docs/tutorial_4_custom_protocol.md | 9 +--- tutorial/docs/tutorial_5_kademlia_basics.md | 9 +--- .../docs/tutorial_6_kademlia_providers.md | 8 +--- tutorial/docs/tutorial_7_gossipsub_polling.md | 9 +--- .../tutorial_8_gossipsub_event_callback.md | 9 +--- tutorial/docs/tutorial_9_service_discovery.md | 9 +--- 12 files changed, 80 insertions(+), 105 deletions(-) diff --git a/tutorial/docs/tutorial_0_introduction.md b/tutorial/docs/tutorial_0_introduction.md index 1409a53..bf797f4 100644 --- a/tutorial/docs/tutorial_0_introduction.md +++ b/tutorial/docs/tutorial_0_introduction.md @@ -42,16 +42,22 @@ operation fails, they print a useful error message to `stderr` and return ## Controlling libp2p Logs -The wrapped libp2p binding can emit runtime logs. Tutorials disable those -logs by default so `stdout` only shows the tutorial's own progress messages. -Use `setLogLevel()` with `LogLevel::None` to disable logs, or choose another -level such as `LogLevel::Info`, `LogLevel::Debug`, or `LogLevel::Trace` when -you need more detail while debugging: +The wrapped libp2p binding can emit runtime logs. Tutorials set the log +level to `LogLevel::None` by default so `stdout` only shows the tutorial's +own progress messages during normal runs. Choose another level such as +`LogLevel::Info`, `LogLevel::Debug`, or `LogLevel::Trace` when you need more +detail while debugging: + +In your own application, `LogLevel::Error` or `LogLevel::Fatal` is often a +useful default. It keeps normal output quiet while still surfacing conditions +that may indicate libp2p is misbehaving or that your integration code needs an +adjustment. Some error logs describe remote-peer behavior, retries, or +recoverable internal state, so they may not require any action from your side. ```cpp StdLogosResult logRes = node.setLogLevel(LogLevel::None); if (!logRes.success) { - fprintf(stderr, "Failed to disable libp2p logs: %s\n", + fprintf(stderr, "Failed to set libp2p log level: %s\n", logRes.error.c_str()); return 1; } @@ -94,6 +100,15 @@ int main() { printf("=== Tutorial 0: Introduction and Common Patterns ===\n\n"); + // Silence logs from wrapped library. It is always advised to check result, + // but in future tutorials will avoid it in order to simplify code. + StdLogosResult logRes = setLogLevel(LogLevel::None); + if (!logRes.success) { + fprintf(stderr, "Failed to disable libp2p logs: %s\n", + logRes.error.c_str()); + return 1; + } + ``` ## Step 1: Create and start a node @@ -102,13 +117,6 @@ Even the first real operation returns a result. Check it before moving on. ```cpp Libp2pModuleImpl node; - StdLogosResult logRes = node.setLogLevel(LogLevel::None); - if (!logRes.success) { - fprintf(stderr, "Failed to disable libp2p logs: %s\n", - logRes.error.c_str()); - return 1; - } - StdLogosResult startRes = node.start(); if (!startRes.success) { fprintf(stderr, "Failed to start node: %s\n", @@ -202,6 +210,20 @@ tutorials with this command and then run it again: ```bash nix --extra-experimental-features 'nix-command flakes' develop --command ./tutorial/build_tutorials.sh ``` + +## Exercise: Enable libp2p debug logs + +Change this tutorial's log level from `LogLevel::None` to +`LogLevel::Debug`: + +```cpp +StdLogosResult logRes = setLogLevel(LogLevel::Debug); +``` + +Compile the tutorial binaries again, using the same command from above. + +Run tutorial 0 again. You should now see libp2p debug logs in `stdout` +alongside the tutorial's own progress messages. ---

Creating and Starting a libp2p Node →

diff --git a/tutorial/docs/tutorial_10_peerstore.md b/tutorial/docs/tutorial_10_peerstore.md index 6733d5a..de537ea 100644 --- a/tutorial/docs/tutorial_10_peerstore.md +++ b/tutorial/docs/tutorial_10_peerstore.md @@ -27,6 +27,8 @@ int main() { printf("=== Tutorial 10: Peer Store Management ===\n\n"); + setLogLevel(LogLevel::None); + ``` ## Step 1: Create two nodes @@ -44,13 +46,6 @@ contains real peer data after a connection is established. Libp2pModuleImpl node(opts); Libp2pModuleImpl remote(remoteOpts); - StdLogosResult logRes = node.setLogLevel(LogLevel::None); - if (!logRes.success) { - fprintf(stderr, "Failed to disable libp2p logs: %s\n", - logRes.error.c_str()); - return 1; - } - StdLogosResult startRes = node.start(); if (!startRes.success) { fprintf(stderr, "Node failed to start: %s\n", diff --git a/tutorial/docs/tutorial_11_circuit_relay.md b/tutorial/docs/tutorial_11_circuit_relay.md index de88620..06ac41e 100644 --- a/tutorial/docs/tutorial_11_circuit_relay.md +++ b/tutorial/docs/tutorial_11_circuit_relay.md @@ -45,6 +45,8 @@ int main() { printf("=== Tutorial 11: Circuit Relay ===\n\n"); + setLogLevel(LogLevel::None); + ``` ## Step 1: Create three nodes @@ -76,13 +78,6 @@ The Client connects to the Relay before dialing the Destination. Libp2pModuleImpl dest(optsDest); Libp2pModuleImpl client(optsClient); - StdLogosResult logRes = relay.setLogLevel(LogLevel::None); - if (!logRes.success) { - fprintf(stderr, "Failed to disable libp2p logs: %s\n", - logRes.error.c_str()); - return 1; - } - printf("Starting nodes...\n"); StdLogosResult relayStartRes = relay.start(); diff --git a/tutorial/docs/tutorial_1_node_lifecycle.md b/tutorial/docs/tutorial_1_node_lifecycle.md index 698bc5b..6724e30 100644 --- a/tutorial/docs/tutorial_1_node_lifecycle.md +++ b/tutorial/docs/tutorial_1_node_lifecycle.md @@ -23,24 +23,22 @@ Every program starts by including the module's single public header - `"plugin.h #include #include "plugin.h" +int main() +{ + printf("=== Tutorial 1: Creating and Starting a libp2p Node ===\n\n"); + + setLogLevel(LogLevel::None); + ``` The main class we work with is `Libp2pModuleImpl`. Let's create one with default options: + ```cpp -int main() -{ // Create a libp2p node with default configuration. // By default it listens on 127.0.0.1 with a random port (tcp/0). Libp2pModuleImpl node; - StdLogosResult logRes = node.setLogLevel(LogLevel::None); - if (!logRes.success) { - fprintf(stderr, "Failed to disable libp2p logs: %s\n", - logRes.error.c_str()); - return 1; - } - printf("Node object created (not yet started)\n"); ``` @@ -118,6 +116,8 @@ Always clean up by stopping the node when you're done. node.stop(); printf("Node stopped\n"); + printf("\n=== Tutorial 1 Complete ===\n"); + return 0; } diff --git a/tutorial/docs/tutorial_2_custom_config.md b/tutorial/docs/tutorial_2_custom_config.md index 78d5680..1c3c52e 100644 --- a/tutorial/docs/tutorial_2_custom_config.md +++ b/tutorial/docs/tutorial_2_custom_config.md @@ -35,6 +35,10 @@ provide a custom address in the `addrs` field. int main() { + printf("=== Tutorial 2: Custom Node Configuration ===\n\n"); + + setLogLevel(LogLevel::None); + ``` ## Method 1: Configure via C++ struct @@ -65,13 +69,6 @@ The most explicit way to configure a node is by constructing Libp2pModuleImpl node(options); - StdLogosResult logRes = node.setLogLevel(LogLevel::None); - if (!logRes.success) { - fprintf(stderr, "Failed to disable libp2p logs: %s\n", - logRes.error.c_str()); - return 1; - } - StdLogosResult startRes = node.start(); if (!startRes.success) { fprintf(stderr, "Failed to start node: %s\n", @@ -163,6 +160,20 @@ supplied via `Libp2pModuleOptions::fromJson()`. ``` +## Summary + +In this tutorial you learned: + - How to configure a node with a fixed port + - How to control connection limits + - How to pass options via C++ struct or JSON + - How to verify the node's actual bound addresses + +## Run tutorial + +```bash +./build/tutorial/tutorial_2_custom_config +``` + ## Exercise: Try different configurations Experiment with these variations: @@ -178,20 +189,6 @@ options.addrs = { "/ip4/0.0.0.0/tcp/9094" }; ``` - -## Summary - -In this tutorial you learned: - - How to configure a node with a fixed port - - How to control connection limits - - How to pass options via C++ struct or JSON - - How to verify the node's actual bound addresses - -## Run tutorial - -```bash -./build/tutorial/tutorial_2_custom_config -``` ---

← Creating and Starting a libp2p Node  |  Connecting Peers and Exchanging Data →

diff --git a/tutorial/docs/tutorial_3_connecting_peers.md b/tutorial/docs/tutorial_3_connecting_peers.md index a0aeef6..4ff620c 100644 --- a/tutorial/docs/tutorial_3_connecting_peers.md +++ b/tutorial/docs/tutorial_3_connecting_peers.md @@ -44,6 +44,8 @@ int main() { printf("=== Tutorial 3: Connecting Peers ===\n\n"); + setLogLevel(LogLevel::None); + ``` ## Step 1: Create and start two nodes @@ -63,13 +65,6 @@ For simplicity, both mount the built-in `/ipfs/ping/1.0.0` protocol Libp2pModuleImpl nodeA(optsA); Libp2pModuleImpl nodeB(optsB); - StdLogosResult logRes = nodeA.setLogLevel(LogLevel::None); - if (!logRes.success) { - fprintf(stderr, "Failed to disable libp2p logs: %s\n", - logRes.error.c_str()); - return 1; - } - StdLogosResult startARes = nodeA.start(); if (!startARes.success) { fprintf(stderr, "Node A failed to start: %s\n", diff --git a/tutorial/docs/tutorial_4_custom_protocol.md b/tutorial/docs/tutorial_4_custom_protocol.md index 914552b..4e6e3a3 100644 --- a/tutorial/docs/tutorial_4_custom_protocol.md +++ b/tutorial/docs/tutorial_4_custom_protocol.md @@ -58,6 +58,8 @@ int main() { printf("=== Tutorial 4: Custom Protocol Handlers ===\n\n"); + setLogLevel(LogLevel::None); + ``` ## Step 1: Create and start two nodes @@ -69,13 +71,6 @@ int main() Libp2pModuleImpl nodeA(optsA); Libp2pModuleImpl nodeB(optsB); - StdLogosResult logRes = nodeA.setLogLevel(LogLevel::None); - if (!logRes.success) { - fprintf(stderr, "Failed to disable libp2p logs: %s\n", - logRes.error.c_str()); - return 1; - } - StdLogosResult startARes = nodeA.start(); if (!startARes.success) { fprintf(stderr, "Node A failed: %s\n", startARes.error.c_str()); diff --git a/tutorial/docs/tutorial_5_kademlia_basics.md b/tutorial/docs/tutorial_5_kademlia_basics.md index e3c577f..f088cfa 100644 --- a/tutorial/docs/tutorial_5_kademlia_basics.md +++ b/tutorial/docs/tutorial_5_kademlia_basics.md @@ -40,6 +40,8 @@ int main() { printf("=== Tutorial 5: Kademlia DHT Basics ===\n\n"); + setLogLevel(LogLevel::None); + ``` ## Step 1: Create two nodes @@ -56,13 +58,6 @@ real network, one node would be a well-known bootstrap peer. // Node A is the bootstrap — no special config needed, just its address. Libp2pModuleImpl nodeA(optsA); - StdLogosResult logRes = nodeA.setLogLevel(LogLevel::None); - if (!logRes.success) { - fprintf(stderr, "Failed to disable libp2p logs: %s\n", - logRes.error.c_str()); - return 1; - } - printf("Starting Node A (bootstrap)...\n"); StdLogosResult startARes = nodeA.start(); if (!startARes.success) { diff --git a/tutorial/docs/tutorial_6_kademlia_providers.md b/tutorial/docs/tutorial_6_kademlia_providers.md index 813fe29..179dcad 100644 --- a/tutorial/docs/tutorial_6_kademlia_providers.md +++ b/tutorial/docs/tutorial_6_kademlia_providers.md @@ -35,6 +35,8 @@ with the provider API. int main() { printf("=== Tutorial 6: Kademlia Provider Records ===\n\n"); + + setLogLevel(LogLevel::None); ``` @@ -45,12 +47,6 @@ int main() optsA.mountKad = true; Libp2pModuleImpl nodeA(optsA); - StdLogosResult logRes = nodeA.setLogLevel(LogLevel::None); - if (!logRes.success) { - fprintf(stderr, "Failed to disable libp2p logs: %s\n", - logRes.error.c_str()); - return 1; - } StdLogosResult startARes = nodeA.start(); if (!startARes.success) { diff --git a/tutorial/docs/tutorial_7_gossipsub_polling.md b/tutorial/docs/tutorial_7_gossipsub_polling.md index 2742562..396464b 100644 --- a/tutorial/docs/tutorial_7_gossipsub_polling.md +++ b/tutorial/docs/tutorial_7_gossipsub_polling.md @@ -37,6 +37,8 @@ int main() { printf("=== Tutorial 7: GossipSub - Polling for Messages ===\n\n"); + setLogLevel(LogLevel::None); + ``` ## Step 1: Create two nodes with GossipSub enabled @@ -54,13 +56,6 @@ We keep it explicit here for clarity. Libp2pModuleImpl nodeA(optsA); Libp2pModuleImpl nodeB(optsB); - StdLogosResult logRes = nodeA.setLogLevel(LogLevel::None); - if (!logRes.success) { - fprintf(stderr, "Failed to disable libp2p logs: %s\n", - logRes.error.c_str()); - return 1; - } - StdLogosResult startARes = nodeA.start(); if (!startARes.success) { fprintf(stderr, "Node A failed: %s\n", startARes.error.c_str()); diff --git a/tutorial/docs/tutorial_8_gossipsub_event_callback.md b/tutorial/docs/tutorial_8_gossipsub_event_callback.md index c197d51..b660192 100644 --- a/tutorial/docs/tutorial_8_gossipsub_event_callback.md +++ b/tutorial/docs/tutorial_8_gossipsub_event_callback.md @@ -36,6 +36,8 @@ int main() { printf("=== Tutorial 8: GossipSub - Event Callback Messages ===\n\n"); + setLogLevel(LogLevel::None); + ``` ## Step 1: Create two nodes with GossipSub enabled @@ -50,13 +52,6 @@ int main() Libp2pModuleImpl nodeA(optsA); Libp2pModuleImpl nodeB(optsB); - StdLogosResult logRes = nodeA.setLogLevel(LogLevel::None); - if (!logRes.success) { - fprintf(stderr, "Failed to disable libp2p logs: %s\n", - logRes.error.c_str()); - return 1; - } - StdLogosResult startARes = nodeA.start(); if (!startARes.success) { fprintf(stderr, "Node A failed: %s\n", startARes.error.c_str()); diff --git a/tutorial/docs/tutorial_9_service_discovery.md b/tutorial/docs/tutorial_9_service_discovery.md index e6c4293..455b23e 100644 --- a/tutorial/docs/tutorial_9_service_discovery.md +++ b/tutorial/docs/tutorial_9_service_discovery.md @@ -36,6 +36,8 @@ int main() { printf("=== Tutorial 9: Service Discovery ===\n\n"); + setLogLevel(LogLevel::None); + ``` ## Step 1: Create a bootstrap node @@ -48,13 +50,6 @@ It relays service advertisements and lookup queries. optsBootstrap.mountServiceDiscovery = true; Libp2pModuleImpl bootstrap(optsBootstrap); - StdLogosResult logRes = bootstrap.setLogLevel(LogLevel::None); - if (!logRes.success) { - fprintf(stderr, "Failed to disable libp2p logs: %s\n", - logRes.error.c_str()); - return 1; - } - StdLogosResult bootstrapStartRes = bootstrap.start(); if (!bootstrapStartRes.success) { fprintf(stderr, "Bootstrap failed: %s\n", From 73a3a2f3188bede196838037d5de4c58686acc50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vlado=20Paji=C4=87?= Date: Thu, 30 Jul 2026 12:57:37 +0200 Subject: [PATCH 10/19] fix --- tutorial/docs/tutorial_0_introduction.md | 2 +- tutorial/tutorial_0_introduction.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tutorial/docs/tutorial_0_introduction.md b/tutorial/docs/tutorial_0_introduction.md index bf797f4..2b5df95 100644 --- a/tutorial/docs/tutorial_0_introduction.md +++ b/tutorial/docs/tutorial_0_introduction.md @@ -55,7 +55,7 @@ adjustment. Some error logs describe remote-peer behavior, retries, or recoverable internal state, so they may not require any action from your side. ```cpp -StdLogosResult logRes = node.setLogLevel(LogLevel::None); +StdLogosResult logRes = setLogLevel(LogLevel::None); if (!logRes.success) { fprintf(stderr, "Failed to set libp2p log level: %s\n", logRes.error.c_str()); diff --git a/tutorial/tutorial_0_introduction.cpp b/tutorial/tutorial_0_introduction.cpp index 8fc6f17..6e19758 100644 --- a/tutorial/tutorial_0_introduction.cpp +++ b/tutorial/tutorial_0_introduction.cpp @@ -55,7 +55,7 @@ /// recoverable internal state, so they may not require any action from your side. /// /// ```cpp -/// StdLogosResult logRes = node.setLogLevel(LogLevel::None); +/// StdLogosResult logRes = setLogLevel(LogLevel::None); /// if (!logRes.success) { /// fprintf(stderr, "Failed to set libp2p log level: %s\n", /// logRes.error.c_str()); From 216f5780f99d113b74e8a57026427d96e3630e4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vlado=20Paji=C4=87?= Date: Thu, 30 Jul 2026 15:47:14 +0200 Subject: [PATCH 11/19] update --- tutorial/docs/tutorial_0_introduction.md | 14 +++++++------- tutorial/tutorial_0_introduction.cpp | 14 +++++++------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/tutorial/docs/tutorial_0_introduction.md b/tutorial/docs/tutorial_0_introduction.md index 2b5df95..76d36e1 100644 --- a/tutorial/docs/tutorial_0_introduction.md +++ b/tutorial/docs/tutorial_0_introduction.md @@ -48,14 +48,8 @@ own progress messages during normal runs. Choose another level such as `LogLevel::Info`, `LogLevel::Debug`, or `LogLevel::Trace` when you need more detail while debugging: -In your own application, `LogLevel::Error` or `LogLevel::Fatal` is often a -useful default. It keeps normal output quiet while still surfacing conditions -that may indicate libp2p is misbehaving or that your integration code needs an -adjustment. Some error logs describe remote-peer behavior, retries, or -recoverable internal state, so they may not require any action from your side. - ```cpp -StdLogosResult logRes = setLogLevel(LogLevel::None); +StdLogosResult logRes = setLogLevel(LogLevel::Info); if (!logRes.success) { fprintf(stderr, "Failed to set libp2p log level: %s\n", logRes.error.c_str()); @@ -63,6 +57,12 @@ if (!logRes.success) { } ``` +In your own application, `LogLevel::Error` or `LogLevel::Fatal` is often a +useful default. It keeps normal output quiet while still surfacing conditions +that may indicate libp2p is misbehaving or that your integration code needs an +adjustment. Some error logs describe remote-peer behavior, retries, or +recoverable internal state, so they may not require any action from your side. + ## Convert JSON Values Explicitly The `value` field is JSON. Convert it to the C++ type you need at the diff --git a/tutorial/tutorial_0_introduction.cpp b/tutorial/tutorial_0_introduction.cpp index 6e19758..79a77a5 100644 --- a/tutorial/tutorial_0_introduction.cpp +++ b/tutorial/tutorial_0_introduction.cpp @@ -48,14 +48,8 @@ /// `LogLevel::Info`, `LogLevel::Debug`, or `LogLevel::Trace` when you need more /// detail while debugging: /// -/// In your own application, `LogLevel::Error` or `LogLevel::Fatal` is often a -/// useful default. It keeps normal output quiet while still surfacing conditions -/// that may indicate libp2p is misbehaving or that your integration code needs an -/// adjustment. Some error logs describe remote-peer behavior, retries, or -/// recoverable internal state, so they may not require any action from your side. -/// /// ```cpp -/// StdLogosResult logRes = setLogLevel(LogLevel::None); +/// StdLogosResult logRes = setLogLevel(LogLevel::Info); /// if (!logRes.success) { /// fprintf(stderr, "Failed to set libp2p log level: %s\n", /// logRes.error.c_str()); @@ -63,6 +57,12 @@ /// } /// ``` /// +/// In your own application, `LogLevel::Error` or `LogLevel::Fatal` is often a +/// useful default. It keeps normal output quiet while still surfacing conditions +/// that may indicate libp2p is misbehaving or that your integration code needs an +/// adjustment. Some error logs describe remote-peer behavior, retries, or +/// recoverable internal state, so they may not require any action from your side. +/// /// ## Convert JSON Values Explicitly /// /// The `value` field is JSON. Convert it to the C++ type you need at the From 69c30575ca2a6c07c230e2ccb9ac2a522149ddbb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vlado=20Paji=C4=87?= Date: Thu, 30 Jul 2026 15:56:26 +0200 Subject: [PATCH 12/19] update --- tutorial/docs/tutorial_0_introduction.md | 2 +- tutorial/tutorial_0_introduction.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tutorial/docs/tutorial_0_introduction.md b/tutorial/docs/tutorial_0_introduction.md index 76d36e1..5132fc3 100644 --- a/tutorial/docs/tutorial_0_introduction.md +++ b/tutorial/docs/tutorial_0_introduction.md @@ -49,7 +49,7 @@ own progress messages during normal runs. Choose another level such as detail while debugging: ```cpp -StdLogosResult logRes = setLogLevel(LogLevel::Info); +StdLogosResult logRes = setLogLevel(LogLevel::Debug); if (!logRes.success) { fprintf(stderr, "Failed to set libp2p log level: %s\n", logRes.error.c_str()); diff --git a/tutorial/tutorial_0_introduction.cpp b/tutorial/tutorial_0_introduction.cpp index 79a77a5..88bdca7 100644 --- a/tutorial/tutorial_0_introduction.cpp +++ b/tutorial/tutorial_0_introduction.cpp @@ -49,7 +49,7 @@ /// detail while debugging: /// /// ```cpp -/// StdLogosResult logRes = setLogLevel(LogLevel::Info); +/// StdLogosResult logRes = setLogLevel(LogLevel::Debug); /// if (!logRes.success) { /// fprintf(stderr, "Failed to set libp2p log level: %s\n", /// logRes.error.c_str()); From ff8efd746cc4955024548ade3a7cd907050852e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vlado=20Paji=C4=87?= Date: Thu, 30 Jul 2026 19:05:05 +0200 Subject: [PATCH 13/19] update deps --- CMakeLists.txt | 4 ++++ flake.lock | 6 +++--- src/plugin.cpp | 4 ++-- src/plugin.h | 11 ++++++++--- 4 files changed, 17 insertions(+), 8 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c4e7871..71abedc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,8 @@ cmake_minimum_required(VERSION 3.14) project(Libp2pModulePlugin LANGUAGES CXX) +find_package(nlohmann_json REQUIRED) + if(DEFINED ENV{LOGOS_MODULE_BUILDER_ROOT}) include($ENV{LOGOS_MODULE_BUILDER_ROOT}/cmake/LogosModule.cmake) else() @@ -31,4 +33,6 @@ logos_module( tinycbor ) +target_link_libraries(libp2p_module_module_plugin PUBLIC nlohmann_json::nlohmann_json) + add_subdirectory(tutorial) diff --git a/flake.lock b/flake.lock index 2d40250..a01fb5b 100644 --- a/flake.lock +++ b/flake.lock @@ -148,11 +148,11 @@ "nixpkgs": "nixpkgs" }, "locked": { - "lastModified": 1785335110, - "narHash": "sha256-CRPBSjLcKjfoSdP8zFVKr+Rhi1ylXWRZ7wJJt736Slk=", + "lastModified": 1785427304, + "narHash": "sha256-PTUsUuUYNTbNJTqIQ80An5+T6xr/7w7kh97gu7daJR0=", "owner": "vacp2p", "repo": "nim-libp2p", - "rev": "a70c615c287a94e1134f45c05c18c338c7a3bc8f", + "rev": "082fb7a3ef22229c852b83881b11631b2ccb5835", "type": "github" }, "original": { diff --git a/src/plugin.cpp b/src/plugin.cpp index 309e416..607475d 100644 --- a/src/plugin.cpp +++ b/src/plugin.cpp @@ -214,10 +214,10 @@ StdLogosResult Libp2pModuleImpl::createNode(const std::string& config) { } StdLogosResult Libp2pModuleImpl::setLogLevel(LogLevel level) { - return callSync("Failed to set log level", [&](SyncPromise* p) { + return callStaticWith("Failed to set log level", [&](SyncPromise* p) { return libp2p_static_set_log_level(static_cast(level), &Libp2pModuleImpl::cbBool, p); - }); + }, [](const SyncResult&) -> StdLogosResult { return {true, {}, ""}; }); } void Libp2pModuleImpl::destroyContext() { diff --git a/src/plugin.h b/src/plugin.h index 7db680e..74ec584 100644 --- a/src/plugin.h +++ b/src/plugin.h @@ -132,12 +132,13 @@ class Libp2pModuleImpl { std::function emitEvent; + static StdLogosResult setLogLevel(LogLevel level); + bool ok(); StdLogosResult status(); StdLogosResult createNode(const std::string& config); StdLogosResult getNodeInfo(const std::string& field); - StdLogosResult setLogLevel(LogLevel level); StdLogosResult start(); StdLogosResult stop(); @@ -298,8 +299,8 @@ class Libp2pModuleImpl { // Same dance without the context check, for the `{.ffiStatic.}` bindings: // they take no ctx and run on the library's own static context. template - StdLogosResult callStaticWith(const char* errPrefix, Invoke&& invoke, Transform&& transform, - int awaitMs = kDefaultOpTimeoutMs) { + static StdLogosResult callStaticWith(const char* errPrefix, Invoke&& invoke, Transform&& transform, + int awaitMs = kDefaultOpTimeoutMs) { auto* p = new SyncPromise(); auto f = p->get_future(); int ret = invoke(p); @@ -319,3 +320,7 @@ class Libp2pModuleImpl { return transform(r); } }; + +inline StdLogosResult setLogLevel(LogLevel level) { + return Libp2pModuleImpl::setLogLevel(level); +} From 79c2d5b05424dbb6e8444b23d6797df4414eb41d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vlado=20Paji=C4=87?= Date: Thu, 30 Jul 2026 19:09:32 +0200 Subject: [PATCH 14/19] update --- tutorial/tutorial_0_introduction.cpp | 2 +- tutorial/tutorial_10_peerstore.cpp | 2 +- tutorial/tutorial_11_circuit_relay.cpp | 2 +- tutorial/tutorial_1_node_lifecycle.cpp | 2 +- tutorial/tutorial_2_custom_config.cpp | 2 +- tutorial/tutorial_3_connecting_peers.cpp | 2 +- tutorial/tutorial_4_custom_protocol.cpp | 2 +- tutorial/tutorial_5_kademlia_basics.cpp | 2 +- tutorial/tutorial_6_kademlia_providers.cpp | 2 +- tutorial/tutorial_7_gossipsub_polling.cpp | 2 +- tutorial/tutorial_8_gossipsub_event_callback.cpp | 2 +- tutorial/tutorial_9_service_discovery.cpp | 2 +- 12 files changed, 12 insertions(+), 12 deletions(-) diff --git a/tutorial/tutorial_0_introduction.cpp b/tutorial/tutorial_0_introduction.cpp index 88bdca7..549dae2 100644 --- a/tutorial/tutorial_0_introduction.cpp +++ b/tutorial/tutorial_0_introduction.cpp @@ -101,7 +101,7 @@ int main() // Silence logs from wrapped library. It is always advised to check result, // but in future tutorials will avoid it in order to simplify code. - StdLogosResult logRes = setLogLevel(LogLevel::None); + StdLogosResult logRes = setLogLevel(LogLevel::Fatal); if (!logRes.success) { fprintf(stderr, "Failed to disable libp2p logs: %s\n", logRes.error.c_str()); diff --git a/tutorial/tutorial_10_peerstore.cpp b/tutorial/tutorial_10_peerstore.cpp index 3109bea..f6a5200 100644 --- a/tutorial/tutorial_10_peerstore.cpp +++ b/tutorial/tutorial_10_peerstore.cpp @@ -26,7 +26,7 @@ int main() { printf("=== Tutorial 10: Peer Store Management ===\n\n"); - setLogLevel(LogLevel::None); + setLogLevel(LogLevel::Fatal); /// ## Step 1: Create two nodes /// diff --git a/tutorial/tutorial_11_circuit_relay.cpp b/tutorial/tutorial_11_circuit_relay.cpp index 8ea55f1..6748d97 100644 --- a/tutorial/tutorial_11_circuit_relay.cpp +++ b/tutorial/tutorial_11_circuit_relay.cpp @@ -44,7 +44,7 @@ int main() { printf("=== Tutorial 11: Circuit Relay ===\n\n"); - setLogLevel(LogLevel::None); + setLogLevel(LogLevel::Fatal); /// ## Step 1: Create three nodes /// diff --git a/tutorial/tutorial_1_node_lifecycle.cpp b/tutorial/tutorial_1_node_lifecycle.cpp index 1d05628..0208211 100644 --- a/tutorial/tutorial_1_node_lifecycle.cpp +++ b/tutorial/tutorial_1_node_lifecycle.cpp @@ -26,7 +26,7 @@ int main() { printf("=== Tutorial 1: Creating and Starting a libp2p Node ===\n\n"); - setLogLevel(LogLevel::None); + setLogLevel(LogLevel::Fatal); /// The main class we work with is `Libp2pModuleImpl`. Let's create one with /// default options: diff --git a/tutorial/tutorial_2_custom_config.cpp b/tutorial/tutorial_2_custom_config.cpp index 3d923f7..c7a3cf2 100644 --- a/tutorial/tutorial_2_custom_config.cpp +++ b/tutorial/tutorial_2_custom_config.cpp @@ -36,7 +36,7 @@ int main() { printf("=== Tutorial 2: Custom Node Configuration ===\n\n"); - setLogLevel(LogLevel::None); + setLogLevel(LogLevel::Fatal); /// ## Method 1: Configure via C++ struct /// diff --git a/tutorial/tutorial_3_connecting_peers.cpp b/tutorial/tutorial_3_connecting_peers.cpp index 433e055..721fc13 100644 --- a/tutorial/tutorial_3_connecting_peers.cpp +++ b/tutorial/tutorial_3_connecting_peers.cpp @@ -43,7 +43,7 @@ int main() { printf("=== Tutorial 3: Connecting Peers ===\n\n"); - setLogLevel(LogLevel::None); + setLogLevel(LogLevel::Fatal); /// ## Step 1: Create and start two nodes /// diff --git a/tutorial/tutorial_4_custom_protocol.cpp b/tutorial/tutorial_4_custom_protocol.cpp index 3a2393e..c0fe0a7 100644 --- a/tutorial/tutorial_4_custom_protocol.cpp +++ b/tutorial/tutorial_4_custom_protocol.cpp @@ -54,7 +54,7 @@ int main() { printf("=== Tutorial 4: Custom Protocol Handlers ===\n\n"); - setLogLevel(LogLevel::None); + setLogLevel(LogLevel::Fatal); /// ## Step 1: Create and start two nodes Libp2pModuleOptions optsA, optsB; diff --git a/tutorial/tutorial_5_kademlia_basics.cpp b/tutorial/tutorial_5_kademlia_basics.cpp index 722fc1e..3a6b9b4 100644 --- a/tutorial/tutorial_5_kademlia_basics.cpp +++ b/tutorial/tutorial_5_kademlia_basics.cpp @@ -39,7 +39,7 @@ int main() { printf("=== Tutorial 5: Kademlia DHT Basics ===\n\n"); - setLogLevel(LogLevel::None); + setLogLevel(LogLevel::Fatal); /// ## Step 1: Create two nodes /// diff --git a/tutorial/tutorial_6_kademlia_providers.cpp b/tutorial/tutorial_6_kademlia_providers.cpp index 82d3dd9..98cd59a 100644 --- a/tutorial/tutorial_6_kademlia_providers.cpp +++ b/tutorial/tutorial_6_kademlia_providers.cpp @@ -35,7 +35,7 @@ int main() { printf("=== Tutorial 6: Kademlia Provider Records ===\n\n"); - setLogLevel(LogLevel::None); + setLogLevel(LogLevel::Fatal); /// ## Step 1: Create two peers Libp2pModuleOptions optsA, optsB; diff --git a/tutorial/tutorial_7_gossipsub_polling.cpp b/tutorial/tutorial_7_gossipsub_polling.cpp index d17e444..06c7f35 100644 --- a/tutorial/tutorial_7_gossipsub_polling.cpp +++ b/tutorial/tutorial_7_gossipsub_polling.cpp @@ -36,7 +36,7 @@ int main() { printf("=== Tutorial 7: GossipSub - Polling for Messages ===\n\n"); - setLogLevel(LogLevel::None); + setLogLevel(LogLevel::Fatal); /// ## Step 1: Create two nodes with GossipSub enabled /// diff --git a/tutorial/tutorial_8_gossipsub_event_callback.cpp b/tutorial/tutorial_8_gossipsub_event_callback.cpp index 60790c7..f16e1a7 100644 --- a/tutorial/tutorial_8_gossipsub_event_callback.cpp +++ b/tutorial/tutorial_8_gossipsub_event_callback.cpp @@ -35,7 +35,7 @@ int main() { printf("=== Tutorial 8: GossipSub - Event Callback Messages ===\n\n"); - setLogLevel(LogLevel::None); + setLogLevel(LogLevel::Fatal); /// ## Step 1: Create two nodes with GossipSub enabled Libp2pModuleOptions optsA, optsB; diff --git a/tutorial/tutorial_9_service_discovery.cpp b/tutorial/tutorial_9_service_discovery.cpp index 55e9e41..e58edfe 100644 --- a/tutorial/tutorial_9_service_discovery.cpp +++ b/tutorial/tutorial_9_service_discovery.cpp @@ -35,7 +35,7 @@ int main() { printf("=== Tutorial 9: Service Discovery ===\n\n"); - setLogLevel(LogLevel::None); + setLogLevel(LogLevel::Fatal); /// ## Step 1: Create a bootstrap node /// From f4f52eb8572f5f14477b8ac66ed4f2823d22094c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vlado=20Paji=C4=87?= Date: Thu, 30 Jul 2026 19:12:04 +0200 Subject: [PATCH 15/19] save log to context --- src/plugin.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/plugin.cpp b/src/plugin.cpp index 607475d..800178c 100644 --- a/src/plugin.cpp +++ b/src/plugin.cpp @@ -55,6 +55,8 @@ void reapLateContext(std::future f) { } constexpr char kModuleVersion[] = "1.0.0"; + +std::atomic g_requestedLogLevel{LOG_LEVEL_DEBUG}; } void Libp2pModuleImpl::publishEmitEvent() { @@ -192,6 +194,9 @@ StdLogosResult Libp2pModuleImpl::createContext() { libp2p_ctx_add_on_incoming_stream_listener(ctx, &Libp2pModuleImpl::onIncomingStream, this); libp2p_ctx_add_on_pubsub_message_listener(ctx, &Libp2pModuleImpl::onPubsubMessage, this); + auto logRes = setLogLevel(static_cast(g_requestedLogLevel.load())); + if (!logRes.success) return logRes; + return {true, {}, ""}; } @@ -214,10 +219,14 @@ StdLogosResult Libp2pModuleImpl::createNode(const std::string& config) { } StdLogosResult Libp2pModuleImpl::setLogLevel(LogLevel level) { - return callStaticWith("Failed to set log level", [&](SyncPromise* p) { + auto res = callStaticWith("Failed to set log level", [&](SyncPromise* p) { return libp2p_static_set_log_level(static_cast(level), &Libp2pModuleImpl::cbBool, p); }, [](const SyncResult&) -> StdLogosResult { return {true, {}, ""}; }); + if (res.success) { + g_requestedLogLevel.store(static_cast(level)); + } + return res; } void Libp2pModuleImpl::destroyContext() { From a9d2c90c3c56c23cbd6e4f65e1ab20c140d530fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vlado=20Paji=C4=87?= Date: Thu, 30 Jul 2026 19:26:08 +0200 Subject: [PATCH 16/19] cfg log lvl --- src/plugin.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/plugin.cpp b/src/plugin.cpp index 800178c..1ceda76 100644 --- a/src/plugin.cpp +++ b/src/plugin.cpp @@ -178,6 +178,7 @@ StdLogosResult Libp2pModuleImpl::createContext() { // identity; a supplied key gives a stable peer id across restarts. m_libp2pConfig.privKey = NimFfiBytes{m_privKey.empty() ? nullptr : m_privKey.data(), m_privKey.size()}; + m_libp2pConfig.logLevel = g_requestedLogLevel.load(); auto r = spawnContext(m_libp2pConfig); if (!r.ok) { From 5e8de4870e2bdaa1bbf5cfc7a359680f4b394cb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vlado=20Paji=C4=87?= Date: Thu, 30 Jul 2026 19:40:17 +0200 Subject: [PATCH 17/19] update --- src/plugin.h | 20 +++++++++++-------- tutorial/docs/tutorial_0_introduction.md | 13 ++++++++---- tutorial/docs/tutorial_10_peerstore.md | 2 +- tutorial/docs/tutorial_11_circuit_relay.md | 2 +- tutorial/docs/tutorial_1_node_lifecycle.md | 2 +- tutorial/docs/tutorial_2_custom_config.md | 2 +- tutorial/docs/tutorial_3_connecting_peers.md | 2 +- tutorial/docs/tutorial_4_custom_protocol.md | 2 +- tutorial/docs/tutorial_5_kademlia_basics.md | 2 +- .../docs/tutorial_6_kademlia_providers.md | 2 +- tutorial/docs/tutorial_7_gossipsub_polling.md | 2 +- .../tutorial_8_gossipsub_event_callback.md | 2 +- tutorial/docs/tutorial_9_service_discovery.md | 2 +- tutorial/tutorial_0_introduction.cpp | 11 +++++++--- 14 files changed, 40 insertions(+), 26 deletions(-) diff --git a/src/plugin.h b/src/plugin.h index 74ec584..2b7c3be 100644 --- a/src/plugin.h +++ b/src/plugin.h @@ -53,15 +53,19 @@ struct SyncResult { LibP2PCtx* newCtx = nullptr; }; +// libp2p logs treat levels as inclusive minimum thresholds: +// `Trace` emits trace and above, `Debug` emits debug and above, etc. +// `None` is the lowest threshold, so it emits all logs; use `Fatal` for the +// quietest built-in threshold. enum class LogLevel : int64_t { - None = LOG_LEVEL_NONE, - Trace = LOG_LEVEL_TRACE, - Debug = LOG_LEVEL_DEBUG, - Info = LOG_LEVEL_INFO, - Notice = LOG_LEVEL_NOTICE, - Warn = LOG_LEVEL_WARN, - Error = LOG_LEVEL_ERROR, - Fatal = LOG_LEVEL_FATAL, + None = LOG_LEVEL_NONE, // All logs. + Trace = LOG_LEVEL_TRACE, // Trace and above. + Debug = LOG_LEVEL_DEBUG, // Debug and above. + Info = LOG_LEVEL_INFO, // Info and above. + Notice = LOG_LEVEL_NOTICE, // Notice and above. + Warn = LOG_LEVEL_WARN, // Warn and above. + Error = LOG_LEVEL_ERROR, // Error and above. + Fatal = LOG_LEVEL_FATAL, // Fatal only. }; using SyncPromise = std::promise; diff --git a/tutorial/docs/tutorial_0_introduction.md b/tutorial/docs/tutorial_0_introduction.md index 5132fc3..ea897bc 100644 --- a/tutorial/docs/tutorial_0_introduction.md +++ b/tutorial/docs/tutorial_0_introduction.md @@ -43,7 +43,7 @@ operation fails, they print a useful error message to `stderr` and return ## Controlling libp2p Logs The wrapped libp2p binding can emit runtime logs. Tutorials set the log -level to `LogLevel::None` by default so `stdout` only shows the tutorial's +level to `LogLevel::Fatal` by default so `stdout` only shows the tutorial's own progress messages during normal runs. Choose another level such as `LogLevel::Info`, `LogLevel::Debug`, or `LogLevel::Trace` when you need more detail while debugging: @@ -57,8 +57,13 @@ if (!logRes.success) { } ``` -In your own application, `LogLevel::Error` or `LogLevel::Fatal` is often a -useful default. It keeps normal output quiet while still surfacing conditions +Log levels are inclusive minimum thresholds: `LogLevel::Trace` emits trace +and above, `LogLevel::Debug` emits debug and above, and so on. +`LogLevel::None` is the lowest threshold, so it emits all logs; it does not +disable logging. Use `LogLevel::Fatal` for the quietest built-in threshold. + +In your own application, `LogLevel::Error` is often a useful default. +It keeps normal output quiet while still surfacing conditions that may indicate libp2p is misbehaving or that your integration code needs an adjustment. Some error logs describe remote-peer behavior, retries, or recoverable internal state, so they may not require any action from your side. @@ -102,7 +107,7 @@ int main() // Silence logs from wrapped library. It is always advised to check result, // but in future tutorials will avoid it in order to simplify code. - StdLogosResult logRes = setLogLevel(LogLevel::None); + StdLogosResult logRes = setLogLevel(LogLevel::Fatal); if (!logRes.success) { fprintf(stderr, "Failed to disable libp2p logs: %s\n", logRes.error.c_str()); diff --git a/tutorial/docs/tutorial_10_peerstore.md b/tutorial/docs/tutorial_10_peerstore.md index de537ea..51af45c 100644 --- a/tutorial/docs/tutorial_10_peerstore.md +++ b/tutorial/docs/tutorial_10_peerstore.md @@ -27,7 +27,7 @@ int main() { printf("=== Tutorial 10: Peer Store Management ===\n\n"); - setLogLevel(LogLevel::None); + setLogLevel(LogLevel::Fatal); ``` diff --git a/tutorial/docs/tutorial_11_circuit_relay.md b/tutorial/docs/tutorial_11_circuit_relay.md index 06ac41e..6ba9bdc 100644 --- a/tutorial/docs/tutorial_11_circuit_relay.md +++ b/tutorial/docs/tutorial_11_circuit_relay.md @@ -45,7 +45,7 @@ int main() { printf("=== Tutorial 11: Circuit Relay ===\n\n"); - setLogLevel(LogLevel::None); + setLogLevel(LogLevel::Fatal); ``` diff --git a/tutorial/docs/tutorial_1_node_lifecycle.md b/tutorial/docs/tutorial_1_node_lifecycle.md index 6724e30..491649a 100644 --- a/tutorial/docs/tutorial_1_node_lifecycle.md +++ b/tutorial/docs/tutorial_1_node_lifecycle.md @@ -27,7 +27,7 @@ int main() { printf("=== Tutorial 1: Creating and Starting a libp2p Node ===\n\n"); - setLogLevel(LogLevel::None); + setLogLevel(LogLevel::Fatal); ``` diff --git a/tutorial/docs/tutorial_2_custom_config.md b/tutorial/docs/tutorial_2_custom_config.md index 1c3c52e..0dd029a 100644 --- a/tutorial/docs/tutorial_2_custom_config.md +++ b/tutorial/docs/tutorial_2_custom_config.md @@ -37,7 +37,7 @@ int main() { printf("=== Tutorial 2: Custom Node Configuration ===\n\n"); - setLogLevel(LogLevel::None); + setLogLevel(LogLevel::Fatal); ``` diff --git a/tutorial/docs/tutorial_3_connecting_peers.md b/tutorial/docs/tutorial_3_connecting_peers.md index 4ff620c..5e9b998 100644 --- a/tutorial/docs/tutorial_3_connecting_peers.md +++ b/tutorial/docs/tutorial_3_connecting_peers.md @@ -44,7 +44,7 @@ int main() { printf("=== Tutorial 3: Connecting Peers ===\n\n"); - setLogLevel(LogLevel::None); + setLogLevel(LogLevel::Fatal); ``` diff --git a/tutorial/docs/tutorial_4_custom_protocol.md b/tutorial/docs/tutorial_4_custom_protocol.md index 4e6e3a3..43e45db 100644 --- a/tutorial/docs/tutorial_4_custom_protocol.md +++ b/tutorial/docs/tutorial_4_custom_protocol.md @@ -58,7 +58,7 @@ int main() { printf("=== Tutorial 4: Custom Protocol Handlers ===\n\n"); - setLogLevel(LogLevel::None); + setLogLevel(LogLevel::Fatal); ``` diff --git a/tutorial/docs/tutorial_5_kademlia_basics.md b/tutorial/docs/tutorial_5_kademlia_basics.md index f088cfa..cbfcd26 100644 --- a/tutorial/docs/tutorial_5_kademlia_basics.md +++ b/tutorial/docs/tutorial_5_kademlia_basics.md @@ -40,7 +40,7 @@ int main() { printf("=== Tutorial 5: Kademlia DHT Basics ===\n\n"); - setLogLevel(LogLevel::None); + setLogLevel(LogLevel::Fatal); ``` diff --git a/tutorial/docs/tutorial_6_kademlia_providers.md b/tutorial/docs/tutorial_6_kademlia_providers.md index 179dcad..cd39bb7 100644 --- a/tutorial/docs/tutorial_6_kademlia_providers.md +++ b/tutorial/docs/tutorial_6_kademlia_providers.md @@ -36,7 +36,7 @@ int main() { printf("=== Tutorial 6: Kademlia Provider Records ===\n\n"); - setLogLevel(LogLevel::None); + setLogLevel(LogLevel::Fatal); ``` diff --git a/tutorial/docs/tutorial_7_gossipsub_polling.md b/tutorial/docs/tutorial_7_gossipsub_polling.md index 396464b..69cc7e9 100644 --- a/tutorial/docs/tutorial_7_gossipsub_polling.md +++ b/tutorial/docs/tutorial_7_gossipsub_polling.md @@ -37,7 +37,7 @@ int main() { printf("=== Tutorial 7: GossipSub - Polling for Messages ===\n\n"); - setLogLevel(LogLevel::None); + setLogLevel(LogLevel::Fatal); ``` diff --git a/tutorial/docs/tutorial_8_gossipsub_event_callback.md b/tutorial/docs/tutorial_8_gossipsub_event_callback.md index b660192..5a9b2e2 100644 --- a/tutorial/docs/tutorial_8_gossipsub_event_callback.md +++ b/tutorial/docs/tutorial_8_gossipsub_event_callback.md @@ -36,7 +36,7 @@ int main() { printf("=== Tutorial 8: GossipSub - Event Callback Messages ===\n\n"); - setLogLevel(LogLevel::None); + setLogLevel(LogLevel::Fatal); ``` diff --git a/tutorial/docs/tutorial_9_service_discovery.md b/tutorial/docs/tutorial_9_service_discovery.md index 455b23e..2d3ebb0 100644 --- a/tutorial/docs/tutorial_9_service_discovery.md +++ b/tutorial/docs/tutorial_9_service_discovery.md @@ -36,7 +36,7 @@ int main() { printf("=== Tutorial 9: Service Discovery ===\n\n"); - setLogLevel(LogLevel::None); + setLogLevel(LogLevel::Fatal); ``` diff --git a/tutorial/tutorial_0_introduction.cpp b/tutorial/tutorial_0_introduction.cpp index 549dae2..99c4f51 100644 --- a/tutorial/tutorial_0_introduction.cpp +++ b/tutorial/tutorial_0_introduction.cpp @@ -43,7 +43,7 @@ /// ## Controlling libp2p Logs /// /// The wrapped libp2p binding can emit runtime logs. Tutorials set the log -/// level to `LogLevel::None` by default so `stdout` only shows the tutorial's +/// level to `LogLevel::Fatal` by default so `stdout` only shows the tutorial's /// own progress messages during normal runs. Choose another level such as /// `LogLevel::Info`, `LogLevel::Debug`, or `LogLevel::Trace` when you need more /// detail while debugging: @@ -57,8 +57,13 @@ /// } /// ``` /// -/// In your own application, `LogLevel::Error` or `LogLevel::Fatal` is often a -/// useful default. It keeps normal output quiet while still surfacing conditions +/// Log levels are inclusive minimum thresholds: `LogLevel::Trace` emits trace +/// and above, `LogLevel::Debug` emits debug and above, and so on. +/// `LogLevel::None` is the lowest threshold, so it emits all logs; it does not +/// disable logging. Use `LogLevel::Fatal` for the quietest built-in threshold. +/// +/// In your own application, `LogLevel::Error` is often a useful default. +/// It keeps normal output quiet while still surfacing conditions /// that may indicate libp2p is misbehaving or that your integration code needs an /// adjustment. Some error logs describe remote-peer behavior, retries, or /// recoverable internal state, so they may not require any action from your side. From d7134a62c6d8de64ef9a1197a9019aa41d2c948f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vlado=20Paji=C4=87?= Date: Fri, 31 Jul 2026 12:08:28 +0200 Subject: [PATCH 18/19] update --- flake.lock | 6 +++--- src/plugin.cpp | 14 ++------------ src/plugin.h | 4 ++-- tutorial/docs/tutorial_0_introduction.md | 19 +++++-------------- tutorial/tutorial_0_introduction.cpp | 19 +++++-------------- 5 files changed, 17 insertions(+), 45 deletions(-) diff --git a/flake.lock b/flake.lock index a01fb5b..7c6d18b 100644 --- a/flake.lock +++ b/flake.lock @@ -148,11 +148,11 @@ "nixpkgs": "nixpkgs" }, "locked": { - "lastModified": 1785427304, - "narHash": "sha256-PTUsUuUYNTbNJTqIQ80An5+T6xr/7w7kh97gu7daJR0=", + "lastModified": 1785445744, + "narHash": "sha256-aLK2iPNsffW9Q2k2LlHq4BE6D25A6vmN9wPC+oz+M9o=", "owner": "vacp2p", "repo": "nim-libp2p", - "rev": "082fb7a3ef22229c852b83881b11631b2ccb5835", + "rev": "f169c5ed39f653a0718d00686a9fabc67194dabf", "type": "github" }, "original": { diff --git a/src/plugin.cpp b/src/plugin.cpp index 1ceda76..2c9fb3e 100644 --- a/src/plugin.cpp +++ b/src/plugin.cpp @@ -195,9 +195,6 @@ StdLogosResult Libp2pModuleImpl::createContext() { libp2p_ctx_add_on_incoming_stream_listener(ctx, &Libp2pModuleImpl::onIncomingStream, this); libp2p_ctx_add_on_pubsub_message_listener(ctx, &Libp2pModuleImpl::onPubsubMessage, this); - auto logRes = setLogLevel(static_cast(g_requestedLogLevel.load())); - if (!logRes.success) return logRes; - return {true, {}, ""}; } @@ -219,15 +216,8 @@ StdLogosResult Libp2pModuleImpl::createNode(const std::string& config) { return createContext(); } -StdLogosResult Libp2pModuleImpl::setLogLevel(LogLevel level) { - auto res = callStaticWith("Failed to set log level", [&](SyncPromise* p) { - return libp2p_static_set_log_level(static_cast(level), - &Libp2pModuleImpl::cbBool, p); - }, [](const SyncResult&) -> StdLogosResult { return {true, {}, ""}; }); - if (res.success) { - g_requestedLogLevel.store(static_cast(level)); - } - return res; +void Libp2pModuleImpl::setLogLevel(LogLevel level) { + g_requestedLogLevel.store(static_cast(level)); } void Libp2pModuleImpl::destroyContext() { diff --git a/src/plugin.h b/src/plugin.h index 2b7c3be..b7db4b7 100644 --- a/src/plugin.h +++ b/src/plugin.h @@ -136,7 +136,7 @@ class Libp2pModuleImpl { std::function emitEvent; - static StdLogosResult setLogLevel(LogLevel level); + static void setLogLevel(LogLevel level); bool ok(); StdLogosResult status(); @@ -325,6 +325,6 @@ class Libp2pModuleImpl { } }; -inline StdLogosResult setLogLevel(LogLevel level) { +inline void setLogLevel(LogLevel level) { return Libp2pModuleImpl::setLogLevel(level); } diff --git a/tutorial/docs/tutorial_0_introduction.md b/tutorial/docs/tutorial_0_introduction.md index ea897bc..d720d28 100644 --- a/tutorial/docs/tutorial_0_introduction.md +++ b/tutorial/docs/tutorial_0_introduction.md @@ -49,12 +49,9 @@ own progress messages during normal runs. Choose another level such as detail while debugging: ```cpp -StdLogosResult logRes = setLogLevel(LogLevel::Debug); -if (!logRes.success) { - fprintf(stderr, "Failed to set libp2p log level: %s\n", - logRes.error.c_str()); - return 1; -} +setLogLevel(LogLevel::Debug); +// ... or +Libp2pModuleImpl::setLogLevel(LogLevel::Debug); ``` Log levels are inclusive minimum thresholds: `LogLevel::Trace` emits trace @@ -105,14 +102,8 @@ int main() { printf("=== Tutorial 0: Introduction and Common Patterns ===\n\n"); - // Silence logs from wrapped library. It is always advised to check result, - // but in future tutorials will avoid it in order to simplify code. - StdLogosResult logRes = setLogLevel(LogLevel::Fatal); - if (!logRes.success) { - fprintf(stderr, "Failed to disable libp2p logs: %s\n", - logRes.error.c_str()); - return 1; - } + // Silence logs from wrapped library. + setLogLevel(LogLevel::Fatal); ``` diff --git a/tutorial/tutorial_0_introduction.cpp b/tutorial/tutorial_0_introduction.cpp index 99c4f51..ba77762 100644 --- a/tutorial/tutorial_0_introduction.cpp +++ b/tutorial/tutorial_0_introduction.cpp @@ -49,12 +49,9 @@ /// detail while debugging: /// /// ```cpp -/// StdLogosResult logRes = setLogLevel(LogLevel::Debug); -/// if (!logRes.success) { -/// fprintf(stderr, "Failed to set libp2p log level: %s\n", -/// logRes.error.c_str()); -/// return 1; -/// } +/// setLogLevel(LogLevel::Debug); +/// // ... or +/// Libp2pModuleImpl::setLogLevel(LogLevel::Debug); /// ``` /// /// Log levels are inclusive minimum thresholds: `LogLevel::Trace` emits trace @@ -104,14 +101,8 @@ int main() { printf("=== Tutorial 0: Introduction and Common Patterns ===\n\n"); - // Silence logs from wrapped library. It is always advised to check result, - // but in future tutorials will avoid it in order to simplify code. - StdLogosResult logRes = setLogLevel(LogLevel::Fatal); - if (!logRes.success) { - fprintf(stderr, "Failed to disable libp2p logs: %s\n", - logRes.error.c_str()); - return 1; - } + // Silence logs from wrapped library. + setLogLevel(LogLevel::Fatal); /// ## Step 1: Create and start a node /// From a6a57bd2900fda746dce75a13df1857e9200db62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vlado=20Paji=C4=87?= Date: Fri, 31 Jul 2026 12:17:16 +0200 Subject: [PATCH 19/19] update --- tutorial/docs/tutorial_0_introduction.md | 2 +- tutorial/tutorial_0_introduction.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tutorial/docs/tutorial_0_introduction.md b/tutorial/docs/tutorial_0_introduction.md index d720d28..dce190c 100644 --- a/tutorial/docs/tutorial_0_introduction.md +++ b/tutorial/docs/tutorial_0_introduction.md @@ -213,7 +213,7 @@ Change this tutorial's log level from `LogLevel::None` to `LogLevel::Debug`: ```cpp -StdLogosResult logRes = setLogLevel(LogLevel::Debug); +setLogLevel(LogLevel::Debug); ``` Compile the tutorial binaries again, using the same command from above. diff --git a/tutorial/tutorial_0_introduction.cpp b/tutorial/tutorial_0_introduction.cpp index ba77762..1b3fb8c 100644 --- a/tutorial/tutorial_0_introduction.cpp +++ b/tutorial/tutorial_0_introduction.cpp @@ -198,7 +198,7 @@ int main() /// `LogLevel::Debug`: /// /// ```cpp -/// StdLogosResult logRes = setLogLevel(LogLevel::Debug); +/// setLogLevel(LogLevel::Debug); /// ``` /// /// Compile the tutorial binaries again, using the same command from above.