Logging with msg!
msg! writes human-readable lines to transaction logs. Useful for development and ops, but each call costs compute units - budget logs like any hot-path code.
Search across all documentation pages
msg! writes human-readable lines to transaction logs. Useful for development and ops, but each call costs compute units - budget logs like any hot-path code.
solana_program::msg!("swap in={} out={}", amount_in, amount_out);When to reach for this:
#[cfg(feature = "verbose_logs")]
macro_rules! vlog { ($($t:tt)*) => { solana_program::msg!($($t)*) }; }
#[cfg(not(feature = "verbose_logs"))]
macro_rules! vlog { ($($t:tt)*) => {}; }What this demonstrates:
Logs charge per syscall + bytes.
sol_log_data for compact key/value.
// Prefer fixed prefixes: "MYPROG:step1"| Alternative | Use When | Don't Use When |
|---|---|---|
| Custom errors only | User-facing | Internal debug |
| Anchor events | Indexer-friendly | CU still applies |
| Off-chain simulation | Dev | Prod |
Non-trivial - simulate.
Yes logMessages.
Binary slices.
Same syscall.
Syscall log.
Tx limit + CU.
Events better.
Geyser plugins.
Recommended or gate.
Same.
Re-profile after upgrade.
Shows logs in trace.
Stack versions: This page was written for Agave 4.1.1, Solana CLI 3.0.10, Anchor 0.32.1, anchor-lang 0.32.1, Rust 1.91.1, @solana/kit 7.0.0, Surfpool 0.12.0, and LiteSVM 0.6.x.
Reviewed by Chris St. John·Last updated Jul 16, 2026