Canister Logging Support [Community Consideration]

Here’s an update on specs, link.

And also dfinity/examples repo was updated to have cases for both replicated and non-replicated queries, link:

rust/canister_logs/src/lib.rs:

#[update]
fn print(text: String) {
    ic_cdk::print(text);
}

#[query]
fn print_query(text: String) {
    ic_cdk::print(text);
}

and tests

	# Test print via update call.
	dfx canister call canister_logs print 'print via update'
	dfx canister logs canister_logs \
		| grep 'print via update' && echo 'PASS'

	# Test print via replicated query call.
	dfx canister call --update canister_logs print_query 'print via replicated query'
	dfx canister logs canister_logs \
		| grep 'print via replicated query' && echo 'PASS'

	# Test print via non-replicated query call should NOT record the message.
	dfx canister call --query canister_logs print_query 'print via non-replicated query'
	! dfx canister logs canister_logs \
		| grep 'print via non-replicated query' && echo 'PASS'

Can I ask what cycle costs are involved with serving up logs (both when a request is and isn’t authorised)?

Calling fetch_canister_logs can only be done in non-replicated mode and it returns the whole 4KiB log buffer. Since the size of the buffer is small currently there is no cost.

When we increase buffer size in the future the cost for storing/serving logs may apply.

https://internetcomputer.org/docs/references/ic-interface-spec#ic-fetch_canister_logs

Thanks @maksym, this is very helpful info.

At that point, can I ask whether protected logs (visible only to the controller or a principal whitelist) will cost cycles to perform the authorization check for unauthorised callers? Would you plan to filter out unauthorised ingress messages to reduce the potential for cycle drain? (at least making it expensive for the attacker)

I’m interested in ways to ensure predictable cycle usage when blackholing canisters that are intended as common good background workers (which don’t expose any endpoints, reducing potential for cycle drain attacks).

Given that the logs endpoint isn’t controlled by the canister developer (other than configuring access control), it seems avoiding the emergence of a cycle drain attack vector should be considered important.

Thank you for raising these valid concerns.

Currently fetching canister logs API is only available in non-replicated mode and returns a small fixed-size 4KiB buffer. Because of this there’s no cycle cost for storing or serving logs, and no risk of cycle drain attacks – it’s free at this size.

In the future we do plan to support larger log buffers and charge accordingly. However, to avoid breaking existing assumptions and exposing (blackholed) canisters to new attack vectors we expect this to be opt-in only. That means:

  • The default 4KiB buffer will likely remain free of charge
  • Larger buffers will come with explicit configuration and associated cycle cost

So blackholed canisters won’t be affected unless they explicitly opt-in to large buffers. Hope this makes sense.

Sounds great, thanks @maksym!