Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
38 changes: 38 additions & 0 deletions docs/references/ic-interface-spec/abstract-behavior.md
Original file line number Diff line number Diff line change
Expand Up @@ -3198,6 +3198,44 @@ S with

```

#### IC Management Canister: Subnet Metrics

:::note

The subnet metrics management canister API is considered EXPERIMENTAL. Canister developers must be aware that the API may evolve in a non-backward-compatible way.

:::

The management canister returns subnet-wide metrics given a subnet ID. The definition of the metrics values
is not captured in this formal semantics.

Conditions

```html

S.messages = Older_messages · CallMessage M · Younger_messages
(M.queue = Unordered) or (∀ CallMessage M' | FuncMessage M' ∈ Older_messages. M'.queue ≠ M.queue)
M.callee = ic_principal
M.method_name = 'subnet_metrics'
M.arg = candid(A)
R = <implementation-specific>

```

State after

```html

S with
messages = Older_messages · Younger_messages ·
ResponseMessage {
origin = M.origin
response = Reply (candid(R))
refunded_cycles = M.transferred_cycles
}

```

#### IC Management Canister: Subnet information

The management canister returns subnet metadata given a subnet ID.
Expand Down
14 changes: 14 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,20 @@ sidebar:

## Changelog {#changelog}

### 0.69.0 (2026-09-17) {$0_69_0}
* New management canister endpoint `subnet_metrics` returning subnet-wide metrics for a
given subnet: the current block height, the number of canisters, the total canister
state size, the total cycles consumed, the total number of processed transactions, and
the total number of instructions accounted for across all rounds
(`million_round_instructions_total`), in units of one million and rounded up. The four
aggregates were previously only readable by external users via the certified state tree
path `/subnet/<subnet_id>/metrics`; the block height and the instruction total have no
path there. Besides the executed Wasm instructions, the instruction total covers the
fixed per-execution and per-canister overheads charged by the scheduler and the charges
for work performed outside of Wasm execution, so it is not a Wasm instruction meter, and
its counter starts when a subnet's replica begins tracking it rather than at subnet
creation. The API is EXPERIMENTAL.

### 0.68.0 (2026-09-14) {$0_68_0}
* New management canister method `flexible_http_request`, a variant of `http_request` in which a committee
of nodes return their individual HTTP responses to the caller instead of the subnet reaching consensus
Expand Down
8 changes: 4 additions & 4 deletions docs/references/ic-interface-spec/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -517,10 +517,10 @@ The state tree contains information about the topology of the Internet Computer.

A collection of subnet-wide metrics related to this subnet's current resource usage and/or performance. The metrics are a CBOR map with the following fields:

- `num_canisters` (`nat`): The number of canisters on this subnet.
- `canister_state_bytes` (`nat`): The total size of the state in bytes taken by canisters on this subnet since this subnet was created.
- `consumed_cycles_total` (`map`): The total number of cycles consumed by all current and deleted canisters on this subnet. It's a map of two values, a low part of type `nat` and a high part of type `opt nat`.
- `update_transactions_total` (`nat`): The total number of transactions processed on this subnet since this subnet was created.
- `num_canisters` (`nat`): The number of canisters on this subnet. This is a current value, not a counter, so it decreases when canisters are deleted.
- `canister_state_bytes` (`nat`): The total size of the state in bytes currently taken by canisters on this subnet. This is a current value, not a counter. Recomputing it is expensive, so it is refreshed only every 10 blocks, at heights that are multiples of 10, and reads 0 until the first refresh after this subnet was created.
- `consumed_cycles_total` (`map`): The total number of cycles removed from circulation on this subnet since this subnet was created. Besides the cycles charged to the canisters currently on this subnet, this includes the cycles charged to canisters that have since been deleted, and the cycles consumed on behalf of the subnet itself rather than charged to any individual canister. Cycles that are charged in advance and later refunded are excluded once the refund is accounted for, so this value can also decrease. It's a map of two values, a low part of type `nat` and a high part of type `opt nat`.
- `update_transactions_total` (`nat`): The total number of transactions processed on this subnet since this subnet was created, i.e., the total number of messages executed in the replicated mode. The value is monotonically non-decreasing.


:::note
Expand Down
38 changes: 38 additions & 0 deletions docs/references/ic-interface-spec/management-canister.md
Original file line number Diff line number Diff line change
Expand Up @@ -849,6 +849,44 @@ A single metric entry is a record with the following fields:

- `num_block_failures_total` (`nat64`): the number of failed block proposals by this node.

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

This method can only be called by canisters, i.e., it cannot be called by external users via ingress messages.

:::note

The subnet metrics management canister API is considered EXPERIMENTAL. Canister developers must be aware that the API may evolve in a non-backward-compatible way.

:::

Given a subnet ID as input, this method returns a record of subnet-wide metrics describing that subnet's resource usage and performance.

The fields `num_canisters`, `canister_state_bytes`, `consumed_cycles_total`, and `update_transactions_total` report the same quantities that the certified state tree exposes at the path `/subnet/<subnet_id>/metrics` (see [Subnet information](./index.md#state-tree-subnet)). This method makes them available to canisters, which cannot read the state tree. The fields `block_height` and `million_round_instructions_total` have no path in the state tree and are only available through this method.

In the following, *the subnet* refers to the subnet identified by the `subnet_id` argument.

Only `block_height` describes the block in whose execution the call is processed. The other five fields are aggregates that the subnet refreshes at block boundaries, so they describe the subnet as of an earlier block. They are not all refreshed at the same rate, so they need not be mutually consistent, and none of them should be read as a snapshot taken at `block_height`.

The fields returned are:

- `block_height` (`nat`): the current block height of the subnet, i.e., the height of the block in whose execution this call is processed.

Heights are consecutive numbers identifying the successive blocks of a subnet. This specification does not otherwise model block heights, and heights of different subnets are unrelated, so this value is only meaningful when compared against other values for the same subnet.

The value is monotonically non-decreasing for a given subnet.

- `num_canisters` (`nat`): the number of canisters on the subnet. This is a current value, not a counter, so it decreases when canisters are deleted.

- `canister_state_bytes` (`nat`): the total size in bytes of the state taken by canisters on the subnet. This is a current value, not a counter. Recomputing it is expensive, so it is refreshed only every 10 blocks, at heights that are multiples of 10, and can therefore be up to 10 blocks staler than the other fields. It reads 0 until the first refresh after the subnet was created.

- `consumed_cycles_total` (`nat`): the total number of cycles removed from circulation on the subnet. Besides the cycles charged to the canisters currently on the subnet, this includes the cycles charged to canisters that have since been deleted, and the cycles consumed on behalf of the subnet itself rather than charged to any individual canister. Cycles that are charged in advance and later refunded are excluded once the refund is accounted for, so this value can also decrease.

- `update_transactions_total` (`nat`): the total number of transactions processed on the subnet, i.e., the total number of messages executed in the replicated mode. The value is monotonically non-decreasing for a given subnet.

- `million_round_instructions_total` (`nat`): the total number of instructions the subnet accounted for across the execution phases of all rounds, in units of one million and rounded up, so a value of `42` means 42 million instructions. Besides the executed Wasm instructions this also covers the fixed per-execution and per-canister overheads charged by the scheduler, and the charges for work performed outside of Wasm execution, such as compilation, chunk assembly, and snapshot operations. It is therefore not a Wasm instruction meter. The value is monotonically non-decreasing for a given subnet.

`consumed_cycles_total`, `update_transactions_total`, and `million_round_instructions_total` cover the whole lifetime of the subnet, or the period since the respective metric was introduced for subnets that predate it.

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

This method can only be called by canisters, i.e., it cannot be called by external users via ingress messages.
Expand Down
23 changes: 23 additions & 0 deletions docs/references/management-canister.md
Original file line number Diff line number Diff line change
Expand Up @@ -589,6 +589,29 @@ Returns a time series of node metrics for a given subnet. Returns up to 60 times
- `num_blocks_proposed_total` (`nat64`)
- `num_block_failures_total` (`nat64`)

### `subnet_metrics`

> This API is **experimental** and may change in a non-backward-compatible way.

Returns subnet-wide metrics for a given subnet, which does not have to be the subnet hosting the caller. The four aggregates (`num_canisters`, `canister_state_bytes`, `consumed_cycles_total`, and `update_transactions_total`) report the same quantities that the certified state tree exposes at `/subnet/<subnet_id>/metrics`; this method makes them available to canisters, which cannot read the state tree. `block_height` and `million_round_instructions_total` have no path in the state tree and are only available here.

- **Caller:** Canisters only
- **Parameters:**
- `subnet_id` (`principal`): any subnet
- **Returns:**
- `block_height` (`nat`): the target subnet's current block height, i.e. the height of the block in whose execution the call is processed
- `num_canisters` (`nat`): canisters on the subnet
- `canister_state_bytes` (`nat`): total size of canister state in bytes
- `consumed_cycles_total` (`nat`): total cycles removed from circulation on the subnet
- `update_transactions_total` (`nat`): total transactions processed on the subnet
- `million_round_instructions_total` (`nat`): total instructions the subnet accounted for across the execution phases of all rounds, in units of one million and rounded up

Only `block_height` is as of the block that processes the call. The other five fields are aggregates refreshed at block boundaries, so they describe an earlier block, and they are not refreshed in lockstep with each other. `canister_state_bytes` is the stalest: it is recomputed only every 10 blocks, at heights that are multiples of 10, so it can be up to 10 blocks behind the others, and it reads 0 until the first recomputation after the subnet was created.

`update_transactions_total` and `million_round_instructions_total` only ever grow. `consumed_cycles_total` covers deleted canisters and cycles consumed by the subnet itself, and it nets out refunds of cycles charged in advance, so it can decrease. `num_canisters` and `canister_state_bytes` are current values, not counters.

`million_round_instructions_total` counts the executed Wasm instructions plus the scheduler's per-execution and per-canister overheads and the charges for work outside Wasm execution (compilation, chunk assembly, snapshots), so it is not a Wasm instruction meter. Like the other counters, it covers the subnet's whole lifetime, or the period since the metric was introduced for subnets that predate it.

### `subnet_info`

Returns metadata about a subnet.
Expand Down
42 changes: 42 additions & 0 deletions public/references/ic.did
Original file line number Diff line number Diff line change
Expand Up @@ -493,6 +493,47 @@ type node_metrics_history_result = vec record {
node_metrics : vec node_metrics;
};

type subnet_metrics_args = record {
subnet_id : principal;
};

// Only `block_height` describes the block in whose execution the call is
// processed. The other five fields are aggregates refreshed at block
// boundaries, so they describe the subnet as of an earlier block, and they are
// not all refreshed at the same rate; see the individual fields.
type subnet_metrics_result = record {
// Current block height of the subnet, i.e. the height of the block in
// whose execution this call is processed. Monotonically non-decreasing for
// a given subnet; the heights of different subnets are unrelated.
block_height : nat;
// Number of canisters on the subnet. A current value, not a counter.
num_canisters : nat;
// Total size in bytes of the state taken by canisters on the subnet. A
// current value, not a counter. Recomputing it is expensive, so it is
// refreshed only every 10 blocks, at heights that are multiples of 10, and
// reads 0 until the first refresh after the subnet was created.
canister_state_bytes : nat;
// Total cycles removed from circulation on the subnet: the cycles charged
// to the canisters currently on the subnet, plus those charged to canisters
// that have since been deleted, plus those consumed on behalf of the subnet
// itself. Refunds of cycles charged in advance are netted out, so this
// value can also decrease.
consumed_cycles_total : nat;
// Total number of transactions processed on the subnet, i.e. the total
// number of messages executed in the replicated mode. Monotonically
// non-decreasing.
update_transactions_total : nat;
// Total instructions the subnet accounted for across the execution phases
// of all rounds, in units of one million and rounded up: a value of 42
// means 42 million instructions. Besides the executed Wasm instructions it
// covers the fixed per-execution and per-canister overheads charged by the
// scheduler and the charges for work performed outside of Wasm execution,
// so it is not a Wasm instruction meter. Monotonically non-decreasing.
// Unlike the four fields above, it has no counterpart under
// `/subnet/<subnet_id>/metrics` in the certified state tree.
million_round_instructions_total : nat;
};

type subnet_info_args = record {
subnet_id : principal;
};
Expand Down Expand Up @@ -762,6 +803,7 @@ service ic : {

// metrics interface
node_metrics_history : (node_metrics_history_args) -> (node_metrics_history_result);
subnet_metrics : (subnet_metrics_args) -> (subnet_metrics_result);

// subnet info
subnet_info : (subnet_info_args) -> (subnet_info_result);
Expand Down
Loading