Lazy formatting for logger calls#5046
Conversation
Test Results for Commit 55cb4acPull Request 5046: Results Test Case Results
Last updated: 2026-03-24 04:29:23 UTC |
There was a problem hiding this comment.
Pull request overview
This PR updates logging and formatting across the Nano node codebase to avoid eager string conversions at call sites by relying on fmt formatting support (including new lazy wrappers) so disabled log levels don’t pay conversion/allocation costs. It also introduces a distinct nano::account type (separate from public_key) to enable account-notation formatting and adds channel formatting support for transport logging.
Changes:
- Replace many logger call-site
.to_string()/.to_account()conversions with lazy formatting viafmt::formattersupport andnano::log::as_*wrappers. - Introduce
nano::accountas a distinct type frompublic_key, add DB conversion and hashing support, and adjust affected APIs/usages. - Add reusable balance/channel formatting utilities and refactor balance formatting to support stream-based encoding.
Reviewed changes
Copilot reviewed 47 out of 47 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| nano/test_common/system.cpp | Uses lazy node-id formatting in startup logs. |
| nano/test_common/rate_observer.cpp | Switches stat enum stringification to ADL-friendly to_string usage. |
| nano/store/db_val.hpp | Adds db_val conversion operator to nano::account. |
| nano/store/db_val_templ.hpp | Implements db_val → nano::account conversion via byte read. |
| nano/secure/ledger.hpp | Changes epoch_signer/epoch_link to return by value (supports new account semantics). |
| nano/secure/ledger.cpp | Replaces eager balance formatting with lazy as_nano; minor cleanup in linked-account logic; updates epoch helpers. |
| nano/rpc/rpc.cpp | Avoids eager address .to_string() in warning log. |
| nano/rpc_test/rpc_context.hpp | Updates forward declarations for new nano::account type. |
| nano/rpc_test/common.hpp | Updates forward declarations for new nano::account type. |
| nano/qt/qt.hpp | Adjusts wallet ctor/member types to reflect account vs public_key separation. |
| nano/qt/qt.cpp | Updates wallet constructor implementation to match new signature/type storage. |
| nano/node/wallet.cpp | Replaces eager account/hash/amount string conversions in wallet logs with lazy formatting wrappers and direct formatting. |
| nano/node/transport/tcp_listener.cpp | Formats endpoint type enum lazily (no eager to_string at call site). |
| nano/node/transport/tcp_channels.cpp | Adds formatting support includes; removes eager node-id/channel conversions in logs. |
| nano/node/transport/formatting.hpp | Adds fmt formatters for channels and shared_ptr<channel> for lazy logging. |
| nano/node/request_aggregator.cpp | Removes eager channel .to_string() from debug logs via channel formatter. |
| nano/node/repcrawler.cpp | Uses lazy formatting for representative accounts and channels. |
| nano/node/portmapping.cpp | Removes eager external address .to_string() in logs. |
| nano/node/online_reps.cpp | Uses as_nano for balances and formats accounts lazily. |
| nano/node/node.cpp | Uses lazy node-id formatting and avoids eager genesis/account string conversions. |
| nano/node/network.cpp | Removes eager channel .to_string() in connect observer log. |
| nano/node/monitor.cpp | Uses as_nano for quorum/weights in monitor logs. |
| nano/node/bounded_backlog.cpp | Removes eager hash .to_string() in rollback logs. |
| nano/node/bootstrap/frontier_strategy.cpp | Removes eager channel .to_string() in debug logs. |
| nano/node/bootstrap/dependency_strategy.cpp | Removes eager channel .to_string() in debug logs. |
| nano/node/bootstrap/bootstrap_context.cpp | Removes eager channel .to_string() across multiple bootstrap request logs. |
| nano/node/block_processor.cpp | Removes eager hash/source/channel conversions; relies on enum/channel formatters. |
| nano/nano_node/benchmarks/benchmarks.cpp | Uses fmt::print instead of std::cout << fmt::format to avoid intermediate string creation. |
| nano/nano_node/benchmarks/benchmark_pipeline.cpp | Converts multiple benchmark output lines to fmt::print. |
| nano/nano_node/benchmarks/benchmark_elections.cpp | Converts multiple benchmark output lines to fmt::print. |
| nano/nano_node/benchmarks/benchmark_cementing.cpp | Converts multiple benchmark output lines to fmt::print. |
| nano/nano_node/benchmarks/benchmark_block_processing.cpp | Converts multiple benchmark output lines to fmt::print. |
| nano/lib/thread_runner.cpp | Logs thread role enum lazily (no eager to_string). |
| nano/lib/stats.cpp | Logs stat::sample lazily via enum formatter. |
| nano/lib/stats_enums.hpp | Moves stat to_string declarations into namespace nano::stat. |
| nano/lib/stats_enums.cpp | Implements stat to_string in namespace nano::stat. |
| nano/lib/object_stream_adapters.hpp | Removes the generic fmt formatter adapter for all object-streamable types (prefers explicit wrapping). |
| nano/lib/numbers.hpp | Introduces nano::account class (distinct from public_key); adds encode_node_id to public_key. |
| nano/lib/numbers.cpp | Implements public_key::encode_node_id; refactors balance formatting into stream-based encoder. |
| nano/lib/numbers_templ.hpp | Adds std::hash and boost::hash specializations for nano::account. |
| nano/lib/fwd.hpp | Updates forward declaration from using account = public_key to class account. |
| nano/lib/formatting.hpp | Adds generic enum formatter (ADL to_string), new lazy log wrappers, and additional type formatters. |
| nano/lib/balance_formatting.hpp | New reusable balance encoding helpers (stream-based, precision/grouping). |
| nano/core_test/vote_cache.cpp | Updates helper signature for account const-correctness. |
| nano/core_test/object_stream.cpp | Updates fmt adapter test to use explicit nano::streamed wrapping. |
| nano/core_test/numbers.cpp | Adds tests for new balance encoding path; renames/extends balance formatting tests. |
| nano/core_test/enums.cpp | Updates stat enum to_string tests to use unqualified to_string (ADL) after namespace move. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
7958272 to
8538f0b
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 47 out of 47 changed files in this pull request and generated 3 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
8538f0b to
61a3afb
Compare
61a3afb to
55cb4ac
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 47 out of 47 changed files in this pull request and generated 4 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| logger.info (nano::log::type::ledger, "Active balance: {} | pending: {} | burned: {}", | ||
| nano::uint128_union{ static_cast<nano::uint128_t> (active_balance) }.format_balance (nano::nano_ratio, 0, true), | ||
| nano::uint128_union{ static_cast<nano::uint128_t> (pending_balance) }.format_balance (nano::nano_ratio, 0, true), | ||
| nano::uint128_union{ static_cast<nano::uint128_t> (burned_balance) }.format_balance (nano::nano_ratio, 0, true)); | ||
| nano::log::as_nano (static_cast<nano::uint128_t> (active_balance)), | ||
| nano::log::as_nano (static_cast<nano::uint128_t> (pending_balance)), | ||
| nano::log::as_nano (static_cast<nano::uint128_t> (burned_balance))); |
There was a problem hiding this comment.
nano::log::as_nano() defaults to precision=1, but these log lines previously used format_balance(..., precision=0, ...). This changes the log output (e.g., showing 1 decimal or “< 0.1”) compared to the prior behavior. Pass an explicit precision of 0 to as_nano here to preserve existing output.
| logger.info (nano::log::type::ledger, "Weight committed: {} | unused: {}", | ||
| nano::uint128_union{ rep_weights.get_weight_committed () }.format_balance (nano::nano_ratio, 0, true), | ||
| nano::uint128_union{ rep_weights.get_weight_unused () }.format_balance (nano::nano_ratio, 0, true)); | ||
| nano::log::as_nano (rep_weights.get_weight_committed ()), | ||
| nano::log::as_nano (rep_weights.get_weight_unused ())); |
There was a problem hiding this comment.
Same precision issue as above: these calls replaced format_balance(..., precision=0, ...) but use as_nano() without specifying precision, which defaults to 1. Consider calling as_nano(value, 0) here to keep log output stable.
| rep.first.to_account (), | ||
| nano::uint128_union (rep.second).format_balance (nano_ratio, 0, true)); | ||
| rep.first, | ||
| nano::log::as_nano (rep.second)); |
There was a problem hiding this comment.
This log previously formatted the bootstrap rep weight with format_balance(..., precision=0, ...), but nano::log::as_nano() defaults to precision=1. If the intent is only to make formatting lazy (not to change output), pass an explicit precision of 0 here.
| nano::log::as_nano (rep.second)); | |
| nano::log::as_nano (rep.second, 0)); |
Add `nano::log::as_account` and `nano::log::as_node_id` wrappers so log formatting can stream public keys without creating temporary strings. Implement ostream-based node ID encoding and update log call sites to use the new wrappers.
Replace the `account` alias with a dedicated class derived from `public_key` and add the formatter, hash, forward declarations, and `db_val` conversion needed to use it across the codebase. Adjust wallet, Qt, RPC test, and vote cache interfaces to match the new type semantics and avoid storing mutable account references.
Replace benchmark log statements that streamed `fmt::format(...)` into `std::cout` with direct `fmt::print(...)` calls.
Extract shared balance formatting helpers into `balance_formatting.hpp` and add `uint128_union::encode_balance()` so callers can write formatted balances directly to streams.
Expose a free encode_balance overload for uint128_t values and update as_nano/as_raw_nano to format by reference without constructing temporary uint128_union instances.
55cb4ac to
2623ba3
Compare
Replace eager string conversions in logger call sites with lazy formatting using
fmt::formatterspecializations. This avoids unnecessary string allocations when the log level is disabled. Add lazy wrappers (nano::log::as_account,as_node_id,as_nano,as_raw_nano), and channel formatting support. Makenano::accounta distinct type frompublic_keyso it automatically formats in account notation (nano_...).