Skip to main content

Logging

Beginner
Tutorial

Overview

The canister logging feature is designed to provide developers with insight into their canister's behavior and assist with scenarios where their canister traps. This feature supports log messages for:

  • Heartbeats.

  • Timers.

  • Pre/post upgrade and canister_init.

  • Update calls.

  • Queries, only if called in replicated mode.

A canister's controller is able to retrieve the canister's logs, even when executions trap, using dfx canister logs.

Non-replicated calls currently are supported for logging.

Using dfx

A canister's logs can be viewed using the dfx canister logs command. As an example, consider a Rust canister with the following code:

use std::cell::RefCell;

use candid::{Nat, Principal};
use ic_cdk::{
export_candid, println,
};

thread_local! {
// create a cell that holds a counter
static COUNTER: std::cell::RefCell<u32> = RefCell::default();
}


#[ic_cdk::update]
fn produce_logs() {
// print the counter value
COUNTER.with_borrow_mut(|counter| {
println!("counter: {}", *counter);
*counter += 1;
});
}

export_candid!();

This simple canister provides an incremental counter method that includes a print function that will return output to the command line and the canister's logs.

Note that this example uses update calls, as non-replicated query calls do not currently support logging.

You can call the canister's method and view the associated logged output for each call. For example, if this canister is deployed as logs_backend, you can call the canister's produce_logs method a few times to increment the counter and get the following command line output:

dfx canister call logs_backend produce_logs
2024-06-04 21:14:25.882276 UTC: [Canister br5f7-7uaaa-aaaaa-qaaca-cai] counter: 0
()
dfx canister call logs_backend produce_logs
2024-06-04 21:18:18.094003 UTC: [Canister br5f7-7uaaa-aaaaa-qaaca-cai] counter: 1
()
dfx canister call logs_backend produce_logs
2024-06-04 21:18:46.036022 UTC: [Canister br5f7-7uaaa-aaaaa-qaaca-cai] counter: 2
()

Then, you can call the canister's logs, which in this case will return the same output that was logged to the command line:

dfx canister logs logs_backend
[0. 2024-06-04T21:14:25.882276Z]: counter: 0
[1. 2024-06-04T21:18:18.094003Z]: counter: 1
[2. 2024-06-04T21:18:46.036022Z]: counter: 2