solana_program_runtime/
stable_log.rs

1//! Stable program log messages
2//!
3//! The format of these log messages should not be modified to avoid breaking downstream consumers
4//! of program logging
5use {
6    base64::{prelude::BASE64_STANDARD, Engine},
7    itertools::Itertools,
8    solana_log_collector::{ic_logger_msg, LogCollector},
9    solana_pubkey::Pubkey,
10    std::{cell::RefCell, rc::Rc},
11};
12
13/// Log a program invoke.
14///
15/// The general form is:
16///
17/// ```notrust
18/// "Program <address> invoke [<depth>]"
19/// ```
20pub fn program_invoke(
21    log_collector: &Option<Rc<RefCell<LogCollector>>>,
22    program_id: &Pubkey,
23    invoke_depth: usize,
24) {
25    ic_logger_msg!(
26        log_collector,
27        "Program {} invoke [{}]",
28        program_id,
29        invoke_depth
30    );
31}
32
33/// Log a message from the program itself.
34///
35/// The general form is:
36///
37/// ```notrust
38/// "Program log: <program-generated output>"
39/// ```
40///
41/// That is, any program-generated output is guaranteed to be prefixed by "Program log: "
42pub fn program_log(log_collector: &Option<Rc<RefCell<LogCollector>>>, message: &str) {
43    ic_logger_msg!(log_collector, "Program log: {}", message);
44}
45
46/// Emit a program data.
47///
48/// The general form is:
49///
50/// ```notrust
51/// "Program data: <binary-data-in-base64>*"
52/// ```
53///
54/// That is, any program-generated output is guaranteed to be prefixed by "Program data: "
55pub fn program_data(log_collector: &Option<Rc<RefCell<LogCollector>>>, data: &[&[u8]]) {
56    ic_logger_msg!(
57        log_collector,
58        "Program data: {}",
59        data.iter().map(|v| BASE64_STANDARD.encode(v)).join(" ")
60    );
61}
62
63/// Log return data as from the program itself. This line will not be present if no return
64/// data was set, or if the return data was set to zero length.
65///
66/// The general form is:
67///
68/// ```notrust
69/// "Program return: <program-id> <program-generated-data-in-base64>"
70/// ```
71///
72/// That is, any program-generated output is guaranteed to be prefixed by "Program return: "
73pub fn program_return(
74    log_collector: &Option<Rc<RefCell<LogCollector>>>,
75    program_id: &Pubkey,
76    data: &[u8],
77) {
78    ic_logger_msg!(
79        log_collector,
80        "Program return: {} {}",
81        program_id,
82        BASE64_STANDARD.encode(data)
83    );
84}
85
86/// Log successful program execution.
87///
88/// The general form is:
89///
90/// ```notrust
91/// "Program <address> success"
92/// ```
93pub fn program_success(log_collector: &Option<Rc<RefCell<LogCollector>>>, program_id: &Pubkey) {
94    ic_logger_msg!(log_collector, "Program {} success", program_id);
95}
96
97/// Log program execution failure
98///
99/// The general form is:
100///
101/// ```notrust
102/// "Program <address> failed: <program error details>"
103/// ```
104pub fn program_failure<E: std::fmt::Display>(
105    log_collector: &Option<Rc<RefCell<LogCollector>>>,
106    program_id: &Pubkey,
107    err: &E,
108) {
109    ic_logger_msg!(log_collector, "Program {} failed: {}", program_id, err);
110}