Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
5115b63
docs: add EdDSA/Ed25519 to allowed WebAuthn signature schemes
mraszyk May 13, 2026
603c136
feat: canister logs extensions
mraszyk May 13, 2026
e31e334
Revert "docs: add EdDSA/Ed25519 to allowed WebAuthn signature schemes"
mraszyk May 13, 2026
9d5b475
note
mraszyk May 13, 2026
f3919c0
Merge branch 'main' into mraszyk/canister-logs
mraszyk May 13, 2026
bfa60a5
reset log_memory_limit if canister out of cycles
mraszyk Jun 3, 2026
3665ee0
docs(logs): clarify canister log trimming direction
mraszyk Jul 17, 2026
92bd88e
docs(logs): drop fetch_canister_logs_cost (calls do not require cycles)
mraszyk Jul 17, 2026
9eb29f6
docs(logs): remove cycles-transfer note from fetch_canister_logs
mraszyk Jul 17, 2026
b3b765b
docs(logs): clarify returned-log size bound is the max response size
mraszyk Jul 17, 2026
9aef188
Merge branch 'main' into mraszyk/canister-logs
mraszyk Aug 11, 2026
99b8ef6
docs(logs): fix state field name in out-of-cycles rule
mraszyk Aug 11, 2026
aab9bb7
docs(logs): account for log memory store in canister memory usage
mraszyk Aug 11, 2026
8557682
docs(logs): reserve cycles for log memory limit changes
mraszyk Aug 11, 2026
c335515
docs(logs): model cycles consumed by log memory store resize
mraszyk Aug 11, 2026
254602a
docs(logs): restrict log_memory_limit to 0 or at least 4096 bytes
mraszyk Aug 17, 2026
d0e6239
docs(logs): return log_memory_limit from canister_status in the abstr…
mraszyk Aug 17, 2026
612cf51
docs(logs): return visibility settings from canister_status in the ab…
mraszyk Aug 17, 2026
daf217f
Merge remote-tracking branch 'origin/main' into mraszyk/canister-logs
mraszyk Aug 18, 2026
6c78fad
docs(logs): add changelog entry 0.67.0 for canister logs extensions
mraszyk Aug 31, 2026
b3e76aa
docs(logs): address PR feedback on canister logs extensions
mraszyk Sep 1, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions docs/guides/canister-management/logs.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,8 @@ icp canister logs <canister-name> -e ic --since-index 100 --until-index 200

Timestamp and index filters cannot be combined with `--follow`.

Filtering also changes which records are dropped when the selected logs exceed the response size. An unfiltered read trims the oldest records, so it returns the most recent logs (the output ends with the newest record). A filtered read trims the newest records instead, so it returns the oldest records that match the filter (the output starts with the oldest matching record), which lets you page forward through a range by advancing the start of the filter.

To output logs as JSON for programmatic processing:

```bash
Expand Down Expand Up @@ -178,6 +180,8 @@ The default log buffer size is 4096 bytes. When the buffer fills up, older log e
icp canister settings update <canister-name> -e ic --log-memory-limit 2mib
```

The limit must be either 0 (no memory for logs) or at least 4096 bytes: values between 1 and 4095 are rejected.

Supported suffixes: `kb` (1,000 bytes), `kib` (1,024 bytes), `mb` (1,000,000 bytes), `mib` (1,048,576 bytes). In `icp.yaml`:

```yaml
Expand Down
4 changes: 1 addition & 3 deletions docs/guides/canister-management/settings.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -197,14 +197,12 @@ settings:

### Log memory limit

{/* Needs human verification: log_memory_limit is exposed by icp-cli but is absent from the canonical ic.did: verify whether this is a management canister setting or an icp-cli layer setting */}

Maximum memory for storing canister logs. Oldest logs are purged when usage exceeds this value.

| Property | Value |
|----------|-------|
| Type | Integer or string with suffix |
| Max | 2 MiB |
| Valid values | 0, or 4096 bytes up to 2 MiB (values between 1 and 4095 are rejected) |
| Default | 4096 bytes |
| icp.yaml key | `log_memory_limit` |

Expand Down
255 changes: 172 additions & 83 deletions docs/references/ic-interface-spec/abstract-behavior.md

Large diffs are not rendered by default.

21 changes: 21 additions & 0 deletions docs/references/ic-interface-spec/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,27 @@ sidebar:

## Changelog {#changelog}

### 0.67.0 (2026-08-31) {$0_67_0}
* New canister setting `log_memory_limit` bounding the memory used for canister logs: it must be either `0`
or a number between `4096` and `2097152` (`2 MiB`), inclusively, with the default value `4096`.
The oldest canister logs are purged if the total memory used for canister logs exceeds this value.
The memory used by the store holding the canister logs is determined by this setting
(it does not depend on the canister logs actually stored) and counted in the canister's memory usage.
Hence, raising this setting might require reserving cycles. Changing this setting also resizes
the store holding the canister logs, which consumes cycles.
The setting is reset if the canister runs out of cycles.
* `canister_status` returns the setting `log_memory_limit` and the memory used by the store holding
the canister logs in the new field `log_memory_store_size` of `memory_metrics`.
* `fetch_canister_logs` can also be called by canisters via replicated (update) calls.
It still cannot be called by external users via replicated calls.
* New optional `filter` argument of `fetch_canister_logs` restricting the returned logs to a range of
log indices (`by_idx`) or timestamps (`by_timestamp_nanos`).
* The total size of all logs returned by `fetch_canister_logs` is bounded by an implementation-defined
constant chosen so as not to exceed the maximum response size (instead of the previous bound of 4KiB).
If the selected logs do not all fit, an unfiltered read trims the oldest logs (so the response ends
with the newest log) and a filtered read trims the newest logs (so the response starts with the oldest
log satisfying the filter).

### 0.66.0 (2026-08-17) {$0_66_0}
* Two new paths in the certified state tree, `/canister/<canister_id>/canister_creation_timestamp`
(the time at which the canister was created) and `/canister/<canister_id>/last_install_timestamp`
Expand Down
25 changes: 22 additions & 3 deletions docs/references/ic-interface-spec/management-canister.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,14 @@ The optional `settings` parameter can be used to set the following settings:

Default value: `controllers`.

- `log_memory_limit` (`nat`)

Must be either `0` or a number between `4096` and `2097152` (`2 MiB`), inclusively, and indicates the maximum amount of memory used for canister logs.
In particular, values between `1` and `4095`, inclusively, are not allowed.
Oldest canister logs are purged if the total memory used for canister logs exceeds this value.

Default value: `4096`.

- `snapshot_visibility` (`snapshot_visibility`)

Controls who can access the canister's snapshots through the following endpoints of the management canister:
Expand Down Expand Up @@ -332,6 +340,8 @@ Regardless of this setting, the canister itself and subnet admins can always req

* `snapshots_size`: Represents the memory consumed by all snapshots that belong to this canister.

* `log_memory_store_size`: Represents the memory used by canister logs of the canister.

All sizes are expressed in bytes.

### IC method `canister_metrics` {#ic-canister_metrics}
Expand Down Expand Up @@ -950,13 +960,14 @@ A snapshot may be deleted only by the controllers of the canister that the snaps

### IC method `fetch_canister_logs` {#ic-fetch_canister_logs}

This method can only be called via non-replicated (query) calls: by external users directly and by canisters from composite query methods and their callbacks, i.e., it cannot be called via replicated calls.
This method can be called by canisters via replicated calls, but it cannot be called by external users via replicated (update) calls.
This method can also be called via non-replicated (query) calls: by external users directly and by canisters from composite query methods and their callbacks.
A call from a composite query is executed against the state of the subnet hosting the calling canister and can thus only target canisters hosted by that subnet.

Given a canister ID as input, this method returns a vector of logs of that canister including its trap messages.
The canister logs are *not* collected in canister methods running in non-replicated mode (NRQ, TQ, CQ, CRy, CRt, CC, and F modes, as defined in [Overview of imports](./canister-interface.md#system-api-imports)) and the canister logs are *purged* when the canister is reinstalled or uninstalled.
The total size of all returned logs does not exceed 4KiB.
If new logs are added resulting in exceeding the maximum total log size of 4KiB, the oldest logs will be removed.
The total size of all returned logs does not exceed an implementation-defined constant chosen so as not to exceed the maximum response size.
Oldest canister logs are purged if the total memory used for canister logs exceeds the value `log_memory_limit` in canister settings.
Logs persist across canister upgrades and they are deleted if the canister is reinstalled or uninstalled.

The log visibility is defined in the `log_visibility` field of `canister_settings` and can be one of the following variants:
Expand All @@ -971,6 +982,14 @@ A single log is a record with the following fields:
- `timestamp_nanos` (`nat64`): the timestamp as nanoseconds since 1970-01-01 at which the log was recorded;
- `content` (`blob`): the actual content of the log;

To filter canister logs, an optional filter can be provided and has one of the following variants:
- `by_idx` (`record { start : nat64; end : nat64 }`): only logs are returned whose `idx` is within the provided range (`start` is inclusive, but `end` is exclusive);
- `by_timestamp_nanos` (`record { start : nat64; end : nat64 }`): only logs are returned whose `timestamp_nanos` is within the provided range (`start` is inclusive, but `end` is exclusive).

When the logs selected for the response do not all fit within a single response, they are trimmed to fit, and the direction of trimming differs between filtered and unfiltered reads:
- An **unfiltered** read trims the **oldest** log records, so the response ends with the newest log record. This surfaces the most recent activity.
- A **filtered** read trims the **newest** log records, so the response starts with the oldest log record satisfying the filter. This lets a filtered read page forward through logs starting from the beginning of the requested range.

:::warning

The response of a query comes from a single replica, and is therefore not appropriate for security-sensitive applications.
Expand Down
13 changes: 9 additions & 4 deletions docs/references/management-canister.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ Several methods accept or return a `canister_settings` record. The fields are:
| `wasm_memory_limit` | `nat` | `0` | Upper limit on Wasm heap memory in bytes (0 = no limit) |
| `wasm_memory_threshold` | `nat` | `0` | Remaining Wasm memory threshold that triggers the low-memory hook |
| `log_visibility` | `log_visibility` | `controllers` | Who can read canister logs: `controllers`, `public`, or `allowed_viewers(vec principal)` |
| `log_memory_limit` | `nat` | `4096` | Memory in bytes for storing canister logs: either `0` or between `4096` and `2097152` (2 MiB) |
| `snapshot_visibility` | `snapshot_visibility` | `controllers` | Who can list and read canister snapshots: `controllers`, `public`, or `allowed_viewers(vec principal)` |
| `status_visibility` | `status_visibility` | `controllers` | Who can read the canister status: `controllers`, `public`, or `allowed_viewers(vec principal)` |
| `environment_variables` | `opt record` | `null` | Key-value pairs accessible during canister execution |
Expand Down Expand Up @@ -129,7 +130,7 @@ Returns detailed information about a canister: status, settings, module hash, cy
- `settings`: the definite canister settings currently in effect
- `module_hash` (`opt blob`): SHA-256 of installed module (`null` if empty)
- `memory_size` (`nat`): total memory consumed
- `memory_metrics`: breakdown by component (Wasm memory, stable memory, globals, binary, custom sections, history, chunk store, snapshots)
- `memory_metrics`: breakdown by component (Wasm memory, stable memory, globals, binary, custom sections, history, chunk store, snapshots, log memory store)
- `cycles` (`nat`): current cycle balance
- `reserved_cycles` (`nat`): reserved cycle balance
- `idle_cycles_burned_per_day` (`nat`): daily idle burn rate
Expand Down Expand Up @@ -534,13 +535,17 @@ For Bitcoin integration patterns, see the [Bitcoin guide](../guides/chain-fusion

### `fetch_canister_logs`

Returns the most recent log entries for a canister. Logs are produced by `ic0.debug_print` and trap messages. Logs persist across upgrades but are purged on reinstall or uninstall. Total log size is capped at 4 KiB.
Returns log entries for a canister. Logs are produced by `ic0.debug_print` and trap messages. Logs persist across upgrades but are purged on reinstall or uninstall. The oldest logs are purged once the memory used for canister logs exceeds the `log_memory_limit` canister setting.

- **Caller:** External users via query calls, or canisters from composite queries (not callable via replicated calls)
- **Parameters:** `canister_id` (`principal`)
- **Caller:** Canisters via replicated calls or composite queries, and external users via query calls (external users cannot call it via replicated calls)
- **Parameters:**
- `canister_id` (`principal`)
- `filter` (`opt variant { by_idx : record { start : nat64; end : nat64 }; by_timestamp_nanos : record { start : nat64; end : nat64 } }`): returns only the logs whose `idx` or `timestamp_nanos` falls in the given range (`start` is inclusive, `end` is exclusive)
- **Returns:**
- `canister_log_records` (`vec record { idx : nat64; timestamp_nanos : nat64; content : blob }`)

The total size of the returned logs is bounded by an implementation-defined constant chosen so as not to exceed the maximum response size. When the selected logs do not all fit, an unfiltered read trims the oldest records, so the response ends with the newest log, and a filtered read trims the newest records, so the response starts with the oldest log matching the filter.

Log visibility is controlled by the `log_visibility` canister setting.

For practical usage, see the [canister logs guide](../guides/canister-management/logs.md).
Expand Down
7 changes: 7 additions & 0 deletions public/references/ic.did
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ type canister_settings = record {
reserved_cycles_limit : opt nat;
minimum_incoming_canister_call_cycles : opt nat;
log_visibility : opt log_visibility;
log_memory_limit : opt nat;
snapshot_visibility : opt snapshot_visibility;
status_visibility : opt status_visibility;
wasm_memory_limit : opt nat;
Expand All @@ -48,6 +49,7 @@ type definite_canister_settings = record {
reserved_cycles_limit : nat;
minimum_incoming_canister_call_cycles : nat;
log_visibility : log_visibility;
log_memory_limit : nat;
snapshot_visibility : snapshot_visibility;
status_visibility : status_visibility;
wasm_memory_limit : nat;
Expand Down Expand Up @@ -310,6 +312,7 @@ type canister_status_result = record {
canister_history_size : nat;
wasm_chunk_store_size : nat;
snapshots_size : nat;
log_memory_store_size : nat;
};
cycles : nat;
reserved_cycles : nat;
Expand Down Expand Up @@ -509,6 +512,10 @@ type delete_canister_snapshot_args = record {

type fetch_canister_logs_args = record {
canister_id : canister_id;
filter : opt variant {
by_idx : record { start : nat64; end : nat64 };
by_timestamp_nanos : record { start : nat64; end : nat64 };
};
};

type canister_log_record = record {
Expand Down
Loading